From 26a15457357c292aa1f6b4e0fd415dd0da6403d7 Mon Sep 17 00:00:00 2001 From: Martin Pool Date: Thu, 8 Jan 2026 07:39:27 -0800 Subject: [PATCH 0001/1309] Document that Linux can add `" (deleted)"` Link to warning that platform-specific behavior is subject to change --- library/std/src/env.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 047dfbe1a2333..9a861e9e0e8ab 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -716,6 +716,11 @@ pub fn temp_dir() -> PathBuf { /// If the executable is renamed while it is running, platforms may return the /// path at the time it was loaded instead of the new path. /// +/// On Linux, if the executable is deleted while it is running, this function +/// may return the path with the string `" (deleted)"` appended. +/// +/// Note that the platform-specific behavior [may change in the future][changes]. +/// /// # Errors /// /// Acquiring the path of the current executable is a platform-specific operation @@ -751,6 +756,8 @@ pub fn temp_dir() -> PathBuf { /// Err(e) => println!("failed to get current exe path: {e}"), /// }; /// ``` +/// +/// [changes]: crate::io#platform-specific-behavior #[stable(feature = "env", since = "1.0.0")] pub fn current_exe() -> io::Result { paths_imp::current_exe() From 88d314ad4cdebe248170d2fd7fe28580c02acecb Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 6 Jun 2026 23:01:26 -0700 Subject: [PATCH 0002/1309] typeck enum discrs before attempting to compute layout --- compiler/rustc_ty_utils/src/layout.rs | 12 +++++++ tests/crashes/138660.rs | 7 ---- ...on-int-discriminant-promoted-ice-138660.rs | 13 ++++++++ ...nt-discriminant-promoted-ice-138660.stderr | 33 +++++++++++++++++++ .../size-of-discriminant-no-cycle.rs | 8 +++++ 5 files changed, 66 insertions(+), 7 deletions(-) delete mode 100644 tests/crashes/138660.rs create mode 100644 tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.rs create mode 100644 tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.stderr create mode 100644 tests/ui/enum-discriminant/size-of-discriminant-no-cycle.rs diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ee6afdf330a77..81d3185fea01a 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -707,6 +707,18 @@ fn layout_of_uncached<'tcx>( let discr_range_of_repr = |min, max| abi::Integer::discr_range_of_repr(tcx, ty, &def.repr(), min, max); + // We shouldn't be computing the layout of discrs that fail typeck + if def.is_enum() { + for v in def.variants() { + if let ty::VariantDiscr::Explicit(def_id) = v.discr + && let Some(local_did) = def_id.as_local() + && let Some(guar) = tcx.typeck(local_did).tainted_by_errors + { + return Err(error(cx, LayoutError::ReferencesError(guar))); + } + } + } + let discriminants_iter = || { def.is_enum() .then(|| def.discriminants(tcx).map(|(v, d)| (v, d.val as i128))) diff --git a/tests/crashes/138660.rs b/tests/crashes/138660.rs deleted file mode 100644 index 90eb8026f072f..0000000000000 --- a/tests/crashes/138660.rs +++ /dev/null @@ -1,7 +0,0 @@ -//@ known-bug: #138660 -enum A { - V1(isize) = 1..=10, - V0 = 1..=10, -} -const B: &'static [A] = &[A::V0, A::V1(111)]; -fn main() {} diff --git a/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.rs b/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.rs new file mode 100644 index 0000000000000..c1e968494540c --- /dev/null +++ b/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.rs @@ -0,0 +1,13 @@ +// Previously, enums with non-int discrs ICEd during CTFE of promoteds. + +enum A { +//~^ ERROR `#[repr(inttype)]` must be specified + V1(isize) = 1..=10, + //~^ ERROR mismatched types + V0 = 1..=10, + //~^ ERROR mismatched types +} + +const B: &'static [A] = &[A::V0, A::V1(111)]; + +fn main() {} diff --git a/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.stderr b/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.stderr new file mode 100644 index 0000000000000..19491ce733d09 --- /dev/null +++ b/tests/ui/enum-discriminant/non-int-discriminant-promoted-ice-138660.stderr @@ -0,0 +1,33 @@ +error[E0308]: mismatched types + --> $DIR/non-int-discriminant-promoted-ice-138660.rs:5:17 + | +LL | V1(isize) = 1..=10, + | ^^^^^^ expected `isize`, found `RangeInclusive<{integer}>` + | + = note: expected type `isize` + found struct `std::ops::RangeInclusive<{integer}>` + = note: enum variant discriminant can only be of a primitive type compatible with the enum's `repr` + +error[E0308]: mismatched types + --> $DIR/non-int-discriminant-promoted-ice-138660.rs:7:10 + | +LL | V0 = 1..=10, + | ^^^^^^ expected `isize`, found `RangeInclusive<{integer}>` + | + = note: expected type `isize` + found struct `std::ops::RangeInclusive<{integer}>` + = note: enum variant discriminant can only be of a primitive type compatible with the enum's `repr` + +error[E0732]: `#[repr(inttype)]` must be specified for enums with explicit discriminants and non-unit variants + --> $DIR/non-int-discriminant-promoted-ice-138660.rs:3:1 + | +LL | enum A { + | ^^^^^^ +LL | +LL | V1(isize) = 1..=10, + | ------ explicit discriminant on non-unit variant specified here + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0308, E0732. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/enum-discriminant/size-of-discriminant-no-cycle.rs b/tests/ui/enum-discriminant/size-of-discriminant-no-cycle.rs new file mode 100644 index 0000000000000..09313735fd4c5 --- /dev/null +++ b/tests/ui/enum-discriminant/size-of-discriminant-no-cycle.rs @@ -0,0 +1,8 @@ +//@ check-pass +// Ensure that `size_of::()` as a discriminant does not cause a cycle error. + +enum Thing { + Variant = size_of::() as isize, +} + +fn main() {} From 5e53d929e4638976cac6b9a3069860af8fe814fc Mon Sep 17 00:00:00 2001 From: byd1 <2156864690@qq.com> Date: Sun, 28 Jun 2026 14:19:13 +0800 Subject: [PATCH 0003/1309] fix --- compiler/rustc_parse/src/parser/stmt.rs | 20 +++++++++++++++++-- .../ui/let-else/detect-invisible-delimiter.rs | 16 +++++++++++++++ 2 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ui/let-else/detect-invisible-delimiter.rs diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 5bd2ca3139228..2b63a31a139da 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -5,6 +5,7 @@ use std::ops::Bound; use ast::Label; use rustc_ast as ast; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; +use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::classify::{self, TrailingBrace}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ @@ -353,6 +354,14 @@ impl<'a> Parser<'a> { } else { (None, None, None) }; + + let init_wrapped = self + .tree_look_ahead(2, |tree| match tree { + TokenTree::Token(tok, _) => tok.is_keyword(kw::Else), + TokenTree::Delimited(..) => false, + }) + .unwrap_or(false); + let init = match (self.parse_initializer(err.is_some()), err) { (Ok(init), None) => { // init parsed, ty parsed @@ -390,6 +399,7 @@ impl<'a> Parser<'a> { return Err(err); } }; + let trailing_token = self.prev_token; let kind = match init { None => LocalKind::Decl, Some(init) => { @@ -401,8 +411,14 @@ impl<'a> Parser<'a> { return Err(self.error_block_no_opening_brace_msg(Cow::from(msg))); } let els = self.parse_block()?; - self.check_let_else_init_bool_expr(&init); - self.check_let_else_init_trailing_brace(&init); + // These checks should also respect invisible delimiter + if !init_wrapped { + self.check_let_else_init_bool_expr(&init); + } + if matches!(trailing_token.kind, TokenKind::CloseBrace) { + self.check_let_else_init_trailing_brace(&init); + } + LocalKind::InitElse(init, els) } else { LocalKind::Init(init) diff --git a/tests/ui/let-else/detect-invisible-delimiter.rs b/tests/ui/let-else/detect-invisible-delimiter.rs new file mode 100644 index 0000000000000..76c231bd21e6d --- /dev/null +++ b/tests/ui/let-else/detect-invisible-delimiter.rs @@ -0,0 +1,16 @@ +// The user shouldn't need to wrap the expression in parentheses(#147899) +//@check-pass +#![allow(irrefutable_let_patterns)] +struct Thing {} +macro_rules! foo { + ($e:expr) => { + let _ = $e else { + return; + }; + }; +} + +fn main() { + foo!(true && true); + foo!(Thing {}); +} From ea48beaf1bb64904ec11fc7382989f60ee5f64d6 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 19 Jul 2026 07:40:22 -0500 Subject: [PATCH 0004/1309] Allow elided ('static) lifetimes in `#[thread_local]` with or without a const initializer, on all platforms. --- library/std/src/sys/thread_local/native/mod.rs | 10 +++++++--- library/std/src/sys/thread_local/no_threads.rs | 8 ++++++-- library/std/src/sys/thread_local/os.rs | 8 ++++++-- 3 files changed, 19 insertions(+), 7 deletions(-) diff --git a/library/std/src/sys/thread_local/native/mod.rs b/library/std/src/sys/thread_local/native/mod.rs index 4dad81685a94e..209a8790def08 100644 --- a/library/std/src/sys/thread_local/native/mod.rs +++ b/library/std/src/sys/thread_local/native/mod.rs @@ -81,8 +81,12 @@ pub macro thread_local_inner { // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{ + // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t` + // become `'static` like they do for `const`s and `static`s, including in the other two + // `thread_local!` implementations. + #[allow(mismatched_lifetime_syntaxes)] #[inline] - fn __rust_std_internal_init_fn() -> $t { + fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t { $init } @@ -94,7 +98,7 @@ pub macro thread_local_inner { $(#[$align_attr])* static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t, ()> = $crate::thread::local_impl::LazyStorage::new(); - __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, __rust_std_internal_init_fn) + __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData)) } } else { |__rust_std_internal_init| { @@ -102,7 +106,7 @@ pub macro thread_local_inner { $(#[$align_attr])* static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t, !> = $crate::thread::local_impl::LazyStorage::new(); - __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, __rust_std_internal_init_fn) + __RUST_STD_INTERNAL_VAL.get_or_init(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData)) } } }) diff --git a/library/std/src/sys/thread_local/no_threads.rs b/library/std/src/sys/thread_local/no_threads.rs index f9d0ed384fe24..0927595280f1f 100644 --- a/library/std/src/sys/thread_local/no_threads.rs +++ b/library/std/src/sys/thread_local/no_threads.rs @@ -31,14 +31,18 @@ pub macro thread_local_inner { // used to generate the `LocalKey` value for `thread_local!` (@key $t:ty, $(#[$align_attr:meta])*, $init:expr) => {{ + // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t` + // become `'static` like they do for `const`s and `static`s, including in the other two + // `thread_local!` implementations. + #[allow(mismatched_lifetime_syntaxes)] #[inline] - fn __rust_std_internal_init_fn() -> $t { $init } + fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t { $init } unsafe { $crate::thread::LocalKey::new(|__rust_std_internal_init| { $(#[$align_attr])* static __RUST_STD_INTERNAL_VAL: $crate::thread::local_impl::LazyStorage<$t> = $crate::thread::local_impl::LazyStorage::new(); - __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, __rust_std_internal_init_fn) + __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData)) }) } }}, diff --git a/library/std/src/sys/thread_local/os.rs b/library/std/src/sys/thread_local/os.rs index bc044aafa983c..289ac33bb7b76 100644 --- a/library/std/src/sys/thread_local/os.rs +++ b/library/std/src/sys/thread_local/os.rs @@ -20,8 +20,12 @@ pub macro thread_local_inner { // used to generate the `LocalKey` value for `thread_local!`. (@key $t:ty, $($(#[$($align_attr:tt)*])+)?, $init:expr) => {{ + // We intentionally have an argument-position `'static` lifetime so that elided lifetimes in `$t` + // become `'static` like they do for `const`s and `static`s, including in the other two + // `thread_local!` implementations. + #[allow(mismatched_lifetime_syntaxes)] #[inline] - fn __rust_std_internal_init_fn() -> $t { $init } + fn __rust_std_internal_init_fn(_lifetime_elision: $crate::marker::PhantomData<&'static ()>) -> $t { $init } // NOTE: this cannot import `LocalKey` or `Storage` with a `use` because that can shadow // user provided type or type alias with a matching name. Please update the shadowing test @@ -43,7 +47,7 @@ pub macro thread_local_inner { final_align }> = $crate::thread::local_impl::Storage::new(); - __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, __rust_std_internal_init_fn) + __RUST_STD_INTERNAL_VAL.get(__rust_std_internal_init, || __rust_std_internal_init_fn($crate::marker::PhantomData)) }) } }}, From e3532e092fce8693e5f7cfd1c3125bf4a825d2a7 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Sun, 19 Jul 2026 08:54:25 -0500 Subject: [PATCH 0005/1309] Remove tests/ui/suggestions/missing-lifetime-specifier.rs It was testing diagnostics emitted for missing lifetime specifiers in `thread_local!`, but now elided lifetimes in `thread_local!` are `'static`, so there's nothing to test. --- .../suggestions/missing-lifetime-specifier.rs | 54 --------- .../missing-lifetime-specifier.stderr | 109 ------------------ 2 files changed, 163 deletions(-) delete mode 100644 tests/ui/suggestions/missing-lifetime-specifier.rs delete mode 100644 tests/ui/suggestions/missing-lifetime-specifier.stderr diff --git a/tests/ui/suggestions/missing-lifetime-specifier.rs b/tests/ui/suggestions/missing-lifetime-specifier.rs deleted file mode 100644 index 93416a9bc2ac7..0000000000000 --- a/tests/ui/suggestions/missing-lifetime-specifier.rs +++ /dev/null @@ -1,54 +0,0 @@ -// The specific errors produced depend the thread-local implementation. -// Run only on platforms with "fast" TLS. -//@ ignore-wasm globals are used instead of thread locals -//@ ignore-emscripten globals are used instead of thread locals -//@ ignore-android does not use #[thread_local] -//@ ignore-nto does not use #[thread_local] -//@ ignore-qnx does not use #[thread_local] -// Different number of duplicated diagnostics on different targets -//@ compile-flags: -Zdeduplicate-diagnostics=yes - -use std::cell::RefCell; -use std::collections::HashMap; - -pub union Foo<'t, 'k> { - i: &'t i64, - f: &'k f64, -} -trait Bar<'t, 'k> {} - -pub union Qux<'t, 'k, I> { - i: &'t I, - f: &'k I, -} -trait Tar<'t, 'k, I> {} - -thread_local! { - static a: RefCell>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers -} -thread_local! { - static b: RefCell>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers -} -thread_local! { - static c: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers -} -thread_local! { - static d: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR missing lifetime specifiers -} - -thread_local! { - static e: RefCell>>>> = RefCell::new(HashMap::new()); - //~^ ERROR union takes 2 lifetime arguments but 1 lifetime argument -} -thread_local! { - static f: RefCell>>>> = - RefCell::new(HashMap::new()); - //~^^ ERROR trait takes 2 lifetime arguments but 1 lifetime argument was supplied - //~| ERROR missing lifetime specifier -} - -fn main() {} diff --git a/tests/ui/suggestions/missing-lifetime-specifier.stderr b/tests/ui/suggestions/missing-lifetime-specifier.stderr deleted file mode 100644 index 4c50f2a43e270..0000000000000 --- a/tests/ui/suggestions/missing-lifetime-specifier.stderr +++ /dev/null @@ -1,109 +0,0 @@ -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:27:44 - | -LL | static a: RefCell>>> = RefCell::new(HashMap::new()); - | ^^^ expected 2 lifetime parameters - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values - | -LL | static a: RefCell>>>> = RefCell::new(HashMap::new()); - | ++++++++++++++++++ - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:31:44 - | -LL | static b: RefCell>>> = RefCell::new(HashMap::new()); - | ^ ^^^ expected 2 lifetime parameters - | | - | expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` - | -LL | static b: RefCell>>>> = RefCell::new(HashMap::new()); - | +++++++ ++++++++++++++++++ - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:35:47 - | -LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ expected 2 lifetime parameters - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static`, or if you will only have owned values - | -LL | static c: RefCell>>>> = RefCell::new(HashMap::new()); - | +++++++++++++++++ - -error[E0106]: missing lifetime specifiers - --> $DIR/missing-lifetime-specifier.rs:39:44 - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | ^ ^ expected 2 lifetime parameters - | | - | expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` - | -LL | static d: RefCell>>>> = RefCell::new(HashMap::new()); - | +++++++ +++++++++++++++++ - -error[E0106]: missing lifetime specifier - --> $DIR/missing-lifetime-specifier.rs:48:44 - | -LL | static f: RefCell>>>> = - | ^ expected named lifetime parameter - | - = help: this function's return type contains a borrowed value, but there is no value for it to be borrowed from -help: consider using the `'static` lifetime, but this is uncommon unless you're returning a borrowed value from a `const` or a `static` - | -LL | static f: RefCell>>>> = - | +++++++ -help: instead, you are more likely to want to return an owned value - | -LL - static f: RefCell>>>> = -LL + static f: RefCell>>>> = - | - -error[E0107]: union takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:44:44 - | -LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); - | ^^^ ------- supplied 1 lifetime argument - | | - | expected 2 lifetime arguments - | -note: union defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:20:11 - | -LL | pub union Qux<'t, 'k, I> { - | ^^^ -- -- -help: add missing lifetime argument - | -LL | static e: RefCell>>>> = RefCell::new(HashMap::new()); - | +++++++++ - -error[E0107]: trait takes 2 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/missing-lifetime-specifier.rs:48:49 - | -LL | static f: RefCell>>>> = - | ^^^ ------- supplied 1 lifetime argument - | | - | expected 2 lifetime arguments - | -note: trait defined here, with 2 lifetime parameters: `'t`, `'k` - --> $DIR/missing-lifetime-specifier.rs:24:7 - | -LL | trait Tar<'t, 'k, I> {} - | ^^^ -- -- -help: add missing lifetime argument - | -LL | static f: RefCell>>>> = - | +++++++++ - -error: aborting due to 7 previous errors - -Some errors have detailed explanations: E0106, E0107. -For more information about an error, try `rustc --explain E0106`. From e423836114c8ae49b2d500cc3e8276970e555b62 Mon Sep 17 00:00:00 2001 From: Zachary S Date: Tue, 21 Jul 2026 12:28:27 -0500 Subject: [PATCH 0006/1309] Add test for thread_local! lifetime elision. --- tests/ui/thread-local/lifetime-elision.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/ui/thread-local/lifetime-elision.rs diff --git a/tests/ui/thread-local/lifetime-elision.rs b/tests/ui/thread-local/lifetime-elision.rs new file mode 100644 index 0000000000000..3b960d18764cb --- /dev/null +++ b/tests/ui/thread-local/lifetime-elision.rs @@ -0,0 +1,14 @@ +// Test that `thread_local!` defaults elided lifetimes in the type to `'static`. +// Regression test for 159358. +// Ideally this should be tested at least one target using each `thread_local!` +// implementation (no-threads, native, os), but currently there are no Tier 1 `no-threads` +// targets. `x86_64-unknown-linux-gnu` is a `native` target and `x86_64-pc-windows-gnu` +// is a `os` target, so those are covered (as of 2026-07-21). +//@ check-pass + +// Const initializer +std::thread_local!(static A: &str = const { "" }); +// Non-const initializer +std::thread_local!(static B: &str = ""); + +fn main() {} From 2ca628eb3cb7a4a5a4f46a5d6dedc48f621e1917 Mon Sep 17 00:00:00 2001 From: tangaac Date: Wed, 22 Jul 2026 18:36:47 +0800 Subject: [PATCH 0007/1309] loongarch: Add portable intrinsics::simd implementations for VAVG/VAVGR intrinsics --- .../src/loongarch64/lasx/generated.rs | 144 ------------------ .../src/loongarch64/lasx/portable.rs | 18 +++ .../src/loongarch64/lsx/generated.rs | 144 ------------------ .../core_arch/src/loongarch64/lsx/portable.rs | 18 +++ .../crates/core_arch/src/loongarch64/simd.rs | 38 +++++ .../crates/stdarch-gen-loongarch/lasx.spec | 16 ++ .../crates/stdarch-gen-loongarch/lsx.spec | 16 ++ .../src/portable-intrinsics.txt | 32 ++++ 8 files changed, 138 insertions(+), 288 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs index 711ade40391a9..fa5a8ccc1a5f2 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs @@ -91,38 +91,6 @@ unsafe extern "unadjusted" { fn __lasx_xvsat_wu(a: __v8u32, b: u32) -> __v8u32; #[link_name = "llvm.loongarch.lasx.xvsat.du"] fn __lasx_xvsat_du(a: __v4u64, b: u32) -> __v4u64; - #[link_name = "llvm.loongarch.lasx.xvavg.b"] - fn __lasx_xvavg_b(a: __v32i8, b: __v32i8) -> __v32i8; - #[link_name = "llvm.loongarch.lasx.xvavg.h"] - fn __lasx_xvavg_h(a: __v16i16, b: __v16i16) -> __v16i16; - #[link_name = "llvm.loongarch.lasx.xvavg.w"] - fn __lasx_xvavg_w(a: __v8i32, b: __v8i32) -> __v8i32; - #[link_name = "llvm.loongarch.lasx.xvavg.d"] - fn __lasx_xvavg_d(a: __v4i64, b: __v4i64) -> __v4i64; - #[link_name = "llvm.loongarch.lasx.xvavg.bu"] - fn __lasx_xvavg_bu(a: __v32u8, b: __v32u8) -> __v32u8; - #[link_name = "llvm.loongarch.lasx.xvavg.hu"] - fn __lasx_xvavg_hu(a: __v16u16, b: __v16u16) -> __v16u16; - #[link_name = "llvm.loongarch.lasx.xvavg.wu"] - fn __lasx_xvavg_wu(a: __v8u32, b: __v8u32) -> __v8u32; - #[link_name = "llvm.loongarch.lasx.xvavg.du"] - fn __lasx_xvavg_du(a: __v4u64, b: __v4u64) -> __v4u64; - #[link_name = "llvm.loongarch.lasx.xvavgr.b"] - fn __lasx_xvavgr_b(a: __v32i8, b: __v32i8) -> __v32i8; - #[link_name = "llvm.loongarch.lasx.xvavgr.h"] - fn __lasx_xvavgr_h(a: __v16i16, b: __v16i16) -> __v16i16; - #[link_name = "llvm.loongarch.lasx.xvavgr.w"] - fn __lasx_xvavgr_w(a: __v8i32, b: __v8i32) -> __v8i32; - #[link_name = "llvm.loongarch.lasx.xvavgr.d"] - fn __lasx_xvavgr_d(a: __v4i64, b: __v4i64) -> __v4i64; - #[link_name = "llvm.loongarch.lasx.xvavgr.bu"] - fn __lasx_xvavgr_bu(a: __v32u8, b: __v32u8) -> __v32u8; - #[link_name = "llvm.loongarch.lasx.xvavgr.hu"] - fn __lasx_xvavgr_hu(a: __v16u16, b: __v16u16) -> __v16u16; - #[link_name = "llvm.loongarch.lasx.xvavgr.wu"] - fn __lasx_xvavgr_wu(a: __v8u32, b: __v8u32) -> __v8u32; - #[link_name = "llvm.loongarch.lasx.xvavgr.du"] - fn __lasx_xvavgr_du(a: __v4u64, b: __v4u64) -> __v4u64; #[link_name = "llvm.loongarch.lasx.xvhaddw.h.b"] fn __lasx_xvhaddw_h_b(a: __v32i8, b: __v32i8) -> __v16i16; #[link_name = "llvm.loongarch.lasx.xvhaddw.w.h"] @@ -1283,118 +1251,6 @@ pub fn lasx_xvsat_du(a: m256i) -> m256i { unsafe { transmute(__lasx_xvsat_du(transmute(a), IMM6)) } } -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_b(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_b(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_h(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_h(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_w(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_w(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_d(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_d(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_bu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_bu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_hu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_hu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_wu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_wu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavg_du(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavg_du(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_b(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_b(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_h(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_h(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_w(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_w(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_d(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_d(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_bu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_bu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_hu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_hu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_wu(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_wu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lasx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lasx_xvavgr_du(a: m256i, b: m256i) -> m256i { - unsafe { transmute(__lasx_xvavgr_du(transmute(a), transmute(b))) } -} - #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lasx/portable.rs b/library/stdarch/crates/core_arch/src/loongarch64/lasx/portable.rs index 73ea74d9dc3bb..d53f21c792626 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lasx/portable.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lasx/portable.rs @@ -896,6 +896,24 @@ impl_vvvv!("lasx", lasx_xvfnmsub_d, simd_ext_fnmsub, m256d, f64x4); impl_vugv!("lasx", lasx_xvinsgr2vr_w, simd_insert, m256i, i32x8, i32, 3); impl_vugv!("lasx", lasx_xvinsgr2vr_d, simd_insert, m256i, i64x4, i64, 2); +impl_vavg!("lasx", lasx_xvavg_b, m256i, i8x32, i16x32); +impl_vavg!("lasx", lasx_xvavg_h, m256i, i16x16, i32x16); +impl_vavg!("lasx", lasx_xvavg_w, m256i, i32x8, i64x8); +impl_vavg!("lasx", lasx_xvavg_d, m256i, i64x4, i128x4); +impl_vavg!("lasx", lasx_xvavg_bu, m256i, u8x32, u16x32); +impl_vavg!("lasx", lasx_xvavg_hu, m256i, u16x16, u32x16); +impl_vavg!("lasx", lasx_xvavg_wu, m256i, u32x8, u64x8); +impl_vavg!("lasx", lasx_xvavg_du, m256i, u64x4, u128x4); + +impl_vavgr!("lasx", lasx_xvavgr_b, m256i, i8x32, i16x32); +impl_vavgr!("lasx", lasx_xvavgr_h, m256i, i16x16, i32x16); +impl_vavgr!("lasx", lasx_xvavgr_w, m256i, i32x8, i64x8); +impl_vavgr!("lasx", lasx_xvavgr_d, m256i, i64x4, i128x4); +impl_vavgr!("lasx", lasx_xvavgr_bu, m256i, u8x32, u16x32); +impl_vavgr!("lasx", lasx_xvavgr_hu, m256i, u16x16, u32x16); +impl_vavgr!("lasx", lasx_xvavgr_wu, m256i, u32x8, u64x8); +impl_vavgr!("lasx", lasx_xvavgr_du, m256i, u64x4, u128x4); + #[cfg(test)] mod tests { use crate::{ diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs index 1542633a34b35..e39413c5fa0c0 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs @@ -91,38 +91,6 @@ unsafe extern "unadjusted" { fn __lsx_vsat_wu(a: __v4u32, b: u32) -> __v4u32; #[link_name = "llvm.loongarch.lsx.vsat.du"] fn __lsx_vsat_du(a: __v2u64, b: u32) -> __v2u64; - #[link_name = "llvm.loongarch.lsx.vavg.b"] - fn __lsx_vavg_b(a: __v16i8, b: __v16i8) -> __v16i8; - #[link_name = "llvm.loongarch.lsx.vavg.h"] - fn __lsx_vavg_h(a: __v8i16, b: __v8i16) -> __v8i16; - #[link_name = "llvm.loongarch.lsx.vavg.w"] - fn __lsx_vavg_w(a: __v4i32, b: __v4i32) -> __v4i32; - #[link_name = "llvm.loongarch.lsx.vavg.d"] - fn __lsx_vavg_d(a: __v2i64, b: __v2i64) -> __v2i64; - #[link_name = "llvm.loongarch.lsx.vavg.bu"] - fn __lsx_vavg_bu(a: __v16u8, b: __v16u8) -> __v16u8; - #[link_name = "llvm.loongarch.lsx.vavg.hu"] - fn __lsx_vavg_hu(a: __v8u16, b: __v8u16) -> __v8u16; - #[link_name = "llvm.loongarch.lsx.vavg.wu"] - fn __lsx_vavg_wu(a: __v4u32, b: __v4u32) -> __v4u32; - #[link_name = "llvm.loongarch.lsx.vavg.du"] - fn __lsx_vavg_du(a: __v2u64, b: __v2u64) -> __v2u64; - #[link_name = "llvm.loongarch.lsx.vavgr.b"] - fn __lsx_vavgr_b(a: __v16i8, b: __v16i8) -> __v16i8; - #[link_name = "llvm.loongarch.lsx.vavgr.h"] - fn __lsx_vavgr_h(a: __v8i16, b: __v8i16) -> __v8i16; - #[link_name = "llvm.loongarch.lsx.vavgr.w"] - fn __lsx_vavgr_w(a: __v4i32, b: __v4i32) -> __v4i32; - #[link_name = "llvm.loongarch.lsx.vavgr.d"] - fn __lsx_vavgr_d(a: __v2i64, b: __v2i64) -> __v2i64; - #[link_name = "llvm.loongarch.lsx.vavgr.bu"] - fn __lsx_vavgr_bu(a: __v16u8, b: __v16u8) -> __v16u8; - #[link_name = "llvm.loongarch.lsx.vavgr.hu"] - fn __lsx_vavgr_hu(a: __v8u16, b: __v8u16) -> __v8u16; - #[link_name = "llvm.loongarch.lsx.vavgr.wu"] - fn __lsx_vavgr_wu(a: __v4u32, b: __v4u32) -> __v4u32; - #[link_name = "llvm.loongarch.lsx.vavgr.du"] - fn __lsx_vavgr_du(a: __v2u64, b: __v2u64) -> __v2u64; #[link_name = "llvm.loongarch.lsx.vhaddw.h.b"] fn __lsx_vhaddw_h_b(a: __v16i8, b: __v16i8) -> __v8i16; #[link_name = "llvm.loongarch.lsx.vhaddw.w.h"] @@ -1203,118 +1171,6 @@ pub fn lsx_vsat_du(a: m128i) -> m128i { unsafe { transmute(__lsx_vsat_du(transmute(a), IMM6)) } } -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_b(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_b(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_h(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_h(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_w(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_w(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_d(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_d(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_bu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_bu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_hu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_hu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_wu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_wu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavg_du(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavg_du(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_b(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_b(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_h(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_h(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_w(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_w(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_d(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_d(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_bu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_bu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_hu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_hu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_wu(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_wu(transmute(a), transmute(b))) } -} - -#[inline] -#[target_feature(enable = "lsx")] -#[unstable(feature = "stdarch_loongarch", issue = "117427")] -pub fn lsx_vavgr_du(a: m128i, b: m128i) -> m128i { - unsafe { transmute(__lsx_vavgr_du(transmute(a), transmute(b))) } -} - #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lsx/portable.rs b/library/stdarch/crates/core_arch/src/loongarch64/lsx/portable.rs index 31467bf013e27..2b5bfe1ab4d2b 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lsx/portable.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lsx/portable.rs @@ -574,6 +574,24 @@ impl_vugv!("lsx", lsx_vinsgr2vr_h, simd_insert, m128i, i16x8, i32, 3); impl_vugv!("lsx", lsx_vinsgr2vr_w, simd_insert, m128i, i32x4, i32, 2); impl_vugv!("lsx", lsx_vinsgr2vr_d, simd_insert, m128i, i64x2, i64, 1); +impl_vavg!("lsx", lsx_vavg_b, m128i, i8x16, i16x16); +impl_vavg!("lsx", lsx_vavg_h, m128i, i16x8, i32x8); +impl_vavg!("lsx", lsx_vavg_w, m128i, i32x4, i64x4); +impl_vavg!("lsx", lsx_vavg_d, m128i, i64x2, i128x2); +impl_vavg!("lsx", lsx_vavg_bu, m128i, u8x16, u16x16); +impl_vavg!("lsx", lsx_vavg_hu, m128i, u16x8, u32x8); +impl_vavg!("lsx", lsx_vavg_wu, m128i, u32x4, u64x4); +impl_vavg!("lsx", lsx_vavg_du, m128i, u64x2, u128x2); + +impl_vavgr!("lsx", lsx_vavgr_b, m128i, i8x16, i16x16); +impl_vavgr!("lsx", lsx_vavgr_h, m128i, i16x8, i32x8); +impl_vavgr!("lsx", lsx_vavgr_w, m128i, i32x4, i64x4); +impl_vavgr!("lsx", lsx_vavgr_d, m128i, i64x2, i128x2); +impl_vavgr!("lsx", lsx_vavgr_bu, m128i, u8x16, u16x16); +impl_vavgr!("lsx", lsx_vavgr_hu, m128i, u16x8, u32x8); +impl_vavgr!("lsx", lsx_vavgr_wu, m128i, u32x4, u64x4); +impl_vavgr!("lsx", lsx_vavgr_du, m128i, u64x2, u128x2); + #[cfg(test)] mod tests { use crate::{ diff --git a/library/stdarch/crates/core_arch/src/loongarch64/simd.rs b/library/stdarch/crates/core_arch/src/loongarch64/simd.rs index 1d83333e2f532..7ce6071841460 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/simd.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/simd.rs @@ -304,6 +304,44 @@ pub(super) const unsafe fn simd_ext_stx(a: T, b: *mut i8, c: i64) { core::ptr::write_unaligned(b, a); } +macro_rules! impl_vavg { + ($ft:literal, $name:ident, $oty:ty, $ity:ty, $wty:ty) => { + #[inline] + #[target_feature(enable = $ft)] + #[unstable(feature = "stdarch_loongarch", issue = "117427")] + pub fn $name(a: $oty, b: $oty) -> $oty { + unsafe { + let a: $wty = simd_cast(transmute::<_, $ity>(a)); + let b: $wty = simd_cast(transmute::<_, $ity>(b)); + let r: $ity = simd_cast(simd_shr(simd_add(a, b), <$wty>::splat(1))); + transmute(r) + } + } + }; +} + +macro_rules! impl_vavgr { + ($ft:literal, $name:ident, $oty:ty, $ity:ty, $wty:ty) => { + #[inline] + #[target_feature(enable = $ft)] + #[unstable(feature = "stdarch_loongarch", issue = "117427")] + pub fn $name(a: $oty, b: $oty) -> $oty { + unsafe { + let a: $wty = simd_cast(transmute::<_, $ity>(a)); + let b: $wty = simd_cast(transmute::<_, $ity>(b)); + let r: $ity = simd_cast(simd_shr( + simd_add(simd_add(a, b), <$wty>::splat(1)), + <$wty>::splat(1), + )); + transmute(r) + } + } + }; +} + +pub(super) use impl_vavg; +pub(super) use impl_vavgr; + macro_rules! impl_vv { ($ft:literal, $name:ident, $op:ident, $oty:ty, $ity:ty) => { #[inline] diff --git a/library/stdarch/crates/stdarch-gen-loongarch/lasx.spec b/library/stdarch/crates/stdarch-gen-loongarch/lasx.spec index 9eff3d01fa1f3..eb3ff074a3978 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/lasx.spec +++ b/library/stdarch/crates/stdarch-gen-loongarch/lasx.spec @@ -996,81 +996,97 @@ asm-fmts = xd, xj, xk data-types = UV4DI, UV4DI, UV4DI /// lasx_xvavg_b +impl = portable name = lasx_xvavg_b asm-fmts = xd, xj, xk data-types = V32QI, V32QI, V32QI /// lasx_xvavg_h +impl = portable name = lasx_xvavg_h asm-fmts = xd, xj, xk data-types = V16HI, V16HI, V16HI /// lasx_xvavg_w +impl = portable name = lasx_xvavg_w asm-fmts = xd, xj, xk data-types = V8SI, V8SI, V8SI /// lasx_xvavg_d +impl = portable name = lasx_xvavg_d asm-fmts = xd, xj, xk data-types = V4DI, V4DI, V4DI /// lasx_xvavg_bu +impl = portable name = lasx_xvavg_bu asm-fmts = xd, xj, xk data-types = UV32QI, UV32QI, UV32QI /// lasx_xvavg_hu +impl = portable name = lasx_xvavg_hu asm-fmts = xd, xj, xk data-types = UV16HI, UV16HI, UV16HI /// lasx_xvavg_wu +impl = portable name = lasx_xvavg_wu asm-fmts = xd, xj, xk data-types = UV8SI, UV8SI, UV8SI /// lasx_xvavg_du +impl = portable name = lasx_xvavg_du asm-fmts = xd, xj, xk data-types = UV4DI, UV4DI, UV4DI /// lasx_xvavgr_b +impl = portable name = lasx_xvavgr_b asm-fmts = xd, xj, xk data-types = V32QI, V32QI, V32QI /// lasx_xvavgr_h +impl = portable name = lasx_xvavgr_h asm-fmts = xd, xj, xk data-types = V16HI, V16HI, V16HI /// lasx_xvavgr_w +impl = portable name = lasx_xvavgr_w asm-fmts = xd, xj, xk data-types = V8SI, V8SI, V8SI /// lasx_xvavgr_d +impl = portable name = lasx_xvavgr_d asm-fmts = xd, xj, xk data-types = V4DI, V4DI, V4DI /// lasx_xvavgr_bu +impl = portable name = lasx_xvavgr_bu asm-fmts = xd, xj, xk data-types = UV32QI, UV32QI, UV32QI /// lasx_xvavgr_hu +impl = portable name = lasx_xvavgr_hu asm-fmts = xd, xj, xk data-types = UV16HI, UV16HI, UV16HI /// lasx_xvavgr_wu +impl = portable name = lasx_xvavgr_wu asm-fmts = xd, xj, xk data-types = UV8SI, UV8SI, UV8SI /// lasx_xvavgr_du +impl = portable name = lasx_xvavgr_du asm-fmts = xd, xj, xk data-types = UV4DI, UV4DI, UV4DI diff --git a/library/stdarch/crates/stdarch-gen-loongarch/lsx.spec b/library/stdarch/crates/stdarch-gen-loongarch/lsx.spec index ba2554b0cf9ff..89970c3657048 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/lsx.spec +++ b/library/stdarch/crates/stdarch-gen-loongarch/lsx.spec @@ -996,81 +996,97 @@ asm-fmts = vd, vj, vk data-types = UV2DI, UV2DI, UV2DI /// lsx_vavg_b +impl = portable name = lsx_vavg_b asm-fmts = vd, vj, vk data-types = V16QI, V16QI, V16QI /// lsx_vavg_h +impl = portable name = lsx_vavg_h asm-fmts = vd, vj, vk data-types = V8HI, V8HI, V8HI /// lsx_vavg_w +impl = portable name = lsx_vavg_w asm-fmts = vd, vj, vk data-types = V4SI, V4SI, V4SI /// lsx_vavg_d +impl = portable name = lsx_vavg_d asm-fmts = vd, vj, vk data-types = V2DI, V2DI, V2DI /// lsx_vavg_bu +impl = portable name = lsx_vavg_bu asm-fmts = vd, vj, vk data-types = UV16QI, UV16QI, UV16QI /// lsx_vavg_hu +impl = portable name = lsx_vavg_hu asm-fmts = vd, vj, vk data-types = UV8HI, UV8HI, UV8HI /// lsx_vavg_wu +impl = portable name = lsx_vavg_wu asm-fmts = vd, vj, vk data-types = UV4SI, UV4SI, UV4SI /// lsx_vavg_du +impl = portable name = lsx_vavg_du asm-fmts = vd, vj, vk data-types = UV2DI, UV2DI, UV2DI /// lsx_vavgr_b +impl = portable name = lsx_vavgr_b asm-fmts = vd, vj, vk data-types = V16QI, V16QI, V16QI /// lsx_vavgr_h +impl = portable name = lsx_vavgr_h asm-fmts = vd, vj, vk data-types = V8HI, V8HI, V8HI /// lsx_vavgr_w +impl = portable name = lsx_vavgr_w asm-fmts = vd, vj, vk data-types = V4SI, V4SI, V4SI /// lsx_vavgr_d +impl = portable name = lsx_vavgr_d asm-fmts = vd, vj, vk data-types = V2DI, V2DI, V2DI /// lsx_vavgr_bu +impl = portable name = lsx_vavgr_bu asm-fmts = vd, vj, vk data-types = UV16QI, UV16QI, UV16QI /// lsx_vavgr_hu +impl = portable name = lsx_vavgr_hu asm-fmts = vd, vj, vk data-types = UV8HI, UV8HI, UV8HI /// lsx_vavgr_wu +impl = portable name = lsx_vavgr_wu asm-fmts = vd, vj, vk data-types = UV4SI, UV4SI, UV4SI /// lsx_vavgr_du +impl = portable name = lsx_vavgr_du asm-fmts = vd, vj, vk data-types = UV2DI, UV2DI, UV2DI diff --git a/library/stdarch/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt b/library/stdarch/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt index 8b8c82b3bb247..f47c17b23adea 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt +++ b/library/stdarch/crates/stdarch-gen-loongarch/src/portable-intrinsics.txt @@ -219,6 +219,22 @@ lsx_vssub_bu lsx_vssub_hu lsx_vssub_wu lsx_vssub_du +lsx_vavg_b +lsx_vavg_h +lsx_vavg_w +lsx_vavg_d +lsx_vavg_bu +lsx_vavg_hu +lsx_vavg_wu +lsx_vavg_du +lsx_vavgr_b +lsx_vavgr_h +lsx_vavgr_w +lsx_vavgr_d +lsx_vavgr_bu +lsx_vavgr_hu +lsx_vavgr_wu +lsx_vavgr_du lsx_vadda_b lsx_vadda_h lsx_vadda_w @@ -512,6 +528,22 @@ lasx_xvssub_bu lasx_xvssub_hu lasx_xvssub_wu lasx_xvssub_du +lasx_xvavg_b +lasx_xvavg_h +lasx_xvavg_w +lasx_xvavg_d +lasx_xvavg_bu +lasx_xvavg_hu +lasx_xvavg_wu +lasx_xvavg_du +lasx_xvavgr_b +lasx_xvavgr_h +lasx_xvavgr_w +lasx_xvavgr_d +lasx_xvavgr_bu +lasx_xvavgr_hu +lasx_xvavgr_wu +lasx_xvavgr_du lasx_xvadda_b lasx_xvadda_h lasx_xvadda_w From 8e8fedc6ed3afc381c6654f8a4d7577d7ebb8ead Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 18 Dec 2025 17:41:19 +0000 Subject: [PATCH 0008/1309] Delay stringification of const to backend --- src/asm.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 6fd7188f656c5..d11ed50e26707 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,6 +12,7 @@ use rustc_codegen_ssa::traits::{ }; use rustc_middle::bug; use rustc_middle::ty::Instance; +use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; use rustc_target::asm::*; @@ -303,8 +304,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } } - InlineAsmOperandRef::Const { ref string } => { - constants_len += string.len() + att_dialect as usize; + InlineAsmOperandRef::Const { .. } => { + // We don't know the size at this point, just some estimate. + constants_len += 20; } InlineAsmOperandRef::SymFn { instance } => { @@ -453,7 +455,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(escaped_char); } } - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier, span } => { let mut push_to_template = |modifier, gcc_idx| { use std::fmt::Write; @@ -511,8 +513,15 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(name); } - InlineAsmOperandRef::Const { ref string } => { - template_str.push_str(string); + InlineAsmOperandRef::Const { value, ty } => { + // Const operands get injected directly into the template + let string = rustc_codegen_ssa::common::asm_const_to_str( + self.tcx, + span, + value, + self.layout_of(ty), + ); + template_str.push_str(&string); } InlineAsmOperandRef::Label { label } => { @@ -933,13 +942,19 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { .unwrap_or(string.len()); } } - InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span: _ } => { + InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { - GlobalAsmOperandRef::Const { ref string } => { + GlobalAsmOperandRef::Const { value, ty } => { // Const operands get injected directly into the // template. Note that we don't need to escape % // here unlike normal inline assembly. - template_str.push_str(string); + let string = rustc_codegen_ssa::common::asm_const_to_str( + self.tcx, + span, + value, + self.layout_of(ty), + ); + template_str.push_str(&string); } GlobalAsmOperandRef::SymFn { instance } => { From 9b99b0564a572701e1dac2bb665c51e8691b8838 Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 18 Dec 2025 18:31:04 +0000 Subject: [PATCH 0009/1309] Unify handling of asm const and sym using CTFE This gives the asm-const code the basic ability to deal wiht pointer and provenances, which lays the ground work for asm_const_ptr. Note that `SymStatic` is not fully removed, a specialized is kept and renamed as `SymThreadLocalStatic`, for `#[thread_local]` statics where CTFE does not support naming. The `#[thread_local]` is unstable feature and it's not clear if we want to support this in `sym`, but removal of it should be a separate PR. --- src/asm.rs | 169 +++++++++++++++++++++++++++++++++-------------------- 1 file changed, 106 insertions(+), 63 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index d11ed50e26707..a1321a681a0d7 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -11,6 +11,7 @@ use rustc_codegen_ssa::traits::{ GlobalAsmOperandRef, InlineAsmOperandRef, }; use rustc_middle::bug; +use rustc_middle::mir::interpret::{GlobalAlloc, Scalar}; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; @@ -309,13 +310,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { constants_len += 20; } - InlineAsmOperandRef::SymFn { instance } => { - // FIXME(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O) - // or byte count suffixes (x86 Windows). - constants_len += self.tcx.symbol_name(instance).name.len(); - } - InlineAsmOperandRef::SymStatic { def_id } => { + InlineAsmOperandRef::SymThreadLocalStatic { def_id } => { // FIXME(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). constants_len += @@ -404,24 +399,32 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // processed in the previous pass } - InlineAsmOperandRef::SymFn { instance } => { - inputs.push(AsmInOperand { - constraint: "X".into(), - rust_idx, - val: get_fn(self.cx, instance).get_address(None), - }); - } - - InlineAsmOperandRef::SymStatic { def_id } => { - inputs.push(AsmInOperand { - constraint: "X".into(), - rust_idx, - val: self.cx.get_static(def_id).get_address(None), - }); - } + InlineAsmOperandRef::Const { value, ty: _ } => match value { + Scalar::Int(_) => (), + Scalar::Ptr(ptr, _) => { + let (prov, offset) = ptr.prov_and_relative_offset(); + assert_eq!(offset.bytes(), 0); + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let val = match global_alloc { + GlobalAlloc::Function { instance } => { + get_fn(self.cx, instance).get_address(None) + } + GlobalAlloc::Static(def_id) => { + self.cx.get_static(def_id).get_address(None) + } + GlobalAlloc::Memory(_) + | GlobalAlloc::VTable(..) + | GlobalAlloc::TypeId { .. } => unreachable!(), + }; + inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, val }); + } + }, - InlineAsmOperandRef::Const { .. } => { - // processed in the previous pass + InlineAsmOperandRef::SymThreadLocalStatic { def_id } => { + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (MachO). + constants_len += + self.tcx.symbol_name(Instance::mono(self.tcx, def_id)).name.len(); } InlineAsmOperandRef::Label { .. } => { @@ -497,15 +500,46 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { push_to_template(modifier, gcc_index); } - InlineAsmOperandRef::SymFn { instance } => { - // FIXME(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O) - // or byte count suffixes (x86 Windows). - let name = self.tcx.symbol_name(instance).name; - template_str.push_str(name); + InlineAsmOperandRef::Const { value, ty } => { + match value { + Scalar::Int(int) => { + // Const operands get injected directly into the template + let string = rustc_codegen_ssa::common::asm_const_to_str( + self.tcx, + span, + int, + self.layout_of(ty), + ); + template_str.push_str(&string); + } + + Scalar::Ptr(ptr, _) => { + let (prov, offset) = ptr.prov_and_relative_offset(); + assert_eq!(offset.bytes(), 0); + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let symbol_name = match global_alloc { + GlobalAlloc::Function { instance } => { + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + self.tcx.symbol_name(instance) + } + GlobalAlloc::Static(def_id) => { + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O). + let instance = Instance::mono(self.tcx, def_id); + self.tcx.symbol_name(instance) + } + GlobalAlloc::Memory(_) + | GlobalAlloc::VTable(..) + | GlobalAlloc::TypeId { .. } => unreachable!(), + }; + template_str.push_str(symbol_name.name); + } + } } - InlineAsmOperandRef::SymStatic { def_id } => { + InlineAsmOperandRef::SymThreadLocalStatic { def_id } => { // FIXME(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). let instance = Instance::mono(self.tcx, def_id); @@ -513,17 +547,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { template_str.push_str(name); } - InlineAsmOperandRef::Const { value, ty } => { - // Const operands get injected directly into the template - let string = rustc_codegen_ssa::common::asm_const_to_str( - self.tcx, - span, - value, - self.layout_of(ty), - ); - template_str.push_str(&string); - } - InlineAsmOperandRef::Label { label } => { let label_gcc_index = labels.iter().position(|&l| l == label).expect("wrong rust index"); @@ -945,29 +968,49 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { InlineAsmTemplatePiece::Placeholder { operand_idx, modifier: _, span } => { match operands[operand_idx] { GlobalAsmOperandRef::Const { value, ty } => { - // Const operands get injected directly into the - // template. Note that we don't need to escape % - // here unlike normal inline assembly. - let string = rustc_codegen_ssa::common::asm_const_to_str( - self.tcx, - span, - value, - self.layout_of(ty), - ); - template_str.push_str(&string); - } + match value { + Scalar::Int(int) => { + // Const operands get injected directly into the + // template. Note that we don't need to escape % + // here unlike normal inline assembly. + let string = rustc_codegen_ssa::common::asm_const_to_str( + self.tcx, + span, + int, + self.layout_of(ty), + ); + template_str.push_str(&string); + } - GlobalAsmOperandRef::SymFn { instance } => { - let function = get_fn(self, instance); - self.add_used_function(function); - // FIXME(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O) - // or byte count suffixes (x86 Windows). - let name = self.tcx.symbol_name(instance).name; - template_str.push_str(name); + Scalar::Ptr(ptr, _) => { + let (prov, offset) = ptr.prov_and_relative_offset(); + assert_eq!(offset.bytes(), 0); + let global_alloc = self.tcx.global_alloc(prov.alloc_id()); + let symbol_name = match global_alloc { + GlobalAlloc::Function { instance } => { + let function = get_fn(self, instance); + self.add_used_function(function); + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + self.tcx.symbol_name(instance) + } + GlobalAlloc::Static(def_id) => { + // FIXME(antoyo): set the global variable as used. + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O). + let instance = Instance::mono(self.tcx, def_id); + self.tcx.symbol_name(instance) + } + GlobalAlloc::Memory(_) + | GlobalAlloc::VTable(..) + | GlobalAlloc::TypeId { .. } => unreachable!(), + }; + template_str.push_str(symbol_name.name); + } + } } - - GlobalAsmOperandRef::SymStatic { def_id } => { + GlobalAsmOperandRef::SymThreadLocalStatic { def_id } => { // FIXME(antoyo): set the global variable as used. // FIXME(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). From 8ad236c8e371bf9688c39144a79cc50dd08abbce Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 19 Dec 2025 16:05:00 +0000 Subject: [PATCH 0010/1309] Unify handling of `GlobalAlloc` inside backend With the previous commit, now we can see there are some code duplication for the handling of `GlobalAlloc` inside backends. Do some clean up to unify them. --- src/asm.rs | 52 ++++++--------------- src/common.rs | 123 ++++++++++++++++++++++++++++++-------------------- 2 files changed, 88 insertions(+), 87 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index a1321a681a0d7..90576906c6702 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -145,6 +145,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { // Clobbers collected from `out("explicit register") _` and `inout("explicit_reg") var => _` let mut clobbers = vec![]; + // Symbols name that needs to be inserted to asm const ptr template string. + let mut const_syms = vec![]; + // We're trying to preallocate space for the template let mut constants_len = 0; @@ -405,17 +408,8 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let (prov, offset) = ptr.prov_and_relative_offset(); assert_eq!(offset.bytes(), 0); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); - let val = match global_alloc { - GlobalAlloc::Function { instance } => { - get_fn(self.cx, instance).get_address(None) - } - GlobalAlloc::Static(def_id) => { - self.cx.get_static(def_id).get_address(None) - } - GlobalAlloc::Memory(_) - | GlobalAlloc::VTable(..) - | GlobalAlloc::TypeId { .. } => unreachable!(), - }; + let (val, sym) = self.cx.alloc_to_backend(global_alloc, true).unwrap(); + const_syms.push(sym.unwrap()); inputs.push(AsmInOperand { constraint: "X".into(), rust_idx, val }); } }, @@ -514,27 +508,13 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { } Scalar::Ptr(ptr, _) => { - let (prov, offset) = ptr.prov_and_relative_offset(); + let (_, offset) = ptr.prov_and_relative_offset(); assert_eq!(offset.bytes(), 0); - let global_alloc = self.tcx.global_alloc(prov.alloc_id()); - let symbol_name = match global_alloc { - GlobalAlloc::Function { instance } => { - // FIXME(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O) - // or byte count suffixes (x86 Windows). - self.tcx.symbol_name(instance) - } - GlobalAlloc::Static(def_id) => { - // FIXME(@Amanieu): Additional mangling is needed on - // some targets to add a leading underscore (Mach-O). - let instance = Instance::mono(self.tcx, def_id); - self.tcx.symbol_name(instance) - } - GlobalAlloc::Memory(_) - | GlobalAlloc::VTable(..) - | GlobalAlloc::TypeId { .. } => unreachable!(), - }; - template_str.push_str(symbol_name.name); + let sym = const_syms.remove(0); + // FIXME(@Amanieu): Additional mangling is needed on + // some targets to add a leading underscore (Mach-O) + // or byte count suffixes (x86 Windows). + template_str.push_str(sym.name); } } } @@ -995,16 +975,14 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // or byte count suffixes (x86 Windows). self.tcx.symbol_name(instance) } - GlobalAlloc::Static(def_id) => { + _ => { + let (_, syms) = + self.alloc_to_backend(global_alloc, true).unwrap(); // FIXME(antoyo): set the global variable as used. // FIXME(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O). - let instance = Instance::mono(self.tcx, def_id); - self.tcx.symbol_name(instance) + syms.unwrap() } - GlobalAlloc::Memory(_) - | GlobalAlloc::VTable(..) - | GlobalAlloc::TypeId { .. } => unreachable!(), }; template_str.push_str(symbol_name.name); } diff --git a/src/common.rs b/src/common.rs index e73b8aab54d73..d3d9f60128b5c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -7,6 +7,7 @@ use rustc_codegen_ssa::traits::{ use rustc_middle::mir::Mutability; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::LayoutOf; +use rustc_middle::ty::{Instance, SymbolName}; use rustc_session::PointerAuthSchema; use crate::consts::const_alloc_to_gcc; @@ -47,6 +48,68 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // SIMD builtins require a constant value. self.bitcast_if_needed(value, typ) } + + pub(crate) fn alloc_to_backend( + &self, + global_alloc: GlobalAlloc<'tcx>, + need_symbol_name: bool, + ) -> Result<(RValue<'gcc>, Option>), u64> { + let alloc = match global_alloc { + GlobalAlloc::Function { instance, .. } => { + return Ok(( + self.get_fn_addr(instance, None), + need_symbol_name.then(|| self.tcx.symbol_name(instance)), + )); + } + GlobalAlloc::Static(def_id) => { + assert!(self.tcx.is_static(def_id)); + return Ok(( + self.get_static(def_id).get_address(None), + need_symbol_name + .then(|| self.tcx.symbol_name(Instance::mono(self.tcx, def_id))), + )); + } + GlobalAlloc::TypeId { .. } => { + // Drop the provenance, the offset contains the bytes of the hash, so + // just return 0 as base address. + return Err(0); + } + + GlobalAlloc::Memory(alloc) => { + if alloc.inner().len() == 0 { + // For ZSTs directly codegen an aligned pointer. + // This avoids generating a zero-sized constant value and actually needing a + // real address at runtime. + return Err(alloc.inner().align.bytes()); + } + + alloc + } + + GlobalAlloc::VTable(ty, dyn_ty) => { + self.tcx + .global_alloc(self.tcx.vtable_allocation(( + ty, + dyn_ty.principal().map(|principal| { + self.tcx.instantiate_bound_regions_with_erased(principal) + }), + ))) + .unwrap_memory() + } + }; + + let value = match alloc.inner().mutability { + Mutability::Mut => { + self.static_addr_of_mut(const_alloc_to_gcc(self, alloc), alloc.inner().align, None) + } + _ => self.static_addr_of(alloc, None), + }; + if !self.sess().fewer_names() { + // FIXME(antoyo): set value name. + } + + Ok((value, None)) + } } pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { @@ -269,57 +332,17 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { Scalar::Ptr(ptr, _size) => { let (prov, offset) = ptr.prov_and_relative_offset(); let alloc_id = prov.alloc_id(); - let base_addr = match self.tcx.global_alloc(alloc_id) { - GlobalAlloc::Memory(alloc) => { - // For ZSTs directly codegen an aligned pointer. - // This avoids generating a zero-sized constant value and actually needing a - // real address at runtime. - if alloc.inner().len() == 0 { - let val = alloc.inner().align.bytes().wrapping_add(offset.bytes()); - let val = self.const_usize(self.tcx.truncate_to_target_usize(val)); - return if matches!(layout.primitive(), Pointer(_)) { - self.context.new_cast(None, val, ty) - } else { - self.const_bitcast(val, ty) - }; - } - - let value = match alloc.inner().mutability { - Mutability::Mut => self.static_addr_of_mut( - const_alloc_to_gcc(self, alloc), - alloc.inner().align, - None, - ), - _ => self.static_addr_of(alloc, None), + let base_addr = match self.alloc_to_backend(self.tcx.global_alloc(alloc_id), false) + { + Ok((base_addr, _)) => base_addr, + Err(base_addr) => { + let val = base_addr.wrapping_add(offset.bytes()); + let val = self.const_usize(self.tcx.truncate_to_target_usize(val)); + return if matches!(layout.primitive(), Pointer(_)) { + self.context.new_cast(None, val, ty) + } else { + self.const_bitcast(val, ty) }; - if !self.sess().fewer_names() { - // FIXME(antoyo): set value name. - } - value - } - GlobalAlloc::Function { instance, .. } => self.get_fn_addr(instance, None), - GlobalAlloc::VTable(ty, dyn_ty) => { - let alloc = self - .tcx - .global_alloc(self.tcx.vtable_allocation(( - ty, - dyn_ty.principal().map(|principal| { - self.tcx.instantiate_bound_regions_with_erased(principal) - }), - ))) - .unwrap_memory(); - self.static_addr_of(alloc, None) - } - GlobalAlloc::TypeId { .. } => { - let val = self.const_usize(offset.bytes()); - // This is still a variable of pointer type, even though we only use the provenance - // of that pointer in CTFE and Miri. But to make LLVM's type system happy, - // we need an int-to-ptr cast here (it doesn't matter at all which provenance that picks). - return self.context.new_cast(None, val, ty); - } - GlobalAlloc::Static(def_id) => { - assert!(self.tcx.is_static(def_id)); - self.get_static(def_id).get_address(None) } }; let ptr_type = base_addr.get_type(); From c634dee314720518762adaf53c6c9322ab9aff4a Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Thu, 18 Dec 2025 20:00:30 +0000 Subject: [PATCH 0011/1309] Handle pointers with offset for asm const --- src/asm.rs | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 90576906c6702..23aeb1e06463c 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -1,8 +1,10 @@ // cSpell:ignoreRegExp [afkspqvwy]reg use std::borrow::Cow; +use std::fmt::Write; use gccjit::{LValue, RValue, ToRValue, Type}; +use rustc_abi::Size; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; use rustc_codegen_ssa::mir::operand::OperandValue; use rustc_codegen_ssa::mir::place::PlaceRef; @@ -11,7 +13,7 @@ use rustc_codegen_ssa::traits::{ GlobalAsmOperandRef, InlineAsmOperandRef, }; use rustc_middle::bug; -use rustc_middle::mir::interpret::{GlobalAlloc, Scalar}; +use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::LayoutOf; use rustc_span::{DUMMY_SP, Span}; @@ -405,8 +407,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { InlineAsmOperandRef::Const { value, ty: _ } => match value { Scalar::Int(_) => (), Scalar::Ptr(ptr, _) => { - let (prov, offset) = ptr.prov_and_relative_offset(); - assert_eq!(offset.bytes(), 0); + let (prov, _) = ptr.prov_and_relative_offset(); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); let (val, sym) = self.cx.alloc_to_backend(global_alloc, true).unwrap(); const_syms.push(sym.unwrap()); @@ -509,12 +510,17 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { Scalar::Ptr(ptr, _) => { let (_, offset) = ptr.prov_and_relative_offset(); - assert_eq!(offset.bytes(), 0); let sym = const_syms.remove(0); // FIXME(@Amanieu): Additional mangling is needed on // some targets to add a leading underscore (Mach-O) // or byte count suffixes (x86 Windows). template_str.push_str(sym.name); + + if offset != Size::ZERO { + let offset = + self.sign_extend_to_target_isize(offset.bytes()); + write!(template_str, "{offset:+}").unwrap(); + } } } } @@ -964,7 +970,6 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { Scalar::Ptr(ptr, _) => { let (prov, offset) = ptr.prov_and_relative_offset(); - assert_eq!(offset.bytes(), 0); let global_alloc = self.tcx.global_alloc(prov.alloc_id()); let symbol_name = match global_alloc { GlobalAlloc::Function { instance } => { @@ -985,6 +990,12 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } }; template_str.push_str(symbol_name.name); + + if offset != Size::ZERO { + let offset = + self.sign_extend_to_target_isize(offset.bytes()); + write!(template_str, "{offset:+}").unwrap(); + } } } } From f71031d4e09ab858bfc8290b9cdd0aed3bd6b3cc Mon Sep 17 00:00:00 2001 From: Gary Guo Date: Fri, 19 Dec 2025 17:10:58 +0000 Subject: [PATCH 0012/1309] Generate unique symbol names if const pointers refer to promoted static --- src/common.rs | 15 ++++++++++++++- src/context.rs | 22 ++++++++++++++++++++++ 2 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/common.rs b/src/common.rs index d3d9f60128b5c..6bd186f1121fc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -1,4 +1,4 @@ -use gccjit::{LValue, RValue, ToRValue, Type}; +use gccjit::{GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_abi::Primitive::Pointer; use rustc_abi::{self as abi, HasDataLayout}; use rustc_codegen_ssa::traits::{ @@ -98,6 +98,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } }; + if need_symbol_name { + let name = self.generate_global_symbol_name(); + + let init = crate::consts::const_alloc_to_gcc_uncached(self, alloc); + let alloc = alloc.inner(); + let typ = self.val_ty(init).get_aligned(alloc.align.bytes()); + + let global = self.declare_global_with_linkage(&name, typ, GlobalKind::Internal); + + global.global_set_initializer_rvalue(init); + return Ok((global.get_address(None), Some(SymbolName::new(self.tcx, &name)))); + } + let value = match alloc.inner().mutability { Mutability::Mut => { self.static_addr_of_mut(const_alloc_to_gcc(self, alloc), alloc.inner().align, None) diff --git a/src/context.rs b/src/context.rs index 184db4cb25778..8045e8ae9d28f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -117,6 +117,9 @@ pub struct CodegenCx<'gcc, 'tcx> { /// A counter that is used for generating local symbol names local_gen_sym_counter: Cell, + /// A counter that is used for generating global symbol names + global_gen_sym_counter: Cell, + eh_personality: Cell>>, #[cfg(feature = "master")] pub rust_try_fn: Cell, Function<'gcc>)>>, @@ -296,6 +299,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { tcx, struct_types: Default::default(), local_gen_sym_counter: Cell::new(0), + global_gen_sym_counter: Cell::new(0), eh_personality: Cell::new(None), #[cfg(feature = "master")] rust_try_fn: Cell::new(None), @@ -599,6 +603,24 @@ impl<'b, 'tcx> CodegenCx<'b, 'tcx> { name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY)); name } + + /// Generates a new global symbol name with the given prefix. This symbol name must + /// only be used for definitions with `internal` or `private` linkage. + pub fn generate_global_symbol_name(&self) -> String { + let idx = self.global_gen_sym_counter.get(); + self.global_gen_sym_counter.set(idx + 1); + + let sym = self.codegen_unit.symbol_name(); + let prefix = sym.as_str(); + let mut name = String::with_capacity(prefix.len() + 6); + name.push_str(prefix); + name.push('.'); + // Offset the index by the base so that always at least two characters + // are generated. This avoids cases where the suffix is interpreted as + // size by the assembler (for m68k: .b, .w, .l). + name.push_str(&(idx as u64 + ALPHANUMERIC_ONLY as u64).to_base(ALPHANUMERIC_ONLY)); + name + } } fn to_gcc_tls_mode(tls_model: TlsModel) -> gccjit::TlsModel { From 9824c0e51f136310f5f8ce814324fbe0424cdf33 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 8 Jul 2026 19:07:34 +0000 Subject: [PATCH 0013/1309] Split IncrCompSession out of Session This will allow introducing a separate incr comp session dir for the post LTO artifacts in the future. In addition it statically encodes the lifetime of the incr comp session rather than requiring an enum behind a mutex stored in the Session. --- src/lib.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 4cc4a2d258d14..c570f4e2165b2 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,8 +94,8 @@ use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; -use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; +use rustc_session::{IncrCompSession, Session}; use rustc_span::{Symbol, sym}; use rustc_target::spec::{Arch, RelocModel}; use tempfile::TempDir; @@ -297,13 +297,14 @@ impl CodegenBackend for GccCodegenBackend { &self, ongoing_codegen: Box, sess: &Session, + incr_comp_session: Option<&IncrCompSession>, _outputs: &OutputFilenames, crate_info: &CrateInfo, ) -> (CompiledModules, WorkProductMap) { ongoing_codegen .downcast::>() .expect("Expected GccCodegenBackend's OngoingCodegen, found Box") - .join(sess, crate_info) + .join(sess, incr_comp_session, crate_info) } fn target_config(&self, sess: &Session) -> TargetConfig { From a0b341668d9fddfacbcf1dc66520ce5672d5cff9 Mon Sep 17 00:00:00 2001 From: aisr Date: Wed, 1 Apr 2026 18:00:47 +0800 Subject: [PATCH 0014/1309] add safety section for mem::zeroed --- library/core/src/mem/mod.rs | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 63dcf768de073..a603f7f9aaac0 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -706,16 +706,18 @@ pub const fn needs_drop() -> bool { /// This means that, for example, the padding byte in `(u8, u16)` is not /// necessarily zeroed. /// -/// There is no guarantee that an all-zero byte-pattern represents a valid value -/// of some type `T`. For example, the all-zero byte-pattern is not a valid value -/// for reference types (`&T`, `&mut T`) and function pointers. Using `zeroed` -/// on such types causes immediate [undefined behavior][ub] because [the Rust -/// compiler assumes][inv] that there always is a valid value in a variable it -/// considers initialized. -/// /// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed]. /// It is useful for FFI sometimes, but should generally be avoided. /// +/// +/// # Safety +/// +/// The all-zero byte-pattern must represent a valid value of type `T`. +/// For example, it is not valid for reference types (`&T`, `&mut T`) or function +/// pointers. Using `zeroed` on such types causes immediate [undefined behavior][ub] +/// because [the Rust compiler assumes][inv] that there always is a valid value in a +/// variable it considers initialized. +/// /// [zeroed]: MaybeUninit::zeroed /// [ub]: ../../reference/behavior-considered-undefined.html /// [inv]: MaybeUninit#initialization-invariant From f15d69b15470d787c3abee0338e1eba7779932a5 Mon Sep 17 00:00:00 2001 From: Mike Hommey Date: Tue, 28 Jul 2026 18:47:39 +0900 Subject: [PATCH 0015/1309] Revert "codegen: add OperandValue::Uninit to skip stores for entirely-uninit constants" This reverts commit ed9de1e4663c73242710235ff343895e16a4d539. --- src/intrinsic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 986c04e6b4813..09ad3254e5714 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -629,7 +629,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc for arg in args { match arg.val { - OperandValue::ZeroSized | OperandValue::Uninit => {} + OperandValue::ZeroSized => {} OperandValue::Immediate(_) => call_args.push(arg.immediate()), OperandValue::Pair(a, b) => { call_args.push(a); From 69336cf79cc0fb3cc67910abb8c0e77e35de1696 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 29 Jul 2026 14:18:32 +0200 Subject: [PATCH 0016/1309] Rename `rustc_codegen_gcc/errors.rs` into `rustc_codegen_gcc/diagnostics.rs` --- src/asm.rs | 2 +- src/back/lto.rs | 2 +- src/back/write.rs | 2 +- src/builder.rs | 4 ++-- src/{errors.rs => diagnostics.rs} | 0 src/lib.rs | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) rename src/{errors.rs => diagnostics.rs} (100%) diff --git a/src/asm.rs b/src/asm.rs index 23aeb1e06463c..ee0cef350b42f 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -22,7 +22,7 @@ use rustc_target::asm::*; use crate::builder::Builder; use crate::callee::get_fn; use crate::context::CodegenCx; -use crate::errors::{NulBytesInAsm, UnwindingInlineAsm}; +use crate::diagnostics::{NulBytesInAsm, UnwindingInlineAsm}; use crate::type_of::LayoutGccExt; // Rust asm! and GCC Extended Asm semantics differ substantially. diff --git a/src/back/lto.rs b/src/back/lto.rs index 7166ad8b1f17f..98f9abdb05c4c 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -35,7 +35,7 @@ use rustc_log::tracing::info; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; -use crate::errors::LtoBitcodeFromRlib; +use crate::diagnostics::LtoBitcodeFromRlib; use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; struct LtoData { diff --git a/src/back/write.rs b/src/back/write.rs index 8fd38a2efd600..cf5514412f745 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -12,7 +12,7 @@ use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; use crate::base::add_pic_option; -use crate::errors::CopyBitcode; +use crate::diagnostics::CopyBitcode; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( diff --git a/src/builder.rs b/src/builder.rs index 7671d2e026b03..a407362638f10 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -36,7 +36,7 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; -use crate::errors; +use crate::diagnostics; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -1803,7 +1803,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _instance: Option>, ) { // FIXME: implement support for explicit tail calls like rustc_codegen_llvm. - self.tcx.dcx().emit_fatal(errors::ExplicitTailCallsUnsupported); + self.tcx.dcx().emit_fatal(diagnostics::ExplicitTailCallsUnsupported); } fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { diff --git a/src/errors.rs b/src/diagnostics.rs similarity index 100% rename from src/errors.rs rename to src/diagnostics.rs diff --git a/src/lib.rs b/src/lib.rs index 4cc4a2d258d14..55c721a9706a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -59,7 +59,7 @@ mod context; mod coverageinfo; mod debuginfo; mod declare; -mod errors; +mod diagnostics; mod gcc_util; mod int; mod intrinsic; From 9a77d40805a7aa5447127c8e63243084fd2d063c Mon Sep 17 00:00:00 2001 From: Scott McMurray Date: Wed, 29 Jul 2026 00:36:13 -0700 Subject: [PATCH 0017/1309] Structurally prevent zero-count `BackendRepr::SimdVector`s This is already *supposed* to be impossible in layout, but this emphasizes that better. Ironically I was inspired to do this as part of looking at making `Simd` *work*, but importantly if that's going to happen I think it should be `BackendRepr::Memory` like other ZSTs, *not* a `BackendRepr::ScalarVector` that would need to carry around a useless LLVM value in `OperandValue::Immediate` (where it's not even clear what the LLVM type of that value would be). --- src/type_of.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/type_of.rs b/src/type_of.rs index f2ce7bca1e338..c6c32236ab49f 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -73,7 +73,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( else { element }; - return cx.context.new_vector_type(element, count); + return cx.context.new_vector_type(element, count.as_u64()); } BackendRepr::ScalarPair { .. } => { return cx.type_struct( From 9e90d80463854e1ba1013e1980597515364e1c1d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 2 Aug 2026 00:06:25 +0200 Subject: [PATCH 0018/1309] Merge commit 'b3791c6305afd6ecc3e7f6232487f2bb31aed3e7' --- .cspell.json | 2 +- .github/workflows/ci.yml | 17 +- .github/workflows/stdarch.yml | 20 +- .gitignore | 2 +- CONTRIBUTING.md | 2 +- Cargo.lock | 100 +--- Cargo.toml | 2 +- Readme.md | 8 +- build_system/Cargo.lock | 2 +- build_system/asm-tester/Cargo.lock | 507 ++++++++++++++++++ build_system/asm-tester/Cargo.toml | 13 + build_system/asm-tester/src/main.rs | 66 +++ build_system/src/build.rs | 2 +- build_system/src/clean.rs | 3 +- build_system/src/clippy.rs | 62 +++ build_system/src/config.rs | 13 +- build_system/src/fmt.rs | 5 +- build_system/src/main.rs | 112 ++-- build_system/src/rust_tools.rs | 2 +- build_system/src/test.rs | 197 +++++-- build_system/src/todo.rs | 72 +++ build_system/src/utils.rs | 58 +- doc/subtree.md | 4 +- libgccjit.version | 2 +- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 -- rust-toolchain | 2 +- src/abi.rs | 41 +- src/asm.rs | 19 +- src/attributes.rs | 26 + src/back/lto.rs | 40 +- src/back/write.rs | 5 +- src/base.rs | 123 +---- src/builder.rs | 193 ++++--- src/callee.rs | 2 +- src/common.rs | 12 +- src/consts.rs | 49 +- src/declare.rs | 32 +- src/diagnostics.rs | 4 - src/gcc_util.rs | 152 +++++- src/int.rs | 30 +- src/intrinsic/archs.rs | 86 ++- src/intrinsic/llvm.rs | 121 ++++- src/intrinsic/mod.rs | 67 +-- src/intrinsic/old_archs.rs | 4 + src/lib.rs | 37 +- src/mono_item.rs | 128 ++++- src/type_.rs | 8 +- tests/asm/asm/comments.rs | 12 + .../x86_64-naked-fn-no-cet-prolog.rs | 24 + tests/asm/panic-no-unwind-no-uwtable.rs | 8 + tests/asm/used.rs | 14 + tests/asm/x86_64-sse_crc.rs | 12 + .../compile/x86_interrupt_first_arg_byval.rs | 16 + tests/cpuid.def | 27 + tests/failing-lto-tests.txt | 4 + tests/failing-run-make-tests.txt | 1 + tests/failing-ui-tests.txt | 68 +-- tests/lang_tests.rs | 18 +- tests/run/asm.rs | 42 ++ tests/run/int.rs | 25 + tests/run/mir_preserve_ub_empty_switch.rs | 35 ++ tools/cspell_dicts/rust.txt | 1 + tools/cspell_dicts/rustc_codegen_gcc.txt | 5 + tools/generate_intrinsics.py | 36 +- 64 files changed, 2167 insertions(+), 674 deletions(-) create mode 100644 build_system/asm-tester/Cargo.lock create mode 100644 build_system/asm-tester/Cargo.toml create mode 100644 build_system/asm-tester/src/main.rs create mode 100644 build_system/src/clippy.rs create mode 100644 build_system/src/todo.rs delete mode 100644 patches/0001-Add-stdarch-Cargo.toml-for-testing.patch create mode 100644 tests/asm/asm/comments.rs create mode 100644 tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs create mode 100644 tests/asm/panic-no-unwind-no-uwtable.rs create mode 100644 tests/asm/used.rs create mode 100644 tests/asm/x86_64-sse_crc.rs create mode 100644 tests/compile/x86_interrupt_first_arg_byval.rs create mode 100644 tests/cpuid.def create mode 100644 tests/run/mir_preserve_ub_empty_switch.rs diff --git a/.cspell.json b/.cspell.json index 556432d69a41b..a2856029c2c1a 100644 --- a/.cspell.json +++ b/.cspell.json @@ -22,7 +22,7 @@ "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ - "/(FIXME|NOTE|TODO)\\([^)]+\\)/", + "/(FIXME|NOTE)\\([^)]+\\)/", "__builtin_\\w*" ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa9535a3729c3..b76c79fd10870 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests", + "--std-tests --alloc-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", @@ -36,6 +36,7 @@ jobs: "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", "--projects", + "--gcc-asm-tests", ] steps: @@ -52,9 +53,6 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - - name: Install rustfmt & clippy - run: rustup component add rustfmt clippy - - name: Download artifact run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} @@ -88,16 +86,17 @@ jobs: - name: Check formatting run: ./y.sh fmt --check - - name: clippy - run: | - cargo clippy --all-targets -- -D warnings - cargo clippy --all-targets --no-default-features -- -D warnings - cargo clippy --manifest-path build_system/Cargo.toml --all-targets -- -D warnings + - name: Check todo + run: ./y.sh check-todo + + - name: Check lints + run: ./y.sh clippy - name: Build run: | ./y.sh build --sysroot ./y.sh test --cargo-tests + CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - name: Run y.sh cargo build run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 66f30b147b4c0..17d6449c85e08 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: cargo_runner: [ - "sde -future -rtm_mode full --", + "sde -cpuid-in /home/runner/work/rustc_codegen_gcc/rustc_codegen_gcc/tests/cpuid.def -rtm_mode full --", "", ] @@ -42,8 +42,14 @@ jobs: - name: Install more recent binutils run: | echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list - sudo apt-get update + sudo apt-get update -o Acquire::Retries=3 sudo apt-get install binutils + installed="$(dpkg-query --showformat='${Version}' --show binutils)" + echo "Installed binutils: $installed" + if dpkg --compare-versions "$installed" lt "2.44"; then + echo "::error::binutils upgrade failed (got $installed, need >= 2.44); the apt fetch probably failed" + exit 1 + fi - name: Install Intel Software Development Emulator if: ${{ matrix.cargo_runner }} @@ -51,10 +57,9 @@ jobs: mkdir intel-sde cd intel-sde version=10.8.0-2026-03-15 - url_path=915934 dir=sde-external-$version-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/$url_path/$file + wget http://ci-mirrors.rust-lang.org/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde @@ -90,14 +95,15 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - # FIXME: remove --skip test_tile_ when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/.gitignore b/.gitignore index 8f73d3eb972a0..1bbd3a9958073 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ perf.data.old *.events *.string* gimple* -*asm +*_asm res test-backend projects diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f81ecca445a8..c5c2a783b1ee7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,7 +112,7 @@ Full list of debugging options can be found in the [README](Readme.md#env-vars). ### Code Style Guidelines - Follow Rust standard coding conventions -- Ensure your code passes `rustfmt` and `clippy` +- Ensure your code passes `rustfmt` and `clippy` (you can run them with `y.sh fmt` and `y.sh clippy`) - Add comments explaining complex logic, especially in GCC interface code ## Additional Resources diff --git a/Cargo.lock b/Cargo.lock index a283ea4cb0b05..060509e51a6f9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.3.0" +version = "4.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" +checksum = "be5dafc4e649cb4a363e95a5960ef50b0c6f1b8e136ff8eb2e928b40353b5d8b" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.3.0" +version = "2.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" +checksum = "ab6a00a243aba2a45442bfd72b28d871137d4dac094f13de7f48cf9705112ffe" dependencies = [ "libc", ] @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "memchr" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", @@ -311,78 +311,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Cargo.toml b/Cargo.toml index 8956bd6948979..63a20d46b9d2f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.3.0", features = ["dlopen"] } +gccjit = { version = "4.0.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/Readme.md b/Readme.md index ce5ee1e4adee6..26783aa39cea8 100644 --- a/Readme.md +++ b/Readme.md @@ -136,19 +136,21 @@ $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run +$ CHANNEL=release $CG_GCCJIT_DIR/y.sh cargo run ``` -If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. ### Rustc If you want to run `rustc` directly, you can do so with: ```bash -$ ./y.sh rustc my_crate.rs +$ CHANNEL=release ./y.sh rustc my_crate.rs ``` +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. + You can do the same manually (although we don't recommend it): ```bash diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index e727561a2bfba..5e761149eb3bc 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "boml" diff --git a/build_system/asm-tester/Cargo.lock b/build_system/asm-tester/Cargo.lock new file mode 100644 index 0000000000000..9ad96acfda407 --- /dev/null +++ b/build_system/asm-tester/Cargo.lock @@ -0,0 +1,507 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "asm-tester" +version = "0.1.0" +dependencies = [ + "compiletest_rs", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compiletest_rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "windows-sys 0.59.0", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "miow" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tester" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/asm-tester/Cargo.toml b/build_system/asm-tester/Cargo.toml new file mode 100644 index 0000000000000..eeefe61bdc75b --- /dev/null +++ b/build_system/asm-tester/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "asm-tester" +version = "0.1.0" +edition = "2024" + +[dependencies] +compiletest_rs = "0.11.2" + +[[bin]] +name = "asm-tester" +path = "src/main.rs" + +[workspace] diff --git a/build_system/asm-tester/src/main.rs b/build_system/asm-tester/src/main.rs new file mode 100644 index 0000000000000..00ee4ac936520 --- /dev/null +++ b/build_system/asm-tester/src/main.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +#[derive(Default)] +struct Config { + llvm_filecheck: Option, + filters: Vec, + rustc_flags: Vec, +} + +impl Config { + fn new() -> Result { + // We skip the program's name. + let mut args = std::env::args().skip(1); + let mut config = Self::default(); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--llvm-filecheck" => { + config.llvm_filecheck = args.next().map(PathBuf::from); + } + "--filter" => { + if let Some(arg) = args.next() { + config.filters.push(arg); + } + } + "--" => { + config.rustc_flags.extend(&mut args); + // Nothing else to be read but the `break` makes it more clear. + break; + } + arg => return Err(format!("Unknown argument {arg:?}")), + } + } + if config.llvm_filecheck.is_none() { + Err("Missing `--llvm-filecheck` option".to_owned()) + } else if config.rustc_flags.is_empty() { + Err("Missing rustc flags (passed after `--`)".to_owned()) + } else { + Ok(config) + } + } +} + +fn main() { + let Config { llvm_filecheck, filters, rustc_flags } = match Config::new() { + Ok(c) => c, + Err(error) => { + eprintln!("{error}"); + std::process::exit(1); + } + }; + + let mut test_config = compiletest_rs::Config::default(); + + test_config.mode = compiletest_rs::common::Mode::Assembly; + test_config.src_base = PathBuf::from("tests/asm"); + test_config.llvm_filecheck = llvm_filecheck; + test_config.filters = filters; + test_config.strict_headers = true; + test_config.build_base = PathBuf::from("build/tests/asm"); + test_config.target_rustcflags = Some(rustc_flags.join(" ")); + test_config.link_deps(); + test_config.clean_rmeta(); + + compiletest_rs::run_tests(&test_config) +} diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 839c762fed742..e570a3f16c39e 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -227,7 +227,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false)?; + args.config_info.setup(&mut env, false, true)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index 43f01fdf35ecb..ec2092ee92ef5 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -74,7 +74,8 @@ fn clean_ui_tests() -> Result<(), String> { let path = Path::new(crate::BUILD_DIR) .join("rust/build/x86_64-unknown-linux-gnu/test/") .join(directory); - run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; + // The directory might not exist, so ignore the error. + let _ = run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None); } Ok(()) } diff --git a/build_system/src/clippy.rs b/build_system/src/clippy.rs new file mode 100644 index 0000000000000..813d4b9141e1c --- /dev/null +++ b/build_system/src/clippy.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present}; + +fn show_usage() { + println!( + r#" +`clippy` command help: + + --help : Show this help"# + ); +} + +pub fn run() -> Result<(), String> { + // We skip binary name and the `info` command. + let args = std::env::args().skip(2); + #[allow(clippy::never_loop)] + for arg in args { + match arg.as_str() { + "--help" => { + show_usage(); + return Ok(()); + } + _ => return Err(format!("Unknown option {arg}")), + } + } + + run_tool_and_install_it_if_not_present(&[ + &"cargo", + &"clippy", + &"--all-targets", + &"--", + &"-D", + &"warnings", + ])?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--no-default-features", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--manifest-path", + &"build_system/Cargo.toml", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + Ok(()) +} diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8eb6d8f019e1c..fd78f691d1657 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -314,6 +314,7 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, + generate_out_dir: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -444,12 +445,12 @@ impl ConfigInfo { self.rustc_command = vec![rustc]; self.rustc_command.extend_from_slice(&rustflags); - self.rustc_command.extend_from_slice(&[ - "-L".to_string(), - format!("crate={}", self.cargo_target_dir), - "--out-dir".to_string(), - self.cargo_target_dir.clone(), - ]); + self.rustc_command + .extend_from_slice(&["-L".to_string(), format!("crate={}", self.cargo_target_dir)]); + if generate_out_dir { + self.rustc_command + .extend_from_slice(&["--out-dir".to_string(), self.cargo_target_dir.clone()]); + } if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index 91535f217e351..dc1ca1d3e82ae 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{run_command_with_output, walk_dir}; +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present, walk_dir}; fn show_usage() { println!( @@ -31,8 +31,9 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - run_command_with_output(cmd, Some(Path::new(".")))?; + run_tool_and_install_it_if_not_present(cmd)?; run_command_with_output(cmd, Some(Path::new("build_system")))?; + run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; run_rustfmt_recursively("tests/run", check) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index ae975c94fff25..83f07a758d659 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -3,6 +3,7 @@ use std::{env, process}; mod abi_test; mod build; mod clean; +mod clippy; mod clone_gcc; mod config; mod fmt; @@ -12,6 +13,7 @@ mod prepare; mod rust_tools; mod rustc_info; mod test; +mod todo; mod utils; const BUILD_DIR: &str = "build"; @@ -24,43 +26,67 @@ macro_rules! arg_error { }}; } -fn usage() { - println!( - "\ +macro_rules! commands_decl { + ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { + enum Command { + $($variant),+ + } + + impl<'a> From> for Command { + fn from(arg: Option<&'a str>) -> Self { + match arg { + $(Some($doc_name) => Self::$variant,)+ + Some("--help") => { + usage(); + process::exit(0); + } + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + } + } + } + + fn usage() { + println!("\ rustc_codegen_gcc build system Usage: build_system [command] [options] Options: - --help : Displays this help message. + --help : Displays this help message. + +Commands:", + ); + let mut commands = vec![$(($doc_name, $doc),)+]; + let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); -Commands: - cargo : Executes a cargo command. - rustc : Compiles the program using the GCC compiler. - clean : Cleans the build directory, removing all compiled files and artifacts. - prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. - test : Runs tests for the project. - info : Displays information about the build environment and project configuration. - clone-gcc : Clones the GCC compiler from a specified source. - fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" - ); + commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); + for (name, doc) in commands { + let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::(); + eprintln!(" {name}{spacing}: {doc}."); + } + } + } } -pub enum Command { - Cargo, - Clean, - CloneGcc, - Prepare, - Build, - Rustc, - Test, - Info, - Fmt, - Fuzz, - AbiTest, +commands_decl! { + Cargo: "cargo" => "Executes a cargo command", + Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", + Clippy: "clippy" => "Runs clippy", + CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", + Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", + Build: "build" => "Compiles the project", + Rustc: "rustc" => "Compiles the program using the GCC compiler", + Test: "test" => "Runs tests for the project", + Info: "info" => "Displays information about the build environment and project configuration", + Fmt: "fmt" => "Runs rustfmt", + Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", + AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", + CheckTodo: "check-todo" => "Checks todo in the project", } fn main() { @@ -70,31 +96,7 @@ fn main() { } } - let command = match env::args().nth(1).as_deref() { - Some("cargo") => Command::Cargo, - Some("rustc") => Command::Rustc, - Some("clean") => Command::Clean, - Some("prepare") => Command::Prepare, - Some("build") => Command::Build, - Some("test") => Command::Test, - Some("info") => Command::Info, - Some("clone-gcc") => Command::CloneGcc, - Some("abi-test") => Command::AbiTest, - Some("fmt") => Command::Fmt, - Some("fuzz") => Command::Fuzz, - Some("--help") => { - usage(); - process::exit(0); - } - Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), - Some(command) => arg_error!("Unknown command {}", command), - None => { - usage(); - process::exit(0); - } - }; - - if let Err(e) = match command { + if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { Command::Cargo => rust_tools::run_cargo(), Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), @@ -106,6 +108,8 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), + Command::Clippy => clippy::run(), + Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs index b1faa27acc4a2..1b50f11c3d324 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -72,7 +72,7 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; + config.setup(&mut env, false, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 2475a3a6a7155..6cc2282c8022f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -9,8 +9,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, - split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, + run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, }; type Env = HashMap; @@ -28,8 +28,10 @@ fn get_runners() -> Runners { ("Run failing ui pattern tests", test_failing_ui_pattern_tests), ); runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); + runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); + runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); runners.insert("--std-tests", ("Run std tests", std_tests)); @@ -42,8 +44,10 @@ fn get_runners() -> Runners { ); runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); + runners.insert("--gcc-asm-tests", ("Run cg_gcc asm tests", test_asm)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); + runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); runners } @@ -505,6 +509,26 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn get_llvm_filecheck(env: &Env) -> Result { + match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14 || \ + which FileCheck", + ], + None, + Some(env), + ) { + Ok(cmd) => Ok(String::from_utf8_lossy(&cmd.stdout).trim().to_string()), + Err(_) => Err("Failed to retrieve LLVM FileCheck, ignoring...".to_owned()), + } +} + fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", @@ -548,23 +572,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let rustc = rustc.trim().to_owned(); if rustc.is_empty() { Err("`rustc` path is empty".to_string()) } else { Ok(rustc) } })?; - let llvm_filecheck = match run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ - which FileCheck-11 || \ - which FileCheck-12 || \ - which FileCheck-13 || \ - which FileCheck-14 || \ - which FileCheck", - ], - rust_dir, - Some(env), - ) { - Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), - Err(_) => { - eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); + let llvm_filecheck = match get_llvm_filecheck(env) { + Ok(l) => l, + Err(error) => { + eprintln!("{error}"); // FIXME: the test tests/run-make/no-builtins-attribute will fail if we cannot find // FileCheck. String::new() @@ -634,7 +645,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"--set", &"build.compiletest-allow-stage0=true", - &"tests/assembly-llvm/asm", + &"tests/assembly-gcc/asm", &"--compiletest-rustc-args", &rustc_args, ], @@ -764,6 +775,39 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { + println!("[TEST] stdarch"); + let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); + let mut env = env.clone(); + + // `config.setup` already baked `CG_RUSTFLAGS` into `RUSTFLAGS`, so append the lint-allow to + // `RUSTFLAGS` directly (which `run_cargo_command` also propagates to `RUSTDOCFLAGS`). + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert( + "RUSTFLAGS".to_string(), + format!("{rustflags} -Ainternal_features").trim().to_owned(), + ); + env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); + + let mut command: Vec<&dyn AsRef> = + vec![&"test", &"--manifest-path", &manifest_path, &"--"]; + for test_name in &args.test_args { + command.push(test_name); + } + run_cargo_command(&command, None, &env, args)?; + Ok(()) +} + +fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] alloc"); + let path = get_sysroot_dir().join("sysroot_src/library/alloctests"); + let _ = remove_dir_all(path.join("target")); + // FIXME(antoyo): run in release mode when we fix the failures. + run_cargo_command(&[&"test"], Some(&path), env, args)?; + Ok(()) +} + fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); @@ -908,7 +952,6 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< "//@ known-bug", "-Cllvm-args", "//~", - "thread", ] .iter() .any(|check| line.contains(check)) @@ -985,21 +1028,6 @@ where true, )?; } else { - walk_dir( - rust_path.join("tests/ui"), - &mut |dir| { - let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); - if ["abi", "extern", "proc-macro", "threads-sendsync"].contains(&dir_name) { - remove_dir_all(dir).map_err(|error| { - format!("Failed to remove folder `{}`: {:?}", dir.display(), error) - })?; - } - Ok(()) - }, - &mut |_| Ok(()), - false, - )?; - // These two functions are used to remove files that are known to not be working currently // with the GCC backend to reduce noise. fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { @@ -1196,6 +1224,46 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String ) } +fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { + let mut env = env.clone(); + let rust_path = setup_rustc(&mut env, args)?; + + let extra = + if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + + let rustc_args = format!( + "{test_flags} -Zcodegen-backend={backend} --sysroot {sysroot}{extra}", + test_flags = env.get("TEST_FLAGS").unwrap_or(&String::new()), + backend = args.config_info.cg_backend_path, + sysroot = args.config_info.sysroot_path, + extra = extra, + ); + + env.get_mut("RUSTFLAGS").unwrap().clear(); + + let mut command: Vec<&dyn AsRef> = vec![ + &"./x.py", + &"test", + &"--run", + &"always", + &"--stage", + &"0", + &"--set", + &"build.compiletest-allow-stage0=true", + &"--compiletest-rustc-args", + &rustc_args, + &"--bypass-ignore-backends", + &"--force-rerun", + ]; + + for test_name in &args.test_args { + command.push(test_name); + } + + run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; + Ok(()) +} + fn retain_files_callback<'a>( file_path: &'a str, test_type: &'a str, @@ -1297,6 +1365,60 @@ fn remove_files_callback<'a>( } } +fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { + fn is_path_time_more_recent(ref_time: std::time::SystemTime, path: &str) -> bool { + std::fs::metadata(path) + .and_then(|metadata| metadata.modified()) + .is_ok_and(|time| ref_time < time) + } + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] cg_gcc assembly"); + let llvm_filecheck = get_llvm_filecheck(env)?; + + let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); + + // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. + let binary_file_path = "build_system/asm-tester/target/debug/asm-tester"; + let mut need_recompilation = true; + if let Ok(metadata) = std::fs::metadata(binary_file_path) + && let Ok(ref_time) = metadata.modified() + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.toml") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.lock") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/src/main.rs") + { + need_recompilation = false; + } + + if need_recompilation { + let build_asm_args: Vec<&dyn AsRef> = vec![ + &"cargo", + &"build", + &"--manifest-path", + &"build_system/asm-tester/Cargo.toml", + &"--target-dir", + &target_dir, + &"--", + ]; + run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(env))?; + } + + let mut test_asm_args: Vec<&dyn AsRef> = vec![ + &"build_system/asm-tester/target/debug/asm-tester", + &"--llvm-filecheck", + &llvm_filecheck, + ]; + for test_arg in &args.test_args { + test_asm_args.push(&"--filter"); + test_asm_args.push(test_arg); + } + test_asm_args.push(&"--"); + for arg in args.config_info.rustc_command_vec().into_iter().skip(1) { + test_asm_args.push(arg); + } + run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(env)) +} + fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; @@ -1308,6 +1430,7 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { cargo_tests(env, args)?; no_builtins_tests(env, args)?; test_rustc(env, args)?; + test_asm(env, args)?; Ok(()) } @@ -1329,7 +1452,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc)?; + args.config_info.setup(&mut env, args.use_system_gcc, true)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/todo.rs b/build_system/src/todo.rs new file mode 100644 index 0000000000000..5b89410844788 --- /dev/null +++ b/build_system/src/todo.rs @@ -0,0 +1,72 @@ +use std::ffi::OsStr; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +const EXTENSIONS: &[&str] = + &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; + +fn has_supported_extension(path: &Path) -> bool { + path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) +} + +fn list_tracked_files() -> Result, String> { + let output = Command::new("git") + .args(["ls-files", "-z"]) + .output() + .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("`git ls-files` failed: {stderr}")); + } + + let mut files = Vec::new(); + for entry in output.stdout.split(|b| *b == 0) { + if entry.is_empty() { + continue; + } + let path = std::str::from_utf8(entry).unwrap(); + files.push(PathBuf::from(path)); + } + + Ok(files) +} + +pub(crate) fn run() -> Result<(), String> { + let files = list_tracked_files()?; + let mut error_count = 0; + // Avoid embedding the task marker in source so greps only find real occurrences. + let todo_marker = "todo".to_ascii_uppercase(); + + for file in files { + if !has_supported_extension(&file) { + continue; + } + + let file_handle = + File::open(&file).map_err(|e| format!("Failed to open {}: {e}", file.display()))?; + let reader = BufReader::new(file_handle); + + for (i, line) in reader.lines().enumerate() { + let line = line.map_err(|e| format!("Failed to read {}: {e}", file.display()))?; + let trimmed = line.trim(); + if trimmed.contains(&todo_marker) { + eprintln!( + "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", + file.display(), + i + 1, + todo_marker + ); + error_count += 1; + } + } + } + + if error_count == 0 { + return Ok(()); + } + + Err(format!("found {} {}(s)", error_count, todo_marker)) +} diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 112322f8688c1..4c67156a85fb2 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; +use std::io::{BufReader, Read}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus, Output}; +use std::process::{Command, ExitStatus, Output, Stdio}; fn exec_command( input: &[&dyn AsRef], @@ -47,7 +48,7 @@ pub(crate) fn get_command_inner( command } -fn check_exit_status( +pub(crate) fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, @@ -115,6 +116,30 @@ pub fn run_command_with_output( check_exit_status(input, cwd, exit_status, None, true) } +pub fn run_command_with_output_and_get_it( + input: &[&dyn AsRef], + cwd: Option<&Path>, +) -> Result<(ExitStatus, String), String> { + let mut child = get_command_inner(input, cwd, None) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| command_error(input, &cwd, e))?; + + let stderr = child.stderr.take().expect("Failed to capture stderr"); + let mut captured = String::new(); + BufReader::new(stderr).read_to_string(&mut captured).expect("failed to read stderr"); + + let status = child.wait().map_err(|e| command_error(input, &cwd, e))?; + #[cfg(unix)] + { + if let Some(signal) = status.signal() { + // In case the signal didn't kill the current process. + return Err(command_error(input, &cwd, format!("Process received signal {signal}"))); + } + } + Ok((status, captured)) +} + pub fn run_command_with_output_and_env( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -124,7 +149,6 @@ pub fn run_command_with_output_and_env( check_exit_status(input, cwd, exit_status, None, true) } -#[cfg(not(unix))] pub fn run_command_with_output_and_env_no_err( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -419,6 +443,34 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } +pub fn run_tool_and_install_it_if_not_present(cmd: &[&dyn AsRef]) -> Result<(), String> { + let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; + if exit_status.success() { + return Ok(()); + } + let mut iter = stderr.split('\n'); + if let Some(line) = iter.next() + && line.contains("is not installed for the toolchain") + && let Some(line) = iter.next() + && line.contains("run `rustup component add") + && let Some(cmd) = line.split('`').nth(1) + && let Some(tool_name) = cmd.rsplit(' ').next() + { + println!("`{tool_name}` is not installed for this toolchain, installing it..."); + // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but + // as long as it works... + let cmd = cmd.split(' ').collect::>(); + let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); + run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; + } else { + // If the component is installed, then it's something else. In this case we fail like we + // should have and let the user handles the error. + return check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true); + } + // We retry the command... + run_command_with_output(cmd, Some(Path::new("."))) +} + #[cfg(test)] mod tests { use super::*; diff --git a/doc/subtree.md b/doc/subtree.md index a81b6c9c74bdd..fcac399e46542 100644 --- a/doc/subtree.md +++ b/doc/subtree.md @@ -1,7 +1,7 @@ # git subtree sync `rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be -sync from time to time to ensure changes that happened on their side are also +synced from time to time to ensure changes that happened on their side are also included on our side. ### How to install a forked git-subtree @@ -41,6 +41,8 @@ cd ../rust git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +# Don't forget to update the `gcc` submodule to the same version as the +# one in `rustc_codegen_gcc/libgccjit.version`. git push # Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. diff --git a/libgccjit.version b/libgccjit.version index 5eef70260466f..7c141c20c4d3d 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 +dfbee712e611693596ffec1de22177089c537491 diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch deleted file mode 100644 index 3a8c37a8b8d9a..0000000000000 --- a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 190e26c9274b3c93a9ee3516b395590e6bd9213b Mon Sep 17 00:00:00 2001 -From: None -Date: Sun, 3 Aug 2025 19:54:56 -0400 -Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch - ---- - library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - create mode 100644 library/stdarch/Cargo.toml - -diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml -new file mode 100644 -index 0000000..bd6725c ---- /dev/null -+++ b/library/stdarch/Cargo.toml -@@ -0,0 +1,20 @@ -+[workspace] -+resolver = "1" -+members = [ -+ "crates/*", -+ #"examples/" -+] -+exclude = [ -+ "crates/wasm-assert-instr-tests", -+ "rust_programs", -+] -+ -+[profile.release] -+debug = true -+opt-level = 3 -+incremental = true -+ -+[profile.bench] -+debug = 1 -+opt-level = 3 -+incremental = true --- -2.50.1 - diff --git a/rust-toolchain b/rust-toolchain index 56fcfdff1c719..104992b5da46b 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-04-29" +channel = "nightly-2026-07-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/abi.rs b/src/abi.rs index 1b7bb8c907735..45fc5e3c4f619 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -146,12 +146,23 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } + // There are a few others `ArgAttribute` variants" + // + // * ArgAttribute::ReadOnly: `access(read_only())`, but it's only used for emitting + // warning, not for optimization. + // * ArgAttribute::NoUndef: No equivalent in GCC + // * ArgAttribute::Writable: `access(read_write())` or `access(write_only())`, but it's + // only used for emitting warning, not for optimization. + // * ArgAttribute::NoFree: No equivalent in GCC ty }; #[cfg(not(feature = "master"))] let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - for arg in self.args.iter() { + for (source_arg_index, arg) in self.args.iter().enumerate() { + #[cfg(not(feature = "master"))] + let _ = source_arg_index; + let arg_ty = match arg.mode { PassMode::Ignore => continue, PassMode::Pair(a, b) => { @@ -177,9 +188,31 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_attrs(ty, &cast.attrs, argument_tys.len()) } PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { - // This is a "byval" argument, so we don't apply the `restrict` attribute on it. - on_stack_param_indices.insert(argument_tys.len()); - arg.layout.gcc_type(cx) + let x86_interrupt_first_arg = { + #[cfg(feature = "master")] + { + source_arg_index == 0 + && matches!(self.conv, CanonAbi::Interrupt(InterruptKind::X86)) + } + #[cfg(not(feature = "master"))] + { + false + } + }; + + if x86_interrupt_first_arg { + // Rust lowers the first `x86-interrupt` argument as a byval stack slot. + // LLVM represents that as a pointer parameter with `byval`; GCC's + // interrupt attribute likewise requires a pointer-shaped first parameter. + // Do not add this parameter to `on_stack_param_indices`: that set is only + // needed when GCC represents a byval argument as a value parameter, while + // this parameter is already pointer-shaped. + cx.type_ptr_to(arg.layout.gcc_type(cx)) + } else { + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + on_stack_param_indices.insert(argument_tys.len()); + arg.layout.gcc_type(cx) + } } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) diff --git a/src/asm.rs b/src/asm.rs index ee0cef350b42f..a1d227157314b 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -298,7 +298,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { out_place, }); - if !readwrite { + if readwrite { + self.llbb().add_assignment(None, tmp_var, in_value.immediate()); + } else { let out_gcc_idx = outputs.len() - 1; let constraint = Cow::Owned(out_gcc_idx.to_string()); @@ -364,7 +366,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = value.layout.gcc_type(self.cx); let reg_var = self.current_func().new_local(None, ty, "input_register"); reg_var.set_register_name(reg_name); - self.llbb().add_assignment(None, reg_var, value.immediate()); + // FIXME: We should remove this when switching to "untyped" pointers + let value = value.immediate(); + let value = if value.get_type() != ty { + self.context.new_cast(None, value, ty) + } else { + value + }; + self.llbb().add_assignment(None, reg_var, value); inputs.push(AsmInOperand { constraint: "r".into(), @@ -603,6 +612,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } + if !options.contains(InlineAsmOptions::NORETURN) + && let Some(dest) = dest + { + self.switch_to_block(dest); + } + // Write results to outputs. // // We need to do this because: diff --git a/src/attributes.rs b/src/attributes.rs index ce1877b308e94..95d12480efa69 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,6 +2,8 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] +use rustc_abi::{CanonAbi, InterruptKind}; +#[cfg(feature = "master")] use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InstructionSetAttr; #[cfg(feature = "master")] @@ -9,6 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] use rustc_middle::mir::TerminatorKind; use rustc_middle::ty; +use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -82,12 +85,23 @@ fn inline_attr<'gcc, 'tcx>( } } +#[cfg(feature = "master")] +fn is_x86_interrupt<'tcx>(fn_abi: Option<&FnAbi<'tcx, ty::Ty<'tcx>>>) -> bool { + matches!( + fn_abi, + Some(fn_abi) if matches!(fn_abi.conv, CanonAbi::Interrupt(InterruptKind::X86)) + ) +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, #[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, + #[cfg_attr(not(feature = "master"), expect(unused_variables))] fn_abi: Option< + &FnAbi<'tcx, ty::Ty<'tcx>>, + >, ) { let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def); @@ -120,6 +134,11 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } + #[cfg(feature = "master")] + let x86_interrupt = is_x86_interrupt(fn_abi); + #[cfg(not(feature = "master"))] + let x86_interrupt = false; + let mut function_features = codegen_fn_attrs .target_features .iter() @@ -135,6 +154,13 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // Check if GCC requires the same. let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); function_features.extend(&mut global_features); + if x86_interrupt { + // GCC does not preserve SSE, MMX, or x87 state in interrupt handlers and rejects + // them whenever those instruction sets are enabled, even if the handler does not + // emit such instructions. Restrict the function to general registers so the + // interrupt attribute works with the default x86_64 target features. + function_features.push("general-regs-only"); + } let target_features = function_features .iter() .filter_map(|feature| { diff --git a/src/back/lto.rs b/src/back/lto.rs index 98f9abdb05c4c..baf1fda02e258 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -20,6 +20,7 @@ use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use gccjit::OutputKind; use object::read::archive::ArchiveFile; @@ -29,14 +30,15 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter} use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; +use rustc_session::Session; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; use crate::diagnostics::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; +use crate::gcc_util::new_context; +use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; struct LtoData { // FIXME(antoyo): use symbols_below_threshold. @@ -102,8 +104,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -114,8 +116,8 @@ pub(crate) fn run_fat( /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( + sess, cgcx, - prof, dcx, modules, lto_data.upstream_modules, @@ -125,15 +127,15 @@ pub(crate) fn run_fat( } fn fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> CompiledModule { - let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = sess.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -183,17 +185,16 @@ fn fat_lto( // module and create a linker with it. let mut module: ModuleCodegen = match costliest_module { Some((_cost, i)) => in_memory.remove(i), - None => { - unimplemented!("Incremental"); - /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); - let (buffer, name) = serialized_modules.remove(0); - info!("no in-memory regular modules to choose from, parsing {:?}", name); - ModuleCodegen { - module_llvm: GccContext::parse(cgcx, &name, buffer.data(), dcx)?, - name: name.into_string().unwrap(), - kind: ModuleKind::Regular, - }*/ - } + None => ModuleCodegen::new_regular( + "lto_module".to_string(), + GccContext { + context: Arc::new(SyncContext::new(new_context(sess))), + relocation_model: sess.relocation_model(), + lto_supported: true, + lto_mode: LtoMode::None, + temp_dir: None, + }, + ), }; { info!("using {:?} as a base module", module.name); @@ -220,7 +221,8 @@ fn fat_lto( // We add the object files and save in should_combine_object_files that we should combine // them into a single object file when compiling later. for (bc_decoded, name) in serialized_modules { - let _timer = prof + let _timer = sess + .prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -258,7 +260,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - codegen(cgcx, prof, dcx, module, &cgcx.module_config) + codegen(cgcx, &sess.prof, dcx, module, &cgcx.module_config) } pub struct ModuleBuffer(PathBuf); diff --git a/src/back/write.rs b/src/back/write.rs index cf5514412f745..1f4fd8a314ad2 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -11,8 +11,8 @@ use rustc_log::tracing::debug; use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; -use crate::base::add_pic_option; use crate::diagnostics::CopyBitcode; +use crate::gcc_util::add_pic_option; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( @@ -60,9 +60,6 @@ pub(crate) fn codegen( let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { - // FIXME(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); - context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); context.add_command_line_option("-ffat-lto-objects"); diff --git a/src/base.rs b/src/base.rs index 7a25fc46fd3fc..041420e35d2b5 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,9 +1,7 @@ -use std::collections::HashSet; -use std::env; use std::sync::Arc; use std::time::Instant; -use gccjit::{CType, Context, FunctionType, GlobalKind}; +use gccjit::{CType, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; @@ -17,11 +15,11 @@ use rustc_session::config::DebugInfo; use rustc_span::Symbol; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; -use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context}; +use crate::gcc_util::new_context; +use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -101,41 +99,7 @@ pub fn compile_codegen_unit( ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(tcx); - - if tcx.sess.panic_strategy().unwinds() { - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); - } - - let disabled_features: HashSet<_> = tcx - .sess - .opts - .cg - .target_feature - .split(',') - .filter(|feature| feature.starts_with('-')) - .map(|string| &string[1..]) - .collect(); - - if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 { - // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for - // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. - // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. - context.add_command_line_option("-mavx"); - } - - for arg in &tcx.sess.opts.cg.llvm_args { - context.add_command_line_option(arg); - } - // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. - context.add_command_line_option("-fno-var-tracking-assignments"); - // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). - context.add_command_line_option("-fno-semantic-interposition"); - // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). - context.add_command_line_option("-fno-strict-aliasing"); - // NOTE: Rust relies on LLVM doing wrapping on overflow. - context.add_command_line_option("-fwrapv"); + let context = new_context(tcx.sess); // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from // replacing code patterns (like loops) with calls to builtins (like memset). @@ -148,64 +112,6 @@ pub fn compile_codegen_unit( context.add_command_line_option("-fno-tree-loop-distribute-patterns"); } - if let Some(model) = tcx.sess.code_model() { - use rustc_target::spec::CodeModel; - - context.add_command_line_option(match model { - CodeModel::Tiny => "-mcmodel=tiny", - CodeModel::Small => "-mcmodel=small", - CodeModel::Kernel => "-mcmodel=kernel", - CodeModel::Medium => "-mcmodel=medium", - CodeModel::Large => "-mcmodel=large", - }); - } - - add_pic_option(&context, tcx.sess.relocation_model()); - - let target_cpu = gcc_util::target_cpu(tcx.sess); - if target_cpu != "generic" { - context.add_command_line_option(format!("-march={}", target_cpu)); - } - - if tcx - .sess - .opts - .unstable_opts - .function_sections - .unwrap_or(tcx.sess.target.function_sections) - { - context.add_command_line_option("-ffunction-sections"); - context.add_command_line_option("-fdata-sections"); - } - - if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-vregs"); - } - if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-all"); - } - if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-tree-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-ipa-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { - context.set_dump_code_on_compile(true); - } - if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { - context.set_dump_initial_gimple(true); - } - if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { - context.set_dump_everything(true); - } - if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { - context.set_keep_intermediates(true); - } - if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { - context.add_driver_option("-v"); - } - // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); @@ -269,24 +175,3 @@ pub fn compile_codegen_unit( (module, cost) } - -pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { - match relocation_model { - rustc_target::spec::RelocModel::Static => { - context.add_command_line_option("-fno-pie"); - context.add_driver_option("-fno-pie"); - } - rustc_target::spec::RelocModel::Pic => { - context.add_command_line_option("-fPIC"); - // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // this module (compile_codegen_unit) requires add_command_line_option while the usage - // in the back::write module (codegen) requires add_driver_option. - context.add_driver_option("-fPIC"); - } - rustc_target::spec::RelocModel::Pie => { - context.add_command_line_option("-fPIE"); - context.add_driver_option("-fPIE"); - } - model => eprintln!("Unsupported relocation model: {:?}", model), - } -} diff --git a/src/builder.rs b/src/builder.rs index a407362638f10..4096679ba0959 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, - UnaryOp, + BinaryOp, Block, CType, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, + Type, UnaryOp, }; use rustc_abi as abi; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; @@ -36,7 +36,6 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; -use crate::diagnostics; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -85,7 +84,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size)); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); - let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); + let return_value = self.new_temp(func, self.location, previous_value.get_type()); self.llbb().add_assignment(self.location, previous_var, previous_value); self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue()); @@ -312,34 +311,59 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } + /// Shared implementation of `call` and `tail_call`. For tail call it is important that this + /// returns a bare call, and not the result assigned to a local, or the result of `add_eval`. + fn build_call( + &mut self, + typ: Type<'gcc>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + func: RValue<'gcc>, + args: &[RValue<'gcc>], + funclet: Option<&Funclet>, + must_tail: bool, + ) -> RValue<'gcc> { + // FIXME(antoyo): remove when having a proper API. + let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; + let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // FIXME(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); + self.function_call(func, args, funclet, must_tail) + } else { + // If it's a not function that was defined, it's a function pointer. + self.function_ptr_call(typ, fn_abi, func, args, funclet, must_tail) + }; + if let Some(_fn_abi) = fn_abi { + // FIXME(bjorn3): Apply function attributes + } + call + } + pub fn function_call( &mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let args = self.check_call("call", func, args); + let call = self.cx.context.new_call(self.location, func, &args); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); let void_type = self.context.new_type::<()>(); let current_func = self.block.get_function(); if return_type != void_type { - let result = current_func.new_local( - self.location, - return_type, - format!("returnValue{}", self.next_value_counter()), - ); - self.block.add_assignment( - self.location, - result, - self.cx.context.new_call(self.location, func, &args), - ); + let result = self.new_temp(current_func, self.location, return_type); + self.block.add_assignment(self.location, result, call); result.to_rvalue() } else { - self.block - .add_eval(self.location, self.cx.context.new_call(self.location, func, &args)); + self.block.add_eval(self.location, call); // Return dummy value when not having return value. self.context.new_rvalue_zero(self.isize_type) } @@ -352,6 +376,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let func_ptr_type = { let func_ptr_type = func_ptr.get_type(); @@ -376,6 +401,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + let call = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = gcc_func.get_return_type(); @@ -392,11 +423,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { args_adjusted, orig_args, ); - let result = current_func.new_local( - self.location, - return_value.get_type(), - format!("ptrReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_value.get_type()); self.block.add_assignment(self.location, result, return_value); result.to_rvalue() } else { @@ -418,8 +445,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.location, self.cx.context.new_call_through_ptr(self.location, func_ptr, &args), ); - // Return dummy value when not having return value. - self.context.new_rvalue_zero(self.isize_type) + // Return dummy value when not having return value, unless the intrinsic adapter + // needs to synthesize a non-void LLVM-level result from out-parameters. + llvm::adjust_intrinsic_return_value( + self, + self.context.new_rvalue_zero(self.isize_type), + &func_name, + &args, + args_adjusted, + orig_args, + ) } } @@ -434,11 +469,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let return_type = self.context.new_type::(); let current_func = self.block.get_function(); // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects. - let result = current_func.new_local( - self.location, - return_type, - format!("overflowReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_type); self.block.add_assignment( self.location, result, @@ -570,6 +601,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { default_block: Block<'gcc>, cases: impl ExactSizeIterator)>, ) { + // A switch with no cases is equivalent to an unconditional jump to the + // default block. Such a `SwitchInt` (one with only an `otherwise` target) + // is normally simplified into a `goto`, but `-Z mir-preserve-ub` keeps it, + // so it can reach here with e.g. the `bool` discriminant produced by a + // range-pattern comparison. `gcc_jit_block_end_with_switch` rejects a + // discriminant that is not of integer type, so emit a plain jump instead + // of a (pointless) switch. + if cases.len() == 0 { + self.block.end_with_jump(self.location, default_block); + return; + } + let mut gcc_cases = vec![]; let typ = self.val_ty(value); // FIXME(FractalFir): This is a workaround for a libgccjit limitation. @@ -616,8 +659,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; - let return_value = - self.current_func().new_local(self.location, call.get_type(), "invokeResult"); + let return_value = self.new_temp(self.current_func(), self.location, call.get_type()); try_block.add_assignment(self.location, return_value, call); @@ -664,8 +706,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { - let return_value = - self.current_func().new_local(self.location, return_type, "unreachableReturn"); + let return_value = self.new_temp(self.current_func(), self.location, return_type); self.block.end_with_return(self.location, return_value) } } @@ -984,11 +1025,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. let deref = ptr.dereference(self.location).to_rvalue(); - let loaded_value = function.new_local( - self.location, - aligned_type, - format!("loadedValue{}", self.next_value_counter()), - ); + let loaded_value = self.new_temp(function, self.location, aligned_type); block.add_assignment(self.location, loaded_value, deref); loaded_value.to_rvalue() } @@ -1106,7 +1143,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var"); + let current = self.new_temp(self.llbb().get_function(), self.location, ptr_type); let current_val = current.to_rvalue(); self.assign(current, start); @@ -1471,7 +1508,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { mut else_val: RValue<'gcc>, ) -> RValue<'gcc> { let func = self.current_func(); - let variable = func.new_local(self.location, then_val.get_type(), "selectVar"); + let variable = self.new_temp(func, self.location, then_val.get_type()); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1493,8 +1530,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { variable.to_rvalue() } - fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { - unimplemented!(); + fn va_arg(&mut self, list: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + let va_list_type = self.context.new_c_type(CType::VaList); + let list = self.context.new_cast(self.location, list, va_list_type.make_pointer()); + self.context.new_va_arg(self.location, list, ty) } #[cfg(feature = "master")] @@ -1615,11 +1654,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self - .current_func() - .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") + .new_temp(self.current_func(), self.location, self.u8_type.make_pointer()) .to_rvalue(); - let value2 = - self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue(); + let value2 = self.new_temp(self.current_func(), self.location, self.i32_type).to_rvalue(); (value1, value2) } @@ -1687,7 +1724,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.current_func().new_local(self.location, self.bool_type, "success"); + let success_var = self.new_temp(self.current_func(), self.location, self.bool_type); self.llbb().add_assignment(self.location, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) @@ -1776,34 +1813,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { - // FIXME(antoyo): remove when having a proper API. - let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; - let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { - // FIXME(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet) - } else { - // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet) - }; - if let Some(_fn_abi) = fn_abi { - // FIXME(bjorn3): Apply function attributes - } - call + self.build_call(typ, fn_abi, func, args, funclet, false) } fn tail_call( &mut self, - _llty: Self::Type, + llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _llfn: Self::Value, - _args: &[Self::Value], - _funclet: Option<&Self::Funclet>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + llfn: Self::Value, + args: &[Self::Value], + funclet: Option<&Self::Funclet>, _instance: Option>, ) { - // FIXME: implement support for explicit tail calls like rustc_codegen_llvm. - self.tcx.dcx().emit_fatal(diagnostics::ExplicitTailCallsUnsupported); + // `emit_call` returns a bare call for here, it has not been assigned or passed to add_eval. + let call = self.build_call(llty, Some(fn_abi), llfn, args, funclet, true); + call.set_require_tail_call(true); + + let return_type = self.current_func().get_return_type(); + let void_type = self.context.new_type::<()>(); + + if return_type == void_type { + // For a void return the call is emitted as its own statement, immediately + // followed by a void return, so the tail call sits in tail position. + self.llbb().add_eval(self.location, call); + self.ret_void(); + } else { + self.ret(call) + } } fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { @@ -2388,11 +2425,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.bitcast_if_needed(res, result_type) } + /// Create a temporary variable. + /// + /// GCC will use more stack space with a local variable than with a temporary variable in debug mode, + /// so in order to avoid having the stack probe test fail in CI, we avoid creating local variables for temporaries. + pub fn new_temp( + &self, + function: Function<'gcc>, + location: Option>, + typ: Type<'gcc>, + ) -> LValue<'gcc> { + #[cfg(feature = "master")] + { + function.new_temp(location, typ) + } + #[cfg(not(feature = "master"))] + { + function.new_local(location, typ, format!("temp{}", self.next_value_counter())) + } + } + // GCC doesn't like deeply nested expressions. // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested // expressions and GCC will use much less RAM. fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> { - let var = self.current_func().new_local(self.location, value.get_type(), "opResult"); + let var = self.new_temp(self.current_func(), self.location, value.get_type()); self.llbb().add_assignment(self.location, var, value); var.to_rvalue() } diff --git a/src/callee.rs b/src/callee.rs index 00f095ed54371..d3f412180da55 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -70,7 +70,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(sym, fn_abi); - attributes::from_fn_attrs(cx, func, instance); + attributes::from_fn_attrs(cx, func, instance, Some(fn_abi)); #[cfg(feature = "master")] { diff --git a/src/common.rs b/src/common.rs index 6bd186f1121fc..d979c8b7ed094 100644 --- a/src/common.rs +++ b/src/common.rs @@ -143,9 +143,9 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); - let elements: Vec<_> = bytes - .as_chunks::<8>() - .0 + let (arrays, remainder) = bytes.as_chunks::<8>(); + debug_assert!(remainder.is_empty()); + let elements: Vec<_> = arrays .iter() .map(|&arr| { context.new_rvalue_from_long( @@ -170,9 +170,9 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); - let elements: Vec<_> = bytes - .as_chunks::<4>() - .0 + let (arrays, remainder) = bytes.as_chunks::<4>(); + debug_assert!(remainder.is_empty()); + let elements: Vec<_> = arrays .iter() .map(|&arr| { context.new_rvalue_from_int( diff --git a/src/consts.rs b/src/consts.rs index 42ff930968501..5ebdf91fe20b6 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,6 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute, Visibility}; -use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; +use gccjit::{FnAttribute, ToRValue, VarAttribute, Visibility}; +use gccjit::{Function, GlobalKind, LValue, RValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, @@ -160,29 +160,52 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { } // Wasm statics with custom link sections get special treatment as they - // go into custom sections of the wasm executable. - if self.tcx.sess.target.is_like_wasm { + // go into custom sections of the wasm executable. The exception to this + // is the `.init_array` section which are treated specially by the wasm linker. + if self.tcx.sess.target.is_like_wasm + && attrs + .link_section + .map(|link_section| !link_section.as_str().starts_with(".init_array")) + .unwrap_or(true) + { if let Some(_section) = attrs.link_section { unimplemented!(); } - } else { - // FIXME(antoyo): set link section. + } else if let Some(_section) = attrs.link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(_section.as_str())); } - if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) - || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - self.add_used_global(global.to_rvalue()); + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + self.add_used_global(global); + } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); + self.add_retained_global(global); } } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. - pub fn add_used_global(&mut self, _global: RValue<'gcc>) { - // FIXME(antoyo) + /// Need to have the `SHF_GNU_RETAIN` flag, so needs to use the `retain` attribute instead of + /// `used`. This is used by `#[used(linker)]`. + pub fn add_retained_global(&mut self, global: LValue<'gcc>) { + // We need to add the `used` C attribute in any case. + self.add_used_global(global); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Retain); + } + + /// This is used by `#[used(compiler)]` and `#[used]`. + pub fn add_used_global(&mut self, _global: LValue<'gcc>) { + #[cfg(feature = "master")] + _global.add_attribute(VarAttribute::Used); } + // No need to have the `SHF_GNU_RETAIN` flag, so `used` attribute is ok. #[cfg_attr(not(feature = "master"), expect(unused_variables))] pub fn add_used_function(&self, function: Function<'gcc>) { #[cfg(feature = "master")] diff --git a/src/declare.rs b/src/declare.rs index 4174eebcf7b02..9bf57fbf75bc0 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -1,12 +1,12 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue}; +use gccjit::{FnAttribute, ToRValue, VarAttribute}; use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::abi::{FnAbiGcc, FnAbiGccExt}; +use crate::abi::FnAbiGccExt; use crate::context::CodegenCx; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -24,6 +24,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } global @@ -73,6 +76,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); @@ -110,22 +116,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { - let FnAbiGcc { - return_type, - arguments_type, - is_c_variadic, - on_stack_param_indices, - #[cfg(feature = "master")] - fn_attributes, - } = fn_abi.gcc_type(self); + let fn_abi_gcc = fn_abi.gcc_type(self); #[cfg(feature = "master")] let conv = fn_abi.gcc_cconv(self); #[cfg(not(feature = "master"))] let conv = None; - let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); - self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); + let func = declare_raw_fn( + self, + name, + conv, + fn_abi_gcc.return_type, + &fn_abi_gcc.arguments_type, + fn_abi_gcc.is_c_variadic, + ); + self.on_stack_function_params.borrow_mut().insert(func, fn_abi_gcc.on_stack_param_indices); #[cfg(feature = "master")] - for fn_attr in fn_attributes { + for fn_attr in fn_abi_gcc.fn_attributes { func.add_attribute(fn_attr); } func diff --git a/src/diagnostics.rs b/src/diagnostics.rs index de633d3bdde79..67723ebd2f30b 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -20,10 +20,6 @@ pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } -#[derive(Diagnostic)] -#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] -pub(crate) struct ExplicitTailCallsUnsupported; - #[derive(Diagnostic)] #[diag("asm contains a NUL byte")] pub(crate) struct NulBytesInAsm { diff --git a/src/gcc_util.rs b/src/gcc_util.rs index a95b4da28eb63..4d7f2cdbb92ed 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,10 +1,14 @@ -#[cfg(feature = "master")] +use std::collections::HashSet; +use std::env; + use gccjit::Context; +#[cfg(feature = "master")] +use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; use rustc_session::config::NATIVE_CPU; -use rustc_target::spec::Arch; +use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector}; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -136,3 +140,147 @@ pub fn target_cpu(sess: &Session) -> &str { None => handle_native(sess.target.cpu.as_ref()), } } + +pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { + let context = Context::default(); + if matches!(sess.target.arch, Arch::X86 | Arch::X86_64) { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature = "master")] + { + context.set_special_chars_allowed_in_func_names("$.*"); + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!( + "rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + + if sess.panic_strategy().unwinds() { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } + + let disabled_features: HashSet<_> = sess + .opts + .cg + .target_feature + .split(',') + .filter(|feature| feature.starts_with('-')) + .map(|string| &string[1..]) + .collect(); + + if !disabled_features.contains("avx") && sess.target.arch == Arch::X86_64 { + // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for + // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. + // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. + context.add_command_line_option("-mavx"); + } + + for arg in &sess.opts.cg.llvm_args { + context.add_command_line_option(arg); + } + // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. + context.add_command_line_option("-fno-var-tracking-assignments"); + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). + context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); + // NOTE: Rust relies on LLVM doing wrapping on overflow. + context.add_command_line_option("-fwrapv"); + + if let Some(model) = sess.code_model() { + use rustc_target::spec::CodeModel; + + context.add_command_line_option(match model { + CodeModel::Tiny => "-mcmodel=tiny", + CodeModel::Small => "-mcmodel=small", + CodeModel::Kernel => "-mcmodel=kernel", + CodeModel::Medium => "-mcmodel=medium", + CodeModel::Large => "-mcmodel=large", + }); + } + + match sess.stack_protector() { + StackProtector::All => context.add_command_line_option("-fstack-protector-all"), + StackProtector::Strong => context.add_command_line_option("-fstack-protector-strong"), + StackProtector::Basic => context.add_command_line_option("-fstack-protector"), + StackProtector::None => (), + } + + match sess.target.stack_probes { + StackProbeType::None => (), + StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { + context.add_command_line_option("-fstack-clash-protection") + } + // FIXME(antoyo): We should define the stack probe symbol to be __rust_probestack, but it seems GCC cannot do that. + StackProbeType::Call => (), + }; + + add_pic_option(&context, sess.relocation_model()); + + let target_cpu = target_cpu(sess); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); + } + + if sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections) { + context.add_command_line_option("-ffunction-sections"); + context.add_command_line_option("-fdata-sections"); + } + + if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-vregs"); + } + if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-all"); + } + if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-tree-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-ipa-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { + context.set_dump_code_on_compile(true); + } + if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { + context.set_dump_initial_gimple(true); + } + if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { + context.set_dump_everything(true); + } + if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { + context.set_keep_intermediates(true); + } + if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { + context.add_driver_option("-v"); + } + + context +} + +pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { + match relocation_model { + rustc_target::spec::RelocModel::Static => { + context.add_command_line_option("-fno-pie"); + context.add_driver_option("-fno-pie"); + } + rustc_target::spec::RelocModel::Pic => { + context.add_command_line_option("-fPIC"); + // NOTE: we use both add_command_line_option and add_driver_option because the usage in + // base (compile_codegen_unit) requires add_command_line_option while the usage + // in the back::write module (codegen) requires add_driver_option. + context.add_driver_option("-fPIC"); + } + rustc_target::spec::RelocModel::Pie => { + context.add_command_line_option("-fPIE"); + context.add_driver_option("-fPIE"); + } + model => eprintln!("Unsupported relocation model: {:?}", model), + } +} diff --git a/src/int.rs b/src/int.rs index dfae4eceebe44..0c9a755694577 100644 --- a/src/int.rs +++ b/src/int.rs @@ -432,7 +432,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // This algorithm is based on compiler-rt's __cmpti2: // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 - let result = self.current_func().new_local(self.location, self.int_type, "icmp_result"); + let result = self.new_temp(self.current_func(), self.location, self.int_type); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); @@ -462,9 +462,15 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + let signed_type = native_int_type.to_signed(self.cx); + lhs_high = self.context.new_cast(self.location, lhs_high, signed_type); + rhs_high = self.context.new_cast(self.location, rhs_high, signed_type); + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } let condition = self.context.new_comparison( @@ -602,9 +608,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { rhs = self.context.new_cast(self.location, rhs, unsigned_type); } } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + if !a_type.is_vector() { + let signed_type = a_type.to_signed(self.cx); + lhs = self.context.new_cast(self.location, lhs, signed_type); + rhs = self.context.new_cast(self.location, rhs, signed_type); + } + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) } @@ -862,7 +876,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } - // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? + // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/1a99c2aa295bb2d507fa0e67a3b5eef64fba92a0/libm/src/math/support/int_traits.rs#L485 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 3c1698df6dec2..1856c2468616d 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "prefetch.ir" => "__builtin_arm_prefetch_ir", "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", @@ -53,6 +54,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "alignbyte" => "__builtin_amdgcn_alignbyte", "ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32", "ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32", + "asyncmark" => "__builtin_amdgcn_asyncmark", "buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1", "buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc", "buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol", @@ -270,6 +272,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fdot2c.f32.bf16" => "__builtin_amdgcn_fdot2c_f32_bf16", "flat.prefetch" => "__builtin_amdgcn_flat_prefetch", "fmul.legacy" => "__builtin_amdgcn_fmul_legacy", + "global.load.async.lds" => "__builtin_amdgcn_global_load_async_lds", "global.load.async.to.lds.b128" => { "__builtin_amdgcn_global_load_async_to_lds_b128" } @@ -361,11 +364,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4", "perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4", "perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4", - "permlane.bcast" => "__builtin_amdgcn_permlane_bcast", - "permlane.down" => "__builtin_amdgcn_permlane_down", "permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen", - "permlane.up" => "__builtin_amdgcn_permlane_up", - "permlane.xor" => "__builtin_amdgcn_permlane_xor", "permlane16.var" => "__builtin_amdgcn_permlane16_var", "permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16", @@ -375,6 +374,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "prng.b32" => "__builtin_amdgcn_prng_b32", "qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "queue.ptr" => "__builtin_amdgcn_queue_ptr", + "raw.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_raw_ptr_buffer_load_async_lds" + } "raw.ptr.buffer.load.lds" => "__builtin_amdgcn_raw_ptr_buffer_load_lds", "rcp.legacy" => "__builtin_amdgcn_rcp_legacy", "rsq.legacy" => "__builtin_amdgcn_rsq_legacy", @@ -386,6 +388,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", "s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", "s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", + "s.bitreplicate" => "__builtin_amdgcn_s_bitreplicate", "s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data", "s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier", "s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", @@ -412,6 +415,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.ttracedata" => "__builtin_amdgcn_s_ttracedata", "s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "s.wait.asynccnt" => "__builtin_amdgcn_s_wait_asynccnt", + "s.wait.event" => "__builtin_amdgcn_s_wait_event", "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", @@ -462,16 +466,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "smfmac.i32.16x16x64.i8" => "__builtin_amdgcn_smfmac_i32_16x16x64_i8", "smfmac.i32.32x32x32.i8" => "__builtin_amdgcn_smfmac_i32_32x32x32_i8", "smfmac.i32.32x32x64.i8" => "__builtin_amdgcn_smfmac_i32_32x32x64_i8", + "struct.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_struct_ptr_buffer_load_async_lds" + } "struct.ptr.buffer.load.lds" => "__builtin_amdgcn_struct_ptr_buffer_load_lds", "sudot4" => "__builtin_amdgcn_sudot4", "sudot8" => "__builtin_amdgcn_sudot8", "tensor.load.to.lds" => "__builtin_amdgcn_tensor_load_to_lds", - "tensor.load.to.lds.d2" => "__builtin_amdgcn_tensor_load_to_lds_d2", "tensor.store.from.lds" => "__builtin_amdgcn_tensor_store_from_lds", - "tensor.store.from.lds.d2" => "__builtin_amdgcn_tensor_store_from_lds_d2", "udot2" => "__builtin_amdgcn_udot2", "udot4" => "__builtin_amdgcn_udot4", "udot8" => "__builtin_amdgcn_udot8", + "wait.asyncmark" => "__builtin_amdgcn_wait_asyncmark", "wave.barrier" => "__builtin_amdgcn_wave_barrier", "wavefrontsize" => "__builtin_amdgcn_wavefrontsize", "workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", @@ -4844,7 +4850,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.ftz.sat.f16" => "__nvvm_add_rn_ftz_sat_f16", + "add.rn.ftz.sat.v2f16" => "__nvvm_add_rn_ftz_sat_v2f16", "add.rn.sat.f" => "__nvvm_add_rn_sat_f", + "add.rn.sat.f16" => "__nvvm_add_rn_sat_f16", + "add.rn.sat.v2f16" => "__nvvm_add_rn_sat_v2f16", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", @@ -5063,18 +5073,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", "fma.rn.f" => "__nvvm_fma_rn_f", - "fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", - "fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", - "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", - "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", - "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", - "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", @@ -5195,6 +5197,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "mul.rn.d" => "__nvvm_mul_rn_d", "mul.rn.f" => "__nvvm_mul_rn_f", "mul.rn.ftz.f" => "__nvvm_mul_rn_ftz_f", + "mul.rn.ftz.sat.f16" => "__nvvm_mul_rn_ftz_sat_f16", + "mul.rn.ftz.sat.v2f16" => "__nvvm_mul_rn_ftz_sat_v2f16", + "mul.rn.sat.f16" => "__nvvm_mul_rn_sat_f16", + "mul.rn.sat.v2f16" => "__nvvm_mul_rn_sat_v2f16", "mul.rp.d" => "__nvvm_mul_rp_d", "mul.rp.f" => "__nvvm_mul_rp_f", "mul.rp.ftz.f" => "__nvvm_mul_rp_ftz_f", @@ -5827,8 +5833,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vmuleuh" => "__builtin_altivec_vmuleuh", "altivec.vmuleuw" => "__builtin_altivec_vmuleuw", "altivec.vmulhsd" => "__builtin_altivec_vmulhsd", + "altivec.vmulhsh" => "__builtin_altivec_vmulhsh", "altivec.vmulhsw" => "__builtin_altivec_vmulhsw", "altivec.vmulhud" => "__builtin_altivec_vmulhud", + "altivec.vmulhuh" => "__builtin_altivec_vmulhuh", "altivec.vmulhuw" => "__builtin_altivec_vmulhuw", "altivec.vmulosb" => "__builtin_altivec_vmulosb", "altivec.vmulosd" => "__builtin_altivec_vmulosd", @@ -5912,22 +5920,45 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vsum4shs" => "__builtin_altivec_vsum4shs", "altivec.vsum4ubs" => "__builtin_altivec_vsum4ubs", "altivec.vsumsws" => "__builtin_altivec_vsumsws", + "altivec.vucmprhb" => "__builtin_altivec_vucmprhb", + "altivec.vucmprhh" => "__builtin_altivec_vucmprhh", + "altivec.vucmprhn" => "__builtin_altivec_vucmprhn", + "altivec.vucmprlb" => "__builtin_altivec_vucmprlb", + "altivec.vucmprlh" => "__builtin_altivec_vucmprlh", + "altivec.vucmprln" => "__builtin_altivec_vucmprln", "altivec.vupkhpx" => "__builtin_altivec_vupkhpx", "altivec.vupkhsb" => "__builtin_altivec_vupkhsb", "altivec.vupkhsh" => "__builtin_altivec_vupkhsh", + "altivec.vupkhsntob" => "__builtin_altivec_vupkhsntob", "altivec.vupkhsw" => "__builtin_altivec_vupkhsw", + "altivec.vupkint4tobf16" => "__builtin_altivec_vupkint4tobf16", + "altivec.vupkint4tofp32" => "__builtin_altivec_vupkint4tofp32", + "altivec.vupkint8tobf16" => "__builtin_altivec_vupkint8tobf16", + "altivec.vupkint8tofp32" => "__builtin_altivec_vupkint8tofp32", "altivec.vupklpx" => "__builtin_altivec_vupklpx", "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", + "altivec.vupklsntob" => "__builtin_altivec_vupklsntob", "altivec.vupklsw" => "__builtin_altivec_vupklsw", "amo.ldat" => "__builtin_amo_ldat", + "amo.ldat.cond" => "__builtin_amo_ldat_cond", + "amo.ldat.csne" => "__builtin_amo_ldat_csne", "amo.lwat" => "__builtin_amo_lwat", + "amo.lwat.cond" => "__builtin_amo_lwat_cond", + "amo.lwat.csne" => "__builtin_amo_lwat_csne", + "amo.stdat" => "__builtin_amo_stdat", + "amo.stwat" => "__builtin_amo_stwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", "bcdsetsign" => "__builtin_ppc_bcdsetsign", + "bcdshift" => "__builtin_ppc_bcdshift", + "bcdshiftround" => "__builtin_ppc_bcdshiftround", "bcdsub" => "__builtin_ppc_bcdsub", "bcdsub.p" => "__builtin_ppc_bcdsub_p", + "bcdtruncate" => "__builtin_ppc_bcdtruncate", + "bcdunsignedshift" => "__builtin_ppc_bcdunsignedshift", + "bcdunsignedtruncate" => "__builtin_ppc_bcdunsignedtruncate", "bpermd" => "__builtin_bpermd", "cbcdtd" => "__builtin_cbcdtd", "cbcdtdd" => "__builtin_ppc_cbcdtd", @@ -6126,6 +6157,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", + "xsaddaddsuqm" => "__builtin_xsaddaddsuqm", + "xsaddadduqm" => "__builtin_xsaddadduqm", + "xsaddsubsuqm" => "__builtin_xsaddsubsuqm", + "xsaddsubuqm" => "__builtin_xsaddsubuqm", + "xsmerge2t1uqm" => "__builtin_xsmerge2t1uqm", + "xsmerge2t2uqm" => "__builtin_xsmerge2t2uqm", + "xsmerge2t3uqm" => "__builtin_xsmerge2t3uqm", + "xsmerge3t1uqm" => "__builtin_xsmerge3t1uqm", + "xsrebase2t1uqm" => "__builtin_xsrebase2t1uqm", + "xsrebase2t2uqm" => "__builtin_xsrebase2t2uqm", + "xsrebase2t3uqm" => "__builtin_xsrebase2t3uqm", + "xsrebase2t4uqm" => "__builtin_xsrebase2t4uqm", + "xsrebase3t1uqm" => "__builtin_xsrebase3t1uqm", + "xsrebase3t2uqm" => "__builtin_xsrebase3t2uqm", + "xsrebase3t3uqm" => "__builtin_xsrebase3t3uqm", + "xxmulmul" => "__builtin_xxmulmul", + "xxmulmulhiadd" => "__builtin_xxmulmulhiadd", + "xxmulmulloadd" => "__builtin_xxmulmulloadd", + "xxssumudm" => "__builtin_xxssumudm", + "xxssumudmc" => "__builtin_xxssumudmc", + "xxssumudmcext" => "__builtin_xxssumudmcext", "zoned2packed" => "__builtin_ppc_zoned2packed", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } @@ -6388,13 +6440,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { // spv "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", + "subgroup.ballot" => "__builtin_spirv_subgroup_ballot", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { "__builtin_spirv_subgroup_local_invocation_id" } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", - "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -8661,10 +8713,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bmi.bextr.64" => "__builtin_ia32_bextr_u64", "bmi.bzhi.32" => "__builtin_ia32_bzhi_si", "bmi.bzhi.64" => "__builtin_ia32_bzhi_di", - "bmi.pdep.32" => "__builtin_ia32_pdep_si", - "bmi.pdep.64" => "__builtin_ia32_pdep_di", - "bmi.pext.32" => "__builtin_ia32_pext_si", - "bmi.pext.64" => "__builtin_ia32_pext_di", "cldemote" => "__builtin_ia32_cldemote", "clflushopt" => "__builtin_ia32_clflushopt", "clrssbsy" => "__builtin_ia32_clrssbsy", diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 41efe3e8209bf..6ad19d5af095e 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,5 +1,7 @@ use std::borrow::Cow; +#[cfg(feature = "master")] +use gccjit::TypeAttribute; use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::BuilderMethods; @@ -23,7 +25,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7], ); #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + encode_type.as_type().add_attribute(TypeAttribute::Packed); (encode_type.as_type(), field1, field2) } @@ -45,7 +47,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8], ); #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + encode_type.as_type().add_attribute(TypeAttribute::Packed); (encode_type.as_type(), field1, field2) } @@ -58,7 +60,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); #[cfg(feature = "master")] - typ.set_packed(); + typ.add_attribute(TypeAttribute::Packed); (typ, field1, field2) } @@ -81,7 +83,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); #[cfg(feature = "master")] - aes_output_type.as_type().set_packed(); + aes_output_type.as_type().add_attribute(TypeAttribute::Packed); (aes_output_type.as_type(), field1, field2) } @@ -478,6 +480,26 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(variable.get_address(None)); args = new_args.into(); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let old_args = args.to_vec(); + let mut new_args = vec![]; + let arg1_type = gcc_func.get_param_type(0); + let first_mask = + builder.current_func().new_local(None, arg1_type, "return_2intersect_arg1"); + let arg2_type = gcc_func.get_param_type(1); + let second_mask = + builder.current_func().new_local(None, arg2_type, "return_2intersect_arg2"); + new_args.push(first_mask.get_address(None)); + new_args.push(second_mask.get_address(None)); + new_args.push(old_args[0]); + new_args.push(old_args[1]); + args = new_args.into(); + } "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask" | "__builtin_ia32_vpermt2varqi128_mask" @@ -489,6 +511,23 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } + "__builtin_ia32_fpclassph128_mask" + | "__builtin_ia32_fpclassph256_mask" + | "__builtin_ia32_fpclassph512_mask" + | "__builtin_ia32_fpclasspd128_mask" + | "__builtin_ia32_fpclassps128_mask" + | "__builtin_ia32_fpclasspd256_mask" + | "__builtin_ia32_fpclassps256_mask" + | "__builtin_ia32_fpclasspd512_mask" + | "__builtin_ia32_fpclassps512_mask" + | "__builtin_ia32_vpshufbitqmb128_mask" + | "__builtin_ia32_vpshufbitqmb256_mask" + | "__builtin_ia32_vpshufbitqmb512_mask" => { + let new_args = args.to_vec(); + let arg3_type = gcc_func.get_param_type(2); + let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); + args = vec![new_args[0], new_args[1], minus_one].into(); + } "__builtin_ia32_xrstor" | "__builtin_ia32_xrstor64" | "__builtin_ia32_xsavec" @@ -840,7 +879,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( "__builtin_ia32_rdrand64_step" => { let random_number = args[0].dereference(None).to_rvalue(); let success_variable = - builder.current_func().new_local(None, return_value.get_type(), "success"); + builder.new_temp(builder.current_func(), None, return_value.get_type()); builder.llbb().add_assignment(None, success_variable, return_value); let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); @@ -854,6 +893,25 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( &[random_number, success_variable.to_rvalue()], ); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let first_mask = args[0].dereference(None).to_rvalue(); + let second_mask = args[1].dereference(None).to_rvalue(); + let field1 = builder.context.new_field(None, first_mask.get_type(), "first_mask"); + let field2 = builder.context.new_field(None, second_mask.get_type(), "second_mask"); + let struct_type = + builder.context.new_struct_type(None, "vp2intersect_result", &[field1, field2]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[first_mask, second_mask], + ); + } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); @@ -1182,6 +1240,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", "llvm.x86.avx512.mask.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", "llvm.x86.avx512.mask.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", + "llvm.x86.avx512.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", + "llvm.x86.avx512.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", + "llvm.x86.avx512.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", "llvm.x86.avx512.mask.ucmp.w.512" => "__builtin_ia32_ucmpw512_mask", "llvm.x86.avx512.mask.ucmp.w.256" => "__builtin_ia32_ucmpw256_mask", "llvm.x86.avx512.mask.ucmp.w.128" => "__builtin_ia32_ucmpw128_mask", @@ -1339,11 +1400,20 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf", + "llvm.x86.vcvtneps2bf16128" => "__builtin_ia32_cvtneps2bf16_v4sf", + "llvm.x86.vcvtneps2bf16256" => "__builtin_ia32_cvtneps2bf16_v8sf", + "llvm.x86.avx512bf16.mask.cvtneps2bf16.128" => "__builtin_ia32_cvtneps2bf16_v4sf_mask", "llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf", "llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf", "llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf", "llvm.x86.avx512bf16.dpbf16ps.256" => "__builtin_ia32_dpbf16ps_v8sf", "llvm.x86.avx512bf16.dpbf16ps.512" => "__builtin_ia32_dpbf16ps_v16sf", + "llvm.x86.avx512.vp2intersect.d.128" => "__builtin_ia32_2intersectd128", + "llvm.x86.avx512.vp2intersect.q.128" => "__builtin_ia32_2intersectq128", + "llvm.x86.avx512.vp2intersect.d.256" => "__builtin_ia32_2intersectd256", + "llvm.x86.avx512.vp2intersect.q.256" => "__builtin_ia32_2intersectq256", + "llvm.x86.avx512.vp2intersect.d.512" => "__builtin_ia32_2intersectd512", + "llvm.x86.avx512.vp2intersect.q.512" => "__builtin_ia32_2intersectq512", "llvm.x86.pclmulqdq.512" => "__builtin_ia32_vpclmulqdq_v8di", "llvm.x86.pclmulqdq.256" => "__builtin_ia32_vpclmulqdq_v4di", "llvm.x86.avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", @@ -1577,38 +1647,79 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", + "llvm.x86.avx512fp16.fpclass.ph.128" => "__builtin_ia32_fpclassph128_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.128" => "__builtin_ia32_cmpph128_mask", + "llvm.x86.avx512fp16.fpclass.ph.256" => "__builtin_ia32_fpclassph256_mask", + "llvm.x86.avx512fp16.fpclass.ph.512" => "__builtin_ia32_fpclassph512_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.256" => "__builtin_ia32_cmpph256_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.512" => "__builtin_ia32_cmpph512_mask_round", + "llvm.x86.avx512.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "llvm.x86.avx512.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "llvm.x86.avx512.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.sttilecfg" => "__builtin_trap", "llvm.x86.tileloadd64" => "__builtin_trap", + "llvm.x86.tileloadd64.internal" => "__builtin_trap", "llvm.x86.tilerelease" => "__builtin_trap", "llvm.x86.tilestored64" => "__builtin_trap", + "llvm.x86.tilestored64.internal" => "__builtin_trap", "llvm.x86.tileloaddrs64" => "__builtin_trap", + "llvm.x86.tileloaddrs64.internal" => "__builtin_trap", "llvm.x86.tileloaddt164" => "__builtin_trap", + "llvm.x86.tileloaddt164.internal" => "__builtin_trap", "llvm.x86.tileloaddrst164" => "__builtin_trap", + "llvm.x86.tileloaddrst164.internal" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", + "llvm.x86.tilezero.internal" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", + "llvm.x86.tilemovrow.internal" => "__builtin_trap", "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", + "llvm.x86.tdpbhf8ps.internal" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", + "llvm.x86.tdphbf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", + "llvm.x86.tdpbf8ps.internal" => "__builtin_trap", "llvm.x86.tdphf8ps" => "__builtin_trap", + "llvm.x86.tdphf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf16ps" => "__builtin_trap", + "llvm.x86.tdpbf16ps.internal" => "__builtin_trap", "llvm.x86.tdpbssd" => "__builtin_trap", + "llvm.x86.tdpbssd.internal" => "__builtin_trap", "llvm.x86.tdpbsud" => "__builtin_trap", + "llvm.x86.tdpbsud.internal" => "__builtin_trap", "llvm.x86.tdpbusd" => "__builtin_trap", + "llvm.x86.tdpbusd.internal" => "__builtin_trap", "llvm.x86.tdpbuud" => "__builtin_trap", + "llvm.x86.tdpbuud.internal" => "__builtin_trap", "llvm.x86.tdpfp16ps" => "__builtin_trap", + "llvm.x86.tdpfp16ps.internal" => "__builtin_trap", "llvm.x86.tmmultf32ps" => "__builtin_trap", + "llvm.x86.tmmultf32ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phh" => "__builtin_trap", + "llvm.x86.tcvtrowps2phh.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", + "llvm.x86.tcvtrowps2phl.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", + "llvm.x86.tcvtrowd2ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => map_arch_intrinsic(name), diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 09ad3254e5714..bbf5acf702e21 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -95,7 +95,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", - sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -118,12 +117,7 @@ fn get_simple_function_f128<'gcc, 'tcx>( let func_name = match name { sym::ceilf128 => "ceilf128", sym::fabs => "fabsf128", - sym::expf128 => "expf128", - sym::exp2f128 => "exp2f128", sym::floorf128 => "floorf128", - sym::logf128 => "logf128", - sym::log2f128 => "log2f128", - sym::log10f128 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", @@ -167,15 +161,8 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", - sym::expf16 => "expf", - sym::exp2f16 => "exp2f", - sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", - sym::logf16 => "logf", - sym::log2f16 => "log2f", - sym::log10f16 => "log10f", - sym::powf16 => "__builtin_powf", sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", sym::sqrtf16 => "__builtin_sqrtf", @@ -210,14 +197,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let simple = get_simple_intrinsic(self, name); let value = match name { - _ if simple.is_some() => { - let func = simple.expect("simple intrinsic function"); - self.cx.context.new_call( - self.location, - func, - &args.iter().map(|arg| arg.immediate()).collect::>(), - ) - } + _ if let Some(func) = simple => self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ), // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { @@ -246,14 +230,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 - | sym::expf16 - | sym::exp2f16 | sym::floorf16 | sym::fmaf16 - | sym::logf16 - | sym::log2f16 - | sym::log10f16 - | sym::powf16 | sym::roundf16 | sym::round_ties_even_f16 | sym::sqrtf16 @@ -264,11 +242,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 - | sym::expf128 - | sym::exp2f128 - | sym::logf128 - | sym::log2f128 - | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); @@ -363,7 +336,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } sym::va_arg => { - unimplemented!(); + let va_list = args[0].immediate(); + let gcc_type = self.immediate_backend_type(result.layout); + self.va_arg(va_list, gcc_type) } sym::volatile_load | sym::unaligned_volatile_load => { @@ -613,7 +588,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); - crate::attributes::from_fn_attrs(self, func, instance); + crate::attributes::from_fn_attrs(self, func, instance, None); func }; @@ -692,8 +667,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, _va_list: RValue<'gcc>) { - unimplemented!(); + fn va_start(&mut self, va_list: RValue<'gcc>) { + let func = self.context.get_builtin_function("__builtin_va_start"); + + let va_list_type = self.context.new_c_type(CType::VaList); + let va_list = self.context.new_cast(self.location, va_list, va_list_type.make_pointer()); + + // Pre-C23 requires that the last "normal" argument was passed to va_start. + // Just pass 0, this appears to be handled correctly. + let last_normal_arg = self.context.new_rvalue_from_int(self.int_type, 0); + + let call = self.context.new_call(self.location, func, &[va_list, last_normal_arg]); + self.block.add_eval(self.location, call); } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { @@ -951,7 +936,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let else_block = func.new_block("else"); let after_block = func.new_block("after"); - let result = func.new_local(None, self.u32_type, "zeros"); + let result = self.new_temp(func, None, self.u32_type); let zero = self.cx.gcc_zero(arg.get_type()); let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); @@ -1032,7 +1017,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // else call it on the 64 high bits and add 64. In the else case, 64 high bits can't be 0 // because arg is not 0. - let result = self.current_func().new_local(None, result_type, "count_zeroes_results"); + let result = self.new_temp(self.current_func(), None, result_type); let cz_then_block = self.current_func().new_block("cz_then"); let cz_else_block = self.current_func().new_block("cz_else"); @@ -1147,8 +1132,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let loop_tail = func.new_block("tail"); let counter_type = self.int_type; - let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); - let val = self.current_func().new_local(None, value_type, "popcount_value"); + let counter = self.new_temp(self.current_func(), None, counter_type); + let val = self.new_temp(self.current_func(), None, value_type); let zero = self.gcc_zero(counter_type); self.llbb().add_assignment(self.location, counter, zero); self.llbb().add_assignment(self.location, val, value); diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 8d3e3487b5cb4..1aac52c28d220 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -1240,6 +1240,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "bmi.pdep.32" => "__builtin_ia32_pdep_si", + "bmi.pdep.64" => "__builtin_ia32_pdep_di", + "bmi.pext.32" => "__builtin_ia32_pext_si", + "bmi.pext.64" => "__builtin_ia32_pext_di", "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", diff --git a/src/lib.rs b/src/lib.rs index 55c721a9706a6..436f8a1176300 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,9 +76,9 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] -use gccjit::{TargetInfo, Version}; +use gccjit::TargetInfo; +use gccjit::{CType, Context, OptimizationLevel}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ @@ -97,7 +97,7 @@ use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::{Arch, RelocModel}; +use rustc_target::spec::RelocModel; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; @@ -197,8 +197,10 @@ impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { - let rustlib_path = - rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); + let rustlib_path = rustc_target::relative_target_rustlib_path( + sysroot_path, + rustc_session::config::host_tuple(), + ); sysroot_path .join(rustlib_path) .join("codegen-backends") @@ -315,27 +317,6 @@ impl CodegenBackend for GccCodegenBackend { } } -fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { - let context = Context::default(); - if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) { - context.add_command_line_option("-masm=intel"); - } - #[cfg(feature = "master")] - { - context.set_special_chars_allowed_in_func_names("$.*"); - let version = Version::get(); - let version = format!("{}.{}.{}", version.major, version.minor, version.patch); - context.set_output_ident(&format!( - "rustc version {} with libgccjit {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - version, - )); - } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); - context -} - impl ExtraBackendMethods for GccCodegenBackend { type Module = GccContext; @@ -347,7 +328,7 @@ impl ExtraBackendMethods for GccCodegenBackend { ) -> Self::Module { let lto_supported = self.lto_supported.load(Ordering::SeqCst); let mut mods = GccContext { - context: Arc::new(SyncContext::new(new_context(tcx))), + context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, lto_supported, @@ -444,7 +425,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(sess, cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( diff --git a/src/mono_item.rs b/src/mono_item.rs index d5874779021d2..7513978b12272 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,11 +1,12 @@ +use gccjit::Function; #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute}; +use gccjit::{FnAttribute, LValue, ToRValue, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -21,7 +22,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { def_id: DefId, _linkage: Linkage, visibility: Visibility, - symbol_name: &str, + global_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); @@ -33,11 +34,20 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); + + let create_global = |this: &CodegenCx<'gcc, 'tcx>, name: &str, visibility: Visibility| { + let global = this.define_global(name, gcc_type, is_tls, attrs.link_section); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + // FIXME(antoyo): set linkage. + global + }; + let global = create_global(self, global_name, visibility); + + let attrs = self.tcx.codegen_instance_attrs(instance.def); #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + self.add_static_aliases(&attrs.foreign_item_symbol_aliases, global_name, &create_global); - // FIXME(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); } @@ -50,12 +60,98 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { assert!(!instance.args.has_infer()); + let attrs = self.tcx.codegen_instance_attrs(instance.def); + + let decl = + self.predefine_without_aliases(instance, &attrs, linkage, visibility, symbol_name); + + #[cfg(feature = "master")] + self.add_function_aliases(instance, decl, &attrs, &attrs.foreign_item_symbol_aliases); + + self.functions.borrow_mut().insert(symbol_name.to_string(), decl); + self.function_instances.borrow_mut().insert(instance, decl); + } +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + #[cfg(feature = "master")] + fn add_static_aliases( + &self, + aliases: &[(DefId, Linkage, Visibility)], + aliased: &str, + create_global: &F, + ) where + F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, + { + for &(alias, _linkage, visibility) in aliases { + let instance = Instance::mono(self.tcx, alias); + let symbol_name = self.tcx.symbol_name(instance); + + let alias = create_global(self, symbol_name.name, visibility); + alias.add_attribute(VarAttribute::Alias(aliased)); + + // Add the alias name to the set of cached items, so there is no duplicate + // instance added to it during the normal `external static` codegen + let prev_entry = self.instances.borrow_mut().insert(instance, alias); + + // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias` + // which would result in incorrect codegen + assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); + } + } + + #[cfg(feature = "master")] + fn add_function_aliases( + &self, + aliased_instance: Instance<'tcx>, + aliased: Function<'gcc>, + attrs: &CodegenFnAttrs, + aliases: &[(DefId, Linkage, Visibility)], + ) { + for &(alias, linkage, visibility) in aliases { + let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, alias)); + + // predefine another copy of the original instance + // with a new symbol name + let alias_fn_decl = self.predefine_without_aliases( + aliased_instance, + attrs, + linkage, + visibility, + symbol_name.name, + ); + + let block = alias_fn_decl.new_block("start"); + let nb_params = alias_fn_decl.get_param_count(); + let mut args = Vec::with_capacity(nb_params); + for idx in 0..nb_params { + args.push(alias_fn_decl.get_param(idx as _).to_rvalue()); + } + + let void_type = self.context.new_type::<()>(); + let call = self.context.new_call(None, aliased, &args); + if alias_fn_decl.get_return_type() == void_type { + block.add_eval(None, call); + block.end_with_void_return(None); + } else { + block.end_with_return(None, call); + } + } + } + + fn predefine_without_aliases( + &self, + instance: Instance<'tcx>, + _attrs: &CodegenFnAttrs, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str, + ) -> Function<'gcc> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); - let decl = self.declare_fn(symbol_name, fn_abi); - //let attrs = self.tcx.codegen_instance_attrs(instance.def); + let fn_decl = self.declare_fn(symbol_name, fn_abi); - attributes::from_fn_attrs(self, decl, instance); + attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden @@ -63,17 +159,21 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // don't want the symbols to get exported. if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + fn_decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else if visibility != Visibility::Default { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + } + + #[cfg(feature = "master")] + if let Some(section) = _attrs.link_section { + fn_decl.add_attribute(FnAttribute::Section(section.as_str())); } - // FIXME(antoyo): call set_link_section() to allow initializing argc/argv. // FIXME(antoyo): set unique comdat. // FIXME(antoyo): use inline attribute from there in linkage.set() above. + // FIXME: Should we handle dso? - self.functions.borrow_mut().insert(symbol_name.to_string(), decl); - self.function_instances.borrow_mut().insert(instance, decl); + fn_decl } } diff --git a/src/type_.rs b/src/type_.rs index 5252f93a92ebe..f008be67e39cb 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; #[cfg(feature = "master")] -use gccjit::CType; +use gccjit::{CType, TypeAttribute}; use gccjit::{RValue, Struct, Type}; use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; @@ -116,7 +116,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); if packed { #[cfg(feature = "master")] - typ.set_packed(); + typ.add_attribute(TypeAttribute::Packed); } self.struct_types.borrow_mut().insert(types, typ); typ @@ -153,7 +153,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { if self.supports_f16_type { return self.context.new_c_type(CType::Float16); } - bug!("unsupported float width 16") + self.u16_type } fn type_f32(&self) -> Type<'gcc> { @@ -333,7 +333,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { typ.set_fields(None, &fields); if packed { #[cfg(feature = "master")] - typ.as_type().set_packed(); + typ.as_type().add_attribute(TypeAttribute::Packed); } } diff --git a/tests/asm/asm/comments.rs b/tests/asm/asm/comments.rs new file mode 100644 index 0000000000000..603bb014930c4 --- /dev/null +++ b/tests/asm/asm/comments.rs @@ -0,0 +1,12 @@ +//@ assembly-output: emit-asm +//@ only-x86_64 +// Check that comments in assembly get passed + +#![crate_type = "lib"] + +// CHECK-LABEL: "test_comments": +#[no_mangle] +pub fn test_comments() { + // CHECK: example comment + unsafe { core::arch::asm!("nop // example comment") }; +} diff --git a/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs new file mode 100644 index 0000000000000..81ee9b13b4eca --- /dev/null +++ b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full +//@ assembly-output: emit-asm +//@ needs-asm-support +//@ only-x86_64 + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", +// meaning "no prologue whatsoever, no, really, not one instruction." +// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection, +// works by using an instruction for each possible landing site, +// and LLVM implements this via making sure of that. +#[no_mangle] +#[unsafe(naked)] +pub extern "sysv64" fn will_halt() -> ! { + // CHECK-NOT: endbr{{32|64}} + // CHECK: hlt + naked_asm!("hlt") +} + +// what about aarch64? +// "branch-protection"=false diff --git a/tests/asm/panic-no-unwind-no-uwtable.rs b/tests/asm/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..b51b173e9616e --- /dev/null +++ b/tests/asm/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3 + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} diff --git a/tests/asm/used.rs b/tests/asm/used.rs new file mode 100644 index 0000000000000..deb0c69dc48fa --- /dev/null +++ b/tests/asm/used.rs @@ -0,0 +1,14 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu + +#![feature(used_with_arg)] +#![crate_type = "lib"] + +// CHECK: .section .rodata.X,"a" +#[used(compiler)] +#[no_mangle] +pub static X: u32 = 12; +// CHECK: .section .rodata.Y,"aR" +#[used(linker)] +#[no_mangle] +pub static Y: u32 = 12; diff --git a/tests/asm/x86_64-sse_crc.rs b/tests/asm/x86_64-sse_crc.rs new file mode 100644 index 0000000000000..bde58955a2146 --- /dev/null +++ b/tests/asm/x86_64-sse_crc.rs @@ -0,0 +1,12 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 + +// CHECK-LABEL: banana +// CHECK: crc32 +#[no_mangle] +pub unsafe fn banana(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} diff --git a/tests/compile/x86_interrupt_first_arg_byval.rs b/tests/compile/x86_interrupt_first_arg_byval.rs new file mode 100644 index 0000000000000..4b6bbd48f7ad5 --- /dev/null +++ b/tests/compile/x86_interrupt_first_arg_byval.rs @@ -0,0 +1,16 @@ +// Compiler: + +// Test that `x86-interrupt` functions whose first argument is passed by value +// emit pointer-shaped GCC parameters and compile with interrupt-safe target features. + +#![feature(abi_x86_interrupt)] +#![crate_type = "lib"] + +#[repr(C)] +pub struct Frame { + ip: u64, +} + +pub extern "x86-interrupt" fn scalar(_a: i64) {} + +pub extern "x86-interrupt" fn aggregate(_frame: Frame) {} diff --git a/tests/cpuid.def b/tests/cpuid.def new file mode 100644 index 0000000000000..05fe8e94a8282 --- /dev/null +++ b/tests/cpuid.def @@ -0,0 +1,27 @@ +# Input => Output +# EAX ECX => EAX EBX ECX EDX +00000000 ******** => 00000024 756e6547 6c65746e 49656e69 #Processor ID and Manufacturer +00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff +00000007 00000000 => 00000002 f3bfbfbf bac05ffe 03d54130 #Extended Features +00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e +0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 +0000000d 00000001 => 0000001f 00000240 00000100 00000000 #Supervisor State +0000000d 00000002 => 00000100 00000240 00000000 00000000 +0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks +0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh +0000000d 00000007 => 00000400 00000680 00000000 00000000 #zmm +0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig +0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles +0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX +00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker +0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile +0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 +0000001e 00000000 => 00000001 00004010 00000000 00000000 #AMX Tmul +0000001e 00000001 => 000001ff 00000000 00000000 00000000 +00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 +00000024 00000001 => 00000000 00000000 00000004 00000000 +80000000 ******** => 80000004 00000000 00000000 00000000 +80000001 ******** => 00000000 00000000 00000121 2c100000 +80000002 ******** => 00000000 00000000 00000000 00000000 +80000003 ******** => 00000000 00000000 00000000 00000000 +80000004 ******** => 00000000 00000000 00000000 00000000 diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index 4c62c35a512c1..e98d2aab9361b 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -4,3 +4,7 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs tests/ui/coroutine/panic-drops-resume.rs tests/ui/coroutine/panic-drops.rs tests/ui/coroutine/panic-safe.rs +tests/ui/panic-handler/catch-unwind-during-unwind-68696.rs +tests/ui/threads-sendsync/task-stderr.rs +tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 528ee1df9f583..1feb2c7cc6edc 100644 --- a/tests/failing-run-make-tests.txt +++ b/tests/failing-run-make-tests.txt @@ -12,3 +12,4 @@ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ tests/run-make/short-ice +tests/run-make/embed-source-dwarf diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index e8a26a90890c1..2b2f21904abb5 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -11,27 +11,22 @@ tests/ui/mir/mir_match_guard_let_chains_drop_order.rs tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs tests/ui/panic-runtime/abort.rs tests/ui/panic-runtime/link-to-abort.rs -tests/ui/parser/unclosed-delimiter-in-dep.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/drop/panic-during-drop-14875.rs -tests/ui/issues/issue-29948.rs +tests/ui/drop/move-closure-drop-on-unwind.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/lto/thin-lto-inlines2.rs tests/ui/panic-runtime/lto-abort.rs tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/coroutine/resume-after-return.rs -tests/ui/simd/masked-load-store.rs tests/ui/simd/repr_packed.rs tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs tests/ui/coroutine/unwind-abort-mix.rs -tests/ui/consts/issue-miri-1910.rs tests/ui/consts/const_cmp_type_id.rs -tests/ui/consts/issue-94675.rs -tests/ui/traits/const-traits/const-drop-fail.rs tests/ui/runtime/on-broken-pipe/child-processes.rs tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs tests/ui/sanitizer/cfi/async-closures.rs @@ -47,7 +42,6 @@ tests/ui/sanitizer/cfi/virtual-auto.rs tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs tests/ui/sanitizer/kcfi-mangling.rs -tests/ui/delegation/fn-header.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs tests/ui/runtime/rt-explody-panic-payloads.rs @@ -67,47 +61,53 @@ tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs tests/ui/process/nofile-limit.rs -tests/ui/linking/no-gc-encapsulation-symbols.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs -tests/ui/explicit-tail-calls/recursion-etc.rs -tests/ui/explicit-tail-calls/indexer.rs -tests/ui/explicit-tail-calls/drop-order.rs -tests/ui/c-variadic/valid.rs -tests/ui/c-variadic/inherent-method.rs -tests/ui/c-variadic/trait-method.rs -tests/ui/explicit-tail-calls/become-cast-return.rs -tests/ui/explicit-tail-calls/become-indirect-return.rs tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs tests/ui/sanitizer/kcfi-c-variadic.rs tests/ui/sanitizer/kcfi/fn-trait-objects.rs tests/ui/statics/const_generics.rs tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs -tests/ui/iterators/rangefrom-overflow-debug.rs -tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs -tests/ui/eii/linking/codegen_single_crate.rs -tests/ui/eii/linking/codegen_cross_crate.rs -tests/ui/eii/default/local_crate.rs -tests/ui/eii/duplicate/multiple_impls.rs -tests/ui/eii/default/call_default.rs -tests/ui/eii/linking/same-symbol.rs -tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs -tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/consts/const-eval/c-variadic.rs -tests/ui/eii/default/call_default_panics.rs -tests/ui/explicit-tail-calls/indirect.rs -tests/ui/traits/inheritance/self-in-supertype.rs -tests/ui/fmt/fmt_debug/shallow.rs -tests/ui/c-variadic/roundtrip.rs -tests/ui/eii/eii_impl_with_contract.rs tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs tests/ui/eii/static/same_address.rs tests/ui/eii/static/simple.rs -tests/ui/explicit-tail-calls/default-trait-method.rs +tests/ui/eii/static/default.rs +tests/ui/eii/static/default_cross_crate.rs +tests/ui/eii/static/default_explicit.rs +tests/ui/eii/static/default_cross_crate_explicit.rs +tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +tests/ui/abi/rust-tail-cc.rs +tests/ui/abi/rust-preserve-none-cc.rs +tests/ui/extern/extern-types-field-offset.rs +tests/ui/numbers-arithmetic/int-abs-overflow.rs +tests/ui/numbers-arithmetic/issue-8460.rs +tests/ui/panics/panic-handler-chain-update-hook.rs +tests/ui/panics/panic-handler-chain.rs +tests/ui/panics/panic-handler-set-twice.rs +tests/ui/panics/panic-recover-propagate.rs +tests/ui/panics/panic-in-dtor-drops-fields.rs +tests/ui/panics/panic-handler-flail-wildly.rs +tests/ui/panics/rvalue-cleanup-during-box-panic.rs +tests/ui/process/multi-panic.rs +tests/ui/sepcomp/sepcomp-unwind.rs +tests/ui/structs/unit-like-struct-drop-run.rs +tests/ui/threads-sendsync/unwind-resource.rs +tests/ui/array-slice-vec/box-of-array-of-drop-2.rs +tests/ui/array-slice-vec/box-of-array-of-drop-1.rs +tests/ui/array-slice-vec/nested-vec-3.rs +tests/ui/array-slice-vec/slice-panic-1.rs +tests/ui/array-slice-vec/slice-panic-2.rs +tests/ui/backtrace/synchronized-panic-handler.rs +tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs +tests/ui/drop/drop-once-on-panic.rs +tests/ui/drop/enum-destructor-on-unwind.rs +tests/ui/drop/drop-trait-enum.rs +tests/ui/drop/panic-during-slice-init.rs +tests/ui/drop/terminate-in-initializer.rs diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 6afd54e1c3fe0..f3b4ad34bc9c4 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -172,6 +172,16 @@ fn build_test_runner( } } + // Extra flags passed at run time (as opposed to the compile-time + // `TEST_FLAGS`). This lets a single test opt into flags like + // `-Zmir-preserve-ub` via an `ignore-if` directive that checks + // whether `CARGO_TEST_FLAGS` is set. + if let Ok(flags) = std::env::var("CARGO_TEST_FLAGS") { + for flag in flags.split_whitespace() { + compiler_args.push(flag.into()); + } + } + if build_mode.is_debug() { compiler_args .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); @@ -201,7 +211,13 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { "lang compile", "tests/compile", TestMode::Compile, - &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], + &[ + "simd-ffi.rs", + "asm_nul_byte.rs", + "global_asm_nul_byte.rs", + "naked_asm_nul_byte.rs", + "x86_interrupt_first_arg_byval.rs", + ], ); } diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 01775c92ffc8a..42141c671b596 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -3,6 +3,8 @@ // Run-time: // status: 0 +#![feature(asm_goto_with_outputs)] + #[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; @@ -32,6 +34,20 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } +#[cfg(target_arch = "x86_64")] +#[unsafe(no_mangle)] +pub fn asm_goto_test(mut a: i16) -> i16 { + unsafe { + std::arch::asm!( + "jmp {op}", + inout("eax") a, + op = label { a = 7; }, + options(nostack,nomem) + ); + a + } +} + #[cfg(target_arch = "x86_64")] fn asm() { unsafe { @@ -190,6 +206,14 @@ fn asm() { } assert_eq!((x, y), (8, 8)); + // Regression test for + // typed pointer inputs to explicit registers need a cast. + let mut x = 123_i32; + unsafe { + asm!("", in("rdi") &mut x, options(nostack, preserves_flags)); + } + assert_eq!(x, 123); + // sysv64 is the default calling convention on unix systems. The rdi register is // used to pass arguments in the sysv64 calling convention, so this register will be clobbered #[cfg(unix)] @@ -227,6 +251,24 @@ fn asm() { out("r15b") _, ); } + + // Make sure the input value from inout is assigned to the input value + unsafe { + // Use a very distinctive value unlikely to live in any register. + let input: u64 = 0x1234567890ABCDEF; + let mut output: u64; + + asm!( + "push {1}", + "pop {0}", + out(reg) output, + inout(reg) input => _, + ); + + assert_eq!(output, 0x1234567890ABCDEF); + } + + asm_goto_test(0); } #[cfg(not(target_arch = "x86_64"))] diff --git a/tests/run/int.rs b/tests/run/int.rs index 78675acb5447b..ef825b4d80185 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -319,4 +319,29 @@ fn main() { const VAL5: T = 73236519889708027473620326106273939584_i128; check_ops128!(); } + + { + #[allow(dead_code)] + #[repr(u8)] + enum Inner { + L0 = 0, + H255 = 255, + } + #[allow(dead_code)] + enum O { + A(Inner), + B, + C, + } + + #[inline(never)] + fn which(o: &O) -> &'static str { + match o { + O::A(_) => "a", + O::B => "b", + O::C => "c", + } + } + assert_eq!(which(black_box(&O::A(Inner::H255))), "a"); + } } diff --git a/tests/run/mir_preserve_ub_empty_switch.rs b/tests/run/mir_preserve_ub_empty_switch.rs new file mode 100644 index 0000000000000..26056360b9212 --- /dev/null +++ b/tests/run/mir_preserve_ub_empty_switch.rs @@ -0,0 +1,35 @@ +// ignore-if: test -z "$CARGO_TEST_FLAGS" +// Compiler: +// +// Run-time: +// status: 0 + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/881 +// +// This needs `-Zmir-preserve-ub`, so it is skipped unless that flag is passed +// through `CARGO_TEST_FLAGS` (see the `ignore-if` directive above). Run it with: +// CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use intrinsics::black_box; +use mini_core::*; + +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { + // With `-Zmir-preserve-ub`, the range pattern below is lowered to a pair of + // comparisons and the second one becomes a `SwitchInt` with no cases (only + // an `otherwise` target) whose discriminant is the `bool` comparison + // result. `gcc_jit_block_end_with_switch` rejects a non-integer + // discriminant, so the backend must emit a plain jump for it instead. + let value = black_box(argc); + match value { + 0..=9 => (), + _ => (), + } + 0 +} diff --git a/tools/cspell_dicts/rust.txt b/tools/cspell_dicts/rust.txt index 379cbd77eef01..15faacd53d5a0 100644 --- a/tools/cspell_dicts/rust.txt +++ b/tools/cspell_dicts/rust.txt @@ -1,2 +1,3 @@ lateout repr +rmeta diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt index 4fb018b3ecd87..bae8edc9ffdf9 100644 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ b/tools/cspell_dicts/rustc_codegen_gcc.txt @@ -60,10 +60,12 @@ nvptx pointee powitf reassoc +retag riscv rlib roundevenf rustc +sgpr sitofp sizet spir @@ -74,5 +76,8 @@ uitofp unord uninlined utrunc +vgpr xabort +xreg +xtensa zext diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 5390323407779..06425f682a88b 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -84,6 +84,10 @@ def update_intrinsics(llvm_path): # This speeds up the comparison, and makes our code considerably smaller. # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) + indent4 = " " + indent8 = indent4 + indent4 + indent12 = indent8 + indent4 + indent16 = indent12 + indent4 with open(output_file, "w", encoding="utf8") as out: out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! @@ -95,33 +99,35 @@ def update_intrinsics(llvm_path): if let ArchCheckResult::Ok(res) = old_arch_res { return res; } -match arch {""") + match arch { +""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" - out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) + out.write(f"""{indent4}"{arch}" => {{ +{indent8}{attribute} fn {arch}(name: &str,full_name:&str) -> &'static str {{ +{indent12}match name {{""") intrinsics[arch].sort(key=lambda x: (x[0], x[1])) - out.write(' // {}\n'.format(arch)) + out.write(f'{indent16}// {arch}\n') for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); if "_round_mask" in entry[1]: - out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) + out.write(f'{indent16}// [INVALID CONVERSION]: "{llvm_name}" => "{entry[1]}",\n') else: - out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) - out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') - out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(""" _ => { - match old_arch_res { - ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), - ArchCheckResult::Ok(_) => unreachable!(), - } - }""") + out.write(f'{indent16}"{llvm_name}" => "{entry[1]}",\n') + out.write(f'{indent16}_ => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"),\n') + out.write(f"{indent16}}}\n{indent12}}}\n{indent8}{arch}(name,full_name)\n{indent8}}}\n,") + out.write(f"""{indent4}_ => {{ +{indent8}match old_arch_res {{ +{indent8}ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"), +{indent8}ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {{arch}}, intrinsic: {{full_name}}"), +{indent8}ArchCheckResult::Ok(_) => unreachable!(), +{indent4}}} +}}""") out.write("}\n}") - subprocess.call(["rustfmt", output_file]) print("Done!") From c9183520739294f4d05485521c02f5e7ba7251a1 Mon Sep 17 00:00:00 2001 From: edwloef Date: Mon, 3 Aug 2026 15:05:42 +0200 Subject: [PATCH 0019/1309] stabilize `Box::take` --- library/alloc/src/boxed.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 90a2330629c1c..fad021fd93dc8 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -755,8 +755,6 @@ impl Box { /// # Examples /// /// ``` - /// #![feature(box_take)] - /// /// let c = Box::new(5); /// /// // take the value out of the box @@ -767,7 +765,7 @@ impl Box { /// let c = Box::write(uninit, 6); /// assert_eq!(*c, 6); /// ``` - #[unstable(feature = "box_take", issue = "147212")] + #[stable(feature = "box_take", since = "CURRENT_RUSTC_VERSION")] pub fn take(boxed: Self) -> (T, Box, A>) { unsafe { let (raw, alloc) = Box::into_non_null_with_allocator(boxed); From 9412bfb9b7f2cff7c451fa2946e8999ec59dd715 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 3 Aug 2026 09:33:26 -0400 Subject: [PATCH 0020/1309] Only emit -fno-asynchronous-unwind-tables when we should not emit unwind tables --- src/gcc_util.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4d7f2cdbb92ed..d986dc68e675a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -157,8 +157,9 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { version, )); } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); + if !sess.must_emit_unwind_tables() { + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + } if sess.panic_strategy().unwinds() { context.add_command_line_option("-fexceptions"); From 3e7fbda2930518b52f1ae18766c04db6579b0cab Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 3 Aug 2026 23:05:36 +0200 Subject: [PATCH 0021/1309] Revert "Auto merge of #159844 - GuillaumeGomez:subtree-update_cg_gcc_2026-07-24, r=GuillaumeGomez" This reverts commit 504869653f510b279c542e65ccd1ea9710c119ba, reversing changes made to 7c329d6c76e11ca40c5673818ab0439c1be8962c. --- .cspell.json | 2 +- .github/workflows/ci.yml | 17 +- .github/workflows/stdarch.yml | 20 +- .gitignore | 2 +- CONTRIBUTING.md | 2 +- Cargo.lock | 100 +++- Cargo.toml | 2 +- Readme.md | 8 +- build_system/Cargo.lock | 2 +- build_system/asm-tester/Cargo.lock | 507 ------------------ build_system/asm-tester/Cargo.toml | 13 - build_system/asm-tester/src/main.rs | 66 --- build_system/src/build.rs | 2 +- build_system/src/clean.rs | 3 +- build_system/src/clippy.rs | 62 --- build_system/src/config.rs | 13 +- build_system/src/fmt.rs | 5 +- build_system/src/main.rs | 112 ++-- build_system/src/rust_tools.rs | 2 +- build_system/src/test.rs | 197 ++----- build_system/src/todo.rs | 72 --- build_system/src/utils.rs | 58 +- doc/subtree.md | 4 +- libgccjit.version | 2 +- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 ++ rust-toolchain | 2 +- src/abi.rs | 41 +- src/asm.rs | 19 +- src/attributes.rs | 26 - src/back/lto.rs | 40 +- src/back/write.rs | 5 +- src/base.rs | 123 ++++- src/builder.rs | 193 +++---- src/callee.rs | 2 +- src/common.rs | 12 +- src/consts.rs | 49 +- src/declare.rs | 32 +- src/diagnostics.rs | 4 + src/gcc_util.rs | 152 +----- src/int.rs | 30 +- src/intrinsic/archs.rs | 86 +-- src/intrinsic/llvm.rs | 121 +---- src/intrinsic/mod.rs | 67 ++- src/intrinsic/old_archs.rs | 4 - src/lib.rs | 37 +- src/mono_item.rs | 128 +---- src/type_.rs | 8 +- tests/asm/asm/comments.rs | 12 - .../x86_64-naked-fn-no-cet-prolog.rs | 24 - tests/asm/panic-no-unwind-no-uwtable.rs | 8 - tests/asm/used.rs | 14 - tests/asm/x86_64-sse_crc.rs | 12 - .../compile/x86_interrupt_first_arg_byval.rs | 16 - tests/cpuid.def | 27 - tests/failing-lto-tests.txt | 4 - tests/failing-run-make-tests.txt | 1 - tests/failing-ui-tests.txt | 68 +-- tests/lang_tests.rs | 18 +- tests/run/asm.rs | 42 -- tests/run/int.rs | 25 - tests/run/mir_preserve_ub_empty_switch.rs | 35 -- tools/cspell_dicts/rust.txt | 1 - tools/cspell_dicts/rustc_codegen_gcc.txt | 5 - tools/generate_intrinsics.py | 36 +- 64 files changed, 674 insertions(+), 2167 deletions(-) delete mode 100644 build_system/asm-tester/Cargo.lock delete mode 100644 build_system/asm-tester/Cargo.toml delete mode 100644 build_system/asm-tester/src/main.rs delete mode 100644 build_system/src/clippy.rs delete mode 100644 build_system/src/todo.rs create mode 100644 patches/0001-Add-stdarch-Cargo.toml-for-testing.patch delete mode 100644 tests/asm/asm/comments.rs delete mode 100644 tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs delete mode 100644 tests/asm/panic-no-unwind-no-uwtable.rs delete mode 100644 tests/asm/used.rs delete mode 100644 tests/asm/x86_64-sse_crc.rs delete mode 100644 tests/compile/x86_interrupt_first_arg_byval.rs delete mode 100644 tests/cpuid.def delete mode 100644 tests/run/mir_preserve_ub_empty_switch.rs diff --git a/.cspell.json b/.cspell.json index a2856029c2c1a..556432d69a41b 100644 --- a/.cspell.json +++ b/.cspell.json @@ -22,7 +22,7 @@ "src/intrinsic/llvm.rs" ], "ignoreRegExpList": [ - "/(FIXME|NOTE)\\([^)]+\\)/", + "/(FIXME|NOTE|TODO)\\([^)]+\\)/", "__builtin_\\w*" ] } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b76c79fd10870..fa9535a3729c3 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests --alloc-tests", + "--std-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", @@ -36,7 +36,6 @@ jobs: "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", "--projects", - "--gcc-asm-tests", ] steps: @@ -53,6 +52,9 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm + - name: Install rustfmt & clippy + run: rustup component add rustfmt clippy + - name: Download artifact run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} @@ -86,17 +88,16 @@ jobs: - name: Check formatting run: ./y.sh fmt --check - - name: Check todo - run: ./y.sh check-todo - - - name: Check lints - run: ./y.sh clippy + - name: clippy + run: | + cargo clippy --all-targets -- -D warnings + cargo clippy --all-targets --no-default-features -- -D warnings + cargo clippy --manifest-path build_system/Cargo.toml --all-targets -- -D warnings - name: Build run: | ./y.sh build --sysroot ./y.sh test --cargo-tests - CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - name: Run y.sh cargo build run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 17d6449c85e08..66f30b147b4c0 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: cargo_runner: [ - "sde -cpuid-in /home/runner/work/rustc_codegen_gcc/rustc_codegen_gcc/tests/cpuid.def -rtm_mode full --", + "sde -future -rtm_mode full --", "", ] @@ -42,14 +42,8 @@ jobs: - name: Install more recent binutils run: | echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list - sudo apt-get update -o Acquire::Retries=3 + sudo apt-get update sudo apt-get install binutils - installed="$(dpkg-query --showformat='${Version}' --show binutils)" - echo "Installed binutils: $installed" - if dpkg --compare-versions "$installed" lt "2.44"; then - echo "::error::binutils upgrade failed (got $installed, need >= 2.44); the apt fetch probably failed" - exit 1 - fi - name: Install Intel Software Development Emulator if: ${{ matrix.cargo_runner }} @@ -57,9 +51,10 @@ jobs: mkdir intel-sde cd intel-sde version=10.8.0-2026-03-15 + url_path=915934 dir=sde-external-$version-lin file=$dir.tar.xz - wget http://ci-mirrors.rust-lang.org/$file + wget https://downloadmirror.intel.com/$url_path/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde @@ -95,15 +90,14 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile + CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_tile_ when it's implemented. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/.gitignore b/.gitignore index 1bbd3a9958073..8f73d3eb972a0 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ perf.data.old *.events *.string* gimple* -*_asm +*asm res test-backend projects diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index c5c2a783b1ee7..8f81ecca445a8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,7 +112,7 @@ Full list of debugging options can be found in the [README](Readme.md#env-vars). ### Code Style Guidelines - Follow Rust standard coding conventions -- Ensure your code passes `rustfmt` and `clippy` (you can run them with `y.sh fmt` and `y.sh clippy`) +- Ensure your code passes `rustfmt` and `clippy` - Add comments explaining complex logic, especially in GCC interface code ## Additional Resources diff --git a/Cargo.lock b/Cargo.lock index 060509e51a6f9..a283ea4cb0b05 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.14" +version = "0.3.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" dependencies = [ "libc", "windows-sys", @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "4.0.0" +version = "3.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5dafc4e649cb4a363e95a5960ef50b0c6f1b8e136ff8eb2e928b40353b5d8b" +checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "2.0.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6a00a243aba2a45442bfd72b28d871137d4dac094f13de7f48cf9705112ffe" +checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" dependencies = [ "libc", ] @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.186" +version = "0.2.168" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" +checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" [[package]] name = "linux-raw-sys" -version = "0.12.1" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "memchr" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" dependencies = [ "bitflags", "errno", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.27.0" +version = "3.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" +checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" dependencies = [ "fastrand", "getrandom", @@ -311,20 +311,78 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-link" -version = "0.2.1" +name = "windows-sys" +version = "0.59.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] [[package]] -name = "windows-sys" -version = "0.61.2" +name = "windows-targets" +version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" dependencies = [ - "windows-link", + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", ] +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Cargo.toml b/Cargo.toml index 63a20d46b9d2f..8956bd6948979 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "4.0.0", features = ["dlopen"] } +gccjit = { version = "3.3.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/Readme.md b/Readme.md index 26783aa39cea8..ce5ee1e4adee6 100644 --- a/Readme.md +++ b/Readme.md @@ -136,21 +136,19 @@ $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ### Cargo ```bash -$ CHANNEL=release $CG_GCCJIT_DIR/y.sh cargo run +$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run ``` -If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. +If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. ### Rustc If you want to run `rustc` directly, you can do so with: ```bash -$ CHANNEL=release ./y.sh rustc my_crate.rs +$ ./y.sh rustc my_crate.rs ``` -If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. - You can do the same manually (although we don't recommend it): ```bash diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index 5e761149eb3bc..e727561a2bfba 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 4 +version = 3 [[package]] name = "boml" diff --git a/build_system/asm-tester/Cargo.lock b/build_system/asm-tester/Cargo.lock deleted file mode 100644 index 9ad96acfda407..0000000000000 --- a/build_system/asm-tester/Cargo.lock +++ /dev/null @@ -1,507 +0,0 @@ -# This file is automatically @generated by Cargo. -# It is not intended for manual editing. -version = 4 - -[[package]] -name = "aho-corasick" -version = "1.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" -dependencies = [ - "memchr", -] - -[[package]] -name = "asm-tester" -version = "0.1.0" -dependencies = [ - "compiletest_rs", -] - -[[package]] -name = "cfg-if" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" - -[[package]] -name = "compiletest_rs" -version = "0.11.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" -dependencies = [ - "diff", - "filetime", - "getopts", - "lazy_static", - "libc", - "log", - "miow", - "regex", - "rustfix", - "serde", - "serde_derive", - "serde_json", - "tester", - "windows-sys 0.59.0", -] - -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - -[[package]] -name = "dirs-next" -version = "2.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" -dependencies = [ - "cfg-if", - "dirs-sys-next", -] - -[[package]] -name = "dirs-sys-next" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" -dependencies = [ - "libc", - "redox_users", - "winapi", -] - -[[package]] -name = "filetime" -version = "0.2.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" -dependencies = [ - "cfg-if", - "libc", -] - -[[package]] -name = "getopts" -version = "0.2.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" -dependencies = [ - "unicode-width", -] - -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - -[[package]] -name = "hermit-abi" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" - -[[package]] -name = "itoa" -version = "1.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" - -[[package]] -name = "lazy_static" -version = "1.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" - -[[package]] -name = "libc" -version = "0.2.186" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" - -[[package]] -name = "libredox" -version = "0.1.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" -dependencies = [ - "libc", -] - -[[package]] -name = "log" -version = "0.4.33" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" - -[[package]] -name = "memchr" -version = "2.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" - -[[package]] -name = "miow" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" -dependencies = [ - "windows-sys 0.61.2", -] - -[[package]] -name = "num_cpus" -version = "1.17.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" -dependencies = [ - "hermit-abi", - "libc", -] - -[[package]] -name = "once_cell" -version = "1.21.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" - -[[package]] -name = "pin-project-lite" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" - -[[package]] -name = "proc-macro2" -version = "1.0.106" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" -dependencies = [ - "unicode-ident", -] - -[[package]] -name = "quote" -version = "1.0.46" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" -dependencies = [ - "proc-macro2", -] - -[[package]] -name = "redox_users" -version = "0.4.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" -dependencies = [ - "getrandom", - "libredox", - "thiserror", -] - -[[package]] -name = "regex" -version = "1.12.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata", - "regex-syntax", -] - -[[package]] -name = "regex-automata" -version = "0.4.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-syntax", -] - -[[package]] -name = "regex-syntax" -version = "0.8.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" - -[[package]] -name = "rustfix" -version = "0.8.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" -dependencies = [ - "serde", - "serde_json", - "thiserror", - "tracing", -] - -[[package]] -name = "rustversion" -version = "1.0.22" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" - -[[package]] -name = "serde" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" -dependencies = [ - "serde_core", - "serde_derive", -] - -[[package]] -name = "serde_core" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" -dependencies = [ - "serde_derive", -] - -[[package]] -name = "serde_derive" -version = "1.0.228" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "serde_json" -version = "1.0.150" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" -dependencies = [ - "itoa", - "memchr", - "serde", - "serde_core", - "zmij", -] - -[[package]] -name = "syn" -version = "2.0.118" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "term" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" -dependencies = [ - "dirs-next", - "rustversion", - "winapi", -] - -[[package]] -name = "tester" -version = "0.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" -dependencies = [ - "cfg-if", - "getopts", - "libc", - "num_cpus", - "term", -] - -[[package]] -name = "thiserror" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "1.0.69" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "tracing" -version = "0.1.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" -dependencies = [ - "pin-project-lite", - "tracing-core", -] - -[[package]] -name = "tracing-core" -version = "0.1.36" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" -dependencies = [ - "once_cell", -] - -[[package]] -name = "unicode-ident" -version = "1.0.24" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" - -[[package]] -name = "unicode-width" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" - -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - -[[package]] -name = "windows-link" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" - -[[package]] -name = "windows-sys" -version = "0.59.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] - -[[package]] -name = "windows-sys" -version = "0.61.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" -dependencies = [ - "windows-link", -] - -[[package]] -name = "windows-targets" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" -dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", -] - -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - -[[package]] -name = "zmij" -version = "1.0.21" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/asm-tester/Cargo.toml b/build_system/asm-tester/Cargo.toml deleted file mode 100644 index eeefe61bdc75b..0000000000000 --- a/build_system/asm-tester/Cargo.toml +++ /dev/null @@ -1,13 +0,0 @@ -[package] -name = "asm-tester" -version = "0.1.0" -edition = "2024" - -[dependencies] -compiletest_rs = "0.11.2" - -[[bin]] -name = "asm-tester" -path = "src/main.rs" - -[workspace] diff --git a/build_system/asm-tester/src/main.rs b/build_system/asm-tester/src/main.rs deleted file mode 100644 index 00ee4ac936520..0000000000000 --- a/build_system/asm-tester/src/main.rs +++ /dev/null @@ -1,66 +0,0 @@ -use std::path::PathBuf; - -#[derive(Default)] -struct Config { - llvm_filecheck: Option, - filters: Vec, - rustc_flags: Vec, -} - -impl Config { - fn new() -> Result { - // We skip the program's name. - let mut args = std::env::args().skip(1); - let mut config = Self::default(); - - while let Some(arg) = args.next() { - match arg.as_str() { - "--llvm-filecheck" => { - config.llvm_filecheck = args.next().map(PathBuf::from); - } - "--filter" => { - if let Some(arg) = args.next() { - config.filters.push(arg); - } - } - "--" => { - config.rustc_flags.extend(&mut args); - // Nothing else to be read but the `break` makes it more clear. - break; - } - arg => return Err(format!("Unknown argument {arg:?}")), - } - } - if config.llvm_filecheck.is_none() { - Err("Missing `--llvm-filecheck` option".to_owned()) - } else if config.rustc_flags.is_empty() { - Err("Missing rustc flags (passed after `--`)".to_owned()) - } else { - Ok(config) - } - } -} - -fn main() { - let Config { llvm_filecheck, filters, rustc_flags } = match Config::new() { - Ok(c) => c, - Err(error) => { - eprintln!("{error}"); - std::process::exit(1); - } - }; - - let mut test_config = compiletest_rs::Config::default(); - - test_config.mode = compiletest_rs::common::Mode::Assembly; - test_config.src_base = PathBuf::from("tests/asm"); - test_config.llvm_filecheck = llvm_filecheck; - test_config.filters = filters; - test_config.strict_headers = true; - test_config.build_base = PathBuf::from("build/tests/asm"); - test_config.target_rustcflags = Some(rustc_flags.join(" ")); - test_config.link_deps(); - test_config.clean_rmeta(); - - compiletest_rs::run_tests(&test_config) -} diff --git a/build_system/src/build.rs b/build_system/src/build.rs index e570a3f16c39e..839c762fed742 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -227,7 +227,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false, true)?; + args.config_info.setup(&mut env, false)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index ec2092ee92ef5..43f01fdf35ecb 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -74,8 +74,7 @@ fn clean_ui_tests() -> Result<(), String> { let path = Path::new(crate::BUILD_DIR) .join("rust/build/x86_64-unknown-linux-gnu/test/") .join(directory); - // The directory might not exist, so ignore the error. - let _ = run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None); + run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; } Ok(()) } diff --git a/build_system/src/clippy.rs b/build_system/src/clippy.rs deleted file mode 100644 index 813d4b9141e1c..0000000000000 --- a/build_system/src/clippy.rs +++ /dev/null @@ -1,62 +0,0 @@ -use std::path::Path; - -use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present}; - -fn show_usage() { - println!( - r#" -`clippy` command help: - - --help : Show this help"# - ); -} - -pub fn run() -> Result<(), String> { - // We skip binary name and the `info` command. - let args = std::env::args().skip(2); - #[allow(clippy::never_loop)] - for arg in args { - match arg.as_str() { - "--help" => { - show_usage(); - return Ok(()); - } - _ => return Err(format!("Unknown option {arg}")), - } - } - - run_tool_and_install_it_if_not_present(&[ - &"cargo", - &"clippy", - &"--all-targets", - &"--", - &"-D", - &"warnings", - ])?; - run_command_with_output( - &[ - &"cargo", - &"clippy", - &"--all-targets", - &"--no-default-features", - &"--", - &"-D", - &"warnings", - ], - Some(Path::new(".")), - )?; - run_command_with_output( - &[ - &"cargo", - &"clippy", - &"--all-targets", - &"--manifest-path", - &"build_system/Cargo.toml", - &"--", - &"-D", - &"warnings", - ], - Some(Path::new(".")), - )?; - Ok(()) -} diff --git a/build_system/src/config.rs b/build_system/src/config.rs index fd78f691d1657..8eb6d8f019e1c 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -314,7 +314,6 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, - generate_out_dir: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -445,12 +444,12 @@ impl ConfigInfo { self.rustc_command = vec![rustc]; self.rustc_command.extend_from_slice(&rustflags); - self.rustc_command - .extend_from_slice(&["-L".to_string(), format!("crate={}", self.cargo_target_dir)]); - if generate_out_dir { - self.rustc_command - .extend_from_slice(&["--out-dir".to_string(), self.cargo_target_dir.clone()]); - } + self.rustc_command.extend_from_slice(&[ + "-L".to_string(), + format!("crate={}", self.cargo_target_dir), + "--out-dir".to_string(), + self.cargo_target_dir.clone(), + ]); if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index dc1ca1d3e82ae..91535f217e351 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present, walk_dir}; +use crate::utils::{run_command_with_output, walk_dir}; fn show_usage() { println!( @@ -31,9 +31,8 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - run_tool_and_install_it_if_not_present(cmd)?; + run_command_with_output(cmd, Some(Path::new(".")))?; run_command_with_output(cmd, Some(Path::new("build_system")))?; - run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; run_rustfmt_recursively("tests/run", check) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 83f07a758d659..ae975c94fff25 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -3,7 +3,6 @@ use std::{env, process}; mod abi_test; mod build; mod clean; -mod clippy; mod clone_gcc; mod config; mod fmt; @@ -13,7 +12,6 @@ mod prepare; mod rust_tools; mod rustc_info; mod test; -mod todo; mod utils; const BUILD_DIR: &str = "build"; @@ -26,67 +24,43 @@ macro_rules! arg_error { }}; } -macro_rules! commands_decl { - ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { - enum Command { - $($variant),+ - } - - impl<'a> From> for Command { - fn from(arg: Option<&'a str>) -> Self { - match arg { - $(Some($doc_name) => Self::$variant,)+ - Some("--help") => { - usage(); - process::exit(0); - } - Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), - Some(command) => arg_error!("Unknown command {}", command), - None => { - usage(); - process::exit(0); - } - } - } - } - - fn usage() { - println!("\ +fn usage() { + println!( + "\ rustc_codegen_gcc build system Usage: build_system [command] [options] Options: - --help : Displays this help message. - -Commands:", - ); - let mut commands = vec![$(($doc_name, $doc),)+]; - let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); + --help : Displays this help message. - commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); - for (name, doc) in commands { - let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::(); - eprintln!(" {name}{spacing}: {doc}."); - } - } - } +Commands: + cargo : Executes a cargo command. + rustc : Compiles the program using the GCC compiler. + clean : Cleans the build directory, removing all compiled files and artifacts. + prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. + build : Compiles the project. + test : Runs tests for the project. + info : Displays information about the build environment and project configuration. + clone-gcc : Clones the GCC compiler from a specified source. + fmt : Runs rustfmt + fuzz : Fuzzes `cg_gcc` using rustlantis + abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" + ); } -commands_decl! { - Cargo: "cargo" => "Executes a cargo command", - Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", - Clippy: "clippy" => "Runs clippy", - CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", - Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", - Build: "build" => "Compiles the project", - Rustc: "rustc" => "Compiles the program using the GCC compiler", - Test: "test" => "Runs tests for the project", - Info: "info" => "Displays information about the build environment and project configuration", - Fmt: "fmt" => "Runs rustfmt", - Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", - AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", - CheckTodo: "check-todo" => "Checks todo in the project", +pub enum Command { + Cargo, + Clean, + CloneGcc, + Prepare, + Build, + Rustc, + Test, + Info, + Fmt, + Fuzz, + AbiTest, } fn main() { @@ -96,7 +70,31 @@ fn main() { } } - if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { + let command = match env::args().nth(1).as_deref() { + Some("cargo") => Command::Cargo, + Some("rustc") => Command::Rustc, + Some("clean") => Command::Clean, + Some("prepare") => Command::Prepare, + Some("build") => Command::Build, + Some("test") => Command::Test, + Some("info") => Command::Info, + Some("clone-gcc") => Command::CloneGcc, + Some("abi-test") => Command::AbiTest, + Some("fmt") => Command::Fmt, + Some("fuzz") => Command::Fuzz, + Some("--help") => { + usage(); + process::exit(0); + } + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + }; + + if let Err(e) = match command { Command::Cargo => rust_tools::run_cargo(), Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), @@ -108,8 +106,6 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), - Command::Clippy => clippy::run(), - Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); process::exit(1); diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs index 1b50f11c3d324..b1faa27acc4a2 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -72,7 +72,7 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false, false)?; + config.setup(&mut env, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 6cc2282c8022f..2475a3a6a7155 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -9,8 +9,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output_and_env, - run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, + split_args, walk_dir, }; type Env = HashMap; @@ -28,10 +28,8 @@ fn get_runners() -> Runners { ("Run failing ui pattern tests", test_failing_ui_pattern_tests), ); runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); - runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); - runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); runners.insert("--std-tests", ("Run std tests", std_tests)); @@ -44,10 +42,8 @@ fn get_runners() -> Runners { ); runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); - runners.insert("--gcc-asm-tests", ("Run cg_gcc asm tests", test_asm)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); - runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); runners } @@ -509,26 +505,6 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -fn get_llvm_filecheck(env: &Env) -> Result { - match run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ - which FileCheck-11 || \ - which FileCheck-12 || \ - which FileCheck-13 || \ - which FileCheck-14 || \ - which FileCheck", - ], - None, - Some(env), - ) { - Ok(cmd) => Ok(String::from_utf8_lossy(&cmd.stdout).trim().to_string()), - Err(_) => Err("Failed to retrieve LLVM FileCheck, ignoring...".to_owned()), - } -} - fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", @@ -572,10 +548,23 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let rustc = rustc.trim().to_owned(); if rustc.is_empty() { Err("`rustc` path is empty".to_string()) } else { Ok(rustc) } })?; - let llvm_filecheck = match get_llvm_filecheck(env) { - Ok(l) => l, - Err(error) => { - eprintln!("{error}"); + let llvm_filecheck = match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14 || \ + which FileCheck", + ], + rust_dir, + Some(env), + ) { + Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), + Err(_) => { + eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); // FIXME: the test tests/run-make/no-builtins-attribute will fail if we cannot find // FileCheck. String::new() @@ -645,7 +634,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"--set", &"build.compiletest-allow-stage0=true", - &"tests/assembly-gcc/asm", + &"tests/assembly-llvm/asm", &"--compiletest-rustc-args", &rustc_args, ], @@ -775,39 +764,6 @@ fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } -fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { - println!("[TEST] stdarch"); - let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); - let mut env = env.clone(); - - // `config.setup` already baked `CG_RUSTFLAGS` into `RUSTFLAGS`, so append the lint-allow to - // `RUSTFLAGS` directly (which `run_cargo_command` also propagates to `RUSTDOCFLAGS`). - let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); - env.insert( - "RUSTFLAGS".to_string(), - format!("{rustflags} -Ainternal_features").trim().to_owned(), - ); - env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); - - let mut command: Vec<&dyn AsRef> = - vec![&"test", &"--manifest-path", &manifest_path, &"--"]; - for test_name in &args.test_args { - command.push(test_name); - } - run_cargo_command(&command, None, &env, args)?; - Ok(()) -} - -fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("[TEST] alloc"); - let path = get_sysroot_dir().join("sysroot_src/library/alloctests"); - let _ = remove_dir_all(path.join("target")); - // FIXME(antoyo): run in release mode when we fix the failures. - run_cargo_command(&[&"test"], Some(&path), env, args)?; - Ok(()) -} - fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); @@ -952,6 +908,7 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< "//@ known-bug", "-Cllvm-args", "//~", + "thread", ] .iter() .any(|check| line.contains(check)) @@ -1028,6 +985,21 @@ where true, )?; } else { + walk_dir( + rust_path.join("tests/ui"), + &mut |dir| { + let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); + if ["abi", "extern", "proc-macro", "threads-sendsync"].contains(&dir_name) { + remove_dir_all(dir).map_err(|error| { + format!("Failed to remove folder `{}`: {:?}", dir.display(), error) + })?; + } + Ok(()) + }, + &mut |_| Ok(()), + false, + )?; + // These two functions are used to remove files that are known to not be working currently // with the GCC backend to reduce noise. fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { @@ -1224,46 +1196,6 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String ) } -fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { - let mut env = env.clone(); - let rust_path = setup_rustc(&mut env, args)?; - - let extra = - if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; - - let rustc_args = format!( - "{test_flags} -Zcodegen-backend={backend} --sysroot {sysroot}{extra}", - test_flags = env.get("TEST_FLAGS").unwrap_or(&String::new()), - backend = args.config_info.cg_backend_path, - sysroot = args.config_info.sysroot_path, - extra = extra, - ); - - env.get_mut("RUSTFLAGS").unwrap().clear(); - - let mut command: Vec<&dyn AsRef> = vec![ - &"./x.py", - &"test", - &"--run", - &"always", - &"--stage", - &"0", - &"--set", - &"build.compiletest-allow-stage0=true", - &"--compiletest-rustc-args", - &rustc_args, - &"--bypass-ignore-backends", - &"--force-rerun", - ]; - - for test_name in &args.test_args { - command.push(test_name); - } - - run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; - Ok(()) -} - fn retain_files_callback<'a>( file_path: &'a str, test_type: &'a str, @@ -1365,60 +1297,6 @@ fn remove_files_callback<'a>( } } -fn test_asm(env: &Env, args: &TestArg) -> Result<(), String> { - fn is_path_time_more_recent(ref_time: std::time::SystemTime, path: &str) -> bool { - std::fs::metadata(path) - .and_then(|metadata| metadata.modified()) - .is_ok_and(|time| ref_time < time) - } - - // FIXME: create a function "display_if_not_quiet" or something along the line. - println!("[TEST] cg_gcc assembly"); - let llvm_filecheck = get_llvm_filecheck(env)?; - - let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); - - // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. - let binary_file_path = "build_system/asm-tester/target/debug/asm-tester"; - let mut need_recompilation = true; - if let Ok(metadata) = std::fs::metadata(binary_file_path) - && let Ok(ref_time) = metadata.modified() - && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.toml") - && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.lock") - && !is_path_time_more_recent(ref_time, "build_system/asm-tester/src/main.rs") - { - need_recompilation = false; - } - - if need_recompilation { - let build_asm_args: Vec<&dyn AsRef> = vec![ - &"cargo", - &"build", - &"--manifest-path", - &"build_system/asm-tester/Cargo.toml", - &"--target-dir", - &target_dir, - &"--", - ]; - run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(env))?; - } - - let mut test_asm_args: Vec<&dyn AsRef> = vec![ - &"build_system/asm-tester/target/debug/asm-tester", - &"--llvm-filecheck", - &llvm_filecheck, - ]; - for test_arg in &args.test_args { - test_asm_args.push(&"--filter"); - test_asm_args.push(test_arg); - } - test_asm_args.push(&"--"); - for arg in args.config_info.rustc_command_vec().into_iter().skip(1) { - test_asm_args.push(arg); - } - run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(env)) -} - fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; @@ -1430,7 +1308,6 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { cargo_tests(env, args)?; no_builtins_tests(env, args)?; test_rustc(env, args)?; - test_asm(env, args)?; Ok(()) } @@ -1452,7 +1329,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc, true)?; + args.config_info.setup(&mut env, args.use_system_gcc)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/todo.rs b/build_system/src/todo.rs deleted file mode 100644 index 5b89410844788..0000000000000 --- a/build_system/src/todo.rs +++ /dev/null @@ -1,72 +0,0 @@ -use std::ffi::OsStr; -use std::fs::File; -use std::io::{BufRead, BufReader}; -use std::path::{Path, PathBuf}; -use std::process::Command; - -const EXTENSIONS: &[&str] = - &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; - -fn has_supported_extension(path: &Path) -> bool { - path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) -} - -fn list_tracked_files() -> Result, String> { - let output = Command::new("git") - .args(["ls-files", "-z"]) - .output() - .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; - - if !output.status.success() { - let stderr = String::from_utf8_lossy(&output.stderr); - return Err(format!("`git ls-files` failed: {stderr}")); - } - - let mut files = Vec::new(); - for entry in output.stdout.split(|b| *b == 0) { - if entry.is_empty() { - continue; - } - let path = std::str::from_utf8(entry).unwrap(); - files.push(PathBuf::from(path)); - } - - Ok(files) -} - -pub(crate) fn run() -> Result<(), String> { - let files = list_tracked_files()?; - let mut error_count = 0; - // Avoid embedding the task marker in source so greps only find real occurrences. - let todo_marker = "todo".to_ascii_uppercase(); - - for file in files { - if !has_supported_extension(&file) { - continue; - } - - let file_handle = - File::open(&file).map_err(|e| format!("Failed to open {}: {e}", file.display()))?; - let reader = BufReader::new(file_handle); - - for (i, line) in reader.lines().enumerate() { - let line = line.map_err(|e| format!("Failed to read {}: {e}", file.display()))?; - let trimmed = line.trim(); - if trimmed.contains(&todo_marker) { - eprintln!( - "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", - file.display(), - i + 1, - todo_marker - ); - error_count += 1; - } - } - } - - if error_count == 0 { - return Ok(()); - } - - Err(format!("found {} {}(s)", error_count, todo_marker)) -} diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 4c67156a85fb2..112322f8688c1 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -2,11 +2,10 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; -use std::io::{BufReader, Read}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus, Output, Stdio}; +use std::process::{Command, ExitStatus, Output}; fn exec_command( input: &[&dyn AsRef], @@ -48,7 +47,7 @@ pub(crate) fn get_command_inner( command } -pub(crate) fn check_exit_status( +fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, @@ -116,30 +115,6 @@ pub fn run_command_with_output( check_exit_status(input, cwd, exit_status, None, true) } -pub fn run_command_with_output_and_get_it( - input: &[&dyn AsRef], - cwd: Option<&Path>, -) -> Result<(ExitStatus, String), String> { - let mut child = get_command_inner(input, cwd, None) - .stderr(Stdio::piped()) - .spawn() - .map_err(|e| command_error(input, &cwd, e))?; - - let stderr = child.stderr.take().expect("Failed to capture stderr"); - let mut captured = String::new(); - BufReader::new(stderr).read_to_string(&mut captured).expect("failed to read stderr"); - - let status = child.wait().map_err(|e| command_error(input, &cwd, e))?; - #[cfg(unix)] - { - if let Some(signal) = status.signal() { - // In case the signal didn't kill the current process. - return Err(command_error(input, &cwd, format!("Process received signal {signal}"))); - } - } - Ok((status, captured)) -} - pub fn run_command_with_output_and_env( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -149,6 +124,7 @@ pub fn run_command_with_output_and_env( check_exit_status(input, cwd, exit_status, None, true) } +#[cfg(not(unix))] pub fn run_command_with_output_and_env_no_err( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -443,34 +419,6 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } -pub fn run_tool_and_install_it_if_not_present(cmd: &[&dyn AsRef]) -> Result<(), String> { - let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; - if exit_status.success() { - return Ok(()); - } - let mut iter = stderr.split('\n'); - if let Some(line) = iter.next() - && line.contains("is not installed for the toolchain") - && let Some(line) = iter.next() - && line.contains("run `rustup component add") - && let Some(cmd) = line.split('`').nth(1) - && let Some(tool_name) = cmd.rsplit(' ').next() - { - println!("`{tool_name}` is not installed for this toolchain, installing it..."); - // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but - // as long as it works... - let cmd = cmd.split(' ').collect::>(); - let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); - run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; - } else { - // If the component is installed, then it's something else. In this case we fail like we - // should have and let the user handles the error. - return check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true); - } - // We retry the command... - run_command_with_output(cmd, Some(Path::new("."))) -} - #[cfg(test)] mod tests { use super::*; diff --git a/doc/subtree.md b/doc/subtree.md index fcac399e46542..a81b6c9c74bdd 100644 --- a/doc/subtree.md +++ b/doc/subtree.md @@ -1,7 +1,7 @@ # git subtree sync `rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be -synced from time to time to ensure changes that happened on their side are also +sync from time to time to ensure changes that happened on their side are also included on our side. ### How to install a forked git-subtree @@ -41,8 +41,6 @@ cd ../rust git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master -# Don't forget to update the `gcc` submodule to the same version as the -# one in `rustc_codegen_gcc/libgccjit.version`. git push # Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. diff --git a/libgccjit.version b/libgccjit.version index 7c141c20c4d3d..5eef70260466f 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -dfbee712e611693596ffec1de22177089c537491 +6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch new file mode 100644 index 0000000000000..3a8c37a8b8d9a --- /dev/null +++ b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch @@ -0,0 +1,39 @@ +From 190e26c9274b3c93a9ee3516b395590e6bd9213b Mon Sep 17 00:00:00 2001 +From: None +Date: Sun, 3 Aug 2025 19:54:56 -0400 +Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch + +--- + library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ + 1 file changed, 20 insertions(+) + create mode 100644 library/stdarch/Cargo.toml + +diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml +new file mode 100644 +index 0000000..bd6725c +--- /dev/null ++++ b/library/stdarch/Cargo.toml +@@ -0,0 +1,20 @@ ++[workspace] ++resolver = "1" ++members = [ ++ "crates/*", ++ #"examples/" ++] ++exclude = [ ++ "crates/wasm-assert-instr-tests", ++ "rust_programs", ++] ++ ++[profile.release] ++debug = true ++opt-level = 3 ++incremental = true ++ ++[profile.bench] ++debug = 1 ++opt-level = 3 ++incremental = true +-- +2.50.1 + diff --git a/rust-toolchain b/rust-toolchain index 104992b5da46b..56fcfdff1c719 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-07-24" +channel = "nightly-2026-04-29" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/abi.rs b/src/abi.rs index 45fc5e3c4f619..1b7bb8c907735 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -146,23 +146,12 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } - // There are a few others `ArgAttribute` variants" - // - // * ArgAttribute::ReadOnly: `access(read_only())`, but it's only used for emitting - // warning, not for optimization. - // * ArgAttribute::NoUndef: No equivalent in GCC - // * ArgAttribute::Writable: `access(read_write())` or `access(write_only())`, but it's - // only used for emitting warning, not for optimization. - // * ArgAttribute::NoFree: No equivalent in GCC ty }; #[cfg(not(feature = "master"))] let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - for (source_arg_index, arg) in self.args.iter().enumerate() { - #[cfg(not(feature = "master"))] - let _ = source_arg_index; - + for arg in self.args.iter() { let arg_ty = match arg.mode { PassMode::Ignore => continue, PassMode::Pair(a, b) => { @@ -188,31 +177,9 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_attrs(ty, &cast.attrs, argument_tys.len()) } PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { - let x86_interrupt_first_arg = { - #[cfg(feature = "master")] - { - source_arg_index == 0 - && matches!(self.conv, CanonAbi::Interrupt(InterruptKind::X86)) - } - #[cfg(not(feature = "master"))] - { - false - } - }; - - if x86_interrupt_first_arg { - // Rust lowers the first `x86-interrupt` argument as a byval stack slot. - // LLVM represents that as a pointer parameter with `byval`; GCC's - // interrupt attribute likewise requires a pointer-shaped first parameter. - // Do not add this parameter to `on_stack_param_indices`: that set is only - // needed when GCC represents a byval argument as a value parameter, while - // this parameter is already pointer-shaped. - cx.type_ptr_to(arg.layout.gcc_type(cx)) - } else { - // This is a "byval" argument, so we don't apply the `restrict` attribute on it. - on_stack_param_indices.insert(argument_tys.len()); - arg.layout.gcc_type(cx) - } + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + on_stack_param_indices.insert(argument_tys.len()); + arg.layout.gcc_type(cx) } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) diff --git a/src/asm.rs b/src/asm.rs index a1d227157314b..ee0cef350b42f 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -298,9 +298,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { out_place, }); - if readwrite { - self.llbb().add_assignment(None, tmp_var, in_value.immediate()); - } else { + if !readwrite { let out_gcc_idx = outputs.len() - 1; let constraint = Cow::Owned(out_gcc_idx.to_string()); @@ -366,14 +364,7 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = value.layout.gcc_type(self.cx); let reg_var = self.current_func().new_local(None, ty, "input_register"); reg_var.set_register_name(reg_name); - // FIXME: We should remove this when switching to "untyped" pointers - let value = value.immediate(); - let value = if value.get_type() != ty { - self.context.new_cast(None, value, ty) - } else { - value - }; - self.llbb().add_assignment(None, reg_var, value); + self.llbb().add_assignment(None, reg_var, value.immediate()); inputs.push(AsmInOperand { constraint: "r".into(), @@ -612,12 +603,6 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } - if !options.contains(InlineAsmOptions::NORETURN) - && let Some(dest) = dest - { - self.switch_to_block(dest); - } - // Write results to outputs. // // We need to do this because: diff --git a/src/attributes.rs b/src/attributes.rs index 95d12480efa69..ce1877b308e94 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,8 +2,6 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] -use rustc_abi::{CanonAbi, InterruptKind}; -#[cfg(feature = "master")] use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InstructionSetAttr; #[cfg(feature = "master")] @@ -11,7 +9,6 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] use rustc_middle::mir::TerminatorKind; use rustc_middle::ty; -use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -85,23 +82,12 @@ fn inline_attr<'gcc, 'tcx>( } } -#[cfg(feature = "master")] -fn is_x86_interrupt<'tcx>(fn_abi: Option<&FnAbi<'tcx, ty::Ty<'tcx>>>) -> bool { - matches!( - fn_abi, - Some(fn_abi) if matches!(fn_abi.conv, CanonAbi::Interrupt(InterruptKind::X86)) - ) -} - /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, #[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, - #[cfg_attr(not(feature = "master"), expect(unused_variables))] fn_abi: Option< - &FnAbi<'tcx, ty::Ty<'tcx>>, - >, ) { let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def); @@ -134,11 +120,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } - #[cfg(feature = "master")] - let x86_interrupt = is_x86_interrupt(fn_abi); - #[cfg(not(feature = "master"))] - let x86_interrupt = false; - let mut function_features = codegen_fn_attrs .target_features .iter() @@ -154,13 +135,6 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // Check if GCC requires the same. let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); function_features.extend(&mut global_features); - if x86_interrupt { - // GCC does not preserve SSE, MMX, or x87 state in interrupt handlers and rejects - // them whenever those instruction sets are enabled, even if the handler does not - // emit such instructions. Restrict the function to general registers so the - // interrupt attribute works with the default x86_64 target features. - function_features.push("general-regs-only"); - } let target_features = function_features .iter() .filter_map(|feature| { diff --git a/src/back/lto.rs b/src/back/lto.rs index baf1fda02e258..98f9abdb05c4c 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -20,7 +20,6 @@ use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; -use std::sync::Arc; use gccjit::OutputKind; use object::read::archive::ArchiveFile; @@ -30,15 +29,14 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter} use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; +use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; -use rustc_session::Session; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; use crate::diagnostics::LtoBitcodeFromRlib; -use crate::gcc_util::new_context; -use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; +use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; struct LtoData { // FIXME(antoyo): use symbols_below_threshold. @@ -104,8 +102,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( - sess: &Session, cgcx: &CodegenContext, + prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -116,8 +114,8 @@ pub(crate) fn run_fat( /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( - sess, cgcx, + prof, dcx, modules, lto_data.upstream_modules, @@ -127,15 +125,15 @@ pub(crate) fn run_fat( } fn fat_lto( - sess: &Session, cgcx: &CodegenContext, + prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> CompiledModule { - let _timer = sess.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -185,16 +183,17 @@ fn fat_lto( // module and create a linker with it. let mut module: ModuleCodegen = match costliest_module { Some((_cost, i)) => in_memory.remove(i), - None => ModuleCodegen::new_regular( - "lto_module".to_string(), - GccContext { - context: Arc::new(SyncContext::new(new_context(sess))), - relocation_model: sess.relocation_model(), - lto_supported: true, - lto_mode: LtoMode::None, - temp_dir: None, - }, - ), + None => { + unimplemented!("Incremental"); + /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); + let (buffer, name) = serialized_modules.remove(0); + info!("no in-memory regular modules to choose from, parsing {:?}", name); + ModuleCodegen { + module_llvm: GccContext::parse(cgcx, &name, buffer.data(), dcx)?, + name: name.into_string().unwrap(), + kind: ModuleKind::Regular, + }*/ + } }; { info!("using {:?} as a base module", module.name); @@ -221,8 +220,7 @@ fn fat_lto( // We add the object files and save in should_combine_object_files that we should combine // them into a single object file when compiling later. for (bc_decoded, name) in serialized_modules { - let _timer = sess - .prof + let _timer = prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -260,7 +258,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - codegen(cgcx, &sess.prof, dcx, module, &cgcx.module_config) + codegen(cgcx, prof, dcx, module, &cgcx.module_config) } pub struct ModuleBuffer(PathBuf); diff --git a/src/back/write.rs b/src/back/write.rs index 1f4fd8a314ad2..cf5514412f745 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -11,8 +11,8 @@ use rustc_log::tracing::debug; use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; +use crate::base::add_pic_option; use crate::diagnostics::CopyBitcode; -use crate::gcc_util::add_pic_option; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( @@ -60,6 +60,9 @@ pub(crate) fn codegen( let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { + // FIXME(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? + //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); + context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); context.add_command_line_option("-ffat-lto-objects"); diff --git a/src/base.rs b/src/base.rs index 041420e35d2b5..7a25fc46fd3fc 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,7 +1,9 @@ +use std::collections::HashSet; +use std::env; use std::sync::Arc; use std::time::Instant; -use gccjit::{CType, FunctionType, GlobalKind}; +use gccjit::{CType, Context, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; @@ -15,11 +17,11 @@ use rustc_session::config::DebugInfo; use rustc_span::Symbol; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; +use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::gcc_util::new_context; -use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext}; +use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -99,7 +101,41 @@ pub fn compile_codegen_unit( ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(tcx.sess); + let context = new_context(tcx); + + if tcx.sess.panic_strategy().unwinds() { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } + + let disabled_features: HashSet<_> = tcx + .sess + .opts + .cg + .target_feature + .split(',') + .filter(|feature| feature.starts_with('-')) + .map(|string| &string[1..]) + .collect(); + + if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 { + // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for + // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. + // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. + context.add_command_line_option("-mavx"); + } + + for arg in &tcx.sess.opts.cg.llvm_args { + context.add_command_line_option(arg); + } + // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. + context.add_command_line_option("-fno-var-tracking-assignments"); + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). + context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); + // NOTE: Rust relies on LLVM doing wrapping on overflow. + context.add_command_line_option("-fwrapv"); // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from // replacing code patterns (like loops) with calls to builtins (like memset). @@ -112,6 +148,64 @@ pub fn compile_codegen_unit( context.add_command_line_option("-fno-tree-loop-distribute-patterns"); } + if let Some(model) = tcx.sess.code_model() { + use rustc_target::spec::CodeModel; + + context.add_command_line_option(match model { + CodeModel::Tiny => "-mcmodel=tiny", + CodeModel::Small => "-mcmodel=small", + CodeModel::Kernel => "-mcmodel=kernel", + CodeModel::Medium => "-mcmodel=medium", + CodeModel::Large => "-mcmodel=large", + }); + } + + add_pic_option(&context, tcx.sess.relocation_model()); + + let target_cpu = gcc_util::target_cpu(tcx.sess); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); + } + + if tcx + .sess + .opts + .unstable_opts + .function_sections + .unwrap_or(tcx.sess.target.function_sections) + { + context.add_command_line_option("-ffunction-sections"); + context.add_command_line_option("-fdata-sections"); + } + + if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-vregs"); + } + if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-all"); + } + if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-tree-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-ipa-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { + context.set_dump_code_on_compile(true); + } + if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { + context.set_dump_initial_gimple(true); + } + if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { + context.set_dump_everything(true); + } + if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { + context.set_keep_intermediates(true); + } + if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { + context.add_driver_option("-v"); + } + // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); @@ -175,3 +269,24 @@ pub fn compile_codegen_unit( (module, cost) } + +pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { + match relocation_model { + rustc_target::spec::RelocModel::Static => { + context.add_command_line_option("-fno-pie"); + context.add_driver_option("-fno-pie"); + } + rustc_target::spec::RelocModel::Pic => { + context.add_command_line_option("-fPIC"); + // NOTE: we use both add_command_line_option and add_driver_option because the usage in + // this module (compile_codegen_unit) requires add_command_line_option while the usage + // in the back::write module (codegen) requires add_driver_option. + context.add_driver_option("-fPIC"); + } + rustc_target::spec::RelocModel::Pie => { + context.add_command_line_option("-fPIE"); + context.add_driver_option("-fPIE"); + } + model => eprintln!("Unsupported relocation model: {:?}", model), + } +} diff --git a/src/builder.rs b/src/builder.rs index 4096679ba0959..a407362638f10 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, Block, CType, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, - Type, UnaryOp, + BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, + UnaryOp, }; use rustc_abi as abi; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; @@ -36,6 +36,7 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; +use crate::diagnostics; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -84,7 +85,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size)); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); - let return_value = self.new_temp(func, self.location, previous_value.get_type()); + let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); self.llbb().add_assignment(self.location, previous_var, previous_value); self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue()); @@ -311,59 +312,34 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } - /// Shared implementation of `call` and `tail_call`. For tail call it is important that this - /// returns a bare call, and not the result assigned to a local, or the result of `add_eval`. - fn build_call( - &mut self, - typ: Type<'gcc>, - fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, - func: RValue<'gcc>, - args: &[RValue<'gcc>], - funclet: Option<&Funclet>, - must_tail: bool, - ) -> RValue<'gcc> { - // FIXME(antoyo): remove when having a proper API. - let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; - let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { - // FIXME(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet, must_tail) - } else { - // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet, must_tail) - }; - if let Some(_fn_abi) = fn_abi { - // FIXME(bjorn3): Apply function attributes - } - call - } - pub fn function_call( &mut self, func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, - must_tail: bool, ) -> RValue<'gcc> { let args = self.check_call("call", func, args); - let call = self.cx.context.new_call(self.location, func, &args); - if must_tail { - // Return the bare tail call, don't assign or `add_eval` it yet. - return call; - } - // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); let void_type = self.context.new_type::<()>(); let current_func = self.block.get_function(); if return_type != void_type { - let result = self.new_temp(current_func, self.location, return_type); - self.block.add_assignment(self.location, result, call); + let result = current_func.new_local( + self.location, + return_type, + format!("returnValue{}", self.next_value_counter()), + ); + self.block.add_assignment( + self.location, + result, + self.cx.context.new_call(self.location, func, &args), + ); result.to_rvalue() } else { - self.block.add_eval(self.location, call); + self.block + .add_eval(self.location, self.cx.context.new_call(self.location, func, &args)); // Return dummy value when not having return value. self.context.new_rvalue_zero(self.isize_type) } @@ -376,7 +352,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, - must_tail: bool, ) -> RValue<'gcc> { let func_ptr_type = { let func_ptr_type = func_ptr.get_type(); @@ -401,12 +376,6 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); - if must_tail { - // Return the bare tail call, don't assign or `add_eval` it yet. - let call = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); - return call; - } - // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = gcc_func.get_return_type(); @@ -423,7 +392,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { args_adjusted, orig_args, ); - let result = self.new_temp(current_func, self.location, return_value.get_type()); + let result = current_func.new_local( + self.location, + return_value.get_type(), + format!("ptrReturnValue{}", self.next_value_counter()), + ); self.block.add_assignment(self.location, result, return_value); result.to_rvalue() } else { @@ -445,16 +418,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.location, self.cx.context.new_call_through_ptr(self.location, func_ptr, &args), ); - // Return dummy value when not having return value, unless the intrinsic adapter - // needs to synthesize a non-void LLVM-level result from out-parameters. - llvm::adjust_intrinsic_return_value( - self, - self.context.new_rvalue_zero(self.isize_type), - &func_name, - &args, - args_adjusted, - orig_args, - ) + // Return dummy value when not having return value. + self.context.new_rvalue_zero(self.isize_type) } } @@ -469,7 +434,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let return_type = self.context.new_type::(); let current_func = self.block.get_function(); // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects. - let result = self.new_temp(current_func, self.location, return_type); + let result = current_func.new_local( + self.location, + return_type, + format!("overflowReturnValue{}", self.next_value_counter()), + ); self.block.add_assignment( self.location, result, @@ -601,18 +570,6 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { default_block: Block<'gcc>, cases: impl ExactSizeIterator)>, ) { - // A switch with no cases is equivalent to an unconditional jump to the - // default block. Such a `SwitchInt` (one with only an `otherwise` target) - // is normally simplified into a `goto`, but `-Z mir-preserve-ub` keeps it, - // so it can reach here with e.g. the `bool` discriminant produced by a - // range-pattern comparison. `gcc_jit_block_end_with_switch` rejects a - // discriminant that is not of integer type, so emit a plain jump instead - // of a (pointless) switch. - if cases.len() == 0 { - self.block.end_with_jump(self.location, default_block); - return; - } - let mut gcc_cases = vec![]; let typ = self.val_ty(value); // FIXME(FractalFir): This is a workaround for a libgccjit limitation. @@ -659,7 +616,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; - let return_value = self.new_temp(self.current_func(), self.location, call.get_type()); + let return_value = + self.current_func().new_local(self.location, call.get_type(), "invokeResult"); try_block.add_assignment(self.location, return_value, call); @@ -706,7 +664,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { - let return_value = self.new_temp(self.current_func(), self.location, return_type); + let return_value = + self.current_func().new_local(self.location, return_type, "unreachableReturn"); self.block.end_with_return(self.location, return_value) } } @@ -1025,7 +984,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. let deref = ptr.dereference(self.location).to_rvalue(); - let loaded_value = self.new_temp(function, self.location, aligned_type); + let loaded_value = function.new_local( + self.location, + aligned_type, + format!("loadedValue{}", self.next_value_counter()), + ); block.add_assignment(self.location, loaded_value, deref); loaded_value.to_rvalue() } @@ -1143,7 +1106,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.new_temp(self.llbb().get_function(), self.location, ptr_type); + let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var"); let current_val = current.to_rvalue(); self.assign(current, start); @@ -1508,7 +1471,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { mut else_val: RValue<'gcc>, ) -> RValue<'gcc> { let func = self.current_func(); - let variable = self.new_temp(func, self.location, then_val.get_type()); + let variable = func.new_local(self.location, then_val.get_type(), "selectVar"); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1530,10 +1493,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { variable.to_rvalue() } - fn va_arg(&mut self, list: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { - let va_list_type = self.context.new_c_type(CType::VaList); - let list = self.context.new_cast(self.location, list, va_list_type.make_pointer()); - self.context.new_va_arg(self.location, list, ty) + fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { + unimplemented!(); } #[cfg(feature = "master")] @@ -1654,9 +1615,11 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self - .new_temp(self.current_func(), self.location, self.u8_type.make_pointer()) + .current_func() + .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") .to_rvalue(); - let value2 = self.new_temp(self.current_func(), self.location, self.i32_type).to_rvalue(); + let value2 = + self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue(); (value1, value2) } @@ -1724,7 +1687,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.new_temp(self.current_func(), self.location, self.bool_type); + let success_var = self.current_func().new_local(self.location, self.bool_type, "success"); self.llbb().add_assignment(self.location, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) @@ -1813,34 +1776,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { - self.build_call(typ, fn_abi, func, args, funclet, false) + // FIXME(antoyo): remove when having a proper API. + let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; + let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // FIXME(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); + self.function_call(func, args, funclet) + } else { + // If it's a not function that was defined, it's a function pointer. + self.function_ptr_call(typ, fn_abi, func, args, funclet) + }; + if let Some(_fn_abi) = fn_abi { + // FIXME(bjorn3): Apply function attributes + } + call } fn tail_call( &mut self, - llty: Self::Type, + _llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, - fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - llfn: Self::Value, - args: &[Self::Value], - funclet: Option<&Self::Funclet>, + _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + _llfn: Self::Value, + _args: &[Self::Value], + _funclet: Option<&Self::Funclet>, _instance: Option>, ) { - // `emit_call` returns a bare call for here, it has not been assigned or passed to add_eval. - let call = self.build_call(llty, Some(fn_abi), llfn, args, funclet, true); - call.set_require_tail_call(true); - - let return_type = self.current_func().get_return_type(); - let void_type = self.context.new_type::<()>(); - - if return_type == void_type { - // For a void return the call is emitted as its own statement, immediately - // followed by a void return, so the tail call sits in tail position. - self.llbb().add_eval(self.location, call); - self.ret_void(); - } else { - self.ret(call) - } + // FIXME: implement support for explicit tail calls like rustc_codegen_llvm. + self.tcx.dcx().emit_fatal(diagnostics::ExplicitTailCallsUnsupported); } fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { @@ -2425,31 +2388,11 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.bitcast_if_needed(res, result_type) } - /// Create a temporary variable. - /// - /// GCC will use more stack space with a local variable than with a temporary variable in debug mode, - /// so in order to avoid having the stack probe test fail in CI, we avoid creating local variables for temporaries. - pub fn new_temp( - &self, - function: Function<'gcc>, - location: Option>, - typ: Type<'gcc>, - ) -> LValue<'gcc> { - #[cfg(feature = "master")] - { - function.new_temp(location, typ) - } - #[cfg(not(feature = "master"))] - { - function.new_local(location, typ, format!("temp{}", self.next_value_counter())) - } - } - // GCC doesn't like deeply nested expressions. // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested // expressions and GCC will use much less RAM. fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> { - let var = self.new_temp(self.current_func(), self.location, value.get_type()); + let var = self.current_func().new_local(self.location, value.get_type(), "opResult"); self.llbb().add_assignment(self.location, var, value); var.to_rvalue() } diff --git a/src/callee.rs b/src/callee.rs index d3f412180da55..00f095ed54371 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -70,7 +70,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(sym, fn_abi); - attributes::from_fn_attrs(cx, func, instance, Some(fn_abi)); + attributes::from_fn_attrs(cx, func, instance); #[cfg(feature = "master")] { diff --git a/src/common.rs b/src/common.rs index d979c8b7ed094..6bd186f1121fc 100644 --- a/src/common.rs +++ b/src/common.rs @@ -143,9 +143,9 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); - let (arrays, remainder) = bytes.as_chunks::<8>(); - debug_assert!(remainder.is_empty()); - let elements: Vec<_> = arrays + let elements: Vec<_> = bytes + .as_chunks::<8>() + .0 .iter() .map(|&arr| { context.new_rvalue_from_long( @@ -170,9 +170,9 @@ pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> let context = &cx.context; let byte_type = context.new_type::(); let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); - let (arrays, remainder) = bytes.as_chunks::<4>(); - debug_assert!(remainder.is_empty()); - let elements: Vec<_> = arrays + let elements: Vec<_> = bytes + .as_chunks::<4>() + .0 .iter() .map(|&arr| { context.new_rvalue_from_int( diff --git a/src/consts.rs b/src/consts.rs index 5ebdf91fe20b6..42ff930968501 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,6 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue, VarAttribute, Visibility}; -use gccjit::{Function, GlobalKind, LValue, RValue, Type}; +use gccjit::{FnAttribute, VarAttribute, Visibility}; +use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, @@ -160,52 +160,29 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { } // Wasm statics with custom link sections get special treatment as they - // go into custom sections of the wasm executable. The exception to this - // is the `.init_array` section which are treated specially by the wasm linker. - if self.tcx.sess.target.is_like_wasm - && attrs - .link_section - .map(|link_section| !link_section.as_str().starts_with(".init_array")) - .unwrap_or(true) - { + // go into custom sections of the wasm executable. + if self.tcx.sess.target.is_like_wasm { if let Some(_section) = attrs.link_section { unimplemented!(); } - } else if let Some(_section) = attrs.link_section { - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Section(_section.as_str())); + } else { + // FIXME(antoyo): set link section. } - if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { - // To copy the conditions from the LLVM backend... - assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); - self.add_used_global(global); - } - if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { - // To copy the conditions from the LLVM backend... - assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); - self.add_retained_global(global); + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) + || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) + { + self.add_used_global(global.to_rvalue()); } } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - /// Need to have the `SHF_GNU_RETAIN` flag, so needs to use the `retain` attribute instead of - /// `used`. This is used by `#[used(linker)]`. - pub fn add_retained_global(&mut self, global: LValue<'gcc>) { - // We need to add the `used` C attribute in any case. - self.add_used_global(global); - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Retain); - } - - /// This is used by `#[used(compiler)]` and `#[used]`. - pub fn add_used_global(&mut self, _global: LValue<'gcc>) { - #[cfg(feature = "master")] - _global.add_attribute(VarAttribute::Used); + /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. + pub fn add_used_global(&mut self, _global: RValue<'gcc>) { + // FIXME(antoyo) } - // No need to have the `SHF_GNU_RETAIN` flag, so `used` attribute is ok. #[cfg_attr(not(feature = "master"), expect(unused_variables))] pub fn add_used_function(&self, function: Function<'gcc>) { #[cfg(feature = "master")] diff --git a/src/declare.rs b/src/declare.rs index 9bf57fbf75bc0..4174eebcf7b02 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -1,12 +1,12 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue, VarAttribute}; +use gccjit::{FnAttribute, ToRValue}; use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::abi::FnAbiGccExt; +use crate::abi::{FnAbiGcc, FnAbiGccExt}; use crate::context::CodegenCx; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -24,9 +24,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Section(link_section.as_str())); - #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } global @@ -76,9 +73,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Section(link_section.as_str())); - #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); @@ -116,22 +110,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { - let fn_abi_gcc = fn_abi.gcc_type(self); + let FnAbiGcc { + return_type, + arguments_type, + is_c_variadic, + on_stack_param_indices, + #[cfg(feature = "master")] + fn_attributes, + } = fn_abi.gcc_type(self); #[cfg(feature = "master")] let conv = fn_abi.gcc_cconv(self); #[cfg(not(feature = "master"))] let conv = None; - let func = declare_raw_fn( - self, - name, - conv, - fn_abi_gcc.return_type, - &fn_abi_gcc.arguments_type, - fn_abi_gcc.is_c_variadic, - ); - self.on_stack_function_params.borrow_mut().insert(func, fn_abi_gcc.on_stack_param_indices); + let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); + self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); #[cfg(feature = "master")] - for fn_attr in fn_abi_gcc.fn_attributes { + for fn_attr in fn_attributes { func.add_attribute(fn_attr); } func diff --git a/src/diagnostics.rs b/src/diagnostics.rs index 67723ebd2f30b..de633d3bdde79 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -20,6 +20,10 @@ pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } +#[derive(Diagnostic)] +#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] +pub(crate) struct ExplicitTailCallsUnsupported; + #[derive(Diagnostic)] #[diag("asm contains a NUL byte")] pub(crate) struct NulBytesInAsm { diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4d7f2cdbb92ed..a95b4da28eb63 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,14 +1,10 @@ -use std::collections::HashSet; -use std::env; - -use gccjit::Context; #[cfg(feature = "master")] -use gccjit::Version; +use gccjit::Context; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::Session; use rustc_session::config::NATIVE_CPU; -use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector}; +use rustc_target::spec::Arch; fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -140,147 +136,3 @@ pub fn target_cpu(sess: &Session) -> &str { None => handle_native(sess.target.cpu.as_ref()), } } - -pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { - let context = Context::default(); - if matches!(sess.target.arch, Arch::X86 | Arch::X86_64) { - context.add_command_line_option("-masm=intel"); - } - #[cfg(feature = "master")] - { - context.set_special_chars_allowed_in_func_names("$.*"); - let version = Version::get(); - let version = format!("{}.{}.{}", version.major, version.minor, version.patch); - context.set_output_ident(&format!( - "rustc version {} with libgccjit {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - version, - )); - } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); - - if sess.panic_strategy().unwinds() { - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); - } - - let disabled_features: HashSet<_> = sess - .opts - .cg - .target_feature - .split(',') - .filter(|feature| feature.starts_with('-')) - .map(|string| &string[1..]) - .collect(); - - if !disabled_features.contains("avx") && sess.target.arch == Arch::X86_64 { - // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for - // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. - // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. - context.add_command_line_option("-mavx"); - } - - for arg in &sess.opts.cg.llvm_args { - context.add_command_line_option(arg); - } - // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. - context.add_command_line_option("-fno-var-tracking-assignments"); - // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). - context.add_command_line_option("-fno-semantic-interposition"); - // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). - context.add_command_line_option("-fno-strict-aliasing"); - // NOTE: Rust relies on LLVM doing wrapping on overflow. - context.add_command_line_option("-fwrapv"); - - if let Some(model) = sess.code_model() { - use rustc_target::spec::CodeModel; - - context.add_command_line_option(match model { - CodeModel::Tiny => "-mcmodel=tiny", - CodeModel::Small => "-mcmodel=small", - CodeModel::Kernel => "-mcmodel=kernel", - CodeModel::Medium => "-mcmodel=medium", - CodeModel::Large => "-mcmodel=large", - }); - } - - match sess.stack_protector() { - StackProtector::All => context.add_command_line_option("-fstack-protector-all"), - StackProtector::Strong => context.add_command_line_option("-fstack-protector-strong"), - StackProtector::Basic => context.add_command_line_option("-fstack-protector"), - StackProtector::None => (), - } - - match sess.target.stack_probes { - StackProbeType::None => (), - StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { - context.add_command_line_option("-fstack-clash-protection") - } - // FIXME(antoyo): We should define the stack probe symbol to be __rust_probestack, but it seems GCC cannot do that. - StackProbeType::Call => (), - }; - - add_pic_option(&context, sess.relocation_model()); - - let target_cpu = target_cpu(sess); - if target_cpu != "generic" { - context.add_command_line_option(format!("-march={}", target_cpu)); - } - - if sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections) { - context.add_command_line_option("-ffunction-sections"); - context.add_command_line_option("-fdata-sections"); - } - - if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-vregs"); - } - if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-all"); - } - if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-tree-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-ipa-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { - context.set_dump_code_on_compile(true); - } - if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { - context.set_dump_initial_gimple(true); - } - if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { - context.set_dump_everything(true); - } - if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { - context.set_keep_intermediates(true); - } - if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { - context.add_driver_option("-v"); - } - - context -} - -pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { - match relocation_model { - rustc_target::spec::RelocModel::Static => { - context.add_command_line_option("-fno-pie"); - context.add_driver_option("-fno-pie"); - } - rustc_target::spec::RelocModel::Pic => { - context.add_command_line_option("-fPIC"); - // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // base (compile_codegen_unit) requires add_command_line_option while the usage - // in the back::write module (codegen) requires add_driver_option. - context.add_driver_option("-fPIC"); - } - rustc_target::spec::RelocModel::Pie => { - context.add_command_line_option("-fPIE"); - context.add_driver_option("-fPIE"); - } - model => eprintln!("Unsupported relocation model: {:?}", model), - } -} diff --git a/src/int.rs b/src/int.rs index 0c9a755694577..dfae4eceebe44 100644 --- a/src/int.rs +++ b/src/int.rs @@ -432,7 +432,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // This algorithm is based on compiler-rt's __cmpti2: // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 - let result = self.new_temp(self.current_func(), self.location, self.int_type); + let result = self.current_func().new_local(self.location, self.int_type, "icmp_result"); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); @@ -462,15 +462,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); } - IntPredicate::IntSGT - | IntPredicate::IntSGE - | IntPredicate::IntSLT - | IntPredicate::IntSLE => { - let signed_type = native_int_type.to_signed(self.cx); - lhs_high = self.context.new_cast(self.location, lhs_high, signed_type); - rhs_high = self.context.new_cast(self.location, rhs_high, signed_type); - } - IntPredicate::IntEQ | IntPredicate::IntNE => (), + // FIXME(antoyo): we probably need to handle signed comparison for unsigned + // integers. + _ => (), } let condition = self.context.new_comparison( @@ -608,17 +602,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { rhs = self.context.new_cast(self.location, rhs, unsigned_type); } } - IntPredicate::IntSGT - | IntPredicate::IntSGE - | IntPredicate::IntSLT - | IntPredicate::IntSLE => { - if !a_type.is_vector() { - let signed_type = a_type.to_signed(self.cx); - lhs = self.context.new_cast(self.location, lhs, signed_type); - rhs = self.context.new_cast(self.location, rhs, signed_type); - } - } - IntPredicate::IntEQ | IntPredicate::IntNE => (), + // FIXME(antoyo): we probably need to handle signed comparison for unsigned + // integers. + _ => (), } self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) } @@ -876,7 +862,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } - // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/1a99c2aa295bb2d507fa0e67a3b5eef64fba92a0/libm/src/math/support/int_traits.rs#L485 instead? + // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 1856c2468616d..3c1698df6dec2 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,7 +24,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", - "prefetch.ir" => "__builtin_arm_prefetch_ir", "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", @@ -54,7 +53,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "alignbyte" => "__builtin_amdgcn_alignbyte", "ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32", "ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32", - "asyncmark" => "__builtin_amdgcn_asyncmark", "buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1", "buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc", "buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol", @@ -272,7 +270,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fdot2c.f32.bf16" => "__builtin_amdgcn_fdot2c_f32_bf16", "flat.prefetch" => "__builtin_amdgcn_flat_prefetch", "fmul.legacy" => "__builtin_amdgcn_fmul_legacy", - "global.load.async.lds" => "__builtin_amdgcn_global_load_async_lds", "global.load.async.to.lds.b128" => { "__builtin_amdgcn_global_load_async_to_lds_b128" } @@ -364,7 +361,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4", "perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4", "perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4", + "permlane.bcast" => "__builtin_amdgcn_permlane_bcast", + "permlane.down" => "__builtin_amdgcn_permlane_down", "permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen", + "permlane.up" => "__builtin_amdgcn_permlane_up", + "permlane.xor" => "__builtin_amdgcn_permlane_xor", "permlane16.var" => "__builtin_amdgcn_permlane16_var", "permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16", @@ -374,9 +375,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "prng.b32" => "__builtin_amdgcn_prng_b32", "qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "queue.ptr" => "__builtin_amdgcn_queue_ptr", - "raw.ptr.buffer.load.async.lds" => { - "__builtin_amdgcn_raw_ptr_buffer_load_async_lds" - } "raw.ptr.buffer.load.lds" => "__builtin_amdgcn_raw_ptr_buffer_load_lds", "rcp.legacy" => "__builtin_amdgcn_rcp_legacy", "rsq.legacy" => "__builtin_amdgcn_rsq_legacy", @@ -388,7 +386,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", "s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", "s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", - "s.bitreplicate" => "__builtin_amdgcn_s_bitreplicate", "s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data", "s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier", "s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", @@ -415,7 +412,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.ttracedata" => "__builtin_amdgcn_s_ttracedata", "s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "s.wait.asynccnt" => "__builtin_amdgcn_s_wait_asynccnt", - "s.wait.event" => "__builtin_amdgcn_s_wait_event", "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", @@ -466,18 +462,16 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "smfmac.i32.16x16x64.i8" => "__builtin_amdgcn_smfmac_i32_16x16x64_i8", "smfmac.i32.32x32x32.i8" => "__builtin_amdgcn_smfmac_i32_32x32x32_i8", "smfmac.i32.32x32x64.i8" => "__builtin_amdgcn_smfmac_i32_32x32x64_i8", - "struct.ptr.buffer.load.async.lds" => { - "__builtin_amdgcn_struct_ptr_buffer_load_async_lds" - } "struct.ptr.buffer.load.lds" => "__builtin_amdgcn_struct_ptr_buffer_load_lds", "sudot4" => "__builtin_amdgcn_sudot4", "sudot8" => "__builtin_amdgcn_sudot8", "tensor.load.to.lds" => "__builtin_amdgcn_tensor_load_to_lds", + "tensor.load.to.lds.d2" => "__builtin_amdgcn_tensor_load_to_lds_d2", "tensor.store.from.lds" => "__builtin_amdgcn_tensor_store_from_lds", + "tensor.store.from.lds.d2" => "__builtin_amdgcn_tensor_store_from_lds_d2", "udot2" => "__builtin_amdgcn_udot2", "udot4" => "__builtin_amdgcn_udot4", "udot8" => "__builtin_amdgcn_udot8", - "wait.asyncmark" => "__builtin_amdgcn_wait_asyncmark", "wave.barrier" => "__builtin_amdgcn_wave_barrier", "wavefrontsize" => "__builtin_amdgcn_wavefrontsize", "workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", @@ -4850,11 +4844,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", - "add.rn.ftz.sat.f16" => "__nvvm_add_rn_ftz_sat_f16", - "add.rn.ftz.sat.v2f16" => "__nvvm_add_rn_ftz_sat_v2f16", "add.rn.sat.f" => "__nvvm_add_rn_sat_f", - "add.rn.sat.f16" => "__nvvm_add_rn_sat_f16", - "add.rn.sat.v2f16" => "__nvvm_add_rn_sat_v2f16", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", @@ -5073,10 +5063,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", "fma.rn.f" => "__nvvm_fma_rn_f", + "fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", + "fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", + "fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", + "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", + "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", + "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", + "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", + "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", @@ -5197,10 +5195,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "mul.rn.d" => "__nvvm_mul_rn_d", "mul.rn.f" => "__nvvm_mul_rn_f", "mul.rn.ftz.f" => "__nvvm_mul_rn_ftz_f", - "mul.rn.ftz.sat.f16" => "__nvvm_mul_rn_ftz_sat_f16", - "mul.rn.ftz.sat.v2f16" => "__nvvm_mul_rn_ftz_sat_v2f16", - "mul.rn.sat.f16" => "__nvvm_mul_rn_sat_f16", - "mul.rn.sat.v2f16" => "__nvvm_mul_rn_sat_v2f16", "mul.rp.d" => "__nvvm_mul_rp_d", "mul.rp.f" => "__nvvm_mul_rp_f", "mul.rp.ftz.f" => "__nvvm_mul_rp_ftz_f", @@ -5833,10 +5827,8 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vmuleuh" => "__builtin_altivec_vmuleuh", "altivec.vmuleuw" => "__builtin_altivec_vmuleuw", "altivec.vmulhsd" => "__builtin_altivec_vmulhsd", - "altivec.vmulhsh" => "__builtin_altivec_vmulhsh", "altivec.vmulhsw" => "__builtin_altivec_vmulhsw", "altivec.vmulhud" => "__builtin_altivec_vmulhud", - "altivec.vmulhuh" => "__builtin_altivec_vmulhuh", "altivec.vmulhuw" => "__builtin_altivec_vmulhuw", "altivec.vmulosb" => "__builtin_altivec_vmulosb", "altivec.vmulosd" => "__builtin_altivec_vmulosd", @@ -5920,45 +5912,22 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vsum4shs" => "__builtin_altivec_vsum4shs", "altivec.vsum4ubs" => "__builtin_altivec_vsum4ubs", "altivec.vsumsws" => "__builtin_altivec_vsumsws", - "altivec.vucmprhb" => "__builtin_altivec_vucmprhb", - "altivec.vucmprhh" => "__builtin_altivec_vucmprhh", - "altivec.vucmprhn" => "__builtin_altivec_vucmprhn", - "altivec.vucmprlb" => "__builtin_altivec_vucmprlb", - "altivec.vucmprlh" => "__builtin_altivec_vucmprlh", - "altivec.vucmprln" => "__builtin_altivec_vucmprln", "altivec.vupkhpx" => "__builtin_altivec_vupkhpx", "altivec.vupkhsb" => "__builtin_altivec_vupkhsb", "altivec.vupkhsh" => "__builtin_altivec_vupkhsh", - "altivec.vupkhsntob" => "__builtin_altivec_vupkhsntob", "altivec.vupkhsw" => "__builtin_altivec_vupkhsw", - "altivec.vupkint4tobf16" => "__builtin_altivec_vupkint4tobf16", - "altivec.vupkint4tofp32" => "__builtin_altivec_vupkint4tofp32", - "altivec.vupkint8tobf16" => "__builtin_altivec_vupkint8tobf16", - "altivec.vupkint8tofp32" => "__builtin_altivec_vupkint8tofp32", "altivec.vupklpx" => "__builtin_altivec_vupklpx", "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", - "altivec.vupklsntob" => "__builtin_altivec_vupklsntob", "altivec.vupklsw" => "__builtin_altivec_vupklsw", "amo.ldat" => "__builtin_amo_ldat", - "amo.ldat.cond" => "__builtin_amo_ldat_cond", - "amo.ldat.csne" => "__builtin_amo_ldat_csne", "amo.lwat" => "__builtin_amo_lwat", - "amo.lwat.cond" => "__builtin_amo_lwat_cond", - "amo.lwat.csne" => "__builtin_amo_lwat_csne", - "amo.stdat" => "__builtin_amo_stdat", - "amo.stwat" => "__builtin_amo_stwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", "bcdsetsign" => "__builtin_ppc_bcdsetsign", - "bcdshift" => "__builtin_ppc_bcdshift", - "bcdshiftround" => "__builtin_ppc_bcdshiftround", "bcdsub" => "__builtin_ppc_bcdsub", "bcdsub.p" => "__builtin_ppc_bcdsub_p", - "bcdtruncate" => "__builtin_ppc_bcdtruncate", - "bcdunsignedshift" => "__builtin_ppc_bcdunsignedshift", - "bcdunsignedtruncate" => "__builtin_ppc_bcdunsignedtruncate", "bpermd" => "__builtin_bpermd", "cbcdtd" => "__builtin_cbcdtd", "cbcdtdd" => "__builtin_ppc_cbcdtd", @@ -6157,27 +6126,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", - "xsaddaddsuqm" => "__builtin_xsaddaddsuqm", - "xsaddadduqm" => "__builtin_xsaddadduqm", - "xsaddsubsuqm" => "__builtin_xsaddsubsuqm", - "xsaddsubuqm" => "__builtin_xsaddsubuqm", - "xsmerge2t1uqm" => "__builtin_xsmerge2t1uqm", - "xsmerge2t2uqm" => "__builtin_xsmerge2t2uqm", - "xsmerge2t3uqm" => "__builtin_xsmerge2t3uqm", - "xsmerge3t1uqm" => "__builtin_xsmerge3t1uqm", - "xsrebase2t1uqm" => "__builtin_xsrebase2t1uqm", - "xsrebase2t2uqm" => "__builtin_xsrebase2t2uqm", - "xsrebase2t3uqm" => "__builtin_xsrebase2t3uqm", - "xsrebase2t4uqm" => "__builtin_xsrebase2t4uqm", - "xsrebase3t1uqm" => "__builtin_xsrebase3t1uqm", - "xsrebase3t2uqm" => "__builtin_xsrebase3t2uqm", - "xsrebase3t3uqm" => "__builtin_xsrebase3t3uqm", - "xxmulmul" => "__builtin_xxmulmul", - "xxmulmulhiadd" => "__builtin_xxmulmulhiadd", - "xxmulmulloadd" => "__builtin_xxmulmulloadd", - "xxssumudm" => "__builtin_xxssumudm", - "xxssumudmc" => "__builtin_xxssumudmc", - "xxssumudmcext" => "__builtin_xxssumudmcext", "zoned2packed" => "__builtin_ppc_zoned2packed", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } @@ -6440,13 +6388,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { // spv "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", - "subgroup.ballot" => "__builtin_spirv_subgroup_ballot", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { "__builtin_spirv_subgroup_local_invocation_id" } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", + "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -8713,6 +8661,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bmi.bextr.64" => "__builtin_ia32_bextr_u64", "bmi.bzhi.32" => "__builtin_ia32_bzhi_si", "bmi.bzhi.64" => "__builtin_ia32_bzhi_di", + "bmi.pdep.32" => "__builtin_ia32_pdep_si", + "bmi.pdep.64" => "__builtin_ia32_pdep_di", + "bmi.pext.32" => "__builtin_ia32_pext_si", + "bmi.pext.64" => "__builtin_ia32_pext_di", "cldemote" => "__builtin_ia32_cldemote", "clflushopt" => "__builtin_ia32_clflushopt", "clrssbsy" => "__builtin_ia32_clrssbsy", diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 6ad19d5af095e..41efe3e8209bf 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,7 +1,5 @@ use std::borrow::Cow; -#[cfg(feature = "master")] -use gccjit::TypeAttribute; use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::BuilderMethods; @@ -25,7 +23,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7], ); #[cfg(feature = "master")] - encode_type.as_type().add_attribute(TypeAttribute::Packed); + encode_type.as_type().set_packed(); (encode_type.as_type(), field1, field2) } @@ -47,7 +45,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8], ); #[cfg(feature = "master")] - encode_type.as_type().add_attribute(TypeAttribute::Packed); + encode_type.as_type().set_packed(); (encode_type.as_type(), field1, field2) } @@ -60,7 +58,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); #[cfg(feature = "master")] - typ.add_attribute(TypeAttribute::Packed); + typ.set_packed(); (typ, field1, field2) } @@ -83,7 +81,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); #[cfg(feature = "master")] - aes_output_type.as_type().add_attribute(TypeAttribute::Packed); + aes_output_type.as_type().set_packed(); (aes_output_type.as_type(), field1, field2) } @@ -480,26 +478,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(variable.get_address(None)); args = new_args.into(); } - "__builtin_ia32_2intersectd128" - | "__builtin_ia32_2intersectq128" - | "__builtin_ia32_2intersectd256" - | "__builtin_ia32_2intersectq256" - | "__builtin_ia32_2intersectd512" - | "__builtin_ia32_2intersectq512" => { - let old_args = args.to_vec(); - let mut new_args = vec![]; - let arg1_type = gcc_func.get_param_type(0); - let first_mask = - builder.current_func().new_local(None, arg1_type, "return_2intersect_arg1"); - let arg2_type = gcc_func.get_param_type(1); - let second_mask = - builder.current_func().new_local(None, arg2_type, "return_2intersect_arg2"); - new_args.push(first_mask.get_address(None)); - new_args.push(second_mask.get_address(None)); - new_args.push(old_args[0]); - new_args.push(old_args[1]); - args = new_args.into(); - } "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask" | "__builtin_ia32_vpermt2varqi128_mask" @@ -511,23 +489,6 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } - "__builtin_ia32_fpclassph128_mask" - | "__builtin_ia32_fpclassph256_mask" - | "__builtin_ia32_fpclassph512_mask" - | "__builtin_ia32_fpclasspd128_mask" - | "__builtin_ia32_fpclassps128_mask" - | "__builtin_ia32_fpclasspd256_mask" - | "__builtin_ia32_fpclassps256_mask" - | "__builtin_ia32_fpclasspd512_mask" - | "__builtin_ia32_fpclassps512_mask" - | "__builtin_ia32_vpshufbitqmb128_mask" - | "__builtin_ia32_vpshufbitqmb256_mask" - | "__builtin_ia32_vpshufbitqmb512_mask" => { - let new_args = args.to_vec(); - let arg3_type = gcc_func.get_param_type(2); - let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); - args = vec![new_args[0], new_args[1], minus_one].into(); - } "__builtin_ia32_xrstor" | "__builtin_ia32_xrstor64" | "__builtin_ia32_xsavec" @@ -879,7 +840,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( "__builtin_ia32_rdrand64_step" => { let random_number = args[0].dereference(None).to_rvalue(); let success_variable = - builder.new_temp(builder.current_func(), None, return_value.get_type()); + builder.current_func().new_local(None, return_value.get_type(), "success"); builder.llbb().add_assignment(None, success_variable, return_value); let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); @@ -893,25 +854,6 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( &[random_number, success_variable.to_rvalue()], ); } - "__builtin_ia32_2intersectd128" - | "__builtin_ia32_2intersectq128" - | "__builtin_ia32_2intersectd256" - | "__builtin_ia32_2intersectq256" - | "__builtin_ia32_2intersectd512" - | "__builtin_ia32_2intersectq512" => { - let first_mask = args[0].dereference(None).to_rvalue(); - let second_mask = args[1].dereference(None).to_rvalue(); - let field1 = builder.context.new_field(None, first_mask.get_type(), "first_mask"); - let field2 = builder.context.new_field(None, second_mask.get_type(), "second_mask"); - let struct_type = - builder.context.new_struct_type(None, "vp2intersect_result", &[field1, field2]); - return_value = builder.context.new_struct_constructor( - None, - struct_type.as_type(), - None, - &[first_mask, second_mask], - ); - } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); @@ -1240,9 +1182,6 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", "llvm.x86.avx512.mask.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", "llvm.x86.avx512.mask.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", - "llvm.x86.avx512.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", - "llvm.x86.avx512.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", - "llvm.x86.avx512.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", "llvm.x86.avx512.mask.ucmp.w.512" => "__builtin_ia32_ucmpw512_mask", "llvm.x86.avx512.mask.ucmp.w.256" => "__builtin_ia32_ucmpw256_mask", "llvm.x86.avx512.mask.ucmp.w.128" => "__builtin_ia32_ucmpw128_mask", @@ -1400,20 +1339,11 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf", - "llvm.x86.vcvtneps2bf16128" => "__builtin_ia32_cvtneps2bf16_v4sf", - "llvm.x86.vcvtneps2bf16256" => "__builtin_ia32_cvtneps2bf16_v8sf", - "llvm.x86.avx512bf16.mask.cvtneps2bf16.128" => "__builtin_ia32_cvtneps2bf16_v4sf_mask", "llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf", "llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf", "llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf", "llvm.x86.avx512bf16.dpbf16ps.256" => "__builtin_ia32_dpbf16ps_v8sf", "llvm.x86.avx512bf16.dpbf16ps.512" => "__builtin_ia32_dpbf16ps_v16sf", - "llvm.x86.avx512.vp2intersect.d.128" => "__builtin_ia32_2intersectd128", - "llvm.x86.avx512.vp2intersect.q.128" => "__builtin_ia32_2intersectq128", - "llvm.x86.avx512.vp2intersect.d.256" => "__builtin_ia32_2intersectd256", - "llvm.x86.avx512.vp2intersect.q.256" => "__builtin_ia32_2intersectq256", - "llvm.x86.avx512.vp2intersect.d.512" => "__builtin_ia32_2intersectd512", - "llvm.x86.avx512.vp2intersect.q.512" => "__builtin_ia32_2intersectq512", "llvm.x86.pclmulqdq.512" => "__builtin_ia32_vpclmulqdq_v8di", "llvm.x86.pclmulqdq.256" => "__builtin_ia32_vpclmulqdq_v4di", "llvm.x86.avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", @@ -1647,79 +1577,38 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", - "llvm.x86.avx512fp16.fpclass.ph.128" => "__builtin_ia32_fpclassph128_mask", - "llvm.x86.avx512fp16.mask.cmp.ph.128" => "__builtin_ia32_cmpph128_mask", - "llvm.x86.avx512fp16.fpclass.ph.256" => "__builtin_ia32_fpclassph256_mask", - "llvm.x86.avx512fp16.fpclass.ph.512" => "__builtin_ia32_fpclassph512_mask", - "llvm.x86.avx512fp16.mask.cmp.ph.256" => "__builtin_ia32_cmpph256_mask", - "llvm.x86.avx512fp16.mask.cmp.ph.512" => "__builtin_ia32_cmpph512_mask_round", - "llvm.x86.avx512.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", - "llvm.x86.avx512.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", - "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", - "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", - "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", - "llvm.x86.avx512.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.sttilecfg" => "__builtin_trap", "llvm.x86.tileloadd64" => "__builtin_trap", - "llvm.x86.tileloadd64.internal" => "__builtin_trap", "llvm.x86.tilerelease" => "__builtin_trap", "llvm.x86.tilestored64" => "__builtin_trap", - "llvm.x86.tilestored64.internal" => "__builtin_trap", "llvm.x86.tileloaddrs64" => "__builtin_trap", - "llvm.x86.tileloaddrs64.internal" => "__builtin_trap", "llvm.x86.tileloaddt164" => "__builtin_trap", - "llvm.x86.tileloaddt164.internal" => "__builtin_trap", "llvm.x86.tileloaddrst164" => "__builtin_trap", - "llvm.x86.tileloaddrst164.internal" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", - "llvm.x86.tilezero.internal" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", - "llvm.x86.tilemovrow.internal" => "__builtin_trap", "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", - "llvm.x86.tdpbhf8ps.internal" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", - "llvm.x86.tdphbf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", - "llvm.x86.tdpbf8ps.internal" => "__builtin_trap", "llvm.x86.tdphf8ps" => "__builtin_trap", - "llvm.x86.tdphf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf16ps" => "__builtin_trap", - "llvm.x86.tdpbf16ps.internal" => "__builtin_trap", "llvm.x86.tdpbssd" => "__builtin_trap", - "llvm.x86.tdpbssd.internal" => "__builtin_trap", "llvm.x86.tdpbsud" => "__builtin_trap", - "llvm.x86.tdpbsud.internal" => "__builtin_trap", "llvm.x86.tdpbusd" => "__builtin_trap", - "llvm.x86.tdpbusd.internal" => "__builtin_trap", "llvm.x86.tdpbuud" => "__builtin_trap", - "llvm.x86.tdpbuud.internal" => "__builtin_trap", "llvm.x86.tdpfp16ps" => "__builtin_trap", - "llvm.x86.tdpfp16ps.internal" => "__builtin_trap", "llvm.x86.tmmultf32ps" => "__builtin_trap", - "llvm.x86.tmmultf32ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phh" => "__builtin_trap", - "llvm.x86.tcvtrowps2phh.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", - "llvm.x86.tcvtrowps2phl.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", - "llvm.x86.tcvtrowd2ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16h.internal" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16l.internal" => "__builtin_trap", - "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", - "llvm.x86.tcmmimfp16ps.internal" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", - "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => map_arch_intrinsic(name), diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index bbf5acf702e21..09ad3254e5714 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -95,6 +95,7 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", + sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -117,7 +118,12 @@ fn get_simple_function_f128<'gcc, 'tcx>( let func_name = match name { sym::ceilf128 => "ceilf128", sym::fabs => "fabsf128", + sym::expf128 => "expf128", + sym::exp2f128 => "exp2f128", sym::floorf128 => "floorf128", + sym::logf128 => "logf128", + sym::log2f128 => "log2f128", + sym::log10f128 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", @@ -161,8 +167,15 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", + sym::expf16 => "expf", + sym::exp2f16 => "exp2f", + sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", sym::fmaf16 => "fmaf", + sym::logf16 => "logf", + sym::log2f16 => "log2f", + sym::log10f16 => "log10f", + sym::powf16 => "__builtin_powf", sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", sym::sqrtf16 => "__builtin_sqrtf", @@ -197,11 +210,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let simple = get_simple_intrinsic(self, name); let value = match name { - _ if let Some(func) = simple => self.cx.context.new_call( - self.location, - func, - &args.iter().map(|arg| arg.immediate()).collect::>(), - ), + _ if simple.is_some() => { + let func = simple.expect("simple intrinsic function"); + self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ) + } // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { @@ -230,8 +246,14 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 + | sym::expf16 + | sym::exp2f16 | sym::floorf16 | sym::fmaf16 + | sym::logf16 + | sym::log2f16 + | sym::log10f16 + | sym::powf16 | sym::roundf16 | sym::round_ties_even_f16 | sym::sqrtf16 @@ -242,6 +264,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 + | sym::expf128 + | sym::exp2f128 + | sym::logf128 + | sym::log2f128 + | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); @@ -336,9 +363,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } sym::va_arg => { - let va_list = args[0].immediate(); - let gcc_type = self.immediate_backend_type(result.layout); - self.va_arg(va_list, gcc_type) + unimplemented!(); } sym::volatile_load | sym::unaligned_volatile_load => { @@ -588,7 +613,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); - crate::attributes::from_fn_attrs(self, func, instance, None); + crate::attributes::from_fn_attrs(self, func, instance); func }; @@ -667,18 +692,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, va_list: RValue<'gcc>) { - let func = self.context.get_builtin_function("__builtin_va_start"); - - let va_list_type = self.context.new_c_type(CType::VaList); - let va_list = self.context.new_cast(self.location, va_list, va_list_type.make_pointer()); - - // Pre-C23 requires that the last "normal" argument was passed to va_start. - // Just pass 0, this appears to be handled correctly. - let last_normal_arg = self.context.new_rvalue_from_int(self.int_type, 0); - - let call = self.context.new_call(self.location, func, &[va_list, last_normal_arg]); - self.block.add_eval(self.location, call); + fn va_start(&mut self, _va_list: RValue<'gcc>) { + unimplemented!(); } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { @@ -936,7 +951,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let else_block = func.new_block("else"); let after_block = func.new_block("after"); - let result = self.new_temp(func, None, self.u32_type); + let result = func.new_local(None, self.u32_type, "zeros"); let zero = self.cx.gcc_zero(arg.get_type()); let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); @@ -1017,7 +1032,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // else call it on the 64 high bits and add 64. In the else case, 64 high bits can't be 0 // because arg is not 0. - let result = self.new_temp(self.current_func(), None, result_type); + let result = self.current_func().new_local(None, result_type, "count_zeroes_results"); let cz_then_block = self.current_func().new_block("cz_then"); let cz_else_block = self.current_func().new_block("cz_else"); @@ -1132,8 +1147,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let loop_tail = func.new_block("tail"); let counter_type = self.int_type; - let counter = self.new_temp(self.current_func(), None, counter_type); - let val = self.new_temp(self.current_func(), None, value_type); + let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); + let val = self.current_func().new_local(None, value_type, "popcount_value"); let zero = self.gcc_zero(counter_type); self.llbb().add_assignment(self.location, counter, zero); self.llbb().add_assignment(self.location, val, value); diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 1aac52c28d220..8d3e3487b5cb4 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -1240,10 +1240,6 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", - "bmi.pdep.32" => "__builtin_ia32_pdep_si", - "bmi.pdep.64" => "__builtin_ia32_pdep_di", - "bmi.pext.32" => "__builtin_ia32_pext_si", - "bmi.pext.64" => "__builtin_ia32_pext_di", "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", diff --git a/src/lib.rs b/src/lib.rs index 436f8a1176300..55c721a9706a6 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -76,9 +76,9 @@ use std::path::{Path, PathBuf}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Mutex}; -#[cfg(feature = "master")] -use gccjit::TargetInfo; use gccjit::{CType, Context, OptimizationLevel}; +#[cfg(feature = "master")] +use gccjit::{TargetInfo, Version}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ @@ -97,7 +97,7 @@ use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::RelocModel; +use rustc_target::spec::{Arch, RelocModel}; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; @@ -197,10 +197,8 @@ impl CodegenBackend for GccCodegenBackend { fn init(&self, sess: &Session) { fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { - let rustlib_path = rustc_target::relative_target_rustlib_path( - sysroot_path, - rustc_session::config::host_tuple(), - ); + let rustlib_path = + rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); sysroot_path .join(rustlib_path) .join("codegen-backends") @@ -317,6 +315,27 @@ impl CodegenBackend for GccCodegenBackend { } } +fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { + let context = Context::default(); + if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature = "master")] + { + context.set_special_chars_allowed_in_func_names("$.*"); + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!( + "rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + context +} + impl ExtraBackendMethods for GccCodegenBackend { type Module = GccContext; @@ -328,7 +347,7 @@ impl ExtraBackendMethods for GccCodegenBackend { ) -> Self::Module { let lto_supported = self.lto_supported.load(Ordering::SeqCst); let mut mods = GccContext { - context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))), + context: Arc::new(SyncContext::new(new_context(tcx))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, lto_supported, @@ -425,7 +444,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(sess, cgcx, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( diff --git a/src/mono_item.rs b/src/mono_item.rs index 7513978b12272..d5874779021d2 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,12 +1,11 @@ -use gccjit::Function; #[cfg(feature = "master")] -use gccjit::{FnAttribute, LValue, ToRValue, VarAttribute}; +use gccjit::{FnAttribute, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::bug; -use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; +use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -22,7 +21,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { def_id: DefId, _linkage: Linkage, visibility: Visibility, - global_name: &str, + symbol_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); @@ -34,20 +33,11 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - - let create_global = |this: &CodegenCx<'gcc, 'tcx>, name: &str, visibility: Visibility| { - let global = this.define_global(name, gcc_type, is_tls, attrs.link_section); - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); - // FIXME(antoyo): set linkage. - global - }; - let global = create_global(self, global_name, visibility); - - let attrs = self.tcx.codegen_instance_attrs(instance.def); + let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); #[cfg(feature = "master")] - self.add_static_aliases(&attrs.foreign_item_symbol_aliases, global_name, &create_global); + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + // FIXME(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); } @@ -60,98 +50,12 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { assert!(!instance.args.has_infer()); - let attrs = self.tcx.codegen_instance_attrs(instance.def); - - let decl = - self.predefine_without_aliases(instance, &attrs, linkage, visibility, symbol_name); - - #[cfg(feature = "master")] - self.add_function_aliases(instance, decl, &attrs, &attrs.foreign_item_symbol_aliases); - - self.functions.borrow_mut().insert(symbol_name.to_string(), decl); - self.function_instances.borrow_mut().insert(instance, decl); - } -} - -impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - #[cfg(feature = "master")] - fn add_static_aliases( - &self, - aliases: &[(DefId, Linkage, Visibility)], - aliased: &str, - create_global: &F, - ) where - F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, - { - for &(alias, _linkage, visibility) in aliases { - let instance = Instance::mono(self.tcx, alias); - let symbol_name = self.tcx.symbol_name(instance); - - let alias = create_global(self, symbol_name.name, visibility); - alias.add_attribute(VarAttribute::Alias(aliased)); - - // Add the alias name to the set of cached items, so there is no duplicate - // instance added to it during the normal `external static` codegen - let prev_entry = self.instances.borrow_mut().insert(instance, alias); - - // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias` - // which would result in incorrect codegen - assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); - } - } - - #[cfg(feature = "master")] - fn add_function_aliases( - &self, - aliased_instance: Instance<'tcx>, - aliased: Function<'gcc>, - attrs: &CodegenFnAttrs, - aliases: &[(DefId, Linkage, Visibility)], - ) { - for &(alias, linkage, visibility) in aliases { - let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, alias)); - - // predefine another copy of the original instance - // with a new symbol name - let alias_fn_decl = self.predefine_without_aliases( - aliased_instance, - attrs, - linkage, - visibility, - symbol_name.name, - ); - - let block = alias_fn_decl.new_block("start"); - let nb_params = alias_fn_decl.get_param_count(); - let mut args = Vec::with_capacity(nb_params); - for idx in 0..nb_params { - args.push(alias_fn_decl.get_param(idx as _).to_rvalue()); - } - - let void_type = self.context.new_type::<()>(); - let call = self.context.new_call(None, aliased, &args); - if alias_fn_decl.get_return_type() == void_type { - block.add_eval(None, call); - block.end_with_void_return(None); - } else { - block.end_with_return(None, call); - } - } - } - - fn predefine_without_aliases( - &self, - instance: Instance<'tcx>, - _attrs: &CodegenFnAttrs, - linkage: Linkage, - visibility: Visibility, - symbol_name: &str, - ) -> Function<'gcc> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); - let fn_decl = self.declare_fn(symbol_name, fn_abi); + let decl = self.declare_fn(symbol_name, fn_abi); + //let attrs = self.tcx.codegen_instance_attrs(instance.def); - attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); + attributes::from_fn_attrs(self, decl, instance); // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden @@ -159,21 +63,17 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // don't want the symbols to get exported. if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] - fn_decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else if visibility != Visibility::Default { #[cfg(feature = "master")] - fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); - } - - #[cfg(feature = "master")] - if let Some(section) = _attrs.link_section { - fn_decl.add_attribute(FnAttribute::Section(section.as_str())); + decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); } + // FIXME(antoyo): call set_link_section() to allow initializing argc/argv. // FIXME(antoyo): set unique comdat. // FIXME(antoyo): use inline attribute from there in linkage.set() above. - // FIXME: Should we handle dso? - fn_decl + self.functions.borrow_mut().insert(symbol_name.to_string(), decl); + self.function_instances.borrow_mut().insert(instance, decl); } } diff --git a/src/type_.rs b/src/type_.rs index f008be67e39cb..5252f93a92ebe 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -2,7 +2,7 @@ use std::convert::TryInto; #[cfg(feature = "master")] -use gccjit::{CType, TypeAttribute}; +use gccjit::CType; use gccjit::{RValue, Struct, Type}; use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; @@ -116,7 +116,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); if packed { #[cfg(feature = "master")] - typ.add_attribute(TypeAttribute::Packed); + typ.set_packed(); } self.struct_types.borrow_mut().insert(types, typ); typ @@ -153,7 +153,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { if self.supports_f16_type { return self.context.new_c_type(CType::Float16); } - self.u16_type + bug!("unsupported float width 16") } fn type_f32(&self) -> Type<'gcc> { @@ -333,7 +333,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { typ.set_fields(None, &fields); if packed { #[cfg(feature = "master")] - typ.as_type().add_attribute(TypeAttribute::Packed); + typ.as_type().set_packed(); } } diff --git a/tests/asm/asm/comments.rs b/tests/asm/asm/comments.rs deleted file mode 100644 index 603bb014930c4..0000000000000 --- a/tests/asm/asm/comments.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ assembly-output: emit-asm -//@ only-x86_64 -// Check that comments in assembly get passed - -#![crate_type = "lib"] - -// CHECK-LABEL: "test_comments": -#[no_mangle] -pub fn test_comments() { - // CHECK: example comment - unsafe { core::arch::asm!("nop // example comment") }; -} diff --git a/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs deleted file mode 100644 index 81ee9b13b4eca..0000000000000 --- a/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full -//@ assembly-output: emit-asm -//@ needs-asm-support -//@ only-x86_64 - -#![crate_type = "lib"] - -use std::arch::naked_asm; - -// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", -// meaning "no prologue whatsoever, no, really, not one instruction." -// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection, -// works by using an instruction for each possible landing site, -// and LLVM implements this via making sure of that. -#[no_mangle] -#[unsafe(naked)] -pub extern "sysv64" fn will_halt() -> ! { - // CHECK-NOT: endbr{{32|64}} - // CHECK: hlt - naked_asm!("hlt") -} - -// what about aarch64? -// "branch-protection"=false diff --git a/tests/asm/panic-no-unwind-no-uwtable.rs b/tests/asm/panic-no-unwind-no-uwtable.rs deleted file mode 100644 index b51b173e9616e..0000000000000 --- a/tests/asm/panic-no-unwind-no-uwtable.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ assembly-output: emit-asm -//@ only-x86_64-unknown-linux-gnu -//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3 - -#![crate_type = "lib"] - -// CHECK-NOT: .cfi_startproc -pub fn foo() {} diff --git a/tests/asm/used.rs b/tests/asm/used.rs deleted file mode 100644 index deb0c69dc48fa..0000000000000 --- a/tests/asm/used.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ assembly-output: emit-asm -//@ only-x86_64-unknown-linux-gnu - -#![feature(used_with_arg)] -#![crate_type = "lib"] - -// CHECK: .section .rodata.X,"a" -#[used(compiler)] -#[no_mangle] -pub static X: u32 = 12; -// CHECK: .section .rodata.Y,"aR" -#[used(linker)] -#[no_mangle] -pub static Y: u32 = 12; diff --git a/tests/asm/x86_64-sse_crc.rs b/tests/asm/x86_64-sse_crc.rs deleted file mode 100644 index bde58955a2146..0000000000000 --- a/tests/asm/x86_64-sse_crc.rs +++ /dev/null @@ -1,12 +0,0 @@ -//@ only-x86_64 -//@ assembly-output: emit-asm -//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 - -// CHECK-LABEL: banana -// CHECK: crc32 -#[no_mangle] -pub unsafe fn banana(v: u8) -> u32 { - use std::arch::x86_64::*; - let out = !0u32; - _mm_crc32_u8(out, v) -} diff --git a/tests/compile/x86_interrupt_first_arg_byval.rs b/tests/compile/x86_interrupt_first_arg_byval.rs deleted file mode 100644 index 4b6bbd48f7ad5..0000000000000 --- a/tests/compile/x86_interrupt_first_arg_byval.rs +++ /dev/null @@ -1,16 +0,0 @@ -// Compiler: - -// Test that `x86-interrupt` functions whose first argument is passed by value -// emit pointer-shaped GCC parameters and compile with interrupt-safe target features. - -#![feature(abi_x86_interrupt)] -#![crate_type = "lib"] - -#[repr(C)] -pub struct Frame { - ip: u64, -} - -pub extern "x86-interrupt" fn scalar(_a: i64) {} - -pub extern "x86-interrupt" fn aggregate(_frame: Frame) {} diff --git a/tests/cpuid.def b/tests/cpuid.def deleted file mode 100644 index 05fe8e94a8282..0000000000000 --- a/tests/cpuid.def +++ /dev/null @@ -1,27 +0,0 @@ -# Input => Output -# EAX ECX => EAX EBX ECX EDX -00000000 ******** => 00000024 756e6547 6c65746e 49656e69 #Processor ID and Manufacturer -00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff -00000007 00000000 => 00000002 f3bfbfbf bac05ffe 03d54130 #Extended Features -00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e -0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 -0000000d 00000001 => 0000001f 00000240 00000100 00000000 #Supervisor State -0000000d 00000002 => 00000100 00000240 00000000 00000000 -0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks -0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh -0000000d 00000007 => 00000400 00000680 00000000 00000000 #zmm -0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig -0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles -0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX -00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker -0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile -0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 -0000001e 00000000 => 00000001 00004010 00000000 00000000 #AMX Tmul -0000001e 00000001 => 000001ff 00000000 00000000 00000000 -00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 -00000024 00000001 => 00000000 00000000 00000004 00000000 -80000000 ******** => 80000004 00000000 00000000 00000000 -80000001 ******** => 00000000 00000000 00000121 2c100000 -80000002 ******** => 00000000 00000000 00000000 00000000 -80000003 ******** => 00000000 00000000 00000000 00000000 -80000004 ******** => 00000000 00000000 00000000 00000000 diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index e98d2aab9361b..4c62c35a512c1 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -4,7 +4,3 @@ tests/ui/uninhabited/uninhabited-transparent-return-abi.rs tests/ui/coroutine/panic-drops-resume.rs tests/ui/coroutine/panic-drops.rs tests/ui/coroutine/panic-safe.rs -tests/ui/panic-handler/catch-unwind-during-unwind-68696.rs -tests/ui/threads-sendsync/task-stderr.rs -tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs -tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 1feb2c7cc6edc..528ee1df9f583 100644 --- a/tests/failing-run-make-tests.txt +++ b/tests/failing-run-make-tests.txt @@ -12,4 +12,3 @@ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ tests/run-make/short-ice -tests/run-make/embed-source-dwarf diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2b2f21904abb5..e8a26a90890c1 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -11,22 +11,27 @@ tests/ui/mir/mir_match_guard_let_chains_drop_order.rs tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs tests/ui/panic-runtime/abort.rs tests/ui/panic-runtime/link-to-abort.rs +tests/ui/parser/unclosed-delimiter-in-dep.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/drop/panic-during-drop-14875.rs -tests/ui/drop/move-closure-drop-on-unwind.rs +tests/ui/issues/issue-29948.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/lto/thin-lto-inlines2.rs tests/ui/panic-runtime/lto-abort.rs tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/coroutine/resume-after-return.rs +tests/ui/simd/masked-load-store.rs tests/ui/simd/repr_packed.rs tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs tests/ui/coroutine/unwind-abort-mix.rs +tests/ui/consts/issue-miri-1910.rs tests/ui/consts/const_cmp_type_id.rs +tests/ui/consts/issue-94675.rs +tests/ui/traits/const-traits/const-drop-fail.rs tests/ui/runtime/on-broken-pipe/child-processes.rs tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs tests/ui/sanitizer/cfi/async-closures.rs @@ -42,6 +47,7 @@ tests/ui/sanitizer/cfi/virtual-auto.rs tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs tests/ui/sanitizer/kcfi-mangling.rs +tests/ui/delegation/fn-header.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs tests/ui/runtime/rt-explody-panic-payloads.rs @@ -61,53 +67,47 @@ tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs tests/ui/process/nofile-limit.rs +tests/ui/linking/no-gc-encapsulation-symbols.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs +tests/ui/explicit-tail-calls/recursion-etc.rs +tests/ui/explicit-tail-calls/indexer.rs +tests/ui/explicit-tail-calls/drop-order.rs +tests/ui/c-variadic/valid.rs +tests/ui/c-variadic/inherent-method.rs +tests/ui/c-variadic/trait-method.rs +tests/ui/explicit-tail-calls/become-cast-return.rs +tests/ui/explicit-tail-calls/become-indirect-return.rs tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs tests/ui/sanitizer/kcfi-c-variadic.rs tests/ui/sanitizer/kcfi/fn-trait-objects.rs tests/ui/statics/const_generics.rs tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs +tests/ui/iterators/rangefrom-overflow-debug.rs +tests/ui/iterators/rangefrom-overflow-overflow-checks.rs tests/ui/iterators/iter-filter-count-debug-check.rs +tests/ui/eii/linking/codegen_single_crate.rs +tests/ui/eii/linking/codegen_cross_crate.rs +tests/ui/eii/default/local_crate.rs +tests/ui/eii/duplicate/multiple_impls.rs +tests/ui/eii/default/call_default.rs +tests/ui/eii/linking/same-symbol.rs +tests/ui/eii/privacy1.rs tests/ui/eii/default/call_impl.rs +tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs +tests/ui/consts/const-eval/c-variadic.rs +tests/ui/eii/default/call_default_panics.rs +tests/ui/explicit-tail-calls/indirect.rs +tests/ui/traits/inheritance/self-in-supertype.rs +tests/ui/fmt/fmt_debug/shallow.rs +tests/ui/c-variadic/roundtrip.rs +tests/ui/eii/eii_impl_with_contract.rs tests/ui/eii/static/cross_crate_decl.rs tests/ui/eii/static/cross_crate_def.rs tests/ui/eii/static/same_address.rs tests/ui/eii/static/simple.rs -tests/ui/eii/static/default.rs -tests/ui/eii/static/default_cross_crate.rs -tests/ui/eii/static/default_explicit.rs -tests/ui/eii/static/default_cross_crate_explicit.rs -tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs -tests/ui/abi/rust-tail-cc.rs -tests/ui/abi/rust-preserve-none-cc.rs -tests/ui/extern/extern-types-field-offset.rs -tests/ui/numbers-arithmetic/int-abs-overflow.rs -tests/ui/numbers-arithmetic/issue-8460.rs -tests/ui/panics/panic-handler-chain-update-hook.rs -tests/ui/panics/panic-handler-chain.rs -tests/ui/panics/panic-handler-set-twice.rs -tests/ui/panics/panic-recover-propagate.rs -tests/ui/panics/panic-in-dtor-drops-fields.rs -tests/ui/panics/panic-handler-flail-wildly.rs -tests/ui/panics/rvalue-cleanup-during-box-panic.rs -tests/ui/process/multi-panic.rs -tests/ui/sepcomp/sepcomp-unwind.rs -tests/ui/structs/unit-like-struct-drop-run.rs -tests/ui/threads-sendsync/unwind-resource.rs -tests/ui/array-slice-vec/box-of-array-of-drop-2.rs -tests/ui/array-slice-vec/box-of-array-of-drop-1.rs -tests/ui/array-slice-vec/nested-vec-3.rs -tests/ui/array-slice-vec/slice-panic-1.rs -tests/ui/array-slice-vec/slice-panic-2.rs -tests/ui/backtrace/synchronized-panic-handler.rs -tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs -tests/ui/drop/drop-once-on-panic.rs -tests/ui/drop/enum-destructor-on-unwind.rs -tests/ui/drop/drop-trait-enum.rs -tests/ui/drop/panic-during-slice-init.rs -tests/ui/drop/terminate-in-initializer.rs +tests/ui/explicit-tail-calls/default-trait-method.rs diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index f3b4ad34bc9c4..6afd54e1c3fe0 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -172,16 +172,6 @@ fn build_test_runner( } } - // Extra flags passed at run time (as opposed to the compile-time - // `TEST_FLAGS`). This lets a single test opt into flags like - // `-Zmir-preserve-ub` via an `ignore-if` directive that checks - // whether `CARGO_TEST_FLAGS` is set. - if let Ok(flags) = std::env::var("CARGO_TEST_FLAGS") { - for flag in flags.split_whitespace() { - compiler_args.push(flag.into()); - } - } - if build_mode.is_debug() { compiler_args .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); @@ -211,13 +201,7 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { "lang compile", "tests/compile", TestMode::Compile, - &[ - "simd-ffi.rs", - "asm_nul_byte.rs", - "global_asm_nul_byte.rs", - "naked_asm_nul_byte.rs", - "x86_interrupt_first_arg_byval.rs", - ], + &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], ); } diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 42141c671b596..01775c92ffc8a 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -3,8 +3,6 @@ // Run-time: // status: 0 -#![feature(asm_goto_with_outputs)] - #[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; @@ -34,20 +32,6 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } -#[cfg(target_arch = "x86_64")] -#[unsafe(no_mangle)] -pub fn asm_goto_test(mut a: i16) -> i16 { - unsafe { - std::arch::asm!( - "jmp {op}", - inout("eax") a, - op = label { a = 7; }, - options(nostack,nomem) - ); - a - } -} - #[cfg(target_arch = "x86_64")] fn asm() { unsafe { @@ -206,14 +190,6 @@ fn asm() { } assert_eq!((x, y), (8, 8)); - // Regression test for - // typed pointer inputs to explicit registers need a cast. - let mut x = 123_i32; - unsafe { - asm!("", in("rdi") &mut x, options(nostack, preserves_flags)); - } - assert_eq!(x, 123); - // sysv64 is the default calling convention on unix systems. The rdi register is // used to pass arguments in the sysv64 calling convention, so this register will be clobbered #[cfg(unix)] @@ -251,24 +227,6 @@ fn asm() { out("r15b") _, ); } - - // Make sure the input value from inout is assigned to the input value - unsafe { - // Use a very distinctive value unlikely to live in any register. - let input: u64 = 0x1234567890ABCDEF; - let mut output: u64; - - asm!( - "push {1}", - "pop {0}", - out(reg) output, - inout(reg) input => _, - ); - - assert_eq!(output, 0x1234567890ABCDEF); - } - - asm_goto_test(0); } #[cfg(not(target_arch = "x86_64"))] diff --git a/tests/run/int.rs b/tests/run/int.rs index ef825b4d80185..78675acb5447b 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -319,29 +319,4 @@ fn main() { const VAL5: T = 73236519889708027473620326106273939584_i128; check_ops128!(); } - - { - #[allow(dead_code)] - #[repr(u8)] - enum Inner { - L0 = 0, - H255 = 255, - } - #[allow(dead_code)] - enum O { - A(Inner), - B, - C, - } - - #[inline(never)] - fn which(o: &O) -> &'static str { - match o { - O::A(_) => "a", - O::B => "b", - O::C => "c", - } - } - assert_eq!(which(black_box(&O::A(Inner::H255))), "a"); - } } diff --git a/tests/run/mir_preserve_ub_empty_switch.rs b/tests/run/mir_preserve_ub_empty_switch.rs deleted file mode 100644 index 26056360b9212..0000000000000 --- a/tests/run/mir_preserve_ub_empty_switch.rs +++ /dev/null @@ -1,35 +0,0 @@ -// ignore-if: test -z "$CARGO_TEST_FLAGS" -// Compiler: -// -// Run-time: -// status: 0 - -// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/881 -// -// This needs `-Zmir-preserve-ub`, so it is skipped unless that flag is passed -// through `CARGO_TEST_FLAGS` (see the `ignore-if` directive above). Run it with: -// CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - -#![feature(no_core)] -#![no_std] -#![no_core] -#![no_main] - -extern crate mini_core; -use intrinsics::black_box; -use mini_core::*; - -#[no_mangle] -extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { - // With `-Zmir-preserve-ub`, the range pattern below is lowered to a pair of - // comparisons and the second one becomes a `SwitchInt` with no cases (only - // an `otherwise` target) whose discriminant is the `bool` comparison - // result. `gcc_jit_block_end_with_switch` rejects a non-integer - // discriminant, so the backend must emit a plain jump for it instead. - let value = black_box(argc); - match value { - 0..=9 => (), - _ => (), - } - 0 -} diff --git a/tools/cspell_dicts/rust.txt b/tools/cspell_dicts/rust.txt index 15faacd53d5a0..379cbd77eef01 100644 --- a/tools/cspell_dicts/rust.txt +++ b/tools/cspell_dicts/rust.txt @@ -1,3 +1,2 @@ lateout repr -rmeta diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt index bae8edc9ffdf9..4fb018b3ecd87 100644 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ b/tools/cspell_dicts/rustc_codegen_gcc.txt @@ -60,12 +60,10 @@ nvptx pointee powitf reassoc -retag riscv rlib roundevenf rustc -sgpr sitofp sizet spir @@ -76,8 +74,5 @@ uitofp unord uninlined utrunc -vgpr xabort -xreg -xtensa zext diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 06425f682a88b..5390323407779 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -84,10 +84,6 @@ def update_intrinsics(llvm_path): # This speeds up the comparison, and makes our code considerably smaller. # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) - indent4 = " " - indent8 = indent4 + indent4 - indent12 = indent8 + indent4 - indent16 = indent12 + indent4 with open(output_file, "w", encoding="utf8") as out: out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! @@ -99,35 +95,33 @@ def update_intrinsics(llvm_path): if let ArchCheckResult::Ok(res) = old_arch_res { return res; } - match arch { -""") +match arch {""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" - out.write(f"""{indent4}"{arch}" => {{ -{indent8}{attribute} fn {arch}(name: &str,full_name:&str) -> &'static str {{ -{indent12}match name {{""") + out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) intrinsics[arch].sort(key=lambda x: (x[0], x[1])) - out.write(f'{indent16}// {arch}\n') + out.write(' // {}\n'.format(arch)) for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); if "_round_mask" in entry[1]: - out.write(f'{indent16}// [INVALID CONVERSION]: "{llvm_name}" => "{entry[1]}",\n') + out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) else: - out.write(f'{indent16}"{llvm_name}" => "{entry[1]}",\n') - out.write(f'{indent16}_ => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"),\n') - out.write(f"{indent16}}}\n{indent12}}}\n{indent8}{arch}(name,full_name)\n{indent8}}}\n,") - out.write(f"""{indent4}_ => {{ -{indent8}match old_arch_res {{ -{indent8}ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"), -{indent8}ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {{arch}}, intrinsic: {{full_name}}"), -{indent8}ArchCheckResult::Ok(_) => unreachable!(), -{indent4}}} -}}""") + out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) + out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') + out.write("}} }} {}(name,full_name) }}\n,".format(arch)) + out.write(""" _ => { + match old_arch_res { + ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), + ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), + ArchCheckResult::Ok(_) => unreachable!(), + } + }""") out.write("}\n}") + subprocess.call(["rustfmt", output_file]) print("Done!") From 0c7a1acef311fbda18392b6d33f818aead608b80 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Aug 2026 09:43:53 -0400 Subject: [PATCH 0022/1309] Update to nightly-2026-08-04 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 104992b5da46b..d777360fd4226 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-07-24" +channel = "nightly-2026-08-04" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From c4a0877d27f92bdfd506bdb92af19e3d198a2ed2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Aug 2026 09:50:04 -0400 Subject: [PATCH 0023/1309] Fix formatting --- src/context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 8045e8ae9d28f..19fbe37c27b9e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -495,7 +495,9 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let entry_name = self.sess().target.entry_name.as_ref(); if !self.functions.borrow().contains_key(entry_name) { let conv = cfg_select! { - feature = "master" => conv_to_fn_attribute(self.sess(), self.sess().target.entry_abi), + feature = "master" => { + conv_to_fn_attribute(self.sess(), self.sess().target.entry_abi) + } _ => None, }; Some(self.declare_entry_fn(entry_name, fn_type, conv)) From 23ff7bd044dfaa2520158de461dcd815fe988f24 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Aug 2026 10:43:41 -0400 Subject: [PATCH 0024/1309] Fix copy of sysroot dependencies --- build_system/src/build.rs | 33 +++++++++++++++++++++++++++------ 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index e570a3f16c39e..2fc4d970545ba 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -188,12 +188,33 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // FIXME: should not use shell command! run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ()) }; - walk_dir( - library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)), - &mut copier.clone(), - &mut copier, - false, - )?; + let target_dir = library_dir.join(format!("target/{}/{}", config.target_triple, channel)); + let deps_dir = target_dir.join("deps"); + if deps_dir.is_dir() { + // Keep copying in the old directory just in case. + walk_dir(&deps_dir, &mut copier.clone(), &mut copier, false)?; + } else { + let build_dir = target_dir.join("build"); + walk_dir( + &build_dir, + &mut |package_dir: &Path| { + walk_dir( + package_dir, + &mut |unit_dir: &Path| { + let out_dir = unit_dir.join("out"); + if out_dir.is_dir() { + walk_dir(&out_dir, &mut copier.clone(), &mut copier.clone(), false)?; + } + Ok(()) + }, + &mut |_| Ok(()), + false, + ) + }, + &mut |_| Ok(()), + false, + )?; + } // Copy the source files to the sysroot (Rust for Linux needs this). let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust"); From e85bf608d3c59a440db047b4d13e4c5d938e76cb Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Aug 2026 11:08:19 -0400 Subject: [PATCH 0025/1309] Add failing UI test --- tests/failing-ui-tests.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2b2f21904abb5..e17183f43f6df 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -111,3 +111,4 @@ tests/ui/drop/enum-destructor-on-unwind.rs tests/ui/drop/drop-trait-enum.rs tests/ui/drop/panic-during-slice-init.rs tests/ui/drop/terminate-in-initializer.rs +tests/ui/std/add-spawn-hook-reentrancy-159923.rs From 80cc13e431733f23a09fc2eecda14034571b1c47 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 5 Aug 2026 08:48:41 -0400 Subject: [PATCH 0026/1309] Remove passing tests from failing-ui-tests.txt --- tests/failing-ui-tests.txt | 36 ------------------------------------ 1 file changed, 36 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index e17183f43f6df..489d0412eb317 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,16 +1,7 @@ tests/ui/asm/may_unwind.rs tests/ui/asm/x86_64/may_unwind.rs tests/ui/drop/dynamic-drop-async.rs -tests/ui/cfg/cfg-panic-abort.rs tests/ui/intrinsics/panic-uninitialized-zeroed.rs -tests/ui/iterators/iter-sum-overflow-debug.rs -tests/ui/iterators/iter-sum-overflow-overflow-checks.rs -tests/ui/mir/mir_drop_order.rs -tests/ui/mir/mir_let_chains_drop_order.rs -tests/ui/mir/mir_match_guard_let_chains_drop_order.rs -tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs -tests/ui/panic-runtime/abort.rs -tests/ui/panic-runtime/link-to-abort.rs tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs @@ -25,9 +16,7 @@ tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/coroutine/resume-after-return.rs tests/ui/simd/repr_packed.rs tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs -tests/ui/coroutine/unwind-abort-mix.rs tests/ui/consts/const_cmp_type_id.rs -tests/ui/runtime/on-broken-pipe/child-processes.rs tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs tests/ui/sanitizer/cfi/async-closures.rs tests/ui/sanitizer/cfi/closures.rs @@ -41,7 +30,6 @@ tests/ui/sanitizer/cfi/supertraits.rs tests/ui/sanitizer/cfi/virtual-auto.rs tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs -tests/ui/sanitizer/kcfi-mangling.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs tests/ui/runtime/rt-explody-panic-payloads.rs @@ -64,9 +52,6 @@ tests/ui/process/nofile-limit.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs -tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs -tests/ui/sanitizer/kcfi-c-variadic.rs -tests/ui/sanitizer/kcfi/fn-trait-objects.rs tests/ui/statics/const_generics.rs tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs @@ -86,29 +71,8 @@ tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs tests/ui/extern/extern-types-field-offset.rs -tests/ui/numbers-arithmetic/int-abs-overflow.rs -tests/ui/numbers-arithmetic/issue-8460.rs -tests/ui/panics/panic-handler-chain-update-hook.rs -tests/ui/panics/panic-handler-chain.rs -tests/ui/panics/panic-handler-set-twice.rs -tests/ui/panics/panic-recover-propagate.rs tests/ui/panics/panic-in-dtor-drops-fields.rs -tests/ui/panics/panic-handler-flail-wildly.rs -tests/ui/panics/rvalue-cleanup-during-box-panic.rs -tests/ui/process/multi-panic.rs -tests/ui/sepcomp/sepcomp-unwind.rs -tests/ui/structs/unit-like-struct-drop-run.rs -tests/ui/threads-sendsync/unwind-resource.rs -tests/ui/array-slice-vec/box-of-array-of-drop-2.rs -tests/ui/array-slice-vec/box-of-array-of-drop-1.rs -tests/ui/array-slice-vec/nested-vec-3.rs tests/ui/array-slice-vec/slice-panic-1.rs tests/ui/array-slice-vec/slice-panic-2.rs -tests/ui/backtrace/synchronized-panic-handler.rs -tests/ui/cross-crate/mut-ref-write-visible-after-unwind.rs -tests/ui/drop/drop-once-on-panic.rs tests/ui/drop/enum-destructor-on-unwind.rs -tests/ui/drop/drop-trait-enum.rs -tests/ui/drop/panic-during-slice-init.rs -tests/ui/drop/terminate-in-initializer.rs tests/ui/std/add-spawn-hook-reentrancy-159923.rs From dda9083ee4fac309735b64649b91a6356307cbfd Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 5 Aug 2026 09:15:12 -0400 Subject: [PATCH 0027/1309] Add new failing LTO tests --- tests/failing-lto-tests.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index e98d2aab9361b..345f1920e55ac 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -8,3 +8,5 @@ tests/ui/panic-handler/catch-unwind-during-unwind-68696.rs tests/ui/threads-sendsync/task-stderr.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +tests/ui/threads-sendsync/unwind-resource.rs +tests/ui/drop/drop-trait-enum.rs From 1dc1f9ee35afa8dccf9db2a75d823f3e74906a25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?H=C3=BCseyin=20Kutsi=20Balc=C4=B1?= Date: Wed, 5 Aug 2026 16:30:23 +0300 Subject: [PATCH 0028/1309] Fix two broken links in the docs doc/tips.md links to ./doc/gimple.md, but tips.md is itself inside doc/, so the link resolves to doc/doc/gimple.md and 404s. The file sits next to it. Readme.md links to ./doc/debugging-gcc-lto.md. That file was added in 79316d4e8 and removed again in 79a6e4eaa, which replaced it with the broader doc/debugging.md; the Readme entry was not updated. The GCC LTO material is still there, as the first section of that file. CONTRIBUTING.md already refers to it as [Debugging](doc/debugging.md), so the Readme entry now matches that name. --- Readme.md | 2 +- doc/tips.md | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Readme.md b/Readme.md index 26783aa39cea8..9a7c624c9bc22 100644 --- a/Readme.md +++ b/Readme.md @@ -178,7 +178,7 @@ $ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(ca More specific documentation is available in the [`doc`](./doc) folder: * [Common errors](./doc/errors.md) - * [Debugging GCC LTO](./doc/debugging-gcc-lto.md) + * [Debugging](./doc/debugging.md) * [Debugging libgccjit](./doc/debugging-libgccjit.md) * [Git subtree sync](./doc/subtree.md) * [List of useful commands](./doc/tips.md) diff --git a/doc/tips.md b/doc/tips.md index ff92566d4a1ab..dc40ee4d39952 100644 --- a/doc/tips.md +++ b/doc/tips.md @@ -58,7 +58,7 @@ If you wish to build a custom sysroot, pass the path of your sysroot source to ` ### How to generate GIMPLE If you need to check what gccjit is generating (GIMPLE), then take a look at how to -generate it in [gimple.md](./doc/gimple.md). +generate it in [gimple.md](./gimple.md). ### How to build a cross-compiling libgccjit From e9d0e581fe42668f63124c2f299a82cc406dc9a3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 5 Aug 2026 00:24:45 +0200 Subject: [PATCH 0029/1309] refactor handling of target features in Session --- src/lib.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 55c721a9706a6..621ee4ce27636 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -85,7 +85,7 @@ use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput, }; use rustc_codegen_ssa::base::codegen_crate; -use rustc_codegen_ssa::target_features::cfg_target_feature; +use rustc_codegen_ssa::target_features::internal_target_features; use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; use rustc_data_structures::profiling::SelfProfilerRef; @@ -531,7 +531,7 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { /// Returns the features that should be set in `cfg(target_feature)`. fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig { - let (unstable_target_features, target_features) = cfg_target_feature( + let internal_target_features = internal_target_features( sess, |feature| to_gcc_features(sess, feature), |feature| { @@ -555,8 +555,7 @@ fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128); TargetConfig { - target_features, - unstable_target_features, + internal_target_features, // There are no known bugs with GCC support for f16 or f128 has_reliable_f16, has_reliable_f16_math: has_reliable_f16, From 56619f32abcd35ca7c0e5595f0feb6dfac5905f5 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 25 Jul 2026 20:56:04 -0400 Subject: [PATCH 0030/1309] Fix overaligned argument --- src/abi.rs | 13 +++++++--- tests/run/overaligned_byval_arg.rs | 41 ++++++++++++++++++++++++++++++ 2 files changed, 51 insertions(+), 3 deletions(-) create mode 100644 tests/run/overaligned_byval_arg.rs diff --git a/src/abi.rs b/src/abi.rs index 45fc5e3c4f619..2ae60e238ecad 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::FnAttribute; +use gccjit::{FnAttribute, TypeAttribute}; use gccjit::{ToLValue, ToRValue, Type}; #[cfg(feature = "master")] use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; @@ -187,7 +187,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs, argument_tys.len()) } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => { let x86_interrupt_first_arg = { #[cfg(feature = "master")] { @@ -211,7 +211,14 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { } else { // This is a "byval" argument, so we don't apply the `restrict` attribute on it. on_stack_param_indices.insert(argument_tys.len()); - arg.layout.gcc_type(cx) + let ty = arg.layout.gcc_type(cx); + #[cfg(feature = "master")] + if let Some(align) = attrs.pointee_align { + ty.add_attribute(TypeAttribute::Aligned(align.bytes() as u8)); + } + #[cfg(not(feature = "master"))] + let _ = attrs; + ty } } PassMode::Direct(attrs) => { diff --git a/tests/run/overaligned_byval_arg.rs b/tests/run/overaligned_byval_arg.rs new file mode 100644 index 0000000000000..e20ec11732962 --- /dev/null +++ b/tests/run/overaligned_byval_arg.rs @@ -0,0 +1,41 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[repr(C)] +struct Big { + a: i64, + b: i64, + c: i64, +} + +#[repr(C, align(64))] +struct Aligned { + x: i32, +} + +#[inline(never)] +#[no_mangle] +extern "C" fn check(_b1: Big, a1: Aligned, _b2: Big, a2: Aligned) -> i32 { + if (&a1 as *const Aligned as usize) % 64 != 0 { + return 1; + } + if (&a2 as *const Aligned as usize) % 64 != 0 { + return 2; + } + 0 +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + check(Big { a: 1, b: 2, c: 3 }, Aligned { x: 42 }, Big { a: 4, b: 5, c: 6 }, Aligned { x: 43 }) +} From a7e1f0552e50d56b7274764d0948cfe0d4ada3d1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 3 Aug 2026 17:36:18 -0400 Subject: [PATCH 0031/1309] Add -Wno-psabi to silent a warning --- src/gcc_util.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index d986dc68e675a..56314dca5effa 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -193,6 +193,8 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { context.add_command_line_option("-fno-strict-aliasing"); // NOTE: Rust relies on LLVM doing wrapping on overflow. context.add_command_line_option("-fwrapv"); + // NOTE: This is needed to hide a warning caused by the alignment fix on byval arguments. + context.add_command_line_option("-Wno-psabi"); if let Some(model) = sess.code_model() { use rustc_target::spec::CodeModel; From 20fbf8564ca6b70784c884050e4895c40244dbbd Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 3 Aug 2026 17:38:26 -0400 Subject: [PATCH 0032/1309] Update gccjit dependency --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/abi.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 060509e51a6f9..cca0e1e590e28 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "gccjit" -version = "4.0.0" +version = "4.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be5dafc4e649cb4a363e95a5960ef50b0c6f1b8e136ff8eb2e928b40353b5d8b" +checksum = "859af1dd2815fd0f8ca97f5917a595f18c415692b07e58993a6ad34ff13204d5" dependencies = [ "gccjit_sys", ] diff --git a/Cargo.toml b/Cargo.toml index 63a20d46b9d2f..141949e9189e6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "4.0.0", features = ["dlopen"] } +gccjit = { version = "4.1.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/abi.rs b/src/abi.rs index 2ae60e238ecad..445da17dc39c7 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -214,7 +214,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = arg.layout.gcc_type(cx); #[cfg(feature = "master")] if let Some(align) = attrs.pointee_align { - ty.add_attribute(TypeAttribute::Aligned(align.bytes() as u8)); + ty.add_attribute(TypeAttribute::Aligned(align.bytes() as u32)); } #[cfg(not(feature = "master"))] let _ = attrs; From 599ab528cae362e517d84d5b7af3786cd55417c5 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 4 Aug 2026 10:26:14 -0400 Subject: [PATCH 0033/1309] Add packed and aligned in type cache, add real test using C --- src/abi.rs | 24 ++++---- src/common.rs | 4 +- src/context.rs | 4 +- src/type_.rs | 71 ++++++++++++++++++++-- src/type_of.rs | 9 +-- tests/c/overaligned_byval_abi.c | 52 ++++++++++++++++ tests/lang_tests.rs | 97 +++++++++++++++++++++++++++--- tests/run/overaligned_byval_abi.rs | 89 +++++++++++++++++++++++++++ 8 files changed, 320 insertions(+), 30 deletions(-) create mode 100644 tests/c/overaligned_byval_abi.c create mode 100644 tests/run/overaligned_byval_abi.rs diff --git a/src/abi.rs b/src/abi.rs index 445da17dc39c7..ba798bab83fa4 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -1,5 +1,5 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, TypeAttribute}; +use gccjit::FnAttribute; use gccjit::{ToLValue, ToRValue, Type}; #[cfg(feature = "master")] use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; @@ -73,7 +73,9 @@ impl GccType for CastTarget { args.push(cx.type_ix(rem_bytes * 8)); } - cx.type_struct(&args, false) + // A cast target describes registers, so its alignment is whatever GCC computes from + // them rather than the alignment of the Rust type being cast. + cx.type_struct(&args, false, None) } } @@ -187,7 +189,7 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs, argument_tys.len()) } - PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { let x86_interrupt_first_arg = { #[cfg(feature = "master")] { @@ -210,15 +212,15 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { cx.type_ptr_to(arg.layout.gcc_type(cx)) } else { // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + // + // GCC picks the argument's stack slot from the alignment of this type, + // which `LayoutGccExt::gcc_type` sets from `layout.align.abi`. We + // deliberately do not use `attrs.pointee_align` here: when it differs + // from the type's alignment it describes the *slot*, not the type, and + // rustc already copies the argument to a sufficiently aligned alloca on + // whichever side needs it. on_stack_param_indices.insert(argument_tys.len()); - let ty = arg.layout.gcc_type(cx); - #[cfg(feature = "master")] - if let Some(align) = attrs.pointee_align { - ty.add_attribute(TypeAttribute::Aligned(align.bytes() as u32)); - } - #[cfg(not(feature = "master"))] - let _ = attrs; - ty + arg.layout.gcc_type(cx) } } PassMode::Direct(attrs) => { diff --git a/src/common.rs b/src/common.rs index 6f9d22885b205..5b89fc7aa639c 100644 --- a/src/common.rs +++ b/src/common.rs @@ -288,7 +288,9 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> { let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect(); // FIXME(antoyo): cache the type? It's anonymous, so probably not. - let typ = self.type_struct(&fields, packed); + // The alignment of a constant aggregate is the one GCC derives from its fields: the Rust + // layout this comes from is not available here. + let typ = self.type_struct(&fields, packed, None); let struct_type = typ.is_struct().expect("struct type"); self.context.new_struct_constructor(None, struct_type.as_type(), None, values) } diff --git a/src/context.rs b/src/context.rs index 19fbe37c27b9e..d971b7f32de3f 100644 --- a/src/context.rs +++ b/src/context.rs @@ -26,6 +26,7 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; use crate::abi::conv_to_fn_attribute; use crate::callee::get_fn; use crate::common::SignType; +use crate::type_::StructTypeKey; #[cfg_attr(not(feature = "master"), expect(dead_code))] pub struct CodegenCx<'gcc, 'tcx> { @@ -85,7 +86,8 @@ pub struct CodegenCx<'gcc, 'tcx> { pub types: RefCell, Option), Type<'gcc>>>, pub tcx: TyCtxt<'tcx>, - pub struct_types: RefCell>, Type<'gcc>>>, + /// Cache of the anonymous struct types. + pub struct_types: RefCell, Type<'gcc>>>, /// Cache instances of monomorphic and polymorphic items pub instances: RefCell, LValue<'gcc>>>, diff --git a/src/type_.rs b/src/type_.rs index f008be67e39cb..e0f6d72d8fd15 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -101,9 +101,15 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bool_type } - pub fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { - let types = fields.to_vec(); - if let Some(typ) = self.struct_types.borrow().get(fields) { + pub fn type_struct( + &self, + fields: &[Type<'gcc>], + packed: bool, + align: Option, + ) -> Type<'gcc> { + let align = normalize_struct_alignment(align); + let key = StructTypeKey { fields: fields.to_vec(), packed, align }; + if let Some(typ) = self.struct_types.borrow().get(&key) { return *typ; } let fields: Vec<_> = fields @@ -118,11 +124,59 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] typ.add_attribute(TypeAttribute::Packed); } - self.struct_types.borrow_mut().insert(types, typ); + set_struct_alignment(typ, align); + self.struct_types.borrow_mut().insert(key, typ); typ } } +/// Identifies an anonymous struct type in `CodegenCx::struct_types`. +/// +/// Everything that can make two of them distinct has to be part of it. In particular the +/// alignment: two Rust types can have the same field list and still differ in alignment (for +/// instance `struct { a: u64, b: u64 }` with and without `repr(align(16))`), and they must not +/// end up sharing a GCC type. +#[derive(Clone, Eq, Hash, PartialEq)] +pub struct StructTypeKey<'gcc> { + pub fields: Vec>, + pub packed: bool, + pub align: Option, +} + +/// Discard an alignment that GCC would give the struct anyway. +/// +/// One byte is the minimum alignment of a GCC struct, so requesting it explicitly changes +/// nothing; mapping it to `None` keeps types that do not care about their alignment sharing a +/// single entry in `CodegenCx::struct_types`. +fn normalize_struct_alignment(align: Option) -> Option { + align.filter(|align| align.bytes() > 1) +} + +/// Give a struct type the alignment that Rust computed for it. +/// +/// GCC derives a struct's alignment from its field list, so a `repr(align(N))` that is larger +/// than what the fields require would otherwise be lost. That is not only a layout concern: the +/// ABI of a by-value ("byval") argument depends on it, since `ix86_function_arg_boundary` reads +/// `TYPE_ALIGN` to pick the argument's stack slot. An over-aligned aggregate whose GCC type has +/// lost its alignment is therefore passed at an offset a C caller does not agree on. +/// +/// This has to be set on the struct type itself. `Type::get_aligned` is not enough: it builds a +/// type *variant*, and the argument-passing code looks at `TYPE_MAIN_VARIANT` first, which +/// discards it. +/// +/// This never under-aligns a struct whose fields need more: GCC starts the record layout from +/// `TYPE_ALIGN` and the fields can only raise it. +#[cfg(feature = "master")] +fn set_struct_alignment(typ: Type<'_>, align: Option) { + if let Some(align) = normalize_struct_alignment(align) { + typ.add_attribute(TypeAttribute::Aligned(align.bytes() as u32)); + } +} + +/// Without the `master` feature, libgccjit has no way to set a type's alignment. +#[cfg(not(feature = "master"))] +fn set_struct_alignment(_typ: Type<'_>, _align: Option) {} + impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { self.i8_type @@ -324,7 +378,13 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.type_array(self.type_from_integer(unit), size / unit_size) } - pub fn set_struct_body(&self, typ: Struct<'gcc>, fields: &[Type<'gcc>], packed: bool) { + pub fn set_struct_body( + &self, + typ: Struct<'gcc>, + fields: &[Type<'gcc>], + packed: bool, + align: Option, + ) { let fields: Vec<_> = fields .iter() .enumerate() @@ -335,6 +395,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] typ.as_type().add_attribute(TypeAttribute::Packed); } + set_struct_alignment(typ.as_type(), align); } pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { diff --git a/src/type_of.rs b/src/type_of.rs index c6c32236ab49f..da9a660e73dbf 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -82,6 +82,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( layout.scalar_pair_element_gcc_type(cx, 1), ], false, + Some(layout.align.abi), ); } BackendRepr::Memory { .. } => {} @@ -130,10 +131,10 @@ fn uncached_gcc_type<'gcc, 'tcx>( let fill = cx.type_padding_filler(layout.size, layout.align.abi); let packed = false; match name { - None => cx.type_struct(&[fill], packed), + None => cx.type_struct(&[fill], packed, Some(layout.align.abi)), Some(ref name) => { let gcc_type = cx.type_named_struct(name); - cx.set_struct_body(gcc_type, &[fill], packed); + cx.set_struct_body(gcc_type, &[fill], packed, Some(layout.align.abi)); gcc_type.as_type() } } @@ -142,7 +143,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Arbitrary { .. } => match name { None => { let (gcc_fields, packed) = struct_fields(cx, layout); - cx.type_struct(&gcc_fields, packed) + cx.type_struct(&gcc_fields, packed, Some(layout.align.abi)) } Some(ref name) => { let gcc_type = cx.type_named_struct(name); @@ -240,7 +241,7 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { if let Some((deferred_ty, layout)) = defer { let (fields, packed) = struct_fields(cx, layout); - cx.set_struct_body(deferred_ty, &fields, packed); + cx.set_struct_body(deferred_ty, &fields, packed, Some(layout.align.abi)); } ty diff --git a/tests/c/overaligned_byval_abi.c b/tests/c/overaligned_byval_abi.c new file mode 100644 index 0000000000000..e7575871e0689 --- /dev/null +++ b/tests/c/overaligned_byval_abi.c @@ -0,0 +1,52 @@ +/* Reference side of `tests/run/overaligned_byval_abi.rs`, compiled by the real GCC. + * + * `Aligned` is an over-aligned aggregate passed by value ("byval"): the ABI places it in a stack + * slot aligned to its own alignment, not packed right after the preceding argument. cg_gcc used + * to build the GCC struct type from the field list alone, which dropped Rust's `repr(align(64))`, + * so it placed the argument at an offset nobody else agreed on. + * + * The two functions here check both directions: `c_take_both` is a GCC-built callee for a cg_gcc + * caller, and `c_call_rust` is a GCC-built caller for a cg_gcc callee. + * + * The checks are on the *values* received rather than on the address of the argument: which + * alignment the ABI gives a stack slot is target-specific, but caller and callee agreeing on it + * is not. A disagreement makes the arguments arrive as garbage. */ + +struct Big { + long a, b, c; +}; + +struct __attribute__((aligned(64))) Aligned { + int x; +}; + +/* Defined on the Rust side. */ +extern int rust_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth); + +/* Called from Rust: checks what a cg_gcc caller passed. */ +int c_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth) +{ + if (first.a != 1 || first.b != 2 || first.c != 3) + return 1; + if (second.x != 42) + return 2; + if (third.a != 4 || third.b != 5 || third.c != 6) + return 3; + if (fourth.x != 43) + return 4; + return 0; +} + +/* Called from Rust: passes the arguments the way the ABI says, for a cg_gcc callee to read. */ +int c_call_rust(void) +{ + struct Big first = {1, 2, 3}; + struct Big third = {4, 5, 6}; + struct Aligned second, fourth; + + second.x = 42; + fourth.x = 43; + return rust_take_both(first, second, third, fourth); +} diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index f3b4ad34bc9c4..5426d777bb49e 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -7,6 +7,74 @@ use std::process::Command; use lang_tester::LangTester; use tempfile::TempDir; +/// Directory holding the C files that the `tests/run` tests can link against. +/// +/// A `tests/c/.c` is compiled by the real GCC and linked into `tests/run/.rs`. +/// This is what makes it possible to test the ABI: with cg_gcc on both sides of a call, caller +/// and callee agree even when they are both wrong, so a pure-Rust test cannot notice. A C +/// caller or callee built by GCC is an independent reference. +const C_TESTS_DIR: &str = "tests/c"; + +/// The m68k cross toolchain is not on the default `PATH` in CI. +// FIXME(antoyo): find a better way to add the PATH necessary locally. +const M68K_TOOLCHAIN_DIR: &str = "/opt/m68k-unknown-linux-gnu/bin"; + +fn target_path(test_target: &Option) -> Option { + test_target.as_ref().map(|_| { + let env_path = std::env::var("PATH").unwrap_or_default(); + format!("{}:{}", M68K_TOOLCHAIN_DIR, env_path) + }) +} + +/// Compile every C file in `tests/c` to an object file in `objects_dir`, named after the C file. +/// +/// The C files are compiled by the real GCC (the cross one when testing another target), not by +/// cg_gcc: they are the reference the Rust side is checked against. +fn compile_c_files(objects_dir: &Path, test_target: &Option) { + let c_tests_dir = Path::new(C_TESTS_DIR); + if !c_tests_dir.is_dir() { + return; + } + std::fs::create_dir_all(objects_dir).expect("create the directory for the C object files"); + + let compiler = match test_target { + Some(target) => format!("{}-gcc", target), + None => "gcc".to_string(), + }; + + for entry in std::fs::read_dir(c_tests_dir).expect("read the C tests directory") { + let source = entry.expect("directory entry").path(); + if source.extension().and_then(|extension| extension.to_str()) != Some("c") { + continue; + } + let object = c_object_path(objects_dir, &source); + + let mut command = Command::new(&compiler); + command.arg("-c"); + // Optimize: an unoptimized C caller can happen to agree with a wrong callee. + command.arg("-O1"); + // GCC notes that the ABI of over-aligned arguments changed in GCC 4.6. That is the ABI + // being tested here, so the note is expected rather than a problem. + command.arg("-Wno-psabi"); + command.arg("-o"); + command.arg(&object); + command.arg(&source); + if let Some(env_path) = target_path(test_target) { + command.env("PATH", env_path); + } + + let status = command + .status() + .unwrap_or_else(|error| panic!("failed to run `{}`: {}", compiler, error)); + assert!(status.success(), "failed to compile `{}`", source.display()); + } +} + +/// The object file that a test source links against, if any: `tests/c/x.c` for `tests/run/x.rs`. +fn c_object_path(objects_dir: &Path, source: &Path) -> PathBuf { + objects_dir.join(source.file_stem().expect("file_stem")).with_extension("o") +} + fn compile_and_run_cmds( compiler_args: Vec, test_target: &Option, @@ -18,10 +86,7 @@ fn compile_and_run_cmds( // Test command 2: run `tempdir/x`. if test_target.is_some() { - let mut env_path = std::env::var("PATH").unwrap_or_default(); - // FIXME(antoyo): find a better way to add the PATH necessary locally. - env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path); - compiler.env("PATH", env_path); + compiler.env("PATH", target_path(test_target).expect("target PATH")); let mut commands = vec![("Compiler", compiler)]; if test_mode.should_run() { @@ -84,6 +149,7 @@ impl TestMode { fn build_test_runner( tempdir: PathBuf, + c_objects_dir: PathBuf, current_dir: String, build_mode: BuildMode, test_kind: &str, @@ -159,6 +225,13 @@ fn build_test_runner( path.to_str().expect("to_str").into(), ]; + // Link against `tests/c/.c`, when the test has one. + let c_object = c_object_path(&c_objects_dir, path); + if c_object.exists() { + compiler_args.push("-C".into()); + compiler_args.push(format!("link-arg={}", c_object.display())); + } + if let Some(ref target) = test_target { compiler_args.extend_from_slice(&["--target".into(), target.into()]); @@ -203,9 +276,10 @@ fn build_test_runner( .run(); } -fn compile_tests(tempdir: PathBuf, current_dir: String) { +fn compile_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { build_test_runner( tempdir, + c_objects_dir, current_dir, BuildMode::Debug, "lang compile", @@ -221,9 +295,10 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { ); } -fn run_tests(tempdir: PathBuf, current_dir: String) { +fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { build_test_runner( tempdir.clone(), + c_objects_dir.clone(), current_dir.clone(), BuildMode::Debug, "[DEBUG] lang run", @@ -233,6 +308,7 @@ fn run_tests(tempdir: PathBuf, current_dir: String) { ); build_test_runner( tempdir, + c_objects_dir, current_dir.to_string(), BuildMode::Release, "[RELEASE] lang run", @@ -248,6 +324,11 @@ fn main() { let current_dir = current_dir.to_str().expect("current dir").to_string(); let tempdir_path: PathBuf = tempdir.as_ref().into(); - compile_tests(tempdir_path.clone(), current_dir.clone()); - run_tests(tempdir_path, current_dir); + let c_objects_dir = tempdir_path.join("c-objects"); + // FIXME(antoyo): find a way to send this via a cli argument. + let test_target = std::env::var("CG_GCC_TEST_TARGET").ok(); + compile_c_files(&c_objects_dir, &test_target); + + compile_tests(tempdir_path.clone(), c_objects_dir.clone(), current_dir.clone()); + run_tests(tempdir_path, c_objects_dir, current_dir); } diff --git a/tests/run/overaligned_byval_abi.rs b/tests/run/overaligned_byval_abi.rs new file mode 100644 index 0000000000000..78ee35f05ca58 --- /dev/null +++ b/tests/run/overaligned_byval_abi.rs @@ -0,0 +1,89 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that cg_gcc passes an over-aligned by-value ("byval") argument where the platform ABI +// says it goes, by calling in both directions with `tests/c/overaligned_byval_abi.c`, which is +// compiled by the real GCC. +// +// `tests/run/overaligned_byval_arg.rs` covers the Rust-visible half of the same bug. It cannot +// cover this one: with cg_gcc on both sides of a call, caller and callee place the argument at +// the same wrong offset and agree with each other. +// +// Two over-aligned arguments are used rather than one so that the failure is deterministic. A +// backend that drops `align(64)` packs the arguments at offsets 0, 24, 88 and 112 of the argument +// area; 112 - 24 = 88 is not a multiple of 64, so the two of them cannot both land on a 64-byte +// boundary however the argument area itself is aligned. With a single over-aligned argument the +// frame often happens to be 64-aligned and the bug hides. +// +// Only the values received are checked, never the address an argument landed at: which alignment +// a target gives a by-value stack slot differs between targets, but the two sides of a call +// agreeing on it does not. `overaligned_byval_arg.rs` is where the alignment itself is asserted. + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[repr(C)] +struct Big { + a: i64, + b: i64, + c: i64, +} + +#[repr(C, align(64))] +struct Aligned { + x: i32, +} + +extern "C" { + fn c_take_both(first: Big, second: Aligned, third: Big, fourth: Aligned) -> i32; + fn c_call_rust() -> i32; +} + +// The callee for the GCC-built caller in `c_call_rust`. +// +// `#[no_mangle]` is not only about the symbol name: it makes the symbol externally visible, which +// pins the calling convention. Without it the function has internal linkage and GCC is free to +// clone it with a changed convention at `-O3` (the symbol comes out as `...constprop.0.isra.0`), +// so the arguments never travel through the stack slots and the release build passes spuriously. +#[no_mangle] +extern "C" fn rust_take_both(first: Big, second: Aligned, third: Big, fourth: Aligned) -> i32 { + if first.a as i32 != 1 || first.b as i32 != 2 || first.c as i32 != 3 { + return 5; + } + if second.x != 42 { + return 6; + } + if third.a as i32 != 4 || third.b as i32 != 5 || third.c as i32 != 6 { + return 7; + } + if fourth.x != 43 { + return 8; + } + 0 +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + // cg_gcc as the caller, GCC as the callee. + let result = unsafe { + c_take_both( + Big { a: 1, b: 2, c: 3 }, + Aligned { x: 42 }, + Big { a: 4, b: 5, c: 6 }, + Aligned { x: 43 }, + ) + }; + if result != 0 { + return result; + } + + // GCC as the caller, cg_gcc as the callee. + unsafe { c_call_rust() } +} From 80b9114ed632d61f29c999a84631fcfe085ce585 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 6 Aug 2026 12:58:34 -0400 Subject: [PATCH 0034/1309] Make type attributes less error-prone --- clippy.toml | 3 + src/abi.rs | 6 +- src/common.rs | 3 +- src/intrinsic/llvm.rs | 15 ++--- src/type_.rs | 127 ++++++++++++++++++++++++++---------------- src/type_of.rs | 18 +++--- 6 files changed, 104 insertions(+), 68 deletions(-) create mode 100644 clippy.toml diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000000..cf1593c691734 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,3 @@ +disallowed-methods = [ + { path = "gccjit::types::Type::add_attribute", reason = "go through `type_::apply_struct_attributes` instead: an attribute set directly on a type would not be part of the `CodegenCx::struct_types` cache key, so it would silently change every other use of that type" }, +] diff --git a/src/abi.rs b/src/abi.rs index ba798bab83fa4..fac5dfc32265f 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -73,9 +73,9 @@ impl GccType for CastTarget { args.push(cx.type_ix(rem_bytes * 8)); } - // A cast target describes registers, so its alignment is whatever GCC computes from - // them rather than the alignment of the Rust type being cast. - cx.type_struct(&args, false, None) + // A cast target describes registers, so its layout is whatever GCC computes from them + // rather than the layout of the Rust type being cast. + cx.type_struct(&args, &[]) } } diff --git a/src/common.rs b/src/common.rs index 5b89fc7aa639c..8d63f5a75a3b3 100644 --- a/src/common.rs +++ b/src/common.rs @@ -12,6 +12,7 @@ use rustc_session::PointerAuthSchema; use crate::consts::const_alloc_to_gcc; use crate::context::{CodegenCx, new_array_type}; +use crate::type_::struct_attributes; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -290,7 +291,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { // FIXME(antoyo): cache the type? It's anonymous, so probably not. // The alignment of a constant aggregate is the one GCC derives from its fields: the Rust // layout this comes from is not available here. - let typ = self.type_struct(&fields, packed, None); + let typ = self.type_struct(&fields, &struct_attributes(packed, None)); let struct_type = typ.is_struct().expect("struct type"); self.context.new_struct_constructor(None, struct_type.as_type(), None, values) } diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 6ad19d5af095e..ef381715c1ea2 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -1,12 +1,11 @@ use std::borrow::Cow; -#[cfg(feature = "master")] -use gccjit::TypeAttribute; use gccjit::{CType, Context, Field, Function, FunctionPtrType, RValue, ToRValue, Type}; use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; use crate::context::{CodegenCx, new_array_type}; +use crate::type_::{StructAttribute, apply_struct_attributes}; fn encode_key_128_type<'a, 'gcc, 'tcx>( builder: &Builder<'a, 'gcc, 'tcx>, @@ -24,8 +23,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( "EncodeKey128Output", &[field1, field2, field3, field4, field5, field6, field7], ); - #[cfg(feature = "master")] - encode_type.as_type().add_attribute(TypeAttribute::Packed); + apply_struct_attributes(encode_type.as_type(), &[StructAttribute::Packed]); (encode_type.as_type(), field1, field2) } @@ -46,8 +44,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( "EncodeKey256Output", &[field1, field2, field3, field4, field5, field6, field7, field8], ); - #[cfg(feature = "master")] - encode_type.as_type().add_attribute(TypeAttribute::Packed); + apply_struct_attributes(encode_type.as_type(), &[StructAttribute::Packed]); (encode_type.as_type(), field1, field2) } @@ -59,8 +56,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, m128i, "field2"); let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); - #[cfg(feature = "master")] - typ.add_attribute(TypeAttribute::Packed); + apply_struct_attributes(typ, &[StructAttribute::Packed]); (typ, field1, field2) } @@ -82,8 +78,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( "WideAesOutput", &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); - #[cfg(feature = "master")] - aes_output_type.as_type().add_attribute(TypeAttribute::Packed); + apply_struct_attributes(aes_output_type.as_type(), &[StructAttribute::Packed]); (aes_output_type.as_type(), field1, field2) } diff --git a/src/type_.rs b/src/type_.rs index e0f6d72d8fd15..cd0fb5aeda448 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -1,5 +1,6 @@ #[cfg(feature = "master")] use std::convert::TryInto; +use std::mem::discriminant; #[cfg(feature = "master")] use gccjit::{CType, TypeAttribute}; @@ -101,14 +102,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bool_type } - pub fn type_struct( - &self, - fields: &[Type<'gcc>], - packed: bool, - align: Option, - ) -> Type<'gcc> { - let align = normalize_struct_alignment(align); - let key = StructTypeKey { fields: fields.to_vec(), packed, align }; + pub fn type_struct(&self, fields: &[Type<'gcc>], attributes: &[StructAttribute]) -> Type<'gcc> { + let key = + StructTypeKey { fields: fields.to_vec(), attributes: canonical_attributes(attributes) }; if let Some(typ) = self.struct_types.borrow().get(&key) { return *typ; } @@ -120,62 +116,104 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { }) .collect(); let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); - if packed { - #[cfg(feature = "master")] - typ.add_attribute(TypeAttribute::Packed); - } - set_struct_alignment(typ, align); + // The attributes that are applied are the very ones the type is keyed on, so the two + // cannot drift apart. + apply_struct_attributes(typ, &key.attributes); self.struct_types.borrow_mut().insert(key, typ); typ } } +/// An attribute that can be set on a GCC struct type. +/// +/// This mirrors the subset of `gccjit::TypeAttribute` that cg_gcc needs, rather than using it +/// directly, because it must exist without the `master` feature and because it is what +/// `StructTypeKey` is keyed on. Adding a variant here is therefore all it takes to make a new +/// attribute part of the cache key: there is no second place to remember to update. +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum StructAttribute { + /// Alignment, in bytes. This can only ever raise a type's alignment: GCC starts the record + /// layout from `TYPE_ALIGN` and the fields can only push it further up. + Aligned(u32), + /// Lay the fields out without inserting padding between them. + Packed, +} + /// Identifies an anonymous struct type in `CodegenCx::struct_types`. /// -/// Everything that can make two of them distinct has to be part of it. In particular the -/// alignment: two Rust types can have the same field list and still differ in alignment (for -/// instance `struct { a: u64, b: u64 }` with and without `repr(align(16))`), and they must not -/// end up sharing a GCC type. +/// Two Rust types with the same field list can still need distinct GCC types — `struct { a: u64, +/// b: u64 }` with and without `repr(align(16))` produces the same fields — so every attribute has +/// to be part of the key. Holding them as one [`StructAttribute`] list rather than as separate +/// fields is what keeps that true when a new attribute is added. #[derive(Clone, Eq, Hash, PartialEq)] pub struct StructTypeKey<'gcc> { pub fields: Vec>, - pub packed: bool, - pub align: Option, + pub attributes: Vec, } -/// Discard an alignment that GCC would give the struct anyway. +/// The attributes a GCC struct needs in order to match the Rust layout it is built from. +/// +/// GCC derives a struct's alignment from its field list, so a `repr(align(N))` larger than what +/// the fields require would otherwise be lost. That is not only a layout concern: the ABI of a +/// by-value ("byval") argument depends on it, since `ix86_function_arg_boundary` reads +/// `TYPE_ALIGN` to pick the argument's stack slot. An over-aligned aggregate whose GCC type has +/// lost its alignment is passed at an offset a C caller does not agree on. /// -/// One byte is the minimum alignment of a GCC struct, so requesting it explicitly changes -/// nothing; mapping it to `None` keeps types that do not care about their alignment sharing a +/// An alignment of one byte is dropped: it is the minimum a GCC struct gets anyway, so asking for +/// it explicitly changes nothing, and dropping it keeps every alignment-indifferent type sharing a /// single entry in `CodegenCx::struct_types`. -fn normalize_struct_alignment(align: Option) -> Option { - align.filter(|align| align.bytes() > 1) +pub fn struct_attributes(packed: bool, align: Option) -> Vec { + let mut attributes = Vec::new(); + if packed { + attributes.push(StructAttribute::Packed); + } + if let Some(align) = align + && align.bytes() > 1 + { + attributes.push(StructAttribute::Aligned(align.bytes() as u32)); + } + attributes } -/// Give a struct type the alignment that Rust computed for it. +/// Put an attribute list into a canonical form so that it can be used as a cache key. /// -/// GCC derives a struct's alignment from its field list, so a `repr(align(N))` that is larger -/// than what the fields require would otherwise be lost. That is not only a layout concern: the -/// ABI of a by-value ("byval") argument depends on it, since `ix86_function_arg_boundary` reads -/// `TYPE_ALIGN` to pick the argument's stack slot. An over-aligned aggregate whose GCC type has -/// lost its alignment is therefore passed at an offset a C caller does not agree on. +/// Without this, `[Packed, Aligned(8)]` and `[Aligned(8), Packed]` would hash differently and mint +/// two GCC types for what is one Rust type. +fn canonical_attributes(attributes: &[StructAttribute]) -> Vec { + let mut attributes = attributes.to_vec(); + attributes.sort_unstable(); + attributes.dedup(); + debug_assert!( + attributes.windows(2).all(|pair| discriminant(&pair[0]) != discriminant(&pair[1])), + "contradictory struct attributes: {attributes:?}" + ); + attributes +} + +/// Set `attributes` on the struct type `typ`. /// -/// This has to be set on the struct type itself. `Type::get_aligned` is not enough: it builds a -/// type *variant*, and the argument-passing code looks at `TYPE_MAIN_VARIANT` first, which -/// discards it. +/// This is the only place allowed to call `Type::add_attribute`; `clippy.toml` forbids it +/// everywhere else. An attribute set on a type that `CodegenCx::struct_types` handed out would +/// change every other use of that type, so attributes have to be decided when the type is created +/// and be part of its cache key. Going through [`StructAttribute`] is what enforces that. /// -/// This never under-aligns a struct whose fields need more: GCC starts the record layout from -/// `TYPE_ALIGN` and the fields can only raise it. +/// Note that the alignment has to be set on the struct type itself: `Type::get_aligned` is not +/// enough, since it builds a type *variant* and the argument-passing code looks at +/// `TYPE_MAIN_VARIANT` first, which discards it. #[cfg(feature = "master")] -fn set_struct_alignment(typ: Type<'_>, align: Option) { - if let Some(align) = normalize_struct_alignment(align) { - typ.add_attribute(TypeAttribute::Aligned(align.bytes() as u32)); +#[allow(clippy::disallowed_methods)] +pub fn apply_struct_attributes(typ: Type<'_>, attributes: &[StructAttribute]) { + for attribute in attributes { + typ.add_attribute(match *attribute { + StructAttribute::Aligned(align) => TypeAttribute::Aligned(align), + StructAttribute::Packed => TypeAttribute::Packed, + }); } } -/// Without the `master` feature, libgccjit has no way to set a type's alignment. +/// Without the `master` feature, libgccjit cannot set attributes on a type. #[cfg(not(feature = "master"))] -fn set_struct_alignment(_typ: Type<'_>, _align: Option) {} +pub fn apply_struct_attributes(_typ: Type<'_>, _attributes: &[StructAttribute]) {} impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { @@ -382,8 +420,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, typ: Struct<'gcc>, fields: &[Type<'gcc>], - packed: bool, - align: Option, + attributes: &[StructAttribute], ) { let fields: Vec<_> = fields .iter() @@ -391,11 +428,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { .map(|(index, field)| self.context.new_field(None, *field, format!("field_{}", index))) .collect(); typ.set_fields(None, &fields); - if packed { - #[cfg(feature = "master")] - typ.as_type().add_attribute(TypeAttribute::Packed); - } - set_struct_alignment(typ.as_type(), align); + apply_struct_attributes(typ.as_type(), &canonical_attributes(attributes)); } pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { diff --git a/src/type_of.rs b/src/type_of.rs index da9a660e73dbf..409343c635182 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -17,7 +17,7 @@ use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; -use crate::type_::struct_fields; +use crate::type_::{struct_attributes, struct_fields}; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn type_from_unsigned_integer(&self, i: Integer) -> Type<'gcc> { @@ -81,8 +81,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( layout.scalar_pair_element_gcc_type(cx, 0), layout.scalar_pair_element_gcc_type(cx, 1), ], - false, - Some(layout.align.abi), + &struct_attributes(false, Some(layout.align.abi)), ); } BackendRepr::Memory { .. } => {} @@ -130,11 +129,12 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Primitive | FieldsShape::Union(_) => { let fill = cx.type_padding_filler(layout.size, layout.align.abi); let packed = false; + let attributes = struct_attributes(packed, Some(layout.align.abi)); match name { - None => cx.type_struct(&[fill], packed, Some(layout.align.abi)), + None => cx.type_struct(&[fill], &attributes), Some(ref name) => { let gcc_type = cx.type_named_struct(name); - cx.set_struct_body(gcc_type, &[fill], packed, Some(layout.align.abi)); + cx.set_struct_body(gcc_type, &[fill], &attributes); gcc_type.as_type() } } @@ -143,7 +143,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Arbitrary { .. } => match name { None => { let (gcc_fields, packed) = struct_fields(cx, layout); - cx.type_struct(&gcc_fields, packed, Some(layout.align.abi)) + cx.type_struct(&gcc_fields, &struct_attributes(packed, Some(layout.align.abi))) } Some(ref name) => { let gcc_type = cx.type_named_struct(name); @@ -241,7 +241,11 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { if let Some((deferred_ty, layout)) = defer { let (fields, packed) = struct_fields(cx, layout); - cx.set_struct_body(deferred_ty, &fields, packed, Some(layout.align.abi)); + cx.set_struct_body( + deferred_ty, + &fields, + &struct_attributes(packed, Some(layout.align.abi)), + ); } ty From d1525e2f206c2e91b6f271a46da6dfccf1b5aaf1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 6 Aug 2026 21:44:53 -0400 Subject: [PATCH 0035/1309] Guard on max GCC alignment --- src/type_.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/type_.rs b/src/type_.rs index cd0fb5aeda448..c3f6304ddae83 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -169,12 +169,23 @@ pub fn struct_attributes(packed: bool, align: Option) -> Vec 1 + && align.bytes() <= MAX_STRUCT_ALIGNMENT { attributes.push(StructAttribute::Aligned(align.bytes() as u32)); } attributes } +/// The largest alignment GCC accepts on a type, in bytes. +/// +/// This is `MAX_OFILE_ALIGNMENT / BITS_PER_UNIT` for ELF targets. Rust allows alignments up to +/// `1 << 29`, so a `repr(align(N))` beyond this simply cannot be expressed: asking for it makes +/// libgccjit fail the whole compilation with "requested alignment `N` exceeds maximum". Such a +/// type keeps whatever alignment GCC derives from its fields instead, which is what every type +/// got before alignments were set at all. See `tests/ui/abi/large-byval-align.rs`, which upstream +/// marks `ignore-backends: gcc` for this reason. +const MAX_STRUCT_ALIGNMENT: u64 = 1 << 28; + /// Put an attribute list into a canonical form so that it can be used as a cache key. /// /// Without this, `[Packed, Aligned(8)]` and `[Aligned(8), Packed]` would hash differently and mint From f525d92d0dec5f4a7fb4379743a6ca8fdc774eae Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 10:18:17 -0400 Subject: [PATCH 0036/1309] Cleanup --- src/abi.rs | 9 --------- src/common.rs | 2 -- src/type_.rs | 27 +-------------------------- tests/lang_tests.rs | 11 +++-------- 4 files changed, 4 insertions(+), 45 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index fac5dfc32265f..240bba0e75284 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -73,8 +73,6 @@ impl GccType for CastTarget { args.push(cx.type_ix(rem_bytes * 8)); } - // A cast target describes registers, so its layout is whatever GCC computes from them - // rather than the layout of the Rust type being cast. cx.type_struct(&args, &[]) } } @@ -212,13 +210,6 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { cx.type_ptr_to(arg.layout.gcc_type(cx)) } else { // This is a "byval" argument, so we don't apply the `restrict` attribute on it. - // - // GCC picks the argument's stack slot from the alignment of this type, - // which `LayoutGccExt::gcc_type` sets from `layout.align.abi`. We - // deliberately do not use `attrs.pointee_align` here: when it differs - // from the type's alignment it describes the *slot*, not the type, and - // rustc already copies the argument to a sufficiently aligned alloca on - // whichever side needs it. on_stack_param_indices.insert(argument_tys.len()); arg.layout.gcc_type(cx) } diff --git a/src/common.rs b/src/common.rs index 8d63f5a75a3b3..a503c1b345126 100644 --- a/src/common.rs +++ b/src/common.rs @@ -289,8 +289,6 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> { let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect(); // FIXME(antoyo): cache the type? It's anonymous, so probably not. - // The alignment of a constant aggregate is the one GCC derives from its fields: the Rust - // layout this comes from is not available here. let typ = self.type_struct(&fields, &struct_attributes(packed, None)); let struct_type = typ.is_struct().expect("struct type"); self.context.new_struct_constructor(None, struct_type.as_type(), None, values) diff --git a/src/type_.rs b/src/type_.rs index c3f6304ddae83..9b2896838e735 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -116,8 +116,6 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { }) .collect(); let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); - // The attributes that are applied are the very ones the type is keyed on, so the two - // cannot drift apart. apply_struct_attributes(typ, &key.attributes); self.struct_types.borrow_mut().insert(key, typ); typ @@ -132,8 +130,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { /// attribute part of the cache key: there is no second place to remember to update. #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] pub enum StructAttribute { - /// Alignment, in bytes. This can only ever raise a type's alignment: GCC starts the record - /// layout from `TYPE_ALIGN` and the fields can only push it further up. + /// Alignment, in bytes. Aligned(u32), /// Lay the fields out without inserting padding between them. Packed, @@ -152,16 +149,6 @@ pub struct StructTypeKey<'gcc> { } /// The attributes a GCC struct needs in order to match the Rust layout it is built from. -/// -/// GCC derives a struct's alignment from its field list, so a `repr(align(N))` larger than what -/// the fields require would otherwise be lost. That is not only a layout concern: the ABI of a -/// by-value ("byval") argument depends on it, since `ix86_function_arg_boundary` reads -/// `TYPE_ALIGN` to pick the argument's stack slot. An over-aligned aggregate whose GCC type has -/// lost its alignment is passed at an offset a C caller does not agree on. -/// -/// An alignment of one byte is dropped: it is the minimum a GCC struct gets anyway, so asking for -/// it explicitly changes nothing, and dropping it keeps every alignment-indifferent type sharing a -/// single entry in `CodegenCx::struct_types`. pub fn struct_attributes(packed: bool, align: Option) -> Vec { let mut attributes = Vec::new(); if packed { @@ -177,13 +164,6 @@ pub fn struct_attributes(packed: bool, align: Option) -> Vec Vec /// everywhere else. An attribute set on a type that `CodegenCx::struct_types` handed out would /// change every other use of that type, so attributes have to be decided when the type is created /// and be part of its cache key. Going through [`StructAttribute`] is what enforces that. -/// -/// Note that the alignment has to be set on the struct type itself: `Type::get_aligned` is not -/// enough, since it builds a type *variant* and the argument-passing code looks at -/// `TYPE_MAIN_VARIANT` first, which discards it. #[cfg(feature = "master")] #[allow(clippy::disallowed_methods)] pub fn apply_struct_attributes(typ: Type<'_>, attributes: &[StructAttribute]) { @@ -222,7 +198,6 @@ pub fn apply_struct_attributes(typ: Type<'_>, attributes: &[StructAttribute]) { } } -/// Without the `master` feature, libgccjit cannot set attributes on a type. #[cfg(not(feature = "master"))] pub fn apply_struct_attributes(_typ: Type<'_>, _attributes: &[StructAttribute]) {} diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 5426d777bb49e..ebce05a0597e0 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -10,9 +10,6 @@ use tempfile::TempDir; /// Directory holding the C files that the `tests/run` tests can link against. /// /// A `tests/c/.c` is compiled by the real GCC and linked into `tests/run/.rs`. -/// This is what makes it possible to test the ABI: with cg_gcc on both sides of a call, caller -/// and callee agree even when they are both wrong, so a pure-Rust test cannot notice. A C -/// caller or callee built by GCC is an independent reference. const C_TESTS_DIR: &str = "tests/c"; /// The m68k cross toolchain is not on the default `PATH` in CI. @@ -26,10 +23,7 @@ fn target_path(test_target: &Option) -> Option { }) } -/// Compile every C file in `tests/c` to an object file in `objects_dir`, named after the C file. -/// -/// The C files are compiled by the real GCC (the cross one when testing another target), not by -/// cg_gcc: they are the reference the Rust side is checked against. +/// Compile every C file in `tests/c` to an object file in `objects_dir`. fn compile_c_files(objects_dir: &Path, test_target: &Option) { let c_tests_dir = Path::new(C_TESTS_DIR); if !c_tests_dir.is_dir() { @@ -54,7 +48,7 @@ fn compile_c_files(objects_dir: &Path, test_target: &Option) { // Optimize: an unoptimized C caller can happen to agree with a wrong callee. command.arg("-O1"); // GCC notes that the ABI of over-aligned arguments changed in GCC 4.6. That is the ABI - // being tested here, so the note is expected rather than a problem. + // being tested in overaligned_byval_abi, so the note is expected rather than a problem. command.arg("-Wno-psabi"); command.arg("-o"); command.arg(&object); @@ -147,6 +141,7 @@ impl TestMode { } } +#[allow(clippy::too_many_arguments)] fn build_test_runner( tempdir: PathBuf, c_objects_dir: PathBuf, From 8ef525032677c4594b8959899613075a04b7a71a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 10:20:49 -0400 Subject: [PATCH 0037/1309] Remove spell checks in CI --- .cspell.json | 28 -------- .github/workflows/ci.yml | 7 -- tools/cspell_dicts/rust.txt | 3 - tools/cspell_dicts/rustc_codegen_gcc.txt | 83 ------------------------ 4 files changed, 121 deletions(-) delete mode 100644 .cspell.json delete mode 100644 tools/cspell_dicts/rust.txt delete mode 100644 tools/cspell_dicts/rustc_codegen_gcc.txt diff --git a/.cspell.json b/.cspell.json deleted file mode 100644 index a2856029c2c1a..0000000000000 --- a/.cspell.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "allowCompoundWords": true, - "dictionaries": ["cpp", "rust-extra", "rustc_codegen_gcc"], - "dictionaryDefinitions": [ - { - "name": "rust-extra", - "path": "tools/cspell_dicts/rust.txt", - "addWords": true - }, - { - "name": "rustc_codegen_gcc", - "path": "tools/cspell_dicts/rustc_codegen_gcc.txt", - "addWords": true - } - ], - "files": [ - "src/**/*.rs" - ], - "ignorePaths": [ - "src/intrinsic/archs.rs", - "src/intrinsic/old_archs.rs", - "src/intrinsic/llvm.rs" - ], - "ignoreRegExpList": [ - "/(FIXME|NOTE)\\([^)]+\\)/", - "__builtin_\\w*" - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b76c79fd10870..e58a1596bff0f 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -126,13 +126,6 @@ jobs: - uses: actions/checkout@v4 - run: python tools/check_intrinsics_duplicates.py - spell_check: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - uses: crate-ci/typos@v1.32.0 - - uses: streetsidesoftware/cspell-action@v7 - build_system: runs-on: ubuntu-24.04 steps: diff --git a/tools/cspell_dicts/rust.txt b/tools/cspell_dicts/rust.txt deleted file mode 100644 index 15faacd53d5a0..0000000000000 --- a/tools/cspell_dicts/rust.txt +++ /dev/null @@ -1,3 +0,0 @@ -lateout -repr -rmeta diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt deleted file mode 100644 index bae8edc9ffdf9..0000000000000 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ /dev/null @@ -1,83 +0,0 @@ -aapcs -addo -archs -ashl -ashr -cgcx -clzll -cmse -codegened -csky -ctfe -ctlz -ctpop -cttz -ctzll -flto -fmaximumf -fmuladd -fmuladdf -fminimumf -fmul -fptosi -fptosui -fptoui -fwrapv -gimple -hrtb -immediates -interner -liblto -llbb -llcx -llextra -llfn -lgcc -llmod -llresult -llret -ltrans -llty -llval -llvals -loong -lshr -masm -maximumf -maxnumf -mavx -mcmodel -minimumf -minnumf -miri -monomorphization -monomorphizations -monomorphized -monomorphizing -movnt -mulo -nvptx -pointee -powitf -reassoc -retag -riscv -rlib -roundevenf -rustc -sgpr -sitofp -sizet -spir -subo -sysv -tbaa -uitofp -unord -uninlined -utrunc -vgpr -xabort -xreg -xtensa -zext From 51584dda48b84c287003094dd3323754bf06d7d0 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 10:38:46 -0400 Subject: [PATCH 0038/1309] Fix test on m68k --- tests/c/overaligned_byval_abi.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/tests/c/overaligned_byval_abi.c b/tests/c/overaligned_byval_abi.c index e7575871e0689..826a104f185ea 100644 --- a/tests/c/overaligned_byval_abi.c +++ b/tests/c/overaligned_byval_abi.c @@ -12,21 +12,23 @@ * alignment the ABI gives a stack slot is target-specific, but caller and callee agreeing on it * is not. A disagreement makes the arguments arrive as garbage. */ +#include + struct Big { - long a, b, c; + int64_t a, b, c; }; struct __attribute__((aligned(64))) Aligned { - int x; + int32_t x; }; /* Defined on the Rust side. */ -extern int rust_take_both(struct Big first, struct Aligned second, struct Big third, - struct Aligned fourth); +extern int32_t rust_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth); /* Called from Rust: checks what a cg_gcc caller passed. */ -int c_take_both(struct Big first, struct Aligned second, struct Big third, - struct Aligned fourth) +int32_t c_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth) { if (first.a != 1 || first.b != 2 || first.c != 3) return 1; @@ -40,7 +42,7 @@ int c_take_both(struct Big first, struct Aligned second, struct Big third, } /* Called from Rust: passes the arguments the way the ABI says, for a cg_gcc callee to read. */ -int c_call_rust(void) +int32_t c_call_rust(void) { struct Big first = {1, 2, 3}; struct Big third = {4, 5, 6}; From 0a026ecdcabb7e39026e200fdebf3cd32026ac56 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 13 Jul 2026 21:29:12 -0400 Subject: [PATCH 0039/1309] Fix unwinding bug in release mode --- src/base.rs | 5 ++++ src/builder.rs | 52 ++++++++++++++++++++------------------- src/context.rs | 48 ++++++++++++++++++++++++++++++++++-- src/intrinsic/mod.rs | 1 + tests/run/catch_unwind.rs | 25 +++++++++++++++++++ 5 files changed, 104 insertions(+), 27 deletions(-) create mode 100644 tests/run/catch_unwind.rs diff --git a/src/base.rs b/src/base.rs index 041420e35d2b5..9c06c7090c8cb 100644 --- a/src/base.rs +++ b/src/base.rs @@ -149,6 +149,11 @@ pub fn compile_codegen_unit( // ... and now that we have everything pre-defined, fill out those definitions. for &(mono_item, item_data) in &mono_items { mono_item.define::>(&mut cx, cgu_name.as_str(), item_data); + + // Now that this function's blocks all exist, fill in the cleanup + // regions reconstructed from MIR while lowering its `invoke`s. + #[cfg(feature = "master")] + cx.populate_cleanup_regions(); } // If this codegen unit contains the main function, also create the diff --git a/src/builder.rs b/src/builder.rs index 4096679ba0959..0ccfa31722f17 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -36,6 +36,8 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; +#[cfg(feature = "master")] +use crate::context::PendingCleanup; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -652,23 +654,34 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let try_block = self.current_func().new_block("try"); + let current_func = self.current_func(); + let try_region = current_func.new_region(self.location); + let try_block = try_region.new_block("try"); let current_block = self.block; self.block = try_block; let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; - let return_value = self.new_temp(self.current_func(), self.location, call.get_type()); + let return_value = self.new_temp(current_func, self.location, call.get_type()); try_block.add_assignment(self.location, return_value, call); try_block.end_with_jump(self.location, then); - if self.cleanup_blocks.borrow().contains(&catch) { - self.block.add_try_finally(self.location, try_block, catch); + if self.cx.landing_pads.borrow().contains(&catch) { + let cleanup_region = current_func.new_region(self.location); + self.block.add_cleanup(self.location, try_region, cleanup_region); + self.cx + .pending_cleanups + .borrow_mut() + .push(PendingCleanup { region: cleanup_region, landing_pad: catch }); } else { - self.block.add_try_catch(self.location, try_block, catch); + let catch_region = current_func.new_region(self.location); + for clone in gccjit::clone_blocks(&[catch]) { + catch_region.add_block(clone); + } + self.block.add_try_catch(self.location, try_region, catch_region); } self.block.end_with_jump(self.location, then); @@ -1636,18 +1649,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: insert the current block in a variable so that a later call to invoke knows to // generate a try/finally instead of a try/catch for this block. - self.cleanup_blocks.borrow_mut().insert(self.block); - - let eh_pointer_builtin = - self.cx.context.get_target_builtin_function("__builtin_eh_pointer"); - let zero = self.cx.context.new_rvalue_zero(self.int_type); - let ptr = self.cx.context.new_call(self.location, eh_pointer_builtin, &[zero]); - - let value1_type = self.u8_type.make_pointer(); - let ptr = self.cx.context.new_cast(self.location, ptr, value1_type); - let value1 = ptr; - let value2 = zero; // FIXME(antoyo): set the proper value here (the type of exception?). + self.cx.landing_pads.borrow_mut().insert(self.block); + // A cleanup resumes by falling through: it never inspects the exception + // object. + let value1 = self.context.new_null(self.u8_type.make_pointer()); + let value2 = self.context.new_rvalue_zero(self.i32_type); (value1, value2) } @@ -1661,18 +1668,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) { - // FIXME(antoyo): generate the correct landing pad - self.cleanup_landing_pad(pers_fn); + self.set_personality_fn(pers_fn); } #[cfg(feature = "master")] - fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) { - let exn_type = exn0.get_type(); - let exn = self.context.new_cast(self.location, exn0, exn_type); - let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume"); - self.llbb() - .add_eval(self.location, self.context.new_call(self.location, unwind_resume, &[exn])); - self.unreachable(); + fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) { + // End the cleanup by falling off the end of its region body. + self.block.end_with_fallthrough(self.location); } #[cfg(not(feature = "master"))] diff --git a/src/context.rs b/src/context.rs index d971b7f32de3f..ebbdbb72516aa 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,8 @@ use std::cell::{Cell, RefCell}; use std::collections::HashMap; +#[cfg(feature = "master")] +use gccjit::Region; use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type}; use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; @@ -28,6 +30,12 @@ use crate::callee::get_fn; use crate::common::SignType; use crate::type_::StructTypeKey; +#[cfg(feature = "master")] +pub struct PendingCleanup<'gcc> { + pub region: Region<'gcc>, + pub landing_pad: Block<'gcc>, +} + #[cfg_attr(not(feature = "master"), expect(dead_code))] pub struct CodegenCx<'gcc, 'tcx> { /// A cache of converted ConstAllocs @@ -128,8 +136,14 @@ pub struct CodegenCx<'gcc, 'tcx> { pub pointee_infos: RefCell, Size), Option>>, + /// Blocks that are cleanup landing pads, so `invoke` can tell an unwind + /// edge into a cleanup from a catch/terminate. #[cfg(feature = "master")] - pub cleanup_blocks: RefCell>>, + pub landing_pads: RefCell>>, + /// Cleanup regions to be filled in once the function is fully codegened + /// (done in `populate_cleanup_regions`). + #[cfg(feature = "master")] + pub pending_cleanups: RefCell>>, /// The alignment of a u128/i128 type. // We cache this, since it is needed for alignment checks during loads. pub int128_align: Align, @@ -307,13 +321,43 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { rust_try_fn: Cell::new(None), pointee_infos: Default::default(), #[cfg(feature = "master")] - cleanup_blocks: Default::default(), + landing_pads: Default::default(), + #[cfg(feature = "master")] + pending_cleanups: Default::default(), }; // FIXME(antoyo): instead of doing this, add SsizeT to libgccjit. cx.isize_type = usize_type.to_signed(&cx); cx } + /// Fill in the member blocks of every pending cleanup region. + /// + /// Clone all blocks reachable from a cleanup block into the cleanup region. + #[cfg(feature = "master")] + pub fn populate_cleanup_regions(&self) { + let pending = std::mem::take(&mut *self.pending_cleanups.borrow_mut()); + + for cleanup in pending { + // The landing pad is the region's entry, so it must come first. + let mut blocks = vec![]; + let mut visited = FxHashSet::default(); + let mut stack = vec![cleanup.landing_pad]; + while let Some(block) = stack.pop() { + if !visited.insert(block) { + continue; + } + blocks.push(block); + stack.extend(block.get_successors()); + } + + for clone in gccjit::clone_blocks(&blocks) { + cleanup.region.add_block(clone); + } + } + + self.landing_pads.borrow_mut().clear(); + } + pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; debug_assert!( diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index bbf5acf702e21..1fb6f3d6864b8 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,6 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; +#[cfg(feature = "master")] use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; diff --git a/tests/run/catch_unwind.rs b/tests/run/catch_unwind.rs new file mode 100644 index 0000000000000..919213db5a4a5 --- /dev/null +++ b/tests/run/catch_unwind.rs @@ -0,0 +1,25 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: Caught + +#![feature(fn_traits, unboxed_closures)] + +struct Wrapper(A); + +impl R> FnOnce<()> for Wrapper { + type Output = R; + + #[inline] + extern "rust-call" fn call_once(self, _args: ()) -> R { + (self.0)() + } +} + +fn main() { + std::panic::set_hook(Box::new(|_| {})); + let result = std::panic::catch_unwind(Wrapper(|| panic!())); + assert!(result.is_err()); + println!("Caught"); +} From c52a94a97234a9484da0da5c0a34809e80848ec0 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 14:29:19 -0400 Subject: [PATCH 0040/1309] Remove passing UI tests --- tests/failing-ui-tests.txt | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 489d0412eb317..333f62637f5e6 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -6,8 +6,6 @@ tests/ui/consts/missing_span_in_backtrace.rs tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs -tests/ui/drop/panic-during-drop-14875.rs -tests/ui/drop/move-closure-drop-on-unwind.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/lto/thin-lto-inlines2.rs tests/ui/panic-runtime/lto-abort.rs @@ -49,11 +47,9 @@ tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs tests/ui/process/nofile-limit.rs -tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs tests/ui/statics/const_generics.rs -tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs tests/ui/iterators/iter-filter-count-debug-check.rs tests/ui/eii/default/call_impl.rs @@ -71,8 +67,4 @@ tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs tests/ui/extern/extern-types-field-offset.rs -tests/ui/panics/panic-in-dtor-drops-fields.rs -tests/ui/array-slice-vec/slice-panic-1.rs -tests/ui/array-slice-vec/slice-panic-2.rs -tests/ui/drop/enum-destructor-on-unwind.rs tests/ui/std/add-spawn-hook-reentrancy-159923.rs From 8278c7757d0f133d6efa565303ec5fa6af20fc5e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 15:50:42 -0400 Subject: [PATCH 0041/1309] Update GCC version --- Cargo.lock | 8 ++++---- Cargo.toml | 4 ++-- libgccjit.version | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cca0e1e590e28..c3b5192c048b7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "4.1.0" +version = "5.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "859af1dd2815fd0f8ca97f5917a595f18c415692b07e58993a6ad34ff13204d5" +checksum = "0d4c19a75fd8c674bbcd459fc8235ff38f8e5219c07fc3b022556fd28d16c909" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "2.0.0" +version = "3.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab6a00a243aba2a45442bfd72b28d871137d4dac094f13de7f48cf9705112ffe" +checksum = "54c3a46c818a4b7d6c8d572ed0f3513a091dcf8e8dbafbb58381c6062eaef942" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 141949e9189e6..c503cff670203 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,11 +20,11 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "4.1.0", features = ["dlopen"] } +gccjit = { version = "5.0.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. -#gccjit = { path = "../gccjit.rs", features = ["dlopen"] } +# gccjit = { path = "../gccjit.rs", features = ["dlopen"] } [dev-dependencies] boml = "0.3.1" diff --git a/libgccjit.version b/libgccjit.version index 7c141c20c4d3d..1ff77eb3efe4a 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -dfbee712e611693596ffec1de22177089c537491 +3498409672c805d51b46faaa4a14f8682de8e1bf From 406a6d06ed516ae8396d0fe823d7239187d43ccb Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 15:56:00 -0400 Subject: [PATCH 0042/1309] Fix compilation without the master feature --- src/intrinsic/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 1fb6f3d6864b8..bbf5acf702e21 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,7 +4,6 @@ mod simd; #[cfg(feature = "master")] use std::iter; -#[cfg(feature = "master")] use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; From 65f62e3072db24fb67870ce962e7f148c9b410bb Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 16:30:53 -0400 Subject: [PATCH 0043/1309] Remove passing UI tests --- tests/failing-ui-tests.txt | 6 ------ 1 file changed, 6 deletions(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 333f62637f5e6..3ebdab870c00b 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,9 +1,7 @@ tests/ui/asm/may_unwind.rs tests/ui/asm/x86_64/may_unwind.rs -tests/ui/drop/dynamic-drop-async.rs tests/ui/intrinsics/panic-uninitialized-zeroed.rs tests/ui/consts/missing_span_in_backtrace.rs -tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/process/println-with-broken-pipe.rs @@ -11,7 +9,6 @@ tests/ui/lto/thin-lto-inlines2.rs tests/ui/panic-runtime/lto-abort.rs tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs tests/ui/async-await/deep-futures-are-freeze.rs -tests/ui/coroutine/resume-after-return.rs tests/ui/simd/repr_packed.rs tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs tests/ui/consts/const_cmp_type_id.rs @@ -30,7 +27,6 @@ tests/ui/sanitizer/cfi/sized-associated-ty.rs tests/ui/sanitizer/cfi/can-reveal-opaques.rs tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs -tests/ui/runtime/rt-explody-panic-payloads.rs tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs @@ -51,7 +47,6 @@ tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs tests/ui/statics/const_generics.rs tests/ui/thir-print/offset_of.rs -tests/ui/iterators/iter-filter-count-debug-check.rs tests/ui/eii/default/call_impl.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs @@ -67,4 +62,3 @@ tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs tests/ui/extern/extern-types-field-offset.rs -tests/ui/std/add-spawn-hook-reentrancy-159923.rs From dbefafb29ae7b6ae68dea852b6ff9c8c4e281c5e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 17:30:30 -0400 Subject: [PATCH 0044/1309] Correctly implement assume to fix a warning in a UI test --- src/intrinsic/mod.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index bbf5acf702e21..47436d8d0742c 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -646,10 +646,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } fn assume(&mut self, value: Self::Value) { - // FIXME(antoyo): switch to assume when it exists. - // Or use something like this: - // #define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0) - self.expect(value, true); + // libgccjit currently has no direct equivalent of LLVM's `llvm.assume`, + // so use the idiom `if (!cond) __builtin_unreachable()`. + // FIXME: this should use IFN_ASSUME when we have internal functions in + // libgccjit. + let then_block = self.append_sibling_block("assume_holds"); + let unreachable_block = self.append_sibling_block("assume_violated"); + self.block.end_with_conditional(self.location, value, then_block, unreachable_block); + + self.switch_to_block(unreachable_block); + self.unreachable(); + + self.switch_to_block(then_block); } fn expect(&mut self, cond: Self::Value, _expected: bool) -> Self::Value { From e9f099839ed532ca052d112496cd5a389c434969 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 18:36:02 -0400 Subject: [PATCH 0045/1309] Improve assume and unreachable --- src/builder.rs | 2 ++ src/intrinsic/mod.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/src/builder.rs b/src/builder.rs index 0ccfa31722f17..550f09615ef4f 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -719,6 +719,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { + let abort = self.context.get_builtin_function("abort"); + self.block.add_eval(self.location, self.context.new_call(self.location, abort, &[])); let return_value = self.new_temp(self.current_func(), self.location, return_type); self.block.end_with_return(self.location, return_value) } diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 47436d8d0742c..9704fd7614ef6 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -25,6 +25,7 @@ use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; use rustc_middle::{bug, span_bug}; +use rustc_session::config::OptLevel; use rustc_span::{Span, Symbol, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; @@ -650,6 +651,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc // so use the idiom `if (!cond) __builtin_unreachable()`. // FIXME: this should use IFN_ASSUME when we have internal functions in // libgccjit. + if self.sess().opts.optimize == OptLevel::No { + return; + } let then_block = self.append_sibling_block("assume_holds"); let unreachable_block = self.append_sibling_block("assume_violated"); self.block.end_with_conditional(self.location, value, then_block, unreachable_block); From aa9101f2b51303dba92f933e343191dd5e7b76ed Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 7 Aug 2026 21:35:21 -0400 Subject: [PATCH 0046/1309] Ignore catch_unwind.rs test on m68k because of a GCC bug --- tests/lang_tests.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index ebce05a0597e0..7ec0ab877b025 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -299,7 +299,10 @@ fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { "[DEBUG] lang run", "tests/run", TestMode::CompileAndRun, - &[], + &[ + // FIXME: remove this when the unwind issue is fixed in GCC m68k upstream. + "catch_unwind.rs", + ], ); build_test_runner( tempdir, @@ -309,7 +312,10 @@ fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { "[RELEASE] lang run", "tests/run", TestMode::CompileAndRun, - &[], + &[ + // FIXME: remove this when the unwind issue is fixed in GCC m68k upstream. + "catch_unwind.rs", + ], ); } From e127e33c8249eeed17344b1915b22e1e9dd92739 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 8 Aug 2026 12:15:58 -0400 Subject: [PATCH 0047/1309] Run the libcore tests in release mode --- .github/workflows/ci.yml | 2 +- build_system/src/test.rs | 16 ++++++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index e58a1596bff0f..3bccb5ccdd72e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -36,7 +36,7 @@ jobs: "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", "--projects", - "--gcc-asm-tests", + "--gcc-asm-tests --test-release-libcore", ] steps: diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 6cc2282c8022f..d8333e15785db 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -31,6 +31,7 @@ fn get_runners() -> Runners { runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); + runners.insert("--test-release-libcore", ("Run libcore tests", test_release_libcore)); runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); @@ -766,12 +767,23 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { } fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { + test_libcore_inner(env, args, false) +} + +fn test_release_libcore(env: &Env, args: &TestArg) -> Result<(), String> { + test_libcore_inner(env, args, true) +} + +fn test_libcore_inner(env: &Env, args: &TestArg, release: bool) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] libcore"); let path = get_sysroot_dir().join("sysroot_src/library/coretests"); let _ = remove_dir_all(path.join("target")); - // FIXME(antoyo): run in release mode when we fix the failures. - run_cargo_command(&[&"test"], Some(&path), env, args)?; + let mut command: Vec<&dyn AsRef> = vec![&"test"]; + if release { + command.push(&"--release"); + } + run_cargo_command(&command, Some(&path), env, args)?; Ok(()) } From f30a91205f29909fc0d3edf7ab358a1d7d1864ff Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 8 Aug 2026 18:26:24 -0400 Subject: [PATCH 0048/1309] Remove passing LTO tests --- tests/failing-lto-tests.txt | 9 --------- 1 file changed, 9 deletions(-) diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index 345f1920e55ac..cd29bc1fd475c 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -1,12 +1,3 @@ tests/ui/lto/debuginfo-lto-alloc.rs -tests/ui/panic-runtime/lto-unwind.rs -tests/ui/uninhabited/uninhabited-transparent-return-abi.rs -tests/ui/coroutine/panic-drops-resume.rs -tests/ui/coroutine/panic-drops.rs -tests/ui/coroutine/panic-safe.rs -tests/ui/panic-handler/catch-unwind-during-unwind-68696.rs -tests/ui/threads-sendsync/task-stderr.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs -tests/ui/threads-sendsync/unwind-resource.rs -tests/ui/drop/drop-trait-enum.rs From df356ea82c5ed8bd0681e5dd0a966c8e7823c5c7 Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Sun, 9 Aug 2026 01:25:54 +0100 Subject: [PATCH 0049/1309] Finish the m68000 target CPU LLVM list for GCC --- src/gcc_util.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 56314dca5effa..4f5b1a9a9e098 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -114,7 +114,11 @@ pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> fn arch_to_gcc(name: &str) -> &str { match name { "M68000" => "68000", + "M68010" => "68010", "M68020" => "68020", + "M68030" => "68030", + "M68040" => "68040", + "M68060" => "68060", _ => name, } } From ed5fcc94319c7771df7c30ede9a0d53cb93eba8b Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Sun, 9 Aug 2026 01:40:27 +0100 Subject: [PATCH 0050/1309] Add explicit register support for m68k --- src/asm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/asm.rs b/src/asm.rs index a1d227157314b..8c5415172ce09 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -697,6 +697,7 @@ fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str { } InlineAsmReg::Arm(reg) => reg.name(), InlineAsmReg::AArch64(reg) => reg.name(), + InlineAsmReg::M68k(reg) => reg.name(), _ => unimplemented!(), } } From 5e9f15f1efeaab1446184f04359a54c516331c3e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 8 Aug 2026 14:26:30 -0400 Subject: [PATCH 0051/1309] Fix mismatched type without native 128-bit integers --- src/int.rs | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/int.rs b/src/int.rs index 0c9a755694577..9633539a16bd5 100644 --- a/src/int.rs +++ b/src/int.rs @@ -178,6 +178,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } else { debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let signed = a_type.is_compatible_with(self.i128_type); let func_name = match (operation, signed) { (BinaryOp::Plus, true) => "__rust_i128_add", @@ -187,7 +190,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!("unexpected additive operation {:?}", operation), }; let param_a = self.context.new_parameter(self.location, a_type, "a"); - let param_b = self.context.new_parameter(self.location, b_type, "b"); + let param_b = self.context.new_parameter(self.location, a_type, "b"); let func = self.context.new_function( self.location, FunctionType::Extern, @@ -238,10 +241,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } else { debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let sign = if signed { "" } else { "u" }; let func_name = format!("__{}{}ti3", sign, operation_name); let param_a = self.context.new_parameter(self.location, a_type, "a"); - let param_b = self.context.new_parameter(self.location, b_type, "b"); + let param_b = self.context.new_parameter(self.location, a_type, "b"); let func = self.context.new_function( self.location, FunctionType::Extern, @@ -470,7 +476,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { lhs_high = self.context.new_cast(self.location, lhs_high, signed_type); rhs_high = self.context.new_cast(self.location, rhs_high, signed_type); } - IntPredicate::IntEQ | IntPredicate::IntNE => (), + IntPredicate::IntEQ | IntPredicate::IntNE => { + lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); + rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); + } } let condition = self.context.new_comparison( @@ -637,6 +646,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } a ^ b } else { + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } self.concat_low_high_rvalues( a_type, self.low(a) ^ self.low(b), @@ -846,6 +858,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { !a_native && !b_native, "both types should either be native or non-native for or operation" ); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let native_int_type = a_type.dyncast_array().expect("get element type"); self.concat_low_high_rvalues( a_type, From d768a56cfa66e8236f9c9df19b4388dbb36500c2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 9 Aug 2026 15:36:20 +0200 Subject: [PATCH 0052/1309] Update GCC version to `201ca90ac810d1c6509c252cc9c87d3ace0661d7` --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 1ff77eb3efe4a..47539d889df51 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -3498409672c805d51b46faaa4a14f8682de8e1bf +201ca90ac810d1c6509c252cc9c87d3ace0661d7 From db95625174ec47a5d1b99aa92cc6b10f4c045999 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 9 Aug 2026 15:48:51 +0200 Subject: [PATCH 0053/1309] Update `gccjit.rs` dependency version to `6.0.0` --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/gcc_util.rs | 9 +++++---- src/lib.rs | 2 +- 4 files changed, 11 insertions(+), 10 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c3b5192c048b7..44aeab75c29e1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "5.0.0" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d4c19a75fd8c674bbcd459fc8235ff38f8e5219c07fc3b022556fd28d16c909" +checksum = "5bb358d2563af5e32af92620915e6b05839ae60645343473735619441f45eb04" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "3.0.0" +version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "54c3a46c818a4b7d6c8d572ed0f3513a091dcf8e8dbafbb58381c6062eaef942" +checksum = "2389fb01673e9cc63684d996a58079edccc5de89008274f3be59f1b16ac1f017" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index c503cff670203..1aff8ed115e1e 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "5.0.0", features = ["dlopen"] } +gccjit = { version = "6.0.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 56314dca5effa..5524cfad32da5 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::collections::HashSet; use std::env; @@ -119,22 +120,22 @@ fn arch_to_gcc(name: &str) -> &str { } } -fn handle_native(name: &str) -> &str { +fn handle_native(name: &str) -> Cow<'_, str> { if name != NATIVE_CPU { - return arch_to_gcc(name); + return arch_to_gcc(name).into(); } #[cfg(feature = "master")] { // Get the native arch. let context = Context::default(); - context.get_target_info().arch().unwrap().to_str().unwrap() + Cow::Owned(context.get_target_info().arch().to_str().unwrap().to_string()) } #[cfg(not(feature = "master"))] unimplemented!(); } -pub fn target_cpu(sess: &Session) -> &str { +pub fn target_cpu(sess: &Session) -> Cow<'_, str> { match sess.opts.cg.target_cpu { Some(ref name) => handle_native(name), None => handle_native(sess.target.cpu.as_ref()), diff --git a/src/lib.rs b/src/lib.rs index 436f8a1176300..2819e04261acb 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -288,7 +288,7 @@ impl CodegenBackend for GccCodegenBackend { } fn target_cpu(&self, sess: &Session) -> String { - target_cpu(sess).to_owned() + target_cpu(sess).into_owned() } fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { From 14bc9eb88275b47e0acba8e0f6245a26e951caa8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 9 Aug 2026 10:14:28 -0400 Subject: [PATCH 0054/1309] Improve failing tests lists --- build_system/src/test.rs | 58 +++++++++++++++++++++++++------------ tests/failing-lto-tests.txt | 2 ++ tests/failing-ui-tests.txt | 33 --------------------- 3 files changed, 42 insertions(+), 51 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index d8333e15785db..3ea62b9579870 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1002,6 +1002,8 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< // * `prepare_files_callback`: A callback function that prepares the files needed for the test. Its used to remove/retain tests giving Error to run various rust test suits. // * `run_error_pattern_test`: A boolean that determines whether to run only error pattern tests. // * `test_type`: A string that indicates the type of the test being run. +// * `retained_tests_list_path`: The list of tests that `prepare_files_callback` retained, if any. +// It is checked against the tests remaining after the filtering to report dead lines. // fn test_rustc_inner( env: &Env, @@ -1009,7 +1011,7 @@ fn test_rustc_inner( prepare_files_callback: F, run_error_pattern_test: bool, test_type: &str, - run_ignored_tests: bool, + retained_tests_list_path: Option<&str>, ) -> Result<(), String> where F: Fn(&Path) -> Result, @@ -1079,6 +1081,9 @@ where false, )?; } + if let Some(retained_tests_list_path) = retained_tests_list_path { + check_for_dead_listed_tests(&rust_path, retained_tests_list_path)?; + } let nb_parts = args.nb_parts.unwrap_or(0); if nb_parts > 0 { let current_part = args.current_part.unwrap(); @@ -1137,7 +1142,7 @@ where env.get_mut("RUSTFLAGS").unwrap().clear(); let test_dir = format!("tests/{test_type}"); - let mut command: Vec<&dyn AsRef> = vec![ + let command: Vec<&dyn AsRef> = vec![ &"./x.py", &"test", &"--run", @@ -1152,19 +1157,36 @@ where &"--bypass-ignore-backends", ]; - if run_ignored_tests { - command.push(&"--"); - command.push(&"--ignored"); - } - run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; Ok(()) } +/// Checks that every test listed in `list_path` survived the filtering done by +/// `contains_ui_error_patterns`. +fn check_for_dead_listed_tests(rust_path: &Path, list_path: &str) -> Result<(), String> { + let listed_tests = std::fs::read_to_string(list_path) + .map_err(|error| format!("Failed to read `{list_path}`: {error:?}"))?; + let dead_tests = listed_tests + .lines() + .map(|line| line.trim()) + .filter(|line| !line.is_empty() && !rust_path.join(line).exists()) + .collect::>(); + if dead_tests.is_empty() { + return Ok(()); + } + Err(format!( + "The following tests listed in `{list_path}` are filtered out before the tests are run, \ + so listing them has no effect:\n{}\n\nThis happens when a test contains an error pattern \ + (like `//~` or `//@ known-bug`), in which case it should be removed from `{list_path}`, \ + or when it uses LTO, in which case it should be moved to `tests/failing-lto-tests.txt`.", + dead_tests.join("\n") + )) +} + fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> { - test_rustc_inner(env, args, |_| Ok(false), false, "run-make", false)?; - test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo", false)?; - test_rustc_inner(env, args, |_| Ok(false), false, "ui", false) + test_rustc_inner(env, args, |_| Ok(false), false, "run-make", None)?; + test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo", None)?; + test_rustc_inner(env, args, |_| Ok(false), false, "ui", None) } fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { @@ -1174,7 +1196,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { retain_files_callback("tests/failing-run-make-tests.txt", "run-make"), false, "run-make", - true, + None, ); let run_make_cargo_result = test_rustc_inner( @@ -1182,8 +1204,8 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { args, retain_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"), false, - "run-make", - true, + "run-make-cargo", + None, ); let ui_result = test_rustc_inner( @@ -1192,7 +1214,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { retain_files_callback("tests/failing-ui-tests.txt", "ui"), false, "ui", - true, + Some("tests/failing-ui-tests.txt"), ); run_make_result.and(run_make_cargo_result).and(ui_result) @@ -1205,7 +1227,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { remove_files_callback("tests/failing-ui-tests.txt", "ui"), false, "ui", - false, + None, )?; test_rustc_inner( env, @@ -1213,7 +1235,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { remove_files_callback("tests/failing-run-make-tests.txt", "run-make"), false, "run-make", - false, + None, )?; test_rustc_inner( env, @@ -1221,7 +1243,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { remove_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"), false, "run-make-cargo", - false, + None, ) } @@ -1232,7 +1254,7 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String remove_files_callback("tests/failing-ice-tests.txt", "ui"), true, "ui", - false, + None, ) } diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index cd29bc1fd475c..7527005321991 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -1,3 +1,5 @@ tests/ui/lto/debuginfo-lto-alloc.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +tests/ui/lto/thin-lto-inlines2.rs +tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 3ebdab870c00b..2cf6925c0b527 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,44 +1,11 @@ tests/ui/asm/may_unwind.rs tests/ui/asm/x86_64/may_unwind.rs tests/ui/intrinsics/panic-uninitialized-zeroed.rs -tests/ui/consts/missing_span_in_backtrace.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/process/println-with-broken-pipe.rs -tests/ui/lto/thin-lto-inlines2.rs -tests/ui/panic-runtime/lto-abort.rs -tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs -tests/ui/async-await/deep-futures-are-freeze.rs tests/ui/simd/repr_packed.rs -tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs -tests/ui/consts/const_cmp_type_id.rs -tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs -tests/ui/sanitizer/cfi/async-closures.rs -tests/ui/sanitizer/cfi/closures.rs -tests/ui/sanitizer/cfi/complex-receiver.rs -tests/ui/sanitizer/cfi/coroutine.rs -tests/ui/sanitizer/cfi/drop-in-place.rs -tests/ui/sanitizer/cfi/drop-no-principal.rs -tests/ui/sanitizer/cfi/fn-ptr.rs -tests/ui/sanitizer/cfi/self-ref.rs -tests/ui/sanitizer/cfi/supertraits.rs -tests/ui/sanitizer/cfi/virtual-auto.rs -tests/ui/sanitizer/cfi/sized-associated-ty.rs -tests/ui/sanitizer/cfi/can-reveal-opaques.rs -tests/ui/consts/const-eval/parse_ints.rs tests/ui/simd/intrinsic/generic-as.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs From 5173175fe062152b40a0f95c9be5d1c6937462ad Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 9 Aug 2026 14:20:40 -0400 Subject: [PATCH 0055/1309] Use rust target triple instead of LLVM's --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2819e04261acb..79af9c5b83aef 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -205,7 +205,7 @@ impl CodegenBackend for GccCodegenBackend { .join(rustlib_path) .join("codegen-backends") .join("lib") - .join(sess.target.llvm_target.as_ref()) + .join(sess.opts.target_triple.tuple()) .join("libgccjit.so") } From 0bc3bfe9e689d4ed11e4d17eaf5f04fe3e5c3c69 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 10 Aug 2026 10:03:01 -0400 Subject: [PATCH 0056/1309] Load libgccjit from the LLVM target path as a fallback --- src/lib.rs | 37 ++++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/src/lib.rs b/src/lib.rs index 79af9c5b83aef..7e22d6db50cc1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -97,7 +97,7 @@ use rustc_middle::util::Providers; use rustc_session::Session; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::RelocModel; +use rustc_target::spec::{RelocModel, TargetTuple}; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; @@ -196,37 +196,44 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&self, sess: &Session) { - fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { + fn file_paths(sysroot_path: &Path, sess: &Session) -> Vec { let rustlib_path = rustc_target::relative_target_rustlib_path( sysroot_path, rustc_session::config::host_tuple(), ); - sysroot_path - .join(rustlib_path) - .join("codegen-backends") - .join("lib") - .join(sess.opts.target_triple.tuple()) - .join("libgccjit.so") + let lib_path = sysroot_path.join(rustlib_path).join("codegen-backends").join("lib"); + let rust_target_path = + lib_path.join(sess.opts.target_triple.tuple()).join("libgccjit.so"); + let mut paths = vec![rust_target_path]; + if matches!(sess.opts.target_triple, TargetTuple::TargetJson { .. }) { + let llvm_target_path = + lib_path.join(sess.target.llvm_target.as_ref()).join("libgccjit.so"); + paths.push(llvm_target_path); + } + paths } // We use all_paths() instead of only path() in case the path specified by --sysroot is // invalid. // This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null. - for path in sess.opts.sysroot.all_paths() { - let libgccjit_target_lib_file = file_path(path, sess); - if let Ok(true) = fs::exists(&libgccjit_target_lib_file) { - load_libgccjit_if_needed(&libgccjit_target_lib_file); - break; + 'sysroot: for path in sess.opts.sysroot.all_paths() { + for libgccjit_target_lib_file in file_paths(path, sess) { + if let Ok(true) = fs::exists(&libgccjit_target_lib_file) { + load_libgccjit_if_needed(&libgccjit_target_lib_file); + break 'sysroot; + } } } if !gccjit::is_loaded() { let mut paths = vec![]; for path in sess.opts.sysroot.all_paths() { - let libgccjit_target_lib_file = file_path(path, sess); - paths.push(libgccjit_target_lib_file); + for libgccjit_target_lib_file in file_paths(path, sess) { + paths.push(libgccjit_target_lib_file); + } } + paths.dedup(); panic!("Could not load libgccjit.so. Attempted paths: {:#?}", paths); } From bcd89373cc133f485bec43ec1188c75298fa5103 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 4 Aug 2026 14:41:47 -0700 Subject: [PATCH 0057/1309] Upgrade and deduplicate dependencies - Upgrade from `getrandom v0.4.2` to `v0.4.3` to drop its `wasip2` and `wasip3` dependencies and many transitives. - Upgrade from `gimli v0.33` to `v0.34` as a direct dependency and through a `thorin-dwp` upgrade. - Upgrade from `object v0.37` and `v0.38` to `v0.39` as a direct dependency and via `ar_archive_writer` and `thorin-dwp` upgrades. - Upgrade `libloading` and `wasmparser` to match other dependencies. This also consolidates from `hashbrown v0.15`, `v0.16`, and `v0.17` to just `v0.17.1`, which is the same that `std` currently uses. --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a283ea4cb0b05..7ce94b58c0516 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -145,9 +145,9 @@ dependencies = [ [[package]] name = "object" -version = "0.37.1" +version = "0.39.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03fd943161069e1768b4b3d050890ba48730e590f57e56d4aa04e7e090e61b4a" +checksum = "2e5a6c098c7a3b6547378093f5cc30bc54fd361ce711e05293a5cc589562739b" dependencies = [ "memchr", ] diff --git a/Cargo.toml b/Cargo.toml index 8956bd6948979..ac5e94b9454e2 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -18,7 +18,7 @@ master = ["gccjit/master"] default = ["master"] [dependencies] -object = { version = "0.37.0", default-features = false, features = ["std", "read"] } +object = { version = "0.39.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" gccjit = { version = "3.3.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } From 3c300ce6e7eb146be5526729c22511fa1ee6a012 Mon Sep 17 00:00:00 2001 From: beetrees Date: Mon, 10 Aug 2026 12:41:42 +0100 Subject: [PATCH 0058/1309] Add MSA and `f16` inline ASM support for MIPS --- src/asm.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index ee0cef350b42f..7cc098431d21a 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -733,7 +733,7 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::reg) => "r", InlineAsmRegClass::CSKY(CSKYInlineAsmRegClass::freg) => "f", InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => "d", // more specific than "r" - InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg | MipsInlineAsmRegClass::wreg) => "f", InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => "r", // https://github.com/gcc-mirror/gcc/blob/master/gcc/config/nvptx/nvptx.md -> look for // "define_constraint". @@ -843,6 +843,7 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl } InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => cx.type_i32(), InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::wreg) => cx.type_vector(cx.type_i32(), 4), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(), InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(), @@ -1084,7 +1085,9 @@ fn modifier_to_gcc( modifier } } - InlineAsmRegClass::Mips(_) => None, + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::reg) => None, + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::freg) => modifier, + InlineAsmRegClass::Mips(MipsInlineAsmRegClass::wreg) => Some('w'), InlineAsmRegClass::Nvptx(_) => None, InlineAsmRegClass::PowerPC(PowerPCInlineAsmRegClass::vsreg) => { if modifier.is_none() { From ca241a485dd6cb1b475b0ef204ab7d83566a4137 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 28 Jul 2026 11:25:42 +0200 Subject: [PATCH 0059/1309] atomic volatile: add intrinsics --- src/builder.rs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index a407362638f10..88049d67964b1 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -81,8 +81,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { AtomicOrdering::AcqRel | AtomicOrdering::Release => AtomicOrdering::Acquire, _ => order, }; - let previous_value = - self.atomic_load(dst.get_type(), dst, load_ordering, Size::from_bytes(size)); + let previous_value = self.atomic_load( + dst.get_type(), + dst, + load_ordering, + /* volatile */ false, + Size::from_bytes(size), + ); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); @@ -1008,6 +1013,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _ty: Type<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, + _volatile: bool, // FIXME we are always making the load volatile size: Size, ) -> RValue<'gcc> { // FIXME(antoyo): use ty. @@ -1177,6 +1183,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { value: RValue<'gcc>, ptr: RValue<'gcc>, order: AtomicOrdering, + _volatile: bool, // FIXME we are always making the store volatile size: Size, ) { // FIXME(antoyo): handle alignment. From d7a283df36d3574b791a39e781b3f4df6c787ff1 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 11 Aug 2026 22:37:26 +0100 Subject: [PATCH 0060/1309] Add floating point inline ASM support for SPARC --- src/asm.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/asm.rs b/src/asm.rs index ee0cef350b42f..ac86fbe7428b0 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -790,6 +790,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => "r", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::freg) => "f", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::dreg) => "e", + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::qreg) => "e", InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Err => unreachable!(), } @@ -896,6 +899,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl unreachable!("clobber-only") } InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::reg) => cx.type_i32(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::freg) => cx.type_f32(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::dreg) => cx.type_f64(), + InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::qreg) => cx.type_f128(), InlineAsmRegClass::Sparc(SparcInlineAsmRegClass::yreg) => unreachable!("clobber-only"), InlineAsmRegClass::Msp430(Msp430InlineAsmRegClass::reg) => cx.type_i16(), InlineAsmRegClass::M68k(M68kInlineAsmRegClass::reg) => cx.type_i32(), From 4256f1db7215614bd155e30c50806c49f5447c2b Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Tue, 18 Aug 2026 13:37:42 -0700 Subject: [PATCH 0061/1309] reformat --- src/context.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/context.rs b/src/context.rs index 8045e8ae9d28f..19fbe37c27b9e 100644 --- a/src/context.rs +++ b/src/context.rs @@ -495,7 +495,9 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let entry_name = self.sess().target.entry_name.as_ref(); if !self.functions.borrow().contains_key(entry_name) { let conv = cfg_select! { - feature = "master" => conv_to_fn_attribute(self.sess(), self.sess().target.entry_abi), + feature = "master" => { + conv_to_fn_attribute(self.sess(), self.sess().target.entry_abi) + } _ => None, }; Some(self.declare_entry_fn(entry_name, fn_type, conv)) From 568de9ac7234e254f76b2cffe2121d03da31d551 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Thu, 20 Aug 2026 18:17:55 +0800 Subject: [PATCH 0062/1309] Mark default EII function aliases as weak --- src/mono_item.rs | 5 +++++ tests/failing-ui-tests.txt | 1 - 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index 7513978b12272..3c1705cfa9384 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -153,6 +153,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); + #[cfg(feature = "master")] + if linkage == Linkage::WeakAny { + fn_decl.add_attribute(FnAttribute::Weak); + } + // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 2cf6925c0b527..0e31935d55e09 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -14,7 +14,6 @@ tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs tests/ui/statics/const_generics.rs tests/ui/thir-print/offset_of.rs -tests/ui/eii/default/call_impl.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs tests/ui/eii/static/cross_crate_decl.rs From 9c5bcb6045340063a6f42d8858a1343269420acd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Thu, 20 Aug 2026 18:18:26 +0800 Subject: [PATCH 0063/1309] Fix EII static alias declarations --- src/mono_item.rs | 45 +++++++++++++++++++++----------------- tests/failing-ui-tests.txt | 8 ------- 2 files changed, 25 insertions(+), 28 deletions(-) diff --git a/src/mono_item.rs b/src/mono_item.rs index 3c1705cfa9384..93b0372587277 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,6 +1,6 @@ use gccjit::Function; #[cfg(feature = "master")] -use gccjit::{FnAttribute, LValue, ToRValue, VarAttribute}; +use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; @@ -34,19 +34,13 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { let gcc_type = self.layout_of(ty).gcc_type(self); let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + let global = self.define_global(global_name, gcc_type, is_tls, attrs.link_section); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + // FIXME(antoyo): set linkage. - let create_global = |this: &CodegenCx<'gcc, 'tcx>, name: &str, visibility: Visibility| { - let global = this.define_global(name, gcc_type, is_tls, attrs.link_section); - #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); - // FIXME(antoyo): set linkage. - global - }; - let global = create_global(self, global_name, visibility); - - let attrs = self.tcx.codegen_instance_attrs(instance.def); #[cfg(feature = "master")] - self.add_static_aliases(&attrs.foreign_item_symbol_aliases, global_name, &create_global); + self.add_static_aliases(gcc_type, global_name, attrs, &attrs.foreign_item_symbol_aliases); self.instances.borrow_mut().insert(instance, global); } @@ -75,20 +69,31 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] - fn add_static_aliases( + fn add_static_aliases( &self, - aliases: &[(DefId, Linkage, Visibility)], + gcc_type: Type<'gcc>, aliased: &str, - create_global: &F, - ) where - F: Fn(&CodegenCx<'gcc, 'tcx>, &str, Visibility) -> LValue<'gcc>, - { - for &(alias, _linkage, visibility) in aliases { + attrs: &CodegenFnAttrs, + aliases: &[(DefId, Linkage, Visibility)], + ) { + let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + + for &(alias, linkage, visibility) in aliases { let instance = Instance::mono(self.tcx, alias); let symbol_name = self.tcx.symbol_name(instance); - let alias = create_global(self, symbol_name.name, visibility); + let alias = self.declare_global( + symbol_name.name, + gcc_type, + GlobalKind::Imported, + is_tls, + attrs.link_section, + ); + alias.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); alias.add_attribute(VarAttribute::Alias(aliased)); + if linkage == Linkage::WeakAny { + alias.add_attribute(VarAttribute::Weak); + } // Add the alias name to the set of cached items, so there is no duplicate // instance added to it during the normal `external static` codegen diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index 0e31935d55e09..ce614fecba2ba 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -16,14 +16,6 @@ tests/ui/statics/const_generics.rs tests/ui/thir-print/offset_of.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/eii/static/cross_crate_decl.rs -tests/ui/eii/static/cross_crate_def.rs -tests/ui/eii/static/same_address.rs -tests/ui/eii/static/simple.rs -tests/ui/eii/static/default.rs -tests/ui/eii/static/default_cross_crate.rs -tests/ui/eii/static/default_explicit.rs -tests/ui/eii/static/default_cross_crate_explicit.rs tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs tests/ui/abi/rust-tail-cc.rs tests/ui/abi/rust-preserve-none-cc.rs From fcf456259d86219325234f0bc22363e4534e8ba6 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Thu, 20 Aug 2026 19:21:22 +0300 Subject: [PATCH 0064/1309] neon: drop the align requirement on vld1/vst1 lane loads and stores vld1 and vst1 lane intrinsics were dereferencing pointer directly which requires it to be aligned to the element type. (Too strict alignment requirements) The instructions don't requires alignment, so calling these with unaligned pointer caused UB. Lane loads and stores were updated to use `read_unaligned()` and `write_unaligned()` instead. --- .../core_arch/src/aarch64/neon/generated.rs | 4 +- .../crates/core_arch/src/aarch64/neon/mod.rs | 4 +- .../src/arm_shared/neon/generated.rs | 116 +++++++++--------- .../src/arm_shared/neon/load_tests.rs | 29 +++++ .../src/arm_shared/neon/store_tests.rs | 24 ++++ .../spec/neon/aarch64.spec.yml | 10 +- .../spec/neon/arm_shared.spec.yml | 43 +++---- 7 files changed, 131 insertions(+), 99 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs index 1b5b17e538bde..c471880919eb6 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/generated.rs @@ -25081,7 +25081,7 @@ pub unsafe fn vst1q_f64_x4(a: *mut f64, b: float64x2x4_t) { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f64)"] @@ -25094,7 +25094,7 @@ pub unsafe fn vst1_lane_f64(a: *mut f64, b: float64x1_t) { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vst1q_lane_f64(a: *mut f64, b: float64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + core::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple 2-element structures from two registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst2_f64)"] diff --git a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs index c66702814cfb2..e04c93ac1acae 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/neon/mod.rs @@ -120,7 +120,7 @@ pub unsafe fn vld1q_dup_f64(ptr: *const f64) -> float64x2_t { #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) -> float64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } /// Load one single-element structure to one lane of one register. @@ -131,7 +131,7 @@ pub unsafe fn vld1_lane_f64(ptr: *const f64, src: float64x1_t) #[stable(feature = "neon_intrinsics", since = "1.59.0")] pub unsafe fn vld1q_lane_f64(ptr: *const f64, src: float64x2_t) -> float64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } /// Bitwise Select instructions. This instruction sets each bit in the destination SIMD&FP register diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 3a47ede1acc88..2c6f663d6ed08 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -19307,7 +19307,7 @@ pub unsafe fn vld1q_f32_x4(a: *const f32) -> float32x4x4_t { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) -> float16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f16)"] @@ -19327,7 +19327,7 @@ pub unsafe fn vld1_lane_f16(ptr: *const f16, src: float16x4_t) #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) -> float16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_f32)"] @@ -19352,7 +19352,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) )] pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) -> float32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p16)"] @@ -19377,7 +19377,7 @@ pub unsafe fn vld1_lane_f32(ptr: *const f32, src: float32x2_t) )] pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) -> poly16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p8)"] @@ -19402,7 +19402,7 @@ pub unsafe fn vld1_lane_p16(ptr: *const p16, src: poly16x4_t) - )] pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> poly8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s16)"] @@ -19427,7 +19427,7 @@ pub unsafe fn vld1_lane_p8(ptr: *const p8, src: poly8x8_t) -> p )] pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> int16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s32)"] @@ -19452,7 +19452,7 @@ pub unsafe fn vld1_lane_s16(ptr: *const i16, src: int16x4_t) -> )] pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> int32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s64)"] @@ -19462,7 +19462,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19477,7 +19477,7 @@ pub unsafe fn vld1_lane_s32(ptr: *const i32, src: int32x2_t) -> )] pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> int64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_s8)"] @@ -19502,7 +19502,7 @@ pub unsafe fn vld1_lane_s64(ptr: *const i64, src: int64x1_t) -> )] pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> int8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u16)"] @@ -19527,7 +19527,7 @@ pub unsafe fn vld1_lane_s8(ptr: *const i8, src: int8x8_t) -> in )] pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) -> uint16x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u32)"] @@ -19552,7 +19552,7 @@ pub unsafe fn vld1_lane_u16(ptr: *const u16, src: uint16x4_t) - )] pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) -> uint32x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u64)"] @@ -19562,7 +19562,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19577,7 +19577,7 @@ pub unsafe fn vld1_lane_u32(ptr: *const u32, src: uint32x2_t) - )] pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) -> uint64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_u8)"] @@ -19602,7 +19602,7 @@ pub unsafe fn vld1_lane_u64(ptr: *const u64, src: uint64x1_t) - )] pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> uint8x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_f32)"] @@ -19627,7 +19627,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u )] pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) -> float32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p16)"] @@ -19652,7 +19652,7 @@ pub unsafe fn vld1q_lane_f32(ptr: *const f32, src: float32x4_t) )] pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) -> poly16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p8)"] @@ -19677,7 +19677,7 @@ pub unsafe fn vld1q_lane_p16(ptr: *const p16, src: poly16x8_t) )] pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> poly8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s16)"] @@ -19702,7 +19702,7 @@ pub unsafe fn vld1q_lane_p8(ptr: *const p8, src: poly8x16_t) -> )] pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) -> int16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s32)"] @@ -19727,7 +19727,7 @@ pub unsafe fn vld1q_lane_s16(ptr: *const i16, src: int16x8_t) - )] pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) -> int32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s64)"] @@ -19737,7 +19737,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19752,7 +19752,7 @@ pub unsafe fn vld1q_lane_s32(ptr: *const i32, src: int32x4_t) - )] pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) -> int64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_s8)"] @@ -19777,7 +19777,7 @@ pub unsafe fn vld1q_lane_s64(ptr: *const i64, src: int64x2_t) - )] pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> int8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u16)"] @@ -19802,7 +19802,7 @@ pub unsafe fn vld1q_lane_s8(ptr: *const i8, src: int8x16_t) -> )] pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) -> uint16x8_t { static_assert_uimm_bits!(LANE, 3); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u32)"] @@ -19827,7 +19827,7 @@ pub unsafe fn vld1q_lane_u16(ptr: *const u16, src: uint16x8_t) )] pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) -> uint32x4_t { static_assert_uimm_bits!(LANE, 2); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u64)"] @@ -19837,7 +19837,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19852,7 +19852,7 @@ pub unsafe fn vld1q_lane_u32(ptr: *const u32, src: uint32x4_t) )] pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) -> uint64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_u8)"] @@ -19877,7 +19877,7 @@ pub unsafe fn vld1q_lane_u64(ptr: *const u64, src: uint64x2_t) )] pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> uint8x16_t { static_assert_uimm_bits!(LANE, 4); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_lane_p64)"] @@ -19887,7 +19887,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 0))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 0))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ldr, LANE = 0) @@ -19902,7 +19902,7 @@ pub unsafe fn vld1q_lane_u8(ptr: *const u8, src: uint8x16_t) -> )] pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) -> poly64x1_t { static_assert!(LANE == 0); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load one single-element structure to one lane of one register."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_lane_p64)"] @@ -19912,7 +19912,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr, LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8", LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19927,7 +19927,7 @@ pub unsafe fn vld1_lane_p64(ptr: *const p64, src: poly64x1_t) - )] pub unsafe fn vld1q_lane_p64(ptr: *const p64, src: poly64x2_t) -> poly64x2_t { static_assert_uimm_bits!(LANE, 1); - simd_insert!(src, LANE as u32, *ptr) + simd_insert!(src, LANE as u32, crate::ptr::read_unaligned(ptr)) } #[doc = "Load multiple single-element structures to one, two, three, or four registers."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_p64)"] @@ -58579,7 +58579,7 @@ pub unsafe fn vst1q_f32_x4(a: *mut f32, b: float32x4x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f16)"] @@ -58599,7 +58599,7 @@ pub unsafe fn vst1_lane_f16(a: *mut f16, b: float16x4_t) { #[cfg(not(target_arch = "arm64ec"))] pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_f32)"] @@ -58624,7 +58624,7 @@ pub unsafe fn vst1q_lane_f16(a: *mut f16, b: float16x8_t) { )] pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_f32)"] @@ -58649,7 +58649,7 @@ pub unsafe fn vst1_lane_f32(a: *mut f32, b: float32x2_t) { )] pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s8)"] @@ -58674,7 +58674,7 @@ pub unsafe fn vst1q_lane_f32(a: *mut f32, b: float32x4_t) { )] pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s8)"] @@ -58699,7 +58699,7 @@ pub unsafe fn vst1_lane_s8(a: *mut i8, b: int8x8_t) { )] pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s16)"] @@ -58724,7 +58724,7 @@ pub unsafe fn vst1q_lane_s8(a: *mut i8, b: int8x16_t) { )] pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s16)"] @@ -58749,7 +58749,7 @@ pub unsafe fn vst1_lane_s16(a: *mut i16, b: int16x4_t) { )] pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s32)"] @@ -58774,7 +58774,7 @@ pub unsafe fn vst1q_lane_s16(a: *mut i16, b: int16x8_t) { )] pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s32)"] @@ -58799,7 +58799,7 @@ pub unsafe fn vst1_lane_s32(a: *mut i32, b: int32x2_t) { )] pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_s64)"] @@ -58824,7 +58824,7 @@ pub unsafe fn vst1q_lane_s32(a: *mut i32, b: int32x4_t) { )] pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u8)"] @@ -58849,7 +58849,7 @@ pub unsafe fn vst1q_lane_s64(a: *mut i64, b: int64x2_t) { )] pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u8)"] @@ -58874,7 +58874,7 @@ pub unsafe fn vst1_lane_u8(a: *mut u8, b: uint8x8_t) { )] pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u16)"] @@ -58899,7 +58899,7 @@ pub unsafe fn vst1q_lane_u8(a: *mut u8, b: uint8x16_t) { )] pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u16)"] @@ -58924,7 +58924,7 @@ pub unsafe fn vst1_lane_u16(a: *mut u16, b: uint16x4_t) { )] pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u32)"] @@ -58949,7 +58949,7 @@ pub unsafe fn vst1q_lane_u16(a: *mut u16, b: uint16x8_t) { )] pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u32)"] @@ -58974,7 +58974,7 @@ pub unsafe fn vst1_lane_u32(a: *mut u32, b: uint32x2_t) { )] pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_u64)"] @@ -58999,7 +58999,7 @@ pub unsafe fn vst1q_lane_u32(a: *mut u32, b: uint32x4_t) { )] pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p8)"] @@ -59024,7 +59024,7 @@ pub unsafe fn vst1q_lane_u64(a: *mut u64, b: uint64x2_t) { )] pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_p8)"] @@ -59049,7 +59049,7 @@ pub unsafe fn vst1_lane_p8(a: *mut p8, b: poly8x8_t) { )] pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { static_assert_uimm_bits!(LANE, 4); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p16)"] @@ -59074,7 +59074,7 @@ pub unsafe fn vst1q_lane_p8(a: *mut p8, b: poly8x16_t) { )] pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { static_assert_uimm_bits!(LANE, 2); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1q_lane_p16)"] @@ -59099,7 +59099,7 @@ pub unsafe fn vst1_lane_p16(a: *mut p16, b: poly16x4_t) { )] pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { static_assert_uimm_bits!(LANE, 3); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_p64)"] @@ -59124,7 +59124,7 @@ pub unsafe fn vst1q_lane_p16(a: *mut p16, b: poly16x8_t) { )] pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_s64)"] @@ -59149,7 +59149,7 @@ pub unsafe fn vst1_lane_p64(a: *mut p64, b: poly64x1_t) { )] pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures from one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_lane_u64)"] @@ -59174,7 +59174,7 @@ pub unsafe fn vst1_lane_s64(a: *mut i64, b: int64x1_t) { )] pub unsafe fn vst1_lane_u64(a: *mut u64, b: uint64x1_t) { static_assert!(LANE == 0); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple single-element structures to one, two, three, or four registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst1_p64_x2)"] @@ -61181,7 +61181,7 @@ unsafe fn vst1q_v8f16(addr: *const i8, val: float16x8_t, align: i32) { )] pub unsafe fn vst1q_lane_p64(a: *mut p64, b: poly64x2_t) { static_assert_uimm_bits!(LANE, 1); - *a = simd_extract!(b, LANE as u32); + crate::ptr::write_unaligned(a, simd_extract!(b, LANE as u32)) } #[doc = "Store multiple 2-element structures from two registers"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vst2_f16)"] diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs index 70a37f7c05dad..ecb5cd53f4575 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -223,3 +223,32 @@ fn test_vld1q_f32() { let r = unsafe { f32x4::from(vld1q_f32(a[1..].as_ptr())) }; assert_eq!(r, e) } + +#[simd_test(enable = "neon")] +fn test_vld1q_lane_u32_unaligned() { + // ld1 single-lane loads impose no alignment requirement: read from an odd byte offset. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = u32::from_ne_bytes([1, 2, 3, 4]); + let src = u32x4::new(10, 11, 12, 13); + let r = unsafe { + u32x4::from(vld1q_lane_u32::<2>( + a.as_ptr().add(1) as *const u32, + src.into(), + )) + }; + assert_eq!(r, u32x4::new(10, 11, e, 13)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_lane_u64_unaligned() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]); + let src = u64x2::new(10, 11); + let r = unsafe { + u64x2::from(vld1q_lane_u64::<1>( + a.as_ptr().add(1) as *const u64, + src.into(), + )) + }; + assert_eq!(r, u64x2::new(10, e)); +} diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs index 6eb60e4c78bc8..68df3ec944abd 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/store_tests.rs @@ -473,3 +473,27 @@ fn test_vst1q_f32() { assert_eq!(vals[3], 3.); assert_eq!(vals[4], 4.); } + +#[simd_test(enable = "neon")] +fn test_vst1q_lane_u32_unaligned() { + // st1 single-lane stores impose no alignment requirement: write to an odd byte offset. + let mut vals = [0_u8; 5]; + let a = u32x4::new(1, 2, 3, 4); + unsafe { + vst1q_lane_u32::<2>(vals.as_mut_ptr().add(1) as *mut u32, a.into()); + } + assert_eq!(vals[0], 0); + assert_eq!(u32::from_ne_bytes([vals[1], vals[2], vals[3], vals[4]]), 3); +} + +#[simd_test(enable = "neon")] +fn test_vst1q_lane_u64_unaligned() { + let mut vals = [0_u8; 9]; + let a = u64x2::new(1, 2); + unsafe { + vst1q_lane_u64::<1>(vals.as_mut_ptr().add(1) as *mut u64, a.into()); + } + assert_eq!(vals[0], 0); + let stored: [u8; 8] = vals[1..9].try_into().unwrap(); + assert_eq!(u64::from_ne_bytes(stored), 2); +} diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml index e5ce77ed8b33f..01942246a0997 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/aarch64.spec.yml @@ -4321,10 +4321,7 @@ intrinsics: - ['*mut f64', float64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4340,10 +4337,7 @@ intrinsics: - ['*mut f64', float64x2_t] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '1']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: [core::ptr::write_unaligned, [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst2{neon_type[1].nox}" doc: "Store multiple 2-element structures from two registers" diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 7a7656e4c14b3..a91bfb2eb8a67 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -2868,7 +2868,7 @@ intrinsics: - ["*const f16", float16x8_t, 'q_lane', '3'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '{type[3]}']] - - FnCall: [simd_insert!, [src, "LANE as u32", "*ptr"]] + - FnCall: [simd_insert!, [src, "LANE as u32", {FnCall: ["crate::ptr::read_unaligned", [ptr]]}]] - name: "vld1{type[2]}_{neon_type[1]}" doc: "Load one single-element structure and replicate to all lanes of one register" @@ -4683,10 +4683,7 @@ intrinsics: - ['*mut u64', uint64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4708,10 +4705,7 @@ intrinsics: - ['*mut p64', poly64x1_t] compose: - FnCall: [static_assert!, ['LANE == 0']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4733,10 +4727,7 @@ intrinsics: - ['*mut p64', poly64x2_t] compose: - FnCall: [static_assert_uimm_bits!, [LANE, '1']] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" doc: "Store multiple single-element structures from one, two, three, or four registers" @@ -4774,10 +4765,7 @@ intrinsics: - ['*mut f32', float32x4_t, '2'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: "vst1{neon_type[1].lane_nox}" @@ -4799,10 +4787,7 @@ intrinsics: - ['*mut f16', float16x8_t, '3'] compose: - FnCall: [static_assert_uimm_bits!, [LANE, "{type[2]}"]] - - Assign: - - "*a" - - FnCall: [simd_extract!, [b, 'LANE as u32']] - - Identifier: [';', Symbol] + - FnCall: ['crate::ptr::write_unaligned', [a, {FnCall: [simd_extract!, [b, 'LANE as u32']]}]] - name: 'vst1{neon_type[1].no}' @@ -14314,13 +14299,13 @@ intrinsics: - ['vld1q_lane_s32', '*const i32', 'int32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - ['vld1q_lane_u32', '*const u32', 'uint32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - ['vld1q_lane_f32', '*const f32', 'float32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - - ['vld1_lane_s64', '*const i64', 'int64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1_lane_u64', '*const u64', 'uint64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1q_lane_s64', '*const i64', 'int64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - - ['vld1q_lane_u64', '*const u64', 'uint64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1_lane_s64', '*const i64', 'int64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1_lane_u64', '*const u64', 'uint64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1q_lane_s64', '*const i64', 'int64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1q_lane_u64', '*const u64', 'uint64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] compose: - FnCall: ["{type[6]}", ["{type[7]}"]] - - FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']] + - FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Load one single-element structure to one lane of one register." @@ -14338,11 +14323,11 @@ intrinsics: safety: unsafe: [neon] types: - - ['vld1_lane_p64', '*const p64', 'poly64x1_t', 'vldr', '0', 'ldr', 'static_assert!', 'LANE == 0'] - - ['vld1q_lane_p64', '*const p64', 'poly64x2_t', 'vldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1_lane_p64', '*const p64', 'poly64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] + - ['vld1q_lane_p64', '*const p64', 'poly64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] compose: - FnCall: ["{type[6]}", ["{type[7]}"]] - - FnCall: [simd_insert!, [src, 'LANE as u32', '*ptr']] + - FnCall: [simd_insert!, [src, 'LANE as u32', {FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Load one single-element structure and Replicate to all lanes (of one register)." From e9bc995100c0360b83e611d5b65540a3bf0820a6 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Thu, 20 Aug 2026 20:32:59 +0300 Subject: [PATCH 0065/1309] neon: drop the align requirement on vld1 dup loads --- .../src/arm_shared/neon/generated.rs | 46 +++++++++---------- .../src/arm_shared/neon/load_tests.rs | 17 +++++++ .../spec/neon/arm_shared.spec.yml | 8 ++-- 3 files changed, 44 insertions(+), 27 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 2c6f663d6ed08..b7cc4057cec29 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -18279,7 +18279,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { - transmute(f32x2::splat(*ptr)) + transmute(f32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p16)"] @@ -18302,7 +18302,7 @@ pub unsafe fn vld1_dup_f32(ptr: *const f32) -> float32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p8)"] @@ -18325,7 +18325,7 @@ pub unsafe fn vld1_dup_p16(ptr: *const p16) -> poly16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s16)"] @@ -18348,7 +18348,7 @@ pub unsafe fn vld1_dup_p8(ptr: *const p8) -> poly8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { - transmute(i16x4::splat(*ptr)) + transmute(i16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s32)"] @@ -18371,7 +18371,7 @@ pub unsafe fn vld1_dup_s16(ptr: *const i16) -> int16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { - transmute(i32x2::splat(*ptr)) + transmute(i32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_s8)"] @@ -18394,7 +18394,7 @@ pub unsafe fn vld1_dup_s32(ptr: *const i32) -> int32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { - transmute(i8x8::splat(*ptr)) + transmute(i8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u16)"] @@ -18417,7 +18417,7 @@ pub unsafe fn vld1_dup_s8(ptr: *const i8) -> int8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { - transmute(u16x4::splat(*ptr)) + transmute(u16x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u32)"] @@ -18440,7 +18440,7 @@ pub unsafe fn vld1_dup_u16(ptr: *const u16) -> uint16x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { - transmute(u32x2::splat(*ptr)) + transmute(u32x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_u8)"] @@ -18463,7 +18463,7 @@ pub unsafe fn vld1_dup_u32(ptr: *const u32) -> uint32x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { - transmute(u8x8::splat(*ptr)) + transmute(u8x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_f32)"] @@ -18486,7 +18486,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { - transmute(f32x4::splat(*ptr)) + transmute(f32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p16)"] @@ -18509,7 +18509,7 @@ pub unsafe fn vld1q_dup_f32(ptr: *const f32) -> float32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_p8)"] @@ -18532,7 +18532,7 @@ pub unsafe fn vld1q_dup_p16(ptr: *const p16) -> poly16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s16)"] @@ -18555,7 +18555,7 @@ pub unsafe fn vld1q_dup_p8(ptr: *const p8) -> poly8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { - transmute(i16x8::splat(*ptr)) + transmute(i16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s32)"] @@ -18578,7 +18578,7 @@ pub unsafe fn vld1q_dup_s16(ptr: *const i16) -> int16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { - transmute(i32x4::splat(*ptr)) + transmute(i32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s64)"] @@ -18587,7 +18587,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18601,7 +18601,7 @@ pub unsafe fn vld1q_dup_s32(ptr: *const i32) -> int32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { - transmute(i64x2::splat(*ptr)) + transmute(i64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_s8)"] @@ -18624,7 +18624,7 @@ pub unsafe fn vld1q_dup_s64(ptr: *const i64) -> int64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { - transmute(i8x16::splat(*ptr)) + transmute(i8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u16)"] @@ -18647,7 +18647,7 @@ pub unsafe fn vld1q_dup_s8(ptr: *const i8) -> int8x16_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { - transmute(u16x8::splat(*ptr)) + transmute(u16x8::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u32)"] @@ -18670,7 +18670,7 @@ pub unsafe fn vld1q_dup_u16(ptr: *const u16) -> uint16x8_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { - transmute(u32x4::splat(*ptr)) + transmute(u32x4::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u64)"] @@ -18679,7 +18679,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vldr"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18693,7 +18693,7 @@ pub unsafe fn vld1q_dup_u32(ptr: *const u32) -> uint32x4_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { - transmute(u64x2::splat(*ptr)) + transmute(u64x2::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1q_dup_u8)"] @@ -18716,7 +18716,7 @@ pub unsafe fn vld1q_dup_u64(ptr: *const u64) -> uint64x2_t { unstable(feature = "stdarch_arm_neon_intrinsics", issue = "111800") )] pub unsafe fn vld1q_dup_u8(ptr: *const u8) -> uint8x16_t { - transmute(u8x16::splat(*ptr)) + transmute(u8x16::splat(crate::ptr::read_unaligned(ptr))) } #[doc = "Load one single-element structure and Replicate to all lanes (of one register)."] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/vld1_dup_p64)"] @@ -21734,7 +21734,7 @@ unsafe fn vld1q_v8f16(a: *const i8, b: i32) -> float16x8_t { #[inline] #[target_feature(enable = "neon,aes")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vldr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.8"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs index ecb5cd53f4575..863fe87f6130a 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -252,3 +252,20 @@ fn test_vld1q_lane_u64_unaligned() { }; assert_eq!(r, u64x2::new(10, e)); } + +#[simd_test(enable = "neon")] +fn test_vld1q_dup_u32_unaligned() { + // ld1r replicate loads impose no alignment requirement either. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = u32::from_ne_bytes([1, 2, 3, 4]); + let r = unsafe { u32x4::from(vld1q_dup_u32(a.as_ptr().add(1) as *const u32)) }; + assert_eq!(r, u32x4::new(e, e, e, e)); +} + +#[simd_test(enable = "neon")] +fn test_vld1q_dup_u64_unaligned() { + let a: [u8; 9] = [0, 1, 2, 3, 4, 5, 6, 7, 8]; + let e = u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]); + let r = unsafe { u64x2::from(vld1q_dup_u64(a.as_ptr().add(1) as *const u64)) }; + assert_eq!(r, u64x2::new(e, e)); +} diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index a91bfb2eb8a67..0f378dd9ef4ab 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -14381,7 +14381,7 @@ intrinsics: safety: unsafe: [neon] types: - - ['vld1q_dup_p64', '*const p64', 'poly64x2_t', 'vldr', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]'] + - ['vld1q_dup_p64', '*const p64', 'poly64x2_t', '"vld1.8"', 'ld1r', 'vld1q_lane_p64::<0>', 'u64x2::splat(0)', '[0, 0]'] compose: - Let: - x @@ -14428,12 +14428,12 @@ intrinsics: - ['vld1q_dup_u32', '*const u32', 'uint32x4_t', 'vld1.32', 'ld1r', 'u32x4::splat'] - ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'vld1.32', 'ld1r', 'f32x4::splat'] - - ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vldr', 'ld1r', 'i64x2::splat'] - - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vldr', 'ld1r', 'u64x2::splat'] + - ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vld1.8', 'ld1r', 'i64x2::splat'] + - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vld1.8', 'ld1r', 'u64x2::splat'] compose: - FnCall: - transmute - - - FnCall: ['{type[5]}', ["*ptr"]] + - - FnCall: ['{type[5]}', [{FnCall: ['crate::ptr::read_unaligned', [ptr]]}]] - name: "{type[0]}" doc: "Absolute difference and accumulate (64-bit)" From 2b059404ff57577e7ef8313837d47487ea26afcd Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Fri, 21 Aug 2026 00:28:12 +0300 Subject: [PATCH 0066/1309] neon: assert ldr for the f32 lane and dup loads on arm --- .../core_arch/src/arm_shared/neon/generated.rs | 8 ++++---- .../core_arch/src/arm_shared/neon/load_tests.rs | 16 ++++++++++++++++ .../spec/neon/arm_shared.spec.yml | 8 ++++---- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index b7cc4057cec29..12958f7b85ec0 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -18265,7 +18265,7 @@ pub unsafe fn vld1q_dup_f16(ptr: *const f16) -> float16x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -18472,7 +18472,7 @@ pub unsafe fn vld1_dup_u8(ptr: *const u8) -> uint8x8_t { #[inline] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32"))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr("ldr"))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1r) @@ -19337,7 +19337,7 @@ pub unsafe fn vld1q_lane_f16(ptr: *const f16, src: float16x8_t) #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 1))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 1))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 1) @@ -19612,7 +19612,7 @@ pub unsafe fn vld1_lane_u8(ptr: *const u8, src: uint8x8_t) -> u #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] #[rustc_legacy_const_generics(2)] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr("vld1.32", LANE = 3))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(ldr, LANE = 3))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(ld1, LANE = 3) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs index 863fe87f6130a..a4db10f7c1d26 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/load_tests.rs @@ -253,6 +253,22 @@ fn test_vld1q_lane_u64_unaligned() { assert_eq!(r, u64x2::new(10, e)); } +#[simd_test(enable = "neon")] +fn test_vld1q_lane_f32_unaligned() { + // Float loads legalize differently from integer ones under low alignment + // (armv7 uses ldr + vmov), so the type class needs its own coverage. + let a: [u8; 5] = [0, 1, 2, 3, 4]; + let e = f32::from_ne_bytes([1, 2, 3, 4]); + let src = f32x4::new(10., 11., 12., 13.); + let r = unsafe { + f32x4::from(vld1q_lane_f32::<2>( + a.as_ptr().add(1) as *const f32, + src.into(), + )) + }; + assert_eq!(r, f32x4::new(10., 11., e, 13.)); +} + #[simd_test(enable = "neon")] fn test_vld1q_dup_u32_unaligned() { // ld1r replicate loads impose no alignment requirement either. diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 0f378dd9ef4ab..de82b203c1f27 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -14295,10 +14295,10 @@ intrinsics: - ['vld1q_lane_p16', '*const p16', 'poly16x8_t', '"vld1.16"', '7', 'ld1', 'static_assert_uimm_bits!', 'LANE, 3'] - ['vld1_lane_s32', '*const i32', 'int32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - ['vld1_lane_u32', '*const u32', 'uint32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - - ['vld1_lane_f32', '*const f32', 'float32x2_t', '"vld1.32"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] + - ['vld1_lane_f32', '*const f32', 'float32x2_t', 'ldr', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] - ['vld1q_lane_s32', '*const i32', 'int32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - ['vld1q_lane_u32', '*const u32', 'uint32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - - ['vld1q_lane_f32', '*const f32', 'float32x4_t', '"vld1.32"', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] + - ['vld1q_lane_f32', '*const f32', 'float32x4_t', 'ldr', '3', 'ld1', 'static_assert_uimm_bits!', 'LANE, 2'] - ['vld1_lane_s64', '*const i64', 'int64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] - ['vld1_lane_u64', '*const u64', 'uint64x1_t', '"vld1.8"', '0', 'ldr', 'static_assert!', 'LANE == 0'] - ['vld1q_lane_s64', '*const i64', 'int64x2_t', '"vld1.8"', '1', 'ld1', 'static_assert_uimm_bits!', 'LANE, 1'] @@ -14422,11 +14422,11 @@ intrinsics: - ['vld1_dup_s32', '*const i32', 'int32x2_t', 'vld1.32', 'ld1r', 'i32x2::splat'] - ['vld1_dup_u32', '*const u32', 'uint32x2_t', 'vld1.32', 'ld1r', 'u32x2::splat'] - - ['vld1_dup_f32', '*const f32', 'float32x2_t', 'vld1.32', 'ld1r', 'f32x2::splat'] + - ['vld1_dup_f32', '*const f32', 'float32x2_t', 'ldr', 'ld1r', 'f32x2::splat'] - ['vld1q_dup_s32', '*const i32', 'int32x4_t', 'vld1.32', 'ld1r', 'i32x4::splat'] - ['vld1q_dup_u32', '*const u32', 'uint32x4_t', 'vld1.32', 'ld1r', 'u32x4::splat'] - - ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'vld1.32', 'ld1r', 'f32x4::splat'] + - ['vld1q_dup_f32', '*const f32', 'float32x4_t', 'ldr', 'ld1r', 'f32x4::splat'] - ['vld1q_dup_s64', '*const i64', 'int64x2_t', 'vld1.8', 'ld1r', 'i64x2::splat'] - ['vld1q_dup_u64', '*const u64', 'uint64x2_t', 'vld1.8', 'ld1r', 'u64x2::splat'] From b78c8acf1e22f904cef325d6fab04a2eab00dc56 Mon Sep 17 00:00:00 2001 From: Chayim Refael Friedman Date: Fri, 21 Aug 2026 06:22:56 +0300 Subject: [PATCH 0067/1309] Provide a `supertrait_def_ids()` function in rustc_type_ir's interner rust-analyzer has a query for this, so we want to use it there. I don't know if using a query for this will be a perf win for rustc, but rust-analyzer already has this query for other reasons, so it feels a waste to not use it. --- compiler/rustc_middle/src/ty/context/impl_interner.rs | 4 ++++ compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 3 ++- compiler/rustc_type_ir/src/elaborate.rs | 3 +++ compiler/rustc_type_ir/src/interner.rs | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 2444f8513b8e4..7f10cb1994ee1 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -430,6 +430,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.impl_super_outlives(impl_def_id) } + fn supertrait_def_ids(self, trait_def_id: DefId) -> impl Iterator { + rustc_type_ir::elaborate::supertrait_def_ids(self, trait_def_id) + } + fn impl_is_const(self, def_id: DefId) -> bool { debug_assert_matches!(self.def_kind(def_id), DefKind::Impl { of_trait: true }); self.is_conditionally_const(def_id) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 335263b1d169d..f9793fb6e417c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1109,7 +1109,8 @@ where .auto_traits() .into_iter() .chain(a_data.principal_def_id().into_iter().flat_map(|principal_def_id| { - elaborate::supertrait_def_ids(self.cx(), principal_def_id) + self.cx() + .supertrait_def_ids(principal_def_id) .filter(|def_id| self.cx().trait_is_auto(*def_id)) })) .collect(); diff --git a/compiler/rustc_type_ir/src/elaborate.rs b/compiler/rustc_type_ir/src/elaborate.rs index 912a5ac90f632..2110521eae764 100644 --- a/compiler/rustc_type_ir/src/elaborate.rs +++ b/compiler/rustc_type_ir/src/elaborate.rs @@ -318,6 +318,9 @@ impl> Iterator for Elaborator { /// does not compute the full elaborated super-predicates but just the set of def-ids. It is used /// to identify which traits may define a given associated type to help avoid cycle errors, /// and to make size estimates for vtable layout computation. +/// +/// rust-analyzer has a query for this, so don't use this function there. +#[cfg(feature = "nightly")] pub fn supertrait_def_ids( cx: I, trait_def_id: I::TraitId, diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 49899147d5747..5a14b60e1d296 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -359,6 +359,9 @@ pub trait Interner: impl_def_id: Self::ImplId, ) -> ty::EarlyBinder>; + fn supertrait_def_ids(self, trait_def_id: Self::TraitId) + -> impl Iterator; + fn impl_is_const(self, def_id: Self::ImplId) -> bool; fn fn_is_const(self, def_id: Self::FunctionId) -> bool; fn closure_is_const(self, def_id: Self::ClosureId) -> bool; From 19ea707955e48f8598042095bcbd20f6b9fb8612 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 20 Aug 2026 14:14:07 -0400 Subject: [PATCH 0068/1309] Refactor to avoid having to use set_type for global variables --- src/common.rs | 92 +++++++++------ src/consts.rs | 188 ++++++++++++++++++++----------- src/context.rs | 7 ++ src/mono_item.rs | 25 +++- tests/run/static_alloc_shapes.rs | 50 ++++++++ 5 files changed, 251 insertions(+), 111 deletions(-) create mode 100644 tests/run/static_alloc_shapes.rs diff --git a/src/common.rs b/src/common.rs index a503c1b345126..21d92c6cc2936 100644 --- a/src/common.rs +++ b/src/common.rs @@ -126,68 +126,86 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } +/// The element type and element count of the array used to represent a run of `len` constant bytes. +/// +/// Larger integers are used where possible: this reduces the number of rvalues, which is a +/// significant memory saving on constant-heavy crates. +fn byte_run_shape<'gcc>(cx: &CodegenCx<'gcc, '_>, len: usize) -> (Type<'gcc>, u64) { + match len % 8 { + 0 => (cx.context.new_type::(), len as u64 / 8), + 4 => (cx.context.new_type::(), len as u64 / 4), + _ => (cx.context.new_type::(), len as u64), + } +} + +/// The type [`bytes_in_context`] gives a run of `len` constant bytes. +/// +/// Exposed separately so that the type of a constant allocation can be computed before any of its +/// rvalues exist; see [`crate::consts::const_alloc_type`]. +/// +/// The result is cached because `gcc_jit_context_new_array_type` mints a fresh type every call. +/// Two equal-but-distinct array types would key [`CodegenCx::type_struct`] differently and so +/// produce two distinct anonymous structs, and libgccjit compares struct types by identity. +pub fn bytes_type_in_context<'gcc>(cx: &CodegenCx<'gcc, '_>, len: usize) -> Type<'gcc> { + let (element_type, count) = byte_run_shape(cx, len); + if let Some(&typ) = cx.byte_array_types.borrow().get(&(element_type, count)) { + return typ; + } + let typ = new_array_type(cx.context, None, element_type, count); + cx.byte_array_types.borrow_mut().insert((element_type, count), typ); + typ +} + +// FIXME(FractalFir): Consider using `global_set_initializer` instead. Before this is done, we need to confirm that +// `global_set_initializer` is more memory efficient than the current solution. +// `global_set_initializer` calls `global_set_initializer_rvalue` under the hood - does it generate an array of rvalues, +// or is it using a more efficient representation? pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { - // Instead of always using an array of bytes, use an array of larger integers of target endianness - // if possible. This reduces the amount of `rvalues` we use, which reduces memory usage significantly. - // - // FIXME(FractalFir): Consider using `global_set_initializer` instead. Before this is done, we need to confirm that - // `global_set_initializer` is more memory efficient than the current solution. - // `global_set_initializer` calls `global_set_initializer_rvalue` under the hood - does it generate an array of rvalues, - // or is it using a more efficient representation? - match bytes.len() % 8 { + let typ = bytes_type_in_context(cx, bytes.len()); + let (element_type, _) = byte_run_shape(cx, bytes.len()); + let context = &cx.context; + // Since we are representing arbitrary byte runs as integers, we need to follow the target + // endianness. + let endian = cx.sess().target.options.endian; + let elements: Vec<_> = match bytes.len() % 8 { 0 => { - let context = &cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); let (arrays, remainder) = bytes.as_chunks::<8>(); debug_assert!(remainder.is_empty()); - let elements: Vec<_> = arrays + arrays .iter() .map(|&arr| { context.new_rvalue_from_long( - byte_type, - // Since we are representing arbitrary byte runs as integers, we need to follow the target - // endianness. - match cx.sess().target.options.endian { + element_type, + match endian { rustc_abi::Endian::Little => u64::from_le_bytes(arr) as i64, rustc_abi::Endian::Big => u64::from_be_bytes(arr) as i64, }, ) }) - .collect(); - context.new_array_constructor(None, typ, &elements) + .collect() } 4 => { - let context = &cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); let (arrays, remainder) = bytes.as_chunks::<4>(); debug_assert!(remainder.is_empty()); - let elements: Vec<_> = arrays + arrays .iter() .map(|&arr| { context.new_rvalue_from_int( - byte_type, - match cx.sess().target.options.endian { + element_type, + match endian { rustc_abi::Endian::Little => u32::from_le_bytes(arr) as i32, rustc_abi::Endian::Big => u32::from_be_bytes(arr) as i32, }, ) }) - .collect(); - context.new_array_constructor(None, typ, &elements) - } - _ => { - let context = cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64); - let elements: Vec<_> = bytes - .iter() - .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) - .collect(); - context.new_array_constructor(None, typ, &elements) + .collect() } - } + _ => bytes + .iter() + .map(|&byte| context.new_rvalue_from_int(element_type, byte as i32)) + .collect(), + }; + context.new_array_constructor(None, typ, &elements) } pub fn type_is_pointer(typ: Type<'_>) -> bool { diff --git a/src/consts.rs b/src/consts.rs index 5ebdf91fe20b6..b1e06f88a234c 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,6 +1,8 @@ +use std::ops::Range; + #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue, VarAttribute, Visibility}; -use gccjit::{Function, GlobalKind, LValue, RValue, Type}; +use gccjit::{FnAttribute, VarAttribute, Visibility}; +use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, @@ -11,15 +13,18 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint, + self, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, read_target_uint, }; +use rustc_middle::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; use crate::base; +use crate::common::bytes_type_in_context; use crate::context::CodegenCx; +use crate::type_::struct_attributes; use crate::type_of::LayoutGccExt; pub(crate) fn const_alloc_to_gcc<'gcc, 'tcx>( @@ -99,10 +104,11 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { let is_thread_local = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let global = self.get_static_inner(def_id, val_llty); - #[cfg(feature = "master")] - if global.to_rvalue().get_type() != val_llty { - global.to_rvalue().set_type(val_llty); - } + debug_assert_eq!( + global.to_rvalue().get_type(), + val_llty, + "`predefine_static` declared this global with a type its initializer does not have" + ); // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); @@ -260,15 +266,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return global; } - // FIXME: Once we stop removing globals in `codegen_static`, we can uncomment this code. - // let defined_in_current_codegen_unit = - // self.codegen_unit.items().contains_key(&MonoItem::Static(def_id)); - // assert!( - // !defined_in_current_codegen_unit, - // "consts::get_static() should always hit the cache for \ - // statics defined in the same CGU, but did not for `{:?}`", - // def_id - // ); + let defined_in_current_codegen_unit = + self.codegen_unit.items().contains_key(&MonoItem::Static(def_id)); + assert!( + !defined_in_current_codegen_unit, + "consts::get_static() should always hit the cache for \ + statics defined in the same CGU, but did not for `{:?}`", + def_id + ); let sym = self.tcx.symbol_name(instance).name; let fn_attrs = self.tcx.codegen_fn_attrs(def_id); @@ -332,71 +337,118 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global } } -/// Converts a given const alloc to a gcc Rvalue, without any caching or deduplication. -/// YOU SHOULD NOT call this function directly - that may break the semantics of Rust. -/// Use `const_data_from_alloc` instead. -pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( - cx: &CodegenCx<'gcc, '_>, - alloc: ConstAllocation<'_>, -) -> RValue<'gcc> { - let alloc = alloc.inner(); - let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); - let dl = cx.data_layout(); - let pointer_size = dl.pointer_size().bytes() as usize; +/// One field of the packed struct that a constant allocation is lowered to. +enum AllocField { + /// A run of bytes carrying no provenance. + Bytes { range: Range }, + /// A pointer with provenance, occupying one target pointer worth of bytes. + Pointer { offset: usize, prov: CtfeProvenance }, +} + +/// The field-by-field shape of `alloc`. +/// +/// [`const_alloc_to_gcc_uncached`] and [`const_alloc_type`] have to agree exactly on this, down to +/// the empty trailing run an allocation ending on a pointer produces, so both derive the shape here +/// instead of each walking the allocation on its own. +fn alloc_fields(cx: &CodegenCx<'_, '_>, alloc: &interpret::Allocation) -> Vec { + let pointer_size = cx.data_layout().pointer_size().bytes() as usize; + let mut fields = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let mut next_offset = 0; for &(offset, prov) in alloc.provenance().ptrs().iter() { - let alloc_id = prov.alloc_id(); let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - // This `inspect` is okay since we have checked that it is not within a pointer with provenance, it - // is within the bounds of the allocation, and it doesn't affect interpreter execution - // (we inspect the result after interpreter execution). Any undef byte is replaced with - // some arbitrary byte value. - // - // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); - llvals.push(cx.const_bytes(bytes)); + fields.push(AllocField::Bytes { range: next_offset..offset }); } - let ptr_offset = read_target_uint( - dl.endian, - // This `inspect` is okay since it is within the bounds of the allocation, it doesn't - // affect interpreter execution (we inspect the result after interpreter execution), - // and we properly interpret the provenance as a relocation pointer offset. - alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), - ) - .expect("const_alloc_to_gcc_uncached: could not read relocation pointer") - as u64; - - let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx); - - llvals.push(cx.scalar_to_backend( - InterpScalar::from_pointer( - interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), - &cx.tcx, - ), - abi::Scalar::Initialized { - value: Primitive::Pointer(address_space), - valid_range: WrappingRange::full(dl.pointer_size()), - }, - cx.type_i8p_ext(address_space), - )); + fields.push(AllocField::Pointer { offset, prov }); next_offset = offset + pointer_size; } if alloc.len() >= next_offset { - let range = next_offset..alloc.len(); - // This `inspect` is okay since we have check that it is after all provenance, it is - // within the bounds of the allocation, and it doesn't affect interpreter execution (we - // inspect the result after interpreter execution). Any undef byte is replaced with some - // arbitrary byte value. - // - // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); - llvals.push(cx.const_bytes(bytes)); + fields.push(AllocField::Bytes { range: next_offset..alloc.len() }); } + fields +} + +/// The type [`const_alloc_to_gcc`] gives `alloc`, computed without building any rvalue. +/// +/// This lets `predefine_static` declare a static's global with the type its initializer will have, +/// so that the two never disagree. It must not reach for the rvalue of anything it points at: +/// during the predefine pass the pointee may not be declared yet, and `alloc_to_backend` would +/// declare it with the wrong type behind our back. +pub(crate) fn const_alloc_type<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, +) -> Type<'gcc> { + let fields: Vec<_> = alloc_fields(cx, alloc.inner()) + .into_iter() + .map(|field| match field { + AllocField::Bytes { range } => bytes_type_in_context(cx, range.len()), + AllocField::Pointer { prov, .. } => { + let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); + cx.type_i8p_ext(address_space) + } + }) + .collect(); + cx.type_struct(&fields, &struct_attributes(true, None)) +} + +/// Converts a given const alloc to a gcc Rvalue, without any caching or deduplication. +/// YOU SHOULD NOT call this function directly - that may break the semantics of Rust. +/// Use `const_data_from_alloc` instead. +pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, +) -> RValue<'gcc> { + let alloc = alloc.inner(); + let dl = cx.data_layout(); + let pointer_size = dl.pointer_size(); + + let llvals: Vec<_> = alloc_fields(cx, alloc) + .into_iter() + .map(|field| match field { + AllocField::Bytes { range } => { + // This `inspect` is okay since we have checked that it is not within a pointer with + // provenance, it is within the bounds of the allocation, and it doesn't affect + // interpreter execution (we inspect the result after interpreter execution). Any + // undef byte is replaced with some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + cx.const_bytes(alloc.inspect_with_uninit_and_ptr_outside_interpreter(range)) + } + AllocField::Pointer { offset, prov } => { + let ptr_offset = read_target_uint( + dl.endian, + // This `inspect` is okay since it is within the bounds of the allocation, it + // doesn't affect interpreter execution (we inspect the result after interpreter + // execution), and we properly interpret the provenance as a relocation pointer + // offset. + alloc.inspect_with_uninit_and_ptr_outside_interpreter( + offset..(offset + pointer_size.bytes() as usize), + ), + ) + .expect("const_alloc_to_gcc_uncached: could not read relocation pointer") + as u64; + + let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); + + cx.scalar_to_backend( + InterpScalar::from_pointer( + interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), + &cx.tcx, + ), + abi::Scalar::Initialized { + value: Primitive::Pointer(address_space), + valid_range: WrappingRange::full(pointer_size), + }, + cx.type_i8p_ext(address_space), + ) + } + }) + .collect(); + // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element. cx.const_struct(&llvals, true) } diff --git a/src/context.rs b/src/context.rs index ebbdbb72516aa..cd835d23e6e39 100644 --- a/src/context.rs +++ b/src/context.rs @@ -97,6 +97,12 @@ pub struct CodegenCx<'gcc, 'tcx> { /// Cache of the anonymous struct types. pub struct_types: RefCell, Type<'gcc>>>, + /// Cache of the array types used for runs of constant bytes, keyed by element type and count. + /// + /// libgccjit mints a fresh type on every `new_array_type`, and struct types are keyed on their + /// field types, so without this two equal byte runs would yield two distinct anonymous structs. + pub byte_array_types: RefCell, u64), Type<'gcc>>>, + /// Cache instances of monomorphic and polymorphic items pub instances: RefCell, LValue<'gcc>>>, /// Cache function instances of monomorphic and polymorphic items @@ -314,6 +320,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { types: Default::default(), tcx, struct_types: Default::default(), + byte_array_types: Default::default(), local_gen_sym_counter: Cell::new(0), global_gen_sym_counter: Cell::new(0), eh_personality: Cell::new(None), diff --git a/src/mono_item.rs b/src/mono_item.rs index 7513978b12272..144bdee65e5db 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -11,6 +11,7 @@ use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; +use crate::consts::const_alloc_type; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; use crate::{attributes, base}; @@ -26,12 +27,24 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); - let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; - // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out - // the gcc type from the actual evaluated initializer. - let ty = - if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; - let gcc_type = self.layout_of(ty).gcc_type(self); + // Declare the global with the type its initializer will have, so that `codegen_static` + // never has to retype it afterwards. The initializer is lowered as a packed struct of byte + // runs and relocations, which almost never matches the layout type. + let gcc_type = match self.tcx.eval_static_initializer(def_id) { + Ok(alloc) => const_alloc_type(self, alloc), + // The initializer failed to evaluate; `codegen_static` bails out on it too, so this + // type is never used to hold one. + Err(_) => { + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a dummy one. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, self.typing_env()) + }; + self.layout_of(ty).gcc_type(self) + } + }; let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); diff --git a/tests/run/static_alloc_shapes.rs b/tests/run/static_alloc_shapes.rs new file mode 100644 index 0000000000000..39a4d07bdf638 --- /dev/null +++ b/tests/run/static_alloc_shapes.rs @@ -0,0 +1,50 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 8 +// 12 +// 5 +// 7 +// 7 +// 9 + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +// One byte run of each length class that maps to a distinct array element type. +static mut BYTES8: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; +static mut BYTES12: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; +static mut BYTES5: [u8; 5] = [1, 2, 3, 4, 5]; + +static mut VALUE: isize = 7; +static mut OTHER: isize = 9; + +// An allocation that is exactly one relocation, so it ends on a pointer with no trailing bytes. +static mut PTR: &isize = unsafe { &VALUE }; + +struct TwoRefs { + first: &'static isize, + second: &'static isize, +} + +// Two adjacent relocations, with no byte run between them. +static mut TWO_REFS: TwoRefs = TwoRefs { first: unsafe { &VALUE }, second: unsafe { &OTHER } }; + +#[no_mangle] +extern "C" fn main(_argc: isize, _argv: *const *const u8) -> i32 { + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES8[7] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES12[11] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES5[4] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *PTR); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *TWO_REFS.first); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *TWO_REFS.second); + } + 0 +} From ea7e8196169ece266269168418d032cf7d288a85 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 29 Jul 2026 11:10:21 +0200 Subject: [PATCH 0069/1309] make `pad_i32` of `PassMode::cast` an integer so that we can specify more than one i32 of padding. --- src/abi.rs | 12 +++++++----- src/type_of.rs | 4 ++-- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 1b7bb8c907735..2901eb8b1a6d2 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -168,11 +168,13 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { )); continue; } - PassMode::Cast { ref cast, pad_i32 } => { - // add padding - if pad_i32 { - argument_tys.push(Reg::i32().gcc_type(cx)); - } + PassMode::Cast { ref cast, pad_i32_count } => { + // Add padding. + argument_tys.extend(std::iter::repeat_n( + Reg::i32().gcc_type(cx), + usize::from(pad_i32_count), + )); + let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs, argument_tys.len()) } diff --git a/src/type_of.rs b/src/type_of.rs index c6c32236ab49f..53192c0a087e4 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -346,8 +346,8 @@ impl<'gcc, 'tcx> LayoutTypeCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn_abi.ptr_to_gcc_type(self) } - fn reg_backend_type(&self, _ty: &Reg) -> Type<'gcc> { - unimplemented!(); + fn reg_backend_type(&self, ty: &Reg) -> Type<'gcc> { + ty.gcc_type(self) } fn fn_decl_backend_type(&self, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Type<'gcc> { From 0b243c55db3a6f9285def3af122994475d9979d5 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 22 Aug 2026 14:53:14 +0200 Subject: [PATCH 0070/1309] test `f16::mul_add` not double-rounding the result A naive `f32::mul_add(a as f32, b as f32, c as f32) as f16` has insufficient precision --- src/intrinsic/mod.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 09ad3254e5714..b3b1bea68e0b4 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -171,7 +171,6 @@ fn f16_builtin<'gcc, 'tcx>( sym::exp2f16 => "exp2f", sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", - sym::fmaf16 => "fmaf", sym::logf16 => "logf", sym::log2f16 => "log2f", sym::log10f16 => "log10f", @@ -249,7 +248,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::expf16 | sym::exp2f16 | sym::floorf16 - | sym::fmaf16 | sym::logf16 | sym::log2f16 | sym::log10f16 From 98f513b2376f13aa427a79dcedb9a10874c849cd Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sun, 26 Jul 2026 10:08:43 +0100 Subject: [PATCH 0071/1309] Add missing avx512vl intrinsics for f32->u32 conversions --- .../crates/core_arch/src/x86/avx512f.rs | 157 ++++++++++++++++++ 1 file changed, 157 insertions(+) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 76e7297bcda40..3588e146f0395 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -13091,6 +13091,104 @@ pub const fn _mm512_maskz_cvtepu32_ps(k: __mmask16, a: __m512i) -> __m512 { } } +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_cvtepu32_ps(a: __m256i) -> __m256 { + unsafe { + let a = a.as_u32x8(); + transmute::(simd_cast(a)) + } +} + +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_mask_cvtepu32_ps(src: __m256, k: __mmask8, a: __m256i) -> __m256 { + unsafe { + let convert = _mm256_cvtepu32_ps(a).as_f32x8(); + transmute(simd_select_bitmask(k, convert, src.as_f32x8())) + } +} + +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm256_maskz_cvtepu32_ps(k: __mmask8, a: __m256i) -> __m256 { + unsafe { + let convert = _mm256_cvtepu32_ps(a).as_f32x8(); + transmute(simd_select_bitmask(k, convert, f32x8::ZERO)) + } +} + +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst. +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_cvtepu32_ps(a: __m128i) -> __m128 { + unsafe { + let a = a.as_u32x4(); + transmute::(simd_cast(a)) + } +} + +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). +/// Bits 4 through 7 of k are ignored. +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_mask_cvtepu32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m128 { + unsafe { + let convert = _mm_cvtepu32_ps(a).as_f32x4(); + transmute(simd_select_bitmask(k, convert, src.as_f32x4())) + } +} + +/// Convert packed unsigned 32-bit integers in a to packed single-precision (32-bit) floating-point elements, and store the results in dst using zeromask k (elements are zeroed out when the corresponding mask bit is not set). +/// Bits 4 through 7 of k are ignored. +/// +/// Due to an omission by Intel, these intrinsics are not documented in the Intrinsics Guide. +/// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). +#[inline] +#[target_feature(enable = "avx512f,avx512vl")] +#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[cfg_attr(test, assert_instr(vcvtudq2ps))] +#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] +pub const fn _mm_maskz_cvtepu32_ps(k: __mmask8, a: __m128i) -> __m128 { + unsafe { + let convert = _mm_cvtepu32_ps(a).as_f32x4(); + transmute(simd_select_bitmask(k, convert, f32x4::ZERO)) + } +} + /// Convert packed unsigned 32-bit integers in a to packed double-precision (64-bit) floating-point elements, and store the results in dst. /// /// [Intel's documentation](https://www.intel.com/content/www/us/en/docs/intrinsics-guide/index.html#text=_mm512_cvtepu32_pd&expand=1580) @@ -50036,6 +50134,65 @@ mod tests { assert_eq_m512(r, e); } + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm256_cvtepu32_ps() { + let a = _mm256_set_epi32(-1, i32::MIN, 16_777_217, 16_777_216, 4, 3, 2, 1); + let r = _mm256_cvtepu32_ps(a); + let e = _mm256_set_ps( + 4_294_967_296., + 2_147_483_648., + 16_777_216., + 16_777_216., + 4., + 3., + 2., + 1., + ); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm256_mask_cvtepu32_ps() { + let a = _mm256_set_epi32(-1, i32::MIN, 6, 5, 4, 3, 2, 1); + let src = _mm256_set1_ps(-1.); + let r = _mm256_mask_cvtepu32_ps(src, 0b10101010, a); + let e = _mm256_set_ps(4_294_967_296., -1., 6., -1., 4., -1., 2., -1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm256_maskz_cvtepu32_ps() { + let a = _mm256_set_epi32(-1, i32::MIN, 6, 5, 4, 3, 2, 1); + let r = _mm256_maskz_cvtepu32_ps(0b01010101, a); + let e = _mm256_set_ps(0., 2_147_483_648., 0., 5., 0., 3., 0., 1.); + assert_eq_m256(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm_cvtepu32_ps() { + let a = _mm_set_epi32(-1, i32::MIN, 1, 0); + let r = _mm_cvtepu32_ps(a); + let e = _mm_set_ps(4_294_967_296., 2_147_483_648., 1., 0.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm_mask_cvtepu32_ps() { + let a = _mm_set_epi32(-1, i32::MIN, 2, 1); + let src = _mm_set1_ps(-1.); + let r = _mm_mask_cvtepu32_ps(src, 0b11110101, a); + let e = _mm_set_ps(-1., 2_147_483_648., -1., 1.); + assert_eq_m128(r, e); + } + + #[simd_test(enable = "avx512f,avx512vl")] + const fn test_mm_maskz_cvtepu32_ps() { + let a = _mm_set_epi32(-1, i32::MIN, 2, 1); + let r = _mm_maskz_cvtepu32_ps(0b11111010, a); + let e = _mm_set_ps(4_294_967_296., 0., 2., 0.); + assert_eq_m128(r, e); + } + #[simd_test(enable = "avx512f")] const fn test_mm512_cvtepi32_epi16() { let a = _mm512_set_epi32(0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15); From ba10b8454d08caee1b23679f74c72eb5222316e2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 21 Aug 2026 15:29:27 -0400 Subject: [PATCH 0072/1309] Fix abort implementation --- src/builder.rs | 4 ++-- src/context.rs | 7 +------ src/intrinsic/mod.rs | 6 ++---- tests/run/custom_abort.rs | 27 +++++++++++++++++++++++++++ 4 files changed, 32 insertions(+), 12 deletions(-) create mode 100644 tests/run/custom_abort.rs diff --git a/src/builder.rs b/src/builder.rs index 550f09615ef4f..cdf71e409ce00 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -719,8 +719,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { - let abort = self.context.get_builtin_function("abort"); - self.block.add_eval(self.location, self.context.new_call(self.location, abort, &[])); + let trap = self.context.get_builtin_function("__builtin_trap"); + self.block.add_eval(self.location, self.context.new_call(self.location, trap, &[])); let return_value = self.new_temp(self.current_func(), self.location, return_type); self.block.end_with_return(self.location, return_value) } diff --git a/src/context.rs b/src/context.rs index ebbdbb72516aa..cb9b681f791eb 100644 --- a/src/context.rs +++ b/src/context.rs @@ -242,12 +242,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let isize_type = usize_type; let bool_type = context.new_type::(); - let mut functions = FxHashMap::default(); - let builtins = ["abort"]; - - for builtin in builtins.iter() { - functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); - } + let functions = FxHashMap::default(); let mut cx = Self { int128_align: tcx diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 9704fd7614ef6..2bbbe5faf0e4c 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -103,7 +103,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::round_ties_even_f64 => "rint", sym::roundf32 => "roundf", sym::roundf64 => "round", - sym::abort => "abort", _ => return None, }; Some(cx.context.get_builtin_function(gcc_name)) @@ -641,9 +640,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } fn abort(&mut self) { - let func = self.context.get_builtin_function("abort"); - let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - self.call(self.type_void(), None, None, func, &[], None, None); + let func = self.context.get_builtin_function("__builtin_trap"); + self.block.add_eval(self.location, self.context.new_call(self.location, func, &[])); } fn assume(&mut self, value: Self::Value) { diff --git a/tests/run/custom_abort.rs b/tests/run/custom_abort.rs new file mode 100644 index 0000000000000..eafa4321a4324 --- /dev/null +++ b/tests/run/custom_abort.rs @@ -0,0 +1,27 @@ +// Compiler: +// +// Run-time: +// status: 42 + +// Check that a program can define its own `abort`. + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[no_mangle] +extern "C" fn abort() { + unsafe { + libc::exit(42); + } +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + abort(); + 0 +} From 773242f1d39b66f58fa6cc6f883892ebd8440023 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sun, 23 Aug 2026 11:36:59 +0100 Subject: [PATCH 0073/1309] Add manual exception for the intrinsics forgotten in the intel intrinsics guide xml --- .../stdarch/crates/stdarch-verify/tests/x86-intel.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs index be948df541b79..d2839bb300c2d 100644 --- a/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs +++ b/library/stdarch/crates/stdarch-verify/tests/x86-intel.rs @@ -293,7 +293,16 @@ fn verify_all_signatures() { "_MM_SHUFFLE" | "_xabort_code" | // Not listed with intel, but manually verified - "cmpxchg16b" + "cmpxchg16b" | + // Apparently forgotten in the Intel Intrinsics Guide + // but present in other Intel documentation and clang, + // see https://github.com/rust-lang/rust/issues/158196 + "_mm_cvtepu32_ps" | + "_mm_mask_cvtepu32_ps" | + "_mm_maskz_cvtepu32_ps" | + "_mm256_cvtepu32_ps" | + "_mm256_mask_cvtepu32_ps" | + "_mm256_maskz_cvtepu32_ps" => continue, _ => {} } From d78d2069074fe3da4125f8a3417dd73cb7adc461 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sun, 23 Aug 2026 11:54:11 +0100 Subject: [PATCH 0074/1309] Use the proper tracking issue --- library/stdarch/crates/core_arch/src/x86/avx512f.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 3588e146f0395..10a0d370df7ba 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -13097,7 +13097,7 @@ pub const fn _mm512_maskz_cvtepu32_ps(k: __mmask16, a: __m512i) -> __m512 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_cvtepu32_ps(a: __m256i) -> __m256 { @@ -13113,7 +13113,7 @@ pub const fn _mm256_cvtepu32_ps(a: __m256i) -> __m256 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_cvtepu32_ps(src: __m256, k: __mmask8, a: __m256i) -> __m256 { @@ -13129,7 +13129,7 @@ pub const fn _mm256_mask_cvtepu32_ps(src: __m256, k: __mmask8, a: __m256i) -> __ /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_cvtepu32_ps(k: __mmask8, a: __m256i) -> __m256 { @@ -13145,7 +13145,7 @@ pub const fn _mm256_maskz_cvtepu32_ps(k: __mmask8, a: __m256i) -> __m256 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtepu32_ps(a: __m128i) -> __m128 { @@ -13162,7 +13162,7 @@ pub const fn _mm_cvtepu32_ps(a: __m128i) -> __m128 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_cvtepu32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m128 { @@ -13179,7 +13179,7 @@ pub const fn _mm_mask_cvtepu32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m12 /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_updates", issue = "158196")] +#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_cvtepu32_ps(k: __mmask8, a: __m128i) -> __m128 { From 9f02c537bbd73a47de67659e9c812e73496c2a44 Mon Sep 17 00:00:00 2001 From: "Sergey \"Shnatsel\" Davidoff" Date: Sun, 23 Aug 2026 11:55:04 +0100 Subject: [PATCH 0075/1309] cargo fmt --- .../crates/core_arch/src/x86/avx512f.rs | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 10a0d370df7ba..50f8a13ac98d4 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -13097,7 +13097,10 @@ pub const fn _mm512_maskz_cvtepu32_ps(k: __mmask16, a: __m512i) -> __m512 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_cvtepu32_ps(a: __m256i) -> __m256 { @@ -13113,7 +13116,10 @@ pub const fn _mm256_cvtepu32_ps(a: __m256i) -> __m256 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_mask_cvtepu32_ps(src: __m256, k: __mmask8, a: __m256i) -> __m256 { @@ -13129,7 +13135,10 @@ pub const fn _mm256_mask_cvtepu32_ps(src: __m256, k: __mmask8, a: __m256i) -> __ /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm256_maskz_cvtepu32_ps(k: __mmask8, a: __m256i) -> __m256 { @@ -13145,7 +13154,10 @@ pub const fn _mm256_maskz_cvtepu32_ps(k: __mmask8, a: __m256i) -> __m256 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_cvtepu32_ps(a: __m128i) -> __m128 { @@ -13162,7 +13174,10 @@ pub const fn _mm_cvtepu32_ps(a: __m128i) -> __m128 { /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_mask_cvtepu32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m128 { @@ -13179,7 +13194,10 @@ pub const fn _mm_mask_cvtepu32_ps(src: __m128, k: __mmask8, a: __m128i) -> __m12 /// Documentation on them can be found in the [Intel Software Development Manual](https://www.intel.com/content/www/us/en/developer/articles/technical/intel-sdm.html). #[inline] #[target_feature(enable = "avx512f,avx512vl")] -#[unstable(feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", issue = "161585")] +#[unstable( + feature = "stdarch_x86_avx512_vl_u32_to_f32_conversions", + issue = "161585" +)] #[cfg_attr(test, assert_instr(vcvtudq2ps))] #[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] pub const fn _mm_maskz_cvtepu32_ps(k: __mmask8, a: __m128i) -> __m128 { From 5e4a79b121bf3d784d20c893b7f34084a67c7912 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 23 Aug 2026 11:36:36 -0400 Subject: [PATCH 0076/1309] Add regression test for #827 --- tests/compile/asm_noreturn_call.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/compile/asm_noreturn_call.rs diff --git a/tests/compile/asm_noreturn_call.rs b/tests/compile/asm_noreturn_call.rs new file mode 100644 index 0000000000000..c9238697d8097 --- /dev/null +++ b/tests/compile/asm_noreturn_call.rs @@ -0,0 +1,15 @@ +// Compiler: + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/827 + +#![crate_type = "lib"] + +#[cfg(target_arch = "x86_64")] +pub type NoReturn = extern "sysv64" fn(&'static u8) -> !; + +#[cfg(target_arch = "x86_64")] +pub fn call_no_return(function: *const NoReturn) -> ! { + unsafe { + std::arch::asm!("call {}", in(reg) function, options(noreturn)); + } +} From 2e36890c46be699fc43e7357220068813b6a8d15 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 24 Aug 2026 04:22:38 +0000 Subject: [PATCH 0077/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to da5114692c9ebe46b869488c5f34f92eb10b98c1. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 61a4b2d8c095f..7b170626619e4 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -1e5ee356374211706221b71b6106d297a646ee57 +da5114692c9ebe46b869488c5f34f92eb10b98c1 From 940498dad7cb35a753a7cce104ab510b414e84de Mon Sep 17 00:00:00 2001 From: Rachit2323 Date: Mon, 24 Aug 2026 12:25:29 +0530 Subject: [PATCH 0078/1309] fix const_item_mutation lint to use needs_drop instead of has_dtor --- .../src/check_const_item_mutation.rs | 40 ++++++++++------- tests/ui/lint/lint-const-item-mutation.rs | 10 +++-- tests/ui/lint/lint-const-item-mutation.stderr | 43 +++++++------------ 3 files changed, 47 insertions(+), 46 deletions(-) diff --git a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs index 5b25bdc01117b..e8ff3c3a08b79 100644 --- a/compiler/rustc_mir_transform/src/check_const_item_mutation.rs +++ b/compiler/rustc_mir_transform/src/check_const_item_mutation.rs @@ -2,7 +2,7 @@ use rustc_hir::HirId; use rustc_lint_defs::builtin::CONST_ITEM_MUTATION; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; -use rustc_middle::ty::TyCtxt; +use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt}; use rustc_span::Span; use rustc_span::def_id::DefId; @@ -35,8 +35,9 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> { fn is_const_item_without_destructor(&self, local: Local) -> Option { let def_id = self.is_const_item(local)?; - // We avoid linting mutation of a const item if the const's type has a - // Drop impl. The Drop logic observes the mutation which was performed. + // We avoid linting mutation of a const item if the const's type needs + // drop. Any drop logic (including that of fields) may observe the + // mutation which was performed. // // pub struct Log { msg: &'static str } // pub const LOG: Log = Log { msg: "" }; @@ -46,21 +47,30 @@ impl<'tcx> ConstMutationChecker<'_, 'tcx> { // // LOG.msg = "wow"; // prints "wow" // + // Likewise, if a field of the const type has its own Drop impl, that + // drop logic may also observe the mutation: + // + // struct Inner { val: u32 } + // impl Drop for Inner { fn drop(&mut self) { println!("{}", self.val); } } + // struct Outer { inner: Inner } + // const O: Outer = Outer { inner: Inner { val: 0 } }; + // + // O.inner.val = 42; // Inner::drop prints "42" + // // FIXME(https://github.com/rust-lang/rust/issues/77425): // Drop this exception once there is a stable attribute to suppress the - // const item mutation lint for a single specific const only. Something - // equivalent to: - // - // #[const_mutation_allowed] - // pub const LOG: Log = Log { msg: "" }; - // FIXME: this should not be checking for `Drop` impls, - // but whether it or any field has a Drop impl (`needs_drop`) - // as fields' Drop impls may make this observable, too. - match self.tcx.type_of(def_id).skip_binder().ty_adt_def().map(|adt| adt.has_dtor(self.tcx)) - { - Some(true) => None, - Some(false) | None => Some(def_id), + // const item mutation lint for a single specific const only. + let ty = self.tcx.type_of(def_id).instantiate_identity().skip_norm_wip(); + // `needs_drop` is overly conservative for types that contain type + // parameters (e.g. `Self` in a trait associated const): it always + // returns `true` because the parameter *might* implement Drop, even + // when the concrete type at the call site does not. In that case we + // cannot suppress the lint, so fall through and warn. + if ty.has_param() { + return Some(def_id); } + let typing_env = ty::TypingEnv::non_body_analysis(self.tcx, def_id); + if ty.needs_drop(self.tcx, typing_env) { None } else { Some(def_id) } } /// If we should lint on this usage, return the [`HirId`], source [`Span`] diff --git a/tests/ui/lint/lint-const-item-mutation.rs b/tests/ui/lint/lint-const-item-mutation.rs index d51d3c394937c..877455e7bb869 100644 --- a/tests/ui/lint/lint-const-item-mutation.rs +++ b/tests/ui/lint/lint-const-item-mutation.rs @@ -18,16 +18,19 @@ impl Drop for Mutable { } } -struct Mutable2 { // this one has drop glue but not a Drop impl +struct Mutable2 { // this one has drop glue but not a direct Drop impl msg: &'static str, other: String, } +struct WithFieldDrop { inner: Mutable } // no Drop on this type, but Mutable has one + const ARRAY: [u8; 1] = [25]; const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; const RAW_PTR: *mut u8 = 1 as *mut u8; const MUTABLE: Mutable = Mutable { msg: "" }; const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; +const WFD: WithFieldDrop = WithFieldDrop { inner: Mutable { msg: "" } }; const VEC: Vec = Vec::new(); const PTR: *mut () = 1 as *mut _; const PTR_TO_ARRAY: *mut [u32; 4] = 0x12345678 as _; @@ -50,8 +53,9 @@ fn main() { *MY_STRUCT.raw_ptr = 0; } - MUTABLE.msg = "wow"; // no warning, because Drop observes the mutation - MUTABLE2.msg = "wow"; //~ WARN attempting to modify + MUTABLE.msg = "wow"; // no warning — Drop impl observes the mutation + MUTABLE2.msg = "wow"; // no warning — field String has drop glue (needs_drop = true) + WFD.inner.msg = "observed"; // no warning — Mutable's Drop observes the field mutation VEC.push(0); //~ WARN taking a mutable reference to a `const` item // Test that we don't warn when converting a raw pointer diff --git a/tests/ui/lint/lint-const-item-mutation.stderr b/tests/ui/lint/lint-const-item-mutation.stderr index 0e405c306fe46..84f5e78953e60 100644 --- a/tests/ui/lint/lint-const-item-mutation.stderr +++ b/tests/ui/lint/lint-const-item-mutation.stderr @@ -1,45 +1,45 @@ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:37:5 + --> $DIR/lint-const-item-mutation.rs:40:5 | LL | ARRAY[0] = 5; | ^^^^^^^^^^^^ | = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:26:1 + --> $DIR/lint-const-item-mutation.rs:28:1 | LL | const ARRAY: [u8; 1] = [25]; | ^^^^^^^^^^^^^^^^^^^^ = note: `#[warn(const_item_mutation)]` on by default warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:38:5 + --> $DIR/lint-const-item-mutation.rs:41:5 | LL | MY_STRUCT.field = false; | ^^^^^^^^^^^^^^^^^^^^^^^ | = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:27:1 + --> $DIR/lint-const-item-mutation.rs:29:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:39:5 + --> $DIR/lint-const-item-mutation.rs:42:5 | LL | MY_STRUCT.inner_array[0] = 'b'; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:27:1 + --> $DIR/lint-const-item-mutation.rs:29:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:40:5 + --> $DIR/lint-const-item-mutation.rs:43:5 | LL | MY_STRUCT.use_mut(); | ^^^^^^^^^^^^^^^^^^^ @@ -52,13 +52,13 @@ note: mutable reference created due to call to this method LL | fn use_mut(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^ note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:27:1 + --> $DIR/lint-const-item-mutation.rs:29:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:41:5 + --> $DIR/lint-const-item-mutation.rs:44:5 | LL | &mut MY_STRUCT; | ^^^^^^^^^^^^^^ @@ -66,13 +66,13 @@ LL | &mut MY_STRUCT; = note: each usage of a `const` item creates a new temporary = note: the mutable reference will refer to this temporary, not the original `const` item note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:27:1 + --> $DIR/lint-const-item-mutation.rs:29:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:42:5 + --> $DIR/lint-const-item-mutation.rs:45:5 | LL | (&mut MY_STRUCT).use_mut(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -85,26 +85,13 @@ note: mutable reference created due to call to this method LL | fn use_mut(&mut self) {} | ^^^^^^^^^^^^^^^^^^^^^ note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:27:1 + --> $DIR/lint-const-item-mutation.rs:29:1 | LL | const MY_STRUCT: MyStruct = MyStruct { field: true, inner_array: ['a'], raw_ptr: 2 as *mut u8 }; | ^^^^^^^^^^^^^^^^^^^^^^^^^ -warning: attempting to modify a `const` item - --> $DIR/lint-const-item-mutation.rs:54:5 - | -LL | MUTABLE2.msg = "wow"; - | ^^^^^^^^^^^^^^^^^^^^ - | - = note: each usage of a `const` item creates a new temporary; the original `const` item will not be modified -note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:30:1 - | -LL | const MUTABLE2: Mutable2 = Mutable2 { msg: "", other: String::new() }; - | ^^^^^^^^^^^^^^^^^^^^^^^^ - warning: taking a mutable reference to a `const` item - --> $DIR/lint-const-item-mutation.rs:55:5 + --> $DIR/lint-const-item-mutation.rs:59:5 | LL | VEC.push(0); | ^^^^^^^^^^^ @@ -114,10 +101,10 @@ LL | VEC.push(0); note: mutable reference created due to call to this method --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL note: `const` item defined here - --> $DIR/lint-const-item-mutation.rs:31:1 + --> $DIR/lint-const-item-mutation.rs:34:1 | LL | const VEC: Vec = Vec::new(); | ^^^^^^^^^^^^^^^^^^^ -warning: 8 warnings emitted +warning: 7 warnings emitted From e3b84cf2bb00be67e08657c2b520e843c84013b4 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:19:25 +0800 Subject: [PATCH 0079/1309] [Bootstrap] Build with `--locked` Even when locally, to minimize supply-chain risk from very-new registry artifacts. --- bootstrap.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.sh b/bootstrap.sh index 05ac0ce2f306f..008147f82b173 100755 --- a/bootstrap.sh +++ b/bootstrap.sh @@ -4,7 +4,7 @@ # power comes great responsibility. # We deliberately avoid reformatting files with rustfmt comment directives. -cargo build --release +cargo build --release --locked target/release/rustfmt src/lib.rs target/release/rustfmt src/bin/main.rs From 00bd42928e98068e33429076158a54f396e0ddb3 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:21:59 +0800 Subject: [PATCH 0080/1309] [Docs] Adjust README to use `--locked` --- README.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 0c7ba34574d75..97796407d5410 100644 --- a/README.md +++ b/README.md @@ -134,8 +134,8 @@ language: rust before_script: - rustup component add rustfmt script: -- cargo build -- cargo test +- cargo build --locked +- cargo test --locked - cargo fmt --all -- --check ``` @@ -144,11 +144,11 @@ for more info. ## How to build and test -`cargo build` to build. +`cargo build --locked` to build. -`cargo test` to run all tests. +`cargo test --locked` to run all tests. -To run rustfmt after this, use `cargo run --bin rustfmt -- filename`. See the +To run rustfmt after this, use `cargo run --locked --bin rustfmt -- filename`. See the notes above on running rustfmt. From d1785af6cc8522e10673abd53e9b7dc545e79da7 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:22:39 +0800 Subject: [PATCH 0081/1309] [Test] Adjust help message to use `--locked` --- src/test/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/test/mod.rs b/src/test/mod.rs index 3353b78b221e3..49987b9b520e4 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -1191,7 +1191,8 @@ fn rustfmt() -> PathBuf { assert!( me.is_file() || me.with_extension("exe").is_file(), "{}", - "no rustfmt bin, try running `cargo build` or `cargo build --release` before testing" + "no rustfmt bin, try running `cargo build --locked` or `cargo build --locked --release` \ + before testing" ); me } From 9b690e819a93f321bdfeb80f30322b2f14436912 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:36:00 +0800 Subject: [PATCH 0082/1309] [Docs] Update contrib docs to suggest `--locked` --- Contributing.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Contributing.md b/Contributing.md index 7b298052ab2a0..3c38e7ad22b46 100644 --- a/Contributing.md +++ b/Contributing.md @@ -20,7 +20,7 @@ issues where it does something you don't expect. Having a strong test suite for a tool like this is essential. It is very easy to create regressions. Any tests you can add are very much appreciated. -The tests can be run with `cargo test`. This does a number of things: +The tests can be run with `cargo test --locked`. This does a number of things: * runs the unit tests for a number of internal functions; * makes sure that rustfmt run on every file in `./tests/source/` is equal to its associated file in `./tests/target/`; this catches From 52bae15cf5c29a4b3ec319fb4640c9f46f256d01 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:39:17 +0800 Subject: [PATCH 0083/1309] [CI] Build/run `build_and_test` with `--locked` --- ci/src/build_and_test.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ci/src/build_and_test.rs b/ci/src/build_and_test.rs index 305c4d5aaa296..3033577596d08 100644 --- a/ci/src/build_and_test.rs +++ b/ci/src/build_and_test.rs @@ -4,7 +4,7 @@ use std::collections::HashMap; fn run_tests_in_dir(env: &HashMap<&str, &str>, dir: &str) -> Result<(), String> { run_command_with_env("cargo", &["build", "--locked"], dir, &env)?; - run_command_with_env("cargo", &["test"], dir, &env) + run_command_with_env("cargo", &["test", "--locked"], dir, &env) } pub fn runner() -> Result<(), String> { @@ -39,7 +39,7 @@ pub fn runner() -> Result<(), String> { &["build", "--locked"] }; run_command_with_env("cargo", options, ".", &env)?; - run_command_with_env("cargo", &["test"], ".", &env)?; + run_command_with_env("cargo", &["test", "--locked"], ".", &env)?; // Build and test config_proc_macro run_tests_in_dir(&env, "config_proc_macro")?; From b3b45551e203d0b29a8a145b00d3c2aa8a9ae7d0 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 21 Aug 2026 17:41:52 +0800 Subject: [PATCH 0084/1309] [CI] Build/test/run with `--locked` --- .github/workflows/check_diff.yml | 2 +- .github/workflows/integration.yml | 2 +- .github/workflows/rustdoc_check.yml | 2 +- .github/workflows/test.yml | 2 +- .github/workflows/upload-assets.yml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml index 41b138acb63fc..d323e8de0b67b 100644 --- a/.github/workflows/check_diff.yml +++ b/.github/workflows/check_diff.yml @@ -46,7 +46,7 @@ jobs: - name: Build check_diff binary working-directory: ./check_diff - run: cargo build --release + run: cargo build --release --locked - name: Run Diff Check working-directory: ./check_diff diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index d248fc41dab5a..09fc59114e97e 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -70,5 +70,5 @@ jobs: - name: run integration tests env: TARGET: x86_64-unknown-linux-gnu - run: cargo run --manifest-path ci/Cargo.toml integration ${{ matrix.integration }} + run: cargo run --locked --manifest-path ci/Cargo.toml integration ${{ matrix.integration }} continue-on-error: ${{ matrix.allow-failure == true }} diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml index 4a22d7801ab05..04bb8e1d240f6 100644 --- a/.github/workflows/rustdoc_check.yml +++ b/.github/workflows/rustdoc_check.yml @@ -23,4 +23,4 @@ jobs: - name: document rustfmt env: RUSTDOCFLAGS: --document-private-items --enable-index-page --show-type-layout --generate-link-to-definition -Zunstable-options -Dwarnings - run: cargo doc -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro + run: cargo doc --locked -Zskip-rustdoc-fingerprint --no-deps -p rustfmt-nightly -p rustfmt-config_proc_macro diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 7202f03f5511c..aed79eb2e7b72 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -78,7 +78,7 @@ jobs: env: RUSTFLAGS: -D warnings CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true - run: cargo run --manifest-path ci/Cargo.toml build-and-test + run: cargo run --locked --manifest-path ci/Cargo.toml build-and-test test-conclusion: name: "test conclusion" diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml index a81545052e07e..a6a3d3bc51a85 100644 --- a/.github/workflows/upload-assets.yml +++ b/.github/workflows/upload-assets.yml @@ -46,7 +46,7 @@ jobs: shell: bash - name: Build release binaries - run: cargo build --release + run: cargo build --release --locked - name: Build archive shell: bash From 7425b212ba33328fd334dcec7de4c9bdf36a6810 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 24 Aug 2026 17:10:05 +0800 Subject: [PATCH 0085/1309] [DiffCheck] Use `--locked` for cargo build --- check_diff/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/check_diff/src/lib.rs b/check_diff/src/lib.rs index 4d3933257dcc5..1d8fcbfce4cb7 100644 --- a/check_diff/src/lib.rs +++ b/check_diff/src/lib.rs @@ -580,7 +580,7 @@ pub fn build_rustfmt_from_src>( info!("Building rustfmt from source"); let Ok(_) = Command::new("cargo") .current_dir(dir) - .args(["build", "-q", "--release", "--bin", "rustfmt"]) + .args(["build", "--locked", "-q", "--release", "--bin", "rustfmt"]) .output() else { return Err(CheckDiffError::FailedSourceBuild( From 658e9db185ca15f13c53c46cf8416b94d5ac6cd4 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 24 Aug 2026 11:28:00 -0400 Subject: [PATCH 0086/1309] Handle alignment and volatile flag for mem operations --- src/builder.rs | 57 ++++++++++++++++++++++++------ tests/asm/bulk_memory_alignment.rs | 45 +++++++++++++++++++++++ tests/asm/volatile_bulk_memory.rs | 37 +++++++++++++++++++ 3 files changed, 128 insertions(+), 11 deletions(-) create mode 100644 tests/asm/bulk_memory_alignment.rs create mode 100644 tests/asm/volatile_bulk_memory.rs diff --git a/src/builder.rs b/src/builder.rs index cdf71e409ce00..8ec72bb6f3ac8 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -66,6 +66,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.value_counter.get() } + /// Tell GCC that `pointer` is `align`-aligned, so that the bulk memory builtins can widen their + /// accesses: a pointer cast to an aligned type would be dropped as a useless conversion. + fn assume_aligned(&mut self, pointer: RValue<'gcc>, align: Align) -> RValue<'gcc> { + if align.bytes() <= 1 { + return pointer; + } + let assume_aligned = self.context.get_builtin_function("__builtin_assume_aligned"); + let alignment = self.context.new_rvalue_from_long(self.type_size_t(), align.bytes() as i64); + let pointer_type = pointer.get_type(); + let const_void_ptr_type = self.context.new_type::<()>().make_const().make_pointer(); + let pointer = self.context.new_cast(self.location, pointer, const_void_ptr_type); + let aligned = self.context.new_call(self.location, assume_aligned, &[pointer, alignment]); + self.context.new_cast(self.location, aligned, pointer_type) + } + + /// GCC ignores a volatile qualifier on the pointers given to `memcpy`/`memmove`/`memset` and + /// happily deletes the call, so a barrier is what keeps the operation observable. The pointers + /// are fed to it because a clobber alone does not reach memory GCC believes never escapes. + fn volatile_barrier(&mut self, pointers: &[RValue<'gcc>]) { + let barrier = self.block.add_extended_asm(self.location, ""); + for pointer in pointers { + barrier.add_input_operand(None, "r", *pointer); + } + barrier.add_clobber("memory"); + barrier.set_volatile_flag(true); + } + fn atomic_extremum( &mut self, operation: ExtremumOperation, @@ -1448,47 +1475,53 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn memcpy( &mut self, dst: RValue<'gcc>, - _dst_align: Align, + dst_align: Align, src: RValue<'gcc>, - _src_align: Align, + src_align: Align, size: RValue<'gcc>, flags: MemFlags, _tt: Option, // Autodiff TypeTrees are LLVM-only, ignored in GCC backend ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported"); let size = self.intcast(size, self.type_size_t(), false); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); + let dst = self.assume_aligned(dst, dst_align); let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + let src = self.assume_aligned(src, src_align); let memcpy = self.context.get_builtin_function("memcpy"); - // FIXME(antoyo): handle aligns and is_volatile. self.block.add_eval( self.location, self.context.new_call(self.location, memcpy, &[dst, src, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[dst, src]); + } } fn memmove( &mut self, dst: RValue<'gcc>, - _dst_align: Align, + dst_align: Align, src: RValue<'gcc>, - _src_align: Align, + src_align: Align, size: RValue<'gcc>, flags: MemFlags, ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported"); let size = self.intcast(size, self.type_size_t(), false); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); + let dst = self.assume_aligned(dst, dst_align); let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + let src = self.assume_aligned(src, src_align); let memmove = self.context.get_builtin_function("memmove"); - // FIXME(antoyo): handle is_volatile. self.block.add_eval( self.location, self.context.new_call(self.location, memmove, &[dst, src, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[dst, src]); + } } fn memset( @@ -1496,20 +1529,22 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, - _align: Align, + align: Align, flags: MemFlags, ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memset not supported"); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let ptr = self.pointercast(ptr, self.type_i8p()); + let ptr = self.assume_aligned(ptr, align); let memset = self.context.get_builtin_function("memset"); - // FIXME(antoyo): handle align and is_volatile. let fill_byte = self.context.new_cast(self.location, fill_byte, self.i32_type); let size = self.intcast(size, self.type_size_t(), false); self.block.add_eval( self.location, self.context.new_call(self.location, memset, &[ptr, fill_byte, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[ptr]); + } } fn vscale(&mut self, _: Self::Type) -> Self::Value { diff --git a/tests/asm/bulk_memory_alignment.rs b/tests/asm/bulk_memory_alignment.rs new file mode 100644 index 0000000000000..6115467447104 --- /dev/null +++ b/tests/asm/bulk_memory_alignment.rs @@ -0,0 +1,45 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +// The alignment reaches GCC's `memcpy`/`memset` expansion only through +// `__builtin_assume_aligned`; a pointer cast to an aligned type is stripped as a useless +// conversion. An over-aligned type therefore has to expand to aligned moves and a packed one +// to unaligned moves. The alignment is 64 so that the contrast holds whatever vector width +// the host picks. + +#[repr(align(64))] +pub struct Aligned([u8; 64]); + +#[repr(C, packed)] +pub struct Packed([u8; 64]); + +// CHECK-LABEL: "copy_aligned": +// CHECK: {{(v)?mov(dqa|aps)}} +#[no_mangle] +pub unsafe fn copy_aligned(destination: *mut Aligned, source: *const Aligned) { + core::ptr::copy_nonoverlapping(source, destination, 1); +} + +// CHECK-LABEL: "copy_packed": +// CHECK: {{(v)?mov(dqu|ups)}} +#[no_mangle] +pub unsafe fn copy_packed(destination: *mut Packed, source: *const Packed) { + core::ptr::copy_nonoverlapping(source, destination, 1); +} + +// CHECK-LABEL: "set_aligned": +// CHECK: {{(v)?mov(dqa|aps)}} +#[no_mangle] +pub unsafe fn set_aligned(destination: *mut Aligned) { + core::ptr::write_bytes(destination, 0, 1); +} + +// CHECK-LABEL: "set_packed": +// CHECK: {{(v)?mov(dqu|ups)}} +#[no_mangle] +pub unsafe fn set_packed(destination: *mut Packed) { + core::ptr::write_bytes(destination, 0, 1); +} diff --git a/tests/asm/volatile_bulk_memory.rs b/tests/asm/volatile_bulk_memory.rs new file mode 100644 index 0000000000000..6233b8ac74c0e --- /dev/null +++ b/tests/asm/volatile_bulk_memory.rs @@ -0,0 +1,37 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -Copt-level=3 + +#![feature(core_intrinsics)] +#![crate_type = "lib"] + +use std::intrinsics::{ + volatile_copy_memory, volatile_copy_nonoverlapping_memory, volatile_set_memory, +}; + +// The buffers below are never read back, so the writes only survive because they are volatile. +// The functions are ordered alphabetically because that is the order they are emitted in. + +// CHECK-LABEL: "volatile_copy": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_copy(source: *const u8) { + let mut buffer = [1u8; 64]; + volatile_copy_memory(buffer.as_mut_ptr(), source, 64); +} + +// CHECK-LABEL: "volatile_copy_nonoverlapping": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_copy_nonoverlapping(source: *const u8) { + let mut buffer = [1u8; 64]; + volatile_copy_nonoverlapping_memory(buffer.as_mut_ptr(), source, 64); +} + +// CHECK-LABEL: "volatile_set": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_set() { + let mut buffer = [1u8; 64]; + volatile_set_memory(buffer.as_mut_ptr(), 0, 64); +} From df828069ea98c621f4ebf92bfc573ebc0727817a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 23 Aug 2026 13:58:31 -0400 Subject: [PATCH 0087/1309] Fix and support more linkages --- src/base.rs | 59 ++++++++++++----- src/mono_item.rs | 2 +- tests/c/import_linkage.c | 16 +++++ tests/c/weak_function_linkage.c | 49 ++++++++++++++ tests/run/import_linkage.rs | 77 ++++++++++++++++++++++ tests/run/weak_function_linkage.rs | 100 +++++++++++++++++++++++++++++ 6 files changed, 285 insertions(+), 18 deletions(-) create mode 100644 tests/c/import_linkage.c create mode 100644 tests/c/weak_function_linkage.c create mode 100644 tests/run/import_linkage.rs create mode 100644 tests/run/weak_function_linkage.rs diff --git a/src/base.rs b/src/base.rs index 9c06c7090c8cb..a7ee26b400282 100644 --- a/src/base.rs +++ b/src/base.rs @@ -39,32 +39,57 @@ pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibil } } +/// The kind of a global declared with an explicit `#[linkage]`. +/// +/// This is only reached for imports (`extern { #[linkage = "..."] static X: *const T; }`), where +/// every flavour but `internal` is an undefined reference. `extern_weak` additionally gets +/// `VarAttribute::Weak` from the caller, so that an unresolved symbol reads as null. pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { match linkage { - Linkage::External => GlobalKind::Imported, - Linkage::AvailableExternally => GlobalKind::Imported, - Linkage::LinkOnceAny => unimplemented!(), - Linkage::LinkOnceODR => unimplemented!(), - Linkage::WeakAny => unimplemented!(), - Linkage::WeakODR => unimplemented!(), Linkage::Internal => GlobalKind::Internal, - Linkage::ExternalWeak => GlobalKind::Imported, // FIXME(antoyo): should be weak linkage. - Linkage::Common => unimplemented!(), + Linkage::External + | Linkage::AvailableExternally + | Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => GlobalKind::Imported, } } +/// The type of a function *definition* with an explicit `#[linkage]`. +/// +/// The flavours that another object file is allowed to override also need +/// `linkage_needs_weak_attribute` from the caller: `FunctionType` alone cannot express weakness. pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { match linkage { Linkage::External => FunctionType::Exported, - // FIXME(antoyo): set the attribute externally_visible. - Linkage::AvailableExternally => FunctionType::Extern, - Linkage::LinkOnceAny => unimplemented!(), - Linkage::LinkOnceODR => unimplemented!(), - Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce. - Linkage::WeakODR => unimplemented!(), - Linkage::Internal => FunctionType::Internal, - Linkage::ExternalWeak => unimplemented!(), - Linkage::Common => unimplemented!(), + // libgccjit cannot emit a definition that the linker discards in favour of the one in + // another object file, so emit a private copy of it instead. + Linkage::AvailableExternally | Linkage::Internal => FunctionType::Internal, + // libgccjit exposes no comdat, so `weak` stands in for every overridable flavour. + Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => FunctionType::Exported, + } +} + +/// Whether a definition with this linkage must carry the `weak` attribute, so that a strong +/// definition in another object file wins over it instead of clashing with it. +#[cfg(feature = "master")] +pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { + match linkage { + Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => true, + Linkage::External | Linkage::AvailableExternally | Linkage::Internal => false, } } diff --git a/src/mono_item.rs b/src/mono_item.rs index 521c86e627415..371f3fd499611 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -172,7 +172,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); #[cfg(feature = "master")] - if linkage == Linkage::WeakAny { + if base::linkage_needs_weak_attribute(linkage) { fn_decl.add_attribute(FnAttribute::Weak); } diff --git a/tests/c/import_linkage.c b/tests/c/import_linkage.c new file mode 100644 index 0000000000000..d725b86c6c14b --- /dev/null +++ b/tests/c/import_linkage.c @@ -0,0 +1,16 @@ +/* The symbols that `tests/run/import_linkage.rs` imports with an explicit `#[linkage]`. + * + * Such an import is a pointer whose value is the address of the symbol, so what the Rust side + * reads back is `&value_*`, not the pointer stored in it. The distinct values make a mix-up + * visible. */ + +#include + +int32_t external_value = 1; +int32_t available_externally_value = 2; +int32_t linkonce_value = 3; +int32_t linkonce_odr_value = 4; +int32_t weak_value = 5; +int32_t weak_odr_value = 6; +int32_t common_value = 7; +int32_t extern_weak_value = 8; diff --git a/tests/c/weak_function_linkage.c b/tests/c/weak_function_linkage.c new file mode 100644 index 0000000000000..72ea483fd86e0 --- /dev/null +++ b/tests/c/weak_function_linkage.c @@ -0,0 +1,49 @@ +/* Strong definitions of the functions that `tests/run/weak_function_linkage.rs` also defines, but + * weakly. The linker has to keep these and drop the Rust ones. + * + * A backend that emits the Rust definitions as ordinary global symbols does not merely pick the + * wrong one: the link fails outright with a duplicate definition. */ + +#include + +int32_t weak_function(void) +{ + return 1; +} + +int32_t weak_odr_function(void) +{ + return 2; +} + +int32_t linkonce_function(void) +{ + return 3; +} + +int32_t linkonce_odr_function(void) +{ + return 4; +} + +int32_t common_function(void) +{ + return 5; +} + +/* Called from Rust, so that the calls also go through a caller that GCC compiled: a cg_gcc caller + * could inline the weak body it can see instead of calling the symbol. */ +int32_t c_call_all(void) +{ + if (weak_function() != 1) + return 11; + if (weak_odr_function() != 2) + return 12; + if (linkonce_function() != 3) + return 13; + if (linkonce_odr_function() != 4) + return 14; + if (common_function() != 5) + return 15; + return 0; +} diff --git a/tests/run/import_linkage.rs b/tests/run/import_linkage.rs new file mode 100644 index 0000000000000..0b044529b9bf4 --- /dev/null +++ b/tests/run/import_linkage.rs @@ -0,0 +1,77 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks the `#[linkage]` flavours an `extern` static can be imported with, against the symbols +// `tests/c/import_linkage.c` defines. `linkonce`, `linkonce_odr`, `weak`, `weak_odr` and `common` +// used to reach an `unimplemented!()` in `global_linkage_to_gcc`. +// +// The value of such an import is the address of the symbol rather than its contents, which is why +// the types are pointers: an `extern_weak` import of a symbol nobody defines reads as null instead +// of failing the link. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +extern "C" { + #[linkage = "external"] + static external_value: *const i32; + #[linkage = "available_externally"] + static available_externally_value: *const i32; + #[linkage = "linkonce"] + static linkonce_value: *const i32; + #[linkage = "linkonce_odr"] + static linkonce_odr_value: *const i32; + #[linkage = "weak"] + static weak_value: *const i32; + #[linkage = "weak_odr"] + static weak_odr_value: *const i32; + #[linkage = "common"] + static common_value: *const i32; + #[linkage = "extern_weak"] + static extern_weak_value: *const i32; + + // Nothing defines this one, so it stays null instead of breaking the link. + #[linkage = "extern_weak"] + static undefined_value: *const i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + unsafe { + if *external_value != 1 { + return 1; + } + if *available_externally_value != 2 { + return 2; + } + if *linkonce_value != 3 { + return 3; + } + if *linkonce_odr_value != 4 { + return 4; + } + if *weak_value != 5 { + return 5; + } + if *weak_odr_value != 6 { + return 6; + } + if *common_value != 7 { + return 7; + } + if *extern_weak_value != 8 { + return 8; + } + if undefined_value as usize != 0 { + return 9; + } + } + 0 +} diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs new file mode 100644 index 0000000000000..6805213636935 --- /dev/null +++ b/tests/run/weak_function_linkage.rs @@ -0,0 +1,100 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that the `#[linkage]` flavours another object file is allowed to override are emitted as +// weak symbols, by linking against `tests/c/weak_function_linkage.c`, which defines the same +// symbols strongly. +// +// `weak` used to be emitted as an ordinary global symbol, which the C definitions clash with, and +// `weak_odr`, `linkonce`, `linkonce_odr` and `common` reached an `unimplemented!()` in +// `linkage_to_gcc`. `available_externally` reached libgccjit, which rejects a body on an imported +// function. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[linkage = "weak"] +#[no_mangle] +extern "C" fn weak_function() -> i32 { + 0 +} + +#[linkage = "weak_odr"] +#[no_mangle] +extern "C" fn weak_odr_function() -> i32 { + 0 +} + +#[linkage = "linkonce"] +#[no_mangle] +extern "C" fn linkonce_function() -> i32 { + 0 +} + +#[linkage = "linkonce_odr"] +#[no_mangle] +extern "C" fn linkonce_odr_function() -> i32 { + 0 +} + +#[linkage = "common"] +#[no_mangle] +extern "C" fn common_function() -> i32 { + 0 +} + +// Not overridden by the C side: the definition here is the one that runs. +#[linkage = "weak"] +#[no_mangle] +extern "C" fn only_weak_function() -> i32 { + 6 +} + +// Emitted as a private copy of a definition that lives elsewhere, so it must still be callable. +#[linkage = "available_externally"] +#[no_mangle] +extern "C" fn available_externally_function() -> i32 { + 7 +} + +extern "C" { + fn c_call_all() -> i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + let result = unsafe { c_call_all() }; + if result != 0 { + return result; + } + + if weak_function() != 1 { + return 1; + } + if weak_odr_function() != 2 { + return 2; + } + if linkonce_function() != 3 { + return 3; + } + if linkonce_odr_function() != 4 { + return 4; + } + if common_function() != 5 { + return 5; + } + if only_weak_function() != 6 { + return 6; + } + if available_externally_function() != 7 { + return 7; + } + 0 +} From 642aaa8c9de2adb5099d90ce268b483e7bccbc55 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 23 Aug 2026 14:42:00 -0400 Subject: [PATCH 0088/1309] Implement linkage in predefine_static and fix internal linkage on extern statics --- src/base.rs | 20 +++++----- src/consts.rs | 17 +++++--- src/declare.rs | 6 ++- src/mono_item.rs | 18 +++++++-- tests/c/import_linkage.c | 1 + tests/c/static_linkage.c | 33 ++++++++++++++++ tests/run/import_linkage.rs | 9 ++++- tests/run/static_linkage.rs | 77 +++++++++++++++++++++++++++++++++++++ 8 files changed, 159 insertions(+), 22 deletions(-) create mode 100644 tests/c/static_linkage.c create mode 100644 tests/run/static_linkage.rs diff --git a/src/base.rs b/src/base.rs index a7ee26b400282..46f864bed98e8 100644 --- a/src/base.rs +++ b/src/base.rs @@ -39,22 +39,24 @@ pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibil } } -/// The kind of a global declared with an explicit `#[linkage]`. +/// The kind of a global *definition* with an explicit `#[linkage]`. /// -/// This is only reached for imports (`extern { #[linkage = "..."] static X: *const T; }`), where -/// every flavour but `internal` is an undefined reference. `extern_weak` additionally gets -/// `VarAttribute::Weak` from the caller, so that an unresolved symbol reads as null. +/// The flavours that another object file is allowed to override also need +/// `linkage_needs_weak_attribute` from the caller: `GlobalKind` alone cannot express weakness. pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { match linkage { - Linkage::Internal => GlobalKind::Internal, - Linkage::External - | Linkage::AvailableExternally - | Linkage::LinkOnceAny + Linkage::External => GlobalKind::Exported, + // libgccjit cannot emit a definition that the linker discards in favour of the one in + // another object file, so emit a private copy of it instead. + Linkage::AvailableExternally | Linkage::Internal => GlobalKind::Internal, + // libgccjit exposes neither comdat nor common storage, so `weak` stands in for every + // overridable flavour. + Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR | Linkage::ExternalWeak - | Linkage::Common => GlobalKind::Imported, + | Linkage::Common => GlobalKind::Exported, } } diff --git a/src/consts.rs b/src/consts.rs index b1e06f88a234c..061c09abcf1d4 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -21,7 +21,6 @@ use rustc_middle::ty::{self, Instance}; use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; -use crate::base; use crate::common::bytes_type_in_context; use crate::context::CodegenCx; use crate::type_::struct_attributes; @@ -469,10 +468,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>( ) -> LValue<'gcc> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); if let Some(linkage) = attrs.import_linkage { - // Declare a symbol `foo` with the desired linkage. - let global1 = - cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); + // Whatever the flavour, an import is an undefined reference to a symbol defined elsewhere. + let global1 = cx.declare_global_with_linkage(sym, cx.type_i8(), GlobalKind::Imported); + // Only `extern_weak` lets the symbol stay unresolved, in which case it reads as null. if linkage == Linkage::ExternalWeak { #[cfg(feature = "master")] global1.add_attribute(VarAttribute::Weak); @@ -486,8 +485,14 @@ fn check_and_apply_linkage<'gcc, 'tcx>( // zero. let real_name = format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); - let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section); - // FIXME(antoyo): set linkage. + let global2 = cx.define_global( + &real_name, + gcc_type, + GlobalKind::Exported, + is_tls, + attrs.link_section, + ); + // FIXME(antoyo): set linkage: cg_llvm makes this helper global internal. let value = cx.const_ptrcast(global1.get_address(None), gcc_type); global2.global_set_initializer_rvalue(value); global2 diff --git a/src/declare.rs b/src/declare.rs index 9bf57fbf75bc0..32bb7c3aa349e 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -14,6 +14,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, ty: Type<'gcc>, + global_kind: GlobalKind, is_tls: bool, link_section: Option, ) -> LValue<'gcc> { @@ -31,7 +32,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } global } else { - self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section) + self.declare_global(name, ty, global_kind, is_tls, link_section) } } @@ -141,10 +142,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, ty: Type<'gcc>, + global_kind: GlobalKind, is_tls: bool, link_section: Option, ) -> LValue<'gcc> { - self.get_or_insert_global(name, ty, is_tls, link_section) + self.get_or_insert_global(name, ty, global_kind, is_tls, link_section) } pub fn get_declared_value(&self, name: &str) -> Option> { diff --git a/src/mono_item.rs b/src/mono_item.rs index 371f3fd499611..47889e1847ee5 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -21,7 +21,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn predefine_static( &mut self, def_id: DefId, - _linkage: Linkage, + linkage: Linkage, visibility: Visibility, global_name: &str, ) { @@ -47,10 +47,20 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { }; let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.define_global(global_name, gcc_type, is_tls, attrs.link_section); + let global_kind = base::global_linkage_to_gcc(linkage); + let global = + self.define_global(global_name, gcc_type, global_kind, is_tls, attrs.link_section); #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); - // FIXME(antoyo): set linkage. + { + // GCC warns that it ignores `visibility` on an internal global, and cg_gcc turns + // libgccjit warnings into errors. + if !matches!(global_kind, GlobalKind::Internal) { + global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + } + if base::linkage_needs_weak_attribute(linkage) { + global.add_attribute(VarAttribute::Weak); + } + } #[cfg(feature = "master")] self.add_static_aliases(gcc_type, global_name, attrs, &attrs.foreign_item_symbol_aliases); diff --git a/tests/c/import_linkage.c b/tests/c/import_linkage.c index d725b86c6c14b..f2beb9603d08b 100644 --- a/tests/c/import_linkage.c +++ b/tests/c/import_linkage.c @@ -14,3 +14,4 @@ int32_t weak_value = 5; int32_t weak_odr_value = 6; int32_t common_value = 7; int32_t extern_weak_value = 8; +int32_t internal_value = 9; diff --git a/tests/c/static_linkage.c b/tests/c/static_linkage.c new file mode 100644 index 0000000000000..1a9b4ca5bd735 --- /dev/null +++ b/tests/c/static_linkage.c @@ -0,0 +1,33 @@ +/* Strong definitions of the statics that `tests/run/static_linkage.rs` also defines, but weakly. + * The linker has to keep these and drop the Rust ones; a backend that emits the Rust definitions + * as ordinary global symbols fails the link with a duplicate definition instead. + * + * `internal_static` is the opposite case: the Rust side keeps its own, and the two definitions + * coexist because the Rust one is local. */ + +#include + +int32_t weak_static = 1; +int32_t weak_odr_static = 2; +int32_t linkonce_static = 3; +int32_t linkonce_odr_static = 4; +int32_t common_static = 5; +int32_t internal_static = 200; + +/* Called from Rust, so that the reads also happen in a translation unit GCC compiled. */ +int32_t c_read_all(void) +{ + if (weak_static != 1) + return 11; + if (weak_odr_static != 2) + return 12; + if (linkonce_static != 3) + return 13; + if (linkonce_odr_static != 4) + return 14; + if (common_static != 5) + return 15; + if (internal_static != 200) + return 16; + return 0; +} diff --git a/tests/run/import_linkage.rs b/tests/run/import_linkage.rs index 0b044529b9bf4..c721309020ec8 100644 --- a/tests/run/import_linkage.rs +++ b/tests/run/import_linkage.rs @@ -36,6 +36,10 @@ extern "C" { static common_value: *const i32; #[linkage = "extern_weak"] static extern_weak_value: *const i32; + // An import is an undefined reference whatever the flavour says; this used to declare a + // private zeroed object of its own instead of reaching the definition in the C file. + #[linkage = "internal"] + static internal_value: *const i32; // Nothing defines this one, so it stays null instead of breaking the link. #[linkage = "extern_weak"] @@ -69,9 +73,12 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { if *extern_weak_value != 8 { return 8; } - if undefined_value as usize != 0 { + if *internal_value != 9 { return 9; } + if undefined_value as usize != 0 { + return 10; + } } 0 } diff --git a/tests/run/static_linkage.rs b/tests/run/static_linkage.rs new file mode 100644 index 0000000000000..adc43ab9fe396 --- /dev/null +++ b/tests/run/static_linkage.rs @@ -0,0 +1,77 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that `#[linkage]` on a static that this crate defines reaches the symbol, against +// `tests/c/static_linkage.c`, which defines the overridable ones strongly. +// +// `predefine_static` used to ignore its `linkage` argument outright, so every static came out as +// an ordinary global symbol: the overridable ones clashed with the C definitions at link time, and +// `internal` exported a symbol it should have kept private. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[linkage = "weak"] +#[no_mangle] +pub static weak_static: i32 = 0; + +#[linkage = "weak_odr"] +#[no_mangle] +pub static weak_odr_static: i32 = 0; + +#[linkage = "linkonce"] +#[no_mangle] +pub static linkonce_static: i32 = 0; + +#[linkage = "linkonce_odr"] +#[no_mangle] +pub static linkonce_odr_static: i32 = 0; + +#[linkage = "common"] +#[no_mangle] +pub static common_static: i32 = 0; + +// Private to this crate, so the C definition of the same name is a different object. +#[linkage = "internal"] +#[no_mangle] +pub static internal_static: i32 = 100; + +// Not overridden by the C side: the definition here is the one that survives. +#[linkage = "weak"] +#[no_mangle] +pub static only_weak_static: i32 = 6; + +// Emitted as a private copy of a definition that lives elsewhere, so it must still be readable. +#[linkage = "available_externally"] +#[no_mangle] +pub static available_externally_static: i32 = 7; + +extern "C" { + fn c_read_all() -> i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + let result = unsafe { c_read_all() }; + if result != 0 { + return result; + } + + if internal_static != 100 { + return 1; + } + if only_weak_static != 6 { + return 2; + } + if available_externally_static != 7 { + return 3; + } + 0 +} From 9ad916e901d1b9e6e2c6d21dafcd8cd535e254ff Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 23 Aug 2026 16:56:27 -0400 Subject: [PATCH 0089/1309] Use internal linkage for check_and_apply_linkage --- src/consts.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/consts.rs b/src/consts.rs index 061c09abcf1d4..956b79b0cacd5 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -488,11 +488,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>( let global2 = cx.define_global( &real_name, gcc_type, - GlobalKind::Exported, + GlobalKind::Internal, is_tls, attrs.link_section, ); - // FIXME(antoyo): set linkage: cg_llvm makes this helper global internal. let value = cx.const_ptrcast(global1.get_address(None), gcc_type); global2.global_set_initializer_rvalue(value); global2 From b0feb7ff8193d017e1b05007a1de343c05e586c1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 24 Aug 2026 18:10:25 -0400 Subject: [PATCH 0090/1309] Fix ICE that happened on a weak function marked inline --- src/attributes.rs | 13 +++++++++++++ src/mono_item.rs | 11 ++++++++++- tests/run/weak_function_linkage.rs | 13 +++++++++++++ 3 files changed, 36 insertions(+), 1 deletion(-) diff --git a/src/attributes.rs b/src/attributes.rs index 95d12480efa69..e4d44d790d3e3 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -15,6 +15,8 @@ use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; +#[cfg(feature = "master")] +use crate::base; use crate::context::CodegenCx; use crate::gcc_util::to_gcc_features; @@ -116,6 +118,17 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } else { codegen_fn_attrs.inline }; + // GCC warns that `inline` and `weak` conflict, and cg_gcc turns libgccjit warnings into + // errors. The linkage is what has to survive: rustc lints `#[inline]` as ignored on a + // function with an explicit `#[linkage]` anyway. `inline(never)` does not conflict. + let inline = match inline { + InlineAttr::Always | InlineAttr::Hint | InlineAttr::Force { .. } + if codegen_fn_attrs.linkage.is_some_and(base::linkage_needs_weak_attribute) => + { + InlineAttr::None + } + inline => inline, + }; if let Some(attr) = inline_attr(cx, inline, instance) { if let FnAttribute::AlwaysInline = attr { func.add_attribute(FnAttribute::Inline); diff --git a/src/mono_item.rs b/src/mono_item.rs index 47889e1847ee5..cb133d9c23300 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -55,7 +55,16 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { // GCC warns that it ignores `visibility` on an internal global, and cg_gcc turns // libgccjit warnings into errors. if !matches!(global_kind, GlobalKind::Internal) { - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + // If we're compiling the compiler-builtins crate, e.g., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + let visibility = if self.tcx.is_compiler_builtins(LOCAL_CRATE) { + gccjit::Visibility::Hidden + } else { + base::visibility_to_gcc(visibility) + }; + global.add_attribute(VarAttribute::Visibility(visibility)); } if base::linkage_needs_weak_attribute(linkage) { global.add_attribute(VarAttribute::Weak); diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs index 6805213636935..82e1c3d2681e1 100644 --- a/tests/run/weak_function_linkage.rs +++ b/tests/run/weak_function_linkage.rs @@ -64,6 +64,16 @@ extern "C" fn available_externally_function() -> i32 { 7 } +// GCC warns that `inline` and `weak` conflict, and cg_gcc turns libgccjit warnings into errors, so +// this used to fail to compile at all. The inline hint is what gives way: rustc lints it as ignored +// on a function with an explicit `#[linkage]` anyway, hence the `allow`. +#[linkage = "weak"] +#[inline] +#[allow(unused_attributes)] +extern "C" fn weak_inline_function() -> i32 { + 8 +} + extern "C" { fn c_call_all() -> i32; } @@ -96,5 +106,8 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { if available_externally_function() != 7 { return 7; } + if weak_inline_function() != 8 { + return 8; + } 0 } From 226b3197040dd40778af18f418d6b16d1147ac7f Mon Sep 17 00:00:00 2001 From: AsthaMishra Date: Mon, 24 Aug 2026 22:50:54 +0000 Subject: [PATCH 0091/1309] reserve width for when formatting inline const blocks --- src/expr.rs | 3 +++ tests/source/issue-7055.rs | 27 +++++++++++++++++++++++++++ tests/target/issue-7055.rs | 23 +++++++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/source/issue-7055.rs create mode 100644 tests/target/issue-7055.rs diff --git a/src/expr.rs b/src/expr.rs index 2a989ad833a48..fb392b9965629 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -186,6 +186,9 @@ pub(crate) fn format_expr( // not the `ast::Block` node we're about to rewrite. To prevent dropping inner // attributes call `rewrite_block` directly. // See https://github.com/rust-lang/rustfmt/issues/6158 + + // Shrink the shape by `"const ".len()` before rewriting the block + let shape = shape.offset_left(6, expr.span)?; rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)? } _ => anon_const.rewrite_result(context, shape)?, diff --git a/tests/source/issue-7055.rs b/tests/source/issue-7055.rs new file mode 100644 index 0000000000000..8689bb37ecff9 --- /dev/null +++ b/tests/source/issue-7055.rs @@ -0,0 +1,27 @@ +struct S; + +impl S { + const fn new(_: &str) -> Self { + S + } + + fn go(&self) {} +} + +fn main() { + const { + S::new( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ) + } + .go(); +} + +fn second_issue() { + const { + S::new( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ) + } + .go(); +} \ No newline at end of file diff --git a/tests/target/issue-7055.rs b/tests/target/issue-7055.rs new file mode 100644 index 0000000000000..22dc163cfd0ac --- /dev/null +++ b/tests/target/issue-7055.rs @@ -0,0 +1,23 @@ +struct S; + +impl S { + const fn new(_: &str) -> Self { + S + } + + fn go(&self) {} +} + +fn main() { + const { + S::new("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + } + .go(); +} + +fn second_issue() { + const { + S::new("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + } + .go(); +} From 0defa2c5619f57cbebed336930a452816a67fd35 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Tue, 25 Aug 2026 07:08:31 +0700 Subject: [PATCH 0092/1309] Stabilize `mem::conjure_zst` Tracking issue: https://github.com/rust-lang/rust/issues/95383 --- library/core/src/mem/mod.rs | 6 +++--- library/proc_macro/src/lib.rs | 2 +- tests/ui/consts/std/conjure_zst.rs | 2 -- tests/ui/consts/std/conjure_zst.stderr | 2 +- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 26390e5071c53..1f55f27a7d5bd 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1692,7 +1692,6 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { /// # Examples /// /// ``` -/// #![feature(mem_conjure_zst)] /// use std::mem::conjure_zst; /// /// assert_eq!(unsafe { conjure_zst::<()>() }, ()); @@ -1700,8 +1699,9 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { /// ``` /// /// [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited -#[unstable(feature = "mem_conjure_zst", issue = "95383")] -#[rustc_const_unstable(feature = "mem_conjure_zst", issue = "95383")] +#[stable(feature = "mem_conjure_zst", since = "CURRENT_RUSTC_VERSION")] +#[rustc_const_stable(feature = "mem_conjure_zst", since = "CURRENT_RUSTC_VERSION")] +#[rustc_allow_const_fn_unstable(const_type_name)] // type_name() called only at run time pub const unsafe fn conjure_zst() -> T { const_assert!( T::IS_ZST, diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index 2f026fb81ee1b..2d771f0890517 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -27,8 +27,8 @@ #![feature(restricted_std)] #![feature(rustc_attrs)] #![feature(extend_one)] -#![feature(mem_conjure_zst)] #![feature(f16)] +#![cfg_attr(bootstrap, feature(mem_conjure_zst))] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] diff --git a/tests/ui/consts/std/conjure_zst.rs b/tests/ui/consts/std/conjure_zst.rs index c04deae502b0f..be52a5c4014b2 100644 --- a/tests/ui/consts/std/conjure_zst.rs +++ b/tests/ui/consts/std/conjure_zst.rs @@ -1,5 +1,3 @@ -#![feature(mem_conjure_zst)] - use std::{convert::Infallible, mem}; const INVALID: Infallible = unsafe { mem::conjure_zst() }; diff --git a/tests/ui/consts/std/conjure_zst.stderr b/tests/ui/consts/std/conjure_zst.stderr index d4c9df07a393a..8e5bedf0a3c04 100644 --- a/tests/ui/consts/std/conjure_zst.stderr +++ b/tests/ui/consts/std/conjure_zst.stderr @@ -1,5 +1,5 @@ error[E0080]: evaluation panicked: aborted execution: attempted to instantiate uninhabited type `!` - --> $DIR/conjure_zst.rs:5:38 + --> $DIR/conjure_zst.rs:3:38 | LL | const INVALID: Infallible = unsafe { mem::conjure_zst() }; | ^^^^^^^^^^^^^^^^^^ evaluation of `INVALID` failed inside this call From 835975a12f82707097d8abdadb529c704a2847ac Mon Sep 17 00:00:00 2001 From: Ricky Date: Sun, 22 Feb 2026 22:32:31 +0800 Subject: [PATCH 0093/1309] alloc: make VecDeque partial equality symmetric with vec/slice/array --- .../alloc/src/collections/vec_deque/macros.rs | 20 ++++++++++++++++++ .../alloc/src/collections/vec_deque/mod.rs | 7 +++++++ library/alloctests/tests/vec_deque.rs | 21 +++++++++++++++++++ 3 files changed, 48 insertions(+) diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index 5c7913073fe87..4ef2a89e06018 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -17,3 +17,23 @@ macro_rules! __impl_slice_eq1 { } } } + +macro_rules! __impl_slice_eq2 { + ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { + #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] + impl PartialEq<$rhs> for $lhs + where + T: PartialEq, + $($constraints)* + { + fn eq(&self, other: &$rhs) -> bool { + if self.len() != other.len() { + return false; + } + let (oa, ob) = other.as_slices(); + let (sa, sb) = self[..].split_at(oa.len()); + sa == oa && sb == ob + } + } + } +} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 9095fc0d4abf4..ab81684ad7467 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3836,6 +3836,13 @@ __impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } +__impl_slice_eq2! { [] Vec, VecDeque, } +__impl_slice_eq2! { [] &[T], VecDeque, } +__impl_slice_eq2! { [] &mut [T], VecDeque, } +__impl_slice_eq2! { [const N: usize] [T; N], VecDeque, } +__impl_slice_eq2! { [const N: usize] &[T; N], VecDeque, } +__impl_slice_eq2! { [const N: usize] &mut [T; N], VecDeque, } + #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for VecDeque { fn partial_cmp(&self, other: &Self) -> Option { diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs index 15cc156d6988f..353d3e64b7b4f 100644 --- a/library/alloctests/tests/vec_deque.rs +++ b/library/alloctests/tests/vec_deque.rs @@ -631,6 +631,27 @@ fn test_partial_eq_array() { assert!(d == ['a', 'b']); } +#[test] +fn test_partial_eq_vecdeque_reverse() { + let mut d = VecDeque::with_capacity(4); + d.push_back(1); + d.push_back(2); + d.push_back(3); + d.pop_front(); + d.push_back(4); + + let v = vec![2, 3, 4]; + let a = [2, 3, 4]; + let mut b = [2, 3, 4]; + + assert!(v == d); + assert!(&v[..] == d); + assert!(&mut b[..] == d); + assert!(a == d); + assert!(&a == d); + assert!(&mut b == d); +} + #[test] fn test_hash() { let mut x = VecDeque::new(); From b50d79a556e0aa9cd3d738ca60da826e185fe6c7 Mon Sep 17 00:00:00 2001 From: Ricky Date: Mon, 23 Feb 2026 09:12:57 +0800 Subject: [PATCH 0094/1309] resolve too_generic_eval_ice stderr conflict --- tests/ui/consts/too_generic_eval_ice.current.stderr | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/ui/consts/too_generic_eval_ice.current.stderr b/tests/ui/consts/too_generic_eval_ice.current.stderr index 061945e344ede..dd5c3bd51bc52 100644 --- a/tests/ui/consts/too_generic_eval_ice.current.stderr +++ b/tests/ui/consts/too_generic_eval_ice.current.stderr @@ -30,15 +30,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error: aborting due to 4 previous errors From 8cdd010c4e19fb5153247fc9c26a9cb867d376d5 Mon Sep 17 00:00:00 2001 From: Ricky Date: Tue, 25 Aug 2026 10:20:10 +0800 Subject: [PATCH 0095/1309] update assert-ne-no-invalid-help-issue-146204.stderr for VecDeque PartialEq output --- .../assert-ne-no-invalid-help-issue-146204.stderr | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr index 64e40ebdd7bdf..726505f0bb0cd 100644 --- a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr +++ b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr @@ -6,15 +6,15 @@ LL | assert_ne!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:19:5 @@ -24,15 +24,15 @@ LL | assert_eq!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: + `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` + `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - `&[u8]` implements `PartialEq` - `&mut [T]` implements `PartialEq>` - and 13 others + and 18 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30 From 746c87243ae5a440395f0f2008247bdfafb2f62e Mon Sep 17 00:00:00 2001 From: joonas-001 Date: Tue, 25 Aug 2026 19:49:23 +0800 Subject: [PATCH 0096/1309] Add performance notes for the floating-point round method --- library/std/src/num/f32.rs | 5 +++++ library/std/src/num/f64.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index 385533748cb5d..09c2e6329831f 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -80,6 +80,11 @@ impl f32 { /// /// This function always returns the precise result. /// + /// On most hardware platforms, [`round_ties_even`](Self::round_ties_even) may execute faster + /// than `round`. If both rounding methods fit the use case, consider using `round_ties_even`. + /// Note that the two methods apply different rounding rules to values exactly halfway between + /// two integers. + /// /// # Examples /// /// ``` diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index 66482a8b654a5..7a813456723a3 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -80,6 +80,11 @@ impl f64 { /// /// This function always returns the precise result. /// + /// On most hardware platforms, [`round_ties_even`](Self::round_ties_even) may execute faster + /// than `round`. If both rounding methods fit the use case, consider using `round_ties_even`. + /// Note that the two methods apply different rounding rules to values exactly halfway between + /// two integers. + /// /// # Examples /// /// ``` From f6b8d36852eb3c16c122f0976028185e9bf5c503 Mon Sep 17 00:00:00 2001 From: AsthaMishra Date: Tue, 25 Aug 2026 12:21:33 +0000 Subject: [PATCH 0097/1309] formatting gated on style_edition 2027 --- src/expr.rs | 9 ++++++--- tests/source/issue-7055.rs | 2 ++ tests/target/issue-7055.rs | 2 ++ 3 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/expr.rs b/src/expr.rs index fb392b9965629..867d6fedd1b72 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -186,9 +186,12 @@ pub(crate) fn format_expr( // not the `ast::Block` node we're about to rewrite. To prevent dropping inner // attributes call `rewrite_block` directly. // See https://github.com/rust-lang/rustfmt/issues/6158 - - // Shrink the shape by `"const ".len()` before rewriting the block - let shape = shape.offset_left(6, expr.span)?; + let shape = if context.config.style_edition() >= StyleEdition::Edition2027 { + // Shrink the shape by `"const ".len()` before rewriting the block + shape.offset_left(6, expr.span)? + } else { + shape + }; rewrite_block(block, Some(&expr.attrs), opt_label, context, shape)? } _ => anon_const.rewrite_result(context, shape)?, diff --git a/tests/source/issue-7055.rs b/tests/source/issue-7055.rs index 8689bb37ecff9..7d0314772bf9f 100644 --- a/tests/source/issue-7055.rs +++ b/tests/source/issue-7055.rs @@ -1,3 +1,5 @@ +// rustfmt-style_edition: 2027 + struct S; impl S { diff --git a/tests/target/issue-7055.rs b/tests/target/issue-7055.rs index 22dc163cfd0ac..4096fbcb3eff8 100644 --- a/tests/target/issue-7055.rs +++ b/tests/target/issue-7055.rs @@ -1,3 +1,5 @@ +// rustfmt-style_edition: 2027 + struct S; impl S { From bd75704193506652a5c94b70efe8dea78a5371db Mon Sep 17 00:00:00 2001 From: AsthaMishra Date: Tue, 25 Aug 2026 14:24:53 +0000 Subject: [PATCH 0098/1309] Rename function `second_issue` to `removes_trailing_whitespace` for clarity --- tests/source/issue-7055.rs | 2 +- tests/target/issue-7055.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/source/issue-7055.rs b/tests/source/issue-7055.rs index 7d0314772bf9f..12d504aae2642 100644 --- a/tests/source/issue-7055.rs +++ b/tests/source/issue-7055.rs @@ -19,7 +19,7 @@ fn main() { .go(); } -fn second_issue() { +fn removes_trailing_whitespace() { const { S::new( "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", diff --git a/tests/target/issue-7055.rs b/tests/target/issue-7055.rs index 4096fbcb3eff8..5a995b6a1e0b2 100644 --- a/tests/target/issue-7055.rs +++ b/tests/target/issue-7055.rs @@ -17,7 +17,7 @@ fn main() { .go(); } -fn second_issue() { +fn removes_trailing_whitespace() { const { S::new("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") } From 9f3034d809679a738621fc87088e7279d8a9cc33 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 25 Aug 2026 14:16:52 -0400 Subject: [PATCH 0099/1309] Cleanup --- tests/run/import_linkage.rs | 6 ++---- tests/run/static_linkage.rs | 6 +++--- tests/run/weak_function_linkage.rs | 5 ----- 3 files changed, 5 insertions(+), 12 deletions(-) diff --git a/tests/run/import_linkage.rs b/tests/run/import_linkage.rs index c721309020ec8..bf83801d35581 100644 --- a/tests/run/import_linkage.rs +++ b/tests/run/import_linkage.rs @@ -4,8 +4,7 @@ // status: 0 // Checks the `#[linkage]` flavours an `extern` static can be imported with, against the symbols -// `tests/c/import_linkage.c` defines. `linkonce`, `linkonce_odr`, `weak`, `weak_odr` and `common` -// used to reach an `unimplemented!()` in `global_linkage_to_gcc`. +// `tests/c/import_linkage.c` defines. // // The value of such an import is the address of the symbol rather than its contents, which is why // the types are pointers: an `extern_weak` import of a symbol nobody defines reads as null instead @@ -36,8 +35,7 @@ extern "C" { static common_value: *const i32; #[linkage = "extern_weak"] static extern_weak_value: *const i32; - // An import is an undefined reference whatever the flavour says; this used to declare a - // private zeroed object of its own instead of reaching the definition in the C file. + // An import is an undefined reference whatever the flavour says. #[linkage = "internal"] static internal_value: *const i32; diff --git a/tests/run/static_linkage.rs b/tests/run/static_linkage.rs index adc43ab9fe396..1a9b672de361d 100644 --- a/tests/run/static_linkage.rs +++ b/tests/run/static_linkage.rs @@ -6,9 +6,9 @@ // Checks that `#[linkage]` on a static that this crate defines reaches the symbol, against // `tests/c/static_linkage.c`, which defines the overridable ones strongly. // -// `predefine_static` used to ignore its `linkage` argument outright, so every static came out as -// an ordinary global symbol: the overridable ones clashed with the C definitions at link time, and -// `internal` exported a symbol it should have kept private. +// If `predefine_static` were to ignore its `linkage` argument outright, every static would come out as +// an ordinary global symbol: the overridable ones would clash with the C definitions at link time, and +// `internal` would export a symbol it should have kept private. #![feature(linkage, no_core)] #![no_std] diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs index 82e1c3d2681e1..353b71a1e62a2 100644 --- a/tests/run/weak_function_linkage.rs +++ b/tests/run/weak_function_linkage.rs @@ -6,11 +6,6 @@ // Checks that the `#[linkage]` flavours another object file is allowed to override are emitted as // weak symbols, by linking against `tests/c/weak_function_linkage.c`, which defines the same // symbols strongly. -// -// `weak` used to be emitted as an ordinary global symbol, which the C definitions clash with, and -// `weak_odr`, `linkonce`, `linkonce_odr` and `common` reached an `unimplemented!()` in -// `linkage_to_gcc`. `available_externally` reached libgccjit, which rejects a body on an imported -// function. #![feature(linkage, no_core)] #![no_std] From 7a6930e3117c7ca4ba1e68589aecbb7d58e6f8df Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 25 Aug 2026 16:34:47 -0400 Subject: [PATCH 0100/1309] Update .gitignore --- .gitignore | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 1bbd3a9958073..13bd0d0ffde9b 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ llvm build_system/target config.toml build -rustlantis \ No newline at end of file +rustlantis +stuff/ From ec5988dae1e54dea6315df8b2231ae9e5fe56829 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 25 Aug 2026 20:58:48 -0400 Subject: [PATCH 0101/1309] Improve tests --- tests/c/static_linkage.c | 4 ++++ tests/c/weak_function_linkage.c | 7 +++++++ tests/run/import_linkage.rs | 4 +++- tests/run/static_linkage.rs | 6 ++++-- tests/run/weak_function_linkage.rs | 11 ++++++++--- 5 files changed, 26 insertions(+), 6 deletions(-) diff --git a/tests/c/static_linkage.c b/tests/c/static_linkage.c index 1a9b4ca5bd735..787e61f9cf105 100644 --- a/tests/c/static_linkage.c +++ b/tests/c/static_linkage.c @@ -14,6 +14,10 @@ int32_t linkonce_odr_static = 4; int32_t common_static = 5; int32_t internal_static = 200; +/* `available_externally` promises the real definition lives elsewhere: a backend may read this one + * or emit an equivalent copy of the Rust initializer, so the two have to hold the same value. */ +int32_t available_externally_static = 7; + /* Called from Rust, so that the reads also happen in a translation unit GCC compiled. */ int32_t c_read_all(void) { diff --git a/tests/c/weak_function_linkage.c b/tests/c/weak_function_linkage.c index 72ea483fd86e0..98325003549fd 100644 --- a/tests/c/weak_function_linkage.c +++ b/tests/c/weak_function_linkage.c @@ -31,6 +31,13 @@ int32_t common_function(void) return 5; } +/* `available_externally` promises the real definition lives elsewhere: a backend may call this one + * or emit an equivalent copy of the Rust body, so the two have to return the same value. */ +int32_t available_externally_function(void) +{ + return 7; +} + /* Called from Rust, so that the calls also go through a caller that GCC compiled: a cg_gcc caller * could inline the weak body it can see instead of calling the symbol. */ int32_t c_call_all(void) diff --git a/tests/run/import_linkage.rs b/tests/run/import_linkage.rs index bf83801d35581..bf5cb9e532799 100644 --- a/tests/run/import_linkage.rs +++ b/tests/run/import_linkage.rs @@ -35,7 +35,9 @@ extern "C" { static common_value: *const i32; #[linkage = "extern_weak"] static extern_weak_value: *const i32; - // An import is an undefined reference whatever the flavour says. + // An import is an undefined reference whatever the flavour says. Upstream bug: rustc lowers + // this one to an internal declaration, which LLVM's verifier rejects ("Global is external, but + // doesn't have external or weak linkage!") and which crashes cg_llvm at -O3. #[linkage = "internal"] static internal_value: *const i32; diff --git a/tests/run/static_linkage.rs b/tests/run/static_linkage.rs index 1a9b672de361d..7b911c064d797 100644 --- a/tests/run/static_linkage.rs +++ b/tests/run/static_linkage.rs @@ -34,9 +34,10 @@ pub static linkonce_static: i32 = 0; #[no_mangle] pub static linkonce_odr_static: i32 = 0; +// `common` is only valid on a mutable global: LLVM rejects a constant one. #[linkage = "common"] #[no_mangle] -pub static common_static: i32 = 0; +pub static mut common_static: i32 = 0; // Private to this crate, so the C definition of the same name is a different object. #[linkage = "internal"] @@ -48,7 +49,8 @@ pub static internal_static: i32 = 100; #[no_mangle] pub static only_weak_static: i32 = 6; -// Emitted as a private copy of a definition that lives elsewhere, so it must still be readable. +// The real definition is the one in the C file; a backend may read it or emit an equivalent copy of +// this initializer, so both spell the same value. #[linkage = "available_externally"] #[no_mangle] pub static available_externally_static: i32 = 7; diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs index 353b71a1e62a2..349d3a3a4850c 100644 --- a/tests/run/weak_function_linkage.rs +++ b/tests/run/weak_function_linkage.rs @@ -21,10 +21,12 @@ extern "C" fn weak_function() -> i32 { 0 } +// `_odr` promises every definition of the symbol is equivalent, which lets a backend call this body +// instead of the one in the C file. They spell the same value for that reason. #[linkage = "weak_odr"] #[no_mangle] extern "C" fn weak_odr_function() -> i32 { - 0 + 2 } #[linkage = "linkonce"] @@ -36,9 +38,11 @@ extern "C" fn linkonce_function() -> i32 { #[linkage = "linkonce_odr"] #[no_mangle] extern "C" fn linkonce_odr_function() -> i32 { - 0 + 4 } +// Upstream bug: LLVM rejects `common` on a function ("Functions may not have common linkage"), and +// with its verifier off inlines this body over the strong C one at -O3, so cg_llvm fails here. #[linkage = "common"] #[no_mangle] extern "C" fn common_function() -> i32 { @@ -52,7 +56,8 @@ extern "C" fn only_weak_function() -> i32 { 6 } -// Emitted as a private copy of a definition that lives elsewhere, so it must still be callable. +// The real definition is the one in the C file; a backend may call it or emit an equivalent copy of +// this body, so both spell the same value. #[linkage = "available_externally"] #[no_mangle] extern "C" fn available_externally_function() -> i32 { From f7548dd67188ff4f71059fa266b4319ddbade1e1 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 12 Aug 2026 21:25:35 -0400 Subject: [PATCH 0102/1309] Stabilize `funnel_shifts` (including `const`) `funnel_shl` and `funnel_shr` have been around for close to a year, the unchecked versions for a number of months. These are reasonably small and uncontroversial, and it can be tricky to get similar performance with a fallback; stabilize them here. Newly stable API: impl {u8, u16, u32, u64, u128, usize} { pub const fn funnel_shl(self, right: Self, shift: u32) -> Self; pub const fn funnel_shr(self, right: Self, shift: u32) -> Self; pub const unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self; pub const unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self; } The tracking issue also mentions a `wrapping_` version but it has not been implemented. Tracking issue: RUST-145686 --- library/core/src/intrinsics/mod.rs | 12 ++++----- library/core/src/lib.rs | 1 - library/core/src/num/uint_macros.rs | 26 +++++++------------ library/coretests/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - library/stdarch/crates/core_arch/src/lib.rs | 1 - .../miri/tests/fail/intrinsics/funnel_shl.rs | 2 +- .../miri/tests/fail/intrinsics/funnel_shr.rs | 2 +- .../miri/tests/pass/intrinsics/integer.rs | 2 +- .../codegen-llvm/force-intrinsic-fallback.rs | 2 +- tests/ui/std/overflow-check-ops.rs | 1 - 11 files changed, 20 insertions(+), 31 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 673454abaf04f..305bab8ec27e0 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2211,7 +2211,7 @@ pub const unsafe fn unchecked_mul(x: T, y: T) -> T; #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_left(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shl`, not the fallback impl. @@ -2233,7 +2233,7 @@ pub const fn rotate_left(x: T, shift: u32) -> #[rustc_intrinsic_const_stable_indirect] #[rustc_nounwind] #[rustc_intrinsic] -#[rustc_allow_const_fn_unstable(const_trait_impl, funnel_shifts)] +#[rustc_allow_const_fn_unstable(const_trait_impl)] #[miri::intrinsic_fallback_is_spec] pub const fn rotate_right(x: T, shift: u32) -> T { // Make sure to call the intrinsic for `funnel_shr`, not the fallback impl. @@ -2329,11 +2329,11 @@ pub const fn saturating_sub(a: T, b: T) -> T; /// /// Safe versions of this intrinsic are available on the integer primitives /// via the `funnel_shl` method. For example, [`u32::funnel_shl`]. +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shl( a: T, @@ -2357,11 +2357,11 @@ pub const unsafe fn unchecked_funnel_shl( /// /// Safer versions of this intrinsic are available on the integer primitives /// via the `funnel_shr` method. For example, [`u32::funnel_shr`] +#[rustc_intrinsic_const_stable_indirect] #[rustc_intrinsic] #[rustc_nounwind] -#[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] -#[unstable(feature = "funnel_shifts", issue = "145686")] #[track_caller] +#[rustc_allow_const_fn_unstable(const_trait_impl, core_intrinsics_fallbacks)] #[miri::intrinsic_fallback_is_spec] pub const unsafe fn unchecked_funnel_shr( a: T, diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index 4fbd3c6dc2142..b047657cf10de 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -131,7 +131,6 @@ #![feature(final_associated_functions)] #![feature(freeze_impls)] #![feature(fundamental)] -#![feature(funnel_shifts)] #![feature(impl_restriction)] #![feature(intra_doc_pointers)] #![feature(intrinsics)] diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs index a98ef99b9d7bb..2f9de03adced8 100644 --- a/library/core/src/num/uint_macros.rs +++ b/library/core/src/num/uint_macros.rs @@ -526,8 +526,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -547,10 +545,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_left`](Self::rotate_left) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_left(", stringify!($SelfT), "::BITS);")] @@ -559,8 +555,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -597,8 +593,6 @@ macro_rules! uint_impl { /// # Examples /// /// ``` - /// #![feature(funnel_shifts)] - /// #[doc = concat!("let a = ", $rot_op, "_", stringify!($SelfT), ";")] #[doc = concat!("let b = ", $fsh_op, "_", stringify!($SelfT), ";")] /// @@ -618,10 +612,8 @@ macro_rules! uint_impl { /// rotating by an unbounded amount like [`rotate_right`](Self::rotate_right) does: /// /// ```should_panic - /// #![feature(funnel_shifts)] /// # #![feature(cfg_overflow_checks)] /// # #[cfg(overflow_checks)] { - /// #[doc = concat!("let a = ", stringify!($SelfT), "::MAX;")] /// // Okay #[doc = concat!("let _ = a.rotate_right(", stringify!($SelfT), "::BITS);")] @@ -630,8 +622,8 @@ macro_rules! uint_impl { /// # } /// # #[cfg(not(overflow_checks))] panic!("fulfill should_panic"); /// ``` - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[rustc_inherit_overflow_checks] @@ -654,8 +646,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shl`](Self::funnel_shl) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] @@ -680,8 +673,9 @@ macro_rules! uint_impl { #[doc = concat!("`", stringify!($SelfT) , "::BITS`,")] /// i.e. when [`funnel_shr`](Self::funnel_shr) would panic. /// - #[rustc_const_unstable(feature = "funnel_shifts", issue = "145686")] - #[unstable(feature = "funnel_shifts", issue = "145686")] + #[rustc_const_stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "funnel_shifts", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_trait_impl)] #[must_use = "this returns the result of the operation, without modifying the original"] #[inline(always)] #[track_caller] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index c993c947929cd..116e1eb48d260 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -63,7 +63,6 @@ #![feature(fmt_internals)] #![feature(formatting_options)] #![feature(freeze)] -#![feature(funnel_shifts)] #![feature(future_join)] #![feature(generic_assert_internals)] #![feature(hasher_prefixfree_extras)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 92eccc27ee05d..921a1ff49511c 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -349,7 +349,6 @@ #![feature(fmt_internals)] #![feature(fn_static)] #![feature(formatting_options)] -#![feature(funnel_shifts)] #![feature(generic_atomic)] #![feature(hash_map_internals)] #![feature(hash_map_macro)] diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 57eca221e1aba..2cb4c43d760e4 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -33,7 +33,6 @@ x86_amx_intrinsics, f16, aarch64_unstable_target_feature, - funnel_shifts, avx10_target_feature, const_trait_impl, const_cmp, diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs index 40b61f65ebe88..b64f4551fd605 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shl.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs index 9582265639716..922144d6d6042 100644 --- a/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs +++ b/src/tools/miri/tests/fail/intrinsics/funnel_shr.rs @@ -1,4 +1,4 @@ -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] fn main() { unsafe { diff --git a/src/tools/miri/tests/pass/intrinsics/integer.rs b/src/tools/miri/tests/pass/intrinsics/integer.rs index 555a85147ee5f..2260068704adf 100644 --- a/src/tools/miri/tests/pass/intrinsics/integer.rs +++ b/src/tools/miri/tests/pass/intrinsics/integer.rs @@ -1,5 +1,5 @@ //@run-native -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] use std::intrinsics::*; fn main() { diff --git a/tests/codegen-llvm/force-intrinsic-fallback.rs b/tests/codegen-llvm/force-intrinsic-fallback.rs index 1fb80b4e83f12..3a934b27f828e 100644 --- a/tests/codegen-llvm/force-intrinsic-fallback.rs +++ b/tests/codegen-llvm/force-intrinsic-fallback.rs @@ -2,7 +2,7 @@ // //@ revisions: NORMAL FALLBACK //@ [FALLBACK] compile-flags: -Zforce-intrinsic-fallback -#![feature(core_intrinsics, funnel_shifts)] +#![feature(core_intrinsics)] // Check the effect of `-Zforce-intrinsic-fallback`. // diff --git a/tests/ui/std/overflow-check-ops.rs b/tests/ui/std/overflow-check-ops.rs index 458c1b121664e..57db92610b20a 100644 --- a/tests/ui/std/overflow-check-ops.rs +++ b/tests/ui/std/overflow-check-ops.rs @@ -7,7 +7,6 @@ //@[WRAP] compile-flags: -C overflow-checks=false #![feature(cfg_overflow_checks)] -#![feature(funnel_shifts)] use std::hint::black_box as bb; use std::{assert_matches, fmt, panic}; From 64092c925ecb3787967f939caae0bc50e98dcce1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 26 Aug 2026 11:57:13 -0400 Subject: [PATCH 0103/1309] Add support for the common attribute --- Cargo.lock | 8 ++++---- Cargo.toml | 2 +- src/base.rs | 21 ++++++++++++++++++--- src/consts.rs | 21 +++++++++++++++++++-- src/mono_item.rs | 4 ++-- tests/c/weak_function_linkage.c | 7 ------- tests/run/weak_function_linkage.rs | 12 ++---------- 7 files changed, 46 insertions(+), 29 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 44aeab75c29e1..6c3dc4b82f926 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "6.0.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5bb358d2563af5e32af92620915e6b05839ae60645343473735619441f45eb04" +checksum = "6d85b5754389edaad832ba320709a25086b3081a8c6c0fab2322965e5fb512b3" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "3.1.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2389fb01673e9cc63684d996a58079edccc5de89008274f3be59f1b16ac1f017" +checksum = "e081669728b490723537f9def7eb674b7c9acd8de0b92ad4f4abf5f5cc75ea4b" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index 1aff8ed115e1e..abfa47a05bd63 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.37.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "6.0.0", features = ["dlopen"] } +gccjit = { version = "6.1.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/base.rs b/src/base.rs index 46f864bed98e8..3346ff85074d0 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,6 +1,8 @@ use std::sync::Arc; use std::time::Instant; +#[cfg(feature = "master")] +use gccjit::VarAttribute; use gccjit::{CType, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; @@ -42,15 +44,14 @@ pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibil /// The kind of a global *definition* with an explicit `#[linkage]`. /// /// The flavours that another object file is allowed to override also need -/// `linkage_needs_weak_attribute` from the caller: `GlobalKind` alone cannot express weakness. +/// `global_linkage_attribute` from the caller: `GlobalKind` alone cannot express weakness. pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { match linkage { Linkage::External => GlobalKind::Exported, // libgccjit cannot emit a definition that the linker discards in favour of the one in // another object file, so emit a private copy of it instead. Linkage::AvailableExternally | Linkage::Internal => GlobalKind::Internal, - // libgccjit exposes neither comdat nor common storage, so `weak` stands in for every - // overridable flavour. + // libgccjit exposes no comdat, so `weak` stands in for the linkonce flavours. Linkage::LinkOnceAny | Linkage::LinkOnceODR | Linkage::WeakAny @@ -60,6 +61,16 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { } } +/// The attribute a global *definition* needs on top of its [`GlobalKind`] to get this linkage. +#[cfg(feature = "master")] +pub fn global_linkage_attribute<'gcc>(linkage: Linkage) -> Option> { + match linkage { + Linkage::Common => Some(VarAttribute::Common), + _ if linkage_needs_weak_attribute(linkage) => Some(VarAttribute::Weak), + _ => None, + } +} + /// The type of a function *definition* with an explicit `#[linkage]`. /// /// The flavours that another object file is allowed to override also need @@ -82,6 +93,10 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { /// Whether a definition with this linkage must carry the `weak` attribute, so that a strong /// definition in another object file wins over it instead of clashing with it. +/// +/// `common` is in here for functions only: GCC honours that attribute on a variable, but drops it +/// on a function, so a common function falls back to weak. Globals go through +/// `global_linkage_attribute` instead. #[cfg(feature = "master")] pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { match linkage { diff --git a/src/consts.rs b/src/consts.rs index 956b79b0cacd5..06e945a6a4576 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -13,7 +13,8 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - self, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, read_target_uint, + self, Allocation, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, + read_target_uint, }; use rustc_middle::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; @@ -112,7 +113,12 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); - global.global_set_initializer_rvalue(value); + // A common symbol is storage the linker allocates and zero-fills, so giving the definition + // an initializer — even an all-zero one — takes it back out of `.comm`. A non-zero one is + // kept: the symbol is then an ordinary definition, which is what GCC does with it too. + if attrs.linkage != Some(Linkage::Common) || !is_zero_initializer(alloc) { + global.global_set_initializer_rvalue(value); + } // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -452,6 +458,17 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( cx.const_struct(&llvals, true) } +/// Whether this allocation is all zeroes, and so needs no initializer to be spelled out. +fn is_zero_initializer(alloc: &Allocation) -> bool { + alloc.provenance().ptrs().is_empty() + // This `inspect` is okay: it is within the bounds of the allocation, there is no provenance + // to misread, and it does not affect interpreter execution. + && alloc + .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.size().bytes_usize()) + .iter() + .all(|&byte| byte == 0) +} + fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, diff --git a/src/mono_item.rs b/src/mono_item.rs index cb133d9c23300..f0b8c8a9dcc4c 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -66,8 +66,8 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { }; global.add_attribute(VarAttribute::Visibility(visibility)); } - if base::linkage_needs_weak_attribute(linkage) { - global.add_attribute(VarAttribute::Weak); + if let Some(attribute) = base::global_linkage_attribute(linkage) { + global.add_attribute(attribute); } } diff --git a/tests/c/weak_function_linkage.c b/tests/c/weak_function_linkage.c index 98325003549fd..1d64f5365d1af 100644 --- a/tests/c/weak_function_linkage.c +++ b/tests/c/weak_function_linkage.c @@ -26,11 +26,6 @@ int32_t linkonce_odr_function(void) return 4; } -int32_t common_function(void) -{ - return 5; -} - /* `available_externally` promises the real definition lives elsewhere: a backend may call this one * or emit an equivalent copy of the Rust body, so the two have to return the same value. */ int32_t available_externally_function(void) @@ -50,7 +45,5 @@ int32_t c_call_all(void) return 13; if (linkonce_odr_function() != 4) return 14; - if (common_function() != 5) - return 15; return 0; } diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs index 349d3a3a4850c..c6c978c61791a 100644 --- a/tests/run/weak_function_linkage.rs +++ b/tests/run/weak_function_linkage.rs @@ -41,13 +41,8 @@ extern "C" fn linkonce_odr_function() -> i32 { 4 } -// Upstream bug: LLVM rejects `common` on a function ("Functions may not have common linkage"), and -// with its verifier off inlines this body over the strong C one at -O3, so cg_llvm fails here. -#[linkage = "common"] -#[no_mangle] -extern "C" fn common_function() -> i32 { - 0 -} +// `#[linkage = "common"]` is absent on purpose: a common symbol is `SHN_COMMON`, which the object +// format only allows for objects, so no backend can give a function that linkage. // Not overridden by the C side: the definition here is the one that runs. #[linkage = "weak"] @@ -97,9 +92,6 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { if linkonce_odr_function() != 4 { return 4; } - if common_function() != 5 { - return 5; - } if only_weak_function() != 6 { return 6; } From 996806ba1e078a8524b99cac3e824f6acf6f2e4b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 26 Aug 2026 13:47:18 -0400 Subject: [PATCH 0104/1309] Update comments --- src/attributes.rs | 5 ++--- src/mono_item.rs | 4 ++-- tests/c/weak_function_linkage.c | 5 +++++ tests/run/weak_function_linkage.rs | 9 +++++---- 4 files changed, 14 insertions(+), 9 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index e4d44d790d3e3..9ff6c19f6f13f 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -118,9 +118,8 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } else { codegen_fn_attrs.inline }; - // GCC warns that `inline` and `weak` conflict, and cg_gcc turns libgccjit warnings into - // errors. The linkage is what has to survive: rustc lints `#[inline]` as ignored on a - // function with an explicit `#[linkage]` anyway. `inline(never)` does not conflict. + // GCC drops `weak` from a function that is also `inline`, leaving the symbol strong, and + // the linkage is what has to survive. `inline(never)` does not conflict. let inline = match inline { InlineAttr::Always | InlineAttr::Hint | InlineAttr::Force { .. } if codegen_fn_attrs.linkage.is_some_and(base::linkage_needs_weak_attribute) => diff --git a/src/mono_item.rs b/src/mono_item.rs index f0b8c8a9dcc4c..57411c854771c 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -52,8 +52,8 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.define_global(global_name, gcc_type, global_kind, is_tls, attrs.link_section); #[cfg(feature = "master")] { - // GCC warns that it ignores `visibility` on an internal global, and cg_gcc turns - // libgccjit warnings into errors. + // Visibility is meaningless on an internal global: GCC ignores the attribute and + // warns about it. if !matches!(global_kind, GlobalKind::Internal) { // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden diff --git a/tests/c/weak_function_linkage.c b/tests/c/weak_function_linkage.c index 1d64f5365d1af..25dcdedbcd950 100644 --- a/tests/c/weak_function_linkage.c +++ b/tests/c/weak_function_linkage.c @@ -26,6 +26,11 @@ int32_t linkonce_odr_function(void) return 4; } +int32_t weak_inline_function(void) +{ + return 8; +} + /* `available_externally` promises the real definition lives elsewhere: a backend may call this one * or emit an equivalent copy of the Rust body, so the two have to return the same value. */ int32_t available_externally_function(void) diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs index c6c978c61791a..677f01353401a 100644 --- a/tests/run/weak_function_linkage.rs +++ b/tests/run/weak_function_linkage.rs @@ -59,14 +59,15 @@ extern "C" fn available_externally_function() -> i32 { 7 } -// GCC warns that `inline` and `weak` conflict, and cg_gcc turns libgccjit warnings into errors, so -// this used to fail to compile at all. The inline hint is what gives way: rustc lints it as ignored -// on a function with an explicit `#[linkage]` anyway, hence the `allow`. +// GCC drops `weak` from a function that is also `inline`: a backend that keeps the hint emits this +// as an ordinary global symbol and clashes with the C definition. rustc lints the hint as ignored +// on a function with an explicit `#[linkage]`, hence the `allow`. #[linkage = "weak"] #[inline] +#[no_mangle] #[allow(unused_attributes)] extern "C" fn weak_inline_function() -> i32 { - 8 + 0 } extern "C" { From 3de358db9e02fc7409f380dc14bee3bb431b26b8 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 26 Aug 2026 13:47:25 -0400 Subject: [PATCH 0105/1309] Update libgccjit version --- libgccjit.version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libgccjit.version b/libgccjit.version index 47539d889df51..62417a80f827e 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -201ca90ac810d1c6509c252cc9c87d3ace0661d7 +badf78d09d16e66f4ca07971c51aa6a227558d4f From 97f3b66d636d2788b3cdb929a266693de3a455a6 Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 28 Aug 2026 09:01:12 +0800 Subject: [PATCH 0106/1309] Add regression test for parenthesized raw borrow suggestions --- ...a-references-parenthesized-issue-161693.rs | 22 +++++++++++++ ...ferences-parenthesized-issue-161693.stderr | 31 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs create mode 100644 tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr diff --git a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs new file mode 100644 index 0000000000000..d395c0929c34d --- /dev/null +++ b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs @@ -0,0 +1,22 @@ +//@ check-pass + +// Parenthesized reference-to-pointer casts should produce syntactically valid suggestions. + +#![feature(const_volatile)] +#![warn(raw_borrows_via_references)] + +const READ: () = unsafe { + let x = 42i32; + let y = (&x as *const i32).read_volatile(); + //~^ WARN creating an intermediate reference implies aliasing requirements + assert!(x == y); +}; + +const WRITE: () = unsafe { + let mut x = 42i32; + (&mut x as *mut i32).write_volatile(13); + //~^ WARN creating an intermediate reference implies aliasing requirements + assert!(x == 13); +}; + +fn main() {} diff --git a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr new file mode 100644 index 0000000000000..75081f5991215 --- /dev/null +++ b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr @@ -0,0 +1,31 @@ +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/raw-borrows-via-references-parenthesized-issue-161693.rs:10:13 + | +LL | let y = (&x as *const i32).read_volatile(); + | ^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/raw-borrows-via-references-parenthesized-issue-161693.rs:6:9 + | +LL | #![warn(raw_borrows_via_references)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - let y = (&x as *const i32).read_volatile(); +LL + let y = &raw const x).read_volatile(); + | + +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/raw-borrows-via-references-parenthesized-issue-161693.rs:17:5 + | +LL | (&mut x as *mut i32).write_volatile(13); + | ^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw mut` for a safer and more explicit raw pointer + | +LL - (&mut x as *mut i32).write_volatile(13); +LL + &raw mut x).write_volatile(13); + | + +warning: 2 warnings emitted + From 78fc847e5d82406f8eb7f8578e6a5b369a54cc59 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 28 Aug 2026 01:04:26 -0400 Subject: [PATCH 0107/1309] doc: add LLM policy Link to the same policy followed by rust-lang/rust. --- Contributing.md | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Contributing.md b/Contributing.md index 7b298052ab2a0..99558079984b4 100644 --- a/Contributing.md +++ b/Contributing.md @@ -9,6 +9,15 @@ or file new issues specifically to get help. All contributors are expected to follow our [Code of Conduct](CODE_OF_CONDUCT.md). + +## LLM policy + +rustfmt follows the same [LLM usage policy] as `rust-lang/rust`. Please read it before using LLM +assistance when participating in `rust-lang/rustfmt`. + +[LLM usage policy]: https://forge.rust-lang.org/policies/llm-usage.html + + ## Test and file issues It would be really useful to have people use rustfmt on their projects and file From a5f779afe53798e203085e94f7653abc1241a611 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Fri, 28 Aug 2026 01:26:54 -0400 Subject: [PATCH 0108/1309] chore: add LLM usage policy note to PR template This also follows what rust-lang/rust is doing. --- .github/pull_request_template.md | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/pull_request_template.md diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md new file mode 100644 index 0000000000000..ed9dbb7395d9a --- /dev/null +++ b/.github/pull_request_template.md @@ -0,0 +1,11 @@ +- [ ] I did not use an LLM to create a change in this PR. +- [ ] I used an LLM to create a change in this PR, and I have explained below how it was used. + + From f136feae16ba4c2ca7cf7a4dfd8cd48cbeddc219 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Sat, 29 Aug 2026 15:34:49 +0800 Subject: [PATCH 0109/1309] Merge commit '7af33204708cefcbd44eea5253f7d9a450f8d290' into rustfmt-subtree-update --- .github/FUNDING.yml | 2 +- .github/workflows/check_diff.yml | 8 + .github/workflows/integration.yml | 8 - .github/workflows/linux.yml | 45 ----- .github/workflows/mac.yml | 41 ---- .github/workflows/rustdoc_check.yml | 4 +- .github/workflows/test.yml | 102 ++++++++++ .github/workflows/upload-assets.yml | 7 +- .github/workflows/windows.yml | 68 ------- Cargo.lock | 114 +++++++++--- Cargo.toml | 6 +- Configurations.md | 7 +- Contributing.md | 5 + Makefile.toml | 71 ------- README.md | 2 +- Subtree sync procedure.md | 3 +- check_diff/Cargo.lock | 24 +-- check_diff/Cargo.toml | 2 +- check_diff/src/lib.rs | 176 ++++++++++-------- check_diff/src/main.rs | 10 +- check_diff/tests/check_diff.rs | 12 +- rust-toolchain | 2 +- src/bin/main.rs | 50 ++++- src/cargo-fmt/main.rs | 9 +- src/cargo-fmt/test/targets.rs | 33 +++- src/chains.rs | 20 +- src/closures.rs | 11 +- src/config/options.rs | 10 +- src/expr.rs | 122 ++++++++++-- src/format_report_formatter.rs | 50 +++-- src/formatting.rs | 74 ++++---- src/items.rs | 52 ++++-- src/lib.rs | 2 +- src/missed_spans.rs | 6 +- src/parse/macros/mod.rs | 4 +- src/patterns.rs | 11 +- src/test/mod.rs | 55 +++++- src/test/parser.rs | 11 +- src/types.rs | 2 +- tests/cargo-fmt/source/issues_6517/Cargo.toml | 2 + .../source/issues_6517/inner_bin/Cargo.toml | 6 + .../source/issues_6517/inner_bin/src/main.rs | 3 + .../source/issues_6517/inner_lib/Cargo.toml | 6 + .../source/issues_6517/inner_lib/src/lib.rs | 14 ++ tests/rustfmt/main.rs | 105 ++++++++++- .../configs/fn_params_layout/vertical.rs | 22 +++ .../fn_params_layout/vertical_style_2027.rs | 39 ++++ tests/source/generic_static.rs | 5 + .../{ => imports}/imports_granularity_one.rs | 0 tests/source/issue-5023.rs | 10 + tests/source/issue-6795.rs | 40 ++++ tests/source/issue-6985.rs | 21 +++ tests/source/issue-7011.rs | 7 + tests/source/issue-7054.rs | 153 +++++++++++++++ tests/source/issue_4037.rs | 24 +++ tests/source/issue_5920_style_edition_2024.rs | 25 +++ tests/source/issue_5920_style_edition_2027.rs | 25 +++ tests/source/issue_5982_style_edition_2024.rs | 39 ++++ tests/source/issue_5982_style_edition_2027.rs | 39 ++++ tests/source/issue_6209.rs | 33 ++++ tests/source/issue_6801.rs | 52 ++++++ tests/source/issue_7003_style_edition_2024.rs | 14 ++ tests/source/issue_7003_style_edition_2027.rs | 14 ++ tests/source/issue_7036.rs | 157 ++++++++++++++++ tests/source/macros.rs | 7 + tests/source/string_lit_unicode_ws.rs | 2 + .../configs/fn_params_layout/vertical.rs | 30 +++ .../fn_params_layout/vertical_style_2027.rs | 73 ++++++++ tests/target/generic_static.rs | 12 ++ .../{ => imports}/imports_granularity_one.rs | 0 tests/target/issue-5023.rs | 16 +- tests/target/issue-6795.rs | 45 +++++ tests/target/issue-6985.rs | 20 ++ tests/target/issue-7011.rs | 7 + tests/target/issue-7054.rs | 168 +++++++++++++++++ tests/target/issue_4037.rs | 17 ++ tests/target/issue_5920_style_edition_2024.rs | 25 +++ tests/target/issue_5920_style_edition_2027.rs | 25 +++ tests/target/issue_5973.rs | 19 ++ tests/target/issue_5982_style_edition_2024.rs | 39 ++++ tests/target/issue_5982_style_edition_2027.rs | 39 ++++ tests/target/issue_6209.rs | 44 +++++ tests/target/issue_6801.rs | 57 ++++++ tests/target/issue_6984_style_edition_2024.rs | 13 ++ tests/target/issue_6984_style_edition_2027.rs | 13 ++ tests/target/issue_7003_style_edition_2024.rs | 14 ++ tests/target/issue_7003_style_edition_2027.rs | 15 ++ tests/target/issue_7036.rs | 141 ++++++++++++++ tests/target/issue_7057.rs | 3 + tests/target/issue_7062.rs | 1 + tests/target/macros.rs | 7 + tests/target/splat.rs | 111 +++++++++++ tests/target/string_lit_unicode_ws.rs | 2 + tests/target/trailing_comments/hard_tabs.rs | 8 +- tests/target/trailing_comments/soft_tabs.rs | 8 +- tests/target/unicode.rs | 3 +- tests/warning/snapshots/deprecated_skip.snap | 10 + .../warning/snapshots/invalid_attribute.snap | 10 + tests/warning/snapshots/issue_3950.snap | 12 ++ tests/warning/snapshots/issue_4968.snap | 12 ++ tests/warning/snapshots/issue_6442.snap | 12 ++ tests/warning/snapshots/issue_6632.snap | 12 ++ tests/warning/snapshots/issue_6826.snap | 18 ++ tests/warning/snapshots/issue_6850.snap | 12 ++ tests/warning/snapshots/line_overflow.snap | 11 ++ .../warning/snapshots/line_overflow_tabs.snap | 12 ++ ...ine_overflow_with_trailing_whitespace.snap | 20 ++ tests/warning/snapshots/lost_comment.snap | 11 ++ tests/warning/snapshots/multiple_errors.snap | 38 ++++ .../snapshots/trailing_whitespace.snap | 12 ++ .../trailing_whitespace_overflow.snap | 12 ++ .../unicode_trailing_whitespace.snap | 12 ++ tests/warning/source/deprecated_skip.rs | 2 + tests/warning/source/invalid_attribute.rs | 2 + tests/warning/source/issue_3950.rs | 5 + tests/warning/source/issue_4968.rs | 10 + tests/warning/source/issue_6442.rs | 5 + tests/warning/source/issue_6632.rs | 14 ++ tests/warning/source/issue_6826.rs | 5 + tests/warning/source/issue_6850.rs | 4 + tests/warning/source/line_overflow.rs | 1 + tests/warning/source/line_overflow_tabs.rs | 4 + .../line_overflow_with_trailing_whitespace.rs | 3 + tests/warning/source/lost_comment.rs | 1 + tests/warning/source/multiple_errors.rs | 12 ++ tests/warning/source/trailing_whitespace.rs | 2 + .../source/trailing_whitespace_overflow.rs | 3 + .../source/unicode_trailing_whitespace.rs | 2 + 128 files changed, 2854 insertions(+), 527 deletions(-) delete mode 100644 .github/workflows/linux.yml delete mode 100644 .github/workflows/mac.yml create mode 100644 .github/workflows/test.yml delete mode 100644 .github/workflows/windows.yml delete mode 100644 Makefile.toml create mode 100644 tests/cargo-fmt/source/issues_6517/Cargo.toml create mode 100644 tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml create mode 100644 tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs create mode 100644 tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml create mode 100644 tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs create mode 100644 tests/source/configs/fn_params_layout/vertical_style_2027.rs create mode 100644 tests/source/generic_static.rs rename tests/source/{ => imports}/imports_granularity_one.rs (100%) create mode 100644 tests/source/issue-6795.rs create mode 100644 tests/source/issue-6985.rs create mode 100644 tests/source/issue-7011.rs create mode 100644 tests/source/issue-7054.rs create mode 100644 tests/source/issue_4037.rs create mode 100644 tests/source/issue_5920_style_edition_2024.rs create mode 100644 tests/source/issue_5920_style_edition_2027.rs create mode 100644 tests/source/issue_5982_style_edition_2024.rs create mode 100644 tests/source/issue_5982_style_edition_2027.rs create mode 100644 tests/source/issue_6209.rs create mode 100644 tests/source/issue_6801.rs create mode 100644 tests/source/issue_7003_style_edition_2024.rs create mode 100644 tests/source/issue_7003_style_edition_2027.rs create mode 100644 tests/source/issue_7036.rs create mode 100644 tests/target/configs/fn_params_layout/vertical_style_2027.rs create mode 100644 tests/target/generic_static.rs rename tests/target/{ => imports}/imports_granularity_one.rs (100%) create mode 100644 tests/target/issue-6795.rs create mode 100644 tests/target/issue-6985.rs create mode 100644 tests/target/issue-7011.rs create mode 100644 tests/target/issue-7054.rs create mode 100644 tests/target/issue_4037.rs create mode 100644 tests/target/issue_5920_style_edition_2024.rs create mode 100644 tests/target/issue_5920_style_edition_2027.rs create mode 100644 tests/target/issue_5973.rs create mode 100644 tests/target/issue_5982_style_edition_2024.rs create mode 100644 tests/target/issue_5982_style_edition_2027.rs create mode 100644 tests/target/issue_6209.rs create mode 100644 tests/target/issue_6801.rs create mode 100644 tests/target/issue_6984_style_edition_2024.rs create mode 100644 tests/target/issue_6984_style_edition_2027.rs create mode 100644 tests/target/issue_7003_style_edition_2024.rs create mode 100644 tests/target/issue_7003_style_edition_2027.rs create mode 100644 tests/target/issue_7036.rs create mode 100644 tests/target/issue_7057.rs create mode 100644 tests/target/issue_7062.rs create mode 100644 tests/target/splat.rs create mode 100644 tests/warning/snapshots/deprecated_skip.snap create mode 100644 tests/warning/snapshots/invalid_attribute.snap create mode 100644 tests/warning/snapshots/issue_3950.snap create mode 100644 tests/warning/snapshots/issue_4968.snap create mode 100644 tests/warning/snapshots/issue_6442.snap create mode 100644 tests/warning/snapshots/issue_6632.snap create mode 100644 tests/warning/snapshots/issue_6826.snap create mode 100644 tests/warning/snapshots/issue_6850.snap create mode 100644 tests/warning/snapshots/line_overflow.snap create mode 100644 tests/warning/snapshots/line_overflow_tabs.snap create mode 100644 tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap create mode 100644 tests/warning/snapshots/lost_comment.snap create mode 100644 tests/warning/snapshots/multiple_errors.snap create mode 100644 tests/warning/snapshots/trailing_whitespace.snap create mode 100644 tests/warning/snapshots/trailing_whitespace_overflow.snap create mode 100644 tests/warning/snapshots/unicode_trailing_whitespace.snap create mode 100644 tests/warning/source/deprecated_skip.rs create mode 100644 tests/warning/source/invalid_attribute.rs create mode 100644 tests/warning/source/issue_3950.rs create mode 100644 tests/warning/source/issue_4968.rs create mode 100644 tests/warning/source/issue_6442.rs create mode 100644 tests/warning/source/issue_6632.rs create mode 100644 tests/warning/source/issue_6826.rs create mode 100644 tests/warning/source/issue_6850.rs create mode 100644 tests/warning/source/line_overflow.rs create mode 100644 tests/warning/source/line_overflow_tabs.rs create mode 100644 tests/warning/source/line_overflow_with_trailing_whitespace.rs create mode 100644 tests/warning/source/lost_comment.rs create mode 100644 tests/warning/source/multiple_errors.rs create mode 100644 tests/warning/source/trailing_whitespace.rs create mode 100644 tests/warning/source/trailing_whitespace_overflow.rs create mode 100644 tests/warning/source/unicode_trailing_whitespace.rs diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml index 1d270e78949f8..dbe0dc229a1a3 100644 --- a/.github/FUNDING.yml +++ b/.github/FUNDING.yml @@ -1,2 +1,2 @@ github: rustfoundation -custom: ["rust-lang.org/funding"] +custom: ["https://rust-lang.org/funding"] diff --git a/.github/workflows/check_diff.yml b/.github/workflows/check_diff.yml index 41b138acb63fc..38aac68b94c72 100644 --- a/.github/workflows/check_diff.yml +++ b/.github/workflows/check_diff.yml @@ -32,6 +32,14 @@ on: rustfmt_configs: description: 'Optional comma separated list of rustfmt config options to pass when running the feature branch' required: false + release_channel: + description: 'Configure which release channel to use when compiling rustfmt' + default: stable + type: choice + options: + - stable + - beta + - nightly permissions: contents: read diff --git a/.github/workflows/integration.yml b/.github/workflows/integration.yml index 9ef809bc5ccf7..d248fc41dab5a 100644 --- a/.github/workflows/integration.yml +++ b/.github/workflows/integration.yml @@ -1,8 +1,5 @@ name: integration on: - push: - branches: - - main pull_request: permissions: @@ -13,11 +10,6 @@ jobs: runs-on: ubuntu-latest name: ${{ matrix.integration }} strategy: - # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits - # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. - # In order to prevent overusing too much of that 60 limit, we throttle the - # number of rustfmt jobs that will run concurrently. - max-parallel: 4 fail-fast: false matrix: integration: [ diff --git a/.github/workflows/linux.yml b/.github/workflows/linux.yml deleted file mode 100644 index 77ab026f1d4b8..0000000000000 --- a/.github/workflows/linux.yml +++ /dev/null @@ -1,45 +0,0 @@ -name: linux -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -jobs: - test: - runs-on: ubuntu-latest - name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) - env: - CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} - strategy: - # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits - # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. - # In order to prevent overusing too much of that 60 limit, we throttle the - # number of rustfmt jobs that will run concurrently. - max-parallel: 1 - fail-fast: false - matrix: - target: [ - x86_64-unknown-linux-gnu, - ] - cfg_release_channel: [nightly, stable] - - steps: - - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - # Run build - - name: install rustup - run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh - sh rustup-init.sh -y --default-toolchain none - rustup target add ${{ matrix.target }} - - - name: Build and Test - env: - RUSTFLAGS: -D warnings - CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true - run: cargo run --manifest-path ci/Cargo.toml build-and-test diff --git a/.github/workflows/mac.yml b/.github/workflows/mac.yml deleted file mode 100644 index 28c218b729b22..0000000000000 --- a/.github/workflows/mac.yml +++ /dev/null @@ -1,41 +0,0 @@ -name: mac -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -jobs: - test: - # https://help.github.com/en/actions/automating-your-workflow-with-github-actions/virtual-environments-for-github-hosted-runners#supported-runners-and-hardware-resources - runs-on: macos-latest - name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) - env: - CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} - strategy: - fail-fast: false - matrix: - target: [ - x86_64-apple-darwin, - ] - cfg_release_channel: [nightly, stable] - - steps: - - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - # Run build - - name: install rustup - run: | - curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh - sh rustup-init.sh -y --default-toolchain none - rustup target add ${{ matrix.target }} - - - name: Build and Test - env: - RUSTFLAGS: -D warnings - CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true - run: cargo run --manifest-path ci/Cargo.toml build-and-test diff --git a/.github/workflows/rustdoc_check.yml b/.github/workflows/rustdoc_check.yml index 430185e3105b5..4a22d7801ab05 100644 --- a/.github/workflows/rustdoc_check.yml +++ b/.github/workflows/rustdoc_check.yml @@ -1,8 +1,6 @@ name: rustdoc check on: - push: - branches: - - main + merge_group: pull_request: permissions: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000000000..7202f03f5511c --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,102 @@ +name: test +on: + merge_group: + pull_request: + +permissions: + contents: read + +jobs: + test: + runs-on: ${{ matrix.os }} + name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) + env: + CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} + strategy: + fail-fast: false + matrix: + build: [linux, macos, win32-gnu, win32-msvc, win64-gnu, win64-msvc] + cfg_release_channel: [nightly, stable] + include: + - build: linux + os: ubuntu-latest + target: x86_64-unknown-linux-gnu + - build: macos + os: macos-latest + target: x86_64-apple-darwin + - build: win32-gnu + os: windows-latest + target: i686-pc-windows-gnu + - build: win32-msvc + os: windows-latest + target: i686-pc-windows-msvc + - build: win64-gnu + os: windows-latest + target: x86_64-pc-windows-gnu + - build: win64-msvc + os: windows-latest + target: x86_64-pc-windows-msvc + + steps: + - name: disable git eol translation + if: ${{ matrix.os == 'windows-latest' }} + run: git config --global core.autocrlf false + - name: checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + + - name: Install Rustup using win.rustup.rs + if: ${{ matrix.os == 'windows-latest' }} + run: | + # Disable the download progress bar which can cause perf issues + $ProgressPreference = "SilentlyContinue" + Invoke-WebRequest https://win.rustup.rs/ -OutFile rustup-init.exe + .\rustup-init.exe -y --default-host=x86_64-pc-windows-msvc --default-toolchain=none + del rustup-init.exe + rustup target add ${{ matrix.target }} + shell: powershell + + - name: Add mingw32 to path for i686-gnu + run: | + echo "C:\msys64\mingw32\bin" >> $GITHUB_PATH + if: matrix.target == 'i686-pc-windows-gnu' && matrix.channel == 'nightly' + shell: bash + + - name: Add mingw64 to path for x86_64-gnu + run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH + if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly' + shell: bash + + - name: install rustup + if: ${{ matrix.os != 'windows-latest' }} + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add ${{ matrix.target }} + + # Run build + - name: Build and Test + env: + RUSTFLAGS: -D warnings + CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true + run: cargo run --manifest-path ci/Cargo.toml build-and-test + + test-conclusion: + name: "test conclusion" + needs: + - test + # We need to ensure this job does *not* get skipped if its dependencies fail, + # because a skipped job is considered a success by GitHub. So we have to + # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run + # when the workflow is canceled manually. + # + # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! + if: ${{ !cancelled() }} + runs-on: ubuntu-latest + steps: + # Manually check the status of all dependencies. `if: failure()` does not work. + - name: Conclusion + run: | + # Print the dependent jobs to see them in the CI log + jq -C <<< '${{ toJson(needs) }}' + # Check if all jobs that we depend on (in the needs array) were successful (or have been skipped). + jq --exit-status 'all(.result == "success" or .result == "skipped")' <<< '${{ toJson(needs) }}' diff --git a/.github/workflows/upload-assets.yml b/.github/workflows/upload-assets.yml index 49c9172cb46d1..a81545052e07e 100644 --- a/.github/workflows/upload-assets.yml +++ b/.github/workflows/upload-assets.yml @@ -68,11 +68,6 @@ jobs: - name: Upload Release Asset if: github.event_name == 'release' - uses: actions/upload-release-asset@v1 env: GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} - with: - upload_url: ${{ github.event.release.upload_url }} - asset_path: ${{ env.ASSET }} - asset_name: ${{ env.ASSET }} - asset_content_type: application/octet-stream + run: gh release upload "${{ github.event.release.tag_name }}" "${{ env.ASSET }}" diff --git a/.github/workflows/windows.yml b/.github/workflows/windows.yml deleted file mode 100644 index 435132106e056..0000000000000 --- a/.github/workflows/windows.yml +++ /dev/null @@ -1,68 +0,0 @@ -name: windows -on: - push: - branches: - - main - pull_request: - -permissions: - contents: read - -jobs: - test: - runs-on: windows-latest - name: (${{ matrix.target }}, ${{ matrix.cfg_release_channel }}) - env: - CFG_RELEASE_CHANNEL: ${{ matrix.cfg_release_channel }} - strategy: - # https://help.github.com/en/actions/getting-started-with-github-actions/about-github-actions#usage-limits - # There's a limit of 60 concurrent jobs across all repos in the rust-lang organization. - # In order to prevent overusing too much of that 60 limit, we throttle the - # number of rustfmt jobs that will run concurrently. - max-parallel: 2 - fail-fast: false - matrix: - target: [ - i686-pc-windows-gnu, - i686-pc-windows-msvc, - x86_64-pc-windows-gnu, - x86_64-pc-windows-msvc, - ] - cfg_release_channel: [nightly, stable] - - steps: - # The Windows runners have autocrlf enabled by default - # which causes failures for some of rustfmt's line-ending sensitive tests - - name: disable git eol translation - run: git config --global core.autocrlf false - - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 - - # Run build - - name: Install Rustup using win.rustup.rs - run: | - # Disable the download progress bar which can cause perf issues - $ProgressPreference = "SilentlyContinue" - Invoke-WebRequest https://win.rustup.rs/ -OutFile rustup-init.exe - .\rustup-init.exe -y --default-host=x86_64-pc-windows-msvc --default-toolchain=none - del rustup-init.exe - rustup target add ${{ matrix.target }} - shell: powershell - - - name: Add mingw32 to path for i686-gnu - run: | - echo "C:\msys64\mingw32\bin" >> $GITHUB_PATH - if: matrix.target == 'i686-pc-windows-gnu' && matrix.channel == 'nightly' - shell: bash - - - name: Add mingw64 to path for x86_64-gnu - run: echo "C:\msys64\mingw64\bin" >> $GITHUB_PATH - if: matrix.target == 'x86_64-pc-windows-gnu' && matrix.channel == 'nightly' - shell: bash - - - name: Build and Test - shell: cmd - env: - RUSTFLAGS: -D warnings - CARGO_UNSTABLE_BUILD_DIR_NEW_LAYOUT: true - run: cargo run --manifest-path ci/Cargo.toml build-and-test diff --git a/Cargo.lock b/Cargo.lock index d95fbec8cb7fd..89594ecee1672 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -13,11 +13,12 @@ dependencies = [ [[package]] name = "annotate-snippets" -version = "0.11.5" +version = "0.12.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "710e8eae58854cdc1790fcb56cca04d712a17be849eeb81da2a724bf4bae2bc4" +checksum = "f211a51805bc641f3ad5b7664c77d2547af685cc33b4cd8d31964027a46f13f1" dependencies = [ "anstyle", + "memchr", "unicode-width 0.2.2", ] @@ -193,6 +194,17 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "acbf1af155f9b9ef647e42cdc158db4b64a1b61f743629225fde6f3e0be2a7c7" +[[package]] +name = "console" +version = "0.16.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" +dependencies = [ + "encode_unicode", + "libc", + "windows-sys", +] + [[package]] name = "crossbeam-utils" version = "0.8.8" @@ -236,6 +248,12 @@ version = "1.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" +[[package]] +name = "encode_unicode" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "34aa73646ffb006b8f5147f3dc182bd4bcb190227ce861fc4a4844bf8e3cb2c0" + [[package]] name = "equivalent" version = "1.0.2" @@ -311,9 +329,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.15.5" +version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9229cfe53dfd69f0609a49f65461bd93001ea1ef889cd5529dd176593f5338a1" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "heck" @@ -341,14 +359,28 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.11.0" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2481980430f9f78649238835720ddccc57e52df14ffce1c6f37391d61b563e9" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", "hashbrown", ] +[[package]] +name = "insta" +version = "1.48.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "86f0f8fee8c926415c58d6ae43a08523a26faccb2323f5e6b644fe7dd4ef6b82" +dependencies = [ + "console", + "once_cell", + "regex", + "similar", + "strip-ansi-escapes", + "tempfile", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.2" @@ -418,9 +450,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.4.1" +version = "2.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "308cc39be01b73d0d18f82a0e7b2a3df85245f84af96fdddc5d202d27e47b86a" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "nu-ansi-term" @@ -546,6 +578,7 @@ dependencies = [ "dirs", "getopts", "ignore", + "insta", "itertools", "regex", "rustfmt-config_proc_macro", @@ -640,11 +673,11 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40734c41988f7306bb04f0ecf60ec0f3f1caa34290e4e8ea471dcd3346483b83" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ - "serde", + "serde_core", ] [[package]] @@ -656,12 +689,27 @@ dependencies = [ "lazy_static", ] +[[package]] +name = "similar" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbbb5d9659141646ae647b42fe094daf6c6192d1620870b449d9557f748b2daa" + [[package]] name = "smallvec" version = "1.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a507befe795404456341dfab10cef66ead4c041f62b8b11bbb92bffe5d0953e0" +[[package]] +name = "strip-ansi-escapes" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55ff8ef943b384c414f54aefa961dd2bd853add74ec75e7ac74cf91dba62bcfa" +dependencies = [ + "vte", +] + [[package]] name = "strsim" version = "0.11.1" @@ -752,12 +800,12 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.5" +version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75129e1dc5000bfbaa9fee9d1b21f974f9fbad9daec557a521ee6e080825f6e8" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", - "serde", + "serde_core", "serde_spanned", "toml_datetime", "toml_parser", @@ -767,27 +815,27 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bade1c3e902f58d73d3f294cd7f20391c1cb2fbcb643b73566bc773971df91e3" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ - "serde", + "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.2" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b551886f449aa90d4fe2bdaa9f4a2577ad2dde302c61ecf262d80b116db95c10" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.2" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc842091f2def52017664b53082ecbbeb5c7731092bad69d2c63050401dfd64" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tracing" @@ -881,6 +929,26 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "vte" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f5022b5fbf9407086c180e9557be968742d839e68346af7792b8592489732197" +dependencies = [ + "utf8parse", + "vte_generate_state_changes", +] + +[[package]] +name = "vte_generate_state_changes" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e369bee1b05d510a7b4ed645f5faa90619e05437111783ea5848f28d97d3c2e" +dependencies = [ + "proc-macro2", + "quote", +] + [[package]] name = "walkdir" version = "2.3.2" @@ -955,9 +1023,9 @@ dependencies = [ [[package]] name = "winnow" -version = "0.7.13" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "21a0236b59786fed61e2a80582dd500fe61f18b5dca67a4a067d0bc9039339cf" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" [[package]] name = "wit-bindgen" diff --git a/Cargo.toml b/Cargo.toml index eedd83cad343a..48dfeed93dad9 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -3,7 +3,6 @@ name = "rustfmt-nightly" version = "1.10.0" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" -readme = "README.md" license = "Apache-2.0 OR MIT" build = "build.rs" categories = ["development-tools"] @@ -35,7 +34,7 @@ rustfmt-format-diff = [] generic-simd = [] [dependencies] -annotate-snippets = { version = "0.11" } +annotate-snippets = { version = "0.12" } anyhow = "1.0" bytecount = "0.6.9" cargo_metadata = "0.23" @@ -51,7 +50,7 @@ serde = { version = "1.0.160", features = ["derive"] } serde_json = "1.0" term = "1.1" thiserror = "1.0.40" -toml = "0.9.5" +toml = "1.1" tracing = { version = "0.1.37", default-features = false, features = ["std"] } tracing-subscriber = { version = "0.3.17", features = ["env-filter"] } unicode-segmentation = "1.9" @@ -63,6 +62,7 @@ semver = "1.0.21" [dev-dependencies] tempfile = "3.23.0" +insta = { version = "1.48.0", features = ["filters"] } # Rustc dependencies are loaded from the sysroot, Cargo doesn't know about them. diff --git a/Configurations.md b/Configurations.md index 976c290489460..189389fe143b6 100644 --- a/Configurations.md +++ b/Configurations.md @@ -2150,9 +2150,9 @@ Convert `#![doc]` and `#[doc]` attributes to `//!` and `///` doc comments. #### `false` (default): ```rust -#![doc = "Example documentation"] +#![doc = " Example documentation"] -#[doc = "Example item documentation"] +#[doc = " Example item documentation"] pub enum Bar {} /// Example item documentation @@ -2164,6 +2164,9 @@ pub enum Foo {} ```rust //! Example documentation +/// Example item documentation +pub enum Bar {} + /// Example item documentation pub enum Foo {} ``` diff --git a/Contributing.md b/Contributing.md index 996a30c3a5bc1..7b298052ab2a0 100644 --- a/Contributing.md +++ b/Contributing.md @@ -63,6 +63,11 @@ would need a configuration file named `test-indent.toml` in that directory. As a example, the `issue-1111.rs` test file is configured by the file `./tests/config/issue-1111.toml`. +### Updating snapshots + +Some tests that test rustfmt-specific output (e.g. `--help` output and formatting-specific errors) use [insta](https://insta.rs/) to snapshot their output. +To update these tests, install [`cargo-insta`](https://insta.rs/docs/cli/) and run `cargo insta test --review`. + ## Debugging Some `rewrite_*` methods use the `debug!` macro for printing useful information. diff --git a/Makefile.toml b/Makefile.toml deleted file mode 100644 index 597dd1205643d..0000000000000 --- a/Makefile.toml +++ /dev/null @@ -1,71 +0,0 @@ -[env] -CFG_RELEASE = { value = "${CARGO_MAKE_RUST_VERSION}", condition = { env_not_set = ["CFG_RELEASE"] } } -CFG_RELEASE_CHANNEL = { value = "${CARGO_MAKE_RUST_CHANNEL}", condition = { env_not_set = ["CFG_RELEASE_CHANNEL"] } } - -[tasks.build-bin] -command = "cargo" -args = [ - "build", - "--bin", - "rustfmt", - "--bin", - "cargo-fmt", -] - -[tasks.build-bins] -command = "cargo" -args = [ - "build", - "--bins", -] - -[tasks.install] -command = "cargo" -args = [ - "install", - "--path", - ".", - "--force", - "--locked", # Respect Cargo.lock -] - -[tasks.release] -command = "cargo" -args = [ - "build", - "--release", -] - -[tasks.test] -command = "cargo" -args = [ - "test", -] - -[tasks.test-all] -dependencies = ["build-bin"] -run_task = { name = ["test", "test-ignored"] } - -[tasks.test-ignored] -command = "cargo" -args = [ - "test", - "--", - "--ignored", -] - -[tasks.b] -alias = "build" - -[tasks.bb] -alias = "build-bin" - -[tasks.bins] -alias = "build-bins" - -[tasks.c] -alias = "check" - -[tasks.t] -alias = "test" - diff --git a/README.md b/README.md index 77e3335cf2cc4..0c7ba34574d75 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# rustfmt [![linux](https://github.com/rust-lang/rustfmt/actions/workflows/linux.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/linux.yml) [![mac](https://github.com/rust-lang/rustfmt/actions/workflows/mac.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/mac.yml) [![windows](https://github.com/rust-lang/rustfmt/actions/workflows/windows.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/windows.yml) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) +# rustfmt [![tests](https://github.com/rust-lang/rustfmt/actions/workflows/test.yml/badge.svg?event=push)](https://github.com/rust-lang/rustfmt/actions/workflows/test.yml?query=branch%3Amain) [![crates.io](https://img.shields.io/crates/v/rustfmt-nightly.svg)](https://crates.io/crates/rustfmt-nightly) A tool for formatting Rust code according to style guidelines. diff --git a/Subtree sync procedure.md b/Subtree sync procedure.md index 444246117d49e..99e01486ed1be 100644 --- a/Subtree sync procedure.md +++ b/Subtree sync procedure.md @@ -116,7 +116,7 @@ commit message template](#rust-toolchain-bump-commit-message-template). #### `rust-toolchain` bump commit message template -```text +````text chore: bump rustfmt toolchain to nightly-$LATEST_NIGHTLY_DATE Bumping the toolchain version as part of a git subtree push. @@ -132,6 +132,7 @@ After: ``` $LATEST_NIGHTLY_VERSION-nightly ($LATEST_NIGHTLY_HASH $LATEST_NIGHTLY_DATE) ``` +```` Substituting the placeholders with the right information. diff --git a/check_diff/Cargo.lock b/check_diff/Cargo.lock index 78736479e501a..8093a08326d2c 100644 --- a/check_diff/Cargo.lock +++ b/check_diff/Cargo.lock @@ -456,9 +456,9 @@ dependencies = [ [[package]] name = "serde_spanned" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8bbf91e5a4d6315eee45e704372590b30e260ee83af6639d64557f51b067776" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" dependencies = [ "serde_core", ] @@ -519,9 +519,9 @@ dependencies = [ [[package]] name = "toml" -version = "0.9.11+spec-1.1.0" +version = "1.1.4+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3afc9a848309fe1aaffaed6e1546a7a14de1f935dc9d89d32afd9a44bab7c46" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" dependencies = [ "indexmap", "serde_core", @@ -534,27 +534,27 @@ dependencies = [ [[package]] name = "toml_datetime" -version = "0.7.5+spec-1.1.0" +version = "1.1.1+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "92e1cfed4a3038bc5a127e35a2d360f145e1f4b971b551a2ba5fd7aedf7e1347" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" dependencies = [ "serde_core", ] [[package]] name = "toml_parser" -version = "1.0.6+spec-1.1.0" +version = "1.1.3+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3198b4b0a8e11f09dd03e133c0280504d0801269e9afa46362ffde1cbeebf44" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" dependencies = [ "winnow", ] [[package]] name = "toml_writer" -version = "1.0.6+spec-1.1.0" +version = "1.1.2+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab16f14aed21ee8bfd8ec22513f7287cd4a91aa92e44edfe2c17ddd004e92607" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tracing" @@ -751,6 +751,6 @@ checksum = "bec47e5bfd1bff0eeaf6d8b485cc1074891a197ab4225d504cb7a1ab88b02bf0" [[package]] name = "winnow" -version = "0.7.14" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5a5364e9d77fcdeeaa6062ced926ee3381faa2ee02d3eb83a5c27a8825540829" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" diff --git a/check_diff/Cargo.toml b/check_diff/Cargo.toml index 50e3f0062d832..18a4aa90d6c0d 100644 --- a/check_diff/Cargo.toml +++ b/check_diff/Cargo.toml @@ -14,4 +14,4 @@ walkdir = "2.5.0" diffy = "0.4.0" crossbeam-channel = "0.5.15" ignore = "0.4.25" -toml = "0.9.11" +toml = "1.1" diff --git a/check_diff/src/lib.rs b/check_diff/src/lib.rs index d6bb7678ea029..9578a2e19c0fd 100644 --- a/check_diff/src/lib.rs +++ b/check_diff/src/lib.rs @@ -79,6 +79,37 @@ impl FromStr for StyleEdition { } } +/// Configure which release channel to use when compiling rustfmt +#[derive(Debug, Clone, Copy)] +pub enum ReleaseChannel { + Stable, + Beta, + Nightly, +} + +impl ReleaseChannel { + fn as_str(&self) -> &str { + match self { + Self::Stable => "stable", + Self::Beta => "beta", + Self::Nightly => "nightly", + } + } +} + +impl FromStr for ReleaseChannel { + type Err = String; + + fn from_str(s: &str) -> Result { + match s { + "stable" => Ok(Self::Stable), + "beta" => Ok(Self::Beta), + "nightly" => Ok(Self::Nightly), + _ => Err(format!("Invalid release channel {s}")), + } + } +} + pub enum FormatCodeError { // IO Error when running code formatter Io(std::io::Error), @@ -105,16 +136,14 @@ impl std::fmt::Debug for FormatCodeError { } pub enum CreateDiffError { - /// Couldn't create a diff because the rustfmt binary compiled from the `main` branch - /// failed to format the input. - MainRustfmtFailed(FormatCodeError), - /// Couldn't create a diff because the rustfmt binary compiled from the `feature` branch - /// failed to format the input. - FeatureRustfmtFailed(FormatCodeError), + /// Couldn't create a diff because the source formatter failed to format the input. + SourceFormatterFailed(FormatCodeError), + /// Couldn't create a diff because the target formatter failed to format the input. + TargetFormatterFailed(FormatCodeError), /// Couldn't create a diff because both rustfmt binaries failed to format the input BothRustfmtFailed { - src: FormatCodeError, - feature: FormatCodeError, + source: FormatCodeError, + target: FormatCodeError, }, } @@ -161,27 +190,27 @@ impl From for GitError { } pub struct Diff { - src_format: String, - feature_format: String, + source: String, + target: String, } impl Display for Diff { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let patch = diffy::create_patch(self.src_format.as_str(), self.feature_format.as_str()); + let patch = diffy::create_patch(self.source.as_str(), self.target.as_str()); write!(f, "{}", patch) } } impl Diff { pub fn is_empty(&self) -> bool { - let patch = diffy::create_patch(self.src_format.as_str(), self.feature_format.as_str()); + let patch = diffy::create_patch(self.source.as_str(), self.target.as_str()); patch.hunks().is_empty() } } -pub struct CheckDiffRunners { - feature_runner: F, - src_runner: S, +pub struct DiffChecker { + source: S, + target: T, } pub trait CodeFormatter { @@ -201,43 +230,34 @@ pub struct RustfmtRunner { config: Cow<'static, str>, } -impl CheckDiffRunners { - pub fn new(feature_runner: F, src_runner: S) -> Self { - Self { - feature_runner, - src_runner, - } +impl DiffChecker { + pub fn new(source: S, target: T) -> Self { + Self { source, target } } } -impl CheckDiffRunners +impl DiffChecker where - F: CodeFormatter, S: CodeFormatter, + T: CodeFormatter, { - /// Creates a diff generated by running the source and feature binaries on the same file path + /// Creates a diff generated by running the source and target formatters on the same file path pub fn create_diff>(&self, path: P) -> Result { - let src_format = self.src_runner.format_code_from_path(&path); - let feature_format = self.feature_runner.format_code_from_path(&path); + let source_format = self.source.format_code_from_path(&path); + let target_format = self.target.format_code_from_path(&path); - match (src_format, feature_format) { - (Ok(s), Ok(f)) => Ok(Diff { - src_format: s, - feature_format: f, + match (source_format, target_format) { + (Ok(s), Ok(t)) => Ok(Diff { + source: s, + target: t, }), - (Err(error), Ok(_)) => { - // main formatting failed. - Err(CreateDiffError::MainRustfmtFailed(error)) - } - (Ok(_), Err(error)) => { - // feature formatting failed - Err(CreateDiffError::FeatureRustfmtFailed(error)) - } - (Err(src_error), Err(feature_error)) => { - // Both main formatting and feature formatting failed + (Err(error), Ok(_)) => Err(CreateDiffError::SourceFormatterFailed(error)), + (Ok(_), Err(error)) => Err(CreateDiffError::TargetFormatterFailed(error)), + (Err(source_error), Err(target_error)) => { + // Both source formatting and target formatting failed Err(CreateDiffError::BothRustfmtFailed { - src: src_error, - feature: feature_error, + source: source_error, + target: target_error, }) } } @@ -507,7 +527,7 @@ pub fn git_remote_add(url: &str) -> Result<(), GitError> { pub fn git_fetch(branch_name: &str) -> Result<(), GitError> { let git_cmd = Command::new("git") - .args(["fetch", "feature", branch_name]) + .args(["fetch", "--depth", "1", "feature", branch_name]) .output()?; // if the git command does not return successfully, @@ -583,13 +603,16 @@ pub fn build_rustfmt_from_src>( edition: Edition, style_edition: StyleEdition, config: Option<&[T]>, + release_channel: ReleaseChannel, ) -> Result { // Because we're building standalone binaries we need to set the dynamic library path // so each rustfmt binary can find it's runtime dependencies. let dynamic_library_path = get_dynamic_library_path(dir)?; + let release_channel = release_channel.as_str(); - info!("Building rustfmt from source"); + info!("Building {} rustfmt from source", release_channel); let Ok(_) = Command::new("cargo") + .env("CFG_RELEASE_CHANNEL", release_channel) .current_dir(dir) .args(["build", "-q", "--release", "--bin", "rustfmt"]) .output() @@ -622,51 +645,52 @@ pub fn compile_rustfmt>( style_edition: StyleEdition, commit_hash: Option, config: Option<&[T]>, -) -> Result, CheckDiffError> { + release_channel: ReleaseChannel, +) -> Result, CheckDiffError> { const RUSTFMT_REPO: &str = "https://github.com/rust-lang/rustfmt.git"; + let checkout_ref = commit_hash.as_ref().unwrap_or(&feature_branch); clone_git_repo(RUSTFMT_REPO, dest)?; change_directory_to_path(dest)?; git_remote_add(remote_repo_url.as_str())?; - git_fetch(feature_branch.as_str())?; + git_fetch(checkout_ref.as_str())?; let cargo_version = get_cargo_version()?; info!("Compiling with {}", cargo_version); - let src_runner = build_rustfmt_from_src( - dest.join("src_rustfmt"), + let source_runner = build_rustfmt_from_src( + dest.join("source_rustfmt"), dest, edition, style_edition, config, + release_channel, )?; let should_detach = commit_hash.is_some(); - git_switch( - commit_hash.as_ref().unwrap_or(&feature_branch), - should_detach, - )?; + git_switch(checkout_ref, should_detach)?; - let feature_runner = build_rustfmt_from_src( - dest.join("feature_rustfmt"), + let target_runner = build_rustfmt_from_src( + dest.join("target_rustfmt"), dest, edition, style_edition, config, + release_channel, )?; - info!("RUSFMT_BIN {}", src_runner.get_binary_version()?); + info!("SOURCE_BIN {}", source_runner.get_binary_version()?); let dynamic_library_path_env_var = dynamic_library_path_env_var_name(); info!( "Runtime dependencies for (main) rustfmt -- {}: {}", - dynamic_library_path_env_var, src_runner.dynamic_library_path + dynamic_library_path_env_var, source_runner.dynamic_library_path ); - info!("FEATURE_BIN {}", feature_runner.get_binary_version()?); + info!("TARGET_BIN {}", target_runner.get_binary_version()?); info!( "Runtime dependencies for ({}) rustfmt -- {}: {}", - feature_branch, dynamic_library_path_env_var, feature_runner.dynamic_library_path + feature_branch, dynamic_library_path_env_var, target_runner.dynamic_library_path ); - Ok(CheckDiffRunners { - src_runner, - feature_runner, + Ok(DiffChecker { + source: source_runner, + target: target_runner, }) } @@ -792,10 +816,10 @@ pub fn clone_repositories_for_diff_check( map.into_values().collect() } -/// Calculates the number of errors when running the compiled binary and the feature binary on the +/// Calculates the number of errors when running the compiled binary and the target binary on the /// repo specified with the specific configs. pub fn check_diff_for_file<'repo, P: AsRef, F: AsRef>( - runners: &CheckDiffRunners, + diff_checker: &DiffChecker, repo: &'repo Repository

, file: F, ) -> Result<(), (Diff, F, &'repo Repository

)> { @@ -808,7 +832,7 @@ pub fn check_diff_for_file<'repo, P: AsRef, F: AsRef>( relative_path.display() ); - match runners.create_diff(file.as_ref()) { + match diff_checker.create_diff(file.as_ref()) { Ok(diff) => { if !diff.is_empty() { Err((diff, file, repo)) @@ -821,31 +845,31 @@ pub fn check_diff_for_file<'repo, P: AsRef, F: AsRef>( Ok(()) } } - Err(CreateDiffError::MainRustfmtFailed(e)) => { + Err(CreateDiffError::SourceFormatterFailed(e)) => { debug!( - "`main` rustfmt failed to format {}/{}\n{:?}", + "`source` rustfmt failed to format {}/{}\n{:?}", repo_name, relative_path.display(), e, ); Ok(()) } - Err(CreateDiffError::FeatureRustfmtFailed(e)) => { + Err(CreateDiffError::TargetFormatterFailed(e)) => { debug!( - "`feature` rustfmt failed to format {}/{}\n{:?}", + "`target` rustfmt failed to format {}/{}\n{:?}", repo_name, relative_path.display(), e, ); Ok(()) } - Err(CreateDiffError::BothRustfmtFailed { src, feature }) => { + Err(CreateDiffError::BothRustfmtFailed { source, target }) => { debug!( "Both rustfmt binaries failed to format {}/{}\n{:?}\n{:?}", repo_name, relative_path.display(), - src, - feature, + source, + target, ); Ok(()) } @@ -861,15 +885,15 @@ pub fn get_repo_name(git_url: &str) -> &str { repo_name } -pub fn check_diff<'repo, P, F, M>( - runners: &CheckDiffRunners, +pub fn check_diff<'repo, P, S, T>( + diff_checker: &DiffChecker, repositories: &'repo [Repository

], worker_threads: std::num::NonZeroU8, ) -> Vec<(Diff, PathBuf, &'repo Repository

)> where P: AsRef + Sync + Send, - F: CodeFormatter + Sync, - M: CodeFormatter + Sync, + S: CodeFormatter + Sync, + T: CodeFormatter + Sync, { let (tx, rx) = crossbeam_channel::unbounded(); @@ -900,7 +924,7 @@ where let rx = rx.clone(); s.spawn(move || { while let Ok((file, repo)) = rx.recv() { - if let Err(e) = check_diff_for_file(runners, repo, file) { + if let Err(e) = check_diff_for_file(diff_checker, repo, file) { // Push errors to report on later errors.lock().unwrap().push(e); } diff --git a/check_diff/src/main.rs b/check_diff/src/main.rs index bffe090f7ace6..c48280f254d4b 100644 --- a/check_diff/src/main.rs +++ b/check_diff/src/main.rs @@ -2,7 +2,8 @@ use std::io::Error; use std::process::ExitCode; use check_diff::{ - Edition, StyleEdition, check_diff, clone_repositories_for_diff_check, compile_rustfmt, + Edition, ReleaseChannel, StyleEdition, check_diff, clone_repositories_for_diff_check, + compile_rustfmt, }; use clap::Parser; use tempfile::tempdir; @@ -67,6 +68,8 @@ struct CliInputs { // Choosing 16 as the default since that's a common multiple of available CPU cores. #[arg(short, long, default_value_t = std::num::NonZeroU8::new(16).unwrap())] worker_threads: std::num::NonZeroU8, + #[arg(long, default_value = "stable")] + release_channel: ReleaseChannel, } fn main() -> Result { @@ -85,9 +88,10 @@ fn main() -> Result { args.style_edition, args.commit_hash, args.rustfmt_config.as_deref(), + args.release_channel, ); - let check_diff_runners = match compilation_result { + let diff_checker = match compilation_result { Ok(runner) => runner, Err(e) => { error!("Failed to compile rustfmt:\n{e:?}"); @@ -99,7 +103,7 @@ fn main() -> Result { let repositories = clone_repositories_for_diff_check(REPOS); info!("Starting the Diff Check"); - let errors = check_diff(&check_diff_runners, &repositories, args.worker_threads); + let errors = check_diff(&diff_checker, &repositories, args.worker_threads); if errors.is_empty() { info!("No diff found 😊"); diff --git a/check_diff/tests/check_diff.rs b/check_diff/tests/check_diff.rs index b1b4001bac178..8e0e9333d7c71 100644 --- a/check_diff/tests/check_diff.rs +++ b/check_diff/tests/check_diff.rs @@ -1,6 +1,6 @@ use check_diff::{ - CheckDiffError, CheckDiffRunners, CodeFormatter, FormatCodeError, Repository, - RustFmtFileFinder, check_diff, + CheckDiffError, CodeFormatter, DiffChecker, FormatCodeError, Repository, RustFmtFileFinder, + check_diff, }; use std::fs::File; use tempfile::Builder; @@ -67,7 +67,7 @@ fn search_for_files_correctly_nested() -> Result<(), Box> #[test] fn check_diff_test_no_formatting_difference() -> Result<(), CheckDiffError> { - let runners = CheckDiffRunners::new(DoNothingFormatter, DoNothingFormatter); + let diff_checker = DiffChecker::new(DoNothingFormatter, DoNothingFormatter); let dir = Builder::new().tempdir_in("").unwrap(); let file_path = dir.path().join("test.rs"); @@ -76,14 +76,14 @@ fn check_diff_test_no_formatting_difference() -> Result<(), CheckDiffError> { let repos = [repo]; let workers = std::num::NonZeroU8::new(1).unwrap(); - let errors = check_diff(&runners, &repos, workers); + let errors = check_diff(&diff_checker, &repos, workers); assert_eq!(errors.len(), 0); Ok(()) } #[test] fn check_diff_test_formatting_difference() -> Result<(), CheckDiffError> { - let runners = CheckDiffRunners::new(DoNothingFormatter, AddWhiteSpaceFormatter); + let diff_checker = DiffChecker::new(DoNothingFormatter, AddWhiteSpaceFormatter); let dir = Builder::new().tempdir_in("").unwrap(); let file_path = dir.path().join("test.rs"); let _tmp_file = File::create(file_path)?; @@ -91,7 +91,7 @@ fn check_diff_test_formatting_difference() -> Result<(), CheckDiffError> { let repos = [repo]; let workers = std::num::NonZeroU8::new(1).unwrap(); - let errors = check_diff(&runners, &repos, workers); + let errors = check_diff(&diff_checker, &repos, workers); assert_ne!(errors.len(), 0); Ok(()) } diff --git a/rust-toolchain b/rust-toolchain index 5dac4fcf28091..9dda873e3e868 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-07-19" +channel = "nightly-2026-08-27" components = ["llvm-tools", "rustc-dev"] diff --git a/src/bin/main.rs b/src/bin/main.rs index 6c48301f6c8f6..ffe9aa7e3a49c 100644 --- a/src/bin/main.rs +++ b/src/bin/main.rs @@ -135,12 +135,6 @@ fn make_opts() -> Options { "Rust edition to use", "[2015|2018|2021|2024]", ); - opts.optopt( - "", - "style-edition", - "The edition of the Style Guide (unstable).", - "[2015|2018|2021|2024]", - ); opts.optopt( "", "color", @@ -630,6 +624,19 @@ impl GetOptsOptions { options.emit_mode = Some(emit_mode_from_emit_str(emit_str)?); } + if options.inline_config.contains_key("emit_mode") { + if options.check { + return Err(format_err!( + "Invalid to use `--config=emit_mode=` and `--check`" + )); + } + if options.emit_mode.is_some() { + return Err(format_err!( + "Invalid to use `--config=emit_mode=` and `--emit`" + )); + } + } + if let Some(ref edition_str) = matches.opt_str("edition") { options.edition = Some(edition_from_edition_str(edition_str)?); } @@ -830,6 +837,37 @@ mod test { assert_eq!(config.style_edition(), StyleEdition::Edition2024); } + #[test] + fn emit_mode_from_inline_config_is_rejected() { + // Regression for #6999. + let emit_modes = [ + "Files", + "Stdout", + "Coverage", + "Checkstyle", + "Json", + "ModifiedLines", + "Diff", + ]; + for mode in emit_modes { + let config = format!("emit_mode={mode}"); + + let matches = make_opts().parse(["--check", "--config", &config]).unwrap(); + assert!( + GetOptsOptions::from_matches(&matches).is_err(), + "`--check` with `--config={config}` should be rejected" + ); + + let matches = make_opts() + .parse(["--emit", "stdout", "--config", &config]) + .unwrap(); + assert!( + GetOptsOptions::from_matches(&matches).is_err(), + "`--emit` with `--config={config}` should be rejected" + ); + } + } + #[nightly_only_test] #[test] fn version_config_file_sets_style_edition_override_correctly() { diff --git a/src/cargo-fmt/main.rs b/src/cargo-fmt/main.rs index 6627ada03fc6a..0513fd766ddf0 100644 --- a/src/cargo-fmt/main.rs +++ b/src/cargo-fmt/main.rs @@ -387,11 +387,16 @@ fn get_targets_root_only( targets: &mut BTreeSet, ) -> Result<(), io::Error> { let metadata = get_cargo_metadata(manifest_path)?; + // `workspace_root_path` is the path to the workspace's root directory let workspace_root_path = PathBuf::from(&metadata.workspace_root).canonicalize()?; let (in_workspace_root, current_dir_manifest) = if let Some(target_manifest) = manifest_path { + // `target_manifest` is the canonicalized path to a `Cargo.toml` file + let target_manifest = target_manifest.canonicalize()?; ( - workspace_root_path == target_manifest, - target_manifest.canonicalize()?, + target_manifest + .parent() + .is_some_and(|manifest_dir| workspace_root_path == manifest_dir), + target_manifest, ) } else { let current_dir = env::current_dir()?.canonicalize()?; diff --git a/src/cargo-fmt/test/targets.rs b/src/cargo-fmt/test/targets.rs index 34accb2136a44..ad2842c91a2e9 100644 --- a/src/cargo-fmt/test/targets.rs +++ b/src/cargo-fmt/test/targets.rs @@ -14,11 +14,12 @@ mod all_targets { source_root: &str, exp_targets: &[ExpTarget], exp_num_targets: usize, + strategy: CargoFmtStrategy, ) { let root_path = Path::new("tests/cargo-fmt/source").join(source_root); let get_path = |exp: &str| PathBuf::from(&root_path).join(exp).canonicalize().unwrap(); let manifest_path = Path::new(&root_path).join(manifest_suffix); - let targets = get_targets(&CargoFmtStrategy::All, Some(manifest_path.as_path())) + let targets = get_targets(&strategy, Some(manifest_path.as_path())) .expect("Targets should have been loaded"); assert_eq!(targets.len(), exp_num_targets); @@ -58,6 +59,7 @@ mod all_targets { "divergent-crate-dir-names", &exp_targets, 3, + CargoFmtStrategy::All, ); } @@ -113,6 +115,7 @@ mod all_targets { "workspaces/path-dep-above", &exp_targets, 6, + CargoFmtStrategy::All, ); } @@ -131,4 +134,32 @@ mod all_targets { assert_correct_targets_loaded("ws/a/d/f/Cargo.toml"); } } + + mod cargo_fmt_strategy_root { + use super::*; + + #[test] + fn assert_correct_targets_loaded_from_root() { + let exp_targets = &[ + ExpTarget { + path: "inner_bin/src/main.rs", + edition: Edition::E2021, + kind: "bin", + }, + ExpTarget { + path: "inner_lib/src/lib.rs", + edition: Edition::E2021, + kind: "lib", + }, + ]; + + super::assert_correct_targets_loaded( + "Cargo.toml", + "issues_6517", + exp_targets, + 2, + CargoFmtStrategy::Root, + ); + } + } } diff --git a/src/chains.rs b/src/chains.rs index 90adb67ad4392..4bb2f66d484f7 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -167,7 +167,7 @@ enum CommentPosition { /// Information about an expression in a chain. struct SubExpr { expr: ast::Expr, - is_method_call_receiver: bool, + is_postfix_receiver: bool, } /// An expression plus trailing `?`s to be formatted together. @@ -226,7 +226,7 @@ impl ChainItemKind { fn from_ast( context: &RewriteContext<'_>, expr: &ast::Expr, - is_method_call_receiver: bool, + is_postfix_receiver: bool, ) -> (ChainItemKind, Span) { let (kind, span) = match expr.kind { ast::ExprKind::MethodCall(ref call) => { @@ -276,7 +276,7 @@ impl ChainItemKind { return ( ChainItemKind::Parent { expr: expr.clone(), - parens: is_method_call_receiver && should_add_parens(expr, context), + parens: is_postfix_receiver && should_add_parens(expr, context), }, expr.span, ); @@ -331,8 +331,7 @@ impl Rewrite for ChainItem { impl ChainItem { fn new(context: &RewriteContext<'_>, expr: &SubExpr, tries: usize) -> ChainItem { - let (kind, span) = - ChainItemKind::from_ast(context, &expr.expr, expr.is_method_call_receiver); + let (kind, span) = ChainItemKind::from_ast(context, &expr.expr, expr.is_postfix_receiver); ChainItem { kind, tries, span } } @@ -503,7 +502,7 @@ impl Chain { fn make_subexpr_list(expr: &ast::Expr, context: &RewriteContext<'_>) -> Vec { let mut subexpr_list = vec![SubExpr { expr: expr.clone(), - is_method_call_receiver: false, + is_postfix_receiver: false, }]; while let Some(subexpr) = Self::pop_expr_chain(subexpr_list.last().unwrap(), context) { @@ -519,15 +518,18 @@ impl Chain { match expr.expr.kind { ast::ExprKind::MethodCall(ref call) => Some(SubExpr { expr: Self::convert_try(&call.receiver, context), - is_method_call_receiver: true, + is_postfix_receiver: true, }), ast::ExprKind::Field(ref subexpr, _) - | ast::ExprKind::Try(ref subexpr) | ast::ExprKind::Await(ref subexpr, _) | ast::ExprKind::Use(ref subexpr, _) | ast::ExprKind::Yield(ast::YieldKind::Postfix(ref subexpr)) => Some(SubExpr { expr: Self::convert_try(subexpr, context), - is_method_call_receiver: false, + is_postfix_receiver: true, + }), + ast::ExprKind::Try(ref subexpr) => Some(SubExpr { + expr: Self::convert_try(subexpr, context), + is_postfix_receiver: false, }), _ => None, } diff --git a/src/closures.rs b/src/closures.rs index e7c04c975a385..551e2e40425fd 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -14,7 +14,9 @@ use crate::rewrite::{Rewrite, RewriteContext, RewriteError, RewriteErrorExt, Rew use crate::shape::Shape; use crate::source_map::SpanUtils; use crate::types::rewrite_bound_params; -use crate::utils::{NodeIdExt, format_coro, last_line_width, left_most_sub_expr, stmt_expr}; +use crate::utils::{ + NodeIdExt, format_coro, last_line_width, left_most_sub_expr, outer_attributes, stmt_expr, +}; // This module is pretty messy because of the rules around closures and blocks: // FIXME - the below is probably no longer true in full. @@ -166,6 +168,8 @@ fn rewrite_closure_with_block( return Err(RewriteError::Unknown); } + // `body.attrs` may hold inner attributes from a nested block, e.g. `while cond { #![attr] }`. + let outer_attrs = outer_attributes(&body.attrs); let block = ast::Block { stmts: thin_vec![ast::Stmt { id: ast::NodeId::root(), @@ -174,8 +178,7 @@ fn rewrite_closure_with_block( }], id: ast::NodeId::root(), rules: ast::BlockCheckMode::Default, - span: body - .attrs + span: outer_attrs .first() .map(|attr| attr.span.to(body.span)) .unwrap_or(body.span), @@ -184,7 +187,7 @@ fn rewrite_closure_with_block( context, "", &block, - Some(&body.attrs), + Some(&outer_attrs), None, shape, false, diff --git a/src/config/options.rs b/src/config/options.rs index 3f970ed4bd710..db48d99604a9f 100644 --- a/src/config/options.rs +++ b/src/config/options.rs @@ -121,11 +121,17 @@ impl DocCodeHeuristics { } impl Density { - pub fn to_list_tactic(self, len: usize) -> ListTactic { + pub fn to_list_tactic(self, style_edition: StyleEdition, len: usize) -> ListTactic { match self { Density::Compressed => ListTactic::Mixed, Density::Tall => ListTactic::HorizontalVertical, - Density::Vertical if len == 1 => ListTactic::Horizontal, + Density::Vertical if len == 1 => { + if style_edition <= StyleEdition::Edition2024 { + ListTactic::Horizontal + } else { + ListTactic::HorizontalVertical + } + } Density::Vertical => ListTactic::Vertical, } } diff --git a/src/expr.rs b/src/expr.rs index 268f79cd127b4..cef0bd97d578c 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -678,6 +678,7 @@ pub(crate) fn rewrite_cond( // Abstraction over control flow expressions #[derive(Debug)] struct ControlFlow<'a> { + inner_attributes: Option>, cond: Option<&'a ast::Expr>, block: &'a ast::Block, else_block: Option<&'a ast::Expr>, @@ -702,6 +703,7 @@ fn extract_pats_and_cond(expr: &ast::Expr) -> (Option<&ast::Pat>, &ast::Expr) { // FIXME: Refactor this. fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option> { + let inner_attributes = inner_attributes(&expr.attrs); match expr.kind { ast::ExprKind::If(ref cond, ref if_block, ref else_block) => { let (pat, cond) = extract_pats_and_cond(cond); @@ -716,14 +718,30 @@ fn to_control_flow(expr: &ast::Expr, expr_type: ExprType) -> Option Some(ControlFlow::new_for( - &f.pat, &f.iter, &f.body, f.label, expr.span, f.kind, + inner_attributes, + &f.pat, + &f.iter, + &f.body, + f.label, + expr.span, + f.kind, + )), + ast::ExprKind::Loop(ref block, label, _) => Some(ControlFlow::new_loop( + inner_attributes, + block, + label, + expr.span, )), - ast::ExprKind::Loop(ref block, label, _) => { - Some(ControlFlow::new_loop(block, label, expr.span)) - } ast::ExprKind::While(ref cond, ref block, label) => { let (pat, cond) = extract_pats_and_cond(cond); - Some(ControlFlow::new_while(pat, cond, block, label, expr.span)) + Some(ControlFlow::new_while( + inner_attributes, + pat, + cond, + block, + label, + expr.span, + )) } _ => None, } @@ -745,6 +763,7 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { let matcher = choose_matcher(pat); ControlFlow { + inner_attributes: None, cond: Some(cond), block, else_block, @@ -760,8 +779,14 @@ impl<'a> ControlFlow<'a> { } } - fn new_loop(block: &'a ast::Block, label: Option, span: Span) -> ControlFlow<'a> { + fn new_loop( + inner_attributes: Vec, + block: &'a ast::Block, + label: Option, + span: Span, + ) -> ControlFlow<'a> { ControlFlow { + inner_attributes: Some(inner_attributes), cond: None, block, else_block: None, @@ -778,6 +803,7 @@ impl<'a> ControlFlow<'a> { } fn new_while( + inner_attributes: Vec, pat: Option<&'a ast::Pat>, cond: &'a ast::Expr, block: &'a ast::Block, @@ -786,6 +812,7 @@ impl<'a> ControlFlow<'a> { ) -> ControlFlow<'a> { let matcher = choose_matcher(pat); ControlFlow { + inner_attributes: Some(inner_attributes), cond: Some(cond), block, else_block: None, @@ -802,6 +829,7 @@ impl<'a> ControlFlow<'a> { } fn new_for( + inner_attributes: Vec, pat: &'a ast::Pat, cond: &'a ast::Expr, block: &'a ast::Block, @@ -810,6 +838,7 @@ impl<'a> ControlFlow<'a> { kind: ForLoopKind, ) -> ControlFlow<'a> { ControlFlow { + inner_attributes: Some(inner_attributes), cond: Some(cond), block, else_block: None, @@ -961,8 +990,50 @@ impl<'a> ControlFlow<'a> { }; let label_string = rewrite_label(context, self.label); + + // Do not include the label in the span. + let lo = self + .label + .map_or(self.span.lo(), |label| label.ident.span.hi()); + + // `for await` is spelled with two tokens, and the source is free to + // separate them with any whitespace or comments. Locate each token in + // turn rather than searching for the rendered keyword, and keep + // whatever sits in the gap. + let (keyword, after_kwd) = if self.keyword == "for await" { + let after_for = context + .snippet_provider + .span_after(mk_sp(lo, self.span.hi()), "for"); + let before_await = context + .snippet_provider + .opt_span_before(mk_sp(after_for, self.span.hi()), "await") + .unknown_error()?; + let after_await = context + .snippet_provider + .opt_span_after(mk_sp(after_for, self.span.hi()), "await") + .unknown_error()?; + + // "for" + whatever is in the gap + "await" + let kwd = combine_strs_with_missing_comments( + context, + "for", + "await", + mk_sp(after_for, before_await), + shape, + true, + )?; + (kwd, after_await) + } else { + ( + self.keyword.to_owned(), + context + .snippet_provider + .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), + ) + }; + // 1 = space after keyword. - let offset = self.keyword.len() + label_string.len() + 1; + let offset = last_line_width(&keyword) + label_string.len() + 1; let pat_expr_string = match self.cond { Some(cond) => self.rewrite_pat_expr(context, cond, constr_shape, offset)?, @@ -980,10 +1051,15 @@ impl<'a> ControlFlow<'a> { .config .max_width() .saturating_sub(constr_shape.used_width() + offset + brace_overhead); + let first_line_indent = if context.config.style_edition() >= StyleEdition::Edition2027 { + shape.indent.width() + } else { + shape.used_width() + }; let force_newline_brace = (pat_expr_string.contains('\n') || pat_expr_string.len() > one_line_budget) && (!last_line_extendable(&pat_expr_string) - || last_line_offsetted(shape.used_width(), &pat_expr_string)); + || last_line_offsetted(first_line_indent, &pat_expr_string)); // Try to format if-else on single line. if self.allow_single_line && context.config.single_line_if_else_max_width() > 0 { @@ -1003,14 +1079,8 @@ impl<'a> ControlFlow<'a> { }; // `for event in event` - // Do not include label in the span. - let lo = self - .label - .map_or(self.span.lo(), |label| label.ident.span.hi()); let between_kwd_cond = mk_sp( - context - .snippet_provider - .span_after(mk_sp(lo, self.span.hi()), self.keyword.trim()), + after_kwd, if self.pat.is_none() { cond_span.lo() } else if self.matcher.is_empty() { @@ -1041,14 +1111,14 @@ impl<'a> ControlFlow<'a> { last_line_width(&pat_expr_string) } else { // 2 = spaces after keyword and condition. - label_string.len() + self.keyword.len() + pat_expr_string.len() + 2 + label_string.len() + last_line_width(&keyword) + pat_expr_string.len() + 2 }; Ok(( format!( "{}{}{}{}{}", label_string, - self.keyword, + keyword, between_kwd_cond_comment.as_ref().map_or( if pat_expr_string.is_empty() || pat_expr_string.starts_with('\n') { "" @@ -1138,8 +1208,15 @@ impl<'a> Rewrite for ControlFlow<'a> { let block_str = { let old_val = context.is_if_else_block.replace(self.else_block.is_some()); let old_is_loop = context.is_loop_block.replace(self.is_loop); - let result = - rewrite_block_with_visitor(context, "", self.block, None, None, block_shape, true); + let result = rewrite_block_with_visitor( + context, + "", + self.block, + self.inner_attributes.as_deref(), + None, + block_shape, + true, + ); context.is_loop_block.replace(old_is_loop); context.is_if_else_block.replace(old_val); result? @@ -1892,8 +1969,13 @@ pub(crate) fn rewrite_field( let expr = field.expr.rewrite_result(context, expr_shape); let is_lit = matches!(field.expr.kind, ast::ExprKind::Lit(_)); match expr { + // A macro can give `Field: value` its own meaning, so shortening `a: a` to `a` may + // change what it expands to. In `winnow::seq!` the result no longer compiles. Ok(ref e) - if !is_lit && e.as_str() == name && context.config.use_field_init_shorthand() => + if !is_lit + && e.as_str() == name + && context.config.use_field_init_shorthand() + && !context.inside_macro() => { Ok(attrs_str + name) } diff --git a/src/format_report_formatter.rs b/src/format_report_formatter.rs index 08889c712a5f9..dc8d2641d5b2e 100644 --- a/src/format_report_formatter.rs +++ b/src/format_report_formatter.rs @@ -1,6 +1,6 @@ use crate::formatting::FormattingError; use crate::{ErrorKind, FormatReport}; -use annotate_snippets::{Annotation, Level, Renderer, Snippet}; +use annotate_snippets::{Annotation, AnnotationKind, Group, Level, Padding, Renderer, Snippet}; use std::fmt::{self, Display}; /// A builder for [`FormatReportFormatter`]. @@ -57,26 +57,23 @@ impl<'a> Display for FormatReportFormatter<'a> { for (file, errors) in errors_by_file { for error in errors { let error_kind = error.kind.to_string(); - let mut message = - error_kind_to_snippet_annotation_level(&error.kind).title(&error_kind); + let mut title = + error_kind_to_snippet_annotation_level(&error.kind).primary_title(error_kind); if error.is_internal() { - message = message.id("internal"); + title = title.id("internal"); } - - let message_suffix = error.msg_suffix(); - if !message_suffix.is_empty() { - message = message.footer(Level::Note.title(&message_suffix)); - } - - let origin = format!("{}:{}", file, error.line); let snippet = Snippet::source(&error.line_buffer) .line_start(error.line) - .origin(&origin) + .path(format!("{file}:{}", error.line)) .fold(false) .annotations(annotation(error)); - message = message.snippet(snippet); - - writeln!(f, "{}\n", renderer.render(message))?; + let mut group = title.element(snippet); + if let Some(message_suffix) = error.msg_suffix() { + group = group.element(Level::NOTE.message(message_suffix)); + } else { + group = group.element(Padding); + } + writeln!(f, "{}\n", renderer.render(&[group]))?; } } @@ -85,26 +82,21 @@ impl<'a> Display for FormatReportFormatter<'a> { "rustfmt has failed to format. See previous {} errors.", self.report.warning_count() ); - let message = Level::Warning.title(&label); - writeln!(f, "{}", renderer.render(message))?; + let group = Group::with_title(Level::WARNING.primary_title(label)); + writeln!(f, "{}\n", renderer.render(&[group]))?; } - Ok(()) } } fn annotation(error: &FormattingError) -> Option> { - let (range_start, range_length) = error.format_len(); - let range_end = range_start + range_length; - - if range_length > 0 { - Some(Level::Error.span(range_start..range_end)) - } else { - None - } + error + .highlight + .clone() + .map(|range| AnnotationKind::Primary.span(range)) } -fn error_kind_to_snippet_annotation_level(error_kind: &ErrorKind) -> Level { +fn error_kind_to_snippet_annotation_level(error_kind: &ErrorKind) -> Level<'_> { match error_kind { ErrorKind::LineOverflow(..) | ErrorKind::TrailingWhitespace @@ -114,7 +106,7 @@ fn error_kind_to_snippet_annotation_level(error_kind: &ErrorKind) -> Level { | ErrorKind::LostComment | ErrorKind::BadAttr | ErrorKind::InvalidGlobPattern(_) - | ErrorKind::VersionMismatch => Level::Error, - ErrorKind::DeprecatedAttr => Level::Warning, + | ErrorKind::VersionMismatch => Level::ERROR, + ErrorKind::DeprecatedAttr => Level::WARNING, } } diff --git a/src/formatting.rs b/src/formatting.rs index 7f2a14f9e314b..2dadf8e65d297 100644 --- a/src/formatting.rs +++ b/src/formatting.rs @@ -2,6 +2,7 @@ use std::collections::HashMap; use std::io::{self, Write}; +use std::ops::Range; use std::time::{Duration, Instant}; use rustc_ast::ast; @@ -318,6 +319,8 @@ pub(crate) struct FormattingError { is_comment: bool, is_string: bool, pub(crate) line_buffer: String, + /// The byte range within `line_buffer` that the error should highlight + pub(crate) highlight: Option>, } impl FormattingError { @@ -328,6 +331,7 @@ impl FormattingError { kind, is_string: false, line_buffer: psess.span_to_first_line_string(span), + highlight: None, } } @@ -342,34 +346,14 @@ impl FormattingError { } } - pub(crate) fn msg_suffix(&self) -> &str { + pub(crate) fn msg_suffix(&self) -> Option<&str> { if self.is_comment || self.is_string { - "set `error_on_unformatted = false` to suppress \ - the warning against comments or string literals\n" + Some( + "set `error_on_unformatted = false` to suppress \ + the warning against comments or string literals", + ) } else { - "" - } - } - - // (space, target) - pub(crate) fn format_len(&self) -> (usize, usize) { - match self.kind { - ErrorKind::LineOverflow(found, max) => (max, found - max), - ErrorKind::TrailingWhitespace - | ErrorKind::DeprecatedAttr - | ErrorKind::BadAttr - | ErrorKind::LostComment => { - let trailing_ws_start = self - .line_buffer - .rfind(|c: char| !c.is_whitespace()) - .map(|pos| pos + 1) - .unwrap_or(0); - ( - trailing_ws_start, - self.line_buffer.len() - trailing_ws_start, - ) - } - _ => unreachable!(), + None } } } @@ -500,7 +484,8 @@ fn format_lines( struct FormatLines<'a> { name: &'a FileName, skipped_range: &'a [(usize, usize)], - last_was_space: bool, + whitespace_start: Option, + overflow_start: Option, line_len: usize, cur_line: usize, newline_count: usize, @@ -520,7 +505,8 @@ impl<'a> FormatLines<'a> { FormatLines { name, skipped_range, - last_was_space: false, + whitespace_start: None, + overflow_start: None, line_len: 0, cur_line: 1, newline_count: 0, @@ -550,7 +536,7 @@ impl<'a> FormatLines<'a> { fn new_line(&mut self, kind: FullCodeCharKind) { if self.format_line { // Check for (and record) trailing whitespace. - if self.last_was_space { + if let Some(whitespace_start) = self.whitespace_start { if self.should_report_error(kind, &ErrorKind::TrailingWhitespace) && !self.is_skipped_line() { @@ -558,9 +544,10 @@ impl<'a> FormatLines<'a> { ErrorKind::TrailingWhitespace, kind.is_comment(), kind.is_string(), + self.line_buffer.trim_end().len()..self.line_buffer.len(), ); } - self.line_len -= 1; + self.line_len = whitespace_start; } // Check for any line width errors we couldn't correct. @@ -570,7 +557,11 @@ impl<'a> FormatLines<'a> { && self.should_report_error(kind, &error_kind) { let is_string = self.current_line_contains_string_literal; - self.push_err(error_kind, kind.is_comment(), is_string); + let overflow_start = self + .overflow_start + .expect("overflow_start is set whenever the line exceeds max_width"); + let highlight = overflow_start..self.line_buffer.trim_end().len(); + self.push_err(error_kind, kind.is_comment(), is_string, highlight); } } @@ -581,32 +572,47 @@ impl<'a> FormatLines<'a> { .file_lines() .contains_line(self.name, self.cur_line); self.newline_count += 1; - self.last_was_space = false; + self.whitespace_start = None; + self.overflow_start = None; self.line_buffer.clear(); self.current_line_contains_string_literal = false; } fn char(&mut self, c: char, kind: FullCodeCharKind) { self.newline_count = 0; + if !c.is_whitespace() { + self.whitespace_start = None; + } else if self.whitespace_start.is_none() { + self.whitespace_start = Some(self.line_len); + } self.line_len += if c == '\t' { self.config.tab_spaces() } else { 1 }; - self.last_was_space = c.is_whitespace(); + if self.line_len > self.config.max_width() && self.overflow_start.is_none() { + self.overflow_start = Some(self.line_buffer.len()); + } self.line_buffer.push(c); if kind.is_string() { self.current_line_contains_string_literal = true; } } - fn push_err(&mut self, kind: ErrorKind, is_comment: bool, is_string: bool) { + fn push_err( + &mut self, + kind: ErrorKind, + is_comment: bool, + is_string: bool, + highlight: Range, + ) { self.errors.push(FormattingError { line: self.cur_line, kind, is_comment, is_string, line_buffer: self.line_buffer.clone(), + highlight: Some(highlight), }); } diff --git a/src/items.rs b/src/items.rs index a4719334fd5e6..37dc231c3c45a 100644 --- a/src/items.rs +++ b/src/items.rs @@ -1711,13 +1711,13 @@ pub(crate) fn rewrite_type_alias<'a>( match (visitor_kind, &op_ty) { (Item | AssocTraitItem | ForeignItem, Some(op_bounds)) => { let op = OpaqueType { bounds: op_bounds }; - rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis) + rewrite_ty(rw_info, Some(bounds), Some(&op), rhs_hi, vis, defaultness) } (Item | AssocTraitItem | ForeignItem, None) => { - rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis) + rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis, defaultness) } (AssocImplItem, _) => { - let result = if let Some(op_bounds) = op_ty { + if let Some(op_bounds) = op_ty { let op = OpaqueType { bounds: op_bounds }; rewrite_ty( rw_info, @@ -1725,13 +1725,10 @@ pub(crate) fn rewrite_type_alias<'a>( Some(&op), rhs_hi, &DEFAULT_VISIBILITY, + defaultness, ) } else { - rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis) - }?; - match defaultness { - ast::Defaultness::Default(..) => Ok(format!("default {result}")), - _ => Ok(result), + rewrite_ty(rw_info, Some(bounds), ty_opt, rhs_hi, vis, defaultness) } } } @@ -1744,10 +1741,15 @@ fn rewrite_ty( // the span of the end of the RHS (or the end of the generics, if there is no RHS) rhs_hi: BytePos, vis: &ast::Visibility, + defaultness: ast::Defaultness, ) -> RewriteResult { let mut result = String::with_capacity(128); let TyAliasRewriteInfo(context, indent, generics, after_where_clause, ident, span) = *rw_info; - result.push_str(&format!("{}type ", format_visibility(context, vis))); + result.push_str(&format!( + "{}{}type ", + format_visibility(context, vis), + format_defaultness(defaultness) + )); let ident_str = rewrite_ident(context, ident); if generics.params.is_empty() { @@ -2106,28 +2108,44 @@ fn rewrite_static( static_parts: &StaticParts<'_>, offset: Indent, ) -> Option { - // For now, if this static (or const) has generics, then bail. + // For now, if this static (or const) has a where clause, then bail. if static_parts .generics - .is_some_and(|g| !g.params.is_empty() || !g.where_clause.is_empty()) + .is_some_and(|g| !g.where_clause.is_empty()) { return None; } - + let generics = static_parts + .generics + .and_then(|g| { + format_generics( + context, + &g, + context.config.brace_style(), + BracePos::None, + offset, + // make a span that starts right after `const x` + mk_sp(static_parts.ident.span.hi(), static_parts.ty.span.lo()), + offset.block_indent, + ) + }) + .map_or("".into(), |x| format!("{x}")); let colon = colon_spaces(context.config); let mut prefix = format!( - "{}{}{}{} {}{}{}", + "{}{}{}{} {}{}{}{}", format_visibility(context, static_parts.vis), static_parts.defaultness.map_or("", format_defaultness), format_safety(static_parts.safety), static_parts.prefix, format_mutability(static_parts.mutability), rewrite_ident(context, static_parts.ident), - colon, + generics, + colon ); + // 2 = " =".len() - let ty_shape = - Shape::indented(offset.block_only(), context.config).offset_left_opt(prefix.len() + 2)?; + let ty_shape = Shape::indented(offset.block_only(), context.config) + .offset_left_opt(last_line_width(&prefix) + 2)?; let ty_str = match static_parts.ty.rewrite(context, ty_shape) { Some(ty_str) => ty_str, None => { @@ -2880,7 +2898,7 @@ fn rewrite_params( context .config .fn_params_layout() - .to_list_tactic(param_items.len()), + .to_list_tactic(context.config.style_edition(), param_items.len()), Separator::Comma, one_line_budget, ); diff --git a/src/lib.rs b/src/lib.rs index 65c83a612bf9f..f54d0641f4629 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -464,7 +464,7 @@ impl<'b, T: Write + 'b> Session<'b, T> { } /// The main entry point for Rustfmt. Formats the given input according to the - /// given config. `out` is only necessary if required by the configuration. + /// session's config. pub fn format(&mut self, input: Input) -> Result { self.format_input_inner(input, false) } diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 2654d2464eed3..0242094a75269 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -269,11 +269,7 @@ impl<'a> FmtVisitor<'a> { Indent::from_width(self.config, last_line_width(&self.buffer)) }; - let comment_width = ::std::cmp::min( - self.config.comment_width(), - self.config.max_width() - self.block_indent.width(), - ); - let comment_shape = Shape::legacy(comment_width, comment_indent); + let comment_shape = Shape::indented(comment_indent, self.config).comment(self.config); if on_same_line { match subslice.find('\n') { diff --git a/src/parse/macros/mod.rs b/src/parse/macros/mod.rs index 3d32821ce08b3..9afeed3c3ee2a 100644 --- a/src/parse/macros/mod.rs +++ b/src/parse/macros/mod.rs @@ -25,7 +25,9 @@ fn parse_macro_arg<'a, 'b: 'a>(parser: &'a mut Parser<'b>) -> Option { macro_rules! parse_macro_arg { ($macro_arg:ident, $nt_kind:expr, $try_parse:expr, $then:expr) => { let mut cloned_parser = (*parser).clone(); - if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) { + if Parser::nonterminal_may_begin_with($nt_kind, &cloned_parser.token) + || matches!(cloned_parser.token.kind, TokenKind::DocComment(..)) + { match $try_parse(&mut cloned_parser) { Ok(x) => { if parser.psess.dcx().has_errors().is_some() { diff --git a/src/patterns.rs b/src/patterns.rs index 62a72c4dc433e..dd0c09b6e9609 100644 --- a/src/patterns.rs +++ b/src/patterns.rs @@ -466,12 +466,19 @@ impl Rewrite for PatField { self.pat.rewrite_result(context, nested_shape)? ) }; + + let combine_shape = if context.config.style_edition() >= StyleEdition::Edition2027 { + shape + } else { + nested_shape + }; + combine_strs_with_missing_comments( context, &attrs_str, &pat_and_id_str, - mk_sp(hi_pos, self.pat.span.lo()), - nested_shape, + mk_sp(hi_pos, self.ident.span.lo()), + combine_shape, false, ) } diff --git a/src/test/mod.rs b/src/test/mod.rs index 201a581549914..213c43d888781 100644 --- a/src/test/mod.rs +++ b/src/test/mod.rs @@ -19,7 +19,7 @@ use crate::{ }; use rustfmt_config_proc_macro::nightly_only_test; -use tracing::{debug, warn}; +use tracing::debug; mod configuration_snippet; mod mod_resolver; @@ -249,6 +249,47 @@ fn system_tests() { }); } +// Check formatting-specific warning/error emissions against snapshots. +#[test] +fn warning_tests() { + init_log(); + let manifest_dir = Path::new(env!("CARGO_MANIFEST_DIR")); + let manifest_dir_filter = regex::escape(manifest_dir.to_string_lossy().as_ref()); + let files = get_test_files(Path::new("tests/warning/source"), true); + + for file in &files { + let mut config = read_config(file); + config.set().error_on_line_overflow(true); + config.set().error_on_unformatted(true); + + let snapshot_name = file.file_stem().unwrap().to_str().unwrap(); + let (parsing_errors, _, report) = format_file(file, config.clone()); + assert!(!parsing_errors, "{} failed to parse", file.display()); + assert!( + report.has_warnings(), + "{} did not emit a warning or error", + file.display() + ); + let warning = FormatReportFormatterBuilder::new(&report) + .build() + .to_string(); + + insta::with_settings!({ + snapshot_path => manifest_dir.join("tests/warning/snapshots"), + prepend_module_to_snapshot => false, + omit_expression => true, + filters => vec![ + (manifest_dir_filter.as_str(), "$$DIR"), + (r"\r\n", "\n"), + (r"\\", "/"), + ], + strip_ansi_escape_codes => true, + }, { + insta::assert_snapshot!(snapshot_name, warning); + }); + } +} + // Do the same for tests/coverage-source directory. // The only difference is the coverage mode. #[test] @@ -445,7 +486,7 @@ fn self_tests() { files.push(path); } // for crates that need to be included but lies outside src - let external_crates = vec!["check_diff", "config_proc_macro"]; + let external_crates = vec!["check_diff", "config_proc_macro", "ci"]; for external_crate in external_crates { let mut path = PathBuf::from(external_crate); path.push("src"); @@ -463,6 +504,9 @@ fn self_tests() { for file in search_files { files.push(file); } + + let mut tests_files = get_test_files(&PathBuf::from(external_crate).join("tests"), true); + files.append(&mut tests_files); } files.push(PathBuf::from("src/lib.rs")); @@ -586,7 +630,9 @@ fn stdin_parser_panic_caught() { // See issue #3239. for text in ["{", "}"].iter().cloned().map(String::from) { let mut buf = vec![]; - let mut session = Session::new(Default::default(), Some(&mut buf)); + let mut config = Config::default(); + config.set().show_parse_errors(false); + let mut session = Session::new(config, Some(&mut buf)); let _ = session.format(Input::Text(text)); assert!(session.has_parsing_errors()); @@ -835,9 +881,6 @@ fn read_config(filename: &Path) -> Config { for (key, val) in &sig_comments { if key != "target" && key != "config" && key != "unstable" && key != "stable" { config.override_value(key, val); - if config.is_default(key) { - warn!("Default value {} used explicitly for {}", val, key); - } } } diff --git a/src/test/parser.rs b/src/test/parser.rs index 903d4e4862573..04b4d3b362b0c 100644 --- a/src/test/parser.rs +++ b/src/test/parser.rs @@ -6,13 +6,20 @@ use super::read_config; use crate::modules::{ModuleResolutionError, ModuleResolutionErrorKind}; use crate::{ErrorKind, Input, Session}; +/// Load the config, but hide expected parse errors +fn read_config_hide_parse_errors(filename: &std::path::Path) -> crate::Config { + let mut config = read_config(&filename); + config.set().show_parse_errors(false); + config +} + #[test] fn parser_errors_in_submods_are_surfaced() { // See also https://github.com/rust-lang/rustfmt/issues/4126 let filename = "tests/parser/issue-4126/lib.rs"; let input_file = PathBuf::from(filename); let exp_mod_name = "invalid"; - let config = read_config(&input_file); + let config = read_config_hide_parse_errors(&input_file); let mut session = Session::::new(config, None); if let Err(ErrorKind::ModuleResolutionError(ModuleResolutionError { module, kind })) = session.format(Input::File(filename.into())) @@ -36,7 +43,7 @@ fn parser_errors_in_submods_are_surfaced() { fn assert_parser_error(filename: &str) { let file = PathBuf::from(filename); - let config = read_config(&file); + let config = read_config_hide_parse_errors(&file); let mut session = Session::::new(config, None); let _ = session.format(Input::File(filename.into())).unwrap(); assert!(session.has_parsing_errors()); diff --git a/src/types.rs b/src/types.rs index 9edfa2cf438fe..b8e072c7c6956 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1122,7 +1122,7 @@ fn rewrite_fn_ptr( &fn_ptr.decl.inputs, &fn_ptr.decl.output, fn_ptr.decl.c_variadic(), - span, + fn_ptr.decl_span, context, func_ty_shape, )?; diff --git a/tests/cargo-fmt/source/issues_6517/Cargo.toml b/tests/cargo-fmt/source/issues_6517/Cargo.toml new file mode 100644 index 0000000000000..7667843cf7548 --- /dev/null +++ b/tests/cargo-fmt/source/issues_6517/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["inner_bin", "inner_lib"] diff --git a/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml b/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml new file mode 100644 index 0000000000000..bb6a80cd0ce9b --- /dev/null +++ b/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inner_bin" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs b/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs new file mode 100644 index 0000000000000..e7a11a969c037 --- /dev/null +++ b/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello, world!"); +} diff --git a/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml b/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml new file mode 100644 index 0000000000000..c9ddf1793b88f --- /dev/null +++ b/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inner_lib" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs b/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs new file mode 100644 index 0000000000000..b93cf3ffd9cc9 --- /dev/null +++ b/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs @@ -0,0 +1,14 @@ +pub fn add(left: u64, right: u64) -> u64 { + left + right +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn it_works() { + let result = add(2, 2); + assert_eq!(result, 4); + } +} diff --git a/tests/rustfmt/main.rs b/tests/rustfmt/main.rs index 4008c8d14357c..ee972d8a6afb7 100644 --- a/tests/rustfmt/main.rs +++ b/tests/rustfmt/main.rs @@ -5,7 +5,7 @@ use std::fs::{File, remove_file}; use std::path::Path; use std::process::Command; -use rustfmt_config_proc_macro::{nightly_only_test, rustfmt_only_ci_test}; +use rustfmt_config_proc_macro::{nightly_only_test, rustfmt_only_ci_test, stable_only_test}; /// Run the rustfmt executable with environment vars set and return its output. fn rustfmt_with_extra( @@ -117,11 +117,112 @@ fn inline_config() { ); } +#[stable_only_test] #[test] fn rustfmt_usage_text() { let args = ["--help"]; let (stdout, _) = rustfmt(&args); - assert!(stdout.contains("Format Rust code\n\nusage: rustfmt [options] ...")); + insta::assert_snapshot!(stdout, @" + Format Rust code + + usage: rustfmt [options] ... + + Options: + --check Run in 'check' mode. Exits with 0 if input is + formatted correctly. Exits with 1 and prints a diff if + formatting is required. + --emit [files|stdout] + What data to emit and how + --backup Backup any modified files. + --config-path [Path for the configuration file] + Recursively searches the given path for the + rustfmt.toml config file. If not found reverts to the + input file path + --edition [2015|2018|2021|2024] + Rust edition to use + --color [always|never|auto] + Use colored output (if supported) + --print-config [default|minimal|current] PATH + Dumps a default or minimal config to PATH. A minimal + config is the subset of the current config file used + for formatting the current program. `current` writes + to stdout current config as if formatting the file at + PATH. + -l, --files-with-diff + Prints the names of mismatched files that were + formatted. Prints the names of files that would be + formatted when used with `--check` mode. + --config [key1=val1,key2=val2...] + Set options from command line. These settings take + priority over .rustfmt.toml + --style-edition [2015|2018|2021|2024] + The edition of the Style Guide. + -v, --verbose Print verbose output + -q, --quiet Print less output + -V, --version Show version information + -h, --help [=TOPIC] Show this message or help about a specific topic: + `config` + "); +} + +#[nightly_only_test] +#[test] +fn rustfmt_nightly_usage_text() { + let args = ["--help"]; + let (stdout, _) = rustfmt(&args); + insta::assert_snapshot!(stdout, @" + Format Rust code + + usage: rustfmt [options] ... + + Options: + --check Run in 'check' mode. Exits with 0 if input is + formatted correctly. Exits with 1 and prints a diff if + formatting is required. + --emit [files|stdout|coverage|checkstyle|json] + What data to emit and how + --backup Backup any modified files. + --config-path [Path for the configuration file] + Recursively searches the given path for the + rustfmt.toml config file. If not found reverts to the + input file path + --edition [2015|2018|2021|2024] + Rust edition to use + --color [always|never|auto] + Use colored output (if supported) + --print-config [default|minimal|current] PATH + Dumps a default or minimal config to PATH. A minimal + config is the subset of the current config file used + for formatting the current program. `current` writes + to stdout current config as if formatting the file at + PATH. + -l, --files-with-diff + Prints the names of mismatched files that were + formatted. Prints the names of files that would be + formatted when used with `--check` mode. + --config [key1=val1,key2=val2...] + Set options from command line. These settings take + priority over .rustfmt.toml + --style-edition [2015|2018|2021|2024] + The edition of the Style Guide. + --unstable-features + Enables unstable features. Only available on nightly + channel. + --file-lines JSON + Format specified line ranges. Run with + `--help=file-lines` for more detail (unstable). + --error-on-unformatted + Error if unable to get comments or string literals + within max_width, or they are left with trailing + whitespaces (unstable). + --skip-children + Don't reformat child modules (unstable). + -v, --verbose Print verbose output + -q, --quiet Print less output + -V, --version Show version information + -h, --help [=TOPIC] Show this message or help about a specific topic: + `config` or `file-lines` + "); } #[test] diff --git a/tests/source/configs/fn_params_layout/vertical.rs b/tests/source/configs/fn_params_layout/vertical.rs index 674968023f997..9f4ea419d9cb9 100644 --- a/tests/source/configs/fn_params_layout/vertical.rs +++ b/tests/source/configs/fn_params_layout/vertical.rs @@ -2,6 +2,10 @@ // Function arguments density trait Lorem { + fn lorem(ipsum: Ipsum); + + fn lorem(ipsum: Ipsum) -> Dolor; + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { @@ -13,4 +17,22 @@ trait Lorem { fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { // body } + + fn long_param_name(lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod: Tempor); + + fn long_param_type(lorem: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore, + ); + + fn long_return_type(lorem: Lorem) + -> IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore; + + fn lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod_tempor_incididunt + (lorem: Lorem); + + fn lorem(t: T); + + fn lorem + ( + t: T, + ); } diff --git a/tests/source/configs/fn_params_layout/vertical_style_2027.rs b/tests/source/configs/fn_params_layout/vertical_style_2027.rs new file mode 100644 index 0000000000000..07c6905ed5ea4 --- /dev/null +++ b/tests/source/configs/fn_params_layout/vertical_style_2027.rs @@ -0,0 +1,39 @@ +// rustfmt-style_edition: 2027 +// rustfmt-fn_params_layout: Vertical +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum); + + fn lorem(ipsum: Ipsum) -> Dolor; + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet) { + // body + } + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit); + + fn lorem(ipsum: Ipsum, dolor: Dolor, sit: Sit, amet: Amet, consectetur: onsectetur, adipiscing: Adipiscing, elit: Elit) { + // body + } + + fn long_param_name(lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod: Tempor); + + fn long_param_type(lorem: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore, + ); + + fn long_return_type(lorem: Lorem) + -> IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore; + + fn lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod_tempor_incididunt + (lorem: Lorem); + + fn lorem(t: T); + + fn lorem + ( + t: T, + ); +} diff --git a/tests/source/generic_static.rs b/tests/source/generic_static.rs new file mode 100644 index 0000000000000..3702daed00813 --- /dev/null +++ b/tests/source/generic_static.rs @@ -0,0 +1,5 @@ +#![feature(generic_const_items)] +pub const SORT: + &[T]= const { 4}; + +pub const SORT: &[T] = const { 4 }; diff --git a/tests/source/imports_granularity_one.rs b/tests/source/imports/imports_granularity_one.rs similarity index 100% rename from tests/source/imports_granularity_one.rs rename to tests/source/imports/imports_granularity_one.rs diff --git a/tests/source/issue-5023.rs b/tests/source/issue-5023.rs index ae1c723eff76a..2a6f4a90aa980 100644 --- a/tests/source/issue-5023.rs +++ b/tests/source/issue-5023.rs @@ -1,5 +1,15 @@ // rustfmt-wrap_comments: true +// below we try and force a split at a byte in the middle of a multi-byte +// character. The two parts of the first line are constructed such that: +// 1) the entire line is longer than `$comment_width` +// 2) the length of the second part is such that: +// `$comment_width - 3 + $length` is positive _and_ less than the number of +// bytes in the multi-byte char + +// xxxxxxxxxx xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// 是 + /// A comment to test special unicode characters on boundaries /// 是,是,是,是,是,是,是,是,是,是,是,是 it should break right here this goes to the next line fn main() { diff --git a/tests/source/issue-6795.rs b/tests/source/issue-6795.rs new file mode 100644 index 0000000000000..d1263ffc5d9ee --- /dev/null +++ b/tests/source/issue-6795.rs @@ -0,0 +1,40 @@ +// rustfmt-use_field_init_shorthand: true + +foo!(Foo { a: a }); + +fn main() { + foo!(Foo { a: a }); + foo![Foo { a: a }]; + foo! { Foo { a: a } } + + seq!(Task { a }); + seq!(Task { a: b }); + seq!(Task { a: 1 }); + seq!(Task { a: a, ..base }); + seq!(Task { #[attr] a: a }); + seq!(Task { a: Inner { b: b } }); + seq!(Task { a: a }.build()); + let _ = Foo { a: seq!(Task { b: b }) }; + + // `vec!` is formatted as an array, so the shorthand still applies. + vec![Foo { a: a }]; + vec![vec![Foo { a: a }]]; + foo!(vec![Foo { a: a }]); + + // std/core prelude macros, where the shorthand would be safe. + assert_eq!(Foo { a: a }, x); + debug_assert_eq!(Foo { a: a }, x); + matches!(v, Foo { a: a }); + assert_matches!(v, Foo { a: a }); + assert!(matches!(v, Foo { a: a })); + + // A shorthand already written by hand is kept. + assert_eq!(Foo { a }, x); + debug_assert_eq!(Foo { a }, x); + matches!(v, Foo { a }); + assert_matches!(v, Foo { a }); + assert!(matches!(v, Foo { a })); + + let _ = Foo { a: a }; + let _ = Foo { a: Inner { b: b } }; +} diff --git a/tests/source/issue-6985.rs b/tests/source/issue-6985.rs new file mode 100644 index 0000000000000..73e9fc8de4b32 --- /dev/null +++ b/tests/source/issue-6985.rs @@ -0,0 +1,21 @@ +macro_rules ! say_hello { + () => { + println!("Hello!") + }; +} + +macro_rules /* comment */ ! say_goodbye { + () => { + println!("Goodbye!") + }; +} + +macro_rules // comment +! do_nothing { + () => {}; +} + +fn main() { + say_hello!(); + say_goodbye!() +} diff --git a/tests/source/issue-7011.rs b/tests/source/issue-7011.rs new file mode 100644 index 0000000000000..e83631d9230bf --- /dev/null +++ b/tests/source/issue-7011.rs @@ -0,0 +1,7 @@ +fn main() { + || 1.. .field; + || 1.. ?.field; + || 1.. .await; + || 1.. .use; + || 1.. .yield; +} diff --git a/tests/source/issue-7054.rs b/tests/source/issue-7054.rs new file mode 100644 index 0000000000000..3ae28c2132963 --- /dev/null +++ b/tests/source/issue-7054.rs @@ -0,0 +1,153 @@ +// rustfmt-edition: 2018 + +// `for await` is spelled with two tokens, so the source may separate them with +// arbitrary whitespace or comments. rustfmt must not search for the rendered +// keyword `for await` as a single literal string. + +#![feature(async_iterator, async_for_loop)] + +async fn for_await_canonical(iter: Iter) { + for await i in iter {} +} + +async fn for_await_extra_spaces(iter: Iter) { + for await i in iter {} +} + +async fn for_await_newline(iter: Iter) { + for + await i in iter {} +} + +async fn for_await_comment_between_keywords(iter: Iter) { + for /* between for and await */ await i in iter {} +} + +async fn for_await_comment_after_keyword(iter: Iter) { + for await /* between await and pat */ i in iter {} +} + +async fn for_await_comment_both_gaps(iter: Iter) { + for /* first gap */ await /* second gap */ i in iter {} +} + +async fn for_multi_line_comment_await(iter: Iter) { + for /* some + * multi-line + * comment */ await + i in iter {} +} + +async fn for_comment_await_comment_(iter: Iter) { + for /* some + * multi-line + * comment */ await +/* some + * multi-line + * comment */ + i in iter {} +} + +async fn for_await_comment_with_long_iterator(iter: Iter) { + for /* some + * multi-line + * comment */ await + i in some_really_long_iterator_expression(alpha, beta, gamma, delta) {} +} + +async fn for_await_comment_exceeding_line_budget(iter: Iter) { + for /* some + * multi-line + * comment + * that keeps + * going on + * and on + * past ninety + * six bytes */ + await + i in iter {} +} + +async fn for_await_line_comment_between_keywords(iter: Iter) { + for // between for and await + await i in iter {} +} + +async fn for_await_multiple_line_comments_between_keywords_with_spaces(iter: Iter) { + for // first line + // second line + await i in iter {} +} + +async fn for_await_line_comment_after_keyword(iter: Iter) { + for await // between await and pat + i in iter {} +} + +async fn for_await_line_comments_both_gaps(iter: Iter) { + for // first gap + await // second gap + i in iter {} +} + +async fn for_await_labeled(iter: Iter) { + 'outer: for await i in iter {} +} + +async fn for_await_labeled(iter: Iter) { + 'outer: for // line comment + await i in iter {} +} + +async fn for_await_labeled_multi_line_comment(iter: Iter) { + 'outer: for /* some + * multi-line + * comment */ await + i in iter {} +} + + +async fn for_await_body(iter: Iter) { + for await i in iter { + do_something(i); + } +} + +// Single-token keywords must be unaffected by the change. + +fn plain_for(iter: Iter) { + for i in iter {} + for /* comment */ i in iter {} + for // line comment + i in iter {} + 'outer: for i in iter {} +} + +fn plain_while(cond: bool) { + while cond {} + while /* comment */ cond {} + while // line comment + cond {} + 'outer: while cond {} +} + +fn plain_while_let(opt: Opt) { + while let Some(x) = opt {} + while /* comment */ let Some(x) = opt {} + while // line comment + let Some(x) = opt {} +} + +fn plain_loop() { + loop {} + 'outer: loop {} +} + +fn plain_if(cond: bool) { + if cond {} + if /* comment */ cond {} + if // line comment + cond {} + if let Some(x) = opt {} +} + diff --git a/tests/source/issue_4037.rs b/tests/source/issue_4037.rs new file mode 100644 index 0000000000000..56dab88c69485 --- /dev/null +++ b/tests/source/issue_4037.rs @@ -0,0 +1,24 @@ +fn f() { + let x = 0; + match x { + 0 => {} + + + 1 => {} + _ => {} + + + // foo + // bar, + } +} + +fn wont_fmt() -> [(); 1] { + [ + () + + + // + // , + ] +} diff --git a/tests/source/issue_5920_style_edition_2024.rs b/tests/source/issue_5920_style_edition_2024.rs new file mode 100644 index 0000000000000..7002338f9fc50 --- /dev/null +++ b/tests/source/issue_5920_style_edition_2024.rs @@ -0,0 +1,25 @@ +// rustfmt-style_edition: 2024 + +struct Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), +} + +fn main() { + let Demo { + field_name_foo, + #[cfg(feature = "diagnostics")] + field_name_baz: _, + field_name_bar, + field_name_tux, + } = Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), + }; +} diff --git a/tests/source/issue_5920_style_edition_2027.rs b/tests/source/issue_5920_style_edition_2027.rs new file mode 100644 index 0000000000000..9d040a37699e3 --- /dev/null +++ b/tests/source/issue_5920_style_edition_2027.rs @@ -0,0 +1,25 @@ +// rustfmt-style_edition: 2027 + +struct Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), +} + +fn main() { + let Demo { + field_name_foo, + #[cfg(feature = "diagnostics")] + field_name_baz: _, + field_name_bar, + field_name_tux, + } = Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), + }; +} diff --git a/tests/source/issue_5982_style_edition_2024.rs b/tests/source/issue_5982_style_edition_2024.rs new file mode 100644 index 0000000000000..01d6a92a4501d --- /dev/null +++ b/tests/source/issue_5982_style_edition_2024.rs @@ -0,0 +1,39 @@ +// rustfmt-style_edition: 2024 + +struct Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: i32, + #[cfg(all())] + something_long_enough_to_wrap_bar: i32, +} + +fn example() { + let Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo, + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} + +// The same, but with leading comments on the fields. +fn example_with_comments() { + let Foo { + // comment on shorthand field + #[cfg(all())] + something_long_enough_to_wrap_foo, + // comment on non-shorthand field + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} diff --git a/tests/source/issue_5982_style_edition_2027.rs b/tests/source/issue_5982_style_edition_2027.rs new file mode 100644 index 0000000000000..f622cd89b47e5 --- /dev/null +++ b/tests/source/issue_5982_style_edition_2027.rs @@ -0,0 +1,39 @@ +// rustfmt-style_edition: 2027 + +struct Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: i32, + #[cfg(all())] + something_long_enough_to_wrap_bar: i32, +} + +fn example() { + let Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo, + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} + +// The same, but with leading comments on the fields. +fn example_with_comments() { + let Foo { + // comment on shorthand field + #[cfg(all())] + something_long_enough_to_wrap_foo, + // comment on non-shorthand field + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} diff --git a/tests/source/issue_6209.rs b/tests/source/issue_6209.rs new file mode 100644 index 0000000000000..78333d1d5cad5 --- /dev/null +++ b/tests/source/issue_6209.rs @@ -0,0 +1,33 @@ +fn while_loop() { + thread::spawn(|| { while i < days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + i += 1; + }}); +} + +fn for_loop() { + thread::spawn(|| { for i in 0..days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + }}); +} + +fn empty_loop_body() { + thread::spawn(|| { while true { + #![allow(clippy::indexing_slicing)] + }}); +} + +fn closure_body_without_block() { + thread::spawn(|| while i < days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + }); +} + +fn outer_attribute_still_formatted() { + thread::spawn(|| { #[allow(clippy::indexing_slicing)] while i < days.len() { + w |= days[i].bit_value(); + }}); +} diff --git a/tests/source/issue_6801.rs b/tests/source/issue_6801.rs new file mode 100644 index 0000000000000..a53c2b305e5ba --- /dev/null +++ b/tests/source/issue_6801.rs @@ -0,0 +1,52 @@ +// rustfmt-wrap_comments: true +// rustfmt-comment_width: 80 +// rustfmt-max_width: 200 + +fn foo() { + // In this line, the next '.' is exactly at'comment_width' . It should break on that dot + + // In this line, 'comment_width' is reached in the middle of ThisVeryLongWord. It should break before that word + + { + { + { + { + // again 'comment_width' is just at the next '.' . Here's some more stuff + fn f1() { + fn f2() { + fn f3() { + fn f4() { + fn f5() { + fn f6() { + fn f7() { + fn f8() { + fn f9() { + fn f10() { + fn f11() { + // again . Deeply nested comment + fn f12() { + fn f13() { + fn f14() { + fn f15() { + // indentation means this comment starts after 'comment_width' + // we don't touch this comment + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/tests/source/issue_7003_style_edition_2024.rs b/tests/source/issue_7003_style_edition_2024.rs new file mode 100644 index 0000000000000..f2e21df15dadc --- /dev/null +++ b/tests/source/issue_7003_style_edition_2024.rs @@ -0,0 +1,14 @@ +// rustfmt-style_edition: 2024 + +fn main() { + _ = if let Some(term_node) = sema + .token_ancestors_with_macros(token.clone()) + .find(|node| { + matches!( + node.kind(), + BLOCK_EXPR | ARG_LIST | PAREN_EXPR | ARRAY_EXPR | MATCH_EXPR + ) + }) { + match term_node.kind() {} + }; +} diff --git a/tests/source/issue_7003_style_edition_2027.rs b/tests/source/issue_7003_style_edition_2027.rs new file mode 100644 index 0000000000000..eecbd1f42fcaa --- /dev/null +++ b/tests/source/issue_7003_style_edition_2027.rs @@ -0,0 +1,14 @@ +// rustfmt-style_edition: 2027 + +fn main() { + _ = if let Some(term_node) = sema + .token_ancestors_with_macros(token.clone()) + .find(|node| { + matches!( + node.kind(), + BLOCK_EXPR | ARG_LIST | PAREN_EXPR | ARRAY_EXPR | MATCH_EXPR + ) + }) { + match term_node.kind() {} + }; +} diff --git a/tests/source/issue_7036.rs b/tests/source/issue_7036.rs new file mode 100644 index 0000000000000..8bc7cadbbd0bd --- /dev/null +++ b/tests/source/issue_7036.rs @@ -0,0 +1,157 @@ +// Doc comments inside macro calls should not prevent formatting. +// +// Each comment form below is tested three ways: on its own, after an +// attribute, and before an attribute. + +foo!( + // Only a comment + A, + B, +); + +foo!( + #[doc = ""] + // Only a comment + A, + B, +); + +foo!( + // Only a comment + #[doc = ""] + A, + B, +); + + +foo!( + /// Outer line doc (exactly 3 slashes) + A, + B, +); + +foo!( + #[doc = ""] + /// Outer line doc (exactly 3 slashes) + A, + B, +); + +foo!( + /// Outer line doc (exactly 3 slashes) + #[doc = ""] + A, + B, +); + + +foo!( + //// Only a comment + A, + B, +); + +foo!( + #[doc = ""] + //// Only a comment + A, + B, +); + +foo!( + //// Only a comment + #[doc = ""] + A, + B, +); + + +foo!( + /* Only a comment */ + A, + B, +); + +foo!( + #[doc = ""] + /* Only a comment */ + A, + B, +); + +foo!( + /* Only a comment */ + #[doc = ""] + A, + B, +); + + +foo!( + /** Outer block doc (exactly 2 asterisks) */ + A, + B, +); + +foo!( + #[doc = ""] + /** Outer block doc (exactly 2 asterisks) */ + A, + B, +); + +foo!( + /** Outer block doc (exactly 2 asterisks) */ + #[doc = ""] + A, + B, +); + + +foo!( + /*** Only a comment */ + A, + B, +); + +foo!( + #[doc = ""] + /*** Only a comment */ + A, + B, +); + +foo!( + /*** Only a comment */ + #[doc = ""] + A, + B, +); + + +// Inner doc comments cannot attach to a macro argument, so these are left +// unformatted on purpose. + +foo!( + //! Inner line doc + A, + B, +); + +foo!( + //!! Still an inner line doc (but with a bang at the beginning) + A, + B, +); + +foo!( + /*! Inner block doc */ + A, + B, +); + +foo!( + /*!! Still an inner block doc (but with a bang at the beginning) */ + A, + B, +); \ No newline at end of file diff --git a/tests/source/macros.rs b/tests/source/macros.rs index 3b286579ca8f1..2bcb8a787a223 100644 --- a/tests/source/macros.rs +++ b/tests/source/macros.rs @@ -484,3 +484,10 @@ f!(match a { // #3583 foo!(|x = y|); + +// #3757 +f!(match a { + _ => ( ), +}); + +g!( 1, 2, 3 ); diff --git a/tests/source/string_lit_unicode_ws.rs b/tests/source/string_lit_unicode_ws.rs index f944711e14f39..fff135fbc4fdf 100644 --- a/tests/source/string_lit_unicode_ws.rs +++ b/tests/source/string_lit_unicode_ws.rs @@ -1,3 +1,5 @@ +// rustfmt-show_parse_errors: false + // Test Unicode whitespace characters in string literal line continuation fn main() { let str = "hello \ diff --git a/tests/target/configs/fn_params_layout/vertical.rs b/tests/target/configs/fn_params_layout/vertical.rs index 7a0e42415f3b9..b1ae5710843fb 100644 --- a/tests/target/configs/fn_params_layout/vertical.rs +++ b/tests/target/configs/fn_params_layout/vertical.rs @@ -2,6 +2,10 @@ // Function arguments density trait Lorem { + fn lorem(ipsum: Ipsum); + + fn lorem(ipsum: Ipsum) -> Dolor; + fn lorem( ipsum: Ipsum, dolor: Dolor, @@ -39,4 +43,30 @@ trait Lorem { ) { // body } + + fn long_param_name( + lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod: Tempor + ); + + fn long_param_type( + lorem: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore + ); + + fn long_return_type( + lorem: Lorem + ) -> IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore; + + fn lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod_tempor_incididunt( + lorem: Lorem + ); + + fn lorem( + t: T + ); + + fn lorem< + T: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLaboreEtDolore, + >( + t: T + ); } diff --git a/tests/target/configs/fn_params_layout/vertical_style_2027.rs b/tests/target/configs/fn_params_layout/vertical_style_2027.rs new file mode 100644 index 0000000000000..838940a9689c9 --- /dev/null +++ b/tests/target/configs/fn_params_layout/vertical_style_2027.rs @@ -0,0 +1,73 @@ +// rustfmt-style_edition: 2027 +// rustfmt-fn_params_layout: Vertical +// Function arguments density + +trait Lorem { + fn lorem(ipsum: Ipsum); + + fn lorem(ipsum: Ipsum) -> Dolor; + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + ) { + // body + } + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ); + + fn lorem( + ipsum: Ipsum, + dolor: Dolor, + sit: Sit, + amet: Amet, + consectetur: onsectetur, + adipiscing: Adipiscing, + elit: Elit, + ) { + // body + } + + fn long_param_name( + lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod: Tempor, + ); + + fn long_param_type( + lorem: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore, + ); + + fn long_return_type( + lorem: Lorem, + ) -> IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLabore; + + fn lorem_ipsum_dolor_sit_amet_consectetur_adipiscing_elit_sed_do_eiusmod_tempor_incididunt( + lorem: Lorem, + ); + + fn lorem( + t: T, + ); + + fn lorem< + T: IpsumDolorSitAmetConsecteturAdipiscingElitSedDoEiusmodTemporIncididuntUtLaboreEtDolore, + >( + t: T, + ); +} diff --git a/tests/target/generic_static.rs b/tests/target/generic_static.rs new file mode 100644 index 0000000000000..b8593760ef0e0 --- /dev/null +++ b/tests/target/generic_static.rs @@ -0,0 +1,12 @@ +#![feature(generic_const_items)] +pub const SORT: &[T] = const { 4 }; + +pub const SORT< + AAAAAAAAAAAAAAAAAAAA, + BBBBBBBBBBBBBBBBBBBb, + CCCCCCCCCCCCCCCCCCC, + DDDDDDDDDDDDDDDDDDDDD, + EEEEEEEEEEEE, + FFFFF, + G, +>: &[T] = const { 4 }; diff --git a/tests/target/imports_granularity_one.rs b/tests/target/imports/imports_granularity_one.rs similarity index 100% rename from tests/target/imports_granularity_one.rs rename to tests/target/imports/imports_granularity_one.rs diff --git a/tests/target/issue-5023.rs b/tests/target/issue-5023.rs index 4e84c7d98427a..aca47d0f4a95c 100644 --- a/tests/target/issue-5023.rs +++ b/tests/target/issue-5023.rs @@ -1,5 +1,16 @@ // rustfmt-wrap_comments: true +// below we try and force a split at a byte in the middle of a multi-byte +// character. The two parts of the first line are constructed such that: +// 1) the entire line is longer than `$comment_width` +// 2) the length of the second part is such that: +// `$comment_width - 3 + $length` is positive _and_ less than the number of +// bytes in the multi-byte char + +// xxxxxxxxxx +// xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx +// 是 + /// A comment to test special unicode characters on boundaries /// 是,是,是,是,是,是,是,是,是,是,是,是 it should break right here /// this goes to the next line @@ -9,8 +20,9 @@ fn main() { .into_iter() .filter(|(xxx, xxx)| { if let Some(x) = Some(1) { - // xxxxxxxxxxxxxxxxxx, xxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxx xxx xxxxxxx, xxxxx xxx - // xxxxxxxxxx. xxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxx xxx xxxxxxx + // xxxxxxxxxxxxxxxxxx, xxxxxxxxxxxx, xxxxxxxxxxxxxxxxxxxx + // xxx xxxxxxx, xxxxx xxx xxxxxxxxxx. + // xxxxxxxxxxxxxxxx,xxxxxxxxxxxxxxxxx xxx xxxxxxx // 是sdfadsdfxxxxxxxxx,sdfaxxxxxx_xxxxx_masdfaonxxx, if false { return true; diff --git a/tests/target/issue-6795.rs b/tests/target/issue-6795.rs new file mode 100644 index 0000000000000..7de2d1140fb5d --- /dev/null +++ b/tests/target/issue-6795.rs @@ -0,0 +1,45 @@ +// rustfmt-use_field_init_shorthand: true + +foo!(Foo { a: a }); + +fn main() { + foo!(Foo { a: a }); + foo![Foo { a: a }]; + foo! { Foo { a: a } } + + seq!(Task { a }); + seq!(Task { a: b }); + seq!(Task { a: 1 }); + seq!(Task { a: a, ..base }); + seq!(Task { + #[attr] + a: a + }); + seq!(Task { a: Inner { b: b } }); + seq!(Task { a: a }.build()); + let _ = Foo { + a: seq!(Task { b: b }), + }; + + // `vec!` is formatted as an array, so the shorthand still applies. + vec![Foo { a }]; + vec![vec![Foo { a }]]; + foo!(vec![Foo { a: a }]); + + // std/core prelude macros, where the shorthand would be safe. + assert_eq!(Foo { a: a }, x); + debug_assert_eq!(Foo { a: a }, x); + matches!(v, Foo { a: a }); + assert_matches!(v, Foo { a: a }); + assert!(matches!(v, Foo { a: a })); + + // A shorthand already written by hand is kept. + assert_eq!(Foo { a }, x); + debug_assert_eq!(Foo { a }, x); + matches!(v, Foo { a }); + assert_matches!(v, Foo { a }); + assert!(matches!(v, Foo { a })); + + let _ = Foo { a }; + let _ = Foo { a: Inner { b } }; +} diff --git a/tests/target/issue-6985.rs b/tests/target/issue-6985.rs new file mode 100644 index 0000000000000..b799937f6f521 --- /dev/null +++ b/tests/target/issue-6985.rs @@ -0,0 +1,20 @@ +macro_rules! say_hello { + () => { + println!("Hello!") + }; +} + +macro_rules! say_goodbye { + () => { + println!("Goodbye!") + }; +} + +macro_rules! do_nothing { + () => {}; +} + +fn main() { + say_hello!(); + say_goodbye!() +} diff --git a/tests/target/issue-7011.rs b/tests/target/issue-7011.rs new file mode 100644 index 0000000000000..b6f147bd94cdc --- /dev/null +++ b/tests/target/issue-7011.rs @@ -0,0 +1,7 @@ +fn main() { + (|| 1..).field; + || 1..?.field; + (|| 1..).await; + (|| 1..).use; + (|| 1..).yield; +} diff --git a/tests/target/issue-7054.rs b/tests/target/issue-7054.rs new file mode 100644 index 0000000000000..754c0379c7677 --- /dev/null +++ b/tests/target/issue-7054.rs @@ -0,0 +1,168 @@ +// rustfmt-edition: 2018 + +// `for await` is spelled with two tokens, so the source may separate them with +// arbitrary whitespace or comments. rustfmt must not search for the rendered +// keyword `for await` as a single literal string. + +#![feature(async_iterator, async_for_loop)] + +async fn for_await_canonical(iter: Iter) { + for await i in iter {} +} + +async fn for_await_extra_spaces(iter: Iter) { + for await i in iter {} +} + +async fn for_await_newline(iter: Iter) { + for await i in iter {} +} + +async fn for_await_comment_between_keywords(iter: Iter) { + for /* between for and await */ await i in iter {} +} + +async fn for_await_comment_after_keyword(iter: Iter) { + for await + /* between await and pat */ + i in iter {} +} + +async fn for_await_comment_both_gaps(iter: Iter) { + for /* first gap */ await + /* second gap */ + i in iter {} +} + +async fn for_multi_line_comment_await(iter: Iter) { + for /* some + * multi-line + * comment */ + await i in iter {} +} + +async fn for_comment_await_comment_(iter: Iter) { + for /* some + * multi-line + * comment */ + await + /* some + * multi-line + * comment */ + i in iter {} +} + +async fn for_await_comment_with_long_iterator(iter: Iter) { + for /* some + * multi-line + * comment */ + await i in some_really_long_iterator_expression(alpha, beta, gamma, delta) {} +} + +async fn for_await_comment_exceeding_line_budget(iter: Iter) { + for /* some + * multi-line + * comment + * that keeps + * going on + * and on + * past ninety + * six bytes */ + await i in iter {} +} + +async fn for_await_line_comment_between_keywords(iter: Iter) { + for // between for and await + await i in iter {} +} + +async fn for_await_multiple_line_comments_between_keywords_with_spaces(iter: Iter) { + for // first line + // second line + await i in iter {} +} + +async fn for_await_line_comment_after_keyword(iter: Iter) { + for await + // between await and pat + i in iter {} +} + +async fn for_await_line_comments_both_gaps(iter: Iter) { + for // first gap + await + // second gap + i in iter {} +} + +async fn for_await_labeled(iter: Iter) { + 'outer: for await i in iter {} +} + +async fn for_await_labeled(iter: Iter) { + 'outer: for // line comment + await i in iter {} +} + +async fn for_await_labeled_multi_line_comment(iter: Iter) { + 'outer: for /* some + * multi-line + * comment */ + await i in iter {} +} + +async fn for_await_body(iter: Iter) { + for await i in iter { + do_something(i); + } +} + +// Single-token keywords must be unaffected by the change. + +fn plain_for(iter: Iter) { + for i in iter {} + for + /* comment */ + i in iter {} + for + // line comment + i in iter {} + 'outer: for i in iter {} +} + +fn plain_while(cond: bool) { + while cond {} + while + /* comment */ + cond {} + while + // line comment + cond {} + 'outer: while cond {} +} + +fn plain_while_let(opt: Opt) { + while let Some(x) = opt {} + while + /* comment */ + let Some(x) = opt {} + while + // line comment + let Some(x) = opt {} +} + +fn plain_loop() { + loop {} + 'outer: loop {} +} + +fn plain_if(cond: bool) { + if cond {} + if + /* comment */ + cond {} + if + // line comment + cond {} + if let Some(x) = opt {} +} diff --git a/tests/target/issue_4037.rs b/tests/target/issue_4037.rs new file mode 100644 index 0000000000000..9380399c64f9e --- /dev/null +++ b/tests/target/issue_4037.rs @@ -0,0 +1,17 @@ +fn f() { + let x = 0; + match x { + 0 => {} + + 1 => {} + _ => {} // foo + // bar, + } +} + +fn wont_fmt() -> [(); 1] { + [ + (), // + // , + ] +} diff --git a/tests/target/issue_5920_style_edition_2024.rs b/tests/target/issue_5920_style_edition_2024.rs new file mode 100644 index 0000000000000..1ca2b208dd6c1 --- /dev/null +++ b/tests/target/issue_5920_style_edition_2024.rs @@ -0,0 +1,25 @@ +// rustfmt-style_edition: 2024 + +struct Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), +} + +fn main() { + let Demo { + field_name_foo, + #[cfg(feature = "diagnostics")] + field_name_baz: _, + field_name_bar, + field_name_tux, + } = Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), + }; +} diff --git a/tests/target/issue_5920_style_edition_2027.rs b/tests/target/issue_5920_style_edition_2027.rs new file mode 100644 index 0000000000000..9d040a37699e3 --- /dev/null +++ b/tests/target/issue_5920_style_edition_2027.rs @@ -0,0 +1,25 @@ +// rustfmt-style_edition: 2027 + +struct Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), +} + +fn main() { + let Demo { + field_name_foo, + #[cfg(feature = "diagnostics")] + field_name_baz: _, + field_name_bar, + field_name_tux, + } = Demo { + field_name_foo: (), + field_name_bar: (), + #[cfg(feature = "diagnostics")] + field_name_baz: (), + field_name_tux: (), + }; +} diff --git a/tests/target/issue_5973.rs b/tests/target/issue_5973.rs new file mode 100644 index 0000000000000..244cf618691c4 --- /dev/null +++ b/tests/target/issue_5973.rs @@ -0,0 +1,19 @@ +fn main() { + while i < days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + i += 1; + } + + for i in 0..days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + i += 1; + } + + loop { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + i += 1; + } +} diff --git a/tests/target/issue_5982_style_edition_2024.rs b/tests/target/issue_5982_style_edition_2024.rs new file mode 100644 index 0000000000000..fe5f4a8987cb1 --- /dev/null +++ b/tests/target/issue_5982_style_edition_2024.rs @@ -0,0 +1,39 @@ +// rustfmt-style_edition: 2024 + +struct Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: i32, + #[cfg(all())] + something_long_enough_to_wrap_bar: i32, +} + +fn example() { + let Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo, + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} + +// The same, but with leading comments on the fields. +fn example_with_comments() { + let Foo { + // comment on shorthand field + #[cfg(all())] + something_long_enough_to_wrap_foo, + // comment on non-shorthand field + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} diff --git a/tests/target/issue_5982_style_edition_2027.rs b/tests/target/issue_5982_style_edition_2027.rs new file mode 100644 index 0000000000000..f622cd89b47e5 --- /dev/null +++ b/tests/target/issue_5982_style_edition_2027.rs @@ -0,0 +1,39 @@ +// rustfmt-style_edition: 2027 + +struct Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: i32, + #[cfg(all())] + something_long_enough_to_wrap_bar: i32, +} + +fn example() { + let Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo, + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} + +// The same, but with leading comments on the fields. +fn example_with_comments() { + let Foo { + // comment on shorthand field + #[cfg(all())] + something_long_enough_to_wrap_foo, + // comment on non-shorthand field + #[cfg(all())] + something_long_enough_to_wrap_bar: bar_var, + } = Foo { + #[cfg(all())] + something_long_enough_to_wrap_foo: 111, + #[cfg(all())] + something_long_enough_to_wrap_bar: 222, + }; +} diff --git a/tests/target/issue_6209.rs b/tests/target/issue_6209.rs new file mode 100644 index 0000000000000..89ef64290d3ce --- /dev/null +++ b/tests/target/issue_6209.rs @@ -0,0 +1,44 @@ +fn while_loop() { + thread::spawn(|| { + while i < days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + i += 1; + } + }); +} + +fn for_loop() { + thread::spawn(|| { + for i in 0..days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + } + }); +} + +fn empty_loop_body() { + thread::spawn(|| { + while true { + #![allow(clippy::indexing_slicing)] + } + }); +} + +fn closure_body_without_block() { + thread::spawn(|| { + while i < days.len() { + #![allow(clippy::indexing_slicing)] + w |= days[i].bit_value(); + } + }); +} + +fn outer_attribute_still_formatted() { + thread::spawn(|| { + #[allow(clippy::indexing_slicing)] + while i < days.len() { + w |= days[i].bit_value(); + } + }); +} diff --git a/tests/target/issue_6801.rs b/tests/target/issue_6801.rs new file mode 100644 index 0000000000000..46372db44769d --- /dev/null +++ b/tests/target/issue_6801.rs @@ -0,0 +1,57 @@ +// rustfmt-wrap_comments: true +// rustfmt-comment_width: 80 +// rustfmt-max_width: 200 + +fn foo() { + // In this line, the next '.' is exactly at'comment_width' . + // It should break on that dot + + // In this line, 'comment_width' is reached in the middle of + // ThisVeryLongWord. It should break before that word + + { + { + { + { + // again 'comment_width' is just at the next '.' . + // Here's some more stuff + fn f1() { + fn f2() { + fn f3() { + fn f4() { + fn f5() { + fn f6() { + fn f7() { + fn f8() { + fn f9() { + fn f10() { + fn f11() { + // again . + // Deeply nested + // comment + fn f12() { + fn f13() { + fn f14() { + fn f15() { + // indentation means this comment starts after 'comment_width' + // we don't touch this comment + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } + } +} diff --git a/tests/target/issue_6984_style_edition_2024.rs b/tests/target/issue_6984_style_edition_2024.rs new file mode 100644 index 0000000000000..001d5cdf14650 --- /dev/null +++ b/tests/target/issue_6984_style_edition_2024.rs @@ -0,0 +1,13 @@ +// rustfmt-style_edition: 2024 + +fn main() { + let Demo { + #[cfg(feature = "diagnostics")] + // comment between attribute and field + field_name_baz: _, + + #[cfg(feature = "diagnostics")] + // comment between attribute and shorthand field + field_name_bar, + } = value; +} diff --git a/tests/target/issue_6984_style_edition_2027.rs b/tests/target/issue_6984_style_edition_2027.rs new file mode 100644 index 0000000000000..eef2abc70cf9a --- /dev/null +++ b/tests/target/issue_6984_style_edition_2027.rs @@ -0,0 +1,13 @@ +// rustfmt-style_edition: 2027 + +fn main() { + let Demo { + #[cfg(feature = "diagnostics")] + // comment between attribute and field + field_name_baz: _, + + #[cfg(feature = "diagnostics")] + // comment between attribute and shorthand field + field_name_bar, + } = value; +} diff --git a/tests/target/issue_7003_style_edition_2024.rs b/tests/target/issue_7003_style_edition_2024.rs new file mode 100644 index 0000000000000..f2e21df15dadc --- /dev/null +++ b/tests/target/issue_7003_style_edition_2024.rs @@ -0,0 +1,14 @@ +// rustfmt-style_edition: 2024 + +fn main() { + _ = if let Some(term_node) = sema + .token_ancestors_with_macros(token.clone()) + .find(|node| { + matches!( + node.kind(), + BLOCK_EXPR | ARG_LIST | PAREN_EXPR | ARRAY_EXPR | MATCH_EXPR + ) + }) { + match term_node.kind() {} + }; +} diff --git a/tests/target/issue_7003_style_edition_2027.rs b/tests/target/issue_7003_style_edition_2027.rs new file mode 100644 index 0000000000000..c32a1278eae4b --- /dev/null +++ b/tests/target/issue_7003_style_edition_2027.rs @@ -0,0 +1,15 @@ +// rustfmt-style_edition: 2027 + +fn main() { + _ = if let Some(term_node) = sema + .token_ancestors_with_macros(token.clone()) + .find(|node| { + matches!( + node.kind(), + BLOCK_EXPR | ARG_LIST | PAREN_EXPR | ARRAY_EXPR | MATCH_EXPR + ) + }) + { + match term_node.kind() {} + }; +} diff --git a/tests/target/issue_7036.rs b/tests/target/issue_7036.rs new file mode 100644 index 0000000000000..294bc77b11d01 --- /dev/null +++ b/tests/target/issue_7036.rs @@ -0,0 +1,141 @@ +// Doc comments inside macro calls should not prevent formatting. +// +// Each comment form below is tested three ways: on its own, after an +// attribute, and before an attribute. + +foo!( + // Only a comment + A, B, +); + +foo!( + #[doc = ""] + // Only a comment + A, + B, +); + +foo!( + // Only a comment + #[doc = ""] + A, + B, +); + +foo!( + /// Outer line doc (exactly 3 slashes) + A, + B, +); + +foo!( + #[doc = ""] + /// Outer line doc (exactly 3 slashes) + A, + B, +); + +foo!( + /// Outer line doc (exactly 3 slashes) + #[doc = ""] + A, + B, +); + +foo!( + //// Only a comment + A, B, +); + +foo!( + #[doc = ""] + //// Only a comment + A, + B, +); + +foo!( + //// Only a comment + #[doc = ""] + A, + B, +); + +foo!(/* Only a comment */ A, B,); + +foo!( + #[doc = ""] + /* Only a comment */ + A, + B, +); + +foo!( + /* Only a comment */ + #[doc = ""] + A, + B, +); + +foo!( + /** Outer block doc (exactly 2 asterisks) */ + A, + B, +); + +foo!( + #[doc = ""] + /** Outer block doc (exactly 2 asterisks) */ + A, + B, +); + +foo!( + /** Outer block doc (exactly 2 asterisks) */ + #[doc = ""] + A, + B, +); + +foo!(/*** Only a comment */ A, B,); + +foo!( + #[doc = ""] + /*** Only a comment */ + A, + B, +); + +foo!( + /*** Only a comment */ + #[doc = ""] + A, + B, +); + +// Inner doc comments cannot attach to a macro argument, so these are left +// unformatted on purpose. + +foo!( + //! Inner line doc + A, + B, +); + +foo!( + //!! Still an inner line doc (but with a bang at the beginning) + A, + B, +); + +foo!( + /*! Inner block doc */ + A, + B, +); + +foo!( + /*!! Still an inner block doc (but with a bang at the beginning) */ + A, + B, +); diff --git a/tests/target/issue_7057.rs b/tests/target/issue_7057.rs new file mode 100644 index 0000000000000..102d13cfa9859 --- /dev/null +++ b/tests/target/issue_7057.rs @@ -0,0 +1,3 @@ +impl T for S { + pub default type X; +} diff --git a/tests/target/issue_7062.rs b/tests/target/issue_7062.rs new file mode 100644 index 0000000000000..58364d3290598 --- /dev/null +++ b/tests/target/issue_7062.rs @@ -0,0 +1 @@ +type FnNo = for<#[cfg_attr(FALSE, unknown)] 'a> fn(); diff --git a/tests/target/macros.rs b/tests/target/macros.rs index 7b4574349df3e..a8275efbe9935 100644 --- a/tests/target/macros.rs +++ b/tests/target/macros.rs @@ -1056,3 +1056,10 @@ f!(match a { // #3583 foo!(|x = y|); + +// #3757 +f!(match a { + _ => (), +}); + +g!(1, 2, 3); diff --git a/tests/target/splat.rs b/tests/target/splat.rs new file mode 100644 index 0000000000000..10702d0bdb231 --- /dev/null +++ b/tests/target/splat.rs @@ -0,0 +1,111 @@ +/// Tests that the `#[rustc_splat]` attribute is preserved by rustfmt. +/// This attribute is currently unstable, and its syntax might change in future. +/// It currently uses the default formatting for attributes. + +// These snippets are mainly from rust/tests/ui/splat + +// Rejected by rustc, but still needs to be formatted correctly + +// Can't have rust-call and splat on the same function +trait Trait: Tuple + Sized { + extern "rust-call" fn method(#[rustc_splat] self: Self); +} + +extern "rust-call" fn f(#[rustc_splat] _: ()); + +fn wrong_type(#[rustc_splat] _x: u32) {} + +// Can't have multiple splats in the same function +fn multi_splat_bad(#[rustc_splat] (_a, _b): (u32, i8), #[rustc_splat] (_c, _d): (u32, i8)) {} + +// Multiple splats on the same argument are redundant +fn multisplat_arg_bad( + #[rustc_splat] + #[rustc_splat] + (_a, _b): (u32, i8), +) { +} + +fn multisplat_arg_fn_bad( + #[rustc_splat] + #[rustc_splat] + (_a, _b): (u32, i8), + #[rustc_splat] (_c, _d): (u32, i8), +) { +} + +// Can't have variadic and splat on the same function +unsafe extern "C" fn splat_variadic(#[rustc_splat] (_a, _b): (u32, i8), varargs: ...) {} +unsafe extern "C" fn splat_variadic2(varargs: ..., #[rustc_splat] (_a, _b): (u32, i8)) {} + +// Accepted by rustc +struct Foo; + +impl Foo { + fn method(&self, #[rustc_splat] args: impl MethodArgs) -> String {} + fn tuple_1(#[rustc_splat] (_a,): (u32,)) {} + fn tuple_3(#[rustc_splat] (_a, _b, _c): (u32, i32, i8)) {} +} + +fn generic(#[rustc_splat] a: T) -> String { + String::new() +} + +fn splat_non_terminal_arg(#[rustc_splat] (a, b): (u32, i8), c: f64) -> (i8, f64, u32) { + (a, b, c) +} + +const X: fn(#[rustc_splat] (f32,)) = None.unwrap(); + +fn main() { + struct Type(T); + + // Rejected by rustc, but still needs to be formatted correctly + // Closures + (|#[rustc_splat] x: i32| {})(1); + + // Function pointer types + + // Rust-call and splat aren't allowed in the same function + let f_: extern "rust-call" fn(#[rustc_splat] ()) = f; + + let wrong_type_: fn(#[rustc_splat] _x: u32) = wrong_type; + + let multi_splat_bad_: fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multi_splat_bad; + let multisplat_arg_bad_: fn( + #[rustc_splat] + #[rustc_splat] + (u32, i8), + ) = multisplat_arg_bad; + let multisplat_arg_fn_bad_: fn( + #[rustc_splat] + #[rustc_splat] + (u32, i8), + #[rustc_splat] (u32, i8), + ) = multisplat_arg_fn_bad; + + // Splat and variadic aren't allowed in the same function + let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; + let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; + + // Accepted by rustc + // Function pointer types + + // Only one splatted arg + let fn_ptr: fn(#[rustc_splat] (u32, i8)) -> String = + generic as fn(#[rustc_splat] (u32, i8)) -> String; + impl Type {} + + // Leading splatted arg + let fn_pp: *const fn(#[rustc_splat] (u32, i8), f64) -> (i8, f64, u32) = + &(splat_non_terminal_arg as fn(#[rustc_splat] (u32, i8), f64) -> (i8, f64, u32)); + + // Trailing splatted arg + impl Type<*mut fn(u32, i8, #[rustc_splat] (f64,))> {} + + // Middle splatted arg + impl Type<&fn(u32, #[rustc_splat] (i8, f32, usize), f64)> {} + + // Splats within splats + impl Type> {} +} diff --git a/tests/target/string_lit_unicode_ws.rs b/tests/target/string_lit_unicode_ws.rs index f944711e14f39..fff135fbc4fdf 100644 --- a/tests/target/string_lit_unicode_ws.rs +++ b/tests/target/string_lit_unicode_ws.rs @@ -1,3 +1,5 @@ +// rustfmt-show_parse_errors: false + // Test Unicode whitespace characters in string literal line continuation fn main() { let str = "hello \ diff --git a/tests/target/trailing_comments/hard_tabs.rs b/tests/target/trailing_comments/hard_tabs.rs index e7009ac00c01b..8135b1a8caf7d 100644 --- a/tests/target/trailing_comments/hard_tabs.rs +++ b/tests/target/trailing_comments/hard_tabs.rs @@ -18,10 +18,10 @@ fn lorem_ipsum() { // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a - // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. - // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique - // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit - // amet, ipsum. In pharetra sagittis nunc. + // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor + // faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla + // tristique condimentum. Donec arcu quam, dictum accumsan, convallis + // accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. let b = baz(); let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] diff --git a/tests/target/trailing_comments/soft_tabs.rs b/tests/target/trailing_comments/soft_tabs.rs index 34cfed1a2293b..3e2dbc1bb7d73 100644 --- a/tests/target/trailing_comments/soft_tabs.rs +++ b/tests/target/trailing_comments/soft_tabs.rs @@ -18,10 +18,10 @@ fn foo() { // nunc. Mauris consequat, enim vitae venenatis sollicitudin, dolor orci // bibendum enim, a sagittis nulla nunc quis elit. Phasellus augue. Nunc // suscipit, magna tincidunt lacinia faucibus, lacus tellus ornare purus, a - // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor faucibus. - // In hac habitasse platea dictumst. Vivamus a orci at nulla tristique - // condimentum. Donec arcu quam, dictum accumsan, convallis accumsan, cursus sit - // amet, ipsum. In pharetra sagittis nunc. + // pulvinar lacus orci eget nibh. Maecenas sed nibh non lacus tempor + // faucibus. In hac habitasse platea dictumst. Vivamus a orci at nulla + // tristique condimentum. Donec arcu quam, dictum accumsan, convallis + // accumsan, cursus sit amet, ipsum. In pharetra sagittis nunc. let b = baz(); let normalized = self.ctfont.all_traits().normalized_weight(); // [-1.0, 1.0] diff --git a/tests/target/unicode.rs b/tests/target/unicode.rs index 34a4f46347969..610e482d6b498 100644 --- a/tests/target/unicode.rs +++ b/tests/target/unicode.rs @@ -4,7 +4,8 @@ fn foo() { let s = "this line goes to 100: ͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶͶ"; let s = 42; - // a comment of length 80, with the starting sigil: ҘҘҘҘҘҘҘҘҘҘ ҘҘҘҘҘҘҘҘҘҘҘҘҘҘ + // a comment of length 80, with the starting sigil: ҘҘҘҘҘҘҘҘҘҘ + // ҘҘҘҘҘҘҘҘҘҘҘҘҘҘ let s = 42; } diff --git a/tests/warning/snapshots/deprecated_skip.snap b/tests/warning/snapshots/deprecated_skip.snap new file mode 100644 index 0000000000000..bdba05a85a17b --- /dev/null +++ b/tests/warning/snapshots/deprecated_skip.snap @@ -0,0 +1,10 @@ +--- +source: src/test/mod.rs +--- +warning: `rustfmt_skip` is deprecated; use `rustfmt::skip` + --> tests/warning/source/deprecated_skip.rs:1 + | +1 | #[rustfmt_skip] + | + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/invalid_attribute.snap b/tests/warning/snapshots/invalid_attribute.snap new file mode 100644 index 0000000000000..5168fd54054bf --- /dev/null +++ b/tests/warning/snapshots/invalid_attribute.snap @@ -0,0 +1,10 @@ +--- +source: src/test/mod.rs +--- +error: invalid attribute + --> tests/warning/source/invalid_attribute.rs:1 + | +1 | #[rustfmt::invalid] + | + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/issue_3950.snap b/tests/warning/snapshots/issue_3950.snap new file mode 100644 index 0000000000000..ce2156813cbb3 --- /dev/null +++ b/tests/warning/snapshots/issue_3950.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 106) + --> tests/warning/source/issue_3950.rs:4:4:98 + | +4 | let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. + | ^^^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/issue_4968.snap b/tests/warning/snapshots/issue_4968.snap new file mode 100644 index 0000000000000..8892c58b136ab --- /dev/null +++ b/tests/warning/snapshots/issue_4968.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 40 (see `max_width` option), found: 61) + --> tests/warning/source/issue_4968.rs:7:7:32 + | +7 | println!("0123456789abcdefghijklmnopqrstuvwxyz"); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/issue_6442.snap b/tests/warning/snapshots/issue_6442.snap new file mode 100644 index 0000000000000..75e7888b3ccbd --- /dev/null +++ b/tests/warning/snapshots/issue_6442.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 125) + --> tests/warning/source/issue_6442.rs:4:4:98 + | +4 | // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/issue_6632.snap b/tests/warning/snapshots/issue_6632.snap new file mode 100644 index 0000000000000..4933f655bc227 --- /dev/null +++ b/tests/warning/snapshots/issue_6632.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 103) + --> tests/warning/source/issue_6632.rs:8:8:83 + | +8 | Self::$variant(s) => s.service_name(),// BuildService::service_name(s.clone()), + | ^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/issue_6826.snap b/tests/warning/snapshots/issue_6826.snap new file mode 100644 index 0000000000000..920d1c0296e52 --- /dev/null +++ b/tests/warning/snapshots/issue_6826.snap @@ -0,0 +1,18 @@ +--- +source: src/test/mod.rs +--- +error[internal]: not formatted because a comment would be lost + --> tests/warning/source/issue_6826.rs:2 + | +2 | c.is_ascii_alphanumeric() // 123 + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +error[internal]: left behind trailing whitespace + --> tests/warning/source/issue_6826.rs:3:3:20 + | +3 | || c == '。' + | ^ + | + +warning: rustfmt has failed to format. See previous 2 errors. diff --git a/tests/warning/snapshots/issue_6850.snap b/tests/warning/snapshots/issue_6850.snap new file mode 100644 index 0000000000000..f074864857744 --- /dev/null +++ b/tests/warning/snapshots/issue_6850.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 50 (see `max_width` option), found: 53) + --> tests/warning/source/issue_6850.rs:3:3:51 + | +3 | "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; + | ^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/line_overflow.snap b/tests/warning/snapshots/line_overflow.snap new file mode 100644 index 0000000000000..beb0257c4aa89 --- /dev/null +++ b/tests/warning/snapshots/line_overflow.snap @@ -0,0 +1,11 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 109) + --> tests/warning/source/line_overflow.rs:1:1:101 + | +1 | fn this_function_name_is_intentionally_long_enough_to_exceed_the_default_one_hundred_character_maximum_width( + | ^^^^^^^^^ + | + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/line_overflow_tabs.snap b/tests/warning/snapshots/line_overflow_tabs.snap new file mode 100644 index 0000000000000..88cf9af8b2c14 --- /dev/null +++ b/tests/warning/snapshots/line_overflow_tabs.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: line formatted, but exceeded maximum width (maximum: 50 (see `max_width` option), found: 59) + --> tests/warning/source/line_overflow_tabs.rs:3:3:23 + | +3 | let s = " "; + | ^^^^^^^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap b/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap new file mode 100644 index 0000000000000..01f685284e730 --- /dev/null +++ b/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap @@ -0,0 +1,20 @@ +--- +source: src/test/mod.rs +--- +error[internal]: left behind trailing whitespace + --> tests/warning/source/line_overflow_with_trailing_whitespace.rs:2:2:55 + | +2 | /// This doc comment overflows and has trailing space. + | ^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +error[internal]: line formatted, but exceeded maximum width (maximum: 50 (see `max_width` option), found: 54) + --> tests/warning/source/line_overflow_with_trailing_whitespace.rs:2:2:51 + | +2 | /// This doc comment overflows and has trailing space. + | ^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 2 errors. diff --git a/tests/warning/snapshots/lost_comment.snap b/tests/warning/snapshots/lost_comment.snap new file mode 100644 index 0000000000000..1983f12d73a91 --- /dev/null +++ b/tests/warning/snapshots/lost_comment.snap @@ -0,0 +1,11 @@ +--- +source: src/test/mod.rs +--- +error[internal]: not formatted because a comment would be lost + --> tests/warning/source/lost_comment.rs:1 + | +1 | fn main() { let _ = 1 /* This comment cannot be retained by the expression formatter. */ + 2; } + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/multiple_errors.snap b/tests/warning/snapshots/multiple_errors.snap new file mode 100644 index 0000000000000..4293505608134 --- /dev/null +++ b/tests/warning/snapshots/multiple_errors.snap @@ -0,0 +1,38 @@ +--- +source: src/test/mod.rs +--- +warning: `rustfmt_skip` is deprecated; use `rustfmt::skip` + --> tests/warning/source/multiple_errors.rs:1 + | +1 | #[rustfmt_skip] + | + +error: invalid attribute + --> tests/warning/source/multiple_errors.rs:4 + | +4 | #[rustfmt::invalid] + | + +error[internal]: not formatted because a comment would be lost + --> tests/warning/source/multiple_errors.rs:9 + | +9 | fn lost_comment() { let _ = 1 /* This comment cannot be retained by the expression formatter. */ + 2; } + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +error[internal]: line formatted, but exceeded maximum width (maximum: 100 (see `max_width` option), found: 109) + --> tests/warning/source/multiple_errors.rs:7:7:101 + | +7 | fn this_function_name_is_intentionally_long_enough_to_exceed_the_default_one_hundred_character_maximum_width( + | ^^^^^^^^^ + | + +error[internal]: left behind trailing whitespace + --> tests/warning/source/multiple_errors.rs:15:15:46 + | +15 | /// This doc comment has trailing whitespace. + | ^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 5 errors. diff --git a/tests/warning/snapshots/trailing_whitespace.snap b/tests/warning/snapshots/trailing_whitespace.snap new file mode 100644 index 0000000000000..13ca45ac2cd47 --- /dev/null +++ b/tests/warning/snapshots/trailing_whitespace.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: left behind trailing whitespace + --> tests/warning/source/trailing_whitespace.rs:1:1:46 + | +1 | /// This doc comment has trailing whitespace. + | ^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/trailing_whitespace_overflow.snap b/tests/warning/snapshots/trailing_whitespace_overflow.snap new file mode 100644 index 0000000000000..6c0a510d1555a --- /dev/null +++ b/tests/warning/snapshots/trailing_whitespace_overflow.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: left behind trailing whitespace + --> tests/warning/source/trailing_whitespace_overflow.rs:2:2:37 + | +2 | /// Overflowing trailing whitespace. + | ^^^^^^^^^^^^^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/snapshots/unicode_trailing_whitespace.snap b/tests/warning/snapshots/unicode_trailing_whitespace.snap new file mode 100644 index 0000000000000..d263a09e5a5a7 --- /dev/null +++ b/tests/warning/snapshots/unicode_trailing_whitespace.snap @@ -0,0 +1,12 @@ +--- +source: src/test/mod.rs +--- +error[internal]: left behind trailing whitespace + --> tests/warning/source/unicode_trailing_whitespace.rs:1:1:41 + | +1 | /// This doc comment ends in a snowman ☃ + | ^^^ + | + = note: set `error_on_unformatted = false` to suppress the warning against comments or string literals + +warning: rustfmt has failed to format. See previous 1 errors. diff --git a/tests/warning/source/deprecated_skip.rs b/tests/warning/source/deprecated_skip.rs new file mode 100644 index 0000000000000..6578f13bc7fb6 --- /dev/null +++ b/tests/warning/source/deprecated_skip.rs @@ -0,0 +1,2 @@ +#[rustfmt_skip] +fn main() {} diff --git a/tests/warning/source/invalid_attribute.rs b/tests/warning/source/invalid_attribute.rs new file mode 100644 index 0000000000000..f3957f4c04240 --- /dev/null +++ b/tests/warning/source/invalid_attribute.rs @@ -0,0 +1,2 @@ +#[rustfmt::invalid] +fn main() {} diff --git a/tests/warning/source/issue_3950.rs b/tests/warning/source/issue_3950.rs new file mode 100644 index 0000000000000..5fa559f5d9872 --- /dev/null +++ b/tests/warning/source/issue_3950.rs @@ -0,0 +1,5 @@ +// rustfmt-hard_tabs: true + +fn lorem_ipsum() { + let f = bar(); // Donec consequat mi. Quisque vitae dolor. Integer lobortis. Maecenas id nulla. Lorem. +} diff --git a/tests/warning/source/issue_4968.rs b/tests/warning/source/issue_4968.rs new file mode 100644 index 0000000000000..3726abc694bae --- /dev/null +++ b/tests/warning/source/issue_4968.rs @@ -0,0 +1,10 @@ +// rustfmt-hard_tabs: true +// rustfmt-max_width: 40 + +fn foo(x: u32) { + if x > 10 { + if x > 20 { + println!("0123456789abcdefghijklmnopqrstuvwxyz"); + } + } +} diff --git a/tests/warning/source/issue_6442.rs b/tests/warning/source/issue_6442.rs new file mode 100644 index 0000000000000..f3760c972313c --- /dev/null +++ b/tests/warning/source/issue_6442.rs @@ -0,0 +1,5 @@ +// rustfmt-hard_tabs: true + +fn main() { + // aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa +} diff --git a/tests/warning/source/issue_6632.rs b/tests/warning/source/issue_6632.rs new file mode 100644 index 0000000000000..e9a5c8a528f85 --- /dev/null +++ b/tests/warning/source/issue_6632.rs @@ -0,0 +1,14 @@ +macro_rules! impl_routes_and_health { + ($($feature:literal, $variant:ident),* $(,)?) => { + impl EitherState { + pub(crate) fn service_name(&self) -> &'static str { + match self { + $( + #[cfg(feature = $feature)] + Self::$variant(s) => s.service_name(),// BuildService::service_name(s.clone()), + )* + } + } + } + }; +} diff --git a/tests/warning/source/issue_6826.rs b/tests/warning/source/issue_6826.rs new file mode 100644 index 0000000000000..330b42b2bb999 --- /dev/null +++ b/tests/warning/source/issue_6826.rs @@ -0,0 +1,5 @@ +pub fn check(c: char) -> bool { + c.is_ascii_alphanumeric() // 123 + || c == '。' + || c == '、' +} diff --git a/tests/warning/source/issue_6850.rs b/tests/warning/source/issue_6850.rs new file mode 100644 index 0000000000000..1f130a43cbf68 --- /dev/null +++ b/tests/warning/source/issue_6850.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 50 +fn main() { + "☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃☃"; +} diff --git a/tests/warning/source/line_overflow.rs b/tests/warning/source/line_overflow.rs new file mode 100644 index 0000000000000..1ce77151c956d --- /dev/null +++ b/tests/warning/source/line_overflow.rs @@ -0,0 +1 @@ +fn this_function_name_is_intentionally_long_enough_to_exceed_the_default_one_hundred_character_maximum_width() {} diff --git a/tests/warning/source/line_overflow_tabs.rs b/tests/warning/source/line_overflow_tabs.rs new file mode 100644 index 0000000000000..e6a2a515ffbda --- /dev/null +++ b/tests/warning/source/line_overflow_tabs.rs @@ -0,0 +1,4 @@ +// rustfmt-max_width: 50 +fn main() { + let s = " "; +} diff --git a/tests/warning/source/line_overflow_with_trailing_whitespace.rs b/tests/warning/source/line_overflow_with_trailing_whitespace.rs new file mode 100644 index 0000000000000..ccb2ece866806 --- /dev/null +++ b/tests/warning/source/line_overflow_with_trailing_whitespace.rs @@ -0,0 +1,3 @@ +// rustfmt-max_width: 50 +/// This doc comment overflows and has trailing space. +fn main() {} diff --git a/tests/warning/source/lost_comment.rs b/tests/warning/source/lost_comment.rs new file mode 100644 index 0000000000000..d075256c92775 --- /dev/null +++ b/tests/warning/source/lost_comment.rs @@ -0,0 +1 @@ +fn main() { let _ = 1 /* This comment cannot be retained by the expression formatter. */ + 2; } diff --git a/tests/warning/source/multiple_errors.rs b/tests/warning/source/multiple_errors.rs new file mode 100644 index 0000000000000..02e660d3cb840 --- /dev/null +++ b/tests/warning/source/multiple_errors.rs @@ -0,0 +1,12 @@ +#[rustfmt_skip] +fn deprecated_skip() {} + +#[rustfmt::invalid] +fn invalid_attribute() {} + +fn this_function_name_is_intentionally_long_enough_to_exceed_the_default_one_hundred_character_maximum_width() {} + +fn lost_comment() { let _ = 1 /* This comment cannot be retained by the expression formatter. */ + 2; } + +/// This doc comment has trailing whitespace. +fn trailing_whitespace() {} diff --git a/tests/warning/source/trailing_whitespace.rs b/tests/warning/source/trailing_whitespace.rs new file mode 100644 index 0000000000000..bfa58ac288764 --- /dev/null +++ b/tests/warning/source/trailing_whitespace.rs @@ -0,0 +1,2 @@ +/// This doc comment has trailing whitespace. +fn main() {} diff --git a/tests/warning/source/trailing_whitespace_overflow.rs b/tests/warning/source/trailing_whitespace_overflow.rs new file mode 100644 index 0000000000000..16be61a5e3cbe --- /dev/null +++ b/tests/warning/source/trailing_whitespace_overflow.rs @@ -0,0 +1,3 @@ +// rustfmt-max_width: 50 +/// Overflowing trailing whitespace. +fn main() {} diff --git a/tests/warning/source/unicode_trailing_whitespace.rs b/tests/warning/source/unicode_trailing_whitespace.rs new file mode 100644 index 0000000000000..0ba61f2f3b140 --- /dev/null +++ b/tests/warning/source/unicode_trailing_whitespace.rs @@ -0,0 +1,2 @@ +/// This doc comment ends in a snowman ☃ +fn main() {} From 70293375ba5dd9c69091686ec21b9920060a7e75 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Aug 2026 22:56:54 +0200 Subject: [PATCH 0110/1309] move .auto settings into miri.toml file --- src/tools/miri/.gitignore | 1 + src/tools/miri/CONTRIBUTING.md | 20 ++++++--- src/tools/miri/miri-script/Cargo.lock | 47 ++++++++++++++++++++++ src/tools/miri/miri-script/Cargo.toml | 3 +- src/tools/miri/miri-script/src/commands.rs | 19 ++++----- src/tools/miri/miri-script/src/config.rs | 44 ++++++++++++++++++++ src/tools/miri/miri-script/src/main.rs | 9 ++++- 7 files changed, 123 insertions(+), 20 deletions(-) create mode 100644 src/tools/miri/miri-script/src/config.rs diff --git a/src/tools/miri/.gitignore b/src/tools/miri/.gitignore index 23f2513addb74..6851dc9190fce 100644 --- a/src/tools/miri/.gitignore +++ b/src/tools/miri/.gitignore @@ -13,5 +13,6 @@ flamegraph*.svg rustc-ice*.txt tests/native-lib/libtestlib.so .auto-* +miri.toml /genmc/ diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 0a330cdd45537..1de98ff52afdd 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -111,13 +111,23 @@ install that exact version of rustc as a toolchain: This will set up a rustup toolchain called `miri` and set it as an override for the current directory. -You can also create a `.auto-everything` file (contents don't matter, can be empty), which -will cause any `./miri` command to automatically call `./miri toolchain`, `clippy` and `rustfmt` -for you. If you don't want all of these to happen, you can add individual `.auto-toolchain`, -`.auto-clippy` and `.auto-fmt` files respectively. - [`rustup-toolchain-install-master`]: https://github.com/kennytm/rustup-toolchain-install-master +### Configuring `./miri` + +The `./miri` script supports optional configuration via a `miri.toml` file. +The following configuration keys are currently supported, with the given default values: + +```toml +[auto] +# Automatically run `./miri toolchain` before most commands. +toolchain = false +# Automatically run `./miri clippy` before most commands. +clippy = false +# Automatically run `./miri fmt` before most commands. +fmt = false +``` + ## Building and testing Miri Invoking Miri requires getting a bunch of flags right and setting up a custom diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock index d946d77987cf3..3a5afb25a74e5 100644 --- a/src/tools/miri/miri-script/Cargo.lock +++ b/src/tools/miri/miri-script/Cargo.lock @@ -274,6 +274,7 @@ dependencies = [ "serde_json", "shell-words", "tempfile", + "toml", "walkdir", "xshell", ] @@ -409,6 +410,15 @@ dependencies = [ "zmij", ] +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + [[package]] name = "shell-words" version = "1.1.1" @@ -445,6 +455,37 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "toml" +version = "1.1.4+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +dependencies = [ + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + [[package]] name = "unicode-ident" version = "1.0.24" @@ -549,6 +590,12 @@ dependencies = [ "windows-link", ] +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" + [[package]] name = "wit-bindgen" version = "0.46.0" diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml index fd9a563e1fafd..1b0a34de3e3db 100644 --- a/src/tools/miri/miri-script/Cargo.toml +++ b/src/tools/miri/miri-script/Cargo.toml @@ -22,7 +22,8 @@ xshell = "0.2.6" rustc_version = "0.4" dunce = "1.0.4" serde = "1" +serde_derive = "1" # direct dependency better parallelizes builds serde_json = "1" -serde_derive = "1" tempfile = "3.13.0" clap = { version = "4.5.21", features = ["derive"] } +toml = {version = "1", default-features = false, features = ["serde", "parse"] } diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index e8fdcd80f8ddb..3223cacc40bc5 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -14,6 +14,7 @@ use walkdir::WalkDir; use xshell::{Shell, cmd}; use crate::Command; +use crate::config::Config; use crate::util::*; impl MiriEnv { @@ -67,25 +68,19 @@ impl MiriEnv { } impl Command { - fn auto_actions() -> Result<()> { + fn auto_actions(config: &Config) -> Result<()> { if env::var_os("MIRI_AUTO_OPS").is_some_and(|x| x == "no") { return Ok(()); } - let miri_dir = miri_dir()?; - let auto_everything = path!(miri_dir / ".auto-everything").exists(); - let auto_toolchain = auto_everything || path!(miri_dir / ".auto-toolchain").exists(); - let auto_fmt = auto_everything || path!(miri_dir / ".auto-fmt").exists(); - let auto_clippy = auto_everything || path!(miri_dir / ".auto-clippy").exists(); - // `toolchain` goes first as it could affect the others - if auto_toolchain { + if config.auto.toolchain { Self::toolchain(None, vec![])?; } - if auto_fmt { + if config.auto.fmt { Self::fmt(vec![])?; } - if auto_clippy { + if config.auto.clippy { // no features for auto actions, see // https://github.com/rust-lang/miri/pull/4396#discussion_r2149654845 Self::clippy(vec![], vec![])?; @@ -94,7 +89,7 @@ impl Command { Ok(()) } - pub fn exec(self) -> Result<()> { + pub fn exec(self, config: &Config) -> Result<()> { // First, and crucially only once, run the auto-actions -- but not for all commands. match &self { Command::Install { .. } @@ -104,7 +99,7 @@ impl Command { | Command::Run { .. } | Command::Fmt { .. } | Command::Doc { .. } - | Command::Clippy { .. } => Self::auto_actions()?, + | Command::Clippy { .. } => Self::auto_actions(config)?, | Command::Toolchain { .. } | Command::Bench { .. } | Command::Squash => {} } // Then run the actual command. diff --git a/src/tools/miri/miri-script/src/config.rs b/src/tools/miri/miri-script/src/config.rs new file mode 100644 index 0000000000000..c4be1ee0abc7b --- /dev/null +++ b/src/tools/miri/miri-script/src/config.rs @@ -0,0 +1,44 @@ +use std::{fs, io}; + +use anyhow::{Context, Result, bail}; +use path_macro::path; +use serde_derive::Deserialize; + +use crate::util::miri_dir; + +#[derive(Deserialize, Default)] +pub struct Config { + #[serde(default)] + pub auto: Auto, +} + +#[derive(Deserialize, Default)] +pub struct Auto { + #[serde(default)] + pub toolchain: bool, + #[serde(default)] + pub fmt: bool, + #[serde(default)] + pub clippy: bool, +} + +impl Config { + pub fn load() -> Result { + let miri_dir = miri_dir()?; + + Ok(match fs::read(path!(miri_dir / "miri.toml")) { + Ok(config) => toml::from_slice(&config).context("failed to parse `miri.toml`")?, + Err(err) if err.kind() == io::ErrorKind::NotFound => { + // Just ignore error if the file does not exist. Fall back to parsing the `.auto-*` + // files. + let mut config = Config::default(); + let everything = path!(miri_dir / ".auto-everything").exists(); + config.auto.toolchain = everything || path!(miri_dir / ".auto-toolchain").exists(); + config.auto.fmt = everything || path!(miri_dir / ".auto-fmt").exists(); + config.auto.clippy = everything || path!(miri_dir / ".auto-clippy").exists(); + config + } + Err(err) => bail!("unable to open `miri.toml`: {err}"), + }) + } +} diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index b575842fc6c78..3c3c8789b10cc 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -1,6 +1,7 @@ #![allow(clippy::needless_question_mark, rustc::internal)] mod commands; +mod config; mod coverage; mod util; @@ -200,6 +201,10 @@ fn main() -> Result<()> { let args = Cli::parse_from(miri_args); let mut command = args.command; command.add_remainder(remainder)?; - command.exec()?; - Ok(()) + + // Parse config file. + let config = config::Config::load()?; + + // Run the thing. + command.exec(&config) } From 4924c571b74001babe8c134ea8abde66aa1be749 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Aug 2026 23:07:06 +0200 Subject: [PATCH 0111/1309] add `./miri toolchain --name` to configure which toolchain to install+activate --- src/tools/miri/miri-script/src/commands.rs | 26 ++++++++++++++-------- src/tools/miri/miri-script/src/main.rs | 3 +++ 2 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 3223cacc40bc5..6f8325aabd5ce 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -75,7 +75,7 @@ impl Command { // `toolchain` goes first as it could affect the others if config.auto.toolchain { - Self::toolchain(None, vec![])?; + Self::toolchain(None, None, vec![])?; } if config.auto.fmt { Self::fmt(vec![])?; @@ -116,12 +116,18 @@ impl Command { Command::Clippy { features, flags } => Self::clippy(features, flags), Command::Bench { target, no_install, save_baseline, load_baseline, benches } => Self::bench(target, no_install, save_baseline, load_baseline, benches), - Command::Toolchain { commit, flags } => Self::toolchain(commit, flags), + Command::Toolchain { name, commit, flags } => Self::toolchain(name, commit, flags), Command::Squash => Self::squash(), } } - fn toolchain(new_commit: Option, flags: Vec) -> Result<()> { + fn toolchain( + name: Option, + new_commit: Option, + flags: Vec, + ) -> Result<()> { + let name = name.as_deref().unwrap_or("miri"); + let sh = Shell::new()?; sh.change_dir(miri_dir()?); let new_commit = match new_commit { @@ -129,7 +135,7 @@ impl Command { None => sh.read_file("rust-version")?.trim().to_owned(), }; let current_commit = { - let rustc_info = cmd!(sh, "rustc +miri --version -v").read(); + let rustc_info = cmd!(sh, "rustc +{name} --version -v").read(); if let Ok(rustc_info) = rustc_info { let metadata = rustc_version::version_meta_for(&rustc_info)?; Some( @@ -143,18 +149,20 @@ impl Command { }; // Check if we already are at that commit. if current_commit.as_ref() == Some(&new_commit) { - if active_toolchain()? != "miri" { - cmd!(sh, "rustup override set miri").run()?; + // The toolchain is already at the right version. Make sure it is active in `miri_dir`. + // Ignore errors from `active_toolchain`, the active toolchain might be uninstalled. + if active_toolchain().ok().is_none_or(|toolchain| toolchain != name) { + cmd!(sh, "rustup override set {name}").run()?; } return Ok(()); } // Install and setup new toolchain. - cmd!(sh, "rustup toolchain uninstall miri").run()?; + cmd!(sh, "rustup toolchain uninstall {name}").run()?; - cmd!(sh, "rustup-toolchain-install-master -n miri -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}") + cmd!(sh, "rustup-toolchain-install-master -n {name} -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}") .run() .context("Failed to run rustup-toolchain-install-master. If it is not installed, run 'cargo install --locked rustup-toolchain-install-master'.")?; - cmd!(sh, "rustup override set miri").run()?; + cmd!(sh, "rustup override set {name}").run()?; // Cleanup. cmd!(sh, "cargo clean").run()?; Ok(()) diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index 3c3c8789b10cc..d697066e71249 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -143,6 +143,9 @@ pub enum Command { /// The `rust-version` file is used to determine the commit that will be intsalled. /// `rustup-toolchain-install-master` must be installed for this to work. Toolchain { + /// Overwrite the name the toolchain will have in `rustup`. + #[arg(long)] + name: Option, /// Overwrite the commit to install. #[arg(long)] commit: Option, From 937d7a216666816ca63cdb1260a21ecbc397fbda Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Aug 2026 23:10:15 +0200 Subject: [PATCH 0112/1309] miri.toml: allow configuring the default toolchain name --- src/tools/miri/CONTRIBUTING.md | 8 ++++++++ src/tools/miri/miri-script/src/commands.rs | 8 +++++--- src/tools/miri/miri-script/src/config.rs | 7 +++++++ src/tools/miri/miri-script/src/main.rs | 3 ++- 4 files changed, 22 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 1de98ff52afdd..567e70544a4df 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -119,8 +119,16 @@ The `./miri` script supports optional configuration via a `miri.toml` file. The following configuration keys are currently supported, with the given default values: ```toml +[toolchain] +# Overwrite the default toolchain name used by `./miri toolchain`. +# Note that all other commands will just use the currently active rustup toolchain! +# (Though note that if you have `auto.toolchain` enabled, most commands will run `./miri toolchain` +# first, which will activate the toolchain given here.) +name = "miri" + [auto] # Automatically run `./miri toolchain` before most commands. +# Uses the toolchain name configured above, if any. toolchain = false # Automatically run `./miri clippy` before most commands. clippy = false diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 6f8325aabd5ce..118b5b0a56c85 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -75,7 +75,7 @@ impl Command { // `toolchain` goes first as it could affect the others if config.auto.toolchain { - Self::toolchain(None, None, vec![])?; + Self::toolchain(None, None, vec![], config)?; } if config.auto.fmt { Self::fmt(vec![])?; @@ -116,7 +116,8 @@ impl Command { Command::Clippy { features, flags } => Self::clippy(features, flags), Command::Bench { target, no_install, save_baseline, load_baseline, benches } => Self::bench(target, no_install, save_baseline, load_baseline, benches), - Command::Toolchain { name, commit, flags } => Self::toolchain(name, commit, flags), + Command::Toolchain { name, commit, flags } => + Self::toolchain(name, commit, flags, config), Command::Squash => Self::squash(), } } @@ -125,8 +126,9 @@ impl Command { name: Option, new_commit: Option, flags: Vec, + config: &Config, ) -> Result<()> { - let name = name.as_deref().unwrap_or("miri"); + let name = name.as_deref().or(config.toolchain.name.as_deref()).unwrap_or("miri"); let sh = Shell::new()?; sh.change_dir(miri_dir()?); diff --git a/src/tools/miri/miri-script/src/config.rs b/src/tools/miri/miri-script/src/config.rs index c4be1ee0abc7b..337463cbb343e 100644 --- a/src/tools/miri/miri-script/src/config.rs +++ b/src/tools/miri/miri-script/src/config.rs @@ -8,10 +8,17 @@ use crate::util::miri_dir; #[derive(Deserialize, Default)] pub struct Config { + #[serde(default)] + pub toolchain: Toolchain, #[serde(default)] pub auto: Auto, } +#[derive(Deserialize, Default)] +pub struct Toolchain { + pub name: Option, +} + #[derive(Deserialize, Default)] pub struct Auto { #[serde(default)] diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs index d697066e71249..bcad8f148d23f 100644 --- a/src/tools/miri/miri-script/src/main.rs +++ b/src/tools/miri/miri-script/src/main.rs @@ -138,7 +138,8 @@ pub enum Command { /// List of benchmarks to run (default: run all benchmarks). benches: Vec, }, - /// Update and activate the rustup toolchain 'miri'. + /// Update and activate the rustup toolchain 'miri' (or whatever name is configured in + /// `miri.toml`). /// /// The `rust-version` file is used to determine the commit that will be intsalled. /// `rustup-toolchain-install-master` must be installed for this to work. From c28b2730793fe9fc945c89cc19c2a2f88a73e18f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 26 Aug 2026 23:23:28 +0200 Subject: [PATCH 0113/1309] miri.toml: allow configuring toolchain components --- src/tools/miri/CONTRIBUTING.md | 5 +++++ src/tools/miri/miri-script/src/commands.rs | 14 ++++++++++---- src/tools/miri/miri-script/src/config.rs | 8 ++++++++ 3 files changed, 23 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md index 567e70544a4df..4bc02217c6f7b 100644 --- a/src/tools/miri/CONTRIBUTING.md +++ b/src/tools/miri/CONTRIBUTING.md @@ -125,6 +125,11 @@ The following configuration keys are currently supported, with the given default # (Though note that if you have `auto.toolchain` enabled, most commands will run `./miri toolchain` # first, which will activate the toolchain given here.) name = "miri" +# Additional components to install with the toolchain. Note that if you remove `clippy` or `rustfmt` +# from this list then obviously `./miri clippy`/`./miri fmt` will not work. +# Only takes effect when a new toolchain is installed. Run `rustup toolchain remove ` followed +# by `./miri toolchain` to force this to have effect. +components = ["clippy", "rustfmt"] [auto] # Automatically run `./miri toolchain` before most commands. diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 118b5b0a56c85..df3161765b7df 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -14,7 +14,7 @@ use walkdir::WalkDir; use xshell::{Shell, cmd}; use crate::Command; -use crate::config::Config; +use crate::config::{Config, Toolchain}; use crate::util::*; impl MiriEnv { @@ -128,7 +128,8 @@ impl Command { flags: Vec, config: &Config, ) -> Result<()> { - let name = name.as_deref().or(config.toolchain.name.as_deref()).unwrap_or("miri"); + let name = + name.as_deref().or(config.toolchain.name.as_deref()).unwrap_or(Toolchain::DEFAULT_NAME); let sh = Shell::new()?; sh.change_dir(miri_dir()?); @@ -158,10 +159,15 @@ impl Command { } return Ok(()); } + + // Compute rustup-toolchain-install-master flags for additional components. + let components = + config.toolchain.components.as_deref().unwrap_or(Toolchain::DEFAULT_COMPONENTS); + let component_flags = components.iter().flat_map(|component| ["-c", component]); + // Install and setup new toolchain. cmd!(sh, "rustup toolchain uninstall {name}").run()?; - - cmd!(sh, "rustup-toolchain-install-master -n {name} -c cargo -c rust-src -c rustc-dev -c llvm-tools -c rustfmt -c clippy {flags...} -- {new_commit}") + cmd!(sh, "rustup-toolchain-install-master -n {name} -c cargo -c rust-src -c rustc-dev -c llvm-tools {component_flags...} {flags...} -- {new_commit}") .run() .context("Failed to run rustup-toolchain-install-master. If it is not installed, run 'cargo install --locked rustup-toolchain-install-master'.")?; cmd!(sh, "rustup override set {name}").run()?; diff --git a/src/tools/miri/miri-script/src/config.rs b/src/tools/miri/miri-script/src/config.rs index 337463cbb343e..b5f4e729c9d35 100644 --- a/src/tools/miri/miri-script/src/config.rs +++ b/src/tools/miri/miri-script/src/config.rs @@ -1,3 +1,4 @@ +use std::borrow::Cow; use std::{fs, io}; use anyhow::{Context, Result, bail}; @@ -17,6 +18,13 @@ pub struct Config { #[derive(Deserialize, Default)] pub struct Toolchain { pub name: Option, + pub components: Option>>, +} + +impl Toolchain { + pub const DEFAULT_NAME: &str = "miri"; + pub const DEFAULT_COMPONENTS: &[Cow<'static, str>] = + &[Cow::Borrowed("clippy"), Cow::Borrowed("rustfmt")]; } #[derive(Deserialize, Default)] From c447e2e61701796fdf3adefcf3fb6d2d65e36d5a Mon Sep 17 00:00:00 2001 From: jyn Date: Sat, 29 Aug 2026 10:58:59 +0200 Subject: [PATCH 0114/1309] open issues when scheduled linkcheck fails - identify issues by label and title - reuse an existing issue if it already exists - use a bash script around `gh` so we don't add unvetted dependencies - add tests for the bash script using a fake `gh` mock --- .../rustc-dev-guide/.github/workflows/ci.yml | 35 +++++++++- .../ci/close-scheduled-linkcheck-issues.sh | 31 +++++++++ .../ci/report-scheduled-linkcheck-failure.sh | 51 ++++++++++++++ src/doc/rustc-dev-guide/ci/tests/fakes/gh | 25 +++++++ .../report-scheduled-linkcheck-failure.sh | 69 +++++++++++++++++++ 5 files changed, 210 insertions(+), 1 deletion(-) create mode 100755 src/doc/rustc-dev-guide/ci/close-scheduled-linkcheck-issues.sh create mode 100755 src/doc/rustc-dev-guide/ci/report-scheduled-linkcheck-failure.sh create mode 100755 src/doc/rustc-dev-guide/ci/tests/fakes/gh create mode 100755 src/doc/rustc-dev-guide/ci/tests/report-scheduled-linkcheck-failure.sh diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index 4108ef8c2e1e2..fd5515dda0e39 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -22,11 +22,14 @@ jobs: BASE_SHA: ${{ github.event.pull_request.base.sha }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 with: # linkcheck needs the base commit. fetch-depth: 0 + - name: Test CI scripts + run: ci/tests/report-scheduled-linkcheck-failure.sh + - name: Cache binaries id: mdbook-cache uses: actions/cache@v4 @@ -88,3 +91,33 @@ jobs: run: | # using split_inclusive that uses regex feature that uses an unstable feature RUSTC_BOOTSTRAP=1 cargo run --release --manifest-path ci/sembr/Cargo.toml src + + notify-scheduled-failure: + name: Open an issue if links are broken + needs: ci + if: failure() && github.event_name == 'schedule' + runs-on: ubuntu-latest + permissions: + actions: read + issues: write + steps: + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 + - name: Open an issue or comment on an existing one + run: ci/report-scheduled-linkcheck-failure.sh + env: + GH_TOKEN: ${{ github.token }} + + close-scheduled-failure: + name: Close linkcheck issue if no links are broken + needs: ci + if: success() && github.event_name == 'schedule' + runs-on: ubuntu-latest + permissions: + contents: read + issues: write + steps: + - uses: actions/checkout@v7 + - name: Close issue + run: ci/close-scheduled-linkcheck-issues.sh + env: + GH_TOKEN: ${{ github.token }} diff --git a/src/doc/rustc-dev-guide/ci/close-scheduled-linkcheck-issues.sh b/src/doc/rustc-dev-guide/ci/close-scheduled-linkcheck-issues.sh new file mode 100755 index 0000000000000..7fb4c74cc128c --- /dev/null +++ b/src/doc/rustc-dev-guide/ci/close-scheduled-linkcheck-issues.sh @@ -0,0 +1,31 @@ +#!/usr/bin/env bash + +set -euo pipefail + +: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY must be set}" +: "${GITHUB_RUN_ID:?GITHUB_RUN_ID must be set}" +: "${GITHUB_SERVER_URL:?GITHUB_SERVER_URL must be set}" +: "${GH_TOKEN:?GH_TOKEN must be set}" + +successful_run_url="$GITHUB_SERVER_URL/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID" + +issue_numbers=$(gh issue list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --label C-broken-links \ + --label C-CI \ + --label A-linkcheck \ + --limit 100 \ + --json number,title \ + --jq '.[] | select(.title == "[automation] Dead links found") | .number') + +if [[ -z "$issue_numbers" ]]; then + echo "No scheduled linkcheck failure issue is open." + exit 0 +fi + +while read -r issue_number; do + gh issue close "$issue_number" \ + --repo "$GITHUB_REPOSITORY" \ + --comment "The scheduled link check is succeeding again: $successful_run_url" +done <<< "$issue_numbers" diff --git a/src/doc/rustc-dev-guide/ci/report-scheduled-linkcheck-failure.sh b/src/doc/rustc-dev-guide/ci/report-scheduled-linkcheck-failure.sh new file mode 100755 index 0000000000000..178b3b40a75bf --- /dev/null +++ b/src/doc/rustc-dev-guide/ci/report-scheduled-linkcheck-failure.sh @@ -0,0 +1,51 @@ +#!/usr/bin/env bash + +set -euo pipefail + +: "${GITHUB_REPOSITORY:?GITHUB_REPOSITORY must be set}" +: "${GITHUB_RUN_ID:?GITHUB_RUN_ID must be set}" +: "${GITHUB_RUN_NUMBER:?GITHUB_RUN_NUMBER must be set}" +: "${GITHUB_SERVER_URL:?GITHUB_SERVER_URL must be set}" +: "${GITHUB_SHA:?GITHUB_SHA must be set}" +: "${GH_TOKEN:?GH_TOKEN must be set}" + +title="[automation] Dead links found" +job_url=$(gh api \ + "repos/$GITHUB_REPOSITORY/actions/runs/$GITHUB_RUN_ID/jobs" \ + --jq '.jobs[] | select(.name == "ci") | .html_url') + +issue_number=$(gh issue list \ + --repo "$GITHUB_REPOSITORY" \ + --state open \ + --label C-broken-links \ + --label C-CI \ + --label A-linkcheck \ + --limit 100 \ + --json number,title \ + --jq '[.[] | select(.title == "[automation] Dead links found")][0].number // empty') + +if [[ -n "$issue_number" ]]; then + gh issue comment "$issue_number" \ + --repo "$GITHUB_REPOSITORY" \ + --body "The scheduled link check failed again in [CI run #$GITHUB_RUN_NUMBER]($job_url)." + exit 0 +fi + +body=$(cat <' "$@" + printf '\n' +} >> "$GH_MOCK_LOG" + +case "$command" in + api) + if [[ ${GH_MOCK_API_FAIL-} == 1 ]]; then + exit 1 + fi + echo "https://github.example/jobs/123" + ;; + issue) + if [[ ${1-} == list && -n ${GH_MOCK_ISSUE_NUMBER-} ]]; then + echo "$GH_MOCK_ISSUE_NUMBER" + fi + ;; +esac diff --git a/src/doc/rustc-dev-guide/ci/tests/report-scheduled-linkcheck-failure.sh b/src/doc/rustc-dev-guide/ci/tests/report-scheduled-linkcheck-failure.sh new file mode 100755 index 0000000000000..96526ef0ea350 --- /dev/null +++ b/src/doc/rustc-dev-guide/ci/tests/report-scheduled-linkcheck-failure.sh @@ -0,0 +1,69 @@ +#!/usr/bin/env bash + +set -euo pipefail + +repo_root=$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd) +script="$repo_root/ci/report-scheduled-linkcheck-failure.sh" +tmp=$(mktemp -d) +trap 'rm -rf "$tmp"' EXIT + +export PATH="$repo_root/ci/tests/fakes:$PATH" +export GH_MOCK_LOG="$tmp/gh.log" +export GITHUB_REPOSITORY="rust-lang/rustc-dev-guide" +export GITHUB_RUN_ID=123 +export GITHUB_RUN_NUMBER=456 +export GITHUB_SERVER_URL="https://github.com" +export GITHUB_SHA=0123456789abcdef +export GH_TOKEN=test-token + +fail() { + echo "error: $*" >&2 + exit 1 +} + +assert_log_contains() { + grep -F -- "$1" "$GH_MOCK_LOG" >/dev/null || fail "gh log does not contain: $1" +} + +assert_log_excludes() { + if grep -F -- "$1" "$GH_MOCK_LOG" >/dev/null; then + fail "gh log unexpectedly contains: $1" + fi +} + +# A first failure creates the issue with all labels and links to the failed job. +: > "$GH_MOCK_LOG" +unset GH_MOCK_ISSUE_NUMBER GH_MOCK_API_FAIL +"$script" >/dev/null +assert_log_contains 'issue <--repo> <--state> ' +assert_log_contains '<--label> <--label> <--label> ' +assert_log_contains '<--json> <--jq> <[.[] | select(.title == "[automation] Dead links found")][0].number // empty>' +assert_log_contains 'issue ' +assert_log_contains '<--title> <[automation] Dead links found>' +assert_log_contains '<--label> <--label> <--label> ' +assert_log_contains '[CI run #456](https://github.example/jobs/123)' +assert_log_excludes 'issue ' + +# A later failure comments on the existing issue instead of creating another. +: > "$GH_MOCK_LOG" +export GH_MOCK_ISSUE_NUMBER=42 +"$script" >/dev/null +assert_log_contains 'issue <42>' +assert_log_contains 'failed again in [CI run #456](https://github.example/jobs/123)' +assert_log_excludes 'issue ' + +# GitHub API errors and missing required environment variables remain fatal. +: > "$GH_MOCK_LOG" +export GH_MOCK_API_FAIL=1 +if "$script" >/dev/null 2>&1; then + fail "script succeeded after gh api failed" +fi +unset GH_MOCK_API_FAIL + +for variable in GITHUB_REPOSITORY GITHUB_RUN_ID GITHUB_RUN_NUMBER GITHUB_SERVER_URL GITHUB_SHA GH_TOKEN; do + if env -u "$variable" "$script" >/dev/null 2>&1; then + fail "script succeeded without $variable" + fi +done + +echo "report-scheduled-linkcheck-failure tests passed" From 6f389ff6a4474bca77a6897518c0b0dfddbdae71 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 29 Aug 2026 16:13:53 -0400 Subject: [PATCH 0115/1309] Use the correct sign for the division --- src/int.rs | 31 +++++++++++++++++++++++++------ tests/run/ptr_to_int_div.rs | 19 +++++++++++++++++++ 2 files changed, 44 insertions(+), 6 deletions(-) create mode 100644 tests/run/ptr_to_int_div.rs diff --git a/src/int.rs b/src/int.rs index 9633539a16bd5..4e4b911666143 100644 --- a/src/int.rs +++ b/src/int.rs @@ -21,12 +21,12 @@ use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit unsigned %: __umodti3 - self.multiplicative_operation(BinaryOp::Modulo, "mod", false, a, b) + self.division_operation(BinaryOp::Modulo, "mod", false, a, b) } pub fn gcc_srem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit signed %: __modti3 - self.multiplicative_operation(BinaryOp::Modulo, "mod", true, a, b) + self.division_operation(BinaryOp::Modulo, "mod", true, a, b) } pub fn gcc_not(&self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -215,6 +215,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.additive_operation(BinaryOp::Minus, a, b) } + fn division_operation( + &self, + operation: BinaryOp, + operation_name: &str, + signed: bool, + mut a: RValue<'gcc>, + mut b: RValue<'gcc>, + ) -> RValue<'gcc> { + let a_type = a.get_type(); + if self.is_native_int_type(a_type) && self.is_native_int_type(b.get_type()) { + let typ = if signed { a_type.to_signed(self.cx) } else { a_type.to_unsigned(self.cx) }; + if !typ.is_compatible_with(a_type) { + a = self.context.new_cast(self.location, a, typ); + } + if !typ.is_compatible_with(b.get_type()) { + b = self.context.new_cast(self.location, b, typ); + } + } + self.multiplicative_operation(operation, operation_name, signed, a, b) + } + fn multiplicative_operation( &self, operation: BinaryOp, @@ -261,15 +282,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn gcc_sdiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): check if the types are signed? // 128-bit, signed: __divti3 - // FIXME(antoyo): convert the arguments to signed? - self.multiplicative_operation(BinaryOp::Divide, "div", true, a, b) + self.division_operation(BinaryOp::Divide, "div", true, a, b) } pub fn gcc_udiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit, unsigned: __udivti3 - self.multiplicative_operation(BinaryOp::Divide, "div", false, a, b) + self.division_operation(BinaryOp::Divide, "div", false, a, b) } pub fn gcc_checked_binop( diff --git a/tests/run/ptr_to_int_div.rs b/tests/run/ptr_to_int_div.rs new file mode 100644 index 0000000000000..afc563d6c977b --- /dev/null +++ b/tests/run/ptr_to_int_div.rs @@ -0,0 +1,19 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::hint::black_box; +use std::mem::transmute; + +fn main() { + let pointer = black_box(usize::MAX) as *const (); + + let unsigned = unsafe { transmute::<*const (), usize>(pointer) }; + assert_eq!(unsigned / black_box(2), usize::MAX / 2); + assert_eq!(unsigned % black_box(2), usize::MAX % 2); + + let signed = unsafe { transmute::<*const (), isize>(pointer) }; + assert_eq!(signed / black_box(2), -1isize / 2); + assert_eq!(signed % black_box(2), -1isize % 2); +} From 56b2b76c5ac6ce33a8831b47cc55a97935d897b7 Mon Sep 17 00:00:00 2001 From: AsthaMishra Date: Sat, 29 Aug 2026 21:18:57 +0000 Subject: [PATCH 0116/1309] renamed test file issue-7055 to issue_7055_style_edition_2027 and added test file for 2024 style-edition --- tests/source/issue_7055_style_edition_2024.rs | 24 +++++++++++++++++++ ...55.rs => issue_7055_style_edition_2027.rs} | 2 +- tests/target/issue_7055_style_edition_2024.rs | 24 +++++++++++++++++++ ...55.rs => issue_7055_style_edition_2027.rs} | 0 4 files changed, 49 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue_7055_style_edition_2024.rs rename tests/source/{issue-7055.rs => issue_7055_style_edition_2027.rs} (99%) create mode 100644 tests/target/issue_7055_style_edition_2024.rs rename tests/target/{issue-7055.rs => issue_7055_style_edition_2027.rs} (100%) diff --git a/tests/source/issue_7055_style_edition_2024.rs b/tests/source/issue_7055_style_edition_2024.rs new file mode 100644 index 0000000000000..785043832542d --- /dev/null +++ b/tests/source/issue_7055_style_edition_2024.rs @@ -0,0 +1,24 @@ +// rustfmt-style_edition: 2024 + +// The `removes_trailing_whitespace` case from the 2027 test is deliberately +// absent here: at style editions before 2027 rustfmt fails with "left behind +// trailing whitespace" and emits nothing, so there is no output to check. + +struct S; + +impl S { + const fn new(_: &str) -> Self { + S + } + + fn go(&self) {} +} + +fn main() { + const { + S::new( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ) + } + .go(); +} diff --git a/tests/source/issue-7055.rs b/tests/source/issue_7055_style_edition_2027.rs similarity index 99% rename from tests/source/issue-7055.rs rename to tests/source/issue_7055_style_edition_2027.rs index 12d504aae2642..895beea3703e7 100644 --- a/tests/source/issue-7055.rs +++ b/tests/source/issue_7055_style_edition_2027.rs @@ -26,4 +26,4 @@ fn removes_trailing_whitespace() { ) } .go(); -} \ No newline at end of file +} diff --git a/tests/target/issue_7055_style_edition_2024.rs b/tests/target/issue_7055_style_edition_2024.rs new file mode 100644 index 0000000000000..785043832542d --- /dev/null +++ b/tests/target/issue_7055_style_edition_2024.rs @@ -0,0 +1,24 @@ +// rustfmt-style_edition: 2024 + +// The `removes_trailing_whitespace` case from the 2027 test is deliberately +// absent here: at style editions before 2027 rustfmt fails with "left behind +// trailing whitespace" and emits nothing, so there is no output to check. + +struct S; + +impl S { + const fn new(_: &str) -> Self { + S + } + + fn go(&self) {} +} + +fn main() { + const { + S::new( + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + ) + } + .go(); +} diff --git a/tests/target/issue-7055.rs b/tests/target/issue_7055_style_edition_2027.rs similarity index 100% rename from tests/target/issue-7055.rs rename to tests/target/issue_7055_style_edition_2027.rs From d83df84eb5f7a50a1ffae16ace8a1b29918b9b94 Mon Sep 17 00:00:00 2001 From: Raushan Singh Date: Thu, 27 Aug 2026 14:10:24 +0000 Subject: [PATCH 0117/1309] test(parser): capture current behavior for fields in traits --- .../parser/trait-item-field-colon-syntax.rs | 9 ++++++++ .../trait-item-field-colon-syntax.stderr | 22 +++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 tests/ui/parser/trait-item-field-colon-syntax.rs create mode 100644 tests/ui/parser/trait-item-field-colon-syntax.stderr diff --git a/tests/ui/parser/trait-item-field-colon-syntax.rs b/tests/ui/parser/trait-item-field-colon-syntax.rs new file mode 100644 index 0000000000000..f9c5a92d05613 --- /dev/null +++ b/tests/ui/parser/trait-item-field-colon-syntax.rs @@ -0,0 +1,9 @@ +fn main() {} + +trait Trait1 { + field_name: String, //~ ERROR expected one of `!` or `::`, found `:` +} + +trait Trait2 { + self: String, //~ ERROR expected one of `!` or `::`, found `:` +} diff --git a/tests/ui/parser/trait-item-field-colon-syntax.stderr b/tests/ui/parser/trait-item-field-colon-syntax.stderr new file mode 100644 index 0000000000000..a0d58f7a6bcd1 --- /dev/null +++ b/tests/ui/parser/trait-item-field-colon-syntax.stderr @@ -0,0 +1,22 @@ +error: expected one of `!` or `::`, found `:` + --> $DIR/trait-item-field-colon-syntax.rs:4:15 + | +LL | trait Trait1 { + | - while parsing this item list starting here +LL | field_name: String, + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: expected one of `!` or `::`, found `:` + --> $DIR/trait-item-field-colon-syntax.rs:8:9 + | +LL | trait Trait2 { + | - while parsing this item list starting here +LL | self: String, + | ^ expected one of `!` or `::` +LL | } + | - the item list ends here + +error: aborting due to 2 previous errors + From ec711b914b16718c5c6bd14cec12cd469d88c1c1 Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 28 Aug 2026 09:17:09 +0800 Subject: [PATCH 0118/1309] Preserve parentheses in raw borrow suggestions --- .../src/raw_borrows_via_references.rs | 9 ++--- ...eferences-parenthesized-issue-161693.fixed | 35 +++++++++++++++++++ ...a-references-parenthesized-issue-161693.rs | 17 +++++++-- ...ferences-parenthesized-issue-161693.stderr | 18 ++++++++-- 4 files changed, 70 insertions(+), 9 deletions(-) create mode 100644 tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.fixed diff --git a/compiler/rustc_lint/src/raw_borrows_via_references.rs b/compiler/rustc_lint/src/raw_borrows_via_references.rs index 2d17d6c301c3d..4db8f2a243678 100644 --- a/compiler/rustc_lint/src/raw_borrows_via_references.rs +++ b/compiler/rustc_lint/src/raw_borrows_via_references.rs @@ -57,15 +57,16 @@ impl<'tcx> LateLintPass<'tcx> for RawBorrowsViaReferences { && let TyKind::Ptr(_) = ty.kind && addr_of_exp.is_syntactic_place_expr() { - let suggestion = if let Some(addr_of_span) = - addr_of_exp.span.find_ancestor_in_same_ctxt(expr.span) + let suggestion = if let Some(borrow_span) = + exp.span.find_ancestor_inside_same_ctxt(expr.span) + && let Some(addr_of_span) = addr_of_exp.span.find_ancestor_in_same_ctxt(expr.span) && let Some(ty_span) = ty.span.find_ancestor_in_same_ctxt(expr.span) - && expr.span.can_be_used_for_suggestions() + && borrow_span.can_be_used_for_suggestions() && addr_of_span.can_be_used_for_suggestions() && ty_span.can_be_used_for_suggestions() { RawBorrowViaReferenceSuggestion::Spanful { - left: expr.span.until(addr_of_span), + left: borrow_span.until(addr_of_span), right: addr_of_span.shrink_to_hi().until(ty_span.shrink_to_hi()), mutbl: mutbl.ptr_str(), } diff --git a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.fixed b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.fixed new file mode 100644 index 0000000000000..2f5bc99add2d1 --- /dev/null +++ b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.fixed @@ -0,0 +1,35 @@ +//@ check-pass +//@ run-rustfix + +#![feature(const_volatile)] +#![allow(dead_code, unused_macros)] +#![warn(raw_borrows_via_references)] + +const READ: () = unsafe { + let x = 42i32; + let y = (&raw const x).read_volatile(); + //~^ WARN creating an intermediate reference implies aliasing requirements + assert!(x == y); +}; + +const WRITE: () = unsafe { + let mut x = 42i32; + (&raw mut x).write_volatile(13); + //~^ WARN creating an intermediate reference implies aliasing requirements + assert!(x == 13); +}; + +macro_rules! make_borrow { + ($value:expr) => { + &$value + }; +} + +fn macro_generated_borrow() { + let value = 0; + // the scenario of macro should also get valid fix suggestion + let _ = &raw const value; + //~^ WARN creating an intermediate reference implies aliasing requirements +} + +fn main() {} diff --git a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs index d395c0929c34d..b19fafdeca28c 100644 --- a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs +++ b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.rs @@ -1,8 +1,8 @@ //@ check-pass - -// Parenthesized reference-to-pointer casts should produce syntactically valid suggestions. +//@ run-rustfix #![feature(const_volatile)] +#![allow(dead_code, unused_macros)] #![warn(raw_borrows_via_references)] const READ: () = unsafe { @@ -19,4 +19,17 @@ const WRITE: () = unsafe { assert!(x == 13); }; +macro_rules! make_borrow { + ($value:expr) => { + &$value + }; +} + +fn macro_generated_borrow() { + let value = 0; + // the scenario of macro should also get valid fix suggestion + let _ = make_borrow!(value) as *const i32; + //~^ WARN creating an intermediate reference implies aliasing requirements +} + fn main() {} diff --git a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr index 75081f5991215..0c43a891d1d86 100644 --- a/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr +++ b/tests/ui/lint/raw-borrows-via-references-parenthesized-issue-161693.stderr @@ -12,7 +12,7 @@ LL | #![warn(raw_borrows_via_references)] help: consider using `&raw const` for a safer and more explicit raw pointer | LL - let y = (&x as *const i32).read_volatile(); -LL + let y = &raw const x).read_volatile(); +LL + let y = (&raw const x).read_volatile(); | warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers @@ -24,8 +24,20 @@ LL | (&mut x as *mut i32).write_volatile(13); help: consider using `&raw mut` for a safer and more explicit raw pointer | LL - (&mut x as *mut i32).write_volatile(13); -LL + &raw mut x).write_volatile(13); +LL + (&raw mut x).write_volatile(13); | -warning: 2 warnings emitted +warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers + --> $DIR/raw-borrows-via-references-parenthesized-issue-161693.rs:31:13 + | +LL | let _ = make_borrow!(value) as *const i32; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: consider using `&raw const` for a safer and more explicit raw pointer + | +LL - let _ = make_borrow!(value) as *const i32; +LL + let _ = &raw const value; + | + +warning: 3 warnings emitted From eb6851ec77a2f4aff356b7ddd3c8cd7235347d35 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 6 Aug 2026 19:15:04 +0200 Subject: [PATCH 0119/1309] attach naked function target features to module assembly --- src/asm.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/asm.rs b/src/asm.rs index ac86fbe7428b0..733dc52465dea 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -928,6 +928,7 @@ impl<'gcc, 'tcx> AsmCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { operands: &[GlobalAsmOperandRef<'tcx>], options: InlineAsmOptions, line_spans: &[Span], + _extra_rust_target_features: &[String], ) { let asm_arch = self.tcx.sess.asm_arch.unwrap(); From 98a157aec8b08729249aa9ca78f9703aa3a4f279 Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 31 Aug 2026 13:21:07 +0330 Subject: [PATCH 0120/1309] Add test for the fn item uniqueness note with late bound lifetimes --- .../fn/fn-item-type-note-late-bound-145558.rs | 19 ++++++++++++++++++ ...fn-item-type-note-late-bound-145558.stderr | 20 +++++++++++++++++++ 2 files changed, 39 insertions(+) create mode 100644 tests/ui/fn/fn-item-type-note-late-bound-145558.rs create mode 100644 tests/ui/fn/fn-item-type-note-late-bound-145558.stderr diff --git a/tests/ui/fn/fn-item-type-note-late-bound-145558.rs b/tests/ui/fn/fn-item-type-note-late-bound-145558.rs new file mode 100644 index 0000000000000..2463e2ba70675 --- /dev/null +++ b/tests/ui/fn/fn-item-type-note-late-bound-145558.rs @@ -0,0 +1,19 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/145558 +//! +//! The note explaining that distinct fn items have distinct types was suppressed when the +//! signatures contained a late-bound lifetime, because the two binders name their bound +//! region differently. + +//@ dont-require-annotations: NOTE + +struct A; + +fn f1<'a>(_: &'a A) {} +fn f2<'a>(_: &'a A) {} + +fn main() { + let mut map = vec![]; + map.push(f1); + map.push(f2); + //~^ ERROR mismatched types +} diff --git a/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr b/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr new file mode 100644 index 0000000000000..31d773c7e4a79 --- /dev/null +++ b/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr @@ -0,0 +1,20 @@ +error[E0308]: mismatched types + --> $DIR/fn-item-type-note-late-bound-145558.rs:17:14 + | +LL | map.push(f1); + | --- -- this argument has type `for<'a> fn(&'a A) {f1}`... + | | + | ... which causes `map` to have type `Vec fn(&'a A) {f1}>` +LL | map.push(f2); + | ---- ^^ expected fn item, found a different fn item + | | + | arguments to this method are incorrect + | + = note: expected fn item `for<'a> fn(&'a A) {f1}` + found fn item `for<'a> fn(&'a A) {f2}` +note: method defined here + --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 21228c2dfa1a8afda35130d0fd59979ed6c34937 Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 31 Aug 2026 13:23:02 +0330 Subject: [PATCH 0121/1309] Do not suppress the fn item uniqueness note for late bound lifetimes --- .../src/error_reporting/infer/suggest.rs | 4 +++- tests/ui/fn/fn-item-type-note-late-bound-145558.rs | 1 + tests/ui/fn/fn-item-type-note-late-bound-145558.stderr | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs index db852701051cf..577571196a239 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/suggest.rs @@ -521,7 +521,9 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> { let found_sig = self.normalize_fn_sig(self.tcx.fn_sig(*did2).instantiate(self.tcx, args2)); - if self.same_type_modulo_infer(expected_sig, found_sig) { + let expected_sig_anon = self.tcx.anonymize_bound_vars(expected_sig); + let found_sig_anon = self.tcx.anonymize_bound_vars(found_sig); + if self.same_type_modulo_infer(expected_sig_anon, found_sig_anon) { diag.subdiagnostic(FnUniqTypes); } diff --git a/tests/ui/fn/fn-item-type-note-late-bound-145558.rs b/tests/ui/fn/fn-item-type-note-late-bound-145558.rs index 2463e2ba70675..3e8fc0e8b14a7 100644 --- a/tests/ui/fn/fn-item-type-note-late-bound-145558.rs +++ b/tests/ui/fn/fn-item-type-note-late-bound-145558.rs @@ -16,4 +16,5 @@ fn main() { map.push(f1); map.push(f2); //~^ ERROR mismatched types + //~| NOTE different fn items have unique types } diff --git a/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr b/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr index 31d773c7e4a79..bf0a1c3316e57 100644 --- a/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr +++ b/tests/ui/fn/fn-item-type-note-late-bound-145558.stderr @@ -12,6 +12,7 @@ LL | map.push(f2); | = note: expected fn item `for<'a> fn(&'a A) {f1}` found fn item `for<'a> fn(&'a A) {f2}` + = note: different fn items have unique types, even if their signatures are the same note: method defined here --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL From bff5a0e24d5bad22ea088d3779e16c2efd03a110 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Mon, 31 Aug 2026 15:41:10 +0300 Subject: [PATCH 0122/1309] core: fix the docs of PanicInfo::location After `core::panic::PanicInfo` and `std::panic::PanicHookInfo` were split, the docs for `location` still showed incorrect usage of `std::panic::set_hook` for `core::panic::PanicInfo` location, leftover from before the split. Also notes for location methods of `PanicInfo` and `PanicHookInfo` were updated, explaining that if it is ever changed to return None, it should be addressed where the location is created and where it's unwrapped, to avoid unexpected behaviour when callers may expect to always receive location. For `PanicInfo`, `panic_fmt` builds it, and `panic_handler` unwraps it. For `PanicHookInfo`, `panic_with_hook` builds it, and `default_hook` unwraps it. --- library/core/src/panic/panic_info.rs | 23 ++++++++--------------- library/std/src/panic.rs | 2 +- 2 files changed, 9 insertions(+), 16 deletions(-) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index ee22521cb014c..6812e2758ed02 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -68,29 +68,22 @@ impl<'a> PanicInfo<'a> { /// This method will currently always return [`Some`], but this may change /// in future versions. /// - /// # Examples - /// - /// ```should_panic - /// use std::panic; + /// # Example /// - /// panic::set_hook(Box::new(|panic_info| { + /// ```ignore (no_std) + /// #[panic_handler] + /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! { /// if let Some(location) = panic_info.location() { - /// println!("panic occurred in file '{}' at line {}", - /// location.file(), - /// location.line(), - /// ); - /// } else { - /// println!("panic occurred but can't get location information..."); + /// write!(DEBUG_OUTPUT, "panicked at {}", location); /// } - /// })); - /// - /// panic!("Normal panic"); + /// loop {} + /// } /// ``` #[must_use] #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&'static Location<'static>> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. + // deal with that case in std::panicking::panic_handler and core::panicking::panic_fmt. Some(self.location) } diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index a07a5fb6290ca..23a4cabc320b0 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -162,7 +162,7 @@ impl<'a> PanicHookInfo<'a> { #[stable(feature = "panic_hooks", since = "1.10.0")] pub fn location(&self) -> Option<&'static Location<'static>> { // NOTE: If this is changed to sometimes return None, - // deal with that case in std::panicking::default_hook and core::panicking::panic_fmt. + // deal with that case in std::panicking::default_hook and std::panicking::panic_with_hook. Some(self.location) } From f092d9af82d640cbe4c64dc757e2042007b92bde Mon Sep 17 00:00:00 2001 From: N1ark Date: Mon, 17 Aug 2026 16:18:46 +0200 Subject: [PATCH 0123/1309] Make sin, cos, exp, exp2, log, log2, log10 generic --- src/intrinsic/mod.rs | 117 ++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 58 deletions(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index b3b1bea68e0b4..5550d22b33aa3 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -62,22 +62,8 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::sqrtf64 => "sqrt", sym::powif32 => "__builtin_powif", sym::powif64 => "__builtin_powi", - sym::sinf32 => "sinf", - sym::sinf64 => "sin", - sym::cosf32 => "cosf", - sym::cosf64 => "cos", sym::powf32 => "powf", sym::powf64 => "pow", - sym::expf32 => "expf", - sym::expf64 => "exp", - sym::exp2f32 => "exp2f", - sym::exp2f64 => "exp2", - sym::logf32 => "logf", - sym::logf64 => "log", - sym::log10f32 => "log10f", - sym::log10f64 => "log10", - sym::log2f32 => "log2f", - sym::log2f64 => "log2", sym::fmaf32 => "fmaf", sym::fmaf64 => "fma", // FIXME: calling `fma` from libc without FMA target feature uses expensive software emulation @@ -117,16 +103,18 @@ fn get_simple_function_f128<'gcc, 'tcx>( let f128_type = cx.type_f128(); let func_name = match name { sym::ceilf128 => "ceilf128", + sym::cos => "cosf128", sym::fabs => "fabsf128", - sym::expf128 => "expf128", - sym::exp2f128 => "exp2f128", + sym::exp => "expf128", + sym::exp2 => "exp2f128", sym::floorf128 => "floorf128", - sym::logf128 => "logf128", - sym::log2f128 => "log2f128", - sym::log10f128 => "log10f128", + sym::log => "logf128", + sym::log2 => "log2f128", + sym::log10 => "log10f128", sym::truncf128 => "truncf128", sym::roundf128 => "roundf128", sym::round_ties_even_f128 => "roundevenf128", + sym::sin => "sinf128", sym::sqrtf128 => "sqrtf128", _ => span_bug!(span, "used get_simple_function_f128 for non-unary f128 intrinsic"), }; @@ -140,24 +128,6 @@ fn get_simple_function_f128<'gcc, 'tcx>( ) } -fn generic_f16_builtin<'gcc, 'tcx>( - cx: &CodegenCx<'gcc, 'tcx>, - name: Symbol, - args: &[OperandRef<'tcx, RValue<'gcc>>], -) -> RValue<'gcc> { - let f32_type = cx.type_f32(); - let builtin_name = match name { - sym::fabs => "fabsf", - _ => unreachable!(), - }; - - let func = cx.context.get_builtin_function(builtin_name); - let args: Vec<_> = - args.iter().map(|arg| cx.context.new_cast(None, arg.immediate(), f32_type)).collect(); - let result = cx.context.new_call(None, func, &args); - cx.context.new_cast(None, result, cx.type_f16()) -} - fn f16_builtin<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, name: Symbol, @@ -167,16 +137,18 @@ fn f16_builtin<'gcc, 'tcx>( let builtin_name = match name { sym::ceilf16 => "__builtin_ceilf", sym::copysignf16 => "__builtin_copysignf", - sym::expf16 => "expf", - sym::exp2f16 => "exp2f", + sym::cos => "cosf", + sym::exp => "expf", + sym::exp2 => "exp2f", sym::fabs => "fabsf", sym::floorf16 => "__builtin_floorf", - sym::logf16 => "logf", - sym::log2f16 => "log2f", - sym::log10f16 => "log10f", + sym::log => "logf", + sym::log2 => "log2f", + sym::log10 => "log10f", sym::powf16 => "__builtin_powf", sym::roundf16 => "__builtin_roundf", sym::round_ties_even_f16 => "__builtin_rintf", + sym::sin => "sinf", sym::sqrtf16 => "__builtin_sqrtf", sym::truncf16 => "__builtin_truncf", _ => unreachable!(), @@ -245,12 +217,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } sym::ceilf16 | sym::copysignf16 - | sym::expf16 - | sym::exp2f16 | sym::floorf16 - | sym::logf16 - | sym::log2f16 - | sym::log10f16 | sym::powf16 | sym::roundf16 | sym::round_ties_even_f16 @@ -262,11 +229,6 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc | sym::roundf128 | sym::round_ties_even_f128 | sym::sqrtf128 - | sym::expf128 - | sym::exp2f128 - | sym::logf128 - | sym::log2f128 - | sym::log10f128 if self.cx.supports_f128_type => { let func = get_simple_function_f128(span, self, name); @@ -450,16 +412,55 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } } } - sym::fabs => 'fabs: { + sym::fabs + | sym::exp + | sym::exp2 + | sym::log + | sym::log10 + | sym::log2 + | sym::sin + | sym::cos => 'float_unop: { let ty = args[0].layout.ty; let ty::Float(float_ty) = *ty.kind() else { span_bug!(span, "expected float type for fabs intrinsic: {:?}", ty); }; - let func = match float_ty { - ty::FloatTy::F16 => break 'fabs generic_f16_builtin(self, name, args), - ty::FloatTy::F32 => self.context.get_builtin_function("fabsf"), - ty::FloatTy::F64 => self.context.get_builtin_function("fabs"), - ty::FloatTy::F128 => get_simple_function_f128(span, self, name), + use ty::FloatTy::*; + let func = match (name, float_ty) { + (sym::fabs, F32) => self.context.get_builtin_function("fabsf"), + (sym::fabs, F64) => self.context.get_builtin_function("fabs"), + + (sym::exp, F32) => self.context.get_builtin_function("expf"), + (sym::exp, F64) => self.context.get_builtin_function("exp"), + + (sym::exp2, F32) => self.context.get_builtin_function("exp2f"), + (sym::exp2, F64) => self.context.get_builtin_function("exp2"), + + (sym::log, F32) => self.context.get_builtin_function("logf"), + (sym::log, F64) => self.context.get_builtin_function("log"), + + (sym::log10, F32) => self.context.get_builtin_function("log10f"), + (sym::log10, F64) => self.context.get_builtin_function("log10"), + + (sym::log2, F32) => self.context.get_builtin_function("log2f"), + (sym::log2, F64) => self.context.get_builtin_function("log2"), + + (sym::sin, F32) => self.context.get_builtin_function("sinf"), + (sym::sin, F64) => self.context.get_builtin_function("sin"), + + (sym::cos, F32) => self.context.get_builtin_function("cosf"), + (sym::cos, F64) => self.context.get_builtin_function("cos"), + + (_, F32 | F64) => unreachable!(), + + (_, F16) => break 'float_unop f16_builtin(self, name, args), + (_, F128) => { + if !self.cx.supports_f128_type { + // Fall back to default body + let fallback = Instance::new_raw(instance.def_id(), instance.args); + return IntrinsicResult::Fallback(fallback); + } + get_simple_function_f128(span, self, name) + } }; self.cx.context.new_call( self.location, From f0010d1a25862cff215f525e6a5794a88691d08f Mon Sep 17 00:00:00 2001 From: Gri-ffin Date: Wed, 13 May 2026 21:05:58 +0100 Subject: [PATCH 0124/1309] extend needless_borrowed_reference to lint mutable ref patterns add inference test --- clippy_lints/src/needless_borrowed_ref.rs | 73 ++++++++++++++++++++++- tests/ui/needless_borrowed_ref.fixed | 44 ++++++++++++++ tests/ui/needless_borrowed_ref.rs | 44 ++++++++++++++ tests/ui/needless_borrowed_ref.stderr | 26 +++++++- 4 files changed, 185 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/needless_borrowed_ref.rs b/clippy_lints/src/needless_borrowed_ref.rs index dad198a903420..f267450470d20 100644 --- a/clippy_lints/src/needless_borrowed_ref.rs +++ b/clippy_lints/src/needless_borrowed_ref.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::usage::local_used_after_expr; use rustc_errors::Applicability; -use rustc_hir::{BindingMode, Mutability, Node, Pat, PatKind, Pinnedness}; +use rustc_hir::{self as hir, BindingMode, ExprKind, Mutability, Node, Pat, PatKind, Pinnedness, QPath}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; declare_clippy_lint! { @@ -104,7 +105,77 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessBorrowedRef { _ => {}, } } + + // Check for `&mut ref mut x` patterns where the `&mut` can be removed + if let PatKind::Ref(pat, Pinnedness::Not, Mutability::Mut) = ref_pat.kind + && !ref_pat.span.from_expansion() + && let PatKind::Binding(BindingMode::REF_MUT, _, ident, None) = pat.kind + && cx + .tcx + .hir_parent_iter(ref_pat.hir_id) + .map_while(|(_, parent)| if let Node::Pat(pat) = parent { Some(pat) } else { None }) + // Do not lint if behind another ref pattern (can't move out of a reference) + // or part of an OR `|` pattern + .all(|pat| !matches!(pat.kind, PatKind::Or(_) | PatKind::Ref(..))) + && can_move_ref(cx, ref_pat) + { + span_lint_and_then( + cx, + NEEDLESS_BORROWED_REFERENCE, + ref_pat.span, + "this pattern takes a mutable reference on something that is being dereferenced", + |diag| { + let span = ref_pat.span.until(ident.span); + diag.span_suggestion_verbose( + span, + "try removing the `&mut ref mut` part", + String::new(), + Applicability::MachineApplicable, + ); + }, + ); + } + } +} + +/// Checks whether the `&mut` reference matched by `ref_pat` can be moved (rather than reborrowed). +/// This is only valid when the scrutinee is a simple local variable that is not used after the +/// enclosing match/if let expression. +fn can_move_ref(cx: &LateContext<'_>, ref_pat: &Pat<'_>) -> bool { + // Walk up past patterns and arms to find the enclosing match/if let expression + let mut scrutinee_and_expr = None; + for (_, parent) in cx.tcx.hir_parent_iter(ref_pat.hir_id) { + if matches!(parent, Node::Pat(_) | Node::PatField(_) | Node::Arm(_)) { + // skip intermediate pattern/arm nodes + } else if let Node::Expr(expr) = parent { + match expr.kind { + ExprKind::Match(scrutinee, _, _) => { + scrutinee_and_expr = Some((scrutinee, expr)); + break; + }, + // the pattern's direct parent is the `Let` expression; + // keep going one level up to the `If` for the right "used after" scope. + ExprKind::Let(let_expr) => { + scrutinee_and_expr = Some((let_expr.init, expr)); + }, + ExprKind::If(..) if scrutinee_and_expr.is_some() => { + scrutinee_and_expr = scrutinee_and_expr.map(|(s, _)| (s, expr)); + break; + }, + _ => break, + } + } else { + break; + } + } + + if let Some((scrutinee, scope_expr)) = scrutinee_and_expr + && let ExprKind::Path(QPath::Resolved(None, path)) = scrutinee.kind + && let hir::def::Res::Local(local_id) = path.res + { + return !local_used_after_expr(cx, local_id, scope_expr); } + false } fn check_subpatterns<'tcx>( diff --git a/tests/ui/needless_borrowed_ref.fixed b/tests/ui/needless_borrowed_ref.fixed index 0db5ae5dbe54c..296ad69a04bc7 100644 --- a/tests/ui/needless_borrowed_ref.fixed +++ b/tests/ui/needless_borrowed_ref.fixed @@ -123,6 +123,50 @@ fn should_not_lint( } } +fn should_lint_mut_ref(x: Option<&mut i32>) { + if let Some(x) = x { + //~^ needless_borrowed_reference + *x = 0; + } +} + +fn should_not_lint_mut_ref_nested(x: Option<&mut &mut i32>) { + if let Some(&mut &mut ref mut x) = x { + *x = 0; + } +} + +fn should_not_lint_mut_ref_used_after(x: Option<&mut i32>) -> Option<&mut i32> { + if let Some(&mut ref mut x) = x { + *x = 0; + } + x +} + +struct WithDrop<'a>(Option<&'a mut i32>); +impl Drop for WithDrop<'_> { + fn drop(&mut self) {} +} + +fn should_not_lint_mut_ref_drop(x: WithDrop<'_>) { + if let Some(&mut ref mut x) = x.0 { + *x = 0; + } +} + +fn identity(value: T) -> T { + value +} + +fn inferred_scrutinee(reference: &mut i32) { + let val = identity(Some(reference)); + + if let Some(x) = val { + //~^ needless_borrowed_reference + *x = 0; + } +} + enum Animal { Cat(u64), Dog(u64), diff --git a/tests/ui/needless_borrowed_ref.rs b/tests/ui/needless_borrowed_ref.rs index 95dcd1bbc7312..c90541a314144 100644 --- a/tests/ui/needless_borrowed_ref.rs +++ b/tests/ui/needless_borrowed_ref.rs @@ -123,6 +123,50 @@ fn should_not_lint( } } +fn should_lint_mut_ref(x: Option<&mut i32>) { + if let Some(&mut ref mut x) = x { + //~^ needless_borrowed_reference + *x = 0; + } +} + +fn should_not_lint_mut_ref_nested(x: Option<&mut &mut i32>) { + if let Some(&mut &mut ref mut x) = x { + *x = 0; + } +} + +fn should_not_lint_mut_ref_used_after(x: Option<&mut i32>) -> Option<&mut i32> { + if let Some(&mut ref mut x) = x { + *x = 0; + } + x +} + +struct WithDrop<'a>(Option<&'a mut i32>); +impl Drop for WithDrop<'_> { + fn drop(&mut self) {} +} + +fn should_not_lint_mut_ref_drop(x: WithDrop<'_>) { + if let Some(&mut ref mut x) = x.0 { + *x = 0; + } +} + +fn identity(value: T) -> T { + value +} + +fn inferred_scrutinee(reference: &mut i32) { + let val = identity(Some(reference)); + + if let Some(&mut ref mut x) = val { + //~^ needless_borrowed_reference + *x = 0; + } +} + enum Animal { Cat(u64), Dog(u64), diff --git a/tests/ui/needless_borrowed_ref.stderr b/tests/ui/needless_borrowed_ref.stderr index 980022715628d..6961bc4eb6bed 100644 --- a/tests/ui/needless_borrowed_ref.stderr +++ b/tests/ui/needless_borrowed_ref.stderr @@ -213,5 +213,29 @@ LL - if let &Struct { ref a, b: _, .. } = &s {} LL + if let Struct { a, b: _, .. } = &s {} | -error: aborting due to 17 previous errors +error: this pattern takes a mutable reference on something that is being dereferenced + --> tests/ui/needless_borrowed_ref.rs:127:17 + | +LL | if let Some(&mut ref mut x) = x { + | ^^^^^^^^^^^^^^ + | +help: try removing the `&mut ref mut` part + | +LL - if let Some(&mut ref mut x) = x { +LL + if let Some(x) = x { + | + +error: this pattern takes a mutable reference on something that is being dereferenced + --> tests/ui/needless_borrowed_ref.rs:164:17 + | +LL | if let Some(&mut ref mut x) = val { + | ^^^^^^^^^^^^^^ + | +help: try removing the `&mut ref mut` part + | +LL - if let Some(&mut ref mut x) = val { +LL + if let Some(x) = val { + | + +error: aborting due to 19 previous errors From 1595b5e0ed508bb2b0246d6c1f33808c6c84857a Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 23 Jun 2026 17:17:57 +0800 Subject: [PATCH 0125/1309] [Test] Add failing regression test for non-idempotent block doc comments See . Compared to the reported MCVE, the test case added: - Adds another layer of outermost block doc comment for the outer module. - Also exercises inner block doc comments (the reported example involves only outer block doc comments). --- .../inner-block-doc-comment.rs | 9 +++++++++ .../outer-block-doc-comment.rs | 13 +++++++++++++ .../inner-block-doc-comment.rs | 9 +++++++++ .../outer-block-doc-comment.rs | 13 +++++++++++++ 4 files changed, 44 insertions(+) create mode 100644 tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs create mode 100644 tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs create mode 100644 tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs create mode 100644 tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs b/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs new file mode 100644 index 0000000000000..d46cf3688ec12 --- /dev/null +++ b/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs @@ -0,0 +1,9 @@ +/*!First comment. +*/ +pub mod outer { + /*!Second comment. +*/ + pub struct Inner { + pub octets: Vec, + } +} diff --git a/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs b/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs new file mode 100644 index 0000000000000..b1c8e1c851812 --- /dev/null +++ b/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs @@ -0,0 +1,13 @@ +/**First comment. +* +*/ +pub mod outer { + /**Second comment. +foo +*/ + pub struct Inner { + /**Third comment. +*/ + pub octets: Vec, + } +} diff --git a/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs b/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs new file mode 100644 index 0000000000000..660b855dadde5 --- /dev/null +++ b/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs @@ -0,0 +1,9 @@ +/*!First comment. + */ +pub mod outer { + /*!Second comment. + */ + pub struct Inner { + pub octets: Vec, + } +} diff --git a/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs b/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs new file mode 100644 index 0000000000000..13bd081a84624 --- /dev/null +++ b/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs @@ -0,0 +1,13 @@ +/**First comment. + * + */ +pub mod outer { + /**Second comment. + foo + */ + pub struct Inner { + /**Third comment. + */ + pub octets: Vec, + } +} From 44ca78d32e60b8af7ce9ccf8f71475791920f717 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 7 Aug 2026 16:26:23 +0800 Subject: [PATCH 0126/1309] [Comment] Make block doc comment closer rewrite idempotent # The symptom Consider the example ```rs pub mod outer { /**First comment. */ pub struct Inner { pub octets: Vec, } } ``` Previously, this was *non-idempotent* and required **2** passes to converge to a final formatting. ## Format 1 Format pass 1 tries to realign the block doc comment closer with the starter `/**`. Notice that the closer `*/` aligns with `/**` without a leading whitespace in the closer. ```diff pub mod outer { /**First comment. -*/ + */ pub struct Inner { pub octets: Vec, } ``` After this pass, if you run `rustfmt --check` on this, rustfmt will report formatting difference: ```text Diff in /Users/joe.xu/Documents/repos/rustfmt/foo.rs:1: pub mod outer { /**First comment. - */ + */ pub struct Inner { pub octets: Vec, } ``` ## Format 2 Run `rustfmt` again, then formatting converges to ```rs pub mod outer { /**First comment. */ pub struct Inner { pub octets: Vec, } } ``` Notice that the closer `*/`'s `*` now has a leading whitespace, aligning it with the first `*` in the starter `/**`. # Analysis What went wrong? The formatting pathways hit here are fairly localized, and mostly concern the pathway `identify_comment -> light_rewrite_comment`. The `light_rewrite_comment` helper has a bug where the implementation doesn't agree with the indent expressed by the comment: ```text // This is basically just l.trim(), but in the case that a line starts // with `*` we want to leave one space before it, so it aligns with the // `*` in `/*`. ``` Take the same `/**First comment.\n*/` example, the execution trace broadly looks like: ``` rustfmt_nightly::comment::identify_comment{} TRACE rustfmt_nightly::comment style=DoubleBullet TRACE rustfmt_nightly::comment block comment TRACE rustfmt_nightly::comment has_bare_lines=false, first_group_ending=20 TRACE rustfmt_nightly::comment first_group="/**First comment.\n*/", rest="" TRACE rustfmt_nightly::comment !normalize_comments && !wrap_comments && !(is_doc_comment && format_code_in_doc_comments) rustfmt_nightly::comment::light_rewrite_comment{orig="/**First comment.\n*/", offset=Indent { block_indent: 4, alignment: 0 }, is_doc_comment=true} TRACE rustfmt_nightly::comment first_non_whitespace=0 TRACE rustfmt_nightly::comment left_trimmed="/**First comment." TRACE rustfmt_nightly::comment first_non_whitespace=0 TRACE rustfmt_nightly::comment left_trimmed="*/" ``` The previous implementation was ```rs let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); let left_trimmed = if let Some(fnw) = first_non_whitespace { if l.as_bytes()[fnw] == b'*' && fnw > 0 { &l[fnw - 1..] } else { &l[fnw..] } } else { "" }; ``` The problem was that, when the closer line has no leading whitespace, i.e. `l = "*/"`, `first_non_whitespace` would trigger on `*`, and so `fnw = 0`. This would hit the else branch `&l[fnw..]`, which eventually produces an closer alignment without a leading whitespace: ```rs /** */ <- missing leading whitespace ``` # Fix The key logical fix here is to drop the `fnw > 0` condition, and in the `*`-leading branch, pad a whitespace and directly use the leading-whitespace trimmed portion `&l[fnw..]`. I used a `Cow` here because the leading-whitespace padding would need a `format!` allocation, whereas the other branch need only a string slice and no additional allocation. *Maybe* it's not worth the extra complexity and we should just use `String`, but yeah. --- src/comment.rs | 20 +++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/src/comment.rs b/src/comment.rs index 05d7310122a4b..40e42b53ed1bc 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1074,16 +1074,26 @@ fn light_rewrite_comment( // `*` in `/*`. let first_non_whitespace = l.find(|c| !char::is_whitespace(c)); let left_trimmed = if let Some(fnw) = first_non_whitespace { - if l.as_bytes()[fnw] == b'*' && fnw > 0 { - &l[fnw - 1..] + if l.as_bytes()[fnw] == b'*' { + Cow::Owned(format!(" {}", &l[fnw..])) } else { - &l[fnw..] + Cow::Borrowed(&l[fnw..]) } } else { - "" + Cow::Borrowed("") }; + // Preserve markdown's double-space line break syntax in doc comment. - trim_end_unless_two_whitespaces(left_trimmed, is_doc_comment) + match left_trimmed { + Cow::Borrowed(left_trimmed) => Cow::Borrowed(trim_end_unless_two_whitespaces( + left_trimmed, + is_doc_comment, + )), + Cow::Owned(left_trimmed) => { + let trimmed = trim_end_unless_two_whitespaces(&left_trimmed, is_doc_comment); + Cow::Owned(trimmed.to_string()) + } + } }) .join(&format!("\n{}", offset.to_string(config))) } From d8d6a47d88f38a01dd572f8671a3a1a6a8a9d311 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 7 Aug 2026 17:07:24 +0800 Subject: [PATCH 0127/1309] [Test] Demonstrate a stable default formatting change For better or worse, for outer block doc comments, this patch does unfortunately change the comment formatting for cases like ``` $ cat foo.rs /** */ mod foo {} ``` Stable rustfmt considers this already well-formatted. ```bash $ rustfmt +stable --version rustfmt 1.9.0-stable (8bab26f4f6 2026-07-14) ``` ```bash $ rustfmt +stable foo.rs --check --config-path=/dev/null ``` With this patch, we only consider the closer well-formatted if its asterisk `*` is aligned with the first `*` in the opener. ``` $ rustfmt-dev foo.rs --check --config-path=/dev/null Diff in /Users/joe.xu/Documents/repos/rustfmt/foo.rs:1: /** -*/ + */ mod foo {} ``` I believe this is acceptable, since: 1. Comments are explicitly carved out from stable formatting stability guarantees, and 2. This impacts block doc comments, which IME is extremely rarely used. --- .../naive-outer-block-comment.rs | 3 +++ .../naive-outer-block-comment.rs | 3 +++ 2 files changed, 6 insertions(+) create mode 100644 tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs create mode 100644 tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs b/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs new file mode 100644 index 0000000000000..581dea9e3ab7f --- /dev/null +++ b/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs @@ -0,0 +1,3 @@ +/** +*/ +mod foo {} diff --git a/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs b/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs new file mode 100644 index 0000000000000..42f39ee29ae5e --- /dev/null +++ b/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs @@ -0,0 +1,3 @@ +/** + */ +mod foo {} From 892ea2c6b6b7ff5e798c3d547fbaa937fb5ca5a6 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 1 Sep 2026 18:18:12 +0800 Subject: [PATCH 0128/1309] [Test] Demonstrate `rustc` block doc comment alignment changes The difference manifests in: (1) The closer's asterisk `*` now alignments with starter asterisk. Previously there was a `rustc_mir_transform` block doc comment that had a misaligned closer: ```rs /** * Integrator. * * Integrates blocks from the callee function into the calling function. * Updates block indices, references to locals and other control flow * stuff. */ <-- ``` This is now properly aligned with the starter. (2) Continuing asterisks now align with starter asterisk. Previously there was a `rustc_codegen_llvm` block doc comment ```rs /* * A note on nomenclature of linking: "extern", "foreign", and "upcall". * [...] * */ ``` where continuing asterisks were flush with line beginnings and not aligned with starter asterisk. Continuing asteriks now align with the starter asterisk. --- .../rustc-sample-1.rs | 34 +++++++++++++++++++ .../rustc-sample-2.rs | 24 +++++++++++++ .../rustc-sample-1.rs | 34 +++++++++++++++++++ .../rustc-sample-2.rs | 24 +++++++++++++ 4 files changed, 116 insertions(+) create mode 100644 tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs create mode 100644 tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs create mode 100644 tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs create mode 100644 tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs b/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs new file mode 100644 index 0000000000000..56cbb7197194a --- /dev/null +++ b/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs @@ -0,0 +1,34 @@ +//! Sample from +//! . + +pub(crate) fn placeholder() {} + +/* +* A note on nomenclature of linking: "extern", "foreign", and "upcall". +* +* An "extern" is an LLVM symbol we wind up emitting an undefined external +* reference to. This means "we don't have the thing in this compilation unit, +* please make sure you link it in at runtime". This could be a reference to +* C code found in a C library, or rust code found in a rust crate. +* +* Most "externs" are implicitly declared (automatically) as a result of a +* user declaring an extern _module_ dependency; this causes the rust driver +* to locate an extern crate, scan its compilation metadata, and emit extern +* declarations for any symbols used by the declaring crate. +* +* A "foreign" is an extern that references C (or other non-rust ABI) code. +* There is no metadata to scan for extern references so in these cases either +* a header-digester like bindgen, or manual function prototypes, have to +* serve as declarators. So these are usually given explicitly as prototype +* declarations, in rust code, with ABI attributes on them noting which ABI to +* link via. +* +* An "upcall" is a foreign call generated by the compiler (not corresponding +* to any user-written call in the code) into the runtime library, to perform +* some helper task such as bringing a task to life, allocating memory, etc. +* +*/ + +/// A structure representing an active landing pad for the duration of a basic +/// block. +pub(crate) struct Funclet<'ll> {} diff --git a/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs b/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs new file mode 100644 index 0000000000000..399a31fc33bd2 --- /dev/null +++ b/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs @@ -0,0 +1,24 @@ +//! Taken from +//! . + +/** + * Integrator. + * + * Integrates blocks from the callee function into the calling function. + * Updates block indices, references to locals and other control flow + * stuff. +*/ +struct Integrator<'a, 'tcx> { + args: &'a [Local], + new_locals: RangeFrom, + new_scopes: RangeFrom, + new_blocks: RangeFrom, + destination: Local, + callsite_scope: SourceScopeData<'tcx>, + callsite: &'a CallSite<'tcx>, + cleanup_block: UnwindAction, + in_cleanup_block: bool, + return_block: Option, + tcx: TyCtxt<'tcx>, + always_live_locals: DenseBitSet, +} diff --git a/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs b/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs new file mode 100644 index 0000000000000..cb89c7fe1465a --- /dev/null +++ b/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs @@ -0,0 +1,34 @@ +//! Sample from +//! . + +pub(crate) fn placeholder() {} + +/* + * A note on nomenclature of linking: "extern", "foreign", and "upcall". + * + * An "extern" is an LLVM symbol we wind up emitting an undefined external + * reference to. This means "we don't have the thing in this compilation unit, + * please make sure you link it in at runtime". This could be a reference to + * C code found in a C library, or rust code found in a rust crate. + * + * Most "externs" are implicitly declared (automatically) as a result of a + * user declaring an extern _module_ dependency; this causes the rust driver + * to locate an extern crate, scan its compilation metadata, and emit extern + * declarations for any symbols used by the declaring crate. + * + * A "foreign" is an extern that references C (or other non-rust ABI) code. + * There is no metadata to scan for extern references so in these cases either + * a header-digester like bindgen, or manual function prototypes, have to + * serve as declarators. So these are usually given explicitly as prototype + * declarations, in rust code, with ABI attributes on them noting which ABI to + * link via. + * + * An "upcall" is a foreign call generated by the compiler (not corresponding + * to any user-written call in the code) into the runtime library, to perform + * some helper task such as bringing a task to life, allocating memory, etc. + * + */ + +/// A structure representing an active landing pad for the duration of a basic +/// block. +pub(crate) struct Funclet<'ll> {} diff --git a/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs b/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs new file mode 100644 index 0000000000000..04dd6e8698bc2 --- /dev/null +++ b/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs @@ -0,0 +1,24 @@ +//! Taken from +//! . + +/** + * Integrator. + * + * Integrates blocks from the callee function into the calling function. + * Updates block indices, references to locals and other control flow + * stuff. + */ +struct Integrator<'a, 'tcx> { + args: &'a [Local], + new_locals: RangeFrom, + new_scopes: RangeFrom, + new_blocks: RangeFrom, + destination: Local, + callsite_scope: SourceScopeData<'tcx>, + callsite: &'a CallSite<'tcx>, + cleanup_block: UnwindAction, + in_cleanup_block: bool, + return_block: Option, + tcx: TyCtxt<'tcx>, + always_live_locals: DenseBitSet, +} From 02ae391b437a208e4797b469142103e86588a1b2 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 31 Aug 2026 23:50:45 -0400 Subject: [PATCH 0129/1309] fix: Prevent infinite loops when parsing items from `cfg_select!` arms Before when we failed to parse an item we'd hit an infinite loop because we wouldn't advance the parser. Now we make sure to advance the parser before starting the next loop iteration. --- src/parse/macros/cfg_select.rs | 6 +++++- tests/source/issue_7088_stable.rs | 12 ++++++++++++ tests/source/issue_7088_unstable.rs | 10 ++++++++++ tests/target/issue_7088_stable.rs | 12 ++++++++++++ tests/target/issue_7088_unstable.rs | 16 ++++++++++++++++ 5 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 tests/source/issue_7088_stable.rs create mode 100644 tests/source/issue_7088_unstable.rs create mode 100644 tests/target/issue_7088_stable.rs create mode 100644 tests/target/issue_7088_unstable.rs diff --git a/src/parse/macros/cfg_select.rs b/src/parse/macros/cfg_select.rs index 7127445a18984..de8f61d24121e 100644 --- a/src/parse/macros/cfg_select.rs +++ b/src/parse/macros/cfg_select.rs @@ -64,7 +64,11 @@ fn parse_items_from_cfg_select_inner<'a>( .parse_item(ForceCollect::No, AllowConstBlockItems::DoesNotMatter) { Ok(Some(item_ptr)) => *item_ptr, - Ok(None) => continue, + Ok(None) => { + // Advance the parser by at least one token to prevent an infinite loop + parser.bump(); + continue; + } Err(err) => { err.cancel(); parser.psess.dcx().reset_err_count(); diff --git a/tests/source/issue_7088_stable.rs b/tests/source/issue_7088_stable.rs new file mode 100644 index 0000000000000..a769a71b9983f --- /dev/null +++ b/tests/source/issue_7088_stable.rs @@ -0,0 +1,12 @@ +// rustfmt-stable: true + +// cfg_select! doesn't get formatted, but indentation is updated. + +#![crate_type = "lib"] + cfg_select! { + _ => { + fn foo(){} {} + } + } + +cfg_select! { _ => {{} {}}} diff --git a/tests/source/issue_7088_unstable.rs b/tests/source/issue_7088_unstable.rs new file mode 100644 index 0000000000000..69c8d246e20a4 --- /dev/null +++ b/tests/source/issue_7088_unstable.rs @@ -0,0 +1,10 @@ +// rustfmt-unstable: true + +#![crate_type = "lib"] + cfg_select! { + _ => { + fn foo(){} {} + } +} + +cfg_select! { _ => {{} {}}} diff --git a/tests/target/issue_7088_stable.rs b/tests/target/issue_7088_stable.rs new file mode 100644 index 0000000000000..80bffedc76f1f --- /dev/null +++ b/tests/target/issue_7088_stable.rs @@ -0,0 +1,12 @@ +// rustfmt-stable: true + +// cfg_select! doesn't get formatted, but indentation is updated. + +#![crate_type = "lib"] +cfg_select! { + _ => { + fn foo(){} {} + } +} + +cfg_select! { _ => {{} {}}} diff --git a/tests/target/issue_7088_unstable.rs b/tests/target/issue_7088_unstable.rs new file mode 100644 index 0000000000000..03d3e63b47212 --- /dev/null +++ b/tests/target/issue_7088_unstable.rs @@ -0,0 +1,16 @@ +// rustfmt-unstable: true + +#![crate_type = "lib"] +cfg_select! { + _ => { + fn foo() {} + {} + } +} + +cfg_select! { + _ => { + {} + {} + } +} From aa81ad40bb6830d9eda306fcd1bf0e783ce5edc4 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Wed, 2 Sep 2026 12:48:57 -0400 Subject: [PATCH 0130/1309] test: Add more #![feature(generic_const_items)] test cases Closes rust-lang/rustfmt 7092 --- tests/source/generic_static.rs | 2 ++ tests/target/generic_static.rs | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/tests/source/generic_static.rs b/tests/source/generic_static.rs index 3702daed00813..d6cb3976edf77 100644 --- a/tests/source/generic_static.rs +++ b/tests/source/generic_static.rs @@ -3,3 +3,5 @@ pub const SORT: &[T]= const { 4}; pub const SORT: &[T] = const { 4 }; + +pub const POLY_CONST_1: () = if C { func3() }; diff --git a/tests/target/generic_static.rs b/tests/target/generic_static.rs index b8593760ef0e0..a6311dc01911e 100644 --- a/tests/target/generic_static.rs +++ b/tests/target/generic_static.rs @@ -10,3 +10,7 @@ pub const SORT< FFFFF, G, >: &[T] = const { 4 }; + +pub const POLY_CONST_1: () = if C { + func3() +}; From 2711eb54517d9fc434572ee5f03038cb60392045 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Wed, 2 Sep 2026 18:14:05 +0100 Subject: [PATCH 0131/1309] refactor(chain): refactor reference matching * Replace `ref` patterns with `&` ones * Use `Box::deref` to simplify matching log --- src/chains.rs | 42 ++++++++++++++++++------------------------ 1 file changed, 18 insertions(+), 24 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index 4bb2f66d484f7..ad0b58f89c186 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -228,47 +228,41 @@ impl ChainItemKind { expr: &ast::Expr, is_postfix_receiver: bool, ) -> (ChainItemKind, Span) { - let (kind, span) = match expr.kind { - ast::ExprKind::MethodCall(ref call) => { - let types = if let Some(ref generic_args) = call.seg.args { - if let ast::GenericArgs::AngleBracketed(ref data) = **generic_args { - data.args - .iter() - .filter_map(|x| match x { - ast::AngleBracketedArg::Arg(ref generic_arg) => { - Some(generic_arg.clone()) - } - _ => None, - }) - .collect::>() - } else { - vec![] - } - } else { - vec![] + let (kind, span) = match &expr.kind { + ast::ExprKind::MethodCall(call) => { + let types = match call.seg.args.as_deref() { + Some(ast::GenericArgs::AngleBracketed(data)) => data + .args + .iter() + .filter_map(|x| match x { + ast::AngleBracketedArg::Arg(generic_arg) => Some(generic_arg.clone()), + _ => None, + }) + .collect::>(), + _ => vec![], }; let span = mk_sp(call.receiver.span.hi(), expr.span.hi()); let kind = ChainItemKind::MethodCall(call.seg.clone(), types, call.args.clone()); (kind, span) } - ast::ExprKind::Field(ref nested, field) => { + ast::ExprKind::Field(nested, field) => { let kind = if Self::is_tup_field_access(expr) { - ChainItemKind::TupleField(field, Self::is_tup_field_access(nested)) + ChainItemKind::TupleField(*field, Self::is_tup_field_access(nested)) } else { - ChainItemKind::StructField(field) + ChainItemKind::StructField(*field) }; let span = mk_sp(nested.span.hi(), field.span.hi()); (kind, span) } - ast::ExprKind::Await(ref nested, _) => { + ast::ExprKind::Await(nested, _) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Await, span) } - ast::ExprKind::Use(ref nested, _) => { + ast::ExprKind::Use(nested, _) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Use, span) } - ast::ExprKind::Yield(ast::YieldKind::Postfix(ref nested)) => { + ast::ExprKind::Yield(ast::YieldKind::Postfix(nested)) => { let span = mk_sp(nested.span.hi(), expr.span.hi()); (ChainItemKind::Yield, span) } From f050628b308c1f182111aa1ca290cdc379d7a435 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Wed, 2 Sep 2026 18:20:30 +0100 Subject: [PATCH 0132/1309] refactor(chain): rework `TupleField` definition * Use name fields, since the role of the fields wasn't immediately clear in a tuple * Split out a helper function to make things slightly more explicit: the old callsite `Self::is_tup_field_access(expr)` made a redundant check that a `Field` expression (already determined from the `match` condition) is indeed a `Field` expression. --- src/chains.rs | 34 ++++++++++++++++++++++------------ 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index ad0b58f89c186..45d9d488c76ba 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -193,7 +193,12 @@ enum ChainItemKind { ThinVec>, ), StructField(symbol::Ident), - TupleField(symbol::Ident, bool), + /// Tuple field access like `foo.1`. + TupleField { + field: symbol::Ident, + /// Whether this is a nested tuple access, like `.2` in `foo.1.2`. + is_nested: bool, + }, Await, Use, Yield, @@ -206,7 +211,7 @@ impl ChainItemKind { ChainItemKind::Parent { expr, .. } => utils::is_block_expr(context, expr, reps), ChainItemKind::MethodCall(..) | ChainItemKind::StructField(..) - | ChainItemKind::TupleField(..) + | ChainItemKind::TupleField { .. } | ChainItemKind::Await | ChainItemKind::Use | ChainItemKind::Yield @@ -214,15 +219,17 @@ impl ChainItemKind { } } - fn is_tup_field_access(expr: &ast::Expr) -> bool { - match expr.kind { - ast::ExprKind::Field(_, ref field) => { - field.name.as_str().chars().all(|c| c.is_digit(10)) - } + fn is_tup_field_access_expr(expr: &ast::Expr) -> bool { + match &expr.kind { + ast::ExprKind::Field(_, right) => Self::is_tup_field_ident(right), _ => false, } } + fn is_tup_field_ident(field: &symbol::Ident) -> bool { + field.name.as_str().chars().all(|c| c.is_ascii_digit()) + } + fn from_ast( context: &RewriteContext<'_>, expr: &ast::Expr, @@ -246,8 +253,11 @@ impl ChainItemKind { (kind, span) } ast::ExprKind::Field(nested, field) => { - let kind = if Self::is_tup_field_access(expr) { - ChainItemKind::TupleField(*field, Self::is_tup_field_access(nested)) + let kind = if Self::is_tup_field_ident(field) { + ChainItemKind::TupleField { + field: *field, + is_nested: Self::is_tup_field_access_expr(nested), + } } else { ChainItemKind::StructField(*field) }; @@ -303,14 +313,14 @@ impl Rewrite for ChainItem { Self::rewrite_method_call(segment.ident, types, exprs, self.span, context, shape)? } ChainItemKind::StructField(ident) => format!(".{}", rewrite_ident(context, ident)), - ChainItemKind::TupleField(ident, nested) => format!( + ChainItemKind::TupleField { field, is_nested } => format!( "{}.{}", - if nested && context.config.style_edition() <= StyleEdition::Edition2021 { + if is_nested && context.config.style_edition() <= StyleEdition::Edition2021 { " " } else { "" }, - rewrite_ident(context, ident) + rewrite_ident(context, field) ), ChainItemKind::Await => ".await".to_owned(), ChainItemKind::Use => ".use".to_owned(), From 8898b4dbe47b15f88b59b9c6a3db524ff1174e89 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 3 Sep 2026 16:28:08 +0800 Subject: [PATCH 0133/1309] [Triagebot] Allow more labels to be changed w/out write access Through triagebot. --- triagebot.toml | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index 3463476c28588..b68e7e1394dbf 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -13,11 +13,15 @@ allow-unauthenticated = [ "E-*", "F-*", "I-*", + "needs-rfc", + "needs-triage", + "regression-*", "S-*", "SO-*", + "T-*", "UO-*", - "needs-triage", - "regression-*", + "unstable-language-feature", + "unstable-option", ] # ------------------------------------------------------------------------------ From 9b8936e04b65b8f79007266bfdbaad12ebea4e24 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 3 Sep 2026 16:32:11 +0800 Subject: [PATCH 0134/1309] [Triagebot] Match `X-*` for updated formatting stability labels --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index b68e7e1394dbf..3d1aa11b4bee7 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -22,6 +22,7 @@ allow-unauthenticated = [ "UO-*", "unstable-language-feature", "unstable-option", + "X-*", ] # ------------------------------------------------------------------------------ From 7e43fd248740886dd756235806e8aaf7582f559c Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 20 Aug 2026 07:04:27 +0000 Subject: [PATCH 0135/1309] add trait_is_marker to Interner --- compiler/rustc_middle/src/ty/context/impl_interner.rs | 4 ++++ compiler/rustc_type_ir/src/interner.rs | 2 ++ 2 files changed, 6 insertions(+) diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 74327278dbca6..388832f411ac3 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -622,6 +622,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.trait_is_auto(trait_def_id) } + fn trait_is_marker(self, trait_def_id: DefId) -> bool { + self.trait_def(trait_def_id).is_marker + } + fn trait_is_coinductive(self, trait_def_id: DefId) -> bool { self.trait_is_coinductive(trait_def_id) } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 1dfb34d94c0fc..3f1ba7ea112e2 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -477,6 +477,8 @@ pub trait Interner: fn trait_is_auto(self, trait_def_id: Self::TraitId) -> bool; + fn trait_is_marker(self, trait_def_id: Self::TraitId) -> bool; + fn trait_is_coinductive(self, trait_def_id: Self::TraitId) -> bool; fn trait_is_alias(self, trait_def_id: Self::TraitId) -> bool; From ab244974cf26dc02447883bb932355afee803d4f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 26 Jul 2026 08:39:24 -0400 Subject: [PATCH 0136/1309] Add core doctests --- build_system/src/test.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 3ea62b9579870..7d5c70043143f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -32,6 +32,7 @@ fn get_runners() -> Runners { runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--test-release-libcore", ("Run libcore tests", test_release_libcore)); + runners.insert("--test-libcore-doctests", ("Run libcore doc-tests", test_libcore_doctests)); runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); @@ -787,6 +788,16 @@ fn test_libcore_inner(env: &Env, args: &TestArg, release: bool) -> Result<(), St Ok(()) } +fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] libcore doctests"); + let path = get_sysroot_dir().join("sysroot_src/library/core"); + let _ = remove_dir_all(path.join("target")); + // FIXME(antoyo): run in release mode when we fix the failures. + run_cargo_command(&[&"test"], Some(&path), env, args)?; + Ok(()) +} + fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { println!("[TEST] stdarch"); let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); From 4da8c7480832d561eef411c4544a3e5a21d0571c Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 2 Sep 2026 17:38:45 -0400 Subject: [PATCH 0137/1309] Fix libcore doc tests --- build_system/src/test.rs | 59 ++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 5 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 7d5c70043143f..03e0b0b99d66f 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,10 +1,12 @@ use std::collections::HashMap; use std::ffi::OsStr; -use std::fs::{File, remove_dir_all}; +use std::fs::{File, read_to_string, remove_dir_all}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::str::FromStr; +use boml::Toml; + use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ @@ -788,13 +790,60 @@ fn test_libcore_inner(env: &Env, args: &TestArg, release: bool) -> Result<(), St Ok(()) } +/// Returns the edition declared in the manifest of the given library crate, so that the doctests +/// are run with the same edition as the crate they are extracted from. +fn get_crate_edition(crate_dir: &Path) -> Result { + let manifest_path = crate_dir.join("Cargo.toml"); + let content = read_to_string(&manifest_path) + .map_err(|error| format!("Failed to read `{}`: {error:?}", manifest_path.display()))?; + let manifest = Toml::parse(&content) + .map_err(|error| format!("Failed to parse `{}`: {error:?}", manifest_path.display()))?; + manifest + .get_table("package") + .and_then(|package| package.get_string("edition")) + .map(|edition| edition.to_string()) + .map_err(|error| { + format!("Failed to get `package.edition` from `{}`: {error:?}", manifest_path.display()) + }) +} + fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] libcore doctests"); - let path = get_sysroot_dir().join("sysroot_src/library/core"); - let _ = remove_dir_all(path.join("target")); - // FIXME(antoyo): run in release mode when we fix the failures. - run_cargo_command(&[&"test"], Some(&path), env, args)?; + + let library_dir = get_sysroot_dir().join("sysroot_src/library"); + let edition = get_crate_edition(&library_dir.join("core"))?; + // `rustdoc` is called directly instead of through `cargo test --doc` because `cargo` builds its + // own `core` and passes it with `--extern`, which then conflicts with the `core` of the sysroot + // the doctests are linked against ("duplicate lang item" errors). + let toolchain = get_toolchain()?; + let toolchain_arg = format!("+{toolchain}"); + let rustflags = split_args(&env.get("RUSTFLAGS").cloned().unwrap_or_default())?; + // `-Zunstable-options` is needed for `--test-args`. + let mut command: Vec<&dyn AsRef> = vec![ + &"rustdoc", + &toolchain_arg, + &"--test", + &"core/src/lib.rs", + &"--crate-name", + &"core", + &"--crate-type", + &"lib", + &"--edition", + &edition, + &"-Zunstable-options", + ]; + for flag in &rustflags { + command.push(flag); + } + // Additional arguments are forwarded to the test harness, so that a subset of the doctests can + // be run. + let test_args = + args.test_args.iter().map(|test_arg| format!("--test-args={test_arg}")).collect::>(); + for test_arg in &test_args { + command.push(test_arg); + } + run_command_with_output_and_env(&command, Some(&library_dir), Some(env))?; Ok(()) } From bee81fe1287400b0e970893ab5cc39a891427f9e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 3 Sep 2026 13:30:16 -0400 Subject: [PATCH 0138/1309] Run libcore doctests in CI --- .github/workflows/ci.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 3bccb5ccdd72e..529003fc384a0 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,7 +31,7 @@ jobs: # "--asm-tests", "--test-libcore", "--extended-rand-tests", - "--extended-regex-example-tests", + "--extended-regex-example-tests --test-libcore-doctests", "--extended-regex-tests", "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", From ad87e6cd7aa494afb32758e1e3928496b65c0551 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 2 Sep 2026 18:30:58 -0400 Subject: [PATCH 0139/1309] Implement simd_arith_offset --- src/intrinsic/simd.rs | 38 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 36 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 1416f4eec9c4a..1b2c3d2297684 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -11,11 +11,12 @@ use rustc_codegen_ssa::diagnostics::ExpectedPointerMutability; use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, LayoutTypeCodegenMethods}; #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::span_bug; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; @@ -655,6 +656,39 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); } + if name == sym::simd_arith_offset { + // This also checks that the first operand is a ptr type. + let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| { + span_bug!(span, "must be called with a vector of pointer types as first argument") + }); + let layout = bx.layout_of(pointee); + // The second argument must be a ptr-sized integer. + // (We don't care about the signedness, this is wrapping anyway.) + let (_, offsets_elem) = args[1].layout.ty.simd_size_and_type(bx.tcx()); + if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) { + span_bug!( + span, + "must be called with a vector of pointer-sized integers as second argument" + ); + } + + let pointee_type = bx.backend_type(layout); + let pointers = args[0].immediate(); + let offsets = args[1].immediate(); + let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let index = bx.gcc_int(bx.usize_type, i as _); + let pointer = bx.extract_element(pointers, index); + let offset = bx.extract_element(offsets, index); + let pointer = bx.gep(pointee_type, pointer, &[offset]); + // GCC has no pointer vectors, so the lanes are `usize`. + bx.ptrtoint(pointer, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); From 0f89894c27b90415c8a8457c18ff50bf8ab40d50 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 2 Sep 2026 19:29:09 -0400 Subject: [PATCH 0140/1309] Workaround broken libcore doc-test --- build_system/src/test.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 03e0b0b99d66f..2e9a67f9a8cd8 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -832,6 +832,10 @@ fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { &"--edition", &edition, &"-Zunstable-options", + // FIXME: remove `-Zforce-unstable-if-unmarked` once the doctest of + // `core::io::ErrorKind`'s `Display` impl declares `#![feature(core_io)]` upstream: without + // it, that doctest fails to compile with `E0658` on any backend. + &"-Zforce-unstable-if-unmarked", ]; for flag in &rustflags { command.push(flag); From 5e6146fe563b3e12757f163dd518756f433e9472 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Wed, 2 Sep 2026 19:30:20 -0400 Subject: [PATCH 0141/1309] Fix generic_simd_intrinsic --- src/intrinsic/simd.rs | 49 +++++++++++++++++--------- tests/run/simd.rs | 81 +++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 114 insertions(+), 16 deletions(-) create mode 100644 tests/run/simd.rs diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 1b2c3d2297684..09c0467063cd6 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -709,20 +709,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(args[0].immediate()); } + #[derive(Copy, Clone)] + enum Sign { + Unsigned, + Signed, + } + use Sign::*; + enum Style { Float, - Int, + Int(Sign), Unsupported, } let in_style = match *in_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Int(_) => Style::Int(Signed), + ty::Uint(_) => Style::Int(Unsigned), ty::Float(_) => Style::Float, _ => Style::Unsupported, }; - let out_style = match *out_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Int(_) => Style::Int(Signed), + ty::Uint(_) => Style::Int(Unsigned), ty::Float(_) => Style::Float, _ => Style::Unsupported, }; @@ -741,6 +749,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } ); } + (Style::Float, Style::Int(sign)) if name == sym::simd_as => { + let vector = args[0].immediate(); + let elem_type = + llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let index = bx.context.new_rvalue_from_int(bx.usize_type, i as _); + let value = bx.extract_element(vector, index); + bx.cast_float_to_int(matches!(sign, Sign::Signed), value, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } } @@ -1344,32 +1365,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (true, false) => { // FIXME(antoyo): dyncast_vector should not require a call to unqualified. let arg_type = lhs.get_type().unqualified(); - // FIXME(antoyo): this uses the same algorithm from saturating add, but add the - // negative of the right operand. Find a proper subtraction algorithm. - let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - // FIXME(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; + let difference = lhs - rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); let unit = vector_type.get_num_units(); let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + // The subtraction overflows when the operands have different signs and the result + // has a different sign than the left operand. let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = - bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; + let xor2 = lhs ^ difference; + let mask = (xor1 & xor2) >> width; let one = bx.context.new_rvalue_one(elem_ty); let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); let shift1 = ones << width; - let shift2 = sum >> width; + let shift2 = difference >> width; let mask_min = shift1 ^ shift2; - let and1 = - bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) + & difference; let and2 = mask & mask_min; and1 + and2 diff --git a/tests/run/simd.rs b/tests/run/simd.rs new file mode 100644 index 0000000000000..e0a23fdccf8ce --- /dev/null +++ b/tests/run/simd.rs @@ -0,0 +1,81 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(portable_simd)] + +use std::hint::black_box; +use std::simd::prelude::*; + +fn test_saturating_add() { + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let ones = i32x4::splat(1); + assert_eq!( + black_box(values).saturating_add(black_box(ones)).to_array(), + [i32::MIN + 1, -1, 4, i32::MAX] + ); + + let values = u32x4::from_array([0, 2, 3, u32::MAX]); + let ones = u32x4::splat(1); + assert_eq!(black_box(values).saturating_add(black_box(ones)).to_array(), [1, 3, 4, u32::MAX]); +} + +fn test_saturating_sub() { + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let zero = i32x4::splat(0); + assert_eq!( + black_box(zero).saturating_sub(black_box(values)).to_array(), + [i32::MAX, 2, -3, i32::MIN + 1] + ); + assert_eq!(black_box(values).saturating_neg().to_array(), [i32::MAX, 2, -3, i32::MIN + 1]); + assert_eq!(black_box(values).saturating_abs().to_array(), [i32::MAX, 2, 3, i32::MAX]); + + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let ones = i32x4::splat(1); + assert_eq!( + black_box(values).saturating_sub(black_box(ones)).to_array(), + [i32::MIN, -3, 2, i32::MAX - 1] + ); + + let values = u32x4::from_array([0, 2, 3, u32::MAX]); + let ones = u32x4::splat(1); + assert_eq!( + black_box(values).saturating_sub(black_box(ones)).to_array(), + [0, 1, 2, u32::MAX - 1] + ); +} + +fn test_float_cast() { + let floats = f32x4::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]); + assert_eq!(black_box(floats).cast::().to_array(), [1, -4, i32::MAX, 0]); + + let floats = f32x4::from_array([f32::NEG_INFINITY, 1e20, -1e20, -0.0]); + assert_eq!(black_box(floats).cast::().to_array(), [i32::MIN, i32::MAX, i32::MIN, 0]); + + let floats = f32x4::from_array([-1.0, 3.7, f32::NAN, 1e20]); + assert_eq!(black_box(floats).cast::().to_array(), [0, 3, 0, u32::MAX]); + + let floats = f64x4::from_array([-1.5, 2.5, f64::NAN, f64::INFINITY]); + assert_eq!(black_box(floats).cast::().to_array(), [-1, 2, 0, i64::MAX]); +} + +fn test_arith_offset() { + let values = [10i32, 11, 12, 13, 14, 15, 16, 17]; + let indices = usizex4::from_array([7, 5, 3, 1]); + assert_eq!( + i32x4::gather_or_default(black_box(&values), black_box(indices)).to_array(), + [17, 15, 13, 11] + ); + + let mut destination = [0i32; 8]; + i32x4::from_array([1, 2, 3, 4]).scatter(black_box(&mut destination), black_box(indices)); + assert_eq!(destination, [0, 4, 0, 3, 0, 2, 0, 1]); +} + +fn main() { + test_saturating_add(); + test_saturating_sub(); + test_float_cast(); + test_arith_offset(); +} From 15cc44904ca708187d21d6386ee7ef38af7fb7fe Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 3 Sep 2026 14:24:54 -0400 Subject: [PATCH 0142/1309] Switch to new_rvalue_from_long in generic_simd_intrinsic --- src/intrinsic/simd.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 09c0467063cd6..02f1f7efd9c1e 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -678,7 +678,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); let values: Vec<_> = (0..in_len) .map(|i| { - let index = bx.gcc_int(bx.usize_type, i as _); + let index = bx.context.new_rvalue_from_long(bx.usize_type, i as _); let pointer = bx.extract_element(pointers, index); let offset = bx.extract_element(offsets, index); let pointer = bx.gep(pointee_type, pointer, &[offset]); @@ -755,7 +755,7 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( llret_ty.dyncast_vector().expect("vector return type").get_element_type(); let values: Vec<_> = (0..in_len) .map(|i| { - let index = bx.context.new_rvalue_from_int(bx.usize_type, i as _); + let index = bx.context.new_rvalue_from_long(bx.usize_type, i as _); let value = bx.extract_element(vector, index); bx.cast_float_to_int(matches!(sign, Sign::Signed), value, elem_type) }) From d35eac8f66c7c473909d9dcb34ae06439b7fc6e3 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 3 Sep 2026 14:27:30 -0400 Subject: [PATCH 0143/1309] Remove passing test --- tests/failing-ui-tests.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index ce614fecba2ba..7f96bfabedbea 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -5,7 +5,6 @@ tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs tests/ui/process/println-with-broken-pipe.rs tests/ui/simd/repr_packed.rs -tests/ui/simd/intrinsic/generic-as.rs tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs From 1f95ab714cf61459a5be86cfb2390ac0677b38ad Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 3 Sep 2026 15:50:37 +0800 Subject: [PATCH 0144/1309] [Triagebot] Enable `issue-links` --- triagebot.toml | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 3463476c28588..d75a32549e099 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -102,3 +102,15 @@ add_labels = ["S-waiting-on-review"] # ------------------------------------------------------------------------------ [assign] + +# ------------------------------------------------------------------------------ +# Misc +# ------------------------------------------------------------------------------ + +# Canonicalize issue numbers to avoid closing the wrong issue +# when commits are included in subtrees, as well as warning links in commits. +# Documentation at: https://forge.rust-lang.org/triagebot/issue-links.html +[issue-links] +# This prevents links from resolving to the wrong repository when the subtree is +# merged upstream while still allowing issue links in commits. +check-commits = "uncanonicalized" From df878714809b7a7874442b886d031bcb2c0d92a0 Mon Sep 17 00:00:00 2001 From: Reuben Cruise Date: Mon, 15 Jun 2026 16:26:37 +0100 Subject: [PATCH 0145/1309] Adds support for AArch64 SVE to inline assembly Adds new `zreg` register type and `SveVec*` variants to `InlineAsmType` --- src/asm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 5b17b4f83fea2..499b39951dea1 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -692,7 +692,8 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) + | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(_)) => "Sg", @@ -807,7 +808,8 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) + | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => cx.type_i32(), @@ -1056,7 +1058,8 @@ fn modifier_to_gcc( | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { if modifier == Some('v') { None } else { modifier } } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) + | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => None, From 64eb1889cb1066ebd7be4ab2c35ab029f0fbb75c Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Tue, 25 Aug 2026 03:27:05 +0100 Subject: [PATCH 0146/1309] Merge zreg into vreg and keep ffr in a clobber-only class --- src/asm.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/asm.rs b/src/asm.rs index 499b39951dea1..8fd438d847d29 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -692,8 +692,9 @@ fn reg_class_to_gcc(reg_class: InlineAsmRegClass) -> &'static str { InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::reg) => "r", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg) => "w", InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => "x", - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) - | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(AmdgpuInlineAsmRegClass::Sgpr(_)) => "Sg", @@ -808,8 +809,9 @@ fn dummy_output_type<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, reg: InlineAsmRegCl | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { cx.type_vector(cx.type_i64(), 2) } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) - | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => cx.type_i32(), @@ -1058,8 +1060,9 @@ fn modifier_to_gcc( | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::vreg_low16) => { if modifier == Some('v') { None } else { modifier } } - InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::zreg) - | InlineAsmRegClass::AArch64(AArch64InlineAsmRegClass::preg) => { + InlineAsmRegClass::AArch64( + AArch64InlineAsmRegClass::preg | AArch64InlineAsmRegClass::ffr, + ) => { unreachable!("clobber-only") } InlineAsmRegClass::Amdgpu(_) => None, From 181a30510223b985ea918cf4d5b30d78e55185bd Mon Sep 17 00:00:00 2001 From: Nathaniel McCallum Date: Thu, 16 Oct 2025 16:39:12 -0400 Subject: [PATCH 0147/1309] constify comparison traits on multiple sliced types --- library/core/src/bstr/traits.rs | 12 ++++++++---- library/core/src/ffi/c_str.rs | 9 ++++++--- library/core/src/panic/location.rs | 16 ++++++++++------ library/core/src/str/traits.rs | 6 ++++-- 4 files changed, 28 insertions(+), 15 deletions(-) diff --git a/library/core/src/bstr/traits.rs b/library/core/src/bstr/traits.rs index 1d8d0e29e9a5a..6e9d836f1a1ff 100644 --- a/library/core/src/bstr/traits.rs +++ b/library/core/src/bstr/traits.rs @@ -6,7 +6,8 @@ use crate::slice::SliceIndex; use crate::{hash, ops, range}; #[unstable(feature = "bstr", issue = "134915")] -impl Ord for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Ord for ByteStr { #[inline] fn cmp(&self, other: &ByteStr) -> Ordering { Ord::cmp(&self.0, &other.0) @@ -14,7 +15,8 @@ impl Ord for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl PartialOrd for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialOrd for ByteStr { #[inline] fn partial_cmp(&self, other: &ByteStr) -> Option { PartialOrd::partial_cmp(&self.0, &other.0) @@ -22,7 +24,8 @@ impl PartialOrd for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl PartialEq for ByteStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialEq for ByteStr { #[inline] fn eq(&self, other: &ByteStr) -> bool { self.0 == other.0 @@ -30,7 +33,8 @@ impl PartialEq for ByteStr { } #[unstable(feature = "bstr", issue = "134915")] -impl Eq for ByteStr {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Eq for ByteStr {} #[unstable(feature = "bstr", issue = "134915")] impl hash::Hash for ByteStr { diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index e5b1f8088a5bf..e575c269bd936 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -88,7 +88,8 @@ use crate::{fmt, ops, range, slice, str}; /// ``` /// /// [str]: prim@str "str" -#[derive(PartialEq, Eq, Hash)] +#[derive(Hash)] +#[derive_const(PartialEq, Eq)] #[stable(feature = "core_c_str", since = "1.64.0")] #[rustc_diagnostic_item = "cstr_type"] #[rustc_has_incoherent_inherent_impls] @@ -684,7 +685,8 @@ impl PartialEq<&Self> for CStr { // because `c_char` is `i8` (not `u8`) on some platforms. // That is why this is implemented manually and not derived. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for CStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialOrd for CStr { #[inline] fn partial_cmp(&self, other: &CStr) -> Option { self.to_bytes().partial_cmp(other.to_bytes()) @@ -692,7 +694,8 @@ impl PartialOrd for CStr { } #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for CStr { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Ord for CStr { #[inline] fn cmp(&self, other: &CStr) -> Ordering { self.to_bytes().cmp(other.to_bytes()) diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index f37f5370997e1..4fa911272e136 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -47,7 +47,8 @@ pub struct Location<'a> { } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl PartialEq for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialEq for Location<'_> { fn eq(&self, other: &Self) -> bool { // Compare col / line first as they're cheaper to compare and more likely to differ, // while not impacting the result. @@ -56,20 +57,23 @@ impl PartialEq for Location<'_> { } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl Eq for Location<'_> {} +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Eq for Location<'_> {} #[stable(feature = "panic_hooks", since = "1.10.0")] -impl Ord for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Ord for Location<'_> { fn cmp(&self, other: &Self) -> Ordering { self.file() .cmp(other.file()) - .then_with(|| self.line.cmp(&other.line)) - .then_with(|| self.col.cmp(&other.col)) + .then_with(const || self.line.cmp(&other.line)) + .then_with(const || self.col.cmp(&other.col)) } } #[stable(feature = "panic_hooks", since = "1.10.0")] -impl PartialOrd for Location<'_> { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialOrd for Location<'_> { fn partial_cmp(&self, other: &Self) -> Option { Some(self.cmp(other)) } diff --git a/library/core/src/str/traits.rs b/library/core/src/str/traits.rs index e4bf752ad2ae6..a72237fd0e8f8 100644 --- a/library/core/src/str/traits.rs +++ b/library/core/src/str/traits.rs @@ -15,7 +15,8 @@ use crate::{ops, range}; /// culturally-accepted standards requires locale-specific data that is outside the scope of /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] -impl Ord for str { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl Ord for str { #[inline] fn cmp(&self, other: &str) -> Ordering { self.as_bytes().cmp(other.as_bytes()) @@ -43,7 +44,8 @@ const impl Eq for str {} /// culturally-accepted standards requires locale-specific data that is outside the scope of /// the `str` type. #[stable(feature = "rust1", since = "1.0.0")] -impl PartialOrd for str { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialOrd for str { #[inline] fn partial_cmp(&self, other: &str) -> Option { Some(self.cmp(other)) From abc01171f0c11e0152105627f22820c9f6481dbc Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 5 Sep 2026 01:04:39 +0000 Subject: [PATCH 0148/1309] Move auto trait leakage of opaques into its own candidate fn --- .../src/solve/assembly/structural_traits.rs | 12 +----- .../src/solve/trait_goals.rs | 40 ++++++++++++++----- 2 files changed, 32 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs index 17172c5333502..6d93634d616ee 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/structural_traits.rs @@ -60,7 +60,8 @@ where | ty::Placeholder(..) | ty::Alias(ty::IsRigid::No, _) | ty::Bound(..) - | ty::Infer(_) => { + | ty::Infer(_) + | ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { .. }, .. }) => { panic!("unexpected type `{ty:?}`") } @@ -106,15 +107,6 @@ where .map(Unnormalized::skip_norm_wip) .collect(), )), - - ty::Alias(ty::IsRigid::Yes, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) => { - // We can resolve the `impl Trait` to its concrete type, - // which enforces a DAG between the functions requiring - // the auto trait bounds in question. - Ok(ty::Binder::dummy(vec![ - cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(), - ])) - } } } diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 51ec0bcbf5ec2..4eabea8ee221a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -236,19 +236,11 @@ where // when merging candidates anyways. // // See tests/ui/impl-trait/auto-trait-leakage/avoid-query-cycle-via-item-bound.rs. - if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) = + if let ty::Alias(is_rigid, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = goal.predicate.self_ty().kind() { debug_assert!(is_rigid == ty::IsRigid::Yes); - - for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() { - if item_bound - .as_trait_clause() - .is_some_and(|b| b.def_id() == goal.predicate.def_id()) - { - return Err(NoSolution.into()); - } - } + return ecx.consider_auto_trait_candidate_for_opaque_ty(goal, def_id, args); } // We need to make sure to stall any coroutines we are inferring to avoid query cycles. @@ -1286,6 +1278,34 @@ where .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) } + fn consider_auto_trait_candidate_for_opaque_ty( + &mut self, + goal: Goal>, + def_id: I::OpaqueTyId, + args: I::GenericArgs, + ) -> Result, NoSolutionOrRerunNonErased> { + let cx = self.cx(); + let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); + if self.opaque_accesses.might_rerun() { + match self.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)? {} + } + + for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() { + if item_bound.as_trait_clause().is_some_and(|b| b.def_id() == goal.predicate.def_id()) { + return Err(NoSolution.into()); + } + } + + self.probe_trait_candidate(source).enter(|ecx| { + let hidden_ty = cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(); + ecx.add_goal( + GoalSource::ImplWhereBound, + goal.with(cx, goal.predicate.with_replaced_self_ty(cx, hidden_ty)), + )?; + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) + } + // Return `Some` if there is an impl (built-in or user provided) that may // hold for the self type of the goal, which for coherence and soundness // purposes must disqualify the built-in auto impl assembled by considering From 4d6260257392d961cbbb1495dabb9b947a127b7e Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 5 Sep 2026 01:04:39 +0000 Subject: [PATCH 0149/1309] Don't constrain inference vars via auto trait leakage of opaques --- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 4eabea8ee221a..bad038022b1fb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1296,14 +1296,20 @@ where } } - self.probe_trait_candidate(source).enter(|ecx| { + let candidate = self.probe_trait_candidate(source).enter(|ecx| { let hidden_ty = cx.type_of(def_id.into()).instantiate(cx, args).skip_norm_wip(); ecx.add_goal( GoalSource::ImplWhereBound, goal.with(cx, goal.predicate.with_replaced_self_ty(cx, hidden_ty)), )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }) + }); + + match candidate { + Ok(candidate) if has_only_region_constraints(candidate.result) => Ok(candidate), + Ok(_) => self.forced_ambiguity(MaybeInfo::AMBIGUOUS), + Err(err) => Err(err), + } } // Return `Some` if there is an impl (built-in or user provided) that may From 6b9210cf005dcdc61afdebb28e662e7154fe4a5c Mon Sep 17 00:00:00 2001 From: Raushan Singh Date: Mon, 31 Aug 2026 12:39:08 +0000 Subject: [PATCH 0150/1309] fix(parser): emit targeted diagnostic for fields inside traits Detect `ident: Type` or `self: Type` inside trait bodies to emit a clearer diagnostics. --- compiler/rustc_parse/src/diagnostics.rs | 17 ++++++++ compiler/rustc_parse/src/parser/item.rs | 37 ++++++++++++++++ .../parser/trait-item-field-colon-syntax.rs | 12 +++++- .../trait-item-field-colon-syntax.stderr | 42 +++++++++++++++---- 4 files changed, 99 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 2be549703e4e6..7517f04bf5846 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -2495,6 +2495,23 @@ pub(crate) struct AssociatedStaticItemNotAllowed { pub span: Span, } +#[derive(Subdiagnostic)] +pub(crate) enum FieldNotAllowedInTraitSugg { + #[help("consider using a method instead: `fn {$ident}(&self) -> {$ty};`")] + Method { ident: String, ty: String }, + #[note("`self` can only appear as a method receiver; consider `fn method(self: {$ty})`")] + SelfReceiver { ty: String }, +} + +#[derive(Diagnostic)] +#[diag("fields are not allowed in trait definitions")] +pub(crate) struct FieldNotAllowedInTrait { + #[primary_span] + pub span: Span, + #[subdiagnostic] + pub sugg: FieldNotAllowedInTraitSugg, +} + #[derive(Diagnostic)] #[diag("crate name using dashes are not valid in `extern crate` statements")] pub(crate) struct ExternCrateNameWithDashes { diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 46fd2445d7c55..8957cc388959e 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -404,6 +404,14 @@ impl<'a> Parser<'a> { Case::Insensitive, ); } else if macros_allowed && self.check_path() { + // Detect `field_name: Type` or `self: Type` inside a trait body and emit + // a clearer diagnostic before falling through to the macro invocation path. + let is_field_in_trait = fn_parse_mode.context == FnContext::Trait + && self.token.is_path_start() + && self.look_ahead(1, |t| t.kind == token::Colon); + if is_field_in_trait { + return self.recover_field_in_trait(); + } if self.isnt_macro_invocation() { self.recover_missing_kw_before_item()?; } @@ -433,6 +441,35 @@ impl<'a> Parser<'a> { } } + fn recover_field_in_trait(&mut self) -> PResult<'a, Option> { + let ident_span = self.token.span; + let ident_str = pprust::token_to_string(&self.token).into_owned(); + let is_self = self.token.is_keyword(kw::SelfLower); + + self.bump(); // identifier or `self` + self.bump(); // `:` + + let ty_str = match self.parse_ty() { + Ok(ty) => pprust::ty_to_string(&ty), + Err(e) => { + e.cancel(); + String::from("Type") + } + }; + // Eat the trailing separator so the parser doesn't trip over it. + let _ = self.eat(exp!(Comma)); + let _ = self.eat(exp!(Semi)); + + let span = ident_span.to(self.prev_token.span); + let sugg = if is_self { + diagnostics::FieldNotAllowedInTraitSugg::SelfReceiver { ty: ty_str } + } else { + diagnostics::FieldNotAllowedInTraitSugg::Method { ident: ident_str, ty: ty_str } + }; + let err = self.dcx().create_err(diagnostics::FieldNotAllowedInTrait { span, sugg }); + Err(err) + } + fn parse_use_item(&mut self) -> PResult<'a, ItemKind> { let use_token_span = self.prev_token.span; let tree = self.parse_use_tree(use_token_span, None)?; diff --git a/tests/ui/parser/trait-item-field-colon-syntax.rs b/tests/ui/parser/trait-item-field-colon-syntax.rs index f9c5a92d05613..0772f0f59bcae 100644 --- a/tests/ui/parser/trait-item-field-colon-syntax.rs +++ b/tests/ui/parser/trait-item-field-colon-syntax.rs @@ -1,9 +1,17 @@ fn main() {} trait Trait1 { - field_name: String, //~ ERROR expected one of `!` or `::`, found `:` + field_name: String, //~ ERROR fields are not allowed in trait definitions } trait Trait2 { - self: String, //~ ERROR expected one of `!` or `::`, found `:` + self: String, //~ ERROR fields are not allowed in trait definitions +} + +trait Trait3 { + field_name: String //~ ERROR fields are not allowed in trait definitions +} + +trait Trait4 { + self: String //~ ERROR fields are not allowed in trait definitions } diff --git a/tests/ui/parser/trait-item-field-colon-syntax.stderr b/tests/ui/parser/trait-item-field-colon-syntax.stderr index a0d58f7a6bcd1..f073b54ecb34a 100644 --- a/tests/ui/parser/trait-item-field-colon-syntax.stderr +++ b/tests/ui/parser/trait-item-field-colon-syntax.stderr @@ -1,22 +1,50 @@ -error: expected one of `!` or `::`, found `:` - --> $DIR/trait-item-field-colon-syntax.rs:4:15 +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:4:5 | LL | trait Trait1 { | - while parsing this item list starting here LL | field_name: String, - | ^ expected one of `!` or `::` + | ^^^^^^^^^^^^^^^^^^^ LL | } | - the item list ends here + | + = help: consider using a method instead: `fn field_name(&self) -> String;` -error: expected one of `!` or `::`, found `:` - --> $DIR/trait-item-field-colon-syntax.rs:8:9 +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:8:5 | LL | trait Trait2 { | - while parsing this item list starting here LL | self: String, - | ^ expected one of `!` or `::` + | ^^^^^^^^^^^^^ +LL | } + | - the item list ends here + | + = note: `self` can only appear as a method receiver; consider `fn method(self: String)` + +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:12:5 + | +LL | trait Trait3 { + | - while parsing this item list starting here +LL | field_name: String + | ^^^^^^^^^^^^^^^^^^ LL | } | - the item list ends here + | + = help: consider using a method instead: `fn field_name(&self) -> String;` + +error: fields are not allowed in trait definitions + --> $DIR/trait-item-field-colon-syntax.rs:16:5 + | +LL | trait Trait4 { + | - while parsing this item list starting here +LL | self: String + | ^^^^^^^^^^^^ +LL | } + | - the item list ends here + | + = note: `self` can only appear as a method receiver; consider `fn method(self: String)` -error: aborting due to 2 previous errors +error: aborting due to 4 previous errors From c82036710ac1985699471e4ea82fccc9e83d38ef Mon Sep 17 00:00:00 2001 From: Matyas Susits Date: Thu, 30 Jul 2026 08:11:34 +0200 Subject: [PATCH 0151/1309] Disable inline asm line info cookies when llvm bitcode is saved or LTO is enabled The parallel frontend makes the cookies nondeterministic in their current form, resulting in nondeterministic outputs when bitcode is emitted or LTO is used. Causes minor diagnostic regression for inline asm in release builds. --- src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/lib.rs b/src/lib.rs index cbc7db8e9e23f..2fb5459a20283 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -365,6 +365,7 @@ impl ExtraBackendMethods for GccCodegenBackend { &self, tcx: TyCtxt<'_>, cgu_name: Symbol, + _bitcode_needed: bool, ) -> (ModuleCodegen, u64) { base::compile_codegen_unit( tcx, From 2afd4ed7482ee3692e510afeb00ccf1345492d88 Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Mon, 31 Aug 2026 23:05:22 +0200 Subject: [PATCH 0152/1309] Manually set initial TCP socket readiness Because shimmed TCP sockets only receive host readiness events after `connect` or `listen` has been invoked, we need to manually set the initial readiness of a TCP socket. --- src/tools/miri/src/shims/unix/tcp_socket.rs | 35 ++++++++++++++++++- .../libc/libc-socket-no-blocking-epoll.rs | 13 +++++++ 2 files changed, 47 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index d0966fab8ab92..43eb51d8b451c 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -17,6 +17,21 @@ use crate::shims::unix::UnixFileDescription; use crate::shims::unix::socket::{SocketFamily, UnixSocketFileDescription}; use crate::*; +/// On Linux a TCP socket is initally in the TCP_CLOSE state: +/// See +/// For a socket in this state, (E)POLLHUP is reported: +/// See +/// Additionally, because the write buffer is initially empty and the socket is not +/// shut down, (E)POLLOUT is also reported for freshly created TCP sockets: +/// See +/// +/// These events are reported when the "write closed" and "writable" readiness of +/// our generic [`Readiness`] struct are set. Because the TCP socket is only added +/// to the blocking I/O manager after it is connected or listening, we manually set +/// this initial readiness. +const INITIAL_TCP_SOCKET_READINESS: Readiness = + Readiness { writable: true, write_closed: true, ..Readiness::EMPTY }; + #[derive(Debug)] enum SocketState { /// No syscall after `socket` has been made. @@ -81,7 +96,7 @@ impl TcpSocket { family, state: RefCell::new(SocketState::Initial), is_non_block: Cell::new(is_non_block), - io_readiness: RefCell::new(Readiness::EMPTY), + io_readiness: RefCell::new(INITIAL_TCP_SOCKET_READINESS), error: RefCell::new(None), read_timeout: Cell::new(None), write_timeout: Cell::new(None), @@ -297,6 +312,15 @@ impl UnixSocketFileDescription for TcpSocket { Ok(listener) => { *state = SocketState::Listening(listener); drop(state); + + // After invoking `listen` on a TCP socket, it transitions out of the + // TCP_CLOSE state which affects the socket's readiness. Because we + // register the socket afterwards to the blocking I/O manager, we just + // clear its readiness here as the blocking I/O manager will update its + // readiness accordingly. + self.io_readiness.replace(Readiness::EMPTY); + ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; + // Register the socket to the blocking I/O manager because // we now have an associated host socket. ecx.machine.blocking_io.register(self); @@ -389,6 +413,15 @@ impl UnixSocketFileDescription for TcpSocket { match TcpStream::connect(address) { Ok(stream) => { *self.state.borrow_mut() = SocketState::Connecting(stream); + + // After invoking `connect` on a TCP socket, it transitions out of the + // TCP_CLOSE state which affects the socket's readiness. Because we + // register the socket afterwards to the blocking I/O manager, we just + // clear its readiness here as the blocking I/O manager will update its + // readiness accordingly. + self.io_readiness.replace(Readiness::EMPTY); + ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; + // Register the socket to the blocking I/O manager because // we now have an associated host socket. ecx.machine.blocking_io.register(self.clone()); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index ebdbcdc82dd35..c91f3474793e3 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -30,6 +30,7 @@ fn main() { test_readiness_after_short_write(); test_readable_after_read_shutdown_and_short_read(); test_writable_after_write_shutdown_with_full_buffer(); + test_initial_readiness(); } /// Test that connecting to a server socket works when the client @@ -778,3 +779,15 @@ fn test_writable_after_write_shutdown_with_full_buffer() { unsafe { errno_result(libc::write(client_sockfd, buffer.as_ptr().cast(), buffer.len())) }; assert_eq!(result.unwrap_err().kind(), ErrorKind::BrokenPipe); } + +/// Test that a socket reports the EPOLLHUP and EPOLLOUT readiness +/// directly after being created. +fn test_initial_readiness() { + let sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)) }.unwrap(); + let epfd = errno_result(unsafe { libc::epoll_create1(0) }).unwrap(); + + epoll_ctl_add(epfd, sockfd, EPOLLOUT | EPOLLIN | EPOLLHUP | EPOLLRDHUP).unwrap(); + + check_epoll_wait(epfd, &[Ev { events: EPOLLOUT | EPOLLHUP, data: sockfd }], -1); +} From 070eb5da79633fdbc20bdf56382650cbc17fbc06 Mon Sep 17 00:00:00 2001 From: patchunwrap <251685895+patchunwrap@users.noreply.github.com> Date: Sun, 6 Sep 2026 13:42:00 +1000 Subject: [PATCH 0153/1309] Add 2 basic blank_lines_upper_bound tests --- .../configs/blank_lines_upper_bound/1.rs | 29 +++++++++++++++++++ .../configs/blank_lines_upper_bound/2.rs | 29 +++++++++++++++++++ .../configs/blank_lines_upper_bound/1.rs | 21 ++++++++++++++ .../configs/blank_lines_upper_bound/2.rs | 24 +++++++++++++++ 4 files changed, 103 insertions(+) create mode 100644 tests/source/configs/blank_lines_upper_bound/1.rs create mode 100644 tests/source/configs/blank_lines_upper_bound/2.rs create mode 100644 tests/target/configs/blank_lines_upper_bound/1.rs create mode 100644 tests/target/configs/blank_lines_upper_bound/2.rs diff --git a/tests/source/configs/blank_lines_upper_bound/1.rs b/tests/source/configs/blank_lines_upper_bound/1.rs new file mode 100644 index 0000000000000..1ddae0bbe1914 --- /dev/null +++ b/tests/source/configs/blank_lines_upper_bound/1.rs @@ -0,0 +1,29 @@ +// rustfmt-blank_lines_upper_bound: 1 + +fn do_stuff() + + +{ + let i = 0; + + + i += 1; + + + + println!("{i}"); +} + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + + + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/tests/source/configs/blank_lines_upper_bound/2.rs b/tests/source/configs/blank_lines_upper_bound/2.rs new file mode 100644 index 0000000000000..caaaa006c0ec8 --- /dev/null +++ b/tests/source/configs/blank_lines_upper_bound/2.rs @@ -0,0 +1,29 @@ +// rustfmt-blank_lines_upper_bound: 2 + +fn do_stuff() + + +{ + let i = 0; + + + i += 1; + + + + println!("{i}"); +} + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + + + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/tests/target/configs/blank_lines_upper_bound/1.rs b/tests/target/configs/blank_lines_upper_bound/1.rs new file mode 100644 index 0000000000000..4519e11c15977 --- /dev/null +++ b/tests/target/configs/blank_lines_upper_bound/1.rs @@ -0,0 +1,21 @@ +// rustfmt-blank_lines_upper_bound: 1 + +fn do_stuff() { + let i = 0; + + i += 1; + + println!("{i}"); +} + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} diff --git a/tests/target/configs/blank_lines_upper_bound/2.rs b/tests/target/configs/blank_lines_upper_bound/2.rs new file mode 100644 index 0000000000000..f43f81150151c --- /dev/null +++ b/tests/target/configs/blank_lines_upper_bound/2.rs @@ -0,0 +1,24 @@ +// rustfmt-blank_lines_upper_bound: 2 + +fn do_stuff() { + let i = 0; + + + i += 1; + + + println!("{i}"); +} + +fn foo() {} +fn bar() {} +// comment +fn foobar() {} + + +fn foo1() {} +fn bar1() {} + +// comment + +fn foobar1() {} From 786d6348dfed6d9f5aac2872628d02296013e164 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 6 Sep 2026 04:30:19 +0000 Subject: [PATCH 0154/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to f248f4038796913873f11ca65b1b901e311c8dae. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0e85574e7b0ec..0e28d51ef406e 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0ed41eb4142dda2df61eb1145a312c1a9d62eb56 +f248f4038796913873f11ca65b1b901e311c8dae From aee14eb9113363529ffd6657c968e817371592b9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 28 Aug 2026 08:46:35 +0200 Subject: [PATCH 0155/1309] declare C and C-unwind as mutually ABI-compatible --- library/core/src/primitive_docs.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 4b84a9de4ce72..5099c2fded6b5 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1810,9 +1810,14 @@ const _: () = (); /// `fn name(...) -> ...` implicitly uses the `"Rust"` ABI string and `extern fn name(...) -> ...` /// implicitly uses the `"C"` ABI string. /// -/// The ABI strings are guaranteed to be compatible if they are the same, or if the caller ABI -/// string is `$X-unwind` and the callee ABI string is `$X`, where `$X` is one of the following: -/// "C", "aapcs", "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64". +/// The ABI strings are guaranteed to be compatible if they are the same, or if one of them is +/// `$X-unwind` and the other one is `$X`, where `$X` is one of the following: "C", "aapcs", +/// "fastcall", "stdcall", "system", "sysv64", "thiscall", "vectorcall", "win64". (Note that [it is +/// undefined behavior][unwind-ub] for a function to unwind unless *both* caller and callee use a +/// signature that permits unwinding, such as "C-unwind". Rust ensures that a function defined with +/// a non-unwinding ABI such as "C" never unwinds due to a panic, so undefined behavior can only +/// arise if the callee ABI is `$X-unwind` and the caller ABI is `$X`, or if a non-Rust unwind +/// occurs.) /// /// The following types are guaranteed to be ABI-compatible: /// @@ -1878,7 +1883,8 @@ const _: () = (); /// Behavior since transmuting `None::>` to `NonZero` violates the non-zero /// requirement. /// -/// [cfi-docs]: https://doc.rust-lang.org/beta/unstable-book/compiler-flags/sanitizer.html#controlflowintegrity +/// [unwind-ub]: ../reference/behavior-considered-undefined.html#r-undefined.call +/// [cfi-docs]: ../unstable-book/compiler-flags/sanitizer.html#controlflowintegrity /// /// ### Trait implementations /// From 0d1e323c71766039046ffc2b3012e4b887014c1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 5 Sep 2026 18:50:20 +0200 Subject: [PATCH 0156/1309] =?UTF-8?q?When=20trying=20to=20recover=20from?= =?UTF-8?q?=20`for<=E2=80=A6>=20dyn=20=E2=80=A6`=20don't=20unconditionally?= =?UTF-8?q?=20treat=20`dyn`=20as=20a=20keyword?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- compiler/rustc_parse/src/parser/ty.rs | 43 ++++++++++--------- .../ui/parser/dyn-2015-identifier.fail.stderr | 21 ++++++++- tests/ui/parser/dyn-2015-identifier.rs | 8 ++++ .../parser/recover-hrtb-before-dyn-impl-kw.rs | 4 -- .../recover-hrtb-before-dyn-impl-kw.stderr | 8 +--- 5 files changed, 51 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 31732882f7e86..2b098d8fdbbbf 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -83,20 +83,22 @@ enum AllowCVariadic { /// Determine if the given token can begin a bound assuming it follows Rust 2015 identifier `dyn`. /// /// In Rust 2015, `dyn` is a contextual keyword, not a full one. -fn can_begin_dyn_bound_in_edition_2015(t: Token) -> bool { - if t.is_path_start() { - // In `dyn::x`, `dyn` and `dyn<::Y>`, `dyn` should (continue to) denote a regular path - // segment for backward compatibility. We make an exception for `dyn(X)` which used to be - // interpreted as a path with parenthesized generic arguments which can be semantically - // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait - // object type whose first bound is parenthesized. - return t != token::PathSep && t != token::Lt && t != token::Shl; - } +fn can_begin_dyn_bound_in_rust_2015(t: Token) -> bool { + // In `dyn::x`, `dyn` and `dyn<::Y>`, `dyn` should (continue to) denote a regular path + // segment for backward compatibility. We make an exception for `dyn(X)` which used to be + // interpreted as a path with parenthesized generic arguments which can be semantically + // well-formed (consider: `use std::ops::Fn as dyn;`). Instead, we treat it as a trait + // object type whose first bound is parenthesized. // Contrary to `Parser::can_begin_bound`, `!`, `const`, `[` and `async` are deliberately not // part of this list to contain the number of potential regressions esp. in MBE code. // `const` and `[` would regress UI test `macro-dyn-const-2015.rs` and // `!` would regress `dyn!(...)` macro calls in Rust 2015 for example. + + if t.is_path_start() { + return t != token::PathSep && t != token::Lt && t != token::Shl; + } + t == token::OpenParen || t == token::Question || t.is_lifetime() || t.is_keyword(kw::For) } @@ -347,9 +349,10 @@ impl<'a> Parser<'a> { } else { // Try to recover `for<'a> dyn Trait` or `for<'a> impl Trait`. if self.may_recover() - && (self.eat_keyword_noexpect(kw::Impl) || self.eat_keyword_noexpect(kw::Dyn)) + && (self.token.is_keyword(kw::Impl) || self.can_begin_dyn_ty()) { - let kw = self.prev_token.ident().unwrap().0; + self.bump(); + let (kw, _) = self.prev_token.ident().unwrap(); let removal_span = kw.span.with_hi(self.token.span.lo()); let path = self.parse_path(PathStyle::Type)?; let parse_plus = allow_plus == AllowPlus::Yes && self.check_plus(); @@ -397,7 +400,7 @@ impl<'a> Parser<'a> { } } else if self.eat_keyword(exp!(Impl)) { self.parse_impl_ty(&mut impl_dyn_multi)? - } else if self.is_explicit_dyn_type() { + } else if self.can_begin_dyn_ty() { self.parse_dyn_ty(&mut impl_dyn_multi)? } else if self.eat_lt() { // Qualified path @@ -1000,16 +1003,14 @@ impl<'a> Parser<'a> { Ok(GenericBound::Use(args, lo.to(self.prev_token.span))) } - /// Is a `dyn B0 + ... + Bn` type allowed here? - fn is_explicit_dyn_type(&mut self) -> bool { - self.check_keyword(exp!(Dyn)) + /// Can the current token begin a `dyn`-prefixed trait object type? + fn can_begin_dyn_ty(&mut self) -> bool { + self.token.is_keyword(kw::Dyn) && (self.token_uninterpolated_span().at_least_rust_2018() - || self.look_ahead(1, |&t| can_begin_dyn_bound_in_edition_2015(t))) + || self.look_ahead(1, |&t| can_begin_dyn_bound_in_rust_2015(t))) } - /// Parses a `dyn B0 + ... + Bn` type. - /// - /// Note that this does *not* parse bare trait objects. + /// Parse a `dyn`-prefixed trait object type. fn parse_dyn_ty(&mut self, impl_dyn_multi: &mut bool) -> PResult<'a, TyKind> { self.bump(); // `dyn` @@ -1067,8 +1068,8 @@ impl<'a> Parser<'a> { && (self.token.can_begin_type() || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where)))) { - if self.token.is_keyword(kw::Dyn) && self.token.span.edition().at_least_rust_2018() { - // Account for `&dyn Trait + dyn Other`. + // Account for `&dyn Trait + dyn Other`. + if self.can_begin_dyn_ty() { self.bump(); self.dcx().emit_err(InvalidDynKeyword { span: self.prev_token.span, diff --git a/tests/ui/parser/dyn-2015-identifier.fail.stderr b/tests/ui/parser/dyn-2015-identifier.fail.stderr index da82a9f2d067f..43ca1a2ffd996 100644 --- a/tests/ui/parser/dyn-2015-identifier.fail.stderr +++ b/tests/ui/parser/dyn-2015-identifier.fail.stderr @@ -52,6 +52,12 @@ error[E0405]: cannot find trait `dyn` in this scope LL | type A4 = dyn + dyn; | ^^^ not found in this scope +error[E0405]: cannot find trait `dyn` in this scope + --> $DIR/dyn-2015-identifier.rs:33:17 + | +LL | type A5 = for<> dyn; + | ^^^ not found in this scope + warning: trait objects without an explicit `dyn` are deprecated --> $DIR/dyn-2015-identifier.rs:24:11 | @@ -66,6 +72,19 @@ help: if this is a dyn-compatible trait, use `dyn` LL | type A4 = dyn dyn + dyn; | +++ +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/dyn-2015-identifier.rs:33:11 + | +LL | type A5 = for<> dyn; + | ^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type A5 = dyn for<> dyn; + | +++ + error[E0433]: cannot find module or crate `dyn` in this scope --> $DIR/dyn-2015-identifier.rs:10:11 | @@ -74,7 +93,7 @@ LL | type A1 = dyn::dyn; | = help: you might be missing a crate named `dyn` -error: aborting due to 10 previous errors; 1 warning emitted +error: aborting due to 11 previous errors; 2 warnings emitted Some errors have detailed explanations: E0405, E0425, E0433. For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/parser/dyn-2015-identifier.rs b/tests/ui/parser/dyn-2015-identifier.rs index 3bac8d2b631dc..53a09c8895a69 100644 --- a/tests/ui/parser/dyn-2015-identifier.rs +++ b/tests/ui/parser/dyn-2015-identifier.rs @@ -26,3 +26,11 @@ type A4 = dyn + dyn; //[fail]~| ERROR cannot find trait `dyn` in this scope //[fail]~| WARN trait objects without an explicit `dyn` are deprecated //[fail]~| WARN this is accepted in the current edition + +// The `for<…> dyn …` -> `dyn for<…> …` recovery code used to incorrectly treat `dyn` as a keyword +// in Rust 2015 even it's not followed by a token in the "trigger set". +// What's more, this also used to ICE for a period of time (see also #118564). +type A5 = for<> dyn; +//[fail]~^ ERROR cannot find trait `dyn` in this scope +//[fail]~| WARN trait objects without an explicit `dyn` are deprecated +//[fail]~| WARN this is accepted in the current edition diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs index b78832bbe3dc0..56eb102b225ee 100644 --- a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.rs @@ -8,8 +8,4 @@ fn test(_: &for<'a> dyn Trait) {} fn test2(_: for<'a> impl Trait) {} //~^ ERROR `for<...>` expected after `impl`, not before -// Issue #118564 -type A2 = dyn dyn>; -//~^ ERROR expected identifier, found `>` - fn main() {} diff --git a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr index 3745cf8b07790..e1032b8fdf232 100644 --- a/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr +++ b/tests/ui/parser/recover-hrtb-before-dyn-impl-kw.stderr @@ -22,11 +22,5 @@ LL - fn test2(_: for<'a> impl Trait) {} LL + fn test2(_: impl for<'a> Trait) {} | -error: expected identifier, found `>` - --> $DIR/recover-hrtb-before-dyn-impl-kw.rs:12:24 - | -LL | type A2 = dyn dyn>; - | ^ expected identifier - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors From dc65780a520d2ca5913cb5dd01ed67cd592eaa8a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 6 Sep 2026 16:04:21 -0400 Subject: [PATCH 0157/1309] Error on stale entries in failing test files --- .github/workflows/failures.yml | 18 ++- build_system/src/main.rs | 5 +- build_system/src/test.rs | 209 ++++++++++++++++++++++++++------- 3 files changed, 184 insertions(+), 48 deletions(-) diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index 2c9e4950706b2..52e96726129b3 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -98,7 +98,14 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' id: tests run: | - ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log + # Without this, `tee` masks the exit status of `y.sh test`. + set -o pipefail + status=0 + ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log || status=$? + # This suite runs the tests known to fail, so only a build system error must fail the job. + if [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then + exit "$status" + fi rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY - name: Run failing ui pattern tests for ICE @@ -106,7 +113,14 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' id: ui-tests run: | - ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log_ui + # Without this, `tee` masks the exit status of `y.sh test`. + set -o pipefail + status=0 + ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log_ui || status=$? + # This suite runs tests that fail, so only a build system error must fail the job here. + if [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then + exit "$status" + fi if grep -q "the compiler unexpectedly panicked" output_log_ui; then echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!" exit 1 diff --git a/build_system/src/main.rs b/build_system/src/main.rs index 83f07a758d659..37b1f306817fd 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -112,6 +112,9 @@ fn main() { Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); - process::exit(1); + // CI needs to tell a build system error apart from the test failures some suites expect. + let exit_code = + if e == test::TESTS_FAILED_ERROR { test::TESTS_FAILED_EXIT_CODE } else { 1 }; + process::exit(exit_code); } } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 2e9a67f9a8cd8..96a45d7dcf5a1 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; use std::fs::{File, read_to_string, remove_dir_all}; use std::io::{BufRead, BufReader}; @@ -15,6 +15,15 @@ use crate::utils::{ run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, }; +/// Exit code of `y.sh test` when the tests ran and reported failures, as opposed to the build +/// system failing to run them at all. CI relies on the distinction: the suites of known-failing +/// tests are expected to report failures, but a broken build system must never pass silently. +pub const TESTS_FAILED_EXIT_CODE: i32 = 2; + +/// The error returned for that case. `main` compares against it to pick the exit code, so no other +/// error may use this message. +pub const TESTS_FAILED_ERROR: &str = "the test suite reported failures"; + type Env = HashMap; type Runner = fn(&Env, &TestArg) -> Result<(), String>; type Runners = HashMap<&'static str, (&'static str, Runner)>; @@ -1221,8 +1230,57 @@ where &"--bypass-ignore-backends", ]; - run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; - Ok(()) + run_test_command(&command, &rust_path, &env) +} + +/// Reads the list of tests at `list_path`, checking that each of them still exists in the rust +/// checkout at `rust_path` and that none is listed twice. +/// +/// Both problems make a line a no-op: the test it names is neither kept nor removed, so the test +/// suite silently drifts away from what the list claims to describe. +fn read_test_list(rust_path: &Path, list_path: &str) -> Result, String> { + let content = std::fs::read_to_string(list_path) + .map_err(|error| format!("Failed to read `{list_path}`: {error:?}"))?; + + let mut tests = Vec::new(); + let mut seen = HashSet::new(); + let mut missing = Vec::new(); + let mut duplicated = Vec::new(); + + for line in content.lines().map(|line| line.trim()).filter(|line| !line.is_empty()) { + if !seen.insert(line) { + duplicated.push(line); + continue; + } + if !rust_path.join(line.trim_end_matches('/')).exists() { + missing.push(line); + } + tests.push(line.to_string()); + } + + if missing.is_empty() && duplicated.is_empty() { + return Ok(tests); + } + + let mut error = format!("`{list_path}` is out of date:\n"); + if !missing.is_empty() { + error.push_str(&format!( + "\nThese tests no longer exist in `{rust_path}`:\n{missing}\n", + rust_path = rust_path.display(), + missing = missing.join("\n"), + )); + } + if !duplicated.is_empty() { + error.push_str(&format!( + "\nThese tests are listed more than once:\n{}\n", + duplicated.join("\n") + )); + } + error.push_str( + "\nEvery line must name a test that exists, exactly once, otherwise the line filters \ + nothing. Delete the stale lines, or update them to the test's current path.", + ); + Err(error) } /// Checks that every test listed in `list_path` survived the filtering done by @@ -1281,14 +1339,29 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { Some("tests/failing-ui-tests.txt"), ); - run_make_result.and(run_make_cargo_result).and(ui_result) + combine_test_results([run_make_result, run_make_cargo_result, ui_result]) +} + +/// Combines the results of several test suites, letting a build system error win over a test +/// failure so that a broken build system is never reported to CI as the failures those suites +/// expect. +fn combine_test_results(results: [Result<(), String>; N]) -> Result<(), String> { + let mut tests_failed = false; + for result in results { + match result { + Ok(()) => {} + Err(error) if error == TESTS_FAILED_ERROR => tests_failed = true, + Err(error) => return Err(error), + } + } + if tests_failed { Err(TESTS_FAILED_ERROR.to_string()) } else { Ok(()) } } fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner( env, args, - remove_files_callback("tests/failing-ui-tests.txt", "ui"), + remove_files_callback("tests/failing-ui-tests.txt"), false, "ui", None, @@ -1296,7 +1369,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner( env, args, - remove_files_callback("tests/failing-run-make-tests.txt", "run-make"), + remove_files_callback("tests/failing-run-make-tests.txt"), false, "run-make", None, @@ -1304,7 +1377,7 @@ fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner( env, args, - remove_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"), + remove_files_callback("tests/failing-run-make-tests.txt"), false, "run-make-cargo", None, @@ -1315,7 +1388,7 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String test_rustc_inner( env, args, - remove_files_callback("tests/failing-ice-tests.txt", "ui"), + remove_files_callback("tests/failing-ice-tests.txt"), true, "ui", None, @@ -1358,7 +1431,20 @@ fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { command.push(test_name); } - run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; + run_test_command(&command, &rust_path, &env) +} + +/// Runs the command that actually runs a test suite, mapping its failure to `TESTS_FAILED_ERROR`. +fn run_test_command( + command: &[&dyn AsRef], + rust_path: &Path, + env: &Env, +) -> Result<(), String> { + if let Err(error) = run_command_with_output_and_env(command, Some(rust_path), Some(env)) { + // The failures themselves were already streamed to the console. + eprintln!("{error}"); + return Err(TESTS_FAILED_ERROR.to_string()); + } Ok(()) } @@ -1367,8 +1453,8 @@ fn retain_files_callback<'a>( test_type: &'a str, ) -> impl Fn(&Path) -> Result + 'a { move |rust_path| { - let files = std::fs::read_to_string(file_path).unwrap_or_default(); - let first_file_name = files.lines().next().unwrap_or(""); + let tests = read_test_list(rust_path, file_path)?; + let first_file_name = tests.first().map(String::as_str).unwrap_or(""); // If the first line ends with a `/`, we treat all lines in the file as a directory. if first_file_name.ends_with('/') { // Treat as directory @@ -1410,53 +1496,31 @@ fn retain_files_callback<'a>( } // Putting back only the failing ones. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) { - run_command(&[&"git", &"checkout", &"--", &file], Some(rust_path))?; - } - } else { - println!("Failed to read `{file_path}`, not putting back failing {test_type} tests"); + for test in &tests { + run_command(&[&"git", &"checkout", &"--", test], Some(rust_path))?; } Ok(true) } } -fn remove_files_callback<'a>( - file_path: &'a str, - test_type: &'a str, -) -> impl Fn(&Path) -> Result + 'a { +fn remove_files_callback(file_path: &str) -> impl Fn(&Path) -> Result + '_ { move |rust_path| { - let files = std::fs::read_to_string(file_path).unwrap_or_default(); - let first_file_name = files.lines().next().unwrap_or(""); + let tests = read_test_list(rust_path, file_path)?; + let first_file_name = tests.first().map(String::as_str).unwrap_or(""); // If the first line ends with a `/`, we treat all lines in the file as a directory. if first_file_name.ends_with('/') { // Removing the failing tests. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in - files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) - { - let path = rust_path.join(file); - if let Err(e) = remove_dir_all(&path) { - println!("Failed to remove directory `{}`: {}", path.display(), e); - } - } - } else { - println!( - "Failed to read `{file_path}`, not putting back failing {test_type} tests" - ); + for test in &tests { + let path = rust_path.join(test); + remove_dir_all(&path).map_err(|error| { + format!("Failed to remove directory `{}`: {error}", path.display()) + })?; } } else { // Removing the failing tests. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in - files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) - { - let path = rust_path.join(file); - remove_file(&path)?; - } - } else { - println!("Failed to read `{file_path}`, not putting back failing ui tests"); + for test in &tests { + remove_file(&rust_path.join(test))?; } } Ok(true) @@ -1563,3 +1627,58 @@ pub fn run() -> Result<(), String> { Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + + fn write_test_list(directory: &Path, content: &str) -> PathBuf { + let list_path = directory.join("failing-tests.txt"); + std::fs::write(&list_path, content).unwrap(); + list_path + } + + #[test] + fn test_combine_test_results() { + let tests_failed = || Err(TESTS_FAILED_ERROR.to_string()); + let build_error = || Err("could not clone rust".to_string()); + + assert_eq!(combine_test_results([Ok(()), Ok(())]), Ok(())); + assert_eq!(combine_test_results([Ok(()), tests_failed()]), tests_failed()); + assert_eq!(combine_test_results([Ok(()), build_error()]), build_error()); + // A build system error wins, whichever suite reported it. + assert_eq!(combine_test_results([tests_failed(), build_error()]), build_error()); + assert_eq!(combine_test_results([build_error(), tests_failed()]), build_error()); + } + + #[test] + fn test_read_test_list() { + let rust_path = std::env::temp_dir().join("cg_gcc_read_test_list"); + let _ = remove_dir_all(&rust_path); + create_dir(rust_path.join("tests/ui")).unwrap(); + std::fs::write(rust_path.join("tests/ui/alive.rs"), "").unwrap(); + + let list_path = write_test_list(&rust_path, "\ntests/ui/alive.rs\n \n"); + let list_path = list_path.display().to_string(); + assert_eq!( + read_test_list(&rust_path, &list_path), + Ok(vec!["tests/ui/alive.rs".to_string()]) + ); + + write_test_list(&rust_path, "tests/ui/alive.rs\ntests/ui/gone.rs\n"); + let error = read_test_list(&rust_path, &list_path).unwrap_err(); + assert!(error.contains("no longer exist"), "{error}"); + assert!(error.contains("tests/ui/gone.rs"), "{error}"); + + write_test_list(&rust_path, "tests/ui/alive.rs\ntests/ui/alive.rs\n"); + let error = read_test_list(&rust_path, &list_path).unwrap_err(); + assert!(error.contains("listed more than once"), "{error}"); + assert!(error.contains("tests/ui/alive.rs"), "{error}"); + + // Directories are listed with a trailing `/`. + write_test_list(&rust_path, "tests/ui/\n"); + assert_eq!(read_test_list(&rust_path, &list_path), Ok(vec!["tests/ui/".to_string()])); + + remove_dir_all(&rust_path).unwrap(); + } +} From 162c62cf1c101d991020e9bb09101b5bf98d1901 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 6 Sep 2026 16:48:57 -0400 Subject: [PATCH 0158/1309] Update failing test lists --- tests/failing-ice-tests.txt | 7 ++----- tests/failing-run-make-tests.txt | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/tests/failing-ice-tests.txt b/tests/failing-ice-tests.txt index ff1b6f1489468..3a1f062d24b9f 100644 --- a/tests/failing-ice-tests.txt +++ b/tests/failing-ice-tests.txt @@ -10,7 +10,6 @@ tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs tests/ui/simd/intrinsic/generic-arithmetic-2.rs tests/ui/panics/default-backtrace-ice.rs tests/ui/mir/lint/storage-live.rs -tests/ui/layout/valid_range_oob.rs tests/ui/higher-ranked/trait-bounds/future.rs tests/ui/consts/const-eval/const-eval-query-stack.rs tests/ui/simd/masked-load-store.rs @@ -28,13 +27,11 @@ tests/ui/lto/thin-lto-global-allocator.rs tests/ui/lto/msvc-imp-present.rs tests/ui/lto/dylib-works.rs tests/ui/lto/all-crates.rs -tests/ui/issues/issue-47364.rs +tests/ui/codegen/no-segfault-with-multiple-codegen-units.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/sepcomp/sepcomp-unwind.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs -tests/ui/unwind-no-uwtable.rs +tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/delegation/fn-header.rs tests/ui/simd/intrinsic/generic-arithmetic-pass.rs -tests/ui/simd/masked-load-store.rs -tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 1feb2c7cc6edc..d5297e069f72f 100644 --- a/tests/failing-run-make-tests.txt +++ b/tests/failing-run-make-tests.txt @@ -11,5 +11,5 @@ tests/run-make/foreign-exceptions/ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ -tests/run-make/short-ice -tests/run-make/embed-source-dwarf +tests/run-make/short-ice/ +tests/run-make/embed-source-dwarf/ From f0570c21419e4e5f149c1653dd0938be61e1e7d2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 6 Sep 2026 18:53:26 -0400 Subject: [PATCH 0159/1309] Remap the sysroot path and keep non-test files --- build_system/src/build.rs | 18 ++++++++ build_system/src/test.rs | 91 ++++++++++++++++++--------------------- 2 files changed, 61 insertions(+), 48 deletions(-) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 2fc4d970545ba..bcd386bfebdae 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -132,6 +132,24 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // Builds libs let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + + // Record the sysroot sources under the path the `rust-src` component uses, which is where + // rustc looks for them to turn a sysroot span into `/rustc/$hash`. Without this, ui tests + // print the build path where they expect `$SRC_DIR`. + let sysroot_source_dir = lib_path.join("rustlib/src/rust/library"); + rustflags.push_str(&format!( + " --remap-path-prefix={library_dir}={sysroot_source_dir}", + library_dir = std::path::absolute(&library_dir) + .map_err(|error| format!( + "Failed to get the absolute path of the sysroot sources: {error:?}" + ))? + .display(), + sysroot_source_dir = std::path::absolute(&sysroot_source_dir) + .map_err(|error| format!( + "Failed to get the absolute path of the sysroot sources: {error:?}" + ))? + .display(), + )); if config.sysroot_panic_abort { rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 96a45d7dcf5a1..a5e79d6f3c1b3 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1100,60 +1100,55 @@ where } if test_type == "ui" { - if run_error_pattern_test { - // After we removed the error tests that are known to panic with rustc_codegen_gcc, we now remove the passing tests since this runs the error tests. - walk_dir( - rust_path.join("tests/ui"), - &mut |_dir| Ok(()), - &mut |file_path| { - if contains_ui_error_patterns(file_path, args.keep_lto_tests)? { - Ok(()) - } else { - remove_file(file_path).map_err(|e| e.to_string()) - } - }, - true, - )?; - } else { - // These two functions are used to remove files that are known to not be working currently - // with the GCC backend to reduce noise. - fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { - move |dir| { - if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) { - return Ok(()); - } - - walk_dir( - dir, - &mut dir_handling(keep_lto_tests), - &mut file_handling(keep_lto_tests), - false, - ) + // Each mode runs one half of the ui tests and removes the other: `run_error_pattern_test` + // runs the tests expected to error, the other mode runs the rest. Only `.rs` files outside + // `auxiliary` are tests, so the expected output and the auxiliary crates are left alone. + fn dir_handling( + keep_lto_tests: bool, + remove_error_pattern_tests: bool, + ) -> impl Fn(&Path) -> Result<(), String> { + move |dir| { + if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) { + return Ok(()); } + + walk_dir( + dir, + &mut dir_handling(keep_lto_tests, remove_error_pattern_tests), + &mut file_handling(keep_lto_tests, remove_error_pattern_tests), + false, + ) } + } - fn file_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { - move |file_path| { - if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) { - return Ok(()); - } - let path_str = file_path.display().to_string().replace("\\", "/"); - if valid_ui_error_pattern_test(&path_str) { - return Ok(()); - } else if contains_ui_error_patterns(file_path, keep_lto_tests)? { - return remove_file(&file_path); - } - Ok(()) + fn file_handling( + keep_lto_tests: bool, + remove_error_pattern_tests: bool, + ) -> impl Fn(&Path) -> Result<(), String> { + move |file_path| { + if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) { + return Ok(()); + } + let path_str = file_path.display().to_string().replace("\\", "/"); + if valid_ui_error_pattern_test(&path_str) { + return Ok(()); + } + if contains_ui_error_patterns(file_path, keep_lto_tests)? + == remove_error_pattern_tests + { + return remove_file(file_path); } + Ok(()) } - - walk_dir( - rust_path.join("tests/ui"), - &mut dir_handling(args.keep_lto_tests), - &mut file_handling(args.keep_lto_tests), - false, - )?; } + + let remove_error_pattern_tests = !run_error_pattern_test; + walk_dir( + rust_path.join("tests/ui"), + &mut dir_handling(args.keep_lto_tests, remove_error_pattern_tests), + &mut file_handling(args.keep_lto_tests, remove_error_pattern_tests), + false, + )?; if let Some(retained_tests_list_path) = retained_tests_list_path { check_for_dead_listed_tests(&rust_path, retained_tests_list_path)?; } From 894f27bf00ccf6276d9d4d870cd4f0f99b96fa57 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 6 Sep 2026 19:23:19 -0400 Subject: [PATCH 0160/1309] Add new ICEing tests --- tests/failing-ice-tests.txt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/failing-ice-tests.txt b/tests/failing-ice-tests.txt index 3a1f062d24b9f..ca685eb2af71c 100644 --- a/tests/failing-ice-tests.txt +++ b/tests/failing-ice-tests.txt @@ -35,3 +35,9 @@ tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/delegation/fn-header.rs tests/ui/simd/intrinsic/generic-arithmetic-pass.rs +tests/ui/codegen/unknown-llvm-intrinsic.rs +tests/ui/codegen/incorrect-llvm-intrinsic-signature.rs +tests/ui/codegen/incorrect-arch-intrinsic.rs +tests/ui/codegen/custom-target-invalid-llvm-target.rs +tests/ui/asm/x86_64/naked_asm_escape.rs +tests/ui/lto/debuginfo-lto-alloc.rs From 2cc2b5791e0fb3ea7b086b48a8e0ae380611d09e Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 7 Sep 2026 04:17:44 +0000 Subject: [PATCH 0161/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 32d94cc9be3f6e6c3fa1deaea9e0ab93c4980dba. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 7b170626619e4..18fea436747c7 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -da5114692c9ebe46b869488c5f34f92eb10b98c1 +32d94cc9be3f6e6c3fa1deaea9e0ab93c4980dba From 9565cedf8500609e975b88f30220c4a187c3d0a8 Mon Sep 17 00:00:00 2001 From: Yukang Date: Mon, 7 Sep 2026 13:53:24 +0800 Subject: [PATCH 0162/1309] Add regression test for importing block-scoped traits --- .../block-scoped-trait-import-issue-134146.rs | 59 ++++++++++++++++++ ...ck-scoped-trait-import-issue-134146.stderr | 62 +++++++++++++++++++ 2 files changed, 121 insertions(+) create mode 100644 tests/ui/traits/block-scoped-trait-import-issue-134146.rs create mode 100644 tests/ui/traits/block-scoped-trait-import-issue-134146.stderr diff --git a/tests/ui/traits/block-scoped-trait-import-issue-134146.rs b/tests/ui/traits/block-scoped-trait-import-issue-134146.rs new file mode 100644 index 0000000000000..0a9874c281d67 --- /dev/null +++ b/tests/ui/traits/block-scoped-trait-import-issue-134146.rs @@ -0,0 +1,59 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/134146. +//! Traits declared inside bodies cannot be imported through their enclosing function or const. + +#![allow(dead_code)] + +fn main() { + { + trait Hello { + fn hello(&self) { + println!("hello world"); + } + } + impl Hello for T {} + } + + ().hello(); + //~^ ERROR no method named `hello` found +} + +fn nested_module() { + mod inner { + pub trait Nested { + fn nested(&self) {} + } + impl Nested for () {} + } +} + +fn use_nested() { + ().nested(); + //~^ ERROR no method named `nested` found +} + +const _: () = { + trait InConst { + fn in_const(&self) {} + } + impl InConst for () {} +}; + +fn use_const() { + ().in_const(); + //~^ ERROR no method named `in_const` found +} + +fn multiple_candidates() { + { + trait First { + fn several(&self) {} + } + trait Second { + fn several(&self) {} + } + impl First for () {} + impl Second for () {} + } + ().several(); + //~^ ERROR no method named `several` found +} diff --git a/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr new file mode 100644 index 0000000000000..dfe305bf9853b --- /dev/null +++ b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr @@ -0,0 +1,62 @@ +error[E0599]: no method named `hello` found for unit type `()` in the current scope + --> $DIR/block-scoped-trait-import-issue-134146.rs:16:8 + | +LL | fn hello(&self) { + | ----- the method is available for `()` here +... +LL | ().hello(); + | ^^^^^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope +help: trait `Hello` which provides `hello` is implemented but not in scope; perhaps you want to import it + | +LL + use main::Hello; + | + +error[E0599]: no method named `nested` found for unit type `()` in the current scope + --> $DIR/block-scoped-trait-import-issue-134146.rs:30:8 + | +LL | fn nested(&self) {} + | ------ the method is available for `()` here +... +LL | ().nested(); + | ^^^^^^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope +help: trait `Nested` which provides `nested` is implemented but not in scope; perhaps you want to import it + | +LL + use nested_module::inner::Nested; + | + +error[E0599]: no method named `in_const` found for unit type `()` in the current scope + --> $DIR/block-scoped-trait-import-issue-134146.rs:42:8 + | +LL | fn in_const(&self) {} + | -------- the method is available for `()` here +... +LL | ().in_const(); + | ^^^^^^^^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope +help: trait `InConst` which provides `in_const` is implemented but not in scope; perhaps you want to import it + | +LL + use _::InConst; + | + +error[E0599]: no method named `several` found for unit type `()` in the current scope + --> $DIR/block-scoped-trait-import-issue-134146.rs:57:8 + | +LL | ().several(); + | ^^^^^^^ method not found in `()` + | + = help: items from traits can only be used if the trait is in scope +help: the following traits which provide `several` are implemented but not in scope; perhaps you want to import one of them + | +LL + use multiple_candidates::First; + | +LL + use multiple_candidates::Second; + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0599`. From c98b78666ff1f33896bb6dd519c4ef974306f149 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 15:20:23 -0300 Subject: [PATCH 0163/1309] Handle reflexive solver region constraints --- compiler/rustc_type_ir/src/region_constraint.rs | 4 ++++ .../reflexive-placeholder-outlives.rs | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 9a643b538d93f..9c6fd993b180a 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -645,6 +645,10 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { + if region_1 == region_2 { + continue; + } + let region_1_u = max_universe(infcx, region_1); let region_2_u = max_universe(infcx, region_2); diff --git a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs new file mode 100644 index 0000000000000..5ae97af1198d0 --- /dev/null +++ b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs @@ -0,0 +1,17 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] + +// Regression test for rust-lang/project-assumptions-on-binders#19. +core::test_binder_constraints! { + impl<> { + forall<'a> { + 'a: 'a + } expect { + } + } +} + +fn main() {} From f88e474b8eac1d87afefce3f7588931caabdf9f7 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:04:16 -0300 Subject: [PATCH 0164/1309] Discharge region constraints entailed by assumptions --- .../rustc_type_ir/src/region_constraint.rs | 8 +++ .../reflexive-placeholder-outlives.rs | 17 ----- .../same-universe-placeholder-outlives.rs | 64 +++++++++++++++++++ 3 files changed, 72 insertions(+), 17 deletions(-) delete mode 100644 tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs create mode 100644 tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 9c6fd993b180a..7b661c400b1ea 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -665,6 +665,14 @@ fn pull_region_outlives_constraints_out_of_universe< } }; + // The constraint may already be entailed by the assumptions of the binder we are + // leaving, e.g. `for<'a, 'b> where 'b: 'a { 'b: 'a }`. There is nothing to lift into + // a smaller universe in that case, and looking for lower universe candidates would + // wrongly result in `Or([])` whenever the placeholders have no lower universe bounds. + if regions_outlived_by(region_1, assumptions).any(|r| r == region_2) { + continue; + } + let mut candidates = vec![]; for ub in regions_outlived_by(region_1, assumptions) diff --git a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs deleted file mode 100644 index 5ae97af1198d0..0000000000000 --- a/tests/ui/assumptions_on_binders/reflexive-placeholder-outlives.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ check-pass -//@ compile-flags: -Zassumptions-on-binders - -#![feature(test_binder_constraints, non_lifetime_binders)] -#![expect(incomplete_features)] - -// Regression test for rust-lang/project-assumptions-on-binders#19. -core::test_binder_constraints! { - impl<> { - forall<'a> { - 'a: 'a - } expect { - } - } -} - -fn main() {} diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs new file mode 100644 index 0000000000000..6d292416cd4cf --- /dev/null +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -0,0 +1,64 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] + +// Regression test for rust-lang/project-assumptions-on-binders#19. +// +// When leaving a binder we lift its region constraints into a smaller universe. Constraints +// which already hold inside of the binder have no lower universe candidates to be lifted to, +// so they used to turn into `Or([])`, i.e. `false`. They have to be discharged instead. + +// Outlives is reflexive. +core::test_binder_constraints! { + impl<> { + forall<'a> { + 'a: 'a + } expect { + } + } +} + +// Directly entailed by an assumption of the binder we're leaving. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where 'b: 'a { + 'b: 'a + } expect { + } + } +} + +// Transitively entailed by the assumptions of the binder we're leaving. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b, 'c> where 'c: 'b, 'b: 'a { + 'c: 'a + } expect { + } + } +} + +// Discharging entailed constraints must not swallow the ones which still have to be lifted +// into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while +// `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. +// +// FIXME(-Zassumptions-on-binders): this should be `impl<'b, 'c: 'b>`, not +// `impl<'b, 'c: 'b + 'static>`, but OR isn't actually implemented yet +core::test_binder_constraints! { + impl<'b, 'c: 'b + 'static> { + forall<'a> where 'b: 'a { + 'a: 'a, + 'b: 'a, + 'c: 'a, + } expect { + or { + 'c: 'b, + 'c: 'static, + } + } + } +} + +fn main() {} From 5cbee6e22b49e219570a7745599e35401fa6e53a Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:08:04 -0300 Subject: [PATCH 0165/1309] Include implied regions in outlives assumptions --- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +++- .../src/infer/outlives/obligations.rs | 17 +++++++- .../eval_ctxt/solver_region_constraints.rs | 5 ++- .../rustc_type_ir/src/region_constraint.rs | 42 +++++++++++++++++++ .../same-universe-placeholder-outlives.rs | 22 ++++++++++ 5 files changed, 88 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0dee9690737df..34f8ae70abac4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2406,8 +2406,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { for &(r1, r2) in &body.region_outlives { builder.add(r1, r2); } - let assumptions = - ty::region_constraint::Assumptions::new(body.type_outlives, builder.freeze()); + let assumptions = ty::region_constraint::Assumptions::new( + self.tcx(), + body.type_outlives, + builder.freeze(), + ); self.infcx.insert_placeholder_assumptions(u, Some(assumptions)); self.check_test_binder_body(body.value); let solver_region_constraint = self.infcx.get_solver_region_constraint(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index cbbf5e3c91c42..23eb48d43dfb7 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -234,8 +234,22 @@ impl<'tcx> InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) { + // `known_type_outlives` only contains the explicit `Ty: 'a` where clauses. The implied + // bounds, e.g. `T: 'a` from a `&'a T` argument, are only tracked in `region_bound_pairs` + // so we have to pull them in separately. Without them we'd fail to prove `T: 'a` for a + // `&'a T` argument whenever the only explicit bound on `T` mentions a different region. + let mut known_type_outlives = outlives_env.known_type_outlives().to_vec(); + for &ty::OutlivesClause(kind, r) in outlives_env.region_bound_pairs() { + let ty = match kind { + GenericKind::Param(p) => Ty::new_param(self.tcx, p.index, p.name), + GenericKind::Placeholder(p) => Ty::new_placeholder(self.tcx, p), + GenericKind::Alias(alias) => alias.to_ty(self.tcx, ty::IsRigid::Yes), + }; + known_type_outlives.push(ty::Binder::dummy(ty::OutlivesClause(ty, r))); + } let assumptions = rustc_type_ir::region_constraint::Assumptions::new( - outlives_env.known_type_outlives().into_iter().cloned().collect(), + self.tcx, + known_type_outlives, outlives_env.free_region_map().relation.clone(), ); self.destructure_solver_region_constraints(assumptions, self); @@ -249,6 +263,7 @@ impl<'tcx> InferCtxt<'tcx> { region_outlives: TransitiveRelation, ) { let assumptions = region_constraint::Assumptions::new( + self.tcx, known_type_outlives.into_iter().cloned().collect(), region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(), ); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 5a4daa5e44fc5..d67e4cf0275bb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -102,8 +102,9 @@ where // FIXME(-Zassumptions-on-binders): we need to normalize here/somewhere // as we assume the type outlives assumptions only have rigid types :> + let cx = self.cx(); let clauses = rustc_type_ir::elaborate::elaborate( - self.cx(), + cx, reqs.into_iter().filter_map(|goal| goal.predicate.as_clause()), ); @@ -120,7 +121,7 @@ where }, ); - Some(Assumptions::new(type_outlives, region_outlives_builder.freeze())) + Some(Assumptions::new(cx, type_outlives, region_outlives_builder.freeze())) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 7b661c400b1ea..b0e931f5ab6bf 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -49,6 +49,7 @@ impl Default for TransitiveRelationBuilder { use crate::data_structures::IndexMap; use crate::fold::TypeSuperFoldable; use crate::inherent::*; +use crate::outlives::{Component, push_outlives_components}; use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, InferCtxtLike, @@ -73,9 +74,50 @@ impl Assumptions { } pub fn new( + cx: I, type_outlives: Vec>>, region_outlives: TransitiveRelation>, ) -> Self { + // A `Ty: 'a` assumption also tells us that every region component of `Ty` outlives `'a`, + // e.g. `&'b u8: 'a` implies `'b: 'a`. Callers do not necessarily hand us an elaborated set + // of assumptions so we destructure them here, otherwise we'd fail to prove `'b: 'a` when + // leaving the binder these assumptions belong to. + // + // The type outlives assumptions are still kept around as they are required for proving + // placeholder and alias outlives. + // + // This mirrors `elaborate`, in particular in how it deals with binders: they're simply + // skipped, so `for<'c> Foo<'a, 'c>: 'b` still gives us `'a: 'b`. + let mut implied_region_outlives = vec![]; + for clause in &type_outlives { + let OutlivesClause(ty, r) = clause.clone().skip_binder(); + // Ignore `for<'a> Ty: 'a`. We could treat this as evidence for `Ty: 'static` but + // `elaborate` conservatively doesn't, so neither do we. + if r.is_bound() { + continue; + } + let mut components = Default::default(); + push_outlives_components(cx, ty, &mut components); + implied_region_outlives.extend(components.into_iter().filter_map(|c| match c { + // Regions bound *inside* of `ty` don't relate to anything in scope here. + Component::Region(c_r) if !c_r.is_bound() => Some((c_r, r)), + _ => None, + })); + } + + let region_outlives = if implied_region_outlives.is_empty() { + region_outlives + } else { + let mut builder = TransitiveRelationBuilder::default(); + for (r1, r2) in region_outlives.base_edges() { + builder.add(r1, r2); + } + for (r1, r2) in implied_region_outlives { + builder.add(r1, r2); + } + builder.freeze() + }; + Self { inverse_region_outlives: { let mut builder = TransitiveRelationBuilder::default(); diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 6d292416cd4cf..56bbf8eacbbcd 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -40,6 +40,28 @@ core::test_binder_constraints! { } } +// `&'b u8: 'a` implies `'b: 'a`, so type outlives assumptions have to be destructured into +// region outlives assumptions. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where &'b u8: 'a { + 'b: 'a + } expect { + } + } +} + +// Binders in a type outlives assumption are skipped rather than bailed on, so +// `for<'c> fn(&'c (), &'b u8): 'a` still gives us `'b: 'a`. +core::test_binder_constraints! { + impl<> { + forall<'a, 'b> where for<'c> fn(&'c (), &'b u8): 'a { + 'b: 'a + } expect { + } + } +} + // Discharging entailed constraints must not swallow the ones which still have to be lifted // into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while // `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. From fdc2acbb46d64fd4638168350a020d7759e12405 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 29 Aug 2026 21:10:50 -0300 Subject: [PATCH 0166/1309] Evaluate reflexive region constraints at the root --- .../rustc_type_ir/src/region_constraint.rs | 27 +++++++++++++----- .../reflexive-outlives-in-root.rs | 28 +++++++++++++++++++ 2 files changed, 48 insertions(+), 7 deletions(-) create mode 100644 tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index b0e931f5ab6bf..d0de852f60b3b 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -687,6 +687,8 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { + // Outlives is reflexive, so this holds no matter which universes are involved + // and regardless of whether we know the assumptions for `u`. if region_1 == region_2 { continue; } @@ -771,16 +773,27 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { + // Outlives is reflexive. Discharging this here and not just when leaving a universe + // matters as constraints are also destructured in the root, where reflexive candidates + // are the whole reason an OR is satisfiable. E.g. `!T: 'a` with a `!T: 'a` assumption + // ends up as `Or([.., RegionOutlives('a, 'a)])`. + RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } - PlaceholderTyOutlives(ty, r, span) => destructured_constraints.push(Or::new( - regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).map( - move |assumption_r| { - And::new([RegionOutlives(assumption_r, *r, span.clone())]) - }, - ), - )), + PlaceholderTyOutlives(ty, r, span) => { + let candidates = + regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).collect::>(); + if candidates.contains(r) { + destructured_constraints.push(Or::new_true()); + } else { + destructured_constraints.push(Or::new(candidates.into_iter().map( + move |assumption_r| { + And::new([RegionOutlives(assumption_r, *r, span.clone())]) + }, + ))); + } + } AliasTyOutlivesViaEnv(bound_outlives, span) => { destructured_constraints.push( alias_outlives_candidates_from_assumptions( diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs new file mode 100644 index 0000000000000..c6e7f025219dc --- /dev/null +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -0,0 +1,28 @@ +//@ check-pass +//@ compile-flags: -Zassumptions-on-binders + +// Regression test for rust-lang/project-assumptions-on-binders#19, minimized from `syn`. +// +// Proving `I: '_` for the `&'_ self` receiver destructures to an OR over every region which +// `I` is known to outlive. Two things are needed for that OR to be satisfiable: +// +// - the implied bound `I: '_` from `&'_ self` has to be part of the root assumptions, not just +// the explicit `I: 'a` where clause, as `'a: '_` does not hold +// - the resulting `RegionOutlives('_, '_)` candidate has to be discharged, which happens when +// evaluating the constraint rather than when leaving a universe + +trait IterTrait<'a, T: 'a>: Iterator { + fn clone_box(&self) -> Box + 'a>; +} + +impl<'a, T, I> IterTrait<'a, T> for I +where + T: 'a, + I: Iterator + Clone + 'a, +{ + fn clone_box(&self) -> Box + 'a> { + Box::new(self.clone()) + } +} + +fn main() {} From 4b73b07cc424d06a9fb7c7ce1c18d55b4f1bfb42 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Thu, 3 Sep 2026 10:11:05 -0300 Subject: [PATCH 0167/1309] Keep reflexive constraint handling self-contained --- .../rustc_hir_analysis/src/check/wfcheck.rs | 7 +-- .../src/infer/outlives/obligations.rs | 17 +----- .../eval_ctxt/solver_region_constraints.rs | 5 +- .../rustc_type_ir/src/region_constraint.rs | 60 ++----------------- .../reflexive-outlives-in-root.rs | 29 +++------ .../same-universe-placeholder-outlives.rs | 22 ------- 6 files changed, 19 insertions(+), 121 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 34f8ae70abac4..0dee9690737df 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2406,11 +2406,8 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { for &(r1, r2) in &body.region_outlives { builder.add(r1, r2); } - let assumptions = ty::region_constraint::Assumptions::new( - self.tcx(), - body.type_outlives, - builder.freeze(), - ); + let assumptions = + ty::region_constraint::Assumptions::new(body.type_outlives, builder.freeze()); self.infcx.insert_placeholder_assumptions(u, Some(assumptions)); self.check_test_binder_body(body.value); let solver_region_constraint = self.infcx.get_solver_region_constraint(); diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 23eb48d43dfb7..cbbf5e3c91c42 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -234,22 +234,8 @@ impl<'tcx> InferCtxt<'tcx> { &self, outlives_env: &OutlivesEnvironment<'tcx>, ) { - // `known_type_outlives` only contains the explicit `Ty: 'a` where clauses. The implied - // bounds, e.g. `T: 'a` from a `&'a T` argument, are only tracked in `region_bound_pairs` - // so we have to pull them in separately. Without them we'd fail to prove `T: 'a` for a - // `&'a T` argument whenever the only explicit bound on `T` mentions a different region. - let mut known_type_outlives = outlives_env.known_type_outlives().to_vec(); - for &ty::OutlivesClause(kind, r) in outlives_env.region_bound_pairs() { - let ty = match kind { - GenericKind::Param(p) => Ty::new_param(self.tcx, p.index, p.name), - GenericKind::Placeholder(p) => Ty::new_placeholder(self.tcx, p), - GenericKind::Alias(alias) => alias.to_ty(self.tcx, ty::IsRigid::Yes), - }; - known_type_outlives.push(ty::Binder::dummy(ty::OutlivesClause(ty, r))); - } let assumptions = rustc_type_ir::region_constraint::Assumptions::new( - self.tcx, - known_type_outlives, + outlives_env.known_type_outlives().into_iter().cloned().collect(), outlives_env.free_region_map().relation.clone(), ); self.destructure_solver_region_constraints(assumptions, self); @@ -263,7 +249,6 @@ impl<'tcx> InferCtxt<'tcx> { region_outlives: TransitiveRelation, ) { let assumptions = region_constraint::Assumptions::new( - self.tcx, known_type_outlives.into_iter().cloned().collect(), region_outlives.maybe_map(|r| Some(Region::new_var(self.tcx, r))).unwrap(), ); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index d67e4cf0275bb..5a4daa5e44fc5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -102,9 +102,8 @@ where // FIXME(-Zassumptions-on-binders): we need to normalize here/somewhere // as we assume the type outlives assumptions only have rigid types :> - let cx = self.cx(); let clauses = rustc_type_ir::elaborate::elaborate( - cx, + self.cx(), reqs.into_iter().filter_map(|goal| goal.predicate.as_clause()), ); @@ -121,7 +120,7 @@ where }, ); - Some(Assumptions::new(cx, type_outlives, region_outlives_builder.freeze())) + Some(Assumptions::new(type_outlives, region_outlives_builder.freeze())) } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index d0de852f60b3b..ff7b00fdbbd98 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -49,7 +49,6 @@ impl Default for TransitiveRelationBuilder { use crate::data_structures::IndexMap; use crate::fold::TypeSuperFoldable; use crate::inherent::*; -use crate::outlives::{Component, push_outlives_components}; use crate::relate::{Relate, RelateResult, TypeRelation, VarianceDiagInfo}; use crate::{ AliasTy, Binder, BoundRegion, BoundVar, BoundVariableKind, DebruijnIndex, InferCtxtLike, @@ -74,50 +73,9 @@ impl Assumptions { } pub fn new( - cx: I, type_outlives: Vec>>, region_outlives: TransitiveRelation>, ) -> Self { - // A `Ty: 'a` assumption also tells us that every region component of `Ty` outlives `'a`, - // e.g. `&'b u8: 'a` implies `'b: 'a`. Callers do not necessarily hand us an elaborated set - // of assumptions so we destructure them here, otherwise we'd fail to prove `'b: 'a` when - // leaving the binder these assumptions belong to. - // - // The type outlives assumptions are still kept around as they are required for proving - // placeholder and alias outlives. - // - // This mirrors `elaborate`, in particular in how it deals with binders: they're simply - // skipped, so `for<'c> Foo<'a, 'c>: 'b` still gives us `'a: 'b`. - let mut implied_region_outlives = vec![]; - for clause in &type_outlives { - let OutlivesClause(ty, r) = clause.clone().skip_binder(); - // Ignore `for<'a> Ty: 'a`. We could treat this as evidence for `Ty: 'static` but - // `elaborate` conservatively doesn't, so neither do we. - if r.is_bound() { - continue; - } - let mut components = Default::default(); - push_outlives_components(cx, ty, &mut components); - implied_region_outlives.extend(components.into_iter().filter_map(|c| match c { - // Regions bound *inside* of `ty` don't relate to anything in scope here. - Component::Region(c_r) if !c_r.is_bound() => Some((c_r, r)), - _ => None, - })); - } - - let region_outlives = if implied_region_outlives.is_empty() { - region_outlives - } else { - let mut builder = TransitiveRelationBuilder::default(); - for (r1, r2) in region_outlives.base_edges() { - builder.add(r1, r2); - } - for (r1, r2) in implied_region_outlives { - builder.add(r1, r2); - } - builder.freeze() - }; - Self { inverse_region_outlives: { let mut builder = TransitiveRelationBuilder::default(); @@ -687,12 +645,6 @@ fn pull_region_outlives_constraints_out_of_universe< pulled_constraints.push(Or::new_leaf(c.clone())); } RegionOutlives(region_1, region_2, ()) => { - // Outlives is reflexive, so this holds no matter which universes are involved - // and regardless of whether we know the assumptions for `u`. - if region_1 == region_2 { - continue; - } - let region_1_u = max_universe(infcx, region_1); let region_2_u = max_universe(infcx, region_2); @@ -773,17 +725,16 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { - // Outlives is reflexive. Discharging this here and not just when leaving a universe - // matters as constraints are also destructured in the root, where reflexive candidates - // are the whole reason an OR is satisfiable. E.g. `!T: 'a` with a `!T: 'a` assumption - // ends up as `Or([.., RegionOutlives('a, 'a)])`. + // Root constraints never go through `pull_region_outlives_constraints_out_of_universe`. + // A reflexive leaf may be the candidate which makes a root OR true, so discharge it here + // instead of requiring the remaining candidates to hold. RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } PlaceholderTyOutlives(ty, r, span) => { - let candidates = - regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).collect::>(); + let candidates = regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()) + .collect::>(); if candidates.contains(r) { destructured_constraints.push(Or::new_true()); } else { @@ -1059,7 +1010,6 @@ pub fn regions_outlived_by( r: Region, assumptions: &Assumptions, ) -> impl Iterator> { - // FIXME(-Zassumptions-on-binders): do we need to be adding the reflexive edge here? assumptions.region_outlives.reachable_from(r).into_iter().chain([r]) } diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index c6e7f025219dc..9cac9e0eaeed3 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -1,27 +1,16 @@ //@ check-pass //@ compile-flags: -Zassumptions-on-binders -// Regression test for rust-lang/project-assumptions-on-binders#19, minimized from `syn`. -// -// Proving `I: '_` for the `&'_ self` receiver destructures to an OR over every region which -// `I` is known to outlive. Two things are needed for that OR to be satisfiable: -// -// - the implied bound `I: '_` from `&'_ self` has to be part of the root assumptions, not just -// the explicit `I: 'a` where clause, as `'a: '_` does not hold -// - the resulting `RegionOutlives('_, '_)` candidate has to be discharged, which happens when -// evaluating the constraint rather than when leaving a universe +#![feature(test_binder_constraints, non_lifetime_binders)] +#![expect(incomplete_features)] -trait IterTrait<'a, T: 'a>: Iterator { - fn clone_box(&self) -> Box + 'a>; -} - -impl<'a, T, I> IterTrait<'a, T> for I -where - T: 'a, - I: Iterator + Clone + 'a, -{ - fn clone_box(&self) -> Box + 'a> { - Box::new(self.clone()) +// Root type outlives constraints are destructured into an OR over every region the type is known +// to outlive. The reflexive `'b: 'b` candidate makes this OR true even though the unrelated +// `'a: 'b` candidate does not hold. Root constraints never go through the universe-pulling code, +// so evaluation has to recognize the reflexive candidate itself. +core::test_binder_constraints! { + impl<'a, 'b, T: 'a + 'b> { + T: 'b } } diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 56bbf8eacbbcd..6d292416cd4cf 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -40,28 +40,6 @@ core::test_binder_constraints! { } } -// `&'b u8: 'a` implies `'b: 'a`, so type outlives assumptions have to be destructured into -// region outlives assumptions. -core::test_binder_constraints! { - impl<> { - forall<'a, 'b> where &'b u8: 'a { - 'b: 'a - } expect { - } - } -} - -// Binders in a type outlives assumption are skipped rather than bailed on, so -// `for<'c> fn(&'c (), &'b u8): 'a` still gives us `'b: 'a`. -core::test_binder_constraints! { - impl<> { - forall<'a, 'b> where for<'c> fn(&'c (), &'b u8): 'a { - 'b: 'a - } expect { - } - } -} - // Discharging entailed constraints must not swallow the ones which still have to be lifted // into the outer universe. Here `'a: 'a` and `'b: 'a` are discharged inside the binder while // `'c: 'a` is lifted, as `'c` outlives every lower universe region that `'a` outlives. From ca6e6f04149170fd7ebd78d6559b03a5dedcc6ae Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Mon, 7 Sep 2026 10:07:09 -0300 Subject: [PATCH 0168/1309] Drop trivially true region constraints when canonicalizing A reflexive `'a: 'a` leaf is always satisfied, so filter it out in `And::new` instead of pattern matching for it in the places which happen to build such a constraint. An AND which ends up empty is trivially true, which makes the OR containing it true. This is how a reflexive candidate discharges a root type outlives constraint, so `destructure_type_outlives_constraints_in_root` no longer has to look at region outlives leaves at all. --- .../rustc_type_ir/src/region_constraint.rs | 46 +++++++++++-------- .../reflexive-outlives-in-root.rs | 4 +- .../test-infra-fails-properly.rs | 2 +- .../test-infra-fails-properly.stderr | 4 +- 4 files changed, 32 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index ff7b00fdbbd98..fcea7db55df1a 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -165,6 +165,7 @@ impl LeafRegionC /// An OR of AND of LEAF constraints. Always in "canonical form" meaning: /// - No two ANDs are equivalent /// - All ANDs are in canonical form +/// - If any AND is empty, i.e. trivially true, it is the only AND pub struct Or(pub Box<[And]>); impl Or { pub fn with_spans( @@ -204,6 +205,13 @@ impl Or { let mut new_ands: Vec> = Vec::new(); for and in ands { + // An empty AND is trivially true, which makes the whole OR true no matter what the + // other candidates are. `And::new` discards leaf constraints which are trivially + // true, so this is how e.g. a reflexive `'a: 'a` candidate discharges an OR. + if and.0.is_empty() { + return Self::new_true(); + } + if new_ands.iter().all(|c| !c.is_and_equivalent_to(&and)) { new_ands.push(and) } @@ -217,7 +225,7 @@ impl Or { } pub fn new_leaf(l: LeafRegionConstraint) -> Self { - Or(Box::new([And(Box::new([l]))])) + Or::new([And::new([l])]) } pub fn build_and(a: Or, b: Or) -> Self { @@ -249,6 +257,7 @@ impl Or { #[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] /// An AND of leaf constraints. Always in "canonical form", meaning: /// - No leaf constraints are present twice in this AND +/// - No leaf constraint is trivially true, i.e. a reflexive `'a: 'a` pub struct And(pub Box<[LeafRegionConstraint]>); impl And { pub fn with_spans( @@ -264,6 +273,15 @@ impl And { And(i .into_iter() .filter(|leaf| { + // Outlives is reflexive so a `'a: 'a` leaf is always true and carries no + // information. Dropping it here keeps the rest of the code from having to special + // case it, and is what lets an OR with a reflexive candidate be recognized as true. + if let LeafRegionConstraint::RegionOutlives(r1, r2, _) = leaf + && r1 == r2 + { + return false; + } + if seen.contains(&leaf.clone().without_span()) { false } else { @@ -409,7 +427,7 @@ impl RegionConst } pub fn new_leaf(l: LeafRegionConstraint) -> Self { - RegionConstraint { and_constraint: And(Box::new([l])), or_constraint: Or::new_true() } + RegionConstraint { and_constraint: And::new([l]), or_constraint: Or::new_true() } } } @@ -725,26 +743,16 @@ pub fn destructure_type_outlives_constraints_in_root< let mut destructured_constraints = Vec::new(); for c in &and.0 { match c { - // Root constraints never go through `pull_region_outlives_constraints_out_of_universe`. - // A reflexive leaf may be the candidate which makes a root OR true, so discharge it here - // instead of requiring the remaining candidates to hold. - RegionOutlives(r1, r2, _) if r1 == r2 => {} Ambiguity(_) | RegionOutlives(..) => { destructured_constraints.push(Or::new_leaf(c.clone())) } - PlaceholderTyOutlives(ty, r, span) => { - let candidates = regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()) - .collect::>(); - if candidates.contains(r) { - destructured_constraints.push(Or::new_true()); - } else { - destructured_constraints.push(Or::new(candidates.into_iter().map( - move |assumption_r| { - And::new([RegionOutlives(assumption_r, *r, span.clone())]) - }, - ))); - } - } + PlaceholderTyOutlives(ty, r, span) => destructured_constraints.push(Or::new( + regions_outlived_by_placeholder(*ty, assumptions, infcx.cx()).map( + move |assumption_r| { + And::new([RegionOutlives(assumption_r, *r, span.clone())]) + }, + ), + )), AliasTyOutlivesViaEnv(bound_outlives, span) => { destructured_constraints.push( alias_outlives_candidates_from_assumptions( diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index 9cac9e0eaeed3..641ac3951d76a 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -6,8 +6,8 @@ // Root type outlives constraints are destructured into an OR over every region the type is known // to outlive. The reflexive `'b: 'b` candidate makes this OR true even though the unrelated -// `'a: 'b` candidate does not hold. Root constraints never go through the universe-pulling code, -// so evaluation has to recognize the reflexive candidate itself. +// `'a: 'b` candidate does not hold. Reflexive leaves are dropped when building an AND, which +// leaves an empty, i.e. trivially true, AND as one of the candidates of the OR. core::test_binder_constraints! { impl<'a, 'b, T: 'a + 'b> { T: 'b diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index 240b64e770f51..97629627ad556 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -60,7 +60,7 @@ core::test_binder_constraints! { } expect { or { 'c: 'b, - 'c: 'c, + 'b: 'c, //~^ ERROR forall expect clause failed } } diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr index 2931a37c0f340..ab025b0e0b9d6 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.stderr @@ -53,7 +53,7 @@ LL | T: 'a, error: forall expect clause failed --> $DIR/test-infra-fails-properly.rs:63:17 | -LL | 'c: 'c, +LL | 'b: 'c, | ^^^^^^ | note: constraint from here @@ -62,7 +62,7 @@ note: constraint from here LL | forall<'a> where 'b: 'a { | ^^^^^^ = note: expected: RegionOutlives( - 'c/#1, + 'b/#0, 'c/#1, $DIR/test-infra-fails-properly.rs:63:17: 63:23 (#0), ) From 0016f59536f3ca4050a621342470fba5983e1a0f Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Mon, 7 Sep 2026 19:00:53 +0100 Subject: [PATCH 0169/1309] Run rustfmt --- library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs index e5722a2d9f49f..537c59bbce861 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs @@ -213,7 +213,7 @@ fn parse_compound_expr(expr: &str) -> Option { if let Some(paren_pos) = after_prefix.find(')') { let builtin_name = &after_prefix[..paren_pos]; let rest = &after_prefix[paren_pos + 1..]; // Skip the closing ) of the WRAP - // rest should now be "(args)" + // rest should now be "(args)" if rest.starts_with('(') && rest.ends_with(')') { let args_str = &rest[1..rest.len() - 1]; let args = parse_compound_args(args_str)?; From f2828cfe4436da090440d295bbe8c866e42c37d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mateusz=20Miku=C5=82a?= Date: Wed, 1 Jul 2026 18:38:41 +0200 Subject: [PATCH 0170/1309] windows-gnu: enable native TLS --- compiler/rustc_target/src/spec/base/windows_gnu.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_target/src/spec/base/windows_gnu.rs b/compiler/rustc_target/src/spec/base/windows_gnu.rs index 1a343c737ad45..c2cf50b40a478 100644 --- a/compiler/rustc_target/src/spec/base/windows_gnu.rs +++ b/compiler/rustc_target/src/spec/base/windows_gnu.rs @@ -101,6 +101,7 @@ pub(crate) fn opts() -> TargetOptions { emit_debug_gdb_scripts: false, requires_uwtable: true, eh_frame_header: false, + has_thread_local: true, debuginfo_kind: DebuginfoKind::Dwarf, // FIXME(davidtwco): Support Split DWARF on Windows GNU - may require LLVM changes to // output DWO, despite using DWARF, doesn't use ELF.. From c9e2b6709dabbc42d2a6214c32b4574986815152 Mon Sep 17 00:00:00 2001 From: Yukang Date: Mon, 7 Sep 2026 14:04:46 +0800 Subject: [PATCH 0171/1309] Avoid suggesting imports of traits declared inside bodies --- .../rustc_hir_typeck/src/method/suggest.rs | 13 +++++----- ...ck-scoped-trait-import-issue-134146.stderr | 24 +++++-------------- 2 files changed, 12 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e59ca32aba116..349e6596bc4b0 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -426,12 +426,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { )); } else { msg += &format!(" but {} not reachable", pluralize!("is", suggs.len())); - err.span_suggestions( - span, - msg, - suggs, - Applicability::MaybeIncorrect, - ); + err.help(format!("{msg}:\n{}", suggs.join("").trim_end())); } }; if accessible_sugg.is_empty() { @@ -4002,6 +3997,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { candidates.into_iter().partition(|id| { let vis = self.tcx.visibility(*id); vis.is_accessible_from(scope, self.tcx) + // Visibility alone does not make `fn_name::Trait` an importable path. + // We need to make sure all parent are modules, otherwise the path is not importable. + && std::iter::successors(self.tcx.opt_parent(*id), |&id| self.tcx.opt_parent(id)) + .all(|id| self.tcx.def_kind(id) == DefKind::Mod) }); let sugg = |candidates: Vec<_>, visible| { @@ -4115,7 +4114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if suggs.len() == 1 { err.help(msg); } else { - err.span_suggestions(span, msg, suggs, Applicability::MaybeIncorrect); + err.help(format!("{msg}:\n{}", suggs.join("").trim_end())); } }; if accessible_sugg.is_empty() { diff --git a/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr index dfe305bf9853b..41827953bb796 100644 --- a/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr +++ b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr @@ -8,10 +8,7 @@ LL | ().hello(); | ^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope -help: trait `Hello` which provides `hello` is implemented but not in scope; perhaps you want to import it - | -LL + use main::Hello; - | + = help: trait `main::Hello` which provides `hello` is implemented but not reachable error[E0599]: no method named `nested` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:30:8 @@ -23,10 +20,7 @@ LL | ().nested(); | ^^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope -help: trait `Nested` which provides `nested` is implemented but not in scope; perhaps you want to import it - | -LL + use nested_module::inner::Nested; - | + = help: trait `nested_module::inner::Nested` which provides `nested` is implemented but not reachable error[E0599]: no method named `in_const` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:42:8 @@ -38,10 +32,7 @@ LL | ().in_const(); | ^^^^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope -help: trait `InConst` which provides `in_const` is implemented but not in scope; perhaps you want to import it - | -LL + use _::InConst; - | + = help: trait `_::InConst` which provides `in_const` is implemented but not reachable error[E0599]: no method named `several` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:57:8 @@ -50,12 +41,9 @@ LL | ().several(); | ^^^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope -help: the following traits which provide `several` are implemented but not in scope; perhaps you want to import one of them - | -LL + use multiple_candidates::First; - | -LL + use multiple_candidates::Second; - | + = help: the following traits which provide `several` are implemented but not reachable: + multiple_candidates::First + multiple_candidates::Second error: aborting due to 4 previous errors From b532a132d668cf7899a1720fe1eefb358bf17d11 Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Tue, 8 Sep 2026 10:03:23 -0300 Subject: [PATCH 0172/1309] Note that OR canonicalization could drop superset ANDs --- compiler/rustc_type_ir/src/region_constraint.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index fcea7db55df1a..da7b0be16cf64 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -166,6 +166,12 @@ impl LeafRegionC /// - No two ANDs are equivalent /// - All ANDs are in canonical form /// - If any AND is empty, i.e. trivially true, it is the only AND +/// +/// FIXME(-Zassumptions-on-binders): We should consider a more general canonical form which also +/// drops any AND that is a superset of another AND. Proving the superset requires strictly more +/// than proving the subset, so it can never be the candidate which makes the OR hold. E.g. +/// `OR(AND('a: 'b), AND('a: 'b, 'b: 'c))` really ought to just be `OR(AND('a: 'b))`. Only keeping +/// an empty AND is the degenerate case of that rule. pub struct Or(pub Box<[And]>); impl Or { pub fn with_spans( @@ -212,6 +218,10 @@ impl Or { return Self::new_true(); } + // FIXME(-Zassumptions-on-binders): We only discard an AND which is equivalent to one + // we already have. More generally we should discard any AND which is a superset of + // another, as it requires strictly more to hold. E.g. the second AND in + // `OR(AND('a: 'b), AND('a: 'b, 'b: 'c))` is never the one which makes the OR true. if new_ands.iter().all(|c| !c.is_and_equivalent_to(&and)) { new_ands.push(and) } From 7cbced258c8d0891a2a794fbfdb7253a9dbcd0e6 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Tue, 8 Sep 2026 14:38:52 +0100 Subject: [PATCH 0173/1309] Update vzipq arm instruction assertions --- .../src/arm_shared/neon/generated.rs | 36 +++++++++---------- .../spec/neon/arm_shared.spec.yml | 2 +- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs index 4fc46a3ba39e8..094b13ca8023a 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/neon/generated.rs @@ -70649,7 +70649,7 @@ pub fn vzip_p16(a: poly16x4_t, b: poly16x4_t) -> poly16x4x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70679,7 +70679,7 @@ pub fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70714,7 +70714,7 @@ pub fn vzipq_f32(a: float32x4_t, b: float32x4_t) -> float32x4x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70752,7 +70752,7 @@ pub fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70805,7 +70805,7 @@ pub fn vzipq_s8(a: int8x16_t, b: int8x16_t) -> int8x16x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70835,7 +70835,7 @@ pub fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70870,7 +70870,7 @@ pub fn vzipq_s16(a: int16x8_t, b: int16x8_t) -> int16x8x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70900,7 +70900,7 @@ pub fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70935,7 +70935,7 @@ pub fn vzipq_s32(a: int32x4_t, b: int32x4_t) -> int32x4x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -70973,7 +70973,7 @@ pub fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71026,7 +71026,7 @@ pub fn vzipq_u8(a: uint8x16_t, b: uint8x16_t) -> uint8x16x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71056,7 +71056,7 @@ pub fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71091,7 +71091,7 @@ pub fn vzipq_u16(a: uint16x8_t, b: uint16x8_t) -> uint16x8x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71121,7 +71121,7 @@ pub fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71156,7 +71156,7 @@ pub fn vzipq_u32(a: uint32x4_t, b: uint32x4_t) -> uint32x4x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71194,7 +71194,7 @@ pub fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71247,7 +71247,7 @@ pub fn vzipq_p8(a: poly8x16_t, b: poly8x16_t) -> poly8x16x2_t { #[cfg(target_endian = "little")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) @@ -71277,7 +71277,7 @@ pub fn vzipq_p16(a: poly16x8_t, b: poly16x8_t) -> poly16x8x2_t { #[cfg(target_endian = "big")] #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] -#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vorr))] +#[cfg_attr(all(test, target_arch = "arm"), assert_instr(vzip))] #[cfg_attr( all(test, any(target_arch = "aarch64", target_arch = "arm64ec")), assert_instr(zip1) diff --git a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml index 195243ac65d3a..a4ade26e45c37 100644 --- a/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml +++ b/library/stdarch/crates/stdarch-gen-arm/spec/neon/arm_shared.spec.yml @@ -9824,7 +9824,7 @@ intrinsics: return_type: "{neon_type[1]}" attr: - *neon-v7 - - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vorr]]}]] + - FnCall: [cfg_attr, [*test-is-arm, {FnCall: [assert_instr, [vzip]]}]] - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [zip1]]}]] - FnCall: [cfg_attr, [*neon-target-aarch64-arm64ec, {FnCall: [assert_instr, [zip2]]}]] - *neon-not-arm-stable From 2850a4cbcafa89ce80929f0cf02dfda19894ee5f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 8 Sep 2026 13:42:15 -0400 Subject: [PATCH 0174/1309] Update to nightly-2026-09-08 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index d777360fd4226..ed97309659931 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-08-04" +channel = "nightly-2026-09-08" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 55be6d95f5eda384b7a332f709ed59f6b74a5746 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 8 Sep 2026 13:56:07 -0400 Subject: [PATCH 0175/1309] Fix clippy warning --- build_system/src/test.rs | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index a5e79d6f3c1b3..d6a158e7b079b 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1062,10 +1062,7 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< eprintln!("nothing found for {file_path:?}"); } // The files in this directory contain errors. - if file_path.contains("/error-emitter/") { - return Ok(true); - } - Ok(false) + Ok(file_path.contains("/error-emitter/")) } // # Parameters From 406f9ec562c495bc9b365af8c1c9f78958b1c68a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 4 Sep 2026 10:22:42 -0400 Subject: [PATCH 0176/1309] Fix failing libcore doctests --- build_system/src/test.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index d6a158e7b079b..6f33bdc392984 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -845,6 +845,8 @@ fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { // `core::io::ErrorKind`'s `Display` impl declares `#![feature(core_io)]` upstream: without // it, that doctest fails to compile with `E0658` on any backend. &"-Zforce-unstable-if-unmarked", + // FIXME: one test cannot compile due to an upstream bug in the new trait solver. + &"-Znext-solver=coherence", ]; for flag in &rustflags { command.push(flag); From c18476f93b4096d23e3a2aba19cdb62b0a8b0f20 Mon Sep 17 00:00:00 2001 From: 000wahab000 Date: Wed, 9 Sep 2026 01:35:48 +0530 Subject: [PATCH 0177/1309] fix: typo in thir.md --- src/doc/rustc-dev-guide/src/thir.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/thir.md b/src/doc/rustc-dev-guide/src/thir.md index 1ba30d86a6913..8b80d0be16874 100644 --- a/src/doc/rustc-dev-guide/src/thir.md +++ b/src/doc/rustc-dev-guide/src/thir.md @@ -136,7 +136,7 @@ Thir { kind: Scope { region_scope: Node(5), hir_id: HirId(DefId(0:3 ~ main[26fd]::main).5), - // reference to expression 0 above + // reference to expression 2 above value: e2, }, ty: i32, From 4e56f8edecf6e4e2be61e3ecf4a4be44c8cdba5c Mon Sep 17 00:00:00 2001 From: devangpratap <115096812+devangpratap@users.noreply.github.com> Date: Tue, 8 Sep 2026 19:13:49 -0400 Subject: [PATCH 0178/1309] fix: don't treat a raw identifier as a raw string prefix CharClasses entered raw string state whenever `r` was followed by `#`, which also matches a raw identifier such as `r#struct`. That marked the first few characters as InString, so replace_names copied `r#s` through verbatim and registered the leftover `truct` as the metavariable name. Undoing the substitution afterwards put the `$` back in the wrong place, so `$r#struct` came out as `r#s$truct` and no longer compiled. Only enter raw string state when the run of `#`s after `r` ends in a quote. --- src/comment.rs | 26 +++++++++++++++++++++++++- tests/target/issue-7056.rs | 25 +++++++++++++++++++++++++ 2 files changed, 50 insertions(+), 1 deletion(-) create mode 100644 tests/target/issue-7056.rs diff --git a/src/comment.rs b/src/comment.rs index 40e42b53ed1bc..4162b5f0db824 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -1347,6 +1347,24 @@ where } } +/// Returns `true` if the `r` just consumed opens a raw string literal, i.e. the run of +/// `#`s that follows it ends in a `"`. Peeking a single `#` is not enough to tell a raw +/// string apart from a raw identifier such as `r#struct`. +fn is_raw_string_prefix(iter: &mut MultiPeek) -> bool +where + T: Iterator, + T::Item: RichChar, +{ + while let Some(c) = iter.peek() { + match c.get_char() { + '#' => continue, + '"' => return true, + _ => return false, + } + } + false +} + fn is_raw_string_suffix(iter: &mut MultiPeek, count: u32) -> bool where T: Iterator, @@ -1430,7 +1448,13 @@ where CharClassesStatus::LitCharEscape => CharClassesStatus::LitChar, CharClassesStatus::Normal => match chr { 'r' => match self.base.peek().map(RichChar::get_char) { - Some('#') | Some('"') => { + Some('"') => { + char_kind = FullCodeCharKind::InString; + CharClassesStatus::RawStringPrefix(0) + } + // `r#` opens a raw string only if the `#`s end in a `"`; otherwise + // this is a raw identifier like `r#struct` and stays normal code. + Some('#') if is_raw_string_prefix(&mut self.base) => { char_kind = FullCodeCharKind::InString; CharClassesStatus::RawStringPrefix(0) } diff --git a/tests/target/issue-7056.rs b/tests/target/issue-7056.rs new file mode 100644 index 0000000000000..daa05387921a6 --- /dev/null +++ b/tests/target/issue-7056.rs @@ -0,0 +1,25 @@ +// `r#` opens a raw string only when the run of `#`s ends in a `"`. A raw identifier +// such as `r#struct` must stay classified as normal code, or the macro body rewriter +// copies part of it through verbatim and puts the `$` back in the wrong place. + +#![feature(decl_macro)] + +macro_rules! r#struct { + ($r#struct:expr) => { $r#struct } +} + +macro r#decl_macro($r#fn:expr) { + $r#fn +} + +macro_rules! old_macro { + ($a:expr) => { + $a + }; +} + +fn raw_ident_next_to_a_raw_string() { + let r#match = r#"still a raw string"#; + let r#fn = r##"hashes too"##; + let _ = (r#match, r#fn); +} From b30d30cd7beafebdd5c692171b303f4223b9f3fe Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2026 01:41:20 +0000 Subject: [PATCH 0179/1309] Bump tracing-subscriber from 0.3.18 to 0.3.20 in /check_diff Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.18 to 0.3.20. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.18...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- check_diff/Cargo.lock | 101 ++++++++---------------------------------- 1 file changed, 18 insertions(+), 83 deletions(-) diff --git a/check_diff/Cargo.lock b/check_diff/Cargo.lock index 8093a08326d2c..1c76fa1e9faa5 100644 --- a/check_diff/Cargo.lock +++ b/check_diff/Cargo.lock @@ -183,7 +183,7 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5d3041965b7a63e70447ec818a46b1e5297f7fcae3058356d226c02750c4e6cb" dependencies = [ - "nu-ansi-term 0.50.1", + "nu-ansi-term", ] [[package]] @@ -217,8 +217,8 @@ dependencies = [ "aho-corasick", "bstr", "log", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", + "regex-automata", + "regex-syntax", ] [[package]] @@ -243,7 +243,7 @@ dependencies = [ "globset", "log", "memchr", - "regex-automata 0.4.7", + "regex-automata", "same-file", "walkdir", "winapi-util", @@ -291,11 +291,11 @@ checksum = "90ed8c1e510134f979dbc4f070f87d4313098b704861a105fe34231c70a3901c" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ - "regex-automata 0.1.10", + "regex-automata", ] [[package]] @@ -304,16 +304,6 @@ version = "2.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "78ca9ab1a0babb1e7d5695e3530886289c18cf2f87ec19a575a0abdce112e3a3" -[[package]] -name = "nu-ansi-term" -version = "0.46.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" -dependencies = [ - "overload", - "winapi", -] - [[package]] name = "nu-ansi-term" version = "0.50.1" @@ -329,12 +319,6 @@ version = "1.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3fdb12b2476b595f9358c5161aa467c2438859caa136dec86c26fdd2efe17b92" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "pin-project-lite" version = "0.2.14" @@ -359,27 +343,6 @@ dependencies = [ "proc-macro2", ] -[[package]] -name = "regex" -version = "1.10.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b91213439dad192326a0d7c6ee3955910425f441d7038e0d6933b0aec5c4517f" -dependencies = [ - "aho-corasick", - "memchr", - "regex-automata 0.4.7", - "regex-syntax 0.8.4", -] - -[[package]] -name = "regex-automata" -version = "0.1.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" -dependencies = [ - "regex-syntax 0.6.29", -] - [[package]] name = "regex-automata" version = "0.4.7" @@ -388,15 +351,9 @@ checksum = "38caf58cc5ef2fed281f89292ef23f6365465ed9a41b7a7754eb4e26496c92df" dependencies = [ "aho-corasick", "memchr", - "regex-syntax 0.8.4", + "regex-syntax", ] -[[package]] -name = "regex-syntax" -version = "0.6.29" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" - [[package]] name = "regex-syntax" version = "0.8.4" @@ -558,9 +515,9 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tracing" -version = "0.1.40" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c3523ab5a71916ccf420eebdf5521fcef02141234bbc0b8a49f2fdc4544364ef" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ "pin-project-lite", "tracing-attributes", @@ -569,9 +526,9 @@ dependencies = [ [[package]] name = "tracing-attributes" -version = "0.1.27" +version = "0.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "34704c8d6ebcbc939824180af020566b01a7c01f80641264eba0999f6c2b6be7" +checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" dependencies = [ "proc-macro2", "quote", @@ -580,9 +537,9 @@ dependencies = [ [[package]] name = "tracing-core" -version = "0.1.32" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c06d3da6113f116aaee68e4d601191614c9053067f9ab7f6edbcb161237daa54" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -601,14 +558,14 @@ dependencies = [ [[package]] name = "tracing-subscriber" -version = "0.3.18" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad0f048c97dbd9faa9b7df56362b8ebcaa52adb06b498c050d2f4e32f90a7a8b" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", - "nu-ansi-term 0.46.0", + "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", @@ -645,22 +602,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "winapi" -version = "0.3.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" -dependencies = [ - "winapi-i686-pc-windows-gnu", - "winapi-x86_64-pc-windows-gnu", -] - -[[package]] -name = "winapi-i686-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" - [[package]] name = "winapi-util" version = "0.1.9" @@ -670,12 +611,6 @@ dependencies = [ "windows-sys", ] -[[package]] -name = "winapi-x86_64-pc-windows-gnu" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" - [[package]] name = "windows-sys" version = "0.52.0" From 58abcbc31092d2a57cdbe66ee84ae326182ad8f2 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Wed, 9 Sep 2026 01:42:14 +0000 Subject: [PATCH 0180/1309] Bump tracing-subscriber from 0.3.17 to 0.3.20 Bumps [tracing-subscriber](https://github.com/tokio-rs/tracing) from 0.3.17 to 0.3.20. - [Release notes](https://github.com/tokio-rs/tracing/releases) - [Commits](https://github.com/tokio-rs/tracing/compare/tracing-subscriber-0.3.17...tracing-subscriber-0.3.20) --- updated-dependencies: - dependency-name: tracing-subscriber dependency-version: 0.3.20 dependency-type: direct:production ... Signed-off-by: dependabot[bot] --- Cargo.lock | 74 +++++++++++++++++++++++++++++------------------------- 1 file changed, 40 insertions(+), 34 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 89594ecee1672..9ba1ded57c853 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -11,6 +11,15 @@ dependencies = [ "memchr", ] +[[package]] +name = "aho-corasick" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c982642fa9e8606056828ee9a8505737230110bb1099153c79efe865c59d12ba" +dependencies = [ + "memchr", +] + [[package]] name = "annotate-snippets" version = "0.12.16" @@ -320,7 +329,7 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "10463d9ff00a2a068db14231982f5132edebad0d7660cd956a1c30292dbcbfbd" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "bstr", "fnv", "log", @@ -432,18 +441,15 @@ checksum = "df1d3c3b53da64cf5760482273a98e575c651a67eec7f77df96b5b642de8f039" [[package]] name = "log" -version = "0.4.16" +version = "0.4.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6389c490849ff5bc16be905ae24bc913a9c8892e19b2341dbc175e14c341c2b8" -dependencies = [ - "cfg-if", -] +checksum = "f9f8bd3e56ce4dfc153cf470fffbfa98c7620958b312ca5c3a4b8d5181fd13c6" [[package]] name = "matchers" -version = "0.1.0" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8263075bb86c5a1b1427b5ae862e8889656f126e9f77c484496e8b47cf5c5558" +checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" dependencies = [ "regex-automata", ] @@ -456,12 +462,11 @@ checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" [[package]] name = "nu-ansi-term" -version = "0.46.0" +version = "0.50.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77a8165726e8236064dbb45459242600304b42a5ea24ee2948e18e023bf7ba84" +checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" dependencies = [ - "overload", - "winapi", + "windows-sys", ] [[package]] @@ -482,12 +487,6 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" -[[package]] -name = "overload" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b15813163c1d831bf4a13c3610c05c0d03b39feb07f7e09fa234dac9b15aaf39" - [[package]] name = "pin-project-lite" version = "0.2.9" @@ -535,18 +534,20 @@ version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8b1f693b24f6ac912f4893ef08244d70b6067480d2f1a46e950c9691e6749d1d" dependencies = [ - "aho-corasick", + "aho-corasick 0.7.18", "memchr", - "regex-syntax", + "regex-syntax 0.6.29", ] [[package]] name = "regex-automata" -version = "0.1.10" +version = "0.4.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" +checksum = "ad8553b9b26413251cbf30e620595c7a41b3887f03da04579c0e6b0d6a06b4b2" dependencies = [ - "regex-syntax", + "aho-corasick 1.1.5", + "memchr", + "regex-syntax 0.8.11", ] [[package]] @@ -555,6 +556,12 @@ version = "0.6.29" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1" +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + [[package]] name = "rustfmt-config_proc_macro" version = "0.3.0" @@ -839,20 +846,19 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "tracing" -version = "0.1.37" +version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ce8c33a8d48bd45d624a6e523445fd21ec13d3653cd51f681abf67418f54eb8" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" dependencies = [ - "cfg-if", "pin-project-lite", "tracing-core", ] [[package]] name = "tracing-core" -version = "0.1.31" +version = "0.1.36" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0955b8137a1df6f1a2e9a37d8a6656291ff0297c1a97c24e0d8425fe2312f79a" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" dependencies = [ "once_cell", "valuable", @@ -860,25 +866,25 @@ dependencies = [ [[package]] name = "tracing-log" -version = "0.1.3" +version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" dependencies = [ - "lazy_static", "log", + "once_cell", "tracing-core", ] [[package]] name = "tracing-subscriber" -version = "0.3.17" +version = "0.3.20" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a651bc37f915e81f087d86e62a18eec5f79550c7faff886f7090b4ea757c77" +checksum = "2054a14f5307d601f88daf0553e1cbf472acc4f2c51afab632431cdcd72124d5" dependencies = [ "matchers", "nu-ansi-term", "once_cell", - "regex", + "regex-automata", "sharded-slab", "smallvec", "thread_local", From 0e3523a754567bd52a1df0654d3efc5c594211fd Mon Sep 17 00:00:00 2001 From: devangpratap <115096812+devangpratap@users.noreply.github.com> Date: Tue, 8 Sep 2026 22:41:56 -0400 Subject: [PATCH 0181/1309] test: use the full issue-7056 snippet, with an unformatted source file --- tests/source/issue-7056.rs | 41 ++++++++++++++++++++++++++++++++++++++ tests/target/issue-7056.rs | 40 ++++++++++++++++++++++++++++--------- 2 files changed, 72 insertions(+), 9 deletions(-) create mode 100644 tests/source/issue-7056.rs diff --git a/tests/source/issue-7056.rs b/tests/source/issue-7056.rs new file mode 100644 index 0000000000000..408a0dc3b34b7 --- /dev/null +++ b/tests/source/issue-7056.rs @@ -0,0 +1,41 @@ +// `r#` opens a raw string only when the run of `#`s ends in a `"`. A raw identifier +// such as `r#struct` must stay classified as normal code, or the macro body rewriter +// copies part of it through verbatim and puts the `$` back in the wrong place. + +#![feature(decl_macro)] + +macro_rules! r#struct { + ($r#struct:expr) => { $r#struct } +} + +macro_rules! old_macro { + ($a:expr) => {$a} +} + +macro r#decl_macro($r#fn:expr) { + $r#fn +} + +macro passthrough($id:ident) { + $id +} + +macro_rules! test_pat_match { + (a) => { 6 }; + (r#a) => { 7 }; +} + +pub fn main() { + r#println!("{struct}", r#struct = 1); + assert_eq!(2, r#struct!(2)); + assert_eq!(3, r#old_macro!(3)); + assert_eq!(4, decl_macro!(4)); + + let r#match = 5; + assert_eq!(5, passthrough!(r#match)); + + assert_eq!("r#struct", stringify!(r#struct)); + + assert_eq!(6, test_pat_match!(a)); + assert_eq!(7, test_pat_match!(r#a)); +} diff --git a/tests/target/issue-7056.rs b/tests/target/issue-7056.rs index daa05387921a6..ed85cf6b00539 100644 --- a/tests/target/issue-7056.rs +++ b/tests/target/issue-7056.rs @@ -4,22 +4,44 @@ #![feature(decl_macro)] -macro_rules! r#struct { +macro_rules! r#struct { ($r#struct:expr) => { $r#struct } } -macro r#decl_macro($r#fn:expr) { - $r#fn -} - macro_rules! old_macro { ($a:expr) => { $a }; } -fn raw_ident_next_to_a_raw_string() { - let r#match = r#"still a raw string"#; - let r#fn = r##"hashes too"##; - let _ = (r#match, r#fn); +macro r#decl_macro($r#fn:expr) { + $r#fn +} + +macro passthrough($id:ident) { + $id +} + +macro_rules! test_pat_match { + (a) => { + 6 + }; + (r#a) => { + 7 + }; +} + +pub fn main() { + r#println!("{struct}", r#struct = 1); + assert_eq!(2, r#struct!(2)); + assert_eq!(3, r#old_macro!(3)); + assert_eq!(4, decl_macro!(4)); + + let r#match = 5; + assert_eq!(5, passthrough!(r#match)); + + assert_eq!("r#struct", stringify!(r#struct)); + + assert_eq!(6, test_pat_match!(a)); + assert_eq!(7, test_pat_match!(r#a)); } From 0c4077db7693376f1c6ff85b470b9c7e04ed3d6d Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Tue, 8 Sep 2026 15:19:05 +0100 Subject: [PATCH 0182/1309] Run cargo fmt on JOSH syncs --- library/stdarch/josh-sync.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/stdarch/josh-sync.toml b/library/stdarch/josh-sync.toml index ebdb4576287c8..eeeb82659a0a6 100644 --- a/library/stdarch/josh-sync.toml +++ b/library/stdarch/josh-sync.toml @@ -1,3 +1,7 @@ org = "rust-lang" repo = "stdarch" path = "library/stdarch" + +[[post-pull]] +cmd = ["cargo", "fmt"] +commit-message = "Run `cargo fmt`" From dd13995fa28b60860cfc166de754376fd4d101f0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Sep 2026 16:36:31 +0200 Subject: [PATCH 0183/1309] Revert "Use SIMD intrinsics for vector shifts" This reverts commit 102f03d2c410660a45d0231fdafdd347e0d4e77f. --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 120 ++++++------------ .../crates/core_arch/src/x86/avx512bw.rs | 111 ++++++---------- .../crates/core_arch/src/x86/avx512f.rs | 99 +++++---------- 3 files changed, 114 insertions(+), 216 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index eb636a4fa0397..e3b6054568f11 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -2871,14 +2871,8 @@ pub const fn _mm256_bslli_epi128(a: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsllvd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_sllv_epi32(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u32x4(); - let no_overflow: u32x4 = simd_lt(count, u32x4::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x4::ZERO); - simd_select(no_overflow, simd_shl(a.as_u32x4(), count), u32x4::ZERO).as_m128i() - } +pub fn _mm_sllv_epi32(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(psllvd(a.as_i32x4(), count.as_i32x4())) } } /// Shifts packed 32-bit integers in `a` left by the amount @@ -2890,14 +2884,8 @@ pub const fn _mm_sllv_epi32(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsllvd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_sllv_epi32(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u32x8(); - let no_overflow: u32x8 = simd_lt(count, u32x8::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x8::ZERO); - simd_select(no_overflow, simd_shl(a.as_u32x8(), count), u32x8::ZERO).as_m256i() - } +pub fn _mm256_sllv_epi32(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(psllvd256(a.as_i32x8(), count.as_i32x8())) } } /// Shifts packed 64-bit integers in `a` left by the amount @@ -2909,14 +2897,8 @@ pub const fn _mm256_sllv_epi32(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsllvq))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_sllv_epi64(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u64x2(); - let no_overflow: u64x2 = simd_lt(count, u64x2::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x2::ZERO); - simd_select(no_overflow, simd_shl(a.as_u64x2(), count), u64x2::ZERO).as_m128i() - } +pub fn _mm_sllv_epi64(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(psllvq(a.as_i64x2(), count.as_i64x2())) } } /// Shifts packed 64-bit integers in `a` left by the amount @@ -2928,14 +2910,8 @@ pub const fn _mm_sllv_epi64(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsllvq))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_sllv_epi64(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u64x4(); - let no_overflow: u64x4 = simd_lt(count, u64x4::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x4::ZERO); - simd_select(no_overflow, simd_shl(a.as_u64x4(), count), u64x4::ZERO).as_m256i() - } +pub fn _mm256_sllv_epi64(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(psllvq256(a.as_i64x4(), count.as_i64x4())) } } /// Shifts packed 16-bit integers in `a` right by `count` while @@ -3000,14 +2976,8 @@ pub const fn _mm256_srai_epi32(a: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsravd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srav_epi32(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u32x4(); - let no_overflow: u32x4 = simd_lt(count, u32x4::splat(u32::BITS)); - let count = simd_select(no_overflow, transmute(count), i32x4::splat(31)); - simd_shr(a.as_i32x4(), count).as_m128i() - } +pub fn _mm_srav_epi32(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(psravd(a.as_i32x4(), count.as_i32x4())) } } /// Shifts packed 32-bit integers in `a` right by the amount specified by the @@ -3018,14 +2988,8 @@ pub const fn _mm_srav_epi32(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsravd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srav_epi32(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u32x8(); - let no_overflow: u32x8 = simd_lt(count, u32x8::splat(u32::BITS)); - let count = simd_select(no_overflow, transmute(count), i32x8::splat(31)); - simd_shr(a.as_i32x8(), count).as_m256i() - } +pub fn _mm256_srav_epi32(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(psravd256(a.as_i32x8(), count.as_i32x8())) } } /// Shifts 128-bit lanes in `a` right by `imm8` bytes while shifting in zeros. @@ -3212,14 +3176,8 @@ pub const fn _mm256_srli_epi64(a: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsrlvd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srlv_epi32(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u32x4(); - let no_overflow: u32x4 = simd_lt(count, u32x4::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x4::ZERO); - simd_select(no_overflow, simd_shr(a.as_u32x4(), count), u32x4::ZERO).as_m128i() - } +pub fn _mm_srlv_epi32(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(psrlvd(a.as_i32x4(), count.as_i32x4())) } } /// Shifts packed 32-bit integers in `a` right by the amount specified by @@ -3230,14 +3188,8 @@ pub const fn _mm_srlv_epi32(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsrlvd))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srlv_epi32(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u32x8(); - let no_overflow: u32x8 = simd_lt(count, u32x8::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x8::ZERO); - simd_select(no_overflow, simd_shr(a.as_u32x8(), count), u32x8::ZERO).as_m256i() - } +pub fn _mm256_srlv_epi32(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(psrlvd256(a.as_i32x8(), count.as_i32x8())) } } /// Shifts packed 64-bit integers in `a` right by the amount specified by @@ -3248,14 +3200,8 @@ pub const fn _mm256_srlv_epi32(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsrlvq))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srlv_epi64(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u64x2(); - let no_overflow: u64x2 = simd_lt(count, u64x2::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x2::ZERO); - simd_select(no_overflow, simd_shr(a.as_u64x2(), count), u64x2::ZERO).as_m128i() - } +pub fn _mm_srlv_epi64(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(psrlvq(a.as_i64x2(), count.as_i64x2())) } } /// Shifts packed 64-bit integers in `a` right by the amount specified by @@ -3266,14 +3212,8 @@ pub const fn _mm_srlv_epi64(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx2")] #[cfg_attr(test, assert_instr(vpsrlvq))] #[stable(feature = "simd_x86", since = "1.27.0")] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srlv_epi64(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u64x4(); - let no_overflow: u64x4 = simd_lt(count, u64x4::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x4::ZERO); - simd_select(no_overflow, simd_shr(a.as_u64x4(), count), u64x4::ZERO).as_m256i() - } +pub fn _mm256_srlv_epi64(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(psrlvq256(a.as_i64x4(), count.as_i64x4())) } } /// Load 256-bits of integer data from memory into dst using a non-temporal memory hint. mem_addr @@ -3849,16 +3789,36 @@ unsafe extern "llvm-intrinsic" { fn pslld(a: i32x8, count: i32x4) -> i32x8; #[link_name = "llvm.x86.avx2.psll.q"] fn psllq(a: i64x4, count: i64x2) -> i64x4; + #[link_name = "llvm.x86.avx2.psllv.d"] + fn psllvd(a: i32x4, count: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx2.psllv.d.256"] + fn psllvd256(a: i32x8, count: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx2.psllv.q"] + fn psllvq(a: i64x2, count: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx2.psllv.q.256"] + fn psllvq256(a: i64x4, count: i64x4) -> i64x4; #[link_name = "llvm.x86.avx2.psra.w"] fn psraw(a: i16x16, count: i16x8) -> i16x16; #[link_name = "llvm.x86.avx2.psra.d"] fn psrad(a: i32x8, count: i32x4) -> i32x8; + #[link_name = "llvm.x86.avx2.psrav.d"] + fn psravd(a: i32x4, count: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx2.psrav.d.256"] + fn psravd256(a: i32x8, count: i32x8) -> i32x8; #[link_name = "llvm.x86.avx2.psrl.w"] fn psrlw(a: i16x16, count: i16x8) -> i16x16; #[link_name = "llvm.x86.avx2.psrl.d"] fn psrld(a: i32x8, count: i32x4) -> i32x8; #[link_name = "llvm.x86.avx2.psrl.q"] fn psrlq(a: i64x4, count: i64x2) -> i64x4; + #[link_name = "llvm.x86.avx2.psrlv.d"] + fn psrlvd(a: i32x4, count: i32x4) -> i32x4; + #[link_name = "llvm.x86.avx2.psrlv.d.256"] + fn psrlvd256(a: i32x8, count: i32x8) -> i32x8; + #[link_name = "llvm.x86.avx2.psrlv.q"] + fn psrlvq(a: i64x2, count: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx2.psrlv.q.256"] + fn psrlvq256(a: i64x4, count: i64x4) -> i64x4; #[link_name = "llvm.x86.avx2.pshuf.b"] fn pshufb(a: u8x32, b: u8x32) -> u8x32; #[link_name = "llvm.x86.avx2.permd"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index cda2fad4ef2de..054ca9816379f 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -7370,14 +7370,8 @@ pub const fn _mm_maskz_slli_epi16(k: __mmask8, a: __m128i) -> _ #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_sllv_epi16(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u16x32(); - let no_overflow: u16x32 = simd_lt(count, u16x32::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x32::ZERO); - simd_select(no_overflow, simd_shl(a.as_u16x32(), count), u16x32::ZERO).as_m512i() - } +pub fn _mm512_sllv_epi16(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsllvw(a.as_i16x32(), count.as_i16x32())) } } /// Shift packed 16-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -7422,14 +7416,8 @@ pub const fn _mm512_maskz_sllv_epi16(k: __mmask32, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_sllv_epi16(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u16x16(); - let no_overflow: u16x16 = simd_lt(count, u16x16::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x16::ZERO); - simd_select(no_overflow, simd_shl(a.as_u16x16(), count), u16x16::ZERO).as_m256i() - } +pub fn _mm256_sllv_epi16(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(vpsllvw256(a.as_i16x16(), count.as_i16x16())) } } /// Shift packed 16-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -7474,14 +7462,8 @@ pub const fn _mm256_maskz_sllv_epi16(k: __mmask16, a: __m256i, count: __m256i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_sllv_epi16(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u16x8(); - let no_overflow: u16x8 = simd_lt(count, u16x8::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x8::ZERO); - simd_select(no_overflow, simd_shl(a.as_u16x8(), count), u16x8::ZERO).as_m128i() - } +pub fn _mm_sllv_epi16(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(vpsllvw128(a.as_i16x8(), count.as_i16x8())) } } /// Shift packed 16-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -7759,14 +7741,8 @@ pub const fn _mm_maskz_srli_epi16(k: __mmask8, a: __m128i) -> _ #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srlv_epi16(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u16x32(); - let no_overflow: u16x32 = simd_lt(count, u16x32::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x32::ZERO); - simd_select(no_overflow, simd_shr(a.as_u16x32(), count), u16x32::ZERO).as_m512i() - } +pub fn _mm512_srlv_epi16(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsrlvw(a.as_i16x32(), count.as_i16x32())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -7811,14 +7787,8 @@ pub const fn _mm512_maskz_srlv_epi16(k: __mmask32, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srlv_epi16(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u16x16(); - let no_overflow: u16x16 = simd_lt(count, u16x16::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x16::ZERO); - simd_select(no_overflow, simd_shr(a.as_u16x16(), count), u16x16::ZERO).as_m256i() - } +pub fn _mm256_srlv_epi16(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(vpsrlvw256(a.as_i16x16(), count.as_i16x16())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -7863,14 +7833,8 @@ pub const fn _mm256_maskz_srlv_epi16(k: __mmask16, a: __m256i, count: __m256i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srlv_epi16(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u16x8(); - let no_overflow: u16x8 = simd_lt(count, u16x8::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, count, u16x8::ZERO); - simd_select(no_overflow, simd_shr(a.as_u16x8(), count), u16x8::ZERO).as_m128i() - } +pub fn _mm_srlv_epi16(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(vpsrlvw128(a.as_i16x8(), count.as_i16x8())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -8135,14 +8099,8 @@ pub const fn _mm_maskz_srai_epi16(k: __mmask8, a: __m128i) -> _ #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srav_epi16(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u16x32(); - let no_overflow: u16x32 = simd_lt(count, u16x32::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, transmute(count), i16x32::splat(15)); - simd_shr(a.as_i16x32(), count).as_m512i() - } +pub fn _mm512_srav_epi16(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsravw(a.as_i16x32(), count.as_i16x32())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -8187,14 +8145,8 @@ pub const fn _mm512_maskz_srav_epi16(k: __mmask32, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srav_epi16(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u16x16(); - let no_overflow: u16x16 = simd_lt(count, u16x16::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, transmute(count), i16x16::splat(15)); - simd_shr(a.as_i16x16(), count).as_m256i() - } +pub fn _mm256_srav_epi16(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(vpsravw256(a.as_i16x16(), count.as_i16x16())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -8239,14 +8191,8 @@ pub const fn _mm256_maskz_srav_epi16(k: __mmask16, a: __m256i, count: __m256i) - #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srav_epi16(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u16x8(); - let no_overflow: u16x8 = simd_lt(count, u16x8::splat(u16::BITS as u16)); - let count = simd_select(no_overflow, transmute(count), i16x8::splat(15)); - simd_shr(a.as_i16x8(), count).as_m128i() - } +pub fn _mm_srav_epi16(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(vpsravw128(a.as_i16x8(), count.as_i16x8())) } } /// Shift packed 16-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -12618,12 +12564,33 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.x86.avx512.psll.w.512"] fn vpsllw(a: i16x32, count: i16x8) -> i16x32; + #[link_name = "llvm.x86.avx512.psllv.w.512"] + fn vpsllvw(a: i16x32, b: i16x32) -> i16x32; + #[link_name = "llvm.x86.avx512.psllv.w.256"] + fn vpsllvw256(a: i16x16, b: i16x16) -> i16x16; + #[link_name = "llvm.x86.avx512.psllv.w.128"] + fn vpsllvw128(a: i16x8, b: i16x8) -> i16x8; + #[link_name = "llvm.x86.avx512.psrl.w.512"] fn vpsrlw(a: i16x32, count: i16x8) -> i16x32; + #[link_name = "llvm.x86.avx512.psrlv.w.512"] + fn vpsrlvw(a: i16x32, b: i16x32) -> i16x32; + #[link_name = "llvm.x86.avx512.psrlv.w.256"] + fn vpsrlvw256(a: i16x16, b: i16x16) -> i16x16; + #[link_name = "llvm.x86.avx512.psrlv.w.128"] + fn vpsrlvw128(a: i16x8, b: i16x8) -> i16x8; + #[link_name = "llvm.x86.avx512.psra.w.512"] fn vpsraw(a: i16x32, count: i16x8) -> i16x32; + #[link_name = "llvm.x86.avx512.psrav.w.512"] + fn vpsravw(a: i16x32, count: i16x32) -> i16x32; + #[link_name = "llvm.x86.avx512.psrav.w.256"] + fn vpsravw256(a: i16x16, count: i16x16) -> i16x16; + #[link_name = "llvm.x86.avx512.psrav.w.128"] + fn vpsravw128(a: i16x8, count: i16x8) -> i16x8; + #[link_name = "llvm.x86.avx512.vpermi2var.hi.512"] fn vpermi2w(a: i16x32, idx: i16x32, b: i16x32) -> i16x32; #[link_name = "llvm.x86.avx512.vpermi2var.hi.256"] diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index f0103df1be79e..2b833e247b1bc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -21648,14 +21648,8 @@ pub const fn _mm_maskz_srai_epi64(k: __mmask8, a: __m128i) -> _ #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srav_epi32(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u32x16(); - let no_overflow: u32x16 = simd_lt(count, u32x16::splat(u32::BITS)); - let count = simd_select(no_overflow, transmute(count), i32x16::splat(31)); - simd_shr(a.as_i32x16(), count).as_m512i() - } +pub fn _mm512_srav_epi32(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsravd(a.as_i32x16(), count.as_i32x16())) } } /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -21765,14 +21759,8 @@ pub const fn _mm_maskz_srav_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __ #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u64x8(); - let no_overflow: u64x8 = simd_lt(count, u64x8::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, transmute(count), i64x8::splat(63)); - simd_shr(a.as_i64x8(), count).as_m512i() - } +pub fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsravq(a.as_i64x8(), count.as_i64x8())) } } /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -21817,14 +21805,8 @@ pub const fn _mm512_maskz_srav_epi64(k: __mmask8, a: __m512i, count: __m512i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_srav_epi64(a: __m256i, count: __m256i) -> __m256i { - unsafe { - let count = count.as_u64x4(); - let no_overflow: u64x4 = simd_lt(count, u64x4::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, transmute(count), i64x4::splat(63)); - simd_shr(a.as_i64x4(), count).as_m256i() - } +pub fn _mm256_srav_epi64(a: __m256i, count: __m256i) -> __m256i { + unsafe { transmute(vpsravq256(a.as_i64x4(), count.as_i64x4())) } } /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -21869,14 +21851,8 @@ pub const fn _mm256_maskz_srav_epi64(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_srav_epi64(a: __m128i, count: __m128i) -> __m128i { - unsafe { - let count = count.as_u64x2(); - let no_overflow: u64x2 = simd_lt(count, u64x2::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, transmute(count), i64x2::splat(63)); - simd_shr(a.as_i64x2(), count).as_m128i() - } +pub fn _mm_srav_epi64(a: __m128i, count: __m128i) -> __m128i { + unsafe { transmute(vpsravq128(a.as_i64x2(), count.as_i64x2())) } } /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in sign bits, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -22492,14 +22468,8 @@ pub const fn _mm_maskz_rorv_epi64(k: __mmask8, a: __m128i, b: __m128i) -> __m128 #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_sllv_epi32(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u32x16(); - let no_overflow: u32x16 = simd_lt(count, u32x16::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x16::ZERO); - simd_select(no_overflow, simd_shl(a.as_u32x16(), count), u32x16::ZERO).as_m512i() - } +pub fn _mm512_sllv_epi32(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsllvd(a.as_i32x16(), count.as_i32x16())) } } /// Shift packed 32-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -22609,14 +22579,8 @@ pub const fn _mm_maskz_sllv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __ #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srlv_epi32(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u32x16(); - let no_overflow: u32x16 = simd_lt(count, u32x16::splat(u32::BITS)); - let count = simd_select(no_overflow, count, u32x16::ZERO); - simd_select(no_overflow, simd_shr(a.as_u32x16(), count), u32x16::ZERO).as_m512i() - } +pub fn _mm512_srlv_epi32(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsrlvd(a.as_i32x16(), count.as_i32x16())) } } /// Shift packed 32-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -22726,14 +22690,8 @@ pub const fn _mm_maskz_srlv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __ #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_sllv_epi64(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u64x8(); - let no_overflow: u64x8 = simd_lt(count, u64x8::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x8::ZERO); - simd_select(no_overflow, simd_shl(a.as_u64x8(), count), u64x8::ZERO).as_m512i() - } +pub fn _mm512_sllv_epi64(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsllvq(a.as_i64x8(), count.as_i64x8())) } } /// Shift packed 64-bit integers in a left by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -22843,14 +22801,8 @@ pub const fn _mm_maskz_sllv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __ #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_srlv_epi64(a: __m512i, count: __m512i) -> __m512i { - unsafe { - let count = count.as_u64x8(); - let no_overflow: u64x8 = simd_lt(count, u64x8::splat(u64::BITS as u64)); - let count = simd_select(no_overflow, count, u64x8::ZERO); - simd_select(no_overflow, simd_shr(a.as_u64x8(), count), u64x8::ZERO).as_m512i() - } +pub fn _mm512_srlv_epi64(a: __m512i, count: __m512i) -> __m512i { + unsafe { transmute(vpsrlvq(a.as_i64x8(), count.as_i64x8())) } } /// Shift packed 64-bit integers in a right by the amount specified by the corresponding element in count while shifting in zeros, and store the results in dst using writemask k (elements are copied from src when the corresponding mask bit is not set). @@ -44884,6 +44836,15 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.x86.avx512.mask.cmp.pd.128"] fn vcmppd128(a: f64x2, b: f64x2, op: i32, m: i8) -> i8; + #[link_name = "llvm.x86.avx512.psllv.d.512"] + fn vpsllvd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.psrlv.d.512"] + fn vpsrlvd(a: i32x16, b: i32x16) -> i32x16; + #[link_name = "llvm.x86.avx512.psllv.q.512"] + fn vpsllvq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.psrlv.q.512"] + fn vpsrlvq(a: i64x8, b: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.psll.d.512"] fn vpslld(a: i32x16, count: i32x4) -> i32x16; #[link_name = "llvm.x86.avx512.psrl.d.512"] @@ -44903,6 +44864,16 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.x86.avx512.psra.q.128"] fn vpsraq128(a: i64x2, count: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx512.psrav.d.512"] + fn vpsravd(a: i32x16, count: i32x16) -> i32x16; + + #[link_name = "llvm.x86.avx512.psrav.q.512"] + fn vpsravq(a: i64x8, count: i64x8) -> i64x8; + #[link_name = "llvm.x86.avx512.psrav.q.256"] + fn vpsravq256(a: i64x4, count: i64x4) -> i64x4; + #[link_name = "llvm.x86.avx512.psrav.q.128"] + fn vpsravq128(a: i64x2, count: i64x2) -> i64x2; + #[link_name = "llvm.x86.avx512.vpermilvar.ps.512"] fn vpermilps(a: f32x16, b: i32x16) -> f32x16; #[link_name = "llvm.x86.avx512.vpermilvar.pd.512"] From 39333b94ddfb4457bc8a6dba64a9f542830e7ae0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Sep 2026 16:37:30 +0200 Subject: [PATCH 0184/1309] de-constify methods that depended on the vector shift ones --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 20 +-- .../crates/core_arch/src/x86/avx512bw.rs | 108 ++++++------- .../crates/core_arch/src/x86/avx512f.rs | 150 +++++++----------- .../crates/core_arch/src/x86_64/avx512f.rs | 46 +++--- 4 files changed, 135 insertions(+), 189 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index e3b6054568f11..333f38e5474cc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -5123,7 +5123,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm_sllv_epi32() { + fn test_mm_sllv_epi32() { let a = _mm_set1_epi32(2); let b = _mm_set1_epi32(1); let r = _mm_sllv_epi32(a, b); @@ -5132,7 +5132,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_sllv_epi32() { + fn test_mm256_sllv_epi32() { let a = _mm256_set1_epi32(2); let b = _mm256_set1_epi32(1); let r = _mm256_sllv_epi32(a, b); @@ -5141,7 +5141,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm_sllv_epi64() { + fn test_mm_sllv_epi64() { let a = _mm_set1_epi64x(2); let b = _mm_set1_epi64x(1); let r = _mm_sllv_epi64(a, b); @@ -5150,7 +5150,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_sllv_epi64() { + fn test_mm256_sllv_epi64() { let a = _mm256_set1_epi64x(2); let b = _mm256_set1_epi64x(1); let r = _mm256_sllv_epi64(a, b); @@ -5191,7 +5191,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm_srav_epi32() { + fn test_mm_srav_epi32() { let a = _mm_set1_epi32(4); let count = _mm_set1_epi32(1); let r = _mm_srav_epi32(a, count); @@ -5200,7 +5200,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_srav_epi32() { + fn test_mm256_srav_epi32() { let a = _mm256_set1_epi32(4); let count = _mm256_set1_epi32(1); let r = _mm256_srav_epi32(a, count); @@ -5277,7 +5277,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm_srlv_epi32() { + fn test_mm_srlv_epi32() { let a = _mm_set1_epi32(2); let count = _mm_set1_epi32(1); let r = _mm_srlv_epi32(a, count); @@ -5286,7 +5286,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_srlv_epi32() { + fn test_mm256_srlv_epi32() { let a = _mm256_set1_epi32(2); let count = _mm256_set1_epi32(1); let r = _mm256_srlv_epi32(a, count); @@ -5295,7 +5295,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm_srlv_epi64() { + fn test_mm_srlv_epi64() { let a = _mm_set1_epi64x(2); let count = _mm_set1_epi64x(1); let r = _mm_srlv_epi64(a, count); @@ -5304,7 +5304,7 @@ mod tests { } #[simd_test(enable = "avx2")] - const fn test_mm256_srlv_epi64() { + fn test_mm256_srlv_epi64() { let a = _mm256_set1_epi64x(2); let count = _mm256_set1_epi64x(1); let r = _mm256_srlv_epi64(a, count); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 054ca9816379f..8e642432151ea 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -7381,8 +7381,7 @@ pub fn _mm512_sllv_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_sllv_epi16( +pub fn _mm512_mask_sllv_epi16( src: __m512i, k: __mmask32, a: __m512i, @@ -7401,8 +7400,7 @@ pub const fn _mm512_mask_sllv_epi16( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_sllv_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_sllv_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, i16x32::ZERO)) @@ -7427,8 +7425,7 @@ pub fn _mm256_sllv_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_sllv_epi16( +pub fn _mm256_mask_sllv_epi16( src: __m256i, k: __mmask16, a: __m256i, @@ -7447,8 +7444,7 @@ pub const fn _mm256_mask_sllv_epi16( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_sllv_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_sllv_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, i16x16::ZERO)) @@ -7473,8 +7469,7 @@ pub fn _mm_sllv_epi16(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_sllv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_sllv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, src.as_i16x8())) @@ -7488,8 +7483,7 @@ pub const fn _mm_mask_sllv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_sllv_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_sllv_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, i16x8::ZERO)) @@ -7752,8 +7746,7 @@ pub fn _mm512_srlv_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srlv_epi16( +pub fn _mm512_mask_srlv_epi16( src: __m512i, k: __mmask32, a: __m512i, @@ -7772,8 +7765,7 @@ pub const fn _mm512_mask_srlv_epi16( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srlv_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srlv_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, i16x32::ZERO)) @@ -7798,8 +7790,7 @@ pub fn _mm256_srlv_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srlv_epi16( +pub fn _mm256_mask_srlv_epi16( src: __m256i, k: __mmask16, a: __m256i, @@ -7818,8 +7809,7 @@ pub const fn _mm256_mask_srlv_epi16( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srlv_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srlv_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, i16x16::ZERO)) @@ -7844,8 +7834,7 @@ pub fn _mm_srlv_epi16(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srlv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srlv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, src.as_i16x8())) @@ -7859,8 +7848,7 @@ pub const fn _mm_mask_srlv_epi16(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srlv_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srlv_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, i16x8::ZERO)) @@ -8110,8 +8098,7 @@ pub fn _mm512_srav_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srav_epi16( +pub fn _mm512_mask_srav_epi16( src: __m512i, k: __mmask32, a: __m512i, @@ -8130,8 +8117,7 @@ pub const fn _mm512_mask_srav_epi16( #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srav_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srav_epi16(k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, i16x32::ZERO)) @@ -8156,8 +8142,7 @@ pub fn _mm256_srav_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srav_epi16( +pub fn _mm256_mask_srav_epi16( src: __m256i, k: __mmask16, a: __m256i, @@ -8176,8 +8161,7 @@ pub const fn _mm256_mask_srav_epi16( #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srav_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srav_epi16(k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, i16x16::ZERO)) @@ -8202,8 +8186,7 @@ pub fn _mm_srav_epi16(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srav_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srav_epi16(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, src.as_i16x8())) @@ -8217,8 +8200,7 @@ pub const fn _mm_mask_srav_epi16(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srav_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srav_epi16(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi16(a, count).as_i16x8(); transmute(simd_select_bitmask(k, shf, i16x8::ZERO)) @@ -18353,7 +18335,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_sllv_epi16() { + fn test_mm512_sllv_epi16() { let a = _mm512_set1_epi16(1 << 15); let count = _mm512_set1_epi16(2); let r = _mm512_sllv_epi16(a, count); @@ -18362,7 +18344,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_sllv_epi16() { + fn test_mm512_mask_sllv_epi16() { let a = _mm512_set1_epi16(1 << 15); let count = _mm512_set1_epi16(2); let r = _mm512_mask_sllv_epi16(a, 0, a, count); @@ -18373,7 +18355,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_sllv_epi16() { + fn test_mm512_maskz_sllv_epi16() { let a = _mm512_set1_epi16(1 << 15); let count = _mm512_set1_epi16(2); let r = _mm512_maskz_sllv_epi16(0, a, count); @@ -18384,7 +18366,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_sllv_epi16() { + fn test_mm256_sllv_epi16() { let a = _mm256_set1_epi16(1 << 15); let count = _mm256_set1_epi16(2); let r = _mm256_sllv_epi16(a, count); @@ -18393,7 +18375,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_sllv_epi16() { + fn test_mm256_mask_sllv_epi16() { let a = _mm256_set1_epi16(1 << 15); let count = _mm256_set1_epi16(2); let r = _mm256_mask_sllv_epi16(a, 0, a, count); @@ -18404,7 +18386,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_sllv_epi16() { + fn test_mm256_maskz_sllv_epi16() { let a = _mm256_set1_epi16(1 << 15); let count = _mm256_set1_epi16(2); let r = _mm256_maskz_sllv_epi16(0, a, count); @@ -18415,7 +18397,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_sllv_epi16() { + fn test_mm_sllv_epi16() { let a = _mm_set1_epi16(1 << 15); let count = _mm_set1_epi16(2); let r = _mm_sllv_epi16(a, count); @@ -18424,7 +18406,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_sllv_epi16() { + fn test_mm_mask_sllv_epi16() { let a = _mm_set1_epi16(1 << 15); let count = _mm_set1_epi16(2); let r = _mm_mask_sllv_epi16(a, 0, a, count); @@ -18435,7 +18417,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_sllv_epi16() { + fn test_mm_maskz_sllv_epi16() { let a = _mm_set1_epi16(1 << 15); let count = _mm_set1_epi16(2); let r = _mm_maskz_sllv_epi16(0, a, count); @@ -18589,7 +18571,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_srlv_epi16() { + fn test_mm512_srlv_epi16() { let a = _mm512_set1_epi16(1 << 1); let count = _mm512_set1_epi16(2); let r = _mm512_srlv_epi16(a, count); @@ -18598,7 +18580,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_srlv_epi16() { + fn test_mm512_mask_srlv_epi16() { let a = _mm512_set1_epi16(1 << 1); let count = _mm512_set1_epi16(2); let r = _mm512_mask_srlv_epi16(a, 0, a, count); @@ -18609,7 +18591,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_srlv_epi16() { + fn test_mm512_maskz_srlv_epi16() { let a = _mm512_set1_epi16(1 << 1); let count = _mm512_set1_epi16(2); let r = _mm512_maskz_srlv_epi16(0, a, count); @@ -18620,7 +18602,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_srlv_epi16() { + fn test_mm256_srlv_epi16() { let a = _mm256_set1_epi16(1 << 1); let count = _mm256_set1_epi16(2); let r = _mm256_srlv_epi16(a, count); @@ -18629,7 +18611,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_srlv_epi16() { + fn test_mm256_mask_srlv_epi16() { let a = _mm256_set1_epi16(1 << 1); let count = _mm256_set1_epi16(2); let r = _mm256_mask_srlv_epi16(a, 0, a, count); @@ -18640,7 +18622,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_srlv_epi16() { + fn test_mm256_maskz_srlv_epi16() { let a = _mm256_set1_epi16(1 << 1); let count = _mm256_set1_epi16(2); let r = _mm256_maskz_srlv_epi16(0, a, count); @@ -18651,7 +18633,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_srlv_epi16() { + fn test_mm_srlv_epi16() { let a = _mm_set1_epi16(1 << 1); let count = _mm_set1_epi16(2); let r = _mm_srlv_epi16(a, count); @@ -18660,7 +18642,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_srlv_epi16() { + fn test_mm_mask_srlv_epi16() { let a = _mm_set1_epi16(1 << 1); let count = _mm_set1_epi16(2); let r = _mm_mask_srlv_epi16(a, 0, a, count); @@ -18671,7 +18653,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_srlv_epi16() { + fn test_mm_maskz_srlv_epi16() { let a = _mm_set1_epi16(1 << 1); let count = _mm_set1_epi16(2); let r = _mm_maskz_srlv_epi16(0, a, count); @@ -18825,7 +18807,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_srav_epi16() { + fn test_mm512_srav_epi16() { let a = _mm512_set1_epi16(8); let count = _mm512_set1_epi16(2); let r = _mm512_srav_epi16(a, count); @@ -18834,7 +18816,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_mask_srav_epi16() { + fn test_mm512_mask_srav_epi16() { let a = _mm512_set1_epi16(8); let count = _mm512_set1_epi16(2); let r = _mm512_mask_srav_epi16(a, 0, a, count); @@ -18845,7 +18827,7 @@ mod tests { } #[simd_test(enable = "avx512bw")] - const fn test_mm512_maskz_srav_epi16() { + fn test_mm512_maskz_srav_epi16() { let a = _mm512_set1_epi16(8); let count = _mm512_set1_epi16(2); let r = _mm512_maskz_srav_epi16(0, a, count); @@ -18856,7 +18838,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_srav_epi16() { + fn test_mm256_srav_epi16() { let a = _mm256_set1_epi16(8); let count = _mm256_set1_epi16(2); let r = _mm256_srav_epi16(a, count); @@ -18865,7 +18847,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_mask_srav_epi16() { + fn test_mm256_mask_srav_epi16() { let a = _mm256_set1_epi16(8); let count = _mm256_set1_epi16(2); let r = _mm256_mask_srav_epi16(a, 0, a, count); @@ -18876,7 +18858,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm256_maskz_srav_epi16() { + fn test_mm256_maskz_srav_epi16() { let a = _mm256_set1_epi16(8); let count = _mm256_set1_epi16(2); let r = _mm256_maskz_srav_epi16(0, a, count); @@ -18887,7 +18869,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_srav_epi16() { + fn test_mm_srav_epi16() { let a = _mm_set1_epi16(8); let count = _mm_set1_epi16(2); let r = _mm_srav_epi16(a, count); @@ -18896,7 +18878,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_mask_srav_epi16() { + fn test_mm_mask_srav_epi16() { let a = _mm_set1_epi16(8); let count = _mm_set1_epi16(2); let r = _mm_mask_srav_epi16(a, 0, a, count); @@ -18907,7 +18889,7 @@ mod tests { } #[simd_test(enable = "avx512bw,avx512vl")] - const fn test_mm_maskz_srav_epi16() { + fn test_mm_maskz_srav_epi16() { let a = _mm_set1_epi16(8); let count = _mm_set1_epi16(2); let r = _mm_maskz_srav_epi16(0, a, count); diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 2b833e247b1bc..27c80312d6ac6 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -21659,8 +21659,7 @@ pub fn _mm512_srav_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srav_epi32( +pub fn _mm512_mask_srav_epi32( src: __m512i, k: __mmask16, a: __m512i, @@ -21679,8 +21678,7 @@ pub const fn _mm512_mask_srav_epi32( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srav_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srav_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, i32x16::ZERO)) @@ -21694,8 +21692,7 @@ pub const fn _mm512_maskz_srav_epi32(k: __mmask16, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srav_epi32( +pub fn _mm256_mask_srav_epi32( src: __m256i, k: __mmask8, a: __m256i, @@ -21714,8 +21711,7 @@ pub const fn _mm256_mask_srav_epi32( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srav_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srav_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, i32x8::ZERO)) @@ -21729,8 +21725,7 @@ pub const fn _mm256_maskz_srav_epi32(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srav_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srav_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, src.as_i32x4())) @@ -21744,8 +21739,7 @@ pub const fn _mm_mask_srav_epi32(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srav_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srav_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, i32x4::ZERO)) @@ -21770,8 +21764,7 @@ pub fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srav_epi64( +pub fn _mm512_mask_srav_epi64( src: __m512i, k: __mmask8, a: __m512i, @@ -21790,8 +21783,7 @@ pub const fn _mm512_mask_srav_epi64( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srav_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srav_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, i64x8::ZERO)) @@ -21816,8 +21808,7 @@ pub fn _mm256_srav_epi64(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srav_epi64( +pub fn _mm256_mask_srav_epi64( src: __m256i, k: __mmask8, a: __m256i, @@ -21836,8 +21827,7 @@ pub const fn _mm256_mask_srav_epi64( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srav_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srav_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, i64x4::ZERO)) @@ -21862,8 +21852,7 @@ pub fn _mm_srav_epi64(a: __m128i, count: __m128i) -> __m128i { #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srav_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srav_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, src.as_i64x2())) @@ -21877,8 +21866,7 @@ pub const fn _mm_mask_srav_epi64(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srav_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srav_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srav_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, i64x2::ZERO)) @@ -22479,8 +22467,7 @@ pub fn _mm512_sllv_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_sllv_epi32( +pub fn _mm512_mask_sllv_epi32( src: __m512i, k: __mmask16, a: __m512i, @@ -22499,8 +22486,7 @@ pub const fn _mm512_mask_sllv_epi32( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_sllv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_sllv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, i32x16::ZERO)) @@ -22514,8 +22500,7 @@ pub const fn _mm512_maskz_sllv_epi32(k: __mmask16, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_sllv_epi32( +pub fn _mm256_mask_sllv_epi32( src: __m256i, k: __mmask8, a: __m256i, @@ -22534,8 +22519,7 @@ pub const fn _mm256_mask_sllv_epi32( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_sllv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_sllv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, i32x8::ZERO)) @@ -22549,8 +22533,7 @@ pub const fn _mm256_maskz_sllv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_sllv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_sllv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, src.as_i32x4())) @@ -22564,8 +22547,7 @@ pub const fn _mm_mask_sllv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_sllv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_sllv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, i32x4::ZERO)) @@ -22590,8 +22572,7 @@ pub fn _mm512_srlv_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srlv_epi32( +pub fn _mm512_mask_srlv_epi32( src: __m512i, k: __mmask16, a: __m512i, @@ -22610,8 +22591,7 @@ pub const fn _mm512_mask_srlv_epi32( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srlv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srlv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, i32x16::ZERO)) @@ -22625,8 +22605,7 @@ pub const fn _mm512_maskz_srlv_epi32(k: __mmask16, a: __m512i, count: __m512i) - #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srlv_epi32( +pub fn _mm256_mask_srlv_epi32( src: __m256i, k: __mmask8, a: __m256i, @@ -22645,8 +22624,7 @@ pub const fn _mm256_mask_srlv_epi32( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srlv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srlv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, i32x8::ZERO)) @@ -22660,8 +22638,7 @@ pub const fn _mm256_maskz_srlv_epi32(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srlv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srlv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, src.as_i32x4())) @@ -22675,8 +22652,7 @@ pub const fn _mm_mask_srlv_epi32(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srlv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srlv_epi32(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi32(a, count).as_i32x4(); transmute(simd_select_bitmask(k, shf, i32x4::ZERO)) @@ -22701,8 +22677,7 @@ pub fn _mm512_sllv_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_sllv_epi64( +pub fn _mm512_mask_sllv_epi64( src: __m512i, k: __mmask8, a: __m512i, @@ -22721,8 +22696,7 @@ pub const fn _mm512_mask_sllv_epi64( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_sllv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_sllv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, i64x8::ZERO)) @@ -22736,8 +22710,7 @@ pub const fn _mm512_maskz_sllv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_sllv_epi64( +pub fn _mm256_mask_sllv_epi64( src: __m256i, k: __mmask8, a: __m256i, @@ -22756,8 +22729,7 @@ pub const fn _mm256_mask_sllv_epi64( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_sllv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_sllv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, i64x4::ZERO)) @@ -22771,8 +22743,7 @@ pub const fn _mm256_maskz_sllv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_sllv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_sllv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, src.as_i64x2())) @@ -22786,8 +22757,7 @@ pub const fn _mm_mask_sllv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_sllv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_sllv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_sllv_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, i64x2::ZERO)) @@ -22812,8 +22782,7 @@ pub fn _mm512_srlv_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_mask_srlv_epi64( +pub fn _mm512_mask_srlv_epi64( src: __m512i, k: __mmask8, a: __m512i, @@ -22832,8 +22801,7 @@ pub const fn _mm512_mask_srlv_epi64( #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm512_maskz_srlv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { +pub fn _mm512_maskz_srlv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, i64x8::ZERO)) @@ -22847,8 +22815,7 @@ pub const fn _mm512_maskz_srlv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_mask_srlv_epi64( +pub fn _mm256_mask_srlv_epi64( src: __m256i, k: __mmask8, a: __m256i, @@ -22867,8 +22834,7 @@ pub const fn _mm256_mask_srlv_epi64( #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm256_maskz_srlv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { +pub fn _mm256_maskz_srlv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, i64x4::ZERO)) @@ -22882,8 +22848,7 @@ pub const fn _mm256_maskz_srlv_epi64(k: __mmask8, a: __m256i, count: __m256i) -> #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_mask_srlv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_mask_srlv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, src.as_i64x2())) @@ -22897,8 +22862,7 @@ pub const fn _mm_mask_srlv_epi64(src: __m128i, k: __mmask8, a: __m128i, count: _ #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -#[rustc_const_unstable(feature = "stdarch_const_x86", issue = "149298")] -pub const fn _mm_maskz_srlv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { +pub fn _mm_maskz_srlv_epi64(k: __mmask8, a: __m128i, count: __m128i) -> __m128i { unsafe { let shf = _mm_srlv_epi64(a, count).as_i64x2(); transmute(simd_select_bitmask(k, shf, i64x2::ZERO)) @@ -54639,7 +54603,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_sllv_epi32() { + fn test_mm512_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let count = _mm512_set1_epi32(1); let r = _mm512_sllv_epi32(a, count); @@ -54648,7 +54612,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_sllv_epi32() { + fn test_mm512_mask_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let count = _mm512_set1_epi32(1); let r = _mm512_mask_sllv_epi32(a, 0, a, count); @@ -54659,7 +54623,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_sllv_epi32() { + fn test_mm512_maskz_sllv_epi32() { let a = _mm512_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 << 31); let count = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let r = _mm512_maskz_sllv_epi32(0, a, count); @@ -54670,7 +54634,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_sllv_epi32() { + fn test_mm256_mask_sllv_epi32() { let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); let count = _mm256_set1_epi32(1); let r = _mm256_mask_sllv_epi32(a, 0, a, count); @@ -54681,7 +54645,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_sllv_epi32() { + fn test_mm256_maskz_sllv_epi32() { let a = _mm256_set_epi32(1 << 31, 1, 1, 1, 1, 1, 1, 1); let count = _mm256_set1_epi32(1); let r = _mm256_maskz_sllv_epi32(0, a, count); @@ -54692,7 +54656,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_sllv_epi32() { + fn test_mm_mask_sllv_epi32() { let a = _mm_set_epi32(1 << 31, 1, 1, 1); let count = _mm_set1_epi32(1); let r = _mm_mask_sllv_epi32(a, 0, a, count); @@ -54703,7 +54667,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_sllv_epi32() { + fn test_mm_maskz_sllv_epi32() { let a = _mm_set_epi32(1 << 31, 1, 1, 1); let count = _mm_set1_epi32(1); let r = _mm_maskz_sllv_epi32(0, a, count); @@ -54714,7 +54678,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_srlv_epi32() { + fn test_mm512_srlv_epi32() { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); let count = _mm512_set1_epi32(1); let r = _mm512_srlv_epi32(a, count); @@ -54723,7 +54687,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_srlv_epi32() { + fn test_mm512_mask_srlv_epi32() { let a = _mm512_set_epi32(0, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2); let count = _mm512_set1_epi32(1); let r = _mm512_mask_srlv_epi32(a, 0, a, count); @@ -54734,7 +54698,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_srlv_epi32() { + fn test_mm512_maskz_srlv_epi32() { let a = _mm512_set_epi32(2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 0); let count = _mm512_set_epi32(0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1); let r = _mm512_maskz_srlv_epi32(0, a, count); @@ -54745,7 +54709,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_srlv_epi32() { + fn test_mm256_mask_srlv_epi32() { let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); let count = _mm256_set1_epi32(1); let r = _mm256_mask_srlv_epi32(a, 0, a, count); @@ -54756,7 +54720,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_srlv_epi32() { + fn test_mm256_maskz_srlv_epi32() { let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); let count = _mm256_set1_epi32(1); let r = _mm256_maskz_srlv_epi32(0, a, count); @@ -54767,7 +54731,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_srlv_epi32() { + fn test_mm_mask_srlv_epi32() { let a = _mm_set_epi32(1 << 5, 0, 0, 0); let count = _mm_set1_epi32(1); let r = _mm_mask_srlv_epi32(a, 0, a, count); @@ -54778,7 +54742,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_srlv_epi32() { + fn test_mm_maskz_srlv_epi32() { let a = _mm_set_epi32(1 << 5, 0, 0, 0); let count = _mm_set1_epi32(1); let r = _mm_maskz_srlv_epi32(0, a, count); @@ -55062,7 +55026,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_srav_epi32() { + fn test_mm512_srav_epi32() { let a = _mm512_set_epi32(8, -8, 16, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); let count = _mm512_set_epi32(2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0); let r = _mm512_srav_epi32(a, count); @@ -55071,7 +55035,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_srav_epi32() { + fn test_mm512_mask_srav_epi32() { let a = _mm512_set_epi32(8, -8, 16, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 16); let count = _mm512_set_epi32(2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1); let r = _mm512_mask_srav_epi32(a, 0, a, count); @@ -55082,7 +55046,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_srav_epi32() { + fn test_mm512_maskz_srav_epi32() { let a = _mm512_set_epi32(8, -8, 16, -15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, -15, -14); let count = _mm512_set_epi32(2, 2, 2, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 2); let r = _mm512_maskz_srav_epi32(0, a, count); @@ -55093,7 +55057,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_srav_epi32() { + fn test_mm256_mask_srav_epi32() { let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); let count = _mm256_set1_epi32(1); let r = _mm256_mask_srav_epi32(a, 0, a, count); @@ -55104,7 +55068,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_srav_epi32() { + fn test_mm256_maskz_srav_epi32() { let a = _mm256_set_epi32(1 << 5, 0, 0, 0, 0, 0, 0, 0); let count = _mm256_set1_epi32(1); let r = _mm256_maskz_srav_epi32(0, a, count); @@ -55115,7 +55079,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_srav_epi32() { + fn test_mm_mask_srav_epi32() { let a = _mm_set_epi32(1 << 5, 0, 0, 0); let count = _mm_set1_epi32(1); let r = _mm_mask_srav_epi32(a, 0, a, count); @@ -55126,7 +55090,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_srav_epi32() { + fn test_mm_maskz_srav_epi32() { let a = _mm_set_epi32(1 << 5, 0, 0, 0); let count = _mm_set1_epi32(1); let r = _mm_maskz_srav_epi32(0, a, count); diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index 28e68d798b1c5..e45a79718209e 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -9035,7 +9035,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_sllv_epi64() { + fn test_mm512_sllv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 63, 1 << 32, 1 << 32, @@ -9052,7 +9052,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_sllv_epi64() { + fn test_mm512_mask_sllv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 32, 1 << 63, 1 << 32, @@ -9071,7 +9071,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_sllv_epi64() { + fn test_mm512_maskz_sllv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 32, 1 << 32, 1 << 32, @@ -9086,7 +9086,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_sllv_epi64() { + fn test_mm256_mask_sllv_epi64() { let a = _mm256_set_epi64x(1 << 32, 1 << 32, 1 << 63, 1 << 32); let count = _mm256_set_epi64x(0, 1, 2, 3); let r = _mm256_mask_sllv_epi64(a, 0, a, count); @@ -9097,7 +9097,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_sllv_epi64() { + fn test_mm256_maskz_sllv_epi64() { let a = _mm256_set_epi64x(1 << 32, 1 << 32, 1 << 63, 1 << 32); let count = _mm256_set_epi64x(0, 1, 2, 3); let r = _mm256_maskz_sllv_epi64(0, a, count); @@ -9108,7 +9108,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_sllv_epi64() { + fn test_mm_mask_sllv_epi64() { let a = _mm_set_epi64x(1 << 63, 1 << 32); let count = _mm_set_epi64x(2, 3); let r = _mm_mask_sllv_epi64(a, 0, a, count); @@ -9119,7 +9119,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_sllv_epi64() { + fn test_mm_maskz_sllv_epi64() { let a = _mm_set_epi64x(1 << 63, 1 << 32); let count = _mm_set_epi64x(2, 3); let r = _mm_maskz_sllv_epi64(0, a, count); @@ -9130,7 +9130,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_srlv_epi64() { + fn test_mm512_srlv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 0, 1 << 32, 1 << 32, @@ -9147,7 +9147,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_srlv_epi64() { + fn test_mm512_mask_srlv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 0, 1 << 32, 1 << 32, @@ -9166,7 +9166,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_srlv_epi64() { + fn test_mm512_maskz_srlv_epi64() { #[rustfmt::skip] let a = _mm512_set_epi64( 1 << 32, 1 << 32, 1 << 32, 1 << 32, @@ -9181,7 +9181,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_srlv_epi64() { + fn test_mm256_mask_srlv_epi64() { let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); let count = _mm256_set1_epi64x(1); let r = _mm256_mask_srlv_epi64(a, 0, a, count); @@ -9192,7 +9192,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_srlv_epi64() { + fn test_mm256_maskz_srlv_epi64() { let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); let count = _mm256_set1_epi64x(1); let r = _mm256_maskz_srlv_epi64(0, a, count); @@ -9203,7 +9203,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_srlv_epi64() { + fn test_mm_mask_srlv_epi64() { let a = _mm_set_epi64x(1 << 5, 0); let count = _mm_set1_epi64x(1); let r = _mm_mask_srlv_epi64(a, 0, a, count); @@ -9214,7 +9214,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_srlv_epi64() { + fn test_mm_maskz_srlv_epi64() { let a = _mm_set_epi64x(1 << 5, 0); let count = _mm_set1_epi64x(1); let r = _mm_maskz_srlv_epi64(0, a, count); @@ -9511,7 +9511,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_srav_epi64() { + fn test_mm512_srav_epi64() { let a = _mm512_set_epi64(1, -8, 0, 0, 0, 0, 15, -16); let count = _mm512_set_epi64(2, 2, 0, 0, 0, 0, 2, 1); let r = _mm512_srav_epi64(a, count); @@ -9520,7 +9520,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_mask_srav_epi64() { + fn test_mm512_mask_srav_epi64() { let a = _mm512_set_epi64(1, -8, 0, 0, 0, 0, 15, -16); let count = _mm512_set_epi64(2, 2, 0, 0, 0, 0, 2, 1); let r = _mm512_mask_srav_epi64(a, 0, a, count); @@ -9531,7 +9531,7 @@ mod tests { } #[simd_test(enable = "avx512f")] - const fn test_mm512_maskz_srav_epi64() { + fn test_mm512_maskz_srav_epi64() { let a = _mm512_set_epi64(1, -8, 0, 0, 0, 0, 15, -16); let count = _mm512_set_epi64(2, 2, 0, 0, 0, 0, 2, 1); let r = _mm512_maskz_srav_epi64(0, a, count); @@ -9542,7 +9542,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_srav_epi64() { + fn test_mm256_srav_epi64() { let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); let count = _mm256_set1_epi64x(1); let r = _mm256_srav_epi64(a, count); @@ -9551,7 +9551,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_mask_srav_epi64() { + fn test_mm256_mask_srav_epi64() { let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); let count = _mm256_set1_epi64x(1); let r = _mm256_mask_srav_epi64(a, 0, a, count); @@ -9562,7 +9562,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm256_maskz_srav_epi64() { + fn test_mm256_maskz_srav_epi64() { let a = _mm256_set_epi64x(1 << 5, 0, 0, 0); let count = _mm256_set1_epi64x(1); let r = _mm256_maskz_srav_epi64(0, a, count); @@ -9573,7 +9573,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_srav_epi64() { + fn test_mm_srav_epi64() { let a = _mm_set_epi64x(1 << 5, 0); let count = _mm_set1_epi64x(1); let r = _mm_srav_epi64(a, count); @@ -9582,7 +9582,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_mask_srav_epi64() { + fn test_mm_mask_srav_epi64() { let a = _mm_set_epi64x(1 << 5, 0); let count = _mm_set1_epi64x(1); let r = _mm_mask_srav_epi64(a, 0, a, count); @@ -9593,7 +9593,7 @@ mod tests { } #[simd_test(enable = "avx512f,avx512vl")] - const fn test_mm_maskz_srav_epi64() { + fn test_mm_maskz_srav_epi64() { let a = _mm_set_epi64x(1 << 5, 0); let count = _mm_set1_epi64x(1); let r = _mm_maskz_srav_epi64(0, a, count); From aa62febfad931562420cdd90d7e790eeea7288ee Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Sep 2026 16:48:34 +0200 Subject: [PATCH 0185/1309] fmt --- .../crates/core_arch/src/x86/avx512bw.rs | 42 ++-------- .../crates/core_arch/src/x86/avx512f.rs | 84 +++---------------- 2 files changed, 18 insertions(+), 108 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs index 8e642432151ea..e400453f627bc 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512bw.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512bw.rs @@ -7381,12 +7381,7 @@ pub fn _mm512_sllv_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -pub fn _mm512_mask_sllv_epi16( - src: __m512i, - k: __mmask32, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_sllv_epi16(src: __m512i, k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, src.as_i16x32())) @@ -7425,12 +7420,7 @@ pub fn _mm256_sllv_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvw))] -pub fn _mm256_mask_sllv_epi16( - src: __m256i, - k: __mmask16, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_sllv_epi16(src: __m256i, k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, src.as_i16x16())) @@ -7746,12 +7736,7 @@ pub fn _mm512_srlv_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -pub fn _mm512_mask_srlv_epi16( - src: __m512i, - k: __mmask32, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srlv_epi16(src: __m512i, k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, src.as_i16x32())) @@ -7790,12 +7775,7 @@ pub fn _mm256_srlv_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvw))] -pub fn _mm256_mask_srlv_epi16( - src: __m256i, - k: __mmask16, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srlv_epi16(src: __m256i, k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, src.as_i16x16())) @@ -8098,12 +8078,7 @@ pub fn _mm512_srav_epi16(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512bw")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -pub fn _mm512_mask_srav_epi16( - src: __m512i, - k: __mmask32, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srav_epi16(src: __m512i, k: __mmask32, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi16(a, count).as_i16x32(); transmute(simd_select_bitmask(k, shf, src.as_i16x32())) @@ -8142,12 +8117,7 @@ pub fn _mm256_srav_epi16(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512bw,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravw))] -pub fn _mm256_mask_srav_epi16( - src: __m256i, - k: __mmask16, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srav_epi16(src: __m256i, k: __mmask16, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi16(a, count).as_i16x16(); transmute(simd_select_bitmask(k, shf, src.as_i16x16())) diff --git a/library/stdarch/crates/core_arch/src/x86/avx512f.rs b/library/stdarch/crates/core_arch/src/x86/avx512f.rs index 27c80312d6ac6..5d9aecff64d84 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512f.rs @@ -21659,12 +21659,7 @@ pub fn _mm512_srav_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -pub fn _mm512_mask_srav_epi32( - src: __m512i, - k: __mmask16, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srav_epi32(src: __m512i, k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, src.as_i32x16())) @@ -21692,12 +21687,7 @@ pub fn _mm512_maskz_srav_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m5 #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravd))] -pub fn _mm256_mask_srav_epi32( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srav_epi32(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, src.as_i32x8())) @@ -21764,12 +21754,7 @@ pub fn _mm512_srav_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -pub fn _mm512_mask_srav_epi64( - src: __m512i, - k: __mmask8, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srav_epi64(src: __m512i, k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srav_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, src.as_i64x8())) @@ -21808,12 +21793,7 @@ pub fn _mm256_srav_epi64(a: __m256i, count: __m256i) -> __m256i { #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsravq))] -pub fn _mm256_mask_srav_epi64( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srav_epi64(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srav_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, src.as_i64x4())) @@ -22467,12 +22447,7 @@ pub fn _mm512_sllv_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -pub fn _mm512_mask_sllv_epi32( - src: __m512i, - k: __mmask16, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_sllv_epi32(src: __m512i, k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, src.as_i32x16())) @@ -22500,12 +22475,7 @@ pub fn _mm512_maskz_sllv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m5 #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvd))] -pub fn _mm256_mask_sllv_epi32( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_sllv_epi32(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, src.as_i32x8())) @@ -22572,12 +22542,7 @@ pub fn _mm512_srlv_epi32(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -pub fn _mm512_mask_srlv_epi32( - src: __m512i, - k: __mmask16, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srlv_epi32(src: __m512i, k: __mmask16, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi32(a, count).as_i32x16(); transmute(simd_select_bitmask(k, shf, src.as_i32x16())) @@ -22605,12 +22570,7 @@ pub fn _mm512_maskz_srlv_epi32(k: __mmask16, a: __m512i, count: __m512i) -> __m5 #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvd))] -pub fn _mm256_mask_srlv_epi32( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srlv_epi32(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi32(a, count).as_i32x8(); transmute(simd_select_bitmask(k, shf, src.as_i32x8())) @@ -22677,12 +22637,7 @@ pub fn _mm512_sllv_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -pub fn _mm512_mask_sllv_epi64( - src: __m512i, - k: __mmask8, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_sllv_epi64(src: __m512i, k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_sllv_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, src.as_i64x8())) @@ -22710,12 +22665,7 @@ pub fn _mm512_maskz_sllv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m51 #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsllvq))] -pub fn _mm256_mask_sllv_epi64( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_sllv_epi64(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_sllv_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, src.as_i64x4())) @@ -22782,12 +22732,7 @@ pub fn _mm512_srlv_epi64(a: __m512i, count: __m512i) -> __m512i { #[target_feature(enable = "avx512f")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -pub fn _mm512_mask_srlv_epi64( - src: __m512i, - k: __mmask8, - a: __m512i, - count: __m512i, -) -> __m512i { +pub fn _mm512_mask_srlv_epi64(src: __m512i, k: __mmask8, a: __m512i, count: __m512i) -> __m512i { unsafe { let shf = _mm512_srlv_epi64(a, count).as_i64x8(); transmute(simd_select_bitmask(k, shf, src.as_i64x8())) @@ -22815,12 +22760,7 @@ pub fn _mm512_maskz_srlv_epi64(k: __mmask8, a: __m512i, count: __m512i) -> __m51 #[target_feature(enable = "avx512f,avx512vl")] #[stable(feature = "stdarch_x86_avx512", since = "1.89")] #[cfg_attr(test, assert_instr(vpsrlvq))] -pub fn _mm256_mask_srlv_epi64( - src: __m256i, - k: __mmask8, - a: __m256i, - count: __m256i, -) -> __m256i { +pub fn _mm256_mask_srlv_epi64(src: __m256i, k: __mmask8, a: __m256i, count: __m256i) -> __m256i { unsafe { let shf = _mm256_srlv_epi64(a, count).as_i64x4(); transmute(simd_select_bitmask(k, shf, src.as_i64x4())) From cfc12ac04fe5606aa90f31059ecbc809883fc371 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Wed, 9 Sep 2026 13:56:18 +0100 Subject: [PATCH 0186/1309] Fix "explicit `package.readme` can be inferred" --- library/stdarch/crates/core_arch/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml index 670447a2d5a8b..c7b8527f4d9fc 100644 --- a/library/stdarch/crates/core_arch/Cargo.toml +++ b/library/stdarch/crates/core_arch/Cargo.toml @@ -9,7 +9,6 @@ authors = [ description = "`core::arch` - Rust's core library architecture-specific intrinsics." homepage = "https://github.com/rust-lang/stdarch" repository = "https://github.com/rust-lang/stdarch" -readme = "README.md" keywords = ["core", "simd", "arch", "intrinsics"] categories = ["hardware-support", "no-std"] license = "MIT OR Apache-2.0" From 89e9fe135e343ed4117489a82f2a32f1da9606c3 Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Wed, 9 Sep 2026 14:01:30 +0100 Subject: [PATCH 0187/1309] Fix "`package.homepage` is redundant with `package.repository`" --- library/stdarch/crates/core_arch/Cargo.toml | 1 - 1 file changed, 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml index c7b8527f4d9fc..ab8b9bcd9fcef 100644 --- a/library/stdarch/crates/core_arch/Cargo.toml +++ b/library/stdarch/crates/core_arch/Cargo.toml @@ -7,7 +7,6 @@ authors = [ "Gonzalo Brito Gadeschi ", ] description = "`core::arch` - Rust's core library architecture-specific intrinsics." -homepage = "https://github.com/rust-lang/stdarch" repository = "https://github.com/rust-lang/stdarch" keywords = ["core", "simd", "arch", "intrinsics"] categories = ["hardware-support", "no-std"] From dce8dd2fe293a941940ef618b5c5a85cb3b7a43d Mon Sep 17 00:00:00 2001 From: Adam Gemmell Date: Wed, 9 Sep 2026 14:19:10 +0100 Subject: [PATCH 0188/1309] Fix "unused dependency" --- library/stdarch/Cargo.lock | 46 ------------------- .../stdarch/crates/intrinsic-test/Cargo.toml | 2 - library/stdarch/examples/Cargo.toml | 4 +- 3 files changed, 3 insertions(+), 49 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 9923b630cd5bb..9ec3227f49e7d 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -217,12 +217,6 @@ dependencies = [ "syn", ] -[[package]] -name = "diff" -version = "0.1.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" - [[package]] name = "either" version = "1.15.0" @@ -400,7 +394,6 @@ name = "intrinsic-test" version = "0.1.0" dependencies = [ "clap", - "diff", "itertools", "log", "pretty_env_logger", @@ -408,7 +401,6 @@ dependencies = [ "rayon", "regex", "serde", - "serde-xml-rs", "serde_json", ] @@ -726,18 +718,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-xml-rs" -version = "0.8.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cc2215ce3e6a77550b80a1c37251b7d294febaf42e36e21b7b411e0bf54d540d" -dependencies = [ - "log", - "serde", - "thiserror", - "xml", -] - [[package]] name = "serde_core" version = "1.0.228" @@ -935,26 +915,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "thiserror" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4288b5bcbc7920c07a1149a35cf9590a2aa808e0bc1eafaade0b80947865fbc4" -dependencies = [ - "thiserror-impl", -] - -[[package]] -name = "thiserror-impl" -version = "2.0.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebc4ee7f67670e9b64d05fa4253e753e016c6c95ff35b89b7941d6b856dec1d5" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "unicode-ident" version = "1.0.24" @@ -1169,12 +1129,6 @@ dependencies = [ "wasmparser 0.244.0", ] -[[package]] -name = "xml" -version = "1.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b8aa498d22c9bbaf482329839bc5620c46be275a19a812e9a22a2b07529a642a" - [[package]] name = "yaml-rust" version = "0.4.5" diff --git a/library/stdarch/crates/intrinsic-test/Cargo.toml b/library/stdarch/crates/intrinsic-test/Cargo.toml index e5c9e44e6d32a..2e11591fe7153 100644 --- a/library/stdarch/crates/intrinsic-test/Cargo.toml +++ b/library/stdarch/crates/intrinsic-test/Cargo.toml @@ -17,8 +17,6 @@ clap = { version = "4.4", features = ["derive"] } log = "0.4.11" pretty_env_logger = "0.5.0" rayon = "1.5.0" -diff = "0.1.12" itertools = "0.15.0" quick-xml = { version = "0.37.5", features = ["serialize", "overlapped-lists"] } -serde-xml-rs = "0.8.0" regex = "1.11.1" diff --git a/library/stdarch/examples/Cargo.toml b/library/stdarch/examples/Cargo.toml index 8752f206526c7..677407cf25206 100644 --- a/library/stdarch/examples/Cargo.toml +++ b/library/stdarch/examples/Cargo.toml @@ -12,9 +12,11 @@ default-run = "hex" [dependencies] core_arch = { path = "../crates/core_arch" } -quickcheck = "1.0" rand = "0.9.3" +[dev-dependencies] +quickcheck = "1.0" + [[bin]] name = "hex" path = "hex.rs" From ebd2995efb0e3d3e9e5038db556968256ef3106c Mon Sep 17 00:00:00 2001 From: FractalFir Date: Tue, 5 Aug 2025 22:12:26 +0200 Subject: [PATCH 0189/1309] Ported cg_gcc to the new cg_ssa version --- src/builder.rs | 23 +++++++++++++++++++---- src/intrinsic/mod.rs | 39 ++++++++++++++++++++++++++++++++++----- 2 files changed, 53 insertions(+), 9 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 88049d67964b1..29155abee276c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -608,6 +608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + indirect_return_pointer: Option>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, @@ -618,7 +619,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let current_block = self.block; self.block = try_block; - let call = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); // FIXME(antoyo): use funclet here? + let call = + self.call(typ, fn_attrs, fn_abi, func, indirect_return_pointer, args, None, instance); // FIXME(antoyo): use funclet here? self.block = current_block; let return_value = @@ -646,13 +648,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + indirect_return_pointer: Option>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let call_site = self.call(typ, fn_attrs, fn_abi, func, args, None, instance); + let call_site = + self.call(typ, fn_attrs, fn_abi, func, indirect_return_pointer, args, None, instance); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(self.location, condition, then, catch); if let Some(_fn_abi) = fn_abi { @@ -1779,19 +1783,30 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + indirect_return_pointer: Option>, args: &[RValue<'gcc>], funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { + // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. + let args = match indirect_return_pointer { + None => args.to_vec(), + Some(sret_ptr) => { + let mut args = args.to_vec(); + // Preappend the indirect return pointer + args.insert(0, sret_ptr); + args + } + }; // FIXME(antoyo): remove when having a proper API. let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { // FIXME(antoyo): remove when the API supports a different type for functions. let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet) + self.function_call(func, &args, funclet) } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet) + self.function_ptr_call(typ, fn_abi, func, &args, funclet) }; if let Some(_fn_abi) = fn_abi { // FIXME(bjorn3): Apply function attributes diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 5550d22b33aa3..4dc24cfa1d3ee 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -666,7 +666,16 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc fn abort(&mut self) { let func = self.context.get_builtin_function("abort"); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - self.call(self.type_void(), None, None, func, &[], None, None); + self.call( + self.type_void(), + None, + None, + func, + None, /* abort does not return, so it can't return indirectly. */ + &[], + None, + None, + ); } fn assume(&mut self, value: Self::Value) { @@ -1347,7 +1356,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( let param_type = bx.u8_type.make_pointer(); let fn_type = bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false); - bx.call(fn_type, None, None, try_func, &[data], None, None); + bx.call(fn_type, None, None, try_func, None, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. OperandValue::Immediate(bx.const_bool(false)).store(bx, dest); @@ -1420,21 +1429,41 @@ fn codegen_gnu_try<'gcc, 'tcx>( let zero = bx.cx.context.new_rvalue_zero(bx.int_type); let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, &[data, ptr], None, None); + bx.call(catch_ty, None, None, catch_func, None, &[data, ptr], None, None); bx.ret(bx.const_bool(true)); // NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not // generate a try/catch. // FIXME(antoyo): add a check in the libgccjit API to prevent this. bx.switch_to_block(current_block); - bx.invoke(try_func_ty, None, None, try_func, &[data], then, catch, None, None); + bx.invoke( + try_func_ty, + None, + None, + try_func, + None, /* this function can't return indirectly */ + &[data], + then, + catch, + None, + None, + ); }); let func = unsafe { std::mem::transmute::, RValue<'gcc>>(func) }; // Note that no invoke is used here because by definition this function // can't panic (that's what it's catching). - let ret = bx.call(llty, None, None, func, &[try_func, data, catch_func], None, None); + let ret = bx.call( + llty, + None, + None, + func, + None, /*This function can't return indirectly*/ + &[try_func, data, catch_func], + None, + None, + ); OperandValue::Immediate(ret).store(bx, dest); } From 8b916a88dec7853f28a6109de02eb0a3a84fee29 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Fractal=20Fir=28Micha=C5=82=20Kostrubiec=29?= Date: Fri, 19 Sep 2025 20:23:52 +0200 Subject: [PATCH 0190/1309] Apply suggestions from code review Co-authored-by: Jubilee --- src/builder.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/builder.rs b/src/builder.rs index 29155abee276c..9b74512b6ac88 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1793,7 +1793,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { None => args.to_vec(), Some(sret_ptr) => { let mut args = args.to_vec(); - // Preappend the indirect return pointer + // Prepend the indirect return pointer args.insert(0, sret_ptr); args } From a03efcf7602abf6c8f8f1dbc27395f46cb831688 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 1 Nov 2025 11:11:49 -0400 Subject: [PATCH 0191/1309] Add missing indirect return argument to new calls --- src/intrinsic/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 4dc24cfa1d3ee..98aeb25573e24 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -655,7 +655,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } // FIXME directly use the llvm intrinsic adjustment functions here - let llret = self.call(fn_ty, None, None, fn_ptr, &call_args, None, None); + let llret = self.call(fn_ty, None, None, fn_ptr, None, &call_args, None, None); if is_cleanup { self.apply_attrs_to_cleanup_callsite(llret); } From 5b910ff115cb70529a80e70b176dd4886da9f18d Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sun, 19 Jul 2026 17:08:54 -0400 Subject: [PATCH 0192/1309] Improve the new indirect return API --- src/builder.rs | 22 +++++++++++----------- src/intrinsic/mod.rs | 24 ++++++++---------------- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index 9b74512b6ac88..83f2bcdd3959c 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -18,7 +18,7 @@ use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::{ BackendTypes, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - LayoutTypeCodegenMethods, OverflowOp, StaticBuilderMethods, + LayoutTypeCodegenMethods, OverflowOp, ReturnSlot, StaticBuilderMethods, }; use rustc_data_structures::fx::FxHashSet; use rustc_middle::bug; @@ -608,7 +608,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, - indirect_return_pointer: Option>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, @@ -619,8 +619,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let current_block = self.block; self.block = try_block; - let call = - self.call(typ, fn_attrs, fn_abi, func, indirect_return_pointer, args, None, instance); // FIXME(antoyo): use funclet here? + // FIXME(antoyo): use funclet here? + let call = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance); self.block = current_block; let return_value = @@ -648,15 +648,14 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, - indirect_return_pointer: Option>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], then: Block<'gcc>, catch: Block<'gcc>, _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let call_site = - self.call(typ, fn_attrs, fn_abi, func, indirect_return_pointer, args, None, instance); + let call_site = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance); let condition = self.context.new_rvalue_from_int(self.bool_type, 1); self.llbb().end_with_conditional(self.location, condition, then, catch); if let Some(_fn_abi) = fn_abi { @@ -1783,15 +1782,15 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, - indirect_return_pointer: Option>, + return_slot: ReturnSlot>, args: &[RValue<'gcc>], funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. - let args = match indirect_return_pointer { - None => args.to_vec(), - Some(sret_ptr) => { + let args = match return_slot { + ReturnSlot::Direct => args.to_vec(), + ReturnSlot::Indirect(sret_ptr) => { let mut args = args.to_vec(); // Prepend the indirect return pointer args.insert(0, sret_ptr); @@ -1820,6 +1819,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, _llfn: Self::Value, + _return_slot: ReturnSlot, _args: &[Self::Value], _funclet: Option<&Self::Funclet>, _instance: Option>, diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 98aeb25573e24..06713016cedbe 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -16,7 +16,7 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::MiscCodegenMethods; use rustc_codegen_ssa::traits::{ ArgAbiBuilderMethods, BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, - IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, + IntrinsicCallBuilderMethods, LayoutTypeCodegenMethods, ReturnSlot, }; use rustc_codegen_ssa::{MemFlags, RetagInfo}; use rustc_data_structures::fx::FxHashSet; @@ -655,7 +655,8 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } // FIXME directly use the llvm intrinsic adjustment functions here - let llret = self.call(fn_ty, None, None, fn_ptr, None, &call_args, None, None); + let llret = + self.call(fn_ty, None, None, fn_ptr, ReturnSlot::Direct, &call_args, None, None); if is_cleanup { self.apply_attrs_to_cleanup_callsite(llret); } @@ -666,16 +667,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc fn abort(&mut self) { let func = self.context.get_builtin_function("abort"); let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - self.call( - self.type_void(), - None, - None, - func, - None, /* abort does not return, so it can't return indirectly. */ - &[], - None, - None, - ); + self.call(self.type_void(), None, None, func, ReturnSlot::Direct, &[], None, None); } fn assume(&mut self, value: Self::Value) { @@ -1356,7 +1348,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( let param_type = bx.u8_type.make_pointer(); let fn_type = bx.context.new_function_pointer_type(None, bx.type_void(), &[param_type], false); - bx.call(fn_type, None, None, try_func, None, &[data], None, None); + bx.call(fn_type, None, None, try_func, ReturnSlot::Direct, &[data], None, None); // Return 0 unconditionally from the intrinsic call; // we can never unwind. OperandValue::Immediate(bx.const_bool(false)).store(bx, dest); @@ -1429,7 +1421,7 @@ fn codegen_gnu_try<'gcc, 'tcx>( let zero = bx.cx.context.new_rvalue_zero(bx.int_type); let ptr = bx.cx.context.new_call(None, eh_pointer_builtin, &[zero]); let catch_ty = bx.type_func(&[bx.type_i8p(), bx.type_i8p()], bx.type_void()); - bx.call(catch_ty, None, None, catch_func, None, &[data, ptr], None, None); + bx.call(catch_ty, None, None, catch_func, ReturnSlot::Direct, &[data, ptr], None, None); bx.ret(bx.const_bool(true)); // NOTE: the blocks must be filled before adding the try/catch, otherwise gcc will not @@ -1441,7 +1433,7 @@ fn codegen_gnu_try<'gcc, 'tcx>( None, None, try_func, - None, /* this function can't return indirectly */ + ReturnSlot::Direct, &[data], then, catch, @@ -1459,7 +1451,7 @@ fn codegen_gnu_try<'gcc, 'tcx>( None, None, func, - None, /*This function can't return indirectly*/ + ReturnSlot::Direct, &[try_func, data, catch_func], None, None, From 93114826c04cc3bad25eb2e98ef1208540c23fb6 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 10 Sep 2026 04:33:29 +0000 Subject: [PATCH 0193/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 315ecf4a939def16631c2b25c3782ad67fc22160. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 0e28d51ef406e..435bd384599f1 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -f248f4038796913873f11ca65b1b901e311c8dae +315ecf4a939def16631c2b25c3782ad67fc22160 From 34deffbbed4d2f34fdebe062f04af0679bdd0caf Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 10 Sep 2026 04:38:41 +0000 Subject: [PATCH 0194/1309] fmt --- src/tools/miri/src/shims/unix/linux_like/thread.rs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/shims/unix/linux_like/thread.rs b/src/tools/miri/src/shims/unix/linux_like/thread.rs index 987de85740ea5..e053547ae42f9 100644 --- a/src/tools/miri/src/shims/unix/linux_like/thread.rs +++ b/src/tools/miri/src/shims/unix/linux_like/thread.rs @@ -25,8 +25,11 @@ pub fn prctl<'tcx>( let res = match ecx.read_scalar(op)?.to_i32()? { op if op == pr_set_name => { - let ([name], _) = - ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_SET_NAME, ...)")?; + let ([name], _) = ecx.check_varargs( + shim_varargs![*libc::c_char], + varargs, + "prctl(PR_SET_NAME, ...)", + )?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; @@ -38,8 +41,11 @@ pub fn prctl<'tcx>( Scalar::from_u32(0) } op if op == pr_get_name => { - let ([name], _) = - ecx.check_varargs(shim_varargs![*libc::c_char], varargs, "prctl(PR_GET_NAME, ...)")?; + let ([name], _) = ecx.check_varargs( + shim_varargs![*libc::c_char], + varargs, + "prctl(PR_GET_NAME, ...)", + )?; let name = ecx.read_scalar(name)?; let thread = ecx.pthread_self()?; From 2b85c28d07e0dca110fe971a9f65c39a5d0b28a9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 10 Sep 2026 08:40:20 +0200 Subject: [PATCH 0195/1309] adjust CI: 32bit windows hosts are no more --- src/tools/miri/.github/workflows/ci.yml | 2 +- src/tools/miri/ci/ci.sh | 9 ++++----- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 65d91ffc9ef15..8befdc5db3331 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -53,7 +53,7 @@ jobs: # qemu: true - host_target: aarch64-apple-darwin os: macos-latest - - host_target: i686-pc-windows-msvc + - host_target: x86_64-pc-windows-msvc os: windows-latest - host_target: aarch64-pc-windows-msvc os: windows-11-arm diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index b9f8c10900853..0cf2c5293c339 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -150,7 +150,7 @@ case $HOST_TARGET in i686-unknown-linux-gnu) # Host MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests - # Not officially supported tier 2 + # Not officially supported tier 2. Also covers "64bit target on 32bit host". MANY_SEEDS=16 TEST_TARGET=aarch64-linux-android run_tests MANY_SEEDS=16 TEST_TARGET=loongarch64-unknown-linux-gnu run_tests # Partially supported targets (no_std, tier 2) @@ -175,7 +175,7 @@ case $HOST_TARGET in MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests # Custom target JSON file TEST_TARGET=tests/x86_64-unknown-kernel.json MIRI_NO_STD=1 MIRIFLAGS="-Zunstable-options" run_tests_minimal no_std - # Not officially supported tier 2 + # Not officially supported tier 2. MANY_SEEDS=16 TEST_TARGET=x86_64-pc-solaris run_tests MANY_SEEDS=16 TEST_TARGET=mips-unknown-linux-gnu run_tests # a 32bit big-endian target, and also a target without 64bit atomics MANY_SEEDS=16 TEST_TARGET=riscv64a23-unknown-linux-gnu run_tests @@ -187,12 +187,11 @@ case $HOST_TARGET in MANY_SEEDS=64 TEST_TARGET=i686-pc-windows-gnu run_tests MANY_SEEDS=64 TEST_TARGET=x86_64-pc-windows-msvc CARGO_MIRI_ENV=1 run_tests ;; - i686-pc-windows-msvc) + x86_64-pc-windows-msvc) # Host MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 run_tests # Extra tier 1 - # We really want to ensure a Linux target works on a Windows host, - # and a 64bit target works on a 32bit host. + # We really want to ensure a Linux target works on a Windows host. TEST_TARGET=x86_64-unknown-linux-gnu run_tests ;; aarch64-pc-windows-msvc) From aa64bfc2f94a938558e177c98db2e780c99c47e0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 31 Aug 2026 12:56:40 +0200 Subject: [PATCH 0196/1309] Don't rely on codegen emitting fn_abi_of_* errors in abi checks This avoids a delayed bug if compilation is aborted between checking function ABIs and codegening all functions. --- src/context.rs | 23 +++-------------------- 1 file changed, 3 insertions(+), 20 deletions(-) diff --git a/src/context.rs b/src/context.rs index 19fbe37c27b9e..64f9982ac7de6 100644 --- a/src/context.rs +++ b/src/context.rs @@ -10,16 +10,15 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, ToBaseN}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir::interpret::Allocation; use rustc_middle::mono::CodegenUnit; -use rustc_middle::span_bug; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOf, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, - LayoutOfHelpers, + LayoutOfHelpers, codegen_handle_fn_abi_err, }; use rustc_middle::ty::{self, ExistentialTraitRef, Instance, Ty, TyCtxt}; #[cfg(feature = "master")] use rustc_session::config::DebugInfo; use rustc_session::{PointerAuthSchema, Session}; -use rustc_span::{DUMMY_SP, Span, Symbol, respan}; +use rustc_span::{DUMMY_SP, Span, Symbol}; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; #[cfg(feature = "master")] @@ -562,23 +561,7 @@ impl<'gcc, 'tcx> FnAbiOfHelpers<'tcx> for CodegenCx<'gcc, 'tcx> { span: Span, fn_abi_request: FnAbiRequest<'tcx>, ) -> ! { - if let FnAbiError::Layout(LayoutError::SizeOverflow(_) | LayoutError::InvalidSimd { .. }) = - err - { - self.tcx.dcx().emit_fatal(respan(span, err)) - } else { - match fn_abi_request { - FnAbiRequest::OfFnPtr { sig, extra_args } => { - span_bug!(span, "`fn_abi_of_fn_ptr({sig}, {extra_args:?})` failed: {err:?}"); - } - FnAbiRequest::OfInstance { instance, extra_args } => { - span_bug!( - span, - "`fn_abi_of_instance({instance}, {extra_args:?})` failed: {err:?}" - ); - } - } - } + codegen_handle_fn_abi_err(self.tcx, err, span, fn_abi_request).raise_fatal() } } From ff7da792fbaebadac25aa7ed20a0aa422c642fff Mon Sep 17 00:00:00 2001 From: Cameron Mulhern Date: Fri, 29 May 2026 12:45:46 -0400 Subject: [PATCH 0197/1309] Add baseline tests for macro body widths --- tests/source/issue-6651/custom_width.rs | 21 +++++++++++++++++++++ tests/source/issue-6651/default.rs | 19 +++++++++++++++++++ tests/target/issue-6651/custom_width.rs | 21 +++++++++++++++++++++ tests/target/issue-6651/default.rs | 24 ++++++++++++++++++++++++ 4 files changed, 85 insertions(+) create mode 100644 tests/source/issue-6651/custom_width.rs create mode 100644 tests/source/issue-6651/default.rs create mode 100644 tests/target/issue-6651/custom_width.rs create mode 100644 tests/target/issue-6651/default.rs diff --git a/tests/source/issue-6651/custom_width.rs b/tests/source/issue-6651/custom_width.rs new file mode 100644 index 0000000000000..b6bbe715290d3 --- /dev/null +++ b/tests/source/issue-6651/custom_width.rs @@ -0,0 +1,21 @@ +// rustfmt-format_macro_bodies: true +// rustfmt-max_width: 82 +// rustfmt-fn_call_width: 76 + +macro_rules! short { + () => { + m!(a, b, c); + }; +} + +macro_rules! medium { + () => { + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddd); + }; +} + +macro_rules! long { + () => { + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddddddddd); + }; +} diff --git a/tests/source/issue-6651/default.rs b/tests/source/issue-6651/default.rs new file mode 100644 index 0000000000000..de8e64b4094d0 --- /dev/null +++ b/tests/source/issue-6651/default.rs @@ -0,0 +1,19 @@ +// rustfmt-format_macro_bodies: true + +macro_rules! short { + () => { + m!(a, b, c); + }; +} + +macro_rules! medium { + () => { + m!(aaaaaaaaaa, bbbbbbbbbb, cccccccccc, ddddddddd); + }; +} + +macro_rules! long { + () => { + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddddddddd); + }; +} diff --git a/tests/target/issue-6651/custom_width.rs b/tests/target/issue-6651/custom_width.rs new file mode 100644 index 0000000000000..b6bbe715290d3 --- /dev/null +++ b/tests/target/issue-6651/custom_width.rs @@ -0,0 +1,21 @@ +// rustfmt-format_macro_bodies: true +// rustfmt-max_width: 82 +// rustfmt-fn_call_width: 76 + +macro_rules! short { + () => { + m!(a, b, c); + }; +} + +macro_rules! medium { + () => { + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddd); + }; +} + +macro_rules! long { + () => { + m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddddddddd); + }; +} diff --git a/tests/target/issue-6651/default.rs b/tests/target/issue-6651/default.rs new file mode 100644 index 0000000000000..6fab41d9018ce --- /dev/null +++ b/tests/target/issue-6651/default.rs @@ -0,0 +1,24 @@ +// rustfmt-format_macro_bodies: true + +macro_rules! short { + () => { + m!(a, b, c); + }; +} + +macro_rules! medium { + () => { + m!(aaaaaaaaaa, bbbbbbbbbb, cccccccccc, ddddddddd); + }; +} + +macro_rules! long { + () => { + m!( + aaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbb, + cccccccccccccccc, + ddddddddddddddd + ); + }; +} From 93e78f2d3a0901718530aa871565257a41869983 Mon Sep 17 00:00:00 2001 From: Cameron Mulhern Date: Wed, 3 Sep 2025 20:47:17 +0100 Subject: [PATCH 0198/1309] Fixes adjustment of max_width within macros --- src/config/config_type.rs | 57 +++++++++++++++++++++++++ src/macros.rs | 6 +-- tests/target/issue-6651/custom_width.rs | 7 ++- 3 files changed, 65 insertions(+), 5 deletions(-) diff --git a/src/config/config_type.rs b/src/config/config_type.rs index afac8d3fcf992..f559cc0d620c4 100644 --- a/src/config/config_type.rs +++ b/src/config/config_type.rs @@ -423,6 +423,63 @@ macro_rules! create_config { )+ } + /// Reduces the maximum width of the configuration. + /// + /// This method is intended to be used when creating a forked + /// configuration for a particular formatting context in which the + /// total available width needs to be reduced. This reduces the + /// size of max_width, and all other properties affected by small + /// heuristics, without treating those adjustments as overrides. + /// + /// As an example use case, this method is used when formatting + /// arms within a declarative macro. + #[allow(unreachable_pub)] + pub fn reduce_max_width(&mut self, delta: usize) { + self.adjust_max_width(-(delta as isize)); + } + + /// Increases the maximum width of the configuration. + /// + /// This method is intended to be used when creating a forked + /// configuration for a particular formatting context in which the + /// total available width needs to be reduced. This increases the + /// size of max_width, and all other properties affected by small + /// heuristics, without treating those adjustments as overrides. + /// + /// As an example use case, this method is used when formatting + /// arms within a declarative macro. + #[allow(unreachable_pub)] + pub fn increase_max_width(&mut self, delta: usize) { + self.adjust_max_width(delta as isize); + } + + /// Adjusts the maximum width of the configuration. + /// + /// This method is intended to be used when creating a forked + /// configuration for a particular formatting context in which the + /// total available width needs to be reduced. This adjusts the + /// size of max_width, and all other properties affected by small + /// heuristics, without treating those adjustments as overrides. + /// + /// As an example use case, this method is used when formatting + /// arms within a declarative macro. + fn adjust_max_width(&mut self, delta: isize) { + let adjust = |value: usize| (value as isize + delta) as usize; + + self.array_width.2 = adjust(self.array_width.2); + self.attr_fn_like_width.2 = adjust(self.attr_fn_like_width.2); + self.chain_width.2 = adjust(self.chain_width.2); + self.fn_call_width.2 = adjust(self.fn_call_width.2); + self.single_line_if_else_max_width.2 = adjust(self.single_line_if_else_max_width.2); + self.single_line_let_else_max_width.2 = + adjust(self.single_line_let_else_max_width.2); + self.struct_lit_width.2 = adjust(self.struct_lit_width.2); + self.struct_variant_width.2 = adjust(self.struct_variant_width.2); + + self.max_width.2 = adjust(self.max_width.2); + self.set_heuristics(); + } + fn set_width_heuristics(&mut self, heuristics: WidthHeuristics) { let max_width = self.max_width.2; let get_width_value = | diff --git a/src/macros.rs b/src/macros.rs index 8bfd99f2f7c9f..7eb63d67580a3 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1361,15 +1361,13 @@ impl MacroBranch { } else { shape.indent.block_indent(&config) }; - let new_width = config.max_width() - body_indent.width(); - config.set().max_width(new_width); + config.reduce_max_width(body_indent.width()); // First try to format as items, then as statements. let new_body_snippet = match crate::format_snippet(&body_str, &config, true) { Some(new_body) => new_body, None => { - let new_width = new_width + config.tab_spaces(); - config.set().max_width(new_width); + config.increase_max_width(config.tab_spaces()); match crate::format_code_block(&body_str, &config, true) { Some(new_body) => new_body, None => { diff --git a/tests/target/issue-6651/custom_width.rs b/tests/target/issue-6651/custom_width.rs index b6bbe715290d3..b46bd5ef5ccab 100644 --- a/tests/target/issue-6651/custom_width.rs +++ b/tests/target/issue-6651/custom_width.rs @@ -16,6 +16,11 @@ macro_rules! medium { macro_rules! long { () => { - m!(aaaaaaaaaaaaaaaa, bbbbbbbbbbbbbbbb, cccccccccccccccc, ddddddddddddddd); + m!( + aaaaaaaaaaaaaaaa, + bbbbbbbbbbbbbbbb, + cccccccccccccccc, + ddddddddddddddd + ); }; } From 78784985c4cb67c5c79dbb2f88b05f5735730423 Mon Sep 17 00:00:00 2001 From: jyn Date: Thu, 10 Sep 2026 17:12:31 +0200 Subject: [PATCH 0199/1309] address review comments --- src/doc/rustc-dev-guide/.github/workflows/ci.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/.github/workflows/ci.yml b/src/doc/rustc-dev-guide/.github/workflows/ci.yml index fd5515dda0e39..606d388d1238b 100644 --- a/src/doc/rustc-dev-guide/.github/workflows/ci.yml +++ b/src/doc/rustc-dev-guide/.github/workflows/ci.yml @@ -99,6 +99,7 @@ jobs: runs-on: ubuntu-latest permissions: actions: read + contents: read issues: write steps: - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 @@ -116,7 +117,7 @@ jobs: contents: read issues: write steps: - - uses: actions/checkout@v7 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Close issue run: ci/close-scheduled-linkcheck-issues.sh env: From 79a93e7b03589374bed92985fec866fb72267099 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Thu, 10 Sep 2026 17:31:15 +0200 Subject: [PATCH 0200/1309] Make the last non-breaking box impl generalizations --- library/alloc/src/boxed/convert.rs | 12 ++++++------ library/alloc/src/bstr.rs | 5 +++-- library/alloc/src/ffi/c_str.rs | 5 +++-- library/std/src/ffi/os_str.rs | 5 +++-- library/std/src/path.rs | 5 +++-- 5 files changed, 18 insertions(+), 14 deletions(-) diff --git a/library/alloc/src/boxed/convert.rs b/library/alloc/src/boxed/convert.rs index f5c16dc7e7040..526e8b18a8031 100644 --- a/library/alloc/src/boxed/convert.rs +++ b/library/alloc/src/boxed/convert.rs @@ -257,8 +257,8 @@ unsafe fn boxed_slice_as_array_unchecked( } #[stable(feature = "boxed_slice_try_from", since = "1.43.0")] -impl TryFrom> for Box<[T; N]> { - type Error = Box<[T]>; +impl TryFrom> for Box<[T; N], A> { + type Error = Box<[T], A>; /// Attempts to convert a `Box<[T]>` into a `Box<[T; N]>`. /// @@ -269,7 +269,7 @@ impl TryFrom> for Box<[T; N]> { /// /// Returns the old `Box<[T]>` in the `Err` variant if /// `boxed_slice.len()` does not equal `N`. - fn try_from(boxed_slice: Box<[T]>) -> Result { + fn try_from(boxed_slice: Box<[T], A>) -> Result { if boxed_slice.len() == N { // SAFETY: Checked length. Ok(unsafe { boxed_slice_as_array_unchecked(boxed_slice) }) @@ -281,8 +281,8 @@ impl TryFrom> for Box<[T; N]> { #[cfg(not(no_global_oom_handling))] #[stable(feature = "boxed_array_try_from_vec", since = "1.66.0")] -impl TryFrom> for Box<[T; N]> { - type Error = Vec; +impl TryFrom> for Box<[T; N], A> { + type Error = Vec; /// Attempts to convert a `Vec` into a `Box<[T; N]>`. /// @@ -302,7 +302,7 @@ impl TryFrom> for Box<[T; N]> { /// let state: Box<[f32; 100]> = vec![1.0; 100].try_into().unwrap(); /// assert_eq!(state.len(), 100); /// ``` - fn try_from(vec: Vec) -> Result { + fn try_from(vec: Vec) -> Result { if vec.len() == N { let boxed_slice = vec.into_boxed_slice(); // SAFETY: Checked length. diff --git a/library/alloc/src/bstr.rs b/library/alloc/src/bstr.rs index 8d993f6758a52..59909ed1db9b2 100644 --- a/library/alloc/src/bstr.rs +++ b/library/alloc/src/bstr.rs @@ -15,6 +15,7 @@ use core::ops::{ use core::str::{FromStr, Utf8Error}; use core::{fmt, hash}; +use crate::alloc::Allocator; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; #[cfg(not(no_rc))] @@ -597,10 +598,10 @@ impl<'a> TryFrom<&'a ByteString> for &'a str { // Additional impls for `ByteStr` that require types from `alloc`: #[unstable(feature = "bstr", issue = "134915")] -impl Clone for Box { +impl Clone for Box { #[inline] fn clone(&self) -> Self { - Self::from(Box::<[u8]>::from(&self.0)) + Box::clone_from_ref_in(&**self, Self::allocator(self).clone()) } } diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs index 78158cad394c6..d13808ee3d21c 100644 --- a/library/alloc/src/ffi/c_str.rs +++ b/library/alloc/src/ffi/c_str.rs @@ -7,6 +7,7 @@ use core::slice::memchr; use core::str::{self, FromStr, Utf8Error}; use core::{fmt, mem, ops, ptr, slice}; +use crate::alloc::Allocator; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::Rc; @@ -863,10 +864,10 @@ impl TryFrom for String { } #[stable(feature = "more_box_slice_clone", since = "1.29.0")] -impl Clone for Box { +impl Clone for Box { #[inline] fn clone(&self) -> Self { - (**self).into() + Box::clone_from_ref_in(&**self, Self::allocator(self).clone()) } } diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs index 6be8f775b441d..b9d344284734b 100644 --- a/library/std/src/ffi/os_str.rs +++ b/library/std/src/ffi/os_str.rs @@ -5,6 +5,7 @@ mod tests; use core::clone::CloneToUninit; +use crate::alloc::Allocator; use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::hash::{Hash, Hasher}; @@ -1395,10 +1396,10 @@ impl From for Box { } #[stable(feature = "more_box_slice_clone", since = "1.29.0")] -impl Clone for Box { +impl Clone for Box { #[inline] fn clone(&self) -> Self { - self.to_os_string().into_boxed_os_str() + Box::clone_from_ref_in(&**self, Self::allocator(self).clone()) } } diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 141bc72fb2e42..08d14b70638a8 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -83,6 +83,7 @@ use core::clone::CloneToUninit; +use crate::alloc::Allocator; use crate::borrow::{Borrow, Cow}; use crate::collections::TryReserveError; use crate::error::Error; @@ -1972,10 +1973,10 @@ impl From for Box { } #[stable(feature = "more_box_slice_clone", since = "1.29.0")] -impl Clone for Box { +impl Clone for Box { #[inline] fn clone(&self) -> Self { - self.to_path_buf().into_boxed_path() + Box::clone_from_ref_in(&**self, Self::allocator(self).clone()) } } From 4aee1dc1493dcd3015e11c0ab4b8cf396ed999df Mon Sep 17 00:00:00 2001 From: supercooltest2024 Date: Thu, 10 Sep 2026 11:45:25 -0600 Subject: [PATCH 0201/1309] spelling --- src/doc/rustc-dev-guide/src/bug-fix-procedure.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md index 0db0e07d4e7be..5416e361e5d24 100644 --- a/src/doc/rustc-dev-guide/src/bug-fix-procedure.md +++ b/src/doc/rustc-dev-guide/src/bug-fix-procedure.md @@ -101,7 +101,7 @@ declare_lint! { }, } -// 2. Add a decidacted lint pass for it. +// 2. Add a dedicated lint pass for it. // This step can be skipped if you emit the lint as part of an existing pass. #[derive(Default)] From 87f7eeeb1f89ff9f94c1ff321d75624550835f76 Mon Sep 17 00:00:00 2001 From: Evgenii Zheltonozhskii Date: Fri, 11 Sep 2026 09:03:38 +0300 Subject: [PATCH 0202/1309] Add regression tests for various issues --- .../dyn-coercion-asyncfn-issue-160355.rs | 21 +++++++++ .../gat-derive-clone-overflow-issue-102580.rs | 17 +++++++ .../gat-where-clause-hang-issue-134370.rs | 23 ++++++++++ .../hrtb-bounds-not-resolving-issue-90950.rs | 44 +++++++++++++++++++ .../hrtb-gat-assoc-hang-issue-134312.rs | 23 ++++++++++ .../mundane-hrtb-constraint-issue-97487.rs | 17 +++++++ .../canonical-query-ambiguity-issue-141478.rs | 42 ++++++++++++++++++ 7 files changed, 187 insertions(+) create mode 100644 tests/ui/async-await/async-closures/dyn-coercion-asyncfn-issue-160355.rs create mode 100644 tests/ui/generic-associated-types/gat-derive-clone-overflow-issue-102580.rs create mode 100644 tests/ui/generic-associated-types/gat-where-clause-hang-issue-134370.rs create mode 100644 tests/ui/generic-associated-types/hrtb-bounds-not-resolving-issue-90950.rs create mode 100644 tests/ui/generic-associated-types/hrtb-gat-assoc-hang-issue-134312.rs create mode 100644 tests/ui/generic-associated-types/mundane-hrtb-constraint-issue-97487.rs create mode 100644 tests/ui/impl-trait/canonical-query-ambiguity-issue-141478.rs diff --git a/tests/ui/async-await/async-closures/dyn-coercion-asyncfn-issue-160355.rs b/tests/ui/async-await/async-closures/dyn-coercion-asyncfn-issue-160355.rs new file mode 100644 index 0000000000000..0eda901835dda --- /dev/null +++ b/tests/ui/async-await/async-closures/dyn-coercion-asyncfn-issue-160355.rs @@ -0,0 +1,21 @@ +//@ edition: 2024 +//@ compile-flags: -Znext-solver +//@ build-pass + +// Regression test for . +// Used to ICE + +struct Wrap(F); + +impl Service for Wrap where F: AsyncFn() {} + +trait Service {} + +impl Service for F where F: AsyncFn() {} + +async fn ice

() {} + +fn main() { + let service = Wrap(ice::<&'static ()>); + let _ = Box::new(service) as Box; +} diff --git a/tests/ui/generic-associated-types/gat-derive-clone-overflow-issue-102580.rs b/tests/ui/generic-associated-types/gat-derive-clone-overflow-issue-102580.rs new file mode 100644 index 0000000000000..7409a0e046841 --- /dev/null +++ b/tests/ui/generic-associated-types/gat-derive-clone-overflow-issue-102580.rs @@ -0,0 +1,17 @@ +//@ edition: 2021 +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Used to overflow + +trait Trait: Clone { + type Type: Clone; +} + +#[derive(Clone)] +struct Struct(Option>); + +fn main() {} diff --git a/tests/ui/generic-associated-types/gat-where-clause-hang-issue-134370.rs b/tests/ui/generic-associated-types/gat-where-clause-hang-issue-134370.rs new file mode 100644 index 0000000000000..6cee37eba6a5a --- /dev/null +++ b/tests/ui/generic-associated-types/gat-where-clause-hang-issue-134370.rs @@ -0,0 +1,23 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Used to get stuck in trait solver + +trait Assoc { + type Ty; +} + +trait Foo { + type Gat<'a>; +} + +trait Bar { + type Ty: Foo + where + for<'a> ::Gat<'a>: Assoc; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/hrtb-bounds-not-resolving-issue-90950.rs b/tests/ui/generic-associated-types/hrtb-bounds-not-resolving-issue-90950.rs new file mode 100644 index 0000000000000..0f2454142f374 --- /dev/null +++ b/tests/ui/generic-associated-types/hrtb-bounds-not-resolving-issue-90950.rs @@ -0,0 +1,44 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Used to say bound not satisfied + +trait Yokeable<'a>: 'static { + type Output: 'a; +} + + +trait IsCovariant<'a> {} + +struct Yoke Yokeable<'a>> { + data: Y, +} + +fn upcast(x: Yoke) -> Yoke + 'static>> +where + Y: for<'a> Yokeable<'a>, + for<'a> >::Output: IsCovariant<'a>, +{ + unimplemented!() +} + + +impl<'a> Yokeable<'a> for Box + 'static> { + type Output = Box + 'a>; +} + +use std::borrow::*; +impl<'a, T: ToOwned + ?Sized> Yokeable<'a> for Cow<'static, T> { + type Output = Cow<'a, T>; +} +impl<'a, T: ToOwned + ?Sized> IsCovariant<'a> for Cow<'a, T> {} + + +fn upcast_yoke(y: Yoke>) -> Yoke + 'static>> { + upcast(y) +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/hrtb-gat-assoc-hang-issue-134312.rs b/tests/ui/generic-associated-types/hrtb-gat-assoc-hang-issue-134312.rs new file mode 100644 index 0000000000000..2abb9cab443a9 --- /dev/null +++ b/tests/ui/generic-associated-types/hrtb-gat-assoc-hang-issue-134312.rs @@ -0,0 +1,23 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Used to hang + +trait Trait { + type Type<'a>; +} + +trait Trait2 { + type Type2; +} + +trait Test { + type Assoc: Trait + where + for<'a> ::Type<'a>: Trait2; +} + +fn main() {} diff --git a/tests/ui/generic-associated-types/mundane-hrtb-constraint-issue-97487.rs b/tests/ui/generic-associated-types/mundane-hrtb-constraint-issue-97487.rs new file mode 100644 index 0000000000000..6f8ad8f227ce0 --- /dev/null +++ b/tests/ui/generic-associated-types/mundane-hrtb-constraint-issue-97487.rs @@ -0,0 +1,17 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// Regression test for . +// Used to ask for type annotations +trait A { + type X; +} + +trait B: for<'a> A { +} + +impl A for T where T: B { + type X = u32; +} + +fn main() {} diff --git a/tests/ui/impl-trait/canonical-query-ambiguity-issue-141478.rs b/tests/ui/impl-trait/canonical-query-ambiguity-issue-141478.rs new file mode 100644 index 0000000000000..213c520683e76 --- /dev/null +++ b/tests/ui/impl-trait/canonical-query-ambiguity-issue-141478.rs @@ -0,0 +1,42 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ check-pass + +// Regression test for . +// Used to ICE + +fn pretty_print<'r, T: ToProviderRef<'r>>() { + request::() +} +fn request>>() -> R::Output { + unimplemented!() +} +trait RequestWithArg

{ + type Output; +} +impl RequestWithArg

for T +where + P: Tagged, +{ + type Output = (); +} +trait ToProviderRef<'r> { + type ProviderRef: Tagged; +} +trait Tagged { + type Tag; +} +trait Unimplemented {} +impl Tagged for T { + type Tag = (); +} +struct PeanoSucc(N); +impl Tagged for PeanoSucc

+where + P: Tagged, +{ + type Tag = (); +} + +fn main() {} From c301619ff116618632c59f4399d530b86458762f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 11 Sep 2026 10:45:26 +0200 Subject: [PATCH 0203/1309] use proper c_void for '*_' shim signatures --- src/tools/miri/src/eval.rs | 9 ++--- src/tools/miri/src/machine.rs | 33 +++++++++++++++---- src/tools/miri/src/shims/alloc.rs | 8 ++--- src/tools/miri/src/shims/backtrace.rs | 6 ++-- src/tools/miri/src/shims/extern_static.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 24 +++++++------- src/tools/miri/src/shims/sig.rs | 7 ++-- src/tools/miri/src/shims/tls.rs | 8 ++--- src/tools/miri/src/shims/unix/env.rs | 4 +-- .../miri/src/shims/unix/foreign_items.rs | 2 +- src/tools/miri/src/shims/unix/thread.rs | 2 +- .../miri/src/shims/windows/foreign_items.rs | 3 +- .../miri/tests/pass/alloc-access-tracking.rs | 2 +- .../tests/pass/alloc-access-tracking.stderr | 4 +-- src/tools/miri/tests/utils/miri_extern.rs | 14 ++++---- 15 files changed, 76 insertions(+), 52 deletions(-) diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 3ba16971eca84..6e2f300e37ce0 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -458,11 +458,13 @@ fn call_main<'tcx>( // Call start function. match entry_type { MiriEntryFnType::Rustc(EntryFnType::Main { .. }) => { + let entry_sig = tcx.fn_sig(entry_id).no_bound_vars().unwrap(); + let main_ret_ty = entry_sig.output(); + let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); + let start_id = tcx.lang_items().start_fn().unwrap_or_else(|| { tcx.dcx().fatal("could not find start lang item"); }); - let main_ret_ty = tcx.fn_sig(entry_id).no_bound_vars().unwrap().output(); - let main_ret_ty = main_ret_ty.no_bound_vars().unwrap(); let start_instance = ty::Instance::try_resolve( tcx, ecx.typing_env(), @@ -484,8 +486,7 @@ fn call_main<'tcx>( &[ ImmTy::from_scalar( Scalar::from_pointer(main_ptr, ecx), - // FIXME use a proper fn ptr type - ecx.machine.layouts.const_raw_ptr, + ecx.layout_of(Ty::new_fn_ptr(tcx, entry_sig)).unwrap(), ), argc, argv, diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 076738a5db08e..05bb642a62b28 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -433,15 +433,33 @@ pub struct PrimitiveLayouts<'tcx> { pub u128: TyAndLayout<'tcx>, pub usize: TyAndLayout<'tcx>, pub bool: TyAndLayout<'tcx>, - pub mut_raw_ptr: TyAndLayout<'tcx>, // *mut () - pub const_raw_ptr: TyAndLayout<'tcx>, // *const () + pub unit_ptr_mut: TyAndLayout<'tcx>, // *mut () + pub unit_ptr_const: TyAndLayout<'tcx>, // *const () + pub void_ptr_mut: TyAndLayout<'tcx>, // *mut c_void + pub void_ptr_const: TyAndLayout<'tcx>, // *const c_void + pub fn_ptr: TyAndLayout<'tcx>, // extern "C" fn() } impl<'tcx> PrimitiveLayouts<'tcx> { fn new(layout_cx: LayoutCx<'tcx>) -> Result> { let tcx = layout_cx.tcx(); - let mut_raw_ptr = Ty::new_mut_ptr(tcx, tcx.types.unit); - let const_raw_ptr = Ty::new_imm_ptr(tcx, tcx.types.unit); + + let unit_ptr_mut = Ty::new_mut_ptr(tcx, tcx.types.unit); + let unit_ptr_const = Ty::new_imm_ptr(tcx, tcx.types.unit); + // We fall back to `()` if the lang item is missing, so `no_core` works better with Miri. + let c_void = match tcx.lang_items().c_void() { + Some(c_void) => ty::Instance::mono(tcx, c_void).ty(tcx, layout_cx.typing_env), + None => tcx.types.unit, + }; + let void_ptr_mut = Ty::new_mut_ptr(tcx, c_void); + let void_ptr_const = Ty::new_imm_ptr(tcx, c_void); + + let sig_kind = ty::FnSigKind::default() + .set_abi(ExternAbi::C { unwind: false }) + .set_safety(rustc_hir::Safety::Safe); + let fn_ptr = + Ty::new_fn_ptr(tcx, ty::Binder::dummy(tcx.mk_fn_sig([], tcx.types.unit, sig_kind))); + Ok(Self { unit: layout_cx.layout_of(tcx.types.unit)?, i8: layout_cx.layout_of(tcx.types.i8)?, @@ -457,8 +475,11 @@ impl<'tcx> PrimitiveLayouts<'tcx> { u128: layout_cx.layout_of(tcx.types.u128)?, usize: layout_cx.layout_of(tcx.types.usize)?, bool: layout_cx.layout_of(tcx.types.bool)?, - mut_raw_ptr: layout_cx.layout_of(mut_raw_ptr)?, - const_raw_ptr: layout_cx.layout_of(const_raw_ptr)?, + unit_ptr_mut: layout_cx.layout_of(unit_ptr_mut)?, + unit_ptr_const: layout_cx.layout_of(unit_ptr_const)?, + void_ptr_mut: layout_cx.layout_of(void_ptr_mut)?, + void_ptr_const: layout_cx.layout_of(void_ptr_const)?, + fn_ptr: layout_cx.layout_of(fn_ptr)?, }) } diff --git a/src/tools/miri/src/shims/alloc.rs b/src/tools/miri/src/shims/alloc.rs index 7d25163bca065..ba1434b79a5be 100644 --- a/src/tools/miri/src/shims/alloc.rs +++ b/src/tools/miri/src/shims/alloc.rs @@ -124,7 +124,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match method { SpecialAllocatorMethod::Alloc | SpecialAllocatorMethod::AllocZeroed => { let [size, align] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(usize, core::mem::Alignment) -> *_), + shim_sig!(extern "Rust" fn(usize, core::mem::Alignment) -> *()), (link_name, abi, args), )?; let size = this.read_target_usize(size)?; @@ -147,7 +147,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } SpecialAllocatorMethod::Dealloc => { let [ptr, old_size, align] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, usize, core::mem::Alignment) -> ()), + shim_sig!(extern "Rust" fn(*(), usize, core::mem::Alignment) -> ()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -163,7 +163,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } SpecialAllocatorMethod::Realloc => { let [ptr, old_size, align, new_size] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, usize, core::mem::Alignment, usize) -> *_), + shim_sig!(extern "Rust" fn(*(), usize, core::mem::Alignment, usize) -> *()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -203,7 +203,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { size: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); - let memptr = this.deref_pointer_as(memptr, this.machine.layouts.mut_raw_ptr)?; + let memptr = this.deref_pointer_as(memptr, this.machine.layouts.unit_ptr_mut)?; let align = this.read_target_usize(align)?; let size = this.read_target_usize(size)?; diff --git a/src/tools/miri/src/shims/backtrace.rs b/src/tools/miri/src/shims/backtrace.rs index 923a8dedc0591..822ef56a345e3 100644 --- a/src/tools/miri/src/shims/backtrace.rs +++ b/src/tools/miri/src/shims/backtrace.rs @@ -35,11 +35,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { args: &[OpTy<'tcx>], ) -> InterpResult<'tcx> { let this = self.eval_context_mut(); - let ptr_ty = this.machine.layouts.mut_raw_ptr.ty; + let ptr_ty = this.machine.layouts.unit_ptr_mut.ty; let ptr_layout = this.layout_of(ptr_ty)?; let [flags, buf] = this - .check_shim_sig(shim_sig!(extern "Rust" fn(u64, *_) -> ()), (link_name, abi, args))?; + .check_shim_sig(shim_sig!(extern "Rust" fn(u64, *()) -> ()), (link_name, abi, args))?; let flags = this.read_scalar(flags)?.to_u64()?; let buf_place = this.deref_pointer_as(buf, ptr_layout)?; @@ -194,7 +194,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let this = self.eval_context_mut(); let [ptr, flags, name_ptr, filename_ptr] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, u64, *_, *_) -> ()), + shim_sig!(extern "Rust" fn(*(), u64, *(), *()) -> ()), (link_name, abi, args), )?; diff --git a/src/tools/miri/src/shims/extern_static.rs b/src/tools/miri/src/shims/extern_static.rs index 05b4cf01cf982..45fe60599fafb 100644 --- a/src/tools/miri/src/shims/extern_static.rs +++ b/src/tools/miri/src/shims/extern_static.rs @@ -30,7 +30,7 @@ impl<'tcx> MiriMachine<'tcx> { ptr: Pointer, ) -> InterpResult<'tcx> { // Allocate the extra indirection place and add it to the map. - let layout = ecx.machine.layouts.mut_raw_ptr; + let layout = ecx.machine.layouts.unit_ptr_mut; let place = ecx.allocate(layout, MiriMemoryKind::ExternStatic.into())?; ecx.write_scalar(Scalar::from_maybe_pointer(ptr, ecx), &place)?; let weak_ptr = place.ptr().into_pointer_or_addr().unwrap(); diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index aebe0a4d2c836..25c659f7b3ae9 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -324,7 +324,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // Miri-specific extern functions "miri_alloc" => { let [size, align] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(usize, usize) -> *_), + shim_sig!(extern "Rust" fn(usize, usize) -> *()), (link_name, abi, args), )?; let size = this.read_target_usize(size)?; @@ -343,7 +343,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } "miri_dealloc" => { let [ptr, old_size, align] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, usize, usize) -> ()), + shim_sig!(extern "Rust" fn(*(), usize, usize) -> ()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -359,7 +359,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } "miri_track_alloc" => { let [ptr] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_) -> ()), + shim_sig!(extern "Rust" fn(*()) -> ()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -376,8 +376,10 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } } "miri_start_unwind" => { - let [payload] = this - .check_shim_sig(shim_sig!(extern "Rust" fn(*_) -> !), (link_name, abi, args))?; + let [payload] = this.check_shim_sig( + shim_sig!(extern "Rust" fn(*()) -> !), + (link_name, abi, args), + )?; this.handle_miri_start_unwind(payload)?; return interp_ok(EmulateItemResult::NeedsUnwind); } @@ -388,7 +390,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } "miri_get_alloc_id" => { let [ptr] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_) -> u64), + shim_sig!(extern "Rust" fn(*()) -> u64), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -418,7 +420,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { // This associates a name to a tag. Very useful for debugging, and also makes // tests more strict. let [ptr, nth_parent, name] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, u8, &[u8]) -> ()), + shim_sig!(extern "Rust" fn(*(), u8, &[u8]) -> ()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -434,7 +436,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } "miri_static_root" => { let [ptr] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_) -> ()), + shim_sig!(extern "Rust" fn(*()) -> ()), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -448,7 +450,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { } "miri_host_to_target_path" => { let [ptr, out, out_size] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, *_, usize) -> usize), + shim_sig!(extern "Rust" fn(*(), *(), usize) -> usize), (link_name, abi, args), )?; let ptr = this.read_pointer(ptr)?; @@ -468,7 +470,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { "miri_thread_spawn" => { let [start_routine, func_arg] = this.check_shim_sig( // FIXME: The first argument is actually a function pointer. - shim_sig!(extern "Rust" fn(fn(..) -> _, *_) -> usize), + shim_sig!(extern "Rust" fn(fn(..) -> _, *()) -> usize), (link_name, abi, args), )?; let start_routine = this.read_pointer(start_routine)?; @@ -551,7 +553,7 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> { use rustc_abi::AlignFromBytesError; let [ptr, align] = this.check_shim_sig( - shim_sig!(extern "Rust" fn(*_, usize) -> ()), + shim_sig!(extern "Rust" fn(*(), usize) -> ()), (link_name, abi, args), )?; diff --git a/src/tools/miri/src/shims/sig.rs b/src/tools/miri/src/shims/sig.rs index e2e01d8ba0aa7..853f7381ccdf5 100644 --- a/src/tools/miri/src/shims/sig.rs +++ b/src/tools/miri/src/shims/sig.rs @@ -150,9 +150,8 @@ macro_rules! shim_sig_arg { $this.tcx.types.bool }; ($this:ident, *_) => { - // Pointee types usually don't matter so we allow it to be omitted. // Mutability does not matter for ABI. - $this.machine.layouts.mut_raw_ptr.ty + $this.machine.layouts.void_ptr_mut.ty }; ($this:ident, *$($ty:tt)*) => { // Pointee types matter for varargs so we support explicitly giving them. @@ -164,8 +163,8 @@ macro_rules! shim_sig_arg { ) }; ($this:ident, fn(..) -> _) => { - // We currently treat fn ptrs as ABI-compatible with data ptrs so we can just use a raw ptr. - $this.machine.layouts.const_raw_ptr.ty + // All function pointer types are the same on the ABI level so we don't care about arg/ret. + $this.machine.layouts.fn_ptr.ty }; ($this:ident, &[$($ty:tt)*]) => { rustc_middle::ty::Ty::new_ref( diff --git a/src/tools/miri/src/shims/tls.rs b/src/tools/miri/src/shims/tls.rs index b0982a813f393..0444efd0ac62a 100644 --- a/src/tools/miri/src/shims/tls.rs +++ b/src/tools/miri/src/shims/tls.rs @@ -360,7 +360,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // but std treats both the same. let reason = this.eval_windows("c", "DLL_THREAD_DETACH"); let null_ptr = - ImmTy::from_scalar(Scalar::null_ptr(this), this.machine.layouts.const_raw_ptr); + ImmTy::from_scalar(Scalar::null_ptr(this), this.machine.layouts.unit_ptr_const); // The signature of this function is `unsafe extern "system" fn(h: c::LPVOID, dwReason: c::DWORD, pv: c::LPVOID)`. // FIXME: `h` should be a handle to the current module and what `pv` should be is unknown @@ -389,7 +389,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.call_thread_root_function( instance, ExternAbi::C { unwind: false }, - &[ImmTy::from_scalar(data, this.machine.layouts.mut_raw_ptr)], + &[ImmTy::from_scalar(data, this.machine.layouts.unit_ptr_mut)], None, span, )?; @@ -426,7 +426,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.call_thread_root_function( instance, ExternAbi::C { unwind: false }, - &[ImmTy::from_scalar(ptr, this.machine.layouts.mut_raw_ptr)], + &[ImmTy::from_scalar(ptr, this.machine.layouts.unit_ptr_mut)], None, span, )?; @@ -492,7 +492,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.call_thread_root_function( instance, ExternAbi::System { unwind: false }, - &[ImmTy::from_scalar(ptr, this.machine.layouts.mut_raw_ptr)], + &[ImmTy::from_scalar(ptr, this.machine.layouts.unit_ptr_mut)], None, span, )?; diff --git a/src/tools/miri/src/shims/unix/env.rs b/src/tools/miri/src/shims/unix/env.rs index 5098c0490c402..07ad90af0d662 100644 --- a/src/tools/miri/src/shims/unix/env.rs +++ b/src/tools/miri/src/shims/unix/env.rs @@ -44,7 +44,7 @@ impl<'tcx> UnixEnvVars<'tcx> { } // This is memory backing an extern static, hence `ExternStatic`, not `Env`. - let layout = ecx.machine.layouts.mut_raw_ptr; + let layout = ecx.machine.layouts.unit_ptr_mut; let environ = ecx.allocate(layout, MiriMemoryKind::ExternStatic.into())?; let environ_block = alloc_environ_block(ecx, env_vars_machine.values().copied().collect())?; ecx.write_pointer(environ_block, &environ)?; @@ -113,7 +113,7 @@ fn alloc_environ_block<'tcx>( // Make an array with all these pointers inside Miri. let vars_layout = ecx.layout_of(Ty::new_array( *ecx.tcx, - ecx.machine.layouts.mut_raw_ptr.ty, + ecx.machine.layouts.unit_ptr_mut.ty, u64::try_from(vars.len()).unwrap(), ))?; let vars_place = ecx.allocate(vars_layout, MiriMemoryKind::Machine.into())?; diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index e0726a834e0c5..fb019a1f6be31 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -1443,7 +1443,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let pwd = this.deref_pointer_as(pwd, this.libc_ty_layout("passwd"))?; let buf = this.read_pointer(buf)?; let buflen = this.read_target_usize(buflen)?; - let result = this.deref_pointer_as(result, this.machine.layouts.mut_raw_ptr)?; + let result = this.deref_pointer_as(result, this.machine.layouts.unit_ptr_mut)?; // Must be for "us". if uid != UID { diff --git a/src/tools/miri/src/shims/unix/thread.rs b/src/tools/miri/src/shims/unix/thread.rs index 15887477a9a30..4fad7cb901903 100644 --- a/src/tools/miri/src/shims/unix/thread.rs +++ b/src/tools/miri/src/shims/unix/thread.rs @@ -32,7 +32,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { start_routine, ExternAbi::C { unwind: false }, func_arg, - this.machine.layouts.mut_raw_ptr, + this.machine.layouts.unit_ptr_mut, )?; interp_ok(()) diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index 5e8d6ef34327b..bb738621a4ad6 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -916,7 +916,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; let handle = this.read_handle(handle, "GetThreadDescription")?; - let name_ptr = this.deref_pointer_as(name_ptr, this.machine.layouts.mut_raw_ptr)?; // the pointer where we should store the ptr to the name + let name_ptr = + this.deref_pointer_as(name_ptr, this.machine.layouts.unit_ptr_mut)?; // the pointer where we should store the ptr to the name let thread = match handle { Handle::Thread(thread) => thread, diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.rs b/src/tools/miri/tests/pass/alloc-access-tracking.rs index 7774b75d5471b..322a1cc15cdc7 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.rs +++ b/src/tools/miri/tests/pass/alloc-access-tracking.rs @@ -7,7 +7,7 @@ fn main() { unsafe { let mut b = Box::<[u8; 123]>::new_uninit(); let ptr = b.as_mut_ptr() as *mut u8; - utils::miri_track_alloc(ptr); + utils::miri_track_alloc(ptr as *mut ()); *ptr = 42; // Crucially, only a write is printed here, no read! assert_eq!(*ptr, 42); } diff --git a/src/tools/miri/tests/pass/alloc-access-tracking.stderr b/src/tools/miri/tests/pass/alloc-access-tracking.stderr index bcc1d987330ab..4b0bfb1273d6e 100644 --- a/src/tools/miri/tests/pass/alloc-access-tracking.stderr +++ b/src/tools/miri/tests/pass/alloc-access-tracking.stderr @@ -1,8 +1,8 @@ note: now tracking allocation ALLOC of 123 bytes (alignment ALIGN bytes) --> tests/pass/alloc-access-tracking.rs:LL:CC | -LL | utils::miri_track_alloc(ptr); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tracking was triggered here +LL | utils::miri_track_alloc(ptr as *mut ()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ tracking was triggered here note: write access at ALLOC[0x0..0x1] --> tests/pass/alloc-access-tracking.rs:LL:CC diff --git a/src/tools/miri/tests/utils/miri_extern.rs b/src/tools/miri/tests/utils/miri_extern.rs index 3cc4610c6b0a3..fa5c540e4ca97 100644 --- a/src/tools/miri/tests/utils/miri_extern.rs +++ b/src/tools/miri/tests/utils/miri_extern.rs @@ -23,7 +23,7 @@ extern "Rust" { /// considered leaking even if it still exists when the program terminates. /// /// `ptr` has to point to the beginning of an allocated block. - pub fn miri_static_root(ptr: *const u8); + pub fn miri_static_root(ptr: *const ()); // Miri-provided extern function to get the amount of frames in the current backtrace. // The `flags` argument must be `0`. @@ -48,15 +48,15 @@ extern "Rust" { pub fn miri_resolve_frame_names( ptr: *mut (), flags: u64, - name_buf: *mut u8, - filename_buf: *mut u8, + name_buf: *mut (), + filename_buf: *mut (), ); /// Miri-provided extern function to begin unwinding with the given payload. /// /// This is internal and unstable and should not be used; we give it here /// just to be complete. - pub fn miri_start_unwind(payload: *mut u8) -> !; + pub fn miri_start_unwind(payload: *mut ()) -> !; /// Miri-provided extern function to get the internal unique identifier for the allocation that a pointer /// points to. If this pointer is invalid (not pointing to an allocation), interpretation will abort. @@ -114,15 +114,15 @@ extern "Rust" { /// /// This is useful when no fundamental way of allocating memory is /// available, e.g. when using `no_std` + `alloc`. - pub fn miri_alloc(size: usize, align: usize) -> *mut u8; + pub fn miri_alloc(size: usize, align: usize) -> *mut (); /// Miri-provided extern function to deallocate memory. - pub fn miri_dealloc(ptr: *mut u8, size: usize, align: usize); + pub fn miri_dealloc(ptr: *mut (), size: usize, align: usize); /// Add the allocation that this pointer points to to the "tracked" allocations. /// This is equivalent to `-Zmiri-track-allic-id=`, but also works if the ID is /// only known at runtime. - pub fn miri_track_alloc(ptr: *const u8); + pub fn miri_track_alloc(ptr: *const ()); /// Convert a path from the host Miri runs on to the target Miri interprets. /// Performs conversion of path separators as needed. From 2d51648e0e3ffeb3b48d697594557c62f02a385b Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:08:12 +0200 Subject: [PATCH 0204/1309] migrate tests --- tests/source/direct_const_arg.rs | 3 ++- tests/target/direct_const_arg.rs | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/source/direct_const_arg.rs b/tests/source/direct_const_arg.rs index f6f9c25d9a0d8..6486d782cc1f5 100644 --- a/tests/source/direct_const_arg.rs +++ b/tests/source/direct_const_arg.rs @@ -5,7 +5,8 @@ #![feature(min_generic_const_args)] trait Trait { - type const TYPE_CONST: usize; + #[rustc_always_gca] + const TYPE_CONST: usize; } struct S; diff --git a/tests/target/direct_const_arg.rs b/tests/target/direct_const_arg.rs index 1ebadae00ff05..94a6c864b78ef 100644 --- a/tests/target/direct_const_arg.rs +++ b/tests/target/direct_const_arg.rs @@ -5,7 +5,8 @@ #![feature(min_generic_const_args)] trait Trait { - type const TYPE_CONST: usize; + #[rustc_always_gca] + const TYPE_CONST: usize; } struct S; From dbc2785540adb6cff667e86427b8ba7c8fddd67e Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 11 Sep 2026 17:08:12 +0200 Subject: [PATCH 0205/1309] yeet type const --- src/items.rs | 40 +++++++--------------------------------- 1 file changed, 7 insertions(+), 33 deletions(-) diff --git a/src/items.rs b/src/items.rs index 37dc231c3c45a..d561ac6cd3b5c 100644 --- a/src/items.rs +++ b/src/items.rs @@ -2010,11 +2010,7 @@ impl<'a> StaticParts<'a> { ), ast::ItemKind::Const(c) => ( Some(c.defaultness), - if c.kind == ast::ConstItemKind::TypeConst { - "type const" - } else { - "const" - }, + "const", ast::Safety::Default, c.ident, &c.ty, @@ -2039,25 +2035,14 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_trait_item(ti: &'a ast::AssocItem, ident: Ident) -> Self { - let (defaultness, ty, expr_opt, generics, prefix) = match &ti.kind { + let (defaultness, ty, expr_opt, generics) = match &ti.kind { ast::AssocItemKind::Const(c) => { - let prefix = if c.kind == ast::ConstItemKind::TypeConst { - "type const" - } else { - "const" - }; - ( - c.defaultness, - &c.ty, - c.body.as_deref(), - Some(&c.generics), - prefix, - ) + (c.defaultness, &c.ty, c.body.as_deref(), Some(&c.generics)) } _ => unreachable!(), }; StaticParts { - prefix, + prefix: "const", safety: ast::Safety::Default, vis: &ti.vis, ident, @@ -2071,25 +2056,14 @@ impl<'a> StaticParts<'a> { } pub(crate) fn from_impl_item(ii: &'a ast::AssocItem, ident: Ident) -> Self { - let (defaultness, ty, expr_opt, generics, prefix) = match &ii.kind { + let (defaultness, ty, expr_opt, generics) = match &ii.kind { ast::AssocItemKind::Const(c) => { - let prefix = if c.kind == ast::ConstItemKind::TypeConst { - "type const" - } else { - "const" - }; - ( - c.defaultness, - &c.ty, - c.body.as_deref(), - Some(&c.generics), - prefix, - ) + (c.defaultness, &c.ty, c.body.as_deref(), Some(&c.generics)) } _ => unreachable!(), }; StaticParts { - prefix, + prefix: "const", safety: ast::Safety::Default, vis: &ii.vis, ident, From fe4736508d52919f2a87f44b39c65b8fbafbded8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Sep 2026 20:27:57 +0200 Subject: [PATCH 0206/1309] Add the alternatives parts in `Cache::paths` --- src/librustdoc/formats/cache.rs | 54 +++++++++++++++++----- src/librustdoc/html/format.rs | 22 +++++---- src/librustdoc/html/render/context.rs | 12 ++--- src/librustdoc/html/render/print_item.rs | 8 ++-- src/librustdoc/html/render/search_index.rs | 28 +++++++---- src/librustdoc/html/render/write_shared.rs | 17 +++++-- src/librustdoc/json/mod.rs | 10 ++-- 7 files changed, 104 insertions(+), 47 deletions(-) diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index ccee062584e01..3dee84c2f4dc4 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -18,6 +18,27 @@ use crate::formats::item_type::ItemType; use crate::html::render::{IndexItem, IndexItemInfo}; use crate::visit_lib::RustdocEffectiveVisibilities; +pub(crate) struct PathInfo { + /// Parts of the path. So in `foo::bar::bib`, it will be `["foo", "bar", "bib"]`. + pub(crate) parts: Vec, + pub(crate) ty: ItemType, + /// When a reexport inline an item, we can end up with the same `DefId` with multiple local + /// targets. So in case like: + /// + /// ``` + /// /// Link to [`a2`]. + /// pub use std::ffi::os_str::OsString as a1; + /// /// Link to [`a1`]. + /// pub use std::ffi::os_str::OsString as a2; + /// /// Link to [`a2`]. + /// pub use std::ffi::os_str::OsString as a3; + /// ``` + /// + /// To ensure that `a1` and `a2` links to `a1` and `a2` which have the same `DefId`, we need + /// to store both paths. + pub(crate) alternatives: Vec>, +} + /// This cache is used to store information about the [`clean::Crate`] being /// rendered in order to provide more useful documentation. This contains /// information like all implementors of a trait, all traits a type implements, @@ -42,7 +63,7 @@ pub(crate) struct Cache { /// URLs when a type is being linked to. External paths are not located in /// this map because the `External` type itself has all the information /// necessary. - pub(crate) paths: FxIndexMap, ItemType)>, + pub(crate) paths: FxIndexMap, /// Similar to `paths`, but only holds external paths. This is only used for /// generating explicit hyperlinks to other crates. @@ -358,7 +379,8 @@ impl DocFolder for CacheBuilder<'_, '_> { | clean::ForeignTypeItem | clean::MacroItem(..) | clean::ProcMacroItem(..) - | clean::VariantItem(..) => { + | clean::VariantItem(..) + | clean::PrimitiveItem(..) => { use rustc_data_structures::fx::IndexEntry as Entry; let skip_because_unstable = matches!( @@ -376,21 +398,31 @@ impl DocFolder for CacheBuilder<'_, '_> { let item_def_id = item.item_id.expect_def_id(); match self.cache.paths.entry(item_def_id) { Entry::Vacant(entry) => { - entry.insert((self.cache.stack.clone(), item.type_())); + entry.insert(PathInfo { + parts: self.cache.stack.clone(), + ty: item.type_(), + alternatives: Vec::new(), + }); } Entry::Occupied(mut entry) => { - if entry.get().0.len() > self.cache.stack.len() { - entry.insert((self.cache.stack.clone(), item.type_())); + // Shorter paths are preferred by default. + if entry.get().parts.len() > self.cache.stack.len() { + let old_parts = std::mem::replace( + &mut entry.get_mut().parts, + self.cache.stack.clone(), + ); + // We only keep the old path if it's a different (final) name. + if old_parts.last() != self.cache.stack.last() { + entry.get_mut().alternatives.push(old_parts); + } + } + if !entry.get().alternatives.contains(&self.cache.stack) { + entry.get_mut().alternatives.push(self.cache.stack.clone()); } } } } } - clean::PrimitiveItem(..) => { - self.cache - .paths - .insert(item.item_id.expect_def_id(), (self.cache.stack.clone(), item.type_())); - } clean::ExternCrateItem { .. } | clean::ImportItem(..) @@ -570,7 +602,7 @@ fn add_item_to_search_index(tcx: TyCtxt<'_>, cache: &mut Cache, item: &clean::It // in a field of the cache whose elements are added to the search index later, // after cache building is complete (see `handle_orphan_impl_child`). match cache.paths.get(&parent_did) { - Some((fqp, _)) => (Some(parent_did), &fqp[..fqp.len() - 1]), + Some(info) => (Some(parent_did), &info.parts[..info.parts.len() - 1]), None => { handle_orphan_impl_child(cache, item, parent_did); return; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 13fc6e3bc1bb8..07b0f02b7d5b8 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -564,7 +564,7 @@ pub(crate) fn href_with_root_path( } _ => original_did, }; - if is_unnamable(cx.tcx(), did) { + if is_unnamable(tcx, did) { return Err(HrefError::UnnamableItem); } let cache = cx.cache(); @@ -586,12 +586,12 @@ pub(crate) fn href_with_root_path( } let (fqp, shortty, url_parts, is_absolute) = match cache.paths.get(&did) { - Some(&(ref fqp, shortty)) => ( - fqp, - shortty, + Some(info) => ( + &info.parts, + info.ty, { - let module_fqp = to_module_fqp(shortty, fqp.as_slice()); - debug!(?fqp, ?shortty, ?module_fqp); + let module_fqp = to_module_fqp(info.ty, info.parts.as_slice()); + debug!(?info.parts, ?info.ty, ?module_fqp); href_relative_parts(module_fqp, relative_to) }, false, @@ -663,11 +663,15 @@ pub(crate) fn link_tooltip( ) -> impl fmt::Display { fmt::from_fn(move |f| { let cache = cx.cache(); - let Some((fqp, shortty)) = cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) + let Some((fqp, shortty)) = cache + .paths + .get(&did) + .map(|info| (&info.parts, info.ty)) + .or_else(|| cache.external_paths.get(&did).map(|(fqp, shortty)| (fqp, *shortty))) else { return Ok(()); }; - let fqp = if *shortty == ItemType::Primitive { + let fqp = if shortty == ItemType::Primitive { // primitives are documented in a crate, but not actually part of it slice::from_ref(fqp.last().unwrap()) } else { @@ -679,7 +683,7 @@ pub(crate) fn link_tooltip( for component in fqp { write!(f, "{component}::")?; } - if *shortty == ItemType::Enum && tcx.def_kind(id) == DefKind::Field { + if shortty == ItemType::Enum && tcx.def_kind(id) == DefKind::Field { write!(f, "{}::", tcx.item_name(tcx.parent(id)))?; } write!(f, "{}", tcx.item_name(id))?; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index 56dd665177a93..d00b705d3766c 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -296,19 +296,19 @@ impl<'tcx> Context<'tcx> { &self.shared.style_files, ) } else { - if let Some(&(ref names, ty)) = self.cache().paths.get(&it.item_id.expect_def_id()) - && (self.current.len() + 1 != names.len() - || self.current.iter().zip(names.iter()).any(|(a, b)| a != b)) + if let Some(info) = self.cache().paths.get(&it.item_id.expect_def_id()) + && (self.current.len() + 1 != info.parts.len() + || self.current.iter().zip(info.parts.iter()).any(|(a, b)| a != b)) { // We checked that the redirection isn't pointing to the current file, // preventing an infinite redirection loop in the generated // documentation. let path = fmt::from_fn(|f| { - for name in &names[..names.len() - 1] { + for name in &info.parts[..info.parts.len() - 1] { write!(f, "{name}/")?; } - write!(f, "{}", print_ty_path(ty, names.last().unwrap().as_str())) + write!(f, "{}", print_ty_path(info.ty, info.parts.last().unwrap().as_str())) }); match self.shared.redirections { Some(ref redirections) => { @@ -320,7 +320,7 @@ impl<'tcx> Context<'tcx> { let _ = write!( current_path, "{}", - print_ty_path(ty, names.last().unwrap().as_str()) + print_ty_path(info.ty, info.parts.last().unwrap().as_str()) ); redirections.borrow_mut().insert(current_path, path.to_string()); } diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 6f66dcf9eae83..46dba0253766a 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1455,12 +1455,12 @@ fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> // [^115718]: https://github.com/rust-lang/rust/issues/115718 let cache = &cx.shared.cache; if let Some(target_did) = t.type_.def_id(cache) - && let get_extern = { || cache.external_paths.get(&target_did) } - && let Some(&(ref target_fqp, target_type)) = - cache.paths.get(&target_did).or_else(get_extern) + && let get_extern = { || cache.external_paths.get(&target_did).map(|(fqp, shortty)| (fqp, *shortty)) } + && let Some((target_fqp, target_type)) = + cache.paths.get(&target_did).map(|info| (&info.parts, info.ty)).or_else(get_extern) && target_type.is_adt() // primitives cannot be inlined && let Some(self_did) = it.item_id.as_def_id() - && let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) } + && let get_local = { || cache.paths.get(&self_did).map(|info| &info.parts) } && let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local) { let mut js_src_path: UrlPartsBuilder = diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index 4c93e632ab467..b459ead9481cb 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -1279,7 +1279,7 @@ pub(crate) fn build_index( for &OrphanImplItem { impl_id, parent, trait_parent, ref item, ref impl_generics } in &cache.orphan_impl_items { - if let Some((fqp, _)) = cache.paths.get(&parent) { + if let Some(path_info) = cache.paths.get(&parent) { let info = IndexItemInfo::new( tcx, cache, @@ -1291,7 +1291,7 @@ pub(crate) fn build_index( search_index.push(IndexItem { defid: item.item_id.as_def_id(), name: item.name.unwrap(), - module_path: fqp[..fqp.len() - 1].to_vec(), + module_path: path_info.parts[..path_info.parts.len() - 1].to_vec(), parent: Some(parent), parent_idx: None, trait_parent, @@ -1418,8 +1418,15 @@ pub(crate) fn build_index( cache .paths .get(&defid) - .or_else(|| check_external.then(|| cache.external_paths.get(&defid)).flatten()) - .map(|&(ref fqp, ty)| { + .map(|info| (&info.parts, info.ty)) + .or_else(|| { + check_external + .then(|| { + cache.external_paths.get(&defid).map(|(parts, ty)| (parts, *ty)) + }) + .flatten() + }) + .map(|(fqp, ty)| { let pathid = serialized_index.names.len(); match serialized_index.crate_paths_index.entry((ty, fqp.clone())) { Entry::Occupied(entry) => *entry.get(), @@ -1661,8 +1668,10 @@ pub(crate) fn build_index( used_in_function_signature, )), RenderTypeId::DefId(defid) => { - if let Some(&(ref fqp, item_type)) = - paths.get(&defid).or_else(|| external_paths.get(&defid)) + if let Some((fqp, item_type)) = paths + .get(&defid) + .map(|info| (&info.parts, info.ty)) + .or_else(|| external_paths.get(&defid).map(|(parts, ty)| (parts, *ty))) { if tcx.lang_items().fn_mut_trait() == Some(defid) || tcx.lang_items().fn_once_trait() == Some(defid) @@ -1974,8 +1983,11 @@ pub(crate) fn get_function_type_for_search( let impl_or_trait_generics = impl_generics.or_else(|| { if let Some(def_id) = parent && let Some(trait_) = cache.traits.get(&def_id) - && let Some((path, _)) = - cache.paths.get(&def_id).or_else(|| cache.external_paths.get(&def_id)) + && let Some((path, _)) = cache + .paths + .get(&def_id) + .map(|info| (&info.parts, info.ty)) + .or_else(|| cache.external_paths.get(&def_id).map(|(parts, ty)| (parts, *ty))) { let path = clean::Path { res: rustc_hir::def::Res::Def(rustc_hir::def::DefKind::Trait, def_id), diff --git a/src/librustdoc/html/render/write_shared.rs b/src/librustdoc/html/render/write_shared.rs index ab72edacae296..5d0dd8ab899f5 100644 --- a/src/librustdoc/html/render/write_shared.rs +++ b/src/librustdoc/html/render/write_shared.rs @@ -833,12 +833,17 @@ impl TraitAliasPart { // FIXME: this is a vague explanation for why this can't be a `get`, in // theory it should be... let (remote_path, remote_item_type) = match cache.exact_paths.get(&did) { - Some(p) => match cache.paths.get(&did).or_else(|| cache.external_paths.get(&did)) { + Some(p) => match cache + .paths + .get(&did) + .map(|info| (&info.parts, info.ty)) + .or_else(|| cache.external_paths.get(&did).map(|(parts, ty)| (parts, *ty))) + { Some((_, t)) => (p, t), None => continue, }, None => match cache.external_paths.get(&did) { - Some((p, t)) => (p, t), + Some((p, t)) => (p, *t), None => continue, }, }; @@ -986,8 +991,10 @@ impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { return; } let Some(target_did) = t.type_.def_id(cache) else { return }; - let get_extern = { || cache.external_paths.get(&target_did) }; - let Some(&(ref target_fqp, target_type)) = cache.paths.get(&target_did).or_else(get_extern) + let get_extern = + { || cache.external_paths.get(&target_did).map(|(parts, ty)| (parts, *ty)) }; + let Some((target_fqp, target_type)) = + cache.paths.get(&target_did).map(|info| (&info.parts, info.ty)).or_else(get_extern) else { return; }; @@ -1003,7 +1010,7 @@ impl<'item> DocVisitor<'item> for TypeImplCollector<'_, '_, 'item> { .collect(); AliasedType { target_fqp: &target_fqp[..], target_type, impl_ } }); - let get_local = { || cache.paths.get(&self_did).map(|(p, _)| p) }; + let get_local = { || cache.paths.get(&self_did).map(|info| &info.parts) }; let Some(self_fqp) = cache.exact_paths.get(&self_did).or_else(get_local) else { return; }; diff --git a/src/librustdoc/json/mod.rs b/src/librustdoc/json/mod.rs index f161b31f94dcb..bdd2b7d416d80 100644 --- a/src/librustdoc/json/mod.rs +++ b/src/librustdoc/json/mod.rs @@ -113,8 +113,9 @@ impl<'tcx> JsonRenderer<'tcx> { .cache .paths .iter() - .chain(&self.cache.external_paths) - .map(|(&k, &(ref path, kind))| { + .map(|(k, info)| (k, (&info.parts, info.ty))) + .chain(self.cache.external_paths.iter().map(|(k, (parts, ty))| (k, (parts, *ty)))) + .map(|(&k, (path, kind))| { ( self.id_from_item_default(k.into()), types::ItemSummary { @@ -195,8 +196,9 @@ impl<'tcx> JsonRenderer<'tcx> { self.cache .paths .get(&item_id) - .or_else(|| self.cache.external_paths.get(&item_id)) - .map(|(path, _)| path.iter().map(|name| name.to_string()).collect()) + .map(|info| &info.parts) + .or_else(|| self.cache.external_paths.get(&item_id).map(|(parts, _)| parts)) + .map(|path| path.iter().map(|name| name.to_string()).collect()) } } From 3ddd7e4b0a580e028099ed8aaf6b2a0466d6a44b Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 11 Sep 2026 14:50:21 -0400 Subject: [PATCH 0207/1309] adjust docs to latest offload usage --- src/doc/rustc-dev-guide/src/offload/usage.md | 29 ++++---------------- 1 file changed, 6 insertions(+), 23 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md index 77b8935fab837..56a29d723b2d9 100644 --- a/src/doc/rustc-dev-guide/src/offload/usage.md +++ b/src/doc/rustc-dev-guide/src/offload/usage.md @@ -89,38 +89,21 @@ Now we generate the device (GPU) code, passing the manifest: ``` RUSTFLAGS="-Ctarget-cpu=gfx90a --emit=llvm-bc,llvm-ir -Zoffload=Device=/absolute/path/to/offload.manifest -Csave-temps -Zunstable-options" cargo +offload build -Zunstable-options -r -v --target amdgcn-amd-amdhsa -Zbuild-std=core ``` -You might afterwards need to copy your target/release/deps/.bc to lib.bc for now, before the next step. -Now we generate the host (CPU) code. +Next we generate the host (CPU) code. ``` -RUSTFLAGS="--emit=llvm-bc,llvm-ir -Csave-temps -Zoffload=Host=/p/lustre1/drehwald1/prog/offload/r/target/amdgcn-amd-amdhsa/release/deps/device.bin -Zunstable-options" cargo +offload build -r -``` -This call also does a lot of work and generates multiple intermediate files for LLVM offload. -While we integrated most offload steps into rustc by now, one binary invocation still remains for now: - -``` -"clang-linker-wrapper" "--should-extract=gfx90a" "--device-compiler=amdgcn-amd-amdhsa=-g" "--device-compiler=amdgcn-amd-amdhsa=-save-temps=cwd" "--device-linker=amdgcn-amd-amdhsa=-lompdevice" "--host-triple=x86_64-unknown-linux-gnu" "--save-temps" "--linker-path=/ABSOlUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/lld/bin/ld.lld" "--hash-style=gnu" "--eh-frame-hdr" "-m" "elf_x86_64" "-pie" "-dynamic-linker" "/lib64/ld-linux-x86-64.so.2" "-o" "main" "/lib/../lib64/Scrt1.o" "/lib/../lib64/crti.o" "/ABSOLUTE_PATH_TO/crtbeginS.o" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/bin/../lib/x86_64-unknown-linux-gnu" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib/clang/21/lib/x86_64-unknown-linux-gnu" "-L/lib/../lib64" "-L/usr/lib64" "-L/lib" "-L/usr/lib" "target//release/host.o" "-lstdc++" "-lm" "-lomp" "-lomptarget" "-L/ABSOLUTE_PATH_TO/rust/build/x86_64-unknown-linux-gnu/llvm/lib" "-lgcc_s" "-lgcc" "-lpthread" "-lc" "-lgcc_s" "-lgcc" "/ABSOLUTE_PATH_TO/crtendS.o" "/lib/../lib64/crtn.o" -``` - -You can try to find the paths to those files on your system. -However, I recommend to not fix the paths, but rather just re-generate them by copying a bare-mode OpenMP example and compiling it with your clang. -By adding `-###` to your clang invocation, you can see the invidual steps. -It will show multiple steps, just look for the clang-linker-wrapper example. -Make sure to still include the path to the `host.o` file, and not whatever tmp file you got when compiling your c++ example with the following call. -``` -myclang++ -fuse-ld=lld -O3 -fopenmp -fopenmp-offload-mandatory --offload-arch=gfx90a omp_bare.cpp -o main -### +RUSTFLAGS="--emit=llvm-bc,llvm-ir -Csave-temps -Zoffload=Host=$PWD/target/amdgcn-amd-amdhsa/release/deps/device.bin -Zunstable-options" cargo +offload build -r ``` In the final step, you can now run your binary ``` -./main +LD_LIBRARY_PATH=$(rustc +nightly --print sysroot)/lib ./target/x86_64-unknown-linux-gnu/release/binary-name all checks passed! ``` -To receive more information about the memory transfer, you can enable info printing with -``` -LIBOMPTARGET_INFO=-1 ./main -``` +These three steps will soon be wrapped into a single command, once we had more time to test all steps. + +To receive more information about the memory transfer, you can enable info printing by adding `LIBOMPTARGET_INFO=-1` ahead of your binary call. [^list]: https://rocm.docs.amd.com/en/latest/reference/gpu-arch-specs.html or https://developer.nvidia.com/cuda/gpus. Alternatively, check `rustc --print target-cpus`. From 10e1f7e23a485d168da2b80d869bfb1cc6bbdbad Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Fri, 11 Sep 2026 15:01:04 -0400 Subject: [PATCH 0208/1309] adjust docs to latest offload install --- src/doc/rustc-dev-guide/src/offload/installation.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md index ab8e7984d5b4a..3641f20ac4f1a 100644 --- a/src/doc/rustc-dev-guide/src/offload/installation.md +++ b/src/doc/rustc-dev-guide/src/offload/installation.md @@ -3,9 +3,16 @@ `std::offload` is partly available in nightly builds for users. For now, everyone however still needs to build rustc from source to use all features of it. +## Rustup installation. +If you are on `x86_64` Linux, you can install the nightly toolchain with: +```console +rustup +nightly component add offload +``` + + ## Build instructions -First you need to clone and configure the Rust repository: +Otherwise you need to clone and configure the Rust repository: ```console git clone git@github.com:rust-lang/rust cd rust From 3e8ba946769701f7fc912e4b18bdc89aa54e0529 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 12 Sep 2026 00:16:33 -0400 Subject: [PATCH 0209/1309] Remove some code duplication in coerce_shared.rs --- .../src/coherence/builtin/coerce_shared.rs | 25 ++++++------------- 1 file changed, 8 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index bd7130ee48bc8..637075f4822ff 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -400,29 +400,20 @@ fn validate_reborrow_field_access( ) -> Result<(), ErrorGuaranteed> { let module = tcx.parent_module_from_def_id(impl_did); let variant = def.non_enum_variant(); - if variant.field_list_has_applicable_non_exhaustive() { - return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedInaccessibleField { + + if variant.field_list_has_applicable_non_exhaustive() + || variant.fields.iter().any(|f| !f.vis.is_accessible_from(module, tcx)) + { + Err(tcx.dcx().emit_err(diagnostics::CoerceSharedInaccessibleField { span: diagnostic_context.impl_span, type_span: role.type_span(diagnostic_context), trait_name, role: role.as_str(), type_name: tcx.item_name(def.did()), - })); - } - - for field in &variant.fields { - if !field.vis.is_accessible_from(module, tcx) { - return Err(tcx.dcx().emit_err(diagnostics::CoerceSharedInaccessibleField { - span: diagnostic_context.impl_span, - type_span: role.type_span(diagnostic_context), - trait_name, - role: role.as_str(), - type_name: tcx.item_name(def.did()), - })); - } + })) + } else { + Ok(()) } - - Ok(()) } fn validate_coerce_shared_fields<'tcx>( From 46dd39c31f787f51d3ddc894d21fef35a1a82573 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sat, 12 Sep 2026 23:55:17 +0200 Subject: [PATCH 0210/1309] regression test for unconstrained const args --- .../mgca/unconstrained-type-params.rs | 12 ++++++++++++ .../mgca/unconstrained-type-params.stderr | 13 +++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 tests/ui/const-generics/mgca/unconstrained-type-params.rs create mode 100644 tests/ui/const-generics/mgca/unconstrained-type-params.stderr diff --git a/tests/ui/const-generics/mgca/unconstrained-type-params.rs b/tests/ui/const-generics/mgca/unconstrained-type-params.rs new file mode 100644 index 0000000000000..7b9688f53818f --- /dev/null +++ b/tests/ui/const-generics/mgca/unconstrained-type-params.rs @@ -0,0 +1,12 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/146906 + +#![feature(min_generic_const_args)] + +trait Trait {} + +impl Trait for [(); N] {} +//~^ ERROR mismatched types + +fn N(f: impl FnOnce(f64) -> f64 + Trait) {} + +fn main() {} diff --git a/tests/ui/const-generics/mgca/unconstrained-type-params.stderr b/tests/ui/const-generics/mgca/unconstrained-type-params.stderr new file mode 100644 index 0000000000000..da3f64aedb15b --- /dev/null +++ b/tests/ui/const-generics/mgca/unconstrained-type-params.stderr @@ -0,0 +1,13 @@ +error[E0308]: mismatched types + --> $DIR/unconstrained-type-params.rs:7:21 + | +LL | impl Trait for [(); N] {} + | ^ expected `usize`, found fn item + | + = note: expected type `usize` + found fn item `fn(_) {N::<_>}` + = note: array length can only be `usize` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 21646df13d677de5db951f0b7ce90ef9e6113568 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sun, 13 Sep 2026 10:42:01 +0200 Subject: [PATCH 0211/1309] move `needless_borrows_for_generic_args` test case to have a better place to add tests depending on `const_trait_impl` --- .../needless_borrows_for_generic_args.fixed | 0 .../needless_borrows_for_generic_args.rs | 0 .../needless_borrows_for_generic_args.stderr | 22 +++++++++---------- 3 files changed, 11 insertions(+), 11 deletions(-) rename tests/ui/{ => needless_borrows_for_generic_args}/needless_borrows_for_generic_args.fixed (100%) rename tests/ui/{ => needless_borrows_for_generic_args}/needless_borrows_for_generic_args.rs (100%) rename tests/ui/{ => needless_borrows_for_generic_args}/needless_borrows_for_generic_args.stderr (69%) diff --git a/tests/ui/needless_borrows_for_generic_args.fixed b/tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.fixed similarity index 100% rename from tests/ui/needless_borrows_for_generic_args.fixed rename to tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.fixed diff --git a/tests/ui/needless_borrows_for_generic_args.rs b/tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs similarity index 100% rename from tests/ui/needless_borrows_for_generic_args.rs rename to tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs diff --git a/tests/ui/needless_borrows_for_generic_args.stderr b/tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.stderr similarity index 69% rename from tests/ui/needless_borrows_for_generic_args.stderr rename to tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.stderr index 5f7a14ade2617..84f60c2153cc1 100644 --- a/tests/ui/needless_borrows_for_generic_args.stderr +++ b/tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.stderr @@ -1,5 +1,5 @@ error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:16:37 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:16:37 | LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` @@ -8,61 +8,61 @@ LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:18:33 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:18:33 | LL | let _ = Path::new(".").join(&&"."); | ^^^^^ help: change this to: `"."` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:23:33 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:23:33 | LL | let _ = std::fs::write("x", &"".to_string()); | ^^^^^^^^^^^^^^^ help: change this to: `"".to_string()` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:39:27 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:39:27 | LL | deref_target_is_x(&X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:53:30 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:53:30 | LL | multiple_constraints(&[[""]]); | ^^^^^^^ help: change this to: `[[""]]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:74:49 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:74:49 | LL | multiple_constraints_normalizes_to_same(&X, X); | ^^ help: change this to: `X` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:132:24 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:132:24 | LL | takes_iter(&mut x) | ^^^^^^ help: change this to: `x` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:142:41 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:142:41 | LL | let _ = Command::new("ls").args(&["-a", "-l"]).status().unwrap(); | ^^^^^^^^^^^^^ help: change this to: `["-a", "-l"]` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:254:13 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:254:13 | LL | foo(&a); | ^^ help: change this to: `a` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:339:11 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:339:11 | LL | f(&String::new()); // Lint, makes no difference | ^^^^^^^^^^^^^^ help: change this to: `String::new()` error: the borrowed expression implements the required traits - --> tests/ui/needless_borrows_for_generic_args.rs:344:11 + --> tests/ui/needless_borrows_for_generic_args/needless_borrows_for_generic_args.rs:344:11 | LL | f(&"".to_owned()); // Lint | ^^^^^^^^^^^^^^ help: change this to: `"".to_owned()` From 957b2f22e47b1f2dfaf6dd6a096ac42d57610f67 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Sun, 13 Sep 2026 10:51:43 +0200 Subject: [PATCH 0212/1309] add `const_trait_impl` compatability (such as for example the destructor of `Vec`) to not send the old solver into an infinite loop --- .../src/needless_borrows_for_generic_args.rs | 11 +++- .../const_trait_impl.coherence.fixed | 50 +++++++++++++++++++ .../const_trait_impl.coherence.stderr | 23 +++++++++ .../const_trait_impl.globally.fixed | 50 +++++++++++++++++++ .../const_trait_impl.globally.stderr | 23 +++++++++ .../const_trait_impl.no.fixed | 50 +++++++++++++++++++ .../const_trait_impl.no.stderr | 23 +++++++++ .../const_trait_impl.rs | 50 +++++++++++++++++++ 8 files changed, 279 insertions(+), 1 deletion(-) create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.fixed create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.stderr create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.fixed create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.stderr create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.fixed create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.stderr create mode 100644 tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs diff --git a/clippy_lints/src/needless_borrows_for_generic_args.rs b/clippy_lints/src/needless_borrows_for_generic_args.rs index a29c3efe82333..840f915b71beb 100644 --- a/clippy_lints/src/needless_borrows_for_generic_args.rs +++ b/clippy_lints/src/needless_borrows_for_generic_args.rs @@ -184,7 +184,16 @@ fn needless_borrow_count<'tcx>( .instantiate_identity() .skip_norm_wip() .skip_binder(); - let clauses = cx.tcx.param_env(fn_id).caller_bounds().collect::>(); + let in_const_context = cx.tcx.hir_is_inside_const_context(expr.hir_id); + let clauses = cx + .tcx + .param_env(fn_id) + .caller_bounds() + // TODO: remove filter once https://github.com/rust-lang/rust/issues/160895 is in stable + // + // This sends the old trait solver into unbounded recursion for `[const] Destruct` on self-recursive types + .filter(|clause| in_const_context || !matches!(clause.kind().skip_binder(), ClauseKind::HostEffect(_))) + .collect::>(); let projection_predicates = clauses .iter() .filter_map(|clause| { diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.fixed b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.fixed new file mode 100644 index 0000000000000..95573f2ef187c --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.fixed @@ -0,0 +1,50 @@ +//@revisions: no coherence globally +//@[no] compile-flags: -Znext-solver=no +//@[coherence] compile-flags: -Znext-solver=coherence +//@[globally] compile-flags: -Znext-solver=globally + +#![feature(const_trait_impl)] +#![warn(clippy::needless_borrows_for_generic_args)] + +mod main { + pub enum SelfRecursiveEnum { + Array(Vec), + Null, + } + + pub fn recursive_type(value: Option) -> Option { + let predicate = |_: &SelfRecursiveEnum| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + // `[const] FnOnce` never holds for a closure, but that is irrelevant from a non-const context. + pub fn closure_with_const_fn_callee(value: Option) -> Option { + let predicate = |_: &String| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + mod const_trait_impl { + const trait Tr {} + const impl Tr for &u32 {} + impl Tr for u32 {} + + const fn consume(t: T) { + std::mem::forget(t); + } + + // No lint because `u32: [const] Tr` does not hold + const fn in_const_fn() { + consume(&0u32); + } + + // No lint because `u32: [const] Tr` does not hold + const IN_CONST_ITEM: () = consume(&0u32); + + fn in_non_const_fn() { + consume(0u32); + //~^ needless_borrows_for_generic_args + } + } +} diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.stderr b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.stderr new file mode 100644 index 0000000000000..90c38e3e2c4dc --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.coherence.stderr @@ -0,0 +1,23 @@ +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:17:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + | + = note: `-D clippy::needless-borrows-for-generic-args` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:24:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:46:21 + | +LL | consume(&0u32); + | ^^^^^ help: change this to: `0u32` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.fixed b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.fixed new file mode 100644 index 0000000000000..95573f2ef187c --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.fixed @@ -0,0 +1,50 @@ +//@revisions: no coherence globally +//@[no] compile-flags: -Znext-solver=no +//@[coherence] compile-flags: -Znext-solver=coherence +//@[globally] compile-flags: -Znext-solver=globally + +#![feature(const_trait_impl)] +#![warn(clippy::needless_borrows_for_generic_args)] + +mod main { + pub enum SelfRecursiveEnum { + Array(Vec), + Null, + } + + pub fn recursive_type(value: Option) -> Option { + let predicate = |_: &SelfRecursiveEnum| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + // `[const] FnOnce` never holds for a closure, but that is irrelevant from a non-const context. + pub fn closure_with_const_fn_callee(value: Option) -> Option { + let predicate = |_: &String| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + mod const_trait_impl { + const trait Tr {} + const impl Tr for &u32 {} + impl Tr for u32 {} + + const fn consume(t: T) { + std::mem::forget(t); + } + + // No lint because `u32: [const] Tr` does not hold + const fn in_const_fn() { + consume(&0u32); + } + + // No lint because `u32: [const] Tr` does not hold + const IN_CONST_ITEM: () = consume(&0u32); + + fn in_non_const_fn() { + consume(0u32); + //~^ needless_borrows_for_generic_args + } + } +} diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.stderr b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.stderr new file mode 100644 index 0000000000000..90c38e3e2c4dc --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.globally.stderr @@ -0,0 +1,23 @@ +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:17:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + | + = note: `-D clippy::needless-borrows-for-generic-args` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:24:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:46:21 + | +LL | consume(&0u32); + | ^^^^^ help: change this to: `0u32` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.fixed b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.fixed new file mode 100644 index 0000000000000..95573f2ef187c --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.fixed @@ -0,0 +1,50 @@ +//@revisions: no coherence globally +//@[no] compile-flags: -Znext-solver=no +//@[coherence] compile-flags: -Znext-solver=coherence +//@[globally] compile-flags: -Znext-solver=globally + +#![feature(const_trait_impl)] +#![warn(clippy::needless_borrows_for_generic_args)] + +mod main { + pub enum SelfRecursiveEnum { + Array(Vec), + Null, + } + + pub fn recursive_type(value: Option) -> Option { + let predicate = |_: &SelfRecursiveEnum| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + // `[const] FnOnce` never holds for a closure, but that is irrelevant from a non-const context. + pub fn closure_with_const_fn_callee(value: Option) -> Option { + let predicate = |_: &String| true; + value.filter(predicate) + //~^ needless_borrows_for_generic_args + } + + mod const_trait_impl { + const trait Tr {} + const impl Tr for &u32 {} + impl Tr for u32 {} + + const fn consume(t: T) { + std::mem::forget(t); + } + + // No lint because `u32: [const] Tr` does not hold + const fn in_const_fn() { + consume(&0u32); + } + + // No lint because `u32: [const] Tr` does not hold + const IN_CONST_ITEM: () = consume(&0u32); + + fn in_non_const_fn() { + consume(0u32); + //~^ needless_borrows_for_generic_args + } + } +} diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.stderr b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.stderr new file mode 100644 index 0000000000000..90c38e3e2c4dc --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.no.stderr @@ -0,0 +1,23 @@ +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:17:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + | + = note: `-D clippy::needless-borrows-for-generic-args` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::needless_borrows_for_generic_args)]` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:24:22 + | +LL | value.filter(&predicate) + | ^^^^^^^^^^ help: change this to: `predicate` + +error: the borrowed expression implements the required traits + --> tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs:46:21 + | +LL | consume(&0u32); + | ^^^^^ help: change this to: `0u32` + +error: aborting due to 3 previous errors + diff --git a/tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs new file mode 100644 index 0000000000000..0be2cf860d139 --- /dev/null +++ b/tests/ui/needless_borrows_for_generic_args/const_trait_impl.rs @@ -0,0 +1,50 @@ +//@revisions: no coherence globally +//@[no] compile-flags: -Znext-solver=no +//@[coherence] compile-flags: -Znext-solver=coherence +//@[globally] compile-flags: -Znext-solver=globally + +#![feature(const_trait_impl)] +#![warn(clippy::needless_borrows_for_generic_args)] + +mod main { + pub enum SelfRecursiveEnum { + Array(Vec), + Null, + } + + pub fn recursive_type(value: Option) -> Option { + let predicate = |_: &SelfRecursiveEnum| true; + value.filter(&predicate) + //~^ needless_borrows_for_generic_args + } + + // `[const] FnOnce` never holds for a closure, but that is irrelevant from a non-const context. + pub fn closure_with_const_fn_callee(value: Option) -> Option { + let predicate = |_: &String| true; + value.filter(&predicate) + //~^ needless_borrows_for_generic_args + } + + mod const_trait_impl { + const trait Tr {} + const impl Tr for &u32 {} + impl Tr for u32 {} + + const fn consume(t: T) { + std::mem::forget(t); + } + + // No lint because `u32: [const] Tr` does not hold + const fn in_const_fn() { + consume(&0u32); + } + + // No lint because `u32: [const] Tr` does not hold + const IN_CONST_ITEM: () = consume(&0u32); + + fn in_non_const_fn() { + consume(&0u32); + //~^ needless_borrows_for_generic_args + } + } +} From 4c3c97f5aa4a628944df6ff3aa65be6c36c4a639 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sun, 13 Sep 2026 15:15:33 +0100 Subject: [PATCH 0213/1309] std: fix unix socket address panic on a full sun_path linux reports an address length one byte past sockaddr_un when the path fills sun_path without a NUL, which made address() slice out of bounds since e96993c68f6. cap the length at the size of sockaddr_un. --- library/std/src/os/unix/net/addr.rs | 2 ++ library/std/src/os/unix/net/tests.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 3daddc2d34323..dd6e4a690e326 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -123,6 +123,8 @@ impl SocketAddr { .map_or(len, |new_len| (new_len + SUN_PATH_OFFSET) as libc::socklen_t); } + len = len.min(size_of::() as libc::socklen_t); + if len == 0 { // When there is a datagram from unnamed unix socket // linux returns zero bytes of address diff --git a/library/std/src/os/unix/net/tests.rs b/library/std/src/os/unix/net/tests.rs index 9c3119e787b33..4014767461389 100644 --- a/library/std/src/os/unix/net/tests.rs +++ b/library/std/src/os/unix/net/tests.rs @@ -52,6 +52,25 @@ fn sock_addr_without_trailing_nul() { assert_eq!(address.as_pathname(), Some(Path::new("/path/to/socket"))); } +#[test] +#[cfg(any(target_os = "android", target_os = "linux"))] +fn sock_addr_pathname_fills_sun_path() { + use crate::ffi::OsStr; + use crate::os::unix::ffi::OsStrExt; + + let mut addr: libc::sockaddr_un = unsafe { crate::mem::zeroed() }; + addr.sun_family = libc::AF_UNIX as libc::sa_family_t; + let mut path = vec![b'a'; addr.sun_path.len()]; + path[0] = b'/'; + for (dst, &src) in addr.sun_path.iter_mut().zip(&path) { + *dst = src as _; + } + let offset = crate::mem::offset_of!(libc::sockaddr_un, sun_path); + + let address = or_panic!(SocketAddr::from_parts(addr, (offset + path.len() + 1) as _)); + assert_eq!(address.as_pathname(), Some(Path::new(OsStr::from_bytes(&path)))); +} + #[test] #[cfg_attr(target_os = "android", ignore)] // Android SELinux rules prevent creating Unix sockets #[cfg_attr(target_os = "vxworks", ignore = "Unix sockets are not implemented in VxWorks")] From 1629bcdb5da8963de38e6c8eef97fece99b480e6 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Sun, 13 Sep 2026 18:30:48 +0200 Subject: [PATCH 0214/1309] Add useful APIs to `Unique(Arc|Rc)` --- library/alloc/src/rc.rs | 85 +++++++++++++++++++++++++++++++------- library/alloc/src/sync.rs | 86 ++++++++++++++++++++++++++++++++------- 2 files changed, 141 insertions(+), 30 deletions(-) diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index b2afe0b464eb6..eebbf7a5baed5 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -4326,6 +4326,13 @@ impl UniqueRc { pub fn new(value: T) -> Self { Self::new_in(value, Global) } + + /// Like [`new`](Self::new), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn try_new(value: T) -> Result { + Self::try_new_in(value, Global) + } } impl UniqueRc { @@ -4337,8 +4344,8 @@ impl UniqueRc { /// point to the new [`Rc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] // #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] pub fn new_in(value: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_unique(Box::new_in( RcInner { @@ -4353,8 +4360,29 @@ impl UniqueRc { Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc } } - #[cfg(not(no_global_oom_handling))] - fn unwrap_with_allocator(this: Self) -> (T, A) { + /// Like [`new_in`](Self::new_in), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_new_in(value: T, alloc: A) -> Result { + let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( + RcInner { + strong: Cell::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueRc still stays valid. + weak: Cell::new(1), + value, + }, + alloc, + )?); + Ok(Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc }) + } + + /// Consumes the `UniqueRc`, returning its wrapped value and allocator. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn unwrap_with_allocator(this: Self) -> (T, A) { let inner_ptr = this.ptr; let (data_ptr, alloc) = Self::into_raw_with_allocator(this); @@ -4368,6 +4396,13 @@ impl UniqueRc { (val, alloc) } + /// Consumes the `UniqueRc`, returning its wrapped value. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn unwrap(this: Self) -> T { + Self::unwrap_with_allocator(this).0 + } + /// Maps the value in a `UniqueRc`, reusing the allocation if possible. /// /// `f` is called on a reference to the value in the `UniqueRc`, and the result is returned, @@ -4399,11 +4434,10 @@ impl UniqueRc { unsafe { let (ptr, alloc) = UniqueRc::into_raw_with_allocator(this); let value = ptr.read(); - let mut allocation = + let allocation = UniqueRc::from_raw_with_allocator(ptr.cast::>(), alloc); - allocation.write(f(value)); - allocation.assume_init() + UniqueRc::write(allocation, f(value)) } } else { let (val, alloc) = UniqueRc::unwrap_with_allocator(this); @@ -4450,13 +4484,12 @@ impl UniqueRc { unsafe { let (ptr, alloc) = UniqueRc::into_raw_with_allocator(this); let value = ptr.read(); - let mut allocation = UniqueRc::from_raw_with_allocator( + let allocation = UniqueRc::from_raw_with_allocator( ptr.cast::>(), alloc, ); - allocation.write(f(value)?); - try { allocation.assume_init() } + try { UniqueRc::write(allocation, f(value)?) } } } else { let (val, alloc) = UniqueRc::unwrap_with_allocator(this); @@ -4484,7 +4517,6 @@ impl UniqueRc { } } - #[cfg(not(no_global_oom_handling))] fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = ManuallyDrop::new(this); // SAFETY: The copy of the allocator stored in `this` is forgotten @@ -4526,7 +4558,6 @@ impl UniqueRc { unsafe { self.ptr.as_ref() } } - #[cfg(not(no_global_oom_handling))] fn as_ptr(this: &Self) -> *const T { let ptr: *mut RcInner = NonNull::as_ptr(this.ptr); @@ -4537,7 +4568,6 @@ impl UniqueRc { } #[inline] - #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); // SAFETY: Pointer is valid for reads. @@ -4545,7 +4575,6 @@ impl UniqueRc { } #[inline] - #[cfg(not(no_global_oom_handling))] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } } @@ -4567,9 +4596,35 @@ impl UniqueRc { } } -#[cfg(not(no_global_oom_handling))] impl UniqueRc, A> { - unsafe fn assume_init(self) -> UniqueRc { + /// Writes the value and converts to `UniqueRc`. + /// + /// This method converts similarly to [`assume_init`](Self::assume_init) but + /// writes `value` into it before conversion, thus guaranteeing safety. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn write(mut this: Self, value: T) -> UniqueRc { + // SAFETY: Writing initialises the wrapped value. + unsafe { + this.write(value); + this.assume_init() + } + } + + /// Converts to `UniqueRc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub unsafe fn assume_init(self) -> UniqueRc { let (ptr, alloc) = UniqueRc::into_inner_with_allocator(self); // SAFETY: Upheld by caller. unsafe { UniqueRc::from_inner_in(ptr.cast(), alloc) } diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 09a371f94bbb9..343ab05f68bc6 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -4803,6 +4803,13 @@ impl UniqueArc { pub fn new(value: T) -> Self { Self::new_in(value, Global) } + + /// Like [`new`](Self::new), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + pub fn try_new(value: T) -> Result { + Self::try_new_in(value, Global) + } } impl UniqueArc { @@ -4814,8 +4821,8 @@ impl UniqueArc { /// point to the new [`Arc`]. #[cfg(not(no_global_oom_handling))] #[unstable(feature = "unique_rc_arc", issue = "112566")] - #[must_use] // #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] pub fn new_in(data: T, alloc: A) -> Self { let (ptr, alloc) = Box::into_unique(Box::new_in( ArcInner { @@ -4830,8 +4837,29 @@ impl UniqueArc { Self { ptr: ptr.into(), _marker: PhantomData, _marker2: PhantomData, alloc } } - #[cfg(not(no_global_oom_handling))] - fn unwrap_with_allocator(this: Self) -> (T, A) { + /// Like [`new_in`](Self::new_in), but returns an error if the allocation + /// fails, instead of calling [`handle_alloc_error`]. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "32838")] + pub fn try_new_in(data: T, alloc: A) -> Result { + let (ptr, alloc) = Box::into_non_null_with_allocator(Box::try_new_in( + ArcInner { + strong: atomic::AtomicUsize::new(0), + // keep one weak reference so if all the weak pointers that are created are dropped + // the UniqueArc still stays valid. + weak: atomic::AtomicUsize::new(1), + data, + }, + alloc, + )?); + Ok(Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc }) + } + + /// Consumes the `UniqueArc`, returning its wrapped value and allocator. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + // #[unstable(feature = "allocator_api", issue = "32838")] + #[must_use] + pub fn unwrap_with_allocator(this: Self) -> (T, A) { let inner_ptr = this.ptr; let (data_ptr, alloc) = Self::into_raw_with_allocator(this); @@ -4839,11 +4867,19 @@ impl UniqueArc { // We do not use the data inside ever again. let val = unsafe { data_ptr.read() }; + // Drop the strong-weak ref drop(Weak { ptr: inner_ptr, alloc: &alloc }); (val, alloc) } + /// Consumes the `UniqueArc`, returning its wrapped value. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn unwrap(this: Self) -> T { + Self::unwrap_with_allocator(this).0 + } + /// Maps the value in a `UniqueArc`, reusing the allocation if possible. /// /// `f` is called on a reference to the value in the `UniqueArc`, and the result is returned, @@ -4875,11 +4911,10 @@ impl UniqueArc { unsafe { let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); let value = ptr.read(); - let mut allocation = + let allocation = UniqueArc::from_raw_with_allocator(ptr.cast::>(), alloc); - allocation.write(f(value)); - allocation.assume_init() + UniqueArc::write(allocation, f(value)) } } else { let (val, alloc) = UniqueArc::unwrap_with_allocator(this); @@ -4926,13 +4961,12 @@ impl UniqueArc { unsafe { let (ptr, alloc) = UniqueArc::into_raw_with_allocator(this); let value = ptr.read(); - let mut allocation = UniqueArc::from_raw_with_allocator( + let allocation = UniqueArc::from_raw_with_allocator( ptr.cast::>(), alloc, ); - allocation.write(f(value)?); - try { allocation.assume_init() } + try { UniqueArc::write(allocation, f(value)?) } } } else { let (val, alloc) = UniqueArc::unwrap_with_allocator(this); @@ -4960,7 +4994,6 @@ impl UniqueArc { } } - #[cfg(not(no_global_oom_handling))] fn into_raw_with_allocator(this: Self) -> (*const T, A) { let this = ManuallyDrop::new(this); // SAFETY: The copy of the allocator stored in `this` is forgotten @@ -5003,7 +5036,6 @@ impl UniqueArc { unsafe { self.ptr.as_ref() } } - #[cfg(not(no_global_oom_handling))] fn as_ptr(this: &Self) -> *const T { let ptr: *mut ArcInner = NonNull::as_ptr(this.ptr); @@ -5014,7 +5046,6 @@ impl UniqueArc { } #[inline] - #[cfg(not(no_global_oom_handling))] fn into_inner_with_allocator(this: Self) -> (NonNull>, A) { let this = mem::ManuallyDrop::new(this); // SAFETY: Pointer is valid for reads and only read once. @@ -5022,7 +5053,6 @@ impl UniqueArc { } #[inline] - #[cfg(not(no_global_oom_handling))] unsafe fn from_inner_in(ptr: NonNull>, alloc: A) -> Self { Self { ptr, _marker: PhantomData, _marker2: PhantomData, alloc } } @@ -5056,9 +5086,35 @@ impl UniqueArc { } } -#[cfg(not(no_global_oom_handling))] impl UniqueArc, A> { - unsafe fn assume_init(self) -> UniqueArc { + /// Writes the value and converts to `UniqueArc`. + /// + /// This method converts similarly to [`assume_init`](Self::assume_init) but + /// writes `value` into it before conversion, thus guaranteeing safety. + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub fn write(mut this: Self, value: T) -> UniqueArc { + // SAFETY: Writing initialises the wrapped value. + unsafe { + this.write(value); + this.assume_init() + } + } + + /// Converts to `UniqueArc`. + /// + /// # Safety + /// + /// As with [`MaybeUninit::assume_init`], + /// it is up to the caller to guarantee that the value + /// really is in an initialized state. + /// Calling this when the content is not yet fully initialized + /// causes immediate undefined behavior. + /// + /// [`MaybeUninit::assume_init`]: mem::MaybeUninit::assume_init + #[unstable(feature = "unique_rc_arc", issue = "112566")] + #[must_use] + pub unsafe fn assume_init(self) -> UniqueArc { let (ptr, alloc) = UniqueArc::into_inner_with_allocator(self); // SAFETY: Upheld by caller. unsafe { UniqueArc::from_inner_in(ptr.cast(), alloc) } From d3d4a643b95748ceeb9b3a3a212c2ce3800421cc Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Mon, 14 Sep 2026 01:00:39 +0200 Subject: [PATCH 0215/1309] only run `f16` tests when `target_has_reliable_f16` --- library/stdarch/crates/core_arch/Cargo.toml | 3 +++ library/stdarch/crates/core_arch/src/lib.rs | 10 +++++++++- library/stdarch/crates/core_arch/src/x86/avx512fp16.rs | 1 + .../stdarch/crates/core_arch/src/x86_64/avx512fp16.rs | 1 + 4 files changed, 14 insertions(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/Cargo.toml b/library/stdarch/crates/core_arch/Cargo.toml index 670447a2d5a8b..3aa2e8de1043a 100644 --- a/library/stdarch/crates/core_arch/Cargo.toml +++ b/library/stdarch/crates/core_arch/Cargo.toml @@ -26,6 +26,9 @@ stdarch-test = { version = "0.*", path = "../stdarch-test" } [target.'cfg(all(target_arch = "x86_64", target_os = "linux"))'.dev-dependencies] syscalls = { version = "0.6.18", default-features = false } +[lints.rust] +unexpected_cfgs = { level = "warn", check-cfg = ['cfg(target_has_reliable_f16)'] } + [lints.clippy] too_long_first_doc_paragraph = "allow" missing_transmute_annotations = "allow" diff --git a/library/stdarch/crates/core_arch/src/lib.rs b/library/stdarch/crates/core_arch/src/lib.rs index 55163fffedd78..513ecc5e5489d 100644 --- a/library/stdarch/crates/core_arch/src/lib.rs +++ b/library/stdarch/crates/core_arch/src/lib.rs @@ -42,7 +42,15 @@ clflushopt_target_feature, min_adt_const_params )] -#![cfg_attr(test, feature(test, abi_vectorcall, stdarch_internal))] +#![cfg_attr( + test, + feature( + test, + abi_vectorcall, + stdarch_internal, + cfg_target_has_reliable_f16_f128 + ) +)] #![deny(clippy::missing_inline_in_public_items)] #![allow( clippy::identity_op, diff --git a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs index 869f577a55905..d54c222eb7ccf 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx512fp16.rs @@ -16837,6 +16837,7 @@ unsafe extern "llvm-intrinsic" { } #[cfg(test)] +#[cfg(target_has_reliable_f16)] mod tests { use crate::core_arch::assert_eq_const as assert_eq; use crate::core_arch::x86::*; diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs index f8d21e3f9d7fd..5b26fc9f45426 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512fp16.rs @@ -227,6 +227,7 @@ unsafe extern "llvm-intrinsic" { } #[cfg(test)] +#[cfg(target_has_reliable_f16)] mod tests { use crate::core_arch::{x86::*, x86_64::*}; use stdarch_test::simd_test; From 5bf69a211c2d6d93fb7fa74c87ea39edd7f93238 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sun, 13 Sep 2026 14:46:47 -0400 Subject: [PATCH 0216/1309] Enable triagebot relabelling --- library/stdarch/triagebot.toml | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/library/stdarch/triagebot.toml b/library/stdarch/triagebot.toml index 5b178f0cdf456..149646aa65f01 100644 --- a/library/stdarch/triagebot.toml +++ b/library/stdarch/triagebot.toml @@ -1,3 +1,35 @@ +[relabel] +allow-unauthenticated = [ + "A-*", + "B-*", + "C-*", + "D-*", + "E-*", + "F-*", + "I-*", + "L-*", + "NLL-*", + "O-*", + "PG-*", + "S-*", + "T-*", + "WG-*", + "-Z*", + "beta-nominated", + "CI-spurious-*", + "const-hack", + "llvm-*", + "needs-fcp", + "relnotes", + "release-blog-post", + "requires-*", + "regression-*", + "rla-*", + "perf-*", + "AsyncAwait-OnDeck", + "needs-triage", + "has-merge-commits",] + [assign] [assign.owners] From 7e374726d3525ca7f27138fd5c4e13d42e697d2e Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 14 Sep 2026 04:26:47 +0000 Subject: [PATCH 0217/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 4b6d04e706108ccfeafe2547fbe857dfe8972bad. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 18fea436747c7..f7d3ea0b9325b 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -32d94cc9be3f6e6c3fa1deaea9e0ab93c4980dba +4b6d04e706108ccfeafe2547fbe857dfe8972bad From a451894bab5c27e8a30175e3a49070f4712ddbb4 Mon Sep 17 00:00:00 2001 From: ywxt Date: Mon, 14 Sep 2026 13:44:48 +0800 Subject: [PATCH 0218/1309] add case mapping fast paths for Latin-1 --- library/core/src/unicode/unicode_data.rs | 25 ++++++++ library/coretests/benches/char/methods.rs | 58 +++++++++++++++++-- .../src/case_mapping.rs | 25 ++++++++ src/tools/unicode-table-generator/src/main.rs | 2 +- 4 files changed, 103 insertions(+), 7 deletions(-) diff --git a/library/core/src/unicode/unicode_data.rs b/library/core/src/unicode/unicode_data.rs index ca3a276b89d90..5ca61155ddca7 100644 --- a/library/core/src/unicode/unicode_data.rs +++ b/library/core/src/unicode/unicode_data.rs @@ -1042,6 +1042,17 @@ pub mod conversions { return [c.to_ascii_lowercase(), '\0', '\0']; } + // The rest of Latin-1: À..=Þ (except ×) add 0x20, everything else maps to itself. + if c <= '\u{FF}' { + return match c { + '\u{C0}'..='\u{DE}' if c != '\u{D7}' => { + // SAFETY: U+00C0..=U+00DE plus 0x20 lands in U+00E0..=U+00FE. + [unsafe { char::from_u32_unchecked(c as u32 + 0x20) }, '\0', '\0'] + } + _ => [c, '\0', '\0'], + }; + } + lookup(c, &LOWERCASE_LUT).unwrap_or([c, '\0', '\0']) } @@ -1050,6 +1061,20 @@ pub mod conversions { if c < '\u{B5}' { return [c.to_ascii_uppercase(), '\0', '\0']; } + // The rest of Latin-1: µ maps to U+039C, ß expands to SS, + // à..=þ (except ÷) subtract 0x20, ÿ maps to U+0178. + if c <= '\u{FF}' { + return match c { + '\u{B5}' => ['\u{39C}', '\0', '\0'], + '\u{DF}' => ['S', 'S', '\0'], + '\u{E0}'..='\u{FE}' if c != '\u{F7}' => { + // SAFETY: U+00E0..=U+00FE minus 0x20 lands in U+00C0..=U+00DE. + [unsafe { char::from_u32_unchecked(c as u32 - 0x20) }, '\0', '\0'] + } + '\u{FF}' => ['\u{178}', '\0', '\0'], + _ => [c, '\0', '\0'], + }; + } lookup(c, &UPPERCASE_LUT).unwrap_or([c, '\0', '\0']) } diff --git a/library/coretests/benches/char/methods.rs b/library/coretests/benches/char/methods.rs index ed71920a4fc2a..5363205b01943 100644 --- a/library/coretests/benches/char/methods.rs +++ b/library/coretests/benches/char/methods.rs @@ -49,41 +49,87 @@ fn bench_to_ascii_lowercase(b: &mut Bencher) { #[bench] fn bench_ascii_mix_to_uppercase(b: &mut Bencher) { b.iter(|| { - (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + (0..=255) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_uppercase())) + .count() }) } #[bench] fn bench_ascii_mix_to_lowercase(b: &mut Bencher) { b.iter(|| { - (0..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + (0..=255) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_lowercase())) + .count() }) } #[bench] fn bench_ascii_char_to_uppercase(b: &mut Bencher) { b.iter(|| { - (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + (0..=127) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_uppercase())) + .count() }) } #[bench] fn bench_ascii_char_to_lowercase(b: &mut Bencher) { b.iter(|| { - (0..=127).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + (0..=127) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_lowercase())) + .count() }) } #[bench] fn bench_non_ascii_char_to_uppercase(b: &mut Bencher) { b.iter(|| { - (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_uppercase()).count() + (128..=255) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_uppercase())) + .count() }) } #[bench] fn bench_non_ascii_char_to_lowercase(b: &mut Bencher) { b.iter(|| { - (128..=255).cycle().take(10_000).map(|b| black_box(char::from(b)).to_lowercase()).count() + (128..=255) + .cycle() + .take(10_000) + .map(|b| black_box(black_box(char::from(b)).to_lowercase())) + .count() + }) +} + +#[bench] +fn bench_non_latin1_char_to_uppercase(b: &mut Bencher) { + b.iter(|| { + ('\u{100}'..='\u{4ff}') + .cycle() + .take(10_000) + .map(|c| black_box(black_box(c).to_uppercase())) + .count() + }) +} + +#[bench] +fn bench_non_latin1_char_to_lowercase(b: &mut Bencher) { + b.iter(|| { + ('\u{100}'..='\u{4ff}') + .cycle() + .take(10_000) + .map(|c| black_box(black_box(c).to_lowercase())) + .count() }) } diff --git a/src/tools/unicode-table-generator/src/case_mapping.rs b/src/tools/unicode-table-generator/src/case_mapping.rs index 9336eaf670e6a..0dace342bfa36 100644 --- a/src/tools/unicode-table-generator/src/case_mapping.rs +++ b/src/tools/unicode-table-generator/src/case_mapping.rs @@ -398,6 +398,17 @@ pub fn to_lower(c: char) -> [char; 3] { return [c.to_ascii_lowercase(), '\0', '\0']; } + // The rest of Latin-1: À..=Þ (except ×) add 0x20, everything else maps to itself. + if c <= '\u{FF}' { + return match c { + '\u{C0}'..='\u{DE}' if c != '\u{D7}' => { + // SAFETY: U+00C0..=U+00DE plus 0x20 lands in U+00E0..=U+00FE. + [unsafe { char::from_u32_unchecked(c as u32 + 0x20) }, '\0', '\0'] + } + _ => [c, '\0', '\0'], + }; + } + lookup(c, &LOWERCASE_LUT).unwrap_or([c, '\0', '\0']) } @@ -406,6 +417,20 @@ pub fn to_upper(c: char) -> [char; 3] { if c < '\u{B5}' { return [c.to_ascii_uppercase(), '\0', '\0']; } + // The rest of Latin-1: µ maps to U+039C, ß expands to SS, + // à..=þ (except ÷) subtract 0x20, ÿ maps to U+0178. + if c <= '\u{FF}' { + return match c { + '\u{B5}' => ['\u{39C}', '\0', '\0'], + '\u{DF}' => ['S', 'S', '\0'], + '\u{E0}'..='\u{FE}' if c != '\u{F7}' => { + // SAFETY: U+00E0..=U+00FE minus 0x20 lands in U+00C0..=U+00DE. + [unsafe { char::from_u32_unchecked(c as u32 - 0x20) }, '\0', '\0'] + } + '\u{FF}' => ['\u{178}', '\0', '\0'], + _ => [c, '\0', '\0'], + }; + } lookup(c, &UPPERCASE_LUT).unwrap_or([c, '\0', '\0']) } diff --git a/src/tools/unicode-table-generator/src/main.rs b/src/tools/unicode-table-generator/src/main.rs index 8f7fa4cc56606..9a98aec0b5aba 100644 --- a/src/tools/unicode-table-generator/src/main.rs +++ b/src/tools/unicode-table-generator/src/main.rs @@ -447,7 +447,7 @@ fn generate_tests(data: &UnicodeData) -> String { let mut out = String::from( "\ //! This file is generated by `./x run src/tools/unicode-table-generator`; do not edit manually! -// ignore-tidy-filelength +// ignore-tidy-file-filelength use std::ops::RangeInclusive; ", From e1cff5b3b14a18656c708524b7f023dc9351a0eb Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Mon, 24 Aug 2026 01:27:19 -0500 Subject: [PATCH 0219/1309] install lldb on `aarch64-gnu-llvm-21` --- .../docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile | 5 +++++ src/ci/run.sh | 6 +++++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile b/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile index c364ac27aaa52..fe6c2d40f5f5c 100644 --- a/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile +++ b/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile @@ -17,6 +17,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ gdb \ llvm-21-tools \ llvm-21-dev \ + lldb-21 \ + python3-lldb-21 \ libedit-dev \ libssl-dev \ pkg-config \ @@ -40,6 +42,9 @@ RUN sh /scripts/sccache.sh ENV NO_DOWNLOAD_CI_LLVM="1" ENV EXTERNAL_LLVM="1" +# Override the default debugger `discover` behavior +ENV LLDB_PATH="lldb-21" + # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS="--build=aarch64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-21 \ diff --git a/src/ci/run.sh b/src/ci/run.sh index 353a8d368d54a..8607b294eb1e0 100755 --- a/src/ci/run.sh +++ b/src/ci/run.sh @@ -143,7 +143,11 @@ else # Enable GDB/LLDB automatic discovery on CI # Ideally, we should later change this to provide the paths explicitly RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.gdb=discover" - RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.lldb=discover" + if [ -n "$LLDB_PATH" ]; then + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.lldb=$LLDB_PATH" + else + RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set build.lldb=discover" + fi # We almost always want debug assertions enabled, but sometimes this takes too # long for too little benefit, so we just turn them off. From e12a74eb003f592528efdd92a43c917a1153e471 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Mon, 24 Aug 2026 01:27:32 -0500 Subject: [PATCH 0220/1309] don't fail if type changes don't break providers --- src/etc/debugger_tester/common.py | 3 +- src/etc/debugger_tester/lldb/check_lldb.py | 33 ++++++++++++++-------- 2 files changed, 23 insertions(+), 13 deletions(-) diff --git a/src/etc/debugger_tester/common.py b/src/etc/debugger_tester/common.py index 69e4f646f23d3..cf6fe3b3b63e5 100644 --- a/src/etc/debugger_tester/common.py +++ b/src/etc/debugger_tester/common.py @@ -319,8 +319,7 @@ def print_field_errors(self, expected: "Type", error_source: str): elif types_match and names_match: reordered = "\n ".join( ( - f"{m[1].name} offset: +{m[1].offset} -> {m[0].name} offset: \n\ -+{m[0].offset}" + f"{m[1].name} offset: +{m[1].offset} -> {m[0].name} offset: +{m[0].offset}" ) for m in mismatches ) diff --git a/src/etc/debugger_tester/lldb/check_lldb.py b/src/etc/debugger_tester/lldb/check_lldb.py index 698513ffc1793..554f29a892991 100644 --- a/src/etc/debugger_tester/lldb/check_lldb.py +++ b/src/etc/debugger_tester/lldb/check_lldb.py @@ -207,24 +207,30 @@ def var_matches(var: Variable, expected: Variable, valobj: lldb.SBValue) -> Resu type_ok = var.type == expected.type + all_providers_ok = ( + summary_ok & synthetic_ok & format_ok & pretty_type_name_ok & pretty_print_ok + ) + if var.has_visualizer() or expected.has_visualizer(): type_match_ok = type_matches( - valobj.GetType(), - valobj.GetTarget(), - summary_ok - & synthetic_ok - & format_ok - & pretty_type_name_ok - & pretty_print_ok, + valobj.GetType(), valobj.GetTarget(), all_providers_ok ) else: type_match_ok = Result.Ok + # (small hack) If the type information doesn't match, BUT it doesn't affect the synthetics, we + # don't actually care that much. This prevents CI from failing when 2 different targets use 2 + # different layouts, e.g.:: + # x86_64-linux-gnu: `Vec { buf, len, marker}` + # aarch64-linux-gnu: `Vec {len, buf, marker}` + if type_match_ok == Result.Mismatch and all_providers_ok: + type_match_ok = Result.Ok + value_ok = var.value == expected.value work_list = [valobj.GetChildAtIndex(i) for i in range(valobj.GetNumChildren())] target = valobj.GetTarget() - child_types_ok = True + child_types_ok = Result.Ok while len(work_list) != 0: obj = work_list.pop() @@ -237,12 +243,17 @@ def var_matches(var: Variable, expected: Variable, valobj: lldb.SBValue) -> Resu if child.IsValid(): work_list.append(child) else: - child_types_ok = False + child_types_ok = Result.Mismatch if var.has_visualizer() or expected.has_visualizer(): - child_types_ok &= type_matches(obj.GetType(), target) == Result.Ok + child_types_ok &= type_matches(obj.GetType(), target) + + # similar to type matching, we don't actually care if there's a mismatch if the + # providers aren't affected. + if child_types_ok == Result.Mismatch and all_providers_ok: + child_types_ok = Result.Ok else: - type_match_ok = Result.Ok + child_types_ok = Result.Ok children_ok = children_match( var.children, expected.children, valobj.GetName(), valobj From ebff12b6980fc65de1826fb39a11825a7f65e754 Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 14 Sep 2026 11:06:57 +0330 Subject: [PATCH 0221/1309] Add regression test for first token source file from TokenStream FromStr --- .../auxiliary/span-first-token-file-48944.rs | 13 +++++++++++++ tests/ui/proc-macro/span-first-token-file-48944.rs | 13 +++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs create mode 100644 tests/ui/proc-macro/span-first-token-file-48944.rs diff --git a/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs b/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs new file mode 100644 index 0000000000000..562bd99fdcc72 --- /dev/null +++ b/tests/ui/proc-macro/auxiliary/span-first-token-file-48944.rs @@ -0,0 +1,13 @@ +extern crate proc_macro; + +use proc_macro::TokenStream; + +// Parses a multi-token string with `FromStr` and checks that every token reports the same +// source file. The first token used to get a different file than the rest. +#[proc_macro] +pub fn check_first_token_file(_: TokenStream) -> TokenStream { + let tokens: Vec<_> = "aaa\nbbb".parse::().unwrap().into_iter().collect(); + assert_eq!(tokens.len(), 2); + assert_eq!(tokens[0].span().file(), tokens[1].span().file()); + TokenStream::new() +} diff --git a/tests/ui/proc-macro/span-first-token-file-48944.rs b/tests/ui/proc-macro/span-first-token-file-48944.rs new file mode 100644 index 0000000000000..b65109a81f107 --- /dev/null +++ b/tests/ui/proc-macro/span-first-token-file-48944.rs @@ -0,0 +1,13 @@ +//! Regression test for . +//! +//! The first token parsed from a string with `FromStr` for `TokenStream` used to report a +//! different source file than the tokens after it. + +//@ check-pass +//@ proc-macro: span-first-token-file-48944.rs + +extern crate span_first_token_file_48944; + +span_first_token_file_48944::check_first_token_file!(); + +fn main() {} From 8b691497dd8e0702b2f0c60c37ee3210c2418a4f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 11:04:03 +0200 Subject: [PATCH 0222/1309] Use clap to parse arguments in `stdarch-gen-hexagon` --- library/stdarch/Cargo.lock | 1 + .../crates/stdarch-gen-common/src/lib.rs | 3 ++- .../crates/stdarch-gen-hexagon/Cargo.toml | 1 + .../crates/stdarch-gen-hexagon/src/main.rs | 27 ++++++++++++------- 4 files changed, 22 insertions(+), 10 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 9ec3227f49e7d..5a1f6148ecc71 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -826,6 +826,7 @@ dependencies = [ name = "stdarch-gen-hexagon" version = "0.1.0" dependencies = [ + "clap", "regex", "stdarch-gen-common", ] diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index 13d788594ca55..f825712fcef6e 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -13,7 +13,7 @@ use std::path::{Path, PathBuf}; pub const GENERATED_MARKER: &str = "// This code is automatically generated. DO NOT MODIFY."; /// Controls what `run_generator` does with the generator's output. -#[derive(Debug, Clone, Copy, PartialEq, Eq)] +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] pub enum Mode { /// Verify that the `committed` matches the generator's output for owned files. /// @@ -26,6 +26,7 @@ pub enum Mode { /// into `committed`. If the generator no longer produces an owned file, the /// committed copy is deleted. Files in `committed` that are not owned /// are left untouched. + #[default] Bless, } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml index c7dfce2c0fd7b..7d457868398ac 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-hexagon/Cargo.toml @@ -6,5 +6,6 @@ license = "MIT OR Apache-2.0" edition = "2021" [dependencies] +clap = { version = "4", features = ["derive", "env"] } regex = "1.10" stdarch-gen-common = { path = "../stdarch-gen-common" } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs index 88ef4fe11f332..98da03b4fcfb5 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs @@ -1,18 +1,27 @@ -//! Hexagon code generator. -//! -//! Single binary that produces every generated file under -//! `core_arch/src/hexagon/`: scalar.rs (scalar intrinsics) and -//! v64.rs / v128.rs (HVX intrinsics). -//! -//! Run in check or bless mode via `STDARCH_GEN_MODE`. - mod hvx; mod scalar; +use clap::Parser; use std::path::PathBuf; use stdarch_gen_common::{run_generator, Mode}; +/// Hexagon code generator. +/// +/// Produces every generated file under +/// `core_arch/src/hexagon/`: scalar.rs (scalar intrinsics) and +/// v64.rs / v128.rs (HVX intrinsics). +/// +/// Run in check or bless mode via `STDARCH_GEN_MODE`. +#[derive(clap::Parser)] +struct Args { + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, +} + fn main() -> Result<(), String> { + let args = Args::parse(); + let crate_dir = std::env::var("CARGO_MANIFEST_DIR") .map(PathBuf::from) .unwrap_or_else(|_| std::env::current_dir().unwrap()); @@ -20,7 +29,7 @@ fn main() -> Result<(), String> { let hexagon_dir = crate_dir.join("../core_arch/src/hexagon"); // Either "check" to check the output versus the committed output, or "bless" // to update the output. - let mode = Mode::from_env(); + let mode = args.mode.unwrap_or_default(); run_generator(&hexagon_dir, mode, |out_dir| -> Result<(), String> { // Here scalar::generate writes scalar.rs . From d4056727a00dcdba290303cb33eb2ae7415db5db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 11:19:12 +0200 Subject: [PATCH 0223/1309] Automatically reformat all generated files with a unified rustfmt config --- .../crates/stdarch-gen-common/src/lib.rs | 71 ++++++++++++++++++- .../crates/stdarch-gen-hexagon/src/hvx.rs | 37 ++++------ .../crates/stdarch-gen-hexagon/src/main.rs | 9 ++- .../crates/stdarch-gen-hexagon/src/scalar.rs | 36 +++------- library/stdarch/rustfmt.toml | 2 + 5 files changed, 102 insertions(+), 53 deletions(-) diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index f825712fcef6e..5308296d8588a 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -6,6 +6,8 @@ use std::fs; use std::io; use std::io::Read; use std::path::{Path, PathBuf}; +use std::process::{Command, Stdio}; +use std::str::FromStr; /// First-line marker identifying an auto-generated file. Generators emit this /// as the first line of every file they produce; the harness uses it to @@ -48,6 +50,20 @@ impl Mode { } } +impl FromStr for Mode { + type Err = String; + + fn from_str(s: &str) -> std::result::Result { + match s { + "check" => Ok(Mode::Check), + "bless" => Ok(Mode::Bless), + other => Err(format!( + "unknown stdarch generation mode: {other:?}. Possible values are `check` or `bless`." + )), + } + } +} + #[derive(Debug)] pub enum Error { Io(io::Error), @@ -103,6 +119,18 @@ impl From for Error { pub type Result = std::result::Result; +pub struct GeneratorCtx { + rustfmt_path: PathBuf, +} + +impl GeneratorCtx { + pub fn new(rustfmt_path: Option) -> Self { + Self { + rustfmt_path: rustfmt_path.unwrap_or_else(|| PathBuf::from("rustfmt")), + } + } +} + /// Run a generator under the chosen `mode`, reconciling its output with `committed`. /// /// Arguments: @@ -121,7 +149,12 @@ pub type Result = std::result::Result; /// - [`Mode::Bless`]: runs the generator into a temp dir and copies owned /// files into `committed`, or removes `committed`'s copy if the generator no /// longer produces them. -pub fn run_generator(committed: &Path, mode: Mode, generate: F) -> Result<()> +pub fn run_generator( + ctx: &GeneratorCtx, + committed: &Path, + mode: Mode, + generate: F, +) -> Result<()> where F: FnOnce(&Path) -> std::result::Result<(), E>, E: Into>, @@ -132,6 +165,14 @@ where let owned = discover_owned(committed)?; let produced = discover_all(scratch.path())?; + // Format all generated Rust files + for file in &produced { + let fullpath = scratch.path().join(file); + if fullpath.extension().and_then(|s| s.to_str()) == Some("rs") { + reformat_file(ctx, &fullpath)?; + } + } + let mut names: Vec<&String> = owned.iter().chain(produced.iter()).collect(); names.sort(); names.dedup(); @@ -145,6 +186,34 @@ where Ok(()) } +fn reformat_file(ctx: &GeneratorCtx, path: &Path) -> std::io::Result<()> { + let file = std::fs::File::open(path)?; + let proc = Command::new(&ctx.rustfmt_path) + // Ensure that rustfmt config files in other directories won't interfere with the formatting + // This is important for usage within the rust-lang/rust repository + .arg("--config-path") + .arg( + Path::new(env!("CARGO_MANIFEST_DIR")) + .parent() + .unwrap() + .parent() + .unwrap() + .join("rustfmt.toml"), + ) + .stdin(Stdio::from(file)) + .stdout(Stdio::piped()) + .spawn()?; + + let output = proc.wait_with_output()?; + if !output.status.success() { + panic!( + "Running {:?} on {path:?} failed with exit code {:?}", + ctx.rustfmt_path, output.status + ); + } + std::fs::write(path, output.stdout) +} + /// Returns the names of files in `dir` whose first line begins with /// [`GENERATED_MARKER`]. Files without the marker are skipped. fn discover_owned(dir: &Path) -> Result> { diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs index 537c59bbce861..95c77ae4700a4 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/hvx.rs @@ -19,7 +19,7 @@ use regex::Regex; use std::collections::{HashMap, HashSet}; use std::fs::File; -use std::io::Write; +use std::io::{BufWriter, Write}; use std::path::Path; use stdarch_gen_common::GENERATED_MARKER; @@ -1606,30 +1606,16 @@ fn generate_module_file( intrinsics: &[IntrinsicInfo], output_path: &Path, mode: VectorMode, -) -> Result<(), String> { - let mut output = - File::create(output_path).map_err(|e| format!("Failed to create output: {}", e))?; - - writeln!(output, "{}", GENERATED_MARKER).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_module_doc(mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_types(mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_extern_block(intrinsics, mode)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_functions(intrinsics)).map_err(|e| e.to_string())?; - - // Ensure file is flushed before running rustfmt - drop(output); - - // Run rustfmt on the generated file - let status = std::process::Command::new("rustfmt") - .arg(output_path) - .status() - .map_err(|e| format!("Failed to run rustfmt: {}", e))?; - - if !status.success() { - return Err("rustfmt failed".to_string()); - } +) -> std::io::Result<()> { + let mut output = BufWriter::new(File::create(output_path)?); - Ok(()) + writeln!(output, "{}", GENERATED_MARKER)?; + writeln!(output, "{}", generate_module_doc(mode))?; + writeln!(output, "{}", generate_types(mode))?; + writeln!(output, "{}", generate_extern_block(intrinsics, mode))?; + writeln!(output, "{}", generate_functions(intrinsics))?; + + output.flush() } /// Parse the HVX header in `crate_dir` and write `v64.rs` and `v128.rs` into `out_dir`. @@ -1642,7 +1628,8 @@ pub fn generate(crate_dir: &std::path::Path, out_dir: &std::path::Path) -> Resul .collect(); for (filename, vmode) in [("v64.rs", VectorMode::V64), ("v128.rs", VectorMode::V128)] { let path = out_dir.join(filename); - generate_module_file(&intrinsics, &path, vmode)?; + generate_module_file(&intrinsics, &path, vmode) + .map_err(|e| format!("Cannot generate {path:?}: {e:?}"))?; } Ok(()) } diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs index 98da03b4fcfb5..1e23e993ef918 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/main.rs @@ -3,7 +3,7 @@ mod scalar; use clap::Parser; use std::path::PathBuf; -use stdarch_gen_common::{run_generator, Mode}; +use stdarch_gen_common::{run_generator, GeneratorCtx, Mode}; /// Hexagon code generator. /// @@ -17,6 +17,10 @@ struct Args { /// Generation mode. #[arg(long, env = "STDARCH_GEN_MODE")] mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, } fn main() -> Result<(), String> { @@ -30,8 +34,9 @@ fn main() -> Result<(), String> { // Either "check" to check the output versus the committed output, or "bless" // to update the output. let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); - run_generator(&hexagon_dir, mode, |out_dir| -> Result<(), String> { + run_generator(&ctx, &hexagon_dir, mode, |out_dir| -> Result<(), String> { // Here scalar::generate writes scalar.rs . scalar::generate(&crate_dir, out_dir)?; // Here hvx::generate writes v64.rs and v128.rs . diff --git a/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs b/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs index 2a64798d097d1..8c7880b58a023 100644 --- a/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs +++ b/library/stdarch/crates/stdarch-gen-hexagon/src/scalar.rs @@ -19,7 +19,7 @@ use regex::Regex; use std::collections::HashMap; use std::fs::File; -use std::io::Write; +use std::io::{BufWriter, Write}; use std::path::Path; use stdarch_gen_common::GENERATED_MARKER; @@ -627,30 +627,16 @@ fn generate_functions(intrinsics: &[ScalarIntrinsic]) -> String { } /// Generate the complete scalar.rs file -fn generate_scalar_file(intrinsics: &[ScalarIntrinsic], output_path: &Path) -> Result<(), String> { - let mut output = - File::create(output_path).map_err(|e| format!("Failed to create output: {}", e))?; - - writeln!(output, "{}", GENERATED_MARKER).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_module_doc()).map_err(|e| e.to_string())?; - writeln!(output, "").map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_extern_block(intrinsics)).map_err(|e| e.to_string())?; - writeln!(output, "{}", generate_functions(intrinsics)).map_err(|e| e.to_string())?; - - // Flush before running rustfmt - drop(output); - - // Run rustfmt on the generated file - let status = std::process::Command::new("rustfmt") - .arg(output_path) - .status() - .map_err(|e| format!("Failed to run rustfmt: {}", e))?; - - if !status.success() { - return Err("rustfmt failed".to_string()); - } +fn generate_scalar_file(intrinsics: &[ScalarIntrinsic], output_path: &Path) -> std::io::Result<()> { + let mut output = BufWriter::new(File::create(output_path)?); - Ok(()) + writeln!(output, "{}", GENERATED_MARKER)?; + writeln!(output, "{}", generate_module_doc())?; + writeln!(output, "")?; + writeln!(output, "{}", generate_extern_block(intrinsics))?; + writeln!(output, "{}", generate_functions(intrinsics))?; + + output.flush() } /// Parse the scalar header in `crate_dir` and write `scalar.rs` into `out_dir`. @@ -659,6 +645,6 @@ pub fn generate(crate_dir: &std::path::Path, out_dir: &std::path::Path) -> Resul let intrinsics = parse_header(&header_content); std::fs::create_dir_all(out_dir).map_err(|e| e.to_string())?; let scalar_path = out_dir.join("scalar.rs"); - generate_scalar_file(&intrinsics, &scalar_path)?; + generate_scalar_file(&intrinsics, &scalar_path).map_err(|e| e.to_string())?; Ok(()) } diff --git a/library/stdarch/rustfmt.toml b/library/stdarch/rustfmt.toml index e69de29bb2d1d..3dd85bb2defbf 100644 --- a/library/stdarch/rustfmt.toml +++ b/library/stdarch/rustfmt.toml @@ -0,0 +1,2 @@ +# Ensure that we generate the same file contents on both Linux and Windows. +newline_style = "Unix" From d0f689751bccaea01f3aeab772ba97150a853cb7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 11:40:35 +0200 Subject: [PATCH 0224/1309] Use rustfmt formatting in stdarch-gen-loongarch --- library/stdarch/.github/workflows/main.yml | 537 +++++++++--------- library/stdarch/Cargo.lock | 1 + .../src/loongarch64/lasx/generated.rs | 194 ++++++- .../src/loongarch64/lsx/generated.rs | 130 ++++- .../crates/stdarch-gen-loongarch/Cargo.toml | 1 + .../crates/stdarch-gen-loongarch/src/main.rs | 102 ++-- 6 files changed, 609 insertions(+), 356 deletions(-) diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 5c2e2ae4a8e21..754f01d399117 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -8,208 +8,208 @@ jobs: name: Check Style runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: ci/style.sh + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: ci/style.sh docs: name: Build Documentation - needs: [style] + needs: [ style ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: ci/dox.sh - env: - CI: 1 + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: ci/dox.sh + env: + CI: 1 verify: name: Automatic intrinsic verification - needs: [style] + needs: [ style ] runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly --no-self-update && rustup default nightly - - run: cargo test --manifest-path crates/stdarch-verify/Cargo.toml + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly --no-self-update && rustup default nightly + - run: cargo test --manifest-path crates/stdarch-verify/Cargo.toml test: - needs: [style] + needs: [ style ] name: Test runs-on: ${{ matrix.target.os }} strategy: matrix: profile: - - dev - - release + - dev + - release target: - # Dockers that are run through docker on linux - - tuple: i686-unknown-linux-gnu - os: ubuntu-latest - - tuple: x86_64-unknown-linux-gnu - os: ubuntu-latest - - tuple: arm-unknown-linux-gnueabihf - os: ubuntu-latest - - tuple: armv7-unknown-linux-gnueabihf - os: ubuntu-latest - - tuple: aarch64-unknown-linux-gnu - os: ubuntu-latest - - tuple: aarch64_be-unknown-linux-gnu - os: ubuntu-latest - - tuple: riscv32gc-unknown-linux-gnu - os: ubuntu-latest - - tuple: riscv64gc-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc64-unknown-linux-gnu - os: ubuntu-latest - - tuple: powerpc64le-unknown-linux-gnu - os: ubuntu-latest - # MIPS targets disabled since they are dropped to tier 3. - # See https://github.com/rust-lang/compiler-team/issues/648 - #- tuple: mips-unknown-linux-gnu - # os: ubuntu-latest - #- tuple: mips64-unknown-linux-gnuabi64 - # os: ubuntu-latest - #- tuple: mips64el-unknown-linux-gnuabi64 - # os: ubuntu-latest - #- tuple: mipsel-unknown-linux-musl - # os: ubuntu-latest - - tuple: s390x-unknown-linux-gnu - os: ubuntu-latest - - tuple: i586-unknown-linux-gnu - os: ubuntu-latest - - tuple: nvptx64-nvidia-cuda - os: ubuntu-latest - - tuple: amdgcn-amd-amdhsa - os: ubuntu-latest - - tuple: thumbv6m-none-eabi - os: ubuntu-latest - - tuple: thumbv7m-none-eabi - os: ubuntu-latest - - tuple: thumbv7em-none-eabi - os: ubuntu-latest - - tuple: thumbv7em-none-eabihf - os: ubuntu-latest - - tuple: loongarch64-unknown-linux-gnu - os: ubuntu-latest - # hexagon doesn't build at the moment due to a libc issue. - # - tuple: hexagon-unknown-linux-musl - # os: ubuntu-latest - - tuple: wasm32-wasip1 - os: ubuntu-latest - - # macOS targets - - tuple: x86_64-apple-darwin - os: macos-15-intel - - tuple: x86_64-apple-ios-macabi - os: macos-15-intel - - tuple: aarch64-apple-darwin - os: macos-15 - - tuple: aarch64-apple-ios-macabi - os: macos-15 - # FIXME: gh-actions build environment doesn't have linker support - # - tuple: i686-apple-darwin - # os: macos-13 - - # Windows targets - - tuple: x86_64-pc-windows-msvc - os: windows-2025 - - tuple: i686-pc-windows-msvc - os: windows-2025 - - tuple: aarch64-pc-windows-msvc - os: windows-11-arm - - tuple: arm64ec-pc-windows-msvc - os: windows-11-arm - - tuple: x86_64-pc-windows-gnu - os: windows-2025 - # - tuple: i686-pc-windows-gnu - # os: windows-latest - - # Add additional variables to the matrix variations generated above using `include`: - include: - # `TEST_EVERYTHING` setups - there should be at least 1 for each architecture - - target: - tuple: aarch64-unknown-linux-gnu + # Dockers that are run through docker on linux + - tuple: i686-unknown-linux-gnu + os: ubuntu-latest + - tuple: x86_64-unknown-linux-gnu + os: ubuntu-latest + - tuple: arm-unknown-linux-gnueabihf + os: ubuntu-latest + - tuple: armv7-unknown-linux-gnueabihf + os: ubuntu-latest + - tuple: aarch64-unknown-linux-gnu + os: ubuntu-latest + - tuple: aarch64_be-unknown-linux-gnu + os: ubuntu-latest + - tuple: riscv32gc-unknown-linux-gnu + os: ubuntu-latest + - tuple: riscv64gc-unknown-linux-gnu + os: ubuntu-latest + - tuple: powerpc-unknown-linux-gnu + os: ubuntu-latest + - tuple: powerpc64-unknown-linux-gnu + os: ubuntu-latest + - tuple: powerpc64le-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: aarch64_be-unknown-linux-gnu + # MIPS targets disabled since they are dropped to tier 3. + # See https://github.com/rust-lang/compiler-team/issues/648 + #- tuple: mips-unknown-linux-gnu + # os: ubuntu-latest + #- tuple: mips64-unknown-linux-gnuabi64 + # os: ubuntu-latest + #- tuple: mips64el-unknown-linux-gnuabi64 + # os: ubuntu-latest + #- tuple: mipsel-unknown-linux-musl + # os: ubuntu-latest + - tuple: s390x-unknown-linux-gnu os: ubuntu-latest - test_everything: true - build_std: true - - target: - tuple: armv7-unknown-linux-gnueabihf + - tuple: i586-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: loongarch64-unknown-linux-gnu + - tuple: nvptx64-nvidia-cuda os: ubuntu-latest - test_everything: true - - target: - tuple: powerpc-unknown-linux-gnu + - tuple: amdgcn-amd-amdhsa os: ubuntu-latest - disable_assert_instr: true - test_everything: true - - target: - tuple: powerpc64-unknown-linux-gnu + - tuple: thumbv6m-none-eabi os: ubuntu-latest - disable_assert_instr: true - test_everything: true - - target: - tuple: powerpc64le-unknown-linux-gnu + - tuple: thumbv7m-none-eabi os: ubuntu-latest - test_everything: true - - target: - tuple: riscv32gc-unknown-linux-gnu + - tuple: thumbv7em-none-eabi os: ubuntu-latest - test_everything: true - build_std: true - - target: - tuple: riscv64gc-unknown-linux-gnu + - tuple: thumbv7em-none-eabihf os: ubuntu-latest - test_everything: true - - target: - tuple: s390x-unknown-linux-gnu + - tuple: loongarch64-unknown-linux-gnu os: ubuntu-latest - test_everything: true - - target: - tuple: x86_64-unknown-linux-gnu + # hexagon doesn't build at the moment due to a libc issue. + # - tuple: hexagon-unknown-linux-musl + # os: ubuntu-latest + - tuple: wasm32-wasip1 os: ubuntu-latest - test_everything: true - # MIPS targets disabled since they are dropped to tier 3. - # See https://github.com/rust-lang/compiler-team/issues/648 - #- target: - # tuple: mips-unknown-linux-gnu - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mips64-unknown-linux-gnuabi64 - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mips64el-unknown-linux-gnuabi64 - # os: ubuntu-latest - # norun: true - #- target: - # tuple: mipsel-unknown-linux-musl - # os: ubuntu-latest - # norun: true - - target: - tuple: aarch64-apple-darwin + + # macOS targets + - tuple: x86_64-apple-darwin + os: macos-15-intel + - tuple: x86_64-apple-ios-macabi + os: macos-15-intel + - tuple: aarch64-apple-darwin os: macos-15 - norun: true # https://github.com/rust-lang/stdarch/issues/1206 - - target: - tuple: aarch64-apple-ios-macabi + - tuple: aarch64-apple-ios-macabi os: macos-15 - norun: true # https://github.com/rust-lang/stdarch/issues/1206 - - target: - tuple: amdgcn-amd-amdhsa - os: ubuntu-latest - norun: true + # FIXME: gh-actions build environment doesn't have linker support + # - tuple: i686-apple-darwin + # os: macos-13 + + # Windows targets + - tuple: x86_64-pc-windows-msvc + os: windows-2025 + - tuple: i686-pc-windows-msvc + os: windows-2025 + - tuple: aarch64-pc-windows-msvc + os: windows-11-arm + - tuple: arm64ec-pc-windows-msvc + os: windows-11-arm + - tuple: x86_64-pc-windows-gnu + os: windows-2025 + # - tuple: i686-pc-windows-gnu + # os: windows-latest + + # Add additional variables to the matrix variations generated above using `include`: + include: + # `TEST_EVERYTHING` setups - there should be at least 1 for each architecture + - target: + tuple: aarch64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: aarch64_be-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + build_std: true + - target: + tuple: armv7-unknown-linux-gnueabihf + os: ubuntu-latest + test_everything: true + - target: + tuple: loongarch64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: powerpc-unknown-linux-gnu + os: ubuntu-latest + disable_assert_instr: true + test_everything: true + - target: + tuple: powerpc64-unknown-linux-gnu + os: ubuntu-latest + disable_assert_instr: true + test_everything: true + - target: + tuple: powerpc64le-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: riscv32gc-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + build_std: true + - target: + tuple: riscv64gc-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: s390x-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + - target: + tuple: x86_64-unknown-linux-gnu + os: ubuntu-latest + test_everything: true + # MIPS targets disabled since they are dropped to tier 3. + # See https://github.com/rust-lang/compiler-team/issues/648 + #- target: + # tuple: mips-unknown-linux-gnu + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mips64-unknown-linux-gnuabi64 + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mips64el-unknown-linux-gnuabi64 + # os: ubuntu-latest + # norun: true + #- target: + # tuple: mipsel-unknown-linux-musl + # os: ubuntu-latest + # norun: true + - target: + tuple: aarch64-apple-darwin + os: macos-15 + norun: true # https://github.com/rust-lang/stdarch/issues/1206 + - target: + tuple: aarch64-apple-ios-macabi + os: macos-15 + norun: true # https://github.com/rust-lang/stdarch/issues/1206 + - target: + tuple: amdgcn-amd-amdhsa + os: ubuntu-latest + norun: true # hexagon doesn't build at the moment due to a libc issue. # - target: # tuple: hexagon-unknown-linux-musl @@ -218,59 +218,59 @@ jobs: # build_std: true steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - shell: bash + - uses: actions/checkout@v6 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + shell: bash - - run: rustup target add ${{ matrix.target.tuple }} - shell: bash - if: matrix.build_std == '' && matrix.target.tuple != 'amdgcn-amd-amdhsa' - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV - shell: bash - if: matrix.build_std != '' - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=core,alloc" >> $GITHUB_ENV - shell: bash - if: matrix.target.tuple == 'amdgcn-amd-amdhsa' + - run: rustup target add ${{ matrix.target.tuple }} + shell: bash + if: matrix.build_std == '' && matrix.target.tuple != 'amdgcn-amd-amdhsa' + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV + shell: bash + if: matrix.build_std != '' + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=core,alloc" >> $GITHUB_ENV + shell: bash + if: matrix.target.tuple == 'amdgcn-amd-amdhsa' - # Configure some env vars based on matrix configuration - - run: echo "PROFILE=${{matrix.profile}}" >> $GITHUB_ENV - shell: bash - - run: echo "NORUN=1" >> $GITHUB_ENV - shell: bash - if: matrix.norun != '' || startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' - - run: echo "STDARCH_TEST_EVERYTHING=1" >> $GITHUB_ENV - shell: bash - if: matrix.test_everything != '' - - run: echo "STDARCH_DISABLE_ASSERT_INSTR=1" >> $GITHUB_ENV - shell: bash - if: matrix.disable_assert_instr != '' - - run: echo "NOSTD=1" >> $GITHUB_ENV - shell: bash - if: startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' || matrix.target.tuple == 'amdgcn-amd-amdhsa' + # Configure some env vars based on matrix configuration + - run: echo "PROFILE=${{matrix.profile}}" >> $GITHUB_ENV + shell: bash + - run: echo "NORUN=1" >> $GITHUB_ENV + shell: bash + if: matrix.norun != '' || startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' + - run: echo "STDARCH_TEST_EVERYTHING=1" >> $GITHUB_ENV + shell: bash + if: matrix.test_everything != '' + - run: echo "STDARCH_DISABLE_ASSERT_INSTR=1" >> $GITHUB_ENV + shell: bash + if: matrix.disable_assert_instr != '' + - run: echo "NOSTD=1" >> $GITHUB_ENV + shell: bash + if: startsWith(matrix.target.tuple, 'thumb') || matrix.target.tuple == 'nvptx64-nvidia-cuda' || matrix.target.tuple == 'amdgcn-amd-amdhsa' - # Windows & OSX go straight to `run.sh` ... - - run: ./ci/run.sh - shell: bash - if: matrix.target.os != 'ubuntu-latest' || startsWith(matrix.target.tuple, 'thumb') - env: - TARGET: ${{ matrix.target.tuple }} + # Windows & OSX go straight to `run.sh` ... + - run: ./ci/run.sh + shell: bash + if: matrix.target.os != 'ubuntu-latest' || startsWith(matrix.target.tuple, 'thumb') + env: + TARGET: ${{ matrix.target.tuple }} - # ... while Linux goes to `run-docker.sh` - - run: ./ci/run-docker.sh ${{ matrix.target.tuple }} - shell: bash - if: matrix.target.os == 'ubuntu-latest' && !startsWith(matrix.target.tuple, 'thumb') - env: - TARGET: ${{ matrix.target.tuple }} + # ... while Linux goes to `run-docker.sh` + - run: ./ci/run-docker.sh ${{ matrix.target.tuple }} + shell: bash + if: matrix.target.os == 'ubuntu-latest' && !startsWith(matrix.target.tuple, 'thumb') + env: + TARGET: ${{ matrix.target.tuple }} intrinsic-test: - needs: [style] + needs: [ style ] name: Intrinsic Test runs-on: ubuntu-latest strategy: @@ -280,8 +280,8 @@ jobs: - aarch64_be-unknown-linux-gnu - armv7-unknown-linux-gnueabihf - x86_64-unknown-linux-gnu - profile: [dev, release] - cc: [clang, gcc] + profile: [ dev, release ] + cc: [ clang, gcc ] include: - target: aarch64_be-unknown-linux-gnu build_std: true @@ -295,74 +295,71 @@ jobs: - target: armv7-unknown-linux-gnueabihf cc: gcc steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: | - rustup update nightly --no-self-update - rustup default nightly - - run: rustup target add ${{ matrix.target }} - if: ${{ (matrix.build_std || false) == false }} - - run: | - rustup component add rust-src - echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV - if: ${{ matrix.build_std }} - - run: rustup component add rustfmt + - uses: actions/checkout@v6 + - name: Install Rust + run: | + rustup update nightly --no-self-update + rustup default nightly + - run: rustup target add ${{ matrix.target }} + if: ${{ (matrix.build_std || false) == false }} + - run: | + rustup component add rust-src + echo "CARGO_UNSTABLE_BUILD_STD=std" >> $GITHUB_ENV + if: ${{ matrix.build_std }} + - run: rustup component add rustfmt - # Configure some env vars based on matrix configuration - - run: echo "PROFILE=${{ matrix.profile }}" >> $GITHUB_ENV - - run: ./ci/intrinsic-test-docker.sh ${{ matrix.target }} ${{ matrix.cc }} - if: ${{ !startsWith(matrix.target, 'thumb') }} - env: - TARGET: ${{ matrix.target }} + # Configure some env vars based on matrix configuration + - run: echo "PROFILE=${{ matrix.profile }}" >> $GITHUB_ENV + - run: ./ci/intrinsic-test-docker.sh ${{ matrix.target }} ${{ matrix.cc }} + if: ${{ !startsWith(matrix.target, 'thumb') }} + env: + TARGET: ${{ matrix.target }} # Check that the generated files agree with the checked-in versions. check-stdarch-gen: - needs: [style] + needs: [ style ] name: Check stdarch-gen-{arm, loongarch, hexagon} output runs-on: ubuntu-latest env: STDARCH_GEN_MODE: check steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly && rustup default nightly && rustup component add rustfmt - - name: Check arm spec - run: | - cargo run --bin=stdarch-gen-arm --release -- crates/stdarch-gen-arm/spec - - name: Check loongarch lsx - run: | - cargo run -p stdarch-gen-loongarch --release -- lsx - git diff --exit-code - - name: Check loongarch lasx - run: | - cargo run -p stdarch-gen-loongarch --release -- lasx - git diff --exit-code - - name: Check hexagon - run: | - cargo run -p stdarch-gen-hexagon --release - git diff --exit-code - + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly && rustup default nightly && rustup component add rustfmt + - name: Check arm spec + run: | + cargo run --bin=stdarch-gen-arm --release -- crates/stdarch-gen-arm/spec + - name: Check loongarch lsx + run: | + cargo run -p stdarch-gen-loongarch --release -- lsx + - name: Check loongarch lasx + run: | + cargo run -p stdarch-gen-loongarch --release -- lasx + - name: Check hexagon + run: | + cargo run -p stdarch-gen-hexagon --release + # Run some tests with Miri. Most stdarch functions use platform-specific intrinsics # that Miri does not support. Also Miri is reltively slow. # # Below we run some tests where Miri might catch UB, for instance on intrinsics that read from # or write to pointers. miri: - needs: [style] + needs: [ style ] name: Run some tests with miri runs-on: ubuntu-latest steps: - - uses: actions/checkout@v6 - - name: Install Rust - run: rustup update nightly && rustup default nightly && rustup component add miri - - name: Run miri tests - env: - TARGET: "aarch64-unknown-linux-gnu" - RUSTFLAGS: "-Ctarget-cpu=neoverse-v3" - run: | - # read filters and join them with a space. - FILTERS=$(cat aarch64-miri-tests.txt | tr '\n' ' ') - cargo miri test -p core_arch --target aarch64-unknown-linux-gnu -- $FILTERS + - uses: actions/checkout@v6 + - name: Install Rust + run: rustup update nightly && rustup default nightly && rustup component add miri + - name: Run miri tests + env: + TARGET: "aarch64-unknown-linux-gnu" + RUSTFLAGS: "-Ctarget-cpu=neoverse-v3" + run: | + # read filters and join them with a space. + FILTERS=$(cat aarch64-miri-tests.txt | tr '\n' ' ') + cargo miri test -p core_arch --target aarch64-unknown-linux-gnu -- $FILTERS conclusion: needs: diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 5a1f6148ecc71..6510b00da9b52 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -835,6 +835,7 @@ dependencies = [ name = "stdarch-gen-loongarch" version = "0.1.0" dependencies = [ + "clap", "rand 0.9.4", "stdarch-gen-common", ] diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs index f481a159eb632..cfc4aced34173 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lasx/generated.rs @@ -6,8 +6,8 @@ // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen-loongarch -- crates/stdarch-gen-loongarch/lasx.spec // ``` -use crate::mem::transmute; use super::super::*; +use crate::mem::transmute; #[allow(improper_ctypes)] unsafe extern "llvm-intrinsic" { @@ -3033,168 +3033,312 @@ pub fn lasx_xvhsubw_qu_du(a: m256i, b: m256i) -> m256i { #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_du(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_wu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_hu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_bu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_du(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_wu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_hu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_bu(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_q_du_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_d_wu_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_w_hu_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwev_h_bu_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwev_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwev_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_q_du_d(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_d_wu_w(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_w_hu_h(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lasx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lasx_xvmaddwod_h_bu_b(a: m256i, b: m256i, c: m256i) -> m256i { - unsafe { transmute(__lasx_xvmaddwod_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lasx_xvmaddwod_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] diff --git a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs index 7915ef07d68e7..aa4e31ce8da6c 100644 --- a/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs +++ b/library/stdarch/crates/core_arch/src/loongarch64/lsx/generated.rs @@ -6,8 +6,8 @@ // OUT_DIR=`pwd`/crates/core_arch cargo run -p stdarch-gen-loongarch -- crates/stdarch-gen-loongarch/lsx.spec // ``` -use crate::mem::transmute; use super::super::*; +use crate::mem::transmute; #[allow(improper_ctypes)] unsafe extern "llvm-intrinsic" { @@ -2747,21 +2747,39 @@ pub fn lsx_vmaddwev_h_b(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_d_wu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_w_hu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_h_bu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] @@ -2789,63 +2807,117 @@ pub fn lsx_vmaddwod_h_b(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_d_wu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_d_wu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_d_wu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_w_hu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_w_hu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_w_hu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_h_bu(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_h_bu(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_h_bu( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_d_wu_w(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_w_hu_h(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_h_bu_b(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_d_wu_w(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_d_wu_w(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_d_wu_w( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_w_hu_h(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_w_hu_h(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_w_hu_h( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_h_bu_b(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_h_bu_b(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_h_bu_b( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] @@ -2866,28 +2938,52 @@ pub fn lsx_vmaddwod_q_d(a: m128i, b: m128i, c: m128i) -> m128i { #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_q_du(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_q_du(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_q_du(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_q_du( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwev_q_du_d(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwev_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwev_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] #[target_feature(enable = "lsx")] #[unstable(feature = "stdarch_loongarch", issue = "117427")] pub fn lsx_vmaddwod_q_du_d(a: m128i, b: m128i, c: m128i) -> m128i { - unsafe { transmute(__lsx_vmaddwod_q_du_d(transmute(a), transmute(b), transmute(c))) } + unsafe { + transmute(__lsx_vmaddwod_q_du_d( + transmute(a), + transmute(b), + transmute(c), + )) + } } #[inline] diff --git a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml index a9ddc123b3688..d174b844b430a 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-loongarch/Cargo.toml @@ -7,5 +7,6 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4", features = ["derive", "env"] } rand = "0.9.3" stdarch-gen-common = { path = "../stdarch-gen-common" } diff --git a/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs b/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs index 86fa8956e6ed1..1fed0b96f9426 100644 --- a/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-loongarch/src/main.rs @@ -1,3 +1,4 @@ +use clap::Parser; use std::collections::HashSet; use std::env; use std::fmt; @@ -6,7 +7,7 @@ use std::io::prelude::*; use std::io::{self, BufReader}; use std::path::Path; use std::path::PathBuf; -use stdarch_gen_common::{Mode, run_generator}; +use stdarch_gen_common::{GeneratorCtx, Mode, run_generator}; /// Complete lines of generated source. /// @@ -1602,51 +1603,64 @@ static void {current_name}(void) /// Runs the check/bless harness for `lsx`/`lasx` when invoked with /// no args or a bare ext name. +#[derive(clap::Parser, Debug)] +struct Args { + /// Either: + /// - The extension (lsx/lasx) to generate, or: + /// - A path to a intrin.h file to generate the spec file from. Optionally followed + /// by "test". + arguments: Vec, + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, +} + pub fn main() -> Result<(), String> { - let args: Vec = env::args().collect(); - let arg_strs: Vec<&str> = args.iter().map(String::as_str).collect(); - let harness_exts: Option<&[&str]> = match arg_strs.as_slice() { - [_] => Some(&["lsx", "lasx"]), - [_, "lsx"] => Some(&["lsx"]), - [_, "lasx"] => Some(&["lasx"]), - _ => None, - }; - if let Some(exts) = harness_exts { - let crate_dir = - PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); - let core_arch_src = crate_dir.join("../core_arch/src"); - let mode = Mode::from_env(); - for ext in exts { - let spec_rel = format!("crates/stdarch-gen-loongarch/{ext}.spec"); - let committed = core_arch_src.join("loongarch64").join(ext); - run_generator(&committed, mode, |out_dir| { - gen_bind(&spec_rel, ext, out_dir) - }) - .map_err(|e| e.to_string())?; - } - return Ok(()); - } + let args = Args::parse(); + + let crate_dir = + PathBuf::from(env::var("CARGO_MANIFEST_DIR").expect("CARGO_MANIFEST_DIR not set")); + let core_arch_src = crate_dir.join("../core_arch/src"); + let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); - let in_file = args[1].clone(); - let in_file_name = PathBuf::from(&in_file) - .file_name() - .unwrap() - .to_string_lossy() - .into_owned(); - let ext_name = if in_file_name.starts_with("lasx") { - "lasx" + let arguments = &args.arguments; + if arguments.len() == 1 && (arguments[0] == "lsx" || arguments[0] == "lasx") { + let extension = arguments[0].as_str(); + let spec_rel = format!("crates/stdarch-gen-loongarch/{extension}.spec"); + let committed = core_arch_src.join("loongarch64").join(extension); + run_generator(&ctx, &committed, mode, |out_dir| { + gen_bind(&spec_rel, extension, out_dir) + }) + .map_err(|e| e.to_string())?; } else { - "lsx" - }; - if in_file_name.ends_with(".h") { - return gen_spec(in_file, ext_name).map_err(|e| e.to_string()); - } - if let [_, _lsx_or_lasx, "test"] = arg_strs.as_slice() { - return gen_test(in_file, ext_name).map_err(|e| e.to_string()); + let in_file = arguments[0].clone(); + let in_file_name = PathBuf::from(&in_file) + .file_name() + .unwrap() + .to_string_lossy() + .into_owned(); + let ext_name = if in_file_name.starts_with("lasx") { + "lasx" + } else { + "lsx" + }; + if in_file_name.ends_with(".h") { + return gen_spec(in_file, ext_name).map_err(|e| e.to_string()); + } + if arguments.last().map(|s| s.as_str()) == Some("test") { + return gen_test(in_file, ext_name).map_err(|e| e.to_string()); + } + // Note: this does not apply rustfmt formatting + let out_path = PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) + .join("src") + .join("loongarch64") + .join(ext_name); + gen_bind(&in_file, ext_name, &out_path).map_err(|e| e.to_string())?; } - let out_path = PathBuf::from(env::var("OUT_DIR").unwrap_or("crates/core_arch".to_string())) - .join("src") - .join("loongarch64") - .join(ext_name); - gen_bind(&in_file, ext_name, &out_path).map_err(|e| e.to_string()) + Ok(()) } From 2b0ee0b195bcd2adffe18296a73d9901cbbc78c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 11:48:14 +0200 Subject: [PATCH 0225/1309] Use unified rustfmt formatting in stdarch-gen-arm --- library/stdarch/Cargo.lock | 1 + .../stdarch/crates/stdarch-gen-arm/Cargo.toml | 1 + .../stdarch-gen-arm/src/load_store_tests.rs | 25 ++--- .../crates/stdarch-gen-arm/src/main.rs | 99 ++++++++----------- .../crates/stdarch-gen-common/src/lib.rs | 18 ---- 5 files changed, 50 insertions(+), 94 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index 6510b00da9b52..b902e966dc2ea 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -804,6 +804,7 @@ dependencies = [ name = "stdarch-gen-arm" version = "0.1.0" dependencies = [ + "clap", "itertools", "proc-macro2", "quote", diff --git a/library/stdarch/crates/stdarch-gen-arm/Cargo.toml b/library/stdarch/crates/stdarch-gen-arm/Cargo.toml index cb284d5f2c57b..9d803538474c7 100644 --- a/library/stdarch/crates/stdarch-gen-arm/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-arm/Cargo.toml @@ -12,6 +12,7 @@ edition = "2024" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +clap = { version = "4", features = ["derive", "env"] } itertools = "0.15.0" proc-macro2 = "1.0" quote = "1.0" diff --git a/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs b/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs index 672047fc057b8..3e3c20c592be0 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/load_store_tests.rs @@ -1,10 +1,9 @@ use std::fs::File; -use std::io::Write; -use std::path::PathBuf; +use std::io::{BufWriter, Write}; +use std::path::Path; use std::str::FromStr; use std::sync::LazyLock; -use crate::format_code; use crate::input::InputType; use crate::intrinsic::Intrinsic; use crate::typekinds::BaseType; @@ -38,15 +37,11 @@ const LEN_U64: usize = VL_MAX_BYTES / core::mem::size_of::(); pub fn generate_load_store_tests( load_intrinsics: Vec, store_intrinsics: Vec, - out_path: Option<&PathBuf>, + out_path: &Path, ) -> Result<(), String> { - let output = match out_path { - Some(out) => { - Box::new(File::create(out).map_err(|e| format!("couldn't create tests file: {e}"))?) - as Box - } - None => Box::new(std::io::stdout()) as Box, - }; + let mut output = BufWriter::new( + File::create(out_path).map_err(|e| format!("couldn't create tests file: {e}"))?, + ); let mut used_stores = vec![false; store_intrinsics.len()]; let tests: Vec<_> = load_intrinsics .iter() @@ -89,10 +84,9 @@ pub fn generate_load_store_tests( .map_err(|e| format!("Manual tests are invalid: {e}"))?, _ => quote!(), }; - format_code( + write!( output, - format!( - "// This code is automatically generated. DO NOT MODIFY. + "// This code is automatically generated. DO NOT MODIFY. // // Instead, modify `crates/stdarch-gen-arm/spec/sve` and run the following command to re-generate // this file: @@ -101,8 +95,7 @@ pub fn generate_load_store_tests( // cargo run --bin=stdarch-gen-arm -- crates/stdarch-gen-arm/spec // ``` {}", - quote! { #preamble #(#tests)* #manual_tests } - ), + quote! { #preamble #(#tests)* #manual_tests } ) .map_err(|e| format!("couldn't write tests: {e}")) } diff --git a/library/stdarch/crates/stdarch-gen-arm/src/main.rs b/library/stdarch/crates/stdarch-gen-arm/src/main.rs index 276cc5ba41b01..db1cfb2bb92b2 100644 --- a/library/stdarch/crates/stdarch-gen-arm/src/main.rs +++ b/library/stdarch/crates/stdarch-gen-arm/src/main.rs @@ -14,19 +14,51 @@ mod typekinds; mod wildcards; mod wildstring; +use clap::Parser; use intrinsic::Test; use itertools::Itertools; use quote::quote; use std::fs::File; use std::io::Write; use std::path::{Path, PathBuf}; -use std::process::{Command, Stdio}; -use stdarch_gen_common::{Mode, run_generator}; +use stdarch_gen_common::{GeneratorCtx, Mode, run_generator}; use walkdir::WalkDir; +#[derive(clap::Parser)] +struct Args { + /// Directory with spec files: //.spec.yml + input_dir: PathBuf, + /// Output directory to generate the files into, such as crates/core_arch/src + output_dir: Option, + /// Generation mode. + #[arg(long, env = "STDARCH_GEN_MODE")] + mode: Option, + /// Path to a rustfmt binary that will be used to reformat the generated code. + /// If unset, it will just use "rustfmt" from the environment. + #[arg(long)] + rustfmt_path: Option, +} + fn main() -> Result<(), String> { - let (in_path, out_base) = parse_args(); - let mode = Mode::from_env(); + let args = Args::parse(); + + let in_path = args.input_dir; + let out_base = args.output_dir.unwrap_or_else(|| { + std::env::current_exe() + .ok() + .map(|mut f| { + f.pop(); + f.push("../../crates/core_arch/src/"); + f + }) + .filter(|f| f.exists()) + .expect("could not locate crates/core_arch/src; pass OUTPUT_DIR command-line argument explicitly") + }); + assert!(in_path.exists()); + assert!(out_base.exists()); + + let mode = args.mode.unwrap_or_default(); + let ctx = GeneratorCtx::new(args.rustfmt_path); for filepath in WalkDir::new(&in_path) .into_iter() @@ -42,7 +74,7 @@ fn main() -> Result<(), String> { .expect("generated output path must have a parent directory") .to_path_buf(); - run_generator(&committed, mode, |scratch: &Path| { + run_generator(&ctx, &committed, mode, |scratch: &Path| { generate_spec(&filepath, scratch) }) .map_err(|e| e.to_string())?; @@ -92,7 +124,7 @@ fn generate_spec(filepath: &Path, out_dir: &Path) -> Result<(), String> { .expect("load/store test path must have a file name") .to_owned(); let tests_path = out_dir.join(tests_name); - load_store_tests::generate_load_store_tests(loads, stores, Some(&tests_path))?; + load_store_tests::generate_load_store_tests(loads, stores, &tests_path)?; } let generated = input::GeneratorInput { @@ -105,44 +137,6 @@ fn generate_spec(filepath: &Path, out_dir: &Path) -> Result<(), String> { .map_err(|e| format!("could not generate output file: {e}")) } -fn parse_args() -> (PathBuf, PathBuf) { - let mut args_it = std::env::args().skip(1); - assert!( - 1 <= args_it.len() && args_it.len() <= 2, - "Usage: cargo run -p stdarch-gen-arm -- INPUT_DIR [OUTPUT_DIR]\n\ - where:\n\ - - INPUT_DIR contains a tree like: INPUT_DIR//.spec.yml\n\ - - OUTPUT_DIR is a directory like: crates/core_arch/src/" - ); - - let in_path = Path::new(args_it.next().unwrap().as_str()).to_path_buf(); - assert!( - in_path.exists() && in_path.is_dir(), - "invalid path {in_path:#?} given" - ); - - let out_base = if let Some(dir) = args_it.next() { - let out_path = Path::new(dir.as_str()).to_path_buf(); - assert!( - out_path.exists() && out_path.is_dir(), - "invalid path {out_path:#?} given" - ); - out_path - } else { - std::env::current_exe() - .ok() - .map(|mut f| { - f.pop(); - f.push("../../crates/core_arch/src/"); - f - }) - .filter(|f| f.exists()) - .expect("could not locate crates/core_arch/src; pass OUTPUT_DIR command-line argument explicitly") - }; - - (in_path, out_base) -} - fn generate_file( generated_input: input::GeneratorInput, mut out: Box, @@ -171,25 +165,10 @@ use super::*;{uses_neon} }, )?; let intrinsics = generated_input.intrinsics; - format_code(out, quote! { #(#intrinsics)* })?; + write!(out, "{}", quote! { #(#intrinsics)* })?; Ok(()) } -pub fn format_code( - mut output: impl std::io::Write, - input: impl std::fmt::Display, -) -> std::io::Result<()> { - let proc = Command::new("rustfmt") - // Ensure that we generate the same file contents on both Linux and Windows. - .arg("--config") - .arg("newline_style=Unix") - .stdin(Stdio::piped()) - .stdout(Stdio::piped()) - .spawn()?; - write!(proc.stdin.as_ref().unwrap(), "{input}")?; - output.write_all(proc.wait_with_output()?.stdout.as_slice()) -} - /// Derive an output file path from an input file path and an output directory. /// /// `in_filepath` is expected to have a structure like: diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index 5308296d8588a..92393eb37885d 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -32,24 +32,6 @@ pub enum Mode { Bless, } -impl Mode { - /// Read the mode from the `STDARCH_GEN_MODE` environment variable. - /// - /// Recognized values: - /// - `"check"` → [`Mode::Check`] - /// - `"bless"` → [`Mode::Bless`] - /// - unset → [`Mode::Bless`] - /// - any other value → panic - pub fn from_env() -> Self { - match std::env::var("STDARCH_GEN_MODE").as_deref() { - Ok("check") => Mode::Check, - Ok("bless") => Mode::Bless, - Ok(other) => panic!("unknown STDARCH_GEN_MODE value: {other:?}"), - Err(_) => Mode::Bless, - } - } -} - impl FromStr for Mode { type Err = String; From 34bda05490f632c106ee25f5a553519fb1bd3616 Mon Sep 17 00:00:00 2001 From: xonx <119700621+xonx4l@users.noreply.github.com> Date: Mon, 14 Sep 2026 12:42:56 +0200 Subject: [PATCH 0226/1309] Show diff when generated files do not match expectations --- library/stdarch/Cargo.lock | 20 +++++++++++++++++++ .../crates/stdarch-gen-common/Cargo.toml | 3 ++- .../crates/stdarch-gen-common/src/lib.rs | 19 +++++++++++++++++- 3 files changed, 40 insertions(+), 2 deletions(-) diff --git a/library/stdarch/Cargo.lock b/library/stdarch/Cargo.lock index b902e966dc2ea..490161626c164 100644 --- a/library/stdarch/Cargo.lock +++ b/library/stdarch/Cargo.lock @@ -88,6 +88,16 @@ version = "2.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "843867be96c8daad0d758b57df9392b6d8d271134fce549de6ce169ff98a92af" +[[package]] +name = "bstr" +version = "1.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bb31b46c14244e20ee9984b11bf5c992b91fb6939fea616e3512c8baecdbe5f" +dependencies = [ + "memchr", + "serde_core", +] + [[package]] name = "cc" version = "1.2.59" @@ -800,6 +810,15 @@ dependencies = [ "syn", ] +[[package]] +name = "similar" +version = "3.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4f66ca1f7aca2474dc10c942eb22feffc897735f54cd1db90138c2fddb490987" +dependencies = [ + "bstr", +] + [[package]] name = "stdarch-gen-arm" version = "0.1.0" @@ -820,6 +839,7 @@ dependencies = [ name = "stdarch-gen-common" version = "0.1.0" dependencies = [ + "similar", "tempfile", ] diff --git a/library/stdarch/crates/stdarch-gen-common/Cargo.toml b/library/stdarch/crates/stdarch-gen-common/Cargo.toml index 691be14971a0d..fda09cb4c5994 100644 --- a/library/stdarch/crates/stdarch-gen-common/Cargo.toml +++ b/library/stdarch/crates/stdarch-gen-common/Cargo.toml @@ -4,4 +4,5 @@ version = "0.1.0" edition = "2024" [dependencies] -tempfile = "3" \ No newline at end of file +tempfile = "3" +similar = "3" diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index 92393eb37885d..535e0bc11cc0f 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -1,5 +1,6 @@ //! Shared check/bless harness for stdarch generators. +use similar::TextDiff; use std::error::Error as StdError; use std::fmt; use std::fs; @@ -251,7 +252,23 @@ fn compare(generated_dir: &Path, committed_dir: &Path, filename: &str) -> Result }), (false, false) => Ok(()), (true, true) => { - if fs::read(&gen_path)? != fs::read(&comm_path)? { + let generated = fs::read(&gen_path)?; + let committed = fs::read(&comm_path)?; + if generated != committed { + if let (Ok(committed), Ok(generated)) = + (str::from_utf8(&committed), str::from_utf8(&generated)) + { + eprintln!( + "{}", + TextDiff::from_lines(committed, generated) + .unified_diff() + .context_radius(3) + .header( + &format!("committed/{filename}"), + &format!("generated/{filename}"), + ) + ); + } Err(Error::Mismatch { path: rel_path, kind: MismatchKind::ContentsDiffer, From 988cc4b43b88a14303a3a40ff0252b99a6a623df Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 12:44:18 +0200 Subject: [PATCH 0227/1309] Bless arm output --- library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs index 324b5bccf3777..75393f594ad64 100644 --- a/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs +++ b/library/stdarch/crates/core_arch/src/aarch64/sve/generated.rs @@ -11,8 +11,8 @@ use stdarch_test::assert_instr; use super::*; -use crate::core_arch::arch::aarch64::*; use super::{AsSigned, AsUnsigned}; +use crate::core_arch::arch::aarch64::*; #[doc = "Absolute difference"] #[doc = "[Arm's documentation](https://developer.arm.com/architectures/instruction-sets/intrinsics/svabd[_f32]_m)"] From 1bda26edef6ac407370ca297e9ef1d061b9f2b94 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 13:01:30 +0200 Subject: [PATCH 0228/1309] Fix tests --- .../crates/stdarch-gen-common/src/lib.rs | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/library/stdarch/crates/stdarch-gen-common/src/lib.rs b/library/stdarch/crates/stdarch-gen-common/src/lib.rs index 535e0bc11cc0f..5dbfc76f27dfe 100644 --- a/library/stdarch/crates/stdarch-gen-common/src/lib.rs +++ b/library/stdarch/crates/stdarch-gen-common/src/lib.rs @@ -318,7 +318,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); write_marker(&committed.join("a.txt"), b"hi"); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |out| -> std::result::Result<(), io::Error> { @@ -341,7 +344,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); write_marker(&committed.join("a.txt"), b"hi"); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |_| -> std::result::Result<(), io::Error> { Ok(()) }, @@ -361,7 +367,10 @@ mod tests { let tmp = tempfile::tempdir().unwrap(); let committed = tmp.path().join("c"); fs::create_dir_all(&committed).unwrap(); + + let ctx = GeneratorCtx::new(None); let e = run_generator( + &ctx, &committed, Mode::Check, |out| -> std::result::Result<(), io::Error> { @@ -385,7 +394,10 @@ mod tests { let committed = tmp.path().join("c"); write_marker(&committed.join("keep.txt"), b""); write_marker(&committed.join("stale.txt"), b""); + + let ctx = GeneratorCtx::new(None); run_generator( + &ctx, &committed, Mode::Bless, |out| -> std::result::Result<(), io::Error> { @@ -405,7 +417,9 @@ mod tests { fs::create_dir_all(&committed).unwrap(); fs::write(committed.join("mod.rs"), b"hand-written").unwrap(); fs::write(committed.join("old.txt"), b"old").unwrap(); + let ctx = GeneratorCtx::new(None); run_generator( + &ctx, &committed, Mode::Bless, |out| -> std::result::Result<(), io::Error> { @@ -418,4 +432,32 @@ mod tests { assert_eq!(fs::read(committed.join("old.txt")).unwrap(), b"old"); assert!(committed.join("new.txt").exists()); } + + #[test] + fn generation_reformats_files() { + let tmp = tempfile::tempdir().unwrap(); + let committed = tmp.path().join("c"); + let file = committed.join("a.rs"); + write_marker(&file, b"foo"); + + let ctx = GeneratorCtx::new(None); + run_generator( + &ctx, + &committed, + Mode::Bless, + |out| -> std::result::Result<(), io::Error> { + write_marker(&out.join("a.rs"), b"fn main() {}"); + Ok(()) + }, + ) + .unwrap(); + assert_eq!( + std::fs::read_to_string(file).unwrap(), + format!( + r#"{GENERATED_MARKER} +fn main() {{}} +"# + ) + ); + } } From 1d6ecb3d7e5b9c1135c9aead64d003d58822204d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 14 Sep 2026 13:45:15 +0200 Subject: [PATCH 0229/1309] Install rustfmt on CI --- library/stdarch/.github/workflows/main.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 754f01d399117..182da81ac2371 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -225,6 +225,8 @@ jobs: rustup default nightly shell: bash + - run: rustup component add rustfmt + - run: rustup target add ${{ matrix.target.tuple }} shell: bash if: matrix.build_std == '' && matrix.target.tuple != 'amdgcn-amd-amdhsa' From 68963d8508e535e919983ceafe8c263290c14025 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Mon, 14 Sep 2026 15:03:18 +0200 Subject: [PATCH 0230/1309] stop unleaking `&mut`s --- src/tools/miri/src/shims/native_lib/trace/child.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/src/shims/native_lib/trace/child.rs b/src/tools/miri/src/shims/native_lib/trace/child.rs index 23670a2cfb053..74fef8c901f6b 100644 --- a/src/tools/miri/src/shims/native_lib/trace/child.rs +++ b/src/tools/miri/src/shims/native_lib/trace/child.rs @@ -83,8 +83,7 @@ impl Supervisor { .map(move |i| start.strict_add(i.strict_mul(page_size))) }) .collect(); - let raw_stack_ptr: *mut [u8; CALLBACK_STACK_SIZE] = - Box::leak(Box::new([0u8; CALLBACK_STACK_SIZE])).as_mut_ptr().cast(); + let raw_stack_ptr: *mut [u8; CALLBACK_STACK_SIZE] = Box::into_raw(Box::new([0; _])); let stack_ptr = raw_stack_ptr.expose_provenance(); let start_info = StartFfiInfo { page_ptrs, stack_ptr }; From 4ff0ef647aca9489660f0b48487dc42dfc200980 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 15 Sep 2026 00:08:33 +0800 Subject: [PATCH 0231/1309] intrinsic-test: Fix intrinsic test names for negative immediate values --- .../crates/intrinsic-test/src/common/gen_c.rs | 11 ++++++++--- .../crates/intrinsic-test/src/common/gen_rust.rs | 13 +++++++++---- .../stdarch/crates/intrinsic-test/src/common/mod.rs | 5 +++++ 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index bbff7a91b6c41..30e7bb1d375a3 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -1,5 +1,6 @@ use itertools::Itertools; +use crate::common::imm_value_to_ident; use crate::common::{SupportedArchitecture, intrinsic::Intrinsic}; use super::intrinsic_helpers::TypeDefinition; @@ -41,9 +42,13 @@ void {name}_wrapper{imm_arglist}({return_ty}* __dst{arglist}) {{ }}", return_ty = intrinsic.results.c_type(), name = intrinsic.name, - imm_arglist = imm_values - .iter() - .format_with("", |i, fmt| fmt(&format_args!("_{i}"))), + imm_arglist = + imm_values + .iter() + .format_with("", |i, fmt| fmt(&format_args!( + "_{}", + imm_value_to_ident(i) + ))), arglist = intrinsic.arguments.as_non_imm_arglist_c(), params = intrinsic.arguments.as_call_params_c(&imm_values) )) diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs index bfe37edbcfe43..f319418b49c7f 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_rust.rs @@ -4,6 +4,7 @@ use itertools::Itertools; use super::intrinsic_helpers::TypeDefinition; use crate::common::cli::{CcArgStyle, ProcessedCli}; +use crate::common::imm_value_to_ident; use crate::common::intrinsic::Intrinsic; use crate::common::intrinsic_helpers::TypeKind; use crate::common::values::{test_values_array_name, test_values_array_static}; @@ -276,7 +277,7 @@ for (id, rust, c) in specializations {{ } }) .join(","), - c_const_args = imm_values.iter().join("_"), + c_const_args = imm_values.iter().map(imm_value_to_ident).join("_"), )) } }), @@ -343,9 +344,13 @@ unsafe extern "C" {{ "fn {name}_wrapper{imm_arglist}(__dst: *mut {return_ty}{arglist});", return_ty = intrinsic.results.rust_type(), name = intrinsic.name, - imm_arglist = imm_values - .iter() - .format_with("", |i, fmt| fmt(&format_args!("_{i}"))), + imm_arglist = + imm_values + .iter() + .format_with("", |i, fmt| fmt(&format_args!( + "_{}", + imm_value_to_ident(i) + ))), arglist = intrinsic.arguments.as_non_imm_arglist_rust(), )) })) diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index b476ad477ca36..e89599d06ea77 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -138,3 +138,8 @@ pub fn manual_chunk(intrinsic_count: usize) -> (usize, usize) { let number_of_chunks = intrinsic_count.div_ceil(max_intrinsics_per_chunk); (max_intrinsics_per_chunk, number_of_chunks) } + +pub fn imm_value_to_ident(value: impl std::fmt::Display) -> String { + let value = value.to_string(); + value.replace('-', "neg") +} From 43ba58a79a834440c9604ce423e43085f60f2217 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Mon, 14 Sep 2026 23:54:00 +0200 Subject: [PATCH 0232/1309] regression test for GCE inherent projection ICE --- .../wf-const-arg-inherent-projection-ice.rs | 19 ++++++++++++++ ...f-const-arg-inherent-projection-ice.stderr | 25 +++++++++++++++++++ 2 files changed, 44 insertions(+) create mode 100644 tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.rs create mode 100644 tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.stderr diff --git a/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.rs b/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.rs new file mode 100644 index 0000000000000..8f6ec1e97a040 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.rs @@ -0,0 +1,19 @@ +//! Regression test for . + +#![feature(generic_const_exprs)] + +fn new() +where + [(); N * 1]:, +{ +} + +fn test() +where + [(); N - usize::MAX * 1]:, +{ + new + //~^ ERROR mismatched types +} + +fn main() {} diff --git a/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.stderr b/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.stderr new file mode 100644 index 0000000000000..3757a462a4173 --- /dev/null +++ b/tests/ui/const-generics/generic_const_exprs/wf-const-arg-inherent-projection-ice.stderr @@ -0,0 +1,25 @@ +error[E0308]: mismatched types + --> $DIR/wf-const-arg-inherent-projection-ice.rs:15:5 + | +LL | / fn new() +LL | | where +LL | | [(); N * 1]:, + | |_________________- function `new` defined here +... +LL | new + | ^^^ expected `()`, found fn item + | + = note: expected unit type `()` + found fn item `fn() {new::::MAX>}` +help: try adding a return type + | +LL | fn test() -> fn() + | +++++++ +help: use parentheses to call this function + | +LL | new() + | ++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. From 84201e9c9a93960b6664db6e03f54307d5abc78b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 14 Sep 2026 20:41:21 -0400 Subject: [PATCH 0233/1309] Fix compile errors --- src/builder.rs | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/builder.rs b/src/builder.rs index eea781d6d7e8b..a0dccfdc1dfbf 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -34,6 +34,7 @@ use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; +use crate::builder; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; #[cfg(feature = "master")] @@ -352,13 +353,14 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { typ: Type<'gcc>, fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, func: RValue<'gcc>, + return_slot: ReturnSlot< as BackendTypes>::Value>, args: &[RValue<'gcc>], funclet: Option<&Funclet>, must_tail: bool, ) -> RValue<'gcc> { // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. let args = match return_slot { - ReturnSlot::Direct => Cow::Borrowed(args.to_vec), + ReturnSlot::Direct => Cow::Borrowed(args), ReturnSlot::Indirect(sret_ptr) => { let mut args = args.to_vec(); // Prepend the indirect return pointer @@ -371,10 +373,10 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { // FIXME(antoyo): remove when the API supports a different type for functions. let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, args, funclet, must_tail) + self.function_call(func, &args, funclet, must_tail) } else { // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, args, funclet, must_tail) + self.function_ptr_call(typ, fn_abi, func, &args, funclet, must_tail) }; if let Some(_fn_abi) = fn_abi { // FIXME(bjorn3): Apply function attributes @@ -1873,10 +1875,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { -<<<<<<< HEAD -======= - self.build_call(typ, fn_abi, func, args, funclet, false) ->>>>>>> master + self.build_call(typ, fn_abi, func, return_slot, args, funclet, false) } fn tail_call( @@ -1885,13 +1884,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Value, - _return_slot: ReturnSlot, + return_slot: ReturnSlot, args: &[Self::Value], funclet: Option<&Self::Funclet>, _instance: Option>, ) { // `emit_call` returns a bare call for here, it has not been assigned or passed to add_eval. - let call = self.build_call(llty, Some(fn_abi), llfn, args, funclet, true); + let call = self.build_call(llty, Some(fn_abi), llfn, return_slot, args, funclet, true); call.set_require_tail_call(true); let return_type = self.current_func().get_return_type(); From fddfb9cb721be316861ea0934b90603c4f5d3c14 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 14 Sep 2026 20:41:26 -0400 Subject: [PATCH 0234/1309] Update to nightly-2026-09-14 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index ed97309659931..4e47a84698e7c 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-08" +channel = "nightly-2026-09-14" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 8c2eb2a9a1fd1f2dcbd4db102fe9e773d244e832 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Mon, 14 Sep 2026 20:42:57 -0400 Subject: [PATCH 0235/1309] Fix clippy warning --- src/builder.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/builder.rs b/src/builder.rs index a0dccfdc1dfbf..feea93ef3b8ff 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -348,6 +348,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { /// Shared implementation of `call` and `tail_call`. For tail call it is important that this /// returns a bare call, and not the result assigned to a local, or the result of `add_eval`. + #[allow(clippy::too_many_arguments)] fn build_call( &mut self, typ: Type<'gcc>, From a74f1e7d47b9796cc76e0345fb3194b0a740d776 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Mon, 14 Sep 2026 23:32:53 -0400 Subject: [PATCH 0236/1309] fix generic offload usage --- src/doc/rustc-dev-guide/src/offload/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md index 56a29d723b2d9..9d61a5a87c744 100644 --- a/src/doc/rustc-dev-guide/src/offload/usage.md +++ b/src/doc/rustc-dev-guide/src/offload/usage.md @@ -49,7 +49,7 @@ fn kernel(x: *mut [T; 256], value: T) { fn main() { let mut x = [0.0f64; 256]; core::offload::offload! { - kernel = kernel, + kernel = kernel::, workgroup_dim = [256, 1, 1], args = (&mut x as *mut [f64; 256], 2.5), } From a243cf40458341ea6d58a59961555b693bc8bd4a Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 15 Sep 2026 04:32:04 +0000 Subject: [PATCH 0237/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to c26ce708de5d14682647895d2f3caf38f70b5aa6. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 435bd384599f1..d8a1a0bba9f52 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -315ecf4a939def16631c2b25c3782ad67fc22160 +c26ce708de5d14682647895d2f3caf38f70b5aa6 From 1e4cab77adc1f10e8b2a74a898d3cce030011298 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Tue, 15 Sep 2026 04:32:00 -0500 Subject: [PATCH 0238/1309] update debuginfo testing information w/ GDB changes --- .../rustc-dev-guide/src/debuginfo/testing.md | 47 ++++++++++++------- 1 file changed, 31 insertions(+), 16 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/testing.md b/src/doc/rustc-dev-guide/src/debuginfo/testing.md index bcbe960034b02..5b80c42afc3de 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/testing.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/testing.md @@ -36,9 +36,8 @@ To help remedy this: # The `repr` directive > [!IMPORTANT] -> As of July 2026, this command is only supported by LLDB. GDB support is planned, but -> has not been implemented. It is unclear whether this directive will ever be suited for use with -> CDB. +> As of September 2026, this command is only supported for LLDB and GDB. +> It is unclear whether this directive will ever be suited for use with CDB. In short, `$DEBUGGER-repr` commands are desugared to: @@ -53,7 +52,7 @@ and runs special logic on them, testing against data stored in "Target groups" cover the set of targets where we cannot guarantee identical output. Those targets are defined by the - [`Target` enum in `common.py`](https://github.com/rust-lang/rust/blob/bf9944f0b8006b152ef4d5f408ae75a0dde3d044/src/etc/lldb_batchmode/common.py#L54). + [`Target` enum in `common.py`](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/common.py#L54). As of Jul 2026, this list includes `non_windows`, `windows_gnu`, and `windows_msvc`. It is intentionally kept as short as possible, since each target is a new set of test data that must be updated when changes are made. @@ -66,7 +65,7 @@ invocation (e.g. `./x test tests/debuginfo/basic-types/main.rs --bless`). and if no errors occur, saves the data back to the target file (or creates a new file if necessary). The schema of the input data is defined by the classes in -[`common.py`](https://github.com/rust-lang/rust/blob/be3d26db984c6f96335faca1f254dc04873cb1c1/src/etc/lldb_batchmode/common.py). +[`common.py`](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/common.py). The top-level container is `TargetData`. This schema is identical for all debuggers. @@ -98,6 +97,13 @@ as well (e.g. if you are on a Windows machine, bless once for `x86_64-pc-windows ## Implementation +Many of the details of the implementation are shared between LLDB and GDB, +and live in `src/etc/debugger_tester/common.py`. +Notably, LLDB's batch execution features execute commands without waiting for breakpoints to be reached, +making it generally unsuited for our purposes. +As such, `debugger_tester/lldb/lldb_batchmode.py` simulates GDB's batchmode behavior by manually +invoking the test script's commands via `lldb.SBDebugger` and `lldb.SBCommandInterpreter` objects. + ### Ser/De `TargetData` is converted to a dictionary with `dataclasses.asdict`, and is serialized with Python's @@ -108,7 +114,7 @@ The current deserialization logic should be resilient to changes in the schema, but requires that all fields contain ONLY types that can be directly serialized/deserialized by `json.dumps`. The acceptable types are those that make up -[`common.JsonType`](https://github.com/rust-lang/rust/blob/bf9944f0b8006b152ef4d5f408ae75a0dde3d044/src/etc/lldb_batchmode/common.py#L17) +[`common.JsonType`](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/common.py#L17) Since the serialization/deserialization is decoupled from the debugger logic, we can easily switch to an alternative format if we find a better alternative to json. @@ -117,11 +123,11 @@ The conversion logic from the debugger's internal representation to our schema c `from_$DEBUGGER.py`. Once imported, `common` automatically deserializes any existing input data and [stores it in the -global variable `INPUT_DATA`](https://github.com/rust-lang/rust/blob/bf9944f0b8006b152ef4d5f408ae75a0dde3d044/src/etc/lldb_batchmode/common.py#L523). +global variable `INPUT_DATA`](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/common.py#L601). This data is what we test against. > [!NOTE] -> Special care was taken to prevent `lldb_batchmode` from importing `common` unless a `repr` command +> Special care was taken to prevent `debugger_tester` from importing `common` unless a `repr` command > was actually processed. This saves us from reading/writing input data for tests that don't need > it. @@ -140,18 +146,27 @@ to help in diagnosing issues that may occur due to Python or the debugger changi ### Entry point and `--bless` -Upon encountering a `repr` pseudo-command, `lldb_batchmode.main` dispatches to -`check_$DEBUGGER.check()`. +* GDB: Upon import, the `repr` command is registered via the Python API in +[`debugger_tester/gdb/gdb_commands.py](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/gdb/gdb_commands.py). +`ReprCommand.invoke` initiates the check logic with the given variable, and handles top-level error reporting. + +* LLDB: Upon encountering a `repr` pseudo-command, `lldb_batchmode.main` dispatches to `check_lldb.check()`. + +> [!Note] +> LLDB also supports registering +> [custom CLI commands via the Python API](https://lldb.llvm.org/use/tutorials/writing-custom-commands.html). +> In the future, LLDB's `repr` logic may be refactored to behave more similarly to GDB's. + If the `--bless` option was specified, the variable is converted from the in-memory representation to our equivalent schema class. This includes the variable's type, visualizers, children, the children's types, etc. Once inserted into `TargetData`, -the variable is tested against the data that was just saved to `TargetData`. +the debugger's variable object is sanity-tested against the data that was just added to `TargetData`. If no exception or errors occurred and the `--bless` option was specified, `INPUT_DATA` is written -to the appropriate file just before `lldb_batchmode` exits. -If errors occur, `INPUT_DATA` is simply discarded. +to the appropriate file just before `debugger_tester` exits. +If errors occur, the blessed data is simply discarded. Currently, the `repr` pseudo-command is checked for directly. GDB and LLDB both support creating custom CLI commands via Python code. @@ -170,7 +185,7 @@ to provide more useful error messages. For example, LLDB can be a bit coy when it comes to reporting errors that occur within synthetic/summary provider calls. This is especially true when running the command within another -command, as the tests do by calling `script import lldb_batchmode; lldb_batchmode.main()` and +command, as the tests do by calling `script import debugger_tester; debugger_tester.main()` and executing commands in that context. When we encounter an error, we can import the appropriate summary provider, pass the variable object @@ -186,7 +201,7 @@ We absolutely do not want people accidentally blessing bad data purely because the first error happened to be an expected change. Errors are printed directly to `stdout` to appear as visible output from the `repr` pseudo command. -There are [several error helper functions](https://github.com/rust-lang/rust/blob/e7b595554e664e6bd281c8cf881093d6c71bc0e1/src/etc/lldb_batchmode/common.py#L35-L51) +There are [several error helper functions](https://github.com/rust-lang/rust/blob/c26ce708de5d14682647895d2f3caf38f70b5aa6/src/etc/debugger_tester/common.py#L35-L51) to keep formatting consistent. > [!NOTE] @@ -198,7 +213,7 @@ to keep formatting consistent. If no errors occurred for a given variable, `$VAR_NAME ok` is printed to `stdout` for `compiletest` to match against. -Before `lldb_batchmode` exits, one last check is done to ensure that all the types and variables +Before `debugger_tester` exits, one last check is done to ensure that all the types and variables that were present in `INPUT_DATA` have been checked against. If this check fails, the script reports the untested types/variables and exits with an error code. From f59ea0516067088b1e8c0db7b04df2cd518f4ca1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 15 Sep 2026 07:54:35 +0200 Subject: [PATCH 0239/1309] libtest: do not early exit from test runners --- clippy_lints/src/items_after_test_module.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index 9cd71c62eb32a..dac7a24bf2a8d 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -65,9 +65,9 @@ impl LateLintPass<'_> for ItemsAfterTestModule { let after: Vec<_> = items .filter(|item| { - // Ignore the generated test main function - if let ItemKind::Fn { ident, .. } = item.kind - && ident.name == sym::main + // Ignore the generated test main function and `extern crate test` + if (matches!(item.kind, ItemKind::Fn { ident, .. } if ident.name == sym::main) + || matches!(item.kind, ItemKind::ExternCrate(None, ident) if ident.name == sym::test)) && item.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::TestHarness) { false From 7488140d1c3958dfb3fb5fc82c67749814167f97 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 15 Sep 2026 14:31:19 +0200 Subject: [PATCH 0240/1309] Use nightly sync mode for josh-sync --- compiler/rustc_codegen_cranelift/josh-sync.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_cranelift/josh-sync.toml b/compiler/rustc_codegen_cranelift/josh-sync.toml index 2de9f9489cce3..d8b49ebac131d 100644 --- a/compiler/rustc_codegen_cranelift/josh-sync.toml +++ b/compiler/rustc_codegen_cranelift/josh-sync.toml @@ -1,3 +1,4 @@ repo = "rustc_codegen_cranelift" filter = ":~(history=\"keep-trivial-merges,no-splice\")[:rev(<=5e120485964f4857f1ad70f7d661fd244d087668:prefix=compiler/rustc_codegen_cranelift,<=7bd21608dfab11ea536f7be8936cc7dfac5864fb:SQUASH)]:/compiler/rustc_codegen_cranelift" filter-version = 2 +pull-mode = "Nightly" From 9e67ac6e7e9e9ee34bb9869b6de2b75d23e31e16 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 27 Aug 2026 16:07:23 +0200 Subject: [PATCH 0241/1309] compiler: fix bug and span_bug imports --- src/abi.rs | 2 +- src/allocator.rs | 2 +- src/asm.rs | 3 +-- src/builder.rs | 3 +-- src/consts.rs | 2 +- src/intrinsic/mod.rs | 3 +-- src/mono_item.rs | 2 +- src/type_.rs | 3 ++- src/type_of.rs | 2 +- 9 files changed, 10 insertions(+), 12 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 2901eb8b1a6d2..6a05f1cbbeef1 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -6,11 +6,11 @@ use rustc_abi::{ArmCall, CanonAbi, InterruptKind, X86Call}; use rustc_abi::{Reg, RegKind}; use rustc_codegen_ssa::traits::{AbiBuilderMethods, BaseTypeCodegenMethods}; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::bug; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::{Session, config}; +use rustc_span::bug; use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; #[cfg(feature = "master")] use rustc_target::spec::Arch; diff --git a/src/allocator.rs b/src/allocator.rs index 6b92174ddf1ce..dc69bfad57b3e 100644 --- a/src/allocator.rs +++ b/src/allocator.rs @@ -4,8 +4,8 @@ use gccjit::{Context, FunctionType, ToRValue, Type}; use rustc_ast::expand::allocator::{ AllocatorMethod, AllocatorTy, NO_ALLOC_SHIM_IS_UNSTABLE, default_fn_name, global_fn_name, }; -use rustc_middle::bug; use rustc_middle::ty::TyCtxt; +use rustc_span::bug; use rustc_symbol_mangling::mangle_internal_symbol; use crate::GccContext; diff --git a/src/asm.rs b/src/asm.rs index 8fd438d847d29..420bf1e7a31c1 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -12,11 +12,10 @@ use rustc_codegen_ssa::traits::{ AsmBuilderMethods, AsmCodegenMethods, BaseTypeCodegenMethods, BuilderMethods, GlobalAsmOperandRef, InlineAsmOperandRef, }; -use rustc_middle::bug; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::Instance; use rustc_middle::ty::layout::LayoutOf; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Span, bug}; use rustc_target::asm::*; use crate::builder::Builder; diff --git a/src/builder.rs b/src/builder.rs index 83f2bcdd3959c..0a88085960e89 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -21,15 +21,14 @@ use rustc_codegen_ssa::traits::{ LayoutTypeCodegenMethods, OverflowOp, ReturnSlot, StaticBuilderMethods, }; use rustc_data_structures::fx::FxHashSet; -use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ FnAbiError, FnAbiOfHelpers, FnAbiRequest, HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers, TyAndLayout, }; use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; -use rustc_span::Span; use rustc_span::def_id::DefId; +use rustc_span::{Span, bug}; use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; diff --git a/src/consts.rs b/src/consts.rs index 42ff930968501..6c3b404547cfc 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -15,8 +15,8 @@ use rustc_middle::mir::interpret::{ }; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; -use rustc_middle::{bug, span_bug}; use rustc_span::def_id::DefId; +use rustc_span::{bug, span_bug}; use crate::base; use crate::context::CodegenCx; diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 06713016cedbe..624cd2dcb7327 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -24,8 +24,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; -use rustc_middle::{bug, span_bug}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Span, Symbol, bug, span_bug, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; #[cfg(feature = "master")] diff --git a/src/mono_item.rs b/src/mono_item.rs index d5874779021d2..fc92cc3d5c7a9 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -4,11 +4,11 @@ use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_middle::bug; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; +use rustc_span::bug; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; diff --git a/src/type_.rs b/src/type_.rs index 5252f93a92ebe..27b0d2079e63e 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -9,8 +9,9 @@ use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, TypeMembershipCodegenMethods, }; +use rustc_middle::ty; use rustc_middle::ty::layout::TyAndLayout; -use rustc_middle::{bug, ty}; +use rustc_span::bug; use crate::common::TypeReflection; use crate::context::{CodegenCx, new_array_type}; diff --git a/src/type_of.rs b/src/type_of.rs index 53192c0a087e4..31654d0e6be81 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -9,10 +9,10 @@ use rustc_abi::{ use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, DerivedTypeCodegenMethods, LayoutTypeCodegenMethods, }; -use rustc_middle::bug; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{self, CoroutineArgsExt, Ty, TypeVisitableExt}; +use rustc_span::bug; use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; From 05840bcfa6aba507e8fa8a751d2fac965198b738 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Thu, 10 Sep 2026 18:16:55 +0100 Subject: [PATCH 0242/1309] Add `clippy` linting to all packages Duplicate the same config across each package and add a script that verifies these configs are all equal, and add a workflow so that `clippy` is run across all packages in PRs. --- .github/workflows/clippy.yml | 45 ++++++++++ Cargo.toml | 14 ++++ Contributing.md | 20 +++++ ci/Cargo.lock | 150 ++++++++++++++++++++++++++++++++++ ci/Cargo.toml | 18 ++++ ci/src/clippy_config_check.rs | 40 +++++++++ ci/src/main.rs | 8 +- config_proc_macro/Cargo.toml | 14 ++++ 8 files changed, 307 insertions(+), 2 deletions(-) create mode 100644 .github/workflows/clippy.yml create mode 100644 ci/src/clippy_config_check.rs diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml new file mode 100644 index 0000000000000..acf3d2d097adc --- /dev/null +++ b/.github/workflows/clippy.yml @@ -0,0 +1,45 @@ +name: clippy +on: + merge_group: + pull_request: + +permissions: + contents: read + +jobs: + check_clippy_configs: + runs-on: ubuntu-latest + name: check clippy configs + steps: + - name: checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + rustup target add x86_64-unknown-linux-gnu + - name: Check clippy configs all match + run: cargo run --manifest-path ci/Cargo.toml -- clippy-config-check + + + run_clippy: + runs-on: ubuntu-latest + name: clippy ${{ matrix.package }} + strategy: + fail-fast: false + matrix: + package: + - . # rustfmt + - check_diff + - ci + - config_proc_macro + steps: + - name: checkout + uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - name: install rustup + run: | + curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh + sh rustup-init.sh -y --default-toolchain none + - name: clippy + run: cargo clippy --manifest-path ${{ matrix.package }}/Cargo.toml + diff --git a/Cargo.toml b/Cargo.toml index 48dfeed93dad9..7e4d2e60565b3 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -69,3 +69,17 @@ insta = { version = "1.48.0", features = ["filters"] } [package.metadata.rust-analyzer] # This package uses #[feature(rustc_private)] rustc_private = true + +[lints.clippy] +# allow all rules with a low priority .. +all = { level = "allow", priority = -1 } +# so we can pick out an exact subset of rules to deny +correctness = "deny" +char_lit_as_u8 = "deny" +four_forward_slashes = "deny" +non_minimal_cfg = "deny" +print_literal = "deny" +same_item_push = "deny" +single_char_add_str = "deny" +to_string_in_format_args = "deny" +unconditional_recursion = "deny" diff --git a/Contributing.md b/Contributing.md index 99558079984b4..ebf1d874f3063 100644 --- a/Contributing.md +++ b/Contributing.md @@ -17,6 +17,26 @@ assistance when participating in `rust-lang/rustfmt`. [LLM usage policy]: https://forge.rust-lang.org/policies/llm-usage.html +## Linting + +This project supports linting via +[`clippy`](https://doc.rust-lang.org/stable/clippy/index.html). You can either +run it directly, or use an integration through your editor. + +``` +# lint rustfmt-nightly (the package at the root of this repo) +cargo clippy +``` + +To Lint a package outside of the root one you will need to do one of: + +``` +# pass the manifest path +cargo clippy --manifest-path ./config_proc_macro/Config.toml +# or run the command from within the package +cd ./config_proc_macro +cargo clippy +``` ## Test and file issues diff --git a/ci/Cargo.lock b/ci/Cargo.lock index 7c7807f6f37f2..caa4dfaad41a8 100644 --- a/ci/Cargo.lock +++ b/ci/Cargo.lock @@ -5,3 +5,153 @@ version = 4 [[package]] name = "ci-integration" version = "0.0.1" +dependencies = [ + "itertools", + "toml", +] + +[[package]] +name = "either" +version = "1.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "252afb9ae5eaa683babdc6a068b3f5726eb19e05070c731f9b2a23a7c3e8ed34" + +[[package]] +name = "equivalent" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" + +[[package]] +name = "hashbrown" +version = "0.17.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" + +[[package]] +name = "indexmap" +version = "2.14.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" +dependencies = [ + "equivalent", + "hashbrown", +] + +[[package]] +name = "itertools" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8b4baf93f58d4425749ca49a51c50ebab072c5df6994d08fed93541c331481dc" +dependencies = [ + "either", +] + +[[package]] +name = "proc-macro2" +version = "1.0.107" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "985e7ec9bb745e6ce6535b544d84d6cd6f7ad8bd711c398938ae983b91a766d9" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.47" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1fbf4db142a473a8d80c26bbf18454ed458bf8d26c8219c331daecfdbd079001" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde_core" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "67dca2c9c51e58a4791a4b1ed58308b39c64224d349a935ab5039aa360942a48" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.229" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_spanned" +version = "1.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6662b5879511e06e8999a8a235d848113e942c9124f211511b16466ee2995f26" +dependencies = [ + "serde_core", +] + +[[package]] +name = "syn" +version = "3.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12df2e0110f65b775f769bb17ef989067a1d931b2eb822bd4346631eeada89f9" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "1.1.5+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "12c0ba9680044b4ce98d391a62094047eada0d64860b80166c39f4a6b5640785" +dependencies = [ + "indexmap", + "serde_core", + "serde_spanned", + "toml_datetime", + "toml_parser", + "toml_writer", + "winnow", +] + +[[package]] +name = "toml_datetime" +version = "1.1.1+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3165f65f62e28e0115a00b2ebdd37eb6f3b641855f9d636d3cd4103767159ad7" +dependencies = [ + "serde_core", +] + +[[package]] +name = "toml_parser" +version = "1.1.3+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d38ac1cf9b95face32296c0a3ede1fdc270627c9d9c02a7274dd6d960dc4d56" +dependencies = [ + "winnow", +] + +[[package]] +name = "toml_writer" +version = "1.1.2+spec-1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "winnow" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b97319f7b8343df12cc98938e5c3eb436064524c8d2b4e30a1d3a36eecdf81" diff --git a/ci/Cargo.toml b/ci/Cargo.toml index 74312216d4ea3..a03a11aa8aa19 100644 --- a/ci/Cargo.toml +++ b/ci/Cargo.toml @@ -5,3 +5,21 @@ edition = "2024" publish = false [workspace] + +[dependencies] +itertools = "0.15.0" +toml = "1.1.5" + +[lints.clippy] +# allow all rules with a low priority .. +all = { level = "allow", priority = -1 } +# so we can pick out an exact subset of rules to deny +correctness = "deny" +char_lit_as_u8 = "deny" +four_forward_slashes = "deny" +non_minimal_cfg = "deny" +print_literal = "deny" +same_item_push = "deny" +single_char_add_str = "deny" +to_string_in_format_args = "deny" +unconditional_recursion = "deny" diff --git a/ci/src/clippy_config_check.rs b/ci/src/clippy_config_check.rs new file mode 100644 index 0000000000000..011ffe4ef18d7 --- /dev/null +++ b/ci/src/clippy_config_check.rs @@ -0,0 +1,40 @@ +use std::fs; + +use itertools::Itertools; + +const CARGO_TOMLS: &[&'static str] = &[ + "Cargo.toml", + "ci/Cargo.toml", + "config_proc_macro/Cargo.toml", +]; + +pub(crate) fn runner() -> Result<(), String> { + for (first, second) in CARGO_TOMLS.iter().tuple_windows() { + let first_table = parse_to_toml(&first)?; + let second_table = parse_to_toml(&second)?; + assert_eq!( + get_lints(first, &first_table)?, + get_lints(second, &second_table)?, + "Clippy configs do not match between {} and {}", + first, + second, + ); + } + Ok(()) +} + +fn parse_to_toml(path: &str) -> Result { + let toml_str = fs::read_to_string(path).map_err(|e| format!("reading {}: {}", path, e))?; + toml_str + .parse::() + .map_err(|e| format!("parsing {} as TOML: {}", path, e)) +} + +fn get_lints<'a>(path: &str, toml: &'a toml::Table) -> Result<&'a toml::Value, String> { + toml.get("lints") + .ok_or(format!("{} is missing key {}", path, "lints")) + .and_then(|t| { + t.get("clippy") + .ok_or(format!("{} is missing key {}", path, "lints.clippy")) + }) +} diff --git a/ci/src/main.rs b/ci/src/main.rs index 4817fa3c49c10..e7c4a2b09dd23 100644 --- a/ci/src/main.rs +++ b/ci/src/main.rs @@ -1,4 +1,5 @@ mod build_and_test; +mod clippy_config_check; mod common; mod integration; @@ -7,11 +8,14 @@ fn main() { if let Err(error) = match args.next().as_deref() { Some("integration") => integration::runner(&mut args), Some("build-and-test") => build_and_test::runner(), + Some("clippy-config-check") => clippy_config_check::runner(), Some(arg) => Err(format!( - "Expected `integration` or `build-and-test` as first argument, found {arg:?}" + "Expected `integration`, `build-and-test`, or `clippy-config-check` \ + as first argument, found {arg:?}" )), None => Err( - "Expected `integration` or `build-and-test` as first argument, found nothing" + "Expected `integration`, `build-and-test`, or `clippy-config-check` \ + as first argument, found nothing" .to_string(), ), } { diff --git a/config_proc_macro/Cargo.toml b/config_proc_macro/Cargo.toml index ec0db49d71cc7..48d894577ef66 100644 --- a/config_proc_macro/Cargo.toml +++ b/config_proc_macro/Cargo.toml @@ -21,3 +21,17 @@ serde = { version = "1.0.160", features = ["derive"] } [features] default = [] debug-with-rustfmt = [] + +[lints.clippy] +# allow all rules with a low priority .. +all = { level = "allow", priority = -1 } +# so we can pick out an exact subset of rules to deny +correctness = "deny" +char_lit_as_u8 = "deny" +four_forward_slashes = "deny" +non_minimal_cfg = "deny" +print_literal = "deny" +same_item_push = "deny" +single_char_add_str = "deny" +to_string_in_format_args = "deny" +unconditional_recursion = "deny" From ad06fc7dddd0eca5a3ab39626780d4c3e4d3f183 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 7 Sep 2026 20:00:26 +0100 Subject: [PATCH 0243/1309] refactor(chain): refactor chain parsing Some general code cleanup, things like: * Replace some `ref` patterns with `&` ones * Only pass down only required field to helper function * Add comments for span attribute --- src/chains.rs | 43 +++++++++++++++++++++---------------------- 1 file changed, 21 insertions(+), 22 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index 45d9d488c76ba..ea2b4ca0ba9cb 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -175,6 +175,8 @@ struct SubExpr { struct ChainItem { kind: ChainItemKind, tries: usize, + // The entire span of the chain item, including the leading dot and any comments, e.g. + // `.some_method(arg, arg)`, or `. /* a comment */ my_attribute`. span: Span, } @@ -421,7 +423,7 @@ impl Chain { prev_span_end: &mut BytePos, children: &mut Vec, ) { - let white_spaces: &[_] = &[' ', '\t']; + let white_spaces = &[' ', '\t']; if post_comment_snippet .trim_matches(white_spaces) .starts_with('\n') @@ -445,6 +447,8 @@ impl Chain { let mut prev_span_end = parent.span.hi(); let mut iter = rev_children.into_iter().rev().peekable(); if let Some(first_chain_item) = iter.peek() { + // `parent? /* maybe comment */ . /* maybe comment */ first_child` + // ^------------------- ^ comment_span let comment_span = mk_sp(prev_span_end, first_chain_item.span.lo()); let comment_snippet = context.snippet(comment_span); if !is_tries(comment_snippet.trim()) { @@ -466,16 +470,14 @@ impl Chain { if handle_comment { let pre_comment_span = mk_sp(prev_span_end, chain_item.span.lo()); let pre_comment_snippet = trim_tries(context.snippet(pre_comment_span)); - let (pre_comment, _) = extract_pre_comment(&pre_comment_snippet); - match pre_comment { - Some(ref comment) if !comment.is_empty() => { + if let (Some(pre_comment), _) = extract_pre_comment(&pre_comment_snippet) { + if !pre_comment.is_empty() { children.push(ChainItem::comment( pre_comment_span, - comment.to_owned(), + pre_comment.to_owned(), CommentPosition::Top, )); } - _ => (), } } @@ -509,7 +511,8 @@ impl Chain { is_postfix_receiver: false, }]; - while let Some(subexpr) = Self::pop_expr_chain(subexpr_list.last().unwrap(), context) { + while let Some(subexpr) = Self::pop_expr_chain(&subexpr_list.last().unwrap().expr, context) + { subexpr_list.push(subexpr); } @@ -518,20 +521,20 @@ impl Chain { // Returns the expression's subexpression, if it exists. When the subexpr // is a try! macro, we'll convert it to shorthand when the option is set. - fn pop_expr_chain(expr: &SubExpr, context: &RewriteContext<'_>) -> Option { - match expr.expr.kind { - ast::ExprKind::MethodCall(ref call) => Some(SubExpr { + fn pop_expr_chain(expr: &ast::Expr, context: &RewriteContext<'_>) -> Option { + match &expr.kind { + ast::ExprKind::MethodCall(call) => Some(SubExpr { expr: Self::convert_try(&call.receiver, context), is_postfix_receiver: true, }), - ast::ExprKind::Field(ref subexpr, _) - | ast::ExprKind::Await(ref subexpr, _) - | ast::ExprKind::Use(ref subexpr, _) - | ast::ExprKind::Yield(ast::YieldKind::Postfix(ref subexpr)) => Some(SubExpr { + ast::ExprKind::Field(subexpr, _) + | ast::ExprKind::Await(subexpr, _) + | ast::ExprKind::Use(subexpr, _) + | ast::ExprKind::Yield(ast::YieldKind::Postfix(subexpr)) => Some(SubExpr { expr: Self::convert_try(subexpr, context), is_postfix_receiver: true, }), - ast::ExprKind::Try(ref subexpr) => Some(SubExpr { + ast::ExprKind::Try(subexpr) => Some(SubExpr { expr: Self::convert_try(subexpr, context), is_postfix_receiver: false, }), @@ -540,13 +543,9 @@ impl Chain { } fn convert_try(expr: &ast::Expr, context: &RewriteContext<'_>) -> ast::Expr { - match expr.kind { - ast::ExprKind::MacCall(ref mac) if context.config.use_try_shorthand() => { - if let Some(subexpr) = convert_try_mac(mac, context) { - subexpr - } else { - expr.clone() - } + match &expr.kind { + ast::ExprKind::MacCall(mac) if context.config.use_try_shorthand() => { + convert_try_mac(mac, context).unwrap_or(expr.clone()) } _ => expr.clone(), } From 5cec9deacd9c690e5e755f30df5a7b79f64dc8b1 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Sat, 12 Sep 2026 22:19:45 +0100 Subject: [PATCH 0244/1309] refactor(chain): rename `CommentPosition` variants I found the naming in this type quite confusing: all it was tracking was "does this comment belong on the same line", so update the name to be clearer (I actually stole the naming from `lists::ListItemCommentStyle` in this same crate) --- src/chains.rs | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/chains.rs b/src/chains.rs index ea2b4ca0ba9cb..b63ec28ff15bf 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -160,8 +160,8 @@ pub(crate) fn rewrite_chain( #[derive(Debug)] enum CommentPosition { - Back, - Top, + SameLine, + DifferentLine, } /// Information about an expression in a chain. @@ -204,6 +204,7 @@ enum ChainItemKind { Await, Use, Yield, + /// A comment within a chain, e.g. `parent. item /* comment */.rest`. Comment(String, CommentPosition), } @@ -436,7 +437,7 @@ impl Chain { children.push(ChainItem::comment( post_comment_span, trimmed_snippet.trim().to_owned(), - CommentPosition::Back, + CommentPosition::SameLine, )); *prev_span_end = post_comment_span.hi(); } @@ -475,7 +476,7 @@ impl Chain { children.push(ChainItem::comment( pre_comment_span, pre_comment.to_owned(), - CommentPosition::Top, + CommentPosition::DifferentLine, )); } } @@ -838,8 +839,10 @@ impl<'a> ChainFormatterShared<'a> { for (rewrite, chain_item) in iter { match chain_item.kind { - ChainItemKind::Comment(_, CommentPosition::Back) => result.push(' '), - ChainItemKind::Comment(_, CommentPosition::Top) => result.push_str(&connector), + ChainItemKind::Comment(_, CommentPosition::SameLine) => result.push(' '), + ChainItemKind::Comment(_, CommentPosition::DifferentLine) => { + result.push_str(&connector) + } _ => result.push_str(&connector), } result.push_str(rewrite); From 511bddada49e8c238c4e840d2bce4d9c4eac0394 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Sun, 13 Sep 2026 19:44:35 +0100 Subject: [PATCH 0245/1309] Add some more chain comment tests So that I can be confidence that my future refactors aren't changing some untested behaviour. --- tests/source/chain_yield_with_comments.rs | 8 ++++++ tests/source/chains_with_comment.rs | 26 ++++++++++++++++++ tests/target/chain_yield_with_comments.rs | 10 +++++++ tests/target/chains_with_comment.rs | 32 +++++++++++++++++++++++ 4 files changed, 76 insertions(+) create mode 100644 tests/source/chain_yield_with_comments.rs create mode 100644 tests/target/chain_yield_with_comments.rs diff --git a/tests/source/chain_yield_with_comments.rs b/tests/source/chain_yield_with_comments.rs new file mode 100644 index 0000000000000..41e1db18edb9e --- /dev/null +++ b/tests/source/chain_yield_with_comments.rs @@ -0,0 +1,8 @@ +// rustfmt-edition: 2024 + +fn f() { + parent /* comment */ .yield /* some comment */?// comment + .yield /* some + long + comment */.yield; +} diff --git a/tests/source/chains_with_comment.rs b/tests/source/chains_with_comment.rs index 91160711b8909..19f959f54843d 100644 --- a/tests/source/chains_with_comment.rs +++ b/tests/source/chains_with_comment.rs @@ -118,4 +118,30 @@ fn foo() { // comment ? ? ? .baz; + + parent /* comment */ .child; + parent /* comment1 */ /* comment2 */ .child; + parent /* comment1 */ // comment 2 + .child; + parent /* ???no tries here */ // nor ??? here ???? + ???.child; + parent/* + some interesting shaped comment + */.child; + + parent /* comment */ + // another comment + .child1(some, args) /* comment */ // again + .await /* longer + comment + */ // more comments! + .use // here's a comment that reaches right to the default width limit aaaaaaaaaaaaaaaaaaaa + .end; + + parent? /* spacing is interesting */ ? /* blah */.child; + + // NB: recording the current state of things + // but is possibly a bug: rustfmt/issues/6433 + parent //comment + .1 .2 .3; } diff --git a/tests/target/chain_yield_with_comments.rs b/tests/target/chain_yield_with_comments.rs new file mode 100644 index 0000000000000..1210759920f78 --- /dev/null +++ b/tests/target/chain_yield_with_comments.rs @@ -0,0 +1,10 @@ +// rustfmt-edition: 2024 + +fn f() { + parent /* comment */ + .yield? /* some comment */// comment + .yield /* some + long + comment */ + .yield; +} diff --git a/tests/target/chains_with_comment.rs b/tests/target/chains_with_comment.rs index 522d70713bcd3..00136f75db227 100644 --- a/tests/target/chains_with_comment.rs +++ b/tests/target/chains_with_comment.rs @@ -134,4 +134,36 @@ fn foo() { // comment // comment .baz; + + parent /* comment */ + .child; + parent /* comment1 */ /* comment2 */ + .child; + parent /* comment1 */ // comment 2 + .child; + parent??? /* ???no tries here */ // nor ??? here ???? + .child; + parent /* + some interesting shaped comment + */ + .child; + + parent /* comment */ + // another comment + .child1(some, args) /* comment */ // again + .await /* longer + comment + */ // more comments! + .use // here's a comment that reaches right to the default width limit aaaaaaaaaaaaaaaaaaaa + .end; + + parent?? /* spacing is interesting */ /* blah */ + .child; + + // NB: recording the current state of things + // but is possibly a bug: rustfmt/issues/6433 + parent //comment + .1 + .2 + .3; } From 200037962ba383732b43d65af5170d23eaa04242 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 25 May 2026 20:33:07 +0100 Subject: [PATCH 0246/1309] Avoid passing entire config to `get_prefix_space_width` And pass only the required attribute, similarly to `wrap_str` --- src/utils.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 2936025d2f92c..474a36df4c7af 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -659,7 +659,7 @@ pub(crate) fn trim_left_preserve_layout( let prefix_space_width = if is_empty_line(&line) { None } else { - Some(get_prefix_space_width(config, &line)) + Some(get_prefix_space_width(&line, config.tab_spaces())) }; // just InString{Commented} in order to allow the start of a string to be indented @@ -735,12 +735,12 @@ pub(crate) fn is_empty_line(s: &str) -> bool { s.is_empty() || s.chars().all(char::is_whitespace) } -fn get_prefix_space_width(config: &Config, s: &str) -> usize { +fn get_prefix_space_width(s: &str, tab_spaces: usize) -> usize { let mut width = 0; for c in s.chars() { match c { ' ' => width += 1, - '\t' => width += config.tab_spaces(), + '\t' => width += tab_spaces, _ => return width, } } From 3e1421c044bc1455fd35e9d577622430981ca6d4 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 25 May 2026 20:42:39 +0100 Subject: [PATCH 0247/1309] Rewrite `get_prefix_space_width` to also give the prefix end This is required so that `last_line_width` knows the width of the prefix and where the rest of the string starts. Rename the function appropriately and replace a call to `str::chars` with `str::char_indices` to make it more explicit we want an index here (though the two are equivalent in this case, since we only loop over single byte characters) --- src/utils.rs | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/utils.rs b/src/utils.rs index 474a36df4c7af..a3f2d8b1534b5 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -659,7 +659,8 @@ pub(crate) fn trim_left_preserve_layout( let prefix_space_width = if is_empty_line(&line) { None } else { - Some(get_prefix_space_width(&line, config.tab_spaces())) + let (prefix_width, _) = get_prefix_space_width_and_end(&line, config.tab_spaces()); + Some(prefix_width) }; // just InString{Commented} in order to allow the start of a string to be indented @@ -735,16 +736,17 @@ pub(crate) fn is_empty_line(s: &str) -> bool { s.is_empty() || s.chars().all(char::is_whitespace) } -fn get_prefix_space_width(s: &str, tab_spaces: usize) -> usize { +fn get_prefix_space_width_and_end(s: &str, tab_spaces: usize) -> (usize, usize) { let mut width = 0; - for c in s.chars() { + + for (i, c) in s.char_indices() { match c { ' ' => width += 1, '\t' => width += tab_spaces, - _ => return width, + _ => return (width, i), } } - width + (width, s.len()) } pub(crate) trait NodeIdExt { From a1c73fa1d69af2f29583ae82742e4656bab992b4 Mon Sep 17 00:00:00 2001 From: Matthew Hughes Date: Mon, 25 May 2026 21:12:19 +0100 Subject: [PATCH 0248/1309] Teach `last_line_width` about `config.tab_spaces` So that the line width is calculated as the rendered width of any trailing space plus the unicode width of the rest of the string. That is, for example, so that the line: \s\s\s\ssome_func(); Would have the same length as \tsome_func(); Assuming `tab_spaces=4`. This fixes a issue where the formatting a collection of binary operations would depend on whether hard of soft tabs were used. Specifically in the change to the call of `last_line_width` at line 135 of `src/pairs.rs`: the inconsistency above meant under some conditions when using hard tabs we could satisfy the condition on that line and drop into the block to snuggle the lines together, where with soft tabs a different width would be computed and we'd avoid snuggling them. A test has been added covering this case. --- src/chains.rs | 29 +++++-- src/closures.rs | 2 +- src/comment.rs | 12 ++- src/expr.rs | 50 +++++++++--- src/items.rs | 93 +++++++++++++--------- src/lists.rs | 5 +- src/macros.rs | 7 +- src/missed_spans.rs | 5 +- src/overflow.rs | 7 +- src/pairs.rs | 18 +++-- src/string.rs | 7 +- src/types.rs | 13 ++- src/utils.rs | 28 +++++-- src/visitor.rs | 5 +- tests/target/issue_6859_hard_tab_breaks.rs | 11 +++ 15 files changed, 206 insertions(+), 86 deletions(-) create mode 100644 tests/target/issue_6859_hard_tab_breaks.rs diff --git a/src/chains.rs b/src/chains.rs index 45d9d488c76ba..ab407bdadae54 100644 --- a/src/chains.rs +++ b/src/chains.rs @@ -572,8 +572,13 @@ impl Rewrite for Chain { formatter.format_root(&self.parent, context, shape)?; if let Some(result) = formatter.pure_root() { - return wrap_str(result, context.config.max_width(), shape) - .max_width_error(shape.width, self.parent.span); + return wrap_str( + result, + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) + .max_width_error(shape.width, self.parent.span); } let first = self.children.first().unwrap_or(&self.parent); @@ -588,7 +593,13 @@ impl Rewrite for Chain { formatter.format_last_child(context, shape, child_shape)?; let result = formatter.join_rewrites(context, child_shape)?; - wrap_str(result, context.config.max_width(), shape).max_width_error(shape.width, full_span) + wrap_str( + result, + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) + .max_width_error(shape.width, full_span) } } @@ -724,7 +735,7 @@ impl<'a> ChainFormatterShared<'a> { ) -> Result<(), RewriteError> { let last = self.children.last().unknown_error()?; let extendable = may_extend && last_line_extendable(&self.rewrites[0]); - let prev_last_line_width = last_line_width(&self.rewrites[0]); + let prev_last_line_width = last_line_width(&self.rewrites[0], context.config.tab_spaces()); // Total of all items excluding the last. let almost_total = if extendable { @@ -964,7 +975,8 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { let mut root_rewrite = parent.rewrite_result(context, parent_shape)?; let multiline = root_rewrite.contains('\n'); self.offset = if multiline { - last_line_width(&root_rewrite).saturating_sub(shape.used_width()) + last_line_width(&root_rewrite, context.config.tab_spaces()) + .saturating_sub(shape.used_width()) } else { trimmed_last_line_width(&root_rewrite) }; @@ -979,7 +991,12 @@ impl<'a> ChainFormatter for ChainFormatterVisual<'a> { .visual_indent(self.offset) .sub_width(self.offset, item.span)?; let rewrite = item.rewrite_result(context, child_shape)?; - if filtered_str_fits(&rewrite, context.config.max_width(), shape) { + if filtered_str_fits( + &rewrite, + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) { root_rewrite.push_str(&rewrite); } else { // We couldn't fit in at the visual indent, try the last diff --git a/src/closures.rs b/src/closures.rs index 551e2e40425fd..c3340ae3e8bf9 100644 --- a/src/closures.rs +++ b/src/closures.rs @@ -348,7 +348,7 @@ fn rewrite_closure_fn_decl( prefix.push_str(&ret_str); } // 1 = space between `|...|` and body. - let extra_offset = last_line_width(&prefix) + 1; + let extra_offset = last_line_width(&prefix, context.config.tab_spaces()) + 1; Ok((prefix, extra_offset)) } diff --git a/src/comment.rs b/src/comment.rs index 4162b5f0db824..43e8e64a7a9a4 100644 --- a/src/comment.rs +++ b/src/comment.rs @@ -174,8 +174,9 @@ pub(crate) fn combine_strs_with_missing_comments( } else { " " }; - let mut one_line_width = - last_line_width(prev_str) + first_line_width(next_str) + first_sep.len(); + let mut one_line_width = last_line_width(prev_str, context.config.tab_spaces()) + + first_line_width(next_str) + + first_sep.len(); let config = context.config; let indent = shape.indent; @@ -207,7 +208,9 @@ pub(crate) fn combine_strs_with_missing_comments( let first_sep = if prev_str.is_empty() || missing_comment.is_empty() { Cow::from("") } else { - let one_line_width = last_line_width(prev_str) + first_line_width(&missing_comment) + 1; + let one_line_width = last_line_width(prev_str, context.config.tab_spaces()) + + first_line_width(&missing_comment) + + 1; if prefer_same_line && one_line_width <= shape.width { Cow::from(" ") } else { @@ -879,7 +882,8 @@ impl<'a> CommentRewrite<'a> { self.fmt.shape = if self.is_prev_line_multi_line { // 1 = " " - let offset = 1 + last_line_width(&self.result) - self.line_start.len(); + let offset = 1 + last_line_width(&self.result, self.fmt.config.tab_spaces()) + - self.line_start.len(); Shape { width: self.max_width.saturating_sub(offset), indent: self.fmt_indent, diff --git a/src/expr.rs b/src/expr.rs index 944367ce12378..f0e56ffb8ea1a 100644 --- a/src/expr.rs +++ b/src/expr.rs @@ -296,6 +296,7 @@ pub(crate) fn format_expr( wrap_str( context.snippet(expr.span).to_owned(), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, expr.span) @@ -550,7 +551,10 @@ fn rewrite_single_line_block( shape: Shape, ) -> RewriteResult { if let Some(block_expr) = stmt::Stmt::from_simple_block(context, block, attrs) { - let expr_shape = shape.offset_left(last_line_width(prefix), block_expr.span())?; + let expr_shape = shape.offset_left( + last_line_width(prefix, context.config.tab_spaces()), + block_expr.span(), + )?; let expr_str = block_expr.rewrite_result(context, expr_shape)?; let label_str = rewrite_label(context, label); let result = format!("{prefix}{label_str}{{ {expr_str} }}"); @@ -1039,7 +1043,8 @@ impl<'a> ControlFlow<'a> { }; // 1 = space after keyword. - let offset = last_line_width(&keyword) + label_string.len() + 1; + let offset = + last_line_width(&keyword, context.config.tab_spaces()) + label_string.len() + 1; let pat_expr_string = match self.cond { Some(cond) => self.rewrite_pat_expr(context, cond, constr_shape, offset)?, @@ -1114,10 +1119,13 @@ impl<'a> ControlFlow<'a> { }; let used_width = if pat_expr_string.contains('\n') { - last_line_width(&pat_expr_string) + last_line_width(&pat_expr_string, context.config.tab_spaces()) } else { // 2 = spaces after keyword and condition. - label_string.len() + last_line_width(&keyword) + pat_expr_string.len() + 2 + label_string.len() + + last_line_width(&keyword, context.config.tab_spaces()) + + pat_expr_string.len() + + 2 }; Ok(( @@ -1366,6 +1374,7 @@ pub(crate) fn rewrite_literal( _ => wrap_str( context.snippet(span).to_owned(), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, span), @@ -1384,8 +1393,13 @@ fn rewrite_string_lit(context: &RewriteContext<'_>, span: Span, shape: Shape) -> { return Ok(string_lit.to_owned()); } else { - return wrap_str(string_lit.to_owned(), context.config.max_width(), shape) - .max_width_error(shape.width, span); + return wrap_str( + string_lit.to_owned(), + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) + .max_width_error(shape.width, span); } } @@ -1426,6 +1440,7 @@ fn rewrite_int_lit( token_lit.suffix.as_ref().map_or("", |s| s.as_str()) ), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, span); @@ -1435,6 +1450,7 @@ fn rewrite_int_lit( wrap_str( context.snippet(span).to_owned(), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, span) @@ -1453,6 +1469,7 @@ fn rewrite_float_lit( return wrap_str( context.snippet(span).to_owned(), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, span); @@ -1501,6 +1518,7 @@ fn rewrite_float_lit( suffix.unwrap_or(""), ), context.config.max_width(), + context.config.tab_spaces(), shape, ) .max_width_error(shape.width, span) @@ -1725,7 +1743,7 @@ fn rewrite_index( ) -> RewriteResult { let expr_str = expr.rewrite_result(context, shape)?; - let offset = last_line_width(&expr_str) + 1; + let offset = last_line_width(&expr_str, context.config.tab_spaces()) + 1; let rhs_overhead = shape.rhs_overhead(context.config); let index_shape = if expr_str.contains('\n') { Shape::legacy(context.config.max_width(), shape.indent) @@ -2252,11 +2270,12 @@ pub(crate) fn rewrite_assign_rhs_expr( rhs_kind: &RhsAssignKind<'_>, rhs_tactics: RhsTactics, ) -> RewriteResult { - let last_line_width = last_line_width(lhs).saturating_sub(if lhs.contains('\n') { - shape.indent.width() - } else { - 0 - }); + let last_line_width = + last_line_width(lhs, context.config.tab_spaces()).saturating_sub(if lhs.contains('\n') { + shape.indent.width() + } else { + 0 + }); // 1 = space between operator and rhs. let orig_shape = shape.offset_left_opt(last_line_width + 1).unwrap_or(Shape { width: 0, @@ -2353,7 +2372,12 @@ fn choose_rhs( match (orig_rhs, new_rhs) { (Ok(ref orig_rhs), Ok(ref new_rhs)) - if !filtered_str_fits(&new_rhs, context.config.max_width(), new_shape) => + if !filtered_str_fits( + &new_rhs, + context.config.max_width(), + context.config.tab_spaces(), + new_shape, + ) => { Ok(format!("{before_space_str}{orig_rhs}")) } diff --git a/src/items.rs b/src/items.rs index 37dc231c3c45a..c5b09002644cd 100644 --- a/src/items.rs +++ b/src/items.rs @@ -103,7 +103,10 @@ impl Rewrite for ast::Local { } else { shape } - .offset_left(last_line_width(&result) + separator.len(), self.span())? + .offset_left( + last_line_width(&result, context.config.tab_spaces()) + separator.len(), + self.span(), + )? // 2 = ` =` .sub_width(2, self.span())?; @@ -433,7 +436,7 @@ impl<'a> FmtVisitor<'a> { // 2 = ` {` if self.config.brace_style() == BraceStyle::AlwaysNextLine || force_newline_brace - || last_line_width(&result) + 2 > self.shape().width + || last_line_width(&result, context.config.tab_spaces()) + 2 > self.shape().width { fn_brace_style = FnBraceStyle::NextLine } @@ -552,7 +555,7 @@ impl<'a> FmtVisitor<'a> { self.block_indent, // make a span that starts right after `enum Foo` mk_sp(ident.span.hi(), body_start), - last_line_width(&enum_header), + last_line_width(&enum_header, self.get_context().config.tab_spaces()), ) .unwrap(); self.push_str(&generics_str); @@ -806,10 +809,10 @@ pub(crate) fn format_impl( let where_budget = if result.contains('\n') { context.config.max_width() } else { - context.budget(last_line_width(&result)) + context.budget(last_line_width(&result, context.config.tab_spaces())) }; - let mut option = WhereClauseOption::snuggled(&ref_and_type); + let mut option = WhereClauseOption::snuggled(&ref_and_type, context.config.tab_spaces()); let snippet = context.snippet(item.span); let open_pos = snippet.find_uncommented("{").unknown_error()? + 1; if !contains_comment(&snippet[open_pos..]) @@ -844,7 +847,7 @@ pub(crate) fn format_impl( mk_sp(self_ty.span.hi(), hi), Shape::indented(offset, context.config), context, - last_line_width(&result), + last_line_width(&result, context.config.tab_spaces()), ) { Ok(ref missing_comment) if !missing_comment.is_empty() => { result.push_str(missing_comment); @@ -963,11 +966,17 @@ fn format_impl_ref_and_type( } let shape = if context.config.style_edition() >= StyleEdition::Edition2024 { - Shape::indented(offset + last_line_width(&result), context.config) + Shape::indented( + offset + last_line_width(&result, context.config.tab_spaces()), + context.config, + ) } else { generics_shape_from_config( context.config, - Shape::indented(offset + last_line_width(&result), context.config), + Shape::indented( + offset + last_line_width(&result, context.config.tab_spaces()), + context.config, + ), 0, item.span, )? @@ -981,7 +990,7 @@ fn format_impl_ref_and_type( ast::ImplPolarity::Negative(_) => "!", ast::ImplPolarity::Positive => "", }; - let result_len = last_line_width(&result); + let result_len = last_line_width(&result, context.config.tab_spaces()); result.push_str(&rewrite_trait_ref( context, &of_trait.trait_ref, @@ -1005,7 +1014,9 @@ fn format_impl_ref_and_type( } else { 0 }; - let used_space = last_line_width(&result) + trait_ref_overhead + curly_brace_overhead; + let used_space = last_line_width(&result, context.config.tab_spaces()) + + trait_ref_overhead + + curly_brace_overhead; // 1 = space before the type. let budget = context.budget(used_space + 1); if let Some(self_ty_str) = self_ty.rewrite(context, Shape::legacy(budget, offset)) { @@ -1028,7 +1039,7 @@ fn format_impl_ref_and_type( if of_trait.is_some() { result.push_str("for "); } - let budget = context.budget(last_line_width(&result)); + let budget = context.budget(last_line_width(&result, context.config.tab_spaces())); let type_offset = match context.config.indent_style() { IndentStyle::Visual => new_line_offset + trait_ref_overhead, IndentStyle::Block => new_line_offset, @@ -1203,13 +1214,13 @@ pub(crate) fn format_trait( if !generics.where_clause.predicates.is_empty() { let where_on_new_line = context.config.indent_style() != IndentStyle::Block; - let where_budget = context.budget(last_line_width(&result)); + let where_budget = context.budget(last_line_width(&result, context.config.tab_spaces())); let pos_before_where = if bounds.is_empty() { generics.where_clause.span.lo() } else { bounds[bounds.len() - 1].span().hi() }; - let option = WhereClauseOption::snuggled(&generics_str); + let option = WhereClauseOption::snuggled(&generics_str, context.config.tab_spaces()); let where_clause_str = rewrite_where_clause( context, &generics.where_clause, @@ -1225,7 +1236,9 @@ pub(crate) fn format_trait( // If the where-clause cannot fit on the same line, // put the where-clause on a new line if !where_clause_str.contains('\n') - && last_line_width(&result) + where_clause_str.len() + offset.width() + && last_line_width(&result, context.config.tab_spaces()) + + where_clause_str.len() + + offset.width() > context.config.comment_width() { let width = offset.block_indent + context.config.tab_spaces() - 1; @@ -1248,7 +1261,7 @@ pub(crate) fn format_trait( mk_sp(comment_lo, comment_hi), Shape::indented(offset, context.config), context, - last_line_width(&result), + last_line_width(&result, context.config.tab_spaces()), ) { Ok(ref missing_comment) if !missing_comment.is_empty() => { result.push_str(missing_comment); @@ -1265,7 +1278,8 @@ pub(crate) fn format_trait( match context.config.brace_style() { _ if last_line_contains_single_line_comment(&result) - || last_line_width(&result) + 2 > context.budget(offset.width()) => + || last_line_width(&result, context.config.tab_spaces()) + 2 + > context.budget(offset.width()) => { result.push_str(&offset.to_string_with_newline(context.config)); } @@ -1407,7 +1421,7 @@ fn format_unit_struct( offset, // make a span that starts right after `struct Foo` mk_sp(p.ident.span.hi(), hi), - last_line_width(&header_str), + last_line_width(&header_str, context.config.tab_spaces()), )? } else { String::new() @@ -1450,7 +1464,7 @@ pub(crate) fn format_struct_struct( offset, // make a span that starts right after `struct Foo` mk_sp(header_hi, body_lo), - last_line_width(&result), + last_line_width(&result, context.config.tab_spaces()), )?, None => { // 3 = ` {}`, 2 = ` {`. @@ -1534,7 +1548,7 @@ pub(crate) fn format_empty_struct_or_tuple( closer: &str, ) { // 3 = " {}" or "();" - let used_width = last_line_used_width(result, offset.width()) + 3; + let used_width = last_line_used_width(result, offset.width(), context.config.tab_spaces()) + 3; if used_width > context.config.max_width() { result.push_str(&offset.to_string_with_newline(context.config)) } @@ -1597,12 +1611,13 @@ fn format_tuple_struct( let where_clause_str = match struct_parts.generics { Some(generics) => { - let budget = context.budget(last_line_width(&header_str)); + let budget = context.budget(last_line_width(&header_str, context.config.tab_spaces())); let shape = Shape::legacy(budget, offset); let generics_str = rewrite_generics(context, "", generics, shape).ok()?; result.push_str(&generics_str); - let where_budget = context.budget(last_line_width(&result)); + let where_budget = + context.budget(last_line_width(&result, context.config.tab_spaces())); let option = WhereClauseOption::new(true, WhereClauseSpace::Newline); rewrite_where_clause( context, @@ -1776,8 +1791,8 @@ fn rewrite_ty( } } - let where_budget = context.budget(last_line_width(&result)); - let mut option = WhereClauseOption::snuggled(&result); + let where_budget = context.budget(last_line_width(&result, context.config.tab_spaces())); + let mut option = WhereClauseOption::snuggled(&result, context.config.tab_spaces()); if rhs.is_none() { option.suppress_comma(); } @@ -2145,7 +2160,7 @@ fn rewrite_static( // 2 = " =".len() let ty_shape = Shape::indented(offset.block_only(), context.config) - .offset_left_opt(last_line_width(&prefix) + 2)?; + .offset_left_opt(last_line_width(&prefix, context.config.tab_spaces()) + 2)?; let ty_str = match static_parts.ty.rewrite(context, ty_shape) { Some(ty_str) => ty_str, None => { @@ -2337,7 +2352,7 @@ impl Rewrite for ast::Param { result.push_str(&before_comment); result.push_str(colon_spaces(context.config)); result.push_str(&after_comment); - let overhead = last_line_width(&result); + let overhead = last_line_width(&result, context.config.tab_spaces()); let max_width = shape .width .checked_sub(overhead) @@ -2365,7 +2380,7 @@ impl Rewrite for ast::Param { result.push_str(&before_comment); result.push_str(colon_spaces(context.config)); result.push_str(&after_comment); - let overhead = last_line_width(&result); + let overhead = last_line_width(&result, context.config.tab_spaces()); let max_width = shape .width .checked_sub(overhead) @@ -2502,7 +2517,7 @@ fn rewrite_fn_base( // 2 = `()` 2 }; - let used_width = last_line_used_width(&result, indent.width()); + let used_width = last_line_used_width(&result, indent.width(), context.config.tab_spaces()); let one_line_budget = context.budget(used_width + overhead); let shape = Shape { width: one_line_budget, @@ -2597,7 +2612,8 @@ fn rewrite_fn_base( result.push(')'); } else { result.push_str(¶m_str); - let used_width = last_line_used_width(&result, indent.width()) + first_line_width(&ret_str); + let used_width = last_line_used_width(&result, indent.width(), context.config.tab_spaces()) + + first_line_width(&ret_str); // Put the closing brace on the next line if it overflows the max width. // 1 = `)` let closing_paren_overflow_max_width = @@ -2695,11 +2711,12 @@ fn rewrite_fn_base( let ret_shape = Shape::indented(indent, context.config); ret_shape - .offset_left_opt(last_line_width(&result)) + .offset_left_opt(last_line_width(&result, context.config.tab_spaces())) .unwrap_or(ret_shape) }; - let exceeds_max_width = last_line_width(&result) + ret_str_len > context.config.max_width(); + let exceeds_max_width = last_line_width(&result, context.config.tab_spaces()) + ret_str_len + > context.config.max_width(); if multi_line_ret_str || ret_should_indent @@ -2776,7 +2793,7 @@ fn rewrite_fn_base( mk_sp(ret_span.lo(), span.hi()), shape, context, - last_line_width(&result), + last_line_width(&result, context.config.tab_spaces()), ) { Ok(ref missing_comment) if !missing_comment.is_empty() => { result.push_str(missing_comment); @@ -2825,10 +2842,10 @@ impl WhereClauseOption { } } - fn snuggled(current: &str) -> WhereClauseOption { + fn snuggled(current: &str, tab_spaces: usize) -> WhereClauseOption { WhereClauseOption { suppress_comma: false, - snuggle: if last_line_width(current) == 1 { + snuggle: if last_line_width(current, tab_spaces) == 1 { WhereClauseSpace::Space } else { WhereClauseSpace::Newline @@ -3384,8 +3401,12 @@ fn format_generics( span.lo() }; let (same_line_brace, missed_comments) = if !generics.where_clause.predicates.is_empty() { - let budget = context.budget(last_line_used_width(&result, offset.width())); - let mut option = WhereClauseOption::snuggled(&result); + let budget = context.budget(last_line_used_width( + &result, + offset.width(), + context.config.tab_spaces(), + )); + let mut option = WhereClauseOption::snuggled(&result, context.config.tab_spaces()); if brace_pos == BracePos::None { option.suppress_comma = true; } @@ -3441,7 +3462,7 @@ fn format_generics( if brace_pos == BracePos::None { return Some(result); } - let total_used_width = last_line_used_width(&result, used_width); + let total_used_width = last_line_used_width(&result, used_width, context.config.tab_spaces()); let remaining_budget = context.budget(total_used_width); // If the same line brace if forced, it indicates that we are rewriting an item with empty body, // and hence we take the closer into account as well for one line budget. diff --git a/src/lists.rs b/src/lists.rs index 9d811e5d9b5e7..f567a191e1f90 100644 --- a/src/lists.rs +++ b/src/lists.rs @@ -425,7 +425,8 @@ where if tactic != DefinitiveListTactic::Horizontal && item.post_comment.is_some() { let comment = item.post_comment.as_ref().unwrap(); - let overhead = last_line_width(&result) + first_line_width(comment.trim()); + let overhead = last_line_width(&result, formatting.config.tab_spaces()) + + first_line_width(comment.trim()); let rewrite_post_comment = |item_max_width: &mut Option| { if item_max_width.is_none() && !last && !inner_item.contains('\n') { @@ -471,7 +472,7 @@ where let mut comment_alignment = post_comment_alignment(item_max_width, unicode_str_width(inner_item)); if first_line_width(&formatted_comment) - + last_line_width(&result) + + last_line_width(&result, formatting.config.tab_spaces()) + comment_alignment + 1 > formatting.config.max_width() diff --git a/src/macros.rs b/src/macros.rs index 7eb63d67580a3..9a88569b7909b 100644 --- a/src/macros.rs +++ b/src/macros.rs @@ -1380,7 +1380,12 @@ impl MacroBranch { } }; - if !filtered_str_fits(&new_body_snippet.snippet, config.max_width(), shape) { + if !filtered_str_fits( + &new_body_snippet.snippet, + config.max_width(), + context.config.tab_spaces(), + shape, + ) { return Err(RewriteError::ExceedsMaxWidth { configured_width: shape.width, span: self.span, diff --git a/src/missed_spans.rs b/src/missed_spans.rs index 0242094a75269..94ca9238ac045 100644 --- a/src/missed_spans.rs +++ b/src/missed_spans.rs @@ -266,7 +266,10 @@ impl<'a> FmtVisitor<'a> { self.block_indent } else { self.push_str(" "); - Indent::from_width(self.config, last_line_width(&self.buffer)) + Indent::from_width( + self.config, + last_line_width(&self.buffer, self.config.tab_spaces()), + ) }; let comment_shape = Shape::indented(comment_indent, self.config).comment(self.config); diff --git a/src/overflow.rs b/src/overflow.rs index 4230c89b57b48..9e9854278cff3 100644 --- a/src/overflow.rs +++ b/src/overflow.rs @@ -385,7 +385,7 @@ impl<'a> Context<'a> { // 1 = "(" or ")" let one_line_shape = shape - .offset_left_opt(last_line_width(ident) + 1) + .offset_left_opt(last_line_width(ident, context.config.tab_spaces()) + 1) .and_then(|shape| shape.sub_width_opt(1)) .unwrap_or(Shape { width: 0, ..shape }); let nested_shape = shape_from_indent_style(context, shape, used_width + 2, used_width + 1); @@ -669,7 +669,10 @@ impl<'a> Context<'a> { fn wrap_items(&self, items_str: &str, shape: Shape, is_extendable: bool) -> String { let shape = Shape { - width: shape.width.saturating_sub(last_line_width(self.ident)), + width: shape.width.saturating_sub(last_line_width( + self.ident, + self.context.config.tab_spaces(), + )), ..shape }; diff --git a/src/pairs.rs b/src/pairs.rs index 48948b88b3be2..b4e390f206167 100644 --- a/src/pairs.rs +++ b/src/pairs.rs @@ -86,7 +86,8 @@ fn rewrite_pairs_one_line( let prefix_len = result.len(); let last = list.list.last()?.0; - let cur_shape = base_shape.offset_left_opt(last_line_width(&result))?; + let cur_shape = + base_shape.offset_left_opt(last_line_width(&result, context.config.tab_spaces()))?; let last_rewrite = last.rewrite(context, cur_shape)?; result.push_str(&last_rewrite); @@ -102,7 +103,12 @@ fn rewrite_pairs_one_line( return None; } - wrap_str(result, context.config.max_width(), shape) + wrap_str( + result, + context.config.max_width(), + context.config.tab_spaces(), + shape, + ) } fn rewrite_pairs_multiline( @@ -132,7 +138,9 @@ fn rewrite_pairs_multiline( } else { shape.used_width() }; - if last_line_width(&result) + offset <= nested_shape.used_width() { + if last_line_width(&result, context.config.tab_spaces()) + offset + <= nested_shape.used_width() + { // We must snuggle the next line onto the previous line to avoid an orphan. if let Some(line_shape) = shape.offset_left_opt(s.len() + 2 + trimmed_last_line_width(&result)) @@ -193,7 +201,7 @@ where // Try to put both lhs and rhs on the same line. let rhs_orig_result = shape - .offset_left_opt(last_line_width(&lhs_result) + pp.infix.len()) + .offset_left_opt(last_line_width(&lhs_result, tab_spaces) + pp.infix.len()) .and_then(|s| s.sub_width_opt(pp.suffix.len())) .and_then(|rhs_shape| rhs.rewrite_result(context, rhs_shape).ok()); @@ -208,7 +216,7 @@ where .map(|first_line| first_line.ends_with('{')) .unwrap_or(false); if !rhs_result.contains('\n') || allow_same_line { - let one_line_width = last_line_width(&lhs_result) + let one_line_width = last_line_width(&lhs_result, tab_spaces) + pp.infix.len() + first_line_width(rhs_result) + pp.suffix.len(); diff --git a/src/string.rs b/src/string.rs index 59c445f904b9e..af90bb055c85f 100644 --- a/src/string.rs +++ b/src/string.rs @@ -150,7 +150,12 @@ pub(crate) fn rewrite_string<'a>( } result.push_str(fmt.closer); - wrap_str(result, fmt.config.max_width(), fmt.shape) + wrap_str( + result, + fmt.config.max_width(), + fmt.config.tab_spaces(), + fmt.shape, + ) } /// Returns the index to the end of the URL if the split at index of the given string includes a diff --git a/src/types.rs b/src/types.rs index b8e072c7c6956..e2c92e58062ae 100644 --- a/src/types.rs +++ b/src/types.rs @@ -416,7 +416,10 @@ fn format_function_type( shape.block().indent.to_string_with_newline(context.config), ) }; - if output.is_empty() || last_line_width(&args) + first_line_width(&output) <= shape.width { + if output.is_empty() + || last_line_width(&args, context.config.tab_spaces()) + first_line_width(&output) + <= shape.width + { Ok(format!("{args}{output}")) } else { Ok(format!( @@ -484,7 +487,9 @@ impl Rewrite for ast::WherePredicate { let mut result = String::with_capacity(attrs_str.len() + pred_str.len() + 1); result.push_str(&attrs_str); let pred_start = self.span.lo(); - let line_len = last_line_width(&attrs_str) + 1 + first_line_width(&pred_str); + let line_len = last_line_width(&attrs_str, context.config.tab_spaces()) + + 1 + + first_line_width(&pred_str); if let Some(last_attr) = self.attrs.last().filter(|last_attr| { contains_comment(context.snippet(mk_sp(last_attr.span.hi(), pred_start))) }) { @@ -578,7 +583,7 @@ fn rewrite_bounded_lifetime( Ok(result) } else { let colon = type_bound_colon(context); - let overhead = last_line_width(&result) + colon.len(); + let overhead = last_line_width(&result, context.config.tab_spaces()) + colon.len(); let shape = shape.sub_width(overhead, span)?; let result = format!( "{}{}{}", @@ -895,7 +900,7 @@ impl Rewrite for ast::Ty { true, )?; } else { - let used_width = last_line_width(&result); + let used_width = last_line_width(&result, context.config.tab_spaces()); let budget = shape .width .checked_sub(used_width) diff --git a/src/utils.rs b/src/utils.rs index a3f2d8b1534b5..6f9fa7ff7024f 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -261,15 +261,17 @@ pub(crate) fn first_line_width(s: &str) -> usize { /// The width of the last line in s. #[inline] -pub(crate) fn last_line_width(s: &str) -> usize { - unicode_str_width(s.rsplitn(2, '\n').next().unwrap_or("")) +pub(crate) fn last_line_width(s: &str, tab_spaces: usize) -> usize { + let last_line = s.rsplitn(2, '\n').next().unwrap_or(""); + let (prefix_width, prefix_end) = get_prefix_space_width_and_end(last_line, tab_spaces); + prefix_width + unicode_str_width(&last_line[prefix_end..]) } /// The total used width of the last line. #[inline] -pub(crate) fn last_line_used_width(s: &str, offset: usize) -> usize { +pub(crate) fn last_line_used_width(s: &str, offset: usize, tab_spaces: usize) -> usize { if s.contains('\n') { - last_line_width(s) + last_line_width(s, tab_spaces) } else { offset + unicode_str_width(s) } @@ -450,15 +452,25 @@ macro_rules! skip_out_of_file_lines_range_visitor { // Wraps String in an Option. Returns Some when the string adheres to the // Rewrite constraints defined for the Rewrite trait and None otherwise. -pub(crate) fn wrap_str(s: String, max_width: usize, shape: Shape) -> Option { - if filtered_str_fits(&s, max_width, shape) { +pub(crate) fn wrap_str( + s: String, + max_width: usize, + tab_spaces: usize, + shape: Shape, +) -> Option { + if filtered_str_fits(&s, max_width, tab_spaces, shape) { Some(s) } else { None } } -pub(crate) fn filtered_str_fits(snippet: &str, max_width: usize, shape: Shape) -> bool { +pub(crate) fn filtered_str_fits( + snippet: &str, + max_width: usize, + tab_spaces: usize, + shape: Shape, +) -> bool { let snippet = &filter_normal_code(snippet); if !snippet.is_empty() { // First line must fits with `shape.width`. @@ -479,7 +491,7 @@ pub(crate) fn filtered_str_fits(snippet: &str, max_width: usize, shape: Shape) - } // A special check for the last line, since the caller may // place trailing characters on this line. - if last_line_width(snippet) > shape.used_width() + shape.width { + if last_line_width(snippet, tab_spaces) > shape.used_width() + shape.width { return false; } } diff --git a/src/visitor.rs b/src/visitor.rs index b3ba0f2df2cdb..5043038d4fc09 100644 --- a/src/visitor.rs +++ b/src/visitor.rs @@ -277,7 +277,8 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { let align_to_right = if unindent_comment && contains_comment(comment_snippet) { let first_lines = comment_snippet.splitn(2, '/').next().unwrap_or(""); - last_line_width(first_lines) > last_line_width(comment_snippet) + last_line_width(first_lines, config.tab_spaces()) + > last_line_width(comment_snippet, config.tab_spaces()) } else { false }; @@ -330,7 +331,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { } else { if comment_on_same_line { // 1 = a space before `//` - let offset_len = 1 + last_line_width(&self.buffer) + let offset_len = 1 + last_line_width(&self.buffer, config.tab_spaces()) .saturating_sub(self.block_indent.width()); match comment_shape .visual_indent(offset_len) diff --git a/tests/target/issue_6859_hard_tab_breaks.rs b/tests/target/issue_6859_hard_tab_breaks.rs new file mode 100644 index 0000000000000..c83dc3637b87b --- /dev/null +++ b/tests/target/issue_6859_hard_tab_breaks.rs @@ -0,0 +1,11 @@ +// rustfmt-hard_tabs: true + +fn testing() { + let _ = some_long_name + | if some_other_long_name { + foo + } + | if some_other_name { + bar + }; +} From a757a1355310f18667039f79862d1411a497e18c Mon Sep 17 00:00:00 2001 From: kulinsky Date: Tue, 15 Sep 2026 23:48:57 +0500 Subject: [PATCH 0249/1309] Avoid suggesting closures when captures cross associated item boundaries --- .../rustc_resolve/src/diagnostics/impls.rs | 7 +++-- compiler/rustc_resolve/src/diagnostics/mod.rs | 3 +- compiler/rustc_resolve/src/ident.rs | 8 +++++- compiler/rustc_resolve/src/lib.rs | 2 +- .../ui/resolve/closure-suggestion-in-impl.rs | 28 +++++++++++++++++++ .../resolve/closure-suggestion-in-impl.stderr | 23 +++++++++++++++ .../impl-method-cant-capture-env.stderr | 2 -- ...mpl-trait-for-type-cant-capture-env.stderr | 2 -- .../trait-impl-cant-capture-env.stderr | 4 --- 9 files changed, 66 insertions(+), 13 deletions(-) create mode 100644 tests/ui/resolve/closure-suggestion-in-impl.rs create mode 100644 tests/ui/resolve/closure-suggestion-in-impl.stderr diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 3fc2f55bbaec6..116d95c59d100 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1180,8 +1180,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err } - ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => { - self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem { span }) + ResolutionError::CannotCaptureDynamicEnvironmentInFnItem { suggest_closure } => { + self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem { + span, + suggest_closure, + }) } ResolutionError::AttemptToUseNonConstantValueInConstant { ident, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index b581777901195..755f0769419d2 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -268,10 +268,11 @@ pub(crate) struct UnreachableLabelWithSimilarNameExists { #[derive(Diagnostic)] #[diag("can't capture dynamic environment in a fn item", code = E0434)] -#[help("use the `|| {\"{\"} ... {\"}\"}` closure form instead")] pub(crate) struct CannotCaptureDynamicEnvironmentInFnItem { #[primary_span] pub(crate) span: Span, + #[help("use the `|| {\"{\"} ... {\"}\"}` closure form instead")] + pub(crate) suggest_closure: bool, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 85457bbba5da7..0d801696ca389 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1506,6 +1506,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { use ResolutionError::*; let mut res_err = None; + let suggest_closure = + !ribs.iter().any(|rib| matches!(rib.kind, RibKind::AssocItem)); + for rib in ribs { match rib.kind { RibKind::Normal @@ -1525,7 +1528,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // we want certain other resolution errors (namely those // emitted for `ConstantItemRibKind` below) to take // precedence. - res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem)); + res_err = Some(( + span, + CannotCaptureDynamicEnvironmentInFnItem { suggest_closure }, + )); } } RibKind::ConstantItem(_, item, requires_type) => { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ce03e1a70399c..055e4f56d2710 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -275,7 +275,7 @@ enum ResolutionError<'ra> { message: String, }, /// Error E0434: can't capture dynamic environment in a fn item. - CannotCaptureDynamicEnvironmentInFnItem, + CannotCaptureDynamicEnvironmentInFnItem { suggest_closure: bool }, /// Error E0435: attempt to use a non-constant value in a constant. AttemptToUseNonConstantValueInConstant { ident: Ident, diff --git a/tests/ui/resolve/closure-suggestion-in-impl.rs b/tests/ui/resolve/closure-suggestion-in-impl.rs new file mode 100644 index 0000000000000..ab05e67f9538e --- /dev/null +++ b/tests/ui/resolve/closure-suggestion-in-impl.rs @@ -0,0 +1,28 @@ +trait T { + fn t() -> impl FnOnce() -> (); +} + +fn f(x: String) { + struct S; + impl T for S { + fn t() -> impl FnOnce() -> () { + move || { + let _ = x; //~ ERROR can't capture dynamic environment in a fn item + } + } + } + + impl S { + fn foo() { + let bar = 42; + + fn inner() { + let _ = bar; //~ ERROR can't capture dynamic environment in a fn item + + let _ = x; //~ ERROR can't capture dynamic environment in a fn item + } + } + } +} + +fn main() {} diff --git a/tests/ui/resolve/closure-suggestion-in-impl.stderr b/tests/ui/resolve/closure-suggestion-in-impl.stderr new file mode 100644 index 0000000000000..6382df9c61b55 --- /dev/null +++ b/tests/ui/resolve/closure-suggestion-in-impl.stderr @@ -0,0 +1,23 @@ +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/closure-suggestion-in-impl.rs:10:25 + | +LL | let _ = x; + | ^ + +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/closure-suggestion-in-impl.rs:20:25 + | +LL | let _ = bar; + | ^^^ + | + = help: use the `|| { ... }` closure form instead + +error[E0434]: can't capture dynamic environment in a fn item + --> $DIR/closure-suggestion-in-impl.rs:22:25 + | +LL | let _ = x; + | ^ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0434`. diff --git a/tests/ui/resolve/impl-method-cant-capture-env.stderr b/tests/ui/resolve/impl-method-cant-capture-env.stderr index 360598dee5827..4a525db70ae2c 100644 --- a/tests/ui/resolve/impl-method-cant-capture-env.stderr +++ b/tests/ui/resolve/impl-method-cant-capture-env.stderr @@ -3,8 +3,6 @@ error[E0434]: can't capture dynamic environment in a fn item | LL | self.v0 = k0 ^ 0x736f6d6570736575; | ^^ - | - = help: use the `|| { ... }` closure form instead error: aborting due to 1 previous error diff --git a/tests/ui/resolve/impl-trait-for-type-cant-capture-env.stderr b/tests/ui/resolve/impl-trait-for-type-cant-capture-env.stderr index 2c25f6b1b8954..4a7c5263ff8df 100644 --- a/tests/ui/resolve/impl-trait-for-type-cant-capture-env.stderr +++ b/tests/ui/resolve/impl-trait-for-type-cant-capture-env.stderr @@ -3,8 +3,6 @@ error[E0434]: can't capture dynamic environment in a fn item | LL | self.v0 = k0 ^ 0x736f6d6570736575; | ^^ - | - = help: use the `|| { ... }` closure form instead error: aborting due to 1 previous error diff --git a/tests/ui/resolve/trait-impl-cant-capture-env.stderr b/tests/ui/resolve/trait-impl-cant-capture-env.stderr index 3c80960a235cb..257e30ea0d85b 100644 --- a/tests/ui/resolve/trait-impl-cant-capture-env.stderr +++ b/tests/ui/resolve/trait-impl-cant-capture-env.stderr @@ -3,16 +3,12 @@ error[E0434]: can't capture dynamic environment in a fn item | LL | self.v0 = k0 ^ 0x736f6d6570736575; | ^^ - | - = help: use the `|| { ... }` closure form instead error[E0434]: can't capture dynamic environment in a fn item --> $DIR/trait-impl-cant-capture-env.rs:25:23 | LL | self.v1 = k1 ^ 0x646f72616e646f6d; | ^^ - | - = help: use the `|| { ... }` closure form instead error: aborting due to 2 previous errors From 5040a040c961df16814ca4101d6485da91bee594 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Tue, 15 Sep 2026 22:19:41 +0300 Subject: [PATCH 0250/1309] docs: PanicInfo::location handling example with no location --- library/core/src/panic/panic_info.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index 6812e2758ed02..d8d4073c83b9e 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -75,6 +75,8 @@ impl<'a> PanicInfo<'a> { /// fn panic_handler(panic_info: &PanicInfo<'_>) -> ! { /// if let Some(location) = panic_info.location() { /// write!(DEBUG_OUTPUT, "panicked at {}", location); + /// } else { + /// write!(DEBUG_OUTPUT, "panicked at unknown location"); /// } /// loop {} /// } From 01da50fc26d00a33b4f8bf23596877d96b6adf80 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 15 Sep 2026 18:44:09 -0700 Subject: [PATCH 0251/1309] Account for split text events in bare urls lint Co-authored-by: malezjaa --- src/librustdoc/passes/lint/bare_urls.rs | 20 ++++++------- tests/rustdoc-ui/lints/bare-urls.fixed | 12 ++++++++ tests/rustdoc-ui/lints/bare-urls.rs | 12 ++++++++ tests/rustdoc-ui/lints/bare-urls.stderr | 38 ++++++++++++++++++++++++- 4 files changed, 71 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 0928980e390a8..8eaa8f45e4651 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -2,13 +2,14 @@ //! Suggests wrapping the link with angle brackets: `Go to .` to linkify it. use core::ops::Range; -use std::mem; use std::sync::LazyLock; use regex::Regex; use rustc_errors::{Applicability, DiagDecorator}; use rustc_hir::HirId; -use rustc_resolve::rustdoc::pulldown_cmark::{Event, Parser, Tag}; +use rustc_resolve::rustdoc::pulldown_cmark::{ + DefaultBrokenLinkCallback, Event, Tag, TextMergeWithOffset, +}; use rustc_resolve::rustdoc::source_span_for_markdown_range; use tracing::trace; @@ -55,21 +56,20 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & ); }; - let mut p = Parser::new_ext(dox, main_body_opts()).into_offset_iter(); + // pulldown-cmark can split a URL into multiple `Text` events while processing + // characters such as `_` according to CommonMark's emphasis rules. + // `TextMergeWithOffset` merges these events so we can check the complete URL. + let mut p = TextMergeWithOffset::::new_ext(dox, main_body_opts()); while let Some((event, range)) = p.next() { match event { Event::Text(s) => find_raw_urls(cx, dox, &s, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { + let end = tag.to_end(); for (event, _) in p.by_ref() { - match event { - Event::End(end) - if mem::discriminant(&end) == mem::discriminant(&tag.to_end()) => - { - break; - } - _ => {} + if matches!(event, Event::End(tag) if tag == end) { + break; } } } diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed index 996214b5ff14f..b0c0b33076d0c 100644 --- a/tests/rustdoc-ui/lints/bare-urls.fixed +++ b/tests/rustdoc-ui/lints/bare-urls.fixed @@ -92,3 +92,15 @@ pub fn trailing_period() {} /// ] //~^ ERROR this URL is not a hyperlink pub fn lint_with_brackets() {} + +/// See +//~^ ERROR this URL is not a hyperlink +pub fn underscore_without_parens_1() {} + +/// See +//~^ ERROR this URL is not a hyperlink +pub fn underscore_without_parens_2() {} + +/// See __ +//~^ ERROR this URL is not a hyperlink +pub fn underscore_emphasis_without_parens() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs index 9b4fe68e00322..2fe82a8b713df 100644 --- a/tests/rustdoc-ui/lints/bare-urls.rs +++ b/tests/rustdoc-ui/lints/bare-urls.rs @@ -92,3 +92,15 @@ pub fn trailing_period() {} /// https://bloob.blob] //~^ ERROR this URL is not a hyperlink pub fn lint_with_brackets() {} + +/// See https://example.com/test_.html +//~^ ERROR this URL is not a hyperlink +pub fn underscore_without_parens_1() {} + +/// See https://example.com/test._html +//~^ ERROR this URL is not a hyperlink +pub fn underscore_without_parens_2() {} + +/// See _https://example.com/test.html_ +//~^ ERROR this URL is not a hyperlink +pub fn underscore_emphasis_without_parens() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr index 05ddd2ed42ab1..1449d03b608b0 100644 --- a/tests/rustdoc-ui/lints/bare-urls.stderr +++ b/tests/rustdoc-ui/lints/bare-urls.stderr @@ -364,5 +364,41 @@ help: use an automatic link instead LL | /// ] | + + -error: aborting due to 30 previous errors +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:96:9 + | +LL | /// See https://example.com/test_.html + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:100:9 + | +LL | /// See https://example.com/test._html + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:104:10 + | +LL | /// See _https://example.com/test.html_ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See __ + | + + + +error: aborting due to 33 previous errors From 8e4f28735b925ddb54f8ab5dfbe45cf2e7bcbed2 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Tue, 15 Sep 2026 19:31:08 -0700 Subject: [PATCH 0252/1309] Account for nested parens in bare urls lint --- src/librustdoc/passes/lint/bare_urls.rs | 47 +++++++++- tests/rustdoc-ui/lints/bare-urls.fixed | 39 +++++++++ tests/rustdoc-ui/lints/bare-urls.rs | 39 +++++++++ tests/rustdoc-ui/lints/bare-urls.stderr | 110 +++++++++++++++++++++++- 4 files changed, 230 insertions(+), 5 deletions(-) diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 8eaa8f45e4651..ed9fcdfaaa448 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -78,12 +78,11 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & } } -static URL_REGEX: LazyLock = LazyLock::new(|| { +static URL_SCHEME_HOST_REGEX: LazyLock = LazyLock::new(|| { Regex::new(concat!( r"https?://", // url scheme r"([-a-zA-Z0-9@:%._\+~#=]{2,256}\.)+", // one or more subdomains r"[a-zA-Z]{2,63}", // root domain - r"\b([-a-zA-Z0-9@:%_\+.~#?&/=]*)", // optional query or url fragments )) .expect("failed to build regex") }); @@ -97,8 +96,48 @@ fn find_raw_urls( ) { trace!("looking for raw urls in {text}"); // For now, we only check "full" URLs (meaning, starting with "http://" or "https://"). - for match_ in URL_REGEX.find_iter(text) { + for match_ in URL_SCHEME_HOST_REGEX.find_iter(text) { let mut url_range = match_.range(); + // We found the scheme and host. Find the path, now. + // We want to check for matching, balanced parens, + // but regex isn't powerful enough for that. + let mut paren_stack = Vec::with_capacity(3); + while let Some(&c) = text.as_bytes().get(url_range.end) { + if c == b'(' { + paren_stack.push(url_range.end); + } else if c == b')' { + if paren_stack.pop().is_none() { + break; + } + } else if !matches!( + c, + b'-' + | b'a'..=b'z' + | b'A'..=b'Z' + | b'0'..=b'9' + | b'@' + | b':' + | b'%' + | b'_' + | b'\\' + | b'+' + | b'.' + | b'~' + | b'#' + | b'?' + | b'&' + | b'/' + | b'=' + ) { + break; + } + url_range.end += 1; + } + if let Some(&end) = paren_stack.first() { + url_range.end = end; + } + // We have a range within `text`. + // We need a range within `dox` to report the diagnostic. url_range.start += range.start; url_range.end += range.start; let mut without_brackets = None; @@ -117,7 +156,7 @@ fn find_raw_urls( // period out of the link, so that `Visit https://example.com/docs.` is linkified as // `Visit .`. let trailing_periods = - match_.as_str().len() - match_.as_str().trim_end_matches('.').len(); + dox[url_range.clone()].len() - dox[url_range.clone()].trim_end_matches('.').len(); url_range.end -= trailing_periods; } f(cx, "this URL is not a hyperlink", url_range, without_brackets); diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed index b0c0b33076d0c..20d04a8a9727b 100644 --- a/tests/rustdoc-ui/lints/bare-urls.fixed +++ b/tests/rustdoc-ui/lints/bare-urls.fixed @@ -104,3 +104,42 @@ pub fn underscore_without_parens_2() {} /// See __ //~^ ERROR this URL is not a hyperlink pub fn underscore_emphasis_without_parens() {} + +/// See +//~^ ERROR this URL is not a hyperlink +pub fn wikipedia_example() {} + +/// See () +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_1() {} + +/// See (1()) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_2() {} + +/// See (1( +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_3() {} + +/// See ) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_1() {} + +/// See (. +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_2() {} + +/// See .( +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_3() {} + +/// See ). +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_4() {} + +/// See .) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_5() {} + +/// See http://ex(amp)le.com/ +pub fn nested_parens_cannot_appear_in_host() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs index 2fe82a8b713df..12ab7b32e8bcb 100644 --- a/tests/rustdoc-ui/lints/bare-urls.rs +++ b/tests/rustdoc-ui/lints/bare-urls.rs @@ -104,3 +104,42 @@ pub fn underscore_without_parens_2() {} /// See _https://example.com/test.html_ //~^ ERROR this URL is not a hyperlink pub fn underscore_emphasis_without_parens() {} + +/// See https://en.wikipedia.org/wiki/Rust_(programming_language) +//~^ ERROR this URL is not a hyperlink +pub fn wikipedia_example() {} + +/// See (http://example.com/(1(2))) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_1() {} + +/// See (1(http://example.com/1(2))) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_2() {} + +/// See (1(http://example.com/1(.) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_balanced_3() {} + +/// See http://example.com/(1(2))) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_1() {} + +/// See http://example.com/test(. +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_2() {} + +/// See http://example.com/test.( +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_3() {} + +/// See http://example.com/test). +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_4() {} + +/// See http://example.com/test.) +//~^ ERROR this URL is not a hyperlink +pub fn nested_parens_unbalanced_5() {} + +/// See http://ex(amp)le.com/ +pub fn nested_parens_cannot_appear_in_host() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr index 1449d03b608b0..1f39f90106f1f 100644 --- a/tests/rustdoc-ui/lints/bare-urls.stderr +++ b/tests/rustdoc-ui/lints/bare-urls.stderr @@ -400,5 +400,113 @@ help: use an automatic link instead LL | /// See __ | + + -error: aborting due to 33 previous errors +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:108:9 + | +LL | /// See https://en.wikipedia.org/wiki/Rust_(programming_language) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:112:10 + | +LL | /// See (http://example.com/(1(2))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See () + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:116:12 + | +LL | /// See (1(http://example.com/1(2))) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See (1()) + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:120:12 + | +LL | /// See (1(http://example.com/1(.) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See (1( + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:124:9 + | +LL | /// See http://example.com/(1(2))) + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See ) + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:128:9 + | +LL | /// See http://example.com/test(. + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See (. + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:132:9 + | +LL | /// See http://example.com/test.( + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See .( + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:136:9 + | +LL | /// See http://example.com/test). + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See ). + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:140:9 + | +LL | /// See http://example.com/test.) + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// See .) + | + + + +error: aborting due to 42 previous errors From a1864bdeb0c5252093ca7948f83d793ef712f555 Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 15 Sep 2026 23:07:58 -0400 Subject: [PATCH 0253/1309] Ping T-libs-ping instead of T-libs-fcp for backports --- triagebot.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index fc9c43d2dbcae..67799f0a944ef 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -850,7 +850,7 @@ zulip_stream = 542373 # #t-libs/backports topic = "#{number}: beta-nominated" message_on_add = [ """\ -@*T-libs-fcp* PR #{number} "{title}" has been nominated for beta backport. +@*T-libs-ping* PR #{number} "{title}" has been nominated for beta backport. """, """\ /poll Should #{number} be beta backported? @@ -874,7 +874,7 @@ zulip_stream = 542373 # #t-libs/backports topic = "#{number}: stable-nominated" message_on_add = [ """\ -@*T-libs-fcp* PR #{number} "{title}" has been nominated for stable backport. +@*T-libs-ping* PR #{number} "{title}" has been nominated for stable backport. """, """\ /poll Approve stable backport of #{number}? From 84009ab481caa2b5cb52aeab9252ca8c39f6356c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 16 Sep 2026 13:29:17 +1000 Subject: [PATCH 0254/1309] Introduce `ast::UseTreeAndId` Currently a `NodeId` is stored in a pair with each nested use tree. This commit changes the pair to a named type `UseTreeAndId`. In most places this doesn't make much difference but in the AST visitor it gets rid of several weird special cases. --- src/imports.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/imports.rs b/src/imports.rs index c5a2a5de2f175..f062eaa332d92 100644 --- a/src/imports.rs +++ b/src/imports.rs @@ -477,7 +477,7 @@ impl UseTree { // This needs to be done before sorting use items. let items = itemize_list( context.snippet_provider, - list.iter().map(|(tree, _)| tree), + list.iter().map(|tree| &tree.inner), "}", ",", |tree| tree.prefix.span.lo(), @@ -501,7 +501,7 @@ impl UseTree { list.iter() .zip(items) .map(|(t, list_item)| { - Self::from_ast(context, &t.0, Some(list_item), None, None, None) + Self::from_ast(context, &t.inner, Some(list_item), None, None, None) }) .collect(), ); From aa95ad8a2753a03e98ceedc243b7cfc883adf592 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 28 Aug 2026 13:45:54 +1000 Subject: [PATCH 0255/1309] Split `build_session` Session creation is currently awkward: we build a mostly-initialized session, then use it to initialize a codegen backend, and then use the codegen backend to finish initializing the session. And it's not just awkward: within the Cranelift backend's `init` method `sess.lto()` is called, which consults `sess.thin_lto_supported`, *before* that field has been properly set! In practice it had no effect but it's worth fixing. This commit cleans up this mess. It introduces `EarlySession`, which contains just four `Session` fields, the ones that are needed for codegen backend initialization. It is now a field within `Session`, and `Session` derefs to `EarlySession` to avoid changing a zillion `sess.target`/`sess.opts`/etc. occurrences. `EarlySession` is passed to `init`, which returns a `CodegenBackendInit` that contains the backend-specific information needed to build a `Session`. (It replaces the `replaced_intrinsics`, `fallback_intrinsics`, and `thin_lto_supported` methods.) The `Session` can then be built in a single step. No more `Session`/`CodegenBackend` initialization intermingling. A few functions that previously took a `Session` now take something else, e.g. a `Target`. Some `Session` methods are now `EarlySession` methods. And a new `early_lto` method is used for Cranelift's LTO check. --- src/attributes.rs | 2 +- src/context.rs | 4 ++-- src/gcc_util.rs | 18 +++++++++--------- src/intrinsic/mod.rs | 2 +- src/lib.rs | 24 +++++++++++------------- 5 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index ce1877b308e94..321e150a1568d 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -124,7 +124,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( .target_features .iter() .map(|features| features.name.as_str()) - .flat_map(|feat| to_gcc_features(cx.tcx.sess, feat).into_iter()) + .flat_map(|feat| to_gcc_features(&cx.tcx.sess.target, feat).into_iter()) .chain(codegen_fn_attrs.instruction_set.iter().map(|x| match *x { InstructionSetAttr::ArmA32 => "-thumb-mode", // FIXME(antoyo): support removing feature. InstructionSetAttr::ArmT32 => "thumb-mode", diff --git a/src/context.rs b/src/context.rs index 64f9982ac7de6..38e0e5f329f76 100644 --- a/src/context.rs +++ b/src/context.rs @@ -450,7 +450,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { } let tcx = self.tcx; let func = match tcx.lang_items().eh_personality() { - Some(def_id) if !wants_msvc_seh(self.sess()) => { + Some(def_id) if !wants_msvc_seh(&self.sess().target) => { let instance = ty::Instance::expect_resolve( tcx, self.typing_env(), @@ -465,7 +465,7 @@ impl<'gcc, 'tcx> MiscCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { self.declare_fn(symbol_name, fn_abi) } _ => { - let name = if wants_msvc_seh(self.sess()) { + let name = if wants_msvc_seh(&self.sess().target) { "__CxxFrameHandler3" } else { "rust_eh_personality" diff --git a/src/gcc_util.rs b/src/gcc_util.rs index a95b4da28eb63..24f552fed32c6 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -2,18 +2,18 @@ use gccjit::Context; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; -use rustc_session::Session; +use rustc_session::EarlySession; use rustc_session::config::NATIVE_CPU; -use rustc_target::spec::Arch; +use rustc_target::spec::{Arch, Target}; -fn gcc_features_by_flags(sess: &Session, features: &mut Vec) { +fn gcc_features_by_flags(sess: &EarlySession, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); // FIXME: LLVM also sets +reserve-x18 here under some conditions. } /// The list of GCC features computed from CLI flags (`-Ctarget-cpu`, `-Ctarget-feature`, /// `--target` and similar). -pub(crate) fn global_gcc_features(sess: &Session) -> Vec { +pub(crate) fn global_gcc_features(sess: &EarlySession) -> Vec { // Features that come earlier are overridden by conflicting features later in the string. // Typically we'll want more explicit settings to override the implicit ones, so: // @@ -40,9 +40,9 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { // features also work on the command line instead of having two // different names when the GCC name and the Rust name differ. features.extend( - to_gcc_features(sess, feature) + to_gcc_features(&sess.target, feature) .iter() - .flat_map(|feat| to_gcc_features(sess, feat).into_iter()) + .flat_map(|feat| to_gcc_features(&sess.target, feat).into_iter()) .map(|feature| if !enable { format!("-{}", feature) } else { feature.to_string() }), ); }; @@ -59,9 +59,9 @@ pub(crate) fn global_gcc_features(sess: &Session) -> Vec { } // To find a list of GCC's names, check https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html -pub fn to_gcc_features<'a>(sess: &Session, s: &'a str) -> SmallVec<[&'a str; 2]> { +pub fn to_gcc_features<'a>(target: &Target, s: &'a str) -> SmallVec<[&'a str; 2]> { // cSpell:disable - match (&sess.target.arch, s) { + match (&target.arch, s) { // FIXME: seems like x87 does not exist? (&Arch::X86 | &Arch::X86_64, "x87") => smallvec![], (&Arch::X86 | &Arch::X86_64, "sse4.2") => smallvec!["sse4.2", "crc32"], @@ -130,7 +130,7 @@ fn handle_native(name: &str) -> &str { unimplemented!(); } -pub fn target_cpu(sess: &Session) -> &str { +pub fn target_cpu(sess: &EarlySession) -> &str { match sess.opts.cg.target_cpu { Some(ref name) => handle_native(name), None => handle_native(sess.target.cpu.as_ref()), diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 624cd2dcb7327..41fa7b3f9f162 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -1352,7 +1352,7 @@ fn try_intrinsic<'a, 'b, 'gcc, 'tcx>( // we can never unwind. OperandValue::Immediate(bx.const_bool(false)).store(bx, dest); } else { - if wants_msvc_seh(bx.sess()) { + if wants_msvc_seh(&bx.sess().target) { unimplemented!(); } #[cfg(feature = "master")] diff --git a/src/lib.rs b/src/lib.rs index 2fb5459a20283..6e40827c48405 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,7 +95,7 @@ use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; use rustc_middle::util::Providers; use rustc_session::config::{OptLevel, OutputFilenames}; -use rustc_session::{IncrCompSession, Session}; +use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; use rustc_span::{Symbol, sym}; use rustc_target::spec::{Arch, RelocModel}; use tempfile::TempDir; @@ -195,8 +195,8 @@ impl CodegenBackend for GccCodegenBackend { "gcc" } - fn init(&self, sess: &Session) { - fn file_path(sysroot_path: &Path, sess: &Session) -> PathBuf { + fn init(&self, sess: &EarlySession) -> CodegenBackendInit { + fn file_path(sysroot_path: &Path, sess: &EarlySession) -> PathBuf { let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); sysroot_path @@ -274,10 +274,12 @@ impl CodegenBackend for GccCodegenBackend { .supports_128bit_integers .store(check_context.get_last_error() == Ok(None), Ordering::SeqCst); } - } - fn thin_lto_supported(&self) -> bool { - false + CodegenBackendInit { + replaced_intrinsics: vec![], + fallback_intrinsics: vec![sym::type_id_eq], + thin_lto_supported: false, + } } fn provide(&self, providers: &mut Providers) { @@ -307,13 +309,9 @@ impl CodegenBackend for GccCodegenBackend { .join(sess, incr_comp_session, crate_info) } - fn target_config(&self, sess: &Session) -> TargetConfig { + fn target_config(&self, sess: &EarlySession) -> TargetConfig { target_config(sess, &self.target_info) } - - fn fallback_intrinsics(&self) -> Vec { - vec![sym::type_id_eq] - } } fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { @@ -532,10 +530,10 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } /// Returns the features that should be set in `cfg(target_feature)`. -fn target_config(sess: &Session, target_info: &LockedTargetInfo) -> TargetConfig { +fn target_config(sess: &EarlySession, target_info: &LockedTargetInfo) -> TargetConfig { let internal_target_features = internal_target_features( sess, - |feature| to_gcc_features(sess, feature), + |feature| to_gcc_features(&sess.target, feature), |feature| { // FIXME: we disable Neon for now since we don't support the LLVM intrinsics for it. if feature == "neon" { From 68b945d587a455a781c701de146e6f5085833810 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 28 Aug 2026 16:12:32 +1000 Subject: [PATCH 0256/1309] Change `CodegenBackend::init` to take `&mut self` It currently takes `&self`, which is a bit strange for an `init` method. As a result, the Cranelift and GCC backends have to use types with interior mutability. This commit changes it to `&mut self`. Benefits: - The Cranelift backend can use `Option` instead of `OnceCell` to indicate uninit vs. init. - The GCC backend can avoid `Mutex`, and use `bool` instead of `AtomicBool`, which makes things much simpler. The commit also restructures `GccCodegenBackend` to mirror `CraneliftCodegenBackend`: just contain an `Option`, which makes the uninit vs. init distinction foolproof. (E.g. no need to set `lto_supported` to false and then later overwrite it with the real value.) As part of this the `LockedTargetInfo` type is renamed `SharedTargetInfo` because that better matches its new internals. (All this compiles both with and without the "master" feature set.) --- src/base.rs | 6 +-- src/lib.rs | 109 +++++++++++++++------------------------------------- 2 files changed, 35 insertions(+), 80 deletions(-) diff --git a/src/base.rs b/src/base.rs index 7a25fc46fd3fc..101af0bb0bff1 100644 --- a/src/base.rs +++ b/src/base.rs @@ -21,7 +21,7 @@ use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::{GccContext, LockedTargetInfo, LtoMode, SyncContext, gcc_util, new_context}; +use crate::{GccContext, LtoMode, SharedTargetInfo, SyncContext, gcc_util, new_context}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -73,7 +73,7 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { pub fn compile_codegen_unit( tcx: TyCtxt<'_>, cgu_name: Symbol, - target_info: LockedTargetInfo, + target_info: SharedTargetInfo, lto_supported: bool, ) -> (ModuleCodegen, u64) { let prof_timer = tcx.prof.generic_activity("codegen_module"); @@ -96,7 +96,7 @@ pub fn compile_codegen_unit( fn module_codegen( tcx: TyCtxt<'_>, cgu_name: Symbol, - target_info: LockedTargetInfo, + target_info: SharedTargetInfo, lto_supported: bool, ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); diff --git a/src/lib.rs b/src/lib.rs index 6e40827c48405..52d732924c866 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -69,12 +69,10 @@ mod type_of; use std::any::Any; use std::ffi::CString; -use std::fmt::Debug; use std::fs; use std::ops::Deref; use std::path::{Path, PathBuf}; -use std::sync::atomic::{AtomicBool, Ordering}; -use std::sync::{Arc, Mutex}; +use std::sync::Arc; use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] @@ -116,7 +114,7 @@ impl String> Drop for PrintOnPanic { #[cfg(not(feature = "master"))] #[derive(Debug)] pub struct TargetInfo { - supports_128bit_integers: AtomicBool, + supports_128bit_integers: bool, } #[cfg(not(feature = "master"))] @@ -128,7 +126,7 @@ impl TargetInfo { fn supports_target_dependent_type(&self, typ: CType) -> bool { match typ { CType::UInt128t | CType::Int128t => { - if self.supports_128bit_integers.load(Ordering::SeqCst) { + if self.supports_128bit_integers { return true; } } @@ -138,43 +136,26 @@ impl TargetInfo { } } +type SharedTargetInfo = Arc>; + #[derive(Clone)] -pub struct LockedTargetInfo { - info: Arc>>>, +pub struct BackendConfig { + target_info: SharedTargetInfo, + lto_supported: bool, } -impl Debug for LockedTargetInfo { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - self.info.lock().expect("lock").fmt(formatter) - } +#[derive(Clone)] +pub struct GccCodegenBackend { + // `None` before `init`, `Some` after. + pub config: Option, } -impl LockedTargetInfo { - fn cpu_supports(&self, feature: &str) -> bool { - self.info - .lock() - .expect("lock") - .as_ref() - .expect("target info not initialized") - .cpu_supports(feature) - } - - fn supports_target_dependent_type(&self, typ: CType) -> bool { - self.info - .lock() - .expect("lock") - .as_ref() - .expect("target info not initialized") - .supports_target_dependent_type(typ) +impl GccCodegenBackend { + fn config(&self) -> &BackendConfig { + self.config.as_ref().expect("target info not initialized") } } -#[derive(Clone)] -pub struct GccCodegenBackend { - target_info: LockedTargetInfo, - lto_supported: Arc, -} - fn load_libgccjit_if_needed(libgccjit_target_lib_file: &Path) { if gccjit::is_loaded() { // Do not load a libgccjit second time. @@ -195,7 +176,7 @@ impl CodegenBackend for GccCodegenBackend { "gcc" } - fn init(&self, sess: &EarlySession) -> CodegenBackendInit { + fn init(&mut self, sess: &EarlySession) -> CodegenBackendInit { fn file_path(sysroot_path: &Path, sess: &EarlySession) -> PathBuf { let rustlib_path = rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); @@ -240,14 +221,10 @@ impl CodegenBackend for GccCodegenBackend { context.add_command_line_option(format!("-march={}", target_cpu)); } - *self.target_info.info.lock().expect("lock") = - IntoDynSyncSend(Some(context.get_target_info())); - } - - #[cfg(feature = "master")] - { - let lto_supported = gccjit::is_lto_supported(); - self.lto_supported.store(lto_supported, Ordering::SeqCst); + self.config = Some(BackendConfig { + target_info: Arc::new(IntoDynSyncSend(context.get_target_info())), + lto_supported: gccjit::is_lto_supported(), + }); gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); } @@ -264,15 +241,12 @@ impl CodegenBackend for GccCodegenBackend { gccjit::OutputKind::Assembler, temp_file.to_str().expect("path to str"), ); - self.target_info - .info - .lock() - .expect("lock") - .0 - .as_ref() - .expect("target info not initialized") - .supports_128bit_integers - .store(check_context.get_last_error() == Ok(None), Ordering::SeqCst); + let target_info = + TargetInfo { supports_128bit_integers: check_context.get_last_error() == Ok(None) }; + self.config = Some(BackendConfig { + target_info: Arc::new(IntoDynSyncSend(target_info)), + lto_supported: false, + }); } CodegenBackendInit { @@ -310,7 +284,7 @@ impl CodegenBackend for GccCodegenBackend { } fn target_config(&self, sess: &EarlySession) -> TargetConfig { - target_config(sess, &self.target_info) + target_config(sess, &self.config().target_info) } } @@ -344,12 +318,11 @@ impl ExtraBackendMethods for GccCodegenBackend { module_name: &str, methods: &[AllocatorMethod], ) -> Self::Module { - let lto_supported = self.lto_supported.load(Ordering::SeqCst); let mut mods = GccContext { context: Arc::new(SyncContext::new(new_context(tcx))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, - lto_supported, + lto_supported: self.config().lto_supported, temp_dir: None, }; @@ -365,12 +338,8 @@ impl ExtraBackendMethods for GccCodegenBackend { cgu_name: Symbol, _bitcode_needed: bool, ) -> (ModuleCodegen, u64) { - base::compile_codegen_unit( - tcx, - cgu_name, - self.target_info.clone(), - self.lto_supported.load(Ordering::SeqCst), - ) + let config = self.config(); + base::compile_codegen_unit(tcx, cgu_name, config.target_info.clone(), config.lto_supported) } } @@ -499,21 +468,7 @@ impl WriteBackendMethods for GccCodegenBackend { /// This is the entrypoint for a hot plugged rustc_codegen_gccjit #[unsafe(no_mangle)] pub fn __rustc_codegen_backend() -> Box { - #[cfg(feature = "master")] - let info = { - // Check whether the target supports 128-bit integers, and sized floating point types (like - // Float16). - Arc::new(Mutex::new(IntoDynSyncSend(None))) - }; - #[cfg(not(feature = "master"))] - let info = Arc::new(Mutex::new(IntoDynSyncSend(Some(TargetInfo { - supports_128bit_integers: AtomicBool::new(false), - })))); - - Box::new(GccCodegenBackend { - lto_supported: Arc::new(AtomicBool::new(false)), - target_info: LockedTargetInfo { info }, - }) + Box::new(GccCodegenBackend { config: None }) } fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { @@ -530,7 +485,7 @@ fn to_gcc_opt_level(optlevel: Option) -> OptimizationLevel { } /// Returns the features that should be set in `cfg(target_feature)`. -fn target_config(sess: &EarlySession, target_info: &LockedTargetInfo) -> TargetConfig { +fn target_config(sess: &EarlySession, target_info: &SharedTargetInfo) -> TargetConfig { let internal_target_features = internal_target_features( sess, |feature| to_gcc_features(&sess.target, feature), From c2cd957dd39b536e63742896c6c696a19ec5938d Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 28 Aug 2026 16:37:48 +1000 Subject: [PATCH 0257/1309] Remove `global_backend_features` query It's now possible to get the backend features (a `Vec`) when the codegen backend is started, pass it back through `CodegenBackendInit`, and just store it in the `Session`. This removes the need for the query. Also: - `WriteBackendMethods::target_machine_factory` no longer needs the `target_features` parameter, because it's now available through the `sess` parameter. - `CodegenContext` no longer needs the `backend_features` field because we can use `sess.global_backend_features` instead. - `CodegenBackend::provide` is now a no-op for all the in-tree backends. I haven't removed it because out-of-tree backends still rely on it. --- src/attributes.rs | 2 +- src/lib.rs | 10 +++------- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 321e150a1568d..a5cc44a46e154 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -133,7 +133,7 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // FIXME(antoyo): cg_llvm adds global features to each function so that LTO keep them. // Check if GCC requires the same. - let mut global_features = cx.tcx.global_backend_features(()).iter().map(|s| s.as_str()); + let mut global_features = cx.tcx.sess.global_backend_features.iter().map(|s| s.as_str()); function_features.extend(&mut global_features); let target_features = function_features .iter() diff --git a/src/lib.rs b/src/lib.rs index 52d732924c866..d7a3ef3b4a6c5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -91,7 +91,6 @@ use rustc_data_structures::sync::IntoDynSyncSend; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; use rustc_middle::ty::TyCtxt; -use rustc_middle::util::Providers; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; use rustc_span::{Symbol, sym}; @@ -188,6 +187,8 @@ impl CodegenBackend for GccCodegenBackend { .join("libgccjit.so") } + let global_backend_features = gcc_util::global_gcc_features(sess); + // We use all_paths() instead of only path() in case the path specified by --sysroot is // invalid. // This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null. @@ -250,17 +251,13 @@ impl CodegenBackend for GccCodegenBackend { } CodegenBackendInit { + global_backend_features, replaced_intrinsics: vec![], fallback_intrinsics: vec![sym::type_id_eq], thin_lto_supported: false, } } - fn provide(&self, providers: &mut Providers) { - providers.queries.global_backend_features = - |tcx, ()| gcc_util::global_gcc_features(tcx.sess) - } - fn target_cpu(&self, sess: &Session) -> String { target_cpu(sess).to_owned() } @@ -397,7 +394,6 @@ impl WriteBackendMethods for GccCodegenBackend { &self, _sess: &Session, _opt_level: OptLevel, - _features: &[String], ) -> TargetMachineFactoryFn { // FIXME(antoyo): set opt level. Arc::new(|_, _| ()) From 8a820836efa55aa985b4cadee58539f6c0db4096 Mon Sep 17 00:00:00 2001 From: Guy Bedford Date: Tue, 15 Sep 2026 23:16:30 -0700 Subject: [PATCH 0258/1309] Drop -sWASM_BIGINT for wasm32-unknown-emscripten, require Emscripten 4.0 --- .../src/spec/targets/wasm32_unknown_emscripten.rs | 3 +-- .../src/platform-support/wasm32-unknown-emscripten.md | 7 ++++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs index bda2681605814..a084e71a0c71f 100644 --- a/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs +++ b/compiler/rustc_target/src/spec/targets/wasm32_unknown_emscripten.rs @@ -6,8 +6,7 @@ use crate::spec::{ pub(crate) fn target() -> Target { // Reset flags for non-Em flavors back to empty to satisfy sanity checking tests. let pre_link_args = LinkArgs::new(); - let post_link_args = - TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0", "-sWASM_BIGINT"]); + let post_link_args = TargetOptions::link_args(LinkerFlavor::EmCc, &["-sABORTING_MALLOC=0"]); let opts = TargetOptions { os: Os::Emscripten, diff --git a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md index fcf6e42be224b..af95f9bccb94c 100644 --- a/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md +++ b/src/doc/rustc/src/platform-support/wasm32-unknown-emscripten.md @@ -43,12 +43,13 @@ APIs, the `wasm32-unknown-emscripten` target may be preferable. ## Requirements This target is cross-compiled. The Emscripten compiler toolchain `emcc` must be -installed to link WASM binaries for this target. You can install `emcc` using: +installed to link WASM binaries for this target. Emscripten 4.0.0 or newer is +required. You can install `emcc` using: ```sh git clone https://github.com/emscripten-core/emsdk.git --depth 1 -./emsdk/emsdk install 3.1.68 -./emsdk/emsdk activate 3.1.68 +./emsdk/emsdk install latest +./emsdk/emsdk activate latest source ./emsdk/emsdk_env.sh ``` From f68cc95efd2c639071fecc320771a3eabc579fa9 Mon Sep 17 00:00:00 2001 From: Johann Hemmann Date: Wed, 16 Sep 2026 13:25:03 +0200 Subject: [PATCH 0259/1309] Fix formatting, and make wording consistent --- src/doc/rustc-dev-guide/src/backend/monomorph.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/backend/monomorph.md b/src/doc/rustc-dev-guide/src/backend/monomorph.md index 670614fe51379..f25211b23e602 100644 --- a/src/doc/rustc-dev-guide/src/backend/monomorph.md +++ b/src/doc/rustc-dev-guide/src/backend/monomorph.md @@ -33,7 +33,7 @@ Take this example: ```rust fn banana() { - peach::(); + peach::(); } fn main() { @@ -67,9 +67,9 @@ or more modules in Crate B. | Crate A function | Behavior | | - | - | -| Non-generic function | Crate A function doesn't appear in any codegen units of Crate B | -| Non-generic `#[inline]` function | Crate A function appears within a single CGU of Crate B, and exists even after post-inlining stage| -| Generic function | Regardless of inlining, all monomorphized (specialized) functions
from Crate A appear within a single codegen unit for Crate B.
The codegen unit exists even after the post inlining stage.| +| Non-generic function | Crate A function doesn't appear in any codegen units of Crate B. | +| Non-generic `#[inline]` function | Crate A function appears within a single CGU of Crate B.
The codegen unit exists even after the post inlining stage. | +| Generic function | Regardless of inlining, all monomorphized (specialized) functions
from Crate A appear within a single codegen unit for Crate B.
The codegen unit exists even after the post inlining stage. | | Generic `#[inline]` function | - same - | For more details about the partitioner read the module level [documentation]. From d7cf3cbce8748136e232ad44f9ff3f935eca9223 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Sat, 15 Aug 2026 21:35:05 -0700 Subject: [PATCH 0260/1309] only rerun const eval if the const actually references opaques --- .../rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3a4875c1d0951..f52408b3401f7 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1411,7 +1411,12 @@ where alias_const: ty::AliasConst, ) -> Result, NoSolutionOrRerunNonErased> { if self.typing_mode().is_erased_not_coherence() { - match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} + let resolved = self.deeply_resolve_ignoring_regions(alias_const); + // FIXME: get rid of this once GCE is removed + let is_gce = self.cx().features().generic_const_exprs(); + if resolved.has_opaque_types() || is_gce { + match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} + } } self.delegate.evaluate_const(param_env, alias_const, |ty| { From ba736a028b6386b1c6069125bae336b137e81187 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Sep 2026 01:05:31 +0200 Subject: [PATCH 0261/1309] Provide the "preferred name" when generating `href` and `title` for intra doc link --- src/librustdoc/clean/types.rs | 6 +++--- src/librustdoc/formats/cache.rs | 22 ++++++++++++++++++++-- src/librustdoc/html/format.rs | 28 +++++++++++++++++++++------- src/librustdoc/html/highlight.rs | 27 +++++++++++++++++---------- 4 files changed, 61 insertions(+), 22 deletions(-) diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 7a99ce8d39e9c..8ad8cd9997a74 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -600,7 +600,7 @@ impl Item { } pub(crate) fn links(&self, cx: &Context<'_>) -> Vec { - use crate::html::format::{href, link_tooltip}; + use crate::html::format::{href_with_path_check, link_tooltip}; let Some(links) = cx.cache().intra_doc_links.get(&self.item_or_reexport_id()) else { return vec![]; @@ -609,7 +609,7 @@ impl Item { .iter() .filter_map(|ItemLink { link: s, link_text, page_id: id, fragment }| { debug!(?id); - if let Ok(HrefInfo { mut url, .. }) = href(*id, cx) { + if let Ok(HrefInfo { mut url, .. }) = href_with_path_check(*id, cx, link_text) { debug!(?url); match fragment { Some(UrlFragment::Item(def_id)) => { @@ -625,7 +625,7 @@ impl Item { Some(RenderedLink { original_text: s.clone(), new_text: link_text.clone(), - tooltip: link_tooltip(*id, fragment, cx).to_string(), + tooltip: link_tooltip(*id, fragment, cx, Some(link_text)).to_string(), href: url, }) } else { diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 3dee84c2f4dc4..c89c3dbd3fbf5 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -19,7 +19,8 @@ use crate::html::render::{IndexItem, IndexItemInfo}; use crate::visit_lib::RustdocEffectiveVisibilities; pub(crate) struct PathInfo { - /// Parts of the path. So in `foo::bar::bib`, it will be `["foo", "bar", "bib"]`. + /// Parts of the fully qualified path. So in `foo::bar::bib`, it will + /// be `["foo", "bar", "bib"]`. pub(crate) parts: Vec, pub(crate) ty: ItemType, /// When a reexport inline an item, we can end up with the same `DefId` with multiple local @@ -35,10 +36,27 @@ pub(crate) struct PathInfo { /// ``` /// /// To ensure that `a1` and `a2` links to `a1` and `a2` which have the same `DefId`, we need - /// to store both paths. + /// to store both `a1` and `a2` paths. + /// + /// The path stored in `parts` is not present in `alternatives`. pub(crate) alternatives: Vec>, } +impl PathInfo { + pub(crate) fn get_preferred_path(&self, preferred_name: Option<&str>) -> &[Symbol] { + if let Some(preferred_name) = preferred_name + && let Some(alternative_path) = self + .alternatives + .iter() + .find(|path| path.last().is_some_and(|last| last.as_str() == preferred_name)) + { + alternative_path + } else { + &self.parts + } + } +} + /// This cache is used to store information about the [`clean::Crate`] being /// rendered in order to provide more useful documentation. This contains /// information like all implementors of a trait, all traits a type implements, diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 07b0f02b7d5b8..da150789b2102 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -543,6 +543,7 @@ pub(crate) fn href_with_root_path( original_did: DefId, cx: &Context<'_>, root_path: Option<&str>, + preferred_name: Option<&str>, ) -> Result { let tcx = cx.tcx(); let def_kind = tcx.def_kind(original_did); @@ -553,7 +554,9 @@ pub(crate) fn href_with_root_path( } // If this a constructor, we get the parent (either a struct or a variant) and then // generate the link for this item. - DefKind::Ctor(..) => return href_with_root_path(tcx.parent(original_did), cx, root_path), + DefKind::Ctor(..) => { + return href_with_root_path(tcx.parent(original_did), cx, root_path, preferred_name); + } DefKind::ExternCrate => { // Link to the crate itself, not the `extern crate` item. if let Some(local_did) = original_did.as_local() { @@ -587,7 +590,7 @@ pub(crate) fn href_with_root_path( let (fqp, shortty, url_parts, is_absolute) = match cache.paths.get(&did) { Some(info) => ( - &info.parts, + info.get_preferred_path(preferred_name), info.ty, { let module_fqp = to_module_fqp(info.ty, info.parts.as_slice()); @@ -604,7 +607,7 @@ pub(crate) fn href_with_root_path( if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&def_id_to_get) { let module_fqp = to_module_fqp(shortty, fqp); let (parts, is_absolute) = url_parts(cache, did, module_fqp, relative_to)?; - (fqp, shortty, parts, is_absolute) + (fqp.as_slice(), shortty, parts, is_absolute) } else if matches!(def_kind, DefKind::Macro(_)) { return generate_macro_def_id_path(did, cx, root_path); } else if did.is_local() { @@ -617,12 +620,20 @@ pub(crate) fn href_with_root_path( Ok(HrefInfo { url: make_href(root_path, shortty, url_parts, fqp, is_absolute), kind: shortty, - rust_path: fqp.clone(), + rust_path: fqp.to_vec(), }) } pub(crate) fn href(did: DefId, cx: &Context<'_>) -> Result { - href_with_root_path(did, cx, None) + href_with_root_path(did, cx, None, None) +} + +pub(crate) fn href_with_path_check( + did: DefId, + cx: &Context<'_>, + text: &str, +) -> Result { + href_with_root_path(did, cx, None, Some(text)) } /// Both paths should only be modules. @@ -660,14 +671,17 @@ pub(crate) fn link_tooltip( did: DefId, fragment: &Option, cx: &Context<'_>, + preferred_name: Option<&str>, ) -> impl fmt::Display { fmt::from_fn(move |f| { let cache = cx.cache(); let Some((fqp, shortty)) = cache .paths .get(&did) - .map(|info| (&info.parts, info.ty)) - .or_else(|| cache.external_paths.get(&did).map(|(fqp, shortty)| (fqp, *shortty))) + .map(|info| (info.get_preferred_path(preferred_name), info.ty)) + .or_else(|| { + cache.external_paths.get(&did).map(|(fqp, shortty)| (fqp.as_slice(), *shortty)) + }) else { return Ok(()); }; diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 89d50680c3a3b..9c73e3b4ad687 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -1406,23 +1406,30 @@ fn generate_link_to_def( LinkFromSrc::Local(span) => { context.href_from_span_relative(*span, &href_context.current_href) } - LinkFromSrc::External(def_id) => { - format::href_with_root_path(*def_id, context, Some(href_context.root_path)) - .ok() - .map(|HrefInfo { url, .. }| url) - } + LinkFromSrc::External(def_id) => format::href_with_root_path( + *def_id, + context, + Some(href_context.root_path), + None, + ) + .ok() + .map(|HrefInfo { url, .. }| url), LinkFromSrc::Primitive(prim) => format::href_with_root_path( PrimitiveType::primitive_locations(context.tcx())[prim], context, Some(href_context.root_path), + None, + ) + .ok() + .map(|HrefInfo { url, .. }| url), + LinkFromSrc::Doc(def_id) => format::href_with_root_path( + *def_id, + context, + Some(href_context.root_path), + None, ) .ok() .map(|HrefInfo { url, .. }| url), - LinkFromSrc::Doc(def_id) => { - format::href_with_root_path(*def_id, context, Some(href_context.root_path)) - .ok() - .map(|HrefInfo { url, .. }| url) - } } }) { From cd6287f229efa4a9637621a0df5839d580794526 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 12 Sep 2026 01:17:06 +0200 Subject: [PATCH 0262/1309] Add regression test for inlined same item with different names --- .../inline-same-item-with-different-names.rs | 43 +++++++++++++++++++ 1 file changed, 43 insertions(+) create mode 100644 tests/rustdoc-html/intra-doc/inline-same-item-with-different-names.rs diff --git a/tests/rustdoc-html/intra-doc/inline-same-item-with-different-names.rs b/tests/rustdoc-html/intra-doc/inline-same-item-with-different-names.rs new file mode 100644 index 0000000000000..c7801da5c98c2 --- /dev/null +++ b/tests/rustdoc-html/intra-doc/inline-same-item-with-different-names.rs @@ -0,0 +1,43 @@ +// This test ensures that when a same item is inlined with different names, the intra +// doc links generate the correct href/title. +// Regression test for . + +#![crate_name = "foo"] + +// We check that the macros and structs are correctly generated. +//@ has 'foo/macro.d1.html' +//@ has 'foo/macro.d2.html' +//@ has 'foo/macro.d3.html' +//@ has 'foo/struct.a1.html' +//@ has 'foo/struct.a2.html' +//@ has 'foo/struct.a3.html' + +//@ has 'foo/index.html' + +//@ has - '//dd/a[@href="macro.d1.html"]' 'd1' +//@ has - '//dd/a[@title="macro foo::d1"]' 'd1' +//@ has - '//dd/a[@href="macro.d2.html"]' 'd2' +//@ has - '//dd/a[@title="macro foo::d2"]' 'd2' +//@ has - '//dd/a[@href="macro.d3.html"]' 'd3' +//@ has - '//dd/a[@title="macro foo::d3"]' 'd3' + +/// Link to [`d3`]. +pub use std::debug_assert as d1; +/// Link to [`d1`]. +pub use std::debug_assert as d2; +/// Link to [`d2`]. +pub use std::debug_assert as d3; + +//@ has - '//dd/a[@href="struct.a1.html"]' 'a1' +//@ has - '//dd/a[@title="struct foo::a1"]' 'a1' +//@ has - '//dd/a[@href="struct.a2.html"]' 'a2' +//@ has - '//dd/a[@title="struct foo::a2"]' 'a2' +//@ has - '//dd/a[@href="struct.a3.html"]' 'a3' +//@ has - '//dd/a[@title="struct foo::a3"]' 'a3' + +/// Link to [`a3`]. +pub use std::ffi::os_str::OsString as a1; +/// Link to [`a1`]. +pub use std::ffi::os_str::OsString as a2; +/// Link to [`a2`]. +pub use std::ffi::os_str::OsString as a3; From 005aa4525614598ccedbc01768ccfb59c8fb833e Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Wed, 16 Sep 2026 22:16:50 -0400 Subject: [PATCH 0263/1309] Mini optimization in `restrict_precision_for_drop_types` Avoid calling `type_is_copy_modulo_regions` if not necessary. --- compiler/rustc_hir_typeck/src/upvar.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 1497bfeb0f774..875517ee4c87e 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -2318,9 +2318,9 @@ fn restrict_precision_for_drop_types<'a, 'tcx>( mut place: Place<'tcx>, mut curr_mode: ty::UpvarCapture, ) -> (Place<'tcx>, ty::UpvarCapture) { - let is_copy_type = fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty()); - - if let (false, UpvarCapture::ByValue) = (is_copy_type, curr_mode) { + if curr_mode == UpvarCapture::ByValue + && !fcx.infcx.type_is_copy_modulo_regions(fcx.param_env, place.ty()) + { for i in 0..place.projections.len() { match place.ty_before_projection(i).kind() { ty::Adt(def, _) if def.destructor(fcx.tcx).is_some() => { From 8aae7a7af74dbd3d6ca90234f75733e7311ad842 Mon Sep 17 00:00:00 2001 From: Obei Sideg Date: Sat, 12 Sep 2026 11:48:45 +0300 Subject: [PATCH 0264/1309] Use attribute parser for `#[inline()]` attribute check --- .../rustc_attr_ir/src/encode_cross_crate.rs | 215 ++++++++++++++++++ .../src/attributes/allow_unstable.rs | 2 +- .../src/attributes/codegen_attrs.rs | 4 +- .../src/attributes/inline.rs | 27 ++- .../src/attributes/link_attrs.rs | 2 +- .../src/attributes/lint_helpers.rs | 2 +- .../src/attributes/macro_attrs.rs | 2 +- .../rustc_attr_parsing/src/attributes/mod.rs | 8 +- .../src/attributes/non_exhaustive.rs | 2 +- compiler/rustc_attr_parsing/src/context.rs | 2 +- .../rustc_attr_parsing/src/diagnostics.rs | 7 + compiler/rustc_attr_parsing/src/interface.rs | 2 +- .../src/middle/codegen_fn_attrs.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 34 +-- compiler/rustc_passes/src/diagnostics.rs | 7 - ...op.runtime-optimized.after.panic-abort.mir | 4 +- .../target-feature/invalid-attribute.stderr | 16 +- 17 files changed, 272 insertions(+), 68 deletions(-) diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 6f05f763f2ada..66fbbc1e3cbf7 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -212,4 +212,219 @@ impl AttributeKind { // tidy-alphabetical-end } } + + /// Whether this attribute is an extern indicator. + /// + /// Must stay in sync with [`CodegenFnAttrs::contains_extern_indicator`]. + /// + /// [`CodegenFnAttrs::contains_extern_indicator`]: ../rustc_middle/middle/codegen_fn_attrs/struct.CodegenFnAttrs.html#method.contains_extern_indicator + pub fn is_extern_indicator(&self) -> bool { + use AttributeKind::*; + + match self { + // tidy-alphabetical-start + AllowInternalUnsafe(..) => false, + AllowInternalUnstable(..) => false, + AlwaysGca => false, + AutomaticallyDerived => false, + CfgAttrTrace(..) => false, + CfgTrace(..) => false, + CfiEncoding { .. } => false, + Cold => false, + CollapseDebugInfo(..) => false, + CompilerBuiltins => false, + ConstContinue(..) => false, + Coroutine => false, + Coverage(..) => false, + CrateName { .. } => false, + CrateType(_) => false, + CustomMir(_, _) => false, + DebuggerVisualizer(..) => false, + DefaultLibAllocator => false, + Deprecated { .. } => false, + DoNotRecommend => false, + Doc(_) => false, + DocComment { .. } => false, + EiiDeclaration(_) => false, + EiiImpl(..) => true, + ExportName { .. } => true, + ExportStable => false, + Feature(..) => false, + FfiConst => false, + FfiPure(..) => false, + Fundamental { .. } => false, + Ignore { .. } => false, + Inline(..) => false, + InstructionSet(..) => false, + InstrumentFn(..) => false, + Lang(item) => item.link_name().is_some(), + Link(..) => false, + LinkName { .. } => false, + LinkOrdinal { .. } => false, + LinkSection { .. } => false, + Linkage(linkage, _) => match *linkage { + crate::Linkage::Internal => false, + crate::Linkage::AvailableExternally + | crate::Linkage::Common + | crate::Linkage::External + | crate::Linkage::ExternalWeak + | crate::Linkage::LinkOnceAny + | crate::Linkage::LinkOnceODR + | crate::Linkage::WeakAny + | crate::Linkage::WeakODR => true, + }, + LoopMatch(..) => false, + MacroEscape => false, + MacroExport { .. } => false, + MacroUse { .. } => false, + Marker => false, + MayDangle(..) => false, + MoveSizeLimit { .. } => false, + MustNotSupend { .. } => false, + MustUse { .. } => false, + Naked(..) => false, + NeedsAllocator => false, + NeedsPanicRuntime => false, + NoBuiltins => false, + NoCore => false, + NoImplicitPrelude => false, + NoLink => false, + NoMain => false, + NoMangle(..) => true, + NoStd => false, + NonExhaustive(..) => false, + OnConst { .. } => false, + OnMove { .. } => false, + OnTypeError { .. } => false, + OnUnimplemented { .. } => false, + OnUnknown { .. } => false, + OnUnmatchedArgs { .. } => false, + Opaque => false, + Optimize(..) => false, + PanicRuntime => false, + PatchableFunctionEntry { .. } => false, + Path(..) => false, + PatternComplexityLimit { .. } => false, + PinV2(..) => false, + PreludeImport => false, + ProcMacro => false, + ProcMacroAttribute => false, + ProcMacroDerive { .. } => false, + ProfilerRuntime => false, + RecursionLimit { .. } => false, + ReexportTestHarnessMain(..) => false, + RegisterTool { .. } => false, + Repr { .. } => false, + RustcAbi { .. } => false, + RustcAlign { .. } => false, + RustcAllocator => false, + RustcAllocatorZeroed => false, + RustcAllocatorZeroedVariant { .. } => false, + RustcAllowConstFnUnstable(..) => false, + RustcAllowIncoherentImpl(..) => false, + RustcAllowLifetimeDependentSpecialization => false, + RustcAsPtr => false, + RustcAutodiff(..) => false, + RustcBodyStability { .. } => false, + RustcBuiltinMacro { .. } => false, + RustcCanonicalSymbol => false, + RustcCaptureAnalysis => false, + RustcCguTestAttr { .. } => false, + RustcClean { .. } => false, + RustcCoherenceIsCore => false, + RustcCoinductive => false, + RustcComptime(..) => false, + RustcConfusables { .. } => false, + RustcConstStability { .. } => false, + RustcConstStableIndirect => false, + RustcConversionSuggestion => false, + RustcDeallocator => false, + RustcDelayedBugFromInsideQuery => false, + RustcDenyExplicitImpl => false, + RustcDeprecatedSafe2024 { .. } => false, + RustcDiagnosticItem(..) => false, + RustcDoNotConstCheck => false, + RustcDocPrimitive(..) => false, + RustcDummy => false, + RustcDumpClauses => false, + RustcDumpDefParents => false, + RustcDumpDefPath(..) => false, + RustcDumpGenerics => false, + RustcDumpHiddenTypeOfOpaques => false, + RustcDumpInferredOutlives => false, + RustcDumpItemBounds => false, + RustcDumpLayout(..) => false, + RustcDumpObjectLifetimeDefaults => false, + RustcDumpSymbolName(..) => false, + RustcDumpUserArgs => false, + RustcDumpVariances => false, + RustcDumpVariancesOfOpaques => false, + RustcDumpVtable(..) => false, + RustcDynIncompatibleTrait(..) => false, + RustcEffectiveVisibility => false, + RustcEiiForeignItem => true, + RustcEvaluateWhereClauses => false, + RustcHasIncoherentInherentImpls => false, + RustcIfThisChanged(..) => false, + RustcInheritOverflowChecks => false, + RustcInsignificantDtor => false, + RustcIntrinsic => false, + RustcIntrinsicConstStableIndirect => false, + RustcLegacyConstGenerics { .. } => false, + RustcLintOptDenyFieldAccess { .. } => false, + RustcLintOptTy => false, + RustcLintQueryInstability => false, + RustcLintUntrackedQueryInformation => false, + RustcMacroTransparency(..) => false, + RustcMain => false, + RustcMir(..) => false, + RustcMustImplementOneOf { .. } => false, + RustcMustMatchExhaustively(..) => false, + RustcNeverReturnsNullPtr => false, + RustcNoImplicitAutorefs => false, + RustcNoImplicitBounds => false, + RustcNoMirInline => false, + RustcNoWritable => false, + RustcNonConstTraitMethod => false, + RustcNonnullOptimizationGuaranteed => false, + RustcNounwind => false, + RustcObjcClass { .. } => false, + RustcObjcSelector { .. } => false, + RustcOffloadKernel => true, + RustcPanicsWhenZero => false, + RustcParenSugar => false, + RustcPassByValue => false, + RustcPassIndirectlyInNonRusticAbis(..) => false, + RustcPreserveUbChecks => false, + RustcProcMacroDecls => false, + RustcPubTransparent(..) => false, + RustcReallocator => false, + RustcRegions => false, + RustcScalableVector { .. } => false, + RustcShouldNotBeCalledOnConstItems => false, + RustcSimdMonomorphizeLaneLimit(..) => false, + RustcSkipDuringMethodDispatch { .. } => false, + RustcSpecializationTrait => false, + RustcStdInternalSymbol => true, + RustcStrictCoherence(..) => false, + RustcTestMarker(..) => false, + RustcThenThisWouldNeed(..) => false, + RustcTrivialFieldReads => false, + Sanitize { .. } => false, + ShouldPanic { .. } => false, + Splat(..) => false, + Stability { .. } => false, + TargetFeature { .. } => false, + TestRunner(..) => false, + ThreadLocal => false, + TrackCaller(..) => false, + TypeLengthLimit { .. } => false, + Unroll(..) => false, + UnstableFeatureBound(..) => false, + UnstableRemoved(..) => false, + Used { .. } => false, + WindowsSubsystem(..) => false, + // tidy-alphabetical-end + } + } } diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 743d3c9b5e76e..42e5f0ca2add4 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -30,7 +30,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { .zip(iter::repeat(cx.attr_span)) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { check_macro_only(cx, attr_span); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index bff7d7ad81cb9..2553829f8c5ce 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -349,7 +349,7 @@ impl NoArgsAttributeParser for TrackCallerParser { const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { match cx.target { Target::Fn => { // `#[track_caller]` is not valid on weak lang items because they are called via @@ -571,7 +571,7 @@ impl CombineAttributeParser for TargetFeatureParser { parse_tf_attribute(cx, args) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[target_feature]` is incompatible with lang item functions, // except on WASM where calling target-feature functions is safe (see #84988). if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc { diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index f3e305ea266a1..b4a5c9da155c9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -1,9 +1,9 @@ -use rustc_attr_ir::{AttributeKind, InlineAttr, find_attr}; +use rustc_attr_ir::{Attribute, AttributeKind, InlineAttr, find_attr}; use rustc_feature::AttributeStability; -use rustc_lint_defs::builtin::ILL_FORMED_ATTRIBUTE_INPUT; +use rustc_lint_defs::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNUSED_ATTRIBUTES}; use super::prelude::*; -use crate::diagnostics::InlineForceInlineConflict; +use crate::diagnostics::{InlineForceInlineConflict, InlineIgnoredForExported}; pub(crate) struct InlineParser; @@ -59,6 +59,25 @@ impl SingleAttributeParser for InlineParser { } } } + + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { + let exported = cx.parsed_attrs.iter().any(|attr| { + let Attribute::Parsed(kind) = attr else { return false }; + kind.is_extern_indicator() + }); + if matches!( + cx.target, + Target::Fn + | Target::Closure + | Target::Method( + MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, + ) + ) && !find_attr!(cx.parsed_attrs, Inline(InlineAttr::Never, _)) + && exported + { + cx.emit_lint(UNUSED_ATTRIBUTES, InlineIgnoredForExported, attr_span); + } + } } pub(crate) struct RustcForceInlineParser; @@ -94,7 +113,7 @@ impl SingleAttributeParser for RustcForceInlineParser { )) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { let Some(inline_span) = find_attr!(cx.parsed_attrs, Inline(attr, span) if !matches!(attr, InlineAttr::Force { .. }) => span) else { return; diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index a00e5af00c2eb..123cea41587f3 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -584,7 +584,7 @@ impl NoArgsAttributeParser for FfiPureParser { const STABILITY: AttributeStability = unstable!(ffi_pure); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[ffi_const]` functions cannot be `#[ffi_pure]`. if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) { cx.emit_err(BothFfiConstAndPure { attr_span }); diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 4ead90af8d630..10e42ced30705 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -29,7 +29,7 @@ impl NoArgsAttributeParser for RustcPubTransparentParser { const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[rustc_pub_transparent]` may only be applied to `#[repr(transparent)]` types. let is_transparent = find_attr!( cx.parsed_attrs, diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index c9625521aec44..85aaeffec00d5 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -140,7 +140,7 @@ impl NoArgsAttributeParser for AllowInternalUnsafeParser { const STABILITY: AttributeStability = unstable!(allow_internal_unsafe); const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { check_macro_only(cx, attr_span); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 242b4a73b06a6..8e47414f6c72a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -169,7 +169,7 @@ pub(crate) trait SingleAttributeParser: 'static { /// combinations. `attr_span` is the span of this attribute. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } /// Use in combination with [`SingleAttributeParser`]. @@ -287,7 +287,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { /// `attr_span` is the span of this attribute. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } pub(crate) struct WithoutArgs(PhantomData); @@ -311,7 +311,7 @@ impl SingleAttributeParser for WithoutArgs { Some(T::CREATE(cx.attr_span)) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { T::finalize_check(cx, attr_span) } } @@ -355,7 +355,7 @@ pub(crate) trait CombineAttributeParser: 'static { /// `attr_span` is the span of the first attribute that was encountered. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } /// Use in combination with [`CombineAttributeParser`]. diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index 30fdadf95e4ce..2acba84956e67 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -21,7 +21,7 @@ impl NoArgsAttributeParser for NonExhaustiveParser { const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { if cx.target != Target::Struct { return; } diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f936f5aab8265..12170d9160213 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -102,7 +102,7 @@ pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> FinalizeOutput; /// finalized, so it can inspect the fully parsed attributes via /// [`FinalizeCheckContext::parsed_attrs`]. The [`Span`] is the span of the attribute the /// check is associated with, used for diagnostics. -pub(crate) type FinalizeCheckFn = fn(&FinalizeCheckContext<'_, '_>, Span); +pub(crate) type FinalizeCheckFn = fn(&mut FinalizeCheckContext<'_, '_>, Span); /// The result of finalizing a single attribute parser. pub(crate) struct FinalizeOutput { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index e5f49690f71dc..cc64586339667 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -896,6 +896,13 @@ pub(crate) struct InlineForceInlineConflict { pub inline_span: Span, } +#[derive(Diagnostic)] +#[diag("`#[inline]` is ignored on externally exported functions")] +#[help( + "externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`" +)] +pub(crate) struct InlineIgnoredForExported; + #[derive(Diagnostic)] #[diag("`#[ffi_const]` function cannot be `#[ffi_pure]`", code = E0757)] pub(crate) struct BothFfiConstAndPure { diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 1cecce8fd43ef..48d57d7210ca3 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -512,7 +512,7 @@ impl<'sess> AttributeParser<'sess> { // inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`. for (check, attr_span) in deferred_checks { check( - &FinalizeCheckContext { + &mut FinalizeCheckContext { shared: SharedContext { cx: self, target_span, diff --git a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs index f15dc1001fd95..fc5345b0b0b92 100644 --- a/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs +++ b/compiler/rustc_middle/src/middle/codegen_fn_attrs.rs @@ -270,7 +270,9 @@ impl CodegenFnAttrs { /// * `#[export_name(...)]` is present /// * `#[linkage]` is present /// - /// Keep this in sync with the logic for the unused_attributes for `#[inline]` lint. + /// Keep this in sync with [`AttributeKind::is_extern_indicator`]. + /// + /// [`AttributeKind::is_extern_indicator`]: rustc_attr_ir::AttributeKind::is_extern_indicator pub fn contains_extern_indicator(&self) -> bool { if self.flags.contains(CodegenFnAttrFlags::FOREIGN_ITEM) { return false; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 79987b86385ef..5d5d1c2b54407 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -199,10 +199,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::ProcMacroDerive { .. } => { self.check_proc_macro(hir_id, target, ProcMacroKind::Derive) } - AttributeKind::Inline(InlineAttr::Force { .. }, ..) => {} // handled separately below - AttributeKind::Inline(kind, attr_span) => { - self.check_inline(hir_id, *attr_span, kind, target) - } AttributeKind::RustcAllowConstFnUnstable(_, first_span) => { self.check_rustc_allow_const_fn_unstable(hir_id, *first_span, span, target) } @@ -268,6 +264,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::FfiPure(..) => (), AttributeKind::Fundamental => (), AttributeKind::Ignore { .. } => (), + AttributeKind::Inline(..) => (), AttributeKind::InstructionSet(..) => (), AttributeKind::InstrumentFn(..) => (), AttributeKind::Lang(..) => (), @@ -740,35 +737,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks if an `#[inline]` is applied to a function or a closure. - fn check_inline(&self, hir_id: HirId, attr_span: Span, kind: &InlineAttr, target: Target) { - match target { - Target::Fn - | Target::Closure - | Target::Method( - MethodKind::Trait { body: true } | MethodKind::TraitImpl | MethodKind::Inherent, - ) => { - // `#[inline]` is ignored if the symbol must be codegened upstream because it's exported. - if let Some(did) = hir_id.as_owner() - && self.tcx.def_kind(did).has_codegen_attrs() - && kind != &InlineAttr::Never - { - let attrs = self.tcx.codegen_fn_attrs(did); - // Not checking naked as `#[inline]` is forbidden for naked functions anyways. - if attrs.contains_extern_indicator() { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - diagnostics::InlineIgnoredForExported, - ); - } - } - } - _ => {} - } - } - /// Checks if `#[naked]` is applied to a function definition. fn check_naked(&self, hir_id: HirId, target: Target) { match target { diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 55f8ac9a585de..2524171d98ab9 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -562,13 +562,6 @@ pub(crate) struct UselessAssignment<'a> { pub ty: Ty<'a>, } -#[derive(Diagnostic)] -#[diag("`#[inline]` is ignored on externally exported functions")] -#[help( - "externally exported functions are functions with `#[no_mangle]`, `#[export_name]`, or `#[linkage]`" -)] -pub(crate) struct InlineIgnoredForExported; - #[derive(Diagnostic)] #[diag("transparent {$target} cannot have other repr hints", code = E0692)] pub(crate) struct TransparentIncompatible { diff --git a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir index 549af7af4d888..b42087b5c822d 100644 --- a/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/slice_iter.enumerated_loop.runtime-optimized.after.panic-abort.mir @@ -21,7 +21,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { debug x => _34; } scope 18 (inlined > as Iterator>::next) { - let mut _22: std::option::Option; + let mut _22: std::option::Option; let mut _27: std::option::Option<&T>; let mut _30: (usize, bool); let mut _31: (usize, &T); @@ -32,7 +32,7 @@ fn enumerated_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () { } scope 20 { scope 21 { - scope 27 (inlined as FromResidual>>::from_residual) { + scope 27 (inlined as FromResidual>>::from_residual) { let mut _21: isize; let mut _23: bool; } diff --git a/tests/ui/target-feature/invalid-attribute.stderr b/tests/ui/target-feature/invalid-attribute.stderr index a1a69188bdbbd..1dc87bfe5bfb2 100644 --- a/tests/ui/target-feature/invalid-attribute.stderr +++ b/tests/ui/target-feature/invalid-attribute.stderr @@ -160,14 +160,6 @@ LL | #[target_feature(enable = "sse2")] | = help: the `target_feature` attribute can be applied to functions and methods -error: cannot use `#[inline(always)]` with `#[target_feature]` - --> $DIR/invalid-attribute.rs:69:1 - | -LL | #[inline(always)] - | ^^^^^^^^^^^^^^^^^ - | - = note: See this issue for full discussion: https://github.com/rust-lang/rust/issues/145574 - error: the feature named `foo` is not valid for this target --> $DIR/invalid-attribute.rs:27:18 | @@ -176,6 +168,14 @@ LL | #[target_feature(enable = "foo")] | = help: valid names are: `fma`, `xop`, `adx`, `aes`, and `avx` and X more +error: cannot use `#[inline(always)]` with `#[target_feature]` + --> $DIR/invalid-attribute.rs:69:1 + | +LL | #[inline(always)] + | ^^^^^^^^^^^^^^^^^ + | + = note: See this issue for full discussion: https://github.com/rust-lang/rust/issues/145574 + error[E0046]: not all trait items implemented, missing: `foo` --> $DIR/invalid-attribute.rs:81:1 | From 0b34b6ecbc09b3ad19391bdb8563ba6487a40061 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 17 Sep 2026 04:34:53 +0000 Subject: [PATCH 0265/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 923c95cdf5ba65cea505aa2ea829f578e1506ed8. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d8a1a0bba9f52..eab2efbccce35 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c26ce708de5d14682647895d2f3caf38f70b5aa6 +923c95cdf5ba65cea505aa2ea829f578e1506ed8 From 66f69fc2ffe2691a3b97e99d86908f5ee5d86b67 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Thu, 17 Sep 2026 01:04:17 -0400 Subject: [PATCH 0266/1309] No longer auto-inline `f16` and `f128` on well-supported platforms In 5d818914af27 ("Always inline functions signatures containing `f16` or `f128`"), these types were changed to automatically inline so codegen wouldn't crash on poorly-supported platforms. We have since gained a cfg to reflect the type's codegen reliability. Update so we only check and auto-inline based on type if this config is set, which makes `f16` and `f128` act more like any other type on most platforms. We still can't remove this entirely since a lot of API in `std` wouldn't get inlined and would crash the few remaining poorly-supported backend+target combinations. --- .../src/cross_crate_inline.rs | 22 +++-- tests/codegen-llvm/float/f16-f128-inline.rs | 91 +++++++++++++++---- 2 files changed, 87 insertions(+), 26 deletions(-) diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 8a4e7740650fc..ca47b27d142a2 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -7,7 +7,7 @@ use rustc_middle::mir::*; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{InliningThreshold, OptLevel}; -use rustc_span::bug; +use rustc_span::{bug, sym}; use crate::{inline, pass_manager as pm}; @@ -64,13 +64,19 @@ fn cross_crate_inlinable(tcx: TyCtxt<'_>, def_id: LocalDefId) -> bool { return true; } - let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); - for ty in sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder())) - { - // FIXME(f16_f128): in order to avoid crashes building `core`, always inline to skip - // codegen if the function is not used. - if ty == &tcx.types.f16 || ty == &tcx.types.f128 { - return true; + let reliable_f16 = tcx.sess.config.contains(&(sym::target_has_reliable_f16, None)); + let reliable_f128 = tcx.sess.config.contains(&(sym::target_has_reliable_f128, None)); + if !reliable_f16 || !reliable_f128 { + let sig = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip(); + for ty in + sig.inputs().skip_binder().iter().chain(std::iter::once(&sig.output().skip_binder())) + { + // FIXME(f16,f128): in order to avoid crashes building `core`, inline on targets that + // have issues to skip codegen if the function is not used. + if (!reliable_f16 && ty == &tcx.types.f16) || (!reliable_f128 && ty == &tcx.types.f128) + { + return true; + } } } diff --git a/tests/codegen-llvm/float/f16-f128-inline.rs b/tests/codegen-llvm/float/f16-f128-inline.rs index aa2c38c209e86..592204cf000a1 100644 --- a/tests/codegen-llvm/float/f16-f128-inline.rs +++ b/tests/codegen-llvm/float/f16-f128-inline.rs @@ -1,29 +1,84 @@ -//@ revisions: default nopt -//@[nopt] compile-flags: -Copt-level=0 -Zcross-crate-inline-threshold=never -Zmir-opt-level=0 -Cno-prepopulate-passes +//@ revisions: DEFAULT NOPT +//@[NOPT] compile-flags: -Copt-level=0 -Zcross-crate-inline-threshold=never -Zmir-opt-level=0 -Cno-prepopulate-passes -// Ensure that functions using `f16` and `f128` are always inlined to avoid crashes -// when the backend does not support these types. +// Ensure that functions using `f16` and `f128` are always inlined when the backend does not +// support these types, to avoid crashes. #![crate_type = "lib"] #![feature(f128)] #![feature(f16)] +#![feature(cfg_target_has_reliable_f16_f128)] -pub fn f16_arg(_a: f16) { - // CHECK-NOT: f16_arg - todo!() -} +// This test does some tricky things. On `target_has_reliable_*` platforms: +// +// * `*_on_reliable` functions should always show up in codegen since they are not auto-inlined +// (the default), +// * `*_on_not_reliable` functions aren't defined at all, so `CHECK-NOT` passes. +// +// On non-`target_has_reliable_*` platforms: +// +// * `*_on_reliable` functions are dummies so they always show up in codegen. +// * `*_on_not_reliable` functions should be auto-inlined and thus not show up in codegen. +// +// `*_on_reliable` is only checked with NOPT since otherwise they may hit auto-inlining thresholds +// unrelated to the type signature. -pub fn f16_ret() -> f16 { - // CHECK-NOT: f16_ret - todo!() -} +// NOPT: f16_arg_on_reliable +// NOPT: f16_ret_on_reliable +// CHECK-NOT: f16_arg_on_not_reliable +// CHECK-NOT: f16_ret_on_not_reliable +cfg_select! { + target_has_reliable_f16 => { + pub fn f16_arg_on_reliable(_a: f16) { + todo!() + } + + pub fn f16_ret_on_reliable() -> f16 { + todo!() + } + } + _ => { + pub fn f16_arg_on_not_reliable(_a: f16) { + todo!() + } + + pub fn f16_ret_on_not_reliable() -> f16 { + todo!() + } -pub fn f128_arg(_a: f128) { - // CHECK-NOT: f128_arg - todo!() + #[unsafe(no_mangle)] + pub fn f16_arg_on_reliable() {} + #[unsafe(no_mangle)] + pub fn f16_ret_on_reliable() {} + } } -pub fn f128_ret() -> f128 { - // CHECK-NOT: f128_ret - todo!() +// NOPT: f128_arg_on_reliable +// NOPT: f128_ret_on_reliable +// CHECK-NOT: f128_arg_on_not_reliable +// CHECK-NOT: f128_ret_on_not_reliable +cfg_select! { + target_has_reliable_f128 => { + pub fn f128_arg_on_reliable(_a: f128) { + todo!() + } + + pub fn f128_ret_on_reliable() -> f128 { + todo!() + } + } + _ => { + pub fn f128_arg_on_not_reliable(_a: f128) { + todo!() + } + + pub fn f128_ret_on_not_reliable() -> f128 { + todo!() + } + + #[unsafe(no_mangle)] + pub fn f128_arg_on_reliable() {} + #[unsafe(no_mangle)] + pub fn f128_ret_on_reliable() {} + } } From 8959071f3ec3b0f7dc0e81786dda757bfccdacfb Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Sep 2026 14:54:58 +0800 Subject: [PATCH 0267/1309] fix(ci): use `--locked` for clippy-related inovcations --- .github/workflows/clippy.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index acf3d2d097adc..ce09d1bb92d84 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -19,7 +19,7 @@ jobs: sh rustup-init.sh -y --default-toolchain none rustup target add x86_64-unknown-linux-gnu - name: Check clippy configs all match - run: cargo run --manifest-path ci/Cargo.toml -- clippy-config-check + run: cargo run --locked --manifest-path ci/Cargo.toml -- clippy-config-check run_clippy: @@ -41,5 +41,5 @@ jobs: curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh sh rustup-init.sh -y --default-toolchain none - name: clippy - run: cargo clippy --manifest-path ${{ matrix.package }}/Cargo.toml + run: cargo clippy --locked --manifest-path ${{ matrix.package }}/Cargo.toml From 01891c74765af5c2910091e6ea23a42410b2d64c Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Sep 2026 14:59:19 +0800 Subject: [PATCH 0268/1309] chore(ci): remove unnecessary `rustup` target add The toolchain config file already makes `rustup` add the target by default. --- .github/workflows/clippy.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/clippy.yml b/.github/workflows/clippy.yml index ce09d1bb92d84..92e385d135c0e 100644 --- a/.github/workflows/clippy.yml +++ b/.github/workflows/clippy.yml @@ -17,7 +17,6 @@ jobs: run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh sh rustup-init.sh -y --default-toolchain none - rustup target add x86_64-unknown-linux-gnu - name: Check clippy configs all match run: cargo run --locked --manifest-path ci/Cargo.toml -- clippy-config-check From 24ba9a5b4c9fd45f57e6e37c883cef873c9c979b Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Sep 2026 15:00:07 +0800 Subject: [PATCH 0269/1309] fix(ci): also run clippy on `check_diff` --- ci/src/clippy_config_check.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/ci/src/clippy_config_check.rs b/ci/src/clippy_config_check.rs index 011ffe4ef18d7..c4c59f692f637 100644 --- a/ci/src/clippy_config_check.rs +++ b/ci/src/clippy_config_check.rs @@ -4,6 +4,7 @@ use itertools::Itertools; const CARGO_TOMLS: &[&'static str] = &[ "Cargo.toml", + "check_diff/Cargo.toml", "ci/Cargo.toml", "config_proc_macro/Cargo.toml", ]; From 1835bfd56fb74ca0c540084b34708813fed17ee1 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Thu, 17 Sep 2026 15:00:45 +0800 Subject: [PATCH 0270/1309] chore(check_diff): use similar clippy config --- check_diff/Cargo.toml | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/check_diff/Cargo.toml b/check_diff/Cargo.toml index 18a4aa90d6c0d..b18aa0c39d02a 100644 --- a/check_diff/Cargo.toml +++ b/check_diff/Cargo.toml @@ -15,3 +15,17 @@ diffy = "0.4.0" crossbeam-channel = "0.5.15" ignore = "0.4.25" toml = "1.1" + +[lints.clippy] +# allow all rules with a low priority .. +all = { level = "allow", priority = -1 } +# so we can pick out an exact subset of rules to deny +correctness = "deny" +char_lit_as_u8 = "deny" +four_forward_slashes = "deny" +non_minimal_cfg = "deny" +print_literal = "deny" +same_item_push = "deny" +single_char_add_str = "deny" +to_string_in_format_args = "deny" +unconditional_recursion = "deny" From f438cf83aa99ca29c8229594b8f28c63bee786ac Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 15 Sep 2026 12:37:49 +0000 Subject: [PATCH 0271/1309] put the check for empty `assert_fields_are_eq` at the right spot --- .../src/deriving/generic/mod.rs | 22 ++++++++---------- .../mgca/const-ctor-overflow-eval.rs | 3 +-- .../mgca/const-ctor-overflow-eval.stderr | 23 ++++++++++--------- tests/ui/derives/deriving-all-codegen.stdout | 7 +----- 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index a041e83a646ce..599c8e7feab43 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -837,7 +837,7 @@ impl<'a> TraitDef<'a> { ) -> Box { let field_tys = struct_def.fields().iter().map(|field| &*field.ty); - let methods = self.methods.iter().map(|method_def| { + let methods = self.methods.iter().filter_map(|method_def| { let ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } = method_def.extract_arg_details(cx, self, type_ident, generics); @@ -912,13 +912,7 @@ impl<'a> TraitDef<'a> { ) }; - // `assert_fields_are_eq` has an empty default implementation - if body.0.is_empty() && body.1.is_none() && method_def.name == sym::assert_fields_are_eq - { - return None; - } - - Some(method_def.create_method( + method_def.create_method( cx, self, type_ident, @@ -926,7 +920,7 @@ impl<'a> TraitDef<'a> { explicit_self, nonself_arg_tys, body, - )) + ) }); let is_packed = false; // enums are never packed @@ -1010,7 +1004,11 @@ impl<'a> MethodDef<'a> { explicit_self: Option, nonself_arg_tys: Vec<(Ident, Box)>, body: BlockOrExpr, - ) -> Box { + ) -> Option> { + // `assert_fields_are_eq` has an empty default implementation + if body.0.is_empty() && body.1.is_none() && self.name == sym::assert_fields_are_eq { + return None; + } let span = trait_.span; // Create the generics that aren't for `Self`. let fn_generics = self.generics.clone(); @@ -1041,7 +1039,7 @@ impl<'a> MethodDef<'a> { let defaultness = ast::Defaultness::Implicit; // Create the method. - Box::new(ast::AssocItem { + Some(Box::new(ast::AssocItem { id: ast::DUMMY_NODE_ID, attrs: self.attributes.clone(), span, @@ -1057,7 +1055,7 @@ impl<'a> MethodDef<'a> { eii_impl: None, })), tokens: None, - }) + })) } /// The normal case uses field access. diff --git a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs index a4538ffff3854..75e936ee8f5e3 100644 --- a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs +++ b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs @@ -7,13 +7,12 @@ struct U; #[derive(ConstParamTy, PartialEq, Eq)] //~^ ERROR overflow evaluating whether `S` is well-formed -//~| ERROR overflow evaluating whether `S` is well-formed - struct S() where S<{ U }>:; //~^ ERROR overflow evaluating whether `S` is well-formed //~| ERROR overflow evaluating whether `S` is well-formed //~| ERROR overflow evaluating whether `S` is well-formed +//~| ERROR overflow evaluating whether `S` is well-formed fn main() {} diff --git a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.stderr b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.stderr index bb393cad567e5..98ba1ed42ce3c 100644 --- a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.stderr +++ b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.stderr @@ -1,11 +1,11 @@ error[E0275]: overflow evaluating whether `S` is well-formed - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | S<{ U }>:; | ^^^^^^^^ | note: required by a bound in `S` - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | struct S() | - required by a bound in this struct @@ -14,13 +14,13 @@ LL | S<{ U }>:; | ^^^^^^^^ required by this bound in `S` error[E0275]: overflow evaluating whether `S` is well-formed - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | S<{ U }>:; | ^^^^^^^^ | note: required by a bound in `S` - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | struct S() | - required by a bound in this struct @@ -30,13 +30,13 @@ LL | S<{ U }>:; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0275]: overflow evaluating whether `S` is well-formed - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | S<{ U }>:; | ^^^^^^^^ | note: required by a bound in `S` - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | struct S() | - required by a bound in this struct @@ -52,7 +52,7 @@ LL | #[derive(ConstParamTy, PartialEq, Eq)] | ^^^^^^^^^ | note: required by a bound in `S` - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | struct S() | - required by a bound in this struct @@ -61,19 +61,20 @@ LL | S<{ U }>:; | ^^^^^^^^ required by this bound in `S` error[E0275]: overflow evaluating whether `S` is well-formed - --> $DIR/const-ctor-overflow-eval.rs:8:35 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | -LL | #[derive(ConstParamTy, PartialEq, Eq)] - | ^^ +LL | S<{ U }>:; + | ^^^^^^^^ | note: required by a bound in `S` - --> $DIR/const-ctor-overflow-eval.rs:14:5 + --> $DIR/const-ctor-overflow-eval.rs:12:5 | LL | struct S() | - required by a bound in this struct LL | where LL | S<{ U }>:; | ^^^^^^^^ required by this bound in `S` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 5 previous errors diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 436f57bb8ecb9..bf88d1c0cb7aa 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -61,12 +61,7 @@ impl ::core::cmp::PartialEq for Empty { fn eq(&self, other: &Empty) -> bool { true } } #[automatically_derived] -impl ::core::cmp::Eq for Empty { - #[inline] - #[doc(hidden)] - #[coverage(off)] - fn assert_fields_are_eq(&self) {} -} +impl ::core::cmp::Eq for Empty { } #[automatically_derived] impl ::core::cmp::PartialOrd for Empty { #[inline] From 459ba37b44f1c2bcea2d8672e5a6dedfb8f00a17 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 17 Sep 2026 01:24:45 -0700 Subject: [PATCH 0272/1309] Account for the separator between host and path --- src/librustdoc/passes/lint/bare_urls.rs | 65 ++++++++++++++----------- tests/rustdoc-ui/lints/bare-urls.fixed | 12 +++++ tests/rustdoc-ui/lints/bare-urls.rs | 12 +++++ tests/rustdoc-ui/lints/bare-urls.stderr | 38 ++++++++++++++- 4 files changed, 98 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index ed9fcdfaaa448..251d13fbfd175 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -98,41 +98,50 @@ fn find_raw_urls( // For now, we only check "full" URLs (meaning, starting with "http://" or "https://"). for match_ in URL_SCHEME_HOST_REGEX.find_iter(text) { let mut url_range = match_.range(); - // We found the scheme and host. Find the path, now. + // We found the scheme and host. Find the path, query, or fragment. // We want to check for matching, balanced parens, // but regex isn't powerful enough for that. let mut paren_stack = Vec::with_capacity(3); - while let Some(&c) = text.as_bytes().get(url_range.end) { - if c == b'(' { - paren_stack.push(url_range.end); - } else if c == b')' { - if paren_stack.pop().is_none() { - break; - } - } else if !matches!( - c, - b'-' - | b'a'..=b'z' - | b'A'..=b'Z' - | b'0'..=b'9' - | b'@' - | b':' - | b'%' - | b'_' - | b'\\' - | b'+' - | b'.' - | b'~' - | b'#' - | b'?' - | b'&' - | b'/' - | b'=' - ) { + 'parts: while let Some(&sep) = text.as_bytes().get(url_range.end) { + // The hostname must be immediately followed by a path, query, + // or fragment-declaring separator. + if !matches!(sep, b'/' | b'?' | b'#') { break; } url_range.end += 1; + while let Some(&c) = text.as_bytes().get(url_range.end) { + if c == b'(' { + paren_stack.push(url_range.end); + } else if c == b')' { + // We assume the first unmatched parenthesis marks the end of the url, + // as urls rarely contain unbalanced parenthesis in practice. + if paren_stack.pop().is_none() { + break 'parts; + } + } else if !matches!( + c, + b'-' + | b'a'..=b'z' + | b'A'..=b'Z' + | b'0'..=b'9' + | b'@' + | b':' + | b'%' + | b'_' + | b'\\' + | b'+' + | b'.' + | b'~' + | b'&' + | b'=' + ) { + break; + } + url_range.end += 1; + } } + // We assume the first unmatched parenthesis marks the end of the url, + // as urls rarely contain unbalanced parenthesis in practice. if let Some(&end) = paren_stack.first() { url_range.end = end; } diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed index 20d04a8a9727b..7a5c5635c01ce 100644 --- a/tests/rustdoc-ui/lints/bare-urls.fixed +++ b/tests/rustdoc-ui/lints/bare-urls.fixed @@ -143,3 +143,15 @@ pub fn nested_parens_unbalanced_5() {} /// See http://ex(amp)le.com/ pub fn nested_parens_cannot_appear_in_host() {} + +/// The path component of a URL must be separated from the rest by a `/`, +/// so the `=a` isn't part of the URL. +/// =a +//~^ ERROR this URL is not a hyperlink +pub fn equal_sign_after_host() {} + +/// A URL can, however, have a fragment or query without a slash. +/// or +//~^ ERROR this URL is not a hyperlink +//~| ERROR this URL is not a hyperlink +pub fn hash_or_question_after_host() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs index 12ab7b32e8bcb..3f493c60ee039 100644 --- a/tests/rustdoc-ui/lints/bare-urls.rs +++ b/tests/rustdoc-ui/lints/bare-urls.rs @@ -143,3 +143,15 @@ pub fn nested_parens_unbalanced_5() {} /// See http://ex(amp)le.com/ pub fn nested_parens_cannot_appear_in_host() {} + +/// The path component of a URL must be separated from the rest by a `/`, +/// so the `=a` isn't part of the URL. +/// https://foo.bar=a +//~^ ERROR this URL is not a hyperlink +pub fn equal_sign_after_host() {} + +/// A URL can, however, have a fragment or query without a slash. +/// https://foo.bar#a or https://foo.bar?a +//~^ ERROR this URL is not a hyperlink +//~| ERROR this URL is not a hyperlink +pub fn hash_or_question_after_host() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr index 1f39f90106f1f..954f95f1a0f43 100644 --- a/tests/rustdoc-ui/lints/bare-urls.stderr +++ b/tests/rustdoc-ui/lints/bare-urls.stderr @@ -508,5 +508,41 @@ help: use an automatic link instead LL | /// See .) | + + -error: aborting due to 42 previous errors +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:149:5 + | +LL | /// https://foo.bar=a + | ^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// =a + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:154:5 + | +LL | /// https://foo.bar#a or https://foo.bar?a + | ^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// or https://foo.bar?a + | + + + +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:154:26 + | +LL | /// https://foo.bar#a or https://foo.bar?a + | ^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// https://foo.bar#a or + | + + + +error: aborting due to 45 previous errors From a83dd65fd16ab1815475eb72ea340d33dd1e2b36 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Thu, 17 Sep 2026 01:39:50 -0700 Subject: [PATCH 0273/1309] Account for URLs with accidental formatting --- src/librustdoc/passes/lint/bare_urls.rs | 19 +++++++++---------- tests/rustdoc-ui/lints/bare-urls.fixed | 8 +++++++- tests/rustdoc-ui/lints/bare-urls.rs | 6 ++++++ tests/rustdoc-ui/lints/bare-urls.stderr | 20 ++++++++++++++++---- 4 files changed, 38 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/passes/lint/bare_urls.rs b/src/librustdoc/passes/lint/bare_urls.rs index 251d13fbfd175..0b78be0e6dc8d 100644 --- a/src/librustdoc/passes/lint/bare_urls.rs +++ b/src/librustdoc/passes/lint/bare_urls.rs @@ -63,7 +63,7 @@ pub(super) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId, dox: & while let Some((event, range)) = p.next() { match event { - Event::Text(s) => find_raw_urls(cx, dox, &s, range, &report_diag), + Event::Text(_s) => find_raw_urls(cx, dox, range, &report_diag), // We don't want to check the text inside code blocks or links. Event::Start(tag @ (Tag::CodeBlock(_) | Tag::Link { .. })) => { let end = tag.to_end(); @@ -90,26 +90,29 @@ static URL_SCHEME_HOST_REGEX: LazyLock = LazyLock::new(|| { fn find_raw_urls( cx: &DocContext<'_>, dox: &str, - text: &str, range: Range, f: &impl Fn(&DocContext<'_>, &'static str, Range, Option<&str>), ) { - trace!("looking for raw urls in {text}"); + trace!("looking for raw urls in {text}", text = &dox[range.clone()]); // For now, we only check "full" URLs (meaning, starting with "http://" or "https://"). - for match_ in URL_SCHEME_HOST_REGEX.find_iter(text) { + for match_ in URL_SCHEME_HOST_REGEX.find_iter(&dox[range.clone()]) { let mut url_range = match_.range(); + // We have a range within `dox[range]`. + // We need a range within `dox` to report the diagnostic. + url_range.start += range.start; + url_range.end += range.start; // We found the scheme and host. Find the path, query, or fragment. // We want to check for matching, balanced parens, // but regex isn't powerful enough for that. let mut paren_stack = Vec::with_capacity(3); - 'parts: while let Some(&sep) = text.as_bytes().get(url_range.end) { + 'parts: while let Some(&sep) = dox.as_bytes().get(url_range.end) { // The hostname must be immediately followed by a path, query, // or fragment-declaring separator. if !matches!(sep, b'/' | b'?' | b'#') { break; } url_range.end += 1; - while let Some(&c) = text.as_bytes().get(url_range.end) { + while let Some(&c) = dox.as_bytes().get(url_range.end) { if c == b'(' { paren_stack.push(url_range.end); } else if c == b')' { @@ -145,10 +148,6 @@ fn find_raw_urls( if let Some(&end) = paren_stack.first() { url_range.end = end; } - // We have a range within `text`. - // We need a range within `dox` to report the diagnostic. - url_range.start += range.start; - url_range.end += range.start; let mut without_brackets = None; // If the link is contained inside `[]`, then we need to replace the brackets and // not just add `<>`. diff --git a/tests/rustdoc-ui/lints/bare-urls.fixed b/tests/rustdoc-ui/lints/bare-urls.fixed index 7a5c5635c01ce..8d4d132e49510 100644 --- a/tests/rustdoc-ui/lints/bare-urls.fixed +++ b/tests/rustdoc-ui/lints/bare-urls.fixed @@ -101,7 +101,7 @@ pub fn underscore_without_parens_1() {} //~^ ERROR this URL is not a hyperlink pub fn underscore_without_parens_2() {} -/// See __ +/// See _ //~^ ERROR this URL is not a hyperlink pub fn underscore_emphasis_without_parens() {} @@ -155,3 +155,9 @@ pub fn equal_sign_after_host() {} //~^ ERROR this URL is not a hyperlink //~| ERROR this URL is not a hyperlink pub fn hash_or_question_after_host() {} + +/// This URL contains italics, +/// but should still produce a suggestion that wraps the whole thing. +/// +//~^ ERROR this URL is not a hyperlink +pub fn italics() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.rs b/tests/rustdoc-ui/lints/bare-urls.rs index 3f493c60ee039..9bcfa2c8b3a0c 100644 --- a/tests/rustdoc-ui/lints/bare-urls.rs +++ b/tests/rustdoc-ui/lints/bare-urls.rs @@ -155,3 +155,9 @@ pub fn equal_sign_after_host() {} //~^ ERROR this URL is not a hyperlink //~| ERROR this URL is not a hyperlink pub fn hash_or_question_after_host() {} + +/// This URL contains italics, +/// but should still produce a suggestion that wraps the whole thing. +/// https://example.com/_foo_/bar +//~^ ERROR this URL is not a hyperlink +pub fn italics() {} diff --git a/tests/rustdoc-ui/lints/bare-urls.stderr b/tests/rustdoc-ui/lints/bare-urls.stderr index 954f95f1a0f43..aa22a4a4f62f3 100644 --- a/tests/rustdoc-ui/lints/bare-urls.stderr +++ b/tests/rustdoc-ui/lints/bare-urls.stderr @@ -392,13 +392,13 @@ error: this URL is not a hyperlink --> $DIR/bare-urls.rs:104:10 | LL | /// See _https://example.com/test.html_ - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: bare URLs are not automatically turned into clickable links help: use an automatic link instead | -LL | /// See __ - | + + +LL | /// See _ + | + + error: this URL is not a hyperlink --> $DIR/bare-urls.rs:108:9 @@ -544,5 +544,17 @@ help: use an automatic link instead LL | /// https://foo.bar#a or | + + -error: aborting due to 45 previous errors +error: this URL is not a hyperlink + --> $DIR/bare-urls.rs:161:5 + | +LL | /// https://example.com/_foo_/bar + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: bare URLs are not automatically turned into clickable links +help: use an automatic link instead + | +LL | /// + | + + + +error: aborting due to 46 previous errors From 8a1e154b9aa20c15e1948d70d58e991daaf707bb Mon Sep 17 00:00:00 2001 From: yilin <21307130191@m.fudan.edu.cn> Date: Thu, 17 Sep 2026 17:06:15 +0800 Subject: [PATCH 0274/1309] Add safety section for atomic_load/store --- library/core/src/intrinsics/mod.rs | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ab2bbb8ab4449..ecc8b66ec5785 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -154,8 +154,20 @@ pub const unsafe fn atomic_cxchgweak< /// Loads the current value of the pointer. /// `T` must be an integer or pointer type. /// +/// # Safety +/// +/// * If `VOLATILE` is `true`, this is equivalent to [Atomic::load_volatile]. +/// Refer to the documentation of that method for safety requirements. +/// +/// * If `VOLATILE` is `false`, this is equivalent to [Atomic::from_ptr] followed +/// by [Atomic::load]. Refer to the documentation of [Atomic::from_ptr] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`]. +/// +/// [Atomic::load_volatile]: AtomicI32::load_volatile +/// [Atomic::from_ptr]: AtomicI32::from_ptr +/// [Atomic::load]: AtomicI32::load #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_load( @@ -165,8 +177,20 @@ pub const unsafe fn atomic_load( From 5a0103421261759da77fb801e2cba0dead819695 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 15 Sep 2026 00:08:34 +0800 Subject: [PATCH 0275/1309] intrinsic-test: Add C intrinsic name prefix support Add a per-architecture C intrinsic name prefix to support architectures whose C intrinsic names differ from their Rust intrinsic names. --- library/stdarch/crates/intrinsic-test/src/arm/mod.rs | 2 ++ library/stdarch/crates/intrinsic-test/src/common/gen_c.rs | 3 ++- library/stdarch/crates/intrinsic-test/src/common/mod.rs | 4 ++++ library/stdarch/crates/intrinsic-test/src/x86/mod.rs | 2 ++ 4 files changed, 10 insertions(+), 1 deletion(-) diff --git a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs index 9c2d0f336a7aa..5e892c613464a 100644 --- a/library/stdarch/crates/intrinsic-test/src/arm/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/arm/mod.rs @@ -37,6 +37,8 @@ impl SupportedArchitecture for Arm { "#; const RUST_PRELUDE: &str = RUST_PRELUDE; + const C_NAME_PREFIX: &str = ""; + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str> { // GCC uses an extra `-` in the arch name let big_endian = cli_options.target.starts_with("aarch64_be"); diff --git a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs index 30e7bb1d375a3..a749afd17d367 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/gen_c.rs @@ -38,9 +38,10 @@ pub fn write_wrapper_c( fmt(&format_args!( " void {name}_wrapper{imm_arglist}({return_ty}* __dst{arglist}) {{ - *__dst = {name}({params}); + *__dst = {prefix}{name}({params}); }}", return_ty = intrinsic.results.c_type(), + prefix = A::C_NAME_PREFIX, name = intrinsic.name, imm_arglist = imm_values diff --git a/library/stdarch/crates/intrinsic-test/src/common/mod.rs b/library/stdarch/crates/intrinsic-test/src/common/mod.rs index e89599d06ea77..9cde80daff76c 100644 --- a/library/stdarch/crates/intrinsic-test/src/common/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/common/mod.rs @@ -49,6 +49,10 @@ pub trait SupportedArchitecture: Sized { const C_PRELUDE: &str; const RUST_PRELUDE: &str; + /// Per-architecture prefix used to convert a Rust intrinsic name to the + /// corresponding C intrinsic name by prepending it to the Rust name. + const C_NAME_PREFIX: &str; + fn c_compiler_flags(&self, cli_options: &ProcessedCli) -> Vec<&str>; fn generate_c_file(&self) { diff --git a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs index 36f4fee43741b..9eafcf1fc7b96 100644 --- a/library/stdarch/crates/intrinsic-test/src/x86/mod.rs +++ b/library/stdarch/crates/intrinsic-test/src/x86/mod.rs @@ -32,6 +32,8 @@ impl SupportedArchitecture for X86 { "#; const RUST_PRELUDE: &str = RUST_PRELUDE; + const C_NAME_PREFIX: &str = ""; + fn c_compiler_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { vec![ "-maes", From bb2b679c54f314b73736ffc4e98418afb94849c8 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Mon, 14 Sep 2026 11:32:27 +0800 Subject: [PATCH 0276/1309] intrinsic-test: Support testing LoongArch64 SIMD intrinsics --- library/stdarch/.github/workflows/main.yml | 1 + .../loongarch64-unknown-linux-gnu/Dockerfile | 9 +- library/stdarch/ci/intrinsic-test.sh | 14 + .../missing_loongarch64_clang.txt | 0 .../missing_loongarch64_common.txt | 31 ++ .../missing_loongarch64_gcc.txt | 0 .../intrinsic-test/src/loongarch/intrinsic.rs | 19 ++ .../intrinsic-test/src/loongarch/mod.rs | 139 ++++++++ .../intrinsic-test/src/loongarch/parser.rs | 179 ++++++++++ .../intrinsic-test/src/loongarch/types.rs | 309 ++++++++++++++++++ .../stdarch/crates/intrinsic-test/src/main.rs | 7 + 11 files changed, 707 insertions(+), 1 deletion(-) create mode 100644 library/stdarch/crates/intrinsic-test/missing_loongarch64_clang.txt create mode 100644 library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt create mode 100644 library/stdarch/crates/intrinsic-test/missing_loongarch64_gcc.txt create mode 100644 library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs create mode 100644 library/stdarch/crates/intrinsic-test/src/loongarch/types.rs diff --git a/library/stdarch/.github/workflows/main.yml b/library/stdarch/.github/workflows/main.yml index 5c2e2ae4a8e21..51a37375d12f5 100644 --- a/library/stdarch/.github/workflows/main.yml +++ b/library/stdarch/.github/workflows/main.yml @@ -279,6 +279,7 @@ jobs: - aarch64-unknown-linux-gnu - aarch64_be-unknown-linux-gnu - armv7-unknown-linux-gnueabihf + - loongarch64-unknown-linux-gnu - x86_64-unknown-linux-gnu profile: [dev, release] cc: [clang, gcc] diff --git a/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile b/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile index e803dae1006a0..8cbd2d8080002 100644 --- a/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile +++ b/library/stdarch/ci/docker/loongarch64-unknown-linux-gnu/Dockerfile @@ -3,8 +3,15 @@ FROM ubuntu:25.10 RUN apt-get update && \ apt-get install -y --no-install-recommends \ gcc libc6-dev qemu-user ca-certificates \ - gcc-loongarch64-linux-gnu libc6-dev-loong64-cross + gcc-loongarch64-linux-gnu libc6-dev-loong64-cross \ + wget +RUN wget https://ci-mirrors.rust-lang.org/llvm/llvm-22.1.4-x86_64.tar.gz -O llvm.tar.xz +RUN mkdir llvm +RUN tar -xvf llvm.tar.xz --strip-components=1 -C llvm + +ENV CLANG_PATH="/llvm/bin/clang" +ENV GCC_PATH=loongarch64-linux-gnu-gcc ENV CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_LINKER=loongarch64-linux-gnu-gcc \ CARGO_TARGET_LOONGARCH64_UNKNOWN_LINUX_GNU_RUNNER="qemu-loongarch64 -cpu max -L /usr/loongarch64-linux-gnu" \ diff --git a/library/stdarch/ci/intrinsic-test.sh b/library/stdarch/ci/intrinsic-test.sh index 3966aa88d8f41..4b7a3d27ea4e2 100755 --- a/library/stdarch/ci/intrinsic-test.sh +++ b/library/stdarch/ci/intrinsic-test.sh @@ -65,6 +65,12 @@ case ${TARGET} in ARCH=x86 RUNTIME_RUSTFLAGS= ;; + + loongarch64*) + export CFLAGS="-I/usr/loongarch64-linux-gnu/include/" + ARCH=loongarch64 + RUNTIME_RUSTFLAGS=-Ctarget-feature=+lsx,+lasx,+frecipe + ;; *) ;; @@ -80,6 +86,14 @@ case "${TARGET}" in --target "${TARGET}" \ --cc-arg-style "${CC_ARG_STYLE}" ;; + loongarch64*) + cargo run "${INTRINSIC_TEST}" --release \ + --bin intrinsic-test -- crates/stdarch-gen-loongarch \ + --skip "crates/intrinsic-test/missing_${ARCH}_common.txt" \ + --skip "crates/intrinsic-test/missing_${ARCH}_${CC_KIND}.txt" \ + --target "${TARGET}" \ + --cc-arg-style "${CC_ARG_STYLE}" + ;; *) cargo run "${INTRINSIC_TEST}" --release \ --bin intrinsic-test -- intrinsics_data/arm_intrinsics.json \ diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_clang.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_clang.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt new file mode 100644 index 0000000000000..5817247c2f4d2 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/missing_loongarch64_common.txt @@ -0,0 +1,31 @@ +# Missing in old c compiler +lasx_concat_128 +lasx_concat_128_d +lasx_concat_128_s +lasx_extract_128_hi +lasx_extract_128_lo +lasx_extract_128_hi_d +lasx_extract_128_lo_d +lasx_extract_128_hi_s +lasx_extract_128_lo_s +lasx_insert_128_hi +lasx_insert_128_lo +lasx_insert_128_hi_d +lasx_insert_128_lo_d +lasx_insert_128_hi_s +lasx_insert_128_lo_s + +# Missing in old qemu +lasx_xvfrecipe_d +lasx_xvfrecipe_s +lasx_xvfrsqrte_d +lasx_xvfrsqrte_s +lsx_vfrecipe_d +lsx_vfrecipe_s +lsx_vfrsqrte_d +lsx_vfrsqrte_s + +# Top bits are undefined, unclear how to test these +lasx_cast_128 +lasx_cast_128_d +lasx_cast_128_s diff --git a/library/stdarch/crates/intrinsic-test/missing_loongarch64_gcc.txt b/library/stdarch/crates/intrinsic-test/missing_loongarch64_gcc.txt new file mode 100644 index 0000000000000..e69de29bb2d1d diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs new file mode 100644 index 0000000000000..f8ebb3e7ab34c --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/intrinsic.rs @@ -0,0 +1,19 @@ +use crate::common::intrinsic_helpers::IntrinsicType; +use std::ops::{Deref, DerefMut}; + +#[derive(Debug, Clone, PartialEq)] +pub struct LoongArchType(pub IntrinsicType); + +impl Deref for LoongArchType { + type Target = IntrinsicType; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for LoongArchType { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs new file mode 100644 index 0000000000000..00cff20a0f083 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/mod.rs @@ -0,0 +1,139 @@ +mod intrinsic; +mod parser; +mod types; + +use std::path::Path; + +use crate::common::SupportedArchitecture; +use crate::common::cli::ProcessedCli; +use crate::common::intrinsic::Intrinsic; +use crate::common::intrinsic_helpers::TypeKind; +use intrinsic::LoongArchType; +use parser::get_intrinsics; + +#[derive(PartialEq)] +pub struct LoongArch { + intrinsics: Vec>, +} + +impl SupportedArchitecture for LoongArch { + type Type = LoongArchType; + + fn intrinsics(&self) -> &[Intrinsic] { + &self.intrinsics + } + + const NOTICE: &str = r#" +// This is a transient test file, not intended for distribution. Some aspects of the +// test are derived from LoongArch specification files, published under the same license as the +// `intrinsic-test` crate. +"#; + + const C_PRELUDE: &str = r#" +#include +#include +"#; + const RUST_PRELUDE: &str = RUST_PRELUDE; + + const C_NAME_PREFIX: &str = "__"; + + fn c_compiler_flags(&self, _cli_options: &ProcessedCli) -> Vec<&str> { + let mut flags = vec!["-mlsx"]; + if self + .intrinsics + .iter() + .any(|intrinsic| intrinsic.extension == "LASX") + { + flags.push("-mlasx"); + } + if self.intrinsics.iter().any(|intrinsic| { + intrinsic.name.contains("frecipe") || intrinsic.name.contains("frsqrte") + }) { + flags.push("-mfrecipe"); + } + flags + } + + fn create(cli_options: &ProcessedCli) -> Self { + let mut intrinsics = + load_intrinsics(&cli_options.filename).expect("Error parsing input file"); + + intrinsics.sort_by(|a, b| a.name.cmp(&b.name)); + intrinsics.dedup_by(|a, b| { + a.name == b.name && a.results == b.results && a.arguments == b.arguments + }); + + let intrinsics = intrinsics + .into_iter() + // Skip intrinsics that don't return a value. + .filter(|intrinsic| intrinsic.results.kind() != TypeKind::Void) + .filter(|intrinsic| !intrinsic.arguments.args.is_empty()) + // Skip pointers for now, we would probably need to look at the return + // type to work out how many elements we need to point to. + .filter(|intrinsic| !intrinsic.arguments.iter().any(|arg| arg.is_ptr())) + // Skip intrinsics from `--skip` + .filter(|intrinsic| !cli_options.skip.contains(&intrinsic.name)) + .collect::>(); + + let sample_percentage: usize = cli_options.sample_percentage as usize; + let sample_size = (intrinsics.len() * sample_percentage) / 100; + let intrinsics = intrinsics.into_iter().take(sample_size).collect(); + + Self { intrinsics } + } + + fn predicate_function(_: u32) -> String { + unimplemented!("no scalable vectors on LoongArch") + } +} + +fn load_intrinsics(path: &Path) -> Result>, Box> { + if path.is_dir() { + let mut intrinsics = Vec::new(); + for spec in ["lsx.spec", "lasx.spec"] { + let spec_path = path.join(spec); + if spec_path.exists() { + intrinsics.extend(get_intrinsics(&spec_path)?); + } + } + return Ok(intrinsics); + } + + get_intrinsics(path) +} + +const RUST_PRELUDE: &str = r#" +#![feature(stdarch_loongarch)] + +use core_arch::arch::loongarch64::*; + +#[inline] +unsafe fn lsx_vld_to_m128i(mem_addr: *const i8) -> m128i { + lsx_vld::<0>(mem_addr) +} + +#[inline] +unsafe fn lsx_vld_to_m128(mem_addr: *const i8) -> m128 { + core::mem::transmute(lsx_vld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lsx_vld_to_m128d(mem_addr: *const i8) -> m128d { + core::mem::transmute(lsx_vld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lasx_xvld_to_m256i(mem_addr: *const i8) -> m256i { + lasx_xvld::<0>(mem_addr) +} + +#[inline] +unsafe fn lasx_xvld_to_m256(mem_addr: *const i8) -> m256 { + core::mem::transmute(lasx_xvld::<0>(mem_addr)) +} + +#[inline] +unsafe fn lasx_xvld_to_m256d(mem_addr: *const i8) -> m256d { + core::mem::transmute(lasx_xvld::<0>(mem_addr)) +} +"#; diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs new file mode 100644 index 0000000000000..ecb5d1ab3e8df --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/parser.rs @@ -0,0 +1,179 @@ +use std::path::Path; + +use super::intrinsic::LoongArchType; +use super::types::parse_intrinsic_type; +use crate::common::argument::{Argument, ArgumentList}; +use crate::common::constraint::Constraint; +use crate::common::intrinsic::Intrinsic; +use crate::loongarch::LoongArch; + +pub fn get_intrinsics( + filename: &Path, +) -> Result>, Box> { + parse_spec_file(filename) +} + +fn parse_spec_file( + filename: &Path, +) -> Result>, Box> { + let contents = std::fs::read_to_string(filename)?; + parse_spec_contents(&contents) +} + +fn parse_spec_contents( + contents: &str, +) -> Result>, Box> { + let mut intrinsics = Vec::new(); + let mut record = Vec::new(); + + for line in contents.lines().chain(std::iter::once("")) { + let line = line.trim(); + if line.is_empty() { + if !record.is_empty() { + if let Some(intrinsic) = parse_record(&record)? { + intrinsics.push(intrinsic); + } + record.clear(); + } + continue; + } + record.push(line); + } + + Ok(intrinsics) +} + +fn parse_record( + record: &[&str], +) -> Result>, Box> { + let mut name = None; + let mut asm_formats = Vec::new(); + let mut data_types = None; + + for line in record { + if let Some(value) = line.strip_prefix("name = ") { + name = Some(value.to_string()); + } else if let Some(value) = line.strip_prefix("asm-fmts = ") { + asm_formats = value + .split(',') + .map(|part| part.trim().to_string()) + .collect(); + } else if let Some(value) = line.strip_prefix("data-types = ") { + data_types = Some(value); + } + } + + let Some(data_types) = data_types else { + return Ok(None); + }; + + let name = name.ok_or("missing name before data-types")?; + Ok(Some(parse_intrinsic(&name, &asm_formats, data_types)?)) +} + +fn parse_intrinsic( + name: &str, + asm_formats: &[String], + data_types: &str, +) -> Result, Box> { + let data_types = data_types + .split(',') + .map(|value| value.trim()) + .filter(|value| !value.is_empty()) + .collect::>(); + let Some((result_type, argument_types)) = data_types.split_first() else { + return Err("missing data-types for intrinsic".into()); + }; + let result = LoongArchType(parse_intrinsic_type(result_type)?); + let asm_offset = asm_formats + .len() + .checked_sub(argument_types.len()) + .ok_or_else(|| format!("{name}: fewer asm formats than arguments"))?; + let arguments = argument_types + .iter() + .enumerate() + .map(|(pos, data_type)| { + let constraint = asm_formats + .get(pos + asm_offset) + .and_then(|format| parse_constraint(name, format)); + let mut ty = LoongArchType(parse_intrinsic_type(data_type)?); + if constraint.is_some() { + ty.constant = true; + } + Ok(Argument::new( + pos, + format!("arg_{pos}"), + ty, + constraint, + false, + )) + }) + .collect::, String>>()?; + + Ok(Intrinsic { + name: name.to_string(), + arguments: ArgumentList { args: arguments }, + results: result, + arch_tags: Vec::new(), + extension: extension_for(name)?.to_string(), + }) +} + +fn parse_constraint(name: &str, asm_format: &str) -> Option { + if let Some(cons) = special_constraint(name) { + return Some(cons); + } + if let Some(bits) = asm_format.strip_prefix("ui") { + return Some(unsigned_constraint(bits.parse::().ok()?)); + } + if let Some(bits) = asm_format + .strip_prefix("si") + .or_else(|| asm_format.strip_prefix('i')) + { + return Some(signed_constraint(bits.parse::().ok()?)); + } + None +} + +fn special_constraint(name: &str) -> Option { + match name { + "lsx_vldi" | "lasx_xvldi" => { + // CC: imm13 only support 0000 ~ 1100 in bits 9 ~ 12 when bit ‘13’ is 1 + let values: Vec = (0i64..8192i64) + .filter(|&x| x < 4096 || ((x >> 8) & 0xf) < 13) + // sign extend + .map(|x| ((x << 51) as i64) >> 51) + .collect(); + Some(Constraint::Set(values)) + } + _ => None, + } +} + +fn unsigned_constraint(bits: u32) -> Constraint { + Constraint::Range(0..(1i64 << bits.min(63))) +} + +fn signed_constraint(bits: u32) -> Constraint { + let min = if bits == 64 { + i64::MIN + } else { + -(1i64 << (bits - 1)) + }; + let max = if bits == 64 { + i64::MAX + } else { + 1i64 << (bits - 1) + }; + Constraint::Range(min..max) +} + +fn extension_for(name: &str) -> Result<&'static str, Box> { + if name.starts_with("lasx_") { + Ok("LASX") + } else if name.starts_with("lsx_") { + Ok("LSX") + } else { + Err(format!("unsupported LoongArch intrinsic name {name}").into()) + } +} diff --git a/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs b/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs new file mode 100644 index 0000000000000..dd4e578e67a41 --- /dev/null +++ b/library/stdarch/crates/intrinsic-test/src/loongarch/types.rs @@ -0,0 +1,309 @@ +use super::intrinsic::LoongArchType; +use crate::common::intrinsic_helpers::{IntrinsicType, Sign, SimdLen, TypeDefinition, TypeKind}; + +impl TypeDefinition for LoongArchType { + fn c_type(&self) -> String { + if self.ptr { + return if self.ptr_constant { + "const void*".to_string() + } else { + "void*".to_string() + }; + } + + match (self.kind(), self.simd_len) { + (_, Some(SimdLen::Fixed(lanes))) => { + format!( + "__{}", + vector_type_name(lanes, self.inner_size(), self.kind()) + ) + } + (TypeKind::Int(Sign::Signed), None) => { + scalar_type_name(true, scalar_signature_bits(self.inner_size())).to_string() + } + (TypeKind::Int(Sign::Unsigned), None) => { + scalar_type_name(false, scalar_signature_bits(self.inner_size())).to_string() + } + (TypeKind::Float, None) => match self.inner_size() { + 32 => "float".to_string(), + 64 => "double".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + (TypeKind::Void, None) => "void".to_string(), + _ => unreachable!("unsupported LoongArch type {self:#?}"), + } + } + + fn rust_type(&self) -> String { + if self.ptr { + return format!( + "*{} core::ffi::c_void", + if self.ptr_constant { "const" } else { "mut" }, + ); + } + + match (self.kind(), self.simd_len) { + (_, Some(SimdLen::Fixed(lanes))) => { + vector_type_name(lanes, self.inner_size(), self.kind()).to_string() + } + (TypeKind::Int(Sign::Signed), None) => { + semantic_rust_scalar_type(true, scalar_signature_bits(self.inner_size())) + .to_string() + } + (TypeKind::Int(Sign::Unsigned), None) => { + semantic_rust_scalar_type(false, scalar_signature_bits(self.inner_size())) + .to_string() + } + (TypeKind::Float, None) => match self.inner_size() { + 32 => "f32".to_string(), + 64 => "f64".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + (TypeKind::Void, None) => "()".to_string(), + _ => unreachable!("unsupported LoongArch type {self:#?}"), + } + } + + fn rust_scalar_type(&self) -> String { + match self.kind() { + TypeKind::Int(Sign::Signed) => { + semantic_rust_scalar_type(true, self.inner_size()).to_string() + } + TypeKind::Int(Sign::Unsigned) => { + semantic_rust_scalar_type(false, self.inner_size()).to_string() + } + TypeKind::Float => match self.inner_size() { + 32 => "f32".to_string(), + 64 => "f64".to_string(), + bits => unreachable!("unsupported scalar float width {bits}"), + }, + _ => unreachable!("unsupported LoongArch scalar type {self:#?}"), + } + } + + fn load_function(&self) -> String { + let Some(SimdLen::Fixed(lanes)) = self.simd_len else { + unreachable!("LoongArch loads are only used for SIMD types") + }; + + match (lanes * self.inner_size(), self.kind()) { + (128, TypeKind::Float) if self.inner_size() == 64 => "lsx_vld_to_m128d".to_string(), + (128, TypeKind::Float) => "lsx_vld_to_m128".to_string(), + (128, _) => "lsx_vld_to_m128i".to_string(), + (256, TypeKind::Float) if self.inner_size() == 64 => "lasx_xvld_to_m256d".to_string(), + (256, TypeKind::Float) => "lasx_xvld_to_m256".to_string(), + (256, _) => "lasx_xvld_to_m256i".to_string(), + bits => unreachable!("unsupported LoongArch vector width {bits:?}"), + } + } +} + +fn vector_type_name(lanes: u32, bit_len: u32, kind: TypeKind) -> &'static str { + match (lanes * bit_len, kind, bit_len) { + (128, TypeKind::Float, 32) => "m128", + (128, TypeKind::Float, 64) => "m128d", + (128, _, _) => "m128i", + (256, TypeKind::Float, 32) => "m256", + (256, TypeKind::Float, 64) => "m256d", + (256, _, _) => "m256i", + _ => unreachable!("unsupported LoongArch vector shape {kind:?}x{bit_len}x{lanes}"), + } +} + +fn scalar_type_name(signed: bool, bit_len: u32) -> &'static str { + match (signed, bit_len) { + (true, 32) => "int32_t", + (true, 64) => "int64_t", + (false, 32) => "uint32_t", + (false, 64) => "uint64_t", + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +fn scalar_signature_bits(bit_len: u32) -> u32 { + match bit_len { + 8 | 16 | 32 => 32, + 64 => 64, + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +fn semantic_rust_scalar_type(signed: bool, bit_len: u32) -> &'static str { + match (signed, bit_len) { + (true, 8) => "i8", + (true, 16) => "i16", + (true, 32) => "i32", + (true, 64) => "i64", + (false, 8) => "u8", + (false, 16) => "u16", + (false, 32) => "u32", + (false, 64) => "u64", + _ => unreachable!("unsupported LoongArch scalar width {bit_len}"), + } +} + +pub fn parse_intrinsic_type(s: &str) -> Result { + let (kind, bit_len, simd_len, ptr, ptr_constant) = match s { + "V16QI" => ( + TypeKind::Int(Sign::Signed), + Some(8), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "V32QI" => ( + TypeKind::Int(Sign::Signed), + Some(8), + Some(SimdLen::Fixed(32)), + false, + false, + ), + "V8HI" => ( + TypeKind::Int(Sign::Signed), + Some(16), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V16HI" => ( + TypeKind::Int(Sign::Signed), + Some(16), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "V4SI" => ( + TypeKind::Int(Sign::Signed), + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V8SI" => ( + TypeKind::Int(Sign::Signed), + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V2DI" => ( + TypeKind::Int(Sign::Signed), + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "V4DI" => ( + TypeKind::Int(Sign::Signed), + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "UV16QI" => ( + TypeKind::Int(Sign::Unsigned), + Some(8), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "UV32QI" => ( + TypeKind::Int(Sign::Unsigned), + Some(8), + Some(SimdLen::Fixed(32)), + false, + false, + ), + "UV8HI" => ( + TypeKind::Int(Sign::Unsigned), + Some(16), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "UV16HI" => ( + TypeKind::Int(Sign::Unsigned), + Some(16), + Some(SimdLen::Fixed(16)), + false, + false, + ), + "UV4SI" => ( + TypeKind::Int(Sign::Unsigned), + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "UV8SI" => ( + TypeKind::Int(Sign::Unsigned), + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "UV2DI" => ( + TypeKind::Int(Sign::Unsigned), + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "UV4DI" => ( + TypeKind::Int(Sign::Unsigned), + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V4SF" => ( + TypeKind::Float, + Some(32), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "V8SF" => ( + TypeKind::Float, + Some(32), + Some(SimdLen::Fixed(8)), + false, + false, + ), + "V2DF" => ( + TypeKind::Float, + Some(64), + Some(SimdLen::Fixed(2)), + false, + false, + ), + "V4DF" => ( + TypeKind::Float, + Some(64), + Some(SimdLen::Fixed(4)), + false, + false, + ), + "QI" => (TypeKind::Int(Sign::Signed), Some(8), None, false, false), + "HI" => (TypeKind::Int(Sign::Signed), Some(16), None, false, false), + "SI" => (TypeKind::Int(Sign::Signed), Some(32), None, false, false), + "UQI" => (TypeKind::Int(Sign::Unsigned), Some(8), None, false, false), + "UHI" => (TypeKind::Int(Sign::Unsigned), Some(16), None, false, false), + "USI" => (TypeKind::Int(Sign::Unsigned), Some(32), None, false, false), + "DI" => (TypeKind::Int(Sign::Signed), Some(64), None, false, false), + "UDI" => (TypeKind::Int(Sign::Unsigned), Some(64), None, false, false), + "CVPOINTER" => (TypeKind::Int(Sign::Signed), Some(8), None, true, true), + "VOID" => (TypeKind::Void, None, None, false, false), + _ => return Err(format!("unsupported LoongArch type {s}")), + }; + + Ok(IntrinsicType { + constant: false, + ptr_constant, + ptr, + kind, + bit_len, + simd_len, + vec_len: None, + }) +} diff --git a/library/stdarch/crates/intrinsic-test/src/main.rs b/library/stdarch/crates/intrinsic-test/src/main.rs index e25eb48a456d1..91e76d8f5fa50 100644 --- a/library/stdarch/crates/intrinsic-test/src/main.rs +++ b/library/stdarch/crates/intrinsic-test/src/main.rs @@ -3,11 +3,13 @@ extern crate log; mod arm; mod common; +mod loongarch; mod x86; use arm::Arm; use common::SupportedArchitecture; use common::cli::{Cli, ProcessedCli}; +use loongarch::LoongArch; use x86::X86; fn main() { @@ -21,6 +23,11 @@ fn main() { run(Arm::create(&processed_cli_options), processed_cli_options) } else if processed_cli_options.target.starts_with("x86") { run(X86::create(&processed_cli_options), processed_cli_options) + } else if processed_cli_options.target.starts_with("loongarch64") { + run( + LoongArch::create(&processed_cli_options), + processed_cli_options, + ) } else { unimplemented!("Unsupported target {}", processed_cli_options.target) } From d4465bad0696e9a592485b997f03aa2859255029 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 17 Sep 2026 14:11:28 +0200 Subject: [PATCH 0277/1309] Merge commit 'd81818092783258083cd7be22e3a92a4f432a545' into clippy-subtree-update --- .github/workflows/clippy_mq.yml | 55 +++++++- .github/workflows/clippy_pr.yml | 54 +++++++- Cargo.toml | 6 +- .../development/common_tools_writing_lints.md | 2 +- clippy_config/src/conf.rs | 2 +- clippy_config/src/de.rs | 2 +- clippy_config/src/lib.rs | 1 + clippy_config/src/types.rs | 3 +- clippy_lints/src/approx_const.rs | 2 +- .../src/arbitrary_source_item_ordering.rs | 2 +- clippy_lints/src/assert_is_empty.rs | 2 +- clippy_lints/src/attrs/inline_always.rs | 4 +- clippy_lints/src/attrs/repr_attributes.rs | 3 +- clippy_lints/src/attrs/utils.rs | 2 +- clippy_lints/src/booleans.rs | 2 +- clippy_lints/src/box_default.rs | 2 +- clippy_lints/src/cloned_ref_to_slice_refs.rs | 2 +- clippy_lints/src/cognitive_complexity.rs | 3 +- clippy_lints/src/collection_is_never_read.rs | 2 +- clippy_lints/src/declared_lints.rs | 4 +- .../src/default_union_representation.rs | 4 +- clippy_lints/src/dereference.rs | 3 +- clippy_lints/src/derivable_impls.rs | 2 +- .../src/doc/doc_suspicious_footnotes.rs | 2 +- clippy_lints/src/doc/mod.rs | 3 +- .../src/doc/suspicious_doc_comments.rs | 3 +- .../src/doc/too_long_first_doc_paragraph.rs | 4 +- clippy_lints/src/drop_forget_ref.rs | 2 +- clippy_lints/src/duration_suboptimal_units.rs | 2 +- clippy_lints/src/eta_reduction.rs | 3 +- clippy_lints/src/exhaustive_items.rs | 3 +- .../floating_point_arithmetic/custom_abs.rs | 9 +- .../src/floating_point_arithmetic/expm1.rs | 6 +- .../floating_point_arithmetic/log_division.rs | 6 +- .../src/floating_point_arithmetic/mod.rs | 30 +++-- .../src/floating_point_arithmetic/mul_add.rs | 9 +- .../src/floating_point_arithmetic/radians.rs | 8 +- clippy_lints/src/format.rs | 74 +++++++---- clippy_lints/src/format_args.rs | 6 +- clippy_lints/src/format_push_string.rs | 2 +- clippy_lints/src/four_forward_slashes.rs | 4 +- clippy_lints/src/from_str_radix_10.rs | 2 +- clippy_lints/src/functions/must_use.rs | 3 +- clippy_lints/src/incompatible_msrv.rs | 4 +- clippy_lints/src/inherent_to_string.rs | 2 +- clippy_lints/src/inline_fn_without_body.rs | 3 +- clippy_lints/src/large_futures.rs | 2 +- clippy_lints/src/legacy_numeric_constants.rs | 2 +- clippy_lints/src/lib.rs | 6 +- clippy_lints/src/lifetimes.rs | 6 +- .../src/loops/char_indices_as_byte_indices.rs | 2 +- clippy_lints/src/loops/empty_loop.rs | 3 +- clippy_lints/src/loops/explicit_iter_loop.rs | 2 +- clippy_lints/src/loops/while_let_loop.rs | 4 +- clippy_lints/src/macro_metavars_in_unsafe.rs | 3 +- clippy_lints/src/macro_use.rs | 3 +- clippy_lints/src/manual_ignore_case_cmp.rs | 2 +- clippy_lints/src/manual_non_exhaustive.rs | 3 +- clippy_lints/src/manual_pop_if.rs | 2 +- clippy_lints/src/manual_retain.rs | 2 +- clippy_lints/src/matches/collapsible_match.rs | 40 ++++-- clippy_lints/src/matches/manual_map.rs | 2 +- clippy_lints/src/matches/manual_ok_err.rs | 2 +- clippy_lints/src/matches/manual_unwrap_or.rs | 2 +- .../src/matches/match_str_case_mismatch.rs | 2 +- clippy_lints/src/matches/mod.rs | 1 + .../src/matches/redundant_pattern_match.rs | 4 +- clippy_lints/src/matches/try_err.rs | 4 +- .../src/methods/bind_instead_of_map.rs | 2 +- .../src/methods/bytes_count_to_len.rs | 2 +- clippy_lints/src/methods/bytes_nth.rs | 2 +- ...se_sensitive_file_extension_comparisons.rs | 2 +- clippy_lints/src/methods/clear_with_drain.rs | 2 +- clippy_lints/src/methods/clone_on_copy.rs | 2 +- clippy_lints/src/methods/expect_fun_call.rs | 2 +- clippy_lints/src/methods/extend_with_drain.rs | 2 +- clippy_lints/src/methods/format_collect.rs | 2 +- .../src/methods/inefficient_to_string.rs | 2 +- clippy_lints/src/methods/is_empty.rs | 3 +- clippy_lints/src/methods/iter_nth_zero.rs | 2 +- clippy_lints/src/methods/manual_clear.rs | 2 +- clippy_lints/src/methods/manual_ok_or.rs | 2 +- clippy_lints/src/methods/manual_str_repeat.rs | 2 +- clippy_lints/src/methods/map_clone.rs | 3 +- .../src/methods/map_unwrap_or_default.rs | 57 ++++++++ clippy_lints/src/methods/mod.rs | 64 ++++++++- clippy_lints/src/methods/needless_as_bytes.rs | 2 +- clippy_lints/src/methods/no_effect_replace.rs | 2 +- .../src/methods/option_map_or_none.rs | 2 +- clippy_lints/src/methods/or_then_unwrap.rs | 2 +- clippy_lints/src/methods/repeat_once.rs | 2 +- .../src/methods/result_map_or_else_none.rs | 2 +- clippy_lints/src/methods/search_is_some.rs | 2 +- .../src/methods/sliced_string_as_bytes.rs | 2 +- clippy_lints/src/methods/str_splitn.rs | 2 +- .../src/methods/string_extend_chars.rs | 2 +- .../src/methods/string_from_utf8_as_bytes.rs | 46 +++++++ .../src/methods/trim_split_white_space.rs | 36 +++++ clippy_lints/src/methods/unnecessary_join.rs | 2 +- .../src/methods/unnecessary_to_owned.rs | 2 +- clippy_lints/src/methods/useless_asref.rs | 2 +- clippy_lints/src/methods/zst_offset.rs | 2 +- clippy_lints/src/missing_doc.rs | 2 +- clippy_lints/src/missing_fields_in_debug.rs | 2 +- clippy_lints/src/missing_inline.rs | 3 +- clippy_lints/src/needless_pass_by_value.rs | 7 +- clippy_lints/src/needless_question_mark.rs | 2 +- clippy_lints/src/new_without_default.rs | 4 +- clippy_lints/src/no_mangle_with_rust_abi.rs | 4 +- clippy_lints/src/non_canonical_impls.rs | 2 +- .../src/non_send_fields_in_send_ty.rs | 2 +- .../src/nonnull_unchecked_on_box_ptr.rs | 2 +- .../integer_division_remainder_used.rs | 5 +- clippy_lints/src/operators/mod.rs | 5 +- clippy_lints/src/option_if_let_else.rs | 2 +- clippy_lints/src/pass_by_ref_or_value.rs | 4 +- clippy_lints/src/pub_underscore_fields.rs | 2 +- clippy_lints/src/question_mark.rs | 2 +- clippy_lints/src/ranges.rs | 2 +- clippy_lints/src/redundant_clone.rs | 2 +- clippy_lints/src/redundant_slicing.rs | 2 +- clippy_lints/src/regex.rs | 4 + clippy_lints/src/replace_box.rs | 2 +- clippy_lints/src/return_self_not_must_use.rs | 3 +- clippy_lints/src/returns/needless_return.rs | 2 +- .../needless_return_with_question_mark.rs | 2 +- clippy_lints/src/same_length_and_capacity.rs | 2 +- clippy_lints/src/std_instead_of_core.rs | 38 +++++- clippy_lints/src/strings.rs | 123 +----------------- clippy_lints/src/strlen_on_c_strings.rs | 2 +- clippy_lints/src/swap.rs | 22 +++- clippy_lints/src/trait_bounds.rs | 2 +- clippy_lints/src/types/owned_cow.rs | 2 +- clippy_lints/src/types/vec_box.rs | 2 +- .../src/unnecessary_owned_empty_strings.rs | 2 +- clippy_lints/src/unnecessary_wraps.rs | 2 +- clippy_lints/src/unused_io_amount.rs | 2 +- clippy_lints/src/useless_conversion.rs | 9 +- clippy_lints/src/useless_vec.rs | 4 +- clippy_lints/src/volatile_composites.rs | 2 +- clippy_lints/src/with_capacity_zero.rs | 2 +- clippy_lints_internal/Cargo.toml | 1 - .../src/almost_standard_lint_formulation.rs | 3 +- clippy_lints_internal/src/lib.rs | 5 +- clippy_lints_internal/src/produce_ice.rs | 41 ------ clippy_utils/README.md | 2 +- clippy_utils/src/ast_utils/mod.rs | 4 +- clippy_utils/src/attrs.rs | 2 +- clippy_utils/src/higher.rs | 2 +- clippy_utils/src/lib.rs | 21 ++- clippy_utils/src/mir/mod.rs | 14 ++ clippy_utils/src/msrvs.rs | 7 +- clippy_utils/src/qualify_min_const_fn.rs | 6 +- clippy_utils/src/res.rs | 2 +- clippy_utils/src/ty/mod.rs | 2 +- declare_clippy_lint/src/lib.rs | 3 +- rust-toolchain.toml | 2 +- tests/compile-test.rs | 98 +++++++------- tests/example_integration_test/Cargo.toml | 9 ++ tests/example_integration_test/clippy.toml | 1 + tests/example_integration_test/src/main.rs | 20 +++ .../tests/unwrap_in_integration.rs | 20 +++ tests/integration.rs | 20 --- .../12145_with_dashes/Cargo.toml | 3 + .../12176_allow_duplicate_crates/Cargo.toml | 3 + .../5041_allow_dev_build/Cargo.toml | 3 + .../multiple_crate_versions/fail/Cargo.toml | 3 + .../multiple_crate_versions/pass/Cargo.toml | 3 + .../wildcard_dependencies/fail/Cargo.toml | 3 + .../wildcard_dependencies/pass/Cargo.toml | 3 + tests/ui-internal/custom_ice_message.rs | 15 --- tests/ui-internal/custom_ice_message.stderr | 26 ---- tests/ui/clippy_all_group.rs | 11 ++ tests/ui/clippy_all_group.stderr | 15 +++ tests/ui/collapsible_match.rs | 28 ++++ tests/ui/custom_ice_message.rs | 13 ++ tests/ui/custom_ice_message.stderr | 24 ++++ tests/ui/floating_point_abs.fixed | 8 +- tests/ui/floating_point_abs.rs | 8 +- tests/ui/floating_point_abs.stderr | 24 ++-- tests/ui/floating_point_mul_add.fixed | 15 ++- tests/ui/floating_point_mul_add.rs | 15 ++- tests/ui/floating_point_mul_add.stderr | 90 +++++++------ tests/ui/floating_point_rad.fixed | 11 +- tests/ui/floating_point_rad.rs | 11 +- tests/ui/floating_point_rad.stderr | 30 +++-- tests/ui/format.fixed | 18 +++ tests/ui/format.rs | 18 +++ tests/ui/format.stderr | 76 ++++++++++- tests/ui/integer_division_remainder_used.rs | 15 +++ .../ui/integer_division_remainder_used.stderr | 35 +++-- tests/ui/map_clone.fixed | 8 ++ tests/ui/map_clone.rs | 8 ++ tests/ui/map_clone.stderr | 18 +-- tests/ui/map_unwrap_or_fixable.fixed | 44 +++++++ tests/ui/map_unwrap_or_fixable.rs | 44 +++++++ tests/ui/map_unwrap_or_fixable.stderr | 74 ++++++++++- tests/ui/needless_pass_by_value.rs | 2 + tests/ui/regex.rs | 108 ++++++++++++++- tests/ui/regex.stderr | 86 +++++++++++- tests/ui/std_instead_of_core.fixed | 14 ++ tests/ui/std_instead_of_core.rs | 14 ++ tests/ui/std_instead_of_core.stderr | 14 +- tests/ui/swap.fixed | 11 +- tests/ui/swap.rs | 14 +- tests/ui/swap.stderr | 15 ++- tests/ui/useless_conversion.fixed | 40 ++++++ tests/ui/useless_conversion.rs | 40 ++++++ triagebot.toml | 3 +- 209 files changed, 1750 insertions(+), 622 deletions(-) create mode 100644 clippy_lints/src/methods/map_unwrap_or_default.rs create mode 100644 clippy_lints/src/methods/string_from_utf8_as_bytes.rs create mode 100644 clippy_lints/src/methods/trim_split_white_space.rs delete mode 100644 clippy_lints_internal/src/produce_ice.rs create mode 100644 tests/example_integration_test/Cargo.toml create mode 100644 tests/example_integration_test/clippy.toml create mode 100644 tests/example_integration_test/src/main.rs create mode 100644 tests/example_integration_test/tests/unwrap_in_integration.rs delete mode 100644 tests/ui-internal/custom_ice_message.rs delete mode 100644 tests/ui-internal/custom_ice_message.stderr create mode 100644 tests/ui/clippy_all_group.rs create mode 100644 tests/ui/clippy_all_group.stderr create mode 100644 tests/ui/custom_ice_message.rs create mode 100644 tests/ui/custom_ice_message.stderr diff --git a/.github/workflows/clippy_mq.yml b/.github/workflows/clippy_mq.yml index 6cb267ec0007c..ca69483764a49 100644 --- a/.github/workflows/clippy_mq.yml +++ b/.github/workflows/clippy_mq.yml @@ -147,7 +147,6 @@ jobs: max-parallel: 6 matrix: integration: - - 'matthiaskrgr/clippy_ci_panic_test' - 'rust-lang/cargo' - 'rust-lang/chalk' - 'rust-lang/rustfmt' @@ -195,8 +194,60 @@ jobs: env: INTEGRATION: ${{ matrix.integration }} + doc: + # NOTE: If you modify this job, make sure you copy the changes to clippy_pr.yml + runs-on: ubuntu-latest + + env: + RUSTDOCFLAGS: "-D rustdoc::broken-intra-doc-links" + + steps: + # Setup + - name: Checkout + uses: actions/checkout@v7 + with: + # Unsetting this would make so that any malicious package could get our Github Token + persist-credentials: false + + - name: Install toolchain + run: | + # Use a way compatible with Rustup pre-1.28.0 and Rustup 1.28.0 + rustup show active-toolchain || rustup toolchain install + + # Run + - name: Rustdoc top-level + run: cargo doc --no-deps + + - name: Rustdoc clippy_config + run: cargo doc --no-deps + working-directory: clippy_config + + - name: Rustdoc clippy_dev + run: cargo doc --no-deps + working-directory: clippy_dev + + - name: Rustdoc clippy_lints + run: cargo doc --no-deps + working-directory: clippy_lints + + - name: Rustdoc clippy_lints_internal + run: cargo doc --no-deps + working-directory: clippy_lints_internal + + - name: Rustdoc clippy_utils + run: cargo doc --no-deps + working-directory: clippy_utils + + - name: Rustdoc declare_clippy_lint + run: cargo doc --no-deps + working-directory: declare_clippy_lint + + - name: Rustdoc lintcheck + run: cargo doc --no-deps + working-directory: lintcheck + conclusion: - needs: [ base, metadata_collection, integration_build, integration ] + needs: [ base, metadata_collection, integration_build, integration, doc ] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run diff --git a/.github/workflows/clippy_pr.yml b/.github/workflows/clippy_pr.yml index ff1d0f2877b5e..fceafd617e0b5 100644 --- a/.github/workflows/clippy_pr.yml +++ b/.github/workflows/clippy_pr.yml @@ -62,10 +62,62 @@ jobs: env: OS: ${{ runner.os }} + doc: + # NOTE: If you modify this job, make sure you copy the changes to clippy_mq.yml + runs-on: ubuntu-latest + + env: + RUSTDOCFLAGS: "-D rustdoc::broken-intra-doc-links" + + steps: + # Setup + - name: Checkout + uses: actions/checkout@v7 + with: + # Unsetting this would make so that any malicious package could get our Github Token + persist-credentials: false + + - name: Install toolchain + run: | + # Use a way compatible with Rustup pre-1.28.0 and Rustup 1.28.0 + rustup show active-toolchain || rustup toolchain install + + # Run + - name: Rustdoc top-level + run: cargo doc --no-deps + + - name: Rustdoc clippy_config + run: cargo doc --no-deps + working-directory: clippy_config + + - name: Rustdoc clippy_dev + run: cargo doc --no-deps + working-directory: clippy_dev + + - name: Rustdoc clippy_lints + run: cargo doc --no-deps + working-directory: clippy_lints + + - name: Rustdoc clippy_lints_internal + run: cargo doc --no-deps + working-directory: clippy_lints_internal + + - name: Rustdoc clippy_utils + run: cargo doc --no-deps + working-directory: clippy_utils + + - name: Rustdoc declare_clippy_lint + run: cargo doc --no-deps + working-directory: declare_clippy_lint + + - name: Rustdoc lintcheck + run: cargo doc --no-deps + working-directory: lintcheck + # We need to have the "conclusion" job also on PR CI, to make it possible # to add PRs to a merge queue. conclusion: - needs: [ base ] + needs: [ base, doc ] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run diff --git a/Cargo.toml b/Cargo.toml index 1dee95965ebd1..bcf2174ee35ab 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -26,7 +26,6 @@ clippy_utils = { path = "clippy_utils" } declare_clippy_lint = { path = "declare_clippy_lint" } rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } clippy_lints_internal = { path = "clippy_lints_internal", optional = true } -tempfile = { version = "3.20", optional = true } color-print = "0.3.4" anstream = "0.6.18" @@ -40,6 +39,7 @@ walkdir = "2.3" itertools = "0.15" pulldown-cmark = { version = "0.11", default-features = false, features = ["html"] } askama = { version = "0.16.1", default-features = false, features = ["alloc", "config", "derive"] } +tempfile = "3.20" [dev-dependencies.toml] version = "1.1" @@ -51,8 +51,8 @@ features = ["parse", "preserve_order"] rustc_tools_util = { path = "rustc_tools_util", version = "0.4.2" } [features] -integration = ["dep:tempfile"] -internal = ["dep:clippy_lints_internal", "dep:tempfile"] +integration = [] +internal = ["dep:clippy_lints_internal"] [package.metadata.rust-analyzer] # This package uses #[feature(rustc_private)] diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index b5958f802e384..1b02e3ced6b76 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -87,7 +87,7 @@ arguments have to be checked separately. ```rust use clippy_utils::{paths, sym}; use clippy_utils::res::MaybeDef; -use rustc_hir::LangItem; +use rustc_attr_ir::lang_items::LangItem; impl LateLintPass<'_> for MyStructLint { fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) { diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index 7b2a7e0010f76..d547eb294f6aa 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -5,10 +5,10 @@ use crate::types::{ PubUnderscoreFieldsBehaviour, Rename, SourceItemOrdering, SourceItemOrderingModuleItemGroupings, SourceItemOrderingTraitAssocItemKinds, SourceItemOrderingWithinModuleItemGroupings, TraitImplItemOrder, }; +use rustc_attr_ir::RustcVersion; use rustc_attr_parsing::parse_version; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::attrs::RustcVersion; use rustc_session::Session; use rustc_span::{Pos as _, SourceFile, Symbol}; use std::path::PathBuf; diff --git a/clippy_config/src/de.rs b/clippy_config/src/de.rs index 803e34aefe91d..fb335f27aeed6 100644 --- a/clippy_config/src/de.rs +++ b/clippy_config/src/de.rs @@ -1,9 +1,9 @@ use arrayvec::ArrayVec; use core::str::FromStr as _; use itertools::Itertools as _; +use rustc_attr_ir::RustcVersion; use rustc_attr_parsing::parse_version; use rustc_errors::{DiagCtxtHandle, DiagMessage}; -use rustc_hir::attrs::RustcVersion; use rustc_session::Session; use rustc_session::config::ErrorOutputType; use rustc_span::edit_distance::edit_distance; diff --git a/clippy_config/src/lib.rs b/clippy_config/src/lib.rs index 997262630ea05..fdf9967d771e0 100644 --- a/clippy_config/src/lib.rs +++ b/clippy_config/src/lib.rs @@ -8,6 +8,7 @@ )] #![expect(clippy::must_use_candidate)] +extern crate rustc_attr_ir; extern crate rustc_attr_parsing; extern crate rustc_data_structures; extern crate rustc_errors; diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index fd602e4ca5b25..53df7f4e2581b 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -841,8 +841,7 @@ impl SourceItemOrderingWithinModuleItemGroupings { .map(|(x, _)| &**x) .collect::>(); let suggestion = find_closest_match(&grouping.node, &names) - .map(|s| format!(" perhaps you meant `{s}`?")) - .unwrap_or_default(); + .map_or_default(|s| format!(" perhaps you meant `{s}`?")); let names = names.iter().map(|s| format!("`{s}`")).join(", "); sess.dcx().span_err(grouping.span, format!( "unknown ordering group: `{}` was not specified in `module-items-ordered-within-groupings`,{suggestion} expected one of: {names}", diff --git a/clippy_lints/src/approx_const.rs b/clippy_lints/src/approx_const.rs index ee211d56ccca2..e4d1fc6d769cb 100644 --- a/clippy_lints/src/approx_const.rs +++ b/clippy_lints/src/approx_const.rs @@ -2,7 +2,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::msrvs::{self, Msrv}; use rustc_ast::ast::{FloatTy, LitFloatType, LitKind}; -use rustc_hir::attrs::RustcVersion; +use rustc_attr_ir::RustcVersion; use rustc_hir::{HirId, Lit}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::{Span, symbol}; diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index ca81a3c50e862..8984184269421 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -6,7 +6,7 @@ use clippy_config::types::{ }; use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_cfg_test; -use rustc_hir::attrs::AttributeKind; +use rustc_attr_ir::AttributeKind; use rustc_hir::{ Attribute, FieldDef, HirId, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, VariantData, diff --git a/clippy_lints/src/assert_is_empty.rs b/clippy_lints/src/assert_is_empty.rs index 5a00d9149c917..677a7d08c562d 100644 --- a/clippy_lints/src/assert_is_empty.rs +++ b/clippy_lints/src/assert_is_empty.rs @@ -5,8 +5,8 @@ use clippy_utils::source::walk_span_to_context; use clippy_utils::sugg::Sugg; use clippy_utils::sym; use clippy_utils::ty::implements_trait; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/attrs/inline_always.rs b/clippy_lints/src/attrs/inline_always.rs index 7ba7f803d2229..fd03ec47da543 100644 --- a/clippy_lints/src/attrs/inline_always.rs +++ b/clippy_lints/src/attrs/inline_always.rs @@ -1,8 +1,8 @@ use super::INLINE_ALWAYS; use super::utils::is_relevant_expr; use clippy_utils::diagnostics::span_lint; -use rustc_hir::attrs::InlineAttr; -use rustc_hir::{Attribute, BodyId, find_attr}; +use rustc_attr_ir::{Attribute, InlineAttr, find_attr}; +use rustc_hir::BodyId; use rustc_lint::LateContext; use rustc_span::Span; use rustc_span::symbol::Symbol; diff --git a/clippy_lints/src/attrs/repr_attributes.rs b/clippy_lints/src/attrs/repr_attributes.rs index 2a3e4b96b1cd9..dbec48141e12e 100644 --- a/clippy_lints/src/attrs/repr_attributes.rs +++ b/clippy_lints/src/attrs/repr_attributes.rs @@ -1,5 +1,4 @@ -use rustc_hir::attrs::ReprAttr; -use rustc_hir::{Attribute, find_attr}; +use rustc_attr_ir::{Attribute, ReprAttr, find_attr}; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/attrs/utils.rs b/clippy_lints/src/attrs/utils.rs index 9e56e019229ec..8305754028f10 100644 --- a/clippy_lints/src/attrs/utils.rs +++ b/clippy_lints/src/attrs/utils.rs @@ -53,7 +53,7 @@ pub(super) fn extract_clippy_lint(lint: &MetaItemInner) -> Option { /// Returns the lint namespace, if any, as well as the lint name. (`None`, `None`) means /// the lint had less than 1 or more than 2 segments. pub(super) fn namespace_and_lint(lint: &MetaItemInner) -> (Option, Option) { - match lint.meta_item().map(|m| m.path.segments.as_slice()).unwrap_or_default() { + match lint.meta_item().map_or_default(|m| m.path.segments.as_slice()) { [name] => (None, Some(name.ident.name)), [namespace, name] => (Some(namespace.ident.name), Some(name.ident.name)), _ => (None, None), diff --git a/clippy_lints/src/booleans.rs b/clippy_lints/src/booleans.rs index 0cd97fddc74df..b2c21377a0a3f 100644 --- a/clippy_lints/src/booleans.rs +++ b/clippy_lints/src/booleans.rs @@ -8,8 +8,8 @@ use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; use clippy_utils::{eq_expr_value, sym}; use rustc_ast::ast::LitKind; +use rustc_attr_ir::RustcVersion; use rustc_errors::Applicability; -use rustc_hir::attrs::RustcVersion; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; use rustc_hir::{BinOpKind, Body, Expr, ExprKind, FnDecl, UnOp}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/box_default.rs b/clippy_lints/src/box_default.rs index 5b32b3860ea19..ea3ab595d8b7f 100644 --- a/clippy_lints/src/box_default.rs +++ b/clippy_lints/src/box_default.rs @@ -3,8 +3,8 @@ use clippy_utils::macros::macro_backtrace; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::ty::expr_sig; use clippy_utils::{is_default_equivalent, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::intravisit::{InferKind, Visitor, walk_ty}; use rustc_hir::{AmbigArg, Block, Expr, ExprKind, HirId, LetStmt, Node, QPath, Ty, TyKind}; diff --git a/clippy_lints/src/cloned_ref_to_slice_refs.rs b/clippy_lints/src/cloned_ref_to_slice_refs.rs index db53ef9b18536..830cb96b8554c 100644 --- a/clippy_lints/src/cloned_ref_to_slice_refs.rs +++ b/clippy_lints/src/cloned_ref_to_slice_refs.rs @@ -8,8 +8,8 @@ use clippy_utils::sugg::Sugg; use clippy_utils::visitors::is_const_evaluatable; use clippy_utils::{is_in_const_context, is_mutable, sym}; use rustc_ast::Mutability; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; diff --git a/clippy_lints/src/cognitive_complexity.rs b/clippy_lints/src/cognitive_complexity.rs index 080ffad6210a6..a28e9d58f2caf 100644 --- a/clippy_lints/src/cognitive_complexity.rs +++ b/clippy_lints/src/cognitive_complexity.rs @@ -5,8 +5,9 @@ use clippy_utils::source::{IntoSpan as _, SpanExt as _}; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{LimitStack, get_async_fn_body, sym}; use core::ops::ControlFlow; +use rustc_attr_ir::Attribute; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Attribute, Body, Expr, ExprKind, FnDecl}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; diff --git a/clippy_lints/src/collection_is_never_read.rs b/clippy_lints/src/collection_is_never_read.rs index 621c903fbcb32..099100bf9d1f6 100644 --- a/clippy_lints/src/collection_is_never_read.rs +++ b/clippy_lints/src/collection_is_never_read.rs @@ -3,7 +3,7 @@ use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::visitors::{Visitable, for_each_expr}; use clippy_utils::{get_enclosing_block, sym}; use core::ops::ControlFlow; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{Body, ExprKind, HirId, LetStmt, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 2258ae7659285..5a143cca874b5 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -489,6 +489,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::STABLE_SORT_PRIMITIVE_INFO, crate::methods::STR_SPLIT_AT_NEWLINE_INFO, crate::methods::STRING_EXTEND_CHARS_INFO, + crate::methods::STRING_FROM_UTF8_AS_BYTES_INFO, crate::methods::STRING_LIT_CHARS_ANY_INFO, crate::methods::SUSPICIOUS_COMMAND_ARG_SPACE_INFO, crate::methods::SUSPICIOUS_MAP_INFO, @@ -496,6 +497,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::SUSPICIOUS_SPLITN_INFO, crate::methods::SUSPICIOUS_TO_OWNED_INFO, crate::methods::SWAP_WITH_TEMPORARY_INFO, + crate::methods::TRIM_SPLIT_WHITESPACE_INFO, crate::methods::TYPE_ID_ON_BOX_INFO, crate::methods::UNBUFFERED_BYTES_INFO, crate::methods::UNINIT_ASSUMED_INIT_INFO, @@ -724,10 +726,8 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::strings::STR_TO_STRING_INFO, crate::strings::STRING_ADD_INFO, crate::strings::STRING_ADD_ASSIGN_INFO, - crate::strings::STRING_FROM_UTF8_AS_BYTES_INFO, crate::strings::STRING_LIT_AS_BYTES_INFO, crate::strings::STRING_SLICE_INFO, - crate::strings::TRIM_SPLIT_WHITESPACE_INFO, crate::strlen_on_c_strings::STRLEN_ON_C_STRINGS_INFO, crate::suspicious_operation_groupings::SUSPICIOUS_OPERATION_GROUPINGS_INFO, crate::suspicious_trait_impl::SUSPICIOUS_ARITHMETIC_IMPL_INFO, diff --git a/clippy_lints/src/default_union_representation.rs b/clippy_lints/src/default_union_representation.rs index e0d782a0d574d..829783c39b298 100644 --- a/clippy_lints/src/default_union_representation.rs +++ b/clippy_lints/src/default_union_representation.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_then; -use rustc_hir::attrs::ReprAttr; -use rustc_hir::{HirId, Item, ItemKind, find_attr}; +use rustc_attr_ir::{ReprAttr, find_attr}; +use rustc_hir::{HirId, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, FieldDef}; diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 3e2227329e5eb..50017eec7cf65 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -380,8 +380,7 @@ impl<'tcx> LateLintPass<'tcx> for Dereferencing<'tcx> { && let Some(trait_id) = cx.tcx.trait_of_assoc(fn_id) && let arg_ty = cx.tcx.erase_and_anonymize_regions(adjusted_ty) && let ty::Ref(_, sub_ty, _) = *arg_ty.kind() - && let args = - typeck.node_args_opt(hir_id).map(|args| &args[1..]).unwrap_or_default() + && let args = typeck.node_args_opt(hir_id).map_or_default(|args| &args[1..]) && let impl_ty = if cx .tcx .fn_sig(fn_id) diff --git a/clippy_lints/src/derivable_impls.rs b/clippy_lints/src/derivable_impls.rs index d6bf5b9834b8e..76bdf41037734 100644 --- a/clippy_lints/src/derivable_impls.rs +++ b/clippy_lints/src/derivable_impls.rs @@ -104,7 +104,7 @@ fn check_struct<'tcx>( if let TyKind::Path(QPath::Resolved(_, p)) = self_ty.kind && let Some(PathSegment { args, .. }) = p.segments.last() { - let args = args.map(|a| a.args).unwrap_or_default(); + let args = args.map_or_default(|a| a.args); // ty_args contains the generic parameters of the type declaration, while args contains the // arguments used at instantiation time. If both len are not equal, it means that some diff --git a/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/clippy_lints/src/doc/doc_suspicious_footnotes.rs index 39e53dbedb580..6c117ad2a4df8 100644 --- a/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::attr::AttributeExt as _; use rustc_ast::token::{CommentKind, DocFragmentKind}; +use rustc_attr_ir::AttributeKind; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; use rustc_hir::{AttrStyle, Attribute}; use rustc_lint::{LateContext, LintContext as _}; diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 4b81c73582e22..8d2eb01e8743f 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -2,9 +2,10 @@ use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; use clippy_utils::{is_entrypoint_fn, is_trait_impl_item}; +use rustc_attr_ir::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{Attribute, FieldDef, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; +use rustc_hir::{FieldDef, ImplItemKind, ItemKind, Node, Safety, TraitItemKind}; use rustc_lint::{EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_resolve::rustdoc::pulldown_cmark::Event::{ Code, DisplayMath, End, FootnoteReference, HardBreak, Html, InlineHtml, InlineMath, Rule, SoftBreak, Start, diff --git a/clippy_lints/src/doc/suspicious_doc_comments.rs b/clippy_lints/src/doc/suspicious_doc_comments.rs index 178d688264b78..ffa38fbe0a018 100644 --- a/clippy_lints/src/doc/suspicious_doc_comments.rs +++ b/clippy_lints/src/doc/suspicious_doc_comments.rs @@ -1,9 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::AttrStyle; use rustc_ast::token::{CommentKind, DocFragmentKind}; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::Attribute; -use rustc_hir::attrs::AttributeKind; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs index 0bafd63732a56..5333379de7e37 100644 --- a/clippy_lints/src/doc/too_long_first_doc_paragraph.rs +++ b/clippy_lints/src/doc/too_long_first_doc_paragraph.rs @@ -1,6 +1,6 @@ +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::{Attribute, Item, ItemKind}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::LateContext; use clippy_utils::diagnostics::span_lint_and_then; diff --git a/clippy_lints/src/drop_forget_ref.rs b/clippy_lints/src/drop_forget_ref.rs index 5661c31f5a796..3f341daf4d822 100644 --- a/clippy_lints/src/drop_forget_ref.rs +++ b/clippy_lints/src/drop_forget_ref.rs @@ -2,7 +2,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::is_must_use_func_call; use clippy_utils::res::MaybeDef as _; use clippy_utils::ty::{is_copy, opt_must_use_path}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{Arm, Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::sym; diff --git a/clippy_lints/src/duration_suboptimal_units.rs b/clippy_lints/src/duration_suboptimal_units.rs index 35a4dca72b4c4..50d02deae6443 100644 --- a/clippy_lints/src/duration_suboptimal_units.rs +++ b/clippy_lints/src/duration_suboptimal_units.rs @@ -6,8 +6,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef as _; use clippy_utils::sym; +use rustc_attr_ir::RustcVersion; use rustc_errors::Applicability; -use rustc_hir::attrs::RustcVersion; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::{self, TyCtxt, UintTy}; diff --git a/clippy_lints/src/eta_reduction.rs b/clippy_lints/src/eta_reduction.rs index 138ed437bd80a..e3674fcf0d0b6 100644 --- a/clippy_lints/src/eta_reduction.rs +++ b/clippy_lints/src/eta_reduction.rs @@ -4,8 +4,9 @@ use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::{snippet_opt, snippet_with_applicability}; use clippy_utils::usage::{local_used_after_expr, local_used_in}; use clippy_utils::{get_path_from_caller_to_method_type, is_adjusted, is_no_std_crate}; +use rustc_attr_ir::find_attr; use rustc_errors::Applicability; -use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind, find_attr}; +use rustc_hir::{BindingMode, Expr, ExprKind, FnRetTy, GenericArgs, Param, PatKind, QPath, Safety, TyKind}; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; diff --git a/clippy_lints/src/exhaustive_items.rs b/clippy_lints/src/exhaustive_items.rs index 839375a012178..2159f8fe9404b 100644 --- a/clippy_lints/src/exhaustive_items.rs +++ b/clippy_lints/src/exhaustive_items.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::indent_of; +use rustc_attr_ir::find_attr; use rustc_errors::Applicability; -use rustc_hir::{Item, ItemKind, find_attr}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; declare_clippy_lint! { diff --git a/clippy_lints/src/floating_point_arithmetic/custom_abs.rs b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs index feff92fbf8762..2aa7485b36b1f 100644 --- a/clippy_lints/src/floating_point_arithmetic/custom_abs.rs +++ b/clippy_lints/src/floating_point_arithmetic/custom_abs.rs @@ -1,8 +1,9 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::consts::Constant::{F32, F64, Int}; use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; -use clippy_utils::{eq_expr_value, higher, peel_blocks}; +use clippy_utils::{eq_expr_value, higher, is_in_const_context, peel_blocks}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, UnOp}; use rustc_lint::LateContext; @@ -84,7 +85,11 @@ fn are_negated<'a>( None } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { + if is_in_const_context(cx) && !msrv.meets(cx, msrvs::ABS_CONST) { + return; + } + if let Some(higher::If { cond, then, diff --git a/clippy_lints/src/floating_point_arithmetic/expm1.rs b/clippy_lints/src/floating_point_arithmetic/expm1.rs index bf376a51fec93..977273c5de89f 100644 --- a/clippy_lints/src/floating_point_arithmetic/expm1.rs +++ b/clippy_lints/src/floating_point_arithmetic/expm1.rs @@ -2,7 +2,7 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::consts::Constant::{F32, F64}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::Sugg; -use clippy_utils::sym; +use clippy_utils::{is_in_const_context, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; use rustc_lint::LateContext; @@ -13,6 +13,10 @@ use super::IMPRECISE_FLOPS; // TODO: Lint expressions of the form `x.exp() - y` where y > 1 // and suggest usage of `x.exp_m1() - (y - 1)` instead pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if is_in_const_context(cx) { + return; + } + if let ExprKind::Binary( Spanned { node: BinOpKind::Sub, .. diff --git a/clippy_lints/src/floating_point_arithmetic/log_division.rs b/clippy_lints/src/floating_point_arithmetic/log_division.rs index ad0038a4c2423..3553032883140 100644 --- a/clippy_lints/src/floating_point_arithmetic/log_division.rs +++ b/clippy_lints/src/floating_point_arithmetic/log_division.rs @@ -1,6 +1,6 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::sugg::Sugg; -use clippy_utils::{eq_expr_value, sym}; +use clippy_utils::{eq_expr_value, is_in_const_context, sym}; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; use rustc_lint::LateContext; @@ -22,6 +22,10 @@ fn are_same_base_logs(cx: &LateContext<'_>, ctxt: SyntaxContext, expr_a: &Expr<' } pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { + if is_in_const_context(cx) { + return; + } + // check if expression of the form x.logN() / y.logN() if let ExprKind::Binary( Spanned { diff --git a/clippy_lints/src/floating_point_arithmetic/mod.rs b/clippy_lints/src/floating_point_arithmetic/mod.rs index 7ab901837bd02..d005d712cf1df 100644 --- a/clippy_lints/src/floating_point_arithmetic/mod.rs +++ b/clippy_lints/src/floating_point_arithmetic/mod.rs @@ -1,7 +1,9 @@ +use clippy_config::Conf; +use clippy_utils::msrvs::Msrv; use clippy_utils::res::{MaybeDef as _, MaybeTypeckRes as _}; use clippy_utils::{is_in_const_context, is_no_std_crate, sym}; use rustc_hir::{Expr, ExprKind}; -use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; +use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; mod custom_abs; mod expm1; @@ -102,16 +104,24 @@ declare_clippy_lint! { "usage of sub-optimal floating point operations" } -declare_lint_pass!(FloatingPointArithmetic => [IMPRECISE_FLOPS, SUBOPTIMAL_FLOPS]); +impl_lint_pass!(FloatingPointArithmetic => [IMPRECISE_FLOPS, SUBOPTIMAL_FLOPS]); + +pub struct FloatingPointArithmetic { + msrv: Msrv, +} + +impl FloatingPointArithmetic { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv.into() } + } +} impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { - // All of these operations are currently not const and are in std. - if is_in_const_context(cx) { - return; - } - if let ExprKind::MethodCall(path, receiver, args, _) = expr.kind { + if is_in_const_context(cx) { + return; // sqrt, powi, powf, ln, log: still not const + } let recv_ty = cx.typeck_results().expr_ty(receiver); if recv_ty.is_floating_point() && !is_no_std_crate(cx) && cx.ty_based_def(expr).opt_parent(cx).is_impl(cx) { @@ -127,11 +137,11 @@ impl<'tcx> LateLintPass<'tcx> for FloatingPointArithmetic { } else { if !is_no_std_crate(cx) { expm1::check(cx, expr); - mul_add::check(cx, expr); - custom_abs::check(cx, expr); log_division::check(cx, expr); + mul_add::check(cx, expr, self.msrv); + custom_abs::check(cx, expr, self.msrv); } - radians::check(cx, expr); + radians::check(cx, expr, self.msrv); } } } diff --git a/clippy_lints/src/floating_point_arithmetic/mul_add.rs b/clippy_lints/src/floating_point_arithmetic/mul_add.rs index f5c3608696d5b..8a1f91e8f3623 100644 --- a/clippy_lints/src/floating_point_arithmetic/mul_add.rs +++ b/clippy_lints/src/floating_point_arithmetic/mul_add.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::expr_type_is_certain; -use clippy_utils::{get_parent_expr, sym}; +use clippy_utils::{get_parent_expr, is_in_const_context, sym}; use rustc_ast::AssignOpKind; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind, PathSegment}; @@ -28,7 +29,11 @@ fn is_float_mul_expr<'a>(cx: &LateContext<'_>, expr: &'a Expr<'a>) -> Option<(&' None } -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { + if is_in_const_context(cx) && !msrv.meets(cx, msrvs::MUL_ADD_CONST) { + return; + } + let (is_assign, op, lhs, rhs) = match &expr.kind { ExprKind::AssignOp( Spanned { diff --git a/clippy_lints/src/floating_point_arithmetic/radians.rs b/clippy_lints/src/floating_point_arithmetic/radians.rs index 8480626133fdd..80ddb265e6d5c 100644 --- a/clippy_lints/src/floating_point_arithmetic/radians.rs +++ b/clippy_lints/src/floating_point_arithmetic/radians.rs @@ -1,7 +1,9 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::consts::Constant::{F32, F64}; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::Msrv; use clippy_utils::sugg::Sugg; +use clippy_utils::{is_in_const_context, msrvs}; use rustc_ast::ast; use rustc_errors::Applicability; use rustc_hir::{BinOpKind, Expr, ExprKind}; @@ -12,7 +14,11 @@ use std::f64::consts as f64_consts; use super::SUBOPTIMAL_FLOPS; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>) { +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, msrv: Msrv) { + if is_in_const_context(cx) && !msrv.meets(cx, msrvs::RADIANS_CONST) { + return; + } + if let ExprKind::Binary( Spanned { node: BinOpKind::Div, .. diff --git a/clippy_lints/src/format.rs b/clippy_lints/src/format.rs index f8e4a779da6f1..be48dd3695ca4 100644 --- a/clippy_lints/src/format.rs +++ b/clippy_lints/src/format.rs @@ -1,10 +1,11 @@ use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::get_parent_expr; use clippy_utils::macros::{FormatArgsStorage, find_format_arg_expr, first_node_in_macro, matching_root_macro_call}; use clippy_utils::source::{SpanExt as _, snippet_with_context}; use clippy_utils::sugg::Sugg; use rustc_ast::{FormatArgsPiece, FormatOptions, FormatTrait}; use rustc_errors::Applicability; -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_span::{Span, sym}; @@ -68,15 +69,29 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { let call_site = macro_call.span; match (format_args.arguments.all_args(), &format_args.template[..]) { - ([], []) => span_useless_format_empty(cx, call_site, "String::new()".to_owned(), applicability), + ([], []) => span_lint( + cx, + call_site, + "`String::new()`", + "String::new()".to_owned(), + applicability, + ), ([], [_]) => { // Simulate macro expansion, converting {{ and }} to { and }. let Some(snippet) = format_args.span.get_text(cx) else { return; }; let s_expand = snippet.replace("{{", "{").replace("}}", "}"); - let sugg = format!("{s_expand}.to_string()"); - span_useless_format(cx, call_site, sugg, applicability); + // If the format! is immediately borrowed as `&format!("literal")`, + // suggest using the string literal directly (no `.to_string()` needed). + if let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind + { + span_lint(cx, parent.span, "the string literal directly", s_expand, applicability); + } else { + let sugg = format!("{s_expand}.to_string()"); + span_lint(cx, call_site, "`.to_string()`", sugg, applicability); + } }, ([arg], [piece]) => { if let Some(value) = find_format_arg_expr(expr, arg) @@ -94,15 +109,34 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { ExprKind::MethodCall(path, ..) => path.ident.name == sym::to_string, _ => false, }; - let sugg = if is_new_string { - snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability) - .0 - .into_owned() - } else { + // If the arg is `&str` (not a newly-constructed string) and the format! is + // immediately borrowed as `&format!("{}", lit)`, suggest the arg directly. + // This avoids producing `&lit.to_string()` which `unnecessary_to_owned` would flag. + if !is_new_string + && matches!(cx.typeck_results().expr_ty(value).peel_refs().kind(), ty::Str) + && let Some(parent) = get_parent_expr(cx, expr) + && let ExprKind::AddrOf(BorrowKind::Ref, Mutability::Not, _) = parent.kind + { let sugg = Sugg::hir_with_context(cx, value, call_site.ctxt(), "", &mut applicability); - format!("{}.to_string()", sugg.maybe_paren()) - }; - span_useless_format(cx, call_site, sugg, applicability); + span_lint( + cx, + parent.span, + "the argument directly", + sugg.to_string(), + applicability, + ); + } else { + let sugg = if is_new_string { + snippet_with_context(cx, value.span, call_site.ctxt(), "..", &mut applicability) + .0 + .into_owned() + } else { + let sugg = + Sugg::hir_with_context(cx, value, call_site.ctxt(), "", &mut applicability); + format!("{}.to_string()", sugg.maybe_paren()) + }; + span_lint(cx, call_site, "`.to_string()`", sugg, applicability); + } } }, _ => {}, @@ -111,25 +145,13 @@ impl<'tcx> LateLintPass<'tcx> for UselessFormat { } } -fn span_useless_format_empty(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { - span_lint_and_sugg( - cx, - USELESS_FORMAT, - span, - "useless use of `format!`", - "consider using `String::new()`", - sugg, - applicability, - ); -} - -fn span_useless_format(cx: &LateContext<'_>, span: Span, sugg: String, applicability: Applicability) { +fn span_lint(cx: &LateContext<'_>, span: Span, expl: &str, sugg: String, applicability: Applicability) { span_lint_and_sugg( cx, USELESS_FORMAT, span, "useless use of `format!`", - "consider using `.to_string()`", + format!("consider using {expl}"), sugg, applicability, ); diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index f6f90f5dc36d5..22be9d8367daa 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -19,12 +19,12 @@ use rustc_ast::{ BorrowKind, FormatArgPosition, FormatArgPositionKind, FormatArgsPiece, FormatArgumentKind, FormatCount, FormatOptions, FormatPlaceholder, Mutability, }; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{RustcVersion, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::Applicability; use rustc_errors::SuggestionStyle::{CompletelyHidden, ShowCode}; -use rustc_hir::attrs::RustcVersion; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, find_attr}; +use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::{self, GenericArg, List, TraitRef, Ty, TyCtxt, Unnormalized, Upcast as _}; diff --git a/clippy_lints/src/format_push_string.rs b/clippy_lints/src/format_push_string.rs index 9008e9d0a5cd5..36d4a237d4cd9 100644 --- a/clippy_lints/src/format_push_string.rs +++ b/clippy_lints/src/format_push_string.rs @@ -3,8 +3,8 @@ use clippy_utils::macros::{FormatArgsStorage, format_args_inputs_span, root_macr use clippy_utils::res::MaybeDef as _; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::{std_or_core, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{AssignOpKind, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/four_forward_slashes.rs b/clippy_lints/src/four_forward_slashes.rs index 399405221f503..b90a3506c20bf 100644 --- a/clippy_lints/src/four_forward_slashes.rs +++ b/clippy_lints/src/four_forward_slashes.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::SpanExt as _; use itertools::Itertools as _; use rustc_ast::AttrStyle; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::{Attribute, Item}; +use rustc_hir::Item; use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/from_str_radix_10.rs b/clippy_lints/src/from_str_radix_10.rs index eb0a3564c505b..96d0c555543aa 100644 --- a/clippy_lints/src/from_str_radix_10.rs +++ b/clippy_lints/src/from_str_radix_10.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::sugg::Sugg; use clippy_utils::{is_in_const_context, is_integer_literal, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, PrimTy, QPath, TyKind, def}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty::Ty; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index 95eb581bcacb3..bca9705f6ed59 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,8 +1,9 @@ use hir::FnSig; +use rustc_attr_ir::find_attr; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, Attribute, QPath, find_attr}; +use rustc_hir::{self as hir, Attribute, QPath}; use rustc_lint::unused::must_use::MustUsePath; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index ed90c1871b4d9..a09b3aa0135f8 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -2,9 +2,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::Msrv; use clippy_utils::{is_in_const_context, is_in_test, sym}; +use rustc_attr_ir::{RustcVersion, find_attr}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::attrs::RustcVersion; -use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, StabilityLevel, StableSince, find_attr}; +use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, StabilityLevel, StableSince}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId}; diff --git a/clippy_lints/src/inherent_to_string.rs b/clippy_lints/src/inherent_to_string.rs index 95bc10bc38554..f44e7bc191a5f 100644 --- a/clippy_lints/src/inherent_to_string.rs +++ b/clippy_lints/src/inherent_to_string.rs @@ -3,7 +3,7 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::ty::implements_trait; use clippy_utils::{return_ty, trait_ref_of_method}; use rustc_abi::ExternAbi; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{GenericParamKind, ImplItem, ImplItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::sym; diff --git a/clippy_lints/src/inline_fn_without_body.rs b/clippy_lints/src/inline_fn_without_body.rs index c2e8618a8ff0a..9ae34010f927e 100644 --- a/clippy_lints/src/inline_fn_without_body.rs +++ b/clippy_lints/src/inline_fn_without_body.rs @@ -1,7 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::sugg::DiagExt as _; +use rustc_attr_ir::find_attr; use rustc_errors::Applicability; -use rustc_hir::{TraitFn, TraitItem, TraitItemKind, find_attr}; +use rustc_hir::{TraitFn, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; declare_clippy_lint! { diff --git a/clippy_lints/src/large_futures.rs b/clippy_lints/src/large_futures.rs index a3ced258e2270..0547f273138c5 100644 --- a/clippy_lints/src/large_futures.rs +++ b/clippy_lints/src/large_futures.rs @@ -3,8 +3,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::source::snippet; use clippy_utils::ty::implements_trait; use rustc_abi::Size; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index 7f83149a222c0..4e982e8fb86f3 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -138,7 +138,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { expr.span, "use the associated constant instead", sugg, - Applicability::MaybeIncorrect, + Applicability::MachineApplicable, ); }); } diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1a1055b609dd..435f787f7012f 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -26,6 +26,7 @@ extern crate rustc_abi; extern crate rustc_arena; extern crate rustc_ast; extern crate rustc_ast_pretty; +extern crate rustc_attr_ir; extern crate rustc_data_structures; extern crate rustc_errors; extern crate rustc_hir; @@ -629,7 +630,7 @@ rustc_lint::late_lint_methods!( CopyAndPaste: ifs::CopyAndPaste<'tcx> = ifs::CopyAndPaste::new(tcx, conf), CopyIterator: copy_iterator::CopyIterator = copy_iterator::CopyIterator, UselessFormat: format::UselessFormat = format::UselessFormat::new(format_args.clone()), - Swap: swap::Swap = swap::Swap, + Swap: swap::Swap = swap::Swap::new(conf), PanickingOverflowChecks: panicking_overflow_checks::PanickingOverflowChecks = panicking_overflow_checks::PanickingOverflowChecks, NewWithoutDefault: new_without_default::NewWithoutDefault = ::default(), DisallowedNames: disallowed_names::DisallowedNames = disallowed_names::DisallowedNames::new(conf), @@ -692,7 +693,7 @@ rustc_lint::late_lint_methods!( ToDigitIsSome: to_digit_is_some::ToDigitIsSome = to_digit_is_some::ToDigitIsSome::new(conf), LargeStackArrays: large_stack_arrays::LargeStackArrays = large_stack_arrays::LargeStackArrays::new(conf), LargeConstArrays: large_const_arrays::LargeConstArrays = large_const_arrays::LargeConstArrays::new(conf), - FloatingPointArithmetic: floating_point_arithmetic::FloatingPointArithmetic = floating_point_arithmetic::FloatingPointArithmetic, + FloatingPointArithmetic: floating_point_arithmetic::FloatingPointArithmetic = floating_point_arithmetic::FloatingPointArithmetic::new(conf), AsConversions: as_conversions::AsConversions = as_conversions::AsConversions, LetUnderscore: let_underscore::LetUnderscore = let_underscore::LetUnderscore, ExcessiveBools: excessive_bools::ExcessiveBools = excessive_bools::ExcessiveBools::new(conf), @@ -747,7 +748,6 @@ rustc_lint::late_lint_methods!( UnnecessaryOwnedEmptyStrings: unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings = unnecessary_owned_empty_strings::UnnecessaryOwnedEmptyStrings, FormatPushString: format_push_string::FormatPushString = format_push_string::FormatPushString::new(format_args.clone()), LargeIncludeFile: large_include_file::LargeIncludeFile = large_include_file::LargeIncludeFile::new(conf), - TrimSplitWhitespace: strings::TrimSplitWhitespace = strings::TrimSplitWhitespace, RcCloneInVecInit: rc_clone_in_vec_init::RcCloneInVecInit = rc_clone_in_vec_init::RcCloneInVecInit, SwapPtrToRef: swap_ptr_to_ref::SwapPtrToRef = swap_ptr_to_ref::SwapPtrToRef, TypeParamMismatch: mismatching_type_param_order::TypeParamMismatch = mismatching_type_param_order::TypeParamMismatch, diff --git a/clippy_lints/src/lifetimes.rs b/clippy_lints/src/lifetimes.rs index bd5c380f7bc23..408d78ae623c0 100644 --- a/clippy_lints/src/lifetimes.rs +++ b/clippy_lints/src/lifetimes.rs @@ -4,13 +4,13 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{is_from_proc_macro, trait_ref_of_method}; use itertools::Itertools as _; use rustc_ast::visit::{try_visit, walk_list}; +use rustc_attr_ir::lang_items; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::Applicability; use rustc_hir::FnRetTy::Return; -use rustc_hir::attrs::lang_items; use rustc_hir::intravisit::{ - IgnoreNested, NestedFilter, Visitor, walk_fn_decl, walk_generic_args, walk_generic_param, - walk_generics, walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, + IgnoreNested, NestedFilter, Visitor, walk_fn_decl, walk_generic_args, walk_generic_param, walk_generics, + walk_impl_item_ref, walk_param_bound, walk_poly_trait_ref, walk_trait_ref, walk_ty, walk_unambig_ty, walk_where_predicate, }; use rustc_hir::{ diff --git a/clippy_lints/src/loops/char_indices_as_byte_indices.rs b/clippy_lints/src/loops/char_indices_as_byte_indices.rs index e89d4b139cb12..949d0fa1eeefb 100644 --- a/clippy_lints/src/loops/char_indices_as_byte_indices.rs +++ b/clippy_lints/src/loops/char_indices_as_byte_indices.rs @@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::visitors::for_each_expr; use clippy_utils::{eq_expr_value, higher, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, Node, Pat, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty::Ty; diff --git a/clippy_lints/src/loops/empty_loop.rs b/clippy_lints/src/loops/empty_loop.rs index f2b2b77c34967..803b3ed7cba13 100644 --- a/clippy_lints/src/loops/empty_loop.rs +++ b/clippy_lints/src/loops/empty_loop.rs @@ -2,7 +2,8 @@ use super::EMPTY_LOOP; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{is_in_panic_handler, is_no_std_crate}; -use rustc_hir::{Block, Expr, ItemKind, Node, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{Block, Expr, ItemKind, Node}; use rustc_lint::LateContext; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, loop_block: &Block<'_>) { diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index cc458e54d16e9..ba2a418104a47 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -8,8 +8,8 @@ use clippy_utils::ty::{ implements_trait, implements_trait_with_env, is_copy, make_normalized_projection, make_normalized_projection_with_regions, normalize_with_regions, }; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index e2ea24c399807..53df9a358b0e2 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -110,9 +110,7 @@ fn could_be_while_let<'tcx>( && let Some(pat_str) = snippet_opt(cx, pat.span) && let Some(init_str) = snippet_opt(cx, peel_blocks(inner_expr).span) { - let ty_str = ty - .map(|ty| format!(": {}", snippet(cx, ty.span, "_"))) - .unwrap_or_default(); + let ty_str = ty.map_or_default(|ty| format!(": {}", snippet(cx, ty.span, "_"))); format!( "\n{indent} let {pat_str}{ty_str} = {init_str};\n{indent} ..\n{indent}", indent = snippet_indent(cx, expr.span).unwrap_or_default(), diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index 0c62b4e5897f3..8242c383140a6 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -2,9 +2,10 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::is_lint_allowed; use itertools::Itertools as _; +use rustc_attr_ir::find_attr; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; -use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource, find_attr}; +use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::{Span, SyntaxContext}; use std::collections::BTreeMap; diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index af33d1f7a8aa5..6f06e8665decc 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::snippet; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, AmbigArg, find_attr}; +use rustc_hir::{self as hir, AmbigArg}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Span; use rustc_span::edition::Edition; diff --git a/clippy_lints/src/manual_ignore_case_cmp.rs b/clippy_lints/src/manual_ignore_case_cmp.rs index 2173617bd5aac..46ca983508e02 100644 --- a/clippy_lints/src/manual_ignore_case_cmp.rs +++ b/clippy_lints/src/manual_ignore_case_cmp.rs @@ -4,9 +4,9 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_context; use clippy_utils::sym; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::ExprKind::{Binary, Lit, MethodCall}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BinOpKind, Expr}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty; diff --git a/clippy_lints/src/manual_non_exhaustive.rs b/clippy_lints/src/manual_non_exhaustive.rs index d4f20fa15c69b..1e4f48e558fa9 100644 --- a/clippy_lints/src/manual_non_exhaustive.rs +++ b/clippy_lints/src/manual_non_exhaustive.rs @@ -4,10 +4,11 @@ use clippy_utils::is_doc_hidden; use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::source::snippet_indent; use itertools::Itertools as _; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData, find_attr}; +use rustc_hir::{Expr, ExprKind, Item, ItemKind, QPath, TyKind, VariantData}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; diff --git a/clippy_lints/src/manual_pop_if.rs b/clippy_lints/src/manual_pop_if.rs index 0fb7d0123dd26..afafe25f8ffd0 100644 --- a/clippy_lints/src/manual_pop_if.rs +++ b/clippy_lints/src/manual_pop_if.rs @@ -6,8 +6,8 @@ use clippy_utils::source::snippet_with_context; use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used}; use clippy_utils::{eq_expr_value, is_else_clause, is_lang_item_or_ctor, span_contains_non_whitespace, sym}; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, MultiSpan}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BlockCheckMode, Expr, ExprKind, PatKind, StmtKind, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::TyCtxt; diff --git a/clippy_lints/src/manual_retain.rs b/clippy_lints/src/manual_retain.rs index cf8d8857841e8..d00d91be2fbde 100644 --- a/clippy_lints/src/manual_retain.rs +++ b/clippy_lints/src/manual_retain.rs @@ -4,10 +4,10 @@ use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet; use clippy_utils::{SpanlessEq, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::ExprKind::Assign; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index 6510af5db8541..d210d61648319 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -7,6 +7,7 @@ use clippy_utils::usage::mutated_variables; use clippy_utils::visitors::is_local_used; use clippy_utils::{ SpanlessEq, get_ref_operators, is_none_pattern, is_unit_expr, peel_blocks_with_stmt, peel_ref_operators, + span_contains_non_whitespace, }; use rustc_ast::BorrowKind; use rustc_errors::{Applicability, MultiSpan}; @@ -34,6 +35,7 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ar arm.body, arm.guard, Some(els_arm.body), + arm.hir_id, msrv, only_wildcards_after, ); @@ -41,16 +43,30 @@ pub(super) fn check_match<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, ar } } +#[expect(clippy::too_many_arguments)] pub(super) fn check_if_let<'tcx>( cx: &LateContext<'tcx>, ctxt: SyntaxContext, + expr: &'tcx Expr<'_>, pat: &'tcx Pat<'_>, body: &'tcx Expr<'_>, else_expr: Option<&'tcx Expr<'_>>, let_expr: &'tcx Expr<'_>, msrv: Msrv, ) { - check_arm(cx, ctxt, false, pat, let_expr, body, None, else_expr, msrv, false); + check_arm( + cx, + ctxt, + false, + pat, + let_expr, + body, + None, + else_expr, + expr.hir_id, + msrv, + false, + ); } #[expect(clippy::too_many_arguments, clippy::too_many_lines)] @@ -63,6 +79,7 @@ fn check_arm<'tcx>( outer_then_body: &'tcx Expr<'tcx>, outer_guard: Option<&'tcx Expr<'tcx>>, outer_else_body: Option<&'tcx Expr<'tcx>>, + outer_hir_id: HirId, msrv: Msrv, only_wildcards_after: bool, ) { @@ -151,10 +168,21 @@ fn check_arm<'tcx>( } && !pat_bindings_moved_or_mutated(cx, outer_pat, inner.cond) { + let outer_then_open_bracket = outer_then_body + .span + .split_at(1) + .0 + .with_leading_whitespace(cx) + .into_span(); + let contains_block = matches!(outer_then_body.kind, ExprKind::Block(..)); + if contains_block && span_contains_non_whitespace(cx, outer_then_open_bracket.between(inner_expr.span), false) { + return; + } + span_lint_hir_and_then( cx, COLLAPSIBLE_MATCH, - inner_expr.hir_id, + outer_hir_id, inner_expr.span, "this `if` can be collapsed into the outer `match`", |diag| { @@ -166,13 +194,7 @@ fn check_arm<'tcx>( let (paren_start, inner_if_span, paren_end) = peel_parens(cx, inner_expr.span); let inner_if = inner_if_span.split_at(2).0; let mut sugg = vec![(inner.then.span.shrink_to_lo(), "=> ".to_string())]; - if matches!(outer_then_body.kind, ExprKind::Block(..)) { - let outer_then_open_bracket = outer_then_body - .span - .split_at(1) - .0 - .with_leading_whitespace(cx) - .into_span(); + if contains_block { let outer_then_closing_bracket = { let end = outer_then_body.span.shrink_to_hi(); end.with_lo(end.lo() - BytePos(1)) diff --git a/clippy_lints/src/matches/manual_map.rs b/clippy_lints/src/matches/manual_map.rs index f322b59c9174b..b427c61ece147 100644 --- a/clippy_lints/src/matches/manual_map.rs +++ b/clippy_lints/src/matches/manual_map.rs @@ -3,7 +3,7 @@ use super::manual_utils::{SomeExpr, check_with}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; -use rustc_hir::attrs::lang_items::LangItem::OptionSome; +use rustc_attr_ir::lang_items::LangItem::OptionSome; use rustc_hir::{Arm, Block, BlockCheckMode, Expr, ExprKind, Pat, UnsafeSource}; use rustc_lint::LateContext; use rustc_span::SyntaxContext; diff --git a/clippy_lints/src/matches/manual_ok_err.rs b/clippy_lints/src/matches/manual_ok_err.rs index 7f3782ac7eb82..e85c482f2dd9b 100644 --- a/clippy_lints/src/matches/manual_ok_err.rs +++ b/clippy_lints/src/matches/manual_ok_err.rs @@ -5,8 +5,8 @@ use clippy_utils::sugg::Sugg; use clippy_utils::ty::{option_arg_ty, peel_and_count_ty_refs}; use clippy_utils::{as_some_expr, get_parent_expr, is_none_expr, peel_blocks, span_contains_comment}; use rustc_ast::{BindingMode, Mutability}; +use rustc_attr_ir::lang_items::LangItem::ResultErr; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::ResultErr; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, Expr, ExprKind, Pat, PatExpr, PatExprKind, PatKind, Path, QPath}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/matches/manual_unwrap_or.rs b/clippy_lints/src/matches/manual_unwrap_or.rs index 6a726bf08c06e..fa09ef1e86b20 100644 --- a/clippy_lints/src/matches/manual_unwrap_or.rs +++ b/clippy_lints/src/matches/manual_unwrap_or.rs @@ -2,8 +2,8 @@ use clippy_utils::consts::ConstEvalCtxt; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _, MaybeResPath as _}; use clippy_utils::source::{SpanExt as _, indent_of, reindent_multiline}; use rustc_ast::{BindingMode, ByRef}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::{Arm, Expr, ExprKind, HirId, Pat, PatKind, QPath}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs index e8c8eb7f37a96..93f9c3f14904b 100644 --- a/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -4,8 +4,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::sym; use rustc_ast::ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, PatKind}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/matches/mod.rs b/clippy_lints/src/matches/mod.rs index f1c50b55f9eec..994d4e8937273 100644 --- a/clippy_lints/src/matches/mod.rs +++ b/clippy_lints/src/matches/mod.rs @@ -1152,6 +1152,7 @@ impl<'tcx> LateLintPass<'tcx> for Matches { collapsible_match::check_if_let( cx, if_let.let_span.ctxt(), + expr, if_let.let_pat, if_let.if_then, if_let.if_else, diff --git a/clippy_lints/src/matches/redundant_pattern_match.rs b/clippy_lints/src/matches/redundant_pattern_match.rs index 787e6147d8526..3233e2c5392f8 100644 --- a/clippy_lints/src/matches/redundant_pattern_match.rs +++ b/clippy_lints/src/matches/redundant_pattern_match.rs @@ -6,10 +6,8 @@ use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::{any_temporaries_need_ordered_drop, for_each_expr_without_closures}; use clippy_utils::{get_parent_expr, is_expn_of, sym}; use rustc_ast::ast::LitKind; +use rustc_attr_ir::lang_items::LangItem::{self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk}; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::{ - self, OptionNone, OptionSome, PollPending, PollReady, ResultErr, ResultOk, -}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Arm, BinOpKind, Expr, ExprKind, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, UnOp}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/matches/try_err.rs b/clippy_lints/src/matches/try_err.rs index 4781d65749634..a61b87672e041 100644 --- a/clippy_lints/src/matches/try_err.rs +++ b/clippy_lints/src/matches/try_err.rs @@ -3,9 +3,9 @@ use clippy_utils::get_parent_expr; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::option_arg_ty; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem::ResultErr; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::lang_items::LangItem::ResultErr; use rustc_hir::{Expr, ExprKind, MatchSource}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/methods/bind_instead_of_map.rs b/clippy_lints/src/methods/bind_instead_of_map.rs index 51edbfb8b1a11..d298bb1a11d9e 100644 --- a/clippy_lints/src/methods/bind_instead_of_map.rs +++ b/clippy_lints/src/methods/bind_instead_of_map.rs @@ -3,10 +3,10 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::peel_blocks; use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::visitors::find_all_ret_expressions; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::QPath; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/methods/bytes_count_to_len.rs b/clippy_lints/src/methods/bytes_count_to_len.rs index 2611f94e5f791..1bf34b41a4984 100644 --- a/clippy_lints/src/methods/bytes_count_to_len.rs +++ b/clippy_lints/src/methods/bytes_count_to_len.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use super::BYTES_COUNT_TO_LEN; diff --git a/clippy_lints/src/methods/bytes_nth.rs b/clippy_lints/src/methods/bytes_nth.rs index a98dd315c09ae..06087db7ab5d0 100644 --- a/clippy_lints/src/methods/bytes_nth.rs +++ b/clippy_lints/src/methods/bytes_nth.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sym; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::Expr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use crate::methods::method_call; diff --git a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs index 5f90a68961fb5..228baf6478c65 100644 --- a/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs +++ b/clippy_lints/src/methods/case_sensitive_file_extension_comparisons.rs @@ -4,8 +4,8 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::{SpanExt as _, indent_of, reindent_multiline}; use clippy_utils::sym; use rustc_ast::ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::{Span, Spanned}; diff --git a/clippy_lints/src/methods/clear_with_drain.rs b/clippy_lints/src/methods/clear_with_drain.rs index ab967ba35cb81..2ef1cbbf5d4da 100644 --- a/clippy_lints/src/methods/clear_with_drain.rs +++ b/clippy_lints/src/methods/clear_with_drain.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::{is_full_collection_range, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::Expr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/methods/clone_on_copy.rs b/clippy_lints/src/methods/clone_on_copy.rs index fa0cb77136708..0891ffda6e7c3 100644 --- a/clippy_lints/src/methods/clone_on_copy.rs +++ b/clippy_lints/src/methods/clone_on_copy.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::peel_hir_expr_refs; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::is_copy; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BindingMode, ByRef, Expr, ExprKind, MatchSource, Node, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; diff --git a/clippy_lints/src/methods/expect_fun_call.rs b/clippy_lints/src/methods/expect_fun_call.rs index 3c16464f83953..99bc084ea29db 100644 --- a/clippy_lints/src/methods/expect_fun_call.rs +++ b/clippy_lints/src/methods/expect_fun_call.rs @@ -5,9 +5,9 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::visitors::for_each_expr; use clippy_utils::{contains_return, is_inside_always_const_context, peel_blocks, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::Span; use std::borrow::Cow; diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 074dafae5846e..21e13d7b0d0eb 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sym; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/format_collect.rs b/clippy_lints/src/methods/format_collect.rs index e075f06c08970..112906a7d01e1 100644 --- a/clippy_lints/src/methods/format_collect.rs +++ b/clippy_lints/src/methods/format_collect.rs @@ -2,7 +2,7 @@ use super::FORMAT_COLLECT; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::macros::{is_format_macro, root_macro_call_first_node}; use clippy_utils::res::MaybeDef as _; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/methods/inefficient_to_string.rs b/clippy_lints/src/methods/inefficient_to_string.rs index bd8582ac014cf..24cd49d5c14b0 100644 --- a/clippy_lints/src/methods/inefficient_to_string.rs +++ b/clippy_lints/src/methods/inefficient_to_string.rs @@ -4,9 +4,9 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::sym; use clippy_utils::ty::peel_and_count_ty_refs; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/methods/is_empty.rs b/clippy_lints/src/methods/is_empty.rs index 3475a54f09858..d4fb98f965973 100644 --- a/clippy_lints/src/methods/is_empty.rs +++ b/clippy_lints/src/methods/is_empty.rs @@ -3,7 +3,8 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::macros::{is_assert_macro, root_macro_call}; use clippy_utils::res::MaybeResPath as _; use clippy_utils::{find_binding_init, get_parent_expr, is_inside_always_const_context}; -use rustc_hir::{Expr, HirId, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{Expr, HirId}; use rustc_lint::LateContext; use super::CONST_IS_EMPTY; diff --git a/clippy_lints/src/methods/iter_nth_zero.rs b/clippy_lints/src/methods/iter_nth_zero.rs index 9c0d0a3e90631..8d62be064615e 100644 --- a/clippy_lints/src/methods/iter_nth_zero.rs +++ b/clippy_lints/src/methods/iter_nth_zero.rs @@ -4,9 +4,9 @@ use clippy_utils::is_lang_item_or_ctor; use clippy_utils::res::{MaybeDef as _, MaybeTypeckRes as _}; use clippy_utils::source::snippet_with_applicability; use hir::OwnerNode; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::sym; diff --git a/clippy_lints/src/methods/manual_clear.rs b/clippy_lints/src/methods/manual_clear.rs index c38839582b112..7dd115f7c000f 100644 --- a/clippy_lints/src/methods/manual_clear.rs +++ b/clippy_lints/src/methods/manual_clear.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef as _; use clippy_utils::{is_integer_literal, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::Expr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/methods/manual_ok_or.rs b/clippy_lints/src/methods/manual_ok_or.rs index a3564706e6dcd..5b6506b853b5f 100644 --- a/clippy_lints/src/methods/manual_ok_or.rs +++ b/clippy_lints/src/methods/manual_ok_or.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _, MaybeResPath as _}; use clippy_utils::source::{SpanExt as _, indent_of, reindent_multiline}; +use rustc_attr_ir::lang_items::LangItem::{ResultErr, ResultOk}; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::{ResultErr, ResultOk}; use rustc_hir::{Expr, ExprKind, PatKind}; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/methods/manual_str_repeat.rs b/clippy_lints/src/methods/manual_str_repeat.rs index 80ee741fab35e..2813a048cb553 100644 --- a/clippy_lints/src/methods/manual_str_repeat.rs +++ b/clippy_lints/src/methods/manual_str_repeat.rs @@ -4,8 +4,8 @@ use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::sugg::Sugg; use clippy_utils::sym; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/methods/map_clone.rs b/clippy_lints/src/methods/map_clone.rs index 1ecd63e62dfe0..072f56b897014 100644 --- a/clippy_lints/src/methods/map_clone.rs +++ b/clippy_lints/src/methods/map_clone.rs @@ -4,9 +4,9 @@ use clippy_utils::peel_blocks; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{is_copy, should_call_clone_as_function}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_lint::LateContext; use rustc_middle::mir::{Mutability, Pinnedness}; @@ -90,6 +90,7 @@ pub(super) fn check(cx: &LateContext<'_>, e: &hir::Expr<'_>, recv: &hir::Expr<'_ hir::ExprKind::Call(call, [arg]) => { if let hir::ExprKind::Path(qpath) = call.kind && ident_eq(name, arg) + && cx.typeck_results().expr_ty(arg) == cx.typeck_results().expr_ty_adjusted(arg) { handle_path(cx, call, &qpath, e, recv); } diff --git a/clippy_lints/src/methods/map_unwrap_or_default.rs b/clippy_lints/src/methods/map_unwrap_or_default.rs new file mode 100644 index 0000000000000..0c078ff3e8248 --- /dev/null +++ b/clippy_lints/src/methods/map_unwrap_or_default.rs @@ -0,0 +1,57 @@ +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; +use clippy_utils::res::MaybeDef as _; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::Expr; +use rustc_lint::LateContext; +use rustc_span::Span; + +use crate::methods::MAP_UNWRAP_OR; + +/// Lints usage of `map(f).unwrap_or_default()`, where the return type of `f` is not `bool`. +/// When `f` returns a `bool` value, the `manual_is_variant_and` lint is more useful. +pub(super) fn check<'tcx>( + cx: &LateContext<'tcx>, + expr: &'tcx Expr<'tcx>, + recv: &'tcx Expr<'tcx>, + map_recv: &'tcx Expr<'tcx>, + map_method_span: Span, + msrv: Msrv, +) { + if !msrv.meets(cx, msrvs::MAP_OR_DEFAULT) { + return; + } + + // Consider `Option` and `Result`. + let Some(ty @ (sym::Option | sym::Result)) = + cx.typeck_results().expr_ty(map_recv).peel_refs().opt_diag_name(&cx.tcx) + else { + return; + }; + + // Ignore `Option` or `Result` + // `manual_is_variant_and` lint is more useful in these cases. + if cx.typeck_results().expr_ty(expr).is_bool() { + return; + } + + // Suggest autofix + let ty = if ty == sym::Option { "an `Option`" } else { "a `Result`" }; + span_lint_and_then( + cx, + MAP_UNWRAP_OR, + expr.span, + format!("called `map(_).unwrap_or_default()` on {ty} value"), + |diag| { + diag.multipart_suggestion( + "use instead", + vec![ + (recv.span.shrink_to_hi().with_hi(expr.span.hi()), String::new()), + (map_method_span, String::from("map_or_default")), + ], + Applicability::MachineApplicable, + ); + }, + ); +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index fe9e71a40f101..784061c7c24cb 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -78,6 +78,7 @@ mod map_flatten; mod map_identity; mod map_or_identity; mod map_unwrap_or; +mod map_unwrap_or_default; mod map_unwrap_or_else; mod map_with_unused_argument_over_ranges; mod mut_mutex_lock; @@ -120,12 +121,14 @@ mod stable_sort_primitive; mod str_split; mod str_splitn; mod string_extend_chars; +mod string_from_utf8_as_bytes; mod string_lit_chars_any; mod suspicious_command_arg_space; mod suspicious_map; mod suspicious_splitn; mod suspicious_to_owned; mod swap_with_temporary; +mod trim_split_white_space; mod type_id_on_box; mod unbuffered_bytes; mod uninit_assumed_init; @@ -2440,12 +2443,12 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `option.map(_).unwrap_or(_)` or `option.map(_).unwrap_or_else(_)` or - /// `result.map(_).unwrap_or_else(_)`. + /// Checks the usage of `map(_).unwrap_or(_)`, `map(_).unwrap_or_default()` + /// or `map(_).unwrap_or_else(_)` for `Option` and `Result` types. /// /// ### Why is this bad? /// Readability, these can be written more concisely (resp.) as - /// `option.map_or(_, _)`, `option.map_or_else(_, _)` and `result.map_or_else(_, _)`. + /// `map_or(_, _)`, `map_or_default(_)` or `map_or_else(_, _)`. /// /// ### Known problems /// The order of the arguments is not in execution order @@ -2457,6 +2460,7 @@ declare_clippy_lint! { /// # fn some_function(foo: ()) -> usize { 1 } /// option.map(|a| a + 1).unwrap_or(0); /// option.map(|a| a > 10).unwrap_or(false); + /// result.map(|a| vec![a]).unwrap_or_default(); /// result.map(|a| a + 1).unwrap_or_else(some_function); /// ``` /// @@ -2467,12 +2471,13 @@ declare_clippy_lint! { /// # fn some_function(foo: ()) -> usize { 1 } /// option.map_or(0, |a| a + 1); /// option.is_some_and(|a| a > 10); + /// result.map_or_default(|a| vec![a]); /// result.map_or_else(some_function, |a| a + 1); /// ``` #[clippy::version = "1.45.0"] pub MAP_UNWRAP_OR, pedantic, - "using `.map(f).unwrap_or(a)` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)` or `map_or_else(a, f)`" + "using `.map(f).unwrap_or(a)`, `map(f).unwrap_or_default()` or `.map(f).unwrap_or_else(func)`, which are more succinctly expressed as `map_or(a, f)`, `map_or_default(f)` or `map_or_else(a, f)`" } declare_clippy_lint! { @@ -3806,6 +3811,28 @@ declare_clippy_lint! { "using `x.extend(s.chars())` where s is a `&str` or `String`" } +declare_clippy_lint! { + /// ### What it does + /// Check if the string is transformed to byte array and casted back to string. + /// + /// ### Why is this bad? + /// It's unnecessary, the string can be used directly. + /// + /// ### Example + /// ```no_run + /// std::str::from_utf8(&"Hello World!".as_bytes()[6..11]).unwrap(); + /// ``` + /// + /// Use instead: + /// ```no_run + /// &"Hello World!"[6..11]; + /// ``` + #[clippy::version = "1.50.0"] + pub STRING_FROM_UTF8_AS_BYTES, + complexity, + "casting string slices to byte slices and back" +} + declare_clippy_lint! { /// ### What it does /// Checks for `.chars().any(|i| i == c)`. @@ -4044,6 +4071,27 @@ declare_clippy_lint! { "detect swap with a temporary value" } +declare_clippy_lint! { + /// ### What it does + /// Warns about calling `str::trim` (or variants) before `str::split_whitespace`. + /// + /// ### Why is this bad? + /// `split_whitespace` already ignores leading and trailing whitespace. + /// + /// ### Example + /// ```no_run + /// " A B C ".trim().split_whitespace(); + /// ``` + /// Use instead: + /// ```no_run + /// " A B C ".split_whitespace(); + /// ``` + #[clippy::version = "1.62.0"] + pub TRIM_SPLIT_WHITESPACE, + style, + "using `str::trim()` or alike before `str::split_whitespace`" +} + declare_clippy_lint! { /// ### What it does /// Looks for calls to `.type_id()` on a `Box`. @@ -5076,6 +5124,7 @@ impl_lint_pass!(Methods => [ SOME_FILTER, STABLE_SORT_PRIMITIVE, STRING_EXTEND_CHARS, + STRING_FROM_UTF8_AS_BYTES, STRING_LIT_CHARS_ANY, STR_SPLIT_AT_NEWLINE, SUSPICIOUS_COMMAND_ARG_SPACE, @@ -5084,6 +5133,7 @@ impl_lint_pass!(Methods => [ SUSPICIOUS_SPLITN, SUSPICIOUS_TO_OWNED, SWAP_WITH_TEMPORARY, + TRIM_SPLIT_WHITESPACE, TYPE_ID_ON_BOX, UNBUFFERED_BYTES, UNINIT_ASSUMED_INIT, @@ -5193,6 +5243,7 @@ impl<'tcx> LateLintPass<'tcx> for Methods { swap_with_temporary::check(cx, expr, func, args); ip_constant::check(cx, expr, func, args); clone_on_copy::check_function(cx, expr); + string_from_utf8_as_bytes::check_call(cx, expr, func, args); unwrap_expect_used::check_call( cx, expr, @@ -5897,6 +5948,7 @@ impl Methods { }, Some((sym::map, m_recv, [arg], span, _)) => { manual_is_variant_and::check_map_unwrap_or_default(cx, expr, m_recv, arg, span, self.msrv); + map_unwrap_or_default::check(cx, expr, recv, m_recv, span, self.msrv); }, Some((then_method @ (sym::then | sym::then_some), t_recv, [t_arg], _, _)) => { obfuscated_if_else::check( @@ -5997,7 +6049,9 @@ impl Methods { (sym::map_or, [def, map]) => { map_or_identity::check(cx, expr, recv, call_span, def, map); }, - + (sym::split_whitespace, []) => { + trim_split_white_space::check(cx, expr, recv, call_span); + }, (sym::to_string, []) => { inefficient_to_string::check(cx, expr, recv, self.msrv); }, diff --git a/clippy_lints/src/methods/needless_as_bytes.rs b/clippy_lints/src/methods/needless_as_bytes.rs index 068d8d2a1d68e..f8d93d24f54ca 100644 --- a/clippy_lints/src/methods/needless_as_bytes.rs +++ b/clippy_lints/src/methods/needless_as_bytes.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::sugg::Sugg; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::Expr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::{Span, Symbol}; diff --git a/clippy_lints/src/methods/no_effect_replace.rs b/clippy_lints/src/methods/no_effect_replace.rs index be5e10be54a89..66f451e5a2124 100644 --- a/clippy_lints/src/methods/no_effect_replace.rs +++ b/clippy_lints/src/methods/no_effect_replace.rs @@ -2,8 +2,8 @@ use clippy_utils::SpanlessEq; use clippy_utils::diagnostics::span_lint; use clippy_utils::res::MaybeDef as _; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::ExprKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use super::NO_EFFECT_REPLACE; diff --git a/clippy_lints/src/methods/option_map_or_none.rs b/clippy_lints/src/methods/option_map_or_none.rs index ef6164654f2de..aa1ef9a37374a 100644 --- a/clippy_lints/src/methods/option_map_or_none.rs +++ b/clippy_lints/src/methods/option_map_or_none.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::is_none_expr; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet; +use rustc_attr_ir::lang_items::LangItem::OptionSome; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem::OptionSome; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/methods/or_then_unwrap.rs b/clippy_lints/src/methods/or_then_unwrap.rs index 3f5b7d34f37e0..29db09eabe6fc 100644 --- a/clippy_lints/src/methods/or_then_unwrap.rs +++ b/clippy_lints/src/methods/or_then_unwrap.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet_with_applicability; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_span::{Span, sym}; diff --git a/clippy_lints/src/methods/repeat_once.rs b/clippy_lints/src/methods/repeat_once.rs index b7a8442d04c2a..de1c9561a9754 100644 --- a/clippy_lints/src/methods/repeat_once.rs +++ b/clippy_lints/src/methods/repeat_once.rs @@ -2,9 +2,9 @@ use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::Expr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use super::REPEAT_ONCE; diff --git a/clippy_lints/src/methods/result_map_or_else_none.rs b/clippy_lints/src/methods/result_map_or_else_none.rs index 6b49cd4e132b4..4f496de99bb1e 100644 --- a/clippy_lints/src/methods/result_map_or_else_none.rs +++ b/clippy_lints/src/methods/result_map_or_else_none.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet; use clippy_utils::{is_none_expr, peel_blocks}; +use rustc_attr_ir::lang_items::LangItem::OptionSome; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem::OptionSome; use rustc_lint::LateContext; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/methods/search_is_some.rs b/clippy_lints/src/methods/search_is_some.rs index fe743556e98a3..7c7211e971c8a 100644 --- a/clippy_lints/src/methods/search_is_some.rs +++ b/clippy_lints/src/methods/search_is_some.rs @@ -4,10 +4,10 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use clippy_utils::sugg::deref_closure_args; use clippy_utils::{is_receiver_of_method_call, strip_pat_refs, sym}; use hir::ExprKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::PatKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use rustc_span::{Span, Symbol}; diff --git a/clippy_lints/src/methods/sliced_string_as_bytes.rs b/clippy_lints/src/methods/sliced_string_as_bytes.rs index 544989fb4bace..6bef1bb1ebceb 100644 --- a/clippy_lints/src/methods/sliced_string_as_bytes.rs +++ b/clippy_lints/src/methods/sliced_string_as_bytes.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::higher; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/str_splitn.rs b/clippy_lints/src/methods/str_splitn.rs index 249496ed52ca1..a173510dea7b8 100644 --- a/clippy_lints/src/methods/str_splitn.rs +++ b/clippy_lints/src/methods/str_splitn.rs @@ -7,8 +7,8 @@ use clippy_utils::usage::local_used_after_expr; use clippy_utils::visitors::{Descend, for_each_expr}; use clippy_utils::{paths, sym}; use core::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BindingMode, Expr, ExprKind, HirId, LetStmt, MatchSource, Node, Pat, PatKind, Stmt, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty; diff --git a/clippy_lints/src/methods/string_extend_chars.rs b/clippy_lints/src/methods/string_extend_chars.rs index 6e318679fb248..b395369449eae 100644 --- a/clippy_lints/src/methods/string_extend_chars.rs +++ b/clippy_lints/src/methods/string_extend_chars.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_applicability; use clippy_utils::{method_chain_args, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::LateContext; use super::STRING_EXTEND_CHARS; diff --git a/clippy_lints/src/methods/string_from_utf8_as_bytes.rs b/clippy_lints/src/methods/string_from_utf8_as_bytes.rs new file mode 100644 index 0000000000000..97506d795cd72 --- /dev/null +++ b/clippy_lints/src/methods/string_from_utf8_as_bytes.rs @@ -0,0 +1,46 @@ +use crate::methods::STRING_FROM_UTF8_AS_BYTES; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; +use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; +use clippy_utils::{method_calls, sym}; +use rustc_ast::BorrowKind; +use rustc_errors::Applicability; +use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; + +pub(super) fn check_call(cx: &LateContext<'_>, expr: &Expr<'_>, fun: &Expr<'_>, args: &[Expr<'_>]) { + // Find `std::str::converts::from_utf8` or `std::primitive::str::from_utf8` + + if let [bytes_arg] = args && let Some(sym::str_from_utf8 | sym::str_inherent_from_utf8) = + fun.res(cx).opt_diag_name(cx) + + // Find string::as_bytes + && let ExprKind::AddrOf(BorrowKind::Ref, _, inner) = bytes_arg.kind + && let ExprKind::Index(left, right, _) = inner.kind + && let (method_names, expressions, _) = method_calls(left, 1) + && method_names == [sym::as_bytes] + && expressions.len() == 1 + && expressions[0].1.is_empty() + + // Check for slicer + && let ExprKind::Struct(&qpath, _, _) = right.kind + && cx.tcx.qpath_is_lang_item(qpath, LangItem::Range) + { + let mut applicability = Applicability::MachineApplicable; + let string_expression = &expressions[0].0; + + let snippet_app = snippet_with_applicability(cx, string_expression.span, "..", &mut applicability); + let (right_snip, _) = snippet_with_context(cx, right.span, expr.span.ctxt(), "..", &mut applicability); + + span_lint_and_sugg( + cx, + STRING_FROM_UTF8_AS_BYTES, + expr.span, + "calling a slice of `as_bytes()` with `from_utf8` should be not necessary", + "try", + format!("Some(&{snippet_app}[{right_snip}])"), + applicability, + ); + } +} diff --git a/clippy_lints/src/methods/trim_split_white_space.rs b/clippy_lints/src/methods/trim_split_white_space.rs new file mode 100644 index 0000000000000..99b55ca108ee2 --- /dev/null +++ b/clippy_lints/src/methods/trim_split_white_space.rs @@ -0,0 +1,36 @@ +use crate::methods::TRIM_SPLIT_WHITESPACE; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::sym; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind}; +use rustc_lint::LateContext; +use rustc_span::Span; +use rustc_span::def_id::DefId; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, split_recv: &Expr<'_>, split_ws_span: Span) { + let tyckres = cx.typeck_results(); + if let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id) + && cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id) + && let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind + && let trim_fn_name @ (sym::trim | sym::trim_start | sym::trim_end) = path.ident.name + && let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id) + && is_one_of_trim_diagnostic_items(cx, trim_def_id) + { + span_lint_and_sugg( + cx, + TRIM_SPLIT_WHITESPACE, + trim_span.with_hi(split_ws_span.lo()), + format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), + format!("remove `{trim_fn_name}()`"), + String::new(), + Applicability::MachineApplicable, + ); + } +} + +fn is_one_of_trim_diagnostic_items(cx: &LateContext<'_>, trim_def_id: DefId) -> bool { + matches!( + cx.tcx.get_diagnostic_name(trim_def_id), + Some(sym::str_trim | sym::str_trim_start | sym::str_trim_end) + ) +} diff --git a/clippy_lints/src/methods/unnecessary_join.rs b/clippy_lints/src/methods/unnecessary_join.rs index e8751646eabf1..963c2f2bf8af9 100644 --- a/clippy_lints/src/methods/unnecessary_join.rs +++ b/clippy_lints/src/methods/unnecessary_join.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use rustc_ast::ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; use rustc_middle::ty; diff --git a/clippy_lints/src/methods/unnecessary_to_owned.rs b/clippy_lints/src/methods/unnecessary_to_owned.rs index 4134143b29cff..c7e5e58b57afa 100644 --- a/clippy_lints/src/methods/unnecessary_to_owned.rs +++ b/clippy_lints/src/methods/unnecessary_to_owned.rs @@ -7,8 +7,8 @@ use clippy_utils::source::{SpanExt as _, snippet, snippet_with_context}; use clippy_utils::ty::{get_iterator_item_ty, implements_trait, is_copy, peel_and_count_ty_refs}; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{fn_def_id, get_parent_expr, is_expr_temporary_value, return_ty, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{BorrowKind, Expr, ExprKind, ItemKind, Node}; diff --git a/clippy_lints/src/methods/useless_asref.rs b/clippy_lints/src/methods/useless_asref.rs index 43fcc52ab7b3b..057bb3a3a538d 100644 --- a/clippy_lints/src/methods/useless_asref.rs +++ b/clippy_lints/src/methods/useless_asref.rs @@ -3,8 +3,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::snippet_with_applicability; use clippy_utils::ty::{implements_trait, peel_and_count_ty_refs, should_call_clone_as_function}; use clippy_utils::{get_parent_expr, peel_blocks, strip_pat_refs}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, Node}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/methods/zst_offset.rs b/clippy_lints/src/methods/zst_offset.rs index 4d3882089a2fc..e21ecef699a8d 100644 --- a/clippy_lints/src/methods/zst_offset.rs +++ b/clippy_lints/src/methods/zst_offset.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::res::MaybeDef as _; +use rustc_attr_ir::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::LangItem; use rustc_lint::LateContext; use rustc_middle::ty; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index 51423b9811fcb..af2c84737c655 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -1,7 +1,7 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::{is_doc_hidden, is_from_proc_macro}; -use rustc_hir::attrs::AttributeKind; +use rustc_attr_ir::AttributeKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::{ AttrArgs, Attribute, Body, BodyId, FieldDef, HirId, ImplItem, Item, ItemKind, Node, TraitItem, Variant, diff --git a/clippy_lints/src/missing_fields_in_debug.rs b/clippy_lints/src/missing_fields_in_debug.rs index a5d8caaf2baa2..82cf696034a40 100644 --- a/clippy_lints/src/missing_fields_in_debug.rs +++ b/clippy_lints/src/missing_fields_in_debug.rs @@ -5,8 +5,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::sym; use clippy_utils::visitors::{Visitable, for_each_expr}; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Block, Expr, ExprKind, Impl, Item, ItemKind, Node, QPath, TyKind, VariantData}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/clippy_lints/src/missing_inline.rs b/clippy_lints/src/missing_inline.rs index 8b8a471cffbc4..fc77359fb8241 100644 --- a/clippy_lints/src/missing_inline.rs +++ b/clippy_lints/src/missing_inline.rs @@ -1,5 +1,6 @@ use clippy_utils::diagnostics::span_lint; -use rustc_hir::{ImplItem, ImplItemKind, Item, ItemKind, OwnerId, TraitFn, TraitItem, TraitItemKind, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{ImplItem, ImplItemKind, Item, ItemKind, OwnerId, TraitFn, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::Span; use rustc_structures::CrateType; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index 439cbe41e72b5..c332b332cbd41 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -1,12 +1,12 @@ -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::{SpanExt as _, snippet}; use clippy_utils::ty::{implements_trait, implements_trait_with_env_from_iter, is_copy}; use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{is_self, peel_hir_ty_options, strip_pat_refs, sym}; use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::intravisit::FnKind; use rustc_hir::{ Attribute, BindingMode, Body, ExprKind, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, Mutability, Node, @@ -295,9 +295,10 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { ); }; - span_lint_and_then( + span_lint_hir_and_then( cx, NEEDLESS_PASS_BY_VALUE, + arg.hir_id, input.span, "this argument is passed by value, but not consumed in the function body", sugg, diff --git a/clippy_lints/src/needless_question_mark.rs b/clippy_lints/src/needless_question_mark.rs index 91817f9457669..740530d277066 100644 --- a/clippy_lints/src/needless_question_mark.rs +++ b/clippy_lints/src/needless_question_mark.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::MaybeQPath as _; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{Block, Body, Expr, ExprKind, MatchSource}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/clippy_lints/src/new_without_default.rs b/clippy_lints/src/new_without_default.rs index 96eef0412cf4e..9d61d2301e2c4 100644 --- a/clippy_lints/src/new_without_default.rs +++ b/clippy_lints/src/new_without_default.rs @@ -2,10 +2,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::return_ty; use clippy_utils::source::{indent_of, reindent_multiline, snippet_with_applicability}; use clippy_utils::sugg::DiagExt as _; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::{Attribute, HirIdSet}; +use rustc_hir::HirIdSet; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::AssocKind; use rustc_span::sym; diff --git a/clippy_lints/src/no_mangle_with_rust_abi.rs b/clippy_lints/src/no_mangle_with_rust_abi.rs index f1d492089cddd..6b15780fc9218 100644 --- a/clippy_lints/src/no_mangle_with_rust_abi.rs +++ b/clippy_lints/src/no_mangle_with_rust_abi.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{snippet, snippet_with_applicability}; use rustc_abi::ExternAbi; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::{Attribute, Item, ItemKind}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::{BytePos, Pos as _}; diff --git a/clippy_lints/src/non_canonical_impls.rs b/clippy_lints/src/non_canonical_impls.rs index a9b601bbf46a2..32cf04908911f 100644 --- a/clippy_lints/src/non_canonical_impls.rs +++ b/clippy_lints/src/non_canonical_impls.rs @@ -3,8 +3,8 @@ use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::ty::implements_trait; use clippy_utils::{is_from_proc_macro, is_lint_allowed, last_path_segment, std_or_core}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{Block, Body, Expr, ExprKind, ImplItem, ImplItemKind, Item, ItemKind, Stmt, StmtKind, UnOp}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; diff --git a/clippy_lints/src/non_send_fields_in_send_ty.rs b/clippy_lints/src/non_send_fields_in_send_ty.rs index ea3b93c071526..bd4feea78f5a2 100644 --- a/clippy_lints/src/non_send_fields_in_send_ty.rs +++ b/clippy_lints/src/non_send_fields_in_send_ty.rs @@ -4,7 +4,7 @@ use clippy_utils::is_lint_allowed; use clippy_utils::source::snippet; use clippy_utils::ty::{implements_trait, is_copy}; use rustc_ast::ImplPolarity; -use rustc_hir::attrs::LangItem; +use rustc_attr_ir::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{FieldDef, Item, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs index 34c8074ecd115..53bc4e08abc5c 100644 --- a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs +++ b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs @@ -5,8 +5,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet_with_context; use clippy_utils::sym; use clippy_utils::visitors::is_expr_unsafe; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, Node, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/operators/integer_division_remainder_used.rs b/clippy_lints/src/operators/integer_division_remainder_used.rs index 976b2d8b0c63a..fa080cba926ed 100644 --- a/clippy_lints/src/operators/integer_division_remainder_used.rs +++ b/clippy_lints/src/operators/integer_division_remainder_used.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use rustc_ast::BinOpKind; use rustc_hir::Expr; -use rustc_lint::LateContext; +use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty; use rustc_span::Span; @@ -13,11 +13,12 @@ pub(super) fn check(cx: &LateContext<'_>, op: BinOpKind, lhs: &Expr<'_>, rhs: &E && let rhs_ty = cx.typeck_results().expr_ty(rhs) && let ty::Int(_) | ty::Uint(_) = lhs_ty.peel_refs().kind() && let ty::Int(_) | ty::Uint(_) = rhs_ty.peel_refs().kind() + && !span.in_external_macro(cx.sess().source_map()) { span_lint( cx, INTEGER_DIVISION_REMAINDER_USED, - span.source_callsite(), + span, format!("use of `{}` has been disallowed in this context", op.as_str()), ); } diff --git a/clippy_lints/src/operators/mod.rs b/clippy_lints/src/operators/mod.rs index 1bd954bf1421e..8a7bbdf08e76b 100644 --- a/clippy_lints/src/operators/mod.rs +++ b/clippy_lints/src/operators/mod.rs @@ -1101,9 +1101,8 @@ impl<'tcx> LateLintPass<'tcx> for Operators { assign_op_pattern::check(cx, e, lhs, rhs, self.msrv); self_assignment::check(cx, e, lhs, rhs); }, - ExprKind::Unary(op, arg) => - { - #[expect(clippy::collapsible_match)] + #[expect(clippy::collapsible_match)] + ExprKind::Unary(op, arg) => { if op == UnOp::Neg { self.arithmetic_context.check_negate(cx, e, arg); } diff --git a/clippy_lints/src/option_if_let_else.rs b/clippy_lints/src/option_if_let_else.rs index e39dbc3b51a78..6a928a4407d17 100644 --- a/clippy_lints/src/option_if_let_else.rs +++ b/clippy_lints/src/option_if_let_else.rs @@ -8,9 +8,9 @@ use clippy_utils::{ CaptureKind, can_move_expr_to_closure, eager_or_lazy, expr_requires_coercion, higher, is_else_clause, is_in_const_context, is_none_pattern, peel_blocks, peel_hir_expr_while, }; +use rustc_attr_ir::lang_items::LangItem::ResultErr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::ResultErr; use rustc_hir::def::Res; use rustc_hir::intravisit::{Visitor, walk_expr, walk_path}; use rustc_hir::{ diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 9498e18e2d35d..70b5adb0a7390 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -5,13 +5,13 @@ use clippy_utils::ty::{for_each_top_level_late_bound_region, is_copy}; use clippy_utils::{is_self, is_self_ty}; use core::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_ir::{InlineAttr, find_attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordItems; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::InlineAttr; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind, find_attr}; +use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf as _; diff --git a/clippy_lints/src/pub_underscore_fields.rs b/clippy_lints/src/pub_underscore_fields.rs index ee468f1b3fd86..57935dd3efd17 100644 --- a/clippy_lints/src/pub_underscore_fields.rs +++ b/clippy_lints/src/pub_underscore_fields.rs @@ -4,7 +4,7 @@ use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::sym::PhantomPinned; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{FieldDef, Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/question_mark.rs b/clippy_lints/src/question_mark.rs index ea8dc36b992e4..0141835b22144 100644 --- a/clippy_lints/src/question_mark.rs +++ b/clippy_lints/src/question_mark.rs @@ -14,8 +14,8 @@ use clippy_utils::{ is_none_expr, is_none_pattern, pat_and_expr_can_be_question_mark, peel_blocks, peel_blocks_with_stmt, span_contains_cfg, span_contains_comment, sym, }; +use rustc_attr_ir::lang_items::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::{self, OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::Res; use rustc_hir::{ Arm, BindingMode, Block, Body, ByRef, Expr, ExprKind, FnRetTy, HirId, LetStmt, MatchSource, Mutability, Node, Pat, diff --git a/clippy_lints/src/ranges.rs b/clippy_lints/src/ranges.rs index 21e0d94d673e3..7dff3b0cc2efd 100644 --- a/clippy_lints/src/ranges.rs +++ b/clippy_lints/src/ranges.rs @@ -11,8 +11,8 @@ use clippy_utils::{ }; use rustc_ast::Mutability; use rustc_ast::ast::RangeLimits; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BinOpKind, Expr, ExprKind, HirId, Node}; use rustc_lint::{LateContext, LateLintPass, Lint, impl_lint_pass}; use rustc_middle::ty::{self, ClauseKind, ClausePolarity, GenericArgKind, Ty}; diff --git a/clippy_lints/src/redundant_clone.rs b/clippy_lints/src/redundant_clone.rs index 94c59ec9e11b9..549b786938a4c 100644 --- a/clippy_lints/src/redundant_clone.rs +++ b/clippy_lints/src/redundant_clone.rs @@ -5,8 +5,8 @@ use clippy_utils::source::SpanExt as _; use clippy_utils::ty::{has_drop, is_copy, peel_and_count_ty_refs}; use clippy_utils::visitors::for_each_expr_without_closures; use clippy_utils::{fn_has_unsatisfiable_clauses, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Constness, ExprKind, FnDecl, def_id}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/clippy_lints/src/redundant_slicing.rs b/clippy_lints/src/redundant_slicing.rs index f68554b743b0f..5c50b32dacc58 100644 --- a/clippy_lints/src/redundant_slicing.rs +++ b/clippy_lints/src/redundant_slicing.rs @@ -4,8 +4,8 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_context; use clippy_utils::ty::peel_and_count_ty_refs; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass, Lint, declare_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, AutoBorrow, AutoBorrowMutability}; diff --git a/clippy_lints/src/regex.rs b/clippy_lints/src/regex.rs index 26ffaafb3f19d..0be79bda733f2 100644 --- a/clippy_lints/src/regex.rs +++ b/clippy_lints/src/regex.rs @@ -2,6 +2,7 @@ use std::fmt::Display; use clippy_utils::consts::{ConstEvalCtxt, Constant}; use clippy_utils::diagnostics::{span_lint, span_lint_and_help}; +use clippy_utils::mir::{block_in_cycle, enclosing_mir, function_call_basic_block}; use clippy_utils::paths; use clippy_utils::paths::PathLookup; use clippy_utils::res::MaybeQPath as _; @@ -144,6 +145,9 @@ impl<'tcx> LateLintPass<'tcx> for Regex { if let Some(&(loop_item_id, loop_span)) = self.loop_stack.last() && loop_item_id == fun.hir_id.owner && (matches!(arg.kind, ExprKind::Lit(_)) || const_str(cx, arg).is_some()) + && let Some(mir_body) = enclosing_mir(cx.tcx, fun.hir_id) + && let Some(mir_fun) = function_call_basic_block(mir_body, fun) + && block_in_cycle(mir_body, mir_fun) { span_lint_and_help( cx, diff --git a/clippy_lints/src/replace_box.rs b/clippy_lints/src/replace_box.rs index e49a766acc26d..c07aeec804f57 100644 --- a/clippy_lints/src/replace_box.rs +++ b/clippy_lints/src/replace_box.rs @@ -3,10 +3,10 @@ use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::sugg::Sugg; use clippy_utils::ty::implements_trait; use clippy_utils::{is_default_equivalent_call, local_is_initialized}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::smallvec::SmallVec; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Body, BodyId, Expr, ExprKind, HirId, QPath}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/return_self_not_must_use.rs b/clippy_lints/src/return_self_not_must_use.rs index ca6486578e1ca..53d59d71dd3e8 100644 --- a/clippy_lints/src/return_self_not_must_use.rs +++ b/clippy_lints/src/return_self_not_must_use.rs @@ -1,9 +1,10 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::ty::opt_must_use_path; use clippy_utils::{nth_arg, return_ty}; +use rustc_attr_ir::find_attr; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; -use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind, find_attr}; +use rustc_hir::{Body, FnDecl, OwnerId, TraitItem, TraitItemKind}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/returns/needless_return.rs b/clippy_lints/src/returns/needless_return.rs index eab681a4cb720..64a136d96a610 100644 --- a/clippy_lints/src/returns/needless_return.rs +++ b/clippy_lints/src/returns/needless_return.rs @@ -5,8 +5,8 @@ use clippy_utils::{ span_contains_cfg, span_find_starting_semi, sym, }; use rustc_ast::MetaItemInner; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, Expr, ExprKind, HirId, MatchSource, StmtKind}; use rustc_lint::{LateContext, Level, LintContext as _}; diff --git a/clippy_lints/src/returns/needless_return_with_question_mark.rs b/clippy_lints/src/returns/needless_return_with_question_mark.rs index bf411d22b8cf7..d0ac03766b670 100644 --- a/clippy_lints/src/returns/needless_return_with_question_mark.rs +++ b/clippy_lints/src/returns/needless_return_with_question_mark.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::{is_from_proc_macro, is_inside_let_else}; +use rustc_attr_ir::lang_items::LangItem::ResultErr; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::ResultErr; use rustc_hir::{Expr, ExprKind, HirId, MatchSource, Node, Stmt, StmtKind}; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty::adjustment::Adjust; diff --git a/clippy_lints/src/same_length_and_capacity.rs b/clippy_lints/src/same_length_and_capacity.rs index 2339e6e2e0c4f..74e343227a477 100644 --- a/clippy_lints/src/same_length_and_capacity.rs +++ b/clippy_lints/src/same_length_and_capacity.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::res::MaybeDef as _; use clippy_utils::{eq_expr_value, sym}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, QPath}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::symbol::sym as rustc_sym; diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 1c7a6e407cc05..24ef61c2ca9c3 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -2,13 +2,14 @@ use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::Msrv; +use clippy_utils::paths::{PathNS, lookup_path}; use rustc_errors::Applicability; -use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Block, Body, HirId, Path, PathSegment, StabilityLevel, StableSince}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext as _, impl_lint_pass}; use rustc_span::symbol::kw; -use rustc_span::{Span, sym}; +use rustc_span::{Span, Symbol, sym}; declare_clippy_lint! { /// ### What it does @@ -148,6 +149,14 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { }, }; + // Only the crate name is replaced, so the rest of the path has to name the same item in + // the target crate. `std::collections::Bound` for instance reaches `core::ops::Bound` + // through a legacy re-export, and `core::collections` does not exist. + if !resolves_in(cx, path, def_kind, def_id, replace_with) { + self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + return; + } + self.lint_if_finish( cx, first_segment.ident.span, @@ -218,6 +227,31 @@ fn emit_lints(cx: &LateContext<'_>, lint_points: Option<(Span, Vec)>) } } +/// Checks whether `path` still resolves to `def_id` once its crate name is replaced with +/// `replace_with`. +/// +/// [`lookup_path`] is expensive, so this is only called once a path is about to be linted. +fn resolves_in(cx: &LateContext<'_>, path: &Path<'_>, def_kind: DefKind, def_id: DefId, replace_with: &str) -> bool { + let ns = match def_kind.ns() { + Some(Namespace::TypeNS) => PathNS::Type, + Some(Namespace::ValueNS) => PathNS::Value, + Some(Namespace::MacroNS) => PathNS::Macro, + None => PathNS::Arbitrary, + }; + + let mut segments = Vec::with_capacity(path.segments.len()); + segments.push(Symbol::intern(replace_with)); + segments.extend( + path.segments + .iter() + .skip_while(|segment| segment.ident.name == kw::PathRoot) + .skip(1) + .map(|segment| segment.ident.name), + ); + + lookup_path(cx.tcx, ns, &segments).contains(&def_id) +} + /// Returns the first named segment of a [`Path`]. /// /// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`] diff --git a/clippy_lints/src/strings.rs b/clippy_lints/src/strings.rs index d97a1205d4378..5ee34a746cff5 100644 --- a/clippy_lints/src/strings.rs +++ b/clippy_lints/src/strings.rs @@ -1,12 +1,11 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_sugg, span_lint_and_then}; use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::{snippet, snippet_with_applicability, snippet_with_context}; -use clippy_utils::{SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, method_calls, sym}; +use clippy_utils::{SpanlessEq, get_expr_use_or_unification_node, get_parent_expr, is_lint_allowed, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::DefId; -use rustc_hir::{BinOpKind, BorrowKind, Expr, ExprKind, Node}; +use rustc_hir::{BinOpKind, Expr, ExprKind, Node}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; use rustc_middle::ty; @@ -91,28 +90,6 @@ declare_clippy_lint! { "using `x = x + ..` where x is a `String` instead of `push_str()`" } -declare_clippy_lint! { - /// ### What it does - /// Check if the string is transformed to byte array and cast back to string. - /// - /// ### Why is this bad? - /// It's unnecessary, the string can be used directly. - /// - /// ### Example - /// ```no_run - /// std::str::from_utf8(&"Hello World!".as_bytes()[6..11]).unwrap(); - /// ``` - /// - /// Use instead: - /// ```no_run - /// &"Hello World!"[6..11]; - /// ``` - #[clippy::version = "1.50.0"] - pub STRING_FROM_UTF8_AS_BYTES, - complexity, - "casting string slices to byte slices and back" -} - declare_clippy_lint! { /// ### What it does /// Checks for the `as_bytes` method called on string literals @@ -183,37 +160,11 @@ declare_clippy_lint! { "slicing a string" } -declare_clippy_lint! { - /// ### What it does - /// Warns about calling `str::trim` (or variants) before `str::split_whitespace`. - /// - /// ### Why is this bad? - /// `split_whitespace` already ignores leading and trailing whitespace. - /// - /// ### Example - /// ```no_run - /// " A B C ".trim().split_whitespace(); - /// ``` - /// Use instead: - /// ```no_run - /// " A B C ".split_whitespace(); - /// ``` - #[clippy::version = "1.62.0"] - pub TRIM_SPLIT_WHITESPACE, - style, - "using `str::trim()` or alike before `str::split_whitespace`" -} - declare_lint_pass!(StrToString => [STR_TO_STRING]); declare_lint_pass!(StringAdd => [STRING_ADD, STRING_ADD_ASSIGN, STRING_SLICE]); -declare_lint_pass!(StringLitAsBytes => [ - STRING_FROM_UTF8_AS_BYTES, - STRING_LIT_AS_BYTES, -]); - -declare_lint_pass!(TrimSplitWhitespace => [TRIM_SPLIT_WHITESPACE]); +declare_lint_pass!(StringLitAsBytes => [STRING_LIT_AS_BYTES]); impl<'tcx> LateLintPass<'tcx> for StringAdd { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { @@ -286,40 +237,6 @@ impl<'tcx> LateLintPass<'tcx> for StringLitAsBytes { fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { use rustc_ast::LitKind; - if let ExprKind::Call(fun, [bytes_arg]) = e.kind - // Find `std::str::converts::from_utf8` or `std::primitive::str::from_utf8` - && let Some(sym::str_from_utf8 | sym::str_inherent_from_utf8) = - fun.res(cx).opt_diag_name(cx) - - // Find string::as_bytes - && let ExprKind::AddrOf(BorrowKind::Ref, _, args) = bytes_arg.kind - && let ExprKind::Index(left, right, _) = args.kind - && let (method_names, expressions, _) = method_calls(left, 1) - && method_names == [sym::as_bytes] - && expressions.len() == 1 - && expressions[0].1.is_empty() - - // Check for slicer - && let ExprKind::Struct(&qpath, _, _) = right.kind - && cx.tcx.qpath_is_lang_item(qpath, LangItem::Range) - { - let mut applicability = Applicability::MachineApplicable; - let string_expression = &expressions[0].0; - - let snippet_app = snippet_with_applicability(cx, string_expression.span, "..", &mut applicability); - let (right_snip, _) = snippet_with_context(cx, right.span, e.span.ctxt(), "..", &mut applicability); - - span_lint_and_sugg( - cx, - STRING_FROM_UTF8_AS_BYTES, - e.span, - "calling a slice of `as_bytes()` with `from_utf8` should be not necessary", - "try", - format!("Some(&{snippet_app}[{right_snip}])"), - applicability, - ); - } - if let ExprKind::MethodCall(path, receiver, ..) = &e.kind && path.ident.name == sym::as_bytes && let ExprKind::Lit(lit) = &receiver.kind @@ -441,35 +358,3 @@ impl<'tcx> LateLintPass<'tcx> for StrToString { } } } - -impl<'tcx> LateLintPass<'tcx> for TrimSplitWhitespace { - fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { - let tyckres = cx.typeck_results(); - if let ExprKind::MethodCall(path, split_recv, [], split_ws_span) = expr.kind - && path.ident.name == sym::split_whitespace - && let Some(split_ws_def_id) = tyckres.type_dependent_def_id(expr.hir_id) - && cx.tcx.is_diagnostic_item(sym::str_split_whitespace, split_ws_def_id) - && let ExprKind::MethodCall(path, _trim_recv, [], trim_span) = split_recv.kind - && let trim_fn_name @ (sym::trim | sym::trim_start | sym::trim_end) = path.ident.name - && let Some(trim_def_id) = tyckres.type_dependent_def_id(split_recv.hir_id) - && is_one_of_trim_diagnostic_items(cx, trim_def_id) - { - span_lint_and_sugg( - cx, - TRIM_SPLIT_WHITESPACE, - trim_span.with_hi(split_ws_span.lo()), - format!("found call to `str::{trim_fn_name}` before `str::split_whitespace`"), - format!("remove `{trim_fn_name}()`"), - String::new(), - Applicability::MachineApplicable, - ); - } - } -} - -fn is_one_of_trim_diagnostic_items(cx: &LateContext<'_>, trim_def_id: DefId) -> bool { - matches!( - cx.tcx.get_diagnostic_name(trim_def_id), - Some(sym::str_trim | sym::str_trim_start | sym::str_trim_end) - ) -} diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index 95f19a1332417..e21f1663c87eb 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -5,8 +5,8 @@ use clippy_utils::res::MaybeDef as _; use clippy_utils::source::snippet_with_context; use clippy_utils::visitors::is_expr_unsafe; use clippy_utils::{match_libc_symbol, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Block, BlockCheckMode, Expr, ExprKind, Node, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index 1a3cb836867d6..abcc81c3c2361 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -1,8 +1,10 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::{snippet_indent, snippet_with_context}; use clippy_utils::sugg::Sugg; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::{can_mut_borrow_both, eq_expr_value, is_in_const_context, std_or_core, sym}; use itertools::Itertools as _; @@ -11,7 +13,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_errors::Applicability; use rustc_hir::{AssignOpKind, Block, Expr, ExprKind, LetStmt, PatKind, QPath, Stmt, StmtKind}; -use rustc_lint::{LateContext, LateLintPass, LintContext as _, declare_lint_pass}; +use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty; use rustc_span::symbol::Ident; use rustc_span::{Span, Spanned, SyntaxContext}; @@ -73,11 +75,21 @@ declare_clippy_lint! { "manual swap of two variables" } -declare_lint_pass!(Swap => [ALMOST_SWAPPED, MANUAL_SWAP]); +impl_lint_pass!(Swap => [ALMOST_SWAPPED, MANUAL_SWAP]); + +pub struct Swap { + msrv: Msrv, +} + +impl Swap { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv.into() } + } +} impl<'tcx> LateLintPass<'tcx> for Swap { fn check_block(&mut self, cx: &LateContext<'tcx>, block: &'tcx Block<'_>) { - check_manual_swap(cx, block); + check_manual_swap(cx, block, self.msrv); check_suspicious_swap(cx, block); check_xor_swap(cx, block); } @@ -166,8 +178,8 @@ fn generate_swap_warning<'tcx>( } /// Implementation of the `MANUAL_SWAP` lint. -fn check_manual_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>) { - if is_in_const_context(cx) { +fn check_manual_swap<'tcx>(cx: &LateContext<'tcx>, block: &'tcx Block<'tcx>, msrv: Msrv) { + if is_in_const_context(cx) && !msrv.meets(cx, msrvs::CONST_MEM_SWAP) { return; } diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 324d451ba5a0b..39b2b71a0d56d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -5,10 +5,10 @@ use clippy_utils::source::{SpanExt as _, snippet, snippet_with_applicability}; use clippy_utils::{SpanlessEq, SpanlessHash, is_from_proc_macro}; use core::hash::{Hash, Hasher}; use itertools::Itertools as _; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, IndexEntry}; use rustc_data_structures::unhash::UnhashMap; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::{ AmbigArg, BoundPolarity, GenericBound, Generics, Item, ItemKind, Node, Path, PathSegment, PredicateOrigin, QPath, diff --git a/clippy_lints/src/types/owned_cow.rs b/clippy_lints/src/types/owned_cow.rs index 8bdb37f5451ae..40af6706601c5 100644 --- a/clippy_lints/src/types/owned_cow.rs +++ b/clippy_lints/src/types/owned_cow.rs @@ -2,9 +2,9 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::snippet_opt; use clippy_utils::sym; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_lint::LateContext; use rustc_span::Span; diff --git a/clippy_lints/src/types/vec_box.rs b/clippy_lints/src/types/vec_box.rs index 204d9f06cc87f..3924d03a8bd19 100644 --- a/clippy_lints/src/types/vec_box.rs +++ b/clippy_lints/src/types/vec_box.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::last_path_segment; use clippy_utils::source::snippet; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, GenericArg, QPath, TyKind}; use rustc_hir_analysis::lower_ty; diff --git a/clippy_lints/src/unnecessary_owned_empty_strings.rs b/clippy_lints/src/unnecessary_owned_empty_strings.rs index 68790482e5854..5f6c095cab000 100644 --- a/clippy_lints/src/unnecessary_owned_empty_strings.rs +++ b/clippy_lints/src/unnecessary_owned_empty_strings.rs @@ -2,8 +2,8 @@ use clippy_utils::diagnostics::span_lint_and_sugg; use clippy_utils::res::MaybeDef as _; use clippy_utils::sym; use rustc_ast::ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty; diff --git a/clippy_lints/src/unnecessary_wraps.rs b/clippy_lints/src/unnecessary_wraps.rs index 1bf5208524f87..0afb5c4d1d0ff 100644 --- a/clippy_lints/src/unnecessary_wraps.rs +++ b/clippy_lints/src/unnecessary_wraps.rs @@ -6,8 +6,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::snippet; use clippy_utils::visitors::find_all_ret_expressions; use clippy_utils::{contains_return, return_ty}; +use rustc_attr_ir::lang_items::LangItem::{OptionSome, ResultOk}; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem::{OptionSome, ResultOk}; use rustc_hir::intravisit::FnKind; use rustc_hir::{Body, ExprKind, FnDecl, Impl, ItemKind, Node}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; diff --git a/clippy_lints/src/unused_io_amount.rs b/clippy_lints/src/unused_io_amount.rs index dcd82e29a0bee..35e9d0a6d78a7 100644 --- a/clippy_lints/src/unused_io_amount.rs +++ b/clippy_lints/src/unused_io_amount.rs @@ -3,8 +3,8 @@ use clippy_utils::macros::{is_panic, root_macro_call_first_node}; use clippy_utils::res::MaybeDef as _; use clippy_utils::{paths, peel_blocks, sym}; use hir::{ExprKind, HirId, PatKind}; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::Span; diff --git a/clippy_lints/src/useless_conversion.rs b/clippy_lints/src/useless_conversion.rs index 03028091e06d2..08197757c0553 100644 --- a/clippy_lints/src/useless_conversion.rs +++ b/clippy_lints/src/useless_conversion.rs @@ -3,9 +3,9 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _, MaybeResPath as _, Maybe use clippy_utils::source::{snippet, snippet_with_context}; use clippy_utils::sugg::{DiagExt as _, Sugg}; use clippy_utils::ty::{is_copy, same_type_modulo_regions}; -use clippy_utils::{get_parent_expr, is_ty_alias, sym}; +use clippy_utils::{get_parent_expr, in_automatically_derived, is_ty_alias, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, Expr, ExprKind, HirId, MatchSource, Mutability, Node, PatKind}; use rustc_infer::infer::TyCtxtInferExt as _; @@ -435,7 +435,10 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion { None, hint, ); - } else if name == sym::from_fn && same_type_modulo_regions(a, b) { + } else if name == sym::from_fn + && same_type_modulo_regions(a, b) + && !in_automatically_derived(cx.tcx, e.hir_id) + { let mut app = Applicability::MachineApplicable; let sugg = Sugg::hir_with_context(cx, arg, e.span.ctxt(), "", &mut app).maybe_paren(); let sugg_msg = format!("consider removing `{}()`", snippet(cx, path.span, "From::from")); diff --git a/clippy_lints/src/useless_vec.rs b/clippy_lints/src/useless_vec.rs index ddfb761af4fc0..3d2f47cee4670 100644 --- a/clippy_lints/src/useless_vec.rs +++ b/clippy_lints/src/useless_vec.rs @@ -288,9 +288,7 @@ impl SuggestedType { let maybe_args = maybe_args.as_deref().unwrap_or_default(); let maybe_len = len_span .map(|sp| sp.get_text(cx).expect("spans are always crate-local")) - .map(|st| format!("; {st}")) - .unwrap_or_default(); - + .map_or_default(|st| format!("; {st}")); match self { Self::SliceRef(Mutability::Mut) => format!("&mut [{maybe_args}{maybe_len}]"), Self::SliceRef(Mutability::Not) => format!("&[{maybe_args}{maybe_len}]"), diff --git a/clippy_lints/src/volatile_composites.rs b/clippy_lints/src/volatile_composites.rs index ac74a0ca54ca1..f4bfca1f98c1f 100644 --- a/clippy_lints/src/volatile_composites.rs +++ b/clippy_lints/src/volatile_composites.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint; use clippy_utils::res::MaybeDef as _; use clippy_utils::sym; -use rustc_hir::attrs::LangItem; +use rustc_attr_ir::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty::layout::LayoutOf as _; diff --git a/clippy_lints/src/with_capacity_zero.rs b/clippy_lints/src/with_capacity_zero.rs index ae6bb75bedc38..d2bf0e5636908 100644 --- a/clippy_lints/src/with_capacity_zero.rs +++ b/clippy_lints/src/with_capacity_zero.rs @@ -1,8 +1,8 @@ use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::res::MaybeDef as _; use clippy_utils::{fn_def_id, is_integer_literal, last_path_segment, span_contains_comment, sym}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::ty::Ty; diff --git a/clippy_lints_internal/Cargo.toml b/clippy_lints_internal/Cargo.toml index 8c12f0db61b5f..910a414e0ac0e 100644 --- a/clippy_lints_internal/Cargo.toml +++ b/clippy_lints_internal/Cargo.toml @@ -4,7 +4,6 @@ version = "0.0.1" edition = "2024" [dependencies] -clippy_config = { path = "../clippy_config" } clippy_utils = { path = "../clippy_utils" } itertools = "0.15" regex = { version = "1.5" } diff --git a/clippy_lints_internal/src/almost_standard_lint_formulation.rs b/clippy_lints_internal/src/almost_standard_lint_formulation.rs index 1d6b958084635..b70bc47754cc0 100644 --- a/clippy_lints_internal/src/almost_standard_lint_formulation.rs +++ b/clippy_lints_internal/src/almost_standard_lint_formulation.rs @@ -2,7 +2,8 @@ use crate::lint_without_lint_pass::is_lint_ref_type; use clippy_utils::diagnostics::span_lint_and_help; use regex::Regex; use rustc_ast::token::DocFragmentKind; -use rustc_hir::{Attribute, Item, ItemKind, Mutability}; +use rustc_attr_ir::Attribute; +use rustc_hir::{Item, ItemKind, Mutability}; use rustc_lint::{LateContext, LateLintPass, declare_tool_lint, impl_lint_pass}; use rustc_span::{Span, Symbol}; diff --git a/clippy_lints_internal/src/lib.rs b/clippy_lints_internal/src/lib.rs index 2d06940981795..a0cd49b2ea634 100644 --- a/clippy_lints_internal/src/lib.rs +++ b/clippy_lints_internal/src/lib.rs @@ -15,6 +15,7 @@ #![allow(rustc::potential_query_instability)] extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_attr_parsing; extern crate rustc_data_structures; extern crate rustc_errors; @@ -29,7 +30,6 @@ mod internal_paths; mod lint_without_lint_pass; mod msrv_attr_impl; mod outer_expn_data_pass; -mod produce_ice; mod repeated_is_diagnostic_item; mod symbols; mod unnecessary_def_path; @@ -47,12 +47,12 @@ static LINTS: &[&Lint] = &[ lint_without_lint_pass::MISSING_CLIPPY_VERSION_ATTRIBUTE, msrv_attr_impl::MISSING_MSRV_ATTR_IMPL, outer_expn_data_pass::OUTER_EXPN_EXPN_DATA, - produce_ice::PRODUCE_ICE, symbols::INTERNING_LITERALS, symbols::SYMBOL_AS_STR, unnecessary_def_path::UNNECESSARY_DEF_PATH, unsorted_clippy_utils_paths::UNSORTED_CLIPPY_UTILS_PATHS, unusual_names::UNUSUAL_NAMES, + repeated_is_diagnostic_item::REPEATED_IS_DIAGNOSTIC_ITEM, ]; pub fn register_lints(store: &mut LintStore) { @@ -61,7 +61,6 @@ pub fn register_lints(store: &mut LintStore) { store.register_early_lint_pass(Box::new(|| { Box::new(unsorted_clippy_utils_paths::UnsortedClippyUtilsPaths) })); - store.register_early_lint_pass(Box::new(|| Box::new(produce_ice::ProduceIce))); store.register_late_lint_pass(Box::new(|_| Box::new(collapsible_span_lint_calls::CollapsibleCalls))); store.register_late_lint_pass(Box::new(|_| Box::::default())); store.register_late_lint_pass(Box::new(|_| { diff --git a/clippy_lints_internal/src/produce_ice.rs b/clippy_lints_internal/src/produce_ice.rs deleted file mode 100644 index 82a6bcdf36af6..0000000000000 --- a/clippy_lints_internal/src/produce_ice.rs +++ /dev/null @@ -1,41 +0,0 @@ -use rustc_ast::ast::NodeId; -use rustc_ast::visit::FnKind; -use rustc_lint::{EarlyContext, EarlyLintPass, LintContext as _, declare_lint_pass, declare_tool_lint}; -use rustc_span::Span; - -declare_tool_lint! { - /// ### What it does - /// Not an actual lint. This lint is only meant for testing our customized internal compiler - /// error message by calling `panic`. - /// - /// ### Why is this bad? - /// ICE in large quantities can damage your teeth - /// - /// ### Example - /// ```rust,ignore - /// 🍦🍦🍦🍦🍦 - /// ``` - pub clippy::PRODUCE_ICE, - Warn, - "this message should not appear anywhere as we ICE before and don't emit the lint", - report_in_external_macro: true -} - -declare_lint_pass!(ProduceIce => [PRODUCE_ICE]); - -impl EarlyLintPass for ProduceIce { - fn check_fn(&mut self, cx: &EarlyContext<'_>, fn_kind: FnKind<'_>, span: Span, _: NodeId) { - if is_trigger_fn(fn_kind) { - cx.sess() - .dcx() - .span_delayed_bug(span, "Would you like some help with that?"); - } - } -} - -fn is_trigger_fn(fn_kind: FnKind<'_>) -> bool { - match fn_kind { - FnKind::Fn(_, _, func) => func.ident.name.as_str() == "it_looks_like_you_are_trying_to_kill_clippy", - FnKind::Closure(..) => false, - } -} diff --git a/clippy_utils/README.md b/clippy_utils/README.md index d3c1812e1a198..da5d9629f86f3 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-09-01 +nightly-2026-09-17 ``` diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 74be29dbb38c0..3c398d74ad7b4 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -778,9 +778,7 @@ fn eq_use_tree_kind(l: &UseTreeKind, r: &UseTreeKind) -> bool { match (l, r) { (Glob(_), Glob(_)) => true, (Simple(l), Simple(r)) => both(l.as_ref(), r.as_ref(), |l, r| eq_id(*l, *r)), - (Nested { items: l, .. }, Nested { items: r, .. }) => { - over(l, r, |l, r| eq_use_tree(&l.inner, &r.inner)) - } + (Nested { items: l, .. }, Nested { items: r, .. }) => over(l, r, |l, r| eq_use_tree(&l.inner, &r.inner)), _ => false, } } diff --git a/clippy_utils/src/attrs.rs b/clippy_utils/src/attrs.rs index 9feb723e7a443..bec3961271289 100644 --- a/clippy_utils/src/attrs.rs +++ b/clippy_utils/src/attrs.rs @@ -3,8 +3,8 @@ use crate::source::SpanExt as _; use crate::{sym, tokenize_with_text}; use rustc_ast::attr::AttributeExt; +use rustc_attr_ir::find_attr; use rustc_errors::Applicability; -use rustc_hir::find_attr; use rustc_lexer::TokenKind; use rustc_lint::LateContext; use rustc_middle::ty::{AdtDef, TyCtxt}; diff --git a/clippy_utils/src/higher.rs b/clippy_utils/src/higher.rs index 442eda329a475..8d37f8df3f016 100644 --- a/clippy_utils/src/higher.rs +++ b/clippy_utils/src/higher.rs @@ -7,7 +7,7 @@ use crate::res::MaybeDef as _; use crate::{is_expn_of, sym}; use rustc_ast::ast; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{ self as hir, Arm, Block, Expr, ExprKind, HirId, LetStmt, LocalSource, LoopSource, MatchSource, Node, Pat, QPath, StructTailExpr, diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index d4ee85dade5ad..0030f1cdc8208 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -17,6 +17,7 @@ // (Currently there is no way to opt into sysroot crates without `extern crate`.) extern crate rustc_abi; extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_attr_parsing; extern crate rustc_const_eval; extern crate rustc_data_structures; @@ -81,13 +82,13 @@ use itertools::Itertools as _; use rustc_abi::Integer; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_ast::{LitIntType, join_path_syms}; +use rustc_attr_ir::CfgEntry; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexmap; use rustc_data_structures::packed::Pu128; use rustc_data_structures::unhash::UnindexMap; -use rustc_hir::attrs::CfgEntry; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::lang_items::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::definitions::{DefPath, DefPathData}; @@ -111,6 +112,7 @@ use rustc_middle::ty::{ self as rustc_ty, Binder, BorrowKind, ClosureKind, EarlyBinder, GenericArgKind, GenericArgsRef, IntTy, Ty, TyCtxt, TypeFlags, TypeVisitableExt as _, TypeckResults, UintTy, UpvarCapture, }; +use rustc_session::config::Input; use rustc_span::hygiene::{ExpnKind, MacroKind}; use rustc_span::source_map::SourceMap; use rustc_span::symbol::{Ident, Symbol, kw}; @@ -2445,7 +2447,18 @@ pub fn is_in_cfg_test(tcx: TyCtxt<'_>, id: HirId) -> bool { /// Checks if the node is in a `#[test]` function or has any parent node marked `#[cfg(test)]` pub fn is_in_test(tcx: TyCtxt<'_>, hir_id: HirId) -> bool { - is_in_test_function(tcx, hir_id) || is_in_cfg_test(tcx, hir_id) + is_in_test_function(tcx, hir_id) || is_in_cfg_test(tcx, hir_id) || is_in_integration_test_file(tcx) +} + +/// Check if the node is in an integration test file (i.e. under `tests/`). +fn is_in_integration_test_file(tcx: TyCtxt<'_>) -> bool { + if let Input::File(ref path) = tcx.sess.io.input + && !tcx.sess.opts.unstable_opts.ui_testing + { + path.starts_with("tests") + } else { + false + } } /// Checks if the item of any of its parents has `#[cfg(...)]` attribute applied. diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index f1b12f1bd1614..edfcd9e4bb231 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -290,3 +290,17 @@ fn is_local_assignment(mir: &Body<'_>, local: Local, location: Location) -> bool }, } } + +/// Returns the basic block that is terminated with this function call. +pub fn function_call_basic_block(body: &Body<'_>, fun: &Expr<'_>) -> Option { + body.basic_blocks.iter_enumerated().find_map(|(block, data)| { + if let Some(terminator) = data.terminator.as_ref() + && let TerminatorKind::Call { fn_span, .. } = terminator.kind + && fn_span.lo() == fun.span.lo() + { + Some(block) + } else { + None + } + }) +} diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 4f4d8f3990d2e..5f30692a677af 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,9 +1,9 @@ use crate::{is_in_const_context, sym}; use rustc_ast::Attribute; use rustc_ast::attr::AttributeExt; +use rustc_attr_ir::RustcVersion; use rustc_attr_parsing::parse_version; use rustc_data_structures::smallvec::SmallVec; -use rustc_hir::attrs::RustcVersion; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_hir::{Constness, HirId, StabilityLevel, StableSince}; @@ -25,15 +25,16 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,98,0 { MAP_OR_DEFAULT } 1,97,0 { ISOLATE_LOWEST_ONE, BIT_WIDTH } - 1,94,0 { EULER_GAMMA, GOLDEN_RATIO } + 1,94,0 { EULER_GAMMA, GOLDEN_RATIO, MUL_ADD_CONST } 1,93,0 { VEC_DEQUE_POP_BACK_IF, VEC_DEQUE_POP_FRONT_IF } 1,91,0 { DURATION_FROM_MINUTES_HOURS } 1,89,0 { NONNULL_FROM_MUT } 1,88,0 { LET_CHAINS, AS_CHUNKS, RAW_PTR_DEFAULT } 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST } 1,86,0 { VEC_POP_IF } - 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL, WAKER_NOOP } + 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL, WAKER_NOOP, ABS_CONST, RADIANS_CONST, CONST_MEM_SWAP } 1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR } 1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP } 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS } diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 493b511661ae2..5249daedd269e 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -4,9 +4,9 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::{self, Msrv}; +use rustc_attr_ir::RustcVersion; +use rustc_attr_ir::lang_items::LangItem; use rustc_const_eval::check_consts::ConstCx; -use rustc_hir::attrs::RustcVersion; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId, StableSince}; use rustc_infer::infer::TyCtxtInferExt as _; @@ -442,7 +442,7 @@ pub fn is_stable_const_fn_at(tcx: TyCtxt<'_>, node: HirId, def_id: DefId, msrv: .and_then(|trait_def_id| tcx.lookup_const_stability(trait_def_id)) }) .is_none_or(|const_stab| { - if let rustc_hir::StabilityLevel::Stable { since, .. } = const_stab.level { + if let rustc_attr_ir::StabilityLevel::Stable { since, .. } = const_stab.level { // Checking MSRV is manually necessary because `rustc` has no such concept. This entire // function could be removed if `rustc` provided a MSRV-aware version of `is_stable_const_fn`. // as a part of an unimplemented MSRV check https://github.com/rust-lang/rust/issues/65262. diff --git a/clippy_utils/src/res.rs b/clippy_utils/src/res.rs index 3d0c4bb1a1188..90c88d6ceb404 100644 --- a/clippy_utils/src/res.rs +++ b/clippy_utils/src/res.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{ diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index ca8b54a6de58b..a244767cf3c3f 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -6,10 +6,10 @@ use core::ops::ControlFlow; use itertools::Itertools as _; use rustc_abi::{BackendRepr, FieldsShape, VariantIdx, Variants}; use rustc_ast::ast::Mutability; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_errors::pluralize; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{Expr, ExprKind, FnDecl}; diff --git a/declare_clippy_lint/src/lib.rs b/declare_clippy_lint/src/lib.rs index 6b1e46404b105..7d2efa95366c2 100644 --- a/declare_clippy_lint/src/lib.rs +++ b/declare_clippy_lint/src/lib.rs @@ -46,7 +46,8 @@ impl LintListBuilder { pub fn register(self, store: &mut LintStore) { store.register_lints(&self.lints); - store.register_group(true, "clippy::all", Some("clippy_all"), self.all); + store.register_group(true, "clippy::default", Some("clippy_all"), self.all); + store.register_group_alias("clippy::default", "clippy::all"); store.register_group(true, "clippy::cargo", Some("clippy_cargo"), self.cargo); store.register_group(true, "clippy::complexity", Some("clippy_complexity"), self.complexity); store.register_group( diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a6c202f04cc4f..f5ae3fb5f52fc 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-09-01" +channel = "nightly-2026-09-17" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" diff --git a/tests/compile-test.rs b/tests/compile-test.rs index 03a74f0b33251..2a5c3f7e3895d 100644 --- a/tests/compile-test.rs +++ b/tests/compile-test.rs @@ -155,17 +155,15 @@ impl TestContext { let mut config = Config { output_conflict_handling: error_on_output_conflict, // Pre-fill filters with TESTNAME; will be later extended with `self.args`. - filter_files: env::var("TESTNAME") - .map(|filters| { - filters - .split(',') - // Make sure that if TESTNAME is empty we produce the empty list here, - // not a list containing an empty string. - .filter(|s| !s.is_empty()) - .map(str::to_string) - .collect() - }) - .unwrap_or_default(), + filter_files: env::var("TESTNAME").map_or_default(|filters| { + filters + .split(',') + // Make sure that if TESTNAME is empty we produce the empty list here, + // not a list containing an empty string. + .filter(|s| !s.is_empty()) + .map(str::to_string) + .collect() + }), target: None, bless_command: Some(if IS_RUSTC_TEST_SUITE { "./x test src/tools/clippy --bless".into() @@ -339,46 +337,48 @@ fn run_ui_cargo(cx: &TestContext) { return; } - let mut config = cx.base_config("ui-cargo", false); - config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; - config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; - config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; - config.program.envs.extend([ - // FIXME(#160895): While the new solver is enabled by default on nightly, - // we don't want to use it in our tests for now. - ("RUSTFLAGS".into(), Some("-Dwarnings -Znext-solver=coherence".into())), - ("CARGO_INCREMENTAL".into(), Some("0".into())), - ]); - // We need to do this while we still have a rustc in the `program` field. - config.fill_host_and_target().unwrap(); - config.program.program.set_file_name(if cfg!(windows) { - "cargo-clippy.exe" - } else { - "cargo-clippy" - }); - config.comment_defaults.base().custom.clear(); - - config - .comment_defaults - .base() - .normalize_stderr - .push((Match::from(env::current_dir().unwrap().as_path()), b"$DIR".into())); + for test_dir in ["ui-cargo", "example_integration_test"] { + let mut config = cx.base_config(test_dir, false); + config.program.input_file_flag = CommandBuilder::cargo().input_file_flag; + config.program.out_dir_flag = CommandBuilder::cargo().out_dir_flag; + config.program.args = vec!["clippy".into(), "--color".into(), "never".into(), "--quiet".into()]; + config.program.envs.extend([ + // FIXME(#160895): While the new solver is enabled by default on nightly, + // we don't want to use it in our tests for now. + ("RUSTFLAGS".into(), Some("-Dwarnings -Znext-solver=coherence".into())), + ("CARGO_INCREMENTAL".into(), Some("0".into())), + ]); + // We need to do this while we still have a rustc in the `program` field. + config.fill_host_and_target().unwrap(); + config.program.program.set_file_name(if cfg!(windows) { + "cargo-clippy.exe" + } else { + "cargo-clippy" + }); + config.comment_defaults.base().custom.clear(); - let ignored_32bit = |path: &Path| { - // FIXME: for some reason the modules are linted in a different order for this test - cfg!(target_pointer_width = "32") && path.ends_with("tests/ui-cargo/module_style/fail_mod/Cargo.toml") - }; + config + .comment_defaults + .base() + .normalize_stderr + .push((Match::from(env::current_dir().unwrap().as_path()), b"$DIR".into())); + + let ignored_32bit = |path: &Path| { + // FIXME: for some reason the modules are linted in a different order for this test + cfg!(target_pointer_width = "32") && path.ends_with("tests/ui-cargo/module_style/fail_mod/Cargo.toml") + }; - ui_test::run_tests_generic( - vec![config], - |path, config| { - path.ends_with("Cargo.toml") - .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)) - }, - |_config, _file_contents| {}, - Box::::from(cx.args.format), - ) - .unwrap(); + ui_test::run_tests_generic( + vec![config], + |path, config| { + path.ends_with("Cargo.toml") + .then(|| ui_test::default_any_file_filter(path, config) && !ignored_32bit(path)) + }, + |_config, _file_contents| {}, + Box::::from(cx.args.format), + ) + .unwrap(); + } } fn main() { diff --git a/tests/example_integration_test/Cargo.toml b/tests/example_integration_test/Cargo.toml new file mode 100644 index 0000000000000..980770dfd5328 --- /dev/null +++ b/tests/example_integration_test/Cargo.toml @@ -0,0 +1,9 @@ +[package] +name = "example_integration_test" +version = "0.1.0" +edition = "2024" + +[dependencies] + +[lints.clippy] +unwrap_used = "deny" diff --git a/tests/example_integration_test/clippy.toml b/tests/example_integration_test/clippy.toml new file mode 100644 index 0000000000000..154626ef4e81f --- /dev/null +++ b/tests/example_integration_test/clippy.toml @@ -0,0 +1 @@ +allow-unwrap-in-tests = true diff --git a/tests/example_integration_test/src/main.rs b/tests/example_integration_test/src/main.rs new file mode 100644 index 0000000000000..0856df57c1370 --- /dev/null +++ b/tests/example_integration_test/src/main.rs @@ -0,0 +1,20 @@ +#![allow(clippy::disallowed_names)] + +fn main() { + println!("testing 123"); +} + +#[cfg(test)] +mod tests { + fn foo() -> Option { + Some(1) + } + + #[test] + fn integration_test() { + // should not lint in test file + // see https://github.com/rust-lang/rust-clippy/issues/13981 + let bar = foo().unwrap(); + println!("bar: {bar}"); + } +} diff --git a/tests/example_integration_test/tests/unwrap_in_integration.rs b/tests/example_integration_test/tests/unwrap_in_integration.rs new file mode 100644 index 0000000000000..9cd8816446d9a --- /dev/null +++ b/tests/example_integration_test/tests/unwrap_in_integration.rs @@ -0,0 +1,20 @@ +#![allow(clippy::disallowed_names)] + +fn foo() -> Option { + Some(1) +} + +fn helper_function() { + // Should not lint in integration test file, see https://github.com/rust-lang/rust-clippy/issues/13981 + let baz = foo().unwrap(); + println!("baz: {baz}"); +} + +#[test] +fn integration_test() { + helper_function(); + + // Should not lint in integration test file, see https://github.com/rust-lang/rust-clippy/issues/13981 + let bar = foo().unwrap(); + println!("bar: {bar}"); +} diff --git a/tests/integration.rs b/tests/integration.rs index 4275292fd86e6..06e87c17d283a 100644 --- a/tests/integration.rs +++ b/tests/integration.rs @@ -61,26 +61,6 @@ fn integration_test() { // debug: eprintln!("{stderr}"); - // this is an internal test to make sure we would correctly panic on a span_delayed_bug - if repo_name == "matthiaskrgr/clippy_ci_panic_test" { - // we need to kind of switch around our logic here: - // if we find a panic, everything is fine, if we don't panic, SOMETHING is broken about our testing - - // the repo basically just contains a span_delayed_bug that forces rustc/clippy to panic: - /* - #![feature(rustc_attrs)] - #[rustc_error(delayed_bug_from_inside_query)] - fn main() {} - */ - - if stderr.find("error: internal compiler error").is_some() { - eprintln!("we saw that we intentionally panicked, yay"); - return; - } - - panic!("panic caused by span_delayed_bug was NOT detected! Something is broken!"); - } - if let Some(backtrace_start) = stderr.find("error: internal compiler error") { static BACKTRACE_END_MSG: &str = "end of query stack"; let backtrace_end = stderr[backtrace_start..] diff --git a/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml index d39ad6c909a8b..8b676705b573e 100644 --- a/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/12145_with_dashes/Cargo.toml @@ -12,3 +12,6 @@ publish = false [dependencies] winapi = "0.2" ansi_term = "=0.11.0" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml index 4c5c761ef5ac6..25d6105a80733 100644 --- a/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/12176_allow_duplicate_crates/Cargo.toml @@ -8,3 +8,6 @@ publish = false [dependencies] winapi = "0.2" ansi_term = "=0.11.0" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml index 0eaf621775a58..8b7275cdd72b1 100644 --- a/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/5041_allow_dev_build/Cargo.toml @@ -17,3 +17,6 @@ ansi_term = "=0.11.0" [build-dependencies] ctrlc = "=3.1.0" ansi_term = "=0.11.0" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml index 4c5c761ef5ac6..25d6105a80733 100644 --- a/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/fail/Cargo.toml @@ -8,3 +8,6 @@ publish = false [dependencies] winapi = "0.2" ansi_term = "=0.11.0" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml index eb5929dcbc504..f09234ac76934 100644 --- a/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml +++ b/tests/ui-cargo/multiple_crate_versions/pass/Cargo.toml @@ -8,3 +8,6 @@ publish = false [dependencies] regex = "1.3.7" serde = "1.0.110" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml index fcb3cc58cc60c..e9b458b59ca26 100644 --- a/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/fail/Cargo.toml @@ -7,3 +7,6 @@ publish = false [dependencies] regex = "*" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml index db6ff477af910..640186af3dc21 100644 --- a/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml +++ b/tests/ui-cargo/wildcard_dependencies/pass/Cargo.toml @@ -7,3 +7,6 @@ publish = false [dependencies] regex = "1" + +[lints.cargo] +unused_dependencies = "allow" diff --git a/tests/ui-internal/custom_ice_message.rs b/tests/ui-internal/custom_ice_message.rs deleted file mode 100644 index c7e92b1bf164f..0000000000000 --- a/tests/ui-internal/custom_ice_message.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@rustc-env:RUST_BACKTRACE=0 -//@normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" -//@normalize-stderr-test: "produce_ice.rs:\d*:\d*" -> "produce_ice.rs" -//@normalize-stderr-test: "', .*clippy_lints" -> "', clippy_lints" -//@normalize-stderr-test: "'rustc'" -> "''" -//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc running on " -//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" - -#![deny(clippy::produce_ice)] -#![allow(clippy::missing_clippy_version_attribute)] - -fn it_looks_like_you_are_trying_to_kill_clippy() {} -//~^ ice: Would you like some help with that? - -fn main() {} diff --git a/tests/ui-internal/custom_ice_message.stderr b/tests/ui-internal/custom_ice_message.stderr deleted file mode 100644 index 2e4d53104fba1..0000000000000 --- a/tests/ui-internal/custom_ice_message.stderr +++ /dev/null @@ -1,26 +0,0 @@ -note: no errors encountered even though delayed bugs were created - -note: those delayed bugs will now be shown as internal compiler errors - -error: internal compiler error: Would you like some help with that? - --> tests/ui-internal/custom_ice_message.rs:12:1 - | -LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: delayed at clippy_lints_internal/src/produce_ice.rs - disabled backtrace - --> tests/ui-internal/custom_ice_message.rs:12:1 - | -LL | fn it_looks_like_you_are_trying_to_kill_clippy() {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -note: we would appreciate a bug report: https://github.com/rust-lang/rust-clippy/issues/new?template=ice.yml - -note: please make sure that you have updated to the latest nightly - -note: rustc running on - -note: compiler flags: -Z ui-testing -Z deduplicate-diagnostics=no -Z next-solver=coherence - -note: Clippy version: foo - diff --git a/tests/ui/clippy_all_group.rs b/tests/ui/clippy_all_group.rs new file mode 100644 index 0000000000000..f761420f42f86 --- /dev/null +++ b/tests/ui/clippy_all_group.rs @@ -0,0 +1,11 @@ +// Tests that `clippy::all` still works without a deprecation warning + +//@require-annotations-for-level: WARN + +#![deny(clippy::all)] + +fn f() { + "a".replace("a", "a"); + //~^ no_effect_replace + //~| NOTE: implied by `#[deny(clippy::all)]` +} diff --git a/tests/ui/clippy_all_group.stderr b/tests/ui/clippy_all_group.stderr new file mode 100644 index 0000000000000..4ebf1b74c8f40 --- /dev/null +++ b/tests/ui/clippy_all_group.stderr @@ -0,0 +1,15 @@ +error: replacing text with itself + --> tests/ui/clippy_all_group.rs:8:5 + | +LL | "a".replace("a", "a"); + | ^^^^^^^^^^^^^^^^^^^^^ + | +note: the lint level is defined here + --> tests/ui/clippy_all_group.rs:5:9 + | +LL | #![deny(clippy::all)] + | ^^^^^^^^^^^ + = note: `#[deny(clippy::no_effect_replace)]` implied by `#[deny(clippy::all)]` + +error: aborting due to 1 previous error + diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs index 9442e331d9207..0d542e8f329a0 100644 --- a/tests/ui/collapsible_match.rs +++ b/tests/ui/collapsible_match.rs @@ -461,3 +461,31 @@ fn issue16705(x: Option) { _ => false, }; } + +fn issue16916() { + use std::env; + match env::args().len() { + 2 => { + println!("Not enough many"); + }, + 3 => { + #[cfg(target_os = "freebsd")] + todo!(); + if env::args().len() > 5 { + println!("So many"); + } + }, + _ => {}, + } + + match env::args().len() { + 2 => {}, + #[expect(clippy::collapsible_match)] + 3 => { + if env::args().len() > 5 { + println!("So many"); + } + }, + _ => {}, + } +} diff --git a/tests/ui/custom_ice_message.rs b/tests/ui/custom_ice_message.rs new file mode 100644 index 0000000000000..0102b9d76eccc --- /dev/null +++ b/tests/ui/custom_ice_message.rs @@ -0,0 +1,13 @@ +//@rustc-env:RUST_BACKTRACE=0 +//@normalize-stderr-test: "Clippy version: .*" -> "Clippy version: foo" +//@normalize-stderr-test: "custom_ice_message.rs:\d*:\d*" -> "custom_ice_message.rs" +//@normalize-stderr-test: "rustc 1\.\d+.* running on .*" -> "rustc running on " +//@normalize-stderr-test: "(?ms)query stack during panic:\n.*end of query stack\n" -> "" +//@normalize-stderr-test: "note: delayed at .*" -> "note: delayed at " +//@normalize-stderr-test: "note: compiler flags: .*" -> "note: compiler flags: " + +#![feature(rustc_attrs)] + +#[rustc_delayed_bug_from_inside_query] +fn main() {} +//~^ ice: delayed bug triggered by diff --git a/tests/ui/custom_ice_message.stderr b/tests/ui/custom_ice_message.stderr new file mode 100644 index 0000000000000..5fc979cfaf67f --- /dev/null +++ b/tests/ui/custom_ice_message.stderr @@ -0,0 +1,24 @@ +note: no errors encountered even though delayed bugs were created + +note: those delayed bugs will now be shown as internal compiler errors + +error: internal compiler error: delayed bug triggered by #[rustc_delayed_bug_from_inside_query] + --> tests/ui/custom_ice_message.rs + | +LL | fn main() {} + | ^^^^^^^^^ + | +note: delayed at + --> tests/ui/custom_ice_message.rs + | +LL | fn main() {} + | ^^^^^^^^^ + +note: using internal features is not supported and expected to cause internal compiler errors when used incorrectly + +note: rustc running on + +note: compiler flags: + +note: Clippy version: foo + diff --git a/tests/ui/floating_point_abs.fixed b/tests/ui/floating_point_abs.fixed index 53e9014e284f5..68c584e0390fb 100644 --- a/tests/ui/floating_point_abs.fixed +++ b/tests/ui/floating_point_abs.fixed @@ -1,7 +1,13 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal ops in constant context +#[clippy::msrv = "1.85.0"] pub const fn in_const_context(num: f64) -> f64 { + num.abs() + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.84.0"] +const fn just_under_msrv(num: f64) -> f64 { if num >= 0.0 { num } else { -num } } diff --git a/tests/ui/floating_point_abs.rs b/tests/ui/floating_point_abs.rs index d5c792f6eb9c9..2edc2b95a5f1c 100644 --- a/tests/ui/floating_point_abs.rs +++ b/tests/ui/floating_point_abs.rs @@ -1,8 +1,14 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal ops in constant context +#[clippy::msrv = "1.85.0"] pub const fn in_const_context(num: f64) -> f64 { if num >= 0.0 { num } else { -num } + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.84.0"] +const fn just_under_msrv(num: f64) -> f64 { + if num >= 0.0 { num } else { -num } } struct A { diff --git a/tests/ui/floating_point_abs.stderr b/tests/ui/floating_point_abs.stderr index f031ac25114d1..68304573e914c 100644 --- a/tests/ui/floating_point_abs.stderr +++ b/tests/ui/floating_point_abs.stderr @@ -1,5 +1,5 @@ error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:14:5 + --> tests/ui/floating_point_abs.rs:5:5 | LL | if num >= 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` @@ -8,46 +8,52 @@ LL | if num >= 0.0 { num } else { -num } = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:19:5 + --> tests/ui/floating_point_abs.rs:20:5 + | +LL | if num >= 0.0 { num } else { -num } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` + +error: manual implementation of `abs` method + --> tests/ui/floating_point_abs.rs:25:5 | LL | if 0.0 < num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:24:5 + --> tests/ui/floating_point_abs.rs:30:5 | LL | if a.a > 0.0 { a.a } else { -a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:29:5 + --> tests/ui/floating_point_abs.rs:35:5 | LL | if 0.0 >= num { -num } else { num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `num.abs()` error: manual implementation of `abs` method - --> tests/ui/floating_point_abs.rs:34:5 + --> tests/ui/floating_point_abs.rs:40:5 | LL | if a.a < 0.0 { -a.a } else { a.a } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `a.a.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:39:5 + --> tests/ui/floating_point_abs.rs:45:5 | LL | if num < 0.0 { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:44:5 + --> tests/ui/floating_point_abs.rs:50:5 | LL | if 0.0 >= num { num } else { -num } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-num.abs()` error: manual implementation of negation of `abs` method - --> tests/ui/floating_point_abs.rs:50:12 + --> tests/ui/floating_point_abs.rs:56:12 | LL | a: if a.a >= 0.0 { -a.a } else { a.a }, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `-a.a.abs()` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/floating_point_mul_add.fixed b/tests/ui/floating_point_mul_add.fixed index 3e60b9efe5b0c..850286f3c5f89 100644 --- a/tests/ui/floating_point_mul_add.fixed +++ b/tests/ui/floating_point_mul_add.fixed @@ -1,13 +1,26 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal_ops in constant context +#[clippy::msrv = "1.94.0"] pub const fn in_const_context() { let a: f64 = 1234.567; let b: f64 = 45.67834; let c: f64 = 0.0004; + let _ = a.mul_add(b, c); + //~^ suboptimal_flops + let _ = a.mul_add(b, c); + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.93.0"] +const fn just_under_msrv() { + let a: f64 = 1234.567; + let b: f64 = 45.67834; + let c: f64 = 0.0004; + let _ = a * b + c; let _ = c + a * b; + // no lint: mul_add wasn't const-stable yet at this MSRV } fn main() { diff --git a/tests/ui/floating_point_mul_add.rs b/tests/ui/floating_point_mul_add.rs index 13625b4bb9ce5..fdc6d3e5eec36 100644 --- a/tests/ui/floating_point_mul_add.rs +++ b/tests/ui/floating_point_mul_add.rs @@ -1,13 +1,26 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal_ops in constant context +#[clippy::msrv = "1.94.0"] pub const fn in_const_context() { let a: f64 = 1234.567; let b: f64 = 45.67834; let c: f64 = 0.0004; + let _ = a * b + c; + //~^ suboptimal_flops + let _ = c + a * b; + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.93.0"] +const fn just_under_msrv() { + let a: f64 = 1234.567; + let b: f64 = 45.67834; + let c: f64 = 0.0004; + let _ = a * b + c; let _ = c + a * b; + // no lint: mul_add wasn't const-stable yet at this MSRV } fn main() { diff --git a/tests/ui/floating_point_mul_add.stderr b/tests/ui/floating_point_mul_add.stderr index f74a874c3351f..dfef0cc3e34d2 100644 --- a/tests/ui/floating_point_mul_add.stderr +++ b/tests/ui/floating_point_mul_add.stderr @@ -1,5 +1,5 @@ error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:19:13 + --> tests/ui/floating_point_mul_add.rs:9:13 | LL | let _ = a * b + c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` @@ -9,226 +9,238 @@ LL | let _ = a * b + c; = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:21:13 + --> tests/ui/floating_point_mul_add.rs:11:13 + | +LL | let _ = c + a * b; + | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + +error: multiply and add expressions may be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:32:13 + | +LL | let _ = a * b + c; + | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` + +error: multiply and add expressions may be calculated more efficiently and accurately + --> tests/ui/floating_point_mul_add.rs:34:13 | LL | let _ = a * b - c; | ^^^^^^^^^ help: consider using: `a.mul_add(b, -c)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:23:13 + --> tests/ui/floating_point_mul_add.rs:36:13 | LL | let _ = c + a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:25:13 + --> tests/ui/floating_point_mul_add.rs:38:13 | LL | let _ = c - a * b; | ^^^^^^^^^ help: consider using: `a.mul_add(-b, c)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:27:13 + --> tests/ui/floating_point_mul_add.rs:40:13 | LL | let _ = a + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, a)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:29:13 + --> tests/ui/floating_point_mul_add.rs:42:13 | LL | let _ = a + 2. * 4.; | ^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4., a)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:32:13 + --> tests/ui/floating_point_mul_add.rs:45:13 | LL | let _ = (a * b) + c; | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:34:13 + --> tests/ui/floating_point_mul_add.rs:47:13 | LL | let _ = c + (a * b); | ^^^^^^^^^^^ help: consider using: `a.mul_add(b, c)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:36:13 + --> tests/ui/floating_point_mul_add.rs:49:13 | LL | let _ = a * b * c + d; | ^^^^^^^^^^^^^ help: consider using: `(a * b).mul_add(c, d)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:39:13 + --> tests/ui/floating_point_mul_add.rs:52:13 | LL | let _ = a.mul_add(b, c) * a.mul_add(b, c) + a.mul_add(b, c) + c; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `a.mul_add(b, c).mul_add(a.mul_add(b, c), a.mul_add(b, c))` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:41:13 + --> tests/ui/floating_point_mul_add.rs:54:13 | LL | let _ = 1234.567_f64 * 45.67834_f64 + 0.0004_f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `1234.567_f64.mul_add(45.67834_f64, 0.0004_f64)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:44:13 + --> tests/ui/floating_point_mul_add.rs:57:13 | LL | let _ = (a * a + b).sqrt(); | ^^^^^^^^^^^ help: consider using: `a.mul_add(a, b)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:48:13 + --> tests/ui/floating_point_mul_add.rs:61:13 | LL | let _ = a - (b * u as f64); | ^^^^^^^^^^^^^^^^^^ help: consider using: `b.mul_add(-(u as f64), a)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:75:13 + --> tests/ui/floating_point_mul_add.rs:88:13 | LL | let _ = x * 2.0 + 0.5; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 2.0, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:79:13 + --> tests/ui/floating_point_mul_add.rs:92:13 | LL | let _ = 0.5 + x * 2.0; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 2.0, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:81:13 + --> tests/ui/floating_point_mul_add.rs:94:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:83:13 + --> tests/ui/floating_point_mul_add.rs:96:13 | LL | let _ = 1.2 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 1.2)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:87:13 + --> tests/ui/floating_point_mul_add.rs:100:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:91:13 + --> tests/ui/floating_point_mul_add.rs:104:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:95:13 + --> tests/ui/floating_point_mul_add.rs:108:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:99:13 + --> tests/ui/floating_point_mul_add.rs:112:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:104:13 + --> tests/ui/floating_point_mul_add.rs:117:13 | LL | let _ = 0.5 + f() * 1.2; | ^^^^^^^^^^^^^^^ help: consider using: `f64::mul_add(f(), 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:107:13 + --> tests/ui/floating_point_mul_add.rs:120:13 | LL | let _ = 0.5 + x * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(x, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:113:13 + --> tests/ui/floating_point_mul_add.rs:126:13 | LL | let _ = 0.5 + z * 1.2; | ^^^^^^^^^^^^^ help: consider using: `f64::mul_add(z, 1.2, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:116:13 + --> tests/ui/floating_point_mul_add.rs:129:13 | LL | let _ = 0.5 + 2.0 * x; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:118:13 + --> tests/ui/floating_point_mul_add.rs:131:13 | LL | let _ = 2.0 * x + 0.5; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(x, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:121:13 + --> tests/ui/floating_point_mul_add.rs:134:13 | LL | let _ = x + 2.0 * 4.0; | ^^^^^^^^^^^^^ help: consider using: `2.0f64.mul_add(4.0, x)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:125:13 + --> tests/ui/floating_point_mul_add.rs:138:13 | LL | let _ = y * 2.0 + 0.5; | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(2.0, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:127:13 + --> tests/ui/floating_point_mul_add.rs:140:13 | LL | let _ = 1.0 * 2.0 + 0.5; | ^^^^^^^^^^^^^^^ help: consider using: `1.0f64.mul_add(2.0, 0.5)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:136:5 + --> tests/ui/floating_point_mul_add.rs:149:5 | LL | a += b * c; | ^^^^^^^^^^ help: consider using: `a = b.mul_add(c, a)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:139:5 + --> tests/ui/floating_point_mul_add.rs:152:5 | LL | a -= b * c; | ^^^^^^^^^^ help: consider using: `a = b.mul_add(-c, a)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:148:13 + --> tests/ui/floating_point_mul_add.rs:161:13 | LL | let _ = 1.0 - y * 0.3; | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-0.3, 1.0)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:153:13 + --> tests/ui/floating_point_mul_add.rs:166:13 | LL | let _ = 1.0 - y * 0.3; | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-0.3, 1.0)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:158:13 + --> tests/ui/floating_point_mul_add.rs:171:13 | LL | let _ = 1.0 - y * 0.3; | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-0.3, 1.0)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:164:13 + --> tests/ui/floating_point_mul_add.rs:177:13 | LL | let _ = 1.0 - y * 0.3; | ^^^^^^^^^^^^^ help: consider using: `y.mul_add(-0.3, 1.0)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:170:13 + --> tests/ui/floating_point_mul_add.rs:183:13 | LL | let _ = x + y * z; | ^^^^^^^^^ help: consider using: `f32::mul_add(y, z, x)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:172:13 + --> tests/ui/floating_point_mul_add.rs:185:13 | LL | let _ = y * z + x; | ^^^^^^^^^ help: consider using: `f32::mul_add(y, z, x)` error: multiply and add expressions may be calculated more efficiently and accurately - --> tests/ui/floating_point_mul_add.rs:176:13 + --> tests/ui/floating_point_mul_add.rs:189:13 | LL | let _ = y + a * z; | ^^^^^^^^^ help: consider using: `a.mul_add(z, y)` -error: aborting due to 38 previous errors +error: aborting due to 40 previous errors diff --git a/tests/ui/floating_point_rad.fixed b/tests/ui/floating_point_rad.fixed index 61f3ccc8bd02c..adabc9614c6e2 100644 --- a/tests/ui/floating_point_rad.fixed +++ b/tests/ui/floating_point_rad.fixed @@ -1,7 +1,14 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal_flops in constant context -pub const fn const_context() { +#[clippy::msrv = "1.85.0"] +pub const fn in_const_context() { + let x = 3f32; + let _ = x.to_degrees(); + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.84.0"] +const fn just_under_msrv() { let x = 3f32; let _ = x * 180f32 / std::f32::consts::PI; } diff --git a/tests/ui/floating_point_rad.rs b/tests/ui/floating_point_rad.rs index f57359e15fe14..35a07f636f46c 100644 --- a/tests/ui/floating_point_rad.rs +++ b/tests/ui/floating_point_rad.rs @@ -1,7 +1,14 @@ #![warn(clippy::suboptimal_flops)] -/// Allow suboptimal_flops in constant context -pub const fn const_context() { +#[clippy::msrv = "1.85.0"] +pub const fn in_const_context() { + let x = 3f32; + let _ = x * 180f32 / std::f32::consts::PI; + //~^ suboptimal_flops +} + +#[clippy::msrv = "1.84.0"] +const fn just_under_msrv() { let x = 3f32; let _ = x * 180f32 / std::f32::consts::PI; } diff --git a/tests/ui/floating_point_rad.stderr b/tests/ui/floating_point_rad.stderr index b888edd59bfd1..de91fc3fd0d33 100644 --- a/tests/ui/floating_point_rad.stderr +++ b/tests/ui/floating_point_rad.stderr @@ -1,53 +1,59 @@ -error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:10:13 +error: conversion to degrees can be done more accurately + --> tests/ui/floating_point_rad.rs:6:13 | -LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_radians()` +LL | let _ = x * 180f32 / std::f32::consts::PI; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` | = note: `-D clippy::suboptimal-flops` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::suboptimal_flops)]` +error: conversion to radians can be done more accurately + --> tests/ui/floating_point_rad.rs:17:13 + | +LL | let _ = degrees as f64 * std::f64::consts::PI / 180.0; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_radians()` + error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:12:13 + --> tests/ui/floating_point_rad.rs:19:13 | LL | let _ = degrees as f64 * 180.0 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `(degrees as f64).to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:18:13 + --> tests/ui/floating_point_rad.rs:25:13 | LL | let _ = x * 180f32 / std::f32::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:20:13 + --> tests/ui/floating_point_rad.rs:27:13 | LL | let _ = 90. * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_degrees()` error: conversion to degrees can be done more accurately - --> tests/ui/floating_point_rad.rs:22:13 + --> tests/ui/floating_point_rad.rs:29:13 | LL | let _ = 90.5 * 180f64 / std::f64::consts::PI; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_degrees()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:24:13 + --> tests/ui/floating_point_rad.rs:31:13 | LL | let _ = x * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `x.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:26:13 + --> tests/ui/floating_point_rad.rs:33:13 | LL | let _ = 90. * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.0_f64.to_radians()` error: conversion to radians can be done more accurately - --> tests/ui/floating_point_rad.rs:28:13 + --> tests/ui/floating_point_rad.rs:35:13 | LL | let _ = 90.5 * std::f32::consts::PI / 180f32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `90.5_f64.to_radians()` -error: aborting due to 8 previous errors +error: aborting due to 9 previous errors diff --git a/tests/ui/format.fixed b/tests/ui/format.fixed index 7f01a88f932bd..2995d3f9896d3 100644 --- a/tests/ui/format.fixed +++ b/tests/ui/format.fixed @@ -95,6 +95,24 @@ fn main() { let xx = "xx"; let _ = xx.to_string(); //~^ useless_format + + // Issue #3361: `&format!("literal")` should suggest the literal directly + let _: &str = "hello"; //~ useless_format + let _: &str = "{}"; //~ useless_format + let _: &str = r"hello"; //~ useless_format + let _: &str = r#"world"#; //~ useless_format + let _: &str = r##"foo"##; //~ useless_format + let _: &str = r##"hello "\u{007B}""##; //~ useless_format + // Only immutable borrows: `&mut format!` is not handled + let _: &mut String = &mut "hello".to_string(); //~ useless_format + + fn literal(lit: &str) {} + literal("hello"); //~ useless_format + literal(&"hello"); //~ useless_format + + let lit = "hello"; + literal(lit); //~ useless_format + literal(lit); //~ useless_format } // `format!` as the tail expression of a block emitted by another macro diff --git a/tests/ui/format.rs b/tests/ui/format.rs index 92654e87a5eef..be89ff0ab72f2 100644 --- a/tests/ui/format.rs +++ b/tests/ui/format.rs @@ -98,6 +98,24 @@ fn main() { let xx = "xx"; let _ = format!("{xx}"); //~^ useless_format + + // Issue #3361: `&format!("literal")` should suggest the literal directly + let _: &str = &format!("hello"); //~ useless_format + let _: &str = &format!("{{}}"); //~ useless_format + let _: &str = &format!(r"hello"); //~ useless_format + let _: &str = &format!(r#"world"#); //~ useless_format + let _: &str = &format!(r##"foo"##); //~ useless_format + let _: &str = &format!(r##"hello "\u{{007B}}""##); //~ useless_format + // Only immutable borrows: `&mut format!` is not handled + let _: &mut String = &mut format!("hello"); //~ useless_format + + fn literal(lit: &str) {} + literal(&format!("hello")); //~ useless_format + literal(&&format!("hello")); //~ useless_format + + let lit = "hello"; + literal(&format!("{}", lit)); //~ useless_format + literal(&format!("{lit}")); //~ useless_format } // `format!` as the tail expression of a block emitted by another macro diff --git a/tests/ui/format.stderr b/tests/ui/format.stderr index 964041d8e87d3..d166017ce1620 100644 --- a/tests/ui/format.stderr +++ b/tests/ui/format.stderr @@ -102,28 +102,94 @@ LL | let _ = format!("{xx}"); | ^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `xx.to_string()` error: useless use of `format!` - --> tests/ui/format.rs:130:27 + --> tests/ui/format.rs:103:19 + | +LL | let _: &str = &format!("hello"); + | ^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `"hello"` + +error: useless use of `format!` + --> tests/ui/format.rs:104:19 + | +LL | let _: &str = &format!("{{}}"); + | ^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `"{}"` + +error: useless use of `format!` + --> tests/ui/format.rs:105:19 + | +LL | let _: &str = &format!(r"hello"); + | ^^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `r"hello"` + +error: useless use of `format!` + --> tests/ui/format.rs:106:19 + | +LL | let _: &str = &format!(r#"world"#); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `r#"world"#` + +error: useless use of `format!` + --> tests/ui/format.rs:107:19 + | +LL | let _: &str = &format!(r##"foo"##); + | ^^^^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `r##"foo"##` + +error: useless use of `format!` + --> tests/ui/format.rs:108:19 + | +LL | let _: &str = &format!(r##"hello "\u{{007B}}""##); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `r##"hello "\u{007B}""##` + +error: useless use of `format!` + --> tests/ui/format.rs:110:31 + | +LL | let _: &mut String = &mut format!("hello"); + | ^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `"hello".to_string()` + +error: useless use of `format!` + --> tests/ui/format.rs:113:13 + | +LL | literal(&format!("hello")); + | ^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `"hello"` + +error: useless use of `format!` + --> tests/ui/format.rs:114:14 + | +LL | literal(&&format!("hello")); + | ^^^^^^^^^^^^^^^^^ help: consider using the string literal directly: `"hello"` + +error: useless use of `format!` + --> tests/ui/format.rs:117:13 + | +LL | literal(&format!("{}", lit)); + | ^^^^^^^^^^^^^^^^^^^ help: consider using the argument directly: `lit` + +error: useless use of `format!` + --> tests/ui/format.rs:118:13 + | +LL | literal(&format!("{lit}")); + | ^^^^^^^^^^^^^^^^^ help: consider using the argument directly: `lit` + +error: useless use of `format!` + --> tests/ui/format.rs:148:27 | LL | let _ = plain_mr!(format!("{}", s())); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` error: useless use of `format!` - --> tests/ui/format.rs:132:27 + --> tests/ui/format.rs:150:27 | LL | let _ = block_mr!(format!("{}", s())); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` error: useless use of `format!` - --> tests/ui/format.rs:134:27 + --> tests/ui/format.rs:152:27 | LL | let _ = plain_dm!(format!("{}", s())); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` error: useless use of `format!` - --> tests/ui/format.rs:136:27 + --> tests/ui/format.rs:154:27 | LL | let _ = block_dm!(format!("{}", s())); | ^^^^^^^^^^^^^^^^^^ help: consider using `.to_string()`: `s().to_string()` -error: aborting due to 19 previous errors +error: aborting due to 30 previous errors diff --git a/tests/ui/integer_division_remainder_used.rs b/tests/ui/integer_division_remainder_used.rs index f8d303b04bfc8..2d5e82dbeadb6 100644 --- a/tests/ui/integer_division_remainder_used.rs +++ b/tests/ui/integer_division_remainder_used.rs @@ -1,3 +1,4 @@ +//@aux-build: proc_macros.rs #![warn(clippy::integer_division_remainder_used)] #![expect(clippy::op_ref)] @@ -53,4 +54,18 @@ fn main() { let w = CustomOps(3); let x = CustomOps(4); let z = w % x; + + macro_rules! mac { + ($a:expr, $b:expr) => { + $a % $b + //~^ integer_division_remainder_used + }; + } + // should not trigger if from expansion in external macro + let issue17048 = mac!(a, b); + let issue17048 = proc_macros::external! {{ + let a = 10; + let b = 5; + a % b + }}; } diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr index 84fa20020adc1..632df3e960c10 100644 --- a/tests/ui/integer_division_remainder_used.stderr +++ b/tests/ui/integer_division_remainder_used.stderr @@ -1,5 +1,5 @@ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:9:14 + --> tests/ui/integer_division_remainder_used.rs:10:14 | LL | Self(self.0 / rhs.0) | ^^^^^^^^^^^^^^ @@ -8,64 +8,75 @@ LL | Self(self.0 / rhs.0) = help: to override `-D warnings` add `#[allow(clippy::integer_division_remainder_used)]` error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:17:14 + --> tests/ui/integer_division_remainder_used.rs:18:14 | LL | Self(self.0 % rhs.0) | ^^^^^^^^^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:26:13 + --> tests/ui/integer_division_remainder_used.rs:27:13 | LL | let c = a / b; | ^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:28:13 + --> tests/ui/integer_division_remainder_used.rs:29:13 | LL | let d = a % b; | ^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:30:13 + --> tests/ui/integer_division_remainder_used.rs:31:13 | LL | let e = &a / b; | ^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:32:13 + --> tests/ui/integer_division_remainder_used.rs:33:13 | LL | let f = a % &b; | ^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:34:13 + --> tests/ui/integer_division_remainder_used.rs:35:13 | LL | let g = &a / &b; | ^^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:36:13 + --> tests/ui/integer_division_remainder_used.rs:37:13 | LL | let h = &10 % b; | ^^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:38:13 + --> tests/ui/integer_division_remainder_used.rs:39:13 | LL | let i = a / &4; | ^^^^^^ error: use of `/` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:43:5 + --> tests/ui/integer_division_remainder_used.rs:44:5 | LL | j /= 2; | ^^^^^^ error: use of `%` has been disallowed in this context - --> tests/ui/integer_division_remainder_used.rs:45:5 + --> tests/ui/integer_division_remainder_used.rs:46:5 | LL | j %= 3; | ^^^^^^ -error: aborting due to 11 previous errors +error: use of `%` has been disallowed in this context + --> tests/ui/integer_division_remainder_used.rs:60:13 + | +LL | $a % $b + | ^^^^^^^ +... +LL | let issue17048 = mac!(a, b); + | ---------- in this macro invocation + | + = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 12 previous errors diff --git a/tests/ui/map_clone.fixed b/tests/ui/map_clone.fixed index fbbd40756239c..908fa328ab24b 100644 --- a/tests/ui/map_clone.fixed +++ b/tests/ui/map_clone.fixed @@ -68,6 +68,14 @@ fn main() { let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone()); } + // Issue #17550 + { + let string = String::new(); + let input = [&string]; + let _: Vec = input.iter().map(|s: &&String| String::clone(s)).collect(); + let _: Vec = input.iter().map(|s: &&String| ::clone(s)).collect(); + } + let x = Some(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.cloned(); diff --git a/tests/ui/map_clone.rs b/tests/ui/map_clone.rs index 5004435cc8cfd..894d561e10a38 100644 --- a/tests/ui/map_clone.rs +++ b/tests/ui/map_clone.rs @@ -68,6 +68,14 @@ fn main() { let _ = Some(RefCell::new(String::new()).borrow()).map(|s| s.clone()); } + // Issue #17550 + { + let string = String::new(); + let input = [&string]; + let _: Vec = input.iter().map(|s: &&String| String::clone(s)).collect(); + let _: Vec = input.iter().map(|s: &&String| ::clone(s)).collect(); + } + let x = Some(String::new()); let x = x.as_ref(); // We do this to prevent triggering the `useless_asref` lint. let y = x.map(|x| String::clone(x)); diff --git a/tests/ui/map_clone.stderr b/tests/ui/map_clone.stderr index c739527ca5c24..e752fbb3476cc 100644 --- a/tests/ui/map_clone.stderr +++ b/tests/ui/map_clone.stderr @@ -38,55 +38,55 @@ LL | let _ = std::env::args().map(|v| v.clone()); | ^^^^^^^^^^^^^^^^^^^ help: remove the `map` call error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:73:13 + --> tests/ui/map_clone.rs:81:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:76:13 + --> tests/ui/map_clone.rs:84:13 | LL | let y = x.map(Clone::clone); | ^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:79:13 + --> tests/ui/map_clone.rs:87:13 | LL | let y = x.map(String::clone); | ^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:84:13 + --> tests/ui/map_clone.rs:92:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:87:13 + --> tests/ui/map_clone.rs:95:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:98:13 + --> tests/ui/map_clone.rs:106:13 | LL | let y = x.map(|x| String::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:101:13 + --> tests/ui/map_clone.rs:109:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `cloned` method: `x.cloned()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:106:13 + --> tests/ui/map_clone.rs:114:13 | LL | let y = x.map(|x| u32::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` error: you are explicitly cloning with `.map()` - --> tests/ui/map_clone.rs:109:13 + --> tests/ui/map_clone.rs:117:13 | LL | let y = x.map(|x| Clone::clone(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider calling the dedicated `copied` method: `x.copied()` diff --git a/tests/ui/map_unwrap_or_fixable.fixed b/tests/ui/map_unwrap_or_fixable.fixed index b92f02c4d6cbf..b9c177e695730 100644 --- a/tests/ui/map_unwrap_or_fixable.fixed +++ b/tests/ui/map_unwrap_or_fixable.fixed @@ -82,3 +82,47 @@ fn issue15713() { println!("{}", x.map_or_else(|_| 3, |y| y + 1)); //~^ map_unwrap_or } + +// Support `map(_).unwrap_or_default()` pattern +mod pr17644 { + macro_rules! identity { + // Inner bracket is necessary to detect macro expansion + ( $e:expr ) => {{ $e }}; + } + + #[clippy::msrv = "1.98"] + mod unwrap_or_default { + fn option(opt: Option) { + let _ = opt.map_or_default(|x| x * x); //~ map_unwrap_or + let _ = opt.map_or_default(|x| vec![x]); //~ map_unwrap_or + let _ = identity!(opt.map_or_default(|x| x + 1)); //~ map_unwrap_or + let _ = identity!(opt.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(opt).map(|x| x + 1).unwrap_or_default(); + } + fn result(res: Result) { + let _ = res.map_or_default(|x| x * x); //~ map_unwrap_or + let _ = res.map_or_default(|x| vec![x]); //~ map_unwrap_or + let _ = identity!(res.map_or_default(|x| x + 1)); //~ map_unwrap_or + let _ = identity!(res.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(res).map(|x| x + 1).unwrap_or_default(); + } + } + + #[clippy::msrv = "1.97"] + mod unwrap_or_default_before_msrv { + fn option(opt: Option) { + let _ = opt.map(|x| x * x).unwrap_or_default(); + let _ = opt.map(|x| vec![x]).unwrap_or_default(); + let _ = identity!(opt.map(|x| x + 1).unwrap_or_default()); + let _ = identity!(opt.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(opt).map(|x| x + 1).unwrap_or_default(); + } + fn result(res: Result) { + let _ = res.map(|x| x * x).unwrap_or_default(); + let _ = res.map(|x| vec![x]).unwrap_or_default(); + let _ = identity!(res.map(|x| x + 1).unwrap_or_default()); + let _ = identity!(res.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(res).map(|x| x + 1).unwrap_or_default(); + } + } +} diff --git a/tests/ui/map_unwrap_or_fixable.rs b/tests/ui/map_unwrap_or_fixable.rs index b922b9e4bd358..54bee67db3317 100644 --- a/tests/ui/map_unwrap_or_fixable.rs +++ b/tests/ui/map_unwrap_or_fixable.rs @@ -88,3 +88,47 @@ fn issue15713() { println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); //~^ map_unwrap_or } + +// Support `map(_).unwrap_or_default()` pattern +mod pr17644 { + macro_rules! identity { + // Inner bracket is necessary to detect macro expansion + ( $e:expr ) => {{ $e }}; + } + + #[clippy::msrv = "1.98"] + mod unwrap_or_default { + fn option(opt: Option) { + let _ = opt.map(|x| x * x).unwrap_or_default(); //~ map_unwrap_or + let _ = opt.map(|x| vec![x]).unwrap_or_default(); //~ map_unwrap_or + let _ = identity!(opt.map(|x| x + 1).unwrap_or_default()); //~ map_unwrap_or + let _ = identity!(opt.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(opt).map(|x| x + 1).unwrap_or_default(); + } + fn result(res: Result) { + let _ = res.map(|x| x * x).unwrap_or_default(); //~ map_unwrap_or + let _ = res.map(|x| vec![x]).unwrap_or_default(); //~ map_unwrap_or + let _ = identity!(res.map(|x| x + 1).unwrap_or_default()); //~ map_unwrap_or + let _ = identity!(res.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(res).map(|x| x + 1).unwrap_or_default(); + } + } + + #[clippy::msrv = "1.97"] + mod unwrap_or_default_before_msrv { + fn option(opt: Option) { + let _ = opt.map(|x| x * x).unwrap_or_default(); + let _ = opt.map(|x| vec![x]).unwrap_or_default(); + let _ = identity!(opt.map(|x| x + 1).unwrap_or_default()); + let _ = identity!(opt.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(opt).map(|x| x + 1).unwrap_or_default(); + } + fn result(res: Result) { + let _ = res.map(|x| x * x).unwrap_or_default(); + let _ = res.map(|x| vec![x]).unwrap_or_default(); + let _ = identity!(res.map(|x| x + 1).unwrap_or_default()); + let _ = identity!(res.map(|x| x + 1)).unwrap_or_default(); + let _ = identity!(res).map(|x| x + 1).unwrap_or_default(); + } + } +} diff --git a/tests/ui/map_unwrap_or_fixable.stderr b/tests/ui/map_unwrap_or_fixable.stderr index 325f75dd572be..d3c0267cf3d42 100644 --- a/tests/ui/map_unwrap_or_fixable.stderr +++ b/tests/ui/map_unwrap_or_fixable.stderr @@ -103,5 +103,77 @@ error: called `map().unwrap_or_else()` on a `Result` value LL | println!("{}", x.map(|y| y + 1).unwrap_or_else(|_| 3)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `x.map_or_else(|_| 3, |y| y + 1)` -error: aborting due to 11 previous errors +error: called `map(_).unwrap_or_default()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:102:21 + | +LL | let _ = opt.map(|x| x * x).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = opt.map(|x| x * x).unwrap_or_default(); +LL + let _ = opt.map_or_default(|x| x * x); + | + +error: called `map(_).unwrap_or_default()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:103:21 + | +LL | let _ = opt.map(|x| vec![x]).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = opt.map(|x| vec![x]).unwrap_or_default(); +LL + let _ = opt.map_or_default(|x| vec![x]); + | + +error: called `map(_).unwrap_or_default()` on an `Option` value + --> tests/ui/map_unwrap_or_fixable.rs:104:31 + | +LL | let _ = identity!(opt.map(|x| x + 1).unwrap_or_default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = identity!(opt.map(|x| x + 1).unwrap_or_default()); +LL + let _ = identity!(opt.map_or_default(|x| x + 1)); + | + +error: called `map(_).unwrap_or_default()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:109:21 + | +LL | let _ = res.map(|x| x * x).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = res.map(|x| x * x).unwrap_or_default(); +LL + let _ = res.map_or_default(|x| x * x); + | + +error: called `map(_).unwrap_or_default()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:110:21 + | +LL | let _ = res.map(|x| vec![x]).unwrap_or_default(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = res.map(|x| vec![x]).unwrap_or_default(); +LL + let _ = res.map_or_default(|x| vec![x]); + | + +error: called `map(_).unwrap_or_default()` on a `Result` value + --> tests/ui/map_unwrap_or_fixable.rs:111:31 + | +LL | let _ = identity!(res.map(|x| x + 1).unwrap_or_default()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: use instead + | +LL - let _ = identity!(res.map(|x| x + 1).unwrap_or_default()); +LL + let _ = identity!(res.map_or_default(|x| x + 1)); + | + +error: aborting due to 17 previous errors diff --git a/tests/ui/needless_pass_by_value.rs b/tests/ui/needless_pass_by_value.rs index d1a65e43e8100..e1e784c3b09a8 100644 --- a/tests/ui/needless_pass_by_value.rs +++ b/tests/ui/needless_pass_by_value.rs @@ -217,6 +217,8 @@ fn non_option_either(x: Opt) { dbg!(&x); } +fn issue_17664(#[allow(clippy::needless_pass_by_value)] sr: String) {} + fn main() { // This should not cause an ICE either // https://github.com/rust-lang/rust-clippy/issues/3144 diff --git a/tests/ui/regex.rs b/tests/ui/regex.rs index 2e28017ab1170..ac64486b2d01e 100644 --- a/tests/ui/regex.rs +++ b/tests/ui/regex.rs @@ -1,6 +1,6 @@ //@require-annotations-for-level: WARN #![warn(clippy::invalid_regex, clippy::regex_creation_in_loops, clippy::trivial_regex)] -#![expect(clippy::needless_borrows_for_generic_args)] +#![expect(clippy::needless_borrows_for_generic_args, clippy::never_loop)] extern crate regex; @@ -144,6 +144,112 @@ fn regex_creation_in_loops() { for i in 0..10 { let dependant_regex = Regex::new(&format!("{i}")); } + + // https://github.com/rust-lang/rust-clippy/issues/15484 + + fn issue_15484_break_noloop() { + loop { + let nested_regex = Regex::new("a.b.1"); + break; + } + } + + fn issue_15484_break_doublenest() { + loop { + loop { + let nested_regex = Regex::new("a.b.2"); + //~^ ERROR: compiling a regex in a loop + break; + } + } + } + + fn issue_15484_break_doublenest_print() { + loop { + println!("foo"); + loop { + let nested_regex = Regex::new("a.b.2"); + //~^ ERROR: compiling a regex in a loop + break; + } + } + } + + fn issue_15484_break_doublenest_fncall() { + loop { + regex_creation_in_loops(); + loop { + let nested_regex = Regex::new("a.b.2"); + //~^ ERROR: compiling a regex in a loop + break; + } + } + } + + // neither loop loops, so no lint + fn issue_15484_break_noloop_doublenest() { + 'outer: loop { + loop { + let nested_regex = Regex::new("a.b.3"); + break 'outer; + } + } + } + + // neither loop loops, so no lint + fn issue_15484_panic_noloop_doublenest() { + loop { + loop { + let nested_regex = Regex::new("a.b.4"); + panic!(); + } + } + } + + // the outer loop doesn't loop, but the inner loop does + fn issue_15484_panic_doublenest() { + loop { + loop { + let nested_regex = Regex::new("a.b.5"); + //~^ ERROR: compiling a regex in a loop + } + panic!(); + } + } + + fn issue_15484_continue_doublenest() { + loop { + loop { + let nested_regex = Regex::new("a.b.6"); + //~^ ERROR: compiling a regex in a loop + continue; + } + } + } + + fn issue_15484_continue_outer_doublenest() { + 'outer: loop { + regex_creation_in_loops(); + loop { + let nested_regex = Regex::new("a.b.6"); + //~^ ERROR: compiling a regex in a loop + continue 'outer; + } + } + } + + fn issue_15484_if() { + loop { + if true { + let nested_regex = Regex::new("a.b.6"); + //~^ ERROR: compiling a regex in a loop + if true { + continue; + } + break; + } + } + } } fn main() {} diff --git a/tests/ui/regex.stderr b/tests/ui/regex.stderr index 159e55baafb51..8240b08eebaf5 100644 --- a/tests/ui/regex.stderr +++ b/tests/ui/regex.stderr @@ -245,5 +245,89 @@ help: move the regex construction outside this loop LL | for _ in 0..10 { | ^^^^^^^^^^^^^^ -error: aborting due to 28 previous errors +error: compiling a regex in a loop + --> tests/ui/regex.rs:160:36 + | +LL | let nested_regex = Regex::new("a.b.2"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:159:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:171:36 + | +LL | let nested_regex = Regex::new("a.b.2"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:170:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:182:36 + | +LL | let nested_regex = Regex::new("a.b.2"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:181:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:213:36 + | +LL | let nested_regex = Regex::new("a.b.5"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:212:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:223:36 + | +LL | let nested_regex = Regex::new("a.b.6"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:222:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:234:36 + | +LL | let nested_regex = Regex::new("a.b.6"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:233:13 + | +LL | loop { + | ^^^^ + +error: compiling a regex in a loop + --> tests/ui/regex.rs:244:36 + | +LL | let nested_regex = Regex::new("a.b.6"); + | ^^^^^^^^^^ + | +help: move the regex construction outside this loop + --> tests/ui/regex.rs:242:9 + | +LL | loop { + | ^^^^ + +error: aborting due to 35 previous errors diff --git a/tests/ui/std_instead_of_core.fixed b/tests/ui/std_instead_of_core.fixed index 63d0e204d72fd..c162dcb0451e2 100644 --- a/tests/ui/std_instead_of_core.fixed +++ b/tests/ui/std_instead_of_core.fixed @@ -115,3 +115,17 @@ fn issue13158_msrv_1_80(_: &dyn std::error::Error) {} #[clippy::msrv = "1.81"] fn issue13158_msrv_1_81(_: &dyn core::error::Error) {} //~^ std_instead_of_core + +fn issue17602() { + // `Bound` is defined in `core::ops` and only reachable from `std::collections` through a + // legacy re-export, so replacing `std` with `core` would name a module that does not exist. + use std::collections::Bound; + use std::collections::Bound::{Excluded, Included}; + + // The very same items are still linted through the path they are actually defined at, both + // as a type and as a value. + use core::ops::Bound as OpsBound; + //~^ std_instead_of_core + use core::ops::Bound::Unbounded; + //~^ std_instead_of_core +} diff --git a/tests/ui/std_instead_of_core.rs b/tests/ui/std_instead_of_core.rs index e5cde188bedd7..6769af11def6f 100644 --- a/tests/ui/std_instead_of_core.rs +++ b/tests/ui/std_instead_of_core.rs @@ -115,3 +115,17 @@ fn issue13158_msrv_1_80(_: &dyn std::error::Error) {} #[clippy::msrv = "1.81"] fn issue13158_msrv_1_81(_: &dyn std::error::Error) {} //~^ std_instead_of_core + +fn issue17602() { + // `Bound` is defined in `core::ops` and only reachable from `std::collections` through a + // legacy re-export, so replacing `std` with `core` would name a module that does not exist. + use std::collections::Bound; + use std::collections::Bound::{Excluded, Included}; + + // The very same items are still linted through the path they are actually defined at, both + // as a type and as a value. + use std::ops::Bound as OpsBound; + //~^ std_instead_of_core + use std::ops::Bound::Unbounded; + //~^ std_instead_of_core +} diff --git a/tests/ui/std_instead_of_core.stderr b/tests/ui/std_instead_of_core.stderr index 7045d44482114..ae0783863fbc2 100644 --- a/tests/ui/std_instead_of_core.stderr +++ b/tests/ui/std_instead_of_core.stderr @@ -109,5 +109,17 @@ error: used import from `std` instead of `core` LL | fn issue13158_msrv_1_81(_: &dyn std::error::Error) {} | ^^^ help: consider importing the item from `core`: `core` -error: aborting due to 17 previous errors +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core.rs:127:9 + | +LL | use std::ops::Bound as OpsBound; + | ^^^ help: consider importing the item from `core`: `core` + +error: used import from `std` instead of `core` + --> tests/ui/std_instead_of_core.rs:129:9 + | +LL | use std::ops::Bound::Unbounded; + | ^^^ help: consider importing the item from `core`: `core` + +error: aborting due to 19 previous errors diff --git a/tests/ui/swap.fixed b/tests/ui/swap.fixed index 98f2d0c746030..baefdaf3d9261 100644 --- a/tests/ui/swap.fixed +++ b/tests/ui/swap.fixed @@ -175,7 +175,8 @@ fn issue_8154() { std::mem::swap(&mut s.0.x, &mut s.0.y); } -const fn issue_9864(mut u: u32) -> u32 { +#[clippy::msrv = "1.84"] +const fn const_swap_msrv_too_low(mut u: u32) -> u32 { let mut v = 10; let temp = u; @@ -184,6 +185,14 @@ const fn issue_9864(mut u: u32) -> u32 { u + v } +#[clippy::msrv = "1.85"] +const fn const_swap_msrv_met(mut u: u32) -> u32 { + let mut v = 10; + + std::mem::swap(&mut u, &mut v); + u + v +} + #[macro_use] extern crate macro_rules; diff --git a/tests/ui/swap.rs b/tests/ui/swap.rs index a37753a007941..9c89bd61d924e 100644 --- a/tests/ui/swap.rs +++ b/tests/ui/swap.rs @@ -221,7 +221,8 @@ fn issue_8154() { s.0.y = t; } -const fn issue_9864(mut u: u32) -> u32 { +#[clippy::msrv = "1.84"] +const fn const_swap_msrv_too_low(mut u: u32) -> u32 { let mut v = 10; let temp = u; @@ -230,6 +231,17 @@ const fn issue_9864(mut u: u32) -> u32 { u + v } +#[clippy::msrv = "1.85"] +const fn const_swap_msrv_met(mut u: u32) -> u32 { + let mut v = 10; + + let temp = u; + //~^ manual_swap + u = v; + v = temp; + u + v +} + #[macro_use] extern crate macro_rules; diff --git a/tests/ui/swap.stderr b/tests/ui/swap.stderr index 1fd1737d7aafd..371a6c774893c 100644 --- a/tests/ui/swap.stderr +++ b/tests/ui/swap.stderr @@ -174,8 +174,19 @@ LL | | s.0.y = t; | = note: or maybe you should use `std::mem::replace`? +error: this looks like you are swapping `u` and `v` manually + --> tests/ui/swap.rs:238:5 + | +LL | / let temp = u; +LL | | +LL | | u = v; +LL | | v = temp; + | |_____________^ help: try: `std::mem::swap(&mut u, &mut v);` + | + = note: or maybe you should use `std::mem::replace`? + error: this looks like you are swapping elements of `test_slice!(foo)` manually - --> tests/ui/swap.rs:252:5 + --> tests/ui/swap.rs:264:5 | LL | / let temp = test_slice!(foo)[0]; LL | | @@ -183,5 +194,5 @@ LL | | test_slice!(foo)[0] = test_slice!(foo)[1]; LL | | test_slice!(foo)[1] = temp; | |_______________________________^ help: try: `test_slice!(foo).swap(0, 1);` -error: aborting due to 18 previous errors +error: aborting due to 19 previous errors diff --git a/tests/ui/useless_conversion.fixed b/tests/ui/useless_conversion.fixed index a0759f9b0efeb..b8315ba3a32d0 100644 --- a/tests/ui/useless_conversion.fixed +++ b/tests/ui/useless_conversion.fixed @@ -501,3 +501,43 @@ fn after_question_mark() -> Result<(), ()> { //~^ useless_conversion Ok(()) } + +mod issue17083 { + trait FromU32: From {} + + trait HasType { + type Type: FromU32; + } + + trait HasNestedType { + type Type: HasType; + } + + trait CanWrite + where + Self: HasNestedType, + { + fn write(output: &mut <::Type as HasType>::Type); + } + + enum Test { + Add(T), + } + + impl HasNestedType for Test + where + T: HasType, + { + type Type = T; + } + + #[automatically_derived] + impl CanWrite for Test + where + T: HasType, + { + fn write(output: &mut T::Type) { + *output = !T::Type::from(1u32); + } + } +} diff --git a/tests/ui/useless_conversion.rs b/tests/ui/useless_conversion.rs index b070dfca32414..01056b628151d 100644 --- a/tests/ui/useless_conversion.rs +++ b/tests/ui/useless_conversion.rs @@ -501,3 +501,43 @@ fn after_question_mark() -> Result<(), ()> { //~^ useless_conversion Ok(()) } + +mod issue17083 { + trait FromU32: From {} + + trait HasType { + type Type: FromU32; + } + + trait HasNestedType { + type Type: HasType; + } + + trait CanWrite + where + Self: HasNestedType, + { + fn write(output: &mut <::Type as HasType>::Type); + } + + enum Test { + Add(T), + } + + impl HasNestedType for Test + where + T: HasType, + { + type Type = T; + } + + #[automatically_derived] + impl CanWrite for Test + where + T: HasType, + { + fn write(output: &mut T::Type) { + *output = !T::Type::from(1u32); + } + } +} diff --git a/triagebot.toml b/triagebot.toml index 69b9a7e54200a..822f5e7c12625 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1,7 +1,7 @@ [relabel] allow-unauthenticated = [ "A-*", "C-*", "D-*", "E-*", "I-*", "L-*", "P-*", "S-*", "T-*", - "good first issue", "beta-nominated" + "good first issue", "beta-nominated", "llm-assisted" ] # Allows shortcuts like `@rustbot ready` @@ -98,7 +98,6 @@ users_on_vacation = [ "Alexendoo", "y21", "ada4a", - "samueltardieu" ] [assign.owners] From 71ef655c92f036d6136bb1788eb26d00e67d3eae Mon Sep 17 00:00:00 2001 From: ltdk Date: Tue, 15 Sep 2026 23:59:29 -0400 Subject: [PATCH 0278/1309] Dedicated Display type for CStr::display --- library/core/src/ffi/c_str.rs | 42 +++++++++++++++++++++++++++++++++-- library/std/src/ffi/c_str.rs | 2 ++ 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index e5b1f8088a5bf..c2834fc603710 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -651,8 +651,8 @@ impl CStr { #[must_use = "this does not display the `CStr`; \ it returns an object that can be displayed"] #[inline] - pub fn display(&self) -> impl fmt::Display { - crate::bstr::ByteStr::from_bytes(self.to_bytes()) + pub fn display(&self) -> Display<'_> { + Display { c_str: self } } /// Returns the same string as a string slice `&CStr`. @@ -847,3 +847,41 @@ impl Iterator for Bytes<'_> { #[unstable(feature = "cstr_bytes", issue = "112115")] impl FusedIterator for Bytes<'_> {} + +/// Helper struct for safely printing a [`CStr`] with [`format!`] and `{}`. +/// +/// A [`CStr`] might contain non-Unicode data. This `struct` implements the +/// [`Display`] trait in a way that mitigates that. It is created by the +/// [`display`](CStr::display) method on [`CStr`]. This may perform lossy +/// conversion, depending on the platform. If you would like an implementation +/// which escapes the [`CStr`] please use [`Debug`] instead. +/// +/// # Examples +/// +/// ``` +/// #![feature(cstr_display)] +/// +/// let s = c"Hello, world!"; +/// println!("{}", s.display()); +/// ``` +/// +/// [`Display`]: fmt::Display +/// [`format!`]: ../../../std/macro.format.html +#[unstable(feature = "cstr_display", issue = "139984")] +pub struct Display<'a> { + c_str: &'a CStr, +} + +#[unstable(feature = "cstr_display", issue = "139984")] +impl fmt::Debug for Display<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&self.c_str, f) + } +} + +#[unstable(feature = "cstr_display", issue = "139984")] +impl fmt::Display for Display<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Display::fmt(crate::bstr::ByteStr::from_bytes(self.c_str.to_bytes()), f) + } +} diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index cb0ca5d1376ea..9c3a6758929a8 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -8,6 +8,8 @@ pub use alloc::ffi::c_str::IntoStringError; pub use alloc::ffi::c_str::{CString, NulError}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ffi::c_str::CStr; +#[unstable(feature = "cstr_display", issue = "139984")] +pub use core::ffi::c_str::Display; #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] pub use core::ffi::c_str::FromBytesUntilNulError; #[stable(feature = "cstr_from_bytes", since = "1.10.0")] From a51fdcba5bfb2d2234e7d90c8d585a324f5f7ad1 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 15 Sep 2026 19:59:19 +0000 Subject: [PATCH 0279/1309] micro cleanups --- .../src/deriving/generic/mod.rs | 26 +++++++++---------- 1 file changed, 12 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 599c8e7feab43..dabf303286de6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -774,6 +774,7 @@ impl<'a> TraitDef<'a> { // Other crates don't need stability attributes, so adding them is not useful, but libcore needs them // on all const trait impls. if self.is_const && cx.ecfg.features.staged_api() { + // #[rustc_const_unstable(feature = "derive_const", issue = "118304")] attrs.push( cx.attr_nested( rustc_ast::AttrItem { @@ -1195,24 +1196,21 @@ impl<'a> MethodDef<'a> { // let __self_discr = ::core::intrinsics::discriminant_value(self); // let __arg1_discr = ::core::intrinsics::discriminant_value(other); // ``` - let get_discr_pieces = |cx: &ExtCtxt<'_>| { - let discr_idents: Vec<_> = prefixes + let get_discr_pieces = || { + let discr_idents = prefixes .iter() - .map(|name| Ident::from_str_and_span(&format!("{name}_discr"), span)) - .collect(); + .map(|name| Ident::from_str_and_span(&format!("{name}_discr"), span)); - let mut discr_exprs: Vec<_> = discr_idents - .iter() - .map(|&ident| cx.expr_addr_of(span, cx.expr_ident(span, ident))) - .collect(); + let mut discr_exprs = + discr_idents.clone().map(|ident| cx.expr_addr_of(span, cx.expr_ident(span, ident))); - let self_expr = discr_exprs.remove(0); - let other_selflike_exprs = discr_exprs; + let self_expr = discr_exprs.next().unwrap(); + let other_selflike_exprs = discr_exprs.collect(); let discr_field = FieldInfo { span, name: None, self_expr, other_selflike_exprs, maybe_scalar: true }; - let discr_let_stmts: ThinVec<_> = iter::zip(&discr_idents, &selflike_args) - .map(|(&ident, selflike_arg)| { + let discr_let_stmts: ThinVec<_> = iter::zip(discr_idents, &selflike_args) + .map(|(ident, selflike_arg)| { let variant_value = deriving::call_intrinsic( cx, span, @@ -1236,7 +1234,7 @@ impl<'a> MethodDef<'a> { // If the type is fieldless and the trait uses the discriminant and // there are multiple variants, we need just an operation on // the discriminant(s). - let (discr_field, mut discr_let_stmts) = get_discr_pieces(cx); + let (discr_field, mut discr_let_stmts) = get_discr_pieces(); let mut discr_check = self.call_substructure_method( cx, trait_, @@ -1371,7 +1369,7 @@ impl<'a> MethodDef<'a> { // to add a discriminant check operation before the match. Otherwise, the match // is enough. if unify_fieldless_variants && variants.len() > 1 { - let (discr_field, mut discr_let_stmts) = get_discr_pieces(cx); + let (discr_field, mut discr_let_stmts) = get_discr_pieces(); // Combine a discriminant check with the match. let mut discr_check_plus_match = self.call_substructure_method( From 08961a71843ad57290bf38f612d17499a286d3ca Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 16 Sep 2026 21:23:52 +0000 Subject: [PATCH 0280/1309] remove `use_foldl` arg --- .../src/deriving/generic/mod.rs | 14 +- .../rustc_builtin_macros/src/deriving/ord.rs | 39 +++--- .../src/deriving/partial_ord.rs | 120 ++++++++---------- 3 files changed, 73 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index dabf303286de6..8789220893c2b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1537,8 +1537,7 @@ pub(crate) enum CsFold { /// Folds over fields, combining the expressions for each field in a sequence. /// Statics may not be folded over. -pub(crate) fn cs_fold( - use_foldl: bool, +pub(crate) fn cs_foldr( cx: &ExtCtxt<'_>, trait_span: Span, substructure: Substructure<'_>, @@ -1550,8 +1549,7 @@ where match substructure.fields { EnumMatching(.., all_fields) | Struct(_, all_fields) => { let mut fields = all_fields.into_iter(); - - let base_field = if use_foldl { fields.next() } else { fields.next_back() }; + let base_field = fields.next_back(); let Some(base_field) = base_field else { return f(cx, CsFold::Fieldless); @@ -1565,16 +1563,12 @@ where f(cx, CsFold::Combine(span, old, new)) }; - if use_foldl { fields.fold(base_expr, op) } else { fields.rfold(base_expr, op) } + fields.rfold(base_expr, op) } EnumDiscr(discr_field, match_expr) => { let discr_check_expr = f(cx, CsFold::Single(discr_field)); if let Some(match_expr) = match_expr { - if use_foldl { - f(cx, CsFold::Combine(trait_span, discr_check_expr, match_expr)) - } else { - f(cx, CsFold::Combine(trait_span, match_expr, discr_check_expr)) - } + f(cx, CsFold::Combine(trait_span, match_expr, discr_check_expr)) } else { discr_check_expr } diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 3c2d95a299a51..feaee242586df 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -52,29 +52,20 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> // ::core::cmp::Ord::cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_fold( - // foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - cx, - span, - substr, - |cx, fold| match fold { - CsFold::Single(field) => { - let [other_expr] = &field.other_selflike_exprs[..] else { - cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); - }; - let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; - cx.expr_call_global(field.span, cmp_path.clone(), args) - } - CsFold::Combine(span, expr1, expr2) => { - let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); - let neq_arm = - cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) - } - CsFold::Fieldless => cx.expr_path(equal_path.clone()), - }, - ); + let expr = cs_foldr(cx, span, substr, |cx, fold| match fold { + CsFold::Single(field) => { + let [other_expr] = &field.other_selflike_exprs[..] else { + cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); + }; + let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; + cx.expr_call_global(field.span, cmp_path.clone(), args) + } + CsFold::Combine(span, expr1, expr2) => { + let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); + let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); + cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) + } + CsFold::Fieldless => cx.expr_path(equal_path.clone()), + }); BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index fe5e48b11367d..abf681cb59b38 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -124,73 +124,61 @@ fn cs_partial_cmp( // ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_fold( - // foldr nests the if-elses correctly, leaving the first field - // as the outermost one, and the last as the innermost. - false, - cx, - span, - substr, - |cx, fold| match fold { - CsFold::Single(field) => { - let [other_expr] = &field.other_selflike_exprs[..] else { - cx.dcx() - .span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`"); - }; - let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; - cx.expr_call_global(field.span, partial_cmp_path.clone(), args) - } - CsFold::Combine(span, mut expr1, expr2) => { - // When the item is an enum, this expands to - // ``` - // match (expr2) { - // Some(Ordering::Equal) => expr1, - // cmp => cmp - // } - // ``` - // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` - // against the enum variants. This means that we begin by comparing the enum discriminants, - // before either inspecting their contents (if they match), or returning - // the `cmp::Ordering` of comparing the enum discriminants. - // ``` - // match partial_cmp(self_discr, other_discr) { - // Some(Ordering::Equal) => match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), - // _ => Some(Ordering::Equal) - // } - // cmp => cmp - // } - // ``` - // If we have any certain enum layouts, flipping this results in better codegen - // ``` - // match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // _ => partial_cmp(self_discr, other_discr) - // } - // ``` - // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 + let expr = cs_foldr(cx, span, substr, |cx, fold| match fold { + CsFold::Single(field) => { + let [other_expr] = &field.other_selflike_exprs[..] else { + cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`"); + }; + let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; + cx.expr_call_global(field.span, partial_cmp_path.clone(), args) + } + CsFold::Combine(span, mut expr1, expr2) => { + // When the item is an enum, this expands to + // ``` + // match (expr2) { + // Some(Ordering::Equal) => expr1, + // cmp => cmp + // } + // ``` + // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` + // against the enum variants. This means that we begin by comparing the enum discriminants, + // before either inspecting their contents (if they match), or returning + // the `cmp::Ordering` of comparing the enum discriminants. + // ``` + // match partial_cmp(self_discr, other_discr) { + // Some(Ordering::Equal) => match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), + // _ => Some(Ordering::Equal) + // } + // cmp => cmp + // } + // ``` + // If we have any certain enum layouts, flipping this results in better codegen + // ``` + // match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // _ => partial_cmp(self_discr, other_discr) + // } + // ``` + // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 - if !discr_then_data - && let ExprKind::Match(_, arms, _) = &mut expr1.kind - && let Some(last) = arms.last_mut() - && let PatKind::Wild = last.pat.kind - { - last.body = Some(expr2); - expr1 - } else { - let eq_arm = cx.arm( - span, - cx.pat_some(span, cx.pat_path(span, equal_path.clone())), - expr1, - ); - let neq_arm = - cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) - } + if !discr_then_data + && let ExprKind::Match(_, arms, _) = &mut expr1.kind + && let Some(last) = arms.last_mut() + && let PatKind::Wild = last.pat.kind + { + last.body = Some(expr2); + expr1 + } else { + let eq_arm = + cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1); + let neq_arm = + cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); + cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) } - CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())), - }, - ); + } + CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())), + }); BlockOrExpr::new_expr(expr) } From b6d07600e9fc80feeeb483aaa0d27df2dff224f8 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Wed, 16 Sep 2026 21:40:03 +0000 Subject: [PATCH 0281/1309] split the `cs_fold` closure into three subclosures --- .../src/deriving/generic/mod.rs | 44 +++++++------------ .../rustc_builtin_macros/src/deriving/ord.rs | 17 ++++--- .../src/deriving/partial_ord.rs | 17 ++++--- 3 files changed, 36 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8789220893c2b..8aa2180cf235b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1519,56 +1519,44 @@ impl<'a> TraitDef<'a> { } } -/// The function passed to `cs_fold` is called repeatedly with a value of this -/// type. It describes one part of the code generation. The result is always an -/// expression. -pub(crate) enum CsFold { - /// The basic case: a field expression for one or more selflike args. E.g. - /// for `PartialEq::eq` this is something like `self.x == other.x`. - Single(FieldInfo), - - /// The combination of two field expressions. E.g. for `PartialEq::eq` this - /// is something like ` && `. - Combine(Span, Box, Box), - - // The fallback case for a struct or enum variant with no fields. - Fieldless, -} - /// Folds over fields, combining the expressions for each field in a sequence. /// Statics may not be folded over. -pub(crate) fn cs_foldr( +pub(crate) fn cs_foldr( cx: &ExtCtxt<'_>, trait_span: Span, substructure: Substructure<'_>, - mut f: F, -) -> Box -where - F: FnMut(&ExtCtxt<'_>, CsFold) -> Box, -{ + // The basic case: a field expression for one or more selflike args. E.g. + // for `PartialEq::eq` this is something like `self.x == other.x`. + single: impl Fn(FieldInfo) -> Box, + // The combination of two field expressions. E.g. for `PartialEq::eq` this + // is something like ` && `. + combine: impl Fn(Span, Box, Box) -> Box, + // The fallback case for a struct or enum variant with no fields. + fieldless: impl Fn() -> Box, +) -> Box { match substructure.fields { EnumMatching(.., all_fields) | Struct(_, all_fields) => { let mut fields = all_fields.into_iter(); let base_field = fields.next_back(); let Some(base_field) = base_field else { - return f(cx, CsFold::Fieldless); + return fieldless(); }; - let base_expr = f(cx, CsFold::Single(base_field)); + let base_expr = single(base_field); let op = |old, field: FieldInfo| { let span = field.span; - let new = f(cx, CsFold::Single(field)); - f(cx, CsFold::Combine(span, old, new)) + let new = single(field); + combine(span, old, new) }; fields.rfold(base_expr, op) } EnumDiscr(discr_field, match_expr) => { - let discr_check_expr = f(cx, CsFold::Single(discr_field)); + let discr_check_expr = single(discr_field); if let Some(match_expr) = match_expr { - f(cx, CsFold::Combine(trait_span, match_expr, discr_check_expr)) + combine(trait_span, match_expr, discr_check_expr) } else { discr_check_expr } diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index feaee242586df..663e9b86a9ebe 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -52,20 +52,23 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> // ::core::cmp::Ord::cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr(cx, span, substr, |cx, fold| match fold { - CsFold::Single(field) => { + let expr = cs_foldr( + cx, + span, + substr, + |field| { let [other_expr] = &field.other_selflike_exprs[..] else { cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); }; let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; cx.expr_call_global(field.span, cmp_path.clone(), args) - } - CsFold::Combine(span, expr1, expr2) => { + }, + |span, expr1, expr2| { let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); let neq_arm = cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) - } - CsFold::Fieldless => cx.expr_path(equal_path.clone()), - }); + }, + || cx.expr_path(equal_path.clone()), + ); BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index abf681cb59b38..8c1d89da6ab30 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -124,15 +124,18 @@ fn cs_partial_cmp( // ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr(cx, span, substr, |cx, fold| match fold { - CsFold::Single(field) => { + let expr = cs_foldr( + cx, + span, + substr, + |field| { let [other_expr] = &field.other_selflike_exprs[..] else { cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`"); }; let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; cx.expr_call_global(field.span, partial_cmp_path.clone(), args) - } - CsFold::Combine(span, mut expr1, expr2) => { + }, + |span, mut expr1, expr2| { // When the item is an enum, this expands to // ``` // match (expr2) { @@ -177,8 +180,8 @@ fn cs_partial_cmp( cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) } - } - CsFold::Fieldless => cx.expr_some(span, cx.expr_path(equal_path.clone())), - }); + }, + || cx.expr_some(span, cx.expr_path(equal_path.clone())), + ); BlockOrExpr::new_expr(expr) } From 8ca7a1c20c1f068a3189757240fc9ad06ab3fa07 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 17 Sep 2026 13:46:41 +0000 Subject: [PATCH 0282/1309] stop passing `explicit_self` around --- .../src/deriving/generic/mod.rs | 42 ++++++------------- 1 file changed, 13 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8aa2180cf235b..bcf01bf33a94e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -839,7 +839,7 @@ impl<'a> TraitDef<'a> { let field_tys = struct_def.fields().iter().map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } = + let ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } = method_def.extract_arg_details(cx, self, type_ident, generics); let body = if from_scratch || method_def.is_static() { @@ -862,15 +862,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method( - cx, - self, - type_ident, - generics, - explicit_self, - nonself_arg_tys, - body, - ) + method_def.create_method(cx, self, type_ident, generics, nonself_arg_tys, body) }); self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) @@ -891,7 +883,7 @@ impl<'a> TraitDef<'a> { .map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } = + let ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } = method_def.extract_arg_details(cx, self, type_ident, generics); let body = if from_scratch || method_def.is_static() { @@ -913,15 +905,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method( - cx, - self, - type_ident, - generics, - explicit_self, - nonself_arg_tys, - body, - ) + method_def.create_method(cx, self, type_ident, generics, nonself_arg_tys, body) }); let is_packed = false; // enums are never packed @@ -930,8 +914,6 @@ impl<'a> TraitDef<'a> { } struct ArgDetails { - /// The `&self` arg, if present. - explicit_self: Option, /// Expressions for `&self` (if present) and also any other /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). selflike_args: ThinVec>, @@ -972,11 +954,10 @@ impl<'a> MethodDef<'a> { let mut nonself_arg_tys = Vec::new(); let span = trait_.span; - let explicit_self = self.explicit_self.then(|| { + if self.explicit_self { // This constructs a fresh `self` path. selflike_args.push(cx.expr_self(span)); - respan(span, SelfKind::Region(None, ast::Mutability::Not)) - }); + } for (ty, name) in self.nonself_args.iter() { let ast_ty = ty.to_ty(cx, span, type_ident, generics); @@ -993,7 +974,7 @@ impl<'a> MethodDef<'a> { } } - ArgDetails { explicit_self, selflike_args, nonselflike_args, nonself_arg_tys } + ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } } fn create_method( @@ -1002,7 +983,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - explicit_self: Option, nonself_arg_tys: Vec<(Ident, Box)>, body: BlockOrExpr, ) -> Option> { @@ -1015,9 +995,13 @@ impl<'a> MethodDef<'a> { let fn_generics = self.generics.clone(); let args = { - let self_arg = explicit_self.map(|explicit_self| { + let self_arg = self.explicit_self.then(|| { let ident = Ident::new(kw::SelfLower, span); - ast::Param::from_self(ast::AttrVec::default(), explicit_self, ident) + ast::Param::from_self( + ast::AttrVec::default(), + respan(span, SelfKind::Region(None, ast::Mutability::Not)), + ident, + ) }); let nonself_args = nonself_arg_tys.into_iter().map(|(name, ty)| cx.param(span, name, ty)); From e9a87d0f7bcc2e6fc2ab2f687e2e6e2c1697fa49 Mon Sep 17 00:00:00 2001 From: Lucas Sunsi Abreu Date: Thu, 17 Sep 2026 11:03:37 -0300 Subject: [PATCH 0283/1309] Add regression test for ambiguous trait with mixed import ids Co-authored-by: Philip Sampaio --- ...ambiguous-trait-with-mixed-import-paths.rs | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs diff --git a/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs new file mode 100644 index 0000000000000..acc97a2491f8e --- /dev/null +++ b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs @@ -0,0 +1,27 @@ +//! Regression test for . +//@ check-pass + +mod vis1 { + pub trait Visitor { + fn visit_b(&self); + fn visit_c(&self); + } +} + +mod vis2 { + pub trait Visitor {} +} + +use crate::{vis1::*, vis2::*}; + +pub struct Impl; + +impl vis1::Visitor for Impl { + fn visit_b(&self) {} + + fn visit_c(&self) { + self.visit_b(); + } +} + +fn main() {} From fff83c5b50993856835be07dda1e262c322af6f3 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Thu, 17 Sep 2026 17:47:51 +0000 Subject: [PATCH 0284/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to c999cef531ea9059e189e82fe0e82c5daf249bc9. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index f7d3ea0b9325b..7c357c0e50e54 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -4b6d04e706108ccfeafe2547fbe857dfe8972bad +c999cef531ea9059e189e82fe0e82c5daf249bc9 From a73d5f1e50ee9facb776e4a9ad4019a32092be0a Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 17 Sep 2026 15:00:53 -0400 Subject: [PATCH 0285/1309] Add regression test for recursive type bug found a while ago when compiling Rust for Linux --- tests/compile/recursive_types.rs | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 tests/compile/recursive_types.rs diff --git a/tests/compile/recursive_types.rs b/tests/compile/recursive_types.rs new file mode 100644 index 0000000000000..3c69074887f3e --- /dev/null +++ b/tests/compile/recursive_types.rs @@ -0,0 +1,22 @@ +// Compiler: + +// `Set` reaches itself by value through `*mut Root`, so a backend that emits `Root`'s +// fields with the still-incomplete `Set` type fails to compile this. + +#![crate_type = "lib"] + +#[repr(C)] +pub struct Set { + pub root: *mut Root, + pub first: usize, + pub second: usize, +} + +#[repr(C)] +pub struct Root { + pub default_set: Set, +} + +pub fn identity(set: Set) -> Set { + set +} From a998f8ad99af7991547c2d399cc2f014f58cfdc7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 17 Sep 2026 21:34:15 +0200 Subject: [PATCH 0286/1309] improve simd bitshift tests --- .../stdarch/crates/core_arch/src/x86/avx2.rs | 67 ++++++++++++++++--- 1 file changed, 56 insertions(+), 11 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/x86/avx2.rs b/library/stdarch/crates/core_arch/src/x86/avx2.rs index 333f38e5474cc..7ad45421cf89f 100644 --- a/library/stdarch/crates/core_arch/src/x86/avx2.rs +++ b/library/stdarch/crates/core_arch/src/x86/avx2.rs @@ -5142,10 +5142,24 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_sllv_epi64() { - let a = _mm_set1_epi64x(2); - let b = _mm_set1_epi64x(1); + let a = _mm_set_epi64x(2, 3); + let b = _mm_set_epi64x(1, 2); let r = _mm_sllv_epi64(a, b); - let e = _mm_set1_epi64x(4); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi64x(2i64.unbounded_shl(1), 3i64.unbounded_shl(2)); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi64x(4, 12); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is 0. + let a = _mm_set_epi64x(1, 2); + let b = _mm_set_epi64x(64, 65); + let r = _mm_sllv_epi64(a, b); + let e = _mm_set_epi64x(1i64.unbounded_shl(64), 2i64.unbounded_shl(65)); + assert_eq_m128i(r, e); + let e = _mm_set_epi64x(0, 0); assert_eq_m128i(r, e); } @@ -5192,10 +5206,27 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_srav_epi32() { - let a = _mm_set1_epi32(4); - let count = _mm_set1_epi32(1); - let r = _mm_srav_epi32(a, count); - let e = _mm_set1_epi32(2); + let a = _mm_set_epi32(16, -32, 64, -128); + let b = _mm_set_epi32(4, 3, 2, 1); + let r = _mm_srav_epi32(a, b); + let e = _mm_set_epi32(1, -4, 16, -64); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is -1. + let a = _mm_set_epi32(-16, -32, -64, -128); + let b = _mm_set_epi32(31, 32, 33, 0); + let r = _mm_srav_epi32(a, b); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi32( + (-16i32).unbounded_shr(31), + (-32i32).unbounded_shr(32), + (-64i32).unbounded_shr(33), + (-128i32).unbounded_shr(0), + ); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi32(-1, -1, -1, -128); assert_eq_m128i(r, e); } @@ -5296,10 +5327,24 @@ mod tests { #[simd_test(enable = "avx2")] fn test_mm_srlv_epi64() { - let a = _mm_set1_epi64x(2); - let count = _mm_set1_epi64x(1); - let r = _mm_srlv_epi64(a, count); - let e = _mm_set1_epi64x(1); + let a = _mm_set_epi64x(4, 8); + let b = _mm_set_epi64x(2, 1); + let r = _mm_srlv_epi64(a, b); + // Compare with the scalar version of the same computation. + let e = _mm_set_epi64x(4i64.unbounded_shr(2), 8i64.unbounded_shr(1)); + assert_eq_m128i(r, e); + // Compare with hardcoded output. + let e = _mm_set_epi64x(1, 4); + assert_eq_m128i(r, e); + + // The shift has unbounded semantics: if the shift amount + // is >= the number of bits the result is 0. + let a = _mm_set_epi64x(i64::MAX, i64::MAX); + let b = _mm_set_epi64x(64, 65); + let r = _mm_sllv_epi64(a, b); + let e = _mm_set_epi64x(i64::MAX.unbounded_shr(64), i64::MAX.unbounded_shr(65)); + assert_eq_m128i(r, e); + let e = _mm_set_epi64x(0, 0); assert_eq_m128i(r, e); } From 677806f9aeb5d0cf206aeffb3e164fd7b93d1b8a Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 21:01:31 +0100 Subject: [PATCH 0287/1309] Remove applying inline attributes at the callsite --- compiler/rustc_codegen_llvm/src/builder.rs | 15 ------- .../call-site-inline-attributes.rs | 40 ------------------- 2 files changed, 55 deletions(-) delete mode 100644 tests/codegen-llvm/call-site-inline-attributes.rs diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 9d4602e49968d..abc71f450a515 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -1523,21 +1523,6 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { ) }; - if let Some(callee_instance) = callee_instance { - // Attributes on the function definition being called - let callee_attrs = self.cx.tcx.codegen_fn_attrs(callee_instance.def_id()); - - if let Some(inlining_rule) = - attributes::inline_attr(&self.cx, self.cx.tcx, callee_instance, callee_attrs) - { - attributes::apply_to_callsite( - call, - llvm::AttributePlace::Function, - &[inlining_rule], - ); - } - } - if let Some(fn_abi) = fn_abi { fn_abi.apply_attrs_callsite(self, call); } diff --git a/tests/codegen-llvm/call-site-inline-attributes.rs b/tests/codegen-llvm/call-site-inline-attributes.rs deleted file mode 100644 index 01839526c50c1..0000000000000 --- a/tests/codegen-llvm/call-site-inline-attributes.rs +++ /dev/null @@ -1,40 +0,0 @@ -//@ compile-flags: -O -Zinline-mir=no -Cno-prepopulate-passes -Zmerge-functions=disabled - -#![crate_type = "lib"] - -// This test checks that we add inlinehint for #[inline], noinline for #[inline(never)], and -// alwaysinline for #[inline(always)] to call sites. - -#[unsafe(no_mangle)] -fn calls_something_noinline() { - // CHECK-LABEL @calls_something_noinline - // CHECK: call void @{{.*}}noinline_fn() #[[NOINLINE:[0-9]+]] - noinline_fn(); -} - -#[inline(never)] -fn noinline_fn() {} - -#[unsafe(no_mangle)] -fn calls_something_inline() { - // CHECK-LABEL @calls_something_inlinehint - // CHECK: call void @{{.*}}inlinehint_fn() #[[INLINEHINT:[0-9]+]] - inlinehint_fn(); -} - -#[inline] -fn inlinehint_fn() {} - -#[unsafe(no_mangle)] -fn calls_something_alwaysinline() { - // CHECK-LABEL @calls_something_alwaysinline - // CHECK: call void @{{.*}}alwaysinline_fn() #[[ALWAYSINLINE:[0-9]+]] - alwaysinline_fn(); -} - -#[inline(always)] -fn alwaysinline_fn() {} - -//CHECK: attributes #[[NOINLINE]] = {{{.*}} noinline {{.*}}} -//CHECK: attributes #[[INLINEHINT]] = {{{.*}} inlinehint {{.*}}} -//CHECK: attributes #[[ALWAYSINLINE]] = {{{.*}} alwaysinline {{.*}}} From d9e6b2f06f9e1517010d613ac30025ba3977b0f0 Mon Sep 17 00:00:00 2001 From: Gri-ffin Date: Thu, 17 Sep 2026 21:48:45 +0100 Subject: [PATCH 0288/1309] document clippy_utils mir pub items --- clippy_utils/src/mir/mod.rs | 6 ++++++ clippy_utils/src/mir/possible_borrower.rs | 5 +++-- clippy_utils/src/mir/possible_origin.rs | 9 +++++---- clippy_utils/src/mir/transitive_relation.rs | 2 ++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/clippy_utils/src/mir/mod.rs b/clippy_utils/src/mir/mod.rs index edfcd9e4bb231..2ea5e368fcfa9 100644 --- a/clippy_utils/src/mir/mod.rs +++ b/clippy_utils/src/mir/mod.rs @@ -26,6 +26,12 @@ pub struct LocalUsage { pub local_consume_or_mutate_locs: Vec, } +/// Collects usage locations (reads, consumes or mutations) for the set of the locals across blocks where their storage +/// remains live relative to the `location` specified. +/// +/// Returns: +/// - `Some([LocalUsage; N])` containing usage metadata for each local in `locals`. +/// - `None` if the analysis fails or `location` is unreachable. pub fn visit_local_usage( locals: [Local; N], mir: &Body<'_>, diff --git a/clippy_utils/src/mir/possible_borrower.rs b/clippy_utils/src/mir/possible_borrower.rs index 7ed28d1846ca5..4038fd8b4acd9 100644 --- a/clippy_utils/src/mir/possible_borrower.rs +++ b/clippy_utils/src/mir/possible_borrower.rs @@ -13,7 +13,7 @@ use std::borrow::Cow; use std::ops::ControlFlow; /// Collects the possible borrowers of each local. -/// For example, `b = &a; c = &a;` will make `b` and (transitively) `c` +/// For example, `b = &a; c = &b;` will make `b` and (transitively) `c` /// possible borrowers of `a`. struct PossibleBorrowerVisitor<'a, 'b, 'tcx> { possible_borrower: TransitiveRelation, @@ -170,7 +170,7 @@ pub struct PossibleBorrowerMap<'b, 'tcx> { /// Mapping `Local -> its possible borrowers` pub map: FxHashMap>, maybe_live: ResultsCursor<'b, 'tcx, MaybeStorageLive<'tcx>>, - // Caches to avoid allocation of `DenseBitSet` on every query + /// Caches to avoid allocation of `DenseBitSet` on every query pub bitset: (DenseBitSet, DenseBitSet), } @@ -232,6 +232,7 @@ impl<'b, 'tcx> PossibleBorrowerMap<'b, 'tcx> { self.bitset.0.is_empty() } + /// Returns `true` if the storage for `local` may be live at `at` pub fn local_is_alive_at(&mut self, local: mir::Local, at: mir::Location) -> bool { self.maybe_live.seek_after_primary_effect(at); self.maybe_live.get().contains(local) diff --git a/clippy_utils/src/mir/possible_origin.rs b/clippy_utils/src/mir/possible_origin.rs index 742eedfa225bc..1bf5012c10010 100644 --- a/clippy_utils/src/mir/possible_origin.rs +++ b/clippy_utils/src/mir/possible_origin.rs @@ -21,6 +21,7 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> { } } + /// Returns a map of each non-`Copy` local to all locals that it can borrow or move from (excluding `_0`). pub fn into_map(self, cx: &LateContext<'tcx>) -> FxHashMap> { let mut map = FxHashMap::default(); for row in (1..self.body.local_decls.len()).map(mir::Local::from_usize) { @@ -28,10 +29,10 @@ impl<'a, 'tcx> PossibleOriginVisitor<'a, 'tcx> { continue; } - let mut borrowers = self.possible_origin.reachable_from(row, self.body.local_decls.len()); - borrowers.remove(mir::Local::from_usize(0)); - if !borrowers.is_empty() { - map.insert(row, borrowers); + let mut origins = self.possible_origin.reachable_from(row, self.body.local_decls.len()); + origins.remove(mir::Local::from_usize(0)); + if !origins.is_empty() { + map.insert(row, origins); } } map diff --git a/clippy_utils/src/mir/transitive_relation.rs b/clippy_utils/src/mir/transitive_relation.rs index da44829a4c804..ebd570147baf0 100644 --- a/clippy_utils/src/mir/transitive_relation.rs +++ b/clippy_utils/src/mir/transitive_relation.rs @@ -8,10 +8,12 @@ pub(super) struct TransitiveRelation { } impl TransitiveRelation { + /// Records a direct relation from local `a` to local `b`. pub fn add(&mut self, a: mir::Local, b: mir::Local) { self.relations.entry(a).or_default().push(b); } + /// Finds all locals directly or indirectly reachable from local `a`. pub fn reachable_from(&self, a: mir::Local, domain_size: usize) -> DenseBitSet { let mut seen = DenseBitSet::new_empty(domain_size); let mut stack = vec![a]; From 5edb259c652ce8bed8477ec54fa37cc48f3472eb Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 3 Sep 2026 15:59:41 -0400 Subject: [PATCH 0289/1309] Add non-zero div test --- tests/run/nonzero_div_ceil.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 tests/run/nonzero_div_ceil.rs diff --git a/tests/run/nonzero_div_ceil.rs b/tests/run/nonzero_div_ceil.rs new file mode 100644 index 0000000000000..e6bd3c2ec9845 --- /dev/null +++ b/tests/run/nonzero_div_ceil.rs @@ -0,0 +1,17 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::hint::black_box; +use std::num::NonZero; + +fn main() { + for (dividend, divisor, expected) in + [(10u8, 3u8, 4u8), (1, 254, 1), (1, 255, 1), (2, 254, 1), (2, 255, 1), (200, 100, 2)] + { + let dividend = NonZero::new(black_box(dividend)).unwrap(); + let divisor = NonZero::new(black_box(divisor)).unwrap(); + assert_eq!(dividend.div_ceil(divisor).get(), expected); + } +} From 64b42492d543805383e225cf0062b88060ffc99b Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 4 Sep 2026 10:04:55 -0400 Subject: [PATCH 0290/1309] Re-enable disabled project tests --- .github/workflows/ci.yml | 7 ++- build_system/src/test.rs | 98 ++++++++++++++++++++++++++++++---------- 2 files changed, 79 insertions(+), 26 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 529003fc384a0..2f5cc409e363d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -35,7 +35,8 @@ jobs: "--extended-regex-tests", "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", - "--projects", + "--projects --nb-parts 2 --current-part 0", + "--projects --nb-parts 2 --current-part 1", "--gcc-asm-tests --test-release-libcore", ] @@ -53,6 +54,10 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm + - name: Install the libraries needed to build librsvg + if: ${{ contains(matrix.commands, '--projects') }} + run: sudo apt-get install libcairo2-dev libpango1.0-dev libfontconfig1-dev libfreetype-dev libharfbuzz-dev libxml2-dev libglib2.0-dev + - name: Download artifact run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 6f33bdc392984..8fd495f82e240 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -724,40 +724,88 @@ where // echo "[BUILD] sysroot in release mode" // ./build_sysroot/build_sysroot.sh --release +struct Project { + url: &'static str, + /// Arguments added to both the `cargo build` and the `cargo test` invocations. + cargo_arguments: &'static [&'static str], + /// Arguments forwarded to the test harness by `cargo test`. + test_harness_arguments: &'static [&'static str], +} + +impl Project { + const fn new(url: &'static str) -> Self { + Self { url, cargo_arguments: &[], test_harness_arguments: &[] } + } + + const fn cargo_arguments(mut self, arguments: &'static [&'static str]) -> Self { + self.cargo_arguments = arguments; + self + } + + const fn test_harness_arguments(mut self, arguments: &'static [&'static str]) -> Self { + self.test_harness_arguments = arguments; + self + } +} + fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let projects = [ - //"https://gitlab.gnome.org/GNOME/librsvg", // FIXME: doesn't compile in the CI since the - // version of cairo and other libraries is too old. - "https://github.com/rust-random/getrandom", - "https://github.com/BurntSushi/memchr", - "https://github.com/dtolnay/itoa", - "https://github.com/rust-lang/cfg-if", - //"https://github.com/rust-lang-nursery/lazy-static.rs", // FIXME: re-enable when the - //failing test is fixed upstream. - //"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed. - // FIXME: ignore the base64 test that is OOM-killed. - //"https://github.com/time-rs/time", // FIXME: one test fails (https://github.com/time-rs/time/issues/719). - "https://github.com/rust-lang/log", - "https://github.com/bitflags/bitflags", - //"https://github.com/serde-rs/serde", // FIXME: one test fails. - //"https://github.com/rayon-rs/rayon", // FIXME: very slow, only run on master? - //"https://github.com/rust-lang/cargo", // FIXME: very slow, only run on master? + Project::new("https://gitlab.gnome.org/GNOME/librsvg"), + Project::new("https://github.com/rust-random/getrandom"), + Project::new("https://github.com/BurntSushi/memchr"), + Project::new("https://github.com/dtolnay/itoa"), + Project::new("https://github.com/rust-lang/cfg-if"), + // The `ui` test compares against the diagnostics of the compiler it was blessed with, so it + // fails on the nightly we use no matter which backend produces the code. + Project::new("https://github.com/rust-lang-nursery/lazy-static.rs") + .test_harness_arguments(&["--skip", "ui", "--exact"]), + Project::new("https://github.com/marshallpierce/rust-base64"), + // The test suite refuses to build unless every feature is enabled; it otherwise spawns a + // nested `cargo test --all-features` which would not use this backend. + Project::new("https://github.com/time-rs/time").cargo_arguments(&["--all-features"]), + Project::new("https://github.com/rust-lang/log"), + Project::new("https://github.com/bitflags/bitflags"), + Project::new("https://github.com/serde-rs/serde"), + Project::new("https://github.com/rayon-rs/rayon"), + // FIXME: too slow to run in the CI: the release build alone takes 46 minutes and the + // `cargo` crate itself needs 5.4 GB of memory in a single rustc process. + //Project::new("https://github.com/rust-lang/cargo"), ]; let mut env = env.clone(); let rustflags = format!("{} --cap-lints allow", env.get("RUSTFLAGS").cloned().unwrap_or_default()); env.insert("RUSTFLAGS".to_string(), rustflags); - let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { - for project in iter { - let clone_result = git_clone_root_dir(project, projects_path, true)?; - let repo_path = Path::new(&clone_result.repo_dir); - run_cargo_command(&[&"build", &"--release"], Some(repo_path), &env, args)?; - run_cargo_command(&[&"test"], Some(repo_path), &env, args)?; - } + let run_tests = + |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { + for project in iter { + let clone_result = git_clone_root_dir(project.url, projects_path, true)?; + let repo_path = Path::new(&clone_result.repo_dir); + + let mut build_command: Vec<&dyn AsRef> = vec![&"build", &"--release"]; + build_command.extend( + project.cargo_arguments.iter().map(|argument| argument as &dyn AsRef), + ); + run_cargo_command(&build_command, Some(repo_path), &env, args)?; - Ok(()) - }; + let mut test_command: Vec<&dyn AsRef> = vec![&"test"]; + test_command.extend( + project.cargo_arguments.iter().map(|argument| argument as &dyn AsRef), + ); + if !project.test_harness_arguments.is_empty() { + test_command.push(&"--"); + test_command.extend( + project + .test_harness_arguments + .iter() + .map(|argument| argument as &dyn AsRef), + ); + } + run_cargo_command(&test_command, Some(repo_path), &env, args)?; + } + + Ok(()) + }; let projects_path = Path::new("projects"); create_dir(projects_path)?; From 0dd8e990cdbc3178f52de654642f1e52b407ffe2 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Thu, 17 Sep 2026 20:28:41 -0400 Subject: [PATCH 0291/1309] Ignore a librsvg test since it fails in CI --- build_system/src/test.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 8fd495f82e240..01375c2c33ddd 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -750,7 +750,13 @@ impl Project { fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let projects = [ - Project::new("https://gitlab.gnome.org/GNOME/librsvg"), + // The reference images assume the exact cairo, pango and freetype that librsvg pins in its + // own CI; this one renders text decorations a pixel off with the versions Ubuntu ships. + Project::new("https://gitlab.gnome.org/GNOME/librsvg").test_harness_arguments(&[ + "--skip", + "tests::svg1_1_text_text_03_b_svg", + "--exact", + ]), Project::new("https://github.com/rust-random/getrandom"), Project::new("https://github.com/BurntSushi/memchr"), Project::new("https://github.com/dtolnay/itoa"), From c59713c3777c8ed3c89151f442009341f1076214 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Thu, 17 Sep 2026 18:34:27 -0700 Subject: [PATCH 0292/1309] `extend_with_drain`: Check for the name `drain()` first. This is faster than checking the types. The new code is not a single if-let-chain because it is about to be changed further to support multiple collection types. --- clippy_lints/src/methods/extend_with_drain.rs | 58 ++++++++++--------- 1 file changed, 30 insertions(+), 28 deletions(-) diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 21e13d7b0d0eb..38adfff4038d8 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -9,35 +9,37 @@ use rustc_lint::LateContext; use super::EXTEND_WITH_DRAIN; -pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, arg: &Expr<'_>) { - let ty = cx.typeck_results().expr_ty(recv).peel_refs(); - if ty.is_diag_item(cx, sym::Vec) - //check source object - && let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Expr<'_>, arg: &Expr<'_>) { + // Check whether the argument of the `extend()` is a `drain()` first, because it’s cheaper than checking types. + if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind && src_method.ident.name == sym::drain - && let src_ty = cx.typeck_results().expr_ty(drain_vec) - //check if actual src type is mutable for code suggestion - && let immutable = src_ty.is_mutable_ptr() - && let src_ty = src_ty.peel_refs() - && src_ty.is_diag_item(cx, sym::Vec) - //check drain range - && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() - && src_ty_range.is_lang_item(cx, LangItem::RangeFull) { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - EXTEND_WITH_DRAIN, - expr.span, - "use of `extend` instead of `append` for adding the full range of a second vector", - "try", - format!( - "{}.append({}{})", - snippet_with_applicability(cx, recv.span, "..", &mut applicability), - if immutable { "" } else { "&mut " }, - snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) - ), - applicability, - ); + let ty = cx.typeck_results().expr_ty(extend_receiver).peel_refs(); + if ty.is_diag_item(cx, sym::Vec) + && let src_ty = cx.typeck_results().expr_ty(drain_vec) + //check if actual src type is mutable for code suggestion + && let immutable = src_ty.is_mutable_ptr() + && let src_ty = src_ty.peel_refs() + && src_ty.is_diag_item(cx, sym::Vec) + //check drain range + && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() + && src_ty_range.is_lang_item(cx, LangItem::RangeFull) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + EXTEND_WITH_DRAIN, + expr.span, + "use of `extend` instead of `append` for adding the full range of a second vector", + "try", + format!( + "{}.append({}{})", + snippet_with_applicability(cx, extend_receiver.span, "..", &mut applicability), + if immutable { "" } else { "&mut " }, + snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) + ), + applicability, + ); + } } } From 3e674c47c9fa03675b14bfb6e354c8b3f7c398b7 Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Thu, 17 Sep 2026 19:13:28 -0700 Subject: [PATCH 0293/1309] =?UTF-8?q?`extend=5Fwith=5Fdrain`:=20Don?= =?UTF-8?q?=E2=80=99t=20use=20a=20shadowed=20variable=20to=20collect=20the?= =?UTF-8?q?=20`drain`=20receiver=20mutability.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This way is shorter and will work better with the next change. --- clippy_lints/src/methods/extend_with_drain.rs | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 38adfff4038d8..6be949d23501d 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -17,10 +17,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Exp let ty = cx.typeck_results().expr_ty(extend_receiver).peel_refs(); if ty.is_diag_item(cx, sym::Vec) && let src_ty = cx.typeck_results().expr_ty(drain_vec) - //check if actual src type is mutable for code suggestion - && let immutable = src_ty.is_mutable_ptr() - && let src_ty = src_ty.peel_refs() - && src_ty.is_diag_item(cx, sym::Vec) + && src_ty.peel_refs().is_diag_item(cx, sym::Vec) //check drain range && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() && src_ty_range.is_lang_item(cx, LangItem::RangeFull) @@ -35,7 +32,7 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Exp format!( "{}.append({}{})", snippet_with_applicability(cx, extend_receiver.span, "..", &mut applicability), - if immutable { "" } else { "&mut " }, + if src_ty.is_mutable_ptr() { "" } else { "&mut " }, snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) ), applicability, From 03f80c3e50b9ff40a5c77870656d5630e5a15f3b Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Thu, 17 Sep 2026 19:13:53 -0700 Subject: [PATCH 0294/1309] `extend_with_drain`: further preparatory refactoring. This renames variables to make their roles clearer, and moves the `expr_ty()` calls to a place where they will be outside the loop that is about to be added. --- clippy_lints/src/methods/extend_with_drain.rs | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 6be949d23501d..3a773acfc6314 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -14,11 +14,12 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Exp if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind && src_method.ident.name == sym::drain { - let ty = cx.typeck_results().expr_ty(extend_receiver).peel_refs(); - if ty.is_diag_item(cx, sym::Vec) - && let src_ty = cx.typeck_results().expr_ty(drain_vec) - && src_ty.peel_refs().is_diag_item(cx, sym::Vec) - //check drain range + let extend_collection_ty = cx.typeck_results().expr_ty(extend_receiver).peel_refs(); + let drain_receiver_ty = cx.typeck_results().expr_ty(drain_vec); + + if extend_collection_ty.is_diag_item(cx, sym::Vec) + && drain_receiver_ty.peel_refs().is_diag_item(cx, sym::Vec) + // Check that the drain range is full, not partial && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() && src_ty_range.is_lang_item(cx, LangItem::RangeFull) { @@ -32,7 +33,11 @@ pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Exp format!( "{}.append({}{})", snippet_with_applicability(cx, extend_receiver.span, "..", &mut applicability), - if src_ty.is_mutable_ptr() { "" } else { "&mut " }, + if drain_receiver_ty.is_mutable_ptr() { + "" + } else { + "&mut " + }, snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) ), applicability, From d618477899e1ab69fa6458f33cc246d93ff6ed3c Mon Sep 17 00:00:00 2001 From: Kevin Reid Date: Sun, 29 Mar 2026 08:30:51 -0700 Subject: [PATCH 0295/1309] Generalize `extend_with_drain` to `VecDeque` and `BinaryHeap`. --- clippy_lints/src/methods/extend_with_drain.rs | 78 ++++++++++++------- clippy_lints/src/methods/mod.rs | 8 +- tests/ui/extend_with_drain.fixed | 44 +++++++++-- tests/ui/extend_with_drain.rs | 44 +++++++++-- tests/ui/extend_with_drain.stderr | 30 ++++--- 5 files changed, 152 insertions(+), 52 deletions(-) diff --git a/clippy_lints/src/methods/extend_with_drain.rs b/clippy_lints/src/methods/extend_with_drain.rs index 3a773acfc6314..7e2d3758b6af9 100644 --- a/clippy_lints/src/methods/extend_with_drain.rs +++ b/clippy_lints/src/methods/extend_with_drain.rs @@ -10,38 +10,64 @@ use rustc_lint::LateContext; use super::EXTEND_WITH_DRAIN; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, extend_receiver: &Expr<'_>, arg: &Expr<'_>) { + // `expr` is a method call expression which has already been checked to have the method name “extend”. + // `extend_receiver` is the receiver of that method call, which will be the collection being extended. + // Check whether the argument of the `extend()` is a `drain()` first, because it’s cheaper than checking types. - if let ExprKind::MethodCall(src_method, drain_vec, [drain_arg], _) = &arg.kind + if let ExprKind::MethodCall(src_method, drain_receiver, drain_args, _) = &arg.kind && src_method.ident.name == sym::drain { let extend_collection_ty = cx.typeck_results().expr_ty(extend_receiver).peel_refs(); - let drain_receiver_ty = cx.typeck_results().expr_ty(drain_vec); + let drain_receiver_ty = cx.typeck_results().expr_ty(drain_receiver); - if extend_collection_ty.is_diag_item(cx, sym::Vec) - && drain_receiver_ty.peel_refs().is_diag_item(cx, sym::Vec) - // Check that the drain range is full, not partial - && let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs() - && src_ty_range.is_lang_item(cx, LangItem::RangeFull) + // Each of these container types has: + // * A method `fn append(&mut self, other: &mut Self)`. + // * A method `fn drain(&mut self, /* maybe a range parameter too */)`. + for (container_type_sym, expect_drain_range_argument) in + [(sym::Vec, true), (sym::VecDeque, true), (sym::BinaryHeap, false)] { - let mut applicability = Applicability::MachineApplicable; - span_lint_and_sugg( - cx, - EXTEND_WITH_DRAIN, - expr.span, - "use of `extend` instead of `append` for adding the full range of a second vector", - "try", - format!( - "{}.append({}{})", - snippet_with_applicability(cx, extend_receiver.span, "..", &mut applicability), - if drain_receiver_ty.is_mutable_ptr() { - "" - } else { - "&mut " - }, - snippet_with_applicability(cx, drain_vec.span, "..", &mut applicability) - ), - applicability, - ); + // Check that the source and destination collections are of the same type. + if extend_collection_ty.is_diag_item(cx, container_type_sym) + && drain_receiver_ty.peel_refs().is_diag_item(cx, container_type_sym) + // Check that the drain range (if there is one) is full, not partial + && drain_args_are_full_range(cx, drain_args, expect_drain_range_argument) + { + let mut applicability = Applicability::MachineApplicable; + span_lint_and_sugg( + cx, + EXTEND_WITH_DRAIN, + expr.span, + format!( + "use of `extend` instead of `append` for moving \ + the full contents of a second `{container_type_sym}`" + ), + "try", + format!( + "{}.append({}{})", + snippet_with_applicability(cx, extend_receiver.span, "..", &mut applicability), + if drain_receiver_ty.is_mutable_ptr() { + "" + } else { + "&mut " + }, + snippet_with_applicability(cx, drain_receiver.span, "..", &mut applicability) + ), + applicability, + ); + } } } } + +/// Check for the correct count of arguments to a `drain()` call, and, if a range is expected, +/// that the range is the full range `..`. +fn drain_args_are_full_range(cx: &LateContext<'_>, args: &[Expr<'_>], expect_drain_range_argument: bool) -> bool { + match (expect_drain_range_argument, args) { + (false, []) => true, + (true, [drain_arg]) => { + let src_ty_range = cx.typeck_results().expr_ty(drain_arg).peel_refs(); + src_ty_range.is_lang_item(cx, LangItem::RangeFull) + }, + (_, _) => false, + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 784061c7c24cb..93a3ab489601d 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -705,10 +705,12 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for occurrences where one vector gets extended instead of append + /// Checks for use of `extend()` and `drain()` methods to transfer items from one `Vec`, + /// `VecDeque`, or `BinaryHeap` to another. /// /// ### Why is this bad? - /// Using `append` instead of `extend` is more concise and faster + /// Using `append()` instead of `extend()` is more concise, and faster because the + /// `append()` method can take advantage of knowledge of the collection’s structure. /// /// ### Example /// ```no_run @@ -728,7 +730,7 @@ declare_clippy_lint! { #[clippy::version = "1.55.0"] pub EXTEND_WITH_DRAIN, perf, - "using vec.append(&mut vec) to move the full range of a vector to another" + "use of `extend(other.drain())` to move the contents of a collection is inefficient" } declare_clippy_lint! { diff --git a/tests/ui/extend_with_drain.fixed b/tests/ui/extend_with_drain.fixed index 34dd4cc3d44a8..ff0a709a71f96 100644 --- a/tests/ui/extend_with_drain.fixed +++ b/tests/ui/extend_with_drain.fixed @@ -1,5 +1,24 @@ #![warn(clippy::extend_with_drain)] -use std::collections::BinaryHeap; + +use std::collections::{BinaryHeap, VecDeque}; + +struct NotAStdCollection {} +impl NotAStdCollection { + /// The lint should *not* use this method because it doesn't know what it does, + /// despite looking similar. + fn append(&mut self, _other: &mut Self) { + unimplemented!() + } + fn drain>(&mut self, _range: R) -> impl Iterator { + core::iter::empty() + } +} +impl Extend<()> for NotAStdCollection { + fn extend>(&mut self, _iter: T) { + unimplemented!() + } +} + fn main() { //gets linted let mut vec1 = vec![0u8; 1024]; @@ -38,17 +57,28 @@ fn main() { return_vector().append(&mut vec9); - //won't get linted because it is not a vec - - let mut heap = BinaryHeap::from(vec![1, 3]); - let mut heap2 = BinaryHeap::from(vec![]); - heap2.extend(heap.drain()); - let mut x = vec![0, 1, 2, 3, 5]; let ref_x = &mut x; let mut y = Vec::new(); y.append(ref_x); //~^ extend_with_drain + + // VecDeque works the same as Vec and gets the same lint + let mut vec_deque1 = VecDeque::from([0u8; 1024]); + let mut vec_deque2 = VecDeque::new(); + vec_deque2.append(&mut vec_deque1); + //~^ extend_with_drain + + // BinaryHeap is the same except for not having a range parameter + let mut heap = BinaryHeap::from(vec![1, 3]); + let mut heap2 = BinaryHeap::from(vec![]); + heap2.append(&mut heap); + //~^ extend_with_drain + + // Unknown types should not get the same treatment + let mut foreign1 = NotAStdCollection {}; + let mut foreign2 = NotAStdCollection {}; + foreign2.extend(foreign1.drain(..)); } fn return_vector() -> Vec { diff --git a/tests/ui/extend_with_drain.rs b/tests/ui/extend_with_drain.rs index aa641a67f2417..b3e276fe3818d 100644 --- a/tests/ui/extend_with_drain.rs +++ b/tests/ui/extend_with_drain.rs @@ -1,5 +1,24 @@ #![warn(clippy::extend_with_drain)] -use std::collections::BinaryHeap; + +use std::collections::{BinaryHeap, VecDeque}; + +struct NotAStdCollection {} +impl NotAStdCollection { + /// The lint should *not* use this method because it doesn't know what it does, + /// despite looking similar. + fn append(&mut self, _other: &mut Self) { + unimplemented!() + } + fn drain>(&mut self, _range: R) -> impl Iterator { + core::iter::empty() + } +} +impl Extend<()> for NotAStdCollection { + fn extend>(&mut self, _iter: T) { + unimplemented!() + } +} + fn main() { //gets linted let mut vec1 = vec![0u8; 1024]; @@ -38,17 +57,28 @@ fn main() { return_vector().append(&mut vec9); - //won't get linted because it is not a vec - - let mut heap = BinaryHeap::from(vec![1, 3]); - let mut heap2 = BinaryHeap::from(vec![]); - heap2.extend(heap.drain()); - let mut x = vec![0, 1, 2, 3, 5]; let ref_x = &mut x; let mut y = Vec::new(); y.extend(ref_x.drain(..)); //~^ extend_with_drain + + // VecDeque works the same as Vec and gets the same lint + let mut vec_deque1 = VecDeque::from([0u8; 1024]); + let mut vec_deque2 = VecDeque::new(); + vec_deque2.extend(vec_deque1.drain(..)); + //~^ extend_with_drain + + // BinaryHeap is the same except for not having a range parameter + let mut heap = BinaryHeap::from(vec![1, 3]); + let mut heap2 = BinaryHeap::from(vec![]); + heap2.extend(heap.drain()); + //~^ extend_with_drain + + // Unknown types should not get the same treatment + let mut foreign1 = NotAStdCollection {}; + let mut foreign2 = NotAStdCollection {}; + foreign2.extend(foreign1.drain(..)); } fn return_vector() -> Vec { diff --git a/tests/ui/extend_with_drain.stderr b/tests/ui/extend_with_drain.stderr index ec8659a1037cf..dd9efc5c8c5e9 100644 --- a/tests/ui/extend_with_drain.stderr +++ b/tests/ui/extend_with_drain.stderr @@ -1,5 +1,5 @@ -error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:7:5 +error: use of `extend` instead of `append` for moving the full contents of a second `Vec` + --> tests/ui/extend_with_drain.rs:26:5 | LL | vec2.extend(vec1.drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec2.append(&mut vec1)` @@ -7,23 +7,35 @@ LL | vec2.extend(vec1.drain(..)); = note: `-D clippy::extend-with-drain` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::extend_with_drain)]` -error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:13:5 +error: use of `extend` instead of `append` for moving the full contents of a second `Vec` + --> tests/ui/extend_with_drain.rs:32:5 | LL | vec4.extend(vec3.drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec4.append(&mut vec3)` -error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:18:5 +error: use of `extend` instead of `append` for moving the full contents of a second `Vec` + --> tests/ui/extend_with_drain.rs:37:5 | LL | vec11.extend(return_vector().drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec11.append(&mut return_vector())` -error: use of `extend` instead of `append` for adding the full range of a second vector - --> tests/ui/extend_with_drain.rs:50:5 +error: use of `extend` instead of `append` for moving the full contents of a second `Vec` + --> tests/ui/extend_with_drain.rs:63:5 | LL | y.extend(ref_x.drain(..)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `y.append(ref_x)` -error: aborting due to 4 previous errors +error: use of `extend` instead of `append` for moving the full contents of a second `VecDeque` + --> tests/ui/extend_with_drain.rs:69:5 + | +LL | vec_deque2.extend(vec_deque1.drain(..)); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `vec_deque2.append(&mut vec_deque1)` + +error: use of `extend` instead of `append` for moving the full contents of a second `BinaryHeap` + --> tests/ui/extend_with_drain.rs:75:5 + | +LL | heap2.extend(heap.drain()); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `heap2.append(&mut heap)` + +error: aborting due to 6 previous errors From f330047c2b4d36fb62320277be57f9d2d01fc30b Mon Sep 17 00:00:00 2001 From: cezarbbb Date: Fri, 7 Aug 2026 17:01:51 +0800 Subject: [PATCH 0296/1309] Add COFF support to -Zstaticlib-rename-internal-symbols --- compiler/rustc_codegen_ssa/src/back/link.rs | 42 ++-- .../rustc_codegen_ssa/src/back/symbol_edit.rs | 156 +++++++++++++- compiler/rustc_codegen_ssa/src/diagnostics.rs | 2 +- .../rmake.rs | 200 ++++++++++++++++++ 4 files changed, 383 insertions(+), 17 deletions(-) create mode 100644 tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c283e464821e5..221998abf6128 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -834,24 +834,33 @@ fn link_staticlib( let hide = sess.opts.unstable_opts.staticlib_hide_internal_symbols; let rename = sess.opts.unstable_opts.staticlib_rename_internal_symbols; + let hide_supported = + matches!(sess.target.binary_format, BinaryFormat::Elf | BinaryFormat::MachO); + // Rename only rewrites symbol names, so it also works on COFF; hide + // needs a visibility concept COFF lacks. + let rename_supported = matches!( + sess.target.binary_format, + BinaryFormat::Elf | BinaryFormat::MachO | BinaryFormat::Coff + ); + let exported_symbols = if hide || rename { - if !matches!(sess.target.binary_format, BinaryFormat::Elf | BinaryFormat::MachO) { - if hide { - sess.dcx().emit_warn(diagnostics::StaticlibHideInternalSymbolsUnsupported { - binary_format: sess.target.archive_format.to_string(), - }); - } - if rename { - sess.dcx().emit_warn(diagnostics::StaticlibRenameInternalSymbolsUnsupported { - binary_format: sess.target.archive_format.to_string(), - }); - } - None - } else { + if hide && !hide_supported { + sess.dcx().emit_warn(diagnostics::StaticlibHideInternalSymbolsUnsupported { + binary_format: sess.target.archive_format.to_string(), + }); + } + if rename && !rename_supported { + sess.dcx().emit_warn(diagnostics::StaticlibRenameInternalSymbolsUnsupported { + binary_format: sess.target.archive_format.to_string(), + }); + } + if (hide && hide_supported) || (rename && rename_supported) { crate_info .exported_symbols .get(&CrateType::StaticLib) .map(|symbols| symbols.iter().map(|symbol| symbol.name.clone()).collect()) + } else { + None } } else { None @@ -859,8 +868,11 @@ fn link_staticlib( let symbols = exported_symbols.map(|exported| ArchiveSymbols { exported, - rename_suffix: rename.then(|| crate_info.symbol_rename_suffix.clone()), - hide, + rename_suffix: (rename && rename_supported) + .then(|| crate_info.symbol_rename_suffix.clone()), + // A warning was already emitted above if hiding was requested for an + // unsupported format; don't also ask the backend to hide there. + hide: hide && hide_supported, }); ab.build(out_filename, symbols); diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs index ef8008216187a..490c634a1845a 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs @@ -7,9 +7,10 @@ use std::borrow::Cow; use std::mem; +use object::read::coff::{CoffHeader, ImageSymbol as _}; use object::read::elf::{SectionHeader as _, Sym as _}; use object::read::macho::Nlist; -use object::{Endianness, elf, macho}; +use object::{Endianness, elf, macho, pe}; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; struct Patch { @@ -57,6 +58,20 @@ pub(super) fn apply_edits<'a>( rename, mem::offset_of!(macho::Nlist32, n_type), ), + Some(object::File::Coff(f)) => coff_edit_impl( + data, + f.coff_header(), + hide, + rename, + coff_strip_underscore(f.coff_header()), + ), + Some(object::File::CoffBig(f)) => coff_edit_impl( + data, + f.coff_header(), + hide, + rename, + coff_strip_underscore(f.coff_header()), + ), _ => None, }; match result { @@ -84,10 +99,30 @@ pub(super) fn collect_internal_names( object::File::MachO32(_) => { macho_collect_impl::>(data, exported, out) } + object::File::Coff(f) => coff_collect_impl( + data, + f.coff_header(), + exported, + out, + coff_strip_underscore(f.coff_header()), + ), + object::File::CoffBig(f) => coff_collect_impl( + data, + f.coff_header(), + exported, + out, + coff_strip_underscore(f.coff_header()), + ), _ => {} } } +/// Whether this machine's COFF ABI decorates external symbols with a leading `_` +/// (i686 only). +fn coff_strip_underscore(header: &impl CoffHeader) -> bool { + header.machine() == pe::IMAGE_FILE_MACHINE_I386 +} + fn elf_collect_impl>( data: &[u8], exported: &FxHashSet, @@ -441,6 +476,125 @@ fn macho_rebuild_strtab( Some(result) } +// --------------------------------------------------------------------------- +// COFF: single-pass collection + apply +// --------------------------------------------------------------------------- + +fn coff_collect_impl<'data, Coff: CoffHeader>( + data: &'data [u8], + header: &'data Coff, + exported: &FxHashSet, + out: &mut FxHashSet, + strip_underscore: bool, +) { + let Ok(symbols) = header.symbols(data) else { return }; + let strings = symbols.strings(); + + for (_index, sym) in symbols.iter() { + let sclass = sym.storage_class(); + if sclass != pe::IMAGE_SYM_CLASS_EXTERNAL && sclass != pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL { + continue; + } + if sym.section_number() <= 0 { + continue; + } + let Ok(name_bytes) = sym.name(strings) else { continue }; + let Ok(mut name) = str::from_utf8(name_bytes).map(String::from) else { continue }; + if strip_underscore { + name = name.strip_prefix('_').unwrap_or(&name).to_string(); + } + if !exported.contains(&name) { + out.insert(name); + } + } +} + +fn coff_edit_impl<'data, Coff: CoffHeader>( + data: &'data [u8], + header: &'data Coff, + hide: bool, + rename: Option<&(FxHashSet, &str)>, + strip_underscore: bool, +) -> Option> { + // COFF has no visibility concept, so hiding is unsupported; the caller + // has already warned and does not request it. + assert!(!hide); + + let pointer_to_symbol_table = header.pointer_to_symbol_table() as usize; + let number_of_symbols = header.number_of_symbols() as usize; + // ImageSymbol is 18 bytes; ImageSymbolEx (bigobj) is 20. + let sym_size = mem::size_of::(); + + let symbol_bytes_offset = pointer_to_symbol_table; + let strtab_base = pointer_to_symbol_table + number_of_symbols * sym_size; + if strtab_base > data.len() { + return None; + } + + if data.len() < strtab_base + 4 { + return None; + } + let old_len = + u32::from_le_bytes(data[strtab_base..strtab_base + 4].try_into().unwrap()) as usize; + if strtab_base + old_len > data.len() { + return None; + } + + let Ok(symbols) = header.symbols(data) else { return None }; + let strings = symbols.strings(); + + let mut renames = Vec::new(); + for (index, sym) in symbols.iter() { + let sclass = sym.storage_class(); + if sclass != pe::IMAGE_SYM_CLASS_EXTERNAL && sclass != pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL { + continue; + } + let Ok(name_bytes) = sym.name(strings) else { continue }; + let Ok(name) = str::from_utf8(name_bytes) else { continue }; + let check_name = + if strip_underscore { name.strip_prefix('_').unwrap_or(name) } else { name }; + if rename.is_some_and(|(rename_set, _)| rename_set.contains(check_name)) { + renames.push(RenameEntry { + name_field_offset: symbol_bytes_offset + index.0 * sym_size, + name: name.to_string(), + }); + } + } + if renames.is_empty() { + return None; + } + let suffix = rename.unwrap().1; + + let mut new_strtab = Vec::new(); + let mut map: FxHashMap = FxHashMap::default(); + let mut sorted_names: Vec<&str> = renames.iter().map(|r| r.name.as_str()).collect(); + sorted_names.sort(); + sorted_names.dedup(); + for name in &sorted_names { + let rel_offset = (old_len + new_strtab.len()) as u32; + new_strtab.extend_from_slice(name.as_bytes()); + new_strtab.extend_from_slice(suffix.as_bytes()); + new_strtab.push(0); + map.insert(name.to_string(), rel_offset); + } + + let mut result = data.to_vec(); + let new_len = (old_len + new_strtab.len()) as u32; + result[strtab_base..strtab_base + 4].copy_from_slice(&new_len.to_le_bytes()); + result.extend_from_slice(&new_strtab); + + // Long names are stored as all-zero name[0..4] plus the string table + // offset in name[4..8]. + for r in &renames { + let rel = map[&r.name]; + let field = &mut result[r.name_field_offset..r.name_field_offset + 8]; + field[..4].fill(0); + field[4..].copy_from_slice(&rel.to_le_bytes()); + } + + Some(result) +} + // --------------------------------------------------------------------------- // Shared helpers // --------------------------------------------------------------------------- diff --git a/compiler/rustc_codegen_ssa/src/diagnostics.rs b/compiler/rustc_codegen_ssa/src/diagnostics.rs index 8aa2da904bd07..0e03a592165e7 100644 --- a/compiler/rustc_codegen_ssa/src/diagnostics.rs +++ b/compiler/rustc_codegen_ssa/src/diagnostics.rs @@ -695,7 +695,7 @@ pub(crate) struct StaticlibHideInternalSymbolsUnsupported { #[derive(Diagnostic)] #[diag( - "-Zstaticlib-rename-internal-symbols only supports ELF and Mach-O targets, but the target uses `{$binary_format}`" + "-Zstaticlib-rename-internal-symbols only supports ELF, Mach-O, and COFF targets, but the target uses `{$binary_format}`" )] pub(crate) struct StaticlibRenameInternalSymbolsUnsupported { pub binary_format: String, diff --git a/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs b/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs new file mode 100644 index 0000000000000..38cf724ee7d1b --- /dev/null +++ b/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs @@ -0,0 +1,200 @@ +//@ only-windows +//@ ignore-cross-compile + +use std::collections::HashSet; + +use run_make_support::object::read::archive::ArchiveFile; +use run_make_support::object::read::coff::ImageSymbol as _; +use run_make_support::object::{File, pe}; +use run_make_support::path_helpers::source_root; +use run_make_support::{cc, extra_c_flags, rfs, run, rustc, static_lib_name}; + +const EXPORTED: &[&str] = &["my_add", "my_hash_lookup", "call_internal", "my_safe_div"]; + +fn main() { + let hide_sibling = source_root().join("tests/run-make/staticlib-hide-internal-symbols"); + let rename_sibling = source_root().join("tests/run-make/staticlib-rename-internal-symbols"); + rfs::copy(hide_sibling.join("lib.rs"), "lib.rs"); + rfs::copy(hide_sibling.join("main.c"), "main.c"); + rfs::copy(rename_sibling.join("liba.rs"), "liba.rs"); + rfs::copy(rename_sibling.join("libb.rs"), "libb.rs"); + rfs::copy(rename_sibling.join("dual_main.c"), "dual_main.c"); + + test_basic_functionality(); + test_rs_suffix_present(); + test_dual_staticlib_linking(); + test_hide_and_rename(); +} + +fn test_basic_functionality() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("main.c").input(&lib_name).out_exe("main").args(extra_c_flags()).run(); + run("main"); + + rfs::remove_file(&lib_name); +} + +fn test_rs_suffix_present() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + let data = rfs::read(&lib_name); + check_rename_symbols(&data); + + rfs::remove_file(&lib_name); +} + +fn test_dual_staticlib_linking() { + let liba_name = static_lib_name("liba"); + let libb_name = static_lib_name("libb"); + + rustc() + .input("liba.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + rustc() + .input("libb.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run(); + + cc().input("dual_main.c") + .input(&liba_name) + .input(&libb_name) + .out_exe("dual_main") + .args(extra_c_flags()) + .run(); + run("dual_main"); +} + +/// On COFF, hiding is unsupported and must only produce a warning, while +/// renaming still applies. +fn test_hide_and_rename() { + let lib_name = static_lib_name("lib"); + + rustc() + .input("lib.rs") + .crate_type("staticlib") + .arg("-Zstaticlib-hide-internal-symbols") + .arg("-Zstaticlib-rename-internal-symbols") + .opt() + .run_unchecked() + .assert_stderr_contains( + "-Zstaticlib-hide-internal-symbols only supports ELF and Mach-O targets", + ) + .assert_exit_code(0); + + let data = rfs::read(&lib_name); + check_rename_symbols(&data); + + cc().input("main.c").input(&lib_name).out_exe("main").args(extra_c_flags()).run(); + run("main"); + + rfs::remove_file(&lib_name); +} + +fn check_rename_symbols(archive_data: &[u8]) { + let archive = ArchiveFile::parse(archive_data).unwrap(); + let mut found_exported = HashSet::new(); + let mut found_rs_suffix = false; + + for member in archive.members() { + let member = member.unwrap(); + if !member.name().ends_with(b".rcgu.o") { + continue; + } + // COFF header/symbol types have alignment 1, so odd-offset members + // parse directly from the borrowed slice. + let data = member.data(archive_data).unwrap(); + match File::parse(data) { + Ok(File::Coff(f)) => { + check_coff_symbols(f.coff_header(), data, &mut found_exported, &mut found_rs_suffix) + } + Ok(File::CoffBig(f)) => { + check_coff_symbols(f.coff_header(), data, &mut found_exported, &mut found_rs_suffix) + } + Ok(_) => panic!("unexpected object file format in archive member"), + Err(e) => panic!("failed to parse archive member: {e}"), + } + } + + assert!(found_rs_suffix, "expected to find at least one renamed symbol with .rs suffix"); + for expected in EXPORTED { + assert!( + found_exported.contains(*expected), + "expected to find exported symbol `{expected}` in archive" + ); + } +} + +fn check_coff_symbols( + header: &Coff, + data: &[u8], + found_exported: &mut HashSet, + found_rs_suffix: &mut bool, +) { + // ImageSymbol is 18 bytes; ImageSymbolEx (bigobj) is 20. + let sym_size = std::mem::size_of::(); + // i686 decorates symbol names with a leading underscore. + let strip_underscore = header.machine() == pe::IMAGE_FILE_MACHINE_I386; + let Ok(symbols) = header.symbols(data) else { return }; + let strings = symbols.strings(); + let symtab_base = header.pointer_to_symbol_table() as usize; + + for (index, symbol) in symbols.iter() { + let storage_class = symbol.storage_class(); + if storage_class != pe::IMAGE_SYM_CLASS_EXTERNAL + && storage_class != pe::IMAGE_SYM_CLASS_WEAK_EXTERNAL + { + continue; + } + if symbol.section_number() <= 0 { + continue; + } + // String-table references keep all four leading name bytes zero. + let name_field = symtab_base + index.0 * sym_size; + if data[name_field] == 0 { + assert!( + data[name_field + 1..name_field + 4] == [0, 0, 0], + "long-name symbol reference at offset {name_field} has non-zero padding bytes" + ); + } + let Ok(name_bytes) = symbol.name(strings) else { continue }; + let Ok(mut name) = str::from_utf8(name_bytes).map(String::from) else { continue }; + if strip_underscore { + name = name.strip_prefix('_').unwrap_or(&name).to_string(); + } + + if EXPORTED.contains(&name.as_str()) { + assert!( + !name.contains(".rs"), + "exported symbol `{name}` should not contain .rs suffix" + ); + found_exported.insert(name); + } else { + assert!( + name.contains(".rs"), + "internal symbol `{name}` should contain .rs suffix after rename" + ); + *found_rs_suffix = true; + } + } +} From 6d00f272fd193c15404616962e90be35cfc4fcc6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Sep 2026 14:57:31 +1000 Subject: [PATCH 0297/1309] Add a new `-Ztrack-diagnostics` test It covers a case that isn't currently covered: `-Ztrack-diagnostics` in combination with a `span_bug!` ICE. Notably, the "created at" line mentions `callbacks.rs`, which is the wrong location. This will be fixed in the next commit. --- tests/ui/track-diagnostics/track7.rs | 40 ++++++++++++++++++++++++ tests/ui/track-diagnostics/track7.stderr | 29 +++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/ui/track-diagnostics/track7.rs create mode 100644 tests/ui/track-diagnostics/track7.stderr diff --git a/tests/ui/track-diagnostics/track7.rs b/tests/ui/track-diagnostics/track7.rs new file mode 100644 index 0000000000000..f43c1e1a81c23 --- /dev/null +++ b/tests/ui/track-diagnostics/track7.rs @@ -0,0 +1,40 @@ +// This test checks that -Ztrack-diagnostics reports the correct source locations for an ICE +// triggered with `span_bug!`. +// +//@ compile-flags: -Zvalidate-mir -Ztrack-diagnostics +//@ rustc-env:RUST_BACKTRACE=0 +//@ failure-status: 101 +// +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@ normalize-stderr: "note: rustc .+ running on .+" -> "note: rustc $$VERSION running on $$TARGET" +//@ normalize-stderr: "/rustc(?:-dev)?/[a-z0-9.]+/" -> "" +//@ normalize-stderr: "track7\[....\]" -> "track7[HASH]" +// The test becomes too flaky if we care about exact args. If `-Z ui-testing` +// from compiletest and `-Z track-diagnostics` from `// compile-flags` at the +// top of this file are present, then assume all args are present. +//@ normalize-stderr: "note: compiler flags: .*-Z ui-testing.*-Z track-diagnostics" -> "note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics" + +#![feature(custom_mir, core_intrinsics)] +extern crate core; +use core::intrinsics::mir::*; + +fn bar(_x: i32) {} + +// Use of `mir!` here is just because it's an easy way to trigger a `span_bug!`. +#[custom_mir(dialect = "built")] +pub fn main() { + mir! { + let a: (i32, i32); + { + a = (1, 2); + Call(RET = bar(Move(a.0)), ReturnTo(retblock), UnwindContinue()) + //~^ ERROR broken MIR in + //~| ERROR encountered `Move` of a non-local, non-box place in `Call` terminator + } + retblock = { + Return() + } + } +} diff --git a/tests/ui/track-diagnostics/track7.stderr b/tests/ui/track-diagnostics/track7.stderr new file mode 100644 index 0000000000000..1b81276dd129b --- /dev/null +++ b/tests/ui/track-diagnostics/track7.stderr @@ -0,0 +1,29 @@ +error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:LL:CC: broken MIR in Item(DefId(0:6 ~ track7[HASH]::main)) (after pass LintAndRemoveUninhabited) at bb0[1]: + encountered `Move` of a non-local, non-box place in `Call` terminator: _0 = bar(move (_1.0: i32)) -> [return: bb1, unwind continue] + --> $DIR/track7.rs:LL:CC + | +LL | Call(RET = bar(Move(a.0)), ReturnTo(retblock), UnwindContinue()) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_interface/src/callbacks.rs:LL:CC + + +thread 'rustc' ($TID) panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC: +broken MIR in Item(DefId(0:6 ~ track7[HASH]::main)) (after pass LintAndRemoveUninhabited) at bb0[1]: +encountered `Move` of a non-local, non-box place in `Call` terminator: _0 = bar(move (_1.0: i32)) -> [return: bb1, unwind continue] +note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace + +error: the compiler unexpectedly panicked. This is a bug + +note: using internal features is not supported and expected to cause internal compiler errors when used incorrectly + +note: rustc $VERSION running on $TARGET + +note: compiler flags: ... -Z ui-testing ... -Z track-diagnostics + +query stack during panic: +#0 [mir_built] building MIR for `main` +#1 [has_ffi_unwind_calls] checking if `main` contains FFI-unwind calls +... and 3 other queries... use `env RUST_BACKTRACE=1` to see the full query stack +error: aborting due to 1 previous error + From 0e617d448a6b06792f642e636a7fc7f38c46eb76 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 17 Sep 2026 06:34:02 +1000 Subject: [PATCH 0298/1309] Adjust `bug!`/`span_bug!` emission PR #161873 moved these macros from `rustc_middle` to `rustc_span`. In doing so it made some undesirable changes. - The internal `emit_producing_nothing` became public. - It gave the macros different behaviour to function-based ICEs like `dcx.bug(..)` or `dcx.struct_bug(..).emit()`. - `ExplicitBug` is not used, so `report_ice` prints an extraneous, unintended "the compiler unexpectedly panicked" message. - It broke the interaction between `span_bug!` and `-Ztrack-diagnostics`. This commit adjusts things to avoid the undesirable changes. It required moving `ExplicitBug` to `rustc_span`. Setting `diag.emitted_at` fixed the `-Ztrack-diagnostics` problem, seen in the change from `callback.rs` to `validate.rs` in `track7.stderr`. `Box` output now occurs again in a few tests because the panic payload is `ExplicitBug` (which std doesn't know about) rather than `String`. That might be worth addressing in the future but it would require a different/additional mechanism and is beyond the scope of this PR. --- compiler/rustc_errors/src/diagnostic.rs | 9 +++-- compiler/rustc_errors/src/lib.rs | 5 +-- compiler/rustc_interface/src/callbacks.rs | 24 ++++++++---- compiler/rustc_span/src/macros.rs | 38 +++++++++++++++---- .../miri/tests/panic/mir-validation.stderr | 5 +-- tests/ui/intrinsics/not-overridden.stderr | 2 - ...tiple_definitions_attribute_merging.stderr | 4 +- .../proc_macro_generated_packed.stderr | 4 +- tests/ui/track-diagnostics/track7.stderr | 7 +--- 9 files changed, 60 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 5017f1228f2d0..dcaa81e37d2c9 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -93,10 +93,13 @@ pub struct DiagLocation { } impl DiagLocation { + pub fn from_location(loc: &'static panic::Location<'static>) -> Self { + DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() } + } + #[track_caller] pub fn caller() -> Self { - let loc = panic::Location::caller(); - DiagLocation { file: loc.file().into(), line: loc.line(), col: loc.column() } + Self::from_location(panic::Location::caller()) } } @@ -1294,7 +1297,7 @@ impl<'a, G> Diag<'a, G> { } /// Most `emit` methods use this as a starting point. - pub fn emit_producing_nothing(mut self) { + fn emit_producing_nothing(mut self) { let diag = self.take_diag(); self.dcx.emit_diagnostic(diag); } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 9ca0344058d7f..b32c83e04d9c0 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -57,6 +57,7 @@ pub use rustc_macros::msg; use rustc_macros::{Decodable, Encodable}; pub use rustc_span::ErrorGuaranteed; pub use rustc_span::fatal_error::{FatalError, FatalErrorMarker, catch_fatal_errors}; +pub use rustc_span::macros::ExplicitBug; use rustc_span::source_map::SourceMap; use rustc_span::{DUMMY_SP, Span}; use tracing::debug; @@ -256,10 +257,6 @@ fn as_substr<'a>(original: &'a str, suggestion: &'a str) -> Option<(usize, &'a s } } -/// Signifies that the compiler died with an explicit call to `.bug` -/// or `.span_bug` rather than a failed assertion, etc. -pub struct ExplicitBug; - /// Signifies that the compiler died due to a delayed bug rather than a failed /// assertion, etc. pub struct DelayedBugPanic; diff --git a/compiler/rustc_interface/src/callbacks.rs b/compiler/rustc_interface/src/callbacks.rs index 0d8b565b4e384..2b9170c80de21 100644 --- a/compiler/rustc_interface/src/callbacks.rs +++ b/compiler/rustc_interface/src/callbacks.rs @@ -13,7 +13,7 @@ use std::fmt; use std::fmt::Arguments; use std::panic::Location; -use rustc_errors::DiagInner; +use rustc_errors::{DiagInner, DiagLocation, Level}; use rustc_middle::dep_graph::{QuerySideEffect, TaskDepsRef}; use rustc_middle::ty::tls; use rustc_span::{Span, Symbol}; @@ -86,16 +86,26 @@ fn def_id_debug(def_id: rustc_hir::def_id::DefId, f: &mut fmt::Formatter<'_>) -> write!(f, ")") } -fn emit_bug_diagnostic(span: Option, args: Arguments<'_>, location: &Location<'_>) { +/// Returns true if it printed the diagnostic, which happens if a `tcx` is available. +fn emit_bug_diagnostic( + span: Option, + args: Arguments<'_>, + location: &'static Location<'static>, +) -> bool { tls::with_opt(move |tcx| { if let Some(tcx) = tcx { - let message = format!("{location}: {args}"); + let mut diag = DiagInner::new(Level::Bug, format!("{location}: {args}")); if let Some(span) = span { - tcx.dcx().struct_span_bug(span, message) - } else { - tcx.dcx().struct_bug(message) + diag.span = span.into(); } - .emit_producing_nothing(); + diag.emitted_at = DiagLocation::from_location(location); + // Emit the bug without aborting. We let `bug_impl` do the abort because it has + // `#[track_caller]` which gives a better location. (`#[track_caller]` doesn't work + // here because this function is called via a function pointer.) + tcx.dcx().emit_diagnostic(diag); + true + } else { + false } }) } diff --git a/compiler/rustc_span/src/macros.rs b/compiler/rustc_span/src/macros.rs index 9b042a2b416c5..db8b7ebbfa11f 100644 --- a/compiler/rustc_span/src/macros.rs +++ b/compiler/rustc_span/src/macros.rs @@ -1,10 +1,14 @@ use std::fmt; -use std::panic::Location; +use std::panic::{Location, panic_any}; use rustc_data_structures::AtomicRef; use crate::Span; +/// Signifies that the compiler died with an explicit call to `.bug` or `.span_bug` rather than a +/// failed assertion, etc. +pub struct ExplicitBug; + /// A macro for triggering an ICE. /// Calling `bug` instead of panicking will result in a nicer error message and should /// therefore be preferred over `panic`/`unreachable` or others. @@ -40,12 +44,32 @@ pub macro span_bug($span:expr, $($arg:tt)+){ #[cold] #[track_caller] -pub fn bug_impl(span: Option, args: fmt::Arguments<'_>, location: &Location<'_>) -> ! { - (*EMIT_BUG_DIAGNOSTIC)(span, args, location); - panic!("{args}") +pub fn bug_impl( + span: Option, + args: fmt::Arguments<'_>, + location: &'static Location<'static>, +) -> ! { + // Emit the bug without aborting. + let emitted = (*EMIT_BUG_DIAGNOSTIC)(span, args, location); + + if emitted { + // Panic with `ExplicitBug`, which tells `report_ice` that it's expected, e.g. originating + // from `bug!` or `dcx.emit_bug(..)`. + panic_any(ExplicitBug); + } else { + // Panic with just a string, which means it's unexpected. + panic_any(format!("{args}")); + } } -pub static EMIT_BUG_DIAGNOSTIC: AtomicRef, fmt::Arguments<'_>, &Location<'_>)> = - AtomicRef::new(&(default_emit_diagnostic as _)); +pub static EMIT_BUG_DIAGNOSTIC: AtomicRef< + fn(Option, fmt::Arguments<'_>, &'static Location<'static>) -> bool, +> = AtomicRef::new(&(default_emit_bug_diagnostic as _)); -fn default_emit_diagnostic(_: Option, _: fmt::Arguments<'_>, _: &Location<'_>) {} +fn default_emit_bug_diagnostic( + _: Option, + _args: fmt::Arguments<'_>, + _location: &'static Location<'static>, +) -> bool { + false +} diff --git a/src/tools/miri/tests/panic/mir-validation.stderr b/src/tools/miri/tests/panic/mir-validation.stderr index 115820510dd89..1d40c93d709e6 100644 --- a/src/tools/miri/tests/panic/mir-validation.stderr +++ b/src/tools/miri/tests/panic/mir-validation.stderr @@ -7,12 +7,9 @@ LL | *(tuple.0) = 1; thread 'rustc' ($TID) panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC: -broken MIR in Item(DefId) (after phase change to runtime-optimized) at bb0[1]: -place (*(_2.0: *mut i32)) has deref as a later projection (it is only permitted as the first projection) +Box stack backtrace: -error: the compiler unexpectedly panicked. This is a bug - diff --git a/tests/ui/intrinsics/not-overridden.stderr b/tests/ui/intrinsics/not-overridden.stderr index ae5586b2f0a85..45c5c37318b89 100644 --- a/tests/ui/intrinsics/not-overridden.stderr +++ b/tests/ui/intrinsics/not-overridden.stderr @@ -5,8 +5,6 @@ LL | unsafe { const_deallocate(std::ptr::null_mut(), 0, 0) } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: the compiler unexpectedly panicked. This is a bug - query stack during panic: end of query stack error: aborting due to 1 previous error diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr index 63bdcfddf3ca2..b8b33e3417bf7 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -17,9 +17,7 @@ LL | struct Dealigned(u8, T); | ^ -builtin derive created an unaligned reference -error: the compiler unexpectedly panicked. This is a bug - +Box query stack during panic: #0 [mir_built] building MIR for `::eq` #1 [check_unsafety] unsafety-checking `::eq` diff --git a/tests/ui/resolve/proc_macro_generated_packed.stderr b/tests/ui/resolve/proc_macro_generated_packed.stderr index 3e63abb4b9e6b..d8e160d0c6a03 100644 --- a/tests/ui/resolve/proc_macro_generated_packed.stderr +++ b/tests/ui/resolve/proc_macro_generated_packed.stderr @@ -8,9 +8,7 @@ LL | struct Dealigned(u8, T); | ^ -builtin derive created an unaligned reference -error: the compiler unexpectedly panicked. This is a bug - +Box query stack during panic: #0 [mir_built] building MIR for `::eq` #1 [check_unsafety] unsafety-checking `::eq` diff --git a/tests/ui/track-diagnostics/track7.stderr b/tests/ui/track-diagnostics/track7.stderr index 1b81276dd129b..61a615f782b8e 100644 --- a/tests/ui/track-diagnostics/track7.stderr +++ b/tests/ui/track-diagnostics/track7.stderr @@ -5,16 +5,13 @@ error: internal compiler error: compiler/rustc_mir_transform/src/validate.rs:LL: LL | Call(RET = bar(Move(a.0)), ReturnTo(retblock), UnwindContinue()) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: -Ztrack-diagnostics: created at compiler/rustc_interface/src/callbacks.rs:LL:CC + = note: -Ztrack-diagnostics: created at compiler/rustc_mir_transform/src/validate.rs:LL:CC thread 'rustc' ($TID) panicked at compiler/rustc_mir_transform/src/validate.rs:LL:CC: -broken MIR in Item(DefId(0:6 ~ track7[HASH]::main)) (after pass LintAndRemoveUninhabited) at bb0[1]: -encountered `Move` of a non-local, non-box place in `Call` terminator: _0 = bar(move (_1.0: i32)) -> [return: bb1, unwind continue] +Box note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -error: the compiler unexpectedly panicked. This is a bug - note: using internal features is not supported and expected to cause internal compiler errors when used incorrectly note: rustc $VERSION running on $TARGET From 653076c76960316dc6a88a88c020bb07072a35fe Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 18 Sep 2026 09:15:10 +0200 Subject: [PATCH 0299/1309] yeet AliasConstKind::opt_def_id --- .../rustc_hir_analysis/src/check/check.rs | 20 ++++++-- .../src/hir_ty_lowering/mod.rs | 48 +++++++++---------- compiler/rustc_middle/src/thir.rs | 2 +- .../rustc_middle/src/ty/abstract_const.rs | 11 +++-- .../src/thir/pattern/check_match.rs | 3 +- .../src/thir/pattern/const_to_pat.rs | 2 +- .../src/unstable/convert/stable/ty.rs | 10 ++-- compiler/rustc_type_ir/src/const_kind.rs | 10 ---- .../mgca/inherent-alias-default.rs | 15 ++++++ tests/ui/thir-print/str-patterns.stdout | 4 +- 10 files changed, 77 insertions(+), 48 deletions(-) create mode 100644 tests/ui/const-generics/mgca/inherent-alias-default.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 705bb780a3ecf..52b69e6050a32 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -775,9 +775,23 @@ pub(crate) fn check_item_type(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Result<(), if has_default { // need to store default and type of default let ct = tcx.const_param_default(param.def_id).skip_binder(); - if let ty::ConstKind::Alias(_, alias_const) = ct.kind() - && let Some(def_id) = alias_const.kind.opt_def_id() - { + if let ty::ConstKind::Alias(_, alias_const) = ct.kind() { + let def_id = match alias_const.kind { + ty::AliasConstKind::Projection { def_id } => def_id, + ty::AliasConstKind::InherentSelf { def_id } => { + // NOTE: typically, InherentSelf is illegal to pass to type_of, + // because the generic args are incorrect (type_of expects impl-form + // arguments). However, we are just checking ensure_ok().type_of(), + // we are not instantiating the result, so it's OK here. + def_id + } + ty::AliasConstKind::InherentImpl { .. } => span_bug!( + tcx.def_span(param.def_id), + "const_param_default should return an unnormalized constant, which should always be InherentSelf, not InherentImpl" + ), + ty::AliasConstKind::Free { def_id } => def_id, + ty::AliasConstKind::Anon { def_id } => def_id, + }; tcx.ensure_ok().type_of(def_id); } } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e89caa6aeff8c..ecfe5d3c2c7c2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -1480,9 +1480,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { )? { TypeRelativePath::AssocItem(alias_term) => { let alias_ct = alias_term.expect_ct(); - if let Some(def_id) = alias_ct.kind.opt_def_id() { - self.check_const_item_in_type_system(def_id, span)?; - } + self.check_const_item_in_type_system(alias_ct.kind, span)?; let ct = Const::new_alias(tcx, ty::IsRigid::No, alias_ct); let ct = self.check_param_uses_if_mcg(ct, span, false); Ok(ct) @@ -1948,13 +1946,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { item_segment, ty::AssocTag::Const, )?; - self.check_const_item_in_type_system(item_def_id, span)?; - let alias_const = ty::AliasConst::new( - tcx, - ty::AliasConstKind::Projection { def_id: item_def_id }, - item_args, - ); - Ok(Const::new_alias(tcx, ty::IsRigid::No, alias_const)) + let kind = ty::AliasConstKind::Projection { def_id: item_def_id }; + self.check_const_item_in_type_system(kind, span)?; + let alias = ty::AliasConst::new(tcx, kind, item_args); + Ok(Const::new_alias(tcx, ty::IsRigid::No, alias)) } /// Lower a [resolved][hir::QPath::Resolved] (type-level) associated item path. @@ -2879,7 +2874,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { self.lower_const_param(def_id, hir_id) } Res::Def(DefKind::Const, did) => { - if let Err(guar) = self.check_const_item_in_type_system(did, span) { + let kind = ty::AliasConstKind::Free { def_id: did }; + if let Err(guar) = self.check_const_item_in_type_system(kind, span) { return Const::new_error(self.tcx(), guar); } @@ -2888,11 +2884,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let _ = self .prohibit_generic_args(leading_segments.iter(), GenericsArgsErrExtend::None); let args = self.lower_generic_args_of_path_segment(span, did, segment); - ty::Const::new_alias( - tcx, - ty::IsRigid::No, - ty::AliasConst::new(tcx, ty::AliasConstKind::Free { def_id: did }, args), - ) + let alias = ty::AliasConst::new(tcx, kind, args); + ty::Const::new_alias(tcx, ty::IsRigid::No, alias) } Res::Def(kind @ DefKind::Ctor(ctor_of, CtorKind::Const), did) => { assert_eq!(opt_self_ty, None); @@ -3126,18 +3119,27 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { /// `def_id` is a const item used in the type system. Checks if that's OK. fn check_const_item_in_type_system( &self, - def_id: DefId, + alias_const: ty::AliasConstKind<'tcx>, span: Span, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - if tcx.features().generic_const_args() || tcx.is_direct_const(def_id) { + if tcx.features().generic_const_args() || alias_const.is_direct_const(tcx) { Ok(()) } else { let mut err = self .dcx() .struct_span_err(span, "use of `const` in the type system not marked as direct"); - if let Some(local_def_id) = def_id.as_local() { - if let Some(body_id) = tcx.hir_node_by_def_id(local_def_id).body_id() { + let hir_node = match alias_const { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } + | ty::AliasConstKind::Anon { def_id } => { + def_id.as_local().map(|id| tcx.hir_node_by_def_id(id)) + } + }; + if let Some(hir_node) = hir_node { + if let Some(body_id) = hir_node.body_id() { let body_span = tcx.hir_body(body_id).value.span; err.multipart_suggestion( @@ -3148,10 +3150,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ], Applicability::MaybeIncorrect, ); - } else if let DefKind::AssocConst = tcx.def_kind(def_id) - && let DefKind::Trait = tcx.def_kind(tcx.parent(def_id)) - { - let node = tcx.hir_node_by_def_id(local_def_id).expect_trait_item(); + } else if let ty::AliasConstKind::Projection { .. } = alias_const { + let node = hir_node.expect_trait_item(); let sp = node.span.shrink_to_lo(); err.span_suggestion_verbose( sp, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index fe7b1bf493051..b20dfe68d98e2 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -661,7 +661,7 @@ pub struct PatExtra<'tcx> { /// /// This is used by some diagnostics for non-exhaustive matches, to map /// the pattern node back to the `DefId` of its original constant. - pub expanded_const: Option, + pub expanded_const: Option>, /// User-written types that must be preserved into MIR so that they can be /// checked. diff --git a/compiler/rustc_middle/src/ty/abstract_const.rs b/compiler/rustc_middle/src/ty/abstract_const.rs index 2853c43ae079d..2227841923514 100644 --- a/compiler/rustc_middle/src/ty/abstract_const.rs +++ b/compiler/rustc_middle/src/ty/abstract_const.rs @@ -52,9 +52,14 @@ impl<'tcx> TyCtxt<'tcx> { } fn fold_const(&mut self, c: Const<'tcx>) -> Const<'tcx> { let ct = match c.kind() { - ty::ConstKind::Alias(_, alias_const) - if let Some(def_id) = alias_const.kind.opt_def_id() => - { + ty::ConstKind::Alias(_, alias_const) => { + let def_id = match alias_const.kind { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } + | ty::AliasConstKind::Anon { def_id } => def_id, + }; match self.tcx.thir_abstract_const(def_id) { Err(e) => ty::Const::new_error(self.tcx, e), Ok(Some(bac)) => { diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index befe4d67253a3..3414ee751585c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1229,8 +1229,7 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx> // The pattern must be a named constant, and the name that appears in // the pattern's source text must resemble a plain identifier without any // `::` namespace separators or other non-identifier characters. - if let Some(def_id) = try { pat.extra.as_deref()?.expanded_const? } - && tcx.def_kind(def_id) == DefKind::Const + if let ty::AliasConstKind::Free { def_id } = pat.extra.as_deref()?.expanded_const? && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span) && snippet.chars().all(|c| c.is_alphanumeric() || c == '_') { diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 55eef6006f278..e24ef5ea5b52d 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -224,7 +224,7 @@ impl<'tcx> ConstToPat<'tcx> { // Mark the pattern to indicate that it is the result of lowering a named // constant. This is used for diagnostics. - thir_pat.extra.get_or_insert_default().expanded_const = alias_const.kind.opt_def_id(); + thir_pat.extra.get_or_insert_default().expanded_const = Some(alias_const.kind); thir_pat } diff --git a/compiler/rustc_public/src/unstable/convert/stable/ty.rs b/compiler/rustc_public/src/unstable/convert/stable/ty.rs index ad1aa1b47132a..c3eebccb6b762 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/ty.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/ty.rs @@ -557,9 +557,13 @@ impl<'tcx> Stable<'tcx> for ty::Const<'tcx> { } ty::ConstKind::Param(param) => crate::ty::TyConstKind::Param(param.stable(tables, cx)), ty::ConstKind::Alias(_, alias_const) => { - let Some(def_id) = alias_const.kind.opt_def_id() else { - // FIXME: implement (both AliasTy and AliasConst will be needing this soon) - panic!("non-defid alias consts are not supported by rustc_public at the moment") + // rustc_public must change its API once we introduce a variant without a def_id. + let def_id = match alias_const.kind { + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } + | ty::AliasConstKind::Anon { def_id } => def_id, }; crate::ty::TyConstKind::Unevaluated( tables.const_def(def_id), diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index dd0578610a2a0..f66322e034814 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -160,16 +160,6 @@ impl AliasConstKind { AliasConstKind::Anon { def_id } => interner.def_span(def_id.into()), } } - - pub fn opt_def_id(self) -> Option { - match self { - AliasConstKind::Projection { def_id } => Some(def_id.into()), - AliasConstKind::InherentSelf { def_id } => Some(def_id.into()), - AliasConstKind::InherentImpl { def_id } => Some(def_id.into()), - AliasConstKind::Free { def_id } => Some(def_id.into()), - AliasConstKind::Anon { def_id } => Some(def_id.into()), - } - } } rustc_index::newtype_index! { diff --git a/tests/ui/const-generics/mgca/inherent-alias-default.rs b/tests/ui/const-generics/mgca/inherent-alias-default.rs new file mode 100644 index 0000000000000..9ba6d1d15e856 --- /dev/null +++ b/tests/ui/const-generics/mgca/inherent-alias-default.rs @@ -0,0 +1,15 @@ +//@ check-pass +//! rustc_hir_analysis::check_item_type does type_of() on the default value. This is wonky, because +//! the generic args are in Self format at that point, not in impl format, so the result can't be +//! used with the Self-format args. However, it does not instantiate the result, it just does +//! ensure_ok(). This test just makes sure that codepath is hit in tests. +#![feature(min_generic_const_args, inherent_associated_types)] + +struct Struct(T1, T2, T3); +impl Struct { + const INHERENT: usize = core::direct_const_arg!(2); +} + +struct WithDefault::INHERENT) }>; + +fn main() {} diff --git a/tests/ui/thir-print/str-patterns.stdout b/tests/ui/thir-print/str-patterns.stdout index da1f86b8fc591..61bcbaef5029a 100644 --- a/tests/ui/thir-print/str-patterns.stdout +++ b/tests/ui/thir-print/str-patterns.stdout @@ -46,7 +46,9 @@ Thir { extra: Some( PatExtra { expanded_const: Some( - DefId(0:4 ~ str_patterns[fc71]::CONSTANT), + Free { + def_id: DefId(0:4 ~ str_patterns[fc71]::CONSTANT), + }, ), ascriptions: [], }, From 172ae8c9af667212edb97a90e3bb55be3a5417a5 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 18 Sep 2026 17:23:43 +1000 Subject: [PATCH 0300/1309] Declare multi-kind constants for MacroKinds If rmeta encoding has to define these constants anyway, we might as well provide them as inherent constants and use them in `descr` too. In current versions of bitflags, flags can be combined in const contexts by calling `union` instead of using the overloaded `|` operator. --- compiler/rustc_hir/src/def.rs | 19 +++++++++++++++---- compiler/rustc_metadata/src/rmeta/table.rs | 18 +++++------------- 2 files changed, 20 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 6deab943b836a..34a7c389d5158 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -55,6 +55,17 @@ impl From for MacroKinds { } impl MacroKinds { + // Constants to allow easy pattern-matching on any combination. + /// `ATTR | BANG` + pub const ATTR_BANG: MacroKinds = MacroKinds::ATTR.union(MacroKinds::BANG); + /// `DERIVE | BANG` + pub const DERIVE_BANG: MacroKinds = MacroKinds::DERIVE.union(MacroKinds::BANG); + /// `DERIVE | ATTR` + pub const DERIVE_ATTR: MacroKinds = MacroKinds::DERIVE.union(MacroKinds::ATTR); + /// `DERIVE | ATTR | BANG` + pub const DERIVE_ATTR_BANG: MacroKinds = + MacroKinds::DERIVE.union(MacroKinds::ATTR).union(MacroKinds::BANG); + /// Convert the MacroKinds to a static string. /// /// This hardcodes all the possibilities, in order to return a static string. @@ -64,10 +75,10 @@ impl MacroKinds { Self::BANG => "macro", Self::ATTR => "attribute macro", Self::DERIVE => "derive macro", - _ if self == (Self::ATTR | Self::BANG) => "attribute/function macro", - _ if self == (Self::DERIVE | Self::BANG) => "derive/function macro", - _ if self == (Self::ATTR | Self::DERIVE) => "attribute/derive macro", - _ if self.is_all() => "attribute/derive/function macro", + Self::ATTR_BANG => "attribute/function macro", + Self::DERIVE_BANG => "derive/function macro", + Self::DERIVE_ATTR => "attribute/derive macro", + Self::DERIVE_ATTR_BANG => "attribute/derive/function macro", _ if self.is_empty() => "useless macro", _ => unreachable!(), } diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 811d370248dd9..7b53ebba8adfc 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -140,16 +140,8 @@ macro_rules! defaulted_enum { } } -// Workaround; need const traits to construct bitflags in a const -macro_rules! const_macro_kinds { - ($($name:ident),+$(,)?) => (MacroKinds::from_bits_truncate($(MacroKinds::$name.bits())|+)) -} -const MACRO_KINDS_ATTR_BANG: MacroKinds = const_macro_kinds!(ATTR, BANG); -const MACRO_KINDS_DERIVE_BANG: MacroKinds = const_macro_kinds!(DERIVE, BANG); -const MACRO_KINDS_DERIVE_ATTR: MacroKinds = const_macro_kinds!(DERIVE, ATTR); -const MACRO_KINDS_DERIVE_ATTR_BANG: MacroKinds = const_macro_kinds!(DERIVE, ATTR, BANG); // Ensure that we get a compilation error if MacroKinds gets extended without updating metadata. -const _: () = assert!(MACRO_KINDS_DERIVE_ATTR_BANG.is_all()); +const _: () = assert!(MacroKinds::DERIVE_ATTR_BANG.is_all()); fixed_size_enum! { DefKind { @@ -195,10 +187,10 @@ fixed_size_enum! { ( Macro(MacroKinds::BANG) ) ( Macro(MacroKinds::ATTR) ) ( Macro(MacroKinds::DERIVE) ) - ( Macro(MACRO_KINDS_ATTR_BANG) ) - ( Macro(MACRO_KINDS_DERIVE_ATTR) ) - ( Macro(MACRO_KINDS_DERIVE_BANG) ) - ( Macro(MACRO_KINDS_DERIVE_ATTR_BANG) ) + ( Macro(MacroKinds::ATTR_BANG) ) + ( Macro(MacroKinds::DERIVE_ATTR) ) + ( Macro(MacroKinds::DERIVE_BANG) ) + ( Macro(MacroKinds::DERIVE_ATTR_BANG) ) ( SyntheticCoroutineBody ) ( TestBinderConstraints ) } unreachable { From d3cc844844c9d3d2d2b95596017cbb8026869320 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 18 Sep 2026 10:41:13 +0200 Subject: [PATCH 0301/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-18. --- compiler/rustc_codegen_cranelift/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index d7e313a7a33ed..ec7694364a8c9 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-11" +channel = "nightly-2026-09-18" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 44d6e57165985b97a890d670a281deb15d008bf3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 10:47:41 +0200 Subject: [PATCH 0302/1309] sembr src/offload/installation.md --- src/doc/rustc-dev-guide/src/offload/installation.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md index db7b69715f078..baf689f458077 100644 --- a/src/doc/rustc-dev-guide/src/offload/installation.md +++ b/src/doc/rustc-dev-guide/src/offload/installation.md @@ -21,7 +21,8 @@ cd rust If you would rather reuse an existing clang than build one, drop `--enable-clang` and pass `--enable-llvm-offload-clang-dir=` -instead. It should match the (major version of the) LLVM in `src/llvm-project`. +instead. +It should match the (major version of the) LLVM in `src/llvm-project`. Afterwards you can build rustc using: ```console From ae341a25a0a6cc5129978cd391bc02c824275512 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 10:48:43 +0200 Subject: [PATCH 0303/1309] sembr src/test-implementation.md --- .../src/test-implementation.md | 86 ++++++++++--------- 1 file changed, 45 insertions(+), 41 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/test-implementation.md b/src/doc/rustc-dev-guide/src/test-implementation.md index 707ba040609e0..a3739ad2fdae6 100644 --- a/src/doc/rustc-dev-guide/src/test-implementation.md +++ b/src/doc/rustc-dev-guide/src/test-implementation.md @@ -2,8 +2,8 @@ -Many Rust programmers rely on a built-in attribute called `#[test]`. All -you have to do is mark a function and include some asserts like so: +Many Rust programmers rely on a built-in attribute called `#[test]`. +All you have to do is mark a function and include some asserts like so: ```rust,ignore @@ -14,9 +14,9 @@ fn my_test() { ``` When this program is compiled using `rustc --test` or `cargo test`, it will -produce an executable that can run this, and any other test function. This -method of testing allows tests to live alongside code in an organic way. You -can even put tests inside private modules: +produce an executable that can run this, and any other test function. +This method of testing allows tests to live alongside code in an organic way. +You can even put tests inside private modules: ```rust,ignore mod my_priv_mod { @@ -30,22 +30,23 @@ mod my_priv_mod { ``` Private items can thus be easily tested without worrying about how to expose -them to any sort of external testing apparatus. This is key to the -ergonomics of testing in Rust. Semantically, however, it's rather odd. +them to any sort of external testing apparatus. +This is key to the ergonomics of testing in Rust. +Semantically, however, it's rather odd. How does any sort of `main` function invoke these tests if they're not visible? What exactly is `rustc --test` doing? `#[test]` is implemented as a syntactic transformation inside the compiler's -[`rustc_ast`][rustc_ast]. Essentially, it's a fancy [`macro`] that -rewrites the crate in 3 steps: +[`rustc_ast`][rustc_ast]. +Essentially, it's a fancy [`macro`] that rewrites the crate in 3 steps: ## Step 1: Re-Exporting As mentioned earlier, tests can exist inside private modules, so we need a -way of exposing them to the main function, without breaking any existing -code. To that end, [`rustc_ast`][rustc_ast] will create local modules called -`__test_reexports` that recursively reexport tests. This expansion translates -the above example into: +way of exposing them to the main function, without breaking any existing code. +To that end, [`rustc_ast`][rustc_ast] will create local modules called +`__test_reexports` that recursively reexport tests. +This expansion translates the above example into: ```rust,ignore mod my_priv_mod { @@ -61,24 +62,27 @@ mod my_priv_mod { } ``` -Now, our test can be accessed as -`my_priv_mod::__test_reexports::test_priv_func`. For deeper module -structures, `__test_reexports` will reexport modules that contain tests, so a -test at `a::b::my_test` becomes -`a::__test_reexports::b::__test_reexports::my_test`. While this process seems -pretty safe, what happens if there is an existing `__test_reexports` module? +Now, our test can be accessed as `my_priv_mod::__test_reexports::test_priv_func`. +For deeper module structures, `__test_reexports` will reexport modules that contain tests, so a +test at `a::b::my_test` becomes `a::__test_reexports::b::__test_reexports::my_test`. +While this process seems pretty safe, +what happens if there is an existing `__test_reexports` module? The answer: nothing. To explain, we need to understand how Rust's [Abstract Syntax Tree][ast] -represents [identifiers][Ident]. The name of every function, variable, module, -etc. is not stored as a string, but rather as an opaque [Symbol][Symbol] which -is essentially an ID number for each identifier. The compiler keeps a separate +represents [identifiers][Ident]. +The name of every function, variable, module, +etc. +is not stored as a string, but rather as an opaque [Symbol][Symbol] which +is essentially an ID number for each identifier. +The compiler keeps a separate hashtable that allows us to recover the human-readable name of a Symbol when -necessary (such as when printing a syntax error). When the compiler generates -the `__test_reexports` module, it generates a new [Symbol][Symbol] for the +necessary (such as when printing a syntax error). +When the compiler generates the `__test_reexports` module, +it generates a new [Symbol][Symbol] for the identifier, so while the compiler-generated `__test_reexports` may share a name -with your hand-written one, it will not share a [Symbol][Symbol]. This -technique prevents name collision during code generation and is the foundation +with your hand-written one, it will not share a [Symbol][Symbol]. +This technique prevents name collision during code generation and is the foundation of Rust's [`macro`] hygiene. ## Step 2: Harness generation @@ -96,20 +100,20 @@ pub fn main() { Here `path::to::test1` is a constant of type [`test::TestDescAndFn`][tdaf]. -While this transformation is simple, it gives us a lot of insight into how -tests are actually run. The tests are aggregated into an array and passed to -a test runner called `test_main_env_args`. We'll come back to exactly what -[`TestDescAndFn`][tdaf] is, but for now, the key takeaway is that there is a crate -called [`test`][test] that is part of Rust core, that implements all of the -runtime for testing. [`test`][test]'s interface is unstable, so the only stable way +While this transformation is simple, it gives us a lot of insight into how tests are actually run. +The tests are aggregated into an array and passed to a test runner called `test_main_env_args`. +We'll come back to exactly what [`TestDescAndFn`][tdaf] is, +but for now, the key takeaway is that there is a crate +called [`test`][test] that is part of Rust core, that implements all of the runtime for testing. +[`test`][test]'s interface is unstable, so the only stable way to interact with it is through the `#[test]` macro. ## Step 3: Test object generation If you've written tests in Rust before, you may be familiar with some of the -optional attributes available on test functions. For example, a test can be -annotated with `#[should_panic]` if we expect the test to cause a panic. It -looks something like this: +optional attributes available on test functions. +For example, a test can be annotated with `#[should_panic]` if we expect the test to cause a panic. +It looks something like this: ```rust,ignore #[test] @@ -120,12 +124,12 @@ fn foo() { ``` This means our tests are more than just simple functions, they have -configuration information as well. `test` encodes this configuration data into -a `struct` called [`TestDesc`]. For each test function in a crate, -[`rustc_ast`][rustc_ast] will parse its attributes and generate a [`TestDesc`] -instance. It then combines the [`TestDesc`] and test function into the -predictably named [`TestDescAndFn`][tdaf] `struct`, that [`test_main_env_args`] -operates on. +configuration information as well. +`test` encodes this configuration data into a `struct` called [`TestDesc`]. +For each test function in a crate, +[`rustc_ast`][rustc_ast] will parse its attributes and generate a [`TestDesc`] instance. +It then combines the [`TestDesc`] and test function into the +predictably named [`TestDescAndFn`][tdaf] `struct`, that [`test_main_env_args`] operates on. For a given test, the generated [`TestDescAndFn`][tdaf] instance looks like so: ```rust,ignore From 9327b11234231777f8bcdc6d672f1fae4b648510 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 10:52:27 +0200 Subject: [PATCH 0304/1309] redundant --- src/doc/rustc-dev-guide/src/test-implementation.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/test-implementation.md b/src/doc/rustc-dev-guide/src/test-implementation.md index a3739ad2fdae6..77146b8a71d33 100644 --- a/src/doc/rustc-dev-guide/src/test-implementation.md +++ b/src/doc/rustc-dev-guide/src/test-implementation.md @@ -73,15 +73,15 @@ To explain, we need to understand how Rust's [Abstract Syntax Tree][ast] represents [identifiers][Ident]. The name of every function, variable, module, etc. -is not stored as a string, but rather as an opaque [Symbol][Symbol] which +is not stored as a string, but rather as an opaque [Symbol] which is essentially an ID number for each identifier. The compiler keeps a separate hashtable that allows us to recover the human-readable name of a Symbol when necessary (such as when printing a syntax error). When the compiler generates the `__test_reexports` module, -it generates a new [Symbol][Symbol] for the +it generates a new [Symbol] for the identifier, so while the compiler-generated `__test_reexports` may share a name -with your hand-written one, it will not share a [Symbol][Symbol]. +with your hand-written one, it will not share a [Symbol]. This technique prevents name collision during code generation and is the foundation of Rust's [`macro`] hygiene. From 8a9db74b79ecb82312c230b9813bd9afd38e9b6d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 10:56:06 +0200 Subject: [PATCH 0305/1309] whitespace --- src/doc/rustc-dev-guide/src/test-implementation.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/test-implementation.md b/src/doc/rustc-dev-guide/src/test-implementation.md index 77146b8a71d33..cf2c6fb1dc9e1 100644 --- a/src/doc/rustc-dev-guide/src/test-implementation.md +++ b/src/doc/rustc-dev-guide/src/test-implementation.md @@ -1,7 +1,5 @@ # The `#[test]` attribute - - Many Rust programmers rely on a built-in attribute called `#[test]`. All you have to do is mark a function and include some asserts like so: From ec4984195ef7c7b6989aadc276fc99620c7762a9 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 11:19:23 +0200 Subject: [PATCH 0306/1309] reflow --- .../rustc-dev-guide/src/test-implementation.md | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/test-implementation.md b/src/doc/rustc-dev-guide/src/test-implementation.md index cf2c6fb1dc9e1..5df7d8d304d22 100644 --- a/src/doc/rustc-dev-guide/src/test-implementation.md +++ b/src/doc/rustc-dev-guide/src/test-implementation.md @@ -69,16 +69,13 @@ The answer: nothing. To explain, we need to understand how Rust's [Abstract Syntax Tree][ast] represents [identifiers][Ident]. -The name of every function, variable, module, -etc. -is not stored as a string, but rather as an opaque [Symbol] which -is essentially an ID number for each identifier. -The compiler keeps a separate -hashtable that allows us to recover the human-readable name of a Symbol when -necessary (such as when printing a syntax error). +The name of every function, variable, module, etc. is not stored as a string, +but rather as an opaque [Symbol] which is essentially an ID number for each identifier. +The compiler keeps a separate hashtable that allows us to recover +the human-readable name of a Symbol when necessary (such as when printing a syntax error). When the compiler generates the `__test_reexports` module, -it generates a new [Symbol] for the -identifier, so while the compiler-generated `__test_reexports` may share a name +it generates a new [Symbol] for the identifier, +so while the compiler-generated `__test_reexports` may share a name with your hand-written one, it will not share a [Symbol]. This technique prevents name collision during code generation and is the foundation of Rust's [`macro`] hygiene. From 9e7d4b22edf5c5fa303673c52f2985f7ea823748 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 14:54:42 +1000 Subject: [PATCH 0307/1309] Don't double-allocate `OwnerInfo` `into_owner_info` arena-allocates the created `OwnerInfo`. `ItemLowerer::with_lctx` calls `into_owner_info` and then re-arena-allocates the returned `OwnerInfo` (the reference, not the entire struct). This commit removes the latter. --- compiler/rustc_ast_lowering/src/item.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index edf184f568b22..24d5a80c59fab 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -62,8 +62,7 @@ impl<'hir> ItemLowerer<'_, 'hir> { let item = f(&mut lctx); - let info = lctx.curr_owner.into_owner_info(self.tcx, item); - hir::MaybeOwner::Owner(lctx.arena.alloc(info)) + hir::MaybeOwner::Owner(lctx.curr_owner.into_owner_info(self.tcx, item)) } #[instrument(level = "debug", skip(self, c))] From 9a03326dc02ee524716005615061b5494093bc93 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 14:59:45 +1000 Subject: [PATCH 0308/1309] Convert some `&mut self` to `&self` in the lowerer --- compiler/rustc_ast_lowering/src/item.rs | 12 ++++++------ compiler/rustc_ast_lowering/src/lib.rs | 12 ++++++------ 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 24d5a80c59fab..7fe5a089fe155 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -54,7 +54,7 @@ fn add_ty_alias_where_clause( impl<'hir> ItemLowerer<'_, 'hir> { fn with_lctx( - &mut self, + &self, owner: NodeId, f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, ) -> hir::MaybeOwner<'hir> { @@ -66,7 +66,7 @@ impl<'hir> ItemLowerer<'_, 'hir> { } #[instrument(level = "debug", skip(self, c))] - pub(super) fn lower_crate(&mut self, c: &Crate) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_crate(&self, c: &Crate) -> hir::MaybeOwner<'hir> { self.with_lctx(CRATE_NODE_ID, |lctx| { debug_assert_eq!(lctx.curr_owner.owner_id(), CRATE_OWNER_ID); let module = lctx.lower_mod(&c.items, &c.spans); @@ -76,19 +76,19 @@ impl<'hir> ItemLowerer<'_, 'hir> { } #[instrument(level = "debug", skip(self))] - pub(super) fn lower_item(&mut self, item: &Item) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_item(&self, item: &Item) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) } - pub(super) fn lower_trait_item(&mut self, item: &AssocItem) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_trait_item(&self, item: &AssocItem) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::TraitItem(lctx.lower_trait_item(item))) } - pub(super) fn lower_impl_item(&mut self, item: &AssocItem) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_impl_item(&self, item: &AssocItem) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::ImplItem(lctx.lower_impl_item(item))) } - pub(super) fn lower_foreign_item(&mut self, item: &ForeignItem) -> hir::MaybeOwner<'hir> { + pub(super) fn lower_foreign_item(&self, item: &ForeignItem) -> hir::MaybeOwner<'hir> { self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 19c37f4a76065..eb64d5027cdba 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -783,7 +783,7 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { return fallback_to_ancestor(tcx.local_parent(def_id)); }; - let mut item_lowerer = item::ItemLowerer { tcx, resolver: &*resolver }; + let item_lowerer = item::ItemLowerer { tcx, resolver: &*resolver }; let item = match &node { // The item existed in the AST. @@ -982,7 +982,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } #[instrument(level = "trace", skip(self))] - fn lower_res(&mut self, res: Res) -> Res { + fn lower_res(&self, res: Res) -> Res { let res: Result = res.apply_id(|id| { let owner = self.curr_owner.owner_id(); let local_id = @@ -999,11 +999,11 @@ impl<'hir> LoweringContext<'_, 'hir> { res.unwrap_or(Res::Err) } - fn expect_full_res(&mut self, id: NodeId) -> Res { + fn expect_full_res(&self, id: NodeId) -> Res { self.get_partial_res(id).map_or(Res::Err, |pr| pr.expect_full_res()) } - fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS> { + fn lower_import_res(&self, id: NodeId, span: Span) -> PerNS> { debug_assert_eq!(id, self.curr_owner.owner.id); let per_ns = self.curr_owner.owner.import_res.map(|res| res.map(|res| self.lower_res(res))); if per_ns.is_empty() { @@ -3058,7 +3058,7 @@ impl<'hir> LoweringContext<'_, 'hir> { })) } - fn lower_unsafe_source(&mut self, u: UnsafeSource) -> hir::UnsafeSource { + fn lower_unsafe_source(&self, u: UnsafeSource) -> hir::UnsafeSource { match u { CompilerGenerated => hir::UnsafeSource::CompilerGenerated, UserProvided => hir::UnsafeSource::UserProvided, @@ -3066,7 +3066,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_trait_bound_modifiers( - &mut self, + &self, modifiers: TraitBoundModifiers, ) -> hir::TraitBoundModifiers { let constness = match modifiers.constness { From 990c292e4178cff8526a50aa47221936a5440feb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 15:07:48 +1000 Subject: [PATCH 0309/1309] Reduce the scope of a local --- compiler/rustc_ast_lowering/src/lib.rs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index eb64d5027cdba..087182e43f95c 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1647,8 +1647,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.lower_array_length_to_const_arg(length), ), TyKind::TraitObject(bounds, kind) => { - let mut lifetime_bound = None; let (bounds, lifetime_bound) = self.with_dyn_type_scope(true, |this| { + let mut lifetime_bound = None; let bounds = this.arena.alloc_from_iter(bounds.iter().filter_map(|bound| match bound { // We can safely ignore constness here since AST validation @@ -1681,9 +1681,7 @@ impl<'hir> LoweringContext<'_, 'hir> { None } })); - let lifetime_bound = - lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span)); - (bounds, lifetime_bound) + (bounds, lifetime_bound.unwrap_or_else(|| this.elided_dyn_bound(t.span))) }); hir::TyKind::TraitObject(bounds, TaggedRef::new(lifetime_bound, *kind)) } From 9b817c55d6e7cd0bc232952bbc4661b833a9b601 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 15:08:45 +1000 Subject: [PATCH 0310/1309] Rename `LoweringContext::current_item` As `LoweringContext::current_item_span`, because it *is* a span. --- compiler/rustc_ast_lowering/src/expr.rs | 4 ++-- compiler/rustc_ast_lowering/src/lib.rs | 10 +++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index 1c1b9a247f7a2..c3bc86a352644 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -1018,7 +1018,7 @@ impl<'hir> LoweringContext<'_, 'hir> { expr.span, hir::ExprKind::Err(self.dcx().emit_err(AwaitOnlyInAsyncFnAndBlocks { await_kw_span, - item_span: self.current_item, + item_span: self.current_item_span, })), ); return hir::ExprKind::Block( @@ -1712,7 +1712,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } Some(hir::CoroutineKind::Coroutine(_)) => false, None => { - let suggestion = self.current_item.map(|s| s.shrink_to_lo()); + let suggestion = self.current_item_span.map(|s| s.shrink_to_lo()); self.dcx().emit_err(YieldInClosure { span, suggestion }); self.coroutine_kind = Some(hir::CoroutineKind::Coroutine(Movability::Movable)); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 087182e43f95c..b9d6f478c9ac0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -296,7 +296,7 @@ struct LoweringContext<'a, 'hir> { /// Used to get the current `fn`'s def span to point to when using `await` /// outside of an `async fn`. - current_item: Option, + current_item_span: Option, try_block_scope: TryBlockScope, loop_scope: Option, @@ -366,7 +366,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { is_in_dyn_type: false, coroutine_kind: None, task_context: None, - current_item: None, + current_item_span: None, move_expr_bindings: Vec::new(), lowering_move_expr_initializer: false, @@ -1154,8 +1154,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn with_new_scopes(&mut self, scope_span: Span, f: impl FnOnce(&mut Self) -> T) -> T { - let current_item = self.current_item; - self.current_item = Some(scope_span); + let current_item_span = self.current_item_span; + self.current_item_span = Some(scope_span); let was_in_loop_condition = self.is_in_loop_condition; self.is_in_loop_condition = false; @@ -1172,7 +1172,7 @@ impl<'hir> LoweringContext<'_, 'hir> { self.is_in_loop_condition = was_in_loop_condition; - self.current_item = current_item; + self.current_item_span = current_item_span; ret } From 3ee39bdf7cc213a7e4e7ff70d91948302f485dfc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 15:09:32 +1000 Subject: [PATCH 0311/1309] Fix an inconsistent comment --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b9d6f478c9ac0..609644804b203 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -824,7 +824,7 @@ enum GenericArgsMode { ParenSugar, /// Allow RTN, don't allow paren sugar. ReturnTypeNotation, - // Error if parenthesized generics or RTN are encountered. + /// Error if parenthesized generics or RTN are encountered. Err, /// Silence errors when lowering generics. Only used with `Res::Err`. Silence, From 6e7d014afa5e089a0ffab69c738ca635bfbfd963 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 21:50:32 +1000 Subject: [PATCH 0312/1309] Inline and remove `lower_delim_args` It's trivial and has a single call site. --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 4 ---- 2 files changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 7fe5a089fe155..72f72d22fb13a 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -543,7 +543,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } ItemKind::MacroDef(ident, MacroDef { body, macro_rules, eii_declaration: _ }) => { let ident = self.lower_ident(*ident); - let body = Box::new(self.lower_delim_args(body)); + let body = body.clone(); let def_id = self.curr_owner.owner.def_id; let def_kind = self.tcx.def_kind(def_id); let DefKind::Macro(macro_kinds) = def_kind else { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 609644804b203..16d098d1c4d75 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1261,10 +1261,6 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_delim_args(&self, args: &DelimArgs) -> DelimArgs { - args.clone() - } - /// Lower an associated item constraint. #[instrument(level = "debug", skip_all)] fn lower_assoc_item_constraint( From f1b023a91b8455d214035c657b35adf77dc31451 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 11:21:16 +0200 Subject: [PATCH 0313/1309] sembr src/solve/sharing-crates-with-rust-analyzer.md --- .../sharing-crates-with-rust-analyzer.md | 83 +++++++++---------- 1 file changed, 41 insertions(+), 42 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md index 2b06f5b414c1b..83d3a0ce0ab3a 100644 --- a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md +++ b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md @@ -77,7 +77,8 @@ Among its essential responsibilities: instantiates the shared IR, - it provides the context required by the solver (e.g., querying [lang items][ir require_lang_item], enumerating [all blanket impls for a trait][ir for_each_blanket_impl]); -- and it must implement [`IrPrint`][ir irprint] for formatting and tracing. +- and it must implement [`IrPrint`][ir irprint] for formatting and tracing. + In practice, these `IrPrint` impls simply route to existing formatting logic inside rustc or rust-analyzer. @@ -91,7 +92,8 @@ rather than rustc queries. Another notable item in `rustc_type_ir` is the [`inherent` module][ir inherent]. This module provides *forward definitions* of inherent methods—expressed as traits—corresponding to -methods that exist on compiler-specific types such as `Ty` or `GenericArg`. +methods that exist on compiler-specific types such as `Ty` or `GenericArg`. + These definitions allow the generic crates (such as `rustc_next_trait_solver`) to call methods that are implemented differently in rustc and rust-analyzer. @@ -152,8 +154,8 @@ This infrastructure is used by the external fuzzing project: - [`trait GenericTypeVisitable`][generictypevisitable] These traits are used heavily in `rustc_type_ir`, their associated macros -primarily exist to reduce the amount of boilerplate otherwise required to -implement `Lift`, `TypeFoldable`, `TypeVisitable` and `GenericTypeVisitable`. +primarily exist to reduce the amount of boilerplate otherwise required to implement `Lift`, +`TypeFoldable`, `TypeVisitable` and `GenericTypeVisitable`. ### `trait TypeVisitable` and `TypeVisitable_Generic` [type-visitable-trait-macro]: #type-visitable-trait-macro @@ -163,8 +165,7 @@ which in turn will transfer control to `TypeVisitor`, this can be [seen in detail here][rustc_typevisitable]. While ostensibly similar due to their names, `TypeVisitable_Generic` and -[`GenericTypeVisitable`][generictypevisitable] they implement two different -visiting systems. +[`GenericTypeVisitable`][generictypevisitable] they implement two different visiting systems. - `TypeVisitable_Generic` means: derive the ordinary `TypeVisitable` trait generically over an `Interner`. @@ -175,50 +176,49 @@ visiting systems. [typevisitable_generic]: #typevisitable_generic It visits the value's fields in declaration order, delegating each field to that -field's own `TypeVisitable` implementation. The traversal can stop early if -the visitor returns a residual result. +field's own `TypeVisitable` implementation. +The traversal can stop early if the visitor returns a residual result. Use `#[type_visitable(ignore)]` to ignore a field; it will not be part of the -traversal and will not need to implement `TypeVisitable`. This should only -be used when the field does not need to be traversed. +traversal and will not need to implement `TypeVisitable`. +This should only be used when the field does not need to be traversed. ### `trait TypeFoldable` and `TypeFoldable_Generic` [type-foldable-trait-macro]: #type-foldable-trait-macro -The trait is implemented by things that need to embed types. This concept is -discussed in detail [here](../ty-fold.md) and can be +The trait is implemented by things that need to embed types. +This concept is discussed in detail [here](../ty-fold.md) and can be [followed in the source][rustc_typefoldable]. -`TypeFoldable_Generic` derives `rustc_type_ir::TypeFoldable` for a struct or -enum. +`TypeFoldable_Generic` derives `rustc_type_ir::TypeFoldable` for a struct or enum. -It consumes a value and reconstructs the same struct or enum variant after -folding its fields. It generates both fallible and infallible folding methods. +It consumes a value and reconstructs the same struct or enum variant after folding its fields. +It generates both fallible and infallible folding methods. -Use `#[type_foldable(identity)]` for a field whose value must be preserved -unchanged. The macro moves that field directly into the reconstructed value -instead of passing it to the folder. Its type therefore does not need to -implement `TypeFoldable`. +Use `#[type_foldable(identity)]` for a field whose value must be preserved unchanged. +The macro moves that field directly into the reconstructed value +instead of passing it to the folder. +Its type therefore does not need to implement `TypeFoldable`. For an enum, the generated match contains one reconstruction arm per variant. ### `trait Lift` and `Lift_Generic` [lift-trait-macro]: #lift-trait-macro -The trait has a method `lift_to_interner(...)`. As the name suggests, it should -'lift' something to the interner. [See here](../memory.md) to read more about -the interner [and here for the source][rustc_lift]. +The trait has a method `lift_to_interner(...)`. +As the name suggests, it should 'lift' something to the interner. +[See here](../memory.md) to read more about the interner [and here for the source][rustc_lift]. -The macro `Lift_Generic` derives `Lift` for a struct or enum, with three -non-obvious considerations: +The macro `Lift_Generic` derives `Lift` for a struct or enum, with three non-obvious considerations: 1. The generic parameters `I` and `J` are reserved for `I: Interner` and `J` being the interner it is being lifted to. -2. `PhantomData` is handled automatically, creating a new `PhantomData`. But it - _has_ to be used in the fully unqualified form -- you cannot use +2. `PhantomData` is handled automatically, creating a new `PhantomData`. + But it _has_ to be used in the fully unqualified form -- you cannot use `std::marker::PhantomData` directly in the field. 3. The bounds are deliberately written as associated type bounds on the `Interner` - trait rather than as `where` clauses on `LiftInto`. Given only `I: LiftInto`, + trait rather than as `where` clauses on `LiftInto`. + Given only `I: LiftInto`, Rust can then treat bounds such as the following as implied: ```rust @@ -228,15 +228,14 @@ I::Const: Lift This allows `Lift_Generic` to emit the bound `I: LiftInto` while still calling `lift_to_interner` on fields of type `I::Ty`, `I::Const`, and the other -declared associated types. It also guarantees that each call produces the -destination field type expected after the derive rewrites `I::Assoc` to -`J::Assoc`. +declared associated types. +It also guarantees that each call produces the +destination field type expected after the derive rewrites `I::Assoc` to `J::Assoc`. Without `declare_lift_into!`, the derive would need to generate a separate bound -for every interner-associated type used by every field. If a new `Interner` -associated type is expected to work with `Lift_Generic`, it needs an appropriate -`Lift` implementation and normally needs to be included in the -`declare_lift_into!` invocation. +for every interner-associated type used by every field. +If a new `Interner` associated type is expected to work with `Lift_Generic`, it needs an appropriate +`Lift` implementation and normally needs to be included in the `declare_lift_into!` invocation. If you want to ignore a field, such as a primitive like a `u32` which can't be lifted you can skip the field with `#[lift(ignore)]`. @@ -245,20 +244,20 @@ lifted you can skip the field with `#[lift(ignore)]`. [generictypevisitable]: #generictypevisitable This a separate more general traversal trait purely used by `rust-analyzer`. -The visitor type is a parameter of the trait rather than a parameter of the -method, and visiting neither returns a result nor supports short-circuiting. +The visitor type is a parameter of the trait rather than a parameter of the method, +and visiting neither returns a result nor supports short-circuiting. -As such a struct or enum can derive both `TypeVisitable_Generic` and -`GenericTypeVisitable` +As such a struct or enum can derive both `TypeVisitable_Generic` and `GenericTypeVisitable` -There is intentionally no ignore attribute. The traversal must visit every -field. This is a soundness requirement for rust-analyzer's use of the traversal +There is intentionally no ignore attribute. +The traversal must visit every field. +This is a soundness requirement for rust-analyzer's use of the traversal when tracing and garbage-collecting interned types. ## Long-term plans for supporting rust-analyzer In general, we aim to support rust-analyzer just as well as rustc in these shared crates—provided -doing so does not substantially harm rustc's performance or maintainability. +doing so does not substantially harm rustc's performance or maintainability. (e.g., [#145377][pr 145377], [#146111][pr 146111], [#146182][pr 146182] and [#147723][pr 147723]) Shared crates that require nightly-only features must guard such code behind a `nightly` feature From 11b373edc96b4bc0f4cf2e1bd692bffbd5ac4dc4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 2 Sep 2026 07:13:08 +1000 Subject: [PATCH 0314/1309] Eliminate `ItemLowerer` It's just a thin wrapper around `tcx` and `resolver`. The `lower_*` methods all have a single call site and can be inlined, and `with_lctx` can just be a local fn within `lower_to_hir`. This requires increasing the visibility of some `LoweringContext::lower_*` methods that are now called outside of `item.rs`. --- compiler/rustc_ast_lowering/src/item.rs | 65 +++---------------------- compiler/rustc_ast_lowering/src/lib.rs | 39 ++++++++++++--- 2 files changed, 39 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 72f72d22fb13a..1073706499919 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -5,11 +5,8 @@ use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; use rustc_hir::attrs::{AttributeKind, EiiImplResolution}; use rustc_hir::def::{DefKind, PerNS, Res}; use rustc_hir::{ - self as hir, CRATE_OWNER_ID, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, - find_attr, + self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr, }; -use rustc_middle::middle::resolve::ResolverAstLowering; -use rustc_middle::ty::TyCtxt; use rustc_middle::ty::data_structures::IndexMap; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::edit_distance::find_best_match_for_name; @@ -28,14 +25,9 @@ use super::{ }; use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly}; -pub(super) struct ItemLowerer<'a, 'hir> { - pub(super) tcx: TyCtxt<'hir>, - pub(super) resolver: &'a ResolverAstLowering<'hir>, -} - -/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set the span -/// to the where clause that is preferred, if it exists. Otherwise, it sets the span to the other where -/// clause if it exists. +/// When we have a ty alias we *may* have two where clauses. To give the best diagnostics, we set +/// the span to the where clause that is preferred, if it exists. Otherwise, it sets the span to +/// the other where clause if it exists. fn add_ty_alias_where_clause( generics: &mut ast::Generics, after_where_clause: &ast::WhereClause, @@ -52,47 +44,6 @@ fn add_ty_alias_where_clause( if before.0 || !after.0 { before } else { after }; } -impl<'hir> ItemLowerer<'_, 'hir> { - fn with_lctx( - &self, - owner: NodeId, - f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, - ) -> hir::MaybeOwner<'hir> { - let mut lctx = LoweringContext::new(self.tcx, self.resolver, owner); - - let item = f(&mut lctx); - - hir::MaybeOwner::Owner(lctx.curr_owner.into_owner_info(self.tcx, item)) - } - - #[instrument(level = "debug", skip(self, c))] - pub(super) fn lower_crate(&self, c: &Crate) -> hir::MaybeOwner<'hir> { - self.with_lctx(CRATE_NODE_ID, |lctx| { - debug_assert_eq!(lctx.curr_owner.owner_id(), CRATE_OWNER_ID); - let module = lctx.lower_mod(&c.items, &c.spans); - lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, c.spans.inner_span, Target::Crate); - hir::OwnerNode::Crate(module) - }) - } - - #[instrument(level = "debug", skip(self))] - pub(super) fn lower_item(&self, item: &Item) -> hir::MaybeOwner<'hir> { - self.with_lctx(item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) - } - - pub(super) fn lower_trait_item(&self, item: &AssocItem) -> hir::MaybeOwner<'hir> { - self.with_lctx(item.id, |lctx| hir::OwnerNode::TraitItem(lctx.lower_trait_item(item))) - } - - pub(super) fn lower_impl_item(&self, item: &AssocItem) -> hir::MaybeOwner<'hir> { - self.with_lctx(item.id, |lctx| hir::OwnerNode::ImplItem(lctx.lower_impl_item(item))) - } - - pub(super) fn lower_foreign_item(&self, item: &ForeignItem) -> hir::MaybeOwner<'hir> { - self.with_lctx(item.id, |lctx| hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item))) - } -} - impl<'hir> LoweringContext<'_, 'hir> { pub(super) fn lower_mod( &mut self, @@ -202,7 +153,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { + pub(super) fn lower_item(&mut self, i: &Item) -> &'hir hir::Item<'hir> { let owner_id = self.curr_owner.owner_id(); let hir_id: HirId = owner_id.into(); let vis_span = self.lower_span(i.vis.span); @@ -729,7 +680,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { + pub(super) fn lower_foreign_item(&mut self, i: &ForeignItem) -> &'hir hir::ForeignItem<'hir> { let owner_id = self.curr_owner.owner_id(); let hir_id: HirId = owner_id.into(); let attrs = @@ -910,7 +861,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } } - fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { + pub(super) fn lower_trait_item(&mut self, i: &AssocItem) -> &'hir hir::TraitItem<'hir> { let trait_item_def_id = self.curr_owner.owner_id(); let hir_id: HirId = trait_item_def_id.into(); let attrs = self.lower_attrs( @@ -1159,7 +1110,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ident } - fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { + pub(super) fn lower_impl_item(&mut self, i: &AssocItem) -> &'hir hir::ImplItem<'hir> { let owner_id = self.curr_owner.owner_id(); let hir_id: HirId = owner_id.into(); let parent_id = self.tcx.local_parent(owner_id.def_id); diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 16d098d1c4d75..410823919c523 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -60,8 +60,9 @@ use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ - self as hir, AngleBrackets, ConstArg, GenericArg, HirId, ItemLocalMap, LifetimeSource, - LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, find_attr, + self as hir, AngleBrackets, CRATE_OWNER_ID, ConstArg, GenericArg, HirId, ItemLocalMap, + LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, + find_attr, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -783,15 +784,37 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { return fallback_to_ancestor(tcx.local_parent(def_id)); }; - let item_lowerer = item::ItemLowerer { tcx, resolver: &*resolver }; + fn with_lctx<'hir>( + tcx: TyCtxt<'hir>, + resolver: &ResolverAstLowering<'hir>, + owner: NodeId, + f: impl FnOnce(&mut LoweringContext<'_, 'hir>) -> hir::OwnerNode<'hir>, + ) -> hir::MaybeOwner<'hir> { + let mut lctx = LoweringContext::new(tcx, resolver, owner); + let item = f(&mut lctx); + hir::MaybeOwner::Owner(lctx.curr_owner.into_owner_info(tcx, item)) + } let item = match &node { // The item existed in the AST. - AstOwner::Crate(c) => item_lowerer.lower_crate(&c), - AstOwner::Item(item) => item_lowerer.lower_item(&item), - AstOwner::TraitItem(item) => item_lowerer.lower_trait_item(&item), - AstOwner::ImplItem(item) => item_lowerer.lower_impl_item(&item), - AstOwner::ForeignItem(item) => item_lowerer.lower_foreign_item(&item), + AstOwner::Crate(c) => with_lctx(tcx, &*resolver, CRATE_NODE_ID, |lctx| { + debug_assert_eq!(lctx.curr_owner.owner_id(), CRATE_OWNER_ID); + let module = lctx.lower_mod(&c.items, &c.spans); + lctx.lower_attrs(hir::CRATE_HIR_ID, &c.attrs, c.spans.inner_span, Target::Crate); + hir::OwnerNode::Crate(module) + }), + AstOwner::Item(item) => { + with_lctx(tcx, &*resolver, item.id, |lctx| hir::OwnerNode::Item(lctx.lower_item(item))) + } + AstOwner::TraitItem(item) => with_lctx(tcx, &*resolver, item.id, |lctx| { + hir::OwnerNode::TraitItem(lctx.lower_trait_item(item)) + }), + AstOwner::ImplItem(item) => with_lctx(tcx, &*resolver, item.id, |lctx| { + hir::OwnerNode::ImplItem(lctx.lower_impl_item(item)) + }), + AstOwner::ForeignItem(item) => with_lctx(tcx, &*resolver, item.id, |lctx| { + hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) + }), AstOwner::NestedUseTree(owner_id) => fallback_to_ancestor(*owner_id), // The item existed in the AST, but is not a HIR owner. // Fetch the correct information from its parent. From d3f82464bc0f20835a14d6cdd7c8b3cdcc5cc17c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 11:29:35 +0200 Subject: [PATCH 0315/1309] whitespace --- .../src/solve/sharing-crates-with-rust-analyzer.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md index 83d3a0ce0ab3a..19db5016eb073 100644 --- a/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md +++ b/src/doc/rustc-dev-guide/src/solve/sharing-crates-with-rust-analyzer.md @@ -59,7 +59,7 @@ solver. `rustc_next_trait_solver` is intended to depend only on the abstract interfaces defined in `rustc_type_ir`. To support this, the type-system traits in `rustc_type_ir` must expose every interface the solver -requires—for example, [creating a new inference type variable][ir new_infer] +requires—for example, [creating a new inference type variable][ir new_infer] ([rustc][rustc new_infer], [rust-analyzer][r-a new_infer]). For items that do not need compiler-specific representations, `rustc_type_ir` defines them directly as structs or enums parameterized over these traits—for example, [`TraitRef`][ir tr]. @@ -78,7 +78,7 @@ Among its essential responsibilities: - it provides the context required by the solver (e.g., querying [lang items][ir require_lang_item], enumerating [all blanket impls for a trait][ir for_each_blanket_impl]); - and it must implement [`IrPrint`][ir irprint] for formatting and tracing. - + In practice, these `IrPrint` impls simply route to existing formatting logic inside rustc or rust-analyzer. @@ -153,7 +153,7 @@ This infrastructure is used by the external fuzzing project: - [`trait Lift` and `Lift_Generic`][lift-trait-macro] - [`trait GenericTypeVisitable`][generictypevisitable] -These traits are used heavily in `rustc_type_ir`, their associated macros +These traits are used heavily in `rustc_type_ir`, their associated macros primarily exist to reduce the amount of boilerplate otherwise required to implement `Lift`, `TypeFoldable`, `TypeVisitable` and `GenericTypeVisitable`. @@ -264,8 +264,8 @@ Shared crates that require nightly-only features must guard such code behind a ` flag, since rust-analyzer is built with the stable toolchain. Looking forward, we plan to uplift more shared logic into `rustc_type_ir`. -There are still duplicated implementations between rustc and rust-analyzer—such as `ObligationCtxt` -([rustc][rustc oblctxt], [rust-analyzer][r-a oblctxt]) and type coercion logic +There are still duplicated implementations between rustc and rust-analyzer—such as `ObligationCtxt` +([rustc][rustc oblctxt], [rust-analyzer][r-a oblctxt]) and type coercion logic ([rustc][rustc coerce], [rust-analyzer][r-a coerce])—that we would like to unify over time. [rustc-auto-publish]: https://github.com/rust-analyzer/rustc-auto-publish @@ -302,5 +302,5 @@ There are still duplicated implementations between rustc and rust-analyzer—suc [rustc coerce]: https://github.com/rust-lang/rust/blob/63b1db05801271e400954e41b8600a3cf1482363/compiler/rustc_hir_typeck/src/coercion.rs [r-a coerce]: https://github.com/rust-lang/rust-analyzer/blob/34f47d9298c478c12c6c4c0348771d1b05706e09/crates/hir-ty/src/infer/coerce.rs [rustc_lift]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/lift.rs#L18 -[rustc_typevisitable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/visit.rs#L62 +[rustc_typevisitable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/visit.rs#L62 [rustc_typefoldable]: https://github.com/rust-lang/rust/blob/0913b18e489ac1011b580e31fa5559654be12bfc/compiler/rustc_type_ir/src/fold.rs#L71 From 1b9a6084b151161c3b0023d35de83ba053610e53 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 11:31:47 +0200 Subject: [PATCH 0316/1309] sembr src/tests/ecosystem.md --- src/doc/rustc-dev-guide/src/tests/ecosystem.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem.md b/src/doc/rustc-dev-guide/src/tests/ecosystem.md index 9e5b3a1e1c11d..ff9aca59ebe49 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem.md @@ -7,9 +7,10 @@ regressions and make informed decisions about the evolution of the language. ### Crater -Crater is a tool which runs tests on many thousands of public projects. This -tool has its own separate infrastructure for running, and is not run as part of -CI. See the [Crater chapter](crater.md) for more details. +Crater is a tool which runs tests on many thousands of public projects. +This tool has its own separate infrastructure for running, and is not run as part of +CI. +See the [Crater chapter](crater.md) for more details. ### `cargotest` @@ -23,8 +24,8 @@ there aren't any significant regressions: ### Large OSS Project builders -We have CI jobs that build large open-source Rust projects that are used as -regression tests in CI. Our integration jobs build the following projects: +We have CI jobs that build large open-source Rust projects that are used as regression tests in CI. +Our integration jobs build the following projects: - [Fuchsia](./ecosystem-test-jobs/fuchsia.md) - [Rust for Linux](./ecosystem-test-jobs/rust-for-linux.md) From a3afbd8d02503af933e435199425c88881feae4d Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Fri, 18 Sep 2026 04:32:20 -0500 Subject: [PATCH 0317/1309] use spawned `SBDebugger` instance --- src/etc/debugger_tester/lldb/batchmode.py | 43 ++++++++++++++++------- 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/src/etc/debugger_tester/lldb/batchmode.py b/src/etc/debugger_tester/lldb/batchmode.py index fdf6a34c01716..ebc7b7ff91577 100644 --- a/src/etc/debugger_tester/lldb/batchmode.py +++ b/src/etc/debugger_tester/lldb/batchmode.py @@ -16,6 +16,7 @@ import _thread as thread import os import re +import signal import sys import threading import time @@ -184,6 +185,27 @@ def dispatch_repr(var_name: str, breakpoint_index: int, frame: lldb.SBFrame) -> return check(var_name, breakpoint_index, frame) == Result.Ok +def quit_with_error(debugger: lldb.SBDebugger): + """Kills the parent LLDB process with a non-0 exit code""" + + # file handles aren't guaranteed to be flushed when python doesn't return control back to LLDB, + # so we need to do it manually + debugger.GetOutputFile().Flush() + debugger.GetErrorFile().Flush() + sys.stdout.flush() + sys.stderr.flush() + + # When using a debugger created from the python script (e.g. `lldb.SBDebugger.Create()`), this + # doesn't actually work, but it doesn't hurt to try =) + debugger.HandleCommand("quit 1") + + # Returning status codes using `sys.exit` doesn't work since we're in an LLDB managed python + # instance. Instead, we kill the PID, which happens to be the parent LLDB process. + # Note: We use SIGTERM because it works on linux and windows, unlike SIGKILL, and doesn't cause + # LLDB to spit out a backtrace like SIGABRT. + os.kill(os.getpid(), signal.SIGTERM) + + #################################################################################################### # ~main #################################################################################################### @@ -203,12 +225,12 @@ def main(): # Start the timeout watchdog start_watchdog() - # This is the debugger instance of the lldb executable that imported and ran this python script. - # There is some weird behavior around LLDB reassigning, clearing, or not updating their own - # references (like `lldb.debugger`) while a python function is actively running (i.e. if control - # is not given back to the REPL). To prevent LLDB from changing things out from under us, we - # store this reference locally. - debugger = lldb.debugger + # We use a new `SBDebugger` instance, since LLDB often doesn't update internal state/python + # state while a command is being run. Since the entirety of `batchmode` is executed via a + # `script` command, the parent LLDB never gets a chance to update. + # In LLDB <23 this was less of an issue, but a change in LLDB 23 made it difficult to create + # targets from the parent debugger instance. + debugger = lldb.SBDebugger.Create() # When we step or continue, don't return from the function until the process # stops. We do this by setting the async mode to false. @@ -283,13 +305,10 @@ def main(): print(f"Could not read debugging script '{script_path}'.") traceback.print_exception(type(e), e, e.__traceback__, file=sys.stdout) print("Aborting.") - # Returning status codes using `sys.exit` doesn't work since we're in an LLDB managed python - # instance. This command sets the exit code but *does not* kill LLDB, the debugee process, - # or the SBDebugger object. - debugger.HandleCommand("quit 1") + quit_with_error(debugger) except Exception as e: traceback.print_exception(type(e), e, e.__traceback__, file=sys.stdout) - debugger.HandleCommand("quit 1") + quit_with_error(debugger) else: # Executes if the `try` block throws no exceptions. if repr_cmd_run: # We save importing these until we actually see a repr command. This prevents us @@ -329,7 +348,7 @@ def main(): ) if not tested_all_types() or not tested_all_variables(): - debugger.HandleCommand("quit 1") + quit_with_error(debugger) elif BLESS: from lldb_providers import FEATURE_FLAGS From 27ed2eda1298d9986a77c751ce6fa7adcaf09650 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:10:15 +0200 Subject: [PATCH 0318/1309] Introduce LockedDir type --- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_data_structures/src/flock.rs | 31 ++++++++++++- compiler/rustc_incremental/src/persist/fs.rs | 48 +++++++++++--------- compiler/rustc_session/src/session.rs | 6 +-- 4 files changed, 58 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c93aa87b25077..0f609464593dc 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1297,7 +1297,7 @@ fn start_executing_work( incr_comp_session_dir: tcx .incr_comp_session .as_ref() - .map(|incr_comp_session| incr_comp_session.session_directory.clone()), + .map(|incr_comp_session| (&*incr_comp_session.session_directory).to_owned()), output_filenames: Arc::clone(tcx.output_filenames(())), module_config: regular_config, opt_level, diff --git a/compiler/rustc_data_structures/src/flock.rs b/compiler/rustc_data_structures/src/flock.rs index 9bd7d06c27f5e..deb779a4996dd 100644 --- a/compiler/rustc_data_structures/src/flock.rs +++ b/compiler/rustc_data_structures/src/flock.rs @@ -6,7 +6,8 @@ use std::fs::{File, OpenOptions}; use std::io; -use std::path::Path; +use std::ops::Deref; +use std::path::{Path, PathBuf}; #[derive(Debug)] pub enum Lock { @@ -68,3 +69,31 @@ cfg_select! { use unsupported as fallback; } } + +/// A directory together with a locked lockfile. +pub struct LockedDir { + dir: PathBuf, + /// `_lock_file` is never directly used, but its presence + /// alone has an effect, because the file will unlock when the session is + /// dropped. + _lock_file: Lock, +} + +impl LockedDir { + pub fn try_lock( + dir: PathBuf, + lock_file: &Path, + create: bool, + exclusive: bool, + ) -> io::Result { + Ok(LockedDir { dir, _lock_file: Lock::try_lock(lock_file, create, exclusive)? }) + } +} + +impl Deref for LockedDir { + type Target = Path; + + fn deref(&self) -> &Path { + &self.dir + } +} diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 504e93cf2aaef..3096b44eafb44 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -236,16 +236,13 @@ pub(crate) fn prepare_session_directory( // Generate a session directory of the form: // // {incr-comp-dir}/{crate-name-and-disambiguator}/s-{timestamp}-{random}-working - let session_dir = generate_session_dir_path(&crate_dir); - debug!("session-dir: {}", session_dir.display()); + let session_directory = generate_session_dir_path(&crate_dir); + debug!("session-dir: {}", session_directory.display()); // Lock the new session directory. If this fails, return an // error without retrying - let (directory_lock, lock_file_path) = lock_directory(sess, &session_dir); - - // Now that we have the lock, we can actually create the session - // directory - create_dir(sess, &session_dir, "session"); + let (session_directory, lock_file_path) = + lock_and_create_directory(sess, &session_directory); // Find a suitable source directory to copy from. Ignore those that we // have already tried before. @@ -258,20 +255,20 @@ pub(crate) fn prepare_session_directory( directory." ); - return IncrCompSession { session_directory: session_dir, _lock_file: directory_lock }; + return IncrCompSession { session_directory }; }; debug!("attempting to copy data from source: {}", source_directory.display()); // Try copying over all files from the source directory - if let Ok(allows_links) = copy_files(sess, &session_dir, &source_directory) { + if let Ok(allows_links) = copy_files(sess, &session_directory, &source_directory) { debug!("successfully copied data from: {}", source_directory.display()); if !allows_links { - sess.dcx().emit_warn(diagnostics::HardLinkFailed { path: &session_dir }); + sess.dcx().emit_warn(diagnostics::HardLinkFailed { path: &session_directory }); } - return IncrCompSession { session_directory: session_dir, _lock_file: directory_lock }; + return IncrCompSession { session_directory }; } else { debug!("copying failed - trying next directory"); @@ -281,12 +278,12 @@ pub(crate) fn prepare_session_directory( // Try to remove the session directory we just allocated. We don't // know if there's any garbage in it from the failed copy action. - if let Err(err) = std_fs::remove_dir_all(&session_dir) { - sess.dcx().emit_warn(diagnostics::DeletePartial { path: &session_dir, err }); + if let Err(err) = std_fs::remove_dir_all(&*session_directory) { + sess.dcx().emit_warn(diagnostics::DeletePartial { path: &session_directory, err }); } delete_session_dir_lock_file(sess, &lock_file_path); - drop(directory_lock); + drop(session_directory); } } } @@ -310,7 +307,7 @@ pub fn finalize_session_directory( let _timer = sess.timer("incr_comp_finalize_session_directory"); - let incr_comp_session_dir = incr_comp_session.session_directory.clone(); + let incr_comp_session_dir = &*incr_comp_session.session_directory; debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display()); @@ -334,7 +331,7 @@ pub fn finalize_session_directory( let new_path = incr_comp_session_dir.parent().unwrap().join(&*sub_dir_name); debug!("finalize_session_directory() - new path: {}", new_path.display()); - let result = std_fs::rename(&*incr_comp_session_dir, &new_path).or_else(|e| { + let result = std_fs::rename(incr_comp_session_dir, &new_path).or_else(|e| { if !cfg!(windows) || e.kind() != ErrorKind::PermissionDenied { return Err(e); } @@ -355,7 +352,7 @@ pub fn finalize_session_directory( debug!("finalize_session_directory() - error replacing hard link with copy: {}", err); } - rename_path_with_retry(&*incr_comp_session_dir, &new_path, 3) + rename_path_with_retry(incr_comp_session_dir, &new_path, 3) }); match result { @@ -364,7 +361,7 @@ pub fn finalize_session_directory( } Err(e) => { // Warn about the error. However, no need to abort compilation now. - sess.dcx().emit_note(diagnostics::Finalize { path: &incr_comp_session_dir, err: e }); + sess.dcx().emit_note(diagnostics::Finalize { path: incr_comp_session_dir, err: e }); debug!("finalize_session_directory() - error"); } @@ -471,18 +468,25 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) { } } -/// Allocate the lock-file and lock it. -fn lock_directory(sess: &Session, session_dir: &Path) -> (flock::Lock, PathBuf) { +/// Allocate the lock-file, lock it and create the session directory. +fn lock_and_create_directory(sess: &Session, session_dir: &Path) -> (flock::LockedDir, PathBuf) { let lock_file_path = lock_file_path(session_dir); debug!("lock_directory() - lock_file: {}", lock_file_path.display()); - match flock::Lock::try_lock( + match flock::LockedDir::try_lock( + session_dir.to_owned(), &lock_file_path, true, // create the lock file true, ) { // the lock should be exclusive - Ok(lock) => (lock, lock_file_path), + Ok(lock) => { + // Now that we have the lock, we can actually create the session + // directory + create_dir(sess, &session_dir, "session"); + + (lock, lock_file_path) + } Err(lock_err) => { let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err); sess.dcx().emit_fatal(diagnostics::CreateLock { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 274cfe8d7eb8a..acfbb08b9b630 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1844,11 +1844,7 @@ pub struct IncrCompSession { /// The directory containing all cached data. Cached data from a previous /// session can be read out of it and new data for the current session will /// be written into it. - pub session_directory: PathBuf, - /// `_lock_file` is never directly used, but its presence - /// alone has an effect, because the file will unlock when the session is - /// dropped. - pub _lock_file: flock::Lock, + pub session_directory: flock::LockedDir, } /// A wrapper around an [`DiagCtxt`] that is used for early error emissions. From cff4b1ac281618214b91187850c4a427e898c2db Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 12:17:03 +0200 Subject: [PATCH 0319/1309] reduce indentation --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 92143aaa1fb87..26f37e0a9b238 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -182,15 +182,15 @@ fn lengthen_lines(content: &str, limit: usize) -> String { new_content[new_n] = format!("{line} {}", next_line.trim_start()); new_content.remove(new_n + 1); skip_next = true; - } else { - const SEP: &str = ", "; - let Some((before_comma, after_comma)) = next_line.split_once(SEP) else { continue }; - if line.len() + before_comma.len() < limit - SEP.len() { - new_content[new_n] = format!("{line} {before_comma}{}", SEP.trim_end()); - new_n += 1; - new_content[new_n] = after_comma.to_owned(); - skip_next = true; - } + continue; + } + const SEP: &str = ", "; + let Some((before_comma, after_comma)) = next_line.split_once(SEP) else { continue }; + if line.len() + before_comma.len() < limit - SEP.len() { + new_content[new_n] = format!("{line} {before_comma}{}", SEP.trim_end()); + new_n += 1; + new_content[new_n] = after_comma.to_owned(); + skip_next = true; } } new_content.join("\n") + "\n" From 6e7ebbe8919d7f991e8a77eedb845dc11c66f959 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 18 Sep 2026 12:34:05 +0200 Subject: [PATCH 0320/1309] Depend on lockfiles to prevent GC of the current session Instead of manually skipping it right before the remove_dir. This will be simpler once we stop immediately copying from the old incr comp dir. Previously this wasn't possible due to the usage of process-based fcntl locking, but I added proper fd-based locking recently. --- compiler/rustc_incremental/src/persist/fs.rs | 94 +++++++------------ .../rustc_incremental/src/persist/fs/tests.rs | 7 +- .../rustc_incremental/src/persist/load.rs | 8 +- .../run-make/incremental-session-gc/rmake.rs | 8 +- 4 files changed, 47 insertions(+), 70 deletions(-) diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 3096b44eafb44..374e0b0dd6d1a 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -367,9 +367,11 @@ pub fn finalize_session_directory( } } - drop(incr_comp_session); // Unlock incr comp session dir - - let _ = garbage_collect_session_directories(sess, &new_path); + let _ = garbage_collect_session_directories( + sess, + &incr_comp_session, + false, // keep_most_recent + ); } pub(crate) fn delete_all_session_dir_contents( @@ -616,10 +618,13 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool { /// Runs garbage collection for the current session. pub(crate) fn garbage_collect_session_directories( sess: &Session, - session_directory: &Path, + incr_comp_session: &IncrCompSession, + keep_most_recent: bool, ) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); + let session_directory = &*incr_comp_session.session_directory; + debug!( "garbage_collect_session_directories() - session directory: {}", session_directory.display() @@ -721,9 +726,6 @@ pub(crate) fn garbage_collect_session_directories( } } - let current_session_directory_name = - session_directory.file_name().expect("session directory is not `..`"); - // Now garbage collect the valid session directories. let deletion_candidates = lock_file_to_session_dir.items().filter_map(|(lock_file_name, directory_name)| { @@ -771,31 +773,6 @@ pub(crate) fn garbage_collect_session_directories( } } } else if is_old_enough_to_be_collected(timestamp) { - if directory_name.as_str() == current_session_directory_name { - // Skipping our own active directory is important for correctness. - // - // To summarize #147821: we will try to lock directories before deciding they can be - // garbage collected, but the ability of `flock::Lock` to detect a lock held *by the - // same process* varies across file locking APIs. Then, if our own session directory - // has become old enough to be eligible for GC, we are beholden to platform-specific - // details about detecting the our own lock on the session directory. - // - // POSIX `fcntl(F_SETLK)`-style file locks are maintained across a process. On - // systems where this is the mechanism for `flock::Lock`, there is no way to - // discover if an `flock::Lock` has been created in the same process on the same - // file. Attempting to set a lock on the lockfile again will succeed, even if the - // lock was set by another thread, on another file descriptor. Then we would - // garbage collect our own live directory, unable to tell it was locked perhaps by - // this same thread. - // - // It's not clear that `flock::Lock` can be fixed for this in general, and our own - // incremental session directory is the only one which this process may own, so skip - // it here and avoid the problem. We know it's not garbage anyway: we're using it. - // Once finalized, its lock is released. Include it in collection so we keep - // the newest completed session. - return None; - } - // When cleaning out "-working" session directories, i.e. // session directories that might still be in use by another // compiler instance, we only look a directories that are @@ -844,24 +821,22 @@ pub(crate) fn garbage_collect_session_directories( let deletion_candidates = deletion_candidates.into(); // Delete all but the most recent of the candidates - all_except_most_recent(deletion_candidates).into_items().all(|(path, lock)| { - if path.file_name() == Some(current_session_directory_name) { - return true; - } + all_except_maybe_most_recent(deletion_candidates, keep_most_recent).into_items().all( + |(path, lock)| { + debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - - if let Err(err) = std_fs::remove_dir_all(&path) { - sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); - } else { - delete_session_dir_lock_file(sess, &lock_file_path(&path)); - } + if let Err(err) = std_fs::remove_dir_all(&path) { + sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); + } else { + delete_session_dir_lock_file(sess, &lock_file_path(&path)); + } - // Let's make it explicit that the file lock is released at this point, - // or rather, that we held on to it until here - drop(lock); - true - }); + // Let's make it explicit that the file lock is released at this point, + // or rather, that we held on to it until here + drop(lock); + true + }, + ); Ok(()) } @@ -876,20 +851,19 @@ fn delete_old(sess: &Session, path: &Path) { } } -fn all_except_most_recent( +fn all_except_maybe_most_recent( deletion_candidates: UnordMap<(SystemTime, PathBuf), Option>, + keep_most_recent: bool, ) -> UnordMap> { - let most_recent = deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max(); - - if let Some(most_recent) = most_recent { - deletion_candidates - .into_items() - .filter(|&((timestamp, _), _)| timestamp != most_recent) - .map(|((_, path), lock)| (path, lock)) - .collect() - } else { - UnordMap::default() - } + let most_recent = keep_most_recent + .then(|| deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max()) + .flatten(); + + deletion_candidates + .into_items() + .filter(|&((timestamp, _), _)| Some(timestamp) != most_recent) + .map(|((_, path), lock)| (path, lock)) + .collect() } fn safe_remove_file(p: &Path) -> io::Result<()> { diff --git a/compiler/rustc_incremental/src/persist/fs/tests.rs b/compiler/rustc_incremental/src/persist/fs/tests.rs index 3652656b7c48f..75b573dd4944a 100644 --- a/compiler/rustc_incremental/src/persist/fs/tests.rs +++ b/compiler/rustc_incremental/src/persist/fs/tests.rs @@ -10,11 +10,14 @@ fn test_all_except_most_recent() { ((UNIX_EPOCH + Duration::new(2, 0), PathBuf::from("2")), None), ]); assert_eq!( - all_except_most_recent(input).into_items().map(|(path, _)| path).into_sorted_stable_ord(), + all_except_maybe_most_recent(input, true) + .into_items() + .map(|(path, _)| path) + .into_sorted_stable_ord(), vec![PathBuf::from("1"), PathBuf::from("2"), PathBuf::from("3"), PathBuf::from("4")] ); - assert!(all_except_most_recent(UnordMap::default()).is_empty()); + assert!(all_except_maybe_most_recent(UnordMap::default(), true).is_empty()); } #[test] diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index 3cf08961ed7b3..fb83149e65b22 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -195,9 +195,11 @@ pub fn setup_dep_graph( let load_result = load_dep_graph(sess, &incr_comp_session); sess.time("incr_comp_garbage_collect_session_directories", || { - if let Err(e) = - garbage_collect_session_directories(sess, &incr_comp_session.session_directory) - { + if let Err(e) = garbage_collect_session_directories( + sess, + &incr_comp_session, + true, // keep_most_recent + ) { warn!( "Error while trying to garbage collect incremental compilation \ cache directory: {e}", diff --git a/tests/run-make/incremental-session-gc/rmake.rs b/tests/run-make/incremental-session-gc/rmake.rs index dd4b300a5ced0..341a21690f215 100644 --- a/tests/run-make/incremental-session-gc/rmake.rs +++ b/tests/run-make/incremental-session-gc/rmake.rs @@ -33,11 +33,9 @@ fn main() { ); compile(); - let sessions = shallow_find_directories(crate_dir, |_| true); - assert_eq!(sessions.len(), 2, "{sessions:?}"); - assert!(sessions.contains(&newer)); - let current = sessions.into_iter().find(|session| *session != newer).unwrap(); - assert!(!current.file_name().unwrap().to_str().unwrap().ends_with("-working")); + let current = session_dir(); + assert_ne!(previous, newer); + assert!(!newer.exists(), "superseded session was not collected: {previous:?}"); assert_eq!(rfs::read_to_string(current.join("sentinel")), "previous session"); } From 6f51268f743b1bdb38a9d8f4276869be4490b42f Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 12:47:18 +0200 Subject: [PATCH 0321/1309] split some more lines on commas --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 27 +++++++++++++------- 1 file changed, 18 insertions(+), 9 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 26f37e0a9b238..04e6fa3df19d8 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -185,12 +185,22 @@ fn lengthen_lines(content: &str, limit: usize) -> String { continue; } const SEP: &str = ", "; - let Some((before_comma, after_comma)) = next_line.split_once(SEP) else { continue }; - if line.len() + before_comma.len() < limit - SEP.len() { - new_content[new_n] = format!("{line} {before_comma}{}", SEP.trim_end()); - new_n += 1; - new_content[new_n] = after_comma.to_owned(); - skip_next = true; + if next_line.contains(SEP) { + let (before_comma, after_comma) = next_line.split_once(SEP).unwrap(); + if line.len() + before_comma.len() < limit - SEP.len() { + new_content[new_n] = format!("{line} {before_comma}{}", SEP.trim_end()); + new_n += 1; + new_content[new_n] = after_comma.to_owned(); + skip_next = true; + } + } else if line.contains(SEP) { + let (before_comma, after_comma) = line.rsplit_once(SEP).unwrap(); + if after_comma.len() + next_line.len() < limit { + new_content[new_n] = format!("{before_comma}{}", SEP.trim_end()); + new_n += 1; + new_content[new_n] = format!("{after_comma} {next_line}"); + skip_next = true; + } } } new_content.join("\n") + "\n" @@ -334,14 +344,13 @@ fn should_pass() { } #[test] -#[ignore] fn split_on_comma_of_current_line() { let original = " -Each derived value has a dependency on other values, which could themselves be either base or +Each derived value has a dependency, on other values, which could themselves be either base or derived. "; let expected = " -Each derived value has a dependency on other values, +Each derived value has a dependency, on other values, which could themselves be either base or derived. "; assert_eq!(expected, lengthen_lines(original, 100)) From 0999e10ab660045ffb879c5b0a09c0c086821aa4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 12:47:58 +0200 Subject: [PATCH 0322/1309] generic --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 04e6fa3df19d8..555f14abe8e72 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -186,19 +186,19 @@ fn lengthen_lines(content: &str, limit: usize) -> String { } const SEP: &str = ", "; if next_line.contains(SEP) { - let (before_comma, after_comma) = next_line.split_once(SEP).unwrap(); - if line.len() + before_comma.len() < limit - SEP.len() { - new_content[new_n] = format!("{line} {before_comma}{}", SEP.trim_end()); + let (before_sep, after_sep) = next_line.split_once(SEP).unwrap(); + if line.len() + before_sep.len() < limit - SEP.len() { + new_content[new_n] = format!("{line} {before_sep}{}", SEP.trim_end()); new_n += 1; - new_content[new_n] = after_comma.to_owned(); + new_content[new_n] = after_sep.to_owned(); skip_next = true; } } else if line.contains(SEP) { - let (before_comma, after_comma) = line.rsplit_once(SEP).unwrap(); - if after_comma.len() + next_line.len() < limit { - new_content[new_n] = format!("{before_comma}{}", SEP.trim_end()); + let (before_sep, after_sep) = line.rsplit_once(SEP).unwrap(); + if after_sep.len() + next_line.len() < limit { + new_content[new_n] = format!("{before_sep}{}", SEP.trim_end()); new_n += 1; - new_content[new_n] = format!("{after_comma} {next_line}"); + new_content[new_n] = format!("{after_sep} {next_line}"); skip_next = true; } } From bf9557a9be5915c529ef4f3c5e36dcec2da1cee2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 12:48:23 +0200 Subject: [PATCH 0323/1309] sembr src/tests/intro.md --- src/doc/rustc-dev-guide/src/tests/intro.md | 87 +++++++++++----------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index 82fb9597cb500..162f8b836fadb 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -1,9 +1,9 @@ # Testing the compiler -The Rust project runs a wide variety of different tests, orchestrated by the -build system (`./x test`). This section gives a brief overview of the different -testing tools. Subsequent chapters dive into [running tests](running.md) and -[adding new tests](adding.md). +The Rust project runs a wide variety of different tests, +orchestrated by the build system (`./x test`). +This section gives a brief overview of the different testing tools. +Subsequent chapters dive into [running tests](running.md) and [adding new tests](adding.md). ## Kinds of tests @@ -12,11 +12,10 @@ Almost all of them are driven by `./x test`, with some exceptions noted below. ### Compiletest -The main test harness for testing the compiler itself is a tool called -[compiletest]. +The main test harness for testing the compiler itself is a tool called [compiletest]. -[compiletest] supports running different styles of tests, organized into *test -suites*. A *test mode* may provide common presets/behavior for a set of *test +[compiletest] supports running different styles of tests, +organized into *test suites*. A *test mode* may provide common presets/behavior for a set of *test suites*. [compiletest]-supported tests are located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. @@ -28,9 +27,9 @@ The [Compiletest chapter][compiletest] goes into detail on how to use this tool. ### Package tests -The standard library and many of the compiler packages include typical Rust -`#[test]` unit tests, integration tests, and documentation tests. You can pass a -path to `./x test` for almost any package in the `library/` or `compiler/` +The standard library and many of the compiler packages include typical Rust `#[test]` unit tests, +integration tests, and documentation tests. +You can pass a path to `./x test` for almost any package in the `library/` or `compiler/` directory, and `x` will essentially run `cargo test` on that package. Examples: @@ -41,13 +40,14 @@ Examples: | `./x test library/core` | Runs tests on `core` only | | `./x test compiler/rustc_data_structures` | Runs tests on `rustc_data_structures` | -The standard library relies very heavily on documentation tests to cover its -functionality. However, unit tests and integration tests can also be used as -needed. Almost all of the compiler packages have doctests disabled. +The standard library relies very heavily on documentation tests to cover its functionality. +However, unit tests and integration tests can also be used as needed. +Almost all of the compiler packages have doctests disabled. All standard library and compiler unit tests are placed in separate `tests` file -(which is enforced in [tidy][tidy-unit-tests]). This ensures that when the test -file is changed, the crate does not need to be recompiled. For example: +(which is enforced in [tidy][tidy-unit-tests]). +This ensures that when the test file is changed, the crate does not need to be recompiled. +For example: ```rust,ignore #[cfg(test)] @@ -55,11 +55,9 @@ mod tests; ``` If it wasn't done this way, and you were working on something like `core`, that -would require recompiling the entire standard library, and the entirety of -`rustc`. +would require recompiling the entire standard library, and the entirety of `rustc`. -`./x test` includes some CLI options for controlling the behavior with these -package tests: +`./x test` includes some CLI options for controlling the behavior with these package tests: * `--doc` — Only runs documentation tests in the package. * `--all-targets` — Run all tests *except* documentation tests. @@ -69,8 +67,9 @@ package tests: ### Tidy -Tidy is a custom tool used for validating source code style and formatting -conventions, such as rejecting long lines. There is more information in the +Tidy is a custom tool used for validating source code style and formatting conventions, +such as rejecting long lines. +There is more information in the [section on coding conventions](../conventions.md#formatting) or the [Tidy Readme]. > Examples: `./x test tidy` @@ -80,9 +79,8 @@ conventions, such as rejecting long lines. There is more information in the ### Formatting -Rustfmt is integrated with the build system to enforce uniform style across the -compiler. The formatting check is automatically run by the Tidy tool mentioned -above. +Rustfmt is integrated with the build system to enforce uniform style across the compiler. +The formatting check is automatically run by the Tidy tool mentioned above. Examples: @@ -94,10 +92,10 @@ Examples: ### Book documentation tests -All of the books that are published have their own tests, primarily for -validating that the Rust code examples pass. Under the hood, these are -essentially using `rustdoc --test` on the markdown files. The tests can be run -by passing a path to a book to `./x test`. +All of the books that are published have their own tests, +primarily for validating that the Rust code examples pass. +Under the hood, these are essentially using `rustdoc --test` on the markdown files. +The tests can be run by passing a path to a book to `./x test`. > Example: `./x test src/doc/book` @@ -114,8 +112,8 @@ This requires building all of the documentation, which might take a while. ### `distcheck` -`distcheck` verifies that the source distribution tarball created by the build -system will unpack, build, and run all tests. +`distcheck` verifies that the source distribution tarball created by the build system will unpack, +build, and run all tests. ```console ./x test distcheck @@ -123,25 +121,24 @@ system will unpack, build, and run all tests. ### Tool tests -Packages that are included with Rust have all of their tests run as well. This -includes things such as cargo, clippy, rustfmt, miri, bootstrap (testing the +Packages that are included with Rust have all of their tests run as well. +This includes things such as cargo, clippy, rustfmt, miri, bootstrap (testing the Rust build system itself), etc. -Most of the tools are located in the [`src/tools`] directory. To run the tool's -tests, just pass its path to `./x test`. +Most of the tools are located in the [`src/tools`] directory. +To run the tool's tests, just pass its path to `./x test`. > Example: `./x test src/tools/cargo` Usually these tools involve running `cargo test` within the tool's directory. -If you want to run only a specified set of tests, append `--test-args -FILTER_NAME` to the command. +If you want to run only a specified set of tests, append `--test-args FILTER_NAME` to the command. > Example: `./x test src/tools/miri --test-args padding` -In CI, some tools are allowed to fail. Failures send notifications to the -corresponding teams, and is tracked on the [toolstate website]. More information -can be found in the [toolstate documentation]. +In CI, some tools are allowed to fail. +Failures send notifications to the corresponding teams, and is tracked on the [toolstate website]. +More information can be found in the [toolstate documentation]. [`src/tools`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/ [toolstate documentation]: https://forge.rust-lang.org/infra/toolstate.html @@ -150,14 +147,14 @@ can be found in the [toolstate documentation]. ### Ecosystem testing Rust tests integration with real-world code to catch regressions and make -informed decisions about the evolution of the language. There are several kinds -of ecosystem tests, including Crater. See the [Ecosystem testing -chapter](ecosystem.md) for more details. +informed decisions about the evolution of the language. +There are several kinds of ecosystem tests, including Crater. +See the [Ecosystem testing chapter](ecosystem.md) for more details. ### Performance testing -A separate infrastructure is used for testing and tracking performance of the -compiler. See the [Performance testing chapter](perf.md) for more details. +A separate infrastructure is used for testing and tracking performance of the compiler. +See the [Performance testing chapter](perf.md) for more details. ### Codegen backend testing From 6a7d5e64dd6b1f4d8de6f68a3840a170fd189d3e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Sep 2026 06:55:00 -0400 Subject: [PATCH 0324/1309] Fix for librsvg project tests --- build_system/src/test.rs | 31 +++++++++++++++++++++++-------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 01375c2c33ddd..a55c2dcf83ddc 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -730,11 +730,13 @@ struct Project { cargo_arguments: &'static [&'static str], /// Arguments forwarded to the test harness by `cargo test`. test_harness_arguments: &'static [&'static str], + /// Variables added to the environment of both invocations. + environment_variables: &'static [(&'static str, &'static str)], } impl Project { const fn new(url: &'static str) -> Self { - Self { url, cargo_arguments: &[], test_harness_arguments: &[] } + Self { url, cargo_arguments: &[], test_harness_arguments: &[], environment_variables: &[] } } const fn cargo_arguments(mut self, arguments: &'static [&'static str]) -> Self { @@ -746,17 +748,25 @@ impl Project { self.test_harness_arguments = arguments; self } + + const fn environment_variables( + mut self, + variables: &'static [(&'static str, &'static str)], + ) -> Self { + self.environment_variables = variables; + self + } } fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let projects = [ // The reference images assume the exact cairo, pango and freetype that librsvg pins in its // own CI; this one renders text decorations a pixel off with the versions Ubuntu ships. - Project::new("https://gitlab.gnome.org/GNOME/librsvg").test_harness_arguments(&[ - "--skip", - "tests::svg1_1_text_text_03_b_svg", - "--exact", - ]), + Project::new("https://gitlab.gnome.org/GNOME/librsvg") + .test_harness_arguments(&["--skip", "tests::svg1_1_text_text_03_b_svg", "--exact"]) + // A debug build of librsvg needs about 5 MB of stack per `cargo test` thread to reach + // its maximum layer nesting depth; librsvg's own CI sets the same value. + .environment_variables(&[("RUST_MIN_STACK", "8388608")]), Project::new("https://github.com/rust-random/getrandom"), Project::new("https://github.com/BurntSushi/memchr"), Project::new("https://github.com/dtolnay/itoa"), @@ -788,11 +798,16 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let clone_result = git_clone_root_dir(project.url, projects_path, true)?; let repo_path = Path::new(&clone_result.repo_dir); + let mut project_environment = env.clone(); + for (name, value) in project.environment_variables { + project_environment.insert(name.to_string(), value.to_string()); + } + let mut build_command: Vec<&dyn AsRef> = vec![&"build", &"--release"]; build_command.extend( project.cargo_arguments.iter().map(|argument| argument as &dyn AsRef), ); - run_cargo_command(&build_command, Some(repo_path), &env, args)?; + run_cargo_command(&build_command, Some(repo_path), &project_environment, args)?; let mut test_command: Vec<&dyn AsRef> = vec![&"test"]; test_command.extend( @@ -807,7 +822,7 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { .map(|argument| argument as &dyn AsRef), ); } - run_cargo_command(&test_command, Some(repo_path), &env, args)?; + run_cargo_command(&test_command, Some(repo_path), &project_environment, args)?; } Ok(()) From 5539256d3fe52002e1c79fa46c9d30d803baf4da Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:20:50 +0200 Subject: [PATCH 0325/1309] respect indents --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 21 +++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 555f14abe8e72..742671ee7b1dd 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -185,12 +185,14 @@ fn lengthen_lines(content: &str, limit: usize) -> String { continue; } const SEP: &str = ", "; + let indent = next_line.find(|ch: char| !ch.is_whitespace()).unwrap(); if next_line.contains(SEP) { let (before_sep, after_sep) = next_line.split_once(SEP).unwrap(); if line.len() + before_sep.len() < limit - SEP.len() { - new_content[new_n] = format!("{line} {before_sep}{}", SEP.trim_end()); + new_content[new_n] = + format!("{line} {}{}", before_sep.trim_start(), SEP.trim_end()); new_n += 1; - new_content[new_n] = after_sep.to_owned(); + new_content[new_n] = format!("{:indent$}{after_sep}", ""); skip_next = true; } } else if line.contains(SEP) { @@ -198,7 +200,8 @@ fn lengthen_lines(content: &str, limit: usize) -> String { if after_sep.len() + next_line.len() < limit { new_content[new_n] = format!("{before_sep}{}", SEP.trim_end()); new_n += 1; - new_content[new_n] = format!("{after_sep} {next_line}"); + new_content[new_n] = + format!("{:indent$}{after_sep} {}", "", next_line.trim_start()); skip_next = true; } } @@ -348,10 +351,16 @@ fn split_on_comma_of_current_line() { let original = " Each derived value has a dependency, on other values, which could themselves be either base or derived. + + Each derived value has a dependency, on other values, which could themselves be either base or + derived. "; let expected = " Each derived value has a dependency, on other values, which could themselves be either base or derived. + + Each derived value has a dependency, on other values, + which could themselves be either base or derived. "; assert_eq!(expected, lengthen_lines(original, 100)) } @@ -361,10 +370,16 @@ fn split_on_comma_of_next_line() { let original = " Because of canonicalization of regions and inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. + + Because of canonicalization of regions and + inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. "; let expected = " Because of canonicalization of regions and inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. + + Because of canonicalization of regions and inference variables, + encountering a cycle doesn't mean that we would get an infinite proof tree. "; assert_eq!(expected, lengthen_lines(original, 100)) } From 6e5231a052656febe9a6294f41fce84743a40bef Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:22:29 +0200 Subject: [PATCH 0326/1309] sembr src/tests/compiletest.md --- .../rustc-dev-guide/src/tests/compiletest.md | 171 +++++++++--------- 1 file changed, 87 insertions(+), 84 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 4573a04d0281c..7b6091c8d3253 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -3,8 +3,8 @@ ## Introduction `compiletest` is the main test harness of the Rust test suite. -It allows test authors to organize large numbers of tests (the Rust compiler has many -thousands), efficient test execution (parallel execution is supported), and +It allows test authors to organize large numbers of tests (the Rust compiler has many thousands), +efficient test execution (parallel execution is supported), and allows the test author to configure behavior and expected results of both individual and groups of tests. @@ -23,14 +23,14 @@ individual and groups of tests. Tests are typically organized as a Rust source file with annotations in comments before and/or within the test code. -These comments serve to direct `compiletest` -on if or how to run the test, what behavior to expect, and more. +These comments serve to direct `compiletest` on if or how to run the test, +what behavior to expect, and more. See [directives](directives.md) and the test suite documentation below for more details on these annotations. See the [Adding new tests](adding.md) and [Best practices](best-practices.md) -chapters for a tutorial on creating a new test and advice on writing a good -test, and the [Running tests](running.md) chapter on how to run the test suite. +chapters for a tutorial on creating a new test and advice on writing a good test, +and the [Running tests](running.md) chapter on how to run the test suite. Arguments can be passed to compiletest using `--test-args` or by placing them after `--`, e.g. - `x test --test-args --force-rerun` @@ -49,8 +49,8 @@ You can use `x test --test-args All of the tests are in the [`tests`] directory. The tests are organized into "suites", with each suite in a separate subdirectory. -Each test suite behaves a -little differently, with different compiler behavior and different checks for correctness. +Each test suite behaves a little differently, +with different compiler behavior and different checks for correctness. For example, the [`tests/incremental`] directory contains tests for incremental compilation. The various suites are defined in [`src/tools/compiletest/src/common.rs`] in the `pub enum Mode` declaration. @@ -114,8 +114,8 @@ The `-Z unpretty` CLI option for `rustc` causes it to translate the input source into various different formats, such as the Rust source after macro expansion. The pretty-printer tests have several [directives](directives.md) described below. -These commands can significantly change the behavior of the test, but the -default behavior without any commands is to: +These commands can significantly change the behavior of the test, +but the default behavior without any commands is to: 1. Run `rustc -Zunpretty=normal` on the source file. 2. Run `rustc -Zunpretty=normal` on the output of the previous step. @@ -133,17 +133,17 @@ The directives for pretty-printing tests are: - `pretty-compare-only` causes a pretty test to only compare the pretty-printed output (stopping after step 3 from above). It will not try to compile the expanded output to type check it. - This is needed for a pretty-mode that does - not expand to valid Rust, or for other situations where the expanded output cannot be compiled. + This is needed for a pretty-mode that does not expand to valid Rust, + or for other situations where the expanded output cannot be compiled. - `pp-exact` is used to ensure a pretty-print test results in specific output. - If specified without a value, then it means the pretty-print output should - match the original source. - If specified with a value, as in `//@ - pp-exact:foo.pp`, it will ensure that the pretty-printed output matches the + If specified without a value, + then it means the pretty-print output should match the original source. + If specified with a value, as in `//@ pp-exact:foo.pp`, + it will ensure that the pretty-printed output matches the contents of the given file. Otherwise, if `pp-exact` is not specified, then - the pretty-printed output will be pretty-printed one more time, and the output - of the two pretty-printing rounds will be compared to ensure that the + the pretty-printed output will be pretty-printed one more time, + and the output of the two pretty-printing rounds will be compared to ensure that the pretty-printed output converges to a steady state. [`tests/pretty`]: https://github.com/rust-lang/rust/tree/HEAD/tests/pretty @@ -166,8 +166,8 @@ Each revision name must start with one of: To make the revisions unique, you should add a suffix like `rpass1` and `rpass2`. -To simulate changing the source, compiletest also passes a `--cfg` flag with the -current revision name. +To simulate changing the source, +compiletest also passes a `--cfg` flag with the current revision name. For example, this will run twice, simulating changing a function: @@ -221,9 +221,10 @@ A simple example of a test using `rustc_clean` is the [hello_world test]. > opt-in. For further context, see: > [Stabilizing the state of the debuginfo test suite](https://github.com/rust-lang/compiler-team/issues/1012) -The tests in [`tests/debuginfo`] test how debuginfo is interpreted by the supported debuggers, and -confirm our visualizers still work as expected. They build a program, launch a debugger, and issue -commands to the debugger. A single test can work with cdb, gdb, and lldb. +The tests in [`tests/debuginfo`] test how debuginfo is interpreted by the supported debuggers, +and confirm our visualizers still work as expected. +They build a program, launch a debugger, and issue commands to the debugger. +A single test can work with cdb, gdb, and lldb. Most tests should have the `//@ compile-flags: -g` directive or something similar to generate the appropriate debuginfo. @@ -245,8 +246,8 @@ The debugger values can be: The command to check the output are of the form `//@ $DEBUGGER-check:$OUTPUT` where `$OUTPUT` is the output to expect. -For example, the following will build the test, start the debugger, set a -breakpoint, launch the program, inspect a value, and check what the debugger prints: +For example, the following will build the test, start the debugger, set a breakpoint, +launch the program, inspect a value, and check what the debugger prints: ```rust,ignore //@ compile-flags: -g @@ -265,7 +266,8 @@ fn b() {} Additionally, there is a special command, `//@ $DEBUGGER-repr:$VAR_NAME` intended to verify variables (and their visualizers) with more granularity than can be achieved with simple string -comparison. This directive should be preferred over the `-command`/`-check` whenever possible. +comparison. +This directive should be preferred over the `-command`/`-check` whenever possible. > [!NOTE] > At time of writing (July 2026) this command is limited to LLDB, with an implementation coming soon @@ -279,8 +281,8 @@ This command effectivly desugars into: ``` The `repr $VAR_NAME` command is intercepted by special logic that uses the debuggers' API to inspect -data that isn't reflected in the variable's printed output. The variable in memory is compared -against input data stored in +data that isn't reflected in the variable's printed output. +The variable in memory is compared against input data stored in `tests/debuginfo//input/_input/.json` and provides detailed error messages on failure. @@ -305,8 +307,9 @@ the debugger currently being used: - `min-apple-lldb-version: 1703.0.236.21`/`min-llvm-lldb-version: 21.1.0` — ignores the test if the version of lldb is below the given version. Note: Apple's fork of LLDB (distributed with Xcode) uses a different versioning scheme that is not - easily mappable to LLVM's LLDB version numbers. As such, the version gates are specified by - vendor. Further info on manually checking version equivalence is available [here](../debuginfo/testing.md#lldb-versioning) + easily mappable to LLVM's LLDB version numbers. + As such, the version gates are specified by vendor. + Further info on manually checking version equivalence is available [here](../debuginfo/testing.md#lldb-versioning) - `rust-lldb` — ignores the test if lldb is not contain the Rust plugin. NOTE: The "Rust" version of LLDB doesn't exist anymore, so this will always be ignored. This should probably be removed. @@ -361,14 +364,14 @@ See the [FileCheck] documentation for a tutorial and more information. See also the [assembly tests](#assembly-tests) for a similar set of tests. By default, codegen tests will have `//@ needs-target-std` *implied* (that the -target needs to support std), *unless* the `#![no_std]`/`#![no_core]` attribute -was specified in the test source. +target needs to support std), +*unless* the `#![no_std]`/`#![no_core]` attribute was specified in the test source. You can override this behavior and explicitly -write `//@ needs-target-std` to only run the test when target supports std, even -if the test is `#![no_std]`/`#![no_core]`. +write `//@ needs-target-std` to only run the test when target supports std, +even if the test is `#![no_std]`/`#![no_core]`. -If you need to work with `#![no_std]` cross-compiling tests, consult the -[`minicore` test auxiliary](./minicore.md) chapter. +If you need to work with `#![no_std]` cross-compiling tests, +consult the [`minicore` test auxiliary](./minicore.md) chapter. [`tests/codegen-llvm`]: https://github.com/rust-lang/rust/tree/HEAD/tests/codegen-llvm [FileCheck]: https://llvm.org/docs/CommandGuide/FileCheck.html @@ -388,8 +391,8 @@ See the [FileCheck] documentation for a tutorial and more information. See also the [codegen tests](#codegen-tests) for a similar set of tests. -If you need to work with `#![no_std]` cross-compiling tests, consult the -[`minicore` test auxiliary](./minicore.md) chapter. +If you need to work with `#![no_std]` cross-compiling tests, +consult the [`minicore` test auxiliary](./minicore.md) chapter. [`tests/assembly-llvm`]: https://github.com/rust-lang/rust/tree/HEAD/tests/assembly-llvm @@ -444,10 +447,10 @@ There are several forms the `EMIT_MIR` comment can take: interested in the final state after an optimization. Some rare cases may want to use the "before" file for completeness. -- `// EMIT_MIR $MIR_PATH.diff` — where `$MIR_PATH` is the filename of the MIR - dump, such as `my_test_name.my_function.EarlyOtherwiseBranch`. - Compiletest will diff the `.before.mir` and `.after.mir` files, and compare the diff - output to the expected `.diff` file from the `EMIT_MIR` comment. +- `// EMIT_MIR $MIR_PATH.diff` — where `$MIR_PATH` is the filename of the MIR dump, + such as `my_test_name.my_function.EarlyOtherwiseBranch`. + Compiletest will diff the `.before.mir` and `.after.mir` files, + and compare the diff output to the expected `.diff` file from the `EMIT_MIR` comment. This is useful if you want to see how an optimization changes the MIR. @@ -457,8 +460,8 @@ There are several forms the `EMIT_MIR` comment can take: By default 32 bit and 64 bit targets use the same dump files, which can be problematic in the presence of pointers in constants or other bit width dependent things. -In that case you can add `// EMIT_MIR_FOR_EACH_BIT_WIDTH` to -your test, causing separate files to be generated for 32bit and 64bit systems. +In that case you can add `// EMIT_MIR_FOR_EACH_BIT_WIDTH` to your test, +causing separate files to be generated for 32bit and 64bit systems. [`tests/mir-opt`]: https://github.com/rust-lang/rust/tree/HEAD/tests/mir-opt @@ -491,8 +494,8 @@ Each test should be in a separate directory with a `rmake.rs` Rust program, called the *recipe*. A recipe will be compiled and executed by compiletest with the `run_make_support` library linked in. -If you need new utilities or functionality, consider extending and improving the -[`run_make_support`] library. +If you need new utilities or functionality, +consider extending and improving the [`run_make_support`] library. Compiletest directives like `//@ only-` or `//@ ignore-` are supported in `rmake.rs`, like in UI tests. @@ -524,11 +527,11 @@ Of course, some tests will not successfully *run* in this way. #### Using rust-analyzer with `rmake.rs` -Like other test programs, the `rmake.rs` scripts used by run-make tests do not -have rust-analyzer integration by default. +Like other test programs, +the `rmake.rs` scripts used by run-make tests do not have rust-analyzer integration by default. -To work around this when working on a particular test, temporarily create a -`Cargo.toml` file in the test's directory +To work around this when working on a particular test, +temporarily create a `Cargo.toml` file in the test's directory (e.g. `tests/run-make/sysroot-crates-are-unstable/Cargo.toml`) with these contents: @@ -589,8 +592,8 @@ Each mode also has an alias to run the coverage tests in just that mode: ./x test coverage-map -- tests/coverage/if.rs # runs the specified test in "coverage-map" mode only ``` -If a particular test should not be run in one of the coverage test modes for -some reason, use the `//@ ignore-coverage-map` or `//@ ignore-coverage-run` directives. +If a particular test should not be run in one of the coverage test modes for some reason, +use the `//@ ignore-coverage-map` or `//@ ignore-coverage-run` directives. #### `coverage-map` suite @@ -598,11 +601,11 @@ In `coverage-map` mode, these tests verify the mappings between source code regions and coverage counters that are emitted by LLVM. They compile the test with `--emit llvm-ir`, then use a custom tool ([`src/tools/coverage-dump`]) to extract and pretty-print the coverage mappings embedded in the IR. -These tests don't require the profiler runtime, so they run in PR CI jobs and are easy to -run/bless locally. +These tests don't require the profiler runtime, +so they run in PR CI jobs and are easy to run/bless locally. -These coverage map tests can be sensitive to changes in MIR lowering or MIR -optimizations, producing mappings that are different but produce identical coverage reports. +These coverage map tests can be sensitive to changes in MIR lowering or MIR optimizations, +producing mappings that are different but produce identical coverage reports. As a rule of thumb, any PR that doesn't change coverage-specific code should **feel free to re-bless** the `coverage-map` tests as necessary, without @@ -612,19 +615,19 @@ worrying about the actual changes, as long as the `coverage-run` tests still pas In `coverage-run` mode, these tests perform an end-to-end test of coverage reporting. They compile a test program with coverage instrumentation, run that -program to produce raw coverage data, and then use LLVM tools to process that -data into a human-readable code coverage report. +program to produce raw coverage data, +and then use LLVM tools to process that data into a human-readable code coverage report. -Instrumented binaries need to be linked against the LLVM profiler runtime, so -`coverage-run` tests are **automatically skipped** unless the profiler runtime +Instrumented binaries need to be linked against the LLVM profiler runtime, +so `coverage-run` tests are **automatically skipped** unless the profiler runtime is enabled in `bootstrap.toml`: ```toml build.profiler = true ``` -This also means that they typically don't run in PR CI jobs, though they do run -as part of the full set of CI jobs used for merging. +This also means that they typically don't run in PR CI jobs, +though they do run as part of the full set of CI jobs used for merging. #### `coverage-run-rustdoc` suite @@ -638,8 +641,8 @@ This avoids having to build rustdoc when only running the main `coverage` suite. ### Crash tests -[`tests/crashes`] serve as a collection of tests that are expected to cause the -compiler to ICE, panic or crash in some other way, so that accidental fixes are tracked. +[`tests/crashes`] serve as a collection of tests that are expected to cause the compiler to ICE, +panic or crash in some other way, so that accidental fixes are tracked. Formerly, this was done at but doing it inside the rust-lang/rust testsuite is more convenient. @@ -659,8 +662,8 @@ When you do so, each issue number should be noted in the file name (`12345.rs` should suffice) and also inside the file by means of a `//@ known-bug: #12345` directive. Please [label][labeling] the relevant issues with `S-bug-has-test` once your PR is merged. -If you happen to fix one of the crashes, please move it to a fitting -subdirectory in `tests/ui` and give it a meaningful name. +If you happen to fix one of the crashes, +please move it to a fitting subdirectory in `tests/ui` and give it a meaningful name. Please add a doc comment at the top of the file explaining why this test exists. Even better will be if you can briefly explain how the example caused rustc to crash previously, and what was done to fix it. @@ -711,8 +714,8 @@ The `-L` flag is used to find the extern crates. `aux-crate` is very similar to `aux-build`. However, it uses the `--extern` flag to link to the extern crate to make the crate be available as an extern prelude. -That allows you to specify the additional syntax of the `--extern` flag, such as -renaming a dependency. +That allows you to specify the additional syntax of the `--extern` flag, +such as renaming a dependency. For example, `//@ aux-crate: foo=bar.rs` will compile `auxiliary/bar.rs` and make it available under the name `foo` within the test. This is similar to how Cargo does dependency renaming. @@ -722,8 +725,8 @@ For example, `//@ aux-crate: noprelude:foo=bar.rs`. `aux-bin` is similar to `aux-build` but will build a binary instead of a library. The binary will be available in `auxiliary/bin` relative to the working directory of the test. -`aux-codegen-backend` is similar to `aux-build`, but will then pass the compiled -dylib to `-Zcodegen-backend` when building the main file. +`aux-codegen-backend` is similar to `aux-build`, +but will then pass the compiled dylib to `-Zcodegen-backend` when building the main file. This will only work for tests in `tests/ui-fulldeps`, since it requires the use of compiler crates. ### Auxiliary proc-macro @@ -740,8 +743,8 @@ preset behavior compared to `aux-build` for the proc-macro test auxiliary: to produce a dylib for the aux crate. 3. The aux crate is made available to the test file via extern prelude with `--extern `. - Note that since UI tests default to edition - 2015, you still need to specify `extern ` unless the main + Note that since UI tests default to edition 2015, + you still need to specify `extern ` unless the main test file is using an edition that is 2018 or newer if you want to use the aux crate name in a `use` import. 4. The `proc_macro` crate is made available as an extern prelude module. @@ -794,8 +797,8 @@ This is done by adding a special directive at the top of the file: //@ revisions: foo bar baz ``` -This will result in the test being compiled (and tested) three times, once with -`--cfg foo`, once with `--cfg bar`, and once with `--cfg baz`. +This will result in the test being compiled (and tested) three times, once with `--cfg foo`, +once with `--cfg bar`, and once with `--cfg baz`. You can therefore use `#[cfg(foo)]` etc within the test to tweak each of these results. You can also customize directives and expected error messages to a particular revision. @@ -814,8 +817,8 @@ fn test_foo() { Multiple revisions can be specified in a comma-separated list, such as `//[foo,bar,baz]~^`. -In test suites that use the LLVM [FileCheck] tool, the current revision name is -also registered as an additional prefix for FileCheck directives: +In test suites that use the LLVM [FileCheck] tool, +the current revision name is also registered as an additional prefix for FileCheck directives: ```rust,ignore //@ revisions: NORMAL COVERAGE @@ -848,8 +851,8 @@ Normally, revision names mentioned in other directives and error annotations must correspond to an actual revision declared in a `revisions` directive. This is enforced by an `./x test tidy` check. -If a revision name needs to be temporarily removed from the revision list for -some reason, the above check can be suppressed by adding the revision name to an +If a revision name needs to be temporarily removed from the revision list for some reason, +the above check can be suppressed by adding the revision name to an `//@ unused-revision-names:` header instead. Specifying an unused name of `*` (i.e. `//@ unused-revision-names: *`) will @@ -857,10 +860,10 @@ permit any unused revision name to be mentioned. ## Compare modes -Compiletest can be run in different modes, called _compare modes_, which can be -used to compare the behavior of all tests with different compiler flags enabled. -This can help highlight what differences might appear with certain flags, and -check for any problems that might arise. +Compiletest can be run in different modes, called _compare modes_, +which can be used to compare the behavior of all tests with different compiler flags enabled. +This can help highlight what differences might appear with certain flags, +and check for any problems that might arise. To run the tests in a different mode, you need to pass the `--compare-mode` CLI flag: @@ -885,8 +888,8 @@ In CI, compare modes are only used in one Linux builder, and only with the follo This helps ensure that none of the debuginfo tests are affected when enabling split-DWARF. Note that compare modes are separate to [revisions](#revisions). -All revisions are tested when running `./x test tests/ui`, however compare-modes must be -manually run individually via the `--compare-mode` flag. +All revisions are tested when running `./x test tests/ui`, +however compare-modes must be manually run individually via the `--compare-mode` flag. ## Parallel frontend From 55ec44e149f4a008e91a9532803e14b3466a10f0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:32:14 +0200 Subject: [PATCH 0327/1309] missing pause --- src/doc/rustc-dev-guide/src/tests/compiletest.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/tests/compiletest.md b/src/doc/rustc-dev-guide/src/tests/compiletest.md index 7b6091c8d3253..ee42cf1fa1d87 100644 --- a/src/doc/rustc-dev-guide/src/tests/compiletest.md +++ b/src/doc/rustc-dev-guide/src/tests/compiletest.md @@ -642,7 +642,7 @@ This avoids having to build rustdoc when only running the main `coverage` suite. ### Crash tests [`tests/crashes`] serve as a collection of tests that are expected to cause the compiler to ICE, -panic or crash in some other way, so that accidental fixes are tracked. +panic, or crash in some other way, so that accidental fixes are tracked. Formerly, this was done at but doing it inside the rust-lang/rust testsuite is more convenient. From 65ee597275dff32783d7b308dddea75904f1a04b Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:32:50 +0200 Subject: [PATCH 0328/1309] sembr src/tests/ecosystem-test-jobs/rust-for-linux.md --- .../ecosystem-test-jobs/rust-for-linux.md | 35 +++++++++---------- 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md index a6a7374b811be..e2d3bec5d86f7 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/rust-for-linux.md @@ -7,23 +7,22 @@ support for the Rust programming language into the Linux kernel. If a PR breaks the Rust for Linux CI job, then: -- If the breakage was unintentional and seems spurious, then let [RfL][rfl-ping] - know and retry. - - If the PR is urgent and retrying doesn't fix it, then disable the CI job - temporarily (comment out the `image: x86_64-rust-for-linux` job in +- If the breakage was unintentional and seems spurious, then let [RfL][rfl-ping] know and retry. + - If the PR is urgent and retrying doesn't fix it, + then disable the CI job temporarily (comment out the `image: x86_64-rust-for-linux` job in `src/ci/github-actions/jobs.yml`). - If the breakage was unintentional, then change the PR to resolve the breakage. -- If the breakage was intentional, then let [RfL][rfl-ping] know and discuss - what will the kernel need to change. +- If the breakage was intentional, + then let [RfL][rfl-ping] know and discuss what will the kernel need to change. - If the PR is urgent, then disable the CI job temporarily (comment out the `image: x86_64-rust-for-linux` job in `src/ci/github-actions/jobs.yml`). - If the PR can wait a few days, then wait for RfL maintainers to provide a - new Linux kernel commit hash with the needed changes done, and apply it to - the PR, which would confirm the changes work (update the `LINUX_VERSION` + new Linux kernel commit hash with the needed changes done, and apply it to the PR, + which would confirm the changes work (update the `LINUX_VERSION` environment variable in `src/ci/docker/scripts/rfl-build.sh`). -If you need to contact the RfL developers, you can ping the [Rust for Linux][rfl-ping] -ping group to ask for help: +If you need to contact the RfL developers, +you can ping the [Rust for Linux][rfl-ping] ping group to ask for help: ```text @rustbot ping rfl @@ -31,17 +30,17 @@ ping group to ask for help: ## Building Rust for Linux in CI -Rust for Linux builds as part of the suite of bors tests that run before a pull -request is merged. +Rust for Linux builds as part of the suite of bors tests that run before a pull request is merged. -The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux -kernel, and tries to compile several Rust for Linux drivers and examples using -this sysroot. RfL uses several unstable compiler/language features, therefore -this workflow notifies us if a given compiler change would break it. +The workflow builds a stage1 sysroot of the Rust compiler, downloads the Linux kernel, +and tries to compile several Rust for Linux drivers and examples using +this sysroot. +RfL uses several unstable compiler/language features, +therefore this workflow notifies us if a given compiler change would break it. If you are worried that a pull request might break the Rust for Linux builder -and want to test it out before submitting it to the bors queue, simply ask -bors to run the try job that builds the Rust for Linux integration: +and want to test it out before submitting it to the bors queue, +simply ask bors to run the try job that builds the Rust for Linux integration: `@bors try jobs=x86_64-rust-for-linux`. [rfl-ping]: ../../notification-groups/rust-for-linux.md From 6c549a9e8a2c2afae49e9a758f87be349211a5e2 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:34:38 +0200 Subject: [PATCH 0329/1309] sembr src/tests/ecosystem-test-jobs/fuchsia.md --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 98 +++++++++---------- 1 file changed, 48 insertions(+), 50 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 75cf782a77025..124e8dfcda18d 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -14,8 +14,7 @@ Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. ## Building Fuchsia in CI -Fuchsia builds as part of the suite of bors tests that run before a pull request -is merged. +Fuchsia builds as part of the suite of bors tests that run before a pull request is merged. If you are worried that a pull request might break the Fuchsia builder and want to test it out before submitting it to the bors queue, simply ask bors to run @@ -23,13 +22,13 @@ the try job that builds the Fuchsia integration: `@bors try jobs=x86_64-fuchsia` ## Building Fuchsia locally -Because Fuchsia uses languages other than Rust, it does not use Cargo as a build -system. It also requires the toolchain build to be configured in a [certain -way][build-toolchain]. +Because Fuchsia uses languages other than Rust, it does not use Cargo as a build system. +It also requires the toolchain build to be configured in a [certain way][build-toolchain]. The recommended way to build Fuchsia is to use the Docker scripts that check out -and run a Fuchsia build for you. If you've run Docker tests before, you can -simply run this command from your Rust checkout to download and build Fuchsia +and run a Fuchsia build for you. +If you've run Docker tests before, +you can simply run this command from your Rust checkout to download and build Fuchsia using your local Rust toolchain. ``` @@ -40,20 +39,19 @@ See the [Testing with Docker](../docker.md) chapter for more details on how to r and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and -build takes 46G of space – and as you might imagine, it takes a while to -complete. +build takes 46G of space – and as you might imagine, it takes a while to complete. ### Modifying the Fuchsia checkout The main reason you would want to build Fuchsia locally is because you need to -investigate a regression. After running a Docker build, you'll find the Fuchsia -checkout inside the `obj/fuchsia` directory of your Rust checkout. If you -modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to -`KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build -command above. This will reuse all the build results from before. +investigate a regression. +After running a Docker build, +you'll find the Fuchsia checkout inside the `obj/fuchsia` directory of your Rust checkout. + If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to +`KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build command above. +This will reuse all the build results from before. -You can find more options to customize the Fuchsia checkout in the -[build-fuchsia.sh] script. +You can find more options to customize the Fuchsia checkout in the [build-fuchsia.sh] script. ### Customizing the Fuchsia build @@ -69,14 +67,15 @@ to add this to your `$PATH` for some workflows. There are a few `fx` subcommands that are relevant, including: -- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and - runs GN. -- `fx build` builds the Fuchsia project using Ninja. It will automatically pick - up changes to build arguments and rerun GN. By default it builds everything, +- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. +- `fx build` builds the Fuchsia project using Ninja. + It will automatically pick up changes to build arguments and rerun GN. + By default it builds everything, but it also accepts target paths to build specific targets (see below). -- `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this - in the Rust CI build to avoid running codegen on most Rust targets. Underneath - it invokes Ninja, just like `fx build`. The clippy results are saved in json +- `fx clippy` runs Clippy on specific Rust targets (or all of them). + We use this in the Rust CI build to avoid running codegen on most Rust targets. + Underneath it invokes Ninja, just like `fx build`. + The clippy results are saved in json files inside the build output directory before being printed. #### Target paths @@ -87,20 +86,20 @@ GN uses paths like the following to identify build targets: //src/starnix/kernel:starnix_core ``` -The initial `//` means the root of the checkout, and the remaining slashes are -directory names. The string after `:` is the _target name_ of a target defined +The initial `//` means the root of the checkout, and the remaining slashes are directory names. +The string after `:` is the _target name_ of a target defined in the `BUILD.gn` file of that directory. -The target name can be omitted if it is the same as the directory name. In other -words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. +The target name can be omitted if it is the same as the directory name. +In other words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. These target paths are used inside `BUILD.gn` files to reference dependencies, and can also be used in `fx build`. #### Modifying compiler flags -You can put custom compiler flags inside a GN `config` that is added to a -target. As a simple example: +You can put custom compiler flags inside a GN `config` that is added to a target. +As a simple example: ``` config("everybody_loops") { @@ -114,20 +113,20 @@ rustc_binary("example") { } ``` -This will add the flag `-Zeverybody-loops` to rustc when building the `example` -target. Note that you can also use [`public_configs`] for a config to be added +This will add the flag `-Zeverybody-loops` to rustc when building the `example` target. +Note that you can also use [`public_configs`] for a config to be added to every target that depends on that target. -If you want to add a flag to every Rust target in the build, you can add -rustflags to the [`//build/config:compiler`] config or to the OS-specific -configs referenced in that file. Note that `cflags` and `ldflags` are ignored on -Rust targets. +If you want to add a flag to every Rust target in the build, +you can add rustflags to the [`//build/config:compiler`] config or to the OS-specific +configs referenced in that file. +Note that `cflags` and `ldflags` are ignored on Rust targets. #### Running ninja and rustc commands directly -Going down one layer, `fx build` invokes `ninja`, which in turn eventually -invokes `rustc`. All build actions are run inside the out directory, which is -usually `out/default` inside the Fuchsia checkout. +Going down one layer, `fx build` invokes `ninja`, which in turn eventually invokes `rustc`. +All build actions are run inside the out directory, +which is usually `out/default` inside the Fuchsia checkout. You can get ninja to print the actual command it invokes by forcing that command to fail, e.g. by adding a syntax error to one of the source files of the target. @@ -135,26 +134,25 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will -rebuild all the Rust targets. This can be done in a text editor and the contents -of the string do not matter, as long as it changes from one build to the next. -[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain -directory. +rebuild all the Rust targets. +This can be done in a text editor and the contents of the string do not matter, +as long as it changes from one build to the next. +[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. The Fuchsia website has more detailed documentation of the [build system]. #### Other tips and tricks When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` -command after the initial run so it won't rerun GN each time. If you do this you -can also comment out the version_string line to save a couple seconds. +command after the initial run so it won't rerun GN each time. +If you do this you can also comment out the version_string line to save a couple seconds. -`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the -initial build. +`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. ## Fuchsia target support -To learn more about Fuchsia target support, see the Fuchsia chapter in [the -rustc book][platform-support]. +To learn more about Fuchsia target support, +see the Fuchsia chapter in [the rustc book][platform-support]. [regressions]: https://gist.github.com/tmandry/7103eba4bd6a6fb0c439b5a90ae355fa [build-toolchain]: https://fuchsia.dev/fuchsia-src/development/build/rust_toolchain @@ -169,5 +167,5 @@ rustc book][platform-support]. [fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust -code and a roughly equal amount of third-party code, as counted by tokei -(excluding comments and blanks). +code and a roughly equal amount of third-party code, +as counted by tokei (excluding comments and blanks). From 3d3f2f823fa54902104dc5ee13c15915cd89a0ce Mon Sep 17 00:00:00 2001 From: Ricky Date: Fri, 18 Sep 2026 20:35:21 +0800 Subject: [PATCH 0330/1309] update VecDeque PartialEq stability metadata --- library/alloc/src/collections/vec_deque/macros.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index 4ef2a89e06018..d808a9d8fa993 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -20,7 +20,7 @@ macro_rules! __impl_slice_eq1 { macro_rules! __impl_slice_eq2 { ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - #[stable(feature = "vec_deque_partial_eq_slice", since = "1.17.0")] + #[stable(feature = "vec_deque_partial_eq_slice", since = "CURRENT_RUSTC_VERSION")] impl PartialEq<$rhs> for $lhs where T: PartialEq, From 0ef25a5183ecb4099051786228c9fb53af1161ea Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 18 Sep 2026 14:46:02 +0200 Subject: [PATCH 0331/1309] Merge pull request #1702 from Kobzol/josh-sync-script Update `rustup.sh` to use `rustc-josh-sync` --- .../rustc_codegen_cranelift/scripts/rustup.sh | 52 +++---------------- 1 file changed, 7 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index e26be307328f0..991524a1be912 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -4,19 +4,8 @@ set -e TOOLCHAIN=${TOOLCHAIN:-$(date +%Y-%m-%d)} -function check_git_fixed_subtree() { - if [[ ! -e ./git-fixed-subtree.sh ]]; then - echo "Missing git-fixed-subtree.sh. Please run the following commands to download it:" - echo "curl --proto '=https' --tlsv1.2 -sSf https://raw.githubusercontent.com/bjorn3/git/tqc-subtree-portable/contrib/subtree/git-subtree.sh -o git-fixed-subtree.sh" - echo "chmod u+x git-fixed-subtree.sh" - exit 1 - fi - if [[ ! -x ./git-fixed-subtree.sh ]]; then - echo "git-fixed-subtree.sh is not executable. Please run the following command to make it executable:" - echo "chmod u+x git-fixed-subtree.sh" - exit 1 - fi -} +export GIT_CONFIG_GLOBAL=../rust/josh.gitconfig +export RUSTC_GIT=../rust case $1 in "prepare") @@ -33,44 +22,17 @@ case $1 in ./y.sh prepare ;; - "commit") - git add rust-toolchain.toml - git commit -m "Rustup to $(rustc -V)" - ;; "push") - check_git_fixed_subtree - - cg_clif=$(pwd) - pushd ../rust - git pull origin main + username=${2:-bjorn3} branch=sync_cg_clif-$(date +%Y-%m-%d) - git checkout -b "$branch" - "$cg_clif/git-fixed-subtree.sh" pull --prefix=compiler/rustc_codegen_cranelift/ https://github.com/rust-lang/rustc_codegen_cranelift.git main - git push -u my "$branch" - - # immediately merge the merge commit into cg_clif to prevent merge conflicts when syncing - # from rust-lang/rust later - "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust - popd - git merge sync_from_rust + rustc-josh-sync push "$branch" "$username" ;; "pull") - check_git_fixed_subtree - - RUST_VERS=$(curl "https://static.rust-lang.org/dist/$TOOLCHAIN/channel-rust-nightly-git-commit-hash.txt") - echo "Pulling $RUST_VERS ($TOOLCHAIN)" - - cg_clif=$(pwd) - pushd ../rust - git fetch origin main - git -c advice.detachedHead=false checkout "$RUST_VERS" - "$cg_clif/git-fixed-subtree.sh" push --prefix=compiler/rustc_codegen_cranelift/ "$cg_clif" sync_from_rust - popd - git merge sync_from_rust -m "Sync from rust $RUST_VERS" - git branch -d sync_from_rust + git checkout -b sync_from_rust + rustc-josh-sync pull ;; *) echo "Unknown command '$1'" - echo "Usage: ./rustup.sh prepare|commit" + echo "Usage: ./rustup.sh prepare|pull|push [fork]" ;; esac From 9f092518e89692b1c2490cb15688361b73b313e1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:54:17 +0200 Subject: [PATCH 0332/1309] improve tests/ecosystem-test-jobs/fuchsia.md --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 124e8dfcda18d..edbb3b93a0808 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -47,7 +47,7 @@ The main reason you would want to build Fuchsia locally is because you need to investigate a regression. After running a Docker build, you'll find the Fuchsia checkout inside the `obj/fuchsia` directory of your Rust checkout. - If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to +If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build command above. This will reuse all the build results from before. @@ -70,11 +70,11 @@ There are a few `fx` subcommands that are relevant, including: - `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. - `fx build` builds the Fuchsia project using Ninja. It will automatically pick up changes to build arguments and rerun GN. - By default it builds everything, + By default, it builds everything, but it also accepts target paths to build specific targets (see below). - `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this in the Rust CI build to avoid running codegen on most Rust targets. - Underneath it invokes Ninja, just like `fx build`. + Underneath, it invokes Ninja, just like `fx build`. The clippy results are saved in json files inside the build output directory before being printed. @@ -135,7 +135,7 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will rebuild all the Rust targets. -This can be done in a text editor and the contents of the string do not matter, +This can be done in a text editor, and the contents of the string do not matter, as long as it changes from one build to the next. [build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. @@ -145,7 +145,7 @@ The Fuchsia website has more detailed documentation of the [build system]. When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` command after the initial run so it won't rerun GN each time. -If you do this you can also comment out the version_string line to save a couple seconds. +If you do this, you can also comment out the version_string line to save a few seconds. `export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. From 04357edb2f8fe29ed8284509cd9ed0d2af80266a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 14:54:30 +0200 Subject: [PATCH 0333/1309] sembr src/closure.md --- src/doc/rustc-dev-guide/src/closure.md | 109 +++++++++++++------------ 1 file changed, 59 insertions(+), 50 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index 427919cd57995..c59e512daef89 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -1,13 +1,12 @@ # Closure Capture Inference -This section describes how rustc handles closures. Closures in Rust are -effectively "desugared" into structs that contain the values they use (or -references to the values they use) from their creator's stack frame. rustc has -the job of figuring out which values a closure uses and how, so it can decide -whether to capture a given variable by shared reference, mutable reference, or -by move. rustc also has to figure out which of the closure traits ([`Fn`][fn], -[`FnMut`][fn_mut], or [`FnOnce`][fn_once]) a closure is capable of -implementing. +This section describes how rustc handles closures. +Closures in Rust are effectively "desugared" into structs that contain the values they use (or +references to the values they use) from their creator's stack frame. +rustc has the job of figuring out which values a closure uses and how, so it can decide +whether to capture a given variable by shared reference, mutable reference, or by move. +rustc also has to figure out which of the closure traits ([`Fn`][fn], +[`FnMut`][fn_mut], or [`FnOnce`][fn_once]) a closure is capable of implementing. [fn]: https://doc.rust-lang.org/std/ops/trait.Fn.html [fn_mut]:https://doc.rust-lang.org/std/ops/trait.FnMut.html @@ -31,8 +30,9 @@ fn main() { } ``` -Let's say the above is the content of a file called `immut.rs`. If we compile -`immut.rs` using the following command. The [`-Z dump-mir=all`][dump-mir] flag will cause +Let's say the above is the content of a file called `immut.rs`. +If we compile `immut.rs` using the following command. +The [`-Z dump-mir=all`][dump-mir] flag will cause `rustc` to generate and dump the [MIR][mir] to a directory called `mir_dump`. ```console > rustc +stage1 immut.rs -Z dump-mir=all @@ -43,8 +43,8 @@ Let's say the above is the content of a file called `immut.rs`. If we compile After we run this command, we will see a newly generated directory in our current working directory called `mir_dump`, which will contain several files. -If we look at file `rustc.main.-------.mir_map.0.mir`, we will find, among -other things, it also contains this line: +If we look at file `rustc.main.-------.mir_map.0.mir`, we will find, among other things, +it also contains this line: ```rust,ignore _4 = &_1; @@ -53,9 +53,9 @@ _3 = [closure@immut.rs:7:13: 7:36] { x: move _4 }; Note that in the MIR examples in this chapter, `_1` is `x`. -Here in first line `_4 = &_1;`, the `mir_dump` tells us that `x` was borrowed -as an immutable reference. This is what we would hope as our closure just -reads `x`. +Here in first line `_4 = &_1;`, +the `mir_dump` tells us that `x` was borrowed as an immutable reference. + This is what we would hope as our closure just reads `x`. ### Example 2 @@ -81,7 +81,8 @@ _4 = &mut _1; _3 = [closure@mut.rs:7:13: 10:6] { x: move _4 }; ``` This time along, in the line `_4 = &mut _1;`, we see that the borrow is changed to mutable borrow. -Fair enough! The closure increments `x` by 10. +Fair enough! +The closure increments `x` by 10. ### Example 3 @@ -104,33 +105,40 @@ fn main() { ```rust,ignore _6 = [closure@move.rs:7:13: 9:6] { x: move _1 }; // bb16[3]: scope 1 at move.rs:7:13: 9:6 ``` -Here, `x` is directly moved into the closure and the access to it will not be permitted after the -closure. +Here, +`x` is directly moved into the closure and the access to it will not be permitted after the closure. ## Inferences in the compiler Now let's dive into rustc code and see how all these inferences are done by the compiler. Let's start with defining a term that we will be using quite a bit in the rest of the discussion - -*upvar*. An **upvar** is a variable that is local to the function where the closure is defined. So, -in the above examples, **x** will be an upvar to the closure. They are also sometimes referred to as +*upvar*. An **upvar** is a variable that is local to the function where the closure is defined. +So, +in the above examples, **x** will be an upvar to the closure. +They are also sometimes referred to as the *free variables* meaning they are not bound to the context of the closure. [`compiler/rustc_passes/src/upvars.rs`][upvars] defines a query called *upvars_mentioned* for this purpose. [upvars]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_passes/upvars/index.html -Other than lazy invocation, one other thing that distinguishes a closure from a -normal function is that it can use the upvars. It borrows these upvars from its surrounding -context; therefore the compiler has to determine the upvar's borrow type. The compiler starts with -assigning an immutable borrow type and lowers the restriction (that is, changes it from -**immutable** to **mutable** to **move**) as needed, based on the usage. In the Example 1 above, the +Other than lazy invocation, +one other thing that distinguishes a closure from a normal function is that it can use the upvars. +It borrows these upvars from its surrounding +context; therefore the compiler has to determine the upvar's borrow type. +The compiler starts with assigning an immutable borrow type and lowers the restriction (that is, +changes it from +**immutable** to **mutable** to **move**) as needed, based on the usage. +In the Example 1 above, the closure only uses the variable for printing but does not modify it in any way and therefore, in the -`mir_dump`, we find the borrow type for the upvar `x` to be immutable. In example 2, however, the -closure modifies `x` and increments it by some value. Because of this mutation, the compiler, which +`mir_dump`, we find the borrow type for the upvar `x` to be immutable. + In example 2, however, the closure modifies `x` and increments it by some value. + Because of this mutation, the compiler, which started off assigning `x` as an immutable reference type, has to adjust it as a mutable reference. Likewise in the third example, the closure drops the vector and therefore this requires the variable -`x` to be moved into the closure. Depending on the borrow kind, the closure has to implement the +`x` to be moved into the closure. +Depending on the borrow kind, the closure has to implement the appropriate trait: `Fn` trait for immutable borrow, `FnMut` for mutable borrow, and `FnOnce` for move semantics. @@ -141,17 +149,17 @@ declared in the file [`compiler/rustc_middle/src/ty/mod.rs`][ty]. [upvar]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/upvar/index.html [ty]:https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/index.html -Before we go any further, let's discuss how we can examine the flow of control through the rustc -codebase. For closures specifically, set the `RUSTC_LOG` env variable as below and collect the -output in a file: +Before we go any further, +let's discuss how we can examine the flow of control through the rustc codebase. +For closures specifically, +set the `RUSTC_LOG` env variable as below and collect the output in a file: ```console > RUSTC_LOG=rustc_hir_typeck::upvar rustc +stage1 -Z dump-mir=all \ <.rs file to compile> 2> ``` -This uses the stage1 compiler and enables `debug!` logging for the -`rustc_hir_typeck::upvar` module. +This uses the stage1 compiler and enables `debug!` logging for the `rustc_hir_typeck::upvar` module. The other option is to step through the code using lldb or gdb. @@ -160,8 +168,8 @@ The other option is to step through the code using lldb or gdb. 1. `b upvar.rs:134` // Setting the breakpoint on a certain line in the upvar.rs file 2. `r` // Run the program until it hits the breakpoint -Let's start with [`upvar.rs`][upvar]. This file has something called -the [`euv::ExprUseVisitor`] which walks the source of the closure and +Let's start with [`upvar.rs`][upvar]. +This file has something called the [`euv::ExprUseVisitor`] which walks the source of the closure and invokes a callback for each upvar that is borrowed, mutated, or moved. [`euv::ExprUseVisitor`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_hir_typeck/expr_use_visitor/struct.ExprUseVisitor.html @@ -176,32 +184,33 @@ fn main() { } ``` -In the above example, our visitor will be called twice, for the lines marked 1 and 2, once for a -shared borrow and another one for a mutable borrow. It will also tell us what was borrowed. +In the above example, our visitor will be called twice, for the lines marked 1 and 2, +once for a shared borrow and another one for a mutable borrow. +It will also tell us what was borrowed. -The callbacks are defined by implementing the [`Delegate`] trait. The -[`InferBorrowKind`][ibk] type implements `Delegate` and keeps a map that -records for each upvar which mode of capture was required. The modes of capture -can be `ByValue` (moved) or `ByRef` (borrowed). For `ByRef` borrows, the possible -[`BorrowKind`]s are `ImmBorrow`, `UniqueImmBorrow`, `MutBorrow` as defined in the +The callbacks are defined by implementing the [`Delegate`] trait. +The [`InferBorrowKind`][ibk] type implements `Delegate` and keeps a map that +records for each upvar which mode of capture was required. +The modes of capture can be `ByValue` (moved) or `ByRef` (borrowed). +For `ByRef` borrows, the possible [`BorrowKind`]s are `ImmBorrow`, +`UniqueImmBorrow`, `MutBorrow` as defined in the [`compiler/rustc_middle/src/ty/mod.rs`][middle_ty]. [`BorrowKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/enum.BorrowKind.html [middle_ty]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/index.html `Delegate` defines a few different methods (the different callbacks): -**consume** for *move* of a variable, **borrow** for a *borrow* of some kind -(shared or mutable), and **mutate** when we see an *assignment* of something. +**consume** for *move* of a variable, **borrow** for a *borrow* of some kind (shared or mutable), +and **mutate** when we see an *assignment* of something. All of these callbacks have a common argument *cmt* which stands for Category, -Mutability and Type and is defined in -[`compiler/rustc_hir_typeck/src/expr_use_visitor.rs`][cmt]. Borrowing from the code -comments, "`cmt` is a complete categorization of a value indicating where it +Mutability and Type and is defined in [`compiler/rustc_hir_typeck/src/expr_use_visitor.rs`][cmt]. +Borrowing from the code comments, "`cmt` is a complete categorization of a value indicating where it originated and how it is located, as well as the mutability of the memory in which the value is stored". Based on the callback (consume, borrow etc.), we -will call the relevant `adjust_upvar_borrow_kind_for_` and pass the -`cmt` along. Once the borrow type is adjusted, we store it in the table, which -basically says what borrows were made for each closure. +will call the relevant `adjust_upvar_borrow_kind_for_` and pass the `cmt` along. +Once the borrow type is adjusted, we store it in the table, +which basically says what borrows were made for each closure. ```rust,ignore self.tables From b0f83b7d0a099fe4af956785ae79aa0edc2d5860 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 14:55:56 +0200 Subject: [PATCH 0334/1309] Update `browser-ui-test` version to `0.25.2` --- package.json | 2 +- yarn.lock | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/package.json b/package.json index d9a3ced805ba5..876d81c1d60ef 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "dependencies": { - "browser-ui-test": "^0.25.0", + "browser-ui-test": "^0.25.2", "es-check": "^9.4.4", "eslint": "^8.57.1", "typescript": "^5.8.3" diff --git a/yarn.lock b/yarn.lock index 55c862d1e75dd..e49c9209142f9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -154,10 +154,10 @@ braces@^3.0.3: dependencies: fill-range "^7.1.1" -browser-ui-test@^0.25.0: - version "0.25.1" - resolved "https://registry.yarnpkg.com/browser-ui-test/-/browser-ui-test-0.25.1.tgz#c7f22a5e2b9e51be4ba34df3adf7bd7a9249bce6" - integrity sha512-woRwKU1dPBIwYmCI6npox8qlPO0WQ8GZH2YbL39mNkiWymByebiB4EK0PlaGMbmEja0MEqfMQD+d33LCW4S2AA== +browser-ui-test@^0.25.2: + version "0.25.2" + resolved "https://registry.yarnpkg.com/browser-ui-test/-/browser-ui-test-0.25.2.tgz#31db7386497b3eef4d79e236bd2091c1162148a9" + integrity sha512-74njL1/xjg5UumbhQblWa6oAn/PcaOnlJmoSe9FabJaXrLsI2f8DJ3B8vunvCJwZa90V4Jm94xyg/JPi+l+zZQ== dependencies: css-unit-converter "^1.1.2" pngjs "^3.4.0" From 14e479d21eef2cdc6934a7078c085747733736fe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 15:09:29 +0200 Subject: [PATCH 0335/1309] improve closure.md --- src/doc/rustc-dev-guide/src/closure.md | 28 +++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index c59e512daef89..33206ed885bc5 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -31,9 +31,10 @@ fn main() { ``` Let's say the above is the content of a file called `immut.rs`. -If we compile `immut.rs` using the following command. -The [`-Z dump-mir=all`][dump-mir] flag will cause -`rustc` to generate and dump the [MIR][mir] to a directory called `mir_dump`. +If we compile `immut.rs` using the following command, +the [`-Z dump-mir=all`][dump-mir] flag will cause +`rustc` to generate and dump the [MIR] to a directory called `mir_dump`. + ```console > rustc +stage1 immut.rs -Z dump-mir=all ``` @@ -55,7 +56,7 @@ Note that in the MIR examples in this chapter, `_1` is `x`. Here in first line `_4 = &_1;`, the `mir_dump` tells us that `x` was borrowed as an immutable reference. - This is what we would hope as our closure just reads `x`. +This is what we would hope as our closure just reads `x`. ### Example 2 @@ -105,19 +106,19 @@ fn main() { ```rust,ignore _6 = [closure@move.rs:7:13: 9:6] { x: move _1 }; // bb16[3]: scope 1 at move.rs:7:13: 9:6 ``` -Here, -`x` is directly moved into the closure and the access to it will not be permitted after the closure. +Here, `x` is directly moved into the closure, +and the access to it will not be permitted after the closure. ## Inferences in the compiler Now let's dive into rustc code and see how all these inferences are done by the compiler. Let's start with defining a term that we will be using quite a bit in the rest of the discussion - -*upvar*. An **upvar** is a variable that is local to the function where the closure is defined. -So, -in the above examples, **x** will be an upvar to the closure. -They are also sometimes referred to as -the *free variables* meaning they are not bound to the context of the closure. +*upvar*. +An **upvar** is a variable that is local to the function where the closure is defined. +So, in the above examples, **x** will be an upvar to the closure. +They are also sometimes referred to as the *free variables*, +meaning they are not bound to the context of the closure. [`compiler/rustc_passes/src/upvars.rs`][upvars] defines a query called *upvars_mentioned* for this purpose. @@ -127,9 +128,8 @@ Other than lazy invocation, one other thing that distinguishes a closure from a normal function is that it can use the upvars. It borrows these upvars from its surrounding context; therefore the compiler has to determine the upvar's borrow type. -The compiler starts with assigning an immutable borrow type and lowers the restriction (that is, -changes it from -**immutable** to **mutable** to **move**) as needed, based on the usage. +The compiler starts with assigning an immutable borrow type and lowers the restriction +(that is, changes it from **immutable** to **mutable** to **move**) as needed, based on the usage. In the Example 1 above, the closure only uses the variable for printing but does not modify it in any way and therefore, in the `mir_dump`, we find the borrow type for the upvar `x` to be immutable. From f8f15cf79fcb06ae2b6004285c9092c020dc7e98 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 15:22:28 +0200 Subject: [PATCH 0336/1309] fix whitespace --- src/doc/rustc-dev-guide/src/offload/installation.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/offload/installation.md b/src/doc/rustc-dev-guide/src/offload/installation.md index baf689f458077..2bb7ea98f6d5b 100644 --- a/src/doc/rustc-dev-guide/src/offload/installation.md +++ b/src/doc/rustc-dev-guide/src/offload/installation.md @@ -4,12 +4,12 @@ For now, everyone however still needs to build rustc from source to use all features of it. ## Rustup installation. + If you are on `x86_64` Linux, you can install the nightly toolchain with: ```console rustup +nightly component add offload ``` - ## Build instructions Otherwise you need to clone and configure the Rust repository: @@ -35,9 +35,8 @@ rustup toolchain link offload build/host/stage1 rustup toolchain install nightly # enables -Z unstable-options ``` - - ## Build instruction for LLVM itself + ```console git clone git@github.com:llvm/llvm-project cd llvm-project @@ -49,8 +48,8 @@ ninja install ``` This gives you a working LLVM build. - ## Testing + Run this test script for offload-specific tests: ```console ./x test --stage 1 tests/codegen-llvm/gpu_offload From c60430f10f465941ad8818e73230e950f170b572 Mon Sep 17 00:00:00 2001 From: beetrees Date: Fri, 18 Sep 2026 12:27:37 +0100 Subject: [PATCH 0337/1309] Add missing `#[repr(C)]` in UI, codegen and assembly tests --- tests/assembly-llvm/asm/amdgpu-vec-types.rs | 3 ++- tests/assembly-llvm/naked-functions/wasm32.rs | 1 - tests/assembly-llvm/reg-struct-return.rs | 3 +++ tests/codegen-llvm/abi-x86_64_sysv.rs | 2 ++ tests/codegen-llvm/bpf-abi/indirect-return.rs | 1 + tests/codegen-llvm/complex-abi.rs | 3 ++- tests/codegen-llvm/regparm-inreg.rs | 11 ++++++----- .../riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs | 3 ++- tests/codegen-llvm/scalable-vectors/memcpy.rs | 3 ++- tests/ui/abi/abi-sysv64-arg-passing.rs | 3 ++- tests/ui/abi/abi-sysv64-register-usage.rs | 2 +- tests/ui/abi/arm-unadjusted-intrinsic.rs | 2 +- tests/ui/abi/compatibility.rs | 2 +- tests/ui/abi/extern-c-two-doubles-x86_64-5754.rs | 2 +- tests/ui/abi/extern/extern-c-method-return-struct.rs | 3 ++- tests/ui/abi/extern/extern-pass-FiveU16s.rs | 2 +- tests/ui/abi/extern/extern-pass-TwoU16s.rs | 2 +- tests/ui/abi/extern/extern-pass-TwoU32s.rs | 2 +- tests/ui/abi/extern/extern-pass-TwoU64s.rs | 2 +- tests/ui/abi/extern/extern-pass-TwoU8s.rs | 2 +- tests/ui/abi/extern/extern-pass-empty.rs | 2 +- tests/ui/abi/extern/extern-return-FiveU16s.rs | 2 +- tests/ui/abi/extern/extern-return-TwoU16s.rs | 2 +- tests/ui/abi/extern/extern-return-TwoU32s.rs | 2 +- tests/ui/abi/extern/extern-return-TwoU64s.rs | 2 +- tests/ui/abi/extern/extern-return-TwoU8s.rs | 2 +- tests/ui/abi/foreign/foreign-fn-with-byval.rs | 2 +- tests/ui/abi/issue-28676.rs | 2 +- .../ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs | 2 +- .../issue-97463-broken-abi-leaked-uninit-data.rs | 2 -- tests/ui/abi/large-byval-align.rs | 3 +-- tests/ui/abi/non-rustic-unsized.rs | 2 +- tests/ui/abi/simd-abi-checks-avx.rs | 2 +- tests/ui/abi/simd-abi-checks-s390x.rs | 2 +- tests/ui/abi/simd-abi-checks-sse.rs | 2 +- .../abi/unsized-args-in-c-abi-issues-94223-115845.rs | 2 +- tests/ui/ffi/ffi-struct-size-alignment.rs | 2 +- 37 files changed, 49 insertions(+), 40 deletions(-) diff --git a/tests/assembly-llvm/asm/amdgpu-vec-types.rs b/tests/assembly-llvm/asm/amdgpu-vec-types.rs index 1613e603fca49..8ff4208636bc6 100644 --- a/tests/assembly-llvm/asm/amdgpu-vec-types.rs +++ b/tests/assembly-llvm/asm/amdgpu-vec-types.rs @@ -14,11 +14,12 @@ #![allow( asm_sub_register, improper_gpu_kernel_arg, - improper_ctypes_definitions, non_camel_case_types, unused_assignments, unused_variables )] +#![deny(unfulfilled_lint_expectations)] +#![expect(improper_ctypes_definitions)] extern crate minicore; use minicore::simd::*; diff --git a/tests/assembly-llvm/naked-functions/wasm32.rs b/tests/assembly-llvm/naked-functions/wasm32.rs index e2a2ab94c8a33..b2754029021bf 100644 --- a/tests/assembly-llvm/naked-functions/wasm32.rs +++ b/tests/assembly-llvm/naked-functions/wasm32.rs @@ -99,7 +99,6 @@ extern "C" fn fn_i64_i64(num: i64) -> i64 { // wasm32-unknown: .functype fn_i128_i128 (i32, i64, i64) -> () // wasm32-wasip1: .functype fn_i128_i128 (i32, i64, i64) -> () // wasm64-unknown: .functype fn_i128_i128 (i64, i64, i64) -> () -#[allow(improper_ctypes_definitions)] #[no_mangle] #[unsafe(naked)] extern "C" fn fn_i128_i128(num: i128) -> i128 { diff --git a/tests/assembly-llvm/reg-struct-return.rs b/tests/assembly-llvm/reg-struct-return.rs index d364954abe30d..59e40c9e6fb12 100644 --- a/tests/assembly-llvm/reg-struct-return.rs +++ b/tests/assembly-llvm/reg-struct-return.rs @@ -23,6 +23,7 @@ use minicore::*; // Verifies ABI changes for small structs, where both fields fit into one register. // WITH is expected to use register return, WITHOUT should use hidden pointer. mod Small { + #[repr(C)] struct SmallStruct { a: i8, b: i8, @@ -66,6 +67,7 @@ mod Small { // WITH is expected to still use register return, WITHOUT should use hidden // pointer. mod Pivot { + #[repr(C)] struct PivotStruct { a: i32, b: i32, @@ -109,6 +111,7 @@ mod Pivot { // maximum size for reg-struct-return (8 bytes). // Here, the hidden pointer convention should be used even when `-Zreg-struct-return` is set. mod Large { + #[repr(C)] struct LargeStruct { a: i32, b: i32, diff --git a/tests/codegen-llvm/abi-x86_64_sysv.rs b/tests/codegen-llvm/abi-x86_64_sysv.rs index 09909f994d652..b8912c91ebaee 100644 --- a/tests/codegen-llvm/abi-x86_64_sysv.rs +++ b/tests/codegen-llvm/abi-x86_64_sysv.rs @@ -4,12 +4,14 @@ #![crate_type = "lib"] +#[repr(C)] pub struct S24 { a: i8, b: i8, c: i8, } +#[repr(C)] pub struct S48 { a: i16, b: i16, diff --git a/tests/codegen-llvm/bpf-abi/indirect-return.rs b/tests/codegen-llvm/bpf-abi/indirect-return.rs index c285bd9431c58..437f4ab0f3abc 100644 --- a/tests/codegen-llvm/bpf-abi/indirect-return.rs +++ b/tests/codegen-llvm/bpf-abi/indirect-return.rs @@ -11,6 +11,7 @@ extern crate minicore; +#[repr(C)] struct Big { a: [u16; 32], b: u64, diff --git a/tests/codegen-llvm/complex-abi.rs b/tests/codegen-llvm/complex-abi.rs index 4ba7ecad764f2..c900c3debd504 100644 --- a/tests/codegen-llvm/complex-abi.rs +++ b/tests/codegen-llvm/complex-abi.rs @@ -103,7 +103,8 @@ #![feature(no_core, lang_items, f16, f128)] #![no_core] -#![allow(improper_ctypes)] // only Complex<{float}> is guaranteed to be ABI-compatible for now +// only Complex<{float}> is guaranteed to be ABI-compatible for now +#![expect(improper_ctypes_definitions)] #![crate_type = "lib"] extern crate minicore; diff --git a/tests/codegen-llvm/regparm-inreg.rs b/tests/codegen-llvm/regparm-inreg.rs index 77d4c206071e7..bf6bc4dd7bf0e 100644 --- a/tests/codegen-llvm/regparm-inreg.rs +++ b/tests/codegen-llvm/regparm-inreg.rs @@ -52,14 +52,15 @@ pub mod tests { #[no_mangle] pub extern "thiscall" fn f6(_: i32, _: i32, _: i32) {} + #[repr(C)] struct S1 { x1: i32, } - // regparm0: @f7(i32 noundef %_1, i32 noundef %_2, i32 noundef %_3, i32 noundef %_4) - // regparm1: @f7(i32 inreg noundef %_1, i32 noundef %_2, i32 noundef %_3, i32 noundef %_4) - // regparm2: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 noundef %_3, i32 noundef %_4) - // regparm3: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, i32 inreg noundef %_3, - // regparm3-SAME: i32 noundef %_4) + // regparm0: @f7(i32 noundef %_1, i32 noundef %_2, ptr {{.*}} byval([4 x i8]) {{.*}} %_3, i32 noundef %_4) + // regparm1: @f7(i32 inreg noundef %_1, i32 noundef %_2, ptr {{.*}} byval([4 x i8]) {{.*}} %_3, i32 noundef %_4) + // regparm2: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, ptr {{.*}} byval([4 x i8]) {{.*}} %_3, i32 noundef %_4) + // regparm3: @f7(i32 inreg noundef %_1, i32 inreg noundef %_2, ptr {{.*}} byval([4 x i8]) {{.*}} %_3, + // regparm3-SAME: i32 inreg noundef %_4) #[no_mangle] pub extern "C" fn f7(_: i32, _: i32, _: S1, _: i32) {} diff --git a/tests/codegen-llvm/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs b/tests/codegen-llvm/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs index 0f5a449ead133..ae806aa64f513 100644 --- a/tests/codegen-llvm/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs +++ b/tests/codegen-llvm/riscv-abi/riscv64-lp64-lp64f-lp64d-abi.rs @@ -5,7 +5,7 @@ #![crate_type = "lib"] #![no_core] #![feature(no_core, lang_items)] -#![allow(improper_ctypes)] +#![deny(unfulfilled_lint_expectations, improper_ctypes_definitions)] extern crate minicore; use minicore::*; @@ -59,6 +59,7 @@ pub extern "C" fn f_fp_scalar_2(x: f64) -> f64 { pub struct Empty {} // CHECK: define void @f_agg_empty_struct() +#[expect(improper_ctypes_definitions)] #[no_mangle] pub extern "C" fn f_agg_empty_struct(e: Empty) -> Empty { e diff --git a/tests/codegen-llvm/scalable-vectors/memcpy.rs b/tests/codegen-llvm/scalable-vectors/memcpy.rs index 859f50b5b1178..30d4b0d17ebe1 100644 --- a/tests/codegen-llvm/scalable-vectors/memcpy.rs +++ b/tests/codegen-llvm/scalable-vectors/memcpy.rs @@ -5,12 +5,13 @@ #![crate_type = "lib"] #![feature(simd_ffi)] #![feature(stdarch_aarch64_sve)] +#![deny(unfulfilled_lint_expectations)] // Test that `vscale * size` is generated for `memcpy` of scalable vector types use std::arch::aarch64::*; -#[allow(improper_ctypes)] +#[expect(improper_ctypes)] unsafe extern "C" { fn svcreate2_s16_wrapper(__dst: *mut svint16x2_t, x0: *const svint16_t, x1: *const svint16_t); fn svcreate3_s16_wrapper( diff --git a/tests/ui/abi/abi-sysv64-arg-passing.rs b/tests/ui/abi/abi-sysv64-arg-passing.rs index 362a1862f9d4c..e21ca94aa6e8f 100644 --- a/tests/ui/abi/abi-sysv64-arg-passing.rs +++ b/tests/ui/abi/abi-sysv64-arg-passing.rs @@ -34,7 +34,6 @@ // the sysv64 ABI on Windows. #[allow(dead_code)] -#[allow(improper_ctypes)] #[cfg(target_arch = "x86_64")] mod tests { @@ -87,6 +86,7 @@ mod tests { #[derive(Copy, Clone)] pub struct Quad { a: u64, b: u64, c: u64, d: u64 } + #[repr(C)] #[derive(Copy, Clone)] pub struct QuadFloats { a: f32, b: f32, c: f32, d: f32 } @@ -113,6 +113,7 @@ mod tests { pub fn rust_dbg_extern_identity_u32(v: u32) -> u32; pub fn rust_dbg_extern_identity_u64(v: u64) -> u64; pub fn rust_dbg_extern_identity_double(v: f64) -> f64; + #[expect(improper_ctypes)] pub fn rust_dbg_extern_empty_struct(v1: ManyInts, e: Empty, v2: ManyInts); pub fn rust_dbg_extern_identity_TwoU8s(v: TwoU8s) -> TwoU8s; pub fn rust_dbg_extern_identity_TwoU16s(v: TwoU16s) -> TwoU16s; diff --git a/tests/ui/abi/abi-sysv64-register-usage.rs b/tests/ui/abi/abi-sysv64-register-usage.rs index cf1620db6f7be..576af8e696438 100644 --- a/tests/ui/abi/abi-sysv64-register-usage.rs +++ b/tests/ui/abi/abi-sysv64-register-usage.rs @@ -45,11 +45,11 @@ pub extern "sysv64" fn all_the_registers( // this struct contains 8 i64's, while only 6 can be passed in registers. #[cfg(target_arch = "x86_64")] #[derive(PartialEq, Eq, Debug)] +#[repr(C)] pub struct LargeStruct(i64, i64, i64, i64, i64, i64, i64, i64); #[cfg(target_arch = "x86_64")] #[inline(never)] -#[allow(improper_ctypes_definitions)] pub extern "sysv64" fn large_struct_by_val(mut foo: LargeStruct) -> LargeStruct { foo.0 *= 1; foo.1 *= 2; diff --git a/tests/ui/abi/arm-unadjusted-intrinsic.rs b/tests/ui/abi/arm-unadjusted-intrinsic.rs index f20fda4c61534..4340369d5ecc7 100644 --- a/tests/ui/abi/arm-unadjusted-intrinsic.rs +++ b/tests/ui/abi/arm-unadjusted-intrinsic.rs @@ -28,7 +28,7 @@ impl Copy for int8x16x4_t {} #[target_feature(enable = "neon")] #[cfg_attr(target_arch = "arm", target_feature(enable = "v7"))] pub unsafe fn vld1q_s8_x4(a: *const i8) -> int8x16x4_t { - #[allow(improper_ctypes)] + #[expect(improper_ctypes)] extern "llvm-intrinsic" { #[cfg_attr(target_arch = "arm", link_name = "llvm.arm.neon.vld1x4.v16i8.p0i8")] #[cfg_attr(target_arch = "aarch64", link_name = "llvm.aarch64.neon.ld1x4.v16i8.p0i8")] diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs index e2496726f4b3f..c0a124208b21e 100644 --- a/tests/ui/abi/compatibility.rs +++ b/tests/ui/abi/compatibility.rs @@ -89,7 +89,7 @@ #![feature(no_core, rustc_attrs, lang_items)] #![feature(unsized_fn_params, transparent_unions)] #![no_core] -#![allow(unused, improper_ctypes_definitions, internal_features)] +#![expect(unused, improper_ctypes_definitions, internal_features)] // FIXME: some targets are broken in various ways. // Hence there are `cfg` throughout this test to disable parts of it on those targets. diff --git a/tests/ui/abi/extern-c-two-doubles-x86_64-5754.rs b/tests/ui/abi/extern-c-two-doubles-x86_64-5754.rs index 7f44ef9c68535..5b278f2506a24 100644 --- a/tests/ui/abi/extern-c-two-doubles-x86_64-5754.rs +++ b/tests/ui/abi/extern-c-two-doubles-x86_64-5754.rs @@ -1,8 +1,8 @@ // https://github.com/rust-lang/rust/issues/5754 //@ build-pass #![allow(dead_code)] -#![allow(improper_ctypes)] +#[repr(C)] struct TwoDoubles { r: f64, i: f64 diff --git a/tests/ui/abi/extern/extern-c-method-return-struct.rs b/tests/ui/abi/extern/extern-c-method-return-struct.rs index 679f0b37758ab..08cfe495ba2a3 100644 --- a/tests/ui/abi/extern/extern-c-method-return-struct.rs +++ b/tests/ui/abi/extern/extern-c-method-return-struct.rs @@ -2,13 +2,14 @@ //@ build-pass #![allow(dead_code)] + +#[repr(C)] pub struct Foo { x: isize, y: isize } impl Foo { - #[allow(improper_ctypes_definitions)] pub extern "C" fn foo_new() -> Foo { Foo { x: 21, y: 33 } } diff --git a/tests/ui/abi/extern/extern-pass-FiveU16s.rs b/tests/ui/abi/extern/extern-pass-FiveU16s.rs index 5f1307beb28e6..48edb8d4a5a92 100644 --- a/tests/ui/abi/extern/extern-pass-FiveU16s.rs +++ b/tests/ui/abi/extern/extern-pass-FiveU16s.rs @@ -1,5 +1,4 @@ //@ run-pass -#![allow(improper_ctypes)] // Test a foreign function that accepts and returns a struct by value. @@ -8,6 +7,7 @@ // sizes, causing there to be padding in the last element. #[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct FiveU16s { one: u16, two: u16, diff --git a/tests/ui/abi/extern/extern-pass-TwoU16s.rs b/tests/ui/abi/extern/extern-pass-TwoU16s.rs index 8bde553050a40..47dd0674ae439 100644 --- a/tests/ui/abi/extern/extern-pass-TwoU16s.rs +++ b/tests/ui/abi/extern/extern-pass-TwoU16s.rs @@ -1,10 +1,10 @@ //@ run-pass -#![allow(improper_ctypes)] // Test a foreign function that accepts and returns a struct // by value. #[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct TwoU16s { one: u16, two: u16, diff --git a/tests/ui/abi/extern/extern-pass-TwoU32s.rs b/tests/ui/abi/extern/extern-pass-TwoU32s.rs index fc90eb6945c7e..f7d9459e8f82f 100644 --- a/tests/ui/abi/extern/extern-pass-TwoU32s.rs +++ b/tests/ui/abi/extern/extern-pass-TwoU32s.rs @@ -1,10 +1,10 @@ //@ run-pass -#![allow(improper_ctypes)] // Test a foreign function that accepts and returns a struct // by value. #[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct TwoU32s { one: u32, two: u32, diff --git a/tests/ui/abi/extern/extern-pass-TwoU64s.rs b/tests/ui/abi/extern/extern-pass-TwoU64s.rs index 603de2e49ab2d..dbce8690d78cd 100644 --- a/tests/ui/abi/extern/extern-pass-TwoU64s.rs +++ b/tests/ui/abi/extern/extern-pass-TwoU64s.rs @@ -1,10 +1,10 @@ //@ run-pass -#![allow(improper_ctypes)] // Test a foreign function that accepts and returns a struct // by value. #[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct TwoU64s { one: u64, two: u64, diff --git a/tests/ui/abi/extern/extern-pass-TwoU8s.rs b/tests/ui/abi/extern/extern-pass-TwoU8s.rs index a712d79a98dd2..56db34dcefea7 100644 --- a/tests/ui/abi/extern/extern-pass-TwoU8s.rs +++ b/tests/ui/abi/extern/extern-pass-TwoU8s.rs @@ -1,10 +1,10 @@ //@ run-pass -#![allow(improper_ctypes)] // Test a foreign function that accepts and returns a struct // by value. #[derive(Copy, Clone, PartialEq, Debug)] +#[repr(C)] pub struct TwoU8s { one: u8, two: u8, diff --git a/tests/ui/abi/extern/extern-pass-empty.rs b/tests/ui/abi/extern/extern-pass-empty.rs index 1ad52b128ad93..707c1944cdd63 100644 --- a/tests/ui/abi/extern/extern-pass-empty.rs +++ b/tests/ui/abi/extern/extern-pass-empty.rs @@ -1,5 +1,5 @@ //@ run-pass -#![allow(improper_ctypes)] // FIXME: this test is inherently not FFI-safe. +#![expect(improper_ctypes)] // FIXME: this test is inherently not FFI-safe. // Test a foreign function that accepts empty struct. diff --git a/tests/ui/abi/extern/extern-return-FiveU16s.rs b/tests/ui/abi/extern/extern-return-FiveU16s.rs index d8ae8b2661c5a..d0566de1e6975 100644 --- a/tests/ui/abi/extern/extern-return-FiveU16s.rs +++ b/tests/ui/abi/extern/extern-return-FiveU16s.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(improper_ctypes)] +#[repr(C)] pub struct FiveU16s { one: u16, two: u16, diff --git a/tests/ui/abi/extern/extern-return-TwoU16s.rs b/tests/ui/abi/extern/extern-return-TwoU16s.rs index bf909a8db24c7..601daf35b4ea9 100644 --- a/tests/ui/abi/extern/extern-return-TwoU16s.rs +++ b/tests/ui/abi/extern/extern-return-TwoU16s.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(improper_ctypes)] +#[repr(C)] pub struct TwoU16s { one: u16, two: u16, diff --git a/tests/ui/abi/extern/extern-return-TwoU32s.rs b/tests/ui/abi/extern/extern-return-TwoU32s.rs index c528da8cfc464..9f81286009959 100644 --- a/tests/ui/abi/extern/extern-return-TwoU32s.rs +++ b/tests/ui/abi/extern/extern-return-TwoU32s.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(improper_ctypes)] +#[repr(C)] pub struct TwoU32s { one: u32, two: u32, diff --git a/tests/ui/abi/extern/extern-return-TwoU64s.rs b/tests/ui/abi/extern/extern-return-TwoU64s.rs index d4f9540ec7b35..a7dd142ffbc0d 100644 --- a/tests/ui/abi/extern/extern-return-TwoU64s.rs +++ b/tests/ui/abi/extern/extern-return-TwoU64s.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(improper_ctypes)] +#[repr(C)] pub struct TwoU64s { one: u64, two: u64, diff --git a/tests/ui/abi/extern/extern-return-TwoU8s.rs b/tests/ui/abi/extern/extern-return-TwoU8s.rs index 228b27396249b..5f2d0418fd166 100644 --- a/tests/ui/abi/extern/extern-return-TwoU8s.rs +++ b/tests/ui/abi/extern/extern-return-TwoU8s.rs @@ -1,6 +1,6 @@ //@ run-pass -#![allow(improper_ctypes)] +#[repr(C)] pub struct TwoU8s { one: u8, two: u8, diff --git a/tests/ui/abi/foreign/foreign-fn-with-byval.rs b/tests/ui/abi/foreign/foreign-fn-with-byval.rs index 9908ec2d2c01a..d5f87c1a804b5 100644 --- a/tests/ui/abi/foreign/foreign-fn-with-byval.rs +++ b/tests/ui/abi/foreign/foreign-fn-with-byval.rs @@ -1,7 +1,7 @@ //@ run-pass -#![allow(improper_ctypes, improper_ctypes_definitions)] #[derive(Copy, Clone)] +#[repr(C)] pub struct S { x: u64, y: u64, diff --git a/tests/ui/abi/issue-28676.rs b/tests/ui/abi/issue-28676.rs index 2abb4ce52b3b3..616ed6bde24b1 100644 --- a/tests/ui/abi/issue-28676.rs +++ b/tests/ui/abi/issue-28676.rs @@ -2,9 +2,9 @@ //@ ignore-backends: gcc #![allow(dead_code)] -#![allow(improper_ctypes)] #[derive(Copy, Clone)] +#[repr(C)] pub struct Quad { a: u64, b: u64, diff --git a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs index 314db42280d99..578381dcd32d1 100644 --- a/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs +++ b/tests/ui/abi/issues/issue-62350-sysv-neg-reg-counts.rs @@ -1,8 +1,8 @@ //@ run-pass #![allow(dead_code)] -#![allow(improper_ctypes)] #[derive(Copy, Clone)] +#[repr(C)] pub struct QuadFloats { a: f32, b: f32, diff --git a/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs index f694205174889..fa8ac0bfe594a 100644 --- a/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs +++ b/tests/ui/abi/issues/issue-97463-broken-abi-leaked-uninit-data.rs @@ -1,6 +1,4 @@ //@ run-pass -#![allow(dead_code)] -#![allow(improper_ctypes)] #[link(name = "rust_test_helpers", kind = "static")] extern "C" { diff --git a/tests/ui/abi/large-byval-align.rs b/tests/ui/abi/large-byval-align.rs index 69418e1cbc7b8..7e640fb42a3cb 100644 --- a/tests/ui/abi/large-byval-align.rs +++ b/tests/ui/abi/large-byval-align.rs @@ -3,10 +3,9 @@ //@ build-pass //@ ignore-backends: gcc -#[repr(align(536870912))] +#[repr(C, align(536870912))] pub struct A(i64); -#[allow(improper_ctypes_definitions)] pub extern "C" fn foo(x: A) {} fn main() { diff --git a/tests/ui/abi/non-rustic-unsized.rs b/tests/ui/abi/non-rustic-unsized.rs index d26c4af72ccaf..fa22f91afeb67 100644 --- a/tests/ui/abi/non-rustic-unsized.rs +++ b/tests/ui/abi/non-rustic-unsized.rs @@ -3,7 +3,7 @@ #![no_core] #![crate_type = "lib"] #![feature(no_core, unsized_fn_params)] -#![allow(improper_ctypes_definitions, improper_ctypes)] +#![expect(improper_ctypes_definitions, improper_ctypes)] extern crate minicore; use minicore::*; diff --git a/tests/ui/abi/simd-abi-checks-avx.rs b/tests/ui/abi/simd-abi-checks-avx.rs index 7432381d15b72..e47346d02ea59 100644 --- a/tests/ui/abi/simd-abi-checks-avx.rs +++ b/tests/ui/abi/simd-abi-checks-avx.rs @@ -4,7 +4,7 @@ #![feature(portable_simd)] #![feature(simd_ffi)] -#![allow(improper_ctypes_definitions)] +#![expect(improper_ctypes_definitions)] use std::arch::x86_64::*; diff --git a/tests/ui/abi/simd-abi-checks-s390x.rs b/tests/ui/abi/simd-abi-checks-s390x.rs index 8ca3d2f457899..95028b8286d55 100644 --- a/tests/ui/abi/simd-abi-checks-s390x.rs +++ b/tests/ui/abi/simd-abi-checks-s390x.rs @@ -15,7 +15,7 @@ #![feature(no_core)] #![no_core] #![crate_type = "lib"] -#![allow(non_camel_case_types, improper_ctypes_definitions)] +#![expect(improper_ctypes_definitions)] extern crate minicore; use minicore::simd::*; diff --git a/tests/ui/abi/simd-abi-checks-sse.rs b/tests/ui/abi/simd-abi-checks-sse.rs index 906b6ec65610e..4ed4b78166f9e 100644 --- a/tests/ui/abi/simd-abi-checks-sse.rs +++ b/tests/ui/abi/simd-abi-checks-sse.rs @@ -9,7 +9,7 @@ //@ dont-require-annotations: NOTE #![feature(no_core)] #![no_core] -#![allow(improper_ctypes_definitions)] +#![expect(improper_ctypes_definitions)] extern crate minicore; use minicore::simd::Simd; diff --git a/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs index 7d21307e1b2d9..f0f6bb3f765b2 100644 --- a/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs +++ b/tests/ui/abi/unsized-args-in-c-abi-issues-94223-115845.rs @@ -1,5 +1,5 @@ //@ check-pass -#![allow(improper_ctypes_definitions)] +#![expect(improper_ctypes_definitions)] #![feature(unsized_fn_params)] #![crate_type = "lib"] diff --git a/tests/ui/ffi/ffi-struct-size-alignment.rs b/tests/ui/ffi/ffi-struct-size-alignment.rs index 287ae7cad2b6d..00f25f0673c5c 100644 --- a/tests/ui/ffi/ffi-struct-size-alignment.rs +++ b/tests/ui/ffi/ffi-struct-size-alignment.rs @@ -1,12 +1,12 @@ //@ run-pass #![allow(dead_code)] -#![allow(improper_ctypes)] // Issue #3656 // Incorrect struct size computation in the FFI, because of not taking // the alignment of elements into account. use std::ffi::{c_uint, c_void}; +#[repr(C)] pub struct KEYGEN { hash_algorithm: [c_uint; 2], count: u32, From c39609dcb269b8fb50065c512bf577beca5601ea Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 18 Sep 2026 15:39:21 +0200 Subject: [PATCH 0338/1309] Revert "./miri toolchain: no need to run 'cargo metadata'" This reverts commit 8c704e3becec2da6d439c439f5a86a48c2e29427. --- src/tools/miri/miri-script/src/commands.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index e8fdcd80f8ddb..3f2c1c5f4f2e6 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -162,6 +162,11 @@ impl Command { cmd!(sh, "rustup override set miri").run()?; // Cleanup. cmd!(sh, "cargo clean").run()?; + // Call `cargo metadata` on the sources in case that changes the lockfile + // (which fails under some setups when it is done from inside vscode). + let sysroot = cmd!(sh, "rustc --print sysroot").read()?; + let sysroot = sysroot.trim(); + cmd!(sh, "cargo metadata --format-version 1 --manifest-path {sysroot}/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml").ignore_stdout().run()?; Ok(()) } From 0d17901218c1e42d145e564ef70cc45f232b4a64 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 18 Sep 2026 15:40:40 +0200 Subject: [PATCH 0339/1309] add issue reference for work-around --- src/tools/miri/miri-script/src/commands.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs index 3f2c1c5f4f2e6..e9b9273611510 100644 --- a/src/tools/miri/miri-script/src/commands.rs +++ b/src/tools/miri/miri-script/src/commands.rs @@ -163,7 +163,7 @@ impl Command { // Cleanup. cmd!(sh, "cargo clean").run()?; // Call `cargo metadata` on the sources in case that changes the lockfile - // (which fails under some setups when it is done from inside vscode). + // (works around ). let sysroot = cmd!(sh, "rustc --print sysroot").read()?; let sysroot = sysroot.trim(); cmd!(sh, "cargo metadata --format-version 1 --manifest-path {sysroot}/lib/rustlib/rustc-src/rust/compiler/rustc/Cargo.toml").ignore_stdout().run()?; From 9e0ad85cccfe49049a11e083dd98cbaa864cb252 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Sep 2026 09:44:25 -0400 Subject: [PATCH 0340/1309] Update to nightly-2026-09-18 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 4e47a84698e7c..0c81f7c7c7398 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-14" +channel = "nightly-2026-09-18" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 5cc5408cc36537003444de501f8d6274480db93e Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Sep 2026 09:44:30 -0400 Subject: [PATCH 0341/1309] Fix compilation --- src/gcc_util.rs | 2 +- src/intrinsic/simd.rs | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 32467286edb33..7112e9b5e74e9 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -7,7 +7,7 @@ use gccjit::Context; use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; -use rustc_session::EarlySession; +use rustc_session::{EarlySession, Session}; use rustc_session::config::NATIVE_CPU; use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector, Target}; diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 02f1f7efd9c1e..bb32a85f193ea 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -15,10 +15,9 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, LayoutTy #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::span_bug; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; -use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, span_bug, sym}; use crate::builder::Builder; #[cfg(not(feature = "master"))] From 461b54148c06d538992dd824e5cc4737e65ad2a6 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Sep 2026 09:44:46 -0400 Subject: [PATCH 0342/1309] Fix formatting --- src/gcc_util.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 7112e9b5e74e9..0628171e488b3 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -7,8 +7,8 @@ use gccjit::Context; use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; -use rustc_session::{EarlySession, Session}; use rustc_session::config::NATIVE_CPU; +use rustc_session::{EarlySession, Session}; use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector, Target}; fn gcc_features_by_flags(sess: &EarlySession, features: &mut Vec) { From addf907be33eb8adb9d15ff85d074b978d66f01f Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Fri, 18 Sep 2026 10:16:07 -0400 Subject: [PATCH 0343/1309] Add failing ICE tests --- tests/failing-ice-tests.txt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tests/failing-ice-tests.txt b/tests/failing-ice-tests.txt index ca685eb2af71c..f9d6f99e7b42b 100644 --- a/tests/failing-ice-tests.txt +++ b/tests/failing-ice-tests.txt @@ -41,3 +41,7 @@ tests/ui/codegen/incorrect-arch-intrinsic.rs tests/ui/codegen/custom-target-invalid-llvm-target.rs tests/ui/asm/x86_64/naked_asm_escape.rs tests/ui/lto/debuginfo-lto-alloc.rs +tests/ui/codegen/normalization-overflow/recursion-issue-118590.rs +tests/ui/codegen/normalization-overflow/recursion-issue-122823.rs +tests/ui/codegen/normalization-overflow/recursion-issue-131342.rs +tests/ui/codegen/normalization-overflow/recursion-issue-92004.rs From e7d3a6a9e68afaba5ea299e301c8e57be7626cd6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Sep 2026 14:11:22 +0200 Subject: [PATCH 0344/1309] Move parse error recovery from some invalid expr ops out of line --- compiler/rustc_parse/src/diagnostics.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 388 ++++++++---------- .../src/parser/expr/diagnostics.rs | 80 ++++ 3 files changed, 262 insertions(+), 210 deletions(-) create mode 100644 compiler/rustc_parse/src/parser/expr/diagnostics.rs diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 829fc5a600e8a..78240b0ee891b 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -797,7 +797,7 @@ pub(crate) struct EqFieldInit { #[derive(Diagnostic)] #[diag("unexpected token: `...`")] -pub(crate) struct DotDotDot { +pub(crate) struct DotDotDotExprOp { #[primary_span] #[suggestion( "use `..` for an exclusive range", @@ -816,7 +816,7 @@ pub(crate) struct DotDotDot { #[derive(Diagnostic)] #[diag("unexpected token: `<-`")] -pub(crate) struct LeftArrowOperator { +pub(crate) struct LArrowExprOp { #[primary_span] #[suggestion( "if you meant to write a comparison against a negative value, add a space in between `<` and `-`", diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 8238a6518e41d..a7bcb93d5b084 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -34,8 +34,9 @@ use super::{ AttrWrapper, BlockMode, ClosureSpans, ExpTokenPair, ForceCollect, Parser, PathStyle, Restrictions, SemiColonMode, SeqSep, TokenType, Trailing, UsePreAttrPos, }; -use crate::diagnostics::ExprParenthesesNeeded; -use crate::{diagnostics, exp, maybe_recover_from_interpolated_ty_qpath}; +use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; + +mod diagnostics; #[derive(Debug)] pub(super) enum DestructuredFloat { @@ -165,74 +166,22 @@ impl<'a> Parser<'a> { } { break; } - // Check for deprecated `...` syntax - if self.token == token::DotDotDot && op.node == AssocOp::Range(RangeLimits::Closed) { - self.err_dotdotdot_syntax(self.token.span); - } - if self.token == token::LArrow { - self.err_larrow_operator(self.token.span); - } + self.reject_dotdotdot_expr_op(); + self.reject_larrow_expr_op(); parsed_something = true; self.bump(); - if op.node.is_comparison() { - if let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { - return Ok((expr, parsed_something)); - } - } - // Look for JS' `===` and `!==` and recover - if let AssocOp::Binary(bop @ BinOpKind::Eq | bop @ BinOpKind::Ne) = op.node - && self.token == token::Eq - && self.prev_token.span.hi() == self.token.span.lo() + if op.node.is_comparison() + && let Some(expr) = self.check_no_chained_comparison(&lhs, &op)? { - let sp = op.span.to(self.token.span); - let sugg = bop.as_str().into(); - let invalid = format!("{sugg}="); - self.dcx().emit_err(diagnostics::InvalidComparisonOperator { - span: sp, - invalid: invalid.clone(), - sub: diagnostics::InvalidComparisonOperatorSub::Correctable { - span: sp, - invalid, - correct: sugg, - }, - }); - self.bump(); + return Ok((expr, parsed_something)); } - // Look for PHP's `<>` and recover - if op.node == AssocOp::Binary(BinOpKind::Lt) - && self.token == token::Gt - && self.prev_token.span.hi() == self.token.span.lo() - { - let sp = op.span.to(self.token.span); - self.dcx().emit_err(diagnostics::InvalidComparisonOperator { - span: sp, - invalid: "<>".into(), - sub: diagnostics::InvalidComparisonOperatorSub::Correctable { - span: sp, - invalid: "<>".into(), - correct: "!=".into(), - }, - }); - self.bump(); - } - - // Look for C++'s `<=>` and recover - if op.node == AssocOp::Binary(BinOpKind::Le) - && self.token == token::Gt - && self.prev_token.span.hi() == self.token.span.lo() - { - let sp = op.span.to(self.token.span); - self.dcx().emit_err(diagnostics::InvalidComparisonOperator { - span: sp, - invalid: "<=>".into(), - sub: diagnostics::InvalidComparisonOperatorSub::Spaceship(sp), - }); - self.bump(); - } + self.recover_from_strict_eq_op(op); + self.recover_from_diamond_ne_op(op); + self.recover_from_spaceship_cmp_op(op); if self.prev_token == token::Plus && self.token == token::Plus @@ -337,10 +286,10 @@ impl<'a> Parser<'a> { /// but the next token implies this should be parsed as an expression. /// For example: `if let Some(x) = x { x } else { 0 } / 2`. fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { - self.dcx().emit_err(diagnostics::FoundExprWouldBeStmt { + self.dcx().emit_err(crate::diagnostics::FoundExprWouldBeStmt { span: self.token.span, token: pprust::token_to_string(&self.token), - suggestion: ExprParenthesesNeeded::surrounding(lhs.span), + suggestion: crate::diagnostics::ExprParenthesesNeeded::surrounding(lhs.span), }); } @@ -377,18 +326,22 @@ impl<'a> Parser<'a> { (None, Some((Ident { name: sym::and, span }, IdentIsRaw::No))) if self.may_recover() => { - self.dcx().emit_err(diagnostics::InvalidLogicalOperator { + self.dcx().emit_err(crate::diagnostics::InvalidLogicalOperator { span: self.token.span, incorrect: "and".into(), - sub: diagnostics::InvalidLogicalOperatorSub::Conjunction(self.token.span), + sub: crate::diagnostics::InvalidLogicalOperatorSub::Conjunction( + self.token.span, + ), }); (AssocOp::Binary(BinOpKind::And), span) } (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => { - self.dcx().emit_err(diagnostics::InvalidLogicalOperator { + self.dcx().emit_err(crate::diagnostics::InvalidLogicalOperator { span: self.token.span, incorrect: "or".into(), - sub: diagnostics::InvalidLogicalOperatorSub::Disjunction(self.token.span), + sub: crate::diagnostics::InvalidLogicalOperatorSub::Disjunction( + self.token.span, + ), }); (AssocOp::Binary(BinOpKind::Or), span) } @@ -441,14 +394,11 @@ impl<'a> Parser<'a> { /// Parses prefix-forms of range notation: `..expr`, `..`, `..=expr`. fn parse_expr_prefix_range(&mut self, attrs: AttrWrapper) -> PResult<'a, Box> { if !attrs.is_empty() { - let err = diagnostics::DotDotRangeAttribute { span: self.token.span }; + let err = crate::diagnostics::DotDotRangeAttribute { span: self.token.span }; self.dcx().emit_err(err); } - // Check for deprecated `...` syntax. - if self.token == token::DotDotDot { - self.err_dotdotdot_syntax(self.token.span); - } + self.reject_dotdotdot_expr_op(); debug_assert!( self.token.is_range_separator(), @@ -513,7 +463,7 @@ impl<'a> Parser<'a> { } // `+lit` token::Plus if this.look_ahead(1, |tok| tok.is_numeric_lit()) => { - let mut err = diagnostics::LeadingPlusNotSupported { + let mut err = crate::diagnostics::LeadingPlusNotSupported { span: lo, remove_plus: None, add_parentheses: None, @@ -521,7 +471,8 @@ impl<'a> Parser<'a> { // a block on the LHS might have been intended to be an expression instead if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { - err.add_parentheses = Some(ExprParenthesesNeeded::surrounding(*sp)); + err.add_parentheses = + Some(crate::diagnostics::ExprParenthesesNeeded::surrounding(*sp)); } else { err.remove_plus = Some(lo); } @@ -574,7 +525,7 @@ impl<'a> Parser<'a> { /// Recover on `~expr` in favor of `!expr`. fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> { - self.dcx().emit_err(diagnostics::TildeAsUnaryOperator(lo)); + self.dcx().emit_err(crate::diagnostics::TildeAsUnaryOperator(lo)); self.parse_expr_unary(lo, UnOp::Not) } @@ -605,14 +556,14 @@ impl<'a> Parser<'a> { let negated_token = self.look_ahead(1, |t| *t); let sub_diag = if negated_token.is_numeric_lit() { - diagnostics::NotAsNegationOperatorSub::SuggestNotBitwise + crate::diagnostics::NotAsNegationOperatorSub::SuggestNotBitwise } else if negated_token.is_bool_lit() { - diagnostics::NotAsNegationOperatorSub::SuggestNotLogical + crate::diagnostics::NotAsNegationOperatorSub::SuggestNotLogical } else { - diagnostics::NotAsNegationOperatorSub::SuggestNotDefault + crate::diagnostics::NotAsNegationOperatorSub::SuggestNotDefault }; - self.dcx().emit_err(diagnostics::NotAsNegationOperator { + self.dcx().emit_err(crate::diagnostics::NotAsNegationOperator { negated: negated_token.span, negated_desc: super::token_descr(&negated_token), // Span the `not` plus trailing whitespace to avoid @@ -683,7 +634,7 @@ impl<'a> Parser<'a> { match self.parse_expr_labeled(label, false) { Ok(expr) => { type_err.cancel(); - self.dcx().emit_err(diagnostics::MalformedLoopLabel { + self.dcx().emit_err(crate::diagnostics::MalformedLoopLabel { span: label.ident.span, suggestion: label.ident.span.shrink_to_lo(), }); @@ -709,23 +660,24 @@ impl<'a> Parser<'a> { let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); match self.token.kind { - token::Lt => { - self.dcx().emit_err(diagnostics::ComparisonInterpretedAsGeneric { + token::Lt => self.dcx().emit_err( + crate::diagnostics::ComparisonInterpretedAsGeneric { comparison: self.token.span, r#type: pprust::path_to_string(&path), args: args_span, - suggestion: diagnostics::ComparisonInterpretedAsGenericSugg { - left: expr.span.shrink_to_lo(), - right: expr.span.shrink_to_hi(), - }, - }) - } + suggestion: + crate::diagnostics::ComparisonInterpretedAsGenericSugg { + left: expr.span.shrink_to_lo(), + right: expr.span.shrink_to_hi(), + }, + }, + ), token::Shl => { - self.dcx().emit_err(diagnostics::ShiftInterpretedAsGeneric { + self.dcx().emit_err(crate::diagnostics::ShiftInterpretedAsGeneric { shift: self.token.span, r#type: pprust::path_to_string(&path), args: args_span, - suggestion: diagnostics::ShiftInterpretedAsGenericSugg { + suggestion: crate::diagnostics::ShiftInterpretedAsGenericSugg { left: expr.span.shrink_to_lo(), right: expr.span.shrink_to_hi(), }, @@ -835,8 +787,10 @@ impl<'a> Parser<'a> { } fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) { - self.dcx() - .emit_err(diagnostics::LifetimeInBorrowExpression { span, lifetime_span: lt_span }); + self.dcx().emit_err(crate::diagnostics::LifetimeInBorrowExpression { + span, + lifetime_span: lt_span, + }); } /// Parse `mut?` or `[ raw | pin ] [ const | mut ]`. @@ -895,7 +849,7 @@ impl<'a> Parser<'a> { // Recovery for `expr->suffix`. self.bump(); let span = self.prev_token.span; - self.dcx().emit_err(diagnostics::ExprRArrowCall { span }); + self.dcx().emit_err(crate::diagnostics::ExprRArrowCall { span }); true } else { self.eat(exp!(Dot)) @@ -1018,7 +972,7 @@ impl<'a> Parser<'a> { } _ => (span, actual), }; - self.dcx().emit_err(diagnostics::UnexpectedTokenAfterDot { span, actual }); + self.dcx().emit_err(crate::diagnostics::UnexpectedTokenAfterDot { span, actual }); } /// We need an identifier or integer, but the next token is a float. @@ -1135,7 +1089,7 @@ impl<'a> Parser<'a> { // Parse this both to give helpful error messages and to // verify it can be done with this parser setup. ExprKind::Index(ref left, ref _right, span) => { - self.dcx().emit_err(diagnostics::ArrayIndexInOffsetOf(span)); + self.dcx().emit_err(crate::diagnostics::ArrayIndexInOffsetOf(span)); current = left; } ExprKind::Lit(token::Lit { @@ -1144,10 +1098,12 @@ impl<'a> Parser<'a> { suffix, }) => { if let Some(suffix) = suffix { - self.dcx().emit_err(diagnostics::InvalidLiteralSuffixOnTupleIndex { - span: current.span, - suffix, - }); + self.dcx().emit_err( + crate::diagnostics::InvalidLiteralSuffixOnTupleIndex { + span: current.span, + suffix, + }, + ); } match self.break_up_float(symbol, current.span) { // 1e2 @@ -1187,14 +1143,15 @@ impl<'a> Parser<'a> { fields.insert(start_idx, *ident) } _ => { - self.dcx().emit_err(diagnostics::InvalidOffsetOf(current.span)); + self.dcx() + .emit_err(crate::diagnostics::InvalidOffsetOf(current.span)); break; } } break; } _ => { - self.dcx().emit_err(diagnostics::InvalidOffsetOf(current.span)); + self.dcx().emit_err(crate::diagnostics::InvalidOffsetOf(current.span)); break; } } @@ -1204,12 +1161,12 @@ impl<'a> Parser<'a> { break; } else if trailing_dot.is_none() { // This loop should only repeat if there is a trailing dot. - self.dcx().emit_err(diagnostics::InvalidOffsetOf(self.token.span)); + self.dcx().emit_err(crate::diagnostics::InvalidOffsetOf(self.token.span)); break; } } if let Some(dot) = trailing_dot { - self.dcx().emit_err(diagnostics::InvalidOffsetOf(dot)); + self.dcx().emit_err(crate::diagnostics::InvalidOffsetOf(dot)); } Ok(fields.into_iter().collect()) } @@ -1223,7 +1180,7 @@ impl<'a> Parser<'a> { suffix: Option, ) -> Box { if let Some(suffix) = suffix { - self.dcx().emit_err(diagnostics::InvalidLiteralSuffixOnTupleIndex { + self.dcx().emit_err(crate::diagnostics::InvalidLiteralSuffixOnTupleIndex { span: ident_span, suffix, }); @@ -1310,14 +1267,14 @@ impl<'a> Parser<'a> { err.cancel(); let type_str = pprust::path_to_string(&path); self.dcx() - .create_err(diagnostics::ParenthesesWithStructFields { + .create_err(crate::diagnostics::ParenthesesWithStructFields { span, - braces_for_struct: diagnostics::BracesForStructLiteral { + braces_for_struct: crate::diagnostics::BracesForStructLiteral { first: open_paren, second: close_paren, r#type: type_str.clone(), }, - no_fields_for_fn: diagnostics::NoFieldsForFnCall { + no_fields_for_fn: crate::diagnostics::NoFieldsForFnCall { r#type: type_str, fields: fields .into_iter() @@ -1419,7 +1376,7 @@ impl<'a> Parser<'a> { if let Some(args) = seg.args { // See `StashKey::GenericInFieldExpr` for more info on why we stash this. self.dcx() - .create_err(diagnostics::FieldExpressionWithGeneric(args.span())) + .create_err(crate::diagnostics::FieldExpressionWithGeneric(args.span())) .stash(seg.ident.span, StashKey::GenericInFieldExpr); } @@ -1491,7 +1448,9 @@ impl<'a> Parser<'a> { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { - err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); + err.subdiagnostic(crate::diagnostics::ExprParenthesesNeeded::surrounding( + *sp, + )); } err }) @@ -1689,7 +1648,8 @@ impl<'a> Parser<'a> { let (span, kind) = if self.eat(exp!(Bang)) { // MACRO INVOCATION expression if qself.is_some() { - self.dcx().emit_err(diagnostics::MacroInvocationWithQualifiedPath(path.span)); + self.dcx() + .emit_err(crate::diagnostics::MacroInvocationWithQualifiedPath(path.span)); } let lo = path.span; let mac = Box::new(MacCall { path, args: self.parse_delim_args()? }); @@ -1734,7 +1694,7 @@ impl<'a> Parser<'a> { { let (lit, _) = self.recover_unclosed_char(label_.ident, Parser::mk_token_lit_char, |self_| { - self_.dcx().create_err(diagnostics::UnexpectedTokenAfterLabel { + self_.dcx().create_err(crate::diagnostics::UnexpectedTokenAfterLabel { span: self_.token.span, remove_label: None, enclose_in_block: None, @@ -1746,7 +1706,7 @@ impl<'a> Parser<'a> { && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt)) { // We're probably inside of a `Path<'a>` that needs a turbofish - let guar = self.dcx().emit_err(diagnostics::UnexpectedTokenAfterLabel { + let guar = self.dcx().emit_err(crate::diagnostics::UnexpectedTokenAfterLabel { span: self.token.span, remove_label: None, enclose_in_block: None, @@ -1754,7 +1714,7 @@ impl<'a> Parser<'a> { consume_colon = false; Ok(self.mk_expr_err(lo, guar)) } else { - let mut err = diagnostics::UnexpectedTokenAfterLabel { + let mut err = crate::diagnostics::UnexpectedTokenAfterLabel { span: self.token.span, remove_label: None, enclose_in_block: None, @@ -1791,7 +1751,7 @@ impl<'a> Parser<'a> { return expr; } - err.enclose_in_block = Some(diagnostics::UnexpectedTokenAfterLabelSugg { + err.enclose_in_block = Some(crate::diagnostics::UnexpectedTokenAfterLabelSugg { left: span.shrink_to_lo(), right: span.shrink_to_hi(), }); @@ -1807,7 +1767,7 @@ impl<'a> Parser<'a> { }?; if !ate_colon && consume_colon { - self.dcx().emit_err(diagnostics::RequireColonAfterLabeledExpression { + self.dcx().emit_err(crate::diagnostics::RequireColonAfterLabeledExpression { span: expr.span, label: lo, label_end: lo.between(tok_sp), @@ -1856,7 +1816,7 @@ impl<'a> Parser<'a> { self.bump(); // `catch` let span = lo.to(self.prev_token.span); - self.dcx().emit_err(diagnostics::DoCatchSyntaxRemoved { span }); + self.dcx().emit_err(crate::diagnostics::DoCatchSyntaxRemoved { span }); self.parse_try_block(lo) } @@ -1916,9 +1876,9 @@ impl<'a> Parser<'a> { // The value expression can be a labeled loop, see issue #86948, e.g.: // `loop { break 'label: loop { break 'label 42; }; }` let lexpr = self.parse_expr_labeled(label, true)?; - self.dcx().emit_err(diagnostics::LabeledLoopInBreak { + self.dcx().emit_err(crate::diagnostics::LabeledLoopInBreak { span: lexpr.span, - sub: diagnostics::WrapInParentheses::Expression { + sub: crate::diagnostics::WrapInParentheses::Expression { left: lexpr.span.shrink_to_lo(), right: lexpr.span.shrink_to_hi(), }, @@ -1945,8 +1905,8 @@ impl<'a> Parser<'a> { BREAK_WITH_LABEL_AND_LOOP, lo.to(expr.span), ast::CRATE_NODE_ID, - diagnostics::BreakWithLabelAndLoop { - sub: diagnostics::BreakWithLabelAndLoopSub { + crate::diagnostics::BreakWithLabelAndLoop { + sub: crate::diagnostics::BreakWithLabelAndLoopSub { left: span.shrink_to_lo(), right: span.shrink_to_hi(), }, @@ -2028,8 +1988,9 @@ impl<'a> Parser<'a> { self.bump(); // `#` let Some((ident, IdentIsRaw::No)) = self.token.ident() else { - let err = - self.dcx().create_err(diagnostics::ExpectedBuiltinIdent { span: self.token.span }); + let err = self + .dcx() + .create_err(crate::diagnostics::ExpectedBuiltinIdent { span: self.token.span }); return Err(err); }; self.psess.gated_spans.gate(sym::builtin_syntax, ident.span); @@ -2039,7 +2000,7 @@ impl<'a> Parser<'a> { let ret = if let Some(res) = parse(self, lo, ident)? { Ok(res) } else { - let err = self.dcx().create_err(diagnostics::UnknownBuiltinConstruct { + let err = self.dcx().create_err(crate::diagnostics::UnknownBuiltinConstruct { span: lo.to(ident.span), name: ident, }); @@ -2188,7 +2149,7 @@ impl<'a> Parser<'a> { } }); if let Some(recovered) = recovered { - self.dcx().emit_err(diagnostics::FloatLiteralRequiresIntegerPart { + self.dcx().emit_err(crate::diagnostics::FloatLiteralRequiresIntegerPart { span: recovered.span, suggestion: recovered.span.shrink_to_lo(), }); @@ -2322,9 +2283,9 @@ impl<'a> Parser<'a> { let mut snapshot = self.create_snapshot_for_diagnostic(); match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { Ok(arr) => { - let guar = self.dcx().emit_err(diagnostics::ArrayBracketsInsteadOfBraces { + let guar = self.dcx().emit_err(crate::diagnostics::ArrayBracketsInsteadOfBraces { span: arr.span, - sub: diagnostics::ArrayBracketsInsteadOfBracesSugg { + sub: crate::diagnostics::ArrayBracketsInsteadOfBracesSugg { left: lo, right: snapshot.prev_token.span, }, @@ -2370,7 +2331,7 @@ impl<'a> Parser<'a> { .span_to_snippet(snapshot.token.span) .is_ok_and(|snippet| snippet == "]") => { - return Err(self.dcx().create_err(diagnostics::MissingSemicolonBeforeArray { + return Err(self.dcx().create_err(crate::diagnostics::MissingSemicolonBeforeArray { open_delim: open_delim_span, semicolon: prev_span.shrink_to_hi(), })); @@ -2396,10 +2357,10 @@ impl<'a> Parser<'a> { } if self.token.is_metavar_block() { - self.dcx().emit_err(diagnostics::InvalidBlockMacroSegment { + self.dcx().emit_err(crate::diagnostics::InvalidBlockMacroSegment { span: self.token.span, context: lo.to(self.token.span), - wrap: diagnostics::WrapInExplicitBlock { + wrap: crate::diagnostics::WrapInExplicitBlock { lo: self.token.span.shrink_to_lo(), hi: self.token.span.shrink_to_hi(), }, @@ -2571,9 +2532,9 @@ impl<'a> Parser<'a> { // Check for `move async` and recover if self.check_keyword(exp!(Async)) { let move_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(self - .dcx() - .create_err(diagnostics::AsyncMoveOrderIncorrect { span: move_async_span })) + Err(self.dcx().create_err(crate::diagnostics::AsyncMoveOrderIncorrect { + span: move_async_span, + })) } else { Ok(CaptureBy::Value { move_kw: move_kw_span }) } @@ -2583,9 +2544,9 @@ impl<'a> Parser<'a> { // Check for `use async` and recover if self.check_keyword(exp!(Async)) { let use_async_span = self.token.span.with_lo(self.prev_token.span.data().lo); - Err(self - .dcx() - .create_err(diagnostics::AsyncUseOrderIncorrect { span: use_async_span })) + Err(self.dcx().create_err(crate::diagnostics::AsyncUseOrderIncorrect { + span: use_async_span, + })) } else { Ok(CaptureBy::Use { use_kw: use_kw_span }) } @@ -2667,10 +2628,10 @@ impl<'a> Parser<'a> { ExprKind::Binary(Spanned { span: binop_span, .. }, _, right) if let ExprKind::Block(_, None) = right.kind => { - let guar = this.dcx().emit_err(diagnostics::IfExpressionMissingThenBlock { + let guar = this.dcx().emit_err(crate::diagnostics::IfExpressionMissingThenBlock { if_span: lo, missing_then_block_sub: - diagnostics::IfExpressionMissingThenBlockSub::UnfinishedCondition( + crate::diagnostics::IfExpressionMissingThenBlockSub::UnfinishedCondition( cond_span.shrink_to_lo().to(*binop_span), ), let_else_sub: None, @@ -2678,10 +2639,11 @@ impl<'a> Parser<'a> { std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi(), guar)) } ExprKind::Block(_, None) => { - let guar = this.dcx().emit_err(diagnostics::IfExpressionMissingCondition { - if_span: lo.with_neighbor(cond.span).shrink_to_hi(), - block_span: self.psess.source_map().start_point(cond_span), - }); + let guar = + this.dcx().emit_err(crate::diagnostics::IfExpressionMissingCondition { + if_span: lo.with_neighbor(cond.span).shrink_to_hi(), + block_span: self.psess.source_map().start_point(cond_span), + }); std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi(), guar)) } _ => { @@ -2699,13 +2661,14 @@ impl<'a> Parser<'a> { if let Some(block) = recover_block_from_condition(self) { block } else { - let let_else_sub = matches!(cond.kind, ExprKind::Let(..)) - .then(|| diagnostics::IfExpressionLetSomeSub { if_span: lo.until(cond_span) }); + let let_else_sub = matches!(cond.kind, ExprKind::Let(..)).then(|| { + crate::diagnostics::IfExpressionLetSomeSub { if_span: lo.until(cond_span) } + }); - let guar = self.dcx().emit_err(diagnostics::IfExpressionMissingThenBlock { + let guar = self.dcx().emit_err(crate::diagnostics::IfExpressionMissingThenBlock { if_span: lo, missing_then_block_sub: - diagnostics::IfExpressionMissingThenBlockSub::AddThenBlock( + crate::diagnostics::IfExpressionMissingThenBlockSub::AddThenBlock( cond_span.shrink_to_hi(), ), let_else_sub, @@ -2798,9 +2761,9 @@ impl<'a> Parser<'a> { /// Parses a `let $pat = $expr` pseudo-expression. fn parse_expr_let(&mut self, restrictions: Restrictions) -> PResult<'a, Box> { let recovered: Recovered = if !restrictions.contains(Restrictions::ALLOW_LET) { - let err = diagnostics::ExpectedExpressionFoundLet { + let err = crate::diagnostics::ExpectedExpressionFoundLet { span: self.token.span, - reason: diagnostics::ForbiddenLetReason::OtherForbidden, + reason: crate::diagnostics::ForbiddenLetReason::OtherForbidden, missing_let: None, comparison: None, }; @@ -2822,7 +2785,7 @@ impl<'a> Parser<'a> { CommaRecoveryMode::LikelyTuple, )?; if self.token == token::EqEq { - self.dcx().emit_err(diagnostics::ExpectedEqForLetExpr { + self.dcx().emit_err(crate::diagnostics::ExpectedEqForLetExpr { span: self.token.span, sugg_span: self.token.span, }); @@ -2888,7 +2851,7 @@ impl<'a> Parser<'a> { || matches!(cond.kind, ExprKind::MacCall(..))) => { - self.dcx().emit_err(diagnostics::ExpectedElseBlock { + self.dcx().emit_err(crate::diagnostics::ExpectedElseBlock { first_tok_span, first_tok, else_span, @@ -2924,7 +2887,7 @@ impl<'a> Parser<'a> { let attributes = x0.span.until(branch_span); let last = xn.span; let ctx = if is_ctx_else { "else" } else { "if" }; - self.dcx().emit_err(diagnostics::OuterAttributeNotAllowedOnIfElse { + self.dcx().emit_err(crate::diagnostics::OuterAttributeNotAllowedOnIfElse { last, branch_span, ctx_span, @@ -2939,7 +2902,7 @@ impl<'a> Parser<'a> { && let BinOpKind::And = binop && let ExprKind::If(cond, ..) = &right.kind { - Err(self.dcx().create_err(diagnostics::UnexpectedIfWithIf( + Err(self.dcx().create_err(crate::diagnostics::UnexpectedIfWithIf( binop_span.shrink_to_hi().to(cond.span.shrink_to_lo()), ))) } else { @@ -2989,12 +2952,12 @@ impl<'a> Parser<'a> { let right = self.prev_token.span.between(self.look_ahead(1, |t| t.span)); self.bump(); // ) err.cancel(); - self.dcx().emit_err(diagnostics::ParenthesesInForHead { + self.dcx().emit_err(crate::diagnostics::ParenthesesInForHead { span, // With e.g. `for (x) in y)` this would replace `(x) in y)` // with `x) in y)` which is syntactically invalid. // However, this is prevented before we get here. - sugg: diagnostics::ParenthesesInForHeadSugg { left, right }, + sugg: crate::diagnostics::ParenthesesInForHeadSugg { left, right }, }); Ok((self.mk_pat(start_span.to(right), ast::PatKind::Wild), expr)) } else { @@ -3029,7 +2992,7 @@ impl<'a> Parser<'a> { && self.token.kind != token::OpenBrace && self.may_recover() { - let guar = self.dcx().emit_err(diagnostics::MissingExpressionInForLoop { + let guar = self.dcx().emit_err(crate::diagnostics::MissingExpressionInForLoop { span: expr.span.shrink_to_lo(), }); let err_expr = self.mk_expr(expr.span, ExprKind::Err(guar)); @@ -3071,7 +3034,7 @@ impl<'a> Parser<'a> { let else_span = self.token.span; self.bump(); let else_clause = self.parse_expr_else()?; - self.dcx().emit_err(diagnostics::LoopElseNotSupported { + self.dcx().emit_err(crate::diagnostics::LoopElseNotSupported { span: else_span.to(else_clause.span), loop_kind, loop_kw, @@ -3085,18 +3048,18 @@ impl<'a> Parser<'a> { // Possibly using JS syntax (#75311). let span = self.token.span; self.bump(); - (span, Some(diagnostics::MissingInInForLoopSub::InNotOf(span))) + (span, Some(crate::diagnostics::MissingInInForLoopSub::InNotOf(span))) } else if self.eat(exp!(Eq)) { let span = self.prev_token.span; - (span, Some(diagnostics::MissingInInForLoopSub::InNotEq(span))) + (span, Some(crate::diagnostics::MissingInInForLoopSub::InNotEq(span))) } else { let span = self.prev_token.span.between(self.token.span); let sub = (!self.for_loop_head_has_in()) - .then_some(diagnostics::MissingInInForLoopSub::AddIn(span)); + .then_some(crate::diagnostics::MissingInInForLoopSub::AddIn(span)); (span, sub) }; - self.dcx().emit_err(diagnostics::MissingInInForLoop { span, sub }); + self.dcx().emit_err(crate::diagnostics::MissingInInForLoop { span, sub }); } /// Whether the `for` loop header already contains an `in` before its body. @@ -3166,7 +3129,7 @@ impl<'a> Parser<'a> { if let Some((ident, is_raw)) = self.token.lifetime() { // Disallow `'fn`, but with a better error message than `expect_lifetime`. if is_raw == IdentIsRaw::No && ident.without_first_quote().is_reserved() { - self.dcx().emit_err(diagnostics::KeywordLabel { span: ident.span }); + self.dcx().emit_err(crate::diagnostics::KeywordLabel { span: ident.span }); } self.bump(); @@ -3263,18 +3226,20 @@ impl<'a> Parser<'a> { let err = |this: &Parser<'_>, stmts: Vec| { let span = stmts[0].span.to(stmts[stmts.len() - 1].span); - let guar = this.dcx().emit_err(diagnostics::MatchArmBodyWithoutBraces { + let guar = this.dcx().emit_err(crate::diagnostics::MatchArmBodyWithoutBraces { statements: span, arrow: arrow_span, num_statements: stmts.len(), sub: if stmts.len() > 1 { - diagnostics::MatchArmBodyWithoutBracesSugg::AddBraces { + crate::diagnostics::MatchArmBodyWithoutBracesSugg::AddBraces { left: span.shrink_to_lo(), right: span.shrink_to_hi(), num_statements: stmts.len(), } } else { - diagnostics::MatchArmBodyWithoutBracesSugg::UseComma { semicolon: semi_sp } + crate::diagnostics::MatchArmBodyWithoutBracesSugg::UseComma { + semicolon: semi_sp, + } }, }); (span, guar) @@ -3492,7 +3457,7 @@ impl<'a> Parser<'a> { .is_ok(); if pattern_follows && snapshot.check(exp!(FatArrow)) { err.cancel(); - let guar = this.dcx().emit_err(diagnostics::MissingCommaAfterMatchArm { + let guar = this.dcx().emit_err(crate::diagnostics::MissingCommaAfterMatchArm { span: arm_span.shrink_to_hi(), }); return Ok(Recovered::Yes(guar)); @@ -3585,9 +3550,9 @@ impl<'a> Parser<'a> { checker.visit_expr(&mut guard.cond); let right = self.prev_token.span; - self.dcx().emit_err(diagnostics::ParenthesesInMatchPat { + self.dcx().emit_err(crate::diagnostics::ParenthesesInMatchPat { span: vec![left, right], - sugg: diagnostics::ParenthesesInMatchPatSugg { left, right }, + sugg: crate::diagnostics::ParenthesesInMatchPatSugg { left, right }, }); if let Some(guar) = checker.found_incorrect_let_chain { @@ -3664,7 +3629,9 @@ impl<'a> Parser<'a> { let (attrs, body) = self.parse_inner_attrs_and_block(None)?; if self.eat_keyword(exp!(Catch)) { - Err(self.dcx().create_err(diagnostics::CatchAfterTry { span: self.prev_token.span })) + Err(self + .dcx() + .create_err(crate::diagnostics::CatchAfterTry { span: self.prev_token.span })) } else { let span = span_lo.to(body.span); let gate_sym = @@ -3767,9 +3734,9 @@ impl<'a> Parser<'a> { match self.parse_expr_struct(qself.clone(), path.clone(), false) { Ok(expr) => { // This is a struct literal, but we don't accept them here. - self.dcx().emit_err(diagnostics::StructLiteralNotAllowedHere { + self.dcx().emit_err(crate::diagnostics::StructLiteralNotAllowedHere { span: expr.span, - sub: diagnostics::StructLiteralNotAllowedHereSugg { + sub: crate::diagnostics::StructLiteralNotAllowedHereSugg { left: path.span.shrink_to_lo(), right: expr.span.shrink_to_hi(), }, @@ -3811,10 +3778,12 @@ impl<'a> Parser<'a> { )?; let guar = if is_underscore_entry_point { - self.dcx().create_err(diagnostics::StructLiteralPlaceholderPath { span }).emit() + self.dcx() + .create_err(crate::diagnostics::StructLiteralPlaceholderPath { span }) + .emit() } else { self.dcx() - .create_err(diagnostics::StructLiteralWithoutPathLate { + .create_err(crate::diagnostics::StructLiteralWithoutPathLate { span: expr.span, suggestion_span: expr.span.shrink_to_lo(), }) @@ -3846,8 +3815,8 @@ impl<'a> Parser<'a> { let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD); let async_block_err = |e: &mut Diag<'_>, span: Span| { - diagnostics::AsyncBlockIn2015 { span }.add_to_diag(e); - diagnostics::HelpUseLatestEdition::new().add_to_diag(e); + crate::diagnostics::AsyncBlockIn2015 { span }.add_to_diag(e); + crate::diagnostics::HelpUseLatestEdition::new().add_to_diag(e); }; while self.token != close.tok { @@ -4029,7 +3998,7 @@ impl<'a> Parser<'a> { if self.token != token::Comma { return; } - self.dcx().emit_err(diagnostics::CommaAfterBaseStruct { + self.dcx().emit_err(crate::diagnostics::CommaAfterBaseStruct { span: span.to(self.prev_token.span), comma: self.token.span, }); @@ -4040,7 +4009,8 @@ impl<'a> Parser<'a> { if !self.look_ahead(1, |t| t == close) && self.eat(exp!(DotDotDot)) { // recover from typo of `...`, suggest `..` let span = self.prev_token.span; - self.dcx().emit_err(diagnostics::MissingDotDot { token_span: span, sugg_span: span }); + self.dcx() + .emit_err(crate::diagnostics::MissingDotDot { token_span: span, sugg_span: span }); return true; } false @@ -4053,7 +4023,7 @@ impl<'a> Parser<'a> { let label = format!("'{}", ident.name); let ident = Ident::new(Symbol::intern(&label), ident.span); - self.dcx().emit_err(diagnostics::ExpectedLabelFoundIdent { + self.dcx().emit_err(crate::diagnostics::ExpectedLabelFoundIdent { span: ident.span, start: ident.span.shrink_to_lo(), }); @@ -4080,7 +4050,7 @@ impl<'a> Parser<'a> { || t == &token::CloseParen }); if is_wrong { - return Err(this.dcx().create_err(diagnostics::ExpectedStructField { + return Err(this.dcx().create_err(crate::diagnostics::ExpectedStructField { span: this.look_ahead(1, |t| t.span), ident_span: this.token.span, token: pprust::token_to_string(&this.look_ahead(1, |t| *t)), @@ -4121,20 +4091,12 @@ impl<'a> Parser<'a> { return; } - self.dcx().emit_err(diagnostics::EqFieldInit { + self.dcx().emit_err(crate::diagnostics::EqFieldInit { span: self.token.span, eq: field_name.span.shrink_to_hi().to(self.token.span), }); } - fn err_dotdotdot_syntax(&self, span: Span) { - self.dcx().emit_err(diagnostics::DotDotDot { span }); - } - - fn err_larrow_operator(&self, span: Span) { - self.dcx().emit_err(diagnostics::LeftArrowOperator { span }); - } - fn mk_assign_op(&self, assign_op: AssignOp, lhs: Box, rhs: Box) -> ExprKind { ExprKind::AssignOp(assign_op, lhs, rhs) } @@ -4282,9 +4244,9 @@ struct CondChecker<'a> { parser: &'a Parser<'a>, let_chains_policy: LetChainsPolicy, depth: u32, - forbid_let_reason: Option, - missing_let: Option, - comparison: Option, + forbid_let_reason: Option, + missing_let: Option, + comparison: Option, found_incorrect_let_chain: Option, } @@ -4311,12 +4273,13 @@ impl MutVisitor for CondChecker<'_> { ExprKind::Let(_, _, _, ref mut recovered @ Recovered::No) => { if let Some(reason) = self.forbid_let_reason { let error = match reason { - diagnostics::ForbiddenLetReason::NotSupportedOr(or_span) => { - self.parser.dcx().emit_err(diagnostics::OrInLetChain { span: or_span }) - } + crate::diagnostics::ForbiddenLetReason::NotSupportedOr(or_span) => self + .parser + .dcx() + .emit_err(crate::diagnostics::OrInLetChain { span: or_span }), _ => { let guar = self.parser.dcx().emit_err( - diagnostics::ExpectedExpressionFoundLet { + crate::diagnostics::ExpectedExpressionFoundLet { span, reason, missing_let: self.missing_let, @@ -4336,7 +4299,9 @@ impl MutVisitor for CondChecker<'_> { LetChainsPolicy::AlwaysAllowed => (), LetChainsPolicy::EditionDependent { current_edition } => { if !current_edition.at_least_rust_2024() || !span.at_least_rust_2024() { - self.parser.dcx().emit_err(diagnostics::LetChainPre2024 { span }); + self.parser + .dcx() + .emit_err(crate::diagnostics::LetChainPre2024 { span }); } } } @@ -4346,22 +4311,24 @@ impl MutVisitor for CondChecker<'_> { mut_visit::walk_expr(self, e); } ExprKind::Binary(Spanned { node: BinOpKind::Or, span: or_span }, _, _) - if let None | Some(diagnostics::ForbiddenLetReason::NotSupportedOr(_)) = + if let None | Some(crate::diagnostics::ForbiddenLetReason::NotSupportedOr(_)) = self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; self.forbid_let_reason = - Some(diagnostics::ForbiddenLetReason::NotSupportedOr(or_span)); + Some(crate::diagnostics::ForbiddenLetReason::NotSupportedOr(or_span)); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } ExprKind::Paren(ref inner) - if let None | Some(diagnostics::ForbiddenLetReason::NotSupportedParentheses(_)) = + if let None + | Some(crate::diagnostics::ForbiddenLetReason::NotSupportedParentheses(_)) = self.forbid_let_reason => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = - Some(diagnostics::ForbiddenLetReason::NotSupportedParentheses(inner.span)); + self.forbid_let_reason = Some( + crate::diagnostics::ForbiddenLetReason::NotSupportedParentheses(inner.span), + ); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4399,13 +4366,14 @@ impl MutVisitor for CondChecker<'_> { if let Some(later_rhs) = find_let_some(rhs) && depth > 0 { - let guar = - self.parser.dcx().emit_err(diagnostics::LetChainMissingLet { + let guar = self.parser.dcx().emit_err( + crate::diagnostics::LetChainMissingLet { span: lhs.span, label_span: expr_span, rhs_span: later_rhs.span, sug_span: lhs.span.shrink_to_lo(), - }); + }, + ); self.found_incorrect_let_chain = Some(guar); } @@ -4413,7 +4381,8 @@ impl MutVisitor for CondChecker<'_> { } let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(diagnostics::ForbiddenLetReason::OtherForbidden); + self.forbid_let_reason = + Some(crate::diagnostics::ForbiddenLetReason::OtherForbidden); let missing_let = self.missing_let; if let ExprKind::Binary(_, _, rhs) = &lhs.kind && let ExprKind::Path(_, _) @@ -4422,10 +4391,11 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Array(_) = rhs.kind { self.missing_let = - Some(diagnostics::MaybeMissingLet { span: rhs.span.shrink_to_lo() }); + Some(crate::diagnostics::MaybeMissingLet { span: rhs.span.shrink_to_lo() }); } let comparison = self.comparison; - self.comparison = Some(diagnostics::MaybeComparison { span: span.shrink_to_hi() }); + self.comparison = + Some(crate::diagnostics::MaybeComparison { span: span.shrink_to_hi() }); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; self.missing_let = missing_let; @@ -4447,7 +4417,8 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Tup(_) | ExprKind::Paren(_) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(diagnostics::ForbiddenLetReason::OtherForbidden); + self.forbid_let_reason = + Some(crate::diagnostics::ForbiddenLetReason::OtherForbidden); mut_visit::walk_expr(self, e); self.forbid_let_reason = forbid_let_reason; } @@ -4455,7 +4426,8 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::Type(ref mut op, _) | ExprKind::UnsafeBinderCast(_, ref mut op, _) => { let forbid_let_reason = self.forbid_let_reason; - self.forbid_let_reason = Some(diagnostics::ForbiddenLetReason::OtherForbidden); + self.forbid_let_reason = + Some(crate::diagnostics::ForbiddenLetReason::OtherForbidden); self.visit_expr(op); self.forbid_let_reason = forbid_let_reason; } diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs new file mode 100644 index 0000000000000..edbf844d5bbb0 --- /dev/null +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -0,0 +1,80 @@ +use rustc_ast::util::parser::AssocOp; +use rustc_ast::{BinOpKind, token}; +use rustc_span::Spanned; + +use crate::diagnostics; +use crate::parser::Parser; + +impl<'a> Parser<'a> { + /// Reject `...` being used as an expression operator. + pub(super) fn reject_dotdotdot_expr_op(&self) { + if self.token == token::DotDotDot { + self.dcx().emit_err(diagnostics::DotDotDotExprOp { span: self.token.span }); + } + } + + /// Reject `<-` being used as an expression operator. + pub(super) fn reject_larrow_expr_op(&self) { + if self.token == token::LArrow { + self.dcx().emit_err(diagnostics::LArrowExprOp { span: self.token.span }); + } + } + + /// Recover from strict equality operators `===` and `!==` as found in e.g., JS and PHP. + pub(super) fn recover_from_strict_eq_op(&mut self, op: Spanned) { + if let AssocOp::Binary(bop @ BinOpKind::Eq | bop @ BinOpKind::Ne) = op.node + && self.token == token::Eq + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + let sugg = bop.as_str().into(); + let invalid = format!("{sugg}="); + self.dcx().emit_err(diagnostics::InvalidComparisonOperator { + span: sp, + invalid: invalid.clone(), + sub: diagnostics::InvalidComparisonOperatorSub::Correctable { + span: sp, + invalid, + correct: sugg, + }, + }); + self.bump(); + } + } + + /// Recover from inequality operator `<>` ("diamond") as found in e.g., PHP. + pub(super) fn recover_from_diamond_ne_op(&mut self, op: Spanned) { + if op.node == AssocOp::Binary(BinOpKind::Lt) + && self.token == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.dcx().emit_err(diagnostics::InvalidComparisonOperator { + span: sp, + invalid: "<>".into(), + sub: diagnostics::InvalidComparisonOperatorSub::Correctable { + span: sp, + invalid: "<>".into(), + correct: "!=".into(), + }, + }); + self.bump(); + } + } + + /// Recover from comparison operator `<=>` ("spaceship") as found in e.g., C++. + pub(super) fn recover_from_spaceship_cmp_op(&mut self, op: Spanned) { + if op.node == AssocOp::Binary(BinOpKind::Le) + && self.token == token::Gt + && self.prev_token.span.hi() == self.token.span.lo() + { + let sp = op.span.to(self.token.span); + self.dcx().emit_err(diagnostics::InvalidComparisonOperator { + span: sp, + invalid: "<=>".into(), + sub: diagnostics::InvalidComparisonOperatorSub::Spaceship(sp), + }); + self.bump(); + } + } +} From b945d684dc870d6cf0bbf058358c9f30e163f830 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Sep 2026 13:25:49 +0200 Subject: [PATCH 0345/1309] Don't needlessly pass the operand through some recovery functions by value These functions didn't actually modifiy the operand or return a new or different expression. So essentially the "`fn(Box) -> Box` part" was an identity function. Just change it to "fn(&Expr)". --- .../rustc_parse/src/parser/diagnostics.rs | 26 ++++++++----------- compiler/rustc_parse/src/parser/expr.rs | 7 ++--- 2 files changed, 15 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 40dbda2466de4..64f24b8216edd 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1651,10 +1651,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_prefix_increment( &mut self, - operand_expr: Box, + operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, Box> { + ) -> PResult<'a, ()> { let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; self.recover_from_inc_dec(operand_expr, kind, op_span) @@ -1662,10 +1662,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_postfix_increment( &mut self, - operand_expr: Box, + operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, Box> { + ) -> PResult<'a, ()> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Inc, @@ -1676,10 +1676,10 @@ impl<'a> Parser<'a> { pub(super) fn recover_from_postfix_decrement( &mut self, - operand_expr: Box, + operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, Box> { + ) -> PResult<'a, ()> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Dec, @@ -1690,22 +1690,16 @@ impl<'a> Parser<'a> { fn recover_from_inc_dec( &mut self, - base: Box, + base: &Expr, kind: IncDecRecovery, op_span: Span, - ) -> PResult<'a, Box> { + ) -> PResult<'a, ()> { let mut err = self.dcx().struct_span_err( op_span, format!("Rust has no {} {} operator", kind.fixity, kind.op.name()), ); err.span_label(op_span, format!("not a valid {} operator", kind.fixity)); - let help_base_case = |mut err: Diag<'_, ErrorGuaranteed>, base| { - err.help(format!("use `{}= 1` instead", kind.op.chr())); - err.emit(); - Ok(base) - }; - // (pre, post) let spans = match kind.fixity { UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()), @@ -1718,7 +1712,9 @@ impl<'a> Parser<'a> { } IsStandalone::Subexpr => { let Ok(base_src) = self.span_to_snippet(base.span) else { - return help_base_case(err, base); + err.help(format!("use `{}= 1` instead", kind.op.chr())); + err.emit(); + return Ok(()); }; match kind.fixity { UnaryFixity::Pre => { diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a7bcb93d5b084..952c9a3fdf240 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -190,7 +190,7 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `+` self.bump(); - lhs = self.recover_from_postfix_increment(lhs, op_span, starts_stmt)?; + self.recover_from_postfix_increment(&lhs, op_span, starts_stmt)?; continue; } @@ -202,7 +202,7 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `-` self.bump(); - lhs = self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)?; + self.recover_from_postfix_decrement(&lhs, op_span, starts_stmt)?; continue; } @@ -491,7 +491,8 @@ impl<'a> Parser<'a> { this.bump(); let operand_expr = this.parse_expr_dot_or_call(attrs)?; - this.recover_from_prefix_increment(operand_expr, pre_span, starts_stmt) + this.recover_from_prefix_increment(&operand_expr, pre_span, starts_stmt)?; + Ok(operand_expr) } token::Ident(..) if this.token.is_keyword(kw::Move) From ceede0ba9c7dc2b2fb2fa68dc7b2b8b08e4372cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 6 Sep 2026 22:13:38 +0200 Subject: [PATCH 0346/1309] Remove odd special case of some parse error recovery functions `recover_from_inc_dec` *always* returns a (fatal) `Err(_)` *except* if the increment/decrement operator is a subexpression *and* the source of the operand is not available in which case it emits the diagnostic and returns `Ok(_)` (rendering it non-fatal). This makes no sense whatsoever. For illustration purposes, listed below are steps that would make us reach this case: 1. `rustc a.rs --crate-type=lib` where `a.rs` contains: `#[macro_export] macro_rules! m { () => { i++ } }`. 2. Move or remove `a.rs` 3. `rustc b.rs --edition 2018 --extern a -L.` where `b.rs` contains: `fn main() { (a::m!()); }`. Just make the error unconditionally fatal and add a FIXME to make it non fatal in the future which would allow us to report name resolution errors and what not. However, since that would be slightly more involved and represent a behavior change (in the error path), this is out of scope for a mere cleanup commit like this one. --- .../rustc_parse/src/parser/diagnostics.rs | 19 ++++++++++++------- compiler/rustc_parse/src/parser/expr.rs | 13 +++++-------- 2 files changed, 17 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 64f24b8216edd..4aef934323bb3 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1654,7 +1654,7 @@ impl<'a> Parser<'a> { operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, ()> { + ) -> Diag<'a> { let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }; let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; self.recover_from_inc_dec(operand_expr, kind, op_span) @@ -1665,7 +1665,7 @@ impl<'a> Parser<'a> { operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, ()> { + ) -> Diag<'a> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Inc, @@ -1679,7 +1679,7 @@ impl<'a> Parser<'a> { operand_expr: &Expr, op_span: Span, start_stmt: bool, - ) -> PResult<'a, ()> { + ) -> Diag<'a> { let kind = IncDecRecovery { standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, op: IncOrDec::Dec, @@ -1693,7 +1693,13 @@ impl<'a> Parser<'a> { base: &Expr, kind: IncDecRecovery, op_span: Span, - ) -> PResult<'a, ()> { + ) -> Diag<'a> { + // FIXME: Don't return an error diag, emit the diag here *and* return a new expr of the form + // `$base += 1` / `$base -= 1` (taking `base: Expr` by value) for *proper* recovery. + // (Just emitting the diag would be insufficient since callers would most likely just + // use `$base` as the recovered AST node which would lead to annoying follow-up diags + // like "variable doesn't need to be mutable" getting emitted in some cases.) + let mut err = self.dcx().struct_span_err( op_span, format!("Rust has no {} {} operator", kind.fixity, kind.op.name()), @@ -1713,8 +1719,7 @@ impl<'a> Parser<'a> { IsStandalone::Subexpr => { let Ok(base_src) = self.span_to_snippet(base.span) else { err.help(format!("use `{}= 1` instead", kind.op.chr())); - err.emit(); - return Ok(()); + return err; }; match kind.fixity { UnaryFixity::Pre => { @@ -1730,7 +1735,7 @@ impl<'a> Parser<'a> { } } } - Err(err) + err } fn prefix_inc_dec_suggest( diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 952c9a3fdf240..c179db3dbfa09 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -190,8 +190,7 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `+` self.bump(); - self.recover_from_postfix_increment(&lhs, op_span, starts_stmt)?; - continue; + return Err(self.recover_from_postfix_increment(&lhs, op_span, starts_stmt)); } if self.prev_token == token::Minus @@ -202,8 +201,7 @@ impl<'a> Parser<'a> { let op_span = self.prev_token.span.to(self.token.span); // Eat the second `-` self.bump(); - self.recover_from_postfix_decrement(&lhs, op_span, starts_stmt)?; - continue; + return Err(self.recover_from_postfix_decrement(&lhs, op_span, starts_stmt)); } let op_span = op.span; @@ -490,9 +488,8 @@ impl<'a> Parser<'a> { this.bump(); this.bump(); - let operand_expr = this.parse_expr_dot_or_call(attrs)?; - this.recover_from_prefix_increment(&operand_expr, pre_span, starts_stmt)?; - Ok(operand_expr) + let operand = this.parse_expr_dot_or_call(attrs)?; + return Err(this.recover_from_prefix_increment(&operand, pre_span, starts_stmt)); } token::Ident(..) if this.token.is_keyword(kw::Move) @@ -503,7 +500,7 @@ impl<'a> Parser<'a> { token::Ident(..) if this.may_recover() && this.is_mistaken_not_ident_negation() => { make_it!(this, attrs, |this, _| this.recover_not_expr(lo)) } - _ => return this.parse_expr_dot_or_call(attrs), + _ => this.parse_expr_dot_or_call(attrs), } } From 6c0ab88a2037fa75cc8d78d8b06a272f483e4710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 6 Sep 2026 22:45:43 +0200 Subject: [PATCH 0347/1309] Dismantle bespoke diagnostic suggestion wrapper API There's literally no upside to use it and only downsides: It's not more concise, only adds code and obfuscates. Its `MultiSugg::emit{,_verbose}` didn't even *emit* the diagnostic, they merely *decorated* it! --- .../rustc_parse/src/parser/diagnostics.rs | 109 ++++++------------ 1 file changed, 36 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 4aef934323bb3..3263fcacec498 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -211,22 +211,6 @@ fn find_similar_kw(lookup: Ident, candidates: &[Symbol]) -> Option }) } -struct MultiSugg { - msg: String, - patches: Vec<(Span, String)>, - applicability: Applicability, -} - -impl MultiSugg { - fn emit(self, err: &mut Diag<'_>) { - err.multipart_suggestion(self.msg, self.patches, self.applicability); - } - - fn emit_verbose(self, err: &mut Diag<'_>) { - err.multipart_suggestion(self.msg, self.patches, self.applicability); - } -} - /// SnapshotParser is used to create a snapshot of the parser /// without causing duplicate errors being emitted when the `Parser` /// is dropped. @@ -1706,15 +1690,23 @@ impl<'a> Parser<'a> { ); err.span_label(op_span, format!("not a valid {} operator", kind.fixity)); - // (pre, post) - let spans = match kind.fixity { + let (pre_span, post_span) = match kind.fixity { UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()), UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), }; match kind.standalone { IsStandalone::Standalone => { - self.inc_dec_standalone_suggest(kind, spans).emit_verbose(&mut err) + let mut patches = Vec::new(); + if !pre_span.is_empty() { + patches.push((pre_span, String::new())); + } + patches.push((post_span, format!(" {}= 1", kind.op.chr()))); + err.multipart_suggestion( + format!("use `{}= 1` instead", kind.op.chr()), + patches, + Applicability::MachineApplicable, + ); } IsStandalone::Subexpr => { let Ok(base_src) = self.span_to_snippet(base.span) else { @@ -1723,13 +1715,36 @@ impl<'a> Parser<'a> { }; match kind.fixity { UnaryFixity::Pre => { - self.prefix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + err.multipart_suggestion( + format!("use `{}= 1` instead", kind.op.chr()), + vec![ + (pre_span, "{ ".to_string()), + (post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)), + ], + Applicability::MachineApplicable, + ); } UnaryFixity::Post => { // won't suggest since we can not handle the precedences // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here if !matches!(base.kind, ExprKind::Binary(_, _, _)) { - self.postfix_inc_dec_suggest(base_src, kind, spans).emit(&mut err) + let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" }; + err.multipart_suggestion( + format!("use `{}= 1` instead", kind.op.chr()), + vec![ + (pre_span, format!("{{ let {tmp_var} = ")), + ( + post_span, + format!( + "; {} {}= 1; {} }}", + base_src, + kind.op.chr(), + tmp_var + ), + ), + ], + Applicability::HasPlaceholders, + ); } } } @@ -1738,58 +1753,6 @@ impl<'a> Parser<'a> { err } - fn prefix_inc_dec_suggest( - &mut self, - base_src: String, - kind: IncDecRecovery, - (pre_span, post_span): (Span, Span), - ) -> MultiSugg { - MultiSugg { - msg: format!("use `{}= 1` instead", kind.op.chr()), - patches: vec![ - (pre_span, "{ ".to_string()), - (post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)), - ], - applicability: Applicability::MachineApplicable, - } - } - - fn postfix_inc_dec_suggest( - &mut self, - base_src: String, - kind: IncDecRecovery, - (pre_span, post_span): (Span, Span), - ) -> MultiSugg { - let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" }; - MultiSugg { - msg: format!("use `{}= 1` instead", kind.op.chr()), - patches: vec![ - (pre_span, format!("{{ let {tmp_var} = ")), - (post_span, format!("; {} {}= 1; {} }}", base_src, kind.op.chr(), tmp_var)), - ], - applicability: Applicability::HasPlaceholders, - } - } - - fn inc_dec_standalone_suggest( - &mut self, - kind: IncDecRecovery, - (pre_span, post_span): (Span, Span), - ) -> MultiSugg { - let mut patches = Vec::new(); - - if !pre_span.is_empty() { - patches.push((pre_span, String::new())); - } - - patches.push((post_span, format!(" {}= 1", kind.op.chr()))); - MultiSugg { - msg: format!("use `{}= 1` instead", kind.op.chr()), - patches, - applicability: Applicability::MachineApplicable, - } - } - /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem` /// tail, and combines them into a `::AssocItem` expression/pattern/type. From ddb9380cde72a3abd88c8521e00c380451aa0e8f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Sep 2026 10:37:14 +0200 Subject: [PATCH 0348/1309] Move parse error recovery from C-style inc/dec ops out of line --- compiler/rustc_parse/src/parser/expr.rs | 23 +---------- .../src/parser/expr/diagnostics.rs | 38 ++++++++++++++++++- 2 files changed, 39 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index c179db3dbfa09..1349af251e649 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -182,27 +182,8 @@ impl<'a> Parser<'a> { self.recover_from_strict_eq_op(op); self.recover_from_diamond_ne_op(op); self.recover_from_spaceship_cmp_op(op); - - if self.prev_token == token::Plus - && self.token == token::Plus - && self.prev_token.span.between(self.token.span).is_empty() - { - let op_span = self.prev_token.span.to(self.token.span); - // Eat the second `+` - self.bump(); - return Err(self.recover_from_postfix_increment(&lhs, op_span, starts_stmt)); - } - - if self.prev_token == token::Minus - && self.token == token::Minus - && self.prev_token.span.between(self.token.span).is_empty() - && !self.look_ahead(1, |tok| tok.can_begin_expr()) - { - let op_span = self.prev_token.span.to(self.token.span); - // Eat the second `-` - self.bump(); - return Err(self.recover_from_postfix_decrement(&lhs, op_span, starts_stmt)); - } + self.recover_from_postfix_inc_op(&lhs, starts_stmt)?; + self.recover_from_postfix_dec_op(&lhs, starts_stmt)?; let op_span = op.span; let op = op.node; diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index edbf844d5bbb0..0008b576fdb4b 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -1,5 +1,6 @@ use rustc_ast::util::parser::AssocOp; -use rustc_ast::{BinOpKind, token}; +use rustc_ast::{BinOpKind, Expr, token}; +use rustc_errors::PResult; use rustc_span::Spanned; use crate::diagnostics; @@ -77,4 +78,39 @@ impl<'a> Parser<'a> { self.bump(); } } + + /// Recover from postfix increment operator `++` as found in many C-style languages. + pub(super) fn recover_from_postfix_inc_op( + &mut self, + lhs: &Expr, + starts_stmt: bool, + ) -> PResult<'a, ()> { + if let (token::Plus, token::Plus) = (self.prev_token.kind, self.token.kind) + && self.prev_token.span.hi() == self.token.span.lo() + { + let op_span = self.prev_token.span.to(self.token.span); + self.bump(); // eat the second `+` + Err(self.recover_from_postfix_increment(lhs, op_span, starts_stmt)) + } else { + Ok(()) + } + } + + /// Recover from postfix decrement operator `--` as found in many C-style languages. + pub(super) fn recover_from_postfix_dec_op( + &mut self, + lhs: &Expr, + starts_stmt: bool, + ) -> PResult<'a, ()> { + if let (token::Minus, token::Minus) = (self.prev_token.kind, self.token.kind) + && self.prev_token.span.hi() == self.token.span.lo() + && !self.look_ahead(1, |tok| tok.can_begin_expr()) + { + let op_span = self.prev_token.span.to(self.token.span); + self.bump(); // eat the second `-` + Err(self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)) + } else { + Ok(()) + } + } } From 1adccf221ff9c6c507354395f255aa973c5a3693 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Sep 2026 10:59:21 +0200 Subject: [PATCH 0349/1309] Inline fns & data types related to parse error recovery from C-style inc/dec ops --- .../rustc_parse/src/parser/diagnostics.rs | 178 ------------------ compiler/rustc_parse/src/parser/expr.rs | 8 +- .../src/parser/expr/diagnostics.rs | 104 +++++++++- 3 files changed, 106 insertions(+), 184 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 3263fcacec498..f5fa592585099 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -141,64 +141,6 @@ impl AttemptLocalParseRecovery { } } -/// Information for emitting suggestions and recovering from -/// C-style `i++`, `--i`, etc. -#[derive(Debug, Copy, Clone)] -struct IncDecRecovery { - /// Is this increment/decrement its own statement? - standalone: IsStandalone, - /// Is this an increment or decrement? - op: IncOrDec, - /// Is this pre- or postfix? - fixity: UnaryFixity, -} - -/// Is an increment or decrement expression its own statement? -#[derive(Debug, Copy, Clone)] -enum IsStandalone { - /// It's standalone, i.e., its own statement. - Standalone, - /// It's a subexpression, i.e., *not* standalone. - Subexpr, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum IncOrDec { - Inc, - Dec, -} - -#[derive(Debug, Copy, Clone, PartialEq, Eq)] -enum UnaryFixity { - Pre, - Post, -} - -impl IncOrDec { - fn chr(&self) -> char { - match self { - Self::Inc => '+', - Self::Dec => '-', - } - } - - fn name(&self) -> &'static str { - match self { - Self::Inc => "increment", - Self::Dec => "decrement", - } - } -} - -impl std::fmt::Display for UnaryFixity { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Pre => write!(f, "prefix"), - Self::Post => write!(f, "postfix"), - } - } -} - /// Checks if the given `lookup` identifier is similar to any keyword symbol in `candidates`. /// /// This is a specialized version of [`Symbol::find_similar`] that constructs an error when a @@ -1633,126 +1575,6 @@ impl<'a> Parser<'a> { Ok(()) } - pub(super) fn recover_from_prefix_increment( - &mut self, - operand_expr: &Expr, - op_span: Span, - start_stmt: bool, - ) -> Diag<'a> { - let standalone = if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }; - let kind = IncDecRecovery { standalone, op: IncOrDec::Inc, fixity: UnaryFixity::Pre }; - self.recover_from_inc_dec(operand_expr, kind, op_span) - } - - pub(super) fn recover_from_postfix_increment( - &mut self, - operand_expr: &Expr, - op_span: Span, - start_stmt: bool, - ) -> Diag<'a> { - let kind = IncDecRecovery { - standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, - op: IncOrDec::Inc, - fixity: UnaryFixity::Post, - }; - self.recover_from_inc_dec(operand_expr, kind, op_span) - } - - pub(super) fn recover_from_postfix_decrement( - &mut self, - operand_expr: &Expr, - op_span: Span, - start_stmt: bool, - ) -> Diag<'a> { - let kind = IncDecRecovery { - standalone: if start_stmt { IsStandalone::Standalone } else { IsStandalone::Subexpr }, - op: IncOrDec::Dec, - fixity: UnaryFixity::Post, - }; - self.recover_from_inc_dec(operand_expr, kind, op_span) - } - - fn recover_from_inc_dec( - &mut self, - base: &Expr, - kind: IncDecRecovery, - op_span: Span, - ) -> Diag<'a> { - // FIXME: Don't return an error diag, emit the diag here *and* return a new expr of the form - // `$base += 1` / `$base -= 1` (taking `base: Expr` by value) for *proper* recovery. - // (Just emitting the diag would be insufficient since callers would most likely just - // use `$base` as the recovered AST node which would lead to annoying follow-up diags - // like "variable doesn't need to be mutable" getting emitted in some cases.) - - let mut err = self.dcx().struct_span_err( - op_span, - format!("Rust has no {} {} operator", kind.fixity, kind.op.name()), - ); - err.span_label(op_span, format!("not a valid {} operator", kind.fixity)); - - let (pre_span, post_span) = match kind.fixity { - UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()), - UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), - }; - - match kind.standalone { - IsStandalone::Standalone => { - let mut patches = Vec::new(); - if !pre_span.is_empty() { - patches.push((pre_span, String::new())); - } - patches.push((post_span, format!(" {}= 1", kind.op.chr()))); - err.multipart_suggestion( - format!("use `{}= 1` instead", kind.op.chr()), - patches, - Applicability::MachineApplicable, - ); - } - IsStandalone::Subexpr => { - let Ok(base_src) = self.span_to_snippet(base.span) else { - err.help(format!("use `{}= 1` instead", kind.op.chr())); - return err; - }; - match kind.fixity { - UnaryFixity::Pre => { - err.multipart_suggestion( - format!("use `{}= 1` instead", kind.op.chr()), - vec![ - (pre_span, "{ ".to_string()), - (post_span, format!(" {}= 1; {} }}", kind.op.chr(), base_src)), - ], - Applicability::MachineApplicable, - ); - } - UnaryFixity::Post => { - // won't suggest since we can not handle the precedences - // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here - if !matches!(base.kind, ExprKind::Binary(_, _, _)) { - let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" }; - err.multipart_suggestion( - format!("use `{}= 1` instead", kind.op.chr()), - vec![ - (pre_span, format!("{{ let {tmp_var} = ")), - ( - post_span, - format!( - "; {} {}= 1; {} }}", - base_src, - kind.op.chr(), - tmp_var - ), - ), - ], - Applicability::HasPlaceholders, - ); - } - } - } - } - } - err - } - /// Tries to recover from associated item paths like `[T]::AssocItem` / `(T, U)::AssocItem`. /// Attempts to convert the base expression/pattern/type into a type, parses the `::AssocItem` /// tail, and combines them into a `::AssocItem` expression/pattern/type. diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 1349af251e649..54e10d05f1140 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -470,7 +470,13 @@ impl<'a> Parser<'a> { this.bump(); let operand = this.parse_expr_dot_or_call(attrs)?; - return Err(this.recover_from_prefix_increment(&operand, pre_span, starts_stmt)); + return Err(this.report_inc_dec_op( + &operand, + starts_stmt, + diagnostics::IncOrDec::Inc, + diagnostics::UnaryFixity::Pre, + pre_span, + )); } token::Ident(..) if this.token.is_keyword(kw::Move) diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index 0008b576fdb4b..18dd6dba13eb5 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -1,7 +1,7 @@ use rustc_ast::util::parser::AssocOp; -use rustc_ast::{BinOpKind, Expr, token}; -use rustc_errors::PResult; -use rustc_span::Spanned; +use rustc_ast::{BinOpKind, Expr, ExprKind, token}; +use rustc_errors::{Applicability, Diag, PResult}; +use rustc_span::{Span, Spanned}; use crate::diagnostics; use crate::parser::Parser; @@ -90,7 +90,7 @@ impl<'a> Parser<'a> { { let op_span = self.prev_token.span.to(self.token.span); self.bump(); // eat the second `+` - Err(self.recover_from_postfix_increment(lhs, op_span, starts_stmt)) + Err(self.report_inc_dec_op(lhs, starts_stmt, IncOrDec::Inc, UnaryFixity::Post, op_span)) } else { Ok(()) } @@ -108,9 +108,103 @@ impl<'a> Parser<'a> { { let op_span = self.prev_token.span.to(self.token.span); self.bump(); // eat the second `-` - Err(self.recover_from_postfix_decrement(lhs, op_span, starts_stmt)) + Err(self.report_inc_dec_op(lhs, starts_stmt, IncOrDec::Dec, UnaryFixity::Post, op_span)) } else { Ok(()) } } + + /// Report increment operator `++` & decrement operator `--` as found in many C-style languages. + pub(super) fn report_inc_dec_op( + &mut self, + base: &Expr, + starts_stmt: bool, + op: IncOrDec, + fixity: UnaryFixity, + op_span: Span, + ) -> Diag<'a> { + // FIXME: Don't return an error diag, emit the diag here *and* return a new expr of the form + // `$base += 1` / `$base -= 1` (taking `base: Expr` by value) for *proper* recovery. + // (Just emitting the diag would be insufficient since callers would most likely just + // use `$base` as the recovered AST node which would lead to annoying follow-up diags + // like "variable doesn't need to be mutable" getting emitted in some cases.) + + let mut err = { + let fixity = match fixity { + UnaryFixity::Pre => "prefix", + UnaryFixity::Post => "postfix", + }; + let op = match op { + IncOrDec::Inc => "increment", + IncOrDec::Dec => "decrement", + }; + self.dcx() + .struct_span_err(op_span, format!("Rust has no {fixity} {op} operator")) + .with_span_label(op_span, format!("not a valid {fixity} operator")) + }; + + let op = match op { + IncOrDec::Inc => "+= 1", + IncOrDec::Dec => "-= 1", + }; + let (pre_span, post_span) = match fixity { + UnaryFixity::Pre => (op_span, base.span.shrink_to_hi()), + UnaryFixity::Post => (base.span.shrink_to_lo(), op_span), + }; + + if starts_stmt { + let mut patches = Vec::new(); + if !pre_span.is_empty() { + patches.push((pre_span, String::new())); + } + patches.push((post_span, format!(" {op}"))); + err.multipart_suggestion( + format!("use `{op}` instead"), + patches, + Applicability::MachineApplicable, + ); + } else { + let Ok(base_src) = self.span_to_snippet(base.span) else { + err.help(format!("use `{op}` instead")); + return err; + }; + match fixity { + UnaryFixity::Pre => { + err.multipart_suggestion( + format!("use `{op}` instead"), + vec![(pre_span, "{ ".into()), (post_span, format!(" {op}; {base_src} }}"))], + Applicability::MachineApplicable, + ); + } + UnaryFixity::Post => { + // won't suggest since we can not handle the precedences + // for example: `a + b++` has been parsed (a + b)++ and we can not suggest here + if !matches!(base.kind, ExprKind::Binary(..)) { + let tmp_var = if base_src.trim() == "tmp" { "tmp_" } else { "tmp" }; + err.multipart_suggestion( + format!("use `{op}` instead"), + vec![ + (pre_span, format!("{{ let {tmp_var} = ")), + (post_span, format!("; {base_src} {op}; {tmp_var} }}")), + ], + Applicability::HasPlaceholders, + ); + } + } + } + } + err + } +} + +#[derive(Copy, Clone)] +pub(super) enum IncOrDec { + Inc, + Dec, +} + +#[derive(Copy, Clone)] +pub(super) enum UnaryFixity { + Pre, + Post, } From d85d3f55051e0d88237c0f4c0b4070f73d5ef837 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 10 Sep 2026 12:05:49 +0200 Subject: [PATCH 0350/1309] Refactor the way we finish parsing expr ops 1. Remove unnecessary rebindings (`op_span` and `op = op.node`) 2. Remove binding `cur_op_span` as it's equal to `op.span` 3. Merge two `match`es on `op.node` into one to make the control flow more obvious and to render everything more legible. Moreover, it allows us to drop an ungly `unreachable!()` --- compiler/rustc_parse/src/parser/expr.rs | 56 ++++++++++++------------- 1 file changed, 27 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 54e10d05f1140..336af55a4e904 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -152,7 +152,6 @@ impl<'a> Parser<'a> { self.expected_token_types.insert(TokenType::Operator); while let Some(op) = self.check_assoc_op() { let lhs_span = self.interpolated_or_expr_span(&lhs); - let cur_op_span = self.token.span; let restrictions = if op.node.is_assign_like() { self.restrictions & Restrictions::NO_STRUCT_LITERAL } else { @@ -185,42 +184,41 @@ impl<'a> Parser<'a> { self.recover_from_postfix_inc_op(&lhs, starts_stmt)?; self.recover_from_postfix_dec_op(&lhs, starts_stmt)?; - let op_span = op.span; - let op = op.node; - // Special cases: - if op == AssocOp::Cast { - lhs = self.parse_assoc_op_cast(lhs, lhs_span, op_span, ExprKind::Cast)?; - continue; - } else if let AssocOp::Range(limits) = op { - // If we didn't have to handle `x..`/`x..=`, it would be pretty easy to - // generalise it to the Fixity::None code. - lhs = self.parse_expr_range(prec, lhs, limits, cur_op_span)?; - break; - } - - let min_prec = match op.fixity() { + let min_prec = match op.node.fixity() { Fixity::Right => Bound::Included(prec), Fixity::Left | Fixity::None => Bound::Excluded(prec), }; - let rhs = self.with_res(restrictions - Restrictions::STMT_EXPR, |this| { - this.parse_expr_assoc(min_prec) - })?; - let span = self.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span); - lhs = match op { + let finish_parsing_bin_op = |this: &mut Self| { + let rhs = this.with_res(restrictions - Restrictions::STMT_EXPR, |this| { + this.parse_expr_assoc(min_prec) + })?; + let span = this.mk_expr_sp(&lhs, lhs_span, op.span, rhs.span); + Ok((rhs, span)) + }; + + lhs = match op.node { AssocOp::Binary(ast_op) => { - let binary = self.mk_binary(respan(cur_op_span, ast_op), lhs, rhs); - self.mk_expr(span, binary) + let (rhs, span) = finish_parsing_bin_op(self)?; + self.mk_expr(span, self.mk_binary(respan(op.span, ast_op), lhs, rhs)) } - AssocOp::Assign => self.mk_expr(span, ExprKind::Assign(lhs, rhs, cur_op_span)), AssocOp::AssignOp(aop) => { - let aopexpr = self.mk_assign_op(respan(cur_op_span, aop), lhs, rhs); - self.mk_expr(span, aopexpr) + let (rhs, span) = finish_parsing_bin_op(self)?; + self.mk_expr(span, self.mk_assign_op(respan(op.span, aop), lhs, rhs)) + } + AssocOp::Assign => { + let (rhs, span) = finish_parsing_bin_op(self)?; + self.mk_expr(span, ExprKind::Assign(lhs, rhs, op.span)) } - AssocOp::Cast | AssocOp::Range(_) => { - self.dcx().span_bug(span, "AssocOp should have been handled by special case") + AssocOp::Cast => { + self.parse_assoc_op_cast(lhs, lhs_span, op.span, ExprKind::Cast)? } + AssocOp::Range(limits) => self.parse_expr_range(min_prec, lhs, limits, op.span)?, }; + + if let AssocOp::Range(_) = op.node { + break; + } } Ok((lhs, parsed_something)) @@ -338,7 +336,7 @@ impl<'a> Parser<'a> { /// The other two variants are handled in `parse_prefix_range_expr` below. fn parse_expr_range( &mut self, - prec: ExprPrecedence, + min_prec: Bound, lhs: Box, limits: RangeLimits, cur_op_span: Span, @@ -346,7 +344,7 @@ impl<'a> Parser<'a> { let rhs = if self.is_at_start_of_range_notation_rhs() { let maybe_lt = self.token; Some( - self.parse_expr_assoc(Bound::Excluded(prec)) + self.parse_expr_assoc(min_prec) .map_err(|err| self.maybe_err_dotdotlt_syntax(maybe_lt, err))?, ) } else { From f0ae097b364ffd9b30f908aeddc0b9eb040464dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 25 Aug 2026 16:30:11 +0200 Subject: [PATCH 0351/1309] Refactor `check_assoc_op` to make it more legible --- compiler/rustc_parse/src/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 80 +++++++------------ .../src/parser/expr/diagnostics.rs | 25 +++++- 3 files changed, 53 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 78240b0ee891b..4f3c702c77ef9 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -257,7 +257,7 @@ pub(crate) enum InvalidComparisonOperatorSub { pub(crate) struct InvalidLogicalOperator { #[primary_span] pub span: Span, - pub incorrect: String, + pub incorrect: Symbol, #[subdiagnostic] pub sub: InvalidLogicalOperatorSub, } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 336af55a4e904..148e49d803875 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -272,59 +272,35 @@ impl<'a> Parser<'a> { /// Possibly translate the current token to an associative operator. /// The method does not advance the current token. - /// - /// Also performs recovery for `and` / `or` which are mistaken for `&&` and `||` respectively. pub(super) fn check_assoc_op(&self) -> Option> { - let (op, span) = match (AssocOp::from_token(&self.token), self.token.ident()) { - // When parsing const expressions, stop parsing when encountering `>`. - ( - Some( - AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge) - | AssocOp::AssignOp(AssignOpKind::ShrAssign), - ), - _, - ) if self.restrictions.contains(Restrictions::CONST_EXPR) => { - return None; - } - // When recovering patterns as expressions, stop parsing when encountering an - // assignment `=`, an alternative `|`, or a range `..`. - ( - Some( - AssocOp::Assign - | AssocOp::AssignOp(_) - | AssocOp::Binary(BinOpKind::BitOr) - | AssocOp::Range(_), - ), - _, - ) if self.restrictions.contains(Restrictions::IS_PAT) => { - return None; - } - (Some(op), _) => (op, self.token.span), - (None, Some((Ident { name: sym::and, span }, IdentIsRaw::No))) - if self.may_recover() => - { - self.dcx().emit_err(crate::diagnostics::InvalidLogicalOperator { - span: self.token.span, - incorrect: "and".into(), - sub: crate::diagnostics::InvalidLogicalOperatorSub::Conjunction( - self.token.span, - ), - }); - (AssocOp::Binary(BinOpKind::And), span) - } - (None, Some((Ident { name: sym::or, span }, IdentIsRaw::No))) if self.may_recover() => { - self.dcx().emit_err(crate::diagnostics::InvalidLogicalOperator { - span: self.token.span, - incorrect: "or".into(), - sub: crate::diagnostics::InvalidLogicalOperatorSub::Disjunction( - self.token.span, - ), - }); - (AssocOp::Binary(BinOpKind::Or), span) - } - _ => return None, - }; - Some(respan(span, op)) + let op = AssocOp::from_token(&self.token); + + // When parsing const expressions, stop parsing when encountering `>`. + if self.restrictions.contains(Restrictions::CONST_EXPR) + && let Some(op) = op + && let AssocOp::Binary(BinOpKind::Shr | BinOpKind::Gt | BinOpKind::Ge) + | AssocOp::AssignOp(AssignOpKind::ShrAssign) = op + { + return None; + } + + // When recovering patterns as expressions, stop parsing when encountering an + // assignment `=`, an alternative `|`, or a range `..`. + if self.restrictions.contains(Restrictions::IS_PAT) + && let Some(op) = op + && let AssocOp::Assign + | AssocOp::AssignOp(_) + | AssocOp::Binary(BinOpKind::BitOr) + | AssocOp::Range(_) = op + { + return None; + } + + if let Some(op) = op { + return Some(respan(self.token.span, op)); + } + + self.recover_from_alpha_logic_op() } /// Checks if this expression is a successfully parsed statement. diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index 18dd6dba13eb5..4b9e288f3ec1b 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -1,12 +1,35 @@ use rustc_ast::util::parser::AssocOp; use rustc_ast::{BinOpKind, Expr, ExprKind, token}; use rustc_errors::{Applicability, Diag, PResult}; -use rustc_span::{Span, Spanned}; +use rustc_span::{Span, Spanned, respan, sym}; use crate::diagnostics; use crate::parser::Parser; impl<'a> Parser<'a> { + /// Recover from alphabetic logic operators `and` and `or` as found in e.g., Python and PHP. + pub(super) fn recover_from_alpha_logic_op(&self) -> Option> { + if self.may_recover() + && let Some((ident, token::IdentIsRaw::No)) = self.token.ident() + { + let (op, sub): (_, fn(_) -> _) = match ident.name { + sym::and => (BinOpKind::And, diagnostics::InvalidLogicalOperatorSub::Conjunction), + sym::or => (BinOpKind::Or, diagnostics::InvalidLogicalOperatorSub::Disjunction), + _ => return None, + }; + + self.dcx().emit_err(diagnostics::InvalidLogicalOperator { + span: self.token.span, + incorrect: ident.name, + sub: sub(self.token.span), + }); + + Some(respan(self.token.span, AssocOp::Binary(op))) + } else { + None + } + } + /// Reject `...` being used as an expression operator. pub(super) fn reject_dotdotdot_expr_op(&self) { if self.token == token::DotDotDot { From 28158721a2f166c635a091b88f09650e3f28da57 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Fri, 11 Sep 2026 10:24:51 +0200 Subject: [PATCH 0352/1309] Don't mistake `<->` for `<>` Previously we would check if the current operator was `Binary(Lt)` and the current token was `>` to determine if we're looking at `<>`. However, since `AssocOp::from_token` also treats `<-` as `Binary(Lt)` for better error recovery, the condition would also hold for `<->` (`<-`, `>`) which is not what we want. E.g., given `1 <-> 2` we would previously emit diagnostic "invalid comparison operator `<>`". --- Also update `recover_from_spaceship_cmp_op` to do something similar -- not to fix anything but simply to eliminate param `op: Spanned`. --- compiler/rustc_parse/src/parser/expr.rs | 4 ++-- .../rustc_parse/src/parser/expr/diagnostics.rs | 14 ++++++-------- 2 files changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 148e49d803875..58e98a64b5e41 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -179,8 +179,8 @@ impl<'a> Parser<'a> { } self.recover_from_strict_eq_op(op); - self.recover_from_diamond_ne_op(op); - self.recover_from_spaceship_cmp_op(op); + self.recover_from_diamond_ne_op(); + self.recover_from_spaceship_cmp_op(); self.recover_from_postfix_inc_op(&lhs, starts_stmt)?; self.recover_from_postfix_dec_op(&lhs, starts_stmt)?; diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index 4b9e288f3ec1b..707ae5d34bc75 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -67,12 +67,11 @@ impl<'a> Parser<'a> { } /// Recover from inequality operator `<>` ("diamond") as found in e.g., PHP. - pub(super) fn recover_from_diamond_ne_op(&mut self, op: Spanned) { - if op.node == AssocOp::Binary(BinOpKind::Lt) - && self.token == token::Gt + pub(super) fn recover_from_diamond_ne_op(&mut self) { + if let (token::Lt, token::Gt) = (self.prev_token.kind, self.token.kind) && self.prev_token.span.hi() == self.token.span.lo() { - let sp = op.span.to(self.token.span); + let sp = self.prev_token.span.to(self.token.span); self.dcx().emit_err(diagnostics::InvalidComparisonOperator { span: sp, invalid: "<>".into(), @@ -87,12 +86,11 @@ impl<'a> Parser<'a> { } /// Recover from comparison operator `<=>` ("spaceship") as found in e.g., C++. - pub(super) fn recover_from_spaceship_cmp_op(&mut self, op: Spanned) { - if op.node == AssocOp::Binary(BinOpKind::Le) - && self.token == token::Gt + pub(super) fn recover_from_spaceship_cmp_op(&mut self) { + if let (token::Le, token::Gt) = (self.prev_token.kind, self.token.kind) && self.prev_token.span.hi() == self.token.span.lo() { - let sp = op.span.to(self.token.span); + let sp = self.prev_token.span.to(self.token.span); self.dcx().emit_err(diagnostics::InvalidComparisonOperator { span: sp, invalid: "<=>".into(), From 963006502518be041b7c7275d8880a13e49d0b8f Mon Sep 17 00:00:00 2001 From: xonx <119700621+xonx4l@users.noreply.github.com> Date: Fri, 18 Sep 2026 15:40:55 +0000 Subject: [PATCH 0353/1309] fix quadratic naming of duplicate sidebar links --- src/librustdoc/html/render/sidebar.rs | 35 ++++++++++++------- .../deref/sidebar-links-deref-chain.rs | 21 +++++++++++ 2 files changed, 44 insertions(+), 12 deletions(-) create mode 100644 tests/rustdoc-html/deref/sidebar-links-deref-chain.rs diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 6fa033f927c85..95cc1c88902e2 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -3,7 +3,7 @@ use std::cmp::Ordering; use std::fmt; use askama::Template; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{DefIdMap, DefIdSet}; use rustc_middle::ty::TyCtxt; @@ -442,7 +442,7 @@ fn sidebar_assoc_items<'a>( let mut assoc_fns = Vec::new(); let mut methods = Vec::new(); if let Some(v) = cache.impls.get(&did) { - let mut used_links = FxHashSet::default(); + let mut used_links = UsedLinks::default(); let mut id_map = IdMap::new(); { @@ -524,7 +524,7 @@ fn sidebar_deref_methods<'a>( impl_: &Impl, v: &[Impl], derefs: &mut DefIdSet, - used_links: &mut FxHashSet, + used_links: &mut UsedLinks, deref_id_map: &'a DefIdMap, ) { let c = cx.cache(); @@ -745,15 +745,26 @@ fn sidebar_render_assoc_items( ]); } -fn get_next_url(used_links: &mut FxHashSet, url: String) -> String { - if used_links.insert(url.clone()) { +/// Tracks sidebar link anchors so duplicates get unique names. +#[derive(Default)] +struct UsedLinks { + links: FxHashSet, + /// Next number to try for each anchor. + next_suffix: FxHashMap, +} + +fn get_next_url(used_links: &mut UsedLinks, url: String) -> String { + if used_links.links.insert(url.clone()) { return url; } - let mut add = 1; - while !used_links.insert(format!("{url}-{add}")) { - add += 1; + let add = used_links.next_suffix.entry(url.clone()).or_insert(1); + loop { + let candidate = format!("{url}-{add}"); + *add += 1; + if used_links.links.insert(candidate.clone()) { + return candidate; + } } - format!("{url}-{add}") } enum GetMethodsMode<'r, 'l> { @@ -764,7 +775,7 @@ enum GetMethodsMode<'r, 'l> { fn get_methods<'a>( i: &'a clean::Impl, mut mode: GetMethodsMode<'_, 'a>, - used_links: &mut FxHashSet, + used_links: &mut UsedLinks, tcx: TyCtxt<'_>, ) -> impl Iterator> { i.items.iter().filter_map(move |item| { @@ -802,7 +813,7 @@ fn get_methods<'a>( fn get_associated_constants<'a>( i: &'a clean::Impl, - used_links: &mut FxHashSet, + used_links: &mut UsedLinks, ) -> impl Iterator> { i.items.iter().filter_map(|item| { if let Some(ref name) = item.name @@ -820,7 +831,7 @@ fn get_associated_constants<'a>( fn get_associated_types<'a>( i: &'a clean::Impl, - used_links: &mut FxHashSet, + used_links: &mut UsedLinks, ) -> impl Iterator> { i.items.iter().filter_map(|item| { if let Some(ref name) = item.name diff --git a/tests/rustdoc-html/deref/sidebar-links-deref-chain.rs b/tests/rustdoc-html/deref/sidebar-links-deref-chain.rs new file mode 100644 index 0000000000000..2b67228f5de30 --- /dev/null +++ b/tests/rustdoc-html/deref/sidebar-links-deref-chain.rs @@ -0,0 +1,21 @@ +// Regression test for . +#![crate_name = "foo"] + +pub struct S0; +pub struct S1; +pub struct S2; +pub struct S3; + +impl S0 { pub fn foo(&self) {} } +impl S1 { pub fn foo(&self) {} } +impl S2 { pub fn foo(&self) {} } +impl S3 { pub fn foo(&self) {} } + +impl std::ops::Deref for S0 { type Target = S1; fn deref(&self) -> &S1 { &S1 } } +impl std::ops::Deref for S1 { type Target = S2; fn deref(&self) -> &S2 { &S2 } } +impl std::ops::Deref for S2 { type Target = S3; fn deref(&self) -> &S3 { &S3 } } + +//@ has foo/struct.S0.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.foo"]' 'foo' +//@ has foo/struct.S0.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.foo-1"]' 'foo' +//@ has foo/struct.S0.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.foo-2"]' 'foo' +//@ has foo/struct.S0.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.foo-3"]' 'foo' From 06c5f7d7506bd70f58cf781949947ad4c03f1927 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 18 Sep 2026 17:39:44 +0200 Subject: [PATCH 0354/1309] add custom test runner test --- tests/pretty/custom-test-runner.pp | 33 ++++++++++++++++++++++++++++++ tests/pretty/custom-test-runner.rs | 25 ++++++++++++++++++++++ 2 files changed, 58 insertions(+) create mode 100644 tests/pretty/custom-test-runner.pp create mode 100644 tests/pretty/custom-test-runner.rs diff --git a/tests/pretty/custom-test-runner.pp b/tests/pretty/custom-test-runner.pp new file mode 100644 index 0000000000000..dc777e37e3041 --- /dev/null +++ b/tests/pretty/custom-test-runner.pp @@ -0,0 +1,33 @@ +#![feature(prelude_import)] +#![no_std] +//@ compile-flags: --crate-type=lib --test --remap-path-prefix={{src-base}}/=/the/src/ --remap-path-prefix={{src-base}}\=/the/src/ +//@ pretty-compare-only +//@ pretty-mode:expanded +//@ pp-exact:custom-test-runner.pp + +// Example taken from the unstable book. + +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] +extern crate std; +#[prelude_import] +use ::std::prelude::rust_2015::*; + +fn my_runner(tests: &[&i32]) { + for t in tests { + if **t == 0 { + + + { ::std::io::_print(format_args!("PASSED\n")); }; + } else { { ::std::io::_print(format_args!("FAILED\n")); }; } + } +} +#[rustc_test_marker = "WILL_PASS"] +pub const WILL_PASS: i32 = 0; +#[rustc_test_marker = "WILL_FAIL"] +pub const WILL_FAIL: i32 = 4; +extern crate test; +#[rustc_main] +#[coverage(off)] +#[doc(hidden)] +pub fn main() -> () { my_runner(&[&WILL_FAIL, &WILL_PASS]) } diff --git a/tests/pretty/custom-test-runner.rs b/tests/pretty/custom-test-runner.rs new file mode 100644 index 0000000000000..b0d7360bcd879 --- /dev/null +++ b/tests/pretty/custom-test-runner.rs @@ -0,0 +1,25 @@ +//@ compile-flags: --crate-type=lib --test --remap-path-prefix={{src-base}}/=/the/src/ --remap-path-prefix={{src-base}}\=/the/src/ +//@ pretty-compare-only +//@ pretty-mode:expanded +//@ pp-exact:custom-test-runner.pp + +// Example taken from the unstable book. + +#![feature(custom_test_frameworks)] +#![test_runner(my_runner)] + +fn my_runner(tests: &[&i32]) { + for t in tests { + if **t == 0 { + println!("PASSED"); + } else { + println!("FAILED"); + } + } +} + +#[test_case] +const WILL_PASS: i32 = 0; + +#[test_case] +const WILL_FAIL: i32 = 4; From 95296e6c9628b9d1a5ca6bc107ea4f8e55380c24 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 18 Sep 2026 17:24:19 +0200 Subject: [PATCH 0355/1309] libtest harness: avoid 'extern crate test' with custom runner --- compiler/rustc_builtin_macros/src/test_harness.rs | 7 ++++++- tests/pretty/custom-test-runner.pp | 1 - 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index 677db66530ecb..bd2ea5a3e6696 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -364,7 +364,12 @@ fn add_main(cx: &mut TestCtxt<'_>, c: &mut ast::Crate) { }); // Integrate the new item into existing module structures. - let items = AstFragment::Items(smallvec![test_extern_stmt, main]); + // `extern crate test;` is only needed with the default runner. + let items = AstFragment::Items(if cx.test_runner.is_none() { + smallvec![test_extern_stmt, main] + } else { + smallvec![main] + }); c.items.extend(cx.ext_cx.monotonic_expander().fully_expand_fragment(items).make_items()); } diff --git a/tests/pretty/custom-test-runner.pp b/tests/pretty/custom-test-runner.pp index dc777e37e3041..5965d76bbc8a5 100644 --- a/tests/pretty/custom-test-runner.pp +++ b/tests/pretty/custom-test-runner.pp @@ -26,7 +26,6 @@ pub const WILL_PASS: i32 = 0; #[rustc_test_marker = "WILL_FAIL"] pub const WILL_FAIL: i32 = 4; -extern crate test; #[rustc_main] #[coverage(off)] #[doc(hidden)] From c99166fac95d61cfd29987ba10b52a54567084ee Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 19:43:46 +0200 Subject: [PATCH 0356/1309] Revert "improve tests/ecosystem-test-jobs/fuchsia.md" This reverts commit 0bb5cd0fb339d3d1765af05fc1411a5742cb9d12. --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index edbb3b93a0808..124e8dfcda18d 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -47,7 +47,7 @@ The main reason you would want to build Fuchsia locally is because you need to investigate a regression. After running a Docker build, you'll find the Fuchsia checkout inside the `obj/fuchsia` directory of your Rust checkout. -If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to + If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build command above. This will reuse all the build results from before. @@ -70,11 +70,11 @@ There are a few `fx` subcommands that are relevant, including: - `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. - `fx build` builds the Fuchsia project using Ninja. It will automatically pick up changes to build arguments and rerun GN. - By default, it builds everything, + By default it builds everything, but it also accepts target paths to build specific targets (see below). - `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this in the Rust CI build to avoid running codegen on most Rust targets. - Underneath, it invokes Ninja, just like `fx build`. + Underneath it invokes Ninja, just like `fx build`. The clippy results are saved in json files inside the build output directory before being printed. @@ -135,7 +135,7 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will rebuild all the Rust targets. -This can be done in a text editor, and the contents of the string do not matter, +This can be done in a text editor and the contents of the string do not matter, as long as it changes from one build to the next. [build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. @@ -145,7 +145,7 @@ The Fuchsia website has more detailed documentation of the [build system]. When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` command after the initial run so it won't rerun GN each time. -If you do this, you can also comment out the version_string line to save a few seconds. +If you do this you can also comment out the version_string line to save a couple seconds. `export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. From 2e95aa2091c588e5d487faa3e3df925ed68a5f79 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 19:44:08 +0200 Subject: [PATCH 0357/1309] Revert "sembr src/tests/ecosystem-test-jobs/fuchsia.md" This reverts commit fcfdbf39d50bf291f24b55ce4d3d80939f4f7f37. --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 98 ++++++++++--------- 1 file changed, 50 insertions(+), 48 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 124e8dfcda18d..75cf782a77025 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -14,7 +14,8 @@ Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. ## Building Fuchsia in CI -Fuchsia builds as part of the suite of bors tests that run before a pull request is merged. +Fuchsia builds as part of the suite of bors tests that run before a pull request +is merged. If you are worried that a pull request might break the Fuchsia builder and want to test it out before submitting it to the bors queue, simply ask bors to run @@ -22,13 +23,13 @@ the try job that builds the Fuchsia integration: `@bors try jobs=x86_64-fuchsia` ## Building Fuchsia locally -Because Fuchsia uses languages other than Rust, it does not use Cargo as a build system. -It also requires the toolchain build to be configured in a [certain way][build-toolchain]. +Because Fuchsia uses languages other than Rust, it does not use Cargo as a build +system. It also requires the toolchain build to be configured in a [certain +way][build-toolchain]. The recommended way to build Fuchsia is to use the Docker scripts that check out -and run a Fuchsia build for you. -If you've run Docker tests before, -you can simply run this command from your Rust checkout to download and build Fuchsia +and run a Fuchsia build for you. If you've run Docker tests before, you can +simply run this command from your Rust checkout to download and build Fuchsia using your local Rust toolchain. ``` @@ -39,19 +40,20 @@ See the [Testing with Docker](../docker.md) chapter for more details on how to r and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and -build takes 46G of space – and as you might imagine, it takes a while to complete. +build takes 46G of space – and as you might imagine, it takes a while to +complete. ### Modifying the Fuchsia checkout The main reason you would want to build Fuchsia locally is because you need to -investigate a regression. -After running a Docker build, -you'll find the Fuchsia checkout inside the `obj/fuchsia` directory of your Rust checkout. - If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to -`KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build command above. -This will reuse all the build results from before. +investigate a regression. After running a Docker build, you'll find the Fuchsia +checkout inside the `obj/fuchsia` directory of your Rust checkout. If you +modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to +`KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build +command above. This will reuse all the build results from before. -You can find more options to customize the Fuchsia checkout in the [build-fuchsia.sh] script. +You can find more options to customize the Fuchsia checkout in the +[build-fuchsia.sh] script. ### Customizing the Fuchsia build @@ -67,15 +69,14 @@ to add this to your `$PATH` for some workflows. There are a few `fx` subcommands that are relevant, including: -- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. -- `fx build` builds the Fuchsia project using Ninja. - It will automatically pick up changes to build arguments and rerun GN. - By default it builds everything, +- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and + runs GN. +- `fx build` builds the Fuchsia project using Ninja. It will automatically pick + up changes to build arguments and rerun GN. By default it builds everything, but it also accepts target paths to build specific targets (see below). -- `fx clippy` runs Clippy on specific Rust targets (or all of them). - We use this in the Rust CI build to avoid running codegen on most Rust targets. - Underneath it invokes Ninja, just like `fx build`. - The clippy results are saved in json +- `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this + in the Rust CI build to avoid running codegen on most Rust targets. Underneath + it invokes Ninja, just like `fx build`. The clippy results are saved in json files inside the build output directory before being printed. #### Target paths @@ -86,20 +87,20 @@ GN uses paths like the following to identify build targets: //src/starnix/kernel:starnix_core ``` -The initial `//` means the root of the checkout, and the remaining slashes are directory names. -The string after `:` is the _target name_ of a target defined +The initial `//` means the root of the checkout, and the remaining slashes are +directory names. The string after `:` is the _target name_ of a target defined in the `BUILD.gn` file of that directory. -The target name can be omitted if it is the same as the directory name. -In other words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. +The target name can be omitted if it is the same as the directory name. In other +words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. These target paths are used inside `BUILD.gn` files to reference dependencies, and can also be used in `fx build`. #### Modifying compiler flags -You can put custom compiler flags inside a GN `config` that is added to a target. -As a simple example: +You can put custom compiler flags inside a GN `config` that is added to a +target. As a simple example: ``` config("everybody_loops") { @@ -113,20 +114,20 @@ rustc_binary("example") { } ``` -This will add the flag `-Zeverybody-loops` to rustc when building the `example` target. -Note that you can also use [`public_configs`] for a config to be added +This will add the flag `-Zeverybody-loops` to rustc when building the `example` +target. Note that you can also use [`public_configs`] for a config to be added to every target that depends on that target. -If you want to add a flag to every Rust target in the build, -you can add rustflags to the [`//build/config:compiler`] config or to the OS-specific -configs referenced in that file. -Note that `cflags` and `ldflags` are ignored on Rust targets. +If you want to add a flag to every Rust target in the build, you can add +rustflags to the [`//build/config:compiler`] config or to the OS-specific +configs referenced in that file. Note that `cflags` and `ldflags` are ignored on +Rust targets. #### Running ninja and rustc commands directly -Going down one layer, `fx build` invokes `ninja`, which in turn eventually invokes `rustc`. -All build actions are run inside the out directory, -which is usually `out/default` inside the Fuchsia checkout. +Going down one layer, `fx build` invokes `ninja`, which in turn eventually +invokes `rustc`. All build actions are run inside the out directory, which is +usually `out/default` inside the Fuchsia checkout. You can get ninja to print the actual command it invokes by forcing that command to fail, e.g. by adding a syntax error to one of the source files of the target. @@ -134,25 +135,26 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will -rebuild all the Rust targets. -This can be done in a text editor and the contents of the string do not matter, -as long as it changes from one build to the next. -[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. +rebuild all the Rust targets. This can be done in a text editor and the contents +of the string do not matter, as long as it changes from one build to the next. +[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain +directory. The Fuchsia website has more detailed documentation of the [build system]. #### Other tips and tricks When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` -command after the initial run so it won't rerun GN each time. -If you do this you can also comment out the version_string line to save a couple seconds. +command after the initial run so it won't rerun GN each time. If you do this you +can also comment out the version_string line to save a couple seconds. -`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. +`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the +initial build. ## Fuchsia target support -To learn more about Fuchsia target support, -see the Fuchsia chapter in [the rustc book][platform-support]. +To learn more about Fuchsia target support, see the Fuchsia chapter in [the +rustc book][platform-support]. [regressions]: https://gist.github.com/tmandry/7103eba4bd6a6fb0c439b5a90ae355fa [build-toolchain]: https://fuchsia.dev/fuchsia-src/development/build/rust_toolchain @@ -167,5 +169,5 @@ see the Fuchsia chapter in [the rustc book][platform-support]. [fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust -code and a roughly equal amount of third-party code, -as counted by tokei (excluding comments and blanks). +code and a roughly equal amount of third-party code, as counted by tokei +(excluding comments and blanks). From cec94799dc959aea3b6bccde4fa8bbb9fbad0129 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Fri, 18 Sep 2026 17:49:10 +0000 Subject: [PATCH 0358/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 420ed2a0c3d7225b1744266fd884d431b4d8cfe0. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 7c357c0e50e54..1c3d6e0224718 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -c999cef531ea9059e189e82fe0e82c5daf249bc9 +420ed2a0c3d7225b1744266fd884d431b4d8cfe0 From 68638387ab79e7dc44623a3e1b029763c35fb1bd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 19:53:49 +0200 Subject: [PATCH 0359/1309] improve closure.md --- src/doc/rustc-dev-guide/src/closure.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/closure.md b/src/doc/rustc-dev-guide/src/closure.md index 33206ed885bc5..81bddd73caba7 100644 --- a/src/doc/rustc-dev-guide/src/closure.md +++ b/src/doc/rustc-dev-guide/src/closure.md @@ -130,11 +130,11 @@ It borrows these upvars from its surrounding context; therefore the compiler has to determine the upvar's borrow type. The compiler starts with assigning an immutable borrow type and lowers the restriction (that is, changes it from **immutable** to **mutable** to **move**) as needed, based on the usage. -In the Example 1 above, the -closure only uses the variable for printing but does not modify it in any way and therefore, in the -`mir_dump`, we find the borrow type for the upvar `x` to be immutable. - In example 2, however, the closure modifies `x` and increments it by some value. - Because of this mutation, the compiler, which +In the Example 1 above, +the closure only uses the variable for printing but does not modify it in any way and therefore, +in the `mir_dump`, we find the borrow type for the upvar `x` to be immutable. +In example 2, however, the closure modifies `x` and increments it by some value. +Because of this mutation, the compiler, which started off assigning `x` as an immutable reference type, has to adjust it as a mutable reference. Likewise in the third example, the closure drops the vector and therefore this requires the variable `x` to be moved into the closure. From b8c15ce19e5154dddc6d1fbea1dd616d01a7a0d0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 19:51:47 +0200 Subject: [PATCH 0360/1309] sembr src/tests/ecosystem-test-jobs/fuchsia.md --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 104 +++++++++--------- 1 file changed, 52 insertions(+), 52 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 3f274464c6e63..7fe06572650ad 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -14,12 +14,11 @@ Please contact the [fuchsia][fuchsia-ping] ping group and ask them for help. ## Building Fuchsia in CI -Fuchsia builds as part of the suite of bors tests that run before a pull request -is merged. +Fuchsia builds as part of the suite of bors tests that run before a pull request is merged. If you are worried that a pull request might break the Fuchsia builder and want -to test it out before submitting it to the bors queue, simply ask bors to run -the try job that builds the Fuchsia integration: +to test it out before submitting it to the bors queue, +simply ask bors to run the try job that builds the Fuchsia integration: ```text @bors try jobs=test-x86_64-fuchsia @@ -27,13 +26,13 @@ the try job that builds the Fuchsia integration: ## Building Fuchsia locally -Because Fuchsia uses languages other than Rust, it does not use Cargo as a build -system. It also requires the toolchain build to be configured in a [certain -way][build-toolchain]. +Because Fuchsia uses languages other than Rust, it does not use Cargo as a build system. +It also requires the toolchain build to be configured in a [certain way][build-toolchain]. The recommended way to build Fuchsia is to use the Docker scripts that check out -and run a Fuchsia build for you. If you've run Docker tests before, you can -simply run this command from your Rust checkout to download and build Fuchsia +and run a Fuchsia build for you. +If you've run Docker tests before, +you can simply run this command from your Rust checkout to download and build Fuchsia using your local Rust toolchain. ``` @@ -44,20 +43,21 @@ See the [Testing with Docker](../docker.md) chapter for more details on how to r and debug jobs with Docker. Note that a Fuchsia checkout is *large* – as of this writing, a checkout and -build takes over 67G of space – and as you might imagine, it takes a while to -complete. +build takes over 67G of space – and as you might imagine, it takes a while to complete. ### Modifying the Fuchsia checkout The main reason you would want to build Fuchsia locally is because you need to -investigate a regression. After running a Docker build, you'll find the Fuchsia -checkout inside the `obj/test-x86_64-fuchsia/fuchsia` directory of your Rust -checkout. If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] -script to `KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun -the build command above. This will reuse all the build results from before. +investigate a regression. +After running a Docker build, +you'll find the Fuchsia checkout inside the `obj/test-x86_64-fuchsia/fuchsia` directory of your Rust +checkout. + If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, +you can change the checkout as needed and rerun +the build command above. +This will reuse all the build results from before. -You can find more options to customize the Fuchsia checkout in the -[build-fuchsia.sh] script. +You can find more options to customize the Fuchsia checkout in the [build-fuchsia.sh] script. ### Customizing the Fuchsia build @@ -73,14 +73,15 @@ to add this to your `$PATH` for some workflows. There are a few `fx` subcommands that are relevant, including: -- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and - runs GN. -- `fx build` builds the Fuchsia project using Ninja. It will automatically pick - up changes to build arguments and rerun GN. By default it builds everything, +- `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. +- `fx build` builds the Fuchsia project using Ninja. + It will automatically pick up changes to build arguments and rerun GN. + By default it builds everything, but it also accepts target paths to build specific targets (see below). -- `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this - in the Rust CI build to avoid running codegen on most Rust targets. Underneath - it invokes Ninja, just like `fx build`. The clippy results are saved in json +- `fx clippy` runs Clippy on specific Rust targets (or all of them). + We use this in the Rust CI build to avoid running codegen on most Rust targets. + Underneath it invokes Ninja, just like `fx build`. + The clippy results are saved in json files inside the build output directory before being printed. #### Target paths @@ -91,20 +92,20 @@ GN uses paths like the following to identify build targets: //src/starnix/kernel:starnix_core ``` -The initial `//` means the root of the checkout, and the remaining slashes are -directory names. The string after `:` is the _target name_ of a target defined +The initial `//` means the root of the checkout, and the remaining slashes are directory names. +The string after `:` is the _target name_ of a target defined in the `BUILD.gn` file of that directory. -The target name can be omitted if it is the same as the directory name. In other -words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. +The target name can be omitted if it is the same as the directory name. +In other words, `//src/starnix/kernel` is the same as `//src/starnix/kernel:kernel`. These target paths are used inside `BUILD.gn` files to reference dependencies, and can also be used in `fx build`. #### Modifying compiler flags -You can put custom compiler flags inside a GN `config` that is added to a -target. As a simple example: +You can put custom compiler flags inside a GN `config` that is added to a target. +As a simple example: ``` config("everybody_loops") { @@ -118,20 +119,20 @@ rustc_binary("example") { } ``` -This will add the flag `-Zeverybody-loops` to rustc when building the `example` -target. Note that you can also use [`public_configs`] for a config to be added +This will add the flag `-Zeverybody-loops` to rustc when building the `example` target. +Note that you can also use [`public_configs`] for a config to be added to every target that depends on that target. -If you want to add a flag to every Rust target in the build, you can add -rustflags to the [`//build/config:compiler`] config or to the OS-specific -configs referenced in that file. Note that `cflags` and `ldflags` are ignored on -Rust targets. +If you want to add a flag to every Rust target in the build, +you can add rustflags to the [`//build/config:compiler`] config or to the OS-specific +configs referenced in that file. +Note that `cflags` and `ldflags` are ignored on Rust targets. #### Running ninja and rustc commands directly -Going down one layer, `fx build` invokes `ninja`, which in turn eventually -invokes `rustc`. All build actions are run inside the out directory, which is -usually `out/default` inside the Fuchsia checkout. +Going down one layer, `fx build` invokes `ninja`, which in turn eventually invokes `rustc`. +All build actions are run inside the out directory, +which is usually `out/default` inside the Fuchsia checkout. You can get ninja to print the actual command it invokes by forcing that command to fail, e.g. by adding a syntax error to one of the source files of the target. @@ -139,26 +140,25 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will -rebuild all the Rust targets. This can be done in a text editor and the contents -of the string do not matter, as long as it changes from one build to the next. -[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain -directory. +rebuild all the Rust targets. +This can be done in a text editor and the contents of the string do not matter, +as long as it changes from one build to the next. +[build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. The Fuchsia website has more detailed documentation of the [build system]. #### Other tips and tricks When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` -command after the initial run so it won't rerun GN each time. If you do this you -can also comment out the version_string line to save a couple seconds. +command after the initial run so it won't rerun GN each time. +If you do this you can also comment out the version_string line to save a couple seconds. -`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the -initial build. +`export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. ## Fuchsia target support -To learn more about Fuchsia target support, see the Fuchsia chapter in [the -rustc book][platform-support]. +To learn more about Fuchsia target support, +see the Fuchsia chapter in [the rustc book][platform-support]. [regressions]: https://gist.github.com/tmandry/7103eba4bd6a6fb0c439b5a90ae355fa [build-toolchain]: https://fuchsia.dev/fuchsia-src/development/build/rust_toolchain @@ -173,5 +173,5 @@ rustc book][platform-support]. [fuchsia-ping]: ../../notification-groups/fuchsia.md [^loc]: As of June 2024, Fuchsia had about 2 million lines of first-party Rust -code and a roughly equal amount of third-party code, as counted by tokei -(excluding comments and blanks). +code and a roughly equal amount of third-party code, +as counted by tokei (excluding comments and blanks). From d9d1b3e6ed9ebfd6a2b4a7199afa42e9a35ef11a Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 18 Sep 2026 19:59:47 +0200 Subject: [PATCH 0361/1309] improve tests/ecosystem-test-jobs/fuchsia.md --- .../src/tests/ecosystem-test-jobs/fuchsia.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index 7fe06572650ad..ca7a9f482f1ae 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -52,7 +52,7 @@ investigate a regression. After running a Docker build, you'll find the Fuchsia checkout inside the `obj/test-x86_64-fuchsia/fuchsia` directory of your Rust checkout. - If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, +If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, you can change the checkout as needed and rerun the build command above. This will reuse all the build results from before. @@ -76,11 +76,11 @@ There are a few `fx` subcommands that are relevant, including: - `fx set` accepts build arguments, writes them to `out/default/args.gn`, and runs GN. - `fx build` builds the Fuchsia project using Ninja. It will automatically pick up changes to build arguments and rerun GN. - By default it builds everything, + By default, it builds everything, but it also accepts target paths to build specific targets (see below). - `fx clippy` runs Clippy on specific Rust targets (or all of them). We use this in the Rust CI build to avoid running codegen on most Rust targets. - Underneath it invokes Ninja, just like `fx build`. + Underneath, it invokes Ninja, just like `fx build`. The clippy results are saved in json files inside the build output directory before being printed. @@ -141,7 +141,7 @@ Once you have the command, you can run it from inside the output directory. After changing the toolchain itself, the build setting `rustc_version_string` in `out/default/args.gn` needs to be changed so that `fx build` or `ninja` will rebuild all the Rust targets. -This can be done in a text editor and the contents of the string do not matter, +This can be done in a text editor, and the contents of the string do not matter, as long as it changes from one build to the next. [build_fuchsia_from_rust_ci.sh] does this for you by hashing the toolchain directory. @@ -151,7 +151,7 @@ The Fuchsia website has more detailed documentation of the [build system]. When using `build_fuchsia_from_rust_ci.sh` you can comment out the `fx set` command after the initial run so it won't rerun GN each time. -If you do this you can also comment out the version_string line to save a couple seconds. +If you do this, you can also comment out the version_string line to save a couple seconds. `export NINJA_PERSISTENT_MODE=1` to get faster ninja startup times after the initial build. From b7bad07da0564a861c8ffcbeb290d4409f5cb937 Mon Sep 17 00:00:00 2001 From: beetrees Date: Tue, 25 Aug 2026 18:26:24 +0100 Subject: [PATCH 0362/1309] Add Natvis visualiser and debuginfo tests for `f128` --- .../src/debuginfo/metadata.rs | 101 ++++++++-------- src/etc/lldb_lookup.py | 17 +++ src/etc/lldb_providers.py | 6 + src/etc/natvis/intrinsic.natvis | 112 ++++++++++++++++++ .../debuginfo/basic-types-globals-metadata.rs | 10 +- tests/debuginfo/basic-types-globals.rs | 24 +++- tests/debuginfo/basic-types-metadata.rs | 4 +- tests/debuginfo/basic-types-mut-globals.rs | 96 +++++++++++++-- tests/debuginfo/basic-types/main.rs | 13 +- tests/debuginfo/borrowed-basic.rs | 17 ++- tests/debuginfo/borrowed-unique-basic.rs | 17 ++- tests/debuginfo/f128-natvis.rs | 92 ++++++++++++++ tests/debuginfo/reference-debuginfo.rs | 18 ++- 13 files changed, 447 insertions(+), 80 deletions(-) create mode 100644 tests/debuginfo/f128-natvis.rs diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 54bdfb5f442d9..53fe51e382e4e 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -5,7 +5,7 @@ use std::path::PathBuf; use std::{assert_matches, iter, ptr}; use libc::{c_longlong, c_uint}; -use rustc_abi::{Align, Layout, NumScalableVectors, Size}; +use rustc_abi::{Align, Endian, Layout, NumScalableVectors, Size}; use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginfo}; use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; @@ -20,7 +20,7 @@ use rustc_middle::ty::{ use rustc_session::config::{self, DebugInfo, Lto}; use rustc_span::{DUMMY_SP, FileName, RemapPathScopeComponents, SourceFile, Span, Symbol, hygiene}; use rustc_symbol_mangling::typeid_for_trait_ref; -use rustc_target::spec::{Arch, DebuginfoKind}; +use rustc_target::spec::{Arch, DebuginfoKind, HasTargetSpec}; use smallvec::smallvec; use tracing::{debug, instrument}; @@ -692,33 +692,22 @@ impl MsvcBasicName for ty::UintTy { } } -impl MsvcBasicName for ty::FloatTy { - fn msvc_basic_name(self) -> &'static str { - // FIXME(f128): `f128` has no MSVC representation. We could improve the debuginfo. - // See: - match self { - ty::FloatTy::F16 => { - bug!("`f16` should have been handled in `build_basic_type_di_node`") - } - ty::FloatTy::F32 => "float", - ty::FloatTy::F64 => "double", - ty::FloatTy::F128 => "fp128", - } - } -} - -fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreationResult<'ll> { - // MSVC has no native support for `f16`. Instead, emit `struct f16 { bits: u16 }` to allow the - // `f16`'s value to be displayed using a Natvis visualiser in `intrinsic.natvis`. - let float_ty = cx.tcx.types.f16; - let bits_ty = cx.tcx.types.u16; - let def_location = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { - match float_ty.kind() { - ty::Adt(def, _) => Some(file_metadata_from_def_id(cx, Some(def.did()))), - _ => None, - } +/// `float_ty` must be a [`ty::Float`] and `bits_ty` must be a [`ty::Uint`]. +/// `cx.size_of(bits_ty) * bits_names.len()` must equal `cx.size_of(float_ty)`. +fn build_cpp_float_struct_di_node<'ll, 'tcx>( + cx: &CodegenCx<'ll, 'tcx>, + float_ty: Ty<'tcx>, + bits_ty: Ty<'tcx>, + bits_names: &[&str], +) -> DINodeCreationResult<'ll> { + debug_assert!(matches!(bits_ty.kind(), ty::Uint(_))); + debug_assert_eq!(cx.size_of(bits_ty) * (bits_names.len() as u64), cx.size_of(float_ty)); + // MSVC has no native support for `f16` or `f128`. Instead, emit a struct containing the bits as + // field(s) to allow the value to be displayed using a Natvis visualiser in `intrinsic.natvis`. + let name = if let ty::Float(f) = float_ty.kind() { + f.name_str() } else { - None + bug!("{float_ty:?} was not a float"); }; type_map::build_type_with_children( cx, @@ -726,32 +715,33 @@ fn build_cpp_f16_di_node<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>) -> DINodeCreation cx, Stub::Struct, UniqueTypeId::for_ty(cx.tcx, float_ty), - "f16", - def_location, + name, + None, cx.size_and_align_of(float_ty), NO_SCOPE_METADATA, DIFlags::FlagZero, ), // Fields: |cx, float_di_node| { - let def_id = if cx.sess().opts.unstable_opts.debug_info_type_line_numbers { - match bits_ty.kind() { - ty::Adt(def, _) => Some(def.did()), - _ => None, - } - } else { - None - }; - smallvec![build_field_di_node( - cx, - float_di_node, - "bits", - cx.layout_of(bits_ty), - Size::ZERO, - DIFlags::FlagZero, - type_di_node(cx, bits_ty), - def_id, - )] + let bits_layout = cx.layout_of(bits_ty); + let bits_node = type_di_node(cx, bits_ty); + bits_names + .iter() + .copied() + .enumerate() + .map(|(i, field_name)| { + build_field_di_node( + cx, + float_di_node, + field_name, + bits_layout, + bits_layout.size * (i as u64), + DIFlags::FlagZero, + bits_node, + None, + ) + }) + .collect() }, NO_GENERICS, ) @@ -783,9 +773,20 @@ fn build_basic_type_di_node<'ll, 'tcx>( ty::Int(int_ty) if cpp_like_debuginfo => (int_ty.msvc_basic_name(), DW_ATE_signed), ty::Uint(uint_ty) if cpp_like_debuginfo => (uint_ty.msvc_basic_name(), DW_ATE_unsigned), ty::Float(ty::FloatTy::F16) if cpp_like_debuginfo => { - return build_cpp_f16_di_node(cx); + return build_cpp_float_struct_di_node(cx, t, cx.tcx.types.u16, &["bits"]); + } + ty::Float(ty::FloatTy::F128) if cpp_like_debuginfo => { + // All MSVC architectures are little endian. + assert_eq!(cx.target_spec().endian, Endian::Little); + return build_cpp_float_struct_di_node( + cx, + t, + cx.tcx.types.u64, + &["low_bits", "high_bits"], + ); } - ty::Float(float_ty) if cpp_like_debuginfo => (float_ty.msvc_basic_name(), DW_ATE_float), + ty::Float(ty::FloatTy::F32) if cpp_like_debuginfo => ("float", DW_ATE_float), + ty::Float(ty::FloatTy::F64) if cpp_like_debuginfo => ("double", DW_ATE_float), ty::Int(int_ty) => (int_ty.name_str(), DW_ATE_signed), ty::Uint(uint_ty) => (uint_ty.name_str(), DW_ATE_unsigned), ty::Float(float_ty) => (float_ty.name_str(), DW_ATE_float), diff --git a/src/etc/lldb_lookup.py b/src/etc/lldb_lookup.py index 365816dc8489a..94ed47af1891f 100644 --- a/src/etc/lldb_lookup.py +++ b/src/etc/lldb_lookup.py @@ -40,6 +40,7 @@ ClangEncodedEnumSummaryProvider, StructSummaryProvider, f16SummaryProvider, + f128SummaryProvider, # re-exports get_template_args as get_template_args, resolve_msvc_template_arg as resolve_msvc_template_arg, @@ -181,6 +182,17 @@ def register_providers_compatibility(): DEFAULT_TYPE_OPTIONS | lldb.eTypeOptionHideChildren, ) + if LLDBFeature.Float128 in FEATURE_FLAGS: + # Force f128 summary on windows-msvc since most Windows debuggers don't support PDB f128 + register_summary( + f128SummaryProvider, + lldb.SBTypeNameSpecifier( + MOD_PREFIX + is_msvc_f128.__name__, + lldb.eFormatterMatchCallback, + ), + DEFAULT_TYPE_OPTIONS | lldb.eTypeOptionHideChildren, + ) + # Tuple-structs register_synth( TupleSyntheticProvider, @@ -501,6 +513,11 @@ def is_msvc_f16(type: lldb.SBType, _dict: LLDBOpaque) -> bool: return type.GetName() == "f16" and type.IsAggregateType() +def is_msvc_f128(type: lldb.SBType, _dict: LLDBOpaque) -> bool: + # Most Windows debuggers don't support PDB f128. + return type.GetName() == "f128" and type.IsAggregateType() + + def classify_rust_type(type: lldb.SBType, is_msvc: bool) -> RustType: if type.IsPointerType(): return RustType.Indirection diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 2791dae3600b0..a3a424ac1abce 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -542,6 +542,12 @@ def f16SummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: ) +def f128SummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: + from lldb import eBasicTypeFloat128 + + return valobj.Cast(valobj.GetTarget().GetBasicType(eBasicTypeFloat128)).GetValue() + + def sequence_formatter(output: str, valobj: SBValue, _dict: LLDBOpaque): length: int = valobj.GetNumChildren() diff --git a/src/etc/natvis/intrinsic.natvis b/src/etc/natvis/intrinsic.natvis index 49e0ce319efac..ac9bf1c427957 100644 --- a/src/etc/natvis/intrinsic.natvis +++ b/src/etc/natvis/intrinsic.natvis @@ -59,6 +59,118 @@ {(float) (sign() * (raw_significand() + 1.0) * two_pow_exponent())} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {sign()}inf + NaN + + {sign()}0x0p+0 + + {sign()}0x1{subnormal_hex()}p{-16382 - subnormal_shift(),d} + {sign()}0x1{normal_hex()}p{normal_exponent_sign()}{normal_exponent(),d} + + + "0x" + hex128(high_bits, low_bits, 128) + + () diff --git a/tests/debuginfo/basic-types-globals-metadata.rs b/tests/debuginfo/basic-types-globals-metadata.rs index 3f1d9fd5de278..f7f3504ae26fa 100644 --- a/tests/debuginfo/basic-types-globals-metadata.rs +++ b/tests/debuginfo/basic-types-globals-metadata.rs @@ -33,11 +33,12 @@ //@ gdb-check:type = f32 //@ gdb-command:whatis basic_types_globals_metadata::F64 //@ gdb-check:type = f64 +// FIXME(f128): gdb doesn't support Rust `f128` yet. //@ gdb-command:continue #![allow(unused_variables)] #![allow(dead_code)] -#![feature(f16)] +#![feature(f16, f128)] // N.B. These are `mut` only so they don't constant fold away. static mut B: bool = false; @@ -55,13 +56,14 @@ static mut U64: u64 = 64; static mut F16: f16 = 1.5; static mut F32: f32 = 2.5; static mut F64: f64 = 3.5; +static mut F128: f128 = 4.5; fn main() { _zzz(); // #break - let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; - // FIXME: Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which - // does not exist on some targets like PowerPC. + let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64, F128) }; + // FIXME(f16): Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which + // does not exist on some targets like PowerPC (fixed in llvm22). // See https://github.com/llvm/llvm-project/issues/97981 and // https://github.com/rust-lang/compiler-builtins/issues/655 let b = unsafe { F16 }; diff --git a/tests/debuginfo/basic-types-globals.rs b/tests/debuginfo/basic-types-globals.rs index 044b757aaf470..3bc9d3becdade 100644 --- a/tests/debuginfo/basic-types-globals.rs +++ b/tests/debuginfo/basic-types-globals.rs @@ -1,11 +1,20 @@ -//@ revisions: lto no-lto +//@ revisions: lto no-lto lto-apple no-lto-apple //@ compile-flags:-g --crate-name=basic_types_globals //@ disable-gdb-pretty-printers +// FIXME(f128): Merge `-apple` revisions once Apple releases Xcode with LLVM 22. +//@ [lto] ignore-apple +//@ [no-lto] ignore-apple +//@ [lto-apple] only-apple +//@ [no-lto-apple] only-apple //@ [lto] compile-flags:-C lto //@ [lto] no-prefer-dynamic +//@ [lto-apple] compile-flags:-C lto +//@ [lto-apple] no-prefer-dynamic //@ ignore-backends: gcc +// `f128` support was added to `lldb` in version 22. +//@ min-llvm-lldb-version: 22 //@ lldb-command:run //@ lldb-command:v basic_types_globals::B @@ -38,6 +47,9 @@ //@ lldb-check:[...]basic_types_globals::F32 = 2.5 //@ lldb-command:v basic_types_globals::F64 //@ lldb-check:[...]basic_types_globals::F64 = 3.5 +//@ lldb-command:v basic_types_globals::F128 +//@[no-lto] lldb-check:[...]basic_types_globals::F128 = 4.5 +//@[lto] lldb-check:[...]basic_types_globals::F128 = 4.5 //@ gdb-command:run //@ gdb-command:print B @@ -70,10 +82,11 @@ //@ gdb-check:$14 = 2.5 //@ gdb-command:print F64 //@ gdb-check:$15 = 3.5 +// FIXME(f128): gdb doesn't support Rust `f128` yet. //@ gdb-command:continue #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] // N.B. These are `mut` only so they don't constant fold away. static mut B: bool = false; @@ -91,13 +104,14 @@ static mut U64: u64 = 64; static mut F16: f16 = 1.5; static mut F32: f32 = 2.5; static mut F64: f64 = 3.5; +static mut F128: f128 = 4.5; fn main() { _zzz(); // #break - let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64) }; - // FIXME: Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which - // does not exist on some targets like PowerPC. + let a = unsafe { (B, I, C, I8, I16, I32, I64, U, U8, U16, U32, U64, F32, F64, F128) }; + // FIXME(f16): Including f16 and f32 in the same tuple emits `__gnu_h2f_ieee`, which + // does not exist on some targets like PowerPC (fixed in llvm22). // See https://github.com/llvm/llvm-project/issues/97981 and // https://github.com/rust-lang/compiler-builtins/issues/655 let b = unsafe { F16 }; diff --git a/tests/debuginfo/basic-types-metadata.rs b/tests/debuginfo/basic-types-metadata.rs index d3a3d03ef7424..7171840077265 100644 --- a/tests/debuginfo/basic-types-metadata.rs +++ b/tests/debuginfo/basic-types-metadata.rs @@ -35,6 +35,7 @@ //@ gdb-check:type = f32 //@ gdb-command:whatis f64 //@ gdb-check:type = f64 +// FIXME(f128): gdb doesn't support Rust `f128` yet. //@ gdb-command:whatis fnptr //@ gdb-check:type = *mut fn () //@ gdb-command:info functions _yyy @@ -54,7 +55,7 @@ //@ gdb-command:continue #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] fn main() { let unit: () = (); @@ -73,6 +74,7 @@ fn main() { let f16: f16 = 1.5; let f32: f32 = 2.5; let f64: f64 = 3.5; + let f128: f128 = 4.5; let fnptr : fn() = _zzz; let closure_0 = || {}; let closure_1 = || { b; }; diff --git a/tests/debuginfo/basic-types-mut-globals.rs b/tests/debuginfo/basic-types-mut-globals.rs index c3cc7be549d47..3f59da2a5d2e0 100644 --- a/tests/debuginfo/basic-types-mut-globals.rs +++ b/tests/debuginfo/basic-types-mut-globals.rs @@ -1,13 +1,14 @@ -// Caveats - gdb prints any 8-bit value (meaning rust I8 and u8 values) -// as its numerical value along with its associated ASCII char, there -// doesn't seem to be any way around this. Also, gdb doesn't know -// about UTF-32 character encoding and will print a rust char as only -// its numerical value. - -//@ compile-flags:-g +//@ compile-flags:-g --crate-name=basic_types_mut_globals //@ disable-gdb-pretty-printers //@ ignore-backends: gcc +// FIXME(f128): Merge `apple` revision once Apple releases Xcode with LLVM 22. +//@ revisions: not-apple apple +//@[not-apple] ignore-apple +//@[apple] only-apple +// `f128` support was added to `lldb` in version 22. +//@ min-llvm-lldb-version: 22 + //@ gdb-command:run // Check initializers @@ -41,6 +42,7 @@ //@ gdb-check:$14 = 2.5 //@ gdb-command:print F64 //@ gdb-check:$15 = 3.5 +// FIXME(f128): gdb doesn't support Rust `f128` yet. //@ gdb-command:continue // Check new values @@ -50,7 +52,7 @@ //@ gdb-check:$17 = 2 //@ gdb-command:print C //@ gdb-check:$18 = 102 'f' -//@ gdb-command:print/d I8 +//@ gdb-command:print I8 //@ gdb-check:$19 = 78 //@ gdb-command:print I16 //@ gdb-check:$20 = -26 @@ -60,7 +62,7 @@ //@ gdb-check:$22 = -54 //@ gdb-command:print U //@ gdb-check:$23 = 5 -//@ gdb-command:print/d U8 +//@ gdb-command:print U8 //@ gdb-check:$24 = 20 //@ gdb-command:print U16 //@ gdb-check:$25 = 32 @@ -74,9 +76,81 @@ //@ gdb-check:$29 = 5.75 //@ gdb-command:print F64 //@ gdb-check:$30 = 9.25 +// FIXME(f128): gdb doesn't support Rust `f128` yet. + +//@ lldb-command:run + +// Check initializers +//@ lldb-command:v basic_types_mut_globals::B +//@ lldb-check:[...]basic_types_mut_globals::B = false +//@ lldb-command:v basic_types_mut_globals::I +//@ lldb-check:[...]basic_types_mut_globals::I = -1 +//@ lldb-command:v basic_types_mut_globals::C +//@ lldb-check:[...]basic_types_mut_globals::C = U+0x00000061 U'a' +//@ lldb-command:v/d basic_types_mut_globals::I8 +//@ lldb-check:[...]basic_types_mut_globals::I8 = 68 +//@ lldb-command:v basic_types_mut_globals::I16 +//@ lldb-check:[...]basic_types_mut_globals::I16 = -16 +//@ lldb-command:v basic_types_mut_globals::I32 +//@ lldb-check:[...]basic_types_mut_globals::I32 = -32 +//@ lldb-command:v basic_types_mut_globals::I64 +//@ lldb-check:[...]basic_types_mut_globals::I64 = -64 +//@ lldb-command:v basic_types_mut_globals::U +//@ lldb-check:[...]basic_types_mut_globals::U = 1 +//@ lldb-command:v/d basic_types_mut_globals::U8 +//@ lldb-check:[...]basic_types_mut_globals::U8 = 100 +//@ lldb-command:v basic_types_mut_globals::U16 +//@ lldb-check:[...]basic_types_mut_globals::U16 = 16 +//@ lldb-command:v basic_types_mut_globals::U32 +//@ lldb-check:[...]basic_types_mut_globals::U32 = 32 +//@ lldb-command:v basic_types_mut_globals::U64 +//@ lldb-check:[...]basic_types_mut_globals::U64 = 64 +//@ lldb-command:v basic_types_mut_globals::F16 +//@ lldb-check:[...]basic_types_mut_globals::F16 = 1.5 +//@ lldb-command:v basic_types_mut_globals::F32 +//@ lldb-check:[...]basic_types_mut_globals::F32 = 2.5 +//@ lldb-command:v basic_types_mut_globals::F64 +//@ lldb-check:[...]basic_types_mut_globals::F64 = 3.5 +//@ lldb-command:v basic_types_mut_globals::F128 +//@[not-apple] lldb-check:[...]basic_types_mut_globals::F128 = 4.5 +//@ lldb-command:continue + +// Check new values +//@ lldb-command:v basic_types_mut_globals::B +//@ lldb-check:[...]basic_types_mut_globals::B = true +//@ lldb-command:v basic_types_mut_globals::I +//@ lldb-check:[...]basic_types_mut_globals::I = 2 +//@ lldb-command:v basic_types_mut_globals::C +//@ lldb-check:[...]basic_types_mut_globals::C = U+0x00000066 U'f' +//@ lldb-command:v/d basic_types_mut_globals::I8 +//@ lldb-check:[...]basic_types_mut_globals::I8 = 78 +//@ lldb-command:v basic_types_mut_globals::I16 +//@ lldb-check:[...]basic_types_mut_globals::I16 = -26 +//@ lldb-command:v basic_types_mut_globals::I32 +//@ lldb-check:[...]basic_types_mut_globals::I32 = -12 +//@ lldb-command:v basic_types_mut_globals::I64 +//@ lldb-check:[...]basic_types_mut_globals::I64 = -54 +//@ lldb-command:v basic_types_mut_globals::U +//@ lldb-check:[...]basic_types_mut_globals::U = 5 +//@ lldb-command:v/d basic_types_mut_globals::U8 +//@ lldb-check:[...]basic_types_mut_globals::U8 = 20 +//@ lldb-command:v basic_types_mut_globals::U16 +//@ lldb-check:[...]basic_types_mut_globals::U16 = 32 +//@ lldb-command:v basic_types_mut_globals::U32 +//@ lldb-check:[...]basic_types_mut_globals::U32 = 16 +//@ lldb-command:v basic_types_mut_globals::U64 +//@ lldb-check:[...]basic_types_mut_globals::U64 = 128 +//@ lldb-command:v basic_types_mut_globals::F16 +//@ lldb-check:[...]basic_types_mut_globals::F16 = 2.25 +//@ lldb-command:v basic_types_mut_globals::F32 +//@ lldb-check:[...]basic_types_mut_globals::F32 = 5.75 +//@ lldb-command:v basic_types_mut_globals::F64 +//@ lldb-check:[...]basic_types_mut_globals::F64 = 9.25 +//@ lldb-command:v basic_types_mut_globals::F128 +//@[not-apple] lldb-check:[...]basic_types_mut_globals::F128 = 12.75 #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] static mut B: bool = false; static mut I: isize = -1; @@ -93,6 +167,7 @@ static mut U64: u64 = 64; static mut F16: f16 = 1.5; static mut F32: f32 = 2.5; static mut F64: f64 = 3.5; +static mut F128: f128 = 4.5; fn main() { _zzz(); // #break @@ -113,6 +188,7 @@ fn main() { F16 = 2.25; F32 = 5.75; F64 = 9.25; + F128 = 12.75; } _zzz(); // #break diff --git a/tests/debuginfo/basic-types/main.rs b/tests/debuginfo/basic-types/main.rs index 9f61862c0dfd8..d01e51036f201 100644 --- a/tests/debuginfo/basic-types/main.rs +++ b/tests/debuginfo/basic-types/main.rs @@ -1,9 +1,3 @@ -// Caveats - gdb prints any 8-bit value (meaning rust i8 and u8 values) -// as its numerical value along with its associated ASCII char, there -// doesn't seem to be any way around this. Also, gdb doesn't know -// about UTF-32 character encoding and will print a rust char as only -// its numerical value. - //@ compile-flags:-g //@ disable-gdb-pretty-printers //@ ignore-backends: gcc @@ -32,6 +26,7 @@ //@ gdb-repr:f16 //@ gdb-repr:f32 //@ gdb-repr:f64 +// FIXME(f128): gdb doesn't support Rust `f128` yet. //@ gdb-repr:s // === LLDB TESTS ================================================================================== @@ -85,13 +80,16 @@ //@ cdb-check:f32 : 2.500000 [Type: float] //@ cdb-command:dx f64 //@ cdb-check:f64 : 3.500000 [Type: double] +//@ cdb-command:dx f128 +//@ cdb-check:f128 : 0x1.2p+2 [Type: f128] +//@ cdb-check:bits : 0x40012000000000000000000000000000 //@ cdb-command:.enable_unicode 1 // FIXME(#88840): The latest version of the Windows SDK broke the visualizer for str. //@ cdb-command:dx s //@ cdb-check:s : [...] [Type: ref$] #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] fn main() { let b: bool = false; @@ -109,6 +107,7 @@ fn main() { let f16: f16 = 1.5; let f32: f32 = 2.5; let f64: f64 = 3.5; + let f128: f128 = 4.5; let s: &str = "Hello, World!"; _zzz(); // #break } diff --git a/tests/debuginfo/borrowed-basic.rs b/tests/debuginfo/borrowed-basic.rs index f7b7d2cbd810c..2872bc65fac3f 100644 --- a/tests/debuginfo/borrowed-basic.rs +++ b/tests/debuginfo/borrowed-basic.rs @@ -2,6 +2,13 @@ //@ disable-gdb-pretty-printers //@ ignore-backends: gcc +// FIXME(f128): Merge `apple` revision once Apple releases Xcode with LLVM 22. +//@ revisions: not-apple apple +//@[not-apple] ignore-apple +//@[apple] only-apple +// `f128` support was added to `lldb` in version 22. +//@ min-llvm-lldb-version: 22 + // === GDB TESTS =================================================================================== //@ gdb-command:run @@ -50,6 +57,8 @@ //@ gdb-command:print *f64_ref //@ gdb-check:$15 = 3.5 +// FIXME(f128): gdb doesn't support Rust `f128` yet. + // === LLDB TESTS ================================================================================== @@ -99,8 +108,11 @@ //@ lldb-command:v *f64_ref //@ lldb-check:[...] 3.5 +//@ lldb-command:v *f128_ref +//@[not-apple] lldb-check:[...] 4.5 + #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] fn main() { let bool_val: bool = true; @@ -148,6 +160,9 @@ fn main() { let f64_val: f64 = 3.5; let f64_ref: &f64 = &f64_val; + let f128_val: f128 = 4.5; + let f128_ref: &f128 = &f128_val; + zzz(); // #break } diff --git a/tests/debuginfo/borrowed-unique-basic.rs b/tests/debuginfo/borrowed-unique-basic.rs index 17939239c0dea..0d1fdec0f58d1 100644 --- a/tests/debuginfo/borrowed-unique-basic.rs +++ b/tests/debuginfo/borrowed-unique-basic.rs @@ -2,6 +2,13 @@ //@ disable-gdb-pretty-printers //@ ignore-backends: gcc +// FIXME(f128): Merge `apple` revision once Apple releases Xcode with LLVM 22. +//@ revisions: not-apple apple +//@[not-apple] ignore-apple +//@[apple] only-apple +// `f128` support was added to `lldb` in version 22. +//@ min-llvm-lldb-version: 22 + // === GDB TESTS =================================================================================== //@ gdb-command:run @@ -51,6 +58,8 @@ //@ gdb-command:print *f64_ref //@ gdb-check:$15 = 3.5 +// FIXME(f128): gdb doesn't support Rust `f128` yet. + // === LLDB TESTS ================================================================================== @@ -102,8 +111,11 @@ //@ lldb-command:v *f64_ref //@ lldb-check:[...] 3.5 +//@ lldb-command:v *f128_ref +//@[not-apple] lldb-check:[...] 4.5 + #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] fn main() { let bool_box: Box = Box::new(true); @@ -151,6 +163,9 @@ fn main() { let f64_box: Box = Box::new(3.5); let f64_ref: &f64 = &*f64_box; + let f128_box: Box = Box::new(4.5); + let f128_ref: &f128 = &*f128_box; + zzz(); // #break } diff --git a/tests/debuginfo/f128-natvis.rs b/tests/debuginfo/f128-natvis.rs new file mode 100644 index 0000000000000..5f91014cfe5db --- /dev/null +++ b/tests/debuginfo/f128-natvis.rs @@ -0,0 +1,92 @@ +//@ compile-flags: -g +//@ only-msvc + +// This tests the `f128` Natvis visualiser. +//@ cdb-command:g +//@ cdb-command:dx v0_0 +//@ cdb-check:v0_0 : 0x0p+0 [Type: f128] +//@ cdb-check:bits : 0x00000000000000000000000000000000 +//@ cdb-command:dx neg_0_0 +//@ cdb-check:neg_0_0 : -0x0p+0 [Type: f128] +//@ cdb-check:bits : 0x80000000000000000000000000000000 +//@ cdb-command:dx v1_0 +//@ cdb-check:v1_0 : 0x1p+0 [Type: f128] +//@ cdb-check:bits : 0x3fff0000000000000000000000000000 +//@ cdb-command:dx v1_5 +//@ cdb-check:v1_5 : 0x1.8p+0 [Type: f128] +//@ cdb-check:bits : 0x3fff8000000000000000000000000000 +//@ cdb-command:dx v72_3 +//@ cdb-check:v72_3 : 0x1.2133333333333333333333333333p+6 [Type: f128] +//@ cdb-check:bits : 0x40052133333333333333333333333333 +//@ cdb-command:dx neg_0_126 +//@ cdb-check:neg_0_126 : -0x1.020c49ba5e353f7ced916872b021p-3 [Type: f128] +//@ cdb-check:bits : 0xbffc020c49ba5e353f7ced916872b021 +//@ cdb-command:dx v0_00003 +//@ cdb-check:v0_00003 : 0x1.f75104d551d68c692f6e82949a56p-16 [Type: f128] +//@ cdb-check:bits : 0x3feff75104d551d68c692f6e82949a56 +//@ cdb-command:dx neg_0_00004 +//@ cdb-check:neg_0_00004 : -0x1.4f8b588e368f08461f9f01b866e4p-15 [Type: f128] +//@ cdb-check:bits : 0xbff04f8b588e368f08461f9f01b866e4 +//@ cdb-command:dx very_small +//@ cdb-check:very_small : 0x1p-16494 [Type: f128] +//@ cdb-check:bits : 0x00000000000000000000000000000001 +//@ cdb-command:dx not_quite_as_small +//@ cdb-check:not_quite_as_small : 0x1.8p-16385 [Type: f128] +//@ cdb-check:bits : 0x00003000000000000000000000000000 +//@ cdb-command:dx smallest_pos_normal +//@ cdb-check:smallest_pos_normal : 0x1p-16382 [Type: f128] +//@ cdb-check:bits : 0x00010000000000000000000000000000 +//@ cdb-command:dx smallest_subnormal +//@ cdb-check:smallest_subnormal : -0x1.fffffffffffffffffffffffffffep-16383 [Type: f128] +//@ cdb-check:bits : 0x8000ffffffffffffffffffffffffffff +//@ cdb-command:dx just_above +//@ cdb-check:just_above : -0x1.ffffffffffffffffffffffffff8p-1 [Type: f128] +//@ cdb-check:bits : 0xbffeffffffffffffffffffffffffff80 +//@ cdb-command:dx max +//@ cdb-check:max : 0x1.ffffffffffffffffffffffffffffp+16383 [Type: f128] +//@ cdb-check:bits : 0x7ffeffffffffffffffffffffffffffff +//@ cdb-command:dx min +//@ cdb-check:min : -0x1.ffffffffffffffffffffffffffffp+16383 [Type: f128] +//@ cdb-check:bits : 0xfffeffffffffffffffffffffffffffff +//@ cdb-command:dx inf +//@ cdb-check:inf : inf [Type: f128] +//@ cdb-check:bits : 0x7fff0000000000000000000000000000 +//@ cdb-command:dx neg_inf +//@ cdb-check:neg_inf : -inf [Type: f128] +//@ cdb-check:bits : 0xffff0000000000000000000000000000 +//@ cdb-command:dx nan +//@ cdb-check:nan : NaN [Type: f128] +//@ cdb-check:bits : 0x7fff8000000000000000000000000000 +//@ cdb-command:dx other_nan +//@ cdb-check:other_nan : NaN [Type: f128] +//@ cdb-check:bits : 0xffff123456789abcdef123456789abcd + +#![feature(f128)] + +fn main() { + let v0_0 = 0.0_f128; + let neg_0_0 = -0.0_f128; + let v1_0 = 1.0_f128; + let v1_5 = 1.5_f128; + let v72_3 = 72.3_f128; + let neg_0_126 = -0.126_f128; + let v0_00003 = 0.00003_f128; + let neg_0_00004 = -0.00004_f128; + let very_small = 0.0_f128.next_up(); + let not_quite_as_small = const { f128::MIN_POSITIVE / 8.0 + f128::MIN_POSITIVE / 16.0 }; + let smallest_pos_normal = f128::MIN_POSITIVE; + let smallest_subnormal = (-f128::MIN_POSITIVE).next_up(); + let just_above = const { -1.0 + f128::EPSILON * 64.0 }; + let max = f128::MAX; + let min = f128::MIN; + let inf = f128::INFINITY; + let neg_inf = f128::NEG_INFINITY; + let nan = f128::NAN; + let other_nan = f128::from_bits(0xffff_1234_5678_9abc_def1_2345_6789_abcd); + + _zzz(); // #break +} + +fn _zzz() { + () +} diff --git a/tests/debuginfo/reference-debuginfo.rs b/tests/debuginfo/reference-debuginfo.rs index 518e1dac2885e..495dde379da7e 100644 --- a/tests/debuginfo/reference-debuginfo.rs +++ b/tests/debuginfo/reference-debuginfo.rs @@ -2,10 +2,18 @@ // That pass replaces debuginfo for `a => _x` where `_x = &b` to be `a => &b`, // and leaves codegen to create a ladder of allocations so as `*a == b`. // +// FIXME: Currently emits warning: MIR pass `ConstDebugInfo` is unknown and will be ignored //@ compile-flags:-g -Zmir-enable-passes=+ReferencePropagation,-ConstDebugInfo //@ disable-gdb-pretty-printers //@ ignore-backends: gcc +// FIXME(f128): Merge `apple` revision once Apple releases Xcode with LLVM 22. +//@ revisions: not-apple apple +//@[not-apple] ignore-apple +//@[apple] only-apple +// `f128` support was added to `lldb` in version 22. +//@ min-llvm-lldb-version: 22 + // === GDB TESTS =================================================================================== //@ gdb-command:run @@ -54,6 +62,8 @@ //@ gdb-command:print *f64_ref //@ gdb-check:$15 = 3.5 +// FIXME(f128): gdb doesn't support Rust `f128` yet. + //@ gdb-command:print *f64_double_ref //@ gdb-check:$16 = 3.5 @@ -106,11 +116,14 @@ //@ lldb-command:v *f64_ref //@ lldb-check:[...] 3.5 +//@ lldb-command:v *f128_ref +//@[not-apple] lldb-check:[...] 4.5 + //@ lldb-command:v *f64_double_ref //@ lldb-check:[...] 3.5 #![allow(unused_variables)] -#![feature(f16)] +#![feature(f16, f128)] fn main() { let bool_val: bool = true; @@ -159,6 +172,9 @@ fn main() { let f64_ref: &f64 = &f64_val; let f64_double_ref: &f64 = &f64_ref; + let f128_val: f128 = 4.5; + let f128_ref: &f128 = &f128_val; + zzz(); // #break } From 3d281d48815e6213ad9911e97d5d8d59d2348b1a Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 3 Sep 2026 21:25:04 +0200 Subject: [PATCH 0363/1309] implement `VaArgSafe` for `f128` --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 3 +- library/core/src/ffi/va_list.rs | 49 +++++++++++++++++ .../c-link-to-rust-va-list-fn/checkrust.rs | 55 ++++++++++++++++++- .../run-make/c-link-to-rust-va-list-fn/test.c | 39 +++++++++++++ tests/ui/c-variadic/roundtrip.rs | 36 +++++++++++- 5 files changed, 177 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index db896fa9c0f2b..c71e83d8f99bd 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -347,8 +347,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { // 64-bit floats are always OK. } Primitive::Float(Float::F128) => { - // FIXME(f128) figure out whether we should support this. - bug!("the va_arg intrinsic does not support `f128`") + // Supported on some targets, especially where long double is IEEE f128. } } diff --git a/library/core/src/ffi/va_list.rs b/library/core/src/ffi/va_list.rs index 21f8e264db953..b308cb7f85df2 100644 --- a/library/core/src/ffi/va_list.rs +++ b/library/core/src/ffi/va_list.rs @@ -416,6 +416,55 @@ cfg_select! { #[unstable(feature = "c_variadic_va_arg_safe", issue = "162911", implied_by = "c_variadic")] unsafe impl VaArgSafe for f64 {} +// Implement `VaArgSafe` for f128 on targets where either: +// +// - clang provides `__float128` +// - `long double` is IEEE f128 on the platform. +// +// When updating this cfg, also update the tests to match. Currently this condition +// is duplicated in: +// +// - tests/ui/c-variadic/roundtrip.rs +// - tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +// +// # Known incompatibilities +// +// Testing versus clang exposed bugs in clang. GCC has no known incompatibilities. +// +// - Clang <= 23 on sparc, see https://github.com/llvm/llvm-project/pull/214981. +// - Clang <= 23 on x86, see https://github.com/llvm/llvm-project/issues/217747. +cfg_select! { + any( + all(target_arch = "x86_64", not(target_vendor = "apple"), not(target_env = "msvc")), + all(target_arch = "x86", not(target_vendor = "apple"), not(target_env = "msvc")), + // PowerPC requires VSX (only little endian has it enabled by default). + all(target_arch = "powerpc64", target_feature = "vsx"), + all( + not(windows), + not(target_vendor = "apple"), + any( + target_arch = "aarch64", + target_arch = "loongarch32", + target_arch = "loongarch64", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "riscv32", + target_arch = "riscv64", + target_arch = "s390x", + target_arch = "sparc", + target_arch = "sparc64", + target_arch = "wasm32", + target_arch = "wasm64", + ), + ), + ) => { + #[unstable_feature_bound(f128)] + #[unstable(feature = "f128", issue = "116909")] + unsafe impl VaArgSafe for f128 {} + } + _ => { /* unsupported */ } +} + #[unstable(feature = "c_variadic_va_arg_safe", issue = "162911", implied_by = "c_variadic")] unsafe impl VaArgSafe for *mut T {} #[unstable(feature = "c_variadic_va_arg_safe", issue = "162911", implied_by = "c_variadic")] diff --git a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs index 37110e75f4779..3f9698afe2d6c 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs +++ b/tests/run-make/c-link-to-rust-va-list-fn/checkrust.rs @@ -1,5 +1,5 @@ #![crate_type = "staticlib"] -#![feature(c_variadic_int128, c_variadic_experimental_arch)] +#![feature(c_variadic_int128, c_variadic_experimental_arch, f128)] use core::ffi::{CStr, VaList, c_char, c_double, c_int, c_long, c_longlong}; @@ -100,6 +100,59 @@ pub unsafe extern "C" fn check_list_i128(mut ap: VaList) -> usize { } } +cfg_select! { + any( + all(target_arch = "x86_64", not(target_vendor = "apple"), not(target_env = "msvc")), + all(target_arch = "x86", not(target_vendor = "apple"), not(target_env = "msvc")), + all(target_arch = "powerpc64", target_feature = "vsx"), + all( + not(windows), + not(target_vendor = "apple"), + any( + target_arch = "aarch64", + target_arch = "loongarch32", + target_arch = "loongarch64", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "riscv64", + target_arch = "s390x", + target_arch = "sparc", + target_arch = "sparc64", + target_arch = "wasm32", + target_arch = "wasm64", + ), + ), + ) => { + #[unsafe(no_mangle)] + pub static RUST_HAS_F128: c_int = 1; + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn check_list_f128(mut ap: VaList) -> usize { + continue_if!(ap.next_arg::() == -42.0); + // use a 32-bit value here to test the alignment logic. + continue_if!(ap.next_arg::() == 0xAAAA_AAAAu32.cast_signed()); + continue_if!(ap.next_arg::() == f128::MAX); + + return 0; + } + } + _ => { + #[unsafe(no_mangle)] + pub static RUST_HAS_F128: c_int = 0; + + #[unsafe(no_mangle)] + pub unsafe extern "C" fn check_list_f128(_: VaList) -> usize { + // This function was called a platform where rustc does not implement + // VaArgSafe for f128 but clang does define _Float128. + // + // This occurs on powerpc64 where f128 support depends on a target feature. + // + // Otherwise, rustc should add the implementation if this comes up. + 0xFF + } + } +} + #[unsafe(no_mangle)] pub unsafe extern "C" fn check_varargs_0(_: c_int, mut ap: ...) -> usize { continue_if!(ap.next_arg::() == 42); diff --git a/tests/run-make/c-link-to-rust-va-list-fn/test.c b/tests/run-make/c-link-to-rust-va-list-fn/test.c index c7510a29445a5..14c507cd6cccd 100644 --- a/tests/run-make/c-link-to-rust-va-list-fn/test.c +++ b/tests/run-make/c-link-to-rust-va-list-fn/test.c @@ -3,12 +3,14 @@ #include #include #include +#include extern size_t check_list_0(va_list ap); extern size_t check_list_1(va_list ap); extern size_t check_list_2(va_list ap); extern size_t check_list_copy_0(va_list ap); extern size_t check_list_i128(va_list ap); +extern size_t check_list_f128(va_list ap); extern size_t check_varargs_0(int fixed, ...); extern size_t check_varargs_1(int fixed, ...); extern size_t check_varargs_2(int fixed, ...); @@ -21,6 +23,9 @@ extern size_t run_test_va_list_by_value(); extern size_t run_test_va_list_by_pointer(); extern size_t run_test_va_list_by_pointer_pointer(); +// Was the rust side compiled with f128 support? +extern const int RUST_HAS_F128; + int test_rust(size_t (*fn)(va_list), ...) { size_t ret = 0; va_list ap; @@ -40,9 +45,43 @@ int main(int argc, char* argv[]) { assert(test_rust(check_list_copy_0, 6.28, 16, 'A', "Skip Me!", "Correct") == 0); #if defined(__SIZEOF_INT128__) + assert(test_rust(check_list_i128, (__int128)-42, 0xAAAAAAAA, (unsigned __int128)-1) == 0); #endif + // Run the f128 test when __float128/_Float128 is defined or long double is IEEE f128. + // Use #define instead of typedef so that `#ifdef` can detect it. +#if defined(__LDBL_MANT_DIG__) && __LDBL_MANT_DIG__ == 113 +#define f128 long double +#elif defined(__SIZEOF_FLOAT128__) +#ifdef __clang__ +#define f128 __float128 +#else +#define f128 _Float128 +#endif +#endif + +#ifdef f128 + // construct f128::MAX. + union cvt128 { + struct { +#if defined(__BYTE_ORDER__) && (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) + uint64_t hi, lo; +#else + uint64_t lo, hi; +#endif + } i; + f128 f; + }; + union cvt128 f128_max; + f128_max.i.hi = 0x7ffeffffffffffff; + f128_max.i.lo = 0xffffffffffffffff; + + if (RUST_HAS_F128) { + assert(test_rust(check_list_f128, (f128)-42.0, 0xAAAAAAAA, f128_max.f) == 0); + } +#endif + assert(check_varargs_0(0, 42, "Hello, World!") == 0); assert(check_varargs_1(0, 3.14, 12l, 'A', 0x1LL) == 0); diff --git a/tests/ui/c-variadic/roundtrip.rs b/tests/ui/c-variadic/roundtrip.rs index 9fa55c36e2441..1fb96ab7cfad7 100644 --- a/tests/ui/c-variadic/roundtrip.rs +++ b/tests/ui/c-variadic/roundtrip.rs @@ -5,7 +5,8 @@ c_variadic_va_arg_safe, c_variadic_int128, const_destruct, - const_raw_ptr_comparison + const_raw_ptr_comparison, + f128 )] #![allow(unused_features)] // c_variadic_int128 is only used on 64-bit targets. @@ -113,7 +114,38 @@ fn main() { roundtrip!(i128, -1, -2); roundtrip!(u128, 1, 2); } - _ => {} + _ => { /* unsupported */ } + } + + cfg_select! { + any( + all( + any(target_arch = "x86_64", target_arch = "x86"), + not(target_vendor = "apple"), + not(target_env = "msvc") + ), + all(target_arch = "powerpc64", target_feature = "vsx"), + all( + not(windows), + not(target_vendor = "apple"), + any( + target_arch = "aarch64", + target_arch = "loongarch32", + target_arch = "loongarch64", + target_arch = "mips64", + target_arch = "mips64r6", + target_arch = "riscv64", + target_arch = "s390x", + target_arch = "sparc", + target_arch = "sparc64", + target_arch = "wasm32", + target_arch = "wasm64", + ), + ), + ) => { + roundtrip!(f128, -1.0, f128::MAX); + } + _ => { /* unsupported */ } } } } From 74a45daaa7cd974bd44fb09b1e00dd2b306967b8 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 20:51:24 +0200 Subject: [PATCH 0364/1309] Merge commit '39f626bc72757517b75d8e2dde50fa832b8d6c03' --- .cspell.json | 28 -- .github/workflows/ci.yml | 18 +- .github/workflows/failures.yml | 18 +- .gitignore | 3 +- Cargo.lock | 8 +- Cargo.toml | 4 +- Readme.md | 2 +- build_system/src/build.rs | 51 +- build_system/src/main.rs | 5 +- build_system/src/test.rs | 614 +++++++++++++++++------ clippy.toml | 3 + doc/tips.md | 2 +- libgccjit.version | 2 +- rust-toolchain | 2 +- src/abi.rs | 2 +- src/asm.rs | 1 + src/attributes.rs | 12 + src/back/lto.rs | 3 +- src/base.rs | 88 +++- src/builder.rs | 208 +++++--- src/common.rs | 113 +++-- src/consts.rs | 219 +++++--- src/context.rs | 66 ++- src/declare.rs | 6 +- src/gcc_util.rs | 168 ++++++- src/int.rs | 62 ++- src/intrinsic/llvm.rs | 13 +- src/intrinsic/mod.rs | 26 +- src/intrinsic/simd.rs | 88 +++- src/lib.rs | 52 +- src/mono_item.rs | 161 +++++- src/type_.rs | 106 +++- src/type_of.rs | 17 +- tests/asm/bulk_memory_alignment.rs | 45 ++ tests/asm/volatile_bulk_memory.rs | 37 ++ tests/c/import_linkage.c | 17 + tests/c/overaligned_byval_abi.c | 54 ++ tests/c/static_linkage.c | 37 ++ tests/c/weak_function_linkage.c | 54 ++ tests/compile/asm_noreturn_call.rs | 15 + tests/compile/recursive_types.rs | 22 + tests/failing-ice-tests.txt | 17 +- tests/failing-lto-tests.txt | 9 +- tests/failing-run-make-tests.txt | 3 +- tests/failing-ui-tests.txt | 100 +--- tests/lang_tests.rs | 102 +++- tests/run/catch_unwind.rs | 25 + tests/run/custom_abort.rs | 27 + tests/run/import_linkage.rs | 84 ++++ tests/run/nonzero_div_ceil.rs | 17 + tests/run/overaligned_byval_abi.rs | 89 ++++ tests/run/overaligned_byval_arg.rs | 41 ++ tests/run/ptr_to_int_div.rs | 19 + tests/run/simd.rs | 81 +++ tests/run/static_alloc_shapes.rs | 50 ++ tests/run/static_linkage.rs | 79 +++ tests/run/weak_function_linkage.rs | 106 ++++ tools/cspell_dicts/rust.txt | 2 - tools/cspell_dicts/rustc_codegen_gcc.txt | 78 --- 59 files changed, 2635 insertions(+), 746 deletions(-) delete mode 100644 .cspell.json create mode 100644 clippy.toml create mode 100644 tests/asm/bulk_memory_alignment.rs create mode 100644 tests/asm/volatile_bulk_memory.rs create mode 100644 tests/c/import_linkage.c create mode 100644 tests/c/overaligned_byval_abi.c create mode 100644 tests/c/static_linkage.c create mode 100644 tests/c/weak_function_linkage.c create mode 100644 tests/compile/asm_noreturn_call.rs create mode 100644 tests/compile/recursive_types.rs create mode 100644 tests/run/catch_unwind.rs create mode 100644 tests/run/custom_abort.rs create mode 100644 tests/run/import_linkage.rs create mode 100644 tests/run/nonzero_div_ceil.rs create mode 100644 tests/run/overaligned_byval_abi.rs create mode 100644 tests/run/overaligned_byval_arg.rs create mode 100644 tests/run/ptr_to_int_div.rs create mode 100644 tests/run/simd.rs create mode 100644 tests/run/static_alloc_shapes.rs create mode 100644 tests/run/static_linkage.rs create mode 100644 tests/run/weak_function_linkage.rs delete mode 100644 tools/cspell_dicts/rust.txt delete mode 100644 tools/cspell_dicts/rustc_codegen_gcc.txt diff --git a/.cspell.json b/.cspell.json deleted file mode 100644 index 556432d69a41b..0000000000000 --- a/.cspell.json +++ /dev/null @@ -1,28 +0,0 @@ -{ - "allowCompoundWords": true, - "dictionaries": ["cpp", "rust-extra", "rustc_codegen_gcc"], - "dictionaryDefinitions": [ - { - "name": "rust-extra", - "path": "tools/cspell_dicts/rust.txt", - "addWords": true - }, - { - "name": "rustc_codegen_gcc", - "path": "tools/cspell_dicts/rustc_codegen_gcc.txt", - "addWords": true - } - ], - "files": [ - "src/**/*.rs" - ], - "ignorePaths": [ - "src/intrinsic/archs.rs", - "src/intrinsic/old_archs.rs", - "src/intrinsic/llvm.rs" - ], - "ignoreRegExpList": [ - "/(FIXME|NOTE|TODO)\\([^)]+\\)/", - "__builtin_\\w*" - ] -} diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index fa9535a3729c3..8888fdc3ee093 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -31,11 +31,13 @@ jobs: # "--asm-tests", "--test-libcore", "--extended-rand-tests", - "--extended-regex-example-tests", + "--extended-regex-example-tests --test-libcore-doctests", "--extended-regex-tests", "--test-successful-rustc --nb-parts 2 --current-part 0", "--test-successful-rustc --nb-parts 2 --current-part 1", - "--projects", + "--projects --nb-parts 2 --current-part 0", + "--projects --nb-parts 2 --current-part 1", + "--gcc-asm-tests --test-release-libcore", ] steps: @@ -52,8 +54,9 @@ jobs: # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - - name: Install rustfmt & clippy - run: rustup component add rustfmt clippy + - name: Install the libraries needed to build librsvg + if: ${{ contains(matrix.commands, '--projects') }} + run: sudo apt-get install libcairo2-dev libpango1.0-dev libfontconfig1-dev libfreetype-dev libharfbuzz-dev libxml2-dev libglib2.0-dev - name: Download artifact run: curl -LO https://github.com/rust-lang/gcc/releases/latest/download/${{ matrix.libgccjit_version.gcc }} @@ -127,13 +130,6 @@ jobs: - uses: actions/checkout@v4 - run: python tools/check_intrinsics_duplicates.py - spell_check: - runs-on: ubuntu-24.04 - steps: - - uses: actions/checkout@v4 - - uses: crate-ci/typos@v1.32.0 - - uses: streetsidesoftware/cspell-action@v7 - build_system: runs-on: ubuntu-24.04 steps: diff --git a/.github/workflows/failures.yml b/.github/workflows/failures.yml index 2c9e4950706b2..52e96726129b3 100644 --- a/.github/workflows/failures.yml +++ b/.github/workflows/failures.yml @@ -98,7 +98,14 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' id: tests run: | - ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log + # Without this, `tee` masks the exit status of `y.sh test`. + set -o pipefail + status=0 + ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --clean --build-sysroot --test-failing-rustc ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log || status=$? + # This suite runs the tests known to fail, so only a build system error must fail the job. + if [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then + exit "$status" + fi rg --text "test result" output_log >> $GITHUB_STEP_SUMMARY - name: Run failing ui pattern tests for ICE @@ -106,7 +113,14 @@ jobs: if: matrix.libgccjit_version.gcc != 'libgccjit12.so' id: ui-tests run: | - ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log_ui + # Without this, `tee` masks the exit status of `y.sh test`. + set -o pipefail + status=0 + ${{ matrix.libgccjit_version.env_extra }} ./y.sh test --release --test-failing-ui-pattern-tests ${{ matrix.libgccjit_version.extra }} 2>&1 | tee output_log_ui || status=$? + # This suite runs tests that fail, so only a build system error must fail the job here. + if [ "$status" -ne 0 ] && [ "$status" -ne 2 ]; then + exit "$status" + fi if grep -q "the compiler unexpectedly panicked" output_log_ui; then echo "Error: 'the compiler unexpectedly panicked' found in output logs. CI Error!!" exit 1 diff --git a/.gitignore b/.gitignore index 8f73d3eb972a0..2a8fdcda0b483 100644 --- a/.gitignore +++ b/.gitignore @@ -20,4 +20,5 @@ llvm build_system/target config.toml build -rustlantis \ No newline at end of file +rustlantis +stuff/ diff --git a/Cargo.lock b/Cargo.lock index 7ce94b58c0516..c7e979a1112e3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,18 +56,18 @@ dependencies = [ [[package]] name = "gccjit" -version = "3.3.0" +version = "6.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "26b73d18b642ce16378af78f89664841d7eeafa113682ff5d14573424eb0232a" +checksum = "6d85b5754389edaad832ba320709a25086b3081a8c6c0fab2322965e5fb512b3" dependencies = [ "gccjit_sys", ] [[package]] name = "gccjit_sys" -version = "1.3.0" +version = "3.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ee689456c013616942d5aef9a84d613cefcc3b335340d036f3650fc1a7459e15" +checksum = "e081669728b490723537f9def7eb674b7c9acd8de0b92ad4f4abf5f5cc75ea4b" dependencies = [ "libc", ] diff --git a/Cargo.toml b/Cargo.toml index ac5e94b9454e2..02be6d56c2310 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,11 +20,11 @@ default = ["master"] [dependencies] object = { version = "0.39.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "3.3.0", features = ["dlopen"] } +gccjit = { version = "6.1.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. -#gccjit = { path = "../gccjit.rs", features = ["dlopen"] } +# gccjit = { path = "../gccjit.rs", features = ["dlopen"] } [dev-dependencies] boml = "0.3.1" diff --git a/Readme.md b/Readme.md index ce5ee1e4adee6..6b1f90b918855 100644 --- a/Readme.md +++ b/Readme.md @@ -176,7 +176,7 @@ $ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(ca More specific documentation is available in the [`doc`](./doc) folder: * [Common errors](./doc/errors.md) - * [Debugging GCC LTO](./doc/debugging-gcc-lto.md) + * [Debugging](./doc/debugging.md) * [Debugging libgccjit](./doc/debugging-libgccjit.md) * [Git subtree sync](./doc/subtree.md) * [List of useful commands](./doc/tips.md) diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 839c762fed742..2f2900af5c88a 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -132,6 +132,24 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // Builds libs let mut rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + + // Record the sysroot sources under the path the `rust-src` component uses, which is where + // rustc looks for them to turn a sysroot span into `/rustc/$hash`. Without this, ui tests + // print the build path where they expect `$SRC_DIR`. + let sysroot_source_dir = lib_path.join("rustlib/src/rust/library"); + rustflags.push_str(&format!( + " --remap-path-prefix={library_dir}={sysroot_source_dir}", + library_dir = std::path::absolute(&library_dir) + .map_err(|error| format!( + "Failed to get the absolute path of the sysroot sources: {error:?}" + ))? + .display(), + sysroot_source_dir = std::path::absolute(&sysroot_source_dir) + .map_err(|error| format!( + "Failed to get the absolute path of the sysroot sources: {error:?}" + ))? + .display(), + )); if config.sysroot_panic_abort { rustflags.push_str(" -Cpanic=abort -Zpanic-abort-tests"); } @@ -188,12 +206,33 @@ pub fn build_sysroot(env: &HashMap, config: &ConfigInfo) -> Resu // FIXME: should not use shell command! run_command(&[&"cp", &"-r", &dir_to_copy, &sysroot_path], None).map(|_| ()) }; - walk_dir( - library_dir.join(format!("target/{}/{}/deps", config.target_triple, channel)), - &mut copier.clone(), - &mut copier, - false, - )?; + let target_dir = library_dir.join(format!("target/{}/{}", config.target_triple, channel)); + let deps_dir = target_dir.join("deps"); + if deps_dir.is_dir() { + // Keep copying in the old directory just in case. + walk_dir(&deps_dir, &mut copier.clone(), &mut copier, false)?; + } else { + let build_dir = target_dir.join("build"); + walk_dir( + &build_dir, + &mut |package_dir: &Path| { + walk_dir( + package_dir, + &mut |unit_dir: &Path| { + let out_dir = unit_dir.join("out"); + if out_dir.is_dir() { + walk_dir(&out_dir, &mut copier.clone(), &mut copier.clone(), false)?; + } + Ok(()) + }, + &mut |_| Ok(()), + false, + ) + }, + &mut |_| Ok(()), + false, + )?; + } // Copy the source files to the sysroot (Rust for Linux needs this). let sysroot_src_path = start_dir.join("sysroot/lib/rustlib/src/rust"); diff --git a/build_system/src/main.rs b/build_system/src/main.rs index ae975c94fff25..d0b9811ac8ceb 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -108,6 +108,9 @@ fn main() { Command::AbiTest => abi_test::run(), } { eprintln!("Command failed to run: {e}"); - process::exit(1); + // CI needs to tell a build system error apart from the test failures some suites expect. + let exit_code = + if e == test::TESTS_FAILED_ERROR { test::TESTS_FAILED_EXIT_CODE } else { 1 }; + process::exit(exit_code); } } diff --git a/build_system/src/test.rs b/build_system/src/test.rs index 2475a3a6a7155..a4bdb80c94f28 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -1,10 +1,12 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use std::ffi::OsStr; -use std::fs::{File, remove_dir_all}; +use std::fs::{File, read_to_string, remove_dir_all}; use std::io::{BufRead, BufReader}; use std::path::{Path, PathBuf}; use std::str::FromStr; +use boml::Toml; + use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ @@ -13,6 +15,15 @@ use crate::utils::{ split_args, walk_dir, }; +/// Exit code of `y.sh test` when the tests ran and reported failures, as opposed to the build +/// system failing to run them at all. CI relies on the distinction: the suites of known-failing +/// tests are expected to report failures, but a broken build system must never pass silently. +pub const TESTS_FAILED_EXIT_CODE: i32 = 2; + +/// The error returned for that case. `main` compares against it to pick the exit code, so no other +/// error may use this message. +pub const TESTS_FAILED_ERROR: &str = "the test suite reported failures"; + type Env = HashMap; type Runner = fn(&Env, &TestArg) -> Result<(), String>; type Runners = HashMap<&'static str, (&'static str, Runner)>; @@ -30,6 +41,9 @@ fn get_runners() -> Runners { runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); + runners.insert("--test-release-libcore", ("Run libcore tests", test_release_libcore)); + runners.insert("--test-libcore-doctests", ("Run libcore doc-tests", test_libcore_doctests)); + runners.insert("--alloc-tests", ("Run alloc tests", test_alloc)); runners.insert("--clean", ("Empty cargo target directory", clean)); runners.insert("--build-sysroot", ("Build sysroot", build_sysroot)); runners.insert("--std-tests", ("Run std tests", std_tests)); @@ -700,40 +714,109 @@ where // echo "[BUILD] sysroot in release mode" // ./build_sysroot/build_sysroot.sh --release +struct Project { + url: &'static str, + /// Arguments added to both the `cargo build` and the `cargo test` invocations. + cargo_arguments: &'static [&'static str], + /// Arguments forwarded to the test harness by `cargo test`. + test_harness_arguments: &'static [&'static str], + /// Variables added to the environment of both invocations. + environment_variables: &'static [(&'static str, &'static str)], +} + +impl Project { + const fn new(url: &'static str) -> Self { + Self { url, cargo_arguments: &[], test_harness_arguments: &[], environment_variables: &[] } + } + + const fn cargo_arguments(mut self, arguments: &'static [&'static str]) -> Self { + self.cargo_arguments = arguments; + self + } + + const fn test_harness_arguments(mut self, arguments: &'static [&'static str]) -> Self { + self.test_harness_arguments = arguments; + self + } + + const fn environment_variables( + mut self, + variables: &'static [(&'static str, &'static str)], + ) -> Self { + self.environment_variables = variables; + self + } +} + fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { let projects = [ - //"https://gitlab.gnome.org/GNOME/librsvg", // FIXME: doesn't compile in the CI since the - // version of cairo and other libraries is too old. - "https://github.com/rust-random/getrandom", - "https://github.com/BurntSushi/memchr", - "https://github.com/dtolnay/itoa", - "https://github.com/rust-lang/cfg-if", - //"https://github.com/rust-lang-nursery/lazy-static.rs", // FIXME: re-enable when the - //failing test is fixed upstream. - //"https://github.com/marshallpierce/rust-base64", // FIXME: one test is OOM-killed. - // FIXME: ignore the base64 test that is OOM-killed. - //"https://github.com/time-rs/time", // FIXME: one test fails (https://github.com/time-rs/time/issues/719). - "https://github.com/rust-lang/log", - "https://github.com/bitflags/bitflags", - //"https://github.com/serde-rs/serde", // FIXME: one test fails. - //"https://github.com/rayon-rs/rayon", // FIXME: very slow, only run on master? - //"https://github.com/rust-lang/cargo", // FIXME: very slow, only run on master? + // The reference images assume the exact cairo, pango and freetype that librsvg pins in its + // own CI; this one renders text decorations a pixel off with the versions Ubuntu ships. + Project::new("https://gitlab.gnome.org/GNOME/librsvg") + .test_harness_arguments(&["--skip", "tests::svg1_1_text_text_03_b_svg", "--exact"]) + // A debug build of librsvg needs about 5 MB of stack per `cargo test` thread to reach + // its maximum layer nesting depth; librsvg's own CI sets the same value. + .environment_variables(&[("RUST_MIN_STACK", "8388608")]), + Project::new("https://github.com/rust-random/getrandom"), + Project::new("https://github.com/BurntSushi/memchr"), + Project::new("https://github.com/dtolnay/itoa"), + Project::new("https://github.com/rust-lang/cfg-if"), + // The `ui` test compares against the diagnostics of the compiler it was blessed with, so it + // fails on the nightly we use no matter which backend produces the code. + Project::new("https://github.com/rust-lang-nursery/lazy-static.rs") + .test_harness_arguments(&["--skip", "ui", "--exact"]), + Project::new("https://github.com/marshallpierce/rust-base64"), + // The test suite refuses to build unless every feature is enabled; it otherwise spawns a + // nested `cargo test --all-features` which would not use this backend. + Project::new("https://github.com/time-rs/time").cargo_arguments(&["--all-features"]), + Project::new("https://github.com/rust-lang/log"), + Project::new("https://github.com/bitflags/bitflags"), + Project::new("https://github.com/serde-rs/serde"), + Project::new("https://github.com/rayon-rs/rayon"), + // FIXME: too slow to run in the CI: the release build alone takes 46 minutes and the + // `cargo` crate itself needs 5.4 GB of memory in a single rustc process. + //Project::new("https://github.com/rust-lang/cargo"), ]; let mut env = env.clone(); let rustflags = format!("{} --cap-lints allow", env.get("RUSTFLAGS").cloned().unwrap_or_default()); env.insert("RUSTFLAGS".to_string(), rustflags); - let run_tests = |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { - for project in iter { - let clone_result = git_clone_root_dir(project, projects_path, true)?; - let repo_path = Path::new(&clone_result.repo_dir); - run_cargo_command(&[&"build", &"--release"], Some(repo_path), &env, args)?; - run_cargo_command(&[&"test"], Some(repo_path), &env, args)?; - } + let run_tests = + |projects_path, iter: &mut dyn Iterator| -> Result<(), String> { + for project in iter { + let clone_result = git_clone_root_dir(project.url, projects_path, true)?; + let repo_path = Path::new(&clone_result.repo_dir); + + let mut project_environment = env.clone(); + for (name, value) in project.environment_variables { + project_environment.insert(name.to_string(), value.to_string()); + } - Ok(()) - }; + let mut build_command: Vec<&dyn AsRef> = vec![&"build", &"--release"]; + build_command.extend( + project.cargo_arguments.iter().map(|argument| argument as &dyn AsRef), + ); + run_cargo_command(&build_command, Some(repo_path), &project_environment, args)?; + + let mut test_command: Vec<&dyn AsRef> = vec![&"test"]; + test_command.extend( + project.cargo_arguments.iter().map(|argument| argument as &dyn AsRef), + ); + if !project.test_harness_arguments.is_empty() { + test_command.push(&"--"); + test_command.extend( + project + .test_harness_arguments + .iter() + .map(|argument| argument as &dyn AsRef), + ); + } + run_cargo_command(&test_command, Some(repo_path), &project_environment, args)?; + } + + Ok(()) + }; let projects_path = Path::new("projects"); create_dir(projects_path)?; @@ -755,12 +838,86 @@ fn test_projects(env: &Env, args: &TestArg) -> Result<(), String> { } fn test_libcore(env: &Env, args: &TestArg) -> Result<(), String> { + test_libcore_inner(env, args, false) +} + +fn test_release_libcore(env: &Env, args: &TestArg) -> Result<(), String> { + test_libcore_inner(env, args, true) +} + +fn test_libcore_inner(env: &Env, args: &TestArg, release: bool) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[TEST] libcore"); let path = get_sysroot_dir().join("sysroot_src/library/coretests"); let _ = remove_dir_all(path.join("target")); - // FIXME(antoyo): run in release mode when we fix the failures. - run_cargo_command(&[&"test"], Some(&path), env, args)?; + let mut command: Vec<&dyn AsRef> = vec![&"test"]; + if release { + command.push(&"--release"); + } + run_cargo_command(&command, Some(&path), env, args)?; + Ok(()) +} + +/// Returns the edition declared in the manifest of the given library crate, so that the doctests +/// are run with the same edition as the crate they are extracted from. +fn get_crate_edition(crate_dir: &Path) -> Result { + let manifest_path = crate_dir.join("Cargo.toml"); + let content = read_to_string(&manifest_path) + .map_err(|error| format!("Failed to read `{}`: {error:?}", manifest_path.display()))?; + let manifest = Toml::parse(&content) + .map_err(|error| format!("Failed to parse `{}`: {error:?}", manifest_path.display()))?; + manifest + .get_table("package") + .and_then(|package| package.get_string("edition")) + .map(|edition| edition.to_string()) + .map_err(|error| { + format!("Failed to get `package.edition` from `{}`: {error:?}", manifest_path.display()) + }) +} + +fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] libcore doctests"); + + let library_dir = get_sysroot_dir().join("sysroot_src/library"); + let edition = get_crate_edition(&library_dir.join("core"))?; + // `rustdoc` is called directly instead of through `cargo test --doc` because `cargo` builds its + // own `core` and passes it with `--extern`, which then conflicts with the `core` of the sysroot + // the doctests are linked against ("duplicate lang item" errors). + let toolchain = get_toolchain()?; + let toolchain_arg = format!("+{toolchain}"); + let rustflags = split_args(&env.get("RUSTFLAGS").cloned().unwrap_or_default())?; + // `-Zunstable-options` is needed for `--test-args`. + let mut command: Vec<&dyn AsRef> = vec![ + &"rustdoc", + &toolchain_arg, + &"--test", + &"core/src/lib.rs", + &"--crate-name", + &"core", + &"--crate-type", + &"lib", + &"--edition", + &edition, + &"-Zunstable-options", + // FIXME: remove `-Zforce-unstable-if-unmarked` once the doctest of + // `core::io::ErrorKind`'s `Display` impl declares `#![feature(core_io)]` upstream: without + // it, that doctest fails to compile with `E0658` on any backend. + &"-Zforce-unstable-if-unmarked", + // FIXME: one test cannot compile due to an upstream bug in the new trait solver. + &"-Znext-solver=coherence", + ]; + for flag in &rustflags { + command.push(flag); + } + // Additional arguments are forwarded to the test harness, so that a subset of the doctests can + // be run. + let test_args = + args.test_args.iter().map(|test_arg| format!("--test-args={test_arg}")).collect::>(); + for test_arg in &test_args { + command.push(test_arg); + } + run_command_with_output_and_env(&command, Some(&library_dir), Some(env))?; Ok(()) } @@ -934,10 +1091,7 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< eprintln!("nothing found for {file_path:?}"); } // The files in this directory contain errors. - if file_path.contains("/error-emitter/") { - return Ok(true); - } - Ok(false) + Ok(file_path.contains("/error-emitter/")) } // # Parameters @@ -947,6 +1101,8 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< // * `prepare_files_callback`: A callback function that prepares the files needed for the test. Its used to remove/retain tests giving Error to run various rust test suits. // * `run_error_pattern_test`: A boolean that determines whether to run only error pattern tests. // * `test_type`: A string that indicates the type of the test being run. +// * `retained_tests_list_path`: The list of tests that `prepare_files_callback` retained, if any. +// It is checked against the tests remaining after the filtering to report dead lines. // fn test_rustc_inner( env: &Env, @@ -954,7 +1110,7 @@ fn test_rustc_inner( prepare_files_callback: F, run_error_pattern_test: bool, test_type: &str, - run_ignored_tests: bool, + retained_tests_list_path: Option<&str>, ) -> Result<(), String> where F: Fn(&Path) -> Result, @@ -970,74 +1126,57 @@ where } if test_type == "ui" { - if run_error_pattern_test { - // After we removed the error tests that are known to panic with rustc_codegen_gcc, we now remove the passing tests since this runs the error tests. - walk_dir( - rust_path.join("tests/ui"), - &mut |_dir| Ok(()), - &mut |file_path| { - if contains_ui_error_patterns(file_path, args.keep_lto_tests)? { - Ok(()) - } else { - remove_file(file_path).map_err(|e| e.to_string()) - } - }, - true, - )?; - } else { - walk_dir( - rust_path.join("tests/ui"), - &mut |dir| { - let dir_name = dir.file_name().and_then(|name| name.to_str()).unwrap_or(""); - if ["abi", "extern", "proc-macro", "threads-sendsync"].contains(&dir_name) { - remove_dir_all(dir).map_err(|error| { - format!("Failed to remove folder `{}`: {:?}", dir.display(), error) - })?; - } - Ok(()) - }, - &mut |_| Ok(()), - false, - )?; - - // These two functions are used to remove files that are known to not be working currently - // with the GCC backend to reduce noise. - fn dir_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { - move |dir| { - if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) { - return Ok(()); - } - - walk_dir( - dir, - &mut dir_handling(keep_lto_tests), - &mut file_handling(keep_lto_tests), - false, - ) + // Each mode runs one half of the ui tests and removes the other: `run_error_pattern_test` + // runs the tests expected to error, the other mode runs the rest. Only `.rs` files outside + // `auxiliary` are tests, so the expected output and the auxiliary crates are left alone. + fn dir_handling( + keep_lto_tests: bool, + remove_error_pattern_tests: bool, + ) -> impl Fn(&Path) -> Result<(), String> { + move |dir| { + if dir.file_name().map(|name| name == "auxiliary").unwrap_or(true) { + return Ok(()); } + + walk_dir( + dir, + &mut dir_handling(keep_lto_tests, remove_error_pattern_tests), + &mut file_handling(keep_lto_tests, remove_error_pattern_tests), + false, + ) } + } - fn file_handling(keep_lto_tests: bool) -> impl Fn(&Path) -> Result<(), String> { - move |file_path| { - if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) { - return Ok(()); - } - let path_str = file_path.display().to_string().replace("\\", "/"); - if valid_ui_error_pattern_test(&path_str) { - return Ok(()); - } else if contains_ui_error_patterns(file_path, keep_lto_tests)? { - return remove_file(&file_path); - } - Ok(()) + fn file_handling( + keep_lto_tests: bool, + remove_error_pattern_tests: bool, + ) -> impl Fn(&Path) -> Result<(), String> { + move |file_path| { + if !file_path.extension().map(|extension| extension == "rs").unwrap_or(false) { + return Ok(()); + } + let path_str = file_path.display().to_string().replace("\\", "/"); + if valid_ui_error_pattern_test(&path_str) { + return Ok(()); } + if contains_ui_error_patterns(file_path, keep_lto_tests)? + == remove_error_pattern_tests + { + return remove_file(file_path); + } + Ok(()) } + } - walk_dir( - rust_path.join("tests/ui"), - &mut dir_handling(args.keep_lto_tests), - &mut file_handling(args.keep_lto_tests), - false, - )?; + let remove_error_pattern_tests = !run_error_pattern_test; + walk_dir( + rust_path.join("tests/ui"), + &mut dir_handling(args.keep_lto_tests, remove_error_pattern_tests), + &mut file_handling(args.keep_lto_tests, remove_error_pattern_tests), + false, + )?; + if let Some(retained_tests_list_path) = retained_tests_list_path { + check_for_dead_listed_tests(&rust_path, retained_tests_list_path)?; } let nb_parts = args.nb_parts.unwrap_or(0); if nb_parts > 0 { @@ -1097,7 +1236,7 @@ where env.get_mut("RUSTFLAGS").unwrap().clear(); let test_dir = format!("tests/{test_type}"); - let mut command: Vec<&dyn AsRef> = vec![ + let command: Vec<&dyn AsRef> = vec![ &"./x.py", &"test", &"--run", @@ -1112,19 +1251,85 @@ where &"--bypass-ignore-backends", ]; - if run_ignored_tests { - command.push(&"--"); - command.push(&"--ignored"); + run_test_command(&command, &rust_path, &env) +} + +/// Reads the list of tests at `list_path`, checking that each of them still exists in the rust +/// checkout at `rust_path` and that none is listed twice. +/// +/// Both problems make a line a no-op: the test it names is neither kept nor removed, so the test +/// suite silently drifts away from what the list claims to describe. +fn read_test_list(rust_path: &Path, list_path: &str) -> Result, String> { + let content = std::fs::read_to_string(list_path) + .map_err(|error| format!("Failed to read `{list_path}`: {error:?}"))?; + + let mut tests = Vec::new(); + let mut seen = HashSet::new(); + let mut missing = Vec::new(); + let mut duplicated = Vec::new(); + + for line in content.lines().map(|line| line.trim()).filter(|line| !line.is_empty()) { + if !seen.insert(line) { + duplicated.push(line); + continue; + } + if !rust_path.join(line.trim_end_matches('/')).exists() { + missing.push(line); + } + tests.push(line.to_string()); } - run_command_with_output_and_env(&command, Some(&rust_path), Some(&env))?; - Ok(()) + if missing.is_empty() && duplicated.is_empty() { + return Ok(tests); + } + + let mut error = format!("`{list_path}` is out of date:\n"); + if !missing.is_empty() { + error.push_str(&format!( + "\nThese tests no longer exist in `{rust_path}`:\n{missing}\n", + rust_path = rust_path.display(), + missing = missing.join("\n"), + )); + } + if !duplicated.is_empty() { + error.push_str(&format!( + "\nThese tests are listed more than once:\n{}\n", + duplicated.join("\n") + )); + } + error.push_str( + "\nEvery line must name a test that exists, exactly once, otherwise the line filters \ + nothing. Delete the stale lines, or update them to the test's current path.", + ); + Err(error) +} + +/// Checks that every test listed in `list_path` survived the filtering done by +/// `contains_ui_error_patterns`. +fn check_for_dead_listed_tests(rust_path: &Path, list_path: &str) -> Result<(), String> { + let listed_tests = std::fs::read_to_string(list_path) + .map_err(|error| format!("Failed to read `{list_path}`: {error:?}"))?; + let dead_tests = listed_tests + .lines() + .map(|line| line.trim()) + .filter(|line| !line.is_empty() && !rust_path.join(line).exists()) + .collect::>(); + if dead_tests.is_empty() { + return Ok(()); + } + Err(format!( + "The following tests listed in `{list_path}` are filtered out before the tests are run, \ + so listing them has no effect:\n{}\n\nThis happens when a test contains an error pattern \ + (like `//~` or `//@ known-bug`), in which case it should be removed from `{list_path}`, \ + or when it uses LTO, in which case it should be moved to `tests/failing-lto-tests.txt`.", + dead_tests.join("\n") + )) } fn test_rustc(env: &Env, args: &TestArg) -> Result<(), String> { - test_rustc_inner(env, args, |_| Ok(false), false, "run-make", false)?; - test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo", false)?; - test_rustc_inner(env, args, |_| Ok(false), false, "ui", false) + test_rustc_inner(env, args, |_| Ok(false), false, "run-make", None)?; + test_rustc_inner(env, args, |_| Ok(false), false, "run-make-cargo", None)?; + test_rustc_inner(env, args, |_| Ok(false), false, "ui", None) } fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { @@ -1134,7 +1339,7 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { retain_files_callback("tests/failing-run-make-tests.txt", "run-make"), false, "run-make", - true, + None, ); let run_make_cargo_result = test_rustc_inner( @@ -1142,8 +1347,8 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { args, retain_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"), false, - "run-make", - true, + "run-make-cargo", + None, ); let ui_result = test_rustc_inner( @@ -1152,36 +1357,51 @@ fn test_failing_rustc(env: &Env, args: &TestArg) -> Result<(), String> { retain_files_callback("tests/failing-ui-tests.txt", "ui"), false, "ui", - true, + Some("tests/failing-ui-tests.txt"), ); - run_make_result.and(run_make_cargo_result).and(ui_result) + combine_test_results([run_make_result, run_make_cargo_result, ui_result]) +} + +/// Combines the results of several test suites, letting a build system error win over a test +/// failure so that a broken build system is never reported to CI as the failures those suites +/// expect. +fn combine_test_results(results: [Result<(), String>; N]) -> Result<(), String> { + let mut tests_failed = false; + for result in results { + match result { + Ok(()) => {} + Err(error) if error == TESTS_FAILED_ERROR => tests_failed = true, + Err(error) => return Err(error), + } + } + if tests_failed { Err(TESTS_FAILED_ERROR.to_string()) } else { Ok(()) } } fn test_successful_rustc(env: &Env, args: &TestArg) -> Result<(), String> { test_rustc_inner( env, args, - remove_files_callback("tests/failing-ui-tests.txt", "ui"), + remove_files_callback("tests/failing-ui-tests.txt"), false, "ui", - false, + None, )?; test_rustc_inner( env, args, - remove_files_callback("tests/failing-run-make-tests.txt", "run-make"), + remove_files_callback("tests/failing-run-make-tests.txt"), false, "run-make", - false, + None, )?; test_rustc_inner( env, args, - remove_files_callback("tests/failing-run-make-tests.txt", "run-make-cargo"), + remove_files_callback("tests/failing-run-make-tests.txt"), false, "run-make-cargo", - false, + None, ) } @@ -1189,20 +1409,73 @@ fn test_failing_ui_pattern_tests(env: &Env, args: &TestArg) -> Result<(), String test_rustc_inner( env, args, - remove_files_callback("tests/failing-ice-tests.txt", "ui"), + remove_files_callback("tests/failing-ice-tests.txt"), true, "ui", - false, + None, ) } +fn run_ui_tests(env: &Env, args: &TestArg) -> Result<(), String> { + let mut env = env.clone(); + let rust_path = setup_rustc(&mut env, args)?; + + let extra = + if args.is_using_gcc_master_branch() { "" } else { " -Csymbol-mangling-version=v0" }; + + let rustc_args = format!( + "{test_flags} -Zcodegen-backend={backend} --sysroot {sysroot}{extra}", + test_flags = env.get("TEST_FLAGS").unwrap_or(&String::new()), + backend = args.config_info.cg_backend_path, + sysroot = args.config_info.sysroot_path, + extra = extra, + ); + + env.get_mut("RUSTFLAGS").unwrap().clear(); + + let mut command: Vec<&dyn AsRef> = vec![ + &"./x.py", + &"test", + &"--run", + &"always", + &"--stage", + &"0", + &"--set", + &"build.compiletest-allow-stage0=true", + &"--compiletest-rustc-args", + &rustc_args, + &"--bypass-ignore-backends", + &"--force-rerun", + ]; + + for test_name in &args.test_args { + command.push(test_name); + } + + run_test_command(&command, &rust_path, &env) +} + +/// Runs the command that actually runs a test suite, mapping its failure to `TESTS_FAILED_ERROR`. +fn run_test_command( + command: &[&dyn AsRef], + rust_path: &Path, + env: &Env, +) -> Result<(), String> { + if let Err(error) = run_command_with_output_and_env(command, Some(rust_path), Some(env)) { + // The failures themselves were already streamed to the console. + eprintln!("{error}"); + return Err(TESTS_FAILED_ERROR.to_string()); + } + Ok(()) +} + fn retain_files_callback<'a>( file_path: &'a str, test_type: &'a str, ) -> impl Fn(&Path) -> Result + 'a { move |rust_path| { - let files = std::fs::read_to_string(file_path).unwrap_or_default(); - let first_file_name = files.lines().next().unwrap_or(""); + let tests = read_test_list(rust_path, file_path)?; + let first_file_name = tests.first().map(String::as_str).unwrap_or(""); // If the first line ends with a `/`, we treat all lines in the file as a directory. if first_file_name.ends_with('/') { // Treat as directory @@ -1244,53 +1517,31 @@ fn retain_files_callback<'a>( } // Putting back only the failing ones. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) { - run_command(&[&"git", &"checkout", &"--", &file], Some(rust_path))?; - } - } else { - println!("Failed to read `{file_path}`, not putting back failing {test_type} tests"); + for test in &tests { + run_command(&[&"git", &"checkout", &"--", test], Some(rust_path))?; } Ok(true) } } -fn remove_files_callback<'a>( - file_path: &'a str, - test_type: &'a str, -) -> impl Fn(&Path) -> Result + 'a { +fn remove_files_callback(file_path: &str) -> impl Fn(&Path) -> Result + '_ { move |rust_path| { - let files = std::fs::read_to_string(file_path).unwrap_or_default(); - let first_file_name = files.lines().next().unwrap_or(""); + let tests = read_test_list(rust_path, file_path)?; + let first_file_name = tests.first().map(String::as_str).unwrap_or(""); // If the first line ends with a `/`, we treat all lines in the file as a directory. if first_file_name.ends_with('/') { // Removing the failing tests. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in - files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) - { - let path = rust_path.join(file); - if let Err(e) = remove_dir_all(&path) { - println!("Failed to remove directory `{}`: {}", path.display(), e); - } - } - } else { - println!( - "Failed to read `{file_path}`, not putting back failing {test_type} tests" - ); + for test in &tests { + let path = rust_path.join(test); + remove_dir_all(&path).map_err(|error| { + format!("Failed to remove directory `{}`: {error}", path.display()) + })?; } } else { // Removing the failing tests. - if let Ok(files) = std::fs::read_to_string(file_path) { - for file in - files.split('\n').map(|line| line.trim()).filter(|line| !line.is_empty()) - { - let path = rust_path.join(file); - remove_file(&path)?; - } - } else { - println!("Failed to read `{file_path}`, not putting back failing ui tests"); + for test in &tests { + remove_file(&rust_path.join(test))?; } } Ok(true) @@ -1342,3 +1593,58 @@ pub fn run() -> Result<(), String> { Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + + fn write_test_list(directory: &Path, content: &str) -> PathBuf { + let list_path = directory.join("failing-tests.txt"); + std::fs::write(&list_path, content).unwrap(); + list_path + } + + #[test] + fn test_combine_test_results() { + let tests_failed = || Err(TESTS_FAILED_ERROR.to_string()); + let build_error = || Err("could not clone rust".to_string()); + + assert_eq!(combine_test_results([Ok(()), Ok(())]), Ok(())); + assert_eq!(combine_test_results([Ok(()), tests_failed()]), tests_failed()); + assert_eq!(combine_test_results([Ok(()), build_error()]), build_error()); + // A build system error wins, whichever suite reported it. + assert_eq!(combine_test_results([tests_failed(), build_error()]), build_error()); + assert_eq!(combine_test_results([build_error(), tests_failed()]), build_error()); + } + + #[test] + fn test_read_test_list() { + let rust_path = std::env::temp_dir().join("cg_gcc_read_test_list"); + let _ = remove_dir_all(&rust_path); + create_dir(rust_path.join("tests/ui")).unwrap(); + std::fs::write(rust_path.join("tests/ui/alive.rs"), "").unwrap(); + + let list_path = write_test_list(&rust_path, "\ntests/ui/alive.rs\n \n"); + let list_path = list_path.display().to_string(); + assert_eq!( + read_test_list(&rust_path, &list_path), + Ok(vec!["tests/ui/alive.rs".to_string()]) + ); + + write_test_list(&rust_path, "tests/ui/alive.rs\ntests/ui/gone.rs\n"); + let error = read_test_list(&rust_path, &list_path).unwrap_err(); + assert!(error.contains("no longer exist"), "{error}"); + assert!(error.contains("tests/ui/gone.rs"), "{error}"); + + write_test_list(&rust_path, "tests/ui/alive.rs\ntests/ui/alive.rs\n"); + let error = read_test_list(&rust_path, &list_path).unwrap_err(); + assert!(error.contains("listed more than once"), "{error}"); + assert!(error.contains("tests/ui/alive.rs"), "{error}"); + + // Directories are listed with a trailing `/`. + write_test_list(&rust_path, "tests/ui/\n"); + assert_eq!(read_test_list(&rust_path, &list_path), Ok(vec!["tests/ui/".to_string()])); + + remove_dir_all(&rust_path).unwrap(); + } +} diff --git a/clippy.toml b/clippy.toml new file mode 100644 index 0000000000000..cf1593c691734 --- /dev/null +++ b/clippy.toml @@ -0,0 +1,3 @@ +disallowed-methods = [ + { path = "gccjit::types::Type::add_attribute", reason = "go through `type_::apply_struct_attributes` instead: an attribute set directly on a type would not be part of the `CodegenCx::struct_types` cache key, so it would silently change every other use of that type" }, +] diff --git a/doc/tips.md b/doc/tips.md index ff92566d4a1ab..dc40ee4d39952 100644 --- a/doc/tips.md +++ b/doc/tips.md @@ -58,7 +58,7 @@ If you wish to build a custom sysroot, pass the path of your sysroot source to ` ### How to generate GIMPLE If you need to check what gccjit is generating (GIMPLE), then take a look at how to -generate it in [gimple.md](./doc/gimple.md). +generate it in [gimple.md](./gimple.md). ### How to build a cross-compiling libgccjit diff --git a/libgccjit.version b/libgccjit.version index 5eef70260466f..62417a80f827e 100644 --- a/libgccjit.version +++ b/libgccjit.version @@ -1 +1 @@ -6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 +badf78d09d16e66f4ca07971c51aa6a227558d4f diff --git a/rust-toolchain b/rust-toolchain index 56fcfdff1c719..0c81f7c7c7398 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-04-29" +channel = "nightly-2026-09-18" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] diff --git a/src/abi.rs b/src/abi.rs index 6a05f1cbbeef1..09e009700a80c 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -73,7 +73,7 @@ impl GccType for CastTarget { args.push(cx.type_ix(rem_bytes * 8)); } - cx.type_struct(&args, false) + cx.type_struct(&args, &[]) } } diff --git a/src/asm.rs b/src/asm.rs index 420bf1e7a31c1..e84cf54cb1147 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -681,6 +681,7 @@ fn explicit_reg_to_gcc(reg: InlineAsmReg) -> &'static str { } InlineAsmReg::Arm(reg) => reg.name(), InlineAsmReg::AArch64(reg) => reg.name(), + InlineAsmReg::M68k(reg) => reg.name(), _ => unimplemented!(), } } diff --git a/src/attributes.rs b/src/attributes.rs index a5cc44a46e154..87c989031678d 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -12,6 +12,8 @@ use rustc_middle::ty; #[cfg(feature = "master")] use rustc_target::spec::Arch; +#[cfg(feature = "master")] +use crate::base; use crate::context::CodegenCx; use crate::gcc_util::to_gcc_features; @@ -102,6 +104,16 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } else { codegen_fn_attrs.inline }; + // GCC drops `weak` from a function that is also `inline`, leaving the symbol strong, and + // the linkage is what has to survive. `inline(never)` does not conflict. + let inline = match inline { + InlineAttr::Always | InlineAttr::Hint | InlineAttr::Force { .. } + if codegen_fn_attrs.linkage.is_some_and(base::linkage_needs_weak_attribute) => + { + InlineAttr::None + } + inline => inline, + }; if let Some(attr) = inline_attr(cx, inline, instance) { if let FnAttribute::AlwaysInline = attr { func.add_attribute(FnAttribute::Inline); diff --git a/src/back/lto.rs b/src/back/lto.rs index 98f9abdb05c4c..b0de1ead56ed1 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -36,7 +36,8 @@ use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; use crate::diagnostics::LtoBitcodeFromRlib; -use crate::{GccCodegenBackend, GccContext, LtoMode, to_gcc_opt_level}; +use crate::gcc_util::new_context; +use crate::{GccCodegenBackend, GccContext, LtoMode, SyncContext, to_gcc_opt_level}; struct LtoData { // FIXME(antoyo): use symbols_below_threshold. diff --git a/src/base.rs b/src/base.rs index 101af0bb0bff1..7cb734d523273 100644 --- a/src/base.rs +++ b/src/base.rs @@ -3,7 +3,9 @@ use std::env; use std::sync::Arc; use std::time::Instant; -use gccjit::{CType, Context, FunctionType, GlobalKind}; +#[cfg(feature = "master")] +use gccjit::VarAttribute; +use gccjit::{CType, FunctionType, GlobalKind}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; @@ -21,7 +23,8 @@ use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; -use crate::{GccContext, LtoMode, SharedTargetInfo, SyncContext, gcc_util, new_context}; +use crate::gcc_util::new_context; +use crate::{GccContext, LtoMode, SharedTargetInfo, SyncContext}; #[cfg(feature = "master")] pub fn visibility_to_gcc(visibility: Visibility) -> gccjit::Visibility { @@ -41,32 +44,72 @@ pub fn symbol_visibility_to_gcc(visibility: SymbolVisibility) -> gccjit::Visibil } } +/// The kind of a global *definition* with an explicit `#[linkage]`. +/// +/// The flavours that another object file is allowed to override also need +/// `global_linkage_attribute` from the caller: `GlobalKind` alone cannot express weakness. pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { match linkage { - Linkage::External => GlobalKind::Imported, - Linkage::AvailableExternally => GlobalKind::Imported, - Linkage::LinkOnceAny => unimplemented!(), - Linkage::LinkOnceODR => unimplemented!(), - Linkage::WeakAny => unimplemented!(), - Linkage::WeakODR => unimplemented!(), - Linkage::Internal => GlobalKind::Internal, - Linkage::ExternalWeak => GlobalKind::Imported, // FIXME(antoyo): should be weak linkage. - Linkage::Common => unimplemented!(), + Linkage::External => GlobalKind::Exported, + // libgccjit cannot emit a definition that the linker discards in favour of the one in + // another object file, so emit a private copy of it instead. + Linkage::AvailableExternally | Linkage::Internal => GlobalKind::Internal, + // libgccjit exposes no comdat, so `weak` stands in for the linkonce flavours. + Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => GlobalKind::Exported, + } +} + +/// The attribute a global *definition* needs on top of its [`GlobalKind`] to get this linkage. +#[cfg(feature = "master")] +pub fn global_linkage_attribute<'gcc>(linkage: Linkage) -> Option> { + match linkage { + Linkage::Common => Some(VarAttribute::Common), + _ if linkage_needs_weak_attribute(linkage) => Some(VarAttribute::Weak), + _ => None, } } +/// The type of a function *definition* with an explicit `#[linkage]`. +/// +/// The flavours that another object file is allowed to override also need +/// `linkage_needs_weak_attribute` from the caller: `FunctionType` alone cannot express weakness. pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { match linkage { Linkage::External => FunctionType::Exported, - // FIXME(antoyo): set the attribute externally_visible. - Linkage::AvailableExternally => FunctionType::Extern, - Linkage::LinkOnceAny => unimplemented!(), - Linkage::LinkOnceODR => unimplemented!(), - Linkage::WeakAny => FunctionType::Exported, // FIXME(antoyo): should be similar to linkonce. - Linkage::WeakODR => unimplemented!(), - Linkage::Internal => FunctionType::Internal, - Linkage::ExternalWeak => unimplemented!(), - Linkage::Common => unimplemented!(), + // libgccjit cannot emit a definition that the linker discards in favour of the one in + // another object file, so emit a private copy of it instead. + Linkage::AvailableExternally | Linkage::Internal => FunctionType::Internal, + // libgccjit exposes no comdat, so `weak` stands in for every overridable flavour. + Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => FunctionType::Exported, + } +} + +/// Whether a definition with this linkage must carry the `weak` attribute, so that a strong +/// definition in another object file wins over it instead of clashing with it. +/// +/// `common` is in here for functions only: GCC honours that attribute on a variable, but drops it +/// on a function, so a common function falls back to weak. Globals go through +/// `global_linkage_attribute` instead. +#[cfg(feature = "master")] +pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { + match linkage { + Linkage::LinkOnceAny + | Linkage::LinkOnceODR + | Linkage::WeakAny + | Linkage::WeakODR + | Linkage::ExternalWeak + | Linkage::Common => true, + Linkage::External | Linkage::AvailableExternally | Linkage::Internal => false, } } @@ -243,6 +286,11 @@ pub fn compile_codegen_unit( // ... and now that we have everything pre-defined, fill out those definitions. for &(mono_item, item_data) in &mono_items { mono_item.define::>(&mut cx, cgu_name.as_str(), item_data); + + // Now that this function's blocks all exist, fill in the cleanup + // regions reconstructed from MIR while lowering its `invoke`s. + #[cfg(feature = "master")] + cx.populate_cleanup_regions(); } // If this codegen unit contains the main function, also create the diff --git a/src/builder.rs b/src/builder.rs index 0a88085960e89..6de2827e63dee 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -33,9 +33,11 @@ use rustc_target::callconv::FnAbi; use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, X86Abi}; use crate::abi::FnAbiGccExt; +use crate::builder; use crate::common::{SignType, TypeReflection, type_is_pointer}; use crate::context::CodegenCx; -use crate::diagnostics; +#[cfg(feature = "master")] +use crate::context::PendingCleanup; use crate::intrinsic::llvm; use crate::type_of::LayoutGccExt; @@ -64,6 +66,33 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.value_counter.get() } + /// Tell GCC that `pointer` is `align`-aligned, so that the bulk memory builtins can widen their + /// accesses: a pointer cast to an aligned type would be dropped as a useless conversion. + fn assume_aligned(&mut self, pointer: RValue<'gcc>, align: Align) -> RValue<'gcc> { + if align.bytes() <= 1 { + return pointer; + } + let assume_aligned = self.context.get_builtin_function("__builtin_assume_aligned"); + let alignment = self.context.new_rvalue_from_long(self.type_size_t(), align.bytes() as i64); + let pointer_type = pointer.get_type(); + let const_void_ptr_type = self.context.new_type::<()>().make_const().make_pointer(); + let pointer = self.context.new_cast(self.location, pointer, const_void_ptr_type); + let aligned = self.context.new_call(self.location, assume_aligned, &[pointer, alignment]); + self.context.new_cast(self.location, aligned, pointer_type) + } + + /// GCC ignores a volatile qualifier on the pointers given to `memcpy`/`memmove`/`memset` and + /// happily deletes the call, so a barrier is what keeps the operation observable. The pointers + /// are fed to it because a clobber alone does not reach memory GCC believes never escapes. + fn volatile_barrier(&mut self, pointers: &[RValue<'gcc>]) { + let barrier = self.block.add_extended_asm(self.location, ""); + for pointer in pointers { + barrier.add_input_operand(None, "r", *pointer); + } + barrier.add_clobber("memory"); + barrier.set_volatile_flag(true); + } + fn atomic_extremum( &mut self, operation: ExtremumOperation, @@ -316,6 +345,45 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.block.get_function() } + /// Shared implementation of `call` and `tail_call`. For tail call it is important that this + /// returns a bare call, and not the result assigned to a local, or the result of `add_eval`. + #[allow(clippy::too_many_arguments)] + fn build_call( + &mut self, + typ: Type<'gcc>, + fn_abi: Option<&FnAbi<'tcx, Ty<'tcx>>>, + func: RValue<'gcc>, + return_slot: ReturnSlot< as BackendTypes>::Value>, + args: &[RValue<'gcc>], + funclet: Option<&Funclet>, + must_tail: bool, + ) -> RValue<'gcc> { + // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. + let args = match return_slot { + ReturnSlot::Direct => Cow::Borrowed(args), + ReturnSlot::Indirect(sret_ptr) => { + let mut args = args.to_vec(); + // Prepend the indirect return pointer + args.insert(0, sret_ptr); + Cow::Owned(args) + } + }; + // FIXME(antoyo): remove when having a proper API. + let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; + let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { + // FIXME(antoyo): remove when the API supports a different type for functions. + let func: Function<'gcc> = self.cx.rvalue_as_function(func); + self.function_call(func, &args, funclet, must_tail) + } else { + // If it's a not function that was defined, it's a function pointer. + self.function_ptr_call(typ, fn_abi, func, &args, funclet, must_tail) + }; + if let Some(_fn_abi) = fn_abi { + // FIXME(bjorn3): Apply function attributes + } + call + } + pub fn function_call( &mut self, func: Function<'gcc>, @@ -614,7 +682,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { _funclet: Option<&Funclet>, instance: Option>, ) -> RValue<'gcc> { - let try_block = self.current_func().new_block("try"); + let current_func = self.current_func(); + let try_region = current_func.new_region(self.location); + let try_block = try_region.new_block("try"); let current_block = self.block; self.block = try_block; @@ -622,17 +692,25 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let call = self.call(typ, fn_attrs, fn_abi, func, return_slot, args, None, instance); self.block = current_block; - let return_value = - self.current_func().new_local(self.location, call.get_type(), "invokeResult"); + let return_value = self.new_temp(current_func, self.location, call.get_type()); try_block.add_assignment(self.location, return_value, call); try_block.end_with_jump(self.location, then); - if self.cleanup_blocks.borrow().contains(&catch) { - self.block.add_try_finally(self.location, try_block, catch); + if self.cx.landing_pads.borrow().contains(&catch) { + let cleanup_region = current_func.new_region(self.location); + self.block.add_cleanup(self.location, try_region, cleanup_region); + self.cx + .pending_cleanups + .borrow_mut() + .push(PendingCleanup { region: cleanup_region, landing_pad: catch }); } else { - self.block.add_try_catch(self.location, try_block, catch); + let catch_region = current_func.new_region(self.location); + for clone in gccjit::clone_blocks(&[catch]) { + catch_region.add_block(clone); + } + self.block.add_try_catch(self.location, try_region, catch_region); } self.block.end_with_jump(self.location, then); @@ -671,8 +749,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { if return_type == void_type { self.block.end_with_void_return(self.location) } else { - let return_value = - self.current_func().new_local(self.location, return_type, "unreachableReturn"); + let trap = self.context.get_builtin_function("__builtin_trap"); + self.block.add_eval(self.location, self.context.new_call(self.location, trap, &[])); + let return_value = self.new_temp(self.current_func(), self.location, return_type); self.block.end_with_return(self.location, return_value) } } @@ -1405,47 +1484,53 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn memcpy( &mut self, dst: RValue<'gcc>, - _dst_align: Align, + dst_align: Align, src: RValue<'gcc>, - _src_align: Align, + src_align: Align, size: RValue<'gcc>, flags: MemFlags, _tt: Option, // Autodiff TypeTrees are LLVM-only, ignored in GCC backend ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memcpy not supported"); let size = self.intcast(size, self.type_size_t(), false); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); + let dst = self.assume_aligned(dst, dst_align); let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + let src = self.assume_aligned(src, src_align); let memcpy = self.context.get_builtin_function("memcpy"); - // FIXME(antoyo): handle aligns and is_volatile. self.block.add_eval( self.location, self.context.new_call(self.location, memcpy, &[dst, src, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[dst, src]); + } } fn memmove( &mut self, dst: RValue<'gcc>, - _dst_align: Align, + dst_align: Align, src: RValue<'gcc>, - _src_align: Align, + src_align: Align, size: RValue<'gcc>, flags: MemFlags, ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memmove not supported"); let size = self.intcast(size, self.type_size_t(), false); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let dst = self.pointercast(dst, self.type_i8p()); + let dst = self.assume_aligned(dst, dst_align); let src = self.pointercast(src, self.type_ptr_to(self.type_void())); + let src = self.assume_aligned(src, src_align); let memmove = self.context.get_builtin_function("memmove"); - // FIXME(antoyo): handle is_volatile. self.block.add_eval( self.location, self.context.new_call(self.location, memmove, &[dst, src, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[dst, src]); + } } fn memset( @@ -1453,20 +1538,22 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { ptr: RValue<'gcc>, fill_byte: RValue<'gcc>, size: RValue<'gcc>, - _align: Align, + align: Align, flags: MemFlags, ) { assert!(!flags.contains(MemFlags::NONTEMPORAL), "non-temporal memset not supported"); - let _is_volatile = flags.contains(MemFlags::VOLATILE); let ptr = self.pointercast(ptr, self.type_i8p()); + let ptr = self.assume_aligned(ptr, align); let memset = self.context.get_builtin_function("memset"); - // FIXME(antoyo): handle align and is_volatile. let fill_byte = self.context.new_cast(self.location, fill_byte, self.i32_type); let size = self.intcast(size, self.type_size_t(), false); self.block.add_eval( self.location, self.context.new_call(self.location, memset, &[ptr, fill_byte, size]), ); + if flags.contains(MemFlags::VOLATILE) { + self.volatile_barrier(&[ptr]); + } } fn vscale(&mut self, _: Self::Type) -> Self::Value { @@ -1606,18 +1693,12 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: insert the current block in a variable so that a later call to invoke knows to // generate a try/finally instead of a try/catch for this block. - self.cleanup_blocks.borrow_mut().insert(self.block); - - let eh_pointer_builtin = - self.cx.context.get_target_builtin_function("__builtin_eh_pointer"); - let zero = self.cx.context.new_rvalue_zero(self.int_type); - let ptr = self.cx.context.new_call(self.location, eh_pointer_builtin, &[zero]); - - let value1_type = self.u8_type.make_pointer(); - let ptr = self.cx.context.new_cast(self.location, ptr, value1_type); - let value1 = ptr; - let value2 = zero; // FIXME(antoyo): set the proper value here (the type of exception?). + self.cx.landing_pads.borrow_mut().insert(self.block); + // A cleanup resumes by falling through: it never inspects the exception + // object. + let value1 = self.context.new_null(self.u8_type.make_pointer()); + let value2 = self.context.new_rvalue_zero(self.i32_type); (value1, value2) } @@ -1633,18 +1714,13 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { } fn filter_landing_pad(&mut self, pers_fn: Function<'gcc>) { - // FIXME(antoyo): generate the correct landing pad - self.cleanup_landing_pad(pers_fn); + self.set_personality_fn(pers_fn); } #[cfg(feature = "master")] - fn resume(&mut self, exn0: RValue<'gcc>, _exn1: RValue<'gcc>) { - let exn_type = exn0.get_type(); - let exn = self.context.new_cast(self.location, exn0, exn_type); - let unwind_resume = self.context.get_target_builtin_function("__builtin_unwind_resume"); - self.llbb() - .add_eval(self.location, self.context.new_call(self.location, unwind_resume, &[exn])); - self.unreachable(); + fn resume(&mut self, _exn0: RValue<'gcc>, _exn1: RValue<'gcc>) { + // End the cleanup by falling off the end of its region body. + self.block.end_with_fallthrough(self.location); } #[cfg(not(feature = "master"))] @@ -1786,45 +1862,35 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { funclet: Option<&Funclet>, _instance: Option>, ) -> RValue<'gcc> { - // FIXME: change this in the `rustc_codegen_gcc` repo after the sync, to use the `libgccjit` indirect return suppport. - let args = match return_slot { - ReturnSlot::Direct => args.to_vec(), - ReturnSlot::Indirect(sret_ptr) => { - let mut args = args.to_vec(); - // Prepend the indirect return pointer - args.insert(0, sret_ptr); - args - } - }; - // FIXME(antoyo): remove when having a proper API. - let gcc_func = unsafe { std::mem::transmute::, Function<'gcc>>(func) }; - let call = if self.functions.borrow().values().any(|value| *value == gcc_func) { - // FIXME(antoyo): remove when the API supports a different type for functions. - let func: Function<'gcc> = self.cx.rvalue_as_function(func); - self.function_call(func, &args, funclet) - } else { - // If it's a not function that was defined, it's a function pointer. - self.function_ptr_call(typ, fn_abi, func, &args, funclet) - }; - if let Some(_fn_abi) = fn_abi { - // FIXME(bjorn3): Apply function attributes - } - call + self.build_call(typ, fn_abi, func, return_slot, args, funclet, false) } fn tail_call( &mut self, _llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, - _fn_abi: &FnAbi<'tcx, Ty<'tcx>>, - _llfn: Self::Value, - _return_slot: ReturnSlot, - _args: &[Self::Value], - _funclet: Option<&Self::Funclet>, + fn_abi: &FnAbi<'tcx, Ty<'tcx>>, + llfn: Self::Value, + return_slot: ReturnSlot, + args: &[Self::Value], + funclet: Option<&Self::Funclet>, _instance: Option>, ) { - // FIXME: implement support for explicit tail calls like rustc_codegen_llvm. - self.tcx.dcx().emit_fatal(diagnostics::ExplicitTailCallsUnsupported); + // `emit_call` returns a bare call for here, it has not been assigned or passed to add_eval. + let call = self.build_call(llty, Some(fn_abi), llfn, return_slot, args, funclet, true); + call.set_require_tail_call(true); + + let return_type = self.current_func().get_return_type(); + let void_type = self.context.new_type::<()>(); + + if return_type == void_type { + // For a void return the call is emitted as its own statement, immediately + // followed by a void return, so the tail call sits in tail position. + self.llbb().add_eval(self.location, call); + self.ret_void(); + } else { + self.ret(call) + } } fn zext(&mut self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { diff --git a/src/common.rs b/src/common.rs index 6bd186f1121fc..21d92c6cc2936 100644 --- a/src/common.rs +++ b/src/common.rs @@ -12,6 +12,7 @@ use rustc_session::PointerAuthSchema; use crate::consts::const_alloc_to_gcc; use crate::context::{CodegenCx, new_array_type}; +use crate::type_::struct_attributes; use crate::type_of::LayoutGccExt; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -125,78 +126,86 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } } +/// The element type and element count of the array used to represent a run of `len` constant bytes. +/// +/// Larger integers are used where possible: this reduces the number of rvalues, which is a +/// significant memory saving on constant-heavy crates. +fn byte_run_shape<'gcc>(cx: &CodegenCx<'gcc, '_>, len: usize) -> (Type<'gcc>, u64) { + match len % 8 { + 0 => (cx.context.new_type::(), len as u64 / 8), + 4 => (cx.context.new_type::(), len as u64 / 4), + _ => (cx.context.new_type::(), len as u64), + } +} + +/// The type [`bytes_in_context`] gives a run of `len` constant bytes. +/// +/// Exposed separately so that the type of a constant allocation can be computed before any of its +/// rvalues exist; see [`crate::consts::const_alloc_type`]. +/// +/// The result is cached because `gcc_jit_context_new_array_type` mints a fresh type every call. +/// Two equal-but-distinct array types would key [`CodegenCx::type_struct`] differently and so +/// produce two distinct anonymous structs, and libgccjit compares struct types by identity. +pub fn bytes_type_in_context<'gcc>(cx: &CodegenCx<'gcc, '_>, len: usize) -> Type<'gcc> { + let (element_type, count) = byte_run_shape(cx, len); + if let Some(&typ) = cx.byte_array_types.borrow().get(&(element_type, count)) { + return typ; + } + let typ = new_array_type(cx.context, None, element_type, count); + cx.byte_array_types.borrow_mut().insert((element_type, count), typ); + typ +} + +// FIXME(FractalFir): Consider using `global_set_initializer` instead. Before this is done, we need to confirm that +// `global_set_initializer` is more memory efficient than the current solution. +// `global_set_initializer` calls `global_set_initializer_rvalue` under the hood - does it generate an array of rvalues, +// or is it using a more efficient representation? pub fn bytes_in_context<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, bytes: &[u8]) -> RValue<'gcc> { - // Instead of always using an array of bytes, use an array of larger integers of target endianness - // if possible. This reduces the amount of `rvalues` we use, which reduces memory usage significantly. - // - // FIXME(FractalFir): Consider using `global_set_initializer` instead. Before this is done, we need to confirm that - // `global_set_initializer` is more memory efficient than the current solution. - // `global_set_initializer` calls `global_set_initializer_rvalue` under the hood - does it generate an array of rvalues, - // or is it using a more efficient representation? - match bytes.len() % 8 { + let typ = bytes_type_in_context(cx, bytes.len()); + let (element_type, _) = byte_run_shape(cx, bytes.len()); + let context = &cx.context; + // Since we are representing arbitrary byte runs as integers, we need to follow the target + // endianness. + let endian = cx.sess().target.options.endian; + let elements: Vec<_> = match bytes.len() % 8 { 0 => { - debug_assert_eq!( - bytes.len() % 8, - 0, - "bytes length is not a multiple of 8, so bytes.as_chunks will have a remainder" - ); - let context = &cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 8); - let elements: Vec<_> = bytes - .as_chunks::<8>() - .0 + let (arrays, remainder) = bytes.as_chunks::<8>(); + debug_assert!(remainder.is_empty()); + arrays .iter() .map(|&arr| { context.new_rvalue_from_long( - byte_type, - // Since we are representing arbitrary byte runs as integers, we need to follow the target - // endianness. - match cx.sess().target.options.endian { + element_type, + match endian { rustc_abi::Endian::Little => u64::from_le_bytes(arr) as i64, rustc_abi::Endian::Big => u64::from_be_bytes(arr) as i64, }, ) }) - .collect(); - context.new_array_constructor(None, typ, &elements) + .collect() } 4 => { - debug_assert_eq!( - bytes.len() % 4, - 0, - "bytes length is not a multiple of 4, so bytes.as_chunks will have a remainder" - ); - let context = &cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64 / 4); - let elements: Vec<_> = bytes - .as_chunks::<4>() - .0 + let (arrays, remainder) = bytes.as_chunks::<4>(); + debug_assert!(remainder.is_empty()); + arrays .iter() .map(|&arr| { context.new_rvalue_from_int( - byte_type, - match cx.sess().target.options.endian { + element_type, + match endian { rustc_abi::Endian::Little => u32::from_le_bytes(arr) as i32, rustc_abi::Endian::Big => u32::from_be_bytes(arr) as i32, }, ) }) - .collect(); - context.new_array_constructor(None, typ, &elements) - } - _ => { - let context = cx.context; - let byte_type = context.new_type::(); - let typ = new_array_type(context, None, byte_type, bytes.len() as u64); - let elements: Vec<_> = bytes - .iter() - .map(|&byte| context.new_rvalue_from_int(byte_type, byte as i32)) - .collect(); - context.new_array_constructor(None, typ, &elements) + .collect() } - } + _ => bytes + .iter() + .map(|&byte| context.new_rvalue_from_int(element_type, byte as i32)) + .collect(), + }; + context.new_array_constructor(None, typ, &elements) } pub fn type_is_pointer(typ: Type<'_>) -> bool { @@ -298,7 +307,7 @@ impl<'gcc, 'tcx> ConstCodegenMethods for CodegenCx<'gcc, 'tcx> { fn const_struct(&self, values: &[RValue<'gcc>], packed: bool) -> RValue<'gcc> { let fields: Vec<_> = values.iter().map(|value| value.get_type()).collect(); // FIXME(antoyo): cache the type? It's anonymous, so probably not. - let typ = self.type_struct(&fields, packed); + let typ = self.type_struct(&fields, &struct_attributes(packed, None)); let struct_type = typ.is_struct().expect("struct type"); self.context.new_struct_constructor(None, struct_type.as_type(), None, values) } diff --git a/src/consts.rs b/src/consts.rs index 6c3b404547cfc..e6acbc6625d44 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -1,3 +1,5 @@ +use std::ops::Range; + #[cfg(feature = "master")] use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; @@ -11,15 +13,18 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - self, ConstAllocation, ErrorHandled, Scalar as InterpScalar, read_target_uint, + self, Allocation, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, + read_target_uint, }; +use rustc_middle::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance}; use rustc_span::def_id::DefId; use rustc_span::{bug, span_bug}; -use crate::base; +use crate::common::bytes_type_in_context; use crate::context::CodegenCx; +use crate::type_::struct_attributes; use crate::type_of::LayoutGccExt; pub(crate) fn const_alloc_to_gcc<'gcc, 'tcx>( @@ -99,15 +104,21 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { let is_thread_local = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); let global = self.get_static_inner(def_id, val_llty); - #[cfg(feature = "master")] - if global.to_rvalue().get_type() != val_llty { - global.to_rvalue().set_type(val_llty); - } + debug_assert_eq!( + global.to_rvalue().get_type(), + val_llty, + "`predefine_static` declared this global with a type its initializer does not have" + ); // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); - global.global_set_initializer_rvalue(value); + // A common symbol is storage the linker allocates and zero-fills, so giving the definition + // an initializer — even an all-zero one — takes it back out of `.comm`. A non-zero one is + // kept: the symbol is then an ordinary definition, which is what GCC does with it too. + if attrs.linkage != Some(Linkage::Common) || !is_zero_initializer(alloc) { + global.global_set_initializer_rvalue(value); + } // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -237,15 +248,14 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { return global; } - // FIXME: Once we stop removing globals in `codegen_static`, we can uncomment this code. - // let defined_in_current_codegen_unit = - // self.codegen_unit.items().contains_key(&MonoItem::Static(def_id)); - // assert!( - // !defined_in_current_codegen_unit, - // "consts::get_static() should always hit the cache for \ - // statics defined in the same CGU, but did not for `{:?}`", - // def_id - // ); + let defined_in_current_codegen_unit = + self.codegen_unit.items().contains_key(&MonoItem::Static(def_id)); + assert!( + !defined_in_current_codegen_unit, + "consts::get_static() should always hit the cache for \ + statics defined in the same CGU, but did not for `{:?}`", + def_id + ); let sym = self.tcx.symbol_name(instance).name; let fn_attrs = self.tcx.codegen_fn_attrs(def_id); @@ -309,75 +319,133 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global } } -/// Converts a given const alloc to a gcc Rvalue, without any caching or deduplication. -/// YOU SHOULD NOT call this function directly - that may break the semantics of Rust. -/// Use `const_data_from_alloc` instead. -pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( - cx: &CodegenCx<'gcc, '_>, - alloc: ConstAllocation<'_>, -) -> RValue<'gcc> { - let alloc = alloc.inner(); - let mut llvals = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); - let dl = cx.data_layout(); - let pointer_size = dl.pointer_size().bytes() as usize; +/// One field of the packed struct that a constant allocation is lowered to. +enum AllocField { + /// A run of bytes carrying no provenance. + Bytes { range: Range }, + /// A pointer with provenance, occupying one target pointer worth of bytes. + Pointer { offset: usize, prov: CtfeProvenance }, +} + +/// The field-by-field shape of `alloc`. +/// +/// [`const_alloc_to_gcc_uncached`] and [`const_alloc_type`] have to agree exactly on this, down to +/// the empty trailing run an allocation ending on a pointer produces, so both derive the shape here +/// instead of each walking the allocation on its own. +fn alloc_fields(cx: &CodegenCx<'_, '_>, alloc: &interpret::Allocation) -> Vec { + let pointer_size = cx.data_layout().pointer_size().bytes() as usize; + let mut fields = Vec::with_capacity(alloc.provenance().ptrs().len() + 1); let mut next_offset = 0; for &(offset, prov) in alloc.provenance().ptrs().iter() { - let alloc_id = prov.alloc_id(); let offset = offset.bytes(); assert_eq!(offset as usize as u64, offset); let offset = offset as usize; if offset > next_offset { - // This `inspect` is okay since we have checked that it is not within a pointer with provenance, it - // is within the bounds of the allocation, and it doesn't affect interpreter execution - // (we inspect the result after interpreter execution). Any undef byte is replaced with - // some arbitrary byte value. - // - // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(next_offset..offset); - llvals.push(cx.const_bytes(bytes)); + fields.push(AllocField::Bytes { range: next_offset..offset }); } - let ptr_offset = read_target_uint( - dl.endian, - // This `inspect` is okay since it is within the bounds of the allocation, it doesn't - // affect interpreter execution (we inspect the result after interpreter execution), - // and we properly interpret the provenance as a relocation pointer offset. - alloc.inspect_with_uninit_and_ptr_outside_interpreter(offset..(offset + pointer_size)), - ) - .expect("const_alloc_to_gcc_uncached: could not read relocation pointer") - as u64; - - let address_space = cx.tcx.global_alloc(alloc_id).address_space(cx); - - llvals.push(cx.scalar_to_backend( - InterpScalar::from_pointer( - interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), - &cx.tcx, - ), - abi::Scalar::Initialized { - value: Primitive::Pointer(address_space), - valid_range: WrappingRange::full(dl.pointer_size()), - }, - cx.type_i8p_ext(address_space), - )); + fields.push(AllocField::Pointer { offset, prov }); next_offset = offset + pointer_size; } if alloc.len() >= next_offset { - let range = next_offset..alloc.len(); - // This `inspect` is okay since we have check that it is after all provenance, it is - // within the bounds of the allocation, and it doesn't affect interpreter execution (we - // inspect the result after interpreter execution). Any undef byte is replaced with some - // arbitrary byte value. - // - // FIXME: relay undef bytes to codegen as undef const bytes - let bytes = alloc.inspect_with_uninit_and_ptr_outside_interpreter(range); - llvals.push(cx.const_bytes(bytes)); + fields.push(AllocField::Bytes { range: next_offset..alloc.len() }); } + fields +} + +/// The type [`const_alloc_to_gcc`] gives `alloc`, computed without building any rvalue. +/// +/// This lets `predefine_static` declare a static's global with the type its initializer will have, +/// so that the two never disagree. It must not reach for the rvalue of anything it points at: +/// during the predefine pass the pointee may not be declared yet, and `alloc_to_backend` would +/// declare it with the wrong type behind our back. +pub(crate) fn const_alloc_type<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, +) -> Type<'gcc> { + let fields: Vec<_> = alloc_fields(cx, alloc.inner()) + .into_iter() + .map(|field| match field { + AllocField::Bytes { range } => bytes_type_in_context(cx, range.len()), + AllocField::Pointer { prov, .. } => { + let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); + cx.type_i8p_ext(address_space) + } + }) + .collect(); + cx.type_struct(&fields, &struct_attributes(true, None)) +} + +/// Converts a given const alloc to a gcc Rvalue, without any caching or deduplication. +/// YOU SHOULD NOT call this function directly - that may break the semantics of Rust. +/// Use `const_data_from_alloc` instead. +pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( + cx: &CodegenCx<'gcc, '_>, + alloc: ConstAllocation<'_>, +) -> RValue<'gcc> { + let alloc = alloc.inner(); + let dl = cx.data_layout(); + let pointer_size = dl.pointer_size(); + + let llvals: Vec<_> = alloc_fields(cx, alloc) + .into_iter() + .map(|field| match field { + AllocField::Bytes { range } => { + // This `inspect` is okay since we have checked that it is not within a pointer with + // provenance, it is within the bounds of the allocation, and it doesn't affect + // interpreter execution (we inspect the result after interpreter execution). Any + // undef byte is replaced with some arbitrary byte value. + // + // FIXME: relay undef bytes to codegen as undef const bytes + cx.const_bytes(alloc.inspect_with_uninit_and_ptr_outside_interpreter(range)) + } + AllocField::Pointer { offset, prov } => { + let ptr_offset = read_target_uint( + dl.endian, + // This `inspect` is okay since it is within the bounds of the allocation, it + // doesn't affect interpreter execution (we inspect the result after interpreter + // execution), and we properly interpret the provenance as a relocation pointer + // offset. + alloc.inspect_with_uninit_and_ptr_outside_interpreter( + offset..(offset + pointer_size.bytes() as usize), + ), + ) + .expect("const_alloc_to_gcc_uncached: could not read relocation pointer") + as u64; + + let address_space = cx.tcx.global_alloc(prov.alloc_id()).address_space(cx); + + cx.scalar_to_backend( + InterpScalar::from_pointer( + interpret::Pointer::new(prov, Size::from_bytes(ptr_offset)), + &cx.tcx, + ), + abi::Scalar::Initialized { + value: Primitive::Pointer(address_space), + valid_range: WrappingRange::full(pointer_size), + }, + cx.type_i8p_ext(address_space), + ) + } + }) + .collect(); + // FIXME(bjorn3) avoid wrapping in a struct when there is only a single element. cx.const_struct(&llvals, true) } +/// Whether this allocation is all zeroes, and so needs no initializer to be spelled out. +fn is_zero_initializer(alloc: &Allocation) -> bool { + alloc.provenance().ptrs().is_empty() + // This `inspect` is okay: it is within the bounds of the allocation, there is no provenance + // to misread, and it does not affect interpreter execution. + && alloc + .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.size().bytes_usize()) + .iter() + .all(|&byte| byte == 0) +} + fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, @@ -394,10 +462,10 @@ fn check_and_apply_linkage<'gcc, 'tcx>( ) -> LValue<'gcc> { let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); if let Some(linkage) = attrs.import_linkage { - // Declare a symbol `foo` with the desired linkage. - let global1 = - cx.declare_global_with_linkage(sym, cx.type_i8(), base::global_linkage_to_gcc(linkage)); + // Whatever the flavour, an import is an undefined reference to a symbol defined elsewhere. + let global1 = cx.declare_global_with_linkage(sym, cx.type_i8(), GlobalKind::Imported); + // Only `extern_weak` lets the symbol stay unresolved, in which case it reads as null. if linkage == Linkage::ExternalWeak { #[cfg(feature = "master")] global1.add_attribute(VarAttribute::Weak); @@ -411,8 +479,13 @@ fn check_and_apply_linkage<'gcc, 'tcx>( // zero. let real_name = format!("_rust_extern_with_linkage_{:016x}_{sym}", cx.tcx.stable_crate_id(LOCAL_CRATE)); - let global2 = cx.define_global(&real_name, gcc_type, is_tls, attrs.link_section); - // FIXME(antoyo): set linkage. + let global2 = cx.define_global( + &real_name, + gcc_type, + GlobalKind::Internal, + is_tls, + attrs.link_section, + ); let value = cx.const_ptrcast(global1.get_address(None), gcc_type); global2.global_set_initializer_rvalue(value); global2 diff --git a/src/context.rs b/src/context.rs index 38e0e5f329f76..7a1931b4967ce 100644 --- a/src/context.rs +++ b/src/context.rs @@ -1,6 +1,8 @@ use std::cell::{Cell, RefCell}; use std::collections::HashMap; +#[cfg(feature = "master")] +use gccjit::Region; use gccjit::{Block, CType, Context, Function, FunctionType, LValue, Location, RValue, Type}; use rustc_abi::{Align, HasDataLayout, PointeeInfo, Size, TargetDataLayout, VariantIdx}; use rustc_codegen_ssa::base::wants_msvc_seh; @@ -25,6 +27,13 @@ use rustc_target::spec::{HasTargetSpec, HasX86AbiOpt, Target, TlsModel, X86Abi}; use crate::abi::conv_to_fn_attribute; use crate::callee::get_fn; use crate::common::SignType; +use crate::type_::StructTypeKey; + +#[cfg(feature = "master")] +pub struct PendingCleanup<'gcc> { + pub region: Region<'gcc>, + pub landing_pad: Block<'gcc>, +} #[cfg_attr(not(feature = "master"), expect(dead_code))] pub struct CodegenCx<'gcc, 'tcx> { @@ -84,7 +93,14 @@ pub struct CodegenCx<'gcc, 'tcx> { pub types: RefCell, Option), Type<'gcc>>>, pub tcx: TyCtxt<'tcx>, - pub struct_types: RefCell>, Type<'gcc>>>, + /// Cache of the anonymous struct types. + pub struct_types: RefCell, Type<'gcc>>>, + + /// Cache of the array types used for runs of constant bytes, keyed by element type and count. + /// + /// libgccjit mints a fresh type on every `new_array_type`, and struct types are keyed on their + /// field types, so without this two equal byte runs would yield two distinct anonymous structs. + pub byte_array_types: RefCell, u64), Type<'gcc>>>, /// Cache instances of monomorphic and polymorphic items pub instances: RefCell, LValue<'gcc>>>, @@ -125,8 +141,14 @@ pub struct CodegenCx<'gcc, 'tcx> { pub pointee_infos: RefCell, Size), Option>>, + /// Blocks that are cleanup landing pads, so `invoke` can tell an unwind + /// edge into a cleanup from a catch/terminate. #[cfg(feature = "master")] - pub cleanup_blocks: RefCell>>, + pub landing_pads: RefCell>>, + /// Cleanup regions to be filled in once the function is fully codegened + /// (done in `populate_cleanup_regions`). + #[cfg(feature = "master")] + pub pending_cleanups: RefCell>>, /// The alignment of a u128/i128 type. // We cache this, since it is needed for alignment checks during loads. pub int128_align: Align, @@ -225,12 +247,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { let isize_type = usize_type; let bool_type = context.new_type::(); - let mut functions = FxHashMap::default(); - let builtins = ["abort"]; - - for builtin in builtins.iter() { - functions.insert(builtin.to_string(), context.get_builtin_function(builtin)); - } + let functions = FxHashMap::default(); let mut cx = Self { int128_align: tcx @@ -297,6 +314,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { types: Default::default(), tcx, struct_types: Default::default(), + byte_array_types: Default::default(), local_gen_sym_counter: Cell::new(0), global_gen_sym_counter: Cell::new(0), eh_personality: Cell::new(None), @@ -304,13 +322,43 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { rust_try_fn: Cell::new(None), pointee_infos: Default::default(), #[cfg(feature = "master")] - cleanup_blocks: Default::default(), + landing_pads: Default::default(), + #[cfg(feature = "master")] + pending_cleanups: Default::default(), }; // FIXME(antoyo): instead of doing this, add SsizeT to libgccjit. cx.isize_type = usize_type.to_signed(&cx); cx } + /// Fill in the member blocks of every pending cleanup region. + /// + /// Clone all blocks reachable from a cleanup block into the cleanup region. + #[cfg(feature = "master")] + pub fn populate_cleanup_regions(&self) { + let pending = std::mem::take(&mut *self.pending_cleanups.borrow_mut()); + + for cleanup in pending { + // The landing pad is the region's entry, so it must come first. + let mut blocks = vec![]; + let mut visited = FxHashSet::default(); + let mut stack = vec![cleanup.landing_pad]; + while let Some(block) = stack.pop() { + if !visited.insert(block) { + continue; + } + blocks.push(block); + stack.extend(block.get_successors()); + } + + for clone in gccjit::clone_blocks(&blocks) { + cleanup.region.add_block(clone); + } + } + + self.landing_pads.borrow_mut().clear(); + } + pub fn rvalue_as_function(&self, value: RValue<'gcc>) -> Function<'gcc> { let function: Function<'gcc> = unsafe { std::mem::transmute(value) }; debug_assert!( diff --git a/src/declare.rs b/src/declare.rs index 4174eebcf7b02..a9503574a03ed 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -14,6 +14,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, ty: Type<'gcc>, + global_kind: GlobalKind, is_tls: bool, link_section: Option, ) -> LValue<'gcc> { @@ -28,7 +29,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } global } else { - self.declare_global(name, ty, GlobalKind::Exported, is_tls, link_section) + self.declare_global(name, ty, global_kind, is_tls, link_section) } } @@ -135,10 +136,11 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { &self, name: &str, ty: Type<'gcc>, + global_kind: GlobalKind, is_tls: bool, link_section: Option, ) -> LValue<'gcc> { - self.get_or_insert_global(name, ty, is_tls, link_section) + self.get_or_insert_global(name, ty, global_kind, is_tls, link_section) } pub fn get_declared_value(&self, name: &str) -> Option> { diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 24f552fed32c6..4b0fef32cac03 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -1,10 +1,15 @@ +use std::borrow::Cow; +use std::collections::HashSet; +use std::env; + +use gccjit::Context; #[cfg(feature = "master")] use gccjit::Context; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; -use rustc_session::EarlySession; use rustc_session::config::NATIVE_CPU; -use rustc_target::spec::{Arch, Target}; +use rustc_session::{EarlySession, Session}; +use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector, Target}; fn gcc_features_by_flags(sess: &EarlySession, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -110,29 +115,180 @@ pub fn to_gcc_features<'a>(target: &Target, s: &'a str) -> SmallVec<[&'a str; 2] fn arch_to_gcc(name: &str) -> &str { match name { "M68000" => "68000", + "M68010" => "68010", "M68020" => "68020", + "M68030" => "68030", + "M68040" => "68040", + "M68060" => "68060", _ => name, } } -fn handle_native(name: &str) -> &str { +fn handle_native(name: &str) -> Cow<'_, str> { if name != NATIVE_CPU { - return arch_to_gcc(name); + return arch_to_gcc(name).into(); } #[cfg(feature = "master")] { // Get the native arch. let context = Context::default(); - context.get_target_info().arch().unwrap().to_str().unwrap() + Cow::Owned(context.get_target_info().arch().to_str().unwrap().to_string()) } #[cfg(not(feature = "master"))] unimplemented!(); } -pub fn target_cpu(sess: &EarlySession) -> &str { +pub fn target_cpu(sess: &EarlySession) -> Cow<'_, str> { match sess.opts.cg.target_cpu { Some(ref name) => handle_native(name), None => handle_native(sess.target.cpu.as_ref()), } } + +pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { + let context = Context::default(); + if matches!(sess.target.arch, Arch::X86 | Arch::X86_64) { + context.add_command_line_option("-masm=intel"); + } + #[cfg(feature = "master")] + { + context.set_special_chars_allowed_in_func_names("$.*"); + let version = Version::get(); + let version = format!("{}.{}.{}", version.major, version.minor, version.patch); + context.set_output_ident(&format!( + "rustc version {} with libgccjit {}", + rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), + version, + )); + } + if !sess.must_emit_unwind_tables() { + context.add_command_line_option("-fno-asynchronous-unwind-tables"); + } + + if sess.panic_strategy().unwinds() { + context.add_command_line_option("-fexceptions"); + context.add_driver_option("-fexceptions"); + } + + let disabled_features: HashSet<_> = sess + .opts + .cg + .target_feature + .split(',') + .filter(|feature| feature.starts_with('-')) + .map(|string| &string[1..]) + .collect(); + + if !disabled_features.contains("avx") && sess.target.arch == Arch::X86_64 { + // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for + // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. + // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. + context.add_command_line_option("-mavx"); + } + + for arg in &sess.opts.cg.llvm_args { + context.add_command_line_option(arg); + } + // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. + context.add_command_line_option("-fno-var-tracking-assignments"); + // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). + context.add_command_line_option("-fno-semantic-interposition"); + // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). + context.add_command_line_option("-fno-strict-aliasing"); + // NOTE: Rust relies on LLVM doing wrapping on overflow. + context.add_command_line_option("-fwrapv"); + // NOTE: This is needed to hide a warning caused by the alignment fix on byval arguments. + context.add_command_line_option("-Wno-psabi"); + + if let Some(model) = sess.code_model() { + use rustc_target::spec::CodeModel; + + context.add_command_line_option(match model { + CodeModel::Tiny => "-mcmodel=tiny", + CodeModel::Small => "-mcmodel=small", + CodeModel::Kernel => "-mcmodel=kernel", + CodeModel::Medium => "-mcmodel=medium", + CodeModel::Large => "-mcmodel=large", + }); + } + + match sess.stack_protector() { + StackProtector::All => context.add_command_line_option("-fstack-protector-all"), + StackProtector::Strong => context.add_command_line_option("-fstack-protector-strong"), + StackProtector::Basic => context.add_command_line_option("-fstack-protector"), + StackProtector::None => (), + } + + match sess.target.stack_probes { + StackProbeType::None => (), + StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { + context.add_command_line_option("-fstack-clash-protection") + } + // FIXME(antoyo): We should define the stack probe symbol to be __rust_probestack, but it seems GCC cannot do that. + StackProbeType::Call => (), + }; + + add_pic_option(&context, sess.relocation_model()); + + let target_cpu = target_cpu(sess); + if target_cpu != "generic" { + context.add_command_line_option(format!("-march={}", target_cpu)); + } + + if sess.opts.unstable_opts.function_sections.unwrap_or(sess.target.function_sections) { + context.add_command_line_option("-ffunction-sections"); + context.add_command_line_option("-fdata-sections"); + } + + if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-vregs"); + } + if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-rtl-all"); + } + if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-tree-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { + context.add_command_line_option("-fdump-ipa-all-eh"); + } + if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { + context.set_dump_code_on_compile(true); + } + if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { + context.set_dump_initial_gimple(true); + } + if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { + context.set_dump_everything(true); + } + if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { + context.set_keep_intermediates(true); + } + if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { + context.add_driver_option("-v"); + } + + context +} + +pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { + match relocation_model { + rustc_target::spec::RelocModel::Static => { + context.add_command_line_option("-fno-pie"); + context.add_driver_option("-fno-pie"); + } + rustc_target::spec::RelocModel::Pic => { + context.add_command_line_option("-fPIC"); + // NOTE: we use both add_command_line_option and add_driver_option because the usage in + // base (compile_codegen_unit) requires add_command_line_option while the usage + // in the back::write module (codegen) requires add_driver_option. + context.add_driver_option("-fPIC"); + } + rustc_target::spec::RelocModel::Pie => { + context.add_command_line_option("-fPIE"); + context.add_driver_option("-fPIE"); + } + model => eprintln!("Unsupported relocation model: {:?}", model), + } +} diff --git a/src/int.rs b/src/int.rs index dfae4eceebe44..021f05c666d46 100644 --- a/src/int.rs +++ b/src/int.rs @@ -21,12 +21,12 @@ use crate::context::CodegenCx; impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { pub fn gcc_urem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit unsigned %: __umodti3 - self.multiplicative_operation(BinaryOp::Modulo, "mod", false, a, b) + self.division_operation(BinaryOp::Modulo, "mod", false, a, b) } pub fn gcc_srem(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit signed %: __modti3 - self.multiplicative_operation(BinaryOp::Modulo, "mod", true, a, b) + self.division_operation(BinaryOp::Modulo, "mod", true, a, b) } pub fn gcc_not(&self, a: RValue<'gcc>) -> RValue<'gcc> { @@ -178,6 +178,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } else { debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let signed = a_type.is_compatible_with(self.i128_type); let func_name = match (operation, signed) { (BinaryOp::Plus, true) => "__rust_i128_add", @@ -187,7 +190,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { _ => unreachable!("unexpected additive operation {:?}", operation), }; let param_a = self.context.new_parameter(self.location, a_type, "a"); - let param_b = self.context.new_parameter(self.location, b_type, "b"); + let param_b = self.context.new_parameter(self.location, a_type, "b"); let func = self.context.new_function( self.location, FunctionType::Extern, @@ -212,6 +215,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.additive_operation(BinaryOp::Minus, a, b) } + fn division_operation( + &self, + operation: BinaryOp, + operation_name: &str, + signed: bool, + mut a: RValue<'gcc>, + mut b: RValue<'gcc>, + ) -> RValue<'gcc> { + let a_type = a.get_type(); + if self.is_native_int_type(a_type) && self.is_native_int_type(b.get_type()) { + let typ = if signed { a_type.to_signed(self.cx) } else { a_type.to_unsigned(self.cx) }; + if !typ.is_compatible_with(a_type) { + a = self.context.new_cast(self.location, a, typ); + } + if !typ.is_compatible_with(b.get_type()) { + b = self.context.new_cast(self.location, b, typ); + } + } + self.multiplicative_operation(operation, operation_name, signed, a, b) + } + fn multiplicative_operation( &self, operation: BinaryOp, @@ -238,10 +262,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } else { debug_assert!(a_type.dyncast_array().is_some()); debug_assert!(b_type.dyncast_array().is_some()); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let sign = if signed { "" } else { "u" }; let func_name = format!("__{}{}ti3", sign, operation_name); let param_a = self.context.new_parameter(self.location, a_type, "a"); - let param_b = self.context.new_parameter(self.location, b_type, "b"); + let param_b = self.context.new_parameter(self.location, a_type, "b"); let func = self.context.new_function( self.location, FunctionType::Extern, @@ -255,15 +282,13 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } pub fn gcc_sdiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { - // FIXME(antoyo): check if the types are signed? // 128-bit, signed: __divti3 - // FIXME(antoyo): convert the arguments to signed? - self.multiplicative_operation(BinaryOp::Divide, "div", true, a, b) + self.division_operation(BinaryOp::Divide, "div", true, a, b) } pub fn gcc_udiv(&self, a: RValue<'gcc>, b: RValue<'gcc>) -> RValue<'gcc> { // 128-bit, unsigned: __udivti3 - self.multiplicative_operation(BinaryOp::Divide, "div", false, a, b) + self.division_operation(BinaryOp::Divide, "div", false, a, b) } pub fn gcc_checked_binop( @@ -462,9 +487,18 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + let signed_type = native_int_type.to_signed(self.cx); + lhs_high = self.context.new_cast(self.location, lhs_high, signed_type); + rhs_high = self.context.new_cast(self.location, rhs_high, signed_type); + } + IntPredicate::IntEQ | IntPredicate::IntNE => { + lhs_high = self.context.new_cast(self.location, lhs_high, unsigned_type); + rhs_high = self.context.new_cast(self.location, rhs_high, unsigned_type); + } } let condition = self.context.new_comparison( @@ -623,6 +657,9 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { } a ^ b } else { + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } self.concat_low_high_rvalues( a_type, self.low(a) ^ self.low(b), @@ -832,6 +869,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { !a_native && !b_native, "both types should either be native or non-native for or operation" ); + if a_type != b_type { + b = self.gcc_int_cast(b, a_type); + } let native_int_type = a_type.dyncast_array().expect("get element type"); self.concat_low_high_rvalues( a_type, diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index 41efe3e8209bf..f3134edb72cb9 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -5,6 +5,7 @@ use rustc_codegen_ssa::traits::BuilderMethods; use crate::builder::Builder; use crate::context::{CodegenCx, new_array_type}; +use crate::type_::{StructAttribute, apply_struct_attributes}; fn encode_key_128_type<'a, 'gcc, 'tcx>( builder: &Builder<'a, 'gcc, 'tcx>, @@ -22,8 +23,7 @@ fn encode_key_128_type<'a, 'gcc, 'tcx>( "EncodeKey128Output", &[field1, field2, field3, field4, field5, field6, field7], ); - #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + apply_struct_attributes(encode_type.as_type(), &[StructAttribute::Packed]); (encode_type.as_type(), field1, field2) } @@ -44,8 +44,7 @@ fn encode_key_256_type<'a, 'gcc, 'tcx>( "EncodeKey256Output", &[field1, field2, field3, field4, field5, field6, field7, field8], ); - #[cfg(feature = "master")] - encode_type.as_type().set_packed(); + apply_struct_attributes(encode_type.as_type(), &[StructAttribute::Packed]); (encode_type.as_type(), field1, field2) } @@ -57,8 +56,7 @@ fn aes_output_type<'a, 'gcc, 'tcx>( let field2 = builder.context.new_field(None, m128i, "field2"); let aes_output_type = builder.context.new_struct_type(None, "AesOutput", &[field1, field2]); let typ = aes_output_type.as_type(); - #[cfg(feature = "master")] - typ.set_packed(); + apply_struct_attributes(typ, &[StructAttribute::Packed]); (typ, field1, field2) } @@ -80,8 +78,7 @@ fn wide_aes_output_type<'a, 'gcc, 'tcx>( "WideAesOutput", &[field1, field2, field3, field4, field5, field6, field7, field8, field9], ); - #[cfg(feature = "master")] - aes_output_type.as_type().set_packed(); + apply_struct_attributes(aes_output_type.as_type(), &[StructAttribute::Packed]); (aes_output_type.as_type(), field1, field2) } diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 41fa7b3f9f162..0a24519a8091e 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -24,6 +24,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_middle::ty::layout::FnAbiOf; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Instance, Ty}; +use rustc_session::config::OptLevel; use rustc_span::{Span, Symbol, bug, span_bug, sym}; use rustc_target::callconv::{ArgAbi, PassMode}; @@ -88,7 +89,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::round_ties_even_f64 => "rint", sym::roundf32 => "roundf", sym::roundf64 => "round", - sym::abort => "abort", _ => return None, }; Some(cx.context.get_builtin_function(gcc_name)) @@ -664,16 +664,26 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc } fn abort(&mut self) { - let func = self.context.get_builtin_function("abort"); - let func: RValue<'gcc> = unsafe { std::mem::transmute(func) }; - self.call(self.type_void(), None, None, func, ReturnSlot::Direct, &[], None, None); + let func = self.context.get_builtin_function("__builtin_trap"); + self.block.add_eval(self.location, self.context.new_call(self.location, func, &[])); } fn assume(&mut self, value: Self::Value) { - // FIXME(antoyo): switch to assume when it exists. - // Or use something like this: - // #define __assume(cond) do { if (!(cond)) __builtin_unreachable(); } while (0) - self.expect(value, true); + // libgccjit currently has no direct equivalent of LLVM's `llvm.assume`, + // so use the idiom `if (!cond) __builtin_unreachable()`. + // FIXME: this should use IFN_ASSUME when we have internal functions in + // libgccjit. + if self.sess().opts.optimize == OptLevel::No { + return; + } + let then_block = self.append_sibling_block("assume_holds"); + let unreachable_block = self.append_sibling_block("assume_violated"); + self.block.end_with_conditional(self.location, value, then_block, unreachable_block); + + self.switch_to_block(unreachable_block); + self.unreachable(); + + self.switch_to_block(then_block); } fn expect(&mut self, cond: Self::Value, _expected: bool) -> Self::Value { diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index 1416f4eec9c4a..bb32a85f193ea 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -11,13 +11,13 @@ use rustc_codegen_ssa::diagnostics::ExpectedPointerMutability; use rustc_codegen_ssa::diagnostics::InvalidMonomorphization; use rustc_codegen_ssa::mir::operand::OperandRef; use rustc_codegen_ssa::mir::place::PlaceRef; -use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods}; +use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, LayoutTypeCodegenMethods}; #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; -use rustc_middle::ty::layout::HasTyCtxt; +use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; -use rustc_span::{ErrorGuaranteed, Span, Symbol, sym}; +use rustc_span::{ErrorGuaranteed, Span, Symbol, span_bug, sym}; use crate::builder::Builder; #[cfg(not(feature = "master"))] @@ -655,6 +655,39 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); } + if name == sym::simd_arith_offset { + // This also checks that the first operand is a ptr type. + let pointee = in_elem.builtin_deref(true).unwrap_or_else(|| { + span_bug!(span, "must be called with a vector of pointer types as first argument") + }); + let layout = bx.layout_of(pointee); + // The second argument must be a ptr-sized integer. + // (We don't care about the signedness, this is wrapping anyway.) + let (_, offsets_elem) = args[1].layout.ty.simd_size_and_type(bx.tcx()); + if !matches!(offsets_elem.kind(), ty::Int(ty::IntTy::Isize) | ty::Uint(ty::UintTy::Usize)) { + span_bug!( + span, + "must be called with a vector of pointer-sized integers as second argument" + ); + } + + let pointee_type = bx.backend_type(layout); + let pointers = args[0].immediate(); + let offsets = args[1].immediate(); + let elem_type = llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let index = bx.context.new_rvalue_from_long(bx.usize_type, i as _); + let pointer = bx.extract_element(pointers, index); + let offset = bx.extract_element(offsets, index); + let pointer = bx.gep(pointee_type, pointer, &[offset]); + // GCC has no pointer vectors, so the lanes are `usize`. + bx.ptrtoint(pointer, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } + #[cfg(feature = "master")] if name == sym::simd_cast || name == sym::simd_as { require_simd!(ret_ty, InvalidMonomorphization::SimdReturn { span, name, ty: ret_ty }); @@ -675,20 +708,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( return Ok(args[0].immediate()); } + #[derive(Copy, Clone)] + enum Sign { + Unsigned, + Signed, + } + use Sign::*; + enum Style { Float, - Int, + Int(Sign), Unsupported, } let in_style = match *in_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Int(_) => Style::Int(Signed), + ty::Uint(_) => Style::Int(Unsigned), ty::Float(_) => Style::Float, _ => Style::Unsupported, }; - let out_style = match *out_elem.kind() { - ty::Int(_) | ty::Uint(_) => Style::Int, + ty::Int(_) => Style::Int(Signed), + ty::Uint(_) => Style::Int(Unsigned), ty::Float(_) => Style::Float, _ => Style::Unsupported, }; @@ -707,6 +748,19 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( } ); } + (Style::Float, Style::Int(sign)) if name == sym::simd_as => { + let vector = args[0].immediate(); + let elem_type = + llret_ty.dyncast_vector().expect("vector return type").get_element_type(); + let values: Vec<_> = (0..in_len) + .map(|i| { + let index = bx.context.new_rvalue_from_long(bx.usize_type, i as _); + let value = bx.extract_element(vector, index); + bx.cast_float_to_int(matches!(sign, Sign::Signed), value, elem_type) + }) + .collect(); + return Ok(bx.context.new_rvalue_from_vector(bx.location, llret_ty, &values)); + } _ => return Ok(bx.context.convert_vector(None, args[0].immediate(), llret_ty)), } } @@ -1310,32 +1364,28 @@ pub fn generic_simd_intrinsic<'a, 'gcc, 'tcx>( (true, false) => { // FIXME(antoyo): dyncast_vector should not require a call to unqualified. let arg_type = lhs.get_type().unqualified(); - // FIXME(antoyo): this uses the same algorithm from saturating add, but add the - // negative of the right operand. Find a proper subtraction algorithm. - let rhs = bx.context.new_unary_op(None, UnaryOp::Minus, arg_type, rhs); - // FIXME(antoyo): convert lhs and rhs to unsigned. - let sum = lhs + rhs; + let difference = lhs - rhs; let vector_type = arg_type.dyncast_vector().expect("vector type"); let unit = vector_type.get_num_units(); let a = bx.context.new_rvalue_from_int(elem_ty, ((elem_width as i32) << 3) - 1); let width = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![a; unit]); + // The subtraction overflows when the operands have different signs and the result + // has a different sign than the left operand. let xor1 = lhs ^ rhs; - let xor2 = lhs ^ sum; - let and = - bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, xor1) & xor2; - let mask = and >> width; + let xor2 = lhs ^ difference; + let mask = (xor1 & xor2) >> width; let one = bx.context.new_rvalue_one(elem_ty); let ones = bx.context.new_rvalue_from_vector(None, lhs.get_type(), &vec![one; unit]); let shift1 = ones << width; - let shift2 = sum >> width; + let shift2 = difference >> width; let mask_min = shift1 ^ shift2; - let and1 = - bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) & sum; + let and1 = bx.context.new_unary_op(None, UnaryOp::BitwiseNegate, arg_type, mask) + & difference; let and2 = mask & mask_min; and1 + and2 diff --git a/src/lib.rs b/src/lib.rs index d7a3ef3b4a6c5..0784823c27b9e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -94,7 +94,7 @@ use rustc_middle::ty::TyCtxt; use rustc_session::config::{OptLevel, OutputFilenames}; use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; use rustc_span::{Symbol, sym}; -use rustc_target::spec::{Arch, RelocModel}; +use rustc_target::spec::{RelocModel, TargetTuple}; use tempfile::TempDir; use crate::back::lto::ModuleBuffer; @@ -176,15 +176,21 @@ impl CodegenBackend for GccCodegenBackend { } fn init(&mut self, sess: &EarlySession) -> CodegenBackendInit { - fn file_path(sysroot_path: &Path, sess: &EarlySession) -> PathBuf { - let rustlib_path = - rustc_target::relative_target_rustlib_path(sysroot_path, &sess.host.llvm_target); - sysroot_path - .join(rustlib_path) - .join("codegen-backends") - .join("lib") - .join(sess.target.llvm_target.as_ref()) - .join("libgccjit.so") + fn file_paths(sysroot_path: &Path, sess: &EarlySession) -> Vec { + let rustlib_path = rustc_target::relative_target_rustlib_path( + sysroot_path, + rustc_session::config::host_tuple(), + ); + let lib_path = sysroot_path.join(rustlib_path).join("codegen-backends").join("lib"); + let rust_target_path = + lib_path.join(sess.opts.target_triple.tuple()).join("libgccjit.so"); + let mut paths = vec![rust_target_path]; + if matches!(sess.opts.target_triple, TargetTuple::TargetJson { .. }) { + let llvm_target_path = + lib_path.join(sess.target.llvm_target.as_ref()).join("libgccjit.so"); + paths.push(llvm_target_path); + } + paths } let global_backend_features = gcc_util::global_gcc_features(sess); @@ -192,21 +198,24 @@ impl CodegenBackend for GccCodegenBackend { // We use all_paths() instead of only path() in case the path specified by --sysroot is // invalid. // This is the case for instance in Rust for Linux where they specify --sysroot=/dev/null. - for path in sess.opts.sysroot.all_paths() { - let libgccjit_target_lib_file = file_path(path, sess); - if let Ok(true) = fs::exists(&libgccjit_target_lib_file) { - load_libgccjit_if_needed(&libgccjit_target_lib_file); - break; + 'sysroot: for path in sess.opts.sysroot.all_paths() { + for libgccjit_target_lib_file in file_paths(path, sess) { + if let Ok(true) = fs::exists(&libgccjit_target_lib_file) { + load_libgccjit_if_needed(&libgccjit_target_lib_file); + break 'sysroot; + } } } if !gccjit::is_loaded() { let mut paths = vec![]; for path in sess.opts.sysroot.all_paths() { - let libgccjit_target_lib_file = file_path(path, sess); - paths.push(libgccjit_target_lib_file); + for libgccjit_target_lib_file in file_paths(path, sess) { + paths.push(libgccjit_target_lib_file); + } } + paths.dedup(); panic!("Could not load libgccjit.so. Attempted paths: {:#?}", paths); } @@ -259,7 +268,7 @@ impl CodegenBackend for GccCodegenBackend { } fn target_cpu(&self, sess: &Session) -> String { - target_cpu(sess).to_owned() + target_cpu(sess).into_owned() } fn codegen_crate(&self, tcx: TyCtxt<'_>) -> Box { @@ -283,13 +292,6 @@ impl CodegenBackend for GccCodegenBackend { fn target_config(&self, sess: &EarlySession) -> TargetConfig { target_config(sess, &self.config().target_info) } -} - -fn new_context<'gcc, 'tcx>(tcx: TyCtxt<'tcx>) -> Context<'gcc> { - let context = Context::default(); - if matches!(tcx.sess.target.arch, Arch::X86 | Arch::X86_64) { - context.add_command_line_option("-masm=intel"); - } #[cfg(feature = "master")] { context.set_special_chars_allowed_in_func_names("$.*"); diff --git a/src/mono_item.rs b/src/mono_item.rs index fc92cc3d5c7a9..014a7ff90536d 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,15 +1,16 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, VarAttribute}; +use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; +use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mono::Visibility; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv, LayoutOf}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; use rustc_span::bug; +use crate::consts::const_alloc_type; use crate::context::CodegenCx; use crate::type_of::LayoutGccExt; use crate::{attributes, base}; @@ -19,23 +20,58 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { fn predefine_static( &mut self, def_id: DefId, - _linkage: Linkage, + linkage: Linkage, visibility: Visibility, symbol_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); - let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; - // Nested statics do not have a type, so pick a dummy type and let `codegen_static` figure out - // the gcc type from the actual evaluated initializer. - let ty = - if nested { self.tcx.types.unit } else { instance.ty(self.tcx, self.typing_env()) }; - let gcc_type = self.layout_of(ty).gcc_type(self); + // Declare the global with the type its initializer will have, so that `codegen_static` + // never has to retype it afterwards. The initializer is lowered as a packed struct of byte + // runs and relocations, which almost never matches the layout type. + let gcc_type = match self.tcx.eval_static_initializer(def_id) { + Ok(alloc) => const_alloc_type(self, alloc), + // The initializer failed to evaluate; `codegen_static` bails out on it too, so this + // type is never used to hold one. + Err(_) => { + let DefKind::Static { nested, .. } = self.tcx.def_kind(def_id) else { bug!() }; + // Nested statics do not have a type, so pick a dummy one. + let ty = if nested { + self.tcx.types.unit + } else { + instance.ty(self.tcx, self.typing_env()) + }; + self.layout_of(ty).gcc_type(self) + } + }; let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); - let global = self.define_global(symbol_name, gcc_type, is_tls, attrs.link_section); + let global_kind = base::global_linkage_to_gcc(linkage); + let global = + self.define_global(global_name, gcc_type, global_kind, is_tls, attrs.link_section); #[cfg(feature = "master")] - global.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + { + // Visibility is meaningless on an internal global: GCC ignores the attribute and + // warns about it. + if !matches!(global_kind, GlobalKind::Internal) { + // If we're compiling the compiler-builtins crate, e.g., the equivalent of + // compiler-rt, then we want to implicitly compile everything with hidden + // visibility as we're going to link this object all over the place but + // don't want the symbols to get exported. + let visibility = if self.tcx.is_compiler_builtins(LOCAL_CRATE) { + gccjit::Visibility::Hidden + } else { + base::visibility_to_gcc(visibility) + }; + global.add_attribute(VarAttribute::Visibility(visibility)); + } + if let Some(attribute) = base::global_linkage_attribute(linkage) { + global.add_attribute(attribute); + } + } + + #[cfg(feature = "master")] + self.add_static_aliases(gcc_type, global_name, attrs, &attrs.foreign_item_symbol_aliases); // FIXME(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); @@ -50,6 +86,104 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { ) { assert!(!instance.args.has_infer()); + let attrs = self.tcx.codegen_instance_attrs(instance.def); + + let decl = + self.predefine_without_aliases(instance, &attrs, linkage, visibility, symbol_name); + + #[cfg(feature = "master")] + self.add_function_aliases(instance, decl, &attrs, &attrs.foreign_item_symbol_aliases); + + self.functions.borrow_mut().insert(symbol_name.to_string(), decl); + self.function_instances.borrow_mut().insert(instance, decl); + } +} + +impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { + #[cfg(feature = "master")] + fn add_static_aliases( + &self, + gcc_type: Type<'gcc>, + aliased: &str, + attrs: &CodegenFnAttrs, + aliases: &[(DefId, Linkage, Visibility)], + ) { + let is_tls = attrs.flags.contains(CodegenFnAttrFlags::THREAD_LOCAL); + + for &(alias, linkage, visibility) in aliases { + let instance = Instance::mono(self.tcx, alias); + let symbol_name = self.tcx.symbol_name(instance); + + let alias = self.declare_global( + symbol_name.name, + gcc_type, + GlobalKind::Imported, + is_tls, + attrs.link_section, + ); + alias.add_attribute(VarAttribute::Visibility(base::visibility_to_gcc(visibility))); + alias.add_attribute(VarAttribute::Alias(aliased)); + if linkage == Linkage::WeakAny { + alias.add_attribute(VarAttribute::Weak); + } + + // Add the alias name to the set of cached items, so there is no duplicate + // instance added to it during the normal `external static` codegen + let prev_entry = self.instances.borrow_mut().insert(instance, alias); + + // If there already was a previous entry, then `add_static_aliases` was called multiple times for the same `alias` + // which would result in incorrect codegen + assert!(prev_entry.is_none(), "An instance was already present for {instance:?}"); + } + } + + #[cfg(feature = "master")] + fn add_function_aliases( + &self, + aliased_instance: Instance<'tcx>, + aliased: Function<'gcc>, + attrs: &CodegenFnAttrs, + aliases: &[(DefId, Linkage, Visibility)], + ) { + for &(alias, linkage, visibility) in aliases { + let symbol_name = self.tcx.symbol_name(Instance::mono(self.tcx, alias)); + + // predefine another copy of the original instance + // with a new symbol name + let alias_fn_decl = self.predefine_without_aliases( + aliased_instance, + attrs, + linkage, + visibility, + symbol_name.name, + ); + + let block = alias_fn_decl.new_block("start"); + let nb_params = alias_fn_decl.get_param_count(); + let mut args = Vec::with_capacity(nb_params); + for idx in 0..nb_params { + args.push(alias_fn_decl.get_param(idx as _).to_rvalue()); + } + + let void_type = self.context.new_type::<()>(); + let call = self.context.new_call(None, aliased, &args); + if alias_fn_decl.get_return_type() == void_type { + block.add_eval(None, call); + block.end_with_void_return(None); + } else { + block.end_with_return(None, call); + } + } + } + + fn predefine_without_aliases( + &self, + instance: Instance<'tcx>, + _attrs: &CodegenFnAttrs, + linkage: Linkage, + visibility: Visibility, + symbol_name: &str, + ) -> Function<'gcc> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); let decl = self.declare_fn(symbol_name, fn_abi); @@ -57,6 +191,11 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { attributes::from_fn_attrs(self, decl, instance); + #[cfg(feature = "master")] + if base::linkage_needs_weak_attribute(linkage) { + fn_decl.add_attribute(FnAttribute::Weak); + } + // If we're compiling the compiler-builtins crate, e.g., the equivalent of // compiler-rt, then we want to implicitly compile everything with hidden // visibility as we're going to link this object all over the place but diff --git a/src/type_.rs b/src/type_.rs index 27b0d2079e63e..45828ce3e92b8 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -1,5 +1,6 @@ #[cfg(feature = "master")] use std::convert::TryInto; +use std::mem::discriminant; #[cfg(feature = "master")] use gccjit::CType; @@ -102,9 +103,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bool_type } - pub fn type_struct(&self, fields: &[Type<'gcc>], packed: bool) -> Type<'gcc> { - let types = fields.to_vec(); - if let Some(typ) = self.struct_types.borrow().get(fields) { + pub fn type_struct(&self, fields: &[Type<'gcc>], attributes: &[StructAttribute]) -> Type<'gcc> { + let key = + StructTypeKey { fields: fields.to_vec(), attributes: canonical_attributes(attributes) }; + if let Some(typ) = self.struct_types.borrow().get(&key) { return *typ; } let fields: Vec<_> = fields @@ -115,15 +117,91 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { }) .collect(); let typ = self.context.new_struct_type(None, "struct", &fields).as_type(); - if packed { - #[cfg(feature = "master")] - typ.set_packed(); - } - self.struct_types.borrow_mut().insert(types, typ); + apply_struct_attributes(typ, &key.attributes); + self.struct_types.borrow_mut().insert(key, typ); typ } } +/// An attribute that can be set on a GCC struct type. +/// +/// This mirrors the subset of `gccjit::TypeAttribute` that cg_gcc needs, rather than using it +/// directly, because it must exist without the `master` feature and because it is what +/// `StructTypeKey` is keyed on. Adding a variant here is therefore all it takes to make a new +/// attribute part of the cache key: there is no second place to remember to update. +#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)] +pub enum StructAttribute { + /// Alignment, in bytes. + Aligned(u32), + /// Lay the fields out without inserting padding between them. + Packed, +} + +/// Identifies an anonymous struct type in `CodegenCx::struct_types`. +/// +/// Two Rust types with the same field list can still need distinct GCC types — `struct { a: u64, +/// b: u64 }` with and without `repr(align(16))` produces the same fields — so every attribute has +/// to be part of the key. Holding them as one [`StructAttribute`] list rather than as separate +/// fields is what keeps that true when a new attribute is added. +#[derive(Clone, Eq, Hash, PartialEq)] +pub struct StructTypeKey<'gcc> { + pub fields: Vec>, + pub attributes: Vec, +} + +/// The attributes a GCC struct needs in order to match the Rust layout it is built from. +pub fn struct_attributes(packed: bool, align: Option) -> Vec { + let mut attributes = Vec::new(); + if packed { + attributes.push(StructAttribute::Packed); + } + if let Some(align) = align + && align.bytes() > 1 + && align.bytes() <= MAX_STRUCT_ALIGNMENT + { + attributes.push(StructAttribute::Aligned(align.bytes() as u32)); + } + attributes +} + +/// The largest alignment GCC accepts on a type, in bytes. +const MAX_STRUCT_ALIGNMENT: u64 = 1 << 28; + +/// Put an attribute list into a canonical form so that it can be used as a cache key. +/// +/// Without this, `[Packed, Aligned(8)]` and `[Aligned(8), Packed]` would hash differently and mint +/// two GCC types for what is one Rust type. +fn canonical_attributes(attributes: &[StructAttribute]) -> Vec { + let mut attributes = attributes.to_vec(); + attributes.sort_unstable(); + attributes.dedup(); + debug_assert!( + attributes.windows(2).all(|pair| discriminant(&pair[0]) != discriminant(&pair[1])), + "contradictory struct attributes: {attributes:?}" + ); + attributes +} + +/// Set `attributes` on the struct type `typ`. +/// +/// This is the only place allowed to call `Type::add_attribute`; `clippy.toml` forbids it +/// everywhere else. An attribute set on a type that `CodegenCx::struct_types` handed out would +/// change every other use of that type, so attributes have to be decided when the type is created +/// and be part of its cache key. Going through [`StructAttribute`] is what enforces that. +#[cfg(feature = "master")] +#[allow(clippy::disallowed_methods)] +pub fn apply_struct_attributes(typ: Type<'_>, attributes: &[StructAttribute]) { + for attribute in attributes { + typ.add_attribute(match *attribute { + StructAttribute::Aligned(align) => TypeAttribute::Aligned(align), + StructAttribute::Packed => TypeAttribute::Packed, + }); + } +} + +#[cfg(not(feature = "master"))] +pub fn apply_struct_attributes(_typ: Type<'_>, _attributes: &[StructAttribute]) {} + impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { fn type_i8(&self) -> Type<'gcc> { self.i8_type @@ -325,17 +403,19 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.type_array(self.type_from_integer(unit), size / unit_size) } - pub fn set_struct_body(&self, typ: Struct<'gcc>, fields: &[Type<'gcc>], packed: bool) { + pub fn set_struct_body( + &self, + typ: Struct<'gcc>, + fields: &[Type<'gcc>], + attributes: &[StructAttribute], + ) { let fields: Vec<_> = fields .iter() .enumerate() .map(|(index, field)| self.context.new_field(None, *field, format!("field_{}", index))) .collect(); typ.set_fields(None, &fields); - if packed { - #[cfg(feature = "master")] - typ.as_type().set_packed(); - } + apply_struct_attributes(typ.as_type(), &canonical_attributes(attributes)); } pub fn type_named_struct(&self, name: &str) -> Struct<'gcc> { diff --git a/src/type_of.rs b/src/type_of.rs index 31654d0e6be81..833ba9efe4efb 100644 --- a/src/type_of.rs +++ b/src/type_of.rs @@ -17,7 +17,7 @@ use rustc_target::callconv::{CastTarget, FnAbi}; use crate::abi::{FnAbiGcc, FnAbiGccExt, GccType}; use crate::context::CodegenCx; -use crate::type_::struct_fields; +use crate::type_::{struct_attributes, struct_fields}; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { fn type_from_unsigned_integer(&self, i: Integer) -> Type<'gcc> { @@ -81,7 +81,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( layout.scalar_pair_element_gcc_type(cx, 0), layout.scalar_pair_element_gcc_type(cx, 1), ], - false, + &struct_attributes(false, Some(layout.align.abi)), ); } BackendRepr::Memory { .. } => {} @@ -129,11 +129,12 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Primitive | FieldsShape::Union(_) => { let fill = cx.type_padding_filler(layout.size, layout.align.abi); let packed = false; + let attributes = struct_attributes(packed, Some(layout.align.abi)); match name { - None => cx.type_struct(&[fill], packed), + None => cx.type_struct(&[fill], &attributes), Some(ref name) => { let gcc_type = cx.type_named_struct(name); - cx.set_struct_body(gcc_type, &[fill], packed); + cx.set_struct_body(gcc_type, &[fill], &attributes); gcc_type.as_type() } } @@ -142,7 +143,7 @@ fn uncached_gcc_type<'gcc, 'tcx>( FieldsShape::Arbitrary { .. } => match name { None => { let (gcc_fields, packed) = struct_fields(cx, layout); - cx.type_struct(&gcc_fields, packed) + cx.type_struct(&gcc_fields, &struct_attributes(packed, Some(layout.align.abi))) } Some(ref name) => { let gcc_type = cx.type_named_struct(name); @@ -240,7 +241,11 @@ impl<'tcx> LayoutGccExt<'tcx> for TyAndLayout<'tcx> { if let Some((deferred_ty, layout)) = defer { let (fields, packed) = struct_fields(cx, layout); - cx.set_struct_body(deferred_ty, &fields, packed); + cx.set_struct_body( + deferred_ty, + &fields, + &struct_attributes(packed, Some(layout.align.abi)), + ); } ty diff --git a/tests/asm/bulk_memory_alignment.rs b/tests/asm/bulk_memory_alignment.rs new file mode 100644 index 0000000000000..6115467447104 --- /dev/null +++ b/tests/asm/bulk_memory_alignment.rs @@ -0,0 +1,45 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +// The alignment reaches GCC's `memcpy`/`memset` expansion only through +// `__builtin_assume_aligned`; a pointer cast to an aligned type is stripped as a useless +// conversion. An over-aligned type therefore has to expand to aligned moves and a packed one +// to unaligned moves. The alignment is 64 so that the contrast holds whatever vector width +// the host picks. + +#[repr(align(64))] +pub struct Aligned([u8; 64]); + +#[repr(C, packed)] +pub struct Packed([u8; 64]); + +// CHECK-LABEL: "copy_aligned": +// CHECK: {{(v)?mov(dqa|aps)}} +#[no_mangle] +pub unsafe fn copy_aligned(destination: *mut Aligned, source: *const Aligned) { + core::ptr::copy_nonoverlapping(source, destination, 1); +} + +// CHECK-LABEL: "copy_packed": +// CHECK: {{(v)?mov(dqu|ups)}} +#[no_mangle] +pub unsafe fn copy_packed(destination: *mut Packed, source: *const Packed) { + core::ptr::copy_nonoverlapping(source, destination, 1); +} + +// CHECK-LABEL: "set_aligned": +// CHECK: {{(v)?mov(dqa|aps)}} +#[no_mangle] +pub unsafe fn set_aligned(destination: *mut Aligned) { + core::ptr::write_bytes(destination, 0, 1); +} + +// CHECK-LABEL: "set_packed": +// CHECK: {{(v)?mov(dqu|ups)}} +#[no_mangle] +pub unsafe fn set_packed(destination: *mut Packed) { + core::ptr::write_bytes(destination, 0, 1); +} diff --git a/tests/asm/volatile_bulk_memory.rs b/tests/asm/volatile_bulk_memory.rs new file mode 100644 index 0000000000000..6233b8ac74c0e --- /dev/null +++ b/tests/asm/volatile_bulk_memory.rs @@ -0,0 +1,37 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -Copt-level=3 + +#![feature(core_intrinsics)] +#![crate_type = "lib"] + +use std::intrinsics::{ + volatile_copy_memory, volatile_copy_nonoverlapping_memory, volatile_set_memory, +}; + +// The buffers below are never read back, so the writes only survive because they are volatile. +// The functions are ordered alphabetically because that is the order they are emitted in. + +// CHECK-LABEL: "volatile_copy": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_copy(source: *const u8) { + let mut buffer = [1u8; 64]; + volatile_copy_memory(buffer.as_mut_ptr(), source, 64); +} + +// CHECK-LABEL: "volatile_copy_nonoverlapping": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_copy_nonoverlapping(source: *const u8) { + let mut buffer = [1u8; 64]; + volatile_copy_nonoverlapping_memory(buffer.as_mut_ptr(), source, 64); +} + +// CHECK-LABEL: "volatile_set": +// CHECK: mov +#[no_mangle] +pub unsafe fn volatile_set() { + let mut buffer = [1u8; 64]; + volatile_set_memory(buffer.as_mut_ptr(), 0, 64); +} diff --git a/tests/c/import_linkage.c b/tests/c/import_linkage.c new file mode 100644 index 0000000000000..f2beb9603d08b --- /dev/null +++ b/tests/c/import_linkage.c @@ -0,0 +1,17 @@ +/* The symbols that `tests/run/import_linkage.rs` imports with an explicit `#[linkage]`. + * + * Such an import is a pointer whose value is the address of the symbol, so what the Rust side + * reads back is `&value_*`, not the pointer stored in it. The distinct values make a mix-up + * visible. */ + +#include + +int32_t external_value = 1; +int32_t available_externally_value = 2; +int32_t linkonce_value = 3; +int32_t linkonce_odr_value = 4; +int32_t weak_value = 5; +int32_t weak_odr_value = 6; +int32_t common_value = 7; +int32_t extern_weak_value = 8; +int32_t internal_value = 9; diff --git a/tests/c/overaligned_byval_abi.c b/tests/c/overaligned_byval_abi.c new file mode 100644 index 0000000000000..826a104f185ea --- /dev/null +++ b/tests/c/overaligned_byval_abi.c @@ -0,0 +1,54 @@ +/* Reference side of `tests/run/overaligned_byval_abi.rs`, compiled by the real GCC. + * + * `Aligned` is an over-aligned aggregate passed by value ("byval"): the ABI places it in a stack + * slot aligned to its own alignment, not packed right after the preceding argument. cg_gcc used + * to build the GCC struct type from the field list alone, which dropped Rust's `repr(align(64))`, + * so it placed the argument at an offset nobody else agreed on. + * + * The two functions here check both directions: `c_take_both` is a GCC-built callee for a cg_gcc + * caller, and `c_call_rust` is a GCC-built caller for a cg_gcc callee. + * + * The checks are on the *values* received rather than on the address of the argument: which + * alignment the ABI gives a stack slot is target-specific, but caller and callee agreeing on it + * is not. A disagreement makes the arguments arrive as garbage. */ + +#include + +struct Big { + int64_t a, b, c; +}; + +struct __attribute__((aligned(64))) Aligned { + int32_t x; +}; + +/* Defined on the Rust side. */ +extern int32_t rust_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth); + +/* Called from Rust: checks what a cg_gcc caller passed. */ +int32_t c_take_both(struct Big first, struct Aligned second, struct Big third, + struct Aligned fourth) +{ + if (first.a != 1 || first.b != 2 || first.c != 3) + return 1; + if (second.x != 42) + return 2; + if (third.a != 4 || third.b != 5 || third.c != 6) + return 3; + if (fourth.x != 43) + return 4; + return 0; +} + +/* Called from Rust: passes the arguments the way the ABI says, for a cg_gcc callee to read. */ +int32_t c_call_rust(void) +{ + struct Big first = {1, 2, 3}; + struct Big third = {4, 5, 6}; + struct Aligned second, fourth; + + second.x = 42; + fourth.x = 43; + return rust_take_both(first, second, third, fourth); +} diff --git a/tests/c/static_linkage.c b/tests/c/static_linkage.c new file mode 100644 index 0000000000000..787e61f9cf105 --- /dev/null +++ b/tests/c/static_linkage.c @@ -0,0 +1,37 @@ +/* Strong definitions of the statics that `tests/run/static_linkage.rs` also defines, but weakly. + * The linker has to keep these and drop the Rust ones; a backend that emits the Rust definitions + * as ordinary global symbols fails the link with a duplicate definition instead. + * + * `internal_static` is the opposite case: the Rust side keeps its own, and the two definitions + * coexist because the Rust one is local. */ + +#include + +int32_t weak_static = 1; +int32_t weak_odr_static = 2; +int32_t linkonce_static = 3; +int32_t linkonce_odr_static = 4; +int32_t common_static = 5; +int32_t internal_static = 200; + +/* `available_externally` promises the real definition lives elsewhere: a backend may read this one + * or emit an equivalent copy of the Rust initializer, so the two have to hold the same value. */ +int32_t available_externally_static = 7; + +/* Called from Rust, so that the reads also happen in a translation unit GCC compiled. */ +int32_t c_read_all(void) +{ + if (weak_static != 1) + return 11; + if (weak_odr_static != 2) + return 12; + if (linkonce_static != 3) + return 13; + if (linkonce_odr_static != 4) + return 14; + if (common_static != 5) + return 15; + if (internal_static != 200) + return 16; + return 0; +} diff --git a/tests/c/weak_function_linkage.c b/tests/c/weak_function_linkage.c new file mode 100644 index 0000000000000..25dcdedbcd950 --- /dev/null +++ b/tests/c/weak_function_linkage.c @@ -0,0 +1,54 @@ +/* Strong definitions of the functions that `tests/run/weak_function_linkage.rs` also defines, but + * weakly. The linker has to keep these and drop the Rust ones. + * + * A backend that emits the Rust definitions as ordinary global symbols does not merely pick the + * wrong one: the link fails outright with a duplicate definition. */ + +#include + +int32_t weak_function(void) +{ + return 1; +} + +int32_t weak_odr_function(void) +{ + return 2; +} + +int32_t linkonce_function(void) +{ + return 3; +} + +int32_t linkonce_odr_function(void) +{ + return 4; +} + +int32_t weak_inline_function(void) +{ + return 8; +} + +/* `available_externally` promises the real definition lives elsewhere: a backend may call this one + * or emit an equivalent copy of the Rust body, so the two have to return the same value. */ +int32_t available_externally_function(void) +{ + return 7; +} + +/* Called from Rust, so that the calls also go through a caller that GCC compiled: a cg_gcc caller + * could inline the weak body it can see instead of calling the symbol. */ +int32_t c_call_all(void) +{ + if (weak_function() != 1) + return 11; + if (weak_odr_function() != 2) + return 12; + if (linkonce_function() != 3) + return 13; + if (linkonce_odr_function() != 4) + return 14; + return 0; +} diff --git a/tests/compile/asm_noreturn_call.rs b/tests/compile/asm_noreturn_call.rs new file mode 100644 index 0000000000000..c9238697d8097 --- /dev/null +++ b/tests/compile/asm_noreturn_call.rs @@ -0,0 +1,15 @@ +// Compiler: + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/827 + +#![crate_type = "lib"] + +#[cfg(target_arch = "x86_64")] +pub type NoReturn = extern "sysv64" fn(&'static u8) -> !; + +#[cfg(target_arch = "x86_64")] +pub fn call_no_return(function: *const NoReturn) -> ! { + unsafe { + std::arch::asm!("call {}", in(reg) function, options(noreturn)); + } +} diff --git a/tests/compile/recursive_types.rs b/tests/compile/recursive_types.rs new file mode 100644 index 0000000000000..3c69074887f3e --- /dev/null +++ b/tests/compile/recursive_types.rs @@ -0,0 +1,22 @@ +// Compiler: + +// `Set` reaches itself by value through `*mut Root`, so a backend that emits `Root`'s +// fields with the still-incomplete `Set` type fails to compile this. + +#![crate_type = "lib"] + +#[repr(C)] +pub struct Set { + pub root: *mut Root, + pub first: usize, + pub second: usize, +} + +#[repr(C)] +pub struct Root { + pub default_set: Set, +} + +pub fn identity(set: Set) -> Set { + set +} diff --git a/tests/failing-ice-tests.txt b/tests/failing-ice-tests.txt index ff1b6f1489468..f9d6f99e7b42b 100644 --- a/tests/failing-ice-tests.txt +++ b/tests/failing-ice-tests.txt @@ -10,7 +10,6 @@ tests/ui/simd/intrinsic/generic-arithmetic-saturating-2.rs tests/ui/simd/intrinsic/generic-arithmetic-2.rs tests/ui/panics/default-backtrace-ice.rs tests/ui/mir/lint/storage-live.rs -tests/ui/layout/valid_range_oob.rs tests/ui/higher-ranked/trait-bounds/future.rs tests/ui/consts/const-eval/const-eval-query-stack.rs tests/ui/simd/masked-load-store.rs @@ -28,13 +27,21 @@ tests/ui/lto/thin-lto-global-allocator.rs tests/ui/lto/msvc-imp-present.rs tests/ui/lto/dylib-works.rs tests/ui/lto/all-crates.rs -tests/ui/issues/issue-47364.rs +tests/ui/codegen/no-segfault-with-multiple-codegen-units.rs tests/ui/functions-closures/parallel-codegen-closures.rs tests/ui/sepcomp/sepcomp-unwind.rs tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs -tests/ui/unwind-no-uwtable.rs +tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/delegation/fn-header.rs tests/ui/simd/intrinsic/generic-arithmetic-pass.rs -tests/ui/simd/masked-load-store.rs -tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs +tests/ui/codegen/unknown-llvm-intrinsic.rs +tests/ui/codegen/incorrect-llvm-intrinsic-signature.rs +tests/ui/codegen/incorrect-arch-intrinsic.rs +tests/ui/codegen/custom-target-invalid-llvm-target.rs +tests/ui/asm/x86_64/naked_asm_escape.rs +tests/ui/lto/debuginfo-lto-alloc.rs +tests/ui/codegen/normalization-overflow/recursion-issue-118590.rs +tests/ui/codegen/normalization-overflow/recursion-issue-122823.rs +tests/ui/codegen/normalization-overflow/recursion-issue-131342.rs +tests/ui/codegen/normalization-overflow/recursion-issue-92004.rs diff --git a/tests/failing-lto-tests.txt b/tests/failing-lto-tests.txt index 4c62c35a512c1..7527005321991 100644 --- a/tests/failing-lto-tests.txt +++ b/tests/failing-lto-tests.txt @@ -1,6 +1,5 @@ tests/ui/lto/debuginfo-lto-alloc.rs -tests/ui/panic-runtime/lto-unwind.rs -tests/ui/uninhabited/uninhabited-transparent-return-abi.rs -tests/ui/coroutine/panic-drops-resume.rs -tests/ui/coroutine/panic-drops.rs -tests/ui/coroutine/panic-safe.rs +tests/ui/extern/issue-64655-allow-unwind-when-calling-panic-directly.rs +tests/ui/extern/issue-64655-extern-rust-must-allow-unwind.rs +tests/ui/lto/thin-lto-inlines2.rs +tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs diff --git a/tests/failing-run-make-tests.txt b/tests/failing-run-make-tests.txt index 528ee1df9f583..d5297e069f72f 100644 --- a/tests/failing-run-make-tests.txt +++ b/tests/failing-run-make-tests.txt @@ -11,4 +11,5 @@ tests/run-make/foreign-exceptions/ tests/run-make/glibc-staticlib-args/ tests/run-make/lto-smoke-c/ tests/run-make/return-non-c-like-enum/ -tests/run-make/short-ice +tests/run-make/short-ice/ +tests/run-make/embed-source-dwarf/ diff --git a/tests/failing-ui-tests.txt b/tests/failing-ui-tests.txt index e8a26a90890c1..7f96bfabedbea 100644 --- a/tests/failing-ui-tests.txt +++ b/tests/failing-ui-tests.txt @@ -1,113 +1,21 @@ tests/ui/asm/may_unwind.rs tests/ui/asm/x86_64/may_unwind.rs -tests/ui/drop/dynamic-drop-async.rs -tests/ui/cfg/cfg-panic-abort.rs tests/ui/intrinsics/panic-uninitialized-zeroed.rs -tests/ui/iterators/iter-sum-overflow-debug.rs -tests/ui/iterators/iter-sum-overflow-overflow-checks.rs -tests/ui/mir/mir_drop_order.rs -tests/ui/mir/mir_let_chains_drop_order.rs -tests/ui/mir/mir_match_guard_let_chains_drop_order.rs -tests/ui/panic-runtime/abort-link-to-unwinding-crates.rs -tests/ui/panic-runtime/abort.rs -tests/ui/panic-runtime/link-to-abort.rs -tests/ui/parser/unclosed-delimiter-in-dep.rs -tests/ui/consts/missing_span_in_backtrace.rs -tests/ui/drop/dynamic-drop.rs tests/ui/simd/issue-17170.rs tests/ui/simd/issue-39720.rs -tests/ui/drop/panic-during-drop-14875.rs -tests/ui/issues/issue-29948.rs tests/ui/process/println-with-broken-pipe.rs -tests/ui/lto/thin-lto-inlines2.rs -tests/ui/panic-runtime/lto-abort.rs -tests/ui/lto/lto-thin-rustc-loads-linker-plugin.rs -tests/ui/async-await/deep-futures-are-freeze.rs -tests/ui/coroutine/resume-after-return.rs -tests/ui/simd/masked-load-store.rs tests/ui/simd/repr_packed.rs -tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs -tests/ui/coroutine/unwind-abort-mix.rs -tests/ui/consts/issue-miri-1910.rs -tests/ui/consts/const_cmp_type_id.rs -tests/ui/consts/issue-94675.rs -tests/ui/traits/const-traits/const-drop-fail.rs -tests/ui/runtime/on-broken-pipe/child-processes.rs -tests/ui/sanitizer/cfi/assoc-ty-lifetime-issue-123053.rs -tests/ui/sanitizer/cfi/async-closures.rs -tests/ui/sanitizer/cfi/closures.rs -tests/ui/sanitizer/cfi/complex-receiver.rs -tests/ui/sanitizer/cfi/coroutine.rs -tests/ui/sanitizer/cfi/drop-in-place.rs -tests/ui/sanitizer/cfi/drop-no-principal.rs -tests/ui/sanitizer/cfi/fn-ptr.rs -tests/ui/sanitizer/cfi/self-ref.rs -tests/ui/sanitizer/cfi/supertraits.rs -tests/ui/sanitizer/cfi/virtual-auto.rs -tests/ui/sanitizer/cfi/sized-associated-ty.rs -tests/ui/sanitizer/cfi/can-reveal-opaques.rs -tests/ui/sanitizer/kcfi-mangling.rs -tests/ui/delegation/fn-header.rs -tests/ui/consts/const-eval/parse_ints.rs -tests/ui/simd/intrinsic/generic-as.rs -tests/ui/runtime/rt-explody-panic-payloads.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/inline1.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/inline2.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/segfault.rs -tests/ui/codegen/equal-pointers-unequal/as-cast/zero.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline1.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/inline2.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/segfault.rs -tests/ui/codegen/equal-pointers-unequal/exposed-provenance/zero.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline1.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/inline2.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/segfault.rs -tests/ui/codegen/equal-pointers-unequal/strict-provenance/zero.rs tests/ui/simd/simd-bitmask-notpow2.rs tests/ui/codegen/StackColoring-not-blowup-stack-issue-40883.rs tests/ui/numbers-arithmetic/u128-as-f32.rs tests/ui/process/nofile-limit.rs -tests/ui/linking/no-gc-encapsulation-symbols.rs -tests/ui/panics/unwind-force-no-unwind-tables.rs tests/ui/attributes/fn-align-dyn.rs tests/ui/linkage-attr/raw-dylib/elf/glibc-x86_64.rs -tests/ui/explicit-tail-calls/recursion-etc.rs -tests/ui/explicit-tail-calls/indexer.rs -tests/ui/explicit-tail-calls/drop-order.rs -tests/ui/c-variadic/valid.rs -tests/ui/c-variadic/inherent-method.rs -tests/ui/c-variadic/trait-method.rs -tests/ui/explicit-tail-calls/become-cast-return.rs -tests/ui/explicit-tail-calls/become-indirect-return.rs -tests/ui/panics/panic-abort-backtrace-without-debuginfo.rs -tests/ui/sanitizer/kcfi-c-variadic.rs -tests/ui/sanitizer/kcfi/fn-trait-objects.rs tests/ui/statics/const_generics.rs -tests/ui/test-attrs/test-panic-while-printing.rs tests/ui/thir-print/offset_of.rs -tests/ui/iterators/rangefrom-overflow-debug.rs -tests/ui/iterators/rangefrom-overflow-overflow-checks.rs -tests/ui/iterators/iter-filter-count-debug-check.rs -tests/ui/eii/linking/codegen_single_crate.rs -tests/ui/eii/linking/codegen_cross_crate.rs -tests/ui/eii/default/local_crate.rs -tests/ui/eii/duplicate/multiple_impls.rs -tests/ui/eii/default/call_default.rs -tests/ui/eii/linking/same-symbol.rs -tests/ui/eii/privacy1.rs -tests/ui/eii/default/call_impl.rs -tests/ui/c-variadic/copy.rs tests/ui/asm/x86_64/global_asm_escape.rs tests/ui/lto/all-crates.rs -tests/ui/consts/const-eval/c-variadic.rs -tests/ui/eii/default/call_default_panics.rs -tests/ui/explicit-tail-calls/indirect.rs -tests/ui/traits/inheritance/self-in-supertype.rs -tests/ui/fmt/fmt_debug/shallow.rs -tests/ui/c-variadic/roundtrip.rs -tests/ui/eii/eii_impl_with_contract.rs -tests/ui/eii/static/cross_crate_decl.rs -tests/ui/eii/static/cross_crate_def.rs -tests/ui/eii/static/same_address.rs -tests/ui/eii/static/simple.rs -tests/ui/explicit-tail-calls/default-trait-method.rs +tests/ui/explicit-tail-calls/tailcc-no-signature-restriction.rs +tests/ui/abi/rust-tail-cc.rs +tests/ui/abi/rust-preserve-none-cc.rs +tests/ui/extern/extern-types-field-offset.rs diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 6afd54e1c3fe0..9c4708274280c 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -7,6 +7,68 @@ use std::process::Command; use lang_tester::LangTester; use tempfile::TempDir; +/// Directory holding the C files that the `tests/run` tests can link against. +/// +/// A `tests/c/.c` is compiled by the real GCC and linked into `tests/run/.rs`. +const C_TESTS_DIR: &str = "tests/c"; + +/// The m68k cross toolchain is not on the default `PATH` in CI. +// FIXME(antoyo): find a better way to add the PATH necessary locally. +const M68K_TOOLCHAIN_DIR: &str = "/opt/m68k-unknown-linux-gnu/bin"; + +fn target_path(test_target: &Option) -> Option { + test_target.as_ref().map(|_| { + let env_path = std::env::var("PATH").unwrap_or_default(); + format!("{}:{}", M68K_TOOLCHAIN_DIR, env_path) + }) +} + +/// Compile every C file in `tests/c` to an object file in `objects_dir`. +fn compile_c_files(objects_dir: &Path, test_target: &Option) { + let c_tests_dir = Path::new(C_TESTS_DIR); + if !c_tests_dir.is_dir() { + return; + } + std::fs::create_dir_all(objects_dir).expect("create the directory for the C object files"); + + let compiler = match test_target { + Some(target) => format!("{}-gcc", target), + None => "gcc".to_string(), + }; + + for entry in std::fs::read_dir(c_tests_dir).expect("read the C tests directory") { + let source = entry.expect("directory entry").path(); + if source.extension().and_then(|extension| extension.to_str()) != Some("c") { + continue; + } + let object = c_object_path(objects_dir, &source); + + let mut command = Command::new(&compiler); + command.arg("-c"); + // Optimize: an unoptimized C caller can happen to agree with a wrong callee. + command.arg("-O1"); + // GCC notes that the ABI of over-aligned arguments changed in GCC 4.6. That is the ABI + // being tested in overaligned_byval_abi, so the note is expected rather than a problem. + command.arg("-Wno-psabi"); + command.arg("-o"); + command.arg(&object); + command.arg(&source); + if let Some(env_path) = target_path(test_target) { + command.env("PATH", env_path); + } + + let status = command + .status() + .unwrap_or_else(|error| panic!("failed to run `{}`: {}", compiler, error)); + assert!(status.success(), "failed to compile `{}`", source.display()); + } +} + +/// The object file that a test source links against, if any: `tests/c/x.c` for `tests/run/x.rs`. +fn c_object_path(objects_dir: &Path, source: &Path) -> PathBuf { + objects_dir.join(source.file_stem().expect("file_stem")).with_extension("o") +} + fn compile_and_run_cmds( compiler_args: Vec, test_target: &Option, @@ -18,10 +80,7 @@ fn compile_and_run_cmds( // Test command 2: run `tempdir/x`. if test_target.is_some() { - let mut env_path = std::env::var("PATH").unwrap_or_default(); - // FIXME(antoyo): find a better way to add the PATH necessary locally. - env_path = format!("/opt/m68k-unknown-linux-gnu/bin:{}", env_path); - compiler.env("PATH", env_path); + compiler.env("PATH", target_path(test_target).expect("target PATH")); let mut commands = vec![("Compiler", compiler)]; if test_mode.should_run() { @@ -82,8 +141,10 @@ impl TestMode { } } +#[allow(clippy::too_many_arguments)] fn build_test_runner( tempdir: PathBuf, + c_objects_dir: PathBuf, current_dir: String, build_mode: BuildMode, test_kind: &str, @@ -159,6 +220,13 @@ fn build_test_runner( path.to_str().expect("to_str").into(), ]; + // Link against `tests/c/.c`, when the test has one. + let c_object = c_object_path(&c_objects_dir, path); + if c_object.exists() { + compiler_args.push("-C".into()); + compiler_args.push(format!("link-arg={}", c_object.display())); + } + if let Some(ref target) = test_target { compiler_args.extend_from_slice(&["--target".into(), target.into()]); @@ -193,9 +261,10 @@ fn build_test_runner( .run(); } -fn compile_tests(tempdir: PathBuf, current_dir: String) { +fn compile_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { build_test_runner( tempdir, + c_objects_dir, current_dir, BuildMode::Debug, "lang compile", @@ -205,24 +274,32 @@ fn compile_tests(tempdir: PathBuf, current_dir: String) { ); } -fn run_tests(tempdir: PathBuf, current_dir: String) { +fn run_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) { build_test_runner( tempdir.clone(), + c_objects_dir.clone(), current_dir.clone(), BuildMode::Debug, "[DEBUG] lang run", "tests/run", TestMode::CompileAndRun, - &[], + &[ + // FIXME: remove this when the unwind issue is fixed in GCC m68k upstream. + "catch_unwind.rs", + ], ); build_test_runner( tempdir, + c_objects_dir, current_dir.to_string(), BuildMode::Release, "[RELEASE] lang run", "tests/run", TestMode::CompileAndRun, - &[], + &[ + // FIXME: remove this when the unwind issue is fixed in GCC m68k upstream. + "catch_unwind.rs", + ], ); } @@ -232,6 +309,11 @@ fn main() { let current_dir = current_dir.to_str().expect("current dir").to_string(); let tempdir_path: PathBuf = tempdir.as_ref().into(); - compile_tests(tempdir_path.clone(), current_dir.clone()); - run_tests(tempdir_path, current_dir); + let c_objects_dir = tempdir_path.join("c-objects"); + // FIXME(antoyo): find a way to send this via a cli argument. + let test_target = std::env::var("CG_GCC_TEST_TARGET").ok(); + compile_c_files(&c_objects_dir, &test_target); + + compile_tests(tempdir_path.clone(), c_objects_dir.clone(), current_dir.clone()); + run_tests(tempdir_path, c_objects_dir, current_dir); } diff --git a/tests/run/catch_unwind.rs b/tests/run/catch_unwind.rs new file mode 100644 index 0000000000000..919213db5a4a5 --- /dev/null +++ b/tests/run/catch_unwind.rs @@ -0,0 +1,25 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: Caught + +#![feature(fn_traits, unboxed_closures)] + +struct Wrapper
(A); + +impl R> FnOnce<()> for Wrapper { + type Output = R; + + #[inline] + extern "rust-call" fn call_once(self, _args: ()) -> R { + (self.0)() + } +} + +fn main() { + std::panic::set_hook(Box::new(|_| {})); + let result = std::panic::catch_unwind(Wrapper(|| panic!())); + assert!(result.is_err()); + println!("Caught"); +} diff --git a/tests/run/custom_abort.rs b/tests/run/custom_abort.rs new file mode 100644 index 0000000000000..eafa4321a4324 --- /dev/null +++ b/tests/run/custom_abort.rs @@ -0,0 +1,27 @@ +// Compiler: +// +// Run-time: +// status: 42 + +// Check that a program can define its own `abort`. + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[no_mangle] +extern "C" fn abort() { + unsafe { + libc::exit(42); + } +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + abort(); + 0 +} diff --git a/tests/run/import_linkage.rs b/tests/run/import_linkage.rs new file mode 100644 index 0000000000000..bf5cb9e532799 --- /dev/null +++ b/tests/run/import_linkage.rs @@ -0,0 +1,84 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks the `#[linkage]` flavours an `extern` static can be imported with, against the symbols +// `tests/c/import_linkage.c` defines. +// +// The value of such an import is the address of the symbol rather than its contents, which is why +// the types are pointers: an `extern_weak` import of a symbol nobody defines reads as null instead +// of failing the link. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +extern "C" { + #[linkage = "external"] + static external_value: *const i32; + #[linkage = "available_externally"] + static available_externally_value: *const i32; + #[linkage = "linkonce"] + static linkonce_value: *const i32; + #[linkage = "linkonce_odr"] + static linkonce_odr_value: *const i32; + #[linkage = "weak"] + static weak_value: *const i32; + #[linkage = "weak_odr"] + static weak_odr_value: *const i32; + #[linkage = "common"] + static common_value: *const i32; + #[linkage = "extern_weak"] + static extern_weak_value: *const i32; + // An import is an undefined reference whatever the flavour says. Upstream bug: rustc lowers + // this one to an internal declaration, which LLVM's verifier rejects ("Global is external, but + // doesn't have external or weak linkage!") and which crashes cg_llvm at -O3. + #[linkage = "internal"] + static internal_value: *const i32; + + // Nothing defines this one, so it stays null instead of breaking the link. + #[linkage = "extern_weak"] + static undefined_value: *const i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + unsafe { + if *external_value != 1 { + return 1; + } + if *available_externally_value != 2 { + return 2; + } + if *linkonce_value != 3 { + return 3; + } + if *linkonce_odr_value != 4 { + return 4; + } + if *weak_value != 5 { + return 5; + } + if *weak_odr_value != 6 { + return 6; + } + if *common_value != 7 { + return 7; + } + if *extern_weak_value != 8 { + return 8; + } + if *internal_value != 9 { + return 9; + } + if undefined_value as usize != 0 { + return 10; + } + } + 0 +} diff --git a/tests/run/nonzero_div_ceil.rs b/tests/run/nonzero_div_ceil.rs new file mode 100644 index 0000000000000..e6bd3c2ec9845 --- /dev/null +++ b/tests/run/nonzero_div_ceil.rs @@ -0,0 +1,17 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::hint::black_box; +use std::num::NonZero; + +fn main() { + for (dividend, divisor, expected) in + [(10u8, 3u8, 4u8), (1, 254, 1), (1, 255, 1), (2, 254, 1), (2, 255, 1), (200, 100, 2)] + { + let dividend = NonZero::new(black_box(dividend)).unwrap(); + let divisor = NonZero::new(black_box(divisor)).unwrap(); + assert_eq!(dividend.div_ceil(divisor).get(), expected); + } +} diff --git a/tests/run/overaligned_byval_abi.rs b/tests/run/overaligned_byval_abi.rs new file mode 100644 index 0000000000000..78ee35f05ca58 --- /dev/null +++ b/tests/run/overaligned_byval_abi.rs @@ -0,0 +1,89 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that cg_gcc passes an over-aligned by-value ("byval") argument where the platform ABI +// says it goes, by calling in both directions with `tests/c/overaligned_byval_abi.c`, which is +// compiled by the real GCC. +// +// `tests/run/overaligned_byval_arg.rs` covers the Rust-visible half of the same bug. It cannot +// cover this one: with cg_gcc on both sides of a call, caller and callee place the argument at +// the same wrong offset and agree with each other. +// +// Two over-aligned arguments are used rather than one so that the failure is deterministic. A +// backend that drops `align(64)` packs the arguments at offsets 0, 24, 88 and 112 of the argument +// area; 112 - 24 = 88 is not a multiple of 64, so the two of them cannot both land on a 64-byte +// boundary however the argument area itself is aligned. With a single over-aligned argument the +// frame often happens to be 64-aligned and the bug hides. +// +// Only the values received are checked, never the address an argument landed at: which alignment +// a target gives a by-value stack slot differs between targets, but the two sides of a call +// agreeing on it does not. `overaligned_byval_arg.rs` is where the alignment itself is asserted. + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[repr(C)] +struct Big { + a: i64, + b: i64, + c: i64, +} + +#[repr(C, align(64))] +struct Aligned { + x: i32, +} + +extern "C" { + fn c_take_both(first: Big, second: Aligned, third: Big, fourth: Aligned) -> i32; + fn c_call_rust() -> i32; +} + +// The callee for the GCC-built caller in `c_call_rust`. +// +// `#[no_mangle]` is not only about the symbol name: it makes the symbol externally visible, which +// pins the calling convention. Without it the function has internal linkage and GCC is free to +// clone it with a changed convention at `-O3` (the symbol comes out as `...constprop.0.isra.0`), +// so the arguments never travel through the stack slots and the release build passes spuriously. +#[no_mangle] +extern "C" fn rust_take_both(first: Big, second: Aligned, third: Big, fourth: Aligned) -> i32 { + if first.a as i32 != 1 || first.b as i32 != 2 || first.c as i32 != 3 { + return 5; + } + if second.x != 42 { + return 6; + } + if third.a as i32 != 4 || third.b as i32 != 5 || third.c as i32 != 6 { + return 7; + } + if fourth.x != 43 { + return 8; + } + 0 +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + // cg_gcc as the caller, GCC as the callee. + let result = unsafe { + c_take_both( + Big { a: 1, b: 2, c: 3 }, + Aligned { x: 42 }, + Big { a: 4, b: 5, c: 6 }, + Aligned { x: 43 }, + ) + }; + if result != 0 { + return result; + } + + // GCC as the caller, cg_gcc as the callee. + unsafe { c_call_rust() } +} diff --git a/tests/run/overaligned_byval_arg.rs b/tests/run/overaligned_byval_arg.rs new file mode 100644 index 0000000000000..e20ec11732962 --- /dev/null +++ b/tests/run/overaligned_byval_arg.rs @@ -0,0 +1,41 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[repr(C)] +struct Big { + a: i64, + b: i64, + c: i64, +} + +#[repr(C, align(64))] +struct Aligned { + x: i32, +} + +#[inline(never)] +#[no_mangle] +extern "C" fn check(_b1: Big, a1: Aligned, _b2: Big, a2: Aligned) -> i32 { + if (&a1 as *const Aligned as usize) % 64 != 0 { + return 1; + } + if (&a2 as *const Aligned as usize) % 64 != 0 { + return 2; + } + 0 +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + check(Big { a: 1, b: 2, c: 3 }, Aligned { x: 42 }, Big { a: 4, b: 5, c: 6 }, Aligned { x: 43 }) +} diff --git a/tests/run/ptr_to_int_div.rs b/tests/run/ptr_to_int_div.rs new file mode 100644 index 0000000000000..afc563d6c977b --- /dev/null +++ b/tests/run/ptr_to_int_div.rs @@ -0,0 +1,19 @@ +// Compiler: +// +// Run-time: +// status: 0 + +use std::hint::black_box; +use std::mem::transmute; + +fn main() { + let pointer = black_box(usize::MAX) as *const (); + + let unsigned = unsafe { transmute::<*const (), usize>(pointer) }; + assert_eq!(unsigned / black_box(2), usize::MAX / 2); + assert_eq!(unsigned % black_box(2), usize::MAX % 2); + + let signed = unsafe { transmute::<*const (), isize>(pointer) }; + assert_eq!(signed / black_box(2), -1isize / 2); + assert_eq!(signed % black_box(2), -1isize % 2); +} diff --git a/tests/run/simd.rs b/tests/run/simd.rs new file mode 100644 index 0000000000000..e0a23fdccf8ce --- /dev/null +++ b/tests/run/simd.rs @@ -0,0 +1,81 @@ +// Compiler: +// +// Run-time: +// status: 0 + +#![feature(portable_simd)] + +use std::hint::black_box; +use std::simd::prelude::*; + +fn test_saturating_add() { + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let ones = i32x4::splat(1); + assert_eq!( + black_box(values).saturating_add(black_box(ones)).to_array(), + [i32::MIN + 1, -1, 4, i32::MAX] + ); + + let values = u32x4::from_array([0, 2, 3, u32::MAX]); + let ones = u32x4::splat(1); + assert_eq!(black_box(values).saturating_add(black_box(ones)).to_array(), [1, 3, 4, u32::MAX]); +} + +fn test_saturating_sub() { + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let zero = i32x4::splat(0); + assert_eq!( + black_box(zero).saturating_sub(black_box(values)).to_array(), + [i32::MAX, 2, -3, i32::MIN + 1] + ); + assert_eq!(black_box(values).saturating_neg().to_array(), [i32::MAX, 2, -3, i32::MIN + 1]); + assert_eq!(black_box(values).saturating_abs().to_array(), [i32::MAX, 2, 3, i32::MAX]); + + let values = i32x4::from_array([i32::MIN, -2, 3, i32::MAX]); + let ones = i32x4::splat(1); + assert_eq!( + black_box(values).saturating_sub(black_box(ones)).to_array(), + [i32::MIN, -3, 2, i32::MAX - 1] + ); + + let values = u32x4::from_array([0, 2, 3, u32::MAX]); + let ones = u32x4::splat(1); + assert_eq!( + black_box(values).saturating_sub(black_box(ones)).to_array(), + [0, 1, 2, u32::MAX - 1] + ); +} + +fn test_float_cast() { + let floats = f32x4::from_array([1.9, -4.5, f32::INFINITY, f32::NAN]); + assert_eq!(black_box(floats).cast::().to_array(), [1, -4, i32::MAX, 0]); + + let floats = f32x4::from_array([f32::NEG_INFINITY, 1e20, -1e20, -0.0]); + assert_eq!(black_box(floats).cast::().to_array(), [i32::MIN, i32::MAX, i32::MIN, 0]); + + let floats = f32x4::from_array([-1.0, 3.7, f32::NAN, 1e20]); + assert_eq!(black_box(floats).cast::().to_array(), [0, 3, 0, u32::MAX]); + + let floats = f64x4::from_array([-1.5, 2.5, f64::NAN, f64::INFINITY]); + assert_eq!(black_box(floats).cast::().to_array(), [-1, 2, 0, i64::MAX]); +} + +fn test_arith_offset() { + let values = [10i32, 11, 12, 13, 14, 15, 16, 17]; + let indices = usizex4::from_array([7, 5, 3, 1]); + assert_eq!( + i32x4::gather_or_default(black_box(&values), black_box(indices)).to_array(), + [17, 15, 13, 11] + ); + + let mut destination = [0i32; 8]; + i32x4::from_array([1, 2, 3, 4]).scatter(black_box(&mut destination), black_box(indices)); + assert_eq!(destination, [0, 4, 0, 3, 0, 2, 0, 1]); +} + +fn main() { + test_saturating_add(); + test_saturating_sub(); + test_float_cast(); + test_arith_offset(); +} diff --git a/tests/run/static_alloc_shapes.rs b/tests/run/static_alloc_shapes.rs new file mode 100644 index 0000000000000..39a4d07bdf638 --- /dev/null +++ b/tests/run/static_alloc_shapes.rs @@ -0,0 +1,50 @@ +// Compiler: +// +// Run-time: +// status: 0 +// stdout: 8 +// 12 +// 5 +// 7 +// 7 +// 9 + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +// One byte run of each length class that maps to a distinct array element type. +static mut BYTES8: [u8; 8] = [1, 2, 3, 4, 5, 6, 7, 8]; +static mut BYTES12: [u8; 12] = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]; +static mut BYTES5: [u8; 5] = [1, 2, 3, 4, 5]; + +static mut VALUE: isize = 7; +static mut OTHER: isize = 9; + +// An allocation that is exactly one relocation, so it ends on a pointer with no trailing bytes. +static mut PTR: &isize = unsafe { &VALUE }; + +struct TwoRefs { + first: &'static isize, + second: &'static isize, +} + +// Two adjacent relocations, with no byte run between them. +static mut TWO_REFS: TwoRefs = TwoRefs { first: unsafe { &VALUE }, second: unsafe { &OTHER } }; + +#[no_mangle] +extern "C" fn main(_argc: isize, _argv: *const *const u8) -> i32 { + unsafe { + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES8[7] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES12[11] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, BYTES5[4] as isize); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *PTR); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *TWO_REFS.first); + libc::printf(b"%ld\n\0" as *const u8 as *const i8, *TWO_REFS.second); + } + 0 +} diff --git a/tests/run/static_linkage.rs b/tests/run/static_linkage.rs new file mode 100644 index 0000000000000..7b911c064d797 --- /dev/null +++ b/tests/run/static_linkage.rs @@ -0,0 +1,79 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that `#[linkage]` on a static that this crate defines reaches the symbol, against +// `tests/c/static_linkage.c`, which defines the overridable ones strongly. +// +// If `predefine_static` were to ignore its `linkage` argument outright, every static would come out as +// an ordinary global symbol: the overridable ones would clash with the C definitions at link time, and +// `internal` would export a symbol it should have kept private. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[linkage = "weak"] +#[no_mangle] +pub static weak_static: i32 = 0; + +#[linkage = "weak_odr"] +#[no_mangle] +pub static weak_odr_static: i32 = 0; + +#[linkage = "linkonce"] +#[no_mangle] +pub static linkonce_static: i32 = 0; + +#[linkage = "linkonce_odr"] +#[no_mangle] +pub static linkonce_odr_static: i32 = 0; + +// `common` is only valid on a mutable global: LLVM rejects a constant one. +#[linkage = "common"] +#[no_mangle] +pub static mut common_static: i32 = 0; + +// Private to this crate, so the C definition of the same name is a different object. +#[linkage = "internal"] +#[no_mangle] +pub static internal_static: i32 = 100; + +// Not overridden by the C side: the definition here is the one that survives. +#[linkage = "weak"] +#[no_mangle] +pub static only_weak_static: i32 = 6; + +// The real definition is the one in the C file; a backend may read it or emit an equivalent copy of +// this initializer, so both spell the same value. +#[linkage = "available_externally"] +#[no_mangle] +pub static available_externally_static: i32 = 7; + +extern "C" { + fn c_read_all() -> i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + let result = unsafe { c_read_all() }; + if result != 0 { + return result; + } + + if internal_static != 100 { + return 1; + } + if only_weak_static != 6 { + return 2; + } + if available_externally_static != 7 { + return 3; + } + 0 +} diff --git a/tests/run/weak_function_linkage.rs b/tests/run/weak_function_linkage.rs new file mode 100644 index 0000000000000..677f01353401a --- /dev/null +++ b/tests/run/weak_function_linkage.rs @@ -0,0 +1,106 @@ +// Compiler: +// +// Run-time: +// status: 0 + +// Checks that the `#[linkage]` flavours another object file is allowed to override are emitted as +// weak symbols, by linking against `tests/c/weak_function_linkage.c`, which defines the same +// symbols strongly. + +#![feature(linkage, no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use mini_core::*; + +#[linkage = "weak"] +#[no_mangle] +extern "C" fn weak_function() -> i32 { + 0 +} + +// `_odr` promises every definition of the symbol is equivalent, which lets a backend call this body +// instead of the one in the C file. They spell the same value for that reason. +#[linkage = "weak_odr"] +#[no_mangle] +extern "C" fn weak_odr_function() -> i32 { + 2 +} + +#[linkage = "linkonce"] +#[no_mangle] +extern "C" fn linkonce_function() -> i32 { + 0 +} + +#[linkage = "linkonce_odr"] +#[no_mangle] +extern "C" fn linkonce_odr_function() -> i32 { + 4 +} + +// `#[linkage = "common"]` is absent on purpose: a common symbol is `SHN_COMMON`, which the object +// format only allows for objects, so no backend can give a function that linkage. + +// Not overridden by the C side: the definition here is the one that runs. +#[linkage = "weak"] +#[no_mangle] +extern "C" fn only_weak_function() -> i32 { + 6 +} + +// The real definition is the one in the C file; a backend may call it or emit an equivalent copy of +// this body, so both spell the same value. +#[linkage = "available_externally"] +#[no_mangle] +extern "C" fn available_externally_function() -> i32 { + 7 +} + +// GCC drops `weak` from a function that is also `inline`: a backend that keeps the hint emits this +// as an ordinary global symbol and clashes with the C definition. rustc lints the hint as ignored +// on a function with an explicit `#[linkage]`, hence the `allow`. +#[linkage = "weak"] +#[inline] +#[no_mangle] +#[allow(unused_attributes)] +extern "C" fn weak_inline_function() -> i32 { + 0 +} + +extern "C" { + fn c_call_all() -> i32; +} + +#[no_mangle] +extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { + let result = unsafe { c_call_all() }; + if result != 0 { + return result; + } + + if weak_function() != 1 { + return 1; + } + if weak_odr_function() != 2 { + return 2; + } + if linkonce_function() != 3 { + return 3; + } + if linkonce_odr_function() != 4 { + return 4; + } + if only_weak_function() != 6 { + return 6; + } + if available_externally_function() != 7 { + return 7; + } + if weak_inline_function() != 8 { + return 8; + } + 0 +} diff --git a/tools/cspell_dicts/rust.txt b/tools/cspell_dicts/rust.txt deleted file mode 100644 index 379cbd77eef01..0000000000000 --- a/tools/cspell_dicts/rust.txt +++ /dev/null @@ -1,2 +0,0 @@ -lateout -repr diff --git a/tools/cspell_dicts/rustc_codegen_gcc.txt b/tools/cspell_dicts/rustc_codegen_gcc.txt deleted file mode 100644 index 4fb018b3ecd87..0000000000000 --- a/tools/cspell_dicts/rustc_codegen_gcc.txt +++ /dev/null @@ -1,78 +0,0 @@ -aapcs -addo -archs -ashl -ashr -cgcx -clzll -cmse -codegened -csky -ctfe -ctlz -ctpop -cttz -ctzll -flto -fmaximumf -fmuladd -fmuladdf -fminimumf -fmul -fptosi -fptosui -fptoui -fwrapv -gimple -hrtb -immediates -interner -liblto -llbb -llcx -llextra -llfn -lgcc -llmod -llresult -llret -ltrans -llty -llval -llvals -loong -lshr -masm -maximumf -maxnumf -mavx -mcmodel -minimumf -minnumf -miri -monomorphization -monomorphizations -monomorphized -monomorphizing -movnt -mulo -nvptx -pointee -powitf -reassoc -riscv -rlib -roundevenf -rustc -sitofp -sizet -spir -subo -sysv -tbaa -uitofp -unord -uninlined -utrunc -xabort -zext From 4ca0cc142880be509464c988e0aaf47be30b8abc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 20:52:04 +0200 Subject: [PATCH 0365/1309] Update gcc submodule --- src/gcc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gcc b/src/gcc index 6f155cc3f5a2d..badf78d09d16e 160000 --- a/src/gcc +++ b/src/gcc @@ -1 +1 @@ -Subproject commit 6f155cc3f5a2dff33afe6cc3ed6c2e0e605ae6a3 +Subproject commit badf78d09d16e66f4ca07971c51aa6a227558d4f From c10c4cf93675ae8532c75b497282d588263f94c7 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 20:56:48 +0200 Subject: [PATCH 0366/1309] Fix source code divergence --- .../.github/workflows/ci.yml | 13 +- .../.github/workflows/stdarch.yml | 20 +- compiler/rustc_codegen_gcc/.gitignore | 2 +- compiler/rustc_codegen_gcc/CONTRIBUTING.md | 2 +- compiler/rustc_codegen_gcc/Cargo.lock | 92 +--- compiler/rustc_codegen_gcc/Readme.md | 8 +- .../rustc_codegen_gcc/build_system/Cargo.lock | 2 +- .../build_system/asm-tester/Cargo.lock | 507 ++++++++++++++++++ .../build_system/asm-tester/Cargo.toml | 13 + .../build_system/asm-tester/src/main.rs | 66 +++ .../build_system/src/build.rs | 2 +- .../build_system/src/clean.rs | 3 +- .../build_system/src/clippy.rs | 62 +++ .../build_system/src/config.rs | 13 +- .../rustc_codegen_gcc/build_system/src/fmt.rs | 5 +- .../build_system/src/main.rs | 112 ++-- .../build_system/src/rust_tools.rs | 2 +- .../build_system/src/test.rs | 141 ++++- .../build_system/src/todo.rs | 72 +++ .../build_system/src/utils.rs | 58 +- compiler/rustc_codegen_gcc/doc/subtree.md | 4 +- .../example/mini_core_hello_world.rs | 2 +- compiler/rustc_codegen_gcc/src/abi.rs | 41 +- compiler/rustc_codegen_gcc/src/asm.rs | 19 +- compiler/rustc_codegen_gcc/src/attributes.rs | 26 + compiler/rustc_codegen_gcc/src/back/lto.rs | 37 +- compiler/rustc_codegen_gcc/src/back/write.rs | 5 +- compiler/rustc_codegen_gcc/src/base.rs | 118 +--- compiler/rustc_codegen_gcc/src/builder.rs | 119 ++-- compiler/rustc_codegen_gcc/src/callee.rs | 2 +- compiler/rustc_codegen_gcc/src/consts.rs | 45 +- compiler/rustc_codegen_gcc/src/declare.rs | 32 +- compiler/rustc_codegen_gcc/src/diagnostics.rs | 4 - compiler/rustc_codegen_gcc/src/gcc_util.rs | 2 +- compiler/rustc_codegen_gcc/src/int.rs | 18 +- .../rustc_codegen_gcc/src/intrinsic/archs.rs | 86 ++- .../rustc_codegen_gcc/src/intrinsic/llvm.rs | 111 +++- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 44 +- .../src/intrinsic/old_archs.rs | 4 + compiler/rustc_codegen_gcc/src/lib.rs | 22 +- compiler/rustc_codegen_gcc/src/mono_item.rs | 23 +- compiler/rustc_codegen_gcc/src/type_.rs | 4 +- .../tests/asm/asm/comments.rs | 12 + .../x86_64-naked-fn-no-cet-prolog.rs | 24 + .../tests/asm/panic-no-unwind-no-uwtable.rs | 8 + compiler/rustc_codegen_gcc/tests/asm/used.rs | 14 + .../tests/asm/x86_64-sse_crc.rs | 12 + .../compile/x86_interrupt_first_arg_byval.rs | 16 + compiler/rustc_codegen_gcc/tests/cpuid.def | 27 + .../rustc_codegen_gcc/tests/lang_tests.rs | 18 +- compiler/rustc_codegen_gcc/tests/run/asm.rs | 42 ++ compiler/rustc_codegen_gcc/tests/run/int.rs | 25 + .../tests/run/mir_preserve_ub_empty_switch.rs | 35 ++ .../tools/generate_intrinsics.py | 36 +- 54 files changed, 1739 insertions(+), 493 deletions(-) create mode 100644 compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.lock create mode 100644 compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.toml create mode 100644 compiler/rustc_codegen_gcc/build_system/asm-tester/src/main.rs create mode 100644 compiler/rustc_codegen_gcc/build_system/src/clippy.rs create mode 100644 compiler/rustc_codegen_gcc/build_system/src/todo.rs create mode 100644 compiler/rustc_codegen_gcc/tests/asm/asm/comments.rs create mode 100644 compiler/rustc_codegen_gcc/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs create mode 100644 compiler/rustc_codegen_gcc/tests/asm/panic-no-unwind-no-uwtable.rs create mode 100644 compiler/rustc_codegen_gcc/tests/asm/used.rs create mode 100644 compiler/rustc_codegen_gcc/tests/asm/x86_64-sse_crc.rs create mode 100644 compiler/rustc_codegen_gcc/tests/compile/x86_interrupt_first_arg_byval.rs create mode 100644 compiler/rustc_codegen_gcc/tests/cpuid.def create mode 100644 compiler/rustc_codegen_gcc/tests/run/mir_preserve_ub_empty_switch.rs diff --git a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml index 8888fdc3ee093..2f5cc409e363d 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/ci.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests", + "--std-tests --alloc-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", @@ -91,16 +91,17 @@ jobs: - name: Check formatting run: ./y.sh fmt --check - - name: clippy - run: | - cargo clippy --all-targets -- -D warnings - cargo clippy --all-targets --no-default-features -- -D warnings - cargo clippy --manifest-path build_system/Cargo.toml --all-targets -- -D warnings + - name: Check todo + run: ./y.sh check-todo + + - name: Check lints + run: ./y.sh clippy - name: Build run: | ./y.sh build --sysroot ./y.sh test --cargo-tests + CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - name: Run y.sh cargo build run: | diff --git a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml index 66f30b147b4c0..17d6449c85e08 100644 --- a/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml +++ b/compiler/rustc_codegen_gcc/.github/workflows/stdarch.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: cargo_runner: [ - "sde -future -rtm_mode full --", + "sde -cpuid-in /home/runner/work/rustc_codegen_gcc/rustc_codegen_gcc/tests/cpuid.def -rtm_mode full --", "", ] @@ -42,8 +42,14 @@ jobs: - name: Install more recent binutils run: | echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list - sudo apt-get update + sudo apt-get update -o Acquire::Retries=3 sudo apt-get install binutils + installed="$(dpkg-query --showformat='${Version}' --show binutils)" + echo "Installed binutils: $installed" + if dpkg --compare-versions "$installed" lt "2.44"; then + echo "::error::binutils upgrade failed (got $installed, need >= 2.44); the apt fetch probably failed" + exit 1 + fi - name: Install Intel Software Development Emulator if: ${{ matrix.cargo_runner }} @@ -51,10 +57,9 @@ jobs: mkdir intel-sde cd intel-sde version=10.8.0-2026-03-15 - url_path=915934 dir=sde-external-$version-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/$url_path/$file + wget http://ci-mirrors.rust-lang.org/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde @@ -90,14 +95,15 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - # FIXME: remove --skip test_tile_ when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/compiler/rustc_codegen_gcc/.gitignore b/compiler/rustc_codegen_gcc/.gitignore index 2a8fdcda0b483..13bd0d0ffde9b 100644 --- a/compiler/rustc_codegen_gcc/.gitignore +++ b/compiler/rustc_codegen_gcc/.gitignore @@ -7,7 +7,7 @@ perf.data.old *.events *.string* gimple* -*asm +*_asm res test-backend projects diff --git a/compiler/rustc_codegen_gcc/CONTRIBUTING.md b/compiler/rustc_codegen_gcc/CONTRIBUTING.md index 8f81ecca445a8..c5c2a783b1ee7 100644 --- a/compiler/rustc_codegen_gcc/CONTRIBUTING.md +++ b/compiler/rustc_codegen_gcc/CONTRIBUTING.md @@ -112,7 +112,7 @@ Full list of debugging options can be found in the [README](Readme.md#env-vars). ### Code Style Guidelines - Follow Rust standard coding conventions -- Ensure your code passes `rustfmt` and `clippy` +- Ensure your code passes `rustfmt` and `clippy` (you can run them with `y.sh fmt` and `y.sh clippy`) - Add comments explaining complex logic, especially in GCC interface code ## Additional Resources diff --git a/compiler/rustc_codegen_gcc/Cargo.lock b/compiler/rustc_codegen_gcc/Cargo.lock index c7e979a1112e3..c174628d0d188 100644 --- a/compiler/rustc_codegen_gcc/Cargo.lock +++ b/compiler/rustc_codegen_gcc/Cargo.lock @@ -31,9 +31,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "memchr" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", @@ -311,78 +311,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/compiler/rustc_codegen_gcc/Readme.md b/compiler/rustc_codegen_gcc/Readme.md index 6b1f90b918855..9a7c624c9bc22 100644 --- a/compiler/rustc_codegen_gcc/Readme.md +++ b/compiler/rustc_codegen_gcc/Readme.md @@ -136,19 +136,21 @@ $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run +$ CHANNEL=release $CG_GCCJIT_DIR/y.sh cargo run ``` -If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. ### Rustc If you want to run `rustc` directly, you can do so with: ```bash -$ ./y.sh rustc my_crate.rs +$ CHANNEL=release ./y.sh rustc my_crate.rs ``` +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. + You can do the same manually (although we don't recommend it): ```bash diff --git a/compiler/rustc_codegen_gcc/build_system/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/Cargo.lock index e727561a2bfba..5e761149eb3bc 100644 --- a/compiler/rustc_codegen_gcc/build_system/Cargo.lock +++ b/compiler/rustc_codegen_gcc/build_system/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "boml" diff --git a/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.lock b/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.lock new file mode 100644 index 0000000000000..9ad96acfda407 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.lock @@ -0,0 +1,507 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "asm-tester" +version = "0.1.0" +dependencies = [ + "compiletest_rs", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compiletest_rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "windows-sys 0.59.0", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "miow" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tester" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.toml b/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.toml new file mode 100644 index 0000000000000..eeefe61bdc75b --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/asm-tester/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "asm-tester" +version = "0.1.0" +edition = "2024" + +[dependencies] +compiletest_rs = "0.11.2" + +[[bin]] +name = "asm-tester" +path = "src/main.rs" + +[workspace] diff --git a/compiler/rustc_codegen_gcc/build_system/asm-tester/src/main.rs b/compiler/rustc_codegen_gcc/build_system/asm-tester/src/main.rs new file mode 100644 index 0000000000000..00ee4ac936520 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/asm-tester/src/main.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +#[derive(Default)] +struct Config { + llvm_filecheck: Option, + filters: Vec, + rustc_flags: Vec, +} + +impl Config { + fn new() -> Result { + // We skip the program's name. + let mut args = std::env::args().skip(1); + let mut config = Self::default(); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--llvm-filecheck" => { + config.llvm_filecheck = args.next().map(PathBuf::from); + } + "--filter" => { + if let Some(arg) = args.next() { + config.filters.push(arg); + } + } + "--" => { + config.rustc_flags.extend(&mut args); + // Nothing else to be read but the `break` makes it more clear. + break; + } + arg => return Err(format!("Unknown argument {arg:?}")), + } + } + if config.llvm_filecheck.is_none() { + Err("Missing `--llvm-filecheck` option".to_owned()) + } else if config.rustc_flags.is_empty() { + Err("Missing rustc flags (passed after `--`)".to_owned()) + } else { + Ok(config) + } + } +} + +fn main() { + let Config { llvm_filecheck, filters, rustc_flags } = match Config::new() { + Ok(c) => c, + Err(error) => { + eprintln!("{error}"); + std::process::exit(1); + } + }; + + let mut test_config = compiletest_rs::Config::default(); + + test_config.mode = compiletest_rs::common::Mode::Assembly; + test_config.src_base = PathBuf::from("tests/asm"); + test_config.llvm_filecheck = llvm_filecheck; + test_config.filters = filters; + test_config.strict_headers = true; + test_config.build_base = PathBuf::from("build/tests/asm"); + test_config.target_rustcflags = Some(rustc_flags.join(" ")); + test_config.link_deps(); + test_config.clean_rmeta(); + + compiletest_rs::run_tests(&test_config) +} diff --git a/compiler/rustc_codegen_gcc/build_system/src/build.rs b/compiler/rustc_codegen_gcc/build_system/src/build.rs index 2f2900af5c88a..bcd386bfebdae 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/build.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/build.rs @@ -266,7 +266,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false)?; + args.config_info.setup(&mut env, false, true)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/compiler/rustc_codegen_gcc/build_system/src/clean.rs b/compiler/rustc_codegen_gcc/build_system/src/clean.rs index 43f01fdf35ecb..ec2092ee92ef5 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/clean.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/clean.rs @@ -74,7 +74,8 @@ fn clean_ui_tests() -> Result<(), String> { let path = Path::new(crate::BUILD_DIR) .join("rust/build/x86_64-unknown-linux-gnu/test/") .join(directory); - run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; + // The directory might not exist, so ignore the error. + let _ = run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None); } Ok(()) } diff --git a/compiler/rustc_codegen_gcc/build_system/src/clippy.rs b/compiler/rustc_codegen_gcc/build_system/src/clippy.rs new file mode 100644 index 0000000000000..813d4b9141e1c --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/src/clippy.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present}; + +fn show_usage() { + println!( + r#" +`clippy` command help: + + --help : Show this help"# + ); +} + +pub fn run() -> Result<(), String> { + // We skip binary name and the `info` command. + let args = std::env::args().skip(2); + #[allow(clippy::never_loop)] + for arg in args { + match arg.as_str() { + "--help" => { + show_usage(); + return Ok(()); + } + _ => return Err(format!("Unknown option {arg}")), + } + } + + run_tool_and_install_it_if_not_present(&[ + &"cargo", + &"clippy", + &"--all-targets", + &"--", + &"-D", + &"warnings", + ])?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--no-default-features", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--manifest-path", + &"build_system/Cargo.toml", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + Ok(()) +} diff --git a/compiler/rustc_codegen_gcc/build_system/src/config.rs b/compiler/rustc_codegen_gcc/build_system/src/config.rs index 8eb6d8f019e1c..fd78f691d1657 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/config.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/config.rs @@ -314,6 +314,7 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, + generate_out_dir: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -444,12 +445,12 @@ impl ConfigInfo { self.rustc_command = vec![rustc]; self.rustc_command.extend_from_slice(&rustflags); - self.rustc_command.extend_from_slice(&[ - "-L".to_string(), - format!("crate={}", self.cargo_target_dir), - "--out-dir".to_string(), - self.cargo_target_dir.clone(), - ]); + self.rustc_command + .extend_from_slice(&["-L".to_string(), format!("crate={}", self.cargo_target_dir)]); + if generate_out_dir { + self.rustc_command + .extend_from_slice(&["--out-dir".to_string(), self.cargo_target_dir.clone()]); + } if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); diff --git a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs index 91535f217e351..dc1ca1d3e82ae 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/fmt.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/fmt.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{run_command_with_output, walk_dir}; +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present, walk_dir}; fn show_usage() { println!( @@ -31,8 +31,9 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - run_command_with_output(cmd, Some(Path::new(".")))?; + run_tool_and_install_it_if_not_present(cmd)?; run_command_with_output(cmd, Some(Path::new("build_system")))?; + run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; run_rustfmt_recursively("tests/run", check) } diff --git a/compiler/rustc_codegen_gcc/build_system/src/main.rs b/compiler/rustc_codegen_gcc/build_system/src/main.rs index d0b9811ac8ceb..37b1f306817fd 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/main.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/main.rs @@ -3,6 +3,7 @@ use std::{env, process}; mod abi_test; mod build; mod clean; +mod clippy; mod clone_gcc; mod config; mod fmt; @@ -12,6 +13,7 @@ mod prepare; mod rust_tools; mod rustc_info; mod test; +mod todo; mod utils; const BUILD_DIR: &str = "build"; @@ -24,43 +26,67 @@ macro_rules! arg_error { }}; } -fn usage() { - println!( - "\ +macro_rules! commands_decl { + ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { + enum Command { + $($variant),+ + } + + impl<'a> From> for Command { + fn from(arg: Option<&'a str>) -> Self { + match arg { + $(Some($doc_name) => Self::$variant,)+ + Some("--help") => { + usage(); + process::exit(0); + } + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + } + } + } + + fn usage() { + println!("\ rustc_codegen_gcc build system Usage: build_system [command] [options] Options: - --help : Displays this help message. + --help : Displays this help message. + +Commands:", + ); + let mut commands = vec![$(($doc_name, $doc),)+]; + let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); -Commands: - cargo : Executes a cargo command. - rustc : Compiles the program using the GCC compiler. - clean : Cleans the build directory, removing all compiled files and artifacts. - prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. - test : Runs tests for the project. - info : Displays information about the build environment and project configuration. - clone-gcc : Clones the GCC compiler from a specified source. - fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" - ); + commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); + for (name, doc) in commands { + let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::(); + eprintln!(" {name}{spacing}: {doc}."); + } + } + } } -pub enum Command { - Cargo, - Clean, - CloneGcc, - Prepare, - Build, - Rustc, - Test, - Info, - Fmt, - Fuzz, - AbiTest, +commands_decl! { + Cargo: "cargo" => "Executes a cargo command", + Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", + Clippy: "clippy" => "Runs clippy", + CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", + Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", + Build: "build" => "Compiles the project", + Rustc: "rustc" => "Compiles the program using the GCC compiler", + Test: "test" => "Runs tests for the project", + Info: "info" => "Displays information about the build environment and project configuration", + Fmt: "fmt" => "Runs rustfmt", + Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", + AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", + CheckTodo: "check-todo" => "Checks todo in the project", } fn main() { @@ -70,31 +96,7 @@ fn main() { } } - let command = match env::args().nth(1).as_deref() { - Some("cargo") => Command::Cargo, - Some("rustc") => Command::Rustc, - Some("clean") => Command::Clean, - Some("prepare") => Command::Prepare, - Some("build") => Command::Build, - Some("test") => Command::Test, - Some("info") => Command::Info, - Some("clone-gcc") => Command::CloneGcc, - Some("abi-test") => Command::AbiTest, - Some("fmt") => Command::Fmt, - Some("fuzz") => Command::Fuzz, - Some("--help") => { - usage(); - process::exit(0); - } - Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), - Some(command) => arg_error!("Unknown command {}", command), - None => { - usage(); - process::exit(0); - } - }; - - if let Err(e) = match command { + if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { Command::Cargo => rust_tools::run_cargo(), Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), @@ -106,6 +108,8 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), + Command::Clippy => clippy::run(), + Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); // CI needs to tell a build system error apart from the test failures some suites expect. diff --git a/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs b/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs index b1faa27acc4a2..1b50f11c3d324 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/rust_tools.rs @@ -72,7 +72,7 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; + config.setup(&mut env, false, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index a4bdb80c94f28..a55c2dcf83ddc 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -11,8 +11,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, - split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, + run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, }; /// Exit code of `y.sh test` when the tests ran and reported failures, as opposed to the build @@ -39,6 +39,7 @@ fn get_runners() -> Runners { ("Run failing ui pattern tests", test_failing_ui_pattern_tests), ); runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); + runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--test-release-libcore", ("Run libcore tests", test_release_libcore)); @@ -56,8 +57,10 @@ fn get_runners() -> Runners { ); runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); + runners.insert("--gcc-asm-tests", ("Run cg_gcc asm tests", test_asm)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); + runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); runners } @@ -519,6 +522,26 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn get_llvm_filecheck(env: &Env) -> Result { + match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14 || \ + which FileCheck", + ], + None, + Some(env), + ) { + Ok(cmd) => Ok(String::from_utf8_lossy(&cmd.stdout).trim().to_string()), + Err(_) => Err("Failed to retrieve LLVM FileCheck, ignoring...".to_owned()), + } +} + fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", @@ -562,23 +585,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let rustc = rustc.trim().to_owned(); if rustc.is_empty() { Err("`rustc` path is empty".to_string()) } else { Ok(rustc) } })?; - let llvm_filecheck = match run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ - which FileCheck-11 || \ - which FileCheck-12 || \ - which FileCheck-13 || \ - which FileCheck-14 || \ - which FileCheck", - ], - rust_dir, - Some(env), - ) { - Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), - Err(_) => { - eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); + let llvm_filecheck = match get_llvm_filecheck(env) { + Ok(l) => l, + Err(error) => { + eprintln!("{error}"); // FIXME: the test tests/run-make/no-builtins-attribute will fail if we cannot find // FileCheck. String::new() @@ -648,7 +658,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"--set", &"build.compiletest-allow-stage0=true", - &"tests/assembly-llvm/asm", + &"tests/assembly-gcc/asm", &"--compiletest-rustc-args", &rustc_args, ], @@ -921,6 +931,39 @@ fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { + println!("[TEST] stdarch"); + let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); + let mut env = env.clone(); + + // `config.setup` already baked `CG_RUSTFLAGS` into `RUSTFLAGS`, so append the lint-allow to + // `RUSTFLAGS` directly (which `run_cargo_command` also propagates to `RUSTDOCFLAGS`). + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert( + "RUSTFLAGS".to_string(), + format!("{rustflags} -Ainternal_features").trim().to_owned(), + ); + env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); + + let mut command: Vec<&dyn AsRef> = + vec![&"test", &"--manifest-path", &manifest_path, &"--"]; + for test_name in &args.test_args { + command.push(test_name); + } + run_cargo_command(&command, None, &env, args)?; + Ok(()) +} + +fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] alloc"); + let path = get_sysroot_dir().join("sysroot_src/library/alloctests"); + let _ = remove_dir_all(path.join("target")); + // FIXME(antoyo): run in release mode when we fix the failures. + run_cargo_command(&[&"test"], Some(&path), env, args)?; + Ok(()) +} + fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); @@ -1065,7 +1108,6 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< "//@ known-bug", "-Cllvm-args", "//~", - "thread", ] .iter() .any(|check| line.contains(check)) @@ -1548,6 +1590,60 @@ fn remove_files_callback(file_path: &str) -> impl Fn(&Path) -> Result Result<(), String> { + fn is_path_time_more_recent(ref_time: std::time::SystemTime, path: &str) -> bool { + std::fs::metadata(path) + .and_then(|metadata| metadata.modified()) + .is_ok_and(|time| ref_time < time) + } + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] cg_gcc assembly"); + let llvm_filecheck = get_llvm_filecheck(env)?; + + let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); + + // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. + let binary_file_path = "build_system/asm-tester/target/debug/asm-tester"; + let mut need_recompilation = true; + if let Ok(metadata) = std::fs::metadata(binary_file_path) + && let Ok(ref_time) = metadata.modified() + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.toml") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.lock") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/src/main.rs") + { + need_recompilation = false; + } + + if need_recompilation { + let build_asm_args: Vec<&dyn AsRef> = vec![ + &"cargo", + &"build", + &"--manifest-path", + &"build_system/asm-tester/Cargo.toml", + &"--target-dir", + &target_dir, + &"--", + ]; + run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(env))?; + } + + let mut test_asm_args: Vec<&dyn AsRef> = vec![ + &"build_system/asm-tester/target/debug/asm-tester", + &"--llvm-filecheck", + &llvm_filecheck, + ]; + for test_arg in &args.test_args { + test_asm_args.push(&"--filter"); + test_asm_args.push(test_arg); + } + test_asm_args.push(&"--"); + for arg in args.config_info.rustc_command_vec().into_iter().skip(1) { + test_asm_args.push(arg); + } + run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(env)) +} + fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; @@ -1559,6 +1655,7 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { cargo_tests(env, args)?; no_builtins_tests(env, args)?; test_rustc(env, args)?; + test_asm(env, args)?; Ok(()) } @@ -1580,7 +1677,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc)?; + args.config_info.setup(&mut env, args.use_system_gcc, true)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/compiler/rustc_codegen_gcc/build_system/src/todo.rs b/compiler/rustc_codegen_gcc/build_system/src/todo.rs new file mode 100644 index 0000000000000..5b89410844788 --- /dev/null +++ b/compiler/rustc_codegen_gcc/build_system/src/todo.rs @@ -0,0 +1,72 @@ +use std::ffi::OsStr; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +const EXTENSIONS: &[&str] = + &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; + +fn has_supported_extension(path: &Path) -> bool { + path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) +} + +fn list_tracked_files() -> Result, String> { + let output = Command::new("git") + .args(["ls-files", "-z"]) + .output() + .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("`git ls-files` failed: {stderr}")); + } + + let mut files = Vec::new(); + for entry in output.stdout.split(|b| *b == 0) { + if entry.is_empty() { + continue; + } + let path = std::str::from_utf8(entry).unwrap(); + files.push(PathBuf::from(path)); + } + + Ok(files) +} + +pub(crate) fn run() -> Result<(), String> { + let files = list_tracked_files()?; + let mut error_count = 0; + // Avoid embedding the task marker in source so greps only find real occurrences. + let todo_marker = "todo".to_ascii_uppercase(); + + for file in files { + if !has_supported_extension(&file) { + continue; + } + + let file_handle = + File::open(&file).map_err(|e| format!("Failed to open {}: {e}", file.display()))?; + let reader = BufReader::new(file_handle); + + for (i, line) in reader.lines().enumerate() { + let line = line.map_err(|e| format!("Failed to read {}: {e}", file.display()))?; + let trimmed = line.trim(); + if trimmed.contains(&todo_marker) { + eprintln!( + "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", + file.display(), + i + 1, + todo_marker + ); + error_count += 1; + } + } + } + + if error_count == 0 { + return Ok(()); + } + + Err(format!("found {} {}(s)", error_count, todo_marker)) +} diff --git a/compiler/rustc_codegen_gcc/build_system/src/utils.rs b/compiler/rustc_codegen_gcc/build_system/src/utils.rs index 112322f8688c1..4c67156a85fb2 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/utils.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/utils.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; +use std::io::{BufReader, Read}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus, Output}; +use std::process::{Command, ExitStatus, Output, Stdio}; fn exec_command( input: &[&dyn AsRef], @@ -47,7 +48,7 @@ pub(crate) fn get_command_inner( command } -fn check_exit_status( +pub(crate) fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, @@ -115,6 +116,30 @@ pub fn run_command_with_output( check_exit_status(input, cwd, exit_status, None, true) } +pub fn run_command_with_output_and_get_it( + input: &[&dyn AsRef], + cwd: Option<&Path>, +) -> Result<(ExitStatus, String), String> { + let mut child = get_command_inner(input, cwd, None) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| command_error(input, &cwd, e))?; + + let stderr = child.stderr.take().expect("Failed to capture stderr"); + let mut captured = String::new(); + BufReader::new(stderr).read_to_string(&mut captured).expect("failed to read stderr"); + + let status = child.wait().map_err(|e| command_error(input, &cwd, e))?; + #[cfg(unix)] + { + if let Some(signal) = status.signal() { + // In case the signal didn't kill the current process. + return Err(command_error(input, &cwd, format!("Process received signal {signal}"))); + } + } + Ok((status, captured)) +} + pub fn run_command_with_output_and_env( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -124,7 +149,6 @@ pub fn run_command_with_output_and_env( check_exit_status(input, cwd, exit_status, None, true) } -#[cfg(not(unix))] pub fn run_command_with_output_and_env_no_err( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -419,6 +443,34 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } +pub fn run_tool_and_install_it_if_not_present(cmd: &[&dyn AsRef]) -> Result<(), String> { + let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; + if exit_status.success() { + return Ok(()); + } + let mut iter = stderr.split('\n'); + if let Some(line) = iter.next() + && line.contains("is not installed for the toolchain") + && let Some(line) = iter.next() + && line.contains("run `rustup component add") + && let Some(cmd) = line.split('`').nth(1) + && let Some(tool_name) = cmd.rsplit(' ').next() + { + println!("`{tool_name}` is not installed for this toolchain, installing it..."); + // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but + // as long as it works... + let cmd = cmd.split(' ').collect::>(); + let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); + run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; + } else { + // If the component is installed, then it's something else. In this case we fail like we + // should have and let the user handles the error. + return check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true); + } + // We retry the command... + run_command_with_output(cmd, Some(Path::new("."))) +} + #[cfg(test)] mod tests { use super::*; diff --git a/compiler/rustc_codegen_gcc/doc/subtree.md b/compiler/rustc_codegen_gcc/doc/subtree.md index a81b6c9c74bdd..fcac399e46542 100644 --- a/compiler/rustc_codegen_gcc/doc/subtree.md +++ b/compiler/rustc_codegen_gcc/doc/subtree.md @@ -1,7 +1,7 @@ # git subtree sync `rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be -sync from time to time to ensure changes that happened on their side are also +synced from time to time to ensure changes that happened on their side are also included on our side. ### How to install a forked git-subtree @@ -41,6 +41,8 @@ cd ../rust git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +# Don't forget to update the `gcc` submodule to the same version as the +# one in `rustc_codegen_gcc/libgccjit.version`. git push # Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index 6e155f89ee5cc..ab841d51a7f53 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -6,7 +6,7 @@ )] #![no_core] #![allow(dead_code, internal_features, non_camel_case_types)] -#![rustfmt_skip] +#![cfg_attr(rustfmt, rustfmt_skip)] extern crate mini_core; diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 09e009700a80c..63eaf52ce9f01 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -146,12 +146,23 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } + // There are a few others `ArgAttribute` variants" + // + // * ArgAttribute::ReadOnly: `access(read_only())`, but it's only used for emitting + // warning, not for optimization. + // * ArgAttribute::NoUndef: No equivalent in GCC + // * ArgAttribute::Writable: `access(read_write())` or `access(write_only())`, but it's + // only used for emitting warning, not for optimization. + // * ArgAttribute::NoFree: No equivalent in GCC ty }; #[cfg(not(feature = "master"))] let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - for arg in self.args.iter() { + for (source_arg_index, arg) in self.args.iter().enumerate() { + #[cfg(not(feature = "master"))] + let _ = source_arg_index; + let arg_ty = match arg.mode { PassMode::Ignore => continue, PassMode::Pair(a, b) => { @@ -179,9 +190,31 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_attrs(ty, &cast.attrs, argument_tys.len()) } PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { - // This is a "byval" argument, so we don't apply the `restrict` attribute on it. - on_stack_param_indices.insert(argument_tys.len()); - arg.layout.gcc_type(cx) + let x86_interrupt_first_arg = { + #[cfg(feature = "master")] + { + source_arg_index == 0 + && matches!(self.conv, CanonAbi::Interrupt(InterruptKind::X86)) + } + #[cfg(not(feature = "master"))] + { + false + } + }; + + if x86_interrupt_first_arg { + // Rust lowers the first `x86-interrupt` argument as a byval stack slot. + // LLVM represents that as a pointer parameter with `byval`; GCC's + // interrupt attribute likewise requires a pointer-shaped first parameter. + // Do not add this parameter to `on_stack_param_indices`: that set is only + // needed when GCC represents a byval argument as a value parameter, while + // this parameter is already pointer-shaped. + cx.type_ptr_to(arg.layout.gcc_type(cx)) + } else { + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + on_stack_param_indices.insert(argument_tys.len()); + arg.layout.gcc_type(cx) + } } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) diff --git a/compiler/rustc_codegen_gcc/src/asm.rs b/compiler/rustc_codegen_gcc/src/asm.rs index e84cf54cb1147..75a48c217c49b 100644 --- a/compiler/rustc_codegen_gcc/src/asm.rs +++ b/compiler/rustc_codegen_gcc/src/asm.rs @@ -297,7 +297,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { out_place, }); - if !readwrite { + if readwrite { + self.llbb().add_assignment(None, tmp_var, in_value.immediate()); + } else { let out_gcc_idx = outputs.len() - 1; let constraint = Cow::Owned(out_gcc_idx.to_string()); @@ -363,7 +365,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = value.layout.gcc_type(self.cx); let reg_var = self.current_func().new_local(None, ty, "input_register"); reg_var.set_register_name(reg_name); - self.llbb().add_assignment(None, reg_var, value.immediate()); + // FIXME: We should remove this when switching to "untyped" pointers + let value = value.immediate(); + let value = if value.get_type() != ty { + self.context.new_cast(None, value, ty) + } else { + value + }; + self.llbb().add_assignment(None, reg_var, value); inputs.push(AsmInOperand { constraint: "r".into(), @@ -602,6 +611,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } + if !options.contains(InlineAsmOptions::NORETURN) + && let Some(dest) = dest + { + self.switch_to_block(dest); + } + // Write results to outputs. // // We need to do this because: diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 87c989031678d..41db5e83bdcc9 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -2,6 +2,8 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] +use rustc_abi::{CanonAbi, InterruptKind}; +#[cfg(feature = "master")] use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InstructionSetAttr; #[cfg(feature = "master")] @@ -9,6 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] use rustc_middle::mir::TerminatorKind; use rustc_middle::ty; +use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -84,12 +87,23 @@ fn inline_attr<'gcc, 'tcx>( } } +#[cfg(feature = "master")] +fn is_x86_interrupt<'tcx>(fn_abi: Option<&FnAbi<'tcx, ty::Ty<'tcx>>>) -> bool { + matches!( + fn_abi, + Some(fn_abi) if matches!(fn_abi.conv, CanonAbi::Interrupt(InterruptKind::X86)) + ) +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, #[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, + #[cfg_attr(not(feature = "master"), expect(unused_variables))] fn_abi: Option< + &FnAbi<'tcx, ty::Ty<'tcx>>, + >, ) { let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def); @@ -132,6 +146,11 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } + #[cfg(feature = "master")] + let x86_interrupt = is_x86_interrupt(fn_abi); + #[cfg(not(feature = "master"))] + let x86_interrupt = false; + let mut function_features = codegen_fn_attrs .target_features .iter() @@ -147,6 +166,13 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // Check if GCC requires the same. let mut global_features = cx.tcx.sess.global_backend_features.iter().map(|s| s.as_str()); function_features.extend(&mut global_features); + if x86_interrupt { + // GCC does not preserve SSE, MMX, or x87 state in interrupt handlers and rejects + // them whenever those instruction sets are enabled, even if the handler does not + // emit such instructions. Restrict the function to general registers so the + // interrupt attribute works with the default x86_64 target features. + function_features.push("general-regs-only"); + } let target_features = function_features .iter() .filter_map(|feature| { diff --git a/compiler/rustc_codegen_gcc/src/back/lto.rs b/compiler/rustc_codegen_gcc/src/back/lto.rs index b0de1ead56ed1..baf1fda02e258 100644 --- a/compiler/rustc_codegen_gcc/src/back/lto.rs +++ b/compiler/rustc_codegen_gcc/src/back/lto.rs @@ -20,6 +20,7 @@ use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use gccjit::OutputKind; use object::read::archive::ArchiveFile; @@ -29,9 +30,9 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter} use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; +use rustc_session::Session; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; @@ -103,8 +104,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -115,8 +116,8 @@ pub(crate) fn run_fat( /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( + sess, cgcx, - prof, dcx, modules, lto_data.upstream_modules, @@ -126,15 +127,15 @@ pub(crate) fn run_fat( } fn fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> CompiledModule { - let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = sess.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -184,17 +185,16 @@ fn fat_lto( // module and create a linker with it. let mut module: ModuleCodegen = match costliest_module { Some((_cost, i)) => in_memory.remove(i), - None => { - unimplemented!("Incremental"); - /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); - let (buffer, name) = serialized_modules.remove(0); - info!("no in-memory regular modules to choose from, parsing {:?}", name); - ModuleCodegen { - module_llvm: GccContext::parse(cgcx, &name, buffer.data(), dcx)?, - name: name.into_string().unwrap(), - kind: ModuleKind::Regular, - }*/ - } + None => ModuleCodegen::new_regular( + "lto_module".to_string(), + GccContext { + context: Arc::new(SyncContext::new(new_context(sess))), + relocation_model: sess.relocation_model(), + lto_supported: true, + lto_mode: LtoMode::None, + temp_dir: None, + }, + ), }; { info!("using {:?} as a base module", module.name); @@ -221,7 +221,8 @@ fn fat_lto( // We add the object files and save in should_combine_object_files that we should combine // them into a single object file when compiling later. for (bc_decoded, name) in serialized_modules { - let _timer = prof + let _timer = sess + .prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -259,7 +260,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - codegen(cgcx, prof, dcx, module, &cgcx.module_config) + codegen(cgcx, &sess.prof, dcx, module, &cgcx.module_config) } pub struct ModuleBuffer(PathBuf); diff --git a/compiler/rustc_codegen_gcc/src/back/write.rs b/compiler/rustc_codegen_gcc/src/back/write.rs index cf5514412f745..1f4fd8a314ad2 100644 --- a/compiler/rustc_codegen_gcc/src/back/write.rs +++ b/compiler/rustc_codegen_gcc/src/back/write.rs @@ -11,8 +11,8 @@ use rustc_log::tracing::debug; use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; -use crate::base::add_pic_option; use crate::diagnostics::CopyBitcode; +use crate::gcc_util::add_pic_option; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( @@ -60,9 +60,6 @@ pub(crate) fn codegen( let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { - // FIXME(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); - context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); context.add_command_line_option("-ffat-lto-objects"); diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 7cb734d523273..436a9e5227352 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; -use std::env; use std::sync::Arc; use std::time::Instant; @@ -19,7 +17,6 @@ use rustc_session::config::DebugInfo; use rustc_span::Symbol; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; -use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -144,41 +141,7 @@ pub fn compile_codegen_unit( ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(tcx); - - if tcx.sess.panic_strategy().unwinds() { - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); - } - - let disabled_features: HashSet<_> = tcx - .sess - .opts - .cg - .target_feature - .split(',') - .filter(|feature| feature.starts_with('-')) - .map(|string| &string[1..]) - .collect(); - - if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 { - // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for - // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. - // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. - context.add_command_line_option("-mavx"); - } - - for arg in &tcx.sess.opts.cg.llvm_args { - context.add_command_line_option(arg); - } - // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. - context.add_command_line_option("-fno-var-tracking-assignments"); - // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). - context.add_command_line_option("-fno-semantic-interposition"); - // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). - context.add_command_line_option("-fno-strict-aliasing"); - // NOTE: Rust relies on LLVM doing wrapping on overflow. - context.add_command_line_option("-fwrapv"); + let context = new_context(tcx.sess); // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from // replacing code patterns (like loops) with calls to builtins (like memset). @@ -191,64 +154,6 @@ pub fn compile_codegen_unit( context.add_command_line_option("-fno-tree-loop-distribute-patterns"); } - if let Some(model) = tcx.sess.code_model() { - use rustc_target::spec::CodeModel; - - context.add_command_line_option(match model { - CodeModel::Tiny => "-mcmodel=tiny", - CodeModel::Small => "-mcmodel=small", - CodeModel::Kernel => "-mcmodel=kernel", - CodeModel::Medium => "-mcmodel=medium", - CodeModel::Large => "-mcmodel=large", - }); - } - - add_pic_option(&context, tcx.sess.relocation_model()); - - let target_cpu = gcc_util::target_cpu(tcx.sess); - if target_cpu != "generic" { - context.add_command_line_option(format!("-march={}", target_cpu)); - } - - if tcx - .sess - .opts - .unstable_opts - .function_sections - .unwrap_or(tcx.sess.target.function_sections) - { - context.add_command_line_option("-ffunction-sections"); - context.add_command_line_option("-fdata-sections"); - } - - if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-vregs"); - } - if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-all"); - } - if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-tree-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-ipa-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { - context.set_dump_code_on_compile(true); - } - if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { - context.set_dump_initial_gimple(true); - } - if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { - context.set_dump_everything(true); - } - if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { - context.set_keep_intermediates(true); - } - if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { - context.add_driver_option("-v"); - } - // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); @@ -317,24 +222,3 @@ pub fn compile_codegen_unit( (module, cost) } - -pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { - match relocation_model { - rustc_target::spec::RelocModel::Static => { - context.add_command_line_option("-fno-pie"); - context.add_driver_option("-fno-pie"); - } - rustc_target::spec::RelocModel::Pic => { - context.add_command_line_option("-fPIC"); - // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // this module (compile_codegen_unit) requires add_command_line_option while the usage - // in the back::write module (codegen) requires add_driver_option. - context.add_driver_option("-fPIC"); - } - rustc_target::spec::RelocModel::Pie => { - context.add_command_line_option("-fPIE"); - context.add_driver_option("-fPIE"); - } - model => eprintln!("Unsupported relocation model: {:?}", model), - } -} diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs index 6de2827e63dee..a1eab8f448990 100644 --- a/compiler/rustc_codegen_gcc/src/builder.rs +++ b/compiler/rustc_codegen_gcc/src/builder.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, - UnaryOp, + BinaryOp, Block, CType, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, + Type, UnaryOp, }; use rustc_abi as abi; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; @@ -118,7 +118,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); - let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); + let return_value = self.new_temp(func, self.location, previous_value.get_type()); self.llbb().add_assignment(self.location, previous_var, previous_value); self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue()); @@ -389,29 +389,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let args = self.check_call("call", func, args); + let call = self.cx.context.new_call(self.location, func, &args); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); let void_type = self.context.new_type::<()>(); let current_func = self.block.get_function(); if return_type != void_type { - let result = current_func.new_local( - self.location, - return_type, - format!("returnValue{}", self.next_value_counter()), - ); - self.block.add_assignment( - self.location, - result, - self.cx.context.new_call(self.location, func, &args), - ); + let result = self.new_temp(current_func, self.location, return_type); + self.block.add_assignment(self.location, result, call); result.to_rvalue() } else { - self.block - .add_eval(self.location, self.cx.context.new_call(self.location, func, &args)); + self.block.add_eval(self.location, call); // Return dummy value when not having return value. self.context.new_rvalue_zero(self.isize_type) } @@ -424,6 +422,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let func_ptr_type = { let func_ptr_type = func_ptr.get_type(); @@ -448,6 +447,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + let call = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = gcc_func.get_return_type(); @@ -464,11 +469,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { args_adjusted, orig_args, ); - let result = current_func.new_local( - self.location, - return_value.get_type(), - format!("ptrReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_value.get_type()); self.block.add_assignment(self.location, result, return_value); result.to_rvalue() } else { @@ -490,8 +491,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.location, self.cx.context.new_call_through_ptr(self.location, func_ptr, &args), ); - // Return dummy value when not having return value. - self.context.new_rvalue_zero(self.isize_type) + // Return dummy value when not having return value, unless the intrinsic adapter + // needs to synthesize a non-void LLVM-level result from out-parameters. + llvm::adjust_intrinsic_return_value( + self, + self.context.new_rvalue_zero(self.isize_type), + &func_name, + &args, + args_adjusted, + orig_args, + ) } } @@ -506,11 +515,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let return_type = self.context.new_type::(); let current_func = self.block.get_function(); // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects. - let result = current_func.new_local( - self.location, - return_type, - format!("overflowReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_type); self.block.add_assignment( self.location, result, @@ -642,6 +647,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { default_block: Block<'gcc>, cases: impl ExactSizeIterator)>, ) { + // A switch with no cases is equivalent to an unconditional jump to the + // default block. Such a `SwitchInt` (one with only an `otherwise` target) + // is normally simplified into a `goto`, but `-Z mir-preserve-ub` keeps it, + // so it can reach here with e.g. the `bool` discriminant produced by a + // range-pattern comparison. `gcc_jit_block_end_with_switch` rejects a + // discriminant that is not of integer type, so emit a plain jump instead + // of a (pointless) switch. + if cases.len() == 0 { + self.block.end_with_jump(self.location, default_block); + return; + } + let mut gcc_cases = vec![]; let typ = self.val_ty(value); // FIXME(FractalFir): This is a workaround for a libgccjit limitation. @@ -1070,11 +1087,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. let deref = ptr.dereference(self.location).to_rvalue(); - let loaded_value = function.new_local( - self.location, - aligned_type, - format!("loadedValue{}", self.next_value_counter()), - ); + let loaded_value = self.new_temp(function, self.location, aligned_type); block.add_assignment(self.location, loaded_value, deref); loaded_value.to_rvalue() } @@ -1193,7 +1206,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var"); + let current = self.new_temp(self.llbb().get_function(), self.location, ptr_type); let current_val = current.to_rvalue(); self.assign(current, start); @@ -1567,7 +1580,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { mut else_val: RValue<'gcc>, ) -> RValue<'gcc> { let func = self.current_func(); - let variable = func.new_local(self.location, then_val.get_type(), "selectVar"); + let variable = self.new_temp(func, self.location, then_val.get_type()); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1589,8 +1602,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { variable.to_rvalue() } - fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { - unimplemented!(); + fn va_arg(&mut self, list: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + let va_list_type = self.context.new_c_type(CType::VaList); + let list = self.context.new_cast(self.location, list, va_list_type.make_pointer()); + self.context.new_va_arg(self.location, list, ty) } #[cfg(feature = "master")] @@ -1705,11 +1720,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self - .current_func() - .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") + .new_temp(self.current_func(), self.location, self.u8_type.make_pointer()) .to_rvalue(); - let value2 = - self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue(); + let value2 = self.new_temp(self.current_func(), self.location, self.i32_type).to_rvalue(); (value1, value2) } @@ -1772,7 +1785,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.current_func().new_local(self.location, self.bool_type, "success"); + let success_var = self.new_temp(self.current_func(), self.location, self.bool_type); self.llbb().add_assignment(self.location, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) @@ -1867,7 +1880,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn tail_call( &mut self, - _llty: Self::Type, + llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Value, @@ -2475,11 +2488,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.bitcast_if_needed(res, result_type) } + /// Create a temporary variable. + /// + /// GCC will use more stack space with a local variable than with a temporary variable in debug mode, + /// so in order to avoid having the stack probe test fail in CI, we avoid creating local variables for temporaries. + pub fn new_temp( + &self, + function: Function<'gcc>, + location: Option>, + typ: Type<'gcc>, + ) -> LValue<'gcc> { + #[cfg(feature = "master")] + { + function.new_temp(location, typ) + } + #[cfg(not(feature = "master"))] + { + function.new_local(location, typ, format!("temp{}", self.next_value_counter())) + } + } + // GCC doesn't like deeply nested expressions. // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested // expressions and GCC will use much less RAM. fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> { - let var = self.current_func().new_local(self.location, value.get_type(), "opResult"); + let var = self.new_temp(self.current_func(), self.location, value.get_type()); self.llbb().add_assignment(self.location, var, value); var.to_rvalue() } diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index 00f095ed54371..d3f412180da55 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -70,7 +70,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(sym, fn_abi); - attributes::from_fn_attrs(cx, func, instance); + attributes::from_fn_attrs(cx, func, instance, Some(fn_abi)); #[cfg(feature = "master")] { diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index e6acbc6625d44..8576dfe079163 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -171,29 +171,52 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { } // Wasm statics with custom link sections get special treatment as they - // go into custom sections of the wasm executable. - if self.tcx.sess.target.is_like_wasm { + // go into custom sections of the wasm executable. The exception to this + // is the `.init_array` section which are treated specially by the wasm linker. + if self.tcx.sess.target.is_like_wasm + && attrs + .link_section + .map(|link_section| !link_section.as_str().starts_with(".init_array")) + .unwrap_or(true) + { if let Some(_section) = attrs.link_section { unimplemented!(); } - } else { - // FIXME(antoyo): set link section. + } else if let Some(_section) = attrs.link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(_section.as_str())); } - if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) - || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - self.add_used_global(global.to_rvalue()); + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + self.add_used_global(global); + } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); + self.add_retained_global(global); } } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. - pub fn add_used_global(&mut self, _global: RValue<'gcc>) { - // FIXME(antoyo) + /// Need to have the `SHF_GNU_RETAIN` flag, so needs to use the `retain` attribute instead of + /// `used`. This is used by `#[used(linker)]`. + pub fn add_retained_global(&mut self, global: LValue<'gcc>) { + // We need to add the `used` C attribute in any case. + self.add_used_global(global); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Retain); + } + + /// This is used by `#[used(compiler)]` and `#[used]`. + pub fn add_used_global(&mut self, _global: LValue<'gcc>) { + #[cfg(feature = "master")] + _global.add_attribute(VarAttribute::Used); } + // No need to have the `SHF_GNU_RETAIN` flag, so `used` attribute is ok. #[cfg_attr(not(feature = "master"), expect(unused_variables))] pub fn add_used_function(&self, function: Function<'gcc>) { #[cfg(feature = "master")] diff --git a/compiler/rustc_codegen_gcc/src/declare.rs b/compiler/rustc_codegen_gcc/src/declare.rs index a9503574a03ed..32bb7c3aa349e 100644 --- a/compiler/rustc_codegen_gcc/src/declare.rs +++ b/compiler/rustc_codegen_gcc/src/declare.rs @@ -1,12 +1,12 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue}; +use gccjit::{FnAttribute, ToRValue, VarAttribute}; use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::abi::{FnAbiGcc, FnAbiGccExt}; +use crate::abi::FnAbiGccExt; use crate::context::CodegenCx; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -25,6 +25,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } global @@ -74,6 +77,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); @@ -111,22 +117,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { - let FnAbiGcc { - return_type, - arguments_type, - is_c_variadic, - on_stack_param_indices, - #[cfg(feature = "master")] - fn_attributes, - } = fn_abi.gcc_type(self); + let fn_abi_gcc = fn_abi.gcc_type(self); #[cfg(feature = "master")] let conv = fn_abi.gcc_cconv(self); #[cfg(not(feature = "master"))] let conv = None; - let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); - self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); + let func = declare_raw_fn( + self, + name, + conv, + fn_abi_gcc.return_type, + &fn_abi_gcc.arguments_type, + fn_abi_gcc.is_c_variadic, + ); + self.on_stack_function_params.borrow_mut().insert(func, fn_abi_gcc.on_stack_param_indices); #[cfg(feature = "master")] - for fn_attr in fn_attributes { + for fn_attr in fn_abi_gcc.fn_attributes { func.add_attribute(fn_attr); } func diff --git a/compiler/rustc_codegen_gcc/src/diagnostics.rs b/compiler/rustc_codegen_gcc/src/diagnostics.rs index de633d3bdde79..67723ebd2f30b 100644 --- a/compiler/rustc_codegen_gcc/src/diagnostics.rs +++ b/compiler/rustc_codegen_gcc/src/diagnostics.rs @@ -20,10 +20,6 @@ pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } -#[derive(Diagnostic)] -#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] -pub(crate) struct ExplicitTailCallsUnsupported; - #[derive(Diagnostic)] #[diag("asm contains a NUL byte")] pub(crate) struct NulBytesInAsm { diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 4b0fef32cac03..0628171e488b3 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -4,7 +4,7 @@ use std::env; use gccjit::Context; #[cfg(feature = "master")] -use gccjit::Context; +use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::config::NATIVE_CPU; diff --git a/compiler/rustc_codegen_gcc/src/int.rs b/compiler/rustc_codegen_gcc/src/int.rs index 021f05c666d46..4e4b911666143 100644 --- a/compiler/rustc_codegen_gcc/src/int.rs +++ b/compiler/rustc_codegen_gcc/src/int.rs @@ -457,7 +457,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // This algorithm is based on compiler-rt's __cmpti2: // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 - let result = self.current_func().new_local(self.location, self.int_type, "icmp_result"); + let result = self.new_temp(self.current_func(), self.location, self.int_type); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); @@ -636,9 +636,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { rhs = self.context.new_cast(self.location, rhs, unsigned_type); } } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + if !a_type.is_vector() { + let signed_type = a_type.to_signed(self.cx); + lhs = self.context.new_cast(self.location, lhs, signed_type); + rhs = self.context.new_cast(self.location, rhs, signed_type); + } + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) } @@ -902,7 +910,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } - // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? + // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/1a99c2aa295bb2d507fa0e67a3b5eef64fba92a0/libm/src/math/support/int_traits.rs#L485 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs index 3c1698df6dec2..1856c2468616d 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/archs.rs @@ -24,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "prefetch.ir" => "__builtin_arm_prefetch_ir", "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", @@ -53,6 +54,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "alignbyte" => "__builtin_amdgcn_alignbyte", "ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32", "ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32", + "asyncmark" => "__builtin_amdgcn_asyncmark", "buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1", "buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc", "buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol", @@ -270,6 +272,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fdot2c.f32.bf16" => "__builtin_amdgcn_fdot2c_f32_bf16", "flat.prefetch" => "__builtin_amdgcn_flat_prefetch", "fmul.legacy" => "__builtin_amdgcn_fmul_legacy", + "global.load.async.lds" => "__builtin_amdgcn_global_load_async_lds", "global.load.async.to.lds.b128" => { "__builtin_amdgcn_global_load_async_to_lds_b128" } @@ -361,11 +364,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4", "perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4", "perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4", - "permlane.bcast" => "__builtin_amdgcn_permlane_bcast", - "permlane.down" => "__builtin_amdgcn_permlane_down", "permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen", - "permlane.up" => "__builtin_amdgcn_permlane_up", - "permlane.xor" => "__builtin_amdgcn_permlane_xor", "permlane16.var" => "__builtin_amdgcn_permlane16_var", "permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16", @@ -375,6 +374,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "prng.b32" => "__builtin_amdgcn_prng_b32", "qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "queue.ptr" => "__builtin_amdgcn_queue_ptr", + "raw.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_raw_ptr_buffer_load_async_lds" + } "raw.ptr.buffer.load.lds" => "__builtin_amdgcn_raw_ptr_buffer_load_lds", "rcp.legacy" => "__builtin_amdgcn_rcp_legacy", "rsq.legacy" => "__builtin_amdgcn_rsq_legacy", @@ -386,6 +388,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", "s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", "s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", + "s.bitreplicate" => "__builtin_amdgcn_s_bitreplicate", "s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data", "s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier", "s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", @@ -412,6 +415,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.ttracedata" => "__builtin_amdgcn_s_ttracedata", "s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "s.wait.asynccnt" => "__builtin_amdgcn_s_wait_asynccnt", + "s.wait.event" => "__builtin_amdgcn_s_wait_event", "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", @@ -462,16 +466,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "smfmac.i32.16x16x64.i8" => "__builtin_amdgcn_smfmac_i32_16x16x64_i8", "smfmac.i32.32x32x32.i8" => "__builtin_amdgcn_smfmac_i32_32x32x32_i8", "smfmac.i32.32x32x64.i8" => "__builtin_amdgcn_smfmac_i32_32x32x64_i8", + "struct.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_struct_ptr_buffer_load_async_lds" + } "struct.ptr.buffer.load.lds" => "__builtin_amdgcn_struct_ptr_buffer_load_lds", "sudot4" => "__builtin_amdgcn_sudot4", "sudot8" => "__builtin_amdgcn_sudot8", "tensor.load.to.lds" => "__builtin_amdgcn_tensor_load_to_lds", - "tensor.load.to.lds.d2" => "__builtin_amdgcn_tensor_load_to_lds_d2", "tensor.store.from.lds" => "__builtin_amdgcn_tensor_store_from_lds", - "tensor.store.from.lds.d2" => "__builtin_amdgcn_tensor_store_from_lds_d2", "udot2" => "__builtin_amdgcn_udot2", "udot4" => "__builtin_amdgcn_udot4", "udot8" => "__builtin_amdgcn_udot8", + "wait.asyncmark" => "__builtin_amdgcn_wait_asyncmark", "wave.barrier" => "__builtin_amdgcn_wave_barrier", "wavefrontsize" => "__builtin_amdgcn_wavefrontsize", "workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", @@ -4844,7 +4850,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.ftz.sat.f16" => "__nvvm_add_rn_ftz_sat_f16", + "add.rn.ftz.sat.v2f16" => "__nvvm_add_rn_ftz_sat_v2f16", "add.rn.sat.f" => "__nvvm_add_rn_sat_f", + "add.rn.sat.f16" => "__nvvm_add_rn_sat_f16", + "add.rn.sat.v2f16" => "__nvvm_add_rn_sat_v2f16", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", @@ -5063,18 +5073,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", "fma.rn.f" => "__nvvm_fma_rn_f", - "fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", - "fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", - "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", - "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", - "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", - "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", @@ -5195,6 +5197,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "mul.rn.d" => "__nvvm_mul_rn_d", "mul.rn.f" => "__nvvm_mul_rn_f", "mul.rn.ftz.f" => "__nvvm_mul_rn_ftz_f", + "mul.rn.ftz.sat.f16" => "__nvvm_mul_rn_ftz_sat_f16", + "mul.rn.ftz.sat.v2f16" => "__nvvm_mul_rn_ftz_sat_v2f16", + "mul.rn.sat.f16" => "__nvvm_mul_rn_sat_f16", + "mul.rn.sat.v2f16" => "__nvvm_mul_rn_sat_v2f16", "mul.rp.d" => "__nvvm_mul_rp_d", "mul.rp.f" => "__nvvm_mul_rp_f", "mul.rp.ftz.f" => "__nvvm_mul_rp_ftz_f", @@ -5827,8 +5833,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vmuleuh" => "__builtin_altivec_vmuleuh", "altivec.vmuleuw" => "__builtin_altivec_vmuleuw", "altivec.vmulhsd" => "__builtin_altivec_vmulhsd", + "altivec.vmulhsh" => "__builtin_altivec_vmulhsh", "altivec.vmulhsw" => "__builtin_altivec_vmulhsw", "altivec.vmulhud" => "__builtin_altivec_vmulhud", + "altivec.vmulhuh" => "__builtin_altivec_vmulhuh", "altivec.vmulhuw" => "__builtin_altivec_vmulhuw", "altivec.vmulosb" => "__builtin_altivec_vmulosb", "altivec.vmulosd" => "__builtin_altivec_vmulosd", @@ -5912,22 +5920,45 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vsum4shs" => "__builtin_altivec_vsum4shs", "altivec.vsum4ubs" => "__builtin_altivec_vsum4ubs", "altivec.vsumsws" => "__builtin_altivec_vsumsws", + "altivec.vucmprhb" => "__builtin_altivec_vucmprhb", + "altivec.vucmprhh" => "__builtin_altivec_vucmprhh", + "altivec.vucmprhn" => "__builtin_altivec_vucmprhn", + "altivec.vucmprlb" => "__builtin_altivec_vucmprlb", + "altivec.vucmprlh" => "__builtin_altivec_vucmprlh", + "altivec.vucmprln" => "__builtin_altivec_vucmprln", "altivec.vupkhpx" => "__builtin_altivec_vupkhpx", "altivec.vupkhsb" => "__builtin_altivec_vupkhsb", "altivec.vupkhsh" => "__builtin_altivec_vupkhsh", + "altivec.vupkhsntob" => "__builtin_altivec_vupkhsntob", "altivec.vupkhsw" => "__builtin_altivec_vupkhsw", + "altivec.vupkint4tobf16" => "__builtin_altivec_vupkint4tobf16", + "altivec.vupkint4tofp32" => "__builtin_altivec_vupkint4tofp32", + "altivec.vupkint8tobf16" => "__builtin_altivec_vupkint8tobf16", + "altivec.vupkint8tofp32" => "__builtin_altivec_vupkint8tofp32", "altivec.vupklpx" => "__builtin_altivec_vupklpx", "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", + "altivec.vupklsntob" => "__builtin_altivec_vupklsntob", "altivec.vupklsw" => "__builtin_altivec_vupklsw", "amo.ldat" => "__builtin_amo_ldat", + "amo.ldat.cond" => "__builtin_amo_ldat_cond", + "amo.ldat.csne" => "__builtin_amo_ldat_csne", "amo.lwat" => "__builtin_amo_lwat", + "amo.lwat.cond" => "__builtin_amo_lwat_cond", + "amo.lwat.csne" => "__builtin_amo_lwat_csne", + "amo.stdat" => "__builtin_amo_stdat", + "amo.stwat" => "__builtin_amo_stwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", "bcdsetsign" => "__builtin_ppc_bcdsetsign", + "bcdshift" => "__builtin_ppc_bcdshift", + "bcdshiftround" => "__builtin_ppc_bcdshiftround", "bcdsub" => "__builtin_ppc_bcdsub", "bcdsub.p" => "__builtin_ppc_bcdsub_p", + "bcdtruncate" => "__builtin_ppc_bcdtruncate", + "bcdunsignedshift" => "__builtin_ppc_bcdunsignedshift", + "bcdunsignedtruncate" => "__builtin_ppc_bcdunsignedtruncate", "bpermd" => "__builtin_bpermd", "cbcdtd" => "__builtin_cbcdtd", "cbcdtdd" => "__builtin_ppc_cbcdtd", @@ -6126,6 +6157,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", + "xsaddaddsuqm" => "__builtin_xsaddaddsuqm", + "xsaddadduqm" => "__builtin_xsaddadduqm", + "xsaddsubsuqm" => "__builtin_xsaddsubsuqm", + "xsaddsubuqm" => "__builtin_xsaddsubuqm", + "xsmerge2t1uqm" => "__builtin_xsmerge2t1uqm", + "xsmerge2t2uqm" => "__builtin_xsmerge2t2uqm", + "xsmerge2t3uqm" => "__builtin_xsmerge2t3uqm", + "xsmerge3t1uqm" => "__builtin_xsmerge3t1uqm", + "xsrebase2t1uqm" => "__builtin_xsrebase2t1uqm", + "xsrebase2t2uqm" => "__builtin_xsrebase2t2uqm", + "xsrebase2t3uqm" => "__builtin_xsrebase2t3uqm", + "xsrebase2t4uqm" => "__builtin_xsrebase2t4uqm", + "xsrebase3t1uqm" => "__builtin_xsrebase3t1uqm", + "xsrebase3t2uqm" => "__builtin_xsrebase3t2uqm", + "xsrebase3t3uqm" => "__builtin_xsrebase3t3uqm", + "xxmulmul" => "__builtin_xxmulmul", + "xxmulmulhiadd" => "__builtin_xxmulmulhiadd", + "xxmulmulloadd" => "__builtin_xxmulmulloadd", + "xxssumudm" => "__builtin_xxssumudm", + "xxssumudmc" => "__builtin_xxssumudmc", + "xxssumudmcext" => "__builtin_xxssumudmcext", "zoned2packed" => "__builtin_ppc_zoned2packed", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } @@ -6388,13 +6440,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { // spv "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", + "subgroup.ballot" => "__builtin_spirv_subgroup_ballot", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { "__builtin_spirv_subgroup_local_invocation_id" } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", - "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -8661,10 +8713,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bmi.bextr.64" => "__builtin_ia32_bextr_u64", "bmi.bzhi.32" => "__builtin_ia32_bzhi_si", "bmi.bzhi.64" => "__builtin_ia32_bzhi_di", - "bmi.pdep.32" => "__builtin_ia32_pdep_si", - "bmi.pdep.64" => "__builtin_ia32_pdep_di", - "bmi.pext.32" => "__builtin_ia32_pext_si", - "bmi.pext.64" => "__builtin_ia32_pext_di", "cldemote" => "__builtin_ia32_cldemote", "clflushopt" => "__builtin_ia32_clflushopt", "clrssbsy" => "__builtin_ia32_clrssbsy", diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs index f3134edb72cb9..ef381715c1ea2 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/llvm.rs @@ -475,6 +475,26 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(variable.get_address(None)); args = new_args.into(); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let old_args = args.to_vec(); + let mut new_args = vec![]; + let arg1_type = gcc_func.get_param_type(0); + let first_mask = + builder.current_func().new_local(None, arg1_type, "return_2intersect_arg1"); + let arg2_type = gcc_func.get_param_type(1); + let second_mask = + builder.current_func().new_local(None, arg2_type, "return_2intersect_arg2"); + new_args.push(first_mask.get_address(None)); + new_args.push(second_mask.get_address(None)); + new_args.push(old_args[0]); + new_args.push(old_args[1]); + args = new_args.into(); + } "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask" | "__builtin_ia32_vpermt2varqi128_mask" @@ -486,6 +506,23 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } + "__builtin_ia32_fpclassph128_mask" + | "__builtin_ia32_fpclassph256_mask" + | "__builtin_ia32_fpclassph512_mask" + | "__builtin_ia32_fpclasspd128_mask" + | "__builtin_ia32_fpclassps128_mask" + | "__builtin_ia32_fpclasspd256_mask" + | "__builtin_ia32_fpclassps256_mask" + | "__builtin_ia32_fpclasspd512_mask" + | "__builtin_ia32_fpclassps512_mask" + | "__builtin_ia32_vpshufbitqmb128_mask" + | "__builtin_ia32_vpshufbitqmb256_mask" + | "__builtin_ia32_vpshufbitqmb512_mask" => { + let new_args = args.to_vec(); + let arg3_type = gcc_func.get_param_type(2); + let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); + args = vec![new_args[0], new_args[1], minus_one].into(); + } "__builtin_ia32_xrstor" | "__builtin_ia32_xrstor64" | "__builtin_ia32_xsavec" @@ -837,7 +874,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( "__builtin_ia32_rdrand64_step" => { let random_number = args[0].dereference(None).to_rvalue(); let success_variable = - builder.current_func().new_local(None, return_value.get_type(), "success"); + builder.new_temp(builder.current_func(), None, return_value.get_type()); builder.llbb().add_assignment(None, success_variable, return_value); let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); @@ -851,6 +888,25 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( &[random_number, success_variable.to_rvalue()], ); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let first_mask = args[0].dereference(None).to_rvalue(); + let second_mask = args[1].dereference(None).to_rvalue(); + let field1 = builder.context.new_field(None, first_mask.get_type(), "first_mask"); + let field2 = builder.context.new_field(None, second_mask.get_type(), "second_mask"); + let struct_type = + builder.context.new_struct_type(None, "vp2intersect_result", &[field1, field2]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[first_mask, second_mask], + ); + } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); @@ -1179,6 +1235,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", "llvm.x86.avx512.mask.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", "llvm.x86.avx512.mask.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", + "llvm.x86.avx512.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", + "llvm.x86.avx512.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", + "llvm.x86.avx512.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", "llvm.x86.avx512.mask.ucmp.w.512" => "__builtin_ia32_ucmpw512_mask", "llvm.x86.avx512.mask.ucmp.w.256" => "__builtin_ia32_ucmpw256_mask", "llvm.x86.avx512.mask.ucmp.w.128" => "__builtin_ia32_ucmpw128_mask", @@ -1336,11 +1395,20 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf", + "llvm.x86.vcvtneps2bf16128" => "__builtin_ia32_cvtneps2bf16_v4sf", + "llvm.x86.vcvtneps2bf16256" => "__builtin_ia32_cvtneps2bf16_v8sf", + "llvm.x86.avx512bf16.mask.cvtneps2bf16.128" => "__builtin_ia32_cvtneps2bf16_v4sf_mask", "llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf", "llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf", "llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf", "llvm.x86.avx512bf16.dpbf16ps.256" => "__builtin_ia32_dpbf16ps_v8sf", "llvm.x86.avx512bf16.dpbf16ps.512" => "__builtin_ia32_dpbf16ps_v16sf", + "llvm.x86.avx512.vp2intersect.d.128" => "__builtin_ia32_2intersectd128", + "llvm.x86.avx512.vp2intersect.q.128" => "__builtin_ia32_2intersectq128", + "llvm.x86.avx512.vp2intersect.d.256" => "__builtin_ia32_2intersectd256", + "llvm.x86.avx512.vp2intersect.q.256" => "__builtin_ia32_2intersectq256", + "llvm.x86.avx512.vp2intersect.d.512" => "__builtin_ia32_2intersectd512", + "llvm.x86.avx512.vp2intersect.q.512" => "__builtin_ia32_2intersectq512", "llvm.x86.pclmulqdq.512" => "__builtin_ia32_vpclmulqdq_v8di", "llvm.x86.pclmulqdq.256" => "__builtin_ia32_vpclmulqdq_v4di", "llvm.x86.avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", @@ -1574,38 +1642,79 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", + "llvm.x86.avx512fp16.fpclass.ph.128" => "__builtin_ia32_fpclassph128_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.128" => "__builtin_ia32_cmpph128_mask", + "llvm.x86.avx512fp16.fpclass.ph.256" => "__builtin_ia32_fpclassph256_mask", + "llvm.x86.avx512fp16.fpclass.ph.512" => "__builtin_ia32_fpclassph512_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.256" => "__builtin_ia32_cmpph256_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.512" => "__builtin_ia32_cmpph512_mask_round", + "llvm.x86.avx512.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "llvm.x86.avx512.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "llvm.x86.avx512.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.sttilecfg" => "__builtin_trap", "llvm.x86.tileloadd64" => "__builtin_trap", + "llvm.x86.tileloadd64.internal" => "__builtin_trap", "llvm.x86.tilerelease" => "__builtin_trap", "llvm.x86.tilestored64" => "__builtin_trap", + "llvm.x86.tilestored64.internal" => "__builtin_trap", "llvm.x86.tileloaddrs64" => "__builtin_trap", + "llvm.x86.tileloaddrs64.internal" => "__builtin_trap", "llvm.x86.tileloaddt164" => "__builtin_trap", + "llvm.x86.tileloaddt164.internal" => "__builtin_trap", "llvm.x86.tileloaddrst164" => "__builtin_trap", + "llvm.x86.tileloaddrst164.internal" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", + "llvm.x86.tilezero.internal" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", + "llvm.x86.tilemovrow.internal" => "__builtin_trap", "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", + "llvm.x86.tdpbhf8ps.internal" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", + "llvm.x86.tdphbf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", + "llvm.x86.tdpbf8ps.internal" => "__builtin_trap", "llvm.x86.tdphf8ps" => "__builtin_trap", + "llvm.x86.tdphf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf16ps" => "__builtin_trap", + "llvm.x86.tdpbf16ps.internal" => "__builtin_trap", "llvm.x86.tdpbssd" => "__builtin_trap", + "llvm.x86.tdpbssd.internal" => "__builtin_trap", "llvm.x86.tdpbsud" => "__builtin_trap", + "llvm.x86.tdpbsud.internal" => "__builtin_trap", "llvm.x86.tdpbusd" => "__builtin_trap", + "llvm.x86.tdpbusd.internal" => "__builtin_trap", "llvm.x86.tdpbuud" => "__builtin_trap", + "llvm.x86.tdpbuud.internal" => "__builtin_trap", "llvm.x86.tdpfp16ps" => "__builtin_trap", + "llvm.x86.tdpfp16ps.internal" => "__builtin_trap", "llvm.x86.tmmultf32ps" => "__builtin_trap", + "llvm.x86.tmmultf32ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phh" => "__builtin_trap", + "llvm.x86.tcvtrowps2phh.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", + "llvm.x86.tcvtrowps2phl.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", + "llvm.x86.tcvtrowd2ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => map_arch_intrinsic(name), diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 0a24519a8091e..4d2590ac81e41 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -81,7 +81,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", - sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -180,14 +179,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let simple = get_simple_intrinsic(self, name); let value = match name { - _ if simple.is_some() => { - let func = simple.expect("simple intrinsic function"); - self.cx.context.new_call( - self.location, - func, - &args.iter().map(|arg| arg.immediate()).collect::>(), - ) - } + _ if let Some(func) = simple => self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ), // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { @@ -322,7 +318,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } sym::va_arg => { - unimplemented!(); + let va_list = args[0].immediate(); + let gcc_type = self.immediate_backend_type(result.layout); + self.va_arg(va_list, gcc_type) } sym::volatile_load | sym::unaligned_volatile_load => { @@ -611,7 +609,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); - crate::attributes::from_fn_attrs(self, func, instance); + crate::attributes::from_fn_attrs(self, func, instance, None); func }; @@ -701,8 +699,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, _va_list: RValue<'gcc>) { - unimplemented!(); + fn va_start(&mut self, va_list: RValue<'gcc>) { + let func = self.context.get_builtin_function("__builtin_va_start"); + + let va_list_type = self.context.new_c_type(CType::VaList); + let va_list = self.context.new_cast(self.location, va_list, va_list_type.make_pointer()); + + // Pre-C23 requires that the last "normal" argument was passed to va_start. + // Just pass 0, this appears to be handled correctly. + let last_normal_arg = self.context.new_rvalue_from_int(self.int_type, 0); + + let call = self.context.new_call(self.location, func, &[va_list, last_normal_arg]); + self.block.add_eval(self.location, call); } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { @@ -960,7 +968,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let else_block = func.new_block("else"); let after_block = func.new_block("after"); - let result = func.new_local(None, self.u32_type, "zeros"); + let result = self.new_temp(func, None, self.u32_type); let zero = self.cx.gcc_zero(arg.get_type()); let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); @@ -1041,7 +1049,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // else call it on the 64 high bits and add 64. In the else case, 64 high bits can't be 0 // because arg is not 0. - let result = self.current_func().new_local(None, result_type, "count_zeroes_results"); + let result = self.new_temp(self.current_func(), None, result_type); let cz_then_block = self.current_func().new_block("cz_then"); let cz_else_block = self.current_func().new_block("cz_else"); @@ -1156,8 +1164,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let loop_tail = func.new_block("tail"); let counter_type = self.int_type; - let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); - let val = self.current_func().new_local(None, value_type, "popcount_value"); + let counter = self.new_temp(self.current_func(), None, counter_type); + let val = self.new_temp(self.current_func(), None, value_type); let zero = self.gcc_zero(counter_type); self.llbb().add_assignment(self.location, counter, zero); self.llbb().add_assignment(self.location, val, value); diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs b/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs index 8d3e3487b5cb4..1aac52c28d220 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/old_archs.rs @@ -1240,6 +1240,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "bmi.pdep.32" => "__builtin_ia32_pdep_si", + "bmi.pdep.64" => "__builtin_ia32_pdep_di", + "bmi.pext.32" => "__builtin_ia32_pext_si", + "bmi.pext.64" => "__builtin_ia32_pext_di", "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 0784823c27b9e..695bca1d69ec1 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -74,9 +74,9 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::Arc; -use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] -use gccjit::{TargetInfo, Version}; +use gccjit::TargetInfo; +use gccjit::{CType, Context, OptimizationLevel}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ @@ -292,20 +292,6 @@ impl CodegenBackend for GccCodegenBackend { fn target_config(&self, sess: &EarlySession) -> TargetConfig { target_config(sess, &self.config().target_info) } - #[cfg(feature = "master")] - { - context.set_special_chars_allowed_in_func_names("$.*"); - let version = Version::get(); - let version = format!("{}.{}.{}", version.major, version.minor, version.patch); - context.set_output_ident(&format!( - "rustc version {} with libgccjit {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - version, - )); - } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); - context } impl ExtraBackendMethods for GccCodegenBackend { @@ -318,7 +304,7 @@ impl ExtraBackendMethods for GccCodegenBackend { methods: &[AllocatorMethod], ) -> Self::Module { let mut mods = GccContext { - context: Arc::new(SyncContext::new(new_context(tcx))), + context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, lto_supported: self.config().lto_supported, @@ -411,7 +397,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(sess, cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index 014a7ff90536d..d8170fbb085a7 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,3 +1,4 @@ +use gccjit::Function; #[cfg(feature = "master")] use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; @@ -22,7 +23,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { def_id: DefId, linkage: Linkage, visibility: Visibility, - symbol_name: &str, + global_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); @@ -73,7 +74,6 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] self.add_static_aliases(gcc_type, global_name, attrs, &attrs.foreign_item_symbol_aliases); - // FIXME(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); } @@ -186,10 +186,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ) -> Function<'gcc> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); - let decl = self.declare_fn(symbol_name, fn_abi); - //let attrs = self.tcx.codegen_instance_attrs(instance.def); + let fn_decl = self.declare_fn(symbol_name, fn_abi); - attributes::from_fn_attrs(self, decl, instance); + attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); #[cfg(feature = "master")] if base::linkage_needs_weak_attribute(linkage) { @@ -202,17 +201,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // don't want the symbols to get exported. if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + fn_decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else if visibility != Visibility::Default { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + } + + #[cfg(feature = "master")] + if let Some(section) = _attrs.link_section { + fn_decl.add_attribute(FnAttribute::Section(section.as_str())); } - // FIXME(antoyo): call set_link_section() to allow initializing argc/argv. // FIXME(antoyo): set unique comdat. // FIXME(antoyo): use inline attribute from there in linkage.set() above. + // FIXME: Should we handle dso? - self.functions.borrow_mut().insert(symbol_name.to_string(), decl); - self.function_instances.borrow_mut().insert(instance, decl); + fn_decl } } diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 45828ce3e92b8..55b37ee89b63f 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use std::mem::discriminant; #[cfg(feature = "master")] -use gccjit::CType; +use gccjit::{CType, TypeAttribute}; use gccjit::{RValue, Struct, Type}; use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; @@ -232,7 +232,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { if self.supports_f16_type { return self.context.new_c_type(CType::Float16); } - bug!("unsupported float width 16") + self.u16_type } fn type_f32(&self) -> Type<'gcc> { diff --git a/compiler/rustc_codegen_gcc/tests/asm/asm/comments.rs b/compiler/rustc_codegen_gcc/tests/asm/asm/comments.rs new file mode 100644 index 0000000000000..603bb014930c4 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/asm/asm/comments.rs @@ -0,0 +1,12 @@ +//@ assembly-output: emit-asm +//@ only-x86_64 +// Check that comments in assembly get passed + +#![crate_type = "lib"] + +// CHECK-LABEL: "test_comments": +#[no_mangle] +pub fn test_comments() { + // CHECK: example comment + unsafe { core::arch::asm!("nop // example comment") }; +} diff --git a/compiler/rustc_codegen_gcc/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/compiler/rustc_codegen_gcc/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs new file mode 100644 index 0000000000000..81ee9b13b4eca --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full +//@ assembly-output: emit-asm +//@ needs-asm-support +//@ only-x86_64 + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", +// meaning "no prologue whatsoever, no, really, not one instruction." +// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection, +// works by using an instruction for each possible landing site, +// and LLVM implements this via making sure of that. +#[no_mangle] +#[unsafe(naked)] +pub extern "sysv64" fn will_halt() -> ! { + // CHECK-NOT: endbr{{32|64}} + // CHECK: hlt + naked_asm!("hlt") +} + +// what about aarch64? +// "branch-protection"=false diff --git a/compiler/rustc_codegen_gcc/tests/asm/panic-no-unwind-no-uwtable.rs b/compiler/rustc_codegen_gcc/tests/asm/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..b51b173e9616e --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/asm/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3 + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} diff --git a/compiler/rustc_codegen_gcc/tests/asm/used.rs b/compiler/rustc_codegen_gcc/tests/asm/used.rs new file mode 100644 index 0000000000000..deb0c69dc48fa --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/asm/used.rs @@ -0,0 +1,14 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu + +#![feature(used_with_arg)] +#![crate_type = "lib"] + +// CHECK: .section .rodata.X,"a" +#[used(compiler)] +#[no_mangle] +pub static X: u32 = 12; +// CHECK: .section .rodata.Y,"aR" +#[used(linker)] +#[no_mangle] +pub static Y: u32 = 12; diff --git a/compiler/rustc_codegen_gcc/tests/asm/x86_64-sse_crc.rs b/compiler/rustc_codegen_gcc/tests/asm/x86_64-sse_crc.rs new file mode 100644 index 0000000000000..bde58955a2146 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/asm/x86_64-sse_crc.rs @@ -0,0 +1,12 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 + +// CHECK-LABEL: banana +// CHECK: crc32 +#[no_mangle] +pub unsafe fn banana(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} diff --git a/compiler/rustc_codegen_gcc/tests/compile/x86_interrupt_first_arg_byval.rs b/compiler/rustc_codegen_gcc/tests/compile/x86_interrupt_first_arg_byval.rs new file mode 100644 index 0000000000000..4b6bbd48f7ad5 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/compile/x86_interrupt_first_arg_byval.rs @@ -0,0 +1,16 @@ +// Compiler: + +// Test that `x86-interrupt` functions whose first argument is passed by value +// emit pointer-shaped GCC parameters and compile with interrupt-safe target features. + +#![feature(abi_x86_interrupt)] +#![crate_type = "lib"] + +#[repr(C)] +pub struct Frame { + ip: u64, +} + +pub extern "x86-interrupt" fn scalar(_a: i64) {} + +pub extern "x86-interrupt" fn aggregate(_frame: Frame) {} diff --git a/compiler/rustc_codegen_gcc/tests/cpuid.def b/compiler/rustc_codegen_gcc/tests/cpuid.def new file mode 100644 index 0000000000000..05fe8e94a8282 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/cpuid.def @@ -0,0 +1,27 @@ +# Input => Output +# EAX ECX => EAX EBX ECX EDX +00000000 ******** => 00000024 756e6547 6c65746e 49656e69 #Processor ID and Manufacturer +00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff +00000007 00000000 => 00000002 f3bfbfbf bac05ffe 03d54130 #Extended Features +00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e +0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 +0000000d 00000001 => 0000001f 00000240 00000100 00000000 #Supervisor State +0000000d 00000002 => 00000100 00000240 00000000 00000000 +0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks +0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh +0000000d 00000007 => 00000400 00000680 00000000 00000000 #zmm +0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig +0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles +0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX +00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker +0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile +0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 +0000001e 00000000 => 00000001 00004010 00000000 00000000 #AMX Tmul +0000001e 00000001 => 000001ff 00000000 00000000 00000000 +00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 +00000024 00000001 => 00000000 00000000 00000004 00000000 +80000000 ******** => 80000004 00000000 00000000 00000000 +80000001 ******** => 00000000 00000000 00000121 2c100000 +80000002 ******** => 00000000 00000000 00000000 00000000 +80000003 ******** => 00000000 00000000 00000000 00000000 +80000004 ******** => 00000000 00000000 00000000 00000000 diff --git a/compiler/rustc_codegen_gcc/tests/lang_tests.rs b/compiler/rustc_codegen_gcc/tests/lang_tests.rs index 9c4708274280c..7ec0ab877b025 100644 --- a/compiler/rustc_codegen_gcc/tests/lang_tests.rs +++ b/compiler/rustc_codegen_gcc/tests/lang_tests.rs @@ -240,6 +240,16 @@ fn build_test_runner( } } + // Extra flags passed at run time (as opposed to the compile-time + // `TEST_FLAGS`). This lets a single test opt into flags like + // `-Zmir-preserve-ub` via an `ignore-if` directive that checks + // whether `CARGO_TEST_FLAGS` is set. + if let Ok(flags) = std::env::var("CARGO_TEST_FLAGS") { + for flag in flags.split_whitespace() { + compiler_args.push(flag.into()); + } + } + if build_mode.is_debug() { compiler_args .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); @@ -270,7 +280,13 @@ fn compile_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) "lang compile", "tests/compile", TestMode::Compile, - &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], + &[ + "simd-ffi.rs", + "asm_nul_byte.rs", + "global_asm_nul_byte.rs", + "naked_asm_nul_byte.rs", + "x86_interrupt_first_arg_byval.rs", + ], ); } diff --git a/compiler/rustc_codegen_gcc/tests/run/asm.rs b/compiler/rustc_codegen_gcc/tests/run/asm.rs index 01775c92ffc8a..42141c671b596 100644 --- a/compiler/rustc_codegen_gcc/tests/run/asm.rs +++ b/compiler/rustc_codegen_gcc/tests/run/asm.rs @@ -3,6 +3,8 @@ // Run-time: // status: 0 +#![feature(asm_goto_with_outputs)] + #[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; @@ -32,6 +34,20 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } +#[cfg(target_arch = "x86_64")] +#[unsafe(no_mangle)] +pub fn asm_goto_test(mut a: i16) -> i16 { + unsafe { + std::arch::asm!( + "jmp {op}", + inout("eax") a, + op = label { a = 7; }, + options(nostack,nomem) + ); + a + } +} + #[cfg(target_arch = "x86_64")] fn asm() { unsafe { @@ -190,6 +206,14 @@ fn asm() { } assert_eq!((x, y), (8, 8)); + // Regression test for + // typed pointer inputs to explicit registers need a cast. + let mut x = 123_i32; + unsafe { + asm!("", in("rdi") &mut x, options(nostack, preserves_flags)); + } + assert_eq!(x, 123); + // sysv64 is the default calling convention on unix systems. The rdi register is // used to pass arguments in the sysv64 calling convention, so this register will be clobbered #[cfg(unix)] @@ -227,6 +251,24 @@ fn asm() { out("r15b") _, ); } + + // Make sure the input value from inout is assigned to the input value + unsafe { + // Use a very distinctive value unlikely to live in any register. + let input: u64 = 0x1234567890ABCDEF; + let mut output: u64; + + asm!( + "push {1}", + "pop {0}", + out(reg) output, + inout(reg) input => _, + ); + + assert_eq!(output, 0x1234567890ABCDEF); + } + + asm_goto_test(0); } #[cfg(not(target_arch = "x86_64"))] diff --git a/compiler/rustc_codegen_gcc/tests/run/int.rs b/compiler/rustc_codegen_gcc/tests/run/int.rs index 78675acb5447b..ef825b4d80185 100644 --- a/compiler/rustc_codegen_gcc/tests/run/int.rs +++ b/compiler/rustc_codegen_gcc/tests/run/int.rs @@ -319,4 +319,29 @@ fn main() { const VAL5: T = 73236519889708027473620326106273939584_i128; check_ops128!(); } + + { + #[allow(dead_code)] + #[repr(u8)] + enum Inner { + L0 = 0, + H255 = 255, + } + #[allow(dead_code)] + enum O { + A(Inner), + B, + C, + } + + #[inline(never)] + fn which(o: &O) -> &'static str { + match o { + O::A(_) => "a", + O::B => "b", + O::C => "c", + } + } + assert_eq!(which(black_box(&O::A(Inner::H255))), "a"); + } } diff --git a/compiler/rustc_codegen_gcc/tests/run/mir_preserve_ub_empty_switch.rs b/compiler/rustc_codegen_gcc/tests/run/mir_preserve_ub_empty_switch.rs new file mode 100644 index 0000000000000..26056360b9212 --- /dev/null +++ b/compiler/rustc_codegen_gcc/tests/run/mir_preserve_ub_empty_switch.rs @@ -0,0 +1,35 @@ +// ignore-if: test -z "$CARGO_TEST_FLAGS" +// Compiler: +// +// Run-time: +// status: 0 + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/881 +// +// This needs `-Zmir-preserve-ub`, so it is skipped unless that flag is passed +// through `CARGO_TEST_FLAGS` (see the `ignore-if` directive above). Run it with: +// CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use intrinsics::black_box; +use mini_core::*; + +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { + // With `-Zmir-preserve-ub`, the range pattern below is lowered to a pair of + // comparisons and the second one becomes a `SwitchInt` with no cases (only + // an `otherwise` target) whose discriminant is the `bool` comparison + // result. `gcc_jit_block_end_with_switch` rejects a non-integer + // discriminant, so the backend must emit a plain jump for it instead. + let value = black_box(argc); + match value { + 0..=9 => (), + _ => (), + } + 0 +} diff --git a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py index 5390323407779..06425f682a88b 100644 --- a/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py +++ b/compiler/rustc_codegen_gcc/tools/generate_intrinsics.py @@ -84,6 +84,10 @@ def update_intrinsics(llvm_path): # This speeds up the comparison, and makes our code considerably smaller. # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) + indent4 = " " + indent8 = indent4 + indent4 + indent12 = indent8 + indent4 + indent16 = indent12 + indent4 with open(output_file, "w", encoding="utf8") as out: out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! @@ -95,33 +99,35 @@ def update_intrinsics(llvm_path): if let ArchCheckResult::Ok(res) = old_arch_res { return res; } -match arch {""") + match arch { +""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" - out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) + out.write(f"""{indent4}"{arch}" => {{ +{indent8}{attribute} fn {arch}(name: &str,full_name:&str) -> &'static str {{ +{indent12}match name {{""") intrinsics[arch].sort(key=lambda x: (x[0], x[1])) - out.write(' // {}\n'.format(arch)) + out.write(f'{indent16}// {arch}\n') for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); if "_round_mask" in entry[1]: - out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) + out.write(f'{indent16}// [INVALID CONVERSION]: "{llvm_name}" => "{entry[1]}",\n') else: - out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) - out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') - out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(""" _ => { - match old_arch_res { - ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), - ArchCheckResult::Ok(_) => unreachable!(), - } - }""") + out.write(f'{indent16}"{llvm_name}" => "{entry[1]}",\n') + out.write(f'{indent16}_ => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"),\n') + out.write(f"{indent16}}}\n{indent12}}}\n{indent8}{arch}(name,full_name)\n{indent8}}}\n,") + out.write(f"""{indent4}_ => {{ +{indent8}match old_arch_res {{ +{indent8}ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"), +{indent8}ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {{arch}}, intrinsic: {{full_name}}"), +{indent8}ArchCheckResult::Ok(_) => unreachable!(), +{indent4}}} +}}""") out.write("}\n}") - subprocess.call(["rustfmt", output_file]) print("Done!") From 0787958c776c4f0e9e0bc252580aadffde5c0a43 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 20:56:48 +0200 Subject: [PATCH 0367/1309] Fix source code divergence --- .github/workflows/ci.yml | 13 +- .github/workflows/stdarch.yml | 20 +- .gitignore | 2 +- CONTRIBUTING.md | 2 +- Cargo.lock | 92 +--- Readme.md | 8 +- build_system/Cargo.lock | 2 +- build_system/asm-tester/Cargo.lock | 507 ++++++++++++++++++ build_system/asm-tester/Cargo.toml | 13 + build_system/asm-tester/src/main.rs | 66 +++ build_system/src/build.rs | 2 +- build_system/src/clean.rs | 3 +- build_system/src/clippy.rs | 62 +++ build_system/src/config.rs | 13 +- build_system/src/fmt.rs | 5 +- build_system/src/main.rs | 112 ++-- build_system/src/rust_tools.rs | 2 +- build_system/src/test.rs | 141 ++++- build_system/src/todo.rs | 72 +++ build_system/src/utils.rs | 58 +- doc/subtree.md | 4 +- example/mini_core_hello_world.rs | 2 +- src/abi.rs | 41 +- src/asm.rs | 19 +- src/attributes.rs | 26 + src/back/lto.rs | 37 +- src/back/write.rs | 5 +- src/base.rs | 118 +--- src/builder.rs | 119 ++-- src/callee.rs | 2 +- src/consts.rs | 45 +- src/declare.rs | 32 +- src/diagnostics.rs | 4 - src/gcc_util.rs | 2 +- src/int.rs | 18 +- src/intrinsic/archs.rs | 86 ++- src/intrinsic/llvm.rs | 111 +++- src/intrinsic/mod.rs | 44 +- src/intrinsic/old_archs.rs | 4 + src/lib.rs | 22 +- src/mono_item.rs | 23 +- src/type_.rs | 4 +- tests/asm/asm/comments.rs | 12 + .../x86_64-naked-fn-no-cet-prolog.rs | 24 + tests/asm/panic-no-unwind-no-uwtable.rs | 8 + tests/asm/used.rs | 14 + tests/asm/x86_64-sse_crc.rs | 12 + .../compile/x86_interrupt_first_arg_byval.rs | 16 + tests/cpuid.def | 27 + tests/lang_tests.rs | 18 +- tests/run/asm.rs | 42 ++ tests/run/int.rs | 25 + tests/run/mir_preserve_ub_empty_switch.rs | 35 ++ tools/generate_intrinsics.py | 36 +- 54 files changed, 1739 insertions(+), 493 deletions(-) create mode 100644 build_system/asm-tester/Cargo.lock create mode 100644 build_system/asm-tester/Cargo.toml create mode 100644 build_system/asm-tester/src/main.rs create mode 100644 build_system/src/clippy.rs create mode 100644 build_system/src/todo.rs create mode 100644 tests/asm/asm/comments.rs create mode 100644 tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs create mode 100644 tests/asm/panic-no-unwind-no-uwtable.rs create mode 100644 tests/asm/used.rs create mode 100644 tests/asm/x86_64-sse_crc.rs create mode 100644 tests/compile/x86_interrupt_first_arg_byval.rs create mode 100644 tests/cpuid.def create mode 100644 tests/run/mir_preserve_ub_empty_switch.rs diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 8888fdc3ee093..2f5cc409e363d 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -26,7 +26,7 @@ jobs: - { gcc: "gcc-15.deb" } - { gcc: "gcc-15-without-int128.deb" } commands: [ - "--std-tests", + "--std-tests --alloc-tests", # FIXME: re-enable asm tests when GCC can emit in the right syntax. # "--asm-tests", "--test-libcore", @@ -91,16 +91,17 @@ jobs: - name: Check formatting run: ./y.sh fmt --check - - name: clippy - run: | - cargo clippy --all-targets -- -D warnings - cargo clippy --all-targets --no-default-features -- -D warnings - cargo clippy --manifest-path build_system/Cargo.toml --all-targets -- -D warnings + - name: Check todo + run: ./y.sh check-todo + + - name: Check lints + run: ./y.sh clippy - name: Build run: | ./y.sh build --sysroot ./y.sh test --cargo-tests + CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch - name: Run y.sh cargo build run: | diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 66f30b147b4c0..17d6449c85e08 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -21,7 +21,7 @@ jobs: fail-fast: false matrix: cargo_runner: [ - "sde -future -rtm_mode full --", + "sde -cpuid-in /home/runner/work/rustc_codegen_gcc/rustc_codegen_gcc/tests/cpuid.def -rtm_mode full --", "", ] @@ -42,8 +42,14 @@ jobs: - name: Install more recent binutils run: | echo "deb http://archive.ubuntu.com/ubuntu plucky main universe" | sudo tee /etc/apt/sources.list.d/plucky-copies.list - sudo apt-get update + sudo apt-get update -o Acquire::Retries=3 sudo apt-get install binutils + installed="$(dpkg-query --showformat='${Version}' --show binutils)" + echo "Installed binutils: $installed" + if dpkg --compare-versions "$installed" lt "2.44"; then + echo "::error::binutils upgrade failed (got $installed, need >= 2.44); the apt fetch probably failed" + exit 1 + fi - name: Install Intel Software Development Emulator if: ${{ matrix.cargo_runner }} @@ -51,10 +57,9 @@ jobs: mkdir intel-sde cd intel-sde version=10.8.0-2026-03-15 - url_path=915934 dir=sde-external-$version-lin file=$dir.tar.xz - wget https://downloadmirror.intel.com/$url_path/$file + wget http://ci-mirrors.rust-lang.org/$file tar xvf $file sudo mkdir /usr/share/intel-sde sudo cp -r $dir/* /usr/share/intel-sde @@ -90,14 +95,15 @@ jobs: - name: Run stdarch tests if: ${{ !matrix.cargo_runner }} run: | - CHANNEL=release TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. - # FIXME: remove --skip test_tile_ when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ + # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/.gitignore b/.gitignore index 2a8fdcda0b483..13bd0d0ffde9b 100644 --- a/.gitignore +++ b/.gitignore @@ -7,7 +7,7 @@ perf.data.old *.events *.string* gimple* -*asm +*_asm res test-backend projects diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8f81ecca445a8..c5c2a783b1ee7 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -112,7 +112,7 @@ Full list of debugging options can be found in the [README](Readme.md#env-vars). ### Code Style Guidelines - Follow Rust standard coding conventions -- Ensure your code passes `rustfmt` and `clippy` +- Ensure your code passes `rustfmt` and `clippy` (you can run them with `y.sh fmt` and `y.sh clippy`) - Add comments explaining complex logic, especially in GCC interface code ## Additional Resources diff --git a/Cargo.lock b/Cargo.lock index c7e979a1112e3..c174628d0d188 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -31,9 +31,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" dependencies = [ "libc", "windows-sys", @@ -117,15 +117,15 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.168" +version = "0.2.186" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5aaeb2981e0606ca11d79718f8bb01164f1d6ed75080182d3abf017e6d244b6d" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" [[package]] name = "linux-raw-sys" -version = "0.9.4" +version = "0.12.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" +checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "memchr" @@ -194,9 +194,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.7" +version = "1.1.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c71e83d6afe7ff64890ec6b71d6a69bb8a610ab78ce364b3352876bb4c801266" +checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" dependencies = [ "bitflags", "errno", @@ -216,9 +216,9 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.20.0" +version = "3.27.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e8a64e3985349f2441a1a9ef0b853f869006c3855f2cda6862a94d26ebb9d6a1" +checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", "getrandom", @@ -311,78 +311,20 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" [[package]] -name = "windows-sys" -version = "0.59.0" +name = "windows-link" +version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" -dependencies = [ - "windows-targets", -] +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" [[package]] -name = "windows-targets" -version = "0.52.6" +name = "windows-sys" +version = "0.61.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" dependencies = [ - "windows_aarch64_gnullvm", - "windows_aarch64_msvc", - "windows_i686_gnu", - "windows_i686_gnullvm", - "windows_i686_msvc", - "windows_x86_64_gnu", - "windows_x86_64_gnullvm", - "windows_x86_64_msvc", + "windows-link", ] -[[package]] -name = "windows_aarch64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" - -[[package]] -name = "windows_aarch64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" - -[[package]] -name = "windows_i686_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" - -[[package]] -name = "windows_i686_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" - -[[package]] -name = "windows_i686_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" - -[[package]] -name = "windows_x86_64_gnu" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" - -[[package]] -name = "windows_x86_64_gnullvm" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" - -[[package]] -name = "windows_x86_64_msvc" -version = "0.52.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" - [[package]] name = "wit-bindgen-rt" version = "0.39.0" diff --git a/Readme.md b/Readme.md index 6b1f90b918855..9a7c624c9bc22 100644 --- a/Readme.md +++ b/Readme.md @@ -136,19 +136,21 @@ $ ./y.sh cargo build --manifest-path tests/hello-world/Cargo.toml ### Cargo ```bash -$ CHANNEL="release" $CG_GCCJIT_DIR/y.sh cargo run +$ CHANNEL=release $CG_GCCJIT_DIR/y.sh cargo run ``` -If you compiled cg_gccjit in debug mode (aka you didn't pass `--release` to `./y.sh test`) you should use `CHANNEL="debug"` instead or omit `CHANNEL="release"` completely. +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. ### Rustc If you want to run `rustc` directly, you can do so with: ```bash -$ ./y.sh rustc my_crate.rs +$ CHANNEL=release ./y.sh rustc my_crate.rs ``` +If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y.sh build`) you should use `CHANNEL=debug` instead or omit `CHANNEL=release` completely. + You can do the same manually (although we don't recommend it): ```bash diff --git a/build_system/Cargo.lock b/build_system/Cargo.lock index e727561a2bfba..5e761149eb3bc 100644 --- a/build_system/Cargo.lock +++ b/build_system/Cargo.lock @@ -1,6 +1,6 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. -version = 3 +version = 4 [[package]] name = "boml" diff --git a/build_system/asm-tester/Cargo.lock b/build_system/asm-tester/Cargo.lock new file mode 100644 index 0000000000000..9ad96acfda407 --- /dev/null +++ b/build_system/asm-tester/Cargo.lock @@ -0,0 +1,507 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "aho-corasick" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" +dependencies = [ + "memchr", +] + +[[package]] +name = "asm-tester" +version = "0.1.0" +dependencies = [ + "compiletest_rs", +] + +[[package]] +name = "cfg-if" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" + +[[package]] +name = "compiletest_rs" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f150fe9105fcd2a57cad53f0c079a24de65195903ef670990f5909f695eac04c" +dependencies = [ + "diff", + "filetime", + "getopts", + "lazy_static", + "libc", + "log", + "miow", + "regex", + "rustfix", + "serde", + "serde_derive", + "serde_json", + "tester", + "windows-sys 0.59.0", +] + +[[package]] +name = "diff" +version = "0.1.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" + +[[package]] +name = "dirs-next" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b98cf8ebf19c3d1b223e151f99a4f9f0690dca41414773390fc824184ac833e1" +dependencies = [ + "cfg-if", + "dirs-sys-next", +] + +[[package]] +name = "dirs-sys-next" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4ebda144c4fe02d1f7ea1a7d9641b6fc6b580adcfa024ae48797ecdeb6825b4d" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + +[[package]] +name = "filetime" +version = "0.2.29" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c287a33c7f0a620c38e641e7f60827713987b3c0f26e8ddc9462cc69cf75759" +dependencies = [ + "cfg-if", + "libc", +] + +[[package]] +name = "getopts" +version = "0.2.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cfe4fbac503b8d1f88e6676011885f34b7174f46e59956bba534ba83abded4df" +dependencies = [ + "unicode-width", +] + +[[package]] +name = "getrandom" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" +dependencies = [ + "cfg-if", + "libc", + "wasi", +] + +[[package]] +name = "hermit-abi" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" + +[[package]] +name = "itoa" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" + +[[package]] +name = "lazy_static" +version = "1.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" + +[[package]] +name = "libc" +version = "0.2.186" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66" + +[[package]] +name = "libredox" +version = "0.1.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c943259e342f1e06ff2da7a83eabdfe7f92ce10262688dbf1895ff0b3e6e4652" +dependencies = [ + "libc", +] + +[[package]] +name = "log" +version = "0.4.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ceec5bc11778974d1bcb055b18002eba7f4b3518b6a0081b3af5f21666da9ad" + +[[package]] +name = "memchr" +version = "2.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88904434abc2901f197fe8cc55f0445e7ded921dba5911dad2e2b39b48e663c4" + +[[package]] +name = "miow" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "536bfad37a309d62069485248eeaba1e8d9853aaf951caaeaed0585a95346f08" +dependencies = [ + "windows-sys 0.61.2", +] + +[[package]] +name = "num_cpus" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91df4bbde75afed763b708b7eee1e8e7651e02d97f6d5dd763e89367e957b23b" +dependencies = [ + "hermit-abi", + "libc", +] + +[[package]] +name = "once_cell" +version = "1.21.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50" + +[[package]] +name = "pin-project-lite" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a89322df9ebe1c1578d689c92318e070967d1042b512afbe49518723f4e6d5cd" + +[[package]] +name = "proc-macro2" +version = "1.0.106" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dfbc457d0c7a0759a614551b11a6409e5951f6c7537be1f1b7682b9ae9230368" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "redox_users" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43" +dependencies = [ + "getrandom", + "libredox", + "thiserror", +] + +[[package]] +name = "regex" +version = "1.12.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1292b7759ae1cb9ec195452d1390a074f0cd8541ab7a5a8c31cd6db45d4a6ba" +dependencies = [ + "aho-corasick", + "memchr", + "regex-automata", + "regex-syntax", +] + +[[package]] +name = "regex-automata" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e1dd4122fc1595e8162618945476892eefca7b88c52820e74af6262213cae8f" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", +] + +[[package]] +name = "regex-syntax" +version = "0.8.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6f6ff9a378485b298a5286656da665ba74413d36db0979633275d2e708145d4" + +[[package]] +name = "rustfix" +version = "0.8.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "82fa69b198d894d84e23afde8e9ab2af4400b2cba20d6bf2b428a8b01c222c5a" +dependencies = [ + "serde", + "serde_json", + "thiserror", + "tracing", +] + +[[package]] +name = "rustversion" +version = "1.0.22" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" + +[[package]] +name = "serde" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" +dependencies = [ + "serde_core", + "serde_derive", +] + +[[package]] +name = "serde_core" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.228" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "serde_json" +version = "1.0.150" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e8014e44b4736ed0538adeecded0fce2a272f22dc9578a7eb6b2d9993c74cfb9" +dependencies = [ + "itoa", + "memchr", + "serde", + "serde_core", + "zmij", +] + +[[package]] +name = "syn" +version = "2.0.118" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b9ae57f904213ebb649ce6895b8a66c66f0203b9319718f69a5612a065b1422" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "term" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c59df8ac95d96ff9bede18eb7300b0fda5e5d8d90960e76f8e14ae765eedbf1f" +dependencies = [ + "dirs-next", + "rustversion", + "winapi", +] + +[[package]] +name = "tester" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89e8bf7e0eb2dd7b4228cc1b6821fc5114cd6841ae59f652a85488c016091e5f" +dependencies = [ + "cfg-if", + "getopts", + "libc", + "num_cpus", + "term", +] + +[[package]] +name = "thiserror" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" +dependencies = [ + "thiserror-impl", +] + +[[package]] +name = "thiserror-impl" +version = "1.0.69" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing" +version = "0.1.44" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" +dependencies = [ + "pin-project-lite", + "tracing-core", +] + +[[package]] +name = "tracing-core" +version = "0.1.36" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" +dependencies = [ + "once_cell", +] + +[[package]] +name = "unicode-ident" +version = "1.0.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" + +[[package]] +name = "unicode-width" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b4ac048d71ede7ee76d585517add45da530660ef4390e49b098733c6e897f254" + +[[package]] +name = "wasi" +version = "0.11.1+wasi-snapshot-preview1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows-link" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" + +[[package]] +name = "windows-sys" +version = "0.59.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e38bc4d79ed67fd075bcc251a1c39b32a1776bbe92e5bef1f0bf1f8c531853b" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-sys" +version = "0.61.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" +dependencies = [ + "windows-link", +] + +[[package]] +name = "windows-targets" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc", + "windows_i686_gnu", + "windows_i686_gnullvm", + "windows_i686_msvc", + "windows_x86_64_gnu", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc", +] + +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" + +[[package]] +name = "windows_aarch64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" + +[[package]] +name = "windows_i686_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" + +[[package]] +name = "windows_i686_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" + +[[package]] +name = "windows_i686_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" + +[[package]] +name = "windows_x86_64_gnu" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" + +[[package]] +name = "windows_x86_64_msvc" +version = "0.52.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "zmij" +version = "1.0.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8848ee67ecc8aedbaf3e4122217aff892639231befc6a1b58d29fff4c2cabaa" diff --git a/build_system/asm-tester/Cargo.toml b/build_system/asm-tester/Cargo.toml new file mode 100644 index 0000000000000..eeefe61bdc75b --- /dev/null +++ b/build_system/asm-tester/Cargo.toml @@ -0,0 +1,13 @@ +[package] +name = "asm-tester" +version = "0.1.0" +edition = "2024" + +[dependencies] +compiletest_rs = "0.11.2" + +[[bin]] +name = "asm-tester" +path = "src/main.rs" + +[workspace] diff --git a/build_system/asm-tester/src/main.rs b/build_system/asm-tester/src/main.rs new file mode 100644 index 0000000000000..00ee4ac936520 --- /dev/null +++ b/build_system/asm-tester/src/main.rs @@ -0,0 +1,66 @@ +use std::path::PathBuf; + +#[derive(Default)] +struct Config { + llvm_filecheck: Option, + filters: Vec, + rustc_flags: Vec, +} + +impl Config { + fn new() -> Result { + // We skip the program's name. + let mut args = std::env::args().skip(1); + let mut config = Self::default(); + + while let Some(arg) = args.next() { + match arg.as_str() { + "--llvm-filecheck" => { + config.llvm_filecheck = args.next().map(PathBuf::from); + } + "--filter" => { + if let Some(arg) = args.next() { + config.filters.push(arg); + } + } + "--" => { + config.rustc_flags.extend(&mut args); + // Nothing else to be read but the `break` makes it more clear. + break; + } + arg => return Err(format!("Unknown argument {arg:?}")), + } + } + if config.llvm_filecheck.is_none() { + Err("Missing `--llvm-filecheck` option".to_owned()) + } else if config.rustc_flags.is_empty() { + Err("Missing rustc flags (passed after `--`)".to_owned()) + } else { + Ok(config) + } + } +} + +fn main() { + let Config { llvm_filecheck, filters, rustc_flags } = match Config::new() { + Ok(c) => c, + Err(error) => { + eprintln!("{error}"); + std::process::exit(1); + } + }; + + let mut test_config = compiletest_rs::Config::default(); + + test_config.mode = compiletest_rs::common::Mode::Assembly; + test_config.src_base = PathBuf::from("tests/asm"); + test_config.llvm_filecheck = llvm_filecheck; + test_config.filters = filters; + test_config.strict_headers = true; + test_config.build_base = PathBuf::from("build/tests/asm"); + test_config.target_rustcflags = Some(rustc_flags.join(" ")); + test_config.link_deps(); + test_config.clean_rmeta(); + + compiletest_rs::run_tests(&test_config) +} diff --git a/build_system/src/build.rs b/build_system/src/build.rs index 2f2900af5c88a..bcd386bfebdae 100644 --- a/build_system/src/build.rs +++ b/build_system/src/build.rs @@ -266,7 +266,7 @@ fn build_codegen(args: &mut BuildArg) -> Result<(), String> { } run_command_with_output_and_env(&command, None, Some(&env))?; - args.config_info.setup(&mut env, false)?; + args.config_info.setup(&mut env, false, true)?; // We voluntarily ignore the error. let _ = fs::remove_dir_all("target/out"); diff --git a/build_system/src/clean.rs b/build_system/src/clean.rs index 43f01fdf35ecb..ec2092ee92ef5 100644 --- a/build_system/src/clean.rs +++ b/build_system/src/clean.rs @@ -74,7 +74,8 @@ fn clean_ui_tests() -> Result<(), String> { let path = Path::new(crate::BUILD_DIR) .join("rust/build/x86_64-unknown-linux-gnu/test/") .join(directory); - run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None)?; + // The directory might not exist, so ignore the error. + let _ = run_command(&[&"find", &path, &"-name", &"stamp", &"-delete"], None); } Ok(()) } diff --git a/build_system/src/clippy.rs b/build_system/src/clippy.rs new file mode 100644 index 0000000000000..813d4b9141e1c --- /dev/null +++ b/build_system/src/clippy.rs @@ -0,0 +1,62 @@ +use std::path::Path; + +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present}; + +fn show_usage() { + println!( + r#" +`clippy` command help: + + --help : Show this help"# + ); +} + +pub fn run() -> Result<(), String> { + // We skip binary name and the `info` command. + let args = std::env::args().skip(2); + #[allow(clippy::never_loop)] + for arg in args { + match arg.as_str() { + "--help" => { + show_usage(); + return Ok(()); + } + _ => return Err(format!("Unknown option {arg}")), + } + } + + run_tool_and_install_it_if_not_present(&[ + &"cargo", + &"clippy", + &"--all-targets", + &"--", + &"-D", + &"warnings", + ])?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--no-default-features", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + run_command_with_output( + &[ + &"cargo", + &"clippy", + &"--all-targets", + &"--manifest-path", + &"build_system/Cargo.toml", + &"--", + &"-D", + &"warnings", + ], + Some(Path::new(".")), + )?; + Ok(()) +} diff --git a/build_system/src/config.rs b/build_system/src/config.rs index 8eb6d8f019e1c..fd78f691d1657 100644 --- a/build_system/src/config.rs +++ b/build_system/src/config.rs @@ -314,6 +314,7 @@ impl ConfigInfo { &mut self, env: &mut HashMap, use_system_gcc: bool, + generate_out_dir: bool, ) -> Result<(), String> { env.insert("CARGO_INCREMENTAL".to_string(), "0".to_string()); @@ -444,12 +445,12 @@ impl ConfigInfo { self.rustc_command = vec![rustc]; self.rustc_command.extend_from_slice(&rustflags); - self.rustc_command.extend_from_slice(&[ - "-L".to_string(), - format!("crate={}", self.cargo_target_dir), - "--out-dir".to_string(), - self.cargo_target_dir.clone(), - ]); + self.rustc_command + .extend_from_slice(&["-L".to_string(), format!("crate={}", self.cargo_target_dir)]); + if generate_out_dir { + self.rustc_command + .extend_from_slice(&["--out-dir".to_string(), self.cargo_target_dir.clone()]); + } if !env.contains_key("RUSTC_LOG") { env.insert("RUSTC_LOG".to_string(), "warn".to_string()); diff --git a/build_system/src/fmt.rs b/build_system/src/fmt.rs index 91535f217e351..dc1ca1d3e82ae 100644 --- a/build_system/src/fmt.rs +++ b/build_system/src/fmt.rs @@ -1,7 +1,7 @@ use std::ffi::OsStr; use std::path::Path; -use crate::utils::{run_command_with_output, walk_dir}; +use crate::utils::{run_command_with_output, run_tool_and_install_it_if_not_present, walk_dir}; fn show_usage() { println!( @@ -31,8 +31,9 @@ pub fn run() -> Result<(), String> { let cmd: &[&dyn AsRef] = if check { &[&"cargo", &"fmt", &"--check"] } else { &[&"cargo", &"fmt"] }; - run_command_with_output(cmd, Some(Path::new(".")))?; + run_tool_and_install_it_if_not_present(cmd)?; run_command_with_output(cmd, Some(Path::new("build_system")))?; + run_command_with_output(cmd, Some(Path::new("build_system/asm-tester")))?; run_rustfmt_recursively("tests/run", check) } diff --git a/build_system/src/main.rs b/build_system/src/main.rs index d0b9811ac8ceb..37b1f306817fd 100644 --- a/build_system/src/main.rs +++ b/build_system/src/main.rs @@ -3,6 +3,7 @@ use std::{env, process}; mod abi_test; mod build; mod clean; +mod clippy; mod clone_gcc; mod config; mod fmt; @@ -12,6 +13,7 @@ mod prepare; mod rust_tools; mod rustc_info; mod test; +mod todo; mod utils; const BUILD_DIR: &str = "build"; @@ -24,43 +26,67 @@ macro_rules! arg_error { }}; } -fn usage() { - println!( - "\ +macro_rules! commands_decl { + ($($variant:ident: $doc_name:literal => $doc:literal ,)+) => { + enum Command { + $($variant),+ + } + + impl<'a> From> for Command { + fn from(arg: Option<&'a str>) -> Self { + match arg { + $(Some($doc_name) => Self::$variant,)+ + Some("--help") => { + usage(); + process::exit(0); + } + Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), + Some(command) => arg_error!("Unknown command {}", command), + None => { + usage(); + process::exit(0); + } + } + } + } + + fn usage() { + println!("\ rustc_codegen_gcc build system Usage: build_system [command] [options] Options: - --help : Displays this help message. + --help : Displays this help message. + +Commands:", + ); + let mut commands = vec![$(($doc_name, $doc),)+]; + let longest = commands.iter().map(|(name, _)| name.len()).max().unwrap(); -Commands: - cargo : Executes a cargo command. - rustc : Compiles the program using the GCC compiler. - clean : Cleans the build directory, removing all compiled files and artifacts. - prepare : Prepares the environment for building, including fetching dependencies and setting up configurations. - build : Compiles the project. - test : Runs tests for the project. - info : Displays information about the build environment and project configuration. - clone-gcc : Clones the GCC compiler from a specified source. - fmt : Runs rustfmt - fuzz : Fuzzes `cg_gcc` using rustlantis - abi-test : Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM" - ); + commands.sort_unstable_by(|a, b| a.0.cmp(b.0)); + for (name, doc) in commands { + let spacing = std::iter::repeat(' ').take(longest - name.len() + 1).collect::(); + eprintln!(" {name}{spacing}: {doc}."); + } + } + } } -pub enum Command { - Cargo, - Clean, - CloneGcc, - Prepare, - Build, - Rustc, - Test, - Info, - Fmt, - Fuzz, - AbiTest, +commands_decl! { + Cargo: "cargo" => "Executes a cargo command", + Clean: "clean" => "Cleans the build directory, removing all compiled files and artifacts", + Clippy: "clippy" => "Runs clippy", + CloneGcc: "clone-gcc" => "Clones the GCC compiler from a specified source", + Prepare: "prepare" => "Prepares the environment for building, including fetching dependencies and setting up configurations", + Build: "build" => "Compiles the project", + Rustc: "rustc" => "Compiles the program using the GCC compiler", + Test: "test" => "Runs tests for the project", + Info: "info" => "Displays information about the build environment and project configuration", + Fmt: "fmt" => "Runs rustfmt", + Fuzz: "fuzz" => "Fuzzes `cg_gcc` using `rustlantis`", + AbiTest: "abi-test" => "Runs the abi-cafe test suite on the codegen, checking for ABI compatibility with LLVM", + CheckTodo: "check-todo" => "Checks todo in the project", } fn main() { @@ -70,31 +96,7 @@ fn main() { } } - let command = match env::args().nth(1).as_deref() { - Some("cargo") => Command::Cargo, - Some("rustc") => Command::Rustc, - Some("clean") => Command::Clean, - Some("prepare") => Command::Prepare, - Some("build") => Command::Build, - Some("test") => Command::Test, - Some("info") => Command::Info, - Some("clone-gcc") => Command::CloneGcc, - Some("abi-test") => Command::AbiTest, - Some("fmt") => Command::Fmt, - Some("fuzz") => Command::Fuzz, - Some("--help") => { - usage(); - process::exit(0); - } - Some(flag) if flag.starts_with('-') => arg_error!("Expected command found flag {}", flag), - Some(command) => arg_error!("Unknown command {}", command), - None => { - usage(); - process::exit(0); - } - }; - - if let Err(e) = match command { + if let Err(e) = match Command::from(env::args().nth(1).as_deref()) { Command::Cargo => rust_tools::run_cargo(), Command::Rustc => rust_tools::run_rustc(), Command::Clean => clean::run(), @@ -106,6 +108,8 @@ fn main() { Command::Fmt => fmt::run(), Command::Fuzz => fuzz::run(), Command::AbiTest => abi_test::run(), + Command::Clippy => clippy::run(), + Command::CheckTodo => todo::run(), } { eprintln!("Command failed to run: {e}"); // CI needs to tell a build system error apart from the test failures some suites expect. diff --git a/build_system/src/rust_tools.rs b/build_system/src/rust_tools.rs index b1faa27acc4a2..1b50f11c3d324 100644 --- a/build_system/src/rust_tools.rs +++ b/build_system/src/rust_tools.rs @@ -72,7 +72,7 @@ impl RustcTools { let mut env: HashMap = std::env::vars().collect(); let mut config = ConfigInfo::default(); - config.setup(&mut env, false)?; + config.setup(&mut env, false, false)?; let toolchain = get_toolchain()?; let toolchain_version = rustc_toolchain_version_info(&toolchain)?; diff --git a/build_system/src/test.rs b/build_system/src/test.rs index a4bdb80c94f28..a55c2dcf83ddc 100644 --- a/build_system/src/test.rs +++ b/build_system/src/test.rs @@ -11,8 +11,8 @@ use crate::build; use crate::config::{Channel, ConfigInfo}; use crate::utils::{ create_dir, get_sysroot_dir, get_toolchain, git_clone, git_clone_root_dir, remove_file, - run_command, run_command_with_env, run_command_with_output_and_env, rustc_version_info, - split_args, walk_dir, + run_command, run_command_with_env, run_command_with_output_and_env, + run_command_with_output_and_env_no_err, rustc_version_info, split_args, walk_dir, }; /// Exit code of `y.sh test` when the tests ran and reported failures, as opposed to the build @@ -39,6 +39,7 @@ fn get_runners() -> Runners { ("Run failing ui pattern tests", test_failing_ui_pattern_tests), ); runners.insert("--test-failing-rustc", ("Run failing rustc tests", test_failing_rustc)); + runners.insert("--run-ui-tests", ("Run specified rustc UI tests", run_ui_tests)); runners.insert("--projects", ("Run the tests of popular crates", test_projects)); runners.insert("--test-libcore", ("Run libcore tests", test_libcore)); runners.insert("--test-release-libcore", ("Run libcore tests", test_release_libcore)); @@ -56,8 +57,10 @@ fn get_runners() -> Runners { ); runners.insert("--extended-regex-tests", ("Run extended regex tests", extended_regex_tests)); runners.insert("--mini-tests", ("Run mini tests", mini_tests)); + runners.insert("--gcc-asm-tests", ("Run cg_gcc asm tests", test_asm)); runners.insert("--cargo-tests", ("Run cargo tests", cargo_tests)); runners.insert("--no-builtins-tests", ("Test #![no_builtins] attribute", no_builtins_tests)); + runners.insert("--stdarch-tests", ("Run stdarch tests", test_stdarch as Runner)); runners } @@ -519,6 +522,26 @@ fn std_tests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn get_llvm_filecheck(env: &Env) -> Result { + match run_command_with_env( + &[ + &"bash", + &"-c", + &"which FileCheck-10 || \ + which FileCheck-11 || \ + which FileCheck-12 || \ + which FileCheck-13 || \ + which FileCheck-14 || \ + which FileCheck", + ], + None, + Some(env), + ) { + Ok(cmd) => Ok(String::from_utf8_lossy(&cmd.stdout).trim().to_string()), + Err(_) => Err("Failed to retrieve LLVM FileCheck, ignoring...".to_owned()), + } +} + fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let toolchain = format!( "+{channel}-{host}", @@ -562,23 +585,10 @@ fn setup_rustc(env: &mut Env, args: &TestArg) -> Result { let rustc = rustc.trim().to_owned(); if rustc.is_empty() { Err("`rustc` path is empty".to_string()) } else { Ok(rustc) } })?; - let llvm_filecheck = match run_command_with_env( - &[ - &"bash", - &"-c", - &"which FileCheck-10 || \ - which FileCheck-11 || \ - which FileCheck-12 || \ - which FileCheck-13 || \ - which FileCheck-14 || \ - which FileCheck", - ], - rust_dir, - Some(env), - ) { - Ok(cmd) => String::from_utf8_lossy(&cmd.stdout).to_string(), - Err(_) => { - eprintln!("Failed to retrieve LLVM FileCheck, ignoring..."); + let llvm_filecheck = match get_llvm_filecheck(env) { + Ok(l) => l, + Err(error) => { + eprintln!("{error}"); // FIXME: the test tests/run-make/no-builtins-attribute will fail if we cannot find // FileCheck. String::new() @@ -648,7 +658,7 @@ fn asm_tests(env: &Env, args: &TestArg) -> Result<(), String> { &"0", &"--set", &"build.compiletest-allow-stage0=true", - &"tests/assembly-llvm/asm", + &"tests/assembly-gcc/asm", &"--compiletest-rustc-args", &rustc_args, ], @@ -921,6 +931,39 @@ fn test_libcore_doctests(env: &Env, args: &TestArg) -> Result<(), String> { Ok(()) } +fn test_stdarch(env: &Env, args: &TestArg) -> Result<(), String> { + println!("[TEST] stdarch"); + let manifest_path = get_sysroot_dir().join("sysroot_src/library/stdarch/Cargo.toml"); + let mut env = env.clone(); + + // `config.setup` already baked `CG_RUSTFLAGS` into `RUSTFLAGS`, so append the lint-allow to + // `RUSTFLAGS` directly (which `run_cargo_command` also propagates to `RUSTDOCFLAGS`). + let rustflags = env.get("RUSTFLAGS").cloned().unwrap_or_default(); + env.insert( + "RUSTFLAGS".to_string(), + format!("{rustflags} -Ainternal_features").trim().to_owned(), + ); + env.insert("TARGET".to_string(), args.config_info.target_triple.clone()); + + let mut command: Vec<&dyn AsRef> = + vec![&"test", &"--manifest-path", &manifest_path, &"--"]; + for test_name in &args.test_args { + command.push(test_name); + } + run_cargo_command(&command, None, &env, args)?; + Ok(()) +} + +fn test_alloc(env: &Env, args: &TestArg) -> Result<(), String> { + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] alloc"); + let path = get_sysroot_dir().join("sysroot_src/library/alloctests"); + let _ = remove_dir_all(path.join("target")); + // FIXME(antoyo): run in release mode when we fix the failures. + run_cargo_command(&[&"test"], Some(&path), env, args)?; + Ok(()) +} + fn extended_rand_tests(env: &Env, args: &TestArg) -> Result<(), String> { if !args.is_using_gcc_master_branch() { println!("Not using GCC master branch. Skipping `extended_rand_tests`."); @@ -1065,7 +1108,6 @@ fn contains_ui_error_patterns(file_path: &Path, keep_lto_tests: bool) -> Result< "//@ known-bug", "-Cllvm-args", "//~", - "thread", ] .iter() .any(|check| line.contains(check)) @@ -1548,6 +1590,60 @@ fn remove_files_callback(file_path: &str) -> impl Fn(&Path) -> Result Result<(), String> { + fn is_path_time_more_recent(ref_time: std::time::SystemTime, path: &str) -> bool { + std::fs::metadata(path) + .and_then(|metadata| metadata.modified()) + .is_ok_and(|time| ref_time < time) + } + + // FIXME: create a function "display_if_not_quiet" or something along the line. + println!("[TEST] cg_gcc assembly"); + let llvm_filecheck = get_llvm_filecheck(env)?; + + let target_dir = std::env::current_dir().unwrap().join("build_system/asm-tester/target"); + + // All this code is because `cargo` keeps recompiling this file, and we can't figure out why. + let binary_file_path = "build_system/asm-tester/target/debug/asm-tester"; + let mut need_recompilation = true; + if let Ok(metadata) = std::fs::metadata(binary_file_path) + && let Ok(ref_time) = metadata.modified() + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.toml") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/Cargo.lock") + && !is_path_time_more_recent(ref_time, "build_system/asm-tester/src/main.rs") + { + need_recompilation = false; + } + + if need_recompilation { + let build_asm_args: Vec<&dyn AsRef> = vec![ + &"cargo", + &"build", + &"--manifest-path", + &"build_system/asm-tester/Cargo.toml", + &"--target-dir", + &target_dir, + &"--", + ]; + run_command_with_output_and_env_no_err(&build_asm_args, Some(Path::new(".")), Some(env))?; + } + + let mut test_asm_args: Vec<&dyn AsRef> = vec![ + &"build_system/asm-tester/target/debug/asm-tester", + &"--llvm-filecheck", + &llvm_filecheck, + ]; + for test_arg in &args.test_args { + test_asm_args.push(&"--filter"); + test_asm_args.push(test_arg); + } + test_asm_args.push(&"--"); + for arg in args.config_info.rustc_command_vec().into_iter().skip(1) { + test_asm_args.push(arg); + } + run_command_with_output_and_env_no_err(&test_asm_args, Some(Path::new(".")), Some(env)) +} + fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { clean(env, args)?; mini_tests(env, args)?; @@ -1559,6 +1655,7 @@ fn run_all(env: &Env, args: &TestArg) -> Result<(), String> { cargo_tests(env, args)?; no_builtins_tests(env, args)?; test_rustc(env, args)?; + test_asm(env, args)?; Ok(()) } @@ -1580,7 +1677,7 @@ pub fn run() -> Result<(), String> { return Ok(()); } - args.config_info.setup(&mut env, args.use_system_gcc)?; + args.config_info.setup(&mut env, args.use_system_gcc, true)?; if args.runners.is_empty() { run_all(&env, &args)?; diff --git a/build_system/src/todo.rs b/build_system/src/todo.rs new file mode 100644 index 0000000000000..5b89410844788 --- /dev/null +++ b/build_system/src/todo.rs @@ -0,0 +1,72 @@ +use std::ffi::OsStr; +use std::fs::File; +use std::io::{BufRead, BufReader}; +use std::path::{Path, PathBuf}; +use std::process::Command; + +const EXTENSIONS: &[&str] = + &["rs", "py", "js", "sh", "c", "cpp", "h", "md", "css", "ftl", "toml", "yml", "yaml"]; + +fn has_supported_extension(path: &Path) -> bool { + path.extension().is_some_and(|ext| EXTENSIONS.iter().any(|e| ext == OsStr::new(e))) +} + +fn list_tracked_files() -> Result, String> { + let output = Command::new("git") + .args(["ls-files", "-z"]) + .output() + .map_err(|e| format!("Failed to run `git ls-files`: {e}"))?; + + if !output.status.success() { + let stderr = String::from_utf8_lossy(&output.stderr); + return Err(format!("`git ls-files` failed: {stderr}")); + } + + let mut files = Vec::new(); + for entry in output.stdout.split(|b| *b == 0) { + if entry.is_empty() { + continue; + } + let path = std::str::from_utf8(entry).unwrap(); + files.push(PathBuf::from(path)); + } + + Ok(files) +} + +pub(crate) fn run() -> Result<(), String> { + let files = list_tracked_files()?; + let mut error_count = 0; + // Avoid embedding the task marker in source so greps only find real occurrences. + let todo_marker = "todo".to_ascii_uppercase(); + + for file in files { + if !has_supported_extension(&file) { + continue; + } + + let file_handle = + File::open(&file).map_err(|e| format!("Failed to open {}: {e}", file.display()))?; + let reader = BufReader::new(file_handle); + + for (i, line) in reader.lines().enumerate() { + let line = line.map_err(|e| format!("Failed to read {}: {e}", file.display()))?; + let trimmed = line.trim(); + if trimmed.contains(&todo_marker) { + eprintln!( + "{}:{}: {} is used for tasks that should be done before merging a PR; if you want to leave a message in the codebase use FIXME", + file.display(), + i + 1, + todo_marker + ); + error_count += 1; + } + } + } + + if error_count == 0 { + return Ok(()); + } + + Err(format!("found {} {}(s)", error_count, todo_marker)) +} diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 112322f8688c1..4c67156a85fb2 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -2,10 +2,11 @@ use std::collections::HashMap; use std::ffi::OsStr; use std::fmt::Debug; use std::fs; +use std::io::{BufReader, Read}; #[cfg(unix)] use std::os::unix::process::ExitStatusExt; use std::path::{Path, PathBuf}; -use std::process::{Command, ExitStatus, Output}; +use std::process::{Command, ExitStatus, Output, Stdio}; fn exec_command( input: &[&dyn AsRef], @@ -47,7 +48,7 @@ pub(crate) fn get_command_inner( command } -fn check_exit_status( +pub(crate) fn check_exit_status( input: &[&dyn AsRef], cwd: Option<&Path>, exit_status: ExitStatus, @@ -115,6 +116,30 @@ pub fn run_command_with_output( check_exit_status(input, cwd, exit_status, None, true) } +pub fn run_command_with_output_and_get_it( + input: &[&dyn AsRef], + cwd: Option<&Path>, +) -> Result<(ExitStatus, String), String> { + let mut child = get_command_inner(input, cwd, None) + .stderr(Stdio::piped()) + .spawn() + .map_err(|e| command_error(input, &cwd, e))?; + + let stderr = child.stderr.take().expect("Failed to capture stderr"); + let mut captured = String::new(); + BufReader::new(stderr).read_to_string(&mut captured).expect("failed to read stderr"); + + let status = child.wait().map_err(|e| command_error(input, &cwd, e))?; + #[cfg(unix)] + { + if let Some(signal) = status.signal() { + // In case the signal didn't kill the current process. + return Err(command_error(input, &cwd, format!("Process received signal {signal}"))); + } + } + Ok((status, captured)) +} + pub fn run_command_with_output_and_env( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -124,7 +149,6 @@ pub fn run_command_with_output_and_env( check_exit_status(input, cwd, exit_status, None, true) } -#[cfg(not(unix))] pub fn run_command_with_output_and_env_no_err( input: &[&dyn AsRef], cwd: Option<&Path>, @@ -419,6 +443,34 @@ pub fn get_sysroot_dir() -> PathBuf { Path::new(crate::BUILD_DIR).join("build_sysroot") } +pub fn run_tool_and_install_it_if_not_present(cmd: &[&dyn AsRef]) -> Result<(), String> { + let (exit_status, stderr) = run_command_with_output_and_get_it(cmd, Some(Path::new(".")))?; + if exit_status.success() { + return Ok(()); + } + let mut iter = stderr.split('\n'); + if let Some(line) = iter.next() + && line.contains("is not installed for the toolchain") + && let Some(line) = iter.next() + && line.contains("run `rustup component add") + && let Some(cmd) = line.split('`').nth(1) + && let Some(tool_name) = cmd.rsplit(' ').next() + { + println!("`{tool_name}` is not installed for this toolchain, installing it..."); + // A weird round-about way to get a `&&str` so I can get a `&dyn AsRef` but + // as long as it works... + let cmd = cmd.split(' ').collect::>(); + let cmd = cmd.iter().map(|s: &&str| s as &dyn AsRef).collect::>(); + run_command_with_output(cmd.as_slice(), Some(Path::new(".")))?; + } else { + // If the component is installed, then it's something else. In this case we fail like we + // should have and let the user handles the error. + return check_exit_status(cmd, Some(Path::new(".")), exit_status, None, true); + } + // We retry the command... + run_command_with_output(cmd, Some(Path::new("."))) +} + #[cfg(test)] mod tests { use super::*; diff --git a/doc/subtree.md b/doc/subtree.md index a81b6c9c74bdd..fcac399e46542 100644 --- a/doc/subtree.md +++ b/doc/subtree.md @@ -1,7 +1,7 @@ # git subtree sync `rustc_codegen_gcc` is a subtree of the rust compiler. As such, it needs to be -sync from time to time to ensure changes that happened on their side are also +synced from time to time to ensure changes that happened on their side are also included on our side. ### How to install a forked git-subtree @@ -41,6 +41,8 @@ cd ../rust git pull origin master git checkout -b subtree-update_cg_gcc_YYYY-MM-DD PATH="$HOME/bin:$PATH" ~/bin/git-subtree pull --prefix=compiler/rustc_codegen_gcc/ https://github.com/rust-lang/rustc_codegen_gcc.git master +# Don't forget to update the `gcc` submodule to the same version as the +# one in `rustc_codegen_gcc/libgccjit.version`. git push # Immediately merge the merge commit into cg_gcc to prevent merge conflicts when syncing from rust-lang/rust later. diff --git a/example/mini_core_hello_world.rs b/example/mini_core_hello_world.rs index 6e155f89ee5cc..ab841d51a7f53 100644 --- a/example/mini_core_hello_world.rs +++ b/example/mini_core_hello_world.rs @@ -6,7 +6,7 @@ )] #![no_core] #![allow(dead_code, internal_features, non_camel_case_types)] -#![rustfmt_skip] +#![cfg_attr(rustfmt, rustfmt_skip)] extern crate mini_core; diff --git a/src/abi.rs b/src/abi.rs index 09e009700a80c..63eaf52ce9f01 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -146,12 +146,23 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { if attrs.regular.contains(rustc_target::callconv::ArgAttribute::NonNull) { non_null_args.push(arg_index as i32 + 1); } + // There are a few others `ArgAttribute` variants" + // + // * ArgAttribute::ReadOnly: `access(read_only())`, but it's only used for emitting + // warning, not for optimization. + // * ArgAttribute::NoUndef: No equivalent in GCC + // * ArgAttribute::Writable: `access(read_write())` or `access(write_only())`, but it's + // only used for emitting warning, not for optimization. + // * ArgAttribute::NoFree: No equivalent in GCC ty }; #[cfg(not(feature = "master"))] let apply_attrs = |ty: Type<'gcc>, _attrs: &ArgAttributes, _arg_index: usize| ty; - for arg in self.args.iter() { + for (source_arg_index, arg) in self.args.iter().enumerate() { + #[cfg(not(feature = "master"))] + let _ = source_arg_index; + let arg_ty = match arg.mode { PassMode::Ignore => continue, PassMode::Pair(a, b) => { @@ -179,9 +190,31 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_attrs(ty, &cast.attrs, argument_tys.len()) } PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { - // This is a "byval" argument, so we don't apply the `restrict` attribute on it. - on_stack_param_indices.insert(argument_tys.len()); - arg.layout.gcc_type(cx) + let x86_interrupt_first_arg = { + #[cfg(feature = "master")] + { + source_arg_index == 0 + && matches!(self.conv, CanonAbi::Interrupt(InterruptKind::X86)) + } + #[cfg(not(feature = "master"))] + { + false + } + }; + + if x86_interrupt_first_arg { + // Rust lowers the first `x86-interrupt` argument as a byval stack slot. + // LLVM represents that as a pointer parameter with `byval`; GCC's + // interrupt attribute likewise requires a pointer-shaped first parameter. + // Do not add this parameter to `on_stack_param_indices`: that set is only + // needed when GCC represents a byval argument as a value parameter, while + // this parameter is already pointer-shaped. + cx.type_ptr_to(arg.layout.gcc_type(cx)) + } else { + // This is a "byval" argument, so we don't apply the `restrict` attribute on it. + on_stack_param_indices.insert(argument_tys.len()); + arg.layout.gcc_type(cx) + } } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) diff --git a/src/asm.rs b/src/asm.rs index e84cf54cb1147..75a48c217c49b 100644 --- a/src/asm.rs +++ b/src/asm.rs @@ -297,7 +297,9 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { out_place, }); - if !readwrite { + if readwrite { + self.llbb().add_assignment(None, tmp_var, in_value.immediate()); + } else { let out_gcc_idx = outputs.len() - 1; let constraint = Cow::Owned(out_gcc_idx.to_string()); @@ -363,7 +365,14 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { let ty = value.layout.gcc_type(self.cx); let reg_var = self.current_func().new_local(None, ty, "input_register"); reg_var.set_register_name(reg_name); - self.llbb().add_assignment(None, reg_var, value.immediate()); + // FIXME: We should remove this when switching to "untyped" pointers + let value = value.immediate(); + let value = if value.get_type() != ty { + self.context.new_cast(None, value, ty) + } else { + value + }; + self.llbb().add_assignment(None, reg_var, value); inputs.push(AsmInOperand { constraint: "r".into(), @@ -602,6 +611,12 @@ impl<'a, 'gcc, 'tcx> AsmBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tcx> { self.llbb().add_eval(None, self.context.new_call(None, builtin_unreachable, &[])); } + if !options.contains(InlineAsmOptions::NORETURN) + && let Some(dest) = dest + { + self.switch_to_block(dest); + } + // Write results to outputs. // // We need to do this because: diff --git a/src/attributes.rs b/src/attributes.rs index 87c989031678d..41db5e83bdcc9 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -2,6 +2,8 @@ use gccjit::FnAttribute; use gccjit::Function; #[cfg(feature = "master")] +use rustc_abi::{CanonAbi, InterruptKind}; +#[cfg(feature = "master")] use rustc_hir::attrs::InlineAttr; use rustc_hir::attrs::InstructionSetAttr; #[cfg(feature = "master")] @@ -9,6 +11,7 @@ use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] use rustc_middle::mir::TerminatorKind; use rustc_middle::ty; +use rustc_target::callconv::FnAbi; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -84,12 +87,23 @@ fn inline_attr<'gcc, 'tcx>( } } +#[cfg(feature = "master")] +fn is_x86_interrupt<'tcx>(fn_abi: Option<&FnAbi<'tcx, ty::Ty<'tcx>>>) -> bool { + matches!( + fn_abi, + Some(fn_abi) if matches!(fn_abi.conv, CanonAbi::Interrupt(InterruptKind::X86)) + ) +} + /// Composite function which sets GCC attributes for function depending on its AST (`#[attribute]`) /// attributes. pub fn from_fn_attrs<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, #[cfg_attr(not(feature = "master"), expect(unused_variables))] func: Function<'gcc>, instance: ty::Instance<'tcx>, + #[cfg_attr(not(feature = "master"), expect(unused_variables))] fn_abi: Option< + &FnAbi<'tcx, ty::Ty<'tcx>>, + >, ) { let codegen_fn_attrs = cx.tcx.codegen_instance_attrs(instance.def); @@ -132,6 +146,11 @@ pub fn from_fn_attrs<'gcc, 'tcx>( } } + #[cfg(feature = "master")] + let x86_interrupt = is_x86_interrupt(fn_abi); + #[cfg(not(feature = "master"))] + let x86_interrupt = false; + let mut function_features = codegen_fn_attrs .target_features .iter() @@ -147,6 +166,13 @@ pub fn from_fn_attrs<'gcc, 'tcx>( // Check if GCC requires the same. let mut global_features = cx.tcx.sess.global_backend_features.iter().map(|s| s.as_str()); function_features.extend(&mut global_features); + if x86_interrupt { + // GCC does not preserve SSE, MMX, or x87 state in interrupt handlers and rejects + // them whenever those instruction sets are enabled, even if the handler does not + // emit such instructions. Restrict the function to general registers so the + // interrupt attribute works with the default x86_64 target features. + function_features.push("general-regs-only"); + } let target_features = function_features .iter() .filter_map(|feature| { diff --git a/src/back/lto.rs b/src/back/lto.rs index b0de1ead56ed1..baf1fda02e258 100644 --- a/src/back/lto.rs +++ b/src/back/lto.rs @@ -20,6 +20,7 @@ use std::ffi::CString; use std::fs::{self, File}; use std::path::{Path, PathBuf}; +use std::sync::Arc; use gccjit::OutputKind; use object::read::archive::ArchiveFile; @@ -29,9 +30,9 @@ use rustc_codegen_ssa::back::write::{CodegenContext, FatLtoInput, SharedEmitter} use rustc_codegen_ssa::traits::*; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::memmap::Mmap; -use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; use rustc_log::tracing::info; +use rustc_session::Session; use tempfile::{TempDir, tempdir}; use crate::back::write::{codegen, save_temp_bitcode}; @@ -103,8 +104,8 @@ fn save_as_file(obj: &[u8], path: &Path) -> Result<(), LtoBitcodeFromRlib> { /// Performs fat LTO by merging all modules into a single one and returning it /// for further optimization. pub(crate) fn run_fat( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, shared_emitter: &SharedEmitter, each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, @@ -115,8 +116,8 @@ pub(crate) fn run_fat( /*let symbols_below_threshold = lto_data.symbols_below_threshold.iter().map(|c| c.as_ptr()).collect::>();*/ fat_lto( + sess, cgcx, - prof, dcx, modules, lto_data.upstream_modules, @@ -126,15 +127,15 @@ pub(crate) fn run_fat( } fn fat_lto( + sess: &Session, cgcx: &CodegenContext, - prof: &SelfProfilerRef, dcx: DiagCtxtHandle<'_>, modules: Vec>, mut serialized_modules: Vec<(SerializedModule, CString)>, tmp_path: TempDir, //symbols_below_threshold: &[String], ) -> CompiledModule { - let _timer = prof.generic_activity("GCC_fat_lto_build_monolithic_module"); + let _timer = sess.prof.generic_activity("GCC_fat_lto_build_monolithic_module"); info!("going for a fat lto"); // Sort out all our lists of incoming modules into two lists. @@ -184,17 +185,16 @@ fn fat_lto( // module and create a linker with it. let mut module: ModuleCodegen = match costliest_module { Some((_cost, i)) => in_memory.remove(i), - None => { - unimplemented!("Incremental"); - /*assert!(!serialized_modules.is_empty(), "must have at least one serialized module"); - let (buffer, name) = serialized_modules.remove(0); - info!("no in-memory regular modules to choose from, parsing {:?}", name); - ModuleCodegen { - module_llvm: GccContext::parse(cgcx, &name, buffer.data(), dcx)?, - name: name.into_string().unwrap(), - kind: ModuleKind::Regular, - }*/ - } + None => ModuleCodegen::new_regular( + "lto_module".to_string(), + GccContext { + context: Arc::new(SyncContext::new(new_context(sess))), + relocation_model: sess.relocation_model(), + lto_supported: true, + lto_mode: LtoMode::None, + temp_dir: None, + }, + ), }; { info!("using {:?} as a base module", module.name); @@ -221,7 +221,8 @@ fn fat_lto( // We add the object files and save in should_combine_object_files that we should combine // them into a single object file when compiling later. for (bc_decoded, name) in serialized_modules { - let _timer = prof + let _timer = sess + .prof .generic_activity_with_arg_recorder("GCC_fat_lto_link_module", |recorder| { recorder.record_arg(format!("{:?}", name)) }); @@ -259,7 +260,7 @@ fn fat_lto( // of now. module.module_llvm.temp_dir = Some(tmp_path); - codegen(cgcx, prof, dcx, module, &cgcx.module_config) + codegen(cgcx, &sess.prof, dcx, module, &cgcx.module_config) } pub struct ModuleBuffer(PathBuf); diff --git a/src/back/write.rs b/src/back/write.rs index cf5514412f745..1f4fd8a314ad2 100644 --- a/src/back/write.rs +++ b/src/back/write.rs @@ -11,8 +11,8 @@ use rustc_log::tracing::debug; use rustc_session::config::OutputType; use rustc_target::spec::SplitDebuginfo; -use crate::base::add_pic_option; use crate::diagnostics::CopyBitcode; +use crate::gcc_util::add_pic_option; use crate::{GccContext, LtoMode}; pub(crate) fn codegen( @@ -60,9 +60,6 @@ pub(crate) fn codegen( let _timer = prof .generic_activity_with_arg("GCC_module_codegen_embed_bitcode", &*module.name); if lto_supported { - // FIXME(antoyo): maybe we should call embed_bitcode to have the proper iOS fixes? - //embed_bitcode(cgcx, llcx, llmod, &config.bc_cmdline, data); - context.add_command_line_option("-flto=auto"); context.add_command_line_option("-flto-partition=one"); context.add_command_line_option("-ffat-lto-objects"); diff --git a/src/base.rs b/src/base.rs index 7cb734d523273..436a9e5227352 100644 --- a/src/base.rs +++ b/src/base.rs @@ -1,5 +1,3 @@ -use std::collections::HashSet; -use std::env; use std::sync::Arc; use std::time::Instant; @@ -19,7 +17,6 @@ use rustc_session::config::DebugInfo; use rustc_span::Symbol; #[cfg(feature = "master")] use rustc_target::spec::SymbolVisibility; -use rustc_target::spec::{Arch, RelocModel}; use crate::builder::Builder; use crate::context::CodegenCx; @@ -144,41 +141,7 @@ pub fn compile_codegen_unit( ) -> ModuleCodegen { let cgu = tcx.codegen_unit(cgu_name); // Instantiate monomorphizations without filling out definitions yet... - let context = new_context(tcx); - - if tcx.sess.panic_strategy().unwinds() { - context.add_command_line_option("-fexceptions"); - context.add_driver_option("-fexceptions"); - } - - let disabled_features: HashSet<_> = tcx - .sess - .opts - .cg - .target_feature - .split(',') - .filter(|feature| feature.starts_with('-')) - .map(|string| &string[1..]) - .collect(); - - if !disabled_features.contains("avx") && tcx.sess.target.arch == Arch::X86_64 { - // NOTE: we always enable AVX because the equivalent of llvm.x86.sse2.cmp.pd in GCC for - // SSE2 is multiple builtins, so we use the AVX __builtin_ia32_cmppd instead. - // FIXME(antoyo): use the proper builtins for llvm.x86.sse2.cmp.pd and similar. - context.add_command_line_option("-mavx"); - } - - for arg in &tcx.sess.opts.cg.llvm_args { - context.add_command_line_option(arg); - } - // NOTE: This is needed to compile the file src/intrinsic/archs.rs during a bootstrap of rustc. - context.add_command_line_option("-fno-var-tracking-assignments"); - // NOTE: an optimization (https://github.com/rust-lang/rustc_codegen_gcc/issues/53). - context.add_command_line_option("-fno-semantic-interposition"); - // NOTE: Rust relies on LLVM not doing TBAA (https://github.com/rust-lang/unsafe-code-guidelines/issues/292). - context.add_command_line_option("-fno-strict-aliasing"); - // NOTE: Rust relies on LLVM doing wrapping on overflow. - context.add_command_line_option("-fwrapv"); + let context = new_context(tcx.sess); // NOTE: We need to honor the `#![no_builtins]` attribute to prevent GCC from // replacing code patterns (like loops) with calls to builtins (like memset). @@ -191,64 +154,6 @@ pub fn compile_codegen_unit( context.add_command_line_option("-fno-tree-loop-distribute-patterns"); } - if let Some(model) = tcx.sess.code_model() { - use rustc_target::spec::CodeModel; - - context.add_command_line_option(match model { - CodeModel::Tiny => "-mcmodel=tiny", - CodeModel::Small => "-mcmodel=small", - CodeModel::Kernel => "-mcmodel=kernel", - CodeModel::Medium => "-mcmodel=medium", - CodeModel::Large => "-mcmodel=large", - }); - } - - add_pic_option(&context, tcx.sess.relocation_model()); - - let target_cpu = gcc_util::target_cpu(tcx.sess); - if target_cpu != "generic" { - context.add_command_line_option(format!("-march={}", target_cpu)); - } - - if tcx - .sess - .opts - .unstable_opts - .function_sections - .unwrap_or(tcx.sess.target.function_sections) - { - context.add_command_line_option("-ffunction-sections"); - context.add_command_line_option("-fdata-sections"); - } - - if env::var("CG_GCCJIT_DUMP_RTL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-vregs"); - } - if env::var("CG_GCCJIT_DUMP_RTL_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-rtl-all"); - } - if env::var("CG_GCCJIT_DUMP_TREE_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-tree-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_IPA_ALL").as_deref() == Ok("1") { - context.add_command_line_option("-fdump-ipa-all-eh"); - } - if env::var("CG_GCCJIT_DUMP_CODE").as_deref() == Ok("1") { - context.set_dump_code_on_compile(true); - } - if env::var("CG_GCCJIT_DUMP_GIMPLE").as_deref() == Ok("1") { - context.set_dump_initial_gimple(true); - } - if env::var("CG_GCCJIT_DUMP_EVERYTHING").as_deref() == Ok("1") { - context.set_dump_everything(true); - } - if env::var("CG_GCCJIT_KEEP_INTERMEDIATES").as_deref() == Ok("1") { - context.set_keep_intermediates(true); - } - if env::var("CG_GCCJIT_VERBOSE").as_deref() == Ok("1") { - context.add_driver_option("-v"); - } - // NOTE: The codegen generates unreachable blocks. context.set_allow_unreachable_blocks(true); @@ -317,24 +222,3 @@ pub fn compile_codegen_unit( (module, cost) } - -pub fn add_pic_option<'gcc>(context: &Context<'gcc>, relocation_model: RelocModel) { - match relocation_model { - rustc_target::spec::RelocModel::Static => { - context.add_command_line_option("-fno-pie"); - context.add_driver_option("-fno-pie"); - } - rustc_target::spec::RelocModel::Pic => { - context.add_command_line_option("-fPIC"); - // NOTE: we use both add_command_line_option and add_driver_option because the usage in - // this module (compile_codegen_unit) requires add_command_line_option while the usage - // in the back::write module (codegen) requires add_driver_option. - context.add_driver_option("-fPIC"); - } - rustc_target::spec::RelocModel::Pie => { - context.add_command_line_option("-fPIE"); - context.add_driver_option("-fPIE"); - } - model => eprintln!("Unsupported relocation model: {:?}", model), - } -} diff --git a/src/builder.rs b/src/builder.rs index 6de2827e63dee..a1eab8f448990 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -4,8 +4,8 @@ use std::convert::TryFrom; use std::ops::Deref; use gccjit::{ - BinaryOp, Block, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, Type, - UnaryOp, + BinaryOp, Block, CType, ComparisonOp, Context, Function, LValue, Location, RValue, ToRValue, + Type, UnaryOp, }; use rustc_abi as abi; use rustc_abi::{Align, HasDataLayout, Size, TargetDataLayout, WrappingRange}; @@ -118,7 +118,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { ); let previous_var = func.new_local(self.location, previous_value.get_type(), "previous_value"); - let return_value = func.new_local(self.location, previous_value.get_type(), "return_value"); + let return_value = self.new_temp(func, self.location, previous_value.get_type()); self.llbb().add_assignment(self.location, previous_var, previous_value); self.llbb().add_assignment(self.location, return_value, previous_var.to_rvalue()); @@ -389,29 +389,27 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { func: Function<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let args = self.check_call("call", func, args); + let call = self.cx.context.new_call(self.location, func, &args); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = func.get_return_type(); let void_type = self.context.new_type::<()>(); let current_func = self.block.get_function(); if return_type != void_type { - let result = current_func.new_local( - self.location, - return_type, - format!("returnValue{}", self.next_value_counter()), - ); - self.block.add_assignment( - self.location, - result, - self.cx.context.new_call(self.location, func, &args), - ); + let result = self.new_temp(current_func, self.location, return_type); + self.block.add_assignment(self.location, result, call); result.to_rvalue() } else { - self.block - .add_eval(self.location, self.cx.context.new_call(self.location, func, &args)); + self.block.add_eval(self.location, call); // Return dummy value when not having return value. self.context.new_rvalue_zero(self.isize_type) } @@ -424,6 +422,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { mut func_ptr: RValue<'gcc>, args: &[RValue<'gcc>], _funclet: Option<&Funclet>, + must_tail: bool, ) -> RValue<'gcc> { let func_ptr_type = { let func_ptr_type = func_ptr.get_type(); @@ -448,6 +447,12 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let args_adjusted = args.len() != previous_arg_count; let args = self.check_ptr_call("call", func_ptr, &args, &on_stack_param_indices); + if must_tail { + // Return the bare tail call, don't assign or `add_eval` it yet. + let call = self.cx.context.new_call_through_ptr(self.location, func_ptr, &args); + return call; + } + // gccjit requires to use the result of functions, even when it's not used. // That's why we assign the result to a local or call add_eval(). let return_type = gcc_func.get_return_type(); @@ -464,11 +469,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { args_adjusted, orig_args, ); - let result = current_func.new_local( - self.location, - return_value.get_type(), - format!("ptrReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_value.get_type()); self.block.add_assignment(self.location, result, return_value); result.to_rvalue() } else { @@ -490,8 +491,16 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.location, self.cx.context.new_call_through_ptr(self.location, func_ptr, &args), ); - // Return dummy value when not having return value. - self.context.new_rvalue_zero(self.isize_type) + // Return dummy value when not having return value, unless the intrinsic adapter + // needs to synthesize a non-void LLVM-level result from out-parameters. + llvm::adjust_intrinsic_return_value( + self, + self.context.new_rvalue_zero(self.isize_type), + &func_name, + &args, + args_adjusted, + orig_args, + ) } } @@ -506,11 +515,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let return_type = self.context.new_type::(); let current_func = self.block.get_function(); // FIXME(antoyo): return the new_call() directly? Since the overflow function has no side-effects. - let result = current_func.new_local( - self.location, - return_type, - format!("overflowReturnValue{}", self.next_value_counter()), - ); + let result = self.new_temp(current_func, self.location, return_type); self.block.add_assignment( self.location, result, @@ -642,6 +647,18 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { default_block: Block<'gcc>, cases: impl ExactSizeIterator)>, ) { + // A switch with no cases is equivalent to an unconditional jump to the + // default block. Such a `SwitchInt` (one with only an `otherwise` target) + // is normally simplified into a `goto`, but `-Z mir-preserve-ub` keeps it, + // so it can reach here with e.g. the `bool` discriminant produced by a + // range-pattern comparison. `gcc_jit_block_end_with_switch` rejects a + // discriminant that is not of integer type, so emit a plain jump instead + // of a (pointless) switch. + if cases.len() == 0 { + self.block.end_with_jump(self.location, default_block); + return; + } + let mut gcc_cases = vec![]; let typ = self.val_ty(value); // FIXME(FractalFir): This is a workaround for a libgccjit limitation. @@ -1070,11 +1087,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // the current basic block. Otherwise, it could be used in another basic block, causing a // dereference after a drop, for instance. let deref = ptr.dereference(self.location).to_rvalue(); - let loaded_value = function.new_local( - self.location, - aligned_type, - format!("loadedValue{}", self.next_value_counter()), - ); + let loaded_value = self.new_temp(function, self.location, aligned_type); block.add_assignment(self.location, loaded_value, deref); loaded_value.to_rvalue() } @@ -1193,7 +1206,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { let next_bb = self.append_sibling_block("repeat_loop_next"); let ptr_type = start.get_type(); - let current = self.llbb().get_function().new_local(self.location, ptr_type, "loop_var"); + let current = self.new_temp(self.llbb().get_function(), self.location, ptr_type); let current_val = current.to_rvalue(); self.assign(current, start); @@ -1567,7 +1580,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { mut else_val: RValue<'gcc>, ) -> RValue<'gcc> { let func = self.current_func(); - let variable = func.new_local(self.location, then_val.get_type(), "selectVar"); + let variable = self.new_temp(func, self.location, then_val.get_type()); let then_block = func.new_block("then"); let else_block = func.new_block("else"); let after_block = func.new_block("after"); @@ -1589,8 +1602,10 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { variable.to_rvalue() } - fn va_arg(&mut self, _list: RValue<'gcc>, _ty: Type<'gcc>) -> RValue<'gcc> { - unimplemented!(); + fn va_arg(&mut self, list: RValue<'gcc>, ty: Type<'gcc>) -> RValue<'gcc> { + let va_list_type = self.context.new_c_type(CType::VaList); + let list = self.context.new_cast(self.location, list, va_list_type.make_pointer()); + self.context.new_va_arg(self.location, list, ty) } #[cfg(feature = "master")] @@ -1705,11 +1720,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { #[cfg(not(feature = "master"))] fn cleanup_landing_pad(&mut self, _pers_fn: Function<'gcc>) -> (RValue<'gcc>, RValue<'gcc>) { let value1 = self - .current_func() - .new_local(self.location, self.u8_type.make_pointer(), "landing_pad0") + .new_temp(self.current_func(), self.location, self.u8_type.make_pointer()) .to_rvalue(); - let value2 = - self.current_func().new_local(self.location, self.i32_type, "landing_pad1").to_rvalue(); + let value2 = self.new_temp(self.current_func(), self.location, self.i32_type).to_rvalue(); (value1, value2) } @@ -1772,7 +1785,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { // NOTE: since success contains the call to the intrinsic, it must be added to the basic block before // expected so that we store expected after the call. - let success_var = self.current_func().new_local(self.location, self.bool_type, "success"); + let success_var = self.new_temp(self.current_func(), self.location, self.bool_type); self.llbb().add_assignment(self.location, success_var, success); (expected.to_rvalue(), success_var.to_rvalue()) @@ -1867,7 +1880,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> { fn tail_call( &mut self, - _llty: Self::Type, + llty: Self::Type, _fn_attrs: Option<&CodegenFnAttrs>, fn_abi: &FnAbi<'tcx, Ty<'tcx>>, llfn: Self::Value, @@ -2475,11 +2488,31 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { self.bitcast_if_needed(res, result_type) } + /// Create a temporary variable. + /// + /// GCC will use more stack space with a local variable than with a temporary variable in debug mode, + /// so in order to avoid having the stack probe test fail in CI, we avoid creating local variables for temporaries. + pub fn new_temp( + &self, + function: Function<'gcc>, + location: Option>, + typ: Type<'gcc>, + ) -> LValue<'gcc> { + #[cfg(feature = "master")] + { + function.new_temp(location, typ) + } + #[cfg(not(feature = "master"))] + { + function.new_local(location, typ, format!("temp{}", self.next_value_counter())) + } + } + // GCC doesn't like deeply nested expressions. // By assigning intermediate expressions to a variable, this allow us to avoid deeply nested // expressions and GCC will use much less RAM. fn assign_to_var(&self, value: RValue<'gcc>) -> RValue<'gcc> { - let var = self.current_func().new_local(self.location, value.get_type(), "opResult"); + let var = self.new_temp(self.current_func(), self.location, value.get_type()); self.llbb().add_assignment(self.location, var, value); var.to_rvalue() } diff --git a/src/callee.rs b/src/callee.rs index 00f095ed54371..d3f412180da55 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -70,7 +70,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) cx.linkage.set(FunctionType::Extern); let func = cx.declare_fn(sym, fn_abi); - attributes::from_fn_attrs(cx, func, instance); + attributes::from_fn_attrs(cx, func, instance, Some(fn_abi)); #[cfg(feature = "master")] { diff --git a/src/consts.rs b/src/consts.rs index e6acbc6625d44..8576dfe079163 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -171,29 +171,52 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { } // Wasm statics with custom link sections get special treatment as they - // go into custom sections of the wasm executable. - if self.tcx.sess.target.is_like_wasm { + // go into custom sections of the wasm executable. The exception to this + // is the `.init_array` section which are treated specially by the wasm linker. + if self.tcx.sess.target.is_like_wasm + && attrs + .link_section + .map(|link_section| !link_section.as_str().starts_with(".init_array")) + .unwrap_or(true) + { if let Some(_section) = attrs.link_section { unimplemented!(); } - } else { - // FIXME(antoyo): set link section. + } else if let Some(_section) = attrs.link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(_section.as_str())); } - if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) - || attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) - { - self.add_used_global(global.to_rvalue()); + if attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER)); + self.add_used_global(global); + } + if attrs.flags.contains(CodegenFnAttrFlags::USED_LINKER) { + // To copy the conditions from the LLVM backend... + assert!(!attrs.flags.contains(CodegenFnAttrFlags::USED_COMPILER)); + self.add_retained_global(global); } } } impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { - /// Add a global value to a list to be stored in the `llvm.used` variable, an array of i8*. - pub fn add_used_global(&mut self, _global: RValue<'gcc>) { - // FIXME(antoyo) + /// Need to have the `SHF_GNU_RETAIN` flag, so needs to use the `retain` attribute instead of + /// `used`. This is used by `#[used(linker)]`. + pub fn add_retained_global(&mut self, global: LValue<'gcc>) { + // We need to add the `used` C attribute in any case. + self.add_used_global(global); + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Retain); + } + + /// This is used by `#[used(compiler)]` and `#[used]`. + pub fn add_used_global(&mut self, _global: LValue<'gcc>) { + #[cfg(feature = "master")] + _global.add_attribute(VarAttribute::Used); } + // No need to have the `SHF_GNU_RETAIN` flag, so `used` attribute is ok. #[cfg_attr(not(feature = "master"), expect(unused_variables))] pub fn add_used_function(&self, function: Function<'gcc>) { #[cfg(feature = "master")] diff --git a/src/declare.rs b/src/declare.rs index a9503574a03ed..32bb7c3aa349e 100644 --- a/src/declare.rs +++ b/src/declare.rs @@ -1,12 +1,12 @@ #[cfg(feature = "master")] -use gccjit::{FnAttribute, ToRValue}; +use gccjit::{FnAttribute, ToRValue, VarAttribute}; use gccjit::{Function, FunctionType, GlobalKind, LValue, RValue, Type}; use rustc_codegen_ssa::traits::BaseTypeCodegenMethods; use rustc_middle::ty::Ty; use rustc_span::Symbol; use rustc_target::callconv::FnAbi; -use crate::abi::{FnAbiGcc, FnAbiGccExt}; +use crate::abi::FnAbiGccExt; use crate::context::CodegenCx; impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { @@ -25,6 +25,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } global @@ -74,6 +77,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { global.set_tls_model(self.tls_model); } if let Some(link_section) = link_section { + #[cfg(feature = "master")] + global.add_attribute(VarAttribute::Section(link_section.as_str())); + #[cfg(not(feature = "master"))] global.set_link_section(link_section.as_str()); } let global_address = global.get_address(None); @@ -111,22 +117,22 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { } pub fn declare_fn(&self, name: &str, fn_abi: &FnAbi<'tcx, Ty<'tcx>>) -> Function<'gcc> { - let FnAbiGcc { - return_type, - arguments_type, - is_c_variadic, - on_stack_param_indices, - #[cfg(feature = "master")] - fn_attributes, - } = fn_abi.gcc_type(self); + let fn_abi_gcc = fn_abi.gcc_type(self); #[cfg(feature = "master")] let conv = fn_abi.gcc_cconv(self); #[cfg(not(feature = "master"))] let conv = None; - let func = declare_raw_fn(self, name, conv, return_type, &arguments_type, is_c_variadic); - self.on_stack_function_params.borrow_mut().insert(func, on_stack_param_indices); + let func = declare_raw_fn( + self, + name, + conv, + fn_abi_gcc.return_type, + &fn_abi_gcc.arguments_type, + fn_abi_gcc.is_c_variadic, + ); + self.on_stack_function_params.borrow_mut().insert(func, fn_abi_gcc.on_stack_param_indices); #[cfg(feature = "master")] - for fn_attr in fn_attributes { + for fn_attr in fn_abi_gcc.fn_attributes { func.add_attribute(fn_attr); } func diff --git a/src/diagnostics.rs b/src/diagnostics.rs index de633d3bdde79..67723ebd2f30b 100644 --- a/src/diagnostics.rs +++ b/src/diagnostics.rs @@ -20,10 +20,6 @@ pub(crate) struct LtoBitcodeFromRlib { pub gcc_err: String, } -#[derive(Diagnostic)] -#[diag("explicit tail calls with the 'become' keyword are not implemented in the GCC backend")] -pub(crate) struct ExplicitTailCallsUnsupported; - #[derive(Diagnostic)] #[diag("asm contains a NUL byte")] pub(crate) struct NulBytesInAsm { diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4b0fef32cac03..0628171e488b3 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -4,7 +4,7 @@ use std::env; use gccjit::Context; #[cfg(feature = "master")] -use gccjit::Context; +use gccjit::Version; use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::config::NATIVE_CPU; diff --git a/src/int.rs b/src/int.rs index 021f05c666d46..4e4b911666143 100644 --- a/src/int.rs +++ b/src/int.rs @@ -457,7 +457,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { if self.is_non_native_int_type(a_type) || self.is_non_native_int_type(b_type) { // This algorithm is based on compiler-rt's __cmpti2: // https://github.com/llvm-mirror/compiler-rt/blob/f0745e8476f069296a7c71accedd061dce4cdf79/lib/builtins/cmpti2.c#L21 - let result = self.current_func().new_local(self.location, self.int_type, "icmp_result"); + let result = self.new_temp(self.current_func(), self.location, self.int_type); let block1 = self.current_func().new_block("block1"); let block2 = self.current_func().new_block("block2"); let block3 = self.current_func().new_block("block3"); @@ -636,9 +636,17 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { rhs = self.context.new_cast(self.location, rhs, unsigned_type); } } - // FIXME(antoyo): we probably need to handle signed comparison for unsigned - // integers. - _ => (), + IntPredicate::IntSGT + | IntPredicate::IntSGE + | IntPredicate::IntSLT + | IntPredicate::IntSLE => { + if !a_type.is_vector() { + let signed_type = a_type.to_signed(self.cx); + lhs = self.context.new_cast(self.location, lhs, signed_type); + rhs = self.context.new_cast(self.location, rhs, signed_type); + } + } + IntPredicate::IntEQ | IntPredicate::IntNE => (), } self.context.new_comparison(self.location, op.to_gcc_comparison(), lhs, rhs) } @@ -902,7 +910,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { self.bitwise_operation(BinaryOp::BitwiseOr, a, b, loc) } - // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/master/src/int/mod.rs#L379 instead? + // FIXME(antoyo): can we use https://github.com/rust-lang/compiler-builtins/blob/1a99c2aa295bb2d507fa0e67a3b5eef64fba92a0/libm/src/math/support/int_traits.rs#L485 instead? pub fn gcc_int_cast(&self, value: RValue<'gcc>, dest_typ: Type<'gcc>) -> RValue<'gcc> { let value_type = value.get_type(); if self.is_native_int_type_or_bool(dest_typ) && self.is_native_int_type_or_bool(value_type) diff --git a/src/intrinsic/archs.rs b/src/intrinsic/archs.rs index 3c1698df6dec2..1856c2468616d 100644 --- a/src/intrinsic/archs.rs +++ b/src/intrinsic/archs.rs @@ -24,6 +24,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "gcsss" => "__builtin_arm_gcsss", "isb" => "__builtin_arm_isb", "prefetch" => "__builtin_arm_prefetch", + "prefetch.ir" => "__builtin_arm_prefetch_ir", "range.prefetch" => "__builtin_arm_range_prefetch", "sme.in.streaming.mode" => "__builtin_arm_in_streaming_mode", "sve.aesd" => "__builtin_sve_svaesd_u8", @@ -53,6 +54,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "alignbyte" => "__builtin_amdgcn_alignbyte", "ashr.pk.i8.i32" => "__builtin_amdgcn_ashr_pk_i8_i32", "ashr.pk.u8.i32" => "__builtin_amdgcn_ashr_pk_u8_i32", + "asyncmark" => "__builtin_amdgcn_asyncmark", "buffer.wbinvl1" => "__builtin_amdgcn_buffer_wbinvl1", "buffer.wbinvl1.sc" => "__builtin_amdgcn_buffer_wbinvl1_sc", "buffer.wbinvl1.vol" => "__builtin_amdgcn_buffer_wbinvl1_vol", @@ -270,6 +272,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fdot2c.f32.bf16" => "__builtin_amdgcn_fdot2c_f32_bf16", "flat.prefetch" => "__builtin_amdgcn_flat_prefetch", "fmul.legacy" => "__builtin_amdgcn_fmul_legacy", + "global.load.async.lds" => "__builtin_amdgcn_global_load_async_lds", "global.load.async.to.lds.b128" => { "__builtin_amdgcn_global_load_async_to_lds_b128" } @@ -361,11 +364,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "perm.pk16.b4.u4" => "__builtin_amdgcn_perm_pk16_b4_u4", "perm.pk16.b6.u4" => "__builtin_amdgcn_perm_pk16_b6_u4", "perm.pk16.b8.u4" => "__builtin_amdgcn_perm_pk16_b8_u4", - "permlane.bcast" => "__builtin_amdgcn_permlane_bcast", - "permlane.down" => "__builtin_amdgcn_permlane_down", "permlane.idx.gen" => "__builtin_amdgcn_permlane_idx_gen", - "permlane.up" => "__builtin_amdgcn_permlane_up", - "permlane.xor" => "__builtin_amdgcn_permlane_xor", "permlane16.var" => "__builtin_amdgcn_permlane16_var", "permlanex16.var" => "__builtin_amdgcn_permlanex16_var", "pk.add.max.i16" => "__builtin_amdgcn_pk_add_max_i16", @@ -375,6 +374,9 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "prng.b32" => "__builtin_amdgcn_prng_b32", "qsad.pk.u16.u8" => "__builtin_amdgcn_qsad_pk_u16_u8", "queue.ptr" => "__builtin_amdgcn_queue_ptr", + "raw.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_raw_ptr_buffer_load_async_lds" + } "raw.ptr.buffer.load.lds" => "__builtin_amdgcn_raw_ptr_buffer_load_lds", "rcp.legacy" => "__builtin_amdgcn_rcp_legacy", "rsq.legacy" => "__builtin_amdgcn_rsq_legacy", @@ -386,6 +388,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.barrier.signal.isfirst" => "__builtin_amdgcn_s_barrier_signal_isfirst", "s.barrier.signal.var" => "__builtin_amdgcn_s_barrier_signal_var", "s.barrier.wait" => "__builtin_amdgcn_s_barrier_wait", + "s.bitreplicate" => "__builtin_amdgcn_s_bitreplicate", "s.buffer.prefetch.data" => "__builtin_amdgcn_s_buffer_prefetch_data", "s.cluster.barrier" => "__builtin_amdgcn_s_cluster_barrier", "s.dcache.inv" => "__builtin_amdgcn_s_dcache_inv", @@ -412,6 +415,7 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "s.ttracedata" => "__builtin_amdgcn_s_ttracedata", "s.ttracedata.imm" => "__builtin_amdgcn_s_ttracedata_imm", "s.wait.asynccnt" => "__builtin_amdgcn_s_wait_asynccnt", + "s.wait.event" => "__builtin_amdgcn_s_wait_event", "s.wait.event.export.ready" => "__builtin_amdgcn_s_wait_event_export_ready", "s.wait.tensorcnt" => "__builtin_amdgcn_s_wait_tensorcnt", "s.waitcnt" => "__builtin_amdgcn_s_waitcnt", @@ -462,16 +466,18 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "smfmac.i32.16x16x64.i8" => "__builtin_amdgcn_smfmac_i32_16x16x64_i8", "smfmac.i32.32x32x32.i8" => "__builtin_amdgcn_smfmac_i32_32x32x32_i8", "smfmac.i32.32x32x64.i8" => "__builtin_amdgcn_smfmac_i32_32x32x64_i8", + "struct.ptr.buffer.load.async.lds" => { + "__builtin_amdgcn_struct_ptr_buffer_load_async_lds" + } "struct.ptr.buffer.load.lds" => "__builtin_amdgcn_struct_ptr_buffer_load_lds", "sudot4" => "__builtin_amdgcn_sudot4", "sudot8" => "__builtin_amdgcn_sudot8", "tensor.load.to.lds" => "__builtin_amdgcn_tensor_load_to_lds", - "tensor.load.to.lds.d2" => "__builtin_amdgcn_tensor_load_to_lds_d2", "tensor.store.from.lds" => "__builtin_amdgcn_tensor_store_from_lds", - "tensor.store.from.lds.d2" => "__builtin_amdgcn_tensor_store_from_lds_d2", "udot2" => "__builtin_amdgcn_udot2", "udot4" => "__builtin_amdgcn_udot4", "udot8" => "__builtin_amdgcn_udot8", + "wait.asyncmark" => "__builtin_amdgcn_wait_asyncmark", "wave.barrier" => "__builtin_amdgcn_wave_barrier", "wavefrontsize" => "__builtin_amdgcn_wavefrontsize", "workgroup.id.x" => "__builtin_amdgcn_workgroup_id_x", @@ -4844,7 +4850,11 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "add.rn.f" => "__nvvm_add_rn_f", "add.rn.ftz.f" => "__nvvm_add_rn_ftz_f", "add.rn.ftz.sat.f" => "__nvvm_add_rn_ftz_sat_f", + "add.rn.ftz.sat.f16" => "__nvvm_add_rn_ftz_sat_f16", + "add.rn.ftz.sat.v2f16" => "__nvvm_add_rn_ftz_sat_v2f16", "add.rn.sat.f" => "__nvvm_add_rn_sat_f", + "add.rn.sat.f16" => "__nvvm_add_rn_sat_f16", + "add.rn.sat.v2f16" => "__nvvm_add_rn_sat_v2f16", "add.rp.d" => "__nvvm_add_rp_d", "add.rp.f" => "__nvvm_add_rp_f", "add.rp.ftz.f" => "__nvvm_add_rp_ftz_f", @@ -5063,18 +5073,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "fma.rn.bf16x2" => "__nvvm_fma_rn_bf16x2", "fma.rn.d" => "__nvvm_fma_rn_d", "fma.rn.f" => "__nvvm_fma_rn_f", - "fma.rn.ftz.bf16" => "__nvvm_fma_rn_ftz_bf16", - "fma.rn.ftz.bf16x2" => "__nvvm_fma_rn_ftz_bf16x2", "fma.rn.ftz.f" => "__nvvm_fma_rn_ftz_f", - "fma.rn.ftz.relu.bf16" => "__nvvm_fma_rn_ftz_relu_bf16", - "fma.rn.ftz.relu.bf16x2" => "__nvvm_fma_rn_ftz_relu_bf16x2", - "fma.rn.ftz.sat.bf16" => "__nvvm_fma_rn_ftz_sat_bf16", - "fma.rn.ftz.sat.bf16x2" => "__nvvm_fma_rn_ftz_sat_bf16x2", "fma.rn.ftz.sat.f" => "__nvvm_fma_rn_ftz_sat_f", "fma.rn.relu.bf16" => "__nvvm_fma_rn_relu_bf16", "fma.rn.relu.bf16x2" => "__nvvm_fma_rn_relu_bf16x2", - "fma.rn.sat.bf16" => "__nvvm_fma_rn_sat_bf16", - "fma.rn.sat.bf16x2" => "__nvvm_fma_rn_sat_bf16x2", "fma.rn.sat.f" => "__nvvm_fma_rn_sat_f", "fma.rp.d" => "__nvvm_fma_rp_d", "fma.rp.f" => "__nvvm_fma_rp_f", @@ -5195,6 +5197,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "mul.rn.d" => "__nvvm_mul_rn_d", "mul.rn.f" => "__nvvm_mul_rn_f", "mul.rn.ftz.f" => "__nvvm_mul_rn_ftz_f", + "mul.rn.ftz.sat.f16" => "__nvvm_mul_rn_ftz_sat_f16", + "mul.rn.ftz.sat.v2f16" => "__nvvm_mul_rn_ftz_sat_v2f16", + "mul.rn.sat.f16" => "__nvvm_mul_rn_sat_f16", + "mul.rn.sat.v2f16" => "__nvvm_mul_rn_sat_v2f16", "mul.rp.d" => "__nvvm_mul_rp_d", "mul.rp.f" => "__nvvm_mul_rp_f", "mul.rp.ftz.f" => "__nvvm_mul_rp_ftz_f", @@ -5827,8 +5833,10 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vmuleuh" => "__builtin_altivec_vmuleuh", "altivec.vmuleuw" => "__builtin_altivec_vmuleuw", "altivec.vmulhsd" => "__builtin_altivec_vmulhsd", + "altivec.vmulhsh" => "__builtin_altivec_vmulhsh", "altivec.vmulhsw" => "__builtin_altivec_vmulhsw", "altivec.vmulhud" => "__builtin_altivec_vmulhud", + "altivec.vmulhuh" => "__builtin_altivec_vmulhuh", "altivec.vmulhuw" => "__builtin_altivec_vmulhuw", "altivec.vmulosb" => "__builtin_altivec_vmulosb", "altivec.vmulosd" => "__builtin_altivec_vmulosd", @@ -5912,22 +5920,45 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "altivec.vsum4shs" => "__builtin_altivec_vsum4shs", "altivec.vsum4ubs" => "__builtin_altivec_vsum4ubs", "altivec.vsumsws" => "__builtin_altivec_vsumsws", + "altivec.vucmprhb" => "__builtin_altivec_vucmprhb", + "altivec.vucmprhh" => "__builtin_altivec_vucmprhh", + "altivec.vucmprhn" => "__builtin_altivec_vucmprhn", + "altivec.vucmprlb" => "__builtin_altivec_vucmprlb", + "altivec.vucmprlh" => "__builtin_altivec_vucmprlh", + "altivec.vucmprln" => "__builtin_altivec_vucmprln", "altivec.vupkhpx" => "__builtin_altivec_vupkhpx", "altivec.vupkhsb" => "__builtin_altivec_vupkhsb", "altivec.vupkhsh" => "__builtin_altivec_vupkhsh", + "altivec.vupkhsntob" => "__builtin_altivec_vupkhsntob", "altivec.vupkhsw" => "__builtin_altivec_vupkhsw", + "altivec.vupkint4tobf16" => "__builtin_altivec_vupkint4tobf16", + "altivec.vupkint4tofp32" => "__builtin_altivec_vupkint4tofp32", + "altivec.vupkint8tobf16" => "__builtin_altivec_vupkint8tobf16", + "altivec.vupkint8tofp32" => "__builtin_altivec_vupkint8tofp32", "altivec.vupklpx" => "__builtin_altivec_vupklpx", "altivec.vupklsb" => "__builtin_altivec_vupklsb", "altivec.vupklsh" => "__builtin_altivec_vupklsh", + "altivec.vupklsntob" => "__builtin_altivec_vupklsntob", "altivec.vupklsw" => "__builtin_altivec_vupklsw", "amo.ldat" => "__builtin_amo_ldat", + "amo.ldat.cond" => "__builtin_amo_ldat_cond", + "amo.ldat.csne" => "__builtin_amo_ldat_csne", "amo.lwat" => "__builtin_amo_lwat", + "amo.lwat.cond" => "__builtin_amo_lwat_cond", + "amo.lwat.csne" => "__builtin_amo_lwat_csne", + "amo.stdat" => "__builtin_amo_stdat", + "amo.stwat" => "__builtin_amo_stwat", "bcdadd" => "__builtin_ppc_bcdadd", "bcdadd.p" => "__builtin_ppc_bcdadd_p", "bcdcopysign" => "__builtin_ppc_bcdcopysign", "bcdsetsign" => "__builtin_ppc_bcdsetsign", + "bcdshift" => "__builtin_ppc_bcdshift", + "bcdshiftround" => "__builtin_ppc_bcdshiftround", "bcdsub" => "__builtin_ppc_bcdsub", "bcdsub.p" => "__builtin_ppc_bcdsub_p", + "bcdtruncate" => "__builtin_ppc_bcdtruncate", + "bcdunsignedshift" => "__builtin_ppc_bcdunsignedshift", + "bcdunsignedtruncate" => "__builtin_ppc_bcdunsignedtruncate", "bpermd" => "__builtin_bpermd", "cbcdtd" => "__builtin_cbcdtd", "cbcdtdd" => "__builtin_ppc_cbcdtd", @@ -6126,6 +6157,27 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "vsx.xxinsertw" => "__builtin_vsx_xxinsertw", "vsx.xxleqv" => "__builtin_vsx_xxleqv", "vsx.xxpermx" => "__builtin_vsx_xxpermx", + "xsaddaddsuqm" => "__builtin_xsaddaddsuqm", + "xsaddadduqm" => "__builtin_xsaddadduqm", + "xsaddsubsuqm" => "__builtin_xsaddsubsuqm", + "xsaddsubuqm" => "__builtin_xsaddsubuqm", + "xsmerge2t1uqm" => "__builtin_xsmerge2t1uqm", + "xsmerge2t2uqm" => "__builtin_xsmerge2t2uqm", + "xsmerge2t3uqm" => "__builtin_xsmerge2t3uqm", + "xsmerge3t1uqm" => "__builtin_xsmerge3t1uqm", + "xsrebase2t1uqm" => "__builtin_xsrebase2t1uqm", + "xsrebase2t2uqm" => "__builtin_xsrebase2t2uqm", + "xsrebase2t3uqm" => "__builtin_xsrebase2t3uqm", + "xsrebase2t4uqm" => "__builtin_xsrebase2t4uqm", + "xsrebase3t1uqm" => "__builtin_xsrebase3t1uqm", + "xsrebase3t2uqm" => "__builtin_xsrebase3t2uqm", + "xsrebase3t3uqm" => "__builtin_xsrebase3t3uqm", + "xxmulmul" => "__builtin_xxmulmul", + "xxmulmulhiadd" => "__builtin_xxmulmulhiadd", + "xxmulmulloadd" => "__builtin_xxmulmulloadd", + "xxssumudm" => "__builtin_xxssumudm", + "xxssumudmc" => "__builtin_xxssumudmc", + "xxssumudmcext" => "__builtin_xxssumudmcext", "zoned2packed" => "__builtin_ppc_zoned2packed", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } @@ -6388,13 +6440,13 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { // spv "group.memory.barrier.with.group.sync" => "__builtin_spirv_group_barrier", "num.subgroups" => "__builtin_spirv_num_subgroups", + "subgroup.ballot" => "__builtin_spirv_subgroup_ballot", "subgroup.id" => "__builtin_spirv_subgroup_id", "subgroup.local.invocation.id" => { "__builtin_spirv_subgroup_local_invocation_id" } "subgroup.max.size" => "__builtin_spirv_subgroup_max_size", "subgroup.size" => "__builtin_spirv_subgroup_size", - "wave.ballot" => "__builtin_spirv_subgroup_ballot", _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), } } @@ -8661,10 +8713,6 @@ fn map_arch_intrinsic(full_name: &str) -> &'static str { "bmi.bextr.64" => "__builtin_ia32_bextr_u64", "bmi.bzhi.32" => "__builtin_ia32_bzhi_si", "bmi.bzhi.64" => "__builtin_ia32_bzhi_di", - "bmi.pdep.32" => "__builtin_ia32_pdep_si", - "bmi.pdep.64" => "__builtin_ia32_pdep_di", - "bmi.pext.32" => "__builtin_ia32_pext_si", - "bmi.pext.64" => "__builtin_ia32_pext_di", "cldemote" => "__builtin_ia32_cldemote", "clflushopt" => "__builtin_ia32_clflushopt", "clrssbsy" => "__builtin_ia32_clrssbsy", diff --git a/src/intrinsic/llvm.rs b/src/intrinsic/llvm.rs index f3134edb72cb9..ef381715c1ea2 100644 --- a/src/intrinsic/llvm.rs +++ b/src/intrinsic/llvm.rs @@ -475,6 +475,26 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( new_args.push(variable.get_address(None)); args = new_args.into(); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let old_args = args.to_vec(); + let mut new_args = vec![]; + let arg1_type = gcc_func.get_param_type(0); + let first_mask = + builder.current_func().new_local(None, arg1_type, "return_2intersect_arg1"); + let arg2_type = gcc_func.get_param_type(1); + let second_mask = + builder.current_func().new_local(None, arg2_type, "return_2intersect_arg2"); + new_args.push(first_mask.get_address(None)); + new_args.push(second_mask.get_address(None)); + new_args.push(old_args[0]); + new_args.push(old_args[1]); + args = new_args.into(); + } "__builtin_ia32_vpermt2varqi512_mask" | "__builtin_ia32_vpermt2varqi256_mask" | "__builtin_ia32_vpermt2varqi128_mask" @@ -486,6 +506,23 @@ pub fn adjust_intrinsic_arguments<'a, 'b, 'gcc, 'tcx>( let minus_one = builder.context.new_rvalue_from_int(arg4_type, -1); args = vec![new_args[1], new_args[0], new_args[2], minus_one].into(); } + "__builtin_ia32_fpclassph128_mask" + | "__builtin_ia32_fpclassph256_mask" + | "__builtin_ia32_fpclassph512_mask" + | "__builtin_ia32_fpclasspd128_mask" + | "__builtin_ia32_fpclassps128_mask" + | "__builtin_ia32_fpclasspd256_mask" + | "__builtin_ia32_fpclassps256_mask" + | "__builtin_ia32_fpclasspd512_mask" + | "__builtin_ia32_fpclassps512_mask" + | "__builtin_ia32_vpshufbitqmb128_mask" + | "__builtin_ia32_vpshufbitqmb256_mask" + | "__builtin_ia32_vpshufbitqmb512_mask" => { + let new_args = args.to_vec(); + let arg3_type = gcc_func.get_param_type(2); + let minus_one = builder.context.new_rvalue_from_int(arg3_type, -1); + args = vec![new_args[0], new_args[1], minus_one].into(); + } "__builtin_ia32_xrstor" | "__builtin_ia32_xrstor64" | "__builtin_ia32_xsavec" @@ -837,7 +874,7 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( "__builtin_ia32_rdrand64_step" => { let random_number = args[0].dereference(None).to_rvalue(); let success_variable = - builder.current_func().new_local(None, return_value.get_type(), "success"); + builder.new_temp(builder.current_func(), None, return_value.get_type()); builder.llbb().add_assignment(None, success_variable, return_value); let field1 = builder.context.new_field(None, random_number.get_type(), "random_number"); @@ -851,6 +888,25 @@ pub fn adjust_intrinsic_return_value<'a, 'gcc, 'tcx>( &[random_number, success_variable.to_rvalue()], ); } + "__builtin_ia32_2intersectd128" + | "__builtin_ia32_2intersectq128" + | "__builtin_ia32_2intersectd256" + | "__builtin_ia32_2intersectq256" + | "__builtin_ia32_2intersectd512" + | "__builtin_ia32_2intersectq512" => { + let first_mask = args[0].dereference(None).to_rvalue(); + let second_mask = args[1].dereference(None).to_rvalue(); + let field1 = builder.context.new_field(None, first_mask.get_type(), "first_mask"); + let field2 = builder.context.new_field(None, second_mask.get_type(), "second_mask"); + let struct_type = + builder.context.new_struct_type(None, "vp2intersect_result", &[field1, field2]); + return_value = builder.context.new_struct_constructor( + None, + struct_type.as_type(), + None, + &[first_mask, second_mask], + ); + } "fma" => { let f16_type = builder.context.new_c_type(CType::Float16); return_value = builder.context.new_cast(None, return_value, f16_type); @@ -1179,6 +1235,9 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.mask.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", "llvm.x86.avx512.mask.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", "llvm.x86.avx512.mask.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", + "llvm.x86.avx512.vpshufbitqmb.512" => "__builtin_ia32_vpshufbitqmb512_mask", + "llvm.x86.avx512.vpshufbitqmb.256" => "__builtin_ia32_vpshufbitqmb256_mask", + "llvm.x86.avx512.vpshufbitqmb.128" => "__builtin_ia32_vpshufbitqmb128_mask", "llvm.x86.avx512.mask.ucmp.w.512" => "__builtin_ia32_ucmpw512_mask", "llvm.x86.avx512.mask.ucmp.w.256" => "__builtin_ia32_ucmpw256_mask", "llvm.x86.avx512.mask.ucmp.w.128" => "__builtin_ia32_ucmpw128_mask", @@ -1336,11 +1395,20 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512bf16.cvtne2ps2bf16.128" => "__builtin_ia32_cvtne2ps2bf16_v8bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.256" => "__builtin_ia32_cvtne2ps2bf16_v16bf", "llvm.x86.avx512bf16.cvtne2ps2bf16.512" => "__builtin_ia32_cvtne2ps2bf16_v32bf", + "llvm.x86.vcvtneps2bf16128" => "__builtin_ia32_cvtneps2bf16_v4sf", + "llvm.x86.vcvtneps2bf16256" => "__builtin_ia32_cvtneps2bf16_v8sf", + "llvm.x86.avx512bf16.mask.cvtneps2bf16.128" => "__builtin_ia32_cvtneps2bf16_v4sf_mask", "llvm.x86.avx512bf16.cvtneps2bf16.256" => "__builtin_ia32_cvtneps2bf16_v8sf", "llvm.x86.avx512bf16.cvtneps2bf16.512" => "__builtin_ia32_cvtneps2bf16_v16sf", "llvm.x86.avx512bf16.dpbf16ps.128" => "__builtin_ia32_dpbf16ps_v4sf", "llvm.x86.avx512bf16.dpbf16ps.256" => "__builtin_ia32_dpbf16ps_v8sf", "llvm.x86.avx512bf16.dpbf16ps.512" => "__builtin_ia32_dpbf16ps_v16sf", + "llvm.x86.avx512.vp2intersect.d.128" => "__builtin_ia32_2intersectd128", + "llvm.x86.avx512.vp2intersect.q.128" => "__builtin_ia32_2intersectq128", + "llvm.x86.avx512.vp2intersect.d.256" => "__builtin_ia32_2intersectd256", + "llvm.x86.avx512.vp2intersect.q.256" => "__builtin_ia32_2intersectq256", + "llvm.x86.avx512.vp2intersect.d.512" => "__builtin_ia32_2intersectd512", + "llvm.x86.avx512.vp2intersect.q.512" => "__builtin_ia32_2intersectq512", "llvm.x86.pclmulqdq.512" => "__builtin_ia32_vpclmulqdq_v8di", "llvm.x86.pclmulqdq.256" => "__builtin_ia32_vpclmulqdq_v4di", "llvm.x86.avx512.pmulhu.w.512" => "__builtin_ia32_pmulhuw512_mask", @@ -1574,38 +1642,79 @@ pub fn intrinsic<'gcc, 'tcx>(name: &str, cx: &CodegenCx<'gcc, 'tcx>) -> Function "llvm.x86.avx512.uitofp.round.v4f64.v4i64" => "__builtin_ia32_cvtuqq2pd256_mask", "llvm.x86.avx512.uitofp.round.v8f32.v8i64" => "__builtin_ia32_cvtuqq2ps512_mask", "llvm.x86.avx512.uitofp.round.v4f32.v4i64" => "__builtin_ia32_cvtuqq2ps256_mask", + "llvm.x86.avx512fp16.fpclass.ph.128" => "__builtin_ia32_fpclassph128_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.128" => "__builtin_ia32_cmpph128_mask", + "llvm.x86.avx512fp16.fpclass.ph.256" => "__builtin_ia32_fpclassph256_mask", + "llvm.x86.avx512fp16.fpclass.ph.512" => "__builtin_ia32_fpclassph512_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.256" => "__builtin_ia32_cmpph256_mask", + "llvm.x86.avx512fp16.mask.cmp.ph.512" => "__builtin_ia32_cmpph512_mask_round", + "llvm.x86.avx512.fpclass.pd.128" => "__builtin_ia32_fpclasspd128_mask", + "llvm.x86.avx512.fpclass.ps.128" => "__builtin_ia32_fpclassps128_mask", + "llvm.x86.avx512.fpclass.pd.256" => "__builtin_ia32_fpclasspd256_mask", + "llvm.x86.avx512.fpclass.ps.256" => "__builtin_ia32_fpclassps256_mask", + "llvm.x86.avx512.fpclass.pd.512" => "__builtin_ia32_fpclasspd512_mask", + "llvm.x86.avx512.fpclass.ps.512" => "__builtin_ia32_fpclassps512_mask", // FIXME: support the tile builtins: "llvm.x86.ldtilecfg" => "__builtin_trap", "llvm.x86.sttilecfg" => "__builtin_trap", "llvm.x86.tileloadd64" => "__builtin_trap", + "llvm.x86.tileloadd64.internal" => "__builtin_trap", "llvm.x86.tilerelease" => "__builtin_trap", "llvm.x86.tilestored64" => "__builtin_trap", + "llvm.x86.tilestored64.internal" => "__builtin_trap", "llvm.x86.tileloaddrs64" => "__builtin_trap", + "llvm.x86.tileloaddrs64.internal" => "__builtin_trap", "llvm.x86.tileloaddt164" => "__builtin_trap", + "llvm.x86.tileloaddt164.internal" => "__builtin_trap", "llvm.x86.tileloaddrst164" => "__builtin_trap", + "llvm.x86.tileloaddrst164.internal" => "__builtin_trap", "llvm.x86.tilezero" => "__builtin_trap", + "llvm.x86.tilezero.internal" => "__builtin_trap", "llvm.x86.tilemovrow" => "__builtin_trap", + "llvm.x86.tilemovrow.internal" => "__builtin_trap", "llvm.x86.tilemovrowi" => "__builtin_trap", "llvm.x86.tdpbhf8ps" => "__builtin_trap", + "llvm.x86.tdpbhf8ps.internal" => "__builtin_trap", "llvm.x86.tdphbf8ps" => "__builtin_trap", + "llvm.x86.tdphbf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf8ps" => "__builtin_trap", + "llvm.x86.tdpbf8ps.internal" => "__builtin_trap", "llvm.x86.tdphf8ps" => "__builtin_trap", + "llvm.x86.tdphf8ps.internal" => "__builtin_trap", "llvm.x86.tdpbf16ps" => "__builtin_trap", + "llvm.x86.tdpbf16ps.internal" => "__builtin_trap", "llvm.x86.tdpbssd" => "__builtin_trap", + "llvm.x86.tdpbssd.internal" => "__builtin_trap", "llvm.x86.tdpbsud" => "__builtin_trap", + "llvm.x86.tdpbsud.internal" => "__builtin_trap", "llvm.x86.tdpbusd" => "__builtin_trap", + "llvm.x86.tdpbusd.internal" => "__builtin_trap", "llvm.x86.tdpbuud" => "__builtin_trap", + "llvm.x86.tdpbuud.internal" => "__builtin_trap", "llvm.x86.tdpfp16ps" => "__builtin_trap", + "llvm.x86.tdpfp16ps.internal" => "__builtin_trap", "llvm.x86.tmmultf32ps" => "__builtin_trap", + "llvm.x86.tmmultf32ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phh" => "__builtin_trap", + "llvm.x86.tcvtrowps2phh.internal" => "__builtin_trap", "llvm.x86.tcvtrowps2phl" => "__builtin_trap", + "llvm.x86.tcvtrowps2phl.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2ps" => "__builtin_trap", + "llvm.x86.tcvtrowd2ps.internal" => "__builtin_trap", "llvm.x86.tcvtrowd2psi" => "__builtin_trap", "llvm.x86.tcvtrowps2phhi" => "__builtin_trap", "llvm.x86.tcvtrowps2phli" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16h.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16hi" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16l.internal" => "__builtin_trap", + "llvm.x86.tcvtrowps2bf16li" => "__builtin_trap", "llvm.x86.tcmmimfp16ps" => "__builtin_trap", + "llvm.x86.tcmmimfp16ps.internal" => "__builtin_trap", "llvm.x86.tcmmrlfp16ps" => "__builtin_trap", + "llvm.x86.tcmmrlfp16ps.internal" => "__builtin_trap", // NOTE: this file is generated by https://github.com/GuillaumeGomez/llvmint/blob/master/generate_list.py _ => map_arch_intrinsic(name), diff --git a/src/intrinsic/mod.rs b/src/intrinsic/mod.rs index 0a24519a8091e..4d2590ac81e41 100644 --- a/src/intrinsic/mod.rs +++ b/src/intrinsic/mod.rs @@ -4,7 +4,7 @@ mod simd; #[cfg(feature = "master")] use std::iter; -use gccjit::{ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; +use gccjit::{CType, ComparisonOp, Function, FunctionType, RValue, ToRValue, Type, UnaryOp}; use rustc_abi::{Align, BackendRepr, HasDataLayout, WrappingRange}; use rustc_codegen_ssa::base::wants_msvc_seh; use rustc_codegen_ssa::common::IntPredicate; @@ -81,7 +81,6 @@ fn get_simple_intrinsic<'gcc, 'tcx>( sym::floorf64 => "floor", sym::ceilf32 => "ceilf", sym::ceilf64 => "ceil", - sym::powf128 => return float_intrinsic(cx, cx.type_f128(), "powf128"), sym::truncf32 => "truncf", sym::truncf64 => "trunc", // We match the LLVM backend and lower this to `rint`. @@ -180,14 +179,11 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc let simple = get_simple_intrinsic(self, name); let value = match name { - _ if simple.is_some() => { - let func = simple.expect("simple intrinsic function"); - self.cx.context.new_call( - self.location, - func, - &args.iter().map(|arg| arg.immediate()).collect::>(), - ) - } + _ if let Some(func) = simple => self.cx.context.new_call( + self.location, + func, + &args.iter().map(|arg| arg.immediate()).collect::>(), + ), // FIXME(antoyo): We can probably remove these and use the fallback intrinsic implementation. sym::minimumf32 | sym::minimumf64 | sym::maximumf32 | sym::maximumf64 => { let (ty, func_name) = match name { @@ -322,7 +318,9 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc unimplemented!(); } sym::va_arg => { - unimplemented!(); + let va_list = args[0].immediate(); + let gcc_type = self.immediate_backend_type(result.layout); + self.va_arg(va_list, gcc_type) } sym::volatile_load | sym::unaligned_volatile_load => { @@ -611,7 +609,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.on_stack_function_params.borrow_mut().insert(func, FxHashSet::default()); - crate::attributes::from_fn_attrs(self, func, instance); + crate::attributes::from_fn_attrs(self, func, instance, None); func }; @@ -701,8 +699,18 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc self.context.new_rvalue_from_int(self.int_type, 0) } - fn va_start(&mut self, _va_list: RValue<'gcc>) { - unimplemented!(); + fn va_start(&mut self, va_list: RValue<'gcc>) { + let func = self.context.get_builtin_function("__builtin_va_start"); + + let va_list_type = self.context.new_c_type(CType::VaList); + let va_list = self.context.new_cast(self.location, va_list, va_list_type.make_pointer()); + + // Pre-C23 requires that the last "normal" argument was passed to va_start. + // Just pass 0, this appears to be handled correctly. + let last_normal_arg = self.context.new_rvalue_from_int(self.int_type, 0); + + let call = self.context.new_call(self.location, func, &[va_list, last_normal_arg]); + self.block.add_eval(self.location, call); } fn retag_reg(&mut self, _ptr: Self::Value, _info: &RetagInfo) -> Self::Value { @@ -960,7 +968,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let else_block = func.new_block("else"); let after_block = func.new_block("after"); - let result = func.new_local(None, self.u32_type, "zeros"); + let result = self.new_temp(func, None, self.u32_type); let zero = self.cx.gcc_zero(arg.get_type()); let cond = self.gcc_icmp(IntPredicate::IntEQ, arg, zero); self.llbb().end_with_conditional(None, cond, then_block, else_block); @@ -1041,7 +1049,7 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { // else call it on the 64 high bits and add 64. In the else case, 64 high bits can't be 0 // because arg is not 0. - let result = self.current_func().new_local(None, result_type, "count_zeroes_results"); + let result = self.new_temp(self.current_func(), None, result_type); let cz_then_block = self.current_func().new_block("cz_then"); let cz_else_block = self.current_func().new_block("cz_else"); @@ -1156,8 +1164,8 @@ impl<'a, 'gcc, 'tcx> Builder<'a, 'gcc, 'tcx> { let loop_tail = func.new_block("tail"); let counter_type = self.int_type; - let counter = self.current_func().new_local(None, counter_type, "popcount_counter"); - let val = self.current_func().new_local(None, value_type, "popcount_value"); + let counter = self.new_temp(self.current_func(), None, counter_type); + let val = self.new_temp(self.current_func(), None, value_type); let zero = self.gcc_zero(counter_type); self.llbb().add_assignment(self.location, counter, zero); self.llbb().add_assignment(self.location, val, value); diff --git a/src/intrinsic/old_archs.rs b/src/intrinsic/old_archs.rs index 8d3e3487b5cb4..1aac52c28d220 100644 --- a/src/intrinsic/old_archs.rs +++ b/src/intrinsic/old_archs.rs @@ -1240,6 +1240,10 @@ pub(crate) fn old_archs(arch: &str, name: &str) -> ArchCheckResult { "avx512.vbroadcast.sd.pd.512" => "__builtin_ia32_vbroadcastsd_pd512", "avx512.vbroadcast.ss.512" => "__builtin_ia32_vbroadcastss512", "avx512.vbroadcast.ss.ps.512" => "__builtin_ia32_vbroadcastss_ps512", + "bmi.pdep.32" => "__builtin_ia32_pdep_si", + "bmi.pdep.64" => "__builtin_ia32_pdep_di", + "bmi.pext.32" => "__builtin_ia32_pext_si", + "bmi.pext.64" => "__builtin_ia32_pext_di", "fma.mask.vfmadd.pd.512" => "__builtin_ia32_vfmaddpd512_mask", "fma.mask.vfmadd.ps.512" => "__builtin_ia32_vfmaddps512_mask", "fma.mask.vfmaddsub.pd.512" => "__builtin_ia32_vfmaddsubpd512_mask", diff --git a/src/lib.rs b/src/lib.rs index 0784823c27b9e..695bca1d69ec1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -74,9 +74,9 @@ use std::ops::Deref; use std::path::{Path, PathBuf}; use std::sync::Arc; -use gccjit::{CType, Context, OptimizationLevel}; #[cfg(feature = "master")] -use gccjit::{TargetInfo, Version}; +use gccjit::TargetInfo; +use gccjit::{CType, Context, OptimizationLevel}; use rustc_ast::expand::allocator::AllocatorMethod; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ @@ -292,20 +292,6 @@ impl CodegenBackend for GccCodegenBackend { fn target_config(&self, sess: &EarlySession) -> TargetConfig { target_config(sess, &self.config().target_info) } - #[cfg(feature = "master")] - { - context.set_special_chars_allowed_in_func_names("$.*"); - let version = Version::get(); - let version = format!("{}.{}.{}", version.major, version.minor, version.patch); - context.set_output_ident(&format!( - "rustc version {} with libgccjit {}", - rustc_interface::util::rustc_version_str().unwrap_or("unknown version"), - version, - )); - } - // FIXME(antoyo): check if this should only be added when using -Cforce-unwind-tables=n. - context.add_command_line_option("-fno-asynchronous-unwind-tables"); - context } impl ExtraBackendMethods for GccCodegenBackend { @@ -318,7 +304,7 @@ impl ExtraBackendMethods for GccCodegenBackend { methods: &[AllocatorMethod], ) -> Self::Module { let mut mods = GccContext { - context: Arc::new(SyncContext::new(new_context(tcx))), + context: Arc::new(SyncContext::new(gcc_util::new_context(tcx.sess))), relocation_model: tcx.sess.relocation_model(), lto_mode: LtoMode::None, lto_supported: self.config().lto_supported, @@ -411,7 +397,7 @@ impl WriteBackendMethods for GccCodegenBackend { each_linked_rlib_for_lto: &[PathBuf], modules: Vec>, ) -> CompiledModule { - back::lto::run_fat(cgcx, &sess.prof, shared_emitter, each_linked_rlib_for_lto, modules) + back::lto::run_fat(sess, cgcx, shared_emitter, each_linked_rlib_for_lto, modules) } fn run_thin_lto( diff --git a/src/mono_item.rs b/src/mono_item.rs index 014a7ff90536d..d8170fbb085a7 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,3 +1,4 @@ +use gccjit::Function; #[cfg(feature = "master")] use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; @@ -22,7 +23,7 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { def_id: DefId, linkage: Linkage, visibility: Visibility, - symbol_name: &str, + global_name: &str, ) { let attrs = self.tcx.codegen_fn_attrs(def_id); let instance = Instance::mono(self.tcx, def_id); @@ -73,7 +74,6 @@ impl<'gcc, 'tcx> PreDefineCodegenMethods<'tcx> for CodegenCx<'gcc, 'tcx> { #[cfg(feature = "master")] self.add_static_aliases(gcc_type, global_name, attrs, &attrs.foreign_item_symbol_aliases); - // FIXME(antoyo): set linkage. self.instances.borrow_mut().insert(instance, global); } @@ -186,10 +186,9 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { ) -> Function<'gcc> { let fn_abi = self.fn_abi_of_instance(instance, ty::List::empty()); self.linkage.set(base::linkage_to_gcc(linkage)); - let decl = self.declare_fn(symbol_name, fn_abi); - //let attrs = self.tcx.codegen_instance_attrs(instance.def); + let fn_decl = self.declare_fn(symbol_name, fn_abi); - attributes::from_fn_attrs(self, decl, instance); + attributes::from_fn_attrs(self, fn_decl, instance, Some(fn_abi)); #[cfg(feature = "master")] if base::linkage_needs_weak_attribute(linkage) { @@ -202,17 +201,21 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { // don't want the symbols to get exported. if linkage != Linkage::Internal && self.tcx.is_compiler_builtins(LOCAL_CRATE) { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); + fn_decl.add_attribute(FnAttribute::Visibility(gccjit::Visibility::Hidden)); } else if visibility != Visibility::Default { #[cfg(feature = "master")] - decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + fn_decl.add_attribute(FnAttribute::Visibility(base::visibility_to_gcc(visibility))); + } + + #[cfg(feature = "master")] + if let Some(section) = _attrs.link_section { + fn_decl.add_attribute(FnAttribute::Section(section.as_str())); } - // FIXME(antoyo): call set_link_section() to allow initializing argc/argv. // FIXME(antoyo): set unique comdat. // FIXME(antoyo): use inline attribute from there in linkage.set() above. + // FIXME: Should we handle dso? - self.functions.borrow_mut().insert(symbol_name.to_string(), decl); - self.function_instances.borrow_mut().insert(instance, decl); + fn_decl } } diff --git a/src/type_.rs b/src/type_.rs index 45828ce3e92b8..55b37ee89b63f 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -3,7 +3,7 @@ use std::convert::TryInto; use std::mem::discriminant; #[cfg(feature = "master")] -use gccjit::CType; +use gccjit::{CType, TypeAttribute}; use gccjit::{RValue, Struct, Type}; use rustc_abi::{AddressSpace, Align, Integer, Size}; use rustc_codegen_ssa::common::TypeKind; @@ -232,7 +232,7 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { if self.supports_f16_type { return self.context.new_c_type(CType::Float16); } - bug!("unsupported float width 16") + self.u16_type } fn type_f32(&self) -> Type<'gcc> { diff --git a/tests/asm/asm/comments.rs b/tests/asm/asm/comments.rs new file mode 100644 index 0000000000000..603bb014930c4 --- /dev/null +++ b/tests/asm/asm/comments.rs @@ -0,0 +1,12 @@ +//@ assembly-output: emit-asm +//@ only-x86_64 +// Check that comments in assembly get passed + +#![crate_type = "lib"] + +// CHECK-LABEL: "test_comments": +#[no_mangle] +pub fn test_comments() { + // CHECK: example comment + unsafe { core::arch::asm!("nop // example comment") }; +} diff --git a/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs new file mode 100644 index 0000000000000..81ee9b13b4eca --- /dev/null +++ b/tests/asm/naked-functions/x86_64-naked-fn-no-cet-prolog.rs @@ -0,0 +1,24 @@ +//@ compile-flags: -C no-prepopulate-passes -Zcf-protection=full +//@ assembly-output: emit-asm +//@ needs-asm-support +//@ only-x86_64 + +#![crate_type = "lib"] + +use std::arch::naked_asm; + +// The problem at hand: Rust has adopted a fairly strict meaning for "naked functions", +// meaning "no prologue whatsoever, no, really, not one instruction." +// Unfortunately, x86's control-flow enforcement, specifically indirect branch protection, +// works by using an instruction for each possible landing site, +// and LLVM implements this via making sure of that. +#[no_mangle] +#[unsafe(naked)] +pub extern "sysv64" fn will_halt() -> ! { + // CHECK-NOT: endbr{{32|64}} + // CHECK: hlt + naked_asm!("hlt") +} + +// what about aarch64? +// "branch-protection"=false diff --git a/tests/asm/panic-no-unwind-no-uwtable.rs b/tests/asm/panic-no-unwind-no-uwtable.rs new file mode 100644 index 0000000000000..b51b173e9616e --- /dev/null +++ b/tests/asm/panic-no-unwind-no-uwtable.rs @@ -0,0 +1,8 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu +//@ compile-flags: -C panic=unwind -C force-unwind-tables=n -Copt-level=3 + +#![crate_type = "lib"] + +// CHECK-NOT: .cfi_startproc +pub fn foo() {} diff --git a/tests/asm/used.rs b/tests/asm/used.rs new file mode 100644 index 0000000000000..deb0c69dc48fa --- /dev/null +++ b/tests/asm/used.rs @@ -0,0 +1,14 @@ +//@ assembly-output: emit-asm +//@ only-x86_64-unknown-linux-gnu + +#![feature(used_with_arg)] +#![crate_type = "lib"] + +// CHECK: .section .rodata.X,"a" +#[used(compiler)] +#[no_mangle] +pub static X: u32 = 12; +// CHECK: .section .rodata.Y,"aR" +#[used(linker)] +#[no_mangle] +pub static Y: u32 = 12; diff --git a/tests/asm/x86_64-sse_crc.rs b/tests/asm/x86_64-sse_crc.rs new file mode 100644 index 0000000000000..bde58955a2146 --- /dev/null +++ b/tests/asm/x86_64-sse_crc.rs @@ -0,0 +1,12 @@ +//@ only-x86_64 +//@ assembly-output: emit-asm +//@ compile-flags: --crate-type staticlib -Ctarget-feature=+sse4.2 + +// CHECK-LABEL: banana +// CHECK: crc32 +#[no_mangle] +pub unsafe fn banana(v: u8) -> u32 { + use std::arch::x86_64::*; + let out = !0u32; + _mm_crc32_u8(out, v) +} diff --git a/tests/compile/x86_interrupt_first_arg_byval.rs b/tests/compile/x86_interrupt_first_arg_byval.rs new file mode 100644 index 0000000000000..4b6bbd48f7ad5 --- /dev/null +++ b/tests/compile/x86_interrupt_first_arg_byval.rs @@ -0,0 +1,16 @@ +// Compiler: + +// Test that `x86-interrupt` functions whose first argument is passed by value +// emit pointer-shaped GCC parameters and compile with interrupt-safe target features. + +#![feature(abi_x86_interrupt)] +#![crate_type = "lib"] + +#[repr(C)] +pub struct Frame { + ip: u64, +} + +pub extern "x86-interrupt" fn scalar(_a: i64) {} + +pub extern "x86-interrupt" fn aggregate(_frame: Frame) {} diff --git a/tests/cpuid.def b/tests/cpuid.def new file mode 100644 index 0000000000000..05fe8e94a8282 --- /dev/null +++ b/tests/cpuid.def @@ -0,0 +1,27 @@ +# Input => Output +# EAX ECX => EAX EBX ECX EDX +00000000 ******** => 00000024 756e6547 6c65746e 49656e69 #Processor ID and Manufacturer +00000001 ******** => 00400f10 00100800 7ffaf3ff bfebfbff +00000007 00000000 => 00000002 f3bfbfbf bac05ffe 03d54130 #Extended Features +00000007 00000001 => 98ee00bf 00000002 00000020 1d29cd3e +0000000d 00000000 => 000e02e7 00002b00 00002b00 00000000 #xcr0 +0000000d 00000001 => 0000001f 00000240 00000100 00000000 #Supervisor State +0000000d 00000002 => 00000100 00000240 00000000 00000000 +0000000d 00000005 => 00000040 00000440 00000000 00000000 #zmasks +0000000d 00000006 => 00000200 00000480 00000000 00000000 #zmmh +0000000d 00000007 => 00000400 00000680 00000000 00000000 #zmm +0000000d 00000011 => 00000040 00000ac0 00000002 00000000 #tileconfig +0000000d 00000012 => 00002000 00000b00 00000006 00000000 #tiles +0000000d 00000013 => 00000080 000003c0 00000000 00000000 #APX +00000019 ******** => 00000000 00000005 00000000 00000000 #Key Locker +0000001d 00000000 => 00000001 00000000 00000000 00000000 #AMX Tile +0000001d 00000001 => 04002000 00080040 00000010 00000000 #AMX Palette1 +0000001e 00000000 => 00000001 00004010 00000000 00000000 #AMX Tmul +0000001e 00000001 => 000001ff 00000000 00000000 00000000 +00000024 00000000 => 00000001 00070002 00000000 00000000 #AVX10 +00000024 00000001 => 00000000 00000000 00000004 00000000 +80000000 ******** => 80000004 00000000 00000000 00000000 +80000001 ******** => 00000000 00000000 00000121 2c100000 +80000002 ******** => 00000000 00000000 00000000 00000000 +80000003 ******** => 00000000 00000000 00000000 00000000 +80000004 ******** => 00000000 00000000 00000000 00000000 diff --git a/tests/lang_tests.rs b/tests/lang_tests.rs index 9c4708274280c..7ec0ab877b025 100644 --- a/tests/lang_tests.rs +++ b/tests/lang_tests.rs @@ -240,6 +240,16 @@ fn build_test_runner( } } + // Extra flags passed at run time (as opposed to the compile-time + // `TEST_FLAGS`). This lets a single test opt into flags like + // `-Zmir-preserve-ub` via an `ignore-if` directive that checks + // whether `CARGO_TEST_FLAGS` is set. + if let Ok(flags) = std::env::var("CARGO_TEST_FLAGS") { + for flag in flags.split_whitespace() { + compiler_args.push(flag.into()); + } + } + if build_mode.is_debug() { compiler_args .extend_from_slice(&["-C".to_string(), "llvm-args=sanitize-undefined".into()]); @@ -270,7 +280,13 @@ fn compile_tests(tempdir: PathBuf, c_objects_dir: PathBuf, current_dir: String) "lang compile", "tests/compile", TestMode::Compile, - &["simd-ffi.rs", "asm_nul_byte.rs", "global_asm_nul_byte.rs", "naked_asm_nul_byte.rs"], + &[ + "simd-ffi.rs", + "asm_nul_byte.rs", + "global_asm_nul_byte.rs", + "naked_asm_nul_byte.rs", + "x86_interrupt_first_arg_byval.rs", + ], ); } diff --git a/tests/run/asm.rs b/tests/run/asm.rs index 01775c92ffc8a..42141c671b596 100644 --- a/tests/run/asm.rs +++ b/tests/run/asm.rs @@ -3,6 +3,8 @@ // Run-time: // status: 0 +#![feature(asm_goto_with_outputs)] + #[cfg(target_arch = "x86_64")] use std::arch::{asm, global_asm}; @@ -32,6 +34,20 @@ pub unsafe fn mem_cpy(dst: *mut u8, src: *const u8, len: usize) { ); } +#[cfg(target_arch = "x86_64")] +#[unsafe(no_mangle)] +pub fn asm_goto_test(mut a: i16) -> i16 { + unsafe { + std::arch::asm!( + "jmp {op}", + inout("eax") a, + op = label { a = 7; }, + options(nostack,nomem) + ); + a + } +} + #[cfg(target_arch = "x86_64")] fn asm() { unsafe { @@ -190,6 +206,14 @@ fn asm() { } assert_eq!((x, y), (8, 8)); + // Regression test for + // typed pointer inputs to explicit registers need a cast. + let mut x = 123_i32; + unsafe { + asm!("", in("rdi") &mut x, options(nostack, preserves_flags)); + } + assert_eq!(x, 123); + // sysv64 is the default calling convention on unix systems. The rdi register is // used to pass arguments in the sysv64 calling convention, so this register will be clobbered #[cfg(unix)] @@ -227,6 +251,24 @@ fn asm() { out("r15b") _, ); } + + // Make sure the input value from inout is assigned to the input value + unsafe { + // Use a very distinctive value unlikely to live in any register. + let input: u64 = 0x1234567890ABCDEF; + let mut output: u64; + + asm!( + "push {1}", + "pop {0}", + out(reg) output, + inout(reg) input => _, + ); + + assert_eq!(output, 0x1234567890ABCDEF); + } + + asm_goto_test(0); } #[cfg(not(target_arch = "x86_64"))] diff --git a/tests/run/int.rs b/tests/run/int.rs index 78675acb5447b..ef825b4d80185 100644 --- a/tests/run/int.rs +++ b/tests/run/int.rs @@ -319,4 +319,29 @@ fn main() { const VAL5: T = 73236519889708027473620326106273939584_i128; check_ops128!(); } + + { + #[allow(dead_code)] + #[repr(u8)] + enum Inner { + L0 = 0, + H255 = 255, + } + #[allow(dead_code)] + enum O { + A(Inner), + B, + C, + } + + #[inline(never)] + fn which(o: &O) -> &'static str { + match o { + O::A(_) => "a", + O::B => "b", + O::C => "c", + } + } + assert_eq!(which(black_box(&O::A(Inner::H255))), "a"); + } } diff --git a/tests/run/mir_preserve_ub_empty_switch.rs b/tests/run/mir_preserve_ub_empty_switch.rs new file mode 100644 index 0000000000000..26056360b9212 --- /dev/null +++ b/tests/run/mir_preserve_ub_empty_switch.rs @@ -0,0 +1,35 @@ +// ignore-if: test -z "$CARGO_TEST_FLAGS" +// Compiler: +// +// Run-time: +// status: 0 + +// Regression test for https://github.com/rust-lang/rustc_codegen_gcc/issues/881 +// +// This needs `-Zmir-preserve-ub`, so it is skipped unless that flag is passed +// through `CARGO_TEST_FLAGS` (see the `ignore-if` directive above). Run it with: +// CARGO_TEST_FLAGS="-Zmir-preserve-ub" ./y.sh test --cargo-tests -- mir_preserve_ub_empty_switch + +#![feature(no_core)] +#![no_std] +#![no_core] +#![no_main] + +extern crate mini_core; +use intrinsics::black_box; +use mini_core::*; + +#[no_mangle] +extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { + // With `-Zmir-preserve-ub`, the range pattern below is lowered to a pair of + // comparisons and the second one becomes a `SwitchInt` with no cases (only + // an `otherwise` target) whose discriminant is the `bool` comparison + // result. `gcc_jit_block_end_with_switch` rejects a non-integer + // discriminant, so the backend must emit a plain jump for it instead. + let value = black_box(argc); + match value { + 0..=9 => (), + _ => (), + } + 0 +} diff --git a/tools/generate_intrinsics.py b/tools/generate_intrinsics.py index 5390323407779..06425f682a88b 100644 --- a/tools/generate_intrinsics.py +++ b/tools/generate_intrinsics.py @@ -84,6 +84,10 @@ def update_intrinsics(llvm_path): # This speeds up the comparison, and makes our code considerably smaller. # Since all intrinsic names start with "llvm.", we skip that prefix. print("Updating content of `{}`...".format(output_file)) + indent4 = " " + indent8 = indent4 + indent4 + indent12 = indent8 + indent4 + indent16 = indent12 + indent4 with open(output_file, "w", encoding="utf8") as out: out.write("""// File generated by `rustc_codegen_gcc/tools/generate_intrinsics.py` // DO NOT EDIT IT! @@ -95,33 +99,35 @@ def update_intrinsics(llvm_path): if let ArchCheckResult::Ok(res) = old_arch_res { return res; } -match arch {""") + match arch { +""") for arch in archs: if len(intrinsics[arch]) == 0: continue attribute = "#[expect(non_snake_case)]" if arch[0].isupper() else "" - out.write("\"{}\" => {{ {} fn {}(name: &str,full_name:&str) -> &'static str {{ match name {{".format(arch, attribute, arch)) + out.write(f"""{indent4}"{arch}" => {{ +{indent8}{attribute} fn {arch}(name: &str,full_name:&str) -> &'static str {{ +{indent12}match name {{""") intrinsics[arch].sort(key=lambda x: (x[0], x[1])) - out.write(' // {}\n'.format(arch)) + out.write(f'{indent16}// {arch}\n') for entry in intrinsics[arch]: llvm_name = entry[0].removeprefix("llvm."); llvm_name = llvm_name.removeprefix(arch); llvm_name = llvm_name.removeprefix("."); if "_round_mask" in entry[1]: - out.write(' // [INVALID CONVERSION]: "{}" => "{}",\n'.format(llvm_name, entry[1])) + out.write(f'{indent16}// [INVALID CONVERSION]: "{llvm_name}" => "{entry[1]}",\n') else: - out.write(' "{}" => "{}",\n'.format(llvm_name, entry[1])) - out.write(' _ => unimplemented!("***** unsupported LLVM intrinsic {full_name}"),\n') - out.write("}} }} {}(name,full_name) }}\n,".format(arch)) - out.write(""" _ => { - match old_arch_res { - ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {full_name}"), - ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {arch}, intrinsic: {full_name}"), - ArchCheckResult::Ok(_) => unreachable!(), - } - }""") + out.write(f'{indent16}"{llvm_name}" => "{entry[1]}",\n') + out.write(f'{indent16}_ => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"),\n') + out.write(f"{indent16}}}\n{indent12}}}\n{indent8}{arch}(name,full_name)\n{indent8}}}\n,") + out.write(f"""{indent4}_ => {{ +{indent8}match old_arch_res {{ +{indent8}ArchCheckResult::UnknownIntrinsic => unimplemented!("***** unsupported LLVM intrinsic {{full_name}}"), +{indent8}ArchCheckResult::UnknownArch => unimplemented!("***** unsupported LLVM architecture {{arch}}, intrinsic: {{full_name}}"), +{indent8}ArchCheckResult::Ok(_) => unreachable!(), +{indent4}}} +}}""") out.write("}\n}") - subprocess.call(["rustfmt", output_file]) print("Done!") From f773f161610b083cb7bdac5bbcc5c6086a04757c Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Fri, 18 Sep 2026 21:31:48 +0200 Subject: [PATCH 0368/1309] Error on invalid placements for unstable attributes --- .../src/attributes/allow_unstable.rs | 8 +-- .../src/attributes/macro_attrs.rs | 8 +-- .../src/attributes/traits.rs | 9 +--- tests/ui/internal/internal-unstable.rs | 6 +-- tests/ui/internal/internal-unstable.stderr | 49 +++++++++---------- 5 files changed, 31 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 743d3c9b5e76e..667c2d0838a25 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -12,12 +12,8 @@ impl CombineAttributeParser for AllowInternalUnstableParser { type Item = (Symbol, Span); const CONVERT: ConvertFn = |items, span| AttributeKind::AllowInternalUnstable(items, span); - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::MacroDef), - Allow(Target::Fn), - Warn(Target::Field), - Warn(Target::Arm), - ]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::MacroDef), Allow(Target::Fn)]); const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]); const STABILITY: AttributeStability = unstable!(allow_internal_unstable); diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index c9625521aec44..92b61fe00b1b9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -131,12 +131,8 @@ pub(crate) struct AllowInternalUnsafeParser; impl NoArgsAttributeParser for AllowInternalUnsafeParser { const PATH: &[Symbol] = &[sym::allow_internal_unsafe]; const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::Fn), - Allow(Target::MacroDef), - Warn(Target::Field), - Warn(Target::Arm), - ]); + const ALLOWED_TARGETS: AllowedTargets<'_> = + AllowedTargets::AllowList(&[Allow(Target::Fn), Allow(Target::MacroDef)]); const STABILITY: AttributeStability = unstable!(allow_internal_unsafe); const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs index 1d0d26ea62cb3..e55a033eb3188 100644 --- a/compiler/rustc_attr_parsing/src/attributes/traits.rs +++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs @@ -8,7 +8,7 @@ use crate::attributes::{NoArgsAttributeParser, SingleAttributeParser}; use crate::context::AcceptContext; use crate::parser::ArgParser; use crate::target_checking::AllowedTargets; -use crate::target_checking::Policy::{Allow, Warn}; +use crate::target_checking::Policy::Allow; pub(crate) struct RustcSkipDuringMethodDispatchParser; impl SingleAttributeParser for RustcSkipDuringMethodDispatchParser { @@ -63,12 +63,7 @@ impl NoArgsAttributeParser for RustcParenSugarParser { pub(crate) struct MarkerParser; impl NoArgsAttributeParser for MarkerParser { const PATH: &[Symbol] = &[sym::marker]; - const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[ - Allow(Target::Trait), - Warn(Target::Field), - Warn(Target::Arm), - Warn(Target::MacroDef), - ]); + const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]); const STABILITY: AttributeStability = unstable!(marker_trait_attr); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Marker; } diff --git a/tests/ui/internal/internal-unstable.rs b/tests/ui/internal/internal-unstable.rs index 5564852e98888..41aa76dea3f7b 100644 --- a/tests/ui/internal/internal-unstable.rs +++ b/tests/ui/internal/internal-unstable.rs @@ -8,8 +8,7 @@ extern crate internal_unstable; struct Baz { #[allow_internal_unstable] //~ ERROR `allow_internal_unstable` expects a list of feature names - //~^ WARN cannot be used on - //~| WARN previously accepted + //~^ ERROR cannot be used on baz: u8, } @@ -59,8 +58,7 @@ fn main() { match true { #[allow_internal_unstable] //~ ERROR `allow_internal_unstable` expects a list of feature names - //~^ WARN cannot be used on - //~| WARN previously accepted + //~^ ERROR cannot be used on _ => {} } diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr index b816dc6f7454c..924d512e99836 100644 --- a/tests/ui/internal/internal-unstable.stderr +++ b/tests/ui/internal/internal-unstable.stderr @@ -4,14 +4,30 @@ error: `allow_internal_unstable` expects a list of feature names LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: the `allow_internal_unstable` attribute cannot be used on struct fields + --> $DIR/internal-unstable.rs:10:7 + | +LL | #[allow_internal_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `allow_internal_unstable` attribute can be applied to functions and macro defs + error: `allow_internal_unstable` expects a list of feature names - --> $DIR/internal-unstable.rs:61:9 + --> $DIR/internal-unstable.rs:60:9 | LL | #[allow_internal_unstable] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +error: the `allow_internal_unstable` attribute cannot be used on match arms + --> $DIR/internal-unstable.rs:60:11 + | +LL | #[allow_internal_unstable] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: the `allow_internal_unstable` attribute can be applied to functions and macro defs + error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:50:25 + --> $DIR/internal-unstable.rs:49:25 | LL | pass_through_allow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -20,7 +36,7 @@ LL | pass_through_allow!(internal_unstable::unstable()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:52:27 + --> $DIR/internal-unstable.rs:51:27 | LL | pass_through_noallow!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -29,7 +45,7 @@ LL | pass_through_noallow!(internal_unstable::unstable()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:56:22 + --> $DIR/internal-unstable.rs:55:22 | LL | println!("{:?}", internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -38,7 +54,7 @@ LL | println!("{:?}", internal_unstable::unstable()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:58:10 + --> $DIR/internal-unstable.rs:57:10 | LL | bar!(internal_unstable::unstable()); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -47,7 +63,7 @@ LL | bar!(internal_unstable::unstable()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `function` - --> $DIR/internal-unstable.rs:20:9 + --> $DIR/internal-unstable.rs:19:9 | LL | internal_unstable::unstable(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -59,25 +75,6 @@ LL | bar!(internal_unstable::unstable()); = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: this error originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) -warning: the `allow_internal_unstable` attribute cannot be used on struct fields - --> $DIR/internal-unstable.rs:10:7 - | -LL | #[allow_internal_unstable] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: the `allow_internal_unstable` attribute can be applied to functions and macro defs - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: requested on the command line with `-W unused-attributes` - -warning: the `allow_internal_unstable` attribute cannot be used on match arms - --> $DIR/internal-unstable.rs:61:11 - | -LL | #[allow_internal_unstable] - | ^^^^^^^^^^^^^^^^^^^^^^^ - | - = help: the `allow_internal_unstable` attribute can be applied to functions and macro defs - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - -error: aborting due to 7 previous errors; 2 warnings emitted +error: aborting due to 9 previous errors For more information about this error, try `rustc --explain E0658`. From a3ad87e548a932b761f387641e23dc8a24159fc7 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 18 Sep 2026 10:34:57 +0200 Subject: [PATCH 0369/1309] mark `f128` as reliable on `powerpc` with `+vsx` This feature is only enabled by default for powerpc64le, and not enabled on the big-endian targets. Even with vsx, the default long double is ppcf128 on the big-endian targets, so LLVM calls the incorrect libcall. Also some libcalls just don't exist --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 90f31e0598f2d..5324ec240b0ab 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -6,6 +6,7 @@ use std::sync::Once; use std::{ptr, slice, str}; use libc::c_int; +use rustc_abi::Endian; use rustc_codegen_ssa::back::versioned_llvm_target; use rustc_codegen_ssa::base::wants_wasm_eh; use rustc_codegen_ssa::target_features::internal_target_features; @@ -15,7 +16,7 @@ use rustc_data_structures::small_c_str::SmallCStr; use rustc_fs_util::path_to_c_string; use rustc_session::config::{NATIVE_CPU, PrintKind, PrintRequest}; use rustc_session::{EarlySession, Session}; -use rustc_span::bug; +use rustc_span::{bug, sym}; use rustc_target::spec::{ Arch, CfgAbi, Env, MergeFunctions, Os, PanicStrategy, SmallDataThresholdSupport, Target, }; @@ -394,6 +395,7 @@ pub(crate) fn target_config(sess: &EarlySession) -> TargetConfig { fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { let target_arch = &target.arch; let target_os = &target.options.os; + let target_endian = &target.options.endian; let target_env = &target.options.env; let target_abi = &target.options.cfg_abi; let target_pointer_width = target.pointer_width; @@ -426,9 +428,12 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // Selection bug . This issue is closed // but basic math still does not work. (Arch::Nvptx64, _) => false, - // ABI bugs et al. (full - // list at ) - (Arch::PowerPC | Arch::PowerPC64, _) => false, + // ABI/LLVM bugs: + // - with +vsx + // - without +vsx + (Arch::PowerPC, _) => false, + // ABI bugs on BE without +vsx . + (Arch::PowerPC64, _) => cfg.internal_target_features.contains(&sym::vsx), // ABI unsupported (fixed in llvm22) (Arch::Sparc, _) if major < 22 => false, // MinGW ABI bugs (fixed in llvm23) @@ -456,9 +461,13 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // (ld is `f64`), anything other than Linux (Windows and MacOS use `f64`), and `x86` // (ld is 80-bit extended precision). // + // On big-endian powerpc the symbol selection is correct, despite __ibmf128 being + // long double on the target, but the f128 symbols are not defined. + // // musl does not implement the symbols required for f128 math at all. _ if *target_env == Env::Musl => false, (Arch::X86_64, _) => false, + (Arch::PowerPC | Arch::PowerPC64, _) if *target_endian == Endian::Big => false, (_, Os::Linux) if target_pointer_width == 64 => true, _ => false, } && cfg.has_reliable_f128; From 9f6895fca3258572270fb2d990072758f988f4fc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 22:15:28 +0200 Subject: [PATCH 0370/1309] Ignore more `run-make` tests for the GCC backend --- tests/run-make/comment-section/rmake.rs | 2 ++ tests/run-make/dirty-incr-due-to-hard-link/rmake.rs | 2 ++ tests/run-make/emit/rmake.rs | 1 + tests/run-make/extra-filename-with-temp-outputs/rmake.rs | 2 ++ tests/run-make/parallel-reproducible-build/rmake.rs | 2 ++ tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs | 2 ++ 6 files changed, 11 insertions(+) diff --git a/tests/run-make/comment-section/rmake.rs b/tests/run-make/comment-section/rmake.rs index ccfc38e870d88..22b0e2b3b3fb9 100644 --- a/tests/run-make/comment-section/rmake.rs +++ b/tests/run-make/comment-section/rmake.rs @@ -6,6 +6,8 @@ //@ only-linux // FIXME(jieyouxu): check cross-compile setup //@ ignore-cross-compile +// FIXME: remove the ignore gcc once fixed. +//@ ignore-backends: gcc use run_make_support::{cwd, env_var, llvm_readobj, rfs, rustc}; diff --git a/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs index 942b667814a91..f6a337513909d 100644 --- a/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs +++ b/tests/run-make/dirty-incr-due-to-hard-link/rmake.rs @@ -1,4 +1,6 @@ //@ only-x86_64-unknown-linux-gnu +// FIXME: remove the ignore gcc once fixed. +//@ ignore-backends: gcc // Regression test for the incremental bug in . // diff --git a/tests/run-make/emit/rmake.rs b/tests/run-make/emit/rmake.rs index 8b3ddb66f9238..5cf13e9bd4879 100644 --- a/tests/run-make/emit/rmake.rs +++ b/tests/run-make/emit/rmake.rs @@ -4,6 +4,7 @@ // See https://github.com/rust-lang/rust/pull/30452 //@ ignore-cross-compile +//@ ignore-backends: gcc use run_make_support::{run, rustc}; diff --git a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs index f93a3ecc8d1b5..2b59459006c23 100644 --- a/tests/run-make/extra-filename-with-temp-outputs/rmake.rs +++ b/tests/run-make/extra-filename-with-temp-outputs/rmake.rs @@ -7,6 +7,8 @@ // See https://github.com/rust-lang/rust/pull/15686 //@ ignore-cross-compile (relocations in generic ELF against `arm-unknown-linux-gnueabihf`) +// FIXME: remove the ignore gcc once fixed. +//@ ignore-backends: gcc use run_make_support::{bin_name, cwd, has_prefix, has_suffix, rfs, rustc, shallow_find_files}; diff --git a/tests/run-make/parallel-reproducible-build/rmake.rs b/tests/run-make/parallel-reproducible-build/rmake.rs index f35d15de07b85..caaee1b47c583 100644 --- a/tests/run-make/parallel-reproducible-build/rmake.rs +++ b/tests/run-make/parallel-reproducible-build/rmake.rs @@ -1,5 +1,7 @@ //@ needs-target-std //@ ignore-cross-compile +// FIXME: remove the ignore gcc once fixed. +//@ ignore-backends: gcc //@ ignore-windows-gnu // GNU Linker for Windows is non-deterministic. (from `reproducible-build-2` test in this suite) diff --git a/tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs b/tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs index 62ad5a46af860..5f4be53c6edf5 100644 --- a/tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs +++ b/tests/run-make/parallel-reproducible-inline-asm-cookie/rmake.rs @@ -1,5 +1,7 @@ //@ needs-target-std //@ ignore-cross-compile +// FIXME: remove the ignore gcc once fixed. +//@ ignore-backends: gcc //@ ignore-windows-gnu // GNU Linker for Windows is non-deterministic. (from `reproducible-build-2` test in this suite) From 8d490ac4f16cf4437d6aa4a05e8b9a83f9217f94 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 22:52:45 +0200 Subject: [PATCH 0371/1309] Remove forgotten file --- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 patches/0001-Add-stdarch-Cargo.toml-for-testing.patch diff --git a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch deleted file mode 100644 index 3a8c37a8b8d9a..0000000000000 --- a/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 190e26c9274b3c93a9ee3516b395590e6bd9213b Mon Sep 17 00:00:00 2001 -From: None -Date: Sun, 3 Aug 2025 19:54:56 -0400 -Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch - ---- - library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - create mode 100644 library/stdarch/Cargo.toml - -diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml -new file mode 100644 -index 0000000..bd6725c ---- /dev/null -+++ b/library/stdarch/Cargo.toml -@@ -0,0 +1,20 @@ -+[workspace] -+resolver = "1" -+members = [ -+ "crates/*", -+ #"examples/" -+] -+exclude = [ -+ "crates/wasm-assert-instr-tests", -+ "rust_programs", -+] -+ -+[profile.release] -+debug = true -+opt-level = 3 -+incremental = true -+ -+[profile.bench] -+debug = 1 -+opt-level = 3 -+incremental = true --- -2.50.1 - From cf4bee683796e6dc0f1f8278118b5e60bca913e5 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 18 Sep 2026 22:52:45 +0200 Subject: [PATCH 0372/1309] Remove forgotten file --- ...1-Add-stdarch-Cargo.toml-for-testing.patch | 39 ------------------- 1 file changed, 39 deletions(-) delete mode 100644 compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch diff --git a/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch b/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch deleted file mode 100644 index 3a8c37a8b8d9a..0000000000000 --- a/compiler/rustc_codegen_gcc/patches/0001-Add-stdarch-Cargo.toml-for-testing.patch +++ /dev/null @@ -1,39 +0,0 @@ -From 190e26c9274b3c93a9ee3516b395590e6bd9213b Mon Sep 17 00:00:00 2001 -From: None -Date: Sun, 3 Aug 2025 19:54:56 -0400 -Subject: [PATCH] Patch 0001-Add-stdarch-Cargo.toml-for-testing.patch - ---- - library/stdarch/Cargo.toml | 20 ++++++++++++++++++++ - 1 file changed, 20 insertions(+) - create mode 100644 library/stdarch/Cargo.toml - -diff --git a/library/stdarch/Cargo.toml b/library/stdarch/Cargo.toml -new file mode 100644 -index 0000000..bd6725c ---- /dev/null -+++ b/library/stdarch/Cargo.toml -@@ -0,0 +1,20 @@ -+[workspace] -+resolver = "1" -+members = [ -+ "crates/*", -+ #"examples/" -+] -+exclude = [ -+ "crates/wasm-assert-instr-tests", -+ "rust_programs", -+] -+ -+[profile.release] -+debug = true -+opt-level = 3 -+incremental = true -+ -+[profile.bench] -+debug = 1 -+opt-level = 3 -+incremental = true --- -2.50.1 - From ee766dc8d03d3f7b9de904333cea9867f58bf9d0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 18 Sep 2026 23:52:25 +0200 Subject: [PATCH 0373/1309] post GH comment on types nominations --- triagebot.toml | 1 + 1 file changed, 1 insertion(+) diff --git a/triagebot.toml b/triagebot.toml index fc9c43d2dbcae..36d9ee29b6597 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -702,6 +702,7 @@ topic = "#{number}: {title}" message_on_add = """\ @*T-types* issue #{number} "{title}" has been nominated for team discussion. """ +github_comment = ":robot: A [dedicated `#t-types/nominated` topic]({zulip_topic_url}) has been opened for humans to discuss this issue :robot:" message_on_remove = "Issue #{number}'s nomination has been removed. Thanks all for participating!" message_on_close = "Issue #{number} has been closed. Thanks for participating!" message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." From 75b444d1ad334617718f331b210fb88a6ff77c4b Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Sun, 6 Sep 2026 11:39:02 +0900 Subject: [PATCH 0374/1309] Constify `impl FromStr for NonZero` --- library/core/src/num/nonzero.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 0563c225f7e0b..d0ae6c31267f3 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1412,7 +1412,8 @@ macro_rules! nonzero_integer { } #[stable(feature = "nonzero_parse", since = "1.35.0")] - impl FromStr for NonZero<$Int> { + #[rustc_const_unstable(feature = "const_convert", issue = "143773")] + const impl FromStr for NonZero<$Int> { type Err = ParseIntError; /// Parses a non-zero integer from a string slice with decimal digits. From b2c6d2d7b45f0b0f1894d05d6590a8b0250c8303 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Fri, 28 Aug 2026 14:39:30 +0000 Subject: [PATCH 0375/1309] Refactor LivenessResults into LivenessComputation, without typeck --- .../rustc_borrowck/src/region_infer/values.rs | 10 - .../src/type_check/liveness/mod.rs | 20 +- .../src/type_check/liveness/trace.rs | 467 ++++++++++-------- 3 files changed, 272 insertions(+), 225 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 35009c3bad485..2f03fec0d2245 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -409,16 +409,6 @@ impl<'tcx, N: Idx> RegionValues<'tcx, N> { } } -/// For debugging purposes, returns a pretty-printed string of the given points. -pub(crate) fn pretty_print_points( - location_map: &DenseLocationMap, - points: impl IntoIterator, -) -> String { - pretty_print_region_elements( - points.into_iter().map(|p| location_map.to_location(p)).map(RegionElement::Location), - ) -} - /// For debugging purposes, returns a pretty-printed string of the given region elements. fn pretty_print_region_elements<'tcx>( elements: impl IntoIterator>, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 2de6635e93ac7..c2fa8ab8637af 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -1,15 +1,18 @@ use itertools::{Either, Itertools}; use rustc_data_structures::fx::FxHashSet; +use rustc_index::interval::IntervalSet; use rustc_middle::mir::visit::{TyContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, SourceInfo}; use rustc_middle::ty::relate::Relate; use rustc_middle::ty::{GenericArgsRef, Region, RegionVid, Ty, TyCtxt, TypeVisitable}; use rustc_mir_dataflow::move_paths::MoveData; -use rustc_mir_dataflow::points::DenseLocationMap; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use rustc_span::span_bug; +use rustc_trait_selection::traits::outlives_for_liveness::FreeRegionsVisitor; use tracing::debug; use super::TypeChecker; +use crate::BorrowckInferCtxt; use crate::constraints::OutlivesConstraintSet; use crate::polonius::{PoloniusContext, record_live_region_variance}; use crate::region_infer::values::LivenessValues; @@ -229,3 +232,18 @@ impl<'a, 'tcx> LiveVariablesVisitor<'a, 'tcx> { } } } + +pub(crate) fn make_all_regions_live<'tcx>( + infcx: &BorrowckInferCtxt<'tcx>, + universal_regions: &UniversalRegions<'tcx>, + liveness: &mut LivenessValues, + value: impl TypeVisitable>, + live_at: &IntervalSet, +) { + debug!("make_all_regions_live(value={value:?})"); + value.visit_with(&mut FreeRegionsVisitor { + tcx: infcx.tcx, + param_env: infcx.param_env, + op: |r| liveness.add_points(universal_regions.to_region_vid(r), live_at), + }); +} diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 90126866cd500..d0302faa513b2 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -6,7 +6,7 @@ use rustc_infer::infer::canonical::QueryRegionConstraints; use rustc_infer::traits::TraitErrors; use rustc_middle::mir::{BasicBlock, Body, ConstraintCategory, Local, Location}; use rustc_middle::traits::query::DropckOutlivesResult; -use rustc_middle::ty::{Ty, TyCtxt, TypeVisitable, TypeVisitableExt}; +use rustc_middle::ty::{GenericArg, Ty, TypeVisitableExt}; use rustc_mir_dataflow::impls::MaybeInitializedPlaces; use rustc_mir_dataflow::move_paths::{HasMoveData, MoveData, MovePathIndex}; use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; @@ -14,16 +14,17 @@ use rustc_mir_dataflow::{Analysis, MaybeReachable, ResultsCursor}; use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span}; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; use rustc_trait_selection::traits::ObligationCtxt; -use rustc_trait_selection::traits::outlives_for_liveness::FreeRegionsVisitor; use rustc_trait_selection::traits::query::dropck_outlives; use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOpOutput}; use tracing::debug; -use crate::BorrowckInferCtxt; -use crate::polonius::{self, record_live_region_variance}; -use crate::region_infer::values; +use crate::polonius::{LiveRegionVariances, record_live_region_variance}; +use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::local_use_map::LocalUseMap; +use crate::type_check::liveness::make_all_regions_live; use crate::type_check::{NormalizeLocation, TypeChecker}; +use crate::universal_regions::UniversalRegions; +use crate::{BorrowckInferCtxt, polonius}; /// This is the heart of the liveness computation. For each variable X /// that requires a liveness computation, it walks over all the uses @@ -48,33 +49,28 @@ pub(super) fn trace<'tcx>( ) { let _timer = typeck.tcx().prof.generic_activity("borrowck_liveness_trace"); - let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, typeck.body); - let cx = LivenessContext { - typeck, - flow_inits: None, + let local_use_map = LocalUseMap::build(&relevant_live_locals, location_map, typeck.body); + let comp = LivenessComputation::new( + typeck.infcx, + typeck.body, location_map, - local_use_map, move_data, - term_states: IndexVec::new(), - exit_states: IndexVec::new(), - drop_data: FxIndexMap::default(), - }; + &local_use_map, + ); - let mut results = LivenessResults::new(cx); + let mut results = LivenessResults::new(typeck, comp); - results.add_extra_drop_facts(relevant_live_locals); + results.record_legacy_polonius_drop_facts(relevant_live_locals); results.compute_for_all_locals(relevant_live_locals); results.dropck_boring_locals(boring_locals); } -/// Contextual state for the type-liveness coroutine. -struct LivenessContext<'a, 'typeck, 'tcx> { - /// Current type-checker, giving us our inference context etc. - /// - /// This also stores the body we're currently analyzing. - typeck: &'a mut TypeChecker<'typeck, 'tcx>, +pub(crate) struct LivenessComputation<'a, 'tcx> { + pub(crate) infcx: &'a BorrowckInferCtxt<'tcx>, + + pub(crate) body: &'a Body<'tcx>, /// Defines the `PointIndex` mapping location_map: &'a DenseLocationMap, @@ -82,9 +78,6 @@ struct LivenessContext<'a, 'typeck, 'tcx> { /// Mapping to/from the various indices used for initialization tracking. move_data: &'a MoveData<'tcx>, - /// Cache for the results of `dropck_outlives` query. - drop_data: FxIndexMap, DropData<'tcx>>, - /// Results of dataflow tracking which variables (and paths) have been /// initialized. Computed lazily when needed by drop-liveness. flow_inits: Option>>, @@ -96,15 +89,6 @@ struct LivenessContext<'a, 'typeck, 'tcx> { // Caches for the results of `initialized_at_terminator` and `initialized_at_exit`. term_states: IndexVec>>>, exit_states: IndexVec>>>, -} - -struct DropData<'tcx> { - dropck_result: DropckOutlivesResult<'tcx>, - region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>, -} - -struct LivenessResults<'a, 'typeck, 'tcx> { - cx: LivenessContext<'a, 'typeck, 'tcx>, /// Set of points that define the current local. defs: DenseBitSet, @@ -125,43 +109,70 @@ struct LivenessResults<'a, 'typeck, 'tcx> { stack: Vec, } +struct LivenessResults<'a, 'typeck, 'tcx> { + /// Current type-checker, giving us our inference context etc. + typeck: &'a mut TypeChecker<'typeck, 'tcx>, + + /// Cache for the results of `dropck_outlives` query. + drop_data: FxIndexMap, DropData<'tcx>>, + + comp: LivenessComputation<'a, 'tcx>, +} + impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { - fn new(cx: LivenessContext<'a, 'typeck, 'tcx>) -> Self { - let num_points = cx.location_map.num_points(); - LivenessResults { - cx, - defs: DenseBitSet::new_empty(num_points), - use_live_at: IntervalSet::new(num_points), - drop_live_at: DenseBitSet::new_empty(num_points), - drop_locations: vec![], - stack: vec![], - } + fn new( + typeck: &'a mut TypeChecker<'typeck, 'tcx>, + comp: LivenessComputation<'a, 'tcx>, + ) -> Self { + LivenessResults { typeck, drop_data: FxIndexMap::default(), comp } } fn compute_for_all_locals(&mut self, relevant_live_locals: &[Local]) { for &local in relevant_live_locals { - self.reset_local_state(); - self.add_defs_for(local); - self.compute_use_live_points_for(local); - self.compute_drop_live_points_for(local); + self.compute_for_local(local); + } + } - let local_ty = self.cx.body().local_decls[local].ty; + fn compute_for_local(&mut self, local: Local) { + // If we end up needing to compute the drop data (because there are + // drop-live points), then we need to register region constraints and + // emit drop facts. + let mut computed_drop_data = None; + + self.comp.compute( + local, + self.typeck.universal_regions, + self.typeck.polonius_context.as_mut().map(|c| &mut c.live_region_variances), + &mut self.typeck.constraints.liveness_constraints, + || { + let local_ty = self.comp.body.local_decls[local].ty; + let local_span = self.comp.body.local_decls[local].source_info.span; + let drop_data = + dropck_local(&self.typeck.infcx, &mut self.drop_data, local_ty, local_span); + let drop_data = computed_drop_data.insert(drop_data); + &drop_data.dropck_result.kinds + }, + ); - if !self.use_live_at.is_empty() { - self.cx.add_use_live_facts_for(local_ty, &self.use_live_at); + if let Some(drop_data) = computed_drop_data { + if let Some(data) = &drop_data.region_constraint_data { + for &drop_location in &self.comp.drop_locations { + self.typeck.push_region_constraints( + drop_location.to_locations(), + ConstraintCategory::Boring, + data, + ); + } } - if !self.drop_live_at.is_empty() { - // `drop_live_at` is using a DenseBitSet, but `add_drop_live_facts_for` expects - // an IntervalSet. We thus convert between those two here. - let mut set: IntervalSet = - IntervalSet::new(self.drop_live_at.domain_size()); - for item in self.drop_live_at.iter() { - // We iterate the `drop_live_at` set from smallest to largest values, so - // we can use append to add things to the interval set at the end. - set.append(item); - } - self.cx.add_drop_live_facts_for(local, local_ty, &self.drop_locations, &set); + for &kind in &drop_data.dropck_result.kinds { + polonius::legacy::emit_drop_facts( + self.typeck.tcx(), + local, + &kind, + self.typeck.universal_regions, + self.typeck.polonius_facts, + ); } } } @@ -174,27 +185,26 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { /// and can therefore safely be dropped. fn dropck_boring_locals(&mut self, boring_locals: &[Local]) { for &local in boring_locals { - let local_ty = self.cx.body().local_decls[local].ty; - let local_span = self.cx.body().local_decls[local].source_info.span; - dropck_local(&self.cx.typeck.infcx, &mut self.cx.drop_data, local_ty, local_span); + let local_ty = self.comp.body.local_decls[local].ty; + let local_span = self.comp.body.local_decls[local].source_info.span; + dropck_local(&self.typeck.infcx, &mut self.drop_data, local_ty, local_span); } } - /// Add extra drop facts needed for Polonius. + /// Add extra drop facts needed for Polonius Legacy. /// /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. - fn add_extra_drop_facts(&mut self, relevant_live_locals: &[Local]) { - // This collect is more necessary than immediately apparent - // because these facts go into `add_drop_live_facts_for()`, - // which also writes to `polonius_facts`, and so this is genuinely - // a simultaneous overlapping mutable borrow. + fn record_legacy_polonius_drop_facts(&mut self, relevant_live_locals: &[Local]) { + // This is *all wonky* because this used to call a shared + // `add_drop_live_facts_for` function that was also used for regular + // relevant locals. Presumably, this can be cleaned up quite a bit. // FIXME for future hackers: investigate whether this is // actually necessary; these facts come from Polonius // and probably maybe plausibly does not need to go back in. // It may be necessary to just pick out the parts of // `add_drop_live_facts_for()` that make sense. - let Some(facts) = self.cx.typeck.polonius_facts.as_ref() else { return }; + let Some(facts) = self.typeck.polonius_facts.as_ref() else { return }; let facts_to_add: Vec<_> = { let relevant_live_locals: FxIndexSet<_> = relevant_live_locals.iter().copied().collect(); @@ -203,20 +213,155 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { .var_dropped_at .iter() .filter_map(|&(local, location_index)| { - let local_ty = self.cx.body().local_decls[local].ty; + let local_ty = self.comp.body.local_decls[local].ty; if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() { return None; } - let location = self.cx.typeck.location_table.to_location(location_index); + let location = self.typeck.location_table.to_location(location_index); Some((local, local_ty, location)) }) .collect() }; - let live_at = IntervalSet::new(self.cx.location_map.num_points()); + let live_at = IntervalSet::new(self.comp.location_map.num_points()); for (local, local_ty, location) in facts_to_add { - self.cx.add_drop_live_facts_for(local, local_ty, &[location], &live_at); + let local_span = self.comp.body.local_decls[local].source_info.span; + let drop_data = + dropck_local(&self.typeck.infcx, &mut self.drop_data, local_ty, local_span); + + if let Some(data) = &drop_data.region_constraint_data { + self.typeck.push_region_constraints( + location.to_locations(), + ConstraintCategory::Boring, + data, + ); + } + + for &kind in &drop_data.dropck_result.kinds { + make_all_regions_live( + self.typeck.infcx, + self.typeck.universal_regions, + &mut self.typeck.constraints.liveness_constraints, + kind, + &live_at, + ); + polonius::legacy::emit_drop_facts( + self.typeck.tcx(), + local, + &kind, + self.typeck.universal_regions, + self.typeck.polonius_facts, + ); + } + + if let Some(polonius_context) = self.typeck.polonius_context.as_mut() { + record_live_region_variance( + self.typeck.infcx.tcx, + &mut polonius_context.live_region_variances, + self.typeck.universal_regions, + local_ty, + ); + } + } + } +} + +enum InitAtLocation { + Terminator, + Exit, +} + +impl<'a, 'tcx> LivenessComputation<'a, 'tcx> { + pub(crate) fn new( + infcx: &'a BorrowckInferCtxt<'tcx>, + body: &'a Body<'tcx>, + location_map: &'a DenseLocationMap, + move_data: &'a MoveData<'tcx>, + local_use_map: &'a LocalUseMap, + ) -> Self { + let num_points = location_map.num_points(); + LivenessComputation { + infcx, + body, + location_map, + move_data, + flow_inits: None, + local_use_map, + term_states: IndexVec::new(), + exit_states: IndexVec::new(), + defs: DenseBitSet::new_empty(num_points), + use_live_at: IntervalSet::new(num_points), + drop_live_at: DenseBitSet::new_empty(num_points), + drop_locations: vec![], + stack: vec![], + } + } + + /// Compute for a given local the use- and drop-live points + fn compute<'drop_data>( + &mut self, + local: Local, + universal_regions: &UniversalRegions<'tcx>, + live_region_variances: Option<&mut LiveRegionVariances>, + liveness_constraints: &mut LivenessValues, + get_drop_args: impl FnOnce() -> &'drop_data Vec>, + ) where + 'tcx: 'drop_data, + { + self.reset_local_state(); + self.add_defs_for(local); + self.compute_use_live_points_for(local); + self.compute_drop_live_points_for(local); + + let local_ty = self.body.local_decls[local].ty; + + // When using `-Zpolonius=next`, we also record the variance of regions in this live type. + // For dropck in particular, note that we walk the type and not its live components seen in + // the dropck results. See issue #160670. + let is_live_anywhere = !self.use_live_at.is_empty() || !self.drop_live_at.is_empty(); + if is_live_anywhere && let Some(live_region_variances) = live_region_variances { + record_live_region_variance( + self.infcx.tcx, + live_region_variances, + universal_regions, + local_ty, + ); + } + if !self.use_live_at.is_empty() { + make_all_regions_live( + self.infcx, + universal_regions, + liveness_constraints, + local_ty, + &self.use_live_at, + ); + } + if !self.drop_live_at.is_empty() { + let drop_data = get_drop_args(); + + // `drop_live_at` is using a DenseBitSet, but `make_all_regions_live` + // expects an IntervalSet. We thus convert between those two here. + // Using a `DenseBitSet` has better performance, but storing liveness + // as a dense matrix has worse performance. There's probably room here + // for some cleanup, but this works for now. + let mut drop_live_at: IntervalSet = + IntervalSet::new(self.drop_live_at.domain_size()); + for item in self.drop_live_at.iter() { + // We iterate the `drop_live_at` set from smallest to largest values, so + // we can use append to add things to the interval set at the end. + drop_live_at.append(item); + } + + for &kind in drop_data { + make_all_regions_live( + self.infcx, + universal_regions, + liveness_constraints, + kind, + &drop_live_at, + ); + } } } @@ -231,7 +376,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { /// Adds the definitions of `local` into `self.defs`. fn add_defs_for(&mut self, local: Local) { - for def in self.cx.local_use_map.defs(local) { + for def in self.local_use_map.defs(local) { debug!("- defined at {:?}", def); self.defs.insert(def); } @@ -246,14 +391,14 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { fn compute_use_live_points_for(&mut self, local: Local) { debug!("compute_use_live_points_for(local={:?})", local); - self.stack.extend(self.cx.local_use_map.uses(local)); + self.stack.extend(self.local_use_map.uses(local)); while let Some(p) = self.stack.pop() { // We are live in this block from the closest to us of: // // * Inclusively, the block start // * Exclusively, the previous definition (if it's in this block) // * Exclusively, the previous live_at setting (an optimization) - let block_start = self.cx.location_map.to_block_start(p); + let block_start = self.location_map.to_block_start(p); let previous_defs = self.defs.last_set_in(block_start..=p); let previous_live_at = self.use_live_at.last_set_in(block_start..=p); @@ -277,12 +422,12 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // terminators of predecessor basic blocks. Push those onto the // stack so that the next iteration(s) will process them. - let block = self.cx.location_map.to_location(block_start).block; + let block = self.location_map.to_location(block_start).block; self.stack.extend( - self.cx.body().basic_blocks.predecessors()[block] + self.body.basic_blocks.predecessors()[block] .iter() - .map(|&pred_bb| self.cx.body().terminator_loc(pred_bb)) - .map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)), + .map(|&pred_bb| self.body.terminator_loc(pred_bb)) + .map(|pred_loc| self.location_map.point_from_location(pred_loc)), ); } } @@ -300,15 +445,15 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { fn compute_drop_live_points_for(&mut self, local: Local) { debug!("compute_drop_live_points_for(local={:?})", local); - let Some(mpi) = self.cx.move_data.rev_lookup.find_local(local) else { return }; + let Some(mpi) = self.move_data.rev_lookup.find_local(local) else { return }; debug!("compute_drop_live_points_for: mpi = {:?}", mpi); // Find the drops where `local` is initialized. - for drop_point in self.cx.local_use_map.drops(local) { - let location = self.cx.location_map.to_location(drop_point); - debug_assert_eq!(self.cx.body().terminator_loc(location.block), location,); + for drop_point in self.local_use_map.drops(local) { + let location = self.location_map.to_location(drop_point); + debug_assert_eq!(self.body.terminator_loc(location.block), location,); - if self.cx.initialized_at_terminator(location.block, mpi) { + if self.initialized_at_terminator(location.block, mpi) { let inserted = self.drop_live_at.insert(drop_point); // Right now, we should not visit a drop_point twice. // If we do, this will trigger a debug assert so we know we can optimize. @@ -342,8 +487,8 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { fn compute_drop_live_points_for_block(&mut self, mpi: MovePathIndex, term_point: PointIndex) { debug!( "compute_drop_live_points_for_block(mpi={:?}, term_point={:?})", - self.cx.move_data.move_paths[mpi].place, - self.cx.location_map.to_location(term_point), + self.move_data.move_paths[mpi].place, + self.location_map.to_location(term_point), ); // We are only invoked with terminators where `mpi` is @@ -353,14 +498,14 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // Otherwise, scan backwards through the statements in the // block. One of them may be either a definition or use // live point. - let term_location = self.cx.location_map.to_location(term_point); - debug_assert_eq!(self.cx.body().terminator_loc(term_location.block), term_location,); + let term_location = self.location_map.to_location(term_point); + debug_assert_eq!(self.body.terminator_loc(term_location.block), term_location,); let block = term_location.block; - let entry_point = self.cx.location_map.entry_point(term_location.block); + let entry_point = self.location_map.entry_point(term_location.block); for p in (entry_point..term_point).rev() { debug!( "compute_drop_live_points_for_block: p = {:?}", - self.cx.location_map.to_location(p) + self.location_map.to_location(p) ); if self.defs.contains(p) { @@ -379,7 +524,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { } } - let body = self.cx.typeck.body; + let body = self.body; for &pred_block in body.basic_blocks.predecessors()[block].iter() { debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,); @@ -401,13 +546,13 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // terminator. *But*, in that case, the terminator is also // a *definition* of the variable, in which case we want // to stop the search anyhow. (But see Note 1 below.) - if !self.cx.initialized_at_exit(pred_block, mpi) { + if !self.initialized_at_exit(pred_block, mpi) { debug!("compute_drop_live_points_for_block: not initialized"); continue; } - let pred_term_loc = self.cx.body().terminator_loc(pred_block); - let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc); + let pred_term_loc = self.body.terminator_loc(pred_block); + let pred_term_point = self.location_map.point_from_location(pred_term_loc); // If the terminator of this predecessor either *assigns* // our value or is a "normal use", then stop. @@ -463,17 +608,6 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // for the call (`TMP = call()...`) and then a // `Drop(X)` followed by `X = TMP` to swap that with `X`. } -} - -enum InitAtLocation { - Terminator, - Exit, -} - -impl<'tcx> LivenessContext<'_, '_, 'tcx> { - fn body(&self) -> &Body<'tcx> { - self.typeck.body - } /// Returns `true` if the local variable (or some part of it) is initialized /// at the location defined by `init_at_location`. @@ -490,8 +624,8 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> { // - there are relevant live locals // - there are drop points for these relevant live locals. let flow_inits = self.flow_inits.get_or_insert_with(|| { - let tcx = self.typeck.tcx(); - let body = self.typeck.body; + let tcx = self.infcx.tcx; + let body = self.body; // FIXME: reduce the `MaybeInitializedPlaces` domain to the useful `MovePath`s. // // This dataflow analysis computes maybe-initializedness of all move paths, which @@ -515,7 +649,7 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> { InitAtLocation::Exit => &mut self.exit_states, }; let state = states.get_or_insert_with(block, || { - let terminator_location = self.typeck.body.terminator_loc(block); + let terminator_location = self.body.terminator_loc(block); match init_at_location { InitAtLocation::Terminator => { flow_inits.seek_before_primary_effect(terminator_location) @@ -548,109 +682,14 @@ impl<'tcx> LivenessContext<'_, '_, 'tcx> { fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool { self.initialized_at(block, mpi, InitAtLocation::Exit) } +} - /// Stores the result that all regions in `value` are live for the - /// points `live_at`. - fn add_use_live_facts_for(&mut self, value: Ty<'tcx>, live_at: &IntervalSet) { - debug!("add_use_live_facts_for(value={:?})", value); - Self::make_all_regions_live(self.location_map, self.typeck, value, live_at); - - // When using `-Zpolonius=next`, we also record the variance of regions in this live type. - if let Some(polonius_context) = self.typeck.polonius_context.as_mut() { - record_live_region_variance( - self.typeck.infcx.tcx, - &mut polonius_context.live_region_variances, - self.typeck.universal_regions, - value, - ); - } - } - - /// Some variable with type `live_ty` is "drop live" at `location` - /// -- i.e., it may be dropped later. This means that *some* of - /// the regions in its type must be live at `location`. The - /// precise set will depend on the dropck constraints, and in - /// particular this takes `#[may_dangle]` into account. - fn add_drop_live_facts_for( - &mut self, - dropped_local: Local, - dropped_ty: Ty<'tcx>, - drop_locations: &[Location], - live_at: &IntervalSet, - ) { - debug!( - "add_drop_live_constraint(\ - dropped_local={:?}, \ - dropped_ty={:?}, \ - drop_locations={:?}, \ - live_at={:?})", - dropped_local, - dropped_ty, - drop_locations, - values::pretty_print_points(self.location_map, live_at.iter()), - ); - - let dropped_span = self.body().local_decls[dropped_local].source_info.span; - let drop_data = - dropck_local(&self.typeck.infcx, &mut self.drop_data, dropped_ty, dropped_span); - - if let Some(data) = &drop_data.region_constraint_data { - for &drop_location in drop_locations { - self.typeck.push_region_constraints( - drop_location.to_locations(), - ConstraintCategory::Boring, - data, - ); - } - } - - // All things in the `outlives` array may be touched by - // the destructor and must be live at this point. - for &kind in &drop_data.dropck_result.kinds { - Self::make_all_regions_live(self.location_map, self.typeck, kind, live_at); - polonius::legacy::emit_drop_facts( - self.typeck.tcx(), - dropped_local, - &kind, - self.typeck.universal_regions, - self.typeck.polonius_facts, - ); - } - - // For polonius: since the local is drop live, record the variance of the regions in its - // type, not the ones in the type's live components seen in the dropck results above. See - // issue #160670. - if let Some(polonius_context) = self.typeck.polonius_context.as_mut() { - record_live_region_variance( - self.typeck.infcx.tcx, - &mut polonius_context.live_region_variances, - self.typeck.universal_regions, - dropped_ty, - ); - } - } - - fn make_all_regions_live( - location_map: &DenseLocationMap, - typeck: &mut TypeChecker<'_, 'tcx>, - value: impl TypeVisitable>, - live_at: &IntervalSet, - ) { - debug!("make_all_regions_live(value={:?})", value); - debug!( - "make_all_regions_live: live_at={}", - values::pretty_print_points(location_map, live_at.iter()), - ); - - value.visit_with(&mut FreeRegionsVisitor { - tcx: typeck.tcx(), - param_env: typeck.infcx.param_env, - op: |r| { - let live_region_vid = typeck.universal_regions.to_region_vid(r); - typeck.constraints.liveness_constraints.add_points(live_region_vid, live_at); - }, - }); - } +/// Contains the results of computing dropck for a local. Namely, this includes +/// the dropped types, and overflows found, and the region constraints that must +/// hold at drop. +struct DropData<'tcx> { + dropck_result: DropckOutlivesResult<'tcx>, + region_constraint_data: Option<&'tcx QueryRegionConstraints<'tcx>>, } /// Computes the `DropData` for a given type, caching the result. From 904fd444c294026cca5d1d78d18ce43ac0458d0b Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 18 Sep 2026 23:23:01 +1000 Subject: [PATCH 0376/1309] Increase visibility of some crate-root items before moving them This makes it easier to confirm that the move itself doesn't modify any code. --- compiler/rustc_codegen_llvm/src/lib.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 2554a518facd0..9040d314798f1 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -465,19 +465,19 @@ impl CodegenBackend for LlvmCodegenBackend { } pub struct ModuleLlvm { - llcx: &'static mut llvm::Context, + pub(crate) llcx: &'static mut llvm::Context, llmod_raw: *const llvm::Module, // This field is `ManuallyDrop` because it is important that the `TargetMachine` // is disposed prior to the `Context` being disposed otherwise UAFs can occur. - tm: ManuallyDrop, + pub(crate) tm: ManuallyDrop, } unsafe impl Send for ModuleLlvm {} unsafe impl Sync for ModuleLlvm {} impl ModuleLlvm { - fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { + pub(crate) fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { unsafe { let llcx = llvm::LLVMContextCreate(); llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); @@ -490,7 +490,7 @@ impl ModuleLlvm { } } - fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { + pub(crate) fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { unsafe { let llcx = llvm::LLVMContextCreate(); llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); @@ -503,7 +503,7 @@ impl ModuleLlvm { } } - fn parse( + pub(crate) fn parse( cgcx: &CodegenContext, tm_factory: TargetMachineFactoryFn, name: &CStr, @@ -520,7 +520,7 @@ impl ModuleLlvm { } } - fn llmod(&self) -> &llvm::Module { + pub(crate) fn llmod(&self) -> &llvm::Module { unsafe { &*self.llmod_raw } } } From eb921eeb3c13a0a806d959f2e333e56f621e5b7c Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 18 Sep 2026 18:02:02 +1000 Subject: [PATCH 0377/1309] Move all code out of the crate root Having non-trivial code in the crate root causes a few problems, most of which stem from every item being effectively `pub(crate)`: - Fields/methods can't be private, so enforcing abstractions is impossible - Every `use` becomes a de-facto re-export, leading to messy imports - Moving items out of the root requires visibility adjustment --- compiler/rustc_codegen_llvm/src/allocator.rs | 3 +- compiler/rustc_codegen_llvm/src/attributes.rs | 3 +- .../src/back/llvm_backend.rs | 494 ++++++++++++++++++ compiler/rustc_codegen_llvm/src/back/mod.rs | 1 + compiler/rustc_codegen_llvm/src/back/write.rs | 3 +- compiler/rustc_codegen_llvm/src/base.rs | 3 +- .../src/builder/gpu_offload.rs | 3 +- .../src/coverageinfo/mapgen.rs | 3 +- compiler/rustc_codegen_llvm/src/lib.rs | 493 +---------------- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 3 +- 10 files changed, 509 insertions(+), 500 deletions(-) create mode 100644 compiler/rustc_codegen_llvm/src/back/llvm_backend.rs diff --git a/compiler/rustc_codegen_llvm/src/allocator.rs b/compiler/rustc_codegen_llvm/src/allocator.rs index f24f4fbacf2f7..ef77abd53527d 100644 --- a/compiler/rustc_codegen_llvm/src/allocator.rs +++ b/compiler/rustc_codegen_llvm/src/allocator.rs @@ -12,9 +12,10 @@ use rustc_symbol_mangling::mangle_internal_symbol; use crate::attributes::llfn_attrs_from_instance; use crate::builder::SBuilder; +use crate::context::SimpleCx; use crate::declare::declare_simple_fn; use crate::llvm::{self, FromGeneric, TRUE, Type}; -use crate::{SimpleCx, attributes, debuginfo}; +use crate::{attributes, debuginfo}; pub(crate) unsafe fn codegen( tcx: TyCtxt<'_>, diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs index 8a7e3ec6b5942..4073d521293a9 100644 --- a/compiler/rustc_codegen_llvm/src/attributes.rs +++ b/compiler/rustc_codegen_llvm/src/attributes.rs @@ -8,6 +8,7 @@ use rustc_middle::middle::codegen_fn_attrs::{ }; use rustc_middle::ty::{self, Instance, TyCtxt}; use rustc_sanitizers::ignorelist::SanitizerIgnoreList; +use rustc_session::Session; use rustc_session::config::{ BranchProtection, FunctionReturn, InstrumentMcount, InstrumentMcountOpts, OptLevel, PAuthKey, PacRet, @@ -23,7 +24,7 @@ use crate::llvm::AttributePlace::Function; use crate::llvm::{ self, AllocKindFlags, Attribute, AttributeKind, AttributePlace, MemoryEffects, Value, }; -use crate::{Session, attributes, llvm_util}; +use crate::{attributes, llvm_util}; pub(crate) fn apply_to_llfn(llfn: &Value, idx: AttributePlace, attrs: &[&Attribute]) { if !attrs.is_empty() { diff --git a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs new file mode 100644 index 0000000000000..3f89777bb28db --- /dev/null +++ b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs @@ -0,0 +1,494 @@ +//! Module containing [`LlvmCodegenBackend`], which implements [`CodegenBackend`] +//! and related traits for the LLVM codegen backend. + +use std::any::Any; +use std::ffi::CStr; +use std::mem::ManuallyDrop; +use std::path::PathBuf; + +use rustc_ast::expand::allocator::AllocatorMethod; +use rustc_codegen_ssa::back::lto::ThinModule; +use rustc_codegen_ssa::back::write::{ + CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig, + TargetMachineFactoryFn, ThinLtoInput, +}; +use rustc_codegen_ssa::traits::{CodegenBackend, ExtraBackendMethods, WriteBackendMethods}; +use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; +use rustc_data_structures::profiling::SelfProfilerRef; +use rustc_errors::{DiagCtxt, DiagCtxtHandle}; +use rustc_metadata::EncodedMetadata; +use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; +use rustc_middle::ty::TyCtxt; +use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; +use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; +use rustc_span::{Symbol, sym}; +use rustc_target::spec::{RelocModel, TlsModel}; + +use crate::back::owned_target_machine::OwnedTargetMachine; +use crate::back::write::{create_informational_target_machine, create_target_machine}; +use crate::context::{self, SimpleCx}; +use crate::llvm::{self, ToLlvmBool}; +use crate::llvm_util::{self, target_config}; +use crate::{allocator, back, base}; + +#[derive(Clone)] +pub struct LlvmCodegenBackend(()); + +struct TimeTraceProfiler {} + +impl TimeTraceProfiler { + fn new() -> Self { + unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() } + TimeTraceProfiler {} + } +} + +impl Drop for TimeTraceProfiler { + fn drop(&mut self) { + unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() } + } +} + +impl ExtraBackendMethods for LlvmCodegenBackend { + type Module = ModuleLlvm; + + fn codegen_allocator<'tcx>( + &self, + tcx: TyCtxt<'tcx>, + module_name: &str, + methods: &[AllocatorMethod], + ) -> ModuleLlvm { + let module_llvm = ModuleLlvm::new_metadata(tcx, module_name); + let cx = + SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size()); + unsafe { + allocator::codegen(tcx, cx, module_name, methods); + } + module_llvm + } + fn compile_codegen_unit( + &self, + tcx: TyCtxt<'_>, + cgu_name: Symbol, + bitcode_needed: bool, + ) -> (ModuleCodegen, u64) { + base::compile_codegen_unit(tcx, cgu_name, bitcode_needed) + } +} + +impl WriteBackendMethods for LlvmCodegenBackend { + type Module = ModuleLlvm; + type ModuleBuffer = back::lto::ModuleBuffer; + type TargetMachine = OwnedTargetMachine; + type ThinData = back::lto::ThinData; + + fn thread_profiler() -> Box { + Box::new(TimeTraceProfiler::new()) + } + fn target_machine_factory( + &self, + sess: &Session, + optlvl: OptLevel, + ) -> TargetMachineFactoryFn { + back::write::target_machine_factory(sess, optlvl) + } + fn optimize_and_codegen_fat_lto( + sess: &Session, + cgcx: &CodegenContext, + shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, + exported_symbols_for_lto: &[String], + each_linked_rlib_for_lto: &[PathBuf], + modules: Vec>, + ) -> CompiledModule { + let mut module = back::lto::run_fat( + cgcx, + &sess.prof, + shared_emitter, + tm_factory, + exported_symbols_for_lto, + each_linked_rlib_for_lto, + modules, + ); + + let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); + let dcx = dcx.handle(); + back::lto::run_pass_manager(cgcx, &sess.prof, dcx, &mut module, false); + + back::write::codegen(cgcx, &sess.prof, shared_emitter, module, &cgcx.module_config) + } + fn run_thin_lto( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, + dcx: DiagCtxtHandle<'_>, + exported_symbols_for_lto: &[String], + each_linked_rlib_for_lto: &[PathBuf], + modules: Vec>, + ) -> (Vec>, Vec) { + back::lto::run_thin( + cgcx, + prof, + dcx, + exported_symbols_for_lto, + each_linked_rlib_for_lto, + modules, + ) + } + fn optimize( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, + shared_emitter: &SharedEmitter, + module: &mut ModuleCodegen, + config: &ModuleConfig, + ) { + back::write::optimize(cgcx, prof, shared_emitter, module, config) + } + fn optimize_and_codegen_thin( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, + shared_emitter: &SharedEmitter, + tm_factory: TargetMachineFactoryFn, + thin: ThinModule, + ) -> CompiledModule { + back::lto::optimize_and_codegen_thin_module(cgcx, prof, shared_emitter, tm_factory, thin) + } + fn codegen( + cgcx: &CodegenContext, + prof: &SelfProfilerRef, + shared_emitter: &SharedEmitter, + module: ModuleCodegen, + config: &ModuleConfig, + ) -> CompiledModule { + back::write::codegen(cgcx, prof, shared_emitter, module, config) + } + fn serialize_module(module: Self::Module, is_thin: bool) -> Self::ModuleBuffer { + back::lto::ModuleBuffer::new(module.llmod(), is_thin) + } +} + +impl LlvmCodegenBackend { + pub fn new() -> Box { + Box::new(LlvmCodegenBackend(())) + } +} + +impl CodegenBackend for LlvmCodegenBackend { + fn name(&self) -> &'static str { + "llvm" + } + + fn init(&mut self, sess: &EarlySession) -> CodegenBackendInit { + llvm_util::init(sess); // Make sure llvm is inited + + let global_backend_features = + llvm_util::global_llvm_features(sess, /* for_cfg */ false); + + // autodiff is based on Enzyme, a library which we might not have available, when it was + // neither build, nor downloaded via rustup. If autodiff is used, but not available we emit + // an early error here and abort compilation. + { + use rustc_session::config::AutoDiff; + + use crate::back::lto::enable_autodiff_settings; + if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) { + match llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { + Ok(_) => {} + Err(llvm::EnzymeLibraryError::NotFound { err }) => { + sess.dcx().emit_fatal(crate::diagnostics::AutoDiffComponentMissing { err }); + } + Err(llvm::EnzymeLibraryError::LoadFailed { err }) => { + sess.dcx() + .emit_fatal(crate::diagnostics::AutoDiffComponentUnavailable { err }); + } + } + enable_autodiff_settings(&sess.opts.unstable_opts.autodiff); + } + } + + // Intrinsics whose fallback body will not be used by the LLVM backend. + let replaced_intrinsics = { + #[rustfmt::skip] + let mut will_not_use_fallback = vec![ + // These are mapped to LLVM intrinsics instead. + sym::unchecked_funnel_shl, + sym::unchecked_funnel_shr, + sym::carrying_mul_add, + sym::integer_max, + sym::integer_min, + + // Fallback via libm, but the LLVM intrinsic is used instead. + sym::sin, + sym::cos, + sym::powf16, sym::powf32, sym::powf64, + sym::exp, + sym::exp2, + sym::log, + sym::log10, + sym::log2, + + // Fallback via f32 or f64, but the LLVM intrinsic is used instead. + sym::floorf16, sym::ceilf16, sym::truncf16, + sym::round_ties_even_f16, sym::roundf16, + sym::sqrtf16, sym::powif16, + sym::fmaf16, + + sym::copysignf16, sym::copysignf32, sym::copysignf64, sym::copysignf128, + ]; + + if llvm_util::get_version() >= (22, 0, 0) { + will_not_use_fallback.push(sym::carryless_mul); + } + + will_not_use_fallback + }; + + // `type_id_eq` is a safe choice since *all* backends use the fallback body for that. When + // adding more intrinsics, keep in mind that the distributed standard library is compiled + // with the LLVM backend but might later be included in a project built with cranelift or + // GCC. Adding an intrinsic here can therefore mean the fallback body is used with + // cranelift/GCC even if they have dedicated implementations. + let fallback_intrinsics = vec![sym::type_id_eq]; + + CodegenBackendInit { + global_backend_features, + replaced_intrinsics, + fallback_intrinsics, + thin_lto_supported: true, + } + } + + fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) { + use std::fmt::Write; + match req.kind { + PrintKind::RelocationModels => { + writeln!(out, "Available relocation models:").unwrap(); + for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) { + writeln!(out, " {name}").unwrap(); + } + writeln!(out).unwrap(); + } + PrintKind::CodeModels => { + writeln!(out, "Available code models:").unwrap(); + for name in &["tiny", "small", "kernel", "medium", "large"] { + writeln!(out, " {name}").unwrap(); + } + writeln!(out).unwrap(); + } + PrintKind::TlsModels => { + writeln!(out, "Available TLS models:").unwrap(); + for name in TlsModel::ALL.iter().map(TlsModel::desc) { + writeln!(out, " {name}").unwrap(); + } + writeln!(out).unwrap(); + } + PrintKind::StackProtectorStrategies => { + writeln!( + out, + r#"Available stack protector strategies: + all + Generate stack canaries in all functions. + + strong + Generate stack canaries in a function if it either: + - has a local variable of `[T; N]` type, regardless of `T` and `N` + - takes the address of a local variable. + + (Note that a local variable being borrowed is not equivalent to its + address being taken: e.g. some borrows may be removed by optimization, + while by-value argument passing may be implemented with reference to a + local stack variable in the ABI.) + + basic + Generate stack canaries in functions with local variables of `[T; N]` + type, where `T` is byte-sized and `N` >= 8. + + none + Do not generate stack canaries. +"# + ) + .unwrap(); + } + _other => llvm_util::print(req, out, sess), + } + } + + fn print_passes(&self) { + llvm_util::print_passes(); + } + + fn print_version(&self) { + llvm_util::print_version(); + } + + fn has_zstd(&self) -> bool { + llvm::LLVMRustLLVMHasZstdCompression() + } + + fn has_mnemonic(&self, sess: &Session, mnemonic: &str) -> bool { + llvm_util::target_has_mnemonic(sess, mnemonic) + } + + fn target_config(&self, sess: &EarlySession) -> TargetConfig { + target_config(sess) + } + + fn target_cpu(&self, sess: &Session) -> String { + crate::llvm_util::target_cpu(sess).to_string() + } + + fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { + use rustc_session::config::Offload; + + if tcx.sess.opts.unstable_opts.offload.iter().any(|o| matches!(o, Offload::Device(_))) + || tcx.sess.opts.unstable_opts.offload.iter().any(|o| matches!(o, Offload::Host(_))) + { + match llvm::RustOffloadWrapper::get_or_init(&tcx.sess.opts.sysroot) { + Ok(_) => {} + Err(llvm::RustOffloadLibraryError::NotFound { err }) => { + tcx.sess + .dcx() + .emit_fatal(crate::diagnostics::RustOffloadComponentMissing { err }); + } + Err(llvm::RustOffloadLibraryError::LoadFailed { err }) => { + tcx.sess + .dcx() + .emit_fatal(crate::diagnostics::RustOffloadComponentUnavailable { err }); + } + } + } + + Box::new(rustc_codegen_ssa::base::codegen_crate(LlvmCodegenBackend(()), tcx)) + } + + fn join_codegen( + &self, + ongoing_codegen: Box, + sess: &Session, + incr_comp_session: Option<&IncrCompSession>, + outputs: &OutputFilenames, + crate_info: &CrateInfo, + ) -> (CompiledModules, WorkProductMap) { + let (compiled_modules, work_products) = ongoing_codegen + .downcast::>() + .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") + .join(sess, incr_comp_session, crate_info); + + if sess.opts.unstable_opts.llvm_time_trace { + sess.time("llvm_dump_timing_file", || { + let file_name = outputs.with_extension("llvm_timings.json"); + llvm_util::time_trace_profiler_finish(&file_name); + }); + } + + (compiled_modules, work_products) + } + + fn print_pass_timings(&self) { + let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap(); + print!("{timings}"); + } + + fn print_statistics(&self) { + let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap(); + print!("{stats}"); + } + + fn print_statistics_json(&self) -> String { + llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatisticsJSON(s) }).unwrap() + } + + fn link( + &self, + sess: &Session, + compiled_modules: CompiledModules, + crate_info: CrateInfo, + metadata: EncodedMetadata, + outputs: &OutputFilenames, + ) { + use rustc_codegen_ssa::back::link::link_binary; + + use crate::back::archive::LlvmArchiveBuilderBuilder; + + // Run the linker on any artifacts that resulted from the LLVM run. + // This should produce either a finished executable or library. + link_binary( + sess, + &LlvmArchiveBuilderBuilder, + compiled_modules, + crate_info, + metadata, + outputs, + self.name(), + ); + } +} + +pub struct ModuleLlvm { + pub(crate) llcx: &'static mut llvm::Context, + llmod_raw: *const llvm::Module, + + // This field is `ManuallyDrop` because it is important that the `TargetMachine` + // is disposed prior to the `Context` being disposed otherwise UAFs can occur. + pub(crate) tm: ManuallyDrop, +} + +unsafe impl Send for ModuleLlvm {} +unsafe impl Sync for ModuleLlvm {} + +impl ModuleLlvm { + pub(crate) fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { + unsafe { + let llcx = llvm::LLVMContextCreate(); + llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); + let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; + ModuleLlvm { + llmod_raw, + llcx, + tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)), + } + } + } + + pub(crate) fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { + unsafe { + let llcx = llvm::LLVMContextCreate(); + llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); + let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; + ModuleLlvm { + llmod_raw, + llcx, + tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)), + } + } + } + + pub(crate) fn parse( + cgcx: &CodegenContext, + tm_factory: TargetMachineFactoryFn, + name: &CStr, + buffer: &[u8], + dcx: DiagCtxtHandle<'_>, + ) -> Self { + unsafe { + let llcx = llvm::LLVMContextCreate(); + llvm::LLVMContextSetDiscardValueNames(llcx, cgcx.fewer_names.to_llvm_bool()); + let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx); + let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap())); + + ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) } + } + } + + pub(crate) fn llmod(&self) -> &llvm::Module { + unsafe { &*self.llmod_raw } + } +} + +impl Drop for ModuleLlvm { + fn drop(&mut self) { + unsafe { + ManuallyDrop::drop(&mut self.tm); + llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); + } + } +} diff --git a/compiler/rustc_codegen_llvm/src/back/mod.rs b/compiler/rustc_codegen_llvm/src/back/mod.rs index de6007c17bfff..3ecd7dd892d37 100644 --- a/compiler/rustc_codegen_llvm/src/back/mod.rs +++ b/compiler/rustc_codegen_llvm/src/back/mod.rs @@ -1,4 +1,5 @@ pub(crate) mod archive; +pub(crate) mod llvm_backend; pub(crate) mod lto; pub(crate) mod owned_mc_subtarget_info; pub(crate) mod owned_target_machine; diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index 92989ba2dcf46..b3882ba51749d 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -34,6 +34,7 @@ use crate::back::profiling::{ use crate::builder::SBuilder; use crate::builder::gpu_offload::scalar_width; use crate::common::AsCCharPtr; +use crate::context::SimpleCx; use crate::diagnostics::{ CopyBitcode, FromLlvmDiag, FromLlvmOptimizationDiag, LlvmError, ParseTargetMachineConfig, UnsupportedCompression, WithLlvmError, WriteBytecode, @@ -41,7 +42,7 @@ use crate::diagnostics::{ use crate::llvm::diagnostic::OptimizationDiagnosticKind::*; use crate::llvm::{self, DiagnosticInfo}; use crate::type_::llvm_type_ptr; -use crate::{LlvmCodegenBackend, ModuleLlvm, SimpleCx, attributes, base, common, llvm_util}; +use crate::{LlvmCodegenBackend, ModuleLlvm, attributes, base, common, llvm_util}; pub(crate) fn llvm_err<'a>(dcx: DiagCtxtHandle<'_>, err: LlvmError<'a>) -> ! { match llvm::last_error() { diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 5316b7425be47..6e7c31f7743d7 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -27,12 +27,11 @@ use rustc_session::config::{DebugInfo, Offload}; use rustc_span::Symbol; use rustc_target::spec::SanitizerSet; -use super::ModuleLlvm; -use crate::attributes; use crate::builder::Builder; use crate::builder::gpu_offload::OffloadGlobals; use crate::context::CodegenCx; use crate::llvm::{self, Value}; +use crate::{ModuleLlvm, attributes}; pub(crate) struct ValueIter<'ll> { cur: Option<&'ll Value>, diff --git a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs index 8ff98b498aa94..d3bb8d7c3e6a4 100644 --- a/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs +++ b/compiler/rustc_codegen_llvm/src/builder/gpu_offload.rs @@ -10,11 +10,12 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSl use rustc_middle::ty::offload_meta::{MappingFlags, OffloadMetadata, OffloadSize}; use rustc_span::bug; +use crate::attributes; use crate::builder::Builder; use crate::common::CodegenCx; +use crate::context::SimpleCx; use crate::llvm::AttributePlace::Function; use crate::llvm::{self, Linkage, Type, Value}; -use crate::{SimpleCx, attributes}; // LLVM kernel-independent globals required for offloading pub(crate) struct OffloadGlobals<'ll> { diff --git a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs index 3dac4b3e0167f..c77a19658c814 100644 --- a/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs +++ b/compiler/rustc_codegen_llvm/src/coverageinfo/mapgen.rs @@ -11,7 +11,8 @@ use tracing::debug; use crate::common::CodegenCx; use crate::coverageinfo::llvm_cov; use crate::coverageinfo::mapgen::covfun::prepare_covfun_record; -use crate::{TryFromU32, llvm}; +use crate::llvm; +use crate::macros::TryFromU32; mod covfun; mod spans; diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 9040d314798f1..19bbf0cf3d8d8 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -15,34 +15,7 @@ #![feature(try_blocks)] // tidy-alphabetical-end -use std::any::Any; -use std::ffi::CStr; -use std::mem::ManuallyDrop; -use std::path::PathBuf; - -use back::owned_target_machine::OwnedTargetMachine; -use back::write::{create_informational_target_machine, create_target_machine}; -use context::SimpleCx; -use llvm_util::target_config; -use rustc_ast::expand::allocator::AllocatorMethod; -use rustc_codegen_ssa::back::lto::ThinModule; -use rustc_codegen_ssa::back::write::{ - CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryConfig, - TargetMachineFactoryFn, ThinLtoInput, -}; -use rustc_codegen_ssa::traits::*; -use rustc_codegen_ssa::{CompiledModule, CompiledModules, CrateInfo, ModuleCodegen, TargetConfig}; -use rustc_data_structures::profiling::SelfProfilerRef; -use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_metadata::EncodedMetadata; -use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; -use rustc_middle::ty::TyCtxt; -use rustc_session::config::{OptLevel, OutputFilenames, PrintKind, PrintRequest}; -use rustc_session::{CodegenBackendInit, EarlySession, IncrCompSession, Session}; -use rustc_span::{Symbol, sym}; -use rustc_target::spec::{RelocModel, TlsModel}; - -use crate::llvm::ToLlvmBool; +pub use crate::back::llvm_backend::{LlvmCodegenBackend, ModuleLlvm}; mod abi; mod allocator; @@ -69,467 +42,3 @@ mod type_of; mod typetree; mod va_arg; mod value; - -pub(crate) use macros::TryFromU32; - -#[derive(Clone)] -pub struct LlvmCodegenBackend(()); - -struct TimeTraceProfiler {} - -impl TimeTraceProfiler { - fn new() -> Self { - unsafe { llvm::LLVMRustTimeTraceProfilerInitialize() } - TimeTraceProfiler {} - } -} - -impl Drop for TimeTraceProfiler { - fn drop(&mut self) { - unsafe { llvm::LLVMRustTimeTraceProfilerFinishThread() } - } -} - -impl ExtraBackendMethods for LlvmCodegenBackend { - type Module = ModuleLlvm; - - fn codegen_allocator<'tcx>( - &self, - tcx: TyCtxt<'tcx>, - module_name: &str, - methods: &[AllocatorMethod], - ) -> ModuleLlvm { - let module_llvm = ModuleLlvm::new_metadata(tcx, module_name); - let cx = - SimpleCx::new(module_llvm.llmod(), &module_llvm.llcx, tcx.data_layout.pointer_size()); - unsafe { - allocator::codegen(tcx, cx, module_name, methods); - } - module_llvm - } - fn compile_codegen_unit( - &self, - tcx: TyCtxt<'_>, - cgu_name: Symbol, - bitcode_needed: bool, - ) -> (ModuleCodegen, u64) { - base::compile_codegen_unit(tcx, cgu_name, bitcode_needed) - } -} - -impl WriteBackendMethods for LlvmCodegenBackend { - type Module = ModuleLlvm; - type ModuleBuffer = back::lto::ModuleBuffer; - type TargetMachine = OwnedTargetMachine; - type ThinData = back::lto::ThinData; - - fn thread_profiler() -> Box { - Box::new(TimeTraceProfiler::new()) - } - fn target_machine_factory( - &self, - sess: &Session, - optlvl: OptLevel, - ) -> TargetMachineFactoryFn { - back::write::target_machine_factory(sess, optlvl) - } - fn optimize_and_codegen_fat_lto( - sess: &Session, - cgcx: &CodegenContext, - shared_emitter: &SharedEmitter, - tm_factory: TargetMachineFactoryFn, - exported_symbols_for_lto: &[String], - each_linked_rlib_for_lto: &[PathBuf], - modules: Vec>, - ) -> CompiledModule { - let mut module = back::lto::run_fat( - cgcx, - &sess.prof, - shared_emitter, - tm_factory, - exported_symbols_for_lto, - each_linked_rlib_for_lto, - modules, - ); - - let dcx = DiagCtxt::new(Box::new(shared_emitter.clone())); - let dcx = dcx.handle(); - back::lto::run_pass_manager(cgcx, &sess.prof, dcx, &mut module, false); - - back::write::codegen(cgcx, &sess.prof, shared_emitter, module, &cgcx.module_config) - } - fn run_thin_lto( - cgcx: &CodegenContext, - prof: &SelfProfilerRef, - dcx: DiagCtxtHandle<'_>, - exported_symbols_for_lto: &[String], - each_linked_rlib_for_lto: &[PathBuf], - modules: Vec>, - ) -> (Vec>, Vec) { - back::lto::run_thin( - cgcx, - prof, - dcx, - exported_symbols_for_lto, - each_linked_rlib_for_lto, - modules, - ) - } - fn optimize( - cgcx: &CodegenContext, - prof: &SelfProfilerRef, - shared_emitter: &SharedEmitter, - module: &mut ModuleCodegen, - config: &ModuleConfig, - ) { - back::write::optimize(cgcx, prof, shared_emitter, module, config) - } - fn optimize_and_codegen_thin( - cgcx: &CodegenContext, - prof: &SelfProfilerRef, - shared_emitter: &SharedEmitter, - tm_factory: TargetMachineFactoryFn, - thin: ThinModule, - ) -> CompiledModule { - back::lto::optimize_and_codegen_thin_module(cgcx, prof, shared_emitter, tm_factory, thin) - } - fn codegen( - cgcx: &CodegenContext, - prof: &SelfProfilerRef, - shared_emitter: &SharedEmitter, - module: ModuleCodegen, - config: &ModuleConfig, - ) -> CompiledModule { - back::write::codegen(cgcx, prof, shared_emitter, module, config) - } - fn serialize_module(module: Self::Module, is_thin: bool) -> Self::ModuleBuffer { - back::lto::ModuleBuffer::new(module.llmod(), is_thin) - } -} - -impl LlvmCodegenBackend { - pub fn new() -> Box { - Box::new(LlvmCodegenBackend(())) - } -} - -impl CodegenBackend for LlvmCodegenBackend { - fn name(&self) -> &'static str { - "llvm" - } - - fn init(&mut self, sess: &EarlySession) -> CodegenBackendInit { - llvm_util::init(sess); // Make sure llvm is inited - - let global_backend_features = - llvm_util::global_llvm_features(sess, /* for_cfg */ false); - - // autodiff is based on Enzyme, a library which we might not have available, when it was - // neither build, nor downloaded via rustup. If autodiff is used, but not available we emit - // an early error here and abort compilation. - { - use rustc_session::config::AutoDiff; - - use crate::back::lto::enable_autodiff_settings; - if sess.opts.unstable_opts.autodiff.contains(&AutoDiff::Enable) { - match llvm::EnzymeWrapper::get_or_init(&sess.opts.sysroot) { - Ok(_) => {} - Err(llvm::EnzymeLibraryError::NotFound { err }) => { - sess.dcx().emit_fatal(crate::diagnostics::AutoDiffComponentMissing { err }); - } - Err(llvm::EnzymeLibraryError::LoadFailed { err }) => { - sess.dcx() - .emit_fatal(crate::diagnostics::AutoDiffComponentUnavailable { err }); - } - } - enable_autodiff_settings(&sess.opts.unstable_opts.autodiff); - } - } - - // Intrinsics whose fallback body will not be used by the LLVM backend. - let replaced_intrinsics = { - #[rustfmt::skip] - let mut will_not_use_fallback = vec![ - // These are mapped to LLVM intrinsics instead. - sym::unchecked_funnel_shl, - sym::unchecked_funnel_shr, - sym::carrying_mul_add, - sym::integer_max, - sym::integer_min, - - // Fallback via libm, but the LLVM intrinsic is used instead. - sym::sin, - sym::cos, - sym::powf16, sym::powf32, sym::powf64, - sym::exp, - sym::exp2, - sym::log, - sym::log10, - sym::log2, - - // Fallback via f32 or f64, but the LLVM intrinsic is used instead. - sym::floorf16, sym::ceilf16, sym::truncf16, - sym::round_ties_even_f16, sym::roundf16, - sym::sqrtf16, sym::powif16, - sym::fmaf16, - - sym::copysignf16, sym::copysignf32, sym::copysignf64, sym::copysignf128, - ]; - - if llvm_util::get_version() >= (22, 0, 0) { - will_not_use_fallback.push(sym::carryless_mul); - } - - will_not_use_fallback - }; - - // `type_id_eq` is a safe choice since *all* backends use the fallback body for that. When - // adding more intrinsics, keep in mind that the distributed standard library is compiled - // with the LLVM backend but might later be included in a project built with cranelift or - // GCC. Adding an intrinsic here can therefore mean the fallback body is used with - // cranelift/GCC even if they have dedicated implementations. - let fallback_intrinsics = vec![sym::type_id_eq]; - - CodegenBackendInit { - global_backend_features, - replaced_intrinsics, - fallback_intrinsics, - thin_lto_supported: true, - } - } - - fn print(&self, req: &PrintRequest, out: &mut String, sess: &Session) { - use std::fmt::Write; - match req.kind { - PrintKind::RelocationModels => { - writeln!(out, "Available relocation models:").unwrap(); - for name in RelocModel::ALL.iter().map(RelocModel::desc).chain(["default"]) { - writeln!(out, " {name}").unwrap(); - } - writeln!(out).unwrap(); - } - PrintKind::CodeModels => { - writeln!(out, "Available code models:").unwrap(); - for name in &["tiny", "small", "kernel", "medium", "large"] { - writeln!(out, " {name}").unwrap(); - } - writeln!(out).unwrap(); - } - PrintKind::TlsModels => { - writeln!(out, "Available TLS models:").unwrap(); - for name in TlsModel::ALL.iter().map(TlsModel::desc) { - writeln!(out, " {name}").unwrap(); - } - writeln!(out).unwrap(); - } - PrintKind::StackProtectorStrategies => { - writeln!( - out, - r#"Available stack protector strategies: - all - Generate stack canaries in all functions. - - strong - Generate stack canaries in a function if it either: - - has a local variable of `[T; N]` type, regardless of `T` and `N` - - takes the address of a local variable. - - (Note that a local variable being borrowed is not equivalent to its - address being taken: e.g. some borrows may be removed by optimization, - while by-value argument passing may be implemented with reference to a - local stack variable in the ABI.) - - basic - Generate stack canaries in functions with local variables of `[T; N]` - type, where `T` is byte-sized and `N` >= 8. - - none - Do not generate stack canaries. -"# - ) - .unwrap(); - } - _other => llvm_util::print(req, out, sess), - } - } - - fn print_passes(&self) { - llvm_util::print_passes(); - } - - fn print_version(&self) { - llvm_util::print_version(); - } - - fn has_zstd(&self) -> bool { - llvm::LLVMRustLLVMHasZstdCompression() - } - - fn has_mnemonic(&self, sess: &Session, mnemonic: &str) -> bool { - llvm_util::target_has_mnemonic(sess, mnemonic) - } - - fn target_config(&self, sess: &EarlySession) -> TargetConfig { - target_config(sess) - } - - fn target_cpu(&self, sess: &Session) -> String { - crate::llvm_util::target_cpu(sess).to_string() - } - - fn codegen_crate<'tcx>(&self, tcx: TyCtxt<'tcx>) -> Box { - use rustc_session::config::Offload; - - if tcx.sess.opts.unstable_opts.offload.iter().any(|o| matches!(o, Offload::Device(_))) - || tcx.sess.opts.unstable_opts.offload.iter().any(|o| matches!(o, Offload::Host(_))) - { - match llvm::RustOffloadWrapper::get_or_init(&tcx.sess.opts.sysroot) { - Ok(_) => {} - Err(llvm::RustOffloadLibraryError::NotFound { err }) => { - tcx.sess - .dcx() - .emit_fatal(crate::diagnostics::RustOffloadComponentMissing { err }); - } - Err(llvm::RustOffloadLibraryError::LoadFailed { err }) => { - tcx.sess - .dcx() - .emit_fatal(crate::diagnostics::RustOffloadComponentUnavailable { err }); - } - } - } - - Box::new(rustc_codegen_ssa::base::codegen_crate(LlvmCodegenBackend(()), tcx)) - } - - fn join_codegen( - &self, - ongoing_codegen: Box, - sess: &Session, - incr_comp_session: Option<&IncrCompSession>, - outputs: &OutputFilenames, - crate_info: &CrateInfo, - ) -> (CompiledModules, WorkProductMap) { - let (compiled_modules, work_products) = ongoing_codegen - .downcast::>() - .expect("Expected LlvmCodegenBackend's OngoingCodegen, found Box") - .join(sess, incr_comp_session, crate_info); - - if sess.opts.unstable_opts.llvm_time_trace { - sess.time("llvm_dump_timing_file", || { - let file_name = outputs.with_extension("llvm_timings.json"); - llvm_util::time_trace_profiler_finish(&file_name); - }); - } - - (compiled_modules, work_products) - } - - fn print_pass_timings(&self) { - let timings = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintPassTimings(s) }).unwrap(); - print!("{timings}"); - } - - fn print_statistics(&self) { - let stats = llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatistics(s) }).unwrap(); - print!("{stats}"); - } - - fn print_statistics_json(&self) -> String { - llvm::build_string(|s| unsafe { llvm::LLVMRustPrintStatisticsJSON(s) }).unwrap() - } - - fn link( - &self, - sess: &Session, - compiled_modules: CompiledModules, - crate_info: CrateInfo, - metadata: EncodedMetadata, - outputs: &OutputFilenames, - ) { - use rustc_codegen_ssa::back::link::link_binary; - - use crate::back::archive::LlvmArchiveBuilderBuilder; - - // Run the linker on any artifacts that resulted from the LLVM run. - // This should produce either a finished executable or library. - link_binary( - sess, - &LlvmArchiveBuilderBuilder, - compiled_modules, - crate_info, - metadata, - outputs, - self.name(), - ); - } -} - -pub struct ModuleLlvm { - pub(crate) llcx: &'static mut llvm::Context, - llmod_raw: *const llvm::Module, - - // This field is `ManuallyDrop` because it is important that the `TargetMachine` - // is disposed prior to the `Context` being disposed otherwise UAFs can occur. - pub(crate) tm: ManuallyDrop, -} - -unsafe impl Send for ModuleLlvm {} -unsafe impl Sync for ModuleLlvm {} - -impl ModuleLlvm { - pub(crate) fn new(tcx: TyCtxt<'_>, mod_name: &str) -> Self { - unsafe { - let llcx = llvm::LLVMContextCreate(); - llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); - let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { - llmod_raw, - llcx, - tm: ManuallyDrop::new(create_target_machine(tcx, mod_name)), - } - } - } - - pub(crate) fn new_metadata(tcx: TyCtxt<'_>, mod_name: &str) -> Self { - unsafe { - let llcx = llvm::LLVMContextCreate(); - llvm::LLVMContextSetDiscardValueNames(llcx, tcx.sess.fewer_names().to_llvm_bool()); - let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _; - ModuleLlvm { - llmod_raw, - llcx, - tm: ManuallyDrop::new(create_informational_target_machine(tcx.sess)), - } - } - } - - pub(crate) fn parse( - cgcx: &CodegenContext, - tm_factory: TargetMachineFactoryFn, - name: &CStr, - buffer: &[u8], - dcx: DiagCtxtHandle<'_>, - ) -> Self { - unsafe { - let llcx = llvm::LLVMContextCreate(); - llvm::LLVMContextSetDiscardValueNames(llcx, cgcx.fewer_names.to_llvm_bool()); - let llmod_raw = back::lto::parse_module(llcx, name, buffer, dcx); - let tm = tm_factory(dcx, TargetMachineFactoryConfig::new(cgcx, name.to_str().unwrap())); - - ModuleLlvm { llmod_raw, llcx, tm: ManuallyDrop::new(tm) } - } - } - - pub(crate) fn llmod(&self) -> &llvm::Module { - unsafe { &*self.llmod_raw } - } -} - -impl Drop for ModuleLlvm { - fn drop(&mut self) { - unsafe { - ManuallyDrop::drop(&mut self.tm); - llvm::LLVMContextDispose(&mut *(self.llcx as *mut _)); - } - } -} diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index d1cdf7bada0b1..52218bfa336b8 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -25,8 +25,9 @@ use super::debuginfo::{ DIArray, DIBuilder, DIDerivedType, DIDescriptor, DIFile, DIFlags, DILocation, DISPFlags, DIScope, DISubprogram, DITemplateTypeParameter, DIType, DebugEmissionKind, DebugNameTableKind, }; +use crate::llvm; use crate::llvm::MetadataKindId; -use crate::{TryFromU32, llvm}; +use crate::macros::TryFromU32; /// In the LLVM-C API, boolean values are passed as `typedef int LLVMBool`, /// which has a different ABI from Rust or C++ `bool`. From a343e5aab3c2f1c66bc330363968b9137303c667 Mon Sep 17 00:00:00 2001 From: Manuel Drehwald Date: Sat, 19 Sep 2026 00:10:53 -0400 Subject: [PATCH 0378/1309] Offload binaries now work out-of-the-box --- src/doc/rustc-dev-guide/src/offload/usage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/offload/usage.md b/src/doc/rustc-dev-guide/src/offload/usage.md index 9d61a5a87c744..2570d60b2663d 100644 --- a/src/doc/rustc-dev-guide/src/offload/usage.md +++ b/src/doc/rustc-dev-guide/src/offload/usage.md @@ -98,7 +98,7 @@ RUSTFLAGS="--emit=llvm-bc,llvm-ir -Csave-temps -Zoffload=Host=$PWD/target/amdgcn In the final step, you can now run your binary ``` -LD_LIBRARY_PATH=$(rustc +nightly --print sysroot)/lib ./target/x86_64-unknown-linux-gnu/release/binary-name +./target/x86_64-unknown-linux-gnu/release/binary-name all checks passed! ``` From c91c25f475e1a5aafcc203782430f7b7483a1136 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 19 Sep 2026 04:32:11 +0000 Subject: [PATCH 0379/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 971903d9aee24befd88423f42826c232e27c8190. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index eab2efbccce35..d5d2fe1388ca6 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -923c95cdf5ba65cea505aa2ea829f578e1506ed8 +971903d9aee24befd88423f42826c232e27c8190 From 15d8a7ad2f902f71ed86f50894e283bbbbcadd55 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Fri, 18 Sep 2026 23:23:38 +0800 Subject: [PATCH 0380/1309] ci: temporarily disable `test-x86_64-fuchsia` Since we seem to be overwhelming unauthenticated servers ``` Error 503 (Service Unavailable)!!1 ``` So let's disable for now. --- src/ci/github-actions/jobs.yml | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index d0645a0f9d475..0fdf50d20a255 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -378,13 +378,16 @@ auto: - name: test-various <<: *job-linux-4c - - name: test-x86_64-fuchsia - # Only run this job on the nightly channel. Fuchsia requires - # nightly features to compile, and this job would fail if - # executed on beta and stable. - only_on_channel: nightly - doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html - <<: *job-linux-x86-8c-ec2 + # FIXME(#162999): temporarily disabled due to unauthenticated + # servers getting overwhelmed + # + #- name: test-x86_64-fuchsia + # # Only run this job on the nightly channel. Fuchsia requires + # # nightly features to compile, and this job would fail if + # # executed on beta and stable. + # only_on_channel: nightly + # doc_url: https://rustc-dev-guide.rust-lang.org/tests/fuchsia.html + # <<: *job-linux-x86-8c-ec2 # Tests integration with Rust for Linux. # Builds stage 1 compiler and tries to compile a few RfL examples with it. From c30f2a421f4a835a04476d4c71e16e8f7fe90c34 Mon Sep 17 00:00:00 2001 From: lapla Date: Sat, 19 Sep 2026 15:45:50 +0900 Subject: [PATCH 0381/1309] Use `end_point` for trailing brace in `let...else` diagnostics --- compiler/rustc_parse/src/parser/stmt.rs | 4 +-- tests/ui/parser/let-else-fullwidth-brace.rs | 7 ++++++ .../ui/parser/let-else-fullwidth-brace.stderr | 25 +++++++++++++++++++ 3 files changed, 34 insertions(+), 2 deletions(-) create mode 100644 tests/ui/parser/let-else-fullwidth-brace.rs create mode 100644 tests/ui/parser/let-else-fullwidth-brace.stderr diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 7c3752cfff187..df34a2864b48a 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -12,7 +12,7 @@ use rustc_ast::{ LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind, }; use rustc_errors::{Applicability, Diag, PResult}; -use rustc_span::{BytePos, ErrorGuaranteed, Ident, Span, kw, sym}; +use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use super::attr::InnerAttrForbiddenReason; @@ -467,7 +467,7 @@ impl<'a> Parser<'a> { ), }; self.dcx().emit_err(diagnostics::InvalidCurlyInLetElse { - span: span.with_lo(span.hi() - BytePos(1)), + span: self.psess.source_map().end_point(span), sugg, }); } diff --git a/tests/ui/parser/let-else-fullwidth-brace.rs b/tests/ui/parser/let-else-fullwidth-brace.rs new file mode 100644 index 0000000000000..98bd65605faa8 --- /dev/null +++ b/tests/ui/parser/let-else-fullwidth-brace.rs @@ -0,0 +1,7 @@ +#![allow(irrefutable_let_patterns)] + +fn main() { + let x = {1} else { return; }; + //~^ ERROR unknown start of token: \u{ff5d} + //~| ERROR right curly brace `}` before `else` in a `let...else` statement not allowed +} diff --git a/tests/ui/parser/let-else-fullwidth-brace.stderr b/tests/ui/parser/let-else-fullwidth-brace.stderr new file mode 100644 index 0000000000000..a5bb4d029dbc5 --- /dev/null +++ b/tests/ui/parser/let-else-fullwidth-brace.stderr @@ -0,0 +1,25 @@ +error: unknown start of token: \u{ff5d} + --> $DIR/let-else-fullwidth-brace.rs:4:15 + | +LL | let x = {1} else { return; }; + | ^^ + | +help: Unicode character '}' (Fullwidth Right Curly Bracket) looks like '}' (Right Curly Brace), but it is not + | +LL - let x = {1} else { return; }; +LL + let x = {1} else { return; }; + | + +error: right curly brace `}` before `else` in a `let...else` statement not allowed + --> $DIR/let-else-fullwidth-brace.rs:4:15 + | +LL | let x = {1} else { return; }; + | ^^ + | +help: wrap the expression in parentheses + | +LL | let x = ({1}) else { return; }; + | + + + +error: aborting due to 2 previous errors + From ae2ecf58fe7242904b475df9a4c58a91126d3b95 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Sat, 19 Sep 2026 08:22:31 +0000 Subject: [PATCH 0382/1309] Avoid integer underflow in CStr::count_bytes() --- library/core/src/ffi/c_str.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index e5b1f8088a5bf..4de0ac44b2577 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -513,7 +513,8 @@ impl CStr { #[stable(feature = "cstr_count_bytes", since = "1.79.0")] #[rustc_const_stable(feature = "const_cstr_from_ptr", since = "1.81.0")] pub const fn count_bytes(&self) -> usize { - self.inner.len() - 1 + // SAFETY: This length includes the nul-terminator, so it's at least one. + unsafe { self.inner.len().unchecked_sub(1) } } /// Returns `true` if `self.to_bytes()` has a length of 0. From ca8ee2fc334407b3ae084ec23526ed4546ba7d57 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Fri, 18 Sep 2026 14:12:21 +0800 Subject: [PATCH 0383/1309] Set target-abi module flag for LoongArch targets --- compiler/rustc_codegen_llvm/src/context.rs | 10 +++++----- .../loongarch-abi/loongarch64-lp64d-abi.rs | 2 ++ 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 125ed8d3e63d2..6f76530063f72 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -559,12 +559,12 @@ pub(crate) unsafe fn create_module<'ll>( let name_metadata = cx.create_metadata(rustc_producer.as_bytes()); cx.module_add_named_metadata_node(llmod, c"llvm.ident", &[name_metadata]); - // Emit RISC-V specific target-abi metadata - // to workaround lld as the LTO plugin not - // correctly setting target-abi for the LTO object - // FIXME: https://github.com/llvm/llvm-project/issues/50591 + // Emit the target-abi module flag for LoongArch and RISC-V to pass the ABI to LTO. let llvm_abiname = &sess.target.options.llvm_abiname; - if matches!(sess.target.arch, Arch::RiscV32 | Arch::RiscV64) { + if matches!( + sess.target.arch, + Arch::LoongArch32 | Arch::LoongArch64 | Arch::RiscV32 | Arch::RiscV64 + ) { llvm::add_module_flag_str( llmod, llvm::ModuleFlagMergeBehavior::Error, diff --git a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs index 68f1267c2a444..5712aba612e5a 100644 --- a/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs +++ b/tests/codegen-llvm/loongarch-abi/loongarch64-lp64d-abi.rs @@ -297,3 +297,5 @@ pub extern "C" fn f_double_u_arg(a: DoubleU) {} pub extern "C" fn f_ret_double_u() -> DoubleU { unsafe { DoubleU { a: 1. } } } + +// CHECK: !{{[0-9]+}} = !{i32 1, !"target-abi", !"lp64d"} From 9942d36bf6e6c6e5b5d4f34ded101dcb2b2cd9f7 Mon Sep 17 00:00:00 2001 From: Ricky Date: Sat, 19 Sep 2026 16:52:43 +0800 Subject: [PATCH 0384/1309] fix stability attributes for VecDeque PartialEq impls --- library/alloc/src/collections/vec_deque/macros.rs | 4 ++-- library/alloc/src/collections/vec_deque/mod.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index d808a9d8fa993..dbc1fa3f11578 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -19,8 +19,8 @@ macro_rules! __impl_slice_eq1 { } macro_rules! __impl_slice_eq2 { - ([$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - #[stable(feature = "vec_deque_partial_eq_slice", since = "CURRENT_RUSTC_VERSION")] + ($(#[$stability:meta])+, [$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { + $(#[$stability])+ impl PartialEq<$rhs> for $lhs where T: PartialEq, diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index ab81684ad7467..330704c2e7358 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3836,12 +3836,12 @@ __impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } -__impl_slice_eq2! { [] Vec, VecDeque, } -__impl_slice_eq2! { [] &[T], VecDeque, } -__impl_slice_eq2! { [] &mut [T], VecDeque, } -__impl_slice_eq2! { [const N: usize] [T; N], VecDeque, } -__impl_slice_eq2! { [const N: usize] &[T; N], VecDeque, } -__impl_slice_eq2! { [const N: usize] &mut [T; N], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] Vec, VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &[T], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &mut [T], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] [T; N], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &[T; N], VecDeque, } +__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &mut [T; N], VecDeque, } #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for VecDeque { From d79631f00f1fe0adfebd2420413767d5b4b61d73 Mon Sep 17 00:00:00 2001 From: kianalikasana Date: Sat, 19 Sep 2026 17:24:09 +0800 Subject: [PATCH 0385/1309] Add safety section for transmute_neo --- library/core/src/mem/mod.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index 64a48d7266746..b70c227e034d6 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1243,6 +1243,12 @@ pub const unsafe fn transmute_prefix(src: Src) -> Dst { /// /// It will not be stabilized under this name. /// +/// # Safety +/// +/// Refer to [`transmute`] for safety requirements. This function is semantically identical to `transmute`. +/// +/// [`transmute`]: crate::mem::transmute +/// /// # Examples /// /// ``` From 3c2c249d243f6fc17a2faebd38abf0eea60e033a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sat, 19 Sep 2026 11:48:07 +0200 Subject: [PATCH 0386/1309] Note that cg-clif is using Josh now --- src/doc/rustc-dev-guide/src/external-repos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 1aca1b2eab1c5..26c7e2e02bd56 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -43,11 +43,11 @@ you should include fixes for those in the rustc PR as well. * `clippy` ([sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-rust-langrust-to-clippy)) * `portable-simd` ([sync script](https://github.com/rust-lang/portable-simd/blob/master/subtree-sync.sh)) * `rustfmt` - * `rustc_codegen_cranelift` ([sync script](https://github.com/rust-lang/rustc_codegen_cranelift/blob/113af154d459e41b3dc2c5d7d878e3d3a8f33c69/scripts/rustup.sh#L7)) * `rustc_codegen_gcc` ([sync guide](https://github.com/rust-lang/rustc_codegen_gcc/blob/master/doc/subtree.md)) * Using the [josh](#synchronizing-a-josh-subtree) tool * `miri` * `rust-analyzer` + * `rustc_codegen_cranelift` * `rustc-dev-guide` * `compiler-builtins` * `stdarch` From 1b3f10d6f9be9dbbe571615aea7749ab83a81433 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 11:13:45 +0200 Subject: [PATCH 0387/1309] add Dir::try_clone --- library/std/src/fs.rs | 22 ++++++++++++++++++++++ library/std/src/fs/tests.rs | 13 +++++++++++++ library/std/src/sys/fs/common.rs | 4 ++++ library/std/src/sys/fs/unix/dir.rs | 4 ++++ library/std/src/sys/fs/windows/dir.rs | 4 ++++ 5 files changed, 47 insertions(+) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 8df809264a6dd..65b8ed634bc05 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1869,6 +1869,28 @@ impl Dir { pub fn remove_dir>(&self, path: P) -> io::Result<()> { self.inner.remove_dir(path.as_ref()) } + + /// Creates a new `Dir` instance that shares the same underlying directory handle + /// as the existing `Dir` instance. + /// + /// # Examples + /// + /// Creates two handles for a directory named `foo`: + /// + /// ```no_run + /// #![feature(dirfd)] + /// use std::fs::Dir; + /// + /// fn main() -> std::io::Result<()> { + /// let dir = Dir::open("foo")?; + /// let dir_copy = dir.try_clone()?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "dirfd", issue = "120426")] + pub fn try_clone(&self) -> io::Result { + Ok(Dir { inner: self.inner.duplicate()? }) + } } impl AsInner for Dir { diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 148f1c32b08b9..e949237d3dca2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2726,6 +2726,19 @@ fn test_dir_read_file() { assert_eq!("bar", &buf); } +#[test] +fn test_dir_clone() { + let tmpdir = tmpdir(); + let mut f = check!(File::create(tmpdir.join("foo.txt"))); + check!(f.write_all(b"bar")); + drop(f); + + let dir = check!(Dir::open(tmpdir.path())); + let dir2 = check!(dir.try_clone()); + let f = check!(dir2.open_file("foo.txt")); + drop(f); +} + #[test] fn test_dir_metadata() { let tmpdir = tmpdir(); diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 17b98a4506544..96bafb26bb969 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -77,6 +77,10 @@ impl Dir { Self::open(path, &opts) } + pub fn duplicate(&self) -> io::Result { + Ok(Self { path: self.path.clone() }) + } + pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result { File::open(&self.path.join(path), opts) } diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs index 3fe952d942927..cf0dece265054 100644 --- a/library/std/src/sys/fs/unix/dir.rs +++ b/library/std/src/sys/fs/unix/dir.rs @@ -47,6 +47,10 @@ impl Dir { run_path_with_cstr(path, &|path| Self::open_traversal_c(path)) } + pub fn duplicate(&self) -> io::Result { + Ok(Self(self.0.try_clone()?)) + } + pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result { run_path_with_cstr(path.as_ref(), &|path| self.open_file_c(path, opts, 0)) .map(FileDesc::from_inner) diff --git a/library/std/src/sys/fs/windows/dir.rs b/library/std/src/sys/fs/windows/dir.rs index 70bade84f58fd..d4674ad24f87e 100644 --- a/library/std/src/sys/fs/windows/dir.rs +++ b/library/std/src/sys/fs/windows/dir.rs @@ -72,6 +72,10 @@ impl Dir { with_native_path(path, &|path| Self::open_with_native(path, &opts)) } + pub fn duplicate(&self) -> io::Result { + Ok(Self { handle: self.handle.try_clone()? }) + } + pub fn open_file(&self, path: &Path, opts: &OpenOptions) -> io::Result { // NtCreateFile will fail if given an absolute path and a non-null RootDirectory if path.is_absolute() { From f4579a6339edee1dec5ee47ab178f5c824ab3890 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 12:27:39 +0200 Subject: [PATCH 0388/1309] use errno_check a few more times --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 55 ++++++++----------- 1 file changed, 23 insertions(+), 32 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 647012eb8f7cf..07bed0c7d77df 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -4,7 +4,7 @@ use std::ffi::{CStr, CString, OsString}; use std::fs::{self, File, canonicalize, create_dir, remove_dir, remove_file}; -use std::io::{Error, ErrorKind, Write}; +use std::io::{ErrorKind, Write}; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::AsRawFd; use std::path::PathBuf; @@ -123,14 +123,13 @@ fn test_statx_on_file_descriptor() { unsafe { let mut stx = MaybeUninit::::zeroed(); - let ret = libc::statx( + errno_check(libc::statx( file.as_raw_fd(), c"".as_ptr(), libc::AT_EMPTY_PATH, libc::STATX_BASIC_STATS | libc::STATX_BTIME, stx.as_mut_ptr(), - ); - assert_eq!(ret, 0, "statx failed: {}", std::io::Error::last_os_error()); + )); let stx = stx.assume_init(); let meta = file.metadata().unwrap(); @@ -151,14 +150,13 @@ fn test_statx_on_file_path() { unsafe { let mut stx = MaybeUninit::::zeroed(); - let ret = libc::statx( + errno_check(libc::statx( libc::AT_FDCWD, c_path.as_ptr(), 0, libc::STATX_BASIC_STATS | libc::STATX_BTIME, stx.as_mut_ptr(), - ); - assert_eq!(ret, 0, "statx failed: {}", std::io::Error::last_os_error()); + )); let stx = stx.assume_init(); let meta = fs::metadata(&path).unwrap(); @@ -342,9 +340,9 @@ fn test_rename() { assert!(path2.metadata().unwrap().is_file()); // Renaming a nonexistent file should fail - let res = unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) }; - assert_eq!(res, -1); - assert_eq!(Error::last_os_error().kind(), ErrorKind::NotFound); + let err = + errno_result(unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) }).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::NotFound); remove_file(&path2).unwrap(); } @@ -366,8 +364,7 @@ fn test_ftruncate>( let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) }; // Truncate to a bigger size - let mut res = unsafe { ftruncate(fd, T::from(10)) }; - assert_eq!(res, 0); + errno_check(unsafe { ftruncate(fd, T::from(10)) }); assert_eq!(file.metadata().unwrap().len(), 10); // Write after truncate @@ -376,8 +373,7 @@ fn test_ftruncate>( assert_eq!(file.metadata().unwrap().len(), 10); // Truncate to smaller size - res = unsafe { ftruncate(fd, T::from(2)) }; - assert_eq!(res, 0); + errno_check(unsafe { ftruncate(fd, T::from(2)) }); assert_eq!(file.metadata().unwrap().len(), 2); remove_file(&path).unwrap(); @@ -708,7 +704,7 @@ fn test_sync_file_range() { file.write(bytes).unwrap(); // Test calling sync_file_range on the file. - let result_1 = unsafe { + errno_check(unsafe { libc::sync_file_range( file.as_raw_fd(), 0, @@ -717,12 +713,12 @@ fn test_sync_file_range() { | libc::SYNC_FILE_RANGE_WRITE | libc::SYNC_FILE_RANGE_WAIT_AFTER, ) - }; + }); drop(file); // Test calling sync_file_range on a file opened for reading. let file = File::open(&path).unwrap(); - let result_2 = unsafe { + errno_check(unsafe { libc::sync_file_range( file.as_raw_fd(), 0, @@ -731,12 +727,10 @@ fn test_sync_file_range() { | libc::SYNC_FILE_RANGE_WRITE | libc::SYNC_FILE_RANGE_WAIT_AFTER, ) - }; + }); drop(file); remove_file(&path).unwrap(); - assert_eq!(result_1, 0); - assert_eq!(result_2, 0); } fn test_fstat() { @@ -748,8 +742,7 @@ fn test_fstat() { let fd = file.as_raw_fd(); let mut stat = MaybeUninit::::uninit(); - let res = unsafe { libc::fstat(fd, stat.as_mut_ptr()) }; - assert_eq!(res, 0); + errno_check(unsafe { libc::fstat(fd, stat.as_mut_ptr()) }); let stat = unsafe { stat.assume_init_ref() }; assert_eq!(stat.st_size, 5); @@ -769,8 +762,7 @@ fn test_stat() { let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); let mut stat = MaybeUninit::::uninit(); - let res = unsafe { libc::stat(cpath.as_ptr(), stat.as_mut_ptr()) }; - assert_eq!(res, 0); + errno_check(unsafe { libc::stat(cpath.as_ptr(), stat.as_mut_ptr()) }); let stat = unsafe { stat.assume_init_ref() }; assert_eq!(stat.st_size, 5); @@ -794,8 +786,7 @@ fn test_lstat() { let cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); let mut stat = MaybeUninit::::uninit(); - let res = unsafe { libc::lstat(cpath.as_ptr(), stat.as_mut_ptr()) }; - assert_eq!(res, 0); + errno_check(unsafe { libc::lstat(cpath.as_ptr(), stat.as_mut_ptr()) }); let stat = unsafe { stat.assume_init_ref() }; assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFLNK); @@ -902,8 +893,8 @@ fn test_read_and_uninit() { assert_eq!(libc::read(fd, buf.as_mut_ptr().cast::(), 1), 1); let buf = buf.assume_init(); assert_eq!(buf, 1); - assert_eq!(libc::close(fd), 0); - assert_eq!(libc::unlink(cpath.as_ptr()), 0); + errno_check(libc::close(fd)); + errno_check(libc::unlink(cpath.as_ptr())); } } { @@ -925,7 +916,7 @@ fn test_read_and_uninit() { "wrong result at pos {i}" ); } - assert_eq!(libc::close(fd), 0); + errno_check(libc::close(fd)); } remove_file(&path).unwrap(); } @@ -951,7 +942,7 @@ fn test_ioctl() { assert_eq!(errno, libc::EBADF); let fd = libc::open(name.as_ptr(), libc::O_RDONLY); - assert_eq!(libc::ioctl(fd, libc::FIOCLEX), 0); + errno_check(libc::ioctl(fd, libc::FIOCLEX)); } } @@ -962,7 +953,7 @@ fn test_opendir_closedir() { let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; assert!(!dir.is_null()); - assert_eq!(unsafe { libc::closedir(dir) }, 0); + errno_check(unsafe { libc::closedir(dir) }); // dir should not exist remove_dir(&path).unwrap(); @@ -1011,7 +1002,7 @@ fn test_readdir() { let name_str = name.to_string_lossy(); entries.push(name_str.into_owned()); } - assert_eq!(libc::closedir(dirp), 0); + errno_check(libc::closedir(dirp)); entries.sort(); assert_eq!(&entries, &[".", "..", "file1.txt", "file2.txt"]); } From 210ef0b68608d33fe1ef236836b02cdf7291c1e4 Mon Sep 17 00:00:00 2001 From: kianalikasana Date: Sat, 19 Sep 2026 19:16:14 +0800 Subject: [PATCH 0389/1309] Wrap safety doc line --- library/core/src/mem/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index b70c227e034d6..5282b39782181 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -1245,7 +1245,8 @@ pub const unsafe fn transmute_prefix(src: Src) -> Dst { /// /// # Safety /// -/// Refer to [`transmute`] for safety requirements. This function is semantically identical to `transmute`. +/// Refer to [`transmute`] for safety requirements. +/// This function is semantically identical to `transmute`. /// /// [`transmute`]: crate::mem::transmute /// From 80c0261c3432b0af07bf45e39e39a21e14999f31 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 12:36:16 +0200 Subject: [PATCH 0390/1309] add dirfd support --- .../miri/src/shims/unix/foreign_items.rs | 5 + src/tools/miri/src/shims/unix/fs.rs | 92 +++++++++++++++---- .../miri/tests/fail-dep/libc/dirfd-closed.rs | 29 ++++++ .../tests/fail-dep/libc/dirfd-closed.stderr | 13 +++ .../tests/fail-dep/libc/dirfd-replaced.rs | 31 +++++++ .../tests/fail-dep/libc/dirfd-replaced.stderr | 13 +++ src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 27 ++++++ 7 files changed, 191 insertions(+), 19 deletions(-) create mode 100644 src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/dirfd-closed.stderr create mode 100644 src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs create mode 100644 src/tools/miri/tests/fail-dep/libc/dirfd-replaced.stderr diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index fb019a1f6be31..e89f0f1b97132 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -462,6 +462,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { .check_shim_sig(shim_sig!(extern "C" fn(*_) -> *_), (link_name, abi, args))?; this.readdir(dirp, dest)?; } + "dirfd" => { + let [dirp] = this + .check_shim_sig(shim_sig!(extern "C" fn(*_) -> i32), (link_name, abi, args))?; + this.dirfd(dirp, dest)?; + } "lseek" => { // FIXME: This does not have a direct test (#3179). let [fd, offset, whence] = this.check_shim_sig( diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 1ad71d0d8a648..7200115f42b0d 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::ffi::OsString; -use std::fs::{self, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; +use std::fs::{self, Dir, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; use std::path::{self, Path}; use std::time::SystemTime; @@ -13,28 +13,34 @@ use rustc_data_structures::fx::FxHashMap; use rustc_target::spec::Os; use self::shims::time::system_time_to_duration; -use crate::shims::files::FileHandle; +use crate::shims::FdId; +use crate::shims::files::{DirHandle, FdNum, FileHandle}; use crate::shims::os_str::bytes_to_os_str; use crate::shims::sig::Varargs; use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; use crate::*; -/// An open directory, tracked by DirHandler. +/// An open directory stream, tracked by DirTable. #[derive(Debug)] -struct OpenDir { +struct DirStream { + /// The directory reader on the host. + read_dir: fs::ReadDir, + /// An FD number for the same handle. Unix directory streams have an "underlying FD" that + /// can be exposed; this is that FD. We also store the FD ID to catch cases where + /// the FD was closed and a different one re-opened. + fd_num: FdNum, + fd_id: FdId, /// The "special" entries that must still be yielded by the iterator. /// Used for `.` and `..`. special_entries: Vec<&'static str>, - /// The directory reader on the host. - read_dir: fs::ReadDir, /// The most recent entry returned by readdir(). /// Will be freed by the next call. entry: Option, } -impl OpenDir { - fn new(read_dir: fs::ReadDir) -> Self { - Self { special_entries: vec!["..", "."], read_dir, entry: None } +impl DirStream { + fn new(read_dir: fs::ReadDir, fd_num: FdNum, fd_id: FdId) -> Self { + Self { read_dir, fd_num, fd_id, special_entries: vec!["..", "."], entry: None } } fn next_host_entry(&mut self) -> Option>> { @@ -178,17 +184,17 @@ pub struct DirTable { /// the corresponding ReadDir iterator from this map, and information from the next /// directory entry is returned. When closedir is called, the ReadDir iterator is removed from /// the map. - streams: FxHashMap, + streams: FxHashMap, /// ID number to be used by the next call to opendir next_id: u64, } impl DirTable { #[expect(clippy::arithmetic_side_effects)] - fn insert_new(&mut self, read_dir: fs::ReadDir) -> u64 { + fn insert_new(&mut self, stream: DirStream) -> u64 { let id = self.next_id; self.next_id += 1; - self.streams.try_insert(id, OpenDir::new(read_dir)).unwrap(); + self.streams.try_insert(id, stream).unwrap(); id } } @@ -1103,15 +1109,33 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Scalar::null_ptr(this)); } - let result = fs::read_dir(name); + let result = fs::read_dir(&name); match result { - Ok(dir_iter) => { - let id = this.machine.dirs.insert_new(dir_iter); + Ok(read_dir) => { + // Also open the same directory as a directory handle, so we have + // an underlying FD. + // FIXME(https://github.com/rust-lang/miri/issues/5326): This is racy! We can't even + // verify whether there was a race. We just trust that the directory did not change + // in between above and here. One day, the standard library will support converting + // between `Dir` and `ReadDir` (one of the two directions would suffice for our + // needs), then we'll use that. + let Ok(dir) = Dir::open(name) else { + throw_unsup_format!( + "cannot `opendir` this directory: failed to create directory handle" + ); + }; + let dir = this.machine.fds.new_ref(DirHandle { dir }); + let dir_fd_id = dir.id(); + let dir_fd_num = this.machine.fds.insert(dir); + + let stream = DirStream::new(read_dir, dir_fd_num, dir_fd_id); + let id = this.machine.dirs.insert_new(stream); // The libc API for opendir says that this method returns a pointer to an opaque // structure, but we are returning an ID number. Thus, pass it as a scalar of - // pointer width. + // pointer width. This also conveniently means that any attempt to access + // memory via this pointer raises UB. interp_ok(Scalar::from_target_usize(id, this)) } Err(e) => { @@ -1145,6 +1169,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { err_ub_format!("the DIR pointer passed to `readdir` did not come from opendir") })?; + // Check that the backing FD is still valid. + if this.machine.fds.get(open_dir.fd_num).is_none_or(|fd| fd.id() != open_dir.fd_id) { + throw_ub_format!("the backing FD for this DIR stream has been tampered with"); + } + let entry = match open_dir.next_host_entry() { Some(Ok(dir_entry)) => { let dir_entry = this.dir_entry_fields(dir_entry)?; @@ -1264,6 +1293,25 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(()) } + fn dirfd(&mut self, dirp_op: &OpTy<'tcx>, dest: &MPlaceTy<'tcx>) -> InterpResult<'tcx> { + let this = self.eval_context_mut(); + + let dirp = this.read_target_usize(dirp_op)?; + + let open_dir = this.machine.dirs.streams.get_mut(&dirp).ok_or_else(|| { + err_ub_format!("the DIR pointer passed to `readdir` did not come from opendir") + })?; + + // Check that the backing FD is still valid. + if this.machine.fds.get(open_dir.fd_num).is_none_or(|fd| fd.id() != open_dir.fd_id) { + throw_ub_format!("the backing FD for this DIR stream has been tampered with"); + } + + let fd_num = open_dir.fd_num; + this.write_int(fd_num, dest)?; + interp_ok(()) + } + fn closedir(&mut self, dirp_op: &OpTy<'tcx>) -> InterpResult<'tcx, Scalar> { let this = self.eval_context_mut(); @@ -1275,9 +1323,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); } - let Some(mut open_dir) = this.machine.dirs.streams.remove(&dirp) else { - return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); - }; + let mut open_dir = this.machine.dirs.streams.remove(&dirp).ok_or_else(|| { + err_ub_format!("the DIR pointer passed to `closedir` did not come from opendir") + })?; + + // Check that the backing FD is still valid. + if this.machine.fds.get(open_dir.fd_num).is_none_or(|fd| fd.id() != open_dir.fd_id) { + throw_ub_format!("the backing FD for this DIR stream has been tampered with"); + } + if let Some(entry) = open_dir.entry.take() { this.deallocate_ptr(entry, None, MiriMemoryKind::Runtime.into())?; } diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs new file mode 100644 index 0000000000000..7cab24bc4d4d9 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs @@ -0,0 +1,29 @@ +//@ignore-target: windows # no libc +//@compile-flags: -Zmiri-disable-isolation + +use std::ffi::CString; +use std::fs::create_dir; +use std::os::unix::ffi::OsStrExt; + +#[path = "../../utils/mod.rs"] +mod utils; + +#[path = "../../utils/libc.rs"] +mod libc_utils; + +use libc_utils::errno_check; + +fn main() { + let path = utils::prepare_dir("miri_test_libc_dirfd_closed"); + create_dir(&path).expect("create_dir failed"); + let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; + assert!(!dir.is_null()); + + let dirfd = unsafe { libc::dirfd(dir) }; + // Mess up the directory stream by closing the backing FD. + errno_check(unsafe { libc::close(dirfd) }); + + errno_check(unsafe { libc::closedir(dir) }); + //~^ERROR: DIR stream has been tampered with +} diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-closed.stderr b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.stderr new file mode 100644 index 0000000000000..d8dbce0754b3b --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: the backing FD for this DIR stream has been tampered with + --> tests/fail-dep/libc/dirfd-closed.rs:LL:CC + | +LL | errno_check(unsafe { libc::closedir(dir) }); + | ^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs new file mode 100644 index 0000000000000..e5e2336e96d63 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs @@ -0,0 +1,31 @@ +//@ignore-target: windows # no libc +//@compile-flags: -Zmiri-disable-isolation + +use std::ffi::CString; +use std::fs::create_dir; +use std::os::unix::ffi::OsStrExt; + +#[path = "../../utils/mod.rs"] +mod utils; + +#[path = "../../utils/libc.rs"] +mod libc_utils; + +use libc_utils::{errno_check, errno_result}; + +fn main() { + let path = utils::prepare_dir("miri_test_libc_dirfd_replaced"); + create_dir(&path).expect("create_dir failed"); + let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; + assert!(!dir.is_null()); + + let dirfd = unsafe { libc::dirfd(dir) }; + // Mess up the directory stream by replacing the backing FD. + errno_result(unsafe { libc::dup2(0, dirfd) }).unwrap(); + + let _entry_ptr = unsafe { libc::readdir(dir) }; + //~^ERROR: DIR stream has been tampered with + + errno_check(unsafe { libc::closedir(dir) }); +} diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.stderr b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.stderr new file mode 100644 index 0000000000000..f3d7b9aa83db5 --- /dev/null +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.stderr @@ -0,0 +1,13 @@ +error: Undefined Behavior: the backing FD for this DIR stream has been tampered with + --> tests/fail-dep/libc/dirfd-replaced.rs:LL:CC + | +LL | let _entry_ptr = unsafe { libc::readdir(dir) }; + | ^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior + = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 07bed0c7d77df..951c52d8fcbf6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -60,6 +60,7 @@ fn main() { test_ioctl(); test_opendir_closedir(); test_readdir(); + test_dirfd(); #[cfg(target_os = "linux")] test_statx_on_file_path(); #[cfg(target_os = "linux")] @@ -1012,8 +1013,34 @@ fn test_readdir() { remove_dir(&dir_path).unwrap(); } +fn test_dirfd() { + use std::mem::MaybeUninit; + + let path = utils::prepare_dir("miri_test_libc_opendir_closedir"); + create_dir(&path).expect("create_dir failed"); + let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; + assert!(!dir.is_null()); + + let dirfd = unsafe { libc::dirfd(dir) }; + + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { libc::fstat(dirfd, stat.as_mut_ptr()) }); + let stat = unsafe { stat.assume_init_ref() }; + + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFDIR); + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + + // Check that all fields are initialized. + check_stat_fields(stat); + + errno_check(unsafe { libc::closedir(dir) }); +} + /// Check that all common fields of a `stat` struct are initialized. pub fn check_stat_fields(stat: &libc::stat) { + let _st_size = stat.st_size; + let _st_mode = stat.st_mode; let _st_nlink = stat.st_nlink; let _st_blksize = stat.st_blksize; let _st_blocks = stat.st_blocks; From ae806144835d48083bf757afa6d35cd861c7389f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 13:18:11 +0200 Subject: [PATCH 0391/1309] prepare statx for metadata relative to dirfd... but we cannot implement this yet --- src/tools/miri/src/shims/unix/fs.rs | 57 +++++++++++++---------------- 1 file changed, 25 insertions(+), 32 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 7200115f42b0d..da64f941fc3b6 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -802,44 +802,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?; - let path = this.read_path_from_c_str(pathname_ptr)?.into_owned(); - // See for a discussion of argument sizes. + let at_empty_path = this.eval_libc_i32("AT_EMPTY_PATH"); let empty_path_flag = flags & at_empty_path == at_empty_path; - // We only support: - // * interpreting `path` as an absolute directory, - // * interpreting `path` as a path relative to `dirfd` when the latter is `AT_FDCWD`, or - // * interpreting `dirfd` as any file descriptor when `path` is empty and AT_EMPTY_PATH is - // set. - // Other behaviors cannot be tested from `libstd` and thus are not implemented. If you - // found this error, please open an issue reporting it. - if !(path.is_absolute() - || dirfd == this.eval_libc_i32("AT_FDCWD") - || (path.as_os_str().is_empty() && empty_path_flag)) - { - throw_unsup_format!( - "using statx is only supported with absolute paths, relative paths with the file \ - descriptor `AT_FDCWD`, and empty paths with the `AT_EMPTY_PATH` flag set and any \ - file descriptor" - ) + + // The docs are kind of unclear about what empty paths should do when the + // flag is *not* set, so we just bail. + if path.is_empty() && !empty_path_flag { + throw_unsup_format!("statx only supports empty paths if `AT_EMPTY_PATH` is set"); } // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`statx`", reject_with)?; - let ecode = if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { - // since `path` is provided, either absolute or - // relative to CWD, `EACCES` is the most relevant. - LibcError("EACCES") - } else { - // `dirfd` is set to target file, and `path` is empty - // (or we would have hit the `throw_unsup_format` - // above). `EACCES` would violate the spec. - assert!(empty_path_flag); - LibcError("EBADF") - }; - return this.set_errno_and_return_neg1_i32(ecode); + return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); } // If the `AT_SYMLINK_NOFOLLOW` flag is set, we query the file's metadata without following @@ -848,11 +825,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file // represented by dirfd, whether it's a directory or otherwise. - let metadata = if path.as_os_str().is_empty() && empty_path_flag { + let metadata = if path.is_absolute() { + // absolute path, dirfd is ignored. + FileMetadata::from_path(this, &path, follow_symlink)? + } else if path.is_empty() { + // no path, load metadata about dirfd FileMetadata::from_fd_num(this, dirfd)? - } else { + } else if dirfd == this.eval_libc_i32("AT_FDCWD") { + // relative to current working directory FileMetadata::from_path(this, &path, follow_symlink)? + } else { + // relative to dirfd, which must be a directory handle + let Some(fd) = this.machine.fds.get(dirfd) else { + return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + }; + let Some(_dir) = fd.downcast::() else { + return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + }; + + throw_unsup_format!("statx relative to a directory handle is not supported"); }; + let metadata = match metadata { Ok(metadata) => metadata, Err(err) => return this.set_errno_and_return_neg1_i32(err), From 001a8662fcf84b57afc473461e4bbe2de44d14e0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 13:27:01 +0200 Subject: [PATCH 0392/1309] statx: complain about invalid flags --- src/tools/miri/src/shims/unix/fs.rs | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index da64f941fc3b6..17cf5505203df 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -543,7 +543,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If `flag` has any bits left set, those are not supported. if flag != 0 { - throw_unsup_format!("unsupported flags {:#x}", flag); + throw_unsup_format!("unsupported flags for `open`: {flag:#x}"); } // Reject if isolation is enabled. @@ -804,8 +804,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let statxbuf = this.deref_pointer_as(statxbuf_op, this.libc_ty_layout("statx"))?; let path = this.read_path_from_c_str(pathname_ptr)?.into_owned(); + // Parse flags. + let mut flags = flags; + // AT_EMPTY_PATH let at_empty_path = this.eval_libc_i32("AT_EMPTY_PATH"); let empty_path_flag = flags & at_empty_path == at_empty_path; + flags &= !at_empty_path; + // AT_SYMLINK_NOFOLLOW + let at_symlink_nofollow = this.eval_libc_i32("AT_SYMLINK_NOFOLLOW"); + let symlink_nofollow_flag = flags & at_symlink_nofollow == at_symlink_nofollow; + flags &= !at_symlink_nofollow; + // Complain about unknown flags. + if flags != 0 { + throw_unsup_format!("unsupported flags for `statx`: {flags:#x}") + } // The docs are kind of unclear about what empty paths should do when the // flag is *not* set, so we just bail. @@ -819,21 +831,17 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); } - // If the `AT_SYMLINK_NOFOLLOW` flag is set, we query the file's metadata without following - // symbolic links. - let follow_symlink = flags & this.eval_libc_i32("AT_SYMLINK_NOFOLLOW") == 0; - // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file // represented by dirfd, whether it's a directory or otherwise. let metadata = if path.is_absolute() { // absolute path, dirfd is ignored. - FileMetadata::from_path(this, &path, follow_symlink)? + FileMetadata::from_path(this, &path, !symlink_nofollow_flag)? } else if path.is_empty() { // no path, load metadata about dirfd FileMetadata::from_fd_num(this, dirfd)? } else if dirfd == this.eval_libc_i32("AT_FDCWD") { // relative to current working directory - FileMetadata::from_path(this, &path, follow_symlink)? + FileMetadata::from_path(this, &path, !symlink_nofollow_flag)? } else { // relative to dirfd, which must be a directory handle let Some(fd) = this.machine.fds.get(dirfd) else { @@ -1403,7 +1411,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We only support `fallocate` as a replacement for `posix_fallocate` on linux, // so a non-default `mode` is not supported. if mode != 0 { - throw_unsup_format!("unsupported flags for `fallocate` in `mode` argument: {mode}") + throw_unsup_format!("unsupported flags for `fallocate` in `mode` argument: {mode:#x}") } match this.fallocate_impl(fd, offset, size)? { From f1289a9f0d80c2c7df5f1322845659438ac56740 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?V=C3=A1nia=20Livadnyi?= Date: Thu, 5 Feb 2026 09:40:12 +0100 Subject: [PATCH 0393/1309] Add `must_use_without_reason` lint Warns on `#[must_use]` attributes with no accompanying message. --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/functions/mod.rs | 25 ++++++++ clippy_lints/src/functions/must_use.rs | 84 +++++++++++++++++-------- tests/ui/must_use_candidates.fixed | 19 ++++++ tests/ui/must_use_candidates.rs | 17 +++++ tests/ui/must_use_candidates.stderr | 26 +++++++- tests/ui/must_use_without_reason.fixed | 64 +++++++++++++++++++ tests/ui/must_use_without_reason.rs | 64 +++++++++++++++++++ tests/ui/must_use_without_reason.stderr | 23 +++++++ 10 files changed, 298 insertions(+), 26 deletions(-) create mode 100644 tests/ui/must_use_without_reason.fixed create mode 100644 tests/ui/must_use_without_reason.rs create mode 100644 tests/ui/must_use_without_reason.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f5eb09e5247..10515df4f28b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7341,6 +7341,7 @@ Released 2018-09-13 [`multiple_unsafe_ops_per_block`]: https://rust-lang.github.io/rust-clippy/main/index.html#multiple_unsafe_ops_per_block [`must_use_candidate`]: https://rust-lang.github.io/rust-clippy/main/index.html#must_use_candidate [`must_use_unit`]: https://rust-lang.github.io/rust-clippy/main/index.html#must_use_unit +[`must_use_without_reason`]: https://rust-lang.github.io/rust-clippy/main/index.html#must_use_without_reason [`mut_from_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_from_ref [`mut_mut`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_mut [`mut_mutex_lock`]: https://rust-lang.github.io/rust-clippy/main/index.html#mut_mutex_lock diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 5a143cca874b5..de7de9ead8e35 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -200,6 +200,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::functions::MISNAMED_GETTERS_INFO, crate::functions::MUST_USE_CANDIDATE_INFO, crate::functions::MUST_USE_UNIT_INFO, + crate::functions::MUST_USE_WITHOUT_REASON_INFO, crate::functions::NOT_UNSAFE_PTR_ARG_DEREF_INFO, crate::functions::REF_OPTION_INFO, crate::functions::RENAMED_FUNCTION_PARAMS_INFO, diff --git a/clippy_lints/src/functions/mod.rs b/clippy_lints/src/functions/mod.rs index 4c23f21a7318a..2c1319ba8f2f3 100644 --- a/clippy_lints/src/functions/mod.rs +++ b/clippy_lints/src/functions/mod.rs @@ -193,6 +193,30 @@ declare_clippy_lint! { "`#[must_use]` attribute on a unit-returning function / method" } +declare_clippy_lint! { + /// ### What it does + /// Checks for `#[must_use]` attributes without a reason. + /// + /// ### Why restrict this? + /// A reason explains why the return value must be used. Without it, + /// users only see a generic "unused must-use value" message which is less helpful. + /// + /// ### Example + /// ```no_run + /// #[must_use] + /// fn compute() -> i32 { 42 } + /// ``` + /// Use instead: + /// ```no_run + /// #[must_use = "computation is expensive"] + /// fn compute() -> i32 { 42 } + /// ``` + #[clippy::version = "1.99.0"] + pub MUST_USE_WITHOUT_REASON, + restriction, + "`#[must_use]` attribute without a reason" +} + declare_clippy_lint! { /// ### What it does /// Checks for public functions that dereference raw pointer @@ -486,6 +510,7 @@ impl_lint_pass!(Functions => [ MISNAMED_GETTERS, MUST_USE_CANDIDATE, MUST_USE_UNIT, + MUST_USE_WITHOUT_REASON, NOT_UNSAFE_PTR_ARG_DEREF, REF_OPTION, RENAMED_FUNCTION_PARAMS, diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index bca9705f6ed59..6c1a671a73676 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -7,19 +7,18 @@ use rustc_hir::{self as hir, Attribute, QPath}; use rustc_lint::unused::must_use::MustUsePath; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty::{self, Ty}; -use rustc_span::{Span, sym}; +use rustc_span::{Span, Symbol, sym}; use clippy_utils::attrs::is_proc_macro; -use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::diagnostics::{span_lint_and_sugg, span_lint_and_then}; use clippy_utils::source::snippet_indent; use clippy_utils::ty::{describe_must_use_type, opt_must_use_path}; use clippy_utils::visitors::for_each_expr_without_closures; -use clippy_utils::{is_entrypoint_fn, return_ty, trait_ref_of_method}; -use rustc_span::Symbol; +use clippy_utils::{is_entrypoint_fn, is_lint_allowed, return_ty, trait_ref_of_method}; use core::ops::ControlFlow; -use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT}; +use super::{DOUBLE_MUST_USE, MUST_USE_CANDIDATE, MUST_USE_UNIT, MUST_USE_WITHOUT_REASON}; pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_>) { let attrs = cx.tcx.hir_attrs(item.hir_id()); @@ -30,21 +29,24 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> ident, .. } = item.kind + && !item.span.in_external_macro(cx.sess().source_map()) { let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); if let Some((attr_span, reason)) = attr { - check_needless_must_use( + let is_needless_must_use = check_needless_must_use( cx, sig.decl, item.owner_id, - item.span, fn_header_span, *attr_span, *reason, attrs, sig, ); + if !is_needless_must_use { + check_must_use_without_reason(cx, *attr_span, *reason); + } } else if is_public && !is_proc_macro(attrs) && !find_attr!(attrs, NoMangle(..)) { check_must_use_candidate( cx, @@ -60,23 +62,27 @@ pub(super) fn check_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Item<'_> } pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::ImplItem<'_>) { - if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind { + if let hir::ImplItemKind::Fn(ref sig, ref body_id) = item.kind + && !item.span.in_external_macro(cx.sess().source_map()) + { let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { - check_needless_must_use( + let is_needless_must_use = check_needless_must_use( cx, sig.decl, item.owner_id, - item.span, fn_header_span, *attr_span, *reason, attrs, sig, ); + if !is_needless_must_use { + check_must_use_without_reason(cx, *attr_span, *reason); + } } else if is_public && !is_proc_macro(attrs) && trait_ref_of_method(cx, item.owner_id).is_none() { check_must_use_candidate( cx, @@ -92,24 +98,28 @@ pub(super) fn check_impl_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::Imp } pub(super) fn check_trait_item<'tcx>(cx: &LateContext<'tcx>, item: &'tcx hir::TraitItem<'_>) { - if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind { + if let hir::TraitItemKind::Fn(ref sig, ref eid) = item.kind + && !item.span.in_external_macro(cx.sess().source_map()) + { let is_public = cx.effective_visibilities.is_exported(item.owner_id.def_id); let fn_header_span = item.span.with_hi(sig.decl.output.span().hi()); let attrs = cx.tcx.hir_attrs(item.hir_id()); let attr = find_attr!(cx.tcx, item.hir_id(), MustUse { span, reason } => (span, reason)); if let Some((attr_span, reason)) = attr { - check_needless_must_use( + let is_needless_must_use = check_needless_must_use( cx, sig.decl, item.owner_id, - item.span, fn_header_span, *attr_span, *reason, attrs, sig, ); + if !is_needless_must_use { + check_must_use_without_reason(cx, *attr_span, *reason); + } } else if let hir::TraitFn::Provided(eid) = *eid { let body = cx.tcx.hir_body(eid); if attr.is_none() && is_public && !is_proc_macro(attrs) { @@ -133,15 +143,14 @@ fn check_needless_must_use( cx: &LateContext<'_>, decl: &hir::FnDecl<'_>, item_id: hir::OwnerId, - item_span: Span, fn_header_span: Span, attr_span: Span, reason: Option, attrs: &[Attribute], sig: &FnSig<'_>, -) { - if item_span.in_external_macro(cx.sess().source_map()) || attr_span.from_expansion() { - return; +) -> bool { + if attr_span.from_expansion() { + return false; } if returns_unit(decl) { span_lint_and_then( @@ -162,6 +171,7 @@ fn check_needless_must_use( } }, ); + return true; } else if reason.is_none() && let Some(return_must_use_path) = opt_must_use_path(cx, return_ty(cx, item_id)) { @@ -170,7 +180,7 @@ fn check_needless_must_use( && let Some(future_ty) = cx.tcx.get_impl_future_output_ty(return_ty(cx, item_id)) && opt_must_use_path(cx, future_ty).is_none() { - return; + return false; } span_lint_and_then( @@ -202,7 +212,27 @@ fn check_needless_must_use( diag.note("alternatively, you may add an explicit reason to the `must_use` attribute"); }, ); + return true; } + + false +} + +/// Checks for `must_use` usage without a reason +fn check_must_use_without_reason(cx: &LateContext<'_>, attr_span: Span, reason: Option) { + if reason.is_some() || attr_span.from_expansion() { + return; + } + + span_lint_and_sugg( + cx, + MUST_USE_WITHOUT_REASON, + attr_span, + "`#[must_use]` attribute without a reason", + "add a reason why the value must be used", + "#[must_use = \"\"]".to_string(), + Applicability::HasPlaceholders, + ); } fn check_must_use_candidate<'tcx>( @@ -216,7 +246,6 @@ fn check_must_use_candidate<'tcx>( ) { if has_mutable_arg(cx, body) || mutates_static(cx, body) - || item_span.in_external_macro(cx.sess().source_map()) || returns_unit(decl) || !cx.effective_visibilities.is_exported(item_id.def_id) || opt_must_use_path(cx, return_ty(cx, item_id)).is_some() @@ -225,14 +254,19 @@ fn check_must_use_candidate<'tcx>( { return; } + let hir_id = cx.tcx.local_def_id_to_hir_id(item_id.def_id); span_lint_and_then(cx, MUST_USE_CANDIDATE, ident_span, msg, |diag| { let indent = snippet_indent(cx, item_span).unwrap_or_default(); - diag.span_suggestion( - item_span.shrink_to_lo(), - "add the attribute", - format!("#[must_use]\n{indent}"), - Applicability::MachineApplicable, - ); + // Suggest a reason as well, otherwise `must_use_without_reason` fires on the result. + let (sugg, applicability) = if is_lint_allowed(cx, MUST_USE_WITHOUT_REASON, hir_id) { + (format!("#[must_use]\n{indent}"), Applicability::MachineApplicable) + } else { + ( + format!("#[must_use = \"\"]\n{indent}"), + Applicability::HasPlaceholders, + ) + }; + diag.span_suggestion(item_span.shrink_to_lo(), "add the attribute", sugg, applicability); }); } diff --git a/tests/ui/must_use_candidates.fixed b/tests/ui/must_use_candidates.fixed index 645ce68c3fc2b..77d78b9b3eb8b 100644 --- a/tests/ui/must_use_candidates.fixed +++ b/tests/ui/must_use_candidates.fixed @@ -134,3 +134,22 @@ pub fn result_never_2() -> Result { pub fn with_box() -> Box { todo!() } + +pub mod with_reason_lint { + // With `must_use_without_reason` enabled the suggestion carries a reason placeholder, + // so applying it does not immediately trip that lint. + #![warn(clippy::must_use_without_reason)] + + //~v must_use_candidate + #[must_use = ""] + pub fn pure(i: u8) -> u8 { + i + } + + #[allow(clippy::must_use_without_reason)] + //~v must_use_candidate + #[must_use] + pub fn reason_lint_allowed(i: u8) -> u8 { + i + } +} diff --git a/tests/ui/must_use_candidates.rs b/tests/ui/must_use_candidates.rs index 23a184c69f36b..405e37091652d 100644 --- a/tests/ui/must_use_candidates.rs +++ b/tests/ui/must_use_candidates.rs @@ -127,3 +127,20 @@ pub fn result_never_2() -> Result { pub fn with_box() -> Box { todo!() } + +pub mod with_reason_lint { + // With `must_use_without_reason` enabled the suggestion carries a reason placeholder, + // so applying it does not immediately trip that lint. + #![warn(clippy::must_use_without_reason)] + + //~v must_use_candidate + pub fn pure(i: u8) -> u8 { + i + } + + #[allow(clippy::must_use_without_reason)] + //~v must_use_candidate + pub fn reason_lint_allowed(i: u8) -> u8 { + i + } +} diff --git a/tests/ui/must_use_candidates.stderr b/tests/ui/must_use_candidates.stderr index 6a6c1e8be9ac0..2bf7337553958 100644 --- a/tests/ui/must_use_candidates.stderr +++ b/tests/ui/must_use_candidates.stderr @@ -84,5 +84,29 @@ LL + #[must_use] LL | pub fn result_never_1() -> Result { | -error: aborting due to 7 previous errors +error: this function could have a `#[must_use]` attribute + --> tests/ui/must_use_candidates.rs:137:12 + | +LL | pub fn pure(i: u8) -> u8 { + | ^^^^ + | +help: add the attribute + | +LL ~ #[must_use = ""] +LL ~ pub fn pure(i: u8) -> u8 { + | + +error: this function could have a `#[must_use]` attribute + --> tests/ui/must_use_candidates.rs:143:12 + | +LL | pub fn reason_lint_allowed(i: u8) -> u8 { + | ^^^^^^^^^^^^^^^^^^^ + | +help: add the attribute + | +LL ~ #[must_use] +LL ~ pub fn reason_lint_allowed(i: u8) -> u8 { + | + +error: aborting due to 9 previous errors diff --git a/tests/ui/must_use_without_reason.fixed b/tests/ui/must_use_without_reason.fixed new file mode 100644 index 0000000000000..fb0d221ccd788 --- /dev/null +++ b/tests/ui/must_use_without_reason.fixed @@ -0,0 +1,64 @@ +//@aux-build:proc_macros.rs + +#![warn(clippy::must_use_without_reason)] +#![allow(clippy::must_use_unit)] + +extern crate proc_macros; +use proc_macros::external; + +// Should trigger lint +#[must_use = ""] +//~^ ERROR: `#[must_use]` attribute without a reason +fn no_note() -> i32 { + 42 +} + +// Should NOT trigger lint - has a note +#[must_use = "expensive operation"] +fn with_note() -> i32 { + 42 +} + +struct MyStruct; + +impl MyStruct { + // Should trigger lint + #[must_use = ""] + //~^ ERROR: `#[must_use]` attribute without a reason + fn method_no_note(&self) -> i32 { + 42 + } + + // Should NOT trigger lint + #[must_use = "important result"] + fn method_with_note(&self) -> i32 { + 42 + } +} + +trait MyTrait { + // Should trigger lint + #[must_use = ""] + //~^ ERROR: `#[must_use]` attribute without a reason + fn trait_method_no_note(&self) -> i32; + + // Should NOT trigger lint + #[must_use = "trait method note"] + fn trait_method_with_note(&self) -> i32; +} + +// Should NOT trigger lint - external macro +external! { + #[must_use] + fn external_macro_no_note() -> i32 { + 42 + } +} + +fn main() { + let _ = no_note(); + let _ = with_note(); + let s = MyStruct; + let _ = s.method_no_note(); + let _ = s.method_with_note(); +} diff --git a/tests/ui/must_use_without_reason.rs b/tests/ui/must_use_without_reason.rs new file mode 100644 index 0000000000000..4ea3f56aedb2c --- /dev/null +++ b/tests/ui/must_use_without_reason.rs @@ -0,0 +1,64 @@ +//@aux-build:proc_macros.rs + +#![warn(clippy::must_use_without_reason)] +#![allow(clippy::must_use_unit)] + +extern crate proc_macros; +use proc_macros::external; + +// Should trigger lint +#[must_use] +//~^ ERROR: `#[must_use]` attribute without a reason +fn no_note() -> i32 { + 42 +} + +// Should NOT trigger lint - has a note +#[must_use = "expensive operation"] +fn with_note() -> i32 { + 42 +} + +struct MyStruct; + +impl MyStruct { + // Should trigger lint + #[must_use] + //~^ ERROR: `#[must_use]` attribute without a reason + fn method_no_note(&self) -> i32 { + 42 + } + + // Should NOT trigger lint + #[must_use = "important result"] + fn method_with_note(&self) -> i32 { + 42 + } +} + +trait MyTrait { + // Should trigger lint + #[must_use] + //~^ ERROR: `#[must_use]` attribute without a reason + fn trait_method_no_note(&self) -> i32; + + // Should NOT trigger lint + #[must_use = "trait method note"] + fn trait_method_with_note(&self) -> i32; +} + +// Should NOT trigger lint - external macro +external! { + #[must_use] + fn external_macro_no_note() -> i32 { + 42 + } +} + +fn main() { + let _ = no_note(); + let _ = with_note(); + let s = MyStruct; + let _ = s.method_no_note(); + let _ = s.method_with_note(); +} diff --git a/tests/ui/must_use_without_reason.stderr b/tests/ui/must_use_without_reason.stderr new file mode 100644 index 0000000000000..d5deb9cbdbb21 --- /dev/null +++ b/tests/ui/must_use_without_reason.stderr @@ -0,0 +1,23 @@ +error: `#[must_use]` attribute without a reason + --> tests/ui/must_use_without_reason.rs:10:1 + | +LL | #[must_use] + | ^^^^^^^^^^^ help: add a reason why the value must be used: `#[must_use = ""]` + | + = note: `-D clippy::must-use-without-reason` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::must_use_without_reason)]` + +error: `#[must_use]` attribute without a reason + --> tests/ui/must_use_without_reason.rs:26:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ help: add a reason why the value must be used: `#[must_use = ""]` + +error: `#[must_use]` attribute without a reason + --> tests/ui/must_use_without_reason.rs:41:5 + | +LL | #[must_use] + | ^^^^^^^^^^^ help: add a reason why the value must be used: `#[must_use = ""]` + +error: aborting due to 3 previous errors + From 3b433cb0c237ae0077c0069db7802d144f7eee36 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 13:27:41 +0000 Subject: [PATCH 0394/1309] stop passing `nonself_arg_tys` around --- .../src/deriving/generic/mod.rs | 60 ++++++++----------- 1 file changed, 25 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index bcf01bf33a94e..baab6552052ed 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -839,8 +839,8 @@ impl<'a> TraitDef<'a> { let field_tys = struct_def.fields().iter().map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } = - method_def.extract_arg_details(cx, self, type_ident, generics); + let ArgDetails { selflike_args, nonselflike_args } = + method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { method_def.call_substructure_method( @@ -862,7 +862,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method(cx, self, type_ident, generics, nonself_arg_tys, body) + method_def.create_method(cx, self, type_ident, generics, body) }); self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) @@ -883,8 +883,8 @@ impl<'a> TraitDef<'a> { .map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } = - method_def.extract_arg_details(cx, self, type_ident, generics); + let ArgDetails { selflike_args, nonselflike_args } = + method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { method_def.call_substructure_method( @@ -905,7 +905,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method(cx, self, type_ident, generics, nonself_arg_tys, body) + method_def.create_method(cx, self, type_ident, generics, body) }); let is_packed = false; // enums are never packed @@ -919,8 +919,6 @@ struct ArgDetails { selflike_args: ThinVec>, /// Expressions for all the remaining args. nonselflike_args: Vec>, - /// Additional information about all the args other than `&self`. - nonself_arg_tys: Vec<(Ident, Box)>, } impl<'a> MethodDef<'a> { @@ -942,16 +940,9 @@ impl<'a> MethodDef<'a> { !self.explicit_self } - fn extract_arg_details( - &self, - cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, - type_ident: Ident, - generics: &Generics, - ) -> ArgDetails { + fn extract_arg_details(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ArgDetails { let mut selflike_args = ThinVec::new(); let mut nonselflike_args = Vec::new(); - let mut nonself_arg_tys = Vec::new(); let span = trait_.span; if self.explicit_self { @@ -960,21 +951,18 @@ impl<'a> MethodDef<'a> { } for (ty, name) in self.nonself_args.iter() { - let ast_ty = ty.to_ty(cx, span, type_ident, generics); let ident = Ident::new(*name, span); - nonself_arg_tys.push((ident, ast_ty)); - let arg_expr = cx.expr_ident(span, ident); match ty { // Selflike (`&Self`) arguments only occur in non-static methods. - Ref(Self_, _) if !self.is_static() => selflike_args.push(arg_expr), + Ref(Self_, _) if self.explicit_self => selflike_args.push(arg_expr), Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"), _ => nonselflike_args.push(arg_expr), } } - ArgDetails { selflike_args, nonselflike_args, nonself_arg_tys } + ArgDetails { selflike_args, nonselflike_args } } fn create_method( @@ -983,7 +971,6 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'_>, type_ident: Ident, generics: &Generics, - nonself_arg_tys: Vec<(Ident, Box)>, body: BlockOrExpr, ) -> Option> { // `assert_fields_are_eq` has an empty default implementation @@ -994,19 +981,22 @@ impl<'a> MethodDef<'a> { // Create the generics that aren't for `Self`. let fn_generics = self.generics.clone(); - let args = { - let self_arg = self.explicit_self.then(|| { - let ident = Ident::new(kw::SelfLower, span); - ast::Param::from_self( - ast::AttrVec::default(), - respan(span, SelfKind::Region(None, ast::Mutability::Not)), - ident, - ) - }); - let nonself_args = - nonself_arg_tys.into_iter().map(|(name, ty)| cx.param(span, name, ty)); - self_arg.into_iter().chain(nonself_args).collect() - }; + let self_arg = self.explicit_self.then(|| { + let ident = Ident::new(kw::SelfLower, span); + ast::Param::from_self( + ast::AttrVec::default(), + respan(span, SelfKind::Region(None, ast::Mutability::Not)), + ident, + ) + }); + let args = self_arg + .into_iter() + .chain(self.nonself_args.iter().map(|(ty, name)| { + let ast_ty = ty.to_ty(cx, span, type_ident, generics); + let ident = Ident::new(*name, span); + cx.param(span, ident, ast_ty) + })) + .collect(); let ret_type = if let Ty::Unit = &self.ret_ty { ast::FnRetTy::Default(span) From d7a86e471780fc4701aea878326b1d9e21730427 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 12:46:01 +0000 Subject: [PATCH 0395/1309] optimize `Path::to_path` --- .../rustc_builtin_macros/src/deriving/generic/ty.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 98ad5b8faf52b..48b9e7f8705c9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -1,6 +1,8 @@ //! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use //! when specifying impls to be derived. +use std::iter::once; + pub(crate) use Ty::*; use rustc_ast::{self as ast, GenericArg, GenericParamKind, Generics, TyKind}; use rustc_expand::base::ExtCtxt; @@ -40,14 +42,16 @@ impl Path { self_ty: Ident, self_generics: &Generics, ) -> ast::Path { - let mut idents = self.path.iter().map(|s| Ident::new(*s, span)).collect::>(); + let idents = self.path.iter().map(|s| Ident::new(*s, span)); let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)); let params = tys.map(GenericArg::Type).collect(); - if let PathKind::Std = self.kind { + let idents = if let PathKind::Std = self.kind { let def_site = cx.with_def_site_ctxt(DUMMY_SP); - idents.insert(0, Ident::new(kw::DollarCrate, def_site)); - } + once(Ident::new(kw::DollarCrate, def_site)).chain(idents).collect() + } else { + idents.collect() + }; cx.path_all(span, false, idents, params) } } From c50e0f00e6be21412cafa546abbe926394aeb0e3 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 17 Sep 2026 20:16:07 +0000 Subject: [PATCH 0396/1309] just use `Self` instead of writing the type out --- .../src/deriving/generic/ty.rs | 22 +- tests/ui/derives/deriving-all-codegen.stdout | 204 +++++++++--------- ...ith-same-name-and-derive-default-133965.rs | 2 - ...same-name-and-derive-default-133965.stderr | 51 ++--- ...ultiple-types-with-same-name-and-derive.rs | 2 - ...ple-types-with-same-name-and-derive.stderr | 30 +-- tests/ui/stats/macro-stats.stderr | 10 +- tests/ui/traits/issue-106072.rs | 2 +- tests/ui/traits/issue-106072.stderr | 8 +- 9 files changed, 128 insertions(+), 203 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 48b9e7f8705c9..108166788d8b6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -4,7 +4,7 @@ use std::iter::once; pub(crate) use Ty::*; -use rustc_ast::{self as ast, GenericArg, GenericParamKind, Generics, TyKind}; +use rustc_ast::{self as ast, GenericArg, Generics, TyKind}; use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use thin_vec::ThinVec; @@ -106,25 +106,7 @@ impl Ty { generics: &Generics, ) -> ast::Path { match self { - Self_ => { - let params: Vec<_> = generics - .params - .iter() - .map(|param| match param.kind { - GenericParamKind::Lifetime => { - GenericArg::Lifetime(ast::Lifetime { id: param.id, ident: param.ident }) - } - GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(span, param.ident)) - } - GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(span, param.ident)) - } - }) - .collect(); - - cx.path_all(span, false, vec![self_ty], params) - } + Self_ => cx.path_ident(span, Ident::new(kw::SelfUpper, span)), Path(p) => p.to_path(cx, span, self_ty, generics), AstTy(ty) => match &ty.kind { TyKind::Path(_, path) => path.clone(), diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index bf88d1c0cb7aa..be6bd1a914c65 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -32,7 +32,7 @@ unsafe impl ::core::clone::TrivialClone for Empty { } #[automatically_derived] impl ::core::clone::Clone for Empty { #[inline] - fn clone(&self) -> Empty { *self } + fn clone(&self) -> Self { *self } } #[automatically_derived] impl ::core::marker::Copy for Empty { } @@ -46,7 +46,7 @@ impl ::core::fmt::Debug for Empty { #[automatically_derived] impl ::core::default::Default for Empty { #[inline] - fn default() -> Empty { Empty } + fn default() -> Self { Empty } } #[automatically_derived] impl ::core::hash::Hash for Empty { @@ -58,14 +58,14 @@ impl ::core::marker::StructuralPartialEq for Empty { } #[automatically_derived] impl ::core::cmp::PartialEq for Empty { #[inline] - fn eq(&self, other: &Empty) -> bool { true } + fn eq(&self, other: &Self) -> bool { true } } #[automatically_derived] impl ::core::cmp::Eq for Empty { } #[automatically_derived] impl ::core::cmp::PartialOrd for Empty { #[inline] - fn partial_cmp(&self, other: &Empty) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } @@ -73,7 +73,7 @@ impl ::core::cmp::PartialOrd for Empty { #[automatically_derived] impl ::core::cmp::Ord for Empty { #[inline] - fn cmp(&self, other: &Empty) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ordering::Equal } } @@ -90,7 +90,7 @@ unsafe impl ::core::clone::TrivialClone for Point { } #[automatically_derived] impl ::core::clone::Clone for Point { #[inline] - fn clone(&self) -> Point { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -108,7 +108,7 @@ impl ::core::fmt::Debug for Point { #[automatically_derived] impl ::core::default::Default for Point { #[inline] - fn default() -> Point { + fn default() -> Self { Point { x: ::core::default::Default::default(), y: ::core::default::Default::default(), @@ -128,7 +128,7 @@ impl ::core::marker::StructuralPartialEq for Point { } #[automatically_derived] impl ::core::cmp::PartialEq for Point { #[inline] - fn eq(&self, other: &Point) -> bool { + fn eq(&self, other: &Self) -> bool { self.x == other.x && self.y == other.y } } @@ -144,7 +144,7 @@ impl ::core::cmp::Eq for Point { #[automatically_derived] impl ::core::cmp::PartialOrd for Point { #[inline] - fn partial_cmp(&self, other: &Point) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -152,7 +152,7 @@ impl ::core::cmp::PartialOrd for Point { #[automatically_derived] impl ::core::cmp::Ord for Point { #[inline] - fn cmp(&self, other: &Point) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match ::core::cmp::Ord::cmp(&self.x, &other.x) { ::core::cmp::Ordering::Equal => ::core::cmp::Ord::cmp(&self.y, &other.y), @@ -174,7 +174,7 @@ unsafe impl ::core::clone::TrivialClone for PackedPoint { } #[automatically_derived] impl ::core::clone::Clone for PackedPoint { #[inline] - fn clone(&self) -> PackedPoint { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -192,7 +192,7 @@ impl ::core::fmt::Debug for PackedPoint { #[automatically_derived] impl ::core::default::Default for PackedPoint { #[inline] - fn default() -> PackedPoint { + fn default() -> Self { PackedPoint { x: ::core::default::Default::default(), y: ::core::default::Default::default(), @@ -212,7 +212,7 @@ impl ::core::marker::StructuralPartialEq for PackedPoint { } #[automatically_derived] impl ::core::cmp::PartialEq for PackedPoint { #[inline] - fn eq(&self, other: &PackedPoint) -> bool { + fn eq(&self, other: &Self) -> bool { ({ self.x }) == ({ other.x }) && ({ self.y }) == ({ other.y }) } } @@ -228,7 +228,7 @@ impl ::core::cmp::Eq for PackedPoint { #[automatically_derived] impl ::core::cmp::PartialOrd for PackedPoint { #[inline] - fn partial_cmp(&self, other: &PackedPoint) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -236,7 +236,7 @@ impl ::core::cmp::PartialOrd for PackedPoint { #[automatically_derived] impl ::core::cmp::Ord for PackedPoint { #[inline] - fn cmp(&self, other: &PackedPoint) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match ::core::cmp::Ord::cmp(&{ self.x }, &{ other.x }) { ::core::cmp::Ordering::Equal => ::core::cmp::Ord::cmp(&{ self.y }, &{ other.y }), @@ -252,7 +252,7 @@ unsafe impl ::core::clone::TrivialClone for TupleSingleField { } #[automatically_derived] impl ::core::clone::Clone for TupleSingleField { #[inline] - fn clone(&self) -> TupleSingleField { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -270,14 +270,14 @@ impl ::core::fmt::Debug for TupleSingleField { #[automatically_derived] impl ::core::default::Default for TupleSingleField { #[inline] - fn default() -> TupleSingleField { + fn default() -> Self { TupleSingleField(::core::default::Default::default()) } } #[automatically_derived] impl ::core::convert::From for TupleSingleField { #[inline] - fn from(value: u32) -> TupleSingleField { Self(value) } + fn from(value: u32) -> Self { Self(value) } } #[automatically_derived] impl ::core::hash::Hash for TupleSingleField { @@ -291,7 +291,7 @@ impl ::core::marker::StructuralPartialEq for TupleSingleField { } #[automatically_derived] impl ::core::cmp::PartialEq for TupleSingleField { #[inline] - fn eq(&self, other: &TupleSingleField) -> bool { self.0 == other.0 } + fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } #[automatically_derived] impl ::core::cmp::Eq for TupleSingleField { @@ -305,7 +305,7 @@ impl ::core::cmp::Eq for TupleSingleField { #[automatically_derived] impl ::core::cmp::PartialOrd for TupleSingleField { #[inline] - fn partial_cmp(&self, other: &TupleSingleField) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -313,7 +313,7 @@ impl ::core::cmp::PartialOrd for TupleSingleField { #[automatically_derived] impl ::core::cmp::Ord for TupleSingleField { #[inline] - fn cmp(&self, other: &TupleSingleField) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } @@ -327,7 +327,7 @@ unsafe impl ::core::clone::TrivialClone for SingleField { } #[automatically_derived] impl ::core::clone::Clone for SingleField { #[inline] - fn clone(&self) -> SingleField { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -345,14 +345,14 @@ impl ::core::fmt::Debug for SingleField { #[automatically_derived] impl ::core::default::Default for SingleField { #[inline] - fn default() -> SingleField { + fn default() -> Self { SingleField { foo: ::core::default::Default::default() } } } #[automatically_derived] impl ::core::convert::From for SingleField { #[inline] - fn from(value: bool) -> SingleField { Self { foo: value } } + fn from(value: bool) -> Self { Self { foo: value } } } #[automatically_derived] impl ::core::hash::Hash for SingleField { @@ -366,7 +366,7 @@ impl ::core::marker::StructuralPartialEq for SingleField { } #[automatically_derived] impl ::core::cmp::PartialEq for SingleField { #[inline] - fn eq(&self, other: &SingleField) -> bool { self.foo == other.foo } + fn eq(&self, other: &Self) -> bool { self.foo == other.foo } } #[automatically_derived] impl ::core::cmp::Eq for SingleField { @@ -380,7 +380,7 @@ impl ::core::cmp::Eq for SingleField { #[automatically_derived] impl ::core::cmp::PartialOrd for SingleField { #[inline] - fn partial_cmp(&self, other: &SingleField) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -388,7 +388,7 @@ impl ::core::cmp::PartialOrd for SingleField { #[automatically_derived] impl ::core::cmp::Ord for SingleField { #[inline] - fn cmp(&self, other: &SingleField) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.foo, &other.foo) } } @@ -411,7 +411,7 @@ unsafe impl ::core::clone::TrivialClone for Big { } #[automatically_derived] impl ::core::clone::Clone for Big { #[inline] - fn clone(&self) -> Big { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -434,7 +434,7 @@ impl ::core::fmt::Debug for Big { #[automatically_derived] impl ::core::default::Default for Big { #[inline] - fn default() -> Big { + fn default() -> Self { Big { b1: ::core::default::Default::default(), b2: ::core::default::Default::default(), @@ -466,7 +466,7 @@ impl ::core::marker::StructuralPartialEq for Big { } #[automatically_derived] impl ::core::cmp::PartialEq for Big { #[inline] - fn eq(&self, other: &Big) -> bool { + fn eq(&self, other: &Self) -> bool { self.b1 == other.b1 && self.b2 == other.b2 && self.b3 == other.b3 && self.b4 == other.b4 && self.b5 == other.b5 && self.b6 == other.b6 && self.b7 == other.b7 && @@ -485,7 +485,7 @@ impl ::core::cmp::Eq for Big { #[automatically_derived] impl ::core::cmp::PartialOrd for Big { #[inline] - fn partial_cmp(&self, other: &Big) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -493,7 +493,7 @@ impl ::core::cmp::PartialOrd for Big { #[automatically_derived] impl ::core::cmp::Ord for Big { #[inline] - fn cmp(&self, other: &Big) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match ::core::cmp::Ord::cmp(&self.b1, &other.b1) { ::core::cmp::Ordering::Equal => match ::core::cmp::Ord::cmp(&self.b2, &other.b2) { @@ -545,7 +545,7 @@ impl ::core::marker::StructuralPartialEq for Reorder { } #[automatically_derived] impl ::core::cmp::PartialEq for Reorder { #[inline] - fn eq(&self, other: &Reorder) -> bool { + fn eq(&self, other: &Self) -> bool { self.b2 == other.b2 && self.b4 == other.b4 && self.b5 == other.b5 && self.b6 == other.b6 && self.b7 == other.b7 && self.b8 == other.b8 && self.b10 == other.b10 && @@ -556,7 +556,7 @@ impl ::core::cmp::PartialEq for Reorder { #[automatically_derived] impl ::core::cmp::PartialOrd for Reorder { #[inline] - fn partial_cmp(&self, other: &Reorder) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { match ::core::cmp::PartialOrd::partial_cmp(&self.b1, &other.b1) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => @@ -626,9 +626,7 @@ struct NonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for NonCopy { #[inline] - fn clone(&self) -> NonCopy { - NonCopy(::core::clone::Clone::clone(&self.0)) - } + fn clone(&self) -> Self { NonCopy(::core::clone::Clone::clone(&self.0)) } } // A packed struct that doesn't impl `Copy`, which means it gets the non-trivial @@ -638,7 +636,7 @@ struct PackedNonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedNonCopy { #[inline] - fn clone(&self) -> PackedNonCopy { + fn clone(&self) -> Self { PackedNonCopy(::core::clone::Clone::clone(&{ self.0 })) } } @@ -649,7 +647,7 @@ struct ManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for ManualCopy { #[inline] - fn clone(&self) -> ManualCopy { + fn clone(&self) -> Self { ManualCopy(::core::clone::Clone::clone(&self.0)) } } @@ -662,7 +660,7 @@ struct PackedManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedManualCopy { #[inline] - fn clone(&self) -> PackedManualCopy { + fn clone(&self) -> Self { PackedManualCopy(::core::clone::Clone::clone(&{ self.0 })) } } @@ -681,7 +679,7 @@ impl ::core::fmt::Debug for Unsized { #[automatically_derived] impl ::core::convert::From<[u32]> for Unsized { #[inline] - fn from(value: [u32]) -> Unsized { Self(value) } + fn from(value: [u32]) -> Self { Self(value) } } #[automatically_derived] impl ::core::hash::Hash for Unsized { @@ -695,7 +693,7 @@ impl ::core::marker::StructuralPartialEq for Unsized { } #[automatically_derived] impl ::core::cmp::PartialEq for Unsized { #[inline] - fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 } + fn eq(&self, other: &Self) -> bool { self.0 == other.0 } } #[automatically_derived] impl ::core::cmp::Eq for Unsized { @@ -709,7 +707,7 @@ impl ::core::cmp::Eq for Unsized { #[automatically_derived] impl ::core::cmp::PartialOrd for Unsized { #[inline] - fn partial_cmp(&self, other: &Unsized) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -717,7 +715,7 @@ impl ::core::cmp::PartialOrd for Unsized { #[automatically_derived] impl ::core::cmp::Ord for Unsized { #[inline] - fn cmp(&self, other: &Unsized) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } @@ -736,7 +734,7 @@ struct Generic { impl ::core::clone::Clone for Generic where T::A: ::core::clone::Clone { #[inline] - fn clone(&self) -> Generic { + fn clone(&self) -> Self { Generic { t: ::core::clone::Clone::clone(&self.t), ta: ::core::clone::Clone::clone(&self.ta), @@ -762,7 +760,7 @@ impl ::core::default::Default for Generic where T::A: ::core::default::Default { #[inline] - fn default() -> Generic { + fn default() -> Self { Generic { t: ::core::default::Default::default(), ta: ::core::default::Default::default(), @@ -790,7 +788,7 @@ impl ::core::cmp::PartialEq for Generic where T::A: ::core::cmp::PartialEq { #[inline] - fn eq(&self, other: &Generic) -> bool { + fn eq(&self, other: &Self) -> bool { self.t == other.t && self.ta == other.ta && self.u == other.u } } @@ -811,7 +809,7 @@ impl ::core::cmp::PartialOrd for Generic where T::A: ::core::cmp::PartialOrd { #[inline] - fn partial_cmp(&self, other: &Generic) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { match ::core::cmp::PartialOrd::partial_cmp(&self.t, &other.t) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => @@ -829,7 +827,7 @@ impl impl ::core::cmp::Ord for Generic where T::A: ::core::cmp::Ord { #[inline] - fn cmp(&self, other: &Generic) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match ::core::cmp::Ord::cmp(&self.t, &other.t) { ::core::cmp::Ordering::Equal => match ::core::cmp::Ord::cmp(&self.ta, &other.ta) { @@ -855,7 +853,7 @@ impl where T::A: ::core::clone::Clone + ::core::marker::Copy { #[inline] - fn clone(&self) -> PackedGeneric { + fn clone(&self) -> Self { PackedGeneric(::core::clone::Clone::clone(&{ self.0 }), ::core::clone::Clone::clone(&{ self.1 }), ::core::clone::Clone::clone(&{ self.2 })) @@ -882,7 +880,7 @@ impl ::core::default::Default for PackedGeneric where T::A: ::core::default::Default { #[inline] - fn default() -> PackedGeneric { + fn default() -> Self { PackedGeneric(::core::default::Default::default(), ::core::default::Default::default(), ::core::default::Default::default()) @@ -911,7 +909,7 @@ impl where T::A: ::core::cmp::PartialEq + ::core::marker::Copy { #[inline] - fn eq(&self, other: &PackedGeneric) -> bool { + fn eq(&self, other: &Self) -> bool { ({ self.0 }) == ({ other.0 }) && ({ self.1 }) == ({ other.1 }) && ({ self.2 }) == ({ other.2 }) } @@ -935,7 +933,7 @@ impl where T::A: ::core::cmp::PartialOrd + ::core::marker::Copy { #[inline] - fn partial_cmp(&self, other: &PackedGeneric) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { match ::core::cmp::PartialOrd::partial_cmp(&{ self.0 }, &{ other.0 }) { @@ -957,7 +955,7 @@ impl ::core::cmp::Ord for PackedGeneric where T::A: ::core::cmp::Ord + ::core::marker::Copy { #[inline] - fn cmp(&self, other: &PackedGeneric) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match ::core::cmp::Ord::cmp(&{ self.0 }, &{ other.0 }) { ::core::cmp::Ordering::Equal => match ::core::cmp::Ord::cmp(&{ self.1 }, &{ other.1 }) { @@ -978,7 +976,7 @@ unsafe impl ::core::clone::TrivialClone for Enum0 { } #[automatically_derived] impl ::core::clone::Clone for Enum0 { #[inline] - fn clone(&self) -> Enum0 { *self } + fn clone(&self) -> Self { *self } } #[automatically_derived] impl ::core::marker::Copy for Enum0 { } @@ -1001,14 +999,14 @@ impl ::core::marker::StructuralPartialEq for Enum0 { } #[automatically_derived] impl ::core::cmp::PartialEq for Enum0 { #[inline] - fn eq(&self, other: &Enum0) -> bool { match *self {} } + fn eq(&self, other: &Self) -> bool { match *self {} } } #[automatically_derived] impl ::core::cmp::Eq for Enum0 { } #[automatically_derived] impl ::core::cmp::PartialOrd for Enum0 { #[inline] - fn partial_cmp(&self, other: &Enum0) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { match *self {} } @@ -1016,7 +1014,7 @@ impl ::core::cmp::PartialOrd for Enum0 { #[automatically_derived] impl ::core::cmp::Ord for Enum0 { #[inline] - fn cmp(&self, other: &Enum0) -> ::core::cmp::Ordering { match *self {} } + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match *self {} } } // A single-variant enum. @@ -1028,7 +1026,7 @@ enum Enum1 { #[automatically_derived] impl ::core::clone::Clone for Enum1 { #[inline] - fn clone(&self) -> Enum1 { + fn clone(&self) -> Self { match self { Enum1::Single { x: __self_0 } => Enum1::Single { x: ::core::clone::Clone::clone(__self_0) }, @@ -1061,7 +1059,7 @@ impl ::core::marker::StructuralPartialEq for Enum1 { } #[automatically_derived] impl ::core::cmp::PartialEq for Enum1 { #[inline] - fn eq(&self, other: &Enum1) -> bool { + fn eq(&self, other: &Self) -> bool { match (self, other) { (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => __self_0 == __arg1_0, @@ -1080,7 +1078,7 @@ impl ::core::cmp::Eq for Enum1 { #[automatically_derived] impl ::core::cmp::PartialOrd for Enum1 { #[inline] - fn partial_cmp(&self, other: &Enum1) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1088,7 +1086,7 @@ impl ::core::cmp::PartialOrd for Enum1 { #[automatically_derived] impl ::core::cmp::Ord for Enum1 { #[inline] - fn cmp(&self, other: &Enum1) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), @@ -1105,7 +1103,7 @@ enum Fieldless1 { #[automatically_derived] impl ::core::clone::Clone for Fieldless1 { #[inline] - fn clone(&self) -> Fieldless1 { Fieldless1::A } + fn clone(&self) -> Self { Fieldless1::A } } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { @@ -1117,7 +1115,7 @@ impl ::core::fmt::Debug for Fieldless1 { #[automatically_derived] impl ::core::default::Default for Fieldless1 { #[inline] - fn default() -> Fieldless1 { Self::A } + fn default() -> Self { Self::A } } #[automatically_derived] impl ::core::hash::Hash for Fieldless1 { @@ -1129,14 +1127,14 @@ impl ::core::marker::StructuralPartialEq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::PartialEq for Fieldless1 { #[inline] - fn eq(&self, other: &Fieldless1) -> bool { true } + fn eq(&self, other: &Self) -> bool { true } } #[automatically_derived] impl ::core::cmp::Eq for Fieldless1 { } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless1 { #[inline] - fn partial_cmp(&self, other: &Fieldless1) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } @@ -1144,7 +1142,7 @@ impl ::core::cmp::PartialOrd for Fieldless1 { #[automatically_derived] impl ::core::cmp::Ord for Fieldless1 { #[inline] - fn cmp(&self, other: &Fieldless1) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ordering::Equal } } @@ -1163,7 +1161,7 @@ unsafe impl ::core::clone::TrivialClone for Fieldless { } #[automatically_derived] impl ::core::clone::Clone for Fieldless { #[inline] - fn clone(&self) -> Fieldless { *self } + fn clone(&self) -> Self { *self } } #[automatically_derived] impl ::core::marker::Copy for Fieldless { } @@ -1182,7 +1180,7 @@ impl ::core::fmt::Debug for Fieldless { #[automatically_derived] impl ::core::default::Default for Fieldless { #[inline] - fn default() -> Fieldless { Self::A } + fn default() -> Self { Self::A } } #[automatically_derived] impl ::core::hash::Hash for Fieldless { @@ -1197,7 +1195,7 @@ impl ::core::marker::StructuralPartialEq for Fieldless { } #[automatically_derived] impl ::core::cmp::PartialEq for Fieldless { #[inline] - fn eq(&self, other: &Fieldless) -> bool { + fn eq(&self, other: &Self) -> bool { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); __self_discr == __arg1_discr @@ -1208,7 +1206,7 @@ impl ::core::cmp::Eq for Fieldless { } #[automatically_derived] impl ::core::cmp::PartialOrd for Fieldless { #[inline] - fn partial_cmp(&self, other: &Fieldless) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1216,7 +1214,7 @@ impl ::core::cmp::PartialOrd for Fieldless { #[automatically_derived] impl ::core::cmp::Ord for Fieldless { #[inline] - fn cmp(&self, other: &Fieldless) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) @@ -1241,7 +1239,7 @@ unsafe impl ::core::clone::TrivialClone for Mixed { } #[automatically_derived] impl ::core::clone::Clone for Mixed { #[inline] - fn clone(&self) -> Mixed { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; let _: ::core::clone::AssertParamIsClone>; let _: ::core::clone::AssertParamIsClone>; @@ -1269,7 +1267,7 @@ impl ::core::fmt::Debug for Mixed { #[automatically_derived] impl ::core::default::Default for Mixed { #[inline] - fn default() -> Mixed { Self::P } + fn default() -> Self { Self::P } } #[automatically_derived] impl ::core::hash::Hash for Mixed { @@ -1292,7 +1290,7 @@ impl ::core::marker::StructuralPartialEq for Mixed { } #[automatically_derived] impl ::core::cmp::PartialEq for Mixed { #[inline] - fn eq(&self, other: &Mixed) -> bool { + fn eq(&self, other: &Self) -> bool { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); __self_discr == __arg1_discr && @@ -1320,7 +1318,7 @@ impl ::core::cmp::Eq for Mixed { #[automatically_derived] impl ::core::cmp::PartialOrd for Mixed { #[inline] - fn partial_cmp(&self, other: &Mixed) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1328,7 +1326,7 @@ impl ::core::cmp::PartialOrd for Mixed { #[automatically_derived] impl ::core::cmp::Ord for Mixed { #[inline] - fn cmp(&self, other: &Mixed) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { @@ -1367,7 +1365,7 @@ impl ::core::marker::StructuralPartialEq for ReorderEnum { } #[automatically_derived] impl ::core::cmp::PartialEq for ReorderEnum { #[inline] - fn eq(&self, other: &ReorderEnum) -> bool { + fn eq(&self, other: &Self) -> bool { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); __self_discr == __arg1_discr && @@ -1387,7 +1385,7 @@ impl ::core::cmp::PartialEq for ReorderEnum { #[automatically_derived] impl ::core::cmp::PartialOrd for ReorderEnum { #[inline] - fn partial_cmp(&self, other: &ReorderEnum) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); @@ -1427,7 +1425,7 @@ enum Fielded { X(u32), Y(bool), Z(Option), } #[automatically_derived] impl ::core::clone::Clone for Fielded { #[inline] - fn clone(&self) -> Fielded { + fn clone(&self) -> Self { match self { Fielded::X(__self_0) => Fielded::X(::core::clone::Clone::clone(__self_0)), @@ -1473,7 +1471,7 @@ impl ::core::marker::StructuralPartialEq for Fielded { } #[automatically_derived] impl ::core::cmp::PartialEq for Fielded { #[inline] - fn eq(&self, other: &Fielded) -> bool { + fn eq(&self, other: &Self) -> bool { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); __self_discr == __arg1_discr && @@ -1502,7 +1500,7 @@ impl ::core::cmp::Eq for Fielded { #[automatically_derived] impl ::core::cmp::PartialOrd for Fielded { #[inline] - fn partial_cmp(&self, other: &Fielded) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1510,7 +1508,7 @@ impl ::core::cmp::PartialOrd for Fielded { #[automatically_derived] impl ::core::cmp::Ord for Fielded { #[inline] - fn cmp(&self, other: &Fielded) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { @@ -1535,7 +1533,7 @@ enum EnumGeneric { One(T), Two(U), } impl ::core::clone::Clone for EnumGeneric { #[inline] - fn clone(&self) -> EnumGeneric { + fn clone(&self) -> Self { match self { EnumGeneric::One(__self_0) => EnumGeneric::One(::core::clone::Clone::clone(__self_0)), @@ -1586,7 +1584,7 @@ impl impl ::core::cmp::PartialEq for EnumGeneric { #[inline] - fn eq(&self, other: &EnumGeneric) -> bool { + fn eq(&self, other: &Self) -> bool { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); __self_discr == __arg1_discr && @@ -1614,7 +1612,7 @@ impl ::core::cmp::Eq for impl ::core::cmp::PartialOrd for EnumGeneric { #[inline] - fn partial_cmp(&self, other: &EnumGeneric) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); @@ -1633,7 +1631,7 @@ impl impl ::core::cmp::Ord for EnumGeneric { #[inline] - fn cmp(&self, other: &EnumGeneric) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { let __self_discr = ::core::intrinsics::discriminant_value(self); let __arg1_discr = ::core::intrinsics::discriminant_value(other); match ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) { @@ -1662,7 +1660,7 @@ impl ::core::marker::StructuralPartialEq for NonCopyEnum { } #[automatically_derived] impl ::core::cmp::PartialEq for NonCopyEnum { #[inline] - fn eq(&self, other: &NonCopyEnum) -> bool { + fn eq(&self, other: &Self) -> bool { match (self, other) { (NonCopyEnum::NonCopyField(__self_0), NonCopyEnum::NonCopyField(__arg1_0)) => __self_0 == __arg1_0, @@ -1686,7 +1684,7 @@ unsafe impl ::core::clone::TrivialClone for Union { } #[automatically_derived] impl ::core::clone::Clone for Union { #[inline] - fn clone(&self) -> Union { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsCopy; *self } @@ -1703,7 +1701,7 @@ unsafe impl ::core::clone::TrivialClone for FooCopyClone { } #[automatically_derived] impl ::core::clone::Clone for FooCopyClone { #[inline] - fn clone(&self) -> FooCopyClone { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -1716,7 +1714,7 @@ unsafe impl ::core::clone::TrivialClone for FooCloneCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneCopy { #[inline] - fn clone(&self) -> FooCloneCopy { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -1731,7 +1729,7 @@ unsafe impl ::core::clone::TrivialClone for FooCopyAndClone { } #[automatically_derived] impl ::core::clone::Clone for FooCopyAndClone { #[inline] - fn clone(&self) -> FooCopyAndClone { + fn clone(&self) -> Self { let _: ::core::clone::AssertParamIsClone; *self } @@ -1748,7 +1746,7 @@ impl ::core::marker::Copy for FooCloneAndCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneAndCopy { #[inline] - fn clone(&self) -> FooCloneAndCopy { + fn clone(&self) -> Self { FooCloneAndCopy(::core::clone::Clone::clone(&self.0)) } } @@ -1757,7 +1755,7 @@ struct FooPartialOrdOrd(i32); #[automatically_derived] impl ::core::cmp::PartialOrd for FooPartialOrdOrd { #[inline] - fn partial_cmp(&self, other: &FooPartialOrdOrd) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1765,7 +1763,7 @@ impl ::core::cmp::PartialOrd for FooPartialOrdOrd { #[automatically_derived] impl ::core::cmp::Ord for FooPartialOrdOrd { #[inline] - fn cmp(&self, other: &FooPartialOrdOrd) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } @@ -1774,14 +1772,14 @@ struct FooOrdPartialOrd(i32); #[automatically_derived] impl ::core::cmp::Ord for FooOrdPartialOrd { #[inline] - fn cmp(&self, other: &FooOrdPartialOrd) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } #[automatically_derived] impl ::core::cmp::PartialOrd for FooOrdPartialOrd { #[inline] - fn partial_cmp(&self, other: &FooOrdPartialOrd) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1791,7 +1789,7 @@ struct FooOrdBeforePartialOrd(i32); #[automatically_derived] impl ::core::cmp::PartialOrd for FooOrdBeforePartialOrd { #[inline] - fn partial_cmp(&self, other: &FooOrdBeforePartialOrd) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ord::cmp(self, other)) } @@ -1799,7 +1797,7 @@ impl ::core::cmp::PartialOrd for FooOrdBeforePartialOrd { #[automatically_derived] impl ::core::cmp::Ord for FooOrdBeforePartialOrd { #[inline] - fn cmp(&self, other: &FooOrdBeforePartialOrd) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } @@ -1809,14 +1807,14 @@ struct FooPartialOrdBeforeOrd(i32); #[automatically_derived] impl ::core::cmp::Ord for FooPartialOrdBeforeOrd { #[inline] - fn cmp(&self, other: &FooPartialOrdBeforeOrd) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ord::cmp(&self.0, &other.0) } } #[automatically_derived] impl ::core::cmp::PartialOrd for FooPartialOrdBeforeOrd { #[inline] - fn partial_cmp(&self, other: &FooPartialOrdBeforeOrd) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::cmp::PartialOrd::partial_cmp(&self.0, &other.0) } @@ -1826,7 +1824,7 @@ struct UnitStruct; #[automatically_derived] impl ::core::cmp::PartialOrd for UnitStruct { #[inline] - fn partial_cmp(&self, other: &UnitStruct) + fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { ::core::option::Option::Some(::core::cmp::Ordering::Equal) } @@ -1834,7 +1832,7 @@ impl ::core::cmp::PartialOrd for UnitStruct { #[automatically_derived] impl ::core::cmp::Ord for UnitStruct { #[inline] - fn cmp(&self, other: &UnitStruct) -> ::core::cmp::Ordering { + fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { ::core::cmp::Ordering::Equal } } diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index f4193f18352d0..34ba998c1dc60 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -3,8 +3,6 @@ struct NonGeneric {} #[derive(Default)] -//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied struct NonGeneric<'a, const N: usize> {} //~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied //~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index 0d6aaaf5186d3..d758cb13f9939 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NonGeneric` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:1 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:1 | LL | struct NonGeneric {} | ----------------- previous definition of the type `NonGeneric` here @@ -10,42 +10,7 @@ LL | struct NonGeneric<'a, const N: usize> {} = note: `NonGeneric` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 - | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 lifetime arguments -... -LL | struct NonGeneric<'a, const N: usize> {} - | -- help: remove the lifetime argument - | -note: struct defined here, with 0 lifetime parameters - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 - | -LL | struct NonGeneric {} - | ^^^^^^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:5:10 - | -LL | #[derive(Default)] - | ^^^^^^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 - | -LL | struct NonGeneric {} - | ^^^^^^^^^^ - -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:19 - | -LL | struct NonGeneric<'a, const N: usize> {} - | ^^ unused lifetime parameter - | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` - -error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:8 | LL | struct NonGeneric<'a, const N: usize> {} | ^^^^^^^^^^ -- help: remove the lifetime argument @@ -59,7 +24,7 @@ LL | struct NonGeneric {} | ^^^^^^^^^^ error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:8:8 + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:8 | LL | struct NonGeneric<'a, const N: usize> {} | ^^^^^^^^^^ - help: remove the unnecessary generic argument @@ -72,7 +37,15 @@ note: struct defined here, with 0 generic parameters LL | struct NonGeneric {} | ^^^^^^^^^^ -error: aborting due to 6 previous errors +error[E0392]: lifetime parameter `'a` is never used + --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:19 + | +LL | struct NonGeneric<'a, const N: usize> {} + | ^^ unused lifetime parameter + | + = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` + +error: aborting due to 4 previous errors Some errors have detailed explanations: E0107, E0392, E0428. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index e946c0c5350ed..3caf5434cd008 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -8,12 +8,10 @@ struct NotSM; #[derive(PartialEq, Eq)] -//~^ ERROR: struct takes 0 generic arguments struct NotSM(T); //~^ ERROR: struct takes 0 generic arguments //~| ERROR: struct takes 0 generic arguments //~| ERROR: struct takes 0 generic arguments //~| ERROR: the name `NotSM` is defined multiple times -//~| ERROR: no field `0` fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index e80cf35d81e1d..e745b3ce8fc2f 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `NotSM` is defined multiple times - --> $DIR/multiple-types-with-same-name-and-derive.rs:12:1 + --> $DIR/multiple-types-with-same-name-and-derive.rs:11:1 | LL | struct NotSM; | ------------- previous definition of the type `NotSM` here @@ -10,7 +10,7 @@ LL | struct NotSM(T); = note: `NotSM` must be defined only once in the type namespace of this module error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 + --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 | LL | struct NotSM(T); | ^^^^^ expected 0 generic arguments @@ -22,19 +22,7 @@ LL | struct NotSM; | ^^^^^ error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:10:10 - | -LL | #[derive(PartialEq, Eq)] - | ^^^^^^^^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 + --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 | LL | struct NotSM(T); | ^^^^^ expected 0 generic arguments @@ -47,7 +35,7 @@ LL | struct NotSM; = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:12:8 + --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 | LL | struct NotSM(T); | ^^^^^ expected 0 generic arguments @@ -59,13 +47,7 @@ LL | struct NotSM; | ^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` -error[E0609]: no field `0` on type `&NotSM` - --> $DIR/multiple-types-with-same-name-and-derive.rs:12:17 - | -LL | struct NotSM(T); - | ^ unknown field - -error: aborting due to 6 previous errors +error: aborting due to 4 previous errors -Some errors have detailed explanations: E0107, E0428, E0609. +Some errors have detailed explanations: E0107, E0428. For more information about an error, try `rustc --explain E0107`. diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index c70895067eb5f..e3ef2add347dc 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -2,15 +2,15 @@ macro-stats ==================================================================== macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- -macro-stats #[derive(Clone)] 8 67 8.4 1_879 234.9 +macro-stats #[derive(Clone)] 8 67 8.4 1_895 236.9 macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 macro-stats q! 1 26 26.0 519 519.0 -macro-stats #[derive(Ord)] 1 15 15.0 503 503.0 -macro-stats #[derive(Default)] 2 16 8.0 403 201.5 +macro-stats #[derive(Ord)] 1 15 15.0 505 505.0 +macro-stats #[derive(Default)] 2 16 8.0 407 203.5 macro-stats #[derive(Eq)] 1 11 11.0 312 312.0 macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 -macro-stats #[derive(PartialEq)] 1 9 9.0 267 267.0 -macro-stats #[derive(PartialOrd)] 1 8 8.0 254 254.0 +macro-stats #[derive(PartialEq)] 1 9 9.0 269 269.0 +macro-stats #[derive(PartialOrd)] 1 8 8.0 256 256.0 macro-stats #[derive(Copy)] 1 2 2.0 61 61.0 macro-stats p! 1 3 3.0 32 32.0 macro-stats trait_impl_tys! 1 2 2.0 28 28.0 diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 6b04004621d82..74a8893d38b07 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,4 +1,4 @@ -#[derive(Clone)] //~ ERROR: expected a type, found a trait +#[derive(Clone)] struct Foo; //~ ERROR: expected a type, found a trait trait Foo {} //~ ERROR: the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index 57661fda73079..ccee54cecf498 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -16,13 +16,7 @@ LL | #[derive(Clone)] LL | struct Foo; | ^^^ -error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:1:10 - | -LL | #[derive(Clone)] - | ^^^^^ - -error: aborting due to 3 previous errors +error: aborting due to 2 previous errors Some errors have detailed explanations: E0428, E0782. For more information about an error, try `rustc --explain E0428`. From 072a61a39fed3c98c3fdc9cdfa1cc3fd914909d1 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 17 Sep 2026 20:19:51 +0000 Subject: [PATCH 0397/1309] remove only recursively used arguments --- .../src/deriving/generic/mod.rs | 35 ++++++------------ .../src/deriving/generic/ty.rs | 36 +++++-------------- 2 files changed, 19 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index baab6552052ed..050b2e793f501 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -571,7 +571,7 @@ impl<'a> TraitDef<'a> { methods: impl Iterator>, is_packed: bool, ) -> Box { - let trait_path = self.path.to_path(cx, self.span, type_ident, generics); + let trait_path = self.path.to_path(cx, self.span); // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem` let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { @@ -589,7 +589,7 @@ impl<'a> TraitDef<'a> { generics: Generics::default(), after_where_clause: ast::WhereClause::default(), bounds: ThinVec::new(), - ty: Some(type_def.to_ty(cx, self.span, type_ident, generics)), + ty: Some(type_def.to_ty(cx, self.span)), })), tokens: None, }) @@ -613,9 +613,7 @@ impl<'a> TraitDef<'a> { let bounds: ThinVec<_> = self .additional_bounds .iter() - .map(|p| { - cx.trait_bound(p.to_path(cx, span, type_ident, generics), self.is_const) - }) + .map(|p| cx.trait_bound(p.to_path(cx, span), self.is_const)) .chain( // Add a bound for the current trait. self.skip_path_as_bound.not().then(|| { @@ -628,10 +626,7 @@ impl<'a> TraitDef<'a> { // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); - Some(cx.trait_bound( - p.to_path(cx, span, type_ident, generics), - self.is_const, - )) + Some(cx.trait_bound(p.to_path(cx, span), self.is_const)) } else { None } @@ -697,12 +692,7 @@ impl<'a> TraitDef<'a> { let mut bounds: ThinVec<_> = self .additional_bounds .iter() - .map(|p| { - cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - ) - }) + .map(|p| cx.trait_bound(p.to_path(cx, self.span), self.is_const)) .collect(); // Require the current trait. @@ -713,10 +703,7 @@ impl<'a> TraitDef<'a> { // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { let p = deriving::path_std!(marker::Copy); - bounds.push(cx.trait_bound( - p.to_path(cx, self.span, type_ident, generics), - self.is_const, - )); + bounds.push(cx.trait_bound(p.to_path(cx, self.span), self.is_const)); } if !bounds.is_empty() { @@ -862,7 +849,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method(cx, self, type_ident, generics, body) + method_def.create_method(cx, self, body) }); self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) @@ -905,7 +892,7 @@ impl<'a> TraitDef<'a> { ) }; - method_def.create_method(cx, self, type_ident, generics, body) + method_def.create_method(cx, self, body) }); let is_packed = false; // enums are never packed @@ -969,8 +956,6 @@ impl<'a> MethodDef<'a> { &self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>, - type_ident: Ident, - generics: &Generics, body: BlockOrExpr, ) -> Option> { // `assert_fields_are_eq` has an empty default implementation @@ -992,7 +977,7 @@ impl<'a> MethodDef<'a> { let args = self_arg .into_iter() .chain(self.nonself_args.iter().map(|(ty, name)| { - let ast_ty = ty.to_ty(cx, span, type_ident, generics); + let ast_ty = ty.to_ty(cx, span); let ident = Ident::new(*name, span); cx.param(span, ident, ast_ty) })) @@ -1001,7 +986,7 @@ impl<'a> MethodDef<'a> { let ret_type = if let Ty::Unit = &self.ret_ty { ast::FnRetTy::Default(span) } else { - ast::FnRetTy::Ty(self.ret_ty.to_ty(cx, span, type_ident, generics)) + ast::FnRetTy::Ty(self.ret_ty.to_ty(cx, span)) }; let method_ident = Ident::new(self.name, span); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 108166788d8b6..9efe0b109f17d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -4,7 +4,7 @@ use std::iter::once; pub(crate) use Ty::*; -use rustc_ast::{self as ast, GenericArg, Generics, TyKind}; +use rustc_ast::{self as ast, GenericArg, TyKind}; use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use thin_vec::ThinVec; @@ -35,15 +35,9 @@ impl Path { Path { path, params, kind } } - pub(crate) fn to_path( - &self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics, - ) -> ast::Path { + pub(crate) fn to_path(&self, cx: &ExtCtxt<'_>, span: Span) -> ast::Path { let idents = self.path.iter().map(|s| Ident::new(*s, span)); - let tys = self.params.iter().map(|t| t.to_ty(cx, span, self_ty, self_generics)); + let tys = self.params.iter().map(|t| t.to_ty(cx, span)); let params = tys.map(GenericArg::Type).collect(); let idents = if let PathKind::Std = self.kind { @@ -76,20 +70,14 @@ pub(crate) fn self_ref() -> Ty { } impl Ty { - pub(crate) fn to_ty( - &self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - self_generics: &Generics, - ) -> Box { + pub(crate) fn to_ty(&self, cx: &ExtCtxt<'_>, span: Span) -> Box { match self { Ref(ty, mutbl) => { - let raw_ty = ty.to_ty(cx, span, self_ty, self_generics); + let raw_ty = ty.to_ty(cx, span); cx.ty_ref(span, raw_ty, None, *mutbl) } - Path(p) => cx.ty_path(p.to_path(cx, span, self_ty, self_generics)), - Self_ => cx.ty_path(self.to_path(cx, span, self_ty, self_generics)), + Path(p) => cx.ty_path(p.to_path(cx, span)), + Self_ => cx.ty_path(self.to_path(cx, span)), Unit => { let ty = ast::TyKind::Tup(ThinVec::new()); cx.ty(span, ty) @@ -98,16 +86,10 @@ impl Ty { } } - pub(crate) fn to_path( - &self, - cx: &ExtCtxt<'_>, - span: Span, - self_ty: Ident, - generics: &Generics, - ) -> ast::Path { + pub(crate) fn to_path(&self, cx: &ExtCtxt<'_>, span: Span) -> ast::Path { match self { Self_ => cx.path_ident(span, Ident::new(kw::SelfUpper, span)), - Path(p) => p.to_path(cx, span, self_ty, generics), + Path(p) => p.to_path(cx, span), AstTy(ty) => match &ty.kind { TyKind::Path(_, path) => path.clone(), _ => cx.dcx().span_bug(span, "non-path in a path in generic `derive`"), From 9bcf16954e8491d9aaf5532f79272c335646760e Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Sat, 19 Sep 2026 15:45:43 +0200 Subject: [PATCH 0398/1309] Don't claim that escaping value is a reference --- .../rustc_borrowck/src/diagnostics/region_errors.rs | 6 ++---- src/tools/clippy/tests/ui/crashes/ice-6256.stderr | 2 +- tests/ui/any/any_static.next.stderr | 2 +- tests/ui/any/any_static.old.stderr | 2 +- tests/ui/any/static_method_bound.stderr | 2 +- tests/ui/async-await/issues/issue-62097.stderr | 2 +- tests/ui/async-await/issues/issue-72312.rs | 2 +- tests/ui/async-await/issues/issue-72312.stderr | 2 +- tests/ui/borrowck/anonymous-region-in-apit.stderr | 2 +- tests/ui/borrowck/fn-item-check-type-params.stderr | 2 +- tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr | 2 +- tests/ui/borrowck/issue-103624.stderr | 2 +- tests/ui/borrowck/issue-45983.stderr | 2 +- tests/ui/borrowck/issue-7573.rs | 2 +- tests/ui/borrowck/issue-7573.stderr | 2 +- tests/ui/borrowck/regions-escape-bound-fn-2.stderr | 2 +- tests/ui/borrowck/regions-escape-bound-fn.stderr | 2 +- .../borrowck/regions-escape-unboxed-closure.stderr | 2 +- ...matching-lifetime-but-unused-not-mentioned.stderr | 2 +- .../ptr-to-trait-obj-different-regions-misc.stderr | 2 +- ...losure-bounds-static-cant-capture-borrowed.stderr | 2 +- .../expect-region-supply-region.stderr | 4 ++-- tests/ui/coroutine/resume-arg-outlives-2.stderr | 2 +- .../bugs/hrtb-implied-2.stderr | 2 +- .../bugs/hrtb-implied-3.stderr | 2 +- .../ui/impl-header-lifetime-elision/dyn-trait.stderr | 2 +- ...ssue-90600-expected-return-static-indirect.stderr | 2 +- .../lifetime-bound-will-change-warning.stderr | 4 ++-- .../closure-arg-type-mismatch.stderr | 2 +- .../nll/check-normalized-sig-for-wf.current.stderr | 4 ++-- tests/ui/nll/check-normalized-sig-for-wf.next.stderr | 4 ++-- ...d-shorter-to-static-comparing-against-free.stderr | 2 +- ...te-approximated-shorter-to-static-no-bound.stderr | 2 +- ...approximated-shorter-to-static-wrong-bound.stderr | 2 +- tests/ui/nll/issue-54779-anon-static-lifetime.stderr | 2 +- tests/ui/nll/user-annotations/closure-substs.stderr | 2 +- .../object-lifetime-default-mybox.stderr | 2 +- tests/ui/regions/issue-78262.base.stderr | 2 +- tests/ui/regions/issue-78262.polonius.stderr | 2 +- tests/ui/regions/regions-nested-fns.stderr | 2 +- tests/ui/regions/regions-static-bound.stderr | 4 ++-- ...icit-static-bound-needing-more-suggestions.stderr | 2 +- ...pl-on-dyn-trait-with-implicit-static-bound.stderr | 12 ++++++------ tests/ui/traits/object/issue-44454-2.stderr | 2 +- .../references/reject_lifetime_extension.stderr | 2 +- 45 files changed, 56 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 93d888d17dc51..414f8dd58d439 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -662,7 +662,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { /// --> $DIR/lifetime-bound-will-change-warning.rs:44:5 /// | /// LL | fn test2<'a>(x: &'a Box) { - /// | - `x` is a reference that is only valid in the function body + /// | - `x` is only valid in the function body /// LL | // but ref_obj will not, so warn. /// LL | ref_obj(x) /// | ^^^^^^^^^^ `x` escapes the function body here @@ -714,9 +714,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { if let Some((Some(fr_name), fr_span)) = fr_name_and_span { diag.span_label( fr_span, - format!( - "`{fr_name}` is a reference that is only valid in the {escapes_from} body", - ), + format!("`{fr_name}` is only valid in the {escapes_from} body"), ); diag.span_label(*span, format!("`{fr_name}` escapes the {escapes_from} body here")); diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr index 922772a6147bc..4cb83e24e7a05 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr @@ -7,7 +7,7 @@ LL | let f = |x: &dyn TT| x.func(); | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` - | `x` is a reference that is only valid in the closure body + | `x` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/any/any_static.next.stderr b/tests/ui/any/any_static.next.stderr index e57d544140980..2f4a0e10427d8 100644 --- a/tests/ui/any/any_static.next.stderr +++ b/tests/ui/any/any_static.next.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn extend(a: &Payload) -> &'static Payload { | - - let's call the lifetime of this reference `'1` | | - | `a` is a reference that is only valid in the function body + | `a` is only valid in the function body LL | let b: &(dyn Any + 'static) = try_as_dyn::<&Payload, dyn Any + 'static>(&a).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/any/any_static.old.stderr b/tests/ui/any/any_static.old.stderr index e57d544140980..2f4a0e10427d8 100644 --- a/tests/ui/any/any_static.old.stderr +++ b/tests/ui/any/any_static.old.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn extend(a: &Payload) -> &'static Payload { | - - let's call the lifetime of this reference `'1` | | - | `a` is a reference that is only valid in the function body + | `a` is only valid in the function body LL | let b: &(dyn Any + 'static) = try_as_dyn::<&Payload, dyn Any + 'static>(&a).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/any/static_method_bound.stderr b/tests/ui/any/static_method_bound.stderr index 152672d024ab1..a886e4d8ae6d0 100644 --- a/tests/ui/any/static_method_bound.stderr +++ b/tests/ui/any/static_method_bound.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn extend(a: &Payload) -> &'static Payload { | - - let's call the lifetime of this reference `'1` | | - | `a` is a reference that is only valid in the function body + | `a` is only valid in the function body LL | let b: &(dyn Trait + 'static) = try_as_dyn::<&Payload, dyn Trait + 'static>(&a).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr index adc8265e6c482..1422d315f88b0 100644 --- a/tests/ui/async-await/issues/issue-62097.stderr +++ b/tests/ui/async-await/issues/issue-62097.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of method LL | pub async fn run_dummy_fn(&self) { | ----- | | - | `self` is a reference that is only valid in the method body + | `self` is only valid in the method body | let's call the lifetime of this reference `'1` LL | foo(|| self.bar()).await; | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/async-await/issues/issue-72312.rs b/tests/ui/async-await/issues/issue-72312.rs index ba4c391058586..c2f01071f4a42 100644 --- a/tests/ui/async-await/issues/issue-72312.rs +++ b/tests/ui/async-await/issues/issue-72312.rs @@ -8,7 +8,7 @@ struct Problem; impl Problem { pub async fn start(&self) { //~^ NOTE let's call - //~| NOTE `self` is a reference + //~| NOTE `self` is only valid require_static(async move { //~^ ERROR borrowed data escapes //~| NOTE `self` escapes diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr index 8e6fb138a1faa..33092a1abd3ab 100644 --- a/tests/ui/async-await/issues/issue-72312.stderr +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of method LL | pub async fn start(&self) { | ----- | | - | `self` is a reference that is only valid in the method body + | `self` is only valid in the method body | let's call the lifetime of this reference `'1` ... LL | / require_static(async move { diff --git a/tests/ui/borrowck/anonymous-region-in-apit.stderr b/tests/ui/borrowck/anonymous-region-in-apit.stderr index 72dfbb797ebc7..1652c7f3a4e5d 100644 --- a/tests/ui/borrowck/anonymous-region-in-apit.stderr +++ b/tests/ui/borrowck/anonymous-region-in-apit.stderr @@ -9,7 +9,7 @@ LL | |baz: &str| foo.bar(baz); | | | `baz` escapes the closure body here | | | argument requires that `'1` must outlive `'2` | | let's call the lifetime of this reference `'1` - | `baz` is a reference that is only valid in the closure body + | `baz` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/fn-item-check-type-params.stderr b/tests/ui/borrowck/fn-item-check-type-params.stderr index 7a0a7752a14b2..b5738135e54a1 100644 --- a/tests/ui/borrowck/fn-item-check-type-params.stderr +++ b/tests/ui/borrowck/fn-item-check-type-params.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/fn-item-check-type-params.rs:31:5 | LL | pub fn test_call<'a>(val: &'a str) { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | extend_lt(val); diff --git a/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr index 2b900a8e68a7b..daedf243712f8 100644 --- a/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr +++ b/tests/ui/borrowck/ice-on-non-ref-sig-ty.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of method LL | impl<'a> W<'a> for &'static () { | -- lifetime `'a` defined here LL | fn g(self, x: &'a T) -> &'static T { - | ---- - `x` is a reference that is only valid in the method body + | ---- - `x` is only valid in the method body | | | `self` declared here, outside of the method body LL | f(&self, x) diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index caae758a48070..77e961ee48fc2 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of method LL | async fn foo(&self) { | ----- | | - | `self` is a reference that is only valid in the method body + | `self` is only valid in the method body | let's call the lifetime of this reference `'1` LL | let bar = self.b.bar().await; LL | / spawn_blocking(move || { diff --git a/tests/ui/borrowck/issue-45983.stderr b/tests/ui/borrowck/issue-45983.stderr index 19a4a98bb1f49..ae4a32bca38ee 100644 --- a/tests/ui/borrowck/issue-45983.stderr +++ b/tests/ui/borrowck/issue-45983.stderr @@ -6,7 +6,7 @@ LL | let mut x = None; LL | give_any(|y| x = Some(y)); | - ^^^^^^^^^^^ `y` escapes the closure body here | | - | `y` is a reference that is only valid in the closure body + | `y` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-7573.rs b/tests/ui/borrowck/issue-7573.rs index f94cd75ab6e2e..e6c11ab8675b9 100644 --- a/tests/ui/borrowck/issue-7573.rs +++ b/tests/ui/borrowck/issue-7573.rs @@ -13,7 +13,7 @@ pub fn remove_package_from_database() { let mut lines_to_use: Vec<&CrateId> = Vec::new(); //~^ NOTE `lines_to_use` declared here, outside of the closure body let push_id = |installed_id: &CrateId| { - //~^ NOTE `installed_id` is a reference that is only valid in the closure body + //~^ NOTE `installed_id` is only valid in the closure body lines_to_use.push(installed_id); //~^ ERROR borrowed data escapes outside of closure //~| NOTE `installed_id` escapes the closure body here diff --git a/tests/ui/borrowck/issue-7573.stderr b/tests/ui/borrowck/issue-7573.stderr index d0121f4ec174f..927cebe620b88 100644 --- a/tests/ui/borrowck/issue-7573.stderr +++ b/tests/ui/borrowck/issue-7573.stderr @@ -5,7 +5,7 @@ LL | let mut lines_to_use: Vec<&CrateId> = Vec::new(); | ---------------- `lines_to_use` declared here, outside of the closure body LL | LL | let push_id = |installed_id: &CrateId| { - | ------------ `installed_id` is a reference that is only valid in the closure body + | ------------ `installed_id` is only valid in the closure body LL | LL | lines_to_use.push(installed_id); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `installed_id` escapes the closure body here diff --git a/tests/ui/borrowck/regions-escape-bound-fn-2.stderr b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr index 9c070de445710..893dffe0601d0 100644 --- a/tests/ui/borrowck/regions-escape-bound-fn-2.stderr +++ b/tests/ui/borrowck/regions-escape-bound-fn-2.stderr @@ -6,7 +6,7 @@ LL | let mut x = None; LL | with_int(|y| x = Some(y)); | - ^^^^^^^^^^^ `y` escapes the closure body here | | - | `y` is a reference that is only valid in the closure body + | `y` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/regions-escape-bound-fn.stderr b/tests/ui/borrowck/regions-escape-bound-fn.stderr index 868ba9c89be2f..92006eea3d9ad 100644 --- a/tests/ui/borrowck/regions-escape-bound-fn.stderr +++ b/tests/ui/borrowck/regions-escape-bound-fn.stderr @@ -6,7 +6,7 @@ LL | let mut x: Option<&isize> = None; LL | with_int(|y| x = Some(y)); | - ^^^^^^^^^^^ `y` escapes the closure body here | | - | `y` is a reference that is only valid in the closure body + | `y` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/regions-escape-unboxed-closure.stderr b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr index c861f772be0d3..6efc75bf1d4bb 100644 --- a/tests/ui/borrowck/regions-escape-unboxed-closure.stderr +++ b/tests/ui/borrowck/regions-escape-unboxed-closure.stderr @@ -6,7 +6,7 @@ LL | let mut x: Option<&isize> = None; LL | with_int(&mut |y| x = Some(y)); | - ^^^^^^^^^^^ `y` escapes the closure body here | | - | `y` is a reference that is only valid in the closure body + | `y` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr index fadb26ace969f..a3cde891b7cac 100644 --- a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr +++ b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn foo<'a>( | -- lifetime `'a` defined here LL | used_arg: &'a u8, - | -------- `used_arg` is a reference that is only valid in the function body + | -------- `used_arg` is only valid in the function body ... LL | consume(c); | ^^^^^^^^^^ diff --git a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr index 74a92f459aa62..92a08d0a58d74 100644 --- a/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr +++ b/tests/ui/cast/ptr-to-trait-obj-different-regions-misc.stderr @@ -231,7 +231,7 @@ LL | fn extend_to_static<'a>(ptr: *const dyn Trait<'a>) { | -- --- | | | | | `ptr` declared here, outside of the function body - | | `ptr` is a reference that is only valid in the function body + | | `ptr` is only valid in the function body | lifetime `'a` defined here LL | require_static(ptr as _) | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr index 798c3bc815696..654ca665ae09c 100644 --- a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr +++ b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn foo(x: &()) { | - - let's call the lifetime of this reference `'1` | | - | `x` is a reference that is only valid in the function body + | `x` is only valid in the function body LL | / bar(|| { LL | | LL | | diff --git a/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr b/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr index 0d97fa7e23014..d8cc760f44e7e 100644 --- a/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr +++ b/tests/ui/closures/closure-expected-type/expect-region-supply-region.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of closure LL | let mut f: Option<&u32> = None; | ----- `f` declared here, outside of the closure body LL | closure_expecting_bound(|x| { - | - `x` is a reference that is only valid in the closure body + | - `x` is only valid in the closure body LL | f = Some(x); | ^^^^^^^^^^^ `x` escapes the closure body here @@ -14,7 +14,7 @@ error[E0521]: borrowed data escapes outside of closure LL | let mut f: Option<&u32> = None; | ----- `f` declared here, outside of the closure body LL | closure_expecting_bound(|x: &u32| { - | - `x` is a reference that is only valid in the closure body + | - `x` is only valid in the closure body LL | f = Some(x); | ^^^^^^^^^^^ `x` escapes the closure body here diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr index 92192d9a55721..9f6aab8d97ba7 100644 --- a/tests/ui/coroutine/resume-arg-outlives-2.stderr +++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/resume-arg-outlives-2.rs:21:5 | LL | fn demo<'not_static>(s: &'not_static str) -> thread::JoinHandle<()> { - | ----------- - `s` is a reference that is only valid in the function body + | ----------- - `s` is only valid in the function body | | | lifetime `'not_static` defined here ... diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr index 1a397f6cdb21a..2c827725bd4cc 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-2.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn fails(iter: &mut I, f: F) -> bool | ---- - let's call the lifetime of this reference `'1` | | - | `iter` is a reference that is only valid in the function body + | `iter` is only valid in the function body ... LL | let _next = iter2.next(); | ^^^^^^^^^^^^ diff --git a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr index aaafcb3b7afb4..3c147130925ca 100644 --- a/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr +++ b/tests/ui/generic-associated-types/bugs/hrtb-implied-3.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn fails(iter: &str) { | ---- - let's call the lifetime of this reference `'1` | | - | `iter` is a reference that is only valid in the function body + | `iter` is only valid in the function body LL | trivial_bound(iter); | ^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr index 2ef35a377e2fc..416e5bedf1a24 100644 --- a/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr +++ b/tests/ui/impl-header-lifetime-elision/dyn-trait.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/dyn-trait.rs:24:5 | LL | fn with_dyn_debug_static<'a>(x: Box) { - | -- - `x` is a reference that is only valid in the function body + | -- - `x` is only valid in the function body | | | lifetime `'a` defined here LL | static_val(x); diff --git a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr index 4df2e906e222f..6fbc14a1cf4f2 100644 --- a/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr +++ b/tests/ui/lifetimes/issue-90600-expected-return-static-indirect.stderr @@ -18,7 +18,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn inner(mut foo: &[u8]) { | ------- - let's call the lifetime of this reference `'1` | | - | `foo` is a reference that is only valid in the function body + | `foo` is only valid in the function body ... LL | read_thing(read); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr b/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr index c51580f287eee..b28206044b772 100644 --- a/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr +++ b/tests/ui/lifetimes/lifetime-bound-will-change-warning.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:34:5 | LL | fn test2<'a>(x: &'a Box) { - | -- - `x` is a reference that is only valid in the function body + | -- - `x` is only valid in the function body | | | lifetime `'a` defined here LL | // but ref_obj will not, so warn. @@ -16,7 +16,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/lifetime-bound-will-change-warning.rs:40:5 | LL | fn test2cc<'a>(x: &'a Box) { - | -- - `x` is a reference that is only valid in the function body + | -- - `x` is only valid in the function body | | | lifetime `'a` defined here LL | // same as test2, but cross crate diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 62e872639671b..ab52f3d3ee43e 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -45,7 +45,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/closure-arg-type-mismatch.rs:10:5 | LL | fn _test<'a>(f: fn(*mut &'a u32)) { - | -- - `f` is a reference that is only valid in the function body + | -- - `f` is only valid in the function body | | | lifetime `'a` defined here LL | baz(f); diff --git a/tests/ui/nll/check-normalized-sig-for-wf.current.stderr b/tests/ui/nll/check-normalized-sig-for-wf.current.stderr index b25ae72f7fb9a..bbfdf9f8f3336 100644 --- a/tests/ui/nll/check-normalized-sig-for-wf.current.stderr +++ b/tests/ui/nll/check-normalized-sig-for-wf.current.stderr @@ -19,7 +19,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn extend(input: &T) -> &'static T { | ----- - let's call the lifetime of this reference `'1` | | - | `input` is a reference that is only valid in the function body + | `input` is only valid in the function body ... LL | n(input).0 | ^^^^^^^^ @@ -31,7 +31,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/check-normalized-sig-for-wf.rs:27:5 | LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { - | -- ----- `input` is a reference that is only valid in the function body + | -- ----- `input` is only valid in the function body | | | lifetime `'a` defined here ... diff --git a/tests/ui/nll/check-normalized-sig-for-wf.next.stderr b/tests/ui/nll/check-normalized-sig-for-wf.next.stderr index b25ae72f7fb9a..bbfdf9f8f3336 100644 --- a/tests/ui/nll/check-normalized-sig-for-wf.next.stderr +++ b/tests/ui/nll/check-normalized-sig-for-wf.next.stderr @@ -19,7 +19,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn extend(input: &T) -> &'static T { | ----- - let's call the lifetime of this reference `'1` | | - | `input` is a reference that is only valid in the function body + | `input` is only valid in the function body ... LL | n(input).0 | ^^^^^^^^ @@ -31,7 +31,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/check-normalized-sig-for-wf.rs:27:5 | LL | fn extend_mut<'a, T>(input: &'a mut T) -> &'static mut T { - | -- ----- `input` is a reference that is only valid in the function body + | -- ----- `input` is only valid in the function body | | | lifetime `'a` defined here ... diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr index f7cbc5b0f68f7..2fe03bff19884 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-comparing-against-free.stderr @@ -23,7 +23,7 @@ error[E0521]: borrowed data escapes outside of closure --> $DIR/propagate-approximated-shorter-to-static-comparing-against-free.rs:22:9 | LL | foo(cell, |cell_a, cell_x| { - | ------ ------ `cell_x` is a reference that is only valid in the closure body + | ------ ------ `cell_x` is only valid in the closure body | | | `cell_a` declared here, outside of the closure body LL | cell_a.set(cell_x.get()); // forces 'x: 'a, error in closure diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr index 9e9eae985973a..0a3d22873d0fb 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-no-bound.stderr @@ -31,7 +31,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-no-bound.rs:34:9 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is only valid in the function body | | | lifetime `'a` defined here ... diff --git a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr index 303fcd4cdfcf3..3035b841d5c60 100644 --- a/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr +++ b/tests/ui/nll/closure-requirements/propagate-approximated-shorter-to-static-wrong-bound.stderr @@ -32,7 +32,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/propagate-approximated-shorter-to-static-wrong-bound.rs:37:9 | LL | fn supply<'a, 'b>(cell_a: Cell<&'a u32>, cell_b: Cell<&'b u32>) { - | -- ------ `cell_a` is a reference that is only valid in the function body + | -- ------ `cell_a` is only valid in the function body | | | lifetime `'a` defined here ... diff --git a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr index 03a5590661422..cc549c34479ca 100644 --- a/tests/ui/nll/issue-54779-anon-static-lifetime.stderr +++ b/tests/ui/nll/issue-54779-anon-static-lifetime.stderr @@ -4,7 +4,7 @@ error[E0521]: borrowed data escapes outside of method LL | cx: &dyn DebugContext, | -- - let's call the lifetime of this reference `'1` | | - | `cx` is a reference that is only valid in the method body + | `cx` is only valid in the method body ... LL | bar.debug_with(cx); | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/nll/user-annotations/closure-substs.stderr b/tests/ui/nll/user-annotations/closure-substs.stderr index 1e8de4ba90541..ce37f205f0642 100644 --- a/tests/ui/nll/user-annotations/closure-substs.stderr +++ b/tests/ui/nll/user-annotations/closure-substs.stderr @@ -30,7 +30,7 @@ error[E0521]: borrowed data escapes outside of closure LL | |x: &i32, b: fn(&'static i32)| { | - - let's call the lifetime of this reference `'1` | | - | `x` is a reference that is only valid in the closure body + | `x` is only valid in the closure body LL | b(x); | ^^^^ | | diff --git a/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr index a1ef0243e3a87..877c578fbd3b7 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-mybox.stderr @@ -15,7 +15,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/object-lifetime-default-mybox.rs:32:5 | LL | fn load2<'a>(ss: &MyBox) -> MyBox { - | -- -- `ss` is a reference that is only valid in the function body + | -- -- `ss` is only valid in the function body | | | lifetime `'a` defined here LL | load0(ss) diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 113c84c656287..472d46ef93644 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -7,7 +7,7 @@ LL | let f = |x: &dyn TT| x.func(); | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` - | `x` is a reference that is only valid in the closure body + | `x` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 113c84c656287..472d46ef93644 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -7,7 +7,7 @@ LL | let f = |x: &dyn TT| x.func(); | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` - | `x` is a reference that is only valid in the closure body + | `x` is only valid in the closure body error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-nested-fns.stderr b/tests/ui/regions/regions-nested-fns.stderr index a911ecf51dc89..42c59fc38a2c7 100644 --- a/tests/ui/regions/regions-nested-fns.stderr +++ b/tests/ui/regions/regions-nested-fns.stderr @@ -37,7 +37,7 @@ LL | let mut ay = &y; | ------ `ay` declared here, outside of the closure body ... LL | ignore:: FnMut(&'z isize)>>(Box::new(|z| { - | - `z` is a reference that is only valid in the closure body + | - `z` is only valid in the closure body ... LL | ay = z; | ^^^^^^ `z` escapes the closure body here diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr index 48aa8f323291d..df31a17ecf113 100644 --- a/tests/ui/regions/regions-static-bound.stderr +++ b/tests/ui/regions/regions-static-bound.stderr @@ -55,7 +55,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn error(u: &(), v: &()) { | - - let's call the lifetime of this reference `'1` | | - | `u` is a reference that is only valid in the function body + | `u` is only valid in the function body LL | static_id(&u); | ^^^^^^^^^^^^^ | | @@ -68,7 +68,7 @@ error[E0521]: borrowed data escapes outside of function LL | fn error(u: &(), v: &()) { | - - let's call the lifetime of this reference `'2` | | - | `v` is a reference that is only valid in the function body + | `v` is only valid in the function body ... LL | static_id_indirect(&v); | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr index 505765d2b41f6..be6fbbaa573f4 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.stderr @@ -29,7 +29,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound-needing-more-suggestions.rs:66:9 | LL | fn use_it<'a>(val: Box + 'a>) -> &'a () { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self() diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 6effaf61099ec..8ef1b052384c6 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:21:9 | LL | fn use_it<'a, T>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self::() @@ -27,7 +27,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:72:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self() @@ -52,7 +52,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:92:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self() @@ -78,7 +78,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:112:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | MyTrait::use_self(val) @@ -104,7 +104,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:38:9 | LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> &'a () { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self() @@ -129,7 +129,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:56:9 | LL | fn use_it<'a>(val: &'a Box) -> &'a () { - | -- --- `val` is a reference that is only valid in the function body + | -- --- `val` is only valid in the function body | | | lifetime `'a` defined here LL | val.use_self() diff --git a/tests/ui/traits/object/issue-44454-2.stderr b/tests/ui/traits/object/issue-44454-2.stderr index 366b519aeb579..280eeb99e0ba8 100644 --- a/tests/ui/traits/object/issue-44454-2.stderr +++ b/tests/ui/traits/object/issue-44454-2.stderr @@ -2,7 +2,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/issue-44454-2.rs:16:5 | LL | fn extend_lt<'a>(x: &'a str) -> Box + 'static> { - | -- - `x` is a reference that is only valid in the function body + | -- - `x` is only valid in the function body | | | lifetime `'a` defined here LL | type DynTrait = dyn for<'a> Trait<&'a str, Assoc = &'a str>; diff --git a/tests/ui/transmutability/references/reject_lifetime_extension.stderr b/tests/ui/transmutability/references/reject_lifetime_extension.stderr index b97029841453f..392aec03b3d2c 100644 --- a/tests/ui/transmutability/references/reject_lifetime_extension.stderr +++ b/tests/ui/transmutability/references/reject_lifetime_extension.stderr @@ -58,7 +58,7 @@ error[E0521]: borrowed data escapes outside of function --> $DIR/reject_lifetime_extension.rs:80:18 | LL | fn call_extend_hrtb<'a>(src: &'a u8) -> &'static u8 { - | -- --- `src` is a reference that is only valid in the function body + | -- --- `src` is only valid in the function body | | | lifetime `'a` defined here LL | unsafe { extend_hrtb(src) } From 1f6a2620eec957dd959afdeb90b61439b3b7da98 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Sat, 19 Sep 2026 15:45:43 +0200 Subject: [PATCH 0399/1309] Don't claim that escaping value is a reference --- tests/ui/crashes/ice-6256.stderr | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/crashes/ice-6256.stderr b/tests/ui/crashes/ice-6256.stderr index 922772a6147bc..4cb83e24e7a05 100644 --- a/tests/ui/crashes/ice-6256.stderr +++ b/tests/ui/crashes/ice-6256.stderr @@ -7,7 +7,7 @@ LL | let f = |x: &dyn TT| x.func(); | | | `x` escapes the closure body here | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` - | `x` is a reference that is only valid in the closure body + | `x` is only valid in the closure body error: aborting due to 1 previous error From bc5fd06c341bb75e473de55455d0b09d6268e234 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 16:25:47 +0200 Subject: [PATCH 0400/1309] Dir: fix fallback impl for remove_dir --- library/std/src/sys/fs/common.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 17b98a4506544..9ce65ad403f4b 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -102,7 +102,7 @@ impl Dir { } pub fn remove_dir(&self, path: &Path) -> io::Result<()> { - remove_dir(path) + remove_dir(self.path.join(path)) } } From 6524ec5bde1bc006773ecceccf80167e9ebd9092 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 12 Sep 2026 23:01:57 +0200 Subject: [PATCH 0401/1309] Remove incorrect parse error recovery code that mistakes `as` casts for the long removed type ascription --- compiler/rustc_parse/src/parser/expr.rs | 32 ------------------------- 1 file changed, 32 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 58e98a64b5e41..021ed221f057c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -576,38 +576,6 @@ impl<'a> Parser<'a> { // `usize < y` as a type with generic arguments. let parser_snapshot_after_type = mem::replace(self, parser_snapshot_before_type); - // Check for typo of `'a: loop { break 'a }` with a missing `'`. - match (&lhs.kind, &self.token.kind) { - ( - // `foo: ` - ExprKind::Path(None, ast::Path { segments, .. }), - token::Ident(kw::For | kw::Loop | kw::While, IdentIsRaw::No), - ) if let [segment] = segments.as_slice() => { - let snapshot = self.create_snapshot_for_diagnostic(); - let label = Label { - ident: Ident::from_str_and_span( - &format!("'{}", segment.ident), - segment.ident.span, - ), - }; - match self.parse_expr_labeled(label, false) { - Ok(expr) => { - type_err.cancel(); - self.dcx().emit_err(crate::diagnostics::MalformedLoopLabel { - span: label.ident.span, - suggestion: label.ident.span.shrink_to_lo(), - }); - return Ok(expr); - } - Err(err) => { - err.cancel(); - self.restore_snapshot(snapshot); - } - } - } - _ => {} - } - match self.parse_path(PathStyle::Expr) { Ok(path) => { let span_after_type = parser_snapshot_after_type.token.span; From c095a72277a472c874db27add811ca9b7e8ad161 Mon Sep 17 00:00:00 2001 From: increasing Date: Fri, 18 Sep 2026 12:24:24 +0200 Subject: [PATCH 0402/1309] add test --- .../issues/true-false-type-issue-162947.rs | 16 +++++++ .../true-false-type-issue-162947.stderr | 46 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 tests/ui/parser/issues/true-false-type-issue-162947.rs create mode 100644 tests/ui/parser/issues/true-false-type-issue-162947.stderr diff --git a/tests/ui/parser/issues/true-false-type-issue-162947.rs b/tests/ui/parser/issues/true-false-type-issue-162947.rs new file mode 100644 index 0000000000000..ba6c9a13a36fa --- /dev/null +++ b/tests/ui/parser/issues/true-false-type-issue-162947.rs @@ -0,0 +1,16 @@ +struct A; + +impl A { + fn _a() -> true { //~ ERROR: expected type, found keyword `true` + false + } + fn b(&self) {} +} + +fn main() { + let a = A; + a.b(); //~ ERROR E0599 + + let _b: true = true; //~ ERROR: expected type, found keyword `true` + //~^ ERROR E0070 +} diff --git a/tests/ui/parser/issues/true-false-type-issue-162947.stderr b/tests/ui/parser/issues/true-false-type-issue-162947.stderr new file mode 100644 index 0000000000000..f471eb2739d81 --- /dev/null +++ b/tests/ui/parser/issues/true-false-type-issue-162947.stderr @@ -0,0 +1,46 @@ +error: expected type, found keyword `true` + --> $DIR/true-false-type-issue-162947.rs:4:15 + | +LL | impl A { + | - while parsing this item list starting here +LL | fn a() -> true { + | ^^^^ expected type +... +LL | } + | - the item list ends here + +error: expected type, found keyword `true` + --> $DIR/true-false-type-issue-162947.rs:14:12 + | +LL | let b: true = true; + | - ^^^^ expected type + | | + | while parsing the type for `b` + | +help: use `=` if you meant to assign + | +LL - let b: true = true; +LL + let b = true = true; + | + +error[E0599]: no method named `b` found for struct `A` in the current scope + --> $DIR/true-false-type-issue-162947.rs:12:7 + | +LL | struct A; + | -------- method `b` not found for this struct +... +LL | a.b(); + | ^ method not found in `A` + +error[E0070]: invalid left-hand side of assignment + --> $DIR/true-false-type-issue-162947.rs:14:17 + | +LL | let b: true = true; + | ---- ^ + | | + | cannot assign to this expression + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0070, E0599. +For more information about an error, try `rustc --explain E0070`. From fe96227afdf72caf064b14b5e3a1f2e9f6cf8c85 Mon Sep 17 00:00:00 2001 From: increasing Date: Fri, 18 Sep 2026 18:09:30 +0200 Subject: [PATCH 0403/1309] recover true and false as bool type --- compiler/rustc_parse/src/parser/ty.rs | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 88c07c6e2778c..42fb9121076f4 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -3,8 +3,8 @@ use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy, GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, - Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, - TyKind, UnsafeBinderTy, + Path, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, + Ty, TyKind, UnsafeBinderTy, }; use rustc_errors::{Applicability, Diag, E0516, PResult}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; @@ -406,7 +406,23 @@ impl<'a> Parser<'a> { let msg = format!("expected type, found {}", super::token_descr(&self.token)); let mut err = self.dcx().struct_span_err(lo, msg); err.span_label(lo, "expected type"); - return Err(err); + if self.may_recover() + && (self.eat_keyword_noexpect(kw::True) || self.eat_keyword_noexpect(kw::False)) + { + err.span_suggestion( + self.prev_token.span, + "the type is called", + "bool", + Applicability::MachineApplicable, + ); + err.emit(); + TyKind::Path( + None, + Path::from_ident(Ident { span: self.prev_token.span, name: sym::bool }), + ) + } else { + return Err(err); + } }; let span = lo.to(self.prev_token.span); From 8026b7beef9fb1b1e8f83efc8cdd7b544bff66d9 Mon Sep 17 00:00:00 2001 From: increasing Date: Fri, 18 Sep 2026 19:35:29 +0200 Subject: [PATCH 0404/1309] bless tests --- .../issues/true-false-type-issue-162947.fixed | 17 ++++++ .../issues/true-false-type-issue-162947.rs | 5 +- .../true-false-type-issue-162947.stderr | 52 +++++-------------- 3 files changed, 33 insertions(+), 41 deletions(-) create mode 100644 tests/ui/parser/issues/true-false-type-issue-162947.fixed diff --git a/tests/ui/parser/issues/true-false-type-issue-162947.fixed b/tests/ui/parser/issues/true-false-type-issue-162947.fixed new file mode 100644 index 0000000000000..8d3037ea0f458 --- /dev/null +++ b/tests/ui/parser/issues/true-false-type-issue-162947.fixed @@ -0,0 +1,17 @@ +//@ run-rustfix + +struct A; + +impl A { + fn _a() -> bool { //~ ERROR: expected type, found keyword `true` + false + } + fn b(&self) {} +} + +fn main() { + let a = A; + a.b(); + + let _b: bool = true; //~ ERROR: expected type, found keyword `true` +} diff --git a/tests/ui/parser/issues/true-false-type-issue-162947.rs b/tests/ui/parser/issues/true-false-type-issue-162947.rs index ba6c9a13a36fa..1c3a35b3f16f1 100644 --- a/tests/ui/parser/issues/true-false-type-issue-162947.rs +++ b/tests/ui/parser/issues/true-false-type-issue-162947.rs @@ -1,3 +1,5 @@ +//@ run-rustfix + struct A; impl A { @@ -9,8 +11,7 @@ impl A { fn main() { let a = A; - a.b(); //~ ERROR E0599 + a.b(); let _b: true = true; //~ ERROR: expected type, found keyword `true` - //~^ ERROR E0070 } diff --git a/tests/ui/parser/issues/true-false-type-issue-162947.stderr b/tests/ui/parser/issues/true-false-type-issue-162947.stderr index f471eb2739d81..558587d8ebe88 100644 --- a/tests/ui/parser/issues/true-false-type-issue-162947.stderr +++ b/tests/ui/parser/issues/true-false-type-issue-162947.stderr @@ -1,46 +1,20 @@ error: expected type, found keyword `true` - --> $DIR/true-false-type-issue-162947.rs:4:15 + --> $DIR/true-false-type-issue-162947.rs:6:16 | -LL | impl A { - | - while parsing this item list starting here -LL | fn a() -> true { - | ^^^^ expected type -... -LL | } - | - the item list ends here +LL | fn _a() -> true { + | ^^^^ + | | + | expected type + | help: the type is called: `bool` error: expected type, found keyword `true` - --> $DIR/true-false-type-issue-162947.rs:14:12 + --> $DIR/true-false-type-issue-162947.rs:16:13 | -LL | let b: true = true; - | - ^^^^ expected type - | | - | while parsing the type for `b` - | -help: use `=` if you meant to assign - | -LL - let b: true = true; -LL + let b = true = true; - | - -error[E0599]: no method named `b` found for struct `A` in the current scope - --> $DIR/true-false-type-issue-162947.rs:12:7 - | -LL | struct A; - | -------- method `b` not found for this struct -... -LL | a.b(); - | ^ method not found in `A` - -error[E0070]: invalid left-hand side of assignment - --> $DIR/true-false-type-issue-162947.rs:14:17 - | -LL | let b: true = true; - | ---- ^ - | | - | cannot assign to this expression +LL | let _b: true = true; + | ^^^^ + | | + | expected type + | help: the type is called: `bool` -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors -Some errors have detailed explanations: E0070, E0599. -For more information about an error, try `rustc --explain E0070`. From e224f8f81ef41b3e7aa64d9a309365768408af36 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 12 Sep 2026 23:01:35 +0200 Subject: [PATCH 0405/1309] Further simplify `parse_assoc_op_cast` --- compiler/rustc_parse/src/parser/expr.rs | 79 ++++++++++--------------- 1 file changed, 32 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 021ed221f057c..c8dfebcedfe87 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -210,9 +210,7 @@ impl<'a> Parser<'a> { let (rhs, span) = finish_parsing_bin_op(self)?; self.mk_expr(span, ExprKind::Assign(lhs, rhs, op.span)) } - AssocOp::Cast => { - self.parse_assoc_op_cast(lhs, lhs_span, op.span, ExprKind::Cast)? - } + AssocOp::Cast => self.parse_assoc_op_cast(lhs, lhs_span, op.span)?, AssocOp::Range(limits) => self.parse_expr_range(min_prec, lhs, limits, op.span)?, }; @@ -555,17 +553,17 @@ impl<'a> Parser<'a> { lhs: Box, lhs_span: Span, op_span: Span, - expr_kind: fn(Box, Box) -> ExprKind, ) -> PResult<'a, Box> { - let mk_expr = |this: &mut Self, lhs: Box, rhs: Box| { - this.mk_expr(this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span), expr_kind(lhs, rhs)) + let mk_expr = |this: &mut Self, rhs: Box| { + let span = this.mk_expr_sp(&lhs, lhs_span, op_span, rhs.span); + this.mk_expr(span, ExprKind::Cast(lhs, rhs)) }; // Save the state of the parser before parsing type normally, in case there is a // LessThan comparison after this cast. let parser_snapshot_before_type = self.clone(); let cast_expr = match self.parse_as_cast_ty() { - Ok(rhs) => mk_expr(self, lhs, rhs), + Ok(rhs) => mk_expr(self, rhs), Err(type_err) => { if !self.may_recover() { return Err(type_err); @@ -579,11 +577,8 @@ impl<'a> Parser<'a> { match self.parse_path(PathStyle::Expr) { Ok(path) => { let span_after_type = parser_snapshot_after_type.token.span; - let expr = mk_expr( - self, - lhs, - self.mk_ty(path.span, TyKind::Path(None, path.clone())), - ); + let expr = + mk_expr(self, self.mk_ty(path.span, TyKind::Path(None, path.clone()))); let args_span = self.look_ahead(1, |t| t.span).to(span_after_type); match self.token.kind { @@ -642,48 +637,38 @@ impl<'a> Parser<'a> { // written `((&x) as T)[0]`. let span = cast_expr.span; - let with_postfix = self.parse_expr_dot_or_call_with(AttrVec::new(), cast_expr, span)?; // Check if an illegal postfix operator has been added after the cast. // If the resulting expression is not a cast, it is an illegal postfix operator. if !matches!(with_postfix.kind, ExprKind::Cast(_, _)) { - let msg = format!( - "cast cannot be followed by {}", - match with_postfix.kind { - ExprKind::Index(..) => "indexing", - ExprKind::Try(_) => "`?`", - ExprKind::Field(_, _) => "a field access", - ExprKind::MethodCall(_) => "a method call", - ExprKind::Call(_, _) => "a function call", - ExprKind::Await(_, _) => "`.await`", - ExprKind::Use(_, _) => "`.use`", - ExprKind::Yield(YieldKind::Postfix(_)) => "`.yield`", - ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match", - ExprKind::Err(_) => return Ok(with_postfix), - _ => unreachable!( - "did not expect {:?} as an illegal postfix operator following cast", - with_postfix.kind - ), - } - ); - let mut err = self.dcx().struct_span_err(span, msg); - - let suggest_parens = |err: &mut Diag<'_>| { - let suggestions = vec![ - (span.shrink_to_lo(), "(".to_string()), - (span.shrink_to_hi(), ")".to_string()), - ]; - err.multipart_suggestion( + let kind = match with_postfix.kind { + ExprKind::Index(..) => "indexing", + ExprKind::Try(_) => "`?`", + ExprKind::Field(_, _) => "a field access", + ExprKind::MethodCall(_) => "a method call", + ExprKind::Call(_, _) => "a function call", + ExprKind::Await(_, _) => "`.await`", + ExprKind::Use(_, _) => "`.use`", + ExprKind::Yield(YieldKind::Postfix(_)) => "`.yield`", + ExprKind::Match(_, _, MatchKind::Postfix) => "a postfix match", + ExprKind::Err(_) => return Ok(with_postfix), + _ => unreachable!( + "did not expect {:?} as an illegal postfix operator following cast", + with_postfix.kind + ), + }; + self.dcx() + .struct_span_err(span, format!("cast cannot be followed by {kind}")) + .with_multipart_suggestion( "try surrounding the expression in parentheses", - suggestions, + vec![ + (span.shrink_to_lo(), "(".to_string()), + (span.shrink_to_hi(), ")".to_string()), + ], Applicability::MachineApplicable, - ); - }; - - suggest_parens(&mut err); - - err.emit(); + ) + .emit(); }; Ok(with_postfix) } From c973b5051072d339c21a3e9493ff0fabac8f8f97 Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Fri, 18 Sep 2026 23:47:48 -0400 Subject: [PATCH 0406/1309] Avoid generating overlapping assignments in DSE --- .../src/dead_store_elimination.rs | 7 +++++ ...eadStoreElimination-final.panic-abort.diff | 2 +- ...adStoreElimination-final.panic-unwind.diff | 2 +- ...eadStoreElimination-final.panic-abort.diff | 16 ++++++++++ ...adStoreElimination-final.panic-unwind.diff | 16 ++++++++++ .../dead-store-elimination/call_arg_copy.rs | 29 ++++++++++++++----- 6 files changed, 62 insertions(+), 10 deletions(-) create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-abort.diff create mode 100644 tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-unwind.diff diff --git a/compiler/rustc_mir_transform/src/dead_store_elimination.rs b/compiler/rustc_mir_transform/src/dead_store_elimination.rs index 9b0e2a0663eca..7c41217f402ff 100644 --- a/compiler/rustc_mir_transform/src/dead_store_elimination.rs +++ b/compiler/rustc_mir_transform/src/dead_store_elimination.rs @@ -63,6 +63,13 @@ fn eliminate<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> bool { loc, ); + // The logic in LivenessTransferFunction isn't quite what we need; it ignores call + // destinations that are just locals because they are killed by the call, which makes + // it eligible to be moved-from in the argument list. That's backwards. + if !destination.is_indirect() { + state.insert(destination.local); + } + for (index, arg) in args.iter().map(|a| &a.node).enumerate().rev() { if let Operand::Copy(place) = *arg && !place.is_indirect() diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-abort.diff index 012dd7d88a5f0..2c4e7ae552844 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-abort.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-abort.diff @@ -5,7 +5,7 @@ let mut _0: (); bb0: { - _1[_2] = passthrough_usize(copy _2) -> [return: bb1, unwind unreachable]; + _1[_2] = identity::(copy _2) -> [return: bb1, unwind unreachable]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-unwind.diff index fcd0ae43e2897..86f9b93130d72 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-unwind.diff +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.move_index.DeadStoreElimination-final.panic-unwind.diff @@ -5,7 +5,7 @@ let mut _0: (); bb0: { - _1[_2] = passthrough_usize(copy _2) -> [return: bb1, unwind continue]; + _1[_2] = identity::(copy _2) -> [return: bb1, unwind continue]; } bb1: { diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-abort.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-abort.diff new file mode 100644 index 0000000000000..d4d49d0fb79e7 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-abort.diff @@ -0,0 +1,16 @@ +- // MIR for `ret_is_arg` before DeadStoreElimination-final ++ // MIR for `ret_is_arg` after DeadStoreElimination-final + + fn ret_is_arg(_1: [u64; 5]) -> [u64; 5] { + let mut _0: [u64; 5]; + + bb0: { + _1 = identity::<[u64; 5]>(copy _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _0 = copy _1; + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-unwind.diff b/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-unwind.diff new file mode 100644 index 0000000000000..d4d49d0fb79e7 --- /dev/null +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.ret_is_arg.DeadStoreElimination-final.panic-unwind.diff @@ -0,0 +1,16 @@ +- // MIR for `ret_is_arg` before DeadStoreElimination-final ++ // MIR for `ret_is_arg` after DeadStoreElimination-final + + fn ret_is_arg(_1: [u64; 5]) -> [u64; 5] { + let mut _0: [u64; 5]; + + bb0: { + _1 = identity::<[u64; 5]>(copy _1) -> [return: bb1, unwind unreachable]; + } + + bb1: { + _0 = copy _1; + return; + } + } + diff --git a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs index 00a9a49c2abb8..1a7f9a1494dbe 100644 --- a/tests/mir-opt/dead-store-elimination/call_arg_copy.rs +++ b/tests/mir-opt/dead-store-elimination/call_arg_copy.rs @@ -6,6 +6,7 @@ #![feature(custom_mir)] #![allow(internal_features)] +use std::convert::identity; use std::intrinsics::mir::*; #[inline(never)] @@ -40,22 +41,17 @@ fn move_packed(packed: Packed) { } } -#[inline(never)] -fn passthrough_usize(a: usize) -> usize { - a -} - // EMIT_MIR call_arg_copy.move_index.DeadStoreElimination-final.diff #[custom_mir(dialect = "analysis")] fn move_index(a: [usize; 10], b: usize) { // CHECK-LABEL: fn move_index( - // CHECK: = passthrough_usize(copy _2) + // CHECK: = identity::(copy _2) mir! { { // The index is used again after the operand is evaluated to - // evaluate the destionation place, so the argument cannot be turned + // evaluate the destination place, so the argument cannot be turned // into a move. - Call(a[b] = passthrough_usize(b), ReturnTo(ret), UnwindContinue()) + Call(a[b] = identity(b), ReturnTo(ret), UnwindContinue()) } ret = { Return() @@ -63,8 +59,25 @@ fn move_index(a: [usize; 10], b: usize) { } } +// EMIT_MIR call_arg_copy.ret_is_arg.DeadStoreElimination-final.diff +#[custom_mir(dialect = "runtime")] +fn ret_is_arg(x: [u64; 5]) -> [u64; 5] { + // CHECK-LABEL: fn ret_is_arg(_1 + // CHECK: _1 = identity::<[u64; 5]>(copy _1) -> + mir! { + { + Call(x = identity(x), ReturnTo(bb1), UnwindUnreachable()) + } + bb1 = { + RET = x; + Return() + } + } +} + fn main() { move_simple(1); move_packed(Packed { x: 0, y: 1 }); move_index([0; _], 1); + ret_is_arg([0; 5]); } From 8a0a23db23e5d2c9055b980a0448e8a16562e9ac Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 13 Sep 2026 01:58:27 +0200 Subject: [PATCH 0407/1309] Trigger "C array" parse error recovery in far fewer cases Previously we would trigger on 1. `unsafe { 1, 2, 3 }` and suggest `[ { 1, 2, 3 ]` (sic!) 2. `'label: { 1, 2, 3 }` and suggest `[: { 1, 2, 3 ]` (sic!) 3. `X::<{ 1, 2, 3 }>` and suggest `X::<[ 1, 2, 3]>` (wrong) 4. `|| -> i32 { 1, 2, 3 }` and suggest `|| -> i32 [ 1, 2, 3 ]` (wrong) 5. `await { 1, 2, 3 }` and suggest `await [ 1, 2, 3 ]` (wrong) Moreover, stop looking for identifiers after the `{` as that case can no longer be reached anyway as `maybe_recover_bad_struct_literal_path` will always snatch it first. --- compiler/rustc_parse/src/parser/expr.rs | 42 ++-------------- .../src/parser/expr/diagnostics.rs | 34 ++++++++++++- .../issue-87830-try-brackets-for-arrays.rs | 32 +++++++++++-- ...issue-87830-try-brackets-for-arrays.stderr | 48 ++++++++++++++----- 4 files changed, 100 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 58e98a64b5e41..2adfefe2bcb04 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1401,6 +1401,9 @@ impl<'a> Parser<'a> { if let Some(expr) = this.maybe_recover_bad_struct_literal_path(false)? { return Ok(expr); } + if let Some(arr) = this.recover_from_c_array(lo) { + return Ok(arr); + } this.parse_expr_block(None, lo, BlockCheckMode::Default) } else if this.check(exp!(Or)) || this.check(exp!(OrOr)) { this.parse_expr_closure().map_err(|mut err| { @@ -2227,39 +2230,6 @@ impl<'a> Parser<'a> { } } - fn is_array_like_block(&mut self) -> bool { - self.token.kind == TokenKind::OpenBrace - && self - .look_ahead(1, |t| matches!(t.kind, TokenKind::Ident(..) | TokenKind::Literal(_))) - && self.look_ahead(2, |t| t == &token::Comma) - && self.look_ahead(3, |t| t.can_begin_expr()) - } - - /// Emits a suggestion if it looks like the user meant an array but - /// accidentally used braces, causing the code to be interpreted as a block - /// expression. - fn maybe_suggest_brackets_instead_of_braces(&mut self, lo: Span) -> Option> { - let mut snapshot = self.create_snapshot_for_diagnostic(); - match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { - Ok(arr) => { - let guar = self.dcx().emit_err(crate::diagnostics::ArrayBracketsInsteadOfBraces { - span: arr.span, - sub: crate::diagnostics::ArrayBracketsInsteadOfBracesSugg { - left: lo, - right: snapshot.prev_token.span, - }, - }); - - self.restore_snapshot(snapshot); - Some(self.mk_expr_err(arr.span, guar)) - } - Err(e) => { - e.cancel(); - None - } - } - } - fn suggest_missing_semicolon_before_array( &self, prev_span: Span, @@ -2309,12 +2279,6 @@ impl<'a> Parser<'a> { lo: Span, blk_mode: BlockCheckMode, ) -> PResult<'a, Box> { - if self.may_recover() && self.is_array_like_block() { - if let Some(arr) = self.maybe_suggest_brackets_instead_of_braces(lo) { - return Ok(arr); - } - } - if self.token.is_metavar_block() { self.dcx().emit_err(crate::diagnostics::InvalidBlockMacroSegment { span: self.token.span, diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index 707ae5d34bc75..6e56ea6c616fd 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -3,8 +3,8 @@ use rustc_ast::{BinOpKind, Expr, ExprKind, token}; use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{Span, Spanned, respan, sym}; -use crate::diagnostics; use crate::parser::Parser; +use crate::{diagnostics, exp}; impl<'a> Parser<'a> { /// Recover from alphabetic logic operators `and` and `or` as found in e.g., Python and PHP. @@ -216,6 +216,38 @@ impl<'a> Parser<'a> { } err } + + /// Recover from array expressions as found in C like `{0, 1, 2, 3}`. + pub(super) fn recover_from_c_array(&mut self, lo: Span) -> Option> { + if !self.may_recover() + || self.token.kind != token::OpenBrace + || self.look_ahead(1, |t| !matches!(t.kind, token::Literal(_))) + || self.look_ahead(2, |t| t != &token::Comma) + || self.look_ahead(3, |t| !t.can_begin_expr()) + { + return None; + } + + let mut snapshot = self.create_snapshot_for_diagnostic(); + match snapshot.parse_expr_array_or_repeat(exp!(CloseBrace)) { + Ok(arr) => { + let guar = self.dcx().emit_err(diagnostics::ArrayBracketsInsteadOfBraces { + span: arr.span, + sub: diagnostics::ArrayBracketsInsteadOfBracesSugg { + left: lo, + right: snapshot.prev_token.span, + }, + }); + + self.restore_snapshot(snapshot); + Some(self.mk_expr_err(arr.span, guar)) + } + Err(e) => { + e.cancel(); + None + } + } + } } #[derive(Copy, Clone)] diff --git a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs index 070ffaa1eff00..99d63929db484 100644 --- a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs +++ b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.rs @@ -1,18 +1,42 @@ +// Test that we can recover from very basic C arrays in the parser & provide a good diagnostic. + fn main() {} -const FOO: [u8; 3] = { +const INTS: [u8; 3] = { //~^ ERROR this is a block expression, not an array 1, 2, 3 }; -const BAR: [&str; 3] = {"one", "two", "three"}; +const STRS: [&str; 3] = {"one", "two", "three"}; //~^ ERROR this is a block expression, not an array -fn foo() { +fn expr_stmt() { {1, 2, 3}; //~^ ERROR this is a block expression, not an array } -fn bar() { +// Don't trigger here. +fn unsafe_block() { + unsafe { 1, 2, 3 } //~ ERROR expected one of +} + +// Don't trigger here. +fn labeled_block() { + 'label: { 1, 2, 3 } //~ ERROR expected one of +} + +// Don't trigger here, this is not a block expression, only a block. +fn fn_body_block() { 1, 2, 3 //~ ERROR expected one of } + +// Don't trigger here, this is not a block expression, only a block. +fn closure_body_block() { + || -> i32 { 1, 2, 3 }; //~ ERROR expected one of +} + +// Don't trigger here. +fn const_arg() { + struct Casket; + Casket::<{ 1, 2, 3 }>; //~ ERROR expected one of +} diff --git a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr index 58232e2307d8e..531d54a9e3f1e 100644 --- a/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr +++ b/tests/ui/did_you_mean/issue-87830-try-brackets-for-arrays.stderr @@ -1,8 +1,8 @@ error: this is a block expression, not an array - --> $DIR/issue-87830-try-brackets-for-arrays.rs:3:22 + --> $DIR/issue-87830-try-brackets-for-arrays.rs:5:23 | -LL | const FOO: [u8; 3] = { - | ______________________^ +LL | const INTS: [u8; 3] = { + | _______________________^ LL | | LL | | 1, 2, 3 LL | | }; @@ -10,26 +10,26 @@ LL | | }; | help: to make an array, use square brackets instead of curly braces | -LL ~ const FOO: [u8; 3] = [ +LL ~ const INTS: [u8; 3] = [ LL | LL | 1, 2, 3 LL ~ ]; | error: this is a block expression, not an array - --> $DIR/issue-87830-try-brackets-for-arrays.rs:8:24 + --> $DIR/issue-87830-try-brackets-for-arrays.rs:10:25 | -LL | const BAR: [&str; 3] = {"one", "two", "three"}; - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | const STRS: [&str; 3] = {"one", "two", "three"}; + | ^^^^^^^^^^^^^^^^^^^^^^^ | help: to make an array, use square brackets instead of curly braces | -LL - const BAR: [&str; 3] = {"one", "two", "three"}; -LL + const BAR: [&str; 3] = ["one", "two", "three"]; +LL - const STRS: [&str; 3] = {"one", "two", "three"}; +LL + const STRS: [&str; 3] = ["one", "two", "three"]; | error: this is a block expression, not an array - --> $DIR/issue-87830-try-brackets-for-arrays.rs:12:5 + --> $DIR/issue-87830-try-brackets-for-arrays.rs:14:5 | LL | {1, 2, 3}; | ^^^^^^^^^ @@ -41,10 +41,34 @@ LL + [1, 2, 3]; | error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` - --> $DIR/issue-87830-try-brackets-for-arrays.rs:17:6 + --> $DIR/issue-87830-try-brackets-for-arrays.rs:20:15 + | +LL | unsafe { 1, 2, 3 } + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:25:16 + | +LL | 'label: { 1, 2, 3 } + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:30:6 | LL | 1, 2, 3 | ^ expected one of `.`, `;`, `?`, `}`, or an operator -error: aborting due to 4 previous errors +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:35:18 + | +LL | || -> i32 { 1, 2, 3 }; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` + --> $DIR/issue-87830-try-brackets-for-arrays.rs:41:17 + | +LL | Casket::<{ 1, 2, 3 }>; + | ^ expected one of `.`, `;`, `?`, `}`, or an operator + +error: aborting due to 8 previous errors From 26be04bec67f222287eaa3706cfda26d078a02bb Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Sat, 19 Sep 2026 12:25:37 -0300 Subject: [PATCH 0408/1309] Preserve eager normalization failures Return failed projection obligations from deep normalization instead of retrying aliases through infallible fallback. Keep regular normalization recovery by rebuilding projection obligations from the original aliases. --- .../src/solve/normalize.rs | 64 ++++++++++++------- ...1.stderr => issue-111404-1.current.stderr} | 10 +-- .../issue-111404-1.next.stderr | 9 +++ .../issue-111404-1.rs | 15 +++-- ..._outlives_bounds_not_resolving_vars_ice.rs | 4 +- ...lives_bounds_not_resolving_vars_ice.stderr | 22 ++----- .../deeply-normalize-fallback-issue-160875.rs | 34 ++++++++++ ...ply-normalize-fallback-issue-160875.stderr | 16 +++++ 8 files changed, 119 insertions(+), 55 deletions(-) rename tests/ui/associated-inherent-types/{issue-111404-1.stderr => issue-111404-1.current.stderr} (88%) create mode 100644 tests/ui/associated-inherent-types/issue-111404-1.next.stderr create mode 100644 tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs create mode 100644 tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr diff --git a/compiler/rustc_trait_selection/src/solve/normalize.rs b/compiler/rustc_trait_selection/src/solve/normalize.rs index 9430b6c4b3307..ef9caca003ef2 100644 --- a/compiler/rustc_trait_selection/src/solve/normalize.rs +++ b/compiler/rustc_trait_selection/src/solve/normalize.rs @@ -2,7 +2,8 @@ use rustc_infer::infer::InferCtxt; use rustc_infer::infer::at::At; use rustc_infer::traits::solve::Goal; use rustc_infer::traits::{ - FromSolverError, Normalized, Obligation, PredicateObligations, TraitEngine, TraitErrors, + FromSolverError, Normalized, Obligation, PredicateObligation, PredicateObligations, + TraitEngine, TraitErrors, }; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::{ @@ -11,23 +12,32 @@ use rustc_middle::ty::{ }; use rustc_next_trait_solver::normalize::{NormalizationFolder, NormalizationWasAmbiguous}; use rustc_next_trait_solver::solve::SolverDelegateEvalExt; -use thin_vec::ThinVec; +use thin_vec::{ThinVec, thin_vec}; use super::{FulfillmentCtxt, NextSolverError}; use crate::solve::{Certainty, SolverDelegate}; use crate::traits::{BoundVarReplacer, ScrubbedTraitError}; -/// see `normalize_with_universes`. +/// Normalize a value, deferring ambiguity and errors to fulfillment. pub fn normalize<'tcx, T>(at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>) -> Normalized<'tcx, T> where T: TypeFoldable>, { - normalize_with_universes(at, value, vec![]) + match normalize_with_universes(at, value.clone(), vec![]) { + Ok(normalized) => normalized, + Err(_) => { + let mut replacer = + ReplaceAliasWithInfer { at, obligations: Default::default(), universes: vec![] }; + let value = at.infcx.deeply_resolve_ignoring_regions(value.skip_normalization()); + let value = value.fold_with(&mut replacer); + Normalized { value, obligations: replacer.obligations } + } + } } /// Like `deeply_normalize`, but we handle ambiguity and inference variables in this routine. /// The behavior should be same as the old solver. -/// For error, we return an infer var plus the failed obligation. +/// On error, return the failed obligation. /// For ambiguity, we have two cases: /// - has_escaping_bound_vars: return the original alias. /// - otherwise: return the normalized result. It can be (partially) inferred @@ -36,7 +46,7 @@ fn normalize_with_universes<'tcx, T>( at: At<'_, 'tcx>, value: Unnormalized<'tcx, T>, universes: Vec>, -) -> Normalized<'tcx, T> +) -> Result, PredicateObligation<'tcx>> where T: TypeFoldable>, { @@ -45,19 +55,25 @@ where let value = infcx.deeply_resolve_ignoring_regions(value); if !infcx.tcx.renormalize_rigid_aliases() && !value.has_non_rigid_aliases() { - return Normalized { value, obligations: Default::default() }; + return Ok(Normalized { value, obligations: Default::default() }); } - let original_value = value.clone(); let mut stalled_goals = vec![]; - let mut folder = NormalizationFolder::new(infcx, universes.clone(), |alias_term| { + let mut folder = NormalizationFolder::new(infcx, universes, |alias_term| { let delegate = <&SolverDelegate<'tcx>>::from(infcx); let infer_term = delegate.next_term_var_of_alias_kind(alias_term, at.cause.span); let predicate = ty::ProjectionClause { projection_term: alias_term, term: infer_term }; let goal = Goal::new(infcx.tcx, at.param_env, predicate); let result = match delegate.evaluate_root_goal(goal, at.cause.span, None) { Ok(result) => result, - Err(err) => return Err(err), + Err(_) => { + return Err(Obligation::new( + infcx.tcx, + at.cause.clone(), + goal.param_env, + goal.predicate, + )); + } }; let normalized = infcx.deeply_resolve_ignoring_regions(infer_term); let normalization_was_ambiguous = match result.certainty { @@ -69,19 +85,12 @@ where }; Ok((normalized, normalization_was_ambiguous)) }); - if let Ok(value) = value.try_fold_with(&mut folder) { - let obligations = stalled_goals - .into_iter() - .map(|goal| { - Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate) - }) - .collect(); - Normalized { value, obligations } - } else { - let mut replacer = ReplaceAliasWithInfer { at, obligations: Default::default(), universes }; - let value = original_value.fold_with(&mut replacer); - Normalized { value, obligations: replacer.obligations } - } + let value = value.try_fold_with(&mut folder)?; + let obligations = stalled_goals + .into_iter() + .map(|goal| Obligation::new(infcx.tcx, at.cause.clone(), goal.param_env, goal.predicate)) + .collect(); + Ok(Normalized { value, obligations }) } struct ReplaceAliasWithInfer<'me, 'tcx> { @@ -134,6 +143,8 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { if ty.has_escaping_bound_vars() { let (replaced, ..) = BoundVarReplacer::replace_bound_vars(self.at.infcx, &mut self.universes, alias); + // Keep the higher-ranked alias in the folded value; the fresh term is only + // used to register its projection obligation. let _ = self.term_to_infer(replaced.into()); ty } else { @@ -158,6 +169,8 @@ impl<'me, 'tcx> TypeFolder> for ReplaceAliasWithInfer<'me, 'tcx> { &mut self.universes, alias_const, ); + // Keep the higher-ranked alias in the folded value; the fresh term is only + // used to register its projection obligation. let _ = self.term_to_infer(replaced.into()); ct } else { @@ -222,7 +235,10 @@ where T: TypeFoldable>, E: FromSolverError<'tcx, NextSolverError<'tcx>>, { - let Normalized { value, obligations } = normalize_with_universes(at, value, universes); + let Normalized { value, obligations } = normalize_with_universes(at, value, universes) + .map_err(|obligation| { + thin_vec![E::from_solver_error(at.infcx, NextSolverError::TrueError(obligation))] + })?; let mut fulfill_cx = FulfillmentCtxt::new(at.infcx); for pred in obligations { diff --git a/tests/ui/associated-inherent-types/issue-111404-1.stderr b/tests/ui/associated-inherent-types/issue-111404-1.current.stderr similarity index 88% rename from tests/ui/associated-inherent-types/issue-111404-1.stderr rename to tests/ui/associated-inherent-types/issue-111404-1.current.stderr index 9a5b69497c0cf..b77b3c00a69f9 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.stderr +++ b/tests/ui/associated-inherent-types/issue-111404-1.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/issue-111404-1.rs:10:11 + --> $DIR/issue-111404-1.rs:14:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other @@ -8,7 +8,7 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} found struct `Foo fn(&'b ())>` error[E0308]: mismatched types - --> $DIR/issue-111404-1.rs:10:11 + --> $DIR/issue-111404-1.rs:14:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other @@ -18,13 +18,13 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 + --> $DIR/issue-111404-1.rs:14:1 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:1 + --> $DIR/issue-111404-1.rs:14:1 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -32,7 +32,7 @@ LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/issue-111404-1.rs:10:8 + --> $DIR/issue-111404-1.rs:14:8 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} | ^ diff --git a/tests/ui/associated-inherent-types/issue-111404-1.next.stderr b/tests/ui/associated-inherent-types/issue-111404-1.next.stderr new file mode 100644 index 0000000000000..812a6ee052d29 --- /dev/null +++ b/tests/ui/associated-inherent-types/issue-111404-1.next.stderr @@ -0,0 +1,9 @@ +error[E0271]: type mismatch resolving `Foo::Assoc == &()` + --> $DIR/issue-111404-1.rs:14:11 + | +LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/associated-inherent-types/issue-111404-1.rs b/tests/ui/associated-inherent-types/issue-111404-1.rs index cad6d48b1c5af..a23856d0eac8d 100644 --- a/tests/ui/associated-inherent-types/issue-111404-1.rs +++ b/tests/ui/associated-inherent-types/issue-111404-1.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@ [next] compile-flags: -Znext-solver + #![feature(inherent_associated_types)] #![allow(incomplete_features)] @@ -8,10 +12,11 @@ impl<'a> Foo { } fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} -//~^ ERROR mismatched types [E0308] -//~| ERROR mismatched types [E0308] -//~| ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error -//~| ERROR higher-ranked subtype error +//[current]~^ ERROR mismatched types [E0308] +//[current]~| ERROR mismatched types [E0308] +//[current]~| ERROR higher-ranked subtype error +//[current]~| ERROR higher-ranked subtype error +//[current]~| ERROR higher-ranked subtype error +//[next]~^^^^^^ ERROR type mismatch resolving fn main() {} diff --git a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs index 17a81b5705dfb..6acc1baf319ef 100644 --- a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs +++ b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.rs @@ -11,8 +11,6 @@ impl<'a> Foo { } fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} -//~^ ERROR: higher-ranked subtype error -//~| ERROR: lifetime bound not satisfied [E0478] -//~| ERROR: lifetime bound not satisfied [E0478] +//~^ ERROR type mismatch resolving fn main() {} diff --git a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr index 47227014ec567..4a032c267e80a 100644 --- a/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr +++ b/tests/ui/traits/next-solver/implied_outlives_bounds_not_resolving_vars_ice.stderr @@ -1,23 +1,9 @@ -error[E0478]: lifetime bound not satisfied +error[E0271]: type mismatch resolving `Foo::Assoc == &()` --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:11 | LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ -error[E0478]: lifetime bound not satisfied - --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:11 - | -LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: higher-ranked subtype error - --> $DIR/implied_outlives_bounds_not_resolving_vars_ice.rs:13:8 - | -LL | fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) {} - | ^ - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0478`. +For more information about this error, try `rustc --explain E0271`. diff --git a/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs new file mode 100644 index 0000000000000..de94cad403a3a --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.rs @@ -0,0 +1,34 @@ +//@ needs-rustc-debug-assertions +//@ compile-flags: -Znext-solver + +// Regression test for #160875. +// +// Eagerly normalizing the inner alias makes the outer alias fail the leak check: +// `Foo fn(&'b ())>` cannot be equated with the impl's `Foo`. +// Deep normalization must propagate that failure. Retrying the original aliases +// with `ReplaceAliasWithInfer` instead moved the lifetime equalities into nested +// goals, whose constraints were invisible to the parent's leak check. +// +// The fallback incorrectly succeeded and returned `fn(?3t)`. Resolving that value +// only hid the failed leak check. With debug assertions enabled, returning the +// unresolved value also triggered an assertion in `normalize_erasing_regions`. +// +// The invalid const body reaches MIR signature normalization in metadata-only +// tests. Keep debug assertions enabled to catch the original ICE as well. + +#![feature(inherent_associated_types)] +#![allow(incomplete_features)] + +struct Foo(T); + +impl<'a> Foo { + type Assoc = &'a (); +} + +const fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) { + //~^ ERROR type mismatch resolving + x + //~^ ERROR cannot find value `x` in this scope +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr new file mode 100644 index 0000000000000..680e5f702b423 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize/deeply-normalize-fallback-issue-160875.stderr @@ -0,0 +1,16 @@ +error[E0425]: cannot find value `x` in this scope + --> $DIR/deeply-normalize-fallback-issue-160875.rs:30:5 + | +LL | x + | ^ not found in this scope + +error[E0271]: type mismatch resolving `Foo::Assoc == &()` + --> $DIR/deeply-normalize-fallback-issue-160875.rs:28:17 + | +LL | const fn bar(_: fn(Foo fn(Foo::Assoc)>::Assoc)) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0271, E0425. +For more information about an error, try `rustc --explain E0271`. From 88a1bbeff06cf5dc45968e55d0e021e0693215aa Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 18:31:48 +0200 Subject: [PATCH 0409/1309] statx: proper error code on empty path without flag --- src/tools/miri/src/shims/unix/fs.rs | 5 +-- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 44 ++++++++++++++----- 2 files changed, 35 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 17cf5505203df..d610decfdd5a6 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -819,10 +819,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags for `statx`: {flags:#x}") } - // The docs are kind of unclear about what empty paths should do when the - // flag is *not* set, so we just bail. + // Empty path requires corresponding flag. if path.is_empty() && !empty_path_flag { - throw_unsup_format!("statx only supports empty paths if `AT_EMPTY_PATH` is set"); + return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); } // Reject if isolation is enabled. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 951c52d8fcbf6..463b45c0150fc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -121,6 +121,7 @@ fn test_statx_on_file_descriptor() { let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx_fd.txt", bytes); let file = File::open(&path).unwrap(); + let meta = file.metadata().unwrap(); unsafe { let mut stx = MaybeUninit::::zeroed(); @@ -133,10 +134,23 @@ fn test_statx_on_file_descriptor() { )); let stx = stx.assume_init(); - let meta = file.metadata().unwrap(); assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); } + // If we don't set AT_EMPTY_PATH, we get an error. + unsafe { + let mut stx = MaybeUninit::::zeroed(); + let err = errno_result(libc::statx( + file.as_raw_fd(), + c"".as_ptr(), + 0, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); + } + drop(file); remove_file(&path).unwrap(); } @@ -148,6 +162,7 @@ fn test_statx_on_file_path() { let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx.txt", bytes); let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let meta = fs::metadata(&path).unwrap(); unsafe { let mut stx = MaybeUninit::::zeroed(); @@ -160,7 +175,21 @@ fn test_statx_on_file_path() { )); let stx = stx.assume_init(); - let meta = fs::metadata(&path).unwrap(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + + // Setting AT_EMPTY_PATH is fine even if the path is not actually empty. + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + libc::AT_FDCWD, + c_path.as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + + let stx = stx.assume_init(); assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); } @@ -175,20 +204,13 @@ fn test_statx_empty_path_on_pipe() { let mut statx_buf = std::mem::MaybeUninit::::zeroed(); - let ret = libc::statx( + errno_check(libc::statx( fds[0], c"".as_ptr(), libc::AT_EMPTY_PATH, libc::STATX_BASIC_STATS, statx_buf.as_mut_ptr(), - ); - - assert_eq!( - ret, - 0, - "statx on pipe with AT_EMPTY_PATH failed: {}", - std::io::Error::last_os_error() - ); + )); let statx_buf = statx_buf.assume_init(); From 900f61b04f0294769e0d35026309d3b8dfa2468a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 18:36:50 +0200 Subject: [PATCH 0410/1309] closedir: also close underlying FD --- src/tools/miri/src/shims/unix/fs.rs | 4 +++- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 4 ++++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 17cf5505203df..fc18eb647dae5 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -17,7 +17,7 @@ use crate::shims::FdId; use crate::shims::files::{DirHandle, FdNum, FileHandle}; use crate::shims::os_str::bytes_to_os_str; use crate::shims::sig::Varargs; -use crate::shims::unix::fd::{FlockOp, UnixFileDescription}; +use crate::shims::unix::fd::{EvalContextExt as _, FlockOp, UnixFileDescription}; use crate::*; /// An open directory stream, tracked by DirTable. @@ -1332,6 +1332,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if this.machine.fds.get(open_dir.fd_num).is_none_or(|fd| fd.id() != open_dir.fd_id) { throw_ub_format!("the backing FD for this DIR stream has been tampered with"); } + // And close it. + this.close(open_dir.fd_num)?; if let Some(entry) = open_dir.entry.take() { this.deallocate_ptr(entry, None, MiriMemoryKind::Runtime.into())?; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 951c52d8fcbf6..5161332ea1376 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -1035,6 +1035,10 @@ fn test_dirfd() { check_stat_fields(stat); errno_check(unsafe { libc::closedir(dir) }); + + // `closedir` should also have closed the stream. + let err = errno_result(unsafe { libc::close(dirfd) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::EBADF); } /// Check that all common fields of a `stat` struct are initialized. From a03dc0935d75c61a97a6d4bac267b1c40023cbf9 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Sat, 19 Sep 2026 12:42:44 -0400 Subject: [PATCH 0411/1309] hir_typeck: simplify `upvar::determine_capture_info` impl --- compiler/rustc_hir_typeck/src/upvar.rs | 60 +++++-------------------- compiler/rustc_middle/src/ty/closure.rs | 44 +++++++++++++++--- 2 files changed, 48 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 875517ee4c87e..f1fc0057111d4 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -30,7 +30,7 @@ //! then mean that all later passes would have to check for these figments //! and report an error, and it just seems like more mess in the end.) -use std::iter; +use std::{cmp, iter}; use rustc_abi::FIRST_VARIANT; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; @@ -2608,56 +2608,18 @@ fn determine_capture_info( capture_info_a: ty::CaptureInfo, capture_info_b: ty::CaptureInfo, ) -> ty::CaptureInfo { - // If the capture kind is equivalent then, we don't need to escalate and can compare the - // expressions. - let eq_capture_kind = match (capture_info_a.capture_kind, capture_info_b.capture_kind) { - (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue) => true, - (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByUse) => true, - (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => ref_a == ref_b, - (ty::UpvarCapture::ByValue, _) - | (ty::UpvarCapture::ByUse, _) - | (ty::UpvarCapture::ByRef(_), _) => false, - }; - - if eq_capture_kind { - match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) { - (Some(_), _) | (None, None) => capture_info_a, - (None, Some(_)) => capture_info_b, - } - } else { - // We select the CaptureKind which ranks higher based the following priority order: - // (ByUse | ByValue) > MutBorrow > UniqueImmBorrow > ImmBorrow - match (capture_info_a.capture_kind, capture_info_b.capture_kind) { - (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByValue) - | (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByUse) => { - bug!("Same capture can't be ByUse and ByValue at the same time") - } - (ty::UpvarCapture::ByValue, ty::UpvarCapture::ByValue) - | (ty::UpvarCapture::ByUse, ty::UpvarCapture::ByUse) - | (ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse, ty::UpvarCapture::ByRef(_)) => { - capture_info_a - } - (ty::UpvarCapture::ByRef(_), ty::UpvarCapture::ByValue | ty::UpvarCapture::ByUse) => { - capture_info_b - } - (ty::UpvarCapture::ByRef(ref_a), ty::UpvarCapture::ByRef(ref_b)) => { - match (ref_a, ref_b) { - // Take LHS: - (BorrowKind::UniqueImmutable | BorrowKind::Mutable, BorrowKind::Immutable) - | (BorrowKind::Mutable, BorrowKind::UniqueImmutable) => capture_info_a, - - // Take RHS: - (BorrowKind::Immutable, BorrowKind::UniqueImmutable | BorrowKind::Mutable) - | (BorrowKind::UniqueImmutable, BorrowKind::Mutable) => capture_info_b, - - (BorrowKind::Immutable, BorrowKind::Immutable) - | (BorrowKind::UniqueImmutable, BorrowKind::UniqueImmutable) - | (BorrowKind::Mutable, BorrowKind::Mutable) => { - bug!("Expected unequal capture kinds"); - } - } + // We select the CaptureKind which ranks higher based the following priority order: + // (ByUse | ByValue) > MutBorrow > UniqueImmBorrow > ImmBorrow + match capture_info_a.capture_kind.partial_cmp(&capture_info_b.capture_kind) { + Some(cmp::Ordering::Equal) => { + match (capture_info_a.capture_kind_expr_id, capture_info_b.capture_kind_expr_id) { + (Some(_), _) | (None, None) => capture_info_a, + (None, Some(_)) => capture_info_b, } } + Some(cmp::Ordering::Greater) => capture_info_a, + Some(cmp::Ordering::Less) => capture_info_b, + None => bug!("Same capture can't be ByUse and ByValue at the same time"), } } diff --git a/compiler/rustc_middle/src/ty/closure.rs b/compiler/rustc_middle/src/ty/closure.rs index 652c353d418c2..4b410b3259bff 100644 --- a/compiler/rustc_middle/src/ty/closure.rs +++ b/compiler/rustc_middle/src/ty/closure.rs @@ -1,3 +1,4 @@ +use std::cmp; use std::fmt::Write; use rustc_data_structures::fx::FxIndexMap; @@ -46,16 +47,32 @@ impl UpvarId { #[derive(Eq, PartialEq, Clone, Debug, Copy, TyEncodable, TyDecodable, StableHash, Hash)] #[derive(TypeFoldable, TypeVisitable)] pub enum UpvarCapture { + /// Upvar is captured by reference. + ByRef(BorrowKind), + + /// Upvar is captured by use. This is true when the closure is labeled `use`. + ByUse, + /// Upvar is captured by value. This is always true when the /// closure is labeled `move`, but can also be true in other cases /// depending on inference. ByValue, +} - /// Upvar is captured by use. This is true when the closure is labeled `use`. - ByUse, - - /// Upvar is captured by reference. - ByRef(BorrowKind), +// Used in rustc_hir_typeck::upvar::determine_capture_info +impl PartialOrd for UpvarCapture { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + match (self, other) { + (Self::ByValue, Self::ByValue) | (Self::ByUse, Self::ByUse) => { + Some(cmp::Ordering::Equal) + } + (Self::ByValue | Self::ByUse, Self::ByRef(_)) => Some(cmp::Ordering::Greater), + (Self::ByRef(_), Self::ByValue | Self::ByUse) => Some(cmp::Ordering::Less), + (Self::ByRef(left), Self::ByRef(right)) => Some(left.cmp(&right)), + (Self::ByUse, Self::ByValue) | (Self::ByValue, Self::ByUse) => None, + } + } } /// Given the closure DefId this map provides a map of root variables to minimum @@ -339,8 +356,21 @@ pub fn place_to_string_for_capture<'tcx>(tcx: TyCtxt<'tcx>, place: &HirPlace<'tc curr_string } -#[derive(Eq, Clone, PartialEq, Debug, TyEncodable, TyDecodable, Copy, StableHash, Hash)] -#[derive(TypeFoldable, TypeVisitable)] +#[derive( + Clone, + Copy, + Debug, + PartialEq, + Eq, + Hash, + PartialOrd, // Order of variants is load-bearing + Ord, + TyEncodable, + TyDecodable, + StableHash, + TypeFoldable, + TypeVisitable +)] pub enum BorrowKind { /// Data must be immutable and is aliasable. Immutable, From 2e15f7b0ea873b1057a98a97294d409cff3bf5f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 27 Jul 2026 20:43:32 +0000 Subject: [PATCH 0412/1309] Better account for `Self` that might be a typo of `self` When in a method trying to access `Self` on its own, suggest `self`. When in any assoc fn trying to access `Self()`, suggest `Self { fields }` or using an enum variant. When enum has no variants, mention it. --- compiler/rustc_hir_typeck/src/expr.rs | 1 + .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 56 ++++++-- compiler/rustc_hir_typeck/src/pat.rs | 11 +- .../invalid-self-constructor-56835.stderr | 8 +- .../self-constructor-type-error-56199.rs | 31 +++++ .../self-constructor-type-error-56199.stderr | 129 +++++++++++++++++- 6 files changed, 213 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a8898acf3a415..c995cdee10fe9 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -617,6 +617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { call_expr_and_args.map_or(expr.span, |(e, _)| e.span), expr.span, expr.hir_id, + call_expr_and_args.is_some(), ) .0 } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e655e0857d858..ea2e3584b2db7 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1006,6 +1006,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, path_span: Span, hir_id: HirId, + has_args: bool, ) -> (Ty<'tcx>, Res) { let tcx = self.tcx; @@ -1253,17 +1254,50 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "the `Self` constructor can only be used with tuple or unit structs", ); if let Some(adt_def) = ty.normalized.ty_adt_def() { - match adt_def.adt_kind() { - AdtKind::Enum => { - err.help("did you mean to use one of the enum's variants?"); - } - AdtKind::Struct | AdtKind::Union => { - err.span_suggestion( - span, - "use curly brackets", - "Self { /* fields */ }", - Applicability::HasPlaceholders, - ); + let def_id = self.body_def_id.to_def_id(); + if !has_args + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.is_method() + { + let self_ty = + tcx.fn_sig(def_id).instantiate_identity().skip_binder().inputs()[0]; + let applicability = if let ty::Adt(..) = self_ty.kind() { + // We're within a method that takes ownership of `Self`, likely a + // builder, so this is most likely a typo. + Applicability::MachineApplicable + } else { + // We still might have meant `self` instead of `Self`. + Applicability::MaybeIncorrect + }; + err.span_suggestion_verbose( + span, + format!( + "you might have meant to refer to the `self` binding of type \ + `{self_ty}`", + ), + "self".to_string(), + applicability, + ); + } else { + match adt_def.adt_kind() { + AdtKind::Enum => { + err.span_help( + tcx.def_span(adt_def.did()), + if adt_def.variants().is_empty() { + "the enum is unconstructable because it has no variants" + } else { + "you might have meant to use one of the enum's variants" + }, + ); + } + AdtKind::Struct | AdtKind::Union => { + err.span_suggestion_verbose( + span, + "use curly brackets", + "Self { /* fields */ }", + Applicability::HasPlaceholders, + ); + } } } } diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..ec4483b62fe72 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -911,7 +911,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rustc_hir::PatExprKind::Path(qpath) => { let (res, opt_ty, segments) = self.resolve_ty_and_res_fully_qualified_call(qpath, lt.hir_id, lt.span); - self.instantiate_value_path(segments, opt_ty, res, lt.span, lt.span, lt.hir_id).0 + self.instantiate_value_path( + segments, opt_ty, res, lt.span, lt.span, lt.hir_id, false, + ) + .0 } }; self.write_ty(lt.hir_id, ty); @@ -1624,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find the type of the path pattern, for later checking. let (pat_ty, pat_res) = - self.instantiate_value_path(segments, opt_ty, res, span, span, path_id); + self.instantiate_value_path(segments, opt_ty, res, span, span, path_id, false); Ok(ResolvedPat { ty: pat_ty, kind: ResolvedPatKind::Path { res, pat_res, segments } }) } @@ -1784,8 +1787,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // Type-check the path. - let (pat_ty, res) = - self.instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id); + let (pat_ty, res) = self + .instantiate_value_path(segments, opt_ty, res, pat.span, pat.span, pat.hir_id, false); if !pat_ty.is_fn() { return report_unexpected_res(res); } diff --git a/tests/ui/structs/invalid-self-constructor-56835.stderr b/tests/ui/structs/invalid-self-constructor-56835.stderr index 045781ec42bd2..9b25348d87d39 100644 --- a/tests/ui/structs/invalid-self-constructor-56835.stderr +++ b/tests/ui/structs/invalid-self-constructor-56835.stderr @@ -2,7 +2,13 @@ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/invalid-self-constructor-56835.rs:5:12 | LL | fn bar(Self(foo): Self) {} - | ^^^^^^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^^^^^^ + | +help: use curly brackets + | +LL - fn bar(Self(foo): Self) {} +LL + fn bar(Self { /* fields */ }: Self) {} + | error[E0164]: expected tuple struct or tuple variant, found self constructor `Self` --> $DIR/invalid-self-constructor-56835.rs:5:12 diff --git a/tests/ui/typeck/self-constructor-type-error-56199.rs b/tests/ui/typeck/self-constructor-type-error-56199.rs index b08d69189807a..34af8bed25c47 100644 --- a/tests/ui/typeck/self-constructor-type-error-56199.rs +++ b/tests/ui/typeck/self-constructor-type-error-56199.rs @@ -1,5 +1,8 @@ // https://github.com/rust-lang/rust/issues/56199 enum Foo {} +enum Lab { + Qux, +} struct Bar {} impl Foo { @@ -9,6 +12,12 @@ impl Foo { let _ = Self(); //~^ ERROR the `Self` constructor can only be used with tuple or unit structs } + fn foo_method(self) { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } } impl Bar { @@ -18,6 +27,28 @@ impl Bar { let _ = Self(); //~^ ERROR the `Self` constructor can only be used with tuple or unit structs } + fn bar_method(self) { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } +} + +impl Lab { + fn lab() { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } + fn lab_method(self) { + let _ = Self; + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + let _ = Self(); + //~^ ERROR the `Self` constructor can only be used with tuple or unit structs + } } + fn main() {} diff --git a/tests/ui/typeck/self-constructor-type-error-56199.stderr b/tests/ui/typeck/self-constructor-type-error-56199.stderr index 6e9d0fcd90c05..d0d124c6f3149 100644 --- a/tests/ui/typeck/self-constructor-type-error-56199.stderr +++ b/tests/ui/typeck/self-constructor-type-error-56199.stderr @@ -1,30 +1,145 @@ error: the `Self` constructor can only be used with tuple or unit structs - --> $DIR/self-constructor-type-error-56199.rs:7:17 + --> $DIR/self-constructor-type-error-56199.rs:10:17 | LL | let _ = Self; | ^^^^ | - = help: did you mean to use one of the enum's variants? +help: the enum is unconstructable because it has no variants + --> $DIR/self-constructor-type-error-56199.rs:2:1 + | +LL | enum Foo {} + | ^^^^^^^^ error: the `Self` constructor can only be used with tuple or unit structs - --> $DIR/self-constructor-type-error-56199.rs:9:17 + --> $DIR/self-constructor-type-error-56199.rs:12:17 | LL | let _ = Self(); | ^^^^^^ | - = help: did you mean to use one of the enum's variants? +help: the enum is unconstructable because it has no variants + --> $DIR/self-constructor-type-error-56199.rs:2:1 + | +LL | enum Foo {} + | ^^^^^^^^ error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/self-constructor-type-error-56199.rs:16:17 | LL | let _ = Self; - | ^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^ + | +help: you might have meant to refer to the `self` binding of type `Foo` (notice the capitalization) + | +LL - let _ = Self; +LL + let _ = self; + | error: the `Self` constructor can only be used with tuple or unit structs --> $DIR/self-constructor-type-error-56199.rs:18:17 | LL | let _ = Self(); - | ^^^^^^ help: use curly brackets: `Self { /* fields */ }` + | ^^^^^^ + | +help: the enum is unconstructable because it has no variants + --> $DIR/self-constructor-type-error-56199.rs:2:1 + | +LL | enum Foo {} + | ^^^^^^^^ + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:25:17 + | +LL | let _ = Self; + | ^^^^ + | +help: use curly brackets + | +LL | let _ = Self { /* fields */ }; + | ++++++++++++++++ + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:27:17 + | +LL | let _ = Self(); + | ^^^^^^ + | +help: use curly brackets + | +LL - let _ = Self(); +LL + let _ = Self { /* fields */ }; + | + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:31:17 + | +LL | let _ = Self; + | ^^^^ + | +help: you might have meant to refer to the `self` binding of type `Bar` (notice the capitalization) + | +LL - let _ = Self; +LL + let _ = self; + | + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:33:17 + | +LL | let _ = Self(); + | ^^^^^^ + | +help: use curly brackets + | +LL - let _ = Self(); +LL + let _ = Self { /* fields */ }; + | + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:40:17 + | +LL | let _ = Self; + | ^^^^ + | +help: you might have meant to use one of the enum's variants + --> $DIR/self-constructor-type-error-56199.rs:3:1 + | +LL | enum Lab { + | ^^^^^^^^ + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:42:17 + | +LL | let _ = Self(); + | ^^^^^^ + | +help: you might have meant to use one of the enum's variants + --> $DIR/self-constructor-type-error-56199.rs:3:1 + | +LL | enum Lab { + | ^^^^^^^^ + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:46:17 + | +LL | let _ = Self; + | ^^^^ + | +help: you might have meant to refer to the `self` binding of type `Lab` (notice the capitalization) + | +LL - let _ = Self; +LL + let _ = self; + | + +error: the `Self` constructor can only be used with tuple or unit structs + --> $DIR/self-constructor-type-error-56199.rs:48:17 + | +LL | let _ = Self(); + | ^^^^^^ + | +help: you might have meant to use one of the enum's variants + --> $DIR/self-constructor-type-error-56199.rs:3:1 + | +LL | enum Lab { + | ^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 12 previous errors From 6c6586a77dbb1da759686f61a8b1ba20beab247c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Sep 2026 22:07:48 +0200 Subject: [PATCH 0413/1309] Correctly handle `dyn` trait methods linking for jump to def feature --- src/librustdoc/html/format.rs | 15 +++++++++++- src/librustdoc/html/span_map.rs | 9 ++++--- tests/rustdoc-html/jump-to-def/dyn.rs | 35 +++++++++++++++++++++++++++ 3 files changed, 54 insertions(+), 5 deletions(-) create mode 100644 tests/rustdoc-html/jump-to-def/dyn.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 13fc6e3bc1bb8..8ecfcbaeedf9f 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -417,6 +417,7 @@ fn generate_item_def_id_path( root_path: Option<&str>, ) -> Result { use rustc_middle::traits::ObligationCause; + use rustc_middle::ty; use rustc_trait_selection::infer::TyCtxtInferExt; use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; @@ -434,7 +435,19 @@ fn generate_item_def_id_path( .query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip())) .map(|resolved| infcx.resolve_vars_if_possible(resolved.value).skip_binder()) .unwrap_or(ty.skip_binder()); - if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) { + // If this is a dyn trait, we want to get the actual trait from which the method comes from. + // Since a `dyn trait` (as of 2026) can only be composed of a trait plus auto traits, we + // look for the trait and ignore auto traits. + if let ty::Dynamic(traits, _) = ty.kind() + && let Some(trait_def_id) = + traits.iter().find_map(|trait_| match trait_.skip_binder() { + ty::ExistentialPredicate::Trait(t) => Some(t.def_id), + ty::ExistentialPredicate::Projection(p) => Some(p.trait_ref(tcx).def_id), + ty::ExistentialPredicate::AutoTrait(_) => None, + }) + { + def_id = trait_def_id; + } else if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) { def_id = new_def_id; } else { prim = PrimitiveType::from_ty(ty); diff --git a/src/librustdoc/html/span_map.rs b/src/librustdoc/html/span_map.rs index 424b3c94fcbb1..1efc3e0082f32 100644 --- a/src/librustdoc/html/span_map.rs +++ b/src/librustdoc/html/span_map.rs @@ -13,11 +13,12 @@ use rustc_span::{BytePos, ExpnKind}; use crate::clean::{self, PrimitiveType, rustc_span}; use crate::html::sources; -/// This is a stripped down version of [`rustc_span::Span`] that only contains the start and end byte positions of the span. +/// This is a stripped down version of [`rustc_span::Span`] that only contains the start and end +/// byte positions of the span. /// -/// Profiling showed that the `Span` interner was taking up a lot of the run-time when highlighting, and since we -/// never actually use the context and parent that are stored in a normal `Span`, we can replace its usages with this -/// one, which is much cheaper to construct. +/// Profiling showed that the `Span` interner was taking up a lot of the run-time when highlighting, +/// and since we never actually use the context and parent that are stored in a normal `Span`, we +/// can replace its usages with this one, which is much cheaper to construct. #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub(crate) struct Span { lo: BytePos, diff --git a/tests/rustdoc-html/jump-to-def/dyn.rs b/tests/rustdoc-html/jump-to-def/dyn.rs new file mode 100644 index 0000000000000..b958f6631cb3c --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/dyn.rs @@ -0,0 +1,35 @@ +// This test ensures that `dyn` traits methods are correctly linked in the +// source code (and not to "foreigntype"). + +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +//@ has 'src/foo/dyn.rs.html' +//@ has - '//a[@href="{{channel}}/core/any/trait.Any.html#method.is"]' 'is' +// There should be two of them. +//@ count - '//a[@href="{{channel}}/core/any/trait.Any.html#method.is"]' 2 + +pub struct X(std::boxed::Box); + +impl X { + pub fn downcast(self) -> Result, Self> { + if self.0.is::() { + Ok(unsafe { std::mem::transmute(self) }) + } else { + Err(self) + } + } +} + +pub struct Y(std::boxed::Box); + +impl Y { + pub fn downcast(self) -> Result, Self> { + if self.0.is::() { + Ok(unsafe { std::mem::transmute(self) }) + } else { + Err(self) + } + } +} From 09fb8491438cc7f31c67073cc101b551a9184263 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 9 Mar 2026 23:28:01 +0000 Subject: [PATCH 0414/1309] Detect more cases of method shadowing with incorrect arguments ``` error[E0061]: this method takes 0 arguments but 1 argument was supplied --> $DIR/shadowed-intrinsic-method.rs:18:7 | LL | a.borrow(()); | ^^^^^^ -- unexpected argument of type `()` | note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `A` --> $DIR/shadowed-intrinsic-method.rs:18:7 | LL | use std::borrow::Borrow; | ------------------- `std::borrow::Borrow` imported here ... LL | a.borrow(()); | ^^^^^^ refers to `std::borrow::Borrow::borrow` note: method defined here --> $SRC_DIR/core/src/borrow.rs:LL:COL help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - a.borrow(()); LL + A::borrow(&mut a, ()); | help: remove the extra argument | LL - a.borrow(()); LL + a.borrow(); | ``` Account for inherent methods Tweak wording on "other methods available" note Handle correct gramar in the face of a single other option, or many. --- compiler/rustc_hir_typeck/src/demand.rs | 105 ++++++++++------- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 + tests/ui/methods/shadowed-intrinsic-method.rs | 37 ++++++ .../methods/shadowed-intrinsic-method.stderr | 111 ++++++++++++++++++ ...thod-lookup-returns-sig-with-fewer-args.rs | 8 +- ...-lookup-returns-sig-with-fewer-args.stderr | 10 +- .../suggestions/shadowed-lplace-method.fixed | 2 +- .../suggestions/shadowed-lplace-method.stderr | 2 +- 8 files changed, 226 insertions(+), 51 deletions(-) create mode 100644 tests/ui/methods/shadowed-intrinsic-method.rs create mode 100644 tests/ui/methods/shadowed-intrinsic-method.stderr diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index d18745e24fd84..55eecef732aa4 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,5 +1,5 @@ -use rustc_errors::{Applicability, Diag, MultiSpan, listify}; -use rustc_hir::def::Res; +use rustc_errors::{Applicability, Diag, MultiSpan, listify, pluralize}; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; @@ -28,7 +28,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if expr_ty == expected { return; } - self.annotate_alternative_method_deref(err, expr, error); + self.annotate_alternative_method_deref_for_unop(err, expr, error); self.explain_self_literal(err, expr, expected, expr_ty); // Use `||` to give these suggestions a precedence @@ -752,11 +752,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { hir::ExprKind::Path(hir::QPath::Resolved( None, hir::Path { - res: - hir::def::Res::Def( - hir::def::DefKind::Static { .. } | hir::def::DefKind::Const, - def_id, - ), + res: hir::def::Res::Def(DefKind::Static { .. } | DefKind::Const, def_id), .. }, )) => { @@ -929,7 +925,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { false } - fn annotate_alternative_method_deref( + fn annotate_alternative_method_deref_for_unop( &self, err: &mut Diag<'_>, expr: &hir::Expr<'_>, @@ -949,7 +945,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::ExprKind::Unary(hir::UnOp::Deref, deref) = lhs.kind else { return; }; - let hir::ExprKind::MethodCall(path, base, args, _) = deref.kind else { + self.annotate_alternative_method_deref(err, deref, Some(expected)) + } + + #[tracing::instrument(skip(self, err), level = "debug")] + pub(crate) fn annotate_alternative_method_deref( + &self, + err: &mut Diag<'_>, + expr: &hir::Expr<'_>, + expected: Option>, + ) { + let hir::ExprKind::MethodCall(path, base, args, _) = expr.kind else { return; }; let Some(self_ty) = self.typeck_results.borrow().expr_ty_adjusted_opt(base) else { @@ -959,7 +965,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(pick) = self.lookup_probe_for_diagnostic( path.ident, self_ty, - deref, + expr, probe::ProbeScope::TraitsInScope, None, ) else { @@ -969,10 +975,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(in_scope_methods) = self.probe_for_name_many( probe::Mode::MethodCall, path.ident, - Some(expected), + expected, probe::IsSuggestion(true), self_ty, - deref.hir_id, + expr.hir_id, probe::ProbeScope::TraitsInScope, ) else { return; @@ -984,10 +990,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let Ok(all_methods) = self.probe_for_name_many( probe::Mode::MethodCall, path.ident, - Some(expected), + expected, probe::IsSuggestion(true), self_ty, - deref.hir_id, + expr.hir_id, probe::ProbeScope::AllTraits, ) else { return; @@ -995,34 +1001,51 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let suggestions: Vec<_> = all_methods .into_iter() - .filter(|c| c.item.def_id != pick.item.def_id) - .map(|c| { + .filter_map(|c| { + if c.item.def_id == pick.item.def_id { + return None; + } let m = c.item; let generic_args = ty::GenericArgs::for_item(self.tcx, m.def_id, |param, _| { - self.var_for_def(deref.span, param) + self.var_for_def(expr.span, param) }); - let mutability = - match self.tcx.fn_sig(m.def_id).skip_binder().input(0).skip_binder().kind() { - ty::Ref(_, _, hir::Mutability::Mut) => "&mut ", - ty::Ref(_, _, _) => "&", - _ => "", - }; - vec![ - ( - deref.span.until(base.span), - format!( - "{}({}", - with_no_trimmed_paths!( - self.tcx.def_path_str_with_args(m.def_id, generic_args,) - ), - mutability, - ), - ), + let fn_sig = self.tcx.fn_sig(m.def_id); + if fn_sig.skip_binder().inputs().skip_binder().len() != args.len() + 1 { + return None; + } + let rcvr_ty = fn_sig.skip_binder().input(0).skip_binder(); + let (mutability, ty) = match rcvr_ty.kind() { + ty::Ref(_, ty, hir::Mutability::Mut) => ("&mut ", ty), + ty::Ref(_, ty, _) => ("&", ty), + _ => ("", &rcvr_ty), + }; + let path = match self.tcx.assoc_parent(m.def_id) { + Some((_, DefKind::Impl { of_trait: true })) => { + // We have `impl Trait for T {}`, suggest `::method`. + self.tcx.def_path_str_with_args(m.def_id, generic_args).to_string() + } + Some((_, DefKind::Impl { of_trait: false })) => { + if let ty::Adt(def, _) = ty.kind() { + // We have `impl T {}`, suggest `T::method`. + format!("{}::{}", self.tcx.def_path_str(def.did()), path.ident) + } else { + // This should be unreachable, as `impl &'a T {}` is invalid. + format!("{ty}::{}", path.ident) + } + } + // Fallback for arbitrary self types. + _ => with_no_trimmed_paths!( + self.tcx.def_path_str_with_args(m.def_id, generic_args) + ) + .to_string(), + }; + Some(vec![ + (expr.span.until(base.span), format!("{path}({}", mutability)), match &args { - [] => (base.span.shrink_to_hi().with_hi(deref.span.hi()), ")".to_string()), + [] => (base.span.shrink_to_hi().with_hi(expr.span.hi()), ")".to_string()), [first, ..] => (base.span.between(first.span), ", ".to_string()), }, - ] + ]) }) .collect(); if suggestions.is_empty() { @@ -1076,9 +1099,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); if suggestions.len() > other_methods_in_scope.len() { + let n = suggestions.len() - other_methods_in_scope.len(); err.note(format!( - "additionally, there are {} other available methods that aren't in scope", - suggestions.len() - other_methods_in_scope.len() + "additionally, there {are} {n} other available method{s} that {are}n't in scope", + are = pluralize!("is", n), + s = pluralize!(n), )); } err.multipart_suggestions( @@ -1293,7 +1318,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let hir::def::Res::Def(kind, def_id) = path.res else { return; }; - let callable_kind = if matches!(kind, hir::def::DefKind::Ctor(_, _)) { + let callable_kind = if matches!(kind, DefKind::Ctor(_, _)) { CallableKind::Constructor } else { CallableKind::Function diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 074b95321db3b..9965a9d071031 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3186,6 +3186,8 @@ impl<'a, 'tcx> ArgMatchingCtxt<'a, 'tcx> { ); return; } + + self.annotate_alternative_method_deref(err, self.call_expr, None); } /// A "softer" version of the `demand_compatible`, which checks types without persisting them, diff --git a/tests/ui/methods/shadowed-intrinsic-method.rs b/tests/ui/methods/shadowed-intrinsic-method.rs new file mode 100644 index 0000000000000..8350d6a7ba5f0 --- /dev/null +++ b/tests/ui/methods/shadowed-intrinsic-method.rs @@ -0,0 +1,37 @@ +// Can't use rustfix because we provide two suggestions: +// to remove the arg for `Borrow::borrow` or to call `Type::borrow`. +use std::borrow::Borrow; + +struct A; + +impl A { fn borrow(&mut self, _: ()) {} } + +struct B; + +fn main() { + // The fully-qualified path for items within functions is unnameable from outside that function. + impl B { fn borrow(&mut self, _: ()) {} } + + struct C; + // The fully-qualified path for items within functions is unnameable from outside that function. + impl C { fn borrow(&mut self, _: ()) {} } + + let mut a = A; + a.borrow(()); //~ ERROR E0061 + // A::borrow(&mut a, ()); + let mut b = B; + b.borrow(()); //~ ERROR E0061 + // This currently suggests `main::::borrow`, which is not correct, it should be + // B::borrow(&mut b, ()); + let mut c = C; + c.borrow(()); //~ ERROR E0061 + // This currently suggests `main::C::borrow`, which is not correct, it should be + // C::borrow(&mut c, ()); +} + +fn foo() { + let mut b = B; + b.borrow(()); //~ ERROR E0061 + // This currently suggests `main::::borrow`, which is not correct, it should be + // B::borrow(&mut b, ()); +} diff --git a/tests/ui/methods/shadowed-intrinsic-method.stderr b/tests/ui/methods/shadowed-intrinsic-method.stderr new file mode 100644 index 0000000000000..a832714cd1f97 --- /dev/null +++ b/tests/ui/methods/shadowed-intrinsic-method.stderr @@ -0,0 +1,111 @@ +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:20:7 + | +LL | a.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `A` + --> $DIR/shadowed-intrinsic-method.rs:20:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | a.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - a.borrow(()); +LL + A::borrow(&mut a, ()); + | +help: remove the extra argument + | +LL - a.borrow(()); +LL + a.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:23:7 + | +LL | b.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` + --> $DIR/shadowed-intrinsic-method.rs:23:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | b.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - b.borrow(()); +LL + B::borrow(&mut b, ()); + | +help: remove the extra argument + | +LL - b.borrow(()); +LL + b.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:27:7 + | +LL | c.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::C` + --> $DIR/shadowed-intrinsic-method.rs:27:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | c.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - c.borrow(()); +LL + C::borrow(&mut c, ()); + | +help: remove the extra argument + | +LL - c.borrow(()); +LL + c.borrow(); + | + +error[E0061]: this method takes 0 arguments but 1 argument was supplied + --> $DIR/shadowed-intrinsic-method.rs:34:7 + | +LL | b.borrow(()); + | ^^^^^^ -- unexpected argument of type `()` + | +note: the `borrow` call is resolved to the method in `std::borrow::Borrow`, shadowing the method of the same name on the inherent impl for `main::` + --> $DIR/shadowed-intrinsic-method.rs:34:7 + | +LL | use std::borrow::Borrow; + | ------------------- `std::borrow::Borrow` imported here +... +LL | b.borrow(()); + | ^^^^^^ refers to `std::borrow::Borrow::borrow` +note: method defined here + --> $SRC_DIR/core/src/borrow.rs:LL:COL +help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly + | +LL - b.borrow(()); +LL + B::borrow(&mut b, ()); + | +help: remove the extra argument + | +LL - b.borrow(()); +LL + b.borrow(); + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0061`. diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs index fd41beecb0a2a..26365d4d3e359 100644 --- a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.rs @@ -1,7 +1,7 @@ fn main() { let target: Target = create_target(); - target.get(0); // correct arguments work - target.get(10.0); // (used to crash here) + target.unique_name(0); // correct arguments work + target.unique_name(10.0); // (used to crash here) //~^ ERROR mismatched types } @@ -12,14 +12,14 @@ fn create_target() -> T { // unimplemented trait, but contains function with the same name pub trait RandomTrait { - fn get(&mut self); // but less arguments + fn unique_name(&mut self); // but less arguments } struct Target; impl Target { // correct function with arguments - pub fn get(&self, data: i32) { + pub fn unique_name(&self, data: i32) { unimplemented!() } } diff --git a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr index 0f86916fcdae4..43aa923a2a758 100644 --- a/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr +++ b/tests/ui/mismatched_types/diagnostic-method-lookup-returns-sig-with-fewer-args.stderr @@ -1,16 +1,16 @@ error[E0308]: mismatched types - --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:16 + --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:4:24 | -LL | target.get(10.0); // (used to crash here) - | --- ^^^^ expected `i32`, found floating-point number +LL | target.unique_name(10.0); // (used to crash here) + | ----------- ^^^^ expected `i32`, found floating-point number | | | arguments to this method are incorrect | note: method defined here --> $DIR/diagnostic-method-lookup-returns-sig-with-fewer-args.rs:22:12 | -LL | pub fn get(&self, data: i32) { - | ^^^ --------- +LL | pub fn unique_name(&self, data: i32) { + | ^^^^^^^^^^^ --------- error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/shadowed-lplace-method.fixed b/tests/ui/suggestions/shadowed-lplace-method.fixed index 87db01a3b230b..e7f6df9fff8fb 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.fixed +++ b/tests/ui/suggestions/shadowed-lplace-method.fixed @@ -6,5 +6,5 @@ use std::rc::Rc; fn main() { let rc = Rc::new(RefCell::new(true)); - *std::cell::RefCell::<_>::borrow_mut(&rc) = false; //~ ERROR E0308 + *RefCell::borrow_mut(&rc) = false; //~ ERROR E0308 } diff --git a/tests/ui/suggestions/shadowed-lplace-method.stderr b/tests/ui/suggestions/shadowed-lplace-method.stderr index aab9e442007ff..dfd52b9b5587b 100644 --- a/tests/ui/suggestions/shadowed-lplace-method.stderr +++ b/tests/ui/suggestions/shadowed-lplace-method.stderr @@ -19,7 +19,7 @@ LL | *rc.borrow_mut() = false; help: you might have meant to call the other method; you can use the fully-qualified path to call it explicitly | LL - *rc.borrow_mut() = false; -LL + *std::cell::RefCell::<_>::borrow_mut(&rc) = false; +LL + *RefCell::borrow_mut(&rc) = false; | error: aborting due to 1 previous error From b5084862c99f79cba5ce50374fefc3df7ae47cb3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Sat, 19 Sep 2026 23:18:37 +0200 Subject: [PATCH 0415/1309] improve tests/intro.md --- src/doc/rustc-dev-guide/src/tests/intro.md | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index 162f8b836fadb..f8cd390a55fbf 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -15,7 +15,8 @@ Almost all of them are driven by `./x test`, with some exceptions noted below. The main test harness for testing the compiler itself is a tool called [compiletest]. [compiletest] supports running different styles of tests, -organized into *test suites*. A *test mode* may provide common presets/behavior for a set of *test +organized into *test suites*. +A *test mode* may provide common presets/behavior for a set of *test suites*. [compiletest]-supported tests are located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. @@ -137,7 +138,7 @@ If you want to run only a specified set of tests, append `--test-args FILTER_NAM > Example: `./x test src/tools/miri --test-args padding` In CI, some tools are allowed to fail. -Failures send notifications to the corresponding teams, and is tracked on the [toolstate website]. +Failures send notifications to the corresponding teams, and are tracked on the [toolstate website]. More information can be found in the [toolstate documentation]. [`src/tools`]: https://github.com/rust-lang/rust/tree/HEAD/src/tools/ From c28b7a9083ff4ed1cd9582cfe307bace5481ee76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Sep 2026 22:23:01 +0000 Subject: [PATCH 0416/1309] Use verbose suggestion for parenthetical `Fn` notation and fully-qualified path on ambiguous assoc item --- .../src/hir_ty_lowering/errors.rs | 4 +- ...dyn-any-to-fn-with-missing-generics.stderr | 6 ++- .../opaque-used-in-extraneous-argument.stderr | 14 +++++- .../future-incompatible-lint-group.stderr | 7 ++- tests/ui/suggestions/fn-trait-notation.stderr | 21 +++++++-- .../assertion-left-right-goal.stderr | 28 ++++++++++-- ...ity-lint-ambiguous_associated_items.stderr | 7 ++- ...-args-issue-136407.feature_disabled.stderr | 43 ++++++++++++++++--- ...nboxed-closure-sugar-not-used-on-fn.stderr | 14 +++++- 9 files changed, 121 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 2a3728573f31e..0e5c01be85c85 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -96,7 +96,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Do not suggest the other syntax if we are in trait impl: // the desugaring would contain an associated type constraint. if !is_impl { - err.span_suggestion( + err.span_suggestion_verbose( span, "use parenthetical notation instead", fn_trait_to_string(self.tcx(), trait_segment, true), @@ -2036,7 +2036,7 @@ impl<'a, 'tcx> rustc_errors::Diagnostic<'a, ()> for AmbiguityBetweenVariantAndAs could_refer_to(DefKind::Variant, variant_def_id, ""); could_refer_to(mode.def_kind_for_diagnostics(), item_def_id, " also"); - lint.span_suggestion( + lint.span_suggestion_verbose( span, "use fully-qualified syntax", format!("<{} as {}>::{}", self_ty, tcx.item_name(bound_def_id), segment_ident), diff --git a/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr index c9b49e9ed2b25..8cc48b64e79fe 100644 --- a/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr +++ b/tests/ui/cast/dyn-any-to-fn-with-missing-generics.stderr @@ -2,11 +2,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/dyn-any-to-fn-with-missing-generics.rs:9:39 | LL | println!("{:?}",(vfnfer[0] as dyn Fn)(3)); - | ^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | println!("{:?}",(vfnfer[0] as dyn Fn() -> ())(3)); + | ++++++++ error[E0107]: missing generics for trait `Fn` --> $DIR/dyn-any-to-fn-with-missing-generics.rs:9:39 diff --git a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr index ffa58f4faeeee..6cec3ea88d515 100644 --- a/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr +++ b/tests/ui/impl-trait/opaque-used-in-extraneous-argument.stderr @@ -37,22 +37,32 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/opaque-used-in-extraneous-argument.rs:5:19 | LL | fn frob() -> impl Fn + '_ {} - | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(P) -> T` + | ^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - fn frob() -> impl Fn + '_ {} +LL + fn frob() -> impl Fn(P) -> T + '_ {} + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/opaque-used-in-extraneous-argument.rs:5:19 | LL | fn frob() -> impl Fn + '_ {} - | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(P) -> T` + | ^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use parenthetical notation instead + | +LL - fn frob() -> impl Fn + '_ {} +LL + fn frob() -> impl Fn(P) -> T + '_ {} + | error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/opaque-used-in-extraneous-argument.rs:17:20 diff --git a/tests/ui/lint/future-incompatible-lint-group.stderr b/tests/ui/lint/future-incompatible-lint-group.stderr index 8f234c6216065..353009dd2a93b 100644 --- a/tests/ui/lint/future-incompatible-lint-group.stderr +++ b/tests/ui/lint/future-incompatible-lint-group.stderr @@ -12,7 +12,7 @@ error: ambiguous associated item --> $DIR/future-incompatible-lint-group.rs:19:17 | LL | fn foo() -> Self::V { 0 } - | ^^^^^^^ help: use fully-qualified syntax: `::V` + | ^^^^^^^ | note: `V` could refer to the variant defined here --> $DIR/future-incompatible-lint-group.rs:8:10 @@ -32,6 +32,11 @@ note: the lint level is defined here LL | #![deny(future_incompatible)] | ^^^^^^^^^^^^^^^^^^^ = note: `#[deny(ambiguous_associated_items)]` implied by `#[deny(future_incompatible)]` +help: use fully-qualified syntax + | +LL - fn foo() -> Self::V { 0 } +LL + fn foo() -> ::V { 0 } + | error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/suggestions/fn-trait-notation.stderr b/tests/ui/suggestions/fn-trait-notation.stderr index ef7d5fe362820..37cfcf3b8b5f8 100644 --- a/tests/ui/suggestions/fn-trait-notation.stderr +++ b/tests/ui/suggestions/fn-trait-notation.stderr @@ -2,31 +2,46 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/fn-trait-notation.rs:4:8 | LL | F: Fn, - | ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | ^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - F: Fn, +LL + F: Fn(i32) -> i32, + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/fn-trait-notation.rs:6:8 | LL | G: Fn<(i32, i32, ), Output = (i32, i32)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - G: Fn<(i32, i32, ), Output = (i32, i32)>, +LL + G: Fn(i32, i32) -> (i32, i32), + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/fn-trait-notation.rs:7:8 | LL | H: Fn<(i32,), Output = i32>, - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32` + | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - H: Fn<(i32,), Output = i32>, +LL + H: Fn(i32) -> i32, + | error[E0059]: type parameter to bare `Fn` trait must be a tuple --> $DIR/fn-trait-notation.rs:4:8 diff --git a/tests/ui/traits/next-solver/assertion-left-right-goal.stderr b/tests/ui/traits/next-solver/assertion-left-right-goal.stderr index 40986169b177b..e714a969df07b 100644 --- a/tests/ui/traits/next-solver/assertion-left-right-goal.stderr +++ b/tests/ui/traits/next-solver/assertion-left-right-goal.stderr @@ -2,44 +2,64 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/assertion-left-right-goal.rs:6:28 | LL | async fn new() -> impl Fn<()> { - | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - async fn new() -> impl Fn<()> { +LL + async fn new() -> impl Fn() -> () { + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/assertion-left-right-goal.rs:6:28 | LL | async fn new() -> impl Fn<()> { - | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use parenthetical notation instead + | +LL - async fn new() -> impl Fn<()> { +LL + async fn new() -> impl Fn() -> () { + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/assertion-left-right-goal.rs:6:28 | LL | async fn new() -> impl Fn<()> { - | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use parenthetical notation instead + | +LL - async fn new() -> impl Fn<()> { +LL + async fn new() -> impl Fn() -> () { + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/assertion-left-right-goal.rs:6:28 | LL | async fn new() -> impl Fn<()> { - | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: use parenthetical notation instead + | +LL - async fn new() -> impl Fn<()> { +LL + async fn new() -> impl Fn() -> () { + | error[E0308]: mismatched types --> $DIR/assertion-left-right-goal.rs:6:35 diff --git a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr index 918d05b5d6781..1cb7b9df6ff7b 100644 --- a/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr +++ b/tests/ui/type-alias-enum-variants/enum-variant-priority-lint-ambiguous_associated_items.stderr @@ -2,7 +2,7 @@ error: ambiguous associated item --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:32:15 | LL | fn f() -> Self::V { 0 } - | ^^^^^^^ help: use fully-qualified syntax: `::V` + | ^^^^^^^ | note: `V` could refer to the variant defined here --> $DIR/enum-variant-priority-lint-ambiguous_associated_items.rs:22:5 @@ -17,6 +17,11 @@ LL | type V; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #57644 = note: `#[deny(ambiguous_associated_items)]` (part of `#[deny(future_incompatible)]`) on by default +help: use fully-qualified syntax + | +LL - fn f() -> Self::V { 0 } +LL + fn f() -> ::V { 0 } + | error: aborting due to 1 previous error diff --git a/tests/ui/unboxed-closures/missing-fn-trait-args-issue-136407.feature_disabled.stderr b/tests/ui/unboxed-closures/missing-fn-trait-args-issue-136407.feature_disabled.stderr index 2a62cdfec2566..33b304d63e4bb 100644 --- a/tests/ui/unboxed-closures/missing-fn-trait-args-issue-136407.feature_disabled.stderr +++ b/tests/ui/unboxed-closures/missing-fn-trait-args-issue-136407.feature_disabled.stderr @@ -2,11 +2,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:9:18 | LL | pub fn shared() {} - | ^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn shared ()>() {} + | ++++++++ error[E0107]: missing generics for trait `Fn` --> $DIR/missing-fn-trait-args-issue-136407.rs:9:18 @@ -18,11 +22,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:13:19 | LL | pub fn mutable() {} - | ^^^^^ help: use parenthetical notation instead: `FnMut() -> ()` + | ^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn mutable ()>() {} + | ++++++++ error[E0107]: missing generics for trait `FnMut` --> $DIR/missing-fn-trait-args-issue-136407.rs:13:19 @@ -34,11 +42,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:17:16 | LL | pub fn once() {} - | ^^^^^^ help: use parenthetical notation instead: `FnOnce() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn once ()>() {} + | ++++++++ error[E0107]: missing generics for trait `FnOnce` --> $DIR/missing-fn-trait-args-issue-136407.rs:17:16 @@ -50,11 +62,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:21:24 | LL | pub fn async_shared() {} - | ^^^^^^^ help: use parenthetical notation instead: `AsyncFn() -> ()` + | ^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn async_shared ()>() {} + | ++++++++ error[E0107]: missing generics for trait `AsyncFn` --> $DIR/missing-fn-trait-args-issue-136407.rs:21:24 @@ -66,11 +82,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:25:25 | LL | pub fn async_mutable() {} - | ^^^^^^^^^^ help: use parenthetical notation instead: `AsyncFnMut() -> ()` + | ^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn async_mutable ()>() {} + | ++++++++ error[E0107]: missing generics for trait `AsyncFnMut` --> $DIR/missing-fn-trait-args-issue-136407.rs:25:25 @@ -82,11 +102,15 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:29:22 | LL | pub fn async_once() {} - | ^^^^^^^^^^^ help: use parenthetical notation instead: `AsyncFnOnce() -> ()` + | ^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL | pub fn async_once ()>() {} + | ++++++++ error[E0107]: missing generics for trait `AsyncFnOnce` --> $DIR/missing-fn-trait-args-issue-136407.rs:29:22 @@ -98,11 +122,16 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/missing-fn-trait-args-issue-136407.rs:33:23 | LL | pub fn with_output>() {} - | ^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - pub fn with_output>() {} +LL + pub fn with_output ()>() {} + | error[E0107]: trait takes 1 generic argument but 0 generic arguments were supplied --> $DIR/missing-fn-trait-args-issue-136407.rs:33:23 diff --git a/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr index e6f34d7e3b4b7..05f960dcf89a8 100644 --- a/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr +++ b/tests/ui/unboxed-closures/unboxed-closure-sugar-not-used-on-fn.stderr @@ -2,21 +2,31 @@ error[E0658]: the precise format of `Fn`-family traits' type parameters is subje --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:3:17 | LL | fn bar1(x: &dyn Fn<(), Output=()>) { - | ^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^^^^^^^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - fn bar1(x: &dyn Fn<(), Output=()>) { +LL + fn bar1(x: &dyn Fn() -> ()) { + | error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change --> $DIR/unboxed-closure-sugar-not-used-on-fn.rs:7:28 | LL | fn bar2(x: &T) where T: Fn<()> { - | ^^^^^^ help: use parenthetical notation instead: `Fn() -> ()` + | ^^^^^^ | = note: see issue #29625 for more information = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +help: use parenthetical notation instead + | +LL - fn bar2(x: &T) where T: Fn<()> { +LL + fn bar2(x: &T) where T: Fn() -> () { + | error: aborting due to 2 previous errors From 5e741954380afd1218d1a840a629ab87366db61e Mon Sep 17 00:00:00 2001 From: jackh726 Date: Sat, 19 Sep 2026 16:06:04 +0000 Subject: [PATCH 0417/1309] Use IndexVec for logical_edges and switch visited.contains for visited.insert --- .../rustc_borrowck/src/polonius/constraints.rs | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 637068a9799d7..7b6ec1d2f2920 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,4 +1,5 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_index::IndexVec; use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::RegionVid; @@ -47,7 +48,7 @@ pub(super) struct LocalizedConstraintGraph { /// The logical edges representing the outlives constraints that hold at all points in the CFG, /// which we don't localize to avoid creating a lot of unnecessary edges in the graph. Some CFGs /// can be big, and we don't need to create such a physical edge for every point in the CFG. - logical_edges: FxHashMap>, + logical_edges: IndexVec>, } /// The visitor interface when traversing a `LocalizedConstraintGraph`. @@ -68,14 +69,13 @@ impl LocalizedConstraintGraph { outlives_constraints: impl Iterator>, ) -> Self { let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); - let mut logical_edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); + let mut logical_edges: IndexVec<_, FxIndexSet<_>> = IndexVec::new(); for outlives_constraint in outlives_constraints { match outlives_constraint.locations { Locations::All(_) => { logical_edges - .entry(outlives_constraint.sup) - .or_default() + .ensure_contains_elem(outlives_constraint.sup, FxIndexSet::default) .insert(outlives_constraint.sub); } @@ -118,13 +118,10 @@ impl LocalizedConstraintGraph { region: loan.region, point: liveness.point_from_location(loan.reserve_location), }; + visited.insert(start_node); stack.push(start_node); while let Some(node) = stack.pop() { - if !visited.insert(node) { - continue; - } - // We've reached a node we haven't visited before. let location = liveness.location_from_point(node.point); visitor.on_node_traversed(loan_idx, node); @@ -133,7 +130,7 @@ impl LocalizedConstraintGraph { // - visit it eventually, // - and let the generic visitor know about it. let mut successor_found = |succ| { - if !visited.contains(&succ) { + if visited.insert(succ) { stack.push(succ); visitor.on_successor_discovered(node, succ); } @@ -228,7 +225,8 @@ impl LocalizedConstraintGraph { } // And finally, we have the logical edges, materialized at this point. - for &logical_succ in self.logical_edges.get(&node.region).into_flat_iter() { + let logical_succs = self.logical_edges.get(node.region); + for &logical_succ in logical_succs.into_flat_iter() { let succ = LocalizedNode { region: logical_succ, point: node.point }; successor_found(succ); } From c690179ad0d064270600ebb670a16a6d24194279 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Sat, 19 Sep 2026 16:20:46 +0000 Subject: [PATCH 0418/1309] Inline compute_forward_successor and compute_backward_successor. --- .../src/polonius/constraints.rs | 215 ++++++------------ 1 file changed, 72 insertions(+), 143 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 7b6ec1d2f2920..4989b87845a31 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,10 +1,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_index::IndexVec; -use rustc_index::interval::SparseIntervalMatrix; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::RegionVid; use rustc_mir_dataflow::points::PointIndex; -use tracing::debug; use crate::BorrowSet; use crate::constraints::OutlivesConstraint; @@ -145,6 +143,23 @@ impl LocalizedConstraintGraph { // Universal regions propagate loans along the CFG, i.e. forwards only. let is_universal_region = universal_regions.is_universal_region(node.region); + // Note: there currently are cases related to promoted and const generics, where we don't yet + // have variance information (possibly about temporary regions created when typeck sanitizes the + // promoteds). Until that is done, we conservatively fallback to maximizing reachability by + // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus + // propagate liveness when needed. + // + // FIXME: add the missing variance information and remove this fallback bidirectional edge. + let liveness_direction = if is_universal_region { + ConstraintDirection::Forward + } else { + live_region_variances + .get(node.region) + .copied() + .flatten() + .unwrap_or(ConstraintDirection::Bidirectional) + }; + // The physical edges present at this node are: // // 1. the typeck edges that flow from region to region *at this point*. @@ -155,52 +170,66 @@ impl LocalizedConstraintGraph { // 2a. the liveness edges that flow *forward*, from this node's point to its // successors in the CFG. - if body[location.block].statements.get(location.statement_index).is_some() { - // Intra-block edges, straight line constraints from each point to its successor - // within the same block. - let next_point = node.point + 1; - if let Some(succ) = compute_forward_successor( - node.region, - next_point, - live_regions, - live_region_variances, - is_universal_region, - ) { - successor_found(succ); - } - } else { - // Inter-block edges, from the block's terminator to each successor block's - // entry point. - for successor_block in body[location.block].terminator().successors() { - let next_location = Location { block: successor_block, statement_index: 0 }; - let next_point = liveness.point_from_location(next_location); - if let Some(succ) = compute_forward_successor( - node.region, - next_point, - live_regions, - live_region_variances, - is_universal_region, - ) { - successor_found(succ); + // + // - for covariant cases: loans flow in the regular direction, from the current point + // to the next point. + // - for invariant cases, loans can flow in both directions, but here we're only + // interested in the forward path of the bidirectional edge. + // + // We still need to check liveness for each next point though. + if matches!( + liveness_direction, + ConstraintDirection::Forward | ConstraintDirection::Bidirectional + ) { + if body[location.block].statements.get(location.statement_index).is_some() { + // Intra-block edges, straight line constraints from each point to its successor + // within the same block. + let next_point = node.point + 1; + if live_regions.contains(node.region, next_point) { + successor_found(LocalizedNode { + region: node.region, + point: next_point, + }); + } + } else { + // Inter-block edges, from the block's terminator to each successor block's + // entry point. + for successor_block in body[location.block].terminator().successors() { + let next_location = + Location { block: successor_block, statement_index: 0 }; + let next_point = liveness.point_from_location(next_location); + if live_regions.contains(node.region, next_point) { + successor_found(LocalizedNode { + region: node.region, + point: next_point, + }); + } } } } // 2b. the liveness edges that flow *backward*, from this node's point to its // predecessors in the CFG. - if !is_universal_region { + // + // - for contravariant cases: loans flow in the inverse direction, from the current + // point to the previous point. + // - for invariant cases, loans can flow in both directions, but here we only + // want the backward path of the bidirectional edge. + // + // Liveness flows into the regions live at the next point. So, in a backwards view, we'll link + // the region from the current point, if it's live there, to the previous point. + if matches!( + liveness_direction, + ConstraintDirection::Backward | ConstraintDirection::Bidirectional + ) && live_regions.contains(node.region, node.point) + { if location.statement_index > 0 { // Backward edges to the predecessor point in the same block. let previous_point = PointIndex::from(node.point.as_usize() - 1); - if let Some(succ) = compute_backward_successor( - node.region, - node.point, - previous_point, - live_regions, - live_region_variances, - ) { - successor_found(succ); - } + successor_found(LocalizedNode { + region: node.region, + point: previous_point, + }); } else { // Backward edges from the block entry point to the terminator of the // predecessor blocks. @@ -211,15 +240,10 @@ impl LocalizedConstraintGraph { statement_index: body[pred_block].statements.len(), }; let previous_point = liveness.point_from_location(previous_location); - if let Some(succ) = compute_backward_successor( - node.region, - node.point, - previous_point, - live_regions, - live_region_variances, - ) { - successor_found(succ); - } + successor_found(LocalizedNode { + region: node.region, + point: previous_point, + }); } } } @@ -234,98 +258,3 @@ impl LocalizedConstraintGraph { } } } - -/// Returns the successor for the current region/point node when propagating a loan through forward -/// edges, if applicable, according to liveness and variance. -fn compute_forward_successor( - region: RegionVid, - next_point: PointIndex, - live_regions: &SparseIntervalMatrix, - live_region_variances: &LiveRegionVariances, - is_universal_region: bool, -) -> Option { - // 1. Universal regions are semantically live at all points. - if is_universal_region { - let succ = LocalizedNode { region, point: next_point }; - return Some(succ); - } - - // 2. Otherwise, gather the edges due to explicit region liveness, when applicable. - if !live_regions.contains(region, next_point) { - debug!(?region, ?next_point, "region isn't live at successor"); - return None; - } - - // Here, `region` could be live at the current point, and is live at the next point: add a - // constraint between them, according to variance. - - // Note: there currently are cases related to promoted and const generics, where we don't yet - // have variance information (possibly about temporary regions created when typeck sanitizes the - // promoteds). Until that is done, we conservatively fallback to maximizing reachability by - // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus - // propagate liveness when needed. - // - // FIXME: add the missing variance information and remove this fallback bidirectional edge. - let direction = live_region_variances - .get(region) - .copied() - .flatten() - .unwrap_or(ConstraintDirection::Bidirectional); - - debug!(?direction); - - match direction { - ConstraintDirection::Backward => { - // Contravariant cases: loans flow in the inverse direction, but we're only interested - // in forward successors and there are none here. - None - } - ConstraintDirection::Forward | ConstraintDirection::Bidirectional => { - // 1. For covariant cases: loans flow in the regular direction, from the current point - // to the next point. - // 2. For invariant cases, loans can flow in both directions, but here as well, we only - // want the forward path of the bidirectional edge. - Some(LocalizedNode { region, point: next_point }) - } - } -} - -/// Returns the successor for the current region/point node when propagating a loan through backward -/// edges, if applicable, according to liveness and variance. -fn compute_backward_successor( - region: RegionVid, - current_point: PointIndex, - previous_point: PointIndex, - live_regions: &SparseIntervalMatrix, - live_region_variances: &LiveRegionVariances, -) -> Option { - // Liveness flows into the regions live at the next point. So, in a backwards view, we'll link - // the region from the current point, if it's live there, to the previous point. - if !live_regions.contains(region, current_point) { - debug!(?region, ?current_point, "region isn't live at current point"); - return None; - } - - // FIXME: add the missing variance information and remove this fallback bidirectional edge. See - // the same comment in `compute_forward_successor`. - let direction = live_region_variances - .get(region) - .copied() - .flatten() - .unwrap_or(ConstraintDirection::Bidirectional); - - match direction { - ConstraintDirection::Forward => { - // Covariant cases: loans flow in the regular direction, but we're only interested in - // backward successors and there are none here. - None - } - ConstraintDirection::Backward | ConstraintDirection::Bidirectional => { - // 1. For contravariant cases: loans flow in the inverse direction, from the current - // point to the previous point. - // 2. For invariant cases, loans can flow in both directions, but here as well, we only - // want the backward path of the bidirectional edge. - Some(LocalizedNode { region, point: previous_point }) - } - } -} From 26ae3049185625d1c1b584920e4197fbaddc89ef Mon Sep 17 00:00:00 2001 From: Jason Newcomb Date: Thu, 17 Sep 2026 12:53:02 -0400 Subject: [PATCH 0419/1309] Don't suggest `Box::leak` in `nonnull_unchecked_on_box_ptr` as unleaking isn't well defined. --- .../src/nonnull_unchecked_on_box_ptr.rs | 20 +++----- clippy_utils/src/msrvs.rs | 1 + tests/ui/nonnull_unchecked_on_box_ptr.fixed | 48 ++++++++----------- tests/ui/nonnull_unchecked_on_box_ptr.rs | 17 ++----- tests/ui/nonnull_unchecked_on_box_ptr.stderr | 46 +++++++----------- 5 files changed, 51 insertions(+), 81 deletions(-) diff --git a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs index 53bc4e08abc5c..9263d0940a890 100644 --- a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs +++ b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs @@ -12,10 +12,11 @@ use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; declare_clippy_lint! { /// ### What it does - /// Checks for unsafe usage of `NonNull::new_unchecked(Box::into_raw(x))`, and suggests calling `NonNull::from_mut(Box::leak(x))` instead. + /// Checks for uses of `NonNull::new_unchecked(Box::into_raw(x))`. /// /// ### Why is this bad? - /// `NonNull::new_unchecked` is an unsafe function, which we don't need to call at all if we can instead use a mutable reference. + /// `NonNull::new_unchecked` is an unsafe function with a safe alternative when coming + /// from a `Box`. /// /// ### Example /// ```no_run @@ -27,12 +28,12 @@ declare_clippy_lint! { /// ```no_run /// use std::ptr::NonNull; /// let one = Box::new(1); - /// let ptr = NonNull::from_mut(Box::leak(one)); + /// let ptr = Box::into_non_null(one); /// ``` #[clippy::version = "1.98.0"] pub NONNULL_UNCHECKED_ON_BOX_PTR, complexity, - "using `NonNull::new_unchecked` with `Box::into_raw`, while `NonNull::from_mut` with `Box::leak` can be used instead" + "checks for uses of `NonNull::new_unchecked` with `Box::into_raw`" } impl_lint_pass!(NonnullUncheckedOnBoxPtr => [NONNULL_UNCHECKED_ON_BOX_PTR]); @@ -62,7 +63,7 @@ impl<'tcx> LateLintPass<'tcx> for NonnullUncheckedOnBoxPtr { .opt_parent(cx) .opt_impl_ty(cx) .is_lang_item(cx, LangItem::OwnedBox) - && self.msrv.meets(cx, msrvs::BOX_LEAK) + && self.msrv.meets(cx, msrvs::BOX_INTO_NON_NULL) { let ctxt = expr.span.ctxt(); let span = match cx.tcx.parent_hir_node(expr.hir_id) { @@ -83,14 +84,7 @@ impl<'tcx> LateLintPass<'tcx> for NonnullUncheckedOnBoxPtr { |diag| { let mut app = Applicability::MachineApplicable; let arg_name = snippet_with_context(cx, arg.span, ctxt, "_", &mut app).0; - - let sugg = if self.msrv.meets(cx, msrvs::NONNULL_FROM_MUT) { - format!("NonNull::from_mut(Box::leak({arg_name}))") - } else { - format!("NonNull::from(Box::leak({arg_name}))") - }; - - diag.span_suggestion(span, "try", sugg, app); + diag.span_suggestion(span, "try", format!("Box::into_non_null({arg_name})"), app); }, ); } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5f30692a677af..4f1d3fa00b08d 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -25,6 +25,7 @@ macro_rules! msrv_aliases { // names may refer to stabilized feature flags or library items msrv_aliases! { + 1,99,0 { BOX_INTO_NON_NULL } 1,98,0 { MAP_OR_DEFAULT } 1,97,0 { ISOLATE_LOWEST_ONE, BIT_WIDTH } 1,94,0 { EULER_GAMMA, GOLDEN_RATIO, MUL_ADD_CONST } diff --git a/tests/ui/nonnull_unchecked_on_box_ptr.fixed b/tests/ui/nonnull_unchecked_on_box_ptr.fixed index 746bd29764dc1..1cdeb942ecadc 100644 --- a/tests/ui/nonnull_unchecked_on_box_ptr.fixed +++ b/tests/ui/nonnull_unchecked_on_box_ptr.fixed @@ -32,78 +32,78 @@ unsafe fn unsafe_identity(x: T) -> T { fn lint() { fn basic() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(identity(one))); + let _ = Box::into_non_null(identity(one)); } fn qualifiers() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); { use Box as Box2; use NonNull as NonNull2; let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } { type Box2 = Box; type NonNull2 = NonNull; let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } } fn macros() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = identity!(NonNull::from_mut(Box::leak(one))); + let _ = identity!(Box::into_non_null(one)); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(weird!(one))); + let _ = Box::into_non_null(weird!(one)); } fn keep_unsafe_block() { let one = Box::new(1); let _ = unsafe { - NonNull::from_mut(Box::leak(unsafe_identity(one))) + Box::into_non_null(unsafe_identity(one)) //~^ nonnull_unchecked_on_box_ptr }; let one = Box::new(1); let _ = unsafe { - identity(NonNull::from_mut(Box::leak(one))) + identity(Box::into_non_null(one)) //~^ nonnull_unchecked_on_box_ptr }; let one = Box::new(1); let _ = unsafe { - unsafe_identity(NonNull::from_mut(Box::leak(one))) + unsafe_identity(Box::into_non_null(one)) //~^ nonnull_unchecked_on_box_ptr }; let _ = unsafe { - NonNull::from_mut(Box::leak(Box::new(std::num::NonZeroI32::new_unchecked(1)))) + Box::into_non_null(Box::new(std::num::NonZeroI32::new_unchecked(1))) //~^ nonnull_unchecked_on_box_ptr }; let _ = unsafe { let one = Box::new(1); - NonNull::from_mut(Box::leak(one)) + Box::into_non_null(one) //~^ nonnull_unchecked_on_box_ptr }; } @@ -135,22 +135,16 @@ fn no_lint() { } } -#[clippy::msrv = "1.25"] -fn msrv_1_25() { +#[clippy::msrv = "1.98"] +fn msrv_1_98() { let one = Box::new(1); let _ = unsafe { NonNull::new_unchecked(Box::into_raw(one)) }; } -#[clippy::msrv = "1.26"] -fn msrv_1_26() { - let one = Box::new(1); - let _ = NonNull::from(Box::leak(one)); -} - -#[clippy::msrv = "1.89"] -fn msrv_1_89() { +#[clippy::msrv = "1.99"] +fn msrv_1_99() { let one = Box::new(1); - let _ = NonNull::from_mut(Box::leak(one)); + let _ = Box::into_non_null(one); } fn main() {} diff --git a/tests/ui/nonnull_unchecked_on_box_ptr.rs b/tests/ui/nonnull_unchecked_on_box_ptr.rs index 2acc5c9270c88..a78a953ff7f38 100644 --- a/tests/ui/nonnull_unchecked_on_box_ptr.rs +++ b/tests/ui/nonnull_unchecked_on_box_ptr.rs @@ -168,23 +168,14 @@ fn no_lint() { } } -#[clippy::msrv = "1.25"] -fn msrv_1_25() { +#[clippy::msrv = "1.98"] +fn msrv_1_98() { let one = Box::new(1); let _ = unsafe { NonNull::new_unchecked(Box::into_raw(one)) }; } -#[clippy::msrv = "1.26"] -fn msrv_1_26() { - let one = Box::new(1); - let _ = unsafe { - //~^ nonnull_unchecked_on_box_ptr - NonNull::new_unchecked(Box::into_raw(one)) - }; -} - -#[clippy::msrv = "1.89"] -fn msrv_1_89() { +#[clippy::msrv = "1.99"] +fn msrv_1_99() { let one = Box::new(1); let _ = unsafe { //~^ nonnull_unchecked_on_box_ptr diff --git a/tests/ui/nonnull_unchecked_on_box_ptr.stderr b/tests/ui/nonnull_unchecked_on_box_ptr.stderr index 8d26914cde7b0..9e452143bfa53 100644 --- a/tests/ui/nonnull_unchecked_on_box_ptr.stderr +++ b/tests/ui/nonnull_unchecked_on_box_ptr.stderr @@ -6,7 +6,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` | = note: `-D clippy::nonnull-unchecked-on-box-ptr` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::nonnull_unchecked_on_box_ptr)]` @@ -19,7 +19,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(identity(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(identity(one)))` + | |_________^ help: try: `Box::into_non_null(identity(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:49:17 @@ -29,7 +29,7 @@ LL | let _ = unsafe { LL | | LL | | std::ptr::NonNull::new_unchecked(std::boxed::Box::into_raw(one)) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:58:21 @@ -39,7 +39,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull2::new_unchecked(Box2::into_raw(one)) LL | | }; - | |_____________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_____________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:68:21 @@ -49,7 +49,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull2::new_unchecked(Box2::into_raw(one)) LL | | }; - | |_____________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_____________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:77:17 @@ -59,7 +59,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(identity!(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:83:27 @@ -69,7 +69,7 @@ LL | let _ = identity!(unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }); - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:89:17 @@ -79,7 +79,7 @@ LL | let _ = unsafe { LL | | LL | | identity!(NonNull::new_unchecked(Box::into_raw(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:95:17 @@ -89,7 +89,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(identity!(Box::into_raw(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:101:17 @@ -99,7 +99,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(identity!(Box::into_raw(identity!(one)))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(one))` + | |_________^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:107:17 @@ -109,37 +109,37 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(weird!(one))) LL | | }; - | |_________^ help: try: `NonNull::from_mut(Box::leak(weird!(one)))` + | |_________^ help: try: `Box::into_non_null(weird!(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:116:13 | LL | NonNull::new_unchecked(Box::into_raw(unsafe_identity(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(unsafe_identity(one)))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(unsafe_identity(one))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:122:22 | LL | identity(NonNull::new_unchecked(Box::into_raw(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:128:29 | LL | unsafe_identity(NonNull::new_unchecked(Box::into_raw(one))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:133:13 | LL | NonNull::new_unchecked(Box::into_raw(Box::new(std::num::NonZeroI32::new_unchecked(1)))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(Box::new(std::num::NonZeroI32::new_unchecked(1))))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(Box::new(std::num::NonZeroI32::new_unchecked(1)))` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:139:13 | LL | NonNull::new_unchecked(Box::into_raw(one)) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `NonNull::from_mut(Box::leak(one))` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `Box::into_non_null(one)` error: use of `NonNull::new_unchecked` with `Box::into_raw` --> tests/ui/nonnull_unchecked_on_box_ptr.rs:180:13 @@ -149,17 +149,7 @@ LL | let _ = unsafe { LL | | LL | | NonNull::new_unchecked(Box::into_raw(one)) LL | | }; - | |_____^ help: try: `NonNull::from(Box::leak(one))` + | |_____^ help: try: `Box::into_non_null(one)` -error: use of `NonNull::new_unchecked` with `Box::into_raw` - --> tests/ui/nonnull_unchecked_on_box_ptr.rs:189:13 - | -LL | let _ = unsafe { - | _____________^ -LL | | -LL | | NonNull::new_unchecked(Box::into_raw(one)) -LL | | }; - | |_____^ help: try: `NonNull::from_mut(Box::leak(one))` - -error: aborting due to 18 previous errors +error: aborting due to 17 previous errors From 9c1bd2de3001dcc0a4bbea6424951c8d6f84b7a3 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 09:01:30 -0500 Subject: [PATCH 0420/1309] Add mod_id to TypeckRootCtxt Use ModId more for visibility checks from TypeckRootCtxt. This just simplifies things a bit and adds consistency. --- compiler/rustc_hir_typeck/src/expr.rs | 39 +++++++------------ .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- .../src/fn_ctxt/suggestions.rs | 9 +---- .../rustc_hir_typeck/src/method/suggest.rs | 13 +------ compiler/rustc_hir_typeck/src/pat.rs | 4 +- .../rustc_hir_typeck/src/typeck_root_ctxt.rs | 7 +++- 6 files changed, 26 insertions(+), 48 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a8898acf3a415..e8eca56bc92d1 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2240,9 +2240,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let private_fields: Vec<&ty::FieldDef> = variant .fields .iter() - .filter(|field| { - !field.vis.is_accessible_from(tcx.parent_module(expr.hir_id), tcx) - }) + .filter(|field| !field.vis.is_accessible_from(self.mod_id, tcx)) .collect(); if !private_fields.is_empty() { @@ -2714,7 +2712,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .iter() .filter(|field| { skip_fields.iter().all(|&skip| skip.ident.name != field.name) - && self.is_field_suggestable(field, expr.hir_id, expr.span) + && self.is_field_suggestable(field, expr.span) }) .map(|field| field.name) .collect() @@ -3269,7 +3267,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } // try to add a suggestion in case the field is a nested field of a field of the Adt - let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); let (ty, unwrap) = if let ty::Adt(def, args) = base_ty.kind() && (self.tcx.is_diagnostic_item(sym::Result, def.did()) || self.tcx.is_diagnostic_item(sym::Option, def.did())) @@ -3280,9 +3277,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { (base_ty, "") }; - for found_fields in - self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, expr.hir_id) - { + for found_fields in self.get_field_candidates_considering_privacy_for_diag(span, ty) { let field_names = found_fields.iter().map(|field| field.0.name).collect::>(); let mut candidate_fields: Vec<_> = found_fields .into_iter() @@ -3292,8 +3287,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &|candidate_field, _| candidate_field == field, candidate_field, vec![], - mod_id, - expr.hir_id, ) }) .map(|mut field_path| { @@ -3354,8 +3347,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, span: Span, base_ty: Ty<'tcx>, - mod_id: DefId, - hir_id: HirId, ) -> Vec)>> { debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty); @@ -3379,15 +3370,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Some struct, e.g. some that impl `Deref`, have all private fields // because you're expected to deref them to access the _real_ fields. // This, for example, will help us suggest accessing a field through a `Box`. - if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) { + if fields + .iter() + .all(|field| !field.vis.is_accessible_from(self.mod_id, tcx)) + { return None; } return Some( fields .iter() .filter(move |field| { - field.vis.is_accessible_from(mod_id, tcx) - && self.is_field_suggestable(field, hir_id, span) + field.vis.is_accessible_from(self.mod_id, tcx) + && self.is_field_suggestable(field, span) }) // For compile-time reasons put a limit on number of fields we search .take(100) @@ -3419,15 +3413,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// This method is called after we have encountered a missing field error to recursively /// search for the field - #[instrument(skip(self, matches, mod_id, hir_id), level = "debug")] + #[instrument(skip(self, matches), level = "debug")] pub(crate) fn check_for_nested_field_satisfying_condition_for_diag( &self, span: Span, matches: &impl Fn(Ident, Ty<'tcx>) -> bool, (candidate_name, candidate_ty): (Ident, Ty<'tcx>), mut field_path: Vec, - mod_id: DefId, - hir_id: HirId, ) -> Option> { if field_path.len() > 3 { // For compile-time reasons and to avoid infinite recursion we only check for fields @@ -3438,12 +3430,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if matches(candidate_name, candidate_ty) { return Some(field_path); } - for nested_fields in self.get_field_candidates_considering_privacy_for_diag( - span, - candidate_ty, - mod_id, - hir_id, - ) { + for nested_fields in + self.get_field_candidates_considering_privacy_for_diag(span, candidate_ty) + { // recursively search fields of `candidate_field` if it's a ty::Adt for field in nested_fields { if let Some(field_path) = self.check_for_nested_field_satisfying_condition_for_diag( @@ -3451,8 +3440,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { matches, field, field_path.clone(), - mod_id, - hir_id, ) { return Some(field_path); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index e655e0857d858..1aac339a29ee0 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -1238,7 +1238,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ctor_kind, ctor_def_id) = adt_def.non_enum_variant().ctor.unwrap(); // Check the visibility of the ctor. let vis = tcx.visibility(ctor_def_id); - if !vis.is_accessible_from(tcx.parent_module(hir_id).to_def_id(), tcx) { + if !vis.is_accessible_from(self.mod_id, tcx) { self.dcx() .emit_err(CtorIsPrivate { span, def: tcx.def_path_str(adt_def.did()) }); } diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index ab8020a3182e0..8895faef0890f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2285,14 +2285,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - pub(crate) fn is_field_suggestable( - &self, - field: &ty::FieldDef, - hir_id: HirId, - span: Span, - ) -> bool { + pub(crate) fn is_field_suggestable(&self, field: &ty::FieldDef, span: Span) -> bool { // The field must be visible in the containing module. - field.vis.is_accessible_from(self.tcx.parent_module(hir_id), self.tcx) + field.vis.is_accessible_from(self.mod_id, self.tcx) // The field must not be unstable. && !matches!( self.tcx.eval_stability(field.did, None, rustc_span::DUMMY_SP, None), diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 545516f2e41a0..1627da52d7d0e 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -2836,8 +2836,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { _ => None, }); if let Some((field, field_ty)) = field_receiver { - let scope = tcx.parent_module_from_def_id(self.body_def_id); - let is_accessible = field.vis.is_accessible_from(scope, tcx); + let is_accessible = field.vis.is_accessible_from(self.mod_id, tcx); if is_accessible { if let Some((what, _, _)) = self.extract_callable_info(field_ty) { @@ -3199,13 +3198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return_type: Option>, ) { if let SelfSource::MethodCall(expr) = source { - let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id(); - for fields in self.get_field_candidates_considering_privacy_for_diag( - span, - actual, - mod_id, - expr.hir_id, - ) { + for fields in self.get_field_candidates_considering_privacy_for_diag(span, actual) { let call_expr = self.tcx.hir_expect_expr(self.tcx.parent_hir_id(expr.hir_id)); let lang_items = self.tcx.lang_items(); @@ -3240,8 +3233,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }, candidate_field, vec![], - mod_id, - expr.hir_id, ) }) .map(|field_path| { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..10046d90e9fab 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2163,7 +2163,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_unmentioned_fields: Vec<_> = unmentioned_fields .iter() .copied() - .filter(|(field, _)| self.is_field_suggestable(field, pat.hir_id, pat.span)) + .filter(|(field, _)| self.is_field_suggestable(field, pat.span)) .collect(); if !has_rest_pat { @@ -2336,7 +2336,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if let [(field_def, field)] = unmentioned_fields.as_slice() - && self.is_field_suggestable(field_def, pat.hir_id, pat.span) + && self.is_field_suggestable(field_def, pat.span) { let suggested_name = find_best_match_for_name(&[field.name], pat_field.ident.name, None); diff --git a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs index 37b753062c708..1c037cc2e2d7e 100644 --- a/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs +++ b/compiler/rustc_hir_typeck/src/typeck_root_ctxt.rs @@ -5,7 +5,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, HirId, HirIdMap}; use rustc_infer::infer::{InferCtxt, InferOk, OpaqueTypeStorageEntries, TyCtxtInferExt}; use rustc_middle::ty::{self, Ty, TyCtxt, TyVid, TypeVisitableExt, TypingMode}; -use rustc_span::def_id::LocalDefIdMap; +use rustc_span::def_id::{LocalDefIdMap, LocalModId}; use rustc_span::{Span, span_bug}; use rustc_trait_selection::traits::{self, FulfillmentEngine, FulfillmentError, TraitEngine}; use tracing::instrument; @@ -67,6 +67,9 @@ pub(crate) struct TypeckRootCtxt<'tcx> { /// we record that type variable here. This is later used to inform /// fallback. See the `fallback` module for details. pub(super) diverging_type_vars: RefCell>, + + /// Parent module + pub(super) mod_id: LocalModId, } impl<'tcx> Deref for TypeckRootCtxt<'tcx> { @@ -78,6 +81,7 @@ impl<'tcx> Deref for TypeckRootCtxt<'tcx> { impl<'tcx> TypeckRootCtxt<'tcx> { pub(crate) fn new(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> Self { + let mod_id = tcx.parent_module_from_def_id(def_id); let hir_owner = tcx.local_def_id_to_hir_id(def_id).owner; let infcx = tcx @@ -102,6 +106,7 @@ impl<'tcx> TypeckRootCtxt<'tcx> { deferred_asm_checks: RefCell::new(Vec::new()), deferred_repeat_expr_checks: RefCell::new(Vec::new()), diverging_type_vars: RefCell::new(Default::default()), + mod_id, } } From 06f21bf5fe782deca0739a9e37a463f326095078 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 11:30:20 -0500 Subject: [PATCH 0421/1309] Restrict Visibility methods to ModId We generally expect Visibility to have ModId or LocalModId, so it seems good to restrict the impls as such. There is just one error path needing adjustment to check that we actually have a ModId. It should be okay since, if it is not a module, an error will be emitted elsewhere. --- compiler/rustc_middle/src/ty/mod.rs | 16 ++++++++-------- compiler/rustc_resolve/src/lib.rs | 2 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index e23ce6b246f12..08c65bc11f2ff 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -428,19 +428,19 @@ impl Visibility { } } -impl> Visibility { - /// Returns `true` if an item with this visibility is accessible from the given module. - pub fn is_accessible_from(self, module: impl Into, tcx: TyCtxt<'_>) -> bool { +impl> Visibility { + /// Returns `true` if an item with this visibility is accessible from the given definition. + pub fn is_accessible_from(self, def_id: impl Into, tcx: TyCtxt<'_>) -> bool { match self { // Public items are visible everywhere. Visibility::Public => true, - Visibility::Restricted(id) => tcx.is_descendant_of(module, id), + Visibility::Restricted(id) => tcx.is_descendant_of(def_id, id.into()), } } pub fn partial_cmp( self, - vis: Visibility>, + vis: Visibility>, tcx: TyCtxt<'_>, ) -> Option { match (self, vis) { @@ -449,18 +449,18 @@ impl> Visibility { (Visibility::Restricted(_), Visibility::Public) => Some(Ordering::Less), (Visibility::Restricted(lhs_id), Visibility::Restricted(rhs_id)) => { let (lhs_id, rhs_id) = (lhs_id.into(), rhs_id.into()); - tcx.def_id_partial_cmp(lhs_id, rhs_id) + tcx.def_id_partial_cmp(lhs_id.to_def_id(), rhs_id.to_def_id()) } } } } -impl + Debug + Copy> Visibility { +impl + Debug + Copy> Visibility { /// Returns `true` if this visibility is strictly larger than the given visibility. #[track_caller] pub fn greater_than( self, - vis: Visibility + Debug + Copy>, + vis: Visibility + Debug + Copy>, tcx: TyCtxt<'_>, ) -> bool { match self.partial_cmp(vis, tcx) { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 87479a4fbedd0..e479ef6a621c9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -2431,7 +2431,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.pat_span_map.insert(node, span); } - fn is_accessible_from(&self, vis: Visibility>, module: Module<'ra>) -> bool { + fn is_accessible_from(&self, vis: Visibility>, module: Module<'ra>) -> bool { vis.is_accessible_from(module.nearest_parent_mod(), self.tcx) } From e710a600578f20128a6fa8c2a086bd618e6fbfc4 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 11:37:23 -0500 Subject: [PATCH 0422/1309] Prefer ModId in more places Especially in adjust_ident_and_get_scope and is_accessible_from. --- compiler/rustc_hir_analysis/src/collect.rs | 5 +++ .../src/hir_ty_lowering/errors.rs | 5 +-- .../src/hir_ty_lowering/mod.rs | 16 ++++---- compiler/rustc_hir_typeck/src/expr.rs | 16 +++----- compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs | 5 +++ compiler/rustc_hir_typeck/src/method/probe.rs | 3 +- .../rustc_hir_typeck/src/method/suggest.rs | 5 +-- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_privacy/src/lib.rs | 40 +++++-------------- .../src/error_reporting/traits/suggestions.rs | 2 +- 10 files changed, 43 insertions(+), 58 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index e581774747601..f1c330aaeed57 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -37,6 +37,7 @@ use rustc_middle::ty::{ self, AdtKind, Const, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, fold_regions, }; +use rustc_span::def_id::LocalModId; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, span_bug, sym}; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::infer::InferCtxtExt; @@ -497,6 +498,10 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { self.item_def_id } + fn mod_id(&self) -> LocalModId { + self.tcx.parent_module_from_def_id(self.item_def_id) + } + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { if let RegionInferReason::ObjectLifetimeDefault(sugg_sp) = reason { // FIXME: Account for trailing plus `dyn Trait+`, the need of parens in diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 2a3728573f31e..93608d16b246c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -199,8 +199,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .visible_traits() .filter(|trait_def_id| { let viz = tcx.visibility(*trait_def_id); - let def_id = self.item_def_id(); - viz.is_accessible_from(def_id, tcx) + viz.is_accessible_from(self.mod_id(), tcx) }) .collect(); @@ -568,7 +567,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { .map(|impl_def_id| tcx.impl_trait_header(impl_def_id)) .filter(|header| { // Consider only accessible traits - tcx.visibility(trait_def_id).is_accessible_from(self.item_def_id(), tcx) + tcx.visibility(trait_def_id).is_accessible_from(self.mod_id(), tcx) && header.polarity != ty::ImplPolarity::Negative }) .map(|header| header.trait_ref.instantiate_identity().skip_norm_wip().self_ty()) diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index ecfe5d3c2c7c2..309757aa66021 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -48,7 +48,7 @@ use rustc_middle::ty::{ const_lit_matches_ty, fold_regions, }; use rustc_session::diagnostics::feature_err; -use rustc_span::def_id::ModId; +use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::{DUMMY_SP, Ident, Span, bug, kw, span_bug, sym}; use rustc_trait_selection::infer::InferCtxtExt; use rustc_trait_selection::traits::{self, FulfillmentError}; @@ -142,6 +142,9 @@ pub trait HirTyLowerer<'tcx> { /// Returns the [`LocalDefId`] of the overarching item whose constituents get lowered. fn item_def_id(&self) -> LocalDefId; + /// Returns the containing module. + fn mod_id(&self) -> LocalModId; + /// Returns the region to use when a lifetime is omitted (and not elided). fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx>; @@ -1814,7 +1817,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ) -> Option<(ty::AssocItem, /*scope*/ ModId)> { let tcx = self.tcx(); - let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, self.item_def_id()); + let (ident, def_scope) = tcx.adjust_ident_and_get_scope(ident, scope, self.mod_id()); // We have already adjusted the item name above, so compare with `.normalize_to_macros_2_0()` // instead of calling `filter_by_name_and_kind` which would needlessly normalize the // `ident` again and again. @@ -1879,7 +1882,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) // Consider only accessible traits && tcx.visibility(*trait_def_id) - .is_accessible_from(self.item_def_id(), tcx) + .is_accessible_from(self.mod_id(), tcx) && tcx.all_impls(*trait_def_id) .any(|impl_def_id| { let header = tcx.impl_trait_header(impl_def_id); @@ -3424,7 +3427,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } hir::TyKind::FieldOf(ty, hir::TyFieldPath { variant, field }) => self.lower_field_of( self.lower_ty(ty), - self.item_def_id(), + self.mod_id(), ty.span, hir_ty.hir_id, *variant, @@ -3478,7 +3481,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { fn lower_field_of( &self, ty: Ty<'tcx>, - item_def_id: LocalDefId, + mod_id: LocalModId, ty_span: Span, hir_id: HirId, variant: Option, @@ -3528,8 +3531,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } (FIRST_VARIANT, def.non_enum_variant()) }; - let (ident, def_scope) = - tcx.adjust_ident_and_get_scope(field, def.did(), item_def_id); + let (ident, def_scope) = tcx.adjust_ident_and_get_scope(field, def.did(), mod_id); if let Some((field_idx, field)) = variant .fields .iter_enumerated() diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index e8eca56bc92d1..f33046c1561cb 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -2788,11 +2788,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Ty::new_error(self.tcx(), guar); } - let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope( - field, - base_def.did(), - self.body_def_id, - ); + let (ident, def_scope) = + self.tcx.adjust_ident_and_get_scope(field, base_def.did(), self.mod_id); if let Some((idx, field)) = self.find_adt_field(*base_def, ident) { self.write_field_index(expr.hir_id, idx); @@ -3851,11 +3848,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .emit(); break; }; - let (subident, sub_def_scope) = self.tcx.adjust_ident_and_get_scope( - subfield, - variant.def_id, - self.body_def_id, - ); + let (subident, sub_def_scope) = + self.tcx.adjust_ident_and_get_scope(subfield, variant.def_id, self.mod_id); let Some((subindex, field)) = variant .fields @@ -3906,7 +3900,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let (ident, def_scope) = self.tcx.adjust_ident_and_get_scope( field, container_def.did(), - self.body_def_id, + self.mod_id, ); let fields = &container_def.non_enum_variant().fields; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs index 3e2d35da5307d..b2b49dc06b7a6 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/mod.rs @@ -22,6 +22,7 @@ use rustc_middle::ty::{ self, CantBeErased, Const, Flags, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized, }; use rustc_session::Session; +use rustc_span::def_id::LocalModId; use rustc_span::{self, DUMMY_SP, ErrorGuaranteed, Ident, Span}; use rustc_trait_selection::error_reporting::TypeErrCtxt; use rustc_trait_selection::traits::{ @@ -239,6 +240,10 @@ impl<'tcx> HirTyLowerer<'tcx> for FnCtxt<'_, 'tcx> { self.body_def_id } + fn mod_id(&self) -> LocalModId { + self.mod_id + } + fn re_infer(&self, span: Span, reason: RegionInferReason<'_>) -> ty::Region<'tcx> { let v = match reason { RegionInferReason::Param(def) => { diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 02b3255e795ac..79b8ef15d7e13 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -859,8 +859,7 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { let is_accessible = if let Some(name) = self.method_name { let item = candidate.item; let container_id = item.container_id(self.tcx); - let def_scope = - self.tcx.adjust_ident_and_get_scope(name, container_id, self.body_def_id).1; + let def_scope = self.tcx.adjust_ident_and_get_scope(name, container_id, self.mod_id).1; item.visibility(self.tcx).is_accessible_from(def_scope, self.tcx) } else { true diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 1627da52d7d0e..bea91a9dc11b6 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -3982,11 +3982,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { { let parent_map = self.tcx.visible_parent_map(()); - let scope = self.tcx.parent_module_from_def_id(self.body_def_id); let (accessible_candidates, inaccessible_candidates): (Vec<_>, Vec<_>) = candidates.into_iter().partition(|id| { let vis = self.tcx.visibility(*id); - vis.is_accessible_from(scope, self.tcx) + vis.is_accessible_from(self.mod_id, self.tcx) // Visibility alone does not make `fn_name::Trait` an importable path. // We need to make sure all parent are modules, otherwise the path is not importable. && std::iter::successors(self.tcx.opt_parent(*id), |&id| self.tcx.opt_parent(id)) @@ -4044,7 +4043,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_sugg = sugg(accessible_candidates, true); let inaccessible_sugg = sugg(inaccessible_candidates, false); - let (module, _, _) = self.tcx.hir_get_module(scope); + let (module, _, _) = self.tcx.hir_get_module(self.mod_id); let span = module.spans.inject_use_span; handle_candidates(accessible_sugg, inaccessible_sugg, span); } diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 08c65bc11f2ff..94345380a544e 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -2183,13 +2183,13 @@ impl<'tcx> TyCtxt<'tcx> { self, mut ident: Ident, scope: DefId, - item_id: LocalDefId, + mod_id: LocalModId, ) -> (Ident, ModId) { let scope = ident .span .normalize_to_macros_2_0_and_adjust(self.expn_that_defined(scope)) .and_then(|actual_expansion| actual_expansion.expn_data().parent_module) - .unwrap_or_else(|| self.parent_module_from_def_id(item_id).to_mod_id()); + .unwrap_or(mod_id.to_mod_id()); (ident, scope) } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 8430b78d75f1b..97475c8fdccf0 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -922,6 +922,7 @@ impl<'a, 'tcx> TestReachabilityVisitor<'a, 'tcx> { /// This pass performs remaining checks for fields in struct expressions and patterns. struct NamePrivacyVisitor<'tcx> { tcx: TyCtxt<'tcx>, + mod_id: LocalModId, maybe_typeck_results: Option<&'tcx ty::TypeckResults<'tcx>>, } @@ -938,7 +939,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // Checks that a field in a struct constructor (expression or pattern) is accessible. fn check_field( &self, - hir_id: hir::HirId, // ID of the field use use_ctxt: Span, // syntax context of the field name at the use site def: ty::AdtDef<'tcx>, // definition of the struct or enum field: &'tcx ty::FieldDef, @@ -949,8 +949,7 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { // definition of the field let ident = Ident::new(sym::dummy, use_ctxt); - let (_, def_id) = - self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id.owner.def_id); + let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), self.mod_id); !field.vis.is_accessible_from(def_id, self.tcx) } @@ -1023,7 +1022,6 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { adt: ty::AdtDef<'tcx>, variant: &'tcx ty::VariantDef, fields: &[hir::ExprField<'tcx>], - hir_id: hir::HirId, span: Span, struct_span: Span, ) { @@ -1031,11 +1029,11 @@ impl<'tcx> NamePrivacyVisitor<'tcx> { for (vf_index, variant_field) in variant.fields.iter_enumerated() { let field = fields.iter().find(|f| self.typeck_results().field_index(f.hir_id) == vf_index); - let (hir_id, use_ctxt, span) = match field { - Some(field) => (field.hir_id, field.ident.span, field.span), - None => (hir_id, span, span), + let (use_ctxt, span) = match field { + Some(field) => (field.ident.span, field.span), + None => (span, span), }; - if self.check_field(hir_id, use_ctxt, adt, variant_field) { + if self.check_field(use_ctxt, adt, variant_field) { let name = match field { Some(field) => field.ident.name, None => variant_field.name, @@ -1069,31 +1067,16 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { // If the expression uses FRU we need to make sure all the unmentioned fields // are checked for privacy (RFC 736). Rather than computing the set of // unmentioned fields, just check them all. - self.check_expanded_fields( - adt, - variant, - fields, - base.hir_id, - base.span, - qpath.span(), - ); + self.check_expanded_fields(adt, variant, fields, base.span, qpath.span()); } hir::StructTailExpr::DefaultFields(span) => { - self.check_expanded_fields( - adt, - variant, - fields, - expr.hir_id, - span, - qpath.span(), - ); + self.check_expanded_fields(adt, variant, fields, span, qpath.span()); } hir::StructTailExpr::None | hir::StructTailExpr::NoneWithError(_) => { let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + if self.check_field(field.ident.span, adt, &variant.fields[index]) { failed_fields.push((field.ident.name, field.ident.span, true)); } } @@ -1112,9 +1095,8 @@ impl<'tcx> Visitor<'tcx> for NamePrivacyVisitor<'tcx> { let variant = adt.variant_of_res(res); let mut failed_fields = vec![]; for field in fields { - let (hir_id, use_ctxt) = (field.hir_id, field.ident.span); let index = self.typeck_results().field_index(field.hir_id); - if self.check_field(hir_id, use_ctxt, adt, &variant.fields[index]) { + if self.check_field(field.ident.span, adt, &variant.fields[index]) { failed_fields.push((field.ident.name, field.ident.span, true)); } } @@ -1753,7 +1735,7 @@ pub fn provide(providers: &mut Providers) { fn check_mod_privacy(tcx: TyCtxt<'_>, mod_id: LocalModId) { // Check privacy of names not checked in previous compilation stages. - let mut visitor = NamePrivacyVisitor { tcx, maybe_typeck_results: None }; + let mut visitor = NamePrivacyVisitor { tcx, mod_id, maybe_typeck_results: None }; tcx.hir_visit_item_likes_in_module(mod_id, &mut visitor); // Check privacy of explicitly written types and traits as well as diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 8de0514b9ef27..fffe80be255ce 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -346,7 +346,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let (adjusted_ident, def_scope) = self.tcx.adjust_ident_and_get_scope( field_ident, base_def.did(), - typeck_results.hir_owner.def_id, + self.tcx.parent_module_from_def_id(typeck_results.hir_owner.def_id), ); let Some((_, field_def)) = From 2532b72d46903b406fe00211c9698a58fdf6a2a1 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 14:50:06 -0500 Subject: [PATCH 0423/1309] Use ModId more in late lint pass --- compiler/rustc_ast_lowering/src/index.rs | 5 ++--- compiler/rustc_hir/src/intravisit.rs | 10 ++++++--- compiler/rustc_hir_id/src/lib.rs | 14 ++++++++++++- .../rustc_hir_typeck/src/method/suggest.rs | 2 +- compiler/rustc_lint/src/late.rs | 21 ++++++++++--------- compiler/rustc_lint/src/levels.rs | 3 ++- compiler/rustc_lint/src/nonstandard_style.rs | 6 +++--- compiler/rustc_lint/src/passes.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 17 +++++++-------- compiler/rustc_passes/src/input_stats.rs | 4 ++-- src/librustdoc/html/span_map.rs | 7 ++++--- src/librustdoc/visit_ast.rs | 4 ++-- .../src/arbitrary_source_item_ordering.rs | 5 +++-- .../src/items_after_test_module.rs | 5 +++-- .../clippy_lints/src/redundant_test_prefix.rs | 2 +- 15 files changed, 63 insertions(+), 44 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index f1b6e196fe413..b00e98891d5e7 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -6,6 +6,7 @@ use rustc_hir::intravisit::Visitor; use rustc_hir::*; use rustc_index::IndexVec; use rustc_middle::ty::TyCtxt; +use rustc_span::def_id::CRATE_MOD_ID; use rustc_span::{DUMMY_SP, Span, span_bug}; use tracing::{debug, instrument}; @@ -48,9 +49,7 @@ pub(super) fn index_hir<'hir>( }; match item { - OwnerNode::Crate(citem) => { - collector.visit_mod(citem, citem.spans.inner_span, hir::CRATE_HIR_ID) - } + OwnerNode::Crate(citem) => collector.visit_mod(citem, citem.spans.inner_span, CRATE_MOD_ID), OwnerNode::Item(item) => collector.visit_item(item), OwnerNode::TraitItem(item) => collector.visit_trait_item(item), OwnerNode::ImplItem(item) => collector.visit_impl_item(item), diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 9cd4b5d7d001f..fc8324fb443f8 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -68,7 +68,7 @@ use rustc_ast::Label; use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list}; use rustc_attr_ir::Attribute; use rustc_hir_id::HirId; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::{LocalDefId, LocalModId}; use rustc_span::{Ident, Span, Symbol}; use crate::hir::*; @@ -311,7 +311,7 @@ pub trait Visitor<'v>: Sized { fn visit_ident(&mut self, ident: Ident) -> Self::Result { walk_ident(self, ident) } - fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, _n: HirId) -> Self::Result { + fn visit_mod(&mut self, m: &'v Mod<'v>, _s: Span, _id: LocalModId) -> Self::Result { walk_mod(self, m) } fn visit_foreign_item(&mut self, i: &'v ForeignItem<'v>) -> Self::Result { @@ -583,7 +583,11 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: } ItemKind::Mod(ident, ref module) => { try_visit!(visitor.visit_ident(ident)); - try_visit!(visitor.visit_mod(module, item.span, item.hir_id())); + try_visit!(visitor.visit_mod( + module, + item.span, + LocalModId::new_unchecked(item.owner_id.def_id) + )); } ItemKind::ForeignMod { abi: _, items } => { walk_list!(visitor, visit_foreign_item_ref, items); diff --git a/compiler/rustc_hir_id/src/lib.rs b/compiler/rustc_hir_id/src/lib.rs index dce7e7fd31a36..0e01600f9cb3d 100644 --- a/compiler/rustc_hir_id/src/lib.rs +++ b/compiler/rustc_hir_id/src/lib.rs @@ -16,7 +16,7 @@ use rustc_data_structures::stable_hash::{ StableHash, StableHashCtxt, StableHasher, StableOrd, ToStableHashKey, }; use rustc_macros::{Decodable, Encodable, StableHash}; -use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId}; +use rustc_span::def_id::{CRATE_DEF_ID, DefId, DefIndex, DefPathHash, LocalDefId, LocalModId}; #[derive(Copy, Clone, PartialEq, Eq, Hash, Encodable, Decodable)] pub struct OwnerId { @@ -42,6 +42,12 @@ impl From for DefId { } } +impl From for OwnerId { + fn from(value: LocalModId) -> Self { + OwnerId { def_id: value.to_local_def_id() } + } +} + impl OwnerId { #[inline] pub fn to_def_id(self) -> DefId { @@ -141,6 +147,12 @@ impl fmt::Display for HirId { } } +impl From for HirId { + fn from(id: LocalModId) -> Self { + HirId::make_owner(id.to_local_def_id()) + } +} + rustc_data_structures::define_stable_id_collections!(HirIdMap, HirIdSet, HirIdMapEntry, HirId); rustc_data_structures::define_id_collections!( ItemLocalMap, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index bea91a9dc11b6..aebfeac2e7e85 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -4043,7 +4043,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let accessible_sugg = sugg(accessible_candidates, true); let inaccessible_sugg = sugg(inaccessible_candidates, false); - let (module, _, _) = self.tcx.hir_get_module(self.mod_id); + let (module, _) = self.tcx.hir_get_module(self.mod_id); let span = module.spans.inject_use_span; handle_candidates(accessible_sugg, inaccessible_sugg, span); } diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index 0679d8abe3d78..ac185c65aa127 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -13,6 +13,7 @@ use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; use rustc_session::Session; use rustc_span::Span; +use rustc_span::def_id::CRATE_MOD_ID; use tracing::debug; use crate::passes::LateLintPassObject; @@ -75,9 +76,9 @@ impl<'tcx, T: LateLintPass<'tcx>> LateContextAndPass<'tcx, T> { self.context.param_env = old_param_env; } - fn process_mod(&mut self, m: &'tcx hir::Mod<'tcx>, n: HirId) { - lint_callback!(self, check_mod, m, n); - hir_visit::walk_mod(self, m); + fn process_mod(&mut self, module: &'tcx hir::Mod<'tcx>, id: LocalModId) { + lint_callback!(self, check_mod, module, id); + hir_visit::walk_mod(self, module); } } @@ -220,9 +221,9 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas hir_visit::walk_ty(self, t); } - fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, n: HirId) { + fn visit_mod(&mut self, m: &'tcx hir::Mod<'tcx>, _: Span, id: LocalModId) { if !self.context.only_module { - self.process_mod(m, n); + self.process_mod(m, id); } } @@ -385,17 +386,17 @@ fn late_lint_mod_inner<'tcx, T: LateLintPass<'tcx>>( actually_rustdoc: tcx.sess.opts.actually_rustdoc, }; - let (module, _span, hir_id) = tcx.hir_get_module(mod_id); + let (module, _span) = tcx.hir_get_module(mod_id); - cx.with_lint_attrs(hir_id, |cx| { + cx.with_lint_attrs(mod_id.into(), |cx| { // There is no module lint that will have the crate itself as an item, so check it here. - if hir_id == hir::CRATE_HIR_ID { + if mod_id == CRATE_MOD_ID { lint_callback!(cx, check_crate,); } - cx.process_mod(module, hir_id); + cx.process_mod(module, mod_id); - if hir_id == hir::CRATE_HIR_ID { + if mod_id == CRATE_MOD_ID { lint_callback!(cx, check_crate_post,); } }); diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 472835388620c..7f3d7fa8d2a10 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -26,6 +26,7 @@ use rustc_middle::lint::{ use rustc_middle::query::Providers; use rustc_middle::ty::{RegisteredTools, TyCtxt}; use rustc_session::Session; +use rustc_span::def_id::CRATE_MOD_ID; use rustc_span::{AttrId, DUMMY_SP, Span, Symbol, sym}; use tracing::{debug, instrument}; @@ -190,7 +191,7 @@ fn shallow_lint_levels_on(tcx: TyCtxt<'_>, owner: hir::OwnerId) -> ShallowLintLe hir::OwnerNode::ImplItem(item) => levels.visit_impl_item(item), hir::OwnerNode::Crate(mod_) => { levels.add_id(hir::CRATE_HIR_ID); - levels.visit_mod(mod_, mod_.spans.inner_span, hir::CRATE_HIR_ID) + levels.visit_mod(mod_, mod_.spans.inner_span, CRATE_MOD_ID) } hir::OwnerNode::Synthetic => unreachable!(), }, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index a0db07e187cba..d1057c4f9ead3 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -11,7 +11,7 @@ use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty::AssocContainer; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::{CRATE_MOD_ID, LocalDefId, LocalModId}; use rustc_span::{BytePos, Ident, Span, sym}; use rustc_structures::CrateType; @@ -328,8 +328,8 @@ impl NonSnakeCase { } impl<'tcx> LateLintPass<'tcx> for NonSnakeCase { - fn check_mod(&mut self, cx: &LateContext<'_>, _: &'tcx hir::Mod<'tcx>, id: hir::HirId) { - if id != hir::CRATE_HIR_ID { + fn check_mod(&mut self, cx: &LateContext<'_>, _: &'tcx hir::Mod<'tcx>, id: LocalModId) { + if id != CRATE_MOD_ID { return; } diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index f870bce669e58..6b7955db483f1 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -11,7 +11,7 @@ macro_rules! late_lint_methods { fn check_body_post(a: &rustc_hir::Body<'tcx>); fn check_crate(); fn check_crate_post(); - fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_hir::HirId); + fn check_mod(a: &'tcx rustc_hir::Mod<'tcx>, b: rustc_span::def_id::LocalModId); fn check_foreign_item(a: &'tcx rustc_hir::ForeignItem<'tcx>); fn check_item(a: &'tcx rustc_hir::Item<'tcx>); fn check_item_post(a: &'tcx rustc_hir::Item<'tcx>); diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 1743f0d05dfcd..affadfd0c6aaf 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -409,11 +409,10 @@ impl<'tcx> TyCtxt<'tcx> { find_attr!(self.hir_krate_attrs(), RustcCoherenceIsCore) } - pub fn hir_get_module(self, module: LocalModId) -> (&'tcx Mod<'tcx>, Span, HirId) { - let hir_id = HirId::make_owner(module.to_local_def_id()); - match self.hir_owner_node(hir_id.owner) { - OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span, hir_id), - OwnerNode::Crate(item) => (item, item.spans.inner_span, hir_id), + pub fn hir_get_module(self, module: LocalModId) -> (&'tcx Mod<'tcx>, Span) { + match self.hir_owner_node(module.into()) { + OwnerNode::Item(&Item { span, kind: ItemKind::Mod(_, m), .. }) => (m, span), + OwnerNode::Crate(item) => (item, item.spans.inner_span), node => panic!("not a module: {node:?}"), } } @@ -423,8 +422,8 @@ impl<'tcx> TyCtxt<'tcx> { where V: Visitor<'tcx>, { - let (top_mod, span, hir_id) = self.hir_get_module(CRATE_MOD_ID); - visitor.visit_mod(top_mod, span, hir_id) + let (top_mod, span) = self.hir_get_module(CRATE_MOD_ID); + visitor.visit_mod(top_mod, span, CRATE_MOD_ID) } /// Walks the attributes in a crate. @@ -1254,8 +1253,8 @@ fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { pub(super) fn hir_module_items(tcx: TyCtxt<'_>, module_id: LocalModId) -> ModuleItems { let mut collector = ItemCollector::new(tcx, false); - let (hir_mod, span, hir_id) = tcx.hir_get_module(module_id); - collector.visit_mod(hir_mod, span, hir_id); + let (hir_mod, span) = tcx.hir_get_module(module_id); + collector.visit_mod(hir_mod, span, module_id); let ItemCollector { submodules, diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index f2a7cb6e46fca..961e6e63a81da 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -9,7 +9,7 @@ use rustc_data_structures::thousands::usize_with_underscores; use rustc_hir::{self as hir, AmbigArg, HirId, intravisit as hir_visit}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; -use rustc_span::def_id::LocalDefId; +use rustc_span::def_id::{LocalDefId, LocalModId}; struct NodeStats { count: usize, @@ -277,7 +277,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_body(self, b); } - fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, _n: HirId) { + fn visit_mod(&mut self, m: &'v hir::Mod<'v>, _s: Span, _id: LocalModId) { self.record("Mod", None, m); hir_visit::walk_mod(self, m) } diff --git a/src/librustdoc/html/span_map.rs b/src/librustdoc/html/span_map.rs index 424b3c94fcbb1..c1e6e23f41c38 100644 --- a/src/librustdoc/html/span_map.rs +++ b/src/librustdoc/html/span_map.rs @@ -8,6 +8,7 @@ use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ExprKind, HirId, Item, ItemKind, Mod, Node, QPath}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, TyCtxt}; +use rustc_span::def_id::LocalModId; use rustc_span::{BytePos, ExpnKind}; use crate::clean::{self, PrimitiveType, rustc_span}; @@ -309,13 +310,13 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { } } - fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: rustc_span::Span, id: HirId) { + fn visit_mod(&mut self, m: &'tcx Mod<'tcx>, span: rustc_span::Span, id: LocalModId) { // To make the difference between "mod foo {}" and "mod foo;". In case we "import" another // file, we want to link to it. Otherwise no need to create a link. if !span.overlaps(m.spans.inner_span) { // Now that we confirmed it's a file import, we want to get the span for the module // name only and not all the "mod foo;". - if let Node::Item(item) = self.tcx.hir_node(id) { + if let Node::Item(item) = self.tcx.hir_node_by_def_id(id.into()) { let (ident, _) = item.expect_mod(); self.matches.insert( ident.span.into(), @@ -324,7 +325,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> { } } else { // If it's a "mod foo {}", we want to look to its documentation page. - self.extract_info_from_hir_id(id); + self.extract_info_from_hir_id(id.into()); } intravisit::walk_mod(self, m); } diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ae5a76545eefb..ee30c6d153c0b 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -14,7 +14,7 @@ use rustc_hir::{Node, find_attr}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::Span; -use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE}; +use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalModId}; use rustc_span::symbol::{Symbol, kw}; use tracing::debug; @@ -642,7 +642,7 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { self.is_importable_from_parent = prev; } - fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: hir::HirId) { + fn visit_mod(&mut self, _: &hir::Mod<'tcx>, _: Span, _: LocalModId) { // Handled in `visit_item_inner` } diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 8984184269421..5da0323167fe6 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -8,12 +8,13 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_cfg_test; use rustc_attr_ir::AttributeKind; use rustc_hir::{ - Attribute, FieldDef, HirId, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, + Attribute, FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext, impl_lint_pass}; use rustc_middle::ty::{AssocKind, TyCtxt}; use rustc_span::{Ident, Symbol, bug}; +use rustc_span::def_id::LocalModId; declare_clippy_lint! { /// ### What it does @@ -486,7 +487,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } } - fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: HirId) { + fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: LocalModId) { struct CurItem<'a> { item: &'a Item<'a>, order: usize, diff --git a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs index dac7a24bf2a8d..b09c77b849f5f 100644 --- a/src/tools/clippy/clippy_lints/src/items_after_test_module.rs +++ b/src/tools/clippy/clippy_lints/src/items_after_test_module.rs @@ -2,9 +2,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::SpanExt as _; use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; use rustc_errors::{Applicability, SuggestionStyle}; -use rustc_hir::{HirId, Item, ItemKind, Mod}; +use rustc_hir::{Item, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::hygiene::AstPass; +use rustc_span::def_id::LocalModId; use rustc_span::{ExpnKind, sym}; declare_clippy_lint! { @@ -56,7 +57,7 @@ fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { } impl LateLintPass<'_> for ItemsAfterTestModule { - fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: HirId) { + fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: LocalModId) { let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir_item(id)); let Some((mod_pos, test_mod)) = items.by_ref().enumerate().find(|(_, item)| cfg_test_module(cx, item)) else { diff --git a/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs b/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs index 6f7750939fd95..db3814748719c 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_test_prefix.rs @@ -131,7 +131,7 @@ fn name_conflicts<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, fn_name: S let id = body.id().hir_id; // Iterate over items in the same module/scope - let (module, _module_span, _module_hir) = tcx.hir_get_module(tcx.parent_module(id)); + let (module, _module_span) = tcx.hir_get_module(tcx.parent_module(id)); if module .item_ids .iter() From de388d0a1bf91703397a466f4c6a72206e136ac0 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Thu, 23 Jul 2026 14:50:06 -0500 Subject: [PATCH 0424/1309] Use ModId more in late lint pass --- clippy_lints/src/arbitrary_source_item_ordering.rs | 5 +++-- clippy_lints/src/items_after_test_module.rs | 5 +++-- clippy_lints/src/redundant_test_prefix.rs | 2 +- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index 8984184269421..5da0323167fe6 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -8,12 +8,13 @@ use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_cfg_test; use rustc_attr_ir::AttributeKind; use rustc_hir::{ - Attribute, FieldDef, HirId, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, + Attribute, FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext, impl_lint_pass}; use rustc_middle::ty::{AssocKind, TyCtxt}; use rustc_span::{Ident, Symbol, bug}; +use rustc_span::def_id::LocalModId; declare_clippy_lint! { /// ### What it does @@ -486,7 +487,7 @@ impl<'tcx> LateLintPass<'tcx> for ArbitrarySourceItemOrdering { } } - fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: HirId) { + fn check_mod(&mut self, cx: &LateContext<'tcx>, module: &'tcx Mod<'tcx>, _: LocalModId) { struct CurItem<'a> { item: &'a Item<'a>, order: usize, diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index dac7a24bf2a8d..b09c77b849f5f 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -2,9 +2,10 @@ use clippy_utils::diagnostics::span_lint_hir_and_then; use clippy_utils::source::SpanExt as _; use clippy_utils::{fulfill_or_allowed, is_cfg_test, is_from_proc_macro}; use rustc_errors::{Applicability, SuggestionStyle}; -use rustc_hir::{HirId, Item, ItemKind, Mod}; +use rustc_hir::{Item, ItemKind, Mod}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::hygiene::AstPass; +use rustc_span::def_id::LocalModId; use rustc_span::{ExpnKind, sym}; declare_clippy_lint! { @@ -56,7 +57,7 @@ fn cfg_test_module<'tcx>(cx: &LateContext<'tcx>, item: &Item<'tcx>) -> bool { } impl LateLintPass<'_> for ItemsAfterTestModule { - fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: HirId) { + fn check_mod(&mut self, cx: &LateContext<'_>, module: &Mod<'_>, _: LocalModId) { let mut items = module.item_ids.iter().map(|&id| cx.tcx.hir_item(id)); let Some((mod_pos, test_mod)) = items.by_ref().enumerate().find(|(_, item)| cfg_test_module(cx, item)) else { diff --git a/clippy_lints/src/redundant_test_prefix.rs b/clippy_lints/src/redundant_test_prefix.rs index 6f7750939fd95..db3814748719c 100644 --- a/clippy_lints/src/redundant_test_prefix.rs +++ b/clippy_lints/src/redundant_test_prefix.rs @@ -131,7 +131,7 @@ fn name_conflicts<'tcx>(cx: &LateContext<'tcx>, body: &'tcx Body<'_>, fn_name: S let id = body.id().hir_id; // Iterate over items in the same module/scope - let (module, _module_span, _module_hir) = tcx.hir_get_module(tcx.parent_module(id)); + let (module, _module_span) = tcx.hir_get_module(tcx.parent_module(id)); if module .item_ids .iter() From 5a43300cfac164d7dac06e7e215d6ca8ad1e7bef Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Sep 2026 23:55:45 +0000 Subject: [PATCH 0425/1309] Remove redundant output from suggestion The inline suggestion message already includes the code to replace. --- compiler/rustc_hir_typeck/src/pat.rs | 2 +- .../experimental/mixed-editions.classic2021.stderr | 8 ++++---- .../experimental/mixed-editions.classic2024.stderr | 8 ++++---- .../mixed-editions.structural2021.stderr | 4 ++-- .../mixed-editions.structural2024.stderr | 4 ++-- .../ref-mut-inside-shared-ref-pat.classic2021.stderr | 12 ++++++------ .../ref-mut-inside-shared-ref-pat.classic2024.stderr | 12 ++++++------ ...f-mut-inside-shared-ref-pat.structural2021.stderr | 10 +++++----- ...f-mut-inside-shared-ref-pat.structural2024.stderr | 10 +++++----- 9 files changed, 35 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..3c2f827645523 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1227,7 +1227,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); if let Some(span) = and_pat_span { - err.span_suggestion( + err.span_suggestion_short( span, "replace this `&` with `&mut`", "&mut ", diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr index 4fa82a603a8e4..011b0fb819945 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr @@ -21,7 +21,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &match_ctor!(y) = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:84:17 @@ -29,7 +29,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &[bind!(z)] = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:110:28 @@ -43,7 +43,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &bind_ref_mut!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:116:29 @@ -57,7 +57,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let [&bind_ref_mut!(x)] = &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: cannot explicitly borrow within an implicitly-borrowing pattern --> $DIR/mixed-editions.rs:30:10 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr index ee152c2871f4e..3519e79220a2f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &match_ctor!(y) = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:84:17 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &[bind!(z)] = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:110:28 @@ -42,7 +42,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &bind_ref_mut!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:116:29 @@ -56,7 +56,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let [&bind_ref_mut!(x)] = &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: cannot explicitly borrow within an implicitly-borrowing pattern --> $DIR/mixed-editions.rs:26:21 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr index 69ddb0720526e..6d2df9f91dd01 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr @@ -21,7 +21,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &bind_ref_mut!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:116:29 @@ -35,7 +35,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let [&bind_ref_mut!(x)] = &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: cannot explicitly borrow within an implicitly-borrowing pattern --> $DIR/mixed-editions.rs:30:10 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr index bc1fee35a6bb4..4034cf22240bb 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &bind_ref_mut!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/mixed-editions.rs:116:29 @@ -34,7 +34,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let [&bind_ref_mut!(x)] = &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: cannot explicitly borrow within an implicitly-borrowing pattern --> $DIR/mixed-editions.rs:26:21 diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr index 8127ca92e025e..5b0d08b720284 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &pat!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30 @@ -36,7 +36,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11 @@ -44,7 +44,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &[x] = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr index 8127ca92e025e..5b0d08b720284 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &pat!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30 @@ -36,7 +36,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11 @@ -44,7 +44,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &[x] = &mut &mut [0]; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: aborting due to 6 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr index e735cfed2492f..87606f0b1913f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &pat!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30 @@ -36,7 +36,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: aborting due to 5 previous errors diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr index e735cfed2492f..87606f0b1913f 100644 --- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr +++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr @@ -4,7 +4,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let Some(&Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31 @@ -12,7 +12,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | if let &Some(Some(ref mut x)) = &mut Some(Some(0)) { | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15 @@ -20,7 +20,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &pat!(x) = &mut 0; | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19 @@ -28,7 +28,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error[E0596]: cannot borrow as mutable inside an `&` pattern --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30 @@ -36,7 +36,7 @@ error[E0596]: cannot borrow as mutable inside an `&` pattern LL | let &(ref mut a, ref mut b) = &mut (true, false); | - ^ | | - | help: replace this `&` with `&mut`: `&mut` + | help: replace this `&` with `&mut` error: aborting due to 5 previous errors From 5f33ac34b5f51cf5461b3618ebad1898151d7b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Sep 2026 22:42:37 +0000 Subject: [PATCH 0426/1309] Tweak "use array's length as const param" suggestion - Don't suggest braces unnecessarily for numeric literals - Use verbose suggestion - Tweak messages ``` error[E0747]: type provided when a constant was expected --> $DIR/suggest_const_for_array.rs:6:15 | LL | example::<[usize; 3]>(); | ^^^^^^^^^^ array type provided where a `usize` was expected | help: you might have meant to use the array's length's value | LL - example::<[usize; 3]>(); LL + example::<3>(); | ``` --- .../src/hir_ty_lowering/generics.rs | 18 ++++++++++--- ..._const_for_array.generic_const_args.stderr | 27 +++++++++++++++++++ ...st_for_array.min_generic_const_args.stderr | 27 +++++++++++++++++++ .../suggest_const_for_array.regular.stderr | 27 +++++++++++++++++++ .../const-generics/suggest_const_for_array.rs | 3 +++ .../suggest_const_for_array.stderr | 15 ----------- 6 files changed, 99 insertions(+), 18 deletions(-) create mode 100644 tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr create mode 100644 tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr create mode 100644 tests/ui/const-generics/suggest_const_for_array.regular.stderr delete mode 100644 tests/ui/const-generics/suggest_const_for_array.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 4a35bcb5ef28f..715e7065799b8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -97,12 +97,24 @@ fn generic_arg_mismatch_err( GenericArg::Type(hir::Ty { kind: hir::TyKind::Array(_, len), .. }), GenericParamDefKind::Const { .. }, ) if tcx.type_of(param.def_id).skip_binder() == tcx.types.usize => { + err.span_label(arg.span(), "array type provided where a `usize` was expected"); let snippet = sess.source_map().span_to_snippet(tcx.hir_span(len.hir_id)); if let Ok(snippet) = snippet { - err.span_suggestion( + let sugg = if let hir::ConstArgKind::Anon(hir::AnonConst { body, .. }) = len.kind + && let hir::ExprKind::Lit(..) = tcx.hir_body(*body).value.kind + { + // We don't need to surround literals in braces when used as consts + snippet + } else if let hir::ConstArgKind::Literal { .. } = len.kind { + // We don't need to surround literals in braces when used as consts + snippet + } else { + format!("{{ {snippet} }}") + }; + err.span_suggestion_verbose( arg.span(), - "array type provided where a `usize` was expected, try", - format!("{{ {snippet} }}"), + format!("you might have meant to use the array's length's value"), + sugg, Applicability::MaybeIncorrect, ); } diff --git a/tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr b/tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr new file mode 100644 index 0000000000000..089c7f6b4a25c --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr @@ -0,0 +1,27 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:9:15 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 3]>(); +LL + example::<3>(); + | + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:11:15 + | +LL | example::<[usize; 4 + 5]>(); + | ^^^^^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 4 + 5]>(); +LL + example::<{ 4 + 5 }>(); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr b/tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr new file mode 100644 index 0000000000000..089c7f6b4a25c --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr @@ -0,0 +1,27 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:9:15 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 3]>(); +LL + example::<3>(); + | + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:11:15 + | +LL | example::<[usize; 4 + 5]>(); + | ^^^^^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 4 + 5]>(); +LL + example::<{ 4 + 5 }>(); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/suggest_const_for_array.regular.stderr b/tests/ui/const-generics/suggest_const_for_array.regular.stderr new file mode 100644 index 0000000000000..089c7f6b4a25c --- /dev/null +++ b/tests/ui/const-generics/suggest_const_for_array.regular.stderr @@ -0,0 +1,27 @@ +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:9:15 + | +LL | example::<[usize; 3]>(); + | ^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 3]>(); +LL + example::<3>(); + | + +error[E0747]: type provided when a constant was expected + --> $DIR/suggest_const_for_array.rs:11:15 + | +LL | example::<[usize; 4 + 5]>(); + | ^^^^^^^^^^^^^^ array type provided where a `usize` was expected + | +help: you might have meant to use the array's length's value + | +LL - example::<[usize; 4 + 5]>(); +LL + example::<{ 4 + 5 }>(); + | + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/suggest_const_for_array.rs b/tests/ui/const-generics/suggest_const_for_array.rs index b52fd152f976a..b85491130c9e8 100644 --- a/tests/ui/const-generics/suggest_const_for_array.rs +++ b/tests/ui/const-generics/suggest_const_for_array.rs @@ -1,4 +1,7 @@ +//@revisions: min_generic_const_args generic_const_args regular #![crate_type = "lib"] +#![cfg_attr(min_generic_const_args, feature(min_generic_const_args))] +#![cfg_attr(generic_const_args, feature(min_generic_const_args))] fn example() {} diff --git a/tests/ui/const-generics/suggest_const_for_array.stderr b/tests/ui/const-generics/suggest_const_for_array.stderr deleted file mode 100644 index f0ad8368e5d71..0000000000000 --- a/tests/ui/const-generics/suggest_const_for_array.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0747]: type provided when a constant was expected - --> $DIR/suggest_const_for_array.rs:6:15 - | -LL | example::<[usize; 3]>(); - | ^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 3 }` - -error[E0747]: type provided when a constant was expected - --> $DIR/suggest_const_for_array.rs:8:15 - | -LL | example::<[usize; 4 + 5]>(); - | ^^^^^^^^^^^^^^ help: array type provided where a `usize` was expected, try: `{ 4 + 5 }` - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0747`. From 837ce844f9b85ef4f2094907aee4fc6edfa694c5 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Sun, 20 Sep 2026 00:29:37 +0000 Subject: [PATCH 0427/1309] Add .seek_read_exact(), .seek_write_all() to std::os::windows::fs::FileExt * First pass at windows::fs::FileExt.seek_read_exact() * First pass at windows::fs::FileExt.seek_write_all() * Fix function signature in seek_read_exact(), duh * First pass at tests for .seek_read_exact(), seek_write_all() * Whitespace fix * Use hypothetical seek_read_exact_seek_write_all feature also for .seek_read_exact() * Tracking issues 162868 * Oops, fix seek_write_all() doc example, was using write_all_at() still * Add mocked test for windows FileExt trait * Spelling fixes * Expand test for windows FileExt trait to include almost all scenarios * Split three tests out of file_test_windows_fileext_trait() * Remove old versions of those 3 tests * Split remaining file_test_windows_fileext_trait() into case 4, 5 * More test cleanup, always test expected_offset where possible * Test read first for consistency * Use same doctsring examples as seek_read(), seek_write() * Missing period * Oops: actually call _exact(), _all() methods in case 2, 3 * Add missing seek_read_exact_seek_write_all feature flags in doc examples --- library/std/src/fs/tests.rs | 267 +++++++++++++++++++++++++++++++ library/std/src/os/windows/fs.rs | 119 ++++++++++++++ 2 files changed, 386 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 148f1c32b08b9..a4c48ed0563ad 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -775,6 +775,273 @@ fn file_test_io_seek_read_write() { check!(fs::remove_file(&filename)); } +#[test] +#[cfg(windows)] +fn file_test_io_seek_read_exact_write_all() { + use crate::os::windows::fs::FileExt; + + let tmpdir = tmpdir(); + let filename = tmpdir.join("file_rt_io_file_test_seek_read_exact_write_all.txt"); + let mut buf = [0; 256]; + let write1 = "asdf"; + let write2 = "qwer-"; + let write3 = "-zxcv"; + let content = "qwer-asdf-zxcv"; + { + let oo = OpenOptions::new().create_new(true).write(true).read(true).clone(); + let mut rw = check!(oo.open(&filename)); + check!(rw.seek_write_all(write1.as_bytes(), 5)); + assert_eq!(check!(rw.stream_position()), 9); + check!(rw.seek_read_exact(&mut buf[..write1.len()], 5)); + assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1)); + assert_eq!(check!(rw.stream_position()), 9); + assert_eq!(check!(rw.seek(SeekFrom::Start(0))), 0); + assert_eq!(check!(rw.write(write2.as_bytes())), write2.len()); + assert_eq!(check!(rw.stream_position()), 5); + assert_eq!(check!(rw.read(&mut buf)), write1.len()); + assert_eq!(str::from_utf8(&buf[..write1.len()]), Ok(write1)); + assert_eq!(check!(rw.stream_position()), 9); + check!(rw.seek_read_exact(&mut buf[..write2.len()], 0)); + assert_eq!(str::from_utf8(&buf[..write2.len()]), Ok(write2)); + assert_eq!(check!(rw.stream_position()), 5); + check!(rw.seek_write_all(write3.as_bytes(), 9)); + assert_eq!(check!(rw.stream_position()), 14); + } + { + let mut read = check!(File::open(&filename)); + check!(read.seek_read_exact(&mut buf[..content.len()], 0)); + assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content)); + assert_eq!(check!(read.stream_position()), 14); + assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9); + check!(read.seek_read_exact(&mut buf[..content.len()], 0)); + assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content)); + assert_eq!(check!(read.stream_position()), 14); + assert_eq!(check!(read.seek(SeekFrom::End(-5))), 9); + assert_eq!(check!(read.read(&mut buf)), write3.len()); + assert_eq!(str::from_utf8(&buf[..write3.len()]), Ok(write3)); + assert_eq!(check!(read.stream_position()), 14); + check!(read.seek_read_exact(&mut buf[..content.len()], 0)); + assert_eq!(str::from_utf8(&buf[..content.len()]), Ok(content)); + assert_eq!(check!(read.stream_position()), 14); + assert!(read.seek_read_exact(&mut buf, 14).is_err()); + assert!(read.seek_read_exact(&mut buf, 15).is_err()); + } + check!(fs::remove_file(&filename)); +} + +#[test] +#[cfg(windows)] +fn file_test_windows_fileext_trait_case_1() { + use crate::os::windows::fs::FileExt; + + // Test when seek_read_exact(), seek_write_all() are called with empty buffers. + struct MockFile {} + + impl FileExt for MockFile { + fn seek_read(&self, _buf: &mut [u8], _offset: u64) -> io::Result { + panic!("should not be called"); + } + + fn seek_write(&self, _buf: &[u8], _offset: u64) -> io::Result { + panic!("should not be called"); + } + } + + let mock_file = MockFile {}; + check!(mock_file.seek_read_exact(&mut [], 0)); + check!(mock_file.seek_write_all(&[], 0)); + check!(mock_file.seek_read_exact(&mut [], 420)); + check!(mock_file.seek_write_all(&[], 420)); +} + +#[test] +#[cfg(windows)] +fn file_test_windows_fileext_trait_case_2() { + use crate::os::windows::fs::FileExt; + + // Test when seek_read(), seek_write() return Ok(0) + struct MockFile { + expected_offset: u64, + } + + impl FileExt for MockFile { + fn seek_read(&self, _buf: &mut [u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + Ok(0) + } + + fn seek_write(&self, _buf: &[u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + Ok(0) + } + } + + { + let mock_file = MockFile { expected_offset: 0 }; + let mut buf = [0; 256]; + assert_eq!( + mock_file.seek_read_exact(&mut buf, 0).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); + assert_eq!(mock_file.seek_write_all(&buf, 0).unwrap_err().kind(), io::ErrorKind::WriteZero); + } + + { + let mock_file = MockFile { expected_offset: 420 }; + let mut buf = [0; 256]; + assert_eq!( + mock_file.seek_read_exact(&mut buf, 420).unwrap_err().kind(), + io::ErrorKind::UnexpectedEof + ); + assert_eq!( + mock_file.seek_write_all(&buf, 420).unwrap_err().kind(), + io::ErrorKind::WriteZero + ); + } +} + +#[test] +#[cfg(windows)] +fn file_test_windows_fileext_trait_case_3() { + use crate::os::windows::fs::FileExt; + + // Test that Err other than io::ErrorKind::Interrupted are propagated up. + struct MockFile { + expected_offset: u64, + } + + impl FileExt for MockFile { + fn seek_read(&self, _buf: &mut [u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + Err(io::Error::new(io::ErrorKind::PermissionDenied, "seek_read")) + } + + fn seek_write(&self, _buf: &[u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + Err(io::Error::new(io::ErrorKind::ConnectionRefused, "seek_write")) + } + } + + { + let mock_file = MockFile { expected_offset: 0 }; + let mut buf = [0; 256]; + assert_eq!( + mock_file.seek_read_exact(&mut buf, 0).unwrap_err().kind(), + io::ErrorKind::PermissionDenied + ); + assert_eq!( + mock_file.seek_write_all(&buf, 0).unwrap_err().kind(), + io::ErrorKind::ConnectionRefused + ); + } + + { + let mock_file = MockFile { expected_offset: 420 }; + let mut buf = [0; 256]; + assert_eq!( + mock_file.seek_read_exact(&mut buf, 420).unwrap_err().kind(), + io::ErrorKind::PermissionDenied + ); + assert_eq!( + mock_file.seek_write_all(&buf, 420).unwrap_err().kind(), + io::ErrorKind::ConnectionRefused + ); + } + // FIXME: Cover io::ErrorKind::Interrupted, but don't infinite loop ;) +} + +#[test] +#[cfg(windows)] +fn file_test_windows_fileext_trait_case_4() { + use crate::os::windows::fs::FileExt; + + const MSG: &[u8] = + b"The Rust programming language helps you write faster, more reliable software."; + + // Test when the entire read or write is satisfied by only one call to seek_read() or + // seek_write(), respectively. + struct MockFile { + expected_offset: u64, + } + + impl FileExt for MockFile { + fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + assert_eq!(buf.len(), MSG.len()); + assert_eq!(buf, &[0; MSG.len()]); + buf.copy_from_slice(MSG); + Ok(MSG.len()) + } + + fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { + assert_eq!(offset, self.expected_offset); + assert_eq!(buf.len(), MSG.len()); + assert_eq!(buf, MSG); + Ok(MSG.len()) + } + } + + { + let mock_file = MockFile { expected_offset: 0 }; + let mut buf = [0; MSG.len()]; + check!(mock_file.seek_read_exact(&mut buf, 0)); + assert_eq!(&buf, MSG); + check!(mock_file.seek_write_all(&buf, 0)); + } + + { + let mock_file = MockFile { expected_offset: 420 }; + let mut buf = [0; MSG.len()]; + check!(mock_file.seek_read_exact(&mut buf, 420)); + assert_eq!(&buf, MSG); + check!(mock_file.seek_write_all(&buf, 420)); + } +} + +#[test] +#[cfg(windows)] +fn file_test_windows_fileext_trait_case_5() { + use crate::os::windows::fs::FileExt; + + const MSG: &[u8] = + b"Rust is for students and those who are interested in learning about systems concepts."; + + // Test pathological case where seek_read(), seek_write() only do 1 byte per call, return Ok(1) + struct MockFile { + base_offset: u64, + } + + impl FileExt for MockFile { + fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result { + let offset = (offset - self.base_offset) as usize; + buf[0..1].copy_from_slice(&MSG[offset..offset + 1]); + Ok(1) + } + + fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result { + let offset = (offset - self.base_offset) as usize; + assert_eq!(buf[0..1], MSG[offset..offset + 1]); + Ok(1) + } + } + + { + let mock_file = MockFile { base_offset: 0 }; + let mut buf = [0; MSG.len()]; + check!(mock_file.seek_read_exact(&mut buf, 0)); + assert_eq!(&buf, MSG); + check!(mock_file.seek_write_all(&buf, 0)); + } + + { + let mock_file = MockFile { base_offset: 420 }; + let mut buf = [0; MSG.len()]; + check!(mock_file.seek_read_exact(&mut buf, 420)); + assert_eq!(&buf, MSG); + check!(mock_file.seek_write_all(&buf, 420)); + } +} + #[test] #[cfg(windows)] fn test_seek_read_buf() { diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 21560638c1d0f..3e6a934f318b2 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -50,6 +50,69 @@ pub trait FileExt { #[stable(feature = "file_offset", since = "1.15.0")] fn seek_read(&self, buf: &mut [u8], offset: u64) -> io::Result; + /// Seeks to a given position and reads the exact number of bytes required to fill `buf`. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. The current cursor **is** affected by this + /// function, it is set to the end of the read. + /// + /// Similar to [`io::Read::read_exact`] but uses [`seek_read`] instead of `read`. + /// + /// [`seek_read`]: FileExt::seek_read + /// + /// # Errors + /// + /// If this function encounters an error of the kind + /// [`io::ErrorKind::Interrupted`] then the error is ignored and the operation + /// will continue. + /// + /// If this function encounters an "end of file" before completely filling + /// the buffer, it returns an error of the kind [`io::ErrorKind::UnexpectedEof`]. + /// The contents of `buf` are unspecified in this case. + /// + /// If any other read error is encountered then this function immediately + /// returns. The contents of `buf` are unspecified in this case. + /// + /// If this function returns an error, it is unspecified how many bytes it + /// has read, but it will never read more than would be necessary to + /// completely fill the buffer. + /// + /// # Examples + /// + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] + /// #![feature(seek_read_exact_seek_write_all)] + /// + /// use std::io; + /// use std::fs::File; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("foo.txt")?; + /// let mut buffer = [0; 10]; + /// + /// // Read 10 bytes, starting 72 bytes from the + /// // start of the file. + /// file.seek_read_exact(&mut buffer[..], 72)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "seek_read_exact_seek_write_all", issue = "162868")] + fn seek_read_exact(&self, mut buf: &mut [u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.seek_read(buf, offset) { + Ok(0) => break, + Ok(n) => { + buf = &mut buf[n..]; + offset += n as u64; + } + Err(ref e) if e.is_interrupted() => {} + Err(e) => return Err(e), + } + } + if !buf.is_empty() { Err(io::Error::READ_EXACT_EOF) } else { Ok(()) } + } + /// Seeks to a given position and reads some bytes into the buffer. /// /// This is equivalent to the [`seek_read`](FileExt::seek_read) method, except that it is passed @@ -122,6 +185,62 @@ pub trait FileExt { /// ``` #[stable(feature = "file_offset", since = "1.15.0")] fn seek_write(&self, buf: &[u8], offset: u64) -> io::Result; + + /// Seeks to a given position and attempts to write an entire buffer. + /// + /// The offset is relative to the start of the file and thus independent + /// from the current cursor. The current cursor **is** affected by this + /// function, it is set to the end of the write. + /// + /// This method will continuously call [`seek_write`] until there is no more data + /// to be written or an error of non-[`io::ErrorKind::Interrupted`] kind is + /// returned. This method will not return until the entire buffer has been + /// successfully written or such an error occurs. The first error that is + /// not of [`io::ErrorKind::Interrupted`] kind generated from this method will be + /// returned. + /// + /// # Errors + /// + /// This function will return the first error of + /// non-[`io::ErrorKind::Interrupted`] kind that [`seek_write`] returns. + /// + /// [`seek_write`]: FileExt::seek_write + /// + /// # Examples + /// + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] + /// #![feature(seek_read_exact_seek_write_all)] + /// + /// use std::fs::File; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> std::io::Result<()> { + /// let mut buffer = File::create("foo.txt")?; + /// + /// // Write a byte string starting 72 bytes from + /// // the start of the file. + /// buffer.seek_write_all(b"some bytes", 72)?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "seek_read_exact_seek_write_all", issue = "162868")] + fn seek_write_all(&self, mut buf: &[u8], mut offset: u64) -> io::Result<()> { + while !buf.is_empty() { + match self.seek_write(buf, offset) { + Ok(0) => { + return Err(io::Error::WRITE_ALL_EOF); + } + Ok(n) => { + buf = &buf[n..]; + offset += n as u64 + } + Err(ref e) if e.is_interrupted() => {} + Err(e) => return Err(e), + } + } + Ok(()) + } } #[stable(feature = "file_offset", since = "1.15.0")] From cfe9a3a4419630de87023a8456becf29ddcff602 Mon Sep 17 00:00:00 2001 From: Cameron Steffen Date: Mon, 31 Aug 2026 17:08:52 -0500 Subject: [PATCH 0428/1309] Tweak Infallible docs Link to the never type and restore the note about possibly deprecating in the future. --- library/core/src/convert/mod.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 7e675815edb2e..e0e58474fd4d2 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -886,7 +886,8 @@ const impl AsMut for str { /// } /// ``` /// -/// Note: since CURRENT_RUSTC_VERSION this is an alias to `!`. If targeting that or future versions, -/// prefer using the never type directly. +/// Note: Since [`!`] (the "never" type) was stabilized in Rust CURRENT_RUSTC_VERSION, it is +/// preferred to use `!` directly unless targeting older Rust versions. `Infallible` may be +/// deprecated in a future Rust version. #[stable(feature = "convert_infallible", since = "1.34.0")] pub type Infallible = !; From ea2fa3e8724516f272f079c8a401cc5904330512 Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 13 Sep 2026 21:01:32 +0800 Subject: [PATCH 0429/1309] Add regression tests for runtime range pattern endpoints --- ...e-range-endpoints-issue-131327.both.stderr | 12 ++++ ...-range-endpoints-issue-131327.chars.stderr | 9 +++ ...ange-endpoints-issue-131327.generic.stderr | 9 +++ ...nge-endpoints-issue-131327.inferred.stderr | 9 +++ .../runtime-range-endpoints-issue-131327.rs | 60 +++++++++++++++++++ ...e-endpoints-issue-131327.wrong_type.stderr | 12 ++++ 6 files changed, 111 insertions(+) create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.chars.stderr create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.rs create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr new file mode 100644 index 0000000000000..9382148254fec --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr @@ -0,0 +1,12 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:29:9 + | +LL | start..=end => (), + | -----^^^--- + | | | + | | this is of type `T` but it should be `char` or numeric + | this is of type `T` but it should be `char` or numeric + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.chars.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.chars.stderr new file mode 100644 index 0000000000000..da20e76d9c75a --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.chars.stderr @@ -0,0 +1,9 @@ +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:20:11 + | +LL | ..y => (), + | ^ references a runtime value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr new file mode 100644 index 0000000000000..555e4e144dd63 --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr @@ -0,0 +1,9 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:10:11 + | +LL | ..y => smaller, + | ^ this is of type `T` but it should be `char` or numeric + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0029`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr new file mode 100644 index 0000000000000..a208d83fac939 --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr @@ -0,0 +1,9 @@ +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:39:11 + | +LL | ..end => (), + | ^^^ references a runtime value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs b/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs new file mode 100644 index 0000000000000..781d4458390fc --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs @@ -0,0 +1,60 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131327. +//! A runtime range endpoint is invalid regardless of its type. + +//@ revisions: generic chars both inferred wrong_type +#![allow(dead_code, unreachable_patterns, unused_variables)] + +#[cfg(generic)] +fn cmp(x: T, y: T, smaller: R, equal: R, greater: R) -> R { + match x { + ..y => smaller, + //[generic]~^ ERROR only `char` and numeric types are allowed in range patterns + y => equal, + _ => greater, + } +} + +#[cfg(chars)] +fn chars(x: char, y: char) { + match x { + ..y => (), + //[chars]~^ ERROR runtime values cannot be referenced in patterns + _ => (), + } +} + +#[cfg(both)] +fn both(x: T, start: T, end: T) { + match x { + start..=end => (), + //[both]~^ ERROR only `char` and numeric types are allowed in range patterns + _ => (), + } +} + +#[cfg(inferred)] +fn inferred() { + let end = Default::default(); + match 0 { + ..end => (), + //[inferred]~^ ERROR runtime values cannot be referenced in patterns + _ => (), + } +} + +const LOWER: u8 = 1; +const UPPER: u8 = 9; +fn constants(x: u8) -> bool { + matches!(x, LOWER..=UPPER) +} + +#[cfg(wrong_type)] +fn wrong_type(x: bool) { + match x { + false..=true => (), + //[wrong_type]~^ ERROR only `char` and numeric types are allowed in range patterns + _ => (), + } +} + +fn main() {} diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr new file mode 100644 index 0000000000000..493e56d9f608d --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr @@ -0,0 +1,12 @@ +error[E0029]: only `char` and numeric types are allowed in range patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:54:9 + | +LL | false..=true => (), + | -----^^^---- + | | | + | | this is of type `bool` but it should be `char` or numeric + | this is of type `bool` but it should be `char` or numeric + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0029`. From 64695f1d7b3f1649b63e2c6730f69ea583a4670a Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 13 Sep 2026 21:21:16 +0800 Subject: [PATCH 0430/1309] Diagnose runtime range endpoints before reporting unsupported types --- compiler/rustc_hir_typeck/src/diagnostics.rs | 8 +++++++ compiler/rustc_hir_typeck/src/pat.rs | 22 +++++++++++++++++-- .../never_type/regress/never-in-range-pat.rs | 5 ++--- .../regress/never-in-range-pat.stderr | 10 ++++----- ...e-range-endpoints-issue-131327.both.stderr | 11 +++++----- ...ange-endpoints-issue-131327.generic.stderr | 6 ++--- ...nge-endpoints-issue-131327.inferred.stderr | 2 +- ...ndpoints-issue-131327.late_inferred.stderr | 9 ++++++++ .../runtime-range-endpoints-issue-131327.rs | 20 ++++++++++++++--- ...e-endpoints-issue-131327.wrong_type.stderr | 2 +- 10 files changed, 70 insertions(+), 25 deletions(-) create mode 100644 tests/ui/pattern/runtime-range-endpoints-issue-131327.late_inferred.stderr diff --git a/compiler/rustc_hir_typeck/src/diagnostics.rs b/compiler/rustc_hir_typeck/src/diagnostics.rs index 3b7de7790ac02..fb1b33b0bdd64 100644 --- a/compiler/rustc_hir_typeck/src/diagnostics.rs +++ b/compiler/rustc_hir_typeck/src/diagnostics.rs @@ -584,6 +584,14 @@ impl Subdiagnostic for RemoveSemiForCoerce { } } +#[derive(Diagnostic)] +#[diag("runtime values cannot be referenced in patterns", code = E0080)] +pub(crate) struct NonConstPathInPattern { + #[primary_span] + #[label("references a runtime value")] + pub spans: Vec, +} + #[derive(Diagnostic)] #[diag("union patterns should have exactly one field")] pub(crate) struct UnionPatMultipleFields { diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..94b59e5642df7 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1036,13 +1036,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Some((fail, ty, expr.span)) } }; + let endpoints = [lhs, rhs]; let mut lhs = calc_side(lhs); let mut rhs = calc_side(rhs); if let (Some((true, ..)), _) | (_, Some((true, ..))) = (lhs, rhs) { // There exists a side that didn't meet our criteria that the end-point // be of a numeric or char type, as checked in `calc_side` above. - let guar = self.emit_err_pat_range(span, lhs, rhs); + let guar = self.emit_err_pat_range(span, lhs, rhs, endpoints); return Ty::new_error(self.tcx, guar); } @@ -1078,7 +1079,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if let Some((ref mut fail, _, _)) = rhs { *fail = true; } - let guar = self.emit_err_pat_range(span, lhs, rhs); + let guar = self.emit_err_pat_range(span, lhs, rhs, endpoints); return Ty::new_error(self.tcx, guar); } ty @@ -1095,7 +1096,24 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span: Span, lhs: Option<(bool, Ty<'tcx>, Span)>, rhs: Option<(bool, Ty<'tcx>, Span)>, + endpoints: [Option<&hir::PatExpr<'tcx>>; 2], ) -> ErrorGuaranteed { + if !(lhs, rhs).references_error() { + // Range endpoints must resolve to constants, not local variables. + // Label both runtime endpoints before the type error. + let mut spans = Vec::new(); + for expr in endpoints.into_iter().flatten() { + if let hir::PatExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind + && matches!(path.res, Res::Local(_)) + { + spans.push(expr.span); + } + } + if !spans.is_empty() { + return self.dcx().emit_err(diagnostics::NonConstPathInPattern { spans }); + } + } + let span = match (lhs, rhs) { (Some((true, ..)), Some((true, ..))) => span, (Some((true, _, sp)), _) => sp, diff --git a/tests/ui/never_type/regress/never-in-range-pat.rs b/tests/ui/never_type/regress/never-in-range-pat.rs index 9b2847f882d2a..7631dd6fa3868 100644 --- a/tests/ui/never_type/regress/never-in-range-pat.rs +++ b/tests/ui/never_type/regress/never-in-range-pat.rs @@ -2,13 +2,12 @@ // // Make sure we don't ICE when there's `!` in a range pattern. // -// This shouldn't be allowed anyways, but we only deny it during MIR -// building, so make sure we handle it semi-gracefully during typeck. +// Report the invalid runtime endpoint during typeck, before MIR building. fn main() { let x: !; match 1 { 0..x => {} - //~^ ERROR only `char` and numeric types are allowed in range patterns + //~^ ERROR runtime values cannot be referenced in patterns } } diff --git a/tests/ui/never_type/regress/never-in-range-pat.stderr b/tests/ui/never_type/regress/never-in-range-pat.stderr index 977f486f598b7..a9f7aa5ed5cf5 100644 --- a/tests/ui/never_type/regress/never-in-range-pat.stderr +++ b/tests/ui/never_type/regress/never-in-range-pat.stderr @@ -1,11 +1,9 @@ -error[E0029]: only `char` and numeric types are allowed in range patterns - --> $DIR/never-in-range-pat.rs:11:12 +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/never-in-range-pat.rs:10:12 | LL | 0..x => {} - | - ^ this is of type `!` but it should be `char` or numeric - | | - | this is of type `{integer}` + | ^ references a runtime value error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0029`. +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr index 9382148254fec..b2b83a1c24f84 100644 --- a/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.both.stderr @@ -1,12 +1,11 @@ -error[E0029]: only `char` and numeric types are allowed in range patterns +error[E0080]: runtime values cannot be referenced in patterns --> $DIR/runtime-range-endpoints-issue-131327.rs:29:9 | LL | start..=end => (), - | -----^^^--- - | | | - | | this is of type `T` but it should be `char` or numeric - | this is of type `T` but it should be `char` or numeric + | ^^^^^ ^^^ references a runtime value + | | + | references a runtime value error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0029`. +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr index 555e4e144dd63..88a9c54825808 100644 --- a/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.generic.stderr @@ -1,9 +1,9 @@ -error[E0029]: only `char` and numeric types are allowed in range patterns +error[E0080]: runtime values cannot be referenced in patterns --> $DIR/runtime-range-endpoints-issue-131327.rs:10:11 | LL | ..y => smaller, - | ^ this is of type `T` but it should be `char` or numeric + | ^ references a runtime value error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0029`. +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr index a208d83fac939..96ec685a3f0cd 100644 --- a/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.inferred.stderr @@ -1,5 +1,5 @@ error[E0080]: runtime values cannot be referenced in patterns - --> $DIR/runtime-range-endpoints-issue-131327.rs:39:11 + --> $DIR/runtime-range-endpoints-issue-131327.rs:40:11 | LL | ..end => (), | ^^^ references a runtime value diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.late_inferred.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.late_inferred.stderr new file mode 100644 index 0000000000000..ffdb398b3cfd1 --- /dev/null +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.late_inferred.stderr @@ -0,0 +1,9 @@ +error[E0080]: runtime values cannot be referenced in patterns + --> $DIR/runtime-range-endpoints-issue-131327.rs:68:11 + | +LL | ..end => (), + | ^^^ references a runtime value + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs b/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs index 781d4458390fc..c232d391b26ab 100644 --- a/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.rs @@ -1,14 +1,14 @@ //! Regression test for https://github.com/rust-lang/rust/issues/131327. //! A runtime range endpoint is invalid regardless of its type. -//@ revisions: generic chars both inferred wrong_type +//@ revisions: generic chars both inferred wrong_type late_inferred #![allow(dead_code, unreachable_patterns, unused_variables)] #[cfg(generic)] fn cmp(x: T, y: T, smaller: R, equal: R, greater: R) -> R { match x { ..y => smaller, - //[generic]~^ ERROR only `char` and numeric types are allowed in range patterns + //[generic]~^ ERROR runtime values cannot be referenced in patterns y => equal, _ => greater, } @@ -27,7 +27,8 @@ fn chars(x: char, y: char) { fn both(x: T, start: T, end: T) { match x { start..=end => (), - //[both]~^ ERROR only `char` and numeric types are allowed in range patterns + //[both]~^ ERROR runtime values cannot be referenced in patterns + // Both endpoints are labeled by the same diagnostic. _ => (), } } @@ -57,4 +58,17 @@ fn wrong_type(x: bool) { } } +#[cfg(late_inferred)] +fn late_inferred() { + #[derive(Default)] + struct Bound; + + let end = Default::default(); + match Bound { + ..end => (), + //[late_inferred]~^ ERROR runtime values cannot be referenced in patterns + _ => (), + } +} + fn main() {} diff --git a/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr b/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr index 493e56d9f608d..b96ba91d2657f 100644 --- a/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr +++ b/tests/ui/pattern/runtime-range-endpoints-issue-131327.wrong_type.stderr @@ -1,5 +1,5 @@ error[E0029]: only `char` and numeric types are allowed in range patterns - --> $DIR/runtime-range-endpoints-issue-131327.rs:54:9 + --> $DIR/runtime-range-endpoints-issue-131327.rs:55:9 | LL | false..=true => (), | -----^^^---- From 76fa1f2dca71137da079b3a0b33f833f91ad3271 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Thu, 17 Sep 2026 16:56:24 +1000 Subject: [PATCH 0431/1309] Add some docs for each non-query DepKind --- compiler/rustc_middle/src/queries.rs | 40 +++++++++++++++++-- .../rustc_query_impl/src/dep_kind_vtables.rs | 7 +++- 2 files changed, 41 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 706d89ca52749..9e1bafa4fd2a2 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2856,17 +2856,49 @@ rustc_queries! { // "Non-queries" are special dep kinds that are not queries. //----------------------------------------------------------------------------- - /// We use this for most things when incr. comp. is turned off. + /// Sentinel for an unused slot in a dense sequence of decoded dep-nodes. + /// + /// Dep-nodes are written to disk in non-sequential order, and the ID range + /// might have gaps due to IDs being allocated in per-thread chunks. Having a + /// sentinel makes it easier for the decoder to allocate a single dense vector + /// of Null nodes, and then decode the actual nodes into that vector. non_query Null - /// We use this to create a forever-red node. + + /// The singleton always-red node, with index `DepNodeIndex::FOREVER_RED_NODE`. + /// + /// A node that depends on the always-red node is never able to skip execution + /// due to having marked all of its dependencies green. + /// + /// Used when query feeding would copy the dependencies of the enclosing query, + /// but the enclosing query has the `eval_always` modifier. + /// + /// (Conceptually, `eval_always` query nodes should also have a `Red` dependency, + /// but instead they are special-cased to avoid having to store one explicitly.) non_query Red - /// We use this to create a side effect node. + + /// A "side-effect" node, e.g. emitting a diagnosting or recording that an + /// unstable feature was used. + /// + /// "Forcing" a side-effect node causes its side-effect to be replayed. non_query SideEffect - /// We use this to create the anon node with zero dependencies. + + // "Anonymous tasks" are similar to queries, but their identity is based on a + // hash of their dep-graph dependencies, rather than a hash of a query key. + + /// The singleton node with index `DepNodeIndex::SINGLETON_ZERO_DEPS_ANON_NODE`, + /// for anonymous tasks that didn't have any dep-graph dependencies. non_query AnonZeroDeps + /// Anonymous task for trait solving. non_query TraitSelect + + // These special tasks are also similar to queries, and have an associated key. + // But they bypass the usual query system machinery for various reasons. + + /// Special task for compiling a CGU. non_query CompileCodegenUnit + /// Special task for compiling a single `MonoItem`. Used by `rustc_codegen_cranelift`. non_query CompileMonoItem + /// Special task for emitting crate metadata. non_query Metadata } diff --git a/compiler/rustc_query_impl/src/dep_kind_vtables.rs b/compiler/rustc_query_impl/src/dep_kind_vtables.rs index ad71563a556d8..5791ca47139c6 100644 --- a/compiler/rustc_query_impl/src/dep_kind_vtables.rs +++ b/compiler/rustc_query_impl/src/dep_kind_vtables.rs @@ -7,11 +7,15 @@ use crate::incremental::promote_from_disk_inner; use crate::query_vtables::GetQueryVTable; /// [`DepKindVTable`] constructors for special dep kinds that aren't queries. +/// +/// See the variants of [`DepKind`] (which are declared in [`rustc_middle::queries`]) +/// for documentation on individual dep kinds. +/// +/// [`DepKind`]: rustc_middle::dep_graph::DepKind #[expect(non_snake_case, reason = "use non-snake case to avoid collision with query names")] mod non_query { use super::*; - // We use this for most things when incr. comp. is turned off. pub(crate) fn Null<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { is_eval_always: false, @@ -23,7 +27,6 @@ mod non_query { } } - // We use this for the forever-red node. pub(crate) fn Red<'tcx>() -> DepKindVTable<'tcx> { DepKindVTable { is_eval_always: false, From 109d3aedf779f618b14f2237cefefd83145b1e7e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 03:04:50 +0000 Subject: [PATCH 0432/1309] Use verbose suggestion for `const _` ``` warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:13:5 | LL | const Z: () = { | ----------- move the `impl` block outside of this constant `Z` ... LL | impl Uto for &Test {} | ^^^^^---^^^^^^---- | | | | | `Test` is not local | `Uto` is not local | = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint = note: `#[warn(non_local_definitions)]` on by default help: use a const-anon item to suppress this lint | LL - const Z: () = { LL + const _: () = { | ``` --- compiler/rustc_lint/src/diagnostics.rs | 2 +- tests/ui/lint/non-local-defs/consts.stderr | 10 ++++++---- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index d96cadaca87eb..fcfb05480d6df 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -1912,7 +1912,7 @@ impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag { if let Some(const_anon) = const_anon { diag.note(msg!("items in an anonymous const item (`const _: () = {\"{\"} ... {\"}\"}`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint")); if let Some(const_anon) = const_anon { - diag.span_suggestion( + diag.span_suggestion_verbose( const_anon, msg!("use a const-anon item to suppress this lint"), "_", diff --git a/tests/ui/lint/non-local-defs/consts.stderr b/tests/ui/lint/non-local-defs/consts.stderr index fc5ce85ac613f..4391b66ff9a4e 100644 --- a/tests/ui/lint/non-local-defs/consts.stderr +++ b/tests/ui/lint/non-local-defs/consts.stderr @@ -2,10 +2,7 @@ warning: non-local `impl` definition, `impl` blocks should be written at the sam --> $DIR/consts.rs:13:5 | LL | const Z: () = { - | ----------- - | | | - | | help: use a const-anon item to suppress this lint: `_` - | move the `impl` block outside of this constant `Z` + | ----------- move the `impl` block outside of this constant `Z` ... LL | impl Uto for &Test {} | ^^^^^---^^^^^^---- @@ -16,6 +13,11 @@ LL | impl Uto for &Test {} = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: items in an anonymous const item (`const _: () = { ... }`) are treated as in the same scope as the anonymous const's declaration for the purpose of this lint = note: `#[warn(non_local_definitions)]` on by default +help: use a const-anon item to suppress this lint + | +LL - const Z: () = { +LL + const _: () = { + | warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/consts.rs:24:5 From 70854cda098e87eaef00324fb5d5a60e28810308 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 03:05:52 +0000 Subject: [PATCH 0433/1309] Use verbose suggestion for `mut binding` instead of `&mut binding` ``` error[E0308]: mismatched types --> $DIR/ref-pat-suggestions.rs:29:13 | LL | let &mut _a = 0; | ^^^^^^^ - this expression has type `{integer}` | | | expected integer, found `&mut _` | = note: expected type `{integer}` found mutable reference `&mut _` help: to declare a mutable variable use | LL - let &mut _a = 0; LL + let mut _a = 0; | ``` --- compiler/rustc_hir_typeck/src/pat.rs | 2 +- tests/ui/mismatched_types/ref-pat-suggestions.stderr | 6 +++++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..cb3768e7134f1 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -1459,7 +1459,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } _ if let Some((sp, msg, sugg)) = mut_var_suggestion => { - err.span_suggestion(sp, msg, sugg, Applicability::MachineApplicable); + err.span_suggestion_verbose(sp, msg, sugg, Applicability::MachineApplicable); } _ => {} // don't provide suggestions in other cases #55175 } diff --git a/tests/ui/mismatched_types/ref-pat-suggestions.stderr b/tests/ui/mismatched_types/ref-pat-suggestions.stderr index d3b605fabf5c5..bfd3ad80bffbf 100644 --- a/tests/ui/mismatched_types/ref-pat-suggestions.stderr +++ b/tests/ui/mismatched_types/ref-pat-suggestions.stderr @@ -314,10 +314,14 @@ LL | let &mut _a = 0; | ^^^^^^^ - this expression has type `{integer}` | | | expected integer, found `&mut _` - | help: to declare a mutable variable use: `mut _a` | = note: expected type `{integer}` found mutable reference `&mut _` +help: to declare a mutable variable use + | +LL - let &mut _a = 0; +LL + let mut _a = 0; + | error[E0308]: mismatched types --> $DIR/ref-pat-suggestions.rs:30:15 From 179b42dcaf2a94b44aee8b24d28e2de7f748aed7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 00:42:58 +0000 Subject: [PATCH 0434/1309] Use verbose suggestion for similarly named label suggestion --- .../rustc_resolve/src/late/diagnostics.rs | 2 +- tests/ui/label/label_misspelled.stderr | 40 +++++++++++-------- tests/ui/label/label_misspelled_2.stderr | 20 ++++++---- tests/ui/loops/loop-break-value.stderr | 10 +++-- .../recover/recover-unticked-labels.stderr | 11 +++-- 5 files changed, 50 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4a6846d09a8c4..c809b9a524a2b 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1511,7 +1511,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .. })) = source { - err.span_suggestion( + err.span_suggestion_verbose( span, "use the similarly named label", label_ident.name, diff --git a/tests/ui/label/label_misspelled.stderr b/tests/ui/label/label_misspelled.stderr index 9f9d32dce6b5d..95ec9beeddc4d 100644 --- a/tests/ui/label/label_misspelled.stderr +++ b/tests/ui/label/label_misspelled.stderr @@ -40,10 +40,12 @@ error[E0425]: cannot find value `LOOP` in this scope LL | 'LOOP: loop { | ----- a label with a similar name exists LL | break LOOP; - | ^^^^ - | | - | not found in this scope - | help: use the similarly named label: `'LOOP` + | ^^^^ not found in this scope + | +help: use the similarly named label + | +LL | break 'LOOP; + | + error[E0425]: cannot find value `while_loop` in this scope --> $DIR/label_misspelled.rs:32:15 @@ -51,10 +53,12 @@ error[E0425]: cannot find value `while_loop` in this scope LL | 'while_loop: while true { | ----------- a label with a similar name exists LL | break while_loop; - | ^^^^^^^^^^ - | | - | not found in this scope - | help: use the similarly named label: `'while_loop` + | ^^^^^^^^^^ not found in this scope + | +help: use the similarly named label + | +LL | break 'while_loop; + | + error[E0425]: cannot find value `while_let` in this scope --> $DIR/label_misspelled.rs:36:15 @@ -62,10 +66,12 @@ error[E0425]: cannot find value `while_let` in this scope LL | 'while_let: while let Some(_) = Some(()) { | ---------- a label with a similar name exists LL | break while_let; - | ^^^^^^^^^ - | | - | not found in this scope - | help: use the similarly named label: `'while_let` + | ^^^^^^^^^ not found in this scope + | +help: use the similarly named label + | +LL | break 'while_let; + | + error[E0425]: cannot find value `for_loop` in this scope --> $DIR/label_misspelled.rs:40:15 @@ -73,10 +79,12 @@ error[E0425]: cannot find value `for_loop` in this scope LL | 'for_loop: for _ in 0..3 { | --------- a label with a similar name exists LL | break for_loop; - | ^^^^^^^^ - | | - | not found in this scope - | help: use the similarly named label: `'for_loop` + | ^^^^^^^^ not found in this scope + | +help: use the similarly named label + | +LL | break 'for_loop; + | + warning: denote infinite loops with `loop { ... }` --> $DIR/label_misspelled.rs:4:5 diff --git a/tests/ui/label/label_misspelled_2.stderr b/tests/ui/label/label_misspelled_2.stderr index 10b0e7b4e0888..e11e4056d80e2 100644 --- a/tests/ui/label/label_misspelled_2.stderr +++ b/tests/ui/label/label_misspelled_2.stderr @@ -26,10 +26,12 @@ error[E0425]: cannot find value `b` in this scope LL | 'b: for _ in 0..1 { | -- a label with a similar name exists LL | break b; - | ^ - | | - | not found in this scope - | help: use the similarly named label: `'b` + | ^ not found in this scope + | +help: use the similarly named label + | +LL | break 'b; + | + error[E0425]: cannot find value `d` in this scope --> $DIR/label_misspelled_2.rs:14:15 @@ -37,10 +39,12 @@ error[E0425]: cannot find value `d` in this scope LL | d: for _ in 0..1 { | - a label with a similar name exists LL | break d; - | ^ - | | - | not found in this scope - | help: use the similarly named label: `'d` + | ^ not found in this scope + | +help: use the similarly named label + | +LL | break 'd; + | + error: aborting due to 4 previous errors diff --git a/tests/ui/loops/loop-break-value.stderr b/tests/ui/loops/loop-break-value.stderr index 432f6be699cbf..e0f49a24f9fd3 100644 --- a/tests/ui/loops/loop-break-value.stderr +++ b/tests/ui/loops/loop-break-value.stderr @@ -22,10 +22,12 @@ error[E0425]: cannot find value `LOOP` in this scope LL | 'LOOP: for _ in 0 .. 9 { | ----- a label with a similar name exists LL | break LOOP; - | ^^^^ - | | - | not found in this scope - | help: use the similarly named label: `'LOOP` + | ^^^^ not found in this scope + | +help: use the similarly named label + | +LL | break 'LOOP; + | + warning: denote infinite loops with `loop { ... }` --> $DIR/loop-break-value.rs:28:5 diff --git a/tests/ui/parser/recover/recover-unticked-labels.stderr b/tests/ui/parser/recover/recover-unticked-labels.stderr index 5cf463677af1d..afa3b71bb666c 100644 --- a/tests/ui/parser/recover/recover-unticked-labels.stderr +++ b/tests/ui/parser/recover/recover-unticked-labels.stderr @@ -24,11 +24,14 @@ error[E0425]: cannot find value `label` in this scope --> $DIR/recover-unticked-labels.rs:4:26 | LL | 'label: loop { break label }; - | ------ ^^^^^ - | | | - | | not found in this scope - | | help: use the similarly named label: `'label` + | ------ ^^^^^ not found in this scope + | | | a label with a similar name exists + | +help: use the similarly named label + | +LL | 'label: loop { break 'label }; + | + error: aborting due to 3 previous errors From 54f9e876866923be1f1e40a6315532f8eae96a87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 19 Sep 2026 22:54:23 +0000 Subject: [PATCH 0435/1309] Be more explicit on suggestion type without changing how they are rendered Replace `span_suggestion` calls with more specific ones, without affecting the output. --- compiler/rustc_attr_parsing/src/diagnostics.rs | 2 +- compiler/rustc_builtin_macros/src/util.rs | 2 +- compiler/rustc_expand/src/mbe/metavar_expr.rs | 2 +- .../diagnostics/wrong_number_of_generic_args.rs | 6 +++--- compiler/rustc_hir_typeck/src/diagnostics.rs | 8 ++++---- compiler/rustc_hir_typeck/src/expr.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 6 +++--- compiler/rustc_lint/src/diagnostics.rs | 4 ++-- compiler/rustc_resolve/src/late/diagnostics.rs | 15 +++++++++------ .../src/error_reporting/infer/mod.rs | 4 ++-- .../error_reporting/traits/fulfillment_errors.rs | 7 ++++--- 11 files changed, 31 insertions(+), 27 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index e5f49690f71dc..aa310595cb3f1 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1604,7 +1604,7 @@ impl<'a, G> Diagnostic<'a, G> for AttributeParseError<'_> { match &self.reason { AttributeParseErrorReason::ExpectedStringLiteral { byte_string } => { if let Some(start_point_span) = byte_string { - diag.span_suggestion( + diag.span_suggestion_short( *start_point_span, "consider removing the prefix", "", diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 80fa3e3b8ac8d..1becc2d61ba0b 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -106,7 +106,7 @@ pub(crate) fn expr_to_spanned_string<'a>( Ok(ast::LitKind::ByteStr(..)) => { let mut err = cx.dcx().struct_span_err(expr.span, err_msg); let span = expr.span.shrink_to_lo(); - err.span_suggestion( + err.span_suggestion_short( span.with_hi(span.lo() + BytePos(1)), "consider removing the leading `b`", "", diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index a02b84204cb39..01712e7f34f74 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -282,7 +282,7 @@ fn parse_ident_from_token<'psess>( let mut err = psess .dcx() .struct_span_err(token.span, format!("expected identifier, found `{token_str}`")); - err.span_suggestion( + err.span_suggestion_short( token.span, format!("try removing `{token_str}`"), "", diff --git a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs index e995d4fdf697b..410dc61aa372b 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs @@ -955,7 +955,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let msg_lifetimes = format!("remove the lifetime argument{s}", s = pluralize!(num_redundant_lt_args)); - err.span_suggestion( + err.span_suggestion_short( span_redundant_lt_args, msg_lifetimes, "", @@ -1004,7 +1004,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { s = pluralize!(num_redundant_gen_args), ); - err.span_suggestion( + err.span_suggestion_short( span_redundant_type_or_const_args, msg_types_or_consts, "", @@ -1082,7 +1082,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { // no code, which would trigger an `assert!` later. Ideally, we would do something a // bit more principled. See closed PR #109082. } else { - err.span_suggestion(span, msg, "", Applicability::MaybeIncorrect); + err.span_suggestion_short(span, msg, "", Applicability::MaybeIncorrect); } } else if redundant_lifetime_args && redundant_type_or_const_args { remove_lifetime_args(err); diff --git a/compiler/rustc_hir_typeck/src/diagnostics.rs b/compiler/rustc_hir_typeck/src/diagnostics.rs index 3b7de7790ac02..b3e1709c18072 100644 --- a/compiler/rustc_hir_typeck/src/diagnostics.rs +++ b/compiler/rustc_hir_typeck/src/diagnostics.rs @@ -360,7 +360,7 @@ impl Subdiagnostic for TypeMismatchFruTypo { ); } - diag.span_suggestion( + diag.span_suggestion_verbose( self.expr_span.shrink_to_hi(), msg!( "to set the remaining fields{$expr -> @@ -718,7 +718,7 @@ impl<'a, G> Diagnostic<'_, G> for BreakNonLoop<'a> { if let Some(head) = self.head { diag.span_label(head, msg!("you can't `break` with a value in a `{$kind}` loop")); } - diag.span_suggestion( + diag.span_suggestion_verbose( self.span, msg!("use `break` on its own without a value inside this `{$kind}` loop"), self.suggestion, @@ -736,7 +736,7 @@ impl<'a, G> Diagnostic<'_, G> for BreakNonLoop<'a> { diag.downgrade_to_delayed_bug(); } _ => { - diag.span_suggestion( + diag.span_suggestion_verbose( self.break_expr_span, msg!("alternatively, you might have meant to use the available loop label"), label.ident, @@ -1249,7 +1249,7 @@ pub(crate) fn maybe_emit_plus_equals_diagnostic<'a>( err.span_label(assign_op.span, "cannot use `+=` in a let chain"); - err.span_suggestion( + err.span_suggestion_short( assign_op.span, "you might have meant to compare with `==` instead of assigning with `+=`", "==", diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index a8898acf3a415..83779f01be8a3 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1717,7 +1717,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, StashKey::UnderscoreForArrayLengths, |err| { - err.span_suggestion( + err.span_suggestion_verbose( span, "consider specifying the array length", array_len, diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index caffef6a217a8..13ee9b06b2d2e 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -2646,7 +2646,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } }; - err.span_suggestion( + err.span_suggestion_verbose( sp, format!( "include the missing field{} in the pattern{}", @@ -2669,7 +2669,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), Applicability::MachineApplicable, ); - err.span_suggestion( + err.span_suggestion_verbose( sp, format!( "if you don't care about {these} missing field{s}, you can explicitly ignore {them}", @@ -2693,7 +2693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), Applicability::MachineApplicable, ); - err.span_suggestion( + err.span_suggestion_verbose( sp, "or always ignore missing fields here", format!("{prefix}..{postfix}"), diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index d96cadaca87eb..2a0624162f261 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -1653,7 +1653,7 @@ impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { .with_arg("count", self.count) .with_note(msg!("this message is not used as a format string when given without arguments, but will be in Rust 2021")); if let Some(span) = self.suggestion { - diag.span_suggestion( + diag.span_suggestion_verbose( span.shrink_to_hi(), msg!( "add the missing {$count -> @@ -1664,7 +1664,7 @@ impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { ", ...", Applicability::HasPlaceholders, ); - diag.span_suggestion( + diag.span_suggestion_verbose( span.shrink_to_lo(), msg!(r#"or add a "{"{"}{"}"}" format string to use the message literally"#), "\"{}\", ", diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4a6846d09a8c4..531e925e8cd7e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -765,12 +765,15 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { if let Some((did, item)) = self.lookup_doc_alias_name(path, source.namespace()) { let item_name = item.name; let suggestion_name = self.r.tcx.item_name(did); - err.span_suggestion( + err.span_suggestion_verbose( item.span, - format!("`{suggestion_name}` has a name defined in the doc alias attribute as `{item_name}`"), - suggestion_name, - Applicability::MaybeIncorrect - ); + format!( + "`{suggestion_name}` has a name defined in the doc alias attribute as \ + `{item_name}`", + ), + suggestion_name, + Applicability::MaybeIncorrect, + ); return (err, Vec::new()); }; @@ -2517,7 +2520,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // The span contains a type alias so we should be able to // replace `type` with `trait`. let snip = snip.replacen("type", "trait", 1); - err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect); + err.span_suggestion_verbose(span, msg, snip, Applicability::MaybeIncorrect); } else { err.span_help(span, msg); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index c798e4e953051..76edf906bca94 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -413,7 +413,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { match scrut_ty { Some(ty) if expected == ty => { let source_map = self.tcx.sess.source_map(); - err.span_suggestion( + err.span_suggestion_short( source_map.end_point(cause.span), "try removing this `?`", "", @@ -452,7 +452,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { match scrut_ty { Some(ty) if expected == ty => { let source_map = self.tcx.sess.source_map(); - err.span_suggestion( + err.span_suggestion_short( source_map.end_point(cause.span), "try removing this `?`", "", diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 26d768e5b22e8..fe901758995d8 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1458,7 +1458,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.dcx(), span, E0741, - "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const generic parameter", + "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const \ + generic parameter", ); // Only suggest derive if this isn't a derived obligation, // and the struct is local. @@ -1466,7 +1467,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { && obligation.cause.code().parent().is_none() { if ty.is_structural_eq_shallow(self.tcx) { - diag.span_suggestion( + diag.span_suggestion_verbose( span.shrink_to_lo(), format!("add `#[derive(ConstParamTy)]` to the {}", def.descr()), "#[derive(ConstParamTy)]\n", @@ -1475,7 +1476,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } else { // FIXME(adt_const_params): We should check there's not already an // overlapping `Eq`/`PartialEq` impl. - diag.span_suggestion( + diag.span_suggestion_verbose( span.shrink_to_lo(), format!( "add `#[derive(ConstParamTy, PartialEq, Eq)]` to the {}", From f546efefdac9925fb8a7d227dc53dab898ee55f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 00:57:56 +0000 Subject: [PATCH 0436/1309] Use verbose suggestion for wrong primitive type names ``` error[E0425]: cannot find type `double` in this scope --> $DIR/recommend-literal.rs:1:13 | LL | type Real = double; | ^^^^^^ not found in this scope | help: you might have intended to use the `f64` primitive type | LL - type Real = double; LL + type Real = f64; | ``` --- .../rustc_resolve/src/late/diagnostics.rs | 4 +- tests/ui/lint/recommend-literal.rs | 18 ++--- tests/ui/lint/recommend-literal.stderr | 81 ++++++++++++------- 3 files changed, 62 insertions(+), 41 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4a6846d09a8c4..950cbd7bc092e 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1527,9 +1527,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { self.suggest_ident_hidden_by_hygiene(err, path, span); // cannot find type in this scope if let Some(correct) = Self::likely_rust_type(path) { - err.span_suggestion( + err.span_suggestion_verbose( span, - "perhaps you intended to use this type", + format!("you might have intended to use the `{correct}` primitive type"), correct, Applicability::MaybeIncorrect, ); diff --git a/tests/ui/lint/recommend-literal.rs b/tests/ui/lint/recommend-literal.rs index 4eae569df130f..93869d8b90a2a 100644 --- a/tests/ui/lint/recommend-literal.rs +++ b/tests/ui/lint/recommend-literal.rs @@ -1,43 +1,43 @@ type Real = double; //~^ ERROR cannot find type `double` in this scope -//~| HELP perhaps you intended to use this type +//~| HELP `f64` primitive type fn main() { let x: Real = 3.5; let y: long = 74802374902374923; //~^ ERROR cannot find type `long` in this scope - //~| HELP perhaps you intended to use this type + //~| HELP `i64` primitive type let v1: Boolean = true; //~^ ERROR: cannot find type `Boolean` in this scope [E0425] - //~| HELP perhaps you intended to use this type + //~| HELP `bool` primitive type let v2: Bool = true; //~^ ERROR: cannot find type `Bool` in this scope [E0425] //~| HELP a builtin type with a similar name exists - //~| HELP perhaps you intended to use this type + //~| HELP `bool` primitive type //~| HELP: there is an enum variant `std::mem::type_info::TypeKind::Bool`; try using the variant's enum } fn z(a: boolean) { //~^ ERROR cannot find type `boolean` in this scope - //~| HELP perhaps you intended to use this type + //~| HELP `bool` primitive type } fn a() -> byte { //~^ ERROR cannot find type `byte` in this scope -//~| HELP perhaps you intended to use this type +//~| HELP `u8` primitive type 3 } struct Data { //~ HELP you might be missing a type parameter width: float, //~^ ERROR cannot find type `float` in this scope - //~| HELP perhaps you intended to use this type + //~| HELP `f32` primitive type depth: Option, //~^ ERROR cannot find type `int` in this scope - //~| HELP perhaps you intended to use this type + //~| HELP `i32` primitive type } trait Stuff {} impl Stuff for short {} //~^ ERROR cannot find type `short` in this scope -//~| HELP perhaps you intended to use this type +//~| HELP `i16` primitive type diff --git a/tests/ui/lint/recommend-literal.stderr b/tests/ui/lint/recommend-literal.stderr index 2dc2259a56742..9dcce3fd381fd 100644 --- a/tests/ui/lint/recommend-literal.stderr +++ b/tests/ui/lint/recommend-literal.stderr @@ -2,28 +2,37 @@ error[E0425]: cannot find type `double` in this scope --> $DIR/recommend-literal.rs:1:13 | LL | type Real = double; - | ^^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `f64` + | ^^^^^^ not found in this scope + | +help: you might have intended to use the `f64` primitive type + | +LL - type Real = double; +LL + type Real = f64; + | error[E0425]: cannot find type `long` in this scope --> $DIR/recommend-literal.rs:7:12 | LL | let y: long = 74802374902374923; - | ^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `i64` + | ^^^^ not found in this scope + | +help: you might have intended to use the `i64` primitive type + | +LL - let y: long = 74802374902374923; +LL + let y: i64 = 74802374902374923; + | error[E0425]: cannot find type `Boolean` in this scope --> $DIR/recommend-literal.rs:10:13 | LL | let v1: Boolean = true; - | ^^^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `bool` + | ^^^^^^^ not found in this scope + | +help: you might have intended to use the `bool` primitive type + | +LL - let v1: Boolean = true; +LL + let v1: bool = true; + | error[E0425]: cannot find type `Bool` in this scope --> $DIR/recommend-literal.rs:13:13 @@ -41,7 +50,7 @@ help: a builtin type with a similar name exists LL - let v2: Bool = true; LL + let v2: bool = true; | -help: perhaps you intended to use this type +help: you might have intended to use the `bool` primitive type | LL - let v2: Bool = true; LL + let v2: bool = true; @@ -51,28 +60,37 @@ error[E0425]: cannot find type `boolean` in this scope --> $DIR/recommend-literal.rs:20:9 | LL | fn z(a: boolean) { - | ^^^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `bool` + | ^^^^^^^ not found in this scope + | +help: you might have intended to use the `bool` primitive type + | +LL - fn z(a: boolean) { +LL + fn z(a: bool) { + | error[E0425]: cannot find type `byte` in this scope --> $DIR/recommend-literal.rs:25:11 | LL | fn a() -> byte { - | ^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `u8` + | ^^^^ not found in this scope + | +help: you might have intended to use the `u8` primitive type + | +LL - fn a() -> byte { +LL + fn a() -> u8 { + | error[E0425]: cannot find type `float` in this scope --> $DIR/recommend-literal.rs:32:12 | LL | width: float, - | ^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `f32` + | ^^^^^ not found in this scope + | +help: you might have intended to use the `f32` primitive type + | +LL - width: float, +LL + width: f32, + | error[E0425]: cannot find type `int` in this scope --> $DIR/recommend-literal.rs:35:19 @@ -80,7 +98,7 @@ error[E0425]: cannot find type `int` in this scope LL | depth: Option, | ^^^ not found in this scope | -help: perhaps you intended to use this type +help: you might have intended to use the `i32` primitive type | LL - depth: Option, LL + depth: Option, @@ -94,10 +112,13 @@ error[E0425]: cannot find type `short` in this scope --> $DIR/recommend-literal.rs:41:16 | LL | impl Stuff for short {} - | ^^^^^ - | | - | not found in this scope - | help: perhaps you intended to use this type: `i16` + | ^^^^^ not found in this scope + | +help: you might have intended to use the `i16` primitive type + | +LL - impl Stuff for short {} +LL + impl Stuff for i16 {} + | error: aborting due to 9 previous errors From 19c656c2a4f278d648dbdf508580e76912c780a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 00:51:30 +0000 Subject: [PATCH 0437/1309] Use verbose suggestion for method written as function ``` error[E0425]: cannot find function `bar` in this scope --> $DIR/suggest-self-2.rs:9:9 | LL | bar(&&self, 102); | ^^^ | help: try calling `bar` as a method | LL - bar(&&self, 102); LL + self.bar(102); | ``` --- .../rustc_resolve/src/late/diagnostics.rs | 2 +- tests/ui/self/suggest-self-2.stderr | 30 +++++++++++++------ 2 files changed, 22 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4a6846d09a8c4..299154b05d440 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1217,7 +1217,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { err.note("constructor is not visible here due to private fields"); } } else { - err.span_suggestion( + err.span_suggestion_verbose( call_span, format!("try calling `{ident}` as a method"), format!("self.{path_str}({args_snippet})"), diff --git a/tests/ui/self/suggest-self-2.stderr b/tests/ui/self/suggest-self-2.stderr index 4bd025ea07630..90d2e5b7aa7f3 100644 --- a/tests/ui/self/suggest-self-2.stderr +++ b/tests/ui/self/suggest-self-2.stderr @@ -2,25 +2,37 @@ error[E0425]: cannot find function `bar` in this scope --> $DIR/suggest-self-2.rs:5:9 | LL | bar(self); - | ^^^------ - | | - | help: try calling `bar` as a method: `self.bar()` + | ^^^ + | +help: try calling `bar` as a method + | +LL - bar(self); +LL + self.bar(); + | error[E0425]: cannot find function `bar` in this scope --> $DIR/suggest-self-2.rs:9:9 | LL | bar(&&self, 102); - | ^^^------------- - | | - | help: try calling `bar` as a method: `self.bar(102)` + | ^^^ + | +help: try calling `bar` as a method + | +LL - bar(&&self, 102); +LL + self.bar(102); + | error[E0425]: cannot find function `bar` in this scope --> $DIR/suggest-self-2.rs:13:9 | LL | bar(&mut self, 102, &"str"); - | ^^^------------------------ - | | - | help: try calling `bar` as a method: `self.bar(102, &"str")` + | ^^^ + | +help: try calling `bar` as a method + | +LL - bar(&mut self, 102, &"str"); +LL + self.bar(102, &"str"); + | error[E0425]: cannot find function `bar` in this scope --> $DIR/suggest-self-2.rs:17:9 From f1e9e5e4aa3f6b868e0108a710affa0fcd642921 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Aug 2026 14:23:04 +0000 Subject: [PATCH 0438/1309] When error from local macro, include macro def span - mention `-Zmacro-backtrace` only for non-local macros - include span for local macro encompassing error --- compiler/rustc_errors/src/emitter.rs | 69 +++++-- .../undocumented_unsafe_blocks.default.stderr | 18 +- ...undocumented_unsafe_blocks.disabled.stderr | 18 +- .../clippy/tests/ui/async_yields_async.stderr | 4 +- src/tools/clippy/tests/ui/cast.stderr | 10 +- .../tests/ui/cast_lossless_integer.stderr | 3 +- .../checked_unwrap/simple_conditionals.stderr | 4 +- .../tests/ui/cmp_owned/with_suggestion.stderr | 4 +- .../clippy/tests/ui/collapsible_match2.stderr | 3 +- .../clippy/tests/ui/crashes/ice-6255.stderr | 7 +- .../tests/ui/dbg_macro/dbg_macro.stderr | 3 +- src/tools/clippy/tests/ui/doc_unsafe.stderr | 4 +- .../clippy/tests/ui/double_parens.stderr | 15 +- .../tests/ui/duration_suboptimal_units.stderr | 3 +- src/tools/clippy/tests/ui/eq_op_macros.stderr | 15 +- src/tools/clippy/tests/ui/exit1.stderr | 4 +- .../clippy/tests/ui/incompatible_msrv.stderr | 4 +- .../ui/integer_division_remainder_used.stderr | 4 +- .../tests/ui/into_iter_without_iter.stderr | 3 +- .../tests/ui/items_after_statement.stderr | 4 +- .../tests/ui/iter_without_into_iter.stderr | 3 +- .../clippy/tests/ui/large_futures.stderr | 3 +- .../clippy/tests/ui/large_stack_arrays.stderr | 8 +- .../tests/ui/legacy_numeric_constants.stderr | 3 +- .../legacy_numeric_constants_unfixable.stderr | 3 +- .../clippy/tests/ui/manual_div_ceil.stderr | 8 +- .../clippy/tests/ui/manual_let_else.stderr | 4 +- .../tests/ui/manual_range_patterns.stderr | 4 +- .../ui/missing_transmute_annotations.stderr | 4 +- .../tests/ui/needless_question_mark.stderr | 3 +- .../ui/pattern_type_mismatch/syntax.stderr | 3 +- .../tests/ui/redundant_async_block.stderr | 8 +- .../ui/redundant_closure_call_fixable.stderr | 19 +- .../tests/ui/redundant_field_names.stderr | 4 +- .../tests/ui/string_lit_as_bytes.stderr | 4 +- .../clippy/tests/ui/struct_fields.stderr | 14 +- .../ui/suspicious_xor_used_as_pow.stderr | 3 +- .../tests/ui/unconditional_recursion.stderr | 3 +- .../tests/ui/uninhabited_references.stderr | 8 +- .../ui/unnecessary_safety_comment.stderr | 3 +- .../tests/ui/unnecessary_unsafety_doc.stderr | 4 +- .../ui/unseparated_prefix_literals.stderr | 4 +- .../clippy/tests/ui/unused_result_ok.stderr | 3 +- .../miri/tests/fail/shims/ctor_ub.stderr | 3 +- .../fail/shims/ctor_wrong_ret_type.stderr | 3 +- tests/rustdoc-ui/macro-docs.stderr | 3 +- .../lint_pass_impl_without_macro.rs | 2 + .../lint_pass_impl_without_macro.stderr | 9 +- .../extra_arguments.stderr | 9 +- .../ui/asm/aarch64/interpolated-idents.stderr | 12 +- .../ui/asm/x86_64/interpolated-idents.stderr | 12 +- ...-trait-bound-theoretical-regression.stderr | 6 +- tests/ui/async-await/issue-73541-2.stderr | 4 +- tests/ui/async-await/unnecessary-await.stderr | 3 +- .../ui/attributes/key-value-expansion.stderr | 8 +- .../attributes/nonterminal-expansion.stderr | 4 +- tests/ui/borrowck/issue-25793.stderr | 4 +- tests/ui/borrowck/move-error-snippets.stderr | 14 +- .../span-semicolon-issue-139049.stderr | 2 - ...-eval-derive-invalid-reparse-no-ice.stderr | 3 +- tests/ui/cfg/cfg-method-receiver.stderr | 3 +- tests/ui/cfg/path-kw-as-cfg-pred.stderr | 9 +- .../closure-body-macro-fragment.stderr | 3 +- .../cfg-attr-syntax-validation.stderr | 4 +- ...r-unknown-attribute-macro-expansion.stderr | 4 +- .../cfg_attr-attr-syntax-validation.stderr | 3 +- ...const_arg_trivial_macro_expansion-2.stderr | 3 +- ...const_arg_trivial_macro_expansion-4.stderr | 6 +- ...ial-const-arg-macro-nested-braces-2.stderr | 3 +- ...ivial-const-arg-macro-nested-braces.stderr | 3 +- .../trivial-const-arg-macro-res-error.stderr | 4 +- .../mgca/macro-const-arg-infer.stderr | 8 +- .../macro-fail-const.stderr | 6 +- .../min_const_generics/macro-fail.stderr | 9 +- .../consts/const-item-no-type/in-macro.stderr | 10 +- tests/ui/consts/enum-discr-type-err.stderr | 6 +- tests/ui/coroutine/parent-expression.stderr | 9 +- tests/ui/delegation/self-hygiene.stderr | 2 - .../unused-target-expr-in-glob-or-list.stderr | 52 ++--- .../on_unknown/point_at_macro_argument.stderr | 8 +- tests/ui/did_you_mean/bad-assoc-expr.stderr | 2 +- tests/ui/did_you_mean/bad-assoc-pat.stderr | 5 +- .../bad-assoc-ty.edition2015.stderr | 4 +- .../bad-assoc-ty.edition2021.stderr | 4 +- .../dont-suggest-hygienic-fields.stderr | 3 +- .../did_you_mean/recursion_limit_deref.stderr | 3 +- .../did_you_mean/recursion_limit_macro.stderr | 3 +- .../macro-expanded-mod.stderr | 3 +- .../dollar-crate-is-keyword-2.stderr | 12 +- .../dollar-crate-is-keyword.stderr | 11 +- .../lint-if-let-rescope-with-macro.stderr | 3 +- .../ui/editions/edition-cstr-2015-2018.stderr | 3 - tests/ui/expr/if/if-let.stderr | 14 +- ...-allow-internal-unsafe-nested-macro.stderr | 3 +- ...llow-internal-unstable-nested-macro.stderr | 3 +- ...-gate-check-nested-macro-invocation.stderr | 6 +- .../ui/feature-gates/trace_macros-gate.stderr | 2 +- .../format-args-capture-macro-hygiene.stderr | 2 +- .../fn-arg-count-mismatch-diagnostics.stderr | 6 +- .../label_break_value_invalid.stderr | 4 +- tests/ui/for-loop-while/while-let-2.stderr | 14 +- .../generics-on-self-mod-segment.stderr | 4 +- .../wrong-number-of-args-in-macro.stderr | 6 +- ...pats-inclusive-dotdotdot-bad-syntax.stderr | 6 +- ...lf-open-range-pats-inclusive-no-end.stderr | 12 +- ...pe.bound_a_b_ret_a_vs_bound_a_ret_a.stderr | 3 +- .../hr-subtype.bound_a_vs_free_x.stderr | 3 +- ...ubtype.bound_inv_a_b_vs_bound_inv_a.stderr | 6 +- ...hr-subtype.free_inv_x_vs_free_inv_y.stderr | 6 +- .../hr-subtype.free_x_vs_free_y.stderr | 3 +- tests/ui/hygiene/assoc_item_ctxt.stderr | 7 +- tests/ui/hygiene/duplicate_lifetimes.stderr | 6 +- ...xtern-prelude-from-opaque-fail-2018.stderr | 7 +- .../extern-prelude-from-opaque-fail.stderr | 7 +- tests/ui/hygiene/fields-definition.stderr | 4 +- tests/ui/hygiene/fields-move.stderr | 3 +- tests/ui/hygiene/fields.stderr | 16 +- tests/ui/hygiene/generate-mod.stderr | 16 +- tests/ui/hygiene/globs.stderr | 9 +- tests/ui/hygiene/hygienic-label-1.stderr | 3 +- tests/ui/hygiene/hygienic-label-3.stderr | 3 +- tests/ui/hygiene/impl_items.stderr | 3 +- tests/ui/hygiene/missing-self-diag.stderr | 3 +- tests/ui/hygiene/no_implicit_prelude.stderr | 5 +- tests/ui/hygiene/pattern-macro.stderr | 3 +- tests/ui/hygiene/privacy-early.stderr | 4 +- .../hygiene/rustc-macro-transparency.stderr | 3 +- tests/ui/hygiene/trait_items.stderr | 1 - .../dont-probe-missing-item-name-4.stderr | 3 +- .../ambiguous-import-visibility-macro.stderr | 3 +- .../ambiguous-import-visibility-module.stderr | 3 +- .../extern-prelude-extern-crate-fail.stderr | 4 +- ...e-extern-crate-restricted-shadowing.stderr | 7 +- tests/ui/imports/import-prefix-macro-1.stderr | 3 +- tests/ui/imports/import-prefix-macro-2.stderr | 3 +- tests/ui/imports/issue-109148.stderr | 10 +- tests/ui/imports/issue-114682-1.stderr | 3 +- .../local-modularized-tricky-fail-1.stderr | 9 +- .../local-modularized-tricky-fail-2.stderr | 12 +- ...ultiple-extern-by-macro-for-buitlin.stderr | 5 +- ...multiple-extern-by-macro-for-custom.stderr | 5 +- ...ultiple-extern-by-macro-for-inexist.stderr | 3 +- tests/ui/imports/point_macro_input.stderr | 4 +- .../private-from-decl-macro.fail.stderr | 3 +- tests/ui/imports/shadow_builtin_macros.stderr | 3 +- .../infinite/infinite-macro-expansion.stderr | 2 +- tests/ui/internal/internal-unstable.stderr | 16 +- .../macro.stderr | 3 +- .../cstring-as-ptr.stderr | 3 +- ...-future_breakage-crash-issue-126521.stderr | 14 +- .../lint/lint-double-negations-macro.stderr | 3 +- .../lint-raw-borrows-via-references.stderr | 3 +- .../lint-strict-provenance-macro-casts.stderr | 10 +- tests/ui/lint/lint-unsafe-code.stderr | 16 +- tests/ui/lint/lints-in-foreign-macros.stderr | 2 +- .../non-local-defs/inside-macro_rules.stderr | 3 +- ...emi-in-macro-expansion-issue-142143.stderr | 2 +- .../expect_lint_from_macro.stderr | 6 +- ...emicolon-in-expressions-from-macros.stderr | 30 ++- ...emicolon-in-expressions-from-macros.stderr | 6 +- tests/ui/lint/static-mut-refs.e2021.stderr | 3 +- tests/ui/lint/static-mut-refs.e2024.stderr | 3 +- tests/ui/lint/unreachable_pub.stderr | 2 +- .../lint-global-asm-as-unsafe.stderr | 3 +- tests/ui/lint/unused-visibilities.stderr | 3 +- .../unused/issue-117284-arg-in-macro.stderr | 3 +- tests/ui/lint/unused/must-use-macros.stderr | 6 +- tests/ui/lint/unused/unused-macros.stderr | 4 +- ...unused-parens-in-macro-issue-120642.stderr | 11 +- tests/ui/lint/wide_pointer_comparisons.stderr | 6 +- .../liveness-return-last-stmt-semi.stderr | 2 - ...ert-ne-no-invalid-help-issue-146204.stderr | 3 +- tests/ui/macros/attr-expr.stderr | 8 +- tests/ui/macros/best-failure.stderr | 1 - tests/ui/macros/cfg_attr-expr.stderr | 3 +- ...cross-crate-nested-macro-rules-span.stderr | 16 +- tests/ui/macros/cross-file-errors.stderr | 4 +- .../deref-raw-pointer-issue-158158.stderr | 4 +- .../derive-in-eager-expansion-hang.stderr | 2 +- .../macros/expand-full-no-resolution.stderr | 6 +- .../invalid-assignment-in-macro-26093.stderr | 8 +- tests/ui/macros/issue-109237.stderr | 2 +- tests/ui/macros/issue-118786.stderr | 3 +- tests/ui/macros/issue-16098.stderr | 3 +- tests/ui/macros/issue-25385.stderr | 3 +- tests/ui/macros/issue-29084.stderr | 3 +- ...421-mac-expr-bad-stmt-good-add-semi.stderr | 6 +- tests/ui/macros/issue-42954.stderr | 3 +- tests/ui/macros/issue-51848.stderr | 3 +- tests/ui/macros/issue-6596-1.stderr | 7 +- tests/ui/macros/issue-6596-2.stderr | 4 +- ...issue-78325-inconsistent-resolution.stderr | 10 +- .../macros/issue-84195-lint-anon-const.stderr | 4 +- ...632-eager-expansion-recursion-limit.stderr | 3 +- .../ui/macros/lint-trailing-macro-call.stderr | 6 +- .../macro-adjacent-ident-on-token.stderr | 3 +- .../macro-backtrace-complex.default.stderr | 29 +-- .../macro-backtrace-invalid-internals.stderr | 30 +-- tests/ui/macros/macro-backtrace-nested.stderr | 28 +-- tests/ui/macros/macro-context.stderr | 12 +- .../macro-expansion-empty-span-147408.stderr | 3 +- .../macro-guard-matcher-recursion.stderr | 3 +- .../macro-hygiene-help-issue-148580.stderr | 1 - .../macro-hygiene-help-issue-149604.stderr | 4 +- .../macros/macro-hygiene-scope-15167.stderr | 4 - .../macros/macro-in-expression-context.stderr | 6 +- tests/ui/macros/macro-interpolation.stderr | 4 +- .../empty-input.stderr | 3 +- tests/ui/macros/macro-rules-attr-error.stderr | 4 +- ...macro-rules-attr-infinite-recursion.stderr | 3 +- .../ui/macros/macro-rules-derive-error.stderr | 4 +- tests/ui/macros/macro-shadowing.stderr | 6 +- .../ui/macros/macro-span-issue-116502.stderr | 12 +- .../metavar-expressions/concat-hygiene.stderr | 3 +- .../concat-raw-identifiers.stderr | 4 +- .../concat-trace-errors.stderr | 6 +- .../concat-usage-errors.stderr | 37 ++-- .../count-empty-index-arg.stderr | 3 +- .../metavar-expressions/usage-errors.stderr | 7 +- ...rror-in-macro-expansion-for-generic.stderr | 4 +- tests/ui/macros/nonterminal-matching.stderr | 14 +- ...te-struct-member-macro-access-25386.stderr | 4 +- .../macros/reparse-expr-issue-139495.stderr | 6 +- .../repeated-macro-expansion-error.stderr | 6 +- .../macros/restricted-shadowing-legacy.stderr | 38 ++-- .../macros/restricted-shadowing-modern.stderr | 34 +-- .../ui/macros/span-covering-argument-1.stderr | 3 +- tests/ui/macros/syntax-error-recovery.stderr | 3 +- tests/ui/macros/trace_faulty_macros.stderr | 12 +- .../ui/macros/typo-in-norepeat-expr-2.stderr | 10 +- tests/ui/macros/typo-in-norepeat-expr.stderr | 3 +- tests/ui/mismatched_types/issue-26480.stderr | 6 +- tests/ui/modules/issue-56411.stderr | 6 +- ...r-type-fallback-flowing-into-unsafe.stderr | 3 +- .../exhaustiveness-unreachable-pattern.stderr | 3 +- .../parser/attribute/attr-bad-meta-4.stderr | 4 +- .../attribute/attr-unquoted-ident.stderr | 2 +- ...-trailing-outer-attribute-in-body-2.stderr | 3 +- tests/ui/parser/bad-interpolated-block.stderr | 9 +- tests/ui/parser/bad-let-else-statement.stderr | 3 +- .../const-block-items/macro-stmt.stderr | 4 +- .../ui/parser/float-field-interpolated.stderr | 16 +- tests/ui/parser/issues/issue-44406.stderr | 3 +- ...interpolate-impl-items-bad-variants.stderr | 9 +- ...sue-65122-mac-invoc-in-mut-patterns.stderr | 10 +- .../issue-68091-unicode-ident-after-if.stderr | 4 +- .../issue-73568-lifetime-after-mut.stderr | 3 +- .../ui/parser/issues/issue-87812-path.stderr | 4 +- tests/ui/parser/issues/issue-87812.stderr | 3 +- tests/ui/parser/labeled-no-colon-expr.stderr | 3 +- .../break-in-unlabeled-block-in-macro.stderr | 15 +- tests/ui/parser/macro/issue-37113.stderr | 3 +- tests/ui/parser/macro/issue-37234.stderr | 4 +- tests/ui/parser/macro/lit-err-in-macro.stderr | 3 +- .../parser/macro/macro-attr-recovery.stderr | 4 +- .../macro/macro-incomplete-parse.stderr | 3 +- tests/ui/parser/macro/pub-item-macro.stderr | 14 +- tests/ui/parser/missing-semicolon.stderr | 4 +- tests/ui/parser/mut-patterns.stderr | 4 +- ...ecover-pat-range-macro-span-overlap.stderr | 3 +- .../parser/recover/recover-range-pats.stderr | 39 ++-- tests/ui/pattern/issue-92074-macro-ice.stderr | 6 +- .../rest-pat-semantic-disallowed.stderr | 2 +- .../associated-item-privacy-inherent.stderr | 80 ++++---- .../associated-item-privacy-trait.stderr | 116 +++++------ ...ssociated-item-privacy-type-binding.stderr | 58 +++--- tests/ui/privacy/private-inferred-type.stderr | 23 +-- .../ui/privacy/restricted/decl-macros.stderr | 8 +- ...derive-helper-shadowing.edition2015.stderr | 3 +- ...derive-helper-shadowing.edition2018.stderr | 3 +- .../proc-macro/gen-macro-rules-hygiene.stderr | 6 +- tests/ui/proc-macro/macro-rules-derive.stderr | 4 +- tests/ui/proc-macro/mixed-site-span.stderr | 12 +- .../ui/proc-macro/parent-source-spans.stderr | 40 ++-- tests/ui/proc-macro/weird-hygiene.stderr | 3 +- .../coerce-shared-decl-macro-hygiene.stderr | 3 +- tests/ui/resolve/decl-macro-use-no-ice.stderr | 2 +- ...ion-type-namespace-suggest-path-sep.stderr | 53 +++-- .../ice-inconsistent-resolution-149821.stderr | 4 +- .../ice-on-shadowing-std-with-macro.stderr | 4 +- tests/ui/resolve/issue-100365.stderr | 9 +- tests/ui/resolve/issue-82865.stderr | 3 +- tests/ui/resolve/open-ns-9.stderr | 3 +- ...uggest-path-instead-of-mod-dot-item.stderr | 12 +- ...urn-from-residual-sugg-issue-125997.stderr | 3 +- .../macro-expanded.stderr | 2 +- .../edition-lint-infer-outlives-macro.stderr | 36 ++-- ...ition-lint-infer-outlives-multispan.stderr | 15 +- .../ambiguity-macros-nested.stderr | 3 +- .../uniform-paths/ambiguity-macros.stderr | 3 +- .../unsafe-attributes-fix.stderr | 9 +- .../unsafe-attributes-from-pm-in-2024.stderr | 2 - tests/ui/simd/not-out-of-bounds.stderr | 24 +-- .../span/macro-span-caller-replacement.stderr | 3 +- .../let-binding-init-expr-as-ty.stderr | 4 +- tests/ui/suggestions/suggest-ref-macro.stderr | 3 +- ...onst-generics-structural-demangling.stderr | 12 +- ...-trait-bound-theoretical-regression.stderr | 12 +- .../ui/tuple/tuple-struct-fields/test2.stderr | 4 +- .../ui/tuple/tuple-struct-fields/test3.stderr | 4 +- ...k-fn-with-more-than-65535-arguments.stderr | 4 +- ...-116473-ice-wrong-span-variant-args.stderr | 133 +++++++----- tests/ui/typeck/issue-81943.stderr | 2 +- ...swap-equality-in-macro-issue-139050.stderr | 3 +- .../macro-shorthand-issue-140659.stderr | 20 +- .../wrapping-unsafe-block-sugg.stderr | 2 - tests/ui/use/use-path-segment-kw.e2015.stderr | 193 +++++++++--------- tests/ui/use/use-path-segment-kw.e2018.stderr | 193 +++++++++--------- 308 files changed, 1616 insertions(+), 1283 deletions(-) diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs index 749b58e5d4b82..aee5afdfd3b04 100644 --- a/compiler/rustc_errors/src/emitter.rs +++ b/compiler/rustc_errors/src/emitter.rs @@ -166,8 +166,8 @@ pub trait Emitter { let has_macro_spans: Vec<_> = iter::once(&*span) .chain(children.iter().map(|child| &child.span)) .flat_map(|span| span.primary_spans()) - .flat_map(|sp| sp.macro_backtrace()) - .filter_map(|expn_data| { + .flat_map(|sp| sp.macro_backtrace().map(move |expn_data| (sp, expn_data))) + .filter_map(|(sp, expn_data)| { match expn_data.kind { ExpnKind::Root => None, @@ -176,7 +176,16 @@ pub trait Emitter { ExpnKind::Desugaring(..) | ExpnKind::AstPass(..) => None, ExpnKind::Macro(macro_kind, name) => { - Some((macro_kind, name, expn_data.diagnostic_opaque)) + let same_line = sp + .overlaps(expn_data.def_site) + .then(|| expn_data.def_site.with_hi(sp.lo())); + Some(( + macro_kind, + name, + expn_data.diagnostic_opaque, + expn_data.def_site, + same_line, + )) } } }) @@ -188,27 +197,47 @@ pub trait Emitter { self.render_multispans_macro_backtrace(span, children, backtrace); - if !backtrace { + if !backtrace // Skip macros annotated with `#[diagnostic::opaque]`. Builtin macros are "opaque" too. - if let Some((macro_kind, name, _)) = has_macro_spans.first() - && let Some((_, _, false)) = has_macro_spans.last() + && let Some((macro_kind, name, _, sp, same_line_span)) = has_macro_spans.first() + && let Some((_, _, false, _, _)) = has_macro_spans.last() + { + // Mark the actual macro this originates from + let and_then = if let Some((macro_kind, last_name, _, _, _)) = has_macro_spans.last() + && last_name != name { - // Mark the actual macro this originates from - let and_then = if let Some((macro_kind, last_name, _)) = has_macro_spans.last() - && last_name != name + let descr = macro_kind.descr(); + format!(" which comes from the expansion of the {descr} `{last_name}`") + } else { + "".to_string() + }; + + let descr = macro_kind.descr(); + let msg = format!("this {level} originates in the {descr} `{name}`{and_then}"); + + if let Some(source_map) = self.source_map() { + if source_map.is_imported(*sp) || same_line_span.is_none() { + let msg = format!( + "{msg} (in Nightly builds, run with -Z macro-backtrace for more info)" + ); + children.push(Subdiag { + level: Sublevel::Note, + messages: vec![(DiagMessage::from(msg), Style::NoStyle)], + span: MultiSpan::new(), + }); + } else if let Some(def) = same_line_span + && source_map.is_multiline(*def) + && !and_then.is_empty() { - let descr = macro_kind.descr(); - format!(" which comes from the expansion of the {descr} `{last_name}`") + // We only point at the macro definition when it is not on the same line as the + // error produced and there are more levels of macro nesting. + span.push_span_label(*sp, msg); } else { - "".to_string() - }; - - let descr = macro_kind.descr(); - let msg = format!( - "this {level} originates in the {descr} `{name}`{and_then} \ - (in Nightly builds, run with -Z macro-backtrace for more info)", - ); - + // We point at the macro def line, but without an underline or message, we + // leave it implied. + span.push_span_context(sp.shrink_to_lo()); + } + } else { children.push(Subdiag { level: Sublevel::Note, messages: vec![(DiagMessage::from(msg), Style::NoStyle)], diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index bcc46adda8a0f..0950a13c8c2ce 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,6 +1,8 @@ error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 | +LL | macro_rules! t { +LL | () => { LL | let _x = unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -10,11 +12,12 @@ LL | t!(); = help: consider adding a safety comment on the preceding line = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 | +LL | macro_rules! t { +... LL | unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 @@ -131,6 +133,8 @@ LL | t!(unsafe {}); error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | +LL | macro_rules! t { +LL | () => { LL | unsafe {} | ^^^^^^^^^ ... @@ -138,7 +142,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 @@ -191,6 +194,8 @@ LL | unsafe impl B for (u32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -198,11 +203,12 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -210,7 +216,6 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 @@ -223,6 +228,8 @@ LL | unsafe impl T for (i32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -230,7 +237,6 @@ LL | no_safety_comment!(u32); | ----------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 diff --git a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 0de8ed716bed9..20483c72228c5 100644 --- a/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/src/tools/clippy/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,6 +1,8 @@ error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 | +LL | macro_rules! t { +LL | () => { LL | let _x = unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -10,11 +12,12 @@ LL | t!(); = help: consider adding a safety comment on the preceding line = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 | +LL | macro_rules! t { +... LL | unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 @@ -131,6 +133,8 @@ LL | t!(unsafe {}); error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | +LL | macro_rules! t { +LL | () => { LL | unsafe {} | ^^^^^^^^^ ... @@ -138,7 +142,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 @@ -191,6 +194,8 @@ LL | unsafe impl B for (u32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -198,11 +203,12 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -210,7 +216,6 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 @@ -223,6 +228,8 @@ LL | unsafe impl T for (i32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -230,7 +237,6 @@ LL | no_safety_comment!(u32); | ----------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 diff --git a/src/tools/clippy/tests/ui/async_yields_async.stderr b/src/tools/clippy/tests/ui/async_yields_async.stderr index 3041cf6578938..57ef895db9944 100644 --- a/src/tools/clippy/tests/ui/async_yields_async.stderr +++ b/src/tools/clippy/tests/ui/async_yields_async.stderr @@ -112,6 +112,8 @@ LL | let y = async { call_bar!() }; error: an async construct yields a type which is itself awaitable --> tests/ui/async_yields_async.rs:90:21 | +LL | macro_rules! call_bar { +LL | () => { LL | async { bar(5) } | --^^^^^^-- | | | @@ -121,8 +123,6 @@ LL | async { bar(5) } ... LL | let y = async { call_bar!() }; | ----------- in this macro invocation - | - = note: this error originates in the macro `call_bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: an async construct yields a type which is itself awaitable --> tests/ui/async_yields_async.rs:119:21 diff --git a/src/tools/clippy/tests/ui/cast.stderr b/src/tools/clippy/tests/ui/cast.stderr index 6b44ff344392e..3e1d418abef61 100644 --- a/src/tools/clippy/tests/ui/cast.stderr +++ b/src/tools/clippy/tests/ui/cast.stderr @@ -670,17 +670,19 @@ LL | (a.abs() * b.pow(2) / c.abs()) as u32 error: casting `i32` to `u32` may lose the sign of the value --> tests/ui/cast.rs:532:21 | +LL | macro_rules! m { +LL | () => { LL | let _ = i32::MIN as u32; // cast_sign_loss | ^^^^^^^^^^^^^^^ help: if this is intentional, use `cast_unsigned()` instead: `i32::MIN.cast_unsigned()` ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `u32` to `u8` may truncate the value --> tests/ui/cast.rs:535:21 | +LL | macro_rules! m { +... LL | let _ = u32::MAX as u8; // cast_possible_truncation | ^^^^^^^^^^^^^^ ... @@ -688,7 +690,6 @@ LL | m!(); | ---- in this macro invocation | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: ... or use `try_from` and handle the error accordingly | LL - let _ = u32::MAX as u8; // cast_possible_truncation @@ -698,6 +699,8 @@ LL + let _ = u8::try_from(u32::MAX); // cast_possible_truncation error: casting `f64` to `f32` may truncate the value --> tests/ui/cast.rs:538:21 | +LL | macro_rules! m { +... LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -705,7 +708,6 @@ LL | m!(); | ---- in this macro invocation | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers --> tests/ui/cast.rs:549:5 diff --git a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr index 9852eca712793..ce2afbb66c23b 100644 --- a/src/tools/clippy/tests/ui/cast_lossless_integer.stderr +++ b/src/tools/clippy/tests/ui/cast_lossless_integer.stderr @@ -497,6 +497,8 @@ LL + let _ = i32::from(sign_cast!(x, u8, i8) + 1); error: casts from `u8` to `u32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_integer.rs:159:13 | +LL | macro_rules! in_macro { +LL | () => { LL | 1u8 as u32 | ^^^^^^^^^^ ... @@ -504,7 +506,6 @@ LL | let _ = in_macro!(); | ----------- in this macro invocation | = help: an `as` cast can become silently lossy if the types change in the future - = note: this error originates in the macro `in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `u32::from` instead | LL - 1u8 as u32 diff --git a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr index be979baa9fe4a..b2d4a9903234a 100644 --- a/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/src/tools/clippy/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -59,6 +59,8 @@ LL | x.unwrap(); error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13 | +LL | macro_rules! m { +LL | ($a:expr) => { LL | if $a.is_some() { | --------------- help: try: `if let Some() = x` LL | $a.unwrap(); @@ -66,8 +68,6 @@ LL | $a.unwrap(); ... LL | m!(x); | ----- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:71:9 diff --git a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr index 7d9a12b1ddd33..54f839b812397 100644 --- a/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr +++ b/src/tools/clippy/tests/ui/cmp_owned/with_suggestion.stderr @@ -58,6 +58,8 @@ LL | if item == t!(frohes_neu_Jahr).to_string() { error: this creates an owned instance just for comparison --> tests/ui/cmp_owned/with_suggestion.rs:141:51 | +LL | macro_rules! all_comes_from_macro { +... LL | let res = <$ty>::default() == "$def".to_string(); | ^^^^^^^^^^^^^^^^^^ help: try: `"$def"` ... @@ -65,8 +67,6 @@ LL | / all_comes_from_macro! { LL | | required_version: String, m!().to_string(); LL | | } | |_____- in this macro invocation - | - = note: this error originates in the macro `all_comes_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: this creates an owned instance just for comparison --> tests/ui/cmp_owned/with_suggestion.rs:156:16 diff --git a/src/tools/clippy/tests/ui/collapsible_match2.stderr b/src/tools/clippy/tests/ui/collapsible_match2.stderr index 6acfd3de782bd..30cbf7705a20d 100644 --- a/src/tools/clippy/tests/ui/collapsible_match2.stderr +++ b/src/tools/clippy/tests/ui/collapsible_match2.stderr @@ -43,6 +43,8 @@ LL | Some(n) => foo(n), error: this `match` can be collapsed into the outer `match` --> tests/ui/collapsible_match2.rs:31:29 | +LL | macro_rules! mac { +... LL | $pat => match $e { | _____________________________^ LL | | @@ -61,7 +63,6 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern | | | replace this binding - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` can be collapsed into the outer `match` --> tests/ui/collapsible_match2.rs:49:20 diff --git a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr index 420e4af936f81..dfaf6ce86f517 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6255.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6255.stderr @@ -1,17 +1,19 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> tests/ui/crashes/ice-6255.rs:6:9 | +LL | macro_rules! define_other_core { +LL | ( ) => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `core` is ambiguous --> tests/ui/crashes/ice-6255.rs:12:5 | +LL | macro_rules! define_other_core { +... LL | core::panic!(); | ^^^^ ambiguous name | @@ -26,7 +28,6 @@ LL | extern crate std as core; LL | define_other_core!(); | -------------------- in this macro invocation = help: use `crate::core` to refer to this crate unambiguously - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr index 2efefef4ee2ec..44b20bd883e68 100644 --- a/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr +++ b/src/tools/clippy/tests/ui/dbg_macro/dbg_macro.stderr @@ -146,13 +146,14 @@ LL + foo2!(foo!(())); error: the `dbg!` macro is intended as a debugging tool --> tests/ui/dbg_macro/dbg_macro.rs:46:13 | +LL | macro_rules! expand_to_dbg { +LL | () => { LL | dbg!(); | ^^^^^^ ... LL | expand_to_dbg!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `expand_to_dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the invocation before committing it to a version control system | LL - dbg!(); diff --git a/src/tools/clippy/tests/ui/doc_unsafe.stderr b/src/tools/clippy/tests/ui/doc_unsafe.stderr index efac6cd64c878..cf3fe5fdbe5d8 100644 --- a/src/tools/clippy/tests/ui/doc_unsafe.stderr +++ b/src/tools/clippy/tests/ui/doc_unsafe.stderr @@ -81,13 +81,13 @@ LL | pub unsafe fn more_undocumented_unsafe() -> Self { error: unsafe function's docs are missing a `# Safety` section --> tests/ui/doc_unsafe.rs:138:9 | +LL | macro_rules! very_unsafe { +LL | () => { LL | pub unsafe fn whee() { | ^^^^^^^^^^^^^^^^^^^^ ... LL | very_unsafe!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/double_parens.stderr b/src/tools/clippy/tests/ui/double_parens.stderr index 51b5c6279b211..7afe8f700e86b 100644 --- a/src/tools/clippy/tests/ui/double_parens.stderr +++ b/src/tools/clippy/tests/ui/double_parens.stderr @@ -40,13 +40,12 @@ LL | assert_eq!(((1, 2)), (1, 2), "Error"); error: unnecessary parentheses --> tests/ui/double_parens.rs:89:16 | +LL | macro_rules! bar { LL | () => {((100))} | ^^^^^^^ help: remove them: `(100)` ... LL | bar!(); | ------ in this macro invocation - | - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:96:5 @@ -69,35 +68,35 @@ LL | x.dummy_method((vec![1, 2])); error: unnecessary parentheses --> tests/ui/double_parens.rs:110:21 | +LL | macro_rules! double_parens{ +... LL | let a = (()); | ^^^^ help: remove them: `()` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:112:21 | +LL | macro_rules! double_parens{ +... LL | let b = ((5)); | ^^^^^ help: remove them: `(5)` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:114:44 | +LL | macro_rules! double_parens{ +... LL | let c = std::convert::identity((5)); | ^^^ help: remove them: `5` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 13 previous errors diff --git a/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr b/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr index 0d1ee48b36df1..abe596bfd46d9 100644 --- a/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr +++ b/src/tools/clippy/tests/ui/duration_suboptimal_units.stderr @@ -147,13 +147,14 @@ LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); error: constructing a `Duration` using a smaller unit when a larger unit would be more readable --> tests/ui/duration_suboptimal_units.rs:13:9 | +LL | macro_rules! mac { +... LL | Duration::from_secs(60 * 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | let dur = mac!(duration); | -------------- in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: try using `Duration::from_mins` | LL - Duration::from_secs(60 * 5) diff --git a/src/tools/clippy/tests/ui/eq_op_macros.stderr b/src/tools/clippy/tests/ui/eq_op_macros.stderr index 72315e87bfeff..8bc75c8efe0b0 100644 --- a/src/tools/clippy/tests/ui/eq_op_macros.stderr +++ b/src/tools/clippy/tests/ui/eq_op_macros.stderr @@ -1,6 +1,8 @@ error: identical args used in this `assert_eq!` macro call --> tests/ui/eq_op_macros.rs:8:20 | +LL | macro_rules! assert_in_macro_def { +... LL | assert_eq!(a, a); | ^^^^ ... @@ -9,40 +11,39 @@ LL | assert_in_macro_def!(); | = note: `-D clippy::eq-op` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::eq_op)]` - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_ne!` macro call --> tests/ui/eq_op_macros.rs:10:20 | +LL | macro_rules! assert_in_macro_def { +... LL | assert_ne!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_eq!` macro call --> tests/ui/eq_op_macros.rs:12:26 | +LL | macro_rules! assert_in_macro_def { +... LL | debug_assert_eq!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_ne!` macro call --> tests/ui/eq_op_macros.rs:14:26 | +LL | macro_rules! assert_in_macro_def { +... LL | debug_assert_ne!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_eq!` macro call --> tests/ui/eq_op_macros.rs:27:16 diff --git a/src/tools/clippy/tests/ui/exit1.stderr b/src/tools/clippy/tests/ui/exit1.stderr index 9398d2f7f4399..3ac6ec2e03b41 100644 --- a/src/tools/clippy/tests/ui/exit1.stderr +++ b/src/tools/clippy/tests/ui/exit1.stderr @@ -16,13 +16,13 @@ LL | mac!(std::process::exit(1)); error: usage of `process::exit` --> tests/ui/exit1.rs:25:13 | +LL | macro_rules! mac { +... LL | std::process::exit($x); | ^^^^^^^^^^^^^^^^^^^^^^ ... LL | mac!(ex 1); | ---------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/incompatible_msrv.stderr b/src/tools/clippy/tests/ui/incompatible_msrv.stderr index 3c0bb595bd5b0..758d48c21eed6 100644 --- a/src/tools/clippy/tests/ui/incompatible_msrv.stderr +++ b/src/tools/clippy/tests/ui/incompatible_msrv.stderr @@ -40,13 +40,13 @@ LL | let _ = core::iter::once_with(|| 0); error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` --> tests/ui/incompatible_msrv.rs:69:21 | +LL | macro_rules! my_panic { +LL | ($msg:expr) => { LL | let _ = core::iter::once_with(|| $msg); | ^^^^^^^^^^^^^^^^^^^^^ ... LL | my_panic!("foo"); | ---------------- in this macro invocation - | - = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` --> tests/ui/incompatible_msrv.rs:76:13 diff --git a/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr index 632df3e960c10..5403c25b59943 100644 --- a/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr +++ b/src/tools/clippy/tests/ui/integer_division_remainder_used.stderr @@ -70,13 +70,13 @@ LL | j %= 3; error: use of `%` has been disallowed in this context --> tests/ui/integer_division_remainder_used.rs:60:13 | +LL | macro_rules! mac { +LL | ($a:expr, $b:expr) => { LL | $a % $b | ^^^^^^^ ... LL | let issue17048 = mac!(a, b); | ---------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr index a033ff645f49a..5137cd6b30f50 100644 --- a/src/tools/clippy/tests/ui/into_iter_without_iter.stderr +++ b/src/tools/clippy/tests/ui/into_iter_without_iter.stderr @@ -108,6 +108,8 @@ LL + } error: `IntoIterator` implemented for a reference type without an `iter` method --> tests/ui/into_iter_without_iter.rs:120:9 | +LL | macro_rules! generate_impl { +LL | () => { LL | / impl<'a> IntoIterator for &'a Issue12037 { LL | | LL | | type IntoIter = std::slice::Iter<'a, u8>; @@ -119,7 +121,6 @@ LL | | } LL | generate_impl!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider implementing `iter` | LL ~ diff --git a/src/tools/clippy/tests/ui/items_after_statement.stderr b/src/tools/clippy/tests/ui/items_after_statement.stderr index 7a5ae2c8d47d2..2e1b75aaa7e9d 100644 --- a/src/tools/clippy/tests/ui/items_after_statement.stderr +++ b/src/tools/clippy/tests/ui/items_after_statement.stderr @@ -24,6 +24,8 @@ LL | | } error: adding items after statements is confusing, since items exist from the start of the scope --> tests/ui/items_after_statement.rs:37:13 | +LL | macro_rules! b { +... LL | / fn say_something() { LL | | LL | | println!("something"); @@ -32,8 +34,6 @@ LL | | } ... LL | b!(); | ---- in this macro invocation - | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr index f42782aae6705..8645897bc8f3d 100644 --- a/src/tools/clippy/tests/ui/iter_without_into_iter.stderr +++ b/src/tools/clippy/tests/ui/iter_without_into_iter.stderr @@ -150,6 +150,8 @@ LL + } error: `iter` method without an `IntoIterator` impl for `&Issue12037` --> tests/ui/iter_without_into_iter.rs:131:13 | +LL | macro_rules! generate_impl { +... LL | / fn iter(&self) -> std::slice::Iter<'_, u8> { LL | | LL | | todo!() @@ -159,7 +161,6 @@ LL | | } LL | generate_impl!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider implementing `IntoIterator` for `&Issue12037` | LL ~ diff --git a/src/tools/clippy/tests/ui/large_futures.stderr b/src/tools/clippy/tests/ui/large_futures.stderr index 26361ce8535a2..65587adcc763c 100644 --- a/src/tools/clippy/tests/ui/large_futures.stderr +++ b/src/tools/clippy/tests/ui/large_futures.stderr @@ -63,6 +63,8 @@ LL + }) error: large future with a size of 65540 bytes --> tests/ui/large_futures.rs:59:13 | +LL | macro_rules! macro_ { +LL | () => { LL | / async { LL | | LL | | let x = [0i32; 1024 * 16]; @@ -74,7 +76,6 @@ LL | | } LL | macro_!().await | --------- in this macro invocation | - = note: this error originates in the macro `macro_` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider `Box::pin` on it | LL ~ Box::pin(async { diff --git a/src/tools/clippy/tests/ui/large_stack_arrays.stderr b/src/tools/clippy/tests/ui/large_stack_arrays.stderr index f48706415e66a..6758d49d38b16 100644 --- a/src/tools/clippy/tests/ui/large_stack_arrays.stderr +++ b/src/tools/clippy/tests/ui/large_stack_arrays.stderr @@ -67,13 +67,13 @@ LL | let y = [x, x, dummy!(x), x, x]; error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:76:13 | +LL | macro_rules! dummy { +... LL | [$a, $b, $a, $b] | ^^^^^^^^^^^^^^^^ ... LL | let y = dummy![x => x]; | -------------- in this macro invocation - | - = note: this error originates in the macro `dummy` (in Nightly builds, run with -Z macro-backtrace for more info) error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:104:20 @@ -92,13 +92,13 @@ LL | let y = proc_macros::make_it_big!([x; 1]); error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:88:23 | +LL | macro_rules! create_then_move { +LL | ($id:ident; $n:literal) => {{ LL | let _x_ = [$id; $n]; | ^^^^^^^^^ ... LL | let y = vec![create_then_move![x; 5]; 5]; | ----------------------- in this macro invocation - | - = note: this error originates in the macro `create_then_move` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/src/tools/clippy/tests/ui/legacy_numeric_constants.stderr b/src/tools/clippy/tests/ui/legacy_numeric_constants.stderr index e0eb9562fbd38..afebb2998ce52 100644 --- a/src/tools/clippy/tests/ui/legacy_numeric_constants.stderr +++ b/src/tools/clippy/tests/ui/legacy_numeric_constants.stderr @@ -158,13 +158,14 @@ LL + u128::MAX; error: usage of a legacy numeric constant --> tests/ui/legacy_numeric_constants.rs:18:25 | +LL | macro_rules! b { +... LL | let x = std::u64::MAX; | ^^^^^^^^^^^^^ ... LL | b!(); | ---- in this macro invocation | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the associated constant instead | LL - let x = std::u64::MAX; diff --git a/src/tools/clippy/tests/ui/legacy_numeric_constants_unfixable.stderr b/src/tools/clippy/tests/ui/legacy_numeric_constants_unfixable.stderr index 96e6c9ef97598..b999e4c2c0ea0 100644 --- a/src/tools/clippy/tests/ui/legacy_numeric_constants_unfixable.stderr +++ b/src/tools/clippy/tests/ui/legacy_numeric_constants_unfixable.stderr @@ -61,6 +61,8 @@ LL | use std::i16::*; error: importing legacy numeric constants --> tests/ui/legacy_numeric_constants_unfixable.rs:22:17 | +LL | macro_rules! b { +... LL | use std::u32; | ^^^^^^^^ ... @@ -69,7 +71,6 @@ LL | b!(); | = help: remove this import = note: then `u32::` will resolve to the respective associated constant - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: importing a legacy numeric constant --> tests/ui/legacy_numeric_constants_unfixable.rs:77:9 diff --git a/src/tools/clippy/tests/ui/manual_div_ceil.stderr b/src/tools/clippy/tests/ui/manual_div_ceil.stderr index 1ebcbc04eeb95..3e505baf35920 100644 --- a/src/tools/clippy/tests/ui/manual_div_ceil.stderr +++ b/src/tools/clippy/tests/ui/manual_div_ceil.stderr @@ -34,24 +34,24 @@ LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:6:17 | +LL | macro_rules! y { +... LL | let _ = (x + 7) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` ... LL | y!(); | ---- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:8:17 | +LL | macro_rules! y { +... LL | let _ = (7 + x) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` ... LL | y!(); | ---- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:62:13 diff --git a/src/tools/clippy/tests/ui/manual_let_else.stderr b/src/tools/clippy/tests/ui/manual_let_else.stderr index 77e32eada5c6e..3cb4a0c601bd7 100644 --- a/src/tools/clippy/tests/ui/manual_let_else.stderr +++ b/src/tools/clippy/tests/ui/manual_let_else.stderr @@ -272,13 +272,13 @@ LL + }; error: this could be rewritten as `let...else` --> tests/ui/manual_let_else.rs:170:13 | +LL | macro_rules! create_binding_if_some { +LL | ($n:ident, $e:expr) => { LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` ... LL | create_binding_if_some!(w, g()); | ------------------------------- in this macro invocation - | - = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` --> tests/ui/manual_let_else.rs:180:5 diff --git a/src/tools/clippy/tests/ui/manual_range_patterns.stderr b/src/tools/clippy/tests/ui/manual_range_patterns.stderr index 729a6d598a116..700d487aa502e 100644 --- a/src/tools/clippy/tests/ui/manual_range_patterns.stderr +++ b/src/tools/clippy/tests/ui/manual_range_patterns.stderr @@ -112,13 +112,13 @@ LL | matches!(f, 5..=10 | 0..5); error: this OR pattern can be rewritten using a range --> tests/ui/manual_range_patterns.rs:60:26 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` ... LL | mac!(f); | ------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 19 previous errors diff --git a/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr b/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr index d4854c122da5c..9044ca4917095 100644 --- a/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr +++ b/src/tools/clippy/tests/ui/missing_transmute_annotations.stderr @@ -40,13 +40,13 @@ LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); error: transmute used without annotations --> tests/ui/missing_transmute_annotations.rs:11:19 | +LL | macro_rules! local_bad_transmute { +LL | ($e:expr) => { LL | std::mem::transmute($e) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` ... LL | i = local_bad_transmute!([1u16, 2u16]); | ---------------------------------- in this macro invocation - | - = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) error: transmute used without annotations --> tests/ui/missing_transmute_annotations.rs:57:23 diff --git a/src/tools/clippy/tests/ui/needless_question_mark.stderr b/src/tools/clippy/tests/ui/needless_question_mark.stderr index 8e0a740cc0ab3..4a91633dc001b 100644 --- a/src/tools/clippy/tests/ui/needless_question_mark.stderr +++ b/src/tools/clippy/tests/ui/needless_question_mark.stderr @@ -135,13 +135,14 @@ LL + return t.magic; error: enclosing `Some` and `?` operator are unneeded --> tests/ui/needless_question_mark.rs:122:27 | +LL | macro_rules! some_and_qmark_in_macro { +LL | ($expr:expr) => { LL | || -> Option<_> { Some(Some($expr)?) }() | ^^^^^^^^^^^^^^^^^^ ... LL | let _x = some_and_qmark_in_macro!(x?); | ---------------------------- in this macro invocation | - = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the enclosing `Some` and `?` operator | LL - || -> Option<_> { Some(Some($expr)?) }() diff --git a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr index 636841e0a21a4..43fbce64ffa80 100644 --- a/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr +++ b/src/tools/clippy/tests/ui/pattern_type_mismatch/syntax.stderr @@ -67,6 +67,8 @@ LL | Some(_) => (), error: type of pattern does not match the expression type --> tests/ui/pattern_type_mismatch/syntax.rs:145:17 | +LL | macro_rules! matching_macro { +... LL | Some(_) => (), | ^^^^^^^ ... @@ -74,7 +76,6 @@ LL | matching_macro!(value); | ---------------------- in this macro invocation | = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings - = note: this error originates in the macro `matching_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_async_block.stderr b/src/tools/clippy/tests/ui/redundant_async_block.stderr index 386f00a25c2f9..785a6b5b5d7c4 100644 --- a/src/tools/clippy/tests/ui/redundant_async_block.stderr +++ b/src/tools/clippy/tests/ui/redundant_async_block.stderr @@ -52,24 +52,24 @@ LL | async { async { f().await + 1 }.await } error: this async expression only awaits a single future --> tests/ui/redundant_async_block.rs:155:13 | +LL | macro_rules! mac { +... LL | async { async { 42 }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` ... LL | mac!() | ------ in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this async expression only awaits a single future --> tests/ui/redundant_async_block.rs:176:13 | +LL | macro_rules! mac { +... LL | async { async { $e }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { $e }` ... LL | mac!(42) | -------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr index d9d2335ef9031..13c22550b3b8b 100644 --- a/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr +++ b/src/tools/clippy/tests/ui/redundant_closure_call_fixable.stderr @@ -60,24 +60,27 @@ LL | let d = (async || something().await)(); error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:38:13 | +LL | macro_rules! m2 { +LL | () => { LL | (|| m!())() | ^^^^^^^^^^^ help: try doing something like: `m!()` ... LL | m2!(); | ----- in this macro invocation - | - = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:33:13 | -LL | (|| 0)() - | ^^^^^^^^ help: try doing something like: `0` +LL | / macro_rules! m { +LL | | () => { +LL | | (|| 0)() + | | ^^^^^^^^ help: try doing something like: `0` +LL | | }; +LL | | } + | |_____- this error originates in the macro `m` which comes from the expansion of the macro `m2` ... -LL | m2!(); - | ----- in this macro invocation - | - = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | m2!(); + | ----- in this macro invocation error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:48:16 diff --git a/src/tools/clippy/tests/ui/redundant_field_names.stderr b/src/tools/clippy/tests/ui/redundant_field_names.stderr index 5554c28b7cff3..8b5ae4d169385 100644 --- a/src/tools/clippy/tests/ui/redundant_field_names.stderr +++ b/src/tools/clippy/tests/ui/redundant_field_names.stderr @@ -46,13 +46,13 @@ LL | let _ = RangeToInclusive { end: end }; error: redundant field names in struct initialization --> tests/ui/redundant_field_names.rs:77:25 | +LL | macro_rules! internal { +LL | ($i:ident) => { LL | let _ = S { v: v }; | ^^^^ help: replace it with: `v` ... LL | internal!(v); | ------------ in this macro invocation - | - = note: this error originates in the macro `internal` (in Nightly builds, run with -Z macro-backtrace for more info) error: redundant field names in struct initialization --> tests/ui/redundant_field_names.rs:106:25 diff --git a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr index 9388fbdc775d3..4dd7a32232713 100644 --- a/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr +++ b/src/tools/clippy/tests/ui/string_lit_as_bytes.stderr @@ -28,13 +28,13 @@ LL | let bs = "lit to owned".to_owned().into_bytes(); error: calling `as_bytes()` on a string literal --> tests/ui/string_lit_as_bytes.rs:11:26 | +LL | macro_rules! b { +LL | ($b:literal) => { LL | const B: &[u8] = $b.as_bytes(); | ^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"warning"` ... LL | b!("warning"); | ------------- in this macro invocation - | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: calling `as_bytes()` on `include_str!(..)` --> tests/ui/string_lit_as_bytes.rs:43:22 diff --git a/src/tools/clippy/tests/ui/struct_fields.stderr b/src/tools/clippy/tests/ui/struct_fields.stderr index 254498ad2eebc..edf29eaafb97d 100644 --- a/src/tools/clippy/tests/ui/struct_fields.stderr +++ b/src/tools/clippy/tests/ui/struct_fields.stderr @@ -210,6 +210,8 @@ LL | proxy: i32, error: all fields have the same prefix: `some` --> tests/ui/struct_fields.rs:225:13 | +LL | macro_rules! mk_struct { +LL | () => { LL | / struct MacroStruct { LL | | LL | | some_a: i32, @@ -222,33 +224,34 @@ LL | mk_struct!(); | ------------ in this macro invocation | = help: remove the prefixes - = note: this error originates in the macro `mk_struct` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:238:17 | +LL | macro_rules! mk_struct2 { +... LL | macrobaz_a: i32, | ^^^^^^^^^^^^^^^ ... LL | mk_struct2!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `mk_struct2` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:250:17 | +LL | macro_rules! mk_struct_with_names { +... LL | $field: i32, | ^^^^^^^^^^^ ... LL | mk_struct_with_names!(Foo, foo); | ------------------------------- in this macro invocation - | - = note: this error originates in the macro `mk_struct_with_names` (in Nightly builds, run with -Z macro-backtrace for more info) error: all fields have the same prefix: `some` --> tests/ui/struct_fields.rs:290:13 | +LL | macro_rules! mk_struct_full_def { +LL | ($struct_name:ident, $field1:ident, $field2:ident, $field3:ident) => { LL | / struct $struct_name { LL | | LL | | $field1: i32, @@ -261,7 +264,6 @@ LL | mk_struct_full_def!(PrefixData, some_data, some_meta, some_other); | ----------------------------------------------------------------- in this macro invocation | = help: remove the prefixes - = note: this error originates in the macro `mk_struct_full_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:338:5 diff --git a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr index 2b6570bb0adfc..b2a507b56ff34 100644 --- a/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr +++ b/src/tools/clippy/tests/ui/suspicious_xor_used_as_pow.stderr @@ -75,13 +75,14 @@ LL + let _ = 2i32.pow(32i32); error: `^` is not the exponentiation operator --> tests/ui/suspicious_xor_used_as_pow.rs:12:9 | +LL | macro_rules! macro_test_inside { +LL | () => { LL | 1 ^ 2 // should warn even if inside macro | ^^^^^ ... LL | macro_test_inside!(); | -------------------- in this macro invocation | - = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info) help: did you mean to write | LL - 1 ^ 2 // should warn even if inside macro diff --git a/src/tools/clippy/tests/ui/unconditional_recursion.stderr b/src/tools/clippy/tests/ui/unconditional_recursion.stderr index 5edccf9593da9..e8bc02f693b08 100644 --- a/src/tools/clippy/tests/ui/unconditional_recursion.stderr +++ b/src/tools/clippy/tests/ui/unconditional_recursion.stderr @@ -278,6 +278,8 @@ LL | self == self error: function cannot return without recursing --> tests/ui/unconditional_recursion.rs:169:13 | +LL | macro_rules! impl_partial_eq { +... LL | / fn eq(&self, other: &Self) -> bool { LL | | LL | | @@ -296,7 +298,6 @@ LL | self == other ... LL | impl_partial_eq!(S5); | -------------------- in this macro invocation - = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: function cannot return without recursing --> tests/ui/unconditional_recursion.rs:199:5 diff --git a/src/tools/clippy/tests/ui/uninhabited_references.stderr b/src/tools/clippy/tests/ui/uninhabited_references.stderr index a76782086d8bc..c2f0dabe41217 100644 --- a/src/tools/clippy/tests/ui/uninhabited_references.stderr +++ b/src/tools/clippy/tests/ui/uninhabited_references.stderr @@ -10,24 +10,24 @@ LL | fn ret_uninh_ref() -> &'static std::convert::Infallible { error: dereferencing a reference to an uninhabited type would be undefined behavior --> tests/ui/uninhabited_references.rs:10:30 | +LL | macro_rules! ret_something { +LL | ($name:ident, $ty:ty) => { LL | fn $name(x: &$ty) -> &$ty { | ^^^^ ... LL | ret_something!(id_never, !); | --------------------------- in this macro invocation - | - = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior --> tests/ui/uninhabited_references.rs:12:14 | +LL | macro_rules! ret_something { +... LL | &*x | ^^ ... LL | ret_something!(id_never, !); | --------------------------- in this macro invocation - | - = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior --> tests/ui/uninhabited_references.rs:23:13 diff --git a/src/tools/clippy/tests/ui/unnecessary_safety_comment.stderr b/src/tools/clippy/tests/ui/unnecessary_safety_comment.stderr index 6ad94f986434d..c969be5de9064 100644 --- a/src/tools/clippy/tests/ui/unnecessary_safety_comment.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_safety_comment.stderr @@ -63,6 +63,8 @@ LL | // SAFETY: error: impl has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:42:13 | +LL | macro_rules! with_safety_comment { +... LL | impl T for $t {} | ^^^^^^^^^^^^^^^^ ... @@ -74,7 +76,6 @@ help: consider removing the safety comment | LL | // Safety: unnecessary | ^^^^^^^ - = note: this error originates in the macro `with_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: expression has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:60:5 diff --git a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.stderr b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.stderr index cb2fb3119e86e..81d2bd8829c3b 100644 --- a/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.stderr +++ b/src/tools/clippy/tests/ui/unnecessary_unsafety_doc.stderr @@ -34,13 +34,13 @@ LL | pub fn documented() -> Self { error: safe function's docs have unnecessary `# Safety` section --> tests/ui/unnecessary_unsafety_doc.rs:127:9 | +LL | macro_rules! very_safe { +... LL | pub fn drive() { | ^^^^^^^^^^^^^^ ... LL | very_safe!(); | ------------ in this macro invocation - | - = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for safe trait have unnecessary `# Safety` section --> tests/ui/unnecessary_unsafety_doc.rs:156:1 diff --git a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr index 67e47865108e1..924be1b4cee9c 100644 --- a/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr +++ b/src/tools/clippy/tests/ui/unseparated_prefix_literals.stderr @@ -46,13 +46,13 @@ LL | let _failf2 = 1f32; error: integer type suffix should be separated by an underscore --> tests/ui/unseparated_prefix_literals.rs:14:9 | +LL | macro_rules! lit_from_macro { +LL | () => { LL | 42usize | ^^^^^^^ help: add an underscore: `42_usize` ... LL | let _ = lit_from_macro!(); | ----------------- in this macro invocation - | - = note: this error originates in the macro `lit_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: integer type suffix should be separated by an underscore --> tests/ui/unseparated_prefix_literals.rs:47:16 diff --git a/src/tools/clippy/tests/ui/unused_result_ok.stderr b/src/tools/clippy/tests/ui/unused_result_ok.stderr index e4560aa84dea1..8a16fa4d3b805 100644 --- a/src/tools/clippy/tests/ui/unused_result_ok.stderr +++ b/src/tools/clippy/tests/ui/unused_result_ok.stderr @@ -39,13 +39,14 @@ LL + let _ = v!(); error: ignoring a result with `.ok()` is misleading --> tests/ui/unused_result_ok.rs:30:9 | +LL | macro_rules! w { +LL | () => { LL | Ok::<(), ()>(()).ok(); | ^^^^^^^^^^^^^^^^^^^^^ ... LL | w!(); | ---- in this macro invocation | - = note: this error originates in the macro `w` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider using `let _ =` and removing the call to `.ok()` instead | LL - Ok::<(), ()>(()).ok(); diff --git a/src/tools/miri/tests/fail/shims/ctor_ub.stderr b/src/tools/miri/tests/fail/shims/ctor_ub.stderr index e89f3b3c90593..a2ae3d0113be4 100644 --- a/src/tools/miri/tests/fail/shims/ctor_ub.stderr +++ b/src/tools/miri/tests/fail/shims/ctor_ub.stderr @@ -3,6 +3,8 @@ error: Undefined Behavior: entering unreachable code | LL | std::hint::unreachable_unchecked() | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here +... +LL | macro_rules! ctor { | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information @@ -14,7 +16,6 @@ LL | static $ident: unsafe extern "C" fn() = $ctor; ... LL | ctor! { CTOR = ctor } | --------------------- in this macro invocation - = note: this error originates in the macro `ctor` (in Nightly builds, run with -Z macro-backtrace for more info) note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace diff --git a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr index 4e474dbadcb69..88ff115b877d5 100644 --- a/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr +++ b/src/tools/miri/tests/fail/shims/ctor_wrong_ret_type.stderr @@ -3,6 +3,8 @@ error: Undefined Behavior: calling a function with return type i32 passing retur | LL | unsafe extern "C" fn ctor() -> i32 { | ^^^ Undefined Behavior occurred here +... +LL | macro_rules! ctor { | = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information @@ -16,7 +18,6 @@ LL | static $ident: unsafe extern "C" fn() -> i32 = $ctor; ... LL | ctor! { CTOR = ctor } | --------------------- in this macro invocation - = note: this error originates in the macro `ctor` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/rustdoc-ui/macro-docs.stderr b/tests/rustdoc-ui/macro-docs.stderr index 2b136f5be16b0..7c4a5d69747c1 100644 --- a/tests/rustdoc-ui/macro-docs.stderr +++ b/tests/rustdoc-ui/macro-docs.stderr @@ -1,6 +1,8 @@ warning: unresolved link to `long_cat` --> $DIR/macro-docs.rs:5:9 | +LL | macro_rules! m { +LL | () => { LL | /// A | ^^^^^ ... @@ -14,7 +16,6 @@ LL | m!(); = note: no item named `long_cat` in scope = help: to escape `[` and `]` characters, add '\' before them like `\[` or `\]` = note: `#[warn(rustdoc::broken_intra_doc_links)]` on by default - = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs index 06804e637ae06..fc87af19eee53 100644 --- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs +++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.rs @@ -1,4 +1,6 @@ //@ compile-flags: -Z unstable-options +// FIXME(bootstrap): Remove the ignore once we promote the next beta. +//@ ignore-stage1 #![feature(rustc_private)] #![deny(rustc::lint_pass_impl_without_macro)] diff --git a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr index 055d66360a4bb..cb245a7ccd66e 100644 --- a/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr +++ b/tests/ui-fulldeps/internal-lints/lint_pass_impl_without_macro.stderr @@ -1,19 +1,21 @@ error: implementing `LintPass` by hand - --> $DIR/lint_pass_impl_without_macro.rs:19:6 + --> $DIR/lint_pass_impl_without_macro.rs:21:6 | LL | impl LintPass for Foo { | ^^^^^^^^ | = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead note: the lint level is defined here - --> $DIR/lint_pass_impl_without_macro.rs:4:9 + --> $DIR/lint_pass_impl_without_macro.rs:6:9 | LL | #![deny(rustc::lint_pass_impl_without_macro)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementing `LintPass` by hand - --> $DIR/lint_pass_impl_without_macro.rs:33:14 + --> $DIR/lint_pass_impl_without_macro.rs:35:14 | +LL | macro_rules! custom_lint_pass_macro { +... LL | impl LintPass for Custom { | ^^^^^^^^ ... @@ -21,7 +23,6 @@ LL | custom_lint_pass_macro!(); | ------------------------- in this macro invocation | = help: try using `declare_lint_pass!` or `impl_lint_pass!` instead - = note: this error originates in the macro `custom_lint_pass_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/argument-suggestions/extra_arguments.stderr b/tests/ui/argument-suggestions/extra_arguments.stderr index 0c80ae8acc433..56e827a3cb70e 100644 --- a/tests/ui/argument-suggestions/extra_arguments.stderr +++ b/tests/ui/argument-suggestions/extra_arguments.stderr @@ -270,6 +270,8 @@ LL - 1, error[E0061]: this function takes 0 arguments but 2 arguments were supplied --> $DIR/extra_arguments.rs:9:9 | +LL | macro_rules! foo { +LL | ($x:expr, ~) => { LL | empty($x, 1); | ^^^^^ - unexpected argument #2 of type `{integer}` ... @@ -284,11 +286,12 @@ note: function defined here | LL | fn empty() {} | ^^^^^ - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 0 arguments but 2 arguments were supplied --> $DIR/extra_arguments.rs:15:9 | +LL | macro_rules! foo { +... LL | empty(1, $y); | ^^^^^ - unexpected argument #1 of type `{integer}` ... @@ -303,11 +306,12 @@ note: function defined here | LL | fn empty() {} | ^^^^^ - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 0 arguments but 2 arguments were supplied --> $DIR/extra_arguments.rs:12:9 | +LL | macro_rules! foo { +... LL | empty($x, $y); | ^^^^^ ... @@ -323,7 +327,6 @@ note: function defined here | LL | fn empty() {} | ^^^^^ - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 1 argument but 2 arguments were supplied --> $DIR/extra_arguments.rs:54:3 diff --git a/tests/ui/asm/aarch64/interpolated-idents.stderr b/tests/ui/asm/aarch64/interpolated-idents.stderr index 8537a5ebf46b2..cd612221d7487 100644 --- a/tests/ui/asm/aarch64/interpolated-idents.stderr +++ b/tests/ui/asm/aarch64/interpolated-idents.stderr @@ -1,6 +1,8 @@ error: the `nomem` and `readonly` options are mutually exclusive --> $DIR/interpolated-idents.rs:20:13 | +LL | macro_rules! m { +... LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -8,12 +10,12 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack options); | |________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `pure` and `noreturn` options are mutually exclusive --> $DIR/interpolated-idents.rs:20:13 | +LL | macro_rules! m { +... LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -21,12 +23,12 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack options); | |________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm outputs are not allowed with the `noreturn` option --> $DIR/interpolated-idents.rs:17:32 | +LL | macro_rules! m { +... LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... @@ -34,8 +36,6 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack options); | |________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/asm/x86_64/interpolated-idents.stderr b/tests/ui/asm/x86_64/interpolated-idents.stderr index 1fb817ec8de0c..51ef89f035ed7 100644 --- a/tests/ui/asm/x86_64/interpolated-idents.stderr +++ b/tests/ui/asm/x86_64/interpolated-idents.stderr @@ -1,6 +1,8 @@ error: the `nomem` and `readonly` options are mutually exclusive --> $DIR/interpolated-idents.rs:19:13 | +LL | macro_rules! m { +... LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -8,12 +10,12 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); | |___________________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `pure` and `noreturn` options are mutually exclusive --> $DIR/interpolated-idents.rs:19:13 | +LL | macro_rules! m { +... LL | $options($pure, $nomem, $readonly, $preserves_flags, $noreturn, $nostack, $att_syntax)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -21,12 +23,12 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); | |___________________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: asm outputs are not allowed with the `noreturn` option --> $DIR/interpolated-idents.rs:16:32 | +LL | macro_rules! m { +... LL | asm!("", $in(x) x, $out(x) x, $lateout(x) x, $inout(x) x, $inlateout(x) x, | ^^^^^^^^^ ^^^^^^^^^^^^^ ^^^^^^^^^^^ ^^^^^^^^^^^^^^^ ... @@ -34,8 +36,6 @@ LL | / m!(in out lateout inout inlateout const sym LL | | pure nomem readonly preserves_flags LL | | noreturn nostack att_syntax options); | |___________________________________________- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/async-await/async-fn/macro-async-trait-bound-theoretical-regression.stderr b/tests/ui/async-await/async-fn/macro-async-trait-bound-theoretical-regression.stderr index 0292c53fb1c17..c10129f2c7012 100644 --- a/tests/ui/async-await/async-fn/macro-async-trait-bound-theoretical-regression.stderr +++ b/tests/ui/async-await/async-fn/macro-async-trait-bound-theoretical-regression.stderr @@ -1,24 +1,22 @@ error: ty --> $DIR/macro-async-trait-bound-theoretical-regression.rs:8:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { impl async Trait } | -------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error: ty --> $DIR/macro-async-trait-bound-theoretical-regression.rs:8:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { dyn async Trait } | ------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: `async` trait bounds are unstable --> $DIR/macro-async-trait-bound-theoretical-regression.rs:18:14 diff --git a/tests/ui/async-await/issue-73541-2.stderr b/tests/ui/async-await/issue-73541-2.stderr index 584b71ce643f5..0ca8befc65566 100644 --- a/tests/ui/async-await/issue-73541-2.stderr +++ b/tests/ui/async-await/issue-73541-2.stderr @@ -3,7 +3,8 @@ error[E0767]: use of unreachable label `'a` | LL | 'a: loop { | -- unreachable label defined here -... +LL | macro_rules! b { +LL | () => { LL | continue 'a | ^^ unreachable label `'a` ... @@ -11,7 +12,6 @@ LL | b!(); | ---- in this macro invocation | = note: labels are unreachable through functions, closures, async blocks and modules - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/async-await/unnecessary-await.stderr b/tests/ui/async-await/unnecessary-await.stderr index f60b4ecb99098..81ae26a1f28d7 100644 --- a/tests/ui/async-await/unnecessary-await.stderr +++ b/tests/ui/async-await/unnecessary-await.stderr @@ -37,6 +37,8 @@ LL + e!(); error[E0277]: `()` is not a future --> $DIR/unnecessary-await.rs:22:15 | +LL | macro_rules! f { +LL | ($expr:expr) => { LL | $expr.await | ^^^^^ | | @@ -49,7 +51,6 @@ LL | f!(()); = help: the trait `Future` is not implemented for `()` = note: () must be a future or must implement `IntoFuture` to be awaited = note: required for `()` to implement `IntoFuture` - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: `()` is not a future --> $DIR/unnecessary-await.rs:36:20 diff --git a/tests/ui/attributes/key-value-expansion.stderr b/tests/ui/attributes/key-value-expansion.stderr index 54d79c5bebb7f..c975f88425cef 100644 --- a/tests/ui/attributes/key-value-expansion.stderr +++ b/tests/ui/attributes/key-value-expansion.stderr @@ -7,24 +7,24 @@ LL | bug!((column!())); error: attribute value must be a literal --> $DIR/key-value-expansion.rs:27:14 | +LL | macro_rules! bug { +LL | () => { LL | bug!("bug" + stringify!(found)); | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | bug!(); | ------ in this macro invocation - | - = note: this error originates in the macro `bug` (in Nightly builds, run with -Z macro-backtrace for more info) error: attribute value must be a literal --> $DIR/key-value-expansion.rs:48:23 | +LL | macro_rules! some_macro { +LL | ($t1: ty) => { LL | doc_comment! {format!("{coor}", coor = stringify!($t1)).as_str()} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | some_macro!(u8); | --------------- in this macro invocation - | - = note: this error originates in the macro `some_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/attributes/nonterminal-expansion.stderr b/tests/ui/attributes/nonterminal-expansion.stderr index 21912de210610..035b39e8581e1 100644 --- a/tests/ui/attributes/nonterminal-expansion.stderr +++ b/tests/ui/attributes/nonterminal-expansion.stderr @@ -1,13 +1,13 @@ error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable --> $DIR/nonterminal-expansion.rs:7:22 | +LL | macro_rules! pass_nonterminal { +LL | ($n:expr) => { LL | #[repr(align($n))] | ^^ ... LL | pass_nonterminal!(n!()); | ----------------------- in this macro invocation - | - = note: this error originates in the macro `pass_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-25793.stderr b/tests/ui/borrowck/issue-25793.stderr index e2efc405faba4..71db5a0a11e56 100644 --- a/tests/ui/borrowck/issue-25793.stderr +++ b/tests/ui/borrowck/issue-25793.stderr @@ -1,6 +1,8 @@ error[E0503]: cannot use `self.width` because it was mutably borrowed --> $DIR/issue-25793.rs:4:9 | +LL | macro_rules! width( +LL | ($this:expr) => { LL | $this.width.unwrap() | ^^^^^^^^^^^ use of borrowed `*self` ... @@ -10,8 +12,6 @@ LL | r.get_size(width!(self)) | -------- ------------ in this macro invocation | | | borrow later used by call - | - = note: this error originates in the macro `width` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/move-error-snippets.stderr b/tests/ui/borrowck/move-error-snippets.stderr index 97d140515184a..ea05dd5a7ca6c 100644 --- a/tests/ui/borrowck/move-error-snippets.stderr +++ b/tests/ui/borrowck/move-error-snippets.stderr @@ -1,13 +1,18 @@ error[E0507]: cannot move out of static item `D` --> $DIR/move-error-snippets-ext.rs:5:17 | -LL | let a = $c; - | ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait +LL | / macro_rules! aaa { +LL | | ($c:ident) => {{ +LL | | let a = $c; + | | ^^ move occurs because `D` has type `A`, which does not implement the `Copy` trait +LL | | }} +LL | | } + | |_- this error originates in the macro `aaa` which comes from the expansion of the macro `sss` | ::: $DIR/move-error-snippets.rs:21:1 | -LL | sss!(); - | ------ in this macro invocation +LL | sss!(); + | ------ in this macro invocation | note: if `A` implemented `Clone`, you could clone the value --> $DIR/move-error-snippets.rs:9:1 @@ -19,7 +24,6 @@ LL | struct A; | LL | let a = $c; | -- you could clone this value - = note: this error originates in the macro `aaa` which comes from the expansion of the macro `sss` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | LL | let a = &$c; diff --git a/tests/ui/borrowck/span-semicolon-issue-139049.stderr b/tests/ui/borrowck/span-semicolon-issue-139049.stderr index 8d2de67382bd8..a125e313c8f5a 100644 --- a/tests/ui/borrowck/span-semicolon-issue-139049.stderr +++ b/tests/ui/borrowck/span-semicolon-issue-139049.stderr @@ -14,7 +14,6 @@ LL | { let l = (); perform!(l) }; | | in this macro invocation | binding `l` declared here | - = note: this error originates in the macro `perform` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider adding semicolon after the expression so its temporaries are dropped sooner, before the local variables declared by the block are dropped | LL | { let l = (); perform!(l); }; @@ -38,7 +37,6 @@ LL | let _x = { let l = (); perform!(l) }; | = note: the temporary is part of an expression at the end of a block; consider forcing this temporary to be dropped sooner, before the block's local variables are dropped - = note: this error originates in the macro `perform` (in Nightly builds, run with -Z macro-backtrace for more info) help: for example, you could save the expression's value in a new local variable `x` and then make `x` be the expression at the end of the block | LL | let _x = { let l = (); let x = perform!(l); x }; diff --git a/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr index 0248b6636fb7a..63400b2b2e202 100644 --- a/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr +++ b/tests/ui/cfg/cfg-eval-derive-invalid-reparse-no-ice.stderr @@ -1,6 +1,8 @@ error: expected expression, found `ty` metavariable --> $DIR/cfg-eval-derive-invalid-reparse-no-ice.rs:8:25 | +LL | macro_rules! values { +... LL | pub enum TokenKind { | --------- while parsing this enum LL | #[cfg(test)] @@ -11,7 +13,6 @@ LL | values!(String); | --------------- in this macro invocation | = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` - = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro expansion ignores `)` and any tokens following --> $DIR/cfg-eval-derive-invalid-reparse-no-ice.rs:8:32 diff --git a/tests/ui/cfg/cfg-method-receiver.stderr b/tests/ui/cfg/cfg-method-receiver.stderr index 44f3d8d058e04..f2f514db0a584 100644 --- a/tests/ui/cfg/cfg-method-receiver.stderr +++ b/tests/ui/cfg/cfg-method-receiver.stderr @@ -7,13 +7,14 @@ LL | cbor_map! { #[cfg(test)] 4}; error[E0689]: can't call method `signum` on ambiguous numeric type `{integer}` --> $DIR/cfg-method-receiver.rs:3:14 | +LL | macro_rules! cbor_map { +LL | ($key:expr) => { LL | $key.signum(); | ^^^^^^ ... LL | cbor_map! { #[cfg(test)] 4}; | --------------------------- in this macro invocation | - = note: this error originates in the macro `cbor_map` (in Nightly builds, run with -Z macro-backtrace for more info) help: you must specify a concrete type for this numeric value, like `i32` | LL | cbor_map! { #[cfg(test)] 4_i32}; diff --git a/tests/ui/cfg/path-kw-as-cfg-pred.stderr b/tests/ui/cfg/path-kw-as-cfg-pred.stderr index 02128acb281e4..5cfb2f48a8370 100644 --- a/tests/ui/cfg/path-kw-as-cfg-pred.stderr +++ b/tests/ui/cfg/path-kw-as-cfg-pred.stderr @@ -485,6 +485,8 @@ LL + #[cfg_attr(predicate, attr1, attr2, ...)] error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:9:11 | +LL | macro_rules! foo { +LL | () => { LL | #[cfg($crate)] | ^^^^------^ | | @@ -494,7 +496,6 @@ LL | foo!(); | ------ in this macro invocation | = note: for more information, visit - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: must be of the form | LL - #[cfg($crate)] @@ -504,6 +505,8 @@ LL + #[cfg(predicate)] error[E0565]: malformed `cfg_attr` attribute input --> $DIR/path-kw-as-cfg-pred.rs:11:11 | +LL | macro_rules! foo { +... LL | #[cfg_attr($crate, path = "foo")] | ^^^^^^^^^------^^^^^^^^^^^^^^^ | | @@ -513,7 +516,6 @@ LL | foo!(); | ------ in this macro invocation | = note: for more information, visit - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: must be of the form | LL - #[cfg_attr($crate, path = "foo")] @@ -523,6 +525,8 @@ LL + #[cfg_attr(predicate, attr1, attr2, ...)] error[E0565]: malformed `cfg` attribute input --> $DIR/path-kw-as-cfg-pred.rs:13:26 | +LL | macro_rules! foo { +... LL | #[cfg_attr(true, cfg($crate))] | ^^^^------^ | | @@ -532,7 +536,6 @@ LL | foo!(); | ------ in this macro invocation | = note: for more information, visit - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: must be of the form | LL - #[cfg_attr(true, cfg($crate))] diff --git a/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr index c49b1d2d0e069..bdd536ea2a4df 100644 --- a/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr +++ b/tests/ui/closures/2229_closure_analysis/migrations/closure-body-macro-fragment.stderr @@ -1,6 +1,8 @@ warning: changes to closure capture in Rust 2021 will affect drop order --> $DIR/closure-body-macro-fragment.rs:16:17 | +LL | macro_rules! m { +LL | (@ $body:expr) => {{ LL | let f = || $body; | ^^ ... @@ -22,7 +24,6 @@ note: the lint level is defined here LL | #![warn(rust_2021_compatibility)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: `#[warn(rust_2021_incompatible_closure_captures)]` implied by `#[warn(rust_2021_compatibility)]` - = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: add a dummy let to cause `a` to be fully captured | LL ~ m!({ diff --git a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr index b4ec634adeb35..44e9e09c88847 100644 --- a/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-syntax-validation.stderr @@ -132,13 +132,13 @@ LL | #[cfg(a = b"hi")] error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable --> $DIR/cfg-attr-syntax-validation.rs:53:25 | +LL | macro_rules! generate_s10 { +LL | ($expr: expr) => { LL | #[cfg(feature = $expr)] | ^^^^^ ... LL | generate_s10!(concat!("nonexistent")); | ------------------------------------- in this macro invocation - | - = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors diff --git a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr index bdddbd68cdaf2..52045e7178f21 100644 --- a/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr +++ b/tests/ui/conditional-compilation/cfg-attr-unknown-attribute-macro-expansion.stderr @@ -1,13 +1,13 @@ error: cannot find attribute `unknown` in this scope --> $DIR/cfg-attr-unknown-attribute-macro-expansion.rs:3:26 | +LL | macro_rules! foo { +LL | () => { LL | #[cfg_attr(true, unknown)] | ^^^^^^^ ... LL | foo!(); | ------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index f21c791cdf7f4..e901460a4eb88 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -123,6 +123,8 @@ LL + #[cfg_attr(predicate, attr1, attr2, ...)] error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable --> $DIR/cfg_attr-attr-syntax-validation.rs:30:30 | +LL | macro_rules! generate_s10 { +LL | ($expr: expr) => { LL | #[cfg_attr(feature = $expr)] | ^^^^^ ... @@ -130,7 +132,6 @@ LL | generate_s10!(concat!("nonexistent")); | ------------------------------------- in this macro invocation | = note: for more information, visit - = note: this error originates in the macro `generate_s10` (in Nightly builds, run with -Z macro-backtrace for more info) help: must be of the form | LL - #[cfg_attr(feature = $expr)] diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr index 26d80c85e1610..f4318b9e9b8ee 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-2.stderr @@ -18,13 +18,14 @@ LL | const _: A< error[E0425]: cannot find value `x` in this scope --> $DIR/const_arg_trivial_macro_expansion-2.rs:7:9 | +LL | macro_rules! y { +LL | ( $($matcher:tt)*) => { LL | x | ^ not found in this scope ... LL | y! { test.tou8 } | ---------------- in this macro invocation | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might be missing a const parameter | LL | const _: A< diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr index 994f9158d5d80..d4d95168caf28 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr @@ -1,6 +1,8 @@ error: generic parameters may not be used in const operations --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 | +LL | macro_rules! arg { +LL | () => { LL | N | ^ cannot perform const operation using `N` ... @@ -10,11 +12,12 @@ LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item - = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) error: generic parameters may not be used in const operations --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 | +LL | macro_rules! arg { +LL | () => { LL | N | ^ cannot perform const operation using `N` ... @@ -24,7 +27,6 @@ LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item - = note: this error originates in the macro `arg` (in Nightly builds, run with -Z macro-backtrace for more info) error: generic parameters may not be used in const operations --> $DIR/const_arg_trivial_macro_expansion-4.rs:15:46 diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr index a1db1f26077df..334b72a2f8416 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr @@ -1,6 +1,8 @@ error: generic parameters may not be used in const operations --> $DIR/trivial-const-arg-macro-nested-braces-2.rs:3:9 | +LL | macro_rules! y { +LL | () => { LL | N | ^ cannot perform const operation using `N` ... @@ -10,7 +12,6 @@ LL | fn foo() -> A<{{ y!() }}> { = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr index 2a826f657d68d..068091e6cc933 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr @@ -1,6 +1,8 @@ error: generic parameters may not be used in const operations --> $DIR/trivial-const-arg-macro-nested-braces.rs:4:11 | +LL | macro_rules! y { +LL | () => { LL | { N } | ^ cannot perform const operation using `N` ... @@ -10,7 +12,6 @@ LL | fn foo() -> A<{ y!() }> { = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr index ab289e5a6b78f..bc1899d98b105 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-res-error.stderr @@ -1,13 +1,13 @@ error[E0425]: cannot find value `target` in this scope --> $DIR/trivial-const-arg-macro-res-error.rs:5:9 | +LL | macro_rules! len { +LL | () => { LL | target | ^^^^^^ not found in this scope ... LL | let val: [str; len!()] = []; | ------ in this macro invocation - | - = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0277]: the size for values of type `str` cannot be known at compilation time --> $DIR/trivial-const-arg-macro-res-error.rs:11:14 diff --git a/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr b/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr index 0d745517e4406..b46114bf4bd5f 100644 --- a/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr +++ b/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr @@ -10,6 +10,8 @@ LL | struct A; error[E0747]: constant provided when a type was expected --> $DIR/macro-const-arg-infer.rs:6:9 | +LL | macro_rules! y { +LL | ( $($matcher:tt)*) => { LL | _ | ^ ... @@ -18,12 +20,12 @@ LL | core::direct_const_arg!(y! { LL | | x LL | | }), | |_____- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants --> $DIR/macro-const-arg-infer.rs:6:9 | +LL | macro_rules! y { +LL | ( $($matcher:tt)*) => { LL | _ | ^ not allowed in type signatures ... @@ -32,8 +34,6 @@ LL | core::direct_const_arg!(y! { LL | | x LL | | }), | |_____- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr b/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr index 2d8cb50834bce..2fa529c750d10 100644 --- a/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr +++ b/tests/ui/const-generics/min_const_generics/macro-fail-const.stderr @@ -7,10 +7,9 @@ LL | fn make_marker() -> impl Marker { | this macro call doesn't expand to a type | in this macro invocation ... +LL | macro_rules! gimme_a_const { LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} | ^ expected type - | - = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` --> $DIR/macro-fail-const.rs:16:27 @@ -21,10 +20,9 @@ LL | Example:: | this macro call doesn't expand to a type | in this macro invocation ... +LL | macro_rules! gimme_a_const { LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} | ^ expected type - | - = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0747]: type provided when a constant was expected --> $DIR/macro-fail-const.rs:5:33 diff --git a/tests/ui/const-generics/min_const_generics/macro-fail.stderr b/tests/ui/const-generics/min_const_generics/macro-fail.stderr index b1d766cbfb644..23eeec7f6daa0 100644 --- a/tests/ui/const-generics/min_const_generics/macro-fail.stderr +++ b/tests/ui/const-generics/min_const_generics/macro-fail.stderr @@ -7,10 +7,9 @@ LL | fn make_marker() -> impl Marker { | this macro call doesn't expand to a type | in this macro invocation ... +LL | macro_rules! gimme_a_const { LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} | ^ expected type - | - = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` --> $DIR/macro-fail.rs:27:27 @@ -21,14 +20,14 @@ LL | Example:: | this macro call doesn't expand to a type | in this macro invocation ... +LL | macro_rules! gimme_a_const { LL | ($rusty: ident) => {{ let $rusty = 3; *&$rusty }} | ^ expected type - | - = note: this error originates in the macro `gimme_a_const` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected type, found `{` --> $DIR/macro-fail.rs:4:10 | +LL | macro_rules! external_macro { LL | () => {{ | ^ expected type ... @@ -37,8 +36,6 @@ LL | let _fail = Example::; | | | this macro call doesn't expand to a type | in this macro invocation - | - = note: this error originates in the macro `external_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected end of macro invocation --> $DIR/macro-fail.rs:36:25 diff --git a/tests/ui/consts/const-item-no-type/in-macro.stderr b/tests/ui/consts/const-item-no-type/in-macro.stderr index e2da412137433..81a7a21fbee30 100644 --- a/tests/ui/consts/const-item-no-type/in-macro.stderr +++ b/tests/ui/consts/const-item-no-type/in-macro.stderr @@ -1,6 +1,8 @@ error[E0428]: the name `A` is defined multiple times --> $DIR/in-macro.rs:4:13 | +LL | macro_rules! suite { +... LL | const A = "A".$fn(); | ^^^^^^^^^^^^^^^^^^^^ `A` redefined here ... @@ -11,11 +13,12 @@ LL | | } | |_- in this macro invocation | = note: `A` must be defined only once in the value namespace of this module - = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) error: missing type for `const` item --> $DIR/in-macro.rs:4:20 | +LL | macro_rules! suite { +... LL | const A = "A".$fn(); | ^ ... @@ -25,7 +28,6 @@ LL | | is_empty; LL | | } | |_- in this macro invocation | - = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) help: provide a type for the item | LL | const A: = "A".$fn(); @@ -34,6 +36,8 @@ LL | const A: = "A".$fn(); error[E0121]: missing type for item --> $DIR/in-macro.rs:4:20 | +LL | macro_rules! suite { +... LL | const A = "A".$fn(); | ^ not allowed in type signatures ... @@ -42,8 +46,6 @@ LL | | len; LL | | is_empty; LL | | } | |_- in this macro invocation - | - = note: this error originates in the macro `suite` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/consts/enum-discr-type-err.stderr b/tests/ui/consts/enum-discr-type-err.stderr index c676a96ad34a0..dba81198fcdf7 100644 --- a/tests/ui/consts/enum-discr-type-err.stderr +++ b/tests/ui/consts/enum-discr-type-err.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/enum-discr-type-err.rs:18:21 | +LL | macro_rules! mac { +... LL | $( $v = $s::V, )* | ^^^^^ expected `isize`, found `i32` ... @@ -11,11 +13,12 @@ LL | | } | |_- in this macro invocation | = note: enum variant discriminant can only be of a primitive type compatible with the enum's `repr` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/enum-discr-type-err.rs:18:21 | +LL | macro_rules! mac { +... LL | $( $v = $s::V, )* | ^^^^^ expected `isize`, found `i32` ... @@ -27,7 +30,6 @@ LL | | } | = note: enum variant discriminant can only be of a primitive type compatible with the enum's `repr` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/coroutine/parent-expression.stderr b/tests/ui/coroutine/parent-expression.stderr index 0dd97c538a87c..3536ce5bc39e7 100644 --- a/tests/ui/coroutine/parent-expression.stderr +++ b/tests/ui/coroutine/parent-expression.stderr @@ -1,6 +1,8 @@ error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:25:13 | +LL | macro_rules! type_combinations { +... LL | assert_send(g); | ^^^^^^^^^^^^^^ coroutine is not `Send` ... @@ -38,11 +40,12 @@ note: required by a bound in `assert_send` | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:25:13 | +LL | macro_rules! type_combinations { +... LL | assert_send(g); | ^^^^^^^^^^^^^^ coroutine is not `Send` ... @@ -80,11 +83,12 @@ note: required by a bound in `assert_send` | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: coroutine cannot be sent between threads safely --> $DIR/parent-expression.rs:25:13 | +LL | macro_rules! type_combinations { +... LL | assert_send(g); | ^^^^^^^^^^^^^^ coroutine is not `Send` ... @@ -122,7 +126,6 @@ note: required by a bound in `assert_send` | LL | fn assert_send(_thing: T) {} | ^^^^ required by this bound in `assert_send` - = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/delegation/self-hygiene.stderr b/tests/ui/delegation/self-hygiene.stderr index a0e14ed3cc259..5f6ba6e26d9a7 100644 --- a/tests/ui/delegation/self-hygiene.stderr +++ b/tests/ui/delegation/self-hygiene.stderr @@ -11,7 +11,6 @@ LL | | } | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters | = note: a module named `self` exists in another namespace - = note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0424]: cannot find value `self` in this scope --> $DIR/self-hygiene.rs:3:34 @@ -26,7 +25,6 @@ LL | | } | |_- delegation supports a `self` parameter, but a macro invocation can only access identifiers it receives from parameters | = note: a module named `self` exists in another namespace - = note: this error originates in the macro `emit_self` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr index 6244806e8af37..11e1c72ec170f 100644 --- a/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr +++ b/tests/ui/delegation/unused-target-expr-in-glob-or-list.stderr @@ -7,24 +7,24 @@ LL | reuse UnresolvedTrait::* { self.0 } error: delegation's target expression is specified for function with no params --> $DIR/unused-target-expr-in-glob-or-list.rs:107:49 | +LL | macro_rules! delegation { +... LL | reuse ::static_self { self.0 } | ^^^^^^^^^^ ... LL | delegation!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error: delegation's target expression is specified for function with no params --> $DIR/unused-target-expr-in-glob-or-list.rs:127:45 | +LL | macro_rules! delegation2 { +LL | () => { LL | reuse ::static_self { self.0 } | ^^^^^^^^^^ ... LL | delegation2!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error: delegation's target expression is specified for function with no params --> $DIR/unused-target-expr-in-glob-or-list.rs:154:45 @@ -163,6 +163,8 @@ LL | reuse to_reuse::{value, mut_ref, r#ref} { () } error[E0053]: method `static_self` has an incompatible type for trait --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 | +LL | macro_rules! delegation { +... LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^ expected `F`, found `()` ... @@ -176,7 +178,6 @@ LL | fn static_self() -> F { F } | ^ = note: expected signature `fn() -> F` found signature `fn() -> ()` - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the output type to match the trait | LL - reuse ::static_self { self.0 } @@ -186,6 +187,8 @@ LL + reuse :: -> F { self.0 } error[E0053]: method `static_self` has an incompatible type for trait --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 | +LL | macro_rules! delegation2 { +LL | () => { LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^ expected `F`, found `()` ... @@ -199,7 +202,6 @@ LL | fn static_self() -> F { F } | ^ = note: expected signature `fn() -> F` found signature `fn() -> ()` - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) help: change the output type to match the trait | LL - reuse ::static_self { self.0 } @@ -209,6 +211,8 @@ LL + reuse :: -> F { self.0 } error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 | +LL | macro_rules! delegation { +... LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^ ---------- unexpected argument ... @@ -220,11 +224,12 @@ note: associated function defined here | LL | fn static_self() -> F { F } | ^^^^^^^^^^^ - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/unused-target-expr-in-glob-or-list.rs:107:37 | +LL | macro_rules! delegation { +... LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^- help: consider using a semicolon here: `;` | | @@ -233,45 +238,45 @@ LL | reuse ::static_self { self.0 } ... LL | delegation!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `F` --> $DIR/unused-target-expr-in-glob-or-list.rs:112:57 | +LL | macro_rules! delegation { +... LL | reuse ::static_value { self.0 } | ^ unknown field ... LL | delegation!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `&mut F` --> $DIR/unused-target-expr-in-glob-or-list.rs:114:59 | +LL | macro_rules! delegation { +... LL | reuse ::static_mut_ref { self.0 } | ^ unknown field ... LL | delegation!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `&F` --> $DIR/unused-target-expr-in-glob-or-list.rs:116:55 | +LL | macro_rules! delegation { +... LL | reuse ::static_ref { self.0 } | ^ unknown field ... LL | delegation!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `delegation` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 | +LL | macro_rules! delegation2 { +LL | () => { LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^ ---------- unexpected argument ... @@ -283,11 +288,12 @@ note: associated function defined here | LL | fn static_self() -> F { F } | ^^^^^^^^^^^ - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/unused-target-expr-in-glob-or-list.rs:127:33 | +LL | macro_rules! delegation2 { +LL | () => { LL | reuse ::static_self { self.0 } | ^^^^^^^^^^^- help: consider using a semicolon here: `;` | | @@ -296,41 +302,39 @@ LL | reuse ::static_self { self.0 } ... LL | delegation2!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `F` --> $DIR/unused-target-expr-in-glob-or-list.rs:132:53 | +LL | macro_rules! delegation2 { +... LL | reuse ::static_value { self.0 } | ^ unknown field ... LL | delegation2!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `&mut F` --> $DIR/unused-target-expr-in-glob-or-list.rs:134:55 | +LL | macro_rules! delegation2 { +... LL | reuse ::static_mut_ref { self.0 } | ^ unknown field ... LL | delegation2!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0609]: no field `0` on type `&F` --> $DIR/unused-target-expr-in-glob-or-list.rs:136:51 | +LL | macro_rules! delegation2 { +... LL | reuse ::static_ref { self.0 } | ^ unknown field ... LL | delegation2!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `delegation2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0061]: this function takes 0 arguments but 1 argument was supplied --> $DIR/unused-target-expr-in-glob-or-list.rs:154:22 diff --git a/tests/ui/diagnostic_namespace/on_unknown/point_at_macro_argument.stderr b/tests/ui/diagnostic_namespace/on_unknown/point_at_macro_argument.stderr index 9cd6f17587151..035d140d9ecec 100644 --- a/tests/ui/diagnostic_namespace/on_unknown/point_at_macro_argument.stderr +++ b/tests/ui/diagnostic_namespace/on_unknown/point_at_macro_argument.stderr @@ -1,6 +1,8 @@ error[E0432]: unresolved import `things::what` --> $DIR/point_at_macro_argument.rs:12:17 | +LL | macro_rules! mac { +... LL | use things::$thing; | ^^^^^^^^^^^^^^ ... @@ -9,12 +11,12 @@ LL | mac!(what); | | | | | you did the bad thing | in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0432]: unresolved import `things::what2` --> $DIR/point_at_macro_argument.rs:12:17 | +LL | macro_rules! mac { +... LL | use things::$thing; | ^^^^^^^^^^^^^^ ... @@ -25,8 +27,6 @@ LL | | what2 ... | LL | | ); | |_____- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/did_you_mean/bad-assoc-expr.stderr b/tests/ui/did_you_mean/bad-assoc-expr.stderr index b83078e21b6a1..a401327705930 100644 --- a/tests/ui/did_you_mean/bad-assoc-expr.stderr +++ b/tests/ui/did_you_mean/bad-assoc-expr.stderr @@ -89,13 +89,13 @@ LL | ::clone(&0); error: missing angle brackets in associated item path --> $DIR/bad-assoc-expr.rs:23:19 | +LL | macro_rules! expr { LL | ($ty: ty) => ($ty::clone(&0)) | ^^^ ... LL | expr!(u8); | --------- in this macro invocation | - = note: this error originates in the macro `expr` (in Nightly builds, run with -Z macro-backtrace for more info) help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths | LL | ($ty: ty) => (<$ty>::clone(&0)) diff --git a/tests/ui/did_you_mean/bad-assoc-pat.stderr b/tests/ui/did_you_mean/bad-assoc-pat.stderr index aff3d97eadaeb..87d4baa54c250 100644 --- a/tests/ui/did_you_mean/bad-assoc-pat.stderr +++ b/tests/ui/did_you_mean/bad-assoc-pat.stderr @@ -56,13 +56,13 @@ LL | ::AssocItem => {} error: missing angle brackets in associated item path --> $DIR/bad-assoc-pat.rs:21:19 | +LL | macro_rules! pat { LL | ($ty: ty) => ($ty::AssocItem) | ^^^ ... LL | pat!(u8) => {} | -------- in this macro invocation | - = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths | LL | ($ty: ty) => (<$ty>::AssocItem) @@ -95,13 +95,12 @@ LL | &(u8,)::AssocItem => {} error[E0599]: no associated function or constant named `AssocItem` found for type `u8` in the current scope --> $DIR/bad-assoc-pat.rs:21:24 | +LL | macro_rules! pat { LL | ($ty: ty) => ($ty::AssocItem) | ^^^^^^^^^ associated function or constant not found in `u8` ... LL | pat!(u8) => {} | -------- in this macro invocation - | - = note: this error originates in the macro `pat` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: no associated function or constant named `AssocItem` found for type `u8` in the current scope --> $DIR/bad-assoc-pat.rs:32:16 diff --git a/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr index a7966f87ad379..bab27ed3fbff9 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2015.stderr @@ -89,13 +89,13 @@ LL | type I = ::AssocTy; error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:44:19 | +LL | macro_rules! ty { LL | ($ty: ty) => ($ty::AssocTy); | ^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | - = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths | LL | ($ty: ty) => (<$ty>::AssocTy); @@ -207,13 +207,13 @@ LL | type H = Fn(u8) -> (u8) + /* 'a */::Output; error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:44:19 | +LL | macro_rules! ty { LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | - = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path | LL - ($ty: ty) => ($ty::AssocTy); diff --git a/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr index 2ee8ab2760a92..bb3d0f862f9ce 100644 --- a/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr +++ b/tests/ui/did_you_mean/bad-assoc-ty.edition2021.stderr @@ -89,13 +89,13 @@ LL | type I = ::AssocTy; error: missing angle brackets in associated item path --> $DIR/bad-assoc-ty.rs:44:19 | +LL | macro_rules! ty { LL | ($ty: ty) => ($ty::AssocTy); | ^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | - = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) help: types that don't start with an identifier need to be surrounded with angle brackets in qualified paths | LL | ($ty: ty) => (<$ty>::AssocTy); @@ -193,13 +193,13 @@ LL | type H = (u8)>::Output; error[E0223]: ambiguous associated type --> $DIR/bad-assoc-ty.rs:44:19 | +LL | macro_rules! ty { LL | ($ty: ty) => ($ty::AssocTy); | ^^^^^^^^^^^^ ... LL | type J = ty!(u8); | ------- in this macro invocation | - = note: this error originates in the macro `ty` (in Nightly builds, run with -Z macro-backtrace for more info) help: if there were a trait named `Example` with associated type `AssocTy` implemented for `u8`, you could use the fully-qualified path | LL - ($ty: ty) => ($ty::AssocTy); diff --git a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr index 08166355748b5..82399b4ad02c4 100644 --- a/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr +++ b/tests/ui/did_you_mean/dont-suggest-hygienic-fields.stderr @@ -38,11 +38,12 @@ error[E0560]: struct `Crate` has no field named `fiel` | LL | environment!(); | -------------- in this macro invocation +LL | +LL | macro environment() { ... LL | const CRATE: Crate = Crate { fiel: () }; | ^^^^ unknown field | - = note: this error originates in the macro `environment` (in Nightly builds, run with -Z macro-backtrace for more info) help: a field with a similar name exists | LL | const CRATE: Crate = Crate { field: () }; diff --git a/tests/ui/did_you_mean/recursion_limit_deref.stderr b/tests/ui/did_you_mean/recursion_limit_deref.stderr index faa85dc5ae98c..8aa4ee1ac6519 100644 --- a/tests/ui/did_you_mean/recursion_limit_deref.stderr +++ b/tests/ui/did_you_mean/recursion_limit_deref.stderr @@ -9,6 +9,8 @@ error: reached the recursion limit finding the struct tail for `Bottom` error: reached the recursion limit finding the struct tail for `Bottom` --> $DIR/recursion_limit_deref.rs:14:9 | +LL | macro_rules! link { +LL | ($outer:ident, $inner:ident) => { LL | struct $outer($inner); | ^^^^^^^^^^^^^^^^^^^^^^ ... @@ -16,7 +18,6 @@ LL | link!(A, B); | ----------- in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` - = note: this error originates in the macro `link` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0055]: reached the recursion limit while auto-dereferencing `J` --> $DIR/recursion_limit_deref.rs:55:22 diff --git a/tests/ui/did_you_mean/recursion_limit_macro.stderr b/tests/ui/did_you_mean/recursion_limit_macro.stderr index dc4189ed9ab68..311faeabaeb7c 100644 --- a/tests/ui/did_you_mean/recursion_limit_macro.stderr +++ b/tests/ui/did_you_mean/recursion_limit_macro.stderr @@ -1,6 +1,8 @@ error: recursion limit reached while expanding `recurse!` --> $DIR/recursion_limit_macro.rs:10:31 | +LL | macro_rules! recurse { +LL | () => { }; LL | ($t:tt $($tail:tt)*) => { recurse!($($tail)*) }; | ^^^^^^^^^^^^^^^^^^^ ... @@ -8,7 +10,6 @@ LL | recurse!(0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9); | ------------------------------------------------- in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit_macro`) - = note: this error originates in the macro `recurse` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/directory_ownership/macro-expanded-mod.stderr b/tests/ui/directory_ownership/macro-expanded-mod.stderr index cb00a3fe60823..cd56f37cee656 100644 --- a/tests/ui/directory_ownership/macro-expanded-mod.stderr +++ b/tests/ui/directory_ownership/macro-expanded-mod.stderr @@ -1,6 +1,8 @@ error: cannot declare a file module inside a block unless it has a path attribute --> $DIR/macro-expanded-mod.rs:5:9 | +LL | macro_rules! mod_decl { +LL | ($i:ident) => { LL | mod $i; | ^^^^^^^ ... @@ -8,7 +10,6 @@ LL | mod_decl!(foo); | -------------- in this macro invocation | = note: file modules are usually placed outside of blocks, at the top level of the file - = note: this error originates in the macro `mod_decl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr index 413d51701be19..43d1a330a4354 100644 --- a/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword-2.stderr @@ -1,35 +1,35 @@ error: `$crate` in paths can only be used in start position --> $DIR/dollar-crate-is-keyword-2.rs:5:16 | +LL | macro_rules! m { +LL | () => { LL | use a::$crate; | ^^^^^^ ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/dollar-crate-is-keyword-2.rs:6:16 | +LL | macro_rules! m { +... LL | use a::$crate::b; | ^^^^^^ can only be used in path start position ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/dollar-crate-is-keyword-2.rs:8:21 | +LL | macro_rules! m { +... LL | type A = a::$crate; | ^^^^^^ can only be used in path start position ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr b/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr index 224380c7ba919..a6f3c1e10fad7 100644 --- a/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr +++ b/tests/ui/dollar-crate/dollar-crate-is-keyword.stderr @@ -1,35 +1,36 @@ error: expected identifier, found reserved identifier `$crate` --> $DIR/dollar-crate-is-keyword.rs:6:20 | +LL | macro_rules! m { +... LL | struct $crate {} | ^^^^^^ expected identifier, found reserved identifier ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected identifier, found reserved identifier `$crate` --> $DIR/dollar-crate-is-keyword.rs:10:23 | +LL | macro_rules! m { +... LL | use $crate as $crate; | ^^^^^^ expected identifier, found reserved identifier ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: imports need to be explicitly named --> $DIR/dollar-crate-is-keyword.rs:9:13 | +LL | macro_rules! m { +... LL | use $crate; | ^^^^^^ ... LL | m!(); | ---- in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate as name; diff --git a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr index a13c84f0e527d..d4432ffb7f245 100644 --- a/tests/ui/drop/lint-if-let-rescope-with-macro.stderr +++ b/tests/ui/drop/lint-if-let-rescope-with-macro.stderr @@ -1,6 +1,8 @@ error: `if let` assigns a shorter lifetime since Edition 2024 --> $DIR/lint-if-let-rescope-with-macro.rs:12:12 | +LL | macro_rules! edition_2021_if_let { +LL | ($p:pat, $e:expr, { $($conseq:tt)* } { $($alt:tt)* }) => { LL | if let $p = $e { $($conseq)* } else { $($alt)* } | ^^^^^^^^^^^ ... @@ -38,7 +40,6 @@ note: the lint level is defined here | LL | #![deny(if_let_rescope)] | ^^^^^^^^^^^^^^ - = note: this error originates in the macro `edition_2021_if_let` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/editions/edition-cstr-2015-2018.stderr b/tests/ui/editions/edition-cstr-2015-2018.stderr index bcc9d65405bd1..f4db7cfcb0356 100644 --- a/tests/ui/editions/edition-cstr-2015-2018.stderr +++ b/tests/ui/editions/edition-cstr-2015-2018.stderr @@ -45,8 +45,6 @@ LL | macro_rules! construct { ($x:ident) => { $x"str" } } ... LL | construct!(c); | ------------- in this macro invocation - | - = note: this error originates in the macro `construct` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `"str"` --> $DIR/edition-cstr-2015-2018.rs:6:33 @@ -61,7 +59,6 @@ LL | contain!(); = note: c-string literals require Rust 2021 or later = help: pass `--edition 2024` to `rustc` = note: for more on editions, read https://doc.rust-lang.org/edition-guide - = note: this error originates in the macro `contain` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/expr/if/if-let.stderr b/tests/ui/expr/if/if-let.stderr index 792504a9772f6..2671e65ca2cf7 100644 --- a/tests/ui/expr/if/if-let.stderr +++ b/tests/ui/expr/if/if-let.stderr @@ -1,6 +1,8 @@ warning: irrefutable `if let` pattern --> $DIR/if-let.rs:6:16 | +LL | macro_rules! foo { +LL | ($p:pat, $e:expr, $b:block) => {{ LL | if let $p = $e $b | ^^^^^^^^^^^ ... @@ -12,13 +14,18 @@ LL | | }); = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` = note: `#[warn(irrefutable_let_patterns)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `if let` pattern --> $DIR/if-let.rs:6:16 | -LL | if let $p = $e $b - | ^^^ +LL | / macro_rules! foo { +LL | | ($p:pat, $e:expr, $b:block) => {{ +LL | | if let $p = $e $b + | | ^^^ +... | +LL | | }} +LL | | } + | |_____- this warning originates in the macro `foo` which comes from the expansion of the macro `bar` ... LL | / bar!(a, 1, { LL | | println!("irrefutable pattern"); @@ -27,7 +34,6 @@ LL | | }); | = note: this pattern will always match, so the `if let` is useless = help: consider replacing the `if let` with a `let` - = note: this warning originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `if let` pattern --> $DIR/if-let.rs:26:8 diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr index ef50447434a5a..24fde629cca9c 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unsafe-nested-macro.stderr @@ -1,6 +1,8 @@ error[E0658]: the `allow_internal_unsafe` attribute side-steps the `unsafe_code` lint --> $DIR/feature-gate-allow-internal-unsafe-nested-macro.rs:8:11 | +LL | macro_rules! bar { +... LL | #[allow_internal_unsafe] | ^^^^^^^^^^^^^^^^^^^^^ ... @@ -9,7 +11,6 @@ LL | bar!(); | = help: add `#![feature(allow_internal_unsafe)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr index 823589c443334..a756a8a52dfd1 100644 --- a/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr +++ b/tests/ui/feature-gates/feature-gate-allow-internal-unstable-nested-macro.stderr @@ -1,6 +1,8 @@ error[E0658]: the `allow_internal_unstable` attribute side-steps feature gating and stability checks --> $DIR/feature-gate-allow-internal-unstable-nested-macro.rs:8:11 | +LL | macro_rules! bar { +... LL | #[allow_internal_unstable()] | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -9,7 +11,6 @@ LL | bar!(); | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr b/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr index 7838d8a32b292..cd6e6e385fbe9 100644 --- a/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr +++ b/tests/ui/feature-gates/feature-gate-check-nested-macro-invocation.stderr @@ -1,6 +1,8 @@ error[E0658]: the `allow_internal_unstable` attribute side-steps feature gating and stability checks --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:11 | +LL | macro_rules! foo ( +LL | () => ( LL | #[allow_internal_unstable()] | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -9,11 +11,12 @@ LL | foo!(); | = help: add `#![feature(allow_internal_unstable)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: the `allow_internal_unstable` attribute cannot be used on macro calls --> $DIR/feature-gate-check-nested-macro-invocation.rs:8:11 | +LL | macro_rules! foo ( +LL | () => ( LL | #[allow_internal_unstable()] | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | foo!(); | = help: the `allow_internal_unstable` attribute can be applied to functions and macro defs = note: placing this attribute on a macro invocation does nothing even if the macro expands to what would be a valid target for the attribute - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/trace_macros-gate.stderr b/tests/ui/feature-gates/trace_macros-gate.stderr index 6ca9d1573d920..dc9ef09308a59 100644 --- a/tests/ui/feature-gates/trace_macros-gate.stderr +++ b/tests/ui/feature-gates/trace_macros-gate.stderr @@ -37,6 +37,7 @@ LL | trace_macros!(false); error[E0658]: use of unstable library feature `trace_macros`: `trace_macros` is not stable enough for use and is subject to change --> $DIR/trace_macros-gate.rs:10:26 | +LL | macro_rules! expando { LL | ($x: ident) => { trace_macros!($x) } | ^^^^^^^^^^^^ ... @@ -46,7 +47,6 @@ LL | expando!(true); = note: see issue #29598 for more information = help: add `#![feature(trace_macros)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `expando` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/fmt/format-args-capture-macro-hygiene.stderr b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr index 47ef581629e20..4dd6b60816a9b 100644 --- a/tests/ui/fmt/format-args-capture-macro-hygiene.stderr +++ b/tests/ui/fmt/format-args-capture-macro-hygiene.stderr @@ -19,6 +19,7 @@ LL | format!(concat!("{ba", "r} {}"), 1); error: there is no argument named `foo` --> $DIR/format-args-capture-macro-hygiene.rs:7:13 | +LL | macro_rules! def_site { LL | () => { "{foo}" } | ^^^^^^^ ... @@ -27,7 +28,6 @@ LL | format!(def_site!()); | = note: did you intend to capture a variable `foo` from the surrounding scope? = note: to avoid ambiguity, `format_args!` cannot capture variables when the format string is expanded from a macro - = note: this error originates in the macro `def_site` (in Nightly builds, run with -Z macro-backtrace for more info) error: there is no argument named `foo` --> $DIR/format-args-capture-macro-hygiene.rs:19:24 diff --git a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr index dda9b398a833c..905f4ad65e026 100644 --- a/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr +++ b/tests/ui/fn/fn-arg-count-mismatch-diagnostics.stderr @@ -1,6 +1,8 @@ error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/fn-arg-count-mismatch-diagnostics.rs:24:9 | +LL | macro_rules! delegate_local { +LL | ($method:ident) => { LL | ::$method(8) | ^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing ... @@ -12,7 +14,6 @@ note: associated function defined here | LL | fn foo(a: u8, b: u8) {} | ^^^ ----- - = note: this error originates in the macro `delegate_local` (in Nightly builds, run with -Z macro-backtrace for more info) help: provide the argument | LL | ::$method(8, /* u8 */) @@ -34,6 +35,8 @@ LL | fn foo(a: u8, b: u8) {} error[E0061]: this function takes 2 arguments but 1 argument was supplied --> $DIR/fn-arg-count-mismatch-diagnostics.rs:31:9 | +LL | macro_rules! delegate_from { +LL | ($from:ident, $method:ident) => { LL | <$from>::$method(8) | ^^^^^^^^^^^^^^^^--- argument #2 of type `u8` is missing ... @@ -45,7 +48,6 @@ note: associated function defined here | LL | fn foo(a: u8, b: u8) {} | ^^^ ----- - = note: this error originates in the macro `delegate_from` (in Nightly builds, run with -Z macro-backtrace for more info) help: provide the argument | LL | <$from>::$method(8, /* u8 */) diff --git a/tests/ui/for-loop-while/label_break_value_invalid.stderr b/tests/ui/for-loop-while/label_break_value_invalid.stderr index f6999c4ab116a..011e29183e8c4 100644 --- a/tests/ui/for-loop-while/label_break_value_invalid.stderr +++ b/tests/ui/for-loop-while/label_break_value_invalid.stderr @@ -1,13 +1,13 @@ error[E0426]: use of undeclared label `'a` --> $DIR/label_break_value_invalid.rs:6:19 | +LL | macro_rules! mac2 { +LL | ($val:expr) => { LL | break 'a $val; | ^^ undeclared label `'a` ... LL | mac2!(2); | -------- in this macro invocation - | - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0426]: use of undeclared label `'a` --> $DIR/label_break_value_invalid.rs:28:19 diff --git a/tests/ui/for-loop-while/while-let-2.stderr b/tests/ui/for-loop-while/while-let-2.stderr index 355ae6f718ec8..8c49cfcb3dbee 100644 --- a/tests/ui/for-loop-while/while-let-2.stderr +++ b/tests/ui/for-loop-while/while-let-2.stderr @@ -1,6 +1,8 @@ warning: irrefutable `while let` pattern --> $DIR/while-let-2.rs:7:19 | +LL | macro_rules! foo{ +LL | ($p:pat, $e:expr, $b:block) => {{ LL | while let $p = $e $b | ^^^^^^^^^^^ ... @@ -12,13 +14,18 @@ LL | | }); = note: this pattern will always match, so the loop will never exit = help: consider instead using a `loop { ... }` with a `let` inside it = note: `#[warn(irrefutable_let_patterns)]` on by default - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern --> $DIR/while-let-2.rs:7:19 | -LL | while let $p = $e $b - | ^^^ +LL | / macro_rules! foo{ +LL | | ($p:pat, $e:expr, $b:block) => {{ +LL | | while let $p = $e $b + | | ^^^ +... | +LL | | }} +LL | | } + | |_____- this warning originates in the macro `foo` which comes from the expansion of the macro `bar` ... LL | / bar!(_a, 1, { LL | | println!("irrefutable pattern"); @@ -27,7 +34,6 @@ LL | | }); | = note: this pattern will always match, so the loop will never exit = help: consider instead using a `loop { ... }` with a `let` inside it - = note: this warning originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) warning: irrefutable `while let` pattern --> $DIR/while-let-2.rs:27:11 diff --git a/tests/ui/generics/generics-on-self-mod-segment.stderr b/tests/ui/generics/generics-on-self-mod-segment.stderr index 4a2d5939a3ec8..eeef8e8584b25 100644 --- a/tests/ui/generics/generics-on-self-mod-segment.stderr +++ b/tests/ui/generics/generics-on-self-mod-segment.stderr @@ -17,6 +17,8 @@ LL | fn crate_(_: crate::::Ty) {} error[E0109]: type arguments are not allowed on module `generics_on_self_mod_segment` --> $DIR/generics-on-self-mod-segment.rs:11:38 | +LL | macro_rules! dollar_crate { +LL | () => { LL | fn dollar_crate_(_: $crate::::Ty) {} | ------ ^^^ type argument not allowed | | @@ -24,8 +26,6 @@ LL | fn dollar_crate_(_: $crate::::Ty) {} ... LL | dollar_crate!(); | --------------- in this macro invocation - | - = note: this error originates in the macro `dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/generics/wrong-number-of-args-in-macro.stderr b/tests/ui/generics/wrong-number-of-args-in-macro.stderr index 62a5eb9414ed5..f882423937e6c 100644 --- a/tests/ui/generics/wrong-number-of-args-in-macro.stderr +++ b/tests/ui/generics/wrong-number-of-args-in-macro.stderr @@ -1,13 +1,14 @@ error[E0425]: cannot find type `a` in this scope --> $DIR/wrong-number-of-args-in-macro.rs:7:13 | +LL | macro_rules! foo_ty { +LL | ($a:ty, $b:ty) => { LL | Foo | ^ not found in this scope ... LL | fn foo<'a, 'b>() -> foo_ty!(&'b (), &'b ()) {} | ----------------------- in this macro invocation | - = note: this error originates in the macro `foo_ty` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might be missing a type parameter | LL | fn foo<'a, 'b, a>() -> foo_ty!(&'b (), &'b ()) {} @@ -16,6 +17,8 @@ LL | fn foo<'a, 'b, a>() -> foo_ty!(&'b (), &'b ()) {} error[E0107]: struct takes 1 generic argument but 2 generic arguments were supplied --> $DIR/wrong-number-of-args-in-macro.rs:7:9 | +LL | macro_rules! foo_ty { +LL | ($a:ty, $b:ty) => { LL | Foo | ^^^ expected 1 generic argument ... @@ -27,7 +30,6 @@ note: struct defined here, with 1 generic parameter: `T` | LL | struct Foo; | ^^^ - - = note: this error originates in the macro `foo_ty` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0392]: type parameter `T` is never used --> $DIR/wrong-number-of-args-in-macro.rs:3:12 diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr index ec0e09a302ea1..8474fa038c47d 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-dotdotdot-bad-syntax.stderr @@ -49,13 +49,14 @@ LL + ..=0.0f32 => {} error: range-to patterns with `...` are not allowed --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | let ...$e; | ^^^ ... LL | mac!(0); | ------- in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..=` instead | LL - let ...$e; @@ -65,6 +66,8 @@ LL + let ..=$e; error[E0005]: refutable pattern in local binding --> $DIR/half-open-range-pats-inclusive-dotdotdot-bad-syntax.rs:25:17 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | let ...$e; | ^^^^^ pattern `1_i32..=i32::MAX` not covered ... @@ -74,7 +77,6 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr index 63258f3538313..baf613e859246 100644 --- a/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr +++ b/tests/ui/half-open-range-patterns/half-open-range-pats-inclusive-no-end.stderr @@ -53,6 +53,8 @@ LL + if let X.. = 1 {} error[E0586]: inclusive range with no end --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:19 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | let $e...; | ^^^ ... @@ -60,7 +62,6 @@ LL | mac!(0); | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..` instead | LL - let $e...; @@ -70,6 +71,8 @@ LL + let $e..; error[E0586]: inclusive range with no end --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:19 | +LL | macro_rules! mac { +... LL | let $e..=; | ^^^ ... @@ -77,7 +80,6 @@ LL | mac!(0); | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..` instead | LL - let $e..=; @@ -87,6 +89,8 @@ LL + let $e..; error[E0005]: refutable pattern in local binding --> $DIR/half-open-range-pats-inclusive-no-end.rs:18:17 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | let $e...; | ^^^^^ pattern `i32::MIN..=-1_i32` not covered ... @@ -96,11 +100,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/half-open-range-pats-inclusive-no-end.rs:20:17 | +LL | macro_rules! mac { +... LL | let $e..=; | ^^^^^ pattern `i32::MIN..=-1_i32` not covered ... @@ -110,7 +115,6 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 8 previous errors diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr index d7f0860a026ac..08f226e6b202a 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other ... @@ -10,7 +12,6 @@ LL | | for<'a> fn(&'a u32, &'a u32) -> &'a u32) } | = note: expected enum `Option fn(&'a _, &'b _) -> &'a _>` found enum `Option fn(&'a _, &'a _) -> &'a _>` - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr index 9b5ca3b2056aa..af50fb333de35 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other ... @@ -10,7 +12,6 @@ LL | | fn(&'x u32)) } | = note: expected enum `Option fn(&'a _)>` found enum `Option` - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr index 48703186cc634..263617a2657ee 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_inv_a_b_vs_bound_inv_a.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other ... @@ -10,11 +12,12 @@ LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } | = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` found enum `Option fn(Inv<'a>, Inv<'a>)>` - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0308]: mismatched types --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | gimme::<$t1>(None::<$t2>); | ^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other ... @@ -25,7 +28,6 @@ LL | | for<'a> fn(Inv<'a>, Inv<'a>)) } = note: expected enum `Option fn(Inv<'a>, Inv<'b>)>` found enum `Option fn(Inv<'a>, Inv<'a>)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr index 31d36d7168b61..078ecde8775de 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.free_inv_x_vs_free_inv_y.stderr @@ -1,6 +1,8 @@ error: lifetime may not live long enough --> $DIR/hr-subtype.rs:48:13 | +LL | macro_rules! check { +... LL | fn subtype<'x, 'y: 'x, 'z: 'y>() { | -- -- lifetime `'y` defined here | | @@ -16,11 +18,12 @@ LL | | fn(Inv<'y>)) } = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see for more information about variance - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: lifetime may not live long enough --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | -- -- lifetime `'y` defined here | | @@ -36,7 +39,6 @@ LL | | fn(Inv<'y>)) } = note: requirement occurs because of the type `Inv<'_>`, which makes the generic argument `'_` invariant = note: the struct `Inv<'a>` is invariant over the parameter `'a` = help: see for more information about variance - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr index a8e00125fc63a..bb734ca3e7190 100644 --- a/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr +++ b/tests/ui/higher-ranked/subtype/hr-subtype.free_x_vs_free_y.stderr @@ -1,6 +1,8 @@ error: lifetime may not live long enough --> $DIR/hr-subtype.rs:54:13 | +LL | macro_rules! check { +... LL | fn supertype<'x, 'y: 'x, 'z: 'y>() { | -- -- lifetime `'y` defined here | | @@ -13,7 +15,6 @@ LL | | fn(&'y u32)) } | |______________- in this macro invocation | = help: consider adding the following bound: `'x: 'y` - = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/assoc_item_ctxt.stderr b/tests/ui/hygiene/assoc_item_ctxt.stderr index effa9e8d65592..30925a8b17dd7 100644 --- a/tests/ui/hygiene/assoc_item_ctxt.stderr +++ b/tests/ui/hygiene/assoc_item_ctxt.stderr @@ -1,6 +1,8 @@ error[E0407]: method `method` is not a member of trait `Tr` --> $DIR/assoc_item_ctxt.rs:33:13 | +LL | macro mac_trait_impl() { +LL | impl Tr for u8 { LL | fn method() {} | ^^^------^^^^^ | | | @@ -9,8 +11,6 @@ LL | fn method() {} ... LL | mac_trait_impl!(); | ----------------- in this macro invocation - | - = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0046]: not all trait items implemented, missing: `method` --> $DIR/assoc_item_ctxt.rs:32:9 @@ -18,13 +18,12 @@ error[E0046]: not all trait items implemented, missing: `method` LL | fn method(); | ------------ `method` from trait ... +LL | macro mac_trait_impl() { LL | impl Tr for u8 { | ^^^^^^^^^^^^^^ missing `method` in implementation ... LL | mac_trait_impl!(); | ----------------- in this macro invocation - | - = note: this error originates in the macro `mac_trait_impl` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/hygiene/duplicate_lifetimes.stderr b/tests/ui/hygiene/duplicate_lifetimes.stderr index 9f1a75147272d..1d43c4becd27c 100644 --- a/tests/ui/hygiene/duplicate_lifetimes.stderr +++ b/tests/ui/hygiene/duplicate_lifetimes.stderr @@ -1,6 +1,7 @@ error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate_lifetimes.rs:8:14 | +LL | macro m($a:lifetime) { LL | fn g<$a, 'a>() {} | ^^ already used ... @@ -9,12 +10,11 @@ LL | m!('a); | | | | | first use of `'a` | in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0403]: the name `'a` is already used for a generic parameter in this item's generic parameters --> $DIR/duplicate_lifetimes.rs:13:14 | +LL | macro n($a:lifetime) { LL | fn h<$a, 'a>() {} | ^^ already used ... @@ -23,8 +23,6 @@ LL | n!('a); | | | | | first use of `'a` | in this macro invocation - | - = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr index db1a56d7d8169..22c0a3068cf12 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr @@ -7,17 +7,19 @@ LL | use my_core; error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail-2018.rs:8:13 | +LL | macro a() { +... LL | use my_core; | ^^^^^^^ no external crate `my_core` ... LL | a!(); | ---- in this macro invocation - | - = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find module or crate `my_core` in this scope --> $DIR/extern-prelude-from-opaque-fail-2018.rs:12:18 | +LL | macro a() { +... LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of unresolved module or unlinked crate `my_core` ... @@ -27,7 +29,6 @@ LL | a!(); = help: you might be missing a crate named `my_core` = help: consider importing this module: std::mem - = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find module or crate `my_core` in this scope --> $DIR/extern-prelude-from-opaque-fail-2018.rs:25:14 diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr index f3a43fa0127c8..fd33b1b394283 100644 --- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr +++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr @@ -7,17 +7,19 @@ LL | use my_core; error[E0432]: unresolved import `my_core` --> $DIR/extern-prelude-from-opaque-fail.rs:8:13 | +LL | macro a() { +... LL | use my_core; | ^^^^^^^ no `my_core` in the root ... LL | a!(); | ---- in this macro invocation - | - = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find module or crate `my_core` in this scope --> $DIR/extern-prelude-from-opaque-fail.rs:12:18 | +LL | macro a() { +... LL | fn f() { my_core::mem::drop(0); } | ^^^^^^^ use of unresolved module or unlinked crate `my_core` ... @@ -27,7 +29,6 @@ LL | a!(); = help: you might be missing a crate named `my_core` = help: consider importing this module: my_core::mem - = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find module or crate `my_core` in this scope --> $DIR/extern-prelude-from-opaque-fail.rs:25:14 diff --git a/tests/ui/hygiene/fields-definition.stderr b/tests/ui/hygiene/fields-definition.stderr index 701986ea76e7f..78e2df984b18e 100644 --- a/tests/ui/hygiene/fields-definition.stderr +++ b/tests/ui/hygiene/fields-definition.stderr @@ -1,6 +1,8 @@ error[E0124]: field `a` is already declared --> $DIR/fields-definition.rs:14:13 | +LL | macro_rules! legacy { +... LL | a: u8, | ----- `a` first declared here LL | $a: u8, @@ -8,8 +10,6 @@ LL | $a: u8, ... LL | legacy!(a); | ---------- in this macro invocation - | - = note: this error originates in the macro `legacy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/fields-move.stderr b/tests/ui/hygiene/fields-move.stderr index b5b507c7daa55..43c538e0d9579 100644 --- a/tests/ui/hygiene/fields-move.stderr +++ b/tests/ui/hygiene/fields-move.stderr @@ -1,6 +1,8 @@ error[E0382]: use of moved value: `foo.x` --> $DIR/fields-move.rs:18:9 | +LL | macro_rules! copy_legacy { +LL | ($foo: ident) => { LL | $foo.x | ^^^^^^ value used here after move ... @@ -10,7 +12,6 @@ LL | assert_two_copies(copy_legacy!(foo), foo.x); | ----------------- in this macro invocation | = note: move occurs because `foo.x` has type `NonCopy`, which does not implement the `Copy` trait - = note: this error originates in the macro `copy_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0382]: use of moved value: `foo.x` --> $DIR/fields-move.rs:28:42 diff --git a/tests/ui/hygiene/fields.stderr b/tests/ui/hygiene/fields.stderr index 99252c4b752cc..d32d0b15ef4db 100644 --- a/tests/ui/hygiene/fields.stderr +++ b/tests/ui/hygiene/fields.stderr @@ -1,46 +1,46 @@ error: type `foo::S` is private --> $DIR/fields.rs:13:17 | +LL | pub macro m($S:ident, $x:ident) {{ +... LL | let s = S { x: 0 }; | ^^^^^^^^^^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation - | - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `foo::S` is private --> $DIR/fields.rs:14:17 | +LL | pub macro m($S:ident, $x:ident) {{ +... LL | let _ = s.x; | ^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation - | - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `T` is private --> $DIR/fields.rs:16:17 | +LL | pub macro m($S:ident, $x:ident) {{ +... LL | let t = T(0); | ^^^^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation - | - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `T` is private --> $DIR/fields.rs:17:17 | +LL | pub macro m($S:ident, $x:ident) {{ +... LL | let _ = t.0; | ^ private type ... LL | let s = foo::m!(S, x); | ------------- in this macro invocation - | - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/hygiene/generate-mod.stderr b/tests/ui/hygiene/generate-mod.stderr index bfdb72c22cb9b..740ae98ce77c0 100644 --- a/tests/ui/hygiene/generate-mod.stderr +++ b/tests/ui/hygiene/generate-mod.stderr @@ -19,46 +19,46 @@ LL | genmod!(FromOutside, Outer); error[E0425]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:19:18 | +LL | macro genmod_transparent() { +... LL | type A = FromOutside; | ^^^^^^^^^^^ not found in this scope ... LL | genmod_transparent!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:20:22 | +LL | macro genmod_transparent() { +... LL | type Inner = Outer; | ^^^^^ not found in this scope ... LL | genmod_transparent!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `genmod_transparent` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `FromOutside` in this scope --> $DIR/generate-mod.rs:28:18 | +LL | macro_rules! genmod_legacy { () => { +... LL | type A = FromOutside; | ^^^^^^^^^^^ not found in this scope ... LL | genmod_legacy!(); | ---------------- in this macro invocation - | - = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `Outer` in this scope --> $DIR/generate-mod.rs:29:22 | +LL | macro_rules! genmod_legacy { () => { +... LL | type Inner = Outer; | ^^^^^ not found in this scope ... LL | genmod_legacy!(); | ---------------- in this macro invocation - | - = note: this error originates in the macro `genmod_legacy` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/hygiene/globs.stderr b/tests/ui/hygiene/globs.stderr index 7decdab3a3954..a35cd12205d4d 100644 --- a/tests/ui/hygiene/globs.stderr +++ b/tests/ui/hygiene/globs.stderr @@ -22,6 +22,8 @@ LL + use foo::f; error[E0425]: cannot find function `g` in this scope --> $DIR/globs.rs:16:5 | +LL | macro m($($t:tt)*) { +... LL | g(); | ^ not found in this scope ... @@ -37,7 +39,6 @@ note: similarly named function `f` defined here | LL | pub fn f() {} | ^^^^^^^^^^ - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: a function with a similar name exists | LL - g(); @@ -56,14 +57,13 @@ LL | n!(f); | | | | | you might have meant to refer to this function | in this macro invocation +LL | macro n($i:ident) { ... LL | $j(); | -- due to this macro variable ... LL | n!(f); | ^ not found in this scope - | - = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find function `f` in this scope --> $DIR/globs.rs:66:17 @@ -73,14 +73,13 @@ LL | n!(f); | | | | | you might have meant to refer to this function | in this macro invocation +LL | macro n($i:ident) { ... LL | $j(); | -- due to this macro variable ... LL | f | ^ not found in this scope - | - = note: this error originates in the macro `n` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/hygiene/hygienic-label-1.stderr b/tests/ui/hygiene/hygienic-label-1.stderr index 5529d8dc83656..3bb2f340fb7bc 100644 --- a/tests/ui/hygiene/hygienic-label-1.stderr +++ b/tests/ui/hygiene/hygienic-label-1.stderr @@ -1,13 +1,12 @@ error[E0426]: use of undeclared label `'x` --> $DIR/hygienic-label-1.rs:2:19 | +LL | macro_rules! foo { LL | () => { break 'x; } | ^^ undeclared label `'x` ... LL | 'x: loop { foo!(); } | ------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/hygienic-label-3.stderr b/tests/ui/hygiene/hygienic-label-3.stderr index 495afc69a9543..f620622c9f3ee 100644 --- a/tests/ui/hygiene/hygienic-label-3.stderr +++ b/tests/ui/hygiene/hygienic-label-3.stderr @@ -1,13 +1,12 @@ error[E0426]: use of undeclared label `'x` --> $DIR/hygienic-label-3.rs:2:19 | +LL | macro_rules! foo { LL | () => { break 'x; } | ^^ undeclared label `'x` ... LL | foo!(); | ------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/impl_items.stderr b/tests/ui/hygiene/impl_items.stderr index 35f2750403de4..05d8f2b998c48 100644 --- a/tests/ui/hygiene/impl_items.stderr +++ b/tests/ui/hygiene/impl_items.stderr @@ -1,13 +1,12 @@ error: type `for<'a> fn(&'a foo::S) {foo::S::f}` is private --> $DIR/impl_items.rs:10:23 | +LL | pub macro m() { LL | let _: () = S.f(); | ^ private type ... LL | foo::m!(); | --------- in this macro invocation - | - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/missing-self-diag.stderr b/tests/ui/hygiene/missing-self-diag.stderr index 21be48b859eb4..8af5e1209a028 100644 --- a/tests/ui/hygiene/missing-self-diag.stderr +++ b/tests/ui/hygiene/missing-self-diag.stderr @@ -1,6 +1,8 @@ error[E0424]: cannot find value `self` in this scope --> $DIR/missing-self-diag.rs:10:9 | +LL | macro_rules! call_bar { +LL | () => { LL | self.bar(); | ^^^^ `self` value is a keyword only available in methods with a `self` parameter ... @@ -11,7 +13,6 @@ LL | | } | |_____- this function has a `self` parameter, but a macro invocation can only access identifiers it receives from parameters | = note: a module named `self` exists in another namespace - = note: this error originates in the macro `call_bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/no_implicit_prelude.stderr b/tests/ui/hygiene/no_implicit_prelude.stderr index 5461ee527b880..10573662fc442 100644 --- a/tests/ui/hygiene/no_implicit_prelude.stderr +++ b/tests/ui/hygiene/no_implicit_prelude.stderr @@ -4,10 +4,10 @@ error[E0433]: cannot find type `Vec` in this scope LL | fn f() { ::bar::m!(); } | ----------- in this macro invocation ... +LL | pub macro m() { LL | Vec::new(); | ^^^ use of undeclared type `Vec` | - = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct | LL + use std::vec::Vec; @@ -19,11 +19,12 @@ error[E0599]: no method named `clone` found for unit type `()` in the current sc LL | fn f() { ::bar::m!(); } | ----------- in this macro invocation ... +LL | pub macro m() { +LL | Vec::new(); LL | ().clone() | ^^^^^ | = help: items from traits can only be used if the trait is in scope - = note: this error originates in the macro `::bar::m` (in Nightly builds, run with -Z macro-backtrace for more info) help: trait `Clone` which provides `clone` is implemented but not in scope; perhaps you want to import it | LL + use std::clone::Clone; diff --git a/tests/ui/hygiene/pattern-macro.stderr b/tests/ui/hygiene/pattern-macro.stderr index 047244ba9edef..be25ee7532d35 100644 --- a/tests/ui/hygiene/pattern-macro.stderr +++ b/tests/ui/hygiene/pattern-macro.stderr @@ -1,6 +1,8 @@ error[E0425]: cannot find value `x` in this scope --> $DIR/pattern-macro.rs:5:5 | +LL | macro_rules! foo { () => ( x ) } +... LL | x + 1; | ^ not found in this scope | @@ -12,7 +14,6 @@ LL | macro_rules! foo { () => ( x ) } ... LL | let foo!() = 2; | ------ in this macro invocation - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/privacy-early.stderr b/tests/ui/hygiene/privacy-early.stderr index 556c6e3fe02ca..22a8db986ad3d 100644 --- a/tests/ui/hygiene/privacy-early.stderr +++ b/tests/ui/hygiene/privacy-early.stderr @@ -1,6 +1,7 @@ error[E0364]: `f` is private, and cannot be re-exported --> $DIR/privacy-early.rs:10:13 | +LL | pub macro m() { LL | use f as g; | ^^^^^^ ... @@ -15,11 +16,11 @@ LL | use f as g; ... LL | foo::m!(); | --------- in this macro invocation - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0364]: `f` is private, and cannot be re-exported --> $DIR/privacy-early.rs:10:13 | +LL | pub macro m() { LL | use f as g; | ^^^^^^ ... @@ -35,7 +36,6 @@ LL | use f as g; LL | foo::m!(); | --------- in this macro invocation = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/hygiene/rustc-macro-transparency.stderr b/tests/ui/hygiene/rustc-macro-transparency.stderr index 597d2f6f9d837..10c725600ba37 100644 --- a/tests/ui/hygiene/rustc-macro-transparency.stderr +++ b/tests/ui/hygiene/rustc-macro-transparency.stderr @@ -7,6 +7,8 @@ LL | Opaque; error[E0423]: cannot find value `semiopaque` in this scope --> $DIR/rustc-macro-transparency.rs:29:5 | +LL | macro semiopaque() { +... LL | semiopaque; | ^^^^^^^^^^ not found in this scope | @@ -19,7 +21,6 @@ LL | struct SemiOpaque; ... LL | semiopaque!(); | ------------- in this macro invocation - = note: this error originates in the macro `semiopaque` (in Nightly builds, run with -Z macro-backtrace for more info) help: a unit struct with a similar name exists (notice the capitalization) | LL - semiopaque; diff --git a/tests/ui/hygiene/trait_items.stderr b/tests/ui/hygiene/trait_items.stderr index e5212ce1f56c0..3609fac714f3d 100644 --- a/tests/ui/hygiene/trait_items.stderr +++ b/tests/ui/hygiene/trait_items.stderr @@ -11,7 +11,6 @@ LL | pub macro m() { ().f() } | ^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = note: this error originates in the macro `::baz::m` (in Nightly builds, run with -Z macro-backtrace for more info) help: trait `T` which provides `f` is implemented but not in scope; perhaps you want to import it | LL + use foo::T; diff --git a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr index b4c022d352193..a0ce4a2a2e080 100644 --- a/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr +++ b/tests/ui/impl-trait/in-trait/dont-probe-missing-item-name-4.stderr @@ -1,6 +1,8 @@ error[E0271]: type mismatch resolving `::Output == i64` --> $DIR/dont-probe-missing-item-name-4.rs:21:13 | +LL | macro_rules! f { +... LL | problem(MyServerFn {}); | ------- ^^^^^^^^^^^^^ type mismatch resolving `::Output == i64` | | @@ -19,7 +21,6 @@ note: required by a bound in `problem` | LL | fn problem>(_: T) {} | ^^^^^^^^^^^^ required by this bound in `problem` - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/imports/ambiguous-import-visibility-macro.stderr b/tests/ui/imports/ambiguous-import-visibility-macro.stderr index 6f5f1c4dd3ec6..ee6976624c7c5 100644 --- a/tests/ui/imports/ambiguous-import-visibility-macro.stderr +++ b/tests/ui/imports/ambiguous-import-visibility-macro.stderr @@ -1,6 +1,8 @@ warning: ambiguous import visibility: pub(crate) or pub --> $DIR/ambiguous-import-visibility-macro.rs:17:9 | +LL | macro_rules! globbing{ +... LL | pub use RustEmbed as Embed; | ^^^^^^^^^ | @@ -23,7 +25,6 @@ LL | #[macro_use] // this imports the `RustEmbed` macro with `pub(crate)` visibi = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #149145 = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default - = note: this warning originates in the macro `globbing` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/imports/ambiguous-import-visibility-module.stderr b/tests/ui/imports/ambiguous-import-visibility-module.stderr index 1532bcfe7f4e6..03d1f05c4a8c4 100644 --- a/tests/ui/imports/ambiguous-import-visibility-module.stderr +++ b/tests/ui/imports/ambiguous-import-visibility-module.stderr @@ -1,6 +1,8 @@ warning: ambiguous import visibility: pub or pub(in crate::reexport) --> $DIR/ambiguous-import-visibility-module.rs:18:13 | +LL | macro_rules! mac { +... LL | pub use S as Z; | ^ | @@ -23,7 +25,6 @@ LL | pub use m::*; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #149145 = note: `#[warn(ambiguous_import_visibilities)]` (part of `#[warn(future_incompatible)]`) on by default - = note: this warning originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/imports/extern-prelude-extern-crate-fail.stderr b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr index 42735ff90c90b..9b31544f250c1 100644 --- a/tests/ui/imports/extern-prelude-extern-crate-fail.stderr +++ b/tests/ui/imports/extern-prelude-extern-crate-fail.stderr @@ -1,13 +1,13 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/extern-prelude-extern-crate-fail.rs:16:9 | +LL | macro_rules! define_std_as_non_existent { +LL | () => { LL | extern crate std as non_existent; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_std_as_non_existent!(); | ----------------------------- in this macro invocation - | - = note: this error originates in the macro `define_std_as_non_existent` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find module or crate `two_macros` in this scope --> $DIR/extern-prelude-extern-crate-fail.rs:10:9 diff --git a/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr index d09d14b27f90f..4ea0f0f1a66b0 100644 --- a/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr +++ b/tests/ui/imports/extern-prelude-extern-crate-restricted-shadowing.stderr @@ -1,17 +1,19 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:20:9 | +LL | macro_rules! define_other_core { +LL | () => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `Vec` is ambiguous --> $DIR/extern-prelude-extern-crate-restricted-shadowing.rs:14:9 | +LL | macro_rules! define_vec { +... LL | Vec::panic!(); | ^^^ ambiguous name | @@ -26,7 +28,6 @@ LL | define_vec!(); | ------------- in this macro invocation note: `Vec` could also refer to a struct from prelude --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL - = note: this error originates in the macro `define_vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/imports/import-prefix-macro-1.stderr b/tests/ui/imports/import-prefix-macro-1.stderr index bdc0e85b43ed0..fa77bc5082398 100644 --- a/tests/ui/imports/import-prefix-macro-1.stderr +++ b/tests/ui/imports/import-prefix-macro-1.stderr @@ -1,13 +1,12 @@ error: expected one of `::`, `;`, or `as`, found `{` --> $DIR/import-prefix-macro-1.rs:11:27 | +LL | macro_rules! import { LL | ($p: path) => (use $p {S, Z}); | ^ expected one of `::`, `;`, or `as` ... LL | import! { a::b::c } | ------------------- in this macro invocation - | - = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/imports/import-prefix-macro-2.stderr b/tests/ui/imports/import-prefix-macro-2.stderr index fbeca99b13800..e1670b8dcf5d9 100644 --- a/tests/ui/imports/import-prefix-macro-2.stderr +++ b/tests/ui/imports/import-prefix-macro-2.stderr @@ -1,13 +1,12 @@ error: expected identifier, found metavariable --> $DIR/import-prefix-macro-2.rs:11:26 | +LL | macro_rules! import { LL | ($p: path) => (use ::$p {S, Z}); | ^^ expected identifier, found metavariable ... LL | import! { a::b::c } | ------------------- in this macro invocation - | - = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/imports/issue-109148.stderr b/tests/ui/imports/issue-109148.stderr index ee047385ae328..499fb1b461b4e 100644 --- a/tests/ui/imports/issue-109148.stderr +++ b/tests/ui/imports/issue-109148.stderr @@ -1,17 +1,19 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/issue-109148.rs:6:9 | +LL | macro_rules! m { +LL | () => { LL | extern crate core as std; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `std` is ambiguous --> $DIR/issue-109148.rs:13:5 | +LL | macro_rules! m { +... LL | use std::mem; | ^^^ ambiguous name | @@ -26,11 +28,12 @@ LL | extern crate core as std; LL | m!(); | ---- in this macro invocation = help: use `crate::std` to refer to this crate unambiguously - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `std` is ambiguous --> $DIR/issue-109148.rs:14:7 | +LL | macro_rules! m { +... LL | use ::std::mem as _; | ^^^ ambiguous name | @@ -44,7 +47,6 @@ LL | extern crate core as std; ... LL | m!(); | ---- in this macro invocation - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/imports/issue-114682-1.stderr b/tests/ui/imports/issue-114682-1.stderr index fd2776f50ad77..fa7354f774fd1 100644 --- a/tests/ui/imports/issue-114682-1.stderr +++ b/tests/ui/imports/issue-114682-1.stderr @@ -1,6 +1,8 @@ error[E0659]: `A` is ambiguous --> $DIR/issue-114682-1.rs:23:5 | +LL | macro_rules! mac { +... LL | A!(); | ^ ambiguous name | @@ -22,7 +24,6 @@ note: `A` could also refer to the macro imported here LL | pub use m::*; | ^^^^ = help: use `crate::A` to refer to this macro unambiguously - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/imports/local-modularized-tricky-fail-1.stderr b/tests/ui/imports/local-modularized-tricky-fail-1.stderr index 0d1a29027845e..b69051140ed25 100644 --- a/tests/ui/imports/local-modularized-tricky-fail-1.stderr +++ b/tests/ui/imports/local-modularized-tricky-fail-1.stderr @@ -1,6 +1,8 @@ error[E0659]: `exported` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:29:1 | +LL | macro_rules! define_exported { () => { +... LL | exported!(); | ^^^^^^^^ ambiguous name | @@ -22,11 +24,12 @@ note: `exported` could also refer to the macro imported here LL | use inner1::*; | ^^^^^^^^^ = help: use `crate::exported` to refer to this macro unambiguously - = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `panic` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:36:5 | +LL | macro_rules! define_panic { () => { +... LL | panic!(); | ^^^^^ ambiguous name | @@ -44,11 +47,12 @@ LL | define_panic!(); = help: use `crate::panic` to refer to this macro unambiguously note: `panic` could also refer to a macro from prelude --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL - = note: this error originates in the macro `define_panic` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `include` is ambiguous --> $DIR/local-modularized-tricky-fail-1.rs:47:1 | +LL | macro_rules! define_include { () => { +... LL | include!(); | ^^^^^^^ ambiguous name | @@ -66,7 +70,6 @@ LL | define_include!(); = help: use `crate::include` to refer to this macro unambiguously note: `include` could also refer to a macro from prelude --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL - = note: this error originates in the macro `define_include` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/imports/local-modularized-tricky-fail-2.stderr b/tests/ui/imports/local-modularized-tricky-fail-2.stderr index 6dae1508995da..3457cfed58459 100644 --- a/tests/ui/imports/local-modularized-tricky-fail-2.stderr +++ b/tests/ui/imports/local-modularized-tricky-fail-2.stderr @@ -1,6 +1,8 @@ error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths --> $DIR/local-modularized-tricky-fail-2.rs:13:9 | +LL | macro_rules! define_exported { () => { +... LL | use crate::exported; | ^^^^^^^^^^^^^^^ | @@ -17,11 +19,12 @@ LL | define_exported!(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #52234 = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths --> $DIR/local-modularized-tricky-fail-2.rs:19:5 | +LL | macro_rules! define_exported { () => { +... LL | crate::exported!(); | ^^^^^^^^^^^^^^^ | @@ -37,7 +40,6 @@ LL | define_exported!(); | ------------------ in this macro invocation = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #52234 - = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors @@ -45,6 +47,8 @@ Future incompatibility report: Future breakage diagnostic: error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths --> $DIR/local-modularized-tricky-fail-2.rs:13:9 | +LL | macro_rules! define_exported { () => { +... LL | use crate::exported; | ^^^^^^^^^^^^^^^ | @@ -61,12 +65,13 @@ LL | define_exported!(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #52234 = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: error: macro-expanded `macro_export` macros from the current crate cannot be referred to by absolute paths --> $DIR/local-modularized-tricky-fail-2.rs:19:5 | +LL | macro_rules! define_exported { () => { +... LL | crate::exported!(); | ^^^^^^^^^^^^^^^ | @@ -83,5 +88,4 @@ LL | define_exported!(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #52234 = note: `#[deny(macro_expanded_macro_exports_accessed_by_absolute_paths)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `define_exported` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr index bc9755732813c..23d8f2f99e21a 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr +++ b/tests/ui/imports/multiple-extern-by-macro-for-buitlin.stderr @@ -3,7 +3,9 @@ error[E0259]: the name `core` is defined multiple times | LL | extern crate core; | ------------------ previous import of the extern crate `core` here -... +LL | +LL | macro_rules! m { +LL | () => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ `core` reimported here ... @@ -11,7 +13,6 @@ LL | m!(); | ---- in this macro invocation | = note: `core` must be defined only once in the type namespace of this module - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: you can use `as` to change the binding name of the import | LL | extern crate std as other_core; diff --git a/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr index f1b60bbe39d5b..3005f83f4f1c2 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr +++ b/tests/ui/imports/multiple-extern-by-macro-for-custom.stderr @@ -3,7 +3,9 @@ error[E0259]: the name `empty` is defined multiple times | LL | extern crate empty; | ------------------- previous import of the extern crate `empty` here -... +LL | +LL | macro_rules! m { +LL | () => { LL | extern crate std as empty; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ `empty` reimported here ... @@ -11,7 +13,6 @@ LL | m!(); | ---- in this macro invocation | = note: `empty` must be defined only once in the type namespace of this module - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: you can use `as` to change the binding name of the import | LL | extern crate std as other_empty; diff --git a/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr index 13e1aaacd7025..47f386073c00e 100644 --- a/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr +++ b/tests/ui/imports/multiple-extern-by-macro-for-inexist.stderr @@ -10,6 +10,8 @@ error[E0259]: the name `non_existent` is defined multiple times LL | extern crate non_existent; | -------------------------- previous import of the extern crate `non_existent` here ... +LL | macro_rules! m { +LL | () => { LL | extern crate std as non_existent; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `non_existent` reimported here ... @@ -17,7 +19,6 @@ LL | m!(); | ---- in this macro invocation | = note: `non_existent` must be defined only once in the type namespace of this module - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: you can use `as` to change the binding name of the import | LL | extern crate std as other_non_existent; diff --git a/tests/ui/imports/point_macro_input.stderr b/tests/ui/imports/point_macro_input.stderr index f063c8c132498..2294a971c1bf2 100644 --- a/tests/ui/imports/point_macro_input.stderr +++ b/tests/ui/imports/point_macro_input.stderr @@ -1,6 +1,8 @@ error[E0432]: unresolved import `things::what2` --> $DIR/point_macro_input.rs:15:17 | +LL | macro_rules! mac2 { +... LL | use things::$thing; | ^^^^^^^^^^^^^^ ... @@ -11,8 +13,6 @@ LL | | what2 LL | | LL | | ); | |_____- in this macro invocation - | - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `what1` in module `things` --> $DIR/point_macro_input.rs:26:9 diff --git a/tests/ui/imports/private-from-decl-macro.fail.stderr b/tests/ui/imports/private-from-decl-macro.fail.stderr index 9d6941d064767..80b6fde5e8539 100644 --- a/tests/ui/imports/private-from-decl-macro.fail.stderr +++ b/tests/ui/imports/private-from-decl-macro.fail.stderr @@ -1,6 +1,8 @@ error[E0364]: `S` is private, and cannot be re-exported --> $DIR/private-from-decl-macro.rs:18:13 | +LL | pub macro mac_glob() { +LL | #[cfg(fail)] LL | use crate::m::*; | ^^^^^^^^^^^ ... @@ -15,7 +17,6 @@ LL | use crate::m::*; ... LL | crate::m::mac_glob!(); | --------------------- in this macro invocation - = note: this error originates in the macro `crate::m::mac_glob` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0423]: cannot find value `S` in this scope --> $DIR/private-from-decl-macro.rs:28:17 diff --git a/tests/ui/imports/shadow_builtin_macros.stderr b/tests/ui/imports/shadow_builtin_macros.stderr index 7799fb230d434..93c282ec0d952 100644 --- a/tests/ui/imports/shadow_builtin_macros.stderr +++ b/tests/ui/imports/shadow_builtin_macros.stderr @@ -18,6 +18,8 @@ note: `panic` could also refer to a macro from prelude error[E0659]: `panic` is ambiguous --> $DIR/shadow_builtin_macros.rs:33:5 | +LL | macro_rules! m { () => { +... LL | panic!(); | ^^^^^ ambiguous name | @@ -32,7 +34,6 @@ LL | m!(); | ---- in this macro invocation note: `panic` could also refer to a macro from prelude --> $SRC_DIR/std/src/prelude/mod.rs:LL:COL - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `n` is ambiguous --> $DIR/shadow_builtin_macros.rs:49:5 diff --git a/tests/ui/infinite/infinite-macro-expansion.stderr b/tests/ui/infinite/infinite-macro-expansion.stderr index 08fb4fa77236b..80db33b493b0f 100644 --- a/tests/ui/infinite/infinite-macro-expansion.stderr +++ b/tests/ui/infinite/infinite-macro-expansion.stderr @@ -1,6 +1,7 @@ error: recursion limit reached while expanding `recursive!` --> $DIR/infinite-macro-expansion.rs:2:12 | +LL | macro_rules! recursive { LL | () => (recursive!()) | ^^^^^^^^^^^^ ... @@ -8,7 +9,6 @@ LL | recursive!() | ------------ in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`infinite_macro_expansion`) - = note: this error originates in the macro `recursive` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/internal/internal-unstable.stderr b/tests/ui/internal/internal-unstable.stderr index 924d512e99836..f3e41f6c2a646 100644 --- a/tests/ui/internal/internal-unstable.stderr +++ b/tests/ui/internal/internal-unstable.stderr @@ -65,15 +65,21 @@ LL | bar!(internal_unstable::unstable()); error[E0658]: use of unstable library feature `function` --> $DIR/internal-unstable.rs:19:9 | -LL | internal_unstable::unstable(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | / macro_rules! foo { +LL | | ($e: expr, $f: expr) => {{ +LL | | $e; +LL | | $f; +LL | | internal_unstable::unstable(); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | | }} +LL | | } + | |_- this error originates in the macro `foo` which comes from the expansion of the macro `bar` ... -LL | bar!(internal_unstable::unstable()); - | ----------------------------------- in this macro invocation +LL | bar!(internal_unstable::unstable()); + | ----------------------------------- in this macro invocation | = help: add `#![feature(function)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - = note: this error originates in the macro `foo` which comes from the expansion of the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors diff --git a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/macro.stderr b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/macro.stderr index 5412c943ec087..81d17c9162588 100644 --- a/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/macro.stderr +++ b/tests/ui/lifetimes/mismatched-lifetime-syntaxes-details/macro.stderr @@ -1,6 +1,8 @@ error: hiding or eliding a lifetime that's named elsewhere is confusing --> $DIR/macro.rs:10:12 | +LL | macro_rules! repeated { +LL | ($($pair:ident),+ ; $middle:ty) => { LL | ($($pair),+, $middle, $($pair),+) | ^^^^^ ^^^^^ the same lifetimes are hidden here | | @@ -19,7 +21,6 @@ note: the lint level is defined here | LL | #![deny(mismatched_lifetime_syntaxes)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `repeated` (in Nightly builds, run with -Z macro-backtrace for more info) help: consistently use `'a` | LL ~ ($($pair<'a, 'a>),+, $middle, $($pair<'a, 'a>),+) diff --git a/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr b/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr index be9f8b19545b5..5a18f0f63e23d 100644 --- a/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr +++ b/tests/ui/lint/dangling-pointers-from-temporaries/cstring-as-ptr.stderr @@ -27,6 +27,8 @@ LL | #![deny(temporary_cstring_as_ptr)] error: this creates a dangling pointer because temporary `CString` is dropped at end of statement --> $DIR/cstring-as-ptr.rs:9:52 | +LL | macro_rules! mymacro { +LL | () => { LL | let s = CString::new("some text").unwrap().as_ptr(); | ---------------------------------- ^^^^^^ pointer created here | | @@ -39,7 +41,6 @@ LL | mymacro!(); = note: a dangling pointer is safe, but dereferencing one is undefined behavior = note: returning a pointer to a local variable will always result in a dangling pointer = note: for more information, see - = note: this error originates in the macro `mymacro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr b/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr index 72a74c1579dd4..bc9893f15f256 100644 --- a/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr +++ b/tests/ui/lint/expect-future_breakage-crash-issue-126521.stderr @@ -2,6 +2,8 @@ Future incompatibility report: Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/expect-future_breakage-crash-issue-126521.rs:7:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -10,12 +12,13 @@ LL | let _ = foo!(x); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/expect-future_breakage-crash-issue-126521.rs:13:35 | +LL | macro_rules! bar { +LL | ($val:ident) => { LL | (5_i32.overflowing_sub(3)); | ^ ... @@ -24,29 +27,28 @@ LL | let _ = bar!(x); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/expect-future_breakage-crash-issue-126521.rs:7:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... LL | let _ = foo!(x); | ------- in this macro invocation - | - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/expect-future_breakage-crash-issue-126521.rs:13:35 | +LL | macro_rules! bar { +LL | ($val:ident) => { LL | (5_i32.overflowing_sub(3)); | ^ ... LL | let _ = bar!(x); | ------- in this macro invocation - | - = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/lint-double-negations-macro.stderr b/tests/ui/lint/lint-double-negations-macro.stderr index d6ac9be48f304..11da29fbedba2 100644 --- a/tests/ui/lint/lint-double-negations-macro.stderr +++ b/tests/ui/lint/lint-double-negations-macro.stderr @@ -1,6 +1,8 @@ warning: use of a double negation --> $DIR/lint-double-negations-macro.rs:9:9 | +LL | macro_rules! bad_macro { +LL | ($e: expr) => { LL | --$e | ^^^^ ... @@ -10,7 +12,6 @@ LL | bad_macro!(1); = note: the prefix `--` could be misinterpreted as a decrement operator which exists in other languages = note: use `-= 1` if you meant to decrement the value = note: `#[warn(double_negations)]` on by default - = note: this warning originates in the macro `bad_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: add parentheses for clarity | LL | -(-$e) diff --git a/tests/ui/lint/lint-raw-borrows-via-references.stderr b/tests/ui/lint/lint-raw-borrows-via-references.stderr index f04922b52f05a..e31c467f76ee2 100644 --- a/tests/ui/lint/lint-raw-borrows-via-references.stderr +++ b/tests/ui/lint/lint-raw-borrows-via-references.stderr @@ -90,6 +90,8 @@ LL + { &raw const y } warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers --> $DIR/lint-raw-borrows-via-references.rs:68:10 | +LL | macro_rules! ref_cast { +LL | ($e:expr) => { LL | &$e as *const i32 | ^^^^^^^^^^^^^^^^ ... @@ -97,7 +99,6 @@ LL | unsafe { ref_cast!(*x) } | ------------- in this macro invocation | = help: consider using `&raw const` for a safer and more explicit raw pointer - = note: this warning originates in the macro `ref_cast` (in Nightly builds, run with -Z macro-backtrace for more info) warning: creating an intermediate reference implies aliasing requirements even when immediately cast to a raw pointers --> $DIR/lint-raw-borrows-via-references.rs:79:13 diff --git a/tests/ui/lint/lint-strict-provenance-macro-casts.stderr b/tests/ui/lint/lint-strict-provenance-macro-casts.stderr index 08a1707490623..93caaafb483c9 100644 --- a/tests/ui/lint/lint-strict-provenance-macro-casts.stderr +++ b/tests/ui/lint/lint-strict-provenance-macro-casts.stderr @@ -1,6 +1,8 @@ error: cast from `*const u8` to `usize` implicitly exposes pointer provenance --> $DIR/lint-strict-provenance-macro-casts.rs:6:9 | +LL | macro_rules! cast { +LL | ($e:expr, $t:ty) => { LL | $e as $t | ^^^^^^^^ ... @@ -14,11 +16,12 @@ note: the lint level is defined here | LL | #![deny(implicit_provenance_casts)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `cast` (in Nightly builds, run with -Z macro-backtrace for more info) error: cast from `usize` to `*const u8` implicitly relies on exposed provenance --> $DIR/lint-strict-provenance-macro-casts.rs:6:9 | +LL | macro_rules! cast { +LL | ($e:expr, $t:ty) => { LL | $e as $t | ^^^^^^^^ ... @@ -27,11 +30,11 @@ LL | let _ptr = cast!(0usize, *const u8); | = help: if conforming to strict provenance is not possible, use `std::ptr::with_exposed_provenance()` = note: for more information, visit - = note: this error originates in the macro `cast` (in Nightly builds, run with -Z macro-backtrace for more info) error: cast from `*const u8` to `usize` implicitly exposes pointer provenance --> $DIR/lint-strict-provenance-macro-casts.rs:13:20 | +LL | macro_rules! p2i { LL | ($e:expr) => { $e as usize }; | ^^^^^^^^^^^ ... @@ -40,11 +43,11 @@ LL | p2i!(&raw const x); | = help: if conforming to strict provenance is not possible, use `.expose_provenance()` = note: for more information, visit - = note: this error originates in the macro `p2i` (in Nightly builds, run with -Z macro-backtrace for more info) error: cast from `usize` to `*const ()` implicitly relies on exposed provenance --> $DIR/lint-strict-provenance-macro-casts.rs:18:20 | +LL | macro_rules! i2p { LL | ($e:expr) => { $e as *const () }; | ^^^^^^^^^^^^^^^ ... @@ -53,7 +56,6 @@ LL | i2p!(0x42); | = help: if conforming to strict provenance is not possible, use `std::ptr::with_exposed_provenance()` = note: for more information, visit - = note: this error originates in the macro `i2p` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/lint/lint-unsafe-code.stderr b/tests/ui/lint/lint-unsafe-code.stderr index 9b4df1273acbc..d39fddbe56806 100644 --- a/tests/ui/lint/lint-unsafe-code.stderr +++ b/tests/ui/lint/lint-unsafe-code.stderr @@ -85,13 +85,13 @@ LL | unsafe {} error: usage of an `unsafe` block --> $DIR/lint-unsafe-code.rs:34:9 | +LL | macro_rules! unsafe_in_macro { +... LL | unsafe {} | ^^^^^^^^^ ... LL | unsafe_in_macro!() | ------------------ in this macro invocation - | - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `no_mangle` attribute --> $DIR/lint-unsafe-code.rs:38:3 @@ -144,6 +144,8 @@ LL | #[link_section = "__TEXT,__text"] static UWU: u32 = 5; error: usage of the unsafe `no_mangle` attribute --> $DIR/lint-unsafe-code.rs:28:11 | +LL | macro_rules! unsafe_in_macro { +LL | () => {{ LL | #[no_mangle] fn foo() {} | ^^^^^^^^^ ... @@ -151,11 +153,12 @@ LL | unsafe_in_macro!() | ------------------ in this macro invocation | = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `no_mangle` attribute --> $DIR/lint-unsafe-code.rs:29:11 | +LL | macro_rules! unsafe_in_macro { +... LL | #[no_mangle] static FOO: u32 = 5; | ^^^^^^^^^ ... @@ -163,11 +166,12 @@ LL | unsafe_in_macro!() | ------------------ in this macro invocation | = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `export_name` attribute --> $DIR/lint-unsafe-code.rs:30:11 | +LL | macro_rules! unsafe_in_macro { +... LL | #[export_name = "bar"] fn bar() {} | ^^^^^^^^^^^^^^^^^^^ ... @@ -175,11 +179,12 @@ LL | unsafe_in_macro!() | ------------------ in this macro invocation | = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `export_name` attribute --> $DIR/lint-unsafe-code.rs:32:11 | +LL | macro_rules! unsafe_in_macro { +... LL | #[export_name = "BAR"] static BAR: u32 = 5; | ^^^^^^^^^^^^^^^^^^^ ... @@ -187,7 +192,6 @@ LL | unsafe_in_macro!() | ------------------ in this macro invocation | = note: the linker's behavior with multiple libraries exporting duplicate symbol names is undefined and Rust cannot provide guarantees when you manually override them - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: usage of the unsafe `naked` attribute --> $DIR/lint-unsafe-code.rs:139:3 diff --git a/tests/ui/lint/lints-in-foreign-macros.stderr b/tests/ui/lint/lints-in-foreign-macros.stderr index c0164bd00ffff..4bfdd97b02983 100644 --- a/tests/ui/lint/lints-in-foreign-macros.stderr +++ b/tests/ui/lint/lints-in-foreign-macros.stderr @@ -1,6 +1,7 @@ warning: unused import: `std::string::ToString` --> $DIR/lints-in-foreign-macros.rs:11:16 | +LL | macro_rules! foo { LL | () => {use std::string::ToString;} | ^^^^^^^^^^^^^^^^^^^^^ ... @@ -12,7 +13,6 @@ note: the lint level is defined here | LL | #![warn(unused_imports)] | ^^^^^^^^^^^^^^ - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unused import: `std::string::ToString` --> $DIR/lints-in-foreign-macros.rs:16:18 diff --git a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr index b6fe1a921d756..deb6f29e61f08 100644 --- a/tests/ui/lint/non-local-defs/inside-macro_rules.stderr +++ b/tests/ui/lint/non-local-defs/inside-macro_rules.stderr @@ -1,6 +1,8 @@ warning: non-local `impl` definition, `impl` blocks should be written at the same level as their item --> $DIR/inside-macro_rules.rs:9:13 | +LL | macro_rules! m { +... LL | fn my_func() { | ------------ move the `impl` block outside of this function `my_func` LL | impl MacroTrait for OutsideStruct {} @@ -15,7 +17,6 @@ LL | m!(); = note: the macro `m` defines the non-local `impl`, and may need to be changed = note: an `impl` is never scoped, even when it is nested inside an item, as it may impact type checking outside of that item, which can be the case if neither the trait or the self type are at the same nesting level as the `impl` = note: `#[warn(non_local_definitions)]` on by default - = note: this warning originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 1 warning emitted diff --git a/tests/ui/lint/redundant-semicolon/suggest-remove-semi-in-macro-expansion-issue-142143.stderr b/tests/ui/lint/redundant-semicolon/suggest-remove-semi-in-macro-expansion-issue-142143.stderr index 7a38ec318ab6a..36b0ff767e453 100644 --- a/tests/ui/lint/redundant-semicolon/suggest-remove-semi-in-macro-expansion-issue-142143.stderr +++ b/tests/ui/lint/redundant-semicolon/suggest-remove-semi-in-macro-expansion-issue-142143.stderr @@ -1,6 +1,7 @@ error: unnecessary trailing semicolon --> $DIR/suggest-remove-semi-in-macro-expansion-issue-142143.rs:6:43 | +LL | macro_rules! m { LL | ($stmt:stmt) => { #[allow(bad_style)] $stmt } | ^^^^^ ... @@ -12,7 +13,6 @@ note: the lint level is defined here | LL | #![deny(redundant_semicolons)] | ^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr index f0ee27a99151f..19a41481542b5 100644 --- a/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr +++ b/tests/ui/lint/rfc-2383-lint-reason/expect_lint_from_macro.stderr @@ -14,6 +14,8 @@ LL | trigger_unused_variables_macro!(); warning: unused variable: `x` --> $DIR/expect_lint_from_macro.rs:7:13 | +LL | macro_rules! trigger_unused_variables_macro { +LL | () => { LL | let x = 0; | ^ ... @@ -33,11 +35,12 @@ note: the lint level is defined here | LL | #![warn(unused_variables)] | ^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unused variable: `x` --> $DIR/expect_lint_from_macro.rs:7:13 | +LL | macro_rules! trigger_unused_variables_macro { +LL | () => { LL | let x = 0; | ^ ... @@ -52,7 +55,6 @@ LL | let x = 0; ... LL | trigger_unused_variables_macro!(); | --------------------------------- in this macro invocation - = note: this warning originates in the macro `trigger_unused_variables_macro` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 3 warnings emitted diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr index 5a426be83f861..d722ea7ee19e8 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/semicolon-in-expressions-from-macros.stderr @@ -1,6 +1,8 @@ warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -16,11 +18,12 @@ note: the lint level is defined here | LL | #![warn(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -29,7 +32,6 @@ LL | let _ = foo!(warn_in_expr); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unused attribute `allow` --> $DIR/semicolon-in-expressions-from-macros.rs:50:13 @@ -47,6 +49,8 @@ LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_ warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -55,7 +59,6 @@ LL | let _ = #[allow(semicolon_in_expressions_from_macros)] foo!(allow_does_ | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 4 warnings emitted @@ -63,6 +66,8 @@ Future incompatibility report: Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -73,12 +78,13 @@ LL | foo!(first) = note: to ignore the value produced by the macro, add a semicolon after the invocation of `foo` = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -87,12 +93,13 @@ LL | let _ = foo!(second); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -101,12 +108,13 @@ LL | let _ = foo!(third); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -115,12 +123,13 @@ LL | let _ = foo!(fourth); | = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -136,12 +145,13 @@ note: the lint level is defined here | LL | #![warn(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -155,12 +165,13 @@ note: the lint level is defined here | LL | #![warn(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) Future breakage diagnostic: warning: trailing semicolon in macro used in expression position --> $DIR/semicolon-in-expressions-from-macros.rs:9:13 | +LL | macro_rules! foo { +LL | ($val:ident) => { LL | true; | ^ ... @@ -174,5 +185,4 @@ note: the lint level is defined here | LL | #![warn(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr index 9506d702f51f1..bb856fd0a1d45 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/warn-semicolon-in-expressions-from-macros.stderr @@ -1,6 +1,8 @@ error: trailing semicolon in macro used in expression position --> $DIR/warn-semicolon-in-expressions-from-macros.rs:5:13 | +LL | macro_rules! foo { +LL | () => { LL | true; | ^ ... @@ -10,7 +12,6 @@ LL | _ => foo!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error @@ -18,6 +19,8 @@ Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position --> $DIR/warn-semicolon-in-expressions-from-macros.rs:5:13 | +LL | macro_rules! foo { +LL | () => { LL | true; | ^ ... @@ -27,5 +30,4 @@ LL | _ => foo!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/lint/static-mut-refs.e2021.stderr b/tests/ui/lint/static-mut-refs.e2021.stderr index e616ba0aa4b28..9d12c7434b20c 100644 --- a/tests/ui/lint/static-mut-refs.e2021.stderr +++ b/tests/ui/lint/static-mut-refs.e2021.stderr @@ -133,6 +133,8 @@ LL | let ref _v = A.value; warning: creating a mutable reference to mutable static --> $DIR/static-mut-refs.rs:14:14 | +LL | macro_rules! bar { +LL | ($x:expr) => { LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static ... @@ -142,7 +144,6 @@ LL | let _x = bar!(FOO); = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives = help: use a type that relies on "interior mutability" instead; to read more on this, visit = note: for more information, see - = note: this warning originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 12 warnings emitted diff --git a/tests/ui/lint/static-mut-refs.e2024.stderr b/tests/ui/lint/static-mut-refs.e2024.stderr index a8985fc8a1763..fa59f92d861aa 100644 --- a/tests/ui/lint/static-mut-refs.e2024.stderr +++ b/tests/ui/lint/static-mut-refs.e2024.stderr @@ -133,6 +133,8 @@ LL | let ref _v = A.value; error: creating a mutable reference to mutable static --> $DIR/static-mut-refs.rs:14:14 | +LL | macro_rules! bar { +LL | ($x:expr) => { LL | &mut ($x.0) | ^^^^^^ mutable reference to mutable static ... @@ -142,7 +144,6 @@ LL | let _x = bar!(FOO); = note: mutable references to mutable statics are dangerous; it's undefined behavior if any other pointer to the static is used or if any other reference is created for the static while the mutable reference lives = help: use a type that relies on "interior mutability" instead; to read more on this, visit = note: for more information, see - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr index 5173ff1f0264d..34b48a1fbb5b0 100644 --- a/tests/ui/lint/unreachable_pub.stderr +++ b/tests/ui/lint/unreachable_pub.stderr @@ -114,6 +114,7 @@ LL | pub type Oxygen = bool; warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:44:47 | +LL | macro_rules! define_empty_struct_with_visibility { LL | ($visibility: vis, $name: ident) => { $visibility struct $name {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -124,7 +125,6 @@ LL | define_empty_struct_with_visibility!(pub, Fluorine); | in this macro invocation | = help: or consider exporting it for use by other crates - = note: this warning originates in the macro `define_empty_struct_with_visibility` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unreachable `pub` item --> $DIR/unreachable_pub.rs:50:9 diff --git a/tests/ui/lint/unsafe_code/lint-global-asm-as-unsafe.stderr b/tests/ui/lint/unsafe_code/lint-global-asm-as-unsafe.stderr index deb67a174f185..d5cb744babd31 100644 --- a/tests/ui/lint/unsafe_code/lint-global-asm-as-unsafe.stderr +++ b/tests/ui/lint/unsafe_code/lint-global-asm-as-unsafe.stderr @@ -14,6 +14,8 @@ LL | #![deny(unsafe_code)] error: usage of `core::arch::global_asm` --> $DIR/lint-global-asm-as-unsafe.rs:13:9 | +LL | macro_rules! unsafe_in_macro { +LL | () => { LL | global_asm!(""); | ^^^^^^^^^^^^^^^ ... @@ -21,7 +23,6 @@ LL | unsafe_in_macro!(); | ------------------ in this macro invocation | = note: using this macro is unsafe even though it does not need an `unsafe` block - = note: this error originates in the macro `unsafe_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/lint/unused-visibilities.stderr b/tests/ui/lint/unused-visibilities.stderr index e5ff2a7fcae8d..ddf3015ecf0c7 100644 --- a/tests/ui/lint/unused-visibilities.stderr +++ b/tests/ui/lint/unused-visibilities.stderr @@ -22,6 +22,8 @@ LL | pub(self) const _: () = {}; warning: visibility qualifiers have no effect on `const _` declarations --> $DIR/unused-visibilities.rs:14:9 | +LL | macro_rules! foo { +LL | () => { LL | pub const _: () = {}; | ^^^ help: remove the qualifier ... @@ -29,7 +31,6 @@ LL | foo!(); | ------ in this macro invocation | = note: `const _` does not declare a name, so there is nothing for the qualifier to apply to - = note: this warning originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 3 warnings emitted diff --git a/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr b/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr index b4a6871713c06..887fbf18fd100 100644 --- a/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr +++ b/tests/ui/lint/unused/issue-117284-arg-in-macro.stderr @@ -1,6 +1,8 @@ error: unused variable: `var` --> $DIR/issue-117284-arg-in-macro.rs:4:13 | +LL | macro_rules! make_var { +LL | ($struct:ident, $var:ident) => { LL | let $var = $struct.$var; | ^^^^ ... @@ -20,7 +22,6 @@ note: the lint level is defined here | LL | #![deny(unused_variables)] | ^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `make_var` (in Nightly builds, run with -Z macro-backtrace for more info) error: unused variable: `a` --> $DIR/issue-117284-arg-in-macro.rs:16:9 diff --git a/tests/ui/lint/unused/must-use-macros.stderr b/tests/ui/lint/unused/must-use-macros.stderr index 2ad174e10b501..c5e9de20595b1 100644 --- a/tests/ui/lint/unused/must-use-macros.stderr +++ b/tests/ui/lint/unused/must-use-macros.stderr @@ -1,6 +1,8 @@ warning: unused comparison that must be used --> $DIR/must-use-macros.rs:28:17 | +LL | macro_rules! cmp { +LL | ($a:ident, $b:ident) => { LL | $a == $b | ^^^^^^^^ the comparison produces a value ... @@ -12,7 +14,6 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ - = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `let _ = ...` to ignore the resulting value | LL | let _ = cmp!(a, b); @@ -21,13 +22,14 @@ LL | let _ = cmp!(a, b); warning: unused comparison that must be used --> $DIR/must-use-macros.rs:41:17 | +LL | macro_rules! cmp { +LL | ($a:expr, $b:expr) => { LL | $a == $b | ^^^^^^^^ the comparison produces a value ... LL | cmp!(1, 1); | ---------- in this macro invocation | - = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `let _ = ...` to ignore the resulting value | LL | let _ = cmp!(1, 1); diff --git a/tests/ui/lint/unused/unused-macros.stderr b/tests/ui/lint/unused/unused-macros.stderr index 50c80b61eb5be..8fb0cf4b98563 100644 --- a/tests/ui/lint/unused/unused-macros.stderr +++ b/tests/ui/lint/unused/unused-macros.stderr @@ -13,13 +13,13 @@ LL | #![deny(unused_macros)] error: unused macro definition: `m` --> $DIR/unused-macros.rs:13:22 | +LL | macro_rules! create_macro { +LL | () => { LL | macro_rules! m { | ^ ... LL | create_macro!(); | --------------- in this macro invocation - | - = note: this error originates in the macro `create_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: unused macro definition: `unused` --> $DIR/unused-macros.rs:26:18 diff --git a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr index b1390debec73b..69f4e0ca7f0bb 100644 --- a/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr +++ b/tests/ui/lint/unused/unused_parens/unused-parens-in-macro-issue-120642.stderr @@ -1,6 +1,8 @@ warning: unnecessary parentheses around pattern --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19 | +LL | macro_rules! unused_parens { +... LL | let (_t) = 1; | ^^^^ ... @@ -12,29 +14,28 @@ note: the lint level is defined here | LL | #![warn(unused_parens)] | ^^^^^^^^^^^^^ - = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unnecessary parentheses around type --> $DIR/unused-parens-in-macro-issue-120642.rs:23:18 | +LL | macro_rules! unused_parens { +... LL | <($($rest),*)>::bar() | ^^^^^^^^^^^^ ... LL | unused_parens!(T1, T2, T3); | -------------------------- in this macro invocation - | - = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) warning: unnecessary parentheses around pattern --> $DIR/unused-parens-in-macro-issue-120642.rs:26:19 | +LL | macro_rules! unused_parens { +... LL | let (_t) = 1; | ^^^^ ... LL | unused_parens!(T1, T2, T3); | -------------------------- in this macro invocation - | - = note: this warning originates in the macro `unused_parens` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 3 warnings emitted diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr index 4199ff62e2a30..1d51cce2013c9 100644 --- a/tests/ui/lint/wide_pointer_comparisons.stderr +++ b/tests/ui/lint/wide_pointer_comparisons.stderr @@ -722,6 +722,7 @@ LL + std::ptr::eq(*a, *b) warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:148:33 | +LL | macro_rules! cmp { LL | ($a:tt, $b:tt) => { $a == $b } | ^^^^^^^^ ... @@ -730,18 +731,17 @@ LL | cmp!(a, b); | = help: use explicit `std::ptr::eq` method to compare metadata and addresses = help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses - = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:157:39 | +LL | macro_rules! cmp { LL | ($a:ident, $b:ident) => { $a == $b } | ^^^^^^^^ ... LL | cmp!(a, b); | ---------- in this macro invocation | - = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses | LL - ($a:ident, $b:ident) => { $a == $b } @@ -751,6 +751,7 @@ LL + ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) } warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected --> $DIR/wide_pointer_comparisons.rs:167:37 | +LL | macro_rules! cmp { LL | ($a:expr, $b:expr) => { $a == $b } | ^^^^^^^^ ... @@ -759,7 +760,6 @@ LL | cmp!(&a, &b); | = help: use explicit `std::ptr::eq` method to compare metadata and addresses = help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses - = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 53 warnings emitted diff --git a/tests/ui/liveness/liveness-return-last-stmt-semi.stderr b/tests/ui/liveness/liveness-return-last-stmt-semi.stderr index de0843aa637f3..2b3c87e0b1869 100644 --- a/tests/ui/liveness/liveness-return-last-stmt-semi.stderr +++ b/tests/ui/liveness/liveness-return-last-stmt-semi.stderr @@ -34,8 +34,6 @@ LL | macro_rules! test { () => { fn foo() -> i32 { 1; } } } ... LL | test!(); | ------- in this macro invocation - | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr index 64e40ebdd7bdf..8c3451af7235f 100644 --- a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr +++ b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr @@ -37,6 +37,8 @@ LL | assert_eq!(buf, b"----"); error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30 | +LL | macro_rules! local_assert_ne { +... LL | if *left_val == *right_val { | ^^ no implementation for `[u8; 4] == &[u8; 4]` ... @@ -44,7 +46,6 @@ LL | local_assert_ne!(buf, b"----"); | ------------------------------ in this macro invocation | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` - = note: this error originates in the macro `local_assert_ne` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider dereferencing here | LL | if *left_val == **right_val { diff --git a/tests/ui/macros/attr-expr.stderr b/tests/ui/macros/attr-expr.stderr index eaad41c44fb9a..2cd707be3ce06 100644 --- a/tests/ui/macros/attr-expr.stderr +++ b/tests/ui/macros/attr-expr.stderr @@ -1,24 +1,24 @@ error: expected identifier, found metavariable --> $DIR/attr-expr.rs:3:11 | +LL | macro_rules! foo { +LL | ($e:expr) => { LL | #[$e] | ^^ expected identifier, found metavariable ... LL | foo!(inline); | ------------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable --> $DIR/attr-expr.rs:12:18 | +LL | macro_rules! bar { +LL | ($e:expr) => { LL | #[inline($e)] | ^^ ... LL | bar!(always); | ------------ in this macro invocation - | - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/best-failure.stderr b/tests/ui/macros/best-failure.stderr index 914ff7fd8207f..541ffae1ecf28 100644 --- a/tests/ui/macros/best-failure.stderr +++ b/tests/ui/macros/best-failure.stderr @@ -15,7 +15,6 @@ note: while trying to match meta-variable `$self:ident` | LL | (neg false, $self:ident) => { $self }; | ^^^^^^^^^^^ - = note: this error originates in the macro `number` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/cfg_attr-expr.stderr b/tests/ui/macros/cfg_attr-expr.stderr index cd1dcaec1ade8..19c24c32afb09 100644 --- a/tests/ui/macros/cfg_attr-expr.stderr +++ b/tests/ui/macros/cfg_attr-expr.stderr @@ -1,6 +1,8 @@ error: expected identifier, found metavariable --> $DIR/cfg_attr-expr.rs:3:26 | +LL | macro_rules! foo { +LL | ($e:expr) => { LL | #[cfg_attr(true, $e)] | ^^ expected identifier, found metavariable ... @@ -8,7 +10,6 @@ LL | foo!(inline); | ------------ in this macro invocation | = note: for more information, visit - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: must be of the form | LL - #[cfg_attr(true, $e)] diff --git a/tests/ui/macros/cross-crate-nested-macro-rules-span.stderr b/tests/ui/macros/cross-crate-nested-macro-rules-span.stderr index edf3d575b972d..5ed3932a8a841 100644 --- a/tests/ui/macros/cross-crate-nested-macro-rules-span.stderr +++ b/tests/ui/macros/cross-crate-nested-macro-rules-span.stderr @@ -9,13 +9,17 @@ LL | all_trigger_fields!(make_event_subscription); error[E0223]: ambiguous associated type --> $DIR/cross-crate-nested-macro-rules-span.rs:10:40 | -LL | pub struct EventSubscription($($channel::ReaderId),*); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | all_trigger_fields!(make_event_subscription); - | -------------------------------------------- in this macro invocation +LL | / macro_rules! make_event_subscription { +LL | | ($(( $field:ident, $ty:ident, $channel:ident )),*) => { +LL | | pub struct EventSubscription($($channel::ReaderId),*); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... | +LL | | } + | |_- this error originates in the macro `make_event_subscription` which comes from the expansion of the macro `all_trigger_fields` +LL | +LL | all_trigger_fields!(make_event_subscription); + | -------------------------------------------- in this macro invocation | - = note: this error originates in the macro `make_event_subscription` which comes from the expansion of the macro `all_trigger_fields` (in Nightly builds, run with -Z macro-backtrace for more info) help: if there were a trait named `Example` with associated type `ReaderId` implemented for `nested_macro_rules_definition::NotificationChannel`, you could use the fully-qualified path | LL - pub struct EventSubscription($($channel::ReaderId),*); diff --git a/tests/ui/macros/cross-file-errors.stderr b/tests/ui/macros/cross-file-errors.stderr index 70db7d5185eac..7a44fa5f0ad5c 100644 --- a/tests/ui/macros/cross-file-errors.stderr +++ b/tests/ui/macros/cross-file-errors.stderr @@ -1,6 +1,8 @@ error: in expressions, `_` can only be used on the left-hand side of an assignment --> $DIR/underscore.rs:5:9 | +LL | macro_rules! underscore { +LL | () => ( LL | _ | ^ `_` not allowed here | @@ -8,8 +10,6 @@ LL | _ | LL | underscore!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `underscore` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/deref-raw-pointer-issue-158158.stderr b/tests/ui/macros/deref-raw-pointer-issue-158158.stderr index d93ac0eac1638..513e082d32b5b 100644 --- a/tests/ui/macros/deref-raw-pointer-issue-158158.stderr +++ b/tests/ui/macros/deref-raw-pointer-issue-158158.stderr @@ -1,13 +1,13 @@ error[E0609]: no field `val` on type `*mut Demo` --> $DIR/deref-raw-pointer-issue-158158.rs:13:21 | +LL | macro_rules! get_value { +LL | ($d:expr) => { LL | as_ptr!($d).val | ^^^ unknown field ... LL | let _ = get_value!(d); | ------------- in this macro invocation - | - = note: this error originates in the macro `get_value` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/derive-in-eager-expansion-hang.stderr b/tests/ui/macros/derive-in-eager-expansion-hang.stderr index b61ef2a9babe8..c8232143688b5 100644 --- a/tests/ui/macros/derive-in-eager-expansion-hang.stderr +++ b/tests/ui/macros/derive-in-eager-expansion-hang.stderr @@ -1,6 +1,7 @@ error: format argument must be a string literal --> $DIR/derive-in-eager-expansion-hang.rs:4:5 | +LL | macro_rules! hang { () => { LL | / { LL | | #[derive(Clone)] LL | | struct S; @@ -11,7 +12,6 @@ LL | | } LL | format_args!(hang!()); | ------- in this macro invocation | - = note: this error originates in the macro `hang` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might be missing a string literal to format with | LL | format_args!("{}", hang!()); diff --git a/tests/ui/macros/expand-full-no-resolution.stderr b/tests/ui/macros/expand-full-no-resolution.stderr index 42e79bb122fb7..2892f80b0d461 100644 --- a/tests/ui/macros/expand-full-no-resolution.stderr +++ b/tests/ui/macros/expand-full-no-resolution.stderr @@ -1,6 +1,8 @@ error: cannot find macro `a` in this scope --> $DIR/expand-full-no-resolution.rs:18:18 | +LL | macro_rules! wrap { +... LL | format_args!(a!()); | ^ | @@ -12,7 +14,6 @@ LL | macro_rules! _a { ... LL | wrap!(); | ------- in this macro invocation - = note: this error originates in the macro `wrap` (in Nightly builds, run with -Z macro-backtrace for more info) help: the leading underscore in `_a` marks it as unused, consider renaming it to `a` | LL - macro_rules! _a { @@ -22,6 +23,8 @@ LL + macro_rules! a { error: cannot find macro `a` in this scope --> $DIR/expand-full-no-resolution.rs:19:10 | +LL | macro_rules! wrap { +... LL | env!(a!()); | ^ | @@ -33,7 +36,6 @@ LL | macro_rules! _a { ... LL | wrap!(); | ------- in this macro invocation - = note: this error originates in the macro `wrap` (in Nightly builds, run with -Z macro-backtrace for more info) help: the leading underscore in `_a` marks it as unused, consider renaming it to `a` | LL - macro_rules! _a { diff --git a/tests/ui/macros/invalid-assignment-in-macro-26093.stderr b/tests/ui/macros/invalid-assignment-in-macro-26093.stderr index 99f188c718361..ad347a2544a2c 100644 --- a/tests/ui/macros/invalid-assignment-in-macro-26093.stderr +++ b/tests/ui/macros/invalid-assignment-in-macro-26093.stderr @@ -1,6 +1,8 @@ error[E0070]: invalid left-hand side of assignment --> $DIR/invalid-assignment-in-macro-26093.rs:4:16 | +LL | macro_rules! not_a_place { +LL | ($thing:expr) => { LL | $thing = 42; | ^ ... @@ -9,12 +11,12 @@ LL | not_a_place!(99); | | | | | cannot assign to this expression | in this macro invocation - | - = note: this error originates in the macro `not_a_place` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0067]: invalid left-hand side of assignment --> $DIR/invalid-assignment-in-macro-26093.rs:6:16 | +LL | macro_rules! not_a_place { +... LL | $thing += 42; | ^^ ... @@ -23,8 +25,6 @@ LL | not_a_place!(99); | | | | | cannot assign to this expression | in this macro invocation - | - = note: this error originates in the macro `not_a_place` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/issue-109237.stderr b/tests/ui/macros/issue-109237.stderr index 9d25420af2561..3ba1158655947 100644 --- a/tests/ui/macros/issue-109237.stderr +++ b/tests/ui/macros/issue-109237.stderr @@ -1,6 +1,7 @@ error: expected expression, found `;` --> $DIR/issue-109237.rs:2:12 | +LL | macro_rules! statement { LL | () => {;}; | ^ expected expression ... @@ -8,7 +9,6 @@ LL | let _ = statement!(); | ------------ in this macro invocation | = note: the macro call doesn't expand to an expression, but it can expand to a statement - = note: this error originates in the macro `statement` (in Nightly builds, run with -Z macro-backtrace for more info) help: surround the macro invocation with `{}` to interpret the expansion as a statement | LL - let _ = statement!(); diff --git a/tests/ui/macros/issue-118786.stderr b/tests/ui/macros/issue-118786.stderr index 02b26e5a1f31b..3ffa5d67b0a16 100644 --- a/tests/ui/macros/issue-118786.stderr +++ b/tests/ui/macros/issue-118786.stderr @@ -24,6 +24,8 @@ LL | make_macro!((meow)); error: cannot find macro `macro_rules` in this scope --> $DIR/issue-118786.rs:10:9 | +LL | macro_rules! make_macro { +LL | ($macro_name:tt) => { LL | macro_rules! $macro_name { | ^^^^^^^^^^^ ... @@ -38,7 +40,6 @@ LL | macro_rules! $macro_name { ... LL | make_macro!((meow)); | ------------------- in this macro invocation - = note: this error originates in the macro `make_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/macros/issue-16098.stderr b/tests/ui/macros/issue-16098.stderr index a7249981648c0..ca5a597293c87 100644 --- a/tests/ui/macros/issue-16098.stderr +++ b/tests/ui/macros/issue-16098.stderr @@ -1,6 +1,8 @@ error: recursion limit reached while expanding `prob1!` --> $DIR/issue-16098.rs:7:18 | +LL | macro_rules! prob1 { +... LL | $n + prob1!($n - 1); | ^^^^^^^^^^^^^^ ... @@ -8,7 +10,6 @@ LL | println!("Problem 1: {}", prob1!(1000)); | ------------ in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_16098`) - = note: this error originates in the macro `prob1` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-25385.stderr b/tests/ui/macros/issue-25385.stderr index 39dbdd753a6ff..4f21a4e17dbbc 100644 --- a/tests/ui/macros/issue-25385.stderr +++ b/tests/ui/macros/issue-25385.stderr @@ -1,13 +1,12 @@ error[E0599]: no method named `foo` found for type `i32` in the current scope --> $DIR/issue-25385.rs:2:23 | +LL | macro_rules! foo { LL | ($e:expr) => { $e.foo() } | ^^^ method not found in `i32` ... LL | foo!(a); | ------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0599]: no method named `foo` found for type `i32` in the current scope --> $DIR/issue-25385.rs:10:15 diff --git a/tests/ui/macros/issue-29084.stderr b/tests/ui/macros/issue-29084.stderr index 6e7474c5b3f74..de64f46747059 100644 --- a/tests/ui/macros/issue-29084.stderr +++ b/tests/ui/macros/issue-29084.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-29084.rs:6:13 | +LL | macro_rules! foo { +... LL | bar(&mut $d); | --- ^^^^^^^ expected `u8`, found `&mut u8` | | @@ -17,7 +19,6 @@ LL | fn bar(d: u8) { } ... LL | foo!(0u8); | --------- in this macro invocation - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr index 00139662d619b..9be3c6f88a67b 100644 --- a/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr +++ b/tests/ui/macros/issue-34421-mac-expr-bad-stmt-good-add-semi.stderr @@ -1,6 +1,8 @@ error: expected expression, found keyword `struct` --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 | +LL | macro_rules! make_item { +LL | ($a:ident) => { LL | struct $a; | ^^^^^^ expected expression ... @@ -8,7 +10,6 @@ LL | make_item!(A) | ------------- in this macro invocation | = note: the macro call doesn't expand to an expression, but it can expand to a statement - = note: this error originates in the macro `make_item` (in Nightly builds, run with -Z macro-backtrace for more info) help: add `;` to interpret the expansion as a statement | LL | make_item!(A); @@ -17,6 +18,8 @@ LL | make_item!(A); error: expected expression, found keyword `struct` --> $DIR/issue-34421-mac-expr-bad-stmt-good-add-semi.rs:3:9 | +LL | macro_rules! make_item { +LL | ($a:ident) => { LL | struct $a; | ^^^^^^ expected expression ... @@ -24,7 +27,6 @@ LL | make_item!(B) | ------------- in this macro invocation | = note: the macro call doesn't expand to an expression, but it can expand to a statement - = note: this error originates in the macro `make_item` (in Nightly builds, run with -Z macro-backtrace for more info) help: add `;` to interpret the expansion as a statement | LL | make_item!(B); diff --git a/tests/ui/macros/issue-42954.stderr b/tests/ui/macros/issue-42954.stderr index d5a8a117f9a37..111376d8ecdd1 100644 --- a/tests/ui/macros/issue-42954.stderr +++ b/tests/ui/macros/issue-42954.stderr @@ -1,6 +1,8 @@ error: `<` is interpreted as a start of generic arguments for `u32`, not a comparison --> $DIR/issue-42954.rs:7:19 | +LL | macro_rules! is_plainly_printable { +LL | ($i: ident) => { LL | $i as u32 < 0 | ^ - interpreted as generic arguments | | @@ -9,7 +11,6 @@ LL | $i as u32 < 0 LL | is_plainly_printable!(c); | ------------------------ in this macro invocation | - = note: this error originates in the macro `is_plainly_printable` (in Nightly builds, run with -Z macro-backtrace for more info) help: try comparing the cast value | LL | ($i as u32) < 0 diff --git a/tests/ui/macros/issue-51848.stderr b/tests/ui/macros/issue-51848.stderr index 30b64113d731e..fb9e28b57c586 100644 --- a/tests/ui/macros/issue-51848.stderr +++ b/tests/ui/macros/issue-51848.stderr @@ -1,6 +1,8 @@ error: invalid format string: expected `}` but string was terminated --> $DIR/issue-51848.rs:6:20 | +LL | macro_rules! macro_with_error { +LL | ( ) => { LL | println!("{"); | -^ expected `}` in format string | | @@ -10,7 +12,6 @@ LL | macro_with_error!(); | ------------------- in this macro invocation | = note: if you intended to print `{`, you can escape it using `{{` - = note: this error originates in the macro `macro_with_error` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found --> $DIR/issue-51848.rs:18:15 diff --git a/tests/ui/macros/issue-6596-1.stderr b/tests/ui/macros/issue-6596-1.stderr index 92998abfa68cf..57eb39f8b78bf 100644 --- a/tests/ui/macros/issue-6596-1.stderr +++ b/tests/ui/macros/issue-6596-1.stderr @@ -1,6 +1,8 @@ error: cannot find macro parameter `$nonexistent` in this scope --> $DIR/issue-6596-1.rs:3:9 | +LL | macro_rules! e { +LL | ($inp:ident) => ( LL | $nonexistent | ^^^^^^^^^^^^ not found in this scope ... @@ -8,18 +10,17 @@ LL | e!(foo); | ------- in this macro invocation | = note: available metavariable names are: $inp - = note: this error originates in the macro `e` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot find macro parameter `$x` in this scope --> $DIR/issue-6596-1.rs:10:9 | +LL | macro_rules! m { +LL | () => ( LL | $x | ^^ not found in this scope ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/issue-6596-2.stderr b/tests/ui/macros/issue-6596-2.stderr index e6281eb54270a..3c47269076828 100644 --- a/tests/ui/macros/issue-6596-2.stderr +++ b/tests/ui/macros/issue-6596-2.stderr @@ -1,13 +1,13 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `$` --> $DIR/issue-6596-2.rs:3:16 | +LL | macro_rules! g { +LL | ($inp:ident) => ( LL | { $inp $nonexistent } | ^^^^^^^^^^^^ expected one of 8 possible tokens ... LL | g!(foo); | ------- in this macro invocation - | - = note: this error originates in the macro `g` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr index 7c745040640ce..400c040cc3161 100644 --- a/tests/ui/macros/issue-78325-inconsistent-resolution.stderr +++ b/tests/ui/macros/issue-78325-inconsistent-resolution.stderr @@ -1,17 +1,19 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/issue-78325-inconsistent-resolution.rs:5:9 | +LL | macro_rules! define_other_core { +LL | ( ) => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `core` is ambiguous --> $DIR/issue-78325-inconsistent-resolution.rs:11:5 | +LL | macro_rules! define_other_core { +... LL | core::panic!(); | ^^^^ ambiguous name | @@ -26,11 +28,12 @@ LL | extern crate std as core; LL | define_other_core!(); | -------------------- in this macro invocation = help: use `crate::core` to refer to this crate unambiguously - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `core` is ambiguous --> $DIR/issue-78325-inconsistent-resolution.rs:12:7 | +LL | macro_rules! define_other_core { +... LL | ::core::panic!(); | ^^^^ ambiguous name | @@ -44,7 +47,6 @@ LL | extern crate std as core; ... LL | define_other_core!(); | -------------------- in this macro invocation - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/macros/issue-84195-lint-anon-const.stderr b/tests/ui/macros/issue-84195-lint-anon-const.stderr index d9042adfc375a..e0b84734e8a73 100644 --- a/tests/ui/macros/issue-84195-lint-anon-const.stderr +++ b/tests/ui/macros/issue-84195-lint-anon-const.stderr @@ -1,6 +1,7 @@ error: trailing semicolon in macro used in expression position --> $DIR/issue-84195-lint-anon-const.rs:8:14 | +LL | macro_rules! len { LL | () => { 0; }; | ^ ... @@ -14,7 +15,6 @@ note: the lint level is defined here | LL | #![deny(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error @@ -22,6 +22,7 @@ Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position --> $DIR/issue-84195-lint-anon-const.rs:8:14 | +LL | macro_rules! len { LL | () => { 0; }; | ^ ... @@ -35,5 +36,4 @@ note: the lint level is defined here | LL | #![deny(semicolon_in_expressions_from_macros)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `len` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr index c395e0c9100d3..7ed69037c8c82 100644 --- a/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr +++ b/tests/ui/macros/issue-84632-eager-expansion-recursion-limit.stderr @@ -1,6 +1,8 @@ error: recursion limit reached while expanding `concat!` --> $DIR/issue-84632-eager-expansion-recursion-limit.rs:8:28 | +LL | macro_rules! a { +... LL | (A, $($A:ident),*) => (concat!("", a!($($A),*))) | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -8,7 +10,6 @@ LL | a!(A, A, A, A, A, A, A, A, A, A, A); | ----------------------------------- in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "30"]` attribute to your crate (`issue_84632_eager_expansion_recursion_limit`) - = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/lint-trailing-macro-call.stderr b/tests/ui/macros/lint-trailing-macro-call.stderr index 1ff8c0c6f66f2..fb2eaa42b1eec 100644 --- a/tests/ui/macros/lint-trailing-macro-call.stderr +++ b/tests/ui/macros/lint-trailing-macro-call.stderr @@ -1,6 +1,8 @@ error: trailing semicolon in macro used in expression position --> $DIR/lint-trailing-macro-call.rs:7:25 | +LL | macro_rules! expand_it { +LL | () => { LL | #[cfg(false)] 25; | ^ ... @@ -12,7 +14,6 @@ LL | expand_it!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error @@ -20,6 +21,8 @@ Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position --> $DIR/lint-trailing-macro-call.rs:7:25 | +LL | macro_rules! expand_it { +LL | () => { LL | #[cfg(false)] 25; | ^ ... @@ -31,5 +34,4 @@ LL | expand_it!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `expand_it` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-adjacent-ident-on-token.stderr b/tests/ui/macros/macro-adjacent-ident-on-token.stderr index b13a3d45828d3..0b2c562c8ecc8 100644 --- a/tests/ui/macros/macro-adjacent-ident-on-token.stderr +++ b/tests/ui/macros/macro-adjacent-ident-on-token.stderr @@ -1,6 +1,8 @@ error: expected `{`, found identifier `foo` --> $DIR/macro-adjacent-ident-on-token.rs:6:21 | +LL | macro_rules! get_opt { +LL | ($tgt:expr, $field:ident) => { LL | if $tgt.has_$field() {} | ^^^^^^ expected `{` ... @@ -15,7 +17,6 @@ LL | if $tgt.has_$field() {} ... LL | get_opt!(bar, foo); | ------------------ in this macro invocation - = note: this error originates in the macro `get_opt` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to write a method call | LL | if $tgt.has_.$field() {} diff --git a/tests/ui/macros/macro-backtrace-complex.default.stderr b/tests/ui/macros/macro-backtrace-complex.default.stderr index 6aae85c1501ad..48a4bf7eb64a9 100644 --- a/tests/ui/macros/macro-backtrace-complex.default.stderr +++ b/tests/ui/macros/macro-backtrace-complex.default.stderr @@ -1,35 +1,36 @@ error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/macro-backtrace-complex.rs:12:20 | +LL | macro_rules! pong { LL | () => { syntax error }; | ^^^^^ expected one of 8 possible tokens ... LL | pong!(); | ------- in this macro invocation - | - = note: this error originates in the macro `pong` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/macro-backtrace-complex.rs:12:20 | -LL | () => { syntax error }; - | ^^^^^ expected one of 8 possible tokens +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- this error originates in the macro `pong` which comes from the expansion of the macro `ping` ... -LL | ping!(); - | ------- in this macro invocation - | - = note: this error originates in the macro `pong` which comes from the expansion of the macro `ping` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | ping!(); + | ------- in this macro invocation error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `error` --> $DIR/macro-backtrace-complex.rs:12:20 | -LL | () => { syntax error }; - | ^^^^^ expected one of 8 possible tokens +LL | / macro_rules! pong { +LL | | () => { syntax error }; + | | ^^^^^ expected one of 8 possible tokens +LL | | } + | |_- this error originates in the macro `pong` which comes from the expansion of the macro `deep` ... -LL | deep!(); - | ------- in this macro invocation - | - = note: this error originates in the macro `pong` which comes from the expansion of the macro `deep` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | deep!(); + | ------- in this macro invocation error: aborting due to 3 previous errors diff --git a/tests/ui/macros/macro-backtrace-invalid-internals.stderr b/tests/ui/macros/macro-backtrace-invalid-internals.stderr index 836098bd9c04e..cf0ec52980a59 100644 --- a/tests/ui/macros/macro-backtrace-invalid-internals.stderr +++ b/tests/ui/macros/macro-backtrace-invalid-internals.stderr @@ -1,46 +1,47 @@ error[E0599]: no method named `fake` found for type `{integer}` in the current scope --> $DIR/macro-backtrace-invalid-internals.rs:5:13 | +LL | macro_rules! fake_method_stmt { +LL | () => { LL | 1.fake() | ^^^^ method not found in `{integer}` ... LL | fake_method_stmt!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `fake_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:11:13 | +LL | macro_rules! fake_field_stmt { +LL | () => { LL | 1.fake | ^^^^ ... LL | fake_field_stmt!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `fake_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:17:15 | +LL | macro_rules! fake_anon_field_stmt { +LL | () => { LL | (1).0 | ^ ... LL | fake_anon_field_stmt!(); | ----------------------- in this macro invocation - | - = note: this error originates in the macro `fake_anon_field_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` --> $DIR/macro-backtrace-invalid-internals.rs:41:15 | +LL | macro_rules! real_method_stmt { +LL | () => { LL | 2.0.neg() | ^^^ ... LL | real_method_stmt!(); | ------------------- in this macro invocation | - = note: this error originates in the macro `real_method_stmt` (in Nightly builds, run with -Z macro-backtrace for more info) help: you must specify a concrete type for this numeric value, like `f32` | LL | 2.0_f32.neg() @@ -49,46 +50,47 @@ LL | 2.0_f32.neg() error[E0599]: no method named `fake` found for type `{integer}` in the current scope --> $DIR/macro-backtrace-invalid-internals.rs:23:13 | +LL | macro_rules! fake_method_expr { +LL | () => { LL | 1.fake() | ^^^^ method not found in `{integer}` ... LL | let _ = fake_method_expr!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `fake_method_expr` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:29:13 | +LL | macro_rules! fake_field_expr { +LL | () => { LL | 1.fake | ^^^^ ... LL | let _ = fake_field_expr!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `fake_field_expr` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0610]: `{integer}` is a primitive type and therefore doesn't have fields --> $DIR/macro-backtrace-invalid-internals.rs:35:15 | +LL | macro_rules! fake_anon_field_expr { +LL | () => { LL | (1).0 | ^ ... LL | let _ = fake_anon_field_expr!(); | ----------------------- in this macro invocation - | - = note: this error originates in the macro `fake_anon_field_expr` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0689]: can't call method `neg` on ambiguous numeric type `{float}` --> $DIR/macro-backtrace-invalid-internals.rs:47:15 | +LL | macro_rules! real_method_expr { +LL | () => { LL | 2.0.neg() | ^^^ ... LL | let _ = real_method_expr!(); | ------------------- in this macro invocation | - = note: this error originates in the macro `real_method_expr` (in Nightly builds, run with -Z macro-backtrace for more info) help: you must specify a concrete type for this numeric value, like `f32` | LL | 2.0_f32.neg() diff --git a/tests/ui/macros/macro-backtrace-nested.stderr b/tests/ui/macros/macro-backtrace-nested.stderr index dadedfbe8f671..ad3969350d8a1 100644 --- a/tests/ui/macros/macro-backtrace-nested.stderr +++ b/tests/ui/macros/macro-backtrace-nested.stderr @@ -1,24 +1,28 @@ error[E0425]: cannot find value `fake` in this scope --> $DIR/macro-backtrace-nested.rs:5:12 | -LL | () => (fake) - | ^^^^ not found in this scope +LL | / macro_rules! nested_expr { +LL | | () => (fake) + | | ^^^^ not found in this scope +LL | | +LL | | } + | |_- this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr` ... -LL | 1 + call_nested_expr!(); - | ------------------- in this macro invocation - | - = note: this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | 1 + call_nested_expr!(); + | ------------------- in this macro invocation error[E0425]: cannot find value `fake` in this scope --> $DIR/macro-backtrace-nested.rs:5:12 | -LL | () => (fake) - | ^^^^ not found in this scope +LL | / macro_rules! nested_expr { +LL | | () => (fake) + | | ^^^^ not found in this scope +LL | | +LL | | } + | |_- this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr_sum` ... -LL | call_nested_expr_sum!(); - | ----------------------- in this macro invocation - | - = note: this error originates in the macro `nested_expr` which comes from the expansion of the macro `call_nested_expr_sum` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | call_nested_expr_sum!(); + | ----------------------- in this macro invocation error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-context.stderr b/tests/ui/macros/macro-context.stderr index f468f77ba657c..d8d17ab674d3a 100644 --- a/tests/ui/macros/macro-context.stderr +++ b/tests/ui/macros/macro-context.stderr @@ -34,24 +34,23 @@ LL | m!() => {} error: expected expression, found reserved keyword `typeof` --> $DIR/macro-context.rs:3:17 | +LL | macro_rules! m { LL | () => ( i ; typeof ); | ^^^^^^ expected expression ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `i` in this scope --> $DIR/macro-context.rs:3:13 | +LL | macro_rules! m { LL | () => ( i ; typeof ); | ^ not found in this scope ... LL | let a: m!(); | ---- in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: a builtin type with a similar name exists | LL | () => ( i8 ; typeof ); @@ -60,17 +59,17 @@ LL | () => ( i8 ; typeof ); error[E0425]: cannot find value `i` in this scope --> $DIR/macro-context.rs:3:13 | +LL | macro_rules! m { LL | () => ( i ; typeof ); | ^ not found in this scope ... LL | let i = m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: trailing semicolon in macro used in expression position --> $DIR/macro-context.rs:3:15 | +LL | macro_rules! m { LL | () => ( i ; typeof ); | ^ ... @@ -80,7 +79,6 @@ LL | let i = m!(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 7 previous errors @@ -89,6 +87,7 @@ Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position --> $DIR/macro-context.rs:3:15 | +LL | macro_rules! m { LL | () => ( i ; typeof ); | ^ ... @@ -98,5 +97,4 @@ LL | let i = m!(); = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-expansion-empty-span-147408.stderr b/tests/ui/macros/macro-expansion-empty-span-147408.stderr index 97eab0dc7233f..c64be0c436cdf 100644 --- a/tests/ui/macros/macro-expansion-empty-span-147408.stderr +++ b/tests/ui/macros/macro-expansion-empty-span-147408.stderr @@ -21,6 +21,8 @@ LL + for _ in dbg!([1, 2]) {} warning: this method call resolves to `<&[T; N] as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to `<[T; N] as IntoIterator>::into_iter` in Rust 2021 --> $DIR/macro-expansion-empty-span-147408.rs:11:16 | +LL | macro_rules! mac { +... LL | $e.into_iter() | ^^^^^^^^^ help: use `.iter()` instead of `.into_iter()` to avoid ambiguity: `iter` ... @@ -29,7 +31,6 @@ LL | for _ in mac!(into_iter [1, 2]) {} | = warning: this changes meaning in Rust 2021 = note: for more information, see - = note: this warning originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) warning: 2 warnings emitted diff --git a/tests/ui/macros/macro-guard-matcher-recursion.stderr b/tests/ui/macros/macro-guard-matcher-recursion.stderr index e12b2de765100..96f0d07904d87 100644 --- a/tests/ui/macros/macro-guard-matcher-recursion.stderr +++ b/tests/ui/macros/macro-guard-matcher-recursion.stderr @@ -1,6 +1,8 @@ error: recursion limit reached while expanding `m!` --> $DIR/macro-guard-matcher-recursion.rs:6:13 | +LL | macro_rules! m { +LL | ($g : guard) => { LL | m!($g) | ^^^^^^ ... @@ -8,7 +10,6 @@ LL | m!(if x) | -------- in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`macro_guard_matcher_recursion`) - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-hygiene-help-issue-148580.stderr b/tests/ui/macros/macro-hygiene-help-issue-148580.stderr index 56e021078855e..7af1520c7ce90 100644 --- a/tests/ui/macros/macro-hygiene-help-issue-148580.stderr +++ b/tests/ui/macros/macro-hygiene-help-issue-148580.stderr @@ -12,7 +12,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | let it = (); | ^^ - = note: this error originates in the macro `print_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-hygiene-help-issue-149604.stderr b/tests/ui/macros/macro-hygiene-help-issue-149604.stderr index 6df7c009e668b..13e2256c6c23c 100644 --- a/tests/ui/macros/macro-hygiene-help-issue-149604.stderr +++ b/tests/ui/macros/macro-hygiene-help-issue-149604.stderr @@ -1,6 +1,8 @@ error[E0425]: cannot find value `it` in this scope --> $DIR/macro-hygiene-help-issue-149604.rs:8:14 | +LL | macro_rules! let_it { {} => { let it = (); } } +... LL | let () = it; | ^^ not found in this scope | @@ -12,7 +14,6 @@ LL | macro_rules! let_it { {} => { let it = (); } } ... LL | let_it!(); | --------- in this macro invocation - = note: this error originates in the macro `let_it` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `it` in this scope --> $DIR/macro-hygiene-help-issue-149604.rs:3:50 @@ -31,7 +32,6 @@ LL | macro_rules! let_it { {} => { let it = (); } } ... LL | let_it!(); | --------- in this macro invocation - = note: this error originates in the macro `print_it` which comes from the expansion of the macro `let_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-hygiene-scope-15167.stderr b/tests/ui/macros/macro-hygiene-scope-15167.stderr index dbb0514ba1aab..cff1eb71e93fd 100644 --- a/tests/ui/macros/macro-hygiene-scope-15167.stderr +++ b/tests/ui/macros/macro-hygiene-scope-15167.stderr @@ -12,7 +12,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | for n in 0..1 { | ^ - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `n` in this scope --> $DIR/macro-hygiene-scope-15167.rs:6:25 @@ -28,7 +27,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | if let Some(n) = None { | ^ - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `n` in this scope --> $DIR/macro-hygiene-scope-15167.rs:6:25 @@ -44,7 +42,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | } else if let Some(n) = None { | ^ - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `n` in this scope --> $DIR/macro-hygiene-scope-15167.rs:6:25 @@ -60,7 +57,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | while let Some(n) = None { | ^ - = note: this error originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/macros/macro-in-expression-context.stderr b/tests/ui/macros/macro-in-expression-context.stderr index 27d9490809a99..3bdef604ceda4 100644 --- a/tests/ui/macros/macro-in-expression-context.stderr +++ b/tests/ui/macros/macro-in-expression-context.stderr @@ -16,6 +16,8 @@ LL | foo!(); error: trailing semicolon in macro used in expression position --> $DIR/macro-in-expression-context.rs:5:29 | +LL | macro_rules! foo { +LL | () => { LL | assert_eq!("A", "A"); | ^ ... @@ -27,7 +29,6 @@ LL | foo!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors @@ -35,6 +36,8 @@ Future incompatibility report: Future breakage diagnostic: error: trailing semicolon in macro used in expression position --> $DIR/macro-in-expression-context.rs:5:29 | +LL | macro_rules! foo { +LL | () => { LL | assert_eq!("A", "A"); | ^ ... @@ -46,5 +49,4 @@ LL | foo!() = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #79813 = note: `#[deny(semicolon_in_expressions_from_macros)]` (part of `#[deny(future_incompatible)]`) on by default - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr index bc24a15861295..3dc6ef6132d2a 100644 --- a/tests/ui/macros/macro-interpolation.stderr +++ b/tests/ui/macros/macro-interpolation.stderr @@ -1,6 +1,8 @@ error: expected identifier, found metavariable --> $DIR/macro-interpolation.rs:21:19 | +LL | macro_rules! qpath { +... LL | <$type as $trait>::$name | ^^^^^^ expected identifier, found metavariable ... @@ -9,8 +11,6 @@ LL | let _: qpath!(ty, ::Owned); | | | this macro call doesn't expand to a type | in this macro invocation - | - = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr b/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr index e95032dd2478d..1e3f18ae0fe68 100644 --- a/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr +++ b/tests/ui/macros/macro-metavar-expr-concat/empty-input.stderr @@ -7,13 +7,12 @@ LL | () => { ${concat()} } error: expected expression, found `$` --> $DIR/empty-input.rs:6:13 | +LL | macro_rules! empty { LL | () => { ${concat()} } | ^ expected expression ... LL | let x = empty!(); | -------- in this macro invocation - | - = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-rules-attr-error.stderr b/tests/ui/macros/macro-rules-attr-error.stderr index 27527a2da7ef2..3a7f5a9f26fd0 100644 --- a/tests/ui/macros/macro-rules-attr-error.stderr +++ b/tests/ui/macros/macro-rules-attr-error.stderr @@ -1,13 +1,13 @@ error: local_attr: struct S; --> $DIR/macro-rules-attr-error.rs:5:9 | +LL | macro_rules! local_attr { +LL | attr() { $($body:tt)* } => { LL | compile_error!(concat!("local_attr: ", stringify!($($body)*))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | #[local_attr] | ------------- in this attribute macro expansion - | - = note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary `unsafe` on safe attribute invocation --> $DIR/macro-rules-attr-error.rs:63:3 diff --git a/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr index 7d9a94338f51f..327619dafa991 100644 --- a/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr +++ b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr @@ -1,6 +1,8 @@ error: recursion limit reached while expanding `#[attr]` --> $DIR/macro-rules-attr-infinite-recursion.rs:6:9 | +LL | macro_rules! attr { +LL | attr() { $($body:tt)* } => { LL | #[attr] $($body)* | ^^^^^^^ ... @@ -8,7 +10,6 @@ LL | #[attr] | ------- in this attribute macro expansion | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`macro_rules_attr_infinite_recursion`) - = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/macro-rules-derive-error.stderr b/tests/ui/macros/macro-rules-derive-error.stderr index bf6f58a3686d2..b0962ea53c241 100644 --- a/tests/ui/macros/macro-rules-derive-error.stderr +++ b/tests/ui/macros/macro-rules-derive-error.stderr @@ -1,13 +1,13 @@ error: MyDerive: struct S1; --> $DIR/macro-rules-derive-error.rs:5:9 | +LL | macro_rules! MyDerive { +LL | derive() { $($body:tt)* } => { LL | compile_error!(concat!("MyDerive: ", stringify!($($body)*))); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | #[derive(MyDerive)] | -------- in this derive macro expansion - | - = note: this error originates in the derive macro `MyDerive` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot find macro `MyDerive` in this scope --> $DIR/macro-rules-derive-error.rs:28:5 diff --git a/tests/ui/macros/macro-shadowing.stderr b/tests/ui/macros/macro-shadowing.stderr index cf2a57d6319dd..96992aee649a4 100644 --- a/tests/ui/macros/macro-shadowing.stderr +++ b/tests/ui/macros/macro-shadowing.stderr @@ -1,6 +1,8 @@ error: `macro_two` is already in scope --> $DIR/macro-shadowing.rs:14:5 | +LL | macro_rules! m1 { () => { +... LL | #[macro_use] | ^^^^^^^^^^^^ ... @@ -8,11 +10,12 @@ LL | m1!(); | ----- in this macro invocation | = note: macro-expanded `#[macro_use]`s may not shadow existing macros (see RFC 1560) - = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `foo` is ambiguous --> $DIR/macro-shadowing.rs:19:1 | +LL | macro_rules! m1 { () => { +... LL | foo!(); | ^^^ ambiguous name | @@ -30,7 +33,6 @@ note: `foo` could also refer to the macro defined here | LL | macro_rules! foo { () => {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/macro-span-issue-116502.stderr b/tests/ui/macros/macro-span-issue-116502.stderr index 024656e685f5b..ea0b2e85b2c04 100644 --- a/tests/ui/macros/macro-span-issue-116502.stderr +++ b/tests/ui/macros/macro-span-issue-116502.stderr @@ -1,35 +1,35 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/macro-span-issue-116502.rs:7:13 | +LL | macro_rules! m { +LL | () => { LL | _ | ^ not allowed in type signatures ... LL | struct S(m!(), T) | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/macro-span-issue-116502.rs:7:13 | +LL | macro_rules! m { +LL | () => { LL | _ | ^ not allowed in type signatures ... LL | T: Trait; | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0121]: the placeholder `_` is not allowed within types on item signatures for structs --> $DIR/macro-span-issue-116502.rs:7:13 | +LL | macro_rules! m { +LL | () => { LL | _ | ^ not allowed in type signatures ... LL | struct S(m!(), T) | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/macros/metavar-expressions/concat-hygiene.stderr b/tests/ui/macros/metavar-expressions/concat-hygiene.stderr index 9520f5182f4a7..2ef13306b3e33 100644 --- a/tests/ui/macros/metavar-expressions/concat-hygiene.stderr +++ b/tests/ui/macros/metavar-expressions/concat-hygiene.stderr @@ -1,6 +1,8 @@ error[E0425]: cannot find value `abcdef` in this scope --> $DIR/concat-hygiene.rs:5:10 | +LL | macro_rules! join { +LL | ($lhs:ident, $rhs:ident) => { LL | ${concat($lhs, $rhs)} | ^^^^^^^^^^^^^^^^^^^^ not found in this scope ... @@ -12,7 +14,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | let abcdef = 1; | ^^^^^^ - = note: this error originates in the macro `join` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr index 7abab6a510358..236637f1fc0c9 100644 --- a/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr +++ b/tests/ui/macros/metavar-expressions/concat-raw-identifiers.stderr @@ -83,13 +83,13 @@ LL | let ${concat($lhs, $rhs)}: () = (); error: expected pattern, found `$` --> $DIR/concat-raw-identifiers.rs:28:13 | +LL | macro_rules! no_params { +LL | () => { LL | let ${concat(r#abc, abc)}: () = (); | ^ expected pattern ... LL | no_params!(); | ------------ in this macro invocation - | - = note: this error originates in the macro `no_params` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 14 previous errors diff --git a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr index a6fc67d415d9c..4f06cc0ed1f92 100644 --- a/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-trace-errors.stderr @@ -1,6 +1,8 @@ error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-trace-errors.rs:17:24 | +LL | macro_rules! post_expansion { +LL | ($a:literal) => { LL | const _: () = ${concat("hi", $a, "bye")}; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -9,11 +11,12 @@ LL | post_expansion!("!"); | = note: this `${concat(..)}` invocation generated `hi!bye`, but '!' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `post_expansion` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-trace-errors.rs:31:24 | +LL | macro_rules! post_expansion_many { +LL | ($a:ident, $b:ident, $c:ident, $d:literal, $e:ident) => { LL | const _: () = ${concat($a, $b, $c, $d, $e)}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | post_expansion_many!(a, b, c, ".d", e); | = note: this `${concat(..)}` invocation generated `abc.de`, but '.' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `post_expansion_many` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr index 2ba81551289df..6bb06f5ca92a1 100644 --- a/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/concat-usage-errors.stderr @@ -141,6 +141,8 @@ LL | const ${concat(FOO, $foo)}: i32 = 2; error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:45:14 | +LL | macro_rules! starting_number { +LL | ($ident:ident) => {{ LL | let ${concat("1", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^ ... @@ -149,11 +151,12 @@ LL | starting_number!(_abc); | = note: this `${concat(..)}` invocation generated `1_abc`, but '1' is neither '_' nor XID_Start = note: see for the definition of valid identifiers - = note: this error originates in the macro `starting_number` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:59:14 | +LL | macro_rules! starting_invalid_unicode { +LL | ($ident:ident) => {{ LL | let ${concat("\u{00BD}", $ident)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -162,11 +165,12 @@ LL | starting_invalid_unicode!(_abc); | = note: this `${concat(..)}` invocation generated `\u{00BD}_abc`, but '\' is neither '_' nor XID_Start = note: see for the definition of valid identifiers - = note: this error originates in the macro `starting_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:80:14 | +LL | macro_rules! ending_invalid_unicode { +LL | ($ident:ident) => {{ LL | let ${concat($ident, "\u{00BD}")}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -175,22 +179,23 @@ LL | ending_invalid_unicode!(_abc); | = note: this `${concat(..)}` invocation generated `_abc\u{00BD}`, but '\' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `ending_invalid_unicode` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected pattern, found `$` --> $DIR/concat-usage-errors.rs:96:13 | +LL | macro_rules! unsupported_literals { +LL | ($ident:ident) => {{ LL | let ${concat(_a, 'b')}: () = (); | ^ expected pattern ... LL | unsupported_literals!(_abc); | --------------------------- in this macro invocation - | - = note: this error originates in the macro `unsupported_literals` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:88:14 | +LL | macro_rules! empty { +LL | () => {{ LL | let ${concat("", "")}: () = (); | ^^^^^^^^^^^^^^^^ ... @@ -198,11 +203,12 @@ LL | empty!(); | -------- in this macro invocation | = note: this `${concat(..)}` invocation generated an empty ident - = note: this error originates in the macro `empty` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -211,11 +217,12 @@ LL | bad_literal_string!("\u{00BD}"); | = note: this `${concat(..)}` invocation generated `_foo\u{00BD}`, but '\' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -224,11 +231,12 @@ LL | bad_literal_string!("\x41"); | = note: this `${concat(..)}` invocation generated `_foo\x41`, but '\' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -237,11 +245,12 @@ LL | bad_literal_string!("🤷"); | = note: this `${concat(..)}` invocation generated `_foo🤷`, but '🤷' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -250,11 +259,12 @@ LL | bad_literal_string!("d[-_-]b"); | = note: this `${concat(..)}` invocation generated `_food[-_-]b`, but '[' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -263,11 +273,12 @@ LL | bad_literal_string!("-1"); | = note: this `${concat(..)}` invocation generated `_foo-1`, but '-' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -276,11 +287,12 @@ LL | bad_literal_string!("1.0"); | = note: this `${concat(..)}` invocation generated `_foo1.0`, but '.' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: `${concat(..)}` is not generating a valid identifier --> $DIR/concat-usage-errors.rs:131:16 | +LL | macro_rules! bad_literal_string { +LL | ($literal:literal) => { LL | const ${concat(_foo, $literal)}: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -289,7 +301,6 @@ LL | bad_literal_string!("'1'"); | = note: this `${concat(..)}` invocation generated `_foo'1'`, but '\'' is not XID_Continue = note: see for the definition of valid identifiers - = note: this error originates in the macro `bad_literal_string` (in Nightly builds, run with -Z macro-backtrace for more info) error: metavariables of `${concat(..)}` must be of type `ident`, `literal` or `tt` --> $DIR/concat-usage-errors.rs:146:31 diff --git a/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr b/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr index e1f9d020b7f86..348ef3cd595d0 100644 --- a/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr +++ b/tests/ui/macros/metavar-expressions/count-empty-index-arg.stderr @@ -7,13 +7,12 @@ LL | ( $( $($t:ident),* );* ) => { ${count($t,)} } error: expected expression, found `$` --> $DIR/count-empty-index-arg.rs:7:35 | +LL | macro_rules! foo { LL | ( $( $($t:ident),* );* ) => { ${count($t,)} } | ^ expected expression ... LL | foo!(a, a; b, b); | ---------------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/metavar-expressions/usage-errors.stderr b/tests/ui/macros/metavar-expressions/usage-errors.stderr index 3d22e3ac4b30c..06b36de44a95a 100644 --- a/tests/ui/macros/metavar-expressions/usage-errors.stderr +++ b/tests/ui/macros/metavar-expressions/usage-errors.stderr @@ -13,13 +13,13 @@ LL | ( $i:ident ) => { ${ count($i) } }; error: missing `fn` or `struct` for function or struct definition --> $DIR/usage-errors.rs:28:30 | +LL | macro_rules! no_curly__no_rhs_dollar__round { LL | ( $( $i:ident ),* ) => { count(i) }; | ^^^^^ ... LL | no_curly__no_rhs_dollar__round !(a, b, c); | ----------------------------------------- in this macro invocation | - = note: this error originates in the macro `no_curly__no_rhs_dollar__round` (in Nightly builds, run with -Z macro-backtrace for more info) help: if you meant to call a macro, try | LL | ( $( $i:ident ),* ) => { count!(i) }; @@ -28,13 +28,13 @@ LL | ( $( $i:ident ),* ) => { count!(i) }; error: missing `fn` or `struct` for function or struct definition --> $DIR/usage-errors.rs:36:23 | +LL | macro_rules! no_curly__no_rhs_dollar__no_round { LL | ( $i:ident ) => { count(i) }; | ^^^^^ ... LL | no_curly__no_rhs_dollar__no_round !(a); | -------------------------------------- in this macro invocation | - = note: this error originates in the macro `no_curly__no_rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) help: if you meant to call a macro, try | LL | ( $i:ident ) => { count!(i) }; @@ -58,13 +58,12 @@ LL | const _: u32 = no_curly__rhs_dollar__no_round! (a); error[E0425]: cannot find function `count` in this scope --> $DIR/usage-errors.rs:51:23 | +LL | macro_rules! no_curly__rhs_dollar__no_round { LL | ( $i:ident ) => { count($i) }; | ^^^^^ not found in this scope ... LL | const _: u32 = no_curly__rhs_dollar__no_round! (a); | ----------------------------------- in this macro invocation - | - = note: this error originates in the macro `no_curly__rhs_dollar__no_round` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 7 previous errors diff --git a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr index 600a569a84ce2..0a6b7fe255db4 100644 --- a/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr +++ b/tests/ui/macros/no-field-error-in-macro-expansion-for-generic.stderr @@ -1,6 +1,8 @@ error[E0609]: no field `trace` on type `&T` --> $DIR/no-field-error-in-macro-expansion-for-generic.rs:7:17 | +LL | macro_rules! log { +LL | ( $ctx:expr, $( $args:expr),* ) => { LL | if $ctx.trace { | ^^^^^ unknown field ... @@ -9,8 +11,6 @@ LL | fn wrap(context: &T) -> () LL | { LL | log!(context, "entered wrapper"); | -------------------------------- in this macro invocation - | - = note: this error originates in the macro `log` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/nonterminal-matching.stderr b/tests/ui/macros/nonterminal-matching.stderr index d01561415664c..8816d779e3b5b 100644 --- a/tests/ui/macros/nonterminal-matching.stderr +++ b/tests/ui/macros/nonterminal-matching.stderr @@ -1,6 +1,7 @@ error: no rules expected `item` metavariable --> $DIR/nonterminal-matching.rs:19:10 | +LL | macro complex_nonterminal($nt_item: item) { LL | macro n(a $nt_item b) { | --------------------- when calling this macro ... @@ -21,11 +22,12 @@ LL | complex_nonterminal!(enum E {}); = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see for more information = help: try using `:tt` instead in the macro definition - = note: this error originates in the macro `complex_nonterminal` (in Nightly builds, run with -Z macro-backtrace for more info) error: no rules expected `expr` metavariable --> $DIR/nonterminal-matching.rs:32:35 | +LL | macro_rules! foo { +... LL | (expr $x:expr) => { bar!(expr $x); }; | ^^ no rules expected this token in macro call ... @@ -43,11 +45,12 @@ LL | (expr 3) => {}; = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see for more information = help: try using `:tt` instead in the macro definition - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: no rules expected `literal` metavariable --> $DIR/nonterminal-matching.rs:33:44 | +LL | macro_rules! foo { +... LL | (literal $x:literal) => { bar!(literal $x); }; | ^^ no rules expected this token in macro call ... @@ -65,11 +68,12 @@ LL | (literal 4) => {}; = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see for more information = help: try using `:tt` instead in the macro definition - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: no rules expected `path` metavariable --> $DIR/nonterminal-matching.rs:34:35 | +LL | macro_rules! foo { +... LL | (path $x:path) => { bar!(path $x); }; | ^^ no rules expected this token in macro call ... @@ -87,11 +91,12 @@ LL | (path a::b::c) => {}; = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see for more information = help: try using `:tt` instead in the macro definition - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: no rules expected `stmt` metavariable --> $DIR/nonterminal-matching.rs:35:35 | +LL | macro_rules! foo { +... LL | (stmt $x:stmt) => { bar!(stmt $x); }; | ^^ no rules expected this token in macro call ... @@ -109,7 +114,6 @@ LL | (stmt let abc = 0) => {}; = note: captured metavariables except for `:tt`, `:ident` and `:lifetime` cannot be compared to other tokens = note: see for more information = help: try using `:tt` instead in the macro definition - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 5 previous errors diff --git a/tests/ui/macros/private-struct-member-macro-access-25386.stderr b/tests/ui/macros/private-struct-member-macro-access-25386.stderr index d02a41848f478..e687c820b33e8 100644 --- a/tests/ui/macros/private-struct-member-macro-access-25386.stderr +++ b/tests/ui/macros/private-struct-member-macro-access-25386.stderr @@ -1,13 +1,13 @@ error[E0616]: field `c_object` of struct `Item` is private --> $DIR/private-struct-member-macro-access-25386.rs:20:16 | +LL | macro_rules! check_ptr_exist { +LL | ($var:expr, $member:ident) => ( LL | (*$var.c_object).$member.is_some() | ^^^^^^^^ private field ... LL | println!("{}", check_ptr_exist!(item, name)); | ---------------------------- in this macro invocation - | - = note: this error originates in the macro `check_ptr_exist` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/macros/reparse-expr-issue-139495.stderr b/tests/ui/macros/reparse-expr-issue-139495.stderr index e2e05d67ecc22..0a7b71a8c55ef 100644 --- a/tests/ui/macros/reparse-expr-issue-139495.stderr +++ b/tests/ui/macros/reparse-expr-issue-139495.stderr @@ -1,24 +1,22 @@ error: expected expression, found keyword `extern` --> $DIR/reparse-expr-issue-139495.rs:2:24 | +LL | macro_rules! m1 { LL | ($abi: literal) => { extern $abi } | ^^^^^^ expected expression ... LL | m1!(-2) | ------- in this macro invocation - | - = note: this error originates in the macro `m1` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected expression, found keyword `extern` --> $DIR/reparse-expr-issue-139495.rs:6:21 | +LL | macro_rules! m2 { LL | ($abi: expr) => { extern $abi } | ^^^^^^ expected expression ... LL | m2!(-2) | ------- in this macro invocation - | - = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/repeated-macro-expansion-error.stderr b/tests/ui/macros/repeated-macro-expansion-error.stderr index f820fac144842..e17540596e2b0 100644 --- a/tests/ui/macros/repeated-macro-expansion-error.stderr +++ b/tests/ui/macros/repeated-macro-expansion-error.stderr @@ -1,6 +1,8 @@ error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/repeated-macro-expansion-error.rs:12:20 | +LL | macro_rules! impl_add { +... LL | S::f::(); | ^------- help: remove the unnecessary generics | | @@ -14,11 +16,12 @@ note: associated function defined here, with 0 generic parameters | LL | fn f() {} | ^ - = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0107]: associated function takes 0 generic arguments but 1 generic argument was supplied --> $DIR/repeated-macro-expansion-error.rs:12:20 | +LL | macro_rules! impl_add { +... LL | S::f::(); | ^------- help: remove the unnecessary generics | | @@ -33,7 +36,6 @@ note: associated function defined here, with 0 generic parameters LL | fn f() {} | ^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - = note: this error originates in the macro `impl_add` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/macros/restricted-shadowing-legacy.stderr b/tests/ui/macros/restricted-shadowing-legacy.stderr index b8865112ed52e..6183d8383dfc0 100644 --- a/tests/ui/macros/restricted-shadowing-legacy.stderr +++ b/tests/ui/macros/restricted-shadowing-legacy.stderr @@ -1,11 +1,15 @@ error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:101:13 | -LL | m!(); - | ^ ambiguous name +LL | / macro_rules! gen_gen_inner_invoc { () => { +LL | | gen_inner!(); +LL | | m!(); + | | ^ ambiguous name +LL | | }} + | |__________- this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` ... -LL | include!(); - | ---------- in this macro invocation +LL | include!(); + | ---------- in this macro invocation | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here @@ -24,7 +28,6 @@ LL | macro_rules! m { () => {} } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:139:42 @@ -52,11 +55,12 @@ LL | macro_rules! m { () => {} } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:148:9 | +LL | macro_rules! include { () => { +... LL | m!(); | ^ ambiguous name ... @@ -80,11 +84,12 @@ LL | macro_rules! m { () => {} } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:164:9 | +LL | macro_rules! include { () => { +... LL | m!(); | ^ ambiguous name ... @@ -108,16 +113,19 @@ LL | macro_rules! m { () => { Wrong } } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:180:13 | -LL | m!(); - | ^ ambiguous name +LL | / macro_rules! gen_gen_inner_invoc { () => { +LL | | gen_inner!(); +LL | | m!(); + | | ^ ambiguous name +LL | | }} + | |__________- this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` ... -LL | include!(); - | ---------- in this macro invocation +LL | include!(); + | ---------- in this macro invocation | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here @@ -136,7 +144,6 @@ LL | macro_rules! m { () => { Wrong } } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:218:42 @@ -164,11 +171,12 @@ LL | macro_rules! m { () => { Wrong } } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:232:9 | +LL | macro_rules! include { () => { +... LL | m!(); | ^ ambiguous name ... @@ -192,7 +200,6 @@ LL | macro_rules! m { () => {} } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-legacy.rs:262:42 @@ -220,7 +227,6 @@ LL | macro_rules! m { () => {} } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 8 previous errors diff --git a/tests/ui/macros/restricted-shadowing-modern.stderr b/tests/ui/macros/restricted-shadowing-modern.stderr index 27665bfc31044..4cb9762f279b5 100644 --- a/tests/ui/macros/restricted-shadowing-modern.stderr +++ b/tests/ui/macros/restricted-shadowing-modern.stderr @@ -1,11 +1,15 @@ error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:104:17 | -LL | m!(); - | ^ ambiguous name +LL | / macro gen_gen_inner_invoc() { +LL | | gen_inner!(); +LL | | m!(); + | | ^ ambiguous name +LL | | } + | |_____________- this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` ... -LL | include!(); - | ---------- in this macro invocation +LL | include!(); + | ---------- in this macro invocation | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here @@ -24,7 +28,6 @@ LL | macro m() {} ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:147:33 @@ -52,11 +55,12 @@ LL | macro m() {} ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:156:13 | +LL | macro include() { +... LL | m!(); | ^ ambiguous name ... @@ -80,11 +84,12 @@ LL | macro m() {} ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:172:13 | +LL | macro include() { +... LL | m!(); | ^ ambiguous name ... @@ -108,16 +113,19 @@ LL | macro m() { Wrong } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:190:17 | -LL | m!(); - | ^ ambiguous name +LL | / macro gen_gen_inner_invoc() { +LL | | gen_inner!(); +LL | | m!(); + | | ^ ambiguous name +LL | | } + | |_____________- this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` ... -LL | include!(); - | ---------- in this macro invocation +LL | include!(); + | ---------- in this macro invocation | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution note: `m` could refer to the macro defined here @@ -136,7 +144,6 @@ LL | macro m() { Wrong } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_gen_inner_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `m` is ambiguous --> $DIR/restricted-shadowing-modern.rs:233:33 @@ -164,7 +171,6 @@ LL | macro m() { Wrong } ... LL | include!(); | ---------- in this macro invocation - = note: this error originates in the macro `gen_invoc` which comes from the expansion of the macro `include` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/macros/span-covering-argument-1.stderr b/tests/ui/macros/span-covering-argument-1.stderr index 9ad2bc73a4ff5..dd2213be59329 100644 --- a/tests/ui/macros/span-covering-argument-1.stderr +++ b/tests/ui/macros/span-covering-argument-1.stderr @@ -1,13 +1,14 @@ error[E0596]: cannot borrow `foo` as mutable, as it is not declared as mutable --> $DIR/span-covering-argument-1.rs:5:14 | +LL | macro_rules! bad { +... LL | *&mut $s = 0; | ^^^^^^^ cannot borrow as mutable ... LL | bad!(foo whatever); | ------------------ in this macro invocation | - = note: this error originates in the macro `bad` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider changing this to be mutable | LL | let mut $s = 0; diff --git a/tests/ui/macros/syntax-error-recovery.stderr b/tests/ui/macros/syntax-error-recovery.stderr index a2059aa1aa802..b73727b9b9fa1 100644 --- a/tests/ui/macros/syntax-error-recovery.stderr +++ b/tests/ui/macros/syntax-error-recovery.stderr @@ -1,6 +1,8 @@ error: expected one of `(`, `,`, `=`, `{`, or `}`, found `ty` metavariable --> $DIR/syntax-error-recovery.rs:7:26 | +LL | macro_rules! values { +... LL | $token $($inner)? = $value, | ^^^^^^ expected one of `(`, `,`, `=`, `{`, or `}` ... @@ -8,7 +10,6 @@ LL | values!(STRING(1) as (String) => cfg(test),); | -------------------------------------------- in this macro invocation | = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` - = note: this error originates in the macro `values` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro expansion ignores `ty` metavariable and any tokens following --> $DIR/syntax-error-recovery.rs:7:26 diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr index e90d7a98db4c7..fd1633dba6aff 100644 --- a/tests/ui/macros/trace_faulty_macros.stderr +++ b/tests/ui/macros/trace_faulty_macros.stderr @@ -11,7 +11,6 @@ LL | my_faulty_macro!(); | ------------------ in this macro invocation | = note: while trying to match end of macro - = note: this error originates in the macro `my_faulty_macro` (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro --> $DIR/trace_faulty_macros.rs:31:5 @@ -26,6 +25,8 @@ LL | my_faulty_macro!(); error: recursion limit reached while expanding `my_recursive_macro!` --> $DIR/trace_faulty_macros.rs:22:9 | +LL | macro_rules! my_recursive_macro { +LL | () => { LL | my_recursive_macro!(); | ^^^^^^^^^^^^^^^^^^^^^ ... @@ -33,7 +34,6 @@ LL | my_recursive_macro!(); | --------------------- in this macro invocation | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "8"]` attribute to your crate (`trace_faulty_macros`) - = note: this error originates in the macro `my_recursive_macro` (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro --> $DIR/trace_faulty_macros.rs:32:5 @@ -53,13 +53,13 @@ LL | my_recursive_macro!(); error: expected expression, found `pat` metavariable --> $DIR/trace_faulty_macros.rs:16:9 | +LL | macro_rules! pat_macro { +... LL | $a | ^^ expected expression ... LL | let a = pat_macro!(); | ------------ in this macro invocation - | - = note: this error originates in the macro `pat_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0774]: `derive` may only be applied to `struct`s, `enum`s and `union`s --> $DIR/trace_faulty_macros.rs:42:1 @@ -72,13 +72,13 @@ LL | fn use_derive_macro_as_attr() {} error: expected expression, found `pat` metavariable --> $DIR/trace_faulty_macros.rs:49:37 | +LL | macro_rules! test { +... LL | (($p:pat, $e:pat)) => {let $p = $e;}; | ^^ expected expression ... LL | test!(let x = 1+1); | ------------------ in this macro invocation - | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) note: trace_macro --> $DIR/trace_faulty_macros.rs:36:13 diff --git a/tests/ui/macros/typo-in-norepeat-expr-2.stderr b/tests/ui/macros/typo-in-norepeat-expr-2.stderr index 50d5dea040be9..406e00ed2a3e7 100644 --- a/tests/ui/macros/typo-in-norepeat-expr-2.stderr +++ b/tests/ui/macros/typo-in-norepeat-expr-2.stderr @@ -1,6 +1,8 @@ error: cannot find macro parameter `$follow` in this scope --> $DIR/typo-in-norepeat-expr-2.rs:6:10 | +LL | macro_rules! err { +... LL | [$follow] | ^------ | || @@ -9,19 +11,18 @@ LL | [$follow] ... LL | let _ = err![begin1 x end ig]; | ---------------------- in this macro invocation - | - = note: this error originates in the macro `err` (in Nightly builds, run with -Z macro-backtrace for more info) error: cannot find macro parameter `$follo` in this scope --> $DIR/typo-in-norepeat-expr-2.rs:17:10 | +LL | macro_rules! err1 { +... LL | [$follo] | ^^^^^^ not found in this scope ... LL | let _ = err1![begin1 x end]; | -------------------- in this macro invocation | - = note: this error originates in the macro `err1` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a macro metavariable with a similar name in another macro matcher | LL | [$follow] @@ -30,6 +31,8 @@ LL | [$follow] error: cannot find macro parameter `$xyz` in this scope --> $DIR/typo-in-norepeat-expr-2.rs:28:10 | +LL | macro_rules! err2 { +... LL | [$xyz] | ^^^^ not found in this scope ... @@ -37,7 +40,6 @@ LL | let _ = err2![begin1 x end]; | -------------------- in this macro invocation | = note: available metavariable names are: $arg1 - = note: this error originates in the macro `err2` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/macros/typo-in-norepeat-expr.stderr b/tests/ui/macros/typo-in-norepeat-expr.stderr index 72fdac0e24cd3..8aa5814eba297 100644 --- a/tests/ui/macros/typo-in-norepeat-expr.stderr +++ b/tests/ui/macros/typo-in-norepeat-expr.stderr @@ -1,13 +1,14 @@ error: cannot find macro parameter `$arg` in this scope --> $DIR/typo-in-norepeat-expr.rs:4:10 | +LL | macro_rules! m { +LL | (begin $ard:ident end) => { LL | [$arg] | ^^^^ not found in this scope ... LL | let _ = m![begin x end]; | --------------- in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: there is a macro metavariable with a similar name | LL - [$arg] diff --git a/tests/ui/mismatched_types/issue-26480.stderr b/tests/ui/mismatched_types/issue-26480.stderr index da8d73225f317..ec91caed5e940 100644 --- a/tests/ui/mismatched_types/issue-26480.stderr +++ b/tests/ui/mismatched_types/issue-26480.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-26480.rs:16:19 | +LL | macro_rules! write { +... LL | write(stdout, $arr.as_ptr() as *const i8, | ----- arguments to this function are incorrect LL | $arr.len() * size_of($arr[0])); @@ -14,7 +16,6 @@ note: function defined here | LL | fn write(fildes: i32, buf: *const i8, nbyte: u64) -> i64; | ^^^^^ ----- - = note: this error originates in the macro `write` (in Nightly builds, run with -Z macro-backtrace for more info) help: you can convert a `usize` to a `u64` and panic if the converted value doesn't fit | LL | ($arr.len() * size_of($arr[0])).try_into().unwrap()); @@ -23,13 +24,12 @@ LL | ($arr.len() * size_of($arr[0])).try_into().unwrap()); error[E0605]: non-primitive cast: `{integer}` as `()` --> $DIR/issue-26480.rs:22:19 | +LL | macro_rules! cast { LL | ($x:expr) => ($x as ()) | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object ... LL | cast!(2); | -------- in this macro invocation - | - = note: this error originates in the macro `cast` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/modules/issue-56411.stderr b/tests/ui/modules/issue-56411.stderr index 6732a8a3d7324..6e8912146883d 100644 --- a/tests/ui/modules/issue-56411.stderr +++ b/tests/ui/modules/issue-56411.stderr @@ -1,6 +1,8 @@ error[E0255]: the name `issue_56411_aux` is defined multiple times --> $DIR/issue-56411.rs:6:21 | +LL | macro_rules! import { +... LL | mod $name; | ---------- previous definition of the module `issue_56411_aux` here LL | pub use self::$name; @@ -13,11 +15,12 @@ LL | import!(("issue-56411-aux.rs", issue_56411_aux)); | ------------------------------------------------ in this macro invocation | = note: `issue_56411_aux` must be defined only once in the type namespace of this module - = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0365]: `issue_56411_aux` is only public within the crate, and cannot be re-exported outside --> $DIR/issue-56411.rs:6:21 | +LL | macro_rules! import { +... LL | pub use self::$name; | ^^^^^^^^^^^ re-export of crate public `issue_56411_aux` ... @@ -25,7 +28,6 @@ LL | import!(("issue-56411-aux.rs", issue_56411_aux)); | ------------------------------------------------ in this macro invocation | = note: consider declaring type or module `issue_56411_aux` with `pub` - = note: this error originates in the macro `import` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.stderr b/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.stderr index 020713d03d34a..5de73060d41ad 100644 --- a/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.stderr +++ b/tests/ui/never_type/fallback_change/lint-never-type-fallback-flowing-into-unsafe.stderr @@ -102,6 +102,8 @@ LL | S(marker::PhantomData).create_out_of_thin_air() error: never type fallback affects this call to an `unsafe` function --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:136:19 | +LL | macro_rules! msg_send { +LL | () => { LL | match send_message::<_ /* ?0 */>() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -109,7 +111,6 @@ LL | msg_send!(); | ----------- in this macro invocation | = help: specify the type explicitly - = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info) warning: the type `!` does not permit zero-initialization --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:9:18 diff --git a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr index 6ddc059566539..acc3ecb865949 100644 --- a/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr +++ b/tests/ui/or-patterns/exhaustiveness-unreachable-pattern.stderr @@ -237,6 +237,8 @@ LL | (true | false, None | Some(true error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:116:14 | +LL | macro_rules! t_or_f { +LL | () => { LL | (true | ^^^^ no value can reach this ... @@ -255,7 +257,6 @@ LL | (false, Some(true)) => {} | ---- matches some of the same values LL | (true | false, None | Some(t_or_f!())) => {} | --------- in this macro invocation - = note: this error originates in the macro `t_or_f` (in Nightly builds, run with -Z macro-backtrace for more info) error: unreachable pattern --> $DIR/exhaustiveness-unreachable-pattern.rs:127:14 diff --git a/tests/ui/parser/attribute/attr-bad-meta-4.stderr b/tests/ui/parser/attribute/attr-bad-meta-4.stderr index 8f4edca226d3b..de0f3c27bf726 100644 --- a/tests/ui/parser/attribute/attr-bad-meta-4.stderr +++ b/tests/ui/parser/attribute/attr-bad-meta-4.stderr @@ -13,13 +13,13 @@ LL + #[cfg(feature = 1)] error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `meta` metavariable --> $DIR/attr-bad-meta-4.rs:3:15 | +LL | macro_rules! mac { +LL | ($attr_item: meta) => { LL | #[cfg($attr_item)] | ^^^^^^^^^^ ... LL | mac!(an(arbitrary token stream)); | -------------------------------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/parser/attribute/attr-unquoted-ident.stderr b/tests/ui/parser/attribute/attr-unquoted-ident.stderr index 48ca499ba78fb..b7204a2669c2c 100644 --- a/tests/ui/parser/attribute/attr-unquoted-ident.stderr +++ b/tests/ui/parser/attribute/attr-unquoted-ident.stderr @@ -34,13 +34,13 @@ LL | #[cfg(key="foo 1 bar 2.0 baz.")] error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found expression --> $DIR/attr-unquoted-ident.rs:28:38 | +LL | macro_rules! make { LL | ($name:ident) => { #[doc(alias = $name)] pub struct S; } | ^^^^^ expressions are not allowed here ... LL | make!(nickname); | --------------- in this macro invocation | - = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info) help: surround the identifier with quotation marks to make it into a string literal | LL | ($name:ident) => { #[doc(alias = "$name")] pub struct S; } diff --git a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr index 41e7b5ab759dd..0e380ae4fd00e 100644 --- a/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr +++ b/tests/ui/parser/attribute/properly-recover-from-trailing-outer-attribute-in-body-2.stderr @@ -1,6 +1,8 @@ error: expected `;`, found `#` --> $DIR/properly-recover-from-trailing-outer-attribute-in-body-2.rs:6:13 | +LL | macro_rules! the_macro { +LL | ( $foo:stmt ; $bar:stmt ; ) => { LL | #[cfg()] | -------- only `;` terminated statements or tail expressions are allowed after this attribute LL | $foo @@ -12,7 +14,6 @@ LL | #[cfg(false)] LL | the_macro!( (); (); ); | --------------------- in this macro invocation | - = note: this error originates in the macro `the_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: add `;` here | LL | $foo; diff --git a/tests/ui/parser/bad-interpolated-block.stderr b/tests/ui/parser/bad-interpolated-block.stderr index 651036c51c948..687ec36fe2021 100644 --- a/tests/ui/parser/bad-interpolated-block.stderr +++ b/tests/ui/parser/bad-interpolated-block.stderr @@ -1,6 +1,8 @@ error: cannot use a `block` macro fragment here --> $DIR/bad-interpolated-block.rs:5:15 | +LL | macro_rules! m { +LL | ($b:block) => { LL | 'lab: $b; | ------^^ | | @@ -9,7 +11,6 @@ LL | 'lab: $b; LL | m!({}); | ------ in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this in another block | LL | 'lab: { $b }; @@ -18,6 +19,8 @@ LL | 'lab: { $b }; error: cannot use a `block` macro fragment here --> $DIR/bad-interpolated-block.rs:6:16 | +LL | macro_rules! m { +... LL | unsafe $b; | -------^^ | | @@ -26,7 +29,6 @@ LL | unsafe $b; LL | m!({}); | ------ in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this in another block | LL | unsafe { $b }; @@ -35,13 +37,14 @@ LL | unsafe { $b }; error: cannot use a `block` macro fragment here --> $DIR/bad-interpolated-block.rs:7:23 | +LL | macro_rules! m { +... LL | |x: u8| -> () $b; | ^^ the `block` fragment is within this context ... LL | m!({}); | ------ in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this in another block | LL | |x: u8| -> () { $b }; diff --git a/tests/ui/parser/bad-let-else-statement.stderr b/tests/ui/parser/bad-let-else-statement.stderr index 76fbbbb8c1e10..0c56be17b8756 100644 --- a/tests/ui/parser/bad-let-else-statement.stderr +++ b/tests/ui/parser/bad-let-else-statement.stderr @@ -243,13 +243,14 @@ LL ~ ) else { error: right curly brace `}` before `else` in a `let...else` statement not allowed --> $DIR/bad-let-else-statement.rs:190:25 | +LL | macro_rules! b { +... LL | let 0 = a! {} else { return; }; | ^ ... LL | b!(2); | ----- in this macro invocation | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) help: use parentheses instead of braces for this macro | LL - let 0 = a! {} else { return; }; diff --git a/tests/ui/parser/const-block-items/macro-stmt.stderr b/tests/ui/parser/const-block-items/macro-stmt.stderr index dce90e5daa4ca..0132a8f4b62c9 100644 --- a/tests/ui/parser/const-block-items/macro-stmt.stderr +++ b/tests/ui/parser/const-block-items/macro-stmt.stderr @@ -1,13 +1,13 @@ error: expected expression, found `` --> $DIR/macro-stmt.rs:7:9 | +LL | macro_rules! foo { +LL | ($item:item) => { LL | $item | ^^^^^ expected expression ... LL | foo!(const {}); | -------------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/float-field-interpolated.stderr b/tests/ui/parser/float-field-interpolated.stderr index e2b7e3a7dbe75..6e227e54d5938 100644 --- a/tests/ui/parser/float-field-interpolated.stderr +++ b/tests/ui/parser/float-field-interpolated.stderr @@ -1,46 +1,46 @@ error: unexpected token: `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | +LL | macro_rules! generate_field_accesses { +... LL | { s.$b; } | ^^ ... LL | generate_field_accesses!(1.1, 1.1, 1.1); | --------------------------------------- in this macro invocation - | - = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected one of `.`, `;`, `?`, `}`, or an operator, found `literal` metavariable --> $DIR/float-field-interpolated.rs:8:13 | +LL | macro_rules! generate_field_accesses { +... LL | { s.$b; } | ^^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | generate_field_accesses!(1.1, 1.1, 1.1); | --------------------------------------- in this macro invocation - | - = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) error: unexpected token: `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | +LL | macro_rules! generate_field_accesses { +... LL | { s.$c; } | ^^ ... LL | generate_field_accesses!(1.1, 1.1, 1.1); | --------------------------------------- in this macro invocation - | - = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) error: expected one of `.`, `;`, `?`, `}`, or an operator, found `expr` metavariable --> $DIR/float-field-interpolated.rs:10:13 | +LL | macro_rules! generate_field_accesses { +... LL | { s.$c; } | ^^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | generate_field_accesses!(1.1, 1.1, 1.1); | --------------------------------------- in this macro invocation - | - = note: this error originates in the macro `generate_field_accesses` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/parser/issues/issue-44406.stderr b/tests/ui/parser/issues/issue-44406.stderr index b2367ce15ea8a..89036b8b44b43 100644 --- a/tests/ui/parser/issues/issue-44406.stderr +++ b/tests/ui/parser/issues/issue-44406.stderr @@ -1,13 +1,14 @@ error: invalid `struct` delimiters or `fn` call arguments --> $DIR/issue-44406.rs:3:9 | +LL | macro_rules! foo { +LL | ($rest: tt) => { LL | bar(baz: $rest) | ^^^^^^^^^^^^^^^ ... LL | foo!(true); | ---------- in this macro invocation | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: if `bar` is a struct, use braces as delimiters | LL - bar(baz: $rest) diff --git a/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr index fdef8ff6df923..d091006d82df5 100644 --- a/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr +++ b/tests/ui/parser/issues/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.stderr @@ -9,6 +9,8 @@ LL | struct BadS; error: enum is not supported in `trait`s or `impl`s --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 | +LL | macro_rules! expand_to_enum { +LL | () => { LL | enum BadE {} | ^^^^^^^^^ ... @@ -16,7 +18,6 @@ LL | expand_to_enum!(); | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope - = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) error: struct is not supported in `trait`s or `impl`s --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:31:5 @@ -29,6 +30,8 @@ LL | struct BadS; error: enum is not supported in `trait`s or `impl`s --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 | +LL | macro_rules! expand_to_enum { +LL | () => { LL | enum BadE {} | ^^^^^^^^^ ... @@ -36,7 +39,6 @@ LL | expand_to_enum!(); | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope - = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) error: struct is not supported in `extern` blocks --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:42:5 @@ -49,6 +51,8 @@ LL | struct BadS; error: enum is not supported in `extern` blocks --> $DIR/issue-48137-macros-cannot-interpolate-impl-items-bad-variants.rs:5:9 | +LL | macro_rules! expand_to_enum { +LL | () => { LL | enum BadE {} | ^^^^^^^^^ ... @@ -56,7 +60,6 @@ LL | expand_to_enum!(); | ----------------- in this macro invocation | = help: consider moving the enum out to a nearby module scope - = note: this error originates in the macro `expand_to_enum` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 6 previous errors diff --git a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr index 59e1b64686b46..a2ad6e619adad 100644 --- a/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr +++ b/tests/ui/parser/issues/issue-65122-mac-invoc-in-mut-patterns.stderr @@ -1,6 +1,8 @@ error: `mut` must be followed by a named binding --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:6:13 | +LL | macro_rules! mac1 { +LL | ($eval:expr) => { LL | let mut $eval = (); | ^^^^ ... @@ -8,7 +10,6 @@ LL | mac1! { does_not_exist!() } | --------------------------- in this macro invocation | = note: `mut` may be followed by `variable` and `variable @ pattern` - = note: this error originates in the macro `mac1` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the `mut` prefix | LL - let mut $eval = (); @@ -18,17 +19,19 @@ LL + let $eval = (); error: expected identifier, found metavariable --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:17 | +LL | macro_rules! mac2 { +LL | ($eval:pat) => { LL | let mut $eval = (); | ^^^^^ expected identifier, found metavariable ... LL | mac2! { does_not_exist!() } | --------------------------- in this macro invocation - | - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error: `mut` must be followed by a named binding --> $DIR/issue-65122-mac-invoc-in-mut-patterns.rs:13:13 | +LL | macro_rules! mac2 { +LL | ($eval:pat) => { LL | let mut $eval = (); | ^^^^ ... @@ -36,7 +39,6 @@ LL | mac2! { does_not_exist!() } | --------------------------- in this macro invocation | = note: `mut` may be followed by `variable` and `variable @ pattern` - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the `mut` prefix | LL - let mut $eval = (); diff --git a/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr b/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr index a68fae1a36ec8..d611ba247bfd7 100644 --- a/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr +++ b/tests/ui/parser/issues/issue-68091-unicode-ident-after-if.stderr @@ -1,6 +1,8 @@ error: missing condition for `if` expression --> $DIR/issue-68091-unicode-ident-after-if.rs:3:13 | +LL | macro_rules! x { +LL | ($($c:tt)*) => { LL | $($c)ö* {} | ^ - if this block is the condition of the `if` expression, then it must be followed by another block | | @@ -8,8 +10,6 @@ LL | $($c)ö* {} ... LL | x!(if); | ------ in this macro invocation - | - = note: this error originates in the macro `x` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr index f967d4a8b3e01..bd931a484e8fc 100644 --- a/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr +++ b/tests/ui/parser/issues/issue-73568-lifetime-after-mut.stderr @@ -24,13 +24,14 @@ LL | fn y<'a>(y: &mut ('a + Send)) { error: lifetime must precede `mut` --> $DIR/issue-73568-lifetime-after-mut.rs:6:22 | +LL | macro_rules! mac { +LL | ($lt:lifetime) => { LL | fn w<$lt>(w: &mut $lt i32) {} | ^^^^^^^^ ... LL | mac!('a); | -------- in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: place the lifetime before `mut` | LL - fn w<$lt>(w: &mut $lt i32) {} diff --git a/tests/ui/parser/issues/issue-87812-path.stderr b/tests/ui/parser/issues/issue-87812-path.stderr index fbe26ea39595a..df734726a7474 100644 --- a/tests/ui/parser/issues/issue-87812-path.stderr +++ b/tests/ui/parser/issues/issue-87812-path.stderr @@ -1,6 +1,8 @@ error[E0308]: mismatched types --> $DIR/issue-87812-path.rs:3:24 | +LL | macro_rules! foo { +LL | ( $f:path ) => {{ LL | let _: usize = $f; | ----- ^^ expected `usize`, found `Baz` | | @@ -8,8 +10,6 @@ LL | let _: usize = $f; ... LL | foo!(Baz); | --------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-87812.stderr b/tests/ui/parser/issues/issue-87812.stderr index 35dc66a528a99..f41b4a2e3bd55 100644 --- a/tests/ui/parser/issues/issue-87812.stderr +++ b/tests/ui/parser/issues/issue-87812.stderr @@ -1,6 +1,8 @@ error: this labeled break expression is easy to confuse with an unlabeled break with a labeled value expression --> $DIR/issue-87812.rs:6:13 | +LL | macro_rules! foo { +... LL | break '_l $f; | ^^^^^^^^^^^^ ... @@ -12,7 +14,6 @@ note: the lint level is defined here | LL | #![deny(break_with_label_and_loop)] | ^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this expression in parentheses | LL | break '_l ($f); diff --git a/tests/ui/parser/labeled-no-colon-expr.stderr b/tests/ui/parser/labeled-no-colon-expr.stderr index 2478319281569..d5f0bb0b0e840 100644 --- a/tests/ui/parser/labeled-no-colon-expr.stderr +++ b/tests/ui/parser/labeled-no-colon-expr.stderr @@ -83,6 +83,8 @@ LL | 'l4: 0; error: cannot use a `block` macro fragment here --> $DIR/labeled-no-colon-expr.rs:11:17 | +LL | macro_rules! m { +LL | ($b:block) => { LL | 'l5 $b; | ----^^ | | @@ -91,7 +93,6 @@ LL | 'l5 $b; LL | m!({}); | ------ in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap this in another block | LL | 'l5 { $b }; diff --git a/tests/ui/parser/macro/break-in-unlabeled-block-in-macro.stderr b/tests/ui/parser/macro/break-in-unlabeled-block-in-macro.stderr index 2f46cb36750be..b0c1bf492e669 100644 --- a/tests/ui/parser/macro/break-in-unlabeled-block-in-macro.stderr +++ b/tests/ui/parser/macro/break-in-unlabeled-block-in-macro.stderr @@ -1,24 +1,24 @@ error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:3:9 | +LL | macro_rules! foo { +LL | () => { LL | break (); | ^^^^^^^^ cannot `break` outside of a loop or labeled block ... LL | foo!(); | ------ in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:6:9 | +LL | macro_rules! foo { +... LL | break $e; | ^^^^^^^^ cannot `break` outside of a loop or labeled block ... LL | foo!(()); | -------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:33:17 @@ -29,24 +29,25 @@ LL | foo!(=> break ()); error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:38:17 | +LL | macro_rules! bar { +LL | () => { LL | break () | ^^^^^^^^ cannot `break` outside of a loop or labeled block ... LL | bar!() | ------ in this macro invocation - | - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0268]: `break` outside of a loop or labeled block --> $DIR/break-in-unlabeled-block-in-macro.rs:12:11 | +LL | macro_rules! foo { +... LL | { break $e; } | ^^^^^^^^ cannot `break` outside of a loop or labeled block ... LL | foo!(@ ()); | ---------- in this macro invocation | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider labeling this block to be able to break within it | LL | 'block: { break 'block $e; } diff --git a/tests/ui/parser/macro/issue-37113.stderr b/tests/ui/parser/macro/issue-37113.stderr index 560329df5ccbd..89944ec3e15cd 100644 --- a/tests/ui/parser/macro/issue-37113.stderr +++ b/tests/ui/parser/macro/issue-37113.stderr @@ -1,6 +1,8 @@ error: expected identifier, found metavariable --> $DIR/issue-37113.rs:4:16 | +LL | macro_rules! test_macro { +LL | ( $( $t:ty ),* $(),*) => { LL | enum SomeEnum { | -------- while parsing this enum LL | $( $t, )* @@ -10,7 +12,6 @@ LL | test_macro!(String,); | -------------------- in this macro invocation | = help: enum variants can be `Variant`, `Variant = `, `Variant(Type, ..., TypeN)` or `Variant { fields: Types }` - = note: this error originates in the macro `test_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/issue-37234.stderr b/tests/ui/parser/macro/issue-37234.stderr index cd91ea441226a..2e8fecf81f7b4 100644 --- a/tests/ui/parser/macro/issue-37234.stderr +++ b/tests/ui/parser/macro/issue-37234.stderr @@ -1,13 +1,13 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found `""` --> $DIR/issue-37234.rs:3:19 | +LL | macro_rules! failed { +LL | () => {{ LL | let x = 5 ""; | ^^ expected one of `.`, `;`, `?`, `else`, or an operator ... LL | failed!(); | --------- in this macro invocation - | - = note: this error originates in the macro `failed` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/macro/lit-err-in-macro.stderr b/tests/ui/parser/macro/lit-err-in-macro.stderr index 08fe58643d40a..8661afc0aefc8 100644 --- a/tests/ui/parser/macro/lit-err-in-macro.stderr +++ b/tests/ui/parser/macro/lit-err-in-macro.stderr @@ -7,6 +7,8 @@ LL | f!("Foo"__); warning: `extern` declarations without an explicit ABI are deprecated --> $DIR/lit-err-in-macro.rs:3:9 | +LL | macro_rules! f { +LL | ($abi:literal) => { LL | extern $abi fn f() {} | ^^^^^^ help: explicitly specify the "C" ABI: `extern "C"` ... @@ -14,7 +16,6 @@ LL | f!("Foo"__); | ----------- in this macro invocation | = note: `#[warn(missing_abi)]` on by default - = note: this warning originates in the macro `f` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/parser/macro/macro-attr-recovery.stderr b/tests/ui/parser/macro/macro-attr-recovery.stderr index e1f8dccf1b8c9..bc292b293ef5a 100644 --- a/tests/ui/parser/macro/macro-attr-recovery.stderr +++ b/tests/ui/parser/macro/macro-attr-recovery.stderr @@ -13,6 +13,8 @@ LL + attr($($args:tt)*) { $($body:tt)* } => { error: attr: args="" body="struct S;" --> $DIR/macro-attr-recovery.rs:8:9 | +LL | macro_rules! attr { +... LL | / compile_error!(concat!( LL | | "attr: args=\"", LL | | stringify!($($args)*), @@ -24,8 +26,6 @@ LL | | )); ... LL | #[attr] | ------- in this attribute macro expansion - | - = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/parser/macro/macro-incomplete-parse.stderr b/tests/ui/parser/macro/macro-incomplete-parse.stderr index 096b5f718ae1c..17d49c66e0820 100644 --- a/tests/ui/parser/macro/macro-incomplete-parse.stderr +++ b/tests/ui/parser/macro/macro-incomplete-parse.stderr @@ -12,13 +12,12 @@ LL | ignored_item!(); error: expected one of `.`, `;`, `?`, `}`, or an operator, found `,` --> $DIR/macro-incomplete-parse.rs:10:14 | +LL | macro_rules! ignored_expr { LL | () => ( 1, | ^ expected one of `.`, `;`, `?`, `}`, or an operator ... LL | ignored_expr!(); | --------------- in this macro invocation - | - = note: this error originates in the macro `ignored_expr` (in Nightly builds, run with -Z macro-backtrace for more info) error: macro expansion ignores `,` and any tokens following --> $DIR/macro-incomplete-parse.rs:16:14 diff --git a/tests/ui/parser/macro/pub-item-macro.stderr b/tests/ui/parser/macro/pub-item-macro.stderr index 14f0b0908d1cb..c6d19cf819b41 100644 --- a/tests/ui/parser/macro/pub-item-macro.stderr +++ b/tests/ui/parser/macro/pub-item-macro.stderr @@ -1,6 +1,7 @@ error: can't qualify macro invocation with `pub` --> $DIR/pub-item-macro.rs:10:5 | +LL | macro_rules! pub_x { () => { LL | pub priv_x!(); | ^^^ ... @@ -8,7 +9,6 @@ LL | pub_x!(); | -------- in this macro invocation | = help: try adjusting the macro to put `pub` inside the invocation - = note: this error originates in the macro `pub_x` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the visibility | LL - pub priv_x!(); @@ -18,8 +18,15 @@ LL + priv_x!(); error[E0603]: static `x` is private --> $DIR/pub-item-macro.rs:20:23 | -LL | let y: u32 = foo::x; - | ^ private static +LL | / macro_rules! priv_x { +LL | | () => { +LL | | static x: u32 = 0; +LL | | }; +LL | | } + | |_- this error originates in the macro `priv_x` which comes from the expansion of the macro `pub_x` +... +LL | let y: u32 = foo::x; + | ^ private static | note: the static `x` is defined here --> $DIR/pub-item-macro.rs:5:9 @@ -29,7 +36,6 @@ LL | static x: u32 = 0; ... LL | pub_x!(); | -------- in this macro invocation - = note: this error originates in the macro `priv_x` which comes from the expansion of the macro `pub_x` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/parser/missing-semicolon.stderr b/tests/ui/parser/missing-semicolon.stderr index 4108cced366a6..fbd4a5985113c 100644 --- a/tests/ui/parser/missing-semicolon.stderr +++ b/tests/ui/parser/missing-semicolon.stderr @@ -1,13 +1,13 @@ error: expected one of `.`, `;`, `?`, `else`, or an operator, found keyword `let` --> $DIR/missing-semicolon.rs:3:12 | +LL | macro_rules! m { +LL | ($($e1:expr),*; $($e2:expr),*) => { LL | $( let x = $e1 )*; | ^^^ expected one of `.`, `;`, `?`, `else`, or an operator ... LL | fn main() { m!(0, 0; 0, 0); } | -------------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/mut-patterns.stderr b/tests/ui/parser/mut-patterns.stderr index 4d5b3e77c05db..d070ad1805f9d 100644 --- a/tests/ui/parser/mut-patterns.stderr +++ b/tests/ui/parser/mut-patterns.stderr @@ -161,13 +161,13 @@ LL + let W(mut a, W(mut b, W(ref c, W(mut d, B { mut f })))) error: expected identifier, found metavariable --> $DIR/mut-patterns.rs:48:21 | +LL | macro_rules! foo { +LL | ($p:pat) => { LL | let mut $p = 0; | ^^ expected identifier, found metavariable ... LL | foo!(x); | ------- in this macro invocation - | - = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 14 previous errors diff --git a/tests/ui/parser/recover/recover-pat-range-macro-span-overlap.stderr b/tests/ui/parser/recover/recover-pat-range-macro-span-overlap.stderr index 901a327980efa..502ab78a28383 100644 --- a/tests/ui/parser/recover/recover-pat-range-macro-span-overlap.stderr +++ b/tests/ui/parser/recover/recover-pat-range-macro-span-overlap.stderr @@ -1,6 +1,8 @@ error: expected a pattern range bound, found an expression --> $DIR/recover-pat-range-macro-span-overlap.rs:5:19 | +LL | macro_rules! m { +... LL | Bar = $value, | ___________________^ LL | | @@ -14,7 +16,6 @@ LL | m!(1); | ----- in this macro invocation | = note: arbitrary expressions are not allowed in patterns: - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/parser/recover/recover-range-pats.stderr b/tests/ui/parser/recover/recover-range-pats.stderr index 436dad620a98c..e93b180143c15 100644 --- a/tests/ui/parser/recover/recover-range-pats.stderr +++ b/tests/ui/parser/recover/recover-range-pats.stderr @@ -285,13 +285,14 @@ LL + if let ..=.3 = 0 {} error: range-to patterns with `...` are not allowed --> $DIR/recover-range-pats.rs:153:17 | +LL | macro_rules! mac { +... LL | let ...$e; | ^^^ ... LL | mac!(0); | ------- in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..=` instead | LL - let ...$e; @@ -301,6 +302,8 @@ LL + let ..=$e; error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:160:19 | +LL | macro_rules! mac { +... LL | let $e...; | ^^^ ... @@ -308,7 +311,6 @@ LL | mac!(0); | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..` instead | LL - let $e...; @@ -318,6 +320,8 @@ LL + let $e..; error[E0586]: inclusive range with no end --> $DIR/recover-range-pats.rs:162:19 | +LL | macro_rules! mac { +... LL | let $e..=; | ^^^ ... @@ -325,7 +329,6 @@ LL | mac!(0); | ------- in this macro invocation | = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`) - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `..` instead | LL - let $e..=; @@ -412,6 +415,8 @@ LL | if let X... .0 = 0 {} error: `...` range patterns are deprecated --> $DIR/recover-range-pats.rs:138:20 | +LL | macro_rules! mac2 { +... LL | let $e1...$e2; | ^^^ help: use `..=` for an inclusive range ... @@ -420,7 +425,6 @@ LL | mac2!(0, 1); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! = note: for more information, see - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0029]: only `char` and numeric types are allowed in range patterns --> $DIR/recover-range-pats.rs:19:12 @@ -611,6 +615,8 @@ LL | if let ....3 = 0 {} error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:136:17 | +LL | macro_rules! mac2 { +LL | ($e1:expr, $e2:expr) => { LL | let $e1..$e2; | ^^^^^^^^ patterns `i32::MIN..=-1_i32` and `1_i32..=i32::MAX` not covered ... @@ -620,11 +626,12 @@ LL | mac2!(0, 1); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:138:17 | +LL | macro_rules! mac2 { +... LL | let $e1...$e2; | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered ... @@ -634,11 +641,12 @@ LL | mac2!(0, 1); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:142:17 | +LL | macro_rules! mac2 { +... LL | let $e1..=$e2; | ^^^^^^^^^ patterns `i32::MIN..=-1_i32` and `2_i32..=i32::MAX` not covered ... @@ -648,11 +656,12 @@ LL | mac2!(0, 1); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:151:17 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | let ..$e; | ^^^^ pattern `0_i32..=i32::MAX` not covered ... @@ -662,11 +671,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:153:17 | +LL | macro_rules! mac { +... LL | let ...$e; | ^^^^^ pattern `1_i32..=i32::MAX` not covered ... @@ -676,11 +686,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:156:17 | +LL | macro_rules! mac { +... LL | let ..=$e; | ^^^^^ pattern `1_i32..=i32::MAX` not covered ... @@ -690,11 +701,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:158:17 | +LL | macro_rules! mac { +... LL | let $e..; | ^^^^ pattern `i32::MIN..=-1_i32` not covered ... @@ -704,11 +716,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:160:17 | +LL | macro_rules! mac { +... LL | let $e...; | ^^^^^ pattern `i32::MIN..=-1_i32` not covered ... @@ -718,11 +731,12 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0005]: refutable pattern in local binding --> $DIR/recover-range-pats.rs:162:17 | +LL | macro_rules! mac { +... LL | let $e..=; | ^^^^^ pattern `i32::MIN..=-1_i32` not covered ... @@ -732,7 +746,6 @@ LL | mac!(0); = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html = note: the matched value is of type `i32` - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 69 previous errors diff --git a/tests/ui/pattern/issue-92074-macro-ice.stderr b/tests/ui/pattern/issue-92074-macro-ice.stderr index 025592116e511..062cc10f87321 100644 --- a/tests/ui/pattern/issue-92074-macro-ice.stderr +++ b/tests/ui/pattern/issue-92074-macro-ice.stderr @@ -1,6 +1,7 @@ error: arbitrary expressions aren't allowed in patterns --> $DIR/issue-92074-macro-ice.rs:18:25 | +LL | macro_rules! make_vec { LL | () => { force_expr!(Vec::new()) } | ^^^^^^^^^^ ... @@ -8,11 +9,11 @@ LL | assert!(matches!(x, En::A(make_vec!()))); | ----------- in this macro invocation | = note: the `expr` fragment specifier forces the metavariable's content to be an expression - = note: this error originates in the macro `make_vec` (in Nightly builds, run with -Z macro-backtrace for more info) error: arbitrary expressions aren't allowed in patterns --> $DIR/issue-92074-macro-ice.rs:22:24 | +LL | macro_rules! make_pat { LL | () => { force_pat!(get_usize(), get_usize()) } | ^^^^^^^^^^^ ... @@ -20,11 +21,11 @@ LL | assert!(matches!(5, make_pat!())); | ----------- in this macro invocation | = note: the `expr` fragment specifier forces the metavariable's content to be an expression - = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) error: arbitrary expressions aren't allowed in patterns --> $DIR/issue-92074-macro-ice.rs:22:37 | +LL | macro_rules! make_pat { LL | () => { force_pat!(get_usize(), get_usize()) } | ^^^^^^^^^^^ ... @@ -32,7 +33,6 @@ LL | assert!(matches!(5, make_pat!())); | ----------- in this macro invocation | = note: the `expr` fragment specifier forces the metavariable's content to be an expression - = note: this error originates in the macro `make_pat` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/pattern/rest-pat-semantic-disallowed.stderr b/tests/ui/pattern/rest-pat-semantic-disallowed.stderr index d3985b830c74a..e795ac606ce74 100644 --- a/tests/ui/pattern/rest-pat-semantic-disallowed.stderr +++ b/tests/ui/pattern/rest-pat-semantic-disallowed.stderr @@ -1,6 +1,7 @@ error: `..` patterns are not allowed here --> $DIR/rest-pat-semantic-disallowed.rs:8:13 | +LL | macro_rules! mk_pat { LL | () => { .. } | ^^ ... @@ -8,7 +9,6 @@ LL | let mk_pat!(); | --------- in this macro invocation | = note: only allowed in tuple, tuple struct, and slice patterns - = note: this error originates in the macro `mk_pat` (in Nightly builds, run with -Z macro-backtrace for more info) error: `..` patterns are not allowed here --> $DIR/rest-pat-semantic-disallowed.rs:16:9 diff --git a/tests/ui/privacy/associated-item-privacy-inherent.stderr b/tests/ui/privacy/associated-item-privacy-inherent.stderr index f4d4ee459204d..8cb23cface4de 100644 --- a/tests/ui/privacy/associated-item-privacy-inherent.stderr +++ b/tests/ui/privacy/associated-item-privacy-inherent.stderr @@ -1,233 +1,229 @@ error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:13:21 | +LL | pub macro mac() { LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_nominal::mac!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:15:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_nominal::mac!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a priv_nominal::Pub) {priv_nominal::Pub::method}` is private --> $DIR/associated-item-privacy-inherent.rs:17:13 | +LL | pub macro mac() { +... LL | Pub.method(); | ^^^^^^ private type ... LL | priv_nominal::mac!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: associated constant `CONST` is private --> $DIR/associated-item-privacy-inherent.rs:19:9 | +LL | pub macro mac() { +... LL | Pub::CONST; | ^^^^^^^^^^ private associated constant ... LL | priv_nominal::mac!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `priv_nominal::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:37:21 | +LL | pub macro mac() { LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:39:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:41:13 | +LL | pub macro mac() { +... LL | Pub.method(loop {}); | ^^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:57:21 | +LL | pub macro mac() { LL | let value = Pub::method::; | ^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:59:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:61:9 | +LL | pub macro mac() { +... LL | Pub.method::(); | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:80:21 | +LL | pub macro mac() { LL | let value = ::method; | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:82:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:84:21 | +LL | pub macro mac() { +... LL | let value = Pub::method; | ^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:86:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:88:21 | +LL | pub macro mac() { +... LL | let value = ::static_method; | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:90:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:92:21 | +LL | pub macro mac() { +... LL | let value = Pub::static_method; | ^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:94:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:96:19 | +LL | pub macro mac() { +... LL | Pub(Priv).method(); | ^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:99:10 | +LL | pub macro mac() { +... LL | ::CONST; | ^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-inherent.rs:101:9 | +LL | pub macro mac() { +... LL | Pub::CONST; | ^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 21 previous errors diff --git a/tests/ui/privacy/associated-item-privacy-trait.stderr b/tests/ui/privacy/associated-item-privacy-trait.stderr index 4e9dfa4a83519..4dc96cc856c2a 100644 --- a/tests/ui/privacy/associated-item-privacy-trait.stderr +++ b/tests/ui/privacy/associated-item-privacy-trait.stderr @@ -1,332 +1,328 @@ error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:15:21 | +LL | pub macro mac() { LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a priv_trait::Pub) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:17:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a Self) {::method}` is private --> $DIR/associated-item-privacy-trait.rs:19:13 | +LL | pub macro mac() { +... LL | Pub.method(); | ^^^^^^ private type ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: associated constant `PrivTr::CONST` is private --> $DIR/associated-item-privacy-trait.rs:21:9 | +LL | pub macro mac() { +... LL | ::CONST; | ^^^^^^^^^^^^^^^^^^^^^^ private associated constant ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: associated type `PrivTr::AssocTy` is private --> $DIR/associated-item-privacy-trait.rs:23:16 | +LL | pub macro mac() { +... LL | let _: ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: associated type `PrivTr::AssocTy` is private --> $DIR/associated-item-privacy-trait.rs:25:34 | +LL | pub macro mac() { +... LL | pub type InSignatureTy = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^ private associated type ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-trait.rs:27:34 | +LL | pub macro mac() { +... LL | pub trait InSignatureTr: PrivTr {} | ^^^^^^ private trait ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-trait.rs:29:14 | +LL | pub macro mac() { +... LL | impl PrivTr for u8 {} | ^^^^^^ private trait ... LL | priv_trait::mac!(); | ------------------ in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:46:21 | +LL | pub macro mac() { LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:48:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_signature::Priv` is private --> $DIR/associated-item-privacy-trait.rs:50:13 | +LL | pub macro mac() { +... LL | Pub.method(loop {}); | ^^^^^^ private type ... LL | priv_signature::mac!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `priv_signature::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:67:21 | +LL | pub macro mac() { LL | let value = ::method::; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:69:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:71:9 | +LL | pub macro mac() { +... LL | Pub.method::(); | ^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_substs::mac!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:91:21 | +LL | pub macro mac() { LL | let value = ::method; | ^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:93:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:95:21 | +LL | pub macro mac() { +... LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:97:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:99:9 | +LL | pub macro mac() { +... LL | Pub.method(); | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:102:21 | +LL | pub macro mac() { +... LL | let value = >::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:104:9 | +LL | pub macro mac() { +... LL | value; | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:106:9 | +LL | pub macro mac() { +... LL | Priv.method(); | ^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:109:9 | +LL | pub macro mac() { +... LL | ::CONST; | ^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:111:9 | +LL | pub macro mac() { +... LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:113:9 | +LL | pub macro mac() { +... LL | >::CONST; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:117:30 | +LL | pub macro mac() { +... LL | let _: >::AssocTy; | ^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:119:17 | +LL | pub macro mac() { +... LL | let _: >::AssocTy; | ^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:122:35 | +LL | pub macro mac() { +... LL | pub type InSignatureTy1 = ::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:124:35 | +LL | pub macro mac() { +... LL | pub type InSignatureTy2 = >::AssocTy; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `priv_parent_substs::Priv` is private --> $DIR/associated-item-privacy-trait.rs:126:14 | +LL | pub macro mac() { +... LL | impl PubTr for u8 {} | ^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 30 previous errors diff --git a/tests/ui/privacy/associated-item-privacy-type-binding.stderr b/tests/ui/privacy/associated-item-privacy-type-binding.stderr index 52bfa3c2ab889..f51427abcfa05 100644 --- a/tests/ui/privacy/associated-item-privacy-type-binding.stderr +++ b/tests/ui/privacy/associated-item-privacy-type-binding.stderr @@ -1,178 +1,172 @@ error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:13 | +LL | pub macro mac1() { LL | let _: Box>; | ^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:11:16 | +LL | pub macro mac1() { LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:14:31 | +LL | pub macro mac1() { +... LL | type InSignatureTy2 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:16:37 | +LL | pub macro mac1() { +... LL | trait InSignatureTr2: PubTr {} | ^^^^^^^^^^^^ private trait ... LL | priv_trait::mac1!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac1` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:13 | +LL | pub macro mac2() { LL | let _: Box>; | ^ private trait ... LL | priv_trait::mac2!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:20:16 | +LL | pub macro mac2() { LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:23:31 | +LL | pub macro mac2() { +... LL | type InSignatureTy1 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `PrivTr` is private --> $DIR/associated-item-privacy-type-binding.rs:25:31 | +LL | pub macro mac2() { +... LL | trait InSignatureTr1: PrivTr {} | ^^^^^^^^^^^^^^^^^^^^ private trait ... LL | priv_trait::mac2!(); | ------------------- in this macro invocation - | - = note: this error originates in the macro `priv_trait::mac2` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:13 | +LL | pub macro mac() { LL | let _: Box>; | ^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:44:16 | +LL | pub macro mac() { LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:13 | +LL | pub macro mac() { +... LL | let _: Box>; | ^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:47:16 | +LL | pub macro mac() { +... LL | let _: Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:50:35 | +LL | pub macro mac() { +... LL | pub type InSignatureTy1 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:52:35 | +LL | pub macro mac() { +... LL | pub type InSignatureTy2 = Box>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:54:31 | +LL | pub macro mac() { +... LL | trait InSignatureTr1: PubTrWithParam {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `Priv` is private --> $DIR/associated-item-privacy-type-binding.rs:56:37 | +LL | pub macro mac() { +... LL | trait InSignatureTr2: PubTr {} | ^^^^^^^^^^^^ private type ... LL | priv_parent_substs::mac!(); | -------------------------- in this macro invocation - | - = note: this error originates in the macro `priv_parent_substs::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 16 previous errors diff --git a/tests/ui/privacy/private-inferred-type.stderr b/tests/ui/privacy/private-inferred-type.stderr index 0dfa799a4d95d..c63deda6d2a9c 100644 --- a/tests/ui/privacy/private-inferred-type.stderr +++ b/tests/ui/privacy/private-inferred-type.stderr @@ -109,68 +109,67 @@ LL | adjust::S1.method_s3(); error: type `fn() {priv_fn}` is private --> $DIR/private-inferred-type.rs:39:9 | +LL | pub macro m() { LL | priv_fn; | ^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `PrivEnum` is private --> $DIR/private-inferred-type.rs:41:9 | +LL | pub macro m() { +... LL | PrivEnum::Variant; | ^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn() {::method}` is private --> $DIR/private-inferred-type.rs:43:9 | +LL | pub macro m() { +... LL | ::method; | ^^^^^^^^^^^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> PrivTupleStruct {PrivTupleStruct}` is private --> $DIR/private-inferred-type.rs:45:9 | +LL | pub macro m() { +... LL | PrivTupleStruct; | ^^^^^^^^^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `fn(u8) -> PubTupleStruct {PubTupleStruct}` is private --> $DIR/private-inferred-type.rs:47:9 | +LL | pub macro m() { +... LL | PubTupleStruct; | ^^^^^^^^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: type `for<'a> fn(&'a Pub) {Pub::::priv_method}` is private --> $DIR/private-inferred-type.rs:49:18 | +LL | pub macro m() { +... LL | Pub(0u8).priv_method(); | ^^^^^^^^^^^ private type ... LL | m::m!(); | ------- in this macro invocation - | - = note: this error originates in the macro `m::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: trait `m::Trait` is private --> $DIR/private-inferred-type.rs:118:5 diff --git a/tests/ui/privacy/restricted/decl-macros.stderr b/tests/ui/privacy/restricted/decl-macros.stderr index c932bb5fe9416..9b2b3c5106fbf 100644 --- a/tests/ui/privacy/restricted/decl-macros.stderr +++ b/tests/ui/privacy/restricted/decl-macros.stderr @@ -1,24 +1,24 @@ error[E0742]: visibilities can only be restricted to ancestor modules --> $DIR/decl-macros.rs:6:13 | +LL | pub macro mac() { +LL | struct A {} LL | pub(self) struct B {} | ^^^^ ... LL | crate::m::mac!(); | ---------------- in this macro invocation - | - = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0742]: visibilities can only be restricted to ancestor modules --> $DIR/decl-macros.rs:7:16 | +LL | pub macro mac() { +... LL | pub(in crate::m) struct C {} | ^^^^^^^^ ... LL | crate::m::mac!(); | ---------------- in this macro invocation - | - = note: this error originates in the macro `crate::m::mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/proc-macro/derive-helper-shadowing.edition2015.stderr b/tests/ui/proc-macro/derive-helper-shadowing.edition2015.stderr index 921284cd54583..3a018bdcf0ad9 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.edition2015.stderr +++ b/tests/ui/proc-macro/derive-helper-shadowing.edition2015.stderr @@ -14,6 +14,8 @@ LL + use empty_helper; error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-shadowing.rs:17:11 | +LL | macro_rules! gen_helper_use { +LL | () => { LL | #[empty_helper] | ^^^^^^^^^^^^ ... @@ -21,7 +23,6 @@ LL | gen_helper_use!(); | ----------------- in this macro invocation | = note: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute - = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this attribute macro through its public re-export | LL + use empty_helper; diff --git a/tests/ui/proc-macro/derive-helper-shadowing.edition2018.stderr b/tests/ui/proc-macro/derive-helper-shadowing.edition2018.stderr index 1e430d154c3e3..a5c6ef25056ce 100644 --- a/tests/ui/proc-macro/derive-helper-shadowing.edition2018.stderr +++ b/tests/ui/proc-macro/derive-helper-shadowing.edition2018.stderr @@ -26,6 +26,8 @@ LL + use crate::empty_helper; error: cannot find attribute `empty_helper` in this scope --> $DIR/derive-helper-shadowing.rs:17:11 | +LL | macro_rules! gen_helper_use { +LL | () => { LL | #[empty_helper] | ^^^^^^^^^^^^ ... @@ -33,7 +35,6 @@ LL | gen_helper_use!(); | ----------------- in this macro invocation | = note: `empty_helper` is an attribute that can be used by the derive macro `Empty`, you might be missing a `derive` attribute - = note: this error originates in the macro `gen_helper_use` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this attribute macro through its public re-export | LL + use crate::empty_helper; diff --git a/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr b/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr index e13a0add8f13b..5238b26a6a74a 100644 --- a/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr +++ b/tests/ui/proc-macro/gen-macro-rules-hygiene.stderr @@ -6,8 +6,6 @@ LL | gen_macro_rules!(); ... LL | generated!(); | ------------ in this macro invocation - | - = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find value `local_use` in this scope --> $DIR/gen-macro-rules-hygiene.rs:13:1 @@ -23,7 +21,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | let local_use = 1; | ^^^^^^^^^ - = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) help: a local variable with a similar name exists | LL - gen_macro_rules!(); @@ -33,6 +30,8 @@ LL + local_def; error[E0425]: cannot find value `local_def` in this scope --> $DIR/gen-macro-rules-hygiene.rs:22:9 | +LL | gen_macro_rules!(); +... LL | local_def; | ^^^^^^^^^ not found in this scope | @@ -44,7 +43,6 @@ LL | gen_macro_rules!(); ... LL | generated!(); | ------------ in this macro invocation - = note: this error originates in the macro `generated` (in Nightly builds, run with -Z macro-backtrace for more info) help: a local variable with a similar name exists | LL - local_def; diff --git a/tests/ui/proc-macro/macro-rules-derive.stderr b/tests/ui/proc-macro/macro-rules-derive.stderr index 05ad9e559ad1c..5697d3db830d1 100644 --- a/tests/ui/proc-macro/macro-rules-derive.stderr +++ b/tests/ui/proc-macro/macro-rules-derive.stderr @@ -1,13 +1,13 @@ error[E0425]: cannot find type `MissingType` in this scope --> $DIR/macro-rules-derive.rs:10:20 | +LL | macro_rules! produce_it { +... LL | field: MissingType | ^^^^^^^^^^^ not found in this scope ... LL | produce_it!(MyName); | ------------------- in this macro invocation - | - = note: this error originates in the macro `produce_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/proc-macro/mixed-site-span.stderr b/tests/ui/proc-macro/mixed-site-span.stderr index 6557b0a904f3e..0c1aaaebba581 100644 --- a/tests/ui/proc-macro/mixed-site-span.stderr +++ b/tests/ui/proc-macro/mixed-site-span.stderr @@ -96,6 +96,8 @@ LL + with_crate!{krate call proc_macro_rules} error[E0432]: unresolved import `$crate::proc_macro_item` --> $DIR/mixed-site-span.rs:62:28 | +LL | macro_rules! test {() => { +LL | // crate::proc_macro_item LL | invoke_with_ident!{$crate input proc_macro_item} | ^^^^^^^^^^^^^--------------- | | @@ -104,7 +106,6 @@ LL | invoke_with_ident!{$crate input proc_macro_item} LL | test!(); | ------- in this macro invocation | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) help: a similar name exists in the module | LL - invoke_with_ident!{$crate input proc_macro_item} @@ -114,6 +115,8 @@ LL + invoke_with_ident!{$crate input proc_macro_rules} error[E0432]: unresolved import `$crate::proc_macro_item` --> $DIR/mixed-site-span.rs:63:21 | +LL | macro_rules! test {() => { +... LL | with_crate!{$crate input proc_macro_item} | ^^^^^^^^^^^^^--------------- | | @@ -122,7 +125,6 @@ LL | with_crate!{$crate input proc_macro_item} LL | test!(); | ------- in this macro invocation | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) help: a similar name exists in the module | LL - with_crate!{$crate input proc_macro_item} @@ -271,6 +273,8 @@ LL + token_site_span::TokenItem as _ error[E0432]: unresolved import `$crate::TokenItem` --> $DIR/mixed-site-span.rs:101:28 | +LL | macro_rules! test {() => { +LL | // crate::TokenItem LL | invoke_with_ident!{$crate input TokenItem} | ^^^^^^^^^^^^^--------- | | @@ -279,7 +283,6 @@ LL | invoke_with_ident!{$crate input TokenItem} LL | test!(); | ------- in this macro invocation | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct instead | LL - invoke_with_ident!{$crate input TokenItem} @@ -289,6 +292,8 @@ LL + invoke_with_ident!{token_site_span::TokenItem as _} error[E0432]: unresolved import `$crate::TokenItem` --> $DIR/mixed-site-span.rs:102:21 | +LL | macro_rules! test {() => { +... LL | with_crate!{$crate input TokenItem} | ^^^^^^^^^^^^^--------- | | @@ -297,7 +302,6 @@ LL | with_crate!{$crate input TokenItem} LL | test!(); | ------- in this macro invocation | - = note: this error originates in the macro `test` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider importing this struct instead | LL - with_crate!{$crate input TokenItem} diff --git a/tests/ui/proc-macro/parent-source-spans.stderr b/tests/ui/proc-macro/parent-source-spans.stderr index ffbeef8f2a944..5d496ab9136a6 100644 --- a/tests/ui/proc-macro/parent-source-spans.stderr +++ b/tests/ui/proc-macro/parent-source-spans.stderr @@ -1,46 +1,48 @@ error: first final: "hello" --> $DIR/parent-source-spans.rs:17:12 | -LL | three!($a, $b); - | ^^ +LL | / macro two($a:expr, $b:expr) { +LL | | three!($a, $b); + | | ^^ +... | +LL | | } + | |_- this error originates in the macro `two` which comes from the expansion of the macro `one` ... -LL | one!("hello", "world"); - | ---------------------- in this macro invocation - | - = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | one!("hello", "world"); + | ---------------------- in this macro invocation error: second final: "world" --> $DIR/parent-source-spans.rs:17:16 | -LL | three!($a, $b); - | ^^ +LL | / macro two($a:expr, $b:expr) { +LL | | three!($a, $b); + | | ^^ +... | +LL | | } + | |_- this error originates in the macro `two` which comes from the expansion of the macro `one` ... -LL | one!("hello", "world"); - | ---------------------- in this macro invocation - | - = note: this error originates in the macro `two` which comes from the expansion of the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | one!("hello", "world"); + | ---------------------- in this macro invocation error: first parent: "hello" --> $DIR/parent-source-spans.rs:11:5 | +LL | macro one($a:expr, $b:expr) { LL | two!($a, $b); | ^^^^^^^^^^^^ ... LL | one!("hello", "world"); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) error: second parent: "world" --> $DIR/parent-source-spans.rs:11:5 | +LL | macro one($a:expr, $b:expr) { LL | two!($a, $b); | ^^^^^^^^^^^^ ... LL | one!("hello", "world"); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `one` (in Nightly builds, run with -Z macro-backtrace for more info) error: first grandparent: "hello" --> $DIR/parent-source-spans.rs:37:5 @@ -69,24 +71,22 @@ LL | one!("hello", "world"); error: first final: "yay" --> $DIR/parent-source-spans.rs:17:12 | +LL | macro two($a:expr, $b:expr) { LL | three!($a, $b); | ^^ ... LL | two!("yay", "rust"); | ------------------- in this macro invocation - | - = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) error: second final: "rust" --> $DIR/parent-source-spans.rs:17:16 | +LL | macro two($a:expr, $b:expr) { LL | three!($a, $b); | ^^ ... LL | two!("yay", "rust"); | ------------------- in this macro invocation - | - = note: this error originates in the macro `two` (in Nightly builds, run with -Z macro-backtrace for more info) error: first parent: "yay" --> $DIR/parent-source-spans.rs:43:5 diff --git a/tests/ui/proc-macro/weird-hygiene.stderr b/tests/ui/proc-macro/weird-hygiene.stderr index aa3ef9556eb16..a3c1e7b7671e6 100644 --- a/tests/ui/proc-macro/weird-hygiene.stderr +++ b/tests/ui/proc-macro/weird-hygiene.stderr @@ -17,6 +17,8 @@ LL | let hidden_ident = "Hello1"; error[E0425]: cannot find value `hidden_ident` in this scope --> $DIR/weird-hygiene.rs:35:13 | +LL | macro_rules! invoke_it { +... LL | hidden_ident | ^^^^^^^^^^^^ not found in this scope ... @@ -28,7 +30,6 @@ help: an identifier with the same name exists, but is not accessible due to macr | LL | let hidden_ident = "Hello1"; | ^^^^^^^^^^^^ - = note: this error originates in the macro `invoke_it` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr b/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr index 0c9d89dd009ec..4755ee557b742 100644 --- a/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr +++ b/tests/ui/reborrow/coerce-shared-decl-macro-hygiene.stderr @@ -1,6 +1,8 @@ error: implementing `CoerceShared` currently requires source and target to have at most one non-ZST reborrow data field --> $DIR/coerce-shared-decl-macro-hygiene.rs:24:5 | +LL | macro my_macro($field:ident) { +... LL | impl<'a> CoerceShared> for MyMut<'a> {} | ^^^^^^^^^^^^^^^^^^^^^^---------^^^^^^---------^^^ | | | | @@ -12,7 +14,6 @@ LL | my_macro!(field); | ---------------- in this macro invocation | = note: this is a temporary restriction until `CoerceShared` lowering supports non-trivially memcpy-compatible field layouts - = note: this error originates in the macro `my_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/resolve/decl-macro-use-no-ice.stderr b/tests/ui/resolve/decl-macro-use-no-ice.stderr index 619a5737090e0..1f47f757f6153 100644 --- a/tests/ui/resolve/decl-macro-use-no-ice.stderr +++ b/tests/ui/resolve/decl-macro-use-no-ice.stderr @@ -1,6 +1,7 @@ error[E0364]: `f` is private, and cannot be re-exported --> $DIR/decl-macro-use-no-ice.rs:13:13 | +LL | pub macro m() { LL | use f; | ^ ... @@ -15,7 +16,6 @@ LL | use f; ... LL | foo::m!(); | --------- in this macro invocation - = note: this error originates in the macro `foo::m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr index c477e94ceb54f..678efdcaf6b22 100644 --- a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr +++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr @@ -79,6 +79,8 @@ LL + let _ = foo::bar; error[E0423]: cannot find value `Cell` in module `::std::cell` --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:22 | +LL | macro_rules! Type { +LL | () => { LL | ::std::cell::Cell | ^^^^ ... @@ -86,7 +88,6 @@ LL | Type!().get(); | ------- in this macro invocation | = note: a struct named `::std::cell::Cell` exists in another namespace - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type!().get(); @@ -96,6 +97,8 @@ LL + ::get(); error[E0423]: cannot find value `Cell` in module `::std::cell` --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:22 | +LL | macro_rules! Type { +LL | () => { LL | ::std::cell::Cell | ^^^^ ... @@ -103,7 +106,6 @@ LL | Type! {}.get; | -------- in this macro invocation | = note: a struct named `::std::cell::Cell` exists in another namespace - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type! {}.get; @@ -113,6 +115,8 @@ LL + ::get; error[E0423]: cannot find value `Alias` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 | +LL | macro_rules! Type { +... LL | Alias | ^^^^^ ... @@ -120,7 +124,6 @@ LL | Type!(alias).get(); | ------------ in this macro invocation | = note: a type alias named `Alias` exists in another namespace - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type!(alias).get(); @@ -130,6 +133,8 @@ LL + ::get(); error[E0423]: cannot find value `Alias` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 | +LL | macro_rules! Type { +... LL | Alias | ^^^^^ ... @@ -137,7 +142,6 @@ LL | Type! {alias}.get; | ------------- in this macro invocation | = note: a type alias named `Alias` exists in another namespace - = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type! {alias}.get; @@ -147,6 +151,8 @@ LL + ::get; error[E0423]: cannot find value `Vec` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:52:9 | +LL | macro_rules! create { +LL | (type method) => { LL | Vec.new() | ^^^ ... @@ -154,7 +160,6 @@ LL | let _ = create!(type method); | -------------------- in this macro invocation | = note: a struct named `Vec` exists in another namespace - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Vec.new() @@ -164,6 +169,8 @@ LL + Vec::new() error[E0423]: cannot find value `Vec` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:57:9 | +LL | macro_rules! create { +... LL | Vec.new | ^^^ ... @@ -171,7 +178,6 @@ LL | let _ = create!(type field); | ------------------- in this macro invocation | = note: a struct named `Vec` exists in another namespace - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Vec.new @@ -181,14 +187,19 @@ LL + Vec::new error[E0423]: cannot find value `Cell` in module `::std::cell` --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:22 | -LL | ::std::cell::Cell - | ^^^^ +LL | / macro_rules! Type { +LL | | () => { +LL | | ::std::cell::Cell + | | ^^^^ +... | +LL | | }; +LL | | } + | |_- this error originates in the macro `Type` which comes from the expansion of the macro `create` ... -LL | let _ = create!(macro method); - | --------------------- in this macro invocation +LL | let _ = create!(macro method); + | --------------------- in this macro invocation | = note: a struct named `::std::cell::Cell` exists in another namespace - = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type!().new(0) @@ -198,14 +209,21 @@ LL + ::new(0) error[E0423]: cannot find value `Alias` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9 | -LL | Alias - | ^^^^^ +LL | / macro_rules! Type { +LL | | () => { +LL | | ::std::cell::Cell +... | +LL | | Alias + | | ^^^^^ +... | +LL | | }; +LL | | } + | |_- this error originates in the macro `Type` which comes from the expansion of the macro `create` ... -LL | let _ = create!(macro method alias); - | --------------------------- in this macro invocation +LL | let _ = create!(macro method alias); + | --------------------------- in this macro invocation | = note: a type alias named `Alias` exists in another namespace - = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Type!(alias).new(0) @@ -231,6 +249,8 @@ LL + $Ty::foo error[E0423]: cannot find value `Alias` in this scope --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:79:9 | +LL | macro_rules! check_ident { +LL | ($Ident:ident) => { LL | Alias.$Ident | ^^^^^ ... @@ -238,7 +258,6 @@ LL | let _ = check_ident!(foo); | ----------------- in this macro invocation | = note: a type alias named `Alias` exists in another namespace - = note: this error originates in the macro `check_ident` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Alias.$Ident diff --git a/tests/ui/resolve/ice-inconsistent-resolution-149821.stderr b/tests/ui/resolve/ice-inconsistent-resolution-149821.stderr index cd75a2f3e19b7..a46d643ff9edc 100644 --- a/tests/ui/resolve/ice-inconsistent-resolution-149821.stderr +++ b/tests/ui/resolve/ice-inconsistent-resolution-149821.stderr @@ -1,13 +1,13 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/ice-inconsistent-resolution-149821.rs:10:9 | +LL | macro_rules! define_other_core { +LL | () => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core! {} | --------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/resolve/ice-on-shadowing-std-with-macro.stderr b/tests/ui/resolve/ice-on-shadowing-std-with-macro.stderr index 8bdf809775516..fb86d34eb0f25 100644 --- a/tests/ui/resolve/ice-on-shadowing-std-with-macro.stderr +++ b/tests/ui/resolve/ice-on-shadowing-std-with-macro.stderr @@ -1,13 +1,13 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> $DIR/ice-on-shadowing-std-with-macro.rs:16:9 | +LL | macro_rules! define_other_core { +LL | () => { LL | extern crate core as std; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core! {} | --------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: cannot find `collections` in `std` --> $DIR/ice-on-shadowing-std-with-macro.rs:8:14 diff --git a/tests/ui/resolve/issue-100365.stderr b/tests/ui/resolve/issue-100365.stderr index d1dd5870f193a..96a14794606be 100644 --- a/tests/ui/resolve/issue-100365.stderr +++ b/tests/ui/resolve/issue-100365.stderr @@ -40,6 +40,8 @@ LL + let _ = Into::<()>::into; error[E0423]: cannot find value `Iterator` in module `::std::iter` --> $DIR/issue-100365.rs:17:22 | +LL | macro_rules! Trait { +LL | () => { LL | ::std::iter::Iterator | ^^^^^^^^ not found in `::std::iter` ... @@ -47,11 +49,12 @@ LL | Trait!().map(std::convert::identity); // no `help` here! | -------- in this macro invocation | = note: a trait named `::std::iter::Iterator` exists in another namespace - = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0423]: cannot find value `Iterator` in module `::std::iter` --> $DIR/issue-100365.rs:17:22 | +LL | macro_rules! Trait { +LL | () => { LL | ::std::iter::Iterator | ^^^^^^^^ not found in `::std::iter` ... @@ -59,11 +62,12 @@ LL | Trait!().map; // no `help` here! | -------- in this macro invocation | = note: a trait named `::std::iter::Iterator` exists in another namespace - = note: this error originates in the macro `Trait` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0423]: cannot find value `Into` in this scope --> $DIR/issue-100365.rs:25:9 | +LL | macro_rules! create { +LL | () => { LL | Into::.into("") | ^^^^ ... @@ -71,7 +75,6 @@ LL | let _ = create!(); | --------- in this macro invocation | = note: a trait named `Into` exists in another namespace - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - Into::.into("") diff --git a/tests/ui/resolve/issue-82865.stderr b/tests/ui/resolve/issue-82865.stderr index 198f7f8e32aa4..a41267942f8b2 100644 --- a/tests/ui/resolve/issue-82865.stderr +++ b/tests/ui/resolve/issue-82865.stderr @@ -12,13 +12,12 @@ LL + extern crate x; error[E0599]: no associated function or constant named `z` found for struct `Box<_, _>` in the current scope --> $DIR/issue-82865.rs:9:10 | +LL | macro mac () { LL | Box::z | ^ associated function or constant not found in `Box<_, _>` ... LL | mac!(); | ------ in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/open-ns-9.stderr b/tests/ui/resolve/open-ns-9.stderr index 675f487823e55..11247471142af 100644 --- a/tests/ui/resolve/open-ns-9.stderr +++ b/tests/ui/resolve/open-ns-9.stderr @@ -3,6 +3,8 @@ error[E0659]: `my_api` is ambiguous | LL | use my_api::utils::get_u32; | ^^^^^^ ambiguous name +... +LL | macro_rules! define { | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `my_api` could refer to a namespaced crate passed with `--extern` @@ -20,7 +22,6 @@ LL | | } LL | define!(); | --------- in this macro invocation = help: use `crate::my_api` to refer to this module unambiguously - = note: this error originates in the macro `define` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/resolve/suggestions/suggest-path-instead-of-mod-dot-item.stderr b/tests/ui/resolve/suggestions/suggest-path-instead-of-mod-dot-item.stderr index 9a7045617eebf..353eea3f25927 100644 --- a/tests/ui/resolve/suggestions/suggest-path-instead-of-mod-dot-item.stderr +++ b/tests/ui/resolve/suggestions/suggest-path-instead-of-mod-dot-item.stderr @@ -153,6 +153,8 @@ LL + a::I() error[E0423]: cannot find value `a` in this scope --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 | +LL | macro_rules! module { +LL | () => { LL | a | ^ not found in this scope ... @@ -160,11 +162,12 @@ LL | module!().g::<()>(); // no `help` here! | --------- in this macro invocation | = note: a module named `a` exists in another namespace - = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0423]: cannot find value `a` in this scope --> $DIR/suggest-path-instead-of-mod-dot-item.rs:72:9 | +LL | macro_rules! module { +LL | () => { LL | a | ^ not found in this scope ... @@ -172,11 +175,12 @@ LL | module!().g; // no `help` here! | --------- in this macro invocation | = note: a module named `a` exists in another namespace - = note: this error originates in the macro `module` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0423]: cannot find value `a` in this scope --> $DIR/suggest-path-instead-of-mod-dot-item.rs:80:9 | +LL | macro_rules! create { +LL | (method) => { LL | a.f() | ^ ... @@ -184,7 +188,6 @@ LL | let _ = create!(method); | --------------- in this macro invocation | = note: a module named `a` exists in another namespace - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - a.f() @@ -194,6 +197,8 @@ LL + a::f() error[E0423]: cannot find value `a` in this scope --> $DIR/suggest-path-instead-of-mod-dot-item.rs:85:9 | +LL | macro_rules! create { +... LL | a.f | ^ ... @@ -201,7 +206,6 @@ LL | let _ = create!(field); | -------------- in this macro invocation | = note: a module named `a` exists in another namespace - = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the path separator to refer to an item | LL - a.f diff --git a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr index 877995dfe1266..86981860677bc 100644 --- a/tests/ui/return/return-from-residual-sugg-issue-125997.stderr +++ b/tests/ui/return/return-from-residual-sugg-issue-125997.stderr @@ -86,6 +86,8 @@ LL + Ok(()) error[E0277]: the `?` operator can only be used in a function that returns `Result` or `Option` (or another type that implements `FromResidual`) --> $DIR/return-from-residual-sugg-issue-125997.rs:23:52 | +LL | macro_rules! mac { +LL | () => { LL | fn test3() { | ---------- this function should return `Result` or `Option` to accept `?` LL | let mut _file = File::create("foo.txt")?; @@ -94,7 +96,6 @@ LL | let mut _file = File::create("foo.txt")?; LL | mac!(); | ------ in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider adding return type | LL ~ fn test3() -> Result<(), Box> { diff --git a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr index eda88c15f7beb..54ea8f8a22006 100644 --- a/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr +++ b/tests/ui/rfcs/rfc-2294-if-let-guard/macro-expanded.stderr @@ -1,6 +1,7 @@ error: expected expression, found `let` statement --> $DIR/macro-expanded.rs:4:20 | +LL | macro_rules! m { LL | ($e:expr) => { let Some(x) = $e } | ^^^ ... @@ -8,7 +9,6 @@ LL | () if m!(Some(5)) => {} | ----------- in this macro invocation | = note: only supported directly in conditions of `if` and `while` expressions - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr index d684911be3975..cda31ed346f28 100644 --- a/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-macro.stderr @@ -19,101 +19,101 @@ LL | struct BarWhere<'a, 'b> where 'b: 'a { error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:41:30 | +LL | macro_rules! m { +LL | ('b: 'a) => { LL | struct Foo<'a, 'b: 'a>(&'a &'b ()); | ^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:43:44 | +LL | macro_rules! m { +... LL | struct Bar<'a, 'b>(&'a &'b ()) where 'b: 'a; | ^^^^^^^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:45:61 | +LL | macro_rules! m { +... LL | struct Baz<'a, 'b>(&'a &'b ()) where (): Sized, 'b: 'a; | ^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:55:30 | +LL | macro_rules! m { +LL | ($b:lifetime: 'a) => { LL | struct Foo<'a, $b: 'a>(&'a &$b ()); | ^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:57:44 | +LL | macro_rules! m { +... LL | struct Bar<'a, $b>(&'a &$b ()) where $b: 'a; | ^^^^^^^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:59:61 | +LL | macro_rules! m { +... LL | struct Baz<'a, $b>(&'a &$b ()) where (): Sized, $b: 'a; | ^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:117:44 | +LL | macro_rules! m { +... LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; | ^^^^^^^^^^^^^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:119:61 | +LL | macro_rules! m { +... LL | struct Baz<$a, $b>(&$a &$b ()) where (): Sized, $b $colon $a; | ^^^^^^^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:132:44 | +LL | macro_rules! m { +... LL | struct Bar<$a, $b>(&$a &$b ()) where $b $colon $a; | ^^^^^^^^^^^^^^^^^^ help: remove this bound ... LL | m!('b: 'a); | ---------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-macro.rs:134:61 diff --git a/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr index 1f4190665b9b0..b2d4c3d035890 100644 --- a/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr +++ b/tests/ui/rust-2018/edition-lint-inter-outlives/edition-lint-infer-outlives-multispan.stderr @@ -822,39 +822,41 @@ LL + union BeeWhereAyTeeYooWhereOutlivesAyIsDebugBee<'a, 'b, T, U> where U: error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-multispan.rs:372:38 | +LL | macro_rules! m { +LL | ($($name:ident)+) => { LL | struct Inline<'a, $($name: 'a,)+>(&'a ($($name,)+)); | ^^^^ help: remove these bounds ... LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15); | --------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-multispan.rs:374:64 | +LL | macro_rules! m { +... LL | struct FullWhere<'a, $($name,)+>(&'a ($($name,)+)) where $($name: 'a,)+; | ^^^^^^^^^^^^^^^^^^ help: remove these bounds ... LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15); | --------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-multispan.rs:376:86 | +LL | macro_rules! m { +... LL | struct PartialWhere<'a, $($name,)+>(&'a ($($name,)+)) where (): Sized, $($name: 'a,)+; | ^^^^^^^^^ help: remove these bounds ... LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15); | --------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: outlives requirements can be inferred --> $DIR/edition-lint-infer-outlives-multispan.rs:381:19 | +LL | macro_rules! m { +... LL | $($name: 'a, $name: 'a, )+ | ^^^^^^^^^ ^^^^^^^^^ LL | $($name: 'a, $name: 'a, )+; @@ -863,7 +865,6 @@ LL | $($name: 'a, $name: 'a, )+; LL | m!(T0 T1 T2 T3 T4 T5 T6 T7 T8 T9 T10 T11 T12 T13 T14 T15); | --------------------------------------------------------- in this macro invocation | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove these bounds | LL ~ $(, , )+ diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr index f2536c1a1e988..c3fadacc25496 100644 --- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros-nested.stderr @@ -3,6 +3,8 @@ error[E0659]: `std` is ambiguous | LL | pub use std::io; | ^^^ ambiguous name +... +LL | macro_rules! m { | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `std` could refer to a built-in crate @@ -18,7 +20,6 @@ LL | | } LL | m!(); | ---- in this macro invocation = help: use `self::std` to refer to this module unambiguously - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr index 3400183df6f41..0b70e98627372 100644 --- a/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr +++ b/tests/ui/rust-2018/uniform-paths/ambiguity-macros.stderr @@ -3,6 +3,8 @@ error[E0659]: `std` is ambiguous | LL | use std::io; | ^^^ ambiguous name +... +LL | macro_rules! m { | = note: ambiguous because of a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution = note: `std` could refer to a built-in crate @@ -18,7 +20,6 @@ LL | | } LL | m!(); | ---- in this macro invocation = help: use `crate::std` to refer to this module unambiguously - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr index f03842139f0b8..eac3e1331e984 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-fix.stderr @@ -19,6 +19,8 @@ LL | tt!([unsafe(no_mangle)]); error: unsafe attribute used without unsafe --> $DIR/unsafe-attributes-fix.rs:14:11 | +LL | macro_rules! ident { +LL | ($e:ident) => { LL | #[$e] | ^^ usage of unsafe attribute ... @@ -27,7 +29,6 @@ LL | ident!(no_mangle); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see - = note: this error originates in the macro `ident` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap the attribute in `unsafe(...)` | LL | #[unsafe($e)] @@ -62,6 +63,8 @@ LL | meta2!(unsafe(export_name = "baw")); error: unsafe attribute used without unsafe --> $DIR/unsafe-attributes-fix.rs:23:11 | +LL | macro_rules! ident2 { +LL | ($e:ident, $l:literal) => { LL | #[$e = $l] | ^^ usage of unsafe attribute ... @@ -70,7 +73,6 @@ LL | ident2!(export_name, "bars"); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see - = note: this error originates in the macro `ident2` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap the attribute in `unsafe(...)` | LL | #[unsafe($e = $l)] @@ -79,6 +81,8 @@ LL | #[unsafe($e = $l)] error: unsafe attribute used without unsafe --> $DIR/unsafe-attributes-fix.rs:46:26 | +LL | macro_rules! with_cfg_attr { +LL | () => { LL | #[cfg_attr(true, link_section = "__TEXT,__custom")] | ^^^^^^^^^^^^ usage of unsafe attribute ... @@ -87,7 +91,6 @@ LL | with_cfg_attr!(); | = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2024! = note: for more information, see - = note: this error originates in the macro `with_cfg_attr` (in Nightly builds, run with -Z macro-backtrace for more info) help: wrap the attribute in `unsafe(...)` | LL | #[cfg_attr(true, unsafe(link_section = "__TEXT,__custom"))] diff --git a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr index fa36b148bf3de..a65ccd29afe5a 100644 --- a/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr +++ b/tests/ui/rust-2024/unsafe-attributes/unsafe-attributes-from-pm-in-2024.stderr @@ -30,8 +30,6 @@ LL | unsafe_attributes_pm_in_2024::macro_rules_missing_unsafe!(); LL | LL | make_fn!(); | ---------- in this macro invocation - | - = note: this error originates in the macro `make_fn` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 4 previous errors diff --git a/tests/ui/simd/not-out-of-bounds.stderr b/tests/ui/simd/not-out-of-bounds.stderr index d5bcd15d97d6c..9b3b3028ff716 100644 --- a/tests/ui/simd/not-out-of-bounds.stderr +++ b/tests/ui/simd/not-out-of-bounds.stderr @@ -1,68 +1,68 @@ error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(2, u8x2, simd_shuffle); | ------------------------------------------ in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 8) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(4, u8x4, simd_shuffle); | ------------------------------------------ in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 16) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(8, u8x8, simd_shuffle); | ------------------------------------------ in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 32) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(16, u8x16, simd_shuffle); | -------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 64) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(32, u8x32, simd_shuffle); | -------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 128) --> $DIR/not-out-of-bounds.rs:53:21 | +LL | macro_rules! test_shuffle_lanes { +... LL | $y(vec1, vec2, IDX) | ^^^^^^^^^^^^^^^^^^^ ... LL | test_shuffle_lanes!(64, u8x64, simd_shuffle); | -------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `test_shuffle_lanes` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0511]: invalid monomorphization of `simd_shuffle` intrinsic: SIMD index #0 is out of bounds (limit 4) --> $DIR/not-out-of-bounds.rs:78:23 diff --git a/tests/ui/span/macro-span-caller-replacement.stderr b/tests/ui/span/macro-span-caller-replacement.stderr index 43be48a9e362e..00cb6938b0508 100644 --- a/tests/ui/span/macro-span-caller-replacement.stderr +++ b/tests/ui/span/macro-span-caller-replacement.stderr @@ -12,6 +12,8 @@ LL | macro_with_format!(); error[E0308]: mismatched types --> $DIR/macro-span-caller-replacement.rs:7:17 | +LL | macro_rules! macro_with_format { () => { +LL | fn check_5(arg : usize) -> String { LL | let s : &str; | ---- expected due to this type ... @@ -21,7 +23,6 @@ LL | s = String::new(); LL | macro_with_format!(); | -------------------- in this macro invocation | - = note: this error originates in the macro `macro_with_format` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider borrowing here | LL | s = &String::new(); diff --git a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr index 9016056b383f2..cadab6975fc22 100644 --- a/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr +++ b/tests/ui/suggestions/let-binding-init-expr-as-ty.stderr @@ -180,13 +180,13 @@ LL + let x = vec![]; error: expected type, found associated function call --> $DIR/let-binding-init-expr-as-ty.rs:37:23 | +LL | macro_rules! make { +LL | ($pat:pat) => { LL | let $pat: Vec::new(); | ^^^^^^^^^^ ... LL | make!(_); | -------- in this macro invocation - | - = note: this error originates in the macro `make` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 15 previous errors diff --git a/tests/ui/suggestions/suggest-ref-macro.stderr b/tests/ui/suggestions/suggest-ref-macro.stderr index 2a52c1e244502..9bb26f7f5ab3a 100644 --- a/tests/ui/suggestions/suggest-ref-macro.stderr +++ b/tests/ui/suggestions/suggest-ref-macro.stderr @@ -17,6 +17,8 @@ LL | #[hello] error[E0308]: mismatched types --> $DIR/suggest-ref-macro.rs:16:11 | +LL | macro_rules! bla { +LL | () => { LL | x(123); | - ^^^ expected `&mut i32`, found integer | | @@ -30,7 +32,6 @@ note: function defined here | LL | fn x(_: &mut i32) {} | ^ ----------- - = note: this error originates in the macro `bla` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider mutably borrowing here | LL | x(&mut 123); diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.stderr b/tests/ui/symbol-names/const-generics-structural-demangling.stderr index 3ec255b3e2359..19deb1af31418 100644 --- a/tests/ui/symbol-names/const-generics-structural-demangling.stderr +++ b/tests/ui/symbol-names/const-generics-structural-demangling.stderr @@ -127,35 +127,35 @@ LL | #[rustc_dump_symbol_name] error: symbol-name(_RMsd_CsCRATE_HASH_1cINtB_4Bar_KVNtB_3BarS1xh7b_s_1xt1000_EE) --> $DIR/const-generics-structural-demangling.rs:93:5 | +LL | macro duplicate_field_name_test($x:ident) { +... LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); | ----------------------------- in this macro invocation - | - = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) error: demangling(>) --> $DIR/const-generics-structural-demangling.rs:93:5 | +LL | macro duplicate_field_name_test($x:ident) { +... LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); | ----------------------------- in this macro invocation - | - = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) error: demangling-alt(>) --> $DIR/const-generics-structural-demangling.rs:93:5 | +LL | macro duplicate_field_name_test($x:ident) { +... LL | #[rustc_dump_symbol_name] | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | duplicate_field_name_test!(x); | ----------------------------- in this macro invocation - | - = note: this error originates in the macro `duplicate_field_name_test` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 24 previous errors diff --git a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr index 383936b9df155..c3e0b2ce2a890 100644 --- a/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr +++ b/tests/ui/traits/const-traits/macro-const-trait-bound-theoretical-regression.stderr @@ -1,46 +1,42 @@ error: ty --> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { impl const Trait } | -------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error: ty --> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { dyn const Trait } | ------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error: ty --> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { impl [const] Trait } | ---------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error: ty --> $DIR/macro-const-trait-bound-theoretical-regression.rs:11:19 | +LL | macro_rules! demo { LL | ($ty:ty) => { compile_error!("ty"); }; // KEEP THIS RULE FIRST AND AS IS! | ^^^^^^^^^^^^^^^^^^^^ ... LL | demo! { dyn [const] Trait } | --------------------------- in this macro invocation - | - = note: this error originates in the macro `demo` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0658]: const trait impls are experimental --> $DIR/macro-const-trait-bound-theoretical-regression.rs:26:14 diff --git a/tests/ui/tuple/tuple-struct-fields/test2.stderr b/tests/ui/tuple/tuple-struct-fields/test2.stderr index 53706eb90bbb7..73106d7c01b05 100644 --- a/tests/ui/tuple/tuple-struct-fields/test2.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test2.stderr @@ -1,6 +1,8 @@ error: expected one of `)` or `,`, found `(` --> $DIR/test2.rs:5:26 | +LL | macro_rules! define_struct { +... LL | struct S3(pub $t ()); | -^ expected one of `)` or `,` | | @@ -8,8 +10,6 @@ LL | struct S3(pub $t ()); ... LL | define_struct! { (foo) } | ------------------------ in this macro invocation - | - = note: this error originates in the macro `define_struct` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `foo` in this scope --> $DIR/test2.rs:11:23 diff --git a/tests/ui/tuple/tuple-struct-fields/test3.stderr b/tests/ui/tuple/tuple-struct-fields/test3.stderr index 6a30e4ba5da2a..455956ffe2d5f 100644 --- a/tests/ui/tuple/tuple-struct-fields/test3.stderr +++ b/tests/ui/tuple/tuple-struct-fields/test3.stderr @@ -1,6 +1,8 @@ error: expected one of `)` or `,`, found `(` --> $DIR/test3.rs:5:27 | +LL | macro_rules! define_struct { +... LL | struct S3(pub($t) ()); | -^ expected one of `)` or `,` | | @@ -8,8 +10,6 @@ LL | struct S3(pub($t) ()); ... LL | define_struct! { foo } | ---------------------- in this macro invocation - | - = note: this error originates in the macro `define_struct` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0425]: cannot find type `foo` in this scope --> $DIR/test3.rs:11:22 diff --git a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr index 1a3848bbcf58d..9e1ee9300ed27 100644 --- a/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr +++ b/tests/ui/type/type-check/issue-88577-check-fn-with-more-than-65535-arguments.stderr @@ -1,13 +1,13 @@ error: function can not have more than 65535 arguments --> $DIR/issue-88577-check-fn-with-more-than-65535-arguments.rs:6:17 | +LL | macro_rules! many_args { +... LL | fn _f($($t: ()),*) {} | ^^^^^^ ... LL | many_args!{[_]########## ######} | -------------------------------- in this macro invocation - | - = note: this error originates in the macro `many_args` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr index cb7666657ef4a..8b89bdf93d04a 100644 --- a/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr +++ b/tests/ui/typeck/issue-116473-ice-wrong-span-variant-args.stderr @@ -1,6 +1,7 @@ error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:51 | +LL | macro_rules! recursive_tt { LL | () => (recursive_tt!(VariantB)); | -------- not allowed on this type LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -10,7 +11,6 @@ LL | recursive_tt!(); | --------------- in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -20,6 +20,8 @@ LL + ($variant:tt) => (if let EnumUnit::::$variant {} = 5 { true } error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:15:30 | +LL | macro_rules! recursive_tt { +LL | () => (recursive_tt!(VariantB)); LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` | | @@ -30,11 +32,11 @@ LL | recursive_tt!(); | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `recursive_tt` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:54 | +LL | macro_rules! recursive_ident { LL | () => (recursive_ident!(VariantB)); | -------- not allowed on this type LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -44,7 +46,6 @@ LL | recursive_ident!(); | ------------------ in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -54,6 +55,8 @@ LL + ($variant:ident) => (if let EnumUnit::::$variant {} = 5 { tru error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:25:33 | +LL | macro_rules! recursive_ident { +LL | () => (recursive_ident!(VariantB)); LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` | | @@ -64,22 +67,24 @@ LL | recursive_ident!(); | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `recursive_ident` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:51 | -LL | () => (nested2_tt!(VariantB)); - | -------- not allowed on this type +LL | () => (nested2_tt!(VariantB)); + | -------- not allowed on this type ... -LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); - | ^^^ ^^^ type argument not allowed +LL | / macro_rules! nested2_tt { +LL | | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | | ^^^ ^^^ type argument not allowed +... | +LL | | } + | |_- this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` ... -LL | nested1_tt!(); - | ------------- in this macro invocation +LL | nested1_tt!(); + | ------------- in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -89,32 +94,38 @@ LL + ($variant:tt) => (if let EnumUnit::::$variant {} = 5 { true } error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:38:30 | -LL | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` - | | - | expected integer, found `Enum<(), ()>` +LL | / macro_rules! nested2_tt { +LL | | ($variant:tt) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | | + | | expected integer, found `Enum<(), ()>` +... | +LL | | } + | |_- this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` ... -LL | nested1_tt!(); - | ------------- in this macro invocation +LL | nested1_tt!(); + | ------------- in this macro invocation | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `nested2_tt` which comes from the expansion of the macro `nested1_tt` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:54 | -LL | () => (nested2_ident!(VariantB)); - | -------- not allowed on this type +LL | () => (nested2_ident!(VariantB)); + | -------- not allowed on this type ... -LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); - | ^^^ ^^^ type argument not allowed +LL | / macro_rules! nested2_ident { +LL | | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | | ^^^ ^^^ type argument not allowed +... | +LL | | } + | |_- this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` ... -LL | nested1_ident!(); - | ---------------- in this macro invocation +LL | nested1_ident!(); + | ---------------- in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); @@ -124,21 +135,25 @@ LL + ($variant:ident) => (if let EnumUnit::::$variant {} = 5 { tru error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:51:33 | -LL | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` - | | - | expected integer, found `Enum<(), ()>` +LL | / macro_rules! nested2_ident { +LL | | ($variant:ident) => (if let EnumUnit::$variant:: {} = 5 { true } else { false }); + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - this expression has type `{integer}` + | | | + | | expected integer, found `Enum<(), ()>` +... | +LL | | } + | |_- this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` ... -LL | nested1_ident!(); - | ---------------- in this macro invocation +LL | nested1_ident!(); + | ---------------- in this macro invocation | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `nested2_ident` which comes from the expansion of the macro `nested1_ident` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:60:44 | +LL | macro_rules! nested1_tt_args_in_first_macro { LL | () => (nested2_tt_args_in_first_macro!(i32, u32)); | ^^^ ^^^ type argument not allowed ... @@ -149,7 +164,6 @@ LL | nested1_tt_args_in_first_macro!(); | --------------------------------- in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} @@ -159,32 +173,37 @@ LL + ($arg1:tt, $arg2:tt) => (if let EnumUnit::<$arg1, $arg2>::VariantB {} error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:65:37 | -LL | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` -LL | -LL | = 5 { true } else { false }); - | - this expression has type `{integer}` +LL | / macro_rules! nested2_tt_args_in_first_macro { +LL | | ($arg1:tt, $arg2:tt) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` +LL | | +LL | | = 5 { true } else { false }); + | | - this expression has type `{integer}` +LL | | } + | |_- this error originates in the macro `nested2_tt_args_in_first_macro` which comes from the expansion of the macro `nested1_tt_args_in_first_macro` ... -LL | nested1_tt_args_in_first_macro!(); - | --------------------------------- in this macro invocation +LL | nested1_tt_args_in_first_macro!(); + | --------------------------------- in this macro invocation | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `nested2_tt_args_in_first_macro` which comes from the expansion of the macro `nested1_tt_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:64 | -LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} - | -------- ^^^^^ ^^^^^ type argument not allowed - | | - | not allowed on this type +LL | / macro_rules! nested2_ident_args_in_first_macro { +LL | | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | | -------- ^^^^^ ^^^^^ type argument not allowed + | | | + | | not allowed on this type +... | +LL | | } + | |_- this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` ... -LL | nested1_ident_args_in_first_macro!(); - | ------------------------------------ in this macro invocation +LL | nested1_ident_args_in_first_macro!(); + | ------------------------------------ in this macro invocation | = note: enum variants can't have type parameters - = note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: you might have meant to specify type parameters on enum `Enum` | LL - ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} @@ -194,18 +213,20 @@ LL + ($arg1:ident, $arg2:ident) => (if let EnumUnit::<$arg1, $arg2>::Variant error[E0308]: mismatched types --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:77:43 | -LL | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` -... -LL | = 5 { true } else { false }); - | - this expression has type `{integer}` +LL | / macro_rules! nested2_ident_args_in_first_macro { +LL | | ($arg1:ident, $arg2:ident) => (if let EnumUnit::VariantB::<$arg1, $arg2> {} + | | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected integer, found `Enum<(), ()>` +... | +LL | | = 5 { true } else { false }); + | | - this expression has type `{integer}` +LL | | } + | |_- this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` ... -LL | nested1_ident_args_in_first_macro!(); - | ------------------------------------ in this macro invocation +LL | nested1_ident_args_in_first_macro!(); + | ------------------------------------ in this macro invocation | = note: expected type `{integer}` found enum `Enum<(), ()>` - = note: this error originates in the macro `nested2_ident_args_in_first_macro` which comes from the expansion of the macro `nested1_ident_args_in_first_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0109]: type arguments are not allowed on this type --> $DIR/issue-116473-ice-wrong-span-variant-args.rs:93:33 diff --git a/tests/ui/typeck/issue-81943.stderr b/tests/ui/typeck/issue-81943.stderr index 041ff10752cf0..7b34e3f043813 100644 --- a/tests/ui/typeck/issue-81943.stderr +++ b/tests/ui/typeck/issue-81943.stderr @@ -27,6 +27,7 @@ LL | f(|x| match x { tmp => { g(tmp) } };); error[E0308]: mismatched types --> $DIR/issue-81943.rs:10:38 | +LL | macro_rules! d { LL | ($e:expr) => { match $e { x => { g(x) } } } | ------------------^^^^---- | | | @@ -36,7 +37,6 @@ LL | } LL | f(|x| d!(x)); | ----- in this macro invocation | - = note: this error originates in the macro `d` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider using a semicolon here | LL | ($e:expr) => { match $e { x => { g(x); } } } diff --git a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr index c217672b0050d..856aecf9264e4 100644 --- a/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr +++ b/tests/ui/typeck/sugg-swap-equality-in-macro-issue-139050.stderr @@ -22,6 +22,8 @@ LL | ext::eq!(assert iter.next(), Some(value)); error[E0308]: mismatched types --> $DIR/sugg-swap-equality-in-macro-issue-139050.rs:15:35 | +LL | macro_rules! eq_local { +... LL | if !(*left_val == *right_val) { | ^^^^^^^^^^ expected `Option<::Item>`, found `Option<&::Item>` ... @@ -31,7 +33,6 @@ LL | eq_local!(assert iter.next(), Some(value)); = note: expected enum `Option<_>` found enum `Option<&_>` = note: `Option<&::Item>` implements `PartialEq::Item>>` - = note: this error originates in the macro `eq_local` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider swapping the equality | LL - if !(*left_val == *right_val) { diff --git a/tests/ui/typeck/suggestions/macro-shorthand-issue-140659.stderr b/tests/ui/typeck/suggestions/macro-shorthand-issue-140659.stderr index 12537754d8029..399056112ce9f 100644 --- a/tests/ui/typeck/suggestions/macro-shorthand-issue-140659.stderr +++ b/tests/ui/typeck/suggestions/macro-shorthand-issue-140659.stderr @@ -1,15 +1,23 @@ error[E0308]: mismatched types --> $DIR/macro-shorthand-issue-140659.rs:42:44 | -LL | Instruction::Suspend { tag_index } - | ^^^^^^^^^ expected `u32`, found `Result::Error>` -... -LL | for_each_operator!(translate) - | ----------------------------- in this macro invocation +LL | / macro_rules! translate { +LL | | (Suspend { tag_index: $ty:ty } => $visit:ident) => { +LL | | match op { +LL | | Operator::Suspend { tag_index } => { +... | +LL | | Instruction::Suspend { tag_index } + | | ^^^^^^^^^ expected `u32`, found `Result::Error>` +... | +LL | | }; +LL | | } + | |_____- this error originates in the macro `translate` which comes from the expansion of the macro `for_each_operator` +LL | +LL | for_each_operator!(translate) + | ----------------------------- in this macro invocation | = note: expected type `u32` found enum `Result::Error>` - = note: this error originates in the macro `translate` which comes from the expansion of the macro `for_each_operator` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 1 previous error diff --git a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr index 3308a0807db6f..b64ca25280faa 100644 --- a/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr +++ b/tests/ui/unsafe/unsafe_op_in_unsafe_fn/wrapping-unsafe-block-sugg.stderr @@ -88,7 +88,6 @@ note: an unsafe function restricts its caller, but its body is safe by default LL | pub unsafe fn unsafe_in_macro() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: for more information, see - = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block --> $DIR/wrapping-unsafe-block-sugg.rs:48:36 @@ -101,7 +100,6 @@ LL | unsafe_macro!(); | = note: consult the function's documentation for information on how to avoid undefined behavior = note: for more information, see - = note: this error originates in the macro `unsafe_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 8 previous errors diff --git a/tests/ui/use/use-path-segment-kw.e2015.stderr b/tests/ui/use/use-path-segment-kw.e2015.stderr index a63cce80896ab..cb7a4bb387634 100644 --- a/tests/ui/use/use-path-segment-kw.e2015.stderr +++ b/tests/ui/use/use-path-segment-kw.e2015.stderr @@ -358,13 +358,14 @@ LL | use self::{self as name}; error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:11:13 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate as name; @@ -373,365 +374,366 @@ LL | use $crate as name; error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:15:15 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:16:15 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::$crate as _dollar_crate2; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:17:16 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:18:16 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::{$crate as _nested_dollar_crate2}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:21:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:22:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::$crate as _dollar_crate3; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:23:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:24:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::{$crate as _nested_dollar_crate3}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:27:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:28:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::$crate as _dollar_crate4; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:29:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:30:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::{$crate as _nested_dollar_crate4}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:33:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:34:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::$crate as _dollar_crate5; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:35:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:36:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::{$crate as _nested_dollar_crate5}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:39:19 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:40:19 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::$crate as _dollar_crate6; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:41:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:42:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::{$crate as _nested_dollar_crate6}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:45:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:46:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::$crate as _dollar_crate7; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:47:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:48:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{$crate as _nested_dollar_crate7}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:51:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::crate; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:52:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::crate as _m_crate8; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:53:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{crate}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:54:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{crate as _m_nested_crate8}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:57:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::super; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:58:21 | -LL | ... use $crate::super as _m_super8; - | ^^^^^ +LL | macro_rules! macro_dollar_crate { ... -LL | ... macro_dollar_crate!(); - | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | use $crate::super as _m_super8; + | ^^^^^ +... +LL | macro_dollar_crate!(); + | --------------------- in this macro invocation error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:59:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{super}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:60:22 | -LL | ... use $crate::{super as _m_nested_super8}; - | ^^^^^ +LL | macro_rules! macro_dollar_crate { ... -LL | ... macro_dollar_crate!(); - | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | use $crate::{super as _m_nested_super8}; + | ^^^^^ +... +LL | macro_dollar_crate!(); + | --------------------- in this macro invocation error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:63:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::self; | ^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate::self as name; @@ -740,13 +742,14 @@ LL | use $crate::self as name; error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:65:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{self}; | ^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate::{self as name}; @@ -799,24 +802,24 @@ LL | pub use self::foobar::{self as _nested_self3}; error[E0573]: expected type, found module `$crate` --> $DIR/use-path-segment-kw.rs:10:19 | +LL | macro_rules! macro_dollar_crate { +... LL | type A1 = $crate; | ^^^^^^ not a type ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0573]: expected type, found module `$crate::self` --> $DIR/use-path-segment-kw.rs:62:20 | +LL | macro_rules! macro_dollar_crate { +... LL | type A10 = $crate::self; | ^^^^^^^^^^^^ not a type ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0573]: expected type, found module `crate` --> $DIR/use-path-segment-kw.rs:95:19 @@ -887,90 +890,90 @@ LL | type D7 = crate::foo::bar::self; error[E0433]: global paths cannot start with `$crate` --> $DIR/use-path-segment-kw.rs:14:21 | +LL | macro_rules! macro_dollar_crate { +... LL | type A2 = ::$crate; | ^^^^^^ cannot start with this ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:20:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A3 = foobar::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:26:26 | +LL | macro_rules! macro_dollar_crate { +... LL | type A4 = crate::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:32:26 | +LL | macro_rules! macro_dollar_crate { +... LL | type A5 = super::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:38:25 | +LL | macro_rules! macro_dollar_crate { +... LL | type A6 = self::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:44:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A7 = $crate::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:50:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A8 = $crate::crate; | ^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `super` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:56:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A9 = $crate::super; | ^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: global paths cannot start with `crate` --> $DIR/use-path-segment-kw.rs:99:21 diff --git a/tests/ui/use/use-path-segment-kw.e2018.stderr b/tests/ui/use/use-path-segment-kw.e2018.stderr index 3f1b01a27de54..bc03f1c7f25a2 100644 --- a/tests/ui/use/use-path-segment-kw.e2018.stderr +++ b/tests/ui/use/use-path-segment-kw.e2018.stderr @@ -360,13 +360,14 @@ LL | use self::{self as name}; error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:11:13 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate as name; @@ -375,365 +376,366 @@ LL | use $crate as name; error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:15:15 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:16:15 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::$crate as _dollar_crate2; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:17:16 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:18:16 | +LL | macro_rules! macro_dollar_crate { +... LL | use ::{$crate as _nested_dollar_crate2}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:21:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:22:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::$crate as _dollar_crate3; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:23:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:24:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use foobar::{$crate as _nested_dollar_crate3}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:27:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:28:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::$crate as _dollar_crate4; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:29:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:30:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use crate::{$crate as _nested_dollar_crate4}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:33:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:34:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::$crate as _dollar_crate5; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:35:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:36:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use super::{$crate as _nested_dollar_crate5}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:39:19 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:40:19 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::$crate as _dollar_crate6; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:41:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:42:20 | +LL | macro_rules! macro_dollar_crate { +... LL | use self::{$crate as _nested_dollar_crate6}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:45:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::$crate; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:46:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::$crate as _dollar_crate7; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:47:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{$crate}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:48:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{$crate as _nested_dollar_crate7}; | ^^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:51:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::crate; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:52:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::crate as _m_crate8; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:53:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{crate}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:54:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{crate as _m_nested_crate8}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:57:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::super; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:58:21 | -LL | ... use $crate::super as _m_super8; - | ^^^^^ +LL | macro_rules! macro_dollar_crate { ... -LL | ... macro_dollar_crate!(); - | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | use $crate::super as _m_super8; + | ^^^^^ +... +LL | macro_dollar_crate!(); + | --------------------- in this macro invocation error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:59:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{super}; | ^^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error: `super` in paths can only be used in start position, after `self`, or after another `super` --> $DIR/use-path-segment-kw.rs:60:22 | -LL | ... use $crate::{super as _m_nested_super8}; - | ^^^^^ +LL | macro_rules! macro_dollar_crate { ... -LL | ... macro_dollar_crate!(); - | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | use $crate::{super as _m_nested_super8}; + | ^^^^^ +... +LL | macro_dollar_crate!(); + | --------------------- in this macro invocation error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:63:21 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::self; | ^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate::self as name; @@ -742,13 +744,14 @@ LL | use $crate::self as name; error: imports need to be explicitly named --> $DIR/use-path-segment-kw.rs:65:22 | +LL | macro_rules! macro_dollar_crate { +... LL | use $crate::{self}; | ^^^^ ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) help: try renaming it with a name | LL | use $crate::{self as name}; @@ -763,24 +766,24 @@ LL | foo::bar::_nested_self2::outer(); error[E0573]: expected type, found module `$crate` --> $DIR/use-path-segment-kw.rs:10:19 | +LL | macro_rules! macro_dollar_crate { +... LL | type A1 = $crate; | ^^^^^^ not a type ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0573]: expected type, found module `$crate::self` --> $DIR/use-path-segment-kw.rs:62:20 | +LL | macro_rules! macro_dollar_crate { +... LL | type A10 = $crate::self; | ^^^^^^^^^^^^ not a type ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0573]: expected type, found module `crate` --> $DIR/use-path-segment-kw.rs:95:19 @@ -851,90 +854,90 @@ LL | type D7 = crate::foo::bar::self; error[E0433]: global paths cannot start with `$crate` --> $DIR/use-path-segment-kw.rs:14:21 | +LL | macro_rules! macro_dollar_crate { +... LL | type A2 = ::$crate; | ^^^^^^ cannot start with this ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:20:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A3 = foobar::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:26:26 | +LL | macro_rules! macro_dollar_crate { +... LL | type A4 = crate::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:32:26 | +LL | macro_rules! macro_dollar_crate { +... LL | type A5 = super::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:38:25 | +LL | macro_rules! macro_dollar_crate { +... LL | type A6 = self::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `$crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:44:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A7 = $crate::$crate; | ^^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `crate` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:50:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A8 = $crate::crate; | ^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: `super` in paths can only be used in start position --> $DIR/use-path-segment-kw.rs:56:27 | +LL | macro_rules! macro_dollar_crate { +... LL | type A9 = $crate::super; | ^^^^^ can only be used in path start position ... LL | macro_dollar_crate!(); | --------------------- in this macro invocation - | - = note: this error originates in the macro `macro_dollar_crate` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0433]: global paths cannot start with `crate` --> $DIR/use-path-segment-kw.rs:99:21 From c517bb837ca8d8dd35364e4a237f5ccab458f487 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 13 Aug 2026 14:23:04 +0000 Subject: [PATCH 0439/1309] When error from local macro, include macro def span - mention `-Zmacro-backtrace` only for non-local macros - include span for local macro encompassing error --- .../undocumented_unsafe_blocks.default.stderr | 18 ++++++++++++------ ...undocumented_unsafe_blocks.disabled.stderr | 18 ++++++++++++------ tests/ui/async_yields_async.stderr | 4 ++-- tests/ui/cast.stderr | 10 ++++++---- tests/ui/cast_lossless_integer.stderr | 3 ++- .../checked_unwrap/simple_conditionals.stderr | 4 ++-- tests/ui/cmp_owned/with_suggestion.stderr | 4 ++-- tests/ui/collapsible_match2.stderr | 3 ++- tests/ui/crashes/ice-6255.stderr | 7 ++++--- tests/ui/dbg_macro/dbg_macro.stderr | 3 ++- tests/ui/doc_unsafe.stderr | 4 ++-- tests/ui/double_parens.stderr | 15 +++++++-------- tests/ui/duration_suboptimal_units.stderr | 3 ++- tests/ui/eq_op_macros.stderr | 15 ++++++++------- tests/ui/exit1.stderr | 4 ++-- tests/ui/incompatible_msrv.stderr | 4 ++-- .../ui/integer_division_remainder_used.stderr | 4 ++-- tests/ui/into_iter_without_iter.stderr | 3 ++- tests/ui/items_after_statement.stderr | 4 ++-- tests/ui/iter_without_into_iter.stderr | 3 ++- tests/ui/large_futures.stderr | 3 ++- tests/ui/large_stack_arrays.stderr | 8 ++++---- tests/ui/legacy_numeric_constants.stderr | 3 ++- .../legacy_numeric_constants_unfixable.stderr | 3 ++- tests/ui/manual_div_ceil.stderr | 8 ++++---- tests/ui/manual_let_else.stderr | 4 ++-- tests/ui/manual_range_patterns.stderr | 4 ++-- tests/ui/missing_transmute_annotations.stderr | 4 ++-- tests/ui/needless_question_mark.stderr | 3 ++- tests/ui/pattern_type_mismatch/syntax.stderr | 3 ++- tests/ui/redundant_async_block.stderr | 8 ++++---- .../ui/redundant_closure_call_fixable.stderr | 19 +++++++++++-------- tests/ui/redundant_field_names.stderr | 4 ++-- tests/ui/string_lit_as_bytes.stderr | 4 ++-- tests/ui/struct_fields.stderr | 14 ++++++++------ tests/ui/suspicious_xor_used_as_pow.stderr | 3 ++- tests/ui/unconditional_recursion.stderr | 3 ++- tests/ui/uninhabited_references.stderr | 8 ++++---- tests/ui/unnecessary_safety_comment.stderr | 3 ++- tests/ui/unnecessary_unsafety_doc.stderr | 4 ++-- tests/ui/unseparated_prefix_literals.stderr | 4 ++-- tests/ui/unused_result_ok.stderr | 3 ++- 42 files changed, 144 insertions(+), 109 deletions(-) diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr index bcc46adda8a0f..0950a13c8c2ce 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.default.stderr @@ -1,6 +1,8 @@ error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 | +LL | macro_rules! t { +LL | () => { LL | let _x = unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -10,11 +12,12 @@ LL | t!(); = help: consider adding a safety comment on the preceding line = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 | +LL | macro_rules! t { +... LL | unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 @@ -131,6 +133,8 @@ LL | t!(unsafe {}); error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | +LL | macro_rules! t { +LL | () => { LL | unsafe {} | ^^^^^^^^^ ... @@ -138,7 +142,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 @@ -191,6 +194,8 @@ LL | unsafe impl B for (u32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -198,11 +203,12 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -210,7 +216,6 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 @@ -223,6 +228,8 @@ LL | unsafe impl T for (i32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -230,7 +237,6 @@ LL | no_safety_comment!(u32); | ----------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 diff --git a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr index 0de8ed716bed9..20483c72228c5 100644 --- a/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr +++ b/tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.disabled.stderr @@ -1,6 +1,8 @@ error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:244:22 | +LL | macro_rules! t { +LL | () => { LL | let _x = unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -10,11 +12,12 @@ LL | t!(); = help: consider adding a safety comment on the preceding line = note: `-D clippy::undocumented-unsafe-blocks` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::undocumented_unsafe_blocks)]` - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:256:13 | +LL | macro_rules! t { +... LL | unsafe { 1 }; | ^^^^^^^^^^^^ ... @@ -22,7 +25,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:337:19 @@ -131,6 +133,8 @@ LL | t!(unsafe {}); error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:401:13 | +LL | macro_rules! t { +LL | () => { LL | unsafe {} | ^^^^^^^^^ ... @@ -138,7 +142,6 @@ LL | t!(); | ---- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `t` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe block missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:410:5 @@ -191,6 +194,8 @@ LL | unsafe impl B for (u32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:470:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -198,11 +203,12 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -210,7 +216,6 @@ LL | no_safety_comment!(()); | ---------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:506:5 @@ -223,6 +228,8 @@ LL | unsafe impl T for (i32) {} error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:496:13 | +LL | macro_rules! no_safety_comment { +LL | ($t:ty) => { LL | unsafe impl T for $t {} | ^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -230,7 +237,6 @@ LL | no_safety_comment!(u32); | ----------------------- in this macro invocation | = help: consider adding a safety comment on the preceding line - = note: this error originates in the macro `no_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: unsafe impl missing a safety comment --> tests/ui-toml/undocumented_unsafe_blocks/undocumented_unsafe_blocks.rs:513:5 diff --git a/tests/ui/async_yields_async.stderr b/tests/ui/async_yields_async.stderr index 3041cf6578938..57ef895db9944 100644 --- a/tests/ui/async_yields_async.stderr +++ b/tests/ui/async_yields_async.stderr @@ -112,6 +112,8 @@ LL | let y = async { call_bar!() }; error: an async construct yields a type which is itself awaitable --> tests/ui/async_yields_async.rs:90:21 | +LL | macro_rules! call_bar { +LL | () => { LL | async { bar(5) } | --^^^^^^-- | | | @@ -121,8 +123,6 @@ LL | async { bar(5) } ... LL | let y = async { call_bar!() }; | ----------- in this macro invocation - | - = note: this error originates in the macro `call_bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: an async construct yields a type which is itself awaitable --> tests/ui/async_yields_async.rs:119:21 diff --git a/tests/ui/cast.stderr b/tests/ui/cast.stderr index 6b44ff344392e..3e1d418abef61 100644 --- a/tests/ui/cast.stderr +++ b/tests/ui/cast.stderr @@ -670,17 +670,19 @@ LL | (a.abs() * b.pow(2) / c.abs()) as u32 error: casting `i32` to `u32` may lose the sign of the value --> tests/ui/cast.rs:532:21 | +LL | macro_rules! m { +LL | () => { LL | let _ = i32::MIN as u32; // cast_sign_loss | ^^^^^^^^^^^^^^^ help: if this is intentional, use `cast_unsigned()` instead: `i32::MIN.cast_unsigned()` ... LL | m!(); | ---- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `u32` to `u8` may truncate the value --> tests/ui/cast.rs:535:21 | +LL | macro_rules! m { +... LL | let _ = u32::MAX as u8; // cast_possible_truncation | ^^^^^^^^^^^^^^ ... @@ -688,7 +690,6 @@ LL | m!(); | ---- in this macro invocation | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) help: ... or use `try_from` and handle the error accordingly | LL - let _ = u32::MAX as u8; // cast_possible_truncation @@ -698,6 +699,8 @@ LL + let _ = u8::try_from(u32::MAX); // cast_possible_truncation error: casting `f64` to `f32` may truncate the value --> tests/ui/cast.rs:538:21 | +LL | macro_rules! m { +... LL | let _ = std::f64::consts::PI as f32; // cast_possible_truncation | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... @@ -705,7 +708,6 @@ LL | m!(); | ---- in this macro invocation | = help: if this is intentional allow the lint with `#[allow(clippy::cast_possible_truncation)]` ... - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: casting `i64` to `usize` may truncate the value on targets with 32-bit wide pointers --> tests/ui/cast.rs:549:5 diff --git a/tests/ui/cast_lossless_integer.stderr b/tests/ui/cast_lossless_integer.stderr index 9852eca712793..ce2afbb66c23b 100644 --- a/tests/ui/cast_lossless_integer.stderr +++ b/tests/ui/cast_lossless_integer.stderr @@ -497,6 +497,8 @@ LL + let _ = i32::from(sign_cast!(x, u8, i8) + 1); error: casts from `u8` to `u32` can be expressed infallibly using `From` --> tests/ui/cast_lossless_integer.rs:159:13 | +LL | macro_rules! in_macro { +LL | () => { LL | 1u8 as u32 | ^^^^^^^^^^ ... @@ -504,7 +506,6 @@ LL | let _ = in_macro!(); | ----------- in this macro invocation | = help: an `as` cast can become silently lossy if the types change in the future - = note: this error originates in the macro `in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: use `u32::from` instead | LL - 1u8 as u32 diff --git a/tests/ui/checked_unwrap/simple_conditionals.stderr b/tests/ui/checked_unwrap/simple_conditionals.stderr index be979baa9fe4a..b2d4a9903234a 100644 --- a/tests/ui/checked_unwrap/simple_conditionals.stderr +++ b/tests/ui/checked_unwrap/simple_conditionals.stderr @@ -59,6 +59,8 @@ LL | x.unwrap(); error: called `unwrap` on `x` after checking its variant with `is_some` --> tests/ui/checked_unwrap/simple_conditionals.rs:13:13 | +LL | macro_rules! m { +LL | ($a:expr) => { LL | if $a.is_some() { | --------------- help: try: `if let Some() = x` LL | $a.unwrap(); @@ -66,8 +68,6 @@ LL | $a.unwrap(); ... LL | m!(x); | ----- in this macro invocation - | - = note: this error originates in the macro `m` (in Nightly builds, run with -Z macro-backtrace for more info) error: called `unwrap` on `x` after checking its variant with `is_ok` --> tests/ui/checked_unwrap/simple_conditionals.rs:71:9 diff --git a/tests/ui/cmp_owned/with_suggestion.stderr b/tests/ui/cmp_owned/with_suggestion.stderr index 7d9a12b1ddd33..54f839b812397 100644 --- a/tests/ui/cmp_owned/with_suggestion.stderr +++ b/tests/ui/cmp_owned/with_suggestion.stderr @@ -58,6 +58,8 @@ LL | if item == t!(frohes_neu_Jahr).to_string() { error: this creates an owned instance just for comparison --> tests/ui/cmp_owned/with_suggestion.rs:141:51 | +LL | macro_rules! all_comes_from_macro { +... LL | let res = <$ty>::default() == "$def".to_string(); | ^^^^^^^^^^^^^^^^^^ help: try: `"$def"` ... @@ -65,8 +67,6 @@ LL | / all_comes_from_macro! { LL | | required_version: String, m!().to_string(); LL | | } | |_____- in this macro invocation - | - = note: this error originates in the macro `all_comes_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: this creates an owned instance just for comparison --> tests/ui/cmp_owned/with_suggestion.rs:156:16 diff --git a/tests/ui/collapsible_match2.stderr b/tests/ui/collapsible_match2.stderr index 6acfd3de782bd..30cbf7705a20d 100644 --- a/tests/ui/collapsible_match2.stderr +++ b/tests/ui/collapsible_match2.stderr @@ -43,6 +43,8 @@ LL | Some(n) => foo(n), error: this `match` can be collapsed into the outer `match` --> tests/ui/collapsible_match2.rs:31:29 | +LL | macro_rules! mac { +... LL | $pat => match $e { | _____________________________^ LL | | @@ -61,7 +63,6 @@ LL | mac!(res_opt => Ok(val), val => Some(n), foo(n)); | ^^^ ^^^^^^^ with this pattern | | | replace this binding - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this `match` can be collapsed into the outer `match` --> tests/ui/collapsible_match2.rs:49:20 diff --git a/tests/ui/crashes/ice-6255.stderr b/tests/ui/crashes/ice-6255.stderr index 420e4af936f81..dfaf6ce86f517 100644 --- a/tests/ui/crashes/ice-6255.stderr +++ b/tests/ui/crashes/ice-6255.stderr @@ -1,17 +1,19 @@ error: macro-expanded `extern crate` items cannot shadow names passed with `--extern` --> tests/ui/crashes/ice-6255.rs:6:9 | +LL | macro_rules! define_other_core { +LL | ( ) => { LL | extern crate std as core; | ^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | define_other_core!(); | -------------------- in this macro invocation - | - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error[E0659]: `core` is ambiguous --> tests/ui/crashes/ice-6255.rs:12:5 | +LL | macro_rules! define_other_core { +... LL | core::panic!(); | ^^^^ ambiguous name | @@ -26,7 +28,6 @@ LL | extern crate std as core; LL | define_other_core!(); | -------------------- in this macro invocation = help: use `crate::core` to refer to this crate unambiguously - = note: this error originates in the macro `define_other_core` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 2 previous errors diff --git a/tests/ui/dbg_macro/dbg_macro.stderr b/tests/ui/dbg_macro/dbg_macro.stderr index 2efefef4ee2ec..44b20bd883e68 100644 --- a/tests/ui/dbg_macro/dbg_macro.stderr +++ b/tests/ui/dbg_macro/dbg_macro.stderr @@ -146,13 +146,14 @@ LL + foo2!(foo!(())); error: the `dbg!` macro is intended as a debugging tool --> tests/ui/dbg_macro/dbg_macro.rs:46:13 | +LL | macro_rules! expand_to_dbg { +LL | () => { LL | dbg!(); | ^^^^^^ ... LL | expand_to_dbg!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `expand_to_dbg` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the invocation before committing it to a version control system | LL - dbg!(); diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr index efac6cd64c878..cf3fe5fdbe5d8 100644 --- a/tests/ui/doc_unsafe.stderr +++ b/tests/ui/doc_unsafe.stderr @@ -81,13 +81,13 @@ LL | pub unsafe fn more_undocumented_unsafe() -> Self { error: unsafe function's docs are missing a `# Safety` section --> tests/ui/doc_unsafe.rs:138:9 | +LL | macro_rules! very_unsafe { +LL | () => { LL | pub unsafe fn whee() { | ^^^^^^^^^^^^^^^^^^^^ ... LL | very_unsafe!(); | -------------- in this macro invocation - | - = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/double_parens.stderr b/tests/ui/double_parens.stderr index 51b5c6279b211..7afe8f700e86b 100644 --- a/tests/ui/double_parens.stderr +++ b/tests/ui/double_parens.stderr @@ -40,13 +40,12 @@ LL | assert_eq!(((1, 2)), (1, 2), "Error"); error: unnecessary parentheses --> tests/ui/double_parens.rs:89:16 | +LL | macro_rules! bar { LL | () => {((100))} | ^^^^^^^ help: remove them: `(100)` ... LL | bar!(); | ------ in this macro invocation - | - = note: this error originates in the macro `bar` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:96:5 @@ -69,35 +68,35 @@ LL | x.dummy_method((vec![1, 2])); error: unnecessary parentheses --> tests/ui/double_parens.rs:110:21 | +LL | macro_rules! double_parens{ +... LL | let a = (()); | ^^^^ help: remove them: `()` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:112:21 | +LL | macro_rules! double_parens{ +... LL | let b = ((5)); | ^^^^^ help: remove them: `(5)` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: unnecessary parentheses --> tests/ui/double_parens.rs:114:44 | +LL | macro_rules! double_parens{ +... LL | let c = std::convert::identity((5)); | ^^^ help: remove them: `5` ... LL | pub const E: InterruptMask = double_parens!((Self::OE), Self::BE, Self::PE, Self::FE); | -------------------------------------------------------- in this macro invocation - | - = note: this error originates in the macro `double_parens` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 13 previous errors diff --git a/tests/ui/duration_suboptimal_units.stderr b/tests/ui/duration_suboptimal_units.stderr index 0d1ee48b36df1..abe596bfd46d9 100644 --- a/tests/ui/duration_suboptimal_units.stderr +++ b/tests/ui/duration_suboptimal_units.stderr @@ -147,13 +147,14 @@ LL + assert_eq!(Duration::from_hours(1), Duration::from_mins(6)); error: constructing a `Duration` using a smaller unit when a larger unit would be more readable --> tests/ui/duration_suboptimal_units.rs:13:9 | +LL | macro_rules! mac { +... LL | Duration::from_secs(60 * 5) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ... LL | let dur = mac!(duration); | -------------- in this macro invocation | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) help: try using `Duration::from_mins` | LL - Duration::from_secs(60 * 5) diff --git a/tests/ui/eq_op_macros.stderr b/tests/ui/eq_op_macros.stderr index 72315e87bfeff..8bc75c8efe0b0 100644 --- a/tests/ui/eq_op_macros.stderr +++ b/tests/ui/eq_op_macros.stderr @@ -1,6 +1,8 @@ error: identical args used in this `assert_eq!` macro call --> tests/ui/eq_op_macros.rs:8:20 | +LL | macro_rules! assert_in_macro_def { +... LL | assert_eq!(a, a); | ^^^^ ... @@ -9,40 +11,39 @@ LL | assert_in_macro_def!(); | = note: `-D clippy::eq-op` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::eq_op)]` - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_ne!` macro call --> tests/ui/eq_op_macros.rs:10:20 | +LL | macro_rules! assert_in_macro_def { +... LL | assert_ne!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_eq!` macro call --> tests/ui/eq_op_macros.rs:12:26 | +LL | macro_rules! assert_in_macro_def { +... LL | debug_assert_eq!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `debug_assert_ne!` macro call --> tests/ui/eq_op_macros.rs:14:26 | +LL | macro_rules! assert_in_macro_def { +... LL | debug_assert_ne!(a, a); | ^^^^ ... LL | assert_in_macro_def!(); | ---------------------- in this macro invocation - | - = note: this error originates in the macro `assert_in_macro_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: identical args used in this `assert_eq!` macro call --> tests/ui/eq_op_macros.rs:27:16 diff --git a/tests/ui/exit1.stderr b/tests/ui/exit1.stderr index 9398d2f7f4399..3ac6ec2e03b41 100644 --- a/tests/ui/exit1.stderr +++ b/tests/ui/exit1.stderr @@ -16,13 +16,13 @@ LL | mac!(std::process::exit(1)); error: usage of `process::exit` --> tests/ui/exit1.rs:25:13 | +LL | macro_rules! mac { +... LL | std::process::exit($x); | ^^^^^^^^^^^^^^^^^^^^^^ ... LL | mac!(ex 1); | ---------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/incompatible_msrv.stderr b/tests/ui/incompatible_msrv.stderr index 3c0bb595bd5b0..758d48c21eed6 100644 --- a/tests/ui/incompatible_msrv.stderr +++ b/tests/ui/incompatible_msrv.stderr @@ -40,13 +40,13 @@ LL | let _ = core::iter::once_with(|| 0); error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` --> tests/ui/incompatible_msrv.rs:69:21 | +LL | macro_rules! my_panic { +LL | ($msg:expr) => { LL | let _ = core::iter::once_with(|| $msg); | ^^^^^^^^^^^^^^^^^^^^^ ... LL | my_panic!("foo"); | ---------------- in this macro invocation - | - = note: this error originates in the macro `my_panic` (in Nightly builds, run with -Z macro-backtrace for more info) error: current MSRV (Minimum Supported Rust Version) is `1.3.0` but this item is stable since `1.43.0` --> tests/ui/incompatible_msrv.rs:76:13 diff --git a/tests/ui/integer_division_remainder_used.stderr b/tests/ui/integer_division_remainder_used.stderr index 632df3e960c10..5403c25b59943 100644 --- a/tests/ui/integer_division_remainder_used.stderr +++ b/tests/ui/integer_division_remainder_used.stderr @@ -70,13 +70,13 @@ LL | j %= 3; error: use of `%` has been disallowed in this context --> tests/ui/integer_division_remainder_used.rs:60:13 | +LL | macro_rules! mac { +LL | ($a:expr, $b:expr) => { LL | $a % $b | ^^^^^^^ ... LL | let issue17048 = mac!(a, b); | ---------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/into_iter_without_iter.stderr b/tests/ui/into_iter_without_iter.stderr index a033ff645f49a..5137cd6b30f50 100644 --- a/tests/ui/into_iter_without_iter.stderr +++ b/tests/ui/into_iter_without_iter.stderr @@ -108,6 +108,8 @@ LL + } error: `IntoIterator` implemented for a reference type without an `iter` method --> tests/ui/into_iter_without_iter.rs:120:9 | +LL | macro_rules! generate_impl { +LL | () => { LL | / impl<'a> IntoIterator for &'a Issue12037 { LL | | LL | | type IntoIter = std::slice::Iter<'a, u8>; @@ -119,7 +121,6 @@ LL | | } LL | generate_impl!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider implementing `iter` | LL ~ diff --git a/tests/ui/items_after_statement.stderr b/tests/ui/items_after_statement.stderr index 7a5ae2c8d47d2..2e1b75aaa7e9d 100644 --- a/tests/ui/items_after_statement.stderr +++ b/tests/ui/items_after_statement.stderr @@ -24,6 +24,8 @@ LL | | } error: adding items after statements is confusing, since items exist from the start of the scope --> tests/ui/items_after_statement.rs:37:13 | +LL | macro_rules! b { +... LL | / fn say_something() { LL | | LL | | println!("something"); @@ -32,8 +34,6 @@ LL | | } ... LL | b!(); | ---- in this macro invocation - | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 3 previous errors diff --git a/tests/ui/iter_without_into_iter.stderr b/tests/ui/iter_without_into_iter.stderr index f42782aae6705..8645897bc8f3d 100644 --- a/tests/ui/iter_without_into_iter.stderr +++ b/tests/ui/iter_without_into_iter.stderr @@ -150,6 +150,8 @@ LL + } error: `iter` method without an `IntoIterator` impl for `&Issue12037` --> tests/ui/iter_without_into_iter.rs:131:13 | +LL | macro_rules! generate_impl { +... LL | / fn iter(&self) -> std::slice::Iter<'_, u8> { LL | | LL | | todo!() @@ -159,7 +161,6 @@ LL | | } LL | generate_impl!(); | ---------------- in this macro invocation | - = note: this error originates in the macro `generate_impl` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider implementing `IntoIterator` for `&Issue12037` | LL ~ diff --git a/tests/ui/large_futures.stderr b/tests/ui/large_futures.stderr index 26361ce8535a2..65587adcc763c 100644 --- a/tests/ui/large_futures.stderr +++ b/tests/ui/large_futures.stderr @@ -63,6 +63,8 @@ LL + }) error: large future with a size of 65540 bytes --> tests/ui/large_futures.rs:59:13 | +LL | macro_rules! macro_ { +LL | () => { LL | / async { LL | | LL | | let x = [0i32; 1024 * 16]; @@ -74,7 +76,6 @@ LL | | } LL | macro_!().await | --------- in this macro invocation | - = note: this error originates in the macro `macro_` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider `Box::pin` on it | LL ~ Box::pin(async { diff --git a/tests/ui/large_stack_arrays.stderr b/tests/ui/large_stack_arrays.stderr index f48706415e66a..6758d49d38b16 100644 --- a/tests/ui/large_stack_arrays.stderr +++ b/tests/ui/large_stack_arrays.stderr @@ -67,13 +67,13 @@ LL | let y = [x, x, dummy!(x), x, x]; error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:76:13 | +LL | macro_rules! dummy { +... LL | [$a, $b, $a, $b] | ^^^^^^^^^^^^^^^^ ... LL | let y = dummy![x => x]; | -------------- in this macro invocation - | - = note: this error originates in the macro `dummy` (in Nightly builds, run with -Z macro-backtrace for more info) error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:104:20 @@ -92,13 +92,13 @@ LL | let y = proc_macros::make_it_big!([x; 1]); error: allocating a local array larger than 16384 bytes --> tests/ui/large_stack_arrays.rs:88:23 | +LL | macro_rules! create_then_move { +LL | ($id:ident; $n:literal) => {{ LL | let _x_ = [$id; $n]; | ^^^^^^^^^ ... LL | let y = vec![create_then_move![x; 5]; 5]; | ----------------------- in this macro invocation - | - = note: this error originates in the macro `create_then_move` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 12 previous errors diff --git a/tests/ui/legacy_numeric_constants.stderr b/tests/ui/legacy_numeric_constants.stderr index e0eb9562fbd38..afebb2998ce52 100644 --- a/tests/ui/legacy_numeric_constants.stderr +++ b/tests/ui/legacy_numeric_constants.stderr @@ -158,13 +158,14 @@ LL + u128::MAX; error: usage of a legacy numeric constant --> tests/ui/legacy_numeric_constants.rs:18:25 | +LL | macro_rules! b { +... LL | let x = std::u64::MAX; | ^^^^^^^^^^^^^ ... LL | b!(); | ---- in this macro invocation | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) help: use the associated constant instead | LL - let x = std::u64::MAX; diff --git a/tests/ui/legacy_numeric_constants_unfixable.stderr b/tests/ui/legacy_numeric_constants_unfixable.stderr index 96e6c9ef97598..b999e4c2c0ea0 100644 --- a/tests/ui/legacy_numeric_constants_unfixable.stderr +++ b/tests/ui/legacy_numeric_constants_unfixable.stderr @@ -61,6 +61,8 @@ LL | use std::i16::*; error: importing legacy numeric constants --> tests/ui/legacy_numeric_constants_unfixable.rs:22:17 | +LL | macro_rules! b { +... LL | use std::u32; | ^^^^^^^^ ... @@ -69,7 +71,6 @@ LL | b!(); | = help: remove this import = note: then `u32::` will resolve to the respective associated constant - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: importing a legacy numeric constant --> tests/ui/legacy_numeric_constants_unfixable.rs:77:9 diff --git a/tests/ui/manual_div_ceil.stderr b/tests/ui/manual_div_ceil.stderr index 1ebcbc04eeb95..3e505baf35920 100644 --- a/tests/ui/manual_div_ceil.stderr +++ b/tests/ui/manual_div_ceil.stderr @@ -34,24 +34,24 @@ LL | let _ = (7_i32 as u32 + (4 - 1)) / 4; error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:6:17 | +LL | macro_rules! y { +... LL | let _ = (x + 7) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` ... LL | y!(); | ---- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:8:17 | +LL | macro_rules! y { +... LL | let _ = (7 + x) / 8; | ^^^^^^^^^^^ help: consider using `.div_ceil()`: `x.div_ceil(8)` ... LL | y!(); | ---- in this macro invocation - | - = note: this error originates in the macro `y` (in Nightly builds, run with -Z macro-backtrace for more info) error: manually reimplementing `div_ceil` --> tests/ui/manual_div_ceil.rs:62:13 diff --git a/tests/ui/manual_let_else.stderr b/tests/ui/manual_let_else.stderr index 77e32eada5c6e..3cb4a0c601bd7 100644 --- a/tests/ui/manual_let_else.stderr +++ b/tests/ui/manual_let_else.stderr @@ -272,13 +272,13 @@ LL + }; error: this could be rewritten as `let...else` --> tests/ui/manual_let_else.rs:170:13 | +LL | macro_rules! create_binding_if_some { +LL | ($n:ident, $e:expr) => { LL | let $n = if let Some(v) = $e { v } else { return }; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider writing: `let Some($n) = g() else { return };` ... LL | create_binding_if_some!(w, g()); | ------------------------------- in this macro invocation - | - = note: this error originates in the macro `create_binding_if_some` (in Nightly builds, run with -Z macro-backtrace for more info) error: this could be rewritten as `let...else` --> tests/ui/manual_let_else.rs:180:5 diff --git a/tests/ui/manual_range_patterns.stderr b/tests/ui/manual_range_patterns.stderr index 729a6d598a116..700d487aa502e 100644 --- a/tests/ui/manual_range_patterns.stderr +++ b/tests/ui/manual_range_patterns.stderr @@ -112,13 +112,13 @@ LL | matches!(f, 5..=10 | 0..5); error: this OR pattern can be rewritten using a range --> tests/ui/manual_range_patterns.rs:60:26 | +LL | macro_rules! mac { +LL | ($e:expr) => { LL | matches!($e, 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `1..=10` ... LL | mac!(f); | ------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 19 previous errors diff --git a/tests/ui/missing_transmute_annotations.stderr b/tests/ui/missing_transmute_annotations.stderr index d4854c122da5c..9044ca4917095 100644 --- a/tests/ui/missing_transmute_annotations.stderr +++ b/tests/ui/missing_transmute_annotations.stderr @@ -40,13 +40,13 @@ LL | bar(std::mem::transmute::<[u16; 2], _>([1u16, 2u16])); error: transmute used without annotations --> tests/ui/missing_transmute_annotations.rs:11:19 | +LL | macro_rules! local_bad_transmute { +LL | ($e:expr) => { LL | std::mem::transmute($e) | ^^^^^^^^^ help: consider adding missing annotations: `transmute::<[u16; 2], i32>` ... LL | i = local_bad_transmute!([1u16, 2u16]); | ---------------------------------- in this macro invocation - | - = note: this error originates in the macro `local_bad_transmute` (in Nightly builds, run with -Z macro-backtrace for more info) error: transmute used without annotations --> tests/ui/missing_transmute_annotations.rs:57:23 diff --git a/tests/ui/needless_question_mark.stderr b/tests/ui/needless_question_mark.stderr index 8e0a740cc0ab3..4a91633dc001b 100644 --- a/tests/ui/needless_question_mark.stderr +++ b/tests/ui/needless_question_mark.stderr @@ -135,13 +135,14 @@ LL + return t.magic; error: enclosing `Some` and `?` operator are unneeded --> tests/ui/needless_question_mark.rs:122:27 | +LL | macro_rules! some_and_qmark_in_macro { +LL | ($expr:expr) => { LL | || -> Option<_> { Some(Some($expr)?) }() | ^^^^^^^^^^^^^^^^^^ ... LL | let _x = some_and_qmark_in_macro!(x?); | ---------------------------- in this macro invocation | - = note: this error originates in the macro `some_and_qmark_in_macro` (in Nightly builds, run with -Z macro-backtrace for more info) help: remove the enclosing `Some` and `?` operator | LL - || -> Option<_> { Some(Some($expr)?) }() diff --git a/tests/ui/pattern_type_mismatch/syntax.stderr b/tests/ui/pattern_type_mismatch/syntax.stderr index 636841e0a21a4..43fbce64ffa80 100644 --- a/tests/ui/pattern_type_mismatch/syntax.stderr +++ b/tests/ui/pattern_type_mismatch/syntax.stderr @@ -67,6 +67,8 @@ LL | Some(_) => (), error: type of pattern does not match the expression type --> tests/ui/pattern_type_mismatch/syntax.rs:145:17 | +LL | macro_rules! matching_macro { +... LL | Some(_) => (), | ^^^^^^^ ... @@ -74,7 +76,6 @@ LL | matching_macro!(value); | ---------------------- in this macro invocation | = help: use `*` to dereference the match expression or explicitly match against a `&_` pattern and adjust the enclosed variable bindings - = note: this error originates in the macro `matching_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 9 previous errors diff --git a/tests/ui/redundant_async_block.stderr b/tests/ui/redundant_async_block.stderr index 386f00a25c2f9..785a6b5b5d7c4 100644 --- a/tests/ui/redundant_async_block.stderr +++ b/tests/ui/redundant_async_block.stderr @@ -52,24 +52,24 @@ LL | async { async { f().await + 1 }.await } error: this async expression only awaits a single future --> tests/ui/redundant_async_block.rs:155:13 | +LL | macro_rules! mac { +... LL | async { async { 42 }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { 42 }` ... LL | mac!() | ------ in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: this async expression only awaits a single future --> tests/ui/redundant_async_block.rs:176:13 | +LL | macro_rules! mac { +... LL | async { async { $e }.await } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: you can reduce it to: `async { $e }` ... LL | mac!(42) | -------- in this macro invocation - | - = note: this error originates in the macro `mac` (in Nightly builds, run with -Z macro-backtrace for more info) error: aborting due to 10 previous errors diff --git a/tests/ui/redundant_closure_call_fixable.stderr b/tests/ui/redundant_closure_call_fixable.stderr index d9d2335ef9031..13c22550b3b8b 100644 --- a/tests/ui/redundant_closure_call_fixable.stderr +++ b/tests/ui/redundant_closure_call_fixable.stderr @@ -60,24 +60,27 @@ LL | let d = (async || something().await)(); error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:38:13 | +LL | macro_rules! m2 { +LL | () => { LL | (|| m!())() | ^^^^^^^^^^^ help: try doing something like: `m!()` ... LL | m2!(); | ----- in this macro invocation - | - = note: this error originates in the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:33:13 | -LL | (|| 0)() - | ^^^^^^^^ help: try doing something like: `0` +LL | / macro_rules! m { +LL | | () => { +LL | | (|| 0)() + | | ^^^^^^^^ help: try doing something like: `0` +LL | | }; +LL | | } + | |_____- this error originates in the macro `m` which comes from the expansion of the macro `m2` ... -LL | m2!(); - | ----- in this macro invocation - | - = note: this error originates in the macro `m` which comes from the expansion of the macro `m2` (in Nightly builds, run with -Z macro-backtrace for more info) +LL | m2!(); + | ----- in this macro invocation error: try not to call a closure in the expression where it is declared --> tests/ui/redundant_closure_call_fixable.rs:48:16 diff --git a/tests/ui/redundant_field_names.stderr b/tests/ui/redundant_field_names.stderr index 5554c28b7cff3..8b5ae4d169385 100644 --- a/tests/ui/redundant_field_names.stderr +++ b/tests/ui/redundant_field_names.stderr @@ -46,13 +46,13 @@ LL | let _ = RangeToInclusive { end: end }; error: redundant field names in struct initialization --> tests/ui/redundant_field_names.rs:77:25 | +LL | macro_rules! internal { +LL | ($i:ident) => { LL | let _ = S { v: v }; | ^^^^ help: replace it with: `v` ... LL | internal!(v); | ------------ in this macro invocation - | - = note: this error originates in the macro `internal` (in Nightly builds, run with -Z macro-backtrace for more info) error: redundant field names in struct initialization --> tests/ui/redundant_field_names.rs:106:25 diff --git a/tests/ui/string_lit_as_bytes.stderr b/tests/ui/string_lit_as_bytes.stderr index 9388fbdc775d3..4dd7a32232713 100644 --- a/tests/ui/string_lit_as_bytes.stderr +++ b/tests/ui/string_lit_as_bytes.stderr @@ -28,13 +28,13 @@ LL | let bs = "lit to owned".to_owned().into_bytes(); error: calling `as_bytes()` on a string literal --> tests/ui/string_lit_as_bytes.rs:11:26 | +LL | macro_rules! b { +LL | ($b:literal) => { LL | const B: &[u8] = $b.as_bytes(); | ^^^^^^^^^^^^^ help: consider using a byte string literal instead: `b"warning"` ... LL | b!("warning"); | ------------- in this macro invocation - | - = note: this error originates in the macro `b` (in Nightly builds, run with -Z macro-backtrace for more info) error: calling `as_bytes()` on `include_str!(..)` --> tests/ui/string_lit_as_bytes.rs:43:22 diff --git a/tests/ui/struct_fields.stderr b/tests/ui/struct_fields.stderr index 254498ad2eebc..edf29eaafb97d 100644 --- a/tests/ui/struct_fields.stderr +++ b/tests/ui/struct_fields.stderr @@ -210,6 +210,8 @@ LL | proxy: i32, error: all fields have the same prefix: `some` --> tests/ui/struct_fields.rs:225:13 | +LL | macro_rules! mk_struct { +LL | () => { LL | / struct MacroStruct { LL | | LL | | some_a: i32, @@ -222,33 +224,34 @@ LL | mk_struct!(); | ------------ in this macro invocation | = help: remove the prefixes - = note: this error originates in the macro `mk_struct` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:238:17 | +LL | macro_rules! mk_struct2 { +... LL | macrobaz_a: i32, | ^^^^^^^^^^^^^^^ ... LL | mk_struct2!(); | ------------- in this macro invocation - | - = note: this error originates in the macro `mk_struct2` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:250:17 | +LL | macro_rules! mk_struct_with_names { +... LL | $field: i32, | ^^^^^^^^^^^ ... LL | mk_struct_with_names!(Foo, foo); | ------------------------------- in this macro invocation - | - = note: this error originates in the macro `mk_struct_with_names` (in Nightly builds, run with -Z macro-backtrace for more info) error: all fields have the same prefix: `some` --> tests/ui/struct_fields.rs:290:13 | +LL | macro_rules! mk_struct_full_def { +LL | ($struct_name:ident, $field1:ident, $field2:ident, $field3:ident) => { LL | / struct $struct_name { LL | | LL | | $field1: i32, @@ -261,7 +264,6 @@ LL | mk_struct_full_def!(PrefixData, some_data, some_meta, some_other); | ----------------------------------------------------------------- in this macro invocation | = help: remove the prefixes - = note: this error originates in the macro `mk_struct_full_def` (in Nightly builds, run with -Z macro-backtrace for more info) error: field name starts with the struct's name --> tests/ui/struct_fields.rs:338:5 diff --git a/tests/ui/suspicious_xor_used_as_pow.stderr b/tests/ui/suspicious_xor_used_as_pow.stderr index 2b6570bb0adfc..b2a507b56ff34 100644 --- a/tests/ui/suspicious_xor_used_as_pow.stderr +++ b/tests/ui/suspicious_xor_used_as_pow.stderr @@ -75,13 +75,14 @@ LL + let _ = 2i32.pow(32i32); error: `^` is not the exponentiation operator --> tests/ui/suspicious_xor_used_as_pow.rs:12:9 | +LL | macro_rules! macro_test_inside { +LL | () => { LL | 1 ^ 2 // should warn even if inside macro | ^^^^^ ... LL | macro_test_inside!(); | -------------------- in this macro invocation | - = note: this error originates in the macro `macro_test_inside` (in Nightly builds, run with -Z macro-backtrace for more info) help: did you mean to write | LL - 1 ^ 2 // should warn even if inside macro diff --git a/tests/ui/unconditional_recursion.stderr b/tests/ui/unconditional_recursion.stderr index 5edccf9593da9..e8bc02f693b08 100644 --- a/tests/ui/unconditional_recursion.stderr +++ b/tests/ui/unconditional_recursion.stderr @@ -278,6 +278,8 @@ LL | self == self error: function cannot return without recursing --> tests/ui/unconditional_recursion.rs:169:13 | +LL | macro_rules! impl_partial_eq { +... LL | / fn eq(&self, other: &Self) -> bool { LL | | LL | | @@ -296,7 +298,6 @@ LL | self == other ... LL | impl_partial_eq!(S5); | -------------------- in this macro invocation - = note: this error originates in the macro `impl_partial_eq` (in Nightly builds, run with -Z macro-backtrace for more info) error: function cannot return without recursing --> tests/ui/unconditional_recursion.rs:199:5 diff --git a/tests/ui/uninhabited_references.stderr b/tests/ui/uninhabited_references.stderr index a76782086d8bc..c2f0dabe41217 100644 --- a/tests/ui/uninhabited_references.stderr +++ b/tests/ui/uninhabited_references.stderr @@ -10,24 +10,24 @@ LL | fn ret_uninh_ref() -> &'static std::convert::Infallible { error: dereferencing a reference to an uninhabited type would be undefined behavior --> tests/ui/uninhabited_references.rs:10:30 | +LL | macro_rules! ret_something { +LL | ($name:ident, $ty:ty) => { LL | fn $name(x: &$ty) -> &$ty { | ^^^^ ... LL | ret_something!(id_never, !); | --------------------------- in this macro invocation - | - = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior --> tests/ui/uninhabited_references.rs:12:14 | +LL | macro_rules! ret_something { +... LL | &*x | ^^ ... LL | ret_something!(id_never, !); | --------------------------- in this macro invocation - | - = note: this error originates in the macro `ret_something` (in Nightly builds, run with -Z macro-backtrace for more info) error: dereferencing a reference to an uninhabited type is undefined behavior --> tests/ui/uninhabited_references.rs:23:13 diff --git a/tests/ui/unnecessary_safety_comment.stderr b/tests/ui/unnecessary_safety_comment.stderr index 6ad94f986434d..c969be5de9064 100644 --- a/tests/ui/unnecessary_safety_comment.stderr +++ b/tests/ui/unnecessary_safety_comment.stderr @@ -63,6 +63,8 @@ LL | // SAFETY: error: impl has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:42:13 | +LL | macro_rules! with_safety_comment { +... LL | impl T for $t {} | ^^^^^^^^^^^^^^^^ ... @@ -74,7 +76,6 @@ help: consider removing the safety comment | LL | // Safety: unnecessary | ^^^^^^^ - = note: this error originates in the macro `with_safety_comment` (in Nightly builds, run with -Z macro-backtrace for more info) error: expression has unnecessary safety comment --> tests/ui/unnecessary_safety_comment.rs:60:5 diff --git a/tests/ui/unnecessary_unsafety_doc.stderr b/tests/ui/unnecessary_unsafety_doc.stderr index cb2fb3119e86e..81d2bd8829c3b 100644 --- a/tests/ui/unnecessary_unsafety_doc.stderr +++ b/tests/ui/unnecessary_unsafety_doc.stderr @@ -34,13 +34,13 @@ LL | pub fn documented() -> Self { error: safe function's docs have unnecessary `# Safety` section --> tests/ui/unnecessary_unsafety_doc.rs:127:9 | +LL | macro_rules! very_safe { +... LL | pub fn drive() { | ^^^^^^^^^^^^^^ ... LL | very_safe!(); | ------------ in this macro invocation - | - = note: this error originates in the macro `very_safe` (in Nightly builds, run with -Z macro-backtrace for more info) error: docs for safe trait have unnecessary `# Safety` section --> tests/ui/unnecessary_unsafety_doc.rs:156:1 diff --git a/tests/ui/unseparated_prefix_literals.stderr b/tests/ui/unseparated_prefix_literals.stderr index 67e47865108e1..924be1b4cee9c 100644 --- a/tests/ui/unseparated_prefix_literals.stderr +++ b/tests/ui/unseparated_prefix_literals.stderr @@ -46,13 +46,13 @@ LL | let _failf2 = 1f32; error: integer type suffix should be separated by an underscore --> tests/ui/unseparated_prefix_literals.rs:14:9 | +LL | macro_rules! lit_from_macro { +LL | () => { LL | 42usize | ^^^^^^^ help: add an underscore: `42_usize` ... LL | let _ = lit_from_macro!(); | ----------------- in this macro invocation - | - = note: this error originates in the macro `lit_from_macro` (in Nightly builds, run with -Z macro-backtrace for more info) error: integer type suffix should be separated by an underscore --> tests/ui/unseparated_prefix_literals.rs:47:16 diff --git a/tests/ui/unused_result_ok.stderr b/tests/ui/unused_result_ok.stderr index e4560aa84dea1..8a16fa4d3b805 100644 --- a/tests/ui/unused_result_ok.stderr +++ b/tests/ui/unused_result_ok.stderr @@ -39,13 +39,14 @@ LL + let _ = v!(); error: ignoring a result with `.ok()` is misleading --> tests/ui/unused_result_ok.rs:30:9 | +LL | macro_rules! w { +LL | () => { LL | Ok::<(), ()>(()).ok(); | ^^^^^^^^^^^^^^^^^^^^^ ... LL | w!(); | ---- in this macro invocation | - = note: this error originates in the macro `w` (in Nightly builds, run with -Z macro-backtrace for more info) help: consider using `let _ =` and removing the call to `.ok()` instead | LL - Ok::<(), ()>(()).ok(); From 3cfab90ecbe8f8d8c105396dcc6f38988edef30c Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 20 Sep 2026 04:32:52 +0000 Subject: [PATCH 0440/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to feaadeeaca7db0594da854e7c8c07495341c7439. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index d5d2fe1388ca6..e861a160a977a 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -971903d9aee24befd88423f42826c232e27c8190 +feaadeeaca7db0594da854e7c8c07495341c7439 From 2a50dca14951e9f84d583bf376aa742ff5a0d557 Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 10 Sep 2026 19:38:04 +0800 Subject: [PATCH 0441/1309] Add regression tests for non-Send field locations --- ...field-location-issue-146016.current.stderr | 90 +++++++++++++++++++ ...nd-field-location-issue-146016.next.stderr | 90 +++++++++++++++++++ .../non-send-field-location-issue-146016.rs | 62 +++++++++++++ 3 files changed, 242 insertions(+) create mode 100644 tests/ui/traits/non-send-field-location-issue-146016.current.stderr create mode 100644 tests/ui/traits/non-send-field-location-issue-146016.next.stderr create mode 100644 tests/ui/traits/non-send-field-location-issue-146016.rs diff --git a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr new file mode 100644 index 0000000000000..e13180a4f1071 --- /dev/null +++ b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr @@ -0,0 +1,90 @@ +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:41:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Record<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:24:8 + | +LL | struct Record { + | ^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:43:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Record<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:24:8 + | +LL | struct Record { + | ^^^^^^ +note: required because it appears within the type `Nested<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:29:8 + | +LL | struct Nested { + | ^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:45:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Multiple<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:33:6 + | +LL | enum Multiple { + | ^^^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:55:27 + | +LL | let h = thread::spawn(move || match rx.recv().unwrap() { + | _____________-------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | Foo::Case(x) => println!("{:?}", x), +LL | | Foo::Case2(b) => println!("{:?}", b), +LL | | }); + | |_____^ `*const c_void` cannot be sent between threads safely + | + = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Foo` + --> $DIR/non-send-field-location-issue-146016.rs:19:6 + | +LL | enum Foo { + | ^^^ + = note: required for `std::sync::mpsc::Receiver` to implement `Send` +note: required because `rx` is used within this closure + --> $DIR/non-send-field-location-issue-146016.rs:55:41 + | +LL | let h = thread::spawn(move || match rx.recv().unwrap() { + | ^^ +note: required by a bound in `spawn` + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr new file mode 100644 index 0000000000000..e13180a4f1071 --- /dev/null +++ b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr @@ -0,0 +1,90 @@ +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:41:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Record<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:24:8 + | +LL | struct Record { + | ^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:43:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Record<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:24:8 + | +LL | struct Record { + | ^^^^^^ +note: required because it appears within the type `Nested<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:29:8 + | +LL | struct Nested { + | ^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:45:20 + | +LL | require_send::>(); + | ^^^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely + | + = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Multiple<*const c_void>` + --> $DIR/non-send-field-location-issue-146016.rs:33:6 + | +LL | enum Multiple { + | ^^^^^^^^ +note: required by a bound in `require_send` + --> $DIR/non-send-field-location-issue-146016.rs:38:20 + | +LL | fn require_send() {} + | ^^^^ required by this bound in `require_send` + +error[E0277]: `*const c_void` cannot be sent between threads safely + --> $DIR/non-send-field-location-issue-146016.rs:55:27 + | +LL | let h = thread::spawn(move || match rx.recv().unwrap() { + | _____________-------------_^ + | | | + | | required by a bound introduced by this call +LL | | +LL | | Foo::Case(x) => println!("{:?}", x), +LL | | Foo::Case2(b) => println!("{:?}", b), +LL | | }); + | |_____^ `*const c_void` cannot be sent between threads safely + | + = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` +note: required because it appears within the type `Foo` + --> $DIR/non-send-field-location-issue-146016.rs:19:6 + | +LL | enum Foo { + | ^^^ + = note: required for `std::sync::mpsc::Receiver` to implement `Send` +note: required because `rx` is used within this closure + --> $DIR/non-send-field-location-issue-146016.rs:55:41 + | +LL | let h = thread::spawn(move || match rx.recv().unwrap() { + | ^^ +note: required by a bound in `spawn` + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/non-send-field-location-issue-146016.rs b/tests/ui/traits/non-send-field-location-issue-146016.rs new file mode 100644 index 0000000000000..9f9cd6a20e48b --- /dev/null +++ b/tests/ui/traits/non-send-field-location-issue-146016.rs @@ -0,0 +1,62 @@ +//@ revisions: current next +//@ [next] compile-flags: -Znext-solver +//@ edition: 2024 + +//! Regression test for https://github.com/rust-lang/rust/issues/146016. +//! Locate the field that introduces an auto-trait requirement, even through a type alias. + +use std::sync::mpsc; +use std::thread; + +mod other { + use std::ffi::c_void; + + pub type Bar = *const c_void; +} + +use other::Bar; + +enum Foo { + Case(i32), + Case2(Bar), +} + +struct Record { + unrelated: u8, + value: T, +} + +struct Nested { + value: Record, +} + +enum Multiple { + Empty, + Values { first: T, second: T }, +} + +fn require_send() {} + +fn generic_fields() { + require_send::>(); + //~^ ERROR `*const c_void` cannot be sent between threads safely + require_send::>(); + //~^ ERROR `*const c_void` cannot be sent between threads safely + require_send::>(); + //~^ ERROR `*const c_void` cannot be sent between threads safely + + require_send::>(); + require_send::>(); + require_send::>(); +} + +fn main() { + let (tx, rx) = mpsc::channel(); + let h = thread::spawn(move || match rx.recv().unwrap() { + //~^ ERROR `*const c_void` cannot be sent between threads safely + Foo::Case(x) => println!("{:?}", x), + Foo::Case2(b) => println!("{:?}", b), + }); + tx.send(Foo::Case2(std::ptr::null())); + h.join(); +} From 07f15ab580e5632b9dcd4ca5e660730c60b6d3bf Mon Sep 17 00:00:00 2001 From: Zalathar Date: Sun, 20 Sep 2026 13:41:07 +1000 Subject: [PATCH 0442/1309] Use the full path of `bug_impl` to avoid bogus errors in rust-analyzer For whatever reason, rust-analyzer doesn't understand hygienic macros well enough to properly resolve this function call, which leads to bogus type errors appearing in rust-analyzer because it doesn't know that the function returns `!` and therefore must diverge. (For example, if `bug!(..);` with a trailing semicolon is used in the else block of a let-else statement, rust-analyzer will complain about it even though rustc is happy.) If we specify the full path to the function, both rustc and rust-analyzer agree that it diverges. --- compiler/rustc_span/src/macros.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_span/src/macros.rs b/compiler/rustc_span/src/macros.rs index db8b7ebbfa11f..58db6ef66f43b 100644 --- a/compiler/rustc_span/src/macros.rs +++ b/compiler/rustc_span/src/macros.rs @@ -25,7 +25,9 @@ pub macro bug { bug!("impossible case reached") ), ($($arg:tt)+) => ( - bug_impl(None, std::format_args!($($arg)+), Location::caller()) + // Use the full path of `bug_impl` to make sure rust-analyzer can resolve it, + // to avoid bogus type errors about `()` versus `!`. + $crate::macros::bug_impl(None, std::format_args!($($arg)+), Location::caller()) ), } @@ -39,7 +41,9 @@ pub macro bug { /// /// [`DiagCtxtHandle::span_delayed_bug`]: ../../rustc_errors/struct.DiagCtxtHandle.html#method.span_delayed_bug pub macro span_bug($span:expr, $($arg:tt)+){ - bug_impl(Some($span), std::format_args!($($arg)+), Location::caller()) + // Use the full path of `bug_impl` to make sure rust-analyzer can resolve it, + // to avoid bogus type errors about `()` versus `!`. + $crate::macros::bug_impl(Some($span), std::format_args!($($arg)+), Location::caller()) } #[cold] From f69eeb67cf5c7a138b6d0a007064e9b9d1cc87f3 Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 20 Sep 2026 16:17:20 +0800 Subject: [PATCH 0443/1309] Point to fields that introduce trait requirements --- .../src/error_reporting/traits/suggestions.rs | 20 ++++++++++++-- tests/ui/associated-consts/issue-58022.stderr | 2 +- .../issue-70935-complex-spans.stderr | 2 +- .../issue-72590-type-error-sized.stderr | 3 +++ .../async-await/pin-needed-to-poll-2.stderr | 2 +- .../auto-trait-phantom-data-bounds.stderr | 6 ++++- .../builtin-superkinds-in-metadata.stderr | 2 +- tests/ui/coherence/deep-bad-copy-reason.rs | 1 + .../ui/coherence/deep-bad-copy-reason.stderr | 11 +++++--- tests/ui/deref/pin-impl-deref.stderr | 4 +-- tests/ui/did_you_mean/recursion_limit.stderr | 27 +++++++++++++++++++ tests/ui/dst/dst-bad-deep-2.stderr | 2 +- tests/ui/dst/dst-bad-deep.stderr | 2 ++ tests/ui/error-codes/E0277-2.stderr | 6 +++++ tests/ui/extern/extern-types-unsized.stderr | 9 +++++++ .../feature-gate-offset-of-slice.stderr | 3 +++ .../feature-gate-trivial_bounds.stderr | 2 ++ tests/ui/mut/mutable-enum-indirect.stderr | 2 +- tests/ui/offset-of/offset-of-dst-field.stderr | 3 +++ tests/ui/pin-ergonomics/pin-pattern.stderr | 2 +- .../recursion/recursive-requirements.stderr | 7 +++++ tests/ui/sized-hierarchy/impls.stderr | 18 ++++++++----- tests/ui/statics/unsized_type2.stderr | 4 +++ .../unsizing-wfcheck-issue-127299.stderr | 2 ++ tests/ui/suggestions/suggest-pin-macro.stderr | 2 ++ .../ui/threads-sendsync/rc-is-not-send.stderr | 4 ++- ...-level-send-bound-check-issue-40827.stderr | 8 ++++-- tests/ui/traits/cycle-cache-err-60010.stderr | 4 +++ .../ui/traits/enum-negative-send-impl.stderr | 2 ++ .../ui/traits/enum-negative-sync-impl.stderr | 2 ++ tests/ui/traits/issue-7013.stderr | 2 ++ .../negated-auto-traits-error.stderr | 2 +- ...field-location-issue-146016.current.stderr | 16 +++++++++++ ...nd-field-location-issue-146016.next.stderr | 16 +++++++++++ .../opaque-trait-size-error-5883.stderr | 2 ++ tests/ui/traits/suggest-where-clause.stderr | 2 +- .../trivial-unsized-projection-2.bad.stderr | 4 +-- ...rivial-unsized-projection-2.bad_new.stderr | 2 +- ...ck-default-trait-impl-negation-sync.stderr | 4 +++ .../typeck/typeck-unsafe-always-share.stderr | 2 ++ .../issue-50940-with-feature.stderr | 2 +- tests/ui/unsized-locals/unsized-exprs.stderr | 4 +-- tests/ui/unsized/unsized-enum2.stderr | 8 +++--- tests/ui/unsized/unsized-struct.stderr | 2 +- tests/ui/unsized/unsized3.stderr | 8 ++++++ tests/ui/wf/let-pat-inferred-non-wf.stderr | 2 +- 46 files changed, 203 insertions(+), 39 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 8de0514b9ef27..edfb203042cbe 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4449,11 +4449,27 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { format!("required because it appears within the type `{ty_str}`") }; match *ty.kind() { - ty::Adt(def, _) => { + ty::Adt(def, args) => { let msg = msg(); match tcx.opt_item_ident(def.did()) { Some(ident) => { - err.span_note(ident.span, msg); + let mut spans = MultiSpan::from(ident.span); + if def.did().is_local() + && let Some(pred) = predicate.as_trait_clause() + { + let field_ty = self.deeply_resolve_ignoring_regions( + pred.skip_binder().self_ty(), + ); + for field in def.all_fields() { + if field.ty(tcx, args).skip_norm_wip() == field_ty { + spans.push_span_label( + tcx.def_span(field.did), + "required by this field", + ); + } + } + } + err.span_note(spans, msg); } None => { err.note(msg); diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr index 24cec6e141bea..2ef3083d0e925 100644 --- a/tests/ui/associated-consts/issue-58022.stderr +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -9,7 +9,7 @@ note: required because it appears within the type `Bar<[u8]>` --> $DIR/issue-58022.rs:8:12 | LL | pub struct Bar(T); - | ^^^ + | ^^^ - required by this field = note: the return type of a function must have a statically known size error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index b9180c620b0dc..9f8f1461bd309 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -11,7 +11,7 @@ note: required because it appears within the type `NotSync` --> $DIR/issue-70935-complex-spans.rs:9:8 | LL | struct NotSync(PhantomData<*mut ()>); - | ^^^^^^^ + | ^^^^^^^ -------------------- required by this field = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure --> $DIR/issue-70935-complex-spans.rs:18:13 diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr index 1d030278fd64e..70f615f03186e 100644 --- a/tests/ui/async-await/issue-72590-type-error-sized.stderr +++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr @@ -22,6 +22,9 @@ note: required because it appears within the type `Foo` | LL | struct Foo { | ^^^ +LL | foo: Nonexistent, +LL | other: str + | ---------- required by this field = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index 8eb671531e792..b7ca47ac4dde2 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -12,7 +12,7 @@ note: required because it appears within the type `Sleep` --> $DIR/pin-needed-to-poll-2.rs:8:8 | LL | struct Sleep(std::marker::PhantomPinned); - | ^^^^^ + | ^^^^^ -------------------------- required by this field note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL diff --git a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr index 56c2e8ff257b7..c37695411d736 100644 --- a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr +++ b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr @@ -18,6 +18,8 @@ note: required because it appears within the type `Guard<'_, T>` | LL | struct Guard<'a, T: 'a> { | ^^^^^ +LL | _marker: PhantomData<&'a T>, + | --------------------------- required by this field note: required by a bound in `is_zen` --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | @@ -48,11 +50,13 @@ note: required because it appears within the type `Guard<'_, T>` | LL | struct Guard<'a, T: 'a> { | ^^^^^ +LL | _marker: PhantomData<&'a T>, + | --------------------------- required by this field note: required because it appears within the type `Nested>` --> $DIR/auto-trait-phantom-data-bounds.rs:16:8 | LL | struct Nested(T); - | ^^^^^^ + | ^^^^^^ - required by this field note: required by a bound in `is_zen` --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index 39a04186981f3..ff26f715d158e 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -8,7 +8,7 @@ note: required because it appears within the type `X` --> $DIR/builtin-superkinds-in-metadata.rs:9:8 | LL | struct X(T); - | ^ + | ^ - required by this field note: required by a bound in `RequiresRequiresShareAndSend` --> $DIR/auxiliary/trait_superkinds_in_metadata.rs:7:58 | diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index f1c2698bad5cc..d93a46f1fcb1a 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -9,6 +9,7 @@ pub struct ListS { len: usize, data: [T; 0], opaque: OpaqueListContents, + //~^ NOTE required by this field } pub struct Interned<'a, T>(&'a T); diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index 534f26c39c2d4..198ea1d75e388 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -1,5 +1,5 @@ error[E0204]: the trait `Copy` cannot be implemented for this type - --> $DIR/deep-bad-copy-reason.rs:38:24 + --> $DIR/deep-bad-copy-reason.rs:39:24 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ------------------------ this field does not implement `Copy` @@ -8,13 +8,13 @@ LL | impl<'tcx, T> Copy for List<'tcx, T> {} | ^^^^^^^^^^^^^ | note: the `Copy` impl for `Interned<'tcx, ListS>` requires that `OpaqueListContents: Sized` - --> $DIR/deep-bad-copy-reason.rs:26:26 + --> $DIR/deep-bad-copy-reason.rs:27:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the size for values of type `OpaqueListContents` cannot be known at compilation time - --> $DIR/deep-bad-copy-reason.rs:26:26 + --> $DIR/deep-bad-copy-reason.rs:27:26 | LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | ^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time @@ -25,8 +25,11 @@ note: required because it appears within the type `ListS` | LL | pub struct ListS { | ^^^^^ +... +LL | opaque: OpaqueListContents, + | -------------------------- required by this field note: required by an implicit `Sized` bound in `Interned` - --> $DIR/deep-bad-copy-reason.rs:14:25 + --> $DIR/deep-bad-copy-reason.rs:15:25 | LL | pub struct Interned<'a, T>(&'a T); | ^ required by the implicit `Sized` requirement on this type parameter in `Interned` diff --git a/tests/ui/deref/pin-impl-deref.stderr b/tests/ui/deref/pin-impl-deref.stderr index 4143d66f42723..5e0e0aa06715b 100644 --- a/tests/ui/deref/pin-impl-deref.stderr +++ b/tests/ui/deref/pin-impl-deref.stderr @@ -44,7 +44,7 @@ note: required because it appears within the type `MyPinType` --> $DIR/pin-impl-deref.rs:15:8 | LL | struct MyPinType(core::marker::PhantomPinned); - | ^^^^^^^^^ + | ^^^^^^^^^ --------------------------- required by this field = note: required for `Pin<&MyPinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 @@ -66,7 +66,7 @@ note: required because it appears within the type `MyPinType` --> $DIR/pin-impl-deref.rs:15:8 | LL | struct MyPinType(core::marker::PhantomPinned); - | ^^^^^^^^^ + | ^^^^^^^^^ --------------------------- required by this field = note: required for `Pin<&mut MyPinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 diff --git a/tests/ui/did_you_mean/recursion_limit.stderr b/tests/ui/did_you_mean/recursion_limit.stderr index 2ecee2030b03f..7960efec9957e 100644 --- a/tests/ui/did_you_mean/recursion_limit.stderr +++ b/tests/ui/did_you_mean/recursion_limit.stderr @@ -8,46 +8,73 @@ LL | is_send::(); note: required because it appears within the type `I` --> $DIR/recursion_limit.rs:23:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { I, J } | ^ note: required because it appears within the type `H` --> $DIR/recursion_limit.rs:22:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { H, I } | ^ note: required because it appears within the type `G` --> $DIR/recursion_limit.rs:21:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { G, H } | ^ note: required because it appears within the type `F` --> $DIR/recursion_limit.rs:20:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { F, G } | ^ note: required because it appears within the type `E` --> $DIR/recursion_limit.rs:19:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { E, F } | ^ note: required because it appears within the type `D` --> $DIR/recursion_limit.rs:18:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { D, E } | ^ note: required because it appears within the type `C` --> $DIR/recursion_limit.rs:17:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { C, D } | ^ note: required because it appears within the type `B` --> $DIR/recursion_limit.rs:16:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { B, C } | ^ note: required because it appears within the type `A` --> $DIR/recursion_limit.rs:15:9 | +LL | enum $id { $id($t) } + | -- required by this field +... LL | link! { A, B } | ^ note: required by a bound in `is_send` diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr index de3f71d206fb4..790e6dff9b5ef 100644 --- a/tests/ui/dst/dst-bad-deep-2.stderr +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -9,7 +9,7 @@ note: required because it appears within the type `Fat<[isize]>` --> $DIR/dst-bad-deep-2.rs:6:8 | LL | struct Fat(T); - | ^^^ + | ^^^ - required by this field = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr index 1b0f9738ab09a..bf9baa8e7e3c9 100644 --- a/tests/ui/dst/dst-bad-deep.stderr +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -10,6 +10,8 @@ note: required because it appears within the type `Fat<[isize]>` | LL | struct Fat { | ^^^ +LL | ptr: T + | ------ required by this field = note: structs must have a statically known size to be initialized error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr index 9a262f7559075..9cf2d5c4fcc65 100644 --- a/tests/ui/error-codes/E0277-2.stderr +++ b/tests/ui/error-codes/E0277-2.stderr @@ -10,16 +10,22 @@ note: required because it appears within the type `Baz` | LL | struct Baz { | ^^^ +LL | x: *const u8 + | ------------ required by this field note: required because it appears within the type `Bar` --> $DIR/E0277-2.rs:5:8 | LL | struct Bar { | ^^^ +LL | baz: Baz + | -------- required by this field note: required because it appears within the type `Foo` --> $DIR/E0277-2.rs:1:8 | LL | struct Foo { | ^^^ +LL | bar: Bar + | -------- required by this field note: required by a bound in `is_send` --> $DIR/E0277-2.rs:13:15 | diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index 6c1d7a7b61b3c..c4c919cd646b4 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -27,6 +27,9 @@ note: required because it appears within the type `Foo` | LL | struct Foo { | ^^^ +LL | x: u8, +LL | tail: A, + | ------- required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | @@ -49,6 +52,9 @@ note: required because it appears within the type `Bar` | LL | struct Bar { | ^^^ +LL | x: u8, +LL | tail: T, + | ------- required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | @@ -84,6 +90,9 @@ note: required because it appears within the type `Bar` | LL | struct Bar { | ^^^ +LL | x: u8, +LL | tail: T, + | ------- required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | diff --git a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr index 83b0acf88bdb5..4ac4472b78e0e 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr @@ -18,6 +18,9 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +... +LL | c: [i32], + | -------- required by this field error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/feature-gate-offset-of-slice.rs:25:5 diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index e9bee1597c5cd..76695064dec16 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -141,6 +141,8 @@ note: required because it appears within the type `Dst<(dyn A + 'static)>` | LL | struct Dst { | ^^^ +LL | x: X, + | ---- required by this field help: add `#![feature(trivial_bounds)]` to the crate attributes to enable | LL + #![feature(trivial_bounds)] diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr index b15492357f5c8..40ece8bce9ab5 100644 --- a/tests/ui/mut/mutable-enum-indirect.stderr +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -15,7 +15,7 @@ note: required because it appears within the type `Foo` --> $DIR/mutable-enum-indirect.rs:11:6 | LL | enum Foo { A(NoSync) } - | ^^^ + | ^^^ ------ required by this field = note: required because it appears within the type `&Foo` note: required by a bound in `bar` --> $DIR/mutable-enum-indirect.rs:13:11 diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index 77ae34b0872fa..1bceb3c409177 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -58,6 +58,9 @@ note: required because it appears within the type `Alpha` | LL | struct Alpha { | ^^^^^ +... +LL | z: [u8], + | ------- required by this field error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/offset-of-dst-field.rs:51:5 diff --git a/tests/ui/pin-ergonomics/pin-pattern.stderr b/tests/ui/pin-ergonomics/pin-pattern.stderr index c0e8b2d40c70f..5262de183e749 100644 --- a/tests/ui/pin-ergonomics/pin-pattern.stderr +++ b/tests/ui/pin-ergonomics/pin-pattern.stderr @@ -36,7 +36,7 @@ note: required because it appears within the type `Foo` --> $DIR/pin-pattern.rs:11:8 | LL | struct Foo(T); - | ^^^ + | ^^^ - required by this field help: consider restricting type parameter `T` with trait `Unpin` | LL | fn tuple_ref_pin_mut_pat_and_mut_of_tuple_pin_mut_ty<'a, T: std::marker::Unpin>( diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr index bb63f7cd0dce0..d4197eded7d28 100644 --- a/tests/ui/recursion/recursive-requirements.stderr +++ b/tests/ui/recursion/recursive-requirements.stderr @@ -10,6 +10,8 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ +LL | bar: *const Bar, + | --------------- required by this field note: required by a bound in `AssertSync` --> $DIR/recursive-requirements.rs:3:22 | @@ -28,6 +30,8 @@ note: required because it appears within the type `Bar` | LL | pub struct Bar { | ^^^ +LL | foo: *const Foo, + | --------------- required by this field note: required because it appears within the type `PhantomData` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Foo` @@ -35,6 +39,9 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ +LL | bar: *const Bar, +LL | phantom: PhantomData, + | ------------------------- required by this field note: required by a bound in `AssertSync` --> $DIR/recursive-requirements.rs:3:22 | diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr index 25c6c933149fd..1e0f234ce19a4 100644 --- a/tests/ui/sized-hierarchy/impls.stderr +++ b/tests/ui/sized-hierarchy/impls.stderr @@ -292,7 +292,9 @@ note: required because it appears within the type `StructAllFieldsMetaSized` --> $DIR/impls.rs:235:12 | LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ ------- ------- required by this field + | | + | required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -310,7 +312,9 @@ note: required because it appears within the type `StructAllFieldsUnsized` --> $DIR/impls.rs:243:12 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ------ ------ required by this field + | | + | required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -328,7 +332,9 @@ note: required because it appears within the type `StructAllFieldsUnsized` --> $DIR/impls.rs:243:12 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ------ ------ required by this field + | | + | required by this field note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 | @@ -346,7 +352,7 @@ note: required because it appears within the type `StructLastFieldMetaSized` --> $DIR/impls.rs:252:12 | LL | struct StructLastFieldMetaSized { x: u32, y: [u8] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -364,7 +370,7 @@ note: required because it appears within the type `StructLastFieldUnsized` --> $DIR/impls.rs:259:12 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ------ required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -382,7 +388,7 @@ note: required because it appears within the type `StructLastFieldUnsized` --> $DIR/impls.rs:259:12 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^^^^^^^^^^ ------ required by this field note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 | diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr index 293df7554e99f..5bccabf0bc133 100644 --- a/tests/ui/statics/unsized_type2.stderr +++ b/tests/ui/statics/unsized_type2.stderr @@ -10,6 +10,8 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ +LL | pub version: str, + | ---------------- required by this field = note: statics and constants must have a statically known size error[E0308]: mismatched types @@ -30,6 +32,8 @@ note: required because it appears within the type `Foo` | LL | pub struct Foo { | ^^^ +LL | pub version: str, + | ---------------- required by this field = note: structs must have a statically known size to be initialized error: aborting due to 3 previous errors diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index e231d57a26d91..1467de675be56 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -34,6 +34,8 @@ note: required because it appears within the type `Lint` | LL | pub struct Lint { | ^^^^ +LL | pub desc: &'static dyn Qux, + | -------------------------- required by this field = note: required because it appears within the type `&'static Lint` = note: shared static variables must have a type that implements `Sync` diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr index a761a454ad5a3..c1877fae753c8 100644 --- a/tests/ui/suggestions/suggest-pin-macro.stderr +++ b/tests/ui/suggestions/suggest-pin-macro.stderr @@ -11,6 +11,8 @@ note: required because it appears within the type `Test` | LL | struct Test { | ^^^^ +LL | _marker: PhantomPinned, + | ---------------------- required by this field note: required by a bound in `Pin::<&'a mut T>::get_mut` --> $SRC_DIR/core/src/pin.rs:LL:COL diff --git a/tests/ui/threads-sendsync/rc-is-not-send.stderr b/tests/ui/threads-sendsync/rc-is-not-send.stderr index 28a74d89def6c..03e4b582cd0eb 100644 --- a/tests/ui/threads-sendsync/rc-is-not-send.stderr +++ b/tests/ui/threads-sendsync/rc-is-not-send.stderr @@ -18,12 +18,14 @@ note: required because it appears within the type `Port<()>` --> $DIR/rc-is-not-send.rs:7:8 | LL | struct Port(Rc); - | ^^^^ + | ^^^^ ----- required by this field note: required because it appears within the type `Foo` --> $DIR/rc-is-not-send.rs:10:8 | LL | struct Foo { | ^^^ +LL | _x: Port<()>, + | ------------ required by this field note: required because `x` is used within this closure --> $DIR/rc-is-not-send.rs:27:17 | diff --git a/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr b/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr index 3776c355318d0..bd4cabc78c990 100644 --- a/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr +++ b/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr @@ -12,12 +12,14 @@ note: required because it appears within the type `Bar` | LL | enum Bar { | ^^^ +LL | A(Rc), + | ------- required by this field = note: required for `Arc` to implement `Send` note: required because it appears within the type `Foo` --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:8 | LL | struct Foo(Arc); - | ^^^ + | ^^^ -------- required by this field note: required by a bound in `f` --> $DIR/deep-level-send-bound-check-issue-40827.rs:11:9 | @@ -38,12 +40,14 @@ note: required because it appears within the type `Bar` | LL | enum Bar { | ^^^ +LL | A(Rc), + | ------- required by this field = note: required for `Arc` to implement `Send` note: required because it appears within the type `Foo` --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:8 | LL | struct Foo(Arc); - | ^^^ + | ^^^ -------- required by this field note: required by a bound in `f` --> $DIR/deep-level-send-bound-check-issue-40827.rs:11:9 | diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 9665d5badf599..e7aba17e060c3 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -20,6 +20,8 @@ note: required because it appears within the type `RootDatabase` | LL | struct RootDatabase { | ^^^^^^^^^^^^ +LL | _runtime: Runtime, + | ------------------------------- required by this field note: required for `RootDatabase` to implement `SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:43:9 | @@ -59,6 +61,8 @@ note: required because it appears within the type `RootDatabase` | LL | struct RootDatabase { | ^^^^^^^^^^^^ +LL | _runtime: Runtime, + | ------------------------------- required by this field note: required for `RootDatabase` to implement `SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:43:9 | diff --git a/tests/ui/traits/enum-negative-send-impl.stderr b/tests/ui/traits/enum-negative-send-impl.stderr index 2aad2265797e6..645d6d856eb1c 100644 --- a/tests/ui/traits/enum-negative-send-impl.stderr +++ b/tests/ui/traits/enum-negative-send-impl.stderr @@ -16,6 +16,8 @@ note: required because it appears within the type `Container` | LL | enum Container { | ^^^^^^^^^ +LL | WithNoSend(NoSend), + | ------ required by this field note: required by a bound in `requires_send` --> $DIR/enum-negative-send-impl.rs:16:21 | diff --git a/tests/ui/traits/enum-negative-sync-impl.stderr b/tests/ui/traits/enum-negative-sync-impl.stderr index b4ab69afb421d..8fdfbe6876266 100644 --- a/tests/ui/traits/enum-negative-sync-impl.stderr +++ b/tests/ui/traits/enum-negative-sync-impl.stderr @@ -16,6 +16,8 @@ note: required because it appears within the type `Container` | LL | enum Container { | ^^^^^^^^^ +LL | WithNoSync(NoSync), + | ------ required by this field note: required by a bound in `requires_sync` --> $DIR/enum-negative-sync-impl.rs:16:21 | diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr index 1749366317286..8621072272259 100644 --- a/tests/ui/traits/issue-7013.stderr +++ b/tests/ui/traits/issue-7013.stderr @@ -12,6 +12,8 @@ note: required because it appears within the type `B` | LL | struct B { | ^ +LL | v: Option>> + | ------------------------- required by this field = note: required for the cast from `Box` to `Box` error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index b7d8484e1041e..356e0b9c18cd6 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -112,7 +112,7 @@ note: required because it appears within the type `Outer2` --> $DIR/negated-auto-traits-error.rs:12:8 | LL | struct Outer2(T); - | ^^^^^^ + | ^^^^^^ - required by this field = note: required for `std::ptr::Unique>` to implement `Send` note: required because it appears within the type `Box>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr index e13180a4f1071..1aad4cb4c7685 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr @@ -10,6 +10,9 @@ note: required because it appears within the type `Record<*const c_void>` | LL | struct Record { | ^^^^^^ +LL | unrelated: u8, +LL | value: T, + | -------- required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -28,11 +31,16 @@ note: required because it appears within the type `Record<*const c_void>` | LL | struct Record { | ^^^^^^ +LL | unrelated: u8, +LL | value: T, + | -------- required by this field note: required because it appears within the type `Nested<*const c_void>` --> $DIR/non-send-field-location-issue-146016.rs:29:8 | LL | struct Nested { | ^^^^^^ +LL | value: Record, + | ---------------- required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -51,6 +59,11 @@ note: required because it appears within the type `Multiple<*const c_void>` | LL | enum Multiple { | ^^^^^^^^ +LL | Empty, +LL | Values { first: T, second: T }, + | -------- --------- required by this field + | | + | required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -76,6 +89,9 @@ note: required because it appears within the type `Foo` | LL | enum Foo { | ^^^ +LL | Case(i32), +LL | Case2(Bar), + | --- required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure --> $DIR/non-send-field-location-issue-146016.rs:55:41 diff --git a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr index e13180a4f1071..1aad4cb4c7685 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr @@ -10,6 +10,9 @@ note: required because it appears within the type `Record<*const c_void>` | LL | struct Record { | ^^^^^^ +LL | unrelated: u8, +LL | value: T, + | -------- required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -28,11 +31,16 @@ note: required because it appears within the type `Record<*const c_void>` | LL | struct Record { | ^^^^^^ +LL | unrelated: u8, +LL | value: T, + | -------- required by this field note: required because it appears within the type `Nested<*const c_void>` --> $DIR/non-send-field-location-issue-146016.rs:29:8 | LL | struct Nested { | ^^^^^^ +LL | value: Record, + | ---------------- required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -51,6 +59,11 @@ note: required because it appears within the type `Multiple<*const c_void>` | LL | enum Multiple { | ^^^^^^^^ +LL | Empty, +LL | Values { first: T, second: T }, + | -------- --------- required by this field + | | + | required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -76,6 +89,9 @@ note: required because it appears within the type `Foo` | LL | enum Foo { | ^^^ +LL | Case(i32), +LL | Case2(Bar), + | --- required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure --> $DIR/non-send-field-location-issue-146016.rs:55:41 diff --git a/tests/ui/traits/opaque-trait-size-error-5883.stderr b/tests/ui/traits/opaque-trait-size-error-5883.stderr index 78de250b19a1e..1cb25b281ce84 100644 --- a/tests/ui/traits/opaque-trait-size-error-5883.stderr +++ b/tests/ui/traits/opaque-trait-size-error-5883.stderr @@ -10,6 +10,8 @@ note: required because it appears within the type `Struct` | LL | struct Struct { | ^^^^^^ +LL | r: dyn A + 'static + | ------------------ required by this field = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index d01cd26730c59..e56c7cd518bd2 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -28,7 +28,7 @@ note: required because it appears within the type `Misc` --> $DIR/suggest-where-clause.rs:3:8 | LL | struct Misc(T); - | ^^^^ + | ^^^^ - required by this field note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr index bf8d3c40cf653..d3b3b3be61f8f 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr @@ -9,7 +9,7 @@ note: required because it appears within the type `Tail` --> $DIR/trivial-unsized-projection-2.rs:17:8 | LL | struct Tail([()]); - | ^^^^ + | ^^^^ ---- required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | @@ -34,7 +34,7 @@ note: required because it appears within the type `Tail` --> $DIR/trivial-unsized-projection-2.rs:17:8 | LL | struct Tail([()]); - | ^^^^ + | ^^^^ ---- required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr index fcac02bc0a049..6f8558547026a 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr @@ -15,7 +15,7 @@ note: required because it appears within the type `Tail` --> $DIR/trivial-unsized-projection-2.rs:17:8 | LL | struct Tail([()]); - | ^^^^ + | ^^^^ ---- required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index 92629704c8986..00ad61a6d7794 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -27,6 +27,8 @@ note: required because it appears within the type `MyTypeWUnsafe` | LL | struct MyTypeWUnsafe { | ^^^^^^^^^^^^^ +LL | t: UnsafeCell + | ----------------- required by this field note: required by a bound in `is_sync` --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 | @@ -49,6 +51,8 @@ note: required because it appears within the type `MyTypeManaged` | LL | struct MyTypeManaged { | ^^^^^^^^^^^^^ +LL | t: Managed + | ---------- required by this field note: required by a bound in `is_sync` --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 | diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr index c680c6ee27bf0..6239db91b52e8 100644 --- a/tests/ui/typeck/typeck-unsafe-always-share.stderr +++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr @@ -42,6 +42,8 @@ note: required because it appears within the type `MySync` | LL | struct MySync { | ^^^^^^ +LL | u: UnsafeCell + | ---------------- required by this field note: required by a bound in `test` --> $DIR/typeck-unsafe-always-share.rs:15:12 | diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index f3fb3ac1a09ff..a0d7e9c6cba31 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -9,7 +9,7 @@ note: required because it appears within the type `A` --> $DIR/issue-50940-with-feature.rs:4:12 | LL | struct A(X); - | ^ + | ^ - required by this field = note: the return type of a function must have a statically known size error: aborting due to 1 previous error diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr index 0455edbe8e77b..8d6156446d26f 100644 --- a/tests/ui/unsized-locals/unsized-exprs.stderr +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -9,7 +9,7 @@ note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | LL | struct A(X); - | ^ + | ^ - required by this field note: unsized values must be place expressions and cannot be put in temporaries --> $DIR/unsized-exprs.rs:19:22 | @@ -27,7 +27,7 @@ note: required because it appears within the type `A<[u8]>` --> $DIR/unsized-exprs.rs:3:8 | LL | struct A(X); - | ^ + | ^ - required by this field note: unsized values must be place expressions and cannot be put in temporaries --> $DIR/unsized-exprs.rs:21:22 | diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr index 71cf782120e57..20cf2556c5df7 100644 --- a/tests/ui/unsized/unsized-enum2.stderr +++ b/tests/ui/unsized/unsized-enum2.stderr @@ -325,7 +325,7 @@ note: required because it appears within the type `Path1` --> $DIR/unsized-enum2.rs:16:8 | LL | struct Path1(dyn PathHelper1); - | ^^^^^ + | ^^^^^ --------------- required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -348,7 +348,7 @@ note: required because it appears within the type `Path2` --> $DIR/unsized-enum2.rs:17:8 | LL | struct Path2(dyn PathHelper2); - | ^^^^^ + | ^^^^^ --------------- required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -371,7 +371,7 @@ note: required because it appears within the type `Path3` --> $DIR/unsized-enum2.rs:18:8 | LL | struct Path3(dyn PathHelper3); - | ^^^^^ + | ^^^^^ --------------- required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -394,7 +394,7 @@ note: required because it appears within the type `Path4` --> $DIR/unsized-enum2.rs:19:8 | LL | struct Path4(dyn PathHelper4); - | ^^^^^ + | ^^^^^ --------------- required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr index 06c4ffb7773c6..d7d392cf9e5f6 100644 --- a/tests/ui/unsized/unsized-struct.stderr +++ b/tests/ui/unsized/unsized-struct.stderr @@ -36,7 +36,7 @@ note: required because it appears within the type `Bar` --> $DIR/unsized-struct.rs:11:8 | LL | struct Bar { data: T } - | ^^^ + | ^^^ ------- required by this field note: required by a bound in `is_sized` --> $DIR/unsized-struct.rs:1:15 | diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr index c7a145b1c5171..547bb9ca62e34 100644 --- a/tests/ui/unsized/unsized3.stderr +++ b/tests/ui/unsized/unsized3.stderr @@ -59,6 +59,8 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +LL | x: X, + | ---- required by this field note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | @@ -87,6 +89,8 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +LL | x: X, + | ---- required by this field = note: only the last element of a tuple may have a dynamically sized type help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -107,6 +111,8 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +LL | x: X, + | ---- required by this field = note: required because it appears within the type `({integer}, S)` = note: tuples must have a statically known size to be initialized help: consider removing the `?Sized` bound to make the type parameter `Sized` @@ -130,6 +136,8 @@ note: required because it appears within the type `S` | LL | struct S { | ^ +LL | x: X, + | ---- required by this field = note: required because it appears within the type `({integer}, S)` note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr index 1c524a22b432b..d05ed37578820 100644 --- a/tests/ui/wf/let-pat-inferred-non-wf.stderr +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -54,7 +54,7 @@ note: required because it appears within the type `S` --> $DIR/let-pat-inferred-non-wf.rs:8:8 | LL | struct S(T); - | ^ + | ^ - required by this field = note: slice and array elements must have `Sized` type error: aborting due to 6 previous errors From 713fef39f2e674373353f47da592868f5f1cf68a Mon Sep 17 00:00:00 2001 From: Adwin White Date: Sun, 20 Sep 2026 17:38:00 +0800 Subject: [PATCH 0444/1309] stop computing overflowed goal chain for crate dependencies --- compiler/rustc_trait_selection/src/solve/delegate.rs | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c67a4bdd329b0..eee6714e64fcd 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -521,8 +521,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< predicates: vec![], recursion_limit: usize::min(16, tcx.recursion_limit().0), }; - let _ = self - .with_disabled_next_solver_overflow_fcw(|| self.visit_proof_tree(goal, &mut visitor)); + + // HACK: avoid computing goal chains for dependencies by relying on the fact that + // `cargo` passes `lint_cap=allow` to deps. This should mitigate some of the perf/rss + // regression when compiling crates whose deps trigger a large number of these FCWs. + if !matches!(tcx.sess.opts.lint_cap, Some(rustc_lint_defs::Level::Allow)) { + let _ = self.with_disabled_next_solver_overflow_fcw(|| { + self.visit_proof_tree(goal, &mut visitor) + }); + } + tcx.emit_node_span_lint( RECURSION_DEPTH_EXCEEDING_LIMIT, CRATE_HIR_ID, From 428aeee7d9dc358d1c611cbb8e59bf25d6af5307 Mon Sep 17 00:00:00 2001 From: Oleksandr Babak Date: Sun, 20 Sep 2026 11:35:25 +0200 Subject: [PATCH 0445/1309] Restore `Send` and `Sync` for `BorrowedCursor` --- library/core/src/io/borrowed_buf.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/core/src/io/borrowed_buf.rs b/library/core/src/io/borrowed_buf.rs index 7b03d58a3fd62..2cc1ebba1a85c 100644 --- a/library/core/src/io/borrowed_buf.rs +++ b/library/core/src/io/borrowed_buf.rs @@ -222,6 +222,14 @@ pub struct BorrowedCursor<'a, T> { borrowed_buf: NonNull>, } +// SAFETY: A `BorrowedCursor<'a, T>` is a unique borrow of a `BorrowedBuf<'a, T>`, which is a +// `&'a mut [MaybeUninit]` and two `Copy` fields. The `buf` raw pointer is used like +// `&mut [MaybeUninit]` so `T: Send` -> `Send` and is: `T: Sync` -> `Sync`, and the +// `borrowed_buf` only touches two `Copy` fields, without depending of `T`. +unsafe impl Send for BorrowedCursor<'_, T> {} +// SAFETY: See the `Send` impl above. +unsafe impl Sync for BorrowedCursor<'_, T> {} + impl Debug for BorrowedCursor<'_, T> { fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { let buf = BorrowedBufDebug { From b3db5fca664af71ed3358b7a94e5a6fd674578a8 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 19 Sep 2026 15:20:02 +0200 Subject: [PATCH 0446/1309] add `minicore::ffi::VaList` --- tests/assembly-llvm/c-variadic/aarch64.rs | 36 ++----- tests/assembly-llvm/c-variadic/avr.rs | 39 ++----- tests/assembly-llvm/c-variadic/gpu.rs | 36 ++----- tests/assembly-llvm/c-variadic/mips.rs | 33 +----- tests/assembly-llvm/c-variadic/powerpc.rs | 37 ++----- tests/assembly-llvm/c-variadic/riscv.rs | 37 ++----- tests/assembly-llvm/c-variadic/s390x.rs | 36 ++----- tests/assembly-llvm/c-variadic/sparc.rs | 37 ++----- tests/assembly-llvm/c-variadic/wasm.rs | 37 ++----- tests/assembly-llvm/c-variadic/x86-linux.rs | 37 ++----- tests/assembly-llvm/c-variadic/x86-windows.rs | 37 ++----- tests/assembly-llvm/c-variadic/xtensa.rs | 34 +----- tests/auxiliary/minicore.rs | 101 ++++++++++++++++++ tests/ui/c-variadic/naked-invalid.rs | 5 +- tests/ui/c-variadic/naked-invalid.stderr | 6 +- tests/ui/c-variadic/unsupported-abi.rs | 4 +- tests/ui/c-variadic/unsupported-abi.stderr | 74 ++++++------- .../cmse-nonsecure-entry/c-variadic.rs | 5 +- .../cmse-nonsecure-entry/c-variadic.stderr | 25 +++-- ...te-c_variadic_experimental_arch.avr.stderr | 4 +- ...e-c_variadic_experimental_arch.m68k.stderr | 4 +- ...c_variadic_experimental_arch.msp430.stderr | 4 +- ...variadic_experimental_arch.riscv32e.stderr | 4 +- ...ature-gate-c_variadic_experimental_arch.rs | 13 +-- ...-c_variadic_experimental_arch.sparc.stderr | 4 +- 25 files changed, 247 insertions(+), 442 deletions(-) diff --git a/tests/assembly-llvm/c-variadic/aarch64.rs b/tests/assembly-llvm/c-variadic/aarch64.rs index 436318bee91e4..b0b06a2536862 100644 --- a/tests/assembly-llvm/c-variadic/aarch64.rs +++ b/tests/assembly-llvm/c-variadic/aarch64.rs @@ -25,33 +25,9 @@ // desugar va_arg early, hence we don't actually match Clang there. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // AARCH64_LINUX-LABEL: read_f64: @@ -109,7 +85,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // AARCH64_MSVC-NEXT: ldr d0, [x8], #8 // AARCH64_MSVC-NEXT: str x8, [x0] // AARCH64_MSVC-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -172,7 +148,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // AARCH64_MSVC-NEXT: ldr w0, [x9], #8 // AARCH64_MSVC-NEXT: str x9, [x8] // AARCH64_MSVC-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -236,7 +212,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // AARCH64_MSVC-NEXT: ldr x0, [x9], #8 // AARCH64_MSVC-NEXT: str x9, [x8] // AARCH64_MSVC-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -319,7 +295,7 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // AARCH64_MSVC-NEXT: ldr x0, [x10], #16 // AARCH64_MSVC-NEXT: str x10, [x8] // AARCH64_MSVC-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -329,5 +305,5 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // AARCH64_MSVC: read_ptr = read_i64 // ARM64EC_MSVC: "#read_ptr" = "#read_i64" // AARCH64_DARWIN-CHECK: _read_ptr = _read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/avr.rs b/tests/assembly-llvm/c-variadic/avr.rs index a795e57cb8287..b2f1668917fc7 100644 --- a/tests/assembly-llvm/c-variadic/avr.rs +++ b/tests/assembly-llvm/c-variadic/avr.rs @@ -11,34 +11,9 @@ // Check that rustc and clang output match, see https://godbolt.org/z/1MvxoceeT. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i16 {} -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for f32 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f32(ap: &mut VaList<'_>) -> f32 { // CHECK-LABEL: read_f32 @@ -63,7 +38,7 @@ unsafe extern "C" fn read_f32(ap: &mut VaList<'_>) -> f32 { // AVR-NEXT: ldd r24, Z+2 // AVR-NEXT: ldd r25, Z+3 // AVR-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -114,7 +89,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // AVR-NEXT: pop r15 // AVR-NEXT: pop r14 // AVR-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -132,7 +107,7 @@ unsafe extern "C" fn read_i16(ap: &mut VaList<'_>) -> i16 { // AVR-NEXT: ld r24, Z // AVR-NEXT: ldd r25, Z+1 // AVR-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -159,7 +134,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // AVR-NEXT: ldd r24, Z+2 // AVR-NEXT: ldd r25, Z+3 // AVR-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -210,11 +185,11 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // AVR-NEXT: pop r15 // AVR-NEXT: pop r14 // AVR-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // AVR: read_ptr = pm(read_i16) - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/gpu.rs b/tests/assembly-llvm/c-variadic/gpu.rs index 0bc9c0f428705..137228d5877bc 100644 --- a/tests/assembly-llvm/c-variadic/gpu.rs +++ b/tests/assembly-llvm/c-variadic/gpu.rs @@ -12,33 +12,9 @@ #![crate_type = "lib"] extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -64,7 +40,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // NVPTX-NEXT: ld.b64 %rd6, [%rd4]; // NVPTX-NEXT: st.param.b64 [func_retval0], %rd6; // NVPTX-NEXT: ret; - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -91,7 +67,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // NVPTX-NEXT: ld.b32 %r1, [%rd4]; // NVPTX-NEXT: st.param.b32 [func_retval0], %r1; // NVPTX-NEXT: ret; - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -119,7 +95,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // NVPTX-NEXT: ld.b64 %rd6, [%rd4]; // NVPTX-NEXT: st.param.b64 [func_retval0], %rd6; // NVPTX-NEXT: ret; - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -147,7 +123,7 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // NVPTX-NEXT: ld.v2.b64 {%rd6, %rd7}, [%rd4]; // NVPTX-NEXT: st.param.v2.b64 [func_retval0], {%rd6, %rd7}; // NVPTX-NEXT: ret; - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -175,5 +151,5 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // NVPTX-NEXT: ld.b64 %rd6, [%rd4]; // NVPTX-NEXT: st.param.b64 [func_retval0], %rd6; // NVPTX-NEXT: ret; - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/mips.rs b/tests/assembly-llvm/c-variadic/mips.rs index da9c08481fc33..0873f968ba563 100644 --- a/tests/assembly-llvm/c-variadic/mips.rs +++ b/tests/assembly-llvm/c-variadic/mips.rs @@ -13,32 +13,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -65,7 +42,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // MIPS64EL-NEXT: ldc1 $f0, 0($1) // MIPS64EL-NEXT: jr $ra // MIPS64EL-NEXT: nop - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -91,7 +68,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // MIPS64EL-NEXT: lw $2, 0($1) // MIPS64EL-NEXT: jr $ra // MIPS64EL-NEXT: nop - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -123,7 +100,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // MIPS64EL-NEXT: ld $2, 0($1) // MIPS64EL-NEXT: jr $ra // MIPS64EL-NEXT: nop - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -131,5 +108,5 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // MIPS: read_ptr = read_i32 // MIPS64: read_ptr = read_i64 // MIPS64EL: read_ptr = read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/powerpc.rs b/tests/assembly-llvm/c-variadic/powerpc.rs index 896817f628662..b5875ebf81b89 100644 --- a/tests/assembly-llvm/c-variadic/powerpc.rs +++ b/tests/assembly-llvm/c-variadic/powerpc.rs @@ -17,34 +17,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -#[cfg(target_pointer_width = "64")] -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -78,7 +53,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // AIX-NEXT: addi 5, 4, 8 // AIX-NEXT: std 5, 0(3) // AIX-NEXT: blr - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -115,7 +90,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // AIX-NEXT: std 5, 0(3) // AIX-NEXT: lwa 3, 4(4) // AIX-NEXT: blr - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -156,7 +131,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // AIX-NEXT: std 5, 0(3) // AIX-NEXT: ld 3, 0(4) // AIX-NEXT: blr - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -186,7 +161,7 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // AIX-NEXT: ld 3, 0(4) // AIX-NEXT: ld 4, 8(4) // AIX-NEXT: blr - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -194,5 +169,5 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // POWERPC: read_ptr = read_i32 // POWERPC64: read_ptr = read_i64 // POWERPC64LE: read_ptr = read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/riscv.rs b/tests/assembly-llvm/c-variadic/riscv.rs index 989c47a04a58d..3a785269e40ce 100644 --- a/tests/assembly-llvm/c-variadic/riscv.rs +++ b/tests/assembly-llvm/c-variadic/riscv.rs @@ -11,34 +11,9 @@ #![crate_type = "lib"] extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -#[cfg(target_pointer_width = "64")] -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -56,7 +31,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // RISCV64-NEXT: addi a1, a1, 8 // RISCV64-NEXT: sd a1, 0(a0) // RISCV64-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -74,7 +49,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // RISCV64-NEXT: addi a2, a2, 8 // RISCV64-NEXT: sd a2, 0([[PTR:a[0-1]]]) // RISCV64: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -95,7 +70,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // RISCV64-NEXT: addi a2, a2, 8 // RISCV64-NEXT: sd a2, 0([[PTR:a[0-1]]]) // RISCV64: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -111,12 +86,12 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // RISCV64-NEXT: addi a3, a3, 16 // RISCV64-NEXT: sd a3, 0([[LIST:a[02]]]) // RISCV64: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // RISCV32: read_ptr = read_i32 // RISCV64: read_ptr = read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/s390x.rs b/tests/assembly-llvm/c-variadic/s390x.rs index cfa193726f862..7dfcda83fda3b 100644 --- a/tests/assembly-llvm/c-variadic/s390x.rs +++ b/tests/assembly-llvm/c-variadic/s390x.rs @@ -10,33 +10,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64: @@ -55,7 +31,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-NEXT: stg %r0, 16(%r2) // CHECK-NEXT: ld %f0, 0(%r1) // CHECK-NEXT: br %r14 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -77,7 +53,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // CHECK-NEXT: stg %r0, 16(%r2) // CHECK-NEXT: lgf %r2, 0(%r1) // CHECK-NEXT: br %r14 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -98,7 +74,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // CHECK-NEXT: stg %r0, 16(%r2) // CHECK-NEXT: lg %r2, 0(%r1) // CHECK-NEXT: br %r14 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -123,11 +99,11 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // CHECK-NEXT: mvc 8(8,%r2), 8(%r1) // CHECK-NEXT: mvc 0(8,%r2), 0(%r1) // CHECK-NEXT: br %r14 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // CHECK: read_ptr = read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/sparc.rs b/tests/assembly-llvm/c-variadic/sparc.rs index 78ce38ac3480e..44e5ce92bfa96 100644 --- a/tests/assembly-llvm/c-variadic/sparc.rs +++ b/tests/assembly-llvm/c-variadic/sparc.rs @@ -14,34 +14,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -#[cfg(target_pointer_width = "64")] -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -64,7 +39,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // SPARC64-NEXT: stx %o2, [%o0] // SPARC64-NEXT: retl // SPARC64-NEXT: ldd [%o1], %f0 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -82,7 +57,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // SPARC64-NEXT: stx %o2, [%o0] // SPARC64-NEXT: retl // SPARC64-NEXT: ldsw [%o1+4], %o0 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -107,7 +82,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // SPARC64-NEXT: stx %o2, [%o0] // SPARC64-NEXT: retl // SPARC64-NEXT: ldx [%o1], %o0 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -123,12 +98,12 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // SPARC64-NEXT: or %o1, 8, %o1 // SPARC64-NEXT: retl // SPARC64-NEXT: ldx [%o1], %o1 - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // SPARC: read_ptr = read_i32 // SPARC64: read_ptr = read_i64 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/wasm.rs b/tests/assembly-llvm/c-variadic/wasm.rs index 69fd8fa9d18b5..3168e79ea9d7f 100644 --- a/tests/assembly-llvm/c-variadic/wasm.rs +++ b/tests/assembly-llvm/c-variadic/wasm.rs @@ -13,33 +13,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // WASM32-LABEL: read_f64: @@ -73,7 +49,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // WASM64-NEXT: local.get 1 // WASM64-NEXT: f64.load 0 // WASM64-NEXT: end_function - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -101,7 +77,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // WASM64-NEXT: local.get 1 // WASM64-NEXT: i32.load 0 // WASM64-NEXT: end_function - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -133,7 +109,7 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // WASM64-NEXT: local.get 1 // WASM64-NEXT: i64.load 0 // WASM64-NEXT: end_function - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -169,7 +145,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // WASM64-NEXT: local.get 1 // WASM64-NEXT: i64.load 0 // WASM64-NEXT: end_function - va_arg(ap) + ap.next_arg() } // Clang and Rustc use a different ABI for i128 on wasm32, and LLVM optimizes differently if we use @@ -220,5 +196,6 @@ unsafe extern "C" fn read_i128(out: *mut i128, ap: *mut VaList<'_>) { // WASM64-NEXT: i64.load 8 // WASM64-NEXT: i64.store 8 // WASM64-NEXT: end_function - *out = va_arg(mem::transmute(ap)); + let ap = &mut *ap; + *out = ap.next_arg(); } diff --git a/tests/assembly-llvm/c-variadic/x86-linux.rs b/tests/assembly-llvm/c-variadic/x86-linux.rs index 59ea4d629281a..d2f5c1144a991 100644 --- a/tests/assembly-llvm/c-variadic/x86-linux.rs +++ b/tests/assembly-llvm/c-variadic/x86-linux.rs @@ -16,34 +16,9 @@ // Check that the assembly that rustc generates matches what clang emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -#[cfg(target_pointer_width = "64")] -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -86,7 +61,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // I686-NEXT: mov dword ptr [eax], edx // I686-NEXT: fld qword ptr [ecx] // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -131,7 +106,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // I686-NEXT: mov dword ptr [eax], edx // I686-NEXT: mov eax, dword ptr [ecx] // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -177,7 +152,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // I686-NEXT: mov eax, dword ptr [ecx] // I686-NEXT: mov edx, dword ptr [ecx + 4] // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -223,7 +198,7 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // X86_64-NEXT_GNUX32-NEXT: mov rdx, qword ptr [ecx + 8] // X86_64-NEXT_GNUX32-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -231,5 +206,5 @@ unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // X86_64: read_ptr = read_i64 // X86_64_GNUX32: read_ptr = read_i32 // I686: read_ptr = read_i32 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/x86-windows.rs b/tests/assembly-llvm/c-variadic/x86-windows.rs index 18a1fd9cb5127..7de244290958d 100644 --- a/tests/assembly-llvm/c-variadic/x86-windows.rs +++ b/tests/assembly-llvm/c-variadic/x86-windows.rs @@ -28,34 +28,9 @@ // ``` extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_arg_safe"] -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -#[cfg(target_pointer_width = "64")] -unsafe impl VaArgSafe for i128 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64: @@ -73,7 +48,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // I686-NEXT: fld qword ptr [ecx] // I686-NEXT: pop ebp // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -93,7 +68,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // I686-NEXT: mov eax, dword ptr [ecx] // I686-NEXT: pop ebp // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -114,7 +89,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // I686-NEXT: mov edx, dword ptr [ecx + 4] // I686-NEXT: pop ebp // I686-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -128,12 +103,12 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // X86_64-NEXT: mov rax, qword ptr [rax] // X86_64-NEXT: movups xmm0, xmmword ptr [rax] // X86_64-NEXT: ret - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // X86_64: read_ptr = read_i64 // X86: _read_ptr = _read_i32 - va_arg(ap) + ap.next_arg() } diff --git a/tests/assembly-llvm/c-variadic/xtensa.rs b/tests/assembly-llvm/c-variadic/xtensa.rs index 0038c4af4eee6..a070980cff3d6 100644 --- a/tests/assembly-llvm/c-variadic/xtensa.rs +++ b/tests/assembly-llvm/c-variadic/xtensa.rs @@ -12,33 +12,9 @@ // Check that the assembly that rustc generates matches what GCC emits. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -pub unsafe trait VaArgSafe {} - -unsafe impl VaArgSafe for i32 {} -unsafe impl VaArgSafe for i64 {} -unsafe impl VaArgSafe for f64 {} -unsafe impl VaArgSafe for *const T {} - -#[repr(C)] -struct VaListInner { - va_stk: *const c_void, - va_reg: *const c_void, - va_ndx: i32, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - -#[rustc_intrinsic] -#[rustc_nounwind] -pub const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; - #[unsafe(no_mangle)] unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // CHECK-LABEL: read_f64 @@ -68,7 +44,7 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { // XTENSA-NEXT: l32i a2, a8, 0 // XTENSA-NEXT: l32i a3, a8, 4 // XTENSA-NEXT: retw.n - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -98,7 +74,7 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // XTENSA-NEXT: add a8, a9, a8 // XTENSA-NEXT: l32i a2, a8, 0 // XTENSA-NEXT: retw.n - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] @@ -130,11 +106,11 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // XTENSA-NEXT: l32i a2, a8, 0 // XTENSA-NEXT: l32i a3, a8, 4 // XTENSA-NEXT: retw.n - va_arg(ap) + ap.next_arg() } #[unsafe(no_mangle)] unsafe extern "C" fn read_ptr(ap: &mut VaList<'_>) -> *const u8 { // XTENSA: read_ptr = read_i32 - va_arg(ap) + ap.next_arg() } diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 2b7eb0b9afbcf..bcbba883b2178 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -498,3 +498,104 @@ pub mod simd { pub type u8x16 = Simd; pub type u64x2 = Simd; } + +pub mod ffi { + use super::*; + + #[repr(transparent)] + #[lang = "va_list"] + pub struct VaList<'a> { + inner: VaListInner, + _marker: PhantomCovariantLifetime<'a>, + } + + #[rustc_intrinsic] + const unsafe fn va_arg(ap: &mut VaList<'_>) -> T; + + impl VaList<'_> { + pub unsafe fn next_arg(&mut self) -> T { + va_arg(self) + } + } + + #[repr(transparent)] + struct PhantomCovariantLifetime<'a>(PhantomCovariant<&'a ()>); + + #[repr(transparent)] + struct PhantomCovariant(PhantomData T>); + + cfg_select! { + all( + target_arch = "aarch64", + not(target_vendor = "apple"), + not(target_os = "uefi"), + not(windows) + ) => { + #[repr(C)] + struct VaListInner { + stack: *const c_void, + gr_top: *const c_void, + vr_top: *const c_void, + gr_offs: i32, + vr_offs: i32, + } + } + all(target_arch = "powerpc", not(target_os = "uefi"), not(windows)) => { + #[repr(C)] + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + gpr: u8, + fpr: u8, + reserved: u16, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, + } + } + target_arch = "s390x" => { + #[repr(C)] + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + gpr: i64, + fpr: i64, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, + } + } + all(target_arch = "x86_64", not(target_os = "uefi"), not(windows)) => { + #[repr(C)] + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + gp_offset: i32, + fp_offset: i32, + overflow_arg_area: *const c_void, + reg_save_area: *const c_void, + } + } + target_arch = "xtensa" => { + #[repr(C)] + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + stk: *const i32, + reg: *const i32, + ndx: i32, + } + } + + all(target_arch = "hexagon", target_env = "musl") => { + #[repr(C)] + #[rustc_pass_indirectly_in_non_rustic_abis] + struct VaListInner { + __current_saved_reg_area_pointer: *const c_void, + __saved_reg_area_end_pointer: *const c_void, + __overflow_area_pointer: *const c_void, + } + } + + _ => { + #[repr(transparent)] + struct VaListInner { + ptr: *const c_void, + } + } + } +} diff --git a/tests/ui/c-variadic/naked-invalid.rs b/tests/ui/c-variadic/naked-invalid.rs index e0f06dad5c93b..0cd37c94b6764 100644 --- a/tests/ui/c-variadic/naked-invalid.rs +++ b/tests/ui/c-variadic/naked-invalid.rs @@ -9,12 +9,9 @@ #![no_core] extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[repr(C)] -#[lang = "va_list"] -pub struct VaList; - #[unsafe(naked)] unsafe extern "sysv64" fn c_variadic_sysv64(_: ...) { naked_asm!("ret") diff --git a/tests/ui/c-variadic/naked-invalid.stderr b/tests/ui/c-variadic/naked-invalid.stderr index a1fc8c1664272..0842be296fe33 100644 --- a/tests/ui/c-variadic/naked-invalid.stderr +++ b/tests/ui/c-variadic/naked-invalid.stderr @@ -1,5 +1,5 @@ error: `...` is not supported for `extern "Rust"` naked functions - --> $DIR/naked-invalid.rs:29:41 + --> $DIR/naked-invalid.rs:26:41 | LL | unsafe extern "Rust" fn c_variadic_rust(_: ...) { | ------------- ^^^^^^ @@ -9,7 +9,7 @@ LL | unsafe extern "Rust" fn c_variadic_rust(_: ...) { = help: C-variadic function must have a compatible calling convention error: `...` is not supported for `extern "x86-interrupt"` naked functions - --> $DIR/naked-invalid.rs:35:59 + --> $DIR/naked-invalid.rs:32:59 | LL | unsafe extern "x86-interrupt" fn c_variadic_x86_interrupt(_: ...) { | ---------------------- ^^^^^^ @@ -19,7 +19,7 @@ LL | unsafe extern "x86-interrupt" fn c_variadic_x86_interrupt(_: ...) { = help: C-variadic function must have a compatible calling convention error[E0703]: invalid ABI: found `nonsense` - --> $DIR/naked-invalid.rs:41:15 + --> $DIR/naked-invalid.rs:38:15 | LL | unsafe extern "nonsense" fn c_variadic_x86_nonsense(_: ...) { | ^^^^^^^^^^ invalid ABI diff --git a/tests/ui/c-variadic/unsupported-abi.rs b/tests/ui/c-variadic/unsupported-abi.rs index 1b62003a9275b..606b95da98dbe 100644 --- a/tests/ui/c-variadic/unsupported-abi.rs +++ b/tests/ui/c-variadic/unsupported-abi.rs @@ -8,6 +8,7 @@ // Test that ABIs for which C-variadics are not supported report an error. extern crate minicore; +use minicore::ffi::VaList; use minicore::*; #[rustfmt::skip] @@ -28,9 +29,6 @@ mod foreign { //~^ ERROR C-variadic functions with the "thiscall-unwind" calling convention are not supported } -#[lang = "va_list"] -struct VaList(*mut u8); - unsafe fn rust_free(_: ...) {} //~^ ERROR `...` is not supported for non-extern functions unsafe extern "Rust" fn rust_free_explicit(_: ...) {} diff --git a/tests/ui/c-variadic/unsupported-abi.stderr b/tests/ui/c-variadic/unsupported-abi.stderr index ee1f5ece82ced..2418b31836fef 100644 --- a/tests/ui/c-variadic/unsupported-abi.stderr +++ b/tests/ui/c-variadic/unsupported-abi.stderr @@ -1,5 +1,5 @@ error: `...` is not supported for non-extern functions - --> $DIR/unsupported-abi.rs:34:21 + --> $DIR/unsupported-abi.rs:32:21 | LL | unsafe fn rust_free(_: ...) {} | ^^^^^^ @@ -7,7 +7,7 @@ LL | unsafe fn rust_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "Rust"` functions - --> $DIR/unsupported-abi.rs:36:44 + --> $DIR/unsupported-abi.rs:34:44 | LL | unsafe extern "Rust" fn rust_free_explicit(_: ...) {} | ------------- ^^^^^^ @@ -17,7 +17,7 @@ LL | unsafe extern "Rust" fn rust_free_explicit(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl"` functions - --> $DIR/unsupported-abi.rs:42:37 + --> $DIR/unsupported-abi.rs:40:37 | LL | unsafe extern "cdecl" fn cdecl_free(_: ...) {} | -------------- ^^^^^^ @@ -27,7 +27,7 @@ LL | unsafe extern "cdecl" fn cdecl_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl-unwind"` functions - --> $DIR/unsupported-abi.rs:44:51 + --> $DIR/unsupported-abi.rs:42:51 | LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_free(_: ...) {} | --------------------- ^^^^^^ @@ -37,7 +37,7 @@ LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall"` functions - --> $DIR/unsupported-abi.rs:46:41 + --> $DIR/unsupported-abi.rs:44:41 | LL | unsafe extern "stdcall" fn stdcall_free(_: ...) {} | ---------------- ^^^^^^ @@ -47,7 +47,7 @@ LL | unsafe extern "stdcall" fn stdcall_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall-unwind"` functions - --> $DIR/unsupported-abi.rs:48:55 + --> $DIR/unsupported-abi.rs:46:55 | LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_free(_: ...) {} | ----------------------- ^^^^^^ @@ -57,7 +57,7 @@ LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall"` functions - --> $DIR/unsupported-abi.rs:50:43 + --> $DIR/unsupported-abi.rs:48:43 | LL | unsafe extern "thiscall" fn thiscall_free(_: ...) {} | ----------------- ^^^^^^ @@ -67,7 +67,7 @@ LL | unsafe extern "thiscall" fn thiscall_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall-unwind"` functions - --> $DIR/unsupported-abi.rs:52:57 + --> $DIR/unsupported-abi.rs:50:57 | LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_free(_: ...) {} | ------------------------ ^^^^^^ @@ -77,7 +77,7 @@ LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_free(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for non-extern functions - --> $DIR/unsupported-abi.rs:58:27 + --> $DIR/unsupported-abi.rs:56:27 | LL | unsafe fn rust_method(_: ...) {} | ^^^^^^ @@ -85,7 +85,7 @@ LL | unsafe fn rust_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "Rust"` functions - --> $DIR/unsupported-abi.rs:60:50 + --> $DIR/unsupported-abi.rs:58:50 | LL | unsafe extern "Rust" fn rust_method_explicit(_: ...) {} | ------------- ^^^^^^ @@ -95,7 +95,7 @@ LL | unsafe extern "Rust" fn rust_method_explicit(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl"` functions - --> $DIR/unsupported-abi.rs:66:43 + --> $DIR/unsupported-abi.rs:64:43 | LL | unsafe extern "cdecl" fn cdecl_method(_: ...) {} | -------------- ^^^^^^ @@ -105,7 +105,7 @@ LL | unsafe extern "cdecl" fn cdecl_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl-unwind"` functions - --> $DIR/unsupported-abi.rs:68:57 + --> $DIR/unsupported-abi.rs:66:57 | LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_method(_: ...) {} | --------------------- ^^^^^^ @@ -115,7 +115,7 @@ LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall"` functions - --> $DIR/unsupported-abi.rs:70:47 + --> $DIR/unsupported-abi.rs:68:47 | LL | unsafe extern "stdcall" fn stdcall_method(_: ...) {} | ---------------- ^^^^^^ @@ -125,7 +125,7 @@ LL | unsafe extern "stdcall" fn stdcall_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall-unwind"` functions - --> $DIR/unsupported-abi.rs:72:61 + --> $DIR/unsupported-abi.rs:70:61 | LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_method(_: ...) {} | ----------------------- ^^^^^^ @@ -135,7 +135,7 @@ LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall"` functions - --> $DIR/unsupported-abi.rs:74:49 + --> $DIR/unsupported-abi.rs:72:49 | LL | unsafe extern "thiscall" fn thiscall_method(_: ...) {} | ----------------- ^^^^^^ @@ -145,7 +145,7 @@ LL | unsafe extern "thiscall" fn thiscall_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall-unwind"` functions - --> $DIR/unsupported-abi.rs:76:63 + --> $DIR/unsupported-abi.rs:74:63 | LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_method(_: ...) {} | ------------------------ ^^^^^^ @@ -155,7 +155,7 @@ LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for non-extern functions - --> $DIR/unsupported-abi.rs:81:33 + --> $DIR/unsupported-abi.rs:79:33 | LL | unsafe fn rust_trait_method(_: ...) {} | ^^^^^^ @@ -163,7 +163,7 @@ LL | unsafe fn rust_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "Rust"` functions - --> $DIR/unsupported-abi.rs:83:56 + --> $DIR/unsupported-abi.rs:81:56 | LL | unsafe extern "Rust" fn rust_trait_method_explicit(_: ...) {} | ------------- ^^^^^^ @@ -173,7 +173,7 @@ LL | unsafe extern "Rust" fn rust_trait_method_explicit(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl"` functions - --> $DIR/unsupported-abi.rs:89:49 + --> $DIR/unsupported-abi.rs:87:49 | LL | unsafe extern "cdecl" fn cdecl_trait_method(_: ...) {} | -------------- ^^^^^^ @@ -183,7 +183,7 @@ LL | unsafe extern "cdecl" fn cdecl_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl-unwind"` functions - --> $DIR/unsupported-abi.rs:91:63 + --> $DIR/unsupported-abi.rs:89:63 | LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_trait_method(_: ...) {} | --------------------- ^^^^^^ @@ -193,7 +193,7 @@ LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall"` functions - --> $DIR/unsupported-abi.rs:93:53 + --> $DIR/unsupported-abi.rs:91:53 | LL | unsafe extern "stdcall" fn stdcall_trait_method(_: ...) {} | ---------------- ^^^^^^ @@ -203,7 +203,7 @@ LL | unsafe extern "stdcall" fn stdcall_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall-unwind"` functions - --> $DIR/unsupported-abi.rs:95:67 + --> $DIR/unsupported-abi.rs:93:67 | LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_trait_method(_: ...) {} | ----------------------- ^^^^^^ @@ -213,7 +213,7 @@ LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_trait_method(_: ...) { = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall"` functions - --> $DIR/unsupported-abi.rs:97:55 + --> $DIR/unsupported-abi.rs:95:55 | LL | unsafe extern "thiscall" fn thiscall_trait_method(_: ...) {} | ----------------- ^^^^^^ @@ -223,7 +223,7 @@ LL | unsafe extern "thiscall" fn thiscall_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall-unwind"` functions - --> $DIR/unsupported-abi.rs:99:69 + --> $DIR/unsupported-abi.rs:97:69 | LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_trait_method(_: ...) {} | ------------------------ ^^^^^^ @@ -233,7 +233,7 @@ LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_trait_method(_: ...) = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for non-extern functions - --> $DIR/unsupported-abi.rs:104:33 + --> $DIR/unsupported-abi.rs:102:33 | LL | unsafe fn rust_trait_method(_: ...) {} | ^^^^^^ @@ -241,7 +241,7 @@ LL | unsafe fn rust_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "Rust"` functions - --> $DIR/unsupported-abi.rs:106:56 + --> $DIR/unsupported-abi.rs:104:56 | LL | unsafe extern "Rust" fn rust_trait_method_explicit(_: ...) {} | ------------- ^^^^^^ @@ -251,7 +251,7 @@ LL | unsafe extern "Rust" fn rust_trait_method_explicit(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl"` functions - --> $DIR/unsupported-abi.rs:112:49 + --> $DIR/unsupported-abi.rs:110:49 | LL | unsafe extern "cdecl" fn cdecl_trait_method(_: ...) {} | -------------- ^^^^^^ @@ -261,7 +261,7 @@ LL | unsafe extern "cdecl" fn cdecl_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "cdecl-unwind"` functions - --> $DIR/unsupported-abi.rs:114:63 + --> $DIR/unsupported-abi.rs:112:63 | LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_trait_method(_: ...) {} | --------------------- ^^^^^^ @@ -271,7 +271,7 @@ LL | unsafe extern "cdecl-unwind" fn cdecl_unwind_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall"` functions - --> $DIR/unsupported-abi.rs:116:53 + --> $DIR/unsupported-abi.rs:114:53 | LL | unsafe extern "stdcall" fn stdcall_trait_method(_: ...) {} | ---------------- ^^^^^^ @@ -281,7 +281,7 @@ LL | unsafe extern "stdcall" fn stdcall_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "stdcall-unwind"` functions - --> $DIR/unsupported-abi.rs:118:67 + --> $DIR/unsupported-abi.rs:116:67 | LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_trait_method(_: ...) {} | ----------------------- ^^^^^^ @@ -291,7 +291,7 @@ LL | unsafe extern "stdcall-unwind" fn stdcall_unwind_trait_method(_: ...) { = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall"` functions - --> $DIR/unsupported-abi.rs:120:55 + --> $DIR/unsupported-abi.rs:118:55 | LL | unsafe extern "thiscall" fn thiscall_trait_method(_: ...) {} | ----------------- ^^^^^^ @@ -301,7 +301,7 @@ LL | unsafe extern "thiscall" fn thiscall_trait_method(_: ...) {} = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: `...` is not supported for `extern "thiscall-unwind"` functions - --> $DIR/unsupported-abi.rs:122:69 + --> $DIR/unsupported-abi.rs:120:69 | LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_trait_method(_: ...) {} | ------------------------ ^^^^^^ @@ -311,31 +311,31 @@ LL | unsafe extern "thiscall-unwind" fn thiscall_unwind_trait_method(_: ...) = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error[E0045]: C-variadic functions with the "Rust" calling convention are not supported - --> $DIR/unsupported-abi.rs:15:22 + --> $DIR/unsupported-abi.rs:16:22 | LL | extern "Rust" { fn rust_foreign_explicit(_: ...); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0045]: C-variadic functions with the "stdcall" calling convention are not supported - --> $DIR/unsupported-abi.rs:21:25 + --> $DIR/unsupported-abi.rs:22:25 | LL | extern "stdcall" { fn stdcall_foreign(_: ...); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0045]: C-variadic functions with the "stdcall-unwind" calling convention are not supported - --> $DIR/unsupported-abi.rs:23:32 + --> $DIR/unsupported-abi.rs:24:32 | LL | extern "stdcall-unwind" { fn stdcall_unwind_foreign(_: ...); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0045]: C-variadic functions with the "thiscall" calling convention are not supported - --> $DIR/unsupported-abi.rs:25:26 + --> $DIR/unsupported-abi.rs:26:26 | LL | extern "thiscall" { fn thiscall_foreign(_: ...); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention error[E0045]: C-variadic functions with the "thiscall-unwind" calling convention are not supported - --> $DIR/unsupported-abi.rs:27:33 + --> $DIR/unsupported-abi.rs:28:33 | LL | extern "thiscall-unwind" { fn thiscall_unwind_foreign(_: ...); } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ C-variadic function must have a compatible calling convention diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs index 40a0f152e3005..1dd49f22f8077 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.rs @@ -7,11 +7,9 @@ #![no_core] extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[lang = "va_list"] -struct VaList(*mut u8); - unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { //~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions } @@ -20,6 +18,7 @@ unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { async unsafe extern "cmse-nonsecure-entry" fn async_and_c_variadic(_: ...) { //~^ ERROR `...` is not supported for `extern "cmse-nonsecure-entry"` functions //~| ERROR functions cannot be both `async` and C-variadic + //~| ERROR hidden type for `impl Future` captures lifetime that does not appear in bounds } // Async on its own is also not allowed. diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.stderr index 2a2d769c7cf89..f4d9f8a2ed29d 100644 --- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.stderr +++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/c-variadic.stderr @@ -1,5 +1,5 @@ error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions - --> $DIR/c-variadic.rs:15:60 + --> $DIR/c-variadic.rs:13:60 | LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { | ----------------------------- ^^^^^^ @@ -9,13 +9,13 @@ LL | unsafe extern "cmse-nonsecure-entry" fn c_variadic(_: u32, _: ...) { = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: functions cannot be both `async` and C-variadic - --> $DIR/c-variadic.rs:20:1 + --> $DIR/c-variadic.rs:18:1 | LL | async unsafe extern "cmse-nonsecure-entry" fn async_and_c_variadic(_: ...) { | ^^^^^ `async` because of this ^^^^^^ C-variadic because of this error: `...` is not supported for `extern "cmse-nonsecure-entry"` functions - --> $DIR/c-variadic.rs:20:68 + --> $DIR/c-variadic.rs:18:68 | LL | async unsafe extern "cmse-nonsecure-entry" fn async_and_c_variadic(_: ...) { | ----------------------------- ^^^^^^ @@ -25,11 +25,24 @@ LL | async unsafe extern "cmse-nonsecure-entry" fn async_and_c_variadic(_: ...) = help: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error[E0798]: `impl Trait` is not allowed in `extern "cmse-nonsecure-entry"` signatures - --> $DIR/c-variadic.rs:26:69 + --> $DIR/c-variadic.rs:25:69 | LL | async unsafe extern "cmse-nonsecure-entry" fn async_is_not_allowed() { | ^ -error: aborting due to 4 previous errors +error[E0700]: hidden type for `impl Future` captures lifetime that does not appear in bounds + --> $DIR/c-variadic.rs:18:76 + | +LL | async unsafe extern "cmse-nonsecure-entry" fn async_and_c_variadic(_: ...) { + | _---------------------------------------------------------------------------^ + | | | | + | | | opaque type defined here + | | hidden type `{async fn body of async_and_c_variadic()}` captures the anonymous lifetime as defined here +... | +LL | | } + | |_^ + +error: aborting due to 5 previous errors -For more information about this error, try `rustc --explain E0798`. +Some errors have detailed explanations: E0700, E0798. +For more information about an error, try `rustc --explain E0700`. diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr index df7697845814e..e37d96a01e3b4 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.avr.stderr @@ -1,5 +1,5 @@ error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:28:39 | LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} | ^^^^^^^ @@ -9,7 +9,7 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:32:45 | LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} | ^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr index df7697845814e..e37d96a01e3b4 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.m68k.stderr @@ -1,5 +1,5 @@ error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:28:39 | LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} | ^^^^^^^ @@ -9,7 +9,7 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:32:45 | LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} | ^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr index df7697845814e..e37d96a01e3b4 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.msp430.stderr @@ -1,5 +1,5 @@ error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:28:39 | LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} | ^^^^^^^ @@ -9,7 +9,7 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:32:45 | LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} | ^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr index df7697845814e..e37d96a01e3b4 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.riscv32e.stderr @@ -1,5 +1,5 @@ error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:28:39 | LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} | ^^^^^^^ @@ -9,7 +9,7 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:32:45 | LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} | ^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs index 49c0bdf3a724b..7d189927bd73d 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.rs @@ -22,20 +22,9 @@ #![no_core] extern crate minicore; +use minicore::ffi::VaList; use minicore::*; -#[repr(transparent)] -struct VaListInner { - ptr: *const c_void, -} - -#[repr(transparent)] -#[lang = "va_list"] -pub struct VaList<'a> { - inner: VaListInner, - _marker: PhantomData<&'a mut ()>, -} - pub unsafe extern "C" fn test(_: i32, ap: ...) {} //~^ ERROR C-variadic function definitions on this target are unstable diff --git a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr index df7697845814e..e37d96a01e3b4 100644 --- a/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr +++ b/tests/ui/feature-gates/feature-gate-c_variadic_experimental_arch.sparc.stderr @@ -1,5 +1,5 @@ error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:39:39 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:28:39 | LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} | ^^^^^^^ @@ -9,7 +9,7 @@ LL | pub unsafe extern "C" fn test(_: i32, ap: ...) {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: C-variadic function definitions on this target are unstable - --> $DIR/feature-gate-c_variadic_experimental_arch.rs:43:45 + --> $DIR/feature-gate-c_variadic_experimental_arch.rs:32:45 | LL | unsafe extern "C" fn trait_test(_: i32, ap: ...) {} | ^^^^^^^ From d61037d90f15e64c2b0e5dc7ca0692702add89bd Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 19 Sep 2026 16:52:59 +0200 Subject: [PATCH 0447/1309] `va_arg`: pass in `TyAndLayout` weird I did not spot this before, it cleans up the code a bunch --- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_llvm/src/va_arg.rs | 119 +++++++------------ 2 files changed, 47 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index c71e83d8f99bd..c2fca69c78821 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -351,7 +351,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { } } - emit_va_arg(self, args[0], result_layout.ty) + emit_va_arg(self, args[0], result_layout) } sym::volatile_load | sym::unaligned_volatile_load => { diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index ca57bee3e6271..b21ce3f2be8e4 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -150,7 +150,7 @@ enum ForceRightAdjust { fn emit_ptr_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, pass_mode: PassMode, slot_size: SlotSize, allow_higher_align: AllowHigherAlign, @@ -161,10 +161,9 @@ fn emit_ptr_va_arg<'ll, 'tcx>( let force_right_adjust = matches!(force_right_adjust, ForceRightAdjust::Yes); let slot_size = Align::from_bytes(slot_size as u64).unwrap(); - let layout = bx.cx.layout_of(target_ty); let (llty, size, align) = if indirect { ( - bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, target_ty)).llvm_type(bx.cx), + bx.cx.layout_of(Ty::new_imm_ptr(bx.cx.tcx, layout.ty)).llvm_type(bx.cx), bx.cx.data_layout().pointer_size(), bx.cx.data_layout().pointer_align().abi, ) @@ -191,7 +190,7 @@ fn emit_ptr_va_arg<'ll, 'tcx>( fn emit_aapcs_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { let dl = bx.cx.data_layout(); @@ -218,8 +217,6 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( let gr_offs = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(3 * ptr_offset)); let vr_offs = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(3 * ptr_offset + i32_offset)); - let layout = bx.cx.layout_of(target_ty); - let maybe_reg = bx.append_sibling_block("va_arg.maybe_reg"); let in_reg = bx.append_sibling_block("va_arg.in_reg"); let on_stack = bx.append_sibling_block("va_arg.on_stack"); @@ -227,7 +224,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( let zero = bx.const_i32(0); let offset_align = Align::from_bytes(4).unwrap(); - let gr_type = target_ty.is_any_ptr() || target_ty.is_integral(); + let gr_type = layout.ty.is_any_ptr() || layout.ty.is_integral(); let (reg_off, reg_top, slot_size) = if gr_type { let nreg = layout.size.bytes().div_ceil(8); (gr_offs, gr_top, nreg * 8) @@ -279,7 +276,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( let stack_value = emit_ptr_va_arg( bx, list, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes8, AllowHigherAlign::Yes, @@ -297,7 +294,7 @@ fn emit_aapcs_va_arg<'ll, 'tcx>( fn emit_powerpc_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { let dl = bx.cx.data_layout(); @@ -311,15 +308,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( let va_list_addr = list.immediate(); // Peel off any newtype wrappers. - let layout = { - let mut layout = bx.cx.layout_of(target_ty); - - while let Some((_, inner)) = layout.non_1zst_field(bx.cx) { - layout = inner; - } - - layout - }; + let layout = layout.peel_transparent_wrappers(bx.cx); // Rust does not currently support any powerpc softfloat targets. let target = &bx.cx.tcx.sess.target; @@ -435,7 +424,7 @@ fn emit_powerpc_va_arg<'ll, 'tcx>( fn emit_s390x_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { let dl = bx.cx.data_layout(); @@ -460,15 +449,13 @@ fn emit_s390x_va_arg<'ll, 'tcx>( let reg_save_area = bx.inbounds_ptradd(va_list_addr, bx.cx.const_usize(2 * i64_offset + ptr_offset)); - let layout = bx.cx.layout_of(target_ty); - let in_reg = bx.append_sibling_block("va_arg.in_reg"); let in_mem = bx.append_sibling_block("va_arg.in_mem"); let end = bx.append_sibling_block("va_arg.end"); let ptr_align_abi = dl.pointer_align().abi; // FIXME: vector ABI not yet supported. - let target_ty_size = bx.cx.size_of(target_ty).bytes(); + let target_ty_size = layout.size.bytes(); let indirect: bool = target_ty_size > 8 || !target_ty_size.is_power_of_two(); let unpadded_size = if indirect { 8 } else { target_ty_size }; let padded_size = 8; @@ -535,7 +522,7 @@ fn emit_s390x_va_arg<'ll, 'tcx>( fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { let dl = bx.cx.data_layout(); @@ -570,15 +557,7 @@ fn emit_x86_64_sysv64_va_arg<'ll, 'tcx>( // #[repr(C)] // struct Foo([Empty; 8], i32); // ``` - let layout = { - let mut layout = bx.cx.layout_of(target_ty); - - while let Some((_, inner)) = layout.non_1zst_field(bx.cx) { - layout = inner; - } - - layout - }; + let layout = layout.peel_transparent_wrappers(bx.cx); // AMD64-ABI 3.5.7p5: Step 1. Determine whether type may be passed // in the registers. If not go to step 7. @@ -847,7 +826,7 @@ fn x86_64_sysv64_va_arg_from_memory<'ll, 'tcx>( fn emit_hexagon_va_arg_musl<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { // Implementation of va_arg for Hexagon musl target. // Based on LLVM's HexagonBuiltinVaList implementation. @@ -861,7 +840,6 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>( // All variadic arguments are passed on the stack, but the musl implementation // uses a register save area for compatibility. let va_list_addr = list.immediate(); - let layout = bx.cx.layout_of(target_ty); let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi; let ptr_size = bx.tcx().data_layout.pointer_size().bytes(); @@ -881,7 +859,7 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>( // Align current pointer based on argument type size (following LLVM's implementation) // Arguments <= 32 bits (4 bytes) use 4-byte alignment, > 32 bits use 8-byte alignment - let type_size_bits = bx.cx.size_of(target_ty).bits(); + let type_size_bits = layout.size.bits(); let arg_align = if type_size_bits > 32 { Align::from_bytes(8).unwrap() } else { @@ -931,14 +909,13 @@ fn emit_hexagon_va_arg_musl<'ll, 'tcx>( fn emit_hexagon_va_arg_bare_metal<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { // Implementation of va_arg for Hexagon bare-metal (non-musl) targets. // Based on LLVM's EmitVAArgForHexagon implementation. // // va_list is a simple pointer (char *) let va_list_addr = list.immediate(); - let layout = bx.cx.layout_of(target_ty); let ptr_align_abi = bx.tcx().data_layout.pointer_align().abi; // Load current pointer from va_list @@ -969,7 +946,7 @@ fn emit_hexagon_va_arg_bare_metal<'ll, 'tcx>( fn emit_xtensa_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, list: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { // Implementation of va_arg for Xtensa. There doesn't seem to be an authoritative source for // this, other than "what GCC does". @@ -989,7 +966,6 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( // primitive value and va_ndx = 20, we instead bump the offset and read everything from va_stk. let va_list_addr = list.immediate(); // FIXME: handle multi-field structs that split across regsave/stack? - let layout = bx.cx.layout_of(target_ty); let from_stack = bx.append_sibling_block("va_arg.from_stack"); let from_regsave = bx.append_sibling_block("va_arg.from_regsave"); let end = bx.append_sibling_block("va_arg.end"); @@ -1071,14 +1047,11 @@ fn emit_xtensa_va_arg<'ll, 'tcx>( pub(super) fn emit_va_arg<'ll, 'tcx>( bx: &mut Builder<'_, 'll, 'tcx>, addr: OperandRef<'tcx, &'ll Value>, - target_ty: Ty<'tcx>, + layout: TyAndLayout<'tcx>, ) -> &'ll Value { - let layout = bx.cx.layout_of(target_ty); - let target_ty_size = layout.layout.size().bytes(); - // Some ABIs have special behavior for zero-sized types. currently `VaArgSafe` is not // implemented for any zero-sized types, so this assert should always hold. - assert!(!bx.layout_of(target_ty).is_zst()); + assert!(!layout.is_zst()); let target = &bx.cx.tcx.sess.target; let stability = target.supports_c_variadic_definitions(); @@ -1087,7 +1060,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::X86 => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes4, if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, @@ -1096,10 +1069,10 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::Arm64EC => emit_ptr_va_arg( bx, addr, - target_ty, + layout, // MS x64 ABI requirement: "Any argument that doesn't fit in 8 bytes, or is // not 1, 2, 4, or 8 bytes, must be passed by reference." - if target_ty_size > 8 || !target_ty_size.is_power_of_two() { + if layout.size.bytes() > 8 || !layout.size.bytes().is_power_of_two() { PassMode::Indirect } else { PassMode::Direct @@ -1111,35 +1084,35 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::AArch64 if target.is_like_windows || target.is_like_darwin => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes8, AllowHigherAlign::Yes, ForceRightAdjust::No, ), - Arch::AArch64 => emit_aapcs_va_arg(bx, addr, target_ty), + Arch::AArch64 => emit_aapcs_va_arg(bx, addr, layout), Arch::Arm => { // Types wider than 16 bytes are not currently supported. Clang has special logic for // such types, but `VaArgSafe` is not implemented for any type that is this large on // arm (i.e. 32-bit) targets. - assert!(bx.cx.size_of(target_ty).bytes() <= 16); + assert!(layout.size.bytes() <= 16); emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes4, AllowHigherAlign::Yes, ForceRightAdjust::No, ) } - Arch::S390x => emit_s390x_va_arg(bx, addr, target_ty), - Arch::PowerPC => emit_powerpc_va_arg(bx, addr, target_ty), + Arch::S390x => emit_s390x_va_arg(bx, addr, layout), + Arch::PowerPC => emit_powerpc_va_arg(bx, addr, layout), Arch::PowerPC64 => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes8, AllowHigherAlign::Yes, @@ -1159,8 +1132,8 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::RiscV32 | Arch::LoongArch32 => emit_ptr_va_arg( bx, addr, - target_ty, - if target_ty_size > 2 * 4 { PassMode::Indirect } else { PassMode::Direct }, + layout, + if layout.size.bytes() > 2 * 4 { PassMode::Indirect } else { PassMode::Direct }, SlotSize::Bytes4, AllowHigherAlign::Yes, ForceRightAdjust::No, @@ -1168,8 +1141,8 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::RiscV64 | Arch::LoongArch64 => emit_ptr_va_arg( bx, addr, - target_ty, - if target_ty_size > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, + layout, + if layout.size.bytes() > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, SlotSize::Bytes8, AllowHigherAlign::Yes, ForceRightAdjust::No, @@ -1177,7 +1150,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::AmdGpu => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes4, AllowHigherAlign::No, @@ -1186,7 +1159,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::Nvptx64 => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes1, AllowHigherAlign::Yes, @@ -1195,7 +1168,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::Wasm32 | Arch::Wasm64 => emit_ptr_va_arg( bx, addr, - target_ty, + layout, if layout.is_aggregate() || layout.is_zst() || layout.is_1zst() { PassMode::Indirect } else { @@ -1208,7 +1181,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::CSky => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, SlotSize::Bytes4, AllowHigherAlign::Yes, @@ -1218,8 +1191,8 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::X86_64 if target.is_like_windows => emit_ptr_va_arg( bx, addr, - target_ty, - if target_ty_size > 8 || !target_ty_size.is_power_of_two() { + layout, + if layout.size.bytes() > 8 || !layout.size.bytes().is_power_of_two() { PassMode::Indirect } else { PassMode::Direct @@ -1229,17 +1202,17 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( ForceRightAdjust::No, ), // This includes `target.is_like_darwin`, which on x86_64 targets is like sysv64. - Arch::X86_64 => emit_x86_64_sysv64_va_arg(bx, addr, target_ty), - Arch::Xtensa => emit_xtensa_va_arg(bx, addr, target_ty), + Arch::X86_64 => emit_x86_64_sysv64_va_arg(bx, addr, layout), + Arch::Xtensa => emit_xtensa_va_arg(bx, addr, layout), Arch::Hexagon => match target.env { - Env::Musl => emit_hexagon_va_arg_musl(bx, addr, target_ty), - _ => emit_hexagon_va_arg_bare_metal(bx, addr, target_ty), + Env::Musl => emit_hexagon_va_arg_musl(bx, addr, layout), + _ => emit_hexagon_va_arg_bare_metal(bx, addr, layout), }, Arch::Sparc64 => emit_ptr_va_arg( bx, addr, - target_ty, - if target_ty_size > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, + layout, + if layout.size.bytes() > 2 * 8 { PassMode::Indirect } else { PassMode::Direct }, SlotSize::Bytes8, AllowHigherAlign::Yes, // sparc64 is a big-endian target and stores variable arguments right-adjusted. @@ -1260,7 +1233,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( emit_ptr_va_arg( bx, addr, - target_ty, + layout, pass_mode, SlotSize::Bytes4, AllowHigherAlign::No, @@ -1270,7 +1243,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( Arch::Mips | Arch::Mips32r6 | Arch::Mips64 | Arch::Mips64r6 => emit_ptr_va_arg( bx, addr, - target_ty, + layout, PassMode::Direct, match &target.llvm_abiname { LlvmAbi::N32 | LlvmAbi::N64 => SlotSize::Bytes8, @@ -1294,7 +1267,7 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( std::assert_matches!(stability, CVariadicStatus::Unstable { .. }); // Clang uses the LLVM implementation for these architectures. - bx.va_arg(addr.immediate(), bx.cx.layout_of(target_ty).llvm_type(bx.cx)) + bx.va_arg(addr.immediate(), layout.llvm_type(bx.cx)) } Arch::Other(ref arch) => { From 8a2e879b5da50b5f99e48652ee19844d29d5acd9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 12:52:15 +0200 Subject: [PATCH 0448/1309] windows Dir::rename: remove incorrect is_dir query --- library/std/src/fs/tests.rs | 10 ++++++++++ library/std/src/sys/fs/windows/dir.rs | 26 +++++++++++++++----------- 2 files changed, 25 insertions(+), 11 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 148f1c32b08b9..0cef72b624dbb 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -2783,6 +2783,16 @@ fn test_dir_remove_dir() { assert!(!matches!(exists(tmpdir.join("foo")), Ok(true))); } +#[test] +fn test_dir_rename_dir() { + let tmpdir = tmpdir(); + check!(fs::create_dir(tmpdir.join("foo"))); + let dir = check!(Dir::open(tmpdir.path())); + check!(dir.rename("foo", &dir, "baz")); + let m = check!(tmpdir.join("baz").metadata()); + assert!(m.is_dir()); +} + #[test] fn test_dir_create_dir() { let tmpdir = tmpdir(); diff --git a/library/std/src/sys/fs/windows/dir.rs b/library/std/src/sys/fs/windows/dir.rs index 70bade84f58fd..57468bd74edb0 100644 --- a/library/std/src/sys/fs/windows/dir.rs +++ b/library/std/src/sys/fs/windows/dir.rs @@ -78,19 +78,18 @@ impl Dir { return File::open(path, opts); } let path = to_u16s_without_nul(path)?; - self.open_file_native(&path, opts, false).map(|handle| File { handle }) + self.open_file_native(&path, opts, c::FILE_NON_DIRECTORY_FILE).map(|handle| File { handle }) } pub fn remove_file(&self, path: &Path) -> io::Result<()> { let path = to_u16s_without_nul(path)?; - self.remove_native(&path, false) + self.remove_native(&path, /* dir */ false) } pub fn rename(&self, from: &Path, to_dir: &Self, to: &Path) -> io::Result<()> { - let is_dir = from.is_dir(); let from = to_u16s_without_nul(from)?; let to = to_u16s_without_nul(to)?; - self.rename_native(&from, to_dir, &to, is_dir) + self.rename_native(&from, to_dir, &to) } pub fn create_dir(&self, path: &Path) -> io::Result<()> { @@ -103,12 +102,12 @@ impl Dir { pub fn open_dir(&self, path: &Path, opts: &OpenOptions) -> io::Result { let path = to_u16s_without_nul(&path)?; - self.open_file_native(&path, &opts, true).map(|handle| Self { handle }) + self.open_file_native(&path, &opts, c::FILE_DIRECTORY_FILE).map(|handle| Self { handle }) } pub fn remove_dir(&self, path: &Path) -> io::Result<()> { let path = to_u16s_without_nul(&path)?; - self.remove_native(&path, true) + self.remove_native(&path, /* dir */ true) } fn open_with_native(path: &WCStr, opts: &OpenOptions) -> io::Result { @@ -136,29 +135,34 @@ impl Dir { } } - fn open_file_native(&self, path: &[u16], opts: &OpenOptions, dir: bool) -> io::Result { + fn open_file_native( + &self, + path: &[u16], + opts: &OpenOptions, + create_opt: u32, + ) -> io::Result { let name = UnicodeStrRef::from_slice(path); let object_attributes = c::OBJECT_ATTRIBUTES { RootDirectory: self.handle.as_raw_handle(), ObjectName: name.as_ptr().cast_mut(), ..c::OBJECT_ATTRIBUTES::with_length() }; - let create_opt = if dir { c::FILE_DIRECTORY_FILE } else { c::FILE_NON_DIRECTORY_FILE }; unsafe { nt_create_file(opts, &object_attributes, create_opt) } } fn remove_native(&self, path: &[u16], dir: bool) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); - let handle = self.open_file_native(path, &opts, dir)?; + let create_opt = if dir { c::FILE_DIRECTORY_FILE } else { c::FILE_NON_DIRECTORY_FILE }; + let handle = self.open_file_native(path, &opts, create_opt)?; File::from_inner(handle).delete().io_result() } - fn rename_native(&self, from: &[u16], to_dir: &Self, to: &[u16], dir: bool) -> io::Result<()> { + fn rename_native(&self, from: &[u16], to_dir: &Self, to: &[u16]) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); - let handle = self.open_file_native(from, &opts, dir)?; + let handle = self.open_file_native(from, &opts, /* create_opt */ 0)?; // Calculate the layout of the `FILE_RENAME_INFORMATION` we pass to `NtSetInformationFile` // This is a dynamically sized struct so we need to get the position of the last field to calculate the actual size. const too_long_err: io::Error = From 506fbb7fd937e2ff058104fc1c5b62b4eba44398 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Sep 2026 12:57:19 +0200 Subject: [PATCH 0449/1309] don't mark `f128` as reliable on AIX In fact the type is really not supported at all there. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5324ec240b0ab..718a500a9abec 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -432,6 +432,8 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // - with +vsx // - without +vsx (Arch::PowerPC, _) => false, + // AIX does not support f128. + (Arch::PowerPC64, Os::Aix) => false, // ABI bugs on BE without +vsx . (Arch::PowerPC64, _) => cfg.internal_target_features.contains(&sym::vsx), // ABI unsupported (fixed in llvm22) From 16337b6cfdee6888adf182c2dbcf77bf7d055776 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Tue, 15 Sep 2026 11:20:51 +0200 Subject: [PATCH 0450/1309] Remove usages of `Unique` from `RawVec` --- library/alloc/src/raw_vec/mod.rs | 38 ++++--- library/alloc/src/raw_vec/tests.rs | 2 +- library/alloctests/lib.rs | 1 - src/etc/lldb_providers.py | 16 ++- src/etc/natvis/liballoc.natvis | 12 +-- src/etc/natvis/libstd.natvis | 6 +- .../pretty-std/lldb_input/non_windows.json | 21 +--- .../pretty-std/lldb_input/windows_gnu.json | 21 +--- .../pretty-std/lldb_input/windows_msvc.json | 16 +-- tests/debuginfo/strings-and-strs.rs | 2 +- .../inline_shims.drop.Inline.panic-abort.diff | 28 +++--- ..._conditions.JumpThreading.panic-abort.diff | 98 +++++++++---------- ...conditions.JumpThreading.panic-unwind.diff | 98 +++++++++---------- ...loops.vec_move.runtime-optimized.after.mir | 50 +++++----- ...ce.runtime-optimized.after.panic-abort.mir | 12 +-- ...e.runtime-optimized.after.panic-unwind.mir | 12 +-- 16 files changed, 176 insertions(+), 257 deletions(-) diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index ffc92056cf464..2a1c30509ebaf 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -6,7 +6,8 @@ use core::marker::{Destruct, PhantomData}; use core::mem::{Alignment, ManuallyDrop, MaybeUninit, SizedTypeProperties}; -use core::ptr::{self, NonNull, Unique}; +use core::panic::UnwindSafe; +use core::ptr::{self, NonNull}; use core::{cmp, hint}; #[cfg(not(no_global_oom_handling))] @@ -54,14 +55,16 @@ const unsafe fn new_cap(cap: usize) -> Cap { /// involved. This type is excellent for building your own data structures like Vec and VecDeque. /// In particular: /// -/// * Produces `Unique::dangling()` on zero-sized types. -/// * Produces `Unique::dangling()` on zero-length allocations. -/// * Avoids freeing `Unique::dangling()`. +/// * Produces `NonNull::dangling()` on zero-sized types. +/// * Produces `NonNull::dangling()` on zero-length allocations. +/// * Avoids freeing `NonNull::dangling()`. /// * Catches all overflows in capacity computations (promotes them to "capacity overflow" panics). /// * Guards against 32-bit systems allocating more than `isize::MAX` bytes. +/// * Provides niches for capacities greater than `isize::MAX`. /// * Guards against overflowing your length. /// * Calls `handle_alloc_error` for fallible allocations. -/// * Contains a `ptr::Unique` and thus endows the user with all related benefits. +/// * Implements `Send`, `Sync` and `UnwindSafe` iff `(T, A)` does. +/// * Carries `PhantomData` for auto trait and `may_dangle` correctness. /// * Uses the excess returned from the allocator to use the largest available capacity. /// /// This type does not in anyway inspect the memory that it manages. When dropped it *will* @@ -85,7 +88,7 @@ pub(crate) struct RawVec { /// as most operations don't need the actual type, just its layout. #[allow(missing_debug_implementations)] struct RawVecInner { - ptr: Unique, + ptr: NonNull, /// Never used for ZSTs; it's `capacity()`'s responsibility to return usize::MAX in that case. /// /// # Safety @@ -95,6 +98,11 @@ struct RawVecInner { alloc: A, } +// FIXME: Consider moving these impls to `RawVec`, once #162850 is resolved. +unsafe impl Send for RawVecInner {} +unsafe impl Sync for RawVecInner {} +impl UnwindSafe for RawVecInner {} + impl RawVec { /// Creates the biggest possible `RawVec` (on the system heap) /// without allocating. If `T` has positive size, then this makes a @@ -298,7 +306,7 @@ impl RawVec { } /// Gets a raw pointer to the start of the allocation. Note that this is - /// `Unique::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must + /// `NonNull::dangling()` if `capacity == 0` or `T` is zero-sized. In the former case, you must /// be careful. #[inline] pub(crate) const fn ptr(&self) -> *mut T { @@ -487,7 +495,7 @@ const impl RawVecInner { // matches the size requested. If that ever changes, the capacity // here should change to `ptr.len() / size_of::()`. Ok(Self { - ptr: Unique::from(ptr.cast()), + ptr: ptr.cast(), // SAFETY: We return early if `T` is a ZST, and if `capacity` would // overflow an isize layout creation would have returned early as well. cap: unsafe { Cap::new_unchecked(capacity) }, @@ -582,7 +590,7 @@ const impl RawVecInner { impl RawVecInner { #[inline] const fn new_in(alloc: A, align: Alignment) -> Self { - let ptr = Unique::from_non_null(NonNull::without_provenance(align.as_nonzero_usize())); + let ptr = NonNull::without_provenance(align.as_nonzero_usize()); // `cap: 0` means "unallocated". zero-sized types are ignored. Self { ptr, cap: ZERO_CAP, alloc } } @@ -608,13 +616,13 @@ impl RawVecInner { #[inline] const unsafe fn from_raw_parts_in(ptr: *mut u8, cap: Cap, alloc: A) -> Self { // SAFETY: Upheld by caller. - Self { ptr: unsafe { Unique::new_unchecked(ptr) }, cap, alloc } + Self { ptr: unsafe { NonNull::new_unchecked(ptr) }, cap, alloc } } #[inline] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe fn from_nonnull_in(ptr: NonNull, cap: Cap, alloc: A) -> Self { - Self { ptr: Unique::from(ptr), cap, alloc } + Self { ptr, cap, alloc } } #[inline] @@ -624,7 +632,7 @@ impl RawVecInner { #[inline] const fn non_null(&self) -> NonNull { - self.ptr.cast().as_non_null_ptr() + self.ptr.cast() } #[inline] @@ -793,7 +801,7 @@ impl RawVecInner { // Allocators currently return a `NonNull<[u8]>` whose length matches // the size requested. If that ever changes, the capacity here should // change to `ptr.len() / size_of::()`. - self.ptr = Unique::from(ptr.cast()); + self.ptr = ptr.cast(); // SAFETY: Upheld by caller. self.cap = unsafe { Cap::new_unchecked(cap) }; } @@ -865,9 +873,7 @@ impl RawVecInner { // SAFETY: T isn't a ZST if we're here and `ptr` is our pointer that `current_memory` // ensures was allocated with `layout`. unsafe { self.alloc.deallocate(ptr, layout) }; - self.ptr = - // SAFETY: Alignment is guaranteed to be nonzero. - unsafe { Unique::new_unchecked(ptr::without_provenance_mut(elem_layout.align())) }; + self.ptr = NonNull::without_provenance(elem_layout.alignment().as_nonzero_usize()); self.cap = ZERO_CAP; } else { // SAFETY: `cap` is less than the previous capacity, which must have fit in an diff --git a/library/alloc/src/raw_vec/tests.rs b/library/alloc/src/raw_vec/tests.rs index 15f48c03dc54c..f325f8b441b32 100644 --- a/library/alloc/src/raw_vec/tests.rs +++ b/library/alloc/src/raw_vec/tests.rs @@ -84,7 +84,7 @@ struct ZST; // A `RawVec` holding zero-sized elements should always look like this. fn zst_sanity(v: &RawVec) { assert_eq!(v.capacity(), usize::MAX); - assert_eq!(v.ptr(), core::ptr::Unique::::dangling().as_ptr()); + assert_eq!(v.ptr(), core::ptr::dangling_mut::()); assert_eq!(unsafe { v.inner.current_memory(T::LAYOUT) }, None); } diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index eca8444812521..3c26ecf9875e2 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -38,7 +38,6 @@ #![feature(maybe_uninit_uninit_array_transpose)] #![feature(ptr_alignment_type)] #![feature(ptr_cast_slice)] -#![feature(ptr_internals)] #![feature(rev_into_inner)] #![feature(sized_type_properties)] #![feature(slice_iter_mut_as_mut_slice)] diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 2791dae3600b0..391d24030f114 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -424,12 +424,10 @@ def StdStringSummaryProvider(valobj: SBValue, dict: LLDBOpaque): .GetNonSyntheticValue() ) - pointer = ( + pointer = unwrap_unique_or_non_null( inner_vec.GetChildMemberWithName("buf") .GetChildMemberWithName("inner") .GetChildMemberWithName("ptr") - .GetChildMemberWithName("pointer") - .GetChildMemberWithName("pointer") ) length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() @@ -462,12 +460,10 @@ def StdOsStringSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: if is_windows: inner_vec = inner_vec.GetChildAtIndex(0) - pointer = ( + pointer = unwrap_unique_or_non_null( inner_vec.GetChildMemberWithName("buf") .GetChildMemberWithName("inner") .GetChildMemberWithName("ptr") - .GetChildMemberWithName("pointer") - .GetChildMemberWithName("pointer") ) length = inner_vec.GetChildMemberWithName("len").GetValueAsUnsigned() @@ -621,12 +617,10 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque): def update(self): inner_vec = self.valobj.GetChildMemberWithName("vec").GetNonSyntheticValue() - self.data_ptr = ( + self.data_ptr = unwrap_unique_or_non_null( inner_vec.GetChildMemberWithName("buf") .GetChildMemberWithName("inner") .GetChildMemberWithName("ptr") - .GetChildMemberWithName("pointer") - .GetChildMemberWithName("pointer") ) self.capacity = ( @@ -1132,6 +1126,10 @@ class StdVecSyntheticProvider: rust 1.62.0: struct Unique { pointer: NonNull, ... } struct NonZero(T) struct NonNull { pointer: *const T } + + FIXME: This version history has been incomplete for a long time. + Maybe either update it to reflect all the version changes, + including addition of RawVecInner and allocators, or just delete it entirely. """ def __init__(self, valobj: SBValue, _dict: LLDBOpaque): diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index dade85dafe738..b56f6f5800eee 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -7,7 +7,7 @@ buf.inner.cap.__0 len - ($T1*)buf.inner.ptr.pointer.pointer + ($T1*)buf.inner.ptr.pointer @@ -23,7 +23,7 @@ - (($T1*)buf.inner.ptr.pointer.pointer)[(i + head.__0) % buf.inner.cap.__0] + (($T1*)buf.inner.ptr.pointer)[(i + head.__0) % buf.inner.cap.__0] i = i + 1 @@ -41,17 +41,17 @@ - {(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8} - (char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8 + {(char*)vec.buf.inner.ptr.pointer,[vec.len]s8} + (char*)vec.buf.inner.ptr.pointer,[vec.len]s8 vec.len vec.buf.inner.cap.__0 - {(char*)vec.buf.inner.ptr.pointer.pointer,[vec.len]s8} + {(char*)vec.buf.inner.ptr.pointer,[vec.len]s8} vec.len - (char*)vec.buf.inner.ptr.pointer.pointer + (char*)vec.buf.inner.ptr.pointer diff --git a/src/etc/natvis/libstd.natvis b/src/etc/natvis/libstd.natvis index 93e94e5f38261..bfad30db3cf7a 100644 --- a/src/etc/natvis/libstd.natvis +++ b/src/etc/natvis/libstd.natvis @@ -104,14 +104,14 @@ - {(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.inner.ptr.pointer,[inner.inner.bytes.len]} - {(char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer,[inner.inner.bytes.len]} + {(char*)inner.inner.bytes.buf.inner.ptr.pointer,[inner.inner.bytes.len]} inner.inner.bytes.len - (char*)inner.inner.bytes.buf.inner.ptr.pointer.pointer + (char*)inner.inner.bytes.buf.inner.ptr.pointer diff --git a/tests/debuginfo/pretty-std/lldb_input/non_windows.json b/tests/debuginfo/pretty-std/lldb_input/non_windows.json index 0c29b7fb779a2..04106aed96d7f 100644 --- a/tests/debuginfo/pretty-std/lldb_input/non_windows.json +++ b/tests/debuginfo/pretty-std/lldb_input/non_windows.json @@ -227,7 +227,7 @@ "fields": [ { "name": "ptr", - "type": "core::ptr::unique::Unique", + "type": "core::ptr::non_null::NonNull", "offset": 8 }, { @@ -245,25 +245,6 @@ "alloc::alloc::Global" ] }, - "core::ptr::unique::Unique": { - "size": 8, - "type_class": 16384, - "fields": [ - { - "name": "pointer", - "type": "core::ptr::non_null::NonNull", - "offset": 0 - }, - { - "name": "_marker", - "type": "core::marker::PhantomData", - "offset": 8 - } - ], - "generic_params": [ - "unsigned char" - ] - }, "core::ptr::non_null::NonNull": { "size": 8, "type_class": 16384, diff --git a/tests/debuginfo/pretty-std/lldb_input/windows_gnu.json b/tests/debuginfo/pretty-std/lldb_input/windows_gnu.json index 39ccd60fecfa4..c0f831e31bfe0 100644 --- a/tests/debuginfo/pretty-std/lldb_input/windows_gnu.json +++ b/tests/debuginfo/pretty-std/lldb_input/windows_gnu.json @@ -238,7 +238,7 @@ "fields": [ { "name": "ptr", - "type": "core::ptr::unique::Unique", + "type": "core::ptr::non_null::NonNull", "offset": 8 }, { @@ -256,25 +256,6 @@ "alloc::alloc::Global" ] }, - "core::ptr::unique::Unique": { - "size": 8, - "type_class": 16384, - "fields": [ - { - "name": "pointer", - "type": "core::ptr::non_null::NonNull", - "offset": 0 - }, - { - "name": "_marker", - "type": "core::marker::PhantomData", - "offset": 8 - } - ], - "generic_params": [ - "unsigned char" - ] - }, "core::ptr::non_null::NonNull": { "size": 8, "type_class": 16384, diff --git a/tests/debuginfo/pretty-std/lldb_input/windows_msvc.json b/tests/debuginfo/pretty-std/lldb_input/windows_msvc.json index 1b070b2ad5106..78ce149f65c66 100644 --- a/tests/debuginfo/pretty-std/lldb_input/windows_msvc.json +++ b/tests/debuginfo/pretty-std/lldb_input/windows_msvc.json @@ -250,7 +250,7 @@ }, { "name": "ptr", - "type": "core::ptr::unique::Unique", + "type": "core::ptr::non_null::NonNull", "offset": 8 } ], @@ -269,20 +269,6 @@ } ] }, - "core::ptr::unique::Unique": { - "size": 8, - "type_class": 16384, - "fields": [ - { - "name": "pointer", - "type": "core::ptr::non_null::NonNull", - "offset": 0 - } - ], - "generic_params": [ - "unsigned char" - ] - }, "core::ptr::non_null::NonNull": { "size": 8, "type_class": 16384, diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 692c75bbfbc9d..4ad61e29d3ec0 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -8,7 +8,7 @@ //@ gdb-command:run //@ gdb-command:print plain_string -//@ gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::unique::Unique {pointer: core::ptr::non_null::NonNull {pointer: 0x[...]}, _marker: core::marker::PhantomData}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} +//@ gdb-check:$1 = alloc::string::String {vec: alloc::vec::Vec {buf: alloc::raw_vec::RawVec {inner: alloc::raw_vec::RawVecInner {ptr: core::ptr::non_null::NonNull {pointer: 0x[...]}, cap: core::num::niche_types::UsizeNoHighBit (5), alloc: alloc::alloc::Global}, _marker: core::marker::PhantomData}, len: 5}} //@ gdb-command:print plain_str //@ gdb-check:$2 = "Hello" diff --git a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff index 8b303fe1c87d9..a7cf6a7733083 100644 --- a/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff +++ b/tests/mir-opt/inline/inline_shims.drop.Inline.panic-abort.diff @@ -22,30 +22,26 @@ + scope 6 (inlined alloc::raw_vec::RawVecInner::ptr::) { + scope 7 (inlined alloc::raw_vec::RawVecInner::non_null::) { + let mut _12: std::ptr::NonNull; -+ scope 8 (inlined std::ptr::Unique::::cast::) { -+ scope 9 (inlined NonNull::::cast::) { -+ scope 10 (inlined NonNull::::as_ptr) { -+ } ++ scope 8 (inlined NonNull::::cast::) { ++ scope 9 (inlined NonNull::::as_ptr) { + } + } -+ scope 11 (inlined std::ptr::Unique::::as_non_null_ptr) { -+ } + } -+ scope 12 (inlined NonNull::::as_ptr) { ++ scope 10 (inlined NonNull::::as_ptr) { + } + } + } + } -+ scope 13 (inlined std::ptr::mut_ptr::::cast_slice) { -+ scope 14 (inlined slice_from_raw_parts_mut::) { -+ scope 15 (inlined std::ptr::from_raw_parts_mut::<[A], A>) { ++ scope 11 (inlined std::ptr::mut_ptr::::cast_slice) { ++ scope 12 (inlined slice_from_raw_parts_mut::) { ++ scope 13 (inlined std::ptr::from_raw_parts_mut::<[A], A>) { + } + } + } -+ scope 16 (inlined std::ptr::mut_ptr::::drop_in_place) { -+ scope 17 (inlined drop_in_place::<[A]>) { ++ scope 14 (inlined std::ptr::mut_ptr::::drop_in_place) { ++ scope 15 (inlined drop_in_place::<[A]>) { + let mut _13: &mut [A]; -+ scope 18 (inlined std::ptr::drop_glue::<[A]> - shim(Some([A]))) { ++ scope 16 (inlined std::ptr::drop_glue::<[A]> - shim(Some([A]))) { + let mut _14: usize; + let mut _15: *mut A; + let mut _16: bool; @@ -55,9 +51,9 @@ + } + } + } -+ scope 19 (inlined drop_in_place::>) { ++ scope 17 (inlined drop_in_place::>) { + let mut _17: &mut std::option::Option; -+ scope 20 (inlined std::ptr::drop_glue::> - shim(Some(Option))) { ++ scope 18 (inlined std::ptr::drop_glue::> - shim(Some(Option))) { + let mut _18: isize; + let mut _19: isize; + } @@ -77,7 +73,7 @@ + StorageLive(_9); + StorageLive(_10); + StorageLive(_12); -+ _12 = copy (((((*_7).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); ++ _12 = copy ((((*_7).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); + _10 = copy _12 as *mut A (Transmute); + StorageDead(_12); + _11 = copy ((*_7).1: usize); diff --git a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff index 6bf6ede926004..fb406b8dfefc9 100644 --- a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff +++ b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-abort.diff @@ -57,57 +57,53 @@ scope 11 (inlined alloc::raw_vec::RawVecInner::ptr::) { scope 12 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _34: std::ptr::NonNull; - scope 13 (inlined std::ptr::Unique::::cast::) { - scope 14 (inlined NonNull::::cast::) { - scope 15 (inlined NonNull::::as_ptr) { - } + scope 13 (inlined NonNull::::cast::) { + scope 14 (inlined NonNull::::as_ptr) { } } - scope 16 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 17 (inlined NonNull::::as_ptr) { + scope 15 (inlined NonNull::::as_ptr) { } } } } } - scope 18 (inlined from_utf8_unchecked) { + scope 16 (inlined from_utf8_unchecked) { } } - scope 19 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 17 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 20 (inlined #[track_caller] core::str::traits:: for str>::index) { - scope 21 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 18 (inlined #[track_caller] core::str::traits:: for str>::index) { + scope 19 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 22 (inlined core::str::traits::::eq) { + scope 20 (inlined core::str::traits::::eq) { let mut _35: &&[u8]; let _36: &[u8]; let mut _37: &&[u8]; let _38: &[u8]; - scope 23 (inlined core::str::::as_bytes) { + scope 21 (inlined core::str::::as_bytes) { } - scope 24 (inlined core::str::::as_bytes) { + scope 22 (inlined core::str::::as_bytes) { } - scope 25 (inlined std::cmp::impls::::eq) { - scope 26 (inlined core::slice::cmp::::eq) { + scope 23 (inlined std::cmp::impls::::eq) { + scope 24 (inlined core::slice::cmp::::eq) { let _39: usize; let mut _40: bool; let mut _41: usize; let mut _42: *const u8; let mut _43: *const u8; - scope 27 { - scope 28 (inlined core::slice::::as_ptr) { + scope 25 { + scope 26 (inlined core::slice::::as_ptr) { let mut _44: *const [u8]; } - scope 29 (inlined core::slice::::as_ptr) { + scope 27 (inlined core::slice::::as_ptr) { let mut _45: *const [u8]; } - scope 30 (inlined >::equal_same_length) { + scope 28 (inlined >::equal_same_length) { let mut _46: i32; - scope 31 { + scope 29 { } } } @@ -116,74 +112,70 @@ } } } - scope 32 (inlined std::cmp::impls:: for &String>::eq) { + scope 30 (inlined std::cmp::impls:: for &String>::eq) { let mut _47: &std::string::String; let mut _48: &str; - scope 33 (inlined >::eq) { - scope 34 (inlined #[track_caller] >::index) { + scope 31 (inlined >::eq) { + scope 32 (inlined #[track_caller] >::index) { let _49: &str; - scope 35 (inlined String::as_str) { + scope 33 (inlined String::as_str) { let _50: &[u8]; - scope 36 (inlined Vec::::as_slice) { + scope 34 (inlined Vec::::as_slice) { let _51: *const [u8]; let mut _52: *const u8; let mut _53: usize; - scope 37 (inlined Vec::::as_ptr) { - scope 38 (inlined alloc::raw_vec::RawVec::::ptr) { - scope 39 (inlined alloc::raw_vec::RawVecInner::ptr::) { - scope 40 (inlined alloc::raw_vec::RawVecInner::non_null::) { + scope 35 (inlined Vec::::as_ptr) { + scope 36 (inlined alloc::raw_vec::RawVec::::ptr) { + scope 37 (inlined alloc::raw_vec::RawVecInner::ptr::) { + scope 38 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _54: std::ptr::NonNull; - scope 41 (inlined std::ptr::Unique::::cast::) { - scope 42 (inlined NonNull::::cast::) { - scope 43 (inlined NonNull::::as_ptr) { - } + scope 39 (inlined NonNull::::cast::) { + scope 40 (inlined NonNull::::as_ptr) { } } - scope 44 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 45 (inlined NonNull::::as_ptr) { + scope 41 (inlined NonNull::::as_ptr) { } } } } } - scope 46 (inlined from_utf8_unchecked) { + scope 42 (inlined from_utf8_unchecked) { } } - scope 47 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 43 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 48 (inlined #[track_caller] core::str::traits:: for str>::index) { - scope 49 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 44 (inlined #[track_caller] core::str::traits:: for str>::index) { + scope 45 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 50 (inlined core::str::traits::::eq) { + scope 46 (inlined core::str::traits::::eq) { let mut _55: &&[u8]; let _56: &[u8]; let mut _57: &&[u8]; let _58: &[u8]; - scope 51 (inlined core::str::::as_bytes) { + scope 47 (inlined core::str::::as_bytes) { } - scope 52 (inlined core::str::::as_bytes) { + scope 48 (inlined core::str::::as_bytes) { } - scope 53 (inlined std::cmp::impls::::eq) { - scope 54 (inlined core::slice::cmp::::eq) { + scope 49 (inlined std::cmp::impls::::eq) { + scope 50 (inlined core::slice::cmp::::eq) { let _59: usize; let mut _60: bool; let mut _61: usize; let mut _62: *const u8; let mut _63: *const u8; - scope 55 { - scope 56 (inlined core::slice::::as_ptr) { + scope 51 { + scope 52 (inlined core::slice::::as_ptr) { let mut _64: *const [u8]; } - scope 57 (inlined core::slice::::as_ptr) { + scope 53 (inlined core::slice::::as_ptr) { let mut _65: *const [u8]; } - scope 58 (inlined >::equal_same_length) { + scope 54 (inlined >::equal_same_length) { let mut _66: i32; - scope 59 { + scope 55 { } } } @@ -238,7 +230,7 @@ StorageLive(_31); StorageLive(_32); StorageLive(_34); - _34 = copy ((((((*_27).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _34 = copy (((((*_27).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _32 = copy _34 as *const u8 (Transmute); StorageDead(_34); StorageLive(_33); @@ -300,7 +292,7 @@ StorageLive(_51); StorageLive(_52); StorageLive(_54); - _54 = copy ((((((*_47).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _54 = copy (((((*_47).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _52 = copy _54 as *const u8 (Transmute); StorageDead(_54); StorageLive(_53); diff --git a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff index 8e52a92f5d0d7..d291e3d1eb51e 100644 --- a/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff +++ b/tests/mir-opt/jump_threading.chained_conditions.JumpThreading.panic-unwind.diff @@ -57,57 +57,53 @@ scope 11 (inlined alloc::raw_vec::RawVecInner::ptr::) { scope 12 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _34: std::ptr::NonNull; - scope 13 (inlined std::ptr::Unique::::cast::) { - scope 14 (inlined NonNull::::cast::) { - scope 15 (inlined NonNull::::as_ptr) { - } + scope 13 (inlined NonNull::::cast::) { + scope 14 (inlined NonNull::::as_ptr) { } } - scope 16 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 17 (inlined NonNull::::as_ptr) { + scope 15 (inlined NonNull::::as_ptr) { } } } } } - scope 18 (inlined from_utf8_unchecked) { + scope 16 (inlined from_utf8_unchecked) { } } - scope 19 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 17 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 20 (inlined #[track_caller] core::str::traits:: for str>::index) { - scope 21 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 18 (inlined #[track_caller] core::str::traits:: for str>::index) { + scope 19 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 22 (inlined core::str::traits::::eq) { + scope 20 (inlined core::str::traits::::eq) { let mut _35: &&[u8]; let _36: &[u8]; let mut _37: &&[u8]; let _38: &[u8]; - scope 23 (inlined core::str::::as_bytes) { + scope 21 (inlined core::str::::as_bytes) { } - scope 24 (inlined core::str::::as_bytes) { + scope 22 (inlined core::str::::as_bytes) { } - scope 25 (inlined std::cmp::impls::::eq) { - scope 26 (inlined core::slice::cmp::::eq) { + scope 23 (inlined std::cmp::impls::::eq) { + scope 24 (inlined core::slice::cmp::::eq) { let _39: usize; let mut _40: bool; let mut _41: usize; let mut _42: *const u8; let mut _43: *const u8; - scope 27 { - scope 28 (inlined core::slice::::as_ptr) { + scope 25 { + scope 26 (inlined core::slice::::as_ptr) { let mut _44: *const [u8]; } - scope 29 (inlined core::slice::::as_ptr) { + scope 27 (inlined core::slice::::as_ptr) { let mut _45: *const [u8]; } - scope 30 (inlined >::equal_same_length) { + scope 28 (inlined >::equal_same_length) { let mut _46: i32; - scope 31 { + scope 29 { } } } @@ -116,74 +112,70 @@ } } } - scope 32 (inlined std::cmp::impls:: for &String>::eq) { + scope 30 (inlined std::cmp::impls:: for &String>::eq) { let mut _47: &std::string::String; let mut _48: &str; - scope 33 (inlined >::eq) { - scope 34 (inlined #[track_caller] >::index) { + scope 31 (inlined >::eq) { + scope 32 (inlined #[track_caller] >::index) { let _49: &str; - scope 35 (inlined String::as_str) { + scope 33 (inlined String::as_str) { let _50: &[u8]; - scope 36 (inlined Vec::::as_slice) { + scope 34 (inlined Vec::::as_slice) { let _51: *const [u8]; let mut _52: *const u8; let mut _53: usize; - scope 37 (inlined Vec::::as_ptr) { - scope 38 (inlined alloc::raw_vec::RawVec::::ptr) { - scope 39 (inlined alloc::raw_vec::RawVecInner::ptr::) { - scope 40 (inlined alloc::raw_vec::RawVecInner::non_null::) { + scope 35 (inlined Vec::::as_ptr) { + scope 36 (inlined alloc::raw_vec::RawVec::::ptr) { + scope 37 (inlined alloc::raw_vec::RawVecInner::ptr::) { + scope 38 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _54: std::ptr::NonNull; - scope 41 (inlined std::ptr::Unique::::cast::) { - scope 42 (inlined NonNull::::cast::) { - scope 43 (inlined NonNull::::as_ptr) { - } + scope 39 (inlined NonNull::::cast::) { + scope 40 (inlined NonNull::::as_ptr) { } } - scope 44 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 45 (inlined NonNull::::as_ptr) { + scope 41 (inlined NonNull::::as_ptr) { } } } } } - scope 46 (inlined from_utf8_unchecked) { + scope 42 (inlined from_utf8_unchecked) { } } - scope 47 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 43 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 48 (inlined #[track_caller] core::str::traits:: for str>::index) { - scope 49 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { + scope 44 (inlined #[track_caller] core::str::traits:: for str>::index) { + scope 45 (inlined #[track_caller] core::str::traits:: for RangeFull>::index) { } } - scope 50 (inlined core::str::traits::::eq) { + scope 46 (inlined core::str::traits::::eq) { let mut _55: &&[u8]; let _56: &[u8]; let mut _57: &&[u8]; let _58: &[u8]; - scope 51 (inlined core::str::::as_bytes) { + scope 47 (inlined core::str::::as_bytes) { } - scope 52 (inlined core::str::::as_bytes) { + scope 48 (inlined core::str::::as_bytes) { } - scope 53 (inlined std::cmp::impls::::eq) { - scope 54 (inlined core::slice::cmp::::eq) { + scope 49 (inlined std::cmp::impls::::eq) { + scope 50 (inlined core::slice::cmp::::eq) { let _59: usize; let mut _60: bool; let mut _61: usize; let mut _62: *const u8; let mut _63: *const u8; - scope 55 { - scope 56 (inlined core::slice::::as_ptr) { + scope 51 { + scope 52 (inlined core::slice::::as_ptr) { let mut _64: *const [u8]; } - scope 57 (inlined core::slice::::as_ptr) { + scope 53 (inlined core::slice::::as_ptr) { let mut _65: *const [u8]; } - scope 58 (inlined >::equal_same_length) { + scope 54 (inlined >::equal_same_length) { let mut _66: i32; - scope 59 { + scope 55 { } } } @@ -238,7 +230,7 @@ StorageLive(_31); StorageLive(_32); StorageLive(_34); - _34 = copy ((((((*_27).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _34 = copy (((((*_27).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _32 = copy _34 as *const u8 (Transmute); StorageDead(_34); StorageLive(_33); @@ -300,7 +292,7 @@ StorageLive(_51); StorageLive(_52); StorageLive(_54); - _54 = copy ((((((*_47).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _54 = copy (((((*_47).0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _52 = copy _54 as *const u8 (Transmute); StorageDead(_54); StorageLive(_53); diff --git a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir index cad38c437e3c3..6815c22fc9552 100644 --- a/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/loops.vec_move.runtime-optimized.after.mir @@ -50,78 +50,78 @@ fn vec_move(_1: Vec) -> () { scope 9 { debug cap => _19; } - scope 39 (inlined > as Deref>::deref) { + scope 37 (inlined > as Deref>::deref) { debug self => _37; } - scope 40 (inlined alloc::raw_vec::RawVec::::capacity) { + scope 38 (inlined alloc::raw_vec::RawVec::::capacity) { debug self => _36; let mut _38: &alloc::raw_vec::RawVecInner; - scope 41 (inlined std::mem::size_of::) { + scope 39 (inlined std::mem::size_of::) { } - scope 42 (inlined alloc::raw_vec::RawVecInner::capacity) { + scope 40 (inlined alloc::raw_vec::RawVecInner::capacity) { debug self => _38; debug elem_size => const ::SIZE; let mut _20: core::num::niche_types::UsizeNoHighBit; - scope 43 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { + scope 41 (inlined core::num::niche_types::UsizeNoHighBit::as_inner) { debug self => _20; } } } } - scope 25 (inlined > as Deref>::deref) { + scope 23 (inlined > as Deref>::deref) { debug self => _33; } - scope 26 (inlined Vec::::len) { + scope 24 (inlined Vec::::len) { debug self => _32; let mut _12: bool; - scope 27 { + scope 25 { } } - scope 28 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { + scope 26 (inlined std::ptr::mut_ptr::::wrapping_byte_add) { debug self => _6; debug count => _11; let mut _13: *mut u8; let mut _17: *mut u8; let mut _18: *const impl Sized; - scope 29 (inlined std::ptr::mut_ptr::::cast::) { + scope 27 (inlined std::ptr::mut_ptr::::cast::) { debug self => _6; } - scope 30 (inlined std::ptr::mut_ptr::::wrapping_add) { + scope 28 (inlined std::ptr::mut_ptr::::wrapping_add) { debug self => _13; debug count => _11; let mut _14: isize; - scope 31 (inlined std::ptr::mut_ptr::::wrapping_offset) { + scope 29 (inlined std::ptr::mut_ptr::::wrapping_offset) { debug self => _13; debug count => _14; let mut _15: *const u8; let mut _16: *const u8; } } - scope 32 (inlined std::ptr::mut_ptr::::with_metadata_of::) { + scope 30 (inlined std::ptr::mut_ptr::::with_metadata_of::) { debug self => _17; debug meta => _18; - scope 33 (inlined std::ptr::metadata::) { + scope 31 (inlined std::ptr::metadata::) { debug ptr => _18; } - scope 34 (inlined std::ptr::from_raw_parts_mut::) { + scope 32 (inlined std::ptr::from_raw_parts_mut::) { } } } - scope 35 (inlined > as Deref>::deref) { + scope 33 (inlined > as Deref>::deref) { debug self => _35; } - scope 36 (inlined Vec::::len) { + scope 34 (inlined Vec::::len) { debug self => _34; let mut _8: bool; - scope 37 { + scope 35 { } } - scope 38 (inlined #[track_caller] std::ptr::mut_ptr::::add) { + scope 36 (inlined #[track_caller] std::ptr::mut_ptr::::add) { debug self => _6; debug count => _7; } } - scope 24 (inlined NonNull::::as_ptr) { + scope 22 (inlined NonNull::::as_ptr) { debug self => _5; } } @@ -132,14 +132,10 @@ fn vec_move(_1: Vec) -> () { debug self => _30; scope 19 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _4: std::ptr::NonNull; - scope 20 (inlined std::ptr::Unique::::cast::) { - scope 21 (inlined NonNull::::cast::) { - scope 22 (inlined NonNull::::as_ptr) { - } + scope 20 (inlined NonNull::::cast::) { + scope 21 (inlined NonNull::::as_ptr) { } } - scope 23 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } } } @@ -181,7 +177,7 @@ fn vec_move(_1: Vec) -> () { StorageLive(_5); // DBG: _31 = &_2; // DBG: _30 = &((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec); - _4 = copy (((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _4 = copy ((((_2.0: std::vec::Vec).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _5 = copy _4 as std::ptr::NonNull (Transmute); StorageLive(_6); _6 = copy _4 as *mut impl Sized (Transmute); diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-abort.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-abort.mir index 831a7d2a7b974..2c86c830c0e5f 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-abort.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-abort.mir @@ -16,16 +16,12 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _2: std::ptr::NonNull; - scope 7 (inlined std::ptr::Unique::::cast::) { - scope 8 (inlined NonNull::::cast::) { - scope 9 (inlined NonNull::::as_ptr) { - } + scope 7 (inlined NonNull::::cast::) { + scope 8 (inlined NonNull::::as_ptr) { } } - scope 10 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 11 (inlined NonNull::::as_ptr) { + scope 9 (inlined NonNull::::as_ptr) { } } } @@ -37,7 +33,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { StorageLive(_5); StorageLive(_3); StorageLive(_2); - _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _2 = copy ((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _3 = copy _2 as *const u8 (Transmute); StorageDead(_2); StorageLive(_4); diff --git a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-unwind.mir index 831a7d2a7b974..2c86c830c0e5f 100644 --- a/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-unwind.mir +++ b/tests/mir-opt/pre-codegen/vec_deref.vec_deref_to_slice.runtime-optimized.after.panic-unwind.mir @@ -16,16 +16,12 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { scope 5 (inlined alloc::raw_vec::RawVecInner::ptr::) { scope 6 (inlined alloc::raw_vec::RawVecInner::non_null::) { let mut _2: std::ptr::NonNull; - scope 7 (inlined std::ptr::Unique::::cast::) { - scope 8 (inlined NonNull::::cast::) { - scope 9 (inlined NonNull::::as_ptr) { - } + scope 7 (inlined NonNull::::cast::) { + scope 8 (inlined NonNull::::as_ptr) { } } - scope 10 (inlined std::ptr::Unique::::as_non_null_ptr) { - } } - scope 11 (inlined NonNull::::as_ptr) { + scope 9 (inlined NonNull::::as_ptr) { } } } @@ -37,7 +33,7 @@ fn vec_deref_to_slice(_1: &Vec) -> &[u8] { StorageLive(_5); StorageLive(_3); StorageLive(_2); - _2 = copy (((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::Unique).0: std::ptr::NonNull); + _2 = copy ((((*_1).0: alloc::raw_vec::RawVec).0: alloc::raw_vec::RawVecInner).0: std::ptr::NonNull); _3 = copy _2 as *const u8 (Transmute); StorageDead(_2); StorageLive(_4); From 35ec478d1f9487ed701f7a601b6d98182a81338a Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sun, 20 Sep 2026 14:14:56 +0200 Subject: [PATCH 0451/1309] Use x30 register name with LLVM 23+ --- compiler/rustc_codegen_llvm/src/asm.rs | 9 +++++++-- tests/codegen-llvm/asm-aarch64-x30.rs | 23 +++++++++++++++++++++++ 2 files changed, 30 insertions(+), 2 deletions(-) create mode 100644 tests/codegen-llvm/asm-aarch64-x30.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 46f90aed0fd1d..590a72cecd6c1 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -752,8 +752,13 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> // We use i32 as the type for discarded outputs 'w' }; - if class == 'x' && reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) { - // LLVM doesn't recognize x30. use lr instead. + + if class == 'x' + && reg == InlineAsmReg::AArch64(AArch64InlineAsmReg::x30) + && llvm_util::get_version() < (23, 0, 0) + { + // FIXME(llvm): LLVM <23 does not recognize `x30` as a register name. + // This workaround can be removed when support for LLVM 22 is dropped. "{lr}".to_string() } else { format!("{{{}{}}}", class, idx) diff --git a/tests/codegen-llvm/asm-aarch64-x30.rs b/tests/codegen-llvm/asm-aarch64-x30.rs new file mode 100644 index 0000000000000..c2eda9ca431bb --- /dev/null +++ b/tests/codegen-llvm/asm-aarch64-x30.rs @@ -0,0 +1,23 @@ +//@ add-minicore +//@ compile-flags: --target aarch64-unknown-none +//@ needs-llvm-components: aarch64 +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 + +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub unsafe fn x30_output() -> u64 { + // CHECK-LABEL: define{{.*}}@x30_output + // LLVM22: asm sideeffect{{.*}}"=&{lr},~{cc},~{memory}" + // LLVM23: asm sideeffect{{.*}}"=&{x30},~{cc},~{memory}" + let output: u64; + asm!("", out("x30") output); + output +} From 3de062444441071db0d1f41cd372dd2875783e0a Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sun, 20 Sep 2026 14:30:18 +0200 Subject: [PATCH 0452/1309] Use r14 register name with LLVM 23+ --- compiler/rustc_codegen_llvm/src/asm.rs | 8 ++++++-- tests/codegen-llvm/asm-arm-r14.rs | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 2 deletions(-) create mode 100644 tests/codegen-llvm/asm-arm-r14.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index 590a72cecd6c1..b20a89859388e 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -791,8 +791,12 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> } else if let Some(idx) = hexagon_vreg_pair_index(reg) { // LLVM uses `wN` for Hexagon HVX vector pair registers. format!("{{w{}}}", idx) - } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) { - // LLVM doesn't recognize r14 + } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) + && llvm_util::get_version() < (23, 0, 0) + { + // FIXME(llvm): LLVM <23 does not recognize `r14` as a register name + // in inline assembly. + // This workaround can be removed when support for LLVM 22 is dropped. "{lr}".to_string() } else if let InlineAsmReg::Sparc(reg) = reg && let Some(num) = reg.dreg_number() diff --git a/tests/codegen-llvm/asm-arm-r14.rs b/tests/codegen-llvm/asm-arm-r14.rs new file mode 100644 index 0000000000000..2404e84c1701e --- /dev/null +++ b/tests/codegen-llvm/asm-arm-r14.rs @@ -0,0 +1,23 @@ +//@ add-minicore +//@ compile-flags: --target armv7-unknown-linux-gnueabihf +//@ needs-llvm-components: arm +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 + +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] + +extern crate minicore; +use minicore::*; + +#[no_mangle] +pub unsafe fn r14_output() -> u32 { + // CHECK-LABEL: define{{.*}}@r14_output + // LLVM22: asm sideeffect{{.*}}"=&{lr},~{cc},~{memory}" + // LLVM23: asm sideeffect{{.*}}"=&{r14},~{cc},~{memory}" + let output: u32; + asm!("", out("r14") output); + output +} From fcddd10cfcaea293978a33db7e078aec493deb86 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Sep 2026 15:03:11 +0200 Subject: [PATCH 0453/1309] s390x: use funnel shift --- library/stdarch/crates/core_arch/src/s390x/vector.rs | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index 6703691f080b2..6899f482e270d 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -122,8 +122,6 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.s390.vsrlb"] fn vsrlb(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char; #[link_name = "llvm.s390.vslb"] fn vslb(a: vector_signed_char, b: vector_signed_char) -> vector_signed_char; - #[link_name = "llvm.s390.vsrd"] fn vsrd(a: i8x16, b: i8x16, c: u32) -> i8x16; - #[link_name = "llvm.s390.verimb"] fn verimb(a: vector_signed_char, b: vector_signed_char, c: vector_signed_char, d: i32) -> vector_signed_char; #[link_name = "llvm.s390.verimh"] fn verimh(a: vector_signed_short, b: vector_signed_short, c: vector_signed_short, d: i32) -> vector_signed_short; #[link_name = "llvm.s390.verimf"] fn verimf(a: vector_signed_int, b: vector_signed_int, c: vector_signed_int, d: i32) -> vector_signed_int; @@ -3664,12 +3662,7 @@ mod sealed { #[target_feature(enable = "vector-enhancements-2")] unsafe fn vec_srdb(self, b: Self) -> Self { static_assert_uimm_bits!(C, 3); - transmute(vsrd(transmute(self), transmute(b), C)) - // FIXME(llvm): https://github.com/llvm/llvm-project/issues/129955#issuecomment-3207488190 - // LLVM currently rewrites `fshr` to `fshl`, and the logic in the s390x - // backend cannot deal with that yet. - // #[link_name = "llvm.fshr.i128"] fn fshr_i128(a: u128, b: u128, c: u128) -> u128; - // transmute(fshr_i128(transmute(self), transmute(b), const { C as u128 })) + transmute(u128::funnel_shr(transmute(self), transmute(b), C)) } } )* From 3da3866635c74f7d666422697daba0b759878129 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Sep 2026 15:09:09 +0200 Subject: [PATCH 0454/1309] s390x: use u128 arithmetic --- .../stdarch/crates/core_arch/src/s390x/vector.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/library/stdarch/crates/core_arch/src/s390x/vector.rs b/library/stdarch/crates/core_arch/src/s390x/vector.rs index 6899f482e270d..8fd9fd83a64cd 100644 --- a/library/stdarch/crates/core_arch/src/s390x/vector.rs +++ b/library/stdarch/crates/core_arch/src/s390x/vector.rs @@ -138,9 +138,6 @@ unsafe extern "llvm-intrinsic" { #[link_name = "llvm.s390.vsumqf"] fn vsumqf(a: vector_unsigned_int, b: vector_unsigned_int) -> u128; #[link_name = "llvm.s390.vsumqg"] fn vsumqg(a: vector_unsigned_long_long, b: vector_unsigned_long_long) -> u128; - #[link_name = "llvm.s390.vaccq"] fn vaccq(a: u128, b: u128) -> u128; - #[link_name = "llvm.s390.vacccq"] fn vacccq(a: u128, b: u128, c: u128) -> u128; - #[link_name = "llvm.s390.vscbiq"] fn vscbiq(a: u128, b: u128) -> u128; #[link_name = "llvm.s390.vsbiq"] fn vsbiq(a: u128, b: u128, c: u128) -> u128; #[link_name = "llvm.s390.vsbcbiq"] fn vsbcbiq(a: u128, b: u128, c: u128) -> u128; @@ -4842,9 +4839,7 @@ pub unsafe fn vec_addc_u128( ) -> vector_unsigned_char { let a: u128 = transmute(a); let b: u128 = transmute(b); - // FIXME(llvm) https://github.com/llvm/llvm-project/pull/153557 - // transmute(a.overflowing_add(b).1 as u128) - transmute(vaccq(a, b)) + transmute(a.overflowing_add(b).1 as u128) } /// Vector Add With Carry unsigned 128-bits @@ -4879,10 +4874,8 @@ pub unsafe fn vec_addec_u128( let a: u128 = transmute(a); let b: u128 = transmute(b); let c: u128 = transmute(c); - // FIXME(llvm) https://github.com/llvm/llvm-project/pull/153557 - // let (_d, carry) = a.carrying_add(b, c & 1 != 0); - // transmute(carry as u128) - transmute(vacccq(a, b, c)) + let (_d, carry) = a.carrying_add(b, c & 1 != 0); + transmute(carry as u128) } /// Vector Subtract with Carryout From a94b19e393ffbb56115ac71d4b77faace8d29ad2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 15:09:37 +0200 Subject: [PATCH 0455/1309] simplify FileMetadata handling a bit --- src/tools/miri/src/shims/files.rs | 2 +- src/tools/miri/src/shims/unix/fs.rs | 46 ++++++++++------------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 6726b85e03403..d73ce57f64f19 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -183,7 +183,7 @@ pub trait FileDescription: std::fmt::Debug + FileDescriptionExt { /// Returns the metadata for this FD, if available. /// This is either host metadata, or a non-file-backed-FD type. - /// The latter is for new represented as a string storing a `libc` name so we only + /// The latter is for now represented as a string storing the `libc` name of the mode so we only /// support that kind of metadata on Unix targets. fn metadata<'tcx>(&self) -> InterpResult<'tcx, Either, &'static str>> { throw_unsup_format!("obtaining metadata is only supported on file-backed file descriptors"); diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index ebc81b9de5cd7..98a7c2ff3c2cf 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -715,8 +715,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); } - // `stat` always follows symlinks. - let metadata = match FileMetadata::from_path(this, &path, true)? { + let metadata = match FileMetadata::from_host(this, fs::metadata(path))? { Ok(metadata) => metadata, Err(err) => return this.set_errno_and_return_neg1_i32(err), }; @@ -744,7 +743,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); } - let metadata = match FileMetadata::from_path(this, &path, false)? { + let metadata = match FileMetadata::from_host(this, fs::symlink_metadata(path))? { Ok(metadata) => metadata, Err(err) => return this.set_errno_and_return_neg1_i32(err), }; @@ -819,11 +818,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags for `statx`: {flags:#x}") } - // Empty path requires corresponding flag. - if path.is_empty() && !empty_path_flag { - return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); - } - // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`statx`", reject_with)?; @@ -832,15 +826,18 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file // represented by dirfd, whether it's a directory or otherwise. - let metadata = if path.is_absolute() { - // absolute path, dirfd is ignored. - FileMetadata::from_path(this, &path, !symlink_nofollow_flag)? - } else if path.is_empty() { - // no path, load metadata about dirfd + let metadata = if path.is_empty() { + // no path: invalid by default, load metadata about dirfd with flag + if !empty_path_flag { + return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); + } FileMetadata::from_fd_num(this, dirfd)? - } else if dirfd == this.eval_libc_i32("AT_FDCWD") { - // relative to current working directory - FileMetadata::from_path(this, &path, !symlink_nofollow_flag)? + } else if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { + // Either absolute path (dirfd is ignored) or relative to working directory. + FileMetadata::from_host( + this, + if symlink_nofollow_flag { fs::symlink_metadata(path) } else { fs::metadata(path) }, + )? } else { // relative to dirfd, which must be a directory handle let Some(fd) = this.machine.fds.get(dirfd) else { @@ -1913,17 +1910,6 @@ struct FileMetadata { } impl FileMetadata { - fn from_path<'tcx>( - ecx: &mut MiriInterpCx<'tcx>, - path: &Path, - follow_symlink: bool, - ) -> InterpResult<'tcx, Result> { - let metadata = - if follow_symlink { std::fs::metadata(path) } else { std::fs::symlink_metadata(path) }; - - FileMetadata::from_meta(ecx, metadata) - } - fn from_fd_num<'tcx>( ecx: &mut MiriInterpCx<'tcx>, fd_num: i32, @@ -1932,8 +1918,8 @@ impl FileMetadata { return interp_ok(Err(LibcError("EBADF"))); }; match fd.metadata()? { - Either::Left(host) => Self::from_meta(ecx, host), - Either::Right(name) => Self::synthetic(ecx, name), + Either::Left(host) => Self::from_host(ecx, host), + Either::Right(mode_name) => Self::synthetic(ecx, mode_name), } } @@ -1961,7 +1947,7 @@ impl FileMetadata { })) } - fn from_meta<'tcx>( + fn from_host<'tcx>( ecx: &mut MiriInterpCx<'tcx>, metadata: Result, ) -> InterpResult<'tcx, Result> { From ba4aca62ad9c6401247d85b0f884b947a3cdac89 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 15:23:05 +0200 Subject: [PATCH 0456/1309] stat test: ensure it does follow symlinks --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index ddf63878e25d4..f90ea57c788ce 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -87,12 +87,12 @@ fn assert_statx_matches_metadata(stx: &libc::statx, meta: &fs::Metadata, expecte let mask = stx.stx_mask; // Guaranteed by the shim on any Linux target. - assert!(mask & libc::STATX_SIZE != 0); - assert_eq!(stx.stx_size, expected_size); assert!(mask & libc::STATX_TYPE != 0); assert_eq!((stx.stx_mode as libc::mode_t) & libc::S_IFMT, libc::S_IFREG); assert!(mask & libc::STATX_MODE != 0); assert_ne!((stx.stx_mode as libc::mode_t) & !libc::S_IFMT, 0); + assert!(mask & libc::STATX_SIZE != 0); + assert_eq!(stx.stx_size, expected_size); // Host-dependent enrichment: only assert when the mask says the field is real. if mask & libc::STATX_INO != 0 { @@ -214,12 +214,12 @@ fn test_statx_empty_path_on_pipe() { let statx_buf = statx_buf.assume_init(); - assert_ne!(statx_buf.stx_mask & libc::STATX_SIZE, 0); - assert_eq!(statx_buf.stx_size, 0); assert_ne!(statx_buf.stx_mask & libc::STATX_TYPE, 0); assert_eq!((statx_buf.stx_mode as libc::mode_t) & libc::S_IFMT, libc::S_IFIFO); assert_ne!(statx_buf.stx_mask & libc::STATX_MODE, 0); assert_ne!((statx_buf.stx_mode as libc::mode_t) & !libc::S_IFMT, 0); + assert_ne!(statx_buf.stx_mask & libc::STATX_SIZE, 0); + assert_eq!(statx_buf.stx_size, 0); if cfg!(miri) { // Synthetic metadata must not advertise host-only fields. @@ -768,9 +768,9 @@ fn test_fstat() { errno_check(unsafe { libc::fstat(fd, stat.as_mut_ptr()) }); let stat = unsafe { stat.assume_init_ref() }; - assert_eq!(stat.st_size, 5); assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFREG); assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + assert_eq!(stat.st_size, 5); // Check that all fields are initialized. check_stat_fields(stat); @@ -780,17 +780,21 @@ fn test_fstat() { fn test_stat() { use std::mem::MaybeUninit; + // Also make sure we *do* follow symlinks. let path = utils::prepare_with_content("miri_test_libc_stat.txt", b"hello"); - let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); + let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + + let cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); let mut stat = MaybeUninit::::uninit(); errno_check(unsafe { libc::stat(cpath.as_ptr(), stat.as_mut_ptr()) }); let stat = unsafe { stat.assume_init_ref() }; - assert_eq!(stat.st_size, 5); assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFREG); assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + assert_eq!(stat.st_size, 5); // Check that all fields are initialized. check_stat_fields(stat); @@ -803,7 +807,6 @@ fn test_lstat() { let path = utils::prepare_with_content("miri_test_libc_lstat.txt", b"hello"); let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); let cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); From d20eef42d35917dead346e637409525ffe4b19a7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 15:29:45 +0200 Subject: [PATCH 0457/1309] statx: test that dirfd is ignored when path is absolute --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index f90ea57c788ce..2ec6c730976d3 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -193,6 +193,22 @@ fn test_statx_on_file_path() { assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); } + // dirfd is ignored because our path is absolute. + assert!(path.is_absolute()); + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + 999, // dirfd + c_path.as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + + let stx = stx.assume_init(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + remove_file(&path).unwrap(); } @@ -329,6 +345,11 @@ fn test_dup() { assert!(third_len > 0); let third_len = third_len as usize; assert_eq!(third_buf[..third_len], remaining_bytes[..third_len]); + + // Cleanup + let err = errno_result(libc::close(99)).unwrap_err(); // new_fd2, already closed above! + assert_eq!(err.raw_os_error().unwrap(), libc::EBADF); + errno_check(libc::close(999)); // new_fd3 } } From 9204d85c7980961d8e46ef38b062abaa38dcc81c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Sep 2026 15:34:45 +0200 Subject: [PATCH 0458/1309] enable `__powitf2` --- compiler/rustc_codegen_cranelift/src/compiler_builtins.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs index ca9157daae584..8e339167a5b12 100644 --- a/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs +++ b/compiler/rustc_codegen_cranelift/src/compiler_builtins.rs @@ -135,8 +135,8 @@ builtin_functions! { // float intrinsics fn __powisf2(a: f32, b: i32) -> f32; fn __powidf2(a: f64, b: i32) -> f64; - // FIXME(f16_f128): `compiler-builtins` doesn't currently support `__powitf2` on MSVC. - // fn __powitf2(a: f128, b: i32) -> f128; + #[cfg(not(all(target_os = "windows", target_env = "gnu")))] + fn __powitf2(a: f128, b: i32) -> f128; fn powf(a: f32, b: f32) -> f32; fn pow(a: f64, b: f64) -> f64; fn expf(f: f32) -> f32; From c654d4d01ac933b8841129f7ecf46a4ac92fc945 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Sun, 20 Sep 2026 19:45:35 +0600 Subject: [PATCH 0459/1309] label the path segment that is not an associated item of the trait E0782 pointed only at the trait, leaving the segment that actually failed to resolve unmarked unless it was close enough to suggest a typo fix. --- .../src/hir_ty_lowering/dyn_trait.rs | 9 +++++++ .../dyn-keyword/unresolved-associated-item.rs | 26 +++++++++++++++++++ .../unresolved-associated-item.stderr | 14 ++++++++++ tests/ui/editions/dyn-trait-sugg-2021.stderr | 2 +- tests/ui/resolve/issue-111312.stderr | 2 +- tests/ui/resolve/issue-111727.stderr | 2 +- 6 files changed, 52 insertions(+), 3 deletions(-) create mode 100644 tests/ui/dyn-keyword/unresolved-associated-item.rs create mode 100644 tests/ui/dyn-keyword/unresolved-associated-item.stderr diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index beacb3f188cd9..2ef1922e45e4e 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -1085,6 +1085,15 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { typo, Applicability::MaybeIncorrect, ); + } else { + diag.span_label( + segment.ident.span, + format!( + "not an associated item of trait `{trait_name}`, so `{trait_name}` is \ + interpreted as a type", + trait_name = tcx.item_name(trait_def_id), + ), + ); } } } diff --git a/tests/ui/dyn-keyword/unresolved-associated-item.rs b/tests/ui/dyn-keyword/unresolved-associated-item.rs new file mode 100644 index 0000000000000..420183b323dc1 --- /dev/null +++ b/tests/ui/dyn-keyword/unresolved-associated-item.rs @@ -0,0 +1,26 @@ +//! Checks the E0782 label when a `Trait::item` path matches nothing on the trait. +//! There is no typo to suggest, so the label is the only thing pointing at the real mistake. +//! +//! This is the negative counterpart of `misspelled-associated-item.rs`, which covers the +//! near-miss arm. +//! Keep `nonexistent` far from `exists` so `find_best_match_for_name` returns `None`. +//! If the names get closer, this test silently turns into a copy of that one and still passes. +//! +//! The label is a `span_label`, not a sub-diagnostic, so it has no `// ~` annotation. +//! Only the `.stderr` checks it. +//! +//! See . + +//@ edition: 2021 +// E0782 only fires on 2021+. On 2018 this is just the bare-trait-object lint and the label +// never appears. + +trait Trait { + fn exists() -> Self; +} + +fn main() { + Trait::nonexistent(); + //~^ ERROR expected a type, found a trait + //~| HELP you can add the `dyn` keyword if you want a trait object +} diff --git a/tests/ui/dyn-keyword/unresolved-associated-item.stderr b/tests/ui/dyn-keyword/unresolved-associated-item.stderr new file mode 100644 index 0000000000000..4720a559f2c74 --- /dev/null +++ b/tests/ui/dyn-keyword/unresolved-associated-item.stderr @@ -0,0 +1,14 @@ +error[E0782]: expected a type, found a trait + --> $DIR/unresolved-associated-item.rs:23:5 + | +LL | Trait::nonexistent(); + | ^^^^^ ----------- not an associated item of trait `Trait`, so `Trait` is interpreted as a type + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | ::nonexistent(); + | ++++ + + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0782`. diff --git a/tests/ui/editions/dyn-trait-sugg-2021.stderr b/tests/ui/editions/dyn-trait-sugg-2021.stderr index 3aea8ac491d40..65245ae180368 100644 --- a/tests/ui/editions/dyn-trait-sugg-2021.stderr +++ b/tests/ui/editions/dyn-trait-sugg-2021.stderr @@ -2,7 +2,7 @@ error[E0782]: expected a type, found a trait --> $DIR/dyn-trait-sugg-2021.rs:10:5 | LL | Foo::hi(123); - | ^^^ + | ^^^ -- not an associated item of trait `Foo`, so `Foo` is interpreted as a type | help: you can add the `dyn` keyword if you want a trait object | diff --git a/tests/ui/resolve/issue-111312.stderr b/tests/ui/resolve/issue-111312.stderr index a1f8d6bc46c59..d5fa9ce6f31d7 100644 --- a/tests/ui/resolve/issue-111312.stderr +++ b/tests/ui/resolve/issue-111312.stderr @@ -2,7 +2,7 @@ error[E0782]: expected a type, found a trait --> $DIR/issue-111312.rs:10:5 | LL | HasNot::has(); - | ^^^^^^ + | ^^^^^^ --- not an associated item of trait `HasNot`, so `HasNot` is interpreted as a type | help: you can add the `dyn` keyword if you want a trait object | diff --git a/tests/ui/resolve/issue-111727.stderr b/tests/ui/resolve/issue-111727.stderr index 71ea989ac349f..b93960093c83b 100644 --- a/tests/ui/resolve/issue-111727.stderr +++ b/tests/ui/resolve/issue-111727.stderr @@ -2,7 +2,7 @@ error[E0782]: expected a type, found a trait --> $DIR/issue-111727.rs:4:5 | LL | std::any::Any::create(); - | ^^^^^^^^^^^^^ + | ^^^^^^^^^^^^^ ------ not an associated item of trait `Any`, so `Any` is interpreted as a type | help: you can add the `dyn` keyword if you want a trait object | From dded7e6f261b5a7c76b1507ab29c5334af44d5e6 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 16:26:17 +0200 Subject: [PATCH 0460/1309] windows: reject some FILE_FLAG_OPEN_REPARSE_POINT uses we do not support --- src/tools/miri/src/shims/windows/fs.rs | 21 ++++++-- .../miri/tests/pass-dep/shims/windows-fs.rs | 50 +++++++++---------- 2 files changed, 43 insertions(+), 28 deletions(-) diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index c6a16a082f2ee..9aae6677faeb2 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -13,10 +13,15 @@ use crate::*; #[derive(Copy, Clone, Debug, PartialEq)] enum CreationDisposition { + /// Truncates the file if it exists; create it if it is missing. CreateAlways, + /// Fails if the file already exists; create it if it is missing. CreateNew, + /// Create the file if it is missing. OpenAlways, + /// Fail if the file is missing. OpenExisting, + /// Truncates the file if it exists; fails if it is missing. TruncateExisting, } @@ -152,6 +157,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { { throw_machine_stop!(TerminationInfo::Abort("Invalid CreateFileW argument combination: FILE_FLAG_OPEN_REPARSE_POINT with CREATE_ALWAYS".to_string())); } + if attributes.contains(FileAttributes::OPEN_REPARSE) && creation_disposition != CreateNew { + // We have no logic to "open" a symlink below, but std uses FILE_FLAG_OPEN_REPARSE_POINT + // to implement `create_new` so we have to support that specific combination. + throw_unsup_format!( + "CreateFileW: FILE_FLAG_OPEN_REPARSE_POINT is only supported with CREATE_NEW" + ); + } if template_file != 0 { throw_unsup_format!("CreateFileW: Template files are not supported"); @@ -245,9 +257,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { options.write(desired_write); match creation_disposition { CreateAlways | OpenAlways => { - // We verify `exists_already`: if we expect it to already exist, we set no - // flag, thus failing if it doesn't exist. If we expect the file to not - // exist, we use `create_new` to fail if it does exist. + // These two create the file if it is missing, but also succeed if it + // already exists. As explained above we cannot just always set `create_new` + // here, so we only do that if we think it is needed. + // We later verify our `exists_already` guess: if we expect it to already + // exist, we set no flag, thus failing if it doesn't exist. If we expect the + // file to not exist, we use `create_new` to fail if it does exist. if !exists_already { options.create_new(true); } diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index 79cb551386a18..08670ac535f3b 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -34,7 +34,7 @@ fn main() { test_create_normal_file(); test_create_always_twice(); test_open_always_twice(); - test_open_dir_reparse(); + // test_open_dir_reparse(); test_delete_file(); test_ntstatus_to_dos(); test_file_read_write(); @@ -79,7 +79,7 @@ unsafe fn test_create_normal_file() { FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, ptr::null_mut(), CREATE_NEW, - 0, + FILE_FLAG_OPEN_REPARSE_POINT, // std also sets this ptr::null_mut(), ); assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); @@ -184,29 +184,29 @@ unsafe fn test_open_always_twice() { } // TODO: Once we support more of the std API, it would be nice to test against an actual symlink -unsafe fn test_open_dir_reparse() { - let temp = utils::tmp(); - let raw_path = to_wide_cstr(&temp); - // Open the `temp` directory. - let handle = CreateFileW( - raw_path.as_ptr(), - GENERIC_READ, - FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, - ptr::null_mut(), - OPEN_EXISTING, - FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, - ptr::null_mut(), - ); - assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); - let mut info = std::mem::zeroed::(); - if GetFileInformationByHandle(handle, &mut info) == 0 { - panic!("Failed to get file information") - }; - assert!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0); - if CloseHandle(handle) == 0 { - panic!("Failed to close file") - }; -} +// unsafe fn test_open_dir_reparse() { +// let temp = utils::tmp(); +// let raw_path = to_wide_cstr(&temp); +// // Open the `temp` directory. +// let handle = CreateFileW( +// raw_path.as_ptr(), +// GENERIC_READ, +// FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, +// ptr::null_mut(), +// OPEN_EXISTING, +// FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, +// ptr::null_mut(), +// ); +// assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); +// let mut info = std::mem::zeroed::(); +// if GetFileInformationByHandle(handle, &mut info) == 0 { +// panic!("Failed to get file information") +// }; +// assert!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY != 0); +// if CloseHandle(handle) == 0 { +// panic!("Failed to close file") +// }; +// } unsafe fn test_delete_file() { let temp = utils::tmp().join("test_delete_file.txt"); From 81d89043eb616dab3cf46cc8bf9597e8c2588033 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Sun, 20 Sep 2026 23:02:26 +0800 Subject: [PATCH 0461/1309] Fix ArgAttributes mismatches in ABI UI tests for LoongArch64 and RiscV64 --- tests/ui-fulldeps/rustc_public/check_abi.rs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/tests/ui-fulldeps/rustc_public/check_abi.rs b/tests/ui-fulldeps/rustc_public/check_abi.rs index f6c95fb745409..ed616cc4d9bb0 100644 --- a/tests/ui-fulldeps/rustc_public/check_abi.rs +++ b/tests/ui-fulldeps/rustc_public/check_abi.rs @@ -110,7 +110,12 @@ fn check_primitive(abi: &ArgAbi) { panic!("Expected PassMode::Direct for char, got: {:?}", abi.mode); }; // A char (32-bit) doesn't need sign/zero extension on most platforms. + #[cfg(not(any(target_arch = "loongarch64", target_arch = "riscv64")))] assert_eq!(attrs.arg_extension(), ArgExtension::None); + // However, LoongArch64 and RiscV64 ABIs require that 32-bit integers + // (signed or unsigned) are sign-extended when passed in registers. + #[cfg(any(target_arch = "loongarch64", target_arch = "riscv64"))] + assert_eq!(attrs.arg_extension(), ArgExtension::Sext); // Direct arguments are not pointers, so no pointee alignment. assert_eq!(attrs.pointee_align(), None); let layout = abi.layout.shape(); From 21d6920351a9264b2398c5821b4aef4b2a39a8fe Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 20 Sep 2026 15:06:13 +0000 Subject: [PATCH 0462/1309] Test windows `access_mode` override --- library/std/src/fs/tests.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 148f1c32b08b9..a1c9243051049 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1640,6 +1640,14 @@ fn open_flavors() { assert_eq!(check!(fs::metadata(&tmpdir.join("h"))).len(), 9); } +#[test] +#[cfg(windows)] +fn windows_access_mode_override() { + // ensure that using access_mode negates the need for using write or append + use crate::os::windows::fs::OpenOptionsExt; + File::options().create(true).access_mode(0).open(tmpdir().join("foo.txt")).unwrap(); +} + #[test] fn _assert_send_sync() { fn _assert_send_sync() {} From ac5ff4527453af4f260e3c1972afd6dfc08d9ee0 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 20 Sep 2026 15:15:19 +0000 Subject: [PATCH 0463/1309] Windows: don't error if `access_mode` is set --- library/std/src/sys/fs/windows.rs | 49 +++++++++---------------------- 1 file changed, 14 insertions(+), 35 deletions(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index b703ad9bd0ae8..37f91ea7acf87 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -265,6 +265,16 @@ impl OpenOptions { fn get_access_mode(&self) -> io::Result { match (self.read, self.write, self.append, self.access_mode) { (.., Some(mode)) => Ok(mode), + (_, false, false, None) if self.truncate || self.create || self.create_new => { + Err(io::Error::new( + io::ErrorKind::InvalidInput, + "creating or truncating a file requires write or append access", + )) + } + (_, _, true, None) if self.truncate && !self.create_new => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "append and truncate cannot both be enabled", + )), (true, false, false, None) => Ok(c::GENERIC_READ), (false, true, false, None) => Ok(c::GENERIC_WRITE), (true, true, false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE), @@ -272,45 +282,14 @@ impl OpenOptions { (true, _, true, None) => { Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)) } - (false, false, false, None) => { - // If no access mode is set, check if any creation flags are set - // to provide a more descriptive error message - if self.create || self.create_new || self.truncate { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "creating or truncating a file requires write or append access", - )) - } else { - Err(io::Error::new( - io::ErrorKind::InvalidInput, - "must specify at least one of read, write, or append access", - )) - } - } + (false, false, false, None) => Err(io::Error::new( + io::ErrorKind::InvalidInput, + "must specify at least one of read, write, or append access", + )), } } fn get_cmode_disposition(&self) -> io::Result<(u32, u32)> { - match (self.write, self.append) { - (true, false) => {} - (false, false) => { - if self.truncate || self.create || self.create_new { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "creating or truncating a file requires write or append access", - )); - } - } - (_, true) => { - if self.truncate && !self.create_new { - return Err(io::Error::new( - io::ErrorKind::InvalidInput, - "append and truncate cannot both be enabled", - )); - } - } - } - Ok(match (self.create, self.truncate, self.create_new) { (false, false, false) => (c::OPEN_EXISTING, c::FILE_OPEN), (true, false, false) => (c::OPEN_ALWAYS, c::FILE_OPEN_IF), From 39f76c99e23e90e3769578b991da300fe1cb7e90 Mon Sep 17 00:00:00 2001 From: Chris Denton Date: Sun, 20 Sep 2026 15:18:32 +0000 Subject: [PATCH 0464/1309] Refactor access_mode case out of match --- library/std/src/sys/fs/windows.rs | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 37f91ea7acf87..399c0749bc21e 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -263,26 +263,27 @@ impl OpenOptions { } fn get_access_mode(&self) -> io::Result { - match (self.read, self.write, self.append, self.access_mode) { - (.., Some(mode)) => Ok(mode), - (_, false, false, None) if self.truncate || self.create || self.create_new => { + if let Some(access) = self.access_mode { + return Ok(access); + } + + match (self.read, self.write, self.append) { + (_, false, false) if self.truncate || self.create || self.create_new => { Err(io::Error::new( io::ErrorKind::InvalidInput, "creating or truncating a file requires write or append access", )) } - (_, _, true, None) if self.truncate && !self.create_new => Err(io::Error::new( + (_, _, true) if self.truncate && !self.create_new => Err(io::Error::new( io::ErrorKind::InvalidInput, "append and truncate cannot both be enabled", )), - (true, false, false, None) => Ok(c::GENERIC_READ), - (false, true, false, None) => Ok(c::GENERIC_WRITE), - (true, true, false, None) => Ok(c::GENERIC_READ | c::GENERIC_WRITE), - (false, _, true, None) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA), - (true, _, true, None) => { - Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)) - } - (false, false, false, None) => Err(io::Error::new( + (true, false, false) => Ok(c::GENERIC_READ), + (false, true, false) => Ok(c::GENERIC_WRITE), + (true, true, false) => Ok(c::GENERIC_READ | c::GENERIC_WRITE), + (false, _, true) => Ok(c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA), + (true, _, true) => Ok(c::GENERIC_READ | (c::FILE_GENERIC_WRITE & !c::FILE_WRITE_DATA)), + (false, false, false) => Err(io::Error::new( io::ErrorKind::InvalidInput, "must specify at least one of read, write, or append access", )), From aceae2d1161fa0886ce539a13e94aab42b13dab9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Tue, 25 Aug 2026 19:13:31 +0200 Subject: [PATCH 0465/1309] Replace `IdentIsRaw` with `IdentKind` --- compiler/rustc_ast/src/token.rs | 83 ++++++++--------- compiler/rustc_ast/src/tokenstream.rs | 2 +- compiler/rustc_ast_pretty/src/pprust/state.rs | 22 ++--- .../src/assert/context.rs | 4 +- compiler/rustc_builtin_macros/src/autodiff.rs | 9 +- .../src/deriving/generic/mod.rs | 6 +- compiler/rustc_builtin_macros/src/offload.rs | 4 +- compiler/rustc_expand/src/mbe/macro_check.rs | 6 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 10 +- compiler/rustc_expand/src/mbe/metavar_expr.rs | 6 +- compiler/rustc_expand/src/mbe/quoted.rs | 8 +- compiler/rustc_expand/src/mbe/transcribe.rs | 16 ++-- .../rustc_expand/src/proc_macro_server.rs | 23 ++--- compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_parse/src/lexer/mod.rs | 16 ++-- .../rustc_parse/src/lexer/unicode_chars.rs | 2 +- compiler/rustc_parse/src/parser/asm.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 18 ++-- compiler/rustc_parse/src/parser/expr.rs | 23 ++--- .../src/parser/expr/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/function.rs | 4 +- compiler/rustc_parse/src/parser/item.rs | 18 ++-- compiler/rustc_parse/src/parser/mod.rs | 18 ++-- .../rustc_parse/src/parser/nonterminal.rs | 6 +- compiler/rustc_parse/src/parser/pat.rs | 6 +- compiler/rustc_parse/src/parser/path.rs | 4 +- compiler/rustc_parse/src/parser/tests.rs | 92 +++++++++---------- .../src/parser/tokenstream/tests.rs | 8 +- compiler/rustc_parse/src/parser/ty.rs | 6 +- src/librustdoc/clean/render_macro_matchers.rs | 4 +- 30 files changed, 218 insertions(+), 216 deletions(-) diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index c5addc5926901..371820f65dc70 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -231,7 +231,9 @@ impl Lit { /// `Parser::eat_token_lit` (excluding unary negation). pub fn from_token(token: &Token) -> Option { match token.uninterpolate().kind { - Ident(name, IdentIsRaw::No) if name.is_bool_lit() => Some(Lit::new(Bool, name, None)), + Ident(name, IdentKind::Normal) if name.is_bool_lit() => { + Some(Lit::new(Bool, name, None)) + } Literal(token_lit) => Some(token_lit), OpenInvisible(InvisibleOrigin::MetaVar( MetaVarKind::Literal | MetaVarKind::Expr { .. }, @@ -307,11 +309,11 @@ impl LitKind { } } -pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool { +pub fn ident_can_begin_expr(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `expr` nonterminal which is user observable. - let ident_token = Token::new(Ident(name, is_raw), span); + let ident_token = Token::new(Ident(name, kind), span); // FIXME: Remove `box` from this list given we officially no longer support box expressions // (#108471) (needs lang FCP as it affects stable macro matching behavior). @@ -344,11 +346,11 @@ pub fn ident_can_begin_expr(name: Symbol, span: Span, is_raw: IdentIsRaw) -> boo .contains(&name) } -fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool { +fn ident_can_begin_type(name: Symbol, span: Span, kind: IdentKind) -> bool { // WARNING: Take care when modifying this function! It will change the stable(!) set of // tokens that are allowed to match an `ty` nonterminal which is user observable. - let ident_token = Token::new(Ident(name, is_raw), span); + let ident_token = Token::new(Ident(name, kind), span); !ident_token.is_reserved_ident() || ident_token.is_path_segment_keyword() @@ -357,32 +359,26 @@ fn ident_can_begin_type(name: Symbol, span: Span, is_raw: IdentIsRaw) -> bool { } #[derive(PartialEq, Eq, Encodable, Decodable, Hash, Debug, Copy, Clone, StableHash)] -pub enum IdentIsRaw { - No, - Yes, +pub enum IdentKind { + Normal, + Raw, } -impl IdentIsRaw { +impl IdentKind { pub fn to_print_mode_ident(self) -> IdentPrintMode { match self { - IdentIsRaw::No => IdentPrintMode::Normal, - IdentIsRaw::Yes => IdentPrintMode::RawIdent, + IdentKind::Normal => IdentPrintMode::Normal, + IdentKind::Raw => IdentPrintMode::RawIdent, } } pub fn to_print_mode_lifetime(self) -> IdentPrintMode { match self { - IdentIsRaw::No => IdentPrintMode::Normal, - IdentIsRaw::Yes => IdentPrintMode::RawLifetime, + IdentKind::Normal => IdentPrintMode::Normal, + IdentKind::Raw => IdentPrintMode::RawLifetime, } } } -impl From for IdentIsRaw { - fn from(b: bool) -> Self { - if b { Self::Yes } else { Self::No } - } -} - #[derive(Clone, Copy, PartialEq, Eq, Hash, Encodable, Decodable, Debug, StableHash)] pub enum TokenKind { /* Expression-operator symbols. */ @@ -507,22 +503,22 @@ pub enum TokenKind { /// It's recommended to use `Token::{ident,uninterpolate}` and /// `Parser::token_uninterpolated_span` to treat regular and interpolated /// identifiers in the same way. - Ident(Symbol, IdentIsRaw), + Ident(Symbol, IdentKind), /// This identifier (and its span) is the identifier passed to the /// declarative macro. The span in the surrounding `Token` is the span of /// the `ident` metavariable in the macro's RHS. - NtIdent(sp::Ident, IdentIsRaw), + NtIdent(sp::Ident, IdentKind), /// Lifetime identifier token. /// Do not forget about `NtLifetime` when you want to match on lifetime identifiers. /// It's recommended to use `Token::{ident,uninterpolate}` and /// `Parser::token_uninterpolated_span` to treat regular and interpolated /// identifiers in the same way. - Lifetime(Symbol, IdentIsRaw), + Lifetime(Symbol, IdentKind), /// This identifier (and its span) is the lifetime passed to the /// declarative macro. The span in the surrounding `Token` is the span of /// the `lifetime` metavariable in the macro's RHS. - NtLifetime(sp::Ident, IdentIsRaw), + NtLifetime(sp::Ident, IdentKind), /// A doc comment token. /// `Symbol` is the doc comment's data excluding its "quotes" (`///`, `/**`, etc) @@ -643,7 +639,8 @@ impl Token { /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary. pub fn from_ast_ident(ident: sp::Ident) -> Self { - Token::new(Ident(ident.name, ident.is_raw_guess().into()), ident.span) + let kind = if ident.is_raw_guess() { IdentKind::Raw } else { IdentKind::Normal }; + Token::new(Ident(ident.name, kind), ident.span) } pub fn is_range_separator(&self) -> bool { @@ -674,8 +671,8 @@ impl Token { // tokens that are allowed to match an `expr` nonterminal which is user observable. match self.uninterpolate().kind { - Ident(name, is_raw) => - ident_can_begin_expr(name, self.span, is_raw), // value name or keyword + Ident(name, kind) => + ident_can_begin_expr(name, self.span, kind), // value name or keyword OpenParen | // tuple OpenBrace | // block OpenBracket | // array @@ -743,8 +740,8 @@ impl Token { // object types (consider `use<>+` and `use + Trait` for example). match self.uninterpolate().kind { - Ident(name, is_raw) => - ident_can_begin_type(name, self.span, is_raw), // type name or keyword + Ident(name, kind) => + ident_can_begin_type(name, self.span, kind), // type name or keyword OpenParen // tuple | OpenBracket // array | Bang // never @@ -766,7 +763,7 @@ impl Token { pub fn can_begin_const_arg(&self) -> bool { match self.kind { OpenBrace | Literal(..) | Minus => true, - Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, + Ident(name, IdentKind::Normal) if name.is_bool_lit() => true, OpenInvisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, )) => true, @@ -815,7 +812,7 @@ impl Token { pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | Minus => true, - Ident(name, IdentIsRaw::No) if name.is_bool_lit() => true, + Ident(name, IdentKind::Normal) if name.is_bool_lit() => true, OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { @@ -845,9 +842,9 @@ impl Token { /// otherwise returns the original token. pub fn uninterpolate(&self) -> Cow<'_, Token> { match self.kind { - NtIdent(ident, is_raw) => Cow::Owned(Token::new(Ident(ident.name, is_raw), ident.span)), - NtLifetime(ident, is_raw) => { - Cow::Owned(Token::new(Lifetime(ident.name, is_raw), ident.span)) + NtIdent(ident, kind) => Cow::Owned(Token::new(Ident(ident.name, kind), ident.span)), + NtLifetime(ident, kind) => { + Cow::Owned(Token::new(Lifetime(ident.name, kind), ident.span)) } _ => Cow::Borrowed(self), } @@ -855,22 +852,22 @@ impl Token { /// Returns an identifier if this token is an identifier. #[inline] - pub fn ident(&self) -> Option<(sp::Ident, IdentIsRaw)> { + pub fn ident(&self) -> Option<(sp::Ident, IdentKind)> { // We avoid using `Token::uninterpolate` here because it's slow. match self.kind { - Ident(name, is_raw) => Some((sp::Ident::new(name, self.span), is_raw)), - NtIdent(ident, is_raw) => Some((ident, is_raw)), + Ident(name, kind) => Some((sp::Ident::new(name, self.span), kind)), + NtIdent(ident, kind) => Some((ident, kind)), _ => None, } } /// Returns a lifetime identifier if this token is a lifetime. #[inline] - pub fn lifetime(&self) -> Option<(sp::Ident, IdentIsRaw)> { + pub fn lifetime(&self) -> Option<(sp::Ident, IdentKind)> { // We avoid using `Token::uninterpolate` here because it's slow. match self.kind { - Lifetime(name, is_raw) => Some((sp::Ident::new(name, self.span), is_raw)), - NtLifetime(ident, is_raw) => Some((ident, is_raw)), + Lifetime(name, kind) => Some((sp::Ident::new(name, self.span), kind)), + NtLifetime(ident, kind) => Some((ident, kind)), _ => None, } } @@ -974,7 +971,7 @@ impl Token { pub fn non_reserved_ident(&self) -> Option { self.ident() - .filter(|&(id, raw)| raw == IdentIsRaw::Yes || !sp::Ident::is_reserved(id)) + .filter(|&(id, kind)| kind == IdentKind::Raw || !sp::Ident::is_reserved(id)) .map(|(id, _)| id) } @@ -998,7 +995,7 @@ impl Token { /// Returns `true` if the token is a non-raw identifier for which `pred` holds. pub fn is_non_raw_ident_where(&self, pred: impl FnOnce(sp::Ident) -> bool) -> bool { match self.ident() { - Some((id, IdentIsRaw::No)) => pred(id), + Some((id, IdentKind::Normal)) => pred(id), _ => false, } } @@ -1076,8 +1073,8 @@ impl Token { (Colon, Colon) => PathSep, (Colon, _) => return None, - (SingleQuote, Ident(name, is_raw)) => { - Lifetime(Symbol::intern(&format!("'{name}")), *is_raw) + (SingleQuote, Ident(name, kind)) => { + Lifetime(Symbol::intern(&format!("'{name}")), *kind) } (SingleQuote, _) => return None, diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs index df71aad0111cd..164d1cb8fd731 100644 --- a/compiler/rustc_ast/src/tokenstream.rs +++ b/compiler/rustc_ast/src/tokenstream.rs @@ -793,7 +793,7 @@ impl TokenStream { DelimSpacing::new(Spacing::JointHidden, Spacing::Alone), Delimiter::Bracket, [ - TokenTree::token_alone(token::Ident(sym::doc, token::IdentIsRaw::No), span), + TokenTree::token_alone(token::Ident(sym::doc, token::IdentKind::Normal), span), TokenTree::token_alone(token::Eq, span), TokenTree::token_alone( TokenKind::lit(token::StrRaw(num_of_hashes), data, None), diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 977eb0ee4592d..d97bf7a2a6db3 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -364,20 +364,18 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { // IDENT + `!`: `println!()`, but `if !x { ... }` needs a space after the `if` ( - Tok(tk::Token { kind: tk::Ident(sym, is_raw), span }, _), + Tok(tk::Token { kind: tk::Ident(sym, kind), span }, _), Tok(tk::Token { kind: tk::Bang, .. }, _), - ) if !Ident::new(*sym, *span).is_reserved() || matches!(is_raw, tk::IdentIsRaw::Yes) => { - false - } + ) if !Ident::new(*sym, *span).is_reserved() || matches!(kind, tk::IdentKind::Raw) => false, // IDENT|`fn`|`Self`|`pub` + `(`: `f(3)`, `fn(x: u8)`, `Self()`, `pub(crate)`, // but `let (a, b) = (1, 2)` needs a space after the `let` - (Tok(tk::Token { kind: tk::Ident(sym, is_raw), span }, _), Del(_, _, Parenthesis, _)) + (Tok(tk::Token { kind: tk::Ident(sym, kind), span }, _), Del(_, _, Parenthesis, _)) if !Ident::new(*sym, *span).is_reserved() || *sym == kw::Fn || *sym == kw::SelfUpper || *sym == kw::Pub - || matches!(is_raw, tk::IdentIsRaw::Yes) => + || matches!(kind, tk::IdentKind::Raw) => { false } @@ -1076,17 +1074,17 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere tk::Literal(lit) => literal_to_string(lit).into(), /* Name components */ - tk::Ident(name, is_raw) => { - IdentPrinter::new(name, is_raw.to_print_mode_ident(), convert_dollar_crate) + tk::Ident(name, kind) => { + IdentPrinter::new(name, kind.to_print_mode_ident(), convert_dollar_crate) .to_string() .into() } - tk::NtIdent(ident, is_raw) => { - IdentPrinter::for_ast_ident(ident, is_raw.to_print_mode_ident()).to_string().into() + tk::NtIdent(ident, kind) => { + IdentPrinter::for_ast_ident(ident, kind.to_print_mode_ident()).to_string().into() } - tk::Lifetime(name, is_raw) | tk::NtLifetime(Ident { name, .. }, is_raw) => { - IdentPrinter::new(name, is_raw.to_print_mode_lifetime(), None).to_string().into() + tk::Lifetime(name, kind) | tk::NtLifetime(Ident { name, .. }, kind) => { + IdentPrinter::new(name, kind.to_print_mode_lifetime(), None).to_string().into() } /* Other */ diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index ef39ca049b811..aa339ce7f4252 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{self, Delimiter, IdentIsRaw}; +use rustc_ast::token::{self, Delimiter, IdentKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::{ BinOpKind, BorrowKind, DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MethodCall, @@ -163,7 +163,7 @@ impl<'cx, 'a> Context<'cx, 'a> { let captures = self.capture_decls.iter().flat_map(|cap| { [ TokenTree::token_joint( - token::Ident(cap.ident.name, IdentIsRaw::No), + token::Ident(cap.ident.name, IdentKind::Normal), cap.ident.span, ), TokenTree::token_alone(token::Comma, self.span), diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 5a9988e076b0d..0c81b9080c6cf 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -10,7 +10,7 @@ mod llvm_enzyme { use rustc_ast::expand::autodiff_attrs::{ DiffActivity, DiffMode, valid_input_activity, valid_ret_activity, valid_ty_for_activity, }; - use rustc_ast::token::{Lit, LitKind, Token, TokenKind}; + use rustc_ast::token::{IdentKind, Lit, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::*; use rustc_ast::visit::AssocCtxt::*; use rustc_ast::{ @@ -264,7 +264,8 @@ mod llvm_enzyme { }; // Insert mode token - let mode_token = Token::new(TokenKind::Ident(mode_symbol, false.into()), Span::default()); + let mode_token = + Token::new(TokenKind::Ident(mode_symbol, IdentKind::Normal), Span::default()); ts.insert(0, TokenTree::Token(mode_token, Spacing::Joint)); ts.insert( 1, @@ -299,7 +300,7 @@ mod llvm_enzyme { if !has_ret { // We don't want users to provide a return activity if the function doesn't return anything. // For simplicity, we just add a dummy token to the end of the list. - let t = Token::new(TokenKind::Ident(sym::None, false.into()), Span::default()); + let t = Token::new(TokenKind::Ident(sym::None, IdentKind::Normal), Span::default()); ts.push(TokenTree::Token(t, Spacing::Joint)); ts.push(TokenTree::Token(comma, Spacing::Alone)); } @@ -346,7 +347,7 @@ mod llvm_enzyme { Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); let ts2: Vec = vec![TokenTree::Token( - Token::new(TokenKind::Ident(sym::never, false.into()), span), + Token::new(TokenKind::Ident(sym::never, IdentKind::Normal), span), Spacing::Joint, )]; let never_arg = ast::DelimArgs { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index a041e83a646ce..aa7aa6c0829e5 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -179,7 +179,7 @@ use std::{iter, vec}; pub(crate) use SubstructureFields::*; pub(crate) use rustc_ast as ast; -use rustc_ast::token::{IdentIsRaw, LitKind, Token, TokenKind}; +use rustc_ast::token::{IdentKind, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ AttrArgs, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, Safety, SelfKind, @@ -783,11 +783,11 @@ impl<'a> TraitDef<'a> { dspan: DelimSpan::from_single(self.span), delim: rustc_ast::token::Delimiter::Parenthesis, tokens: [ - TokenKind::Ident(sym::feature, IdentIsRaw::No), + TokenKind::Ident(sym::feature, IdentKind::Normal), TokenKind::Eq, TokenKind::lit(LitKind::Str, sym::derive_const, None), TokenKind::Comma, - TokenKind::Ident(sym::issue, IdentIsRaw::No), + TokenKind::Ident(sym::issue, IdentKind::Normal), TokenKind::Eq, TokenKind::lit(LitKind::Str, sym::derive_const_issue, None), ] diff --git a/compiler/rustc_builtin_macros/src/offload.rs b/compiler/rustc_builtin_macros/src/offload.rs index 4111843b0c9d8..53bf0f4ca6b86 100644 --- a/compiler/rustc_builtin_macros/src/offload.rs +++ b/compiler/rustc_builtin_macros/src/offload.rs @@ -1,5 +1,5 @@ use rustc_ast::ast; -use rustc_ast::token::{Delimiter, Token, TokenKind}; +use rustc_ast::token::{Delimiter, IdentKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_expand::base::{Annotatable, ExtCtxt}; use rustc_session::config::Offload; @@ -149,7 +149,7 @@ pub(crate) fn expand_kernel( // inline(never) attr let ts: Vec = vec![TokenTree::Token( - Token::new(TokenKind::Ident(sym::never, false.into()), span), + Token::new(TokenKind::Ident(sym::never, IdentKind::Normal), span), Spacing::Joint, )]; diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index 7ab595dc73d89..e28044d7632a9 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -105,7 +105,7 @@ //! stored when entering a macro definition starting from the state in which the meta-variable is //! bound. -use rustc_ast::token::{Delimiter, IdentIsRaw, Token, TokenKind}; +use rustc_ast::token::{Delimiter, IdentKind, Token, TokenKind}; use rustc_ast::{DUMMY_NODE_ID, NodeId}; use rustc_data_structures::fx::FxHashMap; use rustc_errors::DecorateDiagCompat; @@ -396,7 +396,9 @@ fn check_nested_occurrences( match (state, tt) { ( NestedMacroState::Empty, - &TokenTree::Token(Token { kind: TokenKind::Ident(name, IdentIsRaw::No), .. }), + &TokenTree::Token(Token { + kind: TokenKind::Ident(name, IdentKind::Normal), .. + }), ) => { if name == kw::MacroRules { state = NestedMacroState::MacroRules; diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 2212724c68bc1..91989b91c7861 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -3,7 +3,7 @@ use std::collections::hash_map::Entry; use std::sync::Arc; use std::{mem, slice}; -use ast::token::IdentIsRaw; +use ast::token::IdentKind; use rustc_ast::token::NtPatKind::*; use rustc_ast::token::TokenKind::*; use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind}; @@ -1750,7 +1750,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Eq | Or => IsInFollow::Yes, - Ident(name, IdentIsRaw::No) if name == kw::If || name == kw::In => { + Ident(name, IdentKind::Normal) if name == kw::If || name == kw::In => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), @@ -1764,7 +1764,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Eq => IsInFollow::Yes, - Ident(name, IdentIsRaw::No) if name == kw::If || name == kw::In => { + Ident(name, IdentKind::Normal) if name == kw::If || name == kw::In => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), @@ -1792,7 +1792,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { TokenTree::Token(token) => match token.kind { OpenBrace | OpenBracket | Comma | FatArrow | Colon | Eq | Gt | Shr | Semi | Or => IsInFollow::Yes, - Ident(name, IdentIsRaw::No) if name == kw::As || name == kw::Where => { + Ident(name, IdentKind::Normal) if name == kw::As || name == kw::Where => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), @@ -1820,7 +1820,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { match tok { TokenTree::Token(token) => match token.kind { Comma => IsInFollow::Yes, - Ident(_, IdentIsRaw::Yes) => IsInFollow::Yes, + Ident(_, IdentKind::Raw) => IsInFollow::Yes, Ident(name, _) if name != kw::Priv => IsInFollow::Yes, _ => { if token.can_begin_type() { diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index a02b84204cb39..76a8d0497b1ad 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{self, Delimiter, IdentIsRaw, Lit, Token, TokenKind}; +use rustc_ast::token::{self, Delimiter, IdentKind, Lit, Token, TokenKind}; use rustc_ast::tokenstream::{TokenStream, TokenStreamIter, TokenTree}; use rustc_ast::{LitIntType, LitKind}; use rustc_ast_pretty::pprust; @@ -272,8 +272,8 @@ fn parse_ident_from_token<'psess>( psess: &'psess ParseSess, token: &Token, ) -> PResult<'psess, Ident> { - if let Some((elem, is_raw)) = token.ident() { - if let IdentIsRaw::Yes = is_raw { + if let Some((elem, kind)) = token.ident() { + if let IdentKind::Raw = kind { return Err(psess.dcx().struct_span_err(elem.span, RAW_IDENT_ERR)); } return Ok(elem); diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index 2779291abf361..aed69c9f5d938 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -1,4 +1,4 @@ -use rustc_ast::token::{self, Delimiter, IdentIsRaw, NonterminalKind, Token}; +use rustc_ast::token::{self, Delimiter, IdentKind, NonterminalKind, Token}; use rustc_ast::tokenstream::TokenStreamIter; use rustc_ast::{NodeId, tokenstream}; use rustc_ast_pretty::pprust; @@ -325,10 +325,10 @@ fn parse_tree<'a>( // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` // special metavariable that names the crate of the invocation. Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => { - let (ident, is_raw) = token.ident().unwrap(); + let (ident, kind) = token.ident().unwrap(); let span = ident.span.with_lo(dollar_span.lo()); - if ident.name == kw::Crate && matches!(is_raw, IdentIsRaw::No) { - TokenTree::token(token::Ident(kw::DollarCrate, is_raw), span) + if ident.name == kw::Crate && matches!(kind, IdentKind::Normal) { + TokenTree::token(token::Ident(kw::DollarCrate, kind), span) } else { TokenTree::MetaVar(span, ident) } diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 2627e327c0f71..c258d9e471079 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -1,7 +1,7 @@ use std::mem; use rustc_ast::token::{ - self, Delimiter, IdentIsRaw, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind, + self, Delimiter, IdentKind, InvisibleOrigin, Lit, LitKind, MetaVarKind, Token, TokenKind, }; use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree}; use rustc_ast::{ExprKind, StmtKind, TyKind, UnOp}; @@ -498,10 +498,10 @@ fn transcribe_pnr<'tx>( // parsing priorities. maybe_use_metavar_location(tscx.psess, &tscx.stack, sp, tt, &mut tscx.marker) } - ParseNtResult::Ident(ident, is_raw) => { + ParseNtResult::Ident(ident, kind) => { tscx.marker.mark_span(&mut sp); with_metavar_spans(|mspans| mspans.insert(ident.span, sp)); - let kind = token::NtIdent(*ident, *is_raw); + let kind = token::NtIdent(*ident, *kind); TokenTree::token_alone(kind, sp) } ParseNtResult::Lifetime(ident, is_raw) => { @@ -575,7 +575,7 @@ fn transcribe_pnr<'tx>( let leading_if_span = guard.span_with_leading_if.with_hi(guard.span_with_leading_if.lo() + BytePos(2)); let ts = std::iter::once(TokenTree::token_alone( - token::Ident(kw::If, IdentIsRaw::No), + token::Ident(kw::If, IdentKind::Normal), leading_if_span, )) .chain(TokenStream::from_ast(&guard.cond).iter().cloned()) @@ -1004,18 +1004,18 @@ fn extract_symbol_from_pnr<'a>( span_err: Span, ) -> PResult<'a, Symbol> { match pnr { - ParseNtResult::Ident(nt_ident, is_raw) => { - if let IdentIsRaw::Yes = is_raw { + ParseNtResult::Ident(nt_ident, kind) => { + if let IdentKind::Raw = kind { Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) } else { Ok(nt_ident.name) } } ParseNtResult::Tt(TokenTree::Token( - Token { kind: TokenKind::Ident(symbol, is_raw), .. }, + Token { kind: TokenKind::Ident(symbol, kind), .. }, _, )) => { - if let IdentIsRaw::Yes = is_raw { + if let IdentKind::Raw = kind { Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) } else { Ok(*symbol) diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index c0a9a43c64cdf..be837cf9eacc0 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -228,31 +228,31 @@ impl FromInternal for Vec> { tk::Question => op("?"), tk::SingleQuote => op("'"), - tk::Ident(sym, is_raw) => trees.push(TokenTree::Ident(Ident { + tk::Ident(sym, kind) => trees.push(TokenTree::Ident(Ident { sym, - is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), + is_raw: matches!(kind, tk::IdentKind::Raw), span, })), - tk::NtIdent(ident, is_raw) => trees.push(TokenTree::Ident(Ident { + tk::NtIdent(ident, kind) => trees.push(TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), + is_raw: matches!(kind, tk::IdentKind::Raw), span: ident.span, })), - tk::Lifetime(name, is_raw) => { + tk::Lifetime(name, kind) => { let ident = rustc_span::Ident::new(name, span).without_first_quote(); trees.extend([ TokenTree::Punct(Punct { ch: b'\'', joint: true, span }), TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(is_raw, tk::IdentIsRaw::Yes), + is_raw: matches!(kind, tk::IdentKind::Raw), span, }), ]); } - tk::NtLifetime(ident, is_raw) => { + tk::NtLifetime(ident, kind) => { let stream = - TokenStream::token_alone(tk::Lifetime(ident.name, is_raw), ident.span); + TokenStream::token_alone(tk::Lifetime(ident.name, kind), ident.span); trees.push(TokenTree::Group(Group { delimiter: rustc_proc_macro::Delimiter::None, stream: Some(stream), @@ -274,7 +274,7 @@ impl FromInternal for Vec> { escaped.extend(ch.escape_debug()); } let stream = [ - tk::Ident(sym::doc, tk::IdentIsRaw::No), + tk::Ident(sym::doc, tk::IdentKind::Normal), tk::Eq, tk::TokenKind::lit(tk::Str, Symbol::intern(&escaped), None), ] @@ -366,7 +366,8 @@ impl ToInternal> } TokenTree::Ident(self::Ident { sym, is_raw, span }) => { rustc.psess().symbol_gallery.insert(sym, span); - smallvec![tokenstream::TokenTree::token_alone(tk::Ident(sym, is_raw.into()), span)] + let kind = if is_raw { tk::IdentKind::Raw } else { tk::IdentKind::Normal }; + smallvec![tokenstream::TokenTree::token_alone(tk::Ident(sym, kind), span)] } TokenTree::Literal(self::Literal { kind: self::LitKind::Integer, @@ -625,7 +626,7 @@ impl server::Server for Rustc<'_, '_> { match &expr.kind { ast::ExprKind::Lit(token_lit) if token_lit.kind == tk::Bool => { Ok(tokenstream::TokenStream::token_alone( - tk::Ident(token_lit.symbol, tk::IdentIsRaw::No), + tk::Ident(token_lit.symbol, tk::IdentKind::Normal), expr.span, )) } diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2d571d8b8e13d..c41071a8cf7d9 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1757,11 +1757,11 @@ impl KeywordIdents { match tt { // Only report non-raw idents. TokenTree::Token(token, _) => { - if let Some((ident, token::IdentIsRaw::No)) = token.ident() { + if let Some((ident, token::IdentKind::Normal)) = token.ident() { if !prev_dollar { self.check_ident_token(cx, UnderMacro(true), ident, ""); } - } else if let Some((ident, token::IdentIsRaw::No)) = token.lifetime() { + } else if let Some((ident, token::IdentKind::Normal)) = token.lifetime() { self.check_ident_token( cx, UnderMacro(true), diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 2afb55b02e2e6..ddb1f6c77c1fd 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -1,6 +1,6 @@ use diagnostics::make_errors_for_mismatched_closing_delims; use rustc_ast::ast::{self, AttrStyle}; -use rustc_ast::token::{self, CommentKind, Delimiter, IdentIsRaw, Token, TokenKind}; +use rustc_ast::token::{self, CommentKind, Delimiter, IdentKind, Token, TokenKind}; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::unicode::{TEXT_FLOW_CONTROL_CHARS, contains_text_flow_control_chars}; use rustc_errors::codes::*; @@ -238,7 +238,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { self.dcx().emit_err(crate::diagnostics::CannotBeRawIdent { span, ident: sym }); } self.psess.raw_identifier_spans.push(span); - token::Ident(sym, IdentIsRaw::Yes) + token::Ident(sym, IdentKind::Raw) } rustc_lexer::TokenKind::UnknownPrefix => { self.report_unknown_prefix(start); @@ -252,7 +252,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let lifetime_name = self.str_from(start); self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); let ident = Symbol::intern(lifetime_name); - token::Lifetime(ident, IdentIsRaw::No) + token::Lifetime(ident, IdentKind::Normal) } rustc_lexer::TokenKind::InvalidIdent // Do not recover an identifier with emoji if the codepoint is a confusable @@ -270,7 +270,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { .entry(sym) .or_default() .push(span); - token::Ident(sym, IdentIsRaw::No) + token::Ident(sym, IdentKind::Normal) } // split up (raw) c string literals to an ident and a string literal when edition < // 2021. @@ -337,7 +337,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { .with_span(span) .stash(span, StashKey::LifetimeIsChar); } - token::Lifetime(lifetime_name, IdentIsRaw::No) + token::Lifetime(lifetime_name, IdentKind::Normal) } rustc_lexer::TokenKind::RawLifetime => { self.last_lifetime = Some(self.mk_sp(start, start + BytePos(1))); @@ -387,7 +387,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { // Make sure we mark this as a raw identifier. self.psess.raw_identifier_spans.push(span); - token::Lifetime(sym, IdentIsRaw::Yes) + token::Lifetime(sym, IdentKind::Raw) } else { // Reset the state so we just lex the `'r`. self.pos = start + BytePos(2); @@ -407,7 +407,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { ); let lifetime_name = nfc_normalize(self.str_from(start)); - token::Lifetime(lifetime_name, IdentIsRaw::No) + token::Lifetime(lifetime_name, IdentKind::Normal) } } rustc_lexer::TokenKind::Semi => token::Semi, @@ -497,7 +497,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { let sym = nfc_normalize(self.str_from(start)); let span = self.mk_sp(start, self.pos); self.psess.symbol_gallery.insert(sym, span); - token::Ident(sym, IdentIsRaw::No) + token::Ident(sym, IdentKind::Normal) } /// Detect usages of Unicode codepoints changing the direction of the text on screen and loudly diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs index 826d193634a45..a934bb62d6a9c 100644 --- a/compiler/rustc_parse/src/lexer/unicode_chars.rs +++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs @@ -307,7 +307,7 @@ pub(super) static UNICODE_ARRAY: &[(char, &str, &str)] = &[ // fancier error recovery to it, as there will be less overall work to do this way. const ASCII_ARRAY: &[(&str, &str, Option)] = &[ (" ", "Space", None), - ("_", "Underscore", Some(token::Ident(kw::Underscore, token::IdentIsRaw::No))), + ("_", "Underscore", Some(token::Ident(kw::Underscore, token::IdentKind::Normal))), ("-", "Minus/Hyphen", Some(token::Minus)), (",", "Comma", Some(token::Comma)), (";", "Semicolon", Some(token::Semi)), diff --git a/compiler/rustc_parse/src/parser/asm.rs b/compiler/rustc_parse/src/parser/asm.rs index 5c177af086565..92b0b96fab165 100644 --- a/compiler/rustc_parse/src/parser/asm.rs +++ b/compiler/rustc_parse/src/parser/asm.rs @@ -1,7 +1,7 @@ use rustc_ast::{self as ast, AsmMacro}; use rustc_span::{Span, Symbol, kw}; -use super::{ExpKeywordPair, ForceCollect, IdentIsRaw, Trailing, UsePreAttrPos}; +use super::{ExpKeywordPair, ForceCollect, IdentKind, Trailing, UsePreAttrPos}; use crate::{PResult, Parser, diagnostics, exp, token}; /// An argument to one of the `asm!` macros. The argument is syntactically valid, but is otherwise @@ -368,7 +368,7 @@ fn parse_clobber_abi<'a>(p: &mut Parser<'a>) -> PResult<'a, Vec<(Symbol, Span)>> fn parse_reg<'a>(p: &mut Parser<'a>) -> PResult<'a, ast::InlineAsmRegOrRegClass> { p.expect(exp!(OpenParen))?; let result = match p.token.uninterpolate().kind { - token::Ident(name, IdentIsRaw::No) => ast::InlineAsmRegOrRegClass::RegClass(name), + token::Ident(name, IdentKind::Normal) => ast::InlineAsmRegOrRegClass::RegClass(name), token::Literal(token::Lit { kind: token::LitKind::Str, symbol, suffix: _ }) => { ast::InlineAsmRegOrRegClass::Reg(symbol) } diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f5fa592585099..5300fcc133328 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1,7 +1,7 @@ use std::mem::take; use std::ops::{Deref, DerefMut}; -use ast::token::IdentIsRaw; +use ast::token::IdentKind; use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind}; use rustc_ast::util::parser::AssocOp; use rustc_ast::{ @@ -200,7 +200,7 @@ impl<'a> Parser<'a> { pub(super) fn expected_ident_found( &mut self, recover: bool, - ) -> PResult<'a, (Ident, IdentIsRaw)> { + ) -> PResult<'a, (Ident, IdentKind)> { let valid_follow = &[ TokenKind::Eq, TokenKind::Colon, @@ -228,11 +228,11 @@ impl<'a> Parser<'a> { let bad_token = self.token; // suggest prepending a keyword in identifier position with `r#` - let suggest_raw = if let Some((ident, IdentIsRaw::No)) = self.token.ident() + let suggest_raw = if let Some((ident, IdentKind::Normal)) = self.token.ident() && ident.is_raw_guess() && self.look_ahead(1, |t| valid_follow.contains(&t.kind)) { - recovered_ident = Some((ident, IdentIsRaw::Yes)); + recovered_ident = Some((ident, IdentKind::Raw)); // `Symbol::to_string()` is different from `Symbol::into_diag_arg()`, // which uses `Symbol::to_ident_string()` and "helpfully" adds an implicit `r#` @@ -258,7 +258,7 @@ impl<'a> Parser<'a> { let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, valid_portion)| { let (invalid, valid) = self.token.span.split_at(len as u32); - recovered_ident = Some((Ident::new(valid_portion, valid), IdentIsRaw::No)); + recovered_ident = Some((Ident::new(valid_portion, valid), IdentKind::Normal)); HelpIdentifierStartsWithNumber { num_span: invalid } }); @@ -277,7 +277,7 @@ impl<'a> Parser<'a> { if self.token == token::Lt { // Let's check if the previous token could denote the start of an item // whose kind can have generics. - if let Some((Ident { name, .. }, IdentIsRaw::No)) = self.prev_token.ident() + if let Some((Ident { name, .. }, IdentKind::Normal)) = self.prev_token.ident() && let kw::Fn | kw::Type | kw::Struct | kw::Enum | kw::Union | kw::Trait = name { match self.parse_generics() { @@ -508,7 +508,7 @@ impl<'a> Parser<'a> { ); } - if let Some((ident, IdentIsRaw::No)) = self.prev_token.ident() + if let Some((ident, IdentKind::Normal)) = self.prev_token.ident() && let "def" | "fun" | "func" | "function" = ident.name.as_str() { err.span_suggestion_short( @@ -542,9 +542,9 @@ impl<'a> Parser<'a> { // positive for a `cr#` that wasn't intended to start a c-string literal, but identifying // that in the parser requires unbounded lookahead, so we only add a hint to the existing // error rather than replacing it entirely. - if ((self.prev_token == TokenKind::Ident(sym::character('c'), IdentIsRaw::No) + if ((self.prev_token == TokenKind::Ident(sym::character('c'), IdentKind::Normal) && matches!(&self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }))) - || (self.prev_token == TokenKind::Ident(sym::cr, IdentIsRaw::No) + || (self.prev_token == TokenKind::Ident(sym::cr, IdentKind::Normal) && matches!( &self.token.kind, TokenKind::Literal(token::Lit { kind: token::Str, .. }) | token::Pound diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6bc42a0a40734..6297537e2ecbe 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4,7 +4,7 @@ use core::mem; use core::ops::{Bound, ControlFlow}; use ast::mut_visit::{self, MutVisitor}; -use ast::token::IdentIsRaw; +use ast::token::IdentKind; use ast::{ForLoopKind, MatchKind, Pat, Path, PathSegment, Recovered}; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; @@ -501,7 +501,7 @@ impl<'a> Parser<'a> { let token_cannot_continue_expr = |t: &Token| match t.uninterpolate().kind { // These tokens can start an expression after `!`, but // can't continue an expression after an ident - token::Ident(name, is_raw) => token::ident_can_begin_expr(name, t.span, is_raw), + token::Ident(name, kind) => token::ident_can_begin_expr(name, t.span, kind), token::Literal(..) | token::Pound => true, _ => t.is_metavar_expr(), }; @@ -741,7 +741,8 @@ impl<'a> Parser<'a> { lo: Span, ) -> PResult<'a, Box> { let mut res = loop { - let has_question = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + let has_question = if self.prev_token == TokenKind::Ident(kw::Return, IdentKind::Normal) + { // We are using noexpect here because we don't expect a `?` directly after // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Question) @@ -753,7 +754,7 @@ impl<'a> Parser<'a> { e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); continue; } - let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentIsRaw::No) { + let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentKind::Normal) { // We are using noexpect here because we don't expect a `.` directly after // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Dot) @@ -823,7 +824,7 @@ impl<'a> Parser<'a> { // We end up with the `sym` (`1`) token in `self.prev_token` and a dot in // `self.token`. assert!(suffix.is_none()); - self.token = Token::new(token::Ident(sym, IdentIsRaw::No), ident_span); + self.token = Token::new(token::Ident(sym, IdentKind::Normal), ident_span); self.bump_with((Token::new(token::Dot, dot_span), self.token_spacing)); self.mk_expr_tuple_field_access(lo, ident_span, base, sym, None) } @@ -839,7 +840,7 @@ impl<'a> Parser<'a> { // the `sym2` (`2` or `2e3`) token in `self.prev_token` and the following // token in `self.token`. let next_token2 = - Token::new(token::Ident(sym2, IdentIsRaw::No), ident2_span); + Token::new(token::Ident(sym2, IdentKind::Normal), ident2_span); self.bump_with((next_token2, self.token_spacing)); self.bump(); let base1 = @@ -1902,7 +1903,7 @@ impl<'a> Parser<'a> { self.bump(); // `builtin` self.bump(); // `#` - let Some((ident, IdentIsRaw::No)) = self.token.ident() else { + let Some((ident, IdentKind::Normal)) = self.token.ident() else { let err = self .dcx() .create_err(crate::diagnostics::ExpectedBuiltinIdent { span: self.token.span }); @@ -2017,7 +2018,7 @@ impl<'a> Parser<'a> { }; // On an error path, eagerly consider a lifetime to be an unclosed character lit, if that // makes sense. - if let Some((ident, IdentIsRaw::No)) = self.token.lifetime() + if let Some((ident, IdentKind::Normal)) = self.token.lifetime() && could_be_unclosed_char_literal(ident) { let lt = self.expect_lifetime(); @@ -2089,7 +2090,7 @@ impl<'a> Parser<'a> { } }; match self.token.uninterpolate().kind { - token::Ident(name, IdentIsRaw::No) if name.is_bool_lit() => { + token::Ident(name, IdentKind::Normal) if name.is_bool_lit() => { self.bump(); Some(token::Lit::new(token::Bool, name, None)) } @@ -3002,9 +3003,9 @@ impl<'a> Parser<'a> { } pub(crate) fn eat_label(&mut self) -> Option - | ---- required by a bound in this function LL | where LL | MOuter: Monad, | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `join` diff --git a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr index c85b72fbfe11b..fedffd8bc3907 100644 --- a/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr +++ b/tests/ui/generic-associated-types/issue-87429-associated-type-default.stderr @@ -8,6 +8,8 @@ LL | type Member<'a>: for<'b> PartialEq> = Foo; note: required by a bound in `Family2::Member` --> $DIR/issue-87429-associated-type-default.rs:13:22 | +LL | trait Family2 { +LL | // Not fine, not Foo: PartialEq LL | type Member<'a>: for<'b> PartialEq> = Foo; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family2::Member` help: consider annotating `Foo` with `#[derive(PartialEq)]` diff --git a/tests/ui/generic-associated-types/issue-87429-specialization.stderr b/tests/ui/generic-associated-types/issue-87429-specialization.stderr index dbe97bdb74318..91263af3e071e 100644 --- a/tests/ui/generic-associated-types/issue-87429-specialization.stderr +++ b/tests/ui/generic-associated-types/issue-87429-specialization.stderr @@ -8,6 +8,7 @@ LL | default type Member<'a> = Foo; note: required by a bound in `Family::Member` --> $DIR/issue-87429-specialization.rs:6:22 | +LL | trait Family { LL | type Member<'a>: for<'b> PartialEq>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Family::Member` help: consider annotating `Foo` with `#[derive(PartialEq)]` diff --git a/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr b/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr index 57bff7c9e054f..3155d78210c95 100644 --- a/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr +++ b/tests/ui/generic-associated-types/multiple-type-params-with-unmet-bounds.stderr @@ -7,6 +7,7 @@ LL | let _: <() as Trait>::P; note: required by a bound in `Trait::P` --> $DIR/multiple-type-params-with-unmet-bounds.rs:2:15 | +LL | trait Trait { LL | type P; | ^^^^ required by this bound in `Trait::P` diff --git a/tests/ui/generic-associated-types/own-bound-span.stderr b/tests/ui/generic-associated-types/own-bound-span.stderr index 7c34a0acdbe08..4d0688111e0d0 100644 --- a/tests/ui/generic-associated-types/own-bound-span.stderr +++ b/tests/ui/generic-associated-types/own-bound-span.stderr @@ -7,6 +7,7 @@ LL | let _: ::P; note: required by a bound in `D::P` --> $DIR/own-bound-span.rs:4:15 | +LL | trait D { LL | type P; | ^^^^ required by this bound in `D::P` diff --git a/tests/ui/generic-associated-types/type-param-defaults.stderr b/tests/ui/generic-associated-types/type-param-defaults.stderr index 87e9a4d779485..76adedeee782a 100644 --- a/tests/ui/generic-associated-types/type-param-defaults.stderr +++ b/tests/ui/generic-associated-types/type-param-defaults.stderr @@ -31,7 +31,6 @@ note: required by a bound in `foo` --> $DIR/type-param-defaults.rs:25:14 | LL | fn foo() - | --- required by a bound in this function LL | where LL | T: Trait, | ^^^^^^^^^^^ required by this bound in `foo` @@ -51,7 +50,6 @@ note: required by a bound in `foo` --> $DIR/type-param-defaults.rs:26:15 | LL | fn foo() - | --- required by a bound in this function ... LL | T::Assoc: Other { | ^^^^^ required by this bound in `foo` diff --git a/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr index d0d65a030841c..45182d08d4b5d 100644 --- a/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr +++ b/tests/ui/generic-const-items/trivially-unsatisfied-bounds.mentioned.stderr @@ -16,7 +16,6 @@ note: required by a bound in `UNUSABLE` --> $DIR/trivially-unsatisfied-bounds.rs:19:26 | LL | const UNUSABLE: () = () - | -------- required by a bound in this constant LL | where LL | for<'_delay> String: Copy; | ^^^^ required by this bound in `UNUSABLE` diff --git a/tests/ui/generic-const-items/unsatisfied-bounds.stderr b/tests/ui/generic-const-items/unsatisfied-bounds.stderr index 06cd935fae4c0..bb18ad92b9bd6 100644 --- a/tests/ui/generic-const-items/unsatisfied-bounds.stderr +++ b/tests/ui/generic-const-items/unsatisfied-bounds.stderr @@ -20,7 +20,6 @@ note: required by a bound in `K` --> $DIR/unsatisfied-bounds.rs:12:17 | LL | const K: () = () - | - required by a bound in this constant LL | where LL | Infallible: From; | ^^^^^^^ required by this bound in `K` @@ -34,8 +33,8 @@ LL | let _ = <() as Trait>>::A; note: required by a bound in `Trait::A` --> $DIR/unsatisfied-bounds.rs:17:12 | +LL | trait Trait

{ LL | const A: u32 - | - required by a bound in this associated constant LL | where LL | P: Copy; | ^^^^ required by this bound in `Trait::A` @@ -49,8 +48,9 @@ LL | let _ = <() as Trait<&'static str>>::B::<()>; note: required by a bound in `Trait::B` --> $DIR/unsatisfied-bounds.rs:21:21 | +LL | trait Trait

{ +... LL | const B: u32 - | - required by a bound in this associated constant LL | where LL | Infallible: From; | ^^^^^^^ required by this bound in `Trait::B` diff --git a/tests/ui/higher-ranked/hrtb-with-assoc-type-projection.stderr b/tests/ui/higher-ranked/hrtb-with-assoc-type-projection.stderr index bb54da98c2333..79985580e23b5 100644 --- a/tests/ui/higher-ranked/hrtb-with-assoc-type-projection.stderr +++ b/tests/ui/higher-ranked/hrtb-with-assoc-type-projection.stderr @@ -15,7 +15,6 @@ note: required by a bound in `trigger_error` --> $DIR/hrtb-with-assoc-type-projection.rs:12:72 | LL | pub fn trigger_error(iterable: I, functor: F) - | ------------- required by a bound in this function ... LL | for<'t> ::IntoIter, F> as Iterator>::Item: Foo, | ^^^ required by this bound in `trigger_error` diff --git a/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr b/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr index e9ec3e9dc0707..6964e50fb79fb 100644 --- a/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr +++ b/tests/ui/higher-ranked/relate-bound-region-ice-144033.stderr @@ -20,8 +20,8 @@ LL | let collection = std::iter::empty::<()>().map(|_| &()); note: required by a bound in `FooMut::bar` --> $DIR/relate-bound-region-ice-144033.rs:8:33 | +LL | trait FooMut { LL | fn bar(self, _: I) - | --- required by a bound in this associated function LL | where LL | for<'b> &'b I: Iterator; | ^^^^^^^^^^^^^ required by this bound in `FooMut::bar` diff --git a/tests/ui/higher-ranked/trait-bounds/higher-trait-bounds-ice-60218.stderr b/tests/ui/higher-ranked/trait-bounds/higher-trait-bounds-ice-60218.stderr index b02179f141251..028d3cb104e40 100644 --- a/tests/ui/higher-ranked/trait-bounds/higher-trait-bounds-ice-60218.stderr +++ b/tests/ui/higher-ranked/trait-bounds/higher-trait-bounds-ice-60218.stderr @@ -15,7 +15,6 @@ note: required by a bound in `trigger_error` --> $DIR/higher-trait-bounds-ice-60218.rs:12:72 | LL | pub fn trigger_error(iterable: I, functor: F) - | ------------- required by a bound in this function ... LL | for<'t> ::IntoIter, F> as Iterator>::Item: Foo, | ^^^ required by this bound in `trigger_error` diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr index da6013a4af33f..b7f5557bc7160 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-higher-ranker-supertraits-transitive.stderr @@ -10,7 +10,6 @@ note: required by a bound in `want_bar_for_any_ccx` --> $DIR/hrtb-higher-ranker-supertraits-transitive.rs:32:15 | LL | fn want_bar_for_any_ccx(b: &B) - | -------------------- required by a bound in this function LL | where B : for<'ccx> Bar<'ccx> | ^^^^^^^^^^^^^^^^^^^ required by this bound in `want_bar_for_any_ccx` help: consider further restricting type parameter `B` with trait `Bar` diff --git a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr index 4302570cdbdef..591d5fdd75283 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-62203-hrtb-ice.stderr @@ -23,8 +23,8 @@ LL | type O = T::Output; note: required by a bound in `T1::m` --> $DIR/issue-62203-hrtb-ice.rs:27:51 | +LL | trait T1: for<'r> Ty<'r> { LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 - | - required by a bound in this associated function LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` @@ -52,8 +52,8 @@ LL | T: FnMut(A) -> Unit3, note: required by a bound in `T1::m` --> $DIR/issue-62203-hrtb-ice.rs:27:12 | +LL | trait T1: for<'r> Ty<'r> { LL | fn m<'a, B: Ty<'a>, F>(&self, f: F) -> Unit1 - | - required by a bound in this associated function LL | where LL | F: for<'r> T0<'r, (>::V,), O = >::V>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `T1::m` diff --git a/tests/ui/higher-ranked/trait-bounds/issue-95230.stderr b/tests/ui/higher-ranked/trait-bounds/issue-95230.stderr index 9e85c689f69df..7f307378f23f1 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-95230.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-95230.stderr @@ -8,7 +8,6 @@ note: required by a bound in `Bar` --> $DIR/issue-95230.rs:7:13 | LL | pub struct Bar - | --- required by a bound in this struct LL | where LL | for<'a> &'a mut Self:; | ^^^^^^^^^^^^ required by this bound in `Bar` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr index 5ded3a5e76c9d..9d109df0a15a9 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-89118.stderr @@ -20,7 +20,6 @@ note: required by a bound in `StackContext` --> $DIR/issue-89118.rs:9:14 | LL | trait StackContext - | ------------ required by a bound in this trait LL | where LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` @@ -47,7 +46,6 @@ note: required by a bound in `EthernetWorker` --> $DIR/issue-89118.rs:28:14 | LL | struct EthernetWorker(C) - | -------------- required by a bound in this struct LL | where LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `EthernetWorker` @@ -74,7 +72,6 @@ note: required by a bound in `StackContext` --> $DIR/issue-89118.rs:9:14 | LL | trait StackContext - | ------------ required by a bound in this trait LL | where LL | Ctx<()>: for<'a> BufferUdpStateContext<&'a ()>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `StackContext` diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr index 2f417d57752d2..39121c99798bf 100644 --- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr +++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr @@ -9,6 +9,7 @@ LL | type Ty = Option; note: required by a bound in `compare_ty::Trait::Ty` --> $DIR/in-assoc-type-unconstrained.rs:5:31 | +LL | trait Trait { LL | type Ty: IntoIterator; | ^^^^^^^^^ required by this bound in `Trait::Ty` diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr index df89ed9f3b56d..83410e4a38d68 100644 --- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr +++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr @@ -7,6 +7,7 @@ LL | fn bar() -> () {} note: required by a bound in `Foo::bar::{anon_assoc#0}` --> $DIR/doesnt-satisfy.rs:2:22 | +LL | trait Foo { LL | fn bar() -> impl std::fmt::Display; | ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::bar::{anon_assoc#0}` diff --git a/tests/ui/impl-trait/in-trait/not-inferred-generic.stderr b/tests/ui/impl-trait/in-trait/not-inferred-generic.stderr index a9232ea9e63df..0c3a0fc91b017 100644 --- a/tests/ui/impl-trait/in-trait/not-inferred-generic.stderr +++ b/tests/ui/impl-trait/in-trait/not-inferred-generic.stderr @@ -9,6 +9,8 @@ LL | ().publish_typed(); note: required by a bound in `TypedClient::publish_typed::{anon_assoc#0}` --> $DIR/not-inferred-generic.rs:4:12 | +LL | trait TypedClient { +... LL | F: Clone; | ^^^^^ required by this bound in `TypedClient::publish_typed::{anon_assoc#0}` help: consider specifying a concrete type for the type parameter `F` diff --git a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr index af71e52b87d71..f108d1283ac15 100644 --- a/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr +++ b/tests/ui/impl-trait/in-trait/refine-resolution-errors.stderr @@ -16,6 +16,7 @@ LL | type Assoc = T; note: required by a bound in `Mirror::Assoc` --> $DIR/refine-resolution-errors.rs:7:5 | +LL | pub trait Mirror { LL | type Assoc; | ^^^^^^^^^^^ required by this bound in `Mirror::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr index c62e8dbde6feb..471a454a5f522 100644 --- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr +++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr @@ -21,6 +21,7 @@ LL | impl Foo for Bar { note: required by a bound in `Foo::foo::{anon_assoc#0}` --> $DIR/return-dont-satisfy-bounds.rs:2:30 | +LL | trait Foo { LL | fn foo(self) -> impl Foo; | ^^^^^^ required by this bound in `Foo::foo::{anon_assoc#0}` diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr index a83e0df911b09..75e3cd40369f9 100644 --- a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr +++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.stderr @@ -17,6 +17,7 @@ LL | type Other = Tait; note: required by a bound in `Foo::Item` --> $DIR/issue-99348-impl-compatibility.rs:17:20 | +LL | trait Foo { LL | type Item: Bar; | ^^^^^^^^^^^^ required by this bound in `Foo::Item` diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr index b5465e2f3ce08..23c9d61c76d3b 100644 --- a/tests/ui/implied-bounds/issue-100690.stderr +++ b/tests/ui/implied-bounds/issue-100690.stderr @@ -12,7 +12,6 @@ note: required by a bound in `real_dispatch` --> $DIR/issue-100690.rs:8:8 | LL | fn real_dispatch(f: F) -> Result<(), io::Error> - | ------------- required by a bound in this function LL | where LL | F: FnOnce(&mut UIView) -> Result<(), io::Error> + Send + 'static, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch` diff --git a/tests/ui/inference/issue-12028.stderr b/tests/ui/inference/issue-12028.stderr index 92cfd85d96f85..c7ec79389cc4c 100644 --- a/tests/ui/inference/issue-12028.stderr +++ b/tests/ui/inference/issue-12028.stderr @@ -12,7 +12,7 @@ note: required by a bound in `StreamHash::input_stream` LL | trait StreamHash: Hash { | ^^^^^^^^^^^^ required by this bound in `StreamHash::input_stream` LL | fn input_stream(&self, stream: &mut H::S); - | ------------ required by a bound in this associated function + | help: try using a fully qualified path to specify the expected types | LL - self.input_stream(&mut stream); diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr index 9ad0319440e9a..69552e8204575 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.stderr +++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr @@ -30,7 +30,6 @@ note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/filter-relevant-fn-bounds.rs:11:12 | LL | fn do_something_wrapper(self, _: F) - | -------------------- required by a bound in this associated function ... LL | F: for<'a> FnOnce(>::Type), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Wrapper::do_something_wrapper` diff --git a/tests/ui/methods/inherent-bound-in-probe.stderr b/tests/ui/methods/inherent-bound-in-probe.stderr index dacb4523234a5..71e8e39692267 100644 --- a/tests/ui/methods/inherent-bound-in-probe.stderr +++ b/tests/ui/methods/inherent-bound-in-probe.stderr @@ -33,7 +33,6 @@ note: required by a bound in `Helper` --> $DIR/inherent-bound-in-probe.rs:17:12 | LL | struct Helper<'a, T> - | ------ required by a bound in this struct LL | where LL | &'a T: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Helper` diff --git a/tests/ui/methods/issues/issue-61525.stderr b/tests/ui/methods/issues/issue-61525.stderr index 7ac3d3dc0cff0..13310c41f191d 100644 --- a/tests/ui/methods/issues/issue-61525.stderr +++ b/tests/ui/methods/issues/issue-61525.stderr @@ -10,6 +10,7 @@ LL | 1.query::("") note: required by an implicit `Sized` bound in `Example::query` --> $DIR/issue-61525.rs:2:14 | +LL | pub trait Example { LL | fn query(self, q: Q); | ^ required by the implicit `Sized` requirement on this type parameter in `Example::query` help: consider relaxing the implicit `Sized` restriction diff --git a/tests/ui/mismatched_types/issue-47706.stderr b/tests/ui/mismatched_types/issue-47706.stderr index 69d6ee5cbd5a0..12d553225900c 100644 --- a/tests/ui/mismatched_types/issue-47706.stderr +++ b/tests/ui/mismatched_types/issue-47706.stderr @@ -27,7 +27,6 @@ note: required by a bound in `foo` --> $DIR/issue-47706.rs:22:8 | LL | fn foo(f: F) - | --- required by a bound in this function LL | where LL | F: Fn(), | ^^^^ required by this bound in `foo` diff --git a/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr b/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr index bcb2c7dfae8e7..f13d27d35f2b3 100644 --- a/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr +++ b/tests/ui/never_type/regress/never-as-spec-default-associated-type.stderr @@ -8,6 +8,7 @@ LL | default type Out = !; note: required by a bound in `Trait::Out` --> $DIR/never-as-spec-default-associated-type.rs:9:15 | +LL | trait Trait { LL | type Out: Iterator; | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `Trait::Out` diff --git a/tests/ui/parallel-rustc/dyn-trait-ice-153366.stderr b/tests/ui/parallel-rustc/dyn-trait-ice-153366.stderr index a9ca104c00d36..2b3e9516b3731 100644 --- a/tests/ui/parallel-rustc/dyn-trait-ice-153366.stderr +++ b/tests/ui/parallel-rustc/dyn-trait-ice-153366.stderr @@ -34,7 +34,6 @@ note: required by a bound in `iso` --> $DIR/dyn-trait-ice-153366.rs:11:22 | LL | fn iso(a: Fn) -> Option<_> - | --- required by a bound in this function ... LL | dyn Fn(A) -> (): Sized, | ^^^^^ required by this bound in `iso` @@ -82,7 +81,6 @@ note: required by a bound in `iso` --> $DIR/dyn-trait-ice-153366.rs:11:22 | LL | fn iso(a: Fn) -> Option<_> - | --- required by a bound in this function ... LL | dyn Fn(A) -> (): Sized, | ^^^^^ required by this bound in `iso` diff --git a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr index 4e8cbdb319511..e3a58fcca7ee9 100644 --- a/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr +++ b/tests/ui/parallel-rustc/generic-const-exprs-deadlock-issue-120757.stderr @@ -67,6 +67,8 @@ LL | if !self.inbounds(index) { note: required by a bound in `TensorSize::inbounds` --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:15:39 | +LL | trait TensorSize: TensorDimension { +LL | fn size(&self) -> [usize; Self::DIM]; LL | fn inbounds(&self, index: [usize; Self::DIM]) -> bool { | ^^^^^^^^^ required by this bound in `TensorSize::inbounds` help: try adding a `where` bound @@ -92,6 +94,7 @@ LL | let size = self.size(); note: required by a bound in `TensorSize::size` --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:14:31 | +LL | trait TensorSize: TensorDimension { LL | fn size(&self) -> [usize; Self::DIM]; | ^^^^^^^^^ required by this bound in `TensorSize::size` help: try adding a `where` bound @@ -119,6 +122,7 @@ LL | self.reference.size() note: required by a bound in `TensorSize::size` --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:14:31 | +LL | trait TensorSize: TensorDimension { LL | fn size(&self) -> [usize; Self::DIM]; | ^^^^^^^^^ required by this bound in `TensorSize::size` help: try adding a `where` bound @@ -144,6 +148,8 @@ LL | self.reference.bget(index).map(ns_window) note: required by a bound in `Broadcastable::bget` --> $DIR/generic-const-exprs-deadlock-issue-120757.rs:22:35 | +LL | trait Broadcastable: TensorSize + Sized { +LL | type Element; LL | fn bget(&self, index: [usize; Self::DIM]) -> Option; | ^^^^^^^^^ required by this bound in `Broadcastable::bget` help: try adding a `where` bound diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr index 643e3d3b680e0..f20fc381d04dc 100644 --- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr +++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr @@ -12,6 +12,7 @@ LL | struct Something; note: required by a bound in `Main::main::{anon_assoc#0}` --> $DIR/issue-103052-2.rs:3:27 | +LL | trait Main { LL | fn main() -> impl std::process::Termination; | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::main::{anon_assoc#0}` diff --git a/tests/ui/specialization/default-associated-type-bound-1.stderr b/tests/ui/specialization/default-associated-type-bound-1.stderr index 70408145e8039..921a892fa7deb 100644 --- a/tests/ui/specialization/default-associated-type-bound-1.stderr +++ b/tests/ui/specialization/default-associated-type-bound-1.stderr @@ -9,6 +9,7 @@ help: the trait `Clone` is implemented for `String` note: required by a bound in `X::U` --> $DIR/default-associated-type-bound-1.rs:7:13 | +LL | trait X { LL | type U: Clone; | ^^^^^ required by this bound in `X::U` diff --git a/tests/ui/specialization/default-associated-type-bound-2.stderr b/tests/ui/specialization/default-associated-type-bound-2.stderr index 3d3fdbad26408..82fb7e4d9e4d4 100644 --- a/tests/ui/specialization/default-associated-type-bound-2.stderr +++ b/tests/ui/specialization/default-associated-type-bound-2.stderr @@ -8,6 +8,7 @@ LL | default type U = &'static B; note: required by a bound in `X::U` --> $DIR/default-associated-type-bound-2.rs:5:13 | +LL | trait X { LL | type U: PartialEq; | ^^^^^^^^^^^^ required by this bound in `X::U` help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement diff --git a/tests/ui/specialization/default-generic-associated-type-bound.stderr b/tests/ui/specialization/default-generic-associated-type-bound.stderr index 7c2bde84a3675..df5ccb00779ee 100644 --- a/tests/ui/specialization/default-generic-associated-type-bound.stderr +++ b/tests/ui/specialization/default-generic-associated-type-bound.stderr @@ -8,6 +8,7 @@ LL | default type U<'a> = &'a T; note: required by a bound in `X::U` --> $DIR/default-generic-associated-type-bound.rs:6:17 | +LL | trait X { LL | type U<'a>: PartialEq<&'a Self> where Self: 'a; | ^^^^^^^^^^^^^^^^^^^ required by this bound in `X::U` help: consider further restricting type parameter `T` with trait `PartialEq` diff --git a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr index 79117229300ae..bc1e57ff00b7c 100644 --- a/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr +++ b/tests/ui/specialization/fuzzed/fuzzing-ice-134905.stderr @@ -12,6 +12,7 @@ LL | trait Valid {} note: required by a bound in `Iterate::Ty` --> $DIR/fuzzing-ice-134905.rs:6:14 | +LL | trait Iterate<'a> { LL | type Ty: Valid; | ^^^^^ required by this bound in `Iterate::Ty` diff --git a/tests/ui/specialization/issue-33017.stderr b/tests/ui/specialization/issue-33017.stderr index 29a82a4d87519..89a4e9c6ed0b6 100644 --- a/tests/ui/specialization/issue-33017.stderr +++ b/tests/ui/specialization/issue-33017.stderr @@ -7,6 +7,7 @@ LL | default type Output = Self; note: required by a bound in `UncheckedCopy::Output` --> $DIR/issue-33017.rs:8:31 | +LL | trait UncheckedCopy: Sized { LL | type Output: From + Copy + Into; | ^^^^ required by this bound in `UncheckedCopy::Output` help: consider restricting type parameter `T` with trait `Copy` diff --git a/tests/ui/specialization/issue-38091.stderr b/tests/ui/specialization/issue-38091.stderr index 91ea3db70311f..68a5947e77067 100644 --- a/tests/ui/specialization/issue-38091.stderr +++ b/tests/ui/specialization/issue-38091.stderr @@ -12,6 +12,7 @@ LL | trait Valid {} note: required by a bound in `Iterate::Ty` --> $DIR/issue-38091.rs:4:14 | +LL | trait Iterate<'a> { LL | type Ty: Valid; | ^^^^^ required by this bound in `Iterate::Ty` diff --git a/tests/ui/specialization/issue-44861.stderr b/tests/ui/specialization/issue-44861.stderr index e480f65333fda..6e736589b6acb 100644 --- a/tests/ui/specialization/issue-44861.stderr +++ b/tests/ui/specialization/issue-44861.stderr @@ -7,6 +7,8 @@ LL | default type Data2 = (); note: required by a bound in `Smartass::Data2` --> $DIR/issue-44861.rs:12:17 | +LL | pub trait Smartass { +LL | type Data; LL | type Data2: CoerceUnsized<*const [u8]>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Smartass::Data2` diff --git a/tests/ui/specialization/issue-59435.stderr b/tests/ui/specialization/issue-59435.stderr index 60522e0f587b6..89f6a500bd436 100644 --- a/tests/ui/specialization/issue-59435.stderr +++ b/tests/ui/specialization/issue-59435.stderr @@ -7,6 +7,7 @@ LL | default type MyType = MyStruct; note: required by a bound in `MyTrait::MyType` --> $DIR/issue-59435.rs:7:18 | +LL | trait MyTrait { LL | type MyType: Default; | ^^^^^^^ required by this bound in `MyTrait::MyType` help: consider annotating `MyStruct` with `#[derive(Default)]` diff --git a/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr b/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr index 9308075ae89bb..27116d683d1d1 100644 --- a/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr +++ b/tests/ui/splat/splat-dyn-asref-tuple-fail.stderr @@ -17,7 +17,6 @@ note: required by a bound in `dyn_asref_splat` --> $DIR/splat-dyn-asref-tuple-fail.rs:18:8 | LL | fn dyn_asref_splat(#[rustc_splat] _t: &dyn AsRef) - | --------------- required by a bound in this function ... LL | T: std::marker::Tuple, | ^^^^^^^^^^^^^^^^^^ required by this bound in `dyn_asref_splat` diff --git a/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr index f0f9ef83345c7..0a625e0f25cda 100644 --- a/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr +++ b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr @@ -147,7 +147,7 @@ note: required by a bound in `Callable::CALL` LL | trait Callable { | ^^^ required by this bound in `Callable::CALL` LL | const CALL: fn(); - | ---- required by a bound in this associated constant + | error: aborting due to 9 previous errors diff --git a/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr b/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr index 2cd3fba871548..95546191040db 100644 --- a/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr +++ b/tests/ui/suggestions/correct-binder-for-arbitrary-bound-sugg.stderr @@ -8,7 +8,6 @@ note: required by a bound in `Foo` --> $DIR/correct-binder-for-arbitrary-bound-sugg.rs:3:23 | LL | trait Foo - | --- required by a bound in this trait LL | where LL | for<'a> &'a Self: Bar, | ^^^ required by this bound in `Foo` diff --git a/tests/ui/suggestions/fn-trait-notation.stderr b/tests/ui/suggestions/fn-trait-notation.stderr index ef7d5fe362820..dd22fee829f3d 100644 --- a/tests/ui/suggestions/fn-trait-notation.stderr +++ b/tests/ui/suggestions/fn-trait-notation.stderr @@ -65,7 +65,6 @@ note: required by a bound in `e0658` --> $DIR/fn-trait-notation.rs:4:8 | LL | fn e0658(f: F, g: G, h: H) -> i32 - | ----- required by a bound in this function LL | where LL | F: Fn, | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `e0658` diff --git a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr index e25b9ce38571d..5542c32bac173 100644 --- a/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr +++ b/tests/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr @@ -16,7 +16,6 @@ note: required by a bound in `foo` --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:11:20 | LL | fn foo(_: X) - | --- required by a bound in this function LL | where LL | for<'b> &'b X: Trait, | ^^^^^ required by this bound in `foo` diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr index c5e1958e030f2..2dec2d5f43527 100644 --- a/tests/ui/suggestions/issue-84973.stderr +++ b/tests/ui/suggestions/issue-84973.stderr @@ -13,7 +13,7 @@ LL | G: SomeTrait, | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new` LL | { LL | pub fn new(g: G) -> Self { - | --- required by a bound in this associated function + | help: consider borrowing here | LL | let o = Other::new(&f); diff --git a/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr index b459ad47e067a..4182e0eee795f 100644 --- a/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr +++ b/tests/ui/trait-bounds/suggest-maybe-sized-bound.stderr @@ -25,6 +25,7 @@ LL | type P = [u8]; note: required by a bound in `main::Trait::P` --> $DIR/suggest-maybe-sized-bound.rs:13:9 | +LL | trait Trait { LL | type P; | ^^^^^^^^^^ required by this bound in `Trait::P` help: consider relaxing the implicit `Sized` restriction diff --git a/tests/ui/trait-bounds/super-assoc-mismatch.stderr b/tests/ui/trait-bounds/super-assoc-mismatch.stderr index 11d764d111eed..876854415509c 100644 --- a/tests/ui/trait-bounds/super-assoc-mismatch.stderr +++ b/tests/ui/trait-bounds/super-assoc-mismatch.stderr @@ -46,6 +46,7 @@ LL | trait Sub: Super {} note: required by a bound in `BoundOnAssoc::Assoc` --> $DIR/super-assoc-mismatch.rs:18:17 | +LL | trait BoundOnAssoc { LL | type Assoc: Sub; | ^^^ required by this bound in `BoundOnAssoc::Assoc` @@ -97,7 +98,6 @@ note: required by a bound in `MultiAssoc` --> $DIR/super-assoc-mismatch.rs:46:23 | LL | trait MultiAssoc - | ---------- required by a bound in this trait LL | where LL | Self::Assoc1<()>: SubGeneric | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `MultiAssoc` diff --git a/tests/ui/traits/bad-method-typaram-kind.stderr b/tests/ui/traits/bad-method-typaram-kind.stderr index 3b3d6e5f832b6..f97f6c2bb8cb1 100644 --- a/tests/ui/traits/bad-method-typaram-kind.stderr +++ b/tests/ui/traits/bad-method-typaram-kind.stderr @@ -9,6 +9,7 @@ LL | 1.bar::(); note: required by a bound in `Bar::bar` --> $DIR/bad-method-typaram-kind.rs:6:14 | +LL | trait Bar { LL | fn bar(&self); | ^^^^ required by this bound in `Bar::bar` help: consider further restricting type parameter `T` with trait `Send` diff --git a/tests/ui/traits/const-traits/assoc-type.current.stderr b/tests/ui/traits/const-traits/assoc-type.current.stderr index f66e9e03b0754..64e2e58f71944 100644 --- a/tests/ui/traits/const-traits/assoc-type.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type.current.stderr @@ -7,6 +7,7 @@ LL | type Bar = NonConstAdd; note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:31:15 | +LL | const trait Foo { LL | type Bar: [const] Add; | ^^^^^^^^^^^ required by this bound in `Foo::Bar` help: make the `impl` of trait `Add` `const` diff --git a/tests/ui/traits/const-traits/assoc-type.next.stderr b/tests/ui/traits/const-traits/assoc-type.next.stderr index f66e9e03b0754..64e2e58f71944 100644 --- a/tests/ui/traits/const-traits/assoc-type.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type.next.stderr @@ -7,6 +7,7 @@ LL | type Bar = NonConstAdd; note: required by a bound in `Foo::Bar` --> $DIR/assoc-type.rs:31:15 | +LL | const trait Foo { LL | type Bar: [const] Add; | ^^^^^^^^^^^ required by this bound in `Foo::Bar` help: make the `impl` of trait `Add` `const` diff --git a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr index 52b62e7aaccc8..4b7231cb34eff 100644 --- a/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr +++ b/tests/ui/traits/const-traits/conditionally-const-invalid-places.stderr @@ -311,6 +311,7 @@ LL | type Type = (); note: required by a bound in `NonConstTrait::Type` --> $DIR/conditionally-const-invalid-places.rs:24:34 | +LL | trait NonConstTrait { LL | type Type: [const] Trait; | ^^^^^^^^^^^^^ required by this bound in `NonConstTrait::Type` diff --git a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr index 375cb58580490..04034827338ff 100644 --- a/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr +++ b/tests/ui/traits/const-traits/item-bound-entailment-fails.stderr @@ -7,6 +7,7 @@ LL | type Assoc = N note: required by a bound in `Foo::Assoc` --> $DIR/item-bound-entailment-fails.rs:5:20 | +LL | const trait Foo { LL | type Assoc: [const] Bar | ^^^^^^^^^^^ required by this bound in `Foo::Assoc` help: make the `impl` of trait `Bar` `const` @@ -28,6 +29,7 @@ LL | const impl Bar for C where T: [const] Bar {} note: required by a bound in `Foo::Assoc` --> $DIR/item-bound-entailment-fails.rs:5:20 | +LL | const trait Foo { LL | type Assoc: [const] Bar | ^^^^^^^^^^^ required by this bound in `Foo::Assoc` diff --git a/tests/ui/traits/const-traits/trait-where-clause-const.stderr b/tests/ui/traits/const-traits/trait-where-clause-const.stderr index 20dd395b820bf..9aedccc96f5cb 100644 --- a/tests/ui/traits/const-traits/trait-where-clause-const.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause-const.stderr @@ -7,6 +7,8 @@ LL | T::b(); note: required by a bound in `Foo::b` --> $DIR/trait-where-clause-const.rs:13:24 | +LL | const trait Foo { +LL | fn a(); LL | fn b() where Self: [const] Bar; | ^^^^^^^^^^^ required by this bound in `Foo::b` @@ -19,6 +21,8 @@ LL | T::c::(); note: required by a bound in `Foo::c` --> $DIR/trait-where-clause-const.rs:14:13 | +LL | const trait Foo { +... LL | fn c(); | ^^^^^^^^^^^ required by this bound in `Foo::c` diff --git a/tests/ui/traits/const-traits/trait-where-clause.stderr b/tests/ui/traits/const-traits/trait-where-clause.stderr index 57d87f74565e2..38b873abeda48 100644 --- a/tests/ui/traits/const-traits/trait-where-clause.stderr +++ b/tests/ui/traits/const-traits/trait-where-clause.stderr @@ -31,6 +31,8 @@ LL | T::b(); note: required by a bound in `Foo::b` --> $DIR/trait-where-clause.rs:7:24 | +LL | trait Foo { +LL | fn a(); LL | fn b() where Self: [const] Bar; | ^^^^^^^^^^^ required by this bound in `Foo::b` help: consider further restricting type parameter `T` with trait `Bar` @@ -47,6 +49,8 @@ LL | T::c::(); note: required by a bound in `Foo::c` --> $DIR/trait-where-clause.rs:9:13 | +LL | trait Foo { +... LL | fn c(); | ^^^^^^^^^^^ required by this bound in `Foo::c` help: consider further restricting type parameter `T` with trait `Bar` diff --git a/tests/ui/traits/cross-fn-cache-hole.stderr b/tests/ui/traits/cross-fn-cache-hole.stderr index ca43119dde7f6..ed66f4c8ffb9d 100644 --- a/tests/ui/traits/cross-fn-cache-hole.stderr +++ b/tests/ui/traits/cross-fn-cache-hole.stderr @@ -29,7 +29,6 @@ note: required by a bound in `require` --> $DIR/cross-fn-cache-hole.rs:25:14 | LL | fn require() - | ------- required by a bound in this function LL | where A: Bar | ^^^^^^ required by this bound in `require` diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 9665d5badf599..760a911f46161 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -83,6 +83,7 @@ LL | struct SalsaStorage { note: required by a bound in `Database::Storage` --> $DIR/cycle-cache-err-60010.rs:7:5 | +LL | trait Database { LL | type Storage; | ^^^^^^^^^^^^^ required by this bound in `Database::Storage` help: consider relaxing the implicit `Sized` restriction diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr index ab62ab81b213b..9ddcec5a409d5 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-traits.stderr @@ -29,6 +29,8 @@ LL | struct NonLeakS; note: required by a bound in `Test1::Leak2` --> $DIR/maybe-bounds-in-traits.rs:58:9 | +LL | trait Test1 { +LL | type Leak1 = LeakS; LL | type Leak2 = NonLeakS; | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Test1::Leak2` diff --git a/tests/ui/traits/explicit-reference-cast-hrtb.stderr b/tests/ui/traits/explicit-reference-cast-hrtb.stderr index 4921a87900051..1f3f2eeae022c 100644 --- a/tests/ui/traits/explicit-reference-cast-hrtb.stderr +++ b/tests/ui/traits/explicit-reference-cast-hrtb.stderr @@ -13,7 +13,6 @@ note: required by a bound in `f` --> $DIR/explicit-reference-cast-hrtb.rs:7:18 | LL | fn f() - | - required by a bound in this function LL | where LL | for<'a> Foo: From<&'a String>, | ^^^^^^^^^^^^^^^^ required by this bound in `f` diff --git a/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr b/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr index 1e4cb7f1cd18b..75ec60c9ec52e 100644 --- a/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr +++ b/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr @@ -16,7 +16,6 @@ note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/explicit-reference-cast-unrelated-leaf.rs:10:20 | LL | fn do_something_wrapper(self, _: F) - | -------------------- required by a bound in this associated function LL | where LL | for<'a> F: Output<'a>, | ^^^^^^^^^^ required by this bound in `Wrapper::do_something_wrapper` @@ -37,7 +36,6 @@ note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/explicit-reference-cast-unrelated-leaf.rs:11:20 | LL | fn do_something_wrapper(self, _: F) - | -------------------- required by a bound in this associated function ... LL | for<'a> O: From<>::Type>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Wrapper::do_something_wrapper` diff --git a/tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr b/tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr index 2fc1523a19373..0288de2ef7be6 100644 --- a/tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr +++ b/tests/ui/traits/fn-pointer/suggest-wrap-parens-method.stderr @@ -7,6 +7,7 @@ LL | main.do_stuff(); note: required by a bound in `Bar::do_stuff` --> $DIR/suggest-wrap-parens-method.rs:8:36 | +LL | trait Bar { LL | fn do_stuff(&self) where Self: Foo {} | ^^^ required by this bound in `Bar::do_stuff` help: the trait `Foo` is implemented for fn pointer `fn()`, try casting using `as` diff --git a/tests/ui/traits/inductive-overflow/two-traits.stderr b/tests/ui/traits/inductive-overflow/two-traits.stderr index 1816e029f1844..7c80726582336 100644 --- a/tests/ui/traits/inductive-overflow/two-traits.stderr +++ b/tests/ui/traits/inductive-overflow/two-traits.stderr @@ -7,6 +7,7 @@ LL | type X = Self; note: required by a bound in `Magic::X` --> $DIR/two-traits.rs:8:13 | +LL | pub trait Magic { LL | type X: Trait; | ^^^^^ required by this bound in `Magic::X` help: consider further restricting type parameter `T` with trait `Sync` diff --git a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr index 12984c7936c9a..99135c790640a 100644 --- a/tests/ui/traits/multidispatch-convert-ambig-dest.stderr +++ b/tests/ui/traits/multidispatch-convert-ambig-dest.stderr @@ -18,7 +18,6 @@ note: required by a bound in `test` --> $DIR/multidispatch-convert-ambig-dest.rs:21:11 | LL | fn test(_: T, _: U) - | ---- required by a bound in this function LL | where T : Convert | ^^^^^^^^^^ required by this bound in `test` help: consider specifying the generic arguments diff --git a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr index 546a069bb93ab..3f2b788d9c071 100644 --- a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr +++ b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.current.stderr @@ -20,7 +20,6 @@ note: required by a bound in `f` --> $DIR/dont-suppress-independent-projection-error.rs:22:8 | LL | fn f(_: T) - | - required by a bound in this function LL | where LL | T: Sub, | ^^^ required by this bound in `f` @@ -42,7 +41,6 @@ note: required by a bound in `f` --> $DIR/dont-suppress-independent-projection-error.rs:23:14 | LL | fn f(_: T) - | - required by a bound in this function ... LL | T: Super, | ^^^^^^^^^^^ required by this bound in `f` diff --git a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr index 546a069bb93ab..3f2b788d9c071 100644 --- a/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr +++ b/tests/ui/traits/next-solver/diagnostics/dont-suppress-independent-projection-error.next.stderr @@ -20,7 +20,6 @@ note: required by a bound in `f` --> $DIR/dont-suppress-independent-projection-error.rs:22:8 | LL | fn f(_: T) - | - required by a bound in this function LL | where LL | T: Sub, | ^^^ required by this bound in `f` @@ -42,7 +41,6 @@ note: required by a bound in `f` --> $DIR/dont-suppress-independent-projection-error.rs:23:14 | LL | fn f(_: T) - | - required by a bound in this function ... LL | T: Super, | ^^^^^^^^^^^ required by this bound in `f` diff --git a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr index 7f160b1b7e951..59788287ddf7c 100644 --- a/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr +++ b/tests/ui/traits/next-solver/diagnostics/iterator-item-suggest-no-ice.stderr @@ -34,8 +34,8 @@ LL | self.bar(collection); note: required by a bound in `FooMut::bar` --> $DIR/iterator-item-suggest-no-ice.rs:7:24 | +LL | trait FooMut { LL | fn bar(&self, _: I) - | --- required by a bound in this associated function LL | where LL | for<'b> &'b I: Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `FooMut::bar` diff --git a/tests/ui/traits/next-solver/diagnostics/rpitit-fulfillment-error.stderr b/tests/ui/traits/next-solver/diagnostics/rpitit-fulfillment-error.stderr index 49bfbf237b4e2..294938f28c013 100644 --- a/tests/ui/traits/next-solver/diagnostics/rpitit-fulfillment-error.stderr +++ b/tests/ui/traits/next-solver/diagnostics/rpitit-fulfillment-error.stderr @@ -10,6 +10,7 @@ LL | self.build(further_commands) note: required by a bound in `Crash::build` --> $DIR/rpitit-fulfillment-error.rs:5:44 | +LL | trait Crash { LL | fn build<'a>(&mut self, commands: impl Iterator + 'a) -> impl Iterator + 'a { | ^^^^^^^^ required by this bound in `Crash::build` help: consider further restricting `Self` diff --git a/tests/ui/traits/next-solver/more-object-bound.stderr b/tests/ui/traits/next-solver/more-object-bound.stderr index ccbf19ae4d96c..41c2c615b8647 100644 --- a/tests/ui/traits/next-solver/more-object-bound.stderr +++ b/tests/ui/traits/next-solver/more-object-bound.stderr @@ -17,7 +17,6 @@ note: required by a bound in `foo` --> $DIR/more-object-bound.rs:18:8 | LL | fn foo(x: T::A) -> B - | --- required by a bound in this function LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr index f5ff41fc17aae..3ff67da114462 100644 --- a/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr +++ b/tests/ui/traits/next-solver/normalize/normalize-param-env-2.stderr @@ -35,8 +35,9 @@ LL | impl A for () { note: required by a bound in `A::f` --> $DIR/normalize-param-env-2.rs:14:22 | +LL | trait A { +... LL | fn f() - | - required by a bound in this associated function LL | where LL | Self::Assoc: A, | ^^^^ required by this bound in `A::f` diff --git a/tests/ui/traits/next-solver/opaques/implied-bounds-opaque-hidden-in-closure-sig.current.stderr b/tests/ui/traits/next-solver/opaques/implied-bounds-opaque-hidden-in-closure-sig.current.stderr index 955d5b4970d34..1189f62601759 100644 --- a/tests/ui/traits/next-solver/opaques/implied-bounds-opaque-hidden-in-closure-sig.current.stderr +++ b/tests/ui/traits/next-solver/opaques/implied-bounds-opaque-hidden-in-closure-sig.current.stderr @@ -15,7 +15,6 @@ note: required by a bound in `RequiresWf` --> $DIR/implied-bounds-opaque-hidden-in-closure-sig.rs:31:16 | LL | struct RequiresWf(F) - | ---------- required by a bound in this tuple struct ... LL | F::Output: Trait, | ^^^^^ required by this bound in `RequiresWf` @@ -35,7 +34,6 @@ note: required by a bound in `RequiresWf` --> $DIR/implied-bounds-opaque-hidden-in-closure-sig.rs:31:16 | LL | struct RequiresWf(F) - | ---------- required by a bound in this struct ... LL | F::Output: Trait, | ^^^^^ required by this bound in `RequiresWf` @@ -55,7 +53,6 @@ note: required by a bound in `RequiresWf` --> $DIR/implied-bounds-opaque-hidden-in-closure-sig.rs:31:16 | LL | struct RequiresWf(F) - | ---------- required by a bound in this struct ... LL | F::Output: Trait, | ^^^^^ required by this bound in `RequiresWf` @@ -75,7 +72,6 @@ note: required by a bound in `RequiresWf` --> $DIR/implied-bounds-opaque-hidden-in-closure-sig.rs:31:16 | LL | struct RequiresWf(F) - | ---------- required by a bound in this struct ... LL | F::Output: Trait, | ^^^^^ required by this bound in `RequiresWf` diff --git a/tests/ui/traits/next-solver/outlives-goal-error-due-to-normalization-failure-no-ice.stderr b/tests/ui/traits/next-solver/outlives-goal-error-due-to-normalization-failure-no-ice.stderr index 80f1a9328d5e0..e711e1eb00a88 100644 --- a/tests/ui/traits/next-solver/outlives-goal-error-due-to-normalization-failure-no-ice.stderr +++ b/tests/ui/traits/next-solver/outlives-goal-error-due-to-normalization-failure-no-ice.stderr @@ -13,7 +13,6 @@ note: required by a bound in `Z` --> $DIR/outlives-goal-error-due-to-normalization-failure-no-ice.rs:7:8 | LL | trait Z<'a, T: ?Sized> - | - required by a bound in this trait LL | where LL | T: Z<'a, ()>, | ^^^^^^^^^ required by this bound in `Z` diff --git a/tests/ui/traits/next-solver/overflow/dont-drop-obligations-on-overflow-2.stderr b/tests/ui/traits/next-solver/overflow/dont-drop-obligations-on-overflow-2.stderr index c8d3b877657f3..684ad98bc3f38 100644 --- a/tests/ui/traits/next-solver/overflow/dont-drop-obligations-on-overflow-2.stderr +++ b/tests/ui/traits/next-solver/overflow/dont-drop-obligations-on-overflow-2.stderr @@ -9,7 +9,6 @@ note: required by a bound in `prove` --> $DIR/dont-drop-obligations-on-overflow-2.rs:18:23 | LL | fn prove() - | ----- required by a bound in this function LL | where LL | for<'a> Tait<'a>: Sized, | ^^^^^ required by this bound in `prove` diff --git a/tests/ui/traits/next-solver/transmute-from-unconstrained.stderr b/tests/ui/traits/next-solver/transmute-from-unconstrained.stderr index a3a1cee105d59..e6fc0e297a512 100644 --- a/tests/ui/traits/next-solver/transmute-from-unconstrained.stderr +++ b/tests/ui/traits/next-solver/transmute-from-unconstrained.stderr @@ -9,7 +9,6 @@ note: required by a bound in `assert_transmutable` --> $DIR/transmute-from-unconstrained.rs:13:9 | LL | fn assert_transmutable() - | ------------------- required by a bound in this function LL | where LL | (): std::mem::TransmuteFrom, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `assert_transmutable` diff --git a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr index 0b3aa5c904f9c..7e4b5cf68aedc 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-sized-cond.stderr @@ -9,7 +9,6 @@ note: required by a bound in `foo` --> $DIR/bad-sized-cond.rs:5:15 | LL | pub fn foo() - | --- required by a bound in this function LL | where LL | for V: Sized, | ^^^^^ required by this bound in `foo` @@ -26,7 +25,6 @@ note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:11:15 | LL | pub fn bar() - | --- required by a bound in this function LL | where LL | for V: IntoIterator, | ^^^^^^^^^^^^ required by this bound in `bar` @@ -43,7 +41,6 @@ note: required by a bound in `bar` --> $DIR/bad-sized-cond.rs:11:15 | LL | pub fn bar() - | --- required by a bound in this function LL | where LL | for V: IntoIterator, | ^^^^^^^^^^^^ required by this bound in `bar` diff --git a/tests/ui/traits/non_lifetime_binders/fail.stderr b/tests/ui/traits/non_lifetime_binders/fail.stderr index 38a0eabddd3bb..3cc6d79717268 100644 --- a/tests/ui/traits/non_lifetime_binders/fail.stderr +++ b/tests/ui/traits/non_lifetime_binders/fail.stderr @@ -13,7 +13,6 @@ note: required by a bound in `fail` --> $DIR/fail.rs:9:15 | LL | fn fail() - | ---- required by a bound in this function LL | where LL | for T: Trait, | ^^^^^ required by this bound in `fail` @@ -29,7 +28,6 @@ note: required by a bound in `auto_trait` --> $DIR/fail.rs:14:15 | LL | fn auto_trait() - | ---------- required by a bound in this function LL | where LL | for T: Send, | ^^^^ required by this bound in `auto_trait` diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr index 19921e3e06eed..84cf075f34b45 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq-next-solver.stderr @@ -9,7 +9,6 @@ note: required by a bound in `auto_trait` --> $DIR/foreach-partial-eq-next-solver.rs:17:27 | LL | fn auto_trait() - | ---------- required by a bound in this function LL | where LL | for T: PartialEq + PartialOrd, | ^^^^^^^^^^ required by this bound in `auto_trait` diff --git a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr index b621f5c612dee..436ff8f0b3820 100644 --- a/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr +++ b/tests/ui/traits/non_lifetime_binders/foreach-partial-eq.stderr @@ -9,7 +9,6 @@ note: required by a bound in `auto_trait` --> $DIR/foreach-partial-eq.rs:5:27 | LL | fn auto_trait() - | ---------- required by a bound in this function LL | where LL | for T: PartialEq + PartialOrd, | ^^^^^^^^^^ required by this bound in `auto_trait` diff --git a/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr index a634c86afa534..f1bd591086722 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error-host-effect.stderr @@ -34,7 +34,6 @@ note: required by a bound in `foo` --> $DIR/universe-error-host-effect.rs:19:15 | LL | fn foo() - | --- required by a bound in this function LL | where LL | for T: const Other, | ^^^^^^^^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr index 1ef4cc1034bc3..388fb181fe81a 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `foo` --> $DIR/universe-error1.rs:17:15 | LL | fn foo() - | --- required by a bound in this function LL | where LL | for T: Other {} | ^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr b/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr index 1ef4cc1034bc3..388fb181fe81a 100644 --- a/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr +++ b/tests/ui/traits/non_lifetime_binders/universe-error1.next.stderr @@ -8,7 +8,6 @@ note: required by a bound in `foo` --> $DIR/universe-error1.rs:17:15 | LL | fn foo() - | --- required by a bound in this function LL | where LL | for T: Other {} | ^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr index e8742e7f09902..3d249c3949f28 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.current.stderr @@ -25,6 +25,7 @@ LL | type Assoc = T; note: required by a bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization-2.rs:12:5 | +LL | pub trait Every { LL | type Assoc; | ^^^^^^^^^^^ required by this bound in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr index e8742e7f09902..3d249c3949f28 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization-2.next.stderr @@ -25,6 +25,7 @@ LL | type Assoc = T; note: required by a bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization-2.rs:12:5 | +LL | pub trait Every { LL | type Assoc; | ^^^^^^^^^^^ required by this bound in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr index 6e908df0aba2d..598430b62d001 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization.current.stderr @@ -25,6 +25,7 @@ LL | type Assoc = T; note: required by a bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization.rs:11:5 | +LL | pub trait Every { LL | type Assoc; | ^^^^^^^^^^^ required by this bound in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr b/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr index 6e908df0aba2d..598430b62d001 100644 --- a/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr +++ b/tests/ui/traits/normalize/unconstrained-projection-normalization.next.stderr @@ -25,6 +25,7 @@ LL | type Assoc = T; note: required by a bound in `Every::Assoc` --> $DIR/unconstrained-projection-normalization.rs:11:5 | +LL | pub trait Every { LL | type Assoc; | ^^^^^^^^^^^ required by this bound in `Every::Assoc` help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/object/enforce-supertrait-projection.stderr b/tests/ui/traits/object/enforce-supertrait-projection.stderr index 198a185dd4840..8c8a46ff82af6 100644 --- a/tests/ui/traits/object/enforce-supertrait-projection.stderr +++ b/tests/ui/traits/object/enforce-supertrait-projection.stderr @@ -16,7 +16,6 @@ note: required by a bound in `foo` --> $DIR/enforce-supertrait-projection.rs:15:8 | LL | fn foo(x: T::A) -> B - | --- required by a bound in this function LL | where LL | T: Trait, | ^^^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/projection-no-progress-cycle-issue-157516.stderr b/tests/ui/traits/projection-no-progress-cycle-issue-157516.stderr index a6960fc18493f..7a274fc12b9f3 100644 --- a/tests/ui/traits/projection-no-progress-cycle-issue-157516.stderr +++ b/tests/ui/traits/projection-no-progress-cycle-issue-157516.stderr @@ -9,6 +9,7 @@ LL | T::Object::OPS note: required by a bound in `Driver::Object` --> $DIR/projection-no-progress-cycle-issue-157516.rs:12:22 | +LL | trait Driver { LL | type Object: Alloc; | ^^^^^ required by this bound in `Driver::Object` help: use the fully qualified path to an implementation diff --git a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr index 8024ad28d5ae6..6808cef15a173 100644 --- a/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr +++ b/tests/ui/traits/suggest-dereferences/dont-suggest-unsize-deref.stderr @@ -12,7 +12,6 @@ note: required by a bound in `use_iterator` --> $DIR/dont-suggest-unsize-deref.rs:3:8 | LL | fn use_iterator(itr: I) - | ------------ required by a bound in this function LL | where LL | I: IntoIterator, | ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `use_iterator` diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr index bf8d3c40cf653..ba636ad148f11 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr @@ -13,8 +13,8 @@ LL | struct Tail([()]); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` @@ -38,8 +38,8 @@ LL | struct Tail([()]); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr index fcac02bc0a049..6c4ace807442f 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr @@ -19,8 +19,8 @@ LL | struct Tail([()]); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` diff --git a/tests/ui/traits/trivial-unsized-projection.bad.stderr b/tests/ui/traits/trivial-unsized-projection.bad.stderr index 4aea63329b360..bab0a72587320 100644 --- a/tests/ui/traits/trivial-unsized-projection.bad.stderr +++ b/tests/ui/traits/trivial-unsized-projection.bad.stderr @@ -8,8 +8,8 @@ LL | const FOO: <[()] as Bad>::Assert = todo!(); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` @@ -28,8 +28,8 @@ LL | const FOO: <[()] as Bad>::Assert = todo!(); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` diff --git a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr index 09b51b30460d0..a055181542d4d 100644 --- a/tests/ui/traits/trivial-unsized-projection.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection.bad_new.stderr @@ -14,8 +14,8 @@ LL | const FOO: <[()] as Bad>::Assert = todo!(); note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection.rs:14:15 | +LL | trait Bad { LL | type Assert - | ------ required by a bound in this associated type LL | where LL | Self: Sized; | ^^^^^ required by this bound in `Bad::Assert` diff --git a/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr b/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr index d2d679243ee7c..ab4bafac01fad 100644 --- a/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr +++ b/tests/ui/traits/unsize-goal-escaping-bounds.current.stderr @@ -9,7 +9,6 @@ note: required by a bound in `foo` --> $DIR/unsize-goal-escaping-bounds.rs:15:17 | LL | fn foo() - | --- required by a bound in this function LL | where LL | for<'a> (): Unsize, | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` diff --git a/tests/ui/traits/vtable-res-trait-param.stderr b/tests/ui/traits/vtable-res-trait-param.stderr index fff602b8d2bed..0868e57a479fe 100644 --- a/tests/ui/traits/vtable-res-trait-param.stderr +++ b/tests/ui/traits/vtable-res-trait-param.stderr @@ -14,6 +14,7 @@ LL | trait TraitA { note: required by a bound in `TraitB::gimme_an_a` --> $DIR/vtable-res-trait-param.rs:6:21 | +LL | trait TraitB { LL | fn gimme_an_a(&self, a: A) -> isize; | ^^^^^^ required by this bound in `TraitB::gimme_an_a` diff --git a/tests/ui/transmutability/alignment/align-fail.stderr b/tests/ui/transmutability/alignment/align-fail.stderr index 164c57a362442..be2f2058db18d 100644 --- a/tests/ui/transmutability/alignment/align-fail.stderr +++ b/tests/ui/transmutability/alignment/align-fail.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/align-fail.rs:9:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/huge-len.rs:8:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom, | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/huge-len.rs:8:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom, | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr index e9420cd393e9a..a3e9d00eac93e 100644 --- a/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr +++ b/tests/ui/transmutability/arrays/should_require_well_defined_layout.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_require_well_defined_layout.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/assoc-bound.rs:9:18 | +LL | trait B { LL | type AssocB: std::mem::TransmuteFrom<()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB` help: consider further restricting the associated type @@ -24,6 +25,7 @@ LL | type AssocB = <&'static i32 as A>::AssocA; note: required by a bound in `B::AssocB` --> $DIR/assoc-bound.rs:9:18 | +LL | trait B { LL | type AssocB: std::mem::TransmuteFrom<()>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `B::AssocB` diff --git a/tests/ui/transmutability/char.stderr b/tests/ui/transmutability/char.stderr index b15d4c83e29b3..19f76878d4049 100644 --- a/tests/ui/transmutability/char.stderr +++ b/tests/ui/transmutability/char.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/char.rs:7:10 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_transmutable` --> $DIR/char.rs:7:10 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -38,7 +36,6 @@ note: required by a bound in `is_transmutable` --> $DIR/char.rs:7:10 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr index 5c59fb9e175ea..b8f0245486bf3 100644 --- a/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr +++ b/tests/ui/transmutability/dont-assume-err-is-yes-issue-126377.stderr @@ -14,7 +14,6 @@ note: required by a bound in `is_transmutable` --> $DIR/dont-assume-err-is-yes-issue-126377.rs:8:9 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | (): TransmuteFrom<(), { Assume::SAFETY }>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr index 7e5d0a6d41224..3906777a6a164 100644 --- a/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr +++ b/tests/ui/transmutability/enums/repr/primitive_reprs_should_have_correct_length.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/primitive_reprs_should_have_correct_length.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_pad_variants.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_respect_endianness.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/unknown_dst_field.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -35,7 +34,6 @@ note: required by a bound in `is_transmutable` --> $DIR/unknown_dst_field.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr index e6bb45a34a1df..c8ea3503c3de2 100644 --- a/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr +++ b/tests/ui/transmutability/malformed-program-gracefulness/unknown_src_field.stderr @@ -20,7 +20,6 @@ note: required by a bound in `is_transmutable` --> $DIR/unknown_src_field.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -35,7 +34,6 @@ note: required by a bound in `is_transmutable` --> $DIR/unknown_src_field.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/maybeuninit.stderr b/tests/ui/transmutability/maybeuninit.stderr index 897c2df10a8f5..d60f37cbee753 100644 --- a/tests/ui/transmutability/maybeuninit.stderr +++ b/tests/ui/transmutability/maybeuninit.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/maybeuninit.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/primitives/bool-mut.stderr b/tests/ui/transmutability/primitives/bool-mut.stderr index fcf60bc979c2d..da84d8af6af43 100644 --- a/tests/ui/transmutability/primitives/bool-mut.stderr +++ b/tests/ui/transmutability/primitives/bool-mut.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/bool-mut.rs:9:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/primitives/bool.current.stderr b/tests/ui/transmutability/primitives/bool.current.stderr index 2945cdaad4062..cdf6e834232cb 100644 --- a/tests/ui/transmutability/primitives/bool.current.stderr +++ b/tests/ui/transmutability/primitives/bool.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/bool.rs:11:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/primitives/bool.next.stderr b/tests/ui/transmutability/primitives/bool.next.stderr index 2945cdaad4062..cdf6e834232cb 100644 --- a/tests/ui/transmutability/primitives/bool.next.stderr +++ b/tests/ui/transmutability/primitives/bool.next.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/bool.rs:11:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/primitives/numbers.current.stderr b/tests/ui/transmutability/primitives/numbers.current.stderr index efb2ce8c77207..4d304b2981f2e 100644 --- a/tests/ui/transmutability/primitives/numbers.current.stderr +++ b/tests/ui/transmutability/primitives/numbers.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -38,7 +36,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -53,7 +50,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -68,7 +64,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -83,7 +78,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -98,7 +92,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -113,7 +106,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -128,7 +120,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -143,7 +134,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -158,7 +148,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -173,7 +162,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -188,7 +176,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -203,7 +190,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -218,7 +204,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -233,7 +218,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -248,7 +232,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -263,7 +246,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -278,7 +260,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -293,7 +274,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -308,7 +288,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -323,7 +302,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -338,7 +316,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -353,7 +330,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -368,7 +344,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -383,7 +358,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -398,7 +372,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -413,7 +386,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -428,7 +400,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -443,7 +414,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -458,7 +428,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -473,7 +442,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -488,7 +456,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -503,7 +470,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -518,7 +484,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -533,7 +498,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -548,7 +512,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -563,7 +526,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -578,7 +540,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -593,7 +554,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -608,7 +568,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -623,7 +582,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -638,7 +596,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -653,7 +610,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -668,7 +624,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -683,7 +638,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -698,7 +652,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -713,7 +666,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -728,7 +680,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -743,7 +694,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -758,7 +708,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -773,7 +722,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -788,7 +736,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -803,7 +750,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -818,7 +764,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -833,7 +778,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -848,7 +792,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/primitives/numbers.next.stderr b/tests/ui/transmutability/primitives/numbers.next.stderr index efb2ce8c77207..4d304b2981f2e 100644 --- a/tests/ui/transmutability/primitives/numbers.next.stderr +++ b/tests/ui/transmutability/primitives/numbers.next.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -38,7 +36,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -53,7 +50,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -68,7 +64,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -83,7 +78,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -98,7 +92,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -113,7 +106,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -128,7 +120,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -143,7 +134,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -158,7 +148,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -173,7 +162,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -188,7 +176,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -203,7 +190,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -218,7 +204,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -233,7 +218,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -248,7 +232,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -263,7 +246,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -278,7 +260,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -293,7 +274,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -308,7 +288,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -323,7 +302,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -338,7 +316,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -353,7 +330,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -368,7 +344,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -383,7 +358,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -398,7 +372,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -413,7 +386,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -428,7 +400,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -443,7 +414,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -458,7 +428,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -473,7 +442,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -488,7 +456,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -503,7 +470,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -518,7 +484,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -533,7 +498,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -548,7 +512,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -563,7 +526,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -578,7 +540,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -593,7 +554,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -608,7 +568,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -623,7 +582,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -638,7 +596,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -653,7 +610,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -668,7 +624,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -683,7 +638,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -698,7 +652,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -713,7 +666,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -728,7 +680,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -743,7 +694,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -758,7 +708,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -773,7 +722,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -788,7 +736,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -803,7 +750,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -818,7 +764,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -833,7 +778,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -848,7 +792,6 @@ note: required by a bound in `is_transmutable` --> $DIR/numbers.rs:14:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/primitives/unit.current.stderr b/tests/ui/transmutability/primitives/unit.current.stderr index 4bfb229832b3f..b18ec1c8d66e8 100644 --- a/tests/ui/transmutability/primitives/unit.current.stderr +++ b/tests/ui/transmutability/primitives/unit.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/unit.rs:16:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/unit.rs:16:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/recursive-wrapper-types-bit-compatible-mut.rs:9:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/recursive-wrapper-types-bit-incompatible.rs:9:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/reject_extension.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom< | ______________^ diff --git a/tests/ui/transmutability/references/unit-to-u8.stderr b/tests/ui/transmutability/references/unit-to-u8.stderr index 35d1179f451b1..f9fd155320c9f 100644 --- a/tests/ui/transmutability/references/unit-to-u8.stderr +++ b/tests/ui/transmutability/references/unit-to-u8.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/unit-to-u8.rs:9:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/unsafecell.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` @@ -38,7 +36,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` @@ -53,7 +50,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/unsafecell.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/region-infer.stderr b/tests/ui/transmutability/region-infer.stderr index 09ecf484bc893..026f8a97e49f0 100644 --- a/tests/ui/transmutability/region-infer.stderr +++ b/tests/ui/transmutability/region-infer.stderr @@ -8,7 +8,6 @@ note: required by a bound in `test` --> $DIR/region-infer.rs:10:12 | LL | fn test<'a>() - | ---- required by a bound in this function LL | where LL | W<'a>: TransmuteFrom< | ____________^ diff --git a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr index 6445b1e146ede..ccf296cda5f41 100644 --- a/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_dst_has_safety_invariant.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/should_reject_if_dst_has_safety_invariant.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom // safety is NOT assumed | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr index 38ef829f06438..7ee1b06b115b2 100644 --- a/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr +++ b/tests/ui/transmutability/safety/should_reject_if_ref_src_has_safety_invariant.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/should_reject_if_ref_src_has_safety_invariant.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom // safety is NOT assumed | ^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/uninhabited.stderr b/tests/ui/transmutability/uninhabited.stderr index ac4b342ca990c..5f66d85446d5e 100644 --- a/tests/ui/transmutability/uninhabited.stderr +++ b/tests/ui/transmutability/uninhabited.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/uninhabited.rs:10:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/uninhabited.rs:10:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/uninhabited.rs:10:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/uninhabited.rs:10:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/uninhabited.rs:10:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/extension.rs:6:16 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/unions/should_pad_variants.stderr b/tests/ui/transmutability/unions/should_pad_variants.stderr index bb26281c2f0ba..018bf4ccc86d8 100644 --- a/tests/ui/transmutability/unions/should_pad_variants.stderr +++ b/tests/ui/transmutability/unions/should_pad_variants.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/should_pad_variants.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom $DIR/should_reject_contraction.rs:12:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/transmutability/unions/should_reject_disjoint.stderr b/tests/ui/transmutability/unions/should_reject_disjoint.stderr index d55abbe081776..0283c6caa931a 100644 --- a/tests/ui/transmutability/unions/should_reject_disjoint.stderr +++ b/tests/ui/transmutability/unions/should_reject_disjoint.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/should_reject_disjoint.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_maybe_transmutable` --> $DIR/should_reject_disjoint.rs:12:14 | LL | pub fn is_maybe_transmutable() - | --------------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_maybe_transmutable` diff --git a/tests/ui/transmutability/unions/should_reject_intersecting.stderr b/tests/ui/transmutability/unions/should_reject_intersecting.stderr index 522681d7d1578..cef172054b06c 100644 --- a/tests/ui/transmutability/unions/should_reject_intersecting.stderr +++ b/tests/ui/transmutability/unions/should_reject_intersecting.stderr @@ -8,7 +8,6 @@ note: required by a bound in `is_transmutable` --> $DIR/should_reject_intersecting.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` @@ -23,7 +22,6 @@ note: required by a bound in `is_transmutable` --> $DIR/should_reject_intersecting.rs:13:14 | LL | pub fn is_transmutable() - | --------------- required by a bound in this function LL | where LL | Dst: TransmuteFrom | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `is_transmutable` diff --git a/tests/ui/type-alias-impl-trait/issue-57961.stderr b/tests/ui/type-alias-impl-trait/issue-57961.stderr index 314296b5bb317..f6e68373b5888 100644 --- a/tests/ui/type-alias-impl-trait/issue-57961.stderr +++ b/tests/ui/type-alias-impl-trait/issue-57961.stderr @@ -12,6 +12,7 @@ LL | type Bar = std::vec::IntoIter; note: required by a bound in `Foo::Bar` --> $DIR/issue-57961.rs:6:24 | +LL | trait Foo { LL | type Bar: Iterator; | ^^^^^^^^ required by this bound in `Foo::Bar` diff --git a/tests/ui/typeck/method-chain-gats.stderr b/tests/ui/typeck/method-chain-gats.stderr index d3a54dbd0f9e2..be734b2800bde 100644 --- a/tests/ui/typeck/method-chain-gats.stderr +++ b/tests/ui/typeck/method-chain-gats.stderr @@ -12,8 +12,8 @@ LL | fn fmap2(input: T, f1: impl Fn(A) -> B, f2: impl Fn(B) -> C) -> note: required by a bound in `Functor::fmap` --> $DIR/method-chain-gats.rs:10:24 | +LL | trait Functor: Base { LL | fn fmap(self, f: impl Fn(A) -> B) -> Self::Base - | ---- required by a bound in this associated function LL | where LL | Self::Base: Functor; | ^^^^^^^^^^ required by this bound in `Functor::fmap` diff --git a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr index 46ddd4556e96f..4e4c4fc1358f6 100644 --- a/tests/ui/typeck/type-inference-for-associated-types-69683.stderr +++ b/tests/ui/typeck/type-inference-for-associated-types-69683.stderr @@ -16,11 +16,13 @@ LL | impl, S> Element<[S; 3]> for T { note: required by a bound in `Foo::foo` --> $DIR/type-inference-for-associated-types-69683.rs:16:9 | +LL | trait Foo +LL | where LL | u8: Element, | ^^^^^^^^^^ required by this bound in `Foo::foo` LL | { LL | fn foo(self, x: >::Array); - | --- required by a bound in this associated function + | help: try using a fully qualified path to specify the expected types | LL - 0u16.foo(b); diff --git a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr index d811cead513c7..ae99932e8eb64 100644 --- a/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr +++ b/tests/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr @@ -14,7 +14,6 @@ note: required by a bound in `foo` --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:5:14 | LL | fn foo(f: F) - | --- required by a bound in this function LL | where F: Fn() | ^^^^ required by this bound in `foo` diff --git a/tests/ui/unstable-feature-bound/unstable-impl-assoc-type.fail.stderr b/tests/ui/unstable-feature-bound/unstable-impl-assoc-type.fail.stderr index db9759b4cc3a5..e69d6f89d967b 100644 --- a/tests/ui/unstable-feature-bound/unstable-impl-assoc-type.fail.stderr +++ b/tests/ui/unstable-feature-bound/unstable-impl-assoc-type.fail.stderr @@ -15,6 +15,7 @@ LL | impl Bar for Foo {} note: required by a bound in `Trait::Assoc` --> $DIR/unstable-impl-assoc-type.rs:13:17 | +LL | trait Trait { LL | type Assoc: Bar; | ^^^ required by this bound in `Trait::Assoc` diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_free_fn.fail.stderr b/tests/ui/unstable-feature-bound/unstable_feature_bound_free_fn.fail.stderr index f83542568289a..4dd14a165c67f 100644 --- a/tests/ui/unstable-feature-bound/unstable_feature_bound_free_fn.fail.stderr +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_free_fn.fail.stderr @@ -11,7 +11,7 @@ note: required by a bound in `bar` LL | #[unstable_feature_bound(feat_bar)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `bar` LL | fn bar() { - | --- required by a bound in this function + | error: aborting due to 1 previous error diff --git a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr index 69be101a40d2a..cd0fdf7e3ed29 100644 --- a/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr +++ b/tests/ui/unstable-feature-bound/unstable_feature_bound_on_trait.fail.stderr @@ -10,9 +10,10 @@ note: required by a bound in `Bar::bar` | LL | #[unstable_feature_bound(foo)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Bar::bar` -... +LL | trait Bar { +LL | #[stable(feature = "a", since = "1.1.1" )] LL | fn bar() {} - | --- required by a bound in this associated function + | error: aborting due to 1 previous error diff --git a/tests/ui/wf/return-type-non-wf-no-ice.current.stderr b/tests/ui/wf/return-type-non-wf-no-ice.current.stderr index 888f0893ec7c4..edadc7f4c0839 100644 --- a/tests/ui/wf/return-type-non-wf-no-ice.current.stderr +++ b/tests/ui/wf/return-type-non-wf-no-ice.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `Foo` --> $DIR/return-type-non-wf-no-ice.rs:10:8 | LL | pub struct Foo(T) - | --- required by a bound in this struct LL | where LL | T: Iterator, | ^^^^^^^^ required by this bound in `Foo` diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr index 6de4caa76ee0e..47c906175b7a9 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.quiet.stderr @@ -13,7 +13,6 @@ note: required by a bound in `called` --> $DIR/higher-ranked-fn-type.rs:12:25 | LL | fn called() - | ------ required by a bound in this function LL | where LL | for<'b> fn(&'b ()): Foo, | ^^^ required by this bound in `called` diff --git a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr index 89a91a1f1ad7b..5392c269ee907 100644 --- a/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr +++ b/tests/ui/where-clauses/higher-ranked-fn-type.verbose.stderr @@ -14,7 +14,6 @@ note: required by a bound in `called` --> $DIR/higher-ranked-fn-type.rs:12:25 | LL | fn called() - | ------ required by a bound in this function LL | where LL | for<'b> fn(&'b ()): Foo, | ^^^ required by this bound in `called` diff --git a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr index 5d23c4bee00f3..4d4036c488d66 100644 --- a/tests/ui/where-clauses/self-in-where-clause-allowed.stderr +++ b/tests/ui/where-clauses/self-in-where-clause-allowed.stderr @@ -7,6 +7,8 @@ LL | trait_object.autotrait_bound(); note: required by a bound in `Trait::autotrait_bound` --> $DIR/self-in-where-clause-allowed.rs:12:43 | +LL | trait Trait { +... LL | fn autotrait_bound(&self) where Self: AutoTrait {} | ^^^^^^^^^ required by this bound in `Trait::autotrait_bound` diff --git a/tests/ui/where-clauses/where-clause-method-substituion.stderr b/tests/ui/where-clauses/where-clause-method-substituion.stderr index 73aac3d54a310..49dc135ca14ad 100644 --- a/tests/ui/where-clauses/where-clause-method-substituion.stderr +++ b/tests/ui/where-clauses/where-clause-method-substituion.stderr @@ -17,6 +17,7 @@ LL | trait Foo { note: required by a bound in `Bar::method` --> $DIR/where-clause-method-substituion.rs:6:34 | +LL | trait Bar { LL | fn method(&self) where A: Foo; | ^^^^^^ required by this bound in `Bar::method` diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr index d1de813a2d9f8..d69107aa2307d 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `Foo::::equals` --> $DIR/where-clauses-method-unsatisfied.rs:16:12 | LL | fn equals(&self, u: &Foo) -> bool - | ------ required by a bound in this associated function LL | where LL | T: Eq, | ^^ required by this bound in `Foo::::equals` diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr index d1de813a2d9f8..d69107aa2307d 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr @@ -8,7 +8,6 @@ note: required by a bound in `Foo::::equals` --> $DIR/where-clauses-method-unsatisfied.rs:16:12 | LL | fn equals(&self, u: &Foo) -> bool - | ------ required by a bound in this associated function LL | where LL | T: Eq, | ^^ required by this bound in `Foo::::equals` diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr index 485b9459ddd0e..c04c292fb5dee 100644 --- a/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.current.stderr @@ -8,7 +8,6 @@ note: required by a bound in `equal` --> $DIR/where-clauses-unsatisfied.rs:7:8 | LL | fn equal(a: &T, b: &T) -> bool - | ----- required by a bound in this function LL | where LL | T: Eq, | ^^ required by this bound in `equal` diff --git a/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr b/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr index 485b9459ddd0e..c04c292fb5dee 100644 --- a/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr +++ b/tests/ui/where-clauses/where-clauses-unsatisfied.next.stderr @@ -8,7 +8,6 @@ note: required by a bound in `equal` --> $DIR/where-clauses-unsatisfied.rs:7:8 | LL | fn equal(a: &T, b: &T) -> bool - | ----- required by a bound in this function LL | where LL | T: Eq, | ^^ required by this bound in `equal` From dc38c310a0a4703fb73b805b17c616e99ec5e76a Mon Sep 17 00:00:00 2001 From: Josh Triplett Date: Sun, 20 Sep 2026 19:56:51 +0200 Subject: [PATCH 0477/1309] Fix typo: s/declararions/declarations/ --- clippy_lints/src/inline_trait_bounds.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/inline_trait_bounds.rs b/clippy_lints/src/inline_trait_bounds.rs index 9b77d3dc138b3..e9330fbf69267 100644 --- a/clippy_lints/src/inline_trait_bounds.rs +++ b/clippy_lints/src/inline_trait_bounds.rs @@ -19,7 +19,7 @@ declare_clippy_lint! { /// Avoid complex inline bounds, which could make a function declaration more difficult to read. /// /// ### Known limitations - /// Only lints functions and method declararions. Bounds on structs, enums, + /// Only lints functions and method declarations. Bounds on structs, enums, /// and impl blocks are not yet covered. /// /// ### Example From 13c1957e9c433006a19e314115159e538c3e444a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 20 Sep 2026 20:08:44 +0200 Subject: [PATCH 0478/1309] Move some rustdoc-html tests into the right folder --- tests/rustdoc-html/{duplicate_impls => deref}/auxiliary/impls.rs | 0 .../sidebar-links-duplicate-impls-33054.rs | 0 .../{ => inline_cross}/intra-doc-crate/auxiliary/self.rs | 0 tests/rustdoc-html/{ => inline_cross}/intra-doc-crate/self.rs | 0 .../failing-expansion-on-wrong-macro.rs | 0 tests/rustdoc-html/{macro => macro-expansion}/macro_expansion.rs | 0 tests/rustdoc-html/macro/macro-doc-comment-23812.rs | 1 - tests/rustdoc-html/primitive/primitive-link.rs | 1 - 8 files changed, 2 deletions(-) rename tests/rustdoc-html/{duplicate_impls => deref}/auxiliary/impls.rs (100%) rename tests/rustdoc-html/{duplicate_impls => deref}/sidebar-links-duplicate-impls-33054.rs (100%) rename tests/rustdoc-html/{ => inline_cross}/intra-doc-crate/auxiliary/self.rs (100%) rename tests/rustdoc-html/{ => inline_cross}/intra-doc-crate/self.rs (100%) rename tests/rustdoc-html/{source-code-pages => macro-expansion}/failing-expansion-on-wrong-macro.rs (100%) rename tests/rustdoc-html/{macro => macro-expansion}/macro_expansion.rs (100%) diff --git a/tests/rustdoc-html/duplicate_impls/auxiliary/impls.rs b/tests/rustdoc-html/deref/auxiliary/impls.rs similarity index 100% rename from tests/rustdoc-html/duplicate_impls/auxiliary/impls.rs rename to tests/rustdoc-html/deref/auxiliary/impls.rs diff --git a/tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs b/tests/rustdoc-html/deref/sidebar-links-duplicate-impls-33054.rs similarity index 100% rename from tests/rustdoc-html/duplicate_impls/sidebar-links-duplicate-impls-33054.rs rename to tests/rustdoc-html/deref/sidebar-links-duplicate-impls-33054.rs diff --git a/tests/rustdoc-html/intra-doc-crate/auxiliary/self.rs b/tests/rustdoc-html/inline_cross/intra-doc-crate/auxiliary/self.rs similarity index 100% rename from tests/rustdoc-html/intra-doc-crate/auxiliary/self.rs rename to tests/rustdoc-html/inline_cross/intra-doc-crate/auxiliary/self.rs diff --git a/tests/rustdoc-html/intra-doc-crate/self.rs b/tests/rustdoc-html/inline_cross/intra-doc-crate/self.rs similarity index 100% rename from tests/rustdoc-html/intra-doc-crate/self.rs rename to tests/rustdoc-html/inline_cross/intra-doc-crate/self.rs diff --git a/tests/rustdoc-html/source-code-pages/failing-expansion-on-wrong-macro.rs b/tests/rustdoc-html/macro-expansion/failing-expansion-on-wrong-macro.rs similarity index 100% rename from tests/rustdoc-html/source-code-pages/failing-expansion-on-wrong-macro.rs rename to tests/rustdoc-html/macro-expansion/failing-expansion-on-wrong-macro.rs diff --git a/tests/rustdoc-html/macro/macro_expansion.rs b/tests/rustdoc-html/macro-expansion/macro_expansion.rs similarity index 100% rename from tests/rustdoc-html/macro/macro_expansion.rs rename to tests/rustdoc-html/macro-expansion/macro_expansion.rs diff --git a/tests/rustdoc-html/macro/macro-doc-comment-23812.rs b/tests/rustdoc-html/macro/macro-doc-comment-23812.rs index 03fda4a25b9f3..bb592f9a4f216 100644 --- a/tests/rustdoc-html/macro/macro-doc-comment-23812.rs +++ b/tests/rustdoc-html/macro/macro-doc-comment-23812.rs @@ -24,7 +24,6 @@ doc! { //@ hasraw - 'Inner comment' //@ !hasraw - '//! Inner comment' - doc! { /** Outer block comment */ mod Bar { diff --git a/tests/rustdoc-html/primitive/primitive-link.rs b/tests/rustdoc-html/primitive/primitive-link.rs index 3fe9cdc3ca702..f824195fac5e5 100644 --- a/tests/rustdoc-html/primitive/primitive-link.rs +++ b/tests/rustdoc-html/primitive/primitive-link.rs @@ -1,6 +1,5 @@ #![crate_name = "foo"] - //@ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.u32.html"]' 'u32' //@ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i64.html"]' 'i64' //@ has foo/struct.Foo.html '//*[@class="docblock"]/p/a[@href="{{channel}}/std/primitive.i32.html"]' 'std::primitive::i32' From ebf08b9c01926d5319e80d9e7f2eaadd0f436452 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 20 Sep 2026 21:07:51 +0200 Subject: [PATCH 0479/1309] enable `f128` from `u64`/`i64` test --- library/coretests/tests/num/floats.rs | 38 ++++++++++++++------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/library/coretests/tests/num/floats.rs b/library/coretests/tests/num/floats.rs index b8f75489bb212..7093687f04b15 100644 --- a/library/coretests/tests/num/floats.rs +++ b/library/coretests/tests/num/floats.rs @@ -2182,24 +2182,26 @@ float_test! { } } -// FIXME(f128): Uncomment and adapt these tests once the From<{u64,i64}> impls are added. -// float_test! { -// name: from_u64_i64, -// attrs: { -// f16: #[cfg(false)], -// f32: #[cfg(false)], -// f64: #[cfg(false)], -// f128: #[cfg(target_has_reliable_f128)], -// }, -// test { -// assert_biteq!(Float::from(u64::MIN), Float::ZERO); -// assert_biteq!(Float::from(42_u64), 42.0); -// assert_biteq!(Float::from(u64::MAX), 18446744073709551615.0); -// assert_biteq!(Float::from(i64::MIN), -9223372036854775808.0); -// assert_biteq!(Float::from(42_i64), 42.0); -// assert_biteq!(Float::from(i64::MAX), 9223372036854775807.0); -// } -// } +float_test! { + name: from_u64_i64, + attrs: { + f16: #[cfg(false)], + const f16: #[cfg(false)], + f32: #[cfg(false)], + const f32: #[cfg(false)], + f64: #[cfg(false)], + const f64: #[cfg(false)], + f128: #[cfg(target_has_reliable_f128)], + }, + test { + assert_biteq!(Float::from(u64::MIN), Float::ZERO); + assert_biteq!(Float::from(42_u64), 42.0f128); + assert_biteq!(Float::from(u64::MAX), 18446744073709551615.0); + assert_biteq!(Float::from(i64::MIN), -9223372036854775808.0); + assert_biteq!(Float::from(42_i64), 42.0); + assert_biteq!(Float::from(i64::MAX), 9223372036854775807.0); + } +} float_test! { name: real_consts, From 132e321b8939a7ea02263e11a7e5b7097ced9066 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 19:17:59 +0000 Subject: [PATCH 0480/1309] Point at `impl` start --- .../src/error_reporting/traits/suggestions.rs | 4 ++-- .../generic-associated-types-bad.item.stderr | 2 ++ .../generic-associated-types-bad.local.stderr | 1 + .../unsatisfied-bounds-where-clause-on-assoc-ty.stderr | 1 + tests/ui/const-generics/infer/method-chain.stderr | 2 ++ tests/ui/const-generics/infer/uninferred-consts.stderr | 2 ++ tests/ui/consts/ct-var-in-collect_all_mismatches.stderr | 2 ++ tests/ui/delegation/inherent-impls-enums.stderr | 1 + tests/ui/delegation/inherent-impls-parent-generics.stderr | 4 ++++ tests/ui/delegation/inherent-impls-structs.stderr | 1 + tests/ui/inference/issue-86162-2.stderr | 1 + ...ssue-113264-incorrect-impl-trait-in-path-suggestion.stderr | 1 + tests/ui/methods/filter-relevant-fn-bounds.stderr | 1 + .../ui/self/arbitrary_self_types_generic_over_receiver.stderr | 3 +++ .../ui/sized/unsized-str-in-return-expr-arg-and-local.stderr | 1 + tests/ui/structs/ice-missing-field-fn-sig-method.stderr | 1 + tests/ui/suggestions/closure-arg-trailing-semicolon.stderr | 1 + tests/ui/suggestions/issue-84973.stderr | 2 ++ tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr | 2 ++ .../use-parentheses-to-call-closure-issue-145404.stderr | 1 + tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr | 2 ++ tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr | 2 ++ tests/ui/type-alias-impl-trait/issue-90400-1.stderr | 2 ++ .../where-clauses-method-unsatisfied.current.stderr | 1 + .../where-clauses-method-unsatisfied.next.stderr | 1 + 25 files changed, 40 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index fe4d14ebb4bdc..87c8f1c95b08b 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3964,9 +3964,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let sm = tcx.sess.source_map(); if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = tcx.def_kind(item_def_id) - && let Some(ident) = tcx.opt_item_ident(tcx.parent(item_def_id)) { - multispan.push_span_context(ident.span); + let span = tcx.def_span(tcx.parent(item_def_id)).shrink_to_lo(); + multispan.push_span_context(span); } if let Some(ident) = tcx.opt_item_ident(item_def_id) { multispan.push_span_context(ident.span); diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr index 0620725ca3334..d6b37ae1e94cb 100644 --- a/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.item.stderr @@ -7,6 +7,7 @@ LL | const _: Ty::Pr = String::new(); note: required by a bound in `Ty::Pr` --> $DIR/generic-associated-types-bad.rs:10:16 | +LL | impl Ty { LL | type Pr = T; | ^^^^ required by this bound in `Ty::Pr` @@ -19,6 +20,7 @@ LL | const _: Ty::Pr = String::new(); note: required by a bound in `Ty::Pr` --> $DIR/generic-associated-types-bad.rs:10:16 | +LL | impl Ty { LL | type Pr = T; | ^^^^ required by this bound in `Ty::Pr` diff --git a/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr index 5859834053887..69efe563e8e15 100644 --- a/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr +++ b/tests/ui/associated-inherent-types/generic-associated-types-bad.local.stderr @@ -7,6 +7,7 @@ LL | let _: Ty::Pr>; note: required by a bound in `Ty::Pr` --> $DIR/generic-associated-types-bad.rs:10:16 | +LL | impl Ty { LL | type Pr = T; | ^^^^ required by this bound in `Ty::Pr` diff --git a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr index 047fb90c8d8ae..2edf7faa440e1 100644 --- a/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr +++ b/tests/ui/associated-inherent-types/unsatisfied-bounds-where-clause-on-assoc-ty.stderr @@ -7,6 +7,7 @@ LL | let _: S::::X; note: required by a bound in `S::X` --> $DIR/unsatisfied-bounds-where-clause-on-assoc-ty.rs:9:12 | +LL | impl S { LL | type X = () LL | where LL | T: Copy; diff --git a/tests/ui/const-generics/infer/method-chain.stderr b/tests/ui/const-generics/infer/method-chain.stderr index c4dfa3967ba22..66aa9104779e9 100644 --- a/tests/ui/const-generics/infer/method-chain.stderr +++ b/tests/ui/const-generics/infer/method-chain.stderr @@ -7,6 +7,8 @@ LL | Foo.bar().bar().bar().bar().baz(); note: required by a const generic parameter in `Foo::baz` --> $DIR/method-chain.rs:8:12 | +LL | impl Foo { +... LL | fn baz(self) -> Foo { | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo::baz` help: consider specifying a const for the const parameter `N` diff --git a/tests/ui/const-generics/infer/uninferred-consts.stderr b/tests/ui/const-generics/infer/uninferred-consts.stderr index 839fb25c4e1e6..2eca003e0c7f5 100644 --- a/tests/ui/const-generics/infer/uninferred-consts.stderr +++ b/tests/ui/const-generics/infer/uninferred-consts.stderr @@ -7,6 +7,7 @@ LL | Foo.foo(); note: required by a const generic parameter in `Foo::foo` --> $DIR/uninferred-consts.rs:6:12 | +LL | impl Foo { LL | fn foo(self) {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo::foo` help: consider specifying the generic arguments @@ -23,6 +24,7 @@ LL | Foo.foo(); note: required by a const generic parameter in `Foo::foo` --> $DIR/uninferred-consts.rs:6:28 | +LL | impl Foo { LL | fn foo(self) {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `Foo::foo` help: consider specifying the generic arguments diff --git a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr index b5c8d335e85d6..1a2b43ffe4a44 100644 --- a/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr +++ b/tests/ui/consts/ct-var-in-collect_all_mismatches.stderr @@ -7,6 +7,8 @@ LL | self.unsatisfied() note: required by a bound in `Foo::::unsatisfied` --> $DIR/ct-var-in-collect_all_mismatches.rs:15:12 | +LL | impl Foo { +... LL | fn unsatisfied(self) LL | where LL | T: Bar, diff --git a/tests/ui/delegation/inherent-impls-enums.stderr b/tests/ui/delegation/inherent-impls-enums.stderr index d76aba9517ee4..c27f850dd71cf 100644 --- a/tests/ui/delegation/inherent-impls-enums.stderr +++ b/tests/ui/delegation/inherent-impls-enums.stderr @@ -27,6 +27,7 @@ LL | reuse S::<'static, (), 1>::foo_static::<'static, _, _> as foo_static_4; note: required by a const generic parameter in `S::<'a, A, C>::foo_static` --> $DIR/inherent-impls-enums.rs:9:34 | +LL | impl<'a, 'b, 'c, A: 'a, const C: usize> S<'a, A, C> { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `S::<'a, A, C>::foo_static` diff --git a/tests/ui/delegation/inherent-impls-parent-generics.stderr b/tests/ui/delegation/inherent-impls-parent-generics.stderr index 4e5850338b600..5fe1efbf81c13 100644 --- a/tests/ui/delegation/inherent-impls-parent-generics.stderr +++ b/tests/ui/delegation/inherent-impls-parent-generics.stderr @@ -117,6 +117,7 @@ LL | reuse E::foo_static as e; note: required by a const generic parameter in `E::<'a, A, C>::foo_static` --> $DIR/inherent-impls-parent-generics.rs:10:34 | +LL | impl<'a, 'b, 'c, A: 'a, const C: usize> E<'a, A, C> { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `E::<'a, A, C>::foo_static` help: consider specifying the generic arguments @@ -231,6 +232,7 @@ LL | reuse E::<'_, (), _>::foo_static as e8; note: required by a const generic parameter in `E::<'a, A, C>::foo_static` --> $DIR/inherent-impls-parent-generics.rs:10:34 | +LL | impl<'a, 'b, 'c, A: 'a, const C: usize> E<'a, A, C> { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `E::<'a, A, C>::foo_static` help: consider specifying the generic arguments @@ -299,6 +301,7 @@ LL | reuse S::foo_static as s; note: required by a const generic parameter in `S::::foo_static` --> $DIR/inherent-impls-parent-generics.rs:51:34 | +LL | impl<'a, 'b, 'c, A, const C: usize> S { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `S::::foo_static` help: consider specifying the generic arguments @@ -411,6 +414,7 @@ LL | reuse S::<(), _>::foo_static as s8; note: required by a const generic parameter in `S::::foo_static` --> $DIR/inherent-impls-parent-generics.rs:51:34 | +LL | impl<'a, 'b, 'c, A, const C: usize> S { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `S::::foo_static` help: consider specifying the generic arguments diff --git a/tests/ui/delegation/inherent-impls-structs.stderr b/tests/ui/delegation/inherent-impls-structs.stderr index 29963431b1451..dc993fcfb1c70 100644 --- a/tests/ui/delegation/inherent-impls-structs.stderr +++ b/tests/ui/delegation/inherent-impls-structs.stderr @@ -27,6 +27,7 @@ LL | reuse S::<(), 1>::foo_static::<'static, _, _> as foo_static_4; note: required by a const generic parameter in `S::::foo_static` --> $DIR/inherent-impls-structs.rs:8:34 | +LL | impl<'a, 'b, 'c, A, const C: usize> S { LL | fn foo_static<'d: 'd, 'e, T, const B: bool>() {} | ^^^^^^^^^^^^^ required by this const generic parameter in `S::::foo_static` diff --git a/tests/ui/inference/issue-86162-2.stderr b/tests/ui/inference/issue-86162-2.stderr index 155bce3576360..ad79a32d00613 100644 --- a/tests/ui/inference/issue-86162-2.stderr +++ b/tests/ui/inference/issue-86162-2.stderr @@ -10,6 +10,7 @@ LL | Foo::bar(gen()); //<- Do not suggest `Foo::bar::()`! note: required by a bound in `Foo::bar` --> $DIR/issue-86162-2.rs:8:20 | +LL | impl Foo { LL | fn bar(x: impl Clone) {} | ^^^^^ required by this bound in `Foo::bar` help: consider specifying a concrete type for the type parameter `T` diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr index 237015a654211..47cba5e02a4ab 100644 --- a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr +++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr @@ -10,6 +10,7 @@ LL | (S {}).owo(None) note: required by a bound in `S::owo` --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:6:35 | +LL | impl S { LL | fn owo(&self, _: Option<&impl T>) {} | ^ required by this bound in `S::owo` help: consider specifying a concrete type for the type parameter `T` diff --git a/tests/ui/methods/filter-relevant-fn-bounds.stderr b/tests/ui/methods/filter-relevant-fn-bounds.stderr index 69552e8204575..976d39a3714ca 100644 --- a/tests/ui/methods/filter-relevant-fn-bounds.stderr +++ b/tests/ui/methods/filter-relevant-fn-bounds.stderr @@ -29,6 +29,7 @@ LL | trait Output<'a> { note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/filter-relevant-fn-bounds.rs:11:12 | +LL | impl Wrapper { LL | fn do_something_wrapper(self, _: F) ... LL | F: for<'a> FnOnce(>::Type), diff --git a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr index 7a3d8b43c2e3a..7e0a50b563124 100644 --- a/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr +++ b/tests/ui/self/arbitrary_self_types_generic_over_receiver.stderr @@ -26,6 +26,7 @@ LL | foo.a(); note: required by a bound in `Foo::a` --> $DIR/arbitrary_self_types_generic_over_receiver.rs:7:21 | +LL | impl Foo { LL | fn a(self: impl Receiver) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::a` help: consider borrowing here @@ -44,6 +45,8 @@ LL | foo.b(); note: required by a bound in `Foo::b` --> $DIR/arbitrary_self_types_generic_over_receiver.rs:11:21 | +LL | impl Foo { +... LL | fn b(self: impl Deref) -> u32 { | ^^^^^^^^^^^^^^^^^^ required by this bound in `Foo::b` help: consider borrowing here diff --git a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr index 29cedf3ecfdd0..cf7c748ae0b5f 100644 --- a/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr +++ b/tests/ui/sized/unsized-str-in-return-expr-arg-and-local.stderr @@ -60,6 +60,7 @@ LL | S.baz(*""); note: required by a bound in `S::baz` --> $DIR/unsized-str-in-return-expr-arg-and-local.rs:10:27 | +LL | impl S { LL | fn baz(&self, _: impl Sized) {} | ^^^^^ required by this bound in `S::baz` help: references are always `Sized`, even if they point to unsized data; consider not dereferencing the expression diff --git a/tests/ui/structs/ice-missing-field-fn-sig-method.stderr b/tests/ui/structs/ice-missing-field-fn-sig-method.stderr index d652dd9537935..69473145d1c38 100644 --- a/tests/ui/structs/ice-missing-field-fn-sig-method.stderr +++ b/tests/ui/structs/ice-missing-field-fn-sig-method.stderr @@ -14,6 +14,7 @@ LL | trait Context {} note: required by a bound in `Foo::take` --> $DIR/ice-missing-field-fn-sig-method.rs:7:16 | +LL | impl Foo { LL | fn take(&self, _: T) {} | ^^^^^^^ required by this bound in `Foo::take` diff --git a/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr index 0a625e0f25cda..25870c664be78 100644 --- a/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr +++ b/tests/ui/suggestions/closure-arg-trailing-semicolon.stderr @@ -26,6 +26,7 @@ LL | S.run(|| { 5u8; }); note: required by a bound in `S::run` --> $DIR/closure-arg-trailing-semicolon.rs:25:15 | +LL | impl S { LL | fn run(&self, _: impl Fn() -> R) {} | ^^^ required by this bound in `S::run` diff --git a/tests/ui/suggestions/issue-84973.stderr b/tests/ui/suggestions/issue-84973.stderr index 2dec2d5f43527..c42c4af123da4 100644 --- a/tests/ui/suggestions/issue-84973.stderr +++ b/tests/ui/suggestions/issue-84973.stderr @@ -9,6 +9,8 @@ LL | let o = Other::new(f); note: required by a bound in `Other::<'a, G>::new` --> $DIR/issue-84973.rs:25:8 | +LL | impl<'a, G> Other<'a, G> +LL | where LL | G: SomeTrait, | ^^^^^^^^^ required by this bound in `Other::<'a, G>::new` LL | { diff --git a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr index f0acf1dbb963c..6afc6267dbdca 100644 --- a/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr +++ b/tests/ui/suggestions/late-bound-in-borrow-closure-sugg.stderr @@ -14,6 +14,8 @@ LL | trader.set_closure(closure); note: required by a bound in `Trader::<'a>::set_closure` --> $DIR/late-bound-in-borrow-closure-sugg.rs:15:50 | +LL | impl<'a> Trader<'a> { +... LL | pub fn set_closure(&mut self, function: impl Fn(&mut Trader) + 'a) { | ^^^^^^^^^^^^^^^ required by this bound in `Trader::<'a>::set_closure` help: consider wrapping the function in a closure diff --git a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr index e32b2d4a30c80..19151a674c7f8 100644 --- a/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr +++ b/tests/ui/suggestions/use-parentheses-to-call-closure-issue-145404.stderr @@ -10,6 +10,7 @@ LL | S.call(|| "hello"); note: required by a bound in `S::call` --> $DIR/use-parentheses-to-call-closure-issue-145404.rs:8:28 | +LL | impl S { LL | fn call(&self, _: impl Display) {} | ^^^^^^^ required by this bound in `S::call` help: use parentheses to call this closure diff --git a/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr b/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr index 0d1f944dacfe8..a60a260ed1fe7 100644 --- a/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr +++ b/tests/ui/trait-bounds/ownership-mismatch-on-arg.stderr @@ -30,6 +30,7 @@ LL | impl Tr for Hello {} note: required by a bound in `needs_deref::S::foo` --> $DIR/ownership-mismatch-on-arg.rs:13:39 | +LL | impl S { LL | fn foo(&self, _v: T, _w: T, _k: K) {} | ^^ required by this bound in `S::foo` @@ -84,6 +85,7 @@ LL | impl Tr for &Hello {} note: required by a bound in `needs_borrow::S::foo` --> $DIR/ownership-mismatch-on-arg.rs:36:19 | +LL | impl S { LL | fn foo(&self, _v: T, _w: T, _k: K) {} | ^^ required by this bound in `S::foo` help: consider borrowing these argument diff --git a/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr b/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr index 75ec60c9ec52e..9f486cd12874f 100644 --- a/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr +++ b/tests/ui/traits/explicit-reference-cast-unrelated-leaf.stderr @@ -15,6 +15,7 @@ LL | trait Output<'a> { note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/explicit-reference-cast-unrelated-leaf.rs:10:20 | +LL | impl Wrapper { LL | fn do_something_wrapper(self, _: F) LL | where LL | for<'a> F: Output<'a>, @@ -35,6 +36,7 @@ LL | trait Output<'a> { note: required by a bound in `Wrapper::do_something_wrapper` --> $DIR/explicit-reference-cast-unrelated-leaf.rs:11:20 | +LL | impl Wrapper { LL | fn do_something_wrapper(self, _: F) ... LL | for<'a> O: From<>::Type>, diff --git a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr index afdccd56a50f4..85700056d47c6 100644 --- a/tests/ui/type-alias-impl-trait/issue-90400-1.stderr +++ b/tests/ui/type-alias-impl-trait/issue-90400-1.stderr @@ -7,6 +7,8 @@ LL | move || bar.bar() note: required by a bound in `::foo` --> $DIR/issue-90400-1.rs:21:15 | +LL | impl Foo for MyFoo { +... LL | fn foo(&self, bar: B) -> Self::FooFn { | ^^^ required by this bound in `::foo` help: consider restricting type parameter `B` with trait `Bar` diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr index d69107aa2307d..df03acb8f4185 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.current.stderr @@ -7,6 +7,7 @@ LL | x.equals(&x); note: required by a bound in `Foo::::equals` --> $DIR/where-clauses-method-unsatisfied.rs:16:12 | +LL | impl Foo { LL | fn equals(&self, u: &Foo) -> bool LL | where LL | T: Eq, diff --git a/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr index d69107aa2307d..df03acb8f4185 100644 --- a/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr +++ b/tests/ui/where-clauses/where-clauses-method-unsatisfied.next.stderr @@ -7,6 +7,7 @@ LL | x.equals(&x); note: required by a bound in `Foo::::equals` --> $DIR/where-clauses-method-unsatisfied.rs:16:12 | +LL | impl Foo { LL | fn equals(&self, u: &Foo) -> bool LL | where LL | T: Eq, From d85e28f2fd4e43c98ff7d7df909e209f38a6b2c1 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Sun, 20 Sep 2026 12:28:32 -0400 Subject: [PATCH 0481/1309] powerpc64: don't pass multi-field unions in FPRs on ELFv1 The ELFv1 ABI only passes "one member aggregates" containing a floating point value in floating point registers. A union with more than one member is not a one member aggregate, but `homogeneous_aggregate` merges the fields of a union, so e.g. `union { f32, f32 }` was passed in an FPR, while GCC and clang both pass it in a GPR. Reject as a one-member aggregate any layout that is or contains a union with more than one non-1-ZST field. --- .../rustc_target/src/callconv/powerpc64.rs | 29 ++++++++++- .../powerpc64-abi/homogeneous-aggregate.rs | 51 +++++++++++++++++++ 2 files changed, 78 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index d4617d8e7d693..5c31552bdcfcc 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -2,7 +2,7 @@ // Alignment of 128 bit types is not currently handled, this will // need to be fixed when PowerPC vector support is added. -use rustc_abi::{HasDataLayout, Integer, Numeric, TyAbiInterface}; +use rustc_abi::{FieldsShape, HasDataLayout, Integer, Numeric, TyAbiInterface, TyAndLayout}; use crate::callconv::{Align, ArgAbi, CastTarget, FnAbi, Reg, RegKind, Uniform}; use crate::spec::{HasTargetSpec, LlvmAbi, Os}; @@ -15,6 +15,30 @@ enum ABI { } use ABI::*; +/// Whether `layout` is or contains a union with more than one non-1-ZST field. +/// +/// `homogeneous_aggregate` merges the fields of a union, so it cannot tell such a union from a +/// structure. This walks the layout a second time; keep the array and 1-ZST handling here in sync +/// with `homogeneous_aggregate`. +fn contains_multi_field_union<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout, +{ + let fields = + || (0..layout.fields.count()).map(|i| layout.field(cx, i)).filter(|f| !f.is_1zst()); + match layout.fields { + FieldsShape::Primitive => false, + FieldsShape::Union(_) => { + fields().count() > 1 || fields().any(|f| contains_multi_field_union(cx, f)) + } + FieldsShape::Array { count, .. } => { + count > 0 && contains_multi_field_union(cx, layout.field(cx, 0)) + } + FieldsShape::Arbitrary { .. } => fields().any(|f| contains_multi_field_union(cx, f)), + } +} + fn is_homogeneous_aggregate<'a, Ty, C>( cx: &C, arg: &mut ArgAbi<'a, Ty>, @@ -27,7 +51,8 @@ where arg.layout.homogeneous_aggregate(cx).ok().and_then(|ha| ha.unit()).and_then(|unit| { // ELFv1 and AIX only passes one-member aggregates transparently. // ELFv2 passes up to eight uniquely addressable members. - if ((abi == ELFv1 || abi == AIX) && arg.layout.size > unit.size) + if ((abi == ELFv1 || abi == AIX) + && (arg.layout.size > unit.size || contains_multi_field_union(cx, arg.layout))) || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { return None; diff --git a/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs index dd053411aa4e5..5e247092cb643 100644 --- a/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs +++ b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs @@ -94,3 +94,54 @@ pub struct Hfa4V2F64 { pub extern "C" fn test_hfa_4_f64x2(a: Hfa4V2F64) { hint::black_box(a); } + +// A one-member aggregate containing a float is passed in a floating point register. +#[repr(C)] +pub struct OneFloatStruct { + pub a: f32, +} +impl Copy for OneFloatStruct {} + +// ppc64: define void @test_struct_one_float(float %0) +// ppc64_vsx: define void @test_struct_one_float(float %0) +// ppc64le: define void @test_struct_one_float(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_struct_one_float(a: OneFloatStruct) { + hint::black_box(a); +} + +// A union with several members is not a one-member aggregate, so on ELFv1 it is not passed in a +// floating point register. See https://github.com/rust-lang/rust/issues/162011. +#[repr(C)] +pub union TwoFloats { + pub a: f32, + pub b: f32, +} + +// ppc64: define void @test_union_two_floats(i32 %0) +// ppc64_vsx: define void @test_union_two_floats(i32 %0) +// ppc64le: define void @test_union_two_floats(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_union_two_floats(a: TwoFloats) { + hint::black_box(a); +} + +// A zero-sized union contributes no data, so it doesn't disqualify the aggregate. +#[repr(C)] +pub union ZstUnion { + pub a: (), +} + +#[repr(C)] +pub struct OneFloatAndZstUnion { + pub a: f32, + pub u: ZstUnion, +} + +// ppc64: define void @test_struct_one_float_and_zst_union(float %0) +// ppc64_vsx: define void @test_struct_one_float_and_zst_union(float %0) +// ppc64le: define void @test_struct_one_float_and_zst_union(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_struct_one_float_and_zst_union(a: OneFloatAndZstUnion) { + hint::black_box(a); +} From 93c896682f0e10209676dfb67e52a2b042b2adc8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 7 Sep 2026 16:40:57 +1000 Subject: [PATCH 0482/1309] Remove `TypeChecker::root_cx` It's only used for `self.root_cx.root_def_id()`, but `self.infcx.root_def_id` is also available. --- compiler/rustc_borrowck/src/lib.rs | 1 - compiler/rustc_borrowck/src/type_check/mod.rs | 7 ++----- 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 546d91187e05e..ad47dce0f15e6 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -361,7 +361,6 @@ fn borrowck_collect_region_constraints<'tcx>( deferred_closure_requirements, polonius_context, } = type_check::type_check( - root_cx, &infcx, body, &promoted, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6418c73173df0..4c5acd58638fb 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -47,7 +47,7 @@ use crate::region_infer::values::{LivenessValues, PlaceholderIndex, PlaceholderI use crate::session_diagnostics::{MoveUnsized, SimdIntrinsicArgConst}; use crate::type_check::free_region_relations::{CreateResult, UniversalRegionRelations}; use crate::universal_regions::{DefiningTy, UniversalRegions}; -use crate::{BorrowCheckRootCtxt, BorrowckInferCtxt, DeferredClosureRequirements, path_utils}; +use crate::{BorrowckInferCtxt, DeferredClosureRequirements, path_utils}; macro_rules! span_mirbug { ($context:expr, $elem:expr, $($message:tt)*) => ({ @@ -94,7 +94,6 @@ mod relate_tys; /// - `move_data` -- move-data constructed when performing the maybe-init dataflow analysis /// - `location_map` -- map between MIR `Location` and `PointIndex` pub(crate) fn type_check<'tcx>( - root_cx: &BorrowCheckRootCtxt<'_, 'tcx>, infcx: &BorrowckInferCtxt<'tcx>, body: &Body<'tcx>, promoted: &IndexSlice>, @@ -145,7 +144,6 @@ pub(crate) fn type_check<'tcx>( let mut deferred_closure_requirements = Default::default(); let mut typeck = TypeChecker { - root_cx, infcx, last_span: body.span, body, @@ -227,7 +225,6 @@ enum FieldAccessError { /// way, it accrues region constraints -- these can later be used by /// NLL region checking. struct TypeChecker<'a, 'tcx> { - root_cx: &'a BorrowCheckRootCtxt<'a, 'tcx>, infcx: &'a BorrowckInferCtxt<'tcx>, last_span: Span, body: &'a Body<'tcx>, @@ -2715,7 +2712,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { args: GenericArgsRef<'tcx>, location: Location, ) -> ty::InstantiatedClauses<'tcx> { - let root_def_id = self.root_cx.root_def_id(); + let root_def_id = self.infcx.root_def_id; // We will have to handle propagated closure requirements for this closure, // but need to defer this until the nested body has been fully borrow checked. self.deferred_closure_requirements.push((def_id, args, location.to_locations())); From 22dee8fbba20886cf541ddf33c93db293294b210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 21:57:37 +0000 Subject: [PATCH 0483/1309] Fix test --- tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr index f9bcc4ef4d8a6..009c0d37bf825 100644 --- a/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr +++ b/tests/ui-fulldeps/rustc-dev-remap.remap-unremap.stderr @@ -23,6 +23,8 @@ LL | impl VisitorResult for Result<(), E> { note: required by a bound in `rustc_ast::visit::Visitor::Result` --> $COMPILER_DIR_REAL/rustc_ast/src/visit.rs:LL:COL | +LL | pub trait $Visitor<$($lt)?>: Sized $(${ignore($mut)} + MutVisitorResult)? { +... LL | type Result: VisitorResult = (); | ^^^^^^^^^^^^^ required by this bound in `Visitor::Result` ... From 28fe1330266e7b3014db6ee07ae81d88f310dee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 15 Sep 2026 22:12:05 +0000 Subject: [PATCH 0484/1309] Do not continue past `rustc_resolve` when encountering duplicated types Duplicated items cause lots of confusing knock down errors. This change side-steps some known ICEs, and reduces the verbosity of crates with duplicated types at the cost of not emitting every error that we could. Update tests that no longer crash: 120873 -> `tests/ui/resolve/multiple_definitions_attribute_merging.rs` (already existing) 123690 -> `tests/ui/resolve/duplicated-enum-variant.rs` 155482 -> `tests/ui/resolve/duplicated-item-in-const-generics.rs` Added two cases from the report that still ICE. --- .../src/error_codes/E0091.md | 8 +++- .../src/error_codes/E0634.md | 3 +- .../rustc_resolve/src/diagnostics/impls.rs | 8 +++- compiler/rustc_resolve/src/lib.rs | 8 ++++ tests/crashes/120873.rs | 8 ---- tests/crashes/155482-2.rs | 12 +++++ tests/crashes/155482.rs | 12 ++--- ...ith-same-name-and-derive-default-133965.rs | 5 +-- ...same-name-and-derive-default-133965.stderr | 41 +---------------- ...ultiple-types-with-same-name-and-derive.rs | 5 +-- ...ple-types-with-same-name-and-derive.stderr | 43 +----------------- .../ui/enum/enum-and-module-in-same-scope.rs | 1 - .../enum/enum-and-module-in-same-scope.stderr | 13 +----- tests/ui/panic-handler/weak-lang-item.rs | 3 -- tests/ui/panic-handler/weak-lang-item.stderr | 9 +--- .../effective_visibilities_invariants.rs | 4 +- .../effective_visibilities_invariants.stderr | 22 ++++------ .../resolve/duplicated-enum-variant.rs} | 8 +++- .../ui/resolve/duplicated-enum-variant.stderr | 14 ++++++ .../duplicated-item-in-const-generics.rs | 8 ++++ .../duplicated-item-in-const-generics.stderr | 36 +++++++++++++++ .../multiple_definitions_attribute_merging.rs | 13 ++---- ...tiple_definitions_attribute_merging.stderr | 19 ++------ .../static/duplicated-fields-issue-124464.rs | 2 - .../duplicated-fields-issue-124464.stderr | 17 ++----- tests/ui/traits/issue-106072.rs | 2 +- tests/ui/traits/issue-106072.stderr | 13 +----- .../traits/non_lifetime_binders/bad-bounds.rs | 4 +- .../non_lifetime_binders/bad-bounds.stderr | 18 ++------ tests/ui/use/use-self-at-end-2.e2015.stderr | 29 ++++++++++++ tests/ui/use/use-self-at-end-2.e2018.stderr | 29 ++++++++++++ tests/ui/use/use-self-at-end-2.e2021.stderr | 27 ++++++++++++ tests/ui/use/use-self-at-end-2.rs | 26 +++++++++++ tests/ui/use/use-self-at-end.e2015.stderr | 44 ++++--------------- tests/ui/use/use-self-at-end.e2018.stderr | 44 ++++--------------- tests/ui/use/use-self-at-end.e2021.stderr | 41 ++++------------- tests/ui/use/use-self-at-end.rs | 9 +--- 37 files changed, 283 insertions(+), 325 deletions(-) delete mode 100644 tests/crashes/120873.rs create mode 100644 tests/crashes/155482-2.rs rename tests/{crashes/123690.rs => ui/resolve/duplicated-enum-variant.rs} (95%) create mode 100644 tests/ui/resolve/duplicated-enum-variant.stderr create mode 100644 tests/ui/resolve/duplicated-item-in-const-generics.rs create mode 100644 tests/ui/resolve/duplicated-item-in-const-generics.stderr create mode 100644 tests/ui/use/use-self-at-end-2.e2015.stderr create mode 100644 tests/ui/use/use-self-at-end-2.e2018.stderr create mode 100644 tests/ui/use/use-self-at-end-2.e2021.stderr create mode 100644 tests/ui/use/use-self-at-end-2.rs diff --git a/compiler/rustc_error_codes/src/error_codes/E0091.md b/compiler/rustc_error_codes/src/error_codes/E0091.md index 3bf4e907ecb1f..5fbc4b7a63e25 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0091.md +++ b/compiler/rustc_error_codes/src/error_codes/E0091.md @@ -4,7 +4,9 @@ Erroneous code example: ```compile_fail,E0091 type Foo = u32; // error: type parameter `T` is never used -// or: +``` +or: +```compile_fail,E0091 type Foo = Box; // error: type parameter `B` is never used ``` @@ -12,5 +14,7 @@ Please check you didn't write too many parameters. Example: ``` type Foo = u32; // ok! -type Foo2 = Box; // ok! +``` +``` +type Foo = Box; // ok! ``` diff --git a/compiler/rustc_error_codes/src/error_codes/E0634.md b/compiler/rustc_error_codes/src/error_codes/E0634.md index 0c4ed2596e2aa..6b6563a2e8128 100644 --- a/compiler/rustc_error_codes/src/error_codes/E0634.md +++ b/compiler/rustc_error_codes/src/error_codes/E0634.md @@ -5,7 +5,8 @@ Erroneous code examples: ```compile_fail,E0634 #[repr(packed, packed(2))] // error! struct Company(i32); - +``` +```compile_fail,E0634 #[repr(packed(2))] // error! #[repr(packed)] struct Company(i32); diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 6ddfff9f88d83..59daa5da337a0 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -572,6 +572,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } err.emit(); + + if ns == TypeNS { + // Duplicated types wreak havoc on other errors, like impls selecting the wrong + // type causing wrong number of generic params and other assorted number of + // irrelevant nonsense, so avoid advancing to the next compiler stage. + self.raise_fatal_after_resolve = true; + } self.name_already_seen.insert(name, span); } @@ -2872,7 +2879,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { break; } } - err.emit(); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index e479ef6a621c9..7db58394e5d29 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1565,6 +1565,11 @@ pub struct Resolver<'ra, 'tcx> { // for APITs, so we don't want to leak details of resolution into these names. impl_trait_names: FxHashMap = default::fx_hash_map(), + /// When enabled, after reporting every error we will `FatalError.raise()` to avoid advancing + /// to the next compiler stage. Only used when encountering resolution errors that cause lots of + /// unnecessary knock down errors. + raise_fatal_after_resolve: bool = false, + /// Stores `#[diagnostic::on_unknown]` attributes placed on module declarations. on_unknown_data: FxHashMap = default::fx_hash_map(), features: &'tcx Features, @@ -2098,6 +2103,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // Don't mutate the cstore or stable crate id map from here on. self.tcx.untracked().freeze_cstore(); + if self.raise_fatal_after_resolve { + rustc_errors::FatalError.raise(); + } } fn traits_in_scope( diff --git a/tests/crashes/120873.rs b/tests/crashes/120873.rs deleted file mode 100644 index 45bc0bd457b10..0000000000000 --- a/tests/crashes/120873.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #120873 -#[repr(packed)] - -struct Dealigned(u8, T); - -#[derive(PartialEq)] -#[repr(C)] -struct Dealigned(u8, T); diff --git a/tests/crashes/155482-2.rs b/tests/crashes/155482-2.rs new file mode 100644 index 0000000000000..38cef9c101c1f --- /dev/null +++ b/tests/crashes/155482-2.rs @@ -0,0 +1,12 @@ +//@ known-bug: #155482 +//@ only-x86_64 +#![feature(generic_assert)] +fn main() { + std::arch::x86_64::_mm_shuffle_ps( + todo!(), + todo!(), + const { + assert!(X != 2); + }, + ) +} diff --git a/tests/crashes/155482.rs b/tests/crashes/155482.rs index a2182f83d737c..3db4e5fd06587 100644 --- a/tests/crashes/155482.rs +++ b/tests/crashes/155482.rs @@ -1,7 +1,9 @@ //@ known-bug: #155482 -trait TraitA < AsA = impl TraitB < { -#[derive(Hash)] - enum A; - struct A; +//@ only-x86_64 +#![feature(generic_assert)] +fn main() { + const I = 0; + std::arch::x86_64::_mm_shuffle_ps(todo!(), todo!(), const { + assert!(N != 0); + }); } ->> ; diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs index 34ba998c1dc60..27794bdafa215 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.rs @@ -4,9 +4,6 @@ struct NonGeneric {} #[derive(Default)] struct NonGeneric<'a, const N: usize> {} -//~^ ERROR: struct takes 0 lifetime arguments but 1 lifetime argument was supplied -//~| ERROR: struct takes 0 generic arguments but 1 generic argument was supplied -//~| ERROR: lifetime parameter `'a` is never used -//~| ERROR: the name `NonGeneric` is defined multiple times +//~^ ERROR: the name `NonGeneric` is defined multiple times pub fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr index d758cb13f9939..9cb0a56d44aca 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive-default-133965.stderr @@ -9,43 +9,6 @@ LL | struct NonGeneric<'a, const N: usize> {} | = note: `NonGeneric` must be defined only once in the type namespace of this module -error[E0107]: struct takes 0 lifetime arguments but 1 lifetime argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:8 - | -LL | struct NonGeneric<'a, const N: usize> {} - | ^^^^^^^^^^ -- help: remove the lifetime argument - | | - | expected 0 lifetime arguments - | -note: struct defined here, with 0 lifetime parameters - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 - | -LL | struct NonGeneric {} - | ^^^^^^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:8 - | -LL | struct NonGeneric<'a, const N: usize> {} - | ^^^^^^^^^^ - help: remove the unnecessary generic argument - | | - | expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:3:8 - | -LL | struct NonGeneric {} - | ^^^^^^^^^^ - -error[E0392]: lifetime parameter `'a` is never used - --> $DIR/multiple-types-with-same-name-and-derive-default-133965.rs:6:19 - | -LL | struct NonGeneric<'a, const N: usize> {} - | ^^ unused lifetime parameter - | - = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0107, E0392, E0428. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs index 3caf5434cd008..408780b187fb5 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.rs @@ -9,9 +9,6 @@ struct NotSM; #[derive(PartialEq, Eq)] struct NotSM(T); -//~^ ERROR: struct takes 0 generic arguments -//~| ERROR: struct takes 0 generic arguments -//~| ERROR: struct takes 0 generic arguments -//~| ERROR: the name `NotSM` is defined multiple times +//~^ ERROR: the name `NotSM` is defined multiple times fn main() {} diff --git a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr index e745b3ce8fc2f..e12acc708eb70 100644 --- a/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr +++ b/tests/ui/duplicate/multiple-types-with-same-name-and-derive.stderr @@ -9,45 +9,6 @@ LL | struct NotSM(T); | = note: `NotSM` must be defined only once in the type namespace of this module -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 - | -LL | struct NotSM(T); - | ^^^^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 - | -LL | struct NotSM(T); - | ^^^^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error[E0107]: struct takes 0 generic arguments but 1 generic argument was supplied - --> $DIR/multiple-types-with-same-name-and-derive.rs:11:8 - | -LL | struct NotSM(T); - | ^^^^^ expected 0 generic arguments - | -note: struct defined here, with 0 generic parameters - --> $DIR/multiple-types-with-same-name-and-derive.rs:8:8 - | -LL | struct NotSM; - | ^^^^^ - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0107, E0428. -For more information about an error, try `rustc --explain E0107`. +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/enum/enum-and-module-in-same-scope.rs b/tests/ui/enum/enum-and-module-in-same-scope.rs index 8e69c89d792ff..cc6e199bd7ca0 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.rs +++ b/tests/ui/enum/enum-and-module-in-same-scope.rs @@ -5,7 +5,6 @@ enum Foo { mod Foo { //~ ERROR the name `Foo` is defined multiple times pub static X: isize = 42; fn f() { f() } // Check that this does not result in a resolution error - //~^ WARN cannot return without recursing } fn main() {} diff --git a/tests/ui/enum/enum-and-module-in-same-scope.stderr b/tests/ui/enum/enum-and-module-in-same-scope.stderr index f1c02af595ffd..0293acd6201b2 100644 --- a/tests/ui/enum/enum-and-module-in-same-scope.stderr +++ b/tests/ui/enum/enum-and-module-in-same-scope.stderr @@ -9,17 +9,6 @@ LL | mod Foo { | = note: `Foo` must be defined only once in the type namespace of this module -warning: function cannot return without recursing - --> $DIR/enum-and-module-in-same-scope.rs:7:5 - | -LL | fn f() { f() } // Check that this does not result in a resolution error - | ^^^^^^ --- recursive call site - | | - | cannot return without recursing - | - = help: a `loop` may express intention better if this is on purpose - = note: `#[warn(unconditional_recursion)]` on by default - -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/panic-handler/weak-lang-item.rs b/tests/ui/panic-handler/weak-lang-item.rs index 43a235fd6b418..6c3a5b2b271c2 100644 --- a/tests/ui/panic-handler/weak-lang-item.rs +++ b/tests/ui/panic-handler/weak-lang-item.rs @@ -8,6 +8,3 @@ extern crate core; //~ ERROR the name `core` is defined multiple times extern crate weak_lang_items; fn main() {} - -//~? ERROR `#[panic_handler]` function required, but not found -//~? ERROR unwinding panics are not supported without std diff --git a/tests/ui/panic-handler/weak-lang-item.stderr b/tests/ui/panic-handler/weak-lang-item.stderr index 5acd3e3187051..d7b453c96e488 100644 --- a/tests/ui/panic-handler/weak-lang-item.stderr +++ b/tests/ui/panic-handler/weak-lang-item.stderr @@ -10,13 +10,6 @@ help: you can use `as` to change the binding name of the import LL | extern crate core as other_core; | +++++++++++++ -error: `#[panic_handler]` function required, but not found - -error: unwinding panics are not supported without std - | - = help: using nightly cargo, use -Zbuild-std with panic="abort" to avoid unwinding - = note: since the core library is usually precompiled with panic="unwind", rebuilding your crate with panic="abort" may not be enough to fix the problem - -error: aborting due to 3 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0259`. diff --git a/tests/ui/privacy/effective_visibilities_invariants.rs b/tests/ui/privacy/effective_visibilities_invariants.rs index af5a2bed6ab24..92cb24e9da7df 100644 --- a/tests/ui/privacy/effective_visibilities_invariants.rs +++ b/tests/ui/privacy/effective_visibilities_invariants.rs @@ -2,9 +2,9 @@ #![feature(staged_api)] //~ ERROR module has missing stability attribute -pub mod m {} //~ ERROR module has missing stability attribute +pub mod a {} //~ ERROR module has missing stability attribute -pub mod m { //~ ERROR the name `m` is defined multiple times +pub mod b { //~ ERROR module has missing stability attribute mod inner {} type Inner = u8; } diff --git a/tests/ui/privacy/effective_visibilities_invariants.stderr b/tests/ui/privacy/effective_visibilities_invariants.stderr index 97bee1e2d8d36..1ee25606cf27a 100644 --- a/tests/ui/privacy/effective_visibilities_invariants.stderr +++ b/tests/ui/privacy/effective_visibilities_invariants.stderr @@ -1,20 +1,9 @@ -error[E0428]: the name `m` is defined multiple times - --> $DIR/effective_visibilities_invariants.rs:7:1 - | -LL | pub mod m {} - | --------- previous definition of the module `m` here -LL | -LL | pub mod m { - | ^^^^^^^^^ `m` redefined here - | - = note: `m` must be defined only once in the type namespace of this module - error: module has missing stability attribute --> $DIR/effective_visibilities_invariants.rs:3:1 | LL | / #![feature(staged_api)] LL | | -LL | | pub mod m {} +LL | | pub mod a {} ... | LL | | fn main() {} | |____________^ @@ -22,9 +11,14 @@ LL | | fn main() {} error: module has missing stability attribute --> $DIR/effective_visibilities_invariants.rs:5:1 | -LL | pub mod m {} +LL | pub mod a {} + | ^^^^^^^^^ + +error: module has missing stability attribute + --> $DIR/effective_visibilities_invariants.rs:7:1 + | +LL | pub mod b { | ^^^^^^^^^ error: aborting due to 3 previous errors -For more information about this error, try `rustc --explain E0428`. diff --git a/tests/crashes/123690.rs b/tests/ui/resolve/duplicated-enum-variant.rs similarity index 95% rename from tests/crashes/123690.rs rename to tests/ui/resolve/duplicated-enum-variant.rs index 3af70e20aee18..732726c5b7a25 100644 --- a/tests/crashes/123690.rs +++ b/tests/ui/resolve/duplicated-enum-variant.rs @@ -1,4 +1,6 @@ -//@ known-bug: #123690 +// Regression test for #123690. If we allow the compiler to advance past `rustc_resolve`, it causes +// an ICE. + fn more_discriminant_overflow() { pub enum Infallible {} @@ -229,7 +231,7 @@ fn more_discriminant_overflow() { _D5(X), _D6(X), _D7(X), - _D8(X), + _D8(X), //~ ERROR: the name `_D8` is defined multiple times _D9(X), _DA(X), _DB(X), @@ -276,3 +278,5 @@ fn more_discriminant_overflow() { if let E2::V1 { .. } = E2::V3:: {} } + +fn main() {} diff --git a/tests/ui/resolve/duplicated-enum-variant.stderr b/tests/ui/resolve/duplicated-enum-variant.stderr new file mode 100644 index 0000000000000..e52ec8b729b78 --- /dev/null +++ b/tests/ui/resolve/duplicated-enum-variant.stderr @@ -0,0 +1,14 @@ +error[E0428]: the name `_D8` is defined multiple times + --> $DIR/duplicated-enum-variant.rs:234:9 + | +LL | _D8(X), + | ------ previous definition of the type `_D8` here +... +LL | _D8(X), + | ^^^^^^ `_D8` redefined here + | + = note: `_D8` must be defined only once in the type namespace of this enum + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/resolve/duplicated-item-in-const-generics.rs b/tests/ui/resolve/duplicated-item-in-const-generics.rs new file mode 100644 index 0000000000000..b3903864e8dfb --- /dev/null +++ b/tests/ui/resolve/duplicated-item-in-const-generics.rs @@ -0,0 +1,8 @@ +// Regression test for #155482. If we allow the compiler to advance past `rustc_resolve`, it causes +// an ICE. +trait TraitA < AsA = impl TraitB < { //~ ERROR: cannot find trait `TraitB` in this scope +#[derive(Hash)] + enum A; //~ ERROR: expected `{}`, found `;` + struct A; //~ ERROR: the name `A` is defined multiple times +} +>> ; //~ ERROR: expected `{}`, found `;` diff --git a/tests/ui/resolve/duplicated-item-in-const-generics.stderr b/tests/ui/resolve/duplicated-item-in-const-generics.stderr new file mode 100644 index 0000000000000..e27137a3e6db4 --- /dev/null +++ b/tests/ui/resolve/duplicated-item-in-const-generics.stderr @@ -0,0 +1,36 @@ +error: expected `{}`, found `;` + --> $DIR/duplicated-item-in-const-generics.rs:5:9 + | +LL | enum A; + | ^ + | + = help: try using `{}` instead + +error: expected `{}`, found `;` + --> $DIR/duplicated-item-in-const-generics.rs:8:4 + | +LL | >> ; + | ^ + | + = help: try using `{}` instead + +error[E0428]: the name `A` is defined multiple times + --> $DIR/duplicated-item-in-const-generics.rs:6:3 + | +LL | enum A; + | ------- previous definition of the type `A` here +LL | struct A; + | ^^^^^^^^^^^^ `A` redefined here + | + = note: `A` must be defined only once in the type namespace of this block + +error[E0405]: cannot find trait `TraitB` in this scope + --> $DIR/duplicated-item-in-const-generics.rs:3:27 + | +LL | trait TraitA < AsA = impl TraitB < { + | ^^^^^^ not found in this scope + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0405, E0428. +For more information about an error, try `rustc --explain E0405`. diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.rs b/tests/ui/resolve/multiple_definitions_attribute_merging.rs index 9f1bff51a3d4c..ee8798fc3a0a8 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.rs +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.rs @@ -1,20 +1,15 @@ //! This test ICEs because the `repr(packed)` attributes //! end up on the `Dealigned` struct's attribute list, but the //! derive didn't see that. - -//@known-bug: #120873 -//@ failure-status: 101 -//@ normalize-stderr: "note: .*\n\n" -> "" -//@ normalize-stderr: "thread 'rustc'.*panicked.*\n" -> "" -//@ normalize-stderr: "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: " -//@ normalize-stderr: "/rustc(?:-dev)?/[a-z0-9.]+/" -> "" -//@ rustc-env:RUST_BACKTRACE=0 +//! +//! Because we now `Fatal.raise()` in resolve when encountering +//! duplicated names, the ICE in #120873 no longer happens. #[repr(packed)] struct Dealigned(u8, T); #[derive(PartialEq)] #[repr(C)] -struct Dealigned(u8, T); +struct Dealigned(u8, T); //~ ERROR: the name `Dealigned` is defined multiple times fn main() {} diff --git a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr index b8b33e3417bf7..b8dfb7fcae02a 100644 --- a/tests/ui/resolve/multiple_definitions_attribute_merging.stderr +++ b/tests/ui/resolve/multiple_definitions_attribute_merging.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `Dealigned` is defined multiple times - --> $DIR/multiple_definitions_attribute_merging.rs:18:1 + --> $DIR/multiple_definitions_attribute_merging.rs:13:1 | LL | struct Dealigned(u8, T); | --------------------------- previous definition of the type `Dealigned` here @@ -7,21 +7,8 @@ LL | struct Dealigned(u8, T); LL | struct Dealigned(u8, T); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Dealigned` redefined here | - = error: internal compiler error: compiler/rustc_mir_transform/src/check_packed_ref.rs:LL:CC: builtin derive created an unaligned reference - --> $DIR/multiple_definitions_attribute_merging.rs:18:25 - | -LL | #[derive(PartialEq)] - | --------- in this derive macro expansion -LL | #[repr(C)] -LL | struct Dealigned(u8, T); - | ^ - + = note: `Dealigned` must be defined only once in the type namespace of this module -Box -query stack during panic: -#0 [mir_built] building MIR for `::eq` -#1 [check_unsafety] unsafety-checking `::eq` -... and 1 other queries... use `env RUST_BACKTRACE=1` to see the full query stack -error: aborting due to 2 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/static/duplicated-fields-issue-124464.rs b/tests/ui/static/duplicated-fields-issue-124464.rs index 60609edbfebb6..2997dcd600bc7 100644 --- a/tests/ui/static/duplicated-fields-issue-124464.rs +++ b/tests/ui/static/duplicated-fields-issue-124464.rs @@ -3,8 +3,6 @@ enum TestOption { TestSome(T), - TestSome(T), -//~^ ERROR the name `TestSome` is defined multiple times } pub struct Request { diff --git a/tests/ui/static/duplicated-fields-issue-124464.stderr b/tests/ui/static/duplicated-fields-issue-124464.stderr index a36192ae8d69d..5a2f3a74e6a61 100644 --- a/tests/ui/static/duplicated-fields-issue-124464.stderr +++ b/tests/ui/static/duplicated-fields-issue-124464.stderr @@ -1,22 +1,11 @@ -error[E0428]: the name `TestSome` is defined multiple times - --> $DIR/duplicated-fields-issue-124464.rs:6:5 - | -LL | TestSome(T), - | ----------- previous definition of the type `TestSome` here -LL | TestSome(T), - | ^^^^^^^^^^^ `TestSome` redefined here - | - = note: `TestSome` must be defined only once in the type namespace of this enum - error[E0124]: field `bar` is already declared - --> $DIR/duplicated-fields-issue-124464.rs:12:5 + --> $DIR/duplicated-fields-issue-124464.rs:10:5 | LL | bar: TestOption, | -------------------- `bar` first declared here LL | bar: u8, | ^^^^^^^ field already declared -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0124, E0428. -For more information about an error, try `rustc --explain E0124`. +For more information about this error, try `rustc --explain E0124`. diff --git a/tests/ui/traits/issue-106072.rs b/tests/ui/traits/issue-106072.rs index 74a8893d38b07..73b4ce8fbb9b0 100644 --- a/tests/ui/traits/issue-106072.rs +++ b/tests/ui/traits/issue-106072.rs @@ -1,4 +1,4 @@ #[derive(Clone)] -struct Foo; //~ ERROR: expected a type, found a trait +struct Foo; trait Foo {} //~ ERROR: the name `Foo` is defined multiple times fn main() {} diff --git a/tests/ui/traits/issue-106072.stderr b/tests/ui/traits/issue-106072.stderr index ccee54cecf498..db37d02ece1f6 100644 --- a/tests/ui/traits/issue-106072.stderr +++ b/tests/ui/traits/issue-106072.stderr @@ -8,15 +8,6 @@ LL | trait Foo {} | = note: `Foo` must be defined only once in the type namespace of this module -error[E0782]: expected a type, found a trait - --> $DIR/issue-106072.rs:2:8 - | -LL | #[derive(Clone)] - | ----- in this derive macro expansion -LL | struct Foo; - | ^^^ - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -Some errors have detailed explanations: E0428, E0782. -For more information about an error, try `rustc --explain E0428`. +For more information about this error, try `rustc --explain E0428`. diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.rs b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs index 4fccaf1d84f3c..65fa514ce6570 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-bounds.rs +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.rs @@ -6,8 +6,8 @@ fn produce() -> for; //~ ERROR the name `A` is defined multiple times + enum B {} + struct A; }>> Trait {} //~ ERROR cannot find trait `Trait` in this scope fn main() {} diff --git a/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr index ffc238c3f3436..0fd41a209783c 100644 --- a/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr +++ b/tests/ui/traits/non_lifetime_binders/bad-bounds.stderr @@ -1,13 +1,3 @@ -error[E0428]: the name `A` is defined multiple times - --> $DIR/bad-bounds.rs:10:5 - | -LL | enum A {} - | ------ previous definition of the type `A` here -LL | struct A; - | ^^^^^^^^^^^^ `A` redefined here - | - = note: `A` must be defined only once in the type namespace of this block - error[E0404]: expected trait, found type parameter `A` --> $DIR/bad-bounds.rs:6:24 | @@ -17,7 +7,7 @@ LL | fn produce() -> for; LL | | }>> Trait {} | |__^ not a trait @@ -35,12 +25,12 @@ LL | fn produce() -> for; LL | | }>> Trait {} | |__^ -error: aborting due to 4 previous errors +error: aborting due to 3 previous errors -Some errors have detailed explanations: E0404, E0405, E0428. +Some errors have detailed explanations: E0404, E0405. For more information about an error, try `rustc --explain E0404`. diff --git a/tests/ui/use/use-self-at-end-2.e2015.stderr b/tests/ui/use/use-self-at-end-2.e2015.stderr new file mode 100644 index 0000000000000..9901b6b93ed55 --- /dev/null +++ b/tests/ui/use/use-self-at-end-2.e2015.stderr @@ -0,0 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/use-self-at-end-2.rs:14:18 + | +LL | type H = super::Struct::self; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path + | +LL - type H = super::Struct::self; +LL + type H = ::self; + | + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/use-self-at-end-2.rs:15:18 + | +LL | type J = super::Trait::self; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type J = dyn super::Trait::self; + | +++ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/use/use-self-at-end-2.e2018.stderr b/tests/ui/use/use-self-at-end-2.e2018.stderr new file mode 100644 index 0000000000000..2cc518438b7eb --- /dev/null +++ b/tests/ui/use/use-self-at-end-2.e2018.stderr @@ -0,0 +1,29 @@ +error[E0223]: ambiguous associated type + --> $DIR/use-self-at-end-2.rs:14:18 + | +LL | type H = super::Struct::self; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path + | +LL - type H = super::Struct::self; +LL + type H = ::self; + | + +warning: trait objects without an explicit `dyn` are deprecated + --> $DIR/use-self-at-end-2.rs:15:18 + | +LL | type J = super::Trait::self; + | ^^^^^^^^^^^^^^^^^^ + | + = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! + = note: for more information, see + = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: if this is a dyn-compatible trait, use `dyn` + | +LL | type J = dyn super::Trait::self; + | +++ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0223`. diff --git a/tests/ui/use/use-self-at-end-2.e2021.stderr b/tests/ui/use/use-self-at-end-2.e2021.stderr new file mode 100644 index 0000000000000..a2f77ab0795c9 --- /dev/null +++ b/tests/ui/use/use-self-at-end-2.e2021.stderr @@ -0,0 +1,27 @@ +error[E0223]: ambiguous associated type + --> $DIR/use-self-at-end-2.rs:14:18 + | +LL | type H = super::Struct::self; + | ^^^^^^^^^^^^^^^^^^^ + | +help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path + | +LL - type H = super::Struct::self; +LL + type H = ::self; + | + +error[E0782]: expected a type, found a trait + --> $DIR/use-self-at-end-2.rs:15:18 + | +LL | type J = super::Trait::self; + | ^^^^^^^^^^^^^^^^^^ + | +help: you can add the `dyn` keyword if you want a trait object + | +LL | type J = dyn super::Trait::self; + | +++ + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0223, E0782. +For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/use/use-self-at-end-2.rs b/tests/ui/use/use-self-at-end-2.rs new file mode 100644 index 0000000000000..bb794d39e36f4 --- /dev/null +++ b/tests/ui/use/use-self-at-end-2.rs @@ -0,0 +1,26 @@ +//@ revisions: e2015 e2018 e2021 +//@ [e2015] edition: 2015 +//@ [e2018] edition: 2018 +//@ [e2021] edition: 2021.. + +pub mod x { + pub struct Struct; + pub enum Enum {} + pub trait Trait {} + + pub mod y { + pub mod z {} + + type H = super::Struct::self; //~ ERROR: ambiguous associated type + type J = super::Trait::self; + //[e2015]~^ WARN: trait objects without an explicit `dyn` are deprecated + //[e2015]~^^ WARN: this is accepted in the current edition + //[e2018]~^^^ WARN: trait objects without an explicit `dyn` are deprecated + //[e2018]~^^^^ WARN: this is accepted in the current edition + //[e2021]~^^^^^ ERROR: expected a type, found a trait + } +} + +pub mod z {} + +fn main() {} diff --git a/tests/ui/use/use-self-at-end.e2015.stderr b/tests/ui/use/use-self-at-end.e2015.stderr index d77045b45941b..5baca45f3ed9e 100644 --- a/tests/ui/use/use-self-at-end.e2015.stderr +++ b/tests/ui/use/use-self-at-end.e2015.stderr @@ -161,7 +161,7 @@ LL | pub use super::Enum::{self}; = note: `Enum` must be defined only once in the type namespace of this module error[E0252]: the name `Trait` is defined multiple times - --> $DIR/use-self-at-end.rs:88:32 + --> $DIR/use-self-at-end.rs:83:32 | LL | pub use super::Trait::self; | ------------------ previous import of the trait `Trait` here @@ -193,25 +193,25 @@ LL | pub use super::Struct::{self}; | ^^^^^^ `Struct` is a struct, not a module error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:92:24 + --> $DIR/use-self-at-end.rs:87:24 | LL | pub use super::self::y::z; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:93:24 + --> $DIR/use-self-at-end.rs:88:24 | LL | pub use super::self::y::z as z3; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:94:24 + --> $DIR/use-self-at-end.rs:89:24 | LL | pub use super::self::y::{z}; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:95:24 + --> $DIR/use-self-at-end.rs:90:24 | LL | pub use super::self::y::{z as z4}; | ^^^^ can only be used in path start position or last position @@ -229,7 +229,7 @@ LL | type G = z::self::self; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:91:25 + --> $DIR/use-self-at-end.rs:86:25 | LL | type K = super::self::y::z; | ^^^^ can only be used in path start position or last position @@ -270,33 +270,7 @@ error[E0573]: expected type, found module `::self` LL | type F = ::self; | ^^^^^^ not a type -error[E0223]: ambiguous associated type - --> $DIR/use-self-at-end.rs:68:18 - | -LL | type H = super::Struct::self; - | ^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path - | -LL - type H = super::Struct::self; -LL + type H = ::self; - | - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/use-self-at-end.rs:80:18 - | -LL | type J = super::Trait::self; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2021! - = note: for more information, see - = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default -help: if this is a dyn-compatible trait, use `dyn` - | -LL | type J = dyn super::Trait::self; - | +++ - -error: aborting due to 34 previous errors; 1 warning emitted +error: aborting due to 33 previous errors -Some errors have detailed explanations: E0223, E0252, E0432, E0433, E0573. -For more information about an error, try `rustc --explain E0223`. +Some errors have detailed explanations: E0252, E0432, E0433, E0573. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/use/use-self-at-end.e2018.stderr b/tests/ui/use/use-self-at-end.e2018.stderr index 65cba69dd4cdc..0cb0b9a9d2e1a 100644 --- a/tests/ui/use/use-self-at-end.e2018.stderr +++ b/tests/ui/use/use-self-at-end.e2018.stderr @@ -163,7 +163,7 @@ LL | pub use super::Enum::{self}; = note: `Enum` must be defined only once in the type namespace of this module error[E0252]: the name `Trait` is defined multiple times - --> $DIR/use-self-at-end.rs:88:32 + --> $DIR/use-self-at-end.rs:83:32 | LL | pub use super::Trait::self; | ------------------ previous import of the trait `Trait` here @@ -195,25 +195,25 @@ LL | pub use super::Struct::{self}; | ^^^^^^ `Struct` is a struct, not a module error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:92:24 + --> $DIR/use-self-at-end.rs:87:24 | LL | pub use super::self::y::z; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:93:24 + --> $DIR/use-self-at-end.rs:88:24 | LL | pub use super::self::y::z as z3; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:94:24 + --> $DIR/use-self-at-end.rs:89:24 | LL | pub use super::self::y::{z}; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:95:24 + --> $DIR/use-self-at-end.rs:90:24 | LL | pub use super::self::y::{z as z4}; | ^^^^ can only be used in path start position or last position @@ -231,7 +231,7 @@ LL | type G = z::self::self; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:91:25 + --> $DIR/use-self-at-end.rs:86:25 | LL | type K = super::self::y::z; | ^^^^ can only be used in path start position or last position @@ -272,33 +272,7 @@ error[E0425]: cannot find crate `self` in the list of imported crates LL | type F = ::self; | ^^^^ not found in the list of imported crates -error[E0223]: ambiguous associated type - --> $DIR/use-self-at-end.rs:68:18 - | -LL | type H = super::Struct::self; - | ^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path - | -LL - type H = super::Struct::self; -LL + type H = ::self; - | - -warning: trait objects without an explicit `dyn` are deprecated - --> $DIR/use-self-at-end.rs:80:18 - | -LL | type J = super::Trait::self; - | ^^^^^^^^^^^^^^^^^^ - | - = warning: this is accepted in the current edition (Rust 2018) but is a hard error in Rust 2021! - = note: for more information, see - = note: `#[warn(bare_trait_objects)]` (part of `#[warn(rust_2021_compatibility)]`) on by default -help: if this is a dyn-compatible trait, use `dyn` - | -LL | type J = dyn super::Trait::self; - | +++ - -error: aborting due to 36 previous errors; 1 warning emitted +error: aborting due to 35 previous errors -Some errors have detailed explanations: E0223, E0252, E0425, E0432, E0433, E0573. -For more information about an error, try `rustc --explain E0223`. +Some errors have detailed explanations: E0252, E0425, E0432, E0433, E0573. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/use/use-self-at-end.e2021.stderr b/tests/ui/use/use-self-at-end.e2021.stderr index 9809179144b7c..0cb0b9a9d2e1a 100644 --- a/tests/ui/use/use-self-at-end.e2021.stderr +++ b/tests/ui/use/use-self-at-end.e2021.stderr @@ -163,7 +163,7 @@ LL | pub use super::Enum::{self}; = note: `Enum` must be defined only once in the type namespace of this module error[E0252]: the name `Trait` is defined multiple times - --> $DIR/use-self-at-end.rs:88:32 + --> $DIR/use-self-at-end.rs:83:32 | LL | pub use super::Trait::self; | ------------------ previous import of the trait `Trait` here @@ -195,25 +195,25 @@ LL | pub use super::Struct::{self}; | ^^^^^^ `Struct` is a struct, not a module error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:92:24 + --> $DIR/use-self-at-end.rs:87:24 | LL | pub use super::self::y::z; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:93:24 + --> $DIR/use-self-at-end.rs:88:24 | LL | pub use super::self::y::z as z3; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:94:24 + --> $DIR/use-self-at-end.rs:89:24 | LL | pub use super::self::y::{z}; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:95:24 + --> $DIR/use-self-at-end.rs:90:24 | LL | pub use super::self::y::{z as z4}; | ^^^^ can only be used in path start position or last position @@ -231,7 +231,7 @@ LL | type G = z::self::self; | ^^^^ can only be used in path start position or last position error[E0433]: `self` in paths can only be used in start position or last position - --> $DIR/use-self-at-end.rs:91:25 + --> $DIR/use-self-at-end.rs:86:25 | LL | type K = super::self::y::z; | ^^^^ can only be used in path start position or last position @@ -272,30 +272,7 @@ error[E0425]: cannot find crate `self` in the list of imported crates LL | type F = ::self; | ^^^^ not found in the list of imported crates -error[E0223]: ambiguous associated type - --> $DIR/use-self-at-end.rs:68:18 - | -LL | type H = super::Struct::self; - | ^^^^^^^^^^^^^^^^^^^ - | -help: if there were a trait named `Example` with associated type `self` implemented for `x::Struct`, you could use the fully-qualified path - | -LL - type H = super::Struct::self; -LL + type H = ::self; - | - -error[E0782]: expected a type, found a trait - --> $DIR/use-self-at-end.rs:80:18 - | -LL | type J = super::Trait::self; - | ^^^^^^^^^^^^^^^^^^ - | -help: you can add the `dyn` keyword if you want a trait object - | -LL | type J = dyn super::Trait::self; - | +++ - -error: aborting due to 37 previous errors +error: aborting due to 35 previous errors -Some errors have detailed explanations: E0223, E0252, E0425, E0432, E0433, E0573, E0782. -For more information about an error, try `rustc --explain E0223`. +Some errors have detailed explanations: E0252, E0425, E0432, E0433, E0573. +For more information about an error, try `rustc --explain E0252`. diff --git a/tests/ui/use/use-self-at-end.rs b/tests/ui/use/use-self-at-end.rs index 29097bc3dffb8..4d8ffc057d643 100644 --- a/tests/ui/use/use-self-at-end.rs +++ b/tests/ui/use/use-self-at-end.rs @@ -65,7 +65,7 @@ pub mod x { pub use z::{self::{self}}; //~ ERROR `self` in paths can only be used in start position or last position pub use z::{self::{self as z2}}; //~ ERROR `self` in paths can only be used in start position - type H = super::Struct::self; //~ ERROR ambiguous associated type + type H = super::Struct::self; // silenced due to duplicate imports pub use super::Struct::self; //~ ERROR unresolved import `super::Struct` pub use super::Struct::self as Struct1; //~ ERROR unresolved import `super::Struct` pub use super::Struct::{self}; //~ ERROR unresolved import `super::Struct` @@ -77,12 +77,7 @@ pub mod x { pub use super::Enum::{self}; //~ ERROR the name `Enum` is defined multiple times pub use super::Enum::{self as Enum2}; - type J = super::Trait::self; - //[e2015]~^ WARN trait objects without an explicit `dyn` are deprecated - //[e2015]~^^ WARN this is accepted in the current edition - //[e2018]~^^^ WARN trait objects without an explicit `dyn` are deprecated - //[e2018]~^^^^ WARN this is accepted in the current edition - //[e2021]~^^^^^ ERROR expected a type, found a trait + type J = super::Trait::self; // silenced due to duplicate imports pub use super::Trait::self; pub use super::Trait::self as Trait1; pub use super::Trait::{self}; //~ ERROR the name `Trait` is defined multiple times From 73bafeb8ec3b68f70b798bfbc7b4404bd058f9de Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 13 Sep 2026 20:46:47 +0800 Subject: [PATCH 0485/1309] Add regression tests for import module typo suggestions --- ...d-module-typo-inaccessible-issue-131366.rs | 19 +++++++++ ...dule-typo-inaccessible-issue-131366.stderr | 15 +++++++ .../nested-module-typo-issue-131366.rs | 35 +++++++++++++++++ .../nested-module-typo-issue-131366.stderr | 39 +++++++++++++++++++ 4 files changed, 108 insertions(+) create mode 100644 tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs create mode 100644 tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr create mode 100644 tests/ui/imports/nested-module-typo-issue-131366.rs create mode 100644 tests/ui/imports/nested-module-typo-issue-131366.stderr diff --git a/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs new file mode 100644 index 0000000000000..39dc8cd381268 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.rs @@ -0,0 +1,19 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Similar spelling does not make a private module or a non-module importable. + +//@ edition: 2021 +#![allow(unused_imports, dead_code)] + +mod private { + mod collections { pub struct Item; } +} +use private::collection::Item; +//~^ ERROR unresolved import `private::collection` + +mod non_module { + pub struct Collections; +} +use non_module::Collection::Item; +//~^ ERROR unresolved import `non_module::Collection` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr new file mode 100644 index 0000000000000..020711207ef38 --- /dev/null +++ b/tests/ui/imports/nested-module-typo-inaccessible-issue-131366.stderr @@ -0,0 +1,15 @@ +error[E0432]: unresolved import `private::collection` + --> $DIR/nested-module-typo-inaccessible-issue-131366.rs:10:14 + | +LL | use private::collection::Item; + | ^^^^^^^^^^ could not find `collection` in `private` + +error[E0432]: unresolved import `non_module::Collection` + --> $DIR/nested-module-typo-inaccessible-issue-131366.rs:16:17 + | +LL | use non_module::Collection::Item; + | ^^^^^^^^^^ could not find `Collection` in `non_module` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. diff --git a/tests/ui/imports/nested-module-typo-issue-131366.rs b/tests/ui/imports/nested-module-typo-issue-131366.rs new file mode 100644 index 0000000000000..ff16cd129d0ff --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.rs @@ -0,0 +1,35 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Suggest accessible, similarly named modules within the resolved import prefix. + +//@ edition: 2021 +#![allow(unused_imports, dead_code)] + +use std::collection::HashMap; +//~^ ERROR unresolved import `std::collection` + +mod local { + pub mod collections { + pub struct Item; + } + pub use collections as containers; + pub enum Choices { First } +} + +use local::collection::Item; +//~^ ERROR unresolved import `local::collection` +use local::container::Item as Alias; +//~^ ERROR unresolved import `local::container` +use local::Choice::First; +//~^ ERROR unresolved import `local::Choice` + +mod root_module {} +use crate::root_modul::*; +//~^ ERROR unresolved import `crate::root_modul` + +macro_rules! import { + ($module:ident) => { use local::$module::Item as MacroItem; }; +} +import!(collection); +//~^ ERROR unresolved import `local::collection` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.stderr b/tests/ui/imports/nested-module-typo-issue-131366.stderr new file mode 100644 index 0000000000000..3666417c4107c --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.stderr @@ -0,0 +1,39 @@ +error[E0432]: unresolved import `std::collection` + --> $DIR/nested-module-typo-issue-131366.rs:7:10 + | +LL | use std::collection::HashMap; + | ^^^^^^^^^^ could not find `collection` in `std` + +error[E0432]: unresolved import `local::collection` + --> $DIR/nested-module-typo-issue-131366.rs:18:12 + | +LL | use local::collection::Item; + | ^^^^^^^^^^ could not find `collection` in `local` + +error[E0432]: unresolved import `local::container` + --> $DIR/nested-module-typo-issue-131366.rs:20:12 + | +LL | use local::container::Item as Alias; + | ^^^^^^^^^ could not find `container` in `local` + +error[E0432]: unresolved import `local::Choice` + --> $DIR/nested-module-typo-issue-131366.rs:22:12 + | +LL | use local::Choice::First; + | ^^^^^^ could not find `Choice` in `local` + +error[E0432]: unresolved import `crate::root_modul` + --> $DIR/nested-module-typo-issue-131366.rs:26:12 + | +LL | use crate::root_modul::*; + | ^^^^^^^^^^ could not find `root_modul` in the crate root + +error[E0432]: unresolved import `local::collection` + --> $DIR/nested-module-typo-issue-131366.rs:32:9 + | +LL | import!(collection); + | ^^^^^^^^^^ could not find `collection` in `local` + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0432`. From 23ba1fae5fec0b5535c4ea21d23ded2f2d7304a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 21 Sep 2026 08:58:45 +1000 Subject: [PATCH 0486/1309] Convert `create_err(e).emit()` occurrences to `emit_err(e)` --- compiler/rustc_ast_lowering/src/item.rs | 10 ++-- compiler/rustc_builtin_macros/src/asm.rs | 10 ++-- .../src/proc_macro_harness.rs | 10 ++-- .../rustc_codegen_ssa/src/codegen_attrs.rs | 12 ++--- .../rustc_hir_analysis/src/collect/type_of.rs | 6 +-- .../src/hir_ty_lowering/mod.rs | 13 ++---- compiler/rustc_hir_analysis/src/lib.rs | 10 ++-- compiler/rustc_middle/src/ty/opaque_types.rs | 12 ++--- compiler/rustc_parse/src/parser/expr.rs | 46 ++++++++----------- compiler/rustc_parse/src/parser/pat.rs | 20 ++++---- compiler/rustc_resolve/src/imports.rs | 17 +++---- .../rustc_resolve/src/late/diagnostics.rs | 44 ++++++++---------- 12 files changed, 85 insertions(+), 125 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 1073706499919..f8106bd68d82c 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1759,12 +1759,10 @@ impl<'hir> LoweringContext<'_, 'hir> { if !self.tcx.is_descendant_of(parent_module, did) { // If the restriction path is not an ancestor of the item, // emit an error and recover by lowering the restriction to `Unrestricted`. - self.dcx() - .create_err(RestrictionAncestorOnly { - span: path.span, - kind: resolving_kind, - }) - .emit(); + self.dcx().emit_err(RestrictionAncestorOnly { + span: path.span, + kind: resolving_kind, + }); hir::RestrictionKind::Unrestricted } else { hir::RestrictionKind::Restricted(self.arena.alloc(hir::Path { diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 5039d27a46fb4..12132b797bd56 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -481,12 +481,10 @@ fn expand_preparsed_asm( Some(&idx) => Some(idx), None => { let span = arg.position_span; - ecx.dcx() - .create_err(diagnostics::AsmNoMatchedArgumentName { - name: name.to_owned(), - span: span_in_template(span), - }) - .emit(); + ecx.dcx().emit_err(diagnostics::AsmNoMatchedArgumentName { + name: name.to_owned(), + span: span_in_template(span), + }); None } } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index c35e56a8e850b..2fbce3638e021 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -231,12 +231,10 @@ impl<'a> Visitor<'a> for CollectProcMacros<'a> { if !self.is_proc_macro_crate { let path = &attr.get_normal_item().path; - self.dcx - .create_err(diagnostics::AttributeOnlyUsableWithCrateType { - span: path.span, - path: &pprust::path_to_string(&attr.get_normal_item().path), - }) - .emit(); + self.dcx.emit_err(diagnostics::AttributeOnlyUsableWithCrateType { + span: path.span, + path: &pprust::path_to_string(&attr.get_normal_item().path), + }); return; } diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 496e1ca3ce17e..008b10c784d87 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -497,13 +497,11 @@ fn check_result( let span = find_attr!(tcx, did, TargetFeature{attr_span: span, ..} => *span) .unwrap_or_else(|| tcx.def_span(did)); - tcx.dcx() - .create_err(diagnostics::TargetFeatureDisableOrEnable { - features, - span: Some(span), - missing_features: Some(diagnostics::MissingFeatures), - }) - .emit(); + tcx.dcx().emit_err(diagnostics::TargetFeatureDisableOrEnable { + features, + span: Some(span), + missing_features: Some(diagnostics::MissingFeatures), + }); } } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index 4c7b307c4e146..dc86f2837da8e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -256,10 +256,8 @@ pub(super) fn type_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::EarlyBinder<'_ GenericParamKind::Const { ty, .. } => { let lowered_ty = icx.lower_ty(ty); if !tcx.features().generic_const_parameter_types() && lowered_ty.has_param() { - let guar = tcx - .dcx() - .create_err(ParamInTyOfConstParam { span: ty.span, ty: lowered_ty }) - .emit(); + let guar = + tcx.dcx().emit_err(ParamInTyOfConstParam { span: ty.span, ty: lowered_ty }); Ty::new_error(tcx, guar) } else { lowered_ty diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 309757aa66021..c66416802f0ea 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3512,9 +3512,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { { res } else { - let err = dcx - .create_err(NoVariantNamed { span: variant.span, ident: variant, ty }) - .emit(); + let err = + dcx.emit_err(NoVariantNamed { span: variant.span, ident: variant, ty }); return Ty::new_error(tcx, err); } } else { @@ -3552,8 +3551,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } Ty::new_field_representing_type(tcx, ty, variant_idx, field_idx) } else { - let err = - dcx.create_err(NoFieldOnType { span: ident.span, field: ident, ty }).emit(); + let err = dcx.emit_err(NoFieldOnType { span: ident.span, field: ident, ty }); Ty::new_error(tcx, err) } } @@ -3561,8 +3559,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let index = match field.as_str().parse::() { Ok(idx) => idx, Err(_) => { - let err = - dcx.create_err(NoFieldOnType { span: field.span, field, ty }).emit(); + let err = dcx.emit_err(NoFieldOnType { span: field.span, field, ty }); return Ty::new_error(tcx, err); } }; @@ -3572,7 +3569,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if tys.get(index).is_some() { Ty::new_field_representing_type(tcx, ty, FIRST_VARIANT, index.into()) } else { - let err = dcx.create_err(NoFieldOnType { span: field.span, field, ty }).emit(); + let err = dcx.emit_err(NoFieldOnType { span: field.span, field, ty }); Ty::new_error(tcx, err) } } diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index a01ea8271570f..dbbf068185c23 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -104,12 +104,10 @@ fn check_c_variadic_abi(tcx: TyCtxt<'_>, decl: &hir::FnDecl<'_>, abi: ExternAbi, match abi.supports_c_variadic() { CVariadicStatus::Stable => {} CVariadicStatus::NotSupported => { - tcx.dcx() - .create_err(diagnostics::VariadicFunctionCompatibleConvention { - span, - convention: &format!("{abi}"), - }) - .emit(); + tcx.dcx().emit_err(diagnostics::VariadicFunctionCompatibleConvention { + span, + convention: &format!("{abi}"), + }); } CVariadicStatus::Unstable { feature } => { if !tcx.features().enabled(feature) { diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index f4a3c708e0e68..63146ff7ed765 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -201,14 +201,10 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { Some(GenericArgKind::Const(c1)) => c1, Some(u) => panic!("const mapped to unexpected kind: {u:?}"), None => { - let guar = self - .tcx - .dcx() - .create_err(ConstNotUsedTraitAlias { - ct: ct.to_string(), - span: self.span, - }) - .emit(); + let guar = self.tcx.dcx().emit_err(ConstNotUsedTraitAlias { + ct: ct.to_string(), + span: self.span, + }); ty::Const::new_error(self.tcx, guar) } } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 6bc42a0a40734..31e2d15a5ebb3 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1178,23 +1178,21 @@ impl<'a> Parser<'a> { { err.cancel(); let type_str = pprust::path_to_string(&path); - self.dcx() - .create_err(crate::diagnostics::ParenthesesWithStructFields { - span, - braces_for_struct: crate::diagnostics::BracesForStructLiteral { - first: open_paren, - second: close_paren, - r#type: type_str.clone(), - }, - no_fields_for_fn: crate::diagnostics::NoFieldsForFnCall { - r#type: type_str, - fields: fields - .into_iter() - .map(|field| field.span.until(field.expr.span)) - .collect(), - }, - }) - .emit() + self.dcx().emit_err(crate::diagnostics::ParenthesesWithStructFields { + span, + braces_for_struct: crate::diagnostics::BracesForStructLiteral { + first: open_paren, + second: close_paren, + r#type: type_str.clone(), + }, + no_fields_for_fn: crate::diagnostics::NoFieldsForFnCall { + r#type: type_str, + fields: fields + .into_iter() + .map(|field| field.span.until(field.expr.span)) + .collect(), + }, + }) } else { err.emit() }; @@ -3654,16 +3652,12 @@ impl<'a> Parser<'a> { )?; let guar = if is_underscore_entry_point { - self.dcx() - .create_err(crate::diagnostics::StructLiteralPlaceholderPath { span }) - .emit() + self.dcx().emit_err(crate::diagnostics::StructLiteralPlaceholderPath { span }) } else { - self.dcx() - .create_err(crate::diagnostics::StructLiteralWithoutPathLate { - span: expr.span, - suggestion_span: expr.span.shrink_to_lo(), - }) - .emit() + self.dcx().emit_err(crate::diagnostics::StructLiteralWithoutPathLate { + span: expr.span, + suggestion_span: expr.span.shrink_to_lo(), + }) }; Ok(Some(self.mk_expr_err(expr.span, guar))) diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 64cc8ad9812f2..8508941f459f2 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1936,17 +1936,15 @@ impl<'a> Parser<'a> { let subpat = if let Some(box_span) = is_box { let prefix_span = box_span.until(boxed_span); - self.dcx() - .create_err(diagnostics::BoxPatsRemoved { - span: box_span, - sugg_deref_macro_call: diagnostics::UseDerefMacro { - field: Some((prefix_span, fieldname)), - before: boxed_span.shrink_to_lo(), - after: hi.shrink_to_hi(), - }, - sugg_removal: prefix_span, - }) - .emit(); + self.dcx().emit_err(diagnostics::BoxPatsRemoved { + span: box_span, + sugg_deref_macro_call: diagnostics::UseDerefMacro { + field: Some((prefix_span, fieldname)), + before: boxed_span.shrink_to_lo(), + after: hi.shrink_to_hi(), + }, + sugg_removal: prefix_span, + }); self.mk_pat(lo.to(hi), PatKind::Deref(Box::new(fieldpat))) } else { diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 38ad390c23b88..a19207d6fbacc 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1225,9 +1225,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span_bug!(import.span, "inconsistent resolution for an import"); } } else if self.privacy_errors.is_empty() { - self.dcx() - .create_err(CannotDetermineImportResolution { span: import.span }) - .emit(); + self.dcx().emit_err(CannotDetermineImportResolution { span: import.span }); } module @@ -1459,9 +1457,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span_bug!(import.span, "inconsistent resolution for an import"); } } else if this.privacy_errors.is_empty() { - this.dcx() - .create_err(CannotDetermineImportResolution { span: import.span }) - .emit(); + this.dcx().emit_err(CannotDetermineImportResolution { span: import.span }); } } Err(..) => { @@ -1681,12 +1677,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { diagnostic: diagnostic.into(), }); } else if ns == TypeNS { - let err = if crate_private_reexport { - self.dcx().create_err(CannotBeReexportedCratePublicNS { span: import.span, ident }) + if crate_private_reexport { + self.dcx().emit_err(CannotBeReexportedCratePublicNS { span: import.span, ident }); } else { - self.dcx().create_err(CannotBeReexportedPrivateNS { span: import.span, ident }) - }; - err.emit(); + self.dcx().emit_err(CannotBeReexportedPrivateNS { span: import.span, ident }); + } } else { let mut err = if crate_private_reexport { self.dcx().create_err(CannotBeReexportedCratePublic { span: import.span, ident }) diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 4a6846d09a8c4..611e7147757fe 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4132,13 +4132,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &self, lifetime_ref: &ast::Lifetime, ) -> ErrorGuaranteed { - self.r - .dcx() - .create_err(diagnostics::ParamInTyOfConstParam { - span: lifetime_ref.ident.span, - name: lifetime_ref.ident.name, - }) - .emit() + self.r.dcx().emit_err(diagnostics::ParamInTyOfConstParam { + span: lifetime_ref.ident.span, + name: lifetime_ref.ident.name, + }) } /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`. @@ -4150,31 +4147,26 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { lifetime_ref: &ast::Lifetime, ) -> ErrorGuaranteed { match cause { - NoConstantGenericsReason::IsEnumDiscriminant => self - .r - .dcx() - .create_err(diagnostics::ParamInEnumDiscriminant { + NoConstantGenericsReason::IsEnumDiscriminant => { + self.r.dcx().emit_err(diagnostics::ParamInEnumDiscriminant { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInEnumDiscriminant::Lifetime, }) - .emit(), + } NoConstantGenericsReason::NonTrivialConstArg => { assert!(!self.r.features.generic_const_exprs()); - self.r - .dcx() - .create_err(diagnostics::ParamInNonTrivialAnonConst { - span: lifetime_ref.ident.span, - name: lifetime_ref.ident.name, - param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, - help: self.r.tcx.sess.is_nightly_build() - && !self.r.features.min_generic_const_args(), - is_gca: self.r.features.generic_const_args(), - help_gca: self.r.features.generic_const_args(), - help_suggest_gca: self.r.tcx.sess.is_nightly_build() - && !self.r.features.generic_const_args(), - }) - .emit() + self.r.dcx().emit_err(diagnostics::ParamInNonTrivialAnonConst { + span: lifetime_ref.ident.span, + name: lifetime_ref.ident.name, + param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, + help: self.r.tcx.sess.is_nightly_build() + && !self.r.features.min_generic_const_args(), + is_gca: self.r.features.generic_const_args(), + help_gca: self.r.features.generic_const_args(), + help_suggest_gca: self.r.tcx.sess.is_nightly_build() + && !self.r.features.generic_const_args(), + }) } } } From 30b8dfc3533d8104fff5c9db8adc838b4e4bf471 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Sep 2026 07:33:25 +1000 Subject: [PATCH 0487/1309] Remove `G` generic param from `Diag<'_, G>` It encodes the `emit` behaviour, one of: - `BugAbort`: Abort as a bug. - `FatalAbort`: Abort as a fatal error. - `ErrorGuaranteed`: Return an `ErrorGuaranteed` (the default). - `()`: return `()`. This is useful but `Diag` is very widely used and it's arguably not useful enough to be worth the generic parameter. This commit removes it. Benefits: - Many fewer generic parameters, including many functions where the genericity is entirely uninteresting. This includes every `Diagnostic::into_diag` and `Subdiagnostic::add_to_diag`. Removes the need for the comment about `` on `trait Diagnostic`. - No `PhantomData` in `Diag`. - Makes bootstrapping a bit faster. The downside is there is no longer a single `emit` method. - Getting a `!` return type requires calling `emit_bug` or `emit_fatal`. This only affects a few call sites. - Getting an `ErrorGuaranteed` return type requires calling `emit_err`. This affects a lot of call sites. (It arguably makes call sites more self-documenting.) - Using the wrong `emit_*` on a diagnostic causes a runtime abort, which previously couldn't occur. Seems unlikely, but it's not impossible. - Note: If no particular return type is needed, `emit` can be used for any diagnostic. (Bug/fatal diagnostics will still trigger abort.) --- compiler/rustc_abi/src/lib.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_ast_passes/src/diagnostics.rs | 2 +- .../src/attributes/cfg_select.rs | 12 +- compiler/rustc_attr_parsing/src/context.rs | 10 +- .../rustc_attr_parsing/src/diagnostics.rs | 14 +- compiler/rustc_attr_parsing/src/interface.rs | 2 +- compiler/rustc_attr_parsing/src/parser.rs | 2 +- .../src/diagnostics/explain_borrow.rs | 16 +- .../rustc_borrowck/src/diagnostics/mod.rs | 8 +- .../src/diagnostics/opaque_types.rs | 2 +- .../src/diagnostics/region_name.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/region_infer/opaque_types/mod.rs | 2 +- .../rustc_borrowck/src/session_diagnostics.rs | 6 +- .../rustc_borrowck/src/universal_regions.rs | 2 +- compiler/rustc_builtin_macros/src/asm.rs | 10 +- compiler/rustc_builtin_macros/src/assert.rs | 2 +- compiler/rustc_builtin_macros/src/cfg.rs | 2 +- .../rustc_builtin_macros/src/diagnostics.rs | 10 +- compiler/rustc_builtin_macros/src/format.rs | 4 +- compiler/rustc_builtin_macros/src/iter.rs | 2 +- .../rustc_builtin_macros/src/pattern_type.rs | 2 +- .../rustc_builtin_macros/src/source_util.rs | 8 +- compiler/rustc_builtin_macros/src/test.rs | 2 +- .../src/test_binder_constraints.rs | 2 +- compiler/rustc_builtin_macros/src/util.rs | 6 +- .../rustc_builtin_macros/src/view_type.rs | 2 +- .../rustc_codegen_llvm/src/diagnostics.rs | 10 +- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/diagnostics.rs | 16 +- .../src/check_consts/check.rs | 6 +- .../rustc_const_eval/src/const_eval/error.rs | 8 +- compiler/rustc_const_eval/src/diagnostics.rs | 2 +- compiler/rustc_errors/src/decorate_diag.rs | 8 +- compiler/rustc_errors/src/diagnostic.rs | 216 +++++++----------- compiler/rustc_errors/src/diagnostic_impls.rs | 2 +- compiler/rustc_errors/src/lib.rs | 99 ++++---- compiler/rustc_expand/src/expand.rs | 4 +- compiler/rustc_expand/src/mbe/diagnostics.rs | 4 +- compiler/rustc_expand/src/mbe/macro_parser.rs | 6 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 18 +- compiler/rustc_expand/src/module.rs | 2 +- .../rustc_expand/src/proc_macro_server.rs | 3 +- compiler/rustc_hir/src/lints.rs | 2 +- .../src/check/always_applicable.rs | 8 +- .../rustc_hir_analysis/src/check/check.rs | 12 +- .../src/check/compare_eii.rs | 8 +- .../src/check/compare_impl_item.rs | 32 +-- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 14 +- .../rustc_hir_analysis/src/check_unused.rs | 4 +- .../src/coherence/builtin.rs | 2 +- .../src/coherence/inherent_impls_overlap.rs | 4 +- .../rustc_hir_analysis/src/coherence/mod.rs | 6 +- .../src/coherence/orphan.rs | 2 +- .../src/coherence/unsafety.rs | 6 +- compiler/rustc_hir_analysis/src/collect.rs | 10 +- .../rustc_hir_analysis/src/collect/dump.rs | 2 +- .../src/collect/generics_of.rs | 4 +- .../src/collect/resolve_bound_vars.rs | 2 +- .../rustc_hir_analysis/src/collect/type_of.rs | 2 +- .../src/collect/type_of/opaque.rs | 2 +- .../rustc_hir_analysis/src/diagnostics.rs | 8 +- .../wrong_number_of_generic_args.rs | 34 +-- .../src/hir_ty_lowering/bounds.rs | 2 +- .../src/hir_ty_lowering/dyn_trait.rs | 12 +- .../src/hir_ty_lowering/errors.rs | 30 +-- .../src/hir_ty_lowering/generics.rs | 10 +- .../src/hir_ty_lowering/mod.rs | 12 +- .../rustc_hir_analysis/src/impl_wf_check.rs | 4 +- .../src/impl_wf_check/min_specialization.rs | 8 +- compiler/rustc_hir_typeck/src/callee.rs | 4 +- compiler/rustc_hir_typeck/src/cast.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 +- compiler/rustc_hir_typeck/src/diagnostics.rs | 16 +- compiler/rustc_hir_typeck/src/expr.rs | 24 +- .../rustc_hir_typeck/src/fn_ctxt/_impl.rs | 12 +- .../rustc_hir_typeck/src/fn_ctxt/checks.rs | 20 +- compiler/rustc_hir_typeck/src/inline_asm.rs | 4 +- compiler/rustc_hir_typeck/src/intrinsicck.rs | 34 +-- compiler/rustc_hir_typeck/src/lib.rs | 4 +- .../src/method/prelude_edition_lints.rs | 12 +- compiler/rustc_hir_typeck/src/method/probe.rs | 6 +- .../rustc_hir_typeck/src/method/suggest.rs | 12 +- compiler/rustc_hir_typeck/src/op.rs | 4 +- compiler/rustc_hir_typeck/src/opaque_types.rs | 2 +- compiler/rustc_hir_typeck/src/pat.rs | 32 +-- compiler/rustc_hir_typeck/src/place_op.rs | 4 +- compiler/rustc_hir_typeck/src/upvar.rs | 4 +- compiler/rustc_hir_typeck/src/writeback.rs | 6 +- compiler/rustc_interface/src/interface.rs | 4 +- compiler/rustc_interface/src/passes.rs | 8 +- compiler/rustc_interface/src/util.rs | 4 +- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/context.rs | 8 +- .../src/default_could_be_derived.rs | 4 +- compiler/rustc_lint/src/diagnostics.rs | 60 ++--- compiler/rustc_lint/src/early/diagnostics.rs | 6 +- compiler/rustc_lint/src/if_let_rescope.rs | 2 +- .../rustc_lint/src/impl_trait_overcaptures.rs | 4 +- compiler/rustc_lint/src/levels.rs | 14 +- compiler/rustc_lint/src/non_fmt_panic.rs | 4 +- compiler/rustc_lint/src/nonstandard_style.rs | 4 +- .../src/diagnostics/diagnostic.rs | 4 +- .../src/diagnostics/subdiagnostic.rs | 5 +- compiler/rustc_metadata/src/diagnostics.rs | 12 +- compiler/rustc_middle/src/lint.rs | 8 +- compiler/rustc_middle/src/middle/stability.rs | 4 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_middle/src/ty/layout.rs | 4 +- compiler/rustc_middle/src/ty/opaque_types.rs | 8 +- .../rustc_mir_build/src/check_tail_calls.rs | 76 +++--- compiler/rustc_mir_build/src/diagnostics.rs | 12 +- .../src/thir/pattern/check_match.rs | 2 +- .../src/thir/pattern/const_to_pat.rs | 2 +- .../src/thir/pattern/migration.rs | 2 +- .../rustc_mir_transform/src/diagnostics.rs | 12 +- .../src/lint_tail_expr_drop_order.rs | 2 +- .../rustc_mir_transform/src/pass_manager.rs | 2 +- compiler/rustc_parse/src/diagnostics.rs | 16 +- compiler/rustc_parse/src/lexer/mod.rs | 6 +- .../src/lexer/unescape_error_reporting.rs | 6 +- compiler/rustc_parse/src/lib.rs | 6 +- .../rustc_parse/src/parser/diagnostics.rs | 24 +- compiler/rustc_parse/src/parser/expr.rs | 12 +- compiler/rustc_parse/src/parser/function.rs | 6 +- compiler/rustc_parse/src/parser/generics.rs | 2 +- compiler/rustc_parse/src/parser/item.rs | 4 +- compiler/rustc_parse/src/parser/mod.rs | 4 +- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_parse/src/parser/path.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 4 +- compiler/rustc_parse/src/parser/ty.rs | 6 +- compiler/rustc_passes/src/diagnostics.rs | 8 +- .../src/handle_cycle_error.rs | 6 +- .../rustc_resolve/src/diagnostics/impls.rs | 6 +- compiler/rustc_resolve/src/diagnostics/mod.rs | 6 +- compiler/rustc_resolve/src/late.rs | 6 +- .../rustc_resolve/src/late/diagnostics.rs | 6 +- compiler/rustc_session/src/config.rs | 4 +- compiler/rustc_session/src/config/externs.rs | 6 +- .../rustc_session/src/config/print_request.rs | 2 +- compiler/rustc_session/src/diagnostics.rs | 12 +- compiler/rustc_session/src/parse.rs | 4 +- compiler/rustc_session/src/session.rs | 7 +- .../rustc_trait_selection/src/diagnostics.rs | 24 +- .../src/diagnostics/note_and_explain.rs | 2 +- .../infer/nice_region_error/mod.rs | 2 +- .../nice_region_error/static_impl_trait.rs | 4 +- .../trait_impl_difference.rs | 2 +- .../src/error_reporting/infer/region.rs | 22 +- .../src/error_reporting/traits/ambiguity.rs | 4 +- .../traits/fulfillment_errors.rs | 22 +- .../src/error_reporting/traits/mod.rs | 6 +- .../src/error_reporting/traits/overflow.rs | 6 +- .../src/error_reporting/traits/suggestions.rs | 54 ++--- .../rustc_trait_selection/src/opaque_types.rs | 4 +- .../src/traits/coherence.rs | 6 +- .../src/traits/const_evaluatable.rs | 2 +- .../src/traits/project.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../src/traits/specialize/mod.rs | 8 +- .../src/diagnostics/diagnostic-structs.md | 4 +- src/librustdoc/config.rs | 4 +- src/librustdoc/html/markdown.rs | 2 +- .../passes/collect_intra_doc_links.rs | 8 +- .../passes/lint/check_code_block_syntax.rs | 4 +- .../passes/lint/redundant_explicit_links.rs | 12 +- .../passes/lint/unescaped_backticks.rs | 2 +- src/tools/clippy/clippy_config/src/types.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 2 +- .../clippy_lints/src/empty_line_after.rs | 2 +- .../clippy_lints/src/functions/result.rs | 2 +- .../clippy/clippy_lints/src/if_let_mutex.rs | 2 +- .../clippy_lints/src/implicit_hasher.rs | 2 +- .../clippy_lints/src/large_stack_frames.rs | 2 +- .../clippy/clippy_lints/src/manual_clamp.rs | 2 +- .../matches/significant_drop_in_scrutinee.rs | 2 +- .../clippy_lints/src/matches/single_match.rs | 2 +- .../methods/suspicious_command_arg_space.rs | 2 +- .../src/methods/swap_with_temporary.rs | 2 +- .../src/methods/unnecessary_fold.rs | 2 +- .../src/missing_asserts_for_indexing.rs | 2 +- .../clippy/clippy_lints/src/mutex_atomic.rs | 2 +- .../src/needless_pass_by_value.rs | 2 +- .../src/pointers_in_nomem_asm_block.rs | 2 +- .../clippy/clippy_utils/src/diagnostics.rs | 16 +- src/tools/clippy/clippy_utils/src/sugg.rs | 2 +- src/tools/miri/src/diagnostics.rs | 2 +- .../diagnostic-derive-doc-comment-field.rs | 2 +- ...diagnostic-derive-doc-comment-field.stderr | 2 +- 194 files changed, 840 insertions(+), 886 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b056fdc73d40b..f971ee3c563b8 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -399,8 +399,8 @@ pub enum TargetDataLayoutError<'a> { } #[cfg(feature = "nightly")] -impl Diagnostic<'_, G> for TargetDataLayoutError<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for TargetDataLayoutError<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { match self { TargetDataLayoutError::InvalidAddressSpace { addr_space, err, cause } => { Diag::new(dcx, level, msg!("invalid address space `{$addr_space}` for `{$cause}` in \"data-layout\": {$err}")) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 410823919c523..7ff6a2538c1e7 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1751,7 +1751,7 @@ impl<'hir> LoweringContext<'_, 'hir> { }, feature, ) - .emit(); + .emit_err(); hir::TyKind::Err(guar) } ImplTraitContext::Disallowed(position) => { diff --git a/compiler/rustc_ast_passes/src/diagnostics.rs b/compiler/rustc_ast_passes/src/diagnostics.rs index 4771a87335954..a3cffab3fc4dc 100644 --- a/compiler/rustc_ast_passes/src/diagnostics.rs +++ b/compiler/rustc_ast_passes/src/diagnostics.rs @@ -663,7 +663,7 @@ pub(crate) struct EmptyLabelManySpans(pub Vec); // The derive for `Vec` does multiple calls to `span_label`, adding commas between each impl Subdiagnostic for EmptyLabelManySpans { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_labels(self.0, ""); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs index 53d7044521e5a..6c6793b29f586 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg_select.rs @@ -89,13 +89,13 @@ pub fn parse_cfg_select( let mut branches = CfgSelectBranches::default(); while p.token != token::Eof { - p.recover_from_outer_attributes("`cfg_select` branches").map_err(|e| e.emit())?; + p.recover_from_outer_attributes("`cfg_select` branches").map_err(|e| e.emit_err())?; if p.eat_keyword(exp!(Underscore)) { let underscore = p.prev_token; - p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; + p.expect(exp!(FatArrow)).map_err(|e| e.emit_err())?; - let tts = p.parse_cfg_select_branch_rhs().map_err(|e| e.emit())?; + let tts = p.parse_cfg_select_branch_rhs().map_err(|e| e.emit_err())?; let span = underscore.span.to(p.token.span); match branches.wildcard { @@ -110,7 +110,7 @@ pub fn parse_cfg_select( ShouldEmit::ErrorsAndLints { recovery: Recovery::Allowed }, AllowExprMetavar::Yes, ) - .map_err(|diag| diag.emit())?; + .map_err(|diag| diag.emit_err())?; let cfg_span = meta.span(); let cfg = AttributeParser::parse_single_args( sess, @@ -132,9 +132,9 @@ pub fn parse_cfg_select( &AttributeTemplate::default(), )?; - p.expect(exp!(FatArrow)).map_err(|e| e.emit())?; + p.expect(exp!(FatArrow)).map_err(|e| e.emit_err())?; - let tts = p.parse_cfg_select_branch_rhs().map_err(|e| e.emit())?; + let tts = p.parse_cfg_select_branch_rhs().map_err(|e| e.emit_err())?; let span = cfg_span.to(p.token.span); match branches.wildcard { diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index f936f5aab8265..22a4a069b75c7 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -418,7 +418,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { pub(crate) fn emit_lint( &mut self, lint: &'static Lint, - diagnostic: impl for<'x> Diagnostic<'x, ()> + DynSend + DynSync + 'static, + diagnostic: impl for<'x> Diagnostic<'x> + DynSend + DynSync + 'static, span: impl Into, ) { self.emit_lint_inner( @@ -429,7 +429,7 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { } pub(crate) fn emit_lint_with_sess< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a, ()> + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a> + DynSend + DynSync + 'static, @@ -895,9 +895,9 @@ pub enum ShouldEmit { impl ShouldEmit { pub(crate) fn emit_err(self, diag: Diag<'_>) -> ErrorGuaranteed { match self { - ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(), - ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(), - ShouldEmit::ErrorsAndLints { .. } => diag.emit(), + ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit_err(), + ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit_fatal(), + ShouldEmit::ErrorsAndLints { .. } => diag.emit_err(), ShouldEmit::Nothing => diag.delay_as_bug(), } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index e5f49690f71dc..2c0b85d57c208 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1476,9 +1476,9 @@ pub(crate) enum AttributeParseErrorSuggestions { } impl<'a> AttributeParseError<'a> { - fn render_expected_specific_argument( + fn render_expected_specific_argument( &self, - diag: &mut Diag<'_, G>, + diag: &mut Diag<'_>, possibilities: &[Symbol], strings: bool, ) { @@ -1509,9 +1509,9 @@ impl<'a> AttributeParseError<'a> { } } - fn render_expected_specific_argument_list( + fn render_expected_specific_argument_list( &self, - diag: &mut Diag<'_, G>, + diag: &mut Diag<'_>, possibilities: &[Symbol], strings: bool, ) { @@ -1543,7 +1543,7 @@ impl<'a> AttributeParseError<'a> { } } - fn render_suggestions(&self, diag: &mut Diag<'_, G>) { + fn render_suggestions(&self, diag: &mut Diag<'_>) { let description = self.description(); match &self.suggestions { @@ -1592,8 +1592,8 @@ impl AttributeParseErrorSuggestions { } } -impl<'a, G> Diagnostic<'a, G> for AttributeParseError<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for AttributeParseError<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let name = self.path.to_string(); let description = self.description(); diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 1cecce8fd43ef..48083683b6a7a 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -27,7 +27,7 @@ use crate::{AttributeTemplate, ShouldEmit}; pub struct EmitAttribute( pub Box< - dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a, ()> + dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a> + DynSend + DynSync + 'static, diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs index 8efe5bf4f1f90..c85b1f8fee967 100644 --- a/compiler/rustc_attr_parsing/src/parser.rs +++ b/compiler/rustc_attr_parsing/src/parser.rs @@ -434,7 +434,7 @@ fn expr_to_lit<'sess>( let lit = MetaItemLit { symbol: token_lit.symbol, suffix: token_lit.suffix, - kind: LitKind::Err(err.emit()), + kind: LitKind::Err(err.emit_err()), span: expr.span, }; Ok(Some(lit)) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 429eb85ed9e11..f431374de37ba 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -55,10 +55,10 @@ impl<'tcx> BorrowExplanation<'tcx> { pub(crate) fn is_explained(&self) -> bool { !matches!(self, BorrowExplanation::Unexplained) } - pub(crate) fn add_explanation_to_diagnostic( + pub(crate) fn add_explanation_to_diagnostic( &self, cx: &MirBorrowckCtxt<'_, '_, 'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, borrow_desc: &str, borrow_span: Option, multiple_borrow_span: Option<(Span, Span)>, @@ -437,10 +437,10 @@ impl<'tcx> BorrowExplanation<'tcx> { } } - fn add_object_lifetime_default_note( + fn add_object_lifetime_default_note( &self, tcx: TyCtxt<'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, unsize_ty: Ty<'tcx>, ) { if let ty::Adt(def, args) = unsize_ty.kind() { @@ -494,9 +494,9 @@ impl<'tcx> BorrowExplanation<'tcx> { } } - fn add_lifetime_bound_suggestion_to_diagnostic( + fn add_lifetime_bound_suggestion_to_diagnostic( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, category: &ConstraintCategory<'tcx>, span: Span, region_name: &RegionName, @@ -523,14 +523,14 @@ impl<'tcx> BorrowExplanation<'tcx> { } } -fn suggest_rewrite_if_let( +fn suggest_rewrite_if_let( tcx: TyCtxt<'_>, expr: &hir::Expr<'_>, pat: &str, init: &hir::Expr<'_>, conseq: &hir::Expr<'_>, alt: Option<&hir::Expr<'_>>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, ) { let source_map = tcx.sess.source_map(); err.span_note( diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index 5ebf950358c4f..fadcf92b6ea7a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -642,9 +642,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// /// This is very similar to `fn suggest_static_lifetime_for_gat_from_hrtb` which handles this /// note for failed type tests instead of outlives errors. - fn add_placeholder_from_predicate_note( + fn add_placeholder_from_predicate_note( &self, - diag: &mut Diag<'_, G>, + diag: &mut Diag<'_>, path: &[OutlivesConstraint<'tcx>], ) { let tcx = self.infcx.tcx; @@ -704,9 +704,9 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { /// Add a label to region errors and borrow explanations when outlives constraints arise from /// proving a type implements `Sized` or `Copy`. - fn add_sized_or_copy_bound_info( + fn add_sized_or_copy_bound_info( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, blamed_category: ConstraintCategory<'tcx>, path: &[OutlivesConstraint<'tcx>], ) { diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs index 009dff77efd0f..9bfae5582d9fe 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs @@ -61,7 +61,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { { last_unexpected_hidden_region = Some((hidden_type.span, named_ty, named_key)); - diag.emit() + diag.emit_err() } else { diag.delay_as_bug() } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 0e98e0c0bb604..9436d31ba19e8 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -104,7 +104,7 @@ impl RegionName { } } - pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_, G>) { + pub(crate) fn highlight_region_name(&self, diag: &mut Diag<'_>) { match &self.source { RegionNameSource::NamedLateParamRegion(span) | RegionNameSource::NamedEarlyParamRegion(span) => { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 76af4e2dd5530..75ee675b71232 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -430,7 +430,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. - pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) { + pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) { self.universal_regions().annotate(tcx, err) } diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index ad15c5750b092..9a08218fba8a7 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -171,7 +171,7 @@ fn add_hidden_type<'tcx>( prev.span = prev.span.substitute_dummy(hidden_ty.span); } else { let (Ok(guar) | Err(guar)) = - prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit()); + prev.build_mismatch_error(&hidden_ty, tcx).map(|d| d.emit_err()); *prev = ty::DefinitionSiteHiddenType::new_error(tcx, guar); } } else { diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs index a0f347679b05a..8935aed1e7e00 100644 --- a/compiler/rustc_borrowck/src/session_diagnostics.rs +++ b/compiler/rustc_borrowck/src/session_diagnostics.rs @@ -659,13 +659,13 @@ pub(crate) struct SimdIntrinsicArgConst { pub intrinsic: String, } -pub(crate) struct TailExprDropOrder)> { +pub(crate) struct TailExprDropOrder)> { pub borrowed: Span, pub callback: F, } -impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for TailExprDropOrder { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, F: FnOnce(&mut Diag<'_>)> Diagnostic<'a> for TailExprDropOrder { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { borrowed, callback } = self; let mut diag = Diag::new(dcx, level, "relative drop order changing in Rust 2024") .with_span_label( diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index e494f363879cb..1d55c8f940b83 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -614,7 +614,7 @@ impl<'tcx> UniversalRegions<'tcx> { /// that this region imposes on others. The methods in this file /// handle the part about dumping the inference context internal /// state. - pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_, ()>) { + pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) { match self.defining_ty { DefiningTy::Closure(def_id, args) => { let v = with_no_trimmed_paths!( diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 12132b797bd56..975b2c49b292d 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -314,7 +314,7 @@ fn expand_preparsed_asm( Ok(template_part) => template_part, Err(err) => { return ExpandResult::Ready(Err(match err { - Ok((err, _)) => err.emit(), + Ok((err, _)) => err.emit_err(), Err(guar) => guar, })); } @@ -407,7 +407,7 @@ fn expand_preparsed_asm( if let Some((label, span)) = err.secondary_label { e.span_label(span_in_template(span), label); } - let guar = e.emit(); + let guar = e.emit_err(); return ExpandResult::Ready(Err(guar)); } @@ -600,7 +600,7 @@ pub(super) fn expand_asm<'cx>( MacEager::expr(expr) } Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); DummyResult::any(sp, guar) } }) @@ -630,7 +630,7 @@ pub(super) fn expand_naked_asm<'cx>( MacEager::expr(expr) } Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); DummyResult::any(sp, guar) } }) @@ -663,7 +663,7 @@ pub(super) fn expand_global_asm<'cx>( } } Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); DummyResult::any(sp, guar) } }) diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 106b67d1c8ec7..5f71e02d1350b 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -22,7 +22,7 @@ pub(crate) fn expand_assert<'cx>( let Assert { cond_expr, custom_message } = match parse_assert(cx, span, tts) { Ok(assert) => assert, Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); return ExpandResult::Ready(DummyResult::any(span, guar)); } }; diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs index b34d928146efd..ae3781380b90e 100644 --- a/compiler/rustc_builtin_macros/src/cfg.rs +++ b/compiler/rustc_builtin_macros/src/cfg.rs @@ -46,7 +46,7 @@ fn parse_cfg(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream) -> Result Diagnostic<'a, G> for EnvNotDefinedWithUserMessage { +impl<'a> Diagnostic<'a> for EnvNotDefinedWithUserMessage { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, self.msg_from_user.to_string()); diag.span(self.span); diag @@ -773,7 +773,7 @@ pub(crate) struct FormatUnusedArg { // Allow the singular form to be a subdiagnostic of the multiple-unused // form of diagnostic. impl Subdiagnostic for FormatUnusedArg { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_label( self.span, msg!( @@ -957,8 +957,8 @@ pub(crate) struct AsmClobberNoReg { pub(crate) clobbers: Vec, } -impl<'a, G> Diagnostic<'a, G> for AsmClobberNoReg { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for AsmClobberNoReg { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { Diag::new( dcx, level, diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index f501110fc97d5..e23c057f8a651 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -265,7 +265,7 @@ fn make_format_args( } } } - err.emit() + err.emit_err() } Err(guar) => guar, }; @@ -1156,7 +1156,7 @@ fn expand_format_args_impl<'cx>( } } Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); DummyResult::any(sp, guar) } }) diff --git a/compiler/rustc_builtin_macros/src/iter.rs b/compiler/rustc_builtin_macros/src/iter.rs index 86bf347cd9848..59fabe966b7e1 100644 --- a/compiler/rustc_builtin_macros/src/iter.rs +++ b/compiler/rustc_builtin_macros/src/iter.rs @@ -12,7 +12,7 @@ pub(crate) fn expand<'cx>( let closure = match parse_closure(cx, sp, tts) { Ok(parsed) => parsed, Err(err) => { - return ExpandResult::Ready(DummyResult::any(sp, err.emit())); + return ExpandResult::Ready(DummyResult::any(sp, err.emit_err())); } }; diff --git a/compiler/rustc_builtin_macros/src/pattern_type.rs b/compiler/rustc_builtin_macros/src/pattern_type.rs index 215baf099416b..4d34ba963e4e8 100644 --- a/compiler/rustc_builtin_macros/src/pattern_type.rs +++ b/compiler/rustc_builtin_macros/src/pattern_type.rs @@ -14,7 +14,7 @@ pub(crate) fn expand<'cx>( let (ty, pat) = match parse_pat_ty(cx, tts) { Ok(parsed) => parsed, Err(err) => { - return ExpandResult::Ready(DummyResult::any(sp, err.emit())); + return ExpandResult::Ready(DummyResult::any(sp, err.emit_err())); } }; diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs index 37b2f49c3596d..61fa31b5de254 100644 --- a/compiler/rustc_builtin_macros/src/source_util.rs +++ b/compiler/rustc_builtin_macros/src/source_util.rs @@ -120,7 +120,7 @@ pub(crate) fn expand_include<'cx>( let path = match cx.sess.resolve_path(path.as_str(), sp) { Ok(path) => path, Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); return ExpandResult::Ready(DummyResult::any(sp, guar)); } }; @@ -225,7 +225,7 @@ pub(crate) fn expand_include_str( Err(utf8err) => { let mut err = cx.dcx().struct_span_err(sp, format!("`{path}` wasn't a utf-8 file")); utf8_error(cx.source_map(), path.as_str(), None, &mut err, utf8err, &bytes[..]); - DummyResult::any(sp, err.emit()) + DummyResult::any(sp, err.emit_err()) } }, Err(dummy) => dummy, @@ -270,7 +270,7 @@ fn load_binary_file( let resolved_path = match cx.sess.resolve_path(original_path, macro_span) { Ok(path) => path, Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); return Err(DummyResult::any(macro_span, guar)); } }; @@ -306,7 +306,7 @@ fn load_binary_file( ); } } - let guar = err.emit(); + let guar = err.emit_err(); Err(DummyResult::any(macro_span, guar)) } } diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 857d0b774879d..42dbc801bfb5a 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -414,7 +414,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, is_bench: bool, attr_sp: Span, item: Opt Some(ast::ItemKind::MacCall(_)) => Level::Warning, _ => Level::Error, }; - let mut err = Diag::<()>::new(dcx, level, msg); + let mut err = Diag::new(dcx, level, msg); err.span(attr_sp); if let Some(item) = item { err.span_label( diff --git a/compiler/rustc_builtin_macros/src/test_binder_constraints.rs b/compiler/rustc_builtin_macros/src/test_binder_constraints.rs index 0c7482672df46..d6a3649500c29 100644 --- a/compiler/rustc_builtin_macros/src/test_binder_constraints.rs +++ b/compiler/rustc_builtin_macros/src/test_binder_constraints.rs @@ -19,7 +19,7 @@ pub(crate) fn expand<'cx>( let item = match p.parse_test_binder_constraints() { Ok(expr) => expr, Err(diag) => { - let guar = diag.emit(); + let guar = diag.emit_err(); return ExpandResult::Ready(DummyResult::any(span, guar)); } }; diff --git a/compiler/rustc_builtin_macros/src/util.rs b/compiler/rustc_builtin_macros/src/util.rs index 80fa3e3b8ac8d..0c95c30095d5a 100644 --- a/compiler/rustc_builtin_macros/src/util.rs +++ b/compiler/rustc_builtin_macros/src/util.rs @@ -136,7 +136,7 @@ pub(crate) fn expr_to_string( ) -> ExpandResult, ()> { expr_to_spanned_string(cx, expr, err_msg).map(|res| { res.map_err(|err| match err { - Ok((err, _)) => err.emit(), + Ok((err, _)) => err.emit_err(), Err(guar) => guar, }) .map(|ExprToSpannedString { symbol, style, .. }| (symbol, style)) @@ -157,7 +157,7 @@ pub(crate) fn check_zero_tts(cx: &ExtCtxt<'_>, span: Span, tts: TokenStream, nam pub(crate) fn parse_expr(p: &mut parser::Parser<'_>) -> Result, ErrorGuaranteed> { let guar = match p.parse_expr() { Ok(expr) => return Ok(expr), - Err(err) => err.emit(), + Err(err) => err.emit_err(), }; while p.token != token::Eof { p.bump(); @@ -191,7 +191,7 @@ pub(crate) fn get_single_str_spanned_from_tts( }; expr_to_spanned_string(cx, ret, "argument must be a string literal").map(|res| { res.map_err(|err| match err { - Ok((err, _)) => err.emit(), + Ok((err, _)) => err.emit_err(), Err(guar) => guar, }) .map(|ExprToSpannedString { symbol, span, .. }| (symbol, span)) diff --git a/compiler/rustc_builtin_macros/src/view_type.rs b/compiler/rustc_builtin_macros/src/view_type.rs index 090603f4f1253..69bd8f2727fc3 100644 --- a/compiler/rustc_builtin_macros/src/view_type.rs +++ b/compiler/rustc_builtin_macros/src/view_type.rs @@ -15,7 +15,7 @@ pub(crate) fn expand<'cx>( let (ty, pat) = match parse_view_ty(cx, tts) { Ok(parsed) => parsed, Err(err) => { - return ExpandResult::Ready(DummyResult::any(sp, err.emit())); + return ExpandResult::Ready(DummyResult::any(sp, err.emit_err())); } }; diff --git a/compiler/rustc_codegen_llvm/src/diagnostics.rs b/compiler/rustc_codegen_llvm/src/diagnostics.rs index 78e502f13af75..6c5c23203aa79 100644 --- a/compiler/rustc_codegen_llvm/src/diagnostics.rs +++ b/compiler/rustc_codegen_llvm/src/diagnostics.rs @@ -20,10 +20,10 @@ pub(crate) struct SanitizerMemtagRequiresMte; pub(crate) struct ParseTargetMachineConfig<'a>(pub LlvmError<'a>); -impl Diagnostic<'_, G> for ParseTargetMachineConfig<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for ParseTargetMachineConfig<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { // Reuse the formatted primary message from `LlvmError` without emitting it. - let diag: Diag<'_, ()> = self.0.into_diag(dcx, level); + let diag = self.0.into_diag(dcx, level); let (message, _) = diag.messages.first().expect("`LlvmError` with no message"); let message = format_diag_message(message, &diag.args).into_owned(); diag.cancel(); @@ -141,8 +141,8 @@ pub(crate) enum LlvmError<'a> { pub(crate) struct WithLlvmError<'a>(pub LlvmError<'a>, pub String); -impl Diagnostic<'_, G> for WithLlvmError<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for WithLlvmError<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { use LlvmError::*; let msg_with_llvm_err = match &self.0 { WriteOutput { .. } => msg!("could not write output to {$path}: {$llvm_err}"), diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index c93aa87b25077..ef22ab51ef994 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2060,7 +2060,7 @@ impl SharedEmitterMain { } Ok(SharedEmitterMessage::InlineAsmError(inner)) => { assert_matches!(inner.level, Level::Error | Level::Warning | Level::Note); - let mut err = Diag::<()>::new(sess.dcx(), inner.level, inner.msg); + let mut err = Diag::new(sess.dcx(), inner.level, inner.msg); if !inner.span.is_dummy() { err.span(inner.span.span()); } diff --git a/compiler/rustc_codegen_ssa/src/diagnostics.rs b/compiler/rustc_codegen_ssa/src/diagnostics.rs index 8aa2da904bd07..8c72f294235a9 100644 --- a/compiler/rustc_codegen_ssa/src/diagnostics.rs +++ b/compiler/rustc_codegen_ssa/src/diagnostics.rs @@ -202,8 +202,8 @@ pub enum LinkRlibError { pub(crate) struct ThorinErrorWrapper(pub thorin::Error); -impl Diagnostic<'_, G> for ThorinErrorWrapper { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for ThorinErrorWrapper { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let build = |msg| Diag::new(dcx, level, msg); match self.0 { thorin::Error::ReadInput(_) => build(msg!("failed to read input file")), @@ -334,8 +334,8 @@ pub(crate) struct LinkingFailed<'a> { pub sysroot_dir: PathBuf, } -impl Diagnostic<'_, G> for LinkingFailed<'_> { - fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for LinkingFailed<'_> { + fn into_diag(mut self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new(dcx, level, msg!("linking with `{$linker_path}` failed: {$exit_status}")); diag.arg("linker_path", format!("{}", self.linker_path.display())); @@ -463,8 +463,8 @@ pub(crate) struct LinkExeUnexpectedError; pub(crate) struct LinkExeStatusStackBufferOverrun; -impl<'a, G> Diagnostic<'a, G> for LinkExeStatusStackBufferOverrun { - fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for LinkExeStatusStackBufferOverrun { + fn into_diag(self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, msg!("0xc0000409 is `STATUS_STACK_BUFFER_OVERRUN`")); diag.note(msg!( "this may have been caused by a program abort and not a stack buffer overrun" @@ -1265,8 +1265,8 @@ pub(crate) struct TargetFeatureDisableOrEnable<'a> { #[help("add the missing features in a `target_feature` attribute")] pub(crate) struct MissingFeatures; -impl Diagnostic<'_, G> for TargetFeatureDisableOrEnable<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for TargetFeatureDisableOrEnable<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index 4d268c8a1f8cd..c9217856252d8 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -175,7 +175,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { let secondary_errors = mem::take(&mut self.secondary_errors); if self.error_emitted.is_none() { for error in secondary_errors { - self.error_emitted = Some(error.emit()); + self.error_emitted = Some(error.emit_err()); } } else { assert!(self.tcx.dcx().has_errors().is_some()); @@ -276,8 +276,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { match op.importance() { ops::DiagImportance::Primary => { - let reported = err.emit(); - self.error_emitted = Some(reported); + let guar = err.emit_err(); + self.error_emitted = Some(guar); } ops::DiagImportance::Secondary => { diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index f06ef0dbcf575..8532cad91b808 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -223,11 +223,11 @@ pub(super) fn report<'tcx>( ); mk(&mut err, span, frames); - let g = err.emit(); + let guar = err.emit_err(); let reported = if allowed_in_infallible { - ReportedErrorInfo::allowed_in_infallible(g) + ReportedErrorInfo::allowed_in_infallible(guar) } else { - ReportedErrorInfo::const_eval_error(g) + ReportedErrorInfo::const_eval_error(guar) }; ErrorHandled::Reported(reported, span) } @@ -243,7 +243,7 @@ pub(super) fn lint<'tcx, L>( lint: &'static rustc_lint_defs::Lint, decorator: impl FnOnce(Vec) -> L, ) where - L: for<'a> rustc_errors::Diagnostic<'a, ()>, + L: for<'a> rustc_errors::Diagnostic<'a>, { let (span, frames) = get_span_and_frames(tcx, &machine.stack); diff --git a/compiler/rustc_const_eval/src/diagnostics.rs b/compiler/rustc_const_eval/src/diagnostics.rs index 2d8568f7f909b..995356fd3b488 100644 --- a/compiler/rustc_const_eval/src/diagnostics.rs +++ b/compiler/rustc_const_eval/src/diagnostics.rs @@ -317,7 +317,7 @@ pub(crate) struct FrameNote { } impl Subdiagnostic for FrameNote { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut span: MultiSpan = self.span.into(); if self.has_label && !self.span.is_dummy() { span.push_span_label(self.span, msg!("the failure occurred here")); diff --git a/compiler/rustc_errors/src/decorate_diag.rs b/compiler/rustc_errors/src/decorate_diag.rs index 3a222fd8a10cf..382a3b2758407 100644 --- a/compiler/rustc_errors/src/decorate_diag.rs +++ b/compiler/rustc_errors/src/decorate_diag.rs @@ -13,7 +13,7 @@ pub struct DecorateDiagCompat( /// The third argument of the closure is a `Session`. However, due to the dependency tree, /// we don't have access to `rustc_session` here, so we downcast it when needed. pub Box< - dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()> + dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a> + DynSync + DynSend + 'static, @@ -26,7 +26,7 @@ impl std::fmt::Debug for DecorateDiagCompat { } } -impl Diagnostic<'a, ()> + DynSync + DynSend + 'static> From for DecorateDiagCompat { +impl Diagnostic<'a> + DynSync + DynSend + 'static> From for DecorateDiagCompat { #[inline] fn from(d: D) -> Self { Self(Box::new(|dcx, level, _| d.into_diag(dcx, level))) @@ -82,7 +82,7 @@ impl LintBuffer { } pub fn dyn_buffer_lint< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static, + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a> + DynSync + DynSend + 'static, >( &mut self, lint: &'static Lint, @@ -99,7 +99,7 @@ impl LintBuffer { } pub fn dyn_buffer_lint_any< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a, ()> + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn Any) -> Diag<'a> + DynSend + DynSync + 'static, diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 888636365dc0c..9a12d6d53b6e6 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,7 +1,6 @@ use std::borrow::Cow; use std::fmt::{self, Debug}; use std::hash::{Hash, Hasher}; -use std::marker::PhantomData; use std::ops::{Deref, DerefMut}; use std::panic; use std::path::PathBuf; @@ -20,58 +19,29 @@ use crate::{ Suggestions, }; -/// Marker type which enables implementation of `create_bug` and `emit_bug` functions for -/// bug diagnostics. -#[derive(Copy, Clone)] -pub struct BugAbort; - -/// Marker type which enables implementation of `create_fatal` and `emit_fatal` functions for -/// fatal diagnostics. -#[derive(Copy, Clone)] -pub struct FatalAbort; - /// Trait implemented by error types. This is rarely implemented manually. Instead, use /// `#[derive(Diagnostic)]` -- see [rustc_macros::Diagnostic]. -/// -/// When implemented manually, it should be generic over the emission -/// guarantee, i.e.: -/// ```ignore (fragment) -/// impl<'a, G> Diagnostic<'a, G> for Foo { ... } -/// ``` -/// rather than being specific: -/// ```ignore (fragment) -/// impl<'a> Diagnostic<'a> for Bar { ... } // the default type param is `ErrorGuaranteed` -/// impl<'a> Diagnostic<'a, ()> for Baz { ... } -/// ``` -/// There are two reasons for this. -/// - A diagnostic like `Foo` *could* be emitted at any level -- `level` is -/// passed in to `into_diag` from outside. Even if in practice it is -/// always emitted at a single level, we let the diagnostic creation/emission -/// site determine the level (by using `create_err`, `emit_warn`, etc.) -/// rather than the `Diagnostic` impl. -/// - Derived impls are always generic, and it's good for the hand-written -/// impls to be consistent with them. -pub trait Diagnostic<'a, G = ErrorGuaranteed> { +pub trait Diagnostic<'a> { /// Write out as a diagnostic out of `DiagCtxt`. #[must_use] #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G>; + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a>; } -impl<'a, T, G> Diagnostic<'a, G> for Spanned +impl<'a, T> Diagnostic<'a> for Spanned where - T: Diagnostic<'a, G>, + T: Diagnostic<'a>, { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { self.node.into_diag(dcx, level).with_span(self.span) } } /// Type used to emit diagnostic through a closure instead of implementing the `Diagnostic` trait. -pub struct DiagDecorator)>(pub F); +pub struct DiagDecorator)>(pub F); -impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, F: FnOnce(&mut Diag<'_>)> Diagnostic<'a> for DiagDecorator { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, ""); (self.0)(&mut diag); diag @@ -82,7 +52,7 @@ impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for DiagDecorator { /// `#[derive(Subdiagnostic)]` -- see [rustc_macros::Subdiagnostic]. pub trait Subdiagnostic { /// Add a subdiagnostic to an existing diagnostic. - fn add_to_diag(self, diag: &mut Diag<'_, G>); + fn add_to_diag(self, diag: &mut Diag<'_>); } #[derive(Clone, Debug, Encodable, Decodable)] @@ -391,16 +361,16 @@ pub struct Subdiag { /// Wraps a `DiagInner`, adding some useful things. /// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check /// that it has been emitted or cancelled. -/// - `G`, which determines the type returned from `emit`. /// -/// Each constructed `Diag` must be consumed by a function such as `emit`, -/// `cancel`, or `delay_as_bug`. A panic occurs if a `Diag` is dropped without -/// being consumed by one of these functions. +/// Each constructed `Diag` must be consumed by a function such as +/// `emit_bug`/`emit_fatal`/`emit_err`/`emit`, `cancel`, or `delay_as_bug`. A +/// panic occurs if a `Diag` is dropped without being consumed by one of these +/// functions. /// /// If there is some state in a downstream crate you would like to access in /// the methods of `Diag` here, consider extending `DiagCtxtFlags`. #[must_use] -pub struct Diag<'a, G = ErrorGuaranteed> { +pub struct Diag<'a> { pub dcx: DiagCtxtHandle<'a>, /// Why the `Option`? It is always `Some` until the `Diag` is consumed via @@ -413,17 +383,15 @@ pub struct Diag<'a, G = ErrorGuaranteed> { /// theory, return value optimization (RVO) should avoid unnecessary /// copying. In practice, it does not (at the time of writing). diag: Option>, - - _marker: PhantomData, } // Cloning a `Diag` is a recipe for a diagnostic being emitted twice, which // would be bad. -impl !Clone for Diag<'_, G> {} +impl !Clone for Diag<'_> {} -rustc_data_structures::static_assert_size!(Diag<'_, ()>, 3 * size_of::()); +rustc_data_structures::static_assert_size!(Diag<'_>, 3 * size_of::()); -impl Deref for Diag<'_, G> { +impl Deref for Diag<'_> { type Target = DiagInner; fn deref(&self) -> &DiagInner { @@ -431,80 +399,18 @@ impl Deref for Diag<'_, G> { } } -impl DerefMut for Diag<'_, G> { +impl DerefMut for Diag<'_> { fn deref_mut(&mut self) -> &mut DiagInner { self.diag.as_mut().unwrap() } } -impl Debug for Diag<'_, G> { +impl Debug for Diag<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { self.diag.fmt(f) } } -impl Diag<'_, BugAbort> { - #[track_caller] - pub fn emit(self) -> ! { - assert_eq!(self.level, Level::Bug); - self.emit_producing_nothing(); - panic::panic_any(ExplicitBug); - } -} - -impl Diag<'_, FatalAbort> { - #[track_caller] - pub fn emit(self) -> ! { - assert_eq!(self.level, Level::Fatal); - self.emit_producing_nothing(); - crate::FatalError.raise() - } -} - -impl Diag<'_, ErrorGuaranteed> { - #[track_caller] - pub fn emit(self) -> ErrorGuaranteed { - self.emit_producing_error_guaranteed() - } - - /// Emit the diagnostic unless `delay` is true, - /// in which case the emission will be delayed as a bug. - /// - /// See `emit` and `delay_as_bug` for details. - #[track_caller] - pub fn emit_unless_delay(mut self, delay: bool) -> ErrorGuaranteed { - if delay { - self.downgrade_to_delayed_bug(); - } - self.emit() - } - - /// Delay emission of this diagnostic as a bug. - /// - /// This can be useful in contexts where an error indicates a bug but - /// typically this only happens when other compilation errors have already - /// happened. In those cases this can be used to defer emission of this - /// diagnostic as a bug in the compiler only if no other errors have been - /// emitted. - /// - /// In the meantime, though, callsites are required to deal with the "bug" - /// locally in whichever way makes the most sense. - #[track_caller] - pub fn delay_as_bug(mut self) -> ErrorGuaranteed { - self.downgrade_to_delayed_bug(); - self.emit() - } -} - -impl Diag<'_, ()> { - #[track_caller] - pub fn emit(self) { - assert_ne!(self.level, Level::Bug); - assert_ne!(self.level, Level::Fatal); - self.emit_producing_nothing(); - } -} - /// `Diag` impls many `&mut self -> &mut Self` methods. Each one modifies an /// existing diagnostic, either in a standalone fashion, e.g. /// `err.code(code);`, or in a chained fashion to make multiple modifications, @@ -548,22 +454,22 @@ macro_rules! with_fn { }; } -impl<'a, G> Diag<'a, G> { +impl<'a> Diag<'a> { #[track_caller] pub fn new(dcx: DiagCtxtHandle<'a>, level: Level, message: impl Into) -> Self { Self::new_diagnostic(dcx, DiagInner::new(level, message)) } /// Allow moving diagnostics between different error tainting contexts - pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_, G> { - Diag { dcx, diag: self.diag.take(), _marker: PhantomData } + pub fn with_dcx(mut self, dcx: DiagCtxtHandle<'_>) -> Diag<'_> { + Diag { dcx, diag: self.diag.take() } } /// Creates a new `Diag` with an already constructed diagnostic. #[track_caller] pub(crate) fn new_diagnostic(dcx: DiagCtxtHandle<'a>, diag: DiagInner) -> Self { debug!("Created new diagnostic"); - Self { dcx, diag: Some(Box::new(diag)), _marker: PhantomData } + Self { dcx, diag: Some(Box::new(diag)) } } /// Delay emission of this diagnostic as a bug. @@ -588,7 +494,7 @@ impl<'a, G> Diag<'a, G> { /// Make emitting this diagnostic fatal. #[track_caller] - pub fn upgrade_to_fatal(mut self) -> Diag<'a, FatalAbort> { + pub fn upgrade_to_fatal(mut self) -> Diag<'a> { assert!( matches!(self.level, Level::Error), "upgrade_to_fatal: cannot upgrade {:?} to Fatal: not an error", @@ -599,7 +505,7 @@ impl<'a, G> Diag<'a, G> { // Take is okay since we immediately rewrap it in another diagnostic. // i.e. we do emit it despite defusing the original diagnostic's drop bomb. let diag = self.diag.take(); - Diag { dcx: self.dcx, diag, _marker: PhantomData } + Diag { dcx: self.dcx, diag } } with_fn! { with_span_label, @@ -1302,21 +1208,45 @@ impl<'a, G> Diag<'a, G> { self } - /// Most `emit` methods use this as a starting point. - fn emit_producing_nothing(mut self) { + /// Emit the diagnostic. Will also abort appropriately if the level is `Bug` or `Fatal`. + #[track_caller] + pub fn emit(mut self) { + let level = self.level; // get level before taking the inner diag let diag = self.take_diag(); self.dcx.emit_diagnostic(diag); + + match level { + Level::Bug => panic::panic_any(ExplicitBug), + Level::Fatal => crate::FatalError.raise(), + _ => {} + } } - /// `Diag<'_, ErrorGuaranteed>::emit` uses this. - fn emit_producing_error_guaranteed(mut self) -> ErrorGuaranteed { + /// Use this on a `Bug` diagnostic if you need the `!` return type. Otherwise `emit` suffices. + /// Aborts if used on a non-`Bug` diagnostic. + #[track_caller] + pub fn emit_bug(self) -> ! { + assert_eq!(self.level, Level::Bug); + self.emit(); + unreachable!(); // `emit` will have aborted + } + + /// Use this on a `Fatal` diagnostic if you need the `!` return type. Otherwise `emit` + /// suffices. Aborts if used on a non-`Fatal` diagnostic. + #[track_caller] + pub fn emit_fatal(self) -> ! { + assert_eq!(self.level, Level::Fatal); + self.emit(); + unreachable!(); // `emit` will have aborted + } + + /// Use this on an `Error`/`DelayedBug` diagnostic if you need the `ErrorGuaranteed` return + /// type. Otherwise `emit` suffices. Aborts if used on a non-`Error`/`DelayedBug` diagnostic. + #[track_caller] + pub fn emit_err(mut self) -> ErrorGuaranteed { let diag = self.take_diag(); - // The only error levels that produce `ErrorGuaranteed` are - // `Error` and `DelayedBug`. But `DelayedBug` should never occur here - // because delayed bugs have their level changed to `Bug` when they are - // actually printed, so they produce an ICE. - // + // The only error levels that should reach here are `Error` and `DelayedBug`. // (Also, even though `level` isn't `pub`, the whole `DiagInner` could // be overwritten with a new one thanks to `DerefMut`. So this assert // protects against that, too.) @@ -1330,6 +1260,18 @@ impl<'a, G> Diag<'a, G> { guar.unwrap() } + /// Emit the diagnostic unless `delay` is true, + /// in which case the emission will be delayed as a bug. + /// + /// See `emit` and `delay_as_bug` for details. + #[track_caller] + pub fn emit_err_unless_delay(mut self, delay: bool) -> ErrorGuaranteed { + if delay { + self.downgrade_to_delayed_bug(); + } + self.emit_err() + } + /// Cancel and consume the diagnostic. (A diagnostic must either be emitted or /// cancelled or it will panic when dropped). pub fn cancel(mut self) { @@ -1349,11 +1291,27 @@ impl<'a, G> Diag<'a, G> { let diag = self.take_diag(); self.dcx.stash_diagnostic(span, key, diag) } + + /// Delay emission of this diagnostic as a bug. + /// + /// This can be useful in contexts where an error indicates a bug but + /// typically this only happens when other compilation errors have already + /// happened. In those cases this can be used to defer emission of this + /// diagnostic as a bug in the compiler only if no other errors have been + /// emitted. + /// + /// In the meantime, though, callsites are required to deal with the "bug" + /// locally in whichever way makes the most sense. + #[track_caller] + pub fn delay_as_bug(mut self) -> ErrorGuaranteed { + self.downgrade_to_delayed_bug(); + self.emit_err() + } } /// Destructor bomb: every `Diag` must be consumed (emitted, cancelled, etc.) /// or we emit a bug. -impl Drop for Diag<'_, G> { +impl Drop for Diag<'_> { fn drop(&mut self) { match self.diag.take() { Some(diag) if !panicking() => { diff --git a/compiler/rustc_errors/src/diagnostic_impls.rs b/compiler/rustc_errors/src/diagnostic_impls.rs index b002b8932a239..fa9e3544f12ae 100644 --- a/compiler/rustc_errors/src/diagnostic_impls.rs +++ b/compiler/rustc_errors/src/diagnostic_impls.rs @@ -42,7 +42,7 @@ pub struct SingleLabelManySpans { pub label: &'static str, } impl Subdiagnostic for SingleLabelManySpans { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_labels(self.spans, self.label); } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 89209b64e0108..30791a51f7644 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -32,8 +32,8 @@ pub use anstyle::{ pub use codes::*; pub use decorate_diag::{BufferedEarlyLint, DecorateDiagCompat, LintBuffer}; pub use diagnostic::{ - BugAbort, Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, - FatalAbort, StringPart, Subdiag, Subdiagnostic, + Diag, DiagDecorator, DiagInner, DiagLocation, DiagStyledString, Diagnostic, StringPart, + Subdiag, Subdiagnostic, }; pub use diagnostic_impls::{ DiagSymbolList, ElidedLifetimeInPathSubdiag, ExpectedLifetimeParameter, @@ -632,7 +632,7 @@ impl<'a> DiagCtxtHandle<'a> { /// Steal a previously stashed non-error diagnostic with the given `Span` /// and [`StashKey`] as the key. Panics if the found diagnostic is an /// error. - pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { + pub fn steal_non_err(self, span: Span, key: StashKey) -> Option> { // FIXME(#120456) - is `swap_remove` correct? let (diag, guar, _) = self.dcx.inner.borrow_mut().stashed_diagnostics.get_mut(&key).and_then( @@ -661,13 +661,12 @@ impl<'a> DiagCtxtHandle<'a> { |stashed_diagnostics| stashed_diagnostics.swap_remove(&span.with_parent(None)), ); err.map(|(err, guar, _)| { - // The use of `::` is safe because level is `Level::Error`. assert_eq!(err.level, Error); assert!(guar.is_some()); - let mut err = Diag::::new_diagnostic(self, err); + let mut err = Diag::new_diagnostic(self, err); modify_err(&mut err); assert_eq!(err.level, Error); - err.emit() + err.emit_err() }) } @@ -690,11 +689,11 @@ impl<'a> DiagCtxtHandle<'a> { assert!(guar.is_some()); // Because `old_err` has already been counted, it can only be // safely cancelled because the `new_err` supplants it. - Diag::::new_diagnostic(self, old_err).cancel(); + Diag::new_diagnostic(self, old_err).cancel(); } None => {} }; - new_err.emit() + new_err.emit_err() } pub fn has_stashed_diagnostic(&self, span: Span, key: StashKey) -> bool { @@ -952,13 +951,13 @@ impl<'a> DiagCtxtHandle<'a> { // functions create and emit a diagnostic all in one go. impl<'a> DiagCtxtHandle<'a> { #[track_caller] - pub fn struct_bug(self, msg: impl Into>) -> Diag<'a, BugAbort> { + pub fn struct_bug(self, msg: impl Into>) -> Diag<'a> { Diag::new(self, Bug, msg.into()) } #[track_caller] pub fn bug(self, msg: impl Into>) -> ! { - self.struct_bug(msg).emit() + self.struct_bug(msg).emit_bug() } #[track_caller] @@ -966,33 +965,33 @@ impl<'a> DiagCtxtHandle<'a> { self, span: impl Into, msg: impl Into>, - ) -> Diag<'a, BugAbort> { + ) -> Diag<'a> { self.struct_bug(msg).with_span(span) } #[track_caller] pub fn span_bug(self, span: impl Into, msg: impl Into>) -> ! { - self.struct_span_bug(span, msg.into()).emit() + self.struct_span_bug(span, msg.into()).emit_bug() } #[track_caller] - pub fn create_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> Diag<'a, BugAbort> { + pub fn create_bug(self, bug: impl Diagnostic<'a>) -> Diag<'a> { bug.into_diag(self, Bug) } #[track_caller] - pub fn emit_bug(self, bug: impl Diagnostic<'a, BugAbort>) -> ! { - self.create_bug(bug).emit() + pub fn emit_bug(self, bug: impl Diagnostic<'a>) -> ! { + self.create_bug(bug).emit_bug() } #[track_caller] - pub fn struct_fatal(self, msg: impl Into) -> Diag<'a, FatalAbort> { + pub fn struct_fatal(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Fatal, msg) } #[track_caller] pub fn fatal(self, msg: impl Into) -> ! { - self.struct_fatal(msg).emit() + self.struct_fatal(msg).emit_fatal() } #[track_caller] @@ -1000,23 +999,23 @@ impl<'a> DiagCtxtHandle<'a> { self, span: impl Into, msg: impl Into, - ) -> Diag<'a, FatalAbort> { + ) -> Diag<'a> { self.struct_fatal(msg).with_span(span) } #[track_caller] pub fn span_fatal(self, span: impl Into, msg: impl Into) -> ! { - self.struct_span_fatal(span, msg).emit() + self.struct_span_fatal(span, msg).emit_fatal() } #[track_caller] - pub fn create_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> Diag<'a, FatalAbort> { + pub fn create_fatal(self, fatal: impl Diagnostic<'a>) -> Diag<'a> { fatal.into_diag(self, Fatal) } #[track_caller] - pub fn emit_fatal(self, fatal: impl Diagnostic<'a, FatalAbort>) -> ! { - self.create_fatal(fatal).emit() + pub fn emit_fatal(self, fatal: impl Diagnostic<'a>) -> ! { + self.create_fatal(fatal).emit_fatal() } // FIXME: This method should be removed (every error should have an associated error code). @@ -1027,7 +1026,7 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn err(self, msg: impl Into) -> ErrorGuaranteed { - self.struct_err(msg).emit() + self.struct_err(msg).emit_err() } #[track_caller] @@ -1045,7 +1044,7 @@ impl<'a> DiagCtxtHandle<'a> { span: impl Into, msg: impl Into, ) -> ErrorGuaranteed { - self.struct_span_err(span, msg).emit() + self.struct_span_err(span, msg).emit_err() } #[track_caller] @@ -1055,13 +1054,13 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn emit_err(self, err: impl Diagnostic<'a>) -> ErrorGuaranteed { - self.create_err(err).emit() + self.create_err(err).emit_err() } /// Ensures that an error is printed. See [`Level::DelayedBug`]. #[track_caller] pub fn delayed_bug(self, msg: impl Into>) -> ErrorGuaranteed { - Diag::::new(self, DelayedBug, msg.into()).emit() + Diag::new(self, DelayedBug, msg.into()).emit_err() } /// Ensures that an error is printed. See [`Level::DelayedBug`]. @@ -1074,11 +1073,11 @@ impl<'a> DiagCtxtHandle<'a> { sp: impl Into, msg: impl Into>, ) -> ErrorGuaranteed { - Diag::::new(self, DelayedBug, msg.into()).with_span(sp).emit() + Diag::new(self, DelayedBug, msg.into()).with_span(sp).emit_err() } #[track_caller] - pub fn struct_warn(self, msg: impl Into) -> Diag<'a, ()> { + pub fn struct_warn(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Warning, msg) } @@ -1092,7 +1091,7 @@ impl<'a> DiagCtxtHandle<'a> { self, span: impl Into, msg: impl Into, - ) -> Diag<'a, ()> { + ) -> Diag<'a> { self.struct_warn(msg).with_span(span) } @@ -1102,17 +1101,17 @@ impl<'a> DiagCtxtHandle<'a> { } #[track_caller] - pub fn create_warn(self, warning: impl Diagnostic<'a, ()>) -> Diag<'a, ()> { + pub fn create_warn(self, warning: impl Diagnostic<'a>) -> Diag<'a> { warning.into_diag(self, Warning) } #[track_caller] - pub fn emit_warn(self, warning: impl Diagnostic<'a, ()>) { + pub fn emit_warn(self, warning: impl Diagnostic<'a>) { self.create_warn(warning).emit() } #[track_caller] - pub fn struct_note(self, msg: impl Into) -> Diag<'a, ()> { + pub fn struct_note(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Note, msg) } @@ -1126,7 +1125,7 @@ impl<'a> DiagCtxtHandle<'a> { self, span: impl Into, msg: impl Into, - ) -> Diag<'a, ()> { + ) -> Diag<'a> { self.struct_note(msg).with_span(span) } @@ -1136,22 +1135,22 @@ impl<'a> DiagCtxtHandle<'a> { } #[track_caller] - pub fn create_note(self, note: impl Diagnostic<'a, ()>) -> Diag<'a, ()> { + pub fn create_note(self, note: impl Diagnostic<'a>) -> Diag<'a> { note.into_diag(self, Note) } #[track_caller] - pub fn emit_note(self, note: impl Diagnostic<'a, ()>) { + pub fn emit_note(self, note: impl Diagnostic<'a>) { self.create_note(note).emit() } #[track_caller] - pub fn struct_allow(self, msg: impl Into) -> Diag<'a, ()> { + pub fn struct_allow(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Allow, msg) } #[track_caller] - pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a, ()> { + pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a> { Diag::new(self, Expect, msg).with_lint_id(id) } } @@ -1550,19 +1549,19 @@ impl DelayedDiagInner { } } -/// | Level | is_error | emit return type | Top-level | Used in lints? -/// | ----- | -------- | ---------------- | --------- | -------------- -/// | Bug | yes | BugAbort | yes | - -/// | Fatal | yes | FatalAbort | yes | - -/// | Error | yes | ErrorGuaranteed | yes | yes -/// | DelayedBug | yes | ErrorGuaranteed | yes | - -/// | ForceWarning | - | () | yes | lint-only -/// | Warning | - | () | yes | yes -/// | Note | - | () | rare | - -/// | Help | - | () | don't use | - -/// | FailureNote | - | () | rare | - -/// | Allow | - | () | yes | lint-only -/// | Expect | - | () | yes | lint-only +/// | Level | is_error | usable emit fns | Top-level | Used in lints? +/// | ----- | -------- | --------------- | --------- | -------------- +/// | Bug | yes | emit, emit_bug | yes | - +/// | Fatal | yes | emit, emit_fatal | yes | - +/// | Error | yes | emit, emit_err | yes | yes +/// | DelayedBug | yes | emit, emit_err | yes | - +/// | ForceWarning | - | emit | yes | lint-only +/// | Warning | - | emit | yes | yes +/// | Note | - | emit | rare | - +/// | Help | - | emit | don't use | - +/// | FailureNote | - | emit | rare | - +/// | Allow | - | emit | yes | lint-only +/// | Expect | - | emit | yes | lint-only /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs index 51c517ee24a66..5a2442fbccf35 100644 --- a/compiler/rustc_expand/src/expand.rs +++ b/compiler/rustc_expand/src/expand.rs @@ -898,7 +898,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { } } Err(err) => { - let _guar = err.emit(); + err.emit(); fragment_kind.expect_from_annotatables(iter::once(item)) } } @@ -1068,7 +1068,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> { err.span(span); } annotate_err_with_kind(&mut err, kind, span); - let guar = err.emit(); + let guar = err.emit_err(); self.cx.macro_error_and_trace_macros_diag(); kind.dummy(span, guar) } diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs index 0e79dadb3503e..f7603f25bb137 100644 --- a/compiler/rustc_expand/src/mbe/diagnostics.rs +++ b/compiler/rustc_expand/src/mbe/diagnostics.rs @@ -140,7 +140,7 @@ pub(super) fn failed_to_match_macro( } } } - let guar = err.emit(); + let guar = err.emit_err(); (sp, guar) } @@ -497,7 +497,7 @@ pub(super) fn emit_frag_parse_err( } } } - e.emit() + e.emit_err() } pub(crate) fn annotate_err_with_kind(err: &mut Diag<'_>, kind: AstFragmentKind, span: Span) { diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs index 3e94e0ca34773..4505bcf394ace 100644 --- a/compiler/rustc_expand/src/mbe/macro_parser.rs +++ b/compiler/rustc_expand/src/mbe/macro_parser.rs @@ -713,13 +713,13 @@ impl TtParser { fn nt_parsing_error(&self, loc: &MatcherLoc, err: Diag<'_>) -> ParseResult { let &MatcherLoc::MetaVarDecl { span, kind, .. } = loc else { unreachable!() }; - let guarantee = err + let guar = err .with_span_label( span, format!("while parsing argument for this `{kind}` macro fragment"), ) - .emit(); - ErrorReported(guarantee) + .emit_err(); + ErrorReported(guar) } fn nameize>( diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index 2212724c68bc1..5ace9b36d0b6f 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -255,7 +255,7 @@ impl MacroRulesMacroExpander { let id = cx.current_expansion.id; let tts = transcribe(psess, &named_matches, rhs, *rhs_span, self.transparency, id) - .map_err(|e| e.emit())?; + .map_err(|e| e.emit_err())?; if cx.trace_macros() { let msg = format!("to `{}`", pprust::tts_to_string(&tts)); @@ -464,7 +464,7 @@ fn expand_macro<'cx, 'a: 'cx>( let tts = match transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id) { Ok(tts) => tts, Err(err) => { - let guar = err.emit(); + let guar = err.emit_err(); return DummyResult::any(arm_span, guar); } }; @@ -562,7 +562,7 @@ fn expand_macro_attr( let id = cx.current_expansion.id; let tts = transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id) - .map_err(|e| e.emit())?; + .map_err(|e| e.emit_err())?; if cx.trace_macros() { let msg = format!("to `{}`", pprust::tts_to_string(&tts)); @@ -858,7 +858,7 @@ pub fn compile_declarative_macro( if args_not_empty { err.span_label(derive_keyword_span, "need `()` after this `derive`"); } - return dummy_syn_ext(err.emit()); + return dummy_syn_ext(err.emit_err()); } (None, true) } else { @@ -873,7 +873,7 @@ pub fn compile_declarative_macro( let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition); check_emission(check_lhs(sess, features, node_id, &lhs_tt)); if let Err(e) = p.expect(exp!(FatArrow)) { - return dummy_syn_ext(e.emit()); + return dummy_syn_ext(e.emit_err()); } if let Some(guar) = check_no_eof(sess, &p, "expected right-hand side of macro rule") { return dummy_syn_ext(guar); @@ -906,7 +906,7 @@ pub fn compile_declarative_macro( break; } if let Err(e) = p.expect(exp_sep) { - return dummy_syn_ext(e.emit()); + return dummy_syn_ext(e.emit_err()); } } @@ -952,7 +952,7 @@ fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option Result<(), let mut err = sess.dcx().struct_span_err(sp, "repetition matches empty token tree"); check_redundant_vis_repetition(&mut err, sess, seq, span); - return Err(err.emit()); + return Err(err.emit_err()); } check_lhs_no_empty_seq(sess, &seq.tts)? } @@ -1660,7 +1660,7 @@ fn check_matcher_core<'tt>( )); } } - errored = Err(err.emit()); + errored = Err(err.emit_err()); } } } diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs index d49eae9830b3f..8e1641c8fb60c 100644 --- a/compiler/rustc_expand/src/module.rs +++ b/compiler/rustc_expand/src/module.rs @@ -300,7 +300,7 @@ impl ModError<'_> { secondary_path: secondary_path.display().to_string(), }) } - ModError::ParserError(err) => err.emit(), + ModError::ParserError(err) => err.emit_err(), } } } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index c0a9a43c64cdf..1990917c09f17 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -559,8 +559,7 @@ impl server::Server for Rustc<'_, '_> { fn emit_diagnostic(&mut self, diagnostic: Diagnostic) { let message = rustc_errors::DiagMessage::from(diagnostic.message); - let mut diag: Diag<'_, ()> = - Diag::new(self.psess().dcx(), diagnostic.level.to_internal(), message); + let mut diag = Diag::new(self.psess().dcx(), diagnostic.level.to_internal(), message); diag.span(MultiSpan::from_spans(diagnostic.spans)); for child in diagnostic.children { diag.sub(child.level.to_internal(), child.message, MultiSpan::from_spans(child.spans)); diff --git a/compiler/rustc_hir/src/lints.rs b/compiler/rustc_hir/src/lints.rs index 200f1af2142a7..926c9c91ecb61 100644 --- a/compiler/rustc_hir/src/lints.rs +++ b/compiler/rustc_hir/src/lints.rs @@ -17,7 +17,7 @@ pub struct DelayedLint { pub id: HirId, pub span: MultiSpan, pub callback: Box< - dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn std::any::Any) -> Diag<'a, ()> + dyn for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &dyn std::any::Any) -> Diag<'a> + DynSend + DynSync + 'static, diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index 11960d57016f6..b098a6c186457 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -211,7 +211,7 @@ fn ensure_impl_params_and_item_params_correspond<'tcx>( as the {self_descr} definition", ), ); - Err(err.emit()) + Err(err.emit_err()) } fn ensure_all_fields_are_const_destruct<'tcx>( @@ -278,7 +278,7 @@ fn ensure_all_fields_are_const_destruct<'tcx>( None, ); } - Err(diag.emit()) + Err(diag.emit_err()) }) .collect() } @@ -362,7 +362,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( but the {self_descr} it is implemented for does not", ) .with_span_note(item_span, "the implementor must specify the same requirement") - .emit(), + .emit_err(), ); } } @@ -395,7 +395,7 @@ fn ensure_impl_predicates_are_implied_by_item_defn<'tcx>( but the {self_descr} it is implemented for does not", ) .with_span_note(item_span, "the implementor must specify the same requirement") - .emit(), + .emit_err(), ); } return Err(guar.unwrap()); diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 52b69e6050a32..3602c9507624c 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -43,7 +43,7 @@ use crate::check::wfcheck::{ use crate::collect::ItemCtxt; use crate::diagnostics; -fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_, G>) { +fn add_abi_diag_help(abi: ExternAbi, diag: &mut Diag<'_>) { if let ExternAbi::Cdecl { unwind } = abi { let c_abi = ExternAbi::C { unwind }; diag.help(format!("use `extern {c_abi}` instead",)); @@ -62,8 +62,8 @@ pub fn check_abi(tcx: TyCtxt<'_>, hir_id: hir::HirId, span: Span, abi: ExternAbi abi: ExternAbi, } - impl<'a> Diagnostic<'a, ()> for UnsupportedCallingConventions { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for UnsupportedCallingConventions { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { abi } = self; let mut lint = Diag::new( dcx, @@ -557,7 +557,7 @@ fn sanity_check_found_hidden_type<'tcx>( } else { let span = tcx.def_span(key.def_id); let other = ty::ProvisionalHiddenType { ty: hidden_ty, span }; - Err(ty.build_mismatch_error(&other, tcx)?.emit()) + Err(ty.build_mismatch_error(&other, tcx)?.emit_err()) } } @@ -2060,7 +2060,7 @@ fn detect_discriminant_duplicate<'tcx>(tcx: TyCtxt<'tcx>, adt: ty::AdtDef<'tcx>) let mut i = 0; while i < discrs.len() { let var_i_idx = discrs[i].0; - let mut error: Option> = None; + let mut error: Option> = None; let mut o = i + 1; while o < discrs.len() { @@ -2304,7 +2304,7 @@ fn opaque_type_cycle_error(tcx: TyCtxt<'_>, opaque_def_id: LocalDefId) -> ErrorG if !label { err.span_label(span, "cannot resolve opaque type"); } - err.emit() + err.emit_err() } pub(super) fn check_coroutine_obligations( diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index aefe53f2f4399..c9fd3da24fe07 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -201,7 +201,7 @@ pub(crate) fn compare_eii_statics<'tcx>( ); diag.span_note(eii_attr_span, "expected this because of this attribute"); - return Err(diag.emit()); + return Err(diag.emit_err()); } // Check that all obligations are satisfied by the implementation's @@ -349,7 +349,7 @@ fn check_early_region_bounds<'tcx>( }); diag.span_label(eii_attr_span, format!("required because of this attribute")); - return Err(diag.emit()); + return Err(diag.emit_err()); } fn check_number_of_arguments<'tcx>( @@ -447,7 +447,7 @@ fn report_number_of_arguments_mismatch<'tcx>( err.span_label(eii_attr_span, format!("required because of this attribute")); - err.emit() + err.emit_err() } fn report_eii_mismatch<'tcx>( @@ -521,7 +521,7 @@ fn report_eii_mismatch<'tcx>( None, ); - diag.emit() + diag.emit_err() } #[instrument(level = "debug", skip(infcx))] diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 4061d247f59f1..f459628ab8d29 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -638,7 +638,7 @@ pub(super) fn collect_return_position_impl_trait_in_trait_tys<'tcx>( false, None, ); - return Err(diag.emit()); + return Err(diag.emit_err()); } } @@ -950,7 +950,7 @@ impl<'tcx> ty::FallibleTypeFolder> for RemapHiddenTyRegions<'tcx> { "hidden type must only reference lifetimes captured by this impl trait", ) .with_note(format!("hidden type inferred to be `{}`", self.ty)) - .emit() + .emit_err() } None => { // This code path is not reached in any tests, but may be @@ -1091,7 +1091,7 @@ fn report_trait_method_mismatch<'tcx>( None, ); - diag.emit() + diag.emit_err() } fn check_region_bounds_on_impl_item<'tcx>( @@ -1134,7 +1134,7 @@ fn check_region_bounds_on_impl_item<'tcx>( bounds_span, where_span, }) - .emit_unless_delay(delay); + .emit_err_unless_delay(delay); Err(reported) } @@ -1435,7 +1435,7 @@ fn check_region_late_boundedness<'tcx>( } } - Some(diag.emit()) + Some(diag.emit_err()) } fn find_region_in_clauses<'tcx>( @@ -1538,7 +1538,7 @@ fn compare_self_type<'tcx>( } else { err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } - return Err(err.emit_unless_delay(delay)); + return Err(err.emit_err_unless_delay(delay)); } (true, false) => { @@ -1559,7 +1559,7 @@ fn compare_self_type<'tcx>( err.note_trait_signature(trait_m.name(), trait_m.signature(tcx)); } - return Err(err.emit_unless_delay(delay)); + return Err(err.emit_err_unless_delay(delay)); } } @@ -1719,8 +1719,8 @@ fn compare_number_of_generics<'tcx>( err.span_label(*span, "`impl Trait` introduces an implicit type parameter"); } - let reported = err.emit_unless_delay(delay); - err_occurred = Some(reported); + let guar = err.emit_err_unless_delay(delay); + err_occurred = Some(guar); } } @@ -1901,7 +1901,7 @@ fn compare_number_of_method_arguments<'tcx>( } } - return Err(err.emit_unless_delay(delay)); + return Err(err.emit_err_unless_delay(delay)); } Ok(()) @@ -2028,7 +2028,7 @@ fn compare_synthetic_generics<'tcx>( ); }; } - error_found = Some(err.emit_unless_delay(delay)); + error_found = Some(err.emit_err_unless_delay(delay)); } } if let Some(reported) = error_found { Err(reported) } else { Ok(()) } @@ -2130,8 +2130,8 @@ fn compare_generic_param_kinds<'tcx>( err.span_context(impl_header_span); err.span_label(param_impl_span, make_param_message("found", param_impl)); - let reported = err.emit_unless_delay(delay); - return Err(reported); + let guar = err.emit_err_unless_delay(delay); + return Err(guar); } } @@ -2177,7 +2177,7 @@ pub(super) fn compare_const_directness<'tcx>( tcx.def_span(trait_const_item.def_id), "trait declaration of const is marked as `#[rustc_always_gca]`", ) - .emit() + .emit_err() } else { tcx.dcx() .struct_span_err( @@ -2188,7 +2188,7 @@ pub(super) fn compare_const_directness<'tcx>( tcx.def_span(trait_const_item.def_id), "trait declaration of const is not marked as `#[rustc_always_gca]`", ) - .emit() + .emit_err() }; Err(guar) } @@ -2303,7 +2303,7 @@ fn compare_const_clause_entailment<'tcx>( false, None, ); - return Err(diag.emit()); + return Err(diag.emit_err()); }; // Check that all obligations are satisfied by the implementation's diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index 8d936b2cd3498..fa2b3e9f25342 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -724,7 +724,7 @@ pub fn check_function_signature<'tcx>( false, None, ); - return Err(diag.emit()); + return Err(diag.emit_err()); } } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 30947ce0f4f98..bde17c39e2bc4 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -292,7 +292,7 @@ pub(super) fn check_item<'tcx>( .struct_span_err(sp, "impls of auto traits cannot be default") .with_span_labels(of_trait.defaultness_span, "default because of this") .with_span_label(sp, "auto trait") - .emit()); + .emit_err()); } match header.polarity { ty::ImplPolarity::Positive => { @@ -312,7 +312,7 @@ pub(super) fn check_item<'tcx>( E0750, "negative impls cannot be default impls" ) - .emit()); + .emit_err()); } } } @@ -905,7 +905,7 @@ fn check_param_wf(tcx: TyCtxt<'_>, param: &ty::GenericParamDef) -> Result<(), Er tcx.disabled_nightly_features(&mut diag, features); } - Err(diag.emit()) + Err(diag.emit_err()) } } } @@ -1780,7 +1780,7 @@ fn check_method_receiver<'tcx>( ), ) .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) - .emit() + .emit_err() } None | Some(ArbitrarySelfTypesLevel::Basic) if receiver_is_valid( @@ -1804,7 +1804,7 @@ fn check_method_receiver<'tcx>( ), ) .with_help(msg!("consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc`")) - .emit() + .emit_err() } _ => // Report error; would not have worked with `arbitrary_self_types[_pointers]`. @@ -2213,7 +2213,7 @@ fn report_bivariance<'tcx>( // Silence potentially redundant error, as the item had a parse error. diag.delay_as_bug() } else { - diag.emit() + diag.emit_err() } } @@ -2403,7 +2403,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { ); err.note(format!("it is a {ty}")); err.note(format!("and here it is `Debug`ged :3 {ty:?}")); - r = Err(err.emit()); + r = Err(err.emit_err()); } } } diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index 3c8bd2af9b4c1..f6be7a27cc8cf 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -12,8 +12,8 @@ struct UnusedImport<'tcx> { span: Span, } -impl<'a, 'tcx> Diagnostic<'a, ()> for UnusedImport<'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'tcx> Diagnostic<'a> for UnusedImport<'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { tcx, span } = self; if let Ok(snippet) = tcx.sess.source_map().span_to_snippet(span) { Diag::new(dcx, level, format!("unused import: `{snippet}`")) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index f7faefa240abe..e9adabc7ca4bb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -1003,7 +1003,7 @@ fn infringing_fields_error<'tcx>( None, ); - err.emit() + err.emit_err() } fn visit_implementation_of_coerce_pointee_validity( diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs index 9052f11e109b6..05ceb049e0dba 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls_overlap.rs @@ -91,7 +91,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { ) .with_span_label(span, format!("duplicate definitions for `{ident}`")) .with_span_label(*former, format!("other definition for `{ident}`")) - .emit()); + .emit_err()); } IndexEntry::Vacant(entry) => { entry.insert(span); @@ -142,7 +142,7 @@ impl<'tcx> InherentOverlapChecker<'tcx> { traits::add_placeholder_note(&mut err); } - res = Err(err.emit()); + res = Err(err.emit_err()); } } res diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index 894cd584ae41d..e3f4f8d0507d3 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -87,7 +87,7 @@ fn enforce_trait_manually_implementable( err.code(E0328); } - return Err(err.emit()); + return Err(err.emit_err()); } if let ty::trait_def::TraitSpecializationKind::AlwaysApplicable = trait_def.specialization_kind @@ -135,7 +135,7 @@ fn enforce_empty_impls_for_marker_traits( E0715, "impls for marker traits cannot contain items" ) - .emit()) + .emit_err()) } /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`]. @@ -239,7 +239,7 @@ fn check_object_overlap<'tcx>( tcx.def_path_str(trait_def_id) ), ) - .emit()); + .emit_err()); } } } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 44a1211687c29..496994096d69b 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -487,7 +487,7 @@ fn emit_orphan_check_error<'tcx>( } } - diag.emit() + diag.emit_err() } traits::OrphanCheckErr::UncoveredTyParams(UncoveredTyParams { uncovered, local_ty }) => { let mut guar = None; diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index ce0171a4d2d7d..18ba46ff08913 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -49,7 +49,7 @@ pub(super) fn check_item( "", rustc_errors::Applicability::MachineApplicable, ) - .emit()); + .emit_err()); } (Safety::Unsafe, _, Safety::Safe, Positive) => { @@ -83,7 +83,7 @@ pub(super) fn check_item( "unsafe ", rustc_errors::Applicability::MaybeIncorrect, ) - .emit()); + .emit_err()); } (Safety::Safe, Some(attr_name), Safety::Safe, Positive) => { @@ -107,7 +107,7 @@ pub(super) fn check_item( "unsafe ", rustc_errors::Applicability::MaybeIncorrect, ) - .emit()); + .emit_err()); } (_, _, Safety::Unsafe, Negative) => { diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index f1c330aaeed57..02a7fa6f98791 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -319,7 +319,7 @@ impl<'tcx> ItemCtxt<'tcx> { ); } - diag.emit() + diag.emit_err() } #[instrument(level = "debug", skip(self), ret)] @@ -519,7 +519,7 @@ impl<'tcx> HirTyLowerer<'tcx> for ItemCtxt<'tcx> { " + /* 'a */", Applicability::HasPlaceholders, ) - .emit(); + .emit_err(); ty::Region::new_error(self.tcx(), guar) } else { // If we found elided lifetime during lowering of delegation parent or child @@ -812,8 +812,8 @@ pub(super) fn check_enum_variant_types(tcx: TyCtxt<'_>, def_id: LocalDefId) { msg: &'static str, } - impl<'a> Diagnostic<'a, ()> for ReprCIssue { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for ReprCIssue { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { msg } = self; Diag::new(dcx, level, msg) .with_note("`repr(C)` enums with big discriminants are non-portable, and their size in Rust might not match their size in C") @@ -1417,7 +1417,7 @@ fn recover_infer_ret_ty<'tcx>( https://doc.rust-lang.org/book/ch13-01-closures.html", ); } - let guar = diag.emit(); + let guar = diag.emit_err(); // If we return a dummy binder here, we can ICE later in borrowck when it encounters // `ReLateParam` regions (e.g. in a local type annotation) which weren't registered via the diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index 772bbe4a6b579..af6e689c33e13 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -103,7 +103,7 @@ pub(crate) fn clauses_and_item_bounds(tcx: TyCtxt<'_>) { for bound in bounds { diag.note(format!("{bound:?}")); } - diag.emit() + diag.emit_err() } kind => tcx.dcx().span_delayed_bug( tcx.def_span(id), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index c9deedb33ffc7..ee4e7471ee434 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -21,8 +21,8 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { msg: &'static str, } - impl<'a> Diagnostic<'a, ()> for GenericParametersForbiddenHere { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for GenericParametersForbiddenHere { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { msg } = self; Diag::new(dcx, level, msg) } diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index 1f35c302cc9f1..a6cc61d2f7bfe 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -2827,7 +2827,7 @@ fn deny_non_region_late_bound( format!("late-bound {what} parameter not allowed on {where_}"), ); - let guar = diag.emit_unless_delay(!tcx.features().non_lifetime_binders() || !first); + let guar = diag.emit_err_unless_delay(!tcx.features().non_lifetime_binders() || !first); first = false; *arg = ResolvedArg::Error(guar); diff --git a/compiler/rustc_hir_analysis/src/collect/type_of.rs b/compiler/rustc_hir_analysis/src/collect/type_of.rs index dc86f2837da8e..8754430aaa99e 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of.rs @@ -541,7 +541,7 @@ fn infer_placeholder_type<'tcx>( } } - diag.emit() + diag.emit_err() }); Ty::new_error(tcx, guar) } diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs index 66167e0042982..5ffbe693180f0 100644 --- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs +++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs @@ -119,7 +119,7 @@ impl<'tcx> TaitConstraintLocator<'tcx> { if let Some(prev) = &mut self.found { if hidden_ty.ty != prev.ty { let (Ok(guar) | Err(guar)) = - prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit()); + prev.build_mismatch_error(&hidden_ty, self.tcx).map(|d| d.emit_err()); *prev = ty::DefinitionSiteHiddenType::new_error(self.tcx, guar); } } else { diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index 1f0c493b881f1..ff5f7dbb119f1 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -467,9 +467,9 @@ pub(crate) struct MissingGenericParams { } // FIXME: This doesn't need to be a manual impl! -impl<'a, G> Diagnostic<'a, G> for MissingGenericParams { +impl<'a> Diagnostic<'a> for MissingGenericParams { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut err = Diag::new( dcx, level, @@ -2069,8 +2069,8 @@ pub(crate) struct UncoveredTyParam<'tcx> { pub(crate) local_ty: Option>, } -impl Diagnostic<'_, G> for UncoveredTyParam<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for UncoveredTyParam<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let Self { param, local_ty } = self; let mut diag = Diag::new(dcx, level, "") diff --git a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs index e995d4fdf697b..fb1239e0e6ad0 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs @@ -543,7 +543,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Builds the `expected 1 type argument / supplied 2 type arguments` message. - fn notify(&self, err: &mut Diag<'_, G>) { + fn notify(&self, err: &mut Diag<'_>) { let (quantifier, bound) = self.get_quantifier_and_bound(); let provided_args = self.num_provided_args(); @@ -595,7 +595,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest(&self, err: &mut Diag<'_, G>) { + fn suggest(&self, err: &mut Diag<'_>) { debug!( "suggest(self.provided {:?}, self.gen_args.span(): {:?})", self.num_provided_args(), @@ -623,7 +623,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_adding_args(&self, err: &mut Diag<'_, G>) { + fn suggest_adding_args(&self, err: &mut Diag<'_>) { if self.gen_args.parenthesized != hir::GenericArgsParentheses::No { return; } @@ -650,7 +650,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_, G>) { + fn suggest_adding_lifetime_args(&self, err: &mut Diag<'_>) { debug!("suggest_adding_lifetime_args(path_segment: {:?})", self.path_segment); let num_missing_args = self.num_missing_lifetime_args(); let num_params_to_take = num_missing_args; @@ -704,7 +704,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_, G>) { + fn suggest_adding_type_and_const_args(&self, err: &mut Diag<'_>) { let num_missing_args = self.num_missing_type_or_const_args(); let msg = format!("add missing {} argument{}", self.kind(), pluralize!(num_missing_args)); @@ -764,7 +764,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```compile_fail /// Into::into::>(42) // suggests considering `Into::>::into(42)` /// ``` - fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diag<'_, G>) { + fn suggest_moving_args_from_assoc_fn_to_trait(&self, err: &mut Diag<'_>) { let Some(trait_) = self.tcx.trait_of_assoc(self.def_id) else { return; }; @@ -817,9 +817,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path( + fn suggest_moving_args_from_assoc_fn_to_trait_for_qualified_path( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, qpath: &'tcx hir::QPath<'tcx>, msg: String, num_assoc_fn_excess_args: usize, @@ -848,9 +848,9 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } - fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call( + fn suggest_moving_args_from_assoc_fn_to_trait_for_method_call( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, trait_def_id: DefId, expr: &'tcx hir::Expr<'tcx>, msg: String, @@ -904,7 +904,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { /// ```text /// type Map = HashMap; /// ``` - fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_, G>) { + fn suggest_removing_args_or_generics(&self, err: &mut Diag<'_>) { let num_provided_lt_args = self.num_provided_lifetime_args(); let num_provided_type_const_args = self.num_provided_type_or_const_args(); let unbound_assoc_items = self.get_unbound_associated_item(); @@ -920,7 +920,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { let remove_entire_generics = num_redundant_args >= self.gen_args.args.len(); - let remove_lifetime_args = |err: &mut Diag<'_, _>| { + let remove_lifetime_args = |err: &mut Diag<'_>| { let mut lt_arg_spans = Vec::new(); let mut found_redundant = false; for arg in self.gen_args.args { @@ -963,7 +963,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { ); }; - let remove_type_or_const_args = |err: &mut Diag<'_, _>| { + let remove_type_or_const_args = |err: &mut Diag<'_>| { let mut gen_arg_spans = Vec::new(); let mut found_redundant = false; for arg in self.gen_args.args { @@ -1096,7 +1096,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Builds the `type defined here` message. - fn show_definition(&self, err: &mut Diag<'_, G>) { + fn show_definition(&self, err: &mut Diag<'_>) { let Some(def_span) = self.tcx.def_ident_span(self.def_id) else { return }; if !self.tcx.sess.source_map().is_span_accessible(def_span) { return; @@ -1143,7 +1143,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } /// Add note if `impl Trait` is explicitly specified. - fn note_synth_provided(&self, err: &mut Diag<'_, G>) { + fn note_synth_provided(&self, err: &mut Diag<'_>) { if !self.is_synth_provided() { return; } @@ -1152,12 +1152,12 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { } } -impl<'a, G> Diagnostic<'a, G> for WrongNumberOfGenericArgs<'_, '_> { +impl<'a> Diagnostic<'a> for WrongNumberOfGenericArgs<'_, '_> { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: rustc_errors::Level, - ) -> Diag<'a, G> { + ) -> Diag<'a> { let msg = self.create_error_message(); let mut err = Diag::new(dcx, level, msg); err.code(E0107); diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 7f0c6910cc425..011ca64b7f32a 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -564,7 +564,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { constraint.span, "use of trait associated const not defined as `#[rustc_always_gca]`", ); - return Err(err.emit()); + return Err(err.emit_err()); } else { let err = self.dcx().span_delayed_bug( constraint.span, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index beacb3f188cd9..c8ed17d169577 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -138,7 +138,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_pred.def_id(), &violations, ) - .emit(); + .emit_err(); return Ty::new_error(tcx, reported); } } @@ -578,8 +578,8 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { this: &'a dyn HirTyLowerer<'tcx>, } - impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for TraitObjectWithoutDyn<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'tcx> Diagnostic<'a> for TraitObjectWithoutDyn<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { span, hir_id, sugg, this } = self; let mut lint = Diag::new(dcx, level, "trait objects without an explicit `dyn` are deprecated"); @@ -665,7 +665,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { s1.append(s2); sugg.cancel(); } - Some(diag.emit()) + Some(diag.emit_err()) } else { tcx.emit_node_span_lint( BARE_TRAIT_OBJECTS, @@ -739,11 +739,11 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } /// Make sure that we are in the condition to suggest the blanket implementation. - fn maybe_suggest_blanket_trait_impl( + fn maybe_suggest_blanket_trait_impl( &self, span: Span, hir_id: hir::HirId, - diag: &mut Diag<'_, G>, + diag: &mut Diag<'_>, ) { let tcx = self.tcx(); let parent_id = tcx.hir_get_parent_item(hir_id).def_id; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index 5d4770e1fc7de..f2cf4743d76b6 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -314,7 +314,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { Applicability::MaybeIncorrect, ); } - return err.emit(); + return err.emit_err(); } } return self.dcx().emit_err(err); @@ -534,7 +534,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { where_bounds.join(",\n"), )); } - err.emit() + err.emit_err() } pub(crate) fn report_missing_self_ty_for_resolved_path( @@ -681,7 +681,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.span_label(sp, format!("variant `{ident}` not found here")); } - err.emit() + err.emit_err() } else if let Err(reported) = self_ty.error_reported() { reported } else { @@ -813,7 +813,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } } - err.emit() + err.emit_err() } pub(crate) fn report_ambiguous_inherent_assoc_item( @@ -830,7 +830,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); err.span_label(name.span, format!("multiple `{name}` found")); self.note_ambiguous_inherent_assoc_item(&mut err, candidates, span); - err.emit() + err.emit_err() } // FIXME(fmease): Heavily adapted from `rustc_hir_typeck::method::suggest`. Deduplicate. @@ -940,7 +940,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "the associated {assoc_tag_str} was found for\n{type_candidates}{additional_types}", )); add_def_label(&mut err); - return err.emit(); + return err.emit_err(); } let mut bound_spans: SortedMap> = Default::default(); @@ -1048,7 +1048,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.span_label(span, msg); } add_def_label(&mut err); - err.emit() + err.emit_err() } /// If there are any missing associated items, emit an error instructing the user to provide @@ -1100,7 +1100,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { trait_ref.def_id(), &violations, ) - .emit()); + .emit_err()); } names.entry(trait_ref).or_default().push(assoc_item.name()); @@ -1340,7 +1340,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { } } - Err(err.emit()) + Err(err.emit_err()) } /// On ambiguous associated type, look for an associated function whose name matches the @@ -1392,7 +1392,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { name, Applicability::MaybeIncorrect, ) - .emit()) + .emit_err()) } else { Ok(()) } @@ -1477,7 +1477,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { err.span_label(span, format!("not allowed on {what}")); } generics_args_err_extend(self.tcx(), segments.into_iter(), &mut err, err_extend); - err.emit() + err.emit_err() } pub fn report_trait_object_addition_traits( @@ -1520,7 +1520,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { for more information on them, visit \ ", ); - err.emit() + err.emit_err() } pub fn report_trait_object_with_no_traits( @@ -1715,7 +1715,7 @@ pub fn prohibit_assoc_item_constraint( } } - err.emit() + err.emit_err() } pub(crate) fn fn_trait_to_string( @@ -2004,12 +2004,12 @@ pub(super) struct AmbiguityBetweenVariantAndAssocItem<'tcx> { pub(super) mode: super::LowerTypeRelativePathMode, } -impl<'a, 'tcx> rustc_errors::Diagnostic<'a, ()> for AmbiguityBetweenVariantAndAssocItem<'tcx> { +impl<'a, 'tcx> rustc_errors::Diagnostic<'a> for AmbiguityBetweenVariantAndAssocItem<'tcx> { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: rustc_errors::Level, - ) -> Diag<'a, ()> { + ) -> Diag<'a> { let Self { variant_def_id, item_def_id, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 4a35bcb5ef28f..25a17abdbf61c 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -70,7 +70,7 @@ fn generic_arg_mismatch_err( add_braces_suggestion(arg, &mut err); return err .with_primary_message("unresolved item provided when a constant was expected") - .emit(); + .emit_err(); } Res::Def(DefKind::TyParam, src_def_id) => { if let Some(param_local_id) = param.def_id.as_local() { @@ -145,7 +145,7 @@ fn generic_arg_mismatch_err( } } - err.emit() + err.emit_err() } /// Lower generic arguments from the HIR to the [`rustc_middle::ty`] representation. @@ -606,7 +606,7 @@ pub(crate) fn check_generic_arg_count( gen_args, def_id, )) - .emit_unless_delay(all_params_are_binded || has_invalid_bound) + .emit_err_unless_delay(all_params_are_binded || has_invalid_bound) }); Err(reported) @@ -655,8 +655,8 @@ pub(crate) fn prohibit_explicit_late_bound_lifetimes( msg: &'static str, } - impl<'a> Diagnostic<'a, ()> for LifetimeArgsIssue { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for LifetimeArgsIssue { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { msg } = self; Diag::new(dcx, level, msg) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index c66416802f0ea..6bb1c4d04e065 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -452,7 +452,7 @@ impl<'tcx> ForbidParamUsesFolder<'tcx> { diag.help("alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item"); } } - diag.emit() + diag.emit_err() } } @@ -1718,7 +1718,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span, "inherent associated types are unstable", ) - .emit()); + .emit_err()); } ty::AssocTag::Fn => unreachable!(), } @@ -2767,7 +2767,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { format!("`{}` does not have this field", variant_def.name), ); } - return ty::Const::new_error(tcx, err.emit()); + return ty::Const::new_error(tcx, err.emit_err()); } } @@ -2977,7 +2977,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let guar = self .dcx() .struct_span_err(span, "function items cannot be used as const args") - .emit(); + .emit_err(); Const::new_error(tcx, guar) } // Exhaustive match to be clear about what exactly we're considering to be @@ -3168,7 +3168,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { "only consts with a `direct_const_arg!` right-hand side may be used in types", ); } - Err(err.emit()) + Err(err.emit_err()) } } @@ -3501,7 +3501,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { field.span.shrink_to_lo(), "you might be missing a variant here: `Variant.`", ) - .emit(); + .emit_err(); return Ty::new_error(tcx, err); }; diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs index e1a91292abe21..4615f1ae4fe58 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs @@ -179,7 +179,7 @@ pub(crate) fn enforce_impl_lifetime_params_are_constrained( } } suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, param, true); - res = Err(diag.emit()); + res = Err(diag.emit_err()); } } ty::GenericParamDefKind::Type { .. } | ty::GenericParamDefKind::Const { .. } => { @@ -245,7 +245,7 @@ pub(crate) fn enforce_impl_non_lifetime_params_are_constrained( }); diag.code(E0207); suggest_to_remove_or_use_generic(tcx, &mut diag, impl_def_id, ¶m, false); - res = Err(diag.emit()); + res = Err(diag.emit_err()); } } res diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs index d56c094f9f5c3..fdc6357bb9bbe 100644 --- a/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs +++ b/compiler/rustc_hir_analysis/src/impl_wf_check/min_specialization.rs @@ -281,7 +281,7 @@ fn check_duplicate_params<'tcx>( return Err(tcx .dcx() .struct_span_err(span, format!("specializing impl repeats parameter `{param}`")) - .emit()); + .emit_err()); } Ok(()) } @@ -430,7 +430,7 @@ fn check_specialization_on<'tcx>( tcx.def_path_str(trait_ref.def_id), ), ) - .emit()) + .emit_err()) } } ty::ClauseKind::Projection(ty::ProjectionClause { projection_term, term }) => Err(tcx @@ -439,7 +439,7 @@ fn check_specialization_on<'tcx>( span, format!("cannot specialize on associated type `{projection_term} == {term}`",), ) - .emit()), + .emit_err()), ty::ClauseKind::ConstArgHasType(..) => { // FIXME(min_specialization), FIXME(const_generics): // It probably isn't right to allow _every_ `ConstArgHasType` but I am somewhat unsure @@ -454,7 +454,7 @@ fn check_specialization_on<'tcx>( _ => Err(tcx .dcx() .struct_span_err(span, format!("cannot specialize on predicate `{clause}`")) - .emit()), + .emit_err()), } } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index 8a919ede26605..a539898b8fced 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -127,7 +127,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: autoderef.final_ty(), }); err.span_label(callee_expr.span, "you can create scalable vectors using intrinsics"); - Ty::new_error(self.tcx, err.emit()); + Ty::new_error(self.tcx, err.emit_err()); } self.register_predicates(autoderef.into_obligations()); @@ -1069,7 +1069,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { err.span_label(span, label); } } - err.emit() + err.emit_err() } fn confirm_deferred_closure_call( diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index a82290d395de3..02e6b8188a876 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -733,7 +733,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { err.span_help(self.expr_span, "consider using a box or reference as appropriate"); } } - err.emit() + err.emit_err() } fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx>) { diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 22349259b32a6..4a494fda7ca80 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -778,7 +778,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { true, closure_arg_span, ) - .emit(); + .emit_err(); let error_sig = self.error_sig_of_closure(decl, guar); diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index 8a4228ebe3124..c13e68fea210d 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -1913,9 +1913,9 @@ impl<'tcx> CoerceMany<'tcx> { ); } - let reported = err.emit_unless_delay(unsized_return); + let guar = err.emit_err_unless_delay(unsized_return); - self.final_ty = Some(Ty::new_error(fcx.tcx, reported)); + self.final_ty = Some(Ty::new_error(fcx.tcx, guar)); } } } diff --git a/compiler/rustc_hir_typeck/src/diagnostics.rs b/compiler/rustc_hir_typeck/src/diagnostics.rs index 3b7de7790ac02..4885b31ead454 100644 --- a/compiler/rustc_hir_typeck/src/diagnostics.rs +++ b/compiler/rustc_hir_typeck/src/diagnostics.rs @@ -275,7 +275,7 @@ pub(crate) struct SuggestAnnotations { pub suggestions: Vec, } impl Subdiagnostic for SuggestAnnotations { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { if self.suggestions.is_empty() { return; } @@ -338,7 +338,7 @@ pub(crate) struct TypeMismatchFruTypo { } impl Subdiagnostic for TypeMismatchFruTypo { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.arg("expr", self.expr.as_deref().unwrap_or("NONE")); // Only explain that `a ..b` is a range if it's split up @@ -561,7 +561,7 @@ pub(crate) struct RemoveSemiForCoerce { } impl Subdiagnostic for RemoveSemiForCoerce { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut multispan: MultiSpan = self.semi.into(); multispan.push_span_label( self.expr, @@ -704,9 +704,9 @@ pub(crate) struct BreakNonLoop<'a> { pub break_expr_span: Span, } -impl<'a, G> Diagnostic<'_, G> for BreakNonLoop<'a> { +impl<'a> Diagnostic<'_> for BreakNonLoop<'a> { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new(dcx, level, msg!("`break` with value from a `{$kind}` loop")); diag.span(self.span); diag.code(E0571); @@ -906,7 +906,7 @@ pub(crate) enum CastUnknownPointerSub { } impl rustc_errors::Subdiagnostic for CastUnknownPointerSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { CastUnknownPointerSub::To(span) => { let msg = msg!("needs more type information"); @@ -1202,9 +1202,9 @@ pub(crate) struct NakedFunctionsAsmBlock { pub non_asms: Vec, } -impl Diagnostic<'_, G> for NakedFunctionsAsmBlock { +impl Diagnostic<'_> for NakedFunctionsAsmBlock { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 92122c38e4ed3..2935641058b20 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -439,7 +439,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .may_apply() }) }); - Ty::new_error(tcx, err.emit()) + Ty::new_error(tcx, err.emit_err()) }), hir::UnOp::Not => { let result = self.check_user_unop(expr, oprnd_t, unop, expected_inner); @@ -1399,7 +1399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // If the assignment expression itself is ill-formed, don't // bother emitting another error - err.emit_unless_delay(lhs_ty.references_error() || rhs_ty.references_error()) + err.emit_err_unless_delay(lhs_ty.references_error() || rhs_ty.references_error()) } pub(super) fn check_expr_let( @@ -1619,7 +1619,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ) .with_note("unsafe binders are the only valid output of wrap") - .emit(); + .emit_err(); Ty::new_error(self.tcx, guar) } }; @@ -1657,7 +1657,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ) .with_note("only an unsafe binder type can be unwrapped") - .emit(); + .emit_err(); Ty::new_error(self.tcx, guar) } } @@ -2699,7 +2699,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { }; } } - err.emit() + err.emit_err() } fn available_field_names( @@ -2929,7 +2929,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } } - err.emit() + err.emit_err() }; Ty::new_error(self.tcx(), guar) @@ -3040,7 +3040,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { HelpUseLatestEdition::new().add_to_diag(&mut err); } - err.emit() + err.emit_err() } fn ban_private_field_access( @@ -3066,7 +3066,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None, ); } - err.emit() + err.emit_err() } fn ban_take_value_of_method( @@ -3523,8 +3523,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - let reported = err.emit(); - Ty::new_error(self.tcx, reported) + let guar = err.emit_err(); + Ty::new_error(self.tcx, guar) } } } @@ -3834,7 +3834,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.dcx() .create_err(NoVariantNamed { span: ident.span, ident, ty: container }) .with_span_label(field.span, "variant not found") - .emit_unless_delay(container.references_error()); + .emit_err_unless_delay(container.references_error()); break; }; let Some(&subfield) = fields.next() else { @@ -3866,7 +3866,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { enum_span: field.span, field_span: subident.span, }) - .emit_unless_delay(container.references_error()); + .emit_err_unless_delay(container.references_error()); break; }; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index b9f3e2479a903..15383cd8a2a53 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -57,8 +57,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { custom_note: Option<&'b str>, } - impl<'a, 'b, 'c> Diagnostic<'a, ()> for UnreachableItem<'b, 'c> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'c> Diagnostic<'a> for UnreachableItem<'b, 'c> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { kind, span, orig_span, custom_note } = self; let msg = format!("unreachable {kind}"); Diag::new(dcx, level, msg.clone()).with_span_label(span, msg).with_span_label( @@ -1301,8 +1301,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - let reported = err.emit(); - return (Ty::new_error(tcx, reported), res); + let guar = err.emit_err(); + return (Ty::new_error(tcx, guar), res); } } } else { @@ -1563,7 +1563,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { TypeAnnotationNeeded::E0282, true, ) - .emit() + .emit_err() }); let err = Ty::new_error(self.tcx, guar); self.demand_suptype(sp, err, ty); @@ -1589,7 +1589,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { TypeAnnotationNeeded::E0282, true, ) - .emit() + .emit_err() }); // FIXME: Infer `?ct = {const error}`? ty::Const::new_error(self.tcx, e) diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 9965a9d071031..789d06722f897 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -693,7 +693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { must be a tuple or unit type: {:?}", type_errors, ) - .emit(); + .emit_err(); Ty::new_error(self.tcx, guar) } } else { @@ -758,7 +758,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { "cannot use call notation; the first type parameter \ for the function trait is neither a tuple nor unit" ) - .emit(); + .emit_err(); Some(guar) } else if tuple_arguments.is_splatted() { @@ -789,7 +789,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .kind(), ) - .emit(); + .emit_err(); Some(guar) } else if formal_input_tys.len() != provided_args.len() { @@ -803,7 +803,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { provided_args.len(), if provided_args.len() == 1 { "was" } else { "were" }, ) - .emit(); + .emit_err(); Some(guar) } else { @@ -978,7 +978,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ); } - err.emit() + err.emit_err() } fn suggest_ptr_null_mut( @@ -1123,7 +1123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty.normalized.sort_string(self.tcx) ) .with_span_label(path_span, "not a struct") - .emit(), + .emit_err(), }) } } @@ -2363,7 +2363,7 @@ impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> { self.tuple_arguments, ); self.suggest_confusable(&mut err); - Some(err.emit()) + Some(err.emit_err()) } else { None } @@ -2384,7 +2384,7 @@ impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> { span: self.call_metadata.error_span, }); self.arg_matching_ctxt.suggest_confusable(&mut err); - return Some(err.emit()); + return Some(err.emit_err()); } } @@ -2440,7 +2440,7 @@ impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> { *e, ); self.arg_matching_ctxt.suggest_confusable(&mut err); - reported = Some(err.emit()); + reported = Some(err.emit_err()); return false; } true @@ -2522,7 +2522,7 @@ impl<'a, 'tcx> FnCallDiagCtxt<'a, 'tcx> { ); self.arg_matching_ctxt.suggest_confusable(&mut err); self.detect_dotdot(&mut err, provided_ty, self.provided_args[provided_idx]); - return Some(err.emit()); + return Some(err.emit_err()); } None diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 2b1d9ed038b87..6470e45b3bb3a 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -207,8 +207,8 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { default_size: InlineAsmSize, } - impl<'a, 'b> Diagnostic<'a, ()> for FormattingSubRegisterArg<'b> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b> Diagnostic<'a> for FormattingSubRegisterArg<'b> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { expr_span, idx, diff --git a/compiler/rustc_hir_typeck/src/intrinsicck.rs b/compiler/rustc_hir_typeck/src/intrinsicck.rs index 2e52517de07d1..d2432a7e39af6 100644 --- a/compiler/rustc_hir_typeck/src/intrinsicck.rs +++ b/compiler/rustc_hir_typeck/src/intrinsicck.rs @@ -126,11 +126,11 @@ fn check_transmute<'tcx>( ); if from == to { err.note(format!("`{from}` does not have a fixed size")); - Err(err.emit()) + Err(err.emit_err()) } else { err.note(format!("source type: `{}` ({})", from, skeleton_string(from, sk_from))); err.note(format!("target type: `{}` ({})", to, skeleton_string(to, sk_to))); - Err(err.emit()) + Err(err.emit_err()) } } @@ -144,15 +144,15 @@ fn check_offload<'tcx>( ) -> Result<(), ErrorGuaranteed> { let span = tcx.hir_span(hir_id); let ty::FnDef(kernel_def_id, kernel_args) = *kernel_ty.kind() else { - let err = tcx + let guar = tcx .sess .dcx() .struct_span_err( span, format!("expected a function item for the offload kernel, found `{}`", kernel_ty), ) - .emit(); - return Err(err); + .emit_err(); + return Err(guar); }; let kernel_sig = @@ -160,19 +160,19 @@ fn check_offload<'tcx>( let kernel_sig = tcx.instantiate_bound_regions_with_erased(kernel_sig); let ty::Tuple(tuple_fields) = *args_ty.kind() else { - let err = tcx + let guar = tcx .sess .dcx() .struct_span_err( span, format!("expected a tuple for the offload arguments, found `{}`", args_ty), ) - .emit(); - return Err(err); + .emit_err(); + return Err(guar); }; if kernel_sig.inputs().len() != tuple_fields.len() { - let err = tcx + let guar = tcx .sess .dcx() .struct_span_err( @@ -183,8 +183,8 @@ fn check_offload<'tcx>( tuple_fields.len() ), ) - .emit(); - return Err(err); + .emit_err(); + return Err(guar); } let normalize = |ty| { @@ -206,7 +206,7 @@ fn check_offload<'tcx>( let norm_input_ty = normalize(input_ty); let norm_arg_ty = normalize(arg_ty); if norm_input_ty != norm_arg_ty { - let err = tcx + let guar = tcx .sess .dcx() .struct_span_err( @@ -216,22 +216,22 @@ fn check_offload<'tcx>( i, norm_input_ty, norm_arg_ty ), ) - .emit(); - result = Err(err); + .emit_err(); + result = Err(guar); } } let norm_kernel_ret = normalize(kernel_sig.output()); let norm_offload_ret = normalize(ret_ty); if norm_kernel_ret != norm_offload_ret { - let err = tcx.sess.dcx().struct_span_err( + let guar = tcx.sess.dcx().struct_span_err( span, format!( "offload kernel return type mismatch: kernel returns `{}`, but offload call expects `{}`", norm_kernel_ret, norm_offload_ret ) - ).emit(); - result = Err(err); + ).emit_err(); + result = Err(guar); } result diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index dd3b5d4429975..474a390171514 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -607,7 +607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => err.with_span_label(span, format!("not a {expected}")), } - .emit() + .emit_err() } } @@ -714,7 +714,7 @@ fn fatally_break_rust(tcx: TyCtxt<'_>, span: Span) -> ! { diag.note("some of the compiler flags provided by cargo are hidden"); } } - diag.emit() + diag.emit_bug() } /// Adds query implementations to the [Providers] vtable, see [`rustc_middle::query`] diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index d961fdc0885b7..4587e9726a9d7 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -24,8 +24,8 @@ struct AmbiguousTraitMethodCall<'a, 'tcx> { edition: &'static str, } -impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for AmbiguousTraitMethodCall<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'b, 'tcx> Diagnostic<'a> for AmbiguousTraitMethodCall<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { segment_name, self_expr_span, pick, tcx, edition } = self; let mut lint = Diag::new( dcx, @@ -91,8 +91,8 @@ struct AmbiguousTraitMethod<'a, 'tcx, 'fnctx> { this: &'a FnCtxt<'fnctx, 'tcx>, } -impl<'a, 'c, 'tcx, 'fnctx> Diagnostic<'a, ()> for AmbiguousTraitMethod<'c, 'tcx, 'fnctx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'c, 'tcx, 'fnctx> Diagnostic<'a> for AmbiguousTraitMethod<'c, 'tcx, 'fnctx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { segment, call_expr, self_expr, pick, args, edition, span, this } = self; let mut lint = Diag::new( dcx, @@ -289,8 +289,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self_ty: Ty<'tcx>, } - impl<'a, 'b, 'fnctx, 'tcx> Diagnostic<'a, ()> for AmbiguousTraitAssocFunc<'b, 'fnctx, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'fnctx, 'tcx> Diagnostic<'a> for AmbiguousTraitAssocFunc<'b, 'fnctx, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { method_name, this, pick, span, expr_id, self_ty_span, self_ty } = self; let mut lint = Diag::new( dcx, diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 79b8ef15d7e13..58e482adff190 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -555,7 +555,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if raw_ptr_call { err.span_label(span, "cannot call a method on a raw pointer with an unknown pointee type"); } - err.emit() + err.emit_err() } ty::Error(guar) => guar, _ => bug!("unexpected bad final type in method autoderef"), @@ -1876,8 +1876,8 @@ impl<'tcx> Pick<'tcx> { span: Span, } - impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for ItemMaybeBeAddedToStd<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'tcx> Diagnostic<'a> for ItemMaybeBeAddedToStd<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { this, tcx, span } = self; let def_kind = this.item.as_def_kind(); let mut lint = Diag::new( diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index aebfeac2e7e85..e074ebf01bda4 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -352,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut sources, Some(expr_span), ); - err.emit() + err.emit_err() } MethodError::PrivateMatch(kind, def_id, out_of_scope_traits) => { @@ -374,7 +374,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } self.suggest_valid_traits(&mut err, item_name, out_of_scope_traits, true); self.suggest_unwrapping_inner_self(&mut err, source, rcvr_ty, item_name); - err.emit() + err.emit_err() } MethodError::IllegalSizedBound { candidates, needs_mut, bound_span, self_expr } => { @@ -471,7 +471,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit() + err.emit_err() } MethodError::ErrorReported(guar) => guar, @@ -1360,7 +1360,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &static_candidates, ) else { - return err.emit(); + return err.emit_err(); }; let similar_candidate = no_match_data.similar_candidate; @@ -1438,7 +1438,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_ident, expected); self.suggest_bounds_for_range_to_method(&mut err, source, item_ident); - err.emit() + err.emit_err() } fn set_not_found_span_label( @@ -3123,7 +3123,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => {} } - return Err(err.emit()); + return Err(err.emit_err()); } Ok(()) } diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index c5d082fba8016..48a0ec756d8d9 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -557,7 +557,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &mut err, ); - Ty::new_error(self.tcx, err.emit()) + Ty::new_error(self.tcx, err.emit_err()) } fn suggest_deref_or_call_for_binop_error( @@ -1060,7 +1060,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } } - err.emit() + err.emit_err() }); Ty::new_error(self.tcx, guar) } diff --git a/compiler/rustc_hir_typeck/src/opaque_types.rs b/compiler/rustc_hir_typeck/src/opaque_types.rs index 2fc2c0d80a255..c96144d849944 100644 --- a/compiler/rustc_hir_typeck/src/opaque_types.rs +++ b/compiler/rustc_hir_typeck/src/opaque_types.rs @@ -202,7 +202,7 @@ impl<'tcx> FnCtxt<'_, 'tcx> { // hint that the ambiguity is in an opaque's hidden type rather than an // ordinary local inference failure. .with_note("cannot infer type of hidden type of opaque") - .emit() + .emit_err() } } }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index a017b0dfcb507..cb1e66b710c79 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -156,7 +156,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { actual: Ty<'tcx>, ti: &TopInfo<'tcx>, ) -> Result<(), ErrorGuaranteed> { - self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit()) + self.demand_eqtype_pat_diag(cause_span, expected, actual, ti).map_err(|err| err.emit_err()) } } @@ -1143,7 +1143,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { type between two end-points, you can use a guard.", ); } - err.emit() + err.emit_err() } fn check_pat_ident( @@ -1493,7 +1493,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { if self.tcx.sess.teach(err.code.unwrap()) { err.note(CANNOT_IMPLICITLY_DEREF_POINTER_TRAIT_OBJ); } - return Err(err.emit()); + return Err(err.emit_err()); } Ok(()) } @@ -2028,7 +2028,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - err.emit() + err.emit_err() } fn check_pat_tuple( @@ -2198,7 +2198,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Err(e) } else { i.emit(); - Err(u.emit()) + Err(u.emit_err()) } } (None, Some(u)) => { @@ -2206,10 +2206,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { u.delay_as_bug(); Err(e) } else { - Err(u.emit()) + Err(u.emit_err()) } } - (Some(err), None) => Err(err.emit()), + (Some(err), None) => Err(err.emit_err()), (None, None) => { self.error_tuple_variant_index_shorthand(variant, pat, fields)?; result @@ -2244,7 +2244,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("({})", self.get_suggested_tuple_struct_pattern(fields, variant)), Applicability::MaybeIncorrect, ); - return Err(err.emit()); + return Err(err.emit_err()); } } Ok(()) @@ -2287,7 +2287,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ) .with_span_label(span, format!("multiple uses of `{ident}` in pattern")) .with_span_label(other_field, format!("first use of `{ident}`")) - .emit() + .emit_err() } fn error_inexistent_fields( @@ -2441,7 +2441,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { format!("({sugg})"), appl, ); - return Err(err.emit()); + return Err(err.emit_err()); } Ok(()) } @@ -2550,8 +2550,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ty: Ty<'tcx>, } - impl<'a, 'b, 'c, 'tcx> Diagnostic<'a, ()> for FieldsNotListed<'b, 'c, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'c, 'tcx> Diagnostic<'a> for FieldsNotListed<'b, 'c, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { pat_span, unmentioned_fields, joined_patterns, ty } = self; Diag::new(dcx, level, "some fields are not explicitly listed") .with_span_label(pat_span, format!("field{} {} not listed", rustc_errors::pluralize!(unmentioned_fields.len()), joined_patterns)) @@ -2997,7 +2997,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } else { self.dcx().struct_span_err(pat.span, err_msg) }; - err.emit() + err.emit_err() } fn try_resolve_slice_ty_to_array_ty( @@ -3194,7 +3194,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { size, ) .with_span_label(span, format!("expected {} element{}", size, pluralize!(size))) - .emit() + .emit_err() } fn error_scrutinee_with_rest_inconsistent_length( @@ -3216,7 +3216,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, format!("pattern cannot match array of {} element{}", size, pluralize!(size),), ) - .emit() + .emit_err() } fn error_scrutinee_unfixed_length(&self, span: Span) -> ErrorGuaranteed { @@ -3226,7 +3226,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { E0730, "cannot pattern-match on an array without a fixed length", ) - .emit() + .emit_err() } fn error_expected_array_or_slice( diff --git a/compiler/rustc_hir_typeck/src/place_op.rs b/compiler/rustc_hir_typeck/src/place_op.rs index 42ca305d3e00d..f3cba3a27d69f 100644 --- a/compiler/rustc_hir_typeck/src/place_op.rs +++ b/compiler/rustc_hir_typeck/src/place_op.rs @@ -92,8 +92,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { Applicability::MachineApplicable, ); } - let reported = err.emit(); - Some((Ty::new_error(self.tcx, reported), Ty::new_error(self.tcx, reported))) + let guar = err.emit_err(); + Some((Ty::new_error(self.tcx, guar), Ty::new_error(self.tcx, guar))) } /// To type-check `base_expr[index_expr]`, we progressively autoderef diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 875517ee4c87e..0443d48c597f1 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -1085,8 +1085,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { migration_message: String, } - impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for MigrationLint<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b, 'tcx> Diagnostic<'a> for MigrationLint<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { closure_def_id, closure_drop_location_span, diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index f4fe38924351a..5ae65ad26f916 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -619,7 +619,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { guar } else { let (Ok(guar) | Err(guar)) = - prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit()); + prev.build_mismatch_error(&hidden_type, tcx).map(|d| d.emit_err()); guar }; *entry = DefinitionSiteHiddenType::new_error(tcx, guar); @@ -656,7 +656,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { .dcx() .struct_span_err(span, "cannot resolve opaque type") .with_code(E0720) - .emit(); + .emit_err(); self.typeck_results .hidden_types .insert(def_id, DefinitionSiteHiddenType::new_error(tcx, guar)); @@ -947,7 +947,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> { TypeAnnotationNeeded::E0282, false, ) - .emit() + .emit_err() } } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 1950a29661249..3e73bdbf5985f 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -135,7 +135,7 @@ pub(crate) fn parse_check_cfg(sess: &Session, specs: Vec) -> CheckCfg { sess.dcx().struct_fatal(format!("invalid `--check-cfg` argument: `{s}`")); diag.note($reason); diag.note(VISIT); - diag.emit() + diag.emit_fatal() }}; (in $arg:expr, $reason:expr) => {{ let mut diag = @@ -154,7 +154,7 @@ pub(crate) fn parse_check_cfg(sess: &Session, specs: Vec) -> CheckCfg { diag.note($reason); diag.note(VISIT); - diag.emit() + diag.emit_fatal() }}; } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2316e80b6e945..610eb5fd099d2 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -72,7 +72,7 @@ pub fn parse<'a>(sess: &'a Session) -> ast::Crate { parser.parse_crate_mod() }) .unwrap_or_else(|parse_error| { - let guar: ErrorGuaranteed = parse_error.emit(); + let guar: ErrorGuaranteed = parse_error.emit_err(); guar.raise_fatal(); }); @@ -1057,13 +1057,13 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( struct DiagCallback<'tcx> { callback: Box< - dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + DynSync, + dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b> + DynSend + DynSync, >, tcx: TyCtxt<'tcx>, } -impl<'a, 'tcx> Diagnostic<'a, ()> for DiagCallback<'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'tcx> Diagnostic<'a> for DiagCallback<'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { (self.callback)(dcx, level, self.tcx.sess) } } diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 87b2bb94cd4f9..b6bfee02eed66 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -161,7 +161,7 @@ fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize { r#"`RUST_MIN_STACK` should be a number of bytes, but was "{s}""#, )); err.note("you can also unset `RUST_MIN_STACK` to use the default stack size"); - err.emit() + err.emit_fatal() }) }) // otherwise pick a consistent default @@ -338,7 +338,7 @@ internal compiler error: query cycle handler thread panicked, aborting process"; diag.help( "try lowering `-Z threads` or checking the operating system's resource limits", ); - diag.emit() + diag.emit_fatal() }) }) }) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2d571d8b8e13d..795e0b9130907 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -195,7 +195,7 @@ impl UnsafeCode { &self, cx: &EarlyContext<'_>, span: Span, - decorate: impl for<'a> Diagnostic<'a, ()>, + decorate: impl for<'a> Diagnostic<'a>, ) { // This comes from a macro that has `#[allow_internal_unsafe]`. if span.allows_unsafe() { diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index bd8e059bf0f95..68b2e2a3b6e7b 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -521,7 +521,7 @@ pub trait LintContext { &self, lint: &'static Lint, span: Option, - decorate: impl for<'a> Diagnostic<'a, ()>, + decorate: impl for<'a> Diagnostic<'a>, ); /// Emit a lint at `span` from a lint struct (some type that implements `Diagnostic`, @@ -531,7 +531,7 @@ pub trait LintContext { &self, lint: &'static Lint, span: S, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { self.opt_span_lint(lint, Some(span), decorator); } @@ -595,7 +595,7 @@ impl<'tcx> LintContext for LateContext<'tcx> { &self, lint: &'static Lint, span: Option, - decorate: impl for<'a> Diagnostic<'a, ()>, + decorate: impl for<'a> Diagnostic<'a>, ) { let hir_id = self.last_node_with_lint_attrs; @@ -622,7 +622,7 @@ impl LintContext for EarlyContext<'_> { &self, lint: &'static Lint, span: Option, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { self.builder.opt_span_lint(lint, span.map(|s| s.into()), decorator) } diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs index eba5efa25546b..6b20d6ffc41fe 100644 --- a/compiler/rustc_lint/src/default_could_be_derived.rs +++ b/compiler/rustc_lint/src/default_could_be_derived.rs @@ -164,8 +164,8 @@ struct WrongDefaultImpl<'a, 'tcx> { impl_span: Span, } -impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for WrongDefaultImpl<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'b, 'tcx> Diagnostic<'a> for WrongDefaultImpl<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { tcx, type_def_id, orig_fields, fields, impl_span } = self; let mut diag = Diag::new(dcx, level, "`Default` impl doesn't use the declared default field values"); diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index d96cadaca87eb..defb95e1f5fdc 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -42,7 +42,7 @@ pub(crate) enum OverruledAttributeSub { } impl Subdiagnostic for OverruledAttributeSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { OverruledAttributeSub::DefaultSource { id } => { diag.note(msg!("`forbid` lint level is the default for {$id}")); @@ -308,8 +308,8 @@ pub(crate) struct BuiltinMissingDebugImpl<'a> { } // Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for BuiltinMissingDebugImpl<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for BuiltinMissingDebugImpl<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { tcx, def_id } = self; Diag::new( dcx, @@ -368,8 +368,8 @@ pub(crate) struct BuiltinUngatedAsyncFnTrackCaller<'a> { pub session: &'a Session, } -impl<'a> Diagnostic<'a, ()> for BuiltinUngatedAsyncFnTrackCaller<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for BuiltinUngatedAsyncFnTrackCaller<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, "`#[track_caller]` on async functions is a no-op") .with_span_label(self.label, "this function will not propagate the caller location"); rustc_session::diagnostics::add_feature_diagnostics( @@ -412,8 +412,8 @@ pub(crate) struct BuiltinTypeAliasBounds<'hir> { pub ty: Option<&'hir hir::Ty<'hir>>, } -impl<'a> Diagnostic<'a, ()> for BuiltinTypeAliasBounds<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for BuiltinTypeAliasBounds<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, if self.in_where_clause { msg!("where clauses on type aliases are not enforced") } else { @@ -615,8 +615,8 @@ pub(crate) struct BuiltinUnpermittedTypeInit<'a> { pub tcx: TyCtxt<'a>, } -impl<'a> Diagnostic<'a, ()> for BuiltinUnpermittedTypeInit<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for BuiltinUnpermittedTypeInit<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, self.msg) .with_arg("ty", self.ty) .with_span_label(self.label, msg!("this code causes undefined behavior when executed")); @@ -638,7 +638,7 @@ pub(crate) struct BuiltinUnpermittedTypeInitSub { } impl Subdiagnostic for BuiltinUnpermittedTypeInitSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut err = self.err; loop { if let Some(span) = err.span { @@ -689,7 +689,7 @@ pub(crate) struct BuiltinClashingExternSub<'a> { } impl Subdiagnostic for BuiltinClashingExternSub<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut expected_str = DiagStyledString::new(); expected_str.push(self.expected.fn_sig(self.tcx).to_string(), false); let mut found_str = DiagStyledString::new(); @@ -1363,7 +1363,7 @@ pub(crate) struct NonBindingLetSub { } impl Subdiagnostic for NonBindingLetSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let can_suggest_binding = self.drop_fn_start_end.is_some() || !self.is_assign_desugar; if can_suggest_binding { @@ -1639,8 +1639,8 @@ pub(crate) struct NonFmtPanicUnused { } // Used because of two suggestions based on one Option -impl<'a> Diagnostic<'a, ()> for NonFmtPanicUnused { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for NonFmtPanicUnused { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, msg!( "panic message contains {$count -> [one] an unused @@ -1740,7 +1740,7 @@ pub(crate) enum NonSnakeCaseDiagSub { } impl Subdiagnostic for NonSnakeCaseDiagSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { NonSnakeCaseDiagSub::Label { span } => { diag.span_label(span, msg!("should have a snake_case name")); @@ -1876,8 +1876,8 @@ pub(crate) enum NonLocalDefinitionsDiag { }, } -impl<'a> Diagnostic<'a, ()> for NonLocalDefinitionsDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for NonLocalDefinitionsDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, ""); match self { NonLocalDefinitionsDiag::Impl { @@ -2046,8 +2046,8 @@ pub(crate) struct DropTraitConstraintsDiag<'a> { } // Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for DropTraitConstraintsDiag<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for DropTraitConstraintsDiag<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { Diag::new(dcx, level, msg!("bounds on `{$clause}` are most likely incorrect, consider instead using `{$needs_drop}` to detect whether a type can be trivially dropped")) .with_arg("clause", self.clause) .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) @@ -2060,8 +2060,8 @@ pub(crate) struct DropGlue<'a> { } // Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for DropGlue<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { Diag::new(dcx, level, msg!("types that do not implement `Drop` can still have drop glue, consider instead using `{$needs_drop}` to detect whether a type is trivially dropped")) .with_arg("needs_drop", self.tcx.def_path_str(self.def_id)) } @@ -2514,8 +2514,8 @@ pub(crate) struct ImproperCTypes<'a> { } // Used because of the complexity of Option, DiagMessage, and Option -impl<'a> Diagnostic<'a, ()> for ImproperCTypes<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for ImproperCTypes<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new( dcx, level, @@ -2691,8 +2691,8 @@ pub(crate) enum UnusedDefSuggestion { } // Needed because of def_path_str -impl<'a> Diagnostic<'a, ()> for UnusedDef<'_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for UnusedDef<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, msg!("unused {$pre}`{$def}`{$post} that must be used")) .with_arg("pre", self.pre) @@ -2778,8 +2778,8 @@ pub(crate) struct AsyncFnInTraitDiag { pub sugg: Option>, } -impl<'a> Diagnostic<'a, ()> for AsyncFnInTraitDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for AsyncFnInTraitDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new( dcx, level, @@ -2924,8 +2924,8 @@ pub(crate) struct MismatchedLifetimeSyntaxes { pub suggestions: Vec, } -impl<'a, G> Diagnostic<'a, G> for MismatchedLifetimeSyntaxes { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for MismatchedLifetimeSyntaxes { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let counts = self.inputs.len() + self.outputs.len(); let message = match counts { LifetimeSyntaxCategories { hidden: 0, elided: 0, named: 0 } => { @@ -3037,7 +3037,7 @@ impl MismatchedLifetimeSyntaxesSuggestion { } impl Subdiagnostic for MismatchedLifetimeSyntaxesSuggestion { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { use MismatchedLifetimeSyntaxesSuggestion::*; let style = |optional_alternative| { diff --git a/compiler/rustc_lint/src/early/diagnostics.rs b/compiler/rustc_lint/src/early/diagnostics.rs index 91259b010178d..95a925d1c1455 100644 --- a/compiler/rustc_lint/src/early/diagnostics.rs +++ b/compiler/rustc_lint/src/early/diagnostics.rs @@ -6,13 +6,13 @@ use rustc_session::Session; pub struct DiagAndSess<'sess> { pub callback: Box< - dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b, ()> + DynSend + 'static, + dyn for<'b> FnOnce(DiagCtxtHandle<'b>, Level, &dyn Any) -> Diag<'b> + DynSend + 'static, >, pub sess: &'sess Session, } -impl<'a> Diagnostic<'a, ()> for DiagAndSess<'_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for DiagAndSess<'_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { (self.callback)(dcx, level, self.sess) } } diff --git a/compiler/rustc_lint/src/if_let_rescope.rs b/compiler/rustc_lint/src/if_let_rescope.rs index 1cd701db7d10e..c29cff23acee1 100644 --- a/compiler/rustc_lint/src/if_let_rescope.rs +++ b/compiler/rustc_lint/src/if_let_rescope.rs @@ -324,7 +324,7 @@ struct IfLetRescopeRewrite { } impl Subdiagnostic for IfLetRescopeRewrite { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut suggestions = vec![]; for match_head in self.match_heads { match match_head { diff --git a/compiler/rustc_lint/src/impl_trait_overcaptures.rs b/compiler/rustc_lint/src/impl_trait_overcaptures.rs index f8e4c70d193d6..9d7d0a0df475f 100644 --- a/compiler/rustc_lint/src/impl_trait_overcaptures.rs +++ b/compiler/rustc_lint/src/impl_trait_overcaptures.rs @@ -452,12 +452,12 @@ struct ImplTraitOvercapturesLint<'tcx> { suggestion: Option, } -impl<'a> Diagnostic<'a, ()> for ImplTraitOvercapturesLint<'_> { +impl<'a> Diagnostic<'a> for ImplTraitOvercapturesLint<'_> { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: rustc_errors::Level, - ) -> rustc_errors::Diag<'a, ()> { + ) -> rustc_errors::Diag<'a> { let mut diag = rustc_errors::Diag::new( dcx, level, diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs index 7f3d7fa8d2a10..f847d4c6ae904 100644 --- a/compiler/rustc_lint/src/levels.rs +++ b/compiler/rustc_lint/src/levels.rs @@ -960,12 +960,8 @@ where lint_from_cli: bool, } - impl<'a, 'b> Diagnostic<'a, ()> for UnknownLint<'b> { - fn into_diag( - self, - dcx: DiagCtxtHandle<'a>, - level: rustc_errors::Level, - ) -> Diag<'a, ()> { + impl<'a, 'b> Diagnostic<'a> for UnknownLint<'b> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: rustc_errors::Level) -> Diag<'a> { let Self { sess, lint_id, feature, lint_from_cli } = self; let mut lint = Diag::new(dcx, level, msg!("unknown lint: `{$name}`")) .with_arg("name", lint_id.lint.name_lower()) @@ -1013,7 +1009,7 @@ where &self, lint: &'static Lint, span: Option, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { let level_spec = self.lint_level_spec(lint); emit_lint_base(self.sess, lint, level_spec, span, decorator) @@ -1024,14 +1020,14 @@ where &self, lint: &'static Lint, span: MultiSpan, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { let level_spec = self.lint_level_spec(lint); emit_lint_base(self.sess, lint, level_spec, Some(span), decorator); } #[track_caller] - pub fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a, ()>) { + pub fn emit_lint(&self, lint: &'static Lint, decorator: impl for<'a> Diagnostic<'a>) { let level_spec = self.lint_level_spec(lint); emit_lint_base(self.sess, lint, level_spec, None, decorator); } diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 991b1083b3272..cb811421be5c6 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -96,8 +96,8 @@ struct PanicMessageNotLiteral<'a, 'tcx> { panic: Option, } -impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for PanicMessageNotLiteral<'b, 'tcx> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, 'b, 'tcx> Diagnostic<'a> for PanicMessageNotLiteral<'b, 'tcx> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { arg_span, symbol, span, arg_macro, cx, arg, panic } = self; let mut lint = Diag::new(dcx, level, "panic message is not a string literal") .with_arg("name", symbol) diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index d1057c4f9ead3..b7bb7865ea080 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -484,10 +484,10 @@ struct NonUpperCaseGlobalGenerator<'a, F: FnOnce() -> NonUpperCaseGlobal<'a>> { callback: F, } -impl<'a, 'b, F: FnOnce() -> NonUpperCaseGlobal<'b>> Diagnostic<'a, ()> +impl<'a, 'b, F: FnOnce() -> NonUpperCaseGlobal<'b>> Diagnostic<'a> for NonUpperCaseGlobalGenerator<'b, F> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { callback } = self; callback().into_diag(dcx, level) } diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs index 72e7423fc2d88..5bc15eb3d2a5c 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs @@ -48,13 +48,13 @@ impl<'a> DiagnosticDerive<'a> { // A lifetime of `'a` causes conflicts, but `_sess` is fine. structure.gen_impl(quote! { - gen impl<'_sess, G> rustc_errors::Diagnostic<'_sess, G> for @Self { + gen impl<'_sess> rustc_errors::Diagnostic<'_sess> for @Self { #[track_caller] fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'_sess>, level: rustc_errors::Level - ) -> rustc_errors::Diag<'_sess, G> { + ) -> rustc_errors::Diag<'_sess> { #implementation } } diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index d6b101ca0addf..baf38d2fc381f 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -94,10 +94,7 @@ impl SubdiagnosticDerive { let ret = structure.gen_impl(quote! { gen impl rustc_errors::Subdiagnostic for @Self { - fn add_to_diag<__G>( - self, - #diag: &mut rustc_errors::Diag<'_, __G>, - ) { + fn add_to_diag(self, #diag: &mut rustc_errors::Diag<'_>) { #implementation } } diff --git a/compiler/rustc_metadata/src/diagnostics.rs b/compiler/rustc_metadata/src/diagnostics.rs index a093e7990ea28..18796f51375a1 100644 --- a/compiler/rustc_metadata/src/diagnostics.rs +++ b/compiler/rustc_metadata/src/diagnostics.rs @@ -305,8 +305,8 @@ pub(crate) struct MultipleCandidates { pub candidates: Vec, } -impl Diagnostic<'_, G> for MultipleCandidates { - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { +impl Diagnostic<'_> for MultipleCandidates { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, @@ -418,9 +418,9 @@ pub(crate) struct InvalidMetadataFiles { pub crate_rejections: Vec, } -impl Diagnostic<'_, G> for InvalidMetadataFiles { +impl Diagnostic<'_> for InvalidMetadataFiles { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, @@ -450,9 +450,9 @@ pub(crate) struct CannotFindCrate { pub is_tier_3: bool, } -impl Diagnostic<'_, G> for CannotFindCrate { +impl Diagnostic<'_> for CannotFindCrate { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new(dcx, level, msg!("can't find crate for `{$crate_name}`{$add_info}")); diag.arg("crate_name", self.crate_name); diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 49fbbd9164f38..820375ada47a5 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -285,7 +285,7 @@ fn explain_lint_level_source( lint: &'static Lint, level: Level, src: LintLevelSource, - err: &mut Diag<'_, ()>, + err: &mut Diag<'_>, ) { // Find the name of the lint group that contains the given lint. // Assumes the lint only belongs to one group. @@ -382,7 +382,7 @@ fn explain_lint_level_source( /// - [`TyCtxt::emit_node_span_lint`] /// - `LintContext::opt_span_lint` #[track_caller] -pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>( +pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( sess: &'a Session, lint: &'static Lint, level_spec: impl Into, @@ -398,7 +398,7 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>( level_spec: LevelSpec, span: Option, decorate: Box< - dyn FnOnce(rustc_errors::DiagCtxtHandle<'a>, rustc_errors::Level) -> Diag<'a, ()> + 'a, + dyn FnOnce(rustc_errors::DiagCtxtHandle<'a>, rustc_errors::Level) -> Diag<'a> + 'a, >, ) { let LevelSpec { level, lint_id, src } = level_spec; @@ -484,7 +484,7 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a, ()> + 'a>( // will be emitted if `can_emit_warnings` is true. let skip = err_level == rustc_errors::Level::Warning && !sess.dcx().can_emit_warnings(); - let mut err: Diag<'_, ()> = if !skip { + let mut err: Diag<'_> = if !skip { decorate(sess.dcx(), err_level) } else { Diag::new(sess.dcx(), err_level, "") diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 2ad73c8894da5..8213646b4625d 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -114,12 +114,12 @@ pub(crate) struct Deprecated { pub since_kind: DeprecatedSinceKind, } -impl<'a, G> rustc_errors::Diagnostic<'a, G> for Deprecated { +impl<'a> rustc_errors::Diagnostic<'a> for Deprecated { fn into_diag( self, dcx: rustc_errors::DiagCtxtHandle<'a>, level: rustc_errors::Level, - ) -> Diag<'a, G> { + ) -> Diag<'a> { let Self { sub, kind, path, note, since_kind } = self; let mut diag = Diag::new(dcx, level, match &since_kind { DeprecatedSinceKind::InEffect => msg!( diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index f88b7ff0f8a85..8dccead861de7 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -914,7 +914,7 @@ pub enum DynCompatibilityViolationSolution { } impl DynCompatibilityViolationSolution { - pub fn add_to(self, err: &mut Diag<'_, G>) { + pub fn add_to(self, err: &mut Diag<'_>) { match self { DynCompatibilityViolationSolution::None => {} DynCompatibilityViolationSolution::AddSelfOrMakeSized { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9d0b334b63fbd..bd9a5e80b1855 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2609,7 +2609,7 @@ impl<'tcx> TyCtxt<'tcx> { lint: &'static Lint, hir_id: HirId, span: impl Into, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { let level_spec = self.lint_level_spec_at_node(lint, hir_id); emit_lint_base(self.sess, lint, level_spec, Some(span.into()), decorator) @@ -2622,9 +2622,9 @@ impl<'tcx> TyCtxt<'tcx> { m.spans.inject_use_span.shrink_to_lo() } - pub fn disabled_nightly_features( + pub fn disabled_nightly_features( self, - diag: &mut Diag<'_, G>, + diag: &mut Diag<'_>, features: impl IntoIterator, ) { if !self.sess.is_nightly_build() { @@ -2652,7 +2652,7 @@ impl<'tcx> TyCtxt<'tcx> { self, lint: &'static Lint, id: HirId, - decorator: impl for<'a> Diagnostic<'a, ()>, + decorator: impl for<'a> Diagnostic<'a>, ) { let level_spec = self.lint_level_spec_at_node(lint, id); emit_lint_base(self.sess, lint, level_spec, None, decorator); diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 22fbb306849da..80d34d8747344 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1346,8 +1346,8 @@ pub enum FnAbiError<'tcx> { Layout(LayoutError<'tcx>), } -impl<'a, 'b, G> Diagnostic<'a, G> for FnAbiError<'b> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a, 'b> Diagnostic<'a> for FnAbiError<'b> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { match self { Self::Layout(e) => Diag::new(dcx, level, e.to_string()), } diff --git a/compiler/rustc_middle/src/ty/opaque_types.rs b/compiler/rustc_middle/src/ty/opaque_types.rs index 63146ff7ed765..7333d17e259e0 100644 --- a/compiler/rustc_middle/src/ty/opaque_types.rs +++ b/compiler/rustc_middle/src/ty/opaque_types.rs @@ -125,7 +125,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { Some(u) => panic!("region mapped to unexpected kind: {u:?}"), None if self.do_not_error => self.tcx.lifetimes.re_static, None => { - let e = self + let guar = self .tcx .dcx() .struct_span_err(self.span, "non-defining opaque type use in defining scope") @@ -136,9 +136,9 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { parameter list of the `impl Trait` type alias", ), ) - .emit(); + .emit_err(); - ty::Region::new_error(self.cx(), e) + ty::Region::new_error(self.cx(), guar) } } } @@ -179,7 +179,7 @@ impl<'tcx> TypeFolder> for ReverseMapper<'tcx> { used in parameter list for the `impl Trait` type alias" ), ) - .emit(); + .emit_err(); Ty::new_error(self.tcx, guar) } } diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 6c5b4384bd913..298e7898af7f8 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -205,12 +205,12 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { } fn report_in_closure(&mut self, expr: &Expr<'_>) { - let err = self.tcx.dcx().span_err(expr.span, "`become` is not allowed in closures"); - self.found_errors = Err(err); + let guar = self.tcx.dcx().span_err(expr.span, "`become` is not allowed in closures"); + self.found_errors = Err(guar); } fn report_builtin_op(&mut self, value: &Expr<'_>, expr: &Expr<'_>) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(value.span, "`become` does not support operators") @@ -221,8 +221,8 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { "return ", Applicability::MachineApplicable, ) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_op(&mut self, fun_ty: Ty<'_>, args: &[ExprId], fn_span: Span, expr: &Expr<'_>) { @@ -265,11 +265,11 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { } } - self.found_errors = Err(err.emit()); + self.found_errors = Err(err.emit_err()); } fn report_non_call(&mut self, value: &Expr<'_>, expr: &Expr<'_>) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(value.span, "`become` requires a function call") @@ -280,8 +280,8 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { "return ", Applicability::MaybeIncorrect, ) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_calling_closure(&mut self, fun: &Expr<'_>, tupled_args: Ty<'_>, expr: &Expr<'_>) { @@ -291,7 +291,7 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { _ => "_".to_owned(), }; - let err = self + let guar = self .tcx .dcx() .struct_span_err(expr.span, "tail calling closures directly is not allowed") @@ -303,18 +303,18 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { ], Applicability::MaybeIncorrect, ) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_calling_intrinsic(&mut self, expr: &Expr<'_>) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(expr.span, "tail calling intrinsics is not allowed") - .emit(); + .emit_err(); - self.found_errors = Err(err); + self.found_errors = Err(guar); } fn report_nonfn_callee(&mut self, call_sp: Span, fun_sp: Span, ty: Ty<'_>) { @@ -347,29 +347,29 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { ); } - let err = err.emit(); - self.found_errors = Err(err); + let guar = err.emit_err(); + self.found_errors = Err(guar); } fn report_abi_mismatch(&mut self, sp: Span, caller_abi: ExternAbi, callee_abi: ExternAbi) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(sp, "mismatched function ABIs") .with_note("`become` requires caller and callee to have the same ABI") .with_note(format!("caller ABI is `{caller_abi}`, while callee ABI is `{callee_abi}`")) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_unsupported_abi(&mut self, sp: Span, callee_abi: ExternAbi) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(sp, "ABI does not support guaranteed tail calls") .with_note(format!("`become` is not supported for `extern {callee_abi}` functions")) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_signature_mismatch( @@ -378,61 +378,61 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> { caller_sig: ty::FnSig<'_>, callee_sig: ty::FnSig<'_>, ) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(sp, "mismatched signatures") .with_note("`become` requires caller and callee to have matching signatures") .with_note(format!("caller signature: `{caller_sig}`")) .with_note(format!("callee signature: `{callee_sig}`")) - .emit(); - self.found_errors = Err(err); + .emit_err(); + self.found_errors = Err(guar); } fn report_track_caller_caller(&mut self, sp: Span) { - let err = self + let guar = self .tcx .dcx() .struct_span_err( sp, "a function marked with `#[track_caller]` cannot perform a tail-call", ) - .emit(); + .emit_err(); - self.found_errors = Err(err); + self.found_errors = Err(guar); } fn report_c_variadic_caller(&mut self, sp: Span) { - let err = self + let guar = self .tcx .dcx() // FIXME(explicit_tail_calls): highlight the `...` .struct_span_err(sp, "tail-calls are not allowed in c-variadic functions") - .emit(); + .emit_err(); - self.found_errors = Err(err); + self.found_errors = Err(guar); } fn report_c_variadic_callee(&mut self, sp: Span) { - let err = self + let guar = self .tcx .dcx() // FIXME(explicit_tail_calls): highlight the function or something... .struct_span_err(sp, "c-variadic functions can't be tail-called") - .emit(); + .emit_err(); - self.found_errors = Err(err); + self.found_errors = Err(guar); } fn report_unsized_argument(&mut self, sp: Span, arg_ty: Ty<'tcx>) { - let err = self + let guar = self .tcx .dcx() .struct_span_err(sp, format!("unsized arguments cannot be used in a tail call")) .with_note(format!("unsized argument of type `{arg_ty}`")) - .emit(); + .emit_err(); - self.found_errors = Err(err); + self.found_errors = Err(guar); } } diff --git a/compiler/rustc_mir_build/src/diagnostics.rs b/compiler/rustc_mir_build/src/diagnostics.rs index 83bfd322d6444..40d9b0990b2fc 100644 --- a/compiler/rustc_mir_build/src/diagnostics.rs +++ b/compiler/rustc_mir_build/src/diagnostics.rs @@ -585,7 +585,7 @@ pub(crate) struct UnsafeNotInheritedLintNote { } impl Subdiagnostic for UnsafeNotInheritedLintNote { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_note( self.signature_span, msg!("an unsafe function restricts its caller, but its body is safe by default"), @@ -625,8 +625,8 @@ pub(crate) struct NonExhaustivePatternsTypeNotEmpty<'a, 'tcx> { pub(crate) ty: Ty<'tcx>, } -impl<'a, G> Diagnostic<'a, G> for NonExhaustivePatternsTypeNotEmpty<'_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for NonExhaustivePatternsTypeNotEmpty<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, msg!("non-exhaustive patterns: type `{$ty}` is non-empty")); diag.span(self.scrut_span); @@ -730,9 +730,9 @@ pub(crate) struct UnreachablePattern<'tcx> { pub(crate) inner: UnreachablePatternInner<'tcx>, } -impl<'a, 'tcx, G> Diagnostic<'a, G> for UnreachablePattern<'tcx> { +impl<'a, 'tcx> Diagnostic<'a> for UnreachablePattern<'tcx> { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = self.inner.into_diag(dcx, level); if let Some(covered_by_many_n_more_count) = self.covered_by_many_n_more_count { diag.arg("covered_by_many_n_more_count", covered_by_many_n_more_count); @@ -1260,7 +1260,7 @@ pub(crate) struct Variant { } impl<'tcx> Subdiagnostic for AdtDefinedHere<'tcx> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.arg("ty", self.ty); let mut spans = MultiSpan::from(self.adt_def_span); diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 3414ee751585c..5a3870eec57ad 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1469,7 +1469,7 @@ fn report_non_exhaustive_match<'p, 'tcx>( } else { err.help(msg); } - err.emit() + err.emit_err() } fn joined_uncovered_patterns<'p, 'tcx>( diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index e24ef5ea5b52d..df39350bd5c8c 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -94,7 +94,7 @@ impl<'tcx> ConstToPat<'tcx> { err.span_label(self.tcx.def_span(def_id), msg!("constant defined here")); } } - Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit()), extra: None }) + Box::new(Pat { span: self.span, ty, kind: PatKind::Error(err.emit_err()), extra: None }) } fn alias_to_pat(&mut self, alias_const: ty::AliasConst<'tcx>, ty: Ty<'tcx>) -> Box> { diff --git a/compiler/rustc_mir_build/src/thir/pattern/migration.rs b/compiler/rustc_mir_build/src/thir/pattern/migration.rs index e6db030557703..7c789a62b04e2 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/migration.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/migration.rs @@ -90,7 +90,7 @@ impl<'a> PatMigration<'a> { format!("cannot {verb1}{or_verb2} within an implicitly-borrowing pattern{in_rust_2024}") } - fn format_subdiagnostics(self, diag: &mut Diag<'_, G>) { + fn format_subdiagnostics(self, diag: &mut Diag<'_>) { // Format and emit explanatory notes about default binding modes. Reversing the spans' order // means if we have nested spans, the innermost ones will be visited first. for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() { diff --git a/compiler/rustc_mir_transform/src/diagnostics.rs b/compiler/rustc_mir_transform/src/diagnostics.rs index c851b55f9623a..6e083fef20928 100644 --- a/compiler/rustc_mir_transform/src/diagnostics.rs +++ b/compiler/rustc_mir_transform/src/diagnostics.rs @@ -97,8 +97,8 @@ pub(crate) enum AssertLintKind { UnconditionalPanic, } -impl<'a, P: std::fmt::Debug> Diagnostic<'a, ()> for AssertLint

{ - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a, P: std::fmt::Debug> Diagnostic<'a> for AssertLint

{ + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new( dcx, level, @@ -218,7 +218,7 @@ pub(crate) struct UnusedAssignOverwrite { } impl Subdiagnostic for UnusedAssignOverwrite { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_label(self.assigned_span, "this value is reassigned later and never used"); diag.span_label( self.overwrite_span, @@ -297,7 +297,7 @@ pub(crate) struct UnusedVariableStringInterp { } impl Subdiagnostic for UnusedVariableStringInterp { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_label( self.lit, msg!("you might have meant to use string interpolation in this string literal"), @@ -338,8 +338,8 @@ pub(crate) struct MustNotSupend<'a, 'tcx> { } // Needed for def_path_str -impl<'a> Diagnostic<'a, ()> for MustNotSupend<'_, '_> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for MustNotSupend<'_, '_> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new( dcx, level, diff --git a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs index a31a3cfcd6af9..7e91890a08cc2 100644 --- a/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs +++ b/compiler/rustc_mir_transform/src/lint_tail_expr_drop_order.rs @@ -523,7 +523,7 @@ struct LocalLabel<'a> { /// A custom `Subdiagnostic` implementation so that the notes are delivered in a specific order impl Subdiagnostic for LocalLabel<'_> { - fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_, G>) { + fn add_to_diag(self, diag: &mut rustc_errors::Diag<'_>) { diag.span_label( self.span, msg!( diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 74910ce3acde4..0e707688d72b4 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -314,7 +314,7 @@ fn run_passes_inner<'tcx>( for name in rest { err.note(format!("pass `{name}` is also not declared in `PASS_NAMES`")); } - err.emit(); + err.emit_bug(); } } diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 4f3c702c77ef9..566b257d1058d 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -1537,9 +1537,9 @@ pub(crate) struct ExpectedIdentifier { pub help_cannot_start_number: Option, } -impl<'a, G> Diagnostic<'a, G> for ExpectedIdentifier { +impl<'a> Diagnostic<'a> for ExpectedIdentifier { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let token_descr = TokenDescription::from_token(&self.token); let mut add_token = true; @@ -1603,9 +1603,9 @@ pub(crate) struct ExpectedSemi { pub sugg: ExpectedSemiSugg, } -impl<'a, G> Diagnostic<'a, G> for ExpectedSemi { +impl<'a> Diagnostic<'a> for ExpectedSemi { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let token_descr = TokenDescription::from_token(&self.token); let mut add_token = true; @@ -2010,7 +2010,7 @@ pub(crate) struct FnTraitMissingParen { } impl Subdiagnostic for FnTraitMissingParen { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.span_label(self.span, msg!("`Fn` bounds require arguments in parentheses")); diag.span_suggestion_short( self.span.shrink_to_hi(), @@ -3697,7 +3697,7 @@ pub(crate) struct UseDerefMacro { } impl Subdiagnostic for UseDerefMacro { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let Self { field, before, after } = self; let mut parts = Vec::new(); @@ -4355,7 +4355,7 @@ pub(crate) struct HiddenUnicodeCodepointsDiagLabels { } impl Subdiagnostic for HiddenUnicodeCodepointsDiagLabels { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { for (c, span) in self.spans { diag.span_label(span, format!("{c:?}")); } @@ -4369,7 +4369,7 @@ pub(crate) enum HiddenUnicodeCodepointsDiagSub { // Used because of multiple multipart_suggestion and note impl Subdiagnostic for HiddenUnicodeCodepointsDiagSub { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { HiddenUnicodeCodepointsDiagSub::Escape { spans } => { diag.multipart_suggestion_with_style( diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 2afb55b02e2e6..6a362b1b1cde0 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -970,7 +970,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { escaped_char(bad_char) ), ) - .emit() + .emit_fatal() } fn report_unterminated_raw_string( @@ -1004,7 +1004,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { ); } - err.emit() + err.emit_fatal() } fn report_unterminated_block_comment(&self, start: BytePos, doc_style: Option) -> ! { @@ -1050,7 +1050,7 @@ impl<'psess, 'src> Lexer<'psess, 'src> { ); } - err.emit(); + err.emit_fatal(); } // RFC 3101 introduced the idea of (reserved) prefixes. As of Rust 2021, diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs index 9176192c95640..f01caf8d9efed 100644 --- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs +++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs @@ -177,7 +177,7 @@ pub(crate) fn emit_unescape_error( foreign_escape_suggestion(&mut diag, (&ec, span), err_span); } - diag.emit() + diag.emit_err() } EscapeError::TooShortHexEscape => dcx.emit_err(UnescapeError::TooShortHexEscape(err_span)), EscapeError::InvalidCharInHexEscape | EscapeError::InvalidCharInUnicodeEscape => { @@ -227,7 +227,7 @@ pub(crate) fn emit_unescape_error( Applicability::MaybeIncorrect, ); } - err.emit() + err.emit_err() } EscapeError::OutOfRangeHexEscape => { let mut err = dcx.struct_span_err(err_span, "out of range hex escape"); @@ -247,7 +247,7 @@ pub(crate) fn emit_unescape_error( )); } - err.emit() + err.emit_err() } EscapeError::LeadingUnderscoreUnicodeEscape => { let (c, span) = last_char(); diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 16a438b5387ee..8a73215351aea 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -160,16 +160,16 @@ pub fn new_parser_from_file<'a>( if let Some(sp) = sp { err.span(sp); } - err.emit() + err.emit_fatal() }); new_parser_from_source_file(psess, source_file, strip_tokens) } -pub fn utf8_error( +pub fn utf8_error( sm: &SourceMap, path: &str, sp: Option, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, utf8err: Utf8Error, contents: &[u8], ) { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index f5fa592585099..18489162257f6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -609,7 +609,7 @@ impl<'a> Parser<'a> { if self.check_too_many_raw_str_terminators(&mut err) { if expected.contains(&TokenType::Semi) && self.eat(exp!(Semi)) { - let guar = err.emit(); + let guar = err.emit_err(); return Ok(guar); } else { return Err(err); @@ -770,7 +770,7 @@ impl<'a> Parser<'a> { Ok(next_attr) => next_attr, Err(inner_err) => { inner_err.cancel(); - return err.emit(); + return err.emit_err(); } } && let ast::AttrKind::Normal(next_attr_kind) = next_attr.kind @@ -782,7 +782,7 @@ impl<'a> Parser<'a> { Ok(next_expr) => next_expr, Err(inner_err) => { inner_err.cancel(); - return err.emit(); + return err.emit_err(); } }; // We have for sure @@ -816,7 +816,7 @@ impl<'a> Parser<'a> { } } - err.emit() + err.emit_err() } fn check_too_many_raw_str_terminators(&mut self, err: &mut Diag<'_>) -> bool { @@ -941,7 +941,7 @@ impl<'a> Parser<'a> { ], Applicability::MaybeIncorrect, ); - let guar = err.emit(); + let guar = err.emit_err(); self.eat_to_tokens(&[exp!(CloseBrace)]); guar } @@ -958,7 +958,7 @@ impl<'a> Parser<'a> { ], Applicability::MaybeIncorrect, ); - err.emit() + err.emit_err() } _ if token.kind != token::OpenBrace => { // We don't have a heuristic to correctly identify where the block @@ -1175,7 +1175,7 @@ impl<'a> Parser<'a> { // The subsequent expression is valid. Mark // `expr` as erroneous and emit `e` now, but // return `Ok` so parsing can continue. - let guar = e.emit(); + let guar = e.emit_err(); *expr = self.mk_expr_err(expr.span.to(self.prev_token.span), guar); return Ok(guar); } @@ -1834,7 +1834,7 @@ impl<'a> Parser<'a> { "r#", Applicability::MachineApplicable, ); - let guar = err.emit(); + let guar = err.emit_err(); Ok(self.mk_expr_err(lo.to(hi), guar)) } else { Err(self.expected_expression_found()) // The user isn't trying to invoke the try! macro @@ -1881,7 +1881,7 @@ impl<'a> Parser<'a> { lo: Span, err: Diag<'a>, ) -> Box { - let guar = err.emit(); + let guar = err.emit_err(); // Recover from parse error, callers expect the closing delim to be consumed. self.consume_block(open, close, ConsumeClosingDelim::Yes); self.mk_expr(lo.to(self.prev_token.span), ExprKind::Err(guar)) @@ -2410,7 +2410,7 @@ impl<'a> Parser<'a> { "=", Applicability::MaybeIncorrect, ); - let guar = err.emit(); + let guar = err.emit_err(); let value = self.mk_expr_err(start.to(expr.span), guar); return Ok(GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value })); } else if snapshot.token == token::Colon @@ -2424,7 +2424,7 @@ impl<'a> Parser<'a> { "::", Applicability::MaybeIncorrect, ); - let guar = err.emit(); + let guar = err.emit_err(); return Ok(GenericArg::Type( self.mk_ty(start.to(expr.span), TyKind::Err(guar)), )); @@ -2476,7 +2476,7 @@ impl<'a> Parser<'a> { vec![(span.shrink_to_lo(), "{ ".to_string()), (span.shrink_to_hi(), " }".to_string())], Applicability::MaybeIncorrect, ); - let guar = err.emit(); + let guar = err.emit_err(); let value = self.mk_expr_err(span, guar); GenericArg::Const(AnonConst { id: ast::DUMMY_NODE_ID, value }) } diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 31e2d15a5ebb3..a615d4afcba77 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -1115,7 +1115,7 @@ impl<'a> Parser<'a> { Err(err) if self.is_expected_raw_ref_mut() && self.token_cursor.depth() == call_depth => { - let guar = err.emit(); + let guar = err.emit_err(); // Preserve the call expression so later passes can still diagnose the callee, // while treating the malformed `&raw ` argument as an error expression. let args = self.recover_raw_ref_call_args(guar); @@ -1194,7 +1194,7 @@ impl<'a> Parser<'a> { }, }) } else { - err.emit() + err.emit_err() }; Ok(self.mk_expr_err(span, guar)) } @@ -1715,7 +1715,7 @@ impl<'a> Parser<'a> { "'", Applicability::MaybeIncorrect, ) - .emit() + .emit_err() }); let name = ident.without_first_quote().name; mk_lit_char(name, ident.span) @@ -3054,7 +3054,7 @@ impl<'a> Parser<'a> { Ok(arm) => arms.push(arm), Err(e) => { // Recover by skipping to the end of the block. - let guar = e.emit(); + let guar = e.emit_err(); self.recover_stmt(); let span = lo.to(self.token.span); if self.token == token::CloseBrace { @@ -3768,7 +3768,7 @@ impl<'a> Parser<'a> { return Err(e); } - let guar = e.emit(); + let guar = e.emit_err(); if pth == kw::Async { recovered_async = Some(guar); } @@ -3826,7 +3826,7 @@ impl<'a> Parser<'a> { if !recover { return Err(e); } - let guar = e.emit(); + let guar = e.emit_err(); if pth == kw::Async { recovered_async = Some(guar); } else if let Some(f) = field_ident(self, guar) { diff --git a/compiler/rustc_parse/src/parser/function.rs b/compiler/rustc_parse/src/parser/function.rs index e44423e46b0c3..27e671c0d9c52 100644 --- a/compiler/rustc_parse/src/parser/function.rs +++ b/compiler/rustc_parse/src/parser/function.rs @@ -176,7 +176,7 @@ impl<'a> Parser<'a> { // The enclosing `mod`, `trait` or `impl` is being closed, so keep the `fn` in // the AST for typechecking. err.span_label(ident_span, "while parsing this `fn`"); - Ok(err.emit()) + Ok(err.emit_err()) } else if self.token == token::RArrow && let Some(fn_params_end) = fn_params_end { @@ -701,7 +701,7 @@ impl<'a> Parser<'a> { p.recover_vcs_conflict_marker(); let snapshot = p.create_snapshot_for_diagnostic(); let param = p.parse_param_general(fn_parse_mode, first_param).or_else(|e| { - let guar = e.emit(); + let guar = e.emit_err(); // When parsing a param failed, we should check to make the span of the param // not contain '(' before it. // For example when parsing `*mut Self` in function `fn oof(*mut Self)`. @@ -777,7 +777,7 @@ impl<'a> Parser<'a> { first_param, fn_parse_mode, ) { - let guar = err.emit(); + let guar = err.emit_err(); let mut arg = dummy_arg(ident, guar); arg.span = pat_span; Ok((arg, Trailing::No, UsePreAttrPos::No)) diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs index d47f8c4c264dd..5d2aa1bed5b6e 100644 --- a/compiler/rustc_parse/src/parser/generics.rs +++ b/compiler/rustc_parse/src/parser/generics.rs @@ -119,7 +119,7 @@ impl<'a> Parser<'a> { ": /* Type */".to_string(), Applicability::HasPlaceholders, ); - let kind = TyKind::Err(err.emit()); + let kind = TyKind::Err(err.emit_err()); let ty = self.mk_ty(span, kind); Ok(GenericParam { ident, diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 2ab012e0ecc2f..efeaa0653a44a 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -1954,7 +1954,7 @@ impl<'a> Parser<'a> { this.bump(); // } err.span_label(span, "while parsing this enum"); err.help(help); - let guar = err.emit(); + let guar = err.emit_err(); (thin_vec![], Recovered::Yes(guar)) } }; @@ -2130,7 +2130,7 @@ impl<'a> Parser<'a> { ConsumeClosingDelim::No, ); err.span_label(ident_span, format!("while parsing this {adt_ty}")); - let guar = err.emit(); + let guar = err.emit_err(); recovered = Recovered::Yes(guar); break; } diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index b2afd1c51256a..3ec3b7cf6fc3d 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -1289,7 +1289,7 @@ impl<'a> Parser<'a> { .with_help( "use a named `const`-item or an `if`-guard (`x if x == const { ... }`) instead", ) - .emit(); + .emit_err(); ExprKind::Err(guar) } else { ExprKind::ConstBlock(anon_const) @@ -1795,7 +1795,7 @@ impl<'a> Parser<'a> { ";", Applicability::MaybeIncorrect, ); - return Some((lhs.span, err.emit())); + return Some((lhs.span, err.emit_err())); } None } diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 8508941f459f2..e3a5902196acb 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1561,7 +1561,7 @@ impl<'a> Parser<'a> { self.bump(); let (fields, etc) = self.parse_pat_fields().unwrap_or_else(|mut e| { e.span_label(path.span, "while parsing the fields for this pattern"); - let guar = e.emit(); + let guar = e.emit_err(); self.recover_stmt(); // When recovering, pretend we had `Foo { .. }`, to avoid cascading errors. (ThinVec::new(), PatFieldsRest::Recovered(guar)) diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 6bc7195b8371c..2174dbefaa321 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -626,7 +626,7 @@ impl<'a> Parser<'a> { // When encountering severely malformed code where there are several levels of // nested unclosed angle args (`f:: 0 => { self.angle_bracket_nesting -= 1; diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index 4fd3649a6dc3c..9056b67dc4f13 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -796,7 +796,7 @@ impl<'a> Parser<'a> { } } - let guar = err.emit(); + let guar = err.emit_err(); self.recover_stmt_(SemiColonMode::Ignore, BlockMode::Ignore); self.mk_stmt_err(self.token.span, guar) } @@ -1073,7 +1073,7 @@ impl<'a> Parser<'a> { } else { res.unwrap_or_else(|mut e| { self.recover_missing_dot(&mut e); - let guar = e.emit(); + let guar = e.emit_err(); self.recover_stmt(); guar }) diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 42fb9121076f4..8ce81c6ab8c3d 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -527,7 +527,7 @@ impl<'a> Parser<'a> { err.span_label(lo, "expected type"); return Ok(match self.maybe_recover_ref_ty_no_leading_ampersand(lt, lo, err) { Ok(ref_ty) => ref_ty, - Err(err) => TyKind::Err(err.emit()), + Err(err) => TyKind::Err(err.emit_err()), }); } @@ -791,7 +791,7 @@ impl<'a> Parser<'a> { .struct_span_err(span, "`typeof` is a reserved keyword but unimplemented") .with_note("consider replacing `typeof(...)` with an actual type") .with_code(E0516) - .emit(); + .emit_err(); Ok(TyKind::Err(guar)) } @@ -1155,7 +1155,7 @@ impl<'a> Parser<'a> { vec![(lo, String::new()), (hi, String::new())], Applicability::MachineApplicable, ); - diag.emit() + diag.emit_err() } /// Emits an error if any trait bound modifiers were present. diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 55f8ac9a585de..59c1005885903 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -392,9 +392,9 @@ pub(crate) struct NoMainErr { pub add_teach_note: bool, } -impl<'a, G> Diagnostic<'a, G> for NoMainErr { +impl<'a> Diagnostic<'a> for NoMainErr { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, msg!("`main` function not found in crate `{$crate_name}`")); diag.span(DUMMY_SP); @@ -458,9 +458,9 @@ pub(crate) struct DuplicateLangItem { pub(crate) duplicate: Duplicate, } -impl Diagnostic<'_, G> for DuplicateLangItem { +impl Diagnostic<'_> for DuplicateLangItem { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index b47de985224e2..83e95b9195580 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -17,7 +17,7 @@ use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, bug}; // Default cycle handler used for all queries that don't use the `handle_cycle_error` query // modifier. pub(crate) fn default(err: Diag<'_>) -> ! { - let guar = err.emit(); + let guar = err.emit_err(); guar.raise_fatal() } @@ -207,7 +207,7 @@ pub(crate) fn layout_of<'tcx>( || create_cycle_error(tcx, &cycle, false), ); - diag.emit().raise_fatal() + diag.emit_err().raise_fatal() } // item_and_field_ids should form a cycle where each field contains the @@ -292,7 +292,7 @@ fn recursive_type_error( suggestion, Applicability::HasPlaceholders, ) - .emit() + .emit_err() } fn find_item_ty_spans( diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 6ddfff9f88d83..89b70065f8adc 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -326,7 +326,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } - let guar = diag.emit(); + let guar = diag.emit_err(); if glob_error { self.glob_error = Some(guar); } @@ -787,7 +787,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { span: Span, resolution_error: ResolutionError<'ra>, ) -> ErrorGuaranteed { - self.into_struct_error(span, resolution_error).emit() + self.into_struct_error(span, resolution_error).emit_err() } pub(crate) fn into_struct_error( @@ -1460,7 +1460,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.dcx().create_err(diagnostics::ModuleOnly(span)) } } - .emit() + .emit_err() } pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String { diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index b581777901195..119cc130282be 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -1380,7 +1380,7 @@ pub(crate) enum ItemWas { } impl Subdiagnostic for FoundItemConfigureOut { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut multispan: MultiSpan = self.span.into(); match self.item_was { ItemWas::BehindFeature { feature, span } => { @@ -1522,8 +1522,8 @@ pub(crate) struct Ambiguity { pub is_error: bool, } -impl<'a, G> Diagnostic<'a, G> for Ambiguity { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for Ambiguity { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { ident, ambig_vis, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index fe46287373dee..7d90b93b62375 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2018,7 +2018,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { }, ); self.point_at_impl_lifetimes(&mut err, i, lifetime.ident.span); - err.emit() + err.emit_err() } } else if self.diag_metadata.in_assoc_ty_binding { // For associated type bindings, e.g. @@ -2035,7 +2035,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { &mut err, lifetime.ident.span, ); - err.emit() + err.emit_err() } else { self.r.dcx().emit_err( crate::diagnostics::ElidedAnonymousLifetimeReportError { @@ -3211,7 +3211,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { .create_err(crate::diagnostics::UnderscoreLifetimeIsReserved { span: param.ident.span, }) - .emit_unless_delay(is_raw_underscore_lifetime); + .emit_err_unless_delay(is_raw_underscore_lifetime); // Record lifetime res, so lowering knows there is something fishy. self.record_lifetime_err(param.id, guar); continue; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 611e7147757fe..2d8fef78bafa6 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3930,7 +3930,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ); } - err.emit() + err.emit_err() } fn suggest_introducing_lifetime( @@ -4191,7 +4191,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { lifetime_refs, function_param_lifetimes, ); - err.emit() + err.emit_err() } fn add_missing_lifetime_specifiers_label<'a>( @@ -4732,7 +4732,7 @@ pub(super) fn signal_lifetime_shadowing( ) .with_span_label(orig.span, "first declared here") .with_span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name)) - .emit() + .emit_err() } struct LifetimeFinder<'ast> { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 0633fcd253b4f..753a4ed0d779a 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1866,7 +1866,7 @@ pub fn build_target_config( { err.help(format!("did you mean `{suggestion}`?")); } - err.emit() + err.emit_fatal() } } } @@ -2571,7 +2571,7 @@ pub fn parse_externs( let mut externs: BTreeMap = BTreeMap::new(); for arg in matches.opt_strs("extern") { let ExternOpt { crate_name: name, path, options } = - split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit()); + split_extern_opt(early_dcx, unstable_opts, &arg).unwrap_or_else(|e| e.emit_fatal()); let entry = externs.entry(name.to_owned()); diff --git a/compiler/rustc_session/src/config/externs.rs b/compiler/rustc_session/src/config/externs.rs index ff76eaaeaf4fc..0534821b3aec3 100644 --- a/compiler/rustc_session/src/config/externs.rs +++ b/compiler/rustc_session/src/config/externs.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; -use rustc_errors::{Diag, FatalAbort}; +use rustc_errors::Diag; use super::UnstableOptions; use crate::EarlyDiagCtxt; @@ -21,11 +21,13 @@ pub(crate) struct ExternOpt { /// /// The options field will be a string containing comma-separated options that will need further /// parsing and processing. +/// +/// On error, the returned `Diag` is fatal. pub(crate) fn split_extern_opt<'a>( early_dcx: &'a EarlyDiagCtxt, unstable_opts: &UnstableOptions, extern_opt: &str, -) -> Result> { +) -> Result> { let (name, path) = match extern_opt.split_once('=') { None => (extern_opt.to_string(), None), Some((name, path)) => (name.to_string(), Some(PathBuf::from(path))), diff --git a/compiler/rustc_session/src/config/print_request.rs b/compiler/rustc_session/src/config/print_request.rs index b41ceb1699eaa..e48b99626033a 100644 --- a/compiler/rustc_session/src/config/print_request.rs +++ b/compiler/rustc_session/src/config/print_request.rs @@ -339,5 +339,5 @@ fn emit_unknown_print_request_help( diag.help("for more information, see the rustc book: https://doc.rust-lang.org/rustc/command-line-arguments.html#--print-print-compiler-information"); } - diag.emit() + diag.emit_fatal() } diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index a2bf9a0d2dfc3..4ec8ca42edbee 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -95,7 +95,7 @@ pub fn feature_warn_issue( /// Adds the diagnostics for a feature to an existing error. /// Must be a language feature! -pub fn add_feature_diagnostics(err: &mut Diag<'_, G>, sess: &Session, feature: Symbol) { +pub fn add_feature_diagnostics(err: &mut Diag<'_>, sess: &Session, feature: Symbol) { add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false, None); } @@ -104,8 +104,8 @@ pub fn add_feature_diagnostics(err: &mut Diag<'_, G>, sess: &Session, feature /// This variant allows you to control whether it is a library or language feature. /// Almost always, you want to use this for a language feature. If so, prefer /// `add_feature_diagnostics`. -pub fn add_feature_diagnostics_for_issue( - err: &mut Diag<'_, G>, +pub fn add_feature_diagnostics_for_issue( + err: &mut Diag<'_>, sess: &Session, feature: Symbol, issue: GateIssue, @@ -192,9 +192,9 @@ pub(crate) struct FeatureGateError { pub(crate) explain: DiagMessage, } -impl<'a, G> Diagnostic<'a, G> for FeatureGateError { +impl<'a> Diagnostic<'a> for FeatureGateError { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { Diag::new(dcx, level, self.explain).with_span(self.span).with_code(E0658) } } @@ -578,7 +578,7 @@ pub fn report_lit_error( lit: token::Lit, span: Span, ) -> ErrorGuaranteed { - create_lit_error(psess, err, lit, span).emit() + create_lit_error(psess, err, lit, span).emit_err() } pub fn create_lit_error(psess: &ParseSess, err: LitError, lit: token::Lit, span: Span) -> Diag<'_> { diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index 0e79d220b3962..b9555e6520087 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -148,7 +148,7 @@ impl ParseSess { } pub fn dyn_buffer_lint< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a, ()> + DynSync + DynSend + 'static, + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level) -> Diag<'a> + DynSync + DynSend + 'static, >( &self, lint: &'static Lint, @@ -165,7 +165,7 @@ impl ParseSess { } pub fn dyn_buffer_lint_sess< - F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a, ()> + F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a> + DynSync + DynSend + 'static, diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 274cfe8d7eb8a..96b48ef3289eb 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -17,8 +17,7 @@ use rustc_errors::emitter::{DynEmitter, HumanReadableErrorType, OutputTheme, std use rustc_errors::json::JsonEmitter; use rustc_errors::timings::TimingSectionHandler; use rustc_errors::{ - Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, FatalAbort, PResult, - TerminalUrl, + Diag, DiagCtxt, DiagCtxtHandle, DiagMessage, Diagnostic, ErrorGuaranteed, PResult, TerminalUrl, }; use rustc_feature::UnstableFeatures; use rustc_macros::StableHash; @@ -1880,7 +1879,7 @@ impl EarlyDiagCtxt { self.dcx.handle().fatal(msg) } - pub fn early_struct_fatal(&self, msg: impl Into) -> Diag<'_, FatalAbort> { + pub fn early_struct_fatal(&self, msg: impl Into) -> Diag<'_> { self.dcx.handle().struct_fatal(msg) } @@ -1888,7 +1887,7 @@ impl EarlyDiagCtxt { self.dcx.handle().warn(msg) } - pub fn early_struct_warn(&self, msg: impl Into) -> Diag<'_, ()> { + pub fn early_struct_warn(&self, msg: impl Into) -> Diag<'_> { self.dcx.handle().struct_warn(msg) } } diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 02a181adfadb7..4b7be976cdb30 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -36,9 +36,9 @@ pub(crate) struct NegativePositiveConflict<'tcx> { pub positive_impl_span: Result, } -impl Diagnostic<'_, G> for NegativePositiveConflict<'_> { +impl Diagnostic<'_> for NegativePositiveConflict<'_> { #[track_caller] - fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_, G> { + fn into_diag(self, dcx: DiagCtxtHandle<'_>, level: Level) -> Diag<'_> { let mut diag = Diag::new( dcx, level, @@ -89,7 +89,7 @@ pub(crate) enum AdjustSignatureBorrow { } impl Subdiagnostic for AdjustSignatureBorrow { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { AdjustSignatureBorrow::Borrow { to_borrow } => { diag.arg("borrow_len", to_borrow.len()); @@ -437,8 +437,8 @@ pub(crate) enum RegionOriginNote<'a> { } impl Subdiagnostic for RegionOriginNote<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { - let label_or_note = |diag: &mut Diag<'_, G>, span, msg: DiagMessage| { + fn add_to_diag(self, diag: &mut Diag<'_>) { + let label_or_note = |diag: &mut Diag<'_>, span, msg: DiagMessage| { let sub_count = diag.children.iter().filter(|d| d.span.is_dummy()).count(); let expanded_sub_count = diag.children.iter().filter(|d| !d.span.is_dummy()).count(); let span_is_primary = diag.span.primary_spans().iter().all(|&sp| sp == span); @@ -532,7 +532,7 @@ pub(crate) enum LifetimeMismatchLabels { } impl Subdiagnostic for LifetimeMismatchLabels { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { match self { LifetimeMismatchLabels::InRet { param_span, ret_span, span, label_var1 } => { diag.span_label(param_span, msg!("this parameter and the return type are declared with different lifetimes...")); @@ -605,7 +605,7 @@ pub(crate) struct AddLifetimeParamsSuggestion<'a> { } impl Subdiagnostic for AddLifetimeParamsSuggestion<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut mk_suggestion = || { let Some(anon_reg) = self.tcx.is_suitable_region(self.generic_param_scope, self.sub) else { @@ -789,7 +789,7 @@ pub(crate) struct IntroducesStaticBecauseUnmetLifetimeReq { } impl Subdiagnostic for IntroducesStaticBecauseUnmetLifetimeReq { - fn add_to_diag(mut self, diag: &mut Diag<'_, G>) { + fn add_to_diag(mut self, diag: &mut Diag<'_>) { self.unmet_requirements.push_span_label( self.binding_span, msg!("introduces a `'static` lifetime requirement"), @@ -1184,7 +1184,7 @@ pub(crate) struct ConsiderBorrowingParamHelp { } impl Subdiagnostic for ConsiderBorrowingParamHelp { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let mut type_param_span: MultiSpan = self.spans.clone().into(); for &span in &self.spans { // Seems like we can't call f() here as Into is required @@ -1661,7 +1661,7 @@ pub(crate) struct SuggestTuplePatternMany { } impl Subdiagnostic for SuggestTuplePatternMany { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.arg("path", self.path); let message = msg!("try wrapping the pattern in a variant of `{$path}`"); diag.multipart_suggestions( @@ -1907,7 +1907,7 @@ pub(crate) struct AddPreciseCapturingAndParams { } impl Subdiagnostic for AddPreciseCapturingAndParams { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { diag.arg("new_lifetime", self.new_lifetime); diag.multipart_suggestion( msg!("add a `use<...>` bound to explicitly capture `{$new_lifetime}` after turning all argument-position `impl Trait` into type parameters, noting that this possibly affects the API of this crate"), @@ -2047,7 +2047,7 @@ pub struct AddPreciseCapturingForOvercapture { } impl Subdiagnostic for AddPreciseCapturingForOvercapture { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let applicability = if self.apit_spans.is_empty() { Applicability::MachineApplicable } else { diff --git a/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs b/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs index 76a071543d318..906fdd7f963c7 100644 --- a/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/diagnostics/note_and_explain.rs @@ -162,7 +162,7 @@ impl RegionExplanation<'_> { } impl Subdiagnostic for RegionExplanation<'_> { - fn add_to_diag(self, diag: &mut Diag<'_, G>) { + fn add_to_diag(self, diag: &mut Diag<'_>) { let msg = msg!( "{$pref_kind -> *[should_not_happen] [{$pref_kind}] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs index c0b4bdab84945..2fb05084a381a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/mod.rs @@ -73,7 +73,7 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> { pub fn try_report(&self) -> Option { self.try_report_from_nll() - .map(|diag| diag.emit()) + .map(|diag| diag.emit_err()) .or_else(|| self.try_report_impl_not_conforming_to_trait()) .or_else(|| self.try_report_anon_anon_conflict()) .or_else(|| self.try_report_static_impl_trait()) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 6c6d68e63ed63..166c320cda28a 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -128,8 +128,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { Some(anon_reg_sup.scope), ); - let reported = err.emit(); - Some(reported) + let guar = err.emit_err(); + Some(guar) } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index f1be118896b01..03baa5c2acbfb 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -165,7 +165,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { }, )); } - diag.emit() + diag.emit_err() } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index 26aadefb69f1a..b9f70cea5f5ab 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -72,10 +72,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { RegionResolutionError::ConcreteFailure(origin, sub, sup) => { if sub.is_placeholder() || sup.is_placeholder() { self.report_placeholder_failure(generic_param_scope, origin, sub, sup) - .emit() + .emit_err() } else { self.report_concrete_failure(generic_param_scope, origin, sub, sup) - .emit() + .emit_err() } } @@ -104,7 +104,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sub_r, sup_r, ) - .emit() + .emit_err() } else if sup_r.is_placeholder() { self.report_placeholder_failure( generic_param_scope, @@ -112,7 +112,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sub_r, sup_r, ) - .emit() + .emit_err() } else { self.report_sub_sup_conflict( generic_param_scope, @@ -147,7 +147,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sub_r, sup_r, ) - .emit() + .emit_err() } RegionResolutionError::CannotNormalize(clause, origin) => { @@ -156,7 +156,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.tcx .dcx() .struct_span_err(origin.span(), format!("cannot normalize `{clause}`")) - .emit() + .emit_err() } } }; @@ -704,7 +704,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { sub: Region<'tcx>, ) -> ErrorGuaranteed { self.construct_generic_bound_failure(generic_param_scope, span, origin, bound_kind, sub) - .emit() + .emit_err() } pub fn construct_generic_bound_failure( @@ -1051,7 +1051,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { return if sub_region.is_error() | sup_region.is_error() { err.delay_as_bug() } else { - err.emit() + err.emit_err() }; } @@ -1068,7 +1068,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); self.note_region_origin(&mut err, &sub_origin); - if sub_region.is_error() | sup_region.is_error() { err.delay_as_bug() } else { err.emit() } + if sub_region.is_error() | sup_region.is_error() { + err.delay_as_bug() + } else { + err.emit_err() + } } fn report_inference_failure(&self, var_origin: RegionVariableOrigin<'tcx>) -> Diag<'_> { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index a44d53cdfdd05..62ac12a8edd24 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -266,7 +266,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { TypeAnnotationNeeded::E0282, false, ) - .emit(), + .emit_err(), Some(e) => e, }; } @@ -779,7 +779,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { self.note_obligation_cause(&mut err, &error.obligation); } } - err.emit() + err.emit_err() } /// The `impl`s and `where` clauses that could have satisfied `trait_pred`, when listing them diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 26d768e5b22e8..cf729def2f46c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -98,13 +98,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { trait_item_def_id, &format!("`{}`", obligation.predicate), ) - .emit(); + .emit_err(); } // Report a const-param specific error if let ObligationCauseCode::ConstParam(ty) = *obligation.cause.code().peel_derives() { - return self.report_const_param_not_wf(ty, &obligation).emit(); + return self.report_const_param_not_wf(ty, &obligation).emit_err(); } let bound_predicate = obligation.predicate.kind(); @@ -374,7 +374,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { have_alt_message, ) { self.note_obligation_cause(&mut err, &obligation); - return err.emit(); + return err.emit_err(); } let ty_span = match leaf_trait_predicate.self_ty().skip_binder().kind() { @@ -524,11 +524,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &mut err, leaf_trait_predicate, ) { - return err.emit(); + return err.emit_err(); } if self.suggest_impl_trait(&mut err, &obligation, leaf_trait_predicate) { - return err.emit(); + return err.emit_err(); } if is_unsize { @@ -632,7 +632,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { Some(sym::Debug | sym::Display) ) { - return err.emit(); + return err.emit_err(); } err @@ -828,7 +828,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; self.note_obligation_cause(&mut err, &obligation); - err.emit() + err.emit_err() } } @@ -1078,7 +1078,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); self.suggest_change_mut_ref_for_closure(&mut err, &obligation); self.note_obligation_cause(&mut err, &obligation); - return Some(err.emit()); + return Some(err.emit_err()); } // If the closure has captures, then perhaps the reason that the trait @@ -1099,7 +1099,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { coro_kind, }); self.note_obligation_cause(&mut err, &obligation); - return Some(err.emit()); + return Some(err.emit_err()); } None @@ -1901,7 +1901,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if mention_bounds { self.note_obligation_cause(&mut diag, obligation); } - diag.emit() + diag.emit_err() }) } @@ -3993,7 +3993,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Note that with `feature(generic_const_exprs)` this case should not // be reachable. .with_note("this may fail depending on what value the parameter takes") - .emit(); + .emit_err(); return Err(guar); } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index b0a513f692c38..c120df4e2c3ef 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -425,7 +425,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { error.obligation.cause.span, "higher-ranked lifetime bound could not be satisfied", ) - .emit(), + .emit_err(), FulfillmentErrorCode::Ambiguity { overflow: None } => { self.maybe_report_ambiguity(&error.obligation, related) } @@ -440,7 +440,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { expected_found.found, *err, ) - .emit(), + .emit_err(), FulfillmentErrorCode::ConstEquate(ref expected_found, ref err) => { let mut diag = self.report_mismatched_consts( &error.obligation.cause, @@ -463,7 +463,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { &mut Default::default(), ); } - diag.emit() + diag.emit_err() } FulfillmentErrorCode::Cycle(ref cycle) => self.report_overflow_obligation_cycle(cycle), } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs index cea5c2f5a3d53..ac0bb13f8fc35 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/overflow.rs @@ -17,7 +17,7 @@ pub enum OverflowCause<'tcx> { TraitSolver(ty::Predicate<'tcx>), } -pub fn suggest_new_overflow_limit<'tcx, G>(tcx: TyCtxt<'tcx>, err: &mut Diag<'_, G>) { +pub fn suggest_new_overflow_limit<'tcx>(tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) { let suggested_limit = match tcx.recursion_limit() { Limit(0) => Limit(2), limit => limit * 2, @@ -46,7 +46,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ) -> ! { let mut err = self.build_overflow_error(cause, span, suggest_increasing_limit); mutate(&mut err); - err.emit().raise_fatal(); + err.emit_err().raise_fatal(); } pub fn build_overflow_error( @@ -190,6 +190,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { suggest_increasing_limit, ); self.note_obligation_cause(&mut err, &obligation); - err.emit() + err.emit_err() } } diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index fffe80be255ce..277ba8f3d3bac 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -119,12 +119,12 @@ fn predicate_constraint(generics: &hir::Generics<'_>, pred: ty::Predicate<'_>) - /// Type parameter needs more bounds. The trivial case is `T` `where T: Bound`, but /// it can also be an `impl Trait` param that needs to be decomposed to a type /// param for cleaner code. -pub fn suggest_restriction<'tcx, G>( +pub fn suggest_restriction<'tcx>( tcx: TyCtxt<'tcx>, item_id: LocalDefId, hir_generics: &hir::Generics<'tcx>, msg: &str, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, fn_sig: Option<&hir::FnSig<'_>>, projection: Option>, trait_pred: ty::PolyTraitClause<'tcx>, @@ -2758,10 +2758,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { false } - pub(super) fn suggest_borrow_for_unsized_closure_return( + pub(super) fn suggest_borrow_for_unsized_closure_return( &self, body_def_id: LocalDefId, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, predicate: ty::Predicate<'tcx>, ) { let Some(pred) = predicate.as_trait_clause() else { @@ -3303,9 +3303,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// /// Returns `true` if an async-await specific note was added to the diagnostic. #[instrument(level = "debug", skip_all, fields(?obligation.predicate, ?obligation.cause.span))] - pub fn maybe_note_obligation_cause_for_async_await( + pub fn maybe_note_obligation_cause_for_async_await( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, obligation: &PredicateObligation<'tcx>, ) -> bool { // Attempt to detect an async-await error by looking at the obligation causes, looking @@ -3535,9 +3535,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// Unconditionally adds the diagnostic note described in /// `maybe_note_obligation_cause_for_async_await`'s documentation comment. #[instrument(level = "debug", skip_all)] - fn note_obligation_cause_for_async_await( + fn note_obligation_cause_for_async_await( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, interior_or_upvar_span: CoroutineInteriorOrUpvar, is_async: bool, outer_coroutine: Option, @@ -3769,9 +3769,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - fn note_closure_capture( + fn note_closure_capture( &self, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, closure_def_id: DefId, upvar_args: ty::UpvarArgs<'tcx>, capture_ty: Option>, @@ -3822,10 +3822,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { true } - pub(super) fn note_obligation_cause_code( + pub(super) fn note_obligation_cause_code( &self, body_def_id: LocalDefId, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, predicate: T, param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, @@ -3851,10 +3851,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } - fn note_obligation_cause_code_inner( + fn note_obligation_cause_code_inner( &self, body_def_id: LocalDefId, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, predicate: T, param_env: ty::ParamEnv<'tcx>, cause_code: &ObligationCauseCode<'tcx>, @@ -3866,7 +3866,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { { let tcx = self.tcx; let predicate = predicate.upcast(tcx); - let suggest_remove_deref = |err: &mut Diag<'_, G>, expr: &hir::Expr<'_>| { + let suggest_remove_deref = |err: &mut Diag<'_>, expr: &hir::Expr<'_>| { if let Some(pred) = predicate.as_trait_clause() && tcx.is_lang_item(pred.def_id(), LangItem::Sized) && let hir::ExprKind::Unary(hir::UnOp::Deref, inner) = expr.kind @@ -5211,10 +5211,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn note_function_argument_obligation( + fn note_function_argument_obligation( &self, body_def_id: LocalDefId, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, arg_hir_id: HirId, parent_code: &ObligationCauseCode<'tcx>, param_env: ty::ParamEnv<'tcx>, @@ -5450,11 +5450,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn suggest_option_method_if_applicable( + fn suggest_option_method_if_applicable( &self, failed_pred: ty::Predicate<'tcx>, param_env: ty::ParamEnv<'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, expr: &hir::Expr<'_>, ) { let tcx = self.tcx; @@ -5525,7 +5525,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn look_for_iterator_item_mistakes( + fn look_for_iterator_item_mistakes( &self, assocs_in_this_method: &[Option<(Span, (DefId, Ty<'tcx>))>], typeck_results: &TypeckResults<'tcx>, @@ -5534,7 +5534,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { path_segment: &hir::PathSegment<'_>, args: &[hir::Expr<'_>], prev_ty: Ty<'_>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, ) { let tcx = self.tcx; // Special case for iterator chains, we look at potential failures of `Iterator::Item` @@ -5674,13 +5674,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - fn point_at_chain( + fn point_at_chain( &self, expr: &hir::Expr<'_>, typeck_results: &TypeckResults<'tcx>, type_diffs: Vec>, param_env: ty::ParamEnv<'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, ) { let mut primary_spans = vec![]; let mut span_labels = vec![]; @@ -5923,13 +5923,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { /// | | `Iterator::Item` is `&mut Vec` here /// | this expression has type `Vec>` /// ``` - fn point_at_chain_in_return_position( + fn point_at_chain_in_return_position( &self, body_def_id: LocalDefId, expr: &hir::Expr<'_>, typeck_results: &TypeckResults<'tcx>, param_env: ty::ParamEnv<'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, ) { let tcx = self.tcx; if !matches!(tcx.def_kind(body_def_id), DefKind::Fn | DefKind::AssocFn) { @@ -7111,9 +7111,9 @@ pub fn suggest_desugaring_async_fn_to_impl_future_in_trait<'tcx>( /// On `impl` evaluation cycles, look for `Self::AssocTy` restrictions in `where` clauses, explain /// they are not allowed and if possible suggest alternatives. -fn point_at_assoc_type_restriction( +fn point_at_assoc_type_restriction( tcx: TyCtxt<'_>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, self_ty_str: &str, trait_name: &str, predicate: ty::Predicate<'_>, diff --git a/compiler/rustc_trait_selection/src/opaque_types.rs b/compiler/rustc_trait_selection/src/opaque_types.rs index 10d5202905c72..4370935ead285 100644 --- a/compiler/rustc_trait_selection/src/opaque_types.rs +++ b/compiler/rustc_trait_selection/src/opaque_types.rs @@ -51,7 +51,7 @@ impl<'tcx> NonDefiningUseReason<'tcx> { .dcx() .struct_span_err(span, "non-defining opaque type use in defining scope") .with_span_note(spans, format!("{descr} used multiple times")) - .emit() + .emit_err() } } } @@ -231,5 +231,5 @@ pub fn report_item_does_not_constrain_error<'tcx>( format!("this use of `{opaque_ty}` does not have unique universal generic arguments"), ); } - err.emit() + err.emit_err() } diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index 2b7e7ac1c6642..d3c118b33e8ce 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -60,16 +60,16 @@ pub struct OverlapResult<'tcx> { pub overflowing_predicates: Vec>, } -pub fn add_placeholder_note(err: &mut Diag<'_, G>) { +pub fn add_placeholder_note(err: &mut Diag<'_>) { err.note( "this behavior recently changed as a result of a bug fix; \ see rust-lang/rust#56105 for details", ); } -pub(crate) fn suggest_increasing_recursion_limit<'tcx, G>( +pub(crate) fn suggest_increasing_recursion_limit<'tcx>( tcx: TyCtxt<'tcx>, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, overflowing_predicates: &[ty::Predicate<'tcx>], ) { for pred in overflowing_predicates { diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index aa8ab84243f7c..9bcbf393dd05b 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -127,7 +127,7 @@ pub fn is_const_evaluatable<'tcx>( "#![feature(generic_const_exprs)]\n", rustc_errors::Applicability::MaybeIncorrect, ) - .emit() + .emit_fatal() } Err(EvaluateConstErr::HasGenericsOrInfers) => { diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index f1a6c002dc584..c1f4e74119744 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -737,7 +737,7 @@ fn project<'cx, 'tcx>( ) } else { let violations = tcx.dyn_compatibility_violations(def_id); - report_dyn_incompatibility(tcx, span, None, def_id, &violations).emit() + report_dyn_incompatibility(tcx, span, None, def_id, &violations).emit_err() }; return Ok(Projected::Progress(Progress::error_for_term( tcx, diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cf8672814ff70..f8619fcd120a2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -63,7 +63,7 @@ pub enum IntercrateAmbiguityCause<'tcx> { impl<'tcx> IntercrateAmbiguityCause<'tcx> { /// Emits notes when the overlap is caused by complex intercrate ambiguities. /// See #23980 for details. - pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diag<'_, G>) { + pub fn add_intercrate_ambiguity_hint(&self, err: &mut Diag<'_>) { err.note(self.intercrate_ambiguity_hint()); } diff --git a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs index 35c6f60f36035..987e2af81984b 100644 --- a/compiler/rustc_trait_selection/src/traits/specialize/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/specialize/mod.rs @@ -513,7 +513,7 @@ fn report_negative_positive_conflict<'tcx>( cause.add_intercrate_ambiguity_hint(&mut diag); } - diag.emit() + diag.emit_err() } fn report_conflicting_impls<'tcx>( @@ -527,11 +527,11 @@ fn report_conflicting_impls<'tcx>( // Work to be done after we've built the Diag. We have to define it now // because the lint emit methods don't return back the Diag that's passed // in. - fn decorate<'tcx, G>( + fn decorate<'tcx>( tcx: TyCtxt<'tcx>, overlap: &OverlapError<'tcx>, impl_span: Span, - err: &mut Diag<'_, G>, + err: &mut Diag<'_>, ) { match tcx.span_of_impl(overlap.with_impl) { Ok(span) => { @@ -594,7 +594,7 @@ fn report_conflicting_impls<'tcx>( let mut err = tcx.dcx().struct_span_err(impl_span, msg()); err.code(E0119); decorate(tcx, &overlap, impl_span, &mut err); - err.emit() + err.emit_err() } else { tcx.dcx().span_delayed_bug(impl_span, "impl should have failed the orphan check") }; diff --git a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md index 7ca97b7b059e4..f8df01ba5e1cb 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md +++ b/src/doc/rustc-dev-guide/src/diagnostics/diagnostic-structs.md @@ -93,8 +93,8 @@ In the end, the `Diagnostic` derive will generate an implementation of `Diagnostic` that looks like the following: ```rust,ignore -impl<'a, G> Diagnostic<'a> for FieldAlreadyDeclared { - fn into_diag(self, dcx: &'a DiagCtxt, level: Level) -> Diag<'a, G> { +impl<'a> Diagnostic<'a> for FieldAlreadyDeclared { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut diag = Diag::new(dcx, level, "field `{$field_name}` is already declared"); diag.set_span(self.span); diag.span_label( diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index c2c58a345fa22..fb89a6547a931 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -752,12 +752,12 @@ impl Options { if !theme_file.is_file() { dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must be files") - .emit(); + .emit_fatal(); } if theme_file.extension() != Some(OsStr::new("css")) { dcx.struct_fatal(format!("invalid argument: \"{theme_s}\"")) .with_help("arguments to --theme must have a .css extension") - .emit(); + .emit_fatal(); } let (success, ret) = theme::test_theme_against(&theme_file, &paths, dcx); if !success { diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs index af1cd195266cb..43c825c889907 100644 --- a/src/librustdoc/html/markdown.rs +++ b/src/librustdoc/html/markdown.rs @@ -875,7 +875,7 @@ impl<'doc, 'tcx> ExtraInfo<'doc, 'tcx> { fn error_invalid_codeblock_attr_with_help( &self, msg: impl Into, - f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a, ()>), + f: impl for<'a, 'b> FnOnce(&'b mut Diag<'a>), ) { self.tcx.emit_node_span_lint( crate::lint::INVALID_CODEBLOCK_ATTRIBUTES, diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1ae23d58448a3..1f6d15147dcb3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1471,7 +1471,7 @@ impl LinkCollector<'_, '_> { ) { // The resolved item did not match the disambiguator; give a better error than 'not found' let msg = format!("incompatible link kind for `{path_str}`"); - let callback = |diag: &mut Diag<'_, ()>, sp: Option, link_range| { + let callback = |diag: &mut Diag<'_>, sp: Option, link_range| { let note = format!( "this link resolved to {} {}, which is not {} {}", resolved.article(), @@ -1929,7 +1929,7 @@ fn report_diagnostic( lint: &'static Lint, msg: impl Into + Display, DiagnosticInfo { item, ori_link: _, dox, link_range }: &DiagnosticInfo<'_>, - decorate: impl FnOnce(&mut Diag<'_, ()>, Option, MarkdownLinkRange), + decorate: impl FnOnce(&mut Diag<'_>, Option, MarkdownLinkRange), ) { let Some(hir_id) = DocContext::as_local_hir_id(tcx, item.item_id) else { // If non-local, no need to check anything. @@ -2007,7 +2007,7 @@ fn report_diagnostic( fn suggest_path_name_typo( collector: &LinkCollector<'_, '_>, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, span: Option, link_range: &MarkdownLinkRange, dox: &str, @@ -2522,7 +2522,7 @@ fn ambiguity_error( /// disambiguator. fn suggest_disambiguator( res: Res, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, path_str: &str, link_range: MarkdownLinkRange, sp: Option, diff --git a/src/librustdoc/passes/lint/check_code_block_syntax.rs b/src/librustdoc/passes/lint/check_code_block_syntax.rs index b25d081f6ae80..cd838a4a83b20 100644 --- a/src/librustdoc/passes/lint/check_code_block_syntax.rs +++ b/src/librustdoc/passes/lint/check_code_block_syntax.rs @@ -41,8 +41,8 @@ fn check_rust_syntax( is_precise_span: bool, } - impl<'a, 'b> Diagnostic<'a, ()> for CodeblockError<'b> { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, 'b> Diagnostic<'a> for CodeblockError<'b> { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { buffer, code_block, span, is_precise_span } = self; let mut lint = Diag::new( diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index d2f244e7bba0b..902054c917699 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -164,8 +164,8 @@ struct RedundantExplicitLinksWithoutSuggestion { dest_link: String, } -impl<'a> Diagnostic<'a, ()> for RedundantExplicitLinksWithoutSuggestion { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { +impl<'a> Diagnostic<'a> for RedundantExplicitLinksWithoutSuggestion { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { attr_span, display_link, dest_link } = self; Diag::new(dcx, level, "redundant explicit link target") @@ -199,8 +199,8 @@ fn check_inline_or_reference_unknown_redundancy( display_link: String, } - impl<'a> Diagnostic<'a, ()> for RedundantExplicitLinks { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for RedundantExplicitLinks { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { explicit_span, display_span, link_span, display_link } = self; Diag::new(dcx, level, "redundant explicit link target") @@ -318,8 +318,8 @@ fn check_reference_redundancy( display_link: String, } - impl<'a> Diagnostic<'a, ()> for RedundantExplicitLinkTarget { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a> Diagnostic<'a> for RedundantExplicitLinkTarget { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let Self { explicit_span, display_span, def_span, link_span, display_link } = self; Diag::new(dcx, level, "redundant explicit link target") diff --git a/src/librustdoc/passes/lint/unescaped_backticks.rs b/src/librustdoc/passes/lint/unescaped_backticks.rs index 9c86c50dcca7c..dd6a1b26de76f 100644 --- a/src/librustdoc/passes/lint/unescaped_backticks.rs +++ b/src/librustdoc/passes/lint/unescaped_backticks.rs @@ -413,7 +413,7 @@ fn suggest_insertion( cx: &DocContext<'_>, item: &Item, dox: &str, - lint: &mut Diag<'_, ()>, + lint: &mut Diag<'_>, insert_index: usize, suggestion: char, message: &'static str, diff --git a/src/tools/clippy/clippy_config/src/types.rs b/src/tools/clippy/clippy_config/src/types.rs index 53df7f4e2581b..a9a04e8a5c0a9 100644 --- a/src/tools/clippy/clippy_config/src/types.rs +++ b/src/tools/clippy/clippy_config/src/types.rs @@ -141,7 +141,7 @@ impl DisallowedPath { &self.path.node } - pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) { + pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_>) { move |diag| { if let Some(replacement) = &self.replacement { diag.span_suggestion( diff --git a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs index f758fb0042301..ce03afac4c102 100644 --- a/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/src/tools/clippy/clippy_lints/src/casts/cast_possible_truncation.rs @@ -181,7 +181,7 @@ fn offer_suggestion( expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_span: Span, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, ) { let cast_to_snip = snippet(cx, cast_to_span, ".."); let mut applicability = Applicability::Unspecified; diff --git a/src/tools/clippy/clippy_lints/src/empty_line_after.rs b/src/tools/clippy/clippy_lints/src/empty_line_after.rs index aa5b8ec2f727a..805f5dca1bf5d 100644 --- a/src/tools/clippy/clippy_lints/src/empty_line_after.rs +++ b/src/tools/clippy/clippy_lints/src/empty_line_after.rs @@ -431,7 +431,7 @@ impl EmptyLineAfter { /// If the node the attributes/docs apply to is the first in the module/crate suggest converting /// them to inner attributes/docs - fn suggest_inner(&self, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) { + fn suggest_inner(&self, diag: &mut Diag<'_>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) { if let Some(parent) = self.items.iter().rev().nth(1) && matches!(parent.kind, ItemKindDescr::Module | ItemKindDescr::Crate) && parent.mod_items == Some(id) diff --git a/src/tools/clippy/clippy_lints/src/functions/result.rs b/src/tools/clippy/clippy_lints/src/functions/result.rs index 6a7013e0f1737..a2121bb431b4e 100644 --- a/src/tools/clippy/clippy_lints/src/functions/result.rs +++ b/src/tools/clippy/clippy_lints/src/functions/result.rs @@ -174,7 +174,7 @@ fn check_result_large_err<'tcx>( RESULT_LARGE_ERR, hir_ty_span, format!("the `Err`-variant returned from this {subject} is very large"), - |diag: &mut Diag<'_, ()>| { + |diag: &mut Diag<'_>| { diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes")); diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); }, diff --git a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs index 310b45ca408cf..4e9cf7925f286 100644 --- a/src/tools/clippy/clippy_lints/src/if_let_mutex.rs +++ b/src/tools/clippy/clippy_lints/src/if_let_mutex.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { && let Some(arm_mutex) = for_each_expr_without_closures((if_then, if_else), |e| mutex_lock_call(cx, ctxt, e, Some(op_mutex))) { - let diag = |diag: &mut Diag<'_, ()>| { + let diag = |diag: &mut Diag<'_>| { diag.span_label( op_mutex.span, "this Mutex will remain locked for the entire `if let`-block...", diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index e39ff754a5b3b..02f8170fedc27 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn suggestion( cx: &LateContext<'_>, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, generics_span: Span, generics_suggestion_span: Span, target: &ImplicitHasherType<'_>, diff --git a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs index 3d3539bc70458..77357538461f5 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_frames.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_frames.rs @@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { return; } - let explain_lint = |diag: &mut Diag<'_, ()>, ctxt: SyntaxContext| { + let explain_lint = |diag: &mut Diag<'_>, ctxt: SyntaxContext| { // Point out the largest individual contribution to this size, because // it is the most likely to be unintentionally large. if let Some((local, size)) = sizes_of_locals.iter().max_by_key(|&(_, size)| size) diff --git a/src/tools/clippy/clippy_lints/src/manual_clamp.rs b/src/tools/clippy/clippy_lints/src/manual_clamp.rs index 41f8fff98a21c..8a30e01d0aaf0 100644 --- a/src/tools/clippy/clippy_lints/src/manual_clamp.rs +++ b/src/tools/clippy/clippy_lints/src/manual_clamp.rs @@ -205,7 +205,7 @@ fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggest }; let suggestion = format!("{assignment}{input}.clamp({min}, {max}){semicolon}"); let msg = "clamp-like pattern without using clamp function"; - let lint_builder = |d: &mut Diag<'_, ()>| { + let lint_builder = |d: &mut Diag<'_>| { d.span_suggestion(*span, "replace with clamp", suggestion, Applicability::MaybeIncorrect); if *is_float { d.note("clamp will panic if max < min, min.is_nan(), or max.is_nan()") diff --git a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index db1e4f2717bd9..3581f7a93ef07 100644 --- a/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/src/tools/clippy/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -121,7 +121,7 @@ fn check<'tcx>( } } -fn set_suggestion<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { +fn set_suggestion<'tcx>(diag: &mut Diag<'_>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { let original = snippet(cx, found.found_span, ".."); let trailing_indent = " ".repeat(indent_of(cx, found.found_span).unwrap_or(0)); diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index f3e7d080237c8..3d9a634f2008f 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -90,7 +90,7 @@ fn report_single_pattern( ) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; let ctxt = expr.span.ctxt(); - let note = |diag: &mut Diag<'_, ()>| { + let note = |diag: &mut Diag<'_>| { if contains_comments { diag.note("you might want to preserve the comments from inside the `match`"); } diff --git a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs index 185baf592f2e1..b596e710e5307 100644 --- a/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/src/tools/clippy/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg SUSPICIOUS_COMMAND_ARG_SPACE, arg.span, "single argument that looks like it should be multiple arguments", - |diag: &mut Diag<'_, ()>| { + |diag: &mut Diag<'_>| { diag.multipart_suggestion( "consider splitting the argument", vec![(span, "args".to_string()), (arg.span, format!("[{arg1:?}, {arg2:?}]"))], diff --git a/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs index 0b8f6ae9f2779..b04b9140adf2e 100644 --- a/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs +++ b/src/tools/clippy/clippy_lints/src/methods/swap_with_temporary.rs @@ -76,7 +76,7 @@ impl<'tcx> ArgKind<'tcx> { // Emits a note either on the temporary expression if it can be found in the same context as the // base and returns `true`, or on the mutable reference to the temporary expression otherwise and // returns `false`. -fn emit_note(diag: &mut Diag<'_, ()>, base: &Expr<'_>, expr: &Expr<'_>, expr_temp: &Expr<'_>) -> bool { +fn emit_note(diag: &mut Diag<'_>, base: &Expr<'_>, expr: &Expr<'_>, expr_temp: &Expr<'_>) -> bool { if base.span.eq_ctxt(expr.span) { diag.span_note(expr_temp.span.source_callsite(), MSG_TEMPORARY); true diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index 1e6e27afc6775..edb1c9c53ded7 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -75,7 +75,7 @@ impl Replacement { } } - fn maybe_add_note(&self, diag: &mut Diag<'_, ()>) { + fn maybe_add_note(&self, diag: &mut Diag<'_>) { if self.is_short_circuiting { diag.note(format!( "the `{}` method is short circuiting and may change the program semantics if the iterator has side effects", diff --git a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs index 98f8b63532cc5..bb615ff4ef110 100644 --- a/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/src/tools/clippy/clippy_lints/src/missing_asserts_for_indexing.rs @@ -68,7 +68,7 @@ declare_lint_pass!(MissingAssertsForIndexing => [MISSING_ASSERTS_FOR_INDEXING]); fn report_lint(cx: &LateContext<'_>, index_spans: Vec, msg: &'static str, f: F) where - F: FnOnce(&mut Diag<'_, ()>), + F: FnOnce(&mut Diag<'_>), { span_lint_and_then(cx, MISSING_ASSERTS_FOR_INDEXING, index_spans, msg, |diag| { f(diag); diff --git a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs index 52797d43a045f..b3ee09c71af17 100644 --- a/src/tools/clippy/clippy_lints/src/mutex_atomic.rs +++ b/src/tools/clippy/clippy_lints/src/mutex_atomic.rs @@ -135,7 +135,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, ty_ascription: &T && let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = "using a `Mutex` where an atomic would do"; - let diag = |diag: &mut Diag<'_, _>| { + let diag = |diag: &mut Diag<'_>| { // if `expr = Mutex::new(arg)`, we can try emitting a suggestion if let ExprKind::Call(qpath, [arg]) = expr.kind && let ExprKind::Path(QPath::TypeRelative(_mutex, new)) = qpath.kind diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index c332b332cbd41..d6f30e1865853 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -203,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { && !moved_vars.contains(&canonical_id) { // Dereference suggestion - let sugg = |diag: &mut Diag<'_, ()>| { + let sugg = |diag: &mut Diag<'_>| { if let ty::Adt(def, ..) = ty.kind() && let Some(span) = cx.tcx.hir_span_if_local(def.did()) && type_allowed_to_implement_copy( diff --git a/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs b/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs index 58d6fa24ce13b..eeaed34abac50 100644 --- a/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs +++ b/src/tools/clippy/clippy_lints/src/pointers_in_nomem_asm_block.rs @@ -81,7 +81,7 @@ fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) - cx.typeck_results().expr_ty(asm_in_expr).is_any_ptr() } -fn additional_notes(diag: &mut rustc_errors::Diag<'_, ()>) { +fn additional_notes(diag: &mut rustc_errors::Diag<'_>) { diag.note("`nomem` means that no memory write or read happens inside the asm! block"); diag.note("if this is intentional and no pointers are read or written to, consider allowing the lint"); } diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index 4cda9c4aeb568..e063b3d6cc632 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -16,7 +16,7 @@ use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::Span; use std::env; -fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { +fn docs_link(diag: &mut Diag<'_>, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() && let Some(lint) = lint.name_lower().strip_prefix("clippy::") { @@ -43,7 +43,7 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// /// This function makes sure we also validate them in debug clippy builds. #[cfg(debug_assertions)] -fn validate_diag(diag: &Diag<'_, G>) { +fn validate_diag(diag: &Diag<'_>) { let suggestions = match &diag.suggestions { Suggestions::Enabled(suggs) => &**suggs, Suggestions::Sealed(suggs) => &**suggs, @@ -238,12 +238,12 @@ where C: LintContext, S: Into, M: Into, - F: FnOnce(&mut Diag<'_, ()>), + F: FnOnce(&mut Diag<'_>), { - struct ClippyDiag)>(F); + struct ClippyDiag)>(F); - impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for ClippyDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, F: FnOnce(&mut Diag<'_>)> Diagnostic<'a> for ClippyDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut lint = Diag::new(dcx, level, ""); (self.0)(&mut lint); lint @@ -255,7 +255,7 @@ where cx.emit_span_lint( lint, sp.clone(), - ClippyDiag(|diag: &mut Diag<'_, ()>| { + ClippyDiag(|diag: &mut Diag<'_>| { diag.primary_message(msg); diag.span(sp); f(diag); @@ -327,7 +327,7 @@ pub fn span_lint_hir_and_then( hir_id: HirId, sp: impl Into, msg: impl Into, - f: impl FnOnce(&mut Diag<'_, ()>), + f: impl FnOnce(&mut Diag<'_>), ) { #[expect(clippy::disallowed_methods)] cx.tcx.emit_node_span_lint( diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 702bbd0be46dc..3d4645f72fce3 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -744,7 +744,7 @@ pub trait DiagExt { fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability); } -impl DiagExt for rustc_errors::Diag<'_, ()> { +impl DiagExt for rustc_errors::Diag<'_> { fn suggest_item_with_attr( &mut self, cx: &T, diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 1d88a792734f9..4d25aed007416 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -572,7 +572,7 @@ fn report_msg<'tcx>( DiagLevel::Warning => Level::Warning, DiagLevel::Note => Level::Note, }; - let mut err = Diag::<()>::new(tcx.sess.dcx(), level, title); + let mut err = Diag::new(tcx.sess.dcx(), level, title); err.span(span); // Show main message. diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs index b30d33091c47f..c744c03f8649a 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.rs @@ -2,7 +2,7 @@ // Tests that a doc comment will not preclude a field from being considered a diagnostic argument //@ normalize-stderr: "the following other types implement trait `IntoDiagArg`:(?:.*\n){0,9}\s+and \d+ others" -> "normalized in stderr" //@ normalize-stderr: "(COMPILER_DIR/.*\.rs):[0-9]+:[0-9]+" -> "$1:LL:CC" -//@ normalize-stderr: "rustc_errors::Diag::<'a, G>::arg" -> "Diag::<'a, G>::arg" +//@ normalize-stderr: "rustc_errors::Diag::<'a>::arg" -> "Diag::<'a>::arg" // The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, // changing the output of this test. Since Subdiagnostic is strictly internal to the compiler diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr index feee6eed4593f..24f01051bb6f7 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-doc-comment-field.stderr @@ -14,7 +14,7 @@ LL | struct NotIntoDiagArg; | ^^^^^^^^^^^^^^^^^^^^^ = help: normalized in stderr = note: there's an inherent method on `DiagInner` of the same name, which can be auto-dereferenced from `&mut DiagInner` -note: required by a bound in `Diag::<'a, G>::arg` +note: required by a bound in `Diag::<'a>::arg` --> $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC ::: $COMPILER_DIR/rustc_errors/src/diagnostic.rs:LL:CC | From 9d3983393bf87276bb434701b6c141865ee72b49 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 11 Sep 2026 07:33:25 +1000 Subject: [PATCH 0488/1309] Remove `G` generic param from `Diag<'_, G>` It encodes the `emit` behaviour, one of: - `BugAbort`: Abort as a bug. - `FatalAbort`: Abort as a fatal error. - `ErrorGuaranteed`: Return an `ErrorGuaranteed` (the default). - `()`: return `()`. This is useful but `Diag` is very widely used and it's arguably not useful enough to be worth the generic parameter. This commit removes it. Benefits: - Many fewer generic parameters, including many functions where the genericity is entirely uninteresting. This includes every `Diagnostic::into_diag` and `Subdiagnostic::add_to_diag`. Removes the need for the comment about `` on `trait Diagnostic`. - No `PhantomData` in `Diag`. - Makes bootstrapping a bit faster. The downside is there is no longer a single `emit` method. - Getting a `!` return type requires calling `emit_bug` or `emit_fatal`. This only affects a few call sites. - Getting an `ErrorGuaranteed` return type requires calling `emit_err`. This affects a lot of call sites. (It arguably makes call sites more self-documenting.) - Using the wrong `emit_*` on a diagnostic causes a runtime abort, which previously couldn't occur. Seems unlikely, but it's not impossible. - Note: If no particular return type is needed, `emit` can be used for any diagnostic. (Bug/fatal diagnostics will still trigger abort.) --- clippy_config/src/types.rs | 2 +- .../src/casts/cast_possible_truncation.rs | 2 +- clippy_lints/src/empty_line_after.rs | 2 +- clippy_lints/src/functions/result.rs | 2 +- clippy_lints/src/if_let_mutex.rs | 2 +- clippy_lints/src/implicit_hasher.rs | 2 +- clippy_lints/src/large_stack_frames.rs | 2 +- clippy_lints/src/manual_clamp.rs | 2 +- .../src/matches/significant_drop_in_scrutinee.rs | 2 +- clippy_lints/src/matches/single_match.rs | 2 +- .../src/methods/suspicious_command_arg_space.rs | 2 +- clippy_lints/src/methods/swap_with_temporary.rs | 2 +- clippy_lints/src/methods/unnecessary_fold.rs | 2 +- clippy_lints/src/missing_asserts_for_indexing.rs | 2 +- clippy_lints/src/mutex_atomic.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 2 +- clippy_lints/src/pointers_in_nomem_asm_block.rs | 2 +- clippy_utils/src/diagnostics.rs | 16 ++++++++-------- clippy_utils/src/sugg.rs | 2 +- 19 files changed, 26 insertions(+), 26 deletions(-) diff --git a/clippy_config/src/types.rs b/clippy_config/src/types.rs index 53df7f4e2581b..a9a04e8a5c0a9 100644 --- a/clippy_config/src/types.rs +++ b/clippy_config/src/types.rs @@ -141,7 +141,7 @@ impl DisallowedPath { &self.path.node } - pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_, ()>) { + pub fn diag_amendment(&self, span: Span) -> impl FnOnce(&mut Diag<'_>) { move |diag| { if let Some(replacement) = &self.replacement { diag.span_suggestion( diff --git a/clippy_lints/src/casts/cast_possible_truncation.rs b/clippy_lints/src/casts/cast_possible_truncation.rs index f758fb0042301..ce03afac4c102 100644 --- a/clippy_lints/src/casts/cast_possible_truncation.rs +++ b/clippy_lints/src/casts/cast_possible_truncation.rs @@ -181,7 +181,7 @@ fn offer_suggestion( expr: &Expr<'_>, cast_expr: &Expr<'_>, cast_to_span: Span, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, ) { let cast_to_snip = snippet(cx, cast_to_span, ".."); let mut applicability = Applicability::Unspecified; diff --git a/clippy_lints/src/empty_line_after.rs b/clippy_lints/src/empty_line_after.rs index aa5b8ec2f727a..805f5dca1bf5d 100644 --- a/clippy_lints/src/empty_line_after.rs +++ b/clippy_lints/src/empty_line_after.rs @@ -431,7 +431,7 @@ impl EmptyLineAfter { /// If the node the attributes/docs apply to is the first in the module/crate suggest converting /// them to inner attributes/docs - fn suggest_inner(&self, diag: &mut Diag<'_, ()>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) { + fn suggest_inner(&self, diag: &mut Diag<'_>, kind: StopKind, gaps: &[Gap<'_>], id: NodeId) { if let Some(parent) = self.items.iter().rev().nth(1) && matches!(parent.kind, ItemKindDescr::Module | ItemKindDescr::Crate) && parent.mod_items == Some(id) diff --git a/clippy_lints/src/functions/result.rs b/clippy_lints/src/functions/result.rs index 6a7013e0f1737..a2121bb431b4e 100644 --- a/clippy_lints/src/functions/result.rs +++ b/clippy_lints/src/functions/result.rs @@ -174,7 +174,7 @@ fn check_result_large_err<'tcx>( RESULT_LARGE_ERR, hir_ty_span, format!("the `Err`-variant returned from this {subject} is very large"), - |diag: &mut Diag<'_, ()>| { + |diag: &mut Diag<'_>| { diag.span_label(hir_ty_span, format!("the `Err`-variant is at least {ty_size} bytes")); diag.help(format!("try reducing the size of `{err_ty}`, for example by boxing large elements or replacing it with `Box<{err_ty}>`")); }, diff --git a/clippy_lints/src/if_let_mutex.rs b/clippy_lints/src/if_let_mutex.rs index 310b45ca408cf..4e9cf7925f286 100644 --- a/clippy_lints/src/if_let_mutex.rs +++ b/clippy_lints/src/if_let_mutex.rs @@ -66,7 +66,7 @@ impl<'tcx> LateLintPass<'tcx> for IfLetMutex { && let Some(arm_mutex) = for_each_expr_without_closures((if_then, if_else), |e| mutex_lock_call(cx, ctxt, e, Some(op_mutex))) { - let diag = |diag: &mut Diag<'_, ()>| { + let diag = |diag: &mut Diag<'_>| { diag.span_label( op_mutex.span, "this Mutex will remain locked for the entire `if let`-block...", diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index e39ff754a5b3b..02f8170fedc27 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -61,7 +61,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'_>) { fn suggestion( cx: &LateContext<'_>, - diag: &mut Diag<'_, ()>, + diag: &mut Diag<'_>, generics_span: Span, generics_suggestion_span: Span, target: &ImplicitHasherType<'_>, diff --git a/clippy_lints/src/large_stack_frames.rs b/clippy_lints/src/large_stack_frames.rs index 3d3539bc70458..77357538461f5 100644 --- a/clippy_lints/src/large_stack_frames.rs +++ b/clippy_lints/src/large_stack_frames.rs @@ -183,7 +183,7 @@ impl<'tcx> LateLintPass<'tcx> for LargeStackFrames { return; } - let explain_lint = |diag: &mut Diag<'_, ()>, ctxt: SyntaxContext| { + let explain_lint = |diag: &mut Diag<'_>, ctxt: SyntaxContext| { // Point out the largest individual contribution to this size, because // it is the most likely to be unintentionally large. if let Some((local, size)) = sizes_of_locals.iter().max_by_key(|&(_, size)| size) diff --git a/clippy_lints/src/manual_clamp.rs b/clippy_lints/src/manual_clamp.rs index 41f8fff98a21c..8a30e01d0aaf0 100644 --- a/clippy_lints/src/manual_clamp.rs +++ b/clippy_lints/src/manual_clamp.rs @@ -205,7 +205,7 @@ fn maybe_emit_suggestion<'tcx>(cx: &LateContext<'tcx>, suggestion: &ClampSuggest }; let suggestion = format!("{assignment}{input}.clamp({min}, {max}){semicolon}"); let msg = "clamp-like pattern without using clamp function"; - let lint_builder = |d: &mut Diag<'_, ()>| { + let lint_builder = |d: &mut Diag<'_>| { d.span_suggestion(*span, "replace with clamp", suggestion, Applicability::MaybeIncorrect); if *is_float { d.note("clamp will panic if max < min, min.is_nan(), or max.is_nan()") diff --git a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs index db1e4f2717bd9..3581f7a93ef07 100644 --- a/clippy_lints/src/matches/significant_drop_in_scrutinee.rs +++ b/clippy_lints/src/matches/significant_drop_in_scrutinee.rs @@ -121,7 +121,7 @@ fn check<'tcx>( } } -fn set_suggestion<'tcx>(diag: &mut Diag<'_, ()>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { +fn set_suggestion<'tcx>(diag: &mut Diag<'_>, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>, found: FoundSigDrop) { let original = snippet(cx, found.found_span, ".."); let trailing_indent = " ".repeat(indent_of(cx, found.found_span).unwrap_or(0)); diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index f3e7d080237c8..3d9a634f2008f 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -90,7 +90,7 @@ fn report_single_pattern( ) { let lint = if els.is_some() { SINGLE_MATCH_ELSE } else { SINGLE_MATCH }; let ctxt = expr.span.ctxt(); - let note = |diag: &mut Diag<'_, ()>| { + let note = |diag: &mut Diag<'_>| { if contains_comments { diag.note("you might want to preserve the comments from inside the `match`"); } diff --git a/clippy_lints/src/methods/suspicious_command_arg_space.rs b/clippy_lints/src/methods/suspicious_command_arg_space.rs index 185baf592f2e1..b596e710e5307 100644 --- a/clippy_lints/src/methods/suspicious_command_arg_space.rs +++ b/clippy_lints/src/methods/suspicious_command_arg_space.rs @@ -24,7 +24,7 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, recv: &'tcx hir::Expr<'_>, arg SUSPICIOUS_COMMAND_ARG_SPACE, arg.span, "single argument that looks like it should be multiple arguments", - |diag: &mut Diag<'_, ()>| { + |diag: &mut Diag<'_>| { diag.multipart_suggestion( "consider splitting the argument", vec![(span, "args".to_string()), (arg.span, format!("[{arg1:?}, {arg2:?}]"))], diff --git a/clippy_lints/src/methods/swap_with_temporary.rs b/clippy_lints/src/methods/swap_with_temporary.rs index 0b8f6ae9f2779..b04b9140adf2e 100644 --- a/clippy_lints/src/methods/swap_with_temporary.rs +++ b/clippy_lints/src/methods/swap_with_temporary.rs @@ -76,7 +76,7 @@ impl<'tcx> ArgKind<'tcx> { // Emits a note either on the temporary expression if it can be found in the same context as the // base and returns `true`, or on the mutable reference to the temporary expression otherwise and // returns `false`. -fn emit_note(diag: &mut Diag<'_, ()>, base: &Expr<'_>, expr: &Expr<'_>, expr_temp: &Expr<'_>) -> bool { +fn emit_note(diag: &mut Diag<'_>, base: &Expr<'_>, expr: &Expr<'_>, expr_temp: &Expr<'_>) -> bool { if base.span.eq_ctxt(expr.span) { diag.span_note(expr_temp.span.source_callsite(), MSG_TEMPORARY); true diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index 1e6e27afc6775..edb1c9c53ded7 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -75,7 +75,7 @@ impl Replacement { } } - fn maybe_add_note(&self, diag: &mut Diag<'_, ()>) { + fn maybe_add_note(&self, diag: &mut Diag<'_>) { if self.is_short_circuiting { diag.note(format!( "the `{}` method is short circuiting and may change the program semantics if the iterator has side effects", diff --git a/clippy_lints/src/missing_asserts_for_indexing.rs b/clippy_lints/src/missing_asserts_for_indexing.rs index 98f8b63532cc5..bb615ff4ef110 100644 --- a/clippy_lints/src/missing_asserts_for_indexing.rs +++ b/clippy_lints/src/missing_asserts_for_indexing.rs @@ -68,7 +68,7 @@ declare_lint_pass!(MissingAssertsForIndexing => [MISSING_ASSERTS_FOR_INDEXING]); fn report_lint(cx: &LateContext<'_>, index_spans: Vec, msg: &'static str, f: F) where - F: FnOnce(&mut Diag<'_, ()>), + F: FnOnce(&mut Diag<'_>), { span_lint_and_then(cx, MISSING_ASSERTS_FOR_INDEXING, index_spans, msg, |diag| { f(diag); diff --git a/clippy_lints/src/mutex_atomic.rs b/clippy_lints/src/mutex_atomic.rs index 52797d43a045f..b3ee09c71af17 100644 --- a/clippy_lints/src/mutex_atomic.rs +++ b/clippy_lints/src/mutex_atomic.rs @@ -135,7 +135,7 @@ fn check_expr<'tcx>(cx: &LateContext<'tcx>, expr: &Expr<'tcx>, ty_ascription: &T && let Some(atomic_name) = get_atomic_name(mutex_param) { let msg = "using a `Mutex` where an atomic would do"; - let diag = |diag: &mut Diag<'_, _>| { + let diag = |diag: &mut Diag<'_>| { // if `expr = Mutex::new(arg)`, we can try emitting a suggestion if let ExprKind::Call(qpath, [arg]) = expr.kind && let ExprKind::Path(QPath::TypeRelative(_mutex, new)) = qpath.kind diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index c332b332cbd41..d6f30e1865853 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -203,7 +203,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue { && !moved_vars.contains(&canonical_id) { // Dereference suggestion - let sugg = |diag: &mut Diag<'_, ()>| { + let sugg = |diag: &mut Diag<'_>| { if let ty::Adt(def, ..) = ty.kind() && let Some(span) = cx.tcx.hir_span_if_local(def.did()) && type_allowed_to_implement_copy( diff --git a/clippy_lints/src/pointers_in_nomem_asm_block.rs b/clippy_lints/src/pointers_in_nomem_asm_block.rs index 58d6fa24ce13b..eeaed34abac50 100644 --- a/clippy_lints/src/pointers_in_nomem_asm_block.rs +++ b/clippy_lints/src/pointers_in_nomem_asm_block.rs @@ -81,7 +81,7 @@ fn has_in_operand_pointer(cx: &LateContext<'_>, asm_op: &InlineAsmOperand<'_>) - cx.typeck_results().expr_ty(asm_in_expr).is_any_ptr() } -fn additional_notes(diag: &mut rustc_errors::Diag<'_, ()>) { +fn additional_notes(diag: &mut rustc_errors::Diag<'_>) { diag.note("`nomem` means that no memory write or read happens inside the asm! block"); diag.note("if this is intentional and no pointers are read or written to, consider allowing the lint"); } diff --git a/clippy_utils/src/diagnostics.rs b/clippy_utils/src/diagnostics.rs index 4cda9c4aeb568..e063b3d6cc632 100644 --- a/clippy_utils/src/diagnostics.rs +++ b/clippy_utils/src/diagnostics.rs @@ -16,7 +16,7 @@ use rustc_lint::{LateContext, Lint, LintContext}; use rustc_span::Span; use std::env; -fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { +fn docs_link(diag: &mut Diag<'_>, lint: &'static Lint) { if env::var("CLIPPY_DISABLE_DOCS_LINKS").is_err() && let Some(lint) = lint.name_lower().strip_prefix("clippy::") { @@ -43,7 +43,7 @@ fn docs_link(diag: &mut Diag<'_, ()>, lint: &'static Lint) { /// /// This function makes sure we also validate them in debug clippy builds. #[cfg(debug_assertions)] -fn validate_diag(diag: &Diag<'_, G>) { +fn validate_diag(diag: &Diag<'_>) { let suggestions = match &diag.suggestions { Suggestions::Enabled(suggs) => &**suggs, Suggestions::Sealed(suggs) => &**suggs, @@ -238,12 +238,12 @@ where C: LintContext, S: Into, M: Into, - F: FnOnce(&mut Diag<'_, ()>), + F: FnOnce(&mut Diag<'_>), { - struct ClippyDiag)>(F); + struct ClippyDiag)>(F); - impl<'a, F: FnOnce(&mut Diag<'_, ()>)> Diagnostic<'a, ()> for ClippyDiag { - fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a, ()> { + impl<'a, F: FnOnce(&mut Diag<'_>)> Diagnostic<'a> for ClippyDiag { + fn into_diag(self, dcx: DiagCtxtHandle<'a>, level: Level) -> Diag<'a> { let mut lint = Diag::new(dcx, level, ""); (self.0)(&mut lint); lint @@ -255,7 +255,7 @@ where cx.emit_span_lint( lint, sp.clone(), - ClippyDiag(|diag: &mut Diag<'_, ()>| { + ClippyDiag(|diag: &mut Diag<'_>| { diag.primary_message(msg); diag.span(sp); f(diag); @@ -327,7 +327,7 @@ pub fn span_lint_hir_and_then( hir_id: HirId, sp: impl Into, msg: impl Into, - f: impl FnOnce(&mut Diag<'_, ()>), + f: impl FnOnce(&mut Diag<'_>), ) { #[expect(clippy::disallowed_methods)] cx.tcx.emit_node_span_lint( diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 702bbd0be46dc..3d4645f72fce3 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -744,7 +744,7 @@ pub trait DiagExt { fn suggest_remove_item(&mut self, cx: &T, item: Span, msg: &str, applicability: Applicability); } -impl DiagExt for rustc_errors::Diag<'_, ()> { +impl DiagExt for rustc_errors::Diag<'_> { fn suggest_item_with_attr( &mut self, cx: &T, From 02db8ad6411e0f1eaa920ed7d84721be2f058e96 Mon Sep 17 00:00:00 2001 From: Yukang Date: Sun, 13 Sep 2026 20:59:40 +0800 Subject: [PATCH 0489/1309] Suggest similarly named modules in import paths --- .../rustc_resolve/src/diagnostics/impls.rs | 44 +++++++++++- .../nested-module-typo-issue-131366.fixed | 36 ++++++++++ .../nested-module-typo-issue-131366.rs | 1 + .../nested-module-typo-issue-131366.stderr | 42 +++++++++-- tests/ui/unresolved/unresolved-import.fixed | 70 +++++++++++++++++++ tests/ui/unresolved/unresolved-import.rs | 12 ++-- tests/ui/unresolved/unresolved-import.stderr | 24 +++---- 7 files changed, 206 insertions(+), 23 deletions(-) create mode 100644 tests/ui/imports/nested-module-typo-issue-131366.fixed create mode 100644 tests/ui/unresolved/unresolved-import.fixed diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 6ddfff9f88d83..ee13092abd68e 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -3024,6 +3024,41 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let message = format!("cannot find `{ident}` in {scope}"); + // we may have typo in the middle part of path, try find a candidate with a similar name + // and then check whether it contains a candidate that is accessible from the current scope + let typo_suggestion = if opt_ns.is_none() + && ignore_import.is_some() + && let Some(ModuleOrUniformRoot::Module(module)) = module + && let Some(candidate) = self.early_lookup_typo_candidate( + ScopeSet::Module(TypeNS, module), + parent_scope, + ident, + &|res| matches!(res, Res::Def(DefKind::Mod | DefKind::Enum, _)), + ) + && let Ok(binding) = self.cm().resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + Ident::new(candidate.candidate, ident.span), + TypeNS, + parent_scope, + None, + ignore_decl, + ignore_import, + ) + && self.is_accessible_from(binding.vis(), parent_scope.module) + { + Some(( + vec![(ident.span, Ident::new(candidate.candidate, ident.span).to_string())], + format!( + "{} {} with a similar name exists", + candidate.res.article(), + candidate.res.descr(), + ), + Applicability::MaybeIncorrect, + )) + } else { + None + }; + if module_def_id == Some(CRATE_DEF_ID.to_def_id()) { let is_mod = |res| matches!(res, Res::Def(DefKind::Mod, _)); let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod); @@ -3050,6 +3085,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { )), None, ) + } else if let Some(suggestion) = typo_suggestion { + ( + message, + format!("could not find `{ident}` in the crate root"), + Some(suggestion), + None, + ) } else if ident.name == sym::core { ( message, @@ -3182,7 +3224,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { ); }; } - (message, msg, None, None) + (message, msg, typo_suggestion, None) } else if ident.name == kw::SelfUpper { // As mentioned above, `opt_ns` being `None` indicates a module path in import. // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an diff --git a/tests/ui/imports/nested-module-typo-issue-131366.fixed b/tests/ui/imports/nested-module-typo-issue-131366.fixed new file mode 100644 index 0000000000000..a84119fe93a8b --- /dev/null +++ b/tests/ui/imports/nested-module-typo-issue-131366.fixed @@ -0,0 +1,36 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/131366. +//! Suggest accessible, similarly named modules within the resolved import prefix. + +//@ edition: 2021 +//@ run-rustfix +#![allow(unused_imports, dead_code)] + +use std::collections::HashMap; +//~^ ERROR unresolved import `std::collection` + +mod local { + pub mod collections { + pub struct Item; + } + pub use collections as containers; + pub enum Choices { First } +} + +use local::collections::Item; +//~^ ERROR unresolved import `local::collection` +use local::containers::Item as Alias; +//~^ ERROR unresolved import `local::container` +use local::Choices::First; +//~^ ERROR unresolved import `local::Choice` + +mod root_module {} +use crate::root_module::*; +//~^ ERROR unresolved import `crate::root_modul` + +macro_rules! import { + ($module:ident) => { use local::$module::Item as MacroItem; }; +} +import!(collections); +//~^ ERROR unresolved import `local::collection` + +fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.rs b/tests/ui/imports/nested-module-typo-issue-131366.rs index ff16cd129d0ff..2f269da41b209 100644 --- a/tests/ui/imports/nested-module-typo-issue-131366.rs +++ b/tests/ui/imports/nested-module-typo-issue-131366.rs @@ -2,6 +2,7 @@ //! Suggest accessible, similarly named modules within the resolved import prefix. //@ edition: 2021 +//@ run-rustfix #![allow(unused_imports, dead_code)] use std::collection::HashMap; diff --git a/tests/ui/imports/nested-module-typo-issue-131366.stderr b/tests/ui/imports/nested-module-typo-issue-131366.stderr index 3666417c4107c..922b9219a7854 100644 --- a/tests/ui/imports/nested-module-typo-issue-131366.stderr +++ b/tests/ui/imports/nested-module-typo-issue-131366.stderr @@ -1,38 +1,68 @@ error[E0432]: unresolved import `std::collection` - --> $DIR/nested-module-typo-issue-131366.rs:7:10 + --> $DIR/nested-module-typo-issue-131366.rs:8:10 | LL | use std::collection::HashMap; | ^^^^^^^^^^ could not find `collection` in `std` + | +help: a module with a similar name exists + | +LL | use std::collections::HashMap; + | + error[E0432]: unresolved import `local::collection` - --> $DIR/nested-module-typo-issue-131366.rs:18:12 + --> $DIR/nested-module-typo-issue-131366.rs:19:12 | LL | use local::collection::Item; | ^^^^^^^^^^ could not find `collection` in `local` + | +help: a module with a similar name exists + | +LL | use local::collections::Item; + | + error[E0432]: unresolved import `local::container` - --> $DIR/nested-module-typo-issue-131366.rs:20:12 + --> $DIR/nested-module-typo-issue-131366.rs:21:12 | LL | use local::container::Item as Alias; | ^^^^^^^^^ could not find `container` in `local` + | +help: a module with a similar name exists + | +LL | use local::containers::Item as Alias; + | + error[E0432]: unresolved import `local::Choice` - --> $DIR/nested-module-typo-issue-131366.rs:22:12 + --> $DIR/nested-module-typo-issue-131366.rs:23:12 | LL | use local::Choice::First; | ^^^^^^ could not find `Choice` in `local` + | +help: an enum with a similar name exists + | +LL | use local::Choices::First; + | + error[E0432]: unresolved import `crate::root_modul` - --> $DIR/nested-module-typo-issue-131366.rs:26:12 + --> $DIR/nested-module-typo-issue-131366.rs:27:12 | LL | use crate::root_modul::*; | ^^^^^^^^^^ could not find `root_modul` in the crate root + | +help: a module with a similar name exists + | +LL | use crate::root_module::*; + | + error[E0432]: unresolved import `local::collection` - --> $DIR/nested-module-typo-issue-131366.rs:32:9 + --> $DIR/nested-module-typo-issue-131366.rs:33:9 | LL | import!(collection); | ^^^^^^^^^^ could not find `collection` in `local` + | +help: a module with a similar name exists + | +LL | import!(collections); + | + error: aborting due to 6 previous errors diff --git a/tests/ui/unresolved/unresolved-import.fixed b/tests/ui/unresolved/unresolved-import.fixed new file mode 100644 index 0000000000000..2132e5e21859f --- /dev/null +++ b/tests/ui/unresolved/unresolved-import.fixed @@ -0,0 +1,70 @@ +//@ edition:2015 +//@ run-rustfix + +#![allow(unused_imports, dead_code)] + +use food::beans; +//~^ ERROR unresolved import `foo` [E0432] +//~| NOTE could not find `foo` in the crate root +//~| HELP a module with a similar name exists +//~| SUGGESTION food + +use bar::Bar as x; +//~^ ERROR unresolved import `bar::Baz` [E0432] +//~| NOTE no `Baz` in `bar` +//~| HELP a similar name exists in the module +//~| SUGGESTION Bar + +use food::bag; +//~^ ERROR unresolved import `food::baz` +//~| NOTE no `baz` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION bag + +use food::{beans as Foo}; +//~^ ERROR unresolved import `food::beens` [E0432] +//~| NOTE no `beens` in `food` +//~| HELP a similar name exists in the module +//~| SUGGESTION beans + +mod bar { + pub struct Bar; +} + +mod food { + pub use self::zug::baz::{self as bag, Foobar as beans}; + + mod zug { + pub mod baz { + //~^ NOTE module `food::zug::baz` exists but is inaccessible + //~| NOTE not accessible + pub struct Foobar; + } + } +} + +mod m { + enum MyEnum { + MyVariant + } + + use self::MyEnum::*; + //~^ ERROR unresolved import `MyEnum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::MyEnum +} + +mod items { + enum Enum { + Variant + } + + use self::Enum::*; + //~^ ERROR unresolved import `Enum` [E0432] + //~| HELP a similar path exists + //~| SUGGESTION self::Enum + + fn item() {} +} + +fn main() {} diff --git a/tests/ui/unresolved/unresolved-import.rs b/tests/ui/unresolved/unresolved-import.rs index 8795a5342b2fd..ce9bf73537492 100644 --- a/tests/ui/unresolved/unresolved-import.rs +++ b/tests/ui/unresolved/unresolved-import.rs @@ -1,9 +1,13 @@ //@ edition:2015 -use foo::bar; +//@ run-rustfix + +#![allow(unused_imports, dead_code)] + +use foo::beans; //~^ ERROR unresolved import `foo` [E0432] -//~| NOTE use of unresolved module or unlinked crate `foo` -//~| HELP you might be missing a crate named `foo` -//~| SUGGESTION extern crate foo; +//~| NOTE could not find `foo` in the crate root +//~| HELP a module with a similar name exists +//~| SUGGESTION food use bar::Baz as x; //~^ ERROR unresolved import `bar::Baz` [E0432] diff --git a/tests/ui/unresolved/unresolved-import.stderr b/tests/ui/unresolved/unresolved-import.stderr index a5704787688a9..7aac9dc683349 100644 --- a/tests/ui/unresolved/unresolved-import.stderr +++ b/tests/ui/unresolved/unresolved-import.stderr @@ -1,16 +1,16 @@ error[E0432]: unresolved import `foo` - --> $DIR/unresolved-import.rs:2:5 + --> $DIR/unresolved-import.rs:6:5 | -LL | use foo::bar; - | ^^^ use of unresolved module or unlinked crate `foo` +LL | use foo::beans; + | ^^^ could not find `foo` in the crate root | -help: you might be missing a crate named `foo`, add it to your project and import it in your code - | -LL + extern crate foo; +help: a module with a similar name exists | +LL | use food::beans; + | + error[E0432]: unresolved import `bar::Baz` - --> $DIR/unresolved-import.rs:8:5 + --> $DIR/unresolved-import.rs:12:5 | LL | use bar::Baz as x; | ^^^^^---^^^^^ @@ -24,7 +24,7 @@ LL + use bar::Bar as x; | error[E0432]: unresolved import `food::baz` - --> $DIR/unresolved-import.rs:14:5 + --> $DIR/unresolved-import.rs:18:5 | LL | use food::baz; | ^^^^^^--- @@ -32,7 +32,7 @@ LL | use food::baz; | no `baz` in `food` | note: module `food::zug::baz` exists but is inaccessible - --> $DIR/unresolved-import.rs:34:9 + --> $DIR/unresolved-import.rs:38:9 | LL | pub mod baz { | ^^^^^^^^^^^ not accessible @@ -43,7 +43,7 @@ LL + use food::bag; | error[E0432]: unresolved import `food::beens` - --> $DIR/unresolved-import.rs:20:12 + --> $DIR/unresolved-import.rs:24:12 | LL | use food::{beens as Foo}; | -----^^^^^^^ @@ -57,7 +57,7 @@ LL + use food::{beans as Foo}; | error[E0432]: unresolved import `MyEnum` - --> $DIR/unresolved-import.rs:47:9 + --> $DIR/unresolved-import.rs:51:9 | LL | use MyEnum::*; | ^^^^^^ @@ -68,7 +68,7 @@ LL | use self::MyEnum::*; | ++++++ error[E0432]: unresolved import `Enum` - --> $DIR/unresolved-import.rs:58:9 + --> $DIR/unresolved-import.rs:62:9 | LL | use Enum::*; | ^^^^ From 19a586258214f8dcd9a9febbe626aed0b1fce143 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 00:35:52 -0400 Subject: [PATCH 0490/1309] chore: bump rustfmt toolchain to nightly-2026-09-21 Bumping the toolchain version as part of a git subtree push. Before: ``` 1.100.0-nightly (bff8e12ff 2026-08-26) ``` After: ``` 1.100.0-nightly (bba531001 2026-09-20) ``` --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 9dda873e3e868..739ec1b48dad4 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-08-27" +channel = "nightly-2026-09-21" components = ["llvm-tools", "rustc-dev"] From 7fac56cb43b2e4176dc6bfbd9177b5e6ae91879f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Aug 2026 14:40:34 +1000 Subject: [PATCH 0491/1309] Fix graphviz label Commit c68d710d525, which introduced backward analyses, changed a label from `(on entry)` to `(on start)` but failed to update a few relevant places. This commit fixes that. --- compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 4 ++-- tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index be572eab929bc..80338394984f4 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -297,7 +297,7 @@ where // +-+----------------------------------+------------+ // B | MIR | STATE | // +-+----------------------------------+------------+ - // C | | (on entry) | {_0,_2,_3} | + // C | | (on start) | {_0,_2,_3} | // +-+----------------------------------+------------+ // D |0| StorageLive(_7) | | // +-+----------------------------------+------------+ @@ -581,7 +581,7 @@ where f: impl FnOnce(&mut Self, &mut W, &str) -> io::Result<()>, ) -> io::Result<()> { let bg = self.toggle_background(); - let valign = if mir.starts_with("(on ") && mir != "(on entry)" { "bottom" } else { "top" }; + let valign = if mir.starts_with("(on ") && mir != "(on start)" { "bottom" } else { "top" }; let fmt = format!("valign=\"{}\" sides=\"tl\" {}", valign, bg.attr()); diff --git a/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot b/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot index 258404b8da782..3df85518e1277 100644 --- a/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot +++ b/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot @@ -2,5 +2,5 @@ digraph graph_for_def_id_0_3 { graph[fontname="Courier, monospace"]; node[fontname="Courier, monospace"]; edge[fontname="Courier, monospace"]; - bb_0[label=<
bb0
MIRSTATE
(on start){_0}
0_0 = const ()-_0
Treturn
(on end){}
>][shape="none"]; + bb_0[label=<
bb0
MIRSTATE
(on start){_0}
0_0 = const ()-_0
Treturn
(on end){}
>][shape="none"]; } From 259bee66be64326c76c2dcc90618ed7b2345509a Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Aug 2026 14:43:27 +1000 Subject: [PATCH 0492/1309] Remove duplicated trait bound It's on the `impl` line and in the where clause. --- compiler/rustc_mir_dataflow/src/framework/graphviz.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index 80338394984f4..b4770af1d5fde 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -656,7 +656,7 @@ impl<'a, 'tcx, A: Analysis<'tcx>> StateDiffCollector<'a, 'tcx, A> { } } -impl<'a, 'tcx, A: Analysis<'tcx>> ResultsVisitor<'tcx, A> for StateDiffCollector<'a, 'tcx, A> +impl<'a, 'tcx, A> ResultsVisitor<'tcx, A> for StateDiffCollector<'a, 'tcx, A> where A: Analysis<'tcx>, A::Domain: DebugWithContext
, From acc7501018ff1a3fa1c341d39b79bc524535f5a2 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Mon, 21 Sep 2026 07:05:12 +0200 Subject: [PATCH 0493/1309] gca: fix unreachable --- .../src/builder/expr/as_constant.rs | 53 ++++++++++++------- .../gca/const-reference-to-constructor.rs | 10 ++++ 2 files changed, 43 insertions(+), 20 deletions(-) create mode 100644 tests/ui/const-generics/gca/const-reference-to-constructor.rs diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index eb9f56d887684..43936770ff762 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -74,28 +74,41 @@ pub(crate) fn as_constant_inner<'tcx>( ExprKind::NamedConst { def_id, args, ref user_ty } => { let user_ty = user_ty.as_ref().and_then(push_cuta); - // Under generic_const_args, `def_id` might be a regular const declared in a trait, but - // is `impl`d as a directly represented const. We do not know whether it is here, so we - // must use type system normalization for all consts under generic_const_args. - // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses valtrees - // and `Const::Unevaluated` does not, we should revisit this before stabilization. - let def_kind = tcx.def_kind(def_id); - if tcx.features().generic_const_args() - || matches!(def_kind, DefKind::Const | DefKind::AssocConst) - && tcx.is_direct_const(def_id) - { - let kind = match def_kind { - DefKind::AssocConst => { - if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id)) - { - ty::AliasConstKind::InherentImpl { def_id } - } else { - ty::AliasConstKind::Projection { def_id } - } + let get_kind = |def_id, def_kind| match def_kind { + DefKind::AssocConst => { + if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(def_id)) { + ty::AliasConstKind::InherentImpl { def_id } + } else { + ty::AliasConstKind::Projection { def_id } } - DefKind::Const => ty::AliasConstKind::Free { def_id }, - _ => unreachable!(), + } + DefKind::Const => ty::AliasConstKind::Free { def_id }, + kind => bug!("unexpected DefKind in THIR ExprKind::NamedConst: {kind:?}"), + }; + + let could_be_direct_const = |def_id| { + let def_kind = tcx.def_kind(def_id); + let (DefKind::Const | DefKind::AssocConst) = def_kind else { + return None; }; + if tcx.is_direct_const(def_id) { + return Some(get_kind(def_id, def_kind)); + } + // Under generic_const_args, `def_id` might be a regular const declared in a trait, + // but is `impl`d as a directly represented const. We do not know whether it is + // here, so we must use type system normalization for all const projections. + // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses + // valtrees and `Const::Unevaluated` does not, we should revisit this before + // stabilization. + if tcx.features().generic_const_args() + && let kind @ ty::AliasConstKind::Projection { .. } = get_kind(def_id, def_kind) + { + return Some(kind); + } + None + }; + + if let Some(kind) = could_be_direct_const(def_id) { let alias = ty::AliasConst::new(tcx, kind, args); let ct = ty::Const::new_alias(tcx, ty::IsRigid::No, alias); let const_ = Const::Ty(ty, ct); diff --git a/tests/ui/const-generics/gca/const-reference-to-constructor.rs b/tests/ui/const-generics/gca/const-reference-to-constructor.rs new file mode 100644 index 0000000000000..bafaf9f532545 --- /dev/null +++ b/tests/ui/const-generics/gca/const-reference-to-constructor.rs @@ -0,0 +1,10 @@ +//@ check-pass +//@ compile-flags: -Znext-solver +//! https://github.com/rust-lang/rust/issues/162923 +#![feature(min_generic_const_args)] +#![feature(generic_const_args)] +enum T::B as u8 }> { + A = 2, + B, +} +fn main() {} From 90dd142e3034b39e6e6857f770f690ed65855750 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Aug 2026 14:56:53 +1000 Subject: [PATCH 0494/1309] Remove two unnecessary `try` blocks --- .../src/framework/graphviz.rs | 42 +++++++------------ compiler/rustc_mir_dataflow/src/lib.rs | 1 - 2 files changed, 15 insertions(+), 28 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index b4770af1d5fde..b5f405a6a3008 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -43,29 +43,23 @@ where let def_id = body.source.def_id(); let attrs = RustcMirAttrs::parse(tcx, def_id); - let file = try { - match attrs.output_path(A::NAME) { - Some(path) => { - debug!("printing dataflow results for {:?} to {}", def_id, path.display()); - if let Some(parent) = path.parent() { - fs::create_dir_all(parent)?; - } - fs::File::create_buffered(&path)? + let mut file = match attrs.output_path(A::NAME) { + Some(path) => { + debug!("printing dataflow results for {:?} to {}", def_id, path.display()); + if let Some(parent) = path.parent() { + fs::create_dir_all(parent)?; } + fs::File::create_buffered(&path)? + } - None => { - let Some(dumper) = MirDumper::new(tcx, A::NAME, body) else { - return Ok(()); - }; - let disambiguator = &pass_name.unwrap_or("-----"); - dumper.set_disambiguator(disambiguator).create_dump_file("dot", body)? - } + None => { + let Some(dumper) = MirDumper::new(tcx, A::NAME, body) else { + return Ok(()); + }; + let disambiguator = &pass_name.unwrap_or("-----"); + dumper.set_disambiguator(disambiguator).create_dump_file("dot", body)? } }; - let mut file = match file { - Ok(f) => f, - Err(e) => return Err(e), - }; let style = attrs.formatter.unwrap_or(OutputStyle::AfterOnly); @@ -77,14 +71,8 @@ where if tcx.sess.opts.unstable_opts.graphviz_dark_mode { render_opts.push(dot::RenderOption::DarkTheme); } - let r = with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts)); - - let lhs = try { - r?; - file.write_all(&buf)?; - }; - - lhs + with_no_trimmed_paths!(dot::render_opts(&graphviz, &mut buf, &render_opts))?; + file.write_all(&buf) } #[derive(Default)] diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index c0929bef38465..07e42459c7a99 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -4,7 +4,6 @@ #![feature(deref_patterns)] #![feature(exact_size_is_empty)] #![feature(file_buffered)] -#![feature(try_blocks)] // tidy-alphabetical-end use rustc_middle::ty; From 8955f779f27dfbd70839d62935150b629f77b0bb Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:41:17 +0900 Subject: [PATCH 0495/1309] Add `std_or_core` helper for crate-qualified rustfix paths --- compiler/rustc_lint/src/utils.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs index 5854e89d801de..5ece48370c043 100644 --- a/compiler/rustc_lint/src/utils.rs +++ b/compiler/rustc_lint/src/utils.rs @@ -1,4 +1,4 @@ -use rustc_hir::{Expr, ExprKind}; +use rustc_hir::{Expr, ExprKind, find_attr}; use rustc_span::sym; use crate::LateContext; @@ -47,3 +47,14 @@ pub(crate) fn peel_casts<'tcx>( e } + +/// Crate to use for rustfix / diagnostic paths that exist in both `std` and `core`. Returns `None` for `#![no_core]`. +pub(crate) fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { + if find_attr!(cx.tcx, crate, NoCore) { + None + } else if find_attr!(cx.tcx, crate, NoStd) { + Some("core") + } else { + Some("std") + } +} From 266da35635519cd52a210ff98232e5691af49b28 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Aug 2026 15:02:50 +1000 Subject: [PATCH 0496/1309] Remove `regex!` macro It has a single call site. The `OnceLock` can also be replaced with `LazyLock`, which makes the code simpler. --- .../rustc_mir_dataflow/src/framework/graphviz.rs | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index b5f405a6a3008..a95becf70ce29 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use std::ffi::OsString; use std::path::PathBuf; -use std::sync::OnceLock; +use std::sync::LazyLock; use std::{io, ops, str}; use regex::Regex; @@ -694,13 +694,6 @@ where } } -macro_rules! regex { - ($re:literal $(,)?) => {{ - static RE: OnceLock = OnceLock::new(); - RE.get_or_init(|| Regex::new($re).unwrap()) - }}; -} - fn diff_pretty(new: T, old: T, ctxt: &C) -> String where T: DebugWithContext, @@ -709,7 +702,7 @@ where return String::new(); } - let re = regex!("\t?\u{001f}([+-])"); + static RE: LazyLock = LazyLock::new(|| Regex::new("\t?\u{001f}([+-])").unwrap()); let raw_diff = format!("{:#?}", DebugDiffWithAdapter { new, old, ctxt }); let raw_diff = dot::escape_html(&raw_diff); @@ -718,7 +711,7 @@ where let raw_diff = raw_diff.replace('\n', r#"
"#); let mut inside_font_tag = false; - let html_diff = re.replace_all(&raw_diff, |captures: ®ex::Captures<'_>| { + let html_diff = RE.replace_all(&raw_diff, |captures: ®ex::Captures<'_>| { let mut ret = String::new(); if inside_font_tag { ret.push_str(r#""#); From dfd1a7d44cba8d209845ee9188206a3c956cac49 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 18 Aug 2026 16:00:07 +1000 Subject: [PATCH 0497/1309] Streamline `write_node_label` The match on terminator kind has three almost identical arms for `Call`, `Yield`, and `InlineAsm`. The only difference is the label ("(on successful return)" vs. "(on yield resume)") and the third `CallReturnPlaces` argument to `apply_call_return_effect`. The latter is exactly computed by `Terminator::edges` (in the `AssignOnReturn` result), so this commit rewrites the code to use that. There is one slight behavioural change, an improvement: in the case where a `Call` doesn't return (i.e. `return_.is_empty()` is true) a "(on successful return)" row is no longer printed. --- .../src/framework/graphviz.rs | 80 ++++--------------- 1 file changed, 15 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index a95becf70ce29..af185e868fe9c 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -12,7 +12,7 @@ use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcMirKind}; use rustc_hir::find_attr; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ - self, BasicBlock, Body, Location, MirDumper, graphviz_safe_def_name, traversal, + self, BasicBlock, Body, Location, MirDumper, TerminatorEdges, graphviz_safe_def_name, traversal, }; use rustc_middle::ty::TyCtxt; use rustc_middle::ty::print::with_no_trimmed_paths; @@ -20,9 +20,7 @@ use rustc_span::def_id::DefId; use tracing::debug; use super::fmt::{DebugDiffWithAdapter, DebugWithAdapter, DebugWithContext}; -use super::{ - Analysis, CallReturnPlaces, Direction, Results, ResultsCursor, ResultsVisitor, visit_results, -}; +use super::{Analysis, Direction, Results, ResultsCursor, ResultsVisitor, visit_results}; /// Writes a DOT file containing the results of a dataflow analysis if the user requested it via /// `rustc_mir` attributes and `-Z dump-mir-dataflow`. The `Result` in and the `Results` out are @@ -355,68 +353,20 @@ where // FIXME: These should really be printed as part of each outgoing edge rather than the node // for the basic block itself. That way, we could display terminator-specific effects for // backward dataflow analyses as well as effects for `SwitchInt` terminators. - match terminator.kind { - mir::TerminatorKind::Call { destination, .. } => { - self.write_row(w, "", "(on successful return)", |this, w, fmt| { - let state_on_unwind = this.cursor.get().clone(); - this.cursor.apply_custom_effect(|analysis, state| { - analysis.apply_call_return_effect( - state, - block, - CallReturnPlaces::Call(destination), - ); - }); - - write!( - w, - r#"{diff}"#, - colspan = this.style.num_state_columns(), - fmt = fmt, - diff = diff_pretty( - this.cursor.get(), - &state_on_unwind, - this.cursor.analysis() - ), - ) - })?; - } - mir::TerminatorKind::Yield { resume_arg, .. } => { - self.write_row(w, "", "(on yield resume)", |this, w, fmt| { - let state_on_coroutine_drop = this.cursor.get().clone(); - this.cursor.apply_custom_effect(|analysis, state| { - analysis.apply_call_return_effect( - state, - block, - CallReturnPlaces::Yield(resume_arg), - ); - }); - - write!( - w, - r#"{diff}"#, - colspan = this.style.num_state_columns(), - fmt = fmt, - diff = diff_pretty( - this.cursor.get(), - &state_on_coroutine_drop, - this.cursor.analysis() - ), - ) - })?; - } + match terminator.edges() { + TerminatorEdges::AssignOnReturn { return_, place, .. } if !return_.is_empty() => { + let label = match place { + mir::CallReturnPlaces::Call(_) | mir::CallReturnPlaces::InlineAsm(_) => { + "(on successful return)" + } + mir::CallReturnPlaces::Yield(_) => "(on yield resume)", + }; - mir::TerminatorKind::InlineAsm { ref targets, ref operands, .. } - if !targets.is_empty() => - { - self.write_row(w, "", "(on successful return)", |this, w, fmt| { - let state_on_unwind = this.cursor.get().clone(); + self.write_row(w, "", label, |this, w, fmt| { + let state_before_effect = this.cursor.get().clone(); this.cursor.apply_custom_effect(|analysis, state| { - analysis.apply_call_return_effect( - state, - block, - CallReturnPlaces::InlineAsm(operands), - ); + analysis.apply_call_return_effect(state, block, place); }); write!( @@ -426,7 +376,7 @@ where fmt = fmt, diff = diff_pretty( this.cursor.get(), - &state_on_unwind, + &state_before_effect, this.cursor.analysis() ), ) @@ -434,7 +384,7 @@ where } _ => {} - }; + } write!(w, "")?; From ee2e94efbbab8e791fb678653c6aea768af0e39c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Sep 2026 20:21:52 +0200 Subject: [PATCH 0498/1309] better debugging for which env var we carry over from build-time to run-time --- src/tools/miri/cargo-miri/src/phases.rs | 29 +++++++++++++------------ 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/cargo-miri/src/phases.rs b/src/tools/miri/cargo-miri/src/phases.rs index 15ddc19aefffd..5b8f0d6ddab7c 100644 --- a/src/tools/miri/cargo-miri/src/phases.rs +++ b/src/tools/miri/cargo-miri/src/phases.rs @@ -530,10 +530,6 @@ pub fn phase_rustc(args: impl Iterator, phase: RustcPhase) { cmd.env("MIRI_BE_RUSTC", if target_crate { "target" } else { "host" }); // Run it. - if verbose > 0 { - eprintln!("[cargo-miri rustc] target_crate={target_crate} runnable_crate={runnable_crate}"); - } - debug_cmd("[cargo-miri rustc]", verbose, &cmd); exec(cmd); } @@ -582,16 +578,21 @@ pub fn phase_runner(mut binary_args: impl Iterator, phase: Runner if name == "CARGO_MAKEFLAGS" { continue; } - if let Some(old_val) = env::var_os(name) { - if *old_val == *val { - // This one did not actually change, no need to re-set it. - // (This keeps the `debug_cmd` below more manageable.) - continue; - } else if verbose > 0 { - eprintln!( - "[cargo-miri runner] Overwriting run-time env var {name:?}={old_val:?} with build-time value {val:?}" - ); - } + let old_val = env::var_os(name); + if old_val.as_ref() == Some(val) { + // This one did not actually change, no need to re-set it. + // (This keeps the `debug_cmd` below more manageable.) + continue; + } + if verbose > 0 { + eprintln!( + "[cargo-miri runner] Carrying over build-time env var {name:?}={val:?}{}", + if let Some(old_val) = old_val { + format!(", overwriting run-time value {old_val:?}") + } else { + format!("") + } + ); } cmd.env(name, val); } From 1df9314402beaea34b38dbe6fee85d834e751623 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Sep 2026 20:27:13 +0200 Subject: [PATCH 0499/1309] only preserve env vars cargo actually changes from build-time to run-time --- src/tools/miri/cargo-miri/src/util.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index 6d19830e71d44..162ddcb18bd5f 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -39,7 +39,15 @@ impl CrateRunInfo { /// Gather all the information we need. pub fn collect(args: impl Iterator, capture_stdin: bool) -> Self { let args = args.collect(); - let env = env::vars_os().collect(); + let env = env::vars_os() + .filter(|(var, _val)| { + // We only need to bother with env vars cargo actually sets. + // We try to avoid storing anything that may contain secrets. + var.to_str().is_some_and(|var| { + var == "OUT_DIR" || (var.starts_with("CARGO_") && !var.ends_with("_TOKEN")) + }) + }) + .collect(); let current_dir = env::current_dir().unwrap().into_os_string(); let mut stdin = Vec::new(); From a7543d01f62e05403dd4f41f2e36f59f95105d17 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Tue, 28 Jul 2026 09:41:40 -0400 Subject: [PATCH 0500/1309] add test --- .../x86-explicit-register-alias-diagnostic.rs | 51 +++++++++++++++++ ...licit-register-alias-diagnostic.x86.stderr | 56 +++++++++++++++++++ 2 files changed, 107 insertions(+) create mode 100644 tests/ui/asm/x86-explicit-register-alias-diagnostic.rs create mode 100644 tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr diff --git a/tests/ui/asm/x86-explicit-register-alias-diagnostic.rs b/tests/ui/asm/x86-explicit-register-alias-diagnostic.rs new file mode 100644 index 0000000000000..4a67827d3c84e --- /dev/null +++ b/tests/ui/asm/x86-explicit-register-alias-diagnostic.rs @@ -0,0 +1,51 @@ +// Check that inline assembly diagnostics use the explicit register name from the source. +// +// On 32-bit x86, vector registers 8 and higher are unavailable. Registers 16 through 31 +// share a canonical `zmm` representation, but diagnostics must still use the `xmm`, `ymm`, +// or `zmm` name that the user wrote. +// +// Regression test for . + +//@ add-minicore +//@ revisions: x86 x86_64 +//@[x86] compile-flags: --target i686-unknown-linux-gnu +//@[x86] needs-llvm-components: x86 +//@[x86] check-fail +//@[x86_64] compile-flags: --target x86_64-unknown-linux-gnu +//@[x86_64] needs-llvm-components: x86 +//@[x86_64] check-pass +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] + +extern crate minicore; +use minicore::*; + +fn main() { + unsafe { + // Register 15 is the last register with separate canonical representations. + asm!("", lateout("xmm15") _); + //[x86]~^ ERROR cannot use register `xmm15` + asm!("", lateout("ymm15") _); + //[x86]~^ ERROR cannot use register `ymm15` + asm!("", lateout("zmm15") _); + //[x86]~^ ERROR cannot use register `zmm15` + + // Register 16 is the first register whose aliases share the canonical `zmm` representation. + asm!("", lateout("xmm16") _); + //[x86]~^ ERROR cannot use register `xmm16` + asm!("", lateout("ymm16") _); + //[x86]~^ ERROR cannot use register `ymm16` + asm!("", lateout("zmm16") _); + //[x86]~^ ERROR cannot use register `zmm16` + + // Register 31 is the upper boundary of the affected register range. + asm!("", lateout("xmm31") _); + //[x86]~^ ERROR cannot use register `xmm31` + asm!("", lateout("ymm31") _); + //[x86]~^ ERROR cannot use register `ymm31` + asm!("", lateout("zmm31") _); + //[x86]~^ ERROR cannot use register `zmm31` + } +} diff --git a/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr b/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr new file mode 100644 index 0000000000000..0e35f09d8ba4b --- /dev/null +++ b/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr @@ -0,0 +1,56 @@ +error: cannot use register `xmm15`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:28:18 + | +LL | asm!("", lateout("xmm15") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `ymm15`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:30:18 + | +LL | asm!("", lateout("ymm15") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm15`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:32:18 + | +LL | asm!("", lateout("zmm15") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm16`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:36:18 + | +LL | asm!("", lateout("xmm16") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm16`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:38:18 + | +LL | asm!("", lateout("ymm16") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm16`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:40:18 + | +LL | asm!("", lateout("zmm16") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm31`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:44:18 + | +LL | asm!("", lateout("xmm31") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm31`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:46:18 + | +LL | asm!("", lateout("ymm31") _); + | ^^^^^^^^^^^^^^^^^^ + +error: cannot use register `zmm31`: register is only available on x86_64 + --> $DIR/x86-explicit-register-alias-diagnostic.rs:48:18 + | +LL | asm!("", lateout("zmm31") _); + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors + From 5a9eb1e1e8ac14eb7383883a12a8ef0840857a19 Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:56:39 -0400 Subject: [PATCH 0501/1309] preserve explicit register names in inline asm diagnostics --- compiler/rustc_ast_lowering/src/asm.rs | 43 ++++++++++--------- compiler/rustc_hir/src/hir.rs | 42 +++++++++++++++++- compiler/rustc_hir_typeck/src/inline_asm.rs | 13 +++--- compiler/rustc_mir_build/src/thir/cx/expr.rs | 17 +++++--- .../clippy/clippy_utils/src/hir_utils.rs | 8 ++-- tests/ui/asm/sparc/bad-reg.rs | 2 +- tests/ui/asm/sparc/bad-reg.sparc.stderr | 2 +- tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr | 2 +- ...licit-register-alias-diagnostic.x86.stderr | 8 ++-- 9 files changed, 92 insertions(+), 45 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/asm.rs b/compiler/rustc_ast_lowering/src/asm.rs index fd3a00d56fe0b..71bcdb0e27e8f 100644 --- a/compiler/rustc_ast_lowering/src/asm.rs +++ b/compiler/rustc_ast_lowering/src/asm.rs @@ -140,8 +140,8 @@ impl<'hir> LoweringContext<'_, 'hir> { .iter() .map(|(op, op_sp)| { let lower_reg = |®: &_| match reg { - InlineAsmRegOrRegClass::Reg(reg) => { - asm::InlineAsmRegOrRegClass::Reg(if let Some(asm_arch) = asm_arch { + InlineAsmRegOrRegClass::Reg(reg) => hir::InlineAsmRegOrRegClass::Reg { + reg: if let Some(asm_arch) = asm_arch { asm::InlineAsmReg::parse(asm_arch, reg).unwrap_or_else(|error| { self.dcx().emit_err(InvalidRegister { op_span: *op_sp, @@ -152,10 +152,11 @@ impl<'hir> LoweringContext<'_, 'hir> { }) } else { asm::InlineAsmReg::Err - }) - } + }, + source_name: Some(reg), + }, InlineAsmRegOrRegClass::RegClass(reg_class) => { - asm::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { + hir::InlineAsmRegOrRegClass::RegClass(if let Some(asm_arch) = asm_arch { asm::InlineAsmRegClass::parse(asm_arch, reg_class).unwrap_or_else( |supported_register_classes| { self.dcx().emit_err(InvalidRegisterClass { @@ -344,7 +345,7 @@ impl<'hir> LoweringContext<'_, 'hir> { } // Check for conflicts between explicit register operands. - if let asm::InlineAsmRegOrRegClass::Reg(reg) = reg { + if let hir::InlineAsmRegOrRegClass::Reg { reg, .. } = reg { let (input, output) = match op { hir::InlineAsmOperand::In { .. } => (true, false), @@ -393,24 +394,21 @@ impl<'hir> LoweringContext<'_, 'hir> { } _ => None, }; - let reg_str = |idx| -> &str { - // HIR asm doesn't preserve the original alias string of the explicit register, - // so we have to retrieve it from AST - let (op, _): &(InlineAsmOperand, Span) = &asm.operands[idx]; - if let Some(ast::InlineAsmRegOrRegClass::Reg(reg_sym)) = - op.reg() - { - reg_sym.as_str() - } else { - unreachable!("{op:?} is not a register operand"); - } - }; + let reg1_name = op + .reg() + .and_then(|reg| reg.source_name()) + .expect("{op:?} has no source register name"); + + let reg2_name = op2 + .reg() + .and_then(|reg| reg.source_name()) + .expect("{op2:?} has no source register name"); self.dcx().emit_err(RegisterConflict { op_span1: op_sp, op_span2: op_sp2, - reg1_name: reg_str(idx), - reg2_name: reg_str(idx2), + reg1_name: reg1_name.as_str(), + reg2_name: reg2_name.as_str(), in_out, }); } @@ -457,7 +455,10 @@ impl<'hir> LoweringContext<'_, 'hir> { if !output_used { operands.push(( hir::InlineAsmOperand::Out { - reg: asm::InlineAsmRegOrRegClass::Reg(clobber), + reg: hir::InlineAsmRegOrRegClass::Reg { + reg: clobber, + source_name: None, + }, late: true, expr: None, }, diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ee79680d7d1e9..7df199c8cea7b 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -30,7 +30,7 @@ use rustc_span::{ BytePos, DUMMY_SP, DesugaringKind, ErrorGuaranteed, Ident, LocalExpnId, Span, Spanned, Symbol, kw, sym, }; -use rustc_target::asm::InlineAsmRegOrRegClass; +use rustc_target::asm; use tracing::debug; use crate::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; @@ -3611,6 +3611,44 @@ pub enum TyKind<'hir, Unambig = ()> { Infer(Unambig), } +/// Stores explicit register name from source +/// for diagnostics only. +#[derive(Debug, Clone, Copy, StableHash)] +pub enum InlineAsmRegOrRegClass { + Reg { reg: asm::InlineAsmReg, source_name: Option }, + RegClass(asm::InlineAsmRegClass), +} + +impl InlineAsmRegOrRegClass { + // For `rustc_mir_build` and `clippy_utils` + pub fn as_target(self) -> asm::InlineAsmRegOrRegClass { + match self { + Self::Reg { reg, .. } => asm::InlineAsmRegOrRegClass::Reg(reg), + Self::RegClass(reg_class) => asm::InlineAsmRegOrRegClass::RegClass(reg_class), + } + } + + // For `rustc_ast_lowering` + pub fn reg_class(self) -> asm::InlineAsmRegClass { + self.as_target().reg_class() + } + + // For `rustc_ast_lowering` + pub fn source_name(self) -> Option { + match self { + Self::Reg { source_name, .. } => source_name, + Self::RegClass(_) => None, + } + } +} + +// For `rustc_hir_pretty` +impl fmt::Display for InlineAsmRegOrRegClass { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + self.as_target().fmt(f) + } +} + #[derive(Debug, Clone, Copy, StableHash)] pub enum InlineAsmOperand<'hir> { In { @@ -3665,7 +3703,7 @@ impl<'hir> InlineAsmOperand<'hir> { pub fn is_clobber(&self) -> bool { matches!( self, - InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg(_), late: _, expr: None } + InlineAsmOperand::Out { reg: InlineAsmRegOrRegClass::Reg { .. }, expr: None, .. } ) } } diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 2b1d9ed038b87..4790159f4eca7 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -12,8 +12,7 @@ use rustc_middle::ty::{ use rustc_span::def_id::LocalDefId; use rustc_span::{ErrorGuaranteed, Span, Symbol, bug, sym}; use rustc_target::asm::{ - InlineAsmReg, InlineAsmRegClass, InlineAsmRegOrRegClass, InlineAsmSize, InlineAsmType, - ModifierInfo, + InlineAsmReg, InlineAsmRegClass, InlineAsmSize, InlineAsmType, ModifierInfo, }; use rustc_trait_selection::infer::InferCtxtExt; @@ -190,7 +189,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { fn check_asm_operand_type( &self, idx: usize, - reg: InlineAsmRegOrRegClass, + reg: hir::InlineAsmRegOrRegClass, expr: &'tcx hir::Expr<'tcx>, template: &[InlineAsmTemplatePiece], is_input: bool, @@ -476,7 +475,7 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { if let Some(reg) = op.reg() { // Some explicit registers cannot be used depending on the // target. Reject those here. - if let InlineAsmRegOrRegClass::Reg(reg) = reg { + if let hir::InlineAsmRegOrRegClass::Reg { reg, source_name } = reg { if let InlineAsmReg::Err = reg { // `validate` will panic on `Err`, as an error must // already have been reported. @@ -489,7 +488,11 @@ impl<'a, 'tcx> InlineAsmCtxt<'a, 'tcx> { &self.tcx().sess.target, op.is_clobber(), ) { - let msg = format!("cannot use register `{}`: {}", reg.name(), msg); + let reg_name = match source_name { + Some(ref reg_name) => reg_name.as_str(), + None => ®.name(), + }; + let msg = format!("cannot use register `{reg_name}`: {msg}"); self.fcx.dcx().span_err(op_sp, msg); continue; } diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index feef8d24bd9ca..5bad7bec531c9 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -827,22 +827,27 @@ impl<'tcx> ThirBuildCx<'tcx> { .operands .iter() .map(|(op, _op_sp)| match *op { - hir::InlineAsmOperand::In { reg, expr } => { - InlineAsmOperand::In { reg, expr: self.mirror_expr(expr) } - } + hir::InlineAsmOperand::In { reg, expr } => InlineAsmOperand::In { + reg: reg.as_target(), + expr: self.mirror_expr(expr), + }, hir::InlineAsmOperand::Out { reg, late, ref expr } => { InlineAsmOperand::Out { - reg, + reg: reg.as_target(), late, expr: expr.map(|expr| self.mirror_expr(expr)), } } hir::InlineAsmOperand::InOut { reg, late, expr } => { - InlineAsmOperand::InOut { reg, late, expr: self.mirror_expr(expr) } + InlineAsmOperand::InOut { + reg: reg.as_target(), + late, + expr: self.mirror_expr(expr), + } } hir::InlineAsmOperand::SplitInOut { reg, late, in_expr, ref out_expr } => { InlineAsmOperand::SplitInOut { - reg, + reg: reg.as_target(), late, in_expr: self.mirror_expr(in_expr), out_expr: out_expr.map(|expr| self.mirror_expr(expr)), diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index cf7777d037d9b..0d0b1efeca00b 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -1275,18 +1275,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for (op, _op_sp) in asm.operands { match op { InlineAsmOperand::In { reg, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); self.hash_expr(expr); }, InlineAsmOperand::Out { reg, late, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); if let Some(expr) = expr { self.hash_expr(expr); } }, InlineAsmOperand::InOut { reg, late, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); self.hash_expr(expr); }, @@ -1296,7 +1296,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { in_expr, out_expr, } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); self.hash_expr(in_expr); if let Some(out_expr) = out_expr { diff --git a/tests/ui/asm/sparc/bad-reg.rs b/tests/ui/asm/sparc/bad-reg.rs index 8cac5eb6b4ad0..74c31279656d1 100644 --- a/tests/ui/asm/sparc/bad-reg.rs +++ b/tests/ui/asm/sparc/bad-reg.rs @@ -28,7 +28,7 @@ fn f() { asm!("", out("g3") _); asm!("", out("g4") _); asm!("", out("g5") _); - //[sparc,sparcv8plus]~^ ERROR cannot use register `r5`: g5 is reserved for system on SPARC32 + //[sparc,sparcv8plus]~^ ERROR cannot use register `g5`: g5 is reserved for system on SPARC32 asm!("", out("g6") _); //~^ ERROR invalid register `g6`: reserved for system and cannot be used as an operand for inline asm asm!("", out("g7") _); diff --git a/tests/ui/asm/sparc/bad-reg.sparc.stderr b/tests/ui/asm/sparc/bad-reg.sparc.stderr index 06b607ff007ac..ac2ee667d4eea 100644 --- a/tests/ui/asm/sparc/bad-reg.sparc.stderr +++ b/tests/ui/asm/sparc/bad-reg.sparc.stderr @@ -64,7 +64,7 @@ error: register class `yreg` can only be used as a clobber, not as an input or o LL | asm!("/* {} */", out(yreg) _); | ^^^^^^^^^^^ -error: cannot use register `r5`: g5 is reserved for system on SPARC32 +error: cannot use register `g5`: g5 is reserved for system on SPARC32 --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("g5") _); diff --git a/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr index e0580ad3232f5..be931f9a2aad4 100644 --- a/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr +++ b/tests/ui/asm/sparc/bad-reg.sparcv8plus.stderr @@ -64,7 +64,7 @@ error: register class `yreg` can only be used as a clobber, not as an input or o LL | asm!("/* {} */", out(yreg) _); | ^^^^^^^^^^^ -error: cannot use register `r5`: g5 is reserved for system on SPARC32 +error: cannot use register `g5`: g5 is reserved for system on SPARC32 --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("g5") _); diff --git a/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr b/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr index 0e35f09d8ba4b..81718243841aa 100644 --- a/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr +++ b/tests/ui/asm/x86-explicit-register-alias-diagnostic.x86.stderr @@ -16,13 +16,13 @@ error: cannot use register `zmm15`: register is only available on x86_64 LL | asm!("", lateout("zmm15") _); | ^^^^^^^^^^^^^^^^^^ -error: cannot use register `zmm16`: register is only available on x86_64 +error: cannot use register `xmm16`: register is only available on x86_64 --> $DIR/x86-explicit-register-alias-diagnostic.rs:36:18 | LL | asm!("", lateout("xmm16") _); | ^^^^^^^^^^^^^^^^^^ -error: cannot use register `zmm16`: register is only available on x86_64 +error: cannot use register `ymm16`: register is only available on x86_64 --> $DIR/x86-explicit-register-alias-diagnostic.rs:38:18 | LL | asm!("", lateout("ymm16") _); @@ -34,13 +34,13 @@ error: cannot use register `zmm16`: register is only available on x86_64 LL | asm!("", lateout("zmm16") _); | ^^^^^^^^^^^^^^^^^^ -error: cannot use register `zmm31`: register is only available on x86_64 +error: cannot use register `xmm31`: register is only available on x86_64 --> $DIR/x86-explicit-register-alias-diagnostic.rs:44:18 | LL | asm!("", lateout("xmm31") _); | ^^^^^^^^^^^^^^^^^^ -error: cannot use register `zmm31`: register is only available on x86_64 +error: cannot use register `ymm31`: register is only available on x86_64 --> $DIR/x86-explicit-register-alias-diagnostic.rs:46:18 | LL | asm!("", lateout("ymm31") _); From 10b09650428769debf2874873fc904fba054b08f Mon Sep 17 00:00:00 2001 From: qaijuang <237468078+qaijuang@users.noreply.github.com> Date: Tue, 4 Aug 2026 14:56:39 -0400 Subject: [PATCH 0502/1309] preserve explicit register names in inline asm diagnostics --- clippy_utils/src/hir_utils.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index cf7777d037d9b..0d0b1efeca00b 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -1275,18 +1275,18 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { for (op, _op_sp) in asm.operands { match op { InlineAsmOperand::In { reg, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); self.hash_expr(expr); }, InlineAsmOperand::Out { reg, late, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); if let Some(expr) = expr { self.hash_expr(expr); } }, InlineAsmOperand::InOut { reg, late, expr } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); self.hash_expr(expr); }, @@ -1296,7 +1296,7 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { in_expr, out_expr, } => { - reg.hash(&mut self.s); + reg.as_target().hash(&mut self.s); late.hash(&mut self.s); self.hash_expr(in_expr); if let Some(out_expr) = out_expr { From df1b5c96717c5839af6c7fa314b55c046043dbfa Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:51 +0100 Subject: [PATCH 0503/1309] `f16b` Implementation and documentation --- compiler/rustc_attr_ir/src/lang_items.rs | 1 + compiler/rustc_feature/src/builtin_attrs.rs | 5 + compiler/rustc_feature/src/unstable.rs | 4 + .../rustc_hir_analysis/src/check/check.rs | 2 + compiler/rustc_interface/src/util.rs | 4 + compiler/rustc_middle/src/ty/layout.rs | 5 + compiler/rustc_span/src/symbol.rs | 3 + compiler/rustc_ty_utils/src/layout.rs | 10 +- library/core/Cargo.toml | 1 + library/core/src/num/bfloat.rs | 183 ++++++++++++++++++ library/core/src/num/mod.rs | 3 + .../src/language-features/f16b.md | 11 ++ 12 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 library/core/src/num/bfloat.rs create mode 100644 src/doc/unstable-book/src/language-features/f16b.md diff --git a/compiler/rustc_attr_ir/src/lang_items.rs b/compiler/rustc_attr_ir/src/lang_items.rs index c1ad05dc8e4a8..60890f7799290 100644 --- a/compiler/rustc_attr_ir/src/lang_items.rs +++ b/compiler/rustc_attr_ir/src/lang_items.rs @@ -281,6 +281,7 @@ language_item_table! { PartialEq, sym::eq, eq_trait, Target::Trait, GenericRequirement::Exact(1); PartialOrd, sym::partial_ord, partial_ord_trait, Target::Trait, GenericRequirement::Exact(1); CVoid, sym::c_void, c_void, Target::Enum, GenericRequirement::None; + F16B, sym::f16b, f16b, Target::Struct, GenericRequirement::Exact(0); Type, sym::type_info, type_struct, Target::Struct, GenericRequirement::None; TypeGeneric, sym::type_info_generic, type_generic, Target::Enum, GenericRequirement::None; diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs index bb35a3281ccdc..0f96eb7f158ed 100644 --- a/compiler/rustc_feature/src/builtin_attrs.rs +++ b/compiler/rustc_feature/src/builtin_attrs.rs @@ -40,6 +40,11 @@ const GATED_CFGS: &[GatedCfg] = &[ sym::cfg_target_has_reliable_f16_f128, Features::cfg_target_has_reliable_f16_f128, ), + ( + sym::target_has_reliable_f16b, + sym::cfg_target_has_reliable_f16b, + Features::cfg_target_has_reliable_f16b, + ), ( sym::target_has_reliable_f128, sym::cfg_target_has_reliable_f16_f128, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a7138a88ee399..94e3b77c6b575 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -227,6 +227,8 @@ declare_features! ( (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None), /// Allows checking whether or not the backend correctly supports unstable float types. (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), + /// Allows checking whether or not the backend correctly supports the unstable `f16b` type. + (internal, cfg_target_has_reliable_f16b, "CURRENT_RUSTC_VERSION", None), /// Allows checking whether or not the target might have thread support. (internal, cfg_target_has_threads, "1.99.0", None), /// Allows identifying the `compiler_builtins` crate. @@ -520,6 +522,8 @@ declare_features! ( (unstable, f128, "1.78.0", Some(116909)), /// Allow using 16-bit (half precision) floating point numbers. (unstable, f16, "1.78.0", Some(116909)), + /// Allow using bfloat16 floating point numbers. + (unstable, f16b, "CURRENT_RUSTC_VERSION", Some(160630)), /// Allows the use of `#[ffi_const]` on foreign functions. (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 705bb780a3ecf..7cebf6dd16711 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1592,6 +1592,8 @@ fn check_scalable_vector(tcx: TyCtxt<'_>, span: Span, def_id: LocalDefId, scalab // bools match element_ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::Bool => (), + // We need to treat a `bfloat` (`f16b`) as a primitive scalar + ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::F16B) => (), _ => { let mut err = tcx.dcx().struct_span_err( span, diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 87b2bb94cd4f9..5c6aef8676716 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -74,6 +74,9 @@ pub(crate) fn add_configuration( if target_config.has_reliable_f16_math { cfg.insert((sym::target_has_reliable_f16_math, None)); } + if target_config.has_reliable_f16b { + cfg.insert((sym::target_has_reliable_f16b, None)); + } if target_config.has_reliable_f128 { cfg.insert((sym::target_has_reliable_f128, None)); } @@ -419,6 +422,7 @@ impl CodegenBackend for DummyCodegenBackend { internal_target_features, has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 22fbb306849da..8f2bb97e12a8f 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -137,6 +137,11 @@ impl abi::Float { use abi::Float::*; match *self { F16 => tcx.types.f16, + F16B => Ty::new_adt( + tcx, + tcx.adt_def(tcx.require_lang_item(LangItem::F16B, DUMMY_SP)), + ty::List::empty(), + ), F32 => tcx.types.f32, F64 => tcx.types.f64, F128 => tcx.types.f128, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 39d9d2b7b05ce..098b6595f166e 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -621,6 +621,7 @@ symbols! { cfg_target_has_atomic, cfg_target_has_atomic_equal_alignment, cfg_target_has_reliable_f16_f128, + cfg_target_has_reliable_f16b, cfg_target_has_threads, cfg_target_object_format, cfg_target_thread_local, @@ -958,6 +959,7 @@ symbols! { external_doc, f16, f16_nan, + f16b, f16c_target_feature, f32, f32_nan, @@ -2125,6 +2127,7 @@ symbols! { target_has_atomic_primitive_alignment, target_has_reliable_f16, target_has_reliable_f16_math, + target_has_reliable_f16b, target_has_reliable_f128, target_has_reliable_f128_math, target_has_threads, diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index fe093adcbf3f4..dee4b785e418d 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -11,6 +11,7 @@ use rustc_abi::{ }; use rustc_hashes::Hash64; use rustc_hir as hir; +use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::find_attr; use rustc_index::{Idx as _, IndexVec}; use rustc_middle::query::Providers; @@ -737,7 +738,7 @@ fn layout_of_uncached<'tcx>( .is_sized(tcx, typing_env) }); - let layout = cx + let mut layout = cx .calc .layout_of_struct_or_enum( &def.repr(), @@ -804,6 +805,13 @@ fn layout_of_uncached<'tcx>( } } + if tcx.is_lang_item(def.did(), LangItem::F16B) { + let bfloat = scalar_unit(Primitive::Float(abi::Float::F16B)); + assert_eq!(layout.size, abi::Float::F16B.size()); + layout.align = abi::Float::F16B.align(cx); + layout.backend_repr = BackendRepr::Scalar(bfloat); + } + tcx.mk_layout(layout) } diff --git a/library/core/Cargo.toml b/library/core/Cargo.toml index 3f5f9f454a99d..d8f4ec0528dee 100644 --- a/library/core/Cargo.toml +++ b/library/core/Cargo.toml @@ -36,6 +36,7 @@ check-cfg = [ # gate tests. 'cfg(target_has_reliable_f16)', 'cfg(target_has_reliable_f16_math)', + 'cfg(target_has_reliable_f16b)', 'cfg(target_has_reliable_f128)', 'cfg(target_has_reliable_f128_math)', # Prevents use of a static variable for providing platform specific RawOsError diff --git a/library/core/src/num/bfloat.rs b/library/core/src/num/bfloat.rs new file mode 100644 index 0000000000000..4937dd8448c60 --- /dev/null +++ b/library/core/src/num/bfloat.rs @@ -0,0 +1,183 @@ +//! The 16-bit brain floating-point type. + +#![unstable(feature = "f16b", issue = "160630")] + +use crate::{fmt, mem}; + +/// A 16-bit brain floating-point value. +/// +/// This type stores values using the bfloat16 encoding. It deliberately +/// exposes only raw-bit construction, comparison, formatting, and lossless +/// widening to [`f32`]. +/// +/// The 16-bit brain floating-point intends to preserve the dynamic range of +/// a 32-bit floating-point value while using half the storage. It does +/// this by using 8 bits for the exponent, the same as `f32`, but only +/// using 7 bits for the mantissa. See [Wikipedia on bfloat16][wikipedia] for +/// more information. +/// +/// [wikipedia]: https://en.wikipedia.org/wiki/Bfloat16_floating-point_format +#[lang = "f16b"] +#[doc(alias = "bf16")] // what hardware often names it +#[doc(alias = "bfloat")] // LLVM's name +#[doc(alias = "bfloat16")] // Wikipedia's name +#[doc(alias = "bfloat16_t")] // The C++ `stdfloat` name +#[allow(non_camel_case_types)] +#[repr(transparent)] +#[unstable(feature = "f16b", issue = "160630")] +pub struct f16b(u16); + +#[doc(test(attr( + feature(cfg_target_has_reliable_f16b), + allow(internal_features, unused_features) +)))] +impl f16b { + /// Raw transmutation from `u16`. + /// + /// This is currently identical to `transmute::(v)` on all platforms. + /// It turns out this is incredibly portable, for two reasons: + /// + /// * Floats and Ints have the same endianness on all supported platforms. + /// * IEEE 754 very precisely specifies the bit layout of floats. + /// + /// However there is one caveat: prior to the 2008 version of IEEE 754, how + /// to interpret the NaN signaling bit wasn't actually specified. Most platforms + /// (notably x86 and ARM) picked the interpretation that was ultimately + /// standardized in 2008, but some didn't (notably MIPS). As a result, all + /// signaling NaNs on MIPS are quiet NaNs on x86, and vice-versa. + /// + /// Rather than trying to preserve signaling-ness cross-platform, this + /// implementation favors preserving the exact bits. This means that + /// any payloads encoded in NaNs will be preserved even if the result of + /// this method is sent over the network from an x86 machine to a MIPS one. + /// + /// If the results of this method are only manipulated by the same + /// architecture that produced them, then there is no portability concern. + /// + /// If the input isn't NaN, then there is no portability concern. + /// + /// If you don't care about signalingness (very likely), then there is no + /// portability concern. + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ```no_run + /// #![feature(f16b)] + /// # #[cfg(target_has_reliable_f16b)] { + /// use core::num::f16b; + /// + /// let v = f16b::from_bits(0x4148); + /// assert_eq!(f32::from(v), 12.5); + /// # } + /// ``` + #[inline] + #[must_use] + #[unstable(feature = "f16b", issue = "160630")] + pub const fn from_bits(bits: u16) -> Self { + // SAFETY: `f16b` and `u16` have the same size, and every bit pattern is valid. + unsafe { mem::transmute(bits) } + } + + /// Raw transmutation to `u16`. + /// + /// This is currently identical to `transmute::(self)` on all platforms. + /// + /// See [`from_bits`](#method.from_bits) for some discussion of the + /// portability of this operation (there are almost no issues). + /// + /// Note that this function is distinct from `as` casting, which attempts to + /// preserve the *numeric* value, and not the bitwise value. + /// + /// ```no_run + /// #![feature(f16b)] + /// # #[cfg(target_has_reliable_f16b)] { + /// use core::num::f16b; + /// + /// assert_eq!(f16b::from_bits(0x4148).to_bits(), 0x4148); + /// # } + /// ``` + #[inline] + #[unstable(feature = "f16b", issue = "160630")] + #[must_use = "this returns the result of the operation, without modifying the original"] + pub const fn to_bits(self) -> u16 { + // SAFETY: `f16b` and `u16` have the same size, and every bit pattern is valid. + unsafe { mem::transmute(self) } + } +} + +// FIXME(f16b) - This should be a `#[rustc_intrinsic]` using LLVM's `fpext` +// with this implementation constituting the fallback. +#[inline] +const fn widen(value: f16b) -> f32 { + f32::from_bits((value.to_bits() as u32) << 16) +} + +#[unstable(feature = "f16b", issue = "160630")] +impl Copy for f16b {} + +#[unstable(feature = "f16b", issue = "160630")] +impl Clone for f16b { + #[inline] + fn clone(&self) -> Self { + *self + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl Default for f16b { + #[inline] + fn default() -> Self { + Self::from_bits(0) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl PartialEq for f16b { + #[inline] + fn eq(&self, other: &Self) -> bool { + widen(*self).eq(&widen(*other)) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl PartialOrd for f16b { + #[inline] + fn partial_cmp(&self, other: &Self) -> Option { + widen(*self).partial_cmp(&widen(*other)) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl From for f32 { + #[inline] + fn from(value: f16b) -> Self { + widen(value) + } +} + +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::Debug for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::Debug::fmt(&widen(*self), formatter) + } +} + +#[cfg(not(no_fp_fmt_parse))] +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::LowerExp for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::LowerExp::fmt(&widen(*self), formatter) + } +} + +#[cfg(not(no_fp_fmt_parse))] +#[unstable(feature = "f16b", issue = "160630")] +impl fmt::UpperExp for f16b { + #[inline] + fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result { + fmt::UpperExp::fmt(&widen(*self), formatter) + } +} diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index db41d23770477..f5c7c853ef590 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -43,6 +43,7 @@ mod int_macros; // import int_impl! #[macro_use] mod uint_macros; // import uint_impl! +mod bfloat; mod complex; mod error; #[cfg(not(no_fp_fmt_parse))] @@ -56,6 +57,8 @@ mod wrapping; #[doc(hidden)] pub mod niche_types; +#[unstable(feature = "f16b", issue = "160630")] +pub use bfloat::f16b; #[unstable(feature = "complex_numbers", issue = "154023")] pub use complex::Complex; #[stable(feature = "int_error_matching", since = "1.55.0")] diff --git a/src/doc/unstable-book/src/language-features/f16b.md b/src/doc/unstable-book/src/language-features/f16b.md new file mode 100644 index 0000000000000..c18289921e032 --- /dev/null +++ b/src/doc/unstable-book/src/language-features/f16b.md @@ -0,0 +1,11 @@ +# `f16b` + +The tracking issue for this feature is: [#160630] + +[#160630]: https://github.com/rust-lang/rust/issues/160630 + +--- + +Enable the `core::num::f16b` type for values stored in the bfloat16 format. + +`f16b` is a nominal library type, not a primitive floating-point type: it has no literal suffix, arithmetic operators, or numeric `as` casts. A compiler lang item connects its layout to the chosen backend's representation. From cdde2f00b571b6f84a07cdc1c5d1a27335657c6c Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:51 +0100 Subject: [PATCH 0504/1309] Add `F16B` to `Float` enum & wireup trivial matches --- compiler/rustc_abi/src/layout/ty.rs | 2 +- compiler/rustc_abi/src/lib.rs | 8 +++++++- compiler/rustc_codegen_llvm/src/va_arg.rs | 6 +++++- compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 3 +++ compiler/rustc_codegen_ssa/src/traits/type_.rs | 2 ++ compiler/rustc_public/src/abi.rs | 3 ++- compiler/rustc_public/src/unstable/convert/stable/abi.rs | 1 + compiler/rustc_target/src/callconv/mips64.rs | 1 + compiler/rustc_target/src/callconv/sparc64.rs | 1 + 9 files changed, 23 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index 5033f887a60f9..e51255dc5963f 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -342,7 +342,7 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { Primitive::Float(float @ (Float::F16 | Float::F32 | Float::F64 | Float::F128)) => { Some(Numeric::Float(float)) } - Primitive::Pointer(..) => None, + Primitive::Pointer(..) | Primitive::Float(Float::F16B) => None, } } diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b056fdc73d40b..f10f9990debb4 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1420,6 +1420,10 @@ impl Integer { #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum Float { F16, + /// `f16b`. This is not a builtin type in Rust (it is exposed as a lang item), + /// but it is a builtin type in LLVM so needs to be explicitly represented + /// in the backend. + F16B, F32, F64, F128, @@ -1431,6 +1435,7 @@ impl Float { match self { F16 => Size::from_bits(16), + F16B => Size::from_bits(16), F32 => Size::from_bits(32), F64 => Size::from_bits(64), F128 => Size::from_bits(128), @@ -1442,7 +1447,7 @@ impl Float { let dl = cx.data_layout(); AbiAlign::new(match self { - F16 => dl.f16_align, + F16 | F16B => dl.f16_align, F32 => dl.f32_align, F64 => dl.f64_align, F128 => dl.f128_align, @@ -1454,6 +1459,7 @@ impl Float { match self { F16 => "f16", + F16B => "f16b", F32 => "f32", F64 => "f64", F128 => "f128", diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index ca57bee3e6271..e7883871f57e8 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -95,7 +95,7 @@ fn get_param_type_alignment<'ll, 'tcx>( Integer::I128 => return Align::EIGHT, }, Primitive::Float(float) => match float { - Float::F16 | Float::F32 => unreachable!(), + Float::F16 | Float::F16B | Float::F32 => unreachable!(), Float::F64 => { /* fall through */ } Float::F128 => return Align::from_bytes(16).unwrap(), }, @@ -481,7 +481,11 @@ fn emit_s390x_va_arg<'ll, 'tcx>( Primitive::Float(Float::F16 | Float::F32 | Float::F64) => true, Primitive::Float(Float::F128) => false, Primitive::Int(_, _) | Primitive::Pointer(_) => false, + Primitive::Float(Float::F16B) => { + bug!("`f16b` use in varadics unsupported on s390x") + } }, + _ => false, } }; diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index ea58b1cd3c53c..3162463d222ee 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -508,6 +508,9 @@ fn wasm_primitive(primitive: Primitive, ptr_type: &'static str) -> &'static str Integer::I128 => "i64, i64", }, Primitive::Float(float) => match float { + // This could probably use an f32 for WASM however has not been + // verified so leaving as a `bug!(...)` for now. + Float::F16B => bug!("`f16b` unsupported on wasm"), Float::F16 | Float::F32 => "f32", Float::F64 => "f64", Float::F128 => "i64, i64", diff --git a/compiler/rustc_codegen_ssa/src/traits/type_.rs b/compiler/rustc_codegen_ssa/src/traits/type_.rs index 1b70d38dc9e85..986481e7f132f 100644 --- a/compiler/rustc_codegen_ssa/src/traits/type_.rs +++ b/compiler/rustc_codegen_ssa/src/traits/type_.rs @@ -18,6 +18,7 @@ pub trait BaseTypeCodegenMethods: BackendTypes { fn type_isize(&self) -> Self::Type; fn type_f16(&self) -> Self::Type; + fn type_f16b(&self) -> Self::Type; fn type_f32(&self) -> Self::Type; fn type_f64(&self) -> Self::Type; fn type_f128(&self) -> Self::Type; @@ -67,6 +68,7 @@ pub trait DerivedTypeCodegenMethods<'tcx>: use Float::*; match f { F16 => self.type_f16(), + F16B => self.type_f16b(), F32 => self.type_f32(), F64 => self.type_f64(), F128 => self.type_f128(), diff --git a/compiler/rustc_public/src/abi.rs b/compiler/rustc_public/src/abi.rs index b760ed98c7111..67d609c780c42 100644 --- a/compiler/rustc_public/src/abi.rs +++ b/compiler/rustc_public/src/abi.rs @@ -496,6 +496,7 @@ pub enum IntegerLength { #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Serialize)] pub enum FloatLength { F16, + F16B, F32, F64, F128, @@ -516,7 +517,7 @@ impl IntegerLength { impl FloatLength { pub fn bits(self) -> usize { match self { - FloatLength::F16 => 16, + FloatLength::F16 | FloatLength::F16B => 16, FloatLength::F32 => 32, FloatLength::F64 => 64, FloatLength::F128 => 128, diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index 766c522958db7..3c268a6dd23a4 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -463,6 +463,7 @@ impl<'tcx> Stable<'tcx> for rustc_abi::Float { fn stable(&self, _: &mut Tables<'_, BridgeTys>, _: &CompilerCtxt<'_, BridgeTys>) -> Self::T { match self { rustc_abi::Float::F16 => FloatLength::F16, + rustc_abi::Float::F16B => FloatLength::F16B, rustc_abi::Float::F32 => FloatLength::F32, rustc_abi::Float::F64 => FloatLength::F64, rustc_abi::Float::F128 => FloatLength::F128, diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 8002f98507ba8..0e3ccf33c3ffe 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -31,6 +31,7 @@ where match float { // C does not have the f16 type Float::F16 => None, + Float::F16B => unreachable!("`f16b` unsupported on mips64"), Float::F32 => Some(Reg::f32()), Float::F64 => Some(Reg::f64()), Float::F128 => Some(Reg::f128()), diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs index bfaa3f3cb19c8..abef388ef2e12 100644 --- a/compiler/rustc_target/src/callconv/sparc64.rs +++ b/compiler/rustc_target/src/callconv/sparc64.rs @@ -58,6 +58,7 @@ fn classify<'a, Ty, C>( Float::F16 => { // Match LLVM by passing `f16` in integer registers. } + Float::F16B => unreachable!("`f16b` unsupported on sparc64"), } } else { /* pass unaligned floats in integer registers */ From c56a9917d80ad618d18888b14b55895a6838cd66 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:52 +0100 Subject: [PATCH 0505/1309] Wire up f16b in backends --- compiler/rustc_codegen_cranelift/src/common.rs | 1 + compiler/rustc_codegen_cranelift/src/lib.rs | 1 + compiler/rustc_codegen_gcc/src/base.rs | 2 ++ compiler/rustc_codegen_gcc/src/context.rs | 3 +++ compiler/rustc_codegen_gcc/src/lib.rs | 2 ++ compiler/rustc_codegen_gcc/src/type_.rs | 8 ++++++++ compiler/rustc_codegen_llvm/src/abi.rs | 1 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 3 +++ compiler/rustc_codegen_llvm/src/llvm_util.rs | 16 ++++++++++++++++ compiler/rustc_codegen_llvm/src/type_.rs | 4 ++++ compiler/rustc_codegen_ssa/src/lib.rs | 3 +++ compiler/rustc_codegen_ssa/src/traits/backend.rs | 1 + compiler/rustc_session/src/config/cfg.rs | 1 + src/tools/miri/src/bin/miri.rs | 1 + 14 files changed, 47 insertions(+) diff --git a/compiler/rustc_codegen_cranelift/src/common.rs b/compiler/rustc_codegen_cranelift/src/common.rs index d31c8fc810b2c..30bd2f28af53f 100644 --- a/compiler/rustc_codegen_cranelift/src/common.rs +++ b/compiler/rustc_codegen_cranelift/src/common.rs @@ -35,6 +35,7 @@ pub(crate) fn scalar_to_clif_type(tcx: TyCtxt<'_>, scalar: Scalar) -> Type { }, Primitive::Float(float) => match float { Float::F16 => types::F16, + Float::F16B => bug!("f16b is not supported by the Cranelift codegen backend"), Float::F32 => types::F32, Float::F64 => types::F64, Float::F128 => types::F128, diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index d4773e8199aed..6629cc834bbd6 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -196,6 +196,7 @@ impl CodegenBackend for CraneliftCodegenBackend { // available in Cranelift. has_reliable_f16: has_reliable_f16_f128, has_reliable_f16_math: has_reliable_f16_f128, + has_reliable_f16b: false, has_reliable_f128: has_reliable_f16_f128, has_reliable_f128_math, } diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 101af0bb0bff1..498ea4b45a8f8 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -214,6 +214,7 @@ pub fn compile_codegen_unit( // -fsyntax-only), forbid the compilation when get_target_info() is called on a // context. let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16); + let f16b_type_supported = target_info.supports_target_dependent_type(CType::BFloat16); let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32); let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64); let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128); @@ -225,6 +226,7 @@ pub fn compile_codegen_unit( tcx, u128_type_supported, f16_type_supported, + f16b_type_supported, f32_type_supported, f64_type_supported, f128_type_supported, diff --git a/compiler/rustc_codegen_gcc/src/context.rs b/compiler/rustc_codegen_gcc/src/context.rs index 38e0e5f329f76..a41255be9e1ea 100644 --- a/compiler/rustc_codegen_gcc/src/context.rs +++ b/compiler/rustc_codegen_gcc/src/context.rs @@ -72,6 +72,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub supports_128bit_integers: bool, pub supports_f16_type: bool, + pub supports_f16b_type: bool, pub supports_f32_type: bool, pub supports_f64_type: bool, pub supports_f128_type: bool, @@ -140,6 +141,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { tcx: TyCtxt<'tcx>, supports_128bit_integers: bool, supports_f16_type: bool, + supports_f16b_type: bool, supports_f32_type: bool, supports_f64_type: bool, supports_f128_type: bool, @@ -276,6 +278,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_128bit_integers, supports_f16_type, + supports_f16b_type, supports_f32_type, supports_f64_type, supports_f128_type, diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index d7a3ef3b4a6c5..79802a670a3f0 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -503,6 +503,7 @@ fn target_config(sess: &EarlySession, target_info: &SharedTargetInfo) -> TargetC ); let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16); + let has_reliable_f16b = target_info.supports_target_dependent_type(CType::BFloat16); let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128); TargetConfig { @@ -510,6 +511,7 @@ fn target_config(sess: &EarlySession, target_info: &SharedTargetInfo) -> TargetC // There are no known bugs with GCC support for f16 or f128 has_reliable_f16, has_reliable_f16_math: has_reliable_f16, + has_reliable_f16b, has_reliable_f128, has_reliable_f128_math: has_reliable_f128, } diff --git a/compiler/rustc_codegen_gcc/src/type_.rs b/compiler/rustc_codegen_gcc/src/type_.rs index 27b0d2079e63e..1d8582fe337ad 100644 --- a/compiler/rustc_codegen_gcc/src/type_.rs +++ b/compiler/rustc_codegen_gcc/src/type_.rs @@ -157,6 +157,14 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { bug!("unsupported float width 16") } + fn type_f16b(&self) -> Type<'gcc> { + #[cfg(feature = "master")] + if self.supports_f16b_type { + return self.context.new_c_type(CType::BFloat16); + } + bug!("unsupported type bfloat16") + } + fn type_f32(&self) -> Type<'gcc> { #[cfg(feature = "master")] if self.supports_f32_type { diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index a45138849e4e0..dce8db6841b7f 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -159,6 +159,7 @@ impl LlvmType for Reg { }, Primitive::Float(float) => match float { Float::F16 => cx.type_f16(), + Float::F16B => cx.type_f16b(), Float::F32 => cx.type_f32(), Float::F64 => cx.type_f64(), Float::F128 => cx.type_f128(), diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index db896fa9c0f2b..9a898429d0384 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -337,6 +337,9 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { Primitive::Float(Float::F16) => { bug!("the va_arg intrinsic does not support `f16`") } + Primitive::Float(Float::F16B) => { + bug!("the va_arg intrinsic does not support `f16b`") + } Primitive::Float(Float::F32) => { // c_double is actually f32 on avr. if self.cx().sess().target.arch != Arch::Avr { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 90f31e0598f2d..f32e6559a8bfc 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -382,6 +382,7 @@ pub(crate) fn target_config(sess: &EarlySession) -> TargetConfig { internal_target_features, has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, }; @@ -419,6 +420,21 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { _ => true, }; + // The heuristic for evaluating to true is twofold, namely; + // + // 1. Can LLVM compile an IR snippet containing `fpext bfloat % to float` + // 2. Does the documentation indicate `bf16` support, can be seen in the + // tracking issue; + cfg.has_reliable_f16b = match (target_arch, target_os) { + // This is similar to , however + // does not work until LLVM 23 on Windows. + (Arch::Arm64EC, _) => major >= 23, + (Arch::AArch64 | Arch::RiscV64 | Arch::LoongArch64, _) => true, + // FIXME(f16b) until + // is resolved `Arch::X86_64` does not have a reliable `f16b`. + _ => false, + }; + cfg.has_reliable_f128 = match (target_arch, target_os) { // Unsupported https://github.com/llvm/llvm-project/issues/121122 (Arch::AmdGpu, _) => false, diff --git a/compiler/rustc_codegen_llvm/src/type_.rs b/compiler/rustc_codegen_llvm/src/type_.rs index 881b8e3a8bd0e..ff1b5851db0f9 100644 --- a/compiler/rustc_codegen_llvm/src/type_.rs +++ b/compiler/rustc_codegen_llvm/src/type_.rs @@ -214,6 +214,10 @@ impl<'ll, CX: Borrow>> BaseTypeCodegenMethods for GenericCx<'ll, CX> { unsafe { llvm::LLVMHalfTypeInContext(self.llcx()) } } + fn type_f16b(&self) -> &'ll Type { + unsafe { llvm::LLVMBFloatTypeInContext(self.llcx()) } + } + fn type_f32(&self) -> &'ll Type { unsafe { llvm::LLVMFloatTypeInContext(self.llcx()) } } diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 1272b26ca0612..7a29ca383b24b 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -315,6 +315,9 @@ pub struct TargetConfig { pub has_reliable_f16: bool, /// Option for `cfg(target_has_reliable_f16_math)`, true if `f16` math calls work. pub has_reliable_f16_math: bool, + /// Option for `cfg(target_has_reliable_f16b)`, presently true if both the ABI + /// and LLVM version supports `f16b`. + pub has_reliable_f16b: bool, /// Option for `cfg(target_has_reliable_f128)`, true if `f128` basic arithmetic works. pub has_reliable_f128: bool, /// Option for `cfg(target_has_reliable_f128_math)`, true if `f128` math calls work. diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs index 38d562d028f34..e06ac36fd758a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/backend.rs +++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs @@ -52,6 +52,7 @@ pub trait CodegenBackend { // support the float types, rather than accidentally quietly skipping all tests. has_reliable_f16: true, has_reliable_f16_math: true, + has_reliable_f16b: true, has_reliable_f128: true, has_reliable_f128_math: true, } diff --git a/compiler/rustc_session/src/config/cfg.rs b/compiler/rustc_session/src/config/cfg.rs index a6decd5898689..05e3c346cd767 100644 --- a/compiler/rustc_session/src/config/cfg.rs +++ b/compiler/rustc_session/src/config/cfg.rs @@ -154,6 +154,7 @@ pub(crate) fn disallow_cfgs(sess: &Session, user_cfgs: &Cfg) { | (sym::target_has_atomic_load_store, Some(_)) | (sym::target_has_reliable_f16, None | Some(_)) | (sym::target_has_reliable_f16_math, None | Some(_)) + | (sym::target_has_reliable_f16b, None | Some(_)) | (sym::target_has_reliable_f128, None | Some(_)) | (sym::target_has_reliable_f128_math, None | Some(_)) | (sym::target_thread_local, None) => disallow(cfg, "--target"), diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 62280f641e9fd..7b3f166b3bf87 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -221,6 +221,7 @@ impl CodegenBackend for MiriCodegenBackend { internal_target_features: native_target_config.internal_target_features, // The basic types and ABI always work. + has_reliable_f16b: true, has_reliable_f16: true, has_reliable_f128: true, // We always provide the f16 intrinsics, but some are provided via the host, From bec4db66e5f3d21e54da4a4ce4904eb58bce1aa0 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:52 +0100 Subject: [PATCH 0506/1309] Update Tidy rules to allow for `//@ revision` --- src/tools/tidy/src/style.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs index 6066ad5805006..6d8a6371f89e3 100644 --- a/src/tools/tidy/src/style.rs +++ b/src/tools/tidy/src/style.rs @@ -74,6 +74,7 @@ const ANNOTATIONS_TO_IGNORE: &[&str] = &[ "//@ lldb", "//@ cdb", "//@ normalize-stderr", + "//@ revisions", ]; fn generate_problems<'a>( From e1303802277558e6f6cd2f5a37a2503cf8e1440a Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:52 +0100 Subject: [PATCH 0507/1309] Update and write tests --- tests/assembly-llvm/f16b.rs | 124 ++++++++++++++++++ tests/auxiliary/minicore.rs | 43 +++++- tests/codegen-llvm/float/f16b.rs | 40 ++++++ .../scalable-vectors/bf16-intrinsic.rs | 34 +++++ ...ature-gate-cfg-target-has-reliable-f16b.rs | 6 + ...e-gate-cfg-target-has-reliable-f16b.stderr | 12 ++ tests/ui/feature-gates/feature-gate-f16b.rs | 30 +++++ .../ui/feature-gates/feature-gate-f16b.stderr | 121 +++++++++++++++++ tests/ui/float/f16b-restrictions.rs | 20 +++ tests/ui/float/f16b-restrictions.stderr | 43 ++++++ tests/ui/float/f16b.rs | 54 ++++++++ tests/ui/parser/f16b.rs | 14 ++ tests/ui/parser/f16b.stderr | 10 ++ 13 files changed, 549 insertions(+), 2 deletions(-) create mode 100644 tests/assembly-llvm/f16b.rs create mode 100644 tests/codegen-llvm/float/f16b.rs create mode 100644 tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs create mode 100644 tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr create mode 100644 tests/ui/feature-gates/feature-gate-f16b.rs create mode 100644 tests/ui/feature-gates/feature-gate-f16b.stderr create mode 100644 tests/ui/float/f16b-restrictions.rs create mode 100644 tests/ui/float/f16b-restrictions.stderr create mode 100644 tests/ui/float/f16b.rs create mode 100644 tests/ui/parser/f16b.rs create mode 100644 tests/ui/parser/f16b.stderr diff --git a/tests/assembly-llvm/f16b.rs b/tests/assembly-llvm/f16b.rs new file mode 100644 index 0000000000000..373ebd0ac566d --- /dev/null +++ b/tests/assembly-llvm/f16b.rs @@ -0,0 +1,124 @@ +//@ add-minicore +//@ assembly-output: emit-asm +// +//@ revisions: AARCH64_LINUX AARCH64_BE AARCH64_DARWIN AARCH64_MSVC ARM64EC_MSVC X64_LINUX X64_WINDOWS_GNU X64_WINDOWS_MSVC RISCV64 LOONGARCH64 +//@[AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu +//@[AARCH64_LINUX] needs-llvm-components: aarch64 +//@[AARCH64_LINUX] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[AARCH64_BE] compile-flags: -Copt-level=3 --target aarch64_be-unknown-linux-gnu +//@[AARCH64_BE] needs-llvm-components: aarch64 +//@[AARCH64_BE] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[AARCH64_DARWIN] compile-flags: -Copt-level=3 --target aarch64-apple-darwin +//@[AARCH64_DARWIN] needs-llvm-components: aarch64 +//@[AARCH64_DARWIN] filecheck-flags: --check-prefixes AARCH64,AARCH64-APPLE +//@[AARCH64_MSVC] compile-flags: -Copt-level=3 --target aarch64-pc-windows-msvc +//@[AARCH64_MSVC] needs-llvm-components: aarch64 +//@[AARCH64_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[ARM64EC_MSVC] compile-flags: -Copt-level=3 --target arm64ec-pc-windows-msvc +//@[ARM64EC_MSVC] needs-llvm-components: aarch64 +//@[ARM64EC_MSVC] min-llvm-version: 23 +//@[ARM64EC_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE +//@[X64_LINUX] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-unknown-linux-gnu +//@[X64_LINUX] needs-llvm-components: x86 +//@[X64_LINUX] filecheck-flags: --check-prefixes X64,X64-LINUX +//@[X64_WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-gnu +//@[X64_WINDOWS_GNU] needs-llvm-components: x86 +//@[X64_WINDOWS_GNU] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@[X64_WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-msvc +//@[X64_WINDOWS_MSVC] needs-llvm-components: x86 +//@[X64_WINDOWS_MSVC] filecheck-flags: --check-prefixes X64,X64-WINDOWS +//@[RISCV64] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu +//@[RISCV64] needs-llvm-components: riscv +//@[LOONGARCH64] compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu +//@[LOONGARCH64] needs-llvm-components: loongarch + +#![feature(f16b, no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(improper_ctypes_definitions)] + +// Check that the assembly that rustc generates matches what clang emits. + +extern crate minicore; + +use minicore::From; +use minicore::num::f16b; + +// CHECK-LABEL: identity_f16b +// AARCH64: ret +// X64: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: lui a1, 1048560 +// RISCV64-NEXT: or a0, a0, a1 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: lu12i.w $a1, -16 +// LOONGARCH64-NEXT: or $a0, $a0, $a1 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + value +} + +// CHECK-LABEL: f16b_to_bits +// AARCH64-NOTAPPLE: fmov w0, s0 +// AARCH64-APPLE: fmov w8, s0 +// AARCH64-APPLE-NEXT: and w0, w8, #0xffff +// AARCH64-NEXT: ret +// X64: pextrw eax, xmm0, 0 +// X64-NEXT: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: slli a0, a0, 48 +// RISCV64-NEXT: srli a0, a0, 48 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: bstrpick.d $a0, $a0, 15, 0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + value.to_bits() +} + +// CHECK-LABEL: f16b_from_bits +// AARCH64: fmov s0, w0 +// AARCH64-NEXT: ret +// X64-LINUX: pinsrw xmm0, edi, 0 +// X64-LINUX-NEXT: ret +// X64-WINDOWS: pinsrw xmm0, ecx, 0 +// X64-WINDOWS-NEXT: ret +// RISCV64: lui a1, 1048560 +// RISCV64-NEXT: or a0, a0, a1 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: lu12i.w $a1, -16 +// LOONGARCH64-NEXT: or $a0, $a0, $a1 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + f16b::from_bits(bits) +} + +// CHECK-LABEL: widen_f16b +// AARCH64: fmov w8, s0 +// AARCH64-NEXT: lsl w8, w8, #16 +// AARCH64-NEXT: fmov s0, w8 +// AARCH64-NEXT: ret +// X64: pextrw eax, xmm0, 0 +// X64-NEXT: shl eax, 16 +// X64-NEXT: movd xmm0, eax +// X64-NEXT: ret +// RISCV64: fmv.x.w a0, fa0 +// RISCV64-NEXT: slli a0, a0, 16 +// RISCV64-NEXT: fmv.w.x fa0, a0 +// RISCV64-NEXT: ret +// LOONGARCH64: movfr2gr.s $a0, $fa0 +// LOONGARCH64-NEXT: slli.d $a0, $a0, 16 +// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 +// LOONGARCH64-NEXT: ret +#[unsafe(no_mangle)] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + f32::from(value) +} diff --git a/tests/auxiliary/minicore.rs b/tests/auxiliary/minicore.rs index 2b7eb0b9afbcf..f0ccc341a567d 100644 --- a/tests/auxiliary/minicore.rs +++ b/tests/auxiliary/minicore.rs @@ -29,6 +29,8 @@ rustc_attrs, decl_macro, f16, + f16b, + cfg_target_has_reliable_f16b, f128, repr_simd, transparent_unions, @@ -80,6 +82,10 @@ impl LegacyReceiver for &mut T {} #[lang = "copy"] pub trait Copy: Sized {} +pub trait From: Sized { + fn from(value: T) -> Self; +} + #[lang = "bikeshed_guaranteed_no_drop"] pub trait BikeshedGuaranteedNoDrop {} @@ -360,7 +366,7 @@ pub const unsafe fn copy_nonoverlapping(src: *const T, dst: *mut T, count: us pub mod mem { #[rustc_nounwind] #[rustc_intrinsic] - pub unsafe fn transmute(src: Src) -> Dst; + pub const unsafe fn transmute(src: Src) -> Dst; #[rustc_nounwind] #[rustc_intrinsic] @@ -392,7 +398,40 @@ pub mod hint { } pub mod num { - use super::Copy; + use super::{Copy, From, mem}; + + #[rustc_intrinsic] + const unsafe fn unchecked_shl(value: T, shift: U) -> T; + + #[cfg(target_has_reliable_f16b)] + #[allow(non_camel_case_types)] + #[lang = "f16b"] + #[repr(transparent)] + pub struct f16b(u16); + + #[cfg(target_has_reliable_f16b)] + impl f16b { + #[inline] + pub const fn from_bits(bits: u16) -> Self { + unsafe { mem::transmute(bits) } + } + + #[inline] + pub const fn to_bits(self) -> u16 { + unsafe { mem::transmute(self) } + } + } + + #[cfg(target_has_reliable_f16b)] + impl Copy for f16b {} + + #[cfg(target_has_reliable_f16b)] + impl From for f32 { + #[inline] + fn from(value: f16b) -> Self { + unsafe { mem::transmute(unchecked_shl(value.to_bits() as u32, 16u32)) } + } + } #[repr(C)] #[lang = "complex"] diff --git a/tests/codegen-llvm/float/f16b.rs b/tests/codegen-llvm/float/f16b.rs new file mode 100644 index 0000000000000..7de6a776190c9 --- /dev/null +++ b/tests/codegen-llvm/float/f16b.rs @@ -0,0 +1,40 @@ +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] +#![feature(f16b)] +#![allow(improper_ctypes_definitions)] + +extern crate core; + +use core::num::f16b; + +// CHECK-LABEL: define{{.*}} bfloat @identity_f16b(bfloat +#[no_mangle] +pub extern "C" fn identity_f16b(value: f16b) -> f16b { + // CHECK: ret bfloat + value +} + +// CHECK-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat +#[no_mangle] +pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { + // CHECK: bitcast bfloat %value to i16 + value.to_bits() +} + +// CHECK-LABEL: define{{.*}} bfloat @f16b_from_bits(i16 +#[no_mangle] +pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { + // CHECK: bitcast i16 %bits to bfloat + f16b::from_bits(bits) +} + +// CHECK-LABEL: define{{.*}} float @widen_f16b(bfloat +#[no_mangle] +pub extern "C" fn widen_f16b(value: f16b) -> f32 { + // CHECK: bitcast bfloat %value to i16 + // CHECK: zext i16 + // CHECK: shl nuw i32 {{.*}}, 16 + // CHECK: bitcast i32 {{.*}} to float + f32::from(value) +} diff --git a/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs new file mode 100644 index 0000000000000..a080b36382389 --- /dev/null +++ b/tests/codegen-llvm/scalable-vectors/bf16-intrinsic.rs @@ -0,0 +1,34 @@ +//@ add-minicore +//@ revisions: OPT-0 OPT-3 +//@[OPT-0] compile-flags: -Copt-level=0 +//@[OPT-3] compile-flags: -Copt-level=3 +//@ compile-flags: --target aarch64-unknown-linux-gnu +//@ needs-llvm-components: aarch64 + +#![crate_type = "lib"] +#![feature(f16b, link_llvm_intrinsics, no_core, simd_ffi)] +#![no_core] +#![allow(non_camel_case_types)] + +extern crate minicore; + +use minicore::num::f16b; +use minicore::simd::{Simd, f32x4}; + +type bfloat16x8_t = Simd; + +#[unsafe(no_mangle)] +#[target_feature(enable = "neon,bf16")] +// CHECK-LABEL: define <4 x float> @vbfmmlaq_f32( +// CHECK-SAME: <4 x float> %acc, <8 x bfloat> %lhs, <8 x bfloat> %rhs) +pub unsafe extern "C" fn vbfmmlaq_f32(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4 { + unsafe extern "llvm-intrinsic" { + #[link_name = "llvm.aarch64.neon.bfmmla"] + fn bfmmla(acc: f32x4, lhs: bfloat16x8_t, rhs: bfloat16x8_t) -> f32x4; + } + + // CHECK: [[RESULT:%.*]] = {{.*}}call <4 x float> @llvm.aarch64.neon.bfmmla( + // CHECK-SAME: <4 x float> %acc, <8 x bfloat> %lhs, <8 x bfloat> %rhs) + // CHECK: ret <4 x float> [[RESULT]] + unsafe { bfmmla(acc, lhs, rhs) } +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs new file mode 100644 index 0000000000000..a1c2f22782c4c --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.rs @@ -0,0 +1,6 @@ +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) + +fn main() { + cfg!(target_has_reliable_f16b); + //~^ ERROR `cfg(target_has_reliable_f16b)` is experimental and subject to change +} diff --git a/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr new file mode 100644 index 0000000000000..46106f61ad3ae --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-cfg-target-has-reliable-f16b.stderr @@ -0,0 +1,12 @@ +error[E0658]: `cfg(target_has_reliable_f16b)` is experimental and subject to change + --> $DIR/feature-gate-cfg-target-has-reliable-f16b.rs:4:10 + | +LL | cfg!(target_has_reliable_f16b); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: add `#![feature(cfg_target_has_reliable_f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-f16b.rs b/tests/ui/feature-gates/feature-gate-f16b.rs new file mode 100644 index 0000000000000..fc531c19ba5b1 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-f16b.rs @@ -0,0 +1,30 @@ +extern crate core; + +use core::num::f16b; +//~^ ERROR use of unstable library feature `f16b` + +fn main() { + let _ = f16b::from_bits(0); + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR use of unstable library feature `f16b` + + let a = 0.0f16b; + //~^ ERROR invalid suffix `f16b` + + let _: f16b = 1.0; + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR mismatched types + + let x = f16b::from_bits(0x3f80); + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR use of unstable library feature `f16b` + let _ = x + x; + //~^ ERROR cannot add `f16b` to `f16b` + + let _ = 1u16 as f16b; + //~^ ERROR use of unstable library feature `f16b` + //~| ERROR non-primitive cast + + let _ = x as f32; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/feature-gates/feature-gate-f16b.stderr b/tests/ui/feature-gates/feature-gate-f16b.stderr new file mode 100644 index 0000000000000..3ba9299485276 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-f16b.stderr @@ -0,0 +1,121 @@ +error: invalid suffix `f16b` for float literal + --> $DIR/feature-gate-f16b.rs:11:13 + | +LL | let a = 0.0f16b; + | ^^^^^^^ invalid suffix `f16b` + | + = help: valid suffixes are `f32` and `f64` + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:3:5 + | +LL | use core::num::f16b; + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:7:13 + | +LL | let _ = f16b::from_bits(0); + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:14:12 + | +LL | let _: f16b = 1.0; + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:18:13 + | +LL | let x = f16b::from_bits(0x3f80); + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:24:21 + | +LL | let _ = 1u16 as f16b; + | ^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:7:13 + | +LL | let _ = f16b::from_bits(0); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0308]: mismatched types + --> $DIR/feature-gate-f16b.rs:14:19 + | +LL | let _: f16b = 1.0; + | ---- ^^^ expected `f16b`, found floating-point number + | | + | expected due to this + +error[E0658]: use of unstable library feature `f16b` + --> $DIR/feature-gate-f16b.rs:18:13 + | +LL | let x = f16b::from_bits(0x3f80); + | ^^^^^^^^^^^^^^^ + | + = note: see issue #160630 for more information + = help: add `#![feature(f16b)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0369]: cannot add `f16b` to `f16b` + --> $DIR/feature-gate-f16b.rs:21:15 + | +LL | let _ = x + x; + | - ^ - f16b + | | + | f16b + | +note: `f16b` does not implement `Add` + --> $SRC_DIR/core/src/num/bfloat.rs:LL:COL + | + = note: `f16b` is defined in another crate + +error[E0605]: non-primitive cast: `u16` as `f16b` + --> $DIR/feature-gate-f16b.rs:24:13 + | +LL | let _ = 1u16 as f16b; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `f16b` as `f32` + --> $DIR/feature-gate-f16b.rs:28:13 + | +LL | let _ = x as f32; + | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - let _ = x as f32; +LL + let _ = f32::from(x); + | + +error: aborting due to 12 previous errors + +Some errors have detailed explanations: E0308, E0369, E0605, E0658. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/float/f16b-restrictions.rs b/tests/ui/float/f16b-restrictions.rs new file mode 100644 index 0000000000000..b2dbf1a734be3 --- /dev/null +++ b/tests/ui/float/f16b-restrictions.rs @@ -0,0 +1,20 @@ +#![feature(f16b)] + +extern crate core; + +use core::num::f16b; + +fn main() { + let _: f16b = 1.0; + //~^ ERROR mismatched types + + let x = f16b::from_bits(0x3f80); + let _ = x + x; + //~^ ERROR cannot add `f16b` to `f16b` + + let _ = 1u16 as f16b; + //~^ ERROR non-primitive cast + + let _ = x as f32; + //~^ ERROR non-primitive cast +} diff --git a/tests/ui/float/f16b-restrictions.stderr b/tests/ui/float/f16b-restrictions.stderr new file mode 100644 index 0000000000000..540e92d26b384 --- /dev/null +++ b/tests/ui/float/f16b-restrictions.stderr @@ -0,0 +1,43 @@ +error[E0308]: mismatched types + --> $DIR/f16b-restrictions.rs:8:19 + | +LL | let _: f16b = 1.0; + | ---- ^^^ expected `f16b`, found floating-point number + | | + | expected due to this + +error[E0369]: cannot add `f16b` to `f16b` + --> $DIR/f16b-restrictions.rs:12:15 + | +LL | let _ = x + x; + | - ^ - f16b + | | + | f16b + | +note: `f16b` does not implement `Add` + --> $SRC_DIR/core/src/num/bfloat.rs:LL:COL + | + = note: `f16b` is defined in another crate + +error[E0605]: non-primitive cast: `u16` as `f16b` + --> $DIR/f16b-restrictions.rs:15:13 + | +LL | let _ = 1u16 as f16b; + | ^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + +error[E0605]: non-primitive cast: `f16b` as `f32` + --> $DIR/f16b-restrictions.rs:18:13 + | +LL | let _ = x as f32; + | ^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object + | +help: consider using the `From` trait instead + | +LL - let _ = x as f32; +LL + let _ = f32::from(x); + | + +error: aborting due to 4 previous errors + +Some errors have detailed explanations: E0308, E0369, E0605. +For more information about an error, try `rustc --explain E0308`. diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs new file mode 100644 index 0000000000000..ed143c2c2b2fa --- /dev/null +++ b/tests/ui/float/f16b.rs @@ -0,0 +1,54 @@ +// FIXME(f16b): +// This file compiled unoptimised in some function calls, such as `to_bits()`, +// emit a call to `__truncsfbf2` which fails in the CI see here for more; +// +// Remove `-C-opt-level=3` once the `__truncsfbf2` symbol is in +// compiler-builtins. +// +//@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) -Copt-level=3 +//@ run-pass + +#![feature(f16b, cfg_target_has_reliable_f16b)] + +extern crate core; + +use core::num::f16b; +#[cfg(target_has_reliable_f16b)] +use std::fmt::{Debug, LowerExp, UpperExp}; + +#[cfg(target_has_reliable_f16b)] +const ONE: f16b = f16b::from_bits(0x3f80); + +#[cfg(target_has_reliable_f16b)] +const ONE_BITS: u16 = ONE.to_bits(); + +#[cfg(target_has_reliable_f16b)] +fn assert_traits() +where + T: Default + Copy + Clone + Debug + LowerExp + UpperExp + PartialEq + PartialOrd, +{ +} + +fn main() { + assert_eq!(size_of::(), 2); + assert_eq!(align_of::(), 2); + + #[cfg(target_has_reliable_f16b)] + { + assert_traits::(); + + assert_eq!(f16b::default().to_bits(), 0); + assert_eq!(ONE_BITS, 0x3f80); + assert_eq!(f32::from(ONE).to_bits(), 0x3f80_0000); + + let two = f16b::from_bits(0x4000); + let negative_zero = f16b::from_bits(0x8000); + let nan = f16b::from_bits(0x7fc0); + assert!(ONE < two); + assert_eq!(f16b::from_bits(0), negative_zero); + assert!(nan != nan); + assert_eq!(format!("{ONE:?}"), "1.0"); + assert_eq!(format!("{ONE:e}"), "1e0"); + assert_eq!(format!("{ONE:E}"), "1E0"); + } +} diff --git a/tests/ui/parser/f16b.rs b/tests/ui/parser/f16b.rs new file mode 100644 index 0000000000000..bb6f3737a33d5 --- /dev/null +++ b/tests/ui/parser/f16b.rs @@ -0,0 +1,14 @@ +#![feature(f16b)] + +extern crate core; + +use core::num::f16b; + +// `f16b` is a nominal core type, not a floating-point literal type. +fn main() { + let value = f16b::from_bits(0x3f80); + let _: f16b = value; + + let _ = 0.0f16b; + //~^ ERROR invalid suffix `f16b` for float literal +} diff --git a/tests/ui/parser/f16b.stderr b/tests/ui/parser/f16b.stderr new file mode 100644 index 0000000000000..2d89bbe4d8776 --- /dev/null +++ b/tests/ui/parser/f16b.stderr @@ -0,0 +1,10 @@ +error: invalid suffix `f16b` for float literal + --> $DIR/f16b.rs:12:13 + | +LL | let _ = 0.0f16b; + | ^^^^^^^ invalid suffix `f16b` + | + = help: valid suffixes are `f32` and `f64` + +error: aborting due to 1 previous error + From e587f8b32f0dabd62fe4b882ca55d2ae38d9ae77 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 08:57:52 +0100 Subject: [PATCH 0508/1309] Wire up f16b in backends --- src/base.rs | 2 ++ src/context.rs | 3 +++ src/lib.rs | 2 ++ src/type_.rs | 8 ++++++++ 4 files changed, 15 insertions(+) diff --git a/src/base.rs b/src/base.rs index 101af0bb0bff1..498ea4b45a8f8 100644 --- a/src/base.rs +++ b/src/base.rs @@ -214,6 +214,7 @@ pub fn compile_codegen_unit( // -fsyntax-only), forbid the compilation when get_target_info() is called on a // context. let f16_type_supported = target_info.supports_target_dependent_type(CType::Float16); + let f16b_type_supported = target_info.supports_target_dependent_type(CType::BFloat16); let f32_type_supported = target_info.supports_target_dependent_type(CType::Float32); let f64_type_supported = target_info.supports_target_dependent_type(CType::Float64); let f128_type_supported = target_info.supports_target_dependent_type(CType::Float128); @@ -225,6 +226,7 @@ pub fn compile_codegen_unit( tcx, u128_type_supported, f16_type_supported, + f16b_type_supported, f32_type_supported, f64_type_supported, f128_type_supported, diff --git a/src/context.rs b/src/context.rs index 38e0e5f329f76..a41255be9e1ea 100644 --- a/src/context.rs +++ b/src/context.rs @@ -72,6 +72,7 @@ pub struct CodegenCx<'gcc, 'tcx> { pub supports_128bit_integers: bool, pub supports_f16_type: bool, + pub supports_f16b_type: bool, pub supports_f32_type: bool, pub supports_f64_type: bool, pub supports_f128_type: bool, @@ -140,6 +141,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { tcx: TyCtxt<'tcx>, supports_128bit_integers: bool, supports_f16_type: bool, + supports_f16b_type: bool, supports_f32_type: bool, supports_f64_type: bool, supports_f128_type: bool, @@ -276,6 +278,7 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { supports_128bit_integers, supports_f16_type, + supports_f16b_type, supports_f32_type, supports_f64_type, supports_f128_type, diff --git a/src/lib.rs b/src/lib.rs index d7a3ef3b4a6c5..79802a670a3f0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -503,6 +503,7 @@ fn target_config(sess: &EarlySession, target_info: &SharedTargetInfo) -> TargetC ); let has_reliable_f16 = target_info.supports_target_dependent_type(CType::Float16); + let has_reliable_f16b = target_info.supports_target_dependent_type(CType::BFloat16); let has_reliable_f128 = target_info.supports_target_dependent_type(CType::Float128); TargetConfig { @@ -510,6 +511,7 @@ fn target_config(sess: &EarlySession, target_info: &SharedTargetInfo) -> TargetC // There are no known bugs with GCC support for f16 or f128 has_reliable_f16, has_reliable_f16_math: has_reliable_f16, + has_reliable_f16b, has_reliable_f128, has_reliable_f128_math: has_reliable_f128, } diff --git a/src/type_.rs b/src/type_.rs index 27b0d2079e63e..1d8582fe337ad 100644 --- a/src/type_.rs +++ b/src/type_.rs @@ -157,6 +157,14 @@ impl<'gcc, 'tcx> BaseTypeCodegenMethods for CodegenCx<'gcc, 'tcx> { bug!("unsupported float width 16") } + fn type_f16b(&self) -> Type<'gcc> { + #[cfg(feature = "master")] + if self.supports_f16b_type { + return self.context.new_c_type(CType::BFloat16); + } + bug!("unsupported type bfloat16") + } + fn type_f32(&self) -> Type<'gcc> { #[cfg(feature = "master")] if self.supports_f32_type { From 4238ee37539902839218f60a63b0e8fe21b06f48 Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:41:56 +0900 Subject: [PATCH 0509/1309] Use `std_or_core` in `undropped_manually_drops` rustfix --- compiler/rustc_lint/src/diagnostics.rs | 16 ++++++++++------ compiler/rustc_lint/src/drop_forget_useless.rs | 11 +++++++++-- .../lint/undropped_manually_drops-no_std.fixed | 13 +++++++++++++ tests/ui/lint/undropped_manually_drops-no_std.rs | 13 +++++++++++++ .../lint/undropped_manually_drops-no_std.stderr | 16 ++++++++++++++++ 5 files changed, 61 insertions(+), 8 deletions(-) create mode 100644 tests/ui/lint/undropped_manually_drops-no_std.fixed create mode 100644 tests/ui/lint/undropped_manually_drops-no_std.rs create mode 100644 tests/ui/lint/undropped_manually_drops-no_std.stderr diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index d96cadaca87eb..ed5988c5380ca 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -1040,9 +1040,10 @@ pub(crate) struct ForgetCopyDiag<'a> { #[derive(Diagnostic)] #[diag( - "calls to `std::mem::drop` with `std::mem::ManuallyDrop` instead of the inner value does nothing" + "calls to `{$krate}::mem::drop` with `{$krate}::mem::ManuallyDrop` instead of the inner value does nothing" )] pub(crate) struct UndroppedManuallyDropsDiag<'a> { + pub krate: &'static str, pub arg_ty: Ty<'a>, #[label("argument has type `{$arg_ty}`")] pub label: Span, @@ -1052,11 +1053,12 @@ pub(crate) struct UndroppedManuallyDropsDiag<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - "use `std::mem::ManuallyDrop::into_inner` to get the inner value", + "use `{$krate}::mem::ManuallyDrop::into_inner` to get the inner value", applicability = "machine-applicable" )] pub(crate) struct UndroppedManuallyDropsSuggestion { - #[suggestion_part(code = "std::mem::ManuallyDrop::into_inner(")] + pub krate: &'static str, + #[suggestion_part(code = "{krate}::mem::ManuallyDrop::into_inner(")] pub start_span: Span, #[suggestion_part(code = ")")] pub end_span: Span, @@ -1064,9 +1066,10 @@ pub(crate) struct UndroppedManuallyDropsSuggestion { #[derive(Diagnostic)] #[diag( - "calls to `drop_in_place` with a pointer to a `std::mem::ManuallyDrop` instead of the inner value does nothing" + "calls to `drop_in_place` with a pointer to a `{$krate}::mem::ManuallyDrop` instead of the inner value does nothing" )] pub(crate) struct UndroppedManuallyDropsInPlaceDiag<'a> { + pub krate: &'static str, pub arg_ty: Ty<'a>, #[label("argument has type `{$arg_ty}`")] pub label: Span, @@ -1076,11 +1079,12 @@ pub(crate) struct UndroppedManuallyDropsInPlaceDiag<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - "use `std::mem::ManuallyDrop::drop` to drop the inner value", + "use `{$krate}::mem::ManuallyDrop::drop` to drop the inner value", applicability = "maybe-incorrect" )] pub(crate) struct UndroppedManuallyDropsInPlaceSuggestion { - #[suggestion_part(code = "std::mem::ManuallyDrop::drop(&mut *")] + pub krate: &'static str, + #[suggestion_part(code = "{krate}::mem::ManuallyDrop::drop(&mut *")] pub start_span: Span, #[suggestion_part(code = ")")] pub end_span: Span, diff --git a/compiler/rustc_lint/src/drop_forget_useless.rs b/compiler/rustc_lint/src/drop_forget_useless.rs index b952b62ada314..9689f6a053275 100644 --- a/compiler/rustc_lint/src/drop_forget_useless.rs +++ b/compiler/rustc_lint/src/drop_forget_useless.rs @@ -9,6 +9,7 @@ use crate::diagnostics::{ UndroppedManuallyDropsInPlaceSuggestion, UndroppedManuallyDropsSuggestion, UseLetUnderscoreIgnoreSuggestion, }; +use crate::utils::std_or_core; use crate::{LateContext, LateLintPass, LintContext}; declare_lint! { @@ -252,15 +253,18 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { } sym::mem_drop if let ty::Adt(adt, _) = arg_ty.kind() - && adt.is_manually_drop() => + && adt.is_manually_drop() + && let Some(krate) = std_or_core(cx) => { cx.emit_span_lint( UNDROPPED_MANUALLY_DROPS, expr.span, UndroppedManuallyDropsDiag { + krate, arg_ty, label: arg.span, suggestion: UndroppedManuallyDropsSuggestion { + krate, start_span: arg.span.shrink_to_lo(), end_span: arg.span.shrink_to_hi(), }, @@ -270,15 +274,18 @@ impl<'tcx> LateLintPass<'tcx> for DropForgetUseless { sym::ptr_drop_in_place | sym::ptr_drop_in_place_self if let &ty::RawPtr(inner_ty, _mutbl) = arg_ty.kind() && let ty::Adt(adt, _) = inner_ty.kind() - && adt.is_manually_drop() => + && adt.is_manually_drop() + && let Some(krate) = std_or_core(cx) => { cx.emit_span_lint( UNDROPPED_MANUALLY_DROPS, expr.span, UndroppedManuallyDropsInPlaceDiag { + krate, arg_ty, label: arg.span, suggestion: UndroppedManuallyDropsInPlaceSuggestion { + krate, start_span: expr.span.shrink_to_lo().until(arg.span.shrink_to_lo()), end_span: arg.span.shrink_to_hi().until(expr.span.shrink_to_hi()), }, diff --git a/tests/ui/lint/undropped_manually_drops-no_std.fixed b/tests/ui/lint/undropped_manually_drops-no_std.fixed new file mode 100644 index 0000000000000..f3b26a1f2903a --- /dev/null +++ b/tests/ui/lint/undropped_manually_drops-no_std.fixed @@ -0,0 +1,13 @@ +//@ check-fail +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(dead_code)] + +struct S; + +fn drop_md() { + core::mem::drop(core::mem::ManuallyDrop::into_inner(core::mem::ManuallyDrop::new(S))); + //~^ ERROR calls to `core::mem::drop` +} diff --git a/tests/ui/lint/undropped_manually_drops-no_std.rs b/tests/ui/lint/undropped_manually_drops-no_std.rs new file mode 100644 index 0000000000000..fb9f23282861f --- /dev/null +++ b/tests/ui/lint/undropped_manually_drops-no_std.rs @@ -0,0 +1,13 @@ +//@ check-fail +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(dead_code)] + +struct S; + +fn drop_md() { + core::mem::drop(core::mem::ManuallyDrop::new(S)); + //~^ ERROR calls to `core::mem::drop` +} diff --git a/tests/ui/lint/undropped_manually_drops-no_std.stderr b/tests/ui/lint/undropped_manually_drops-no_std.stderr new file mode 100644 index 0000000000000..db573e1f7388a --- /dev/null +++ b/tests/ui/lint/undropped_manually_drops-no_std.stderr @@ -0,0 +1,16 @@ +error: calls to `core::mem::drop` with `core::mem::ManuallyDrop` instead of the inner value does nothing + --> $DIR/undropped_manually_drops-no_std.rs:11:5 + | +LL | core::mem::drop(core::mem::ManuallyDrop::new(S)); + | ^^^^^^^^^^^^^^^^-------------------------------^ + | | + | argument has type `ManuallyDrop` + | + = note: `#[deny(undropped_manually_drops)]` on by default +help: use `core::mem::ManuallyDrop::into_inner` to get the inner value + | +LL | core::mem::drop(core::mem::ManuallyDrop::into_inner(core::mem::ManuallyDrop::new(S))); + | ++++++++++++++++++++++++++++++++++++ + + +error: aborting due to 1 previous error + From b84b0bb827416d916e34b67cc55b9acab808958b Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 21 Sep 2026 11:54:29 +0330 Subject: [PATCH 0510/1309] Add rustdoc regression test for glob import of a crate that re-exports at its root --- .../auxiliary/glob-of-reexports-53724.rs | 13 +++++++++++++ .../inline_cross/glob-of-reexports-53724.rs | 17 +++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 tests/rustdoc-html/inline_cross/auxiliary/glob-of-reexports-53724.rs create mode 100644 tests/rustdoc-html/inline_cross/glob-of-reexports-53724.rs diff --git a/tests/rustdoc-html/inline_cross/auxiliary/glob-of-reexports-53724.rs b/tests/rustdoc-html/inline_cross/auxiliary/glob-of-reexports-53724.rs new file mode 100644 index 0000000000000..9adc1bd772064 --- /dev/null +++ b/tests/rustdoc-html/inline_cross/auxiliary/glob-of-reexports-53724.rs @@ -0,0 +1,13 @@ +#![crate_name = "inner"] + +pub mod ser { + pub trait Serialize {} + pub trait Serializer {} +} + +pub mod de { + pub trait Deserialize {} +} + +pub use ser::{Serialize, Serializer}; +pub use de::*; diff --git a/tests/rustdoc-html/inline_cross/glob-of-reexports-53724.rs b/tests/rustdoc-html/inline_cross/glob-of-reexports-53724.rs new file mode 100644 index 0000000000000..d80b4e78f96e2 --- /dev/null +++ b/tests/rustdoc-html/inline_cross/glob-of-reexports-53724.rs @@ -0,0 +1,17 @@ +// Regression test for . + +//@ aux-build:glob-of-reexports-53724.rs +//@ build-aux-docs +//@ ignore-cross-compile + +#![crate_name = "foo"] + +extern crate inner; + +//@ has foo/trait.Serialize.html +//@ has foo/trait.Serializer.html +//@ has foo/trait.Deserialize.html +//@ has foo/index.html '//a[@class="trait"]' 'Serialize' +//@ has foo/index.html '//a[@class="trait"]' 'Serializer' +//@ has foo/index.html '//a[@class="trait"]' 'Deserialize' +pub use inner::*; From fe048b622eced56ae3e415191192f159d79342f8 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 21 Sep 2026 09:32:35 +0100 Subject: [PATCH 0511/1309] Only AArch64 `has_reliable_f16b` presently due to an LLVM codegen issue, also updated test --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 7 ++- tests/assembly-llvm/f16b.rs | 58 +------------------- 2 files changed, 6 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index f32e6559a8bfc..e7cf210747666 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -429,9 +429,12 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { // This is similar to , however // does not work until LLVM 23 on Windows. (Arch::Arm64EC, _) => major >= 23, - (Arch::AArch64 | Arch::RiscV64 | Arch::LoongArch64, _) => true, + (Arch::AArch64, _) => true, // FIXME(f16b) until - // is resolved `Arch::X86_64` does not have a reliable `f16b`. + // is resolved the below do not have a reliable `f16b`, on a widening + // path a call to `__truncsfbf2` is emitted. Or when using architectural + // extensions a non-portable narrowing instruction is emitted. + (Arch::X86_64 | Arch::RiscV64 | Arch::LoongArch64, _) => false, _ => false, }; diff --git a/tests/assembly-llvm/f16b.rs b/tests/assembly-llvm/f16b.rs index 373ebd0ac566d..036b6fc087d02 100644 --- a/tests/assembly-llvm/f16b.rs +++ b/tests/assembly-llvm/f16b.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ assembly-output: emit-asm // -//@ revisions: AARCH64_LINUX AARCH64_BE AARCH64_DARWIN AARCH64_MSVC ARM64EC_MSVC X64_LINUX X64_WINDOWS_GNU X64_WINDOWS_MSVC RISCV64 LOONGARCH64 +//@ revisions: AARCH64_LINUX AARCH64_BE AARCH64_DARWIN AARCH64_MSVC ARM64EC_MSVC //@[AARCH64_LINUX] compile-flags: -Copt-level=3 --target aarch64-unknown-linux-gnu //@[AARCH64_LINUX] needs-llvm-components: aarch64 //@[AARCH64_LINUX] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE @@ -18,19 +18,6 @@ //@[ARM64EC_MSVC] needs-llvm-components: aarch64 //@[ARM64EC_MSVC] min-llvm-version: 23 //@[ARM64EC_MSVC] filecheck-flags: --check-prefixes AARCH64,AARCH64-NOTAPPLE -//@[X64_LINUX] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-unknown-linux-gnu -//@[X64_LINUX] needs-llvm-components: x86 -//@[X64_LINUX] filecheck-flags: --check-prefixes X64,X64-LINUX -//@[X64_WINDOWS_GNU] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-gnu -//@[X64_WINDOWS_GNU] needs-llvm-components: x86 -//@[X64_WINDOWS_GNU] filecheck-flags: --check-prefixes X64,X64-WINDOWS -//@[X64_WINDOWS_MSVC] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel --target x86_64-pc-windows-msvc -//@[X64_WINDOWS_MSVC] needs-llvm-components: x86 -//@[X64_WINDOWS_MSVC] filecheck-flags: --check-prefixes X64,X64-WINDOWS -//@[RISCV64] compile-flags: -Copt-level=3 --target riscv64gc-unknown-linux-gnu -//@[RISCV64] needs-llvm-components: riscv -//@[LOONGARCH64] compile-flags: -Copt-level=3 --target loongarch64-unknown-linux-gnu -//@[LOONGARCH64] needs-llvm-components: loongarch #![feature(f16b, no_core)] #![no_core] @@ -47,16 +34,6 @@ use minicore::num::f16b; // CHECK-LABEL: identity_f16b // AARCH64: ret // X64: ret -// RISCV64: fmv.x.w a0, fa0 -// RISCV64-NEXT: lui a1, 1048560 -// RISCV64-NEXT: or a0, a0, a1 -// RISCV64-NEXT: fmv.w.x fa0, a0 -// RISCV64-NEXT: ret -// LOONGARCH64: movfr2gr.s $a0, $fa0 -// LOONGARCH64-NEXT: lu12i.w $a1, -16 -// LOONGARCH64-NEXT: or $a0, $a0, $a1 -// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 -// LOONGARCH64-NEXT: ret #[unsafe(no_mangle)] pub extern "C" fn identity_f16b(value: f16b) -> f16b { value @@ -67,15 +44,6 @@ pub extern "C" fn identity_f16b(value: f16b) -> f16b { // AARCH64-APPLE: fmov w8, s0 // AARCH64-APPLE-NEXT: and w0, w8, #0xffff // AARCH64-NEXT: ret -// X64: pextrw eax, xmm0, 0 -// X64-NEXT: ret -// RISCV64: fmv.x.w a0, fa0 -// RISCV64-NEXT: slli a0, a0, 48 -// RISCV64-NEXT: srli a0, a0, 48 -// RISCV64-NEXT: ret -// LOONGARCH64: movfr2gr.s $a0, $fa0 -// LOONGARCH64-NEXT: bstrpick.d $a0, $a0, 15, 0 -// LOONGARCH64-NEXT: ret #[unsafe(no_mangle)] pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { value.to_bits() @@ -84,18 +52,6 @@ pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { // CHECK-LABEL: f16b_from_bits // AARCH64: fmov s0, w0 // AARCH64-NEXT: ret -// X64-LINUX: pinsrw xmm0, edi, 0 -// X64-LINUX-NEXT: ret -// X64-WINDOWS: pinsrw xmm0, ecx, 0 -// X64-WINDOWS-NEXT: ret -// RISCV64: lui a1, 1048560 -// RISCV64-NEXT: or a0, a0, a1 -// RISCV64-NEXT: fmv.w.x fa0, a0 -// RISCV64-NEXT: ret -// LOONGARCH64: lu12i.w $a1, -16 -// LOONGARCH64-NEXT: or $a0, $a0, $a1 -// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 -// LOONGARCH64-NEXT: ret #[unsafe(no_mangle)] pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { f16b::from_bits(bits) @@ -106,18 +62,6 @@ pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { // AARCH64-NEXT: lsl w8, w8, #16 // AARCH64-NEXT: fmov s0, w8 // AARCH64-NEXT: ret -// X64: pextrw eax, xmm0, 0 -// X64-NEXT: shl eax, 16 -// X64-NEXT: movd xmm0, eax -// X64-NEXT: ret -// RISCV64: fmv.x.w a0, fa0 -// RISCV64-NEXT: slli a0, a0, 16 -// RISCV64-NEXT: fmv.w.x fa0, a0 -// RISCV64-NEXT: ret -// LOONGARCH64: movfr2gr.s $a0, $fa0 -// LOONGARCH64-NEXT: slli.d $a0, $a0, 16 -// LOONGARCH64-NEXT: movgr2fr.w $fa0, $a0 -// LOONGARCH64-NEXT: ret #[unsafe(no_mangle)] pub extern "C" fn widen_f16b(value: f16b) -> f32 { f32::from(value) From fc49efd517cabd80f27969c5313ce58a9f2905a4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 21 Sep 2026 11:06:46 +0200 Subject: [PATCH 0512/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 220b36c420c49c59923f54cd4a76634fac98a067. --- library/stdarch/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/rust-version b/library/stdarch/rust-version index 18fea436747c7..368cecc0b82f9 100644 --- a/library/stdarch/rust-version +++ b/library/stdarch/rust-version @@ -1 +1 @@ -32d94cc9be3f6e6c3fa1deaea9e0ab93c4980dba +220b36c420c49c59923f54cd4a76634fac98a067 From c176c109d98d50d24bc7d3273c764e258e89a368 Mon Sep 17 00:00:00 2001 From: Brad Smith Date: Mon, 21 Sep 2026 05:06:59 -0400 Subject: [PATCH 0513/1309] OpenBSD/sparc64 has switched from GCC to Clang --- compiler/rustc_llvm/build.rs | 5 ++--- library/unwind/src/lib.rs | 6 +----- src/doc/rustc/src/platform-support/openbsd.md | 2 +- 3 files changed, 4 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_llvm/build.rs b/compiler/rustc_llvm/build.rs index 78f3929dbce47..450b98f20cde9 100644 --- a/compiler/rustc_llvm/build.rs +++ b/compiler/rustc_llvm/build.rs @@ -484,9 +484,8 @@ fn main() { let llvm_static_stdcpp = tracked_env_var_os("LLVM_STATIC_STDCPP"); let llvm_use_libcxx = tracked_env_var_os("LLVM_USE_LIBCXX"); - let stdcppname = if target.contains("openbsd") { - if target.contains("sparc64") { "estdc++" } else { "c++" } - } else if target.contains("darwin") + let stdcppname = if target.contains("openbsd") + || target.contains("darwin") || target.contains("freebsd") || target.contains("windows-gnullvm") || target.contains("aix") diff --git a/library/unwind/src/lib.rs b/library/unwind/src/lib.rs index 043f854ea79fd..fb0acdab835a9 100644 --- a/library/unwind/src/lib.rs +++ b/library/unwind/src/lib.rs @@ -204,11 +204,7 @@ unsafe extern "C" {} #[link(name = "gcc_s", cfg(not(target_feature = "crt-static")))] unsafe extern "C" {} -#[cfg(all(target_os = "openbsd", target_arch = "sparc64"))] -#[link(name = "gcc")] -unsafe extern "C" {} - -#[cfg(all(target_os = "openbsd", not(target_arch = "sparc64")))] +#[cfg(target_os = "openbsd")] #[link(name = "c++abi")] unsafe extern "C" {} diff --git a/src/doc/rustc/src/platform-support/openbsd.md b/src/doc/rustc/src/platform-support/openbsd.md index e6fb23ca9eefd..75bae0e2382fd 100644 --- a/src/doc/rustc/src/platform-support/openbsd.md +++ b/src/doc/rustc/src/platform-support/openbsd.md @@ -14,7 +14,7 @@ The target names follow this format: `$ARCH-unknown-openbsd`, where `$ARCH` spec | `i686-unknown-openbsd` | libc++ | [Standard PC and clones based on the Intel i386 architecture and compatible processors](https://www.openbsd.org/i386.html) | | `powerpc64-unknown-openbsd` | libc++ | [IBM POWER-based PowerNV systems](https://www.openbsd.org/powerpc64.html) | | `riscv64gc-unknown-openbsd` | libc++ | [64-bit RISC-V systems](https://www.openbsd.org/riscv64.html) | -| `sparc64-unknown-openbsd` | estdc++ | [Sun UltraSPARC and Fujitsu SPARC64 systems](https://www.openbsd.org/sparc64.html) | +| `sparc64-unknown-openbsd` | libc++ | [Sun UltraSPARC and Fujitsu SPARC64 systems](https://www.openbsd.org/sparc64.html) | | `x86_64-unknown-openbsd` | libc++ | [AMD64-based systems](https://www.openbsd.org/amd64.html) | Note that all OS versions are *major* even if using X.Y notation (`6.8` and `6.9` are different major versions) and could be binary incompatibles (with breaking changes). From b7996518b94f7917fd3ffa833aef3c9ff228ab2f Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Mon, 21 Sep 2026 04:10:45 -0500 Subject: [PATCH 0514/1309] add workaround to read `Rc` strong/weak counts --- src/etc/lldb_providers.py | 48 +++++++++++++++++++---------- tests/debuginfo/rc_arc.rs | 4 +-- tests/debuginfo/strings-and-strs.rs | 4 +-- 3 files changed, 36 insertions(+), 20 deletions(-) diff --git a/src/etc/lldb_providers.py b/src/etc/lldb_providers.py index 2791dae3600b0..431d450885638 100644 --- a/src/etc/lldb_providers.py +++ b/src/etc/lldb_providers.py @@ -20,7 +20,6 @@ eBasicTypeUnsignedLongLong, eBasicTypeUnsignedShort, eFormatChar, - eTypeIsInteger, ) from rust_types import is_tuple_fields @@ -171,12 +170,6 @@ def unwrap_unique_or_non_null(unique_or_nonnull: SBValue) -> SBValue: return ptr if ptr.TypeIsPointerType() else ptr.GetChildAtIndex(0) -def unwrap_scalar_wrappers(wrapper: SBValue) -> SBValue: - while (wrapper.type.GetTypeFlags() & eTypeIsInteger) == 0: - wrapper = wrapper.GetChildAtIndex(0) - return wrapper - - class DefaultSyntheticProvider: def __init__(self, valobj: SBValue, _dict: LLDBOpaque): # logger = Logger.Logger() @@ -1545,9 +1538,17 @@ def has_children(self) -> bool: def StdRcSummaryProvider(valobj: SBValue, _dict: LLDBOpaque) -> str: - strong = valobj.GetChildMemberWithName("strong").GetValueAsUnsigned() - weak = valobj.GetChildMemberWithName("weak").GetValueAsUnsigned() - return "strong={}, weak={}".format(strong, weak) + strong = valobj.GetChildMemberWithName("strong") + weak = valobj.GetChildMemberWithName("weak") + + if not (strong.IsValid() and weak.IsValid()): + strong = "?" + weak = "?" + else: + strong = strong.GetValueAsUnsigned() + weak = weak.GetValueAsUnsigned() + + return f"strong={strong}, weak={weak}" class StdRcSyntheticProvider: @@ -1570,8 +1571,24 @@ def __init__(self, valobj: SBValue, _dict: LLDBOpaque, is_atomic: bool = False): self.value = self.ptr.GetChildMemberWithName("data" if is_atomic else "value") - self.strong = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("strong")) - self.weak = unwrap_scalar_wrappers(self.ptr.GetChildMemberWithName("weak")) + # infallibly gets an unsigned integer type of at least 64 bits. We don't need to worry about + # whether or not `usize` is actually smaller than that since we don't ever display the + # underlying type to the user anyway + usize_type = valobj.GetTarget().GetBasicType(eBasicTypeUnsignedLongLong) + + self.strong = self.ptr.GetChildMemberWithName("strong").Cast(usize_type) + self.weak = self.ptr.GetChildMemberWithName("weak").Cast(usize_type) + + # If the usize type isn't valid due to llvm/llvm-project#196812, not even the type's fields + # will populate. Luckily, `RcInner` is `#[repr(C)]`, so we can infallibly find the strong + # and weak values in memory + if not self.strong.IsValid() or not self.weak.IsValid(): + raw_ptr = self.ptr.Cast(usize_type.GetPointerType()) + addr = raw_ptr.GetValueAsAddress() + self.strong = self.valobj.CreateValueFromAddress("strong", addr, usize_type) + self.weak = self.valobj.CreateValueFromAddress( + "weak", addr + usize_type.GetByteSize(), usize_type + ) self.value_builder = ValueBuilder(valobj) @@ -1594,15 +1611,14 @@ def get_child_at_index(self, index: int) -> Optional[SBValue]: if index == 0: return self.value if index == 1: - return self.value_builder.from_uint("strong", self.strong_count) + return self.strong if index == 2: - return self.value_builder.from_uint("weak", self.weak_count) + return self.weak return None def update(self): - self.strong_count = self.strong.GetValueAsUnsigned() - self.weak_count = self.weak.GetValueAsUnsigned() - 1 + pass def has_children(self) -> bool: return True diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index b22b7e0d1611d..4399dfe54e7a5 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -18,9 +18,9 @@ //@ lldb-command:run //@ lldb-command:v rc -//@ lldb-check:[...] strong=11, weak=1 { value = 111 } +//@ lldb-check:[...] strong=11, weak=2 { value = 111 } //@ lldb-command:v arc -//@ lldb-check:[...] strong=21, weak=1 { data = 222 } +//@ lldb-check:[...] strong=21, weak=2 { data = 222 } // === CDB TESTS ================================================================================== diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 692c75bbfbc9d..e081bf0a2ee8e 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -43,7 +43,7 @@ //@ lldb-check:[...] str_in_tuple = ("Hello", "World") //@ lldb-command:v str_in_rc -//@ lldb-check:[...] str_in_rc = strong=1, weak=0 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } +//@ lldb-check:[...] str_in_rc = strong=1, weak=1 { value = "Hello" { [0] = 'H' [1] = 'e' [2] = 'l' [3] = 'l' [4] = 'o' } } //@ lldb-command:v box_str //@ lldb-check:[...] box_str = "World" { [0] = 'W' [1] = 'o' [2] = 'r' [3] = 'l' [4] = 'd' } @@ -56,7 +56,7 @@ // lldb-command:v rc_str // ignore-tidy-linelength -// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=0 { value = "World" } +// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } #![allow(unused_variables)] From 1bd00d4f7277abbcdaa62382aff4e314869d8b28 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Tue, 1 Sep 2026 14:36:21 +0000 Subject: [PATCH 0515/1309] Add support for -Zsanitizer-cfi-minimal-runtime For production use, we should only link in the ubsan_minimal runtime, instead of the complete ubsan runtime. This adds support for both cfi-recover and cfi-diag to use the minimal runtime when `-Zsanitizer-cfi-minimal-runtime` is specified. This also includes tests, to ensure the flag can only be used if either cfi-recover or cfi-diag is enabled, it doesn't disrupt the original behavior, and links in the correct runtime when specified. Co-Authored-By: Bastian Kersting --- compiler/rustc_codegen_llvm/src/builder.rs | 33 +++- compiler/rustc_codegen_ssa/src/back/link.rs | 6 +- compiler/rustc_session/src/diagnostics.rs | 6 + compiler/rustc_session/src/options.rs | 2 + compiler/rustc_session/src/session.rs | 11 ++ src/bootstrap/src/core/build_steps/llvm.rs | 14 +- .../cfi/emit-type-checks-diag-mode.rs | 5 +- .../cfi/emit-type-checks-recover-mode.rs | 5 +- .../run-make/sanitizer-cfi-runtime/program.rs | 17 ++ tests/run-make/sanitizer-cfi-runtime/rmake.rs | 171 ++++++++++++++++++ .../cfi/fn-ptr-type-mismatch-recover.rs | 38 ++++ .../ui/sanitizer/cfi/fn-ptr-type-mismatch.rs | 9 +- ...al-runtime-requires-cfi-recover-or-diag.rs | 11 ++ ...untime-requires-cfi-recover-or-diag.stderr | 4 + 14 files changed, 319 insertions(+), 13 deletions(-) create mode 100644 tests/run-make/sanitizer-cfi-runtime/program.rs create mode 100644 tests/run-make/sanitizer-cfi-runtime/rmake.rs create mode 100644 tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index abc71f450a515..438accb85f377 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2065,17 +2065,31 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { let is_diag = self.tcx.sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false); let is_recover = self.tcx.sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false); + let is_minimal = + self.tcx.sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false); if is_diag || is_recover { - let fty = self.cx.type_func( - &[self.cx.type_ptr(), self.cx.type_isize(), self.cx.type_isize()], - self.cx.type_void(), - ); + let fty = if is_minimal { + self.cx.type_func(&[], self.cx.type_void()) + } else { + self.cx.type_func( + &[self.cx.type_ptr(), self.cx.type_isize(), self.cx.type_isize()], + self.cx.type_void(), + ) + }; let ubsan_handler = self.declare_cfn( if is_recover { - "__ubsan_handle_cfi_check_fail" + if is_minimal { + "__ubsan_handle_cfi_check_fail_minimal" + } else { + "__ubsan_handle_cfi_check_fail" + } } else { - "__ubsan_handle_cfi_check_fail_abort" + if is_minimal { + "__ubsan_handle_cfi_check_fail_minimal_abort" + } else { + "__ubsan_handle_cfi_check_fail_abort" + } }, llvm::UnnamedAddr::Global, fty, @@ -2101,13 +2115,18 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.generate_ubsan_cfi_diag_data(self.span, expected_ty, check_kind); let function_address = self.ptrtoint(llfn, self.cx.type_isize()); + let arguments: &[_] = if is_minimal { + &[] + } else { + &[diag_data, function_address, self.const_usize(0)] + }; self.call( fty, None, None, ubsan_handler, ReturnSlot::Direct, - &[diag_data, function_address, self.const_usize(0)], + arguments, None, None, ); diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index c283e464821e5..7c8bb4f59dfba 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1764,7 +1764,11 @@ fn add_sanitizer_libraries( && (sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false) || sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false)) { - link_sanitizer_runtime(sess, flavor, linker, "ubsan"); + if sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false) { + link_sanitizer_runtime(sess, flavor, linker, "ubsan_minimal"); + } else { + link_sanitizer_runtime(sess, flavor, linker, "ubsan"); + } } } diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index a2bf9a0d2dfc3..d27b616d7e359 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -340,6 +340,12 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; #[diag("`-Zsanitizer-cfi-diag` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiDiagRequiresCfi; +#[derive(Diagnostic)] +#[diag( + "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`" +)] +pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag; + #[derive(Diagnostic)] #[diag("`-Zsanitizer-kcfi-arity` requires `-Zsanitizer=kcfi`")] pub(crate) struct SanitizerKcfiArityRequiresKcfi; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..f11bdadf5b67d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2825,6 +2825,8 @@ written to standard error output)"), "enable CFI diagnostics (default: no)"), sanitizer_cfi_recover: Option = (None, parse_opt_bool, [TRACKED], "enable CFI recovery (default: no)"), + sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED], + "enable minimal UBSan runtime for CFI (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), sanitizer_kcfi_arity: Option = (None, parse_opt_bool, [TRACKED], diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 274cfe8d7eb8a..bf310270d0a19 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -746,6 +746,10 @@ impl Session { self.opts.unstable_opts.sanitizer_cfi_diag == Some(true) } + pub fn is_sanitizer_cfi_minimal_runtime_enabled(&self) -> bool { + self.opts.unstable_opts.sanitizer_cfi_minimal_runtime == Some(true) + } + pub fn is_sanitizer_kcfi_arity_enabled(&self) -> bool { self.opts.unstable_opts.sanitizer_kcfi_arity == Some(true) } @@ -1684,6 +1688,13 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } + // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. + if sess.is_sanitizer_cfi_minimal_runtime_enabled() { + if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { + sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); + } + } + // LLVM CFI integer normalization requires CFI or KCFI. if sess.is_sanitizer_cfi_normalize_integers_enabled() { if !(sess.is_sanitizer_cfi_enabled() || sess.is_sanitizer_kcfi_enabled()) { diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 096184ee9e5b4..2062461de4c2a 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -1903,7 +1903,7 @@ fn supported_sanitizers( "aarch64-unknown-linux-gnu" => common_libs( "linux", "aarch64", - &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan", "ubsan"], + &["asan", "lsan", "msan", "tsan", "hwasan", "rtsan", "ubsan", "ubsan_minimal"], ), "aarch64-unknown-linux-ohos" => { common_libs("linux", "aarch64", &["asan", "lsan", "msan", "tsan", "hwasan"]) @@ -1924,7 +1924,17 @@ fn supported_sanitizers( "x86_64-unknown-linux-gnu" => common_libs( "linux", "x86_64", - &["asan", "dfsan", "lsan", "msan", "safestack", "tsan", "rtsan", "ubsan"], + &[ + "asan", + "dfsan", + "lsan", + "msan", + "safestack", + "tsan", + "rtsan", + "ubsan", + "ubsan_minimal", + ], ), "x86_64-unknown-linux-gnuasan" => common_libs("linux", "x86_64", &["asan"]), "x86_64-unknown-linux-gnumsan" => common_libs("linux", "x86_64", &["msan"]), diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs index 07688a8e5cb0b..96cfb94289724 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs @@ -1,7 +1,9 @@ // Verifies that pointer type membership tests for indirect calls are emitted. // +//@ revisions: cfi-diag cfi-diag-minimal-runtime //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ [cfi-diag-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] @@ -14,7 +16,8 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg) // CHECK: type_test.fail: // CHECK-NEXT: {{%.+}} = ptrtoint ptr {{%f|%0}} to i64 - // CHECK-NEXT: call void @__ubsan_handle_cfi_check_fail_abort( + // cfi-diag-NEXT: call void @__ubsan_handle_cfi_check_fail_abort( + // cfi-diag-minimal-runtime-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal_abort() // CHECK-NEXT: unreachable f(arg) } diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs index 0dbcb7a833fb7..b3a1e2cb0b02e 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs @@ -1,7 +1,9 @@ // Verifies that pointer type membership tests for indirect calls are emitted. // +//@ revisions: cfi-recover cfi-recover-minimal-runtime //@ needs-sanitizer-cfi //@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ [cfi-recover-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] @@ -14,7 +16,8 @@ pub fn foo(f: fn(i32) -> i32, arg: i32) -> i32 { // CHECK-NEXT: {{%.+}} = call i32 %f(i32{{.*}} %arg) // CHECK: type_test.fail: // CHECK-NEXT: {{%.+}} = ptrtoint ptr {{%f|%0}} to i64 - // CHECK-NEXT: call void @__ubsan_handle_cfi_check_fail( + // cfi-recover-NEXT: call void @__ubsan_handle_cfi_check_fail( + // cfi-recover-minimal-runtime-NEXT: call void @__ubsan_handle_cfi_check_fail_minimal() // CHECK-NEXT: br label %type_test.pass f(arg) } diff --git a/tests/run-make/sanitizer-cfi-runtime/program.rs b/tests/run-make/sanitizer-cfi-runtime/program.rs new file mode 100644 index 0000000000000..0a46dcedef9de --- /dev/null +++ b/tests/run-make/sanitizer-cfi-runtime/program.rs @@ -0,0 +1,17 @@ +use std::hint::black_box; +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +#[inline(never)] +fn call_with_mismatch(f: fn(i32) -> i32) { + let g: fn(i32, i32) -> i32 = unsafe { mem::transmute(f) }; + let res = g(1, 2); + assert_eq!(res, 2); +} + +fn main() { + call_with_mismatch(black_box(add_one)); +} diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs new file mode 100644 index 0000000000000..adb739e43c341 --- /dev/null +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -0,0 +1,171 @@ +//@ needs-sanitizer-support +//@ needs-sanitizer-cfi + +use run_make_support::{run, run_fail, rustc}; + +fn main() { + // 1. Check link args for default CFI (no diag/recover, no UBSan runtime) + let link_args_default = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + !link_args_default.contains("ubsan"), + "did not expect any ubsan runtime in link args, got: {link_args_default}" + ); + + // 2. Check link args for full UBSan runtime with CFI diag mode + let link_args_full_diag = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_full_diag.contains("rt.ubsan.") || link_args_full_diag.contains("rt.ubsan\""), + "expected ubsan runtime in link args, got: {link_args_full_diag}" + ); + assert!( + !link_args_full_diag.contains("ubsan_minimal"), + "did not expect ubsan_minimal in link args, got: {link_args_full_diag}" + ); + + // 3. Check link args for full UBSan runtime with CFI recover mode + let link_args_full_recover = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_full_recover.contains("rt.ubsan.") + || link_args_full_recover.contains("rt.ubsan\""), + "expected ubsan runtime in link args, got: {link_args_full_recover}" + ); + assert!( + !link_args_full_recover.contains("ubsan_minimal"), + "did not expect ubsan_minimal in link args, got: {link_args_full_recover}" + ); + + // 4. Check link args for minimal UBSan runtime with CFI diag mode + let link_args_min_diag = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_min_diag.contains("rt.ubsan_minimal.") + || link_args_min_diag.contains("rt.ubsan_minimal\""), + "expected ubsan_minimal runtime in link args, got: {link_args_min_diag}" + ); + + // 5. Check link args for minimal UBSan runtime with CFI recover mode + let link_args_min_recover = rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .print("link-args") + .input("program.rs") + .run() + .stdout_utf8(); + assert!( + link_args_min_recover.contains("rt.ubsan_minimal.") + || link_args_min_recover.contains("rt.ubsan_minimal\""), + "expected ubsan_minimal runtime in link args, got: {link_args_min_recover}" + ); + + // 6. Build and run binary with default CFI (trap mode, no runtime) + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .output("program_default") + .input("program.rs") + .run(); + run_fail("program_default"); + + // 7. Build and run binary with full runtime in diag (abort) mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .output("program_full_diag") + .input("program.rs") + .run(); + run_fail("program_full_diag") + .assert_stderr_contains("runtime error: control flow integrity check for type"); + + // 8. Build and run binary with full runtime in recover mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .output("program_full_recover") + .input("program.rs") + .run(); + run("program_full_recover") + .assert_stderr_contains("runtime error: control flow integrity check for type"); + + // 9. Build and run binary with minimal runtime in diag (abort) mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-diag=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .output("program_min_diag") + .input("program.rs") + .run(); + run_fail("program_min_diag").assert_stderr_contains("ubsan: cfi-check-fail"); + + // 10. Build and run binary with minimal runtime in recover mode + rustc() + .arg("-Clto") + .arg("-Ccodegen-units=1") + .arg("-Ctarget-feature=-crt-static") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Zsanitizer=cfi") + .arg("-Zsanitizer-cfi-recover=true") + .arg("-Zsanitizer-cfi-minimal-runtime=true") + .output("program_min_recover") + .input("program.rs") + .run(); + run("program_min_recover").assert_stderr_contains("ubsan: cfi-check-fail"); +} diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs new file mode 100644 index 0000000000000..21953675684ee --- /dev/null +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs @@ -0,0 +1,38 @@ +// Verifies that calling a function pointer with a mismatched type with CFI +// recovery enabled reports the failure and continues execution. + +//@ revisions: cfi cfi-minimal-runtime +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux +//@ ignore-backends: gcc +//@ [cfi] needs-sanitizer-cfi +//@ [cfi] needs-sanitizer-support +//@ [cfi-minimal-runtime] needs-sanitizer-cfi +//@ [cfi-minimal-runtime] needs-sanitizer-support +//@ compile-flags: -C target-feature=-crt-static +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C opt-level=0 -C codegen-units=1 -C lto +//@ compile-flags: -C prefer-dynamic=off +//@ compile-flags: -Z sanitizer=cfi +//@ [cfi] compile-flags: -Z sanitizer-cfi-recover=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-recover=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-minimal-runtime=true +//@ run-pass + +use std::hint::black_box; +use std::mem; + +fn add_one(x: i32) -> i32 { + x + 1 +} + +#[inline(never)] +fn call_with_mismatch(f: fn(i32) -> i32) { + let g: fn(i32, i32) -> i32 = unsafe { mem::transmute(f) }; + let res = g(1, 2); + assert_eq!(res, 2); +} + +fn main() { + call_with_mismatch(black_box(add_one)); +} diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs index 6fe7eec7c6920..d64f6c1f43965 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs @@ -1,12 +1,14 @@ // Verifies that calling a function pointer with a mismatched type triggers a // CFI violation and causes the process to trap. -//@ revisions: cfi kcfi +//@ revisions: cfi cfi-minimal-runtime kcfi // FIXME(#122848) Remove only-linux once OSX CFI binaries work //@ only-linux //@ ignore-backends: gcc //@ [cfi] needs-sanitizer-cfi //@ [cfi] needs-sanitizer-support +//@ [cfi-minimal-runtime] needs-sanitizer-cfi +//@ [cfi-minimal-runtime] needs-sanitizer-support //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static //@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer @@ -14,6 +16,11 @@ //@ [cfi] compile-flags: -C prefer-dynamic=off //@ [cfi] compile-flags: -Z sanitizer=cfi //@ [cfi] compile-flags: -Z sanitizer-cfi-diag=true +//@ [cfi-minimal-runtime] compile-flags: -C opt-level=0 -C codegen-units=1 -C lto +//@ [cfi-minimal-runtime] compile-flags: -C prefer-dynamic=off +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer=cfi +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-diag=true +//@ [cfi-minimal-runtime] compile-flags: -Z sanitizer-cfi-minimal-runtime=true //@ [kcfi] compile-flags: -Z sanitizer=kcfi //@ [kcfi] compile-flags: -C panic=abort -C prefer-dynamic=off //@ run-fail-or-crash diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs new file mode 100644 index 0000000000000..f241598131d65 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -0,0 +1,11 @@ +// Verifies that `-Zsanitizer-cfi-minimal-runtime` requires +// `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr new file mode 100644 index 0000000000000..f3d483bef7eb7 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.stderr @@ -0,0 +1,4 @@ +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` + +error: aborting due to 1 previous error + From 4d68be3d806fd0894977dea0a5758800cab25ac6 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Thu, 10 Sep 2026 14:11:10 +0000 Subject: [PATCH 0516/1309] minor cleanup for minimal runtime test --- .../cfi/minimal-runtime-requires-cfi-recover-or-diag.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs index f241598131d65..cbc0bac40c2b3 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -2,7 +2,7 @@ // `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. // //@ needs-sanitizer-cfi -//@ compile-flags: -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![no_core] From 855d8a275b860bf5bb6d0a2499278a90a8d1b547 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Thu, 10 Sep 2026 14:42:35 +0000 Subject: [PATCH 0517/1309] Add target modifier for -Zsanitizer-cfi-minimal-runtime Co-Authored-By: Bastian Kersting --- compiler/rustc_session/src/options.rs | 22 ++++++++++++++++++- .../auxiliary/cfi-minimal-runtime.rs | 7 ++++++ .../sanitizer-cfi-minimal-runtime.rs | 18 +++++++++++++++ ...izer-cfi-minimal-runtime.wrong_flag.stderr | 9 ++++++++ ...cfi-minimal-runtime.wrong_sanitizer.stderr | 9 ++++++++ 5 files changed, 64 insertions(+), 1 deletion(-) create mode 100644 tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr create mode 100644 tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index f11bdadf5b67d..63bc2da30f063 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -136,6 +136,21 @@ mod target_modifier_consistency_check { } true } + pub(super) fn sanitizer_cfi_minimal_runtime( + sess: &Session, + l: &TargetModifier, + r: Option<&TargetModifier>, + ) -> bool { + // For CFI, the helper flag -Zsanitizer-cfi-minimal-runtime should also be a target modifier + if sess.sanitizers().contains(SanitizerSet::CFI) { + if let Some(r) = r { + return l.extend().tech_value == r.extend().tech_value; + } else { + return false; + } + } + true + } pub(super) fn target_cpu( sess: &Session, l: &TargetModifier, @@ -178,6 +193,11 @@ impl TargetModifier { sess, self, other, ); } + UnstableOptionsTargetModifiers::SanitizerCfiMinimalRuntime => { + return target_modifier_consistency_check::sanitizer_cfi_minimal_runtime( + sess, self, other, + ); + } _ => {} }, OptionsTargetModifiers::CodegenOptions(codegen) => match codegen { @@ -2825,7 +2845,7 @@ written to standard error output)"), "enable CFI diagnostics (default: no)"), sanitizer_cfi_recover: Option = (None, parse_opt_bool, [TRACKED], "enable CFI recovery (default: no)"), - sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED], + sanitizer_cfi_minimal_runtime: Option = (None, parse_opt_bool, [TRACKED] { TARGET_MODIFIER: SanitizerCfiMinimalRuntime }, "enable minimal UBSan runtime for CFI (default: no)"), sanitizer_dataflow_abilist: Vec = (Vec::new(), parse_comma_list, [TRACKED], "additional ABI list files that control how shadow parameters are passed (comma separated)"), diff --git a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs new file mode 100644 index 0000000000000..aacea1ee65dd2 --- /dev/null +++ b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs @@ -0,0 +1,7 @@ +//@ no-prefer-dynamic +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs new file mode 100644 index 0000000000000..45c6ad7b521a3 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs @@ -0,0 +1,18 @@ +// For CFI, the helper flag -Zsanitizer-cfi-minimal-runtime should also be a target modifier. + +//@ needs-sanitizer-cfi +//@ aux-build:cfi-minimal-runtime.rs + +//@ revisions: ok wrong_flag wrong_sanitizer +//@[ok] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime +//@[wrong_flag] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover +//@[ok] check-pass + +#![feature(no_core)] +#![crate_type = "rlib"] +#![no_core] + +extern crate cfi_minimal_runtime; + +//[wrong_flag]~? ERROR mixing `-Zsanitizer-cfi-minimal-runtime` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` +//[wrong_sanitizer]~? ERROR mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr new file mode 100644 index 0000000000000..6dfc1a3bb7d16 --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_flag.stderr @@ -0,0 +1,9 @@ +error: mixing `-Zsanitizer-cfi-minimal-runtime` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` + | + = help: the `-Zsanitizer-cfi-minimal-runtime` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer-cfi-minimal-runtime` is unset in this crate which is incompatible with `-Zsanitizer-cfi-minimal-runtime` being set in dependency `cfi_minimal_runtime` + = help: set `-Zsanitizer-cfi-minimal-runtime` in this crate or unset `-Zsanitizer-cfi-minimal-runtime` in `cfi_minimal_runtime` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer-cfi-minimal-runtime` to silence this error + +error: aborting due to 1 previous error + diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr new file mode 100644 index 0000000000000..32ba848b3b2ad --- /dev/null +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.wrong_sanitizer.stderr @@ -0,0 +1,9 @@ +error: mixing `-Zsanitizer` will cause an ABI mismatch in crate `sanitizer_cfi_minimal_runtime` + | + = help: the `-Zsanitizer` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely + = note: `-Zsanitizer` is unset in this crate which is incompatible with `-Zsanitizer=cfi` in dependency `cfi_minimal_runtime` + = help: set `-Zsanitizer=cfi` in this crate or unset `-Zsanitizer` in `cfi_minimal_runtime` + = help: if you are sure this will not cause problems, you may use `-Cunsafe-allow-abi-mismatch=sanitizer` to silence this error + +error: aborting due to 1 previous error + From a42ab2f36cf031d3f95181edc8a613d38c7e00b5 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 08:47:12 +0000 Subject: [PATCH 0518/1309] Make -Zsanitizer-cfi-minimal-runtime also dependent on -Zsanitizer=cfi --- compiler/rustc_session/src/diagnostics.rs | 6 ++++++ compiler/rustc_session/src/session.rs | 3 +++ .../minimal-runtime-requires-cfi-recover-or-diag.rs | 2 +- .../ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs | 11 +++++++++++ .../sanitizer/cfi/minimal-runtime-requires-cfi.stderr | 6 ++++++ 5 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs create mode 100644 tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index d27b616d7e359..b0bbccd7fe91f 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -340,6 +340,12 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; #[diag("`-Zsanitizer-cfi-diag` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiDiagRequiresCfi; +#[derive(Diagnostic)] +#[diag( + "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`" +)] +pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfi; + #[derive(Diagnostic)] #[diag( "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`" diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index bf310270d0a19..a209219758026 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1690,6 +1690,9 @@ fn validate_commandline_args_with_session_available(sess: &Session) { // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. if sess.is_sanitizer_cfi_minimal_runtime_enabled() { + if !sess.is_sanitizer_cfi_enabled() { + sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfi); + } if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); } diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs index cbc0bac40c2b3..16f39f09ec7a0 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi-recover-or-diag.rs @@ -2,7 +2,7 @@ // `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag`. // //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![no_core] diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs new file mode 100644 index 0000000000000..13b296b4329ee --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs @@ -0,0 +1,11 @@ +// Verifies that `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`. +// +//@ needs-sanitizer-cfi +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer-cfi-minimal-runtime + +#![feature(no_core)] +#![no_core] +#![no_main] + +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` +//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr new file mode 100644 index 0000000000000..251d0d0817631 --- /dev/null +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr @@ -0,0 +1,6 @@ +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` + +error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` + +error: aborting due to 2 previous errors + From bba4a3f986f4e2d4b0bea8711c436bf3ffe4a92a Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 09:00:38 +0000 Subject: [PATCH 0519/1309] Fix tests with new cfi-minimal-runtime target modifier --- tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs | 2 +- tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs index 21953675684ee..069ac811f481d 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch-recover.rs @@ -10,7 +10,7 @@ //@ [cfi-minimal-runtime] needs-sanitizer-cfi //@ [cfi-minimal-runtime] needs-sanitizer-support //@ compile-flags: -C target-feature=-crt-static -//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ compile-flags: -C opt-level=0 -C codegen-units=1 -C lto //@ compile-flags: -C prefer-dynamic=off //@ compile-flags: -Z sanitizer=cfi diff --git a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs index d64f6c1f43965..1e32a1042c848 100644 --- a/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs +++ b/tests/ui/sanitizer/cfi/fn-ptr-type-mismatch.rs @@ -11,7 +11,7 @@ //@ [cfi-minimal-runtime] needs-sanitizer-support //@ [kcfi] needs-sanitizer-kcfi //@ compile-flags: -C target-feature=-crt-static -//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi] compile-flags: -C opt-level=0 -C codegen-units=1 -C lto //@ [cfi] compile-flags: -C prefer-dynamic=off //@ [cfi] compile-flags: -Z sanitizer=cfi From 775c187f3add8c381e818575687df32c01abf92a Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 09:37:04 +0000 Subject: [PATCH 0520/1309] Fix linter issue in diagnostics.rs --- compiler/rustc_session/src/diagnostics.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/compiler/rustc_session/src/diagnostics.rs b/compiler/rustc_session/src/diagnostics.rs index b0bbccd7fe91f..0ec847767336e 100644 --- a/compiler/rustc_session/src/diagnostics.rs +++ b/compiler/rustc_session/src/diagnostics.rs @@ -341,9 +341,7 @@ pub(crate) struct SanitizerCfiRecoverRequiresCfi; pub(crate) struct SanitizerCfiDiagRequiresCfi; #[derive(Diagnostic)] -#[diag( - "`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`" -)] +#[diag("`-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi`")] pub(crate) struct SanitizerCfiMinimalRuntimeRequiresCfi; #[derive(Diagnostic)] From 3058339f0e35413263d71e595a8bb1421646edd3 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 10:53:13 +0000 Subject: [PATCH 0521/1309] Fix broken test introduced by cfi-minimal-runtime target modifier --- .../sanitizer/cfi/emit-type-checks-diag-mode.rs | 2 +- .../sanitizer/cfi/emit-type-checks-recover-mode.rs | 2 +- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 8 ++++---- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs index 96cfb94289724..4d58872db7c45 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-diag-mode.rs @@ -2,7 +2,7 @@ // //@ revisions: cfi-diag cfi-diag-minimal-runtime //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-diag=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi-diag-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] diff --git a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs index b3a1e2cb0b02e..3ea97e44c21e7 100644 --- a/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs +++ b/tests/codegen-llvm/sanitizer/cfi/emit-type-checks-recover-mode.rs @@ -2,7 +2,7 @@ // //@ revisions: cfi-recover cfi-recover-minimal-runtime //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer +//@ compile-flags: -Clto -Cno-prepopulate-passes -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover=true -Copt-level=0 -C unsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime //@ [cfi-recover-minimal-runtime] compile-flags: -Zsanitizer-cfi-minimal-runtime=true #![crate_type = "lib"] diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index adb739e43c341..8e92f5927d952 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -68,7 +68,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-diag=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -87,7 +87,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-recover=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -146,7 +146,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-diag=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") @@ -160,7 +160,7 @@ fn main() { .arg("-Clto") .arg("-Ccodegen-units=1") .arg("-Ctarget-feature=-crt-static") - .arg("-Cunsafe-allow-abi-mismatch=sanitizer") + .arg("-Cunsafe-allow-abi-mismatch=sanitizer,sanitizer-cfi-minimal-runtime") .arg("-Zsanitizer=cfi") .arg("-Zsanitizer-cfi-recover=true") .arg("-Zsanitizer-cfi-minimal-runtime=true") From 7aacc8a2dab9300860afc1d912193e490ceeb5a1 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 11 Sep 2026 12:05:31 +0000 Subject: [PATCH 0522/1309] Skip gcc for CFI runtime tests --- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index 8e92f5927d952..3cad996a14054 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -1,5 +1,6 @@ //@ needs-sanitizer-support //@ needs-sanitizer-cfi +//@ ignore-backends: gcc use run_make_support::{run, run_fail, rustc}; From 1e9b3bccbbcb3c0f298e59422c331cab092f03d0 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 12:03:07 +0200 Subject: [PATCH 0523/1309] normalize normalizes, avoid next-solver hack --- compiler/rustc_hir_typeck/src/closure.rs | 40 ++---------------------- 1 file changed, 2 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 22349259b32a6..26277089bcc91 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -385,44 +385,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } - // Don't infer a closure signature from a goal that names the closure type as this will - // (almost always) lead to occurs check errors later in type checking. - if self.next_trait_solver() - && let Some(inferred_sig) = inferred_sig - { - // In the new solver it is difficult to explicitly normalize the inferred signature as we - // would have to manually handle universes and rewriting bound vars and placeholders back - // and forth. - // - // Instead we take advantage of the fact that we relating an inference variable with an alias - // will only instantiate the variable if the alias is rigid(*not quite). Concretely we: - // - Create some new variable `?sig` - // - Equate `?sig` with the unnormalized signature, e.g. `fn( as Trait>::Assoc)` - // - Depending on whether ` as Trait>::Assoc` is rigid, ambiguous or normalizeable, - // we will either wind up with `?sig= as Trait>::Assoc/?y/ConcreteTy` respectively. - // - // *: In cases where there are ambiguous aliases in the signature that make use of bound vars - // they will wind up present in `?sig` even though they are non-rigid. - // - // This is a bit weird and means we may wind up discarding the goal due to it naming `expected_ty` - // even though the normalized form may not name `expected_ty`. However, this matches the existing - // behaviour of the old solver and would be technically a breaking change to fix. - let generalized_fnptr_sig = self.next_ty_var(span); - let inferred_fnptr_sig = Ty::new_fn_ptr(self.tcx, inferred_sig.sig); - self.demand_eqtype(span, inferred_fnptr_sig, generalized_fnptr_sig); - - let resolved_sig = self.deeply_resolve_ignoring_regions(generalized_fnptr_sig); - - if resolved_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { - expected_sig = Some(ExpectedSig { - cause_span: inferred_sig.cause_span, - sig: resolved_sig.fn_sig(self.tcx), - }); - } - } else { - if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { - expected_sig = inferred_sig; - } + if inferred_sig.visit_with(&mut MentionsTy { expected_ty }).is_continue() { + expected_sig = inferred_sig; } } From 5abfe0f550231cd3020fe2931833e88b9c80747c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sun, 20 Sep 2026 20:09:15 +0200 Subject: [PATCH 0524/1309] Add a README in `tests/rustdoc-html` to explain what each folder content is for --- tests/rustdoc-html/README.md | 154 +++++++++++++++++++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 tests/rustdoc-html/README.md diff --git a/tests/rustdoc-html/README.md b/tests/rustdoc-html/README.md new file mode 100644 index 0000000000000..4acb1d54bbb89 --- /dev/null +++ b/tests/rustdoc-html/README.md @@ -0,0 +1,154 @@ +# rustdoc HTML test suite categories + +This is a high-level summary of the organization of the rustdoc HTML test suite +(`tests/rustdoc-html`). It is not intended to be *prescriptive*, but instead provide a quick survey +of existing groupings. + +For now, only immediate subdirectories under `tests/rustdoc-html` are described. + +## `tests/rustdoc-html/anchors` + +Check for the link anchors. Rustdoc uses anchors when we want to point an element on an item +page, like the method of a type. + +## `tests/rustdoc-html/assoc` + +Contains tests checking how an associated item like a trait method is rendered in the +docs. + +## `tests/rustdoc-html/async` + +Contains tests checking the rendering of `async` items. + +## `tests/rustdoc-html/auto` + +Contains tests related to auto traits implementations. + +## `tests/rustdoc-html/codeblock` + +Contains tests to check the rendering of the code blocks (also called code examples). + +## `tests/rustdoc-html/const-generics` + +Mostly the same as `tests/rustdoc-html/constant` except that this folder focuses on the +rendering of const generics. Same problematics overall. + +## `tests/rustdoc-html/constant` + +Contains tests to check constant items rendering. Constant items can sometimes have +code that needs to be kept as is or inferred, making this a very tricky topic in rustdoc. :) + +## `tests/rustdoc-html/cross-crate-info` + +Contains tests to check how information is used across crates. It only contains folders +which all contain an `auxiliary` subfolder for their own dependencies (and avoid potential naming +conflicts, in particular for simpler crate names). + +## `tests/rustdoc-html/deref` + +Contains tests to check the display of items implementing the `Deref` and/or `DerefMut` traits. + +## `tests/rustdoc-html/doc-cfg` + +Contains tests to check the rustdoc `doc_cfg` feature. + +## `tests/rustdoc-html/enum` + +Contains tests for the rendering of enum types and in particular its variants. + +## `tests/rustdoc-html/extern` + +Contains tests to check how extern items (like `extern "C"` functions) are rendered. + +## `tests/rustdoc-html/footnote` + +Contains tests checking the markdown footnote features and how it is rendered. + +## `tests/rustdoc-html/generic-associated-types` + +Contains tests checking the rendering of items when they have generic associated types, +like `Iterator::Item` where `Item` would instead be `Item<'a> where Self: 'a`. Fun times. :) + +## `tests/rustdoc-html/hidden` + +Contains tests checking both `doc(hidden)` and the `--document-hidden-items` CLI flag. + +## `tests/rustdoc-html/impl` + +Contains tests checking the rendering of impl blocks. More general than +`tests/rustdoc-html/generic-associated-types`. + +## `tests/rustdoc-html/inline_cross` + +Contains tests which check inlined foreign items and how they render based on the limitless +list of corner cases we have to handle with reexports. + +## `tests/rustdoc-html/inline_local` + +Similar to `tests/rustdoc-html/inline_cross` except this time it's reexports of local items. +Still a lot of "fun" and dark magic. + +## `tests/rustdoc-html/intra-doc` + +Contains tests which check the intra doc links feature. This feature is very important in +rustdoc as it allows to simply write the name or the path of an item to get its link +generated. It comes with a lot of corner cases around scope and namespaces (illustrated +by the very high number of tests in this folder). + +## `tests/rustdoc-html/jump-to-def` + +This folder contains tests for the "jump to def(inition)" feature which is enabled with the +`--generate-link-to-definition` CLI flag. + +## `tests/rustdoc-html/macro` + +Contains tests checking the rendering of macro items (both `derive` and `macro_rules!`). + +## `tests/rustdoc-html/macro-expansion` + +Contains tests checking the `--generate-macro-expansion` CLI flag. + +## `tests/rustdoc-html/notable-trait` + +Contains tests checking the `doc(notable_trait)` attribute. + +## `tests/rustdoc-html/primitive` + +Everything related to primitive types, like intra-doc links pointing to them, documenting +them with the `rustc_doc_primitive` attribute, reexporting them, etc. + +## `tests/rustdoc-html/private` + +Everything related to non-`doc(hidden)` items which aren't public. Either it's struct/union +fields, impl blocks containing only private items or the handling of the +`--document-private-items` CLI flag. + +## `tests/rustdoc-html/reexport` + +Another folder about reexports (might be worth merging the three of them?). It checks +everything related to reexports like concatenated docs and attributes, inlining, transitive +reexported crates, etc. + +## `tests/rustdoc-html/sidebar` + +Contains tests checking the content of the sidebar like sections or links to items present on the +page, etc. + +## `tests/rustdoc-html/source-code-pages` + +Contains tests checking the content of the source code pages (when you click on the `source` +links). + +## `tests/rustdoc-html/synthetic_auto` + +Somewhat equivalent to the `auto` folder's tests. Both should likely be merged. + +## `tests/rustdoc-html/typedef` + +Contains tests checking type aliases (`type X = Y`) rendering. In particular when the +alias contains generics, meaning a specialized aliased type, allowing in some cases +more auto traits implementations. + +## `tests/rustdoc-html/union` + +Same as `tests/rustdoc-html/enum` but for union items. From 93bcb0f22214f621dae3d2849431f57c381e0d35 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Sep 2026 12:22:34 +0200 Subject: [PATCH 0525/1309] Add tidy check for `rustdoc-html/README.md` --- src/tools/tidy/src/lib.rs | 1 + src/tools/tidy/src/main.rs | 1 + src/tools/tidy/src/rustdoc_html_tests.rs | 77 ++++++++++++++++++++++++ 3 files changed, 79 insertions(+) create mode 100644 src/tools/tidy/src/rustdoc_html_tests.rs diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs index 292808b90cbfc..9975570fa17fc 100644 --- a/src/tools/tidy/src/lib.rs +++ b/src/tools/tidy/src/lib.rs @@ -121,6 +121,7 @@ pub mod mir_opt_tests; pub mod pal; pub mod rustdoc_css_themes; pub mod rustdoc_gui_tests; +pub mod rustdoc_html_tests; pub mod rustdoc_json; pub mod rustdoc_templates; pub mod style; diff --git a/src/tools/tidy/src/main.rs b/src/tools/tidy/src/main.rs index 1b5baf2a21972..c77ef00be9eaf 100644 --- a/src/tools/tidy/src/main.rs +++ b/src/tools/tidy/src/main.rs @@ -102,6 +102,7 @@ fn main() { check!(rustdoc_css_themes, &librustdoc_path); check!(rustdoc_templates, &librustdoc_path); check!(rustdoc_json, &src_path); + check!(rustdoc_html_tests, &tests_path); check!(known_bug, &crashes_path); check!(unknown_revision, &tests_path); diff --git a/src/tools/tidy/src/rustdoc_html_tests.rs b/src/tools/tidy/src/rustdoc_html_tests.rs new file mode 100644 index 0000000000000..1cb7cd3efb584 --- /dev/null +++ b/src/tools/tidy/src/rustdoc_html_tests.rs @@ -0,0 +1,77 @@ +//! Tidy check to ensure that rustdoc GUI tests start with a small description. + +use std::collections::BTreeSet; +use std::path::Path; + +use crate::diagnostics::{CheckId, TidyCtx}; + +pub fn check(path: &Path, tidy_ctx: TidyCtx) { + let path = path.join("rustdoc-html"); + let mut check = tidy_ctx.start_check(CheckId::new("rustdoc_html_tests").path(&path)); + + // The list of subdirectories in rustdoc-html tests. + // Compare previous subdirectory with current subdirectory + // to sync with `tests/rustdoc-html/README.md`. + let mut prev_line = String::new(); + let documented_subdirs: BTreeSet<_> = include_str!("../../../../tests/rustdoc-html/README.md") + .lines() + .filter_map(|line| { + static_regex!(r"^##.*?`(?

[^`]+)`").captures(line).map(|cap| { + let dir = &cap["dir"]; + // FIXME(reddevilmidzy) normalize subdirs title in tests/rustdoc-html/README.md + if dir.ends_with('/') { + dir.strip_suffix('/').unwrap().to_string() + } else { + dir.to_string() + } + }) + }) + .inspect(|line| { + if prev_line.as_str() > line.as_str() { + check.error(&format!( + "`tests/rustdoc-html/README.md` is not in order: {prev_line:?} should be after {line:?}" + )); + } + + prev_line = line.clone(); + }) + .collect(); + + let filesystem_subdirs = collect_rustdoc_html_tests_subdirs(&path); + let is_modified = !filesystem_subdirs.eq(&documented_subdirs); + + if is_modified { + for directory in documented_subdirs.symmetric_difference(&filesystem_subdirs) { + if documented_subdirs.contains(directory) { + check.error(format!( + "rustdoc-html subdirectory `{directory}` is listed in `tests/rustdoc-html/README.md` but does not exist in the filesystem" + )); + } else { + check.error(format!( + "rustdoc-html subdirectory `{directory}` exists in the filesystem but is not documented in `tests/rustdoc-html/README.md`" + )); + } + } + check.error( + "`tests/rustdoc-html/README.md` subdirectory listing is out of sync with the filesystem. \ + Please add or remove subdirectory entries (## headers with backtick-wrapped names) to match the actual directories in `tests/rustdoc-html/`" + ); + } +} + +fn collect_rustdoc_html_tests_subdirs(path: &Path) -> BTreeSet { + let entries = std::fs::read_dir(path).unwrap(); + + entries + .filter_map(|entry| entry.ok()) + .map(|entry| entry.path()) + .filter(|path| path.is_dir() && path.file_name().is_some_and(|name| name != "auxiliary")) + .map(|dir_path| { + let dir_path = dir_path.strip_prefix(path).unwrap(); + format!( + "tests/rustdoc-html/{}", + dir_path.to_string_lossy().replace(std::path::MAIN_SEPARATOR_STR, "/") + ) + }) + .collect() +} From dddede5a8b0d0973da41559d0e818f2f48337201 Mon Sep 17 00:00:00 2001 From: zakrad <49591476+zakrad@users.noreply.github.com> Date: Mon, 21 Sep 2026 14:30:40 +0330 Subject: [PATCH 0526/1309] Add regression test for hang on mutually recursive trait impls --- ...recursive-impls-hang-143018.current.stderr | 9 ++++++ ...ly-recursive-impls-hang-143018.next.stderr | 15 ++++++++++ .../mutually-recursive-impls-hang-143018.rs | 29 +++++++++++++++++++ 3 files changed, 53 insertions(+) create mode 100644 tests/ui/traits/mutually-recursive-impls-hang-143018.current.stderr create mode 100644 tests/ui/traits/mutually-recursive-impls-hang-143018.next.stderr create mode 100644 tests/ui/traits/mutually-recursive-impls-hang-143018.rs diff --git a/tests/ui/traits/mutually-recursive-impls-hang-143018.current.stderr b/tests/ui/traits/mutually-recursive-impls-hang-143018.current.stderr new file mode 100644 index 0000000000000..c6410d7eac39c --- /dev/null +++ b/tests/ui/traits/mutually-recursive-impls-hang-143018.current.stderr @@ -0,0 +1,9 @@ +error[E0282]: type annotations needed + --> $DIR/mutually-recursive-impls-hang-143018.rs:26:5 + | +LL | impls_trait::(); + | ^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/traits/mutually-recursive-impls-hang-143018.next.stderr b/tests/ui/traits/mutually-recursive-impls-hang-143018.next.stderr new file mode 100644 index 0000000000000..680182b7350c8 --- /dev/null +++ b/tests/ui/traits/mutually-recursive-impls-hang-143018.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `A: Trait<_>` + --> $DIR/mutually-recursive-impls-hang-143018.rs:26:19 + | +LL | impls_trait::(); + | ^ + | +note: required by a bound in `impls_trait` + --> $DIR/mutually-recursive-impls-hang-143018.rs:24:19 + | +LL | fn impls_trait, V>() {} + | ^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/mutually-recursive-impls-hang-143018.rs b/tests/ui/traits/mutually-recursive-impls-hang-143018.rs new file mode 100644 index 0000000000000..8db92502a8621 --- /dev/null +++ b/tests/ui/traits/mutually-recursive-impls-hang-143018.rs @@ -0,0 +1,29 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// Regression test for . + +trait Trait {} +struct A; +struct B; + +impl Trait for A +where + A: Trait, + B: Trait, +{ +} + +impl Trait for B +where + A: Trait, +{ +} + +fn impls_trait, V>() {} +fn main() { + impls_trait::(); + //[current]~^ ERROR type annotations needed + //[next]~^^ ERROR overflow evaluating the requirement +} From 5e86855354b3dde36c3de271cf600ce6b9d7e46d Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Mon, 21 Sep 2026 17:13:27 +0600 Subject: [PATCH 0527/1309] emit the constant pattern note for raw identifier bindings `is_const_pat_that_looks_like_binding` matched the pattern snippet against a plain identifier so the `#` in `let r#x = 0` rejected it and the binding lost both the label pointing at `const x` and the `introduce a variable instead` suggestion. strip a leading `r#` before the check and render the const name with `to_ident_string` in the label so a keyword name prints as `r#fn`. fixes https://github.com/rust-lang/rust/issues/162949 --- .../src/thir/pattern/check_match.rs | 15 ++++-- tests/ui/consts/const-pattern-irrefutable.rs | 14 ++++++ .../consts/const-pattern-irrefutable.stderr | 48 ++++++++++++++++--- 3 files changed, 67 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 3414ee751585c..5b4f7a79d4bac 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -678,10 +678,13 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { if let Some(def_id) = is_const_pat_that_looks_like_binding(self.tcx, pat) { let span = self.tcx.def_span(def_id); - let variable = self.tcx.item_name(def_id).to_string(); + let name = self.tcx.item_name(def_id); // When we encounter a constant as the binding name, point at the `const` definition. - interpreted_as_const = Some(InterpretedAsConst { span, variable: variable.clone() }); - interpreted_as_const_sugg = Some(InterpretedAsConstSugg { span: pat.span, variable }); + interpreted_as_const = + Some(InterpretedAsConst { span, variable: name.to_ident_string() }); + // The suggested name is suffixed, so it is never a keyword and never needs `r#`. + interpreted_as_const_sugg = + Some(InterpretedAsConstSugg { span: pat.span, variable: name.to_string() }); } else if let PatKind::Constant { .. } = pat.kind && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span) { @@ -1231,7 +1234,11 @@ fn is_const_pat_that_looks_like_binding<'tcx>(tcx: TyCtxt<'tcx>, pat: &Pat<'tcx> // `::` namespace separators or other non-identifier characters. if let ty::AliasConstKind::Free { def_id } = pat.extra.as_deref()?.expanded_const? && let Ok(snippet) = tcx.sess.source_map().span_to_snippet(pat.span) - && snippet.chars().all(|c| c.is_alphanumeric() || c == '_') + && snippet + .strip_prefix("r#") + .unwrap_or(&snippet) + .chars() + .all(|c| c.is_alphanumeric() || c == '_') { Some(def_id) } else { diff --git a/tests/ui/consts/const-pattern-irrefutable.rs b/tests/ui/consts/const-pattern-irrefutable.rs index e131fd27d532c..f0f5fc90d5195 100644 --- a/tests/ui/consts/const-pattern-irrefutable.rs +++ b/tests/ui/consts/const-pattern-irrefutable.rs @@ -13,6 +13,12 @@ use foo::d; const a: u8 = 2; //~^ NOTE missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable +const g: u8 = 2; +//~^ NOTE missing patterns are not covered because `g` is interpreted as a constant pattern, not a new variable + +const r#fn: u8 = 2; +//~^ NOTE missing patterns are not covered because `r#fn` is interpreted as a constant pattern, not a new variable + #[derive(PartialEq)] struct S { foo: u8, @@ -41,5 +47,13 @@ fn main() { //~| HELP introduce a variable instead foo: 1, }; + let r#g = 4; + //~^ ERROR refutable pattern in local binding + //~| NOTE patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + //~| HELP introduce a variable instead + let r#fn = 4; + //~^ ERROR refutable pattern in local binding + //~| NOTE patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + //~| HELP introduce a variable instead fn f() {} // Check that the `NOTE`s still work with an item here (cf. issue #35115). } diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr index f52ebc313339c..a59b17e41c799 100644 --- a/tests/ui/consts/const-pattern-irrefutable.stderr +++ b/tests/ui/consts/const-pattern-irrefutable.stderr @@ -1,5 +1,5 @@ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:26:9 + --> $DIR/const-pattern-irrefutable.rs:32:9 | LL | const a: u8 = 2; | ----------- missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable @@ -16,7 +16,7 @@ LL | let a_var = 4; | ++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:30:9 + --> $DIR/const-pattern-irrefutable.rs:36:9 | LL | pub const b: u8 = 2; | --------------- missing patterns are not covered because `b` is interpreted as a constant pattern, not a new variable @@ -34,7 +34,7 @@ LL + let b_var = 4; | error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:34:9 + --> $DIR/const-pattern-irrefutable.rs:40:9 | LL | pub const d: (u8, u8) = (2, 1); | --------------------- missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable @@ -51,7 +51,7 @@ LL | let d_var = (4, 4); | ++++ error[E0005]: refutable pattern in local binding - --> $DIR/const-pattern-irrefutable.rs:38:9 + --> $DIR/const-pattern-irrefutable.rs:44:9 | LL | const e: S = S { | ---------- missing patterns are not covered because `e` is interpreted as a constant pattern, not a new variable @@ -62,7 +62,7 @@ LL | let e = S { = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html note: `S` defined here - --> $DIR/const-pattern-irrefutable.rs:17:8 + --> $DIR/const-pattern-irrefutable.rs:23:8 | LL | struct S { | ^ @@ -72,6 +72,42 @@ help: introduce a variable instead LL | let e_var = S { | ++++ -error: aborting due to 4 previous errors +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:50:9 + | +LL | const g: u8 = 2; + | ----------- missing patterns are not covered because `g` is interpreted as a constant pattern, not a new variable +... +LL | let r#g = 4; + | ^^^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html + = note: the matched value is of type `u8` +help: introduce a variable instead + | +LL - let r#g = 4; +LL + let g_var = 4; + | + +error[E0005]: refutable pattern in local binding + --> $DIR/const-pattern-irrefutable.rs:54:9 + | +LL | const r#fn: u8 = 2; + | -------------- missing patterns are not covered because `r#fn` is interpreted as a constant pattern, not a new variable +... +LL | let r#fn = 4; + | ^^^^ patterns `0_u8..=1_u8` and `3_u8..=u8::MAX` not covered + | + = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant + = note: for more information, visit https://doc.rust-lang.org/book/ch19-02-refutability.html + = note: the matched value is of type `u8` +help: introduce a variable instead + | +LL - let r#fn = 4; +LL + let fn_var = 4; + | + +error: aborting due to 6 previous errors For more information about this error, try `rustc --explain E0005`. From 8e5ad6c1e4d2590797636dd5c8e7049e002b3b39 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Mon, 21 Sep 2026 11:14:06 +0000 Subject: [PATCH 0528/1309] use match to determine correct ubsan cfi handler --- compiler/rustc_codegen_llvm/src/builder.rs | 17 +++++------------ 1 file changed, 5 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 438accb85f377..7fa079a01a6b1 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2078,18 +2078,11 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { ) }; let ubsan_handler = self.declare_cfn( - if is_recover { - if is_minimal { - "__ubsan_handle_cfi_check_fail_minimal" - } else { - "__ubsan_handle_cfi_check_fail" - } - } else { - if is_minimal { - "__ubsan_handle_cfi_check_fail_minimal_abort" - } else { - "__ubsan_handle_cfi_check_fail_abort" - } + match (is_minimal, is_recover) { + (true, true) => "__ubsan_handle_cfi_check_fail_minimal", + (true, false) => "__ubsan_handle_cfi_check_fail_minimal_abort", + (false, true) => "__ubsan_handle_cfi_check_fail", + (false, false) => "__ubsan_handle_cfi_check_fail_abort", }, llvm::UnnamedAddr::Global, fty, From 919170b08cc014c8e85709dd80efeed2bac74562 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 12:24:34 +0200 Subject: [PATCH 0529/1309] remove unnecessary restriction with next-solver --- .../src/region_infer/opaque_types/mod.rs | 55 +++++++++---------- ...tderr => lifetime_mismatch.current.stderr} | 8 +-- .../lifetime_mismatch.rs | 7 ++- ...f-uses-in-one-fn-lifetimes.current.stderr} | 4 +- .../multiple-def-uses-in-one-fn-lifetimes.rs | 5 +- 5 files changed, 42 insertions(+), 37 deletions(-) rename tests/ui/type-alias-impl-trait/{lifetime_mismatch.stderr => lifetime_mismatch.current.stderr} (84%) rename tests/ui/type-alias-impl-trait/{multiple-def-uses-in-one-fn-lifetimes.stderr => multiple-def-uses-in-one-fn-lifetimes.current.stderr} (78%) diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index ad15c5750b092..069f6b598e19c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -362,11 +362,11 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>( DefinitionSiteHiddenType::new_error(tcx, guar) }); - // Sometimes, when the hidden type is an inference variable, it can happen that - // the hidden type becomes the opaque type itself. In this case, this was an opaque - // usage of the opaque type and we can ignore it. This check is mirrored in typeck's - // writeback. if !rcx.infcx.tcx.use_typing_mode_post_typeck_until_borrowck() { + // Sometimes, when the hidden type is an inference variable, it can happen that + // the hidden type becomes the opaque type itself. In this case, this was an opaque + // usage of the opaque type and we can ignore it. This check is mirrored in typeck's + // writeback. if let &ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, args, .. }) = hidden_type.ty.skip_binder().kind() && def_id == opaque_type_key.def_id.to_def_id() @@ -374,32 +374,31 @@ fn compute_definition_site_hidden_types_from_defining_uses<'tcx>( { continue; } - } - // Check that all opaque types have the same region parameters if they have the same - // non-region parameters. This is necessary because within the new solver we perform - // various query operations modulo regions, and thus could unsoundly select some impls - // that don't hold. - // - // FIXME(-Znext-solver): This isn't necessary after all. We can remove this check again. - if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert( - rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key), - (opaque_type_key, hidden_type.span), - ) && let Some((arg1, arg2)) = std::iter::zip( - prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg), - opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg), - ) - .find(|(arg1, arg2)| arg1 != arg2) - { - errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam( - LifetimeMismatchOpaqueParam { - arg: arg1, - prev: arg2, - span: prev_span, - prev_span: hidden_type.span, - }, - )); + // Check that all opaque types have the same region parameters if they have the same + // non-region parameters. This is necessary because within the new solver we perform + // various query operations modulo regions, and thus could unsoundly select some impls + // that don't hold. + if let Some((prev_decl_key, prev_span)) = decls_modulo_regions.insert( + rcx.infcx.tcx.erase_and_anonymize_regions(opaque_type_key), + (opaque_type_key, hidden_type.span), + ) && let Some((arg1, arg2)) = std::iter::zip( + prev_decl_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg), + opaque_type_key.iter_captured_args(infcx.tcx).map(|(_, arg)| arg), + ) + .find(|(arg1, arg2)| arg1 != arg2) + { + errors.push(DeferredOpaqueTypeError::LifetimeMismatchOpaqueParam( + LifetimeMismatchOpaqueParam { + arg: arg1, + prev: arg2, + span: prev_span, + prev_span: hidden_type.span, + }, + )); + } } + add_hidden_type(tcx, hidden_types, opaque_type_key.def_id, hidden_type); } } diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr similarity index 84% rename from tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr rename to tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr index 719748edc011f..83ed7ae17902c 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr @@ -1,5 +1,5 @@ error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:7:5 + --> $DIR/lifetime_mismatch.rs:10:5 | LL | (x, y) | ^^^^^^ @@ -8,13 +8,13 @@ LL | (x, y) | lifetime `'b` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:7:5 + --> $DIR/lifetime_mismatch.rs:10:5 | LL | (x, y) | ^^^^^^ error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:15:5 + --> $DIR/lifetime_mismatch.rs:18:5 | LL | (i, j) | ^^^^^^ @@ -23,7 +23,7 @@ LL | (i, j) | lifetime `'y` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:15:5 + --> $DIR/lifetime_mismatch.rs:18:5 | LL | (i, j) | ^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs index b58840718a354..4a8320e922a2e 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver=globally +//@[next] check-pass #![feature(type_alias_impl_trait)] type Foo<'a> = impl Sized; @@ -5,7 +8,7 @@ type Foo<'a> = impl Sized; #[define_opaque(Foo)] fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) { (x, y) - //~^ ERROR opaque type used twice with different lifetimes + //[current]~^ ERROR opaque type used twice with different lifetimes } type Bar<'a, 'b> = impl std::fmt::Debug; @@ -13,7 +16,7 @@ type Bar<'a, 'b> = impl std::fmt::Debug; #[define_opaque(Bar)] fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) { (i, j) - //~^ ERROR opaque type used twice with different lifetimes + //[current]~^ ERROR opaque type used twice with different lifetimes } fn main() { diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr similarity index 78% rename from tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr rename to tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr index 03f2b1c532a00..fb67f6ffa44e4 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr @@ -1,5 +1,5 @@ error: opaque type used twice with different lifetimes - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:7:5 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 | LL | (i, j) | ^^^^^^ @@ -8,7 +8,7 @@ LL | (i, j) | lifetime `'y` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:7:5 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 | LL | (i, j) | ^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs index 39e4912ae3af6..f1c0bc190108b 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -1,3 +1,6 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver=globally +//@[next] check-pass #![feature(type_alias_impl_trait)] type Foo<'a, 'b> = impl std::fmt::Debug; @@ -5,7 +8,7 @@ type Foo<'a, 'b> = impl std::fmt::Debug; #[define_opaque(Foo)] fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) { (i, j) - //~^ ERROR opaque type used twice with different lifetimes + //[current]~^ ERROR opaque type used twice with different lifetimes } fn main() {} From 45490f887a38b04b05e5875cb8dff20a238d4f1d Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Mon, 21 Sep 2026 13:35:23 +0200 Subject: [PATCH 0530/1309] Implement Allocator for Pin unstably --- library/core/src/alloc/mod.rs | 57 +++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 6069c468f96e4..35932b11e3b5f 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -683,6 +683,63 @@ where } } +#[unstable(feature = "allocator_api", issue = "32838")] +#[rustc_const_unstable(feature = "const_heap", issue = "79597")] +#[unstable_feature_bound(allocator_api)] +const unsafe impl

Allocator for core::pin::Pin

Allocator for core::pin::Pin

where P: [const] core::ops::Deref + core::pin::PinSafePointer, @@ -740,13 +742,13 @@ where } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for &A {} // If an allocator is `StaticAllocator` all equivalent allocators must also uphold // its semantics, and references are equivalent to the allocator they reference. -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl StaticAllocator for &A {} -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl StaticAllocator for &mut A {} diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs index 5ec875cf47868..a279c373dea4a 100644 --- a/library/core/src/ptr/non_null.rs +++ b/library/core/src/ptr/non_null.rs @@ -1559,7 +1559,7 @@ impl NonNull<[T]> { /// # Examples /// /// ```rust - /// #![feature(allocator_api, ptr_as_uninit)] + /// #![feature(ptr_as_uninit)] /// /// use std::alloc::{Allocator, Layout, Global}; /// use std::mem::MaybeUninit; diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 8e0143c137b5e..c6f94944006c9 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -145,10 +145,10 @@ use crate::{hint, mem, ptr}; #[derive_const(Clone, Default)] pub struct System; -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl core::alloc::AllocatorClone for System {} -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl core::alloc::StaticAllocator for System {} impl System { @@ -216,7 +216,7 @@ impl System { // The Allocator impl checks the layout size to be non-zero and forwards to the // platform functions in `std::sys::*::alloc`. -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] unsafe impl Allocator for System { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { @@ -303,7 +303,7 @@ unsafe impl Allocator for System { } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl GlobalAllocator for System {} static HOOK: AtomicPtr<()> = AtomicPtr::new(ptr::null_mut()); diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs index 121a525bd0c4b..d95fcf38a3b49 100644 --- a/library/std/src/collections/hash/map.rs +++ b/library/std/src/collections/hash/map.rs @@ -246,7 +246,7 @@ pub struct HashMap< K, V, S = RandomState, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::HashMap, } @@ -299,7 +299,7 @@ impl HashMap { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::collections::HashMap; /// use std::alloc::Global; /// @@ -307,7 +307,7 @@ impl HashMap { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_in(alloc: A) -> Self { HashMap::with_hasher_in(Default::default(), alloc) } @@ -322,7 +322,7 @@ impl HashMap { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::collections::HashMap; /// use std::alloc::Global; /// @@ -330,7 +330,7 @@ impl HashMap { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { HashMap::with_capacity_and_hasher_in(capacity, Default::default(), alloc) } @@ -418,7 +418,7 @@ impl HashMap { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::alloc::Global; /// use std::collections::HashMap; /// use std::hash::RandomState; @@ -428,7 +428,7 @@ impl HashMap { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_hasher_in(hash_builder: S, alloc: A) -> Self { HashMap { base: base::HashMap::with_hasher_in(hash_builder, alloc) } } @@ -451,7 +451,7 @@ impl HashMap { /// # Examples /// /// ``` - /// #![feature(allocator_api)] + /// #![feature(allocator_ext)] /// use std::alloc::Global; /// use std::collections::HashMap; /// use std::hash::RandomState; @@ -461,7 +461,7 @@ impl HashMap { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_capacity_and_hasher_in(capacity: usize, hash_builder: S, alloc: A) -> Self { HashMap { base: base::HashMap::with_capacity_and_hasher_in(capacity, hash_builder, alloc) } } @@ -1660,7 +1660,7 @@ impl Default for IterMut<'_, K, V> { pub struct IntoIter< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::IntoIter, } @@ -1798,7 +1798,7 @@ pub struct Drain< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::Drain<'a, K, V, A>, } @@ -1835,7 +1835,7 @@ pub struct ExtractIf< K, V, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::ExtractIf<'a, K, V, F, A>, } @@ -1892,7 +1892,7 @@ impl Default for ValuesMut<'_, K, V> { pub struct IntoKeys< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { inner: IntoIter, } @@ -1926,7 +1926,7 @@ impl Default for IntoKeys { pub struct IntoValues< K, V, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { inner: IntoIter, } @@ -1950,7 +1950,7 @@ pub enum Entry< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { /// An occupied entry. #[stable(feature = "rust1", since = "1.0.0")] @@ -1978,7 +1978,7 @@ pub struct OccupiedEntry< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::RustcOccupiedEntry<'a, K, V, A>, } @@ -2000,7 +2000,7 @@ pub struct VacantEntry< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::RustcVacantEntry<'a, K, V, A>, } @@ -2021,7 +2021,7 @@ pub struct OccupiedError< 'a, K: 'a, V: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { /// The entry in the map that was already occupied. pub entry: OccupiedEntry<'a, K, V, A>, diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs index b0a8e8ff42149..ea1307895b7f8 100644 --- a/library/std/src/collections/hash/set.rs +++ b/library/std/src/collections/hash/set.rs @@ -126,7 +126,7 @@ use crate::ops::{BitAnd, BitOr, BitXor, Sub}; pub struct HashSet< T, S = RandomState, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::HashSet, } @@ -179,7 +179,7 @@ impl HashSet { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::alloc::Global; /// use std::collections::HashSet; /// @@ -187,7 +187,7 @@ impl HashSet { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn new_in(alloc: A) -> HashSet { HashSet::with_hasher_in(Default::default(), alloc) } @@ -201,7 +201,7 @@ impl HashSet { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::collections::HashSet; /// use std::alloc::Global; /// @@ -209,7 +209,7 @@ impl HashSet { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_capacity_in(capacity: usize, alloc: A) -> HashSet { HashSet::with_capacity_and_hasher_in(capacity, Default::default(), alloc) } @@ -297,7 +297,7 @@ impl HashSet { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::alloc::Global; /// use std::collections::HashSet; /// use std::hash::RandomState; @@ -307,7 +307,7 @@ impl HashSet { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_hasher_in(hasher: S, alloc: A) -> HashSet { HashSet { base: base::HashSet::with_hasher_in(hasher, alloc) } } @@ -330,7 +330,7 @@ impl HashSet { /// # Examples /// /// ``` - /// # #![feature(allocator_api)] + /// # #![feature(allocator_ext)] /// use std::alloc::Global; /// use std::collections::HashSet; /// use std::hash::RandomState; @@ -340,7 +340,7 @@ impl HashSet { /// ``` #[inline] #[must_use] - #[unstable(feature = "allocator_api", issue = "32838")] + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn with_capacity_and_hasher_in(capacity: usize, hasher: S, alloc: A) -> HashSet { HashSet { base: base::HashSet::with_capacity_and_hasher_in(capacity, hasher, alloc) } } @@ -1468,7 +1468,7 @@ impl Default for Iter<'_, K> { #[stable(feature = "rust1", since = "1.0.0")] pub struct IntoIter< K, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::IntoIter, } @@ -1502,7 +1502,7 @@ impl Default for IntoIter { pub struct Drain< 'a, K: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::Drain<'a, K, A>, } @@ -1529,7 +1529,7 @@ pub struct ExtractIf< 'a, K, F, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::ExtractIf<'a, K, F, A>, } @@ -1558,7 +1558,7 @@ pub struct Intersection< 'a, T: 'a, S: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // iterator of the first set iter: Iter<'a, T>, @@ -1590,7 +1590,7 @@ pub struct Difference< 'a, T: 'a, S: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { // iterator of the first set iter: Iter<'a, T>, @@ -1622,7 +1622,7 @@ pub struct SymmetricDifference< 'a, T: 'a, S: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { iter: Chain, Difference<'a, T, S, A>>, } @@ -1651,7 +1651,7 @@ pub struct Union< 'a, T: 'a, S: 'a, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { iter: Chain, Difference<'a, T, S, A>>, } @@ -2145,7 +2145,7 @@ pub enum Entry< 'a, T, S, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { /// An occupied entry. /// @@ -2237,7 +2237,7 @@ pub struct OccupiedEntry< 'a, T, S, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::OccupiedEntry<'a, T, S, A>, } @@ -2282,7 +2282,7 @@ pub struct VacantEntry< 'a, T, S, - #[unstable(feature = "allocator_api", issue = "32838")] A: Allocator = Global, + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { base: base::VacantEntry<'a, T, S, A>, } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index acc8cdfc8281d..23e30379aefc4 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -399,7 +399,7 @@ // Library features (alloc): // tidy-alphabetical-start #![feature(alloc_io)] -#![feature(allocator_api)] +#![feature(allocator_ext)] #![feature(buf_read_has_data_left)] #![feature(clone_from_ref)] #![feature(get_mut_unchecked)] diff --git a/src/doc/unstable-book/src/library-features/allocator-api.md b/src/doc/unstable-book/src/library-features/allocator-ext.md similarity index 96% rename from src/doc/unstable-book/src/library-features/allocator-api.md rename to src/doc/unstable-book/src/library-features/allocator-ext.md index 9f045ce08a433..f1e7551bdfa08 100644 --- a/src/doc/unstable-book/src/library-features/allocator-api.md +++ b/src/doc/unstable-book/src/library-features/allocator-ext.md @@ -1,4 +1,4 @@ -# `allocator_api` +# `allocator_ext` The tracking issue for this feature is [#32838] diff --git a/src/tools/clippy/tests/ui/vec_box_sized.rs b/src/tools/clippy/tests/ui/vec_box_sized.rs index 5cc140953cecc..3694d32be9eb0 100644 --- a/src/tools/clippy/tests/ui/vec_box_sized.rs +++ b/src/tools/clippy/tests/ui/vec_box_sized.rs @@ -1,7 +1,7 @@ //@no-rustfix #![warn(clippy::vec_box)] -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::{AllocError, Allocator, Layout}; use std::ptr::NonNull; diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs index 35b8e20e56b3c..71e4eadc4e0b8 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler.rs @@ -1,5 +1,5 @@ //@error-in-other-file: aborted -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::*; diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs index 8d41002735cc9..72f45be61b299 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs @@ -1,7 +1,7 @@ //@compile-flags: -Cpanic=abort #![feature(core_intrinsics)] #![feature(alloc_error_handler)] -#![feature(allocator_api)] +#![feature(allocator_ext)] #![no_std] #![no_main] diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs index f73f8e3e7e196..c7c51c95e9c26 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs @@ -1,7 +1,7 @@ //@compile-flags: -Cpanic=abort #![feature(core_intrinsics)] #![feature(alloc_error_handler)] -#![feature(allocator_api)] +#![feature(allocator_ext)] #![no_std] #![no_main] diff --git a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs index bbf069b7a2def..f80ac906fd952 100644 --- a/src/tools/miri/tests/fail/alloc/global_system_mixup.rs +++ b/src/tools/miri/tests/fail/alloc/global_system_mixup.rs @@ -8,7 +8,7 @@ //@normalize-stderr-test: "alloc::[A-Za-z]+::" -> "alloc::PLATFORM::" //@normalize-stderr-test: "alloc/[A-Za-z]+.rs" -> "alloc/PLATFORM.rs" -#![feature(allocator_api, slice_ptr_get)] +#![feature(allocator_ext, slice_ptr_get)] use std::alloc::{Allocator, Global, Layout, System}; diff --git a/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.rs b/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.rs index 5fb81296494e5..cc0bd3fc3a22c 100644 --- a/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.rs +++ b/src/tools/miri/tests/fail/validity/box-custom-alloc-dangling-ptr.rs @@ -1,5 +1,5 @@ //! Ensure that a box with a custom allocator detects when the pointer is dangling. -#![feature(allocator_api)] +#![feature(allocator_ext)] // This should not need the aliasing model. //@compile-flags: -Zmiri-disable-stacked-borrows use std::alloc::Layout; diff --git a/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.rs b/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.rs index 101a550593f90..0ed54d0112dd4 100644 --- a/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.rs +++ b/src/tools/miri/tests/fail/validity/box-custom-alloc-invalid-alloc.rs @@ -1,5 +1,5 @@ //! Ensure that a box with a custom allocator detects when the allocator itself is invalid. -#![feature(allocator_api)] +#![feature(allocator_ext)] // This should not need the aliasing model. //@compile-flags: -Zmiri-disable-stacked-borrows use std::alloc::Layout; diff --git a/src/tools/miri/tests/panic/alloc_error_handler_hook.rs b/src/tools/miri/tests/panic/alloc_error_handler_hook.rs index a1eadb45fd13b..f7516ce86e883 100644 --- a/src/tools/miri/tests/panic/alloc_error_handler_hook.rs +++ b/src/tools/miri/tests/panic/alloc_error_handler_hook.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api, alloc_error_hook)] +#![feature(allocator_ext, alloc_error_hook)] use std::alloc::*; diff --git a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs index ab57ab246b4f3..00b340125b7c3 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc-aliasing.rs @@ -5,7 +5,6 @@ //@revisions: stack tree tree_implicit_writes //@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(allocator_api)] use std::alloc::{AllocError, Allocator, Layout}; use std::cell::{Cell, UnsafeCell}; diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs index 8016cb2c13c0b..21667e1a52be0 100644 --- a/src/tools/miri/tests/pass/box-custom-alloc.rs +++ b/src/tools/miri/tests/pass/box-custom-alloc.rs @@ -1,7 +1,6 @@ //@revisions: stack tree tree_implicit_writes //@[tree_implicit_writes]compile-flags: -Zmiri-tree-borrows -Zmiri-tree-borrows-implicit-writes //@[tree]compile-flags: -Zmiri-tree-borrows -#![feature(allocator_api)] use std::alloc::{AllocError, Allocator, Global, Layout}; use std::cell::Cell; diff --git a/src/tools/miri/tests/pass/global_allocator.rs b/src/tools/miri/tests/pass/global_allocator.rs index ecb3a5e46e3a4..788c58a3c54c0 100644 --- a/src/tools/miri/tests/pass/global_allocator.rs +++ b/src/tools/miri/tests/pass/global_allocator.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api, slice_ptr_get)] +#![feature(slice_ptr_get)] use std::alloc::{Allocator as _, Global, GlobalAlloc, Layout, System}; diff --git a/src/tools/miri/tests/pass/heap_allocator.rs b/src/tools/miri/tests/pass/heap_allocator.rs index 2c38dcb49f1ce..dcd8515ab99f6 100644 --- a/src/tools/miri/tests/pass/heap_allocator.rs +++ b/src/tools/miri/tests/pass/heap_allocator.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api, slice_ptr_get)] +#![feature(slice_ptr_get)] use std::alloc::{Allocator, Global, Layout, System}; use std::ptr::NonNull; diff --git a/tests/incremental/lint-unused-features.rs b/tests/incremental/lint-unused-features.rs index 0bf9730727f74..a3004871aa292 100644 --- a/tests/incremental/lint-unused-features.rs +++ b/tests/incremental/lint-unused-features.rs @@ -10,8 +10,8 @@ // Used library features #![feature(error_iter)] //[bfail]~^ ERROR feature `error_iter` is declared but not used -#![cfg_attr(all(), feature(allocator_api))] -//[bfail]~^ ERROR feature `allocator_api` is declared but not used +#![cfg_attr(all(), feature(allocator_ext))] +//[bfail]~^ ERROR feature `allocator_ext` is declared but not used macro m() {} pub fn use_decl_macro() { @@ -28,8 +28,7 @@ pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) { #[cfg(rpass)] pub fn use_allocator_api() { - use std::alloc::Global; - let _ = Vec::::new_in(Global); + let _a: std::rc::Rc; } fn main() {} diff --git a/tests/mir-opt/box_conditional_drop_allocator.rs b/tests/mir-opt/box_conditional_drop_allocator.rs index 741c396b0c2d7..766c81340f6e8 100644 --- a/tests/mir-opt/box_conditional_drop_allocator.rs +++ b/tests/mir-opt/box_conditional_drop_allocator.rs @@ -1,7 +1,7 @@ //@ skip-filecheck //@ test-mir-pass: ElaborateDrops //@ needs-unwind -#![feature(allocator_api)] +#![feature(allocator_ext)] // Regression test for #131082. // Testing that the allocator of a Box is dropped in conditional drops diff --git a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs index 08347f71b4239..1613b8cb8c2c2 100644 --- a/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs +++ b/tests/mir-opt/pre-codegen/issue_117368_print_invalid_constant.rs @@ -3,7 +3,7 @@ // EMIT_MIR_FOR_EACH_BIT_WIDTH // EMIT_MIR_FOR_EACH_PANIC_STRATEGY -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::{Allocator, Global, Layout}; diff --git a/tests/run-make/std-core-cycle/bar.rs b/tests/run-make/std-core-cycle/bar.rs index 9f5e7c29bddd7..d1a3c5089dddb 100644 --- a/tests/run-make/std-core-cycle/bar.rs +++ b/tests/run-make/std-core-cycle/bar.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api)] +#![feature(allocator_ext)] #![crate_type = "rlib"] use std::alloc::*; diff --git a/tests/ui/README.md b/tests/ui/README.md index 8df2769996f41..27995e0ab4cd5 100644 --- a/tests/ui/README.md +++ b/tests/ui/README.md @@ -18,7 +18,7 @@ See . ## `tests/ui/allocator` -These tests exercise `#![feature(allocator_api)]` and the `#[global_allocator]` attribute. +These tests exercise `#![feature(allocator_ext)]` and the `#[global_allocator]` attribute. See [Allocator traits and `std::heap` #32838](https://github.com/rust-lang/rust/issues/32838). diff --git a/tests/ui/allocator/156920-allocator-clone.rs b/tests/ui/allocator/156920-allocator-clone.rs index 2b9966b68eca8..cf38c1f4b04fe 100644 --- a/tests/ui/allocator/156920-allocator-clone.rs +++ b/tests/ui/allocator/156920-allocator-clone.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::{ alloc::{Allocator, Global, System}, diff --git a/tests/ui/allocator/157089-box-pin-in.rs b/tests/ui/allocator/157089-box-pin-in.rs index 307a933bba6f6..f24092fd66745 100644 --- a/tests/ui/allocator/157089-box-pin-in.rs +++ b/tests/ui/allocator/157089-box-pin-in.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::{ alloc::{AllocError, Allocator, Layout}, diff --git a/tests/ui/allocator/159445-unsize-pin-box.rs b/tests/ui/allocator/159445-unsize-pin-box.rs index 391c8c95813a0..836d938d1d3c6 100644 --- a/tests/ui/allocator/159445-unsize-pin-box.rs +++ b/tests/ui/allocator/159445-unsize-pin-box.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::{ alloc::{AllocError, Allocator, Layout}, diff --git a/tests/ui/allocator/alloc-shrink-oob-read.rs b/tests/ui/allocator/alloc-shrink-oob-read.rs index b9edfca3b7b51..120d327e2a344 100644 --- a/tests/ui/allocator/alloc-shrink-oob-read.rs +++ b/tests/ui/allocator/alloc-shrink-oob-read.rs @@ -4,7 +4,6 @@ //@ run-pass -#![feature(allocator_api)] #![feature(slice_ptr_get)] use std::alloc::{Allocator, Global, Layout, handle_alloc_error}; diff --git a/tests/ui/allocator/auxiliary/custom.rs b/tests/ui/allocator/auxiliary/custom.rs index b6835307dec2f..0cde0547351d2 100644 --- a/tests/ui/allocator/auxiliary/custom.rs +++ b/tests/ui/allocator/auxiliary/custom.rs @@ -1,6 +1,6 @@ //@ no-prefer-dynamic -#![feature(allocator_api)] +#![feature(allocator_ext)] #![crate_type = "rlib"] use std::alloc::{GlobalAlloc, System, Layout}; diff --git a/tests/ui/allocator/custom.rs b/tests/ui/allocator/custom.rs index 97de54dd4d6e3..eefd89c7b5a25 100644 --- a/tests/ui/allocator/custom.rs +++ b/tests/ui/allocator/custom.rs @@ -3,7 +3,6 @@ //@ aux-build:helper.rs //@ no-prefer-dynamic -#![feature(allocator_api)] #![feature(slice_ptr_get)] extern crate helper; diff --git a/tests/ui/allocator/dyn-compatible.rs b/tests/ui/allocator/dyn-compatible.rs index 9d8235e58d929..0e4ccb6fd162b 100644 --- a/tests/ui/allocator/dyn-compatible.rs +++ b/tests/ui/allocator/dyn-compatible.rs @@ -2,8 +2,6 @@ // Check that `Allocator` is dyn-compatible, this allows for polymorphic allocators -#![feature(allocator_api)] - use std::alloc::{Allocator, System}; fn ensure_dyn_compatible(_: &dyn Allocator) {} diff --git a/tests/ui/allocator/xcrate-use.rs b/tests/ui/allocator/xcrate-use.rs index 5934d73981305..a2b71c4498b13 100644 --- a/tests/ui/allocator/xcrate-use.rs +++ b/tests/ui/allocator/xcrate-use.rs @@ -4,7 +4,6 @@ //@ aux-build:helper.rs //@ no-prefer-dynamic -#![feature(allocator_api)] #![feature(slice_ptr_get)] extern crate custom; diff --git a/tests/ui/array-slice-vec/vec-res-add.stderr b/tests/ui/array-slice-vec/vec-res-add.stderr index 4e13dbd0366d0..6d5ad1d3c9694 100644 --- a/tests/ui/array-slice-vec/vec-res-add.stderr +++ b/tests/ui/array-slice-vec/vec-res-add.stderr @@ -8,6 +8,7 @@ LL | let k = i + j; | note: `Vec` does not implement `Add` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is defined in another crate diff --git a/tests/ui/async-await/async-drop/async-drop-box-allocator.rs b/tests/ui/async-await/async-drop/async-drop-box-allocator.rs index 86ebf8a0ffd13..58aa5c422bd61 100644 --- a/tests/ui/async-await/async-drop/async-drop-box-allocator.rs +++ b/tests/ui/async-await/async-drop/async-drop-box-allocator.rs @@ -4,7 +4,7 @@ // It's used as the allocator of a `Box` which is conditionally moved out of. // Sync version is called in sync context, async version is called in async function. -#![feature(async_drop, allocator_api)] +#![feature(async_drop)] #![allow(incomplete_features)] use std::mem::ManuallyDrop; diff --git a/tests/ui/box/alloc-unstable-fail.rs b/tests/ui/box/alloc-unstable-fail.rs deleted file mode 100644 index e209af97d7f75..0000000000000 --- a/tests/ui/box/alloc-unstable-fail.rs +++ /dev/null @@ -1,6 +0,0 @@ -use std::boxed::Box; - -fn main() { - let _boxed: Box = Box::new(10); - //~^ ERROR use of unstable library feature `allocator_api` -} diff --git a/tests/ui/box/alloc-unstable-fail.stderr b/tests/ui/box/alloc-unstable-fail.stderr deleted file mode 100644 index 6ce63a7996662..0000000000000 --- a/tests/ui/box/alloc-unstable-fail.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/alloc-unstable-fail.rs:4:26 - | -LL | let _boxed: Box = Box::new(10); - | ^ - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/box/alloc-unstable.rs b/tests/ui/box/alloc-unstable.rs deleted file mode 100644 index b8c8bc0c70af4..0000000000000 --- a/tests/ui/box/alloc-unstable.rs +++ /dev/null @@ -1,5 +0,0 @@ -//@ run-pass -#![feature(allocator_api)] -fn main() { - let _boxed: Box = Box::new(10); -} diff --git a/tests/ui/box/issue-95036.rs b/tests/ui/box/issue-95036.rs index f20f4b98437fd..505cb996fd57e 100644 --- a/tests/ui/box/issue-95036.rs +++ b/tests/ui/box/issue-95036.rs @@ -1,7 +1,7 @@ //@ compile-flags: -O //@ build-pass -#![feature(allocator_api)] +#![feature(allocator_ext)] #[inline(never)] pub fn by_ref(node: &mut Box<[u8; 1], &std::alloc::Global>) { diff --git a/tests/ui/box/large-allocator-ice.rs b/tests/ui/box/large-allocator-ice.rs index d5c7069cfb951..e85b308428fe4 100644 --- a/tests/ui/box/large-allocator-ice.rs +++ b/tests/ui/box/large-allocator-ice.rs @@ -1,5 +1,5 @@ //@ build-pass -#![feature(allocator_api)] +#![feature(allocator_ext)] #![allow(unused_must_use)] use std::alloc::Allocator; diff --git a/tests/ui/box/leak-alloc.rs b/tests/ui/box/leak-alloc.rs index e87650f42ab61..2308e0c585e3d 100644 --- a/tests/ui/box/leak-alloc.rs +++ b/tests/ui/box/leak-alloc.rs @@ -1,4 +1,4 @@ -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::{AllocError, Allocator, Layout, System}; use std::ptr::NonNull; diff --git a/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs b/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs index 2a1d4828f4a93..ec243f0be8498 100644 --- a/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs +++ b/tests/ui/coherence/impl-foreign-for-box[foreign_local].rs @@ -4,7 +4,7 @@ // Ensure that `Box` in particular isn't fundamental over // the allocator parameter (but is over T). -#![feature(allocator_api)] +#![feature(allocator_ext)] extern crate coherence_lib as lib; diff --git a/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr b/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr index 38440af675feb..ab823c8fc73b9 100644 --- a/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr +++ b/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr @@ -123,6 +123,7 @@ LL | V => {} | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -143,6 +144,7 @@ LL | if let V = vec![] {} | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -158,6 +160,7 @@ LL | let V = vec![] else { return; }; | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -173,6 +176,7 @@ LL | let V = Vec::new() else { return; }; | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | diff --git a/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs b/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs index ac857ff34a4d7..e5233c696c8a8 100644 --- a/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs +++ b/tests/ui/debuginfo/debuginfo-box-with-large-allocator.rs @@ -2,7 +2,7 @@ //@ compile-flags: -Cdebuginfo=2 // fixes issue #94725 -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::{AllocError, Allocator, Layout}; use std::ptr::NonNull; diff --git a/tests/ui/drop/box-conditional-drop-allocator.rs b/tests/ui/drop/box-conditional-drop-allocator.rs index 8f78da16473e7..605969c58f0a0 100644 --- a/tests/ui/drop/box-conditional-drop-allocator.rs +++ b/tests/ui/drop/box-conditional-drop-allocator.rs @@ -1,5 +1,4 @@ //@ run-pass -#![feature(allocator_api)] // Regression test for #131082. // Testing that the allocator of a Box is dropped in conditional drops diff --git a/tests/ui/lifetimes/could-not-resolve-issue-121503.rs b/tests/ui/lifetimes/could-not-resolve-issue-121503.rs index 363162370f21b..6721fde174ef9 100644 --- a/tests/ui/lifetimes/could-not-resolve-issue-121503.rs +++ b/tests/ui/lifetimes/could-not-resolve-issue-121503.rs @@ -1,6 +1,6 @@ //@ edition:2018 -#![feature(allocator_api)] +#![feature(allocator_ext)] struct Struct; impl Struct { async fn box_ref_Struct(self: Box) -> &u32 { diff --git a/tests/ui/lint/must_not_suspend/allocator.rs b/tests/ui/lint/must_not_suspend/allocator.rs index c2ceb3297f37f..8c65c5889d987 100644 --- a/tests/ui/lint/must_not_suspend/allocator.rs +++ b/tests/ui/lint/must_not_suspend/allocator.rs @@ -1,6 +1,6 @@ //@ edition: 2021 -#![feature(must_not_suspend, allocator_api)] +#![feature(must_not_suspend, allocator_ext)] #![deny(must_not_suspend)] use std::alloc::*; diff --git a/tests/ui/lint/unused-features/used-library-features.rs b/tests/ui/lint/unused-features/used-library-features.rs index 1747c7741880e..5d18356febdc7 100644 --- a/tests/ui/lint/unused-features/used-library-features.rs +++ b/tests/ui/lint/unused-features/used-library-features.rs @@ -5,7 +5,7 @@ // Used library features #![feature(error_iter)] -#![cfg_attr(all(), feature(allocator_api))] +#![cfg_attr(all(), feature(allocator_ext))] pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) { for _ in e.sources() {} @@ -13,5 +13,5 @@ pub fn use_error_iter(e: &(dyn std::error::Error + 'static)) { pub fn use_allocator_api() { use std::alloc::Global; - let _ = Vec::::new_in(Global); + let _ = Vec::::try_with_capacity_in(1, Global); } diff --git a/tests/ui/lto/issue-100772.rs b/tests/ui/lto/issue-100772.rs index e07d44e3be880..4452688c7187b 100644 --- a/tests/ui/lto/issue-100772.rs +++ b/tests/ui/lto/issue-100772.rs @@ -5,7 +5,7 @@ //@ only-x86_64-unknown-linux-gnu //@ ignore-backends: gcc -#![feature(allocator_api)] +#![feature(allocator_ext)] fn main() { let _ = Box::new_in(&[0, 1], &std::alloc::Global); diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr index 7c176162ad184..c03137fcc4151 100644 --- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr @@ -8,6 +8,7 @@ LL | EMPTY => {} | ^^^^^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index f776623ff75b2..280516deba14b 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -8,6 +8,7 @@ LL | if let CONST_STRING = empty_str {} | ^^^^^^^^^^^^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is not usable in patterns | diff --git a/tests/ui/pattern/pattern-tyvar-2.stderr b/tests/ui/pattern/pattern-tyvar-2.stderr index 6676d5129872b..4761a4e829b85 100644 --- a/tests/ui/pattern/pattern-tyvar-2.stderr +++ b/tests/ui/pattern/pattern-tyvar-2.stderr @@ -8,6 +8,7 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; | note: `Vec` does not implement `Mul<{integer}>` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL + ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is defined in another crate diff --git a/tests/ui/precondition-checks/vec-from-parts.rs b/tests/ui/precondition-checks/vec-from-parts.rs index ace90770360e5..2b4c3edc8b4a6 100644 --- a/tests/ui/precondition-checks/vec-from-parts.rs +++ b/tests/ui/precondition-checks/vec-from-parts.rs @@ -1,7 +1,7 @@ //@ run-crash //@ compile-flags: -Cdebug-assertions=yes //@ error-pattern: unsafe precondition(s) violated: Vec::from_parts_in requires that length <= capacity -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::ptr::NonNull; diff --git a/tests/ui/precondition-checks/vec-from-raw-parts.rs b/tests/ui/precondition-checks/vec-from-raw-parts.rs index 1bc8e6ada10d9..db883d2589754 100644 --- a/tests/ui/precondition-checks/vec-from-raw-parts.rs +++ b/tests/ui/precondition-checks/vec-from-raw-parts.rs @@ -3,7 +3,7 @@ //@ error-pattern: unsafe precondition(s) violated: Vec::from_raw_parts_in requires that length <= capacity //@ revisions: vec_from_raw_parts vec_from_raw_parts_in string_from_raw_parts -#![feature(allocator_api)] +#![feature(allocator_ext)] fn main() { let ptr = std::ptr::null_mut::(); diff --git a/tests/ui/regions/regions-mock-codegen.rs b/tests/ui/regions/regions-mock-codegen.rs index 99c863640669e..0677e0fabbf6d 100644 --- a/tests/ui/regions/regions-mock-codegen.rs +++ b/tests/ui/regions/regions-mock-codegen.rs @@ -1,7 +1,6 @@ //@ run-pass #![allow(dead_code)] #![allow(non_camel_case_types)] -#![feature(allocator_api)] use std::alloc::{handle_alloc_error, Allocator, Global, Layout}; use std::ptr::NonNull; diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs b/tests/ui/stability-attribute/suggest-vec-allocator-api.rs deleted file mode 100644 index 61a48c19e72ad..0000000000000 --- a/tests/ui/stability-attribute/suggest-vec-allocator-api.rs +++ /dev/null @@ -1,9 +0,0 @@ -fn main() { - let _: Vec = vec![]; //~ ERROR use of unstable library feature `allocator_api` - #[rustfmt::skip] - let _: Vec< - String, - _> = vec![]; //~ ERROR use of unstable library feature `allocator_api` - let _ = Vec::::new(); //~ ERROR use of unstable library feature `allocator_api` - let _boxed: Box = Box::new(10); //~ ERROR use of unstable library feature `allocator_api` -} diff --git a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr b/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr deleted file mode 100644 index 78b7d07b60cc3..0000000000000 --- a/tests/ui/stability-attribute/suggest-vec-allocator-api.stderr +++ /dev/null @@ -1,53 +0,0 @@ -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/suggest-vec-allocator-api.rs:2:20 - | -LL | let _: Vec = vec![]; - | ----^ - | | - | help: consider wrapping the inner types in tuple: `(u8, _)` - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/suggest-vec-allocator-api.rs:6:9 - | -LL | _> = vec![]; - | ^ - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -help: consider wrapping the inner types in tuple - | -LL ~ let _: Vec<( -LL + String, -LL ~ _)> = vec![]; - | - -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/suggest-vec-allocator-api.rs:7:24 - | -LL | let _ = Vec::::new(); - | -----^ - | | - | help: consider wrapping the inner types in tuple: `(u16, _)` - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `allocator_api` - --> $DIR/suggest-vec-allocator-api.rs:8:26 - | -LL | let _boxed: Box = Box::new(10); - | ^ - | - = note: see issue #32838 for more information - = help: add `#![feature(allocator_api)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/traits/const-traits/issue-102156.rs b/tests/ui/traits/const-traits/issue-102156.rs index 506fdaa79c6f3..a6bd26eb2c8db 100644 --- a/tests/ui/traits/const-traits/issue-102156.rs +++ b/tests/ui/traits/const-traits/issue-102156.rs @@ -1,5 +1,5 @@ //@ edition:2015 -#![feature(allocator_api)] +#![feature(allocator_ext)] #![feature(const_trait_impl)] use core::convert::{From, TryFrom}; From 04705ab7add36e3fa012b96b2c5a65f1697a671d Mon Sep 17 00:00:00 2001 From: Nia Deckers Date: Sun, 31 May 2026 13:56:23 +0200 Subject: [PATCH 0664/1309] core/alloc: stabilise `Allocator` --- tests/ui/vec_box_sized.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/vec_box_sized.rs b/tests/ui/vec_box_sized.rs index 5cc140953cecc..3694d32be9eb0 100644 --- a/tests/ui/vec_box_sized.rs +++ b/tests/ui/vec_box_sized.rs @@ -1,7 +1,7 @@ //@no-rustfix #![warn(clippy::vec_box)] -#![feature(allocator_api)] +#![feature(allocator_ext)] use std::alloc::{AllocError, Allocator, Layout}; use std::ptr::NonNull; From 0cbfdb4c5f3c3aebec5fbc630c129ee872a90371 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 13:58:36 +0200 Subject: [PATCH 0665/1309] unix DirEntry: make fallback handling more clear --- library/std/src/sys/fs/unix.rs | 129 ++++++++++++++------------------- 1 file changed, 55 insertions(+), 74 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 46d5d33d23ac2..2e297cd10b537 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1016,89 +1016,70 @@ impl DirEntry { self.file_name_os_str().to_os_string() } - #[cfg(all( - any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "fuchsia", - target_os = "hurd", - target_os = "illumos", - target_vendor = "apple", - ), - not(miri) // no dirfd on Miri - ))] pub fn metadata(&self) -> io::Result { - let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; - let name = self.name.as_ptr(); + cfg_select! { + // Use fstatat (or similar) where possible + all( + any( + all(target_os = "linux", not(target_env = "musl")), + target_os = "android", + target_os = "fuchsia", + target_os = "hurd", + target_os = "illumos", + target_vendor = "apple", + ), + not(miri) // no dirfd on Miri + ) => { + let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; + let name = self.name.as_ptr(); + + cfg_has_statx! { + if let Some(ret) = unsafe { try_statx( + fd, + name, + libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; + } + } - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - fd, - name, - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; + let mut stat: stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; + Ok(FileAttr::from_stat64(stat)) } - } - - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; - Ok(FileAttr::from_stat64(stat)) - } - #[cfg(any( - not(any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "fuchsia", - target_os = "hurd", - target_os = "illumos", - target_vendor = "apple", - )), - miri // no dirfd on Miri - ))] - pub fn metadata(&self) -> io::Result { - run_path_with_cstr(&self.path(), &lstat) - } - - #[cfg(any( - target_os = "solaris", - target_os = "illumos", - target_os = "haiku", - target_os = "vxworks", - target_os = "aix", - target_os = "nto", - target_os = "qnx", - target_os = "vita", - target_os = "l4re", - ))] - pub fn file_type(&self) -> io::Result { - self.metadata().map(|m| m.file_type()) + // Fallback based on path + _ => run_path_with_cstr(&self.path(), &lstat), + } } - #[cfg(not(any( - target_os = "solaris", - target_os = "illumos", - target_os = "haiku", - target_os = "vxworks", - target_os = "aix", - target_os = "nto", - target_os = "qnx", - target_os = "vita", - target_os = "l4re", - )))] pub fn file_type(&self) -> io::Result { + // Use `entry.d_type` if available. + #[cfg(not(any( + target_os = "solaris", + target_os = "illumos", + target_os = "haiku", + target_os = "vxworks", + target_os = "aix", + target_os = "nto", + target_os = "qnx", + target_os = "vita", + target_os = "l4re", + )))] match self.entry.d_type { - libc::DT_CHR => Ok(FileType { mode: libc::S_IFCHR }), - libc::DT_FIFO => Ok(FileType { mode: libc::S_IFIFO }), - libc::DT_LNK => Ok(FileType { mode: libc::S_IFLNK }), - libc::DT_REG => Ok(FileType { mode: libc::S_IFREG }), - libc::DT_SOCK => Ok(FileType { mode: libc::S_IFSOCK }), - libc::DT_DIR => Ok(FileType { mode: libc::S_IFDIR }), - libc::DT_BLK => Ok(FileType { mode: libc::S_IFBLK }), - _ => self.metadata().map(|m| m.file_type()), + libc::DT_CHR => return Ok(FileType { mode: libc::S_IFCHR }), + libc::DT_FIFO => return Ok(FileType { mode: libc::S_IFIFO }), + libc::DT_LNK => return Ok(FileType { mode: libc::S_IFLNK }), + libc::DT_REG => return Ok(FileType { mode: libc::S_IFREG }), + libc::DT_SOCK => return Ok(FileType { mode: libc::S_IFSOCK }), + libc::DT_DIR => return Ok(FileType { mode: libc::S_IFDIR }), + libc::DT_BLK => return Ok(FileType { mode: libc::S_IFBLK }), + _ => {} } + + // Fall back to loading the metadata. + self.metadata().map(|m| m.file_type()) } pub fn ino(&self) -> u64 { From 49c0a85c79241bfbff71ae689492b3802c1a2ac0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 16:14:44 +0200 Subject: [PATCH 0666/1309] add Dir::(symlink_)metadata_at --- library/std/src/fs.rs | 48 +++++++++++++++++++++++++++ library/std/src/fs/tests.rs | 31 +++++++++++++---- library/std/src/sys/fs/common.rs | 8 +++++ library/std/src/sys/fs/unix/dir.rs | 36 ++++++++++++++++++-- library/std/src/sys/fs/windows.rs | 4 ++- library/std/src/sys/fs/windows/dir.rs | 42 ++++++++++++++++++++++- 6 files changed, 158 insertions(+), 11 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 65b8ed634bc05..e7efa32af6964 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1891,6 +1891,54 @@ impl Dir { pub fn try_clone(&self) -> io::Result { Ok(Dir { inner: self.inner.duplicate()? }) } + + /// Queries the file system to get information about a file, directory, etc. relative to this + /// directory. + /// + /// This function will traverse symbolic links to query information about the destination file. + /// To query metadata about the path itself without following symbolic links, use + /// [`symlink_metadata_at`][Self::symlink_metadata_at]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(dirfd)] + /// use std::fs::Dir; + /// + /// fn main() -> std::io::Result<()> { + /// let dir = Dir::open("foo")?; + /// let metadata = dir.metadata_at("subdir/file.txt")?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "dirfd", issue = "120426")] + pub fn metadata_at>(&self, path: P) -> io::Result { + self.inner.metadata_at(path.as_ref()).map(Metadata) + } + + /// Queries the file system to get information about a file, directory, etc. relative to this + /// directory. + /// + /// This function will return the [`Metadata`] of the exact path without traversing symbolic + /// links to a resolved destination file. Using this function on a path that is a file or + /// directory (not a symbolic link) will behave the same as [`metadata_at`][Self::metadata_at]. + /// + /// # Examples + /// + /// ```no_run + /// #![feature(dirfd)] + /// use std::fs::Dir; + /// + /// fn main() -> std::io::Result<()> { + /// let dir = Dir::open("foo")?; + /// let metadata = dir.symlink_metadata_at("subdir/file.txt")?; + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "dirfd", issue = "120426")] + pub fn symlink_metadata_at>(&self, path: P) -> io::Result { + self.inner.symlink_metadata_at(path.as_ref()).map(Metadata) + } } impl AsInner for Dir { diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 250109f277dab..15711652cb05f 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -13,7 +13,7 @@ use crate::os::unix::fs::symlink as symlink_file; use crate::os::unix::fs::symlink as junction_point; #[cfg(windows)] use crate::os::windows::fs::{OpenOptionsExt, junction_point, symlink_dir, symlink_file}; -use crate::path::Path; +use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::test_helpers::{TempDir, tmpdir}; use crate::time::{Duration, Instant, SystemTime}; @@ -655,11 +655,6 @@ fn set_get_permissions_nofollows() { not(any(target_os = "espidf", target_os = "horizon", target_os = "wasi")) ))] fn set_get_permissions_nofollows_symlink() { - #[cfg(not(windows))] - use crate::os::unix::fs::symlink as symlink_file; - #[cfg(windows)] - use crate::os::windows::fs::symlink_file; - let tmpdir = tmpdir(); let filename = tmpdir.join("set_get_unix_permissions_file"); let symlink_name = tmpdir.join("set_get_unix_permissions"); @@ -3106,3 +3101,27 @@ fn test_dir_open_dir() { check!(f.read_exact(&mut buf)); assert_eq!(b"baz", &buf); } + +#[test] +fn test_dir_metadata_at() { + let tmpdir = tmpdir(); + let dir = check!(Dir::open(tmpdir.path())); + check!(dir.create_dir("subdir")); + // FIXME: `/` does not work as path separator on Windows. + let barpath = PathBuf::from("subdir").join("bar.txt"); + drop(check!(dir.open_file_with(&barpath, &OpenOptions::new().create(true).write(true)))); + check!(symlink_file(&tmpdir.join("subdir/bar.txt"), &tmpdir.join("link"))); + + let metadata = check!(dir.metadata_at(&barpath)); + assert!(metadata.is_file()); + let metadata = check!(dir.metadata_at("subdir")); + assert!(metadata.is_dir()); + dir.metadata_at("does-not-exist").unwrap_err(); + + let metadata = check!(dir.metadata_at("link")); + assert!(metadata.is_file()); + assert!(!metadata.is_symlink()); + let metadata = check!(dir.symlink_metadata_at("link")); + assert!(!metadata.is_file()); + assert!(metadata.is_symlink()); +} diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index b2472665fe465..70cb57ac2915d 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -108,6 +108,14 @@ impl Dir { pub fn remove_dir(&self, path: &Path) -> io::Result<()> { remove_dir(self.path.join(path)) } + + pub fn metadata_at(&self, path: &Path) -> io::Result { + self.path.join(path).metadata().map(|m| m.into_inner()) + } + + pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { + self.path.join(path).symlink_metadata().map(|m| m.into_inner()) + } } impl fmt::Debug for Dir { diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs index cf0dece265054..a1e336b7fc237 100644 --- a/library/std/src/sys/fs/unix/dir.rs +++ b/library/std/src/sys/fs/unix/dir.rs @@ -26,7 +26,7 @@ use crate::sys::fs::OpenOptions; use crate::sys::fs::unix::{File, FileAttr, debug_path_fd}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::{AsInner, FromInner, IntoInner, cvt, cvt_r}; -use crate::{fmt, fs, io}; +use crate::{fmt, fs, io, mem}; const TRAVERSE_DIRECTORY: i32 = cfg_select! { @@ -68,7 +68,7 @@ impl Dir { } pub fn remove_file(&self, path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| self.remove_c(path, false)) + run_path_with_cstr(path, &|path| self.remove_c(path, /* remove_dir */ false)) } pub fn rename(&self, from: &Path, to_dir: &Self, to: &Path) -> io::Result<()> { @@ -86,7 +86,17 @@ impl Dir { } pub fn remove_dir(&self, path: &Path) -> io::Result<()> { - run_path_with_cstr(path, &|path| self.remove_c(path, true)) + run_path_with_cstr(path, &|path| self.remove_c(path, /* remove_dir */ true)) + } + + pub fn metadata_at(&self, path: &Path) -> io::Result { + run_path_with_cstr(path, &|path| { + self.metadata_at_c(path, /* symlink_nofollow */ false) + }) + } + + pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { + run_path_with_cstr(path, &|path| self.metadata_at_c(path, /* symlink_nofollow */ true)) } fn open_with_c(path: &CStr, opts: &OpenOptions) -> io::Result { @@ -143,6 +153,26 @@ impl Dir { fn create_dir_c(&self, path: &CStr) -> io::Result<()> { cvt(unsafe { mkdirat(self.0.as_raw_fd(), path.as_ptr(), 0o777) }).map(|_| ()) } + + fn metadata_at_c(&self, path: &CStr, symlink_nofollow: bool) -> io::Result { + let fd = self.0.as_raw_fd(); + let flag = if symlink_nofollow { libc::AT_SYMLINK_NOFOLLOW } else { 0 }; + + cfg_has_statx! { + if let Some(ret) = unsafe { super::try_statx( + fd, + path.as_ptr(), + flag | libc::AT_STATX_SYNC_AS_STAT, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + ) } { + return ret; + } + } + + let mut stat: super::stat64 = unsafe { mem::zeroed() }; + cvt(unsafe { super::fstatat64(fd, path.as_ptr(), &mut stat, flag) })?; + Ok(FileAttr::from_stat64(stat)) + } } impl fmt::Debug for Dir { diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index 399c0749bc21e..473d92aface26 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -1454,7 +1454,9 @@ pub fn link(_original: &WCStr, _link: &WCStr) -> io::Result<()> { pub fn stat(path: &WCStr) -> io::Result { match metadata(path, ReparsePoint::Follow) { Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { - if let Ok(attrs) = lstat(path) { + // Fallback to opening reparse points when following fails. Needed for UNIX domain + // sockets. See . + if let Ok(attrs) = metadata(path, ReparsePoint::Open) { if !attrs.file_type().is_symlink() { return Ok(attrs); } diff --git a/library/std/src/sys/fs/windows/dir.rs b/library/std/src/sys/fs/windows/dir.rs index 6f6d59af31628..7b8cd60fd8d06 100644 --- a/library/std/src/sys/fs/windows/dir.rs +++ b/library/std/src/sys/fs/windows/dir.rs @@ -7,7 +7,7 @@ use crate::os::windows::io::{ }; use crate::path::Path; use crate::sys::api::{UnicodeStrRef, WinError}; -use crate::sys::fs::windows::debug_path_handle; +use crate::sys::fs::windows::{ReparsePoint, debug_path_handle}; use crate::sys::fs::{File, FileAttr, OpenOptions}; use crate::sys::handle::Handle; use crate::sys::path::{WCStr, with_native_path}; @@ -165,6 +165,7 @@ impl Dir { fn rename_native(&self, from: &[u16], to_dir: &Self, to: &[u16]) -> io::Result<()> { let mut opts = OpenOptions::new(); opts.access_mode(c::DELETE); + // FIXME: custom_flags is ignored by `open_file_native`! opts.custom_flags(c::FILE_FLAG_OPEN_REPARSE_POINT | c::FILE_FLAG_BACKUP_SEMANTICS); let handle = self.open_file_native(from, &opts, /* create_opt */ 0)?; // Calculate the layout of the `FILE_RENAME_INFORMATION` we pass to `NtSetInformationFile` @@ -231,6 +232,45 @@ impl Dir { }); f.file_attr() } + + pub fn metadata_at(&self, path: &Path) -> io::Result { + let path = to_u16s_without_nul(path)?; + // Same as the `stat` logic used for `fs::metadata` + match self.metadata_at_native(&path, ReparsePoint::Follow) { + Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { + // Fallback to opening reparse points when following fails. Needed for UNIX domain + // sockets. See . + if let Ok(attrs) = self.metadata_at_native(&path, ReparsePoint::Open) { + if !attrs.file_type().is_symlink() { + return Ok(attrs); + } + } + Err(err) + } + result => result, + } + } + + pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { + let path = to_u16s_without_nul(path)?; + self.metadata_at_native(&path, ReparsePoint::Open) + } + + fn metadata_at_native(&self, path: &[u16], reparse: ReparsePoint) -> io::Result { + let mut opts = OpenOptions::new(); + // the NT functions need at least c::FILE_READ_ATTRIBUTES + opts.access_mode(c::FILE_READ_ATTRIBUTES); + let create_opt = if reparse == ReparsePoint::Open { c::FILE_OPEN_REPARSE_POINT } else { 0 }; + + let name = UnicodeStrRef::from_slice(path); + let object_attributes = c::OBJECT_ATTRIBUTES { + RootDirectory: self.handle.as_raw_handle(), + ObjectName: name.as_ptr().cast_mut(), + ..c::OBJECT_ATTRIBUTES::with_length() + }; + let handle = unsafe { nt_create_file(&opts, &object_attributes, create_opt)? }; + File { handle }.file_attr() + } } impl fmt::Debug for Dir { From cadaa2e7bf5a4c7ed2f9c4fd1de42d6527f6c8b8 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 19 Sep 2026 16:22:23 +0200 Subject: [PATCH 0667/1309] reuse Dir::metadata_at code for DirEntry::metadata --- library/std/src/sys/fs/unix.rs | 27 +++++++-------------------- library/std/src/sys/fs/unix/dir.rs | 14 +++++++++----- 2 files changed, 16 insertions(+), 25 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 2e297cd10b537..988bacd57d1b2 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -17,10 +17,6 @@ use libc::c_char; target_vendor = "apple", ))] use libc::dirfd; -#[cfg(any(target_os = "fuchsia", target_os = "illumos", target_vendor = "apple"))] -use libc::fstatat as fstatat64; -#[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))] -use libc::fstatat64; use libc::{c_int, mode_t}; #[cfg(target_os = "android")] use libc::{ @@ -1018,7 +1014,7 @@ impl DirEntry { pub fn metadata(&self) -> io::Result { cfg_select! { - // Use fstatat (or similar) where possible + // Use directory handle where possible all( any( all(target_os = "linux", not(target_env = "musl")), @@ -1031,22 +1027,13 @@ impl DirEntry { not(miri) // no dirfd on Miri ) => { let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; - let name = self.name.as_ptr(); - - cfg_has_statx! { - if let Some(ret) = unsafe { try_statx( - fd, - name, - libc::AT_SYMLINK_NOFOLLOW | libc::AT_STATX_SYNC_AS_STAT, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - ) } { - return ret; - } - } - let mut stat: stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { fstatat64(fd, name, &mut stat, libc::AT_SYMLINK_NOFOLLOW) })?; - Ok(FileAttr::from_stat64(stat)) + // Make this FD into a directory handle. We don't actually drop it, + // so having an `OwnedFd` is fine. + let dir_handle = + mem::ManuallyDrop::new(dir::Dir(unsafe { OwnedFd::from_raw_fd(fd) })); + + dir_handle.metadata_at_c(&self.name, /* symlink_nofollow */ true) } // Fallback based on path diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs index a1e336b7fc237..087916fd9ff63 100644 --- a/library/std/src/sys/fs/unix/dir.rs +++ b/library/std/src/sys/fs/unix/dir.rs @@ -7,10 +7,10 @@ cfg_select! { target_os = "android", target_os = "hurd", )) => { - use libc::{open as open64, openat as openat64}; + use libc::{fstatat as fstatat64, open as open64, openat as openat64}; } _ => { - use libc::{open64, openat64}; + use libc::{fstatat64, open64, openat64}; } } @@ -36,7 +36,7 @@ const TRAVERSE_DIRECTORY: i32 = _ => libc::O_RDONLY, }; -pub struct Dir(OwnedFd); +pub struct Dir(pub(super) OwnedFd); impl Dir { pub fn open(path: &Path, opts: &OpenOptions) -> io::Result { @@ -154,7 +154,11 @@ impl Dir { cvt(unsafe { mkdirat(self.0.as_raw_fd(), path.as_ptr(), 0o777) }).map(|_| ()) } - fn metadata_at_c(&self, path: &CStr, symlink_nofollow: bool) -> io::Result { + pub(super) fn metadata_at_c( + &self, + path: &CStr, + symlink_nofollow: bool, + ) -> io::Result { let fd = self.0.as_raw_fd(); let flag = if symlink_nofollow { libc::AT_SYMLINK_NOFOLLOW } else { 0 }; @@ -170,7 +174,7 @@ impl Dir { } let mut stat: super::stat64 = unsafe { mem::zeroed() }; - cvt(unsafe { super::fstatat64(fd, path.as_ptr(), &mut stat, flag) })?; + cvt(unsafe { fstatat64(fd, path.as_ptr(), &mut stat, flag) })?; Ok(FileAttr::from_stat64(stat)) } } From e53b292767ce546ce06e726302bcc0f6ccc0a66a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 22 Sep 2026 22:44:58 +0200 Subject: [PATCH 0668/1309] forward rustdoc env vars to doctests --- src/tools/miri/cargo-miri/src/util.rs | 12 ++++++++++-- src/tools/miri/test-cargo-miri/run-test.py | 1 + .../miri/test-cargo-miri/test.default.stdout.ref | 6 +++--- .../miri/test-cargo-miri/test.filter.stdout.ref | 2 +- .../test-cargo-miri/test.multiple_targets.stdout.ref | 12 ++++++------ .../miri/test-cargo-miri/test.workspace.stdout.ref | 6 +++--- 6 files changed, 24 insertions(+), 15 deletions(-) diff --git a/src/tools/miri/cargo-miri/src/util.rs b/src/tools/miri/cargo-miri/src/util.rs index 162ddcb18bd5f..fb93f177aac9e 100644 --- a/src/tools/miri/cargo-miri/src/util.rs +++ b/src/tools/miri/cargo-miri/src/util.rs @@ -42,9 +42,17 @@ impl CrateRunInfo { let env = env::vars_os() .filter(|(var, _val)| { // We only need to bother with env vars cargo actually sets. - // We try to avoid storing anything that may contain secrets. var.to_str().is_some_and(|var| { - var == "OUT_DIR" || (var.starts_with("CARGO_") && !var.ends_with("_TOKEN")) + ( // Env vars cargo sets for crates. + // + var == "OUT_DIR" + || var.starts_with("CARGO_") + // Env vars rustdoc sets for its rustc invocation. + || var.starts_with("UNSTABLE_RUSTDOC_") + || var.starts_with("RUSTDOC_") + ) + // We try to avoid storing anything that may contain secrets. + && !var.ends_with("_TOKEN") }) }) .collect(); diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index 9764700347c8f..f593a16df9869 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -49,6 +49,7 @@ def check_output(actual, path, name): if expected == actual: return True print(f"{name} output did not match reference in {path}!") + print("Run `./run-test.py --bless` to update reference files.") print(f"--- BEGIN diff {name} ---") for text in difflib.unified_diff(expected.split("\n"), actual.split("\n")): print(text) diff --git a/src/tools/miri/test-cargo-miri/test.default.stdout.ref b/src/tools/miri/test-cargo-miri/test.default.stdout.ref index deb7cd839f125..b800d17b83b29 100644 --- a/src/tools/miri/test-cargo-miri/test.default.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.default.stdout.ref @@ -10,8 +10,8 @@ running 6 tests test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME -running 5 tests -..... -test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +running 6 tests +...... +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME all doctests ran in $TIME; merged doctests compilation took $TIME diff --git a/src/tools/miri/test-cargo-miri/test.filter.stdout.ref b/src/tools/miri/test-cargo-miri/test.filter.stdout.ref index a4d912e7a8d0a..5b0c846b8a1e0 100644 --- a/src/tools/miri/test-cargo-miri/test.filter.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.filter.stdout.ref @@ -13,6 +13,6 @@ test result: ok. 1 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; fini running 0 tests -test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 5 filtered out; finished in $TIME +test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 6 filtered out; finished in $TIME all doctests ran in $TIME; merged doctests compilation took $TIME diff --git a/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref b/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref index b36fb3af66641..d4f9de09366b1 100644 --- a/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.multiple_targets.stdout.ref @@ -21,14 +21,14 @@ running 6 tests test result: ok. 5 passed; 0 failed; 1 ignored; 0 measured; 0 filtered out; finished in $TIME -running 5 tests -..... -test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +running 6 tests +...... +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME all doctests ran in $TIME; merged doctests compilation took $TIME -running 5 tests -..... -test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +running 6 tests +...... +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME all doctests ran in $TIME; merged doctests compilation took $TIME diff --git a/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref b/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref index c890af4bd974c..2400dff6c3197 100644 --- a/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref +++ b/src/tools/miri/test-cargo-miri/test.workspace.stdout.ref @@ -21,9 +21,9 @@ running 0 tests test result: ok. 0 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME -running 5 tests -..... -test result: ok. 5 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME +running 6 tests +...... +test result: ok. 6 passed; 0 failed; 0 ignored; 0 measured; 0 filtered out; finished in $TIME all doctests ran in $TIME; merged doctests compilation took $TIME From 78d478a7e4bdf8dcb0275168e65722f77f5e3e9c Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 22 Sep 2026 20:12:57 +0200 Subject: [PATCH 0669/1309] Update deprecated rustc_hir imports --- Cargo.lock | 6 ++- compiler/rustc_ast_lowering/src/block.rs | 2 +- compiler/rustc_ast_lowering/src/contract.rs | 9 ++-- .../src/delegation/attributes.rs | 26 +++++----- .../rustc_ast_lowering/src/delegation/mod.rs | 2 +- .../rustc_ast_lowering/src/expr/closure.rs | 12 +++-- compiler/rustc_ast_lowering/src/format.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 39 ++++++++------- compiler/rustc_ast_lowering/src/lib.rs | 19 ++++---- compiler/rustc_ast_lowering/src/pat.rs | 5 +- compiler/rustc_hir/src/lib.rs | 18 ++++--- compiler/rustc_hir_pretty/Cargo.toml | 1 + compiler/rustc_hir_pretty/src/lib.rs | 47 +++++++++---------- compiler/rustc_middle/src/arena.rs | 8 ++-- compiler/rustc_middle/src/hir/map.rs | 1 + compiler/rustc_middle/src/hir/mod.rs | 3 +- .../src/middle/debugger_visualizer.rs | 2 +- .../rustc_middle/src/middle/lang_items.rs | 2 +- compiler/rustc_middle/src/mir/syntax.rs | 2 +- compiler/rustc_middle/src/mir/terminator.rs | 4 +- compiler/rustc_middle/src/mono.rs | 2 +- compiler/rustc_middle/src/queries.rs | 11 +++-- compiler/rustc_middle/src/query/erase.rs | 6 +-- compiler/rustc_middle/src/thir.rs | 2 +- .../src/traits/specialization_graph.rs | 2 +- compiler/rustc_middle/src/ty/adjustment.rs | 2 +- compiler/rustc_middle/src/ty/adt.rs | 5 +- compiler/rustc_middle/src/ty/consts/lit.rs | 3 +- compiler/rustc_middle/src/ty/context.rs | 7 +-- .../src/ty/context/impl_interner.rs | 2 +- compiler/rustc_middle/src/ty/diagnostics.rs | 2 +- compiler/rustc_middle/src/ty/instance.rs | 4 +- compiler/rustc_middle/src/ty/layout.rs | 2 +- compiler/rustc_middle/src/ty/mod.rs | 4 +- compiler/rustc_middle/src/ty/print/pretty.rs | 2 +- .../rustc_middle/src/ty/structural_impls.rs | 2 +- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_middle/src/ty/trait_def.rs | 3 +- compiler/rustc_middle/src/ty/util.rs | 3 +- compiler/rustc_passes/src/abi_test.rs | 3 +- .../rustc_passes/src/canonical_symbols.rs | 4 +- compiler/rustc_passes/src/check_attr.rs | 18 +++---- .../rustc_passes/src/debugger_visualizer.rs | 3 +- compiler/rustc_passes/src/diagnostic_items.rs | 5 +- compiler/rustc_passes/src/eii.rs | 2 +- compiler/rustc_passes/src/lang_items.rs | 4 +- compiler/rustc_passes/src/layout_test.rs | 3 +- compiler/rustc_passes/src/lib_features.rs | 3 +- compiler/rustc_passes/src/stability.rs | 10 ++-- compiler/rustc_passes/src/weak_lang_items.rs | 4 +- compiler/rustc_resolve/Cargo.toml | 1 + compiler/rustc_resolve/src/def_collector.rs | 5 +- compiler/rustc_symbol_mangling/Cargo.toml | 1 + compiler/rustc_symbol_mangling/src/test.rs | 3 +- compiler/rustc_transmute/Cargo.toml | 4 +- compiler/rustc_transmute/src/lib.rs | 2 +- compiler/rustc_ty_utils/Cargo.toml | 1 + compiler/rustc_ty_utils/src/abi.rs | 2 +- compiler/rustc_ty_utils/src/common_traits.rs | 2 +- compiler/rustc_ty_utils/src/instance.rs | 2 +- compiler/rustc_ty_utils/src/layout.rs | 2 +- .../rustc_ty_utils/src/structural_match.rs | 2 +- .../src/attrs/deprecated_semver.rs | 2 +- .../clippy/clippy_lints/src/missing_doc.rs | 6 +-- tests/ui-fulldeps/internal-lints/find_attr.rs | 4 +- tests/ui-fulldeps/polymorphic-drop-glue.rs | 3 +- 66 files changed, 200 insertions(+), 177 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc62ae98e0372..471734dd69e3d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4174,6 +4174,7 @@ dependencies = [ "rustc_abi", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_ir", "rustc_hir", "rustc_span", ] @@ -4738,6 +4739,7 @@ dependencies = [ "rustc_arena", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -4854,6 +4856,7 @@ dependencies = [ "punycode", "rustc-demangle", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_hashes", "rustc_hir", @@ -4953,8 +4956,8 @@ version = "0.0.0" dependencies = [ "itertools", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", - "rustc_hir", "rustc_middle", "rustc_span", "smallvec", @@ -4967,6 +4970,7 @@ version = "0.0.0" dependencies = [ "itertools", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hashes", diff --git a/compiler/rustc_ast_lowering/src/block.rs b/compiler/rustc_ast_lowering/src/block.rs index b52af8fd3715a..b2cb1718b86a3 100644 --- a/compiler/rustc_ast_lowering/src/block.rs +++ b/compiler/rustc_ast_lowering/src/block.rs @@ -1,6 +1,6 @@ use rustc_ast::{Block, BlockCheckMode, Local, LocalKind, Stmt, StmtKind}; +use rustc_attr_ir::target::Target; use rustc_hir as hir; -use rustc_hir::Target; use rustc_span::sym; use smallvec::SmallVec; diff --git a/compiler/rustc_ast_lowering/src/contract.rs b/compiler/rustc_ast_lowering/src/contract.rs index eaebff521cb68..80bd0f7f4bb95 100644 --- a/compiler/rustc_ast_lowering/src/contract.rs +++ b/compiler/rustc_ast_lowering/src/contract.rs @@ -1,6 +1,7 @@ use std::sync::Arc; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::Target; use thin_vec::thin_vec; use crate::LoweringContext; @@ -209,7 +210,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let postcond_checker = self.arena.alloc(self.expr_enum_variant_lang_item( postcond_checker.span, - rustc_hir::attrs::lang_items::LangItem::OptionSome, + LangItem::OptionSome, &*arena_vec![self; *postcond_checker], )); let then_block_stmts = self.block_all(span, stmts, Some(postcond_checker)); @@ -217,7 +218,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let none_expr = self.arena.alloc(self.expr_enum_variant_lang_item( postcond_checker.span, - rustc_hir::attrs::lang_items::LangItem::OptionNone, + LangItem::OptionNone, Default::default(), )); let else_block = self.block_expr(none_expr); @@ -350,7 +351,7 @@ impl<'hir> LoweringContext<'_, 'hir> { )); let attrs: rustc_ast::AttrVec = thin_vec![self.unreachable_code_attr(span)]; - self.lower_attrs(contract_check.hir_id, &attrs, span, rustc_hir::Target::Expression); + self.lower_attrs(contract_check.hir_id, &attrs, span, Target::Expression); let ret_block = self.block_all(span, arena_vec![self; ret_stmt], Some(contract_check)); self.arena.alloc(self.expr_block(self.arena.alloc(ret_block))) diff --git a/compiler/rustc_ast_lowering/src/delegation/attributes.rs b/compiler/rustc_ast_lowering/src/delegation/attributes.rs index 834f85450a2cd..686f5bbf06acc 100644 --- a/compiler/rustc_ast_lowering/src/delegation/attributes.rs +++ b/compiler/rustc_ast_lowering/src/delegation/attributes.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::{AttributeKind, InlineAttr}; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, InlineAttr}; use rustc_span::Span; use rustc_span::def_id::DefId; @@ -7,33 +7,37 @@ use crate::LoweringContext; use crate::delegation::DelegationResolution; struct AdditionInfo { - pub equals: fn(&hir::Attribute) -> bool, + pub equals: fn(&rustc_attr_ir::Attribute) -> bool, pub kind: AdditionKind, } enum AdditionKind { - Default { factory: fn(Span) -> hir::Attribute }, - Inherit { factory: fn(Span, &hir::Attribute) -> hir::Attribute }, + Default { factory: fn(Span) -> rustc_attr_ir::Attribute }, + Inherit { factory: fn(Span, &rustc_attr_ir::Attribute) -> rustc_attr_ir::Attribute }, } static ADDITIONS: &[AdditionInfo] = &[ AdditionInfo { - equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::MustUse { .. })), + equals: |a| matches!(a, rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { .. })), kind: AdditionKind::Inherit { factory: |span, original_attr| { let reason = match original_attr { - hir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => *reason, + rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { reason, .. }) => { + *reason + } _ => None, }; - hir::Attribute::Parsed(AttributeKind::MustUse { span, reason }) + rustc_attr_ir::Attribute::Parsed(AttributeKind::MustUse { span, reason }) }, }, }, AdditionInfo { - equals: |a| matches!(a, hir::Attribute::Parsed(AttributeKind::Inline(..))), + equals: |a| matches!(a, rustc_attr_ir::Attribute::Parsed(AttributeKind::Inline(..))), kind: AdditionKind::Default { - factory: |span| hir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)), + factory: |span| { + rustc_attr_ir::Attribute::Parsed(AttributeKind::Inline(InlineAttr::Hint, span)) + }, }, }, ]; @@ -61,8 +65,8 @@ impl<'hir> LoweringContext<'_, 'hir> { &self, span: Span, sig_id: DefId, - existing: Option<&&[hir::Attribute]>, - ) -> Vec { + existing: Option<&&[rustc_attr_ir::Attribute]>, + ) -> Vec { ADDITIONS .iter() .filter_map(|addition| { diff --git a/compiler/rustc_ast_lowering/src/delegation/mod.rs b/compiler/rustc_ast_lowering/src/delegation/mod.rs index 0e94016963c78..b2c0e1ffa81b1 100644 --- a/compiler/rustc_ast_lowering/src/delegation/mod.rs +++ b/compiler/rustc_ast_lowering/src/delegation/mod.rs @@ -45,7 +45,7 @@ use hir::def::Res; use rustc_abi::ExternAbi; use rustc_ast as ast; use rustc_ast::*; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::{self as hir, FnDeclFlags, QPath}; use rustc_middle::ty::Asyncness; diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index 1b8740948d726..c72956545b7c8 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -1,6 +1,8 @@ use rustc_ast::*; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::target::Target; use rustc_hir as hir; -use rustc_hir::{HirId, Target, find_attr}; +use rustc_hir::HirId; use rustc_span::{Span, span_bug}; use super::{LoweringContext, MoveExprState}; @@ -55,7 +57,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_coroutine_closure_with_move_exprs( &mut self, expr_hir_id: HirId, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, @@ -114,7 +116,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_expr_plain_closure_with_move_exprs( &mut self, expr_hir_id: HirId, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, @@ -153,7 +155,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // local uses and the caller can later add the matching initializers. fn lower_expr_closure( &mut self, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, @@ -283,7 +285,7 @@ impl<'hir> LoweringContext<'_, 'hir> { body: &Expr, fn_decl_span: Span, fn_arg_span: Span, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], ) -> hir::ExprKind<'hir> { let closure_def_id = self.local_def_id(closure_id); let (binder_clause, generic_params) = self.lower_closure_binder(binder); diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs index b9974edea71a4..9da42511c0d7f 100644 --- a/compiler/rustc_ast_lowering/src/format.rs +++ b/compiler/rustc_ast_lowering/src/format.rs @@ -1,9 +1,9 @@ use std::borrow::Cow; use rustc_ast::*; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_session::config::FmtDebug; use rustc_span::{ByteSymbol, DesugaringKind, Ident, Span, Symbol, sym}; diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index f8106bd68d82c..33b73ed30c518 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -1,12 +1,11 @@ use rustc_abi::ExternAbi; use rustc_ast::visit::AssocCtxt; use rustc_ast::*; +use rustc_attr_ir::target::Target; +use rustc_attr_ir::{AttributeKind, EiiImplResolution, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; -use rustc_hir::attrs::{AttributeKind, EiiImplResolution}; use rustc_hir::def::{DefKind, PerNS, Res}; -use rustc_hir::{ - self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin, Target, find_attr, -}; +use rustc_hir::{self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin}; use rustc_middle::ty::data_structures::IndexMap; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::edit_distance::find_best_match_for_name; @@ -68,8 +67,8 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, name: Ident, EiiDecl { foreign_item, impl_unsafe }: &EiiDecl, - ) -> Option { - self.lower_path_simple_eii(id, foreign_item).map(|did| hir::attrs::EiiDecl { + ) -> Option { + self.lower_path_simple_eii(id, foreign_item).map(|did| rustc_attr_ir::EiiDecl { foreign_item: did, impl_unsafe: *impl_unsafe, name, @@ -87,7 +86,7 @@ impl<'hir> LoweringContext<'_, 'hir> { is_default, known_eii_macro_resolution, }: &EiiImpl, - ) -> hir::attrs::EiiImpl { + ) -> rustc_attr_ir::EiiImpl { let resolution = if let Some(target) = known_eii_macro_resolution && let Some(foreign_item_did) = self.lower_path_simple_eii(*node_id, target) { @@ -100,7 +99,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ) }; - hir::attrs::EiiImpl { + rustc_attr_ir::EiiImpl { span: self.lower_span(*span), inner_span: self.lower_span(*inner_span), impl_unsafe_span: match *impl_safety { @@ -116,19 +115,21 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, id: NodeId, i: &ItemKind, - ) -> Vec { + ) -> Vec { match i { ItemKind::Fn(Fn { eii_impl: None, .. }) | ItemKind::Static(StaticItem { eii_impl: None, .. }) => Vec::new(), ItemKind::Fn(Fn { eii_impl: Some(eii_impl), .. }) | ItemKind::Static(StaticItem { eii_impl: Some(eii_impl), .. }) => { - vec![hir::Attribute::Parsed(AttributeKind::EiiImpl(Box::new( + vec![rustc_attr_ir::Attribute::Parsed(AttributeKind::EiiImpl(Box::new( self.lower_eii_impl(eii_impl), )))] } ItemKind::MacroDef(name, MacroDef { eii_declaration: Some(target), .. }) => self .lower_eii_decl(id, *name, target) - .map(|decl| vec![hir::Attribute::Parsed(AttributeKind::EiiDeclaration(decl))]) + .map(|decl| { + vec![rustc_attr_ir::Attribute::Parsed(AttributeKind::EiiDeclaration(decl))] + }) .unwrap_or_default(), ItemKind::ExternCrate(..) @@ -184,7 +185,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, id: NodeId, hir_id: hir::HirId, - attrs: &'hir [hir::Attribute], + attrs: &'hir [rustc_attr_ir::Attribute], vis_span: Span, i: &ItemKind, ) -> hir::ItemKind<'hir> { @@ -551,7 +552,7 @@ impl<'hir> LoweringContext<'_, 'hir> { prefix: &Path, id: NodeId, vis_span: Span, - attrs: &'hir [hir::Attribute], + attrs: &'hir [rustc_attr_ir::Attribute], ) -> hir::ItemKind<'hir> { let path = &tree.prefix; let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect(); @@ -1351,7 +1352,7 @@ impl<'hir> LoweringContext<'_, 'hir> { decl: &FnDecl, coroutine_marker: Option, body: Option<&Block>, - attrs: &'hir [hir::Attribute], + attrs: &'hir [rustc_attr_ir::Attribute], contract: Option<&FnContract>, ) -> hir::BodyId { let Some(body) = body else { @@ -1612,7 +1613,7 @@ impl<'hir> LoweringContext<'_, 'hir> { id: NodeId, kind: FnDeclKind, coroutine_marker: Option, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; @@ -1626,7 +1627,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, h: FnHeader, default_safety: hir::Safety, - attrs: &[hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], ) -> hir::FnHeader { let asyncness = if let Some(coroutine_marker) = h.coroutine_marker && let CoroutineKind::Async = coroutine_marker.kind @@ -1713,7 +1714,11 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Lowers constness or comptime attribute. /// Whether `const` is allowed here is checked by ast validation. /// Whether `comptime` is allowed here is checked by the `comptime` attribute parser. - pub(super) fn lower_constness(&mut self, attrs: &[hir::Attribute], c: Const) -> hir::Constness { + pub(super) fn lower_constness( + &mut self, + attrs: &[rustc_attr_ir::Attribute], + c: Const, + ) -> hir::Constness { let mut constness = match c { Const::Yes(_) => hir::Constness::Const { always: false }, Const::No => hir::Constness::NotConst, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7ff6a2538c1e7..d35e8df40f20b 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -45,6 +45,9 @@ use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; use rustc_ast::{self as ast, *}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::Target; use rustc_attr_parsing::{AttributeParser, Recovery, ShouldEmit}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; @@ -54,15 +57,13 @@ use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; use rustc_hir::{ self as hir, AngleBrackets, CRATE_OWNER_ID, ConstArg, GenericArg, HirId, ItemLocalMap, - LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, Target, TraitCandidate, - find_attr, + LifetimeSource, LifetimeSyntax, MissingLifetimeKind, ParamName, TraitCandidate, }; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; @@ -169,7 +170,7 @@ struct PerOwnerLoweringState<'a, 'hir> { // -- Accumulated outputs -- /// Attributes inside the owner being lowered. - attrs: SortedMap, + attrs: SortedMap, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// `#[define_opaque]` attributes @@ -1206,7 +1207,7 @@ impl<'hir> LoweringContext<'_, 'hir> { attrs: &[Attribute], target_span: Span, target: Target, - ) -> &'hir [hir::Attribute] { + ) -> &'hir [rustc_attr_ir::Attribute] { self.lower_attrs_with_extra(id, attrs, target_span, target, None, &[]) } @@ -1217,8 +1218,8 @@ impl<'hir> LoweringContext<'_, 'hir> { target_span: Span, target: Target, target_item: Option<&ast::Item>, - extra_hir_attributes: &[hir::Attribute], - ) -> &'hir [hir::Attribute] { + extra_hir_attributes: &[rustc_attr_ir::Attribute], + ) -> &'hir [rustc_attr_ir::Attribute] { if attrs.is_empty() && extra_hir_attributes.is_empty() { &[] } else { @@ -1251,7 +1252,7 @@ impl<'hir> LoweringContext<'_, 'hir> { target_hir_id: HirId, target: Target, target_item: Option<&ast::Item>, - ) -> Vec { + ) -> Vec { let l = self.span_lowerer(); self.attribute_parser.parse_attribute_list( attrs, @@ -3111,7 +3112,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn stmt_let_pat( &mut self, - attrs: Option<&'hir [hir::Attribute]>, + attrs: Option<&'hir [rustc_attr_ir::Attribute]>, span: Span, init: Option<&'hir hir::Expr<'hir>>, pat: &'hir hir::Pat<'hir>, diff --git a/compiler/rustc_ast_lowering/src/pat.rs b/compiler/rustc_ast_lowering/src/pat.rs index 0edba3fe0cd14..df3d7b1a3c0a6 100644 --- a/compiler/rustc_ast_lowering/src/pat.rs +++ b/compiler/rustc_ast_lowering/src/pat.rs @@ -1,9 +1,10 @@ use std::sync::Arc; use rustc_ast::*; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::Target; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, Target}; use rustc_span::{DesugaringKind, Ident, Span, Spanned, respan, span_bug}; use crate::diagnostics::{ diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 0f31ed196c3df..5855c1126a971 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -24,20 +24,18 @@ pub mod pat_util; mod stable_hash_impls; mod target_impls; +// FIXME: Remove this use tree, replace by `rustc_attr_ir` imports +#[doc(hidden)] +pub use attrs::{ + Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, + UnstableReason, target::Target, +}; #[doc(no_inline)] pub use hir::*; +// FIXME: Remove this use tree, replace by `rustc_attr_ir` imports +#[doc(hidden)] pub use rustc_attr_ir::{self as attrs, find_attr}; pub use rustc_hir_id::*; pub use rustc_span::def_id; -// FIXME: Remove this use tree, replace by `rustc_hir::attrs` or `rustc_attr_ir` imports -#[doc(hidden)] -pub use { - attrs::target::{self, AssocCtxt, MethodKind, Target}, - attrs::{ - AttrArgs, AttrItem, AttrPath, Attribute, ConstStability, DefaultBodyStability, - HashIgnoredAttrId, PartialConstStability, Stability, StabilityLevel, StableSince, - UnstableReason, VERSION_PLACEHOLDER, - }, -}; pub use crate::arena::Arena; diff --git a/compiler/rustc_hir_pretty/Cargo.toml b/compiler/rustc_hir_pretty/Cargo.toml index f5d7dbd3f96e4..8279d9c6d620a 100644 --- a/compiler/rustc_hir_pretty/Cargo.toml +++ b/compiler/rustc_hir_pretty/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_hir = { path = "../rustc_hir" } rustc_span = { path = "../rustc_span" } # tidy-alphabetical-end diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 6d1ae563a9fa2..ddd1a296ecd35 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -16,8 +16,8 @@ use rustc_ast_pretty::pp::Breaks::{Consistent, Inconsistent}; use rustc_ast_pretty::pp::{self, BoxMarker, Breaks}; use rustc_ast_pretty::pprust::state::MacHeader; use rustc_ast_pretty::pprust::{Comments, PrintState}; +use rustc_attr_ir::{AttrArgs, AttrItem, Attribute, AttributeKind, PrintAttribute}; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, PrintAttribute}; use rustc_hir::{ BindingMode, ByRef, ConstArg, ConstArgExprField, ConstArgKind, GenericArg, GenericBound, GenericParam, GenericParamKind, HirId, ImplicitSelfKind, LifetimeParamKind, Node, PatKind, @@ -72,12 +72,12 @@ impl PpAnn for &dyn rustc_hir::intravisit::HirTyCtxt<'_> { pub struct State<'a> { pub s: pp::Printer, comments: Option>, - attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute], + attrs: &'a dyn Fn(HirId) -> &'a [Attribute], ann: &'a (dyn PpAnn + 'a), } impl<'a> State<'a> { - fn attrs(&self, id: HirId) -> &'a [hir::Attribute] { + fn attrs(&self, id: HirId) -> &'a [Attribute] { (self.attrs)(id) } @@ -86,7 +86,7 @@ impl<'a> State<'a> { expr.precedence(&has_attr) } - fn print_attrs(&mut self, attrs: &[hir::Attribute]) { + fn print_attrs(&mut self, attrs: &[Attribute]) { if attrs.is_empty() { return; } @@ -99,9 +99,9 @@ impl<'a> State<'a> { /// Print a single attribute as if it has style `style`, disregarding the /// actual style of the attribute. - fn print_attribute_as_style(&mut self, attr: &hir::Attribute, style: ast::AttrStyle) { + fn print_attribute_as_style(&mut self, attr: &Attribute, style: ast::AttrStyle) { match &attr { - hir::Attribute::Unparsed(unparsed) => { + Attribute::Unparsed(unparsed) => { self.maybe_print_comment(unparsed.span.lo()); match style { ast::AttrStyle::Inner => self.word("#!["), @@ -111,13 +111,13 @@ impl<'a> State<'a> { self.word("]"); self.hardbreak() } - hir::Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => { + Attribute::Parsed(AttributeKind::DocComment { kind, comment, .. }) => { self.word(rustc_ast_pretty::pprust::state::doc_comment_to_string( *kind, style, *comment, )); self.hardbreak() } - hir::Attribute::Parsed(pa) => { + Attribute::Parsed(pa) => { match style { ast::AttrStyle::Inner => self.word("#![attr = "), ast::AttrStyle::Outer => self.word("#[attr = "), @@ -129,7 +129,7 @@ impl<'a> State<'a> { } } - fn print_attr_item(&mut self, item: &hir::AttrItem, span: Span) { + fn print_attr_item(&mut self, item: &AttrItem, span: Span) { let ib = self.ibox(0); let path = ast::Path { span, @@ -146,21 +146,20 @@ impl<'a> State<'a> { }; match &item.args { - hir::AttrArgs::Delimited(DelimArgs { dspan: _, delim, tokens }) => self - .print_mac_common( - Some(MacHeader::Path(&path)), - false, - None, - *delim, - None, - &tokens, - true, - span, - ), - hir::AttrArgs::Empty => { + AttrArgs::Delimited(DelimArgs { dspan: _, delim, tokens }) => self.print_mac_common( + Some(MacHeader::Path(&path)), + false, + None, + *delim, + None, + &tokens, + true, + span, + ), + AttrArgs::Empty => { PrintState::print_path(self, &path, false, 0); } - hir::AttrArgs::Eq { eq_span: _, expr } => { + AttrArgs::Eq { eq_span: _, expr } => { PrintState::print_path(self, &path, false, 0); self.space(); self.word_space("="); @@ -277,7 +276,7 @@ pub fn print_crate<'a>( krate: &hir::Mod<'_>, filename: FileName, input: String, - attrs: &'a dyn Fn(HirId) -> &'a [hir::Attribute], + attrs: &'a dyn Fn(HirId) -> &'a [Attribute], ann: &'a dyn PpAnn, ) -> String { let mut s = State { @@ -311,7 +310,7 @@ where printer.s.eof() } -pub fn attribute_to_string(ann: &dyn PpAnn, attr: &hir::Attribute) -> String { +pub fn attribute_to_string(ann: &dyn PpAnn, attr: &Attribute) -> String { to_string(ann, |s| s.print_attribute_as_style(attr, ast::AttrStyle::Outer)) } diff --git a/compiler/rustc_middle/src/arena.rs b/compiler/rustc_middle/src/arena.rs index ee71d4d46e48f..a423b6bdca5b2 100644 --- a/compiler/rustc_middle/src/arena.rs +++ b/compiler/rustc_middle/src/arena.rs @@ -107,9 +107,9 @@ rustc_arena::declare_arena! { upvars_mentioned: rustc_data_structures::fx::FxIndexMap, dyn_compatibility_violations: rustc_middle::traits::DynCompatibilityViolation, codegen_unit: rustc_middle::mono::CodegenUnit<'tcx>, - attribute: rustc_hir::Attribute, + attribute: rustc_attr_ir::Attribute, name_set: rustc_data_structures::unord::UnordSet, - autodiff_item: rustc_hir::attrs::AutoDiffItem, + autodiff_item: rustc_attr_ir::AutoDiffItem, ordered_name_set: rustc_data_structures::fx::FxIndexSet, stable_order_of_exportable_impls: rustc_data_structures::fx::FxIndexMap, @@ -131,7 +131,7 @@ rustc_arena::declare_arena! { >, external_constraints: rustc_middle::traits::solve::ExternalConstraintsData>, doc_link_resolutions: rustc_middle::middle::resolve::DocLinkResMap, - stripped_cfg_items: rustc_hir::attrs::StrippedCfgItem, + stripped_cfg_items: rustc_attr_ir::StrippedCfgItem, mod_child: rustc_middle::middle::resolve::ModChild, features: rustc_feature::Features, specialization_graph: rustc_middle::traits::specialization_graph::Graph, @@ -204,9 +204,9 @@ impl_ref_decodable_into_arena! { Spanned>, rustc_ast::InlineAsmTemplatePiece, rustc_ast::tokenstream::TokenStream, + rustc_attr_ir::Attribute, rustc_data_structures::unord::UnordMap>>, rustc_data_structures::unord::UnordSet, - rustc_hir::Attribute, rustc_index::IndexVec>, rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs, rustc_middle::mir::Body<'tcx>, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index affadfd0c6aaf..664c85980addd 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -4,6 +4,7 @@ use rustc_abi::ExternAbi; use rustc_ast::visit::{VisitorResult, walk_list}; +use rustc_attr_ir::{Attribute, find_attr}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_data_structures::steal::Steal; diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index eae84fde7e305..d899ba0190f00 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -6,12 +6,13 @@ pub mod map; pub mod nested_filter; pub mod place; +use rustc_attr_ir::Attribute; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{DynSend, DynSync, try_par_for_each_in}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalDefIdMap, LocalModId}; use rustc_hir::lints::DelayedLints; diff --git a/compiler/rustc_middle/src/middle/debugger_visualizer.rs b/compiler/rustc_middle/src/middle/debugger_visualizer.rs index b6fc2d4f1a8d0..0fded7a77662d 100644 --- a/compiler/rustc_middle/src/middle/debugger_visualizer.rs +++ b/compiler/rustc_middle/src/middle/debugger_visualizer.rs @@ -1,7 +1,7 @@ use std::path::PathBuf; use std::sync::Arc; -use rustc_hir::attrs::DebuggerVisualizerType; +use rustc_attr_ir::DebuggerVisualizerType; use rustc_macros::{Decodable, Encodable, StableHash}; /// A single debugger visualizer file. diff --git a/compiler/rustc_middle/src/middle/lang_items.rs b/compiler/rustc_middle/src/middle/lang_items.rs index 829df12ff543c..9d07c2edeb386 100644 --- a/compiler/rustc_middle/src/middle/lang_items.rs +++ b/compiler/rustc_middle/src/middle/lang_items.rs @@ -7,7 +7,7 @@ //! * Traits that represent operators; e.g., `Add`, `Sub`, `Index`. //! * Functions called by the compiler itself. -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_span::Span; use rustc_target::spec::PanicStrategy; diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs index 4c4a16953d5ed..6bb0190cd70b8 100644 --- a/compiler/rustc_middle/src/mir/syntax.rs +++ b/compiler/rustc_middle/src/mir/syntax.rs @@ -1712,7 +1712,7 @@ pub enum BinOp { /// - `Ordering::Equal` (`0_i8`, as a Scalar) if `A == B` /// - `Ordering::Greater` (`+1_i8`, as a Scalar) if `A > B` /// - /// [`LangItem::OrderingEnum`]: rustc_hir::attrs::lang_items::LangItem + /// [`LangItem::OrderingEnum`]: rustc_attr_ir::lang_items::LangItem Cmp, /// The `ptr.offset` operator Offset, diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index cc75bebbb3f93..2d51f382f0998 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -3,9 +3,9 @@ use std::slice; use rustc_ast::InlineAsmOptions; +use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::packed::Pu128; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::bug; use smallvec::{SmallVec, smallvec}; diff --git a/compiler/rustc_middle/src/mono.rs b/compiler/rustc_middle/src/mono.rs index 76828cbee60f1..a54ca4faf81ee 100644 --- a/compiler/rustc_middle/src/mono.rs +++ b/compiler/rustc_middle/src/mono.rs @@ -2,6 +2,7 @@ use std::borrow::Cow; use std::fmt; use std::hash::Hash; +use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexMap; @@ -11,7 +12,6 @@ use rustc_data_structures::stable_hash::{ use rustc_data_structures::unord::UnordMap; use rustc_hashes::Hash128; use rustc_hir::ItemId; -use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE}; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use rustc_session::config::OptLevel; diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 9e1bafa4fd2a2..cb39c17cd4023 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -53,6 +53,7 @@ use rustc_arena::TypedArena; use rustc_ast as ast; use rustc_ast::expand::allocator::AllocatorKind; use rustc_ast::tokenstream::TokenStream; +use rustc_attr_ir::diagnostic_items::DiagnosticItems; use rustc_attr_ir::lang_items::{LangItem, LanguageItems}; use rustc_attr_ir::{CanonicalSymbols, EiiDecl, EiiImpl, StrippedCfgItem}; use rustc_crate_store::{ @@ -1493,19 +1494,19 @@ rustc_queries! { cache_on_disk } - query lookup_stability(def_id: DefId) -> Option { + query lookup_stability(def_id: DefId) -> Option { desc { "looking up stability of `{}`", tcx.def_path_str(def_id) } cache_on_disk separate_provide_extern } - query lookup_const_stability(def_id: DefId) -> Option { + query lookup_const_stability(def_id: DefId) -> Option { desc { "looking up const stability of `{}`", tcx.def_path_str(def_id) } cache_on_disk separate_provide_extern } - query lookup_default_body_stability(def_id: DefId) -> Option { + query lookup_default_body_stability(def_id: DefId) -> Option { desc { "looking up default body stability of `{}`", tcx.def_path_str(def_id) } separate_provide_extern } @@ -2302,7 +2303,7 @@ rustc_queries! { } /// Returns all diagnostic items defined in all crates. - query all_diagnostic_items(_: ()) -> &'tcx rustc_hir::attrs::diagnostic_items::DiagnosticItems { + query all_diagnostic_items(_: ()) -> &'tcx DiagnosticItems { arena_cache eval_always desc { "calculating the diagnostic items map" } @@ -2322,7 +2323,7 @@ rustc_queries! { } /// Returns the diagnostic items defined in a crate. - query diagnostic_items(_: CrateNum) -> &'tcx rustc_hir::attrs::diagnostic_items::DiagnosticItems { + query diagnostic_items(_: CrateNum) -> &'tcx DiagnosticItems { arena_cache desc { "calculating the diagnostic items map in a crate" } separate_provide_extern diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs index 15a684491dcab..b0281a70eeb73 100644 --- a/compiler/rustc_middle/src/query/erase.rs +++ b/compiler/rustc_middle/src/query/erase.rs @@ -185,11 +185,11 @@ impl_erasable_for_types_with_no_type_params! { Option<(rustc_span::def_id::DefId, rustc_session::config::EntryFnType)>, Option, Option, + Option, + Option, + Option, Option, - Option, Option, - Option, - Option, Option, Option, Option, diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index b20dfe68d98e2..69d518bf82786 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -15,10 +15,10 @@ use std::sync::Arc; use rustc_abi::{FieldIdx, Integer, Size, VariantIdx}; use rustc_ast::{AsmMacro, InlineAsmOptions, InlineAsmTemplatePiece, Mutability}; +use rustc_attr_ir::AttributeKind; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::DefId; use rustc_hir::{BindingMode, ByRef, HirId, MatchSource, RangeEnd}; use rustc_index::{IndexVec, newtype_index}; diff --git a/compiler/rustc_middle/src/traits/specialization_graph.rs b/compiler/rustc_middle/src/traits/specialization_graph.rs index 19b72d1a7d1c4..b13af2705c736 100644 --- a/compiler/rustc_middle/src/traits/specialization_graph.rs +++ b/compiler/rustc_middle/src/traits/specialization_graph.rs @@ -1,7 +1,7 @@ +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def_id::{DefId, DefIdMap}; -use rustc_hir::find_attr; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use crate::diagnostics::StrictCoherenceNeedsNegativeCoherence; diff --git a/compiler/rustc_middle/src/ty/adjustment.rs b/compiler/rustc_middle/src/ty/adjustment.rs index 00efbe912b883..b3a2925b24bfa 100644 --- a/compiler/rustc_middle/src/ty/adjustment.rs +++ b/compiler/rustc_middle/src/ty/adjustment.rs @@ -1,6 +1,6 @@ use rustc_abi::FieldIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; use rustc_span::Span; diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs index d189fbc5d59bd..8ad5de3fa85cc 100644 --- a/compiler/rustc_middle/src/ty/adt.rs +++ b/compiler/rustc_middle/src/ty/adt.rs @@ -4,6 +4,8 @@ use std::ops::Range; use std::str; use rustc_abi::{FIRST_VARIANT, FieldIdx, ReprOptions, VariantIdx}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::intern::Interned; @@ -11,10 +13,9 @@ use rustc_data_structures::stable_hash::{ StableHash, StableHashControls, StableHashCtxt, StableHasher, }; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, find_attr}; use rustc_index::{IndexSlice, IndexVec}; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use rustc_session::DataTypeKind; diff --git a/compiler/rustc_middle/src/ty/consts/lit.rs b/compiler/rustc_middle/src/ty/consts/lit.rs index 08dadf6ad9f5f..9dd8c958cd2f0 100644 --- a/compiler/rustc_middle/src/ty/consts/lit.rs +++ b/compiler/rustc_middle/src/ty/consts/lit.rs @@ -1,6 +1,5 @@ use rustc_ast::{LitFloatType, LitIntType, LitKind}; -use rustc_hir; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_macros::StableHash; use crate::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 4009191430afb..9edb12949f4cf 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -17,6 +17,8 @@ use std::{debug_assert_matches, fmt, iter, mem}; use rustc_abi::{ExternAbi, FieldIdx, Layout, LayoutData, TargetDataLayout, VariantIdx}; use rustc_ast as ast; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{CrateStoreDyn, Untracked}; use rustc_data_structures::defer; use rustc_data_structures::fx::FxHashMap; @@ -29,12 +31,11 @@ use rustc_data_structures::sync::{ self, DynSend, DynSync, FreezeReadGuard, Lock, RwLock, WorkerLocal, }; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, MultiSpan}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::definitions::{DefPathData, Definitions, PerParentDisambiguatorState}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, Node, TraitCandidate, find_attr}; +use rustc_hir::{self as hir, CRATE_HIR_ID, HirId, Node, TraitCandidate}; use rustc_index::IndexVec; use rustc_lint_defs::Lint; use rustc_lint_defs::builtin::UNUSED_FEATURES; @@ -990,7 +991,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Obtain all lang items of this crate and all dependencies (recursively) - pub fn lang_items(self) -> &'tcx rustc_hir::attrs::lang_items::LanguageItems { + pub fn lang_items(self) -> &'tcx rustc_attr_ir::lang_items::LanguageItems { self.get_lang_items(()) } diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index f13797b48fcbf..fdaf5cacfbf27 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -2,10 +2,10 @@ use std::{debug_assert_matches, fmt}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::intern::Interned; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_span::{DUMMY_SP, Span, Symbol, bug}; diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs index 1f2a9aca60142..df1daac366c53 100644 --- a/compiler/rustc_middle/src/ty/diagnostics.rs +++ b/compiler/rustc_middle/src/ty/diagnostics.rs @@ -3,9 +3,9 @@ use std::fmt::Write; use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::{Applicability, Diag, DiagArgValue, IntoDiagArg, listify, pluralize}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, AmbigArg, PredicateOrigin, WherePredicateKind}; diff --git a/compiler/rustc_middle/src/ty/instance.rs b/compiler/rustc_middle/src/ty/instance.rs index 44e5a875a74ae..1a00293f8ffc6 100644 --- a/compiler/rustc_middle/src/ty/instance.rs +++ b/compiler/rustc_middle/src/ty/instance.rs @@ -1,9 +1,9 @@ use std::{assert_matches, fmt}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashMap; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_macros::{Lift, StableHash, TyDecodable, TyEncodable}; @@ -231,7 +231,7 @@ impl<'tcx> Instance<'tcx> { if !tcx.sess.opts.share_generics() // However, if the def_id is marked inline(never), then it's fine to just reuse the // upstream monomorphization. - && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_hir::attrs::InlineAttr::Never + && tcx.codegen_fn_attrs(self.def_id()).inline != rustc_attr_ir::InlineAttr::Never { return None; } diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 1e4e96ceed576..7952b97e94e13 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -6,9 +6,9 @@ use rustc_abi::{ PointerKind, Primitive, ReprFlags, ReprOptions, Scalar, Size, TagEncoding, TargetDataLayout, TyAbiInterface, VariantIdx, Variants, }; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, IntoDiagArg, Level}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; use rustc_session::config::OptLevel; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index c7de3afb7cd3c..1f2ffb17cc2c7 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -1870,7 +1870,7 @@ impl<'tcx> TyCtxt<'tcx> { } /// Gets all attributes with the given name. - #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call rustc_hir::find_attr! instead."] + #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to use `rustc_attr_ir::find_attr!` instead."] pub fn get_attrs( self, did: impl Into, @@ -1889,7 +1889,7 @@ impl<'tcx> TyCtxt<'tcx> { /// /// /// - #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to call rustc_hir::find_attr! instead."] + #[deprecated = "Though there are valid usecases for this method, especially when your attribute is not a parsed attribute, usually you want to use `rustc_attr_ir::find_attr!` instead."] pub fn get_all_attrs(self, did: impl Into) -> &'tcx [rustc_attr_ir::Attribute] { let did: DefId = did.into(); if let Some(did) = did.as_local() { diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 3ba7ea6d43794..cafe93c591090 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -6,11 +6,11 @@ use std::ops::{Deref, DerefMut}; use rustc_abi::{ExternAbi, Size}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{ExternCrate, ExternCrateSource}; use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_data_structures::unord::UnordMap; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{self, CtorKind, DefKind, Namespace}; use rustc_hir::def_id::{DefIdMap, DefIdSet, LOCAL_CRATE, ModId}; use rustc_hir::definitions::{DefKey, DefPathDataName}; diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 02107fee370cb..3710a159b3fdd 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -217,11 +217,11 @@ TrivialTypeTraversalImpls! { rustc_abi::VariantIdx, rustc_ast::InlineAsmOptions, rustc_ast::InlineAsmTemplatePiece, + rustc_attr_ir::AttributeKind, rustc_hir::CoroutineKind, rustc_hir::HirId, rustc_hir::MatchSource, rustc_hir::RangeEnd, - rustc_hir::attrs::AttributeKind, rustc_hir::def_id::LocalDefId, rustc_span::Ident, rustc_span::Span, diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index fe569bf282d36..c32ddb724e71e 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -8,9 +8,9 @@ use std::ops::{ControlFlow, Range}; use hir::def::{CtorKind, DefKind}; use rustc_abi::{FIRST_VARIANT, FieldIdx, NumScalableVectors, ScalableElt, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, extension}; use rustc_span::{DUMMY_SP, Span, Symbol, bug, kw, sym}; diff --git a/compiler/rustc_middle/src/ty/trait_def.rs b/compiler/rustc_middle/src/ty/trait_def.rs index fce9af1c465af..114e5331b8b9b 100644 --- a/compiler/rustc_middle/src/ty/trait_def.rs +++ b/compiler/rustc_middle/src/ty/trait_def.rs @@ -1,10 +1,11 @@ use std::iter; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::ErrorGuaranteed; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{self as hir, find_attr}; use rustc_macros::{Decodable, Encodable, StableHash}; use rustc_span::{Span, bug}; use tracing::debug; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index a66d15299f16c..ac16d9da6867d 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -4,13 +4,14 @@ use std::{fmt, iter}; use rustc_abi::{Float, Integer, IntegerType, Size}; use rustc_apfloat::Float as _; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_errors::ErrorGuaranteed; use rustc_hashes::Hash128; +use rustc_hir as hir; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; -use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::GrowableBitSet; use rustc_macros::{StableHash, TyDecodable, TyEncodable, extension}; use rustc_span::{bug, span_bug, sym}; diff --git a/compiler/rustc_passes/src/abi_test.rs b/compiler/rustc_passes/src/abi_test.rs index f2b98f1fa2c03..1a2ccc75d0bcf 100644 --- a/compiler/rustc_passes/src/abi_test.rs +++ b/compiler/rustc_passes/src/abi_test.rs @@ -1,7 +1,6 @@ -use rustc_hir::attrs::RustcAbiAttrKind; +use rustc_attr_ir::{RustcAbiAttrKind, find_attr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::layout::{FnAbiError, LayoutError}; use rustc_middle::ty::{self, GenericArgs, Instance, Ty, TyCtxt}; use rustc_span::{Span, span_bug}; diff --git a/compiler/rustc_passes/src/canonical_symbols.rs b/compiler/rustc_passes/src/canonical_symbols.rs index 7a67a46c5a738..afecab452bf3d 100644 --- a/compiler/rustc_passes/src/canonical_symbols.rs +++ b/compiler/rustc_passes/src/canonical_symbols.rs @@ -1,5 +1,5 @@ -use rustc_hir::attrs::CanonicalSymbols; -use rustc_hir::{ForeignItemId, find_attr}; +use rustc_attr_ir::{CanonicalSymbols, find_attr}; +use rustc_hir::ForeignItemId; use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::{Instance, List, TyCtxt}; use rustc_span::def_id::{DefId, LOCAL_CRATE}; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index f6bd780802401..4926ec9872d3b 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -10,23 +10,23 @@ use std::slice; use rustc_abi::ExternAbi; use rustc_ast::MetaItemKind; +use rustc_attr_ir::diagnostic::Directive; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::{AssocCtxt, MethodKind, Target}; +use rustc_attr_ir::{ + Attribute, AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, + InlineAttr, OptimizeAttr, ReprAttr, find_attr, +}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg}; use rustc_feature::BUILTIN_ATTRIBUTE_SET; -use rustc_hir::attrs::diagnostic::Directive; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{ - AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, - OptimizeAttr, ReprAttr, -}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, AssocCtxt, Attribute, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, - GenericParamKind, HirId, Item, ItemKind, MethodKind, Mod, Node, ParamName, Target, TraitItem, - find_attr, + self as hir, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, GenericParamKind, + HirId, Item, ItemKind, Mod, Node, ParamName, TraitItem, }; use rustc_lint_defs::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES, diff --git a/compiler/rustc_passes/src/debugger_visualizer.rs b/compiler/rustc_passes/src/debugger_visualizer.rs index 91e7c69c2efdb..f5aa163d59a6e 100644 --- a/compiler/rustc_passes/src/debugger_visualizer.rs +++ b/compiler/rustc_passes/src/debugger_visualizer.rs @@ -1,9 +1,8 @@ //! Detecting usage of the `#[debugger_visualizer]` attribute. use rustc_ast::{ItemKind, ast}; +use rustc_attr_ir::{Attribute, AttributeKind, DebugVisualizer}; use rustc_attr_parsing::AttributeParser; -use rustc_hir::Attribute; -use rustc_hir::attrs::{AttributeKind, DebugVisualizer}; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_passes/src/diagnostic_items.rs b/compiler/rustc_passes/src/diagnostic_items.rs index 74cd94259f4b4..1f17edb3254e3 100644 --- a/compiler/rustc_passes/src/diagnostic_items.rs +++ b/compiler/rustc_passes/src/diagnostic_items.rs @@ -9,8 +9,9 @@ //! //! * Compiler internal types like `Ty` and `TyCtxt` -use rustc_hir::attrs::diagnostic_items::DiagnosticItems; -use rustc_hir::{CRATE_OWNER_ID, OwnerId, find_attr}; +use rustc_attr_ir::diagnostic_items::DiagnosticItems; +use rustc_attr_ir::find_attr; +use rustc_hir::{CRATE_OWNER_ID, OwnerId}; use rustc_middle::query::{LocalCrate, Providers}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, LOCAL_CRATE}; diff --git a/compiler/rustc_passes/src/eii.rs b/compiler/rustc_passes/src/eii.rs index 05cb10e174d89..4daff2358e87f 100644 --- a/compiler/rustc_passes/src/eii.rs +++ b/compiler/rustc_passes/src/eii.rs @@ -3,8 +3,8 @@ use std::iter; +use rustc_attr_ir::{EiiDecl, EiiImpl}; use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::attrs::{EiiDecl, EiiImpl}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; use rustc_middle::diagnostics::DuplicateEiiImpls; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 68be74886a2e4..0306a0bc349af 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -9,9 +9,9 @@ use rustc_ast as ast; use rustc_ast::visit; +use rustc_attr_ir::lang_items::{GenericRequirement, LangItem, LanguageItems}; +use rustc_attr_ir::target::Target; use rustc_crate_store::ExternCrate; -use rustc_hir::Target; -use rustc_hir::attrs::lang_items::{GenericRequirement, LangItem, LanguageItems}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::middle::resolve::ResolverAstLowering; use rustc_middle::query::Providers; diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs index f73916d861f27..961d39ec8e5ca 100644 --- a/compiler/rustc_passes/src/layout_test.rs +++ b/compiler/rustc_passes/src/layout_test.rs @@ -1,8 +1,7 @@ use rustc_abi::{HasDataLayout, TargetDataLayout}; -use rustc_hir::attrs::RustcDumpLayoutKind; +use rustc_attr_ir::{RustcDumpLayoutKind, find_attr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutError, LayoutOfHelpers}; use rustc_middle::ty::{self, Ty, TyCtxt, Unnormalized}; use rustc_span::{Span, span_bug}; diff --git a/compiler/rustc_passes/src/lib_features.rs b/compiler/rustc_passes/src/lib_features.rs index ceaad91d25982..2420d55545805 100644 --- a/compiler/rustc_passes/src/lib_features.rs +++ b/compiler/rustc_passes/src/lib_features.rs @@ -4,9 +4,8 @@ //! but are not declared in one single location (unlike lang features), which means we need to //! collect them instead. -use rustc_hir::attrs::AttributeKind; +use rustc_attr_ir::{Attribute, AttributeKind, StabilityLevel, StableSince}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{Attribute, StabilityLevel, StableSince}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; use rustc_middle::query::{LocalCrate, Providers}; diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index b2535b4c4d9c0..1148aac51f3e8 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -4,17 +4,19 @@ use std::num::NonZero; use rustc_ast_lowering::stability::extern_abi_stability; +use rustc_attr_ir::{ + AttributeKind, ConstStability, DefaultBodyStability, DeprecatedSince, Stability, + StabilityLevel, StableSince, UnstableReason, VERSION_PLACEHOLDER, find_attr, +}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_feature::{EnabledLangFeature, EnabledLibFeature, UNSTABLE_LANG_FEATURES}; -use rustc_hir::attrs::{AttributeKind, DeprecatedSince}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, AmbigArg, ConstStability, Constness, DefaultBodyStability, FieldDef, HirId, Item, - ItemKind, Path, Stability, StabilityLevel, StableSince, TraitRef, Ty, TyKind, UnstableReason, - UsePath, VERSION_PLACEHOLDER, Variant, find_attr, + self as hir, AmbigArg, Constness, FieldDef, HirId, Item, ItemKind, Path, TraitRef, Ty, TyKind, + UsePath, Variant, }; use rustc_lint_defs::builtin::{ DEPRECATED, DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_REEXPORTS, diff --git a/compiler/rustc_passes/src/weak_lang_items.rs b/compiler/rustc_passes/src/weak_lang_items.rs index e7042767f8bae..42e07bc0eaaee 100644 --- a/compiler/rustc_passes/src/weak_lang_items.rs +++ b/compiler/rustc_passes/src/weak_lang_items.rs @@ -1,8 +1,8 @@ //! Validity checking for weak lang items +use rustc_attr_ir::lang_items::{self, LangItem}; +use rustc_attr_ir::weak_lang_items::WEAK_LANG_ITEMS; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::lang_items::{self, LangItem}; -use rustc_hir::attrs::weak_lang_items::WEAK_LANG_ITEMS; use rustc_middle::middle::lang_items::required; use rustc_middle::ty::TyCtxt; use rustc_structures::CrateType; diff --git a/compiler/rustc_resolve/Cargo.toml b/compiler/rustc_resolve/Cargo.toml index 19a4ee5a55ff7..a635f7853d971 100644 --- a/compiler/rustc_resolve/Cargo.toml +++ b/compiler/rustc_resolve/Cargo.toml @@ -13,6 +13,7 @@ pulldown-cmark = { version = "0.11", features = [ rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 89ea973cb3ff8..ee35d23691628 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -2,11 +2,10 @@ use std::mem; use rustc_ast::visit::FnKind; use rustc_ast::*; -use rustc_attr_parsing as attr; +use rustc_attr_ir::target::Target; use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_expand::expand::AstFragment; use rustc_hir as hir; -use rustc_hir::Target; use rustc_hir::def::DefKind; use rustc_hir::def::Namespace::{TypeNS, ValueNS}; use rustc_hir::def_id::LocalDefId; @@ -558,7 +557,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { let orig_in_attr = mem::replace(&mut self.invocation_parent.in_attr, true); match &attr.kind { AttrKind::Normal(normal) => { - if attr::is_builtin_attr(&normal.item) { + if rustc_attr_parsing::is_builtin_attr(&normal.item) { self.r .builtin_attrs .push((normal.item.path.segments[0].ident, self.parent_scope)); diff --git a/compiler/rustc_symbol_mangling/Cargo.toml b/compiler/rustc_symbol_mangling/Cargo.toml index bb79bb3ece781..1e078015257d7 100644 --- a/compiler/rustc_symbol_mangling/Cargo.toml +++ b/compiler/rustc_symbol_mangling/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" punycode = "0.4.0" rustc-demangle = "0.1.28" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index a4364cc20b68e..646a916fb5085 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -4,7 +4,8 @@ //! def-path. This is used for unit testing the code that generates //! paths etc in all kinds of annoying scenarios. -use rustc_hir::{CRATE_OWNER_ID, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::CRATE_OWNER_ID; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{GenericArgs, Instance, TyCtxt}; diff --git a/compiler/rustc_transmute/Cargo.toml b/compiler/rustc_transmute/Cargo.toml index 5da9435e77e63..55e2f7e99b869 100644 --- a/compiler/rustc_transmute/Cargo.toml +++ b/compiler/rustc_transmute/Cargo.toml @@ -6,8 +6,8 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi", optional = true } +rustc_attr_ir = { path = "../rustc_attr_ir", optional = true } rustc_data_structures = { path = "../rustc_data_structures" } -rustc_hir = { path = "../rustc_hir", optional = true } rustc_middle = { path = "../rustc_middle", optional = true } rustc_span = { path = "../rustc_span", optional = true } smallvec = "1.8.1" @@ -23,7 +23,7 @@ itertools = "0.15" # tidy-alphabetical-start rustc = [ "dep:rustc_abi", - "dep:rustc_hir", + "dep:rustc_attr_ir", "dep:rustc_middle", "dep:rustc_span", ] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index 53287dbe331ee..cb5a76b51df1b 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -103,7 +103,7 @@ pub enum Reason { #[cfg(feature = "rustc")] mod rustc { - use rustc_hir::attrs::lang_items::LangItem; + use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{Const, Region, Ty, TyCtxt}; diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml index e6de7bd1fab24..5ac4d72a6c573 100644 --- a/compiler/rustc_ty_utils/Cargo.toml +++ b/compiler/rustc_ty_utils/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start itertools = "0.15" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hashes = { path = "../rustc_hashes" } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index 55140d2c5458d..bcba5839926db 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -2,7 +2,7 @@ use std::{assert_matches, iter}; use rustc_abi::Primitive::Pointer; use rustc_abi::{Align, BackendRepr, ExternAbi, PointerKind, Scalar, Size}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{self as hir, find_attr}; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::query::Providers; diff --git a/compiler/rustc_ty_utils/src/common_traits.rs b/compiler/rustc_ty_utils/src/common_traits.rs index 4d25a2886fa27..48e2a68bec7f6 100644 --- a/compiler/rustc_ty_utils/src/common_traits.rs +++ b/compiler/rustc_ty_utils/src/common_traits.rs @@ -1,6 +1,6 @@ //! Queries for checking whether a type implements one of a few common traits. -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_ty_utils/src/instance.rs b/compiler/rustc_ty_utils/src/instance.rs index f0f0a66a8eeba..9a41caafc6da6 100644 --- a/compiler/rustc_ty_utils/src/instance.rs +++ b/compiler/rustc_ty_utils/src/instance.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index dee4b785e418d..43af74d10aba7 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -9,9 +9,9 @@ use rustc_abi::{ LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; +use rustc_attr_ir::lang_items::LangItem; use rustc_hashes::Hash64; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::find_attr; use rustc_index::{Idx as _, IndexVec}; use rustc_middle::query::Providers; diff --git a/compiler/rustc_ty_utils/src/structural_match.rs b/compiler/rustc_ty_utils/src/structural_match.rs index 85d13cfda743b..7dd596fa5bdfc 100644 --- a/compiler/rustc_ty_utils/src/structural_match.rs +++ b/compiler/rustc_ty_utils/src/structural_match.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::query::Providers; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; diff --git a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs index e3b1a05bda7dd..ff929df0acded 100644 --- a/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs +++ b/src/tools/clippy/clippy_lints/src/attrs/deprecated_semver.rs @@ -2,7 +2,7 @@ use super::DEPRECATED_SEMVER; use clippy_utils::diagnostics::span_lint; use clippy_utils::sym; use rustc_ast::{LitKind, MetaItemLit}; -use rustc_hir::VERSION_PLACEHOLDER; +use rustc_attr_ir::VERSION_PLACEHOLDER; use rustc_lint::EarlyContext; use rustc_span::Span; use semver::Version; diff --git a/src/tools/clippy/clippy_lints/src/missing_doc.rs b/src/tools/clippy/clippy_lints/src/missing_doc.rs index af2c84737c655..2ef893edd4236 100644 --- a/src/tools/clippy/clippy_lints/src/missing_doc.rs +++ b/src/tools/clippy/clippy_lints/src/missing_doc.rs @@ -1,11 +1,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::{is_doc_hidden, is_from_proc_macro}; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{AttrArgs, Attribute, AttributeKind}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{ - AttrArgs, Attribute, Body, BodyId, FieldDef, HirId, ImplItem, Item, ItemKind, Node, TraitItem, Variant, -}; +use rustc_hir::{Body, BodyId, FieldDef, HirId, ImplItem, Item, ItemKind, Node, TraitItem, Variant}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::middle::privacy::Level; use rustc_middle::ty::Visibility; diff --git a/tests/ui-fulldeps/internal-lints/find_attr.rs b/tests/ui-fulldeps/internal-lints/find_attr.rs index 90b9b96ba54ef..f2ee921c731f4 100644 --- a/tests/ui-fulldeps/internal-lints/find_attr.rs +++ b/tests/ui-fulldeps/internal-lints/find_attr.rs @@ -4,9 +4,9 @@ #![feature(rustc_private)] #![deny(rustc::bad_use_of_find_attr)] -extern crate rustc_hir; +extern crate rustc_attr_ir; -use rustc_hir::{attrs::AttributeKind, find_attr}; +use rustc_attr_ir::{AttributeKind, find_attr}; fn main() { let attrs = &[]; diff --git a/tests/ui-fulldeps/polymorphic-drop-glue.rs b/tests/ui-fulldeps/polymorphic-drop-glue.rs index 861c7c74b705c..4d85d342d7395 100644 --- a/tests/ui-fulldeps/polymorphic-drop-glue.rs +++ b/tests/ui-fulldeps/polymorphic-drop-glue.rs @@ -6,6 +6,7 @@ //@ ignore-backends: gcc #![feature(rustc_private)] +extern crate rustc_attr_ir; extern crate rustc_driver; extern crate rustc_hir; extern crate rustc_interface; @@ -16,7 +17,7 @@ extern crate rustc_span; use std::process::ExitCode; use rustc_driver::Compilation; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_interface::interface::Compiler; use rustc_middle::ty::{self, TyCtxt}; From ad4c7db31a8ba27d458655001e6d333f220867c9 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 22 Sep 2026 20:12:57 +0200 Subject: [PATCH 0670/1309] Update deprecated rustc_hir imports --- clippy_lints/src/attrs/deprecated_semver.rs | 2 +- clippy_lints/src/missing_doc.rs | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/attrs/deprecated_semver.rs b/clippy_lints/src/attrs/deprecated_semver.rs index e3b1a05bda7dd..ff929df0acded 100644 --- a/clippy_lints/src/attrs/deprecated_semver.rs +++ b/clippy_lints/src/attrs/deprecated_semver.rs @@ -2,7 +2,7 @@ use super::DEPRECATED_SEMVER; use clippy_utils::diagnostics::span_lint; use clippy_utils::sym; use rustc_ast::{LitKind, MetaItemLit}; -use rustc_hir::VERSION_PLACEHOLDER; +use rustc_attr_ir::VERSION_PLACEHOLDER; use rustc_lint::EarlyContext; use rustc_span::Span; use semver::Version; diff --git a/clippy_lints/src/missing_doc.rs b/clippy_lints/src/missing_doc.rs index af2c84737c655..2ef893edd4236 100644 --- a/clippy_lints/src/missing_doc.rs +++ b/clippy_lints/src/missing_doc.rs @@ -1,11 +1,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint; use clippy_utils::{is_doc_hidden, is_from_proc_macro}; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{AttrArgs, Attribute, AttributeKind}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{ - AttrArgs, Attribute, Body, BodyId, FieldDef, HirId, ImplItem, Item, ItemKind, Node, TraitItem, Variant, -}; +use rustc_hir::{Body, BodyId, FieldDef, HirId, ImplItem, Item, ItemKind, Node, TraitItem, Variant}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::middle::privacy::Level; use rustc_middle::ty::Visibility; From 0109ed292f8f5b23a067f94df215e62996958b1b Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:14:29 +0200 Subject: [PATCH 0671/1309] BTree: make dropping an empty BTreeMap free --- library/alloc/src/collections/btree/map.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index e8ee6fa628bfa..9876e1c131122 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -205,8 +205,11 @@ pub struct BTreeMap< #[stable(feature = "btree_drop", since = "1.7.0")] unsafe impl<#[may_dangle] K, #[may_dangle] V, A: AllocatorClone> Drop for BTreeMap { fn drop(&mut self) { - // ignore-tidy-undocumented-unsafe - drop(unsafe { ptr::read(self) }.into_iter()) + if self.root.is_some() { + drop(unsafe { ptr::read(self) }.into_iter()) + } else { + unsafe { ManuallyDrop::drop(&mut self.alloc) } + } } } From 756abe8393782352f5badfbee2dcc88334c5f1e2 Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:14:29 +0200 Subject: [PATCH 0672/1309] Adding codegen for the empty BTree drop --- tests/codegen-llvm/btree-empty-drop.rs | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 tests/codegen-llvm/btree-empty-drop.rs diff --git a/tests/codegen-llvm/btree-empty-drop.rs b/tests/codegen-llvm/btree-empty-drop.rs new file mode 100644 index 0000000000000..4e08920f55dbf --- /dev/null +++ b/tests/codegen-llvm/btree-empty-drop.rs @@ -0,0 +1,15 @@ +// Regression test for https://github.com/rust-lang/rust/issues/161375 +// Checking that an empty BTree's drop is optimized away. +//@ compile-flags: -Copt-level=3 + +#![crate_type = "lib"] + +use std::collections::BTreeMap; + +// CHECK-LABEL: @drop_btree +// CHECK-NOT: dying_next +// CHECK: ret void +#[no_mangle] +pub fn drop_btree() { + let _ = BTreeMap::<(), ()>::new(); +} From 15831b0a64907b45e98f1b55eaa060cb1c368fce Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:14:29 +0200 Subject: [PATCH 0673/1309] BTree: documenting the unsafe in the empty map drop --- library/alloc/src/collections/btree/map.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 9876e1c131122..1f479569705f8 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -206,8 +206,11 @@ pub struct BTreeMap< unsafe impl<#[may_dangle] K, #[may_dangle] V, A: AllocatorClone> Drop for BTreeMap { fn drop(&mut self) { if self.root.is_some() { + // ignore-tidy-undocumented-unsafe drop(unsafe { ptr::read(self) }.into_iter()) } else { + // SAFETY: With no root there are no nodes to free, so only the allocator needs + // dropping. `self` is not used after this, and `alloc` is dropped only here. unsafe { ManuallyDrop::drop(&mut self.alloc) } } } From 70ff620dc79853f245a9010de8773847e0512bcf Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Wed, 23 Sep 2026 01:14:29 +0200 Subject: [PATCH 0674/1309] Check for dealloc instead of dying_next --- tests/codegen-llvm/btree-empty-drop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/codegen-llvm/btree-empty-drop.rs b/tests/codegen-llvm/btree-empty-drop.rs index 4e08920f55dbf..60e3c3b0c9a70 100644 --- a/tests/codegen-llvm/btree-empty-drop.rs +++ b/tests/codegen-llvm/btree-empty-drop.rs @@ -7,7 +7,7 @@ use std::collections::BTreeMap; // CHECK-LABEL: @drop_btree -// CHECK-NOT: dying_next +// CHECK-NOT: dealloc // CHECK: ret void #[no_mangle] pub fn drop_btree() { From 1b5517299cbe9c2f6b7137f32786e3dadadfc2ae Mon Sep 17 00:00:00 2001 From: Tom Anderson Date: Thu, 3 Sep 2026 19:33:26 +1000 Subject: [PATCH 0675/1309] improve doc attr span tracking for proc-macro --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 2 + .../src/arbitrary_source_item_ordering.rs | 14 +-- clippy_lints/src/attrs/mod.rs | 38 +++---- clippy_lints/src/bool_to_int_with_if.rs | 2 +- clippy_lints/src/crate_in_macro_def.rs | 2 +- clippy_lints/src/default.rs | 2 +- clippy_lints/src/doc/mod.rs | 24 +++-- clippy_lints/src/loops/mod.rs | 2 +- clippy_lints/src/main_recursion.rs | 6 +- clippy_lints/src/methods/mod.rs | 15 ++- clippy_lints/src/misc_early/mod.rs | 14 +-- .../src/missing_const_for_thread_local.rs | 2 +- clippy_lints/src/strlen_on_c_strings.rs | 2 +- clippy_lints/src/suspicious_trait_impl.rs | 4 +- clippy_lints/src/swap.rs | 2 +- clippy_lints/src/transmute/mod.rs | 2 +- clippy_lints/src/unit_return_expecting_ord.rs | 8 +- clippy_lints/src/unnecessary_self_imports.rs | 2 +- clippy_lints/src/write/mod.rs | 10 +- .../src/collapsible_span_lint_calls.rs | 2 +- .../src/unsorted_clippy_utils_paths.rs | 2 +- tests/ui/doc_unsafe.rs | 18 ++++ tests/ui/doc_unsafe.stderr | 8 +- tests/ui/empty_docs.rs | 11 +++ tests/ui/empty_docs.stderr | 29 ++++-- tests/ui/missing_panics_doc.rs | 32 ++++++ tests/ui/missing_panics_doc.stderr | 98 ++++++++++++------- 28 files changed, 232 insertions(+), 123 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index f323d7040d260..b99ae21eaace6 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -640,7 +640,7 @@ default configuration of Clippy. By default, any configuration will replace the * `doc-valid-idents = ["ClipPy"]` would replace the default list with `["ClipPy"]`. * `doc-valid-idents = ["ClipPy", ".."]` would append `ClipPy` to the default list. -**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebAuthn", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase"]` +**Default Value:** `["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "MHz", "GHz", "THz", "AccessKit", "CoAP", "CoreFoundation", "CoreGraphics", "CoreText", "DevOps", "Direct2D", "Direct3D", "DirectWrite", "DirectX", "ECMAScript", "GPLv2", "GPLv3", "GitHub", "GitLab", "IPv4", "IPv6", "InfiniBand", "RoCE", "ClojureScript", "CoffeeScript", "JavaScript", "PostScript", "PureScript", "TypeScript", "PowerPC", "PowerShell", "WebAssembly", "NaN", "NaNs", "OAuth", "GraphQL", "SQLite", "MySQL", "PostgreSQL", "MariaDB", "MongoDB", "OCaml", "OpenAL", "OpenDNS", "OpenGL", "OpenMP", "OpenSSH", "OpenSSL", "OpenStreetMap", "OpenTelemetry", "OpenType", "WebAuthn", "WebGL", "WebGL2", "WebGPU", "WebRTC", "WebSocket", "WebTransport", "WebP", "OpenExr", "YCbCr", "sRGB", "TensorFlow", "TrueType", "iOS", "macOS", "FreeBSD", "NetBSD", "OpenBSD", "NixOS", "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase", "x86_64", "CommonMark", "IntelliJ"]` --- **Affected lints:** diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index d547eb294f6aa..ab809997abc66 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -45,6 +45,8 @@ static DEFAULT_DOC_VALID_IDENTS: &[&str] = &[ "TeX", "LaTeX", "BibTeX", "BibLaTeX", "MinGW", "CamelCase", + "x86_64", + "CommonMark", "IntelliJ", ]; static DEFAULT_DISALLOWED_NAMES: &[&str] = &["foo", "baz", "quux"]; static DEFAULT_ALLOWED_IDENTS_BELOW_MIN_CHARS: &[&str] = &["i", "j", "x", "y", "z", "w", "n"]; diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index c85ffa98936ce..f6388a43a8c8a 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -58,13 +58,13 @@ declare_clippy_lint! { /// /// | Group | Item Kinds | /// |--------------------|----------------------| - /// | `modules` | "mod", "foreign_mod" | - /// | `use` | "use" | - /// | `macros` | "macro" | - /// | `global_asm` | "global_asm" | - /// | `UPPER_SNAKE_CASE` | "static", "const" | - /// | `PascalCase` | "ty_alias", "opaque_ty", "enum", "struct", "union", "trait", "trait_alias", "impl" | - /// | `lower_snake_case` | "fn" | + /// | `modules` | `mod`, `foreign_mod` | + /// | `use` | `use` | + /// | `macros` | `macro` | + /// | `global_asm` | `global_asm` | + /// | `UPPER_SNAKE_CASE` | `static`, `const` | + /// | `PascalCase` | `ty_alias`, `opaque_ty`, `enum`, `struct`, `union`, `trait`, `trait_alias`, `impl` | + /// | `lower_snake_case` | `fn` | /// /// The groups' names are arbitrary and can be changed to suit the /// conventions that should be enforced for a specific project. diff --git a/clippy_lints/src/attrs/mod.rs b/clippy_lints/src/attrs/mod.rs index 23d5adfb201a4..071b3b1df0786 100644 --- a/clippy_lints/src/attrs/mod.rs +++ b/clippy_lints/src/attrs/mod.rs @@ -83,7 +83,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole clippy::restriction category. + /// Checks for `warn`/`deny`/`forbid` attributes targeting the whole `clippy::restriction` category. /// /// ### Why is this bad? /// Restriction lints sometimes are in contrast with other lints or even go against idiomatic rust. @@ -110,12 +110,12 @@ declare_clippy_lint! { /// with `#[rustfmt::skip]`. /// /// ### Why is this bad? - /// Since tool_attributes ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690)) + /// Since `tool_attributes` ([rust-lang/rust#44690](https://github.com/rust-lang/rust/issues/44690)) /// are stable now, they should be used instead of the old `cfg_attr(rustfmt)` attributes. /// /// ### Known problems /// This lint doesn't detect crate level inner attributes, because they get - /// processed before the PreExpansionPass lints get executed. See + /// processed before the pre-expansion pass lints get executed. See /// [#3123](https://github.com/rust-lang/rust-clippy/pull/3123#issuecomment-422321765) /// /// ### Example @@ -432,22 +432,22 @@ declare_clippy_lint! { /// /// This lint permits lint attributes for lints emitted on the items themself. /// For `use` items these lints are: - /// * ambiguous_glob_reexports - /// * dead_code - /// * deprecated - /// * hidden_glob_reexports - /// * unreachable_pub - /// * unused - /// * unused_braces - /// * unused_import_braces - /// * clippy::disallowed_types - /// * clippy::enum_glob_use - /// * clippy::macro_use_imports - /// * clippy::module_name_repetitions - /// * clippy::redundant_pub_crate - /// * clippy::single_component_path_imports - /// * clippy::unsafe_removed_from_name - /// * clippy::wildcard_imports + /// * `ambiguous_glob_reexports` + /// * `dead_code` + /// * `deprecated` + /// * `hidden_glob_reexports` + /// * `unreachable_pub` + /// * `unused` + /// * `unused_braces` + /// * `unused_import_braces` + /// * `clippy::disallowed_types` + /// * `clippy::enum_glob_use` + /// * `clippy::macro_use_imports` + /// * `clippy::module_name_repetitions` + /// * `clippy::redundant_pub_crate` + /// * `clippy::single_component_path_imports` + /// * `clippy::unsafe_removed_from_name` + /// * `clippy::wildcard_imports` /// /// For `extern crate` items these lints are: /// * `unused_imports` on items with `#[macro_use]` diff --git a/clippy_lints/src/bool_to_int_with_if.rs b/clippy_lints/src/bool_to_int_with_if.rs index ecddefe25a264..c1ce1211ddfcd 100644 --- a/clippy_lints/src/bool_to_int_with_if.rs +++ b/clippy_lints/src/bool_to_int_with_if.rs @@ -15,7 +15,7 @@ declare_clippy_lint! { /// Coercion or `from()` is another way to convert bool to a number. /// Both methods are guaranteed to return 1 for true, and 0 for false. /// - /// See https://doc.rust-lang.org/std/primitive.bool.html#impl-From%3Cbool%3E + /// See /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/crate_in_macro_def.rs b/clippy_lints/src/crate_in_macro_def.rs index ddd666477612a..0a9bb452a0a7c 100644 --- a/clippy_lints/src/crate_in_macro_def.rs +++ b/clippy_lints/src/crate_in_macro_def.rs @@ -14,7 +14,7 @@ declare_clippy_lint! { /// ### Why is this bad? /// `crate` refers to the macro call's crate, whereas `$crate` refers to the macro definition's /// crate. Rarely is the former intended. See: - /// https://doc.rust-lang.org/reference/macros-by-example.html#hygiene + /// /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/default.rs b/clippy_lints/src/default.rs index d6812cc29173a..d6db2c570e616 100644 --- a/clippy_lints/src/default.rs +++ b/clippy_lints/src/default.rs @@ -37,7 +37,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does /// Checks for immediate reassignment of fields initialized - /// with Default::default(). + /// with `Default::default()`. /// /// ### Why is this bad? ///It's more idiomatic to use the [functional update syntax](https://doc.rust-lang.org/reference/expressions/struct-expr.html#functional-update-syntax). diff --git a/clippy_lints/src/doc/mod.rs b/clippy_lints/src/doc/mod.rs index 8d2eb01e8743f..7fde6fcf4dd35 100644 --- a/clippy_lints/src/doc/mod.rs +++ b/clippy_lints/src/doc/mod.rs @@ -1,7 +1,9 @@ use clippy_config::Conf; use clippy_utils::attrs::is_doc_hidden; use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_and_then}; -use clippy_utils::{is_entrypoint_fn, is_trait_impl_item}; +use clippy_utils::macros::root_macro_call; +use clippy_utils::{is_entrypoint_fn, is_trait_impl_item, sym}; +use rustc_ast::token::DocFragmentKind; use rustc_attr_ir::Attribute; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; @@ -263,7 +265,7 @@ declare_clippy_lint! { /// /// Consume the array and return the inner /// /// [`SmallVec<[T; INLINE_CAPACITY]>`][SmallVec]. /// /// [SmallVec]: SmallVec - /// fn main() {} + /// fn foo() {} /// ``` #[clippy::version = "pre 1.29.0"] pub DOC_MARKDOWN, @@ -878,11 +880,15 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ let (fragments, _) = attrs_to_doc_fragments( attrs.iter().filter_map(|attr| { - if attr.doc_str_and_fragment_kind().is_none() || attr.span().in_external_macro(cx.sess().source_map()) { - None - } else { - Some((attr, None)) - } + let (_, kind) = attr.doc_str_and_fragment_kind()?; + let (is_raw, doc_str_span) = match kind { + DocFragmentKind::Sugared(_) => (false, attr.span()), + DocFragmentKind::Raw(span) => (true, span), + }; + let from_include_str_macro = is_raw + && !attr.span().in_external_macro(cx.sess().source_map()) + && originated_from_include_str_macro(cx, doc_str_span); + (from_include_str_macro || !doc_str_span.in_external_macro(cx.sess().source_map())).then_some((attr, None)) }), true, ); @@ -963,6 +969,10 @@ fn check_attrs(cx: &LateContext<'_>, valid_idents: &FxHashSet, attrs: &[ )) } +fn originated_from_include_str_macro(cx: &LateContext<'_>, span: Span) -> bool { + root_macro_call(span).is_some_and(|macro_call| cx.tcx.is_diagnostic_item(sym::include_str_macro, macro_call.def_id)) +} + enum Container { Blockquote, List(usize), diff --git a/clippy_lints/src/loops/mod.rs b/clippy_lints/src/loops/mod.rs index a4d3fe9e2296d..5ce0e919fbd3a 100644 --- a/clippy_lints/src/loops/mod.rs +++ b/clippy_lints/src/loops/mod.rs @@ -333,7 +333,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for manual implementations of Iterator::find + /// Checks for manual implementations of `Iterator::find` /// /// ### Why is this bad? /// It doesn't affect performance, but using `find` is shorter and easier to read. diff --git a/clippy_lints/src/main_recursion.rs b/clippy_lints/src/main_recursion.rs index 26576693a0727..23f00352bbc6d 100644 --- a/clippy_lints/src/main_recursion.rs +++ b/clippy_lints/src/main_recursion.rs @@ -1,3 +1,5 @@ +#![expect(clippy::needless_doctest_main)] + use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::source::snippet; use clippy_utils::{is_entrypoint_fn, is_no_std_crate}; @@ -9,8 +11,8 @@ declare_clippy_lint! { /// Checks for recursion using the entrypoint. /// /// ### Why is this bad? - /// Apart from special setups (which we could detect following attributes like #![no_std]), - /// recursing into main() seems like an unintuitive anti-pattern we should be able to detect. + /// Apart from special setups (which we could detect following attributes like `#![no_std]`), + /// recursing into `main()` seems like an unintuitive anti-pattern we should be able to detect. /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 53f8d839787c3..ee10735de41d0 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -997,7 +997,7 @@ declare_clippy_lint! { /// `x.last()`. Indexing into the array will panic on out-of-bounds /// accesses, while `x.get()` and `x.last()` will return `None`. /// - /// There is another lint (get_unwrap) that covers the case of using + /// There is another lint (`get_unwrap`) that covers the case of using /// `x.get(index).unwrap()` instead of `x[index]`. /// /// ### Example @@ -2907,7 +2907,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as String::as_str). + /// Checks for usage of `_.as_ref().map(Deref::deref)` or its aliases (such as `String::as_str`). /// /// ### Why is this bad? /// Readability, this can be written more concisely as @@ -3923,9 +3923,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for calls to [`splitn`] - /// (https://doc.rust-lang.org/std/primitive.str.html#method.splitn) and - /// related functions with either zero or one splits. + /// Checks for calls to [`splitn`](https://doc.rust-lang.org/std/primitive.str.html#method.splitn) + /// and related functions with either zero or one splits. /// /// ### Why is this bad? /// These calls don't actually split the value and are @@ -4501,7 +4500,7 @@ declare_clippy_lint! { /// ### What it does /// Checks for unnecessary calls to `min()` or `max()` in the following cases /// - Either both side is constant - /// - One side is clearly larger than the other, like i32::MIN and an i32 variable + /// - One side is clearly larger than the other, like `i32::MIN` and an `i32` variable /// /// ### Why is this bad? /// @@ -4830,7 +4829,7 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Checks for usage of File::read_to_end and File::read_to_string. + /// Checks for usage of ``File::read_to_end`` and `File::read_to_string`. /// /// ### Why restrict this? /// `fs::{read, read_to_string}` provide the same functionality when `buf` is empty with fewer imports and no intermediate values. @@ -4903,7 +4902,7 @@ declare_clippy_lint! { /// Clippy allows `Pin<&Self>` and `Pin<&mut Self>` if `&self` and `&mut self` is required. /// /// Please find more info here: - /// https://rust-lang.github.io/api-guidelines/naming.html#ad-hoc-conversions-follow-as_-to_-into_-conventions-c-conv + /// /// /// ### Why is this bad? /// Consistency breeds readability. If you follow the diff --git a/clippy_lints/src/misc_early/mod.rs b/clippy_lints/src/misc_early/mod.rs index c47402f72adde..072a8e9354792 100644 --- a/clippy_lints/src/misc_early/mod.rs +++ b/clippy_lints/src/misc_early/mod.rs @@ -277,21 +277,15 @@ declare_clippy_lint! { /// /// In Rust: /// ```no_run - /// fn main() { - /// let a = 0123; - /// println!("{}", a); - /// } + /// let a = 0123; + /// println!("{}", a); /// ``` /// /// prints `123`, while in C: /// /// ```c - /// #include - /// - /// int main() { - /// int a = 0123; - /// printf("%d\n", a); - /// } + /// int a = 0123; + /// printf("%d\n", a); /// ``` /// /// prints `83` (as `83 == 0o123` while `123 == 0o173`). diff --git a/clippy_lints/src/missing_const_for_thread_local.rs b/clippy_lints/src/missing_const_for_thread_local.rs index 81a48f9a92a1a..ddc23a11c9767 100644 --- a/clippy_lints/src/missing_const_for_thread_local.rs +++ b/clippy_lints/src/missing_const_for_thread_local.rs @@ -21,7 +21,7 @@ declare_clippy_lint! { /// need to be dropped, this can enable an even more efficient implementation that /// does not need to track any additional state. /// - /// https://doc.rust-lang.org/std/macro.thread_local.html + /// /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/strlen_on_c_strings.rs b/clippy_lints/src/strlen_on_c_strings.rs index e21f1663c87eb..dc9e682f26b55 100644 --- a/clippy_lints/src/strlen_on_c_strings.rs +++ b/clippy_lints/src/strlen_on_c_strings.rs @@ -16,7 +16,7 @@ declare_clippy_lint! { /// and suggest calling `count_bytes()` instead. /// /// ### Why is this bad? - /// libc::strlen is an unsafe function, which we don't need to call + /// `libc::strlen` is an unsafe function, which we don't need to call /// if all we want to know is the length of the c-string. /// /// ### Example diff --git a/clippy_lints/src/suspicious_trait_impl.rs b/clippy_lints/src/suspicious_trait_impl.rs index 74cd87c7cc935..0ba88b8ae9048 100644 --- a/clippy_lints/src/suspicious_trait_impl.rs +++ b/clippy_lints/src/suspicious_trait_impl.rs @@ -32,8 +32,8 @@ declare_clippy_lint! { declare_clippy_lint! { /// ### What it does - /// Lints for suspicious operations in impls of OpAssign, e.g. - /// subtracting elements in an AddAssign impl. + /// Lints for suspicious operations in impls of `OpAssign`, e.g. + /// subtracting elements in an `AddAssign` impl. /// /// ### Why is this bad? /// This is probably a typo or copy-and-paste error and not intended. diff --git a/clippy_lints/src/swap.rs b/clippy_lints/src/swap.rs index abcc81c3c2361..938fe464b78a5 100644 --- a/clippy_lints/src/swap.rs +++ b/clippy_lints/src/swap.rs @@ -63,7 +63,7 @@ declare_clippy_lint! { /// b = a; /// a = t; /// ``` - /// Use std::mem::swap(): + /// Use `std::mem::swap()`: /// ```no_run /// let mut a = 1; /// let mut b = 2; diff --git a/clippy_lints/src/transmute/mod.rs b/clippy_lints/src/transmute/mod.rs index 89beedcfe3623..a3b6b1d348537 100644 --- a/clippy_lints/src/transmute/mod.rs +++ b/clippy_lints/src/transmute/mod.rs @@ -241,7 +241,7 @@ declare_clippy_lint! { /// ### Why is this bad? /// Creating a null function pointer is undefined behavior. /// - /// More info: https://doc.rust-lang.org/nomicon/ffi.html#the-nullable-pointer-optimization + /// More info: /// /// ### Known problems /// Not all cases can be detected at the moment of this writing. diff --git a/clippy_lints/src/unit_return_expecting_ord.rs b/clippy_lints/src/unit_return_expecting_ord.rs index 2225a85b09487..4784fd5713c81 100644 --- a/clippy_lints/src/unit_return_expecting_ord.rs +++ b/clippy_lints/src/unit_return_expecting_ord.rs @@ -9,18 +9,18 @@ use rustc_span::{BytePos, Span, Symbol, sym}; declare_clippy_lint! { /// ### What it does /// Checks for functions that expect closures of type - /// Fn(...) -> Ord where the implemented closure returns the unit type. + /// `Fn(...) -> Ord` where the implemented closure returns the unit type. /// The lint also suggests to remove the semi-colon at the end of the statement if present. /// /// ### Why is this bad? /// Likely, returning the unit type is unintentional, and - /// could simply be caused by an extra semi-colon. Since () implements Ord + /// could simply be caused by an extra semi-colon. Since `()` implements `Ord` /// it doesn't cause a compilation error. - /// This is the same reasoning behind the unit_cmp lint. + /// This is the same reasoning behind the `unit_cmp` lint. /// /// ### Known problems /// If returning unit is intentional, then there is no - /// way of specifying this without triggering needless_return lint + /// way of specifying this without triggering `needless_return` lint /// /// ### Example /// ```no_run diff --git a/clippy_lints/src/unnecessary_self_imports.rs b/clippy_lints/src/unnecessary_self_imports.rs index 677a459a03c7b..6f5098cdda564 100644 --- a/clippy_lints/src/unnecessary_self_imports.rs +++ b/clippy_lints/src/unnecessary_self_imports.rs @@ -13,7 +13,7 @@ declare_clippy_lint! { /// /// ### Known problems /// Removing `::{self}` will cause any non-module items at the same path to also be imported. - /// This might cause a naming conflict (https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt + /// This might cause a [naming conflict](https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt /// to detect this scenario and that is why it is a restriction lint. /// /// ### Example diff --git a/clippy_lints/src/write/mod.rs b/clippy_lints/src/write/mod.rs index ac8ddd3653e56..86f4920b5b7f6 100644 --- a/clippy_lints/src/write/mod.rs +++ b/clippy_lints/src/write/mod.rs @@ -15,8 +15,7 @@ declare_clippy_lint! { /// This lint warns about the use of literals as `print!`/`println!` args. /// /// ### Why is this bad? - /// Using literals as `println!` args is inefficient - /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary + /// Using literals as `println!` args is [inefficient] and unnecessary /// (i.e., just put the literal in the format string) /// /// ### Example @@ -27,6 +26,8 @@ declare_clippy_lint! { /// ```no_run /// println!("foo"); /// ``` + /// + /// [inefficient]: https://github.com/matthiaskrgr/rust-str-bench #[clippy::version = "pre 1.29.0"] pub PRINT_LITERAL, style, @@ -153,8 +154,7 @@ declare_clippy_lint! { /// This lint warns about the use of literals as `write!`/`writeln!` args. /// /// ### Why is this bad? - /// Using literals as `writeln!` args is inefficient - /// (c.f., https://github.com/matthiaskrgr/rust-str-bench) and unnecessary + /// Using literals as `writeln!` args is [inefficient] and unnecessary /// (i.e., just put the literal in the format string) /// /// ### Example @@ -170,6 +170,8 @@ declare_clippy_lint! { /// # let mut buf = String::new(); /// writeln!(buf, "foo"); /// ``` + /// + /// [inefficient]: https://github.com/matthiaskrgr/rust-str-bench #[clippy::version = "pre 1.29.0"] pub WRITE_LITERAL, style, diff --git a/clippy_lints_internal/src/collapsible_span_lint_calls.rs b/clippy_lints_internal/src/collapsible_span_lint_calls.rs index 14fb62e467db1..0cd10da70a0b5 100644 --- a/clippy_lints_internal/src/collapsible_span_lint_calls.rs +++ b/clippy_lints_internal/src/collapsible_span_lint_calls.rs @@ -18,7 +18,7 @@ declare_tool_lint! { /// span), `help` or `note`. /// /// These usages of `span_lint_and_then` should be replaced with one of the - /// wrapper functions `span_lint_and_sugg`, span_lint_and_help`, or + /// wrapper functions `span_lint_and_sugg`, `span_lint_and_help`, or /// `span_lint_and_note`. /// /// ### Why is this bad? diff --git a/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs b/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs index 8e4a83b7be4e1..badb106bd8c3c 100644 --- a/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs +++ b/clippy_lints_internal/src/unsorted_clippy_utils_paths.rs @@ -11,7 +11,7 @@ declare_tool_lint! { /// We like to pretend we're an example of tidy code. /// /// ### Example - /// Wrong ordering of the util::paths constants. + /// Wrong ordering of the `util::paths` constants. pub clippy::UNSORTED_CLIPPY_UTILS_PATHS, Warn, "various things that will negatively affect your clippy experience", diff --git a/tests/ui/doc_unsafe.rs b/tests/ui/doc_unsafe.rs index e6180f7c62e8e..3946147bfd0b5 100644 --- a/tests/ui/doc_unsafe.rs +++ b/tests/ui/doc_unsafe.rs @@ -183,3 +183,21 @@ pub mod __macro { pub unsafe trait DocumentedUnsafeTraitWithImplementationHeader { fn method(); } + +pub mod issue_16317 { + use super::external; + + external! { + #[doc = $("# Safety")] + $( + pub unsafe fn expanded_unsafe_fn_with_safety() {} + ) + } + external! { + #[doc = $("No safety comment")] + $( + pub unsafe fn expanded_unsafe_fn_without_safety() {} + //~^ missing_safety_doc + ) + } +} diff --git a/tests/ui/doc_unsafe.stderr b/tests/ui/doc_unsafe.stderr index efac6cd64c878..84c62a9e0589e 100644 --- a/tests/ui/doc_unsafe.stderr +++ b/tests/ui/doc_unsafe.stderr @@ -89,5 +89,11 @@ LL | very_unsafe!(); | = note: this error originates in the macro `very_unsafe` (in Nightly builds, run with -Z macro-backtrace for more info) -error: aborting due to 12 previous errors +error: unsafe function's docs are missing a `# Safety` section + --> tests/ui/doc_unsafe.rs:199:13 + | +LL | pub unsafe fn expanded_unsafe_fn_without_safety() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 13 previous errors diff --git a/tests/ui/empty_docs.rs b/tests/ui/empty_docs.rs index b6134324d675f..f91bba7e72048 100644 --- a/tests/ui/empty_docs.rs +++ b/tests/ui/empty_docs.rs @@ -4,6 +4,9 @@ #![expect(clippy::mixed_attributes_style)] #![feature(extern_types)] +extern crate proc_macros; +use proc_macros::external; + mod outer { //! //~^ empty_docs @@ -92,3 +95,11 @@ mod issue_12377 { a: u8, } } + +external! { + #[doc = $("")] + //~^ empty_docs + $( + fn issue_16382() {} + ) +} diff --git a/tests/ui/empty_docs.stderr b/tests/ui/empty_docs.stderr index 75f57442843ee..3a131e4a5505a 100644 --- a/tests/ui/empty_docs.stderr +++ b/tests/ui/empty_docs.stderr @@ -1,5 +1,5 @@ error: empty doc comment - --> tests/ui/empty_docs.rs:8:5 + --> tests/ui/empty_docs.rs:11:5 | LL | //! | ^^^ @@ -9,7 +9,7 @@ LL | //! = help: to override `-D warnings` add `#[allow(clippy::empty_docs)]` error: empty doc comment - --> tests/ui/empty_docs.rs:17:5 + --> tests/ui/empty_docs.rs:20:5 | LL | /// | ^^^ @@ -17,7 +17,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:20:9 + --> tests/ui/empty_docs.rs:23:9 | LL | /// | ^^^ @@ -25,7 +25,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:32:13 + --> tests/ui/empty_docs.rs:35:13 | LL | #[doc = ""] | ^^ @@ -33,7 +33,7 @@ LL | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:36:13 + --> tests/ui/empty_docs.rs:39:13 | LL | #[doc = ""] | _____________^ @@ -43,7 +43,7 @@ LL | | #[doc = ""] = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:44:5 + --> tests/ui/empty_docs.rs:47:5 | LL | /// | ^^^ @@ -51,7 +51,7 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:58:13 + --> tests/ui/empty_docs.rs:61:13 | LL | /*! */ | ^^^^^^ @@ -59,7 +59,7 @@ LL | /*! */ = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:67:13 + --> tests/ui/empty_docs.rs:70:13 | LL | /// | ^^^ @@ -67,12 +67,21 @@ LL | /// = help: consider removing or filling it error: empty doc comment - --> tests/ui/empty_docs.rs:76:9 + --> tests/ui/empty_docs.rs:79:9 | LL | /// | ^^^ | = help: consider removing or filling it -error: aborting due to 9 previous errors +error: empty doc comment + --> tests/ui/empty_docs.rs:100:15 + | +LL | #[doc = $("")] + | ^^ + | + = help: consider removing or filling it + = note: this error originates in the macro `external` (in Nightly builds, run with -Z macro-backtrace for more info) + +error: aborting due to 10 previous errors diff --git a/tests/ui/missing_panics_doc.rs b/tests/ui/missing_panics_doc.rs index 63e84ffaab634..d561c726a5575 100644 --- a/tests/ui/missing_panics_doc.rs +++ b/tests/ui/missing_panics_doc.rs @@ -4,8 +4,10 @@ #[macro_use] extern crate macro_rules; +extern crate proc_macros; use macro_rules::macro_with_panic; +use proc_macros::external; fn main() {} @@ -278,3 +280,33 @@ pub const fn in_const_fn(n: usize) { //~^ missing_panics_doc assert!(N > n); } + +pub mod doc_with_original_span { + use super::external; + external! { + #[doc = $("# Panics ")] + $( + pub fn foo() { panic!() } + ) + } + + external! { + #[doc = $("missing panics doc")] + $( + pub fn foo1() { panic!() } + //~^ missing_panics_doc + ) + } + + pub struct Bar; + + impl Bar { + external! { + #[doc = $("missing panics doc")] + $( + pub fn foo() { panic!() } + //~^ missing_panics_doc + ) + } + } +} diff --git a/tests/ui/missing_panics_doc.stderr b/tests/ui/missing_panics_doc.stderr index 85a0091442734..5d5d99d2baa9f 100644 --- a/tests/ui/missing_panics_doc.stderr +++ b/tests/ui/missing_panics_doc.stderr @@ -1,11 +1,11 @@ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:13:1 + --> tests/ui/missing_panics_doc.rs:15:1 | LL | pub fn unwrap() { | ^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:16:5 + --> tests/ui/missing_panics_doc.rs:18:5 | LL | result.unwrap() | ^^^^^^^^^^^^^^^ @@ -13,208 +13,232 @@ LL | result.unwrap() = help: to override `-D warnings` add `#[allow(clippy::missing_panics_doc)]` error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:20:1 + --> tests/ui/missing_panics_doc.rs:22:1 | LL | pub fn panic() { | ^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:22:5 + --> tests/ui/missing_panics_doc.rs:24:5 | LL | panic!("This function panics") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:26:1 + --> tests/ui/missing_panics_doc.rs:28:1 | LL | pub fn inner_body(opt: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:30:13 + --> tests/ui/missing_panics_doc.rs:32:13 | LL | panic!() | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:36:1 + --> tests/ui/missing_panics_doc.rs:38:1 | LL | pub fn unreachable_and_panic() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:38:39 + --> tests/ui/missing_panics_doc.rs:40:39 | LL | if true { unreachable!() } else { panic!() } | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:42:1 + --> tests/ui/missing_panics_doc.rs:44:1 | LL | pub fn assert_eq() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:45:5 + --> tests/ui/missing_panics_doc.rs:47:5 | LL | assert_eq!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:49:1 + --> tests/ui/missing_panics_doc.rs:51:1 | LL | pub fn assert_ne() { | ^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:52:5 + --> tests/ui/missing_panics_doc.rs:54:5 | LL | assert_ne!(x, 0); | ^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:154:1 + --> tests/ui/missing_panics_doc.rs:156:1 | LL | pub fn partially_const(n: usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:161:5 + --> tests/ui/missing_panics_doc.rs:163:5 | LL | assert!(N > n); | ^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:172:1 + --> tests/ui/missing_panics_doc.rs:174:1 | LL | pub fn expect_allow_with_error(i: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:181:5 + --> tests/ui/missing_panics_doc.rs:183:5 | LL | i.unwrap(); | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:184:1 + --> tests/ui/missing_panics_doc.rs:186:1 | LL | pub fn expect_after_error(x: Option, y: Option) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:187:13 + --> tests/ui/missing_panics_doc.rs:189:13 | LL | let x = x.unwrap(); | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:196:5 + --> tests/ui/missing_panics_doc.rs:198:5 | LL | pub fn option_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:199:9 + --> tests/ui/missing_panics_doc.rs:201:9 | LL | o.unwrap() | ^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:202:5 + --> tests/ui/missing_panics_doc.rs:204:5 | LL | pub fn option_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:205:9 + --> tests/ui/missing_panics_doc.rs:207:9 | LL | o.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:208:5 + --> tests/ui/missing_panics_doc.rs:210:5 | LL | pub fn result_unwrap(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:211:9 + --> tests/ui/missing_panics_doc.rs:213:9 | LL | res.unwrap() | ^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:214:5 + --> tests/ui/missing_panics_doc.rs:216:5 | LL | pub fn result_expect(v: &[T]) -> &T { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:217:9 + --> tests/ui/missing_panics_doc.rs:219:9 | LL | res.expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:220:5 + --> tests/ui/missing_panics_doc.rs:222:5 | LL | pub fn last_unwrap(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:222:10 + --> tests/ui/missing_panics_doc.rs:224:10 | LL | *v.last().unwrap() | ^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:225:5 + --> tests/ui/missing_panics_doc.rs:227:5 | LL | pub fn last_expect(v: &[u32]) -> u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:227:10 + --> tests/ui/missing_panics_doc.rs:229:10 | LL | *v.last().expect("passed an empty thing") | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:262:1 + --> tests/ui/missing_panics_doc.rs:264:1 | LL | pub const fn unwrap_expect_etc_in_const_fn_fails() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:264:13 + --> tests/ui/missing_panics_doc.rs:266:13 | LL | let a = std::num::NonZeroUsize::new(1).unwrap(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:268:1 + --> tests/ui/missing_panics_doc.rs:270:1 | LL | pub const fn assert_in_const_fn_fails() { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:272:9 + --> tests/ui/missing_panics_doc.rs:274:9 | LL | panic!(); | ^^^^^^^^ error: docs for function which may panic missing `# Panics` section - --> tests/ui/missing_panics_doc.rs:277:1 + --> tests/ui/missing_panics_doc.rs:279:1 | LL | pub const fn in_const_fn(n: usize) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: first possible panic found here - --> tests/ui/missing_panics_doc.rs:279:5 + --> tests/ui/missing_panics_doc.rs:281:5 | LL | assert!(N > n); | ^^^^^^^^^^^^^^ -error: aborting due to 18 previous errors +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:296:13 + | +LL | pub fn foo1() { panic!() } + | ^^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:296:29 + | +LL | pub fn foo1() { panic!() } + | ^^^^^^^^ + +error: docs for function which may panic missing `# Panics` section + --> tests/ui/missing_panics_doc.rs:307:17 + | +LL | pub fn foo() { panic!() } + | ^^^^^^^^^^^^ + | +note: first possible panic found here + --> tests/ui/missing_panics_doc.rs:307:32 + | +LL | pub fn foo() { panic!() } + | ^^^^^^^^ + +error: aborting due to 20 previous errors From df8fb0f5ad45c474597fa579988ccfb53aff855a Mon Sep 17 00:00:00 2001 From: jackh726 Date: Wed, 23 Sep 2026 01:57:54 +0000 Subject: [PATCH 0676/1309] Use SmallVec in LocalizedConstraintGraph --- .../src/polonius/constraints.rs | 24 ++++++++++++------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 5855f60a85217..68e851c05ace3 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,10 +1,11 @@ use std::rc::Rc; -use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::IndexVec; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::RegionVid; use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; +use smallvec::SmallVec; use crate::BorrowSet; use crate::constraints::OutlivesConstraint; @@ -44,12 +45,12 @@ pub(super) struct LocalizedConstraintGraph { /// The actual, physical, edges we have recorded for a given node. We localize them on-demand /// when traversing from the node to the successor region. - edges: FxHashMap>, + edges: FxHashMap>, /// The logical edges representing the outlives constraints that hold at all points in the CFG, /// which we don't localize to avoid creating a lot of unnecessary edges in the graph. Some CFGs /// can be big, and we don't need to create such a physical edge for every point in the CFG. - logical_edges: IndexVec>, + logical_edges: IndexVec>, } /// The visitor interface when traversing a `LocalizedConstraintGraph`. @@ -69,15 +70,17 @@ impl LocalizedConstraintGraph { location_map: Rc, outlives_constraints: impl Iterator>, ) -> Self { - let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); - let mut logical_edges: IndexVec<_, FxIndexSet<_>> = IndexVec::new(); + let mut edges: FxHashMap<_, SmallVec<[RegionVid; 4]>> = FxHashMap::default(); + let mut logical_edges: IndexVec<_, SmallVec<[RegionVid; 4]>> = IndexVec::new(); for outlives_constraint in outlives_constraints { match outlives_constraint.locations { Locations::All(_) => { - logical_edges - .ensure_contains_elem(outlives_constraint.sup, FxIndexSet::default) - .insert(outlives_constraint.sub); + let succs = + logical_edges.ensure_contains_elem(outlives_constraint.sup, SmallVec::new); + if !succs.contains(&outlives_constraint.sub) { + succs.push(outlives_constraint.sub); + } } Locations::Single(location) => { @@ -85,7 +88,10 @@ impl LocalizedConstraintGraph { region: outlives_constraint.sup, point: location_map.point_from_location(location), }; - edges.entry(node).or_default().insert(outlives_constraint.sub); + let succs = edges.entry(node).or_default(); + if !succs.contains(&outlives_constraint.sub) { + succs.push(outlives_constraint.sub); + } } } } From 87e95d69da85bc2c54432240cff00fb56c439eb2 Mon Sep 17 00:00:00 2001 From: Yukang Date: Tue, 22 Sep 2026 00:10:54 +0800 Subject: [PATCH 0677/1309] Enhance mutable closure suggestions with as_mut() support --- .../src/fn_ctxt/suggestions.rs | 33 ++++++++---- tests/ui/suggestions/as-mut-closure.fixed | 34 ++++++++++++ tests/ui/suggestions/as-mut-closure.rs | 1 + tests/ui/suggestions/as-mut-closure.stderr | 52 +++++++++---------- 4 files changed, 84 insertions(+), 36 deletions(-) create mode 100644 tests/ui/suggestions/as-mut-closure.fixed diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 8895faef0890f..49f7b2e551b78 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -2855,7 +2855,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { true } - /// Identify some cases where `as_ref()` would be appropriate and suggest it. + /// Identify some cases where `as_ref()` or `as_mut()` would be appropriate and suggest it. /// /// Given the following code: /// ```compile_fail,E0308 @@ -2871,7 +2871,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { /// ```ignore (illustrative) /// opt.map(|param| { takes_ref(param) }); /// ``` - fn can_use_as_ref(&self, expr: &hir::Expr<'_>) -> Option<(Vec<(Span, String)>, &'static str)> { + fn can_use_as_ref_or_mut( + &self, + expr: &hir::Expr<'_>, + mutability: hir::Mutability, + ) -> Option<(Vec<(Span, String)>, &'static str)> { let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = expr.kind else { return None; }; @@ -2908,9 +2912,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return None; }; - let self_ty = self.typeck_results.borrow().expr_ty_opt(receiver)?; + let mut self_ty = self.typeck_results.borrow().expr_ty_opt(receiver)?; + while let ty::Ref(_, inner, ref_mutability) = self_ty.kind() { + // `as_mut()` cannot borrow through a shared reference, + // also we cannot suggest `as_ref()` either when the reference is shared + if mutability.is_mut() && ref_mutability.is_not() { + return None; + } + self_ty = *inner; + } let name = method_path.ident.name; - let is_as_ref_able = match self_ty.peel_refs().kind() { + let can_borrow = match self_ty.kind() { ty::Adt(def, _) => { (self.tcx.is_diagnostic_item(sym::Option, def.did()) || self.tcx.is_diagnostic_item(sym::Result, def.did())) @@ -2918,11 +2930,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } _ => false, }; - if is_as_ref_able { - Some(( - vec![(method_path.ident.span.shrink_to_lo(), "as_ref().".to_string())], - "consider using `as_ref` instead", - )) + if can_borrow { + let (suggestion, message) = match mutability { + hir::Mutability::Not => ("as_ref().", "consider using `as_ref` instead"), + hir::Mutability::Mut => ("as_mut().", "consider using `as_mut` instead"), + }; + Some((vec![(method_path.ident.span.shrink_to_lo(), suggestion.to_string())], message)) } else { None } @@ -3113,7 +3126,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { return Some((suggs, help, app, mutref)); } - if let Some((sugg, msg)) = self.can_use_as_ref(expr) { + if let Some((sugg, msg)) = self.can_use_as_ref_or_mut(expr, mutability) { return Some(( sugg, msg.to_string(), diff --git a/tests/ui/suggestions/as-mut-closure.fixed b/tests/ui/suggestions/as-mut-closure.fixed new file mode 100644 index 0000000000000..76a9cc5ab7c88 --- /dev/null +++ b/tests/ui/suggestions/as-mut-closure.fixed @@ -0,0 +1,34 @@ +// Borrowing a container for a closure argument must preserve the expected mutability. +//@ run-rustfix + +#![allow(unused_mut)] + +fn append(value: &mut String) { + value.push('!'); +} + +fn increment(value: &mut i32) { + *value += 1; +} + +fn main() { + let mut option = Some(String::new()); + let _ = option.as_mut().map(|arg| append(arg)); + //~^ ERROR mismatched types + let _ = (&mut option).as_mut().and_then(|arg| Some(append(arg))); + //~^ ERROR mismatched types + + let mut result: Result<_, ()> = Ok(String::new()); + let _ = result.as_mut().map(|arg| append(arg)); + //~^ ERROR mismatched types + let _ = (&mut result).as_mut().and_then(|arg| Ok(append(arg))); + //~^ ERROR mismatched types + + // A shared reference cannot supply `as_mut()`. Borrow the copied argument instead. + let shared = &Some(0); + let _ = shared.map(|mut arg| increment(&mut arg)); + //~^ ERROR mismatched types + let nested = &mut &Some(0); + let _ = nested.map(|mut arg| increment(&mut arg)); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/as-mut-closure.rs b/tests/ui/suggestions/as-mut-closure.rs index ab1c8bff5bf77..4b583cbc4f2dc 100644 --- a/tests/ui/suggestions/as-mut-closure.rs +++ b/tests/ui/suggestions/as-mut-closure.rs @@ -1,4 +1,5 @@ // Borrowing a container for a closure argument must preserve the expected mutability. +//@ run-rustfix #![allow(unused_mut)] diff --git a/tests/ui/suggestions/as-mut-closure.stderr b/tests/ui/suggestions/as-mut-closure.stderr index c133641b6a5a7..8a998be539458 100644 --- a/tests/ui/suggestions/as-mut-closure.stderr +++ b/tests/ui/suggestions/as-mut-closure.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:15:37 + --> $DIR/as-mut-closure.rs:16:37 | LL | let _ = option.map(|arg| append(arg)); | ------ ^^^ expected `&mut String`, found `String` @@ -7,17 +7,17 @@ LL | let _ = option.map(|arg| append(arg)); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:5:4 + --> $DIR/as-mut-closure.rs:6:4 | LL | fn append(value: &mut String) { | ^^^^^^ ------------------ -help: consider using `as_ref` instead +help: consider using `as_mut` instead | -LL | let _ = option.as_ref().map(|arg| append(arg)); +LL | let _ = option.as_mut().map(|arg| append(arg)); | +++++++++ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:17:54 + --> $DIR/as-mut-closure.rs:18:54 | LL | let _ = (&mut option).and_then(|arg| Some(append(arg))); | ------ ^^^ expected `&mut String`, found `String` @@ -25,17 +25,17 @@ LL | let _ = (&mut option).and_then(|arg| Some(append(arg))); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:5:4 + --> $DIR/as-mut-closure.rs:6:4 | LL | fn append(value: &mut String) { | ^^^^^^ ------------------ -help: consider using `as_ref` instead +help: consider using `as_mut` instead | -LL | let _ = (&mut option).as_ref().and_then(|arg| Some(append(arg))); +LL | let _ = (&mut option).as_mut().and_then(|arg| Some(append(arg))); | +++++++++ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:21:37 + --> $DIR/as-mut-closure.rs:22:37 | LL | let _ = result.map(|arg| append(arg)); | ------ ^^^ expected `&mut String`, found `String` @@ -43,17 +43,17 @@ LL | let _ = result.map(|arg| append(arg)); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:5:4 + --> $DIR/as-mut-closure.rs:6:4 | LL | fn append(value: &mut String) { | ^^^^^^ ------------------ -help: consider using `as_ref` instead +help: consider using `as_mut` instead | -LL | let _ = result.as_ref().map(|arg| append(arg)); +LL | let _ = result.as_mut().map(|arg| append(arg)); | +++++++++ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:23:52 + --> $DIR/as-mut-closure.rs:24:52 | LL | let _ = (&mut result).and_then(|arg| Ok(append(arg))); | ------ ^^^ expected `&mut String`, found `String` @@ -61,17 +61,17 @@ LL | let _ = (&mut result).and_then(|arg| Ok(append(arg))); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:5:4 + --> $DIR/as-mut-closure.rs:6:4 | LL | fn append(value: &mut String) { | ^^^^^^ ------------------ -help: consider using `as_ref` instead +help: consider using `as_mut` instead | -LL | let _ = (&mut result).as_ref().and_then(|arg| Ok(append(arg))); +LL | let _ = (&mut result).as_mut().and_then(|arg| Ok(append(arg))); | +++++++++ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:28:44 + --> $DIR/as-mut-closure.rs:29:44 | LL | let _ = shared.map(|mut arg| increment(arg)); | --------- ^^^ expected `&mut i32`, found integer @@ -79,17 +79,17 @@ LL | let _ = shared.map(|mut arg| increment(arg)); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:9:4 + --> $DIR/as-mut-closure.rs:10:4 | LL | fn increment(value: &mut i32) { | ^^^^^^^^^ --------------- -help: consider using `as_ref` instead +help: consider mutably borrowing here | -LL | let _ = shared.as_ref().map(|mut arg| increment(arg)); - | +++++++++ +LL | let _ = shared.map(|mut arg| increment(&mut arg)); + | ++++ error[E0308]: mismatched types - --> $DIR/as-mut-closure.rs:31:44 + --> $DIR/as-mut-closure.rs:32:44 | LL | let _ = nested.map(|mut arg| increment(arg)); | --------- ^^^ expected `&mut i32`, found integer @@ -97,14 +97,14 @@ LL | let _ = nested.map(|mut arg| increment(arg)); | arguments to this function are incorrect | note: function defined here - --> $DIR/as-mut-closure.rs:9:4 + --> $DIR/as-mut-closure.rs:10:4 | LL | fn increment(value: &mut i32) { | ^^^^^^^^^ --------------- -help: consider using `as_ref` instead +help: consider mutably borrowing here | -LL | let _ = nested.as_ref().map(|mut arg| increment(arg)); - | +++++++++ +LL | let _ = nested.map(|mut arg| increment(&mut arg)); + | ++++ error: aborting due to 6 previous errors From a08787066f392c85aa52f3e1cc0917554d2b2e7c Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 23 Sep 2026 04:02:23 +0100 Subject: [PATCH 0678/1309] Add the experimental -Zmir-move-elimination option --- compiler/rustc_interface/src/tests.rs | 1 + compiler/rustc_session/src/options.rs | 2 ++ 2 files changed, 3 insertions(+) diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 0d584be4ad0b0..2f9489ac67ad4 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -851,6 +851,7 @@ fn test_unstable_options_tracking_hash() { tracked!(min_function_alignment, Some(Align::EIGHT)); tracked!(min_recursion_limit, Some(256)); tracked!(mir_enable_passes, vec![("DestProp".to_string(), false)]); + tracked!(mir_move_elimination, true); tracked!(mir_opt_level, Some(4)); tracked!(mir_preserve_ub, true); tracked!(move_size_limit, Some(4096)); diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..6b9ffa1b9ed2b 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2662,6 +2662,8 @@ options! { mir_include_spans: MirIncludeSpans = (MirIncludeSpans::default(), parse_mir_include_spans, [UNTRACKED], "include extra comments in mir pretty printing, like line numbers and statement indices, \ details about types, etc. (boolean for all passes, 'nll' to enable in NLL MIR only, default: 'nll')"), + mir_move_elimination: bool = (false, parse_bool, [TRACKED], + "enable the experimental MIR move elimination pass (default: no)"), mir_opt_bisect_limit: Option = (None, parse_opt_number, [TRACKED], "limit the number of MIR optimization pass executions (global across all bodies). \ Pass executions after this limit are skipped and reported. (default: no limit)"), From 7ce6f3f689efaedd5713b3fc3a208a35fcd7d840 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Wed, 23 Sep 2026 04:02:24 +0100 Subject: [PATCH 0679/1309] Add a MIR pass which turns copies into moves just before a return --- compiler/rustc_mir_transform/src/lib.rs | 2 + .../src/tail_copy_to_move.rs | 258 +++++++++++++ ...copy_to_move.aggregate.TailCopyToMove.diff | 24 ++ ...ove.aggregate_operands.TailCopyToMove.diff | 13 + ...e.aggregate_with_deref.TailCopyToMove.diff | 16 + ...rrowed_dest_stops_tail.TailCopyToMove.diff | 17 + ...e.borrowed_source_tail.TailCopyToMove.diff | 15 + ...ail_copy_to_move.chain.TailCopyToMove.diff | 22 ++ ...il_copy_to_move.direct.TailCopyToMove.diff | 14 + ...opy_to_move.index_dest.TailCopyToMove.diff | 18 + ..._to_move.index_operand.TailCopyToMove.diff | 13 + ...ove.indirect_tail_read.TailCopyToMove.diff | 19 + ...ve.indirect_tail_write.TailCopyToMove.diff | 16 + ...copy_to_move.projected.TailCopyToMove.diff | 14 + ...to_move.projected_dest.TailCopyToMove.diff | 15 + ..._move.repeated_operand.TailCopyToMove.diff | 13 + tests/mir-opt/tail_copy_to_move.rs | 347 ++++++++++++++++++ ..._move.set_discriminant.TailCopyToMove.diff | 14 + ..._discriminant_borrowed.TailCopyToMove.diff | 17 + ...set_discriminant_index.TailCopyToMove.diff | 17 + ..._discriminant_indirect.TailCopyToMove.diff | 16 + ..._to_move.shared_return.TailCopyToMove.diff | 34 ++ ...e.unrelated_tail_store.TailCopyToMove.diff | 17 + 23 files changed, 951 insertions(+) create mode 100644 compiler/rustc_mir_transform/src/tail_copy_to_move.rs create mode 100644 tests/mir-opt/tail_copy_to_move.aggregate.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.aggregate_operands.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.aggregate_with_deref.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.borrowed_dest_stops_tail.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.borrowed_source_tail.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.chain.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.direct.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.index_dest.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.index_operand.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.indirect_tail_read.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.indirect_tail_write.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.projected.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.projected_dest.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.repeated_operand.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.rs create mode 100644 tests/mir-opt/tail_copy_to_move.set_discriminant.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.set_discriminant_borrowed.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.set_discriminant_index.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.set_discriminant_indirect.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.shared_return.TailCopyToMove.diff create mode 100644 tests/mir-opt/tail_copy_to_move.unrelated_tail_store.TailCopyToMove.diff diff --git a/compiler/rustc_mir_transform/src/lib.rs b/compiler/rustc_mir_transform/src/lib.rs index 95a708f125660..d0b9c686c3037 100644 --- a/compiler/rustc_mir_transform/src/lib.rs +++ b/compiler/rustc_mir_transform/src/lib.rs @@ -205,6 +205,7 @@ declare_passes! { mod sroa : ScalarReplacementOfAggregates; mod strip_debuginfo : StripDebugInfo; mod ssa_range_prop: SsaRangePropagation; + mod tail_copy_to_move : TailCopyToMove; mod unreachable_enum_branching : UnreachableEnumBranching; mod unreachable_prop : UnreachablePropagation; mod validate : Validator; @@ -761,6 +762,7 @@ pub(crate) fn run_optimization_passes<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<' ©_prop::CopyProp, &dead_store_elimination::DeadStoreElimination::Final, &dest_prop::DestinationPropagation, + &tail_copy_to_move::TailCopyToMove, &simplify::SimplifyLocals::Final, &multiple_return_terminators::MultipleReturnTerminators, // Some cleanup necessary at least for LLVM and potentially other codegen backends. diff --git a/compiler/rustc_mir_transform/src/tail_copy_to_move.rs b/compiler/rustc_mir_transform/src/tail_copy_to_move.rs new file mode 100644 index 0000000000000..1668449190307 --- /dev/null +++ b/compiler/rustc_mir_transform/src/tail_copy_to_move.rs @@ -0,0 +1,258 @@ +//! Rewrite final-use copies before return into moves. +//! +//! # The problem +//! +//! MIR building represents reads of values whose type is `Copy` using +//! `Operand::Copy`, including when such a local is returned. If that local's +//! address has ever been observed, then the local's allocation is semantically +//! valid until its `StorageDead` or function exit. This keeps the local live +//! across `_0 = copy local`, so its live range overlaps with the return place +//! and `MoveElimination` cannot unify the source local with `_0`. +//! +//! # The solution +//! +//! At function return, all local allocations are about to become invalid +//! anyway. After borrowck, this pass can therefore turn a final-use `Copy` into +//! a `Move`, as long as shortening the source local's live range has no +//! observable effect before the return happens. Concretely, between the +//! transformed copy (now a move) and the return, there may only be writes to +//! unborrowed locals, storage markers, nops, and gotos. +//! +//! # The algorithm +//! +//! Start from every `Return` terminator, with `_0` treated as used by the +//! return. Then scan predecessor blocks backward through `Goto` edges, forming +//! a return-tail tree. The scan maintains `used_after`, the set of locals +//! accessed later on that path. +//! +//! A `Copy` operand is rewritten to a `Move` when its base local is not in +//! `used_after`. Then any locals touched by that operand, including +//! index-projection locals, are added to `used_after` before the backward scan +//! continues. +//! +//! The scan stops when accessing an indirect place because that may access any +//! borrowed local, which would make the pass unable to prove any useful final +//! uses. It also stops at writes to borrowed locals, because those can create a +//! new address-observed allocation range whose overlap with an earlier borrowed +//! local must be preserved. + +use std::ops::ControlFlow; + +use rustc_index::bit_set::DenseBitSet; +use rustc_middle::mir::*; +use rustc_middle::ty::TyCtxt; +use rustc_mir_dataflow::impls::borrowed_locals; + +use crate::PassPolicy; + +pub(super) struct TailCopyToMove; + +impl<'tcx> crate::MirPass<'tcx> for TailCopyToMove { + fn policy(&self, ctx: &crate::PassCtx<'_>) -> PassPolicy { + PassPolicy::optional( + ctx.mir_opt_level() >= 2 && ctx.opts.unstable_opts.mir_move_elimination, + ) + } + + #[tracing::instrument(level = "trace", skip(self, _tcx, body))] + fn run_pass(&self, _tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) { + let borrowed = borrowed_locals(body); + let predecessors = body.basic_blocks.predecessors().clone(); + let mut stack = Vec::new(); + + // A return terminator implicitly uses the return place. Walking + // backward through assignments records the locals accessed later on + // this path. + for (bb, data) in body.basic_blocks.iter_enumerated() { + if matches!(data.terminator().kind, TerminatorKind::Return) { + let mut used_after = DenseBitSet::new_empty(body.local_decls.len()); + used_after.insert(RETURN_PLACE); + stack.push(TailState { block: bb, used_after }); + } + } + + while let Some(mut state) = stack.pop() { + // `scan_block` rewrites final-use copies in this block and updates + // `used_after` to the locals whose allocation is accessed after the + // block starts. If the block is not pure tail code, this path is + // done. + if scan_block(body, state.block, &mut state.used_after, &borrowed).is_break() { + continue; + } + + // Continue through predecessor blocks only when the predecessor's + // terminator is a plain `Goto` to this block. Other terminators are + // control-flow or effect boundaries. + let mut first = None; + for pred in predecessors[state.block].iter().copied() { + let terminator = body.basic_blocks[pred].terminator(); + if let TerminatorKind::Goto { target } = terminator.kind { + debug_assert_eq!(target, state.block); + if first.is_none() { + first = Some(pred); + } else { + stack.push(TailState { block: pred, used_after: state.used_after.clone() }); + } + } + } + + // Avoid cloning the bitset for the first predecessor. + if let Some(pred) = first { + stack.push(TailState { block: pred, used_after: state.used_after }); + } + } + } +} + +struct TailState { + block: BasicBlock, + used_after: DenseBitSet, +} + +/// Scan a block backward while the return-tail invariant still holds. +/// +/// The invariant is that a whole-local `Copy` can be changed to a `Move` only +/// if this path has no later access to that local's allocation before +/// returning, and no later operation whose observable behavior could depend on +/// ending an address-observed local's allocation early. `used_after` tracks +/// those later local-allocation accesses. +fn scan_block<'tcx>( + body: &mut Body<'tcx>, + block: BasicBlock, + used_after: &mut DenseBitSet, + borrowed: &DenseBitSet, +) -> ControlFlow<()> { + for statement in body.basic_blocks.as_mut_preserves_cfg()[block].statements.iter_mut().rev() { + match &mut statement.kind { + // Under the local lifetime semantics from RFC 3943, `StorageLive` + // does not allocate, and `StorageDead` has no effect if the local + // was already freed by a move. These markers therefore do not + // affect whether a copy can be treated as a final use. + StatementKind::StorageLive(_) | StatementKind::StorageDead(_) | StatementKind::Nop => {} + StatementKind::Assign((place, rhs)) => { + // Accessing an indirect place may touch any borrowed local, so + // continuing would require treating all borrowed locals as used + // after this point. + if place.is_indirect_first_projection() { + return ControlFlow::Break(()); + } + + // Writing to a borrowed local can start a new allocation range. + // Shortening an earlier borrowed local could remove an overlap + // with that new range. + if borrowed.contains(place.local) { + return ControlFlow::Break(()); + } + + // A destination write accesses the base local, and evaluating + // the destination may also access projection locals, such as an + // index. + record_place_locals(*place, used_after); + + // This pass only models `Use` and `Aggregate` rvalues whose + // operands are direct. Other rvalues are outside the + // conservative return-tail shape handled here. + process_rvalue(rhs, used_after)?; + } + StatementKind::SetDiscriminant { place, .. } => { + // Accessing an indirect place may touch any borrowed local, so + // continuing would require treating all borrowed locals as used + // after this point. + if place.is_indirect_first_projection() { + return ControlFlow::Break(()); + } + + // Writing to a borrowed local can start a new allocation range. + // Shortening an earlier borrowed local could remove an overlap + // with that new range. + if borrowed.contains(place.local) { + return ControlFlow::Break(()); + } + + // `SetDiscriminant` has a validity invariant on the rest of the + // place, so treat the base local as accessed along with any + // projection locals. + record_place_locals(**place, used_after); + } + _ => { + // Anything else may perform effects or evaluate places in ways + // this pass does not model, so it is not part of the pure + // return tail. + return ControlFlow::Break(()); + } + } + } + + ControlFlow::Continue(()) +} + +/// Records all locals used in a place, including `Index` projections in +/// `used_after`. +fn record_place_locals<'tcx>(place: Place<'tcx>, used_after: &mut DenseBitSet) { + for local in place.as_ref().accessed_locals() { + used_after.insert(local); + } +} + +/// Process the RHS of an assignment in a pure return tail. +fn process_rvalue<'tcx>( + rvalue: &mut Rvalue<'tcx>, + used_after: &mut DenseBitSet, +) -> ControlFlow<()> { + match rvalue { + Rvalue::Use(operand, _) => process_operand(operand, used_after), + Rvalue::Aggregate(_, operands) => { + // Operands are evaluated left-to-right. We scan them right-to-left + // so `used_after` includes uses later in the same statement. If an + // operand accesses an indirect place, only earlier operands and + // earlier statements are outside the pure tail. + for operand in operands.iter_mut().rev() { + process_operand(operand, used_after)?; + } + + ControlFlow::Continue(()) + } + _ => { + // This pass doesn't model other rvalues, so they are not part of + // the pure return tail. + ControlFlow::Break(()) + } + } +} + +/// Process one operand in an rvalue. +fn process_operand<'tcx>( + operand: &mut Operand<'tcx>, + used_after: &mut DenseBitSet, +) -> ControlFlow<()> { + let place = match operand { + Operand::Copy(place) | Operand::Move(place) if place.is_indirect_first_projection() => { + // Accessing an indirect place may touch any borrowed local. + // Continuing would require treating all borrowed locals as used + // after this point, which would prevent the useful copy-to-move + // rewrites this pass is looking for. + return ControlFlow::Break(()); + } + Operand::Copy(place) => { + let place = *place; + // No later operation in the scanned tail accesses this local's + // allocation, so this copy is a final use on the current return + // path and can be represented as a move. + if !used_after.contains(place.local) { + *operand = Operand::Move(place); + } + Some(place) + } + Operand::Move(place) => Some(*place), + Operand::Constant(_) | Operand::RuntimeChecks(_) => None, + }; + + if let Some(place) = place { + // Reading an operand place accesses its base local, and evaluating its + // projections may access additional locals, such as the index local in + // `place[index]`. + record_place_locals(place, used_after); + } + + ControlFlow::Continue(()) +} diff --git a/tests/mir-opt/tail_copy_to_move.aggregate.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.aggregate.TailCopyToMove.diff new file mode 100644 index 0000000000000..8c4045d4efcea --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.aggregate.TailCopyToMove.diff @@ -0,0 +1,24 @@ +- // MIR for `aggregate` before TailCopyToMove ++ // MIR for `aggregate` after TailCopyToMove + + fn aggregate(_1: u32, _2: u32) -> Pair { + debug x => _1; + debug y => _2; + let mut _0: Pair; + let mut _3: u32; + let mut _4: u32; + + bb0: { + StorageLive(_3); +- _3 = copy _1; ++ _3 = move _1; + StorageLive(_4); +- _4 = copy _2; ++ _4 = move _2; + _0 = Pair { a: move _3, b: move _4 }; + StorageDead(_4); + StorageDead(_3); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.aggregate_operands.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.aggregate_operands.TailCopyToMove.diff new file mode 100644 index 0000000000000..cf0c2d62d3960 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.aggregate_operands.TailCopyToMove.diff @@ -0,0 +1,13 @@ +- // MIR for `aggregate_operands` before TailCopyToMove ++ // MIR for `aggregate_operands` after TailCopyToMove + + fn aggregate_operands(_1: u32, _2: u32) -> (u32, u32) { + let mut _0: (u32, u32); + + bb0: { +- _0 = (copy _1, copy _2); ++ _0 = (move _1, move _2); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.aggregate_with_deref.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.aggregate_with_deref.TailCopyToMove.diff new file mode 100644 index 0000000000000..f4a70b1d9fabb --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.aggregate_with_deref.TailCopyToMove.diff @@ -0,0 +1,16 @@ +- // MIR for `aggregate_with_deref` before TailCopyToMove ++ // MIR for `aggregate_with_deref` after TailCopyToMove + + fn aggregate_with_deref(_1: u32) -> (u32, u32) { + let mut _0: (u32, u32); + let mut _2: *const u32; + let mut _3: u32; + + bb0: { + _2 = &raw const _1; + _3 = copy _1; + _0 = (copy _3, copy (*_2)); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.borrowed_dest_stops_tail.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.borrowed_dest_stops_tail.TailCopyToMove.diff new file mode 100644 index 0000000000000..ac0046e4624e3 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.borrowed_dest_stops_tail.TailCopyToMove.diff @@ -0,0 +1,17 @@ +- // MIR for `borrowed_dest_stops_tail` before TailCopyToMove ++ // MIR for `borrowed_dest_stops_tail` after TailCopyToMove + + fn borrowed_dest_stops_tail(_1: u32, _2: u32) -> u32 { + debug y => _3; + let mut _0: u32; + let mut _3: u32; + let mut _4: *const u32; + + bb0: { + _4 = &raw const _3; + _0 = copy _1; + _3 = copy _2; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.borrowed_source_tail.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.borrowed_source_tail.TailCopyToMove.diff new file mode 100644 index 0000000000000..fb24d156a7383 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.borrowed_source_tail.TailCopyToMove.diff @@ -0,0 +1,15 @@ +- // MIR for `borrowed_source_tail` before TailCopyToMove ++ // MIR for `borrowed_source_tail` after TailCopyToMove + + fn borrowed_source_tail(_1: u32) -> u32 { + let mut _0: u32; + let mut _2: *const u32; + + bb0: { + _2 = &raw const _1; +- _0 = copy _1; ++ _0 = move _1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.chain.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.chain.TailCopyToMove.diff new file mode 100644 index 0000000000000..d354f9f23446f --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.chain.TailCopyToMove.diff @@ -0,0 +1,22 @@ +- // MIR for `chain` before TailCopyToMove ++ // MIR for `chain` after TailCopyToMove + + fn chain(_1: u32) -> u32 { + debug x => _1; + let mut _0: u32; + let _2: u32; + scope 1 { + debug t => _2; + } + + bb0: { + StorageLive(_2); +- _2 = copy _1; +- _0 = copy _2; ++ _2 = move _1; ++ _0 = move _2; + StorageDead(_2); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.direct.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.direct.TailCopyToMove.diff new file mode 100644 index 0000000000000..84e7c4f9d42ca --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.direct.TailCopyToMove.diff @@ -0,0 +1,14 @@ +- // MIR for `direct` before TailCopyToMove ++ // MIR for `direct` after TailCopyToMove + + fn direct(_1: u32) -> u32 { + debug x => _1; + let mut _0: u32; + + bb0: { +- _0 = copy _1; ++ _0 = move _1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.index_dest.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.index_dest.TailCopyToMove.diff new file mode 100644 index 0000000000000..37ee7527b3492 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.index_dest.TailCopyToMove.diff @@ -0,0 +1,18 @@ +- // MIR for `index_dest` before TailCopyToMove ++ // MIR for `index_dest` after TailCopyToMove + + fn index_dest(_1: [usize; 4], _2: usize) -> [usize; 4] { + debug a => _3; + let mut _0: [usize; 4]; + let mut _3: [usize; 4]; + + bb0: { +- _3 = copy _1; ++ _3 = move _1; + _3[_2] = copy _2; +- _0 = copy _3; ++ _0 = move _3; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.index_operand.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.index_operand.TailCopyToMove.diff new file mode 100644 index 0000000000000..da6bbb117a846 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.index_operand.TailCopyToMove.diff @@ -0,0 +1,13 @@ +- // MIR for `index_operand` before TailCopyToMove ++ // MIR for `index_operand` after TailCopyToMove + + fn index_operand(_1: [u32; 4], _2: usize) -> (usize, u32) { + let mut _0: (usize, u32); + + bb0: { +- _0 = (copy _2, copy _1[_2]); ++ _0 = (copy _2, move _1[_2]); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.indirect_tail_read.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.indirect_tail_read.TailCopyToMove.diff new file mode 100644 index 0000000000000..16ac0dd1806ca --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.indirect_tail_read.TailCopyToMove.diff @@ -0,0 +1,19 @@ +- // MIR for `indirect_tail_read` before TailCopyToMove ++ // MIR for `indirect_tail_read` after TailCopyToMove + + fn indirect_tail_read(_1: u32) -> (u32, u32) { + let mut _0: (u32, u32); + let mut _2: *const u32; + let mut _3: u32; + let mut _4: u32; + + bb0: { + _2 = &raw const _1; + _3 = copy _1; + _4 = copy (*_2); +- _0 = (copy _3, copy _4); ++ _0 = (move _3, move _4); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.indirect_tail_write.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.indirect_tail_write.TailCopyToMove.diff new file mode 100644 index 0000000000000..b98fb6458eec3 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.indirect_tail_write.TailCopyToMove.diff @@ -0,0 +1,16 @@ +- // MIR for `indirect_tail_write` before TailCopyToMove ++ // MIR for `indirect_tail_write` after TailCopyToMove + + fn indirect_tail_write(_1: u32, _2: u32) -> u32 { + debug p => _3; + let mut _0: u32; + let mut _3: *mut u32; + + bb0: { + _3 = &raw mut _1; + _0 = copy _1; + (*_3) = copy _2; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.projected.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.projected.TailCopyToMove.diff new file mode 100644 index 0000000000000..d19a551cfb737 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.projected.TailCopyToMove.diff @@ -0,0 +1,14 @@ +- // MIR for `projected` before TailCopyToMove ++ // MIR for `projected` after TailCopyToMove + + fn projected(_1: Pair) -> u32 { + debug pair => _1; + let mut _0: u32; + + bb0: { +- _0 = copy (_1.0: u32); ++ _0 = move (_1.0: u32); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.projected_dest.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.projected_dest.TailCopyToMove.diff new file mode 100644 index 0000000000000..14911f4313ebd --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.projected_dest.TailCopyToMove.diff @@ -0,0 +1,15 @@ +- // MIR for `projected_dest` before TailCopyToMove ++ // MIR for `projected_dest` after TailCopyToMove + + fn projected_dest(_1: u32, _2: u32) -> (u32, u32) { + let mut _0: (u32, u32); + + bb0: { +- (_0.0: u32) = copy _1; +- (_0.1: u32) = copy _2; ++ (_0.0: u32) = move _1; ++ (_0.1: u32) = move _2; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.repeated_operand.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.repeated_operand.TailCopyToMove.diff new file mode 100644 index 0000000000000..59e775c20f898 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.repeated_operand.TailCopyToMove.diff @@ -0,0 +1,13 @@ +- // MIR for `repeated_operand` before TailCopyToMove ++ // MIR for `repeated_operand` after TailCopyToMove + + fn repeated_operand(_1: u32) -> (u32, u32) { + let mut _0: (u32, u32); + + bb0: { +- _0 = (copy _1, copy _1); ++ _0 = (copy _1, move _1); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.rs b/tests/mir-opt/tail_copy_to_move.rs new file mode 100644 index 0000000000000..c4c18db6570d3 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.rs @@ -0,0 +1,347 @@ +//@ test-mir-pass: TailCopyToMove +//@ compile-flags: -Cpanic=abort + +#![feature(custom_mir, core_intrinsics)] +#![allow(internal_features)] + +use std::intrinsics::mir::*; + +#[derive(Copy, Clone)] +pub struct Pair { + a: u32, + b: u32, +} + +#[derive(Copy, Clone)] +pub enum Choice { + A(u32), + B, +} + +// EMIT_MIR tail_copy_to_move.direct.TailCopyToMove.diff +pub fn direct(x: u32) -> u32 { + // Checks the simplest returned `Copy` local. + // CHECK-LABEL: fn direct( + // CHECK: _0 = move _1; + x +} + +// EMIT_MIR tail_copy_to_move.chain.TailCopyToMove.diff +pub fn chain(x: u32) -> u32 { + // Checks that the scan propagates through a temporary local. + // CHECK-LABEL: fn chain( + // CHECK: debug t => [[TMP:_.*]]; + // CHECK: [[TMP]] = move _1; + // CHECK: _0 = move [[TMP]]; + let t = x; + t +} + +// EMIT_MIR tail_copy_to_move.aggregate.TailCopyToMove.diff +pub fn aggregate(x: u32, y: u32) -> Pair { + // Checks aggregate construction from returned `Copy` locals. + // CHECK-LABEL: fn aggregate( + // CHECK: [[A:_.*]] = move _1; + // CHECK: [[B:_.*]] = move _2; + // CHECK: _0 = Pair { a: move [[A]], b: move [[B]] }; + Pair { a: x, b: y } +} + +// EMIT_MIR tail_copy_to_move.aggregate_operands.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn aggregate_operands(x: u32, y: u32) -> (u32, u32) { + // Checks aggregate operands that are already in the final assignment. + // CHECK-LABEL: fn aggregate_operands( + // CHECK: _0 = (move _1, move _2); + mir!({ + RET = (x, y); + Return() + }) +} + +// EMIT_MIR tail_copy_to_move.projected_dest.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn projected_dest(x: u32, y: u32) -> (u32, u32) { + // Checks assignments to direct projections of the return place. + // CHECK-LABEL: fn projected_dest( + // CHECK: (_0.0: u32) = move _1; + // CHECK: (_0.1: u32) = move _2; + mir! { + type RET = (u32, u32); + { + RET.0 = x; + RET.1 = y; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.projected.TailCopyToMove.diff +pub fn projected(pair: Pair) -> u32 { + // Checks that direct projected source copies are also rewritten. + // CHECK-LABEL: fn projected( + // CHECK: _0 = move (_1.0: u32); + pair.a +} + +// EMIT_MIR tail_copy_to_move.set_discriminant.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn set_discriminant(choice: Choice) -> Choice { + // Checks that `SetDiscriminant` is accepted in the return tail. + // CHECK-LABEL: fn set_discriminant( + // CHECK: _0 = move _1; + // CHECK: discriminant(_0) = 1; + mir!({ + RET = choice; + SetDiscriminant(RET, 1); + Return() + }) +} + +// EMIT_MIR tail_copy_to_move.set_discriminant_indirect.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn set_discriminant_indirect(choice: Choice) -> Choice { + // Checks that an indirect `SetDiscriminant` place stops the scan. + // CHECK-LABEL: fn set_discriminant_indirect( + // CHECK: debug p => [[P:_.*]]; + // CHECK: _0 = copy _1; + // CHECK: discriminant((*[[P]])) = 1; + mir! { + let p: *mut Choice; + debug p => p; + + { + p = &raw mut choice; + RET = choice; + SetDiscriminant(*p, 1); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.set_discriminant_borrowed.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn set_discriminant_borrowed(input: Choice) -> Choice { + // Checks that writing a borrowed local's discriminant stops the scan. + // CHECK-LABEL: fn set_discriminant_borrowed( + // CHECK: debug local => [[LOCAL:_.*]]; + // CHECK: _0 = copy _1; + // CHECK: discriminant([[LOCAL]]) = 1; + mir! { + let local: Choice; + let p: *const Choice; + debug local => local; + + { + p = &raw const local; + RET = input; + SetDiscriminant(local, 1); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.set_discriminant_index.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn set_discriminant_index(arr: [Choice; 4], idx: usize) -> usize { + // Checks that `SetDiscriminant` records projection locals such as indexes. + // CHECK-LABEL: fn set_discriminant_index( + // CHECK: debug local => [[ARR:_.*]]; + // CHECK: [[ARR]] = move _1; + // CHECK: _0 = copy _2; + // CHECK: discriminant([[ARR]][_2]) = 1; + mir! { + let local: [Choice; 4]; + debug local => local; + + { + local = arr; + RET = idx; + SetDiscriminant(local[idx], 1); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.indirect_tail_read.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn indirect_tail_read(x: u32) -> (u32, u32) { + // Checks that an indirect read stops the scan before earlier assignments. + // CHECK-LABEL: fn indirect_tail_read( + // CHECK: [[P:_.*]] = &raw const _1; + // CHECK: [[Q:_.*]] = copy _1; + // CHECK: [[S:_.*]] = copy (*[[P]]); + // CHECK: _0 = (move [[Q]], move [[S]]); + mir! { + let p: *const u32; + let q: u32; + let s: u32; + + { + p = &raw const x; + q = x; + s = *p; + RET = (q, s); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.indirect_tail_write.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn indirect_tail_write(x: u32, z: u32) -> u32 { + // Checks that an indirect assignment destination stops the scan. + // CHECK-LABEL: fn indirect_tail_write( + // CHECK: debug p => [[P:_.*]]; + // CHECK: _0 = copy _1; + // CHECK: (*[[P]]) = copy _2; + mir! { + let p: *mut u32; + debug p => p; + + { + p = &raw mut x; + RET = x; + *p = z; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.aggregate_with_deref.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn aggregate_with_deref(x: u32) -> (u32, u32) { + // Checks that an indirect aggregate operand stops the aggregate scan. + // CHECK-LABEL: fn aggregate_with_deref( + // CHECK: [[P:_.*]] = &raw const _1; + // CHECK: [[Q:_.*]] = copy _1; + // CHECK: _0 = (copy [[Q]], copy (*[[P]])); + mir! { + let p: *const u32; + let q: u32; + + { + p = &raw const x; + q = x; + RET = (q, *p); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.borrowed_dest_stops_tail.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn borrowed_dest_stops_tail(x: u32, z: u32) -> u32 { + // Checks that writing to a borrowed local stops the scan. + // CHECK-LABEL: fn borrowed_dest_stops_tail( + // CHECK: debug y => [[Y:_.*]]; + // CHECK: _0 = copy _1; + // CHECK: [[Y]] = copy _2; + mir! { + let y: u32; + let p: *const u32; + debug y => y; + + { + p = &raw const y; + RET = x; + y = z; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.unrelated_tail_store.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn unrelated_tail_store(x: u32, z: u32) -> u32 { + // Checks that writing to an unborrowed local remains in the tail. + // CHECK-LABEL: fn unrelated_tail_store( + // CHECK: debug y => [[Y:_.*]]; + // CHECK: _0 = move _1; + // CHECK: [[Y]] = move _2; + mir! { + let y: u32; + debug y => y; + + { + RET = x; + y = z; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.index_operand.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn index_operand(arr: [u32; 4], idx: usize) -> (usize, u32) { + // Checks that index projection locals count as later uses. + // CHECK-LABEL: fn index_operand( + // CHECK: _0 = (copy _2, move _1[_2]); + mir! { + { + RET = (idx, arr[idx]); + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.index_dest.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn index_dest(arr: [usize; 4], idx: usize) -> [usize; 4] { + // Checks that index locals in destination projections are recorded. + // CHECK-LABEL: fn index_dest( + // CHECK: debug a => [[ARR:_.*]]; + // CHECK: [[ARR]] = move _1; + // CHECK: [[ARR]][_2] = copy _2; + // CHECK: _0 = move [[ARR]]; + mir! { + let a: [usize; 4]; + debug a => a; + + { + a = arr; + a[idx] = idx; + RET = a; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.repeated_operand.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn repeated_operand(x: u32) -> (u32, u32) { + // Checks right-to-left aggregate scanning for repeated operands. + // CHECK-LABEL: fn repeated_operand( + // CHECK: _0 = (copy _1, move _1); + mir!({ + RET = (x, x); + Return() + }) +} + +// EMIT_MIR tail_copy_to_move.borrowed_source_tail.TailCopyToMove.diff +#[custom_mir(dialect = "runtime", phase = "post-cleanup")] +pub fn borrowed_source_tail(x: u32) -> u32 { + // Checks that a borrowed source can still move at its final use. + // CHECK-LABEL: fn borrowed_source_tail( + // CHECK: [[P:_.*]] = &raw const _1; + // CHECK: _0 = move _1; + mir! { + let p: *const u32; + + { + p = &raw const x; + RET = x; + Return() + } + } +} + +// EMIT_MIR tail_copy_to_move.shared_return.TailCopyToMove.diff +pub fn shared_return(x: u32, y: u32, take_x: bool) -> u32 { + // Checks branch arms that share a return block. + // CHECK-LABEL: fn shared_return( + // CHECK: _0 = move _1; + // CHECK: _0 = move _2; + if take_x { x } else { y } +} diff --git a/tests/mir-opt/tail_copy_to_move.set_discriminant.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.set_discriminant.TailCopyToMove.diff new file mode 100644 index 0000000000000..76f23dae83a91 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.set_discriminant.TailCopyToMove.diff @@ -0,0 +1,14 @@ +- // MIR for `set_discriminant` before TailCopyToMove ++ // MIR for `set_discriminant` after TailCopyToMove + + fn set_discriminant(_1: Choice) -> Choice { + let mut _0: Choice; + + bb0: { +- _0 = copy _1; ++ _0 = move _1; + discriminant(_0) = 1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.set_discriminant_borrowed.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.set_discriminant_borrowed.TailCopyToMove.diff new file mode 100644 index 0000000000000..945c0e6101b4b --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.set_discriminant_borrowed.TailCopyToMove.diff @@ -0,0 +1,17 @@ +- // MIR for `set_discriminant_borrowed` before TailCopyToMove ++ // MIR for `set_discriminant_borrowed` after TailCopyToMove + + fn set_discriminant_borrowed(_1: Choice) -> Choice { + debug local => _2; + let mut _0: Choice; + let mut _2: Choice; + let mut _3: *const Choice; + + bb0: { + _3 = &raw const _2; + _0 = copy _1; + discriminant(_2) = 1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.set_discriminant_index.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.set_discriminant_index.TailCopyToMove.diff new file mode 100644 index 0000000000000..cde22c5d7a9f9 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.set_discriminant_index.TailCopyToMove.diff @@ -0,0 +1,17 @@ +- // MIR for `set_discriminant_index` before TailCopyToMove ++ // MIR for `set_discriminant_index` after TailCopyToMove + + fn set_discriminant_index(_1: [Choice; 4], _2: usize) -> usize { + debug local => _3; + let mut _0: usize; + let mut _3: [Choice; 4]; + + bb0: { +- _3 = copy _1; ++ _3 = move _1; + _0 = copy _2; + discriminant(_3[_2]) = 1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.set_discriminant_indirect.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.set_discriminant_indirect.TailCopyToMove.diff new file mode 100644 index 0000000000000..80df658ce9e25 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.set_discriminant_indirect.TailCopyToMove.diff @@ -0,0 +1,16 @@ +- // MIR for `set_discriminant_indirect` before TailCopyToMove ++ // MIR for `set_discriminant_indirect` after TailCopyToMove + + fn set_discriminant_indirect(_1: Choice) -> Choice { + debug p => _2; + let mut _0: Choice; + let mut _2: *mut Choice; + + bb0: { + _2 = &raw mut _1; + _0 = copy _1; + discriminant((*_2)) = 1; + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.shared_return.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.shared_return.TailCopyToMove.diff new file mode 100644 index 0000000000000..26c0879695ae2 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.shared_return.TailCopyToMove.diff @@ -0,0 +1,34 @@ +- // MIR for `shared_return` before TailCopyToMove ++ // MIR for `shared_return` after TailCopyToMove + + fn shared_return(_1: u32, _2: u32, _3: bool) -> u32 { + debug x => _1; + debug y => _2; + debug take_x => _3; + let mut _0: u32; + let mut _4: bool; + + bb0: { + StorageLive(_4); + _4 = copy _3; + switchInt(move _4) -> [0: bb2, otherwise: bb1]; + } + + bb1: { +- _0 = copy _1; ++ _0 = move _1; + goto -> bb3; + } + + bb2: { +- _0 = copy _2; ++ _0 = move _2; + goto -> bb3; + } + + bb3: { + StorageDead(_4); + return; + } + } + diff --git a/tests/mir-opt/tail_copy_to_move.unrelated_tail_store.TailCopyToMove.diff b/tests/mir-opt/tail_copy_to_move.unrelated_tail_store.TailCopyToMove.diff new file mode 100644 index 0000000000000..4af29766f48e9 --- /dev/null +++ b/tests/mir-opt/tail_copy_to_move.unrelated_tail_store.TailCopyToMove.diff @@ -0,0 +1,17 @@ +- // MIR for `unrelated_tail_store` before TailCopyToMove ++ // MIR for `unrelated_tail_store` after TailCopyToMove + + fn unrelated_tail_store(_1: u32, _2: u32) -> u32 { + debug y => _3; + let mut _0: u32; + let mut _3: u32; + + bb0: { +- _0 = copy _1; +- _3 = copy _2; ++ _0 = move _1; ++ _3 = move _2; + return; + } + } + From e5e0b1057f9579198f4c536dcd2c2f7ad933cf75 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Wed, 23 Sep 2026 13:44:47 +1000 Subject: [PATCH 0680/1309] Fix typo in std::sys::process::unix::unsupported::wait_status documentation --- library/std/src/sys/process/unix/unsupported/wait_status.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/std/src/sys/process/unix/unsupported/wait_status.rs b/library/std/src/sys/process/unix/unsupported/wait_status.rs index ac54824875813..b77e7ae835656 100644 --- a/library/std/src/sys/process/unix/unsupported/wait_status.rs +++ b/library/std/src/sys/process/unix/unsupported/wait_status.rs @@ -1,4 +1,4 @@ -//! Emulated wait status for non-Unix #[cfg(unix) platforms +//! Emulated wait status for non-Unix `#[cfg(unix)]` platforms //! //! Separate module to facilitate testing against a real Unix implementation. From 16e81e97d9747e4da7d68e38234cb9a0e62197e5 Mon Sep 17 00:00:00 2001 From: Amar Shah Date: Tue, 22 Sep 2026 22:49:09 -0700 Subject: [PATCH 0681/1309] Fix bignum build on 16-bit targets --- library/core/src/num/imp/bignum.rs | 6 +++--- library/core/src/num/imp/flt2dec/strategy/dragon.rs | 10 +++++----- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/imp/bignum.rs b/library/core/src/num/imp/bignum.rs index 95046e96fc8f2..5c2a19f39dfce 100644 --- a/library/core/src/num/imp/bignum.rs +++ b/library/core/src/num/imp/bignum.rs @@ -386,7 +386,7 @@ macro_rules! define_bignum { /// the digit type for `Big32x40` pub type Digit32 = u32; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] define_bignum!(Big32x40: type=Digit32, n=40); /// The digit type for `Big64x20`. @@ -395,12 +395,12 @@ pub type Digit64 = u64; #[cfg(target_pointer_width = "64")] define_bignum!(Big64x20: type=Digit64, n=20); -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub type Big = Big32x40; #[cfg(target_pointer_width = "64")] pub type Big = Big64x20; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] pub type Digit = Digit32; #[cfg(target_pointer_width = "64")] pub type Digit = Digit64; diff --git a/library/core/src/num/imp/flt2dec/strategy/dragon.rs b/library/core/src/num/imp/flt2dec/strategy/dragon.rs index 4ae0d4b4ab0ba..b63b93034d57f 100644 --- a/library/core/src/num/imp/flt2dec/strategy/dragon.rs +++ b/library/core/src/num/imp/flt2dec/strategy/dragon.rs @@ -16,22 +16,22 @@ static POW10: [Digit; 10] = [1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000]; // precalculated arrays of `Digit`s for 5^(2^n). // FIXME(#162879): these tables have u64 and u32 versions, future versions may be generated by macro. -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] static POW5TO16: [Digit; 2] = [0x86f26fc1, 0x23]; #[cfg(target_pointer_width = "64")] static POW5TO16: [Digit; 1] = [0x2386f26fc1]; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] static POW5TO32: [Digit; 3] = [0x85acef81, 0x2d6d415b, 0x4ee]; #[cfg(target_pointer_width = "64")] static POW5TO32: [Digit; 2] = [0x2d6d415b85acef81, 0x4ee]; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] static POW5TO64: [Digit; 5] = [0xbf6a1f01, 0x6e38ed64, 0xdaa797ed, 0xe93ff9f4, 0x184f03]; #[cfg(target_pointer_width = "64")] static POW5TO64: [Digit; 3] = [0x6e38ed64bf6a1f01, 0xe93ff9f4daa797ed, 0x184f03]; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] static POW5TO128: [Digit; 10] = [ 0x2e953e01, 0x3df9909, 0xf1538fd, 0x2374e42f, 0xd3cff5ec, 0xc404dc08, 0xbccdb0da, 0xa6337f19, 0xe91f2603, 0x24e, @@ -40,7 +40,7 @@ static POW5TO128: [Digit; 10] = [ static POW5TO128: [Digit; 5] = [0x3df99092e953e01, 0x2374e42f0f1538fd, 0xc404dc08d3cff5ec, 0xa6337f19bccdb0da, 0x24ee91f2603]; -#[cfg(target_pointer_width = "32")] +#[cfg(any(target_pointer_width = "16", target_pointer_width = "32"))] static POW5TO256: [Digit; 19] = [ 0x982e7c01, 0xbed3875b, 0xd8d99f72, 0x12152f87, 0x6bde50c6, 0xcf4a6e70, 0xd595d80f, 0x26b2716e, 0xadc666b0, 0x1d153624, 0x3c42d35a, 0x63ff540e, 0xcc5573c0, 0x65f9ef17, 0x55bc28f2, 0x80dcc7f7, From 8084d720c54590965aac4779edd1d8dc96af51cf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Sep 2026 15:44:49 +1000 Subject: [PATCH 0682/1309] Remove `DiagInner::sort_span` It's a field that can be used for sorting diagnostics. By default it is set to the primary span. It's only used for `BorrowckDiagnosticsBuffer`. This commit removes it and adds a `sort_span` to each diagnostic recorded in `BorrowckDiagnosticsBuffer`. This avoids various other pieces of code having to deal with it. --- .../rustc_borrowck/src/diagnostics/mod.rs | 20 ++++++++++++++----- .../src/diagnostics/outlives_suggestion.rs | 3 +-- compiler/rustc_codegen_ssa/src/back/write.rs | 2 -- compiler/rustc_errors/src/diagnostic.rs | 14 +------------ compiler/rustc_resolve/src/late.rs | 1 - 5 files changed, 17 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index fadcf92b6ea7a..c8abc2689ff7f 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -94,13 +94,19 @@ pub(crate) struct BorrowckDiagnosticsBuffer<'diag, 'tcx> { buffered_mut_errors: FxIndexMap, usize)>, - /// Buffer of diagnostics to be reported. - buffered_diags: Vec>, + /// Buffer of diagnostics to be reported. Each one is paired with a span for sorting purposes; + /// by default it's the primary span. + buffered_diags: Vec<(Span, Diag<'diag>)>, } impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> { pub(crate) fn buffer_error(&mut self, diag: Diag<'diag>) { - self.buffered_diags.push(diag); + let sort_span = diag.span.primary_span().unwrap_or(DUMMY_SP); + self.buffered_diags.push((sort_span, diag)); + } + + pub(crate) fn buffer_error_with_sort_span(&mut self, diag: Diag<'diag>, sort_span: Span) { + self.buffered_diags.push((sort_span, diag)); } pub(crate) fn emit_errors(&mut self) { @@ -117,8 +123,8 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> { } if !self.buffered_diags.is_empty() { - self.buffered_diags.sort_by_key(|diag| diag.sort_span); - for diag in self.buffered_diags.drain(..) { + self.buffered_diags.sort_by_key(|(sort_span, _)| *sort_span); + for (_, diag) in self.buffered_diags.drain(..) { diag.emit(); } } @@ -130,6 +136,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { self.diags_buffer.buffer_error(diag.with_dcx(self.dcx())); } + pub(crate) fn buffer_error_with_sort_span(&mut self, diag: Diag<'_>, sort_span: Span) { + self.diags_buffer.buffer_error_with_sort_span(diag.with_dcx(self.dcx()), sort_span); + } + pub(crate) fn buffer_move_error( &mut self, move_out_indices: Vec, diff --git a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs index 75c666f49a2f7..d7ad34048e5bf 100644 --- a/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs +++ b/compiler/rustc_borrowck/src/diagnostics/outlives_suggestion.rs @@ -220,9 +220,8 @@ impl OutlivesSuggestionBuilder { // We want this message to appear after other messages on the mir def. let mir_span = mbcx.body.span; - diag.sort_span = mir_span.shrink_to_hi(); // Buffer the diagnostic - mbcx.buffer_error(diag); + mbcx.buffer_error_with_sort_span(diag, mir_span.shrink_to_hi()); } } diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 06453ffd24ed9..f16eb78b36e35 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -1199,7 +1199,6 @@ pub struct CguMessage; // - `span`: it doesn't impl `Send`. // - `suggestions`: it doesn't impl `Send`, and isn't used for codegen // diagnostics. -// - `sort_span`: it doesn't impl `Send`. // - `is_lint`: lints aren't relevant during codegen. // - `emitted_at`: not used for codegen diagnostics. struct Diagnostic { @@ -1993,7 +1992,6 @@ impl Emitter for SharedEmitter { // the cut-down local `DiagInner`. assert!(!diag.span.has_span_labels()); assert_eq!(diag.suggestions, Suggestions::Enabled(vec![])); - assert_eq!(diag.sort_span, rustc_span::DUMMY_SP); assert_eq!(diag.is_lint, None); // No sensible check for `diag.emitted_at`. diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 729569fd5f5d1..9688f99abfebb 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,7 +12,7 @@ use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg}; use rustc_hashes::Hash128; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; -use rustc_span::{DUMMY_SP, Span, Spanned, Symbol}; +use rustc_span::{Span, Spanned, Symbol}; use tracing::debug; use crate::{ @@ -195,14 +195,7 @@ pub struct DiagInner { pub children: Vec, pub suggestions: Suggestions, pub args: DiagArgMap, - - /// This is not used for highlighting or rendering any error message. Rather, it can be used - /// as a sort key to sort a buffer of diagnostics. By default, it is the primary span of - /// `span` if there is one. Otherwise, it is `DUMMY_SP`. - pub sort_span: Span, - pub is_lint: Option, - pub long_ty_path: Option, /// With `-Ztrack_diagnostics` enabled, /// we print where in rustc this error was emitted. @@ -226,7 +219,6 @@ impl DiagInner { children: vec![], suggestions: Suggestions::Enabled(vec![]), args: Default::default(), - sort_span: DUMMY_SP, is_lint: None, long_ty_path: None, emitted_at: DiagLocation::caller(), @@ -320,7 +312,6 @@ impl DiagInner { children, suggestions, args, - sort_span: _, // ignore is_lint, long_ty_path: _, // ignore emitted_at: _, // ignore @@ -1088,9 +1079,6 @@ impl<'a> Diag<'a> { /// Add a span. pub fn span(&mut self, sp: impl Into) -> &mut Self { self.span = sp.into(); - if let Some(span) = self.span.primary_span() { - self.sort_span = span; - } self } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7d90b93b62375..9c4d51aee9fe6 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4751,7 +4751,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } else { err.children.append(&mut parent_err.children); } - err.sort_span = parent_err.sort_span; err.is_lint = parent_err.is_lint.clone(); // merge the parent_err's suggestions with the typo (err's) suggestions From 039b8bcadc7bcce087a278668f2bf7a56d7cc60c Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 1 Sep 2026 09:40:37 +0200 Subject: [PATCH 0683/1309] Add address_space and byref to abi PassMode::Indirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both will be used by the amdgpu target to implement the `gpu-kernel` ABI. `address_space` specifies the address space of an indirect argument. `AmdgpuKernelArg` translates to LLVM’s byref, which is similar to on_stack/byval, however, there is no extra copy made, the pointer may not point to the stack but can point to some other address space, and the passed argument should not be modified. byval and byref are mutually exclusive, so change on_stack to an enum with the new states, Pointer (none), OnStack and AmdgpuKernelArg. --- compiler/rustc_abi/src/layout/ty.rs | 4 +- .../src/abi/pass_mode.rs | 24 ++-- .../src/abi/returning.rs | 17 +-- compiler/rustc_codegen_gcc/src/abi.rs | 33 ++++- compiler/rustc_codegen_llvm/src/abi.rs | 111 +++++++++++++--- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 1 + compiler/rustc_codegen_llvm/src/llvm/mod.rs | 4 + compiler/rustc_codegen_ssa/src/mir/block.rs | 48 ++++--- compiler/rustc_codegen_ssa/src/mir/mod.rs | 16 ++- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 5 + .../src/deduce_param_attrs.rs | 2 +- compiler/rustc_public/src/abi.rs | 18 ++- .../src/unstable/convert/stable/abi.rs | 35 +++-- compiler/rustc_target/src/callconv/mod.rs | 125 ++++++++++++++---- compiler/rustc_target/src/callconv/x86.rs | 5 +- compiler/rustc_target/src/callconv/xtensa.rs | 6 +- compiler/rustc_ty_utils/src/abi.rs | 14 +- tests/assembly-llvm/tail-call-indirect.rs | 6 +- tests/ui-fulldeps/rustc_public/check_abi.rs | 8 +- .../rustc_public/check_abi_cast.rs | 4 +- tests/ui/abi/c-zst.powerpc-linux.stderr | 3 +- tests/ui/abi/c-zst.s390x-linux.stderr | 3 +- tests/ui/abi/c-zst.sparc-linux.stderr | 3 +- tests/ui/abi/c-zst.sparc-none.stderr | 3 +- tests/ui/abi/c-zst.sparc64-linux.stderr | 3 +- .../ui/abi/c-zst.x86_64-pc-windows-gnu.stderr | 3 +- tests/ui/abi/debug.generic.stderr | 6 +- tests/ui/abi/debug.loongarch64.stderr | 6 +- tests/ui/abi/debug.riscv64.stderr | 6 +- tests/ui/abi/pass-indirectly-attr.rs | 2 +- tests/ui/abi/pass-indirectly-attr.stderr | 3 +- .../pass-by-value-abi.aarch64.stderr | 3 +- tests/ui/c-variadic/pass-by-value-abi.rs | 8 +- .../pass-by-value-abi.x86_64.stderr | 9 +- tests/ui/explicit-tail-calls/indirect.rs | 10 +- 35 files changed, 406 insertions(+), 151 deletions(-) diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs index e51255dc5963f..b8928aecf0cc5 100644 --- a/compiler/rustc_abi/src/layout/ty.rs +++ b/compiler/rustc_abi/src/layout/ty.rs @@ -233,8 +233,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { } /// If this method returns `true`, then this type should always have a `PassMode` of - /// `Indirect { on_stack: false, .. }` when being used as the argument type of a function with a - /// non-Rustic ABI (this is true for structs annotated with the + /// `Indirect { mode: IndirectMode::Pointer, .. }` when being used as the argument type of a + /// function with a non-Rustic ABI (this is true for structs annotated with the /// `#[rustc_pass_indirectly_in_non_rustic_abis]` attribute). /// /// This is used to replicate some of the behaviour of C array-to-pointer decay; however unlike diff --git a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs index 1c552ca1a9c32..48ffc43c5cfa1 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/pass_mode.rs @@ -3,7 +3,7 @@ use cranelift_codegen::ir::ArgumentPurpose; use rustc_abi::{Reg, RegKind}; use rustc_target::callconv::{ - ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, PassMode, + ArgAbi, ArgAttributes, ArgExtension as RustcArgExtension, CastTarget, IndirectMode, PassMode, }; use smallvec::{SmallVec, smallvec}; @@ -126,8 +126,12 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { assert_eq!(pad_i32_count, 0, "padding support not yet implemented"); cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect() } - PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { - if on_stack { + PassMode::Indirect { attrs, meta_attrs: None, address_space: _, mode } => { + assert!( + mode != IndirectMode::AmdgpuKernelArg, + "unsupported amdgpu kernel argument" + ); + if mode == IndirectMode::OnStack { // Abi requires aligning struct size to pointer size let size = self.layout.size.align_to(tcx.data_layout.pointer_align().abi); let size = u32::try_from(size.bytes()).unwrap(); @@ -139,8 +143,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { smallvec![apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs)] } } - PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { - assert!(!on_stack); + PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), address_space: _, mode } => { + assert!(mode == IndirectMode::Pointer); smallvec![ apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), attrs), apply_attrs_to_abi_param(AbiParam::new(pointer_ty(tcx)), meta_attrs), @@ -184,8 +188,8 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { None, cast_target_to_abi_params(cast).into_iter().map(|(_, param)| param).collect(), ), - PassMode::Indirect { attrs, meta_attrs: None, on_stack } => { - assert!(!on_stack); + PassMode::Indirect { attrs, meta_attrs: None, address_space: _, mode } => { + assert!(mode == IndirectMode::Pointer); ( Some(apply_attrs_to_abi_param( AbiParam::special(pointer_ty(tcx), ArgumentPurpose::StructReturn), @@ -194,7 +198,7 @@ impl<'tcx> ArgAbiExt<'tcx> for ArgAbi<'tcx, Ty<'tcx>> { vec![], ) } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { unreachable!("unsized return value") } } @@ -324,7 +328,7 @@ pub(super) fn cvalue_for_param<'tcx>( PassMode::Cast { ref cast, .. } => { from_casted_value(fx, &block_params, arg_abi.layout, cast) } - PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs, meta_attrs: None, address_space: _, mode: _ } => { assert_eq!(block_params.len(), 1, "{:?}", block_params); if let Some(pointee_align) = attrs.pointee_align && pointee_align < arg_abi.layout.align.abi @@ -342,7 +346,7 @@ pub(super) fn cvalue_for_param<'tcx>( CValue::by_ref(Pointer::new(block_params[0]), arg_abi.layout) } } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { assert_eq!(block_params.len(), 2, "{:?}", block_params); CValue::by_ref_unsized(Pointer::new(block_params[0]), block_params[1], arg_abi.layout) } diff --git a/compiler/rustc_codegen_cranelift/src/abi/returning.rs b/compiler/rustc_codegen_cranelift/src/abi/returning.rs index 36087f96dd776..7f4ee9435b506 100644 --- a/compiler/rustc_codegen_cranelift/src/abi/returning.rs +++ b/compiler/rustc_codegen_cranelift/src/abi/returning.rs @@ -17,12 +17,12 @@ pub(super) fn codegen_return_param<'tcx>( let is_ssa = ssa_analyzed[RETURN_PLACE].is_ssa(fx, fx.fn_abi.ret.layout.ty); (super::make_local_place(fx, RETURN_PLACE, fx.fn_abi.ret.layout, is_ssa), smallvec![]) } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } => { let ret_param = block_params_iter.next().unwrap(); assert_eq!(fx.bcx.func.dfg.value_type(ret_param), fx.pointer_type); (CPlace::for_ptr(Pointer::new(ret_param), fx.fn_abi.ret.layout), smallvec![ret_param]) } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { unreachable!("unsized return value") } }; @@ -50,7 +50,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( ) { let (ret_temp_place, return_ptr) = match ret_arg_abi.mode { PassMode::Ignore => (None, None), - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } => { if let Some(ret_ptr) = ret_place.try_to_ptr() { // This is an optimization to prevent unnecessary copies of the return value when // the return place is already a memory place as opposed to a register. @@ -61,7 +61,7 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( (Some(place), Some(place.to_ptr().get_addr(fx))) } } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { unreachable!("unsized return value") } PassMode::Direct(_) | PassMode::Pair(_, _) | PassMode::Cast { .. } => (None, None), @@ -86,14 +86,14 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( super::pass_mode::from_casted_value(fx, &results, ret_place.layout(), cast); ret_place.write_cvalue(fx, result); } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } => { if let Some(ret_temp_place) = ret_temp_place { // If ret_temp_place is None, it is not necessary to copy the return value. let ret_temp_value = ret_temp_place.to_cvalue(fx); ret_place.write_cvalue(fx, ret_temp_value); } } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { unreachable!("unsized return value") } } @@ -102,10 +102,11 @@ pub(super) fn codegen_with_call_return_arg<'tcx>( /// Codegen a return instruction with the right return value(s) if any. pub(crate) fn codegen_return(fx: &mut FunctionCx<'_, '_, '_>) { match fx.fn_abi.ret.mode { - PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { + PassMode::Ignore + | PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } => { fx.bcx.ins().return_(&[]); } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { unreachable!("unsized return value") } PassMode::Direct(_) => { diff --git a/compiler/rustc_codegen_gcc/src/abi.rs b/compiler/rustc_codegen_gcc/src/abi.rs index 63eaf52ce9f01..5b88cebb4f174 100644 --- a/compiler/rustc_codegen_gcc/src/abi.rs +++ b/compiler/rustc_codegen_gcc/src/abi.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::{Session, config}; use rustc_span::bug; -use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, IndirectMode, PassMode}; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -189,7 +189,12 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs, argument_tys.len()) } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { + attrs: _, + meta_attrs: None, + address_space: _, + mode: IndirectMode::OnStack, + } => { let x86_interrupt_first_arg = { #[cfg(feature = "master")] { @@ -216,14 +221,32 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { arg.layout.gcc_type(cx) } } + PassMode::Indirect { + attrs: _, + meta_attrs: None, + address_space: _, + mode: IndirectMode::AmdgpuKernelArg, + } => { + unimplemented!("unsupported amdgpu kernel argument") + } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) } - PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::Pointer, + } => { apply_attrs(cx.type_ptr_to(arg.layout.gcc_type(cx)), &attrs, argument_tys.len()) } - PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { - assert!(!on_stack); + PassMode::Indirect { + attrs, + meta_attrs: Some(meta_attrs), + address_space: _, + mode, + } => { + assert!(mode == IndirectMode::Pointer); // Construct the type of a (wide) pointer to `ty`, and pass its two fields. // Any two ABI-compatible unsized types have the same metadata type and // moreover the same metadata value leads to the same dynamic size and diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index dce8db6841b7f..e16f34483a0c5 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -15,7 +15,7 @@ use rustc_middle::ty::layout::LayoutOf; use rustc_session::{Session, config}; use rustc_span::bug; use rustc_target::callconv::{ - ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, + ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, IndirectMode, PassMode, }; use rustc_target::spec::{Arch, SanitizerSet}; use smallvec::SmallVec; @@ -243,12 +243,12 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { match &self.mode { PassMode::Ignore => {} // Sized indirect arguments - PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs, meta_attrs: None, address_space: _, mode: _ } => { let align = attrs.pointee_align.unwrap_or(self.layout.align.abi); OperandValue::Ref(PlaceValue::new_sized(val, align)).store(bx, dst); } // Unsized indirect arguments cannot be stored - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { bug!("unsized `ArgAbi` cannot be stored"); } PassMode::Cast { cast, pad_i32_count: _ } => { @@ -304,11 +304,11 @@ impl<'ll, 'tcx> ArgAbiExt<'ll, 'tcx> for ArgAbi<'tcx, Ty<'tcx>> { PassMode::Pair(..) => { OperandValue::Pair(next(), next()).store(bx, dst); } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { bug!("unsized `ArgAbi` cannot be stored"); } PassMode::Direct(_) - | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } + | PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } | PassMode::Cast { .. } => { let next_arg = next(); self.store(bx, next_arg, dst); @@ -369,8 +369,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Ignore => cx.type_void(), PassMode::Direct(_) | PassMode::Pair(..) => self.ret.layout.immediate_llvm_type(cx), PassMode::Cast { cast, pad_i32_count: _ } => cast.llvm_type(cx), - PassMode::Indirect { .. } => { - llargument_tys.push(cx.type_ptr()); + PassMode::Indirect { address_space, .. } => { + let ty = if let Some(address_space) = address_space { + cx.type_ptr_ext(*address_space) + } else { + cx.type_ptr() + }; + llargument_tys.push(ty); cx.type_void() } }; @@ -395,7 +400,7 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(arg.layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { // Construct the type of a (wide) pointer to `ty`, and pass its two fields. // Any two ABI-compatible unsized types have the same metadata type and // moreover the same metadata value leads to the same dynamic size and @@ -406,7 +411,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { llargument_tys.push(ptr_layout.scalar_pair_element_llvm_type(cx, 1, true)); continue; } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => cx.type_ptr(), + PassMode::Indirect { attrs: _, meta_attrs: None, address_space, mode: _ } => { + if let Some(address_space) = address_space { + cx.type_ptr_ext(*address_space) + } else { + cx.type_ptr() + } + } PassMode::Cast { cast, pad_i32_count } => { // Add padding. llargument_tys.extend(std::iter::repeat_n( @@ -496,8 +507,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { apply_range_attr(llvm::AttributePlace::ReturnValue, scalar); } } - PassMode::Indirect { attrs, meta_attrs: _, on_stack } => { - assert!(!on_stack); + PassMode::Indirect { attrs, meta_attrs: _, address_space: _, mode } => { + assert!(*mode == IndirectMode::Pointer); let i = apply(attrs); let sret = llvm::CreateStructRetAttr( cx.llcx, @@ -523,7 +534,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { for arg in self.args.iter() { match &arg.mode { PassMode::Ignore => {} - PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::OnStack, + } => { let i = apply(attrs); let byval = llvm::CreateByValAttr( cx.llcx, @@ -531,13 +547,31 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byval]); } + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::AmdgpuKernelArg, + } => { + let i = apply(attrs); + let byref = llvm::CreateByRefAttr( + cx.llcx, + cx.type_array(cx.type_i8(), arg.layout.size.bytes()), + ); + attributes::apply_to_llfn(llfn, llvm::AttributePlace::Argument(i), &[byref]); + } PassMode::Direct(attrs) => { let i = apply(attrs); if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr { apply_range_attr(llvm::AttributePlace::Argument(i), scalar); } } - PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::Pointer, + } => { let i = apply(attrs); if cx.sess().opts.optimize != config::OptLevel::No { attributes::apply_to_llfn( @@ -547,8 +581,13 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { ); } } - PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { - assert!(!on_stack); + PassMode::Indirect { + attrs, + meta_attrs: Some(meta_attrs), + address_space: _, + mode, + } => { + assert!(*mode == IndirectMode::Pointer); apply(attrs); apply(meta_attrs); } @@ -626,8 +665,8 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { PassMode::Direct(attrs) => { attrs.apply_attrs_to_callsite(llvm::AttributePlace::ReturnValue, bx.cx, callsite); } - PassMode::Indirect { attrs, meta_attrs: _, on_stack } => { - assert!(!on_stack); + PassMode::Indirect { attrs, meta_attrs: _, address_space: _, mode } => { + assert!(*mode == IndirectMode::Pointer); let i = apply(bx.cx, attrs); let sret = llvm::CreateStructRetAttr( bx.cx.llcx, @@ -647,7 +686,12 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { for arg in self.args.iter() { match &arg.mode { PassMode::Ignore => {} - PassMode::Indirect { attrs, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::OnStack, + } => { let i = apply(bx.cx, attrs); let byval = llvm::CreateByValAttr( bx.cx.llcx, @@ -659,11 +703,38 @@ impl<'ll, 'tcx> FnAbiLlvmExt<'ll, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { &[byval], ); } + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::AmdgpuKernelArg, + } => { + let i = apply(bx.cx, attrs); + let byref = llvm::CreateByRefAttr( + bx.cx.llcx, + bx.cx.type_array(bx.cx.type_i8(), arg.layout.size.bytes()), + ); + attributes::apply_to_callsite( + callsite, + llvm::AttributePlace::Argument(i), + &[byref], + ); + } PassMode::Direct(attrs) - | PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { + | PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::Pointer, + } => { apply(bx.cx, attrs); } - PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack: _ } => { + PassMode::Indirect { + attrs, + meta_attrs: Some(meta_attrs), + address_space: _, + mode: _, + } => { apply(bx.cx, attrs); apply(bx.cx, meta_attrs); } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 52218bfa336b8..07381745afe84 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2016,6 +2016,7 @@ unsafe extern "C" { pub(crate) fn LLVMRustCreateDereferenceableAttr(C: &Context, bytes: u64) -> &Attribute; pub(crate) fn LLVMRustCreateDereferenceableOrNullAttr(C: &Context, bytes: u64) -> &Attribute; pub(crate) fn LLVMRustCreateByValAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; + pub(crate) fn LLVMRustCreateByRefAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; pub(crate) fn LLVMRustCreateStructRetAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; pub(crate) fn LLVMRustCreateElementTypeAttr<'a>(C: &'a Context, ty: &'a Type) -> &'a Attribute; pub(crate) fn LLVMRustCreateUWTableAttr(C: &Context, async_: bool) -> &Attribute; diff --git a/compiler/rustc_codegen_llvm/src/llvm/mod.rs b/compiler/rustc_codegen_llvm/src/llvm/mod.rs index 5452f4abc5c33..89e4d60656d34 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/mod.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/mod.rs @@ -122,6 +122,10 @@ pub(crate) fn CreateByValAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll At unsafe { LLVMRustCreateByValAttr(llcx, ty) } } +pub(crate) fn CreateByRefAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute { + unsafe { LLVMRustCreateByRefAttr(llcx, ty) } +} + pub(crate) fn CreateStructRetAttr<'ll>(llcx: &'ll Context, ty: &'ll Type) -> &'ll Attribute { unsafe { LLVMRustCreateStructRetAttr(llcx, ty) } } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6b0def4ffa182..f99009a0f4243 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Instance, Ty, TypeVisitableExt}; use rustc_session::config::OptLevel; use rustc_span::{Span, Spanned, bug, span_bug}; -use rustc_target::callconv::{ArgAbi, ArgAttributes, CastTarget, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAbi, ArgAttributes, CastTarget, FnAbi, IndirectMode, PassMode}; use tracing::{debug, info}; use super::operand::OperandRef; @@ -1257,7 +1257,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { (args, None) }; - // Special logic for tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. + // Special logic for tail calls with `PassMode::Indirect { mode: IndirectMode::Pointer, .. }` arguments. // // Normally an indirect argument that is allocated in the caller's stack frame // would be passed as a pointer into the callee's stack frame. @@ -1282,10 +1282,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let mut tail_call_temporaries = vec![]; if kind == CallKind::Tail { tail_call_temporaries = vec![None; first_args.len()]; - // Copy the arguments that use `PassMode::Indirect { on_stack: false , ..}` + // Copy the arguments that use `PassMode::Indirect { mode: IndirectMode::Pointer , ..}` // to temporary stack allocations. See the comment above. for (i, arg) in first_args.iter().enumerate() { - if !matches!(fn_abi.args[i].mode, PassMode::Indirect { on_stack: false, .. }) { + if !matches!( + fn_abi.args[i].mode, + PassMode::Indirect { mode: IndirectMode::Pointer, .. } + ) { continue; } @@ -1353,10 +1356,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } } - let by_move = if let PassMode::Indirect { on_stack: false, .. } = fn_abi.args[i].mode + let by_move = if let PassMode::Indirect { mode: IndirectMode::Pointer, .. } = + fn_abi.args[i].mode && kind == CallKind::Tail { - // Special logic for tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. + // Special logic for tail calls with `PassMode::Indirect { mode: IndirectMode::Pointer, .. }` arguments. // // Normally an indirect argument that is allocated in the caller's stack frame // would be passed as a pointer into the callee's stack frame. @@ -1977,14 +1981,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } _ => bug!("codegen_argument: {:?} invalid for pair argument", op), }, - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => match op.val { - Ref(PlaceValue { llval: a, llextra: Some(b), .. }) => { - llargs.push(a); - llargs.push(b); - return; + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { + match op.val { + Ref(PlaceValue { llval: a, llextra: Some(b), .. }) => { + llargs.push(a); + llargs.push(b); + return; + } + _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op), } - _ => bug!("codegen_argument: {:?} invalid for unsized indirect argument", op), - }, + } _ => {} } @@ -2014,7 +2020,10 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { PassMode::Ignore | PassMode::Pair(..) => unreachable!("handled above"), }, Ref(op_place_val) => match arg.mode { - PassMode::Indirect { attrs, on_stack, .. } => { + PassMode::Indirect { attrs, mode, .. } => { + if mode == IndirectMode::AmdgpuKernelArg { + bug!("{op:?} passed as amdgpu kernel argument with abi {arg:?}"); + } // For `foo(packed.large_field)`, and types with <4 byte alignment on x86, // alignment requirements may be higher than the type's alignment, so copy // to a higher-aligned alloca. @@ -2023,7 +2032,9 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { None => arg.layout.align.abi, }; // Copy to an alloca when the argument is neither by-val nor by-move. - if op_place_val.align < required_align || (!on_stack && !by_move) { + if op_place_val.align < required_align + || (mode == IndirectMode::Pointer && !by_move) + { let scratch = PlaceValue::alloca(bx, arg.layout.size, required_align); bx.lifetime_start(scratch.llval, arg.layout.size); op.store_with_annotation(bx, scratch.with_type(arg.layout)); @@ -2036,8 +2047,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { _ => (op_place_val.llval, op_place_val.align, true), }, ZeroSized => match arg.mode { - PassMode::Indirect { on_stack, .. } => { - if on_stack { + PassMode::Indirect { mode, .. } => { + if mode == IndirectMode::AmdgpuKernelArg { + bug!("{op:?} passed as amdgpu kernel argument with abi {arg:?}"); + } + if mode == IndirectMode::OnStack { // It doesn't seem like any target can have `byval` ZSTs, so this assert // is here to replace a would-be untested codepath. bug!("ZST {op:?} passed on stack with abi {arg:?}"); diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs index b5cecf4b5c434..aefa8356536dc 100644 --- a/compiler/rustc_codegen_ssa/src/mir/mod.rs +++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs @@ -8,7 +8,7 @@ use rustc_middle::mir::{Body, Local, UnwindTerminateReason, traversal}; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Instance, Ty, TyCtxt, TypeFoldable, TypeVisitableExt}; use rustc_span::{ErrorGuaranteed, bug, span_bug}; -use rustc_target::callconv::{FnAbi, PassMode}; +use rustc_target::callconv::{FnAbi, IndirectMode, PassMode}; use tracing::{debug, instrument}; use crate::base; @@ -561,15 +561,21 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( match arg.mode { // Sized indirect arguments - PassMode::Indirect { attrs, meta_attrs: None, on_stack: _ } => { + PassMode::Indirect { attrs, meta_attrs: None, address_space: _, mode } => { // Don't copy an indirect argument to an alloca, the caller already put it // in a temporary alloca and gave it up. + // AmdgpuKernelArg/byref arguments must not be modified, so always create a + // local alloca for them. + // If the argument is underaligned, then we need to copy it to a higher-aligned + // alloca. // FIXME: lifetimes + let mut needs_alloca = mode == IndirectMode::AmdgpuKernelArg; if let Some(pointee_align) = attrs.pointee_align && pointee_align < arg.layout.align.abi { - // ...unless the argument is underaligned, then we need to copy it to - // a higher-aligned alloca. + needs_alloca = true; + } + if needs_alloca { let tmp = PlaceRef::alloca(bx, arg.layout); bx.store_fn_arg(arg, &mut llarg_idx, tmp); LocalRef::Place(tmp) @@ -580,7 +586,7 @@ fn arg_local_refs<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>( } } // Unsized indirect arguments - PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } => { + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } => { // As the storage for the indirect argument lives during // the whole function call, we just copy the wide pointer. let llarg = bx.get_param(llarg_idx); diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 161b5bdb952d3..bc8fa60b66a52 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -480,6 +480,11 @@ extern "C" LLVMAttributeRef LLVMRustCreateByValAttr(LLVMContextRef C, return wrap(Attribute::getWithByValType(*unwrap(C), unwrap(Ty))); } +extern "C" LLVMAttributeRef LLVMRustCreateByRefAttr(LLVMContextRef C, + LLVMTypeRef Ty) { + return wrap(Attribute::getWithByRefType(*unwrap(C), unwrap(Ty))); +} + extern "C" LLVMAttributeRef LLVMRustCreateStructRetAttr(LLVMContextRef C, LLVMTypeRef Ty) { return wrap(Attribute::getWithStructRetType(*unwrap(C), unwrap(Ty))); diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs index 5bba125aefc58..8814670ca4300 100644 --- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs +++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs @@ -135,7 +135,7 @@ impl<'tcx> Visitor<'tcx> for DeduceParamAttrs { } // Like a call, but more conservative because the backend may introduce writes to an - // argument if the argument is passed as `PassMode::Indirect { on_stack: false, ... }`. + // argument if the argument is passed as `PassMode::Indirect { mode: IndirectMode::Pointer, ... }`. TerminatorKind::TailCall { .. } => { for usage in self.usage.iter_mut() { *usage |= UsageSummary::MUTATE; diff --git a/compiler/rustc_public/src/abi.rs b/compiler/rustc_public/src/abi.rs index 67d609c780c42..72387fce19797 100644 --- a/compiler/rustc_public/src/abi.rs +++ b/compiler/rustc_public/src/abi.rs @@ -41,6 +41,19 @@ pub struct ArgAbi { pub mode: PassMode, } +/// Different modes in which indirect arguments can be passed. +#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Serialize)] +pub enum IndirectMode { + /// Passed as a normal pointer, nothing special. + Pointer, + /// The value is placed at a fixed stack offset rather than passed as a regular pointer + /// argument. + OnStack, + /// Similar to `OnStack` except that the pointer does not necessarily point to the stack, no + /// extra copy is made, and the passed argument should not be modified. + AmdgpuKernelArg, +} + /// How a function argument should be passed in to the target function. /// /// The pass mode is determined by the platform's calling convention and the @@ -74,14 +87,13 @@ pub enum PassMode { /// Pass the argument indirectly via a pointer. /// /// The caller places the value in memory and passes a pointer to it. - /// When `on_stack` is true, the value is placed at a fixed stack offset - /// rather than passed as a regular pointer argument. Indirect { attrs: ArgAttributes, /// Attributes for the metadata pointer (vtable or length) of unsized arguments. /// Only present for unsized types (e.g., `dyn Trait`, `[T]`). meta_attrs: Option, - on_stack: bool, + address_space: Option, + mode: IndirectMode, }, } diff --git a/compiler/rustc_public/src/unstable/convert/stable/abi.rs b/compiler/rustc_public/src/unstable/convert/stable/abi.rs index 3c268a6dd23a4..1ac0b706ed091 100644 --- a/compiler/rustc_public/src/unstable/convert/stable/abi.rs +++ b/compiler/rustc_public/src/unstable/convert/stable/abi.rs @@ -11,9 +11,9 @@ use rustc_target::callconv; use crate::IndexedVal; use crate::abi::{ AddressSpace, ArgAbi, ArgAttributes, ArgExtension, CallConvention, CastTarget, FieldsShape, - FloatLength, FnAbi, IntegerLength, IntegerType, Layout, LayoutShape, NumScalableVectors, - PassMode, Primitive, Reg, RegKind, ReprFlags, ReprOptions, Scalar, TagEncoding, TyAndLayout, - Uniform, ValueRepr, VariantFields, VariantsShape, WrappingRange, + FloatLength, FnAbi, IndirectMode, IntegerLength, IntegerType, Layout, LayoutShape, + NumScalableVectors, PassMode, Primitive, Reg, RegKind, ReprFlags, ReprOptions, Scalar, + TagEncoding, TyAndLayout, Uniform, ValueRepr, VariantFields, VariantsShape, WrappingRange, }; use crate::compiler_interface::BridgeTys; use crate::target::MachineSize as Size; @@ -155,6 +155,22 @@ impl<'tcx> Stable<'tcx> for CanonAbi { } } +impl<'tcx> Stable<'tcx> for callconv::IndirectMode { + type T = IndirectMode; + + fn stable<'cx>( + &self, + _tables: &mut Tables<'cx, BridgeTys>, + _cx: &CompilerCtxt<'cx, BridgeTys>, + ) -> Self::T { + match self { + callconv::IndirectMode::Pointer => IndirectMode::Pointer, + callconv::IndirectMode::OnStack => IndirectMode::OnStack, + callconv::IndirectMode::AmdgpuKernelArg => IndirectMode::AmdgpuKernelArg, + } + } +} + impl<'tcx> Stable<'tcx> for callconv::PassMode { type T = PassMode; @@ -172,11 +188,14 @@ impl<'tcx> Stable<'tcx> for callconv::PassMode { callconv::PassMode::Cast { pad_i32_count, cast } => { PassMode::Cast { pad_i32_count: *pad_i32_count, cast: cast.stable(tables, cx) } } - callconv::PassMode::Indirect { attrs, meta_attrs, on_stack } => PassMode::Indirect { - attrs: attrs.stable(tables, cx), - meta_attrs: meta_attrs.map(|a| a.stable(tables, cx)), - on_stack: *on_stack, - }, + callconv::PassMode::Indirect { attrs, meta_attrs, address_space, mode } => { + PassMode::Indirect { + attrs: attrs.stable(tables, cx), + meta_attrs: meta_attrs.map(|a| a.stable(tables, cx)), + address_space: address_space.stable(tables, cx), + mode: mode.stable(tables, cx), + } + } } } } diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index 1ac6168035085..edc23b6c50b45 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -36,6 +36,25 @@ mod x86_win32; mod x86_win64; mod xtensa; +/// Different modes in which indirect arguments can be passed. +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug, StableHash)] +pub enum IndirectMode { + /// Passed as a normal pointer, nothing special. + Pointer, + /// The value should be passed at a fixed stack offset in accordance to + /// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument + /// attribute. The `byval` argument will use a byte array with the same size as the Rust type + /// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout), + /// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's + /// alignment (if `None`). This means that the alignment will not always + /// match the Rust type's alignment; see documentation of `pass_by_stack_offset` for more info. + OnStack, + /// `AmdgpuKernelArg` behaves similar to `OnStack` except that the pointer does not necessarily + /// point to the stack, no extra copy is made, and the passed argument should not be modified. + /// This corresponds to the `byref` LLVM argument attribute. + AmdgpuKernelArg, +} + #[derive(Clone, PartialEq, Eq, Hash, Debug, StableHash)] pub enum PassMode { /// Ignore the argument. @@ -63,16 +82,17 @@ pub enum PassMode { /// The `meta_attrs` value, if any, is for the metadata (vtable or length) of an unsized /// argument. (This is the only mode that supports unsized arguments.) /// - /// `on_stack` defines that the value should be passed at a fixed stack offset in accordance to - /// the ABI rather than passed using a pointer. This corresponds to the `byval` LLVM argument - /// attribute. The `byval` argument will use a byte array with the same size as the Rust type - /// (which ensures that padding is preserved and that we do not rely on LLVM's struct layout), - /// and will use the alignment specified in `attrs.pointee_align` (if `Some`) or the type's - /// alignment (if `None`). This means that the alignment will not always - /// match the Rust type's alignment; see documentation of `pass_by_stack_offset` for more info. + /// `address_space` specifies if the pointer is in a special address space or the default one. /// - /// `on_stack` cannot be true for unsized arguments, i.e., when `meta_attrs` is `Some`. - Indirect { attrs: ArgAttributes, meta_attrs: Option, on_stack: bool }, + /// `mode` can be a special way to pass an argument indirectly. + /// `OnStack` and `AmdgpuKernelArg` cannot be used for unsized arguments, i.e., when + /// `meta_attrs` is `Some`. + Indirect { + attrs: ArgAttributes, + meta_attrs: Option, + address_space: Option, + mode: IndirectMode, + }, } impl PassMode { @@ -89,13 +109,23 @@ impl PassMode { PassMode::Cast { cast: c2, pad_i32_count: pad2 }, ) => c1.eq_abi(c2) && pad1 == pad2, ( - PassMode::Indirect { attrs: a1, meta_attrs: None, on_stack: s1 }, - PassMode::Indirect { attrs: a2, meta_attrs: None, on_stack: s2 }, - ) => a1.eq_abi(a2) && s1 == s2, + PassMode::Indirect { attrs: a1, meta_attrs: None, address_space: as1, mode: m1 }, + PassMode::Indirect { attrs: a2, meta_attrs: None, address_space: as2, mode: m2 }, + ) => a1.eq_abi(a2) && as1 == as2 && m1 == m2, ( - PassMode::Indirect { attrs: a1, meta_attrs: Some(e1), on_stack: s1 }, - PassMode::Indirect { attrs: a2, meta_attrs: Some(e2), on_stack: s2 }, - ) => a1.eq_abi(a2) && e1.eq_abi(e2) && s1 == s2, + PassMode::Indirect { + attrs: a1, + meta_attrs: Some(e1), + address_space: as1, + mode: m1, + }, + PassMode::Indirect { + attrs: a2, + meta_attrs: Some(e2), + address_space: as2, + mode: m2, + }, + ) => a1.eq_abi(a2) && as1 == as2 && e1.eq_abi(e2) && m1 == m2, _ => false, } } @@ -424,7 +454,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> { let meta_attrs = layout.is_unsized().then_some(ArgAttributes::new()); - PassMode::Indirect { attrs, meta_attrs, on_stack: false } + PassMode::Indirect { attrs, meta_attrs, address_space: None, mode: IndirectMode::Pointer } } /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead. @@ -435,13 +465,31 @@ impl<'a, Ty> ArgAbi<'a, Ty> { PassMode::Direct(_) | PassMode::Pair(_, _) => { self.mode = Self::indirect_pass_mode(&self.layout); } - PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { + PassMode::Indirect { + attrs: _, + meta_attrs: _, + address_space: _, + mode: IndirectMode::Pointer, + } => { // already indirect } _ => panic!("Tried to make {:?} indirect", self.mode), } } + /// Pass this argument indirectly, by passing a (thin or wide) pointer to the argument instead. + /// This is valid for both sized and unsized arguments. + #[track_caller] + pub fn make_indirect_addrspace(&mut self, addrspace: AddressSpace) { + self.make_indirect(); + match self.mode { + PassMode::Indirect { ref mut address_space, .. } => { + *address_space = Some(addrspace); + } + _ => unreachable!(), + } + } + /// Same as `make_indirect`, but for arguments that are ignored. Only needed for ABIs that pass /// ZSTs indirectly. #[track_caller] @@ -450,7 +498,12 @@ impl<'a, Ty> ArgAbi<'a, Ty> { PassMode::Ignore => { self.mode = Self::indirect_pass_mode(&self.layout); } - PassMode::Indirect { attrs: _, meta_attrs: _, on_stack: false } => { + PassMode::Indirect { + attrs: _, + meta_attrs: _, + address_space: _, + mode: IndirectMode::Pointer, + } => { // already indirect } _ => panic!("Tried to make {:?} indirect (expected `PassMode::Ignore`)", self.mode), @@ -477,8 +530,8 @@ impl<'a, Ty> ArgAbi<'a, Ty> { assert!(!self.layout.is_unsized(), "used byval ABI for unsized layout"); self.make_indirect(); match self.mode { - PassMode::Indirect { ref mut attrs, meta_attrs: _, ref mut on_stack } => { - *on_stack = true; + PassMode::Indirect { ref mut attrs, meta_attrs: _, address_space: _, ref mut mode } => { + *mode = IndirectMode::OnStack; // Some platforms, like 32-bit x86, change the alignment of the type when passing // `byval`. Account for that. @@ -492,6 +545,22 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } } + /// Pass this argument indirectly. + /// This corresponds to the `byref` LLVM argument attribute. + /// + /// `address_space` specifies the address space of the passed pointer. + pub fn pass_amdgpu_kernel_arg(&mut self, addrspace: Option) { + assert!(!self.layout.is_unsized(), "used amdgpu kernel arg ABI for unsized layout"); + self.make_indirect(); + match self.mode { + PassMode::Indirect { attrs: _, meta_attrs: _, ref mut address_space, ref mut mode } => { + *mode = IndirectMode::AmdgpuKernelArg; + *address_space = addrspace; + } + _ => unreachable!(), + } + } + pub fn extend_integer_width_to(&mut self, bits: u64) { // Only integers have signedness if let BackendRepr::Scalar(scalar) = self.layout.backend_repr @@ -545,11 +614,17 @@ impl<'a, Ty> ArgAbi<'a, Ty> { } pub fn is_sized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ }) + matches!( + self.mode, + PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } + ) } pub fn is_unsized_indirect(&self) -> bool { - matches!(self.mode, PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ }) + matches!( + self.mode, + PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } + ) } pub fn is_ignore(&self) -> bool { @@ -851,7 +926,7 @@ impl<'a, Ty> FnAbi<'a, Ty> { // Compute `Aggregate` ABI. let is_indirect_not_on_stack = - matches!(arg.mode, PassMode::Indirect { on_stack: false, .. }); + matches!(arg.mode, PassMode::Indirect { mode: IndirectMode::Pointer, .. }); assert!(is_indirect_not_on_stack); let size = arg.layout.size; @@ -962,7 +1037,7 @@ mod size_asserts { use super::*; // tidy-alphabetical-start - static_assert_size!(ArgAbi<'_, usize>, 56); - static_assert_size!(FnAbi<'_, usize>, 80); + static_assert_size!(ArgAbi<'_, usize>, 64); + static_assert_size!(FnAbi<'_, usize>, 88); // tidy-alphabetical-end } diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index a1c59d885b7fc..3476f41e3bc75 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -200,12 +200,13 @@ pub(crate) fn fill_inregs<'a, Ty, C>( for arg in fn_abi.args.iter_mut() { let attrs = match arg.mode { - PassMode::Ignore | PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: _ } => { + PassMode::Ignore + | PassMode::Indirect { attrs: _, meta_attrs: None, address_space: _, mode: _ } => { continue; } PassMode::Direct(ref mut attrs) => attrs, PassMode::Pair(..) - | PassMode::Indirect { attrs: _, meta_attrs: Some(_), on_stack: _ } + | PassMode::Indirect { attrs: _, meta_attrs: Some(_), address_space: _, mode: _ } | PassMode::Cast { .. } => { unreachable!("x86 shouldn't be passing arguments by {:?}", arg.mode) } diff --git a/compiler/rustc_target/src/callconv/xtensa.rs b/compiler/rustc_target/src/callconv/xtensa.rs index 4dc9fad650636..49005adeb33c0 100644 --- a/compiler/rustc_target/src/callconv/xtensa.rs +++ b/compiler/rustc_target/src/callconv/xtensa.rs @@ -7,7 +7,7 @@ use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface}; -use crate::callconv::{ArgAbi, FnAbi, Reg, Uniform}; +use crate::callconv::{ArgAbi, FnAbi, IndirectMode, Reg, Uniform}; use crate::spec::HasTargetSpec; const NUM_ARG_GPRS: u64 = 6; @@ -29,8 +29,8 @@ where classify_arg_ty(cx, arg, &mut arg_gprs_left, true); // Ret args cannot be passed via stack, we lower to indirect and let the backend handle the invisible reference match arg.mode { - super::PassMode::Indirect { attrs: _, meta_attrs: _, ref mut on_stack } => { - *on_stack = false; + super::PassMode::Indirect { attrs: _, meta_attrs: _, address_space: _, ref mut mode } => { + *mode = IndirectMode::Pointer; } _ => {} } diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index bcba5839926db..a9d8aa23b1ea5 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -12,7 +12,9 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, InstanceKind, ShimKind, Ty, TyCtxt, Unnormalized}; use rustc_span::def_id::DefId; use rustc_span::{DUMMY_SP, bug}; -use rustc_target::callconv::{AbiMap, ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMode}; +use rustc_target::callconv::{ + AbiMap, ArgAbi, ArgAttribute, ArgAttributes, FnAbi, IndirectMode, PassMode, +}; use tracing::debug; pub(crate) fn provide(providers: &mut Providers) { @@ -444,15 +446,15 @@ fn fn_abi_sanity_check<'tcx>( // omitted entirely in the calling convention. assert!(arg.is_ignore()); } - if let PassMode::Indirect { on_stack, .. } = arg.mode + if let PassMode::Indirect { mode, .. } = arg.mode && spec_abi != ExternAbi::RustTail { - assert!(!on_stack, "rustic abi {spec_abi:?} shouldn't use on_stack"); + assert!(mode == IndirectMode::Pointer, "rust abi must use plain pointer mode"); } } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { assert_matches!( arg.mode, - PassMode::Indirect { on_stack: false, .. }, + PassMode::Indirect { mode: IndirectMode::Pointer, .. }, "the {spec_abi} ABI does not implement `#[rustc_pass_indirectly_in_non_rustic_abis]`" ); } @@ -506,9 +508,9 @@ fn fn_abi_sanity_check<'tcx>( // Indirect returns are arguments from an ABI perspective. fn_arg_attrs_sanity_check(attrs, false); } - PassMode::Indirect { meta_attrs: Some(meta_attrs), attrs, on_stack } => { + PassMode::Indirect { meta_attrs: Some(meta_attrs), attrs, address_space: _, mode } => { // With metadata. Must be unsized and not on the stack. - assert!(arg.layout.is_unsized() && !on_stack); + assert!(arg.layout.is_unsized() && *mode == IndirectMode::Pointer); // Also, must not be `extern` type. let tail = tcx.struct_tail_for_codegen(arg.layout.ty, cx.typing_env); if matches!(tail.kind(), ty::Foreign(..)) { diff --git a/tests/assembly-llvm/tail-call-indirect.rs b/tests/assembly-llvm/tail-call-indirect.rs index 2bc1743a9bafd..918283966b405 100644 --- a/tests/assembly-llvm/tail-call-indirect.rs +++ b/tests/assembly-llvm/tail-call-indirect.rs @@ -10,10 +10,10 @@ #![no_core] #![crate_type = "lib"] -// Test tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. +// Test tail calls with `PassMode::Indirect { mode: IndirectMode::Pointer, .. }` arguments. // -// Normally an indirect argument with `on_stack: false` would be passed as a pointer to the -// caller's stack frame. For tail calls, that would be unsound, because the caller's stack +// Normally an indirect argument with `mode: IndirectMode::Pointer` would be passed as a pointer to +// the caller's stack frame. For tail calls, that would be unsound, because the caller's stack // frame is overwritten by the callee's stack frame. // // The solution is to write the argument into the caller's argument place (stored somewhere further diff --git a/tests/ui-fulldeps/rustc_public/check_abi.rs b/tests/ui-fulldeps/rustc_public/check_abi.rs index ed616cc4d9bb0..92d6f28f8fd8c 100644 --- a/tests/ui-fulldeps/rustc_public/check_abi.rs +++ b/tests/ui-fulldeps/rustc_public/check_abi.rs @@ -15,8 +15,8 @@ extern crate rustc_middle; extern crate rustc_public; use rustc_public::abi::{ - ArgAbi, ArgExtension, CallConvention, FieldsShape, IntegerLength, PassMode, Primitive, Scalar, - ValueRepr, VariantsShape, + ArgAbi, ArgExtension, CallConvention, FieldsShape, IndirectMode, IntegerLength, PassMode, + Primitive, Scalar, ValueRepr, VariantsShape, }; use rustc_public::mir::MirVisitor; use rustc_public::mir::mono::Instance; @@ -127,14 +127,14 @@ fn check_primitive(abi: &ArgAbi) { /// Check the return value: `Result`. fn check_result(abi: &ArgAbi) { assert!(abi.ty.kind().is_enum()); - let PassMode::Indirect { ref attrs, ref meta_attrs, on_stack } = abi.mode else { + let PassMode::Indirect { ref attrs, ref meta_attrs, address_space: _, mode } = abi.mode else { panic!("Expected PassMode::Indirect for Result, got: {:?}", abi.mode); }; // Indirect arguments have a pointee alignment (the pointer must be aligned). assert!(attrs.pointee_align().is_some()); // Result is a sized type, so no metadata pointer. assert!(meta_attrs.is_none()); - assert!(!on_stack); + assert!(mode == IndirectMode::Pointer); let layout = abi.layout.shape(); assert!(layout.is_sized()); assert_matches!(layout.fields, FieldsShape::Arbitrary { .. }); diff --git a/tests/ui-fulldeps/rustc_public/check_abi_cast.rs b/tests/ui-fulldeps/rustc_public/check_abi_cast.rs index 0bd4ac684066e..a54abdd5deeaf 100644 --- a/tests/ui-fulldeps/rustc_public/check_abi_cast.rs +++ b/tests/ui-fulldeps/rustc_public/check_abi_cast.rs @@ -23,7 +23,7 @@ use std::convert::TryFrom; use std::io::Write; use std::ops::ControlFlow; -use rustc_public::abi::{CallConvention, PassMode, RegKind}; +use rustc_public::abi::{CallConvention, IndirectMode, PassMode, RegKind}; use rustc_public::mir::mono::Instance; use rustc_public::{CrateDef, ItemKind}; @@ -147,7 +147,7 @@ fn test_abi_cast() -> ControlFlow<()> { } // Fourth TwoWords has no registers left → Indirect (on stack) assert!( - matches!(&abi.args[3].mode, PassMode::Indirect { on_stack: true, .. }), + matches!(&abi.args[3].mode, PassMode::Indirect { mode: IndirectMode::OnStack, .. }), "Expected arg 3 to be Indirect on stack, got: {:?}", abi.args[3].mode ); diff --git a/tests/ui/abi/c-zst.powerpc-linux.stderr b/tests/ui/abi/c-zst.powerpc-linux.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.powerpc-linux.stderr +++ b/tests/ui/abi/c-zst.powerpc-linux.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/c-zst.s390x-linux.stderr b/tests/ui/abi/c-zst.s390x-linux.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.s390x-linux.stderr +++ b/tests/ui/abi/c-zst.s390x-linux.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/c-zst.sparc-linux.stderr b/tests/ui/abi/c-zst.sparc-linux.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.sparc-linux.stderr +++ b/tests/ui/abi/c-zst.sparc-linux.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/c-zst.sparc-none.stderr b/tests/ui/abi/c-zst.sparc-none.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.sparc-none.stderr +++ b/tests/ui/abi/c-zst.sparc-none.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/c-zst.sparc64-linux.stderr b/tests/ui/abi/c-zst.sparc64-linux.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.sparc64-linux.stderr +++ b/tests/ui/abi/c-zst.sparc64-linux.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr index 302ffe1efc8b8..e5cad2199491b 100644 --- a/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr +++ b/tests/ui/abi/c-zst.x86_64-pc-windows-gnu.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(pass_zst) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/debug.generic.stderr b/tests/ui/abi/debug.generic.stderr index 6242d93b09534..1793674fa462a 100644 --- a/tests/ui/abi/debug.generic.stderr +++ b/tests/ui/abi/debug.generic.stderr @@ -446,7 +446,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], @@ -519,7 +520,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/debug.loongarch64.stderr b/tests/ui/abi/debug.loongarch64.stderr index 176c68ecd4c7b..29ec7846101f1 100644 --- a/tests/ui/abi/debug.loongarch64.stderr +++ b/tests/ui/abi/debug.loongarch64.stderr @@ -446,7 +446,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], @@ -519,7 +520,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/debug.riscv64.stderr b/tests/ui/abi/debug.riscv64.stderr index 176c68ecd4c7b..29ec7846101f1 100644 --- a/tests/ui/abi/debug.riscv64.stderr +++ b/tests/ui/abi/debug.riscv64.stderr @@ -446,7 +446,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], @@ -519,7 +520,8 @@ error: ABIs are not compatible ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/abi/pass-indirectly-attr.rs b/tests/ui/abi/pass-indirectly-attr.rs index 54aafc716587c..bb90b8354ea91 100644 --- a/tests/ui/abi/pass-indirectly-attr.rs +++ b/tests/ui/abi/pass-indirectly-attr.rs @@ -20,7 +20,7 @@ pub struct Type(u8); pub extern "C" fn extern_c(_: Type) {} //~^ ERROR fn_abi_of(extern_c) = FnAbi { //~| ERROR mode: Indirect -//~| ERROR on_stack: false, +//~| ERROR mode: Pointer, //~| ERROR conv: C, #[rustc_abi(debug)] diff --git a/tests/ui/abi/pass-indirectly-attr.stderr b/tests/ui/abi/pass-indirectly-attr.stderr index efeec0d86982b..5821e6279bb85 100644 --- a/tests/ui/abi/pass-indirectly-attr.stderr +++ b/tests/ui/abi/pass-indirectly-attr.stderr @@ -48,7 +48,8 @@ error: fn_abi_of(extern_c) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr index 45edd7bc0e0ee..c9e77ac941901 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.aarch64.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(take_va_list) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/c-variadic/pass-by-value-abi.rs b/tests/ui/c-variadic/pass-by-value-abi.rs index bcca09e90438a..317840601c050 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.rs +++ b/tests/ui/c-variadic/pass-by-value-abi.rs @@ -27,9 +27,9 @@ use std::ffi::VaList; pub extern "C" fn take_va_list(_: VaList<'_>) {} //~^ ERROR fn_abi_of(take_va_list) = FnAbi { //[x86_64]~^^ ERROR mode: Indirect { -//[x86_64]~^^^ ERROR on_stack: false, +//[x86_64]~^^^ ERROR mode: Pointer, //[aarch64]~^^^^ ERROR mode: Indirect { -//[aarch64]~^^^^^ ERROR on_stack: false, +//[aarch64]~^^^^^ ERROR mode: Pointer, //[win]~^^^^^^ ERROR mode: Direct( #[cfg(all(target_arch = "x86_64", not(windows)))] @@ -37,11 +37,11 @@ pub extern "C" fn take_va_list(_: VaList<'_>) {} pub extern "sysv64" fn take_va_list_sysv64(_: VaList<'_>) {} //[x86_64]~^ ERROR fn_abi_of(take_va_list_sysv64) = FnAbi { //[x86_64]~^^ ERROR mode: Indirect { -//[x86_64]~^^^ ERROR on_stack: false, +//[x86_64]~^^^ ERROR mode: Pointer, #[cfg(all(target_arch = "x86_64", not(windows)))] #[rustc_abi(debug)] pub extern "win64" fn take_va_list_win64(_: VaList<'_>) {} //[x86_64]~^ ERROR: fn_abi_of(take_va_list_win64) = FnAbi { //[x86_64]~^^ ERROR mode: Indirect { -//[x86_64]~^^^ ERROR on_stack: false, +//[x86_64]~^^^ ERROR mode: Pointer, diff --git a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr index 1e203b93e66b3..04320a5312361 100644 --- a/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr +++ b/tests/ui/c-variadic/pass-by-value-abi.x86_64.stderr @@ -35,7 +35,8 @@ error: fn_abi_of(take_va_list) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], @@ -113,7 +114,8 @@ error: fn_abi_of(take_va_list_sysv64) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], @@ -193,7 +195,8 @@ error: fn_abi_of(take_va_list_win64) = FnAbi { ), }, meta_attrs: None, - on_stack: false, + address_space: None, + mode: Pointer, }, }, ], diff --git a/tests/ui/explicit-tail-calls/indirect.rs b/tests/ui/explicit-tail-calls/indirect.rs index b3e2613efad25..71107ef420c35 100644 --- a/tests/ui/explicit-tail-calls/indirect.rs +++ b/tests/ui/explicit-tail-calls/indirect.rs @@ -25,17 +25,17 @@ #![feature(explicit_tail_calls)] #![expect(incomplete_features)] -// Test tail calls with `PassMode::Indirect { on_stack: false, .. }` arguments. +// Test tail calls with `PassMode::Indirect { mode: IndirectMode::Pointer, .. }` arguments. // -// Normally an indirect argument with `on_stack: false` would be passed as a pointer to the -// caller's stack frame. For tail calls, that would be unsound, because the caller's stack +// Normally an indirect argument with `mode: IndirectMode::Pointer` would be passed as a pointer to +// the caller's stack frame. For tail calls, that would be unsound, because the caller's stack // frame is overwritten by the callee's stack frame. // // The solution is to write the argument into the caller's argument place (stored somewhere further // up the stack), and forward that place. // A struct big enough that it is not passed via registers, so that the rust calling convention uses -// `Indirect { on_stack: false, .. }`. +// `Indirect { mode: IndirectMode::Pointer, .. }`. #[repr(C)] #[derive(Default, Debug, Clone, Copy, PartialEq, Eq)] pub struct Big([u64; 4]); @@ -79,7 +79,7 @@ fn main() { assert_eq!(update_in_caller(Big::default()), 0 + 2 + 3 + 4); assert_eq!(swapper(u8::MIN, u8::MAX), (u8::MAX, u8::MIN)); - // i128 uses `PassMode::Indirect { on_stack: false, .. }` on x86_64 MSVC. + // i128 uses `PassMode::Indirect { mode: IndirectMode::Pointer, .. }` on x86_64 MSVC. assert_eq!(swapper(i128::MIN, i128::MAX), (i128::MAX, i128::MIN)); assert_eq!(swapper(Big([1; 4]), Big([2; 4])), (Big([2; 4]), Big([1; 4]))); From b8c747f548ba53a20b57484fc06b567a82aa227b Mon Sep 17 00:00:00 2001 From: Flakebi Date: Thu, 3 Sep 2026 09:21:39 +0200 Subject: [PATCH 0684/1309] Pre-commit amdgpu gpu-kernel ABI test --- tests/codegen-llvm/amdgpu-abi/struct-abi.rs | 133 ++++++++++++++++++++ 1 file changed, 133 insertions(+) create mode 100644 tests/codegen-llvm/amdgpu-abi/struct-abi.rs diff --git a/tests/codegen-llvm/amdgpu-abi/struct-abi.rs b/tests/codegen-llvm/amdgpu-abi/struct-abi.rs new file mode 100644 index 0000000000000..bf51cbfa7f7a0 --- /dev/null +++ b/tests/codegen-llvm/amdgpu-abi/struct-abi.rs @@ -0,0 +1,133 @@ +//@ add-minicore +//@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900 -Copt-level=3 +//@ needs-llvm-components: amdgpu +#![feature(no_core, abi_gpu_kernel)] +#![no_core] +#![allow(improper_gpu_kernel_arg)] + +extern crate minicore; +use minicore::num::Complex; + +// Tests from llvm-project/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl + +#[repr(C)] +pub struct SingleElementStructArg { + i: i32, +} + +#[repr(C)] +pub struct NestedSingleElementStructArg { + i: SingleElementStructArg, +} + +#[repr(C)] +pub struct StructArg { + i1: i32, + f: f32, + i2: i32, +} + +#[repr(C)] +pub struct StructPaddingArg { + i1: i8, + f: i64, +} + +#[repr(C)] +pub struct StructOfArraysArg { + i1: [i32; 2], + f1: f32, + i2: [i32; 4], + f2: [f32; 3], + i3: i32, +} + +#[repr(C)] +pub struct StructOfStructsArg { + i1: i32, + f1: f32, + s1: StructArg, + i2: i32, +} + +#[repr(C)] +pub union U { + b1: i32, + b2: f32, +} + +#[repr(C)] +pub struct SingleArrayElementStructArg { + i: [i32; 4], +} + +#[repr(C)] +pub struct SingleStructElementStructArgInner { + i: i32, + b: i64, +} + +#[repr(C)] +pub struct SingleStructElementStructArg { + s: SingleStructElementStructArgInner, +} + +#[repr(C)] +pub struct DifferentSizeTypePair { + l: i64, + i: i32, +} + +// CHECK: define amdgpu_kernel void @kernel_single_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_single_element_struct_arg(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_nested_single_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_nested_single_element_struct_arg( + _: NestedSingleElementStructArg, +) { +} + +// CHECK: define amdgpu_kernel void @kernel_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(12) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_struct_arg(_: StructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_struct_padding_arg(i8 noundef {{%.+}}, i64 noundef {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_struct_padding_arg(_: StructPaddingArg) {} + +// CHECK: define amdgpu_kernel void @kernel_struct_of_arrays_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(44) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_struct_of_arrays_arg(_: StructOfArraysArg) {} + +// CHECK: define amdgpu_kernel void @kernel_struct_of_structs_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(24) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_struct_of_structs_arg(_: StructOfStructsArg) {} + +// CHECK: define amdgpu_kernel void @test_kernel_union_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn test_kernel_union_arg(_: U) {} + +// CHECK: define amdgpu_kernel void @kernel_single_array_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(16) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_single_array_element_struct_arg(_: SingleArrayElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_single_struct_element_struct_arg(i32 noundef {{%.+}}, i64 noundef {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_single_struct_element_struct_arg( + _: SingleStructElementStructArg, +) { +} + +// CHECK: define amdgpu_kernel void @kernel_different_size_type_pair_arg(i64 noundef {{%.+}}, i32 noundef {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_different_size_type_pair_arg(_: DifferentSizeTypePair) {} + +// CHECK: define amdgpu_kernel void @kernel_complex(float noundef {{%.+}}, float noundef {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_complex(_: Complex) {} + +// CHECK: define amdgpu_kernel void @kernel_slice(ptr noalias nofree noundef nonnull readonly align 4 captures(none) {{%.+}}, i64 noundef range(i64 0, 2305843009213693952) {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_slice(_: &[u32]) {} From be988e9f8563e138c777cd4530594972a81af9b9 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 15 Sep 2026 10:33:14 +0200 Subject: [PATCH 0685/1309] Properly implement the gpu-kernel ABI for amdgpu MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add support to pass structs, arrays and vectors to amdgpu kernels. Scalars and vectors are taken by value, aggregates are passed by byref pointers. Structs containing a single scalar/vector are handled like a scalar. Judging from clang tests, nvptx seems to do somewhat the same, just using byval instead of byref: https://github.com/llvm/llvm-project/blob/3a8affeef4da19d39191aac316e189eca3214a8c/clang/test/CodeGenCUDA/kernel-args.cu I tested a couple of the lit test signatures on real hardware and it seems to work fine. Given the relatively simple implementation, I hope this amount of testing is enough (the C calling convention seems like a worse fit for Rust’s current ABI code, it’s still giving me headaches). --- compiler/rustc_abi/src/lib.rs | 4 + compiler/rustc_target/src/callconv/amdgpu.rs | 82 ++++++++++++++---- tests/codegen-llvm/amdgpu-abi/struct-abi.rs | 88 ++++++++++++++++---- 3 files changed, 139 insertions(+), 35 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 9c11405e9bb58..56cfbf138af00 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -1778,6 +1778,10 @@ pub struct AddressSpace(pub u32); impl AddressSpace { /// LLVM's `0` address space. pub const ZERO: Self = AddressSpace(0); + /// The address space for constant memory on nvptx and amdgpu. + /// This address space is used e.g. for kernel arguments that are constant throughout the + /// execution. + pub const GPU_CONSTANT: Self = AddressSpace(4); /// The address space for workgroup memory on nvptx and amdgpu. /// See e.g. the `gpu_launch_sized_workgroup_mem` intrinsic for details. pub const GPU_WORKGROUP: Self = AddressSpace(3); diff --git a/compiler/rustc_target/src/callconv/amdgpu.rs b/compiler/rustc_target/src/callconv/amdgpu.rs index 98ab3ce8eb746..7a9eeaba19c96 100644 --- a/compiler/rustc_target/src/callconv/amdgpu.rs +++ b/compiler/rustc_target/src/callconv/amdgpu.rs @@ -1,25 +1,60 @@ -use rustc_abi::{HasDataLayout, TyAbiInterface}; +use rustc_abi::{ + AddressSpace, BackendRepr, CanonAbi, HasDataLayout, Reg, RegKind, TyAbiInterface, TyAndLayout, +}; -use crate::callconv::{ArgAbi, FnAbi}; +use crate::callconv::{FnAbi, Uniform}; -fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>) -where - Ty: TyAbiInterface<'a, C> + Copy, - C: HasDataLayout, -{ - ret.extend_integer_width_to(32); -} +// For reference, see llvm-project/clang/lib/CodeGen/Targets/AMDGPU.cpp -fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +/// If the given type is a (potentially nested) struct containing a single scalar, return +/// a `Uniform` for the contained, single element. +fn single_element_struct_to_reg<'a, Ty, C>(cx: &C, ty: TyAndLayout<'a, Ty>) -> Option where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { - arg.make_indirect(); - return; + assert!(ty.is_aggregate(), "Only handles aggregate types"); + if ty.layout.fields.count() != 1 { + return None; + } + let field = ty.field(cx, 0); + match field.backend_repr { + BackendRepr::SimdScalableVector { .. } => panic!("scalable vectors are unsupported"), + BackendRepr::Scalar(_) => { + // Check that the size is the same as the size for ty, so no extra padding + let size = field.layout.size.bytes(); + if ty.layout.size.bytes() != size { + return None; + } + + // clang passes the inner type directly, we emulate it with fitting integer types + match size { + 1 => Some(Uniform::new(Reg::i8(), field.layout.size)), + 2 => Some(Uniform::new(Reg::i16(), field.layout.size)), + 4 => Some(Uniform::new(Reg::i32(), field.layout.size)), + 8 => Some(Uniform::new(Reg::i64(), field.layout.size)), + 16 => Some(Uniform::new(Reg::i128(), field.layout.size)), + s => panic!("Unhandled scalar of size {s} in amdgpu gpu-kernel ABI"), + } + } + BackendRepr::SimdVector { element, .. } => { + // Check that the size is the same as the size for ty, so no extra padding + let size = field.layout.size.bytes(); + if ty.layout.size.bytes() != size { + return None; + } + + // clang passes the inner type directly, we emulate it with a vector of the same type. + // The size is rounded up to the size of the complete type (including alignment). + let reg = Reg { + kind: RegKind::Vector { hint_vector_elem: element.primitive() }, + size: field.layout.size, + }; + Some(Uniform::new(reg, field.layout.size)) + } + BackendRepr::Memory { .. } => single_element_struct_to_reg(cx, field), + BackendRepr::ScalarPair { .. } => None, } - arg.extend_integer_width_to(32); } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) @@ -27,14 +62,25 @@ where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - if !fn_abi.ret.is_ignore() { - classify_ret(cx, &mut fn_abi.ret); - } + // Kernels cannot return values, so do not handle return types + // Try to fill first registers with values and pass by_ref pointers for later indirect arguments for arg in fn_abi.args.iter_mut() { if arg.is_ignore() { continue; } - classify_arg(cx, arg); + if fn_abi.conv == CanonAbi::GpuKernel { + if arg.layout.is_aggregate() { + if let Some(uniform) = single_element_struct_to_reg(cx, arg.layout) { + // Single element structs are passed directly as the inner type + arg.cast_to(uniform); + } else { + // All other aggregates are passed as by_ref pointer in the constant address space + arg.pass_amdgpu_kernel_arg(Some(AddressSpace::GPU_CONSTANT)); + } + } + } else { + // FIXME: C ABI is not yet implemented + } } } diff --git a/tests/codegen-llvm/amdgpu-abi/struct-abi.rs b/tests/codegen-llvm/amdgpu-abi/struct-abi.rs index bf51cbfa7f7a0..bc83f6510a6fe 100644 --- a/tests/codegen-llvm/amdgpu-abi/struct-abi.rs +++ b/tests/codegen-llvm/amdgpu-abi/struct-abi.rs @@ -1,7 +1,7 @@ //@ add-minicore //@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900 -Copt-level=3 //@ needs-llvm-components: amdgpu -#![feature(no_core, abi_gpu_kernel)] +#![feature(no_core, abi_gpu_kernel, repr_simd)] #![no_core] #![allow(improper_gpu_kernel_arg)] @@ -10,14 +10,32 @@ use minicore::num::Complex; // Tests from llvm-project/clang/test/CodeGenOpenCL/amdgpu-abi-struct-coerce.cl +#[repr(simd)] +pub struct I8X2([i8; 2]); + +#[repr(simd)] +pub struct I16X2([i16; 2]); + +#[repr(simd)] +pub struct I16X3([i16; 3]); + +#[repr(simd)] +pub struct I16X4([i16; 4]); + +#[repr(simd)] +pub struct I32X3([i32; 3]); + +#[repr(simd)] +pub struct I32X4([i32; 4]); + #[repr(C)] -pub struct SingleElementStructArg { - i: i32, +pub struct SingleElementStructArg { + i: T, } #[repr(C)] pub struct NestedSingleElementStructArg { - i: SingleElementStructArg, + i: SingleElementStructArg, } #[repr(C)] @@ -78,56 +96,92 @@ pub struct DifferentSizeTypePair { i: i32, } -// CHECK: define amdgpu_kernel void @kernel_single_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_single_element_struct_arg(i32 %0) #[no_mangle] -pub extern "gpu-kernel" fn kernel_single_element_struct_arg(_: SingleElementStructArg) {} +pub extern "gpu-kernel" fn kernel_single_element_struct_arg(_: SingleElementStructArg) {} -// CHECK: define amdgpu_kernel void @kernel_nested_single_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_nested_single_element_struct_arg(i32 %0) #[no_mangle] pub extern "gpu-kernel" fn kernel_nested_single_element_struct_arg( _: NestedSingleElementStructArg, ) { } -// CHECK: define amdgpu_kernel void @kernel_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(12) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_struct_arg(ptr addrspace(4) noalias nofree noundef readnone byref([12 x i8]) align 4 captures(none) dereferenceable(12) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_struct_arg(_: StructArg) {} -// CHECK: define amdgpu_kernel void @kernel_struct_padding_arg(i8 noundef {{%.+}}, i64 noundef {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_struct_padding_arg(ptr addrspace(4) noalias nofree noundef readnone byref([16 x i8]) align 8 captures(none) dereferenceable(16) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_struct_padding_arg(_: StructPaddingArg) {} -// CHECK: define amdgpu_kernel void @kernel_struct_of_arrays_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(44) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_struct_of_arrays_arg(ptr addrspace(4) noalias nofree noundef readnone byref([44 x i8]) align 4 captures(none) dereferenceable(44) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_struct_of_arrays_arg(_: StructOfArraysArg) {} -// CHECK: define amdgpu_kernel void @kernel_struct_of_structs_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(24) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_struct_of_structs_arg(ptr addrspace(4) noalias nofree noundef readnone byref([24 x i8]) align 4 captures(none) dereferenceable(24) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_struct_of_structs_arg(_: StructOfStructsArg) {} -// CHECK: define amdgpu_kernel void @test_kernel_union_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(4) {{%.+}}) +// CHECK: define amdgpu_kernel void @test_kernel_union_arg(ptr addrspace(4) noalias nofree noundef readnone byref([4 x i8]) align 4 captures(none) dereferenceable(4) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn test_kernel_union_arg(_: U) {} -// CHECK: define amdgpu_kernel void @kernel_single_array_element_struct_arg(ptr noalias nofree noundef readnone align 4 captures(none) dead_on_return dereferenceable(16) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_single_array_element_struct_arg(ptr addrspace(4) noalias nofree noundef readnone byref([16 x i8]) align 4 captures(none) dereferenceable(16) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_single_array_element_struct_arg(_: SingleArrayElementStructArg) {} -// CHECK: define amdgpu_kernel void @kernel_single_struct_element_struct_arg(i32 noundef {{%.+}}, i64 noundef {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_single_struct_element_struct_arg(ptr addrspace(4) noalias nofree noundef readnone byref([16 x i8]) align 8 captures(none) dereferenceable(16) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_single_struct_element_struct_arg( _: SingleStructElementStructArg, ) { } -// CHECK: define amdgpu_kernel void @kernel_different_size_type_pair_arg(i64 noundef {{%.+}}, i32 noundef {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_different_size_type_pair_arg(ptr addrspace(4) noalias nofree noundef readnone byref([16 x i8]) align 8 captures(none) dereferenceable(16) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_different_size_type_pair_arg(_: DifferentSizeTypePair) {} -// CHECK: define amdgpu_kernel void @kernel_complex(float noundef {{%.+}}, float noundef {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_complex(ptr addrspace(4) noalias nofree noundef readnone byref([8 x i8]) align 4 captures(none) dereferenceable(8) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_complex(_: Complex) {} -// CHECK: define amdgpu_kernel void @kernel_slice(ptr noalias nofree noundef nonnull readonly align 4 captures(none) {{%.+}}, i64 noundef range(i64 0, 2305843009213693952) {{%.+}}) +// CHECK: define amdgpu_kernel void @kernel_slice(ptr addrspace(4) noalias nofree noundef readnone byref([16 x i8]) align 8 captures(none) dereferenceable(16) {{%.+}}) #[no_mangle] pub extern "gpu-kernel" fn kernel_slice(_: &[u32]) {} + +// CHECK: define amdgpu_kernel void @kernel_i64(i64 noundef {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i64(_: i64) {} + +// CHECK: define amdgpu_kernel void @kernel_i64_struct(i64 {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i64_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i128_struct(i128 {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i128_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i8x2_struct(<2 x i8> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i8x2_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i16x2_struct(<2 x i16> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i16x2_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i16x3_struct(<4 x i16> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i16x3_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i16x4_struct(<4 x i16> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i16x4_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i32x3_struct(<4 x i32> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i32x3_struct(_: SingleElementStructArg) {} + +// CHECK: define amdgpu_kernel void @kernel_i32x4_struct(<4 x i32> {{%.+}}) +#[no_mangle] +pub extern "gpu-kernel" fn kernel_i32x4_struct(_: SingleElementStructArg) {} From dc249dca94155267c02a52a6dbacc92f1ffd8331 Mon Sep 17 00:00:00 2001 From: Flakebi Date: Tue, 1 Sep 2026 09:40:37 +0200 Subject: [PATCH 0686/1309] Add address_space and byref to abi PassMode::Indirect MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both will be used by the amdgpu target to implement the `gpu-kernel` ABI. `address_space` specifies the address space of an indirect argument. `AmdgpuKernelArg` translates to LLVM’s byref, which is similar to on_stack/byval, however, there is no extra copy made, the pointer may not point to the stack but can point to some other address space, and the passed argument should not be modified. byval and byref are mutually exclusive, so change on_stack to an enum with the new states, Pointer (none), OnStack and AmdgpuKernelArg. --- src/abi.rs | 33 ++++++++++++++++++++++++++++----- 1 file changed, 28 insertions(+), 5 deletions(-) diff --git a/src/abi.rs b/src/abi.rs index 63eaf52ce9f01..5b88cebb4f174 100644 --- a/src/abi.rs +++ b/src/abi.rs @@ -11,7 +11,7 @@ use rustc_middle::ty::layout::LayoutOf; #[cfg(feature = "master")] use rustc_session::{Session, config}; use rustc_span::bug; -use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, PassMode}; +use rustc_target::callconv::{ArgAttributes, CastTarget, FnAbi, IndirectMode, PassMode}; #[cfg(feature = "master")] use rustc_target::spec::Arch; @@ -189,7 +189,12 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { let ty = cast.gcc_type(cx); apply_attrs(ty, &cast.attrs, argument_tys.len()) } - PassMode::Indirect { attrs: _, meta_attrs: None, on_stack: true } => { + PassMode::Indirect { + attrs: _, + meta_attrs: None, + address_space: _, + mode: IndirectMode::OnStack, + } => { let x86_interrupt_first_arg = { #[cfg(feature = "master")] { @@ -216,14 +221,32 @@ impl<'gcc, 'tcx> FnAbiGccExt<'gcc, 'tcx> for FnAbi<'tcx, Ty<'tcx>> { arg.layout.gcc_type(cx) } } + PassMode::Indirect { + attrs: _, + meta_attrs: None, + address_space: _, + mode: IndirectMode::AmdgpuKernelArg, + } => { + unimplemented!("unsupported amdgpu kernel argument") + } PassMode::Direct(attrs) => { apply_attrs(arg.layout.immediate_gcc_type(cx), &attrs, argument_tys.len()) } - PassMode::Indirect { attrs, meta_attrs: None, on_stack: false } => { + PassMode::Indirect { + attrs, + meta_attrs: None, + address_space: _, + mode: IndirectMode::Pointer, + } => { apply_attrs(cx.type_ptr_to(arg.layout.gcc_type(cx)), &attrs, argument_tys.len()) } - PassMode::Indirect { attrs, meta_attrs: Some(meta_attrs), on_stack } => { - assert!(!on_stack); + PassMode::Indirect { + attrs, + meta_attrs: Some(meta_attrs), + address_space: _, + mode, + } => { + assert!(mode == IndirectMode::Pointer); // Construct the type of a (wide) pointer to `ty`, and pass its two fields. // Any two ABI-compatible unsized types have the same metadata type and // moreover the same metadata value leads to the same dynamic size and From 4cf035f6814d2c1f482487e9d671b4fd56a2c38f Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:00:52 +0200 Subject: [PATCH 0687/1309] Checking that an empty BTreeMap drop compiles down to only a `ret void`, and that function only match drop_btree exactly. As the previous dealloc also passed on old code so didn't catch the regression --- tests/codegen-llvm/btree-empty-drop.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/codegen-llvm/btree-empty-drop.rs b/tests/codegen-llvm/btree-empty-drop.rs index 60e3c3b0c9a70..f1aaf52e95729 100644 --- a/tests/codegen-llvm/btree-empty-drop.rs +++ b/tests/codegen-llvm/btree-empty-drop.rs @@ -6,9 +6,9 @@ use std::collections::BTreeMap; -// CHECK-LABEL: @drop_btree -// CHECK-NOT: dealloc -// CHECK: ret void +// CHECK-LABEL: @drop_btree( +// CHECK-NEXT: {{.*}}: +// CHECK-NEXT: ret void #[no_mangle] pub fn drop_btree() { let _ = BTreeMap::<(), ()>::new(); From 93bfeed513279837781482ce88707cb6a18ef8c1 Mon Sep 17 00:00:00 2001 From: Yukang Date: Tue, 22 Sep 2026 00:18:16 +0800 Subject: [PATCH 0688/1309] Add regression tests for Option predicate suggestion precedence --- tests/ui/suggestions/option-to-bool.rs | 29 ++++++++++++++- tests/ui/suggestions/option-to-bool.stderr | 43 +++++++++++++++++++++- 2 files changed, 69 insertions(+), 3 deletions(-) diff --git a/tests/ui/suggestions/option-to-bool.rs b/tests/ui/suggestions/option-to-bool.rs index bbc5d1d71cb72..b36c28c06ef9d 100644 --- a/tests/ui/suggestions/option-to-bool.rs +++ b/tests/ui/suggestions/option-to-bool.rs @@ -1,7 +1,34 @@ +// An `is_some()` suggestion must apply to the whole expression, preserving its precedence. + fn foo(x: Option) { if true && x {} //~^ ERROR mismatched types //~| HELP use `Option::is_some` to test if the `Option` has a value + + let reference = &x; + if *reference {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value + + if &x {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value + + if Value + Value {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value } -fn main() {} +struct Value; + +impl std::ops::Add for Value { + type Output = Option; + + fn add(self, _: Self) -> Self::Output { + Some(1) + } +} + +fn main() { + foo(Some(1)); +} diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr index ab97eae6c5c55..2ee282670d794 100644 --- a/tests/ui/suggestions/option-to-bool.stderr +++ b/tests/ui/suggestions/option-to-bool.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/option-to-bool.rs:2:16 + --> $DIR/option-to-bool.rs:4:16 | LL | if true && x {} | ---- ^ expected `bool`, found `Option` @@ -13,6 +13,45 @@ help: use `Option::is_some` to test if the `Option` has a value LL | if true && x.is_some() {} | ++++++++++ -error: aborting due to 1 previous error +error[E0308]: mismatched types + --> $DIR/option-to-bool.rs:9:8 + | +LL | if *reference {} + | ^^^^^^^^^^ expected `bool`, found `Option` + | + = note: expected type `bool` + found enum `Option` +help: use `Option::is_some` to test if the `Option` has a value + | +LL | if *reference.is_some() {} + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/option-to-bool.rs:13:8 + | +LL | if &x {} + | ^^ expected `bool`, found `&Option` + | + = note: expected type `bool` + found reference `&Option` +help: use `Option::is_some` to test if the `Option` has a value + | +LL | if &x.is_some() {} + | ++++++++++ + +error[E0308]: mismatched types + --> $DIR/option-to-bool.rs:17:8 + | +LL | if Value + Value {} + | ^^^^^^^^^^^^^ expected `bool`, found `Option` + | + = note: expected type `bool` + found enum `Option` +help: use `Option::is_some` to test if the `Option` has a value + | +LL | if Value + Value.is_some() {} + | ++++++++++ + +error: aborting due to 4 previous errors For more information about this error, try `rustc --explain E0308`. From 452a7cac6e79b4bff25906e2e45bb820d46f793b Mon Sep 17 00:00:00 2001 From: dianne Date: Tue, 22 Sep 2026 23:53:16 -0700 Subject: [PATCH 0689/1309] make `RustaceansAreAwesome` satisfy trait bounds --- .../src/traits/dyn_compatibility.rs | 9 ++++ ...tchability-placeholder-satisfies-bounds.rs | 37 ++++++++++++++ .../ice-generics-of-crate-root-152335.rs | 2 + .../ice-generics-of-crate-root-152335.stderr | 50 +++++++++++++++---- .../unhandled-crate-mod-issue-144888.rs | 2 + .../unhandled-crate-mod-issue-144888.stderr | 46 ++++++++++++++--- 6 files changed, 129 insertions(+), 17 deletions(-) create mode 100644 tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e964c09420b0e..7f05f7e04aadf 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -749,6 +749,15 @@ fn receiver_is_dispatchable<'tcx>( let trait_predicate = ty::TraitRef::new_from_args(tcx, trait_def_id, args); clauses.push(trait_predicate.upcast(tcx)); + // U satisfies `Trait`'s where-bounds. + clauses.extend( + tcx.clauses_of(trait_def_id) + .instantiate(tcx, args) + .clauses + .into_iter() + .map(Unnormalized::skip_norm_wip), + ); + let meta_sized_predicate = { let meta_sized_did = tcx.require_lang_item(LangItem::MetaSized, DUMMY_SP); ty::TraitRef::new(tcx, meta_sized_did, [unsized_self_ty]) diff --git a/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs b/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs new file mode 100644 index 0000000000000..421b9a512c1e4 --- /dev/null +++ b/tests/ui/dyn-compatibility/dispatchability-placeholder-satisfies-bounds.rs @@ -0,0 +1,37 @@ +//! Regression tests for . When checking whether +//! method receivers for a trait `Trait` are dynamically dispatchable, we use a placeholder type in +//! place of `dyn Trait` to avoid a cycle (as that would require determining whether `Trait` is dyn- +//! compatible). This placeholder must satisfy `Trait`'s where-bounds to avoid errors in param- +//! environment normalization. +//@ check-pass + +// Test 1 + +use std::ops::Deref; + +trait SignatureToFnPtr { + type Ptr; +} + +trait DerefsToFn +where + (Args, Self::Output): SignatureToFnPtr, + Self: Deref::Ptr>, +{ + type Output; + fn method(&self); +} + +// Test 2 + +trait Associator { + type Point; +} + +trait Marker {} + +trait Trait + ?Sized>: Marker { + fn method(&self); +} + +fn main() {} diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs index cfafca68bfd2f..188f63fa94bab 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.rs @@ -26,6 +26,8 @@ where //~| ERROR the size for values of type `Self` cannot be known //~| ERROR type mismatch resolving //~| ERROR the size for values of type `Self` cannot be known + //~| ERROR type mismatch resolving + //~| ERROR the size for values of type `RustaceansAreAwesome` cannot be known } trait Mirror { diff --git a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr index b8796f673f4a5..06fd8bced4af1 100644 --- a/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr +++ b/tests/ui/dyn-compatibility/ice-generics-of-crate-root-152335.stderr @@ -5,11 +5,29 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^ not found in this scope error[E0601]: `main` function not found in crate `ice_generics_of_crate_root_152335` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:57 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:57 | LL | impl> Mirror for T {} | ^ consider adding a `main` function to `$DIR/ice-generics-of-crate-root-152335.rs` +error[E0271]: type mismatch resolving `>::Assoc == RustaceansAreAwesome` + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 + | +LL | fn transmute(&self, t: T) -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected type parameter `RustaceansAreAwesome`, found type parameter `T` + | + = note: expected type parameter `RustaceansAreAwesome` + found type parameter `T` + = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound + = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 + | +LL | impl> Mirror for T {} + | --------- ^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + error[E0271]: type mismatch resolving `>::Assoc == Self` --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | @@ -21,13 +39,27 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ | | | unsatisfied trait bound introduced here +error[E0277]: the size for values of type `RustaceansAreAwesome` cannot be known at compilation time + --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 + | +LL | fn transmute(&self, t: T) -> ::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 + | +LL | impl> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/ice-generics-of-crate-root-152335.rs:23:5 | @@ -35,7 +67,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -69,7 +101,7 @@ LL | trait Foo: Super = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -83,7 +115,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -95,7 +127,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:1 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:1 | LL | type Assoc: ?Sized; | ------------------ `Assoc` from trait @@ -120,7 +152,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; = note: a type parameter was expected, but a different one was found; you might be missing a type parameter or trait bound = note: for more information, visit https://doc.rust-lang.org/book/ch10-02-traits.html#traits-as-parameters note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | --------- ^^^^^^ ^ @@ -134,7 +166,7 @@ LL | fn transmute(&self, t: T) -> ::Assoc; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/ice-generics-of-crate-root-152335.rs:34:42 + --> $DIR/ice-generics-of-crate-root-152335.rs:36:42 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -145,7 +177,7 @@ help: consider further restricting `Self` LL | fn transmute(&self, t: T) -> ::Assoc where Self: Sized; | +++++++++++++++++ -error: aborting due to 10 previous errors +error: aborting due to 12 previous errors Some errors have detailed explanations: E0038, E0046, E0271, E0277, E0405, E0601. For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs index 8c9085ee80b35..41f233398d83b 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.rs +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.rs @@ -18,6 +18,8 @@ where //~| ERROR the size for values of type `Self` cannot be known at compilation time //~| ERROR type mismatch resolving //~| ERROR the size for values of type `Self` cannot be known at compilation time + //~| ERROR type mismatch resolving + //~| ERROR the size for values of type `RustaceansAreAwesome` cannot be known at compilation time } trait Mirror { diff --git a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr index 3208945a5b732..4cc5b41588efa 100644 --- a/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr +++ b/tests/ui/traits/unhandled-crate-mod-issue-144888.stderr @@ -1,3 +1,19 @@ +error[E0271]: type mismatch resolving `::Assoc == ()` + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 + | +LL | fn transmute(&self) {} + | ^^^^^^^^^^^^^^^^^^^ expected `()`, found type parameter `T` + | + = note: expected unit type `()` + found type parameter `T` +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 + | +LL | impl> Mirror for T {} + | ---------- ^^^^^^ ^ + | | + | unsatisfied trait bound introduced here + error[E0271]: type mismatch resolving `::Assoc == ()` --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | @@ -7,13 +23,27 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ | | | unsatisfied trait bound introduced here +error[E0277]: the size for values of type `RustaceansAreAwesome` cannot be known at compilation time + --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 + | +LL | fn transmute(&self) {} + | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required for `RustaceansAreAwesome` to implement `Mirror` + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 + | +LL | impl> Mirror for T {} + | - ^^^^^^ ^ + | | + | unsatisfied trait bound implicitly introduced here + error[E0277]: the size for values of type `Self` cannot be known at compilation time --> $DIR/unhandled-crate-mod-issue-144888.rs:16:5 | @@ -21,7 +51,7 @@ LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -37,7 +67,7 @@ LL | trait Foo: Super = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -51,7 +81,7 @@ LL | trait Foo: Super | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -63,7 +93,7 @@ LL | trait Foo: Super + Sized | +++++++ error[E0046]: not all trait items implemented, missing: `Assoc` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:1 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:1 | LL | type Assoc; | ---------- `Assoc` from trait @@ -83,7 +113,7 @@ LL | fn transmute(&self) {} = note: expected unit type `()` found type parameter `T` note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | ---------- ^^^^^^ ^ @@ -97,7 +127,7 @@ LL | fn transmute(&self) {} | ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required for `Self` to implement `Mirror` - --> $DIR/unhandled-crate-mod-issue-144888.rs:27:28 + --> $DIR/unhandled-crate-mod-issue-144888.rs:29:28 | LL | impl> Mirror for T {} | - ^^^^^^ ^ @@ -108,7 +138,7 @@ help: consider further restricting `Self` LL | fn transmute(&self) where Self: Sized {} | +++++++++++++++++ -error: aborting due to 7 previous errors +error: aborting due to 9 previous errors Some errors have detailed explanations: E0046, E0271, E0277. For more information about an error, try `rustc --explain E0046`. From b267be921e3f95b96c7eafd6e47028822afe96e2 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 23 Sep 2026 12:03:41 +0200 Subject: [PATCH 0690/1309] Remove `suggestion_for_allocator_api` --- compiler/rustc_middle/src/middle/stability.rs | 62 +++---------------- compiler/rustc_resolve/src/macros.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - 3 files changed, 7 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_middle/src/middle/stability.rs b/compiler/rustc_middle/src/middle/stability.rs index 8213646b4625d..0235d5bb17224 100644 --- a/compiler/rustc_middle/src/middle/stability.rs +++ b/compiler/rustc_middle/src/middle/stability.rs @@ -7,7 +7,7 @@ use rustc_ast::NodeId; use rustc_attr_ir::{ ConstStability, DefaultBodyStability, DeprecatedSince, Deprecation, Stability, StabilityLevel, }; -use rustc_errors::{Applicability, Diag, Diagnostic, LintBuffer, msg}; +use rustc_errors::{Diag, Diagnostic, LintBuffer, msg}; use rustc_feature::GateIssue; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, HirId}; @@ -62,7 +62,6 @@ pub fn report_unstable( feature: Symbol, reason: Option, issue: Option>, - suggestion: Option<(Span, String, String, Applicability)>, span: Span, kind: UnstableKind, ) { @@ -77,9 +76,6 @@ pub fn report_unstable( }; let mut err = feature_err_issue(sess, feature, span, GateIssue::Library(issue), msg); - if let Some((inner_types, msg, sugg, applicability)) = suggestion { - err.span_suggestion(inner_types, msg, sugg, applicability); - } if let UnstableKind::Const(kw) = kind { err.span_label(kw, "trait is not stable as const yet"); } @@ -260,42 +256,11 @@ pub enum EvalResult { Allow, /// We cannot use the item because it is unstable and we did not provide the /// corresponding feature gate. - Deny { - feature: Symbol, - reason: Option, - issue: Option>, - suggestion: Option<(Span, String, String, Applicability)>, - }, + Deny { feature: Symbol, reason: Option, issue: Option> }, /// The item does not have the `#[stable]` or `#[unstable]` marker assigned. Unmarked, } -// See issue #83250. -fn suggestion_for_allocator_api( - tcx: TyCtxt<'_>, - def_id: DefId, - span: Span, - feature: Symbol, -) -> Option<(Span, String, String, Applicability)> { - if feature == sym::allocator_api { - if let Some(trait_) = tcx.opt_parent(def_id) { - if tcx.is_diagnostic_item(sym::Vec, trait_) { - let sm = tcx.sess.psess.source_map(); - let inner_types = sm.span_extend_to_prev_char(span, '<', true); - if let Ok(snippet) = sm.span_to_snippet(inner_types) { - return Some(( - inner_types, - "consider wrapping the inner types in tuple".to_string(), - format!("({snippet})"), - Applicability::MaybeIncorrect, - )); - } - } - } - } - None -} - /// An override option for eval_stability. pub enum AllowUnstable { /// Don't emit an unstable error for the item @@ -425,8 +390,7 @@ impl<'tcx> TyCtxt<'tcx> { return EvalResult::Allow; } - let suggestion = suggestion_for_allocator_api(self, def_id, span, feature); - EvalResult::Deny { feature, reason: reason.to_opt_reason(), issue, suggestion } + EvalResult::Deny { feature, reason: reason.to_opt_reason(), issue } } Some(_) => { // Stable APIs are always ok to call and deprecated APIs are @@ -472,12 +436,7 @@ impl<'tcx> TyCtxt<'tcx> { return EvalResult::Allow; } - EvalResult::Deny { - feature, - reason: reason.to_opt_reason(), - issue, - suggestion: None, - } + EvalResult::Deny { feature, reason: reason.to_opt_reason(), issue } } Some(_) => { // Stable APIs are always ok to call @@ -559,15 +518,9 @@ impl<'tcx> TyCtxt<'tcx> { let is_allowed = matches!(eval_result, EvalResult::Allow); match eval_result { EvalResult::Allow => {} - EvalResult::Deny { feature, reason, issue, suggestion } => report_unstable( - self.sess, - feature, - reason, - issue, - suggestion, - span, - UnstableKind::Regular, - ), + EvalResult::Deny { feature, reason, issue } => { + report_unstable(self.sess, feature, reason, issue, span, UnstableKind::Regular) + } EvalResult::Unmarked => unmarked(span, def_id), } @@ -628,7 +581,6 @@ impl<'tcx> TyCtxt<'tcx> { feature, reason.to_opt_reason(), issue, - None, span, UnstableKind::Const(const_kw_span), ); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 24a52d4143493..823a66dcd5d93 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -1098,7 +1098,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { feature, reason.to_opt_reason(), issue, - None, span, stability::UnstableKind::Regular, ); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bd70e5acab4d7..f2ab04b41d938 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -413,7 +413,6 @@ symbols! { alloc_layout, alloc_zeroed, allocator, - allocator_api, allocator_internals, allow, allow_fail, From 71d4ef88c61ab0f4673589bb4d19e96c76f89560 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Sep 2026 09:30:29 +1000 Subject: [PATCH 0691/1309] Remove unused `StashKey::UnderscoreForArrayLengths` It's no longer ever used for stashing, so the code looking for it is dead. It became dead in PR 141610 when `generic_arg_infer` was stabilized and `[T; _]` became valid. --- compiler/rustc_errors/src/lib.rs | 1 - compiler/rustc_hir_typeck/src/expr.rs | 29 --------------------------- 2 files changed, 30 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 68e10802e21c5..25a82b22707cc 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -375,7 +375,6 @@ struct DiagCtxtInner { #[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum StashKey { ItemNoType, - UnderscoreForArrayLengths, EarlySyntaxWarning, CallIntoMethod, /// When an invalid lifetime e.g. `'2` should be reinterpreted diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 04e55dd0fdd95..8944d6a47488a 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -1702,34 +1702,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { self.next_ty_var(expr.span) }; let array_len = args.len() as u64; - self.suggest_array_len(expr, array_len); Ty::new_array(self.tcx, element_ty, array_len) } - fn suggest_array_len(&self, expr: &'tcx hir::Expr<'tcx>, array_len: u64) { - let parent_node = self.tcx.hir_parent_iter(expr.hir_id).find(|(_, node)| { - !matches!(node, hir::Node::Expr(hir::Expr { kind: hir::ExprKind::AddrOf(..), .. })) - }); - let Some((_, hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), .. }))) = parent_node else { - return; - }; - if let hir::TyKind::Array(_, ct) = ty.peel_refs().kind { - let span = ct.span; - self.dcx().try_steal_modify_and_emit_err( - span, - StashKey::UnderscoreForArrayLengths, - |err| { - err.span_suggestion_verbose( - span, - "consider specifying the array length", - array_len, - Applicability::MaybeIncorrect, - ); - }, - ); - } - } - pub(super) fn check_expr_const_block( &self, block: &'tcx hir::ConstBlock, @@ -1764,10 +1739,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { ), ); - if let Some(count) = count.try_to_target_usize(tcx) { - self.suggest_array_len(expr, count); - } - let uty = match expected { ExpectHasType(uty) => uty.builtin_index(), _ => None, From 4dcd02e3aa1b8101d24aa4ef8d887627407539a1 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:50:17 +0000 Subject: [PATCH 0692/1309] rename direct_const_arg! to gca! Co-authored-by: Boxy --- compiler/rustc_ast/src/ast.rs | 10 +- compiler/rustc_ast/src/util/classify.rs | 6 +- compiler/rustc_ast/src/visit.rs | 2 +- compiler/rustc_ast_lowering/src/expr.rs | 4 +- compiler/rustc_ast_lowering/src/lib.rs | 31 +++--- compiler/rustc_ast_pretty/src/pprust/state.rs | 4 +- .../rustc_ast_pretty/src/pprust/state/expr.rs | 4 +- .../src/assert/context.rs | 2 +- .../src/{direct_const_arg.rs => gca.rs} | 7 +- compiler/rustc_builtin_macros/src/lib.rs | 4 +- compiler/rustc_feature/src/unstable.rs | 4 +- compiler/rustc_hir/src/hir.rs | 2 +- .../src/check/compare_impl_item.rs | 4 +- .../src/hir_ty_lowering/mod.rs | 8 +- compiler/rustc_lint/src/unused.rs | 4 +- compiler/rustc_middle/src/queries.rs | 4 +- compiler/rustc_parse/src/parser/expr.rs | 2 +- compiler/rustc_passes/src/input_stats.rs | 4 +- compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_span/src/symbol.rs | 2 +- library/core/src/marker.rs | 8 +- library/std/src/lib.rs | 2 + ...macroless-const-item-generic-const-args.md | 6 +- .../macroless-generic-const-args.md | 16 ++-- .../min-generic-const-args.md | 28 +++--- .../clippy_utils/src/check_proc_macro.rs | 2 +- src/tools/clippy/clippy_utils/src/sugg.rs | 2 +- .../clippy/tests/ui/crashes/mgca-16691.rs | 4 +- src/tools/rustfmt/src/expr.rs | 2 +- src/tools/rustfmt/src/types.rs | 2 +- src/tools/rustfmt/src/utils.rs | 2 +- .../rustfmt/tests/source/direct_const_arg.rs | 15 --- src/tools/rustfmt/tests/source/gca.rs | 17 ++++ .../rustfmt/tests/target/direct_const_arg.rs | 15 --- src/tools/rustfmt/tests/target/gca.rs | 17 ++++ tests/crashes/138009.rs | 5 +- tests/crashes/149809.rs | 8 +- tests/crashes/150049.rs | 5 +- tests/crashes/150749.rs | 6 +- tests/debuginfo/associated-const-bindings.rs | 5 +- tests/pretty/direct-const-arg.rs | 10 -- .../{direct-const-arg.pp => gca-macro.pp} | 9 +- tests/pretty/gca-macro.rs | 12 +++ .../rustdoc-html/type-const-free-in-array.rs | 4 +- .../type-const-inherent-with-body.rs | 4 +- .../type-const-in-array-len-wrong-type.rs | 4 +- .../type-const-in-array-len-wrong-type.stderr | 2 +- .../type-const-in-array-len.rs | 8 +- .../duplicate-bound-err.rs | 6 +- .../associated-type-bounds/duplicate-bound.rs | 4 +- .../type-const-inherent-impl-normalize.rs | 4 +- .../type-const-inherent-impl-normalize.stderr | 10 +- .../resolved-region-var-max-universe.rs | 4 +- .../resolved-region-var-max-universe.stderr | 2 +- .../associated-const-bindings/ambiguity.rs | 4 +- .../ambiguity.stderr | 8 +- .../associated-const-bindings/assoc-const.rs | 4 +- .../coexisting-with-type-binding.rs | 4 +- .../associated-const-bindings/coherence.rs | 4 +- .../coherence.stderr | 2 +- .../const_evaluatable_unchecked.rs | 4 +- .../dyn-compat-basic.rs | 4 +- .../dyn-compat-const-mismatch.rs | 4 +- .../dyn-compat-const-mismatch.stderr | 2 +- ...ompat-const-param-default-mentions-self.rs | 4 +- ...t-const-param-default-mentions-self.stderr | 2 +- ...und-on-assoc-const-allowed-and-enforced.rs | 4 +- ...on-assoc-const-allowed-and-enforced.stderr | 6 +- ...elf-const-projections-in-assoc-const-ty.rs | 4 +- ...const-projections-in-assoc-const-ty.stderr | 4 +- ...ompat-self-const-projections-in-methods.rs | 6 +- .../equality-unused-issue-126729.rs | 12 ++- .../equality_bound_with_infer.rs | 4 +- .../mismatched-types-with-generic-in-ace.rs | 4 +- ...ismatched-types-with-generic-in-ace.stderr | 8 +- .../wf-mismatch-3.rs | 4 +- .../wf-mismatch-3.stderr | 6 +- ...-on-failed-eval-with-vars-fail.next.stderr | 16 ++-- ...ambiguous-on-failed-eval-with-vars-fail.rs | 6 +- tests/ui/const-generics/gca/assoc-const.rs | 7 +- .../gca/basic-different-definitions.rs | 4 +- tests/ui/const-generics/gca/basic.rs | 6 +- tests/ui/const-generics/gca/coherence-ok.rs | 6 +- .../gca/gca-anon-const-rejected.rs | 4 +- .../gca/gca-anon-const-rejected.stderr | 6 +- ...st-arg-fn-call.rs => gca-macro-fn-call.rs} | 0 ...n-call.stderr => gca-macro-fn-call.stderr} | 10 +- .../gca/non-type-equality-fail.rs | 9 +- .../gca/non-type-equality-fail.stderr | 20 ++-- .../ui/const-generics/gca/rhs-but-not-root.rs | 6 +- .../gca/rhs-but-not-root.stderr | 6 +- .../suggest-const-item-for-generic-expr.rs | 2 +- .../ui/const-generics/gca/wf-inherentimpl.rs | 3 +- .../auxiliary/non_local_type_const.rs | 4 +- .../inherent-type-const.rs | 6 +- .../mgca/adt_expr_arg_simple.rs | 4 +- .../mgca/adt_expr_arg_simple.stderr | 8 +- .../mgca/adt_expr_infers_from_value.rs | 3 +- .../mgca/array-const-arg-len-mismatch.rs | 3 +- .../mgca/array-const-arg-len-mismatch.stderr | 20 ++-- .../mgca/array-expr-complex.r1.stderr | 6 +- .../mgca/array-expr-complex.r2.stderr | 6 +- .../mgca/array-expr-complex.r3.stderr | 6 +- .../const-generics/mgca/array-expr-complex.rs | 8 +- .../mgca/array_expr_arg_complex.rs | 6 +- .../mgca/array_expr_arg_complex.stderr | 12 +-- .../mgca/assoc-const-projection-in-bound.rs | 4 +- .../mgca/bad-const-arg-fn-154539.rs | 4 +- .../mgca/bad-const-arg-fn-154539.stderr | 6 +- .../mgca/bad-direct-const-arg.rs | 15 --- .../mgca/bad-direct-const-arg.stderr | 20 ---- tests/ui/const-generics/mgca/bad-gca-macro.rs | 17 ++++ .../const-generics/mgca/bad-gca-macro.stderr | 20 ++++ .../mgca/bad-type_const-syntax.rs | 13 ++- .../mgca/bad-type_const-syntax.stderr | 60 +++++++++--- .../mgca/braced-const-infer-in-body.rs | 8 +- .../mgca/braced-const-infer-in-body.stderr | 8 +- .../concrete-expr-with-generics-in-env.rs | 9 +- ...const-arg-coherence-conflicting-methods.rs | 4 +- ...t-arg-coherence-conflicting-methods.stderr | 6 +- .../const-arg-mismatched-literal-suffix.rs | 4 +- ...const-arg-mismatched-literal-suffix.stderr | 4 +- .../mgca/cyclic-type-const-151251.rs | 4 +- .../mgca/cyclic-type-const-151251.stderr | 4 +- .../mgca/direct-const-arg-correct-rib.stderr | 8 -- .../mgca/direct-const-arg-multiple-exprs.rs | 5 - .../direct-const-arg-multiple-exprs.stderr | 8 -- .../mgca/direct_const_arg-infer-as-type.rs | 13 --- .../direct_const_arg-infer-as-type.stderr | 15 --- .../mgca/explicit_anon_consts.rs | 22 +++-- .../mgca/explicit_anon_consts.stderr | 54 +++++------ .../mgca/free-const-recursive.gca.stderr | 8 +- .../mgca/free-const-recursive.min_gca.stderr | 4 +- .../mgca/free-const-recursive.rs | 4 +- ...orrect-rib.rs => gca-macro-correct-rib.rs} | 6 +- .../mgca/gca-macro-correct-rib.stderr | 8 ++ ...ture-gate.rs => gca-macro-feature-gate.rs} | 4 +- ...e.stderr => gca-macro-feature-gate.stderr} | 20 ++-- .../mgca/gca-macro-infer-as-type.rs | 14 +++ .../mgca/gca-macro-infer-as-type.stderr | 15 +++ .../mgca/gca-macro-multiple-exprs.rs | 6 ++ .../mgca/gca-macro-multiple-exprs.stderr | 8 ++ ...eric-args-on-enum-variant-segments-fail.rs | 7 +- ...-args-on-enum-variant-segments-fail.stderr | 38 ++++---- .../generic-args-on-enum-variant-segments.rs | 6 +- ...eneric_const_items-mismatched-array-len.rs | 4 +- ...ic_const_items-mismatched-array-len.stderr | 4 +- ...onst_parameter_types-inferred-array-len.rs | 5 +- .../mgca/generic_const_type_mismatch.rs | 4 +- .../mgca/generic_const_type_mismatch.stderr | 6 +- .../mgca/inherent-alias-default.rs | 6 +- ...t-const-arg-owner-issue-159172.expr.stderr | 13 --- ...d-gca-macro-owner-issue-159172.expr.stderr | 13 +++ ...> invalid-gca-macro-owner-issue-159172.rs} | 10 +- ...id-gca-macro-owner-issue-159172.ty.stderr} | 6 +- .../mgca/macro-const-arg-infer.rs | 5 +- .../mgca/macro-const-arg-infer.stderr | 14 +-- ...ixed-direct-anon-expression-diagnostics.rs | 4 +- ...-direct-anon-expression-diagnostics.stderr | 8 +- ...onst_args.rs => multi_braced_gca_macro.rs} | 0 .../non-local-const-without-type_const.stderr | 2 +- .../mgca/none-as-usize-const-arg.rs | 4 +- .../mgca/none-as-usize-const-arg.stderr | 16 ++-- .../opaque-ty-assoc-const-equality-117923.rs | 4 +- tests/ui/const-generics/mgca/paren.rs | 52 +++++----- .../mgca/projection-const-recursive.rs | 4 +- .../mgca/projection-const-recursive.stderr | 8 +- .../const-generics/mgca/static-const-arg.rs | 6 +- .../mgca/static-const-arg.stderr | 12 +-- .../mgca/suggest-direct-const.fixed | 33 ++++--- .../mgca/suggest-direct-const.rs | 21 +++-- .../mgca/suggest-direct-const.stderr | 94 +++++++++---------- .../mgca/syntactic-type-mismatch.rs | 6 +- .../mgca/syntactic-type-mismatch.stderr | 10 +- .../mgca/tuple_ctor_complex_args.rs | 3 +- .../mgca/tuple_ctor_complex_args.stderr | 8 +- .../mgca/tuple_ctor_erroneous.rs | 3 +- .../mgca/tuple_ctor_erroneous.stderr | 22 ++--- .../mgca/tuple_expr_arg_complex.rs | 10 +- .../mgca/tuple_expr_arg_complex.stderr | 24 ++--- .../mgca/tuple_expr_arg_simple.rs | 10 +- .../type-const-assoc-const-without-body.rs | 4 +- ...type-const-assoc-const-without-body.stderr | 8 +- .../mgca/type-const-associated-default.rs | 3 +- .../mgca/type-const-associated-default.stderr | 6 +- .../mgca/type-const-ctor-148953.rs | 5 +- .../type-const-free-anon-const-mismatch.rs | 6 +- ...type-const-free-anon-const-mismatch.stderr | 8 +- ...st-free-value-type-mismatch.current.stderr | 6 +- ...const-free-value-type-mismatch.next.stderr | 8 +- .../type-const-free-value-type-mismatch.rs | 4 +- .../type-const-free-value-used-in-body.rs | 6 +- .../type-const-free-value-used-in-body.stderr | 8 +- ...nherent-value-type-mismatch.current.stderr | 6 +- ...t-inherent-value-type-mismatch.next.stderr | 8 +- ...type-const-inherent-value-type-mismatch.rs | 4 +- .../mgca/type-const-used-in-trait.rs | 4 +- ...e-const-value-type-mismatch.current.stderr | 10 +- ...type-const-value-type-mismatch.next.stderr | 10 +- .../mgca/type-const-value-type-mismatch.rs | 4 +- .../mgca/type_const-adt-expr-missing-field.rs | 6 +- .../type_const-adt-expr-missing-field.stderr | 16 ++-- .../mgca/type_const-array-return.rs | 4 +- ..._const-generic-param-in-type.nogate.stderr | 18 ++-- .../mgca/type_const-generic-param-in-type.rs | 19 ++-- .../mgca/type_const-incemental-compile.rs | 4 +- .../type_const-inherent-const-omitted-type.rs | 4 +- ...e_const-inherent-const-omitted-type.stderr | 12 +-- .../type_const-mismatched-type-incremental.rs | 11 ++- ...e_const-mismatched-type-incremental.stderr | 16 ++-- .../mgca/type_const-mismatched-types.rs | 8 +- .../mgca/type_const-mismatched-types.stderr | 16 ++-- .../mgca/type_const-not-constparamty.rs | 6 +- .../mgca/type_const-not-constparamty.stderr | 10 +- .../mgca/type_const-on-generic-expr.rs | 6 +- .../mgca/type_const-on-generic-expr.stderr | 12 +-- .../mgca/type_const-on-generic_expr-2.rs | 8 +- .../mgca/type_const-on-generic_expr-2.stderr | 18 ++-- .../type_const-only-in-impl-omitted-type.rs | 6 +- ...ype_const-only-in-impl-omitted-type.stderr | 20 ++-- .../mgca/type_const-only-in-impl.rs | 6 +- .../mgca/type_const-only-in-impl.stderr | 10 +- .../mgca/type_const-only-in-trait.rs | 4 +- .../mgca/type_const-only-in-trait.stderr | 6 +- .../ui/const-generics/mgca/type_const-pub.rs | 4 +- .../mgca/type_const-recursive.rs | 4 +- .../mgca/type_const-recursive.stderr | 4 +- .../ui/const-generics/mgca/type_const-use.rs | 4 +- .../mgca/type_const_in_pattern.rs | 8 +- .../unbraced_const_block_const_arg_gated.rs | 6 +- ...nbraced_const_block_const_arg_gated.stderr | 24 ++--- .../mgca/unmarked-free-const.rs | 4 +- .../mgca/unmarked-free-const.stderr | 12 +-- .../type-const-ice-issue-151631.rs | 4 +- .../type-const-ice-issue-151631.stderr | 10 +- .../type-relative-path-144547.rs | 2 +- ...ems-before-lowering-ices.ice_155125.stderr | 8 +- ...ems-before-lowering-ices.ice_155127.stderr | 2 +- ...ems-before-lowering-ices.ice_155128.stderr | 6 +- ...ems-before-lowering-ices.ice_155164.stderr | 6 +- ...ems-before-lowering-ices.ice_155202.stderr | 4 +- .../hir-crate-items-before-lowering-ices.rs | 6 +- .../inside-const-body-ice-155300.rs | 4 +- .../inside-const-body-ice-155300.stderr | 8 +- .../ui/delegation/wrong-fn-kind-ice-159127.rs | 6 +- .../wrong-fn-kind-ice-159127.stderr | 8 +- .../feature-gate-generic-const-args.rs | 4 +- .../feature-gate-generic-const-args.stderr | 6 +- .../feature-gate-mgca-type-const-syntax.rs | 10 +- ...feature-gate-mgca-type-const-syntax.stderr | 24 ++--- .../feature-gate-min-generic-const-args.rs | 4 +- ...feature-gate-min-generic-const-args.stderr | 16 ++-- .../assoc-const-bindings.rs | 7 +- .../assoc-const-no-infer-ice-115806.rs | 6 +- .../assoc-const-no-infer-ice-115806.stderr | 6 +- .../type-const-nested-assoc-const.rs | 6 +- .../object-lifetime-default-inherent-gac.rs | 8 +- ...bject-lifetime-default-inherent-gac.stderr | 4 +- .../assoc-const-projection-issue-151878.rs | 4 +- .../overlap-due-to-unsatisfied-const-bound.rs | 4 +- ...rlap-due-to-unsatisfied-const-bound.stderr | 2 +- tests/ui/supertrait-shadowing/assoc-const.rs | 4 +- .../supertrait-shadowing/common-ancestor-2.rs | 3 +- .../common-ancestor-2.stderr | 18 ++-- .../supertrait-shadowing/common-ancestor-3.rs | 5 +- .../common-ancestor-3.stderr | 30 +++--- .../supertrait-shadowing/common-ancestor.rs | 3 +- .../common-ancestor.stderr | 18 ++-- .../no-common-ancestor-2.rs | 5 +- .../no-common-ancestor-2.stderr | 22 ++--- tests/ui/supertrait-shadowing/out-of-scope.rs | 3 +- .../ui/supertrait-shadowing/type-dependent.rs | 3 +- .../next-solver/normalize-const-item-type.rs | 8 +- .../normalize-const-item-type.stderr | 18 ++-- 274 files changed, 1325 insertions(+), 1042 deletions(-) rename compiler/rustc_builtin_macros/src/{direct_const_arg.rs => gca.rs} (81%) delete mode 100644 src/tools/rustfmt/tests/source/direct_const_arg.rs create mode 100644 src/tools/rustfmt/tests/source/gca.rs delete mode 100644 src/tools/rustfmt/tests/target/direct_const_arg.rs create mode 100644 src/tools/rustfmt/tests/target/gca.rs delete mode 100644 tests/pretty/direct-const-arg.rs rename tests/pretty/{direct-const-arg.pp => gca-macro.pp} (60%) create mode 100644 tests/pretty/gca-macro.rs rename tests/ui/const-generics/gca/{direct-const-arg-fn-call.rs => gca-macro-fn-call.rs} (100%) rename tests/ui/const-generics/gca/{direct-const-arg-fn-call.stderr => gca-macro-fn-call.stderr} (81%) delete mode 100644 tests/ui/const-generics/mgca/bad-direct-const-arg.rs delete mode 100644 tests/ui/const-generics/mgca/bad-direct-const-arg.stderr create mode 100644 tests/ui/const-generics/mgca/bad-gca-macro.rs create mode 100644 tests/ui/const-generics/mgca/bad-gca-macro.stderr delete mode 100644 tests/ui/const-generics/mgca/direct-const-arg-correct-rib.stderr delete mode 100644 tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.rs delete mode 100644 tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.stderr delete mode 100644 tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.rs delete mode 100644 tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.stderr rename tests/ui/const-generics/mgca/{direct-const-arg-correct-rib.rs => gca-macro-correct-rib.rs} (57%) create mode 100644 tests/ui/const-generics/mgca/gca-macro-correct-rib.stderr rename tests/ui/const-generics/mgca/{direct-const-arg-feature-gate.rs => gca-macro-feature-gate.rs} (52%) rename tests/ui/const-generics/mgca/{direct-const-arg-feature-gate.stderr => gca-macro-feature-gate.stderr} (56%) create mode 100644 tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs create mode 100644 tests/ui/const-generics/mgca/gca-macro-infer-as-type.stderr create mode 100644 tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs create mode 100644 tests/ui/const-generics/mgca/gca-macro-multiple-exprs.stderr delete mode 100644 tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr create mode 100644 tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.expr.stderr rename tests/ui/const-generics/mgca/{invalid-direct-const-arg-owner-issue-159172.rs => invalid-gca-macro-owner-issue-159172.rs} (57%) rename tests/ui/const-generics/mgca/{invalid-direct-const-arg-owner-issue-159172.ty.stderr => invalid-gca-macro-owner-issue-159172.ty.stderr} (58%) rename tests/ui/const-generics/mgca/{multi_braced_direct_const_args.rs => multi_braced_gca_macro.rs} (100%) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 5b9f3231fc744..2f1a547e05a48 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -1623,7 +1623,7 @@ impl Expr { | ExprKind::UnsafeBinderCast(..) | ExprKind::While(..) | ExprKind::Yield(YieldKind::Postfix(..)) - | ExprKind::DirectConstArg(..) + | ExprKind::GcaMacro(..) | ExprKind::Err(_) | ExprKind::Dummy => prefix_attrs_precedence(&self.attrs), } @@ -1920,8 +1920,8 @@ pub enum ExprKind { UnsafeBinderCast(UnsafeBinderCastKind, Box, Option>), - /// An mGCA `direct_const_arg!()` expression. - DirectConstArg(Box), + /// An mGCA `gca!()` expression. + GcaMacro(Box), /// Placeholder for an expression that wasn't syntactically well formed in some way. Err(ErrorGuaranteed), @@ -2579,8 +2579,8 @@ pub enum TyKind { FieldOf(Box, Option, Ident), /// A view of a type. `T.{ field_1, field_2 }`. View(Box, #[visitable(ignore)] ThinVec), - /// An mGCA `direct_const_arg!()` expression. - DirectConstArg(Box), + /// An mGCA `gca!()` expression. + GcaMacro(Box), /// Sometimes we need a dummy value when no error has occurred. Dummy, /// Placeholder for a kind that has failed to be defined. diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index e799f73ff544f..c4c181743543e 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -158,7 +158,7 @@ pub fn leading_labeled_expr(mut expr: &ast::Expr) -> bool { | Yeet(..) | Yield(..) | UnsafeBinderCast(..) - | DirectConstArg(..) + | GcaMacro(..) | Err(..) | Dummy => return false, } @@ -244,7 +244,7 @@ pub fn expr_trailing_brace(mut expr: &ast::Expr) -> Option> { | Try(_) | Yeet(None) | UnsafeBinderCast(..) - | DirectConstArg(..) + | GcaMacro(..) | Err(_) | Dummy => { break None; @@ -307,7 +307,7 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { | ast::TyKind::Pat(..) | ast::TyKind::FieldOf(..) | ast::TyKind::View(..) - | ast::TyKind::DirectConstArg(..) + | ast::TyKind::GcaMacro(..) | ast::TyKind::Dummy | ast::TyKind::Err(..) => break None, } diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index 4270ac0656deb..ec77de62607ce 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -1112,7 +1112,7 @@ macro_rules! common_visitor_and_walkers { visit_visitable!(vis, bytes), ExprKind::UnsafeBinderCast(kind, expr, ty) => visit_visitable!(vis, kind, expr, ty), - ExprKind::DirectConstArg(expr) => + ExprKind::GcaMacro(expr) => visit_visitable!(vis, expr), ExprKind::Err(_guar) => {} ExprKind::Dummy => {} diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs index c3bc86a352644..f4bfec24e3b1b 100644 --- a/compiler/rustc_ast_lowering/src/expr.rs +++ b/compiler/rustc_ast_lowering/src/expr.rs @@ -544,8 +544,8 @@ impl<'hir> LoweringContext<'_, 'hir> { ExprKind::MacCall(_) => panic!("{:?} shouldn't exist here", e.span), - ExprKind::DirectConstArg(expr) => { - let e = self.emit_bad_direct_const_arg(e.span, expr, "expression"); + ExprKind::GcaMacro(expr) => { + let e = self.emit_bad_gca_macro(e.span, expr, "expression"); hir::ExprKind::Err(e) } }; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 7ff6a2538c1e7..ba5a9b52f7dd1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1489,9 +1489,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ct = self.arena.alloc(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } - TyKind::DirectConstArg(expr) - if self.tcx.features().min_generic_const_args() => - { + TyKind::GcaMacro(expr) if self.tcx.features().min_generic_const_args() => { let ct = match self.can_lower_expr_to_const_arg_direct( expr, DirectConstArgContext::MacrolessMinGenericConstArgs, @@ -1797,8 +1795,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let fields = self.arena.alloc_slice(fields); hir::TyKind::View(ty, fields) } - TyKind::DirectConstArg(expr) => { - let e = self.emit_bad_direct_const_arg(t.span, expr, "type"); + TyKind::GcaMacro(expr) => { + let e = self.emit_bad_gca_macro(t.span, expr, "type"); hir::TyKind::Err(e) } TyKind::Dummy => panic!("`TyKind::Dummy` should never be lowered"), @@ -1807,16 +1805,16 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::Ty { kind, span: self.lower_span(t.span), hir_id: self.lower_node_id(t.id) } } - pub(crate) fn emit_bad_direct_const_arg( + pub(crate) fn emit_bad_gca_macro( &mut self, span: Span, expr: &Expr, expected: &'static str, ) -> ErrorGuaranteed { - let msg = format!("expected {expected}, found `direct_const_arg!()` constant"); + let msg = format!("expected {expected}, found `gca!()` constant"); if expr::WillCreateDefIdsVisitor.visit_expr(expr).is_break() { // FIXME(mgca): make this non-fatal once we have a better way to handle - // nested items in invalid `direct_const_arg!()` arguments. + // nested items in invalid `gca!()` arguments. self.dcx().span_fatal(span, msg) } else { self.dcx().span_err(span, msg) @@ -2711,9 +2709,9 @@ impl<'hir> LoweringContext<'_, 'hir> { .is_ok() } else { // do not check can_lower_expr_to_const_arg_direct, but rather just - // ExprKind::DirectConstArg, because we don't want e.g. + // ExprKind::GcaMacro, because we don't want e.g. // `impl { const C: u8 = N; }` to be a direct-rhs const - matches!(body, Expr { kind: ExprKind::DirectConstArg(_), .. }) + matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. }) } }; if self.tcx.features().min_generic_const_args() @@ -2816,7 +2814,7 @@ impl<'hir> LoweringContext<'_, 'hir> { Ok(()) } (ExprKind::ConstBlock(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::DirectConstArg(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => { + (ExprKind::GcaMacro(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => { // Always report this as able to be represented directly. If it turns out not to be, // `lower_expr_to_const_arg_direct` will report an error. Ok(()) @@ -2998,11 +2996,10 @@ impl<'hir> LoweringContext<'_, 'hir> { span, } } - ExprKind::DirectConstArg(expr) => { + ExprKind::GcaMacro(expr) => { // `can_lower_expr_to_const_arg_direct` always returns success upon encountering a - // ExprKind::DirectConstArg, which effectively forces the expression to be lowered - // as a direct arg. If it actually turns out to not be possible, emit an error - // instead. + // ExprKind::GcaMacro, which effectively forces the expression to be lowered as a + // direct arg. If it actually turns out to not be possible, emit an error instead. // Always use MacrolessMinGenericConstArgs, even if we're under regular GCA, because // that's what the macro means: to enter a context that is like macroless GCA. match self.can_lower_expr_to_const_arg_direct( @@ -3354,12 +3351,12 @@ enum DirectConstArgContext { /// The only allowed direct const arg representation is simple paths that nameres to generic /// const parameters. Stable, - /// The allowed representations are what is allowed on stable, plus the `direct_const_arg!` macro. + /// The allowed representations are what is allowed on stable, plus the `gca!` macro. MinGenericConstArgs, /// Expressions attempt to be lowered directly, and if that fails, the expression falls back to /// being represented as an anon const. /// - /// This context is also used under MinGenericConstArgs inside a `direct_const_arg!` macro, for + /// This context is also used under MinGenericConstArgs inside a `gca!` macro, for /// simplicity, as they allow the same code. MacrolessMinGenericConstArgs, } diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index d97bf7a2a6db3..6637ed356f557 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1460,8 +1460,8 @@ impl<'a> State<'a> { self.print_type(ty); self.print_view(fields); } - ast::TyKind::DirectConstArg(expr) => { - self.word_nbsp("core::direct_const_arg!"); + ast::TyKind::GcaMacro(expr) => { + self.word_nbsp("core::gca!"); self.popen(); self.print_expr(expr, FixupContext::default()); self.pclose(); diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs index b6c22e7da9cb1..d6e8f69dbfa03 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs @@ -883,8 +883,8 @@ impl<'a> State<'a> { self.word("/*DUMMY*/"); self.pclose(); } - ast::ExprKind::DirectConstArg(expr) => { - self.word_nbsp("core::direct_const_arg!"); + ast::ExprKind::GcaMacro(expr) => { + self.word_nbsp("core::gca!"); self.popen(); self.print_expr(expr, FixupContext::default()); self.pclose() diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index aa339ce7f4252..cb3ea2475721e 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -321,7 +321,7 @@ impl<'cx, 'a> Context<'cx, 'a> { | ExprKind::Yeet(_) | ExprKind::Become(_) | ExprKind::Yield(_) - | ExprKind::DirectConstArg(_) + | ExprKind::GcaMacro(_) | ExprKind::UnsafeBinderCast(..) => {} } } diff --git a/compiler/rustc_builtin_macros/src/direct_const_arg.rs b/compiler/rustc_builtin_macros/src/gca.rs similarity index 81% rename from compiler/rustc_builtin_macros/src/direct_const_arg.rs rename to compiler/rustc_builtin_macros/src/gca.rs index 6af503e9a4681..ba26b16d06be5 100644 --- a/compiler/rustc_builtin_macros/src/direct_const_arg.rs +++ b/compiler/rustc_builtin_macros/src/gca.rs @@ -10,8 +10,7 @@ pub(crate) fn expand<'cx>( span: Span, tts: TokenStream, ) -> MacroExpanderResult<'cx> { - let ExpandResult::Ready(expr) = get_single_expr_from_tts(cx, span, tts, "direct_const_arg!") - else { + let ExpandResult::Ready(expr) = get_single_expr_from_tts(cx, span, tts, "gca!") else { return ExpandResult::Retry(()); }; let expr = match expr { @@ -23,12 +22,12 @@ pub(crate) fn expand<'cx>( ExpandResult::Ready(Box::new(base::MacEager { expr: Some(Box::new(ast::Expr { id, - kind: ast::ExprKind::DirectConstArg(expr.clone()), + kind: ast::ExprKind::GcaMacro(expr.clone()), span, attrs: Default::default(), tokens: None, })), - ty: Some(Box::new(ast::Ty { id, kind: ast::TyKind::DirectConstArg(expr), span })), + ty: Some(Box::new(ast::Ty { id, kind: ast::TyKind::GcaMacro(expr), span })), ..Default::default() })) } diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs index 57759bb113401..c564e14776c91 100644 --- a/compiler/rustc_builtin_macros/src/lib.rs +++ b/compiler/rustc_builtin_macros/src/lib.rs @@ -34,12 +34,12 @@ mod define_opaque; mod derive; mod deriving; mod diagnostics; -mod direct_const_arg; mod edition_panic; mod eii; mod env; mod format; mod format_foreign; +mod gca; mod global_allocator; mod iter; mod log_syntax; @@ -83,11 +83,11 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) { concat_bytes: concat_bytes::expand_concat_bytes, const_format_args: format::expand_format_args, core_panic: edition_panic::expand_panic, - direct_const_arg: direct_const_arg::expand, env: env::expand_env, file: source_util::expand_file, format_args: format::expand_format_args, format_args_nl: format::expand_format_args_nl, + gca: gca::expand, global_asm: asm::expand_global_asm, include: source_util::expand_include, include_bytes: source_util::expand_include_bytes, diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 94e3b77c6b575..a020ff315e470 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -610,9 +610,9 @@ declare_features! ( /// Provides a way to concatenate identifiers using metavariable expressions. (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), /// Allows directly represented generic_const_args as the rhs of const items without the - /// `direct_const_arg!` macro. + /// `gca!` macro. (incomplete, macroless_const_item_generic_const_args, "CURRENT_RUSTC_VERSION", Some(162540)), - /// Allows directly represented generic_const_args without the `direct_const_arg!` macro. + /// Allows directly represented generic_const_args without the `gca!` macro. (incomplete, macroless_generic_const_args, "1.99.0", Some(159006)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index ee79680d7d1e9..203f2bb935133 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -554,7 +554,7 @@ pub enum InferArgKind { /// determined during HIR ty lowering. TypeOrConst, /// An infer argument with unambiguous const syntax, e.g. S<{ _ }> or - /// S. It can only be inferred to a const. + /// S. It can only be inferred to a const. Const, } diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 01f4f5cc527d6..af380929c446e 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2171,7 +2171,7 @@ pub(super) fn compare_const_directness<'tcx>( tcx.dcx() .struct_span_err( tcx.def_span(impl_const_item.def_id), - "implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS", + "implementation of a `#[rustc_always_gca]` must have a `gca!` RHS", ) .with_span_note( tcx.def_span(trait_const_item.def_id), @@ -2182,7 +2182,7 @@ pub(super) fn compare_const_directness<'tcx>( tcx.dcx() .struct_span_err( tcx.def_span(impl_const_item.def_id), - "implementation of a regular const cannot have a `direct_const_arg!` RHS", + "implementation of a regular const cannot have a `gca!` RHS", ) .with_span_note( tcx.def_span(trait_const_item.def_id), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e7ecde09ce27b..99694554b00af 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3147,9 +3147,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let body_span = tcx.hir_body(body_id).value.span; err.multipart_suggestion( - "add direct_const_arg!() to the right-hand side of the constant", + "add gca!() to the right-hand side of the constant", vec![ - (body_span.shrink_to_lo(), String::from("core::direct_const_arg!(")), + (body_span.shrink_to_lo(), String::from("core::gca!(")), (body_span.shrink_to_hi(), String::from(")")), ], Applicability::MaybeIncorrect, @@ -3165,9 +3165,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } else { - err.note( - "only consts with a `direct_const_arg!` right-hand side may be used in types", - ); + err.note("only consts with a `gca!` right-hand side may be used in types"); } Err(err.emit_err()) } diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 17c078615c411..2651ce55281fe 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -198,8 +198,8 @@ trait UnusedDelimLint { | Paren(_) | Become(_) => true, Call(..) | MethodCall(_) | Let(..) | Field(..) | MacCall(_) | FormatArgs(_) => false, - // `direct_const_arg!()` is invalid in function/method argument position. - DirectConstArg(_) => false, + // `gca!()` is invalid in function/method argument position. + GcaMacro(_) => false, // don't lint for placeholder/error-recovery Underscore | Err(_) | Dummy => false, } diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 9e1bafa4fd2a2..8612adb8aa975 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -287,8 +287,8 @@ rustc_queries! { } /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`, or if - /// it is a directly represented `const` (i.e. a const with a `direct_const_arg!` RHS, or a - /// const that `feature(macroless_generic_const_args)` has decided is direct). + /// it is a directly represented `const` (i.e. a const with a `gca!` RHS, or a const that + /// `feature(macroless_generic_const_args)` has decided is direct). /// /// When a const item is used in a type-level expression, like in equality for an assoc const /// projection, this allows us to retrieve the typesystem-appropriate representation of the diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 5bc30ae7ba325..a5c31672a2bc7 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -4358,7 +4358,7 @@ impl MutVisitor for CondChecker<'_> { | ExprKind::IncludedBytes(_) | ExprKind::FormatArgs(_) | ExprKind::Err(_) - | ExprKind::DirectConstArg(_) + | ExprKind::GcaMacro(_) | ExprKind::Dummy => { // These would forbid any let expressions they contain already. } diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 961e6e63a81da..c7bcbfe82f3f2 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -661,7 +661,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { If, While, ForLoop, Loop, Match, Closure, Block, Await, Move, Use, TryBlock, Assign, AssignOp, Field, Index, Range, Underscore, Path, AddrOf, Break, Continue, Ret, InlineAsm, FormatArgs, OffsetOf, MacCall, Struct, Repeat, Paren, Try, Yield, Yeet, - Become, IncludedBytes, Gen, UnsafeBinderCast, Err, Dummy, DirectConstArg + Become, IncludedBytes, Gen, UnsafeBinderCast, GcaMacro, Err, Dummy ] ); ast_visit::walk_expr(self, e) @@ -691,7 +691,7 @@ impl<'v> ast_visit::Visitor<'v> for StatCollector<'v> { CVarArgs, FieldOf, View, - DirectConstArg, + GcaMacro, Dummy, Err ] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7d90b93b62375..aab01d43acba9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -1034,7 +1034,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc self.visit_ty(element_ty); self.resolve_anon_const(length, AnonConstKind::ArrayLength); } - TyKind::DirectConstArg(expr) => self.resolve_anon_const_manual( + TyKind::GcaMacro(expr) => self.resolve_anon_const_manual( true, AnonConstKind::ConstArg(IsRepeatExpr::No), |this| this.resolve_expr(expr, None), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index bd70e5acab4d7..748c2c23fd10d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -848,7 +848,6 @@ symbols! { diagnostic_opaque, dialect, direct, - direct_const_arg, discriminant_kind, discriminant_type, discriminant_value, @@ -1068,6 +1067,7 @@ symbols! { future_output, future_trait, fxsr, + gca, gdb_script_file, ge, gen_blocks, diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 217f29d6a86e1..e67c7114d6d6a 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1076,13 +1076,13 @@ pub trait Tuple {} /// Creates a new style directly represented const argument. /// ```ignore (cannot test this from within core yet) -/// const BAR: usize = direct_const_arg!(N); -/// const FOO: usize = direct_const_arg!(BAR::); +/// const BAR: usize = gca!(N); +/// const FOO: usize = gca!(BAR::); /// ``` -#[rustc_builtin_macro(direct_const_arg)] +#[rustc_builtin_macro(gca)] #[unstable(feature = "min_generic_const_args", issue = "132980")] #[macro_export] -macro_rules! direct_const_arg { +macro_rules! gca { ($($arg:tt)*) => { /* compiler built-in */ }; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index acc8cdfc8281d..93b129c5c6641 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -758,6 +758,8 @@ pub use core::concat_bytes; )] #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; +#[unstable(feature = "min_generic_const_args", issue = "132980")] +pub use core::gca; #[stable(feature = "matches_macro", since = "1.42.0")] pub use core::matches; #[stable(feature = "core_primitive", since = "1.43.0")] diff --git a/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md b/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md index df9172e04b9ac..feb03a633d1bd 100644 --- a/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md @@ -1,6 +1,6 @@ # macroless_generic_const_args -Enables implementing const items under `#![feature(min_generic_const_args)]` and `#![feature(generic_const_args)]` without the `direct_const_arg!` macro. +Enables implementing const items under `#![feature(min_generic_const_args)]` and `#![feature(generic_const_args)]` without the `gca!` macro. The tracking issue for this feature is: [#162540] @@ -11,7 +11,7 @@ The tracking issue for this feature is: [#162540] Warning: This feature is incomplete; its design and syntax may change. Related features: -- [min_generic_const_args]. See that doc for what the `direct_const_arg!` is. This feature enables +- [min_generic_const_args]. See that doc for what the `gca!` is. This feature enables support for directly represented const arguments as the rhs of const items without the macro. - [macroless_generic_const_args]. For a version of this feature that works for const arguments in other positions @@ -39,7 +39,7 @@ trait Trait { } impl Trait for () { - const ASSOC: usize = core::direct_const_arg!(N); + const ASSOC: usize = core::gca!(N); } fn foo() { diff --git a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md b/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md index 410834a79712e..fadc2260bfbdc 100644 --- a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md @@ -1,6 +1,6 @@ # macroless_generic_const_args -Enables using `#![feature(min_generic_const_args)]` without the `direct_const_arg!` macro. +Enables using `#![feature(min_generic_const_args)]` without the `gca!` macro. The tracking issue for this feature is: [#159006] @@ -11,7 +11,7 @@ The tracking issue for this feature is: [#159006] Warning: This feature is incomplete; its design and syntax may change. Related features: -- [min_generic_const_args]. See that doc for what the `direct_const_arg!` is. This feature enables +- [min_generic_const_args]. See that doc for what the `gca!` is. This feature enables support for directly represented const arguments without the macro. - [macroless_const_item_generic_const_args]. For a version of this feature that works for const arguments as the right hand side of a const item. @@ -39,13 +39,13 @@ trait Bar { struct Baz; impl Bar for Baz { - const VAL: usize = core::direct_const_arg!(2); - const VAL2: usize = core::direct_const_arg!(const { Self::VAL * 2 }); + const VAL: usize = core::gca!(2); + const VAL2: usize = core::gca!(const { Self::VAL * 2 }); } struct Foo { - arr1: [usize; core::direct_const_arg!(B::VAL)], - arr2: [usize; core::direct_const_arg!(B::VAL2)], + arr1: [usize; core::gca!(B::VAL)], + arr2: [usize; core::gca!(B::VAL2)], } ``` @@ -66,8 +66,8 @@ struct Baz; impl Bar for Baz { // note these still need a macro, macroless for these is `macroless_const_item_generic_const_args` - const VAL: usize = core::direct_const_arg!(2); - const VAL2: usize = core::direct_const_arg!(const { Self::VAL * 2 }); + const VAL: usize = core::gca!(2); + const VAL2: usize = core::gca!(const { Self::VAL * 2 }); } struct Foo { diff --git a/src/doc/unstable-book/src/language-features/min-generic-const-args.md b/src/doc/unstable-book/src/language-features/min-generic-const-args.md index 0d33af9092cf6..920bc0e36c1ba 100644 --- a/src/doc/unstable-book/src/language-features/min-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/min-generic-const-args.md @@ -23,36 +23,36 @@ Related features: [macroless_generic_const_args], [generic_const_args], [generic [generic_const_args]: generic-const-args.md [generic_const_items]: generic-const-items.md -## `direct_const_arg!` macro +## `gca!` macro -This feature introduces a new macro: `direct_const_arg!`. +This feature introduces a new macro: `gca!`. When an expression is used as a generic argument, it is typically lowered as an "anon const", which is an expression -that is opaque to the type system and cannot contain generics. Using `direct_const_arg!` instead represents the +that is opaque to the type system and cannot contain generics. Using `gca!` instead represents the expression "directly", i.e. without an anon const, in a way that is visible to the type system. -(Note that plain paths to generic parameters are always represented directly, without `direct_const_arg!`, as this +(Note that plain paths to generic parameters are always represented directly, without `gca!`, as this already works on stable) -See [macroless_generic_const_args] as a feature to disable the requirement of writing `direct_const_arg!`. +See [macroless_generic_const_args] as a feature to disable the requirement of writing `gca!`. [macroless_generic_const_args]: macroless-generic-const-args.md ## direct const items -This feature introduces a new item kind: consts with a `direct_const_arg!` right-hand side. +This feature introduces a new item kind: consts with a `gca!` right-hand side. Constants with a direct right-hand side are allowed to be used in type contexts, e.g.: ```compile_fail #![allow(incomplete_features)] #![feature(min_generic_const_args)] -const X: usize = core::direct_const_arg!(1); +const X: usize = core::gca!(1); const Y: usize = 1; struct Foo { - good_arr: [(); core::direct_const_arg!(X)], // Allowed - bad_arr: [(); core::direct_const_arg!(Y)], // Will not compile + good_arr: [(); core::gca!(X)], // Allowed + bad_arr: [(); core::gca!(Y)], // Will not compile } ``` @@ -72,13 +72,13 @@ trait Bar { struct Baz; impl Bar for Baz { - const VAL: usize = core::direct_const_arg!(2); - const VAL2: usize = core::direct_const_arg!(const { Self::VAL * 2 }); + const VAL: usize = core::gca!(2); + const VAL2: usize = core::gca!(const { Self::VAL * 2 }); } struct Foo { - arr1: [usize; core::direct_const_arg!(B::VAL)], - arr2: [usize; core::direct_const_arg!(B::VAL2)], + arr1: [usize; core::gca!(B::VAL)], + arr2: [usize; core::gca!(B::VAL2)], } ``` @@ -122,7 +122,7 @@ const fn inc(val: usize) -> usize { val + 1 } -const INC: usize = core::direct_const_arg!(const { inc(VAL) }); +const INC: usize = core::gca!(const { inc(VAL) }); const ARR: [usize; INC] = [0; INC]; ``` diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index c8ee7c5a1034f..baff6a99fc9e0 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -539,7 +539,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { | TyKind::Pat(..) | TyKind::FieldOf(..) | TyKind::View(..) - | TyKind::DirectConstArg(..) + | TyKind::GcaMacro(..) // unused | TyKind::CVarArgs diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index 3d4645f72fce3..d2045c1346ee5 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -248,7 +248,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) - | ast::ExprKind::DirectConstArg(..) + | ast::ExprKind::GcaMacro(..) | ast::ExprKind::Err(_) | ast::ExprKind::Dummy | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)), diff --git a/src/tools/clippy/tests/ui/crashes/mgca-16691.rs b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs index 7e45f96fa9a9a..554528905fc85 100644 --- a/src/tools/clippy/tests/ui/crashes/mgca-16691.rs +++ b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs @@ -2,6 +2,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: usize; @@ -9,7 +11,7 @@ trait Trait { } impl Trait for () { - const N: usize = core::direct_const_arg!(3); + const N: usize = gca!(3); fn process() { const N: usize = <()>::N; _ = 0..Self::N; diff --git a/src/tools/rustfmt/src/expr.rs b/src/tools/rustfmt/src/expr.rs index f0e56ffb8ea1a..48f17fb0fd1a8 100644 --- a/src/tools/rustfmt/src/expr.rs +++ b/src/tools/rustfmt/src/expr.rs @@ -430,7 +430,7 @@ pub(crate) fn format_expr( | ast::ExprKind::IncludedBytes(..) | ast::ExprKind::OffsetOf(..) | ast::ExprKind::UnsafeBinderCast(..) - | ast::ExprKind::DirectConstArg(..) => { + | ast::ExprKind::GcaMacro(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not totally // impossible for rustfmt to come across one of these nodes when formatting a file. diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index e2c92e58062ae..d119cd50c846a 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -1043,7 +1043,7 @@ impl Rewrite for ast::Ty { result.push_str(&rewrite); Ok(result) } - ast::TyKind::Pat(..) | ast::TyKind::View(..) | ast::TyKind::DirectConstArg(..) => { + ast::TyKind::Pat(..) | ast::TyKind::View(..) | ast::TyKind::GcaMacro(..) => { // These don't normally occur in the AST because macros aren't expanded. However, // rustfmt tries to parse macro arguments when formatting macros, so it's not // totally impossible for rustfmt to come across these nodes when formatting a file. diff --git a/src/tools/rustfmt/src/utils.rs b/src/tools/rustfmt/src/utils.rs index 6f9fa7ff7024f..f7933ac52f75c 100644 --- a/src/tools/rustfmt/src/utils.rs +++ b/src/tools/rustfmt/src/utils.rs @@ -562,7 +562,7 @@ pub(crate) fn is_block_expr(context: &RewriteContext<'_>, expr: &ast::Expr, repr | ast::ExprKind::Unary(_, ref expr) | ast::ExprKind::Try(ref expr) | ast::ExprKind::Yield(YieldKind::Prefix(Some(ref expr))) - | ast::ExprKind::DirectConstArg(ref expr) => is_block_expr(context, expr, repr), + | ast::ExprKind::GcaMacro(ref expr) => is_block_expr(context, expr, repr), ast::ExprKind::Closure(ref closure) => is_block_expr(context, &closure.body, repr), // This can only be a string lit ast::ExprKind::Lit(_) => { diff --git a/src/tools/rustfmt/tests/source/direct_const_arg.rs b/src/tools/rustfmt/tests/source/direct_const_arg.rs deleted file mode 100644 index 6486d782cc1f5..0000000000000 --- a/src/tools/rustfmt/tests/source/direct_const_arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -// direct_const_arg! is a built-in macro relevant to min_generic_const_args; its contents should be -// formatted as if its contents were passed through unchanged (the macro changes the semantics of -// the contained expression, the syntax is unchanged) - -#![feature(min_generic_const_args)] - -trait Trait { - #[rustc_always_gca] - const TYPE_CONST: usize; -} - -struct S; - -fn parsed_as_expr_kind(_: S<{ core::direct_const_arg!( T :: TYPE_CONST ) }>) {} -fn parsed_as_ty_kind(_: S< core::direct_const_arg!( T :: TYPE_CONST ) >) {} diff --git a/src/tools/rustfmt/tests/source/gca.rs b/src/tools/rustfmt/tests/source/gca.rs new file mode 100644 index 0000000000000..ab394c21b8b32 --- /dev/null +++ b/src/tools/rustfmt/tests/source/gca.rs @@ -0,0 +1,17 @@ +// gca! is a built-in macro relevant to min_generic_const_args; its contents should be formatted as +// if its contents were passed through unchanged (the macro changes the semantics of the contained +// expression, the syntax is unchanged) + +#![feature(min_generic_const_args)] + +use std::gca; + +trait Trait { + #[rustc_always_gca] + const TYPE_CONST: usize; +} + +struct S; + +fn parsed_as_expr_kind(_: S<{ gca!( T :: TYPE_CONST ) }>) {} +fn parsed_as_ty_kind(_: S< gca!( T :: TYPE_CONST ) >) {} diff --git a/src/tools/rustfmt/tests/target/direct_const_arg.rs b/src/tools/rustfmt/tests/target/direct_const_arg.rs deleted file mode 100644 index 94a6c864b78ef..0000000000000 --- a/src/tools/rustfmt/tests/target/direct_const_arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -// direct_const_arg! is a built-in macro relevant to min_generic_const_args; its contents should be -// formatted as if its contents were passed through unchanged (the macro changes the semantics of -// the contained expression, the syntax is unchanged) - -#![feature(min_generic_const_args)] - -trait Trait { - #[rustc_always_gca] - const TYPE_CONST: usize; -} - -struct S; - -fn parsed_as_expr_kind(_: S<{ core::direct_const_arg!(T::TYPE_CONST) }>) {} -fn parsed_as_ty_kind(_: S) {} diff --git a/src/tools/rustfmt/tests/target/gca.rs b/src/tools/rustfmt/tests/target/gca.rs new file mode 100644 index 0000000000000..8110bb0d2c827 --- /dev/null +++ b/src/tools/rustfmt/tests/target/gca.rs @@ -0,0 +1,17 @@ +// gca! is a built-in macro relevant to min_generic_const_args; its contents should be formatted as +// if its contents were passed through unchanged (the macro changes the semantics of the contained +// expression, the syntax is unchanged) + +#![feature(min_generic_const_args)] + +use std::gca; + +trait Trait { + #[rustc_always_gca] + const TYPE_CONST: usize; +} + +struct S; + +fn parsed_as_expr_kind(_: S<{ gca!(T::TYPE_CONST) }>) {} +fn parsed_as_ty_kind(_: S) {} diff --git a/tests/crashes/138009.rs b/tests/crashes/138009.rs index 15c34a848e05f..494e3fb827ddb 100644 --- a/tests/crashes/138009.rs +++ b/tests/crashes/138009.rs @@ -1,6 +1,9 @@ //@ known-bug: #138009 #![feature(min_generic_const_args)] + +use std::gca; + #[repr(simd)] -struct T([isize; core::direct_const_arg!(N)]); +struct T([isize; gca!(N)]); static X: T = T(); diff --git a/tests/crashes/149809.rs b/tests/crashes/149809.rs index c2392a9c41eb2..b1172b72b17cd 100644 --- a/tests/crashes/149809.rs +++ b/tests/crashes/149809.rs @@ -1,12 +1,16 @@ //@ known-bug: #149809 #![feature(min_generic_const_args)] #![feature(inherent_associated_types)] + +use std::gca; + struct Qux<'a> { x: &'a (), } + impl<'a> Qux<'a> { - const LEN: usize = core::direct_const_arg!(4); - fn foo(_: [u8; core::direct_const_arg!(Qux::LEN)]) {} + const LEN: usize = gca!(4); + fn foo(_: [u8; gca!(Qux::LEN)]) {} } fn main() {} diff --git a/tests/crashes/150049.rs b/tests/crashes/150049.rs index 45289679e04ba..994e257a28d59 100644 --- a/tests/crashes/150049.rs +++ b/tests/crashes/150049.rs @@ -1,12 +1,15 @@ //@ known-bug: #150049 #![feature(min_generic_const_args)] #![feature(inherent_associated_types)] + +use std::gca; + struct Foo<'a> { x: &'a (), } impl<'a> Foo<'a> { - fn foo(_: [u8; core::direct_const_arg!(Foo::X)]) { + fn foo(_: [u8; gca!(Foo::X)]) { std::mem::transmute([4]) } } diff --git a/tests/crashes/150749.rs b/tests/crashes/150749.rs index 59d07f9860b9a..8e4e413236c82 100644 --- a/tests/crashes/150749.rs +++ b/tests/crashes/150749.rs @@ -1,12 +1,16 @@ //@ known-bug: #150749 #![feature(min_generic_const_args)] +use std::gca; + trait CollectArray { fn inner_array(); } + impl CollectArray for () { fn inner_array() { - let temp_ptr: [(); core::direct_const_arg!(Self)]; + let temp_ptr: [(); gca!(Self)]; } } + fn main() {} diff --git a/tests/debuginfo/associated-const-bindings.rs b/tests/debuginfo/associated-const-bindings.rs index 1a7ca6a5b0a95..171d457925522 100644 --- a/tests/debuginfo/associated-const-bindings.rs +++ b/tests/debuginfo/associated-const-bindings.rs @@ -13,12 +13,15 @@ #![feature(min_generic_const_args)] #![expect(unused_variables, incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: usize; } + impl Trait for () { - const N: usize = core::direct_const_arg!(101); + const N: usize = gca!(101); } fn main() { diff --git a/tests/pretty/direct-const-arg.rs b/tests/pretty/direct-const-arg.rs deleted file mode 100644 index 330c1cac024de..0000000000000 --- a/tests/pretty/direct-const-arg.rs +++ /dev/null @@ -1,10 +0,0 @@ -//@ pretty-mode:expanded -//@ pp-exact:direct-const-arg.pp -#![feature(min_generic_const_args)] - -fn f() {} - -fn main() { - f::(); - f::<{ core::direct_const_arg!(2) }>(); -} diff --git a/tests/pretty/direct-const-arg.pp b/tests/pretty/gca-macro.pp similarity index 60% rename from tests/pretty/direct-const-arg.pp rename to tests/pretty/gca-macro.pp index a76ed9a480e71..8912d790b337a 100644 --- a/tests/pretty/direct-const-arg.pp +++ b/tests/pretty/gca-macro.pp @@ -1,15 +1,14 @@ #![feature(prelude_import)] #![no_std] //@ pretty-mode:expanded -//@ pp-exact:direct-const-arg.pp +//@ pp-exact:gca-macro.pp #![feature(min_generic_const_args)] extern crate std; #[prelude_import] use ::std::prelude::rust_2015::*; +use std::gca; + fn f() {} -fn main() { - f::(); - f::<{ core::direct_const_arg! (2) }>(); -} +fn main() { f::(); f::<{ core::gca! (2) }>(); } diff --git a/tests/pretty/gca-macro.rs b/tests/pretty/gca-macro.rs new file mode 100644 index 0000000000000..248fd4424e1da --- /dev/null +++ b/tests/pretty/gca-macro.rs @@ -0,0 +1,12 @@ +//@ pretty-mode:expanded +//@ pp-exact:gca-macro.pp +#![feature(min_generic_const_args)] + +use std::gca; + +fn f() {} + +fn main() { + f::(); + f::<{ gca!(2) }>(); +} diff --git a/tests/rustdoc-html/type-const-free-in-array.rs b/tests/rustdoc-html/type-const-free-in-array.rs index 4583e20fb8998..3fd6b21e34eea 100644 --- a/tests/rustdoc-html/type-const-free-in-array.rs +++ b/tests/rustdoc-html/type-const-free-in-array.rs @@ -2,7 +2,9 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![expect(incomplete_features)] -const N: usize = core::direct_const_arg!(2); +use std::gca; + +const N: usize = gca!(2); //@ has 'foo/trait.CollectArray.html' //@ has - '//pre[@class="rust item-decl"]/code' '[A; N]' diff --git a/tests/rustdoc-html/type-const-inherent-with-body.rs b/tests/rustdoc-html/type-const-inherent-with-body.rs index a209ac47dcb0d..030ca8608a02d 100644 --- a/tests/rustdoc-html/type-const-inherent-with-body.rs +++ b/tests/rustdoc-html/type-const-inherent-with-body.rs @@ -2,10 +2,12 @@ #![feature(min_generic_const_args, macroless_generic_const_args, inherent_associated_types)] #![expect(incomplete_features)] +use std::gca; + pub struct Foo; impl Foo { - const LEN: usize = core::direct_const_arg!(4); + const LEN: usize = gca!(4); } //@ has 'foo/fn.mk_array.html' diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs index 919aba47aea28..bb5e7ad4be181 100644 --- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs +++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs @@ -5,10 +5,12 @@ inherent_associated_types )] +use std::gca; + struct OnDiskDirEntry<'a>(&'a ()); impl<'a> OnDiskDirEntry<'a> { - const LFN_FRAGMENT_LEN: i64 = core::direct_const_arg!(2); + const LFN_FRAGMENT_LEN: i64 = gca!(2); fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] { //~^ ERROR the constant `2` is not of type `usize` diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr index dcb88f77f82cd..80c477ed43f29 100644 --- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr +++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.stderr @@ -1,5 +1,5 @@ error: the constant `2` is not of type `usize` - --> $DIR/type-const-in-array-len-wrong-type.rs:13:26 + --> $DIR/type-const-in-array-len-wrong-type.rs:15:26 | LL | fn lfn_contents() -> [char; Self::LFN_FRAGMENT_LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `usize`, found `i64` diff --git a/tests/ui/associated-consts/type-const-in-array-len.rs b/tests/ui/associated-consts/type-const-in-array-len.rs index 0f53aa9dd56fe..b4cf05a618255 100644 --- a/tests/ui/associated-consts/type-const-in-array-len.rs +++ b/tests/ui/associated-consts/type-const-in-array-len.rs @@ -2,10 +2,12 @@ #![feature(min_generic_const_args, macroless_generic_const_args, inherent_associated_types)] +use std::gca; + // Test case from #138226: generic impl with multiple type parameters struct Foo(A, B); impl Foo { - const LEN: usize = core::direct_const_arg!(4); + const LEN: usize = gca!(4); fn foo() { let _ = [5; Self::LEN]; @@ -15,7 +17,7 @@ impl Foo { // Test case from #138226: generic impl with const parameter struct Bar; impl Bar { - const LEN: usize = core::direct_const_arg!(4); + const LEN: usize = gca!(4); fn bar() { let _ = [0; Self::LEN]; @@ -25,7 +27,7 @@ impl Bar { // Test case from #150960: non-generic impl with const block struct Baz; impl Baz { - const LEN: usize = core::direct_const_arg!(4); + const LEN: usize = gca!(4); fn baz() { let _ = [0; { Self::LEN }]; diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.rs b/tests/ui/associated-type-bounds/duplicate-bound-err.rs index 0d1ab691c5c7f..5dc2ad6a3a56c 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.rs @@ -4,7 +4,7 @@ #![expect(incomplete_features)] #![allow(refining_impl_trait_internal)] -use std::iter; +use std::{gca, iter}; fn rpit1() -> impl Iterator { iter::empty() @@ -55,7 +55,7 @@ trait Trait { impl Trait for () { type Gat = (); - const ASSOC: i32 = core::direct_const_arg!(3); + const ASSOC: i32 = gca!(3); fn foo() {} } @@ -63,7 +63,7 @@ impl Trait for () { impl Trait for u32 { type Gat = (); - const ASSOC: i32 = core::direct_const_arg!(4); + const ASSOC: i32 = gca!(4); fn foo() -> u32 { 42 diff --git a/tests/ui/associated-type-bounds/duplicate-bound.rs b/tests/ui/associated-type-bounds/duplicate-bound.rs index 233b1ffb6ce76..68f9c373cd49c 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound.rs @@ -5,8 +5,8 @@ #![expect(incomplete_features)] #![allow(dead_code, refining_impl_trait_internal, type_alias_bounds)] -use std::iter; use std::mem::ManuallyDrop; +use std::{gca, iter}; struct Si1> { f: T, @@ -198,7 +198,7 @@ trait Trait { impl Trait for () { type Gat = (); - const ASSOC: i32 = core::direct_const_arg!(3); + const ASSOC: i32 = gca!(3); fn foo() {} } diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs index 63fa8eff1473b..8a0d14554d201 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs @@ -1,8 +1,8 @@ struct S; impl S { - const LEN: usize = core::direct_const_arg!(1); + const LEN: usize = std::gca!(1); //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] - //~| ERROR: expected expression, found `direct_const_arg!()` + //~| ERROR: expected expression, found `gca!()` fn arr() { [8; Self::LEN] } diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr index 421c2a83a19b9..9ee66984529de 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr @@ -1,18 +1,18 @@ error[E0658]: use of unstable library feature `min_generic_const_args` --> $DIR/type-const-inherent-impl-normalize.rs:3:24 | -LL | const LEN: usize = core::direct_const_arg!(1); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | const LEN: usize = std::gca!(1); + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant +error: expected expression, found `gca!()` constant --> $DIR/type-const-inherent-impl-normalize.rs:3:24 | -LL | const LEN: usize = core::direct_const_arg!(1); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const LEN: usize = std::gca!(1); + | ^^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs index ffc605c0d51e0..378af46decb96 100644 --- a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs @@ -10,12 +10,14 @@ #![feature(min_generic_const_args, inherent_associated_types, generic_const_items)] +use std::gca; + struct Parent<'a> { a: &'a str, } impl<'a> Parent<'a> { - const CT: usize = core::direct_const_arg!(0); + const CT: usize = gca!(0); } fn check() diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr index e77a0994fc2db..3cdd01182f84c 100644 --- a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find type `T` in this scope - --> $DIR/resolved-region-var-max-universe.rs:23:23 + --> $DIR/resolved-region-var-max-universe.rs:25:23 | LL | [(); Parent::CT::]:, | ^ not found in this scope diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs index 88c1212fe2c93..a8d66c950a064 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs @@ -4,6 +4,8 @@ #![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] +use std::gca; + trait Trait0: Parent0 + Parent0 {} trait Parent0 { #[rustc_always_gca] @@ -23,7 +25,7 @@ trait Parent2 { const C: &'static str; } -fn take1(_: impl Trait1) {} +fn take1(_: impl Trait1) {} //~^ ERROR ambiguous associated constant `C` in bounds of `Trait1` fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr index 5ed843de96074..88f356d1297bc 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.stderr @@ -1,5 +1,5 @@ error[E0222]: ambiguous associated constant `K` in bounds of `Trait0` - --> $DIR/ambiguity.rs:13:25 + --> $DIR/ambiguity.rs:15:25 | LL | const K: (); | ----------- @@ -17,7 +17,7 @@ LL | fn take0(_: impl Trait0) {} T: Parent0::K = const {} error[E0222]: ambiguous associated constant `C` in bounds of `Trait1` - --> $DIR/ambiguity.rs:26:25 + --> $DIR/ambiguity.rs:28:25 | LL | const C: i32; | ------------ ambiguous `C` from `Parent1` @@ -25,8 +25,8 @@ LL | const C: i32; LL | const C: &'static str; | --------------------- ambiguous `C` from `Parent2` ... -LL | fn take1(_: impl Trait1) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ambiguous associated constant `C` +LL | fn take1(_: impl Trait1) {} + | ^^^^^^^^^^^^^^^^^ ambiguous associated constant `C` | = help: consider introducing a new type parameter `T` and adding `where` constraints: where diff --git a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs index 598924316590c..d7e5ce3229dfd 100644 --- a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs @@ -2,6 +2,8 @@ #![feature(min_generic_const_args)] #![allow(unused, incomplete_features)] +use std::gca; + pub trait Foo { #[rustc_always_gca] const N: usize; @@ -10,7 +12,7 @@ pub trait Foo { pub struct Bar; impl Foo for Bar { - const N: usize = core::direct_const_arg!(3); + const N: usize = gca!(3); } fn foo>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs index a6c86ce4b867d..f6fa6ece02ad9 100644 --- a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs +++ b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs @@ -8,6 +8,8 @@ #![feature(adt_const_params, min_generic_const_args, unsized_const_params)] #![allow(incomplete_features)] +use std::gca; + trait Trait: SuperTrait { type N; type Q; @@ -23,6 +25,6 @@ trait SuperTrait { fn take0(_: impl Trait) {} -fn take1(_: impl Trait) {} +fn take1(_: impl Trait) {} fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/coherence.rs b/tests/ui/const-generics/associated-const-bindings/coherence.rs index aa26c6f4cd18f..d5764bfc93b61 100644 --- a/tests/ui/const-generics/associated-const-bindings/coherence.rs +++ b/tests/ui/const-generics/associated-const-bindings/coherence.rs @@ -1,12 +1,14 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + pub trait IsVoid { #[rustc_always_gca] const IS_VOID: bool; } impl IsVoid for () { - const IS_VOID: bool = core::direct_const_arg!(true); + const IS_VOID: bool = gca!(true); } pub trait Maybe {} diff --git a/tests/ui/const-generics/associated-const-bindings/coherence.stderr b/tests/ui/const-generics/associated-const-bindings/coherence.stderr index ca1c968801243..519c95719a732 100644 --- a/tests/ui/const-generics/associated-const-bindings/coherence.stderr +++ b/tests/ui/const-generics/associated-const-bindings/coherence.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Maybe` for type `()` - --> $DIR/coherence.rs:14:1 + --> $DIR/coherence.rs:16:1 | LL | impl Maybe for () {} | ----------------- first implementation here diff --git a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs index a472118e51a82..7f7aec0ebcdd5 100644 --- a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs +++ b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs @@ -7,9 +7,11 @@ #![feature(min_generic_const_args, associated_type_defaults)] #![allow(incomplete_features)] +use std::gca; + pub trait TraitA { #[rustc_always_gca] - const K: u8 = core::direct_const_arg!(0); + const K: u8 = gca!(0); } pub trait TraitB {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs index 3a896b6b2e1fa..cddb6eb88e937 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs @@ -6,6 +6,8 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait: SuperTrait { #[rustc_always_gca] const K: usize; @@ -24,7 +26,7 @@ trait Bound { } impl Bound for () { - const N: usize = core::direct_const_arg!(10); + const N: usize = gca!(10); } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs index a28805f87b0f8..c38431c8e1d78 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs @@ -3,13 +3,15 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: usize; } impl Trait for () { - const N: usize = core::direct_const_arg!(1); + const N: usize = gca!(1); } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr index ea781f784a9b0..82b4f7ca9ba6e 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.stderr @@ -1,5 +1,5 @@ error[E0271]: type mismatch resolving `<() as Trait>::N == 0` - --> $DIR/dyn-compat-const-mismatch.rs:16:32 + --> $DIR/dyn-compat-const-mismatch.rs:18:32 | LL | let _: &dyn Trait = &(); | ^^^ expected `0`, found `1` diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs index f957a60a78b0b..b6d67f8fd8b19 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs @@ -4,6 +4,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait X::N }> {} trait Y { @@ -12,7 +14,7 @@ trait Y { } impl Y for T { - const N: usize = core::direct_const_arg!(1); + const N: usize = gca!(1); } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr index 365bae2188b00..bfe1e213e330b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.stderr @@ -1,5 +1,5 @@ error[E0393]: the const parameter `N` must be explicitly specified - --> $DIR/dyn-compat-const-param-default-mentions-self.rs:19:16 + --> $DIR/dyn-compat-const-param-default-mentions-self.rs:21:16 | LL | trait X::N }> {} | -------------------------------------------- const parameter `N` must be specified for this diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs index 16fb2af1c4b54..2d282ace5436a 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs @@ -5,13 +5,15 @@ #![feature(min_generic_const_args, generic_const_items)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: i32 where Self: Bound; } impl Trait for () { - const N: i32 = core::direct_const_arg!(0); + const N: i32 = gca!(0); } trait Bound {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr index 770e7b561fadd..38a5ec4e1a9f8 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.stderr @@ -1,16 +1,16 @@ error[E0277]: the trait bound `(): Bound` is not satisfied - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:22:32 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:24:32 | LL | let _: &dyn Trait = &(); | ^^^ the trait `Bound` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:17:1 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:19:1 | LL | trait Bound {} | ^^^^^^^^^^^ note: required by a bound in `Trait::N` - --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:10:30 + --> $DIR/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs:12:30 | LL | trait Trait { LL | #[rustc_always_gca] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs index b2f0b25041056..53746231f46d7 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs @@ -13,6 +13,8 @@ )] #![expect(incomplete_features)] +use std::gca; + trait A { type Ty: std::marker::ConstParamTy_; #[rustc_always_gca] @@ -21,7 +23,7 @@ trait A { impl A for () { type Ty = i32; - const CT: i32 = core::direct_const_arg!(0); + const CT: i32 = gca!(0); } fn main() { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr index e3873eae6f04f..50faeaf4eed9e 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.stderr @@ -1,11 +1,11 @@ error: type annotations needed for the literal - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:34:33 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:36:33 | LL | let _: dyn A; | ^ error: type annotations needed for the literal - --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:36:34 + --> $DIR/dyn-compat-self-const-projections-in-assoc-const-ty.rs:38:34 | LL | let _: &dyn A = &(); | ^ diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs index 148f5b8654af0..7cd8d6ef36302 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs @@ -14,6 +14,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: usize; @@ -22,7 +24,7 @@ trait Trait { } impl Trait for u8 { - const N: usize = core::direct_const_arg!(2); + const N: usize = gca!(2); fn process(&self, [x, y]: [u8; Self::N]) -> [u8; Self::N] { [self * x, self + y] @@ -30,7 +32,7 @@ impl Trait for u8 { } impl Trait for [u8; N] { - const N: usize = core::direct_const_arg!(N); + const N: usize = gca!(N); fn process(&self, other: [u8; Self::N]) -> [u8; Self::N] { let mut result = [0; _]; diff --git a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs index 7b05da5623b10..0b4e871ceb5c6 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs @@ -4,13 +4,15 @@ #![allow(incomplete_features)] #![deny(dead_code)] +use std::gca; + trait Tr { #[rustc_always_gca] const I: i32; } impl Tr for () { - const I: i32 = core::direct_const_arg!(1); + const I: i32 = gca!(1); } fn foo() -> impl Tr {} @@ -23,20 +25,22 @@ trait Tr2 { } impl Tr2 for () { - const J: i32 = core::direct_const_arg!(1); - const K: i32 = core::direct_const_arg!(1); + const J: i32 = gca!(1); + const K: i32 = gca!(1); } fn foo2() -> impl Tr2 {} mod t { + use std::gca; + pub trait Tr3 { #[rustc_always_gca] const L: i32; } impl Tr3 for () { - const L: i32 = core::direct_const_arg!(1); + const L: i32 = gca!(1); } } diff --git a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs index 01589ac645b05..3027357d0fb7e 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args, generic_const_items)] #![expect(incomplete_features)] +use std::gca; + // Regression test for #133066 where we would try to evaluate `<() as Foo>::ASSOC<_>` even // though it contained inference variables, which would cause ICEs. @@ -12,7 +14,7 @@ trait Foo { } impl Foo for () { - const ASSOC: u32 = core::direct_const_arg!(N); + const ASSOC: u32 = gca!(N); } fn bar = 10>>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs index 818609486d20c..9ef5c902062e3 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs @@ -1,13 +1,15 @@ #![feature(generic_const_items, min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Foo { #[rustc_always_gca] const ASSOC: u32; } impl Foo for () { - const ASSOC: u32 = core::direct_const_arg!(N); + const ASSOC: u32 = gca!(N); } fn bar = { N }>>() {} diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr index e879cafdc86ea..1eaa635e13532 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.stderr @@ -1,11 +1,11 @@ error: the constant `N` is not of type `u32` - --> $DIR/mismatched-types-with-generic-in-ace.rs:13:29 + --> $DIR/mismatched-types-with-generic-in-ace.rs:15:29 | LL | fn bar = { N }>>() {} | ^^^^^^^^^^^^^^^^ expected `u32`, found `u64` | note: required by a const generic parameter in `Foo::ASSOC` - --> $DIR/mismatched-types-with-generic-in-ace.rs:6:17 + --> $DIR/mismatched-types-with-generic-in-ace.rs:8:17 | LL | trait Foo { LL | #[rustc_always_gca] @@ -13,13 +13,13 @@ LL | const ASSOC: u32; | ^^^^^^^^^^^^ required by this const generic parameter in `Foo::ASSOC` error: the constant `10` is not of type `u32` - --> $DIR/mismatched-types-with-generic-in-ace.rs:17:5 + --> $DIR/mismatched-types-with-generic-in-ace.rs:19:5 | LL | bar::<10_u64, ()>(); | ^^^^^^^^^^^^^^^^^^^ expected `u32`, found `u64` | note: required by a const generic parameter in `Foo::ASSOC` - --> $DIR/mismatched-types-with-generic-in-ace.rs:6:17 + --> $DIR/mismatched-types-with-generic-in-ace.rs:8:17 | LL | trait Foo { LL | #[rustc_always_gca] diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs index d5682e7de1294..0180aa4694f67 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs @@ -4,6 +4,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const CT: bool; @@ -14,7 +16,7 @@ trait Bound { const N: u32; } impl Bound for () { - const N: u32 = core::direct_const_arg!(0); + const N: u32 = gca!(0); } fn f() { diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr index f921e5893b51e..ddcf1d00dfbd8 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.stderr @@ -1,17 +1,17 @@ error: the constant `0` is not of type `bool` - --> $DIR/wf-mismatch-3.rs:24:20 + --> $DIR/wf-mismatch-3.rs:26:20 | LL | fn g(_: impl Trait::N }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `u32` | note: required by a const generic parameter in `g` - --> $DIR/wf-mismatch-3.rs:24:20 + --> $DIR/wf-mismatch-3.rs:26:20 | LL | fn g(_: impl Trait::N }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `g` error: the constant `0` is not of type `bool` - --> $DIR/wf-mismatch-3.rs:21:12 + --> $DIR/wf-mismatch-3.rs:23:12 | LL | let _: dyn Trait::N }>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `bool`, found `u32` diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index 3b53adb07a2b9..0bbfe0626470d 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -1,13 +1,13 @@ error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:31:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:33:9 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | note: required by a const generic parameter in `free` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:26:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:28:9 | -LL | fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { +LL | fn free() -> ([(); N], [(); gca!(FREE::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `free` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -15,7 +15,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ error[E0271]: type mismatch resolving `FREE<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:37:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:39:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^ expected `2`, found `10` @@ -24,16 +24,16 @@ LL | let (mut arr, mut arr_with_weird_len) = free(); found constant `10` error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:48:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:50:9 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | = note: cannot satisfy `::PROJ<_> == 10` note: required by a const generic parameter in `proj` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:43:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:45:9 | -LL | fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { +LL | fn proj() -> ([(); N], [(); gca!(::PROJ::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `proj` help: consider giving this pattern a type, where the value of const parameter `N` is specified | @@ -41,7 +41,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ error[E0271]: type mismatch resolving `::PROJ<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:54:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:56:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^ expected `2`, found `10` diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index 8ee278af6ef56..a178a0f0d0b95 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -12,6 +12,8 @@ )] #![expect(incomplete_features)] +use std::gca; + const FREE: usize = 10; trait Trait { @@ -23,7 +25,7 @@ impl Trait for S { const PROJ: usize = 10; } -fn free() -> ([(); N], [(); core::direct_const_arg!(FREE::)]) { +fn free() -> ([(); N], [(); gca!(FREE::)]) { loop {} } @@ -40,7 +42,7 @@ fn test_free_mismatch() { arr = [(); 10]; } -fn proj() -> ([(); N], [(); core::direct_const_arg!(::PROJ::)]) { +fn proj() -> ([(); N], [(); gca!(::PROJ::)]) { loop {} } diff --git a/tests/ui/const-generics/gca/assoc-const.rs b/tests/ui/const-generics/gca/assoc-const.rs index 8a8d1b52e7e5a..316084e5b8cf9 100644 --- a/tests/ui/const-generics/gca/assoc-const.rs +++ b/tests/ui/const-generics/gca/assoc-const.rs @@ -2,12 +2,14 @@ //@ compile-flags: -Znext-solver #![feature(min_generic_const_args, generic_const_args)] +use std::gca; + trait Trait { const ASSOC: usize; } impl Trait for T { - const ASSOC: usize = core::direct_const_arg!(T::RIGID); + const ASSOC: usize = gca!(T::RIGID); } trait Other { @@ -15,8 +17,7 @@ trait Other { } fn foo() { - let a: [(); core::direct_const_arg!(::ASSOC)] = - [(); core::direct_const_arg!(T::RIGID)]; + let a: [(); gca!(::ASSOC)] = [(); gca!(T::RIGID)]; } fn main() {} diff --git a/tests/ui/const-generics/gca/basic-different-definitions.rs b/tests/ui/const-generics/gca/basic-different-definitions.rs index a80e50a6cb9e9..215b28c985113 100644 --- a/tests/ui/const-generics/gca/basic-different-definitions.rs +++ b/tests/ui/const-generics/gca/basic-different-definitions.rs @@ -6,10 +6,12 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] +use std::gca; + const ADD1: usize = N + 1; const INC: usize = N + 1; -const ARR: [(); core::direct_const_arg!(ADD1::<0>)] = [(); core::direct_const_arg!(INC::<0>)]; +const ARR: [(); gca!(ADD1::<0>)] = [(); gca!(INC::<0>)]; fn main() {} diff --git a/tests/ui/const-generics/gca/basic.rs b/tests/ui/const-generics/gca/basic.rs index 55712a80f2195..c6158023a1be5 100644 --- a/tests/ui/const-generics/gca/basic.rs +++ b/tests/ui/const-generics/gca/basic.rs @@ -6,10 +6,12 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] +use std::gca; + const ADD1: usize = N + 1; -const INC: usize = core::direct_const_arg!(ADD1::); +const INC: usize = gca!(ADD1::); -const ARR: [(); core::direct_const_arg!(ADD1::<0>)] = [(); core::direct_const_arg!(INC::<0>)]; +const ARR: [(); gca!(ADD1::<0>)] = [(); gca!(INC::<0>)]; fn main() {} diff --git a/tests/ui/const-generics/gca/coherence-ok.rs b/tests/ui/const-generics/gca/coherence-ok.rs index 5feebd2b2a6fb..4ea66eb8e290d 100644 --- a/tests/ui/const-generics/gca/coherence-ok.rs +++ b/tests/ui/const-generics/gca/coherence-ok.rs @@ -3,13 +3,15 @@ #![feature(generic_const_items, min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] +use std::gca; + // computing different values with the same const item should be fine const ADD1: usize = N + 1; trait Trait {} -impl Trait for [(); core::direct_const_arg!(ADD1::<1>)] {} -impl Trait for [(); core::direct_const_arg!(ADD1::<2>)] {} +impl Trait for [(); gca!(ADD1::<1>)] {} +impl Trait for [(); gca!(ADD1::<2>)] {} fn main() {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs index 72babbcfe0401..9cb0891127dd8 100644 --- a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs @@ -4,6 +4,8 @@ // `const FOO: usize = N + 1;` #![feature(generic_const_args, min_generic_const_args, generic_const_items)] -const FOO: usize = core::direct_const_arg!(const { N + 1 }); //~ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead +use std::gca; + +const FOO: usize = gca!(const { N + 1 }); //~ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead fn main() {} diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr index 1b98cd734afd2..93d4c1ce76e39 100644 --- a/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.stderr @@ -1,8 +1,8 @@ error: generic parameters in const blocks are not allowed; use a named `const` item instead - --> $DIR/gca-anon-const-rejected.rs:7:68 + --> $DIR/gca-anon-const-rejected.rs:9:49 | -LL | const FOO: usize = core::direct_const_arg!(const { N + 1 }); - | ^ +LL | const FOO: usize = gca!(const { N + 1 }); + | ^ | = help: consider factoring the expression into a `type const` item and use it as the const argument instead diff --git a/tests/ui/const-generics/gca/direct-const-arg-fn-call.rs b/tests/ui/const-generics/gca/gca-macro-fn-call.rs similarity index 100% rename from tests/ui/const-generics/gca/direct-const-arg-fn-call.rs rename to tests/ui/const-generics/gca/gca-macro-fn-call.rs diff --git a/tests/ui/const-generics/gca/direct-const-arg-fn-call.stderr b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr similarity index 81% rename from tests/ui/const-generics/gca/direct-const-arg-fn-call.stderr rename to tests/ui/const-generics/gca/gca-macro-fn-call.stderr index b73cc02dae915..1399bcb1dee92 100644 --- a/tests/ui/const-generics/gca/direct-const-arg-fn-call.stderr +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr @@ -1,29 +1,29 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/direct-const-arg-fn-call.rs:35:23 + --> $DIR/gca-macro-fn-call.rs:35:23 | LL | fn bad(_: FieldName<{ FieldName::len() }>) {} | ^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/direct-const-arg-fn-call.rs:44:31 + --> $DIR/gca-macro-fn-call.rs:44:31 | LL | fn bad_tracing(_: FieldName<{ FieldName::len_of("id") }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/direct-const-arg-fn-call.rs:61:23 + --> $DIR/gca-macro-fn-call.rs:61:23 | LL | fn bad_union(_: Tag<{ Tag::width() }>) {} | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/direct-const-arg-fn-call.rs:70:28 + --> $DIR/gca-macro-fn-call.rs:70:28 | LL | fn bad_prim(_: FieldName<{ u32::from_str_radix("10", 10) }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/direct-const-arg-fn-call.rs:81:31 + --> $DIR/gca-macro-fn-call.rs:81:31 | LL | fn bad_foreign(_: FieldName<{ Opaque::foo() }>) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.rs b/tests/ui/const-generics/gca/non-type-equality-fail.rs index e058648e3da54..1ea34829c6c6a 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.rs +++ b/tests/ui/const-generics/gca/non-type-equality-fail.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args, generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait { const PROJECTED_A: usize; const PROJECTED_B: usize; @@ -27,14 +29,13 @@ const FREE_B: usize = 1; struct Struct; fn f() { - let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = - Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; + let _: Struct<{ gca!( as Trait>::PROJECTED_A) }> = + Struct::<{ gca!( as Trait>::PROJECTED_B) }>; //~^ ERROR mismatched types } fn g() { - let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = - Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; + let _: Struct<{ gca!(T::PROJECTED_A) }> = Struct::<{ gca!(T::PROJECTED_B) }>; //~^ ERROR mismatched types } diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.stderr b/tests/ui/const-generics/gca/non-type-equality-fail.stderr index 28557d76d84e5..413ccf59a3290 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.stderr +++ b/tests/ui/const-generics/gca/non-type-equality-fail.stderr @@ -1,21 +1,21 @@ error[E0308]: mismatched types - --> $DIR/non-type-equality-fail.rs:31:9 + --> $DIR/non-type-equality-fail.rs:33:9 | -LL | let _: Struct<{ core::direct_const_arg!( as Trait>::PROJECTED_A) }> = - | --------------------------------------------------------------------------------- expected due to this -LL | Struct::<{ core::direct_const_arg!( as Trait>::PROJECTED_B) }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` +LL | let _: Struct<{ gca!( as Trait>::PROJECTED_A) }> = + | -------------------------------------------------------------- expected due to this +LL | Struct::<{ gca!( as Trait>::PROJECTED_B) }>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected ` as Trait>::PROJECTED_A`, found ` as Trait>::PROJECTED_B` | = note: expected struct `Struct< as Trait>::PROJECTED_A>` found struct `Struct< as Trait>::PROJECTED_B>` error[E0308]: mismatched types - --> $DIR/non-type-equality-fail.rs:37:9 + --> $DIR/non-type-equality-fail.rs:38:47 | -LL | let _: Struct<{ core::direct_const_arg!(T::PROJECTED_A) }> = - | --------------------------------------------------- expected due to this -LL | Struct::<{ core::direct_const_arg!(T::PROJECTED_B) }>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` +LL | let _: Struct<{ gca!(T::PROJECTED_A) }> = Struct::<{ gca!(T::PROJECTED_B) }>; + | -------------------------------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `::PROJECTED_A`, found `::PROJECTED_B` + | | + | expected due to this | = note: expected struct `Struct<::PROJECTED_A>` found struct `Struct<::PROJECTED_B>` diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.rs b/tests/ui/const-generics/gca/rhs-but-not-root.rs index 2c5f1e050a3fe..4f355c84e4875 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/gca/rhs-but-not-root.rs @@ -4,9 +4,11 @@ #![feature(generic_const_args)] #![expect(incomplete_features)] +use std::gca; + // Anon consts must be the root of the RHS to be GCA. -const FOO: usize = core::direct_const_arg!(ID::); +const FOO: usize = gca!(ID::); //~^ ERROR generic parameters in const blocks are not allowed; use a named `const` item instead -const ID: usize = core::direct_const_arg!(N); +const ID: usize = gca!(N); fn main() {} diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.stderr b/tests/ui/const-generics/gca/rhs-but-not-root.stderr index 6b2e5d61112d9..d34d7f6b51a74 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.stderr +++ b/tests/ui/const-generics/gca/rhs-but-not-root.stderr @@ -1,8 +1,8 @@ error: generic parameters in const blocks are not allowed; use a named `const` item instead - --> $DIR/rhs-but-not-root.rs:8:73 + --> $DIR/rhs-but-not-root.rs:10:54 | -LL | const FOO: usize = core::direct_const_arg!(ID::); - | ^ +LL | const FOO: usize = gca!(ID::); + | ^ | = help: consider factoring the expression into a `type const` item and use it as the const argument instead diff --git a/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.rs b/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.rs index f6415412e0df4..85be63fd83b59 100644 --- a/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.rs +++ b/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.rs @@ -1,7 +1,7 @@ // Regression test for https://github.com/rust-lang/rust/issues/156729 // // When a generic parameter is used in a const operation, the diagnostic should -// suggest creating a `direct_const_arg!` item as an alternative to `generic_const_exprs`. +// suggest creating a `gca!` item as an alternative to `generic_const_exprs`. use std::mem::size_of; diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.rs b/tests/ui/const-generics/gca/wf-inherentimpl.rs index c0a7e7f930877..8248c7b01832a 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.rs +++ b/tests/ui/const-generics/gca/wf-inherentimpl.rs @@ -5,10 +5,11 @@ #![feature(inherent_associated_types)] #![feature(generic_const_args, min_generic_const_args)] //[old]~^ ERROR `generic_const_args` requires -Znext-solver=globally to be enabled +use std::gca; struct Foo; impl Foo { const SIZE: usize = { todo!() }; - fn to_bytes() -> [u8; core::direct_const_arg!(Self::SIZE)] { + fn to_bytes() -> [u8; gca!(Self::SIZE)] { todo!() } } diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs index 689a981e5469b..b4401b182be4e 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs @@ -1,4 +1,6 @@ #![feature(min_generic_const_args)] #![allow(incomplete_features)] -pub const NON_LOCAL_CONST: char = core::direct_const_arg!('a'); +use std::gca; + +pub const NON_LOCAL_CONST: char = gca!('a'); diff --git a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs index be91b0a5933bd..97edbef7df10d 100644 --- a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs +++ b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs @@ -10,15 +10,17 @@ const_param_ty_trait )] +use std::gca; + struct ThreeTypes(T1, T2, T3); impl ThreeTypes { - const INHERENT: [T3; 0] = core::direct_const_arg!([]); + const INHERENT: [T3; 0] = gca!([]); } struct Struct; -fn f() -> Struct<{ core::direct_const_arg!(ThreeTypes::::INHERENT) }> { +fn f() -> Struct<{ gca!(ThreeTypes::::INHERENT) }> { Struct } diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 34fca58ff4e00..32714ca551fbc 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -1,6 +1,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] #![expect(incomplete_features)] +use std::gca; + #[derive(Eq, PartialEq, std::marker::ConstParamTy)] enum Option { Some(T), @@ -26,7 +28,7 @@ fn bar() { // this on the other hand is not allowed as `N + 1` is not a legal // const argument - foo::<{ core::direct_const_arg!(Some:: { 0: N + 1 }) }>(); + foo::<{ gca!(Some:: { 0: N + 1 }) }>(); //~^ ERROR: complex const arguments must be placed inside of a `const` block // this also is not allowed as generic parameters cannot be used diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 7b1249773f0cb..0213c447b59ca 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/adt_expr_arg_simple.rs:29:54 + --> $DIR/adt_expr_arg_simple.rs:31:35 | -LL | foo::<{ core::direct_const_arg!(Some:: { 0: N + 1 }) }>(); - | ^^^^^ +LL | foo::<{ gca!(Some:: { 0: N + 1 }) }>(); + | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/adt_expr_arg_simple.rs:34:38 + --> $DIR/adt_expr_arg_simple.rs:36:38 | LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index bcd6660dc3533..3db15a2aef49c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -10,6 +10,7 @@ )] #![expect(incomplete_features)] +use std::gca; use std::marker::{ConstParamTy, ConstParamTy_, PhantomData}; #[derive(PartialEq, Eq, ConstParamTy)] @@ -17,7 +18,7 @@ struct Foo { field: T, } -const WRAP: Foo = core::direct_const_arg!(Foo:: { field: N }); +const WRAP: Foo = gca!(Foo:: { field: N }); fn main() { // What we're trying to accomplish here is winding up with an equality relation diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index f2c8a242dbcc0..78e9c0821fa88 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -6,6 +6,7 @@ #![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] #![feature(unsized_const_params, generic_const_parameter_types)] +use std::gca; use std::marker::ConstParamTy_; fn foo() -> [T; N] { @@ -21,7 +22,7 @@ trait Trait { struct S; impl Trait for S { - const LEN: usize = core::direct_const_arg!(3); + const LEN: usize = gca!(3); } fn baz::LEN]>() {} diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr index 82a9cfc86b5d7..72c2a367c7246 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -1,59 +1,59 @@ error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:30:11 + --> $DIR/array-const-arg-len-mismatch.rs:31:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:11:42 + --> $DIR/array-const-arg-len-mismatch.rs:12:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:32:11 + --> $DIR/array-const-arg-len-mismatch.rs:33:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:11:42 + --> $DIR/array-const-arg-len-mismatch.rs:12:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:34:13 + --> $DIR/array-const-arg-len-mismatch.rs:35:13 | LL | bar::<{ [] }>(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:15:8 + --> $DIR/array-const-arg-len-mismatch.rs:16:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:36:13 + --> $DIR/array-const-arg-len-mismatch.rs:37:13 | LL | bar::<{ [1, 2, 3] }>(); | ^^^^^^^^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:15:8 + --> $DIR/array-const-arg-len-mismatch.rs:16:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"*"` is not of type `[u8; 3]` - --> $DIR/array-const-arg-len-mismatch.rs:38:13 + --> $DIR/array-const-arg-len-mismatch.rs:39:13 | LL | baz::<{ [42] }>(); | ^^^^ expected `[u8; 3]`, found `[u8; 1]` | note: required by a const generic parameter in `baz` - --> $DIR/array-const-arg-len-mismatch.rs:27:8 + --> $DIR/array-const-arg-len-mismatch.rs:28:8 | LL | fn baz::LEN]>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `baz` diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr index a226d7ff0c225..2e3b2172b7325 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:11:52 + --> $DIR/array-expr-complex.rs:13:33 | -LL | takes_array::<{ core::direct_const_arg!([1, 2, 1 + 2]) }>(); - | ^^^^^ +LL | takes_array::<{ gca!([1, 2, 1 + 2]) }>(); + | ^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr index cc1e70c1d9a7a..2b25efb6ab090 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:14:45 + --> $DIR/array-expr-complex.rs:16:26 | -LL | takes_array::<{ core::direct_const_arg!([X; 3]) }>(); - | ^^^^^^ +LL | takes_array::<{ gca!([X; 3]) }>(); + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr index cc52abe0e8fb8..09515bafa7025 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:17:45 + --> $DIR/array-expr-complex.rs:19:26 | -LL | takes_array::<{ core::direct_const_arg!([0; Y]) }>(); - | ^^^^^^ +LL | takes_array::<{ gca!([0; Y]) }>(); + | ^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index 7f5a77fdff3df..be3b85e2bd240 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -3,18 +3,20 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, adt_const_params)] +use std::gca; + fn takes_array() {} fn generic_caller() { // not supported yet #[cfg(r1)] - takes_array::<{ core::direct_const_arg!([1, 2, 1 + 2]) }>(); + takes_array::<{ gca!([1, 2, 1 + 2]) }>(); //[r1]~^ ERROR: complex const arguments must be placed inside of a `const` block #[cfg(r2)] - takes_array::<{ core::direct_const_arg!([X; 3]) }>(); + takes_array::<{ gca!([X; 3]) }>(); //[r2]~^ ERROR: complex const arguments must be placed inside of a `const` block #[cfg(r3)] - takes_array::<{ core::direct_const_arg!([0; Y]) }>(); + takes_array::<{ gca!([0; Y]) }>(); //[r3]~^ ERROR: complex const arguments must be placed inside of a `const` block } diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs index 3d62adae09ada..76534f12d80c8 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs @@ -1,6 +1,8 @@ #![feature(min_generic_const_args, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const ASSOC: usize; @@ -10,8 +12,8 @@ fn takes_array() {} fn takes_tuple_with_array() {} fn generic_caller() { - takes_array::<{ core::direct_const_arg!([N, N + 1]) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block - takes_tuple_with_array::<{ core::direct_const_arg!(([N, N + 1], N)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_array::<{ gca!([N, N + 1]) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_tuple_with_array::<{ gca!(([N, N + 1], N)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block } fn main() {} diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr index c7db1e4753f8c..b044775b80c94 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr @@ -1,14 +1,14 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:13:49 + --> $DIR/array_expr_arg_complex.rs:15:30 | -LL | takes_array::<{ core::direct_const_arg!([N, N + 1]) }>(); - | ^^^^^ +LL | takes_array::<{ gca!([N, N + 1]) }>(); + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:14:61 + --> $DIR/array_expr_arg_complex.rs:16:42 | -LL | takes_tuple_with_array::<{ core::direct_const_arg!(([N, N + 1], N)) }>(); - | ^^^^^ +LL | takes_tuple_with_array::<{ gca!(([N, N + 1], N)) }>(); + | ^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs index 1b4c5b60edb72..9601cbc997f45 100644 --- a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs +++ b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs @@ -4,6 +4,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![allow(dead_code)] +use std::gca; + trait Abc {} trait A { @@ -12,7 +14,7 @@ trait A { } impl A for T { - const VALUE: usize = core::direct_const_arg!(0); + const VALUE: usize = gca!(0); } trait S {} diff --git a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs index e3d1f577d4f60..a4ad2cccaa544 100644 --- a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs +++ b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs @@ -1,8 +1,10 @@ #![feature(min_generic_const_args)] +use std::gca; + trait Iter< const FN: fn() = { - core::direct_const_arg!(|| { + gca!(|| { //~^ ERROR complex const arguments must be placed inside of a `const` block use std::io::*; write!(_, "") diff --git a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr index 96fcea9e906cf..49796692d9dcc 100644 --- a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr +++ b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/bad-const-arg-fn-154539.rs:5:33 + --> $DIR/bad-const-arg-fn-154539.rs:7:14 | -LL | core::direct_const_arg!(|| { - | _________________________________^ +LL | gca!(|| { + | ______________^ LL | | LL | | use std::io::*; LL | | write!(_, "") diff --git a/tests/ui/const-generics/mgca/bad-direct-const-arg.rs b/tests/ui/const-generics/mgca/bad-direct-const-arg.rs deleted file mode 100644 index 59fdccf29b7b5..0000000000000 --- a/tests/ui/const-generics/mgca/bad-direct-const-arg.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ edition: 2024 - -//! Reject direct const arguments in value/type positions without unrelated brace suggestions. -#![feature(min_generic_const_args)] -#![deny(unused_braces)] - -fn main(x: core::direct_const_arg!(2)) { - //~^ ERROR expected type, found `direct_const_arg!()` constant - let _ = core::direct_const_arg!(2); - //~^ ERROR expected expression, found `direct_const_arg!()` constant - consume({ core::direct_const_arg!(2) }); - //~^ ERROR expected expression, found `direct_const_arg!()` constant -} - -fn consume(_: usize) {} diff --git a/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr b/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr deleted file mode 100644 index d54a2c4400ea7..0000000000000 --- a/tests/ui/const-generics/mgca/bad-direct-const-arg.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/bad-direct-const-arg.rs:9:13 - | -LL | let _ = core::direct_const_arg!(2); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/bad-direct-const-arg.rs:11:15 - | -LL | consume({ core::direct_const_arg!(2) }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: expected type, found `direct_const_arg!()` constant - --> $DIR/bad-direct-const-arg.rs:7:12 - | -LL | fn main(x: core::direct_const_arg!(2)) { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 3 previous errors - diff --git a/tests/ui/const-generics/mgca/bad-gca-macro.rs b/tests/ui/const-generics/mgca/bad-gca-macro.rs new file mode 100644 index 0000000000000..50f2ebe65e818 --- /dev/null +++ b/tests/ui/const-generics/mgca/bad-gca-macro.rs @@ -0,0 +1,17 @@ +//@ edition: 2024 + +//! Reject direct const arguments in value/type positions without unrelated brace suggestions. +#![feature(min_generic_const_args)] +#![deny(unused_braces)] + +use std::gca; + +fn main(x: gca!(2)) { + //~^ ERROR expected type, found `gca!()` constant + let _ = gca!(2); + //~^ ERROR expected expression, found `gca!()` constant + consume({ gca!(2) }); + //~^ ERROR expected expression, found `gca!()` constant +} + +fn consume(_: usize) {} diff --git a/tests/ui/const-generics/mgca/bad-gca-macro.stderr b/tests/ui/const-generics/mgca/bad-gca-macro.stderr new file mode 100644 index 0000000000000..e22bfc76d43c7 --- /dev/null +++ b/tests/ui/const-generics/mgca/bad-gca-macro.stderr @@ -0,0 +1,20 @@ +error: expected expression, found `gca!()` constant + --> $DIR/bad-gca-macro.rs:11:13 + | +LL | let _ = gca!(2); + | ^^^^^^^ + +error: expected expression, found `gca!()` constant + --> $DIR/bad-gca-macro.rs:13:15 + | +LL | consume({ gca!(2) }); + | ^^^^^^^ + +error: expected type, found `gca!()` constant + --> $DIR/bad-gca-macro.rs:9:12 + | +LL | fn main(x: gca!(2)) { + | ^^^^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs index 9ffc2b70eecaf..c0391d54e423d 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs @@ -2,15 +2,22 @@ trait Tr { #[rustc_always_gca] //~^ ERROR: the `rustc_always_gca` attribute is an experimental feature [E0658] const N: usize; + #[rustc_always_gca] + //~^ ERROR: the `rustc_always_gca` attribute is an experimental feature [E0658] + const M: usize; } struct S; impl Tr for S { - const N: usize = core::direct_const_arg!(0); + const N: usize = core::gca!(0); + //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] + //~| ERROR: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + //~| ERROR: expected expression, found `gca!()` constant + const M: usize = std::gca!(0); //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] - //~| ERROR: implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS - //~| ERROR: expected expression, found `direct_const_arg!()` constant + //~| ERROR: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + //~| ERROR: expected expression, found `gca!()` constant } fn main() {} diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr index 31be797b12590..0e8c2f4971a41 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr @@ -1,8 +1,18 @@ error[E0658]: use of unstable library feature `min_generic_const_args` - --> $DIR/bad-type_const-syntax.rs:10:22 + --> $DIR/bad-type_const-syntax.rs:13:22 | -LL | const N: usize = core::direct_const_arg!(0); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | const N: usize = core::gca!(0); + | ^^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `min_generic_const_args` + --> $DIR/bad-type_const-syntax.rs:17:22 + | +LL | const M: usize = std::gca!(0); + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable @@ -18,16 +28,32 @@ LL | #[rustc_always_gca] = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/bad-type_const-syntax.rs:10:22 +error[E0658]: the `rustc_always_gca` attribute is an experimental feature + --> $DIR/bad-type_const-syntax.rs:5:7 + | +LL | #[rustc_always_gca] + | ^^^^^^^^^^^^^^^^ | -LL | const N: usize = core::direct_const_arg!(0); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: see issue #132980 for more information + = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: expected expression, found `gca!()` constant + --> $DIR/bad-type_const-syntax.rs:13:22 + | +LL | const N: usize = core::gca!(0); + | ^^^^^^^^^^^^^ -error: implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS - --> $DIR/bad-type_const-syntax.rs:10:5 +error: expected expression, found `gca!()` constant + --> $DIR/bad-type_const-syntax.rs:17:22 | -LL | const N: usize = core::direct_const_arg!(0); +LL | const M: usize = std::gca!(0); + | ^^^^^^^^^^^^ + +error: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + --> $DIR/bad-type_const-syntax.rs:13:5 + | +LL | const N: usize = core::gca!(0); | ^^^^^^^^^^^^^^ | note: trait declaration of const is marked as `#[rustc_always_gca]` @@ -36,6 +62,18 @@ note: trait declaration of const is marked as `#[rustc_always_gca]` LL | const N: usize; | ^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + --> $DIR/bad-type_const-syntax.rs:17:5 + | +LL | const M: usize = std::gca!(0); + | ^^^^^^^^^^^^^^ + | +note: trait declaration of const is marked as `#[rustc_always_gca]` + --> $DIR/bad-type_const-syntax.rs:7:5 + | +LL | const M: usize; + | ^^^^^^^^^^^^^^ + +error: aborting due to 8 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs b/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs index a696ff5964e7f..38851a6e5130f 100644 --- a/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs +++ b/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args)] #![feature(macroless_generic_const_args)] +use std::gca; + trait Trait {} impl Trait for i32 {} @@ -13,11 +15,11 @@ fn main() { // Const-only infer args used for a type parameter are rejected. let _z: &[&dyn Trait<{ _ }>] = &[&0i32]; //~^ ERROR: constant provided when a type was expected - let _y: &dyn Trait = &0i32; + let _y: &dyn Trait = &0i32; //~^ ERROR: constant provided when a type was expected let _a: S<{ _ }> = S::<3>; - let _b: S = S::<3>; - let _c: S<{ core::direct_const_arg!(_) }> = S::<3>; + let _b: S = S::<3>; + let _c: S<{ gca!(_) }> = S::<3>; let _d: S<_> = S::<3>; } diff --git a/tests/ui/const-generics/mgca/braced-const-infer-in-body.stderr b/tests/ui/const-generics/mgca/braced-const-infer-in-body.stderr index dec966c111253..2a7960c57b1e9 100644 --- a/tests/ui/const-generics/mgca/braced-const-infer-in-body.stderr +++ b/tests/ui/const-generics/mgca/braced-const-infer-in-body.stderr @@ -1,14 +1,14 @@ error[E0747]: constant provided when a type was expected - --> $DIR/braced-const-infer-in-body.rs:14:28 + --> $DIR/braced-const-infer-in-body.rs:16:28 | LL | let _z: &[&dyn Trait<{ _ }>] = &[&0i32]; | ^ error[E0747]: constant provided when a type was expected - --> $DIR/braced-const-infer-in-body.rs:16:48 + --> $DIR/braced-const-infer-in-body.rs:18:29 | -LL | let _y: &dyn Trait = &0i32; - | ^ +LL | let _y: &dyn Trait = &0i32; + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs index b365de395e80d..9f6a62aa60e17 100644 --- a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs +++ b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs @@ -3,8 +3,7 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, generic_const_items)] -extern crate core; -use core::direct_const_arg; +use std::gca; pub trait Tr { #[rustc_always_gca] @@ -18,9 +17,9 @@ pub trait Tr { pub struct S; impl Tr for S { - const N1: usize = core::direct_const_arg!(0); - const N2: usize = core::direct_const_arg!(1); - const N3: usize = core::direct_const_arg!(2); + const N1: usize = gca!(0); + const N2: usize = gca!(1); + const N3: usize = gca!(2); } fn main() {} diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs index c89c6a14a367a..e19b71153b1e5 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs @@ -3,7 +3,9 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -const C: usize = core::direct_const_arg!(0); +use std::gca; + +const C: usize = gca!(0); pub struct A {} impl A { fn fun1() {} diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr index 3d74d1db206e1..c82f8a96167ba 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.stderr @@ -1,11 +1,11 @@ error[E0107]: missing generics for struct `A` - --> $DIR/const-arg-coherence-conflicting-methods.rs:12:6 + --> $DIR/const-arg-coherence-conflicting-methods.rs:14:6 | LL | impl A { | ^ expected 1 generic argument | note: struct defined here, with 1 generic parameter: `M` - --> $DIR/const-arg-coherence-conflicting-methods.rs:7:12 + --> $DIR/const-arg-coherence-conflicting-methods.rs:9:12 | LL | pub struct A {} | ^ -------------- @@ -15,7 +15,7 @@ LL | impl A { | +++ error[E0592]: duplicate definitions with name `fun1` - --> $DIR/const-arg-coherence-conflicting-methods.rs:9:5 + --> $DIR/const-arg-coherence-conflicting-methods.rs:11:5 | LL | fn fun1() {} | ^^^^^^^^^ duplicate definitions for `fun1` diff --git a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs index df2dd048e6a43..c4e941edbb4de 100644 --- a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs +++ b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs @@ -1,7 +1,9 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] -const CONST: usize = core::direct_const_arg!(1_i32); +use std::gca; + +const CONST: usize = gca!(1_i32); //~^ ERROR the constant `1` is not of type `usize` //~| NOTE expected `usize`, found `i32` diff --git a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.stderr b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.stderr index 49f9f76d6cb1b..3f009d17be58a 100644 --- a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.stderr +++ b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.stderr @@ -1,7 +1,7 @@ error: the constant `1` is not of type `usize` - --> $DIR/const-arg-mismatched-literal-suffix.rs:4:1 + --> $DIR/const-arg-mismatched-literal-suffix.rs:6:1 | -LL | const CONST: usize = core::direct_const_arg!(1_i32); +LL | const CONST: usize = gca!(1_i32); | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `i32` error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs index 89320472a3913..7c0a6c9f7771b 100644 --- a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs +++ b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs @@ -4,7 +4,9 @@ #![feature(generic_const_exprs)] #![expect(incomplete_features)] -const A: u8 = core::direct_const_arg!(A); +use std::gca; + +const A: u8 = gca!(A); //~^ ERROR cycle detected when computing the type-level value for `A` fn main() {} diff --git a/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr b/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr index ac37da026f95f..934057da24139 100644 --- a/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr +++ b/tests/ui/const-generics/mgca/cyclic-type-const-151251.stderr @@ -1,7 +1,7 @@ error[E0391]: cycle detected when computing the type-level value for `A` - --> $DIR/cyclic-type-const-151251.rs:7:1 + --> $DIR/cyclic-type-const-151251.rs:9:1 | -LL | const A: u8 = core::direct_const_arg!(A); +LL | const A: u8 = gca!(A); | ^^^^^^^^^^^ | = note: ...which immediately requires computing the type-level value for `A` again diff --git a/tests/ui/const-generics/mgca/direct-const-arg-correct-rib.stderr b/tests/ui/const-generics/mgca/direct-const-arg-correct-rib.stderr deleted file mode 100644 index 76f189e38e4d5..0000000000000 --- a/tests/ui/const-generics/mgca/direct-const-arg-correct-rib.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: attempt to use a non-constant value in a constant - --> $DIR/direct-const-arg-correct-rib.rs:8:42 - | -LL | let _: V; - | ^^^^ help: try using `Self` - -error: aborting due to 1 previous error - diff --git a/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.rs b/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.rs deleted file mode 100644 index 8c802e563db7c..0000000000000 --- a/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(min_generic_const_args)] -struct S; -fn foo(_: S) {} -//~^ ERROR direct_const_arg! takes 1 argument -fn main() {} diff --git a/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.stderr b/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.stderr deleted file mode 100644 index 6f54a563ffbfc..0000000000000 --- a/tests/ui/const-generics/mgca/direct-const-arg-multiple-exprs.stderr +++ /dev/null @@ -1,8 +0,0 @@ -error: direct_const_arg! takes 1 argument - --> $DIR/direct-const-arg-multiple-exprs.rs:3:45 - | -LL | fn foo(_: S) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.rs b/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.rs deleted file mode 100644 index 9e2c744c617c5..0000000000000 --- a/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.rs +++ /dev/null @@ -1,13 +0,0 @@ -//! `direct_const_arg!(_)` used to be allowed to infer to a type as a compiler -//! implementation quirk. Since it uses explicit const argument syntax, -//! it is now rejected when passed as a type argument -#![feature(min_generic_const_args)] - -struct S(T); - -fn main() { - let _: S = S(2u32); - //~^ ERROR: constant provided when a type was expected - let _: S<{ core::direct_const_arg!(_) }> = S(2u32); - //~^ ERROR: constant provided when a type was expected -} diff --git a/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.stderr b/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.stderr deleted file mode 100644 index 07e0faf0ba792..0000000000000 --- a/tests/ui/const-generics/mgca/direct_const_arg-infer-as-type.stderr +++ /dev/null @@ -1,15 +0,0 @@ -error[E0747]: constant provided when a type was expected - --> $DIR/direct_const_arg-infer-as-type.rs:9:38 - | -LL | let _: S = S(2u32); - | ^ - -error[E0747]: constant provided when a type was expected - --> $DIR/direct_const_arg-infer-as-type.rs:11:40 - | -LL | let _: S<{ core::direct_const_arg!(_) }> = S(2u32); - | ^ - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.rs b/tests/ui/const-generics/mgca/explicit_anon_consts.rs index 2fc1a0ea4b8ed..3c7c1da90ed39 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.rs +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.rs @@ -4,13 +4,15 @@ // DefIds which were created for const args. #![crate_type = "lib"] +use std::gca; + struct Foo; type Adt1 = Foo; type Adt2 = Foo<{ N }>; type Adt3 = Foo; //~^ ERROR: generic parameters may not be used in const operations -type Adt4 = Foo; +type Adt4 = Foo; //~^ ERROR: complex const arguments must be placed inside of a `const` block type Adt5 = Foo; @@ -18,7 +20,7 @@ type Arr = [(); N]; type Arr2 = [(); { N }]; type Arr3 = [(); const { N }]; //~^ ERROR: generic parameters may not be used in const operations -type Arr4 = [(); core::direct_const_arg!(1 + 1)]; +type Arr4 = [(); gca!(1 + 1)]; //~^ ERROR: complex const arguments must be placed inside of a `const` block type Arr5 = [(); const { 1 + 1 }]; @@ -27,24 +29,24 @@ fn repeats() -> [(); N] { let _2 = [(); { N }]; let _3 = [(); const { N }]; //~^ ERROR: generic parameters may not be used in const operations - let _4 = [(); core::direct_const_arg!(1 + 1)]; + let _4 = [(); gca!(1 + 1)]; //~^ ERROR: complex const arguments must be placed inside of a `const` block let _5 = [(); const { 1 + 1 }]; let _6: [(); const { N }] = todo!(); //~^ ERROR: generic parameters may not be used in const operations } -const ITEM1: usize = core::direct_const_arg!(N); +const ITEM1: usize = gca!(N); -const ITEM2: usize = core::direct_const_arg!({ N }); +const ITEM2: usize = gca!({ N }); -const ITEM3: usize = core::direct_const_arg!(const { N }); +const ITEM3: usize = gca!(const { N }); //~^ ERROR: generic parameters may not be used in const operations -const ITEM4: usize = core::direct_const_arg!(1 + 1); +const ITEM4: usize = gca!(1 + 1); //~^ ERROR: complex const arguments must be placed inside of a `const` block -const ITEM5: usize = core::direct_const_arg!(const { 1 + 1 }); +const ITEM5: usize = gca!(const { 1 + 1 }); trait Trait { #[rustc_always_gca] @@ -58,7 +60,7 @@ fn ace_bounds< T2: Trait, T3: Trait, //~^ ERROR: generic parameters may not be used in const operations - T4: Trait, + T4: Trait, //~^ ERROR: complex const arguments must be placed inside of a `const` block T5: Trait, >() { @@ -68,6 +70,6 @@ struct Default1; struct Default2; struct Default3; //~^ ERROR: generic parameters may not be used in const operations -struct Default4; +struct Default4; //~^ ERROR: complex const arguments must be placed inside of a `const` block struct Default5; diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index aa479bce84a7e..ad533df5138f5 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -1,49 +1,49 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:13:57 + --> $DIR/explicit_anon_consts.rs:15:38 | -LL | type Adt4 = Foo; - | ^^^^^ +LL | type Adt4 = Foo; + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:21:58 + --> $DIR/explicit_anon_consts.rs:23:39 | -LL | type Arr4 = [(); core::direct_const_arg!(1 + 1)]; - | ^^^^^ +LL | type Arr4 = [(); gca!(1 + 1)]; + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:30:43 + --> $DIR/explicit_anon_consts.rs:32:24 | -LL | let _4 = [(); core::direct_const_arg!(1 + 1)]; - | ^^^^^ +LL | let _4 = [(); gca!(1 + 1)]; + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:44:62 + --> $DIR/explicit_anon_consts.rs:46:43 | -LL | const ITEM4: usize = core::direct_const_arg!(1 + 1); - | ^^^^^ +LL | const ITEM4: usize = gca!(1 + 1); + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:61:49 + --> $DIR/explicit_anon_consts.rs:63:30 | -LL | T4: Trait, - | ^^^^^ +LL | T4: Trait, + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/explicit_anon_consts.rs:71:76 + --> $DIR/explicit_anon_consts.rs:73:57 | -LL | struct Default4; - | ^^^^^ +LL | struct Default4; + | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:41:70 + --> $DIR/explicit_anon_consts.rs:43:51 | -LL | const ITEM3: usize = core::direct_const_arg!(const { N }); - | ^ +LL | const ITEM3: usize = gca!(const { N }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:59:31 + --> $DIR/explicit_anon_consts.rs:61:31 | LL | T3: Trait, | ^ @@ -51,7 +51,7 @@ LL | T3: Trait, = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:69:58 + --> $DIR/explicit_anon_consts.rs:71:58 | LL | struct Default3; | ^ @@ -59,7 +59,7 @@ LL | struct Default3; = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:28:27 + --> $DIR/explicit_anon_consts.rs:30:27 | LL | let _3 = [(); const { N }]; | ^ @@ -67,7 +67,7 @@ LL | let _3 = [(); const { N }]; = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:33:26 + --> $DIR/explicit_anon_consts.rs:35:26 | LL | let _6: [(); const { N }] = todo!(); | ^ @@ -75,7 +75,7 @@ LL | let _6: [(); const { N }] = todo!(); = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:11:41 + --> $DIR/explicit_anon_consts.rs:13:41 | LL | type Adt3 = Foo; | ^ @@ -83,7 +83,7 @@ LL | type Adt3 = Foo; = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/explicit_anon_consts.rs:19:42 + --> $DIR/explicit_anon_consts.rs:21:42 | LL | type Arr3 = [(); const { N }]; | ^ diff --git a/tests/ui/const-generics/mgca/free-const-recursive.gca.stderr b/tests/ui/const-generics/mgca/free-const-recursive.gca.stderr index fdbfeae464f8d..7bdab2d09acda 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.gca.stderr +++ b/tests/ui/const-generics/mgca/free-const-recursive.gca.stderr @@ -1,13 +1,13 @@ error[E0275]: overflow evaluating the requirement `A == _` - --> $DIR/free-const-recursive.rs:11:1 + --> $DIR/free-const-recursive.rs:13:1 | -LL | const A: () = core::direct_const_arg!(A); +LL | const A: () = gca!(A); | ^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `the constant `A` has type `()`` - --> $DIR/free-const-recursive.rs:11:1 + --> $DIR/free-const-recursive.rs:13:1 | -LL | const A: () = core::direct_const_arg!(A); +LL | const A: () = gca!(A); | ^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/free-const-recursive.min_gca.stderr b/tests/ui/const-generics/mgca/free-const-recursive.min_gca.stderr index 5f588a00055b6..3dcce0ad7eea6 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.min_gca.stderr +++ b/tests/ui/const-generics/mgca/free-const-recursive.min_gca.stderr @@ -1,7 +1,7 @@ error[E0391]: cycle detected when computing the type-level value for `A` - --> $DIR/free-const-recursive.rs:11:1 + --> $DIR/free-const-recursive.rs:13:1 | -LL | const A: () = core::direct_const_arg!(A); +LL | const A: () = gca!(A); | ^^^^^^^^^^^ | = note: ...which immediately requires computing the type-level value for `A` again diff --git a/tests/ui/const-generics/mgca/free-const-recursive.rs b/tests/ui/const-generics/mgca/free-const-recursive.rs index 6d4d78b46dccc..3fdeb37aa5d5d 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.rs +++ b/tests/ui/const-generics/mgca/free-const-recursive.rs @@ -8,7 +8,9 @@ #![expect(incomplete_features)] #![cfg_attr(gca, feature(generic_const_args))] -const A: () = core::direct_const_arg!(A); +use std::gca; + +const A: () = gca!(A); //[gca]~^ ERROR: overflow evaluating the requirement `A == _` //[gca]~| ERROR: overflow evaluating the requirement `the constant `A` has type `()`` //[min_gca]~^^^ ERROR: cycle detected when computing the type-level value for `A` diff --git a/tests/ui/const-generics/mgca/direct-const-arg-correct-rib.rs b/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs similarity index 57% rename from tests/ui/const-generics/mgca/direct-const-arg-correct-rib.rs rename to tests/ui/const-generics/mgca/gca-macro-correct-rib.rs index 9f088a05b98f9..b03bbb7faacc3 100644 --- a/tests/ui/const-generics/mgca/direct-const-arg-correct-rib.rs +++ b/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs @@ -1,11 +1,13 @@ -//! make sure TyKind::DirectConstArg resolves properly with the correct ribs and doesn't ICE +//! make sure TyKind::GcaMacro resolves properly with the correct ribs and doesn't ICE #![feature(min_generic_const_args)] +use std::gca; + struct S; struct V; impl S { fn f(self) { - let _: V; + let _: V; //~^ ERROR attempt to use a non-constant value in a constant } } diff --git a/tests/ui/const-generics/mgca/gca-macro-correct-rib.stderr b/tests/ui/const-generics/mgca/gca-macro-correct-rib.stderr new file mode 100644 index 0000000000000..baf864f60f8f0 --- /dev/null +++ b/tests/ui/const-generics/mgca/gca-macro-correct-rib.stderr @@ -0,0 +1,8 @@ +error: attempt to use a non-constant value in a constant + --> $DIR/gca-macro-correct-rib.rs:10:23 + | +LL | let _: V; + | ^^^^ help: try using `Self` + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/direct-const-arg-feature-gate.rs b/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs similarity index 52% rename from tests/ui/const-generics/mgca/direct-const-arg-feature-gate.rs rename to tests/ui/const-generics/mgca/gca-macro-feature-gate.rs index 16ba349a29be6..1f4d302110490 100644 --- a/tests/ui/const-generics/mgca/direct-const-arg-feature-gate.rs +++ b/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs @@ -1,5 +1,5 @@ -fn foo(_: [(); core::direct_const_arg!(N)]) {} +fn foo(_: [(); std::gca!(N)]) {} //~^ ERROR use of unstable library feature `min_generic_const_args` -//~| ERROR expected expression, found `direct_const_arg!()` constant +//~| ERROR expected expression, found `gca!()` constant //~| ERROR generic parameters may not be used in const operations fn main() {} diff --git a/tests/ui/const-generics/mgca/direct-const-arg-feature-gate.stderr b/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr similarity index 56% rename from tests/ui/const-generics/mgca/direct-const-arg-feature-gate.stderr rename to tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr index a2927d0625b55..70586b9b288b4 100644 --- a/tests/ui/const-generics/mgca/direct-const-arg-feature-gate.stderr +++ b/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr @@ -1,28 +1,28 @@ error[E0658]: use of unstable library feature `min_generic_const_args` - --> $DIR/direct-const-arg-feature-gate.rs:1:32 + --> $DIR/gca-macro-feature-gate.rs:1:32 | -LL | fn foo(_: [(); core::direct_const_arg!(N)]) {} - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo(_: [(); std::gca!(N)]) {} + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: generic parameters may not be used in const operations - --> $DIR/direct-const-arg-feature-gate.rs:1:56 + --> $DIR/gca-macro-feature-gate.rs:1:42 | -LL | fn foo(_: [(); core::direct_const_arg!(N)]) {} - | ^ cannot perform const operation using `N` +LL | fn foo(_: [(); std::gca!(N)]) {} + | ^ cannot perform const operation using `N` | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/direct-const-arg-feature-gate.rs:1:32 +error: expected expression, found `gca!()` constant + --> $DIR/gca-macro-feature-gate.rs:1:32 | -LL | fn foo(_: [(); core::direct_const_arg!(N)]) {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo(_: [(); std::gca!(N)]) {} + | ^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs new file mode 100644 index 0000000000000..155626ad9d47f --- /dev/null +++ b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs @@ -0,0 +1,14 @@ +//! `gca!(_)` used to be allowed to infer to a type as a compiler implementation quirk. Since it +//! uses explicit const argument syntax, it is now rejected when passed as a type argument +#![feature(min_generic_const_args)] + +use std::gca; + +struct S(T); + +fn main() { + let _: S = S(2u32); + //~^ ERROR: constant provided when a type was expected + let _: S<{ gca!(_) }> = S(2u32); + //~^ ERROR: constant provided when a type was expected +} diff --git a/tests/ui/const-generics/mgca/gca-macro-infer-as-type.stderr b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.stderr new file mode 100644 index 0000000000000..22c20958b6626 --- /dev/null +++ b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.stderr @@ -0,0 +1,15 @@ +error[E0747]: constant provided when a type was expected + --> $DIR/gca-macro-infer-as-type.rs:10:19 + | +LL | let _: S = S(2u32); + | ^ + +error[E0747]: constant provided when a type was expected + --> $DIR/gca-macro-infer-as-type.rs:12:21 + | +LL | let _: S<{ gca!(_) }> = S(2u32); + | ^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0747`. diff --git a/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs new file mode 100644 index 0000000000000..518fc63d68bb9 --- /dev/null +++ b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs @@ -0,0 +1,6 @@ +#![feature(min_generic_const_args)] +use std::gca; +struct S; +fn foo(_: S) {} +//~^ ERROR gca! takes 1 argument +fn main() {} diff --git a/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.stderr b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.stderr new file mode 100644 index 0000000000000..992d981624924 --- /dev/null +++ b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.stderr @@ -0,0 +1,8 @@ +error: gca! takes 1 argument + --> $DIR/gca-macro-multiple-exprs.rs:4:45 + | +LL | fn foo(_: S) {} + | ^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs index b435dcde6dc93..4f71ad857cf5a 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -1,5 +1,6 @@ #![feature(min_generic_const_args)] #![feature(adt_const_params, unsized_const_params)] +use std::gca; #[derive(PartialEq, Eq, std::marker::ConstParamTy)] pub enum Enum { Unit, @@ -10,10 +11,10 @@ pub mod module { pub use super::Enum::Store; } fn main() { - const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Unit::<()>); + const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] - const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Tuple::<()>()); + const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); //~^ ERROR: type arguments are not allowed on tuple variant `Tuple` [E0109] - const _: Enum<()> = core::direct_const_arg!(self::::Enum::<()>::Store); + const _: Enum<()> = gca!(self::::Enum::<()>::Store); //~^ ERROR: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` [E0109] } diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr index 3a6c7a17544c8..02903379932ae 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -1,40 +1,40 @@ error[E0109]: type arguments are not allowed on unit variant `Unit` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:13:68 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:14:49 | -LL | const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Unit::<()>); - | ---- ^^ type argument not allowed - | | - | not allowed on unit variant `Unit` +LL | const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); + | ---- ^^ type argument not allowed + | | + | not allowed on unit variant `Unit` | = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other help: remove the generics arguments from one of the path segments | -LL - const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Unit::<()>); -LL + const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Unit); +LL - const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); +LL + const _: Enum<()> = gca!(Enum::<()>::Unit); | error[E0109]: type arguments are not allowed on tuple variant `Tuple` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:15:69 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:16:50 | -LL | const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Tuple::<()>()); - | ----- ^^ type argument not allowed - | | - | not allowed on tuple variant `Tuple` +LL | const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); + | ----- ^^ type argument not allowed + | | + | not allowed on tuple variant `Tuple` | = note: generic arguments are not allowed on both an enum and its variant's path segments simultaneously; they are only valid in one place or the other help: remove the generics arguments from one of the path segments | -LL - const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Tuple::<()>()); -LL + const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Tuple()); +LL - const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); +LL + const _: Enum<()> = gca!(Enum::<()>::Tuple()); | error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:56 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:18:37 | -LL | const _: Enum<()> = core::direct_const_arg!(self::::Enum::<()>::Store); - | ---- ^^^ type argument not allowed - | | - | not allowed on module `generic_args_on_enum_variant_segments_fail` +LL | const _: Enum<()> = gca!(self::::Enum::<()>::Store); + | ---- ^^^ type argument not allowed + | | + | not allowed on module `generic_args_on_enum_variant_segments_fail` error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs index 234bca78d6cb3..94782da82f150 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args)] #![feature(adt_const_params, unsized_const_params)] +use std::gca; + #[derive(PartialEq, Eq, std::marker::ConstParamTy)] enum Enum { Unit, @@ -10,7 +12,7 @@ enum Enum { Store(T), } -const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Unit); -const _: Enum<()> = core::direct_const_arg!(Enum::<()>::Tuple()); +const _: Enum<()> = gca!(Enum::<()>::Unit); +const _: Enum<()> = gca!(Enum::<()>::Tuple()); fn main() {} diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index 2c680a37ea1f9..fad1703e3bfee 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -3,6 +3,8 @@ #![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] #![feature(generic_const_parameter_types)] +use std::gca; + trait Trait { #[rustc_always_gca] const LEN: usize; @@ -10,7 +12,7 @@ trait Trait { struct S; impl Trait for S { - const LEN: usize = core::direct_const_arg!(2); + const LEN: usize = gca!(2); } fn foo::LEN]>() -> [u8; ::LEN] { diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr index c9ee69146f326..4906b05939900 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr @@ -1,11 +1,11 @@ error: the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` - --> $DIR/generic_const_items-mismatched-array-len.rs:21:11 + --> $DIR/generic_const_items-mismatched-array-len.rs:23:11 | LL | foo::() | ^ expected `[u8; ::LEN]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/generic_const_items-mismatched-array-len.rs:16:18 + --> $DIR/generic_const_items-mismatched-array-len.rs:18:18 | LL | fn foo::LEN]>() -> [u8; ::LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs index 5891e66aa77b0..eb32077dcfaca 100644 --- a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -1,8 +1,11 @@ //@ check-pass #![feature(min_adt_const_params, min_generic_const_args, generic_const_parameter_types)] + +use std::gca; + fn foo() {} fn main() { - foo::<_, core::direct_const_arg!([0, 1, 2, 3])>(); + foo::<_, gca!([0, 1, 2, 3])>(); } diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index 928205d4bc4df..55443874a36d1 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -7,13 +7,15 @@ min_generic_const_args, const_param_ty_trait )] + +use std::gca; use std::marker::ConstParamTy_; struct Foo { field: T, } -const WRAP: T = core::direct_const_arg!(Foo:: { field: 1 }); +const WRAP: T = gca!(Foo:: { field: 1 }); //~^ ERROR: type annotations needed for the literal fn main() {} diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr index d7f89bede8d4d..241e396c11569 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.stderr @@ -1,8 +1,8 @@ error: type annotations needed for the literal - --> $DIR/generic_const_type_mismatch.rs:16:77 + --> $DIR/generic_const_type_mismatch.rs:18:58 | -LL | const WRAP: T = core::direct_const_arg!(Foo:: { field: 1 }); - | ^ +LL | const WRAP: T = gca!(Foo:: { field: 1 }); + | ^ error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/inherent-alias-default.rs b/tests/ui/const-generics/mgca/inherent-alias-default.rs index 9ba6d1d15e856..2ef400454a195 100644 --- a/tests/ui/const-generics/mgca/inherent-alias-default.rs +++ b/tests/ui/const-generics/mgca/inherent-alias-default.rs @@ -5,11 +5,13 @@ //! ensure_ok(). This test just makes sure that codepath is hit in tests. #![feature(min_generic_const_args, inherent_associated_types)] +use std::gca; + struct Struct(T1, T2, T3); impl Struct { - const INHERENT: usize = core::direct_const_arg!(2); + const INHERENT: usize = gca!(2); } -struct WithDefault::INHERENT) }>; +struct WithDefault::INHERENT) }>; fn main() {} diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr b/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr deleted file mode 100644 index 016c7afc4b8b5..0000000000000 --- a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.expr.stderr +++ /dev/null @@ -1,13 +0,0 @@ -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/invalid-direct-const-arg-owner-issue-159172.rs:21:13 - | -LL | let _ = core::direct_const_arg!(|| { - | _____________^ -LL | | -LL | | use std::io::*; -LL | | write!(_, "") -LL | | }); - | |______^ - -error: aborting due to 1 previous error - diff --git a/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.expr.stderr b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.expr.stderr new file mode 100644 index 0000000000000..d579038f3cd7b --- /dev/null +++ b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.expr.stderr @@ -0,0 +1,13 @@ +error: expected expression, found `gca!()` constant + --> $DIR/invalid-gca-macro-owner-issue-159172.rs:23:13 + | +LL | let _ = gca!(|| { + | _____________^ +LL | | +LL | | use std::io::*; +LL | | write!(_, "") +LL | | }); + | |______^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs similarity index 57% rename from tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs rename to tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs index 80673ec127adf..0b0f30fd5b9fe 100644 --- a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.rs +++ b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs @@ -1,10 +1,12 @@ //@ revisions: ty expr #![feature(min_generic_const_args)] +use std::gca; + #[cfg(ty)] trait Iter< - const C: core::direct_const_arg!(|| { - //[ty]~^ ERROR expected type, found `direct_const_arg!()` constant + const C: gca!(|| { + //[ty]~^ ERROR expected type, found `gca!()` constant use std::io::*; let mut buffer = std::fs::File::create("foo.txt")?; write!(buffer, "oh no")?; @@ -18,8 +20,8 @@ fn main() {} #[cfg(expr)] fn main() { - let _ = core::direct_const_arg!(|| { - //[expr]~^ ERROR expected expression, found `direct_const_arg!()` constant + let _ = gca!(|| { + //[expr]~^ ERROR expected expression, found `gca!()` constant use std::io::*; write!(_, "") }); diff --git a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.ty.stderr similarity index 58% rename from tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr rename to tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.ty.stderr index 936153ce52b75..b3882df585ac0 100644 --- a/tests/ui/const-generics/mgca/invalid-direct-const-arg-owner-issue-159172.ty.stderr +++ b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.ty.stderr @@ -1,7 +1,7 @@ -error: expected type, found `direct_const_arg!()` constant - --> $DIR/invalid-direct-const-arg-owner-issue-159172.rs:6:14 +error: expected type, found `gca!()` constant + --> $DIR/invalid-gca-macro-owner-issue-159172.rs:8:14 | -LL | const C: core::direct_const_arg!(|| { +LL | const C: gca!(|| { | ______________^ LL | | LL | | use std::io::*; diff --git a/tests/ui/const-generics/mgca/macro-const-arg-infer.rs b/tests/ui/const-generics/mgca/macro-const-arg-infer.rs index a768228d94d28..010b1c240e2a6 100644 --- a/tests/ui/const-generics/mgca/macro-const-arg-infer.rs +++ b/tests/ui/const-generics/mgca/macro-const-arg-infer.rs @@ -1,6 +1,9 @@ //! Regression test for https://github.com/rust-lang/rust/issues/153198 #![feature(min_generic_const_args)] #![allow(incomplete_features)] + +use std::gca; + macro_rules! y { ( $($matcher:tt)*) => { _ //~ ERROR: constant provided when a type was expected @@ -11,7 +14,7 @@ macro_rules! y { struct A; //~ ERROR: type parameter `T` is never used const y: A< - core::direct_const_arg!(y! { + gca!(y! { x }), > = 1; diff --git a/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr b/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr index b46114bf4bd5f..a791b9d17fcce 100644 --- a/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr +++ b/tests/ui/const-generics/mgca/macro-const-arg-infer.stderr @@ -1,5 +1,5 @@ error[E0392]: type parameter `T` is never used - --> $DIR/macro-const-arg-infer.rs:11:10 + --> $DIR/macro-const-arg-infer.rs:14:10 | LL | struct A; | ^ unused type parameter @@ -8,29 +8,29 @@ LL | struct A; = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead error[E0747]: constant provided when a type was expected - --> $DIR/macro-const-arg-infer.rs:6:9 + --> $DIR/macro-const-arg-infer.rs:9:9 | LL | macro_rules! y { LL | ( $($matcher:tt)*) => { LL | _ | ^ ... -LL | core::direct_const_arg!(y! { - | _____________________________- +LL | gca!(y! { + | __________- LL | | x LL | | }), | |_____- in this macro invocation error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/macro-const-arg-infer.rs:6:9 + --> $DIR/macro-const-arg-infer.rs:9:9 | LL | macro_rules! y { LL | ( $($matcher:tt)*) => { LL | _ | ^ not allowed in type signatures ... -LL | core::direct_const_arg!(y! { - | _____________________________- +LL | gca!(y! { + | __________- LL | | x LL | | }), | |_____- in this macro invocation diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs index 1653fd63ed3f8..b4214f5f74e89 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs @@ -5,12 +5,14 @@ #![feature(min_generic_const_args, min_adt_const_params)] #![allow(incomplete_features)] +use std::gca; + fn f() {} fn g() { f::<{ (N, 1 + 1) }>(); //~^ ERROR: generic parameters may not be used in const operations - f::<{ core::direct_const_arg!((N, 1 + 1)) }>(); + f::<{ gca!((N, 1 + 1)) }>(); //~^ ERROR: complex const arguments must be placed inside of a `const` block } diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr index 50f849b6389ee..920143d33626f 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:13:39 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:15:20 | -LL | f::<{ core::direct_const_arg!((N, 1 + 1)) }>(); - | ^^^^^ +LL | f::<{ gca!((N, 1 + 1)) }>(); + | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:11:12 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:13:12 | LL | f::<{ (N, 1 + 1) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs b/tests/ui/const-generics/mgca/multi_braced_gca_macro.rs similarity index 100% rename from tests/ui/const-generics/mgca/multi_braced_direct_const_args.rs rename to tests/ui/const-generics/mgca/multi_braced_gca_macro.rs diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr index 593eac88122c0..a9a6c168b8d14 100644 --- a/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.stderr @@ -4,7 +4,7 @@ error: use of `const` in the type system not marked as direct LL | let x = [(); non_local_const::N]; | ^^^^^^^^^^^^^^^^^^ | - = note: only consts with a `direct_const_arg!` right-hand side may be used in types + = note: only consts with a `gca!` right-hand side may be used in types error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs b/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs index c21f1d0014ad5..d691aaaa6cf88 100644 --- a/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs +++ b/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs @@ -3,11 +3,13 @@ #![feature(generic_const_exprs)] #![feature(min_generic_const_args)] +use std::gca; + fn pass_enum { //~^ ERROR: missing parameters for function definition //~| ERROR: defaults for generic parameters are not allowed here //~| ERROR: overly complex generic constant - pass_enum::<{ core::direct_const_arg!(None) }> + pass_enum::<{ gca!(None) }> //~^ ERROR: missing generics for enum `Option` [E0107] } diff --git a/tests/ui/const-generics/mgca/none-as-usize-const-arg.stderr b/tests/ui/const-generics/mgca/none-as-usize-const-arg.stderr index dbd1ac607e88c..2cba595e2048b 100644 --- a/tests/ui/const-generics/mgca/none-as-usize-const-arg.stderr +++ b/tests/ui/const-generics/mgca/none-as-usize-const-arg.stderr @@ -1,5 +1,5 @@ error: missing parameters for function definition - --> $DIR/none-as-usize-const-arg.rs:6:59 + --> $DIR/none-as-usize-const-arg.rs:8:59 | LL | fn pass_enum { | ^ @@ -10,24 +10,24 @@ LL | fn pass_enum() { | ++ error: defaults for generic parameters are not allowed here - --> $DIR/none-as-usize-const-arg.rs:6:30 + --> $DIR/none-as-usize-const-arg.rs:8:30 | LL | fn pass_enum { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0107]: missing generics for enum `Option` - --> $DIR/none-as-usize-const-arg.rs:10:43 + --> $DIR/none-as-usize-const-arg.rs:12:24 | -LL | pass_enum::<{ core::direct_const_arg!(None) }> - | ^^^^ expected 1 generic argument +LL | pass_enum::<{ gca!(None) }> + | ^^^^ expected 1 generic argument | help: add missing generic argument | -LL | pass_enum::<{ core::direct_const_arg!(None) }> - | +++ +LL | pass_enum::<{ gca!(None) }> + | +++ error: overly complex generic constant - --> $DIR/none-as-usize-const-arg.rs:6:47 + --> $DIR/none-as-usize-const-arg.rs:8:47 | LL | fn pass_enum { | ^^^^^^^^^^^ const blocks are not supported in generic constants diff --git a/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs b/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs index ee336ea3f61e7..71112d632b5d8 100644 --- a/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs +++ b/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] #![allow(incomplete_features, dead_code)] +use std::gca; + trait Trait { #[rustc_always_gca] const CT: usize; @@ -13,7 +15,7 @@ struct Type { } impl Trait for Type { - const CT: usize = core::direct_const_arg!(N); + const CT: usize = gca!(N); } fn func() -> impl Trait as Trait>::CT }> { diff --git a/tests/ui/const-generics/mgca/paren.rs b/tests/ui/const-generics/mgca/paren.rs index de9e726a756f0..df60c06531755 100644 --- a/tests/ui/const-generics/mgca/paren.rs +++ b/tests/ui/const-generics/mgca/paren.rs @@ -2,35 +2,37 @@ //! See also: tests/ui/const-generics/paren.rs #![feature(min_generic_const_args, generic_const_items)] +use std::gca; + struct Thing; -const A: usize = core::direct_const_arg!(N); +const A: usize = gca!(N); fn f() { - let _: [u32; core::direct_const_arg!(_)] = [5; 5]; - let _: [u32; core::direct_const_arg!((_))] = [5; 5]; - let _: [u32; core::direct_const_arg!({ _ })] = [5; 5]; - let _: [u32; core::direct_const_arg!({ (_) })] = [5; 5]; - let _: [u32; core::direct_const_arg!(N)] = [5; _]; - let _: [u32; core::direct_const_arg!((N))] = [5; _]; - let _: [u32; core::direct_const_arg!({ N })] = [5; _]; - let _: [u32; core::direct_const_arg!({ (N) })] = [5; _]; - let _: [u32; core::direct_const_arg!(A::)] = [5; _]; - let _: [u32; core::direct_const_arg!((A::))] = [5; _]; - let _: [u32; core::direct_const_arg!({ A:: })] = [5; _]; - let _: [u32; core::direct_const_arg!({ (A::) })] = [5; _]; - let _: Thing = Thing::<5>; - let _: Thing = Thing::<5>; - let _: Thing = Thing::<5>; - let _: Thing = Thing::<5>; - let _: Thing = Thing; - let _: Thing = Thing; - let _: Thing = Thing; - let _: Thing = Thing; - let _: Thing)> = Thing; - let _: Thing))> = Thing; - let _: Thing })> = Thing; - let _: Thing) })> = Thing; + let _: [u32; gca!(_)] = [5; 5]; + let _: [u32; gca!((_))] = [5; 5]; + let _: [u32; gca!({ _ })] = [5; 5]; + let _: [u32; gca!({ (_) })] = [5; 5]; + let _: [u32; gca!(N)] = [5; _]; + let _: [u32; gca!((N))] = [5; _]; + let _: [u32; gca!({ N })] = [5; _]; + let _: [u32; gca!({ (N) })] = [5; _]; + let _: [u32; gca!(A::)] = [5; _]; + let _: [u32; gca!((A::))] = [5; _]; + let _: [u32; gca!({ A:: })] = [5; _]; + let _: [u32; gca!({ (A::) })] = [5; _]; + let _: Thing = Thing::<5>; + let _: Thing = Thing::<5>; + let _: Thing = Thing::<5>; + let _: Thing = Thing::<5>; + let _: Thing = Thing; + let _: Thing = Thing; + let _: Thing = Thing; + let _: Thing = Thing; + let _: Thing)> = Thing; + let _: Thing))> = Thing; + let _: Thing })> = Thing; + let _: Thing) })> = Thing; } fn main() {} diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.rs b/tests/ui/const-generics/mgca/projection-const-recursive.rs index 0f1e30e0e610b..4a4b0c918e80a 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.rs +++ b/tests/ui/const-generics/mgca/projection-const-recursive.rs @@ -6,13 +6,15 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const A: (); } impl Trait for () { - const A: () = core::direct_const_arg!(<() as Trait>::A); + const A: () = gca!(<() as Trait>::A); //~^ ERROR: overflow evaluating the requirement `<() as Trait>::A == _` //~| ERROR: overflow evaluating the requirement `the constant `<() as Trait>::A` has type `()`` } diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.stderr b/tests/ui/const-generics/mgca/projection-const-recursive.stderr index 54f94ea2e8e2e..1ffb6a88cc0f3 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.stderr +++ b/tests/ui/const-generics/mgca/projection-const-recursive.stderr @@ -1,13 +1,13 @@ error[E0275]: overflow evaluating the requirement `<() as Trait>::A == _` - --> $DIR/projection-const-recursive.rs:15:5 + --> $DIR/projection-const-recursive.rs:17:5 | -LL | const A: () = core::direct_const_arg!(<() as Trait>::A); +LL | const A: () = gca!(<() as Trait>::A); | ^^^^^^^^^^^ error[E0275]: overflow evaluating the requirement `the constant `<() as Trait>::A` has type `()`` - --> $DIR/projection-const-recursive.rs:15:5 + --> $DIR/projection-const-recursive.rs:17:5 | -LL | const A: () = core::direct_const_arg!(<() as Trait>::A); +LL | const A: () = gca!(<() as Trait>::A); | ^^^^^^^^^^^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/static-const-arg.rs b/tests/ui/const-generics/mgca/static-const-arg.rs index 8afc57c1c2785..cc97267b4726e 100644 --- a/tests/ui/const-generics/mgca/static-const-arg.rs +++ b/tests/ui/const-generics/mgca/static-const-arg.rs @@ -5,14 +5,16 @@ #![feature(min_generic_const_args)] #![allow(incomplete_features)] +use std::gca; + static A: u32 = 0; struct Foo; -const _: Foo<{ core::direct_const_arg!(A) }> = Foo; +const _: Foo<{ gca!(A) }> = Foo; //~^ ERROR static items cannot be used as const arguments -const _: Foo = Foo; +const _: Foo = Foo; //~^ ERROR static items cannot be used as const arguments fn main() {} diff --git a/tests/ui/const-generics/mgca/static-const-arg.stderr b/tests/ui/const-generics/mgca/static-const-arg.stderr index d2f878545971b..1ba21dc552961 100644 --- a/tests/ui/const-generics/mgca/static-const-arg.stderr +++ b/tests/ui/const-generics/mgca/static-const-arg.stderr @@ -1,14 +1,14 @@ error: static items cannot be used as const arguments - --> $DIR/static-const-arg.rs:12:40 + --> $DIR/static-const-arg.rs:14:21 | -LL | const _: Foo<{ core::direct_const_arg!(A) }> = Foo; - | ^ +LL | const _: Foo<{ gca!(A) }> = Foo; + | ^ error: static items cannot be used as const arguments - --> $DIR/static-const-arg.rs:15:38 + --> $DIR/static-const-arg.rs:17:19 | -LL | const _: Foo = Foo; - | ^ +LL | const _: Foo = Foo; + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/suggest-direct-const.fixed b/tests/ui/const-generics/mgca/suggest-direct-const.fixed index 6a6af81570255..044d875f1b4bb 100644 --- a/tests/ui/const-generics/mgca/suggest-direct-const.fixed +++ b/tests/ui/const-generics/mgca/suggest-direct-const.fixed @@ -4,35 +4,38 @@ #![allow(dead_code)] mod impl_item { + use std::gca; pub struct Bar; impl Bar { - pub const PUBLIC: usize = core::direct_const_arg!(1); - pub(crate) const RESTRICTED: usize = core::direct_const_arg!(1); - const PRIVATE: usize = core::direct_const_arg!(1); + pub const PUBLIC: usize = core::gca!(1); + pub(crate) const RESTRICTED: usize = core::gca!(1); + const PRIVATE: usize = core::gca!(1); } - pub struct Foo1([u8; core::direct_const_arg!(Bar::PUBLIC)]); + pub struct Foo1([u8; gca!(Bar::PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo2([u8; core::direct_const_arg!(Bar::RESTRICTED)]); + pub struct Foo2([u8; gca!(Bar::RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo3([u8; core::direct_const_arg!(Bar::PRIVATE)]); + pub struct Foo3([u8; gca!(Bar::PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } mod top_level_item { - pub const PUBLIC: usize = core::direct_const_arg!(1); - pub(crate) const RESTRICTED: usize = core::direct_const_arg!(1); - const PRIVATE: usize = core::direct_const_arg!(1); + use std::gca; + pub const PUBLIC: usize = core::gca!(1); + pub(crate) const RESTRICTED: usize = core::gca!(1); + const PRIVATE: usize = core::gca!(1); - pub struct Foo1([u8; core::direct_const_arg!(PUBLIC)]); + pub struct Foo1([u8; gca!(PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo2([u8; core::direct_const_arg!(RESTRICTED)]); + pub struct Foo2([u8; gca!(RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo3([u8; core::direct_const_arg!(PRIVATE)]); + pub struct Foo3([u8; gca!(PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } mod trait_item { + use std::gca; pub trait Foo { #[rustc_always_gca] const PUBLIC: usize; //~^ ERROR: [E0449] @@ -41,11 +44,11 @@ mod trait_item { #[rustc_always_gca] const PRIVATE: usize; } - pub struct Bar([u8; core::direct_const_arg!(T::PUBLIC)]); + pub struct Bar([u8; gca!(T::PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Bar2([u8; core::direct_const_arg!(T::RESTRICTED)]); + pub struct Bar2([u8; gca!(T::RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Bar3([u8; core::direct_const_arg!(T::PRIVATE)]); + pub struct Bar3([u8; gca!(T::PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } diff --git a/tests/ui/const-generics/mgca/suggest-direct-const.rs b/tests/ui/const-generics/mgca/suggest-direct-const.rs index 05b538a6cd1d9..e4f394e9c18bd 100644 --- a/tests/ui/const-generics/mgca/suggest-direct-const.rs +++ b/tests/ui/const-generics/mgca/suggest-direct-const.rs @@ -4,6 +4,7 @@ #![allow(dead_code)] mod impl_item { + use std::gca; pub struct Bar; impl Bar { pub const PUBLIC: usize = 1; @@ -11,28 +12,30 @@ mod impl_item { const PRIVATE: usize = 1; } - pub struct Foo1([u8; core::direct_const_arg!(Bar::PUBLIC)]); + pub struct Foo1([u8; gca!(Bar::PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo2([u8; core::direct_const_arg!(Bar::RESTRICTED)]); + pub struct Foo2([u8; gca!(Bar::RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo3([u8; core::direct_const_arg!(Bar::PRIVATE)]); + pub struct Foo3([u8; gca!(Bar::PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } mod top_level_item { + use std::gca; pub const PUBLIC: usize = 1; pub(crate) const RESTRICTED: usize = 1; const PRIVATE: usize = 1; - pub struct Foo1([u8; core::direct_const_arg!(PUBLIC)]); + pub struct Foo1([u8; gca!(PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo2([u8; core::direct_const_arg!(RESTRICTED)]); + pub struct Foo2([u8; gca!(RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Foo3([u8; core::direct_const_arg!(PRIVATE)]); + pub struct Foo3([u8; gca!(PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } mod trait_item { + use std::gca; pub trait Foo { pub const PUBLIC: usize; //~^ ERROR: [E0449] @@ -41,11 +44,11 @@ mod trait_item { const PRIVATE: usize; } - pub struct Bar([u8; core::direct_const_arg!(T::PUBLIC)]); + pub struct Bar([u8; gca!(T::PUBLIC)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Bar2([u8; core::direct_const_arg!(T::RESTRICTED)]); + pub struct Bar2([u8; gca!(T::RESTRICTED)]); //~^ ERROR: use of `const` in the type system not marked as direct - pub struct Bar3([u8; core::direct_const_arg!(T::PRIVATE)]); + pub struct Bar3([u8; gca!(T::PRIVATE)]); //~^ ERROR: use of `const` in the type system not marked as direct } diff --git a/tests/ui/const-generics/mgca/suggest-direct-const.stderr b/tests/ui/const-generics/mgca/suggest-direct-const.stderr index 69eeee156675d..d2cef03c3c3f2 100644 --- a/tests/ui/const-generics/mgca/suggest-direct-const.stderr +++ b/tests/ui/const-generics/mgca/suggest-direct-const.stderr @@ -1,5 +1,5 @@ error[E0449]: visibility qualifiers are not permitted here - --> $DIR/suggest-direct-const.rs:37:9 + --> $DIR/suggest-direct-const.rs:40:9 | LL | pub const PUBLIC: usize; | ^^^ help: remove the qualifier @@ -7,7 +7,7 @@ LL | pub const PUBLIC: usize; = note: trait items always share the visibility of their trait error[E0449]: visibility qualifiers are not permitted here - --> $DIR/suggest-direct-const.rs:39:9 + --> $DIR/suggest-direct-const.rs:42:9 | LL | pub(crate) const RESTRICTED: usize; | ^^^^^^^^^^ help: remove the qualifier @@ -15,76 +15,76 @@ LL | pub(crate) const RESTRICTED: usize; = note: trait items always share the visibility of their trait error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:14:50 + --> $DIR/suggest-direct-const.rs:15:31 | -LL | pub struct Foo1([u8; core::direct_const_arg!(Bar::PUBLIC)]); - | ^^^^^^^^^^^ +LL | pub struct Foo1([u8; gca!(Bar::PUBLIC)]); + | ^^^^^^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | pub const PUBLIC: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | pub const PUBLIC: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:16:50 + --> $DIR/suggest-direct-const.rs:17:31 | -LL | pub struct Foo2([u8; core::direct_const_arg!(Bar::RESTRICTED)]); - | ^^^^^^^^^^^^^^^ +LL | pub struct Foo2([u8; gca!(Bar::RESTRICTED)]); + | ^^^^^^^^^^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | pub(crate) const RESTRICTED: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | pub(crate) const RESTRICTED: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:18:50 + --> $DIR/suggest-direct-const.rs:19:31 | -LL | pub struct Foo3([u8; core::direct_const_arg!(Bar::PRIVATE)]); - | ^^^^^^^^^^^^ +LL | pub struct Foo3([u8; gca!(Bar::PRIVATE)]); + | ^^^^^^^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | const PRIVATE: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | const PRIVATE: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:27:50 + --> $DIR/suggest-direct-const.rs:29:31 | -LL | pub struct Foo1([u8; core::direct_const_arg!(PUBLIC)]); - | ^^^^^^ +LL | pub struct Foo1([u8; gca!(PUBLIC)]); + | ^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | pub const PUBLIC: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | pub const PUBLIC: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:29:50 + --> $DIR/suggest-direct-const.rs:31:31 | -LL | pub struct Foo2([u8; core::direct_const_arg!(RESTRICTED)]); - | ^^^^^^^^^^ +LL | pub struct Foo2([u8; gca!(RESTRICTED)]); + | ^^^^^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | pub(crate) const RESTRICTED: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | pub(crate) const RESTRICTED: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:31:50 + --> $DIR/suggest-direct-const.rs:33:31 | -LL | pub struct Foo3([u8; core::direct_const_arg!(PRIVATE)]); - | ^^^^^^^ +LL | pub struct Foo3([u8; gca!(PRIVATE)]); + | ^^^^^^^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | const PRIVATE: usize = core::direct_const_arg!(1); - | ++++++++++++++++++++++++ + +LL | const PRIVATE: usize = core::gca!(1); + | +++++++++++ + error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:44:57 + --> $DIR/suggest-direct-const.rs:47:38 | -LL | pub struct Bar([u8; core::direct_const_arg!(T::PUBLIC)]); - | ^^^^^^^^^ +LL | pub struct Bar([u8; gca!(T::PUBLIC)]); + | ^^^^^^^^^ | help: add `#[rustc_always_gca]` to the constant | @@ -92,10 +92,10 @@ LL | #[rustc_always_gca] pub const PUBLIC: usize; | +++++++++++++++++++ error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:46:58 + --> $DIR/suggest-direct-const.rs:49:39 | -LL | pub struct Bar2([u8; core::direct_const_arg!(T::RESTRICTED)]); - | ^^^^^^^^^^^^^ +LL | pub struct Bar2([u8; gca!(T::RESTRICTED)]); + | ^^^^^^^^^^^^^ | help: add `#[rustc_always_gca]` to the constant | @@ -103,10 +103,10 @@ LL | #[rustc_always_gca] pub(crate) const RESTRICTED: usize; | +++++++++++++++++++ error: use of `const` in the type system not marked as direct - --> $DIR/suggest-direct-const.rs:48:58 + --> $DIR/suggest-direct-const.rs:51:39 | -LL | pub struct Bar3([u8; core::direct_const_arg!(T::PRIVATE)]); - | ^^^^^^^^^^ +LL | pub struct Bar3([u8; gca!(T::PRIVATE)]); + | ^^^^^^^^^^ | help: add `#[rustc_always_gca]` to the constant | diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs index 2fd3dea527370..bb0349ccb604a 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -4,10 +4,12 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] -const T0: _ = core::direct_const_arg!(()); +use std::gca; + +const T0: _ = gca!(()); //~^ ERROR: the placeholder `_` is not allowed within types on item signatures for constants [E0121] -const T1 = core::direct_const_arg!([0]); +const T1 = gca!([0]); //~^ ERROR: missing type for `const` item fn main() {} diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr index 6f0544c80a480..3d09bbdab6072 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr @@ -1,18 +1,18 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/syntactic-type-mismatch.rs:7:11 + --> $DIR/syntactic-type-mismatch.rs:9:11 | -LL | const T0: _ = core::direct_const_arg!(()); +LL | const T0: _ = gca!(()); | ^ not allowed in type signatures error: missing type for `const` item - --> $DIR/syntactic-type-mismatch.rs:10:9 + --> $DIR/syntactic-type-mismatch.rs:12:9 | -LL | const T1 = core::direct_const_arg!([0]); +LL | const T1 = gca!([0]); | ^ | help: provide a type for the item | -LL | const T1: = core::direct_const_arg!([0]); +LL | const T1: = gca!([0]); | ++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs index 8bdafd6c270f8..bd9d77eee3a85 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs @@ -1,6 +1,7 @@ #![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] #![expect(incomplete_features)] +use std::gca; use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] @@ -9,7 +10,7 @@ struct Point(u32, u32); fn with_point() {} fn test() { - with_point::<{ core::direct_const_arg!(Point(N + 1, N)) }>(); + with_point::<{ gca!(Point(N + 1, N)) }>(); //~^ ERROR complex const arguments must be placed inside of a `const` block with_point::<{ Point(const { N + 1 }, N) }>(); diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 9b7c40d91515b..481afef0ee4e4 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_ctor_complex_args.rs:12:50 + --> $DIR/tuple_ctor_complex_args.rs:13:31 | -LL | with_point::<{ core::direct_const_arg!(Point(N + 1, N)) }>(); - | ^^^^^ +LL | with_point::<{ gca!(Point(N + 1, N)) }>(); + | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_ctor_complex_args.rs:15:34 + --> $DIR/tuple_ctor_complex_args.rs:16:34 | LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index d121566868a95..abe225e3f9291 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -1,6 +1,7 @@ #![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] #![expect(incomplete_features)] +use std::gca; use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] @@ -12,7 +13,7 @@ enum MyEnum { Unit, } -const CONST_ITEM: u32 = core::direct_const_arg!(42); +const CONST_ITEM: u32 = gca!(42); fn accepts_point() {} fn accepts_enum>() {} diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index b9bbfcc37469d..56b11b2894aa2 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope - --> $DIR/tuple_ctor_erroneous.rs:29:23 + --> $DIR/tuple_ctor_erroneous.rs:30:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^ not found in this scope @@ -10,61 +10,61 @@ LL | fn test_errors() { | +++++++++++++++++++++++++++++++++++ error: tuple constructor has 2 arguments but 1 were provided - --> $DIR/tuple_ctor_erroneous.rs:23:23 + --> $DIR/tuple_ctor_erroneous.rs:24:23 | LL | accepts_point::<{ Point(N) }>(); | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided - --> $DIR/tuple_ctor_erroneous.rs:26:23 + --> $DIR/tuple_ctor_erroneous.rs:27:23 | LL | accepts_point::<{ Point(N, N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:29:23 + --> $DIR/tuple_ctor_erroneous.rs:30:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ error: function items cannot be used as const args - --> $DIR/tuple_ctor_erroneous.rs:33:23 + --> $DIR/tuple_ctor_erroneous.rs:34:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:33:23 + --> $DIR/tuple_ctor_erroneous.rs:34:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:37:23 + --> $DIR/tuple_ctor_erroneous.rs:38:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` - --> $DIR/tuple_ctor_erroneous.rs:40:23 + --> $DIR/tuple_ctor_erroneous.rs:41:23 | LL | accepts_point::<{ Point }>(); | ^^^^^ expected `Point`, found struct constructor | note: required by a const generic parameter in `accepts_point` - --> $DIR/tuple_ctor_erroneous.rs:17:18 + --> $DIR/tuple_ctor_erroneous.rs:18:18 | LL | fn accepts_point() {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point` error: the constant `MyEnum::::Variant` is not of type `MyEnum` - --> $DIR/tuple_ctor_erroneous.rs:43:22 + --> $DIR/tuple_ctor_erroneous.rs:44:22 | LL | accepts_enum::<{ MyEnum::Variant:: }>(); | ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum`, found enum constructor | note: required by a const generic parameter in `accepts_enum` - --> $DIR/tuple_ctor_erroneous.rs:18:17 + --> $DIR/tuple_ctor_erroneous.rs:19:17 | LL | fn accepts_enum>() {} | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index c932fdd248dae..ea0edad9e673f 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -1,6 +1,8 @@ #![feature(min_generic_const_args, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const ASSOC: usize; @@ -10,11 +12,11 @@ fn takes_tuple() {} fn takes_nested_tuple() {} fn generic_caller() { - takes_tuple::<{ core::direct_const_arg!((N, N + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block - takes_tuple::<{ core::direct_const_arg!((N, T::ASSOC + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_tuple::<{ gca!((N, N + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_tuple::<{ gca!((N, T::ASSOC + 1)) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block - takes_nested_tuple::<{ core::direct_const_arg!((N, (N, N + 1))) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block - takes_nested_tuple::<{ core::direct_const_arg!((N, (N, const { N + 1 }))) }>(); //~ ERROR generic parameters may not be used in const operations + takes_nested_tuple::<{ gca!((N, (N, N + 1))) }>(); //~ ERROR complex const arguments must be placed inside of a `const` block + takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); //~ ERROR generic parameters may not be used in const operations } fn main() {} diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index 1ab93b1995749..045b9dd790919 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -1,26 +1,26 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:13:49 + --> $DIR/tuple_expr_arg_complex.rs:15:30 | -LL | takes_tuple::<{ core::direct_const_arg!((N, N + 1)) }>(); - | ^^^^^ +LL | takes_tuple::<{ gca!((N, N + 1)) }>(); + | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:14:49 + --> $DIR/tuple_expr_arg_complex.rs:16:30 | -LL | takes_tuple::<{ core::direct_const_arg!((N, T::ASSOC + 1)) }>(); - | ^^^^^^^^^^^^ +LL | takes_tuple::<{ gca!((N, T::ASSOC + 1)) }>(); + | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:16:60 + --> $DIR/tuple_expr_arg_complex.rs:18:41 | -LL | takes_nested_tuple::<{ core::direct_const_arg!((N, (N, N + 1))) }>(); - | ^^^^^ +LL | takes_nested_tuple::<{ gca!((N, (N, N + 1))) }>(); + | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_expr_arg_complex.rs:17:68 + --> $DIR/tuple_expr_arg_complex.rs:19:49 | -LL | takes_nested_tuple::<{ core::direct_const_arg!((N, (N, const { N + 1 }))) }>(); - | ^ +LL | takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index 70ca61c63c538..b4e664e1ca680 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] const ASSOC: u32; @@ -12,11 +14,11 @@ fn takes_tuple() {} fn takes_nested_tuple() {} fn generic_caller() { - takes_tuple::<{ core::direct_const_arg!((N, N2)) }>(); - takes_tuple::<{ core::direct_const_arg!((N, T::ASSOC)) }>(); + takes_tuple::<{ gca!((N, N2)) }>(); + takes_tuple::<{ gca!((N, T::ASSOC)) }>(); - takes_nested_tuple::<{ core::direct_const_arg!((N, (N, N2))) }>(); - takes_nested_tuple::<{ core::direct_const_arg!((N, (N, T::ASSOC))) }>(); + takes_nested_tuple::<{ gca!((N, (N, N2))) }>(); + takes_nested_tuple::<{ gca!((N, (N, T::ASSOC))) }>(); } fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs index 7b9923994b0ac..d41110e594514 100644 --- a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs +++ b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait Tr { #[rustc_always_gca] const SIZE: usize; @@ -13,7 +15,7 @@ struct T; impl Tr for T { const SIZE: usize; //~^ ERROR associated constant in `impl` without body - //~| ERROR implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS + //~| ERROR implementation of a `#[rustc_always_gca]` must have a `gca!` RHS } fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr index 7425c09bb8a6a..ac0a3054d000f 100644 --- a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr +++ b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.stderr @@ -1,19 +1,19 @@ error: associated constant in `impl` without body - --> $DIR/type-const-assoc-const-without-body.rs:14:5 + --> $DIR/type-const-assoc-const-without-body.rs:16:5 | LL | const SIZE: usize; | ^^^^^^^^^^^^^^^^^- | | | help: provide a definition for the constant: `= ;` -error: implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS - --> $DIR/type-const-assoc-const-without-body.rs:14:5 +error: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + --> $DIR/type-const-assoc-const-without-body.rs:16:5 | LL | const SIZE: usize; | ^^^^^^^^^^^^^^^^^ | note: trait declaration of const is marked as `#[rustc_always_gca]` - --> $DIR/type-const-assoc-const-without-body.rs:8:5 + --> $DIR/type-const-assoc-const-without-body.rs:10:5 | LL | const SIZE: usize; | ^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type-const-associated-default.rs b/tests/ui/const-generics/mgca/type-const-associated-default.rs index a6d7869261b24..f2591248269cc 100644 --- a/tests/ui/const-generics/mgca/type-const-associated-default.rs +++ b/tests/ui/const-generics/mgca/type-const-associated-default.rs @@ -1,8 +1,9 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; trait Trait { #[rustc_always_gca] - const N: usize = core::direct_const_arg!(10); + const N: usize = gca!(10); //~^ ERROR associated type defaults are unstable } diff --git a/tests/ui/const-generics/mgca/type-const-associated-default.stderr b/tests/ui/const-generics/mgca/type-const-associated-default.stderr index e2443d4e288e0..e08a8c75bc68e 100644 --- a/tests/ui/const-generics/mgca/type-const-associated-default.stderr +++ b/tests/ui/const-generics/mgca/type-const-associated-default.stderr @@ -1,8 +1,8 @@ error[E0658]: associated type defaults are unstable - --> $DIR/type-const-associated-default.rs:5:5 + --> $DIR/type-const-associated-default.rs:6:5 | -LL | const N: usize = core::direct_const_arg!(10); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const N: usize = gca!(10); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #29661 for more information = help: add `#![feature(associated_type_defaults)]` to the crate attributes to enable diff --git a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs index 2c5ce1a3f260d..774cab562cb61 100644 --- a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs +++ b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs @@ -10,13 +10,14 @@ #![feature(min_generic_const_args, adt_const_params)] #![expect(incomplete_features)] +use std::gca; use std::marker::ConstParamTy; #[derive(ConstParamTy, PartialEq, Eq)] struct S; impl S { - const N: S = core::direct_const_arg!(S); + const N: S = gca!(S); } #[derive(ConstParamTy, PartialEq, Eq)] @@ -25,7 +26,7 @@ enum E { } impl E { - const M: E = core::direct_const_arg!({ E::V }); + const M: E = gca!({ E::V }); } fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs index 31f5ce56f3979..3b76abd2edc3c 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -2,10 +2,12 @@ #![feature(min_generic_const_args)] -const X: usize = core::direct_const_arg!(const { N }); +use std::gca; + +const X: usize = gca!(const { N }); //~^ ERROR type annotations needed -const N: usize = core::direct_const_arg!("this isn't a usize"); +const N: usize = gca!("this isn't a usize"); //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` fn main() {} diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr index f8655132e9574..60dd8699d180f 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.stderr @@ -1,15 +1,15 @@ error[E0284]: type annotations needed - --> $DIR/type-const-free-anon-const-mismatch.rs:5:1 + --> $DIR/type-const-free-anon-const-mismatch.rs:7:1 | -LL | const X: usize = core::direct_const_arg!(const { N }); +LL | const X: usize = gca!(const { N }); | ^^^^^^^^^^^^^^ cannot infer the value of the constant `_` | = note: cannot satisfy `X::{constant#0} == _` error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-anon-const-mismatch.rs:8:1 + --> $DIR/type-const-free-anon-const-mismatch.rs:10:1 | -LL | const N: usize = core::direct_const_arg!("this isn't a usize"); +LL | const N: usize = gca!("this isn't a usize"); | ^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr index 425de1e1b1d4b..a2bd54b0b2b21 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:8:1 + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 | -LL | const N: usize = core::direct_const_arg!("this isn't a usize"); +LL | const N: usize = gca!("this isn't a usize"); | ^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-free-value-type-mismatch.rs:11:11 + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 | LL | fn f() -> [u8; const { N }] {} | - ^^^^^^^^^^^^^^^^^ expected `[u8; const { N }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr index 74fb8ab8999d9..d6b719115cad3 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.next.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-free-value-type-mismatch.rs:8:1 + --> $DIR/type-const-free-value-type-mismatch.rs:10:1 | -LL | const N: usize = core::direct_const_arg!("this isn't a usize"); +LL | const N: usize = gca!("this isn't a usize"); | ^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0284]: type annotations needed - --> $DIR/type-const-free-value-type-mismatch.rs:11:11 + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 | LL | fn f() -> [u8; const { N }] {} | ^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` @@ -13,7 +13,7 @@ LL | fn f() -> [u8; const { N }] {} = note: cannot satisfy `f::{constant#0} == _` error[E0308]: mismatched types - --> $DIR/type-const-free-value-type-mismatch.rs:11:11 + --> $DIR/type-const-free-value-type-mismatch.rs:13:11 | LL | fn f() -> [u8; const { N }] {} | - ^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs index 7cb465d114935..f49ac09ea3fcc 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -5,7 +5,9 @@ //@[next] compile-flags: -Znext-solver //@ compile-flags: -Zvalidate-mir -const N: usize = core::direct_const_arg!("this isn't a usize"); +use std::gca; + +const N: usize = gca!("this isn't a usize"); //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` fn f() -> [u8; const { N }] {} diff --git a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs index c1e0044b0947c..509bf3debc878 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs @@ -4,10 +4,12 @@ //@ compile-flags: --emit=mir -const CONST: usize = core::direct_const_arg!(1u32); +use std::gca; + +const CONST: usize = gca!(1u32); //~^ ERROR the constant `1` is not of type `usize` -const S: bool = core::direct_const_arg!(1i32); +const S: bool = gca!(1i32); //~^ ERROR the constant `1` is not of type `bool` fn main() { diff --git a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr index 1e20f48b7515c..a03b3db0a73f3 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr +++ b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.stderr @@ -1,13 +1,13 @@ error: the constant `1` is not of type `usize` - --> $DIR/type-const-free-value-used-in-body.rs:7:1 + --> $DIR/type-const-free-value-used-in-body.rs:9:1 | -LL | const CONST: usize = core::direct_const_arg!(1u32); +LL | const CONST: usize = gca!(1u32); | ^^^^^^^^^^^^^^^^^^ expected `usize`, found `u32` error: the constant `1` is not of type `bool` - --> $DIR/type-const-free-value-used-in-body.rs:10:1 + --> $DIR/type-const-free-value-used-in-body.rs:12:1 | -LL | const S: bool = core::direct_const_arg!(1i32); +LL | const S: bool = gca!(1i32); | ^^^^^^^^^^^^^ expected `bool`, found `i32` error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr index 017bc22d7fe0f..1b87914503453 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-inherent-value-type-mismatch.rs:13:5 + --> $DIR/type-const-inherent-value-type-mismatch.rs:15:5 | -LL | const N: usize = core::direct_const_arg!("this isn't a usize"); +LL | const N: usize = gca!("this isn't a usize"); | ^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:19:11 | LL | fn f() -> [u8; const { Struct::N }] {} | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Struct::N }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr index 111a1801d7adb..0da310a55c369 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.next.stderr @@ -1,5 +1,5 @@ error[E0284]: type annotations needed - --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:19:11 | LL | fn f() -> [u8; const { Struct::N }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` @@ -7,13 +7,13 @@ LL | fn f() -> [u8; const { Struct::N }] {} = note: cannot satisfy `f::{constant#0} == _` error: the constant `"this isn't a usize"` is not of type `usize` - --> $DIR/type-const-inherent-value-type-mismatch.rs:13:5 + --> $DIR/type-const-inherent-value-type-mismatch.rs:15:5 | -LL | const N: usize = core::direct_const_arg!("this isn't a usize"); +LL | const N: usize = gca!("this isn't a usize"); | ^^^^^^^^^^^^^^ expected `usize`, found `&'static str` error[E0308]: mismatched types - --> $DIR/type-const-inherent-value-type-mismatch.rs:17:11 + --> $DIR/type-const-inherent-value-type-mismatch.rs:19:11 | LL | fn f() -> [u8; const { Struct::N }] {} | - ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs index a08f31e686f2f..3a0fdd6bfd0ea 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -7,10 +7,12 @@ #![feature(min_generic_const_args)] +use std::gca; + struct Struct; impl Struct { - const N: usize = core::direct_const_arg!("this isn't a usize"); + const N: usize = gca!("this isn't a usize"); //~^ ERROR the constant `"this isn't a usize"` is not of type `usize` } diff --git a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs index 71bdc472e2e22..1f921960710c5 100644 --- a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs +++ b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs @@ -3,7 +3,9 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] -const N: usize = core::direct_const_arg!(2); +use std::gca; + +const N: usize = gca!(2); trait CollectArray { fn inner_array(&mut self) -> [A; N]; diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr index 614946eb7dc0f..dc7f73f2549e8 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.current.stderr @@ -1,11 +1,11 @@ error[E0053]: method `arr` has an incompatible type for trait - --> $DIR/type-const-value-type-mismatch.rs:22:5 + --> $DIR/type-const-value-type-mismatch.rs:24:5 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an array with a size of 0, found one with a size of const { Self::LEN } | note: type in trait - --> $DIR/type-const-value-type-mismatch.rs:15:5 + --> $DIR/type-const-value-type-mismatch.rs:17:5 | LL | fn arr() -> [u8; Self::LEN]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | fn arr() -> [u8; Self::LEN]; found signature `fn() -> [u8; const { Self::LEN }]` error: the constant `0` is not of type `usize` - --> $DIR/type-const-value-type-mismatch.rs:19:5 + --> $DIR/type-const-value-type-mismatch.rs:21:5 | -LL | const LEN: usize = core::direct_const_arg!(0u8); +LL | const LEN: usize = gca!(0u8); | ^^^^^^^^^^^^^^^^ expected `usize`, found `u8` error[E0308]: mismatched types - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:24:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; const { Self::LEN }]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr index 9180bf19727cf..8e006112641a3 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.next.stderr @@ -1,17 +1,17 @@ error[E0271]: type mismatch resolving `::LEN == _` - --> $DIR/type-const-value-type-mismatch.rs:22:5 + --> $DIR/type-const-value-type-mismatch.rs:24:5 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ error: the constant `0` is not of type `usize` - --> $DIR/type-const-value-type-mismatch.rs:19:5 + --> $DIR/type-const-value-type-mismatch.rs:21:5 | -LL | const LEN: usize = core::direct_const_arg!(0u8); +LL | const LEN: usize = gca!(0u8); | ^^^^^^^^^^^^^^^^ expected `usize`, found `u8` error[E0284]: type annotations needed - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:24:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer the value of the constant `_` @@ -19,7 +19,7 @@ LL | fn arr() -> [u8; const { Self::LEN }] {} = note: cannot satisfy `::arr::{constant#0}::{constant#0} == _` error[E0308]: mismatched types - --> $DIR/type-const-value-type-mismatch.rs:22:17 + --> $DIR/type-const-value-type-mismatch.rs:24:17 | LL | fn arr() -> [u8; const { Self::LEN }] {} | --- ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `[u8; _]`, found `()` diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs index 5609924575693..0a9f90e90de7f 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -7,6 +7,8 @@ #![feature(min_generic_const_args, macroless_generic_const_args)] +use std::gca; + pub struct A; pub trait Array { @@ -16,7 +18,7 @@ pub trait Array { } impl Array for A { - const LEN: usize = core::direct_const_arg!(0u8); + const LEN: usize = gca!(0u8); //~^ ERROR the constant `0` is not of type `usize` fn arr() -> [u8; const { Self::LEN }] {} diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs index 4d4fcdb03164b..421b6b4cb5993 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -5,9 +5,11 @@ #![feature(macroless_generic_const_args)] #![feature(generic_const_items)] -const ADD1: usize = core::direct_const_arg!(const { N + 1 }); +use std::gca; + +const ADD1: usize = gca!(const { N + 1 }); //~^ ERROR: unconstrained generic constant -const AliasFnUnused: ADD1 = core::direct_const_arg!(ADD1::<{ Some:: {} }>); +const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); //~^ ERROR: cannot find type `ADD1` in this scope [E0573] //~| ERROR: struct expression with missing field initialiser for `0` diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr index 7a5a299320459..623ae087687f5 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr @@ -1,27 +1,27 @@ error[E0573]: cannot find type `ADD1` in this scope - --> $DIR/type_const-adt-expr-missing-field.rs:10:22 + --> $DIR/type_const-adt-expr-missing-field.rs:12:22 | -LL | const AliasFnUnused: ADD1 = core::direct_const_arg!(ADD1::<{ Some:: {} }>); +LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^ not found in this scope | = note: a constant named `ADD1` exists in another namespace error: unconstrained generic constant - --> $DIR/type_const-adt-expr-missing-field.rs:8:1 + --> $DIR/type_const-adt-expr-missing-field.rs:10:1 | -LL | const ADD1: usize = core::direct_const_arg!(const { N + 1 }); +LL | const ADD1: usize = gca!(const { N + 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | help: try adding a `where` bound | -LL | const ADD1: usize where [(); const { N + 1 }]: = core::direct_const_arg!(const { N + 1 }); +LL | const ADD1: usize where [(); const { N + 1 }]: = gca!(const { N + 1 }); | ++++++++++++++++++++++++++++ error: struct expression with missing field initialiser for `0` - --> $DIR/type_const-adt-expr-missing-field.rs:10:62 + --> $DIR/type_const-adt-expr-missing-field.rs:12:43 | -LL | const AliasFnUnused: ADD1 = core::direct_const_arg!(ADD1::<{ Some:: {} }>); - | ^^^^^^^^^^^^^^^^ +LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); + | ^^^^^^^^^^^^^^^^ error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-array-return.rs b/tests/ui/const-generics/mgca/type_const-array-return.rs index 5b8f50925529d..ed27f0df8599b 100644 --- a/tests/ui/const-generics/mgca/type_const-array-return.rs +++ b/tests/ui/const-generics/mgca/type_const-array-return.rs @@ -3,6 +3,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, macroless_generic_const_args)] +use std::gca; + pub struct A; pub trait Array { @@ -12,7 +14,7 @@ pub trait Array { } impl Array for A { - const LEN: usize = core::direct_const_arg!(4); + const LEN: usize = gca!(4); #[allow(unused_braces)] fn arr() -> [u8; const { Self::LEN }] { diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr index 03251f4c7bd2b..46be38bb1a53d 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr @@ -1,37 +1,37 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:12:1 + --> $DIR/type_const-generic-param-in-type.rs:13:1 | -LL | const FOO: [T; 0] = core::direct_const_arg!([]); +LL | const FOO: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:15:1 + --> $DIR/type_const-generic-param-in-type.rs:16:1 | -LL | const BAR: StructWithConstParam = +LL | const BAR: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters --> $DIR/type_const-generic-param-in-type.rs:19:1 | -LL | const BAZ<'a>: [&'a (); 0] = core::direct_const_arg!([]); +LL | const BAZ<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters --> $DIR/type_const-generic-param-in-type.rs:37:5 | -LL | const ASSOC: [T; 0] = core::direct_const_arg!([]); +LL | const ASSOC: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters --> $DIR/type_const-generic-param-in-type.rs:40:5 | -LL | const ASSOC_CONST: StructWithConstParam = +LL | const ASSOC_CONST: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:44:5 + --> $DIR/type_const-generic-param-in-type.rs:43:5 | -LL | const ASSOC_LT<'a>: [&'a (); 0] = core::direct_const_arg!([]); +LL | const ASSOC_LT<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index e5e36b79eca57..d8c1627858257 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -4,19 +4,19 @@ #![feature(adt_const_params, unsized_const_params, min_generic_const_args, generic_const_items)] #![cfg_attr(gate, feature(generic_const_parameter_types))] +use std::gca; use std::marker::ConstParamTy; #[derive(ConstParamTy, PartialEq, Eq, Debug)] struct StructWithConstParam; -const FOO: [T; 0] = core::direct_const_arg!([]); +const FOO: [T; 0] = gca!([]); //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters -const BAR: StructWithConstParam = - //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - core::direct_const_arg!(StructWithConstParam::); +const BAR: StructWithConstParam = gca!(StructWithConstParam::); +//[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters -const BAZ<'a>: [&'a (); 0] = core::direct_const_arg!([]); +const BAZ<'a>: [&'a (); 0] = gca!([]); //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters trait Tr { @@ -34,14 +34,13 @@ trait Tr { } impl Tr for () { - const ASSOC: [T; 0] = core::direct_const_arg!([]); + const ASSOC: [T; 0] = gca!([]); //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - const ASSOC_CONST: StructWithConstParam = - //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - core::direct_const_arg!(StructWithConstParam::); + const ASSOC_CONST: StructWithConstParam = gca!(StructWithConstParam::); + //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters - const ASSOC_LT<'a>: [&'a (); 0] = core::direct_const_arg!([]); + const ASSOC_LT<'a>: [&'a (); 0] = gca!([]); //[nogate]~^ ERROR the type of const parameters must not depend on other generic parameters } diff --git a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs index 59581327cbb2d..7f82050044fad 100644 --- a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs +++ b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs @@ -6,5 +6,7 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -const TYPE_CONST: usize = core::direct_const_arg!(0); +use std::gca; + +const TYPE_CONST: usize = gca!(0); fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs index 81c567f034e1e..32d052204ee27 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs @@ -1,10 +1,12 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + struct A; impl A { - const B = core::direct_const_arg!(4); + const B = gca!(4); //~^ ERROR: missing type for `const` item //~| ERROR: type annotations needed for the literal } diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr index 742e5aff86285..04f8051509ab1 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.stderr @@ -1,19 +1,19 @@ error: missing type for `const` item - --> $DIR/type_const-inherent-const-omitted-type.rs:7:12 + --> $DIR/type_const-inherent-const-omitted-type.rs:9:12 | -LL | const B = core::direct_const_arg!(4); +LL | const B = gca!(4); | ^ | help: provide a type for the item | -LL | const B: = core::direct_const_arg!(4); +LL | const B: = gca!(4); | ++++++++ error: type annotations needed for the literal - --> $DIR/type_const-inherent-const-omitted-type.rs:7:39 + --> $DIR/type_const-inherent-const-omitted-type.rs:9:20 | -LL | const B = core::direct_const_arg!(4); - | ^ +LL | const B = gca!(4); + | ^ error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs index af59430e5b6ef..620c49cc6fe0f 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs @@ -2,10 +2,13 @@ //! //@ incremental #![feature(min_generic_const_args)] -const R: usize = core::direct_const_arg!(1_i32); //~ ERROR: the constant `1` is not of type `usize` -const U: usize = core::direct_const_arg!(-1_i32); //~ ERROR: the constant `-1` is not of type `usize` -const S: bool = core::direct_const_arg!(1i32); //~ ERROR: the constant `1` is not of type `bool` -const T: bool = core::direct_const_arg!(-1i32); //~ ERROR: the constant `-1` is not of type `bool` + +use std::gca; + +const R: usize = gca!(1_i32); //~ ERROR: the constant `1` is not of type `usize` +const U: usize = gca!(-1_i32); //~ ERROR: the constant `-1` is not of type `usize` +const S: bool = gca!(1i32); //~ ERROR: the constant `1` is not of type `bool` +const T: bool = gca!(-1i32); //~ ERROR: the constant `-1` is not of type `bool` fn main() { R; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr index 86c807d9df356..2b05fe422b4a6 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.stderr @@ -1,25 +1,25 @@ error: the constant `1` is not of type `usize` - --> $DIR/type_const-mismatched-type-incremental.rs:5:1 + --> $DIR/type_const-mismatched-type-incremental.rs:8:1 | -LL | const R: usize = core::direct_const_arg!(1_i32); +LL | const R: usize = gca!(1_i32); | ^^^^^^^^^^^^^^ expected `usize`, found `i32` error: the constant `-1` is not of type `usize` - --> $DIR/type_const-mismatched-type-incremental.rs:6:1 + --> $DIR/type_const-mismatched-type-incremental.rs:9:1 | -LL | const U: usize = core::direct_const_arg!(-1_i32); +LL | const U: usize = gca!(-1_i32); | ^^^^^^^^^^^^^^ expected `usize`, found `i32` error: the constant `1` is not of type `bool` - --> $DIR/type_const-mismatched-type-incremental.rs:7:1 + --> $DIR/type_const-mismatched-type-incremental.rs:10:1 | -LL | const S: bool = core::direct_const_arg!(1i32); +LL | const S: bool = gca!(1i32); | ^^^^^^^^^^^^^ expected `bool`, found `i32` error: the constant `-1` is not of type `bool` - --> $DIR/type_const-mismatched-type-incremental.rs:8:1 + --> $DIR/type_const-mismatched-type-incremental.rs:11:1 | -LL | const T: bool = core::direct_const_arg!(-1i32); +LL | const T: bool = gca!(-1i32); | ^^^^^^^^^^^^^ expected `bool`, found `i32` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index 9dbba436520c6..d4169868903b2 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -1,10 +1,12 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -const FREE: u32 = core::direct_const_arg!(5_usize); +use std::gca; + +const FREE: u32 = gca!(5_usize); //~^ ERROR the constant `5` is not of type `u32` -const FREE2: isize = core::direct_const_arg!(FREE); +const FREE2: isize = gca!(FREE); //~^ ERROR the constant `5` is not of type `u32` //~| ERROR the constant `5` is not of type `isize` @@ -14,7 +16,7 @@ trait Tr { } impl Tr for () { - const N: usize = core::direct_const_arg!(false); + const N: usize = gca!(false); //~^ ERROR the constant `false` is not of type `usize` } diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr index e4b3e39180361..3cba92197dcae 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.stderr @@ -1,25 +1,25 @@ error: the constant `5` is not of type `u32` - --> $DIR/type_const-mismatched-types.rs:4:1 + --> $DIR/type_const-mismatched-types.rs:6:1 | -LL | const FREE: u32 = core::direct_const_arg!(5_usize); +LL | const FREE: u32 = gca!(5_usize); | ^^^^^^^^^^^^^^^ expected `u32`, found `usize` error: the constant `5` is not of type `u32` - --> $DIR/type_const-mismatched-types.rs:7:1 + --> $DIR/type_const-mismatched-types.rs:9:1 | -LL | const FREE2: isize = core::direct_const_arg!(FREE); +LL | const FREE2: isize = gca!(FREE); | ^^^^^^^^^^^^^^^^^^ expected `u32`, found `usize` error: the constant `5` is not of type `isize` - --> $DIR/type_const-mismatched-types.rs:7:1 + --> $DIR/type_const-mismatched-types.rs:9:1 | -LL | const FREE2: isize = core::direct_const_arg!(FREE); +LL | const FREE2: isize = gca!(FREE); | ^^^^^^^^^^^^^^^^^^ expected `isize`, found `usize` error: the constant `false` is not of type `usize` - --> $DIR/type_const-mismatched-types.rs:17:5 + --> $DIR/type_const-mismatched-types.rs:19:5 | -LL | const N: usize = core::direct_const_arg!(false); +LL | const N: usize = gca!(false); | ^^^^^^^^^^^^^^ expected `usize`, found `bool` error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs index 27debb924ffd6..bc26ee967f573 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs @@ -1,11 +1,13 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + struct S; // FIXME(mgca): need support for ctors without anon const // (we use a const-block to trigger an anon const here) -const FREE: S = core::direct_const_arg!(const { S }); +const FREE: S = gca!(const { S }); //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter trait Tr { @@ -17,7 +19,7 @@ trait Tr { impl Tr for S { // FIXME(mgca): need support for ctors without anon const // (we use a const-block to trigger an anon const here) - const N: S = core::direct_const_arg!(const { S }); + const N: S = gca!(const { S }); //~^ ERROR `S` must implement `ConstParamTy` to be used as the type of a const generic parameter } diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr index 7492432119943..9c55277eb3b39 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.stderr @@ -1,7 +1,7 @@ error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:8:13 + --> $DIR/type_const-not-constparamty.rs:10:13 | -LL | const FREE: S = core::direct_const_arg!(const { S }); +LL | const FREE: S = gca!(const { S }); | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct @@ -11,9 +11,9 @@ LL | struct S; | error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:20:14 + --> $DIR/type_const-not-constparamty.rs:22:14 | -LL | const N: S = core::direct_const_arg!(const { S }); +LL | const N: S = gca!(const { S }); | ^ | help: add `#[derive(ConstParamTy, PartialEq, Eq)]` to the struct @@ -23,7 +23,7 @@ LL | struct S; | error[E0741]: `S` must implement `ConstParamTy` to be used as the type of a const generic parameter - --> $DIR/type_const-not-constparamty.rs:13:14 + --> $DIR/type_const-not-constparamty.rs:15:14 | LL | const N: S; | ^ diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs index 574a5febadaac..ce6ca6cf01bf0 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs @@ -1,10 +1,12 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, generic_const_items)] -const FREE1: usize = core::direct_const_arg!(const { std::mem::size_of::() }); +use std::gca; + +const FREE1: usize = gca!(const { std::mem::size_of::() }); //~^ ERROR generic parameters may not be used in const operations -const FREE2: usize = core::direct_const_arg!(const { I + 1 }); +const FREE2: usize = gca!(const { I + 1 }); //~^ ERROR generic parameters may not be used in const operations fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index 1e11af4de9571..545675ead06a5 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -1,16 +1,16 @@ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:4:77 + --> $DIR/type_const-on-generic-expr.rs:6:58 | -LL | const FREE1: usize = core::direct_const_arg!(const { std::mem::size_of::() }); - | ^ +LL | const FREE1: usize = gca!(const { std::mem::size_of::() }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic-expr.rs:7:70 + --> $DIR/type_const-on-generic-expr.rs:9:51 | -LL | const FREE2: usize = core::direct_const_arg!(const { I + 1 }); - | ^ +LL | const FREE2: usize = gca!(const { I + 1 }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs index b82eb2f046485..59898c76f4e78 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs @@ -1,6 +1,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args, generic_const_items)] +use std::gca; + pub trait Tr { #[rustc_always_gca] const N1: usize; @@ -13,11 +15,11 @@ pub trait Tr { pub struct S; impl Tr for S { - const N1: usize = core::direct_const_arg!(const { std::mem::size_of::() }); + const N1: usize = gca!(const { std::mem::size_of::() }); //~^ ERROR generic parameters may not be used in const operations - const N2: usize = core::direct_const_arg!(const { I + 1 }); + const N2: usize = gca!(const { I + 1 }); //~^ ERROR generic parameters may not be used in const operations - const N3: usize = core::direct_const_arg!(const { 2 & X }); + const N3: usize = gca!(const { 2 & X }); //~^ ERROR generic parameters may not be used in const operations } diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr index cac6858b937c0..4eb207e110fdb 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr @@ -1,24 +1,24 @@ error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:16:78 + --> $DIR/type_const-on-generic_expr-2.rs:18:59 | -LL | const N1: usize = core::direct_const_arg!(const { std::mem::size_of::() }); - | ^ +LL | const N1: usize = gca!(const { std::mem::size_of::() }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:18:71 + --> $DIR/type_const-on-generic_expr-2.rs:20:52 | -LL | const N2: usize = core::direct_const_arg!(const { I + 1 }); - | ^ +LL | const N2: usize = gca!(const { I + 1 }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations - --> $DIR/type_const-on-generic_expr-2.rs:20:59 + --> $DIR/type_const-on-generic_expr-2.rs:22:40 | -LL | const N3: usize = core::direct_const_arg!(const { 2 & X }); - | ^ +LL | const N3: usize = gca!(const { 2 & X }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs index 853eb37aae3f0..5a716807fc3e4 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs @@ -1,6 +1,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + trait BadTr { const NUM: usize; } @@ -8,10 +10,10 @@ trait BadTr { struct GoodS; impl BadTr for GoodS { - const NUM: = core::direct_const_arg!(84); + const NUM: = gca!(84); //~^ ERROR: missing type for `const` item //~| ERROR: type annotations needed for the literal - //~| ERROR: implementation of a regular const cannot have a `direct_const_arg!` RHS + //~| ERROR: implementation of a regular const cannot have a `gca!` RHS } fn accept_bad_tr>(_x: &T) {} diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr index 445d5d4a2efd9..18dc857d1deb0 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.stderr @@ -1,29 +1,29 @@ error: missing type for `const` item - --> $DIR/type_const-only-in-impl-omitted-type.rs:11:15 + --> $DIR/type_const-only-in-impl-omitted-type.rs:13:15 | -LL | const NUM: = core::direct_const_arg!(84); +LL | const NUM: = gca!(84); | ^ help: provide a type for the associated constant: `usize` error: type annotations needed for the literal - --> $DIR/type_const-only-in-impl-omitted-type.rs:11:42 + --> $DIR/type_const-only-in-impl-omitted-type.rs:13:23 | -LL | const NUM: = core::direct_const_arg!(84); - | ^^ +LL | const NUM: = gca!(84); + | ^^ -error: implementation of a regular const cannot have a `direct_const_arg!` RHS - --> $DIR/type_const-only-in-impl-omitted-type.rs:11:5 +error: implementation of a regular const cannot have a `gca!` RHS + --> $DIR/type_const-only-in-impl-omitted-type.rs:13:5 | -LL | const NUM: = core::direct_const_arg!(84); +LL | const NUM: = gca!(84); | ^^^^^^^^^^ | note: trait declaration of const is not marked as `#[rustc_always_gca]` - --> $DIR/type_const-only-in-impl-omitted-type.rs:5:5 + --> $DIR/type_const-only-in-impl-omitted-type.rs:7:5 | LL | const NUM: usize; | ^^^^^^^^^^^^^^^^ error: use of trait associated const not defined as `#[rustc_always_gca]` - --> $DIR/type_const-only-in-impl-omitted-type.rs:17:43 + --> $DIR/type_const-only-in-impl-omitted-type.rs:19:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs index 3f8b924af0799..f536e810348d8 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs @@ -1,6 +1,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + trait BadTr { const NUM: usize; } @@ -8,8 +10,8 @@ trait BadTr { struct GoodS; impl BadTr for GoodS { - const NUM: usize = core::direct_const_arg!(84); - //~^ ERROR implementation of a regular const cannot have a `direct_const_arg!` RHS + const NUM: usize = gca!(84); + //~^ ERROR implementation of a regular const cannot have a `gca!` RHS } fn accept_bad_tr>(_x: &T) {} diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr b/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr index cc32eafad40fc..99b49c6e8bdcd 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.stderr @@ -1,17 +1,17 @@ -error: implementation of a regular const cannot have a `direct_const_arg!` RHS - --> $DIR/type_const-only-in-impl.rs:11:5 +error: implementation of a regular const cannot have a `gca!` RHS + --> $DIR/type_const-only-in-impl.rs:13:5 | -LL | const NUM: usize = core::direct_const_arg!(84); +LL | const NUM: usize = gca!(84); | ^^^^^^^^^^^^^^^^ | note: trait declaration of const is not marked as `#[rustc_always_gca]` - --> $DIR/type_const-only-in-impl.rs:5:5 + --> $DIR/type_const-only-in-impl.rs:7:5 | LL | const NUM: usize; | ^^^^^^^^^^^^^^^^ error: use of trait associated const not defined as `#[rustc_always_gca]` - --> $DIR/type_const-only-in-impl.rs:15:43 + --> $DIR/type_const-only-in-impl.rs:17:43 | LL | fn accept_bad_tr>(_x: &T) {} | ^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs index 82c5a6f8417a5..687adf8371272 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs @@ -1,6 +1,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + trait GoodTr { #[rustc_always_gca] const NUM: usize; @@ -10,7 +12,7 @@ struct BadS; impl GoodTr for BadS { const NUM: usize = 42; - //~^ ERROR implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS + //~^ ERROR implementation of a `#[rustc_always_gca]` must have a `gca!` RHS } fn accept_good_tr>(_x: &T) {} diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr index e2ba59133925f..cab3f9b08aec1 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.stderr @@ -1,11 +1,11 @@ -error: implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS - --> $DIR/type_const-only-in-trait.rs:12:5 +error: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS + --> $DIR/type_const-only-in-trait.rs:14:5 | LL | const NUM: usize = 42; | ^^^^^^^^^^^^^^^^ | note: trait declaration of const is marked as `#[rustc_always_gca]` - --> $DIR/type_const-only-in-trait.rs:6:5 + --> $DIR/type_const-only-in-trait.rs:8:5 | LL | const NUM: usize; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-pub.rs b/tests/ui/const-generics/mgca/type_const-pub.rs index 36936e22726d4..9499e7e952384 100644 --- a/tests/ui/const-generics/mgca/type_const-pub.rs +++ b/tests/ui/const-generics/mgca/type_const-pub.rs @@ -5,7 +5,9 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -pub const TYPE_CONST: usize = core::direct_const_arg!(1); +use std::gca; + +pub const TYPE_CONST: usize = gca!(1); fn main() { print!("{}", TYPE_CONST) } diff --git a/tests/ui/const-generics/mgca/type_const-recursive.rs b/tests/ui/const-generics/mgca/type_const-recursive.rs index 1963cdce9fe4c..c7178da8f437c 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.rs +++ b/tests/ui/const-generics/mgca/type_const-recursive.rs @@ -1,7 +1,9 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -const A: u8 = core::direct_const_arg!(A); +use std::gca; + +const A: u8 = gca!(A); //~^ ERROR: cycle detected when computing the type-level value for `A` [E0391] fn main() {} diff --git a/tests/ui/const-generics/mgca/type_const-recursive.stderr b/tests/ui/const-generics/mgca/type_const-recursive.stderr index 2dd4102b472bc..551fc016b2c73 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.stderr +++ b/tests/ui/const-generics/mgca/type_const-recursive.stderr @@ -1,7 +1,7 @@ error[E0391]: cycle detected when computing the type-level value for `A` - --> $DIR/type_const-recursive.rs:4:1 + --> $DIR/type_const-recursive.rs:6:1 | -LL | const A: u8 = core::direct_const_arg!(A); +LL | const A: u8 = gca!(A); | ^^^^^^^^^^^ | = note: ...which immediately requires computing the type-level value for `A` again diff --git a/tests/ui/const-generics/mgca/type_const-use.rs b/tests/ui/const-generics/mgca/type_const-use.rs index cef0d10f0c4ed..e8900e0d4e69e 100644 --- a/tests/ui/const-generics/mgca/type_const-use.rs +++ b/tests/ui/const-generics/mgca/type_const-use.rs @@ -3,7 +3,9 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] -const CONST: usize = core::direct_const_arg!(1); +use std::gca; + +const CONST: usize = gca!(1); fn uses_const() { CONST; diff --git a/tests/ui/const-generics/mgca/type_const_in_pattern.rs b/tests/ui/const-generics/mgca/type_const_in_pattern.rs index 01fae246f9293..52d824343c2a6 100644 --- a/tests/ui/const-generics/mgca/type_const_in_pattern.rs +++ b/tests/ui/const-generics/mgca/type_const_in_pattern.rs @@ -3,12 +3,14 @@ #![expect(incomplete_features)] #![allow(irrefutable_let_patterns)] -const CONST: usize = core::direct_const_arg!(1_usize); +use std::gca; + +const CONST: usize = gca!(1_usize); struct Inherent; impl Inherent { - const BAR: usize = core::direct_const_arg!(1_usize); + const BAR: usize = gca!(1_usize); } trait Trait { @@ -19,7 +21,7 @@ trait Trait { struct Assoc; impl Trait for Assoc { - const BAZ: usize = core::direct_const_arg!(1_usize); + const BAZ: usize = gca!(1_usize); } fn main() { diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs index e341727407143..9e6370c485a0b 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -1,5 +1,7 @@ #![feature(adt_const_params)] +use std::gca; + #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct Inner; @@ -32,9 +34,9 @@ fn generic() { const NON_TYPE_CONST: usize = const { 1 }; -const TYPE_CONST: usize = core::direct_const_arg!(const { 1 }); +const TYPE_CONST: usize = gca!(const { 1 }); //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] -//~| ERROR: expected expression, found `direct_const_arg!()` constant +//~| ERROR: expected expression, found `gca!()` constant static STATIC: usize = const { 1 }; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr index bd2b5238a9356..8467c3abdc942 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -1,15 +1,15 @@ error[E0658]: use of unstable library feature `min_generic_const_args` - --> $DIR/unbraced_const_block_const_arg_gated.rs:35:27 + --> $DIR/unbraced_const_block_const_arg_gated.rs:37:27 | -LL | const TYPE_CONST: usize = core::direct_const_arg!(const { 1 }); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | const TYPE_CONST: usize = gca!(const { 1 }); + | ^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:7:27 + --> $DIR/unbraced_const_block_const_arg_gated.rs:9:27 | LL | const PARAM_TY: Inner, | ^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | const PARAM_TY: Inner, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:9:28 + --> $DIR/unbraced_const_block_const_arg_gated.rs:11:28 | LL | const DEFAULT: usize = const { 1 }, | ^^^^^^^^^^^ @@ -29,7 +29,7 @@ LL | const DEFAULT: usize = const { 1 }, = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:14:23 + --> $DIR/unbraced_const_block_const_arg_gated.rs:16:23 | LL | type NormalTy = Inner; | ^^^^^^^^^^^ @@ -39,7 +39,7 @@ LL | type NormalTy = Inner; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:22:18 + --> $DIR/unbraced_const_block_const_arg_gated.rs:24:18 | LL | let _: Inner; | ^^^^^^^^^^^ @@ -49,7 +49,7 @@ LL | let _: Inner; = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental - --> $DIR/unbraced_const_block_const_arg_gated.rs:28:19 + --> $DIR/unbraced_const_block_const_arg_gated.rs:30:19 | LL | generic::(); | ^^^^^^^^^^^ @@ -58,11 +58,11 @@ LL | generic::(); = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant - --> $DIR/unbraced_const_block_const_arg_gated.rs:35:27 +error: expected expression, found `gca!()` constant + --> $DIR/unbraced_const_block_const_arg_gated.rs:37:27 | -LL | const TYPE_CONST: usize = core::direct_const_arg!(const { 1 }); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const TYPE_CONST: usize = gca!(const { 1 }); + | ^^^^^^^^^^^^^^^^^ error: aborting due to 7 previous errors diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.rs b/tests/ui/const-generics/mgca/unmarked-free-const.rs index e118b486f2c77..04cf63b71ed07 100644 --- a/tests/ui/const-generics/mgca/unmarked-free-const.rs +++ b/tests/ui/const-generics/mgca/unmarked-free-const.rs @@ -3,9 +3,11 @@ #![feature(min_generic_const_args)] #![allow(incomplete_features)] +use std::gca; + const N: usize = 4; fn main() { - let x = [(); core::direct_const_arg!(N)]; + let x = [(); gca!(N)]; //~^ ERROR use of `const` in the type system not marked as direct } diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.stderr b/tests/ui/const-generics/mgca/unmarked-free-const.stderr index 246a8200247c1..de797a46f33ce 100644 --- a/tests/ui/const-generics/mgca/unmarked-free-const.stderr +++ b/tests/ui/const-generics/mgca/unmarked-free-const.stderr @@ -1,13 +1,13 @@ error: use of `const` in the type system not marked as direct - --> $DIR/unmarked-free-const.rs:9:42 + --> $DIR/unmarked-free-const.rs:11:23 | -LL | let x = [(); core::direct_const_arg!(N)]; - | ^ +LL | let x = [(); gca!(N)]; + | ^ | -help: add direct_const_arg!() to the right-hand side of the constant +help: add gca!() to the right-hand side of the constant | -LL | const N: usize = core::direct_const_arg!(4); - | ++++++++++++++++++++++++ + +LL | const N: usize = core::gca!(4); + | +++++++++++ + error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.rs b/tests/ui/const-generics/type-const-ice-issue-151631.rs index 8112d21a923f0..6133feba70a3b 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.rs +++ b/tests/ui/const-generics/type-const-ice-issue-151631.rs @@ -3,6 +3,8 @@ #![feature(min_generic_const_args)] #![expect(incomplete_features)] +use std::gca; + trait SuperTrait {} trait Trait: SuperTrait { #[rustc_always_gca] @@ -10,7 +12,7 @@ trait Trait: SuperTrait { } impl Trait for () { //~^ ERROR: the trait bound `(): SuperTrait` is not satisfied - const K: u32 = core::direct_const_arg!(const { 1 }); + const K: u32 = gca!(const { 1 }); } fn check(_: impl Trait) {} diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.stderr b/tests/ui/const-generics/type-const-ice-issue-151631.stderr index aa934b91fb5a4..2a42518efc790 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.stderr +++ b/tests/ui/const-generics/type-const-ice-issue-151631.stderr @@ -1,22 +1,22 @@ error[E0277]: the trait bound `(): SuperTrait` is not satisfied - --> $DIR/type-const-ice-issue-151631.rs:11:16 + --> $DIR/type-const-ice-issue-151631.rs:13:16 | LL | impl Trait for () { | ^^ the trait `SuperTrait` is not implemented for `()` | help: this trait has no implementations, consider adding one - --> $DIR/type-const-ice-issue-151631.rs:6:1 + --> $DIR/type-const-ice-issue-151631.rs:8:1 | LL | trait SuperTrait {} | ^^^^^^^^^^^^^^^^ note: required by a bound in `Trait` - --> $DIR/type-const-ice-issue-151631.rs:7:14 + --> $DIR/type-const-ice-issue-151631.rs:9:14 | LL | trait Trait: SuperTrait { | ^^^^^^^^^^ required by this bound in `Trait` error[E0271]: type mismatch resolving `<() as Trait>::K == 0` - --> $DIR/type-const-ice-issue-151631.rs:19:11 + --> $DIR/type-const-ice-issue-151631.rs:21:11 | LL | check(()); | ----- ^^ expected `0`, found `1` @@ -26,7 +26,7 @@ LL | check(()); = note: expected constant `0` found constant `1` note: required by a bound in `check` - --> $DIR/type-const-ice-issue-151631.rs:16:24 + --> $DIR/type-const-ice-issue-151631.rs:18:24 | LL | fn check(_: impl Trait) {} | ^^^^^ required by this bound in `check` diff --git a/tests/ui/const-generics/type-relative-path-144547.rs b/tests/ui/const-generics/type-relative-path-144547.rs index 399918ec6cffc..35722efd17fd4 100644 --- a/tests/ui/const-generics/type-relative-path-144547.rs +++ b/tests/ui/const-generics/type-relative-path-144547.rs @@ -22,7 +22,7 @@ struct Info; impl LevelInfo for Info { #[cfg(mgca)] - const SUPPORTED_SLOTS: usize = core::direct_const_arg!(1); + const SUPPORTED_SLOTS: usize = std::gca!(1); #[cfg(not(mgca))] const SUPPORTED_SLOTS: usize = 1; diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr index 30aad09279447..290c5a492fa90 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155125.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `foo` is defined multiple times - --> $DIR/hir-crate-items-before-lowering-ices.rs:13:17 + --> $DIR/hir-crate-items-before-lowering-ices.rs:14:17 | LL | fn foo() {} | -------- previous definition of the value `foo` here @@ -9,10 +9,10 @@ LL | reuse foo; = note: `foo` must be defined only once in the value namespace of this block error: complex const arguments must be placed inside of a `const` block - --> $DIR/hir-crate-items-before-lowering-ices.rs:11:37 + --> $DIR/hir-crate-items-before-lowering-ices.rs:12:18 | -LL | core::direct_const_arg!({ - | _____________________________________^ +LL | gca!({ + | __________________^ LL | | fn foo() {} LL | | reuse foo; LL | | 2 diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr index e38645655a8a5..571a0f7198df9 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155127.stderr @@ -1,5 +1,5 @@ error: the `deprecated` attribute cannot be used on delegations - --> $DIR/hir-crate-items-before-lowering-ices.rs:27:11 + --> $DIR/hir-crate-items-before-lowering-ices.rs:28:11 | LL | #[deprecated] | ^^^^^^^^^^ diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr index 674035c79f019..9f1e95d570b53 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155128.stderr @@ -1,5 +1,5 @@ error: delegation's target expression is specified for function with no params - --> $DIR/hir-crate-items-before-lowering-ices.rs:37:18 + --> $DIR/hir-crate-items-before-lowering-ices.rs:38:18 | LL | reuse a as b { | __________________^ @@ -10,7 +10,7 @@ LL | | } | |_____^ error[E0061]: this function takes 0 arguments but 1 argument was supplied - --> $DIR/hir-crate-items-before-lowering-ices.rs:37:11 + --> $DIR/hir-crate-items-before-lowering-ices.rs:38:11 | LL | reuse a as b { | ___________^______- @@ -21,7 +21,7 @@ LL | | } | |_____- unexpected argument of type `fn() {foo::<_>}` | note: function defined here - --> $DIR/hir-crate-items-before-lowering-ices.rs:35:8 + --> $DIR/hir-crate-items-before-lowering-ices.rs:36:8 | LL | fn a() {} | ^ diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr index b44a3c4174540..132c93b6c5532 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155164.stderr @@ -1,8 +1,8 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/hir-crate-items-before-lowering-ices.rs:48:37 + --> $DIR/hir-crate-items-before-lowering-ices.rs:50:18 | -LL | core::direct_const_arg!({ - | _____________________________________^ +LL | gca!({ + | __________________^ LL | | LL | | struct W; LL | | impl W { diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr index 5012905807597..d331191ac24e0 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.ice_155202.stderr @@ -1,5 +1,5 @@ error: function cannot return without recursing - --> $DIR/hir-crate-items-before-lowering-ices.rs:67:22 + --> $DIR/hir-crate-items-before-lowering-ices.rs:69:22 | LL | reuse Trait::bar { | ^^^ @@ -9,7 +9,7 @@ LL | reuse Trait::bar { | = help: a `loop` may express intention better if this is on purpose note: the lint level is defined here - --> $DIR/hir-crate-items-before-lowering-ices.rs:61:8 + --> $DIR/hir-crate-items-before-lowering-ices.rs:63:8 | LL | #[deny(unconditional_recursion)] | ^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs index 5689a29cafe11..cbe6cdd06df7e 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -5,10 +5,11 @@ #[cfg(ice_155125)] mod ice_155125 { + use std::gca; struct S; impl S< - core::direct_const_arg!({ //[ice_155125]~ ERROR: complex const arguments must be placed inside of a `const` block + gca!({ //[ice_155125]~ ERROR: complex const arguments must be placed inside of a `const` block fn foo() {} reuse foo; //[ice_155125]~ ERROR: the name `foo` is defined multiple times 2 @@ -43,9 +44,10 @@ mod ice_155128 { #[cfg(ice_155164)] mod ice_155164 { + use std::gca; struct X { inner: std::iter::Map< - core::direct_const_arg!({ + gca!({ //[ice_155164]~^ ERROR: complex const arguments must be placed inside of a `const` block struct W; impl W { diff --git a/tests/ui/delegation/inside-const-body-ice-155300.rs b/tests/ui/delegation/inside-const-body-ice-155300.rs index 2d13007bc807b..224f84845b354 100644 --- a/tests/ui/delegation/inside-const-body-ice-155300.rs +++ b/tests/ui/delegation/inside-const-body-ice-155300.rs @@ -1,11 +1,13 @@ #![feature(min_generic_const_args)] #![feature(fn_delegation)] +use std::gca; + pub struct S; impl S< - core::direct_const_arg!({ + gca!({ //~^ ERROR: complex const arguments must be placed inside of a `const` block fn foo() {} reuse foo::<> as bar; diff --git a/tests/ui/delegation/inside-const-body-ice-155300.stderr b/tests/ui/delegation/inside-const-body-ice-155300.stderr index f0cb830109f8a..d30f240556ac4 100644 --- a/tests/ui/delegation/inside-const-body-ice-155300.stderr +++ b/tests/ui/delegation/inside-const-body-ice-155300.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `bar` is defined multiple times - --> $DIR/inside-const-body-ice-155300.rs:12:13 + --> $DIR/inside-const-body-ice-155300.rs:14:13 | LL | reuse foo::<> as bar; | --------------------- previous definition of the value `bar` here @@ -9,10 +9,10 @@ LL | reuse bar; = note: `bar` must be defined only once in the value namespace of this block error: complex const arguments must be placed inside of a `const` block - --> $DIR/inside-const-body-ice-155300.rs:8:33 + --> $DIR/inside-const-body-ice-155300.rs:10:14 | -LL | core::direct_const_arg!({ - | _________________________________^ +LL | gca!({ + | ______________^ LL | | LL | | fn foo() {} LL | | reuse foo::<> as bar; diff --git a/tests/ui/delegation/wrong-fn-kind-ice-159127.rs b/tests/ui/delegation/wrong-fn-kind-ice-159127.rs index e117826ef099c..e1cde084600fd 100644 --- a/tests/ui/delegation/wrong-fn-kind-ice-159127.rs +++ b/tests/ui/delegation/wrong-fn-kind-ice-159127.rs @@ -1,9 +1,11 @@ #![feature(fn_delegation)] #![feature(min_generic_const_args)] +use std::gca; + impl - core::direct_const_arg!({ - //~^ ERROR: expected type, found `direct_const_arg!()` constant + gca!({ + //~^ ERROR: expected type, found `gca!()` constant fn foo() {} reuse foo::<>as bar; reuse bar; diff --git a/tests/ui/delegation/wrong-fn-kind-ice-159127.stderr b/tests/ui/delegation/wrong-fn-kind-ice-159127.stderr index bc218f39ab65a..8afa2c45bdc4b 100644 --- a/tests/ui/delegation/wrong-fn-kind-ice-159127.stderr +++ b/tests/ui/delegation/wrong-fn-kind-ice-159127.stderr @@ -1,5 +1,5 @@ error[E0428]: the name `bar` is defined multiple times - --> $DIR/wrong-fn-kind-ice-159127.rs:9:9 + --> $DIR/wrong-fn-kind-ice-159127.rs:11:9 | LL | reuse foo::<>as bar; | -------------------- previous definition of the value `bar` here @@ -8,10 +8,10 @@ LL | reuse bar; | = note: `bar` must be defined only once in the value namespace of this block -error: expected type, found `direct_const_arg!()` constant - --> $DIR/wrong-fn-kind-ice-159127.rs:5:5 +error: expected type, found `gca!()` constant + --> $DIR/wrong-fn-kind-ice-159127.rs:7:5 | -LL | / core::direct_const_arg!({ +LL | / gca!({ LL | | LL | | fn foo() {} LL | | reuse foo::<>as bar; diff --git a/tests/ui/feature-gates/feature-gate-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-generic-const-args.rs index c9403a269a8bc..e5bc617d96e4d 100644 --- a/tests/ui/feature-gates/feature-gate-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-generic-const-args.rs @@ -1,7 +1,9 @@ #![feature(generic_const_items, min_generic_const_args)] #![expect(incomplete_features)] -const INC: usize = core::direct_const_arg!(const { N + 1 }); +use std::gca; + +const INC: usize = gca!(const { N + 1 }); //~^ ERROR generic parameters may not be used in const operations //~| HELP add `#![feature(generic_const_args)]` diff --git a/tests/ui/feature-gates/feature-gate-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-generic-const-args.stderr index 6094430968f51..7d4c5a67c56a6 100644 --- a/tests/ui/feature-gates/feature-gate-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-generic-const-args.stderr @@ -1,8 +1,8 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-generic-const-args.rs:4:68 + --> $DIR/feature-gate-generic-const-args.rs:6:49 | -LL | const INC: usize = core::direct_const_arg!(const { N + 1 }); - | ^ +LL | const INC: usize = gca!(const { N + 1 }); + | ^ | = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs index 9737d9c521ac7..8da5824d9c49c 100644 --- a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs @@ -1,6 +1,6 @@ -const FOO: u8 = core::direct_const_arg!(10); +const FOO: u8 = std::gca!(10); //~^ ERROR use of unstable library feature `min_generic_const_args` [E0658] -//~| ERROR expected expression, found `direct_const_arg!()` constant +//~| ERROR expected expression, found `gca!()` constant trait Bar { #[rustc_always_gca] @@ -9,10 +9,10 @@ trait Bar { } impl Bar for bool { - const BAR: bool = core::direct_const_arg!(false); + const BAR: bool = std::gca!(false); //~^ ERROR use of unstable library feature `min_generic_const_args` [E0658] - //~| ERROR expected expression, found `direct_const_arg!()` constant - //~| ERROR implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS + //~| ERROR expected expression, found `gca!()` constant + //~| ERROR implementation of a `#[rustc_always_gca]` must have a `gca!` RHS } fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr index 2daf2e1056b95..3ee23f4883e05 100644 --- a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr @@ -1,8 +1,8 @@ error[E0658]: use of unstable library feature `min_generic_const_args` --> $DIR/feature-gate-mgca-type-const-syntax.rs:1:17 | -LL | const FOO: u8 = core::direct_const_arg!(10); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | const FOO: u8 = std::gca!(10); + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable @@ -11,18 +11,18 @@ LL | const FOO: u8 = core::direct_const_arg!(10); error[E0658]: use of unstable library feature `min_generic_const_args` --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:23 | -LL | const BAR: bool = core::direct_const_arg!(false); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | const BAR: bool = std::gca!(false); + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant +error: expected expression, found `gca!()` constant --> $DIR/feature-gate-mgca-type-const-syntax.rs:1:17 | -LL | const FOO: u8 = core::direct_const_arg!(10); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const FOO: u8 = std::gca!(10); + | ^^^^^^^^^^^^^ error[E0658]: the `rustc_always_gca` attribute is an experimental feature --> $DIR/feature-gate-mgca-type-const-syntax.rs:6:7 @@ -34,16 +34,16 @@ LL | #[rustc_always_gca] = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant +error: expected expression, found `gca!()` constant --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:23 | -LL | const BAR: bool = core::direct_const_arg!(false); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | const BAR: bool = std::gca!(false); + | ^^^^^^^^^^^^^^^^ -error: implementation of a `#[rustc_always_gca]` must have a `direct_const_arg!` RHS +error: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:5 | -LL | const BAR: bool = core::direct_const_arg!(false); +LL | const BAR: bool = std::gca!(false); | ^^^^^^^^^^^^^^^ | note: trait declaration of const is marked as `#[rustc_always_gca]` diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs index a39d07eca0ee7..07f278f04591a 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs @@ -5,10 +5,10 @@ trait Trait { } // FIXME(mgca): add suggestion for mgca to this error -fn foo() -> [u8; core::direct_const_arg!(::ASSOC)] { +fn foo() -> [u8; std::gca!(::ASSOC)] { //~^ ERROR generic parameters may not be used in const operations //~| ERROR: use of unstable library feature `min_generic_const_args` [E0658] - //~| ERROR: expected expression, found `direct_const_arg!()` + //~| ERROR: expected expression, found `gca!()` loop {} } diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr index eac9545d29681..f709affb8a819 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr @@ -1,18 +1,18 @@ error[E0658]: use of unstable library feature `min_generic_const_args` --> $DIR/feature-gate-min-generic-const-args.rs:8:28 | -LL | fn foo() -> [u8; core::direct_const_arg!(::ASSOC)] { - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() -> [u8; std::gca!(::ASSOC)] { + | ^^^^^^^^ | = note: see issue #132980 for more information = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: generic parameters may not be used in const operations - --> $DIR/feature-gate-min-generic-const-args.rs:8:53 + --> $DIR/feature-gate-min-generic-const-args.rs:8:39 | -LL | fn foo() -> [u8; core::direct_const_arg!(::ASSOC)] { - | ^ cannot perform const operation using `T` +LL | fn foo() -> [u8; std::gca!(::ASSOC)] { + | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions @@ -28,11 +28,11 @@ LL | #[rustc_always_gca] = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: expected expression, found `direct_const_arg!()` constant +error: expected expression, found `gca!()` constant --> $DIR/feature-gate-min-generic-const-args.rs:8:28 | -LL | fn foo() -> [u8; core::direct_const_arg!(::ASSOC)] { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo() -> [u8; std::gca!(::ASSOC)] { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 4 previous errors diff --git a/tests/ui/generic-const-items/assoc-const-bindings.rs b/tests/ui/generic-const-items/assoc-const-bindings.rs index 596c47de98f86..2e0929a56867c 100644 --- a/tests/ui/generic-const-items/assoc-const-bindings.rs +++ b/tests/ui/generic-const-items/assoc-const-bindings.rs @@ -4,6 +4,7 @@ #![feature(adt_const_params, const_param_ty_trait, generic_const_parameter_types)] #![expect(incomplete_features)] +use std::gca; use std::marker::{ConstParamTy, ConstParamTy_}; trait Owner { @@ -16,9 +17,9 @@ trait Owner { } impl Owner for () { - const C: u32 = core::direct_const_arg!(N); - const K: u32 = core::direct_const_arg!(const { 99 + 1 }); - const Q: Maybe = core::direct_const_arg!(Maybe::Nothing::); + const C: u32 = gca!(N); + const K: u32 = gca!(const { 99 + 1 }); + const Q: Maybe = gca!(Maybe::Nothing::); } fn take0(_: impl Owner = { N }>) {} diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index 31bca180df8a8..d1b88db9466ef 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -4,13 +4,15 @@ #![feature(associated_type_defaults)] #![allow(incomplete_features)] +use std::gca; + pub struct NoPin; impl Pins for NoPin {} pub trait PinA { #[rustc_always_gca] - const A: &'static () = core::direct_const_arg!(const { &() }); + const A: &'static () = gca!(const { &() }); } pub trait Pins {} @@ -18,7 +20,7 @@ pub trait Pins {} impl Pins for T //~^ ERROR conflicting implementations of trait `Pins<_>` for type `NoPin` where - T: PinA + T: PinA { } diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr index 515ee3f0af8be..65ec6a2c4e46e 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Pins<_>` for type `NoPin` - --> $DIR/assoc-const-no-infer-ice-115806.rs:18:1 + --> $DIR/assoc-const-no-infer-ice-115806.rs:20:1 | LL | impl Pins for NoPin {} | --------------------------- first implementation here @@ -7,8 +7,8 @@ LL | impl Pins for NoPin {} LL | / impl Pins for T LL | | LL | | where -LL | | T: PinA - | |__________________________________________________________________^ conflicting implementation for `NoPin` +LL | | T: PinA + | |_______________________________________________^ conflicting implementation for `NoPin` | = note: downstream crates may implement trait `PinA<_>` for type `NoPin` diff --git a/tests/ui/generic-const-items/type-const-nested-assoc-const.rs b/tests/ui/generic-const-items/type-const-nested-assoc-const.rs index 64df0183f101e..4d91d7edc8f16 100644 --- a/tests/ui/generic-const-items/type-const-nested-assoc-const.rs +++ b/tests/ui/generic-const-items/type-const-nested-assoc-const.rs @@ -3,7 +3,9 @@ #![feature(generic_const_items, min_generic_const_args)] #![allow(incomplete_features)] -const CT: usize = core::direct_const_arg!(::N); +use std::gca; + +const CT: usize = gca!(::N); trait Trait { #[rustc_always_gca] @@ -11,7 +13,7 @@ trait Trait { } impl Trait for T { - const N: usize = core::direct_const_arg!(0); + const N: usize = gca!(0); } fn f(_x: [(); CT::<()>]) {} diff --git a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs index 4b415a230cbd4..8e77c40b113d9 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs @@ -13,10 +13,12 @@ #![expect(incomplete_features)] mod own { + use std::gca; + // the lifetime comes from the own generics struct Parent; impl Parent { - const CT<'a, T: 'a + super::AbideBy<'a> + ?Sized>: usize = core::direct_const_arg!(0); + const CT<'a, T: 'a + super::AbideBy<'a> + ?Sized>: usize = gca!(0); } // FIXME: Ideally, we would deduce `dyn Trait + 'r` from the bound `'a` on ty param `T` of @@ -31,10 +33,12 @@ mod own { } mod parent { + use std::gca; + // the lifetime comes from the parent generics struct Parent<'a>(&'a ()); impl<'a> Parent<'a> { - const CT + ?Sized>: usize = core::direct_const_arg!(0); + const CT + ?Sized>: usize = gca!(0); } //FIXME: Ideally, we would deduce `dyn Trait + 'r` from the bound `'a` on ty param `T` of diff --git a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.stderr b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.stderr index 1461caea1bbed..97d5fcd582681 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.stderr +++ b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.stderr @@ -1,5 +1,5 @@ error[E0228]: cannot deduce the lifetime bound for this trait object type from context - --> $DIR/object-lifetime-default-inherent-gac.rs:27:31 + --> $DIR/object-lifetime-default-inherent-gac.rs:29:31 | LL | [(); Parent::CT::<'r, dyn super::Trait>]:, | ^^^^^^^^^^^^^^^^ @@ -10,7 +10,7 @@ LL | [(); Parent::CT::<'r, dyn super::Trait + /* 'a */>]:, | ++++++++++ error[E0228]: cannot deduce the lifetime bound for this trait object type from context - --> $DIR/object-lifetime-default-inherent-gac.rs:45:33 + --> $DIR/object-lifetime-default-inherent-gac.rs:49:33 | LL | [(); Parent::<'r>::CT::]:, | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs index 113ef41f532f0..6db3ebceb1cff 100644 --- a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs +++ b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs @@ -7,9 +7,11 @@ #![feature(min_generic_const_args, macroless_generic_const_args, associated_type_defaults)] #![expect(incomplete_features)] +use std::gca; + trait Trait { #[rustc_always_gca] - const N: usize = core::direct_const_arg!(0); + const N: usize = gca!(0); fn process(&self, _: [u8; Self::N]) {} } diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index a57e86127da7b..33b3aa4cd2430 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -2,12 +2,14 @@ #![feature(min_generic_const_args, specialization)] +use std::gca; + pub trait IsVoid { #[rustc_always_gca] const IS_VOID: bool; } impl IsVoid for T { - default const IS_VOID: bool = core::direct_const_arg!(false); + default const IS_VOID: bool = gca!(false); } pub trait NotVoid {} diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr index 3ec3e83cc1d44..eda6b57ca8f7a 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Maybe<()>` for type `()` - --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:18:1 + --> $DIR/overlap-due-to-unsatisfied-const-bound.rs:20:1 | LL | impl Maybe for T {} | ---------------------- first implementation here diff --git a/tests/ui/supertrait-shadowing/assoc-const.rs b/tests/ui/supertrait-shadowing/assoc-const.rs index 0fd798217d77a..9e49004e7c836 100644 --- a/tests/ui/supertrait-shadowing/assoc-const.rs +++ b/tests/ui/supertrait-shadowing/assoc-const.rs @@ -4,6 +4,8 @@ #![feature(min_generic_const_args)] #![allow(dead_code)] +use std::gca; + trait A { const CONST: i32; } @@ -16,7 +18,7 @@ trait B: A { const CONST: i32; } impl B for T { - const CONST: i32 = core::direct_const_arg!(2); + const CONST: i32 = gca!(2); } trait C: B {} diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/supertrait-shadowing/common-ancestor-2.rs index b1ff2e895eb48..4844b0a43aa89 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.rs @@ -6,6 +6,7 @@ #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::gca; use std::mem::size_of; trait A { @@ -45,7 +46,7 @@ trait C: A + B { } impl C for T { type Assoc = i32; - const CONST: i32 = core::direct_const_arg!(3); + const CONST: i32 = gca!(3); } fn main() { diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr index 3e47a33991007..35f8a434fe861 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-2.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:36:5 + --> $DIR/common-ancestor-2.rs:37:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-2.rs:12:5 + --> $DIR/common-ancestor-2.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,13 +19,13 @@ LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: trait item `Assoc` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:40:5 + --> $DIR/common-ancestor-2.rs:41:5 | LL | type Assoc; | ^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-2.rs:15:5 + --> $DIR/common-ancestor-2.rs:16:5 | LL | type Assoc; | ^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | type Assoc; | ^^^^^^^^^^ warning: trait item `CONST` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:43:5 + --> $DIR/common-ancestor-2.rs:44:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-2.rs:16:5 + --> $DIR/common-ancestor-2.rs:17:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ @@ -49,18 +49,18 @@ LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-2.rs:52:19 + --> $DIR/common-ancestor-2.rs:53:19 | LL | assert_eq!(().hello(), "C"); | ^^^^^ | note: item from `C` shadows a supertrait item - --> $DIR/common-ancestor-2.rs:36:5 + --> $DIR/common-ancestor-2.rs:37:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: items from several supertraits are shadowed: `A` and `B` - --> $DIR/common-ancestor-2.rs:12:5 + --> $DIR/common-ancestor-2.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/supertrait-shadowing/common-ancestor-3.rs index ba8689d3a43f2..c815919c7e318 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-3.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.rs @@ -6,6 +6,7 @@ #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::gca; use std::mem::size_of; trait A { @@ -45,7 +46,7 @@ trait C: A + B { } impl C for T { type Assoc = i32; - const CONST: i32 = core::direct_const_arg!(3); + const CONST: i32 = gca!(3); } // `D` extends `C` which extends `B` and `A` @@ -63,7 +64,7 @@ trait D: C { } impl D for T { type Assoc = i64; - const CONST: i32 = core::direct_const_arg!(4); + const CONST: i32 = gca!(4); } fn main() { diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.stderr b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr index 2fd7ff0003c74..b18355f1a7920 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-3.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:36:5 + --> $DIR/common-ancestor-3.rs:37:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-3.rs:12:5 + --> $DIR/common-ancestor-3.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,13 +19,13 @@ LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: trait item `Assoc` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:40:5 + --> $DIR/common-ancestor-3.rs:41:5 | LL | type Assoc; | ^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-3.rs:15:5 + --> $DIR/common-ancestor-3.rs:16:5 | LL | type Assoc; | ^^^^^^^^^^ @@ -34,13 +34,13 @@ LL | type Assoc; | ^^^^^^^^^^ warning: trait item `CONST` from `C` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:43:5 + --> $DIR/common-ancestor-3.rs:44:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `B` and `A` - --> $DIR/common-ancestor-3.rs:16:5 + --> $DIR/common-ancestor-3.rs:17:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ @@ -49,13 +49,13 @@ LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:54:5 + --> $DIR/common-ancestor-3.rs:55:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `C`, `B`, and `A` - --> $DIR/common-ancestor-3.rs:12:5 + --> $DIR/common-ancestor-3.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -67,13 +67,13 @@ LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: trait item `Assoc` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:58:5 + --> $DIR/common-ancestor-3.rs:59:5 | LL | type Assoc; | ^^^^^^^^^^ | note: items from several supertraits are shadowed: `C`, `B`, and `A` - --> $DIR/common-ancestor-3.rs:15:5 + --> $DIR/common-ancestor-3.rs:16:5 | LL | type Assoc; | ^^^^^^^^^^ @@ -85,13 +85,13 @@ LL | type Assoc; | ^^^^^^^^^^ warning: trait item `CONST` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:61:5 + --> $DIR/common-ancestor-3.rs:62:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ | note: items from several supertraits are shadowed: `C`, `B`, and `A` - --> $DIR/common-ancestor-3.rs:16:5 + --> $DIR/common-ancestor-3.rs:17:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ @@ -103,18 +103,18 @@ LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ warning: trait item `hello` from `D` shadows identically named item from supertrait - --> $DIR/common-ancestor-3.rs:70:19 + --> $DIR/common-ancestor-3.rs:71:19 | LL | assert_eq!(().hello(), "D"); | ^^^^^ | note: item from `D` shadows a supertrait item - --> $DIR/common-ancestor-3.rs:54:5 + --> $DIR/common-ancestor-3.rs:55:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: items from several supertraits are shadowed: `A`, `B`, and `C` - --> $DIR/common-ancestor-3.rs:12:5 + --> $DIR/common-ancestor-3.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/supertrait-shadowing/common-ancestor.rs b/tests/ui/supertrait-shadowing/common-ancestor.rs index 7acc4bcad56ca..e89167c9215fd 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor.rs @@ -6,6 +6,7 @@ #![warn(shadowing_supertrait_items)] #![allow(dead_code)] +use std::gca; use std::mem::size_of; trait A { @@ -33,7 +34,7 @@ trait B: A { } impl B for T { type Assoc = i16; - const CONST: i32 = core::direct_const_arg!(2); + const CONST: i32 = gca!(2); } fn main() { diff --git a/tests/ui/supertrait-shadowing/common-ancestor.stderr b/tests/ui/supertrait-shadowing/common-ancestor.stderr index a0b885b58eb5f..99ea66a166dbd 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor.stderr +++ b/tests/ui/supertrait-shadowing/common-ancestor.stderr @@ -1,11 +1,11 @@ warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:24:5 + --> $DIR/common-ancestor.rs:25:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:12:5 + --> $DIR/common-ancestor.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -16,42 +16,42 @@ LL | #![warn(shadowing_supertrait_items)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: trait item `Assoc` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:28:5 + --> $DIR/common-ancestor.rs:29:5 | LL | type Assoc; | ^^^^^^^^^^ | note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:15:5 + --> $DIR/common-ancestor.rs:16:5 | LL | type Assoc; | ^^^^^^^^^^ warning: trait item `CONST` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:31:5 + --> $DIR/common-ancestor.rs:32:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ | note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:16:5 + --> $DIR/common-ancestor.rs:17:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ warning: trait item `hello` from `B` shadows identically named item from supertrait - --> $DIR/common-ancestor.rs:40:19 + --> $DIR/common-ancestor.rs:41:19 | LL | assert_eq!(().hello(), "B"); | ^^^^^ | note: item from `B` shadows a supertrait item - --> $DIR/common-ancestor.rs:24:5 + --> $DIR/common-ancestor.rs:25:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: item from `A` is shadowed by a subtrait item - --> $DIR/common-ancestor.rs:12:5 + --> $DIR/common-ancestor.rs:13:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs index 64d34ccb8c9ae..3462ac4e37d4d 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs @@ -1,6 +1,7 @@ #![feature(supertrait_item_shadowing)] #![feature(min_generic_const_args)] +use std::gca; use std::mem::size_of; trait A { @@ -37,7 +38,7 @@ trait C: A + B { } impl C for T { type Assoc = i32; - const CONST: i32 = core::direct_const_arg!(3); + const CONST: i32 = gca!(3); } // Since `D` is not a subtrait of `C`, @@ -53,7 +54,7 @@ trait D: B { } impl D for T { type Assoc = i64; - const CONST: i32 = core::direct_const_arg!(4); + const CONST: i32 = gca!(4); } fn main() { diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr index 85c0937c03d9c..220a26d7757a0 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.stderr @@ -1,26 +1,26 @@ error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor-2.rs:60:8 + --> $DIR/no-common-ancestor-2.rs:61:8 | LL | ().hello(); | ^^^^^ multiple `hello` found | note: candidate #1 is defined in an impl of the trait `A` for the type `T` - --> $DIR/no-common-ancestor-2.rs:7:5 + --> $DIR/no-common-ancestor-2.rs:8:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #2 is defined in an impl of the trait `B` for the type `T` - --> $DIR/no-common-ancestor-2.rs:19:5 + --> $DIR/no-common-ancestor-2.rs:20:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #3 is defined in an impl of the trait `C` for the type `T` - --> $DIR/no-common-ancestor-2.rs:31:5 + --> $DIR/no-common-ancestor-2.rs:32:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ note: candidate #4 is defined in an impl of the trait `D` for the type `T` - --> $DIR/no-common-ancestor-2.rs:47:5 + --> $DIR/no-common-ancestor-2.rs:48:5 | LL | fn hello(&self) -> &'static str { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -46,7 +46,7 @@ LL + D::hello(&()); | error[E0221]: ambiguous associated type `Assoc` in bounds of `T` - --> $DIR/no-common-ancestor-2.rs:66:23 + --> $DIR/no-common-ancestor-2.rs:67:23 | LL | type Assoc; | ---------- ambiguous `Assoc` from `A` @@ -85,28 +85,28 @@ LL + let _ = size_of::<::Assoc>(); | error[E0034]: multiple applicable items in scope - --> $DIR/no-common-ancestor-2.rs:68:16 + --> $DIR/no-common-ancestor-2.rs:69:16 | LL | let _ = T::CONST; | ^^^^^ multiple `CONST` found | note: candidate #1 is defined in the trait `A` - --> $DIR/no-common-ancestor-2.rs:11:5 + --> $DIR/no-common-ancestor-2.rs:12:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ note: candidate #2 is defined in the trait `B` - --> $DIR/no-common-ancestor-2.rs:23:5 + --> $DIR/no-common-ancestor-2.rs:24:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ note: candidate #3 is defined in the trait `C` - --> $DIR/no-common-ancestor-2.rs:36:5 + --> $DIR/no-common-ancestor-2.rs:37:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ note: candidate #4 is defined in the trait `D` - --> $DIR/no-common-ancestor-2.rs:52:5 + --> $DIR/no-common-ancestor-2.rs:53:5 | LL | const CONST: i32; | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/supertrait-shadowing/out-of-scope.rs b/tests/ui/supertrait-shadowing/out-of-scope.rs index 11c7477cc3f8a..fc967e525dc40 100644 --- a/tests/ui/supertrait-shadowing/out-of-scope.rs +++ b/tests/ui/supertrait-shadowing/out-of-scope.rs @@ -6,6 +6,7 @@ use std::mem::size_of; mod out_of_scope { + use std::gca; pub trait Subtrait: super::Supertrait { fn hello(&self) -> &'static str { "subtrait" @@ -16,7 +17,7 @@ mod out_of_scope { } impl Subtrait for T { type Assoc = i16; - const CONST: i32 = core::direct_const_arg!(2); + const CONST: i32 = gca!(2); } } diff --git a/tests/ui/supertrait-shadowing/type-dependent.rs b/tests/ui/supertrait-shadowing/type-dependent.rs index 0287bb7ad43a8..b2c31b352deee 100644 --- a/tests/ui/supertrait-shadowing/type-dependent.rs +++ b/tests/ui/supertrait-shadowing/type-dependent.rs @@ -6,6 +6,7 @@ #![feature(supertrait_item_shadowing)] #![allow(dead_code)] +use std::gca; use std::mem::size_of; trait A { @@ -30,7 +31,7 @@ trait B: A { } impl B for T { type Assoc = i16; - const CONST: i32 = core::direct_const_arg!(2); + const CONST: i32 = gca!(2); } fn foo() -> &'static str { diff --git a/tests/ui/traits/next-solver/normalize-const-item-type.rs b/tests/ui/traits/next-solver/normalize-const-item-type.rs index 873b0bb690e4c..3b70e8718488b 100644 --- a/tests/ui/traits/next-solver/normalize-const-item-type.rs +++ b/tests/ui/traits/next-solver/normalize-const-item-type.rs @@ -3,6 +3,7 @@ #![feature(min_generic_const_args)] #![feature(generic_const_args)] +use std::gca; use std::marker::PhantomData; trait Project1<'a> { @@ -21,14 +22,15 @@ impl> Project2 for PhantomData { type Assoc2 = usize; } -const N: as Project2>::Assoc2 = 2_usize; +const N: as Project2>::Assoc2 = 2_usize; -fn func(_: [(); core::direct_const_arg!(N::)]) +fn func(_: [(); gca!(N::)]) //~^ ERROR: type mismatch resolving `N == _` [E0271] //~| ERROR: the type `[(); N::]` is not well-formed //~| ERROR: type mismatch resolving `N == _` [E0271] where for<'a> u32: Project1<'a>, -{} +{ +} fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-const-item-type.stderr b/tests/ui/traits/next-solver/normalize-const-item-type.stderr index 67f4f596f40bf..926ba7e43b2f5 100644 --- a/tests/ui/traits/next-solver/normalize-const-item-type.stderr +++ b/tests/ui/traits/next-solver/normalize-const-item-type.stderr @@ -1,20 +1,20 @@ error[E0271]: type mismatch resolving `N == _` - --> $DIR/normalize-const-item-type.rs:26:12 + --> $DIR/normalize-const-item-type.rs:27:12 | -LL | fn func(_: [(); core::direct_const_arg!(N::)]) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ +LL | fn func(_: [(); gca!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^ types differ error: the type `[(); N::]` is not well-formed - --> $DIR/normalize-const-item-type.rs:26:12 + --> $DIR/normalize-const-item-type.rs:27:12 | -LL | fn func(_: [(); core::direct_const_arg!(N::)]) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn func(_: [(); gca!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^ error[E0271]: type mismatch resolving `N == _` - --> $DIR/normalize-const-item-type.rs:26:12 + --> $DIR/normalize-const-item-type.rs:27:12 | -LL | fn func(_: [(); core::direct_const_arg!(N::)]) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ +LL | fn func(_: [(); gca!(N::)]) + | ^^^^^^^^^^^^^^^^^^^^ types differ | = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` From 0083a0f37cec67f4ccdefd32d6571088934d21da Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Wed, 23 Sep 2026 10:50:17 +0000 Subject: [PATCH 0693/1309] rename direct_const_arg! to gca! Co-authored-by: Boxy --- clippy_utils/src/check_proc_macro.rs | 2 +- clippy_utils/src/sugg.rs | 2 +- tests/ui/crashes/mgca-16691.rs | 4 +++- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index c8ee7c5a1034f..baff6a99fc9e0 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -539,7 +539,7 @@ fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { | TyKind::Pat(..) | TyKind::FieldOf(..) | TyKind::View(..) - | TyKind::DirectConstArg(..) + | TyKind::GcaMacro(..) // unused | TyKind::CVarArgs diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index 3d4645f72fce3..d2045c1346ee5 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -248,7 +248,7 @@ impl<'a> Sugg<'a> { | ast::ExprKind::Array(..) | ast::ExprKind::While(..) | ast::ExprKind::Await(..) - | ast::ExprKind::DirectConstArg(..) + | ast::ExprKind::GcaMacro(..) | ast::ExprKind::Err(_) | ast::ExprKind::Dummy | ast::ExprKind::UnsafeBinderCast(..) => Sugg::NonParen(snippet(expr.span)), diff --git a/tests/ui/crashes/mgca-16691.rs b/tests/ui/crashes/mgca-16691.rs index 7e45f96fa9a9a..554528905fc85 100644 --- a/tests/ui/crashes/mgca-16691.rs +++ b/tests/ui/crashes/mgca-16691.rs @@ -2,6 +2,8 @@ #![expect(incomplete_features)] #![feature(min_generic_const_args)] +use std::gca; + trait Trait { #[rustc_always_gca] const N: usize; @@ -9,7 +11,7 @@ trait Trait { } impl Trait for () { - const N: usize = core::direct_const_arg!(3); + const N: usize = gca!(3); fn process() { const N: usize = <()>::N; _ = 0..Self::N; From b850b3504c7d48db84982c1100bd96dfa8600096 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 12:52:59 +0200 Subject: [PATCH 0694/1309] Initial josh-sync configuration --- src/tools/rustfmt/josh-sync.toml | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 src/tools/rustfmt/josh-sync.toml diff --git a/src/tools/rustfmt/josh-sync.toml b/src/tools/rustfmt/josh-sync.toml new file mode 100644 index 0000000000000..736b3d52cb886 --- /dev/null +++ b/src/tools/rustfmt/josh-sync.toml @@ -0,0 +1,4 @@ +repo = "rustfmt" +filter = ":~(history=\"keep-trivial-merges,no-splice\")[:rev(<=e47f161c8476418e8b55b61db3bbf0338e0ab827:prefix=src/tools/rustfmt,<=e5b95097d9a14bdec7cd9101dde67ee3aad2578a:SQUASH)]:/src/tools/rustfmt" +filter-version = 2 +pull-mode = "Nightly" From d8fb1130ab5fb003c65288de9435e23409a58b69 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 12:52:59 +0200 Subject: [PATCH 0695/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-23 (6bb1652a020e80cef79332741d89e996d71933c9). --- src/tools/rustfmt/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/rust-toolchain.toml b/src/tools/rustfmt/rust-toolchain.toml index 739ec1b48dad4..0d01929160891 100644 --- a/src/tools/rustfmt/rust-toolchain.toml +++ b/src/tools/rustfmt/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-21" +channel = "nightly-2026-09-23" components = ["llvm-tools", "rustc-dev"] From 4858117c582c8a3b530a923862f4981c47399092 Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:42:09 +0900 Subject: [PATCH 0696/1309] Use `std_or_core` in `integer_to_ptr_transmutes` rustfix --- compiler/rustc_lint/src/diagnostics.rs | 23 ++++++++++----- compiler/rustc_lint/src/transmute.rs | 35 ++++++++++++----------- tests/ui/lint/int_to_ptr-no_core.rs | 15 ++++++++++ tests/ui/lint/int_to_ptr-no_core.stderr | 14 ++++++++++ tests/ui/lint/int_to_ptr-no_std.fixed | 14 ++++++++++ tests/ui/lint/int_to_ptr-no_std.rs | 14 ++++++++++ tests/ui/lint/int_to_ptr-no_std.stderr | 37 +++++++++++++++++++++++++ tests/ui/lint/int_to_ptr-unsized.stderr | 4 +-- tests/ui/lint/int_to_ptr.stderr | 24 ++++++++-------- 9 files changed, 143 insertions(+), 37 deletions(-) create mode 100644 tests/ui/lint/int_to_ptr-no_core.rs create mode 100644 tests/ui/lint/int_to_ptr-no_core.stderr create mode 100644 tests/ui/lint/int_to_ptr-no_std.fixed create mode 100644 tests/ui/lint/int_to_ptr-no_std.rs create mode 100644 tests/ui/lint/int_to_ptr-no_std.stderr diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index ed5988c5380ca..12fd049724413 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -2078,9 +2078,6 @@ impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { #[note( "exposed provenance semantics can be used to create a pointer based on some previously exposed provenance" )] -#[help( - "if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut`" -)] #[help( "for more information about transmute, see " )] @@ -2088,34 +2085,46 @@ impl<'a> Diagnostic<'a, ()> for DropGlue<'_> { "for more information about exposed provenance, see " )] pub(crate) struct IntegerToPtrTransmutes<'tcx> { + #[subdiagnostic] + pub without_prov: Option, #[subdiagnostic] pub suggestion: Option>, } +#[derive(Subdiagnostic)] +#[help( + "if you truly mean to create a pointer without provenance, use `{$krate}::ptr::without_provenance_mut`" +)] +pub(crate) struct IntegerToPtrWithoutProvHelp { + pub krate: &'static str, +} + #[derive(Subdiagnostic)] pub(crate) enum IntegerToPtrTransmutesSuggestion<'tcx> { #[multipart_suggestion( - "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", + "use `{$krate}::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] ToPtr { + krate: &'static str, dst: Ty<'tcx>, suffix: &'static str, - #[suggestion_part(code = "std::ptr::with_exposed_provenance{suffix}::<{dst}>(")] + #[suggestion_part(code = "{krate}::ptr::with_exposed_provenance{suffix}::<{dst}>(")] start_call: Span, }, #[multipart_suggestion( - "use `std::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", + "use `{$krate}::ptr::with_exposed_provenance{$suffix}` instead to use a previously exposed provenance", applicability = "machine-applicable", style = "verbose" )] ToRef { + krate: &'static str, dst: Ty<'tcx>, suffix: &'static str, ref_mutbl: &'static str, #[suggestion_part( - code = "&{ref_mutbl}*std::ptr::with_exposed_provenance{suffix}::<{dst}>(" + code = "&{ref_mutbl}*{krate}::ptr::with_exposed_provenance{suffix}::<{dst}>(" )] start_call: Span, }, diff --git a/compiler/rustc_lint/src/transmute.rs b/compiler/rustc_lint/src/transmute.rs index 3a4092a46a6b6..3b269a215cb6b 100644 --- a/compiler/rustc_lint/src/transmute.rs +++ b/compiler/rustc_lint/src/transmute.rs @@ -8,7 +8,10 @@ use rustc_macros::Diagnostic; use rustc_middle::ty::{self, Ty}; use rustc_span::sym; -use crate::diagnostics::{IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion}; +use crate::diagnostics::{ + IntegerToPtrTransmutes, IntegerToPtrTransmutesSuggestion, IntegerToPtrWithoutProvHelp, +}; +use crate::utils::std_or_core; use crate::{LateContext, LateLintPass}; declare_lint! { @@ -166,30 +169,30 @@ fn check_int_to_ptr_transmute<'tcx>( } let suffix = if mutbl.is_mut() { "_mut" } else { "" }; + let krate = std_or_core(cx); cx.tcx.emit_node_span_lint( INTEGER_TO_PTR_TRANSMUTES, expr.hir_id, expr.span, IntegerToPtrTransmutes { - suggestion: if layout_inner_ty.is_sized() { - Some(if dst.is_ref() { - IntegerToPtrTransmutesSuggestion::ToRef { + without_prov: krate.map(|krate| IntegerToPtrWithoutProvHelp { krate }), + suggestion: match (krate, layout_inner_ty.is_sized()) { + (Some(krate), true) if dst.is_ref() => { + Some(IntegerToPtrTransmutesSuggestion::ToRef { + krate, dst: *inner_ty, suffix, ref_mutbl: mutbl.prefix_str(), start_call: expr.span.shrink_to_lo().until(arg.span), - } - } else { - IntegerToPtrTransmutesSuggestion::ToPtr { - dst: *inner_ty, - suffix, - start_call: expr.span.shrink_to_lo().until(arg.span), - } - }) - } else { - // We can't suggest using `with_exposed_provenance` for unsized type - // so don't suggest anything. - None + }) + } + (Some(krate), true) => Some(IntegerToPtrTransmutesSuggestion::ToPtr { + krate, + dst: *inner_ty, + suffix, + start_call: expr.span.shrink_to_lo().until(arg.span), + }), + _ => None, }, }, ); diff --git a/tests/ui/lint/int_to_ptr-no_core.rs b/tests/ui/lint/int_to_ptr-no_core.rs new file mode 100644 index 0000000000000..d62855e43ddb8 --- /dev/null +++ b/tests/ui/lint/int_to_ptr-no_core.rs @@ -0,0 +1,15 @@ +//@ check-pass +//@ add-minicore + +#![feature(no_core)] +#![no_core] +#![crate_type = "lib"] +#![allow(dead_code)] + +extern crate minicore; +use minicore::*; + +pub unsafe fn should_lint(a: usize) -> *const u8 { + unsafe { mem::transmute::(a) } + //~^ WARN transmuting an integer to a pointer +} diff --git a/tests/ui/lint/int_to_ptr-no_core.stderr b/tests/ui/lint/int_to_ptr-no_core.stderr new file mode 100644 index 0000000000000..4977bfe058cde --- /dev/null +++ b/tests/ui/lint/int_to_ptr-no_core.stderr @@ -0,0 +1,14 @@ +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr-no_core.rs:13:14 + | +LL | unsafe { mem::transmute::(a) } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + = note: `#[warn(integer_to_ptr_transmutes)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/lint/int_to_ptr-no_std.fixed b/tests/ui/lint/int_to_ptr-no_std.fixed new file mode 100644 index 0000000000000..4d476c265abb5 --- /dev/null +++ b/tests/ui/lint/int_to_ptr-no_std.fixed @@ -0,0 +1,14 @@ +//@ check-pass +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(unused_unsafe)] +#![allow(dead_code)] + +pub unsafe fn should_lint(a: usize) { + let _ptr: *const u8 = unsafe { core::ptr::with_exposed_provenance::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { core::ptr::with_exposed_provenance_mut::(a) }; + //~^ WARN transmuting an integer to a pointer +} diff --git a/tests/ui/lint/int_to_ptr-no_std.rs b/tests/ui/lint/int_to_ptr-no_std.rs new file mode 100644 index 0000000000000..f0eb95b3db7d1 --- /dev/null +++ b/tests/ui/lint/int_to_ptr-no_std.rs @@ -0,0 +1,14 @@ +//@ check-pass +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(unused_unsafe)] +#![allow(dead_code)] + +pub unsafe fn should_lint(a: usize) { + let _ptr: *const u8 = unsafe { core::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer + let _ptr: *mut u8 = unsafe { core::mem::transmute::(a) }; + //~^ WARN transmuting an integer to a pointer +} diff --git a/tests/ui/lint/int_to_ptr-no_std.stderr b/tests/ui/lint/int_to_ptr-no_std.stderr new file mode 100644 index 0000000000000..9de31a80efcc5 --- /dev/null +++ b/tests/ui/lint/int_to_ptr-no_std.stderr @@ -0,0 +1,37 @@ +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr-no_std.rs:10:36 + | +LL | let _ptr: *const u8 = unsafe { core::mem::transmute::(a) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `core::ptr::without_provenance_mut` + = note: `#[warn(integer_to_ptr_transmutes)]` on by default +help: use `core::ptr::with_exposed_provenance` instead to use a previously exposed provenance + | +LL - let _ptr: *const u8 = unsafe { core::mem::transmute::(a) }; +LL + let _ptr: *const u8 = unsafe { core::ptr::with_exposed_provenance::(a) }; + | + +warning: transmuting an integer to a pointer creates a pointer without provenance + --> $DIR/int_to_ptr-no_std.rs:12:34 + | +LL | let _ptr: *mut u8 = unsafe { core::mem::transmute::(a) }; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: this is dangerous because dereferencing the resulting pointer is undefined behavior + = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance + = help: for more information about transmute, see + = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `core::ptr::without_provenance_mut` +help: use `core::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance + | +LL - let _ptr: *mut u8 = unsafe { core::mem::transmute::(a) }; +LL + let _ptr: *mut u8 = unsafe { core::ptr::with_exposed_provenance_mut::(a) }; + | + +warning: 2 warnings emitted + diff --git a/tests/ui/lint/int_to_ptr-unsized.stderr b/tests/ui/lint/int_to_ptr-unsized.stderr index 9799af8b12c15..559c4011c6c2e 100644 --- a/tests/ui/lint/int_to_ptr-unsized.stderr +++ b/tests/ui/lint/int_to_ptr-unsized.stderr @@ -6,9 +6,9 @@ LL | let _ref = unsafe { std::mem::transmute::( | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = note: `#[warn(integer_to_ptr_transmutes)]` on by default warning: transmuting an integer to a pointer creates a pointer without provenance @@ -19,9 +19,9 @@ LL | let _ptr = unsafe { std::mem::transmute::(0 | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` warning: 2 warnings emitted diff --git a/tests/ui/lint/int_to_ptr.stderr b/tests/ui/lint/int_to_ptr.stderr index 4035bda8fb2cf..fe4cf56373208 100644 --- a/tests/ui/lint/int_to_ptr.stderr +++ b/tests/ui/lint/int_to_ptr.stderr @@ -6,9 +6,9 @@ LL | let _ptr: *const u8 = unsafe { std::mem::transmute::( | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = note: `#[warn(integer_to_ptr_transmutes)]` on by default help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | @@ -24,9 +24,9 @@ LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) } | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance | LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; @@ -41,9 +41,9 @@ LL | let _ref: &'static u8 = unsafe { std::mem::transmute:: = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; @@ -58,9 +58,9 @@ LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute:: = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance | LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; @@ -75,9 +75,9 @@ LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ptr = unsafe { std::mem::transmute::(42usize) }; @@ -92,9 +92,9 @@ LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ptr = unsafe { std::mem::transmute::(a + a) }; @@ -109,9 +109,9 @@ LL | let _ptr: *const u8 = unsafe { std::mem::transmute::( | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ptr: *const u8 = unsafe { std::mem::transmute::(a) }; @@ -126,9 +126,9 @@ LL | let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) } | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance | LL - let _ptr: *mut u8 = unsafe { std::mem::transmute::(a) }; @@ -143,9 +143,9 @@ LL | let _ref: &'static u8 = unsafe { std::mem::transmute:: = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ref: &'static u8 = unsafe { std::mem::transmute::(a) }; @@ -160,9 +160,9 @@ LL | let _ref: &'static mut u8 = unsafe { std::mem::transmute:: = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance_mut` instead to use a previously exposed provenance | LL - let _ref: &'static mut u8 = unsafe { std::mem::transmute::(a) }; @@ -177,9 +177,9 @@ LL | let _ptr = unsafe { std::mem::transmute::(42usize) }; | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ptr = unsafe { std::mem::transmute::(42usize) }; @@ -194,9 +194,9 @@ LL | let _ptr = unsafe { std::mem::transmute::(a + a) }; | = note: this is dangerous because dereferencing the resulting pointer is undefined behavior = note: exposed provenance semantics can be used to create a pointer based on some previously exposed provenance - = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` = help: for more information about transmute, see = help: for more information about exposed provenance, see + = help: if you truly mean to create a pointer without provenance, use `std::ptr::without_provenance_mut` help: use `std::ptr::with_exposed_provenance` instead to use a previously exposed provenance | LL - let _ptr = unsafe { std::mem::transmute::(a + a) }; From c2e5f1152c7090b37250eb1539f9ac5dce753b61 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 13:07:35 +0200 Subject: [PATCH 0697/1309] Update sync docs --- src/tools/rustfmt/Subtree sync procedure.md | 187 +++----------------- 1 file changed, 20 insertions(+), 167 deletions(-) diff --git a/src/tools/rustfmt/Subtree sync procedure.md b/src/tools/rustfmt/Subtree sync procedure.md index e993456f8bc37..cedca7b40f5da 100644 --- a/src/tools/rustfmt/Subtree sync procedure.md +++ b/src/tools/rustfmt/Subtree sync procedure.md @@ -1,190 +1,43 @@ # `rustfmt` subtree sync procedure -Note that `rustfmt` has not migrated to `josh` yet, so the git subtree sync is somewhat involved. -This procedure is mostly adapted from the `clippy` subtree sync process at -, but adapted for -`rustfmt`. We are keeping a separate copy of the instructions for `rustfmt` in case `clippy` moves -off of `git subtree` in the mean time (and also slightly adjusted to be `rustfmt`-specific. +`rustfmt` is using [Josh] to perform subtree synces with the `rust-lang/rust` repository. -> [!NOTE] -> -> Note that AFAIK, eventually both `clippy` and `rustfmt` would like to move to the `josh`-sync -> workflow, just that `rustfmt` is blocked on actually doing a bidirectional sync first, while -> `clippy` is sorting out some issues related to tags and git history (due to usage of `git -> subtree`). +[Josh]: https://josh-project.dev/docs/intro.html ## Tooling -The `git-subtree` tooling still has a bug that prevents it from working properly with the -`rust-lang/rust` repository. This means that you need to build and use a patched version of -`git-subtree`. +The [`josh-sync`][josh-sync] tool is used as a wrapper on top of Josh to help automate the subtree +sync process (both pulls and pushes). You can install it with `cargo install --git https://github.com/rust-lang/josh-sync`. -> [!NOTE] -> -> The patched version of `git-subtree` is the sources corresponding to the stale PR -> . +[josh-sync]: https://github.com/rust-lang/josh-sync -On Linux, place `git-subtree` under `/usr/lib/git-core` (make sure to keep a backup copy of the -'standard' `git-subtree`), and make sure it has proper permissions: +## Subtree pull direction: syncing changes from `rust-lang/rust` to `rustfmt` -```sh -$ sudo cp --backup /path/to/patched/git-subtree.sh /usr/lib/git-core/git-subtree -$ sudo chmod --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree -$ sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree -``` +1. Be in a `rustfmt` checkout +2. Checkout the latest `main` branch from upstream +3. Create a new branch that will be used for the sync +4. Run `rustc-josh-sync pull` +5. Confirm the creation of a PR directly by `rustc-josh-sync`, or create a PR to `rust-lang/rustfmt` repository -> [!NOTE] -> -> Running `git subtree push` for the first time requires building a cache, which involves going -> through the entire history of `rustfmt` once. You likely will need to increase the stack limit via -> -> ```sh -> $ ulimit -s 60000 -> ``` - -> [!NOTE] -> -> The following steps assume that you have configured the `rustfmt` remote as `upstream`, i.e. -> -> ```sh -> $ git remote add upstream git@github.com:rust-lang/rustfmt -> ``` - -## Subtree push direction: syncing changes from `rust-lang/rust` to `rustfmt` - -> [!WARNING] -> -> **For this subtree-push direction, all commands described must be run within the `rust-lang/rust` -> checkout.** - -### 1. Acquire a checkout of `rust-lang/rust` - -Either acquire a clone of `rust-lang/rust`, or if you already have a checkout, make sure the -checkout is up-to-date via `git fetch`. - -### 2. Checkout the commit from the latest available nightly - - You can fetch the commit hash of the latest available nightly by inspecting `rustup check` output. - -### 3. Sync changes from the `rust`-copy of `rustfmt` to your `rustfmt` fork - -> [!WARNING] -> -> **Make sure to either use a fresh branch, e.g. `subtree-push`, or delete the branch beforehand**. -> Changes cannot be fast forwarded and you have to run this command again. - -```sh -$ git subtree push -P src/tools/rustfmt /path/to/rustfmt/checkout subtree-push -``` - -Most of the time, you will need to create a **merge commit** in the `rustfmt` repository. Note that -this must be done in the subtree repo (i.e. `rustfmt` repo) and not in the `rust`-copy of `rustfmt`. - -Assuming the `upstream` remote is the `rust-lang/rust` remote: - -```sh -$ git fetch upstream -$ git switch subtree-push -$ git merge upstream/main --no-ff -``` - -> [!WARNING] -> -> You may have to manually resolve certain merge conflicts. Pay extra attention when resolving them, -> since it's easy to accidentally resolve the conflict in incorrect ways. - -> [!TIP] -> -> Subtree syncs are one of the rare occasions where a merge commit is allowed in a PR. - -### 4. Bump the nightly toolchain version in the `rustfmt` repository - -Using the same latest nightly date (that you can obtain by inspecting `rustup check` output), -manually edit `rust-toolchain.toml`: - -```diff - [toolchain] --channel = "nightly-2025-04-02" -+channel = "nightly-$LATEST_NIGHTLY_DATE" - components = ["llvm-tools", "rustc-dev"] -``` - -Substituting `$LATEST_NIGHTLY_DATE` with the latest nightly date. - -Create a separate commit dedicated to making the `rust-toolchain` change. You can use [the following -commit message template](#rust-toolchain-bump-commit-message-template). - -#### `rust-toolchain` bump commit message template - -````text -chore: bump rustfmt toolchain to nightly-$LATEST_NIGHTLY_DATE - -Bumping the toolchain version as part of a git subtree push. - -Before: - -``` -$CURRENT_NIGHTLY_VERSION-nightly ($CURRENT_NIGHTLY_HASH $CURRENT_NIGHTLY_DATE) -``` - -After: - -``` -$LATEST_NIGHTLY_VERSION-nightly ($LATEST_NIGHTLY_HASH $LATEST_NIGHTLY_DATE) -``` -```` - -Substituting the placeholders with the right information. - -### 5. Open a PR against `rustfmt` - -And wait for the sync PR to be merged. The `rustfmt` maintainers will run Diff Check against the PR -to catch any unexpected formatting changes. +The `rustfmt` maintainers will run Diff Check against the PR to catch any unexpected formatting changes. - Maintainers should trigger Diff-Check for the combinations of Edition {2021, 2024} x Style Edition {2021, 2024}. Once Diff Check failures are investigated and are resolved, the PR can then be merged. -For the PR: - -- Use the title `subtree-push nightly-$LATEST_NIGHTLY_DATE` for consistency with previous - subtree-pushes. -- Include a copy of the bump commit message in the PR description for quick reference. Feel free to - include additional notes that might be helpful for the maintainers when reviewing. - -**Make sure to minimize the time between the subtree-push direction and the subtree-pull direction -to avoid unnecessary complications.** - -### 5. (Where applicable) Update changelog and bump rustfmt version number +### (Where applicable) Update changelog and bump rustfmt version number Where applicable, we may need to update the CHANGELOG entries with merged PRs (both in `rustfmt` repository and also in the `rust-lang/rust` `rustfmt` subtree that was included in the subtree-push merge), and then bump rustfmt version number. -## Subtree pull direction: syncing from `rustfmt` to `rust-lang/rust` - -> [!WARNING] -> -> For this **subtree-pull** direction, all commands must also be performed within the -> `rust-lang/rust` checkout. - -### 1. Make sure latest `main` of `rust-lang/rust` is checked out - -### 2. Sync `rustfmt` `main` to the `rust`-copy of `rustfmt` - -```sh -$ git switch -c rustfmt-subtree-update -$ git subtree pull -P src/tools/rustfmt /path/to/rustfmt/checkout main -``` - -### 3. Open a PR against `rust-lang/rust` - -Use the PR title - -> `rustfmt` subtree update +## Subtree push direction: syncing changes from `rustfmt` to rust-lang/rust` -so that `triagebot` will not warn against the PR containing a merge commit, and makes it easy for -`rustfmt` maintainers to discover. +1. Be in a `rustfmt` checkout +2. Checkout the latest `main` branch from upstream +3. Run `rustc-josh-sync push ` + - Josh will push the changes to a branch with the given name in your `/rust` fork of `rust-lang/rust`. +4. Follow the prompt of `rustc-josh-sync` to open a PR to `rust-lang/rust`, or create the PR manually. -Back link to the `rustfmt` subtree-push PR as helpful context. +**Make sure to minimize the time between a pull and a subsequent push to avoid unnecessary complications.** From d9e4b39c549474cc12239d6ee797acd4d7c1f2e9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 13:10:03 +0200 Subject: [PATCH 0698/1309] Rename rust-toolchain to rust-toolchain.toml For better compatibility with josh-sync. The old filename is deprecated anyway. --- rust-toolchain => rust-toolchain.toml | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename rust-toolchain => rust-toolchain.toml (100%) diff --git a/rust-toolchain b/rust-toolchain.toml similarity index 100% rename from rust-toolchain rename to rust-toolchain.toml From 047bdcbe109cbed3a78ea01ff1a5637ef6c8c3dd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 13:13:00 +0200 Subject: [PATCH 0699/1309] Update apt packages before installing them --- .github/workflows/ci.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f5cc409e363d..f37123c124c74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,9 @@ jobs: - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. - run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm + run: | + sudo apt-get update + sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - name: Install the libraries needed to build librsvg if: ${{ contains(matrix.commands, '--projects') }} From 5695ab858ef53df19d937a072dc2a6acee183219 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 23 Sep 2026 13:44:32 +0200 Subject: [PATCH 0700/1309] std: split stack overflow module (duplicate) --- .../handler_cygwin.rs} | 0 .../pal/unix/stack_overflow/handler_none.rs | 844 ++++++++++++++++++ .../pal/unix/stack_overflow/handler_signal.rs | 844 ++++++++++++++++++ .../src/sys/pal/unix/stack_overflow/mod.rs | 844 ++++++++++++++++++ 4 files changed, 2532 insertions(+) rename library/std/src/sys/pal/unix/{stack_overflow.rs => stack_overflow/handler_cygwin.rs} (100%) create mode 100644 library/std/src/sys/pal/unix/stack_overflow/handler_none.rs create mode 100644 library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs create mode 100644 library/std/src/sys/pal/unix/stack_overflow/mod.rs diff --git a/library/std/src/sys/pal/unix/stack_overflow.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs similarity index 100% rename from library/std/src/sys/pal/unix/stack_overflow.rs rename to library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs new file mode 100644 index 0000000000000..5604e3e6dbf42 --- /dev/null +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs @@ -0,0 +1,844 @@ +#![cfg_attr(test, allow(dead_code))] +#![forbid(unsafe_op_in_unsafe_fn)] + +pub use self::imp::init; +use self::imp::{drop_handler, make_handler}; + +pub struct Handler { + data: *mut libc::c_void, +} + +impl Handler { + pub unsafe fn new() -> Handler { + make_handler(false) + } + + fn null() -> Handler { + Handler { data: crate::ptr::null_mut() } + } +} + +impl Drop for Handler { + fn drop(&mut self) { + unsafe { + drop_handler(self.data); + } + } +} + +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ), +))] +mod thread_info; + +// miri doesn't model signals nor stack overflows and this code has some +// synchronization properties that we don't want to expose to user code, +// hence we disable it on miri. +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ) +))] +mod imp { + use libc::{ + MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, + SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, + }; + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] + use libc::{mmap as mmap64, mprotect, munmap}; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + use libc::{mmap64, mprotect, munmap}; + + use super::Handler; + use super::thread_info::{delete_current_info, set_current_info, with_current_info}; + use crate::ops::Range; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; + use crate::sys::pal::unix::conf; + use crate::{io, mem, ptr}; + + /// Signal handler for the SIGSEGV and SIGBUS handlers. + /// + /// We've got guard pages (unmapped pages) at the end of every thread's + /// stack, so if a thread ends up running into the guard page it'll trigger + /// this handler. We want to detect these cases and print out a helpful error + /// saying that the stack has overflowed. All other signals, however, should + /// go back to what they were originally supposed to do. + /// + /// This handler currently exists purely to print an informative message + /// whenever a thread overflows its stack. We then abort to exit and + /// indicate a crash, but to avoid a misleading SIGSEGV that might lead + /// users to believe that unsafe code has accessed an invalid pointer; the + /// SIGSEGV encountered when overflowing the stack is expected and + /// well-defined. + /// + /// If this is not a stack overflow, the handler un-registers itself and + /// then returns (to allow the original signal to be delivered again). + /// Returning from this kind of signal handler is technically not defined + /// to work when reading the POSIX spec strictly, but in practice it turns + /// out many large systems and all implementations allow returning from a + /// signal handler to work. For a more detailed explanation see the + /// comments on #26458. + /// + /// # Safety + /// Rust doesn't call this, it *gets called* by the kernel, which we expect + /// to provide valid parameters. Apart from that, this function does not + /// have any other preconditions. + unsafe extern "C" fn signal_handler( + signum: libc::c_int, + info: *mut libc::siginfo_t, + _data: *mut libc::c_void, + ) { + // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. + let fault_addr = unsafe { (*info).si_addr().addr() }; + + // `with_current_info` expects that the process aborts after it is + // called. If the signal was not caused by a memory access, this might + // not be true. We detect this by noticing that the `si_addr` field is + // zero if the signal is synthetic. + if fault_addr != 0 { + with_current_info(|thread_info| { + // If the faulting address is within the guard page, then we print a + // message saying so and abort. + if let Some(thread_info) = thread_info + && thread_info.guard_page_range.contains(&fault_addr) + { + // Hey you! Yes, you modifying the stack overflow message! + // Please make sure that all functions called here are + // actually async-signal-safe. If they're not, try retrieving + // the information beforehand and storing it in `ThreadInfo`. + // Thank you! + // - says Jonas after having had to watch his carefully + // written code get made unsound again. + let tid = thread_info.tid; + let name = thread_info.name.as_deref().unwrap_or(""); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + rtabort!("stack overflow"); + } + }) + } + + // Unregister ourselves by reverting back to the default behavior. + // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" + let mut action: sigaction = unsafe { mem::zeroed() }; + action.sa_sigaction = SIG_DFL; + // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction + unsafe { sigaction(signum, &action, ptr::null_mut()) }; + + // See comment above for why this function returns. + } + + static PAGE_SIZE: Atomic = AtomicUsize::new(0); + // Store a pointer to the allocation for the main thread's altstack so that + // tools like valgrind don't complain about a leaked unreachable allocation. + // + // If the main thread exits, the process will terminate so there's no use in + // freeing resources. It also means that the altstack is still installed + // while TLS destructors are run on the main thread (c.f. #111272). + static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); + static NEED_ALTSTACK: Atomic = AtomicBool::new(false); + + /// # Safety + /// Must be called only once, on the main thread, during program startup. + pub unsafe fn init() { + PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); + + // SAFETY: + // This is only called on the main thread, and since it is still early + // in the programs lifetime there is (almost) certainly enough stack + // space left to install the guard page. + let mut guard_page_range = unsafe { install_main_guard() }; + + // Even for panic=immediate-abort, installing the guard pages is important for soundness. + // That said, we do not care about giving nice stackoverflow messages via our custom + // signal handler, just exit early and let the user enjoy the segfault. + if cfg!(panic = "immediate-abort") { + return; + } + + // SAFETY: C structures are always zero-initializable. + let mut action: sigaction = unsafe { mem::zeroed() }; + for &signal in &[SIGSEGV, SIGBUS] { + // SAFETY: just fetches the current signal handler into action + unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; + // We assume that overriding the signal handler is always safe, + // which might conflict with certain libraries that rely on a + // specific signal behaviour. To prevent problems, we only + // override the handler if it has not been set yet. + if action.sa_sigaction == SIG_DFL { + if !NEED_ALTSTACK.load(Ordering::Relaxed) { + // haven't set up our sigaltstack yet + NEED_ALTSTACK.store(true, Ordering::Release); + let handler = make_handler(true); + MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); + mem::forget(handler); + + if let Some(guard_page_range) = guard_page_range.take() { + set_current_info(guard_page_range); + } + } + + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + action.sa_sigaction = signal_handler + as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) + as sighandler_t; + // SAFETY: + // `&action` describes a valid `sigaction` and `signal_handler` + // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. + unsafe { sigaction(signal, &action, ptr::null_mut()) }; + } + } + } + + fn get_stack() -> libc::stack_t { + // OpenBSD requires this flag for stack mapping + // otherwise the said mapping will fail as a no-op on most systems + // and has a different meaning on FreeBSD + #[cfg(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + ))] + let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; + #[cfg(not(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + )))] + let flags = MAP_PRIVATE | MAP_ANON; + + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // SAFETY: this does not unmap any existing pages. + let stackp = unsafe { + mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) + }; + if stackp == MAP_FAILED { + panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); + } + // SAFETY: this only affects the memory we just allocated. + let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; + if guard_result != 0 { + panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); + } + // SAFETY: + // The region was allocated with a larger size than `page_size`, so this + // addition is within bounds. + let stackp = unsafe { stackp.add(page_size) }; + + libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } + } + + pub fn make_handler(main_thread: bool) -> Handler { + if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { + return Handler::null(); + } + + if !main_thread { + if let Some(guard_page_range) = current_guard() { + set_current_info(guard_page_range); + } + } + + // Load the current alternate signal stack to see if we need to install + // our own. + // + // SAFETY: C structures are always zero-initializable. + let mut stack = unsafe { mem::zeroed() }; + // SAFETY: `&mut stack` is valid for writing a `stack_t`. + unsafe { sigaltstack(ptr::null(), &mut stack) }; + + // Configure alternate signal stack, if one is not already set. + if stack.ss_flags & SS_DISABLE != 0 { + let stack = get_stack(); + // SAFETY: + // `stack_t` is a freshly allocated stack that's not used anywhere + // else. It contains a guard page, so stack overflows in signal + // handlers will not cause undefined behaviour. We must make the + // fundamental runtime assumption that it is safe to install an + // alternate signal stack if there is none currently installed. + // This might conflict with foreign libraries that use the existence + // of an alternate signal stack as indication that certain runtime + // initialisation by the library has been performed (e.g. old + // versions of `std` assumed that certain thread-locals were already + // accessed and thus initialized in the thread if the stack overflow + // signal was successfully delivered). Such assumptions in other + // libraries are fundamentally flawed, so we pay no regard to them. + unsafe { sigaltstack(&stack, ptr::null_mut()) }; + Handler { data: stack.ss_sp as *mut libc::c_void } + } else { + Handler::null() + } + } + + /// # Safety + /// Must only be called with a pointer returned by `make_handler`, and only + /// once per `Handler`. + pub unsafe fn drop_handler(data: *mut libc::c_void) { + if !data.is_null() { + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + let disabling_stack = libc::stack_t { + ss_sp: ptr::null_mut(), + ss_flags: SS_DISABLE, + // Workaround for bug in macOS implementation of sigaltstack + // UNIX2003 which returns ENOMEM when disabling a stack while + // passing ss_size smaller than MINSIGSTKSZ. According to POSIX + // both ss_sp and ss_size should be ignored in this case. + ss_size: sigstack_size, + }; + // SAFETY: + // We assume that disabling the alternate signal stack is always + // sound, even if the current alternate signal stack is not the one + // we installed in `make_handler`. Any stack overflows from this + // point on will abort the program when the kernel tries to write + // the signal information to the guard page. + // + // FIXME: detect if the stack has changed, and only uninstall if it hasn't. + unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; + // The stack returned by `get_stack` is part of a mapping that + // started one page earlier, so walk back a page and unmap from + // there. + // + // SAFETY: + // This allocation was created by us in `get_stack` and, as the + // alternate signal stack is now disabled, is no longer in use. + unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; + } + + delete_current_info(); + } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] + fn sigstack_size() -> usize { + // SAFETY: `getauxval` is always safe to call. + let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::SIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] + fn sigstack_size() -> usize { + libc::SIGSTKSZ + } + + #[cfg(any(target_os = "solaris", target_os = "illumos"))] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // The pointer is valid for writing a `stack_t`. + assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: always safe to call. + let th = unsafe { libc::pthread_self() }; + // SAFETY: `th` is a valid `pthread_t`. + unsafe { + let stackptr = libc::pthread_get_stackaddr_np(th); + let stacksize = libc::pthread_get_stacksize_np(th); + Some(stackptr.map_addr(|addr| addr - stacksize)) + } + } + + #[cfg(target_os = "openbsd")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t`. + // * `&mut current_stack` is coerced to a pointer that is valid for writing + // a `stack_t`. + assert_eq!( + unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, + 0 + ); + + let stack_ptr = current_stack.ss_sp; + // SAFETY: this is always safe to call. + let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { + // main thread + stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) + } else { + // new thread + stack_ptr.addr() - current_stack.ss_size + }; + Some(stack_ptr.with_addr(stackaddr)) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "hurd", + target_os = "linux", + target_os = "l4re" + ))] + fn get_stack_start() -> Option<*mut libc::c_void> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut stackaddr = crate::ptr::null_mut(); + let mut stacksize = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, + 0 + ); + ret = Some(stackaddr); + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } + + fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + + // Ensure stackaddr is page aligned! A parent process might + // have reset RLIMIT_STACK to be non-page aligned. The + // pthread_attr_getstack() reports the usable stack area + // stackaddr < stackaddr + stacksize, so if stackaddr is not + // page-aligned, calculate the fix such that stackaddr < + // new_page_aligned_stackaddr < stackaddr + stacksize + let remainder = stackaddr % page_size; + Some(if remainder == 0 { + stackptr + } else { + stackptr.with_addr(stackaddr + page_size - remainder) + }) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard() -> Option> { + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // this way someone on any unix-y OS can check that all these compile + if cfg!(all(target_os = "linux", not(target_env = "musl"))) { + install_main_guard_linux(page_size) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + install_main_guard_linux_musl(page_size) + } else if cfg!(target_os = "freebsd") { + #[cfg(not(target_os = "freebsd"))] + return None; + // The FreeBSD code cannot be checked on non-BSDs. + #[cfg(target_os = "freebsd")] + install_main_guard_freebsd(page_size) + } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { + install_main_guard_bsds(page_size) + } else { + // SAFETY: guaranteed by caller. + unsafe { install_main_guard_default(page_size) } + } + } + + fn install_main_guard_linux(page_size: usize) -> Option> { + // See the corresponding conditional in init(). + // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps + if cfg!(panic = "immediate-abort") { + return None; + } + // Linux doesn't allocate the whole stack right away, and + // the kernel has its own stack-guard mechanism to fault + // when growing too close to an existing mapping. If we map + // our own guard, then the kernel starts enforcing a rather + // large gap above that, rendering much of the possible + // stack space useless. See #43052. + // + // Instead, we'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + fn install_main_guard_linux_musl(_page_size: usize) -> Option> { + // For the main thread, the musl's pthread_attr_getstack + // returns the current stack size, rather than maximum size + // it can eventually grow to. It cannot be used to determine + // the position of kernel's stack guard. + None + } + + #[cfg(target_os = "freebsd")] + fn install_main_guard_freebsd(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // FreeBSD's stack autogrows, and optionally includes a guard page + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // the builtin guard page. + let stackptr = stack_start_aligned(page_size)?; + let guardaddr = stackptr.addr(); + // Technically the number of guard pages is tunable and controlled + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + // FIXME(joboet): this function is only called once, remove the caching. + static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); + + let pages = PAGES.get_or_init(|| { + let mut guard: usize = 0; + let mut size = size_of_val(&guard); + let oid = c"security.bsd.stack_guard_page"; + + let r = unsafe { + libc::sysctlbyname( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) + }; + if r == 0 { guard } else { 1 } + }); + Some(guardaddr..guardaddr + pages * page_size) + } + + fn install_main_guard_bsds(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // OpenBSD stack already includes a guard page, and stack is + // immutable. + // NetBSD stack includes the guard page. + // + // We'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard_default(page_size: usize) -> Option> { + // Reallocate the last page of the stack. + // This ensures SIGBUS will be raised on + // stack overflow. + // Systems which enforce strict PAX MPROTECT do not allow + // to mprotect() a mapping with less restrictive permissions + // than the initial mmap() used, so we mmap() here with + // read/write permissions and only then mprotect() it to + // no permissions at all. See issue #50313. + let stackptr = stack_start_aligned(page_size)?; + // SAFETY: + // The memory region from `stackptr..stackptr + page_size` belongs to + // the current thread's stack, and the caller has asserted that there + // is sufficient stack space, which means that this will not overwrite + // any existing allocations. + let result = unsafe { + mmap64( + stackptr, + page_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + -1, + 0, + ) + }; + if result != stackptr || result == MAP_FAILED { + panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); + } + + // SAFETY: + // Since this function is only called on the main thread, the stack will + // not be reused until program exit, so the runtime will never observe + // that part of the stack has been made unusable in this way. + let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; + if result != 0 { + panic!("failed to protect the guard page: {}", io::Error::last_os_error()); + } + + let guardaddr = stackptr.addr(); + + Some(guardaddr..guardaddr + page_size) + } + + #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ))] + fn current_guard() -> Option> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "hurd", + target_os = "linux", + target_os = "netbsd", + target_os = "l4re" + ))] + fn current_guard() -> Option> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut guardsize = 0; + // SAFETY: + // `attr` is an initialized attribute object and the pointer is valid + // for writing. + assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); + if guardsize == 0 { + if cfg!(all(target_os = "linux", target_env = "musl")) { + // musl versions before 1.1.19 always reported guard + // size obtained from pthread_attr_get_np as zero. + // Use page size as a fallback. + guardsize = PAGE_SIZE.load(Ordering::Relaxed); + } else { + panic!("there is no guard page"); + } + } + let mut stackptr = crate::ptr::null_mut::(); + let mut size = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, + 0 + ); + + let stackaddr = stackptr.addr(); + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) + { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) + } else { + Some(stackaddr..stackaddr + guardsize) + }; + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } +} + +// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses +// several symbols that might lead to rejections from the App Store, namely +// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. +// +// This might be overly cautious, though it is also what Swift does (and they +// usually have fewer qualms about forwards compatibility, since the runtime +// is shipped with the OS): +// +#[cfg(any( + miri, + not(any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + target_os = "cygwin", + )) +))] +mod imp { + pub unsafe fn init() {} + + pub fn make_handler(_main_thread: bool) -> super::Handler { + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or(""); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs new file mode 100644 index 0000000000000..5604e3e6dbf42 --- /dev/null +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs @@ -0,0 +1,844 @@ +#![cfg_attr(test, allow(dead_code))] +#![forbid(unsafe_op_in_unsafe_fn)] + +pub use self::imp::init; +use self::imp::{drop_handler, make_handler}; + +pub struct Handler { + data: *mut libc::c_void, +} + +impl Handler { + pub unsafe fn new() -> Handler { + make_handler(false) + } + + fn null() -> Handler { + Handler { data: crate::ptr::null_mut() } + } +} + +impl Drop for Handler { + fn drop(&mut self) { + unsafe { + drop_handler(self.data); + } + } +} + +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ), +))] +mod thread_info; + +// miri doesn't model signals nor stack overflows and this code has some +// synchronization properties that we don't want to expose to user code, +// hence we disable it on miri. +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ) +))] +mod imp { + use libc::{ + MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, + SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, + }; + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] + use libc::{mmap as mmap64, mprotect, munmap}; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + use libc::{mmap64, mprotect, munmap}; + + use super::Handler; + use super::thread_info::{delete_current_info, set_current_info, with_current_info}; + use crate::ops::Range; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; + use crate::sys::pal::unix::conf; + use crate::{io, mem, ptr}; + + /// Signal handler for the SIGSEGV and SIGBUS handlers. + /// + /// We've got guard pages (unmapped pages) at the end of every thread's + /// stack, so if a thread ends up running into the guard page it'll trigger + /// this handler. We want to detect these cases and print out a helpful error + /// saying that the stack has overflowed. All other signals, however, should + /// go back to what they were originally supposed to do. + /// + /// This handler currently exists purely to print an informative message + /// whenever a thread overflows its stack. We then abort to exit and + /// indicate a crash, but to avoid a misleading SIGSEGV that might lead + /// users to believe that unsafe code has accessed an invalid pointer; the + /// SIGSEGV encountered when overflowing the stack is expected and + /// well-defined. + /// + /// If this is not a stack overflow, the handler un-registers itself and + /// then returns (to allow the original signal to be delivered again). + /// Returning from this kind of signal handler is technically not defined + /// to work when reading the POSIX spec strictly, but in practice it turns + /// out many large systems and all implementations allow returning from a + /// signal handler to work. For a more detailed explanation see the + /// comments on #26458. + /// + /// # Safety + /// Rust doesn't call this, it *gets called* by the kernel, which we expect + /// to provide valid parameters. Apart from that, this function does not + /// have any other preconditions. + unsafe extern "C" fn signal_handler( + signum: libc::c_int, + info: *mut libc::siginfo_t, + _data: *mut libc::c_void, + ) { + // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. + let fault_addr = unsafe { (*info).si_addr().addr() }; + + // `with_current_info` expects that the process aborts after it is + // called. If the signal was not caused by a memory access, this might + // not be true. We detect this by noticing that the `si_addr` field is + // zero if the signal is synthetic. + if fault_addr != 0 { + with_current_info(|thread_info| { + // If the faulting address is within the guard page, then we print a + // message saying so and abort. + if let Some(thread_info) = thread_info + && thread_info.guard_page_range.contains(&fault_addr) + { + // Hey you! Yes, you modifying the stack overflow message! + // Please make sure that all functions called here are + // actually async-signal-safe. If they're not, try retrieving + // the information beforehand and storing it in `ThreadInfo`. + // Thank you! + // - says Jonas after having had to watch his carefully + // written code get made unsound again. + let tid = thread_info.tid; + let name = thread_info.name.as_deref().unwrap_or(""); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + rtabort!("stack overflow"); + } + }) + } + + // Unregister ourselves by reverting back to the default behavior. + // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" + let mut action: sigaction = unsafe { mem::zeroed() }; + action.sa_sigaction = SIG_DFL; + // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction + unsafe { sigaction(signum, &action, ptr::null_mut()) }; + + // See comment above for why this function returns. + } + + static PAGE_SIZE: Atomic = AtomicUsize::new(0); + // Store a pointer to the allocation for the main thread's altstack so that + // tools like valgrind don't complain about a leaked unreachable allocation. + // + // If the main thread exits, the process will terminate so there's no use in + // freeing resources. It also means that the altstack is still installed + // while TLS destructors are run on the main thread (c.f. #111272). + static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); + static NEED_ALTSTACK: Atomic = AtomicBool::new(false); + + /// # Safety + /// Must be called only once, on the main thread, during program startup. + pub unsafe fn init() { + PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); + + // SAFETY: + // This is only called on the main thread, and since it is still early + // in the programs lifetime there is (almost) certainly enough stack + // space left to install the guard page. + let mut guard_page_range = unsafe { install_main_guard() }; + + // Even for panic=immediate-abort, installing the guard pages is important for soundness. + // That said, we do not care about giving nice stackoverflow messages via our custom + // signal handler, just exit early and let the user enjoy the segfault. + if cfg!(panic = "immediate-abort") { + return; + } + + // SAFETY: C structures are always zero-initializable. + let mut action: sigaction = unsafe { mem::zeroed() }; + for &signal in &[SIGSEGV, SIGBUS] { + // SAFETY: just fetches the current signal handler into action + unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; + // We assume that overriding the signal handler is always safe, + // which might conflict with certain libraries that rely on a + // specific signal behaviour. To prevent problems, we only + // override the handler if it has not been set yet. + if action.sa_sigaction == SIG_DFL { + if !NEED_ALTSTACK.load(Ordering::Relaxed) { + // haven't set up our sigaltstack yet + NEED_ALTSTACK.store(true, Ordering::Release); + let handler = make_handler(true); + MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); + mem::forget(handler); + + if let Some(guard_page_range) = guard_page_range.take() { + set_current_info(guard_page_range); + } + } + + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + action.sa_sigaction = signal_handler + as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) + as sighandler_t; + // SAFETY: + // `&action` describes a valid `sigaction` and `signal_handler` + // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. + unsafe { sigaction(signal, &action, ptr::null_mut()) }; + } + } + } + + fn get_stack() -> libc::stack_t { + // OpenBSD requires this flag for stack mapping + // otherwise the said mapping will fail as a no-op on most systems + // and has a different meaning on FreeBSD + #[cfg(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + ))] + let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; + #[cfg(not(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + )))] + let flags = MAP_PRIVATE | MAP_ANON; + + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // SAFETY: this does not unmap any existing pages. + let stackp = unsafe { + mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) + }; + if stackp == MAP_FAILED { + panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); + } + // SAFETY: this only affects the memory we just allocated. + let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; + if guard_result != 0 { + panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); + } + // SAFETY: + // The region was allocated with a larger size than `page_size`, so this + // addition is within bounds. + let stackp = unsafe { stackp.add(page_size) }; + + libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } + } + + pub fn make_handler(main_thread: bool) -> Handler { + if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { + return Handler::null(); + } + + if !main_thread { + if let Some(guard_page_range) = current_guard() { + set_current_info(guard_page_range); + } + } + + // Load the current alternate signal stack to see if we need to install + // our own. + // + // SAFETY: C structures are always zero-initializable. + let mut stack = unsafe { mem::zeroed() }; + // SAFETY: `&mut stack` is valid for writing a `stack_t`. + unsafe { sigaltstack(ptr::null(), &mut stack) }; + + // Configure alternate signal stack, if one is not already set. + if stack.ss_flags & SS_DISABLE != 0 { + let stack = get_stack(); + // SAFETY: + // `stack_t` is a freshly allocated stack that's not used anywhere + // else. It contains a guard page, so stack overflows in signal + // handlers will not cause undefined behaviour. We must make the + // fundamental runtime assumption that it is safe to install an + // alternate signal stack if there is none currently installed. + // This might conflict with foreign libraries that use the existence + // of an alternate signal stack as indication that certain runtime + // initialisation by the library has been performed (e.g. old + // versions of `std` assumed that certain thread-locals were already + // accessed and thus initialized in the thread if the stack overflow + // signal was successfully delivered). Such assumptions in other + // libraries are fundamentally flawed, so we pay no regard to them. + unsafe { sigaltstack(&stack, ptr::null_mut()) }; + Handler { data: stack.ss_sp as *mut libc::c_void } + } else { + Handler::null() + } + } + + /// # Safety + /// Must only be called with a pointer returned by `make_handler`, and only + /// once per `Handler`. + pub unsafe fn drop_handler(data: *mut libc::c_void) { + if !data.is_null() { + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + let disabling_stack = libc::stack_t { + ss_sp: ptr::null_mut(), + ss_flags: SS_DISABLE, + // Workaround for bug in macOS implementation of sigaltstack + // UNIX2003 which returns ENOMEM when disabling a stack while + // passing ss_size smaller than MINSIGSTKSZ. According to POSIX + // both ss_sp and ss_size should be ignored in this case. + ss_size: sigstack_size, + }; + // SAFETY: + // We assume that disabling the alternate signal stack is always + // sound, even if the current alternate signal stack is not the one + // we installed in `make_handler`. Any stack overflows from this + // point on will abort the program when the kernel tries to write + // the signal information to the guard page. + // + // FIXME: detect if the stack has changed, and only uninstall if it hasn't. + unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; + // The stack returned by `get_stack` is part of a mapping that + // started one page earlier, so walk back a page and unmap from + // there. + // + // SAFETY: + // This allocation was created by us in `get_stack` and, as the + // alternate signal stack is now disabled, is no longer in use. + unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; + } + + delete_current_info(); + } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] + fn sigstack_size() -> usize { + // SAFETY: `getauxval` is always safe to call. + let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::SIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] + fn sigstack_size() -> usize { + libc::SIGSTKSZ + } + + #[cfg(any(target_os = "solaris", target_os = "illumos"))] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // The pointer is valid for writing a `stack_t`. + assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: always safe to call. + let th = unsafe { libc::pthread_self() }; + // SAFETY: `th` is a valid `pthread_t`. + unsafe { + let stackptr = libc::pthread_get_stackaddr_np(th); + let stacksize = libc::pthread_get_stacksize_np(th); + Some(stackptr.map_addr(|addr| addr - stacksize)) + } + } + + #[cfg(target_os = "openbsd")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t`. + // * `&mut current_stack` is coerced to a pointer that is valid for writing + // a `stack_t`. + assert_eq!( + unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, + 0 + ); + + let stack_ptr = current_stack.ss_sp; + // SAFETY: this is always safe to call. + let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { + // main thread + stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) + } else { + // new thread + stack_ptr.addr() - current_stack.ss_size + }; + Some(stack_ptr.with_addr(stackaddr)) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "hurd", + target_os = "linux", + target_os = "l4re" + ))] + fn get_stack_start() -> Option<*mut libc::c_void> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut stackaddr = crate::ptr::null_mut(); + let mut stacksize = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, + 0 + ); + ret = Some(stackaddr); + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } + + fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + + // Ensure stackaddr is page aligned! A parent process might + // have reset RLIMIT_STACK to be non-page aligned. The + // pthread_attr_getstack() reports the usable stack area + // stackaddr < stackaddr + stacksize, so if stackaddr is not + // page-aligned, calculate the fix such that stackaddr < + // new_page_aligned_stackaddr < stackaddr + stacksize + let remainder = stackaddr % page_size; + Some(if remainder == 0 { + stackptr + } else { + stackptr.with_addr(stackaddr + page_size - remainder) + }) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard() -> Option> { + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // this way someone on any unix-y OS can check that all these compile + if cfg!(all(target_os = "linux", not(target_env = "musl"))) { + install_main_guard_linux(page_size) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + install_main_guard_linux_musl(page_size) + } else if cfg!(target_os = "freebsd") { + #[cfg(not(target_os = "freebsd"))] + return None; + // The FreeBSD code cannot be checked on non-BSDs. + #[cfg(target_os = "freebsd")] + install_main_guard_freebsd(page_size) + } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { + install_main_guard_bsds(page_size) + } else { + // SAFETY: guaranteed by caller. + unsafe { install_main_guard_default(page_size) } + } + } + + fn install_main_guard_linux(page_size: usize) -> Option> { + // See the corresponding conditional in init(). + // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps + if cfg!(panic = "immediate-abort") { + return None; + } + // Linux doesn't allocate the whole stack right away, and + // the kernel has its own stack-guard mechanism to fault + // when growing too close to an existing mapping. If we map + // our own guard, then the kernel starts enforcing a rather + // large gap above that, rendering much of the possible + // stack space useless. See #43052. + // + // Instead, we'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + fn install_main_guard_linux_musl(_page_size: usize) -> Option> { + // For the main thread, the musl's pthread_attr_getstack + // returns the current stack size, rather than maximum size + // it can eventually grow to. It cannot be used to determine + // the position of kernel's stack guard. + None + } + + #[cfg(target_os = "freebsd")] + fn install_main_guard_freebsd(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // FreeBSD's stack autogrows, and optionally includes a guard page + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // the builtin guard page. + let stackptr = stack_start_aligned(page_size)?; + let guardaddr = stackptr.addr(); + // Technically the number of guard pages is tunable and controlled + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + // FIXME(joboet): this function is only called once, remove the caching. + static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); + + let pages = PAGES.get_or_init(|| { + let mut guard: usize = 0; + let mut size = size_of_val(&guard); + let oid = c"security.bsd.stack_guard_page"; + + let r = unsafe { + libc::sysctlbyname( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) + }; + if r == 0 { guard } else { 1 } + }); + Some(guardaddr..guardaddr + pages * page_size) + } + + fn install_main_guard_bsds(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // OpenBSD stack already includes a guard page, and stack is + // immutable. + // NetBSD stack includes the guard page. + // + // We'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard_default(page_size: usize) -> Option> { + // Reallocate the last page of the stack. + // This ensures SIGBUS will be raised on + // stack overflow. + // Systems which enforce strict PAX MPROTECT do not allow + // to mprotect() a mapping with less restrictive permissions + // than the initial mmap() used, so we mmap() here with + // read/write permissions and only then mprotect() it to + // no permissions at all. See issue #50313. + let stackptr = stack_start_aligned(page_size)?; + // SAFETY: + // The memory region from `stackptr..stackptr + page_size` belongs to + // the current thread's stack, and the caller has asserted that there + // is sufficient stack space, which means that this will not overwrite + // any existing allocations. + let result = unsafe { + mmap64( + stackptr, + page_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + -1, + 0, + ) + }; + if result != stackptr || result == MAP_FAILED { + panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); + } + + // SAFETY: + // Since this function is only called on the main thread, the stack will + // not be reused until program exit, so the runtime will never observe + // that part of the stack has been made unusable in this way. + let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; + if result != 0 { + panic!("failed to protect the guard page: {}", io::Error::last_os_error()); + } + + let guardaddr = stackptr.addr(); + + Some(guardaddr..guardaddr + page_size) + } + + #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ))] + fn current_guard() -> Option> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "hurd", + target_os = "linux", + target_os = "netbsd", + target_os = "l4re" + ))] + fn current_guard() -> Option> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut guardsize = 0; + // SAFETY: + // `attr` is an initialized attribute object and the pointer is valid + // for writing. + assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); + if guardsize == 0 { + if cfg!(all(target_os = "linux", target_env = "musl")) { + // musl versions before 1.1.19 always reported guard + // size obtained from pthread_attr_get_np as zero. + // Use page size as a fallback. + guardsize = PAGE_SIZE.load(Ordering::Relaxed); + } else { + panic!("there is no guard page"); + } + } + let mut stackptr = crate::ptr::null_mut::(); + let mut size = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, + 0 + ); + + let stackaddr = stackptr.addr(); + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) + { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) + } else { + Some(stackaddr..stackaddr + guardsize) + }; + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } +} + +// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses +// several symbols that might lead to rejections from the App Store, namely +// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. +// +// This might be overly cautious, though it is also what Swift does (and they +// usually have fewer qualms about forwards compatibility, since the runtime +// is shipped with the OS): +// +#[cfg(any( + miri, + not(any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + target_os = "cygwin", + )) +))] +mod imp { + pub unsafe fn init() {} + + pub fn make_handler(_main_thread: bool) -> super::Handler { + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or(""); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} diff --git a/library/std/src/sys/pal/unix/stack_overflow/mod.rs b/library/std/src/sys/pal/unix/stack_overflow/mod.rs new file mode 100644 index 0000000000000..5604e3e6dbf42 --- /dev/null +++ b/library/std/src/sys/pal/unix/stack_overflow/mod.rs @@ -0,0 +1,844 @@ +#![cfg_attr(test, allow(dead_code))] +#![forbid(unsafe_op_in_unsafe_fn)] + +pub use self::imp::init; +use self::imp::{drop_handler, make_handler}; + +pub struct Handler { + data: *mut libc::c_void, +} + +impl Handler { + pub unsafe fn new() -> Handler { + make_handler(false) + } + + fn null() -> Handler { + Handler { data: crate::ptr::null_mut() } + } +} + +impl Drop for Handler { + fn drop(&mut self) { + unsafe { + drop_handler(self.data); + } + } +} + +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ), +))] +mod thread_info; + +// miri doesn't model signals nor stack overflows and this code has some +// synchronization properties that we don't want to expose to user code, +// hence we disable it on miri. +#[cfg(all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ) +))] +mod imp { + use libc::{ + MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, + SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, + }; + #[cfg(not(all(target_os = "linux", target_env = "gnu")))] + use libc::{mmap as mmap64, mprotect, munmap}; + #[cfg(all(target_os = "linux", target_env = "gnu"))] + use libc::{mmap64, mprotect, munmap}; + + use super::Handler; + use super::thread_info::{delete_current_info, set_current_info, with_current_info}; + use crate::ops::Range; + use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; + use crate::sys::pal::unix::conf; + use crate::{io, mem, ptr}; + + /// Signal handler for the SIGSEGV and SIGBUS handlers. + /// + /// We've got guard pages (unmapped pages) at the end of every thread's + /// stack, so if a thread ends up running into the guard page it'll trigger + /// this handler. We want to detect these cases and print out a helpful error + /// saying that the stack has overflowed. All other signals, however, should + /// go back to what they were originally supposed to do. + /// + /// This handler currently exists purely to print an informative message + /// whenever a thread overflows its stack. We then abort to exit and + /// indicate a crash, but to avoid a misleading SIGSEGV that might lead + /// users to believe that unsafe code has accessed an invalid pointer; the + /// SIGSEGV encountered when overflowing the stack is expected and + /// well-defined. + /// + /// If this is not a stack overflow, the handler un-registers itself and + /// then returns (to allow the original signal to be delivered again). + /// Returning from this kind of signal handler is technically not defined + /// to work when reading the POSIX spec strictly, but in practice it turns + /// out many large systems and all implementations allow returning from a + /// signal handler to work. For a more detailed explanation see the + /// comments on #26458. + /// + /// # Safety + /// Rust doesn't call this, it *gets called* by the kernel, which we expect + /// to provide valid parameters. Apart from that, this function does not + /// have any other preconditions. + unsafe extern "C" fn signal_handler( + signum: libc::c_int, + info: *mut libc::siginfo_t, + _data: *mut libc::c_void, + ) { + // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. + let fault_addr = unsafe { (*info).si_addr().addr() }; + + // `with_current_info` expects that the process aborts after it is + // called. If the signal was not caused by a memory access, this might + // not be true. We detect this by noticing that the `si_addr` field is + // zero if the signal is synthetic. + if fault_addr != 0 { + with_current_info(|thread_info| { + // If the faulting address is within the guard page, then we print a + // message saying so and abort. + if let Some(thread_info) = thread_info + && thread_info.guard_page_range.contains(&fault_addr) + { + // Hey you! Yes, you modifying the stack overflow message! + // Please make sure that all functions called here are + // actually async-signal-safe. If they're not, try retrieving + // the information beforehand and storing it in `ThreadInfo`. + // Thank you! + // - says Jonas after having had to watch his carefully + // written code get made unsound again. + let tid = thread_info.tid; + let name = thread_info.name.as_deref().unwrap_or(""); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + rtabort!("stack overflow"); + } + }) + } + + // Unregister ourselves by reverting back to the default behavior. + // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" + let mut action: sigaction = unsafe { mem::zeroed() }; + action.sa_sigaction = SIG_DFL; + // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction + unsafe { sigaction(signum, &action, ptr::null_mut()) }; + + // See comment above for why this function returns. + } + + static PAGE_SIZE: Atomic = AtomicUsize::new(0); + // Store a pointer to the allocation for the main thread's altstack so that + // tools like valgrind don't complain about a leaked unreachable allocation. + // + // If the main thread exits, the process will terminate so there's no use in + // freeing resources. It also means that the altstack is still installed + // while TLS destructors are run on the main thread (c.f. #111272). + static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); + static NEED_ALTSTACK: Atomic = AtomicBool::new(false); + + /// # Safety + /// Must be called only once, on the main thread, during program startup. + pub unsafe fn init() { + PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); + + // SAFETY: + // This is only called on the main thread, and since it is still early + // in the programs lifetime there is (almost) certainly enough stack + // space left to install the guard page. + let mut guard_page_range = unsafe { install_main_guard() }; + + // Even for panic=immediate-abort, installing the guard pages is important for soundness. + // That said, we do not care about giving nice stackoverflow messages via our custom + // signal handler, just exit early and let the user enjoy the segfault. + if cfg!(panic = "immediate-abort") { + return; + } + + // SAFETY: C structures are always zero-initializable. + let mut action: sigaction = unsafe { mem::zeroed() }; + for &signal in &[SIGSEGV, SIGBUS] { + // SAFETY: just fetches the current signal handler into action + unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; + // We assume that overriding the signal handler is always safe, + // which might conflict with certain libraries that rely on a + // specific signal behaviour. To prevent problems, we only + // override the handler if it has not been set yet. + if action.sa_sigaction == SIG_DFL { + if !NEED_ALTSTACK.load(Ordering::Relaxed) { + // haven't set up our sigaltstack yet + NEED_ALTSTACK.store(true, Ordering::Release); + let handler = make_handler(true); + MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); + mem::forget(handler); + + if let Some(guard_page_range) = guard_page_range.take() { + set_current_info(guard_page_range); + } + } + + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + action.sa_sigaction = signal_handler + as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) + as sighandler_t; + // SAFETY: + // `&action` describes a valid `sigaction` and `signal_handler` + // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. + unsafe { sigaction(signal, &action, ptr::null_mut()) }; + } + } + } + + fn get_stack() -> libc::stack_t { + // OpenBSD requires this flag for stack mapping + // otherwise the said mapping will fail as a no-op on most systems + // and has a different meaning on FreeBSD + #[cfg(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + ))] + let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; + #[cfg(not(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + )))] + let flags = MAP_PRIVATE | MAP_ANON; + + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // SAFETY: this does not unmap any existing pages. + let stackp = unsafe { + mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) + }; + if stackp == MAP_FAILED { + panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); + } + // SAFETY: this only affects the memory we just allocated. + let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; + if guard_result != 0 { + panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); + } + // SAFETY: + // The region was allocated with a larger size than `page_size`, so this + // addition is within bounds. + let stackp = unsafe { stackp.add(page_size) }; + + libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } + } + + pub fn make_handler(main_thread: bool) -> Handler { + if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { + return Handler::null(); + } + + if !main_thread { + if let Some(guard_page_range) = current_guard() { + set_current_info(guard_page_range); + } + } + + // Load the current alternate signal stack to see if we need to install + // our own. + // + // SAFETY: C structures are always zero-initializable. + let mut stack = unsafe { mem::zeroed() }; + // SAFETY: `&mut stack` is valid for writing a `stack_t`. + unsafe { sigaltstack(ptr::null(), &mut stack) }; + + // Configure alternate signal stack, if one is not already set. + if stack.ss_flags & SS_DISABLE != 0 { + let stack = get_stack(); + // SAFETY: + // `stack_t` is a freshly allocated stack that's not used anywhere + // else. It contains a guard page, so stack overflows in signal + // handlers will not cause undefined behaviour. We must make the + // fundamental runtime assumption that it is safe to install an + // alternate signal stack if there is none currently installed. + // This might conflict with foreign libraries that use the existence + // of an alternate signal stack as indication that certain runtime + // initialisation by the library has been performed (e.g. old + // versions of `std` assumed that certain thread-locals were already + // accessed and thus initialized in the thread if the stack overflow + // signal was successfully delivered). Such assumptions in other + // libraries are fundamentally flawed, so we pay no regard to them. + unsafe { sigaltstack(&stack, ptr::null_mut()) }; + Handler { data: stack.ss_sp as *mut libc::c_void } + } else { + Handler::null() + } + } + + /// # Safety + /// Must only be called with a pointer returned by `make_handler`, and only + /// once per `Handler`. + pub unsafe fn drop_handler(data: *mut libc::c_void) { + if !data.is_null() { + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + let disabling_stack = libc::stack_t { + ss_sp: ptr::null_mut(), + ss_flags: SS_DISABLE, + // Workaround for bug in macOS implementation of sigaltstack + // UNIX2003 which returns ENOMEM when disabling a stack while + // passing ss_size smaller than MINSIGSTKSZ. According to POSIX + // both ss_sp and ss_size should be ignored in this case. + ss_size: sigstack_size, + }; + // SAFETY: + // We assume that disabling the alternate signal stack is always + // sound, even if the current alternate signal stack is not the one + // we installed in `make_handler`. Any stack overflows from this + // point on will abort the program when the kernel tries to write + // the signal information to the guard page. + // + // FIXME: detect if the stack has changed, and only uninstall if it hasn't. + unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; + // The stack returned by `get_stack` is part of a mapping that + // started one page earlier, so walk back a page and unmap from + // there. + // + // SAFETY: + // This allocation was created by us in `get_stack` and, as the + // alternate signal stack is now disabled, is no longer in use. + unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; + } + + delete_current_info(); + } + + /// Modern kernels on modern hardware can have dynamic signal stack sizes. + #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] + fn sigstack_size() -> usize { + // SAFETY: `getauxval` is always safe to call. + let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::SIGSTKSZ.max(dynamic_sigstksz as _) + } + + /// Not all OS support hardware where this is needed. + #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] + fn sigstack_size() -> usize { + libc::SIGSTKSZ + } + + #[cfg(any(target_os = "solaris", target_os = "illumos"))] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // The pointer is valid for writing a `stack_t`. + assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); + Some(current_stack.ss_sp) + } + + #[cfg(target_os = "macos")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: always safe to call. + let th = unsafe { libc::pthread_self() }; + // SAFETY: `th` is a valid `pthread_t`. + unsafe { + let stackptr = libc::pthread_get_stackaddr_np(th); + let stacksize = libc::pthread_get_stacksize_np(th); + Some(stackptr.map_addr(|addr| addr - stacksize)) + } + } + + #[cfg(target_os = "openbsd")] + fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t`. + // * `&mut current_stack` is coerced to a pointer that is valid for writing + // a `stack_t`. + assert_eq!( + unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, + 0 + ); + + let stack_ptr = current_stack.ss_sp; + // SAFETY: this is always safe to call. + let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { + // main thread + stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) + } else { + // new thread + stack_ptr.addr() - current_stack.ss_size + }; + Some(stack_ptr.with_addr(stackaddr)) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "hurd", + target_os = "linux", + target_os = "l4re" + ))] + fn get_stack_start() -> Option<*mut libc::c_void> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut stackaddr = crate::ptr::null_mut(); + let mut stacksize = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, + 0 + ); + ret = Some(stackaddr); + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } + + fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + + // Ensure stackaddr is page aligned! A parent process might + // have reset RLIMIT_STACK to be non-page aligned. The + // pthread_attr_getstack() reports the usable stack area + // stackaddr < stackaddr + stacksize, so if stackaddr is not + // page-aligned, calculate the fix such that stackaddr < + // new_page_aligned_stackaddr < stackaddr + stacksize + let remainder = stackaddr % page_size; + Some(if remainder == 0 { + stackptr + } else { + stackptr.with_addr(stackaddr + page_size - remainder) + }) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard() -> Option> { + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // this way someone on any unix-y OS can check that all these compile + if cfg!(all(target_os = "linux", not(target_env = "musl"))) { + install_main_guard_linux(page_size) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + install_main_guard_linux_musl(page_size) + } else if cfg!(target_os = "freebsd") { + #[cfg(not(target_os = "freebsd"))] + return None; + // The FreeBSD code cannot be checked on non-BSDs. + #[cfg(target_os = "freebsd")] + install_main_guard_freebsd(page_size) + } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { + install_main_guard_bsds(page_size) + } else { + // SAFETY: guaranteed by caller. + unsafe { install_main_guard_default(page_size) } + } + } + + fn install_main_guard_linux(page_size: usize) -> Option> { + // See the corresponding conditional in init(). + // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps + if cfg!(panic = "immediate-abort") { + return None; + } + // Linux doesn't allocate the whole stack right away, and + // the kernel has its own stack-guard mechanism to fault + // when growing too close to an existing mapping. If we map + // our own guard, then the kernel starts enforcing a rather + // large gap above that, rendering much of the possible + // stack space useless. See #43052. + // + // Instead, we'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + fn install_main_guard_linux_musl(_page_size: usize) -> Option> { + // For the main thread, the musl's pthread_attr_getstack + // returns the current stack size, rather than maximum size + // it can eventually grow to. It cannot be used to determine + // the position of kernel's stack guard. + None + } + + #[cfg(target_os = "freebsd")] + fn install_main_guard_freebsd(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // FreeBSD's stack autogrows, and optionally includes a guard page + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // the builtin guard page. + let stackptr = stack_start_aligned(page_size)?; + let guardaddr = stackptr.addr(); + // Technically the number of guard pages is tunable and controlled + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + // FIXME(joboet): this function is only called once, remove the caching. + static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); + + let pages = PAGES.get_or_init(|| { + let mut guard: usize = 0; + let mut size = size_of_val(&guard); + let oid = c"security.bsd.stack_guard_page"; + + let r = unsafe { + libc::sysctlbyname( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) + }; + if r == 0 { guard } else { 1 } + }); + Some(guardaddr..guardaddr + pages * page_size) + } + + fn install_main_guard_bsds(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; + } + // OpenBSD stack already includes a guard page, and stack is + // immutable. + // NetBSD stack includes the guard page. + // + // We'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) + } + + /// # Safety + /// This function must only be called from the main thread, and there must + /// be sufficient stack space remaining to place a stack guard. + unsafe fn install_main_guard_default(page_size: usize) -> Option> { + // Reallocate the last page of the stack. + // This ensures SIGBUS will be raised on + // stack overflow. + // Systems which enforce strict PAX MPROTECT do not allow + // to mprotect() a mapping with less restrictive permissions + // than the initial mmap() used, so we mmap() here with + // read/write permissions and only then mprotect() it to + // no permissions at all. See issue #50313. + let stackptr = stack_start_aligned(page_size)?; + // SAFETY: + // The memory region from `stackptr..stackptr + page_size` belongs to + // the current thread's stack, and the caller has asserted that there + // is sufficient stack space, which means that this will not overwrite + // any existing allocations. + let result = unsafe { + mmap64( + stackptr, + page_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + -1, + 0, + ) + }; + if result != stackptr || result == MAP_FAILED { + panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); + } + + // SAFETY: + // Since this function is only called on the main thread, the stack will + // not be reused until program exit, so the runtime will never observe + // that part of the stack has been made unusable in this way. + let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; + if result != 0 { + panic!("failed to protect the guard page: {}", io::Error::last_os_error()); + } + + let guardaddr = stackptr.addr(); + + Some(guardaddr..guardaddr + page_size) + } + + #[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ))] + fn current_guard() -> Option> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) + } + + #[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "hurd", + target_os = "linux", + target_os = "netbsd", + target_os = "l4re" + ))] + fn current_guard() -> Option> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); + + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut guardsize = 0; + // SAFETY: + // `attr` is an initialized attribute object and the pointer is valid + // for writing. + assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); + if guardsize == 0 { + if cfg!(all(target_os = "linux", target_env = "musl")) { + // musl versions before 1.1.19 always reported guard + // size obtained from pthread_attr_get_np as zero. + // Use page size as a fallback. + guardsize = PAGE_SIZE.load(Ordering::Relaxed); + } else { + panic!("there is no guard page"); + } + } + let mut stackptr = crate::ptr::null_mut::(); + let mut size = 0; + // SAFETY: + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!( + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, + 0 + ); + + let stackaddr = stackptr.addr(); + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) + { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) + } else { + Some(stackaddr..stackaddr + guardsize) + }; + } + if e == 0 || cfg!(target_os = "freebsd") { + // SAFETY: + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret + } +} + +// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses +// several symbols that might lead to rejections from the App Store, namely +// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. +// +// This might be overly cautious, though it is also what Swift does (and they +// usually have fewer qualms about forwards compatibility, since the runtime +// is shipped with the OS): +// +#[cfg(any( + miri, + not(any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + target_os = "cygwin", + )) +))] +mod imp { + pub unsafe fn init() {} + + pub fn make_handler(_main_thread: bool) -> super::Handler { + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} + +#[cfg(target_os = "cygwin")] +mod imp { + mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; + + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } + + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, + } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], + } + } + + /// Reserve stack space for use in stack overflow exceptions. + fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + } + + unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or(""); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + }); + } + c::EXCEPTION_CONTINUE_SEARCH + } + } + + pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); + } + // Set the thread stack guarantee for the main thread. + reserve_stack(); + } + + pub fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); + } + super::Handler::null() + } + + pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +} From 3a4c1c0e1196f64a3759bca77908979a4ee4cba7 Mon Sep 17 00:00:00 2001 From: Lucy Menon <168595099+syntactically@users.noreply.github.com> Date: Mon, 21 Sep 2026 19:08:35 +0100 Subject: [PATCH 0701/1309] Add Tier 3 targets for Hyperlight guests --- .../rustc_target/src/spec/base/hyperlight.rs | 19 +++++ compiler/rustc_target/src/spec/base/mod.rs | 1 + compiler/rustc_target/src/spec/mod.rs | 4 + .../targets/aarch64_unknown_hyperlight.rs | 31 ++++++++ .../spec/targets/x86_64_unknown_hyperlight.rs | 30 ++++++++ src/doc/rustc/src/SUMMARY.md | 1 + src/doc/rustc/src/platform-support.md | 2 + .../rustc/src/platform-support/hyperlight.md | 75 +++++++++++++++++++ src/librustdoc/clean/cfg.rs | 1 + .../src/completions/attribute/cfg.rs | 3 +- tests/assembly-llvm/targets/targets-elf.rs | 6 ++ tests/rustdoc-html/doc-cfg/all-targets.rs | 7 +- tests/ui/check-cfg/cfg-crate-features.stderr | 2 +- tests/ui/check-cfg/well-known-values.stderr | 4 +- 14 files changed, 179 insertions(+), 7 deletions(-) create mode 100644 compiler/rustc_target/src/spec/base/hyperlight.rs create mode 100644 compiler/rustc_target/src/spec/targets/aarch64_unknown_hyperlight.rs create mode 100644 compiler/rustc_target/src/spec/targets/x86_64_unknown_hyperlight.rs create mode 100644 src/doc/rustc/src/platform-support/hyperlight.md diff --git a/compiler/rustc_target/src/spec/base/hyperlight.rs b/compiler/rustc_target/src/spec/base/hyperlight.rs new file mode 100644 index 0000000000000..2865d3eaa35ad --- /dev/null +++ b/compiler/rustc_target/src/spec/base/hyperlight.rs @@ -0,0 +1,19 @@ +use crate::spec::{ + Cc, CodeModel, LinkerFlavor, Lld, Os, PanicStrategy, RelocModel, StackProbeType, TargetOptions, +}; + +pub(crate) fn opts() -> TargetOptions { + TargetOptions { + os: Os::Hyperlight, + linker_flavor: LinkerFlavor::Gnu(Cc::No, Lld::Yes), + linker: Some("rust-lld".into()), + disable_redzone: true, + panic_strategy: PanicStrategy::Abort, + stack_probes: StackProbeType::Inline, + code_model: Some(CodeModel::Small), + relocation_model: RelocModel::Pic, + position_independent_executables: true, + static_position_independent_executables: true, + ..Default::default() + } +} diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs index 13f364f3d8258..1fc2deed765f6 100644 --- a/compiler/rustc_target/src/spec/base/mod.rs +++ b/compiler/rustc_target/src/spec/base/mod.rs @@ -13,6 +13,7 @@ pub(crate) mod helenos; pub(crate) mod hermit; pub(crate) mod hurd; pub(crate) mod hurd_gnu; +pub(crate) mod hyperlight; pub(crate) mod illumos; pub(crate) mod l4re; pub(crate) mod linux; diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 42d817c7daa31..31bf200280eb7 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1695,6 +1695,9 @@ supported_targets! { ("i686-oe-linux-gnu", i686_oe_linux_gnu), ("riscv64-oe-linux-gnu", riscv64_oe_linux_gnu), ("x86_64-oe-linux-gnu", x86_64_oe_linux_gnu), + + ("aarch64-unknown-hyperlight", aarch64_unknown_hyperlight), + ("x86_64-unknown-hyperlight", x86_64_unknown_hyperlight), } /// Cow-Vec-Str: Cow<'static, [Cow<'static, str>]> @@ -1850,6 +1853,7 @@ crate::target_spec_enum! { Hermit = "hermit", Horizon = "horizon", Hurd = "hurd", + Hyperlight = "hyperlight", Illumos = "illumos", IOs = "ios", L4Re = "l4re", diff --git a/compiler/rustc_target/src/spec/targets/aarch64_unknown_hyperlight.rs b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hyperlight.rs new file mode 100644 index 0000000000000..651ae753cb59c --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/aarch64_unknown_hyperlight.rs @@ -0,0 +1,31 @@ +// Hyperlight Guest target for AArch64 + +use crate::spec::{Arch, SanitizerSet, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + features: "+v8.1a,+strict-align,+neon,+fp-armv8".into(), + direct_access_external_data: Some(true), + + supported_sanitizers: SanitizerSet::KCFI + | SanitizerSet::KERNELADDRESS + | SanitizerSet::KERNELHWADDRESS, + max_atomic_width: Some(128), + default_uwtable: true, + supports_xray: true, + ..base::hyperlight::opts() + }; + Target { + llvm_target: "aarch64-unknown-none".into(), + metadata: TargetMetadata { + description: Some("ARM64 Hyperlight guest".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: "e-m:e-p270:32:32-p271:32:32-p272:64:64-i8:8:32-i16:16:32-i64:64-i128:128-n32:64-S128-Fn32".into(), + arch: Arch::AArch64, + options: opts, + } +} diff --git a/compiler/rustc_target/src/spec/targets/x86_64_unknown_hyperlight.rs b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hyperlight.rs new file mode 100644 index 0000000000000..373b6995117b0 --- /dev/null +++ b/compiler/rustc_target/src/spec/targets/x86_64_unknown_hyperlight.rs @@ -0,0 +1,30 @@ +// Hyperlight Guest target for x86_64 + +use crate::spec::{Arch, RelroLevel, SanitizerSet, Target, TargetMetadata, TargetOptions, base}; + +pub(crate) fn target() -> Target { + let opts = TargetOptions { + features: "-mmx,+sse,+sse2,-sse3,-ssse3,-sse4.1,-sse4.2,-avx,-avx2,-soft-float".into(), + + cpu: "x86-64".into(), + plt_by_default: false, + max_atomic_width: Some(64), + relro_level: RelroLevel::Full, + supported_sanitizers: SanitizerSet::KCFI | SanitizerSet::KERNELADDRESS, + ..base::hyperlight::opts() + }; + Target { + llvm_target: "x86_64-unknown-none-elf".into(), + metadata: TargetMetadata { + description: Some("x86_64 Hyperlight guest".into()), + tier: Some(3), + host_tools: Some(false), + std: Some(false), + }, + pointer_width: 64, + data_layout: + "e-m:e-p270:32:32-p271:32:32-p272:64:64-i64:64-i128:128-f80:128-n8:16:32:64-S128".into(), + arch: Arch::X86_64, + options: opts, + } +} diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md index f15c712c32b91..1c2935ff264e0 100644 --- a/src/doc/rustc/src/SUMMARY.md +++ b/src/doc/rustc/src/SUMMARY.md @@ -133,6 +133,7 @@ - [\*-unikraft-linux-musl](platform-support/unikraft-linux-musl.md) - [\*-unknown-helenos](platform-support/helenos.md) - [\*-unknown-hermit](platform-support/hermit.md) + - [\*-unknown-hyperlight](platform-support/hyperlight.md) - [\*-unknown-freebsd](platform-support/freebsd.md) - [\*-unknown-managarm-mlibc](platform-support/managarm.md) - [\*-unknown-motor](platform-support/motor.md) diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md index c2a86d85dfcde..11a6ada2c4f89 100644 --- a/src/doc/rustc/src/platform-support.md +++ b/src/doc/rustc/src/platform-support.md @@ -273,6 +273,7 @@ target | std | host | notes [`aarch64-oe-linux-gnu`](platform-support/oe-linux-gnu.md) | ✓ | | ARM64 OpenEmbedded/Yocto Linux (GNU) [`aarch64-unknown-helenos`](platform-support/helenos.md) | ✓ | | ARM64 HelenOS [`aarch64-unknown-hermit`](platform-support/hermit.md) | ✓ | | ARM64 Hermit +[`aarch64-unknown-hyperlight`](platform-support/hyperlight.md) | * | | ARM64 Hyperlight [`aarch64-unknown-illumos`](platform-support/illumos.md) | ✓ | ✓ | ARM64 illumos [`aarch64-unknown-l4re-uclibc`](platform-support/l4re.md) | ✓ | | ARM64 L4Re with uclibc `aarch64-unknown-linux-gnu_ilp32` | ✓ | ✓ | ARM64 Linux (ILP32 ABI) @@ -461,6 +462,7 @@ target | std | host | notes `x86_64-unknown-haiku` | ✓ | ✓ | 64-bit Haiku [`x86_64-unknown-hermit`](platform-support/hermit.md) | ✓ | | x86_64 Hermit [`x86_64-unknown-helenos`](platform-support/helenos.md) | ✓ | | x86_64 (amd64) HelenOS +[`x86_64-unknown-hyperlight`](platform-support/hyperlight.md) | * | | x86_64 (amd64) Hyperlight [`x86_64-unknown-hurd-gnu`](platform-support/hurd.md) | ✓ | ✓ | 64-bit GNU/Hurd [`x86_64-unknown-l4re-uclibc`](platform-support/l4re.md) | ✓ | | x86_64 L4Re with uclibc [`x86_64-unknown-linux-none`](platform-support/x86_64-unknown-linux-none.md) | * | | 64-bit Linux with no libc diff --git a/src/doc/rustc/src/platform-support/hyperlight.md b/src/doc/rustc/src/platform-support/hyperlight.md new file mode 100644 index 0000000000000..be54a87e6a0fc --- /dev/null +++ b/src/doc/rustc/src/platform-support/hyperlight.md @@ -0,0 +1,75 @@ +# `*-unknown-hyperlight` + +**Tier: 3** + +These targets are used to build guest executables for the +[Hyperlight](https://github.com/hyperlight-dev/hyperlight) sandboxing +solution. + +## Target maintainers + +- [@syntactically](https://github.com/syntactically) +- [@yoshuawuyts](https://github.com/yoshuawuyts) + +## Requirements + +These targets can only be used for cross-compilation. They should not +require anything special as host tooling, but the usual way to use +them is via the +[cargo-hyperlight](https://github.com/hyperlight-dev/cargo-hyperlight) +tool. + +Hyperlight targets do not have any `std` support, but do fully support +`alloc`. + +These targets assume ARMv8.1-A (with Neon) on aarch64 and SSE2 on +x86_64, which are required by core Hyperlight libraries. The targets +are only expected to work with recent versions of Hyperlight. + +Hyperlight uses the official hardfloat calling convention of each +architecture for `extern "C"`. + +Hyperlight guest binaries use the ELF file format. + +## Building the target + +These targets can be built by adding them to the `target` list in +`bootstrap.toml`. + +```toml +[build] +build-stage = 1 +target = [ + "", + "-unknown-hyperlight", +] + +[target.-unknown-hyperlight] +no-std = true +``` + +## Building Rust programs + +Rust does not yet ship pre-compiled artifacts for this target. To +compile for this target, you will either need to build Rust with the +target enabled (see "Building the target" above), or build your own +copy of `core` by using `build-std` or similar. When using +`cargo-hyperlight`, the tool will manage this automatically. + +## Testing + +Binaries built for this target need to use the +[`hyperlight-guest-bin`](https://crates.io/crates/hyperlight-guest-bin) +crate. A given binary can then be loaded by a host process that uses +[`hyperlight-host`](https://crates.io/crates/hyperlight-host) and +agrees with it on a host/guest interface. For more details on the +programming model and how to write a host, see those crates and +documentation on the Hyperlight [website](https://hyperlight.org) and +in the [repository](https://github.com/hyperlight-dev/hyperlight). + +## Cross-compilation toolchains and C code + +This target does support C code through +[cargo-hyperlight](https://github.com/hyperlight-dev/cargo-hyperlight), +which supports wrapping an `-unknown-none` C toolchain into +something that can build targeting Hyperlight. diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index db63dbaa24663..a3384a5ee88cd 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -672,6 +672,7 @@ fn human_readable_target_os(os: Symbol) -> Option<&'static str> { Hermit => "Hermit", Horizon => "Horizon", Hurd => "GNU/Hurd", + Hyperlight => "Hyperlight", IOs => "iOS", Illumos => "illumos", L4Re => "L4Re", diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs index c314b3f37c04d..9c24ee1a5808b 100644 --- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs +++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/attribute/cfg.rs @@ -114,7 +114,7 @@ const KNOWN_ARCH: [&str; 20] = [ const KNOWN_ENV: [&str; 7] = ["eabihf", "gnu", "gnueabihf", "msvc", "relibc", "sgx", "uclibc"]; -const KNOWN_OS: [&str; 21] = [ +const KNOWN_OS: [&str; 22] = [ "cuda", "dragonfly", "emscripten", @@ -122,6 +122,7 @@ const KNOWN_OS: [&str; 21] = [ "fuchsia", "haiku", "hermit", + "hyperlight", "illumos", "l4re", "linux", diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 610a271d91144..971e9700035e5 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -43,6 +43,9 @@ //@ revisions: aarch64_unknown_hermit //@ [aarch64_unknown_hermit] compile-flags: --target aarch64-unknown-hermit //@ [aarch64_unknown_hermit] needs-llvm-components: aarch64 +//@ revisions: aarch64_unknown_hyperlight +//@ [aarch64_unknown_hyperlight] compile-flags: --target aarch64-unknown-hyperlight +//@ [aarch64_unknown_hyperlight] needs-llvm-components: aarch64 //@ revisions: aarch64_unknown_illumos //@ [aarch64_unknown_illumos] compile-flags: --target aarch64-unknown-illumos //@ [aarch64_unknown_illumos] needs-llvm-components: aarch64 @@ -724,6 +727,9 @@ //@ revisions: x86_64_unknown_hermit //@ [x86_64_unknown_hermit] compile-flags: --target x86_64-unknown-hermit //@ [x86_64_unknown_hermit] needs-llvm-components: x86 +//@ revisions: x86_64_unknown_hyperlight +//@ [x86_64_unknown_hyperlight] compile-flags: --target x86_64-unknown-hyperlight +//@ [x86_64_unknown_hyperlight] needs-llvm-components: x86 //@ revisions: x86_64_unknown_illumos //@ [x86_64_unknown_illumos] compile-flags: --target x86_64-unknown-illumos //@ [x86_64_unknown_illumos] needs-llvm-components: x86 diff --git a/tests/rustdoc-html/doc-cfg/all-targets.rs b/tests/rustdoc-html/doc-cfg/all-targets.rs index aec251878781e..421dfe4dcd793 100644 --- a/tests/rustdoc-html/doc-cfg/all-targets.rs +++ b/tests/rustdoc-html/doc-cfg/all-targets.rs @@ -77,9 +77,9 @@ pub fn bar() {} // 'Available on target_os=fake_os and target_os=unknown and AIX and AMD HSA \ // and Android and bare-metal and CUDA and Cygwin and DragonFly BSD and \ // Emscripten and ESP-IDF and FreeBSD and Fuchsia and GNU/Hurd and Haiku \ -// and HelenOS and Hermit and Horizon and illumos and iOS and L4Re and Linux \ -// and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and NuttX \ -// and OpenBSD and Play Station 1 and Play Station 3 and Play Station Portable \ +// and HelenOS and Hermit and Horizon and Hyperlight and illumos and iOS and L4Re \ +// and Linux and LynxOS-178 and macOS and Managarm and Motor OS and NetBSD and \ +// NuttX and OpenBSD and Play Station 1 and Play Station 3 and Play Station Portable \ // and Play Station Vita and QNX SDP 7.x and QNX SDP 8.0+ and QuRT and Redox OS \ // and RTEMS OS and Solaris and SOLID ASP3 and TEEOS and Trusty and tvOS and UEFI \ // and VEXos and visionOS and VxWorks and WASI and watchOS and Windows and Xous \ @@ -100,6 +100,7 @@ pub fn bar() {} target_os = "hermit", target_os = "horizon", target_os = "hurd", + target_os = "hyperlight", target_os = "illumos", target_os = "ios", target_os = "l4re", diff --git a/tests/ui/check-cfg/cfg-crate-features.stderr b/tests/ui/check-cfg/cfg-crate-features.stderr index d65562313cb42..6bc375e0383aa 100644 --- a/tests/ui/check-cfg/cfg-crate-features.stderr +++ b/tests/ui/check-cfg/cfg-crate-features.stderr @@ -24,7 +24,7 @@ warning: unexpected `cfg` condition value: `does_not_exist` LL | #![cfg(not(target(os = "does_not_exist")))] | ^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, and `rtems` and 16 more + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `hyperlight`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, and `redox` and 17 more = note: see for more information about checking conditional configuration = note: `#[warn(unexpected_cfgs)]` on by default diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 5ccaf1e9aa698..a99f230c6f911 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -232,7 +232,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_os = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `hyperlight`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` @@ -305,7 +305,7 @@ LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux` | | | help: there is a expected value with a similar name: `"linux"` | - = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` + = note: expected values for `target_os` are: `aix`, `amdhsa`, `android`, `cuda`, `cygwin`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `helenos`, `hermit`, `horizon`, `hurd`, `hyperlight`, `illumos`, `ios`, `l4re`, `linux`, `lynxos178`, `macos`, `managarm`, `motor`, `netbsd`, `none`, `nto`, `nuttx`, `openbsd`, `ps3`, `psp`, `psx`, `qnx`, `qurt`, `redox`, `rtems`, `solaris`, `solid_asp3`, `teeos`, `trusty`, `tvos`, `uefi`, `unknown`, `vexos`, `visionos`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`, and `zkvm` = note: see for more information about checking conditional configuration warning: 31 warnings emitted From 86d18b46ef59a67b514ef59aa80a0705dadb96c0 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 23 Sep 2026 13:46:57 +0200 Subject: [PATCH 0702/1309] std: split stack overflow module (delete) --- .../pal/unix/stack_overflow/handler_cygwin.rs | 763 ---------------- .../pal/unix/stack_overflow/handler_none.rs | 837 ------------------ .../pal/unix/stack_overflow/handler_signal.rs | 178 ---- .../src/sys/pal/unix/stack_overflow/mod.rs | 754 ---------------- 4 files changed, 2532 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs index 5604e3e6dbf42..089bd2c95073d 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs @@ -1,765 +1,3 @@ -#![cfg_attr(test, allow(dead_code))] -#![forbid(unsafe_op_in_unsafe_fn)] - -pub use self::imp::init; -use self::imp::{drop_handler, make_handler}; - -pub struct Handler { - data: *mut libc::c_void, -} - -impl Handler { - pub unsafe fn new() -> Handler { - make_handler(false) - } - - fn null() -> Handler { - Handler { data: crate::ptr::null_mut() } - } -} - -impl Drop for Handler { - fn drop(&mut self) { - unsafe { - drop_handler(self.data); - } - } -} - -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ), -))] -mod thread_info; - -// miri doesn't model signals nor stack overflows and this code has some -// synchronization properties that we don't want to expose to user code, -// hence we disable it on miri. -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ) -))] -mod imp { - use libc::{ - MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, - SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, - }; - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::{mmap as mmap64, mprotect, munmap}; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::{mmap64, mprotect, munmap}; - - use super::Handler; - use super::thread_info::{delete_current_info, set_current_info, with_current_info}; - use crate::ops::Range; - use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; - use crate::sys::pal::unix::conf; - use crate::{io, mem, ptr}; - - /// Signal handler for the SIGSEGV and SIGBUS handlers. - /// - /// We've got guard pages (unmapped pages) at the end of every thread's - /// stack, so if a thread ends up running into the guard page it'll trigger - /// this handler. We want to detect these cases and print out a helpful error - /// saying that the stack has overflowed. All other signals, however, should - /// go back to what they were originally supposed to do. - /// - /// This handler currently exists purely to print an informative message - /// whenever a thread overflows its stack. We then abort to exit and - /// indicate a crash, but to avoid a misleading SIGSEGV that might lead - /// users to believe that unsafe code has accessed an invalid pointer; the - /// SIGSEGV encountered when overflowing the stack is expected and - /// well-defined. - /// - /// If this is not a stack overflow, the handler un-registers itself and - /// then returns (to allow the original signal to be delivered again). - /// Returning from this kind of signal handler is technically not defined - /// to work when reading the POSIX spec strictly, but in practice it turns - /// out many large systems and all implementations allow returning from a - /// signal handler to work. For a more detailed explanation see the - /// comments on #26458. - /// - /// # Safety - /// Rust doesn't call this, it *gets called* by the kernel, which we expect - /// to provide valid parameters. Apart from that, this function does not - /// have any other preconditions. - unsafe extern "C" fn signal_handler( - signum: libc::c_int, - info: *mut libc::siginfo_t, - _data: *mut libc::c_void, - ) { - // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. - let fault_addr = unsafe { (*info).si_addr().addr() }; - - // `with_current_info` expects that the process aborts after it is - // called. If the signal was not caused by a memory access, this might - // not be true. We detect this by noticing that the `si_addr` field is - // zero if the signal is synthetic. - if fault_addr != 0 { - with_current_info(|thread_info| { - // If the faulting address is within the guard page, then we print a - // message saying so and abort. - if let Some(thread_info) = thread_info - && thread_info.guard_page_range.contains(&fault_addr) - { - // Hey you! Yes, you modifying the stack overflow message! - // Please make sure that all functions called here are - // actually async-signal-safe. If they're not, try retrieving - // the information beforehand and storing it in `ThreadInfo`. - // Thank you! - // - says Jonas after having had to watch his carefully - // written code get made unsound again. - let tid = thread_info.tid; - let name = thread_info.name.as_deref().unwrap_or(""); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - rtabort!("stack overflow"); - } - }) - } - - // Unregister ourselves by reverting back to the default behavior. - // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" - let mut action: sigaction = unsafe { mem::zeroed() }; - action.sa_sigaction = SIG_DFL; - // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction - unsafe { sigaction(signum, &action, ptr::null_mut()) }; - - // See comment above for why this function returns. - } - - static PAGE_SIZE: Atomic = AtomicUsize::new(0); - // Store a pointer to the allocation for the main thread's altstack so that - // tools like valgrind don't complain about a leaked unreachable allocation. - // - // If the main thread exits, the process will terminate so there's no use in - // freeing resources. It also means that the altstack is still installed - // while TLS destructors are run on the main thread (c.f. #111272). - static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); - static NEED_ALTSTACK: Atomic = AtomicBool::new(false); - - /// # Safety - /// Must be called only once, on the main thread, during program startup. - pub unsafe fn init() { - PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); - - // SAFETY: - // This is only called on the main thread, and since it is still early - // in the programs lifetime there is (almost) certainly enough stack - // space left to install the guard page. - let mut guard_page_range = unsafe { install_main_guard() }; - - // Even for panic=immediate-abort, installing the guard pages is important for soundness. - // That said, we do not care about giving nice stackoverflow messages via our custom - // signal handler, just exit early and let the user enjoy the segfault. - if cfg!(panic = "immediate-abort") { - return; - } - - // SAFETY: C structures are always zero-initializable. - let mut action: sigaction = unsafe { mem::zeroed() }; - for &signal in &[SIGSEGV, SIGBUS] { - // SAFETY: just fetches the current signal handler into action - unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; - // We assume that overriding the signal handler is always safe, - // which might conflict with certain libraries that rely on a - // specific signal behaviour. To prevent problems, we only - // override the handler if it has not been set yet. - if action.sa_sigaction == SIG_DFL { - if !NEED_ALTSTACK.load(Ordering::Relaxed) { - // haven't set up our sigaltstack yet - NEED_ALTSTACK.store(true, Ordering::Release); - let handler = make_handler(true); - MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); - mem::forget(handler); - - if let Some(guard_page_range) = guard_page_range.take() { - set_current_info(guard_page_range); - } - } - - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler - as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) - as sighandler_t; - // SAFETY: - // `&action` describes a valid `sigaction` and `signal_handler` - // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. - unsafe { sigaction(signal, &action, ptr::null_mut()) }; - } - } - } - - fn get_stack() -> libc::stack_t { - // OpenBSD requires this flag for stack mapping - // otherwise the said mapping will fail as a no-op on most systems - // and has a different meaning on FreeBSD - #[cfg(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - ))] - let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; - #[cfg(not(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - )))] - let flags = MAP_PRIVATE | MAP_ANON; - - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // SAFETY: this does not unmap any existing pages. - let stackp = unsafe { - mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) - }; - if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); - } - // SAFETY: this only affects the memory we just allocated. - let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; - if guard_result != 0 { - panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); - } - // SAFETY: - // The region was allocated with a larger size than `page_size`, so this - // addition is within bounds. - let stackp = unsafe { stackp.add(page_size) }; - - libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } - } - - pub fn make_handler(main_thread: bool) -> Handler { - if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { - return Handler::null(); - } - - if !main_thread { - if let Some(guard_page_range) = current_guard() { - set_current_info(guard_page_range); - } - } - - // Load the current alternate signal stack to see if we need to install - // our own. - // - // SAFETY: C structures are always zero-initializable. - let mut stack = unsafe { mem::zeroed() }; - // SAFETY: `&mut stack` is valid for writing a `stack_t`. - unsafe { sigaltstack(ptr::null(), &mut stack) }; - - // Configure alternate signal stack, if one is not already set. - if stack.ss_flags & SS_DISABLE != 0 { - let stack = get_stack(); - // SAFETY: - // `stack_t` is a freshly allocated stack that's not used anywhere - // else. It contains a guard page, so stack overflows in signal - // handlers will not cause undefined behaviour. We must make the - // fundamental runtime assumption that it is safe to install an - // alternate signal stack if there is none currently installed. - // This might conflict with foreign libraries that use the existence - // of an alternate signal stack as indication that certain runtime - // initialisation by the library has been performed (e.g. old - // versions of `std` assumed that certain thread-locals were already - // accessed and thus initialized in the thread if the stack overflow - // signal was successfully delivered). Such assumptions in other - // libraries are fundamentally flawed, so we pay no regard to them. - unsafe { sigaltstack(&stack, ptr::null_mut()) }; - Handler { data: stack.ss_sp as *mut libc::c_void } - } else { - Handler::null() - } - } - - /// # Safety - /// Must only be called with a pointer returned by `make_handler`, and only - /// once per `Handler`. - pub unsafe fn drop_handler(data: *mut libc::c_void) { - if !data.is_null() { - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - let disabling_stack = libc::stack_t { - ss_sp: ptr::null_mut(), - ss_flags: SS_DISABLE, - // Workaround for bug in macOS implementation of sigaltstack - // UNIX2003 which returns ENOMEM when disabling a stack while - // passing ss_size smaller than MINSIGSTKSZ. According to POSIX - // both ss_sp and ss_size should be ignored in this case. - ss_size: sigstack_size, - }; - // SAFETY: - // We assume that disabling the alternate signal stack is always - // sound, even if the current alternate signal stack is not the one - // we installed in `make_handler`. Any stack overflows from this - // point on will abort the program when the kernel tries to write - // the signal information to the guard page. - // - // FIXME: detect if the stack has changed, and only uninstall if it hasn't. - unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; - // The stack returned by `get_stack` is part of a mapping that - // started one page earlier, so walk back a page and unmap from - // there. - // - // SAFETY: - // This allocation was created by us in `get_stack` and, as the - // alternate signal stack is now disabled, is no longer in use. - unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; - } - - delete_current_info(); - } - - /// Modern kernels on modern hardware can have dynamic signal stack sizes. - #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] - fn sigstack_size() -> usize { - // SAFETY: `getauxval` is always safe to call. - let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; - // If getauxval couldn't find the entry, it returns 0, - // so take the higher of the "constant" and auxval. - // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ - libc::SIGSTKSZ.max(dynamic_sigstksz as _) - } - - /// Not all OS support hardware where this is needed. - #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] - fn sigstack_size() -> usize { - libc::SIGSTKSZ - } - - #[cfg(any(target_os = "solaris", target_os = "illumos"))] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // The pointer is valid for writing a `stack_t`. - assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); - Some(current_stack.ss_sp) - } - - #[cfg(target_os = "macos")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: always safe to call. - let th = unsafe { libc::pthread_self() }; - // SAFETY: `th` is a valid `pthread_t`. - unsafe { - let stackptr = libc::pthread_get_stackaddr_np(th); - let stacksize = libc::pthread_get_stacksize_np(th); - Some(stackptr.map_addr(|addr| addr - stacksize)) - } - } - - #[cfg(target_os = "openbsd")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t`. - // * `&mut current_stack` is coerced to a pointer that is valid for writing - // a `stack_t`. - assert_eq!( - unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, - 0 - ); - - let stack_ptr = current_stack.ss_sp; - // SAFETY: this is always safe to call. - let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { - // main thread - stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) - } else { - // new thread - stack_ptr.addr() - current_stack.ss_size - }; - Some(stack_ptr.with_addr(stackaddr)) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - target_os = "hurd", - target_os = "linux", - target_os = "l4re" - ))] - fn get_stack_start() -> Option<*mut libc::c_void> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut stackaddr = crate::ptr::null_mut(); - let mut stacksize = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, - 0 - ); - ret = Some(stackaddr); - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } - - fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - - // Ensure stackaddr is page aligned! A parent process might - // have reset RLIMIT_STACK to be non-page aligned. The - // pthread_attr_getstack() reports the usable stack area - // stackaddr < stackaddr + stacksize, so if stackaddr is not - // page-aligned, calculate the fix such that stackaddr < - // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = stackaddr % page_size; - Some(if remainder == 0 { - stackptr - } else { - stackptr.with_addr(stackaddr + page_size - remainder) - }) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard() -> Option> { - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // this way someone on any unix-y OS can check that all these compile - if cfg!(all(target_os = "linux", not(target_env = "musl"))) { - install_main_guard_linux(page_size) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - install_main_guard_linux_musl(page_size) - } else if cfg!(target_os = "freebsd") { - #[cfg(not(target_os = "freebsd"))] - return None; - // The FreeBSD code cannot be checked on non-BSDs. - #[cfg(target_os = "freebsd")] - install_main_guard_freebsd(page_size) - } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { - install_main_guard_bsds(page_size) - } else { - // SAFETY: guaranteed by caller. - unsafe { install_main_guard_default(page_size) } - } - } - - fn install_main_guard_linux(page_size: usize) -> Option> { - // See the corresponding conditional in init(). - // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps - if cfg!(panic = "immediate-abort") { - return None; - } - // Linux doesn't allocate the whole stack right away, and - // the kernel has its own stack-guard mechanism to fault - // when growing too close to an existing mapping. If we map - // our own guard, then the kernel starts enforcing a rather - // large gap above that, rendering much of the possible - // stack space useless. See #43052. - // - // Instead, we'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - fn install_main_guard_linux_musl(_page_size: usize) -> Option> { - // For the main thread, the musl's pthread_attr_getstack - // returns the current stack size, rather than maximum size - // it can eventually grow to. It cannot be used to determine - // the position of kernel's stack guard. - None - } - - #[cfg(target_os = "freebsd")] - fn install_main_guard_freebsd(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // FreeBSD's stack autogrows, and optionally includes a guard page - // at the bottom. If we try to remap the bottom of the stack - // ourselves, FreeBSD's guard page moves upwards. So we'll just use - // the builtin guard page. - let stackptr = stack_start_aligned(page_size)?; - let guardaddr = stackptr.addr(); - // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl. - // By default it is 1, checking once is enough since it is - // a boot time config value. - // FIXME(joboet): this function is only called once, remove the caching. - static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); - - let pages = PAGES.get_or_init(|| { - let mut guard: usize = 0; - let mut size = size_of_val(&guard); - let oid = c"security.bsd.stack_guard_page"; - - let r = unsafe { - libc::sysctlbyname( - oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0, - ) - }; - if r == 0 { guard } else { 1 } - }); - Some(guardaddr..guardaddr + pages * page_size) - } - - fn install_main_guard_bsds(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // OpenBSD stack already includes a guard page, and stack is - // immutable. - // NetBSD stack includes the guard page. - // - // We'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard_default(page_size: usize) -> Option> { - // Reallocate the last page of the stack. - // This ensures SIGBUS will be raised on - // stack overflow. - // Systems which enforce strict PAX MPROTECT do not allow - // to mprotect() a mapping with less restrictive permissions - // than the initial mmap() used, so we mmap() here with - // read/write permissions and only then mprotect() it to - // no permissions at all. See issue #50313. - let stackptr = stack_start_aligned(page_size)?; - // SAFETY: - // The memory region from `stackptr..stackptr + page_size` belongs to - // the current thread's stack, and the caller has asserted that there - // is sufficient stack space, which means that this will not overwrite - // any existing allocations. - let result = unsafe { - mmap64( - stackptr, - page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - -1, - 0, - ) - }; - if result != stackptr || result == MAP_FAILED { - panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); - } - - // SAFETY: - // Since this function is only called on the main thread, the stack will - // not be reused until program exit, so the runtime will never observe - // that part of the stack has been made unusable in this way. - let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; - if result != 0 { - panic!("failed to protect the guard page: {}", io::Error::last_os_error()); - } - - let guardaddr = stackptr.addr(); - - Some(guardaddr..guardaddr + page_size) - } - - #[cfg(any( - target_os = "macos", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ))] - fn current_guard() -> Option> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "hurd", - target_os = "linux", - target_os = "netbsd", - target_os = "l4re" - ))] - fn current_guard() -> Option> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut guardsize = 0; - // SAFETY: - // `attr` is an initialized attribute object and the pointer is valid - // for writing. - assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); - if guardsize == 0 { - if cfg!(all(target_os = "linux", target_env = "musl")) { - // musl versions before 1.1.19 always reported guard - // size obtained from pthread_attr_get_np as zero. - // Use page size as a fallback. - guardsize = PAGE_SIZE.load(Ordering::Relaxed); - } else { - panic!("there is no guard page"); - } - } - let mut stackptr = crate::ptr::null_mut::(); - let mut size = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, - 0 - ); - - let stackaddr = stackptr.addr(); - ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) - { - // glibc used to include the guard area within the stack, as noted in the BUGS - // section of `man pthread_attr_getguardsize`. This has been corrected starting - // with glibc 2.27, and in some distro backports, so the guard is now placed at the - // end (below) the stack. There's no easy way for us to know which we have at - // runtime, so we'll just match any fault in the range right above or below the - // stack base to call that fault a stack overflow. - Some(stackaddr - guardsize..stackaddr + guardsize) - } else { - Some(stackaddr..stackaddr + guardsize) - }; - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } -} - -// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses -// several symbols that might lead to rejections from the App Store, namely -// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. -// -// This might be overly cautious, though it is also what Swift does (and they -// usually have fewer qualms about forwards compatibility, since the runtime -// is shipped with the OS): -// -#[cfg(any( - miri, - not(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - target_os = "cygwin", - )) -))] -mod imp { - pub unsafe fn init() {} - - pub fn make_handler(_main_thread: bool) -> super::Handler { - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} - -#[cfg(target_os = "cygwin")] -mod imp { mod c { pub type PVECTORED_EXCEPTION_HANDLER = Option i32>; @@ -841,4 +79,3 @@ mod imp { } pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs index 5604e3e6dbf42..f765090ffff7d 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs @@ -1,754 +1,3 @@ -#![cfg_attr(test, allow(dead_code))] -#![forbid(unsafe_op_in_unsafe_fn)] - -pub use self::imp::init; -use self::imp::{drop_handler, make_handler}; - -pub struct Handler { - data: *mut libc::c_void, -} - -impl Handler { - pub unsafe fn new() -> Handler { - make_handler(false) - } - - fn null() -> Handler { - Handler { data: crate::ptr::null_mut() } - } -} - -impl Drop for Handler { - fn drop(&mut self) { - unsafe { - drop_handler(self.data); - } - } -} - -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ), -))] -mod thread_info; - -// miri doesn't model signals nor stack overflows and this code has some -// synchronization properties that we don't want to expose to user code, -// hence we disable it on miri. -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ) -))] -mod imp { - use libc::{ - MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, - SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, - }; - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::{mmap as mmap64, mprotect, munmap}; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::{mmap64, mprotect, munmap}; - - use super::Handler; - use super::thread_info::{delete_current_info, set_current_info, with_current_info}; - use crate::ops::Range; - use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; - use crate::sys::pal::unix::conf; - use crate::{io, mem, ptr}; - - /// Signal handler for the SIGSEGV and SIGBUS handlers. - /// - /// We've got guard pages (unmapped pages) at the end of every thread's - /// stack, so if a thread ends up running into the guard page it'll trigger - /// this handler. We want to detect these cases and print out a helpful error - /// saying that the stack has overflowed. All other signals, however, should - /// go back to what they were originally supposed to do. - /// - /// This handler currently exists purely to print an informative message - /// whenever a thread overflows its stack. We then abort to exit and - /// indicate a crash, but to avoid a misleading SIGSEGV that might lead - /// users to believe that unsafe code has accessed an invalid pointer; the - /// SIGSEGV encountered when overflowing the stack is expected and - /// well-defined. - /// - /// If this is not a stack overflow, the handler un-registers itself and - /// then returns (to allow the original signal to be delivered again). - /// Returning from this kind of signal handler is technically not defined - /// to work when reading the POSIX spec strictly, but in practice it turns - /// out many large systems and all implementations allow returning from a - /// signal handler to work. For a more detailed explanation see the - /// comments on #26458. - /// - /// # Safety - /// Rust doesn't call this, it *gets called* by the kernel, which we expect - /// to provide valid parameters. Apart from that, this function does not - /// have any other preconditions. - unsafe extern "C" fn signal_handler( - signum: libc::c_int, - info: *mut libc::siginfo_t, - _data: *mut libc::c_void, - ) { - // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. - let fault_addr = unsafe { (*info).si_addr().addr() }; - - // `with_current_info` expects that the process aborts after it is - // called. If the signal was not caused by a memory access, this might - // not be true. We detect this by noticing that the `si_addr` field is - // zero if the signal is synthetic. - if fault_addr != 0 { - with_current_info(|thread_info| { - // If the faulting address is within the guard page, then we print a - // message saying so and abort. - if let Some(thread_info) = thread_info - && thread_info.guard_page_range.contains(&fault_addr) - { - // Hey you! Yes, you modifying the stack overflow message! - // Please make sure that all functions called here are - // actually async-signal-safe. If they're not, try retrieving - // the information beforehand and storing it in `ThreadInfo`. - // Thank you! - // - says Jonas after having had to watch his carefully - // written code get made unsound again. - let tid = thread_info.tid; - let name = thread_info.name.as_deref().unwrap_or(""); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - rtabort!("stack overflow"); - } - }) - } - - // Unregister ourselves by reverting back to the default behavior. - // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" - let mut action: sigaction = unsafe { mem::zeroed() }; - action.sa_sigaction = SIG_DFL; - // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction - unsafe { sigaction(signum, &action, ptr::null_mut()) }; - - // See comment above for why this function returns. - } - - static PAGE_SIZE: Atomic = AtomicUsize::new(0); - // Store a pointer to the allocation for the main thread's altstack so that - // tools like valgrind don't complain about a leaked unreachable allocation. - // - // If the main thread exits, the process will terminate so there's no use in - // freeing resources. It also means that the altstack is still installed - // while TLS destructors are run on the main thread (c.f. #111272). - static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); - static NEED_ALTSTACK: Atomic = AtomicBool::new(false); - - /// # Safety - /// Must be called only once, on the main thread, during program startup. - pub unsafe fn init() { - PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); - - // SAFETY: - // This is only called on the main thread, and since it is still early - // in the programs lifetime there is (almost) certainly enough stack - // space left to install the guard page. - let mut guard_page_range = unsafe { install_main_guard() }; - - // Even for panic=immediate-abort, installing the guard pages is important for soundness. - // That said, we do not care about giving nice stackoverflow messages via our custom - // signal handler, just exit early and let the user enjoy the segfault. - if cfg!(panic = "immediate-abort") { - return; - } - - // SAFETY: C structures are always zero-initializable. - let mut action: sigaction = unsafe { mem::zeroed() }; - for &signal in &[SIGSEGV, SIGBUS] { - // SAFETY: just fetches the current signal handler into action - unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; - // We assume that overriding the signal handler is always safe, - // which might conflict with certain libraries that rely on a - // specific signal behaviour. To prevent problems, we only - // override the handler if it has not been set yet. - if action.sa_sigaction == SIG_DFL { - if !NEED_ALTSTACK.load(Ordering::Relaxed) { - // haven't set up our sigaltstack yet - NEED_ALTSTACK.store(true, Ordering::Release); - let handler = make_handler(true); - MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); - mem::forget(handler); - - if let Some(guard_page_range) = guard_page_range.take() { - set_current_info(guard_page_range); - } - } - - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler - as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) - as sighandler_t; - // SAFETY: - // `&action` describes a valid `sigaction` and `signal_handler` - // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. - unsafe { sigaction(signal, &action, ptr::null_mut()) }; - } - } - } - - fn get_stack() -> libc::stack_t { - // OpenBSD requires this flag for stack mapping - // otherwise the said mapping will fail as a no-op on most systems - // and has a different meaning on FreeBSD - #[cfg(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - ))] - let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; - #[cfg(not(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - )))] - let flags = MAP_PRIVATE | MAP_ANON; - - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // SAFETY: this does not unmap any existing pages. - let stackp = unsafe { - mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) - }; - if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); - } - // SAFETY: this only affects the memory we just allocated. - let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; - if guard_result != 0 { - panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); - } - // SAFETY: - // The region was allocated with a larger size than `page_size`, so this - // addition is within bounds. - let stackp = unsafe { stackp.add(page_size) }; - - libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } - } - - pub fn make_handler(main_thread: bool) -> Handler { - if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { - return Handler::null(); - } - - if !main_thread { - if let Some(guard_page_range) = current_guard() { - set_current_info(guard_page_range); - } - } - - // Load the current alternate signal stack to see if we need to install - // our own. - // - // SAFETY: C structures are always zero-initializable. - let mut stack = unsafe { mem::zeroed() }; - // SAFETY: `&mut stack` is valid for writing a `stack_t`. - unsafe { sigaltstack(ptr::null(), &mut stack) }; - - // Configure alternate signal stack, if one is not already set. - if stack.ss_flags & SS_DISABLE != 0 { - let stack = get_stack(); - // SAFETY: - // `stack_t` is a freshly allocated stack that's not used anywhere - // else. It contains a guard page, so stack overflows in signal - // handlers will not cause undefined behaviour. We must make the - // fundamental runtime assumption that it is safe to install an - // alternate signal stack if there is none currently installed. - // This might conflict with foreign libraries that use the existence - // of an alternate signal stack as indication that certain runtime - // initialisation by the library has been performed (e.g. old - // versions of `std` assumed that certain thread-locals were already - // accessed and thus initialized in the thread if the stack overflow - // signal was successfully delivered). Such assumptions in other - // libraries are fundamentally flawed, so we pay no regard to them. - unsafe { sigaltstack(&stack, ptr::null_mut()) }; - Handler { data: stack.ss_sp as *mut libc::c_void } - } else { - Handler::null() - } - } - - /// # Safety - /// Must only be called with a pointer returned by `make_handler`, and only - /// once per `Handler`. - pub unsafe fn drop_handler(data: *mut libc::c_void) { - if !data.is_null() { - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - let disabling_stack = libc::stack_t { - ss_sp: ptr::null_mut(), - ss_flags: SS_DISABLE, - // Workaround for bug in macOS implementation of sigaltstack - // UNIX2003 which returns ENOMEM when disabling a stack while - // passing ss_size smaller than MINSIGSTKSZ. According to POSIX - // both ss_sp and ss_size should be ignored in this case. - ss_size: sigstack_size, - }; - // SAFETY: - // We assume that disabling the alternate signal stack is always - // sound, even if the current alternate signal stack is not the one - // we installed in `make_handler`. Any stack overflows from this - // point on will abort the program when the kernel tries to write - // the signal information to the guard page. - // - // FIXME: detect if the stack has changed, and only uninstall if it hasn't. - unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; - // The stack returned by `get_stack` is part of a mapping that - // started one page earlier, so walk back a page and unmap from - // there. - // - // SAFETY: - // This allocation was created by us in `get_stack` and, as the - // alternate signal stack is now disabled, is no longer in use. - unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; - } - - delete_current_info(); - } - - /// Modern kernels on modern hardware can have dynamic signal stack sizes. - #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] - fn sigstack_size() -> usize { - // SAFETY: `getauxval` is always safe to call. - let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; - // If getauxval couldn't find the entry, it returns 0, - // so take the higher of the "constant" and auxval. - // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ - libc::SIGSTKSZ.max(dynamic_sigstksz as _) - } - - /// Not all OS support hardware where this is needed. - #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] - fn sigstack_size() -> usize { - libc::SIGSTKSZ - } - - #[cfg(any(target_os = "solaris", target_os = "illumos"))] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // The pointer is valid for writing a `stack_t`. - assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); - Some(current_stack.ss_sp) - } - - #[cfg(target_os = "macos")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: always safe to call. - let th = unsafe { libc::pthread_self() }; - // SAFETY: `th` is a valid `pthread_t`. - unsafe { - let stackptr = libc::pthread_get_stackaddr_np(th); - let stacksize = libc::pthread_get_stacksize_np(th); - Some(stackptr.map_addr(|addr| addr - stacksize)) - } - } - - #[cfg(target_os = "openbsd")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t`. - // * `&mut current_stack` is coerced to a pointer that is valid for writing - // a `stack_t`. - assert_eq!( - unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, - 0 - ); - - let stack_ptr = current_stack.ss_sp; - // SAFETY: this is always safe to call. - let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { - // main thread - stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) - } else { - // new thread - stack_ptr.addr() - current_stack.ss_size - }; - Some(stack_ptr.with_addr(stackaddr)) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - target_os = "hurd", - target_os = "linux", - target_os = "l4re" - ))] - fn get_stack_start() -> Option<*mut libc::c_void> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut stackaddr = crate::ptr::null_mut(); - let mut stacksize = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, - 0 - ); - ret = Some(stackaddr); - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } - - fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - - // Ensure stackaddr is page aligned! A parent process might - // have reset RLIMIT_STACK to be non-page aligned. The - // pthread_attr_getstack() reports the usable stack area - // stackaddr < stackaddr + stacksize, so if stackaddr is not - // page-aligned, calculate the fix such that stackaddr < - // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = stackaddr % page_size; - Some(if remainder == 0 { - stackptr - } else { - stackptr.with_addr(stackaddr + page_size - remainder) - }) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard() -> Option> { - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // this way someone on any unix-y OS can check that all these compile - if cfg!(all(target_os = "linux", not(target_env = "musl"))) { - install_main_guard_linux(page_size) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - install_main_guard_linux_musl(page_size) - } else if cfg!(target_os = "freebsd") { - #[cfg(not(target_os = "freebsd"))] - return None; - // The FreeBSD code cannot be checked on non-BSDs. - #[cfg(target_os = "freebsd")] - install_main_guard_freebsd(page_size) - } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { - install_main_guard_bsds(page_size) - } else { - // SAFETY: guaranteed by caller. - unsafe { install_main_guard_default(page_size) } - } - } - - fn install_main_guard_linux(page_size: usize) -> Option> { - // See the corresponding conditional in init(). - // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps - if cfg!(panic = "immediate-abort") { - return None; - } - // Linux doesn't allocate the whole stack right away, and - // the kernel has its own stack-guard mechanism to fault - // when growing too close to an existing mapping. If we map - // our own guard, then the kernel starts enforcing a rather - // large gap above that, rendering much of the possible - // stack space useless. See #43052. - // - // Instead, we'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - fn install_main_guard_linux_musl(_page_size: usize) -> Option> { - // For the main thread, the musl's pthread_attr_getstack - // returns the current stack size, rather than maximum size - // it can eventually grow to. It cannot be used to determine - // the position of kernel's stack guard. - None - } - - #[cfg(target_os = "freebsd")] - fn install_main_guard_freebsd(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // FreeBSD's stack autogrows, and optionally includes a guard page - // at the bottom. If we try to remap the bottom of the stack - // ourselves, FreeBSD's guard page moves upwards. So we'll just use - // the builtin guard page. - let stackptr = stack_start_aligned(page_size)?; - let guardaddr = stackptr.addr(); - // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl. - // By default it is 1, checking once is enough since it is - // a boot time config value. - // FIXME(joboet): this function is only called once, remove the caching. - static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); - - let pages = PAGES.get_or_init(|| { - let mut guard: usize = 0; - let mut size = size_of_val(&guard); - let oid = c"security.bsd.stack_guard_page"; - - let r = unsafe { - libc::sysctlbyname( - oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0, - ) - }; - if r == 0 { guard } else { 1 } - }); - Some(guardaddr..guardaddr + pages * page_size) - } - - fn install_main_guard_bsds(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // OpenBSD stack already includes a guard page, and stack is - // immutable. - // NetBSD stack includes the guard page. - // - // We'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard_default(page_size: usize) -> Option> { - // Reallocate the last page of the stack. - // This ensures SIGBUS will be raised on - // stack overflow. - // Systems which enforce strict PAX MPROTECT do not allow - // to mprotect() a mapping with less restrictive permissions - // than the initial mmap() used, so we mmap() here with - // read/write permissions and only then mprotect() it to - // no permissions at all. See issue #50313. - let stackptr = stack_start_aligned(page_size)?; - // SAFETY: - // The memory region from `stackptr..stackptr + page_size` belongs to - // the current thread's stack, and the caller has asserted that there - // is sufficient stack space, which means that this will not overwrite - // any existing allocations. - let result = unsafe { - mmap64( - stackptr, - page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - -1, - 0, - ) - }; - if result != stackptr || result == MAP_FAILED { - panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); - } - - // SAFETY: - // Since this function is only called on the main thread, the stack will - // not be reused until program exit, so the runtime will never observe - // that part of the stack has been made unusable in this way. - let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; - if result != 0 { - panic!("failed to protect the guard page: {}", io::Error::last_os_error()); - } - - let guardaddr = stackptr.addr(); - - Some(guardaddr..guardaddr + page_size) - } - - #[cfg(any( - target_os = "macos", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ))] - fn current_guard() -> Option> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "hurd", - target_os = "linux", - target_os = "netbsd", - target_os = "l4re" - ))] - fn current_guard() -> Option> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut guardsize = 0; - // SAFETY: - // `attr` is an initialized attribute object and the pointer is valid - // for writing. - assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); - if guardsize == 0 { - if cfg!(all(target_os = "linux", target_env = "musl")) { - // musl versions before 1.1.19 always reported guard - // size obtained from pthread_attr_get_np as zero. - // Use page size as a fallback. - guardsize = PAGE_SIZE.load(Ordering::Relaxed); - } else { - panic!("there is no guard page"); - } - } - let mut stackptr = crate::ptr::null_mut::(); - let mut size = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, - 0 - ); - - let stackaddr = stackptr.addr(); - ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) - { - // glibc used to include the guard area within the stack, as noted in the BUGS - // section of `man pthread_attr_getguardsize`. This has been corrected starting - // with glibc 2.27, and in some distro backports, so the guard is now placed at the - // end (below) the stack. There's no easy way for us to know which we have at - // runtime, so we'll just match any fault in the range right above or below the - // stack base to call that fault a stack overflow. - Some(stackaddr - guardsize..stackaddr + guardsize) - } else { - Some(stackaddr..stackaddr + guardsize) - }; - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } -} - -// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses -// several symbols that might lead to rejections from the App Store, namely -// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. -// -// This might be overly cautious, though it is also what Swift does (and they -// usually have fewer qualms about forwards compatibility, since the runtime -// is shipped with the OS): -// -#[cfg(any( - miri, - not(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - target_os = "cygwin", - )) -))] -mod imp { pub unsafe fn init() {} pub fn make_handler(_main_thread: bool) -> super::Handler { @@ -756,89 +5,3 @@ mod imp { } pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} - -#[cfg(target_os = "cygwin")] -mod imp { - mod c { - pub type PVECTORED_EXCEPTION_HANDLER = - Option i32>; - pub type NTSTATUS = i32; - pub type BOOL = i32; - - unsafe extern "system" { - pub fn AddVectoredExceptionHandler( - first: u32, - handler: PVECTORED_EXCEPTION_HANDLER, - ) -> *mut core::ffi::c_void; - pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; - } - - pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; - pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; - - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - // We don't need this field here - // pub Context: *mut CONTEXT, - } - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_RECORD { - pub ExceptionCode: NTSTATUS, - pub ExceptionFlags: u32, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: *mut core::ffi::c_void, - pub NumberParameters: u32, - pub ExceptionInformation: [usize; 15], - } - } - - /// Reserve stack space for use in stack overflow exceptions. - fn reserve_stack() { - let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; - // Reserving stack space is not critical so we allow it to fail in the released build of libstd. - // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. - debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); - } - - unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { - // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. - unsafe { - let rec = &(*(*ExceptionInfo).ExceptionRecord); - let code = rec.ExceptionCode; - - if code == c::EXCEPTION_STACK_OVERFLOW { - crate::thread::with_current_name(|name| { - let name = name.unwrap_or(""); - let tid = crate::thread::current_os_id(); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - }); - } - c::EXCEPTION_CONTINUE_SEARCH - } - } - - pub unsafe fn init() { - // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. - unsafe { - let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); - // Similar to the above, adding the stack overflow handler is allowed to fail - // but a debug assert is used so CI will still test that it normally works. - debug_assert!(!result.is_null(), "failed to install exception handler"); - } - // Set the thread stack guarantee for the main thread. - reserve_stack(); - } - - pub fn make_handler(main_thread: bool) -> super::Handler { - if !main_thread { - reserve_stack(); - } - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs index 5604e3e6dbf42..ee4de76121097 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs @@ -1,63 +1,3 @@ -#![cfg_attr(test, allow(dead_code))] -#![forbid(unsafe_op_in_unsafe_fn)] - -pub use self::imp::init; -use self::imp::{drop_handler, make_handler}; - -pub struct Handler { - data: *mut libc::c_void, -} - -impl Handler { - pub unsafe fn new() -> Handler { - make_handler(false) - } - - fn null() -> Handler { - Handler { data: crate::ptr::null_mut() } - } -} - -impl Drop for Handler { - fn drop(&mut self) { - unsafe { - drop_handler(self.data); - } - } -} - -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ), -))] -mod thread_info; - -// miri doesn't model signals nor stack overflows and this code has some -// synchronization properties that we don't want to expose to user code, -// hence we disable it on miri. -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ) -))] -mod imp { use libc::{ MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, @@ -724,121 +664,3 @@ mod imp { } ret } -} - -// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses -// several symbols that might lead to rejections from the App Store, namely -// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. -// -// This might be overly cautious, though it is also what Swift does (and they -// usually have fewer qualms about forwards compatibility, since the runtime -// is shipped with the OS): -// -#[cfg(any( - miri, - not(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - target_os = "cygwin", - )) -))] -mod imp { - pub unsafe fn init() {} - - pub fn make_handler(_main_thread: bool) -> super::Handler { - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} - -#[cfg(target_os = "cygwin")] -mod imp { - mod c { - pub type PVECTORED_EXCEPTION_HANDLER = - Option i32>; - pub type NTSTATUS = i32; - pub type BOOL = i32; - - unsafe extern "system" { - pub fn AddVectoredExceptionHandler( - first: u32, - handler: PVECTORED_EXCEPTION_HANDLER, - ) -> *mut core::ffi::c_void; - pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; - } - - pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; - pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; - - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - // We don't need this field here - // pub Context: *mut CONTEXT, - } - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_RECORD { - pub ExceptionCode: NTSTATUS, - pub ExceptionFlags: u32, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: *mut core::ffi::c_void, - pub NumberParameters: u32, - pub ExceptionInformation: [usize; 15], - } - } - - /// Reserve stack space for use in stack overflow exceptions. - fn reserve_stack() { - let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; - // Reserving stack space is not critical so we allow it to fail in the released build of libstd. - // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. - debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); - } - - unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { - // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. - unsafe { - let rec = &(*(*ExceptionInfo).ExceptionRecord); - let code = rec.ExceptionCode; - - if code == c::EXCEPTION_STACK_OVERFLOW { - crate::thread::with_current_name(|name| { - let name = name.unwrap_or(""); - let tid = crate::thread::current_os_id(); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - }); - } - c::EXCEPTION_CONTINUE_SEARCH - } - } - - pub unsafe fn init() { - // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. - unsafe { - let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); - // Similar to the above, adding the stack overflow handler is allowed to fail - // but a debug assert is used so CI will still test that it normally works. - debug_assert!(!result.is_null(), "failed to install exception handler"); - } - // Set the thread stack guarantee for the main thread. - reserve_stack(); - } - - pub fn make_handler(main_thread: bool) -> super::Handler { - if !main_thread { - reserve_stack(); - } - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} -} diff --git a/library/std/src/sys/pal/unix/stack_overflow/mod.rs b/library/std/src/sys/pal/unix/stack_overflow/mod.rs index 5604e3e6dbf42..f9541e182156c 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/mod.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/mod.rs @@ -58,672 +58,6 @@ mod thread_info; ) ))] mod imp { - use libc::{ - MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, - SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, - }; - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::{mmap as mmap64, mprotect, munmap}; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::{mmap64, mprotect, munmap}; - - use super::Handler; - use super::thread_info::{delete_current_info, set_current_info, with_current_info}; - use crate::ops::Range; - use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; - use crate::sys::pal::unix::conf; - use crate::{io, mem, ptr}; - - /// Signal handler for the SIGSEGV and SIGBUS handlers. - /// - /// We've got guard pages (unmapped pages) at the end of every thread's - /// stack, so if a thread ends up running into the guard page it'll trigger - /// this handler. We want to detect these cases and print out a helpful error - /// saying that the stack has overflowed. All other signals, however, should - /// go back to what they were originally supposed to do. - /// - /// This handler currently exists purely to print an informative message - /// whenever a thread overflows its stack. We then abort to exit and - /// indicate a crash, but to avoid a misleading SIGSEGV that might lead - /// users to believe that unsafe code has accessed an invalid pointer; the - /// SIGSEGV encountered when overflowing the stack is expected and - /// well-defined. - /// - /// If this is not a stack overflow, the handler un-registers itself and - /// then returns (to allow the original signal to be delivered again). - /// Returning from this kind of signal handler is technically not defined - /// to work when reading the POSIX spec strictly, but in practice it turns - /// out many large systems and all implementations allow returning from a - /// signal handler to work. For a more detailed explanation see the - /// comments on #26458. - /// - /// # Safety - /// Rust doesn't call this, it *gets called* by the kernel, which we expect - /// to provide valid parameters. Apart from that, this function does not - /// have any other preconditions. - unsafe extern "C" fn signal_handler( - signum: libc::c_int, - info: *mut libc::siginfo_t, - _data: *mut libc::c_void, - ) { - // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. - let fault_addr = unsafe { (*info).si_addr().addr() }; - - // `with_current_info` expects that the process aborts after it is - // called. If the signal was not caused by a memory access, this might - // not be true. We detect this by noticing that the `si_addr` field is - // zero if the signal is synthetic. - if fault_addr != 0 { - with_current_info(|thread_info| { - // If the faulting address is within the guard page, then we print a - // message saying so and abort. - if let Some(thread_info) = thread_info - && thread_info.guard_page_range.contains(&fault_addr) - { - // Hey you! Yes, you modifying the stack overflow message! - // Please make sure that all functions called here are - // actually async-signal-safe. If they're not, try retrieving - // the information beforehand and storing it in `ThreadInfo`. - // Thank you! - // - says Jonas after having had to watch his carefully - // written code get made unsound again. - let tid = thread_info.tid; - let name = thread_info.name.as_deref().unwrap_or(""); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - rtabort!("stack overflow"); - } - }) - } - - // Unregister ourselves by reverting back to the default behavior. - // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" - let mut action: sigaction = unsafe { mem::zeroed() }; - action.sa_sigaction = SIG_DFL; - // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction - unsafe { sigaction(signum, &action, ptr::null_mut()) }; - - // See comment above for why this function returns. - } - - static PAGE_SIZE: Atomic = AtomicUsize::new(0); - // Store a pointer to the allocation for the main thread's altstack so that - // tools like valgrind don't complain about a leaked unreachable allocation. - // - // If the main thread exits, the process will terminate so there's no use in - // freeing resources. It also means that the altstack is still installed - // while TLS destructors are run on the main thread (c.f. #111272). - static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); - static NEED_ALTSTACK: Atomic = AtomicBool::new(false); - - /// # Safety - /// Must be called only once, on the main thread, during program startup. - pub unsafe fn init() { - PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); - - // SAFETY: - // This is only called on the main thread, and since it is still early - // in the programs lifetime there is (almost) certainly enough stack - // space left to install the guard page. - let mut guard_page_range = unsafe { install_main_guard() }; - - // Even for panic=immediate-abort, installing the guard pages is important for soundness. - // That said, we do not care about giving nice stackoverflow messages via our custom - // signal handler, just exit early and let the user enjoy the segfault. - if cfg!(panic = "immediate-abort") { - return; - } - - // SAFETY: C structures are always zero-initializable. - let mut action: sigaction = unsafe { mem::zeroed() }; - for &signal in &[SIGSEGV, SIGBUS] { - // SAFETY: just fetches the current signal handler into action - unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; - // We assume that overriding the signal handler is always safe, - // which might conflict with certain libraries that rely on a - // specific signal behaviour. To prevent problems, we only - // override the handler if it has not been set yet. - if action.sa_sigaction == SIG_DFL { - if !NEED_ALTSTACK.load(Ordering::Relaxed) { - // haven't set up our sigaltstack yet - NEED_ALTSTACK.store(true, Ordering::Release); - let handler = make_handler(true); - MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); - mem::forget(handler); - - if let Some(guard_page_range) = guard_page_range.take() { - set_current_info(guard_page_range); - } - } - - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler - as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) - as sighandler_t; - // SAFETY: - // `&action` describes a valid `sigaction` and `signal_handler` - // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. - unsafe { sigaction(signal, &action, ptr::null_mut()) }; - } - } - } - - fn get_stack() -> libc::stack_t { - // OpenBSD requires this flag for stack mapping - // otherwise the said mapping will fail as a no-op on most systems - // and has a different meaning on FreeBSD - #[cfg(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - ))] - let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; - #[cfg(not(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - )))] - let flags = MAP_PRIVATE | MAP_ANON; - - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // SAFETY: this does not unmap any existing pages. - let stackp = unsafe { - mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) - }; - if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); - } - // SAFETY: this only affects the memory we just allocated. - let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; - if guard_result != 0 { - panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); - } - // SAFETY: - // The region was allocated with a larger size than `page_size`, so this - // addition is within bounds. - let stackp = unsafe { stackp.add(page_size) }; - - libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } - } - - pub fn make_handler(main_thread: bool) -> Handler { - if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { - return Handler::null(); - } - - if !main_thread { - if let Some(guard_page_range) = current_guard() { - set_current_info(guard_page_range); - } - } - - // Load the current alternate signal stack to see if we need to install - // our own. - // - // SAFETY: C structures are always zero-initializable. - let mut stack = unsafe { mem::zeroed() }; - // SAFETY: `&mut stack` is valid for writing a `stack_t`. - unsafe { sigaltstack(ptr::null(), &mut stack) }; - - // Configure alternate signal stack, if one is not already set. - if stack.ss_flags & SS_DISABLE != 0 { - let stack = get_stack(); - // SAFETY: - // `stack_t` is a freshly allocated stack that's not used anywhere - // else. It contains a guard page, so stack overflows in signal - // handlers will not cause undefined behaviour. We must make the - // fundamental runtime assumption that it is safe to install an - // alternate signal stack if there is none currently installed. - // This might conflict with foreign libraries that use the existence - // of an alternate signal stack as indication that certain runtime - // initialisation by the library has been performed (e.g. old - // versions of `std` assumed that certain thread-locals were already - // accessed and thus initialized in the thread if the stack overflow - // signal was successfully delivered). Such assumptions in other - // libraries are fundamentally flawed, so we pay no regard to them. - unsafe { sigaltstack(&stack, ptr::null_mut()) }; - Handler { data: stack.ss_sp as *mut libc::c_void } - } else { - Handler::null() - } - } - - /// # Safety - /// Must only be called with a pointer returned by `make_handler`, and only - /// once per `Handler`. - pub unsafe fn drop_handler(data: *mut libc::c_void) { - if !data.is_null() { - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - let disabling_stack = libc::stack_t { - ss_sp: ptr::null_mut(), - ss_flags: SS_DISABLE, - // Workaround for bug in macOS implementation of sigaltstack - // UNIX2003 which returns ENOMEM when disabling a stack while - // passing ss_size smaller than MINSIGSTKSZ. According to POSIX - // both ss_sp and ss_size should be ignored in this case. - ss_size: sigstack_size, - }; - // SAFETY: - // We assume that disabling the alternate signal stack is always - // sound, even if the current alternate signal stack is not the one - // we installed in `make_handler`. Any stack overflows from this - // point on will abort the program when the kernel tries to write - // the signal information to the guard page. - // - // FIXME: detect if the stack has changed, and only uninstall if it hasn't. - unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; - // The stack returned by `get_stack` is part of a mapping that - // started one page earlier, so walk back a page and unmap from - // there. - // - // SAFETY: - // This allocation was created by us in `get_stack` and, as the - // alternate signal stack is now disabled, is no longer in use. - unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; - } - - delete_current_info(); - } - - /// Modern kernels on modern hardware can have dynamic signal stack sizes. - #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] - fn sigstack_size() -> usize { - // SAFETY: `getauxval` is always safe to call. - let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; - // If getauxval couldn't find the entry, it returns 0, - // so take the higher of the "constant" and auxval. - // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ - libc::SIGSTKSZ.max(dynamic_sigstksz as _) - } - - /// Not all OS support hardware where this is needed. - #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] - fn sigstack_size() -> usize { - libc::SIGSTKSZ - } - - #[cfg(any(target_os = "solaris", target_os = "illumos"))] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // The pointer is valid for writing a `stack_t`. - assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); - Some(current_stack.ss_sp) - } - - #[cfg(target_os = "macos")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: always safe to call. - let th = unsafe { libc::pthread_self() }; - // SAFETY: `th` is a valid `pthread_t`. - unsafe { - let stackptr = libc::pthread_get_stackaddr_np(th); - let stacksize = libc::pthread_get_stacksize_np(th); - Some(stackptr.map_addr(|addr| addr - stacksize)) - } - } - - #[cfg(target_os = "openbsd")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t`. - // * `&mut current_stack` is coerced to a pointer that is valid for writing - // a `stack_t`. - assert_eq!( - unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, - 0 - ); - - let stack_ptr = current_stack.ss_sp; - // SAFETY: this is always safe to call. - let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { - // main thread - stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) - } else { - // new thread - stack_ptr.addr() - current_stack.ss_size - }; - Some(stack_ptr.with_addr(stackaddr)) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - target_os = "hurd", - target_os = "linux", - target_os = "l4re" - ))] - fn get_stack_start() -> Option<*mut libc::c_void> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut stackaddr = crate::ptr::null_mut(); - let mut stacksize = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, - 0 - ); - ret = Some(stackaddr); - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } - - fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - - // Ensure stackaddr is page aligned! A parent process might - // have reset RLIMIT_STACK to be non-page aligned. The - // pthread_attr_getstack() reports the usable stack area - // stackaddr < stackaddr + stacksize, so if stackaddr is not - // page-aligned, calculate the fix such that stackaddr < - // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = stackaddr % page_size; - Some(if remainder == 0 { - stackptr - } else { - stackptr.with_addr(stackaddr + page_size - remainder) - }) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard() -> Option> { - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // this way someone on any unix-y OS can check that all these compile - if cfg!(all(target_os = "linux", not(target_env = "musl"))) { - install_main_guard_linux(page_size) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - install_main_guard_linux_musl(page_size) - } else if cfg!(target_os = "freebsd") { - #[cfg(not(target_os = "freebsd"))] - return None; - // The FreeBSD code cannot be checked on non-BSDs. - #[cfg(target_os = "freebsd")] - install_main_guard_freebsd(page_size) - } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { - install_main_guard_bsds(page_size) - } else { - // SAFETY: guaranteed by caller. - unsafe { install_main_guard_default(page_size) } - } - } - - fn install_main_guard_linux(page_size: usize) -> Option> { - // See the corresponding conditional in init(). - // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps - if cfg!(panic = "immediate-abort") { - return None; - } - // Linux doesn't allocate the whole stack right away, and - // the kernel has its own stack-guard mechanism to fault - // when growing too close to an existing mapping. If we map - // our own guard, then the kernel starts enforcing a rather - // large gap above that, rendering much of the possible - // stack space useless. See #43052. - // - // Instead, we'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - fn install_main_guard_linux_musl(_page_size: usize) -> Option> { - // For the main thread, the musl's pthread_attr_getstack - // returns the current stack size, rather than maximum size - // it can eventually grow to. It cannot be used to determine - // the position of kernel's stack guard. - None - } - - #[cfg(target_os = "freebsd")] - fn install_main_guard_freebsd(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // FreeBSD's stack autogrows, and optionally includes a guard page - // at the bottom. If we try to remap the bottom of the stack - // ourselves, FreeBSD's guard page moves upwards. So we'll just use - // the builtin guard page. - let stackptr = stack_start_aligned(page_size)?; - let guardaddr = stackptr.addr(); - // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl. - // By default it is 1, checking once is enough since it is - // a boot time config value. - // FIXME(joboet): this function is only called once, remove the caching. - static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); - - let pages = PAGES.get_or_init(|| { - let mut guard: usize = 0; - let mut size = size_of_val(&guard); - let oid = c"security.bsd.stack_guard_page"; - - let r = unsafe { - libc::sysctlbyname( - oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0, - ) - }; - if r == 0 { guard } else { 1 } - }); - Some(guardaddr..guardaddr + pages * page_size) - } - - fn install_main_guard_bsds(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // OpenBSD stack already includes a guard page, and stack is - // immutable. - // NetBSD stack includes the guard page. - // - // We'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) - } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard_default(page_size: usize) -> Option> { - // Reallocate the last page of the stack. - // This ensures SIGBUS will be raised on - // stack overflow. - // Systems which enforce strict PAX MPROTECT do not allow - // to mprotect() a mapping with less restrictive permissions - // than the initial mmap() used, so we mmap() here with - // read/write permissions and only then mprotect() it to - // no permissions at all. See issue #50313. - let stackptr = stack_start_aligned(page_size)?; - // SAFETY: - // The memory region from `stackptr..stackptr + page_size` belongs to - // the current thread's stack, and the caller has asserted that there - // is sufficient stack space, which means that this will not overwrite - // any existing allocations. - let result = unsafe { - mmap64( - stackptr, - page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - -1, - 0, - ) - }; - if result != stackptr || result == MAP_FAILED { - panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); - } - - // SAFETY: - // Since this function is only called on the main thread, the stack will - // not be reused until program exit, so the runtime will never observe - // that part of the stack has been made unusable in this way. - let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; - if result != 0 { - panic!("failed to protect the guard page: {}", io::Error::last_os_error()); - } - - let guardaddr = stackptr.addr(); - - Some(guardaddr..guardaddr + page_size) - } - - #[cfg(any( - target_os = "macos", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ))] - fn current_guard() -> Option> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) - } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "hurd", - target_os = "linux", - target_os = "netbsd", - target_os = "l4re" - ))] - fn current_guard() -> Option> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut guardsize = 0; - // SAFETY: - // `attr` is an initialized attribute object and the pointer is valid - // for writing. - assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); - if guardsize == 0 { - if cfg!(all(target_os = "linux", target_env = "musl")) { - // musl versions before 1.1.19 always reported guard - // size obtained from pthread_attr_get_np as zero. - // Use page size as a fallback. - guardsize = PAGE_SIZE.load(Ordering::Relaxed); - } else { - panic!("there is no guard page"); - } - } - let mut stackptr = crate::ptr::null_mut::(); - let mut size = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, - 0 - ); - - let stackaddr = stackptr.addr(); - ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) - { - // glibc used to include the guard area within the stack, as noted in the BUGS - // section of `man pthread_attr_getguardsize`. This has been corrected starting - // with glibc 2.27, and in some distro backports, so the guard is now placed at the - // end (below) the stack. There's no easy way for us to know which we have at - // runtime, so we'll just match any fault in the range right above or below the - // stack base to call that fault a stack overflow. - Some(stackaddr - guardsize..stackaddr + guardsize) - } else { - Some(stackaddr..stackaddr + guardsize) - }; - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret - } } // This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses @@ -749,96 +83,8 @@ mod imp { )) ))] mod imp { - pub unsafe fn init() {} - - pub fn make_handler(_main_thread: bool) -> super::Handler { - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } #[cfg(target_os = "cygwin")] mod imp { - mod c { - pub type PVECTORED_EXCEPTION_HANDLER = - Option i32>; - pub type NTSTATUS = i32; - pub type BOOL = i32; - - unsafe extern "system" { - pub fn AddVectoredExceptionHandler( - first: u32, - handler: PVECTORED_EXCEPTION_HANDLER, - ) -> *mut core::ffi::c_void; - pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; - } - - pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; - pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; - - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - // We don't need this field here - // pub Context: *mut CONTEXT, - } - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_RECORD { - pub ExceptionCode: NTSTATUS, - pub ExceptionFlags: u32, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: *mut core::ffi::c_void, - pub NumberParameters: u32, - pub ExceptionInformation: [usize; 15], - } - } - - /// Reserve stack space for use in stack overflow exceptions. - fn reserve_stack() { - let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; - // Reserving stack space is not critical so we allow it to fail in the released build of libstd. - // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. - debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); - } - - unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { - // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. - unsafe { - let rec = &(*(*ExceptionInfo).ExceptionRecord); - let code = rec.ExceptionCode; - - if code == c::EXCEPTION_STACK_OVERFLOW { - crate::thread::with_current_name(|name| { - let name = name.unwrap_or(""); - let tid = crate::thread::current_os_id(); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - }); - } - c::EXCEPTION_CONTINUE_SEARCH - } - } - - pub unsafe fn init() { - // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. - unsafe { - let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); - // Similar to the above, adding the stack overflow handler is allowed to fail - // but a debug assert is used so CI will still test that it normally works. - debug_assert!(!result.is_null(), "failed to install exception handler"); - } - // Set the thread stack guarantee for the main thread. - reserve_stack(); - } - - pub fn make_handler(main_thread: bool) -> super::Handler { - if !main_thread { - reserve_stack(); - } - super::Handler::null() - } - - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} } From e449348b8a02e876834a2f152aef1634f22d2904 Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 23 Sep 2026 13:48:51 +0200 Subject: [PATCH 0703/1309] std: split stack overflow module (format) --- .../pal/unix/stack_overflow/handler_cygwin.rs | 134 +- .../pal/unix/stack_overflow/handler_none.rs | 10 +- .../pal/unix/stack_overflow/handler_signal.rs | 1223 ++++++++--------- .../src/sys/pal/unix/stack_overflow/mod.rs | 9 +- 4 files changed, 683 insertions(+), 693 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs index 089bd2c95073d..3289efe05b068 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_cygwin.rs @@ -1,81 +1,81 @@ - mod c { - pub type PVECTORED_EXCEPTION_HANDLER = - Option i32>; - pub type NTSTATUS = i32; - pub type BOOL = i32; +mod c { + pub type PVECTORED_EXCEPTION_HANDLER = + Option i32>; + pub type NTSTATUS = i32; + pub type BOOL = i32; - unsafe extern "system" { - pub fn AddVectoredExceptionHandler( - first: u32, - handler: PVECTORED_EXCEPTION_HANDLER, - ) -> *mut core::ffi::c_void; - pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; - } + unsafe extern "system" { + pub fn AddVectoredExceptionHandler( + first: u32, + handler: PVECTORED_EXCEPTION_HANDLER, + ) -> *mut core::ffi::c_void; + pub fn SetThreadStackGuarantee(stacksizeinbytes: *mut u32) -> BOOL; + } - pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; - pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; + pub const EXCEPTION_STACK_OVERFLOW: NTSTATUS = 0xC00000FD_u32 as _; + pub const EXCEPTION_CONTINUE_SEARCH: i32 = 1i32; - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_POINTERS { - pub ExceptionRecord: *mut EXCEPTION_RECORD, - // We don't need this field here - // pub Context: *mut CONTEXT, - } - #[repr(C)] - #[derive(Clone, Copy)] - pub struct EXCEPTION_RECORD { - pub ExceptionCode: NTSTATUS, - pub ExceptionFlags: u32, - pub ExceptionRecord: *mut EXCEPTION_RECORD, - pub ExceptionAddress: *mut core::ffi::c_void, - pub NumberParameters: u32, - pub ExceptionInformation: [usize; 15], - } + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_POINTERS { + pub ExceptionRecord: *mut EXCEPTION_RECORD, + // We don't need this field here + // pub Context: *mut CONTEXT, } - - /// Reserve stack space for use in stack overflow exceptions. - fn reserve_stack() { - let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; - // Reserving stack space is not critical so we allow it to fail in the released build of libstd. - // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. - debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); + #[repr(C)] + #[derive(Clone, Copy)] + pub struct EXCEPTION_RECORD { + pub ExceptionCode: NTSTATUS, + pub ExceptionFlags: u32, + pub ExceptionRecord: *mut EXCEPTION_RECORD, + pub ExceptionAddress: *mut core::ffi::c_void, + pub NumberParameters: u32, + pub ExceptionInformation: [usize; 15], } +} - unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { - // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. - unsafe { - let rec = &(*(*ExceptionInfo).ExceptionRecord); - let code = rec.ExceptionCode; +/// Reserve stack space for use in stack overflow exceptions. +fn reserve_stack() { + let result = unsafe { c::SetThreadStackGuarantee(&mut 0x5000) }; + // Reserving stack space is not critical so we allow it to fail in the released build of libstd. + // We still use debug assert here so that CI will test that we haven't made a mistake calling the function. + debug_assert_ne!(result, 0, "failed to reserve stack space for exception handling"); +} - if code == c::EXCEPTION_STACK_OVERFLOW { - crate::thread::with_current_name(|name| { - let name = name.unwrap_or(""); - let tid = crate::thread::current_os_id(); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - }); - } - c::EXCEPTION_CONTINUE_SEARCH +unsafe extern "system" fn vectored_handler(ExceptionInfo: *mut c::EXCEPTION_POINTERS) -> i32 { + // SAFETY: It's up to the caller (which in this case is the OS) to ensure that `ExceptionInfo` is valid. + unsafe { + let rec = &(*(*ExceptionInfo).ExceptionRecord); + let code = rec.ExceptionCode; + + if code == c::EXCEPTION_STACK_OVERFLOW { + crate::thread::with_current_name(|name| { + let name = name.unwrap_or(""); + let tid = crate::thread::current_os_id(); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + }); } + c::EXCEPTION_CONTINUE_SEARCH } +} - pub unsafe fn init() { - // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. - unsafe { - let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); - // Similar to the above, adding the stack overflow handler is allowed to fail - // but a debug assert is used so CI will still test that it normally works. - debug_assert!(!result.is_null(), "failed to install exception handler"); - } - // Set the thread stack guarantee for the main thread. - reserve_stack(); +pub unsafe fn init() { + // SAFETY: `vectored_handler` has the correct ABI and is safe to call during exception handling. + unsafe { + let result = c::AddVectoredExceptionHandler(0, Some(vectored_handler)); + // Similar to the above, adding the stack overflow handler is allowed to fail + // but a debug assert is used so CI will still test that it normally works. + debug_assert!(!result.is_null(), "failed to install exception handler"); } + // Set the thread stack guarantee for the main thread. + reserve_stack(); +} - pub fn make_handler(main_thread: bool) -> super::Handler { - if !main_thread { - reserve_stack(); - } - super::Handler::null() +pub fn make_handler(main_thread: bool) -> super::Handler { + if !main_thread { + reserve_stack(); } + super::Handler::null() +} - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +pub unsafe fn drop_handler(_data: *mut libc::c_void) {} diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs index f765090ffff7d..a0e2dfa941867 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_none.rs @@ -1,7 +1,7 @@ - pub unsafe fn init() {} +pub unsafe fn init() {} - pub fn make_handler(_main_thread: bool) -> super::Handler { - super::Handler::null() - } +pub fn make_handler(_main_thread: bool) -> super::Handler { + super::Handler::null() +} - pub unsafe fn drop_handler(_data: *mut libc::c_void) {} +pub unsafe fn drop_handler(_data: *mut libc::c_void) {} diff --git a/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs index ee4de76121097..54e94e0f22578 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/handler_signal.rs @@ -1,666 +1,659 @@ - use libc::{ - MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, - SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, - }; - #[cfg(not(all(target_os = "linux", target_env = "gnu")))] - use libc::{mmap as mmap64, mprotect, munmap}; - #[cfg(all(target_os = "linux", target_env = "gnu"))] - use libc::{mmap64, mprotect, munmap}; - - use super::Handler; - use super::thread_info::{delete_current_info, set_current_info, with_current_info}; - use crate::ops::Range; - use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; - use crate::sys::pal::unix::conf; - use crate::{io, mem, ptr}; - - /// Signal handler for the SIGSEGV and SIGBUS handlers. - /// - /// We've got guard pages (unmapped pages) at the end of every thread's - /// stack, so if a thread ends up running into the guard page it'll trigger - /// this handler. We want to detect these cases and print out a helpful error - /// saying that the stack has overflowed. All other signals, however, should - /// go back to what they were originally supposed to do. - /// - /// This handler currently exists purely to print an informative message - /// whenever a thread overflows its stack. We then abort to exit and - /// indicate a crash, but to avoid a misleading SIGSEGV that might lead - /// users to believe that unsafe code has accessed an invalid pointer; the - /// SIGSEGV encountered when overflowing the stack is expected and - /// well-defined. - /// - /// If this is not a stack overflow, the handler un-registers itself and - /// then returns (to allow the original signal to be delivered again). - /// Returning from this kind of signal handler is technically not defined - /// to work when reading the POSIX spec strictly, but in practice it turns - /// out many large systems and all implementations allow returning from a - /// signal handler to work. For a more detailed explanation see the - /// comments on #26458. - /// - /// # Safety - /// Rust doesn't call this, it *gets called* by the kernel, which we expect - /// to provide valid parameters. Apart from that, this function does not - /// have any other preconditions. - unsafe extern "C" fn signal_handler( - signum: libc::c_int, - info: *mut libc::siginfo_t, - _data: *mut libc::c_void, - ) { - // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. - let fault_addr = unsafe { (*info).si_addr().addr() }; - - // `with_current_info` expects that the process aborts after it is - // called. If the signal was not caused by a memory access, this might - // not be true. We detect this by noticing that the `si_addr` field is - // zero if the signal is synthetic. - if fault_addr != 0 { - with_current_info(|thread_info| { - // If the faulting address is within the guard page, then we print a - // message saying so and abort. - if let Some(thread_info) = thread_info - && thread_info.guard_page_range.contains(&fault_addr) - { - // Hey you! Yes, you modifying the stack overflow message! - // Please make sure that all functions called here are - // actually async-signal-safe. If they're not, try retrieving - // the information beforehand and storing it in `ThreadInfo`. - // Thank you! - // - says Jonas after having had to watch his carefully - // written code get made unsound again. - let tid = thread_info.tid; - let name = thread_info.name.as_deref().unwrap_or(""); - rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); - rtabort!("stack overflow"); - } - }) - } - - // Unregister ourselves by reverting back to the default behavior. - // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" - let mut action: sigaction = unsafe { mem::zeroed() }; - action.sa_sigaction = SIG_DFL; - // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction - unsafe { sigaction(signum, &action, ptr::null_mut()) }; - - // See comment above for why this function returns. +use libc::{ + MAP_ANON, MAP_FAILED, MAP_FIXED, MAP_PRIVATE, PROT_NONE, PROT_READ, PROT_WRITE, SA_ONSTACK, + SA_SIGINFO, SIG_DFL, SIGBUS, SIGSEGV, SS_DISABLE, sigaction, sigaltstack, sighandler_t, +}; +#[cfg(not(all(target_os = "linux", target_env = "gnu")))] +use libc::{mmap as mmap64, mprotect, munmap}; +#[cfg(all(target_os = "linux", target_env = "gnu"))] +use libc::{mmap64, mprotect, munmap}; + +use super::Handler; +use super::thread_info::{delete_current_info, set_current_info, with_current_info}; +use crate::ops::Range; +use crate::sync::atomic::{Atomic, AtomicBool, AtomicPtr, AtomicUsize, Ordering}; +use crate::sys::pal::unix::conf; +use crate::{io, mem, ptr}; + +/// Signal handler for the SIGSEGV and SIGBUS handlers. +/// +/// We've got guard pages (unmapped pages) at the end of every thread's +/// stack, so if a thread ends up running into the guard page it'll trigger +/// this handler. We want to detect these cases and print out a helpful error +/// saying that the stack has overflowed. All other signals, however, should +/// go back to what they were originally supposed to do. +/// +/// This handler currently exists purely to print an informative message +/// whenever a thread overflows its stack. We then abort to exit and +/// indicate a crash, but to avoid a misleading SIGSEGV that might lead +/// users to believe that unsafe code has accessed an invalid pointer; the +/// SIGSEGV encountered when overflowing the stack is expected and +/// well-defined. +/// +/// If this is not a stack overflow, the handler un-registers itself and +/// then returns (to allow the original signal to be delivered again). +/// Returning from this kind of signal handler is technically not defined +/// to work when reading the POSIX spec strictly, but in practice it turns +/// out many large systems and all implementations allow returning from a +/// signal handler to work. For a more detailed explanation see the +/// comments on #26458. +/// +/// # Safety +/// Rust doesn't call this, it *gets called* by the kernel, which we expect +/// to provide valid parameters. Apart from that, this function does not +/// have any other preconditions. +unsafe extern "C" fn signal_handler( + signum: libc::c_int, + info: *mut libc::siginfo_t, + _data: *mut libc::c_void, +) { + // SAFETY: this pointer is provided by the system and will always point to a valid `siginfo_t`. + let fault_addr = unsafe { (*info).si_addr().addr() }; + + // `with_current_info` expects that the process aborts after it is + // called. If the signal was not caused by a memory access, this might + // not be true. We detect this by noticing that the `si_addr` field is + // zero if the signal is synthetic. + if fault_addr != 0 { + with_current_info(|thread_info| { + // If the faulting address is within the guard page, then we print a + // message saying so and abort. + if let Some(thread_info) = thread_info + && thread_info.guard_page_range.contains(&fault_addr) + { + // Hey you! Yes, you modifying the stack overflow message! + // Please make sure that all functions called here are + // actually async-signal-safe. If they're not, try retrieving + // the information beforehand and storing it in `ThreadInfo`. + // Thank you! + // - says Jonas after having had to watch his carefully + // written code get made unsound again. + let tid = thread_info.tid; + let name = thread_info.name.as_deref().unwrap_or(""); + rtprintpanic!("\nthread '{name}' ({tid}) has overflowed its stack\n"); + rtabort!("stack overflow"); + } + }) } - static PAGE_SIZE: Atomic = AtomicUsize::new(0); - // Store a pointer to the allocation for the main thread's altstack so that - // tools like valgrind don't complain about a leaked unreachable allocation. - // - // If the main thread exits, the process will terminate so there's no use in - // freeing resources. It also means that the altstack is still installed - // while TLS destructors are run on the main thread (c.f. #111272). - static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); - static NEED_ALTSTACK: Atomic = AtomicBool::new(false); - - /// # Safety - /// Must be called only once, on the main thread, during program startup. - pub unsafe fn init() { - PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); - - // SAFETY: - // This is only called on the main thread, and since it is still early - // in the programs lifetime there is (almost) certainly enough stack - // space left to install the guard page. - let mut guard_page_range = unsafe { install_main_guard() }; - - // Even for panic=immediate-abort, installing the guard pages is important for soundness. - // That said, we do not care about giving nice stackoverflow messages via our custom - // signal handler, just exit early and let the user enjoy the segfault. - if cfg!(panic = "immediate-abort") { - return; - } + // Unregister ourselves by reverting back to the default behavior. + // SAFETY: assuming all platforms define struct sigaction as "zero-initializable" + let mut action: sigaction = unsafe { mem::zeroed() }; + action.sa_sigaction = SIG_DFL; + // SAFETY: pray this is a well-behaved POSIX implementation of fn sigaction + unsafe { sigaction(signum, &action, ptr::null_mut()) }; + + // See comment above for why this function returns. +} + +static PAGE_SIZE: Atomic = AtomicUsize::new(0); +// Store a pointer to the allocation for the main thread's altstack so that +// tools like valgrind don't complain about a leaked unreachable allocation. +// +// If the main thread exits, the process will terminate so there's no use in +// freeing resources. It also means that the altstack is still installed +// while TLS destructors are run on the main thread (c.f. #111272). +static MAIN_ALTSTACK: Atomic<*mut libc::c_void> = AtomicPtr::new(ptr::null_mut()); +static NEED_ALTSTACK: Atomic = AtomicBool::new(false); + +/// # Safety +/// Must be called only once, on the main thread, during program startup. +pub unsafe fn init() { + PAGE_SIZE.store(conf::page_size(), Ordering::Relaxed); + + // SAFETY: + // This is only called on the main thread, and since it is still early + // in the programs lifetime there is (almost) certainly enough stack + // space left to install the guard page. + let mut guard_page_range = unsafe { install_main_guard() }; + + // Even for panic=immediate-abort, installing the guard pages is important for soundness. + // That said, we do not care about giving nice stackoverflow messages via our custom + // signal handler, just exit early and let the user enjoy the segfault. + if cfg!(panic = "immediate-abort") { + return; + } - // SAFETY: C structures are always zero-initializable. - let mut action: sigaction = unsafe { mem::zeroed() }; - for &signal in &[SIGSEGV, SIGBUS] { - // SAFETY: just fetches the current signal handler into action - unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; - // We assume that overriding the signal handler is always safe, - // which might conflict with certain libraries that rely on a - // specific signal behaviour. To prevent problems, we only - // override the handler if it has not been set yet. - if action.sa_sigaction == SIG_DFL { - if !NEED_ALTSTACK.load(Ordering::Relaxed) { - // haven't set up our sigaltstack yet - NEED_ALTSTACK.store(true, Ordering::Release); - let handler = make_handler(true); - MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); - mem::forget(handler); - - if let Some(guard_page_range) = guard_page_range.take() { - set_current_info(guard_page_range); - } + // SAFETY: C structures are always zero-initializable. + let mut action: sigaction = unsafe { mem::zeroed() }; + for &signal in &[SIGSEGV, SIGBUS] { + // SAFETY: just fetches the current signal handler into action + unsafe { sigaction(signal, ptr::null_mut(), &mut action) }; + // We assume that overriding the signal handler is always safe, + // which might conflict with certain libraries that rely on a + // specific signal behaviour. To prevent problems, we only + // override the handler if it has not been set yet. + if action.sa_sigaction == SIG_DFL { + if !NEED_ALTSTACK.load(Ordering::Relaxed) { + // haven't set up our sigaltstack yet + NEED_ALTSTACK.store(true, Ordering::Release); + let handler = make_handler(true); + MAIN_ALTSTACK.store(handler.data, Ordering::Relaxed); + mem::forget(handler); + + if let Some(guard_page_range) = guard_page_range.take() { + set_current_info(guard_page_range); } - - action.sa_flags = SA_SIGINFO | SA_ONSTACK; - action.sa_sigaction = signal_handler - as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) - as sighandler_t; - // SAFETY: - // `&action` describes a valid `sigaction` and `signal_handler` - // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. - unsafe { sigaction(signal, &action, ptr::null_mut()) }; } - } - } - fn get_stack() -> libc::stack_t { - // OpenBSD requires this flag for stack mapping - // otherwise the said mapping will fail as a no-op on most systems - // and has a different meaning on FreeBSD - #[cfg(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - ))] - let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; - #[cfg(not(any( - target_os = "openbsd", - target_os = "netbsd", - target_os = "linux", - target_os = "dragonfly", - )))] - let flags = MAP_PRIVATE | MAP_ANON; - - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // SAFETY: this does not unmap any existing pages. - let stackp = unsafe { - mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) - }; - if stackp == MAP_FAILED { - panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); - } - // SAFETY: this only affects the memory we just allocated. - let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; - if guard_result != 0 { - panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); + action.sa_flags = SA_SIGINFO | SA_ONSTACK; + action.sa_sigaction = signal_handler + as unsafe extern "C" fn(i32, *mut libc::siginfo_t, *mut libc::c_void) + as sighandler_t; + // SAFETY: + // `&action` describes a valid `sigaction` and `signal_handler` + // is safe to use as a signal handler for `SIGSEGV` and `SIGBUS`. + unsafe { sigaction(signal, &action, ptr::null_mut()) }; } - // SAFETY: - // The region was allocated with a larger size than `page_size`, so this - // addition is within bounds. - let stackp = unsafe { stackp.add(page_size) }; - - libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } } +} - pub fn make_handler(main_thread: bool) -> Handler { - if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { - return Handler::null(); - } +fn get_stack() -> libc::stack_t { + // OpenBSD requires this flag for stack mapping + // otherwise the said mapping will fail as a no-op on most systems + // and has a different meaning on FreeBSD + #[cfg(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + ))] + let flags = MAP_PRIVATE | MAP_ANON | libc::MAP_STACK; + #[cfg(not(any( + target_os = "openbsd", + target_os = "netbsd", + target_os = "linux", + target_os = "dragonfly", + )))] + let flags = MAP_PRIVATE | MAP_ANON; - if !main_thread { - if let Some(guard_page_range) = current_guard() { - set_current_info(guard_page_range); - } - } + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); - // Load the current alternate signal stack to see if we need to install - // our own. - // - // SAFETY: C structures are always zero-initializable. - let mut stack = unsafe { mem::zeroed() }; - // SAFETY: `&mut stack` is valid for writing a `stack_t`. - unsafe { sigaltstack(ptr::null(), &mut stack) }; - - // Configure alternate signal stack, if one is not already set. - if stack.ss_flags & SS_DISABLE != 0 { - let stack = get_stack(); - // SAFETY: - // `stack_t` is a freshly allocated stack that's not used anywhere - // else. It contains a guard page, so stack overflows in signal - // handlers will not cause undefined behaviour. We must make the - // fundamental runtime assumption that it is safe to install an - // alternate signal stack if there is none currently installed. - // This might conflict with foreign libraries that use the existence - // of an alternate signal stack as indication that certain runtime - // initialisation by the library has been performed (e.g. old - // versions of `std` assumed that certain thread-locals were already - // accessed and thus initialized in the thread if the stack overflow - // signal was successfully delivered). Such assumptions in other - // libraries are fundamentally flawed, so we pay no regard to them. - unsafe { sigaltstack(&stack, ptr::null_mut()) }; - Handler { data: stack.ss_sp as *mut libc::c_void } - } else { - Handler::null() - } + // SAFETY: this does not unmap any existing pages. + let stackp = unsafe { + mmap64(ptr::null_mut(), sigstack_size + page_size, PROT_READ | PROT_WRITE, flags, -1, 0) + }; + if stackp == MAP_FAILED { + panic!("failed to allocate an alternative stack: {}", io::Error::last_os_error()); } + // SAFETY: this only affects the memory we just allocated. + let guard_result = unsafe { libc::mprotect(stackp, page_size, PROT_NONE) }; + if guard_result != 0 { + panic!("failed to set up alternative stack guard page: {}", io::Error::last_os_error()); + } + // SAFETY: + // The region was allocated with a larger size than `page_size`, so this + // addition is within bounds. + let stackp = unsafe { stackp.add(page_size) }; - /// # Safety - /// Must only be called with a pointer returned by `make_handler`, and only - /// once per `Handler`. - pub unsafe fn drop_handler(data: *mut libc::c_void) { - if !data.is_null() { - let sigstack_size = sigstack_size(); - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - let disabling_stack = libc::stack_t { - ss_sp: ptr::null_mut(), - ss_flags: SS_DISABLE, - // Workaround for bug in macOS implementation of sigaltstack - // UNIX2003 which returns ENOMEM when disabling a stack while - // passing ss_size smaller than MINSIGSTKSZ. According to POSIX - // both ss_sp and ss_size should be ignored in this case. - ss_size: sigstack_size, - }; - // SAFETY: - // We assume that disabling the alternate signal stack is always - // sound, even if the current alternate signal stack is not the one - // we installed in `make_handler`. Any stack overflows from this - // point on will abort the program when the kernel tries to write - // the signal information to the guard page. - // - // FIXME: detect if the stack has changed, and only uninstall if it hasn't. - unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; - // The stack returned by `get_stack` is part of a mapping that - // started one page earlier, so walk back a page and unmap from - // there. - // - // SAFETY: - // This allocation was created by us in `get_stack` and, as the - // alternate signal stack is now disabled, is no longer in use. - unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; - } + libc::stack_t { ss_sp: stackp, ss_flags: 0, ss_size: sigstack_size } +} - delete_current_info(); +pub fn make_handler(main_thread: bool) -> Handler { + if cfg!(panic = "immediate-abort") || !NEED_ALTSTACK.load(Ordering::Acquire) { + return Handler::null(); } - /// Modern kernels on modern hardware can have dynamic signal stack sizes. - #[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] - fn sigstack_size() -> usize { - // SAFETY: `getauxval` is always safe to call. - let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; - // If getauxval couldn't find the entry, it returns 0, - // so take the higher of the "constant" and auxval. - // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ - libc::SIGSTKSZ.max(dynamic_sigstksz as _) + if !main_thread { + if let Some(guard_page_range) = current_guard() { + set_current_info(guard_page_range); + } } - /// Not all OS support hardware where this is needed. - #[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] - fn sigstack_size() -> usize { - libc::SIGSTKSZ + // Load the current alternate signal stack to see if we need to install + // our own. + // + // SAFETY: C structures are always zero-initializable. + let mut stack = unsafe { mem::zeroed() }; + // SAFETY: `&mut stack` is valid for writing a `stack_t`. + unsafe { sigaltstack(ptr::null(), &mut stack) }; + + // Configure alternate signal stack, if one is not already set. + if stack.ss_flags & SS_DISABLE != 0 { + let stack = get_stack(); + // SAFETY: + // `stack_t` is a freshly allocated stack that's not used anywhere + // else. It contains a guard page, so stack overflows in signal + // handlers will not cause undefined behaviour. We must make the + // fundamental runtime assumption that it is safe to install an + // alternate signal stack if there is none currently installed. + // This might conflict with foreign libraries that use the existence + // of an alternate signal stack as indication that certain runtime + // initialisation by the library has been performed (e.g. old + // versions of `std` assumed that certain thread-locals were already + // accessed and thus initialized in the thread if the stack overflow + // signal was successfully delivered). Such assumptions in other + // libraries are fundamentally flawed, so we pay no regard to them. + unsafe { sigaltstack(&stack, ptr::null_mut()) }; + Handler { data: stack.ss_sp as *mut libc::c_void } + } else { + Handler::null() } +} - #[cfg(any(target_os = "solaris", target_os = "illumos"))] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; +/// # Safety +/// Must only be called with a pointer returned by `make_handler`, and only +/// once per `Handler`. +pub unsafe fn drop_handler(data: *mut libc::c_void) { + if !data.is_null() { + let sigstack_size = sigstack_size(); + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + let disabling_stack = libc::stack_t { + ss_sp: ptr::null_mut(), + ss_flags: SS_DISABLE, + // Workaround for bug in macOS implementation of sigaltstack + // UNIX2003 which returns ENOMEM when disabling a stack while + // passing ss_size smaller than MINSIGSTKSZ. According to POSIX + // both ss_sp and ss_size should be ignored in this case. + ss_size: sigstack_size, + }; // SAFETY: - // The pointer is valid for writing a `stack_t`. - assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); - Some(current_stack.ss_sp) + // We assume that disabling the alternate signal stack is always + // sound, even if the current alternate signal stack is not the one + // we installed in `make_handler`. Any stack overflows from this + // point on will abort the program when the kernel tries to write + // the signal information to the guard page. + // + // FIXME: detect if the stack has changed, and only uninstall if it hasn't. + unsafe { sigaltstack(&disabling_stack, ptr::null_mut()) }; + // The stack returned by `get_stack` is part of a mapping that + // started one page earlier, so walk back a page and unmap from + // there. + // + // SAFETY: + // This allocation was created by us in `get_stack` and, as the + // alternate signal stack is now disabled, is no longer in use. + unsafe { munmap(data.sub(page_size), sigstack_size + page_size) }; } - #[cfg(target_os = "macos")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: always safe to call. - let th = unsafe { libc::pthread_self() }; - // SAFETY: `th` is a valid `pthread_t`. - unsafe { - let stackptr = libc::pthread_get_stackaddr_np(th); - let stacksize = libc::pthread_get_stacksize_np(th); - Some(stackptr.map_addr(|addr| addr - stacksize)) - } + delete_current_info(); +} + +/// Modern kernels on modern hardware can have dynamic signal stack sizes. +#[cfg(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc")))] +fn sigstack_size() -> usize { + // SAFETY: `getauxval` is always safe to call. + let dynamic_sigstksz = unsafe { libc::getauxval(libc::AT_MINSIGSTKSZ) }; + // If getauxval couldn't find the entry, it returns 0, + // so take the higher of the "constant" and auxval. + // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ + libc::SIGSTKSZ.max(dynamic_sigstksz as _) +} + +/// Not all OS support hardware where this is needed. +#[cfg(not(all(any(target_os = "linux", target_os = "android"), not(target_env = "uclibc"))))] +fn sigstack_size() -> usize { + libc::SIGSTKSZ +} + +#[cfg(any(target_os = "solaris", target_os = "illumos"))] +fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // The pointer is valid for writing a `stack_t`. + assert_eq!(unsafe { libc::stack_getbounds(&mut current_stack) }, 0); + Some(current_stack.ss_sp) +} + +#[cfg(target_os = "macos")] +fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: always safe to call. + let th = unsafe { libc::pthread_self() }; + // SAFETY: `th` is a valid `pthread_t`. + unsafe { + let stackptr = libc::pthread_get_stackaddr_np(th); + let stacksize = libc::pthread_get_stacksize_np(th); + Some(stackptr.map_addr(|addr| addr - stacksize)) } +} + +#[cfg(target_os = "openbsd")] +fn get_stack_start() -> Option<*mut libc::c_void> { + // SAFETY: C types are always zero-initializable. + let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t`. + // * `&mut current_stack` is coerced to a pointer that is valid for writing + // a `stack_t`. + assert_eq!(unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, 0); + + let stack_ptr = current_stack.ss_sp; + // SAFETY: this is always safe to call. + let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { + // main thread + stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) + } else { + // new thread + stack_ptr.addr() - current_stack.ss_size + }; + Some(stack_ptr.with_addr(stackaddr)) +} + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "netbsd", + target_os = "hurd", + target_os = "linux", + target_os = "l4re" +))] +fn get_stack_start() -> Option<*mut libc::c_void> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); + } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); - #[cfg(target_os = "openbsd")] - fn get_stack_start() -> Option<*mut libc::c_void> { - // SAFETY: C types are always zero-initializable. - let mut current_stack: libc::stack_t = unsafe { crate::mem::zeroed() }; + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut stackaddr = crate::ptr::null_mut(); + let mut stacksize = 0; // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t`. - // * `&mut current_stack` is coerced to a pointer that is valid for writing - // a `stack_t`. + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. assert_eq!( - unsafe { libc::pthread_stackseg_np(libc::pthread_self(), &mut current_stack) }, + unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, 0 ); - - let stack_ptr = current_stack.ss_sp; - // SAFETY: this is always safe to call. - let stackaddr = if unsafe { libc::pthread_main_np() } == 1 { - // main thread - stack_ptr.addr() - current_stack.ss_size + PAGE_SIZE.load(Ordering::Relaxed) - } else { - // new thread - stack_ptr.addr() - current_stack.ss_size - }; - Some(stack_ptr.with_addr(stackaddr)) + ret = Some(stackaddr); } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "netbsd", - target_os = "hurd", - target_os = "linux", - target_os = "l4re" - ))] - fn get_stack_start() -> Option<*mut libc::c_void> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - - // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + if e == 0 || cfg!(target_os = "freebsd") { // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); + } + ret +} + +fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + + // Ensure stackaddr is page aligned! A parent process might + // have reset RLIMIT_STACK to be non-page aligned. The + // pthread_attr_getstack() reports the usable stack area + // stackaddr < stackaddr + stacksize, so if stackaddr is not + // page-aligned, calculate the fix such that stackaddr < + // new_page_aligned_stackaddr < stackaddr + stacksize + let remainder = stackaddr % page_size; + Some(if remainder == 0 { + stackptr + } else { + stackptr.with_addr(stackaddr + page_size - remainder) + }) +} + +/// # Safety +/// This function must only be called from the main thread, and there must +/// be sufficient stack space remaining to place a stack guard. +unsafe fn install_main_guard() -> Option> { + let page_size = PAGE_SIZE.load(Ordering::Relaxed); + + // this way someone on any unix-y OS can check that all these compile + if cfg!(all(target_os = "linux", not(target_env = "musl"))) { + install_main_guard_linux(page_size) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + install_main_guard_linux_musl(page_size) + } else if cfg!(target_os = "freebsd") { #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut stackaddr = crate::ptr::null_mut(); - let mut stacksize = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackaddr, &mut stacksize) }, - 0 - ); - ret = Some(stackaddr); - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret + return None; + // The FreeBSD code cannot be checked on non-BSDs. + #[cfg(target_os = "freebsd")] + install_main_guard_freebsd(page_size) + } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { + install_main_guard_bsds(page_size) + } else { + // SAFETY: guaranteed by caller. + unsafe { install_main_guard_default(page_size) } } +} - fn stack_start_aligned(page_size: usize) -> Option<*mut libc::c_void> { - let stackptr = get_stack_start()?; - let stackaddr = stackptr.addr(); - - // Ensure stackaddr is page aligned! A parent process might - // have reset RLIMIT_STACK to be non-page aligned. The - // pthread_attr_getstack() reports the usable stack area - // stackaddr < stackaddr + stacksize, so if stackaddr is not - // page-aligned, calculate the fix such that stackaddr < - // new_page_aligned_stackaddr < stackaddr + stacksize - let remainder = stackaddr % page_size; - Some(if remainder == 0 { - stackptr - } else { - stackptr.with_addr(stackaddr + page_size - remainder) - }) +fn install_main_guard_linux(page_size: usize) -> Option> { + // See the corresponding conditional in init(). + // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps + if cfg!(panic = "immediate-abort") { + return None; } - - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard() -> Option> { - let page_size = PAGE_SIZE.load(Ordering::Relaxed); - - // this way someone on any unix-y OS can check that all these compile - if cfg!(all(target_os = "linux", not(target_env = "musl"))) { - install_main_guard_linux(page_size) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - install_main_guard_linux_musl(page_size) - } else if cfg!(target_os = "freebsd") { - #[cfg(not(target_os = "freebsd"))] - return None; - // The FreeBSD code cannot be checked on non-BSDs. - #[cfg(target_os = "freebsd")] - install_main_guard_freebsd(page_size) - } else if cfg!(any(target_os = "netbsd", target_os = "openbsd")) { - install_main_guard_bsds(page_size) - } else { - // SAFETY: guaranteed by caller. - unsafe { install_main_guard_default(page_size) } - } + // Linux doesn't allocate the whole stack right away, and + // the kernel has its own stack-guard mechanism to fault + // when growing too close to an existing mapping. If we map + // our own guard, then the kernel starts enforcing a rather + // large gap above that, rendering much of the possible + // stack space useless. See #43052. + // + // Instead, we'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) +} + +fn install_main_guard_linux_musl(_page_size: usize) -> Option> { + // For the main thread, the musl's pthread_attr_getstack + // returns the current stack size, rather than maximum size + // it can eventually grow to. It cannot be used to determine + // the position of kernel's stack guard. + None +} + +#[cfg(target_os = "freebsd")] +fn install_main_guard_freebsd(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; } - - fn install_main_guard_linux(page_size: usize) -> Option> { - // See the corresponding conditional in init(). - // Avoid stack_start_aligned, which makes slow syscalls to read /proc/self/maps - if cfg!(panic = "immediate-abort") { - return None; - } - // Linux doesn't allocate the whole stack right away, and - // the kernel has its own stack-guard mechanism to fault - // when growing too close to an existing mapping. If we map - // our own guard, then the kernel starts enforcing a rather - // large gap above that, rendering much of the possible - // stack space useless. See #43052. - // - // Instead, we'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) + // FreeBSD's stack autogrows, and optionally includes a guard page + // at the bottom. If we try to remap the bottom of the stack + // ourselves, FreeBSD's guard page moves upwards. So we'll just use + // the builtin guard page. + let stackptr = stack_start_aligned(page_size)?; + let guardaddr = stackptr.addr(); + // Technically the number of guard pages is tunable and controlled + // by the security.bsd.stack_guard_page sysctl. + // By default it is 1, checking once is enough since it is + // a boot time config value. + // FIXME(joboet): this function is only called once, remove the caching. + static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); + + let pages = PAGES.get_or_init(|| { + let mut guard: usize = 0; + let mut size = size_of_val(&guard); + let oid = c"security.bsd.stack_guard_page"; + + let r = unsafe { + libc::sysctlbyname( + oid.as_ptr(), + (&raw mut guard).cast(), + &raw mut size, + ptr::null_mut(), + 0, + ) + }; + if r == 0 { guard } else { 1 } + }); + Some(guardaddr..guardaddr + pages * page_size) +} + +fn install_main_guard_bsds(page_size: usize) -> Option> { + // See the corresponding conditional in install_main_guard_linux(). + if cfg!(panic = "immediate-abort") { + return None; } - - fn install_main_guard_linux_musl(_page_size: usize) -> Option> { - // For the main thread, the musl's pthread_attr_getstack - // returns the current stack size, rather than maximum size - // it can eventually grow to. It cannot be used to determine - // the position of kernel's stack guard. - None + // OpenBSD stack already includes a guard page, and stack is + // immutable. + // NetBSD stack includes the guard page. + // + // We'll just note where we expect rlimit to start + // faulting, so our handler can report "stack overflow", and + // trust that the kernel's own stack guard will work. + let stackptr = stack_start_aligned(page_size)?; + let stackaddr = stackptr.addr(); + Some(stackaddr - page_size..stackaddr) +} + +/// # Safety +/// This function must only be called from the main thread, and there must +/// be sufficient stack space remaining to place a stack guard. +unsafe fn install_main_guard_default(page_size: usize) -> Option> { + // Reallocate the last page of the stack. + // This ensures SIGBUS will be raised on + // stack overflow. + // Systems which enforce strict PAX MPROTECT do not allow + // to mprotect() a mapping with less restrictive permissions + // than the initial mmap() used, so we mmap() here with + // read/write permissions and only then mprotect() it to + // no permissions at all. See issue #50313. + let stackptr = stack_start_aligned(page_size)?; + // SAFETY: + // The memory region from `stackptr..stackptr + page_size` belongs to + // the current thread's stack, and the caller has asserted that there + // is sufficient stack space, which means that this will not overwrite + // any existing allocations. + let result = unsafe { + mmap64( + stackptr, + page_size, + PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON | MAP_FIXED, + -1, + 0, + ) + }; + if result != stackptr || result == MAP_FAILED { + panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); } - #[cfg(target_os = "freebsd")] - fn install_main_guard_freebsd(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // FreeBSD's stack autogrows, and optionally includes a guard page - // at the bottom. If we try to remap the bottom of the stack - // ourselves, FreeBSD's guard page moves upwards. So we'll just use - // the builtin guard page. - let stackptr = stack_start_aligned(page_size)?; - let guardaddr = stackptr.addr(); - // Technically the number of guard pages is tunable and controlled - // by the security.bsd.stack_guard_page sysctl. - // By default it is 1, checking once is enough since it is - // a boot time config value. - // FIXME(joboet): this function is only called once, remove the caching. - static PAGES: crate::sync::OnceLock = crate::sync::OnceLock::new(); - - let pages = PAGES.get_or_init(|| { - let mut guard: usize = 0; - let mut size = size_of_val(&guard); - let oid = c"security.bsd.stack_guard_page"; - - let r = unsafe { - libc::sysctlbyname( - oid.as_ptr(), - (&raw mut guard).cast(), - &raw mut size, - ptr::null_mut(), - 0, - ) - }; - if r == 0 { guard } else { 1 } - }); - Some(guardaddr..guardaddr + pages * page_size) + // SAFETY: + // Since this function is only called on the main thread, the stack will + // not be reused until program exit, so the runtime will never observe + // that part of the stack has been made unusable in this way. + let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; + if result != 0 { + panic!("failed to protect the guard page: {}", io::Error::last_os_error()); } - fn install_main_guard_bsds(page_size: usize) -> Option> { - // See the corresponding conditional in install_main_guard_linux(). - if cfg!(panic = "immediate-abort") { - return None; - } - // OpenBSD stack already includes a guard page, and stack is - // immutable. - // NetBSD stack includes the guard page. - // - // We'll just note where we expect rlimit to start - // faulting, so our handler can report "stack overflow", and - // trust that the kernel's own stack guard will work. - let stackptr = stack_start_aligned(page_size)?; - let stackaddr = stackptr.addr(); - Some(stackaddr - page_size..stackaddr) + let guardaddr = stackptr.addr(); + + Some(guardaddr..guardaddr + page_size) +} + +#[cfg(any( + target_os = "macos", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", +))] +fn current_guard() -> Option> { + let stackptr = get_stack_start()?; + let stackaddr = stackptr.addr(); + Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) +} + +#[cfg(any( + target_os = "android", + target_os = "freebsd", + target_os = "hurd", + target_os = "linux", + target_os = "netbsd", + target_os = "l4re" +))] +fn current_guard() -> Option> { + use crate::pin::pin; + use crate::sys::helpers::COpaque; + + let mut ret = None; + + let mut attr: COpaque = COpaque::uninit(); + if !cfg!(target_os = "freebsd") { + attr = COpaque::zeroed(); } + let attr = pin!(attr); + // FIXME(pin-ergonomics): remove the next line. + let attr = attr.into_ref(); - /// # Safety - /// This function must only be called from the main thread, and there must - /// be sufficient stack space remaining to place a stack guard. - unsafe fn install_main_guard_default(page_size: usize) -> Option> { - // Reallocate the last page of the stack. - // This ensures SIGBUS will be raised on - // stack overflow. - // Systems which enforce strict PAX MPROTECT do not allow - // to mprotect() a mapping with less restrictive permissions - // than the initial mmap() used, so we mmap() here with - // read/write permissions and only then mprotect() it to - // no permissions at all. See issue #50313. - let stackptr = stack_start_aligned(page_size)?; + // SAFETY: + // The attributes object has not been initialized yet and will not be + // moved until destroyed. + #[cfg(target_os = "freebsd")] + assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` is an initialized attribute object that can be written to. + #[cfg(target_os = "freebsd")] + let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; + // SAFETY: + // * calling `pthread_self` is always valid and returns a valid `pthread_t` + // * `attr` can be written to, and will be initialized by this call. + #[cfg(not(target_os = "freebsd"))] + let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; + if e == 0 { + let mut guardsize = 0; // SAFETY: - // The memory region from `stackptr..stackptr + page_size` belongs to - // the current thread's stack, and the caller has asserted that there - // is sufficient stack space, which means that this will not overwrite - // any existing allocations. - let result = unsafe { - mmap64( - stackptr, - page_size, - PROT_READ | PROT_WRITE, - MAP_PRIVATE | MAP_ANON | MAP_FIXED, - -1, - 0, - ) - }; - if result != stackptr || result == MAP_FAILED { - panic!("failed to allocate a guard page: {}", io::Error::last_os_error()); + // `attr` is an initialized attribute object and the pointer is valid + // for writing. + assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); + if guardsize == 0 { + if cfg!(all(target_os = "linux", target_env = "musl")) { + // musl versions before 1.1.19 always reported guard + // size obtained from pthread_attr_get_np as zero. + // Use page size as a fallback. + guardsize = PAGE_SIZE.load(Ordering::Relaxed); + } else { + panic!("there is no guard page"); + } } - + let mut stackptr = crate::ptr::null_mut::(); + let mut size = 0; // SAFETY: - // Since this function is only called on the main thread, the stack will - // not be reused until program exit, so the runtime will never observe - // that part of the stack has been made unusable in this way. - let result = unsafe { mprotect(stackptr, page_size, PROT_NONE) }; - if result != 0 { - panic!("failed to protect the guard page: {}", io::Error::last_os_error()); - } - - let guardaddr = stackptr.addr(); + // `attr` is an initialized attribute object and both the pointers + // are valid for writing. + assert_eq!(unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, 0); - Some(guardaddr..guardaddr + page_size) - } - - #[cfg(any( - target_os = "macos", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ))] - fn current_guard() -> Option> { - let stackptr = get_stack_start()?; let stackaddr = stackptr.addr(); - Some(stackaddr - PAGE_SIZE.load(Ordering::Relaxed)..stackaddr) + ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", target_env = "musl")) { + Some(stackaddr - guardsize..stackaddr) + } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) { + // glibc used to include the guard area within the stack, as noted in the BUGS + // section of `man pthread_attr_getguardsize`. This has been corrected starting + // with glibc 2.27, and in some distro backports, so the guard is now placed at the + // end (below) the stack. There's no easy way for us to know which we have at + // runtime, so we'll just match any fault in the range right above or below the + // stack base to call that fault a stack overflow. + Some(stackaddr - guardsize..stackaddr + guardsize) + } else { + Some(stackaddr..stackaddr + guardsize) + }; } - - #[cfg(any( - target_os = "android", - target_os = "freebsd", - target_os = "hurd", - target_os = "linux", - target_os = "netbsd", - target_os = "l4re" - ))] - fn current_guard() -> Option> { - use crate::pin::pin; - use crate::sys::helpers::COpaque; - - let mut ret = None; - - let mut attr: COpaque = COpaque::uninit(); - if !cfg!(target_os = "freebsd") { - attr = COpaque::zeroed(); - } - let attr = pin!(attr); - // FIXME(pin-ergonomics): remove the next line. - let attr = attr.into_ref(); - + if e == 0 || cfg!(target_os = "freebsd") { // SAFETY: - // The attributes object has not been initialized yet and will not be - // moved until destroyed. - #[cfg(target_os = "freebsd")] - assert_eq!(unsafe { libc::pthread_attr_init(attr.get()) }, 0); - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` is an initialized attribute object that can be written to. - #[cfg(target_os = "freebsd")] - let e = unsafe { libc::pthread_attr_get_np(libc::pthread_self(), attr.get()) }; - // SAFETY: - // * calling `pthread_self` is always valid and returns a valid `pthread_t` - // * `attr` can be written to, and will be initialized by this call. - #[cfg(not(target_os = "freebsd"))] - let e = unsafe { libc::pthread_getattr_np(libc::pthread_self(), attr.get()) }; - if e == 0 { - let mut guardsize = 0; - // SAFETY: - // `attr` is an initialized attribute object and the pointer is valid - // for writing. - assert_eq!(unsafe { libc::pthread_attr_getguardsize(attr.get(), &mut guardsize) }, 0); - if guardsize == 0 { - if cfg!(all(target_os = "linux", target_env = "musl")) { - // musl versions before 1.1.19 always reported guard - // size obtained from pthread_attr_get_np as zero. - // Use page size as a fallback. - guardsize = PAGE_SIZE.load(Ordering::Relaxed); - } else { - panic!("there is no guard page"); - } - } - let mut stackptr = crate::ptr::null_mut::(); - let mut size = 0; - // SAFETY: - // `attr` is an initialized attribute object and both the pointers - // are valid for writing. - assert_eq!( - unsafe { libc::pthread_attr_getstack(attr.get(), &mut stackptr, &mut size) }, - 0 - ); - - let stackaddr = stackptr.addr(); - ret = if cfg!(any(target_os = "freebsd", target_os = "netbsd", target_os = "hurd")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", target_env = "musl")) { - Some(stackaddr - guardsize..stackaddr) - } else if cfg!(all(target_os = "linux", any(target_env = "gnu", target_env = "uclibc"))) - { - // glibc used to include the guard area within the stack, as noted in the BUGS - // section of `man pthread_attr_getguardsize`. This has been corrected starting - // with glibc 2.27, and in some distro backports, so the guard is now placed at the - // end (below) the stack. There's no easy way for us to know which we have at - // runtime, so we'll just match any fault in the range right above or below the - // stack base to call that fault a stack overflow. - Some(stackaddr - guardsize..stackaddr + guardsize) - } else { - Some(stackaddr..stackaddr + guardsize) - }; - } - if e == 0 || cfg!(target_os = "freebsd") { - // SAFETY: - // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or - // by `pthread_attr_get_np`, and is not used after this point. - assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); - } - ret + // `attr` was initialized either by `pthread_attr_init` (FreeBSD) or + // by `pthread_attr_get_np`, and is not used after this point. + assert_eq!(unsafe { libc::pthread_attr_destroy(attr.get()) }, 0); } + ret +} diff --git a/library/std/src/sys/pal/unix/stack_overflow/mod.rs b/library/std/src/sys/pal/unix/stack_overflow/mod.rs index f9541e182156c..0a070a20d432f 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/mod.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/mod.rs @@ -57,8 +57,7 @@ mod thread_info; target_os = "illumos", ) ))] -mod imp { -} +mod imp {} // This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses // several symbols that might lead to rejections from the App Store, namely @@ -82,9 +81,7 @@ mod imp { target_os = "cygwin", )) ))] -mod imp { -} +mod imp {} #[cfg(target_os = "cygwin")] -mod imp { -} +mod imp {} From 6387f4b9bcde5a76f05411c9b441396f2458690c Mon Sep 17 00:00:00 2001 From: joboet Date: Wed, 23 Sep 2026 13:56:19 +0200 Subject: [PATCH 0704/1309] std: split stack overflow module --- .../src/sys/pal/unix/stack_overflow/mod.rs | 100 +++++++----------- 1 file changed, 40 insertions(+), 60 deletions(-) diff --git a/library/std/src/sys/pal/unix/stack_overflow/mod.rs b/library/std/src/sys/pal/unix/stack_overflow/mod.rs index 0a070a20d432f..d60fe4b5bbec8 100644 --- a/library/std/src/sys/pal/unix/stack_overflow/mod.rs +++ b/library/std/src/sys/pal/unix/stack_overflow/mod.rs @@ -1,6 +1,46 @@ #![cfg_attr(test, allow(dead_code))] #![forbid(unsafe_op_in_unsafe_fn)] +cfg_select! { + // This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses + // several symbols that might lead to rejections from the App Store, namely + // `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. + // + // This might be overly cautious, though it is also what Swift does (and they + // usually have fewer qualms about forwards compatibility, since the runtime + // is shipped with the OS): + // + // + // miri doesn't model signals nor stack overflows and this code has some + // synchronization properties that we don't want to expose to user code, + // hence we disable it on miri. + all( + not(miri), + any( + target_os = "linux", + target_os = "freebsd", + target_os = "hurd", + target_os = "macos", + target_os = "netbsd", + target_os = "openbsd", + target_os = "solaris", + target_os = "illumos", + ) + ) => { + mod handler_signal; + mod thread_info; + use handler_signal as imp; + } + target_os = "cygwin" => { + mod handler_cygwin; + use handler_cygwin as imp; + } + _ => { + mod handler_none; + use handler_none as imp; + } +} + pub use self::imp::init; use self::imp::{drop_handler, make_handler}; @@ -25,63 +65,3 @@ impl Drop for Handler { } } } - -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ), -))] -mod thread_info; - -// miri doesn't model signals nor stack overflows and this code has some -// synchronization properties that we don't want to expose to user code, -// hence we disable it on miri. -#[cfg(all( - not(miri), - any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - ) -))] -mod imp {} - -// This is intentionally not enabled on iOS/tvOS/watchOS/visionOS, as it uses -// several symbols that might lead to rejections from the App Store, namely -// `sigaction`, `sigaltstack`, `sysctlbyname`, `mmap`, `munmap` and `mprotect`. -// -// This might be overly cautious, though it is also what Swift does (and they -// usually have fewer qualms about forwards compatibility, since the runtime -// is shipped with the OS): -// -#[cfg(any( - miri, - not(any( - target_os = "linux", - target_os = "freebsd", - target_os = "hurd", - target_os = "macos", - target_os = "netbsd", - target_os = "openbsd", - target_os = "solaris", - target_os = "illumos", - target_os = "cygwin", - )) -))] -mod imp {} - -#[cfg(target_os = "cygwin")] -mod imp {} From 4778ae5040c10568d98e9bff8283057d9cd8ac3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 14:09:50 +0200 Subject: [PATCH 0705/1309] Mark `rustfmt` as being managed by Josh --- src/doc/rustc-dev-guide/src/external-repos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 26c7e2e02bd56..fe0c0385d5f63 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -42,13 +42,13 @@ you should include fixes for those in the rustc PR as well. * Using `git subtree` * `clippy` ([sync guide](https://doc.rust-lang.org/nightly/clippy/development/infrastructure/sync.html#performing-the-sync-from-rust-langrust-to-clippy)) * `portable-simd` ([sync script](https://github.com/rust-lang/portable-simd/blob/master/subtree-sync.sh)) - * `rustfmt` * `rustc_codegen_gcc` ([sync guide](https://github.com/rust-lang/rustc_codegen_gcc/blob/master/doc/subtree.md)) * Using the [josh](#synchronizing-a-josh-subtree) tool * `miri` * `rust-analyzer` * `rustc_codegen_cranelift` * `rustc-dev-guide` + * `rustfmt` * `compiler-builtins` * `stdarch` From 693bf504c707e17f7fc7450277be10c193a1465d Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Wed, 23 Sep 2026 14:27:49 +0200 Subject: [PATCH 0706/1309] Update deprecated rustc_hir imports --- Cargo.lock | 10 ++++++- compiler/rustc_const_eval/Cargo.toml | 1 + .../src/check_consts/check.rs | 20 ++++++------- .../rustc_const_eval/src/check_consts/mod.rs | 3 +- .../rustc_const_eval/src/check_consts/ops.rs | 2 +- .../src/check_consts/post_drop_elaboration.rs | 2 +- .../src/check_consts/qualifs.rs | 2 +- .../src/const_eval/fn_queries.rs | 3 +- .../src/const_eval/machine.rs | 7 +++-- .../src/const_eval/type_info.rs | 2 +- .../rustc_const_eval/src/interpret/call.rs | 2 +- .../src/util/caller_location.rs | 2 +- compiler/rustc_hir/src/lib.rs | 11 +++----- compiler/rustc_hir_analysis/Cargo.toml | 1 + .../src/check/always_applicable.rs | 3 +- .../rustc_hir_analysis/src/check/check.rs | 4 +-- .../src/check/compare_eii.rs | 4 +-- .../rustc_hir_analysis/src/check/entry.rs | 3 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 2 +- compiler/rustc_hir_analysis/src/check/mod.rs | 2 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 6 ++-- .../src/coherence/builtin.rs | 2 +- .../src/coherence/builtin/coerce_shared.rs | 2 +- .../src/coherence/inherent_impls.rs | 2 +- .../rustc_hir_analysis/src/coherence/mod.rs | 2 +- .../src/coherence/unsafety.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 3 +- .../src/collect/clauses_of.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 5 ++-- .../src/hir_ty_lowering/dyn_trait.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_hir_analysis/src/outlives/dump.rs | 2 +- .../rustc_hir_analysis/src/variance/dump.rs | 2 +- compiler/rustc_incremental/Cargo.toml | 1 + .../rustc_incremental/src/assert_dep_graph.rs | 3 +- .../rustc_incremental/src/persist/clean.rs | 7 ++--- compiler/rustc_lint/Cargo.toml | 1 + compiler/rustc_lint/src/autorefs.rs | 3 +- compiler/rustc_lint/src/builtin.rs | 28 +++++++++---------- compiler/rustc_lint/src/c_void_returns.rs | 2 +- compiler/rustc_lint/src/context.rs | 5 +++- compiler/rustc_lint/src/dangling.rs | 5 ++-- .../src/deref_into_dyn_supertrait.rs | 2 +- .../rustc_lint/src/disallowed_pass_by_ref.rs | 3 +- .../src/for_loops_over_fallibles.rs | 2 +- compiler/rustc_lint/src/foreign_modules.rs | 2 +- compiler/rustc_lint/src/gpukernel_abi.rs | 3 +- .../rustc_lint/src/interior_mutable_consts.rs | 3 +- compiler/rustc_lint/src/internal.rs | 3 +- .../src/multiple_supertrait_upcastable.rs | 2 +- compiler/rustc_lint/src/non_fmt_panic.rs | 2 +- compiler/rustc_lint/src/non_local_def.rs | 3 +- compiler/rustc_lint/src/nonstandard_style.rs | 4 +-- compiler/rustc_lint/src/passes.rs | 6 ++-- compiler/rustc_lint/src/ptr_nulls.rs | 3 +- compiler/rustc_lint/src/runtime_symbols.rs | 2 +- compiler/rustc_lint/src/shadowed_into_iter.rs | 2 +- compiler/rustc_lint/src/traits.rs | 2 +- compiler/rustc_lint/src/types.rs | 5 ++-- compiler/rustc_lint/src/unused/must_use.rs | 5 ++-- compiler/rustc_metadata/Cargo.toml | 1 + compiler/rustc_metadata/src/creader.rs | 3 +- compiler/rustc_metadata/src/eii.rs | 3 +- compiler/rustc_metadata/src/native_libs.rs | 3 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 ++-- .../src/rmeta/decoder/cstore_impl.rs | 2 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 11 ++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 18 ++++++------ .../rustc_metadata/src/rmeta/parameterized.rs | 18 ++++++------ compiler/rustc_mir_dataflow/Cargo.toml | 2 +- .../src/framework/graphviz.rs | 3 +- compiler/rustc_mir_dataflow/src/rustc_peek.rs | 3 +- compiler/rustc_monomorphize/Cargo.toml | 1 + compiler/rustc_monomorphize/src/collector.rs | 4 +-- compiler/rustc_monomorphize/src/lib.rs | 2 +- .../rustc_monomorphize/src/partitioning.rs | 4 +-- compiler/rustc_passes/src/check_export.rs | 2 +- compiler/rustc_passes/src/dead.rs | 3 +- compiler/rustc_passes/src/entry.rs | 3 +- compiler/rustc_passes/src/input_stats.rs | 2 +- compiler/rustc_privacy/Cargo.toml | 1 + compiler/rustc_privacy/src/lib.rs | 3 +- .../rustc_resolve/src/build_reduced_graph.rs | 3 +- .../rustc_resolve/src/diagnostics/impls.rs | 8 ++++-- .../rustc_resolve/src/late/diagnostics.rs | 8 +++--- compiler/rustc_resolve/src/lib.rs | 4 +-- compiler/rustc_resolve/src/macros.rs | 5 ++-- compiler/rustc_trait_selection/Cargo.toml | 1 + .../src/error_reporting/infer/mod.rs | 5 ++-- .../error_reporting/infer/note_and_explain.rs | 5 ++-- .../src/error_reporting/traits/ambiguity.rs | 2 +- .../src/error_reporting/traits/call_kind.rs | 2 +- .../traits/fulfillment_errors.rs | 7 +++-- .../src/error_reporting/traits/mod.rs | 2 +- .../traits/on_unimplemented.rs | 4 +-- .../src/error_reporting/traits/suggestions.rs | 2 +- compiler/rustc_trait_selection/src/infer.rs | 2 +- .../src/solve/delegate.rs | 2 +- .../src/solve/fulfill/derive_errors.rs | 2 +- .../src/traits/dyn_compatibility.rs | 2 +- .../src/traits/effects.rs | 2 +- .../rustc_trait_selection/src/traits/misc.rs | 5 ++-- .../src/traits/project.rs | 2 +- .../src/traits/select/candidate_assembly.rs | 2 +- .../src/traits/select/confirmation.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../rustc_trait_selection/src/traits/util.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_ty_utils/src/abi.rs | 3 +- compiler/rustc_ty_utils/src/layout.rs | 5 ++-- compiler/rustc_ty_utils/src/needs_drop.rs | 2 +- 111 files changed, 225 insertions(+), 197 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index a1a43f47965c0..5f35ce252b78e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3872,6 +3872,7 @@ dependencies = [ "rustc_abi", "rustc_apfloat", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4129,6 +4130,7 @@ dependencies = [ "rustc_abi", "rustc_arena", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_feature", @@ -4204,6 +4206,7 @@ name = "rustc_incremental" version = "0.0.0" dependencies = [ "rand 0.9.3", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_fs_util", @@ -4325,6 +4328,7 @@ dependencies = [ "rustc_apfloat", "rustc_ast", "rustc_ast_pretty", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_data_structures", "rustc_errors", @@ -4403,6 +4407,7 @@ dependencies = [ "odht", "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_crate_store", "rustc_data_structures", @@ -4493,10 +4498,10 @@ dependencies = [ "polonius-engine", "regex", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_graphviz", - "rustc_hir", "rustc_index", "rustc_macros", "rustc_middle", @@ -4539,6 +4544,7 @@ version = "0.0.0" dependencies = [ "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4656,6 +4662,7 @@ name = "rustc_privacy" version = "0.0.0" dependencies = [ "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4913,6 +4920,7 @@ dependencies = [ "itertools", "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_crate_store", "rustc_data_structures", "rustc_errors", diff --git a/compiler/rustc_const_eval/Cargo.toml b/compiler/rustc_const_eval/Cargo.toml index 296368c42034b..8d14d86581a66 100644 --- a/compiler/rustc_const_eval/Cargo.toml +++ b/compiler/rustc_const_eval/Cargo.toml @@ -9,6 +9,7 @@ either = "1" rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_const_eval/src/check_consts/check.rs b/compiler/rustc_const_eval/src/check_consts/check.rs index c9217856252d8..192bb8556a75d 100644 --- a/compiler/rustc_const_eval/src/check_consts/check.rs +++ b/compiler/rustc_const_eval/src/check_consts/check.rs @@ -5,11 +5,12 @@ use std::num::NonZero; use std::ops::Deref; use std::{assert_matches, mem}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{ConstStability, StabilityLevel, find_attr}; use rustc_errors::{Diag, ErrorGuaranteed}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir::visit::Visitor; @@ -427,7 +428,7 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { /// Check the const stability of the given item (fn or trait). fn check_callee_stability(&mut self, def_id: DefId) { match self.tcx.lookup_const_stability(def_id) { - Some(hir::ConstStability { level: hir::StabilityLevel::Stable { .. }, .. }) => { + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. } None => { @@ -443,8 +444,8 @@ impl<'mir, 'tcx> Checker<'mir, 'tcx> { }); } } - Some(hir::ConstStability { - level: hir::StabilityLevel::Unstable { implied_by: implied_feature, issue, .. }, + Some(ConstStability { + level: StabilityLevel::Unstable { implied_by: implied_feature, issue, .. }, feature, .. }) => { @@ -858,8 +859,8 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { }); } } - Some(hir::ConstStability { - level: hir::StabilityLevel::Unstable { .. }, + Some(ConstStability { + level: StabilityLevel::Unstable { .. }, feature, .. }) => { @@ -878,10 +879,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> { const_stable_indirect, }); } - Some(hir::ConstStability { - level: hir::StabilityLevel::Stable { .. }, - .. - }) => { + Some(ConstStability { level: StabilityLevel::Stable { .. }, .. }) => { // All good. Note that a `#[rustc_const_stable]` intrinsic (meaning it // can be *directly* invoked from stable const code) does not always // have the `#[rustc_intrinsic_const_stable_indirect]` attribute (which controls diff --git a/compiler/rustc_const_eval/src/check_consts/mod.rs b/compiler/rustc_const_eval/src/check_consts/mod.rs index df7d0a2182428..99b6062a23ac4 100644 --- a/compiler/rustc_const_eval/src/check_consts/mod.rs +++ b/compiler/rustc_const_eval/src/check_consts/mod.rs @@ -4,9 +4,10 @@ //! has interior mutability or needs to be dropped, as well as the visitor that emits errors when //! it finds operations that are invalid in a certain context. +use rustc_attr_ir::find_attr; use rustc_errors::DiagCtxtHandle; +use rustc_hir as hir; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::mir; use rustc_middle::ty::{self, PolyFnSig, TyCtxt}; use rustc_span::{Symbol, bug}; diff --git a/compiler/rustc_const_eval/src/check_consts/ops.rs b/compiler/rustc_const_eval/src/check_consts/ops.rs index 1d1a99d2c6095..ace12201abf02 100644 --- a/compiler/rustc_const_eval/src/check_consts/ops.rs +++ b/compiler/rustc_const_eval/src/check_consts/ops.rs @@ -1,10 +1,10 @@ //! Concrete error types for all operations which may be invalid in a certain const context. use hir::ConstContext; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, MultiSpan, msg}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::{ImplSource, Obligation, ObligationCause}; diff --git a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs index 34d4ce9f9f2c2..e8ddff445133e 100644 --- a/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs +++ b/compiler/rustc_const_eval/src/check_consts/post_drop_elaboration.rs @@ -1,4 +1,4 @@ -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::{self, BasicBlock, Location}; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_const_eval/src/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/check_consts/qualifs.rs index 9331c50b84b37..4d1a72808972b 100644 --- a/compiler/rustc_const_eval/src/check_consts/qualifs.rs +++ b/compiler/rustc_const_eval/src/check_consts/qualifs.rs @@ -5,8 +5,8 @@ // FIXME(const_trait_impl): This API should be really reworked. It's dangerously general for // having basically only two use-cases that act in different ways. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_middle::mir; use rustc_middle::mir::*; diff --git a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs index 8267cb66e9e15..4da9d79a8434a 100644 --- a/compiler/rustc_const_eval/src/const_eval/fn_queries.rs +++ b/compiler/rustc_const_eval/src/const_eval/fn_queries.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{ Constness, ExprKind, ForeignItemKind, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, - Node, TraitItem, TraitItemKind, VariantData, find_attr, + Node, TraitItem, TraitItemKind, VariantData, }; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index c0617c19263e7..843cd7cb4930d 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -4,10 +4,11 @@ use std::{fmt, mem}; use rustc_abi::{Align, FIRST_VARIANT, FieldIdx, Size, VariantIdx}; use rustc_ast::Mutability; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, CRATE_HIR_ID, find_attr}; +use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; use rustc_middle::mir; use rustc_middle::mir::AssertMessage; @@ -394,7 +395,7 @@ impl<'tcx> CompileTimeMachine<'tcx> { #[inline(always)] /// Find the first stack frame that is within the current crate, if any. /// Otherwise, return the crate's HirId - pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> hir::HirId { + pub fn best_lint_scope(&self, tcx: TyCtxt<'tcx>) -> HirId { self.stack.iter().find_map(|frame| frame.lint_root(tcx)).unwrap_or(CRATE_HIR_ID) } } diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index f0875952a5039..0bece36c64ed0 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -3,7 +3,7 @@ mod adt; use std::borrow::Cow; use rustc_abi::{ExternAbi, FieldIdx}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, FnHeader, FnSigKind, FnSigTys, ScalarInt, Ty, TyCtxt}; use rustc_span::{Symbol, span_bug, sym}; diff --git a/compiler/rustc_const_eval/src/interpret/call.rs b/compiler/rustc_const_eval/src/interpret/call.rs index 3bf020009beed..c7615a216312e 100644 --- a/compiler/rustc_const_eval/src/interpret/call.rs +++ b/compiler/rustc_const_eval/src/interpret/call.rs @@ -6,8 +6,8 @@ use std::borrow::Cow; use either::{Left, Right}; use rustc_abi::{self as abi, ExternAbi, FieldIdx, Integer, VariantIdx}; +use rustc_attr_ir::find_attr; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::mir; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, AdtDef, FieldDef, Instance, Ty, VariantDef}; diff --git a/compiler/rustc_const_eval/src/util/caller_location.rs b/compiler/rustc_const_eval/src/util/caller_location.rs index 99220a23de4fc..c76da6c6a36c8 100644 --- a/compiler/rustc_const_eval/src/util/caller_location.rs +++ b/compiler/rustc_const_eval/src/util/caller_location.rs @@ -1,5 +1,5 @@ use rustc_abi::FieldIdx; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::mir; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{Symbol, bug}; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 5855c1126a971..5a23d23e4f622 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -24,17 +24,14 @@ pub mod pat_util; mod stable_hash_impls; mod target_impls; -// FIXME: Remove this use tree, replace by `rustc_attr_ir` imports -#[doc(hidden)] -pub use attrs::{ - Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, StableSince, - UnstableReason, target::Target, -}; #[doc(no_inline)] pub use hir::*; // FIXME: Remove this use tree, replace by `rustc_attr_ir` imports #[doc(hidden)] -pub use rustc_attr_ir::{self as attrs, find_attr}; +pub use rustc_attr_ir::{ + self as attrs, Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, + StableSince, find_attr, target::Target, +}; pub use rustc_hir_id::*; pub use rustc_span::def_id; diff --git a/compiler/rustc_hir_analysis/Cargo.toml b/compiler/rustc_hir_analysis/Cargo.toml index 06092f53272ce..a250ed77bb8c2 100644 --- a/compiler/rustc_hir_analysis/Cargo.toml +++ b/compiler/rustc_hir_analysis/Cargo.toml @@ -13,6 +13,7 @@ itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_feature = { path = "../rustc_feature" } diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index b098a6c186457..e805ccb4a1d89 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -4,6 +4,7 @@ //! //! This is necessary for `Drop` and negative impls to be well-formed. +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; @@ -442,7 +443,7 @@ fn check_drop_xor_pin_drop<'tcx>( } (Some(span), None) => { if tcx.adt_def(adt_def_id).is_pin_project() { - let pin_v2_span = rustc_hir::find_attr!(tcx, adt_def_id, PinV2(attr) => *attr); + let pin_v2_span = find_attr!(tcx, adt_def_id, PinV2(attr) => *attr); let adt_name = tcx.item_name(adt_def_id); return Err(tcx.dcx().emit_err(crate::diagnostics::PinV2WithoutPinDrop { span, diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 924041c399ef1..f35b901633fcb 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -2,12 +2,12 @@ use std::cell::LazyCell; use std::ops::ControlFlow; use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt}; +use rustc_attr_ir::ReprAttr::ReprPacked; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; use rustc_hir as hir; -use rustc_hir::attrs::ReprAttr::ReprPacked; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::{Node, find_attr, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; diff --git a/compiler/rustc_hir_analysis/src/check/compare_eii.rs b/compiler/rustc_hir_analysis/src/check/compare_eii.rs index c9fd3da24fe07..6e22ce3d84b76 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_eii.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_eii.rs @@ -6,12 +6,12 @@ use std::borrow::Cow; use std::iter; +use rustc_attr_ir::{EiiImplResolution, find_attr}; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Applicability, E0806, struct_span_code_err}; -use rustc_hir::attrs::EiiImplResolution; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, FnSig, HirId, ItemKind, find_attr}; +use rustc_hir::{self as hir, FnSig, HirId, ItemKind}; use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{ObligationCause, ObligationCauseCode, TraitErrors}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; diff --git a/compiler/rustc_hir_analysis/src/check/entry.rs b/compiler/rustc_hir_analysis/src/check/entry.rs index a115ccba9ad08..17123376159de 100644 --- a/compiler/rustc_hir_analysis/src/check/entry.rs +++ b/compiler/rustc_hir_analysis/src/check/entry.rs @@ -1,7 +1,8 @@ use std::ops::Not; +use rustc_attr_ir::find_attr; use rustc_hir as hir; -use rustc_hir::{Node, find_attr}; +use rustc_hir::Node; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::TraitErrors; use rustc_middle::ty::{self, TyCtxt, TypingMode, Unnormalized}; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index b566f6b04bf41..bcab1457e0655 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -1,8 +1,8 @@ //! Type-checking for the `#[rustc_intrinsic]` intrinsics that the compiler exposes. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::DiagMessage; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index fa2b3e9f25342..00700713afc88 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -76,9 +76,9 @@ use std::num::NonZero; pub use check::check_abi; use rustc_abi::VariantIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_errors::{ErrorGuaranteed, pluralize, struct_span_code_err}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_index::bit_set::DenseBitSet; diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index bde17c39e2bc4..0a1787a23c893 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -4,16 +4,16 @@ use std::ops::{ControlFlow, Deref}; use hir::intravisit::{self, Visitor}; use rustc_abi::{ExternAbi, ScalableElt}; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{EiiDecl, EiiImpl, EiiImplResolution, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::transitive_relation::TransitiveRelationBuilder; use rustc_errors::codes::*; use rustc_errors::{Applicability, ErrorGuaranteed, msg, pluralize, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{AmbigArg, ItemKind, find_attr}; +use rustc_hir::{AmbigArg, ItemKind}; use rustc_infer::infer::outlives::env::OutlivesEnvironment; use rustc_infer::infer::{BoundRegionConversionTime, SolverRegionConstraint, TyCtxtInferExt}; use rustc_infer::traits::{PredicateObligations, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index e9adabc7ca4bb..efed5994f63fe 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -3,11 +3,11 @@ use std::collections::BTreeMap; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir as hir; use rustc_hir::ItemKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::{self, InferCtxt, RegionResolutionError, SubregionOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index 77330e4fa3b34..e405e149c8eef 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -1,7 +1,7 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; use rustc_hir::ItemKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitErrors}; diff --git a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs index 94234cd185a02..591ff35becf81 100644 --- a/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs +++ b/compiler/rustc_hir_analysis/src/coherence/inherent_impls.rs @@ -7,10 +7,10 @@ //! `tcx.inherent_impls(def_id)`). That value, however, //! is computed by selecting an idea from this table. +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_middle::ty::fast_reject::{SimplifiedType, TreatParams, simplify_type}; use rustc_middle::ty::{self, CrateInherentImpls, Ty, TyCtxt}; use rustc_span::{ErrorGuaranteed, bug}; diff --git a/compiler/rustc_hir_analysis/src/coherence/mod.rs b/compiler/rustc_hir_analysis/src/coherence/mod.rs index e3f4f8d0507d3..c1ca62d333e64 100644 --- a/compiler/rustc_hir_analysis/src/coherence/mod.rs +++ b/compiler/rustc_hir_analysis/src/coherence/mod.rs @@ -5,9 +5,9 @@ // done by the orphan and overlap modules. Then we build up various // mappings. That mapping code resides here. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_middle::query::Providers; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, elaborate}; diff --git a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs index 18ba46ff08913..cfca879abe8f1 100644 --- a/compiler/rustc_hir_analysis/src/coherence/unsafety.rs +++ b/compiler/rustc_hir_analysis/src/coherence/unsafety.rs @@ -1,10 +1,10 @@ //! Unsafety checker: every impl either implements a trait defined in this //! crate or pertains to a type defined in this crate. +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir::Safety; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::ty::ImplPolarity::*; use rustc_middle::ty::print::PrintTraitRefExt as _; use rustc_middle::ty::{ImplTraitHeader, TraitDef, TyCtxt}; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 02a7fa6f98791..8f693221b0fd2 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -19,6 +19,7 @@ use std::{assert_matches, debug_assert_matches, iter}; use rustc_abi::{ExternAbi, Size}; use rustc_ast::Recovered; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_errors::{ @@ -27,7 +28,7 @@ use rustc_errors::{ use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::intravisit::{InferKind, Visitor}; -use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind, find_attr}; +use rustc_hir::{self as hir, GenericParamKind, HirId, Node, PreciseCapturingArgKind}; use rustc_infer::infer::{InferCtxt, SolverRegionConstraint, TyCtxtInferExt}; use rustc_infer::traits::{DynCompatibilityViolation, ObligationCause}; use rustc_lint_defs::builtin::REPR_C_ENUMS_LARGER_THAN_INT; diff --git a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs index 78884bab033bf..ae384a67ee6aa 100644 --- a/compiler/rustc_hir_analysis/src/collect/clauses_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/clauses_of.rs @@ -1,11 +1,11 @@ use std::assert_matches; use hir::Node; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxIndexSet; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_middle::ty::{ self, GenericClauses, ImplTraitInTraitData, Ty, TyCtxt, TypeVisitable, TypeVisitor, Upcast, }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 011ca64b7f32a..4bfe93f5949f7 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -1,13 +1,14 @@ use std::ops::ControlFlow; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::struct_span_code_err; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::PolyTraitRef; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{PolyTraitRef, find_attr}; use rustc_middle::ty::{ self as ty, IsSuggestable, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, Upcast, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index cab8fcf556edb..a3cba8ce15fda 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -1,11 +1,11 @@ use rustc_ast::TraitObjectSyntax; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, StashKey, Suggestions, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e7ecde09ce27b..be608ced39a48 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -25,6 +25,7 @@ use std::{assert_matches, slice}; use rustc_abi::FIRST_VARIANT; use rustc_ast::LitKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::sso::SsoHashSet; use rustc_data_structures::thin_vec::ThinVec; @@ -33,7 +34,6 @@ use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, ErrorGuaranteed, FatalError, StashKey, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{self as hir, AnonConst, GenericArg, GenericArgs, HirId}; diff --git a/compiler/rustc_hir_analysis/src/outlives/dump.rs b/compiler/rustc_hir_analysis/src/outlives/dump.rs index c0314c378fbdd..6cb585c6c97c5 100644 --- a/compiler/rustc_hir_analysis/src/outlives/dump.rs +++ b/compiler/rustc_hir_analysis/src/outlives/dump.rs @@ -1,4 +1,4 @@ -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::{bug, sym}; diff --git a/compiler/rustc_hir_analysis/src/variance/dump.rs b/compiler/rustc_hir_analysis/src/variance/dump.rs index 7963f5da0e870..aa05e512dc2af 100644 --- a/compiler/rustc_hir_analysis/src/variance/dump.rs +++ b/compiler/rustc_hir_analysis/src/variance/dump.rs @@ -1,8 +1,8 @@ use std::fmt::Write; +use rustc_attr_ir::find_attr; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::{GenericArgs, TyCtxt}; fn format_variances(tcx: TyCtxt<'_>, def_id: LocalDefId) -> String { diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml index ac4d7d8e1cbc0..bf331f41b0e09 100644 --- a/compiler/rustc_incremental/Cargo.toml +++ b/compiler/rustc_incremental/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rand = "0.9.0" +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_fs_util = { path = "../rustc_fs_util" } diff --git a/compiler/rustc_incremental/src/assert_dep_graph.rs b/compiler/rustc_incremental/src/assert_dep_graph.rs index be23c3466f184..8147e3c3ae550 100644 --- a/compiler/rustc_incremental/src/assert_dep_graph.rs +++ b/compiler/rustc_incremental/src/assert_dep_graph.rs @@ -37,12 +37,11 @@ use std::env; use std::fs::{self, File}; use std::io::Write; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::graph::linked_graph::{Direction, INCOMING, NodeIndex, OUTGOING}; use rustc_graphviz as dot; use rustc_hir as hir; -use rustc_hir::Attribute; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::dep_graph::{DepKind, DepNode, DepNodeFilter, EdgeFilter, RetainedDepGraph}; diff --git a/compiler/rustc_incremental/src/persist/clean.rs b/compiler/rustc_incremental/src/persist/clean.rs index a311832e62d96..b6402181fba12 100644 --- a/compiler/rustc_incremental/src/persist/clean.rs +++ b/compiler/rustc_incremental/src/persist/clean.rs @@ -19,14 +19,11 @@ //! Errors are reported if we are in the suitable configuration but //! the required condition is not met. +use rustc_attr_ir::{Attribute, AttributeKind, RustcCleanAttribute, find_attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::unord::UnordSet; -use rustc_hir::attrs::{AttributeKind, RustcCleanAttribute}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{ - Attribute, ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, find_attr, - intravisit, -}; +use rustc_hir::{ImplItemKind, ItemKind as HirItem, Node as HirNode, TraitItemKind, intravisit}; use rustc_middle::dep_graph::{DepKind, DepNode, dep_kind_from_label}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_lint/Cargo.toml b/compiler/rustc_lint/Cargo.toml index a672f242449e4..0024d8b26f1fb 100644 --- a/compiler/rustc_lint/Cargo.toml +++ b/compiler/rustc_lint/Cargo.toml @@ -10,6 +10,7 @@ rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_ast = { path = "../rustc_ast" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_lint/src/autorefs.rs b/compiler/rustc_lint/src/autorefs.rs index 728937b762110..0064e8c6b3a23 100644 --- a/compiler/rustc_lint/src/autorefs.rs +++ b/compiler/rustc_lint/src/autorefs.rs @@ -1,5 +1,6 @@ use rustc_ast::{BorrowKind, UnOp}; -use rustc_hir::{Expr, ExprKind, Mutability, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{Expr, ExprKind, Mutability}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::adjustment::{ Adjust, Adjustment, AutoBorrow, DerefAdjustKind, OverloadedDeref, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 7ccbef12af4c6..bba993ee3f052 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -21,15 +21,15 @@ use rustc_ast::tokenstream::{TokenStream, TokenTree}; use rustc_ast::visit::{FnCtxt, FnKind}; use rustc_ast::{self as ast, *}; use rustc_ast_pretty::pprust::expr_to_string; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{AttributeKind, DocAttribute, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diagnostic, msg}; use rustc_feature::GateIssue; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{AttributeKind, DocAttribute}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId}; use rustc_hir::intravisit::FnKind as HirFnKind; -use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateOrigin}; // Lints from rustc_lint_defs pub use rustc_lint_defs::builtin::*; use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw, impl_lint_pass}; @@ -239,13 +239,13 @@ impl EarlyLintPass for UnsafeCode { } ast::ItemKind::MacroDef(..) => { - if let Some(hir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe(span))) = - AttributeParser::parse_limited_sym( - cx.builder.sess(), - &it.attrs, - &[sym::allow_internal_unsafe], - ) - { + if let Some(rustc_attr_ir::Attribute::Parsed(AttributeKind::AllowInternalUnsafe( + span, + ))) = AttributeParser::parse_limited_sym( + cx.builder.sess(), + &it.attrs, + &[sym::allow_internal_unsafe], + ) { self.report_unsafe(cx, span, BuiltinUnsafe::AllowInternalUnsafe); } } @@ -307,12 +307,12 @@ pub struct MissingDoc; impl_lint_pass!(MissingDoc => [MISSING_DOCS]); -fn has_doc(attr: &hir::Attribute) -> bool { - if matches!(attr, hir::Attribute::Parsed(AttributeKind::DocComment { .. })) { +fn has_doc(attr: &rustc_attr_ir::Attribute) -> bool { + if matches!(attr, rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. })) { return true; } - if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr + if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr && matches!(d.as_ref(), DocAttribute { hidden: Some(..), .. }) { return true; @@ -1030,7 +1030,7 @@ declare_lint_pass!( ); impl<'tcx> LateLintPass<'tcx> for UnstableFeatures { - fn check_attributes(&mut self, cx: &LateContext<'_>, attrs: &[hir::Attribute]) { + fn check_attributes(&mut self, cx: &LateContext<'_>, attrs: &[rustc_attr_ir::Attribute]) { if let Some(features) = find_attr!(attrs, Feature(features, _) => features) { for feature in features { cx.emit_span_lint(UNSTABLE_FEATURES, feature.span, BuiltinUnstableFeatures); diff --git a/compiler/rustc_lint/src/c_void_returns.rs b/compiler/rustc_lint/src/c_void_returns.rs index 1358dcea262e8..da2c52d019923 100644 --- a/compiler/rustc_lint/src/c_void_returns.rs +++ b/compiler/rustc_lint/src/c_void_returns.rs @@ -1,6 +1,6 @@ use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::FnKind; diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index 68b2e2a3b6e7b..a7ded8a82b5dc 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -842,7 +842,10 @@ impl<'tcx> LateContext<'tcx> { /// be used for pretty-printing HIR by rustc_hir_pretty. pub fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { let has_attr = |id: hir::HirId| -> bool { - self.tcx.hir_attrs(id).iter().any(hir::Attribute::is_prefix_attr_for_suggestions) + self.tcx + .hir_attrs(id) + .iter() + .any(rustc_attr_ir::Attribute::is_prefix_attr_for_suggestions) }; expr.precedence(&has_attr) } diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index c272dd4496984..d06292d62730f 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -1,9 +1,10 @@ use rustc_ast::visit::{visit_opt, walk_list}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::Res; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{FnKind, Visitor, walk_expr}; -use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind, find_attr}; +use rustc_hir::{Block, Body, Expr, ExprKind, FnDecl, FnRetTy, TyKind}; use rustc_lint_defs::{declare_lint, impl_lint_pass}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs index 165c8f58a09f9..506ab027d8771 100644 --- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs +++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty; use rustc_span::{Ident, sym}; diff --git a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs index 92350ecf60a21..5ecc4d4b07548 100644 --- a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs +++ b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs @@ -1,5 +1,6 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def::Res; -use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind, find_attr}; +use rustc_hir::{self as hir, AmbigArg, GenericArg, PathSegment, QPath, TyKind}; use rustc_lint_defs::{declare_lint_pass, declare_tool_lint}; use rustc_middle::ty; diff --git a/compiler/rustc_lint/src/for_loops_over_fallibles.rs b/compiler/rustc_lint/src/for_loops_over_fallibles.rs index df0455470feb7..bb0f2a2793ab8 100644 --- a/compiler/rustc_lint/src/for_loops_over_fallibles.rs +++ b/compiler/rustc_lint/src/for_loops_over_fallibles.rs @@ -1,6 +1,6 @@ use hir::{Expr, Pat}; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::ObligationCause; use rustc_lint_defs::{declare_lint, declare_lint_pass}; diff --git a/compiler/rustc_lint/src/foreign_modules.rs b/compiler/rustc_lint/src/foreign_modules.rs index 7dae504804752..e6092a1497a0f 100644 --- a/compiler/rustc_lint/src/foreign_modules.rs +++ b/compiler/rustc_lint/src/foreign_modules.rs @@ -1,8 +1,8 @@ use rustc_abi::FIRST_VARIANT; +use rustc_attr_ir::find_attr; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::find_attr; use rustc_lint_defs::declare_lint; use rustc_middle::query::Providers; use rustc_middle::ty::{self, AdtDef, Instance, Ty, TyCtxt}; diff --git a/compiler/rustc_lint/src/gpukernel_abi.rs b/compiler/rustc_lint/src/gpukernel_abi.rs index 64f0744dffed4..05f41cd6fdf48 100644 --- a/compiler/rustc_lint/src/gpukernel_abi.rs +++ b/compiler/rustc_lint/src/gpukernel_abi.rs @@ -1,7 +1,8 @@ use std::iter; use rustc_abi::ExternAbi; -use rustc_hir::{self as hir, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir as hir; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable}; use rustc_span::Span; diff --git a/compiler/rustc_lint/src/interior_mutable_consts.rs b/compiler/rustc_lint/src/interior_mutable_consts.rs index ff48749a2e6a9..4d0557d5e9b54 100644 --- a/compiler/rustc_lint/src/interior_mutable_consts.rs +++ b/compiler/rustc_lint/src/interior_mutable_consts.rs @@ -1,5 +1,6 @@ +use rustc_attr_ir::find_attr; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Expr, ExprKind, ItemKind, Node, find_attr}; +use rustc_hir::{Expr, ExprKind, ItemKind, Node}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::adjustment::Adjust; diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 9746b52dda41e..2646131bb59cd 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -3,10 +3,11 @@ use rustc_ast as ast; use rustc_ast::{Pat, PatKind, Path}; +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::Res; use rustc_hir::def_id::DefId; -use rustc_hir::{Expr, ExprKind, HirId, find_attr}; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint_defs::{declare_lint_pass, declare_tool_lint}; use rustc_middle::ty::{self, ClausePolarity, GenericArgsRef}; use rustc_span::hygiene::{ExpnKind, MacroKind}; diff --git a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs index ae07295db512f..75552ab759fd5 100644 --- a/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs +++ b/compiler/rustc_lint/src/multiple_supertrait_upcastable.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::Unnormalized; diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index cb811421be5c6..fbe8eb837f852 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -1,7 +1,7 @@ use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, msg}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::TyCtxtInferExt; use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw}; diff --git a/compiler/rustc_lint/src/non_local_def.rs b/compiler/rustc_lint/src/non_local_def.rs index 01ddc172f274d..e4f082d49cba7 100644 --- a/compiler/rustc_lint/src/non_local_def.rs +++ b/compiler/rustc_lint/src/non_local_def.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_errors::{MultiSpan, msg}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind, find_attr}; +use rustc_hir::{Body, HirId, Item, ItemKind, Node, Path, TyKind}; use rustc_lint_defs::{declare_lint, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::{DefId, LOCAL_CRATE}; diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index b7bb7865ea080..551843947b758 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,13 +1,13 @@ use rustc_abi::ExternAbi; use rustc_ast as ast; +use rustc_attr_ir::{AttributeKind, ReprAttr, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, ReprAttr}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind, find_attr}; +use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty::AssocContainer; diff --git a/compiler/rustc_lint/src/passes.rs b/compiler/rustc_lint/src/passes.rs index 6b7955db483f1..98ab44c37e26a 100644 --- a/compiler/rustc_lint/src/passes.rs +++ b/compiler/rustc_lint/src/passes.rs @@ -40,9 +40,9 @@ macro_rules! late_lint_methods { fn check_field_def(a: &'tcx rustc_hir::FieldDef<'tcx>); fn check_variant(a: &'tcx rustc_hir::Variant<'tcx>); fn check_path(a: &rustc_hir::Path<'tcx>, b: rustc_hir::HirId); - fn check_attribute(a: &'tcx rustc_hir::Attribute); - fn check_attributes(a: &'tcx [rustc_hir::Attribute]); - fn check_attributes_post(a: &'tcx [rustc_hir::Attribute]); + fn check_attribute(a: &'tcx rustc_attr_ir::Attribute); + fn check_attributes(a: &'tcx [rustc_attr_ir::Attribute]); + fn check_attributes_post(a: &'tcx [rustc_attr_ir::Attribute]); ]); ) } diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 19c1a8a1b665c..0c4dba0893fc4 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -1,5 +1,6 @@ use rustc_ast::LitKind; -use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::RawPtr; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_lint/src/runtime_symbols.rs b/compiler/rustc_lint/src/runtime_symbols.rs index df52150799522..f0e186c34ca0f 100644 --- a/compiler/rustc_lint/src/runtime_symbols.rs +++ b/compiler/rustc_lint/src/runtime_symbols.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::CanonicalSymbol; +use rustc_attr_ir::CanonicalSymbol; use rustc_hir::def_id::LocalDefId; use rustc_hir::{self as hir, FnSig, ForeignItemKind}; use rustc_infer::infer::DefineOpaqueTypes; diff --git a/compiler/rustc_lint/src/shadowed_into_iter.rs b/compiler/rustc_lint/src/shadowed_into_iter.rs index 0468142a987ca..021499f6b712c 100644 --- a/compiler/rustc_lint/src/shadowed_into_iter.rs +++ b/compiler/rustc_lint/src/shadowed_into_iter.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::{declare_lint, fcw, impl_lint_pass}; use rustc_middle::ty::{self, Ty}; diff --git a/compiler/rustc_lint/src/traits.rs b/compiler/rustc_lint/src/traits.rs index 2d6d83d4e0776..1e2c012ee337a 100644 --- a/compiler/rustc_lint/src/traits.rs +++ b/compiler/rustc_lint/src/traits.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::{self as hir, AmbigArg}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_span::sym; diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index d62fca02cf4cf..eab950f4d66a8 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -2,9 +2,10 @@ use std::iter; use rustc_abi::{BackendRepr, TagEncoding, Variants, WrappingRange}; use rustc_ast as ast; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::{Expr, ExprKind, HirId, find_attr}; +use rustc_hir::{Expr, ExprKind, HirId}; use rustc_lint_defs::{declare_lint, declare_lint_pass, impl_lint_pass}; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index a637e8cf3b0f4..dab842a688ae1 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -1,10 +1,11 @@ use std::iter; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::pluralize; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, find_attr}; use rustc_infer::traits::util::elaborate; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::ty::consts::ConstExt; diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a2ef8454ed6a6..e036c2d7e23c9 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -10,6 +10,7 @@ libloading = "0.9.0" odht = { version = "0.3.1", features = ["nightly"] } rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index c828ba13b8af6..ad8264078348b 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -14,7 +14,6 @@ use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::UnordMap; use rustc_expand::base::SyntaxExtension; -use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId}; use rustc_hir::definitions::Definitions; use rustc_index::IndexVec; @@ -89,7 +88,7 @@ pub enum LoadedMacro { MacroDef { def: MacroDef, ident: Ident, - attrs: Vec, + attrs: Vec, span: Span, edition: Edition, }, diff --git a/compiler/rustc_metadata/src/eii.rs b/compiler/rustc_metadata/src/eii.rs index 47e982a315395..d7942e2085522 100644 --- a/compiler/rustc_metadata/src/eii.rs +++ b/compiler/rustc_metadata/src/eii.rs @@ -1,7 +1,6 @@ +use rustc_attr_ir::{EiiDecl, EiiImpl, EiiImplResolution, find_attr}; use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::attrs::{EiiDecl, EiiImpl, EiiImplResolution}; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::query::LocalCrate; use rustc_middle::ty::TyCtxt; use rustc_span::bug; diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs index 1c7d865e41234..6cb6ad0015f92 100644 --- a/compiler/rustc_metadata/src/native_libs.rs +++ b/compiler/rustc_metadata/src/native_libs.rs @@ -1,12 +1,11 @@ use rustc_abi::ExternAbi; +use rustc_attr_ir::{PeImportNameType, find_attr}; use rustc_attr_parsing::eval_config_entry; use rustc_crate_store::{ DllCallingConvention, DllImport, DllImportSymbolType, ForeignModule, NativeLib, }; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::PeImportNameType; use rustc_hir::def::DefKind; -use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::query::LocalCrate; use rustc_middle::ty::{self, List, Ty, TyCtxt}; diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index a73e94dd076e7..2f41ca1a77511 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -7,6 +7,8 @@ use std::{io, mem}; pub(super) use cstore_impl::provide; use rustc_ast as ast; +use rustc_attr_ir::CanonicalSymbols; +use rustc_attr_ir::diagnostic_items::DiagnosticItems; use rustc_crate_store::{CrateSource, ExternCrate}; use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxIndexMap; @@ -16,8 +18,6 @@ use rustc_data_structures::unhash::UnhashMap; use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind}; use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro}; use rustc_hir::Safety; -use rustc_hir::attrs::CanonicalSymbols; -use rustc_hir::attrs::diagnostic_items::DiagnosticItems; use rustc_hir::def::Res; use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE}; use rustc_hir::definitions::{DefPath, DefPathData}; @@ -1424,7 +1424,7 @@ impl CrateMetadata { &self, tcx: TyCtxt<'_>, id: DefIndex, - ) -> impl Iterator { + ) -> impl Iterator { self.root .tables .attributes diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index f1a4ed09b3516..79bfb15eefac1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -2,9 +2,9 @@ use std::any::Any; use std::mem; use std::sync::Arc; +use rustc_attr_ir::Deprecation; use rustc_crate_store::{CrateStore, ExternCrate}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::attrs::Deprecation; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, LOCAL_CRATE}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8481db9d3c523..1031af39f272b 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -7,16 +7,15 @@ use std::path::{Path, PathBuf}; use std::rc::Rc; use std::sync::Arc; +use rustc_attr_ir::{AttributeKind, EncodeCrossCrate, find_attr}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; use rustc_data_structures::sync::{par_for_each_in, par_join}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::thousands::usize_with_underscores; use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, EncodeCrossCrate}; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; -use rustc_hir::find_attr; use rustc_hir_pretty::id_to_string; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; use rustc_middle::middle::dependency_format::Linkage; @@ -872,9 +871,9 @@ struct AnalyzeAttrState { /// visibility: this is a piece of data that can be computed once per defid, and not once per /// attribute. Some attributes would only be usable downstream if they are public. #[inline] -fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState) -> bool { +fn analyze_attr(attr: &rustc_attr_ir::Attribute, state: &mut AnalyzeAttrState) -> bool { let mut should_encode = false; - if let hir::Attribute::Parsed(p) = attr + if let rustc_attr_ir::Attribute::Parsed(p) = attr && p.encode_cross_crate() == EncodeCrossCrate::No { // Attributes not marked encode-cross-crate don't need to be encoded for downstream crates. @@ -883,14 +882,14 @@ fn analyze_attr(attr: &hir::Attribute, state: &mut AnalyzeAttrState) -> bool { { // Lint attributes don't need to be encoded for downstream crates. // FIXME remove this when #152369 is re-merged - } else if let hir::Attribute::Parsed(AttributeKind::DocComment { .. }) = attr { + } else if let rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. }) = attr { // We keep all doc comments reachable to rustdoc because they might be "imported" into // downstream crates if they use `#[doc(inline)]` to copy an item's documentation into // their own. if state.is_exported { should_encode = true; } - } else if let hir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { + } else if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { should_encode = true; if d.hidden.is_some() { state.is_doc_hidden = true; diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index f89be5368da9a..99429647bd26c 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -9,16 +9,16 @@ pub use encoder::{EncodedMetadata, encode_metadata, rendered_const}; pub(crate) use parameterized::ParameterizedOverTcx; use rustc_abi::{FieldIdx, ReprOptions, VariantIdx}; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{Stability, StrippedCfgItem}; use rustc_crate_store::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir as hir; -use rustc_hir::attrs::StrippedCfgItem; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir::PreciseCapturingArgKind; use rustc_hir::def::{CtorKind, DefKind, MacroKinds}; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIndex, DefPathHash, StableCrateId}; use rustc_hir::definitions::DefKey; -use rustc_hir::{PreciseCapturingArgKind, attrs}; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_macros::{ @@ -192,7 +192,7 @@ type ExpnHashTable = LazyTable>>; #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct ProcMacroData { proc_macro_decls_static: DefIndex, - stability: Option, + stability: Option, macros: LazyArray<(DefIndex, LazyValue)>, } @@ -417,7 +417,7 @@ define_tables! { impl_is_fully_generic_for_reflection: Table, - optional: - attributes: Table>, + attributes: Table>, // For non-reexported names in a module every name is associated with a separate `DefId`, // so we can take their names, visibilities etc from other encoded tables. module_children_non_reexports: Table>, @@ -426,10 +426,10 @@ define_tables! { visibility: Table>>, def_span: Table>, def_ident_span: Table>, - lookup_stability: Table>, - lookup_const_stability: Table>, - lookup_default_body_stability: Table>, - lookup_deprecation_entry: Table>, + lookup_stability: Table>, + lookup_const_stability: Table>, + lookup_default_body_stability: Table>, + lookup_deprecation_entry: Table>, explicit_clauses_of: Table>>, generics_of: Table>, type_of: Table>>>, diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index 4eb922446b71b..a6a937a56ed50 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -85,24 +85,24 @@ trivially_parameterized_over_tcx! { crate::rmeta::VariantData, rustc_abi::ReprOptions, rustc_ast::DelimArgs, + rustc_attr_ir::Attribute, + rustc_attr_ir::ConstStability, + rustc_attr_ir::DefaultBodyStability, + rustc_attr_ir::Deprecation, + rustc_attr_ir::EiiDecl, + rustc_attr_ir::EiiImpl, + rustc_attr_ir::Stability, + rustc_attr_ir::StrippedCfgItem, + rustc_attr_ir::lang_items::LangItem, rustc_crate_store::ForeignModule, rustc_crate_store::LinkagePreference, rustc_crate_store::NativeLib, - rustc_hir::Attribute, - rustc_hir::ConstStability, rustc_hir::Constness, rustc_hir::CoroutineKind, - rustc_hir::DefaultBodyStability, rustc_hir::Defaultness, rustc_hir::OpaqueTyOrigin, rustc_hir::PreciseCapturingArgKind, rustc_hir::Safety, - rustc_hir::Stability, - rustc_hir::attrs::Deprecation, - rustc_hir::attrs::EiiDecl, - rustc_hir::attrs::EiiImpl, - rustc_hir::attrs::StrippedCfgItem, - rustc_hir::attrs::lang_items::LangItem, rustc_hir::def::DefKind, rustc_hir::def_id::DefId, rustc_hir::def_id::DefIndex, diff --git a/compiler/rustc_mir_dataflow/Cargo.toml b/compiler/rustc_mir_dataflow/Cargo.toml index 156caa7030a03..c1ef4d96f385b 100644 --- a/compiler/rustc_mir_dataflow/Cargo.toml +++ b/compiler/rustc_mir_dataflow/Cargo.toml @@ -8,10 +8,10 @@ edition = "2024" polonius-engine = "0.13.0" regex = "1" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_graphviz = { path = "../rustc_graphviz" } -rustc_hir = { path = "../rustc_hir" } rustc_index = { path = "../rustc_index" } rustc_macros = { path = "../rustc_macros" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs index af185e868fe9c..b1e4bbe98b86b 100644 --- a/compiler/rustc_mir_dataflow/src/framework/graphviz.rs +++ b/compiler/rustc_mir_dataflow/src/framework/graphviz.rs @@ -7,9 +7,8 @@ use std::sync::LazyLock; use std::{io, ops, str}; use regex::Regex; +use rustc_attr_ir::{BorrowckGraphvizFormatKind, RustcMirKind, find_attr}; use rustc_graphviz as dot; -use rustc_hir::attrs::{BorrowckGraphvizFormatKind, RustcMirKind}; -use rustc_hir::find_attr; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{ self, BasicBlock, Body, Location, MirDumper, TerminatorEdges, graphviz_safe_def_name, traversal, diff --git a/compiler/rustc_mir_dataflow/src/rustc_peek.rs b/compiler/rustc_mir_dataflow/src/rustc_peek.rs index 35c601f09acd4..0e14d1f830492 100644 --- a/compiler/rustc_mir_dataflow/src/rustc_peek.rs +++ b/compiler/rustc_mir_dataflow/src/rustc_peek.rs @@ -1,5 +1,4 @@ -use rustc_hir::attrs::RustcMirKind; -use rustc_hir::find_attr; +use rustc_attr_ir::{RustcMirKind, find_attr}; use rustc_middle::mir::{self, Body, Local, Location}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{Span, sym}; diff --git a/compiler/rustc_monomorphize/Cargo.toml b/compiler/rustc_monomorphize/Cargo.toml index ce5b90e2593a8..b2edfed1f5ce2 100644 --- a/compiler/rustc_monomorphize/Cargo.toml +++ b/compiler/rustc_monomorphize/Cargo.toml @@ -7,6 +7,7 @@ edition = "2024" # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs index 3e16760ba3c00..bfe3ba91bb6bc 100644 --- a/compiler/rustc_monomorphize/src/collector.rs +++ b/compiler/rustc_monomorphize/src/collector.rs @@ -208,12 +208,12 @@ use std::cell::OnceCell; use std::ops::ControlFlow; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::{Lock, par_for_each_in}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir as hir; -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; diff --git a/compiler/rustc_monomorphize/src/lib.rs b/compiler/rustc_monomorphize/src/lib.rs index 16a4a04e8eb39..ec52a837e1a51 100644 --- a/compiler/rustc_monomorphize/src/lib.rs +++ b/compiler/rustc_monomorphize/src/lib.rs @@ -4,7 +4,7 @@ #![feature(once_cell_get_mut)] // tidy-alphabetical-end -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::query::TyCtxtAt; use rustc_middle::traits; use rustc_middle::ty::adjustment::CustomCoerceUnsized; diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 32de7a3d5f7ab..43ce9634cc203 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -98,12 +98,12 @@ use std::fs::{self, File}; use std::io::Write; use std::path::{Path, PathBuf}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sync::par_join; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{InlineAttr, Linkage}; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdSet, LOCAL_CRATE}; use rustc_hir::definitions::DefPathDataName; diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index bd2cf272faa35..15a1084686718 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -2,11 +2,11 @@ use std::iter; use std::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_hir::intravisit::{self, Visitor}; use rustc_middle::hir::nested_filter; use rustc_middle::middle::privacy::{EffectiveVisibility, Level}; diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index 1800d4fc6c25e..bd1bdf7cc0646 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -9,12 +9,13 @@ use std::sync::atomic::Ordering; use hir::def_id::{LocalDefIdMap, LocalDefIdSet}; use rustc_abi::FieldIdx; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_errors::{ErrorGuaranteed, MultiSpan}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath, find_attr}; +use rustc_hir::{self as hir, ForeignItemId, ItemId, Node, PatKind, QPath}; use rustc_lint_defs::builtin::{DEAD_CODE, DEAD_CODE_PUB_IN_BINARY}; use rustc_lint_defs::{self as lint, Lint, StableLintExpectationId}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; diff --git a/compiler/rustc_passes/src/entry.rs b/compiler/rustc_passes/src/entry.rs index 3b0ee311efc22..8f933bb7a3b6d 100644 --- a/compiler/rustc_passes/src/entry.rs +++ b/compiler/rustc_passes/src/entry.rs @@ -1,7 +1,8 @@ use rustc_ast::entry::EntryPointType; +use rustc_attr_ir::find_attr; use rustc_errors::codes::*; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{ItemId, Node, find_attr}; +use rustc_hir::{ItemId, Node}; use rustc_middle::query::Providers; use rustc_middle::ty::TyCtxt; use rustc_session::config::{EntryFnType, sigpipe}; diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index 961e6e63a81da..f8ee98e28685d 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -547,7 +547,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_assoc_item_constraint(self, constraint) } - fn visit_attribute(&mut self, attr: &'v hir::Attribute) { + fn visit_attribute(&mut self, attr: &'v rustc_attr_ir::Attribute) { self.record("Attribute", None, attr); } diff --git a/compiler/rustc_privacy/Cargo.toml b/compiler/rustc_privacy/Cargo.toml index e5fdcc6e0749e..6cd997cce27c5 100644 --- a/compiler/rustc_privacy/Cargo.toml +++ b/compiler/rustc_privacy/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 97475c8fdccf0..9406f23155399 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -16,6 +16,7 @@ use diagnostics::{ UnnamedItemIsPrivate, }; use rustc_ast::visit::{VisitorResult, try_visit}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::indexmap::IndexSet; use rustc_data_structures::intern::Interned; @@ -23,7 +24,7 @@ use rustc_errors::{MultiSpan, listify}; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, InferKind, Visitor}; -use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind, find_attr}; +use rustc_hir::{self as hir, AmbigArg, ForeignItemId, ItemId, OwnerId, PatKind}; use rustc_lint_defs::builtin::{ EXPORTED_PRIVATE_DEPENDENCIES, PRIVATE_BOUNDS, PRIVATE_INTERFACES, UNNAMEABLE_TYPES, }; diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 24f9f56c0a3a6..7ddf916bc7b6b 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -13,12 +13,11 @@ use rustc_ast::{ DelegationSource, Fn, ForeignItem, ForeignItemKind, Inline, Item, ItemKind, NodeId, StaticItem, StmtKind, TraitAlias, TyAlias, }; +use rustc_attr_ir::{Attribute, AttributeKind, MacroUseArgs}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sync::WriteGuard; use rustc_expand::base::{ResolverExpand, SyntaxExtension, SyntaxExtensionKind}; -use rustc_hir::Attribute; -use rustc_hir::attrs::{AttributeKind, MacroUseArgs}; use rustc_hir::def::{self, *}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::bit_set::DenseBitSet; diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 8357372c40839..331c948c66403 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -9,6 +9,10 @@ use rustc_ast::{ join_path_idents, }; use rustc_ast_pretty::pprust; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_attr_ir::{ + Attribute, AttributeKind, CfgEntry, Stability, StabilityLevel, StrippedCfgItem, find_attr, +}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; @@ -18,12 +22,10 @@ use rustc_errors::{ pluralize, struct_span_code_err, }; use rustc_feature::BUILTIN_ATTRIBUTES; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; -use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; +use rustc_hir::PrimTy; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{Attribute, PrimTy, Stability, StabilityLevel, find_attr}; use rustc_lint_defs::builtin::{ ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES, AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index d7a527f365c02..3dbb1b7fff662 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -11,6 +11,8 @@ use rustc_ast::{ PathSegment, Ty, TyKind, }; use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string}; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordItems; use rustc_errors::codes::*; @@ -18,12 +20,10 @@ use rustc_errors::{ Applicability, Diag, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize, struct_span_code_err, }; -use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FormatArgs}; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; -use rustc_hir::{MissingLifetimeKind, PrimTy, find_attr}; +use rustc_hir::{MissingLifetimeKind, PrimTy}; use rustc_lint_defs::builtin::{SINGLE_USE_LIFETIMES, UNUSED_LIFETIMES}; use rustc_middle::ty; use rustc_session::Session; @@ -1287,7 +1287,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // confused by them. continue; } - if let Some(d) = hir::find_attr!(r.tcx, did, Doc(d) => d) + if let Some(d) = find_attr!(r.tcx, did, Doc(d) => d) && d.aliases.contains_key(&item_name) { return Some(did); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ecbcb0d609a3c..7c80a892fa131 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -43,6 +43,7 @@ use rustc_ast::{ self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, GenericArg, GenericArgs, Generics, NodeId, Path, attr, }; +use rustc_attr_ir::{StrippedCfgItem, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; @@ -51,12 +52,11 @@ use rustc_data_structures::unord::{UnordItems, UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::{BUILTIN_ATTRIBUTES, Features}; -use rustc_hir::attrs::StrippedCfgItem; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{self, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap}; -use rustc_hir::{PrimTy, TraitCandidate, find_attr}; +use rustc_hir::{PrimTy, TraitCandidate}; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::PRIVATE_MACRO_USE; use rustc_metadata::creader::CStore; diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 24a52d4143493..3442d946b4f30 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -6,6 +6,7 @@ use std::sync::Arc; use rustc_ast::{self as ast, Crate, DelegationSuffixes, NodeId}; use rustc_ast_pretty::pprust; +use rustc_attr_ir::{Attribute, AttributeKind, CfgEntry, StabilityLevel, StrippedCfgItem}; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::sync::RwLock; use rustc_errors::{Applicability, StashKey}; @@ -17,10 +18,8 @@ use rustc_expand::compile_declarative_macro; use rustc_expand::expand::{ AstFragment, AstFragmentKind, Invocation, InvocationKind, SupportsMacroExpansion, }; -use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem}; use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind}; use rustc_hir::def_id::{CrateNum, DefId, LocalDefId}; -use rustc_hir::{Attribute, StabilityLevel}; use rustc_lint_defs::builtin::{ LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNUSED_MACRO_RULES, UNUSED_MACROS, }; @@ -1213,7 +1212,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { &self, macro_def: &ast::MacroDef, ident: Ident, - attrs: &[rustc_hir::Attribute], + attrs: &[rustc_attr_ir::Attribute], span: Span, node_id: NodeId, edition: Edition, diff --git a/compiler/rustc_trait_selection/Cargo.toml b/compiler/rustc_trait_selection/Cargo.toml index 8eecfda24e557..92ff046af8241 100644 --- a/compiler/rustc_trait_selection/Cargo.toml +++ b/compiler/rustc_trait_selection/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index f554620c57208..d83df2dfdf291 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -51,12 +51,13 @@ use std::path::PathBuf; use std::{cmp, fmt, iter}; use rustc_abi::ExternAbi; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, DiagStyledString, IntoDiagArg, StringPart, pluralize}; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs}; +use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::extension; use rustc_middle::traits::PatternOriginExpr; diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs index de829a5c6ae1a..7b5bd350fe8f9 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs @@ -1,8 +1,9 @@ +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability::{MachineApplicable, MaybeIncorrect}; use rustc_errors::{Diag, MultiSpan, pluralize}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 261dc5594bd24..05e1cb6210b50 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -1,8 +1,8 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag, E0283, E0284, E0790, MultiSpan, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_hir::intravisit::Visitor as _; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs index 3b1feeaa1424a..4142febc7844f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/call_kind.rs @@ -2,7 +2,7 @@ //! as well as errors when attempting to call a non-const function in a const //! context. -use rustc_hir::attrs::lang_items::{self, LangItem}; +use rustc_attr_ir::lang_items::{self, LangItem}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index bc5bf38ec9266..4cb5465b5bbee 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -6,6 +6,9 @@ use std::path::PathBuf; use rustc_ast::ast::LitKind; use rustc_ast::{LitIntType, TraitObjectSyntax}; +use rustc_attr_ir::diagnostic::CustomDiagnostic; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; @@ -13,11 +16,9 @@ use rustc_errors::{ Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, StringPart, Sublevel, Suggestions, msg, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::diagnostic::CustomDiagnostic; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, Node, expr_needs_parens, find_attr}; +use rustc_hir::{self as hir, Node, expr_needs_parens}; use rustc_infer::infer::{InferOk, TypeTrace}; use rustc_infer::traits::solve::Goal; use rustc_infer::traits::{ImplSource, TraitErrors}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index c120df4e2c3ef..a7a907e8f4d94 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -7,11 +7,11 @@ pub mod suggestions; use std::{fmt, iter}; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{ExternCrate, ExternCrateSource}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{Applicability, Diag, E0038, E0276, MultiSpan, struct_span_code_err}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, AmbigArg}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index 2967dfb64e710..cc5375cb334c1 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -1,9 +1,9 @@ use std::path::PathBuf; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; +use rustc_attr_ir::find_attr; use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; use rustc_hir::def_id::LocalDefId; -use rustc_hir::find_attr; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind}; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 47652c22a7ebc..32237e9f60ca3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -6,12 +6,12 @@ use std::{debug_assert_matches, iter}; use itertools::{EitherOrBoth, Itertools}; use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::{self, LangItem}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, MultiSpan, Style, SuggestionStyle, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::{self, LangItem}; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_trait_selection/src/infer.rs b/compiler/rustc_trait_selection/src/infer.rs index 802393a22b7e5..7e1ad3234440e 100644 --- a/compiler/rustc_trait_selection/src/infer.rs +++ b/compiler/rustc_trait_selection/src/infer.rs @@ -1,6 +1,6 @@ use std::fmt::Debug; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def_id::DefId; pub use rustc_infer::infer::*; use rustc_infer::traits::TraitErrors; diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index c67a4bdd329b0..e1043d53fa6fc 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -3,9 +3,9 @@ use std::fmt::Debug; use std::mem; use std::ops::{ControlFlow, Deref}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::CRATE_HIR_ID; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::Namespace; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE}; use rustc_infer::infer::canonical::query_response::make_query_region_constraints; diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 7f704d41ab6c5..d30421a762ea9 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -1,6 +1,6 @@ use std::ops::ControlFlow; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::solve::{CandidateSource, GoalSource, MaybeCause}; use rustc_infer::traits::{ diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index e964c09420b0e..59f3ebfcce33e 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -6,9 +6,9 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::FatalError; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_middle::query::Providers; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/traits/effects.rs b/compiler/rustc_trait_selection/src/traits/effects.rs index dda72a45d5764..5892e376126eb 100644 --- a/compiler/rustc_trait_selection/src/traits/effects.rs +++ b/compiler/rustc_trait_selection/src/traits/effects.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::traits::{ ImplDerivedHostCause, ImplSource, Obligation, ObligationCause, ObligationCauseCode, diff --git a/compiler/rustc_trait_selection/src/traits/misc.rs b/compiler/rustc_trait_selection/src/traits/misc.rs index 658248144b529..69fc873c4aae9 100644 --- a/compiler/rustc_trait_selection/src/traits/misc.rs +++ b/compiler/rustc_trait_selection/src/traits/misc.rs @@ -1,8 +1,9 @@ //! Miscellaneous type-system utilities that are too small to deserve their own modules. use rustc_ast::Mutability; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; use rustc_infer::traits::TraitErrors; use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; @@ -122,7 +123,7 @@ pub fn type_allowed_to_implement_const_param_ty<'tcx>( if !tcx.features().adt_const_params() { for variant in adt.variants() { if variant.is_field_list_non_exhaustive() { - let attr_span = match hir::find_attr!(tcx, variant.def_id, hir::attrs::AttributeKind::NonExhaustive(span) => *span) + let attr_span = match find_attr!(tcx, variant.def_id, NonExhaustive(span) => *span) { Some(sp) => sp, None => bug!("non_exhaustive variant missing NonExhaustive attribute"), diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index c1f4e74119744..6f7c46089632f 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -2,9 +2,9 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::sso::SsoHashSet; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::DefineOpaqueTypes; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 120f83c14b5c7..9ebfb4d5ecda0 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -9,8 +9,8 @@ use std::ops::ControlFlow; use hir::def_id::DefId; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_infer::traits::{Obligation, PolyTraitObligation, PredicateObligation, SelectionError}; use rustc_middle::ty::fast_reject::DeepRejectCtxt; diff --git a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs index b410070123da7..81517955181ee 100644 --- a/compiler/rustc_trait_selection/src/traits/select/confirmation.rs +++ b/compiler/rustc_trait_selection/src/traits/select/confirmation.rs @@ -9,7 +9,7 @@ use std::ops::ControlFlow; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk}; use rustc_infer::traits::ObligationCauseCode; use rustc_middle::traits::{BuiltinImplSource, SignatureMismatchData}; diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index f8619fcd120a2..7ee6eec3e1c44 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -8,10 +8,10 @@ use std::fmt::{self, Display}; use std::ops::ControlFlow; use hir::def::DefKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::Diag; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::BoundRegionConversionTime::{self, HigherRankedType}; use rustc_infer::infer::DefineOpaqueTypes; diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs index 5685bd8ef55f8..c60ebc4758ead 100644 --- a/compiler/rustc_trait_selection/src/traits/util.rs +++ b/compiler/rustc_trait_selection/src/traits/util.rs @@ -1,7 +1,7 @@ use std::collections::VecDeque; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::PolyTraitObligation; diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 175183ce633ab..ba33270c2adba 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -5,8 +5,8 @@ use std::iter; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_infer::traits::{ObligationCauseCode, PredicateObligation, PredicateObligations}; use rustc_middle::ty::{ self, DelayedSet, GenericArgsRef, PredicateProxy, Term, TermKind, Ty, TyCtxt, diff --git a/compiler/rustc_ty_utils/src/abi.rs b/compiler/rustc_ty_utils/src/abi.rs index bcba5839926db..011c6fde740ac 100644 --- a/compiler/rustc_ty_utils/src/abi.rs +++ b/compiler/rustc_ty_utils/src/abi.rs @@ -2,8 +2,9 @@ use std::{assert_matches, iter}; use rustc_abi::Primitive::Pointer; use rustc_abi::{Align, BackendRepr, ExternAbi, PointerKind, Scalar, Size}; +use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; -use rustc_hir::{self as hir, find_attr}; +use rustc_hir as hir; use rustc_middle::middle::deduced_param_attrs::DeducedParamAttrs; use rustc_middle::query::Providers; use rustc_middle::ty::layout::{ diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index 43af74d10aba7..ef1241266cac6 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -1,6 +1,5 @@ use std::range::{RangeFrom, RangeToInclusive}; -use hir::def_id::DefId; use rustc_abi as abi; use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; @@ -9,10 +8,10 @@ use rustc_abi::{ LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; +use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_hashes::Hash64; -use rustc_hir as hir; -use rustc_hir::find_attr; +use rustc_hir::def_id::DefId; use rustc_index::{Idx as _, IndexVec}; use rustc_middle::query::Providers; use rustc_middle::traits::ObligationCause; diff --git a/compiler/rustc_ty_utils/src/needs_drop.rs b/compiler/rustc_ty_utils/src/needs_drop.rs index 529abd1d41415..094cf5aec0bd1 100644 --- a/compiler/rustc_ty_utils/src/needs_drop.rs +++ b/compiler/rustc_ty_utils/src/needs_drop.rs @@ -1,8 +1,8 @@ //! Check whether a type has (potentially) non-trivial drop glue. +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::query::Providers; use rustc_middle::ty::util::{AlwaysRequiresDrop, needs_drop_components}; use rustc_middle::ty::{self, EarlyBinder, GenericArgsRef, Ty, TyCtxt, Unnormalized}; From a49d3932c0c2ade458efd0eedad5c40693577553 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 23 Sep 2026 20:34:41 +0800 Subject: [PATCH 0707/1309] chore: drop unneeded `#![allow(unreachable_pub)]` This probably was needed at some point in the rust-lang/rust tree when someone was tuning the lint itself? But in any case, we don't need this anymore. --- src/tools/rustfmt/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index f54d0641f4629..285fa26d00a50 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -3,7 +3,6 @@ #![warn(unreachable_pub)] #![recursion_limit = "256"] #![allow(clippy::match_like_matches_macro)] -#![allow(unreachable_pub)] // N.B. these crates are loaded from the sysroot, so they need extern crate. extern crate rustc_ast; From 711d8619a0f38466e7c84f02acf699fb7b25a88b Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:48:45 +0900 Subject: [PATCH 0708/1309] Use `std_or_core` in `ambiguous_wide_pointer_comparisons` rustfix --- compiler/rustc_lint/src/diagnostics.rs | 20 ++++++++++++------- compiler/rustc_lint/src/types.rs | 13 +++++++++++- .../lint/wide_pointer_comparisons-no_std.rs | 10 ++++++++++ .../wide_pointer_comparisons-no_std.stderr | 20 +++++++++++++++++++ 4 files changed, 55 insertions(+), 8 deletions(-) create mode 100644 tests/ui/lint/wide_pointer_comparisons-no_std.rs create mode 100644 tests/ui/lint/wide_pointer_comparisons-no_std.stderr diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 12fd049724413..d7cfb409c13f5 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -2361,25 +2361,30 @@ pub(crate) enum AmbiguousWidePointerComparisons<'a> { #[diag( "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" )] - #[help("use explicit `std::ptr::eq` method to compare metadata and addresses")] - #[help("use `std::ptr::addr_eq` or untyped pointers to only compare their addresses")] - Spanless, + #[help("use explicit `{$krate}::ptr::eq` method to compare metadata and addresses")] + #[help("use `{$krate}::ptr::addr_eq` or untyped pointers to only compare their addresses")] + Spanless { krate: &'static str }, + #[diag( + "ambiguous wide pointer comparison, the comparison includes metadata which may not be expected" + )] + Warn, } #[derive(Subdiagnostic)] #[multipart_suggestion( - "use explicit `std::ptr::eq` method to compare metadata and addresses", + "use explicit `{$krate}::ptr::eq` method to compare metadata and addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" )] pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { + pub krate: &'static str, pub ne: &'a str, pub deref_left: &'a str, pub deref_right: &'a str, pub l_modifiers: &'a str, pub r_modifiers: &'a str, - #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")] + #[suggestion_part(code = "{ne}{krate}::ptr::eq({deref_left}")] pub left: Span, #[suggestion_part(code = "{l_modifiers}, {deref_right}")] pub middle: Span, @@ -2389,18 +2394,19 @@ pub(crate) struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> { #[derive(Subdiagnostic)] #[multipart_suggestion( - "use `std::ptr::addr_eq` or untyped pointers to only compare their addresses", + "use `{$krate}::ptr::addr_eq` or untyped pointers to only compare their addresses", style = "verbose", // FIXME(#53934): make machine-applicable again applicability = "maybe-incorrect" )] pub(crate) struct AmbiguousWidePointerComparisonsAddrSuggestion<'a> { + pub(crate) krate: &'static str, pub(crate) ne: &'a str, pub(crate) deref_left: &'a str, pub(crate) deref_right: &'a str, pub(crate) l_modifiers: &'a str, pub(crate) r_modifiers: &'a str, - #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")] + #[suggestion_part(code = "{ne}{krate}::ptr::addr_eq({deref_left}")] pub(crate) left: Span, #[suggestion_part(code = "{l_modifiers}, {deref_right}")] pub(crate) middle: Span, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 4d741e06198b5..7e7804e74f352 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -23,6 +23,7 @@ use crate::diagnostics::{ UnpredictableFunctionPointerComparisonsSuggestion, UnusedComparisons, VariantSizeDifferencesDiag, }; +use crate::utils::std_or_core; use crate::{LateContext, LateLintPass, LintContext}; mod literal; @@ -346,13 +347,21 @@ fn lint_wide_pointer<'tcx>( return; }; + let Some(krate) = std_or_core(cx) else { + return cx.emit_span_lint( + AMBIGUOUS_WIDE_POINTER_COMPARISONS, + e.span, + AmbiguousWidePointerComparisons::Warn, + ); + }; + let (Some(l_span), Some(r_span)) = (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span)) else { return cx.emit_span_lint( AMBIGUOUS_WIDE_POINTER_COMPARISONS, e.span, - AmbiguousWidePointerComparisons::Spanless, + AmbiguousWidePointerComparisons::Spanless { krate }, ); }; @@ -378,6 +387,7 @@ fn lint_wide_pointer<'tcx>( AmbiguousWidePointerComparisons::SpanfulEq { addr_metadata_suggestion: (!is_dyn_comparison).then(|| { AmbiguousWidePointerComparisonsAddrMetadataSuggestion { + krate, ne, deref_left, deref_right, @@ -389,6 +399,7 @@ fn lint_wide_pointer<'tcx>( } }), addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion { + krate, ne, deref_left, deref_right, diff --git a/tests/ui/lint/wide_pointer_comparisons-no_std.rs b/tests/ui/lint/wide_pointer_comparisons-no_std.rs new file mode 100644 index 0000000000000..745c9925f22a6 --- /dev/null +++ b/tests/ui/lint/wide_pointer_comparisons-no_std.rs @@ -0,0 +1,10 @@ +//@ check-pass + +#![no_std] +#![crate_type = "lib"] +#![allow(dead_code)] + +fn cmp(a: *mut [u8], b: *mut [u8]) -> bool { + a == b + //~^ WARN ambiguous wide pointer comparison +} diff --git a/tests/ui/lint/wide_pointer_comparisons-no_std.stderr b/tests/ui/lint/wide_pointer_comparisons-no_std.stderr new file mode 100644 index 0000000000000..a5090cb872a41 --- /dev/null +++ b/tests/ui/lint/wide_pointer_comparisons-no_std.stderr @@ -0,0 +1,20 @@ +warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected + --> $DIR/wide_pointer_comparisons-no_std.rs:8:5 + | +LL | a == b + | ^^^^^^ + | + = note: `#[warn(ambiguous_wide_pointer_comparisons)]` on by default +help: use `core::ptr::addr_eq` or untyped pointers to only compare their addresses + | +LL - a == b +LL + core::ptr::addr_eq(a, b) + | +help: use explicit `core::ptr::eq` method to compare metadata and addresses + | +LL - a == b +LL + core::ptr::eq(a, b) + | + +warning: 1 warning emitted + From ed84aded9c6f4c8d40e2bb15e5178109bada68bc Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 20:51:00 +0900 Subject: [PATCH 0709/1309] Use `std_or_core` in `unpredictable_function_pointer_comparisons` rustfix --- compiler/rustc_lint/src/diagnostics.rs | 10 ++++++---- compiler/rustc_lint/src/types.rs | 10 ++++++++++ tests/ui/lint/fn-ptr-comparisons-no_std.fixed | 13 +++++++++++++ tests/ui/lint/fn-ptr-comparisons-no_std.rs | 13 +++++++++++++ tests/ui/lint/fn-ptr-comparisons-no_std.stderr | 18 ++++++++++++++++++ 5 files changed, 60 insertions(+), 4 deletions(-) create mode 100644 tests/ui/lint/fn-ptr-comparisons-no_std.fixed create mode 100644 tests/ui/lint/fn-ptr-comparisons-no_std.rs create mode 100644 tests/ui/lint/fn-ptr-comparisons-no_std.stderr diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index d7cfb409c13f5..51242fafdda9f 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -2489,15 +2489,16 @@ pub(crate) enum UnpredictableFunctionPointerComparisons<'a, 'tcx> { #[derive(Subdiagnostic)] pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { #[multipart_suggestion( - "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", + "refactor your code, or use `{$krate}::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] FnAddrEq { + krate: &'static str, ne: &'a str, deref_left: &'a str, deref_right: &'a str, - #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + #[suggestion_part(code = "{ne}{krate}::ptr::fn_addr_eq({deref_left}")] left: Span, #[suggestion_part(code = ", {deref_right}")] middle: Span, @@ -2505,16 +2506,17 @@ pub(crate) enum UnpredictableFunctionPointerComparisonsSuggestion<'a, 'tcx> { right: Span, }, #[multipart_suggestion( - "refactor your code, or use `std::ptr::fn_addr_eq` to suppress the lint", + "refactor your code, or use `{$krate}::ptr::fn_addr_eq` to suppress the lint", style = "verbose", applicability = "maybe-incorrect" )] FnAddrEqWithCast { + krate: &'static str, ne: &'a str, deref_left: &'a str, deref_right: &'a str, fn_sig: rustc_middle::ty::PolyFnSig<'tcx>, - #[suggestion_part(code = "{ne}std::ptr::fn_addr_eq({deref_left}")] + #[suggestion_part(code = "{ne}{krate}::ptr::fn_addr_eq({deref_left}")] left: Span, #[suggestion_part(code = ", {deref_right}")] middle: Span, diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 7e7804e74f352..7d29cc367b25c 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -521,6 +521,14 @@ fn lint_fn_pointer<'tcx>( let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo()); let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi()); + let Some(krate) = std_or_core(cx) else { + return cx.emit_span_lint( + UNPREDICTABLE_FUNCTION_POINTER_COMPARISONS, + e.span, + UnpredictableFunctionPointerComparisons::Warn, + ); + }; + let sugg = // We only check for a right cast as `FnDef` == `FnPtr` is not possible, // only `FnPtr == FnDef` is possible. @@ -528,6 +536,7 @@ fn lint_fn_pointer<'tcx>( let fn_sig = r_ty.fn_sig(cx.tcx); UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEqWithCast { + krate, ne, fn_sig, deref_left, @@ -538,6 +547,7 @@ fn lint_fn_pointer<'tcx>( } } else { UnpredictableFunctionPointerComparisonsSuggestion::FnAddrEq { + krate, ne, deref_left, deref_right, diff --git a/tests/ui/lint/fn-ptr-comparisons-no_std.fixed b/tests/ui/lint/fn-ptr-comparisons-no_std.fixed new file mode 100644 index 0000000000000..dd7477976b108 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons-no_std.fixed @@ -0,0 +1,13 @@ +//@ check-pass +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(dead_code)] + +fn a() {} + +fn cmp(f: fn()) -> bool { + core::ptr::fn_addr_eq(f, a as fn()) + //~^ WARN function pointer comparisons +} diff --git a/tests/ui/lint/fn-ptr-comparisons-no_std.rs b/tests/ui/lint/fn-ptr-comparisons-no_std.rs new file mode 100644 index 0000000000000..cdeab43b8b2b1 --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons-no_std.rs @@ -0,0 +1,13 @@ +//@ check-pass +//@ run-rustfix + +#![no_std] +#![crate_type = "lib"] +#![allow(dead_code)] + +fn a() {} + +fn cmp(f: fn()) -> bool { + f == a + //~^ WARN function pointer comparisons +} diff --git a/tests/ui/lint/fn-ptr-comparisons-no_std.stderr b/tests/ui/lint/fn-ptr-comparisons-no_std.stderr new file mode 100644 index 0000000000000..f51f0bbb7437b --- /dev/null +++ b/tests/ui/lint/fn-ptr-comparisons-no_std.stderr @@ -0,0 +1,18 @@ +warning: function pointer comparisons do not produce meaningful results since their addresses are not guaranteed to be unique + --> $DIR/fn-ptr-comparisons-no_std.rs:11:5 + | +LL | f == a + | ^^^^^^ + | + = note: the address of the same function can vary between different codegen units + = note: furthermore, different functions could have the same address after being merged together + = note: for more information visit + = note: `#[warn(unpredictable_function_pointer_comparisons)]` on by default +help: refactor your code, or use `core::ptr::fn_addr_eq` to suppress the lint + | +LL - f == a +LL + core::ptr::fn_addr_eq(f, a as fn()) + | + +warning: 1 warning emitted + From e31fb47c9fff9832cd74ec1e7de43e8c88d4586e Mon Sep 17 00:00:00 2001 From: lapla Date: Mon, 14 Sep 2026 21:04:20 +0900 Subject: [PATCH 0710/1309] Skip `panic_any` rustfix in `non_fmt_panics` when it is unavailable --- compiler/rustc_lint/src/non_fmt_panic.rs | 9 +++++- .../non-fmt-panic-no_std-extern-std.fixed | 14 +++++++++ .../macros/non-fmt-panic-no_std-extern-std.rs | 14 +++++++++ .../non-fmt-panic-no_std-extern-std.stderr | 22 +++++++++++++ tests/ui/macros/non-fmt-panic-no_std.fixed | 14 +++++++++ tests/ui/macros/non-fmt-panic-no_std.rs | 14 +++++++++ tests/ui/macros/non-fmt-panic-no_std.stderr | 31 +++++++++++++++++++ 7 files changed, 117 insertions(+), 1 deletion(-) create mode 100644 tests/ui/macros/non-fmt-panic-no_std-extern-std.fixed create mode 100644 tests/ui/macros/non-fmt-panic-no_std-extern-std.rs create mode 100644 tests/ui/macros/non-fmt-panic-no_std-extern-std.stderr create mode 100644 tests/ui/macros/non-fmt-panic-no_std.fixed create mode 100644 tests/ui/macros/non-fmt-panic-no_std.rs create mode 100644 tests/ui/macros/non-fmt-panic-no_std.stderr diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 991b1083b3272..05d35bd5fac46 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -143,7 +143,14 @@ impl<'a, 'b, 'tcx> Diagnostic<'a, ()> for PanicMessageNotLiteral<'b, 'tcx> { .get_diagnostic_item(sym::Debug) .is_some_and(|t| infcx.type_implements_trait(t, [ty], param_env).may_apply()); - let suggest_panic_any = !is_str && panic == Some(sym::std_panic_macro); + let suggest_panic_any = !is_str + && panic == Some(sym::std_panic_macro) + && cx + .tcx + .all_diagnostic_items(()) + .name_to_id + .keys() + .any(|name| name.as_str() == "panic_any"); let fmt_applicability = if suggest_panic_any { // If we can use panic_any, use that as the MachineApplicable suggestion. diff --git a/tests/ui/macros/non-fmt-panic-no_std-extern-std.fixed b/tests/ui/macros/non-fmt-panic-no_std-extern-std.fixed new file mode 100644 index 0000000000000..e39a5a5566db4 --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std-extern-std.fixed @@ -0,0 +1,14 @@ +//@ edition:2018 +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![no_std] +#![crate_type = "lib"] + +extern crate std; + +pub fn f() { + std::panic::panic_any(123); + //~^ WARN panic message is not a string literal +} diff --git a/tests/ui/macros/non-fmt-panic-no_std-extern-std.rs b/tests/ui/macros/non-fmt-panic-no_std-extern-std.rs new file mode 100644 index 0000000000000..0e2dd8dab6e3c --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std-extern-std.rs @@ -0,0 +1,14 @@ +//@ edition:2018 +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![no_std] +#![crate_type = "lib"] + +extern crate std; + +pub fn f() { + std::panic!(123); + //~^ WARN panic message is not a string literal +} diff --git a/tests/ui/macros/non-fmt-panic-no_std-extern-std.stderr b/tests/ui/macros/non-fmt-panic-no_std-extern-std.stderr new file mode 100644 index 0000000000000..9c96c1f032cc5 --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std-extern-std.stderr @@ -0,0 +1,22 @@ +warning: panic message is not a string literal + --> $DIR/non-fmt-panic-no_std-extern-std.rs:12:17 + | +LL | std::panic!(123); + | ^^^ + | + = note: this usage of `std::panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: for more information, see + = note: `#[warn(non_fmt_panics)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: add a "{}" format string to `Display` the message + | +LL | std::panic!("{}", 123); + | +++++ +help: or use std::panic::panic_any instead + | +LL - std::panic!(123); +LL + std::panic::panic_any(123); + | + +warning: 1 warning emitted + diff --git a/tests/ui/macros/non-fmt-panic-no_std.fixed b/tests/ui/macros/non-fmt-panic-no_std.fixed new file mode 100644 index 0000000000000..f7904b15b2b23 --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std.fixed @@ -0,0 +1,14 @@ +//@ edition:2018 +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![no_std] +#![crate_type = "lib"] + +pub fn f(s: &str) { + panic!("{}", s); + //~^ WARN panic message is not a string literal + core::panic!("{}", s); + //~^ WARN panic message is not a string literal +} diff --git a/tests/ui/macros/non-fmt-panic-no_std.rs b/tests/ui/macros/non-fmt-panic-no_std.rs new file mode 100644 index 0000000000000..b1b0f609e6716 --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std.rs @@ -0,0 +1,14 @@ +//@ edition:2018 +//@ check-pass +//@ run-rustfix +//@ rustfix-only-machine-applicable + +#![no_std] +#![crate_type = "lib"] + +pub fn f(s: &str) { + panic!(s); + //~^ WARN panic message is not a string literal + core::panic!(s); + //~^ WARN panic message is not a string literal +} diff --git a/tests/ui/macros/non-fmt-panic-no_std.stderr b/tests/ui/macros/non-fmt-panic-no_std.stderr new file mode 100644 index 0000000000000..8fdf5bfaf7e13 --- /dev/null +++ b/tests/ui/macros/non-fmt-panic-no_std.stderr @@ -0,0 +1,31 @@ +warning: panic message is not a string literal + --> $DIR/non-fmt-panic-no_std.rs:10:12 + | +LL | panic!(s); + | ^ + | + = note: this usage of `panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: for more information, see + = note: `#[warn(non_fmt_panics)]` (part of `#[warn(rust_2021_compatibility)]`) on by default +help: add a "{}" format string to `Display` the message + | +LL | panic!("{}", s); + | +++++ + +warning: panic message is not a string literal + --> $DIR/non-fmt-panic-no_std.rs:12:18 + | +LL | core::panic!(s); + | ^ + | + = note: this usage of `core::panic!()` is deprecated; it will be a hard error in Rust 2021 + = note: for more information, see + = note: for more information, see +help: add a "{}" format string to `Display` the message + | +LL | core::panic!("{}", s); + | +++++ + +warning: 2 warnings emitted + From 3ca6e6cf2033c561330e813e571edd490a72396e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Wed, 23 Sep 2026 14:47:31 +0200 Subject: [PATCH 0711/1309] fix `test_mm_srav_epi64` shift direction --- library/stdarch/crates/core_arch/src/x86_64/avx512f.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs index 832384b11e68b..9c261784553bd 100644 --- a/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs +++ b/library/stdarch/crates/core_arch/src/x86_64/avx512f.rs @@ -9583,7 +9583,7 @@ mod tests { let a = _mm_set_epi64x(-1, -2); let b = _mm_set_epi64x(64, 65); let r = _mm_srav_epi64(a, b); - let e = _mm_set_epi64x((-1i64).unbounded_shl(64), (-2i64).unbounded_shl(65)); + let e = _mm_set_epi64x((-1i64).unbounded_shr(64), (-2i64).unbounded_shr(65)); assert_eq_m128i(r, e); let e = _mm_set_epi64x(-1, -1); assert_eq_m128i(r, e); From b7dc0720062b9e6c37857bac9bceaf7ad212a90a Mon Sep 17 00:00:00 2001 From: malezjaa Date: Wed, 23 Sep 2026 15:08:43 +0200 Subject: [PATCH 0712/1309] revert r14 register names for arm --- compiler/rustc_codegen_llvm/src/asm.rs | 6 ++---- tests/codegen-llvm/asm-arm-r14.rs | 6 +----- tests/ui/asm/thumbv6m-clobber-abi-r14.rs | 18 ++++++++++++++++++ 3 files changed, 21 insertions(+), 9 deletions(-) create mode 100644 tests/ui/asm/thumbv6m-clobber-abi-r14.rs diff --git a/compiler/rustc_codegen_llvm/src/asm.rs b/compiler/rustc_codegen_llvm/src/asm.rs index b20a89859388e..21888720524a5 100644 --- a/compiler/rustc_codegen_llvm/src/asm.rs +++ b/compiler/rustc_codegen_llvm/src/asm.rs @@ -791,12 +791,10 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass, layout: Option<&TyAndLayout<'_>>) -> } else if let Some(idx) = hexagon_vreg_pair_index(reg) { // LLVM uses `wN` for Hexagon HVX vector pair registers. format!("{{w{}}}", idx) - } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) - && llvm_util::get_version() < (23, 0, 0) - { + } else if reg == InlineAsmReg::Arm(ArmInlineAsmReg::r14) { // FIXME(llvm): LLVM <23 does not recognize `r14` as a register name // in inline assembly. - // This workaround can be removed when support for LLVM 22 is dropped. + // We can make this branch fallthrough again for LLVM 23+ when https://github.com/llvm/llvm-project/pull/225746 gets released. "{lr}".to_string() } else if let InlineAsmReg::Sparc(reg) = reg && let Some(num) = reg.dreg_number() diff --git a/tests/codegen-llvm/asm-arm-r14.rs b/tests/codegen-llvm/asm-arm-r14.rs index 2404e84c1701e..2af9e372a462d 100644 --- a/tests/codegen-llvm/asm-arm-r14.rs +++ b/tests/codegen-llvm/asm-arm-r14.rs @@ -1,9 +1,6 @@ //@ add-minicore //@ compile-flags: --target armv7-unknown-linux-gnueabihf //@ needs-llvm-components: arm -//@ revisions: LLVM22 LLVM23 -//@ [LLVM22] max-llvm-major-version: 22 -//@ [LLVM23] min-llvm-version: 23 #![feature(no_core)] #![no_core] @@ -15,8 +12,7 @@ use minicore::*; #[no_mangle] pub unsafe fn r14_output() -> u32 { // CHECK-LABEL: define{{.*}}@r14_output - // LLVM22: asm sideeffect{{.*}}"=&{lr},~{cc},~{memory}" - // LLVM23: asm sideeffect{{.*}}"=&{r14},~{cc},~{memory}" + // CHECK: asm sideeffect{{.*}}"=&{lr},~{cc},~{memory}" let output: u32; asm!("", out("r14") output); output diff --git a/tests/ui/asm/thumbv6m-clobber-abi-r14.rs b/tests/ui/asm/thumbv6m-clobber-abi-r14.rs new file mode 100644 index 0000000000000..342e65b52d9d8 --- /dev/null +++ b/tests/ui/asm/thumbv6m-clobber-abi-r14.rs @@ -0,0 +1,18 @@ +//@ add-minicore +//@ build-pass +//@ compile-flags: --target thumbv6m-none-eabi +//@ needs-llvm-components: arm +//@ ignore-backends: gcc + +#![feature(no_core)] +#![no_core] +#![crate_type = "rlib"] + +extern crate minicore; +use minicore::*; + +pub fn clobber_c_abi() { + unsafe { + asm!("nop", clobber_abi("C")); + } +} From ffb56b9fa7f6129639c69b0a19ef54606ca4856d Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 20 Sep 2026 21:47:05 +0000 Subject: [PATCH 0713/1309] merge `Ord` and `PartialOrd` code --- .../src/deriving/generic/mod.rs | 46 ----- .../rustc_builtin_macros/src/deriving/ord.rs | 36 +--- .../src/deriving/partial_ord.rs | 183 ++++++++++++------ 3 files changed, 124 insertions(+), 141 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b6bd482945546..b9888f2773699 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1373,49 +1373,3 @@ impl<'a> TraitDef<'a> { }) } } - -/// Folds over fields, combining the expressions for each field in a sequence. -/// Statics may not be folded over. -pub(crate) fn cs_foldr( - cx: &ExtCtxt<'_>, - trait_span: Span, - substructure: Substructure<'_>, - // The basic case: a field expression for one or more selflike args. E.g. - // for `PartialEq::eq` this is something like `self.x == other.x`. - single: impl Fn(FieldInfo) -> Box, - // The combination of two field expressions. E.g. for `PartialEq::eq` this - // is something like ` && `. - combine: impl Fn(Span, Box, Box) -> Box, - // The fallback case for a struct or enum variant with no fields. - fieldless: impl Fn() -> Box, -) -> Box { - match substructure { - EnumMatching(.., all_fields) | Struct(_, all_fields) => { - let mut fields = all_fields.into_iter(); - let base_field = fields.next_back(); - - let Some(base_field) = base_field else { - return fieldless(); - }; - - let base_expr = single(base_field); - - let op = |old, field: FieldInfo| { - let span = field.span; - let new = single(field); - combine(span, old, new) - }; - - fields.rfold(base_expr, op) - } - EnumDiscr(discr_field, match_expr) => { - let discr_check_expr = single(discr_field); - if let Some(match_expr) = match_expr { - combine(trait_span, match_expr, discr_check_expr) - } else { - discr_check_expr - } - } - _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive`"), - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index c6b37d8d0edea..8851dd994a542 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -1,11 +1,11 @@ use rustc_ast::Safety; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Span, sym}; use thin_vec::thin_vec; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::partial_ord::discr_data_order; +use crate::deriving::partial_ord::{OrdlikeDerive, cmp_body, discr_data_order}; use crate::deriving::path_std; pub(crate) fn expand_deriving_ord( @@ -54,10 +54,6 @@ pub(crate) fn cs_cmp( substr: Substructure<'_>, discr_then_data: bool, ) -> BlockOrExpr { - let test_id = Ident::new(sym::cmp, span); - let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let cmp_path = cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]); - // Builds: // // match ::core::cmp::Ord::cmp(&self.x, &other.x) { @@ -65,32 +61,6 @@ pub(crate) fn cs_cmp( // ::core::cmp::Ord::cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr( - cx, - span, - substr, - |field| { - let other_expr = - field.other_selflike_expr.expect("not exactly 2 arguments in `derive(Ord)`"); - let args = thin_vec![field.self_expr, other_expr]; - cx.expr_call_global(field.span, cmp_path.clone(), args) - }, - |span, mut expr1, expr2| { - if !discr_then_data - && let ast::ExprKind::Match(_, arms, _) = &mut expr1.kind - && let Some(last) = arms.last_mut() - && let ast::PatKind::Wild = last.pat.kind - { - last.body = Some(expr2); - expr1 - } else { - let eq_arm = cx.arm(span, cx.pat_path(span, equal_path.clone()), expr1); - let neq_arm = - cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) - } - }, - || cx.expr_path(equal_path.clone()), - ); + let expr = cmp_body(cx, span, substr, discr_then_data, OrdlikeDerive::Ord); BlockOrExpr::new_expr(expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 2f30aa7a5cc0e..35e93b254565f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -1,4 +1,4 @@ -use rustc_ast::{ExprKind, ItemKind, PatKind, Safety, ast}; +use rustc_ast::{Expr, ItemKind, Safety, ast}; use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; @@ -116,10 +116,6 @@ fn cs_partial_cmp( substr: Substructure<'_>, discr_then_data: bool, ) -> BlockOrExpr { - let test_id = Ident::new(sym::cmp, span); - let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - let partial_cmp_path = cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]); - // Builds: // // match ::core::cmp::PartialOrd::partial_cmp(&self.x, &other.x) { @@ -127,63 +123,126 @@ fn cs_partial_cmp( // ::core::cmp::PartialOrd::partial_cmp(&self.y, &other.y), // cmp => cmp, // } - let expr = cs_foldr( - cx, - span, - substr, - |field| { - let other_expr = - field.other_selflike_expr.expect("not exactly 2 arguments in `derive(PartialOrd)`"); - let args = thin_vec![field.self_expr, other_expr]; - cx.expr_call_global(field.span, partial_cmp_path.clone(), args) - }, - |span, mut expr1, expr2| { - // When the item is an enum, this expands to - // ``` - // match (expr2) { - // Some(Ordering::Equal) => expr1, - // cmp => cmp - // } - // ``` - // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` - // against the enum variants. This means that we begin by comparing the enum discriminants, - // before either inspecting their contents (if they match), or returning - // the `cmp::Ordering` of comparing the enum discriminants. - // ``` - // match partial_cmp(self_discr, other_discr) { - // Some(Ordering::Equal) => match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), - // _ => Some(Ordering::Equal) - // } - // cmp => cmp - // } - // ``` - // If we have any certain enum layouts, flipping this results in better codegen - // ``` - // match (self, other) { - // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), - // _ => partial_cmp(self_discr, other_discr) - // } - // ``` - // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 - - if !discr_then_data - && let ExprKind::Match(_, arms, _) = &mut expr1.kind - && let Some(last) = arms.last_mut() - && let PatKind::Wild = last.pat.kind - { - last.body = Some(expr2); - expr1 + let expr = cmp_body(cx, span, substr, discr_then_data, OrdlikeDerive::PartialOrd); + BlockOrExpr::new_expr(expr) +} + +#[derive(PartialEq)] +pub(crate) enum OrdlikeDerive { + PartialOrd, + Ord, +} + +pub(crate) fn cmp_body( + cx: &ExtCtxt<'_>, + span: Span, + substructure: Substructure<'_>, + discr_then_data: bool, + derive: OrdlikeDerive, +) -> Box { + let is_partial_ord = derive == OrdlikeDerive::PartialOrd; + let method_path = if is_partial_ord { + cx.std_path(&[sym::cmp, sym::PartialOrd, sym::partial_cmp]) + } else { + cx.std_path(&[sym::cmp, sym::Ord, sym::cmp]) + }; + let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); + + // The basic case: a field expression for one or more selflike args. E.g. + // for `Ord::cmp` this is something like `Ord::cmp(&self.x, &other.x)`. + let single = |field: FieldInfo| { + let other_expr = field.other_selflike_expr.expect("not exactly 2 arguments in `derive`"); + let args = thin_vec![field.self_expr, other_expr]; + cx.expr_call_global(field.span, method_path.clone(), args) + }; + + // The combination of two field expressions. E.g. for `PartialEq::eq` this + // is something like ` && `. + let combine = |span, mut expr1: Box, expr2| { + // For `PartialOrd` (`Ord` works the same but without the `Some` wrapping), + // when the item is an enum, this expands to + // ``` + // match (expr2) { + // Some(Ordering::Equal) => expr1, + // cmp => cmp + // } + // ``` + // where `expr2` is `partial_cmp(self_discr, other_discr)`, and `expr1` is a `match` + // against the enum variants. This means that we begin by comparing the enum discriminants, + // before either inspecting their contents (if they match), or returning + // the `cmp::Ordering` of comparing the enum discriminants. + // ``` + // match partial_cmp(self_discr, other_discr) { + // Some(Ordering::Equal) => match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // (Self::B(self_0), Self::B(other_0)) => partial_cmp(self_0, other_0), + // _ => Some(Ordering::Equal) + // } + // cmp => cmp + // } + // ``` + // If we have any certain enum layouts, flipping this results in better codegen + // ``` + // match (self, other) { + // (Self::A(self_0), Self::A(other_0)) => partial_cmp(self_0, other_0), + // _ => partial_cmp(self_discr, other_discr) + // } + // ``` + // Reference: https://github.com/rust-lang/rust/pull/103659#issuecomment-1328126354 + + if !discr_then_data + && let ast::ExprKind::Match(_, arms, _) = &mut expr1.kind + && let Some(last) = arms.last_mut() + && let ast::PatKind::Wild = last.pat.kind + { + last.body = Some(expr2); + expr1 + } else { + let eq_pat = cx.pat_path(span, equal_path.clone()); + let eq_arm = cx.arm( + span, + if is_partial_ord { cx.pat_some(span, eq_pat) } else { eq_pat }, + expr1, + ); + let cmp_ident = Ident::new(sym::cmp, span); + let neq_arm = + cx.arm(span, cx.pat_ident(span, cmp_ident), cx.expr_ident(span, cmp_ident)); + cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) + } + }; + + match substructure { + EnumMatching(.., all_fields) | Struct(_, all_fields) => { + let mut fields = all_fields.into_iter(); + let base_field = fields.next_back(); + + let Some(base_field) = base_field else { + // The fallback case for a struct or enum variant with no fields. + let mut expr = cx.expr_path(equal_path); + if is_partial_ord { + expr = cx.expr_some(span, expr) + }; + return expr; + }; + + let base_expr = single(base_field); + + let op = |old, field: FieldInfo| { + let span = field.span; + let new = single(field); + combine(span, old, new) + }; + + fields.rfold(base_expr, op) + } + EnumDiscr(discr_field, match_expr) => { + let discr_check_expr = single(discr_field); + if let Some(match_expr) = match_expr { + combine(span, match_expr, discr_check_expr) } else { - let eq_arm = - cx.arm(span, cx.pat_some(span, cx.pat_path(span, equal_path.clone())), expr1); - let neq_arm = - cx.arm(span, cx.pat_ident(span, test_id), cx.expr_ident(span, test_id)); - cx.expr_match(span, expr2, thin_vec![eq_arm, neq_arm]) + discr_check_expr } - }, - || cx.expr_some(span, cx.expr_path(equal_path.clone())), - ); - BlockOrExpr::new_expr(expr) + } + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive`"), + } } From c9412ec1c0873c1ae551ebcf7b9d3ceb077aec9a Mon Sep 17 00:00:00 2001 From: Yukang Date: Wed, 23 Sep 2026 21:32:00 +0800 Subject: [PATCH 0714/1309] Fix suggestion for Option to bool with proper precedence handling --- .../src/fn_ctxt/suggestions.rs | 14 +++++--- tests/ui/suggestions/option-to-bool.fixed | 35 +++++++++++++++++++ tests/ui/suggestions/option-to-bool.rs | 1 + tests/ui/suggestions/option-to-bool.stderr | 20 +++++------ 4 files changed, 56 insertions(+), 14 deletions(-) create mode 100644 tests/ui/suggestions/option-to-bool.fixed diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 7f8edae4f17c3..62d48af2f3f08 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1692,12 +1692,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let suggestion = match self.tcx.hir_maybe_get_struct_pattern_shorthand_field(expr) { - Some(ident) => format!(": {ident}.is_some()"), - None => ".is_some()".to_string(), + Some(ident) => vec![(expr.span.shrink_to_hi(), format!(": {ident}.is_some()"))], + None if self.precedence(expr) < ExprPrecedence::Unambiguous => { + // Apply the method to the whole expression, e.g. `(*value).is_some()`. + vec![ + (expr.span.shrink_to_lo(), "(".to_string()), + (expr.span.shrink_to_hi(), ").is_some()".to_string()), + ] + } + None => vec![(expr.span.shrink_to_hi(), ".is_some()".to_string())], }; - diag.span_suggestion_verbose( - expr.span.shrink_to_hi(), + diag.multipart_suggestion( "use `Option::is_some` to test if the `Option` has a value", suggestion, Applicability::MachineApplicable, diff --git a/tests/ui/suggestions/option-to-bool.fixed b/tests/ui/suggestions/option-to-bool.fixed new file mode 100644 index 0000000000000..b6160a1bb8f15 --- /dev/null +++ b/tests/ui/suggestions/option-to-bool.fixed @@ -0,0 +1,35 @@ +// An `is_some()` suggestion must apply to the whole expression, preserving its precedence. +//@ run-rustfix + +fn foo(x: Option) { + if true && x.is_some() {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value + + let reference = &x; + if (*reference).is_some() {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value + + if (&x).is_some() {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value + + if (Value + Value).is_some() {} + //~^ ERROR mismatched types + //~| HELP use `Option::is_some` to test if the `Option` has a value +} + +struct Value; + +impl std::ops::Add for Value { + type Output = Option; + + fn add(self, _: Self) -> Self::Output { + Some(1) + } +} + +fn main() { + foo(Some(1)); +} diff --git a/tests/ui/suggestions/option-to-bool.rs b/tests/ui/suggestions/option-to-bool.rs index b36c28c06ef9d..25272b96dfc28 100644 --- a/tests/ui/suggestions/option-to-bool.rs +++ b/tests/ui/suggestions/option-to-bool.rs @@ -1,4 +1,5 @@ // An `is_some()` suggestion must apply to the whole expression, preserving its precedence. +//@ run-rustfix fn foo(x: Option) { if true && x {} diff --git a/tests/ui/suggestions/option-to-bool.stderr b/tests/ui/suggestions/option-to-bool.stderr index 2ee282670d794..dd49b1b2b0ad1 100644 --- a/tests/ui/suggestions/option-to-bool.stderr +++ b/tests/ui/suggestions/option-to-bool.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/option-to-bool.rs:4:16 + --> $DIR/option-to-bool.rs:5:16 | LL | if true && x {} | ---- ^ expected `bool`, found `Option` @@ -14,7 +14,7 @@ LL | if true && x.is_some() {} | ++++++++++ error[E0308]: mismatched types - --> $DIR/option-to-bool.rs:9:8 + --> $DIR/option-to-bool.rs:10:8 | LL | if *reference {} | ^^^^^^^^^^ expected `bool`, found `Option` @@ -23,11 +23,11 @@ LL | if *reference {} found enum `Option` help: use `Option::is_some` to test if the `Option` has a value | -LL | if *reference.is_some() {} - | ++++++++++ +LL | if (*reference).is_some() {} + | + +++++++++++ error[E0308]: mismatched types - --> $DIR/option-to-bool.rs:13:8 + --> $DIR/option-to-bool.rs:14:8 | LL | if &x {} | ^^ expected `bool`, found `&Option` @@ -36,11 +36,11 @@ LL | if &x {} found reference `&Option` help: use `Option::is_some` to test if the `Option` has a value | -LL | if &x.is_some() {} - | ++++++++++ +LL | if (&x).is_some() {} + | + +++++++++++ error[E0308]: mismatched types - --> $DIR/option-to-bool.rs:17:8 + --> $DIR/option-to-bool.rs:18:8 | LL | if Value + Value {} | ^^^^^^^^^^^^^ expected `bool`, found `Option` @@ -49,8 +49,8 @@ LL | if Value + Value {} found enum `Option` help: use `Option::is_some` to test if the `Option` has a value | -LL | if Value + Value.is_some() {} - | ++++++++++ +LL | if (Value + Value).is_some() {} + | + +++++++++++ error: aborting due to 4 previous errors From d67606b1a0ff66ce94cf799308b6678e7456cd89 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 23 Sep 2026 15:38:23 +0200 Subject: [PATCH 0715/1309] Update code to use the new file --- Readme.md | 2 +- build_system/src/abi_test.rs | 2 +- build_system/src/utils.rs | 6 +++--- doc/tips.md | 2 +- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Readme.md b/Readme.md index 9a7c624c9bc22..14c0e3ad0f21c 100644 --- a/Readme.md +++ b/Readme.md @@ -154,7 +154,7 @@ If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y. You can do the same manually (although we don't recommend it): ```bash -$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs +$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain.toml | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs ``` ## Environment variables diff --git a/build_system/src/abi_test.rs b/build_system/src/abi_test.rs index a85886d87f365..9fc06dc8dbc04 100644 --- a/build_system/src/abi_test.rs +++ b/build_system/src/abi_test.rs @@ -34,7 +34,7 @@ pub fn run() -> Result<(), String> { .map_err(|err| format!("Git clone failed with message: {err:?}!"))?; // Configure abi-cafe to use the exact same rustc version we use - this is crucial. // Otherwise, the concept of ABI compatibility becomes meanignless. - std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain") + std::fs::copy("rust-toolchain.toml", "clones/abi-cafe/rust-toolchain.toml") .expect("Could not copy toolchain configs!"); // Get the backend path. // We will use the *debug* build of the backend - it has more checks enabled. diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 4c67156a85fb2..dda44e4d16d41 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -242,9 +242,9 @@ fn rustc_version_info_inner( } pub fn get_toolchain() -> Result { - let content = match fs::read_to_string("rust-toolchain") { + let content = match fs::read_to_string("rust-toolchain.toml") { Ok(content) => content, - Err(_) => return Err("No `rust-toolchain` file found".to_string()), + Err(_) => return Err("No `rust-toolchain.toml` file found".to_string()), }; match content .split('\n') @@ -259,7 +259,7 @@ pub fn get_toolchain() -> Result { .next() { Some(toolchain) => Ok(toolchain.to_string()), - None => Err("Couldn't find `channel` in `rust-toolchain` file".to_string()), + None => Err("Couldn't find `channel` in `rust-toolchain.toml` file".to_string()), } } diff --git a/doc/tips.md b/doc/tips.md index dc40ee4d39952..28964f66403bf 100644 --- a/doc/tips.md +++ b/doc/tips.md @@ -41,7 +41,7 @@ COLLECT_NO_DEMANGLE=1 ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). - * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain.toml`. ### How to use a custom sysroot source path From 6cc4e7e2788cb8f7c71454efb074e2f114b84898 Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Wed, 23 Sep 2026 22:52:15 +0900 Subject: [PATCH 0716/1309] Add `inline` attribute to `NonZero::from_str` --- library/core/src/num/nonzero.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d0ae6c31267f3..595f3d2248190 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1449,6 +1449,7 @@ macro_rules! nonzero_integer { /// #[doc = concat!("assert!(NonZero::<", stringify!($Int), ">::from_str(\"1 \").is_err());")] /// ``` + #[inline] fn from_str(src: &str) -> Result { Self::from_str_radix(src, 10) } From 9f208cb493f605226853d6015c2df8d4f6a983af Mon Sep 17 00:00:00 2001 From: David Carlier Date: Fri, 2 Feb 2024 20:55:44 +0000 Subject: [PATCH 0717/1309] std::thread::available_parallelism merging linux/android/freebsd version FreeBSD 13.1 had introduced a sched cpu affinity compatibility layer with Linux. 13.0 and even 13.1 being EOL, we can simplify here. --- library/std/src/sys/thread/unix.rs | 40 +++++++++--------------------- 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index b7908dea2b5de..11fe569f8e0a9 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -162,6 +162,7 @@ pub fn available_parallelism() -> io::Result> { target_os = "hurd", target_os = "linux", target_os = "aix", + target_os = "freebsd", target_vendor = "apple", target_os = "cygwin", target_os = "redox", @@ -174,9 +175,17 @@ pub fn available_parallelism() -> io::Result> { #[cfg(any(target_os = "android", target_os = "linux"))] { quota = cgroups::quota().max(1); - let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; + } + + #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] + { + #[cfg(not(target_os = "freebsd"))] + type Cpuset = libc::cpu_set_t; + #[cfg(target_os = "freebsd")] + type Cpuset = libc::cpuset_t; + let mut set: Cpuset = unsafe { mem::zeroed() }; unsafe { - if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { + if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { let count = libc::CPU_COUNT(&set) as usize; let count = count.min(quota); @@ -201,34 +210,9 @@ pub fn available_parallelism() -> io::Result> { } } } - any( - target_os = "freebsd", - target_os = "dragonfly", - target_os = "openbsd", - target_os = "netbsd", - ) => { + any(target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd") => { use crate::ptr; - #[cfg(target_os = "freebsd")] - { - let mut set: libc::cpuset_t = unsafe { mem::zeroed() }; - unsafe { - if libc::cpuset_getaffinity( - libc::CPU_LEVEL_WHICH, - libc::CPU_WHICH_PID, - -1, - size_of::(), - &mut set, - ) == 0 - { - let count = libc::CPU_COUNT(&set) as usize; - if count > 0 { - return Ok(NonZero::new_unchecked(count)); - } - } - } - } - #[cfg(target_os = "netbsd")] { unsafe { From 2b022a3d4bf8142d7faeaf9c4ebce160d0722a57 Mon Sep 17 00:00:00 2001 From: lapla Date: Thu, 24 Sep 2026 00:07:03 +0900 Subject: [PATCH 0718/1309] Export `std_or_core` --- compiler/rustc_lint/src/lib.rs | 1 + compiler/rustc_lint/src/utils.rs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs index 95033707cf110..deea9e1bbc13c 100644 --- a/compiler/rustc_lint/src/lib.rs +++ b/compiler/rustc_lint/src/lib.rs @@ -148,6 +148,7 @@ pub use rustc_lint_defs::{ Applicability, FutureIncompatibleInfo, Lint, LintId, LintPass, LintVec, declare_lint, declare_lint_pass, declare_tool_lint, impl_lint_pass, }; +pub use utils::std_or_core; pub fn provide(providers: &mut Providers) { levels::provide(providers); diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs index 5ece48370c043..e3c0198775433 100644 --- a/compiler/rustc_lint/src/utils.rs +++ b/compiler/rustc_lint/src/utils.rs @@ -49,7 +49,7 @@ pub(crate) fn peel_casts<'tcx>( } /// Crate to use for rustfix / diagnostic paths that exist in both `std` and `core`. Returns `None` for `#![no_core]`. -pub(crate) fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { +pub fn std_or_core(cx: &LateContext<'_>) -> Option<&'static str> { if find_attr!(cx.tcx, crate, NoCore) { None } else if find_attr!(cx.tcx, crate, NoStd) { From e2160bd1cd7a99e0fc2d33b1c0f5229a5ec80ca1 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Thu, 24 Sep 2026 00:14:06 +0900 Subject: [PATCH 0719/1309] convert the malformed function parameter crash test to a UI test --- tests/crashes/160490.rs | 2 - ...r-invalid-function-parameter-pattern-1.rs} | 0 ...valid-function-parameter-pattern-1.stderr} | 6 +-- ...er-invalid-function-parameter-pattern-2.rs | 8 ++++ ...nvalid-function-parameter-pattern-2.stderr | 43 +++++++++++++++++++ 5 files changed, 54 insertions(+), 5 deletions(-) delete mode 100644 tests/crashes/160490.rs rename tests/ui/parser/{recover-invalid-function-parameter-pattern.rs => recover-invalid-function-parameter-pattern-1.rs} (100%) rename tests/ui/parser/{recover-invalid-function-parameter-pattern.stderr => recover-invalid-function-parameter-pattern-1.stderr} (75%) create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr diff --git a/tests/crashes/160490.rs b/tests/crashes/160490.rs deleted file mode 100644 index 5f713ed268042..0000000000000 --- a/tests/crashes/160490.rs +++ /dev/null @@ -1,2 +0,0 @@ -//@ known-bug: #160490 -fn f(...: u8) {} diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.rs similarity index 100% rename from tests/ui/parser/recover-invalid-function-parameter-pattern.rs rename to tests/ui/parser/recover-invalid-function-parameter-pattern-1.rs diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr similarity index 75% rename from tests/ui/parser/recover-invalid-function-parameter-pattern.stderr rename to tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr index d4b78db29dba9..0bf724d0db8eb 100644 --- a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-1.stderr @@ -1,5 +1,5 @@ error: unexpected `...` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:9 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:9 | LL | fn main(... : ...) | ^^^ not a valid pattern @@ -11,7 +11,7 @@ LL + fn main(.. : ...) | error: unexpected `...` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:15 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:15 | LL | fn main(... : ...) | ^^^ @@ -19,7 +19,7 @@ LL | fn main(... : ...) = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list error: expected one of `->`, `where`, or `{`, found `` - --> $DIR/recover-invalid-function-parameter-pattern.rs:3:18 + --> $DIR/recover-invalid-function-parameter-pattern-1.rs:3:18 | LL | fn main(... : ...) | ^ expected one of `->`, `where`, or `{` diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs new file mode 100644 index 0000000000000..ea0233f433099 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.rs @@ -0,0 +1,8 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160490. + +fn f(...: u8) {} +//~^ ERROR unexpected `...` +//~| ERROR missing pattern for `...` argument +//~| WARN this was previously accepted by the compiler + +fn main() {} diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr new file mode 100644 index 0000000000000..7a9ea16a9d5d5 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern-2.stderr @@ -0,0 +1,43 @@ +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - fn f(...: u8) {} +LL + fn f(..: u8) {} + | + +error: missing pattern for `...` argument + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 + = note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default +help: name the argument, or use `_` to continue ignoring it + | +LL | fn f(_: ...: u8) {} + | ++ + +error: aborting due to 2 previous errors + +Future incompatibility report: Future breakage diagnostic: +error: missing pattern for `...` argument + --> $DIR/recover-invalid-function-parameter-pattern-2.rs:3:6 + | +LL | fn f(...: u8) {} + | ^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #145544 + = note: `#[deny(varargs_without_pattern)]` (part of `#[deny(future_incompatible)]`) on by default +help: name the argument, or use `_` to continue ignoring it + | +LL | fn f(_: ...: u8) {} + | ++ + From 29ff6f98fc92c4adb5111422daffacc93ef800b2 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:15:03 +0200 Subject: [PATCH 0720/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-23 (6bb1652a020e80cef79332741d89e996d71933c9). --- compiler/rustc_codegen_cranelift/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index a4cf19824d3d2..84d28e7f293e0 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-22" +channel = "nightly-2026-09-23" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From e3d5fb05b91b8534aa6f56b041c891c5262c6c32 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Wed, 23 Sep 2026 18:20:11 +0200 Subject: [PATCH 0721/1309] regression test for async handler normalization ICE --- .../normalize-erased-async-handler-141850.rs | 33 +++++++++++++++++++ ...rmalize-erased-async-handler-141850.stderr | 10 ++++++ 2 files changed, 43 insertions(+) create mode 100644 tests/ui/traits/next-solver/normalize-erased-async-handler-141850.rs create mode 100644 tests/ui/traits/next-solver/normalize-erased-async-handler-141850.stderr diff --git a/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.rs b/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.rs new file mode 100644 index 0000000000000..1072993378052 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.rs @@ -0,0 +1,33 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/141850. +//@ edition: 2024 +//@ compile-flags: -Znext-solver=globally + +#![feature(pin_ergonomics)] +#![allow(incomplete_features, dead_code, unused_must_use)] + +async fn a() { + wrapper_call(handler).await; +} + +async fn wrapper_call(_: F) -> F::Output +where + F: Handler, +{ + todo!() +} + +async fn handler(); //~ ERROR free function without a body + +trait Handler { + type Output; +} + +impl Handler for Func +where + Func: Fn() -> Fut, + Fut: Future, +{ + type Output = Fut; +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.stderr b/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.stderr new file mode 100644 index 0000000000000..d4366e58734e5 --- /dev/null +++ b/tests/ui/traits/next-solver/normalize-erased-async-handler-141850.stderr @@ -0,0 +1,10 @@ +error: free function without a body + --> $DIR/normalize-erased-async-handler-141850.rs:19:1 + | +LL | async fn handler(); + | ^^^^^^^^^^^^^^^^^^- + | | + | help: provide a definition for the function: `{ }` + +error: aborting due to 1 previous error + From 8201a7b4bd655461299236b4e7b815411f1a42e5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 6 Sep 2026 10:57:37 +0200 Subject: [PATCH 0722/1309] give noalias back to refs in closures --- compiler/rustc_middle/src/ty/sty.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index fe569bf282d36..103d9c37a2297 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2190,7 +2190,7 @@ impl<'tcx> Ty<'tcx> { def.flags().contains(AdtFlags::IS_MAYBE_DANGLING) || def.flags().contains(AdtFlags::IS_MANUALLY_DROP) } - ty::Closure(..) | ty::Coroutine(..) | ty::CoroutineClosure(..) => true, + ty::Coroutine(..) | ty::CoroutineClosure(..) => true, _ => false, } } From b81ddc962702e4b908fed61282c607d2150c3a56 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 23 Sep 2026 18:09:51 +0200 Subject: [PATCH 0723/1309] Revert "remove no-longer-needed MaybeDangling from thread spawning" This reverts commit 95d43bf5355ae272eb6b9b33202a3a8cae4fca4c. Now that closures have field retagging again, we need this MaybeDangling again. --- library/std/src/thread/lifecycle.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/std/src/thread/lifecycle.rs b/library/std/src/thread/lifecycle.rs index c22b97c39ecd5..b435f7185f043 100644 --- a/library/std/src/thread/lifecycle.rs +++ b/library/std/src/thread/lifecycle.rs @@ -7,6 +7,7 @@ use super::thread::Thread; use super::{Result, spawnhook}; use crate::cell::UnsafeCell; use crate::marker::PhantomData; +use crate::mem::MaybeDangling; use crate::sync::Arc; use crate::sync::atomic::{Atomic, AtomicUsize, Ordering}; use crate::sys::{AsInner, IntoInner, thread as imp}; @@ -56,9 +57,14 @@ where Arc::new(Packet { scope: scope_data, result: UnsafeCell::new(None), _marker: PhantomData }); let their_packet = my_packet.clone(); + // Pass `f` in `MaybeDangling` because actually that closure might *run longer than the lifetime of `F`*. + // See for more details. + let f = MaybeDangling::new(f); + // The entrypoint of the Rust thread, after platform-specific thread // initialization is done. let rust_start = move || { + let f = f.into_inner(); let try_result = panic::catch_unwind(panic::AssertUnwindSafe(|| { crate::sys::backtrace::__rust_begin_short_backtrace(|| hooks.inherit_and_run()); crate::sys::backtrace::__rust_begin_short_backtrace(f) From 69f75dbd9240907f15b49d8079a529a3b4fa500d Mon Sep 17 00:00:00 2001 From: hizyyo Date: Sat, 5 Sep 2026 21:33:26 +0500 Subject: [PATCH 0724/1309] Move the foreign module #[link] ABI check to attribute parsing --- compiler/rustc_ast_lowering/src/lib.rs | 1 + .../src/attributes/allow_unstable.rs | 2 +- .../src/attributes/codegen_attrs.rs | 4 +- .../src/attributes/inline.rs | 2 +- .../src/attributes/link_attrs.rs | 19 ++++++-- .../src/attributes/lint_helpers.rs | 2 +- .../src/attributes/macro_attrs.rs | 2 +- .../rustc_attr_parsing/src/attributes/mod.rs | 8 ++-- compiler/rustc_attr_parsing/src/context.rs | 2 +- .../rustc_attr_parsing/src/diagnostics.rs | 7 +++ compiler/rustc_attr_parsing/src/interface.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 19 +------- compiler/rustc_passes/src/diagnostics.rs | 7 --- tests/ui/attributes/link-foreign-mod-abi.rs | 45 +++++++++++++++++++ tests/ui/attributes/link-invalid-abi.rs | 13 ++++++ tests/ui/attributes/link-invalid-abi.stderr | 24 ++++++++++ ...issue-43106-gating-of-builtin-attrs.stderr | 16 +++---- 17 files changed, 127 insertions(+), 48 deletions(-) create mode 100644 tests/ui/attributes/link-foreign-mod-abi.rs create mode 100644 tests/ui/attributes/link-invalid-abi.rs create mode 100644 tests/ui/attributes/link-invalid-abi.stderr diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8513ee39855d0..efb434c921653 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -41,6 +41,7 @@ use std::mem; use std::sync::{Arc, LazyLock}; +use rustc_abi::ExternAbi; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; diff --git a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs index 667c2d0838a25..4a6e57b12233a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs +++ b/compiler/rustc_attr_parsing/src/attributes/allow_unstable.rs @@ -26,7 +26,7 @@ impl CombineAttributeParser for AllowInternalUnstableParser { .zip(iter::repeat(cx.attr_span)) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { check_macro_only(cx, attr_span); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs index bff7d7ad81cb9..2553829f8c5ce 100644 --- a/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/codegen_attrs.rs @@ -349,7 +349,7 @@ impl NoArgsAttributeParser for TrackCallerParser { const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = AttributeKind::TrackCaller; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { match cx.target { Target::Fn => { // `#[track_caller]` is not valid on weak lang items because they are called via @@ -571,7 +571,7 @@ impl CombineAttributeParser for TargetFeatureParser { parse_tf_attribute(cx, args) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[target_feature]` is incompatible with lang item functions, // except on WASM where calling target-feature functions is safe (see #84988). if !cx.sess().target.is_like_wasm && !cx.sess().opts.actually_rustdoc { diff --git a/compiler/rustc_attr_parsing/src/attributes/inline.rs b/compiler/rustc_attr_parsing/src/attributes/inline.rs index f3e305ea266a1..78a989fdfdba6 100644 --- a/compiler/rustc_attr_parsing/src/attributes/inline.rs +++ b/compiler/rustc_attr_parsing/src/attributes/inline.rs @@ -94,7 +94,7 @@ impl SingleAttributeParser for RustcForceInlineParser { )) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { let Some(inline_span) = find_attr!(cx.parsed_attrs, Inline(attr, span) if !matches!(attr, InlineAttr::Force { .. }) => span) else { return; diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index a00e5af00c2eb..e3e74971e99db 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -1,8 +1,10 @@ +use rustc_abi::ExternAbi; +use rustc_ast::ItemKind; use rustc_attr_ir::AttributeKind::{LinkName, LinkOrdinal, LinkSection}; use rustc_attr_ir::*; use rustc_errors::msg; use rustc_feature::{AttributeStability, Features}; -use rustc_lint_defs::builtin::ILL_FORMED_ATTRIBUTE_INPUT; +use rustc_lint_defs::builtin::{ILL_FORMED_ATTRIBUTE_INPUT, UNUSED_ATTRIBUTES}; use rustc_session::Session; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition::Edition2024; @@ -17,7 +19,7 @@ use crate::attributes::cfg::parse_cfg_entry; use crate::diagnostics::{ AsNeededCompatibility, BothFfiConstAndPure, BundleNeedsStatic, EmptyLinkName, ExportSymbolsNeedsStatic, ImportNameTypeRaw, ImportNameTypeX86, IncompatibleWasmLink, - InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, LinkFrameworkApple, + InvalidLinkModifier, InvalidMachoSection, InvalidMachoSectionReason, Link, LinkFrameworkApple, LinkOrdinalOutOfRange, LinkRequiresName, MultipleModifiers, NullOnLinkName, NullOnLinkSection, RawDylibOnlyWindows, WholeArchiveNeedsStatic, }; @@ -258,6 +260,17 @@ impl CombineAttributeParser for LinkParser { import_name_type, }) } + + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { + let Some(item) = cx.target_item else { return }; + let ItemKind::ForeignMod(fm) = &item.kind else { return }; + let abi = fm.abi.map_or(ExternAbi::FALLBACK, |abi| { + abi.symbol_unescaped.as_str().parse().unwrap_or(ExternAbi::Rust) + }); + if matches!(abi, ExternAbi::Rust) { + cx.emit_lint(UNUSED_ATTRIBUTES, Link, attr_span); + } + } } impl LinkParser { @@ -584,7 +597,7 @@ impl NoArgsAttributeParser for FfiPureParser { const STABILITY: AttributeStability = unstable!(ffi_pure); const CREATE: fn(Span) -> AttributeKind = AttributeKind::FfiPure; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[ffi_const]` functions cannot be `#[ffi_pure]`. if cx.all_attrs.iter().any(|a| a.word_is(sym::ffi_const)) { cx.emit_err(BothFfiConstAndPure { attr_span }); diff --git a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs index 4ead90af8d630..10e42ced30705 100644 --- a/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs +++ b/compiler/rustc_attr_parsing/src/attributes/lint_helpers.rs @@ -29,7 +29,7 @@ impl NoArgsAttributeParser for RustcPubTransparentParser { const STABILITY: AttributeStability = unstable!(rustc_attrs); const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcPubTransparent; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { // `#[rustc_pub_transparent]` may only be applied to `#[repr(transparent)]` types. let is_transparent = find_attr!( cx.parsed_attrs, diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 92b61fe00b1b9..dde10225e652f 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -136,7 +136,7 @@ impl NoArgsAttributeParser for AllowInternalUnsafeParser { const STABILITY: AttributeStability = unstable!(allow_internal_unsafe); const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span); - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { check_macro_only(cx, attr_span); } } diff --git a/compiler/rustc_attr_parsing/src/attributes/mod.rs b/compiler/rustc_attr_parsing/src/attributes/mod.rs index 242b4a73b06a6..8e47414f6c72a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/mod.rs +++ b/compiler/rustc_attr_parsing/src/attributes/mod.rs @@ -169,7 +169,7 @@ pub(crate) trait SingleAttributeParser: 'static { /// combinations. `attr_span` is the span of this attribute. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } /// Use in combination with [`SingleAttributeParser`]. @@ -287,7 +287,7 @@ pub(crate) trait NoArgsAttributeParser: 'static { /// `attr_span` is the span of this attribute. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } pub(crate) struct WithoutArgs(PhantomData); @@ -311,7 +311,7 @@ impl SingleAttributeParser for WithoutArgs { Some(T::CREATE(cx.attr_span)) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { T::finalize_check(cx, attr_span) } } @@ -355,7 +355,7 @@ pub(crate) trait CombineAttributeParser: 'static { /// `attr_span` is the span of the first attribute that was encountered. /// /// Defaults to a no-op. - fn finalize_check(_cx: &FinalizeCheckContext<'_, '_>, _attr_span: Span) {} + fn finalize_check(_cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) {} } /// Use in combination with [`CombineAttributeParser`]. diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 22a4a069b75c7..72839643b4dc3 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -102,7 +102,7 @@ pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> FinalizeOutput; /// finalized, so it can inspect the fully parsed attributes via /// [`FinalizeCheckContext::parsed_attrs`]. The [`Span`] is the span of the attribute the /// check is associated with, used for diagnostics. -pub(crate) type FinalizeCheckFn = fn(&FinalizeCheckContext<'_, '_>, Span); +pub(crate) type FinalizeCheckFn = fn(&mut FinalizeCheckContext<'_, '_>, Span); /// The result of finalizing a single attribute parser. pub(crate) struct FinalizeOutput { diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 44e405fcf5269..bf630c6bf91a0 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1825,6 +1825,13 @@ pub(crate) struct EmptyLinkName { pub span: Span, } +#[derive(Diagnostic)] +#[diag("attribute should be applied to an `extern` block with non-Rust ABI")] +#[warning( + "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" +)] +pub(crate) struct Link; + #[derive(Diagnostic)] #[diag("link kind `framework` is only supported on Apple targets", code = E0455)] pub(crate) struct LinkFrameworkApple { diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 48083683b6a7a..df89ffe57b9a0 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -512,7 +512,7 @@ impl<'sess> AttributeParser<'sess> { // inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`. for (check, attr_span) in deferred_checks { check( - &FinalizeCheckContext { + &mut FinalizeCheckContext { shared: SharedContext { cx: self, target_span, diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4926ec9872d3b..2c9a18239665e 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -8,7 +8,6 @@ use std::cell::Cell; use std::slice; -use rustc_abi::ExternAbi; use rustc_ast::MetaItemKind; use rustc_attr_ir::diagnostic::Directive; use rustc_attr_ir::lang_items::LangItem; @@ -208,7 +207,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } AttributeKind::Naked(..) => self.check_naked(hir_id, target), AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), - AttributeKind::Link(_, attr_span) => self.check_link(hir_id, *attr_span, target), AttributeKind::MacroExport { span, .. } => { self.check_macro_export(hir_id, *span, target) } @@ -271,6 +269,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::InstructionSet(..) => (), AttributeKind::InstrumentFn(..) => (), AttributeKind::Lang(..) => (), + AttributeKind::Link(..) => (), AttributeKind::LinkName { .. } => (), AttributeKind::LinkOrdinal { .. } => (), AttributeKind::LinkSection { .. } => (), @@ -1100,22 +1099,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(diagnostics::InvalidMayDangle { attr_span }); } - /// Checks if `#[link]` is applied to an item other than a foreign module. - fn check_link(&self, hir_id: HirId, attr_span: Span, target: Target) { - if target != Target::ForeignMod { - return; // Checked by attribute parser - } - - if let hir::Node::Item(item) = self.tcx.hir_node(hir_id) - && let Item { kind: ItemKind::ForeignMod { abi, .. }, .. } = item - && !matches!(abi, ExternAbi::Rust) - { - return; - } - - self.tcx.emit_node_span_lint(UNUSED_ATTRIBUTES, hir_id, attr_span, diagnostics::Link); - } - /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. fn check_rustc_legacy_const_generics( &self, diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 59c1005885903..7c82811f99276 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -126,13 +126,6 @@ pub(crate) struct BothOptimizeNoneAndInline { pub inline_span: Span, } -#[derive(Diagnostic)] -#[diag("attribute should be applied to an `extern` block with non-Rust ABI")] -#[warning( - "this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!" -)] -pub(crate) struct Link; - #[derive(Diagnostic)] #[diag("#[rustc_legacy_const_generics] functions must only have const generics")] pub(crate) struct RustcLegacyConstGenericsOnly { diff --git a/tests/ui/attributes/link-foreign-mod-abi.rs b/tests/ui/attributes/link-foreign-mod-abi.rs new file mode 100644 index 0000000000000..83d0a2dd47f0b --- /dev/null +++ b/tests/ui/attributes/link-foreign-mod-abi.rs @@ -0,0 +1,45 @@ +//@ check-pass +//@ compile-flags: --crate-type=lib + +#![no_core] +#![feature(no_core, rust_cold_cc, rust_preserve_none_cc, rust_tail_cc, unboxed_closures)] +#![allow(missing_abi)] +#![deny(unfulfilled_lint_expectations, unused_attributes)] + +#[link(name = "omitted")] +extern {} + +#[link(name = "c")] +extern "C" {} + +#[link(name = "rust-call")] +extern "rust-call" {} + +#[link(name = "rust-cold")] +extern "rust-cold" {} + +#[link(name = "rust-preserve-none")] +extern "rust-preserve-none" {} + +#[link(name = "tail")] +extern "tail" {} + +#[cfg_attr(any(), link(name = "disabled"))] +extern "Rust" {} + +#[expect(unused_attributes)] +#[cfg_attr(all(), link(name = "enabled"))] +extern "Rust" {} + +#[allow(unused_attributes)] +#[link(name = "allowed")] +extern "Rust" {} + +#[expect(unused_attributes)] +#[link(name = "expected")] +extern "Rust" {} + +#[expect(unused_attributes)] +#[link(name = "first")] +#[link(name = "second")] +extern "Rust" {} diff --git a/tests/ui/attributes/link-invalid-abi.rs b/tests/ui/attributes/link-invalid-abi.rs new file mode 100644 index 0000000000000..49f91236c1a2b --- /dev/null +++ b/tests/ui/attributes/link-invalid-abi.rs @@ -0,0 +1,13 @@ +//@ check-fail +//@ compile-flags: --crate-type=lib + +#![no_core] +#![feature(no_core)] +#![warn(unused_attributes)] + +#[link(name = "first")] +//~^ WARN +//~| WARN +#[link(name = "second")] +extern "invalid" {} +//~^ ERROR diff --git a/tests/ui/attributes/link-invalid-abi.stderr b/tests/ui/attributes/link-invalid-abi.stderr new file mode 100644 index 0000000000000..add2ebcb7c186 --- /dev/null +++ b/tests/ui/attributes/link-invalid-abi.stderr @@ -0,0 +1,24 @@ +error[E0703]: invalid ABI: found `invalid` + --> $DIR/link-invalid-abi.rs:12:8 + | +LL | extern "invalid" {} + | ^^^^^^^^^ invalid ABI + | + = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions + +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/link-invalid-abi.rs:8:1 + | +LL | #[link(name = "first")] + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +note: the lint level is defined here + --> $DIR/link-invalid-abi.rs:6:9 + | +LL | #![warn(unused_attributes)] + | ^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr index a677339551153..2d3b7658f9aae 100644 --- a/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr +++ b/tests/ui/feature-gates/issue-43106-gating-of-builtin-attrs.stderr @@ -207,14 +207,6 @@ note: the lint level is defined here LL | #![warn(unused_attributes, unknown_lints)] | ^^^^^^^^^^^^^^^^^ -warning: attribute should be applied to an `extern` block with non-Rust ABI - --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 - | -LL | #[link(name = "x")] extern "Rust" {} - | ^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - warning: the `macro_use` attribute cannot be used on crates --> $DIR/issue-43106-gating-of-builtin-attrs.rs:45:4 | @@ -978,6 +970,14 @@ LL | #[link(name = "x")] impl S { } = help: the `link` attribute can only be applied to foreign modules = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! +warning: attribute should be applied to an `extern` block with non-Rust ABI + --> $DIR/issue-43106-gating-of-builtin-attrs.rs:729:5 + | +LL | #[link(name = "x")] extern "Rust" {} + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + warning: the `must_use` attribute cannot be used on modules --> $DIR/issue-43106-gating-of-builtin-attrs.rs:749:3 | From 0c182d66b47f8203e551f0302022bcd9ea5c5277 Mon Sep 17 00:00:00 2001 From: hizyyo Date: Sat, 12 Sep 2026 16:00:46 +0500 Subject: [PATCH 0725/1309] Fix finalize_check signatures --- compiler/rustc_ast_lowering/src/lib.rs | 1 - compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index efb434c921653..8513ee39855d0 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -41,7 +41,6 @@ use std::mem; use std::sync::{Arc, LazyLock}; -use rustc_abi::ExternAbi; use rustc_ast::mut_visit::{self, MutVisitor}; use rustc_ast::node_id::NodeMap; use rustc_ast::visit::{self, Visitor}; diff --git a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs index 30fdadf95e4ce..2acba84956e67 100644 --- a/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs +++ b/compiler/rustc_attr_parsing/src/attributes/non_exhaustive.rs @@ -21,7 +21,7 @@ impl NoArgsAttributeParser for NonExhaustiveParser { const STABILITY: AttributeStability = AttributeStability::Stable; const CREATE: fn(Span) -> AttributeKind = AttributeKind::NonExhaustive; - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { if cx.target != Target::Struct { return; } From 89da8633dd9a996e633aae359cc100a009e98ae4 Mon Sep 17 00:00:00 2001 From: hizyyo Date: Sat, 19 Sep 2026 18:23:47 +0500 Subject: [PATCH 0726/1309] Address link attribute finalization invariants --- .../src/attributes/link_attrs.rs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index e3e74971e99db..f4d0fa35e3f47 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -262,10 +262,22 @@ impl CombineAttributeParser for LinkParser { } fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - let Some(item) = cx.target_item else { return }; - let ItemKind::ForeignMod(fm) = &item.kind else { return }; + if cx.target != Target::ForeignMod { + return; + } + + let item = cx.target_item.expect("missing AST target item for Target::ForeignMod"); + let ItemKind::ForeignMod(fm) = &item.kind else { + panic!("expected foreign module AST target item for Target::ForeignMod"); + }; let abi = fm.abi.map_or(ExternAbi::FALLBACK, |abi| { - abi.symbol_unescaped.as_str().parse().unwrap_or(ExternAbi::Rust) + abi.symbol_unescaped.as_str().parse().unwrap_or_else(|_| { + cx.dcx().span_delayed_bug( + abi.span, + "LinkParser::finalize_check was unable to pre-detect the ABI, so it continues to use the recovery value solely to check for unused_attributes in the lint; a user error E0703 will be reported later in lower_abi", + ); + ExternAbi::Rust + }) }); if matches!(abi, ExternAbi::Rust) { cx.emit_lint(UNUSED_ATTRIBUTES, Link, attr_span); From 12a8eb2a7a19d50e2858d934da38fd0a212267c8 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 15 Sep 2026 19:38:04 +0000 Subject: [PATCH 0727/1309] Move RegionInferenceContext to its own file --- compiler/rustc_borrowck/src/consumers.rs | 2 +- .../src/diagnostics/opaque_types.rs | 2 +- .../src/diagnostics/region_errors.rs | 4 +- .../src/region_infer/graphviz.rs | 1 + .../rustc_borrowck/src/region_infer/mod.rs | 1673 +---------------- .../src/region_infer/opaque_types/mod.rs | 2 +- .../src/region_infer/region_context.rs | 1673 +++++++++++++++++ 7 files changed, 1689 insertions(+), 1668 deletions(-) create mode 100644 compiler/rustc_borrowck/src/region_infer/region_context.rs diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs index 4039c2d88c6be..f6d0599773e94 100644 --- a/compiler/rustc_borrowck/src/consumers.rs +++ b/compiler/rustc_borrowck/src/consumers.rs @@ -16,7 +16,7 @@ pub use super::polonius::legacy::{ PoloniusFacts as PoloniusInput, PoloniusLocationTable, PoloniusOutput, PoloniusRegionVid, RichLocation, RustcFacts, }; -pub use super::region_infer::RegionInferenceContext; +use super::region_infer::RegionInferenceContext; use crate::BorrowCheckRootCtxt; /// Struct used during mir borrowck to collect bodies with facts for a typeck root and all diff --git a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs index 9bfae5582d9fe..9038b71ade222 100644 --- a/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs +++ b/compiler/rustc_borrowck/src/diagnostics/opaque_types.rs @@ -17,7 +17,7 @@ use rustc_trait_selection::error_reporting::infer::region::unexpected_hidden_reg use crate::MirBorrowckCtxt; use crate::borrow_set::BorrowData; -use crate::consumers::RegionInferenceContext; +use crate::region_infer::RegionInferenceContext; use crate::region_infer::opaque_types::DeferredOpaqueTypeError; use crate::type_check::Locations; diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 414f8dd58d439..278467ef893cc 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -27,9 +27,9 @@ use rustc_trait_selection::traits::{Obligation, ObligationCtxt}; use tracing::{debug, instrument, trace}; use super::{LIMITATION_NOTE, OutlivesSuggestionBuilder, RegionName, RegionNameSource}; -use crate::consumers::{OutlivesConstraint, RegionInferenceContext}; +use crate::consumers::OutlivesConstraint; use crate::nll::ConstraintDescription; -use crate::region_infer::TypeTest; +use crate::region_infer::{RegionInferenceContext, TypeTest}; use crate::session_diagnostics::{ FnMutError, FnMutReturnTypeErr, GenericDoesNotLiveLongEnough, LifetimeOutliveErr, LifetimeReturnCategoryErr, RequireStaticErr, VarHereDenote, diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs index ceb33d82deba8..5b0491a526204 100644 --- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs +++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs @@ -8,6 +8,7 @@ use std::io::{self, Write}; use itertools::Itertools; use rustc_graphviz as dot; use rustc_middle::ty::UniverseIndex; +use rustc_span::bug; use super::*; diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 75ee675b71232..8c589113ad5b2 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -1,45 +1,27 @@ -use std::collections::VecDeque; use std::fmt; -use std::rc::Rc; -use rustc_data_structures::frozen::Frozen; +pub(crate) use region_context::*; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::graph::scc::Sccs; -use rustc_errors::Diag; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_index::IndexVec; -use rustc_infer::infer::outlives::test_type_match; -use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound, VerifyIfEq}; -use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; -use rustc_middle::mir::{ - AnnotationSource, BasicBlock, Body, ConstraintCategory, Local, Location, ReturnConstraint, - TerminatorKind, -}; +use rustc_infer::infer::NllRegionVariableOrigin; +use rustc_infer::infer::region_constraints::{GenericKind, VerifyBound}; +use rustc_middle::mir::{ConstraintCategory, Local, Location}; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; -use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; -use rustc_mir_dataflow::points::DenseLocationMap; -use rustc_span::hygiene::DesugaringKind; -use rustc_span::{DUMMY_SP, Span, bug}; -use tracing::{Level, debug, enabled, instrument, trace}; +use rustc_middle::ty::{self, RegionVid, TyCtxt}; +use rustc_span::Span; +use tracing::{Level, debug, enabled, instrument}; -use crate::constraints::graph::NormalConstraintGraph; +use crate::BorrowckInferCtxt; use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}; -use crate::dataflow::BorrowIndex; -use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}; -use crate::handle_placeholders::{LoweredConstraints, RegionTracker}; -use crate::polonius::legacy::PoloniusOutput; -use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues}; +use crate::handle_placeholders::RegionTracker; use crate::type_check::Locations; -use crate::type_check::free_region_relations::UniversalRegionRelations; -use crate::universal_regions::UniversalRegions; -use crate::{ - BorrowckInferCtxt, ClosureOutlivesRequirement, ClosureOutlivesSubject, - ClosureOutlivesSubjectTy, ClosureRegionRequirements, -}; mod dump_mir; mod graphviz; pub(crate) mod opaque_types; +mod region_context; mod reverse_sccs; pub(crate) mod values; @@ -75,50 +57,6 @@ impl Representative { pub(crate) type ConstraintSccs = Sccs; -pub struct RegionInferenceContext<'tcx> { - /// Contains the definition for every region variable. Region - /// variables are identified by their index (`RegionVid`). The - /// definition contains information about where the region came - /// from as well as its final inferred value. - pub(crate) definitions: Frozen>>, - - /// The liveness constraints added to each region. For most - /// regions, these start out empty and steadily grow, though for - /// each universally quantified region R they start out containing - /// the entire CFG and `end(R)`. - liveness_constraints: LivenessValues, - - /// The outlives constraints computed by the type-check. - constraints: Frozen>, - - /// The constraint-set, but in graph form, making it easy to traverse - /// the constraints adjacent to a particular region. Used to construct - /// the SCC (see `constraint_sccs`) and for error reporting. - constraint_graph: Frozen, - - /// The SCC computed from `constraints` and the constraint - /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to - /// compute the values of each region. - constraint_sccs: ConstraintSccs, - - scc_annotations: IndexVec, - - /// Map universe indexes to information on why we created it. - universe_causes: FxIndexMap>, - - /// The final inferred values of the region variables; we compute - /// one value per SCC. To get the value for any given *region*, - /// you first find which scc it is a part of. - scc_values: RegionValues<'tcx, ConstraintSccIndex>, - - /// Type constraints that we check after solving. - type_tests: Vec>, - - /// Information about how the universally quantified regions in - /// scope on this function relate to one another. - universal_region_relations: Frozen>, -} - #[derive(Debug)] pub(crate) struct RegionDefinition<'tcx> { /// What kind of variable is this -- a free region? existential @@ -321,1597 +259,6 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { debug!("SCC edges {:#?}", scc_node_to_edges); } -impl<'tcx> RegionInferenceContext<'tcx> { - /// Creates a new region inference context with a total of - /// `num_region_variables` valid inference variables; the first N - /// of those will be constant regions representing the free - /// regions defined in `universal_regions`. - /// - /// The `outlives_constraints` and `type_tests` are an initial set - /// of constraints produced by the MIR type check. - pub(crate) fn new( - infcx: &BorrowckInferCtxt<'tcx>, - lowered_constraints: LoweredConstraints<'tcx>, - universal_region_relations: Frozen>, - location_map: Rc, - ) -> Self { - let universal_regions = &universal_region_relations.universal_regions; - - let LoweredConstraints { - constraint_sccs, - definitions, - outlives_constraints, - scc_annotations, - type_tests, - liveness_constraints, - universe_causes, - placeholder_indices, - } = lowered_constraints; - - debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); - debug!("outlives constraints: {:#?}", outlives_constraints); - debug!("placeholder_indices: {:#?}", placeholder_indices); - debug!("type tests: {:#?}", type_tests); - - let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); - - if cfg!(debug_assertions) { - sccs_info(infcx, &constraint_sccs); - } - - let mut scc_values = - RegionValues::new(location_map, universal_regions.len(), placeholder_indices); - - // Initializes the region variables with their initial live points. - for (region, definition) in definitions.iter_enumerated() { - let scc = constraint_sccs.scc(region); - - // For each universally quantified region (lifetime parameter). The - // first N variables always correspond to the regions appearing in the - // function signature (both named and anonymous) and in where-clauses. - match definition.origin { - // For each free, universally quantified region X: - NllRegionVariableOrigin::FreeRegion => { - // Add `end(X)` into the set for X. - scc_values.add_free_region(scc, region); - } - - NllRegionVariableOrigin::Placeholder(placeholder) => { - scc_values.add_placeholder(scc, placeholder); - } - - NllRegionVariableOrigin::Existential { .. } => { - // For existential, regions, nothing to do. - } - } - - // Initially copy the liveness constraints of any region that - // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. - // - // These values will later be propagated during [`Self::propagate_constraints()`]. - // The values include any live-at-all-points constraints added previously in `liveness::generate`. - if let Some(liveness) = liveness_constraints.point_liveness(region) { - scc_values.merge_liveness(scc, liveness) - } - } - - Self { - definitions, - liveness_constraints, - constraints: outlives_constraints, - constraint_graph, - constraint_sccs, - scc_annotations, - universe_causes, - scc_values, - type_tests, - universal_region_relations, - } - } - - /// Returns an iterator over all the region indices. - pub(crate) fn regions(&self) -> impl Iterator + 'tcx { - self.definitions.indices() - } - - /// Given a universal region in scope on the MIR, returns the - /// corresponding index. - /// - /// Panics if `r` is not a registered universal region, most notably - /// if it is a placeholder. Handling placeholders requires access to the - /// `MirTypeckRegionConstraints`. - pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { - self.universal_regions().to_region_vid(r) - } - - /// Returns an iterator over all the outlives constraints. - pub(crate) fn outlives_constraints(&self) -> impl Iterator> { - self.constraints.outlives().iter().copied() - } - - /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. - pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) { - self.universal_regions().annotate(tcx, err) - } - - /// Returns `true` if the region `r` contains the point `p`. - /// - /// Panics if called before `solve()` executes, - pub(crate) fn region_contains_point(&self, r: RegionVid, p: Location) -> bool { - let scc = self.constraint_sccs.scc(r); - self.scc_values.contains_point(scc, p) - } - - /// Returns the lowest statement index in `start..=end` which is not contained by `r`. - /// - /// Panics if called before `solve()` executes. - pub(crate) fn first_non_contained_inclusive( - &self, - r: RegionVid, - block: BasicBlock, - start: usize, - end: usize, - ) -> Option { - let scc = self.constraint_sccs.scc(r); - self.scc_values.first_non_contained_inclusive(scc, block, start, end) - } - - /// Returns access to the value of `r` for debugging purposes. - pub(crate) fn region_value_str(&self, r: RegionVid) -> String { - let scc = self.constraint_sccs.scc(r); - self.scc_values.region_value_str(scc) - } - - pub(crate) fn placeholders_contained_in( - &self, - r: RegionVid, - ) -> impl Iterator> { - let scc = self.constraint_sccs.scc(r); - self.scc_values.placeholders_contained_in(scc) - } - - /// Performs region inference and report errors if we see any - /// unsatisfiable constraints. If this is a closure, returns the - /// region requirements to propagate to our creator, if any. - #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] - pub(super) fn solve( - &mut self, - infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, - polonius_output: Option>, - ) -> (Option>, RegionErrors<'tcx>) { - let mir_def_id = body.source.def_id(); - self.propagate_constraints(); - - let mut errors_buffer = RegionErrors::new(infcx.tcx); - - // If this is a nested body, we propagate unsatisfied - // outlives constraints to the parent body instead of - // eagerly erroing. - let mut propagated_outlives_requirements = - infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - - self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); - - debug!(?errors_buffer); - debug!(?propagated_outlives_requirements); - - // In Polonius mode, the errors about missing universal region relations are in the output - // and need to be emitted or propagated. Otherwise, we need to check whether the - // constraints were too strong, and if so, emit or propagate those errors. - if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { - self.check_polonius_subset_errors( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - polonius_output - .as_ref() - .expect("Polonius output is unavailable despite `-Z polonius`"), - ); - } else { - self.check_universal_regions( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - ); - } - - debug!(?errors_buffer); - - let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); - - if propagated_outlives_requirements.is_empty() { - (None, errors_buffer) - } else { - let num_external_vids = self.universal_regions().num_global_and_external_regions(); - ( - Some(ClosureRegionRequirements { - num_external_vids, - outlives_requirements: propagated_outlives_requirements, - }), - errors_buffer, - ) - } - } - - /// Propagate the region constraints: this will grow the values - /// for each region variable until all the constraints are - /// satisfied. Note that some values may grow **too** large to be - /// feasible, but we check this later. - #[instrument(skip(self), level = "debug")] - fn propagate_constraints(&mut self) { - debug!("constraints={:#?}", { - let mut constraints: Vec<_> = self.outlives_constraints().collect(); - constraints.sort_by_key(|c| (c.sup, c.sub)); - constraints - .into_iter() - .map(|c| (c, self.constraint_sccs.scc(c.sup), self.constraint_sccs.scc(c.sub))) - .collect::>() - }); - - // To propagate constraints, we walk the DAG induced by the - // SCC. For each SCC `A`, we visit its successors and compute - // their values, then we union all those values to get our - // own. This one-shot approach works because iteration is in - // dependency order. I.e. a chain A: B: C will visit C, B, A. - for scc_a in self.constraint_sccs.all_sccs() { - // Walk each SCC `B` such that `A: B`... - for &scc_b in self.constraint_sccs.successors(scc_a) { - debug!(?scc_b); - self.scc_values.add_region(scc_a, scc_b); - } - } - } - - /// Returns `true` if all the placeholders in the value of `scc_b` are nameable - /// in `scc_a`. Used during constraint propagation, and only once - /// the value of `scc_b` has been computed. - fn can_name_all_placeholders( - &self, - scc_a: ConstraintSccIndex, - scc_b: ConstraintSccIndex, - ) -> bool { - self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) - } - - /// Once regions have been propagated, this method is used to see - /// whether the "type tests" produced by typeck were satisfied; - /// type tests encode type-outlives relationships like `T: - /// 'a`. See `TypeTest` for more details. - fn check_type_tests( - &self, - infcx: &InferCtxt<'tcx>, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - let tcx = infcx.tcx; - - // Sometimes we register equivalent type-tests that would - // result in basically the exact same error being reported to - // the user. Avoid that. - let mut deduplicate_errors = FxIndexSet::default(); - let mut failed_type_tests = Vec::new(); - - for type_test in &self.type_tests { - debug!("check_type_test: {:?}", type_test); - - let generic_ty = type_test.generic_kind.to_ty(tcx); - if self.eval_verify_bound( - infcx, - generic_ty, - type_test.lower_bound, - &type_test.verify_bound, - ) { - continue; - } - - if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements - && self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) - { - continue; - } - - // Type-test failed. Collect it so we can suppress redundant errors below. - let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind); - failed_type_tests.push((erased_generic_kind, type_test)); - } - - // An async body can produce both `G: 'static` and `G: 'a` type-test failures at - // the same span, as in `tests/ui/async-await/spurious-static-bound-issue-115376.rs`. - // Reporting the weaker bound adds a redundant diagnostic and suggests a lifetime - // bound that cannot fix the missing `G: 'static` requirement. Keep the `'static` - // error and suppress weaker failures for the same erased generic kind and span. - // This is a diagnostic heuristic, using the same erasure as deduplication below. - // - // Collect all failed `'static` bounds before reporting errors so suppression does - // not depend on the order of the type tests. Compare SCCs because a lower-bound - // region can be equivalent to `'static` without being `fr_static` itself. - let static_scc = self.constraint_sccs.scc(self.universal_regions().fr_static); - let static_bound_errors: FxIndexSet<_> = failed_type_tests - .iter() - .filter_map(|&(erased_generic_kind, type_test)| { - if self.constraint_sccs.scc(type_test.lower_bound) == static_scc { - Some((erased_generic_kind, type_test.span)) - } else { - None - } - }) - .collect(); - - // If `G: 'static` failed at this span, then same-span `G: 'a` failures are weaker. - for (erased_generic_kind, type_test) in failed_type_tests { - if self.constraint_sccs.scc(type_test.lower_bound) != static_scc - && static_bound_errors.contains(&(erased_generic_kind, type_test.span)) - { - continue; - } - - // Skip duplicate-ish errors. - if deduplicate_errors.insert(( - erased_generic_kind, - type_test.lower_bound, - type_test.span, - )) { - debug!( - "check_type_test: reporting error for erased_generic_kind={:?}, \ - lower_bound_region={:?}, \ - type_test.span={:?}", - erased_generic_kind, type_test.lower_bound, type_test.span, - ); - - errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); - } - } - } - - /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot - /// prove to be satisfied. If this is a closure, we will attempt to - /// "promote" this type-test into our `ClosureRegionRequirements` and - /// hence pass it up the creator. To do this, we have to phrase the - /// type-test in terms of external free regions, as local free - /// regions are not nameable by the closure's creator. - /// - /// Promotion works as follows: we first check that the type `T` - /// contains only regions that the creator knows about. If this is - /// true, then -- as a consequence -- we know that all regions in - /// the type `T` are free regions that outlive the closure body. If - /// false, then promotion fails. - /// - /// Once we've promoted T, we have to "promote" `'X` to some region - /// that is "external" to the closure. Generally speaking, a region - /// may be the union of some points in the closure body as well as - /// various free lifetimes. We can ignore the points in the closure - /// body: if the type T can be expressed in terms of external regions, - /// we know it outlives the points in the closure body. That - /// just leaves the free regions. - /// - /// The idea then is to lower the `T: 'X` constraint into multiple - /// bounds -- e.g., if `'X` is the union of two free lifetimes, - /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. - #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] - fn try_promote_type_test( - &self, - infcx: &InferCtxt<'tcx>, - type_test: &TypeTest<'tcx>, - propagated_outlives_requirements: &mut Vec>, - ) -> bool { - let tcx = infcx.tcx; - let TypeTest { generic_kind, lower_bound, span: blame_span, verify_bound: _ } = *type_test; - - let generic_ty = generic_kind.to_ty(tcx); - let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { - return false; - }; - - let r_scc = self.constraint_sccs.scc(lower_bound); - debug!( - "lower_bound = {:?} r_scc={:?} universe={:?}", - lower_bound, - r_scc, - self.max_nameable_universe(r_scc) - ); - // If the type test requires that `T: 'a` where `'a` is a - // placeholder from another universe, that effectively requires - // `T: 'static`, so we have to propagate that requirement. - // - // It doesn't matter *what* universe because the promoted `T` will - // always be in the root universe. - if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { - debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); - let static_r = self.universal_regions().fr_static; - propagated_outlives_requirements.push(ClosureOutlivesRequirement { - subject, - outlived_free_region: static_r, - blame_span, - category: ConstraintCategory::Boring, - }); - - // we can return here -- the code below might push add'l constraints - // but they would all be weaker than this one. - return true; - } - - // For each region outlived by lower_bound find a non-local, - // universal region (it may be the same region) and add it to - // `ClosureOutlivesRequirement`. - let mut found_outlived_universal_region = false; - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - found_outlived_universal_region = true; - debug!("universal_region_outlived_by ur={:?}", ur); - let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); - debug!(?non_local_ub); - - // This is slightly too conservative. To show T: '1, given `'2: '1` - // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to - // avoid potential non-determinism we approximate this by requiring - // T: '1 and T: '2. - for upper_bound in non_local_ub { - debug_assert!(self.universal_regions().is_universal_region(upper_bound)); - debug_assert!(!self.universal_regions().is_local_free_region(upper_bound)); - - let requirement = ClosureOutlivesRequirement { - subject, - outlived_free_region: upper_bound, - blame_span, - category: ConstraintCategory::Boring, - }; - debug!(?requirement, "adding closure requirement"); - propagated_outlives_requirements.push(requirement); - } - } - // If we succeed to promote the subject, i.e. it only contains non-local regions, - // and fail to prove the type test inside of the closure, the `lower_bound` has to - // also be at least as large as some universal region, as the type test is otherwise - // trivial. - assert!(found_outlived_universal_region); - true - } - - /// When we promote a type test `T: 'r`, we have to replace all region - /// variables in the type `T` with an equal universal region from the - /// closure signature. - /// This is not always possible, so this is a fallible process. - #[instrument(level = "debug", skip(self, infcx), ret)] - fn try_promote_type_test_subject( - &self, - infcx: &InferCtxt<'tcx>, - ty: Ty<'tcx>, - ) -> Option> { - let tcx = infcx.tcx; - let mut failed = false; - let ty = fold_regions(tcx, ty, |r, _depth| { - let r_vid = self.to_region_vid(r); - let r_scc = self.constraint_sccs.scc(r_vid); - - // The challenge is this. We have some region variable `r` - // whose value is a set of CFG points and universal - // regions. We want to find if that set is *equivalent* to - // any of the named regions found in the closure. - // To do so, we simply check every candidate `u_r` for equality. - self.scc_values - .universal_regions_outlived_by(r_scc) - .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r)) - .find(|&u_r| self.eval_equal(u_r, r_vid)) - .map(|u_r| ty::Region::new_var(tcx, u_r)) - // In case we could not find a named region to map to, - // we will return `None` below. - .unwrap_or_else(|| { - failed = true; - r - }) - }); - - debug!("try_promote_type_test_subject: folded ty = {:?}", ty); - - // This will be true if we failed to promote some region. - if failed { - return None; - } - - Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) - } - - /// Like `universal_upper_bound`, but returns an approximation more suitable - /// for diagnostics. If `r` contains multiple disjoint universal regions - /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. - /// This corresponds to picking named regions over unnamed regions - /// (e.g. picking early-bound regions over a closure late-bound region). - /// - /// This means that the returned value may not be a true upper bound, since - /// only 'static is known to outlive disjoint universal regions. - /// Therefore, this method should only be used in diagnostic code, - /// where displaying *some* named universal region is better than - /// falling back to 'static. - #[instrument(level = "debug", skip(self))] - pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!("{}", self.region_value_str(r)); - - // Find the smallest universal region that contains all other - // universal regions within `region`. - let mut lub = self.universal_regions().fr_fn_body; - let r_scc = self.constraint_sccs.scc(r); - let static_r = self.universal_regions().fr_static; - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur); - debug!(?ur, ?lub, ?new_lub); - // The upper bound of two non-static regions is static: this - // means we know nothing about the relationship between these - // two regions. Pick a 'better' one to use when constructing - // a diagnostic - if ur != static_r && lub != static_r && new_lub == static_r { - // Prefer the region with an `external_name` - this - // indicates that the region is early-bound, so working with - // it can produce a nicer error. - if self.region_definition(ur).external_name.is_some() { - lub = ur; - } else if self.region_definition(lub).external_name.is_some() { - // Leave lub unchanged - } else { - // If we get here, we don't have any reason to prefer - // one region over the other. Just pick the - // one with the lower index for now. - lub = std::cmp::min(ur, lub); - } - } else { - lub = new_lub; - } - } - - debug!(?r, ?lub); - - lub - } - - /// Tests if `test` is true when applied to `lower_bound` at - /// `point`. - fn eval_verify_bound( - &self, - infcx: &InferCtxt<'tcx>, - generic_ty: Ty<'tcx>, - lower_bound: RegionVid, - verify_bound: &VerifyBound<'tcx>, - ) -> bool { - debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound); - - match verify_bound { - VerifyBound::IfEq(verify_if_eq_b) => { - self.eval_if_eq(infcx, generic_ty, lower_bound, *verify_if_eq_b) - } - - VerifyBound::IsEmpty => { - let lower_bound_scc = self.constraint_sccs.scc(lower_bound); - self.scc_values.elements_contained_in(lower_bound_scc).next().is_none() - } - - VerifyBound::OutlivedBy(r) => { - let r_vid = self.to_region_vid(*r); - self.eval_outlives(r_vid, lower_bound) - } - - VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { - self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) - }), - - VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { - self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) - }), - } - } - - fn eval_if_eq( - &self, - infcx: &InferCtxt<'tcx>, - generic_ty: Ty<'tcx>, - lower_bound: RegionVid, - verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>, - ) -> bool { - let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty); - let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b); - match test_type_match::extract_verify_if_eq(infcx.tcx, &verify_if_eq_b, generic_ty) { - Some(r) => { - let r_vid = self.to_region_vid(r); - self.eval_outlives(r_vid, lower_bound) - } - None => false, - } - } - - /// This is a conservative normalization procedure. It takes every - /// free region in `value` and replaces it with the - /// "representative" of its SCC (see `scc_representatives` field). - /// We are guaranteed that if two values normalize to the same - /// thing, then they are equal; this is a conservative check in - /// that they could still be equal even if they normalize to - /// different results. (For example, there might be two regions - /// with the same value that are not in the same SCC). - /// - /// N.B., this is not an ideal approach and I would like to revisit - /// it. However, it works pretty well in practice. In particular, - /// this is needed to deal with projection outlives bounds like - /// - /// ```text - /// >::Item: '1 - /// ``` - /// - /// In particular, this routine winds up being important when - /// there are bounds like `where >::Item: 'b` in the - /// environment. In this case, if we can show that `'0 == 'a`, - /// and that `'b: '1`, then we know that the clause is - /// satisfied. In such cases, particularly due to limitations of - /// the trait solver =), we usually wind up with a where-clause like - /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as - /// a constraint, and thus ensures that they are in the same SCC. - /// - /// So why can't we do a more correct routine? Well, we could - /// *almost* use the `relate_tys` code, but the way it is - /// currently setup it creates inference variables to deal with - /// higher-ranked things and so forth, and right now the inference - /// context is not permitted to make more inference variables. So - /// we use this kind of hacky solution. - fn normalize_to_scc_representatives(&self, tcx: TyCtxt<'tcx>, value: T) -> T - where - T: TypeFoldable>, - { - fold_regions(tcx, value, |r, _db| { - let vid = self.to_region_vid(r); - let scc = self.constraint_sccs.scc(vid); - let repr = self.scc_representative(scc); - ty::Region::new_var(tcx, repr) - }) - } - - /// Evaluate whether `sup_region == sub_region`. - /// - /// Panics if called before `solve()` executes, - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - pub fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool { - self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1) - } - - /// Evaluate whether `sup_region: sub_region`. - /// - /// Panics if called before `solve()` executes, - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - #[instrument(skip(self), level = "debug", ret)] - pub fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool { - debug!( - "sup_region's value = {:?} universal={:?}", - self.region_value_str(sup_region), - self.universal_regions().is_universal_region(sup_region), - ); - debug!( - "sub_region's value = {:?} universal={:?}", - self.region_value_str(sub_region), - self.universal_regions().is_universal_region(sub_region), - ); - - let sub_region_scc = self.constraint_sccs.scc(sub_region); - let sup_region_scc = self.constraint_sccs.scc(sup_region); - - if sub_region_scc == sup_region_scc { - debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC"); - return true; - } - - let fr_static = self.universal_regions().fr_static; - - // If we are checking that `'sup: 'sub`, and `'sub` contains - // some placeholder that `'sup` cannot name, then this is only - // true if `'sup` outlives static. - // - // Avoid infinite recursion if `sub_region` is already `'static` - if sub_region != fr_static - && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) - { - debug!( - "sub universe `{sub_region_scc:?}` is not nameable \ - by super `{sup_region_scc:?}`, promoting to static", - ); - - return self.eval_outlives(sup_region, fr_static); - } - - // Both the `sub_region` and `sup_region` consist of the union - // of some number of universal regions (along with the union - // of various points in the CFG; ignore those points for - // now). Therefore, the sup-region outlives the sub-region if, - // for each universal region R1 in the sub-region, there - // exists some region R2 in the sup-region that outlives R1. - let universal_outlives = - self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| { - self.scc_values - .universal_regions_outlived_by(sup_region_scc) - .any(|r2| self.universal_region_relations.outlives(r2, r1)) - }); - - if !universal_outlives { - debug!("sub region contains a universal region not present in super"); - return false; - } - - // Now we have to compare all the points in the sub region and make - // sure they exist in the sup region. - - if self.universal_regions().is_universal_region(sup_region) { - // Micro-opt: universal regions contain all points. - debug!("super is universal and hence contains all points"); - return true; - } - - debug!("comparison between points in sup/sub"); - - self.scc_values.contains_points(sup_region_scc, sub_region_scc) - } - - /// Once regions have been propagated, this method is used to see - /// whether any of the constraints were too strong. In particular, - /// we want to check for a case where a universally quantified - /// region exceeded its bounds. Consider: - /// ```compile_fail - /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } - /// ``` - /// In this case, returning `x` requires `&'a u32 <: &'b u32` - /// and hence we establish (transitively) a constraint that - /// `'a: 'b`. The `propagate_constraints` code above will - /// therefore add `end('a)` into the region for `'b` -- but we - /// have no evidence that `'b` outlives `'a`, so we want to report - /// an error. - /// - /// If `propagated_outlives_requirements` is `Some`, then we will - /// push unsatisfied obligations into there. Otherwise, we'll - /// report them as errors. - fn check_universal_regions( - &self, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - for (fr, fr_definition) in self.definitions.iter_enumerated() { - debug!(?fr, ?fr_definition); - match fr_definition.origin { - NllRegionVariableOrigin::FreeRegion => { - // Go through each of the universal regions `fr` and check that - // they did not grow too large, accumulating any requirements - // for our caller into the `outlives_requirements` vector. - self.check_universal_region( - fr, - &mut propagated_outlives_requirements, - errors_buffer, - ); - } - - NllRegionVariableOrigin::Placeholder(placeholder) => { - self.check_bound_universal_region(fr, placeholder, errors_buffer); - } - - NllRegionVariableOrigin::Existential { .. } => { - // nothing to check here - } - } - } - } - - /// Checks if Polonius has found any unexpected free region relations. - /// - /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent - /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a` - /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL - /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`. - /// - /// More details can be found in this blog post by Niko: - /// - /// - /// In the canonical example - /// ```compile_fail - /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } - /// ``` - /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a - /// constraint that `'a: 'b`. It is an error that we have no evidence that this - /// constraint holds. - /// - /// If `propagated_outlives_requirements` is `Some`, then we will - /// push unsatisfied obligations into there. Otherwise, we'll - /// report them as errors. - fn check_polonius_subset_errors( - &self, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - polonius_output: &PoloniusOutput, - ) { - debug!( - "check_polonius_subset_errors: {} subset_errors", - polonius_output.subset_errors.len() - ); - - // Similarly to `check_universal_regions`: a free region relation, which was not explicitly - // declared ("known") was found by Polonius, so emit an error, or propagate the - // requirements for our caller into the `propagated_outlives_requirements` vector. - // - // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the - // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with - // the rest of the NLL infrastructure. The "subset origin" is the "longer free region", - // and the "superset origin" is the outlived "shorter free region". - // - // Note: Polonius will produce a subset error at every point where the unexpected - // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful - // for diagnostics in the future, e.g. to point more precisely at the key locations - // requiring this constraint to hold. However, the error and diagnostics code downstream - // expects that these errors are not duplicated (and that they are in a certain order). - // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or - // anonymous lifetimes for example, could give these names differently, while others like - // the outlives suggestions or the debug output from `#[rustc_regions]` would be - // duplicated. The polonius subset errors are deduplicated here, while keeping the - // CFG-location ordering. - // We can iterate the HashMap here because the result is sorted afterwards. - #[allow(rustc::potential_query_instability)] - let mut subset_errors: Vec<_> = polonius_output - .subset_errors - .iter() - .flat_map(|(_location, subset_errors)| subset_errors.iter()) - .collect(); - subset_errors.sort(); - subset_errors.dedup(); - - for &(longer_fr, shorter_fr) in subset_errors.into_iter() { - debug!( - "check_polonius_subset_errors: subset_error longer_fr={:?},\ - shorter_fr={:?}", - longer_fr, shorter_fr - ); - - let propagated = self.try_propagate_universal_region_error( - longer_fr.into(), - shorter_fr.into(), - &mut propagated_outlives_requirements, - ); - if propagated == RegionRelationCheckResult::Error { - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr: longer_fr.into(), - shorter_fr: shorter_fr.into(), - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: true, - }); - } - } - - // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has - // a more complete picture on how to separate this responsibility. - for (fr, fr_definition) in self.definitions.iter_enumerated() { - match fr_definition.origin { - NllRegionVariableOrigin::FreeRegion => { - // handled by polonius above - } - - NllRegionVariableOrigin::Placeholder(placeholder) => { - self.check_bound_universal_region(fr, placeholder, errors_buffer); - } - - NllRegionVariableOrigin::Existential { .. } => { - // nothing to check here - } - } - } - } - - /// The largest universe of any region nameable from this SCC. - fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex { - self.scc_annotations[scc].max_nameable_universe() - } - - /// Checks the final value for the free region `fr` to see if it - /// grew too large. In particular, examine what `end(X)` points - /// wound up in `fr`'s final value; for each `end(X)` where `X != - /// fr`, we want to check that `fr: X`. If not, that's either an - /// error, or something we have to propagate to our creator. - /// - /// Things that are to be propagated are accumulated into the - /// `outlives_requirements` vector. - #[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")] - fn check_universal_region( - &self, - longer_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - let longer_fr_scc = self.constraint_sccs.scc(longer_fr); - - // Because this free region must be in the ROOT universe, we - // know it cannot contain any bound universes. - assert!(self.max_nameable_universe(longer_fr_scc).is_root()); - - // Only check all of the relations for the main representative of each - // SCC, otherwise just check that we outlive said representative. This - // reduces the number of redundant relations propagated out of - // closures. - // Note that the representative will be a universal region if there is - // one in this SCC, so we will always check the representative here. - let representative = self.scc_representative(longer_fr_scc); - if representative != longer_fr { - if let RegionRelationCheckResult::Error = self.check_universal_region_relation( - longer_fr, - representative, - propagated_outlives_requirements, - ) { - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr, - shorter_fr: representative, - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: true, - }); - } - return; - } - - // Find every region `o` such that `fr: o` - // (because `fr` includes `end(o)`). - let mut error_reported = false; - for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { - if let RegionRelationCheckResult::Error = self.check_universal_region_relation( - longer_fr, - shorter_fr, - propagated_outlives_requirements, - ) { - // We only report the first region error. Subsequent errors are hidden so as - // not to overwhelm the user, but we do record them so as to potentially print - // better diagnostics elsewhere... - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr, - shorter_fr, - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: !error_reported, - }); - - error_reported = true; - } - } - } - - /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate - /// the constraint outward (e.g. to a closure environment), but if that fails, there is an - /// error. - fn check_universal_region_relation( - &self, - longer_fr: RegionVid, - shorter_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - ) -> RegionRelationCheckResult { - // If it is known that `fr: o`, carry on. - if self.universal_region_relations.outlives(longer_fr, shorter_fr) { - RegionRelationCheckResult::Ok - } else { - // If we are not in a context where we can't propagate errors, or we - // could not shrink `fr` to something smaller, then just report an - // error. - // - // Note: in this case, we use the unapproximated regions to report the - // error. This gives better error messages in some cases. - self.try_propagate_universal_region_error( - longer_fr, - shorter_fr, - propagated_outlives_requirements, - ) - } - } - - /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's - /// creator. If we cannot, then the caller should report an error to the user. - fn try_propagate_universal_region_error( - &self, - longer_fr: RegionVid, - shorter_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - ) -> RegionRelationCheckResult { - if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { - // Shrink `longer_fr` until we find some non-local regions. - // We'll call them `longer_fr-` -- they are ever so slightly smaller than - // `longer_fr`. - let longer_fr_minus = self.universal_region_relations.non_local_lower_bounds(longer_fr); - - debug!("try_propagate_universal_region_error: fr_minus={:?}", longer_fr_minus); - - // If we don't find a any non-local regions, we should error out as there is nothing - // to propagate. - if longer_fr_minus.is_empty() { - return RegionRelationCheckResult::Error; - } - - let best_blame = self.best_blame_constraint( - longer_fr, - NllRegionVariableOrigin::FreeRegion, - shorter_fr, - ); - let OutlivesConstraint { category, span, .. } = best_blame.constraint(); - - // Grow `shorter_fr` until we find some non-local regions. - // We will always find at least one: `'static`. We'll call - // them `shorter_fr+` -- they're ever so slightly larger - // than `shorter_fr`. - let shorter_fr_plus = - self.universal_region_relations.non_local_upper_bounds(shorter_fr); - debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus); - - // We then create constraints `longer_fr-: shorter_fr+` that may or may not - // be propagated (see below). - let mut constraints = vec![]; - for fr_minus in longer_fr_minus { - for shorter_fr_plus in &shorter_fr_plus { - constraints.push((fr_minus, *shorter_fr_plus)); - } - } - - // We only need to propagate at least one of the constraints for - // soundness. However, we want to avoid arbitrary choices here - // and currently don't support returning OR constraints. - // - // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`, - // we propagate only those. - // - // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`: - // a --> b --> d - // \ - // \-> c - // Here, `shorter_fr+` of `'a` == `['b, 'c]`. - // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of - // `'d: 'b` and could reject valid code. - // - // So we filter the constraints to regions already outlived by `longer_fr-`, but if - // the filter yields an empty set, we fall back to the original one. - let subset: Vec<_> = constraints - .iter() - .filter(|&&(fr_minus, shorter_fr_plus)| { - self.eval_outlives(fr_minus, shorter_fr_plus) - }) - .copied() - .collect(); - let propagated_constraints = if subset.is_empty() { constraints } else { subset }; - debug!( - "try_propagate_universal_region_error: constraints={:?}", - propagated_constraints - ); - - assert!( - !propagated_constraints.is_empty(), - "Expected at least one constraint to propagate here" - ); - - for (fr_minus, fr_plus) in propagated_constraints { - // Push the constraint `long_fr-: shorter_fr+` - propagated_outlives_requirements.push(ClosureOutlivesRequirement { - subject: ClosureOutlivesSubject::Region(fr_minus), - outlived_free_region: fr_plus, - blame_span: *span, - category: *category, - }); - } - return RegionRelationCheckResult::Propagated; - } - - RegionRelationCheckResult::Error - } - - fn check_bound_universal_region( - &self, - longer_fr: RegionVid, - placeholder: ty::PlaceholderRegion<'tcx>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,); - - let longer_fr_scc = self.constraint_sccs.scc(longer_fr); - debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); - - // If we have some bound universal region `'a`, then the only - // elements it can contain is itself -- we don't know anything - // else about it! - if let Some(error_element) = self - .scc_values - .elements_contained_in(longer_fr_scc) - .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) - { - let illegally_outlived_r = self.region_from_element(longer_fr, &error_element); - // Stop after the first error, it gets too noisy otherwise, and does not provide more information. - errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion { - longer_fr, - illegally_outlived_r, - }); - } else { - debug!("check_bound_universal_region: all bounds satisfied"); - } - } - - pub(crate) fn constraint_path_between_regions( - &self, - from_region: RegionVid, - to_region: RegionVid, - ) -> Option>> { - if from_region == to_region { - bug!("Tried to find a path between {from_region:?} and itself!"); - } - self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0) - } - - /// Walks the graph of constraints (where `'a: 'b` is considered - /// an edge `'a -> 'b`) to find a path from `from_region` to - /// `to_region`. - /// - /// Returns: a series of constraints as well as the region `R` - /// that passed the target test. - /// If `include_static_outlives_all` is `true`, then the synthetic - /// outlives constraints `'static -> a` for every region `a` are - /// considered in the search, otherwise they are ignored. - #[instrument(skip(self, target_test), ret)] - pub(crate) fn constraint_path_to( - &self, - from_region: RegionVid, - target_test: impl Fn(RegionVid) -> bool, - include_placeholder_static: bool, - ) -> Option<(Vec>, RegionVid)> { - self.find_constraint_path_between_regions_inner( - true, - from_region, - &target_test, - include_placeholder_static, - ) - .or_else(|| { - self.find_constraint_path_between_regions_inner( - false, - from_region, - &target_test, - include_placeholder_static, - ) - }) - } - - /// The constraints we get from equating the hidden type of each use of an opaque - /// with its final hidden type may end up getting preferred over other, potentially - /// longer constraint paths. - /// - /// Given that we compute the final hidden type by relying on this existing constraint - /// path, this can easily end up hiding the actual reason for why we require these regions - /// to be equal. - /// - /// To handle this, we first look at the path while ignoring these constraints and then - /// retry while considering them. This is not perfect, as the `from_region` may have already - /// been partially related to its argument region, so while we rely on a member constraint - /// to get a complete path, the most relevant step of that path already existed before then. - fn find_constraint_path_between_regions_inner( - &self, - ignore_opaque_type_constraints: bool, - from_region: RegionVid, - target_test: impl Fn(RegionVid) -> bool, - include_placeholder_static: bool, - ) -> Option<(Vec>, RegionVid)> { - let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); - context[from_region] = Trace::StartRegion; - - let fr_static = self.universal_regions().fr_static; - - // Use a deque so that we do a breadth-first search. We will - // stop at the first match, which ought to be the shortest - // path (fewest constraints). - let mut deque = VecDeque::new(); - deque.push_back(from_region); - - while let Some(r) = deque.pop_front() { - debug!( - "constraint_path_to: from_region={:?} r={:?} value={}", - from_region, - r, - self.region_value_str(r), - ); - - // Check if we reached the region we were looking for. If so, - // we can reconstruct the path that led to it and return it. - if target_test(r) { - let mut result = vec![]; - let mut p = r; - // This loop is cold and runs at the end, which is why we delay - // `OutlivesConstraint` construction until now. - loop { - match context[p] { - Trace::FromGraph(c) => { - p = c.sup; - result.push(*c); - } - - Trace::FromStatic(sub) => { - let c = OutlivesConstraint { - sup: fr_static, - sub, - locations: Locations::All(DUMMY_SP), - span: DUMMY_SP, - category: ConstraintCategory::Internal, - variance_info: ty::VarianceDiagInfo::default(), - from_closure: false, - }; - p = c.sup; - result.push(c); - } - - Trace::StartRegion => { - result.reverse(); - return Some((result, r)); - } - - Trace::NotVisited => { - bug!("found unvisited region {:?} on path to {:?}", p, r) - } - } - } - } - - // Otherwise, walk over the outgoing constraints and - // enqueue any regions we find, keeping track of how we - // reached them. - - // A constraint like `'r: 'x` can come from our constraint - // graph. - - // Always inline this closure because it can be hot. - let mut handle_trace = #[inline(always)] - |sub, trace| { - if let Trace::NotVisited = context[sub] { - context[sub] = trace; - deque.push_back(sub); - } - }; - - // If this is the `'static` region and the graph's direction is normal, then set up the - // Edges iterator to return all regions (#53178). - if r == fr_static && self.constraint_graph.is_normal() { - for sub in self.constraint_graph.outgoing_edges_from_static() { - handle_trace(sub, Trace::FromStatic(sub)); - } - } else { - let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints); - // This loop can be hot. - for constraint in edges { - match constraint.category { - ConstraintCategory::OutlivesUnnameablePlaceholder(_) - if !include_placeholder_static => - { - debug!("Ignoring illegal placeholder constraint: {constraint:?}"); - continue; - } - ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => { - debug!("Ignoring member constraint: {constraint:?}"); - continue; - } - _ => {} - } - - debug_assert_eq!(constraint.sup, r); - handle_trace(constraint.sub, Trace::FromGraph(constraint)); - } - } - } - - None - } - - /// Finds some region R such that `fr1: R` and `R` is live at `location`. - #[instrument(skip(self), level = "trace", ret)] - pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { - trace!(scc = ?self.constraint_sccs.scc(fr1)); - trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1))); - self.constraint_path_to(fr1, |r| { - trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); - self.liveness_constraints.is_live_at(r, location) - }, true).unwrap().1 - } - - /// Get the region outlived by `longer_fr` and live at `element`. - fn region_from_element( - &self, - longer_fr: RegionVid, - element: &RegionElement<'tcx>, - ) -> RegionVid { - match *element { - RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), - RegionElement::RootUniversalRegion(r) => r, - RegionElement::PlaceholderRegion(error_placeholder) => self - .definitions - .iter_enumerated() - .find_map(|(r, definition)| match definition.origin { - NllRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), - _ => None, - }) - .unwrap(), - } - } - - /// Get the region definition of `r`. - pub(crate) fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { - &self.definitions[r] - } - - /// Check if the SCC of `r` contains `upper`, a free region. - pub(crate) fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { - let r_scc = self.constraint_sccs.scc(r); - self.scc_values.contains_free_region(r_scc, upper) - } - - pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> { - &self.universal_region_relations.universal_regions - } - - /// Tries to find the best constraint to blame for the fact that - /// `R: from_region`, where `R` is some region that meets - /// `target_test`. This works by following the constraint graph, - /// creating a constraint path that forces `R` to outlive - /// `from_region`, and then finding the best choices within that - /// path to blame. - #[instrument(level = "debug", skip(self))] - pub(crate) fn best_blame_constraint( - &self, - from_region: RegionVid, - from_region_origin: NllRegionVariableOrigin<'tcx>, - to_region: RegionVid, - ) -> BestBlame<'tcx> { - assert!(from_region != to_region, "Trying to blame a region for itself!"); - - let path = self.constraint_path_between_regions(from_region, to_region).unwrap(); - - // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`, - // redirect search towards `'unnameable`. - let due_to_placeholder_outlives = path.iter().find_map(|c| { - if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category { - Some(unnameable) - } else { - None - } - }); - - // Edge case: it's possible that `'from_region` is an unnameable placeholder. - let mut path = if let Some(unnameable) = due_to_placeholder_outlives - && unnameable != from_region - { - // We ignore the extra edges due to unnameable placeholders to get - // an explanation that was present in the original constraint graph. - self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0 - } else { - path - }; - - debug!( - "path={:#?}", - path.iter() - .map(|c| format!( - "{:?} ({:?}: {:?})", - c, - self.constraint_sccs.scc(c.sup), - self.constraint_sccs.scc(c.sub), - )) - .collect::>() - ); - - // When reporting an error, there is typically a chain of constraints leading from some - // "source" region which must outlive some "target" region. - // In most cases, we prefer to "blame" the constraints closer to the target -- - // but there is one exception. When constraints arise from higher-ranked subtyping, - // we generally prefer to blame the source value, - // as the "target" in this case tends to be some type annotation that the user gave. - // Therefore, if we find that the region origin is some instantiation - // of a higher-ranked region, we start our search from the "source" point - // rather than the "target", and we also tweak a few other things. - // - // An example might be this bit of Rust code: - // - // ```rust - // let x: fn(&'static ()) = |_| {}; - // let y: for<'a> fn(&'a ()) = x; - // ``` - // - // In MIR, this will be converted into a combination of assignments and type ascriptions. - // In particular, the 'static is imposed through a type ascription: - // - // ```rust - // x = ...; - // AscribeUserType(x, fn(&'static ()) - // y = x; - // ``` - // - // We wind up ultimately with constraints like - // - // ```rust - // !a: 'temp1 // from the `y = x` statement - // 'temp1: 'temp2 - // 'temp2: 'static // from the AscribeUserType - // ``` - // - // and here we prefer to blame the source (the y = x statement). - let blame_source = match from_region_origin { - NllRegionVariableOrigin::FreeRegion => true, - NllRegionVariableOrigin::Placeholder(_) => false, - // `'existential: 'whatever` never results in a region error by itself. - // We may always infer it to `'static` afterall. This means while an error - // path may go through an existential, these existentials are never the - // `from_region`. - NllRegionVariableOrigin::Existential { name: _ } => { - unreachable!("existentials can outlive everything") - } - }; - - // To pick a constraint to blame, we organize constraints by how interesting we expect them - // to be in diagnostics, then pick the most interesting one closest to either the source or - // the target on our constraint path. - let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| { - // Try to avoid blaming constraints from desugarings, since they may not clearly match - // match what users have written. As an exception, allow blaming returns generated by - // `?` desugaring, since the correspondence is fairly clear. - let category = if let Some(kind) = constraint.span.desugaring_kind() - && (kind != DesugaringKind::QuestionMark - || !matches!(constraint.category, ConstraintCategory::Return(_))) - { - ConstraintCategory::Boring - } else { - constraint.category - }; - - let interest = match category { - // Returns usually provide a type to blame and have specially written diagnostics, - // so prioritize them. - ConstraintCategory::Return(_) => 0, - // Unsizing coercions are interesting, since we have a note for that: - // `BorrowExplanation::add_object_lifetime_default_note`. - // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue - // #131008 for an example of where we currently don't emit it but should. - // Once the note is handled properly, this case should be removed. Until then, it - // should be as limited as possible; the note is prone to false positives and this - // constraint usually isn't best to blame. - ConstraintCategory::Cast { - is_raw_ptr_dyn_type_cast: _, - unsize_to: Some(unsize_ty), - is_implicit_coercion: true, - } if to_region == self.universal_regions().fr_static - // Mirror the note's condition, to minimize how often this diverts blame. - && let ty::Adt(_, args) = unsize_ty.kind() - && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) - // Mimic old logic for this, to minimize false positives in tests. - && !path - .iter() - .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) => - { - 1 - } - // Between other interesting constraints, order by their position on the `path`. - ConstraintCategory::Yield - | ConstraintCategory::UseAsConst - | ConstraintCategory::UseAsStatic - | ConstraintCategory::TypeAnnotation( - AnnotationSource::Ascription - | AnnotationSource::Declaration - | AnnotationSource::OpaqueCast, - ) - | ConstraintCategory::Cast { .. } - | ConstraintCategory::CallArgument(_) - | ConstraintCategory::CopyBound - | ConstraintCategory::SizedBound - | ConstraintCategory::Assignment - | ConstraintCategory::Usage - | ConstraintCategory::ClosureUpvar(_) => 2, - // Generic arguments are unlikely to be what relates regions together - ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, - // We handle predicates and opaque types specially; don't prioritize them here. - ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, - // `Boring` constraints can correspond to user-written code and have useful spans, - // but don't provide any other useful information for diagnostics. - ConstraintCategory::Boring => 5, - // `BoringNoLocation` constraints can point to user-written code, but are less - // specific, and are not used for relations that would make sense to blame. - ConstraintCategory::BoringNoLocation => 6, - // Do not blame internal constraints if we can avoid it. Never blame - // the `'region: 'static` constraints introduced by placeholder outlives. - ConstraintCategory::Internal => 7, - ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8, - ConstraintCategory::SolverRegionConstraint(_) => 9, - }; - - debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); - - interest - }; - - let best_choice = if blame_source { - path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 - } else { - path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 - }; - - debug!(?best_choice, ?blame_source); - - let best_blame_idx = if let Some(next) = path.get(best_choice + 1) - && matches!(path[best_choice].category, ConstraintCategory::Return(_)) - && next.category == ConstraintCategory::OpaqueType - { - // The return expression is being influenced by the return type being - // impl Trait, point at the return type and not the return expr. - best_choice + 1 - } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal) - && let Some(field) = path.iter().find_map(|p| { - if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None } - }) - { - path[best_choice].category = - ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); - best_choice - } else { - best_choice - }; - - assert!( - !matches!( - path[best_blame_idx].category, - ConstraintCategory::OutlivesUnnameablePlaceholder(_) - ), - "Illegal placeholder constraint blamed; should have redirected to other region relation" - ); - - BestBlame { path, idx: best_blame_idx } - } - - pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - // Query canonicalization can create local superuniverses (for example in - // `InferCtx::query_response_instantiation_guess`), but they don't have an associated - // `UniverseInfo` explaining why they were created. - // This can cause ICEs if these causes are accessed in diagnostics, for example in issue - // #114907 where this happens via liveness and dropck outlives results. - // Therefore, we return a default value in case that happens, which should at worst emit a - // suboptimal error, instead of the ICE. - self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other) - } - - /// Tries to find the terminator of the loop in which the region 'r' resides. - /// Returns the location of the terminator if found. - pub(crate) fn find_loop_terminator_location( - &self, - r: RegionVid, - body: &Body<'_>, - ) -> Option { - let scc = self.constraint_sccs.scc(r); - let locations = self.scc_values.locations_outlived_by(scc); - for location in locations { - let bb = &body[location.block]; - if let Some(terminator) = &bb.terminator - // terminator of a loop should be TerminatorKind::FalseUnwind - && let TerminatorKind::FalseUnwind { .. } = terminator.kind - { - return Some(location); - } - } - None - } - - /// Access to the SCC constraint graph. - /// This can be used to quickly under-approximate the regions which are equal to each other - /// and their relative orderings. - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - pub fn constraint_sccs(&self) -> &ConstraintSccs { - &self.constraint_sccs - } - - /// Returns the representative `RegionVid` for a given SCC. - /// See `RegionTracker` for how a region variable ID is chosen. - /// - /// It is a hacky way to manage checking regions for equality, - /// since we can 'canonicalize' each region to the representative - /// of its SCC and be sure that -- if they have the same repr -- - /// they *must* be equal (though not having the same repr does not - /// mean they are unequal). - fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid { - self.scc_annotations[scc].representative.rvid() - } - - pub(crate) fn liveness_constraints(&self) -> &LivenessValues { - &self.liveness_constraints - } - - /// Returns whether the `loan_idx` is live at the given `location`: whether its issuing - /// region is contained within the type of a variable that is live at this point. - /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. - pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { - let point = self.liveness_constraints.point_from_location(location); - self.liveness_constraints.is_loan_live_at(loan_idx, point) - } -} - #[derive(Clone, Debug)] pub(crate) struct BestBlame<'tcx> { /// See docs on [`RegionInferenceContext::best_blame_constraint`] for what this is. diff --git a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs index bfb4055860c85..e3240c2add95c 100644 --- a/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/opaque_types/mod.rs @@ -24,7 +24,7 @@ use rustc_trait_selection::traits::query::type_op::custom::CustomTypeOp; use tracing::{debug, instrument}; use super::reverse_sccs::ReverseSccGraph; -use crate::consumers::RegionInferenceContext; +use crate::region_infer::RegionInferenceContext; use crate::session_diagnostics::LifetimeMismatchOpaqueParam; use crate::type_check::canonical::fully_perform_op_raw; use crate::type_check::free_region_relations::UniversalRegionRelations; diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs new file mode 100644 index 0000000000000..a6a86a2d9cd0b --- /dev/null +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -0,0 +1,1673 @@ +use std::collections::VecDeque; +use std::rc::Rc; + +use rustc_data_structures::frozen::Frozen; +use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; +use rustc_errors::Diag; +use rustc_index::IndexVec; +use rustc_infer::infer::outlives::test_type_match; +use rustc_infer::infer::region_constraints::{VerifyBound, VerifyIfEq}; +use rustc_infer::infer::{InferCtxt, NllRegionVariableOrigin}; +use rustc_middle::mir::{ + AnnotationSource, BasicBlock, Body, ConstraintCategory, Location, ReturnConstraint, + TerminatorKind, +}; +use rustc_middle::ty::{self, RegionVid, Ty, TyCtxt, TypeFoldable, UniverseIndex, fold_regions}; +use rustc_mir_dataflow::points::DenseLocationMap; +use rustc_span::hygiene::DesugaringKind; +use rustc_span::{DUMMY_SP, bug}; +use tracing::{debug, instrument, trace}; + +use crate::constraints::graph::NormalConstraintGraph; +use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}; +use crate::dataflow::BorrowIndex; +use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}; +use crate::handle_placeholders::{LoweredConstraints, RegionTracker}; +use crate::polonius::legacy::PoloniusOutput; +use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues}; +use crate::region_infer::{ + BestBlame, ConstraintSccs, RegionDefinition, RegionRelationCheckResult, Trace, TypeTest, + sccs_info, +}; +use crate::type_check::Locations; +use crate::type_check::free_region_relations::UniversalRegionRelations; +use crate::universal_regions::UniversalRegions; +use crate::{ + BorrowckInferCtxt, ClosureOutlivesRequirement, ClosureOutlivesSubject, + ClosureOutlivesSubjectTy, ClosureRegionRequirements, +}; + +pub struct RegionInferenceContext<'tcx> { + /// Contains the definition for every region variable. Region + /// variables are identified by their index (`RegionVid`). The + /// definition contains information about where the region came + /// from as well as its final inferred value. + pub(crate) definitions: Frozen>>, + + /// The liveness constraints added to each region. For most + /// regions, these start out empty and steadily grow, though for + /// each universally quantified region R they start out containing + /// the entire CFG and `end(R)`. + pub(super) liveness_constraints: LivenessValues, + + /// The outlives constraints computed by the type-check. + pub(super) constraints: Frozen>, + + /// The constraint-set, but in graph form, making it easy to traverse + /// the constraints adjacent to a particular region. Used to construct + /// the SCC (see `constraint_sccs`) and for error reporting. + pub(super) constraint_graph: Frozen, + + /// The SCC computed from `constraints` and the constraint + /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to + /// compute the values of each region. + pub(super) constraint_sccs: ConstraintSccs, + + pub(super) scc_annotations: IndexVec, + + /// Map universe indexes to information on why we created it. + pub(super) universe_causes: FxIndexMap>, + + /// The final inferred values of the region variables; we compute + /// one value per SCC. To get the value for any given *region*, + /// you first find which scc it is a part of. + pub(super) scc_values: RegionValues<'tcx, ConstraintSccIndex>, + + /// Type constraints that we check after solving. + pub(super) type_tests: Vec>, + + /// Information about how the universally quantified regions in + /// scope on this function relate to one another. + pub(super) universal_region_relations: Frozen>, +} + +impl<'tcx> RegionInferenceContext<'tcx> { + /// Creates a new region inference context with a total of + /// `num_region_variables` valid inference variables; the first N + /// of those will be constant regions representing the free + /// regions defined in `universal_regions`. + /// + /// The `outlives_constraints` and `type_tests` are an initial set + /// of constraints produced by the MIR type check. + pub(crate) fn new( + infcx: &BorrowckInferCtxt<'tcx>, + lowered_constraints: LoweredConstraints<'tcx>, + universal_region_relations: Frozen>, + location_map: Rc, + ) -> Self { + let universal_regions = &universal_region_relations.universal_regions; + + let LoweredConstraints { + constraint_sccs, + definitions, + outlives_constraints, + scc_annotations, + type_tests, + liveness_constraints, + universe_causes, + placeholder_indices, + } = lowered_constraints; + + debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); + debug!("outlives constraints: {:#?}", outlives_constraints); + debug!("placeholder_indices: {:#?}", placeholder_indices); + debug!("type tests: {:#?}", type_tests); + + let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); + + if cfg!(debug_assertions) { + sccs_info(infcx, &constraint_sccs); + } + + let mut scc_values = + RegionValues::new(location_map, universal_regions.len(), placeholder_indices); + + // Initializes the region variables with their initial live points. + for (region, definition) in definitions.iter_enumerated() { + let scc = constraint_sccs.scc(region); + + // For each universally quantified region (lifetime parameter). The + // first N variables always correspond to the regions appearing in the + // function signature (both named and anonymous) and in where-clauses. + match definition.origin { + // For each free, universally quantified region X: + NllRegionVariableOrigin::FreeRegion => { + // Add `end(X)` into the set for X. + scc_values.add_free_region(scc, region); + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + scc_values.add_placeholder(scc, placeholder); + } + + NllRegionVariableOrigin::Existential { .. } => { + // For existential, regions, nothing to do. + } + } + + // Initially copy the liveness constraints of any region that + // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. + // + // These values will later be propagated during [`Self::propagate_constraints()`]. + // The values include any live-at-all-points constraints added previously in `liveness::generate`. + if let Some(liveness) = liveness_constraints.point_liveness(region) { + scc_values.merge_liveness(scc, liveness) + } + } + + Self { + definitions, + liveness_constraints, + constraints: outlives_constraints, + constraint_graph, + constraint_sccs, + scc_annotations, + universe_causes, + scc_values, + type_tests, + universal_region_relations, + } + } + + /// Returns an iterator over all the region indices. + pub(crate) fn regions(&self) -> impl Iterator + 'tcx { + self.definitions.indices() + } + + /// Given a universal region in scope on the MIR, returns the + /// corresponding index. + /// + /// Panics if `r` is not a registered universal region, most notably + /// if it is a placeholder. Handling placeholders requires access to the + /// `MirTypeckRegionConstraints`. + pub(crate) fn to_region_vid(&self, r: ty::Region<'tcx>) -> RegionVid { + self.universal_regions().to_region_vid(r) + } + + /// Returns an iterator over all the outlives constraints. + pub(crate) fn outlives_constraints(&self) -> impl Iterator> { + self.constraints.outlives().iter().copied() + } + + /// Adds annotations for `#[rustc_regions]`; see `UniversalRegions::annotate`. + pub(crate) fn annotate(&self, tcx: TyCtxt<'tcx>, err: &mut Diag<'_>) { + self.universal_regions().annotate(tcx, err) + } + + /// Returns `true` if the region `r` contains the point `p`. + /// + /// Panics if called before `solve()` executes, + pub(crate) fn region_contains_point(&self, r: RegionVid, p: Location) -> bool { + let scc = self.constraint_sccs.scc(r); + self.scc_values.contains_point(scc, p) + } + + /// Returns the lowest statement index in `start..=end` which is not contained by `r`. + /// + /// Panics if called before `solve()` executes. + pub(crate) fn first_non_contained_inclusive( + &self, + r: RegionVid, + block: BasicBlock, + start: usize, + end: usize, + ) -> Option { + let scc = self.constraint_sccs.scc(r); + self.scc_values.first_non_contained_inclusive(scc, block, start, end) + } + + /// Returns access to the value of `r` for debugging purposes. + pub(crate) fn region_value_str(&self, r: RegionVid) -> String { + let scc = self.constraint_sccs.scc(r); + self.scc_values.region_value_str(scc) + } + + pub(crate) fn placeholders_contained_in( + &self, + r: RegionVid, + ) -> impl Iterator> { + let scc = self.constraint_sccs.scc(r); + self.scc_values.placeholders_contained_in(scc) + } + + /// Performs region inference and report errors if we see any + /// unsatisfiable constraints. If this is a closure, returns the + /// region requirements to propagate to our creator, if any. + #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] + pub(crate) fn solve( + &mut self, + infcx: &InferCtxt<'tcx>, + body: &Body<'tcx>, + polonius_output: Option>, + ) -> (Option>, RegionErrors<'tcx>) { + let mir_def_id = body.source.def_id(); + self.propagate_constraints(); + + let mut errors_buffer = RegionErrors::new(infcx.tcx); + + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + + self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); + + debug!(?errors_buffer); + debug!(?propagated_outlives_requirements); + + // In Polonius mode, the errors about missing universal region relations are in the output + // and need to be emitted or propagated. Otherwise, we need to check whether the + // constraints were too strong, and if so, emit or propagate those errors. + if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { + self.check_polonius_subset_errors( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + polonius_output + .as_ref() + .expect("Polonius output is unavailable despite `-Z polonius`"), + ); + } else { + self.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); + } + + debug!(?errors_buffer); + + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); + + if propagated_outlives_requirements.is_empty() { + (None, errors_buffer) + } else { + let num_external_vids = self.universal_regions().num_global_and_external_regions(); + ( + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), + errors_buffer, + ) + } + } + + /// Propagate the region constraints: this will grow the values + /// for each region variable until all the constraints are + /// satisfied. Note that some values may grow **too** large to be + /// feasible, but we check this later. + #[instrument(skip(self), level = "debug")] + fn propagate_constraints(&mut self) { + debug!("constraints={:#?}", { + let mut constraints: Vec<_> = self.outlives_constraints().collect(); + constraints.sort_by_key(|c| (c.sup, c.sub)); + constraints + .into_iter() + .map(|c| (c, self.constraint_sccs.scc(c.sup), self.constraint_sccs.scc(c.sub))) + .collect::>() + }); + + // To propagate constraints, we walk the DAG induced by the + // SCC. For each SCC `A`, we visit its successors and compute + // their values, then we union all those values to get our + // own. This one-shot approach works because iteration is in + // dependency order. I.e. a chain A: B: C will visit C, B, A. + for scc_a in self.constraint_sccs.all_sccs() { + // Walk each SCC `B` such that `A: B`... + for &scc_b in self.constraint_sccs.successors(scc_a) { + debug!(?scc_b); + self.scc_values.add_region(scc_a, scc_b); + } + } + } + + /// Returns `true` if all the placeholders in the value of `scc_b` are nameable + /// in `scc_a`. Used during constraint propagation, and only once + /// the value of `scc_b` has been computed. + fn can_name_all_placeholders( + &self, + scc_a: ConstraintSccIndex, + scc_b: ConstraintSccIndex, + ) -> bool { + self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) + } + + /// Once regions have been propagated, this method is used to see + /// whether the "type tests" produced by typeck were satisfied; + /// type tests encode type-outlives relationships like `T: + /// 'a`. See `TypeTest` for more details. + fn check_type_tests( + &self, + infcx: &InferCtxt<'tcx>, + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + let tcx = infcx.tcx; + + // Sometimes we register equivalent type-tests that would + // result in basically the exact same error being reported to + // the user. Avoid that. + let mut deduplicate_errors = FxIndexSet::default(); + let mut failed_type_tests = Vec::new(); + + for type_test in &self.type_tests { + debug!("check_type_test: {:?}", type_test); + + let generic_ty = type_test.generic_kind.to_ty(tcx); + if self.eval_verify_bound( + infcx, + generic_ty, + type_test.lower_bound, + &type_test.verify_bound, + ) { + continue; + } + + if let Some(propagated_outlives_requirements) = &mut propagated_outlives_requirements + && self.try_promote_type_test(infcx, type_test, propagated_outlives_requirements) + { + continue; + } + + // Type-test failed. Collect it so we can suppress redundant errors below. + let erased_generic_kind = infcx.tcx.erase_and_anonymize_regions(type_test.generic_kind); + failed_type_tests.push((erased_generic_kind, type_test)); + } + + // An async body can produce both `G: 'static` and `G: 'a` type-test failures at + // the same span, as in `tests/ui/async-await/spurious-static-bound-issue-115376.rs`. + // Reporting the weaker bound adds a redundant diagnostic and suggests a lifetime + // bound that cannot fix the missing `G: 'static` requirement. Keep the `'static` + // error and suppress weaker failures for the same erased generic kind and span. + // This is a diagnostic heuristic, using the same erasure as deduplication below. + // + // Collect all failed `'static` bounds before reporting errors so suppression does + // not depend on the order of the type tests. Compare SCCs because a lower-bound + // region can be equivalent to `'static` without being `fr_static` itself. + let static_scc = self.constraint_sccs.scc(self.universal_regions().fr_static); + let static_bound_errors: FxIndexSet<_> = failed_type_tests + .iter() + .filter_map(|&(erased_generic_kind, type_test)| { + if self.constraint_sccs.scc(type_test.lower_bound) == static_scc { + Some((erased_generic_kind, type_test.span)) + } else { + None + } + }) + .collect(); + + // If `G: 'static` failed at this span, then same-span `G: 'a` failures are weaker. + for (erased_generic_kind, type_test) in failed_type_tests { + if self.constraint_sccs.scc(type_test.lower_bound) != static_scc + && static_bound_errors.contains(&(erased_generic_kind, type_test.span)) + { + continue; + } + + // Skip duplicate-ish errors. + if deduplicate_errors.insert(( + erased_generic_kind, + type_test.lower_bound, + type_test.span, + )) { + debug!( + "check_type_test: reporting error for erased_generic_kind={:?}, \ + lower_bound_region={:?}, \ + type_test.span={:?}", + erased_generic_kind, type_test.lower_bound, type_test.span, + ); + + errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); + } + } + } + + /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot + /// prove to be satisfied. If this is a closure, we will attempt to + /// "promote" this type-test into our `ClosureRegionRequirements` and + /// hence pass it up the creator. To do this, we have to phrase the + /// type-test in terms of external free regions, as local free + /// regions are not nameable by the closure's creator. + /// + /// Promotion works as follows: we first check that the type `T` + /// contains only regions that the creator knows about. If this is + /// true, then -- as a consequence -- we know that all regions in + /// the type `T` are free regions that outlive the closure body. If + /// false, then promotion fails. + /// + /// Once we've promoted T, we have to "promote" `'X` to some region + /// that is "external" to the closure. Generally speaking, a region + /// may be the union of some points in the closure body as well as + /// various free lifetimes. We can ignore the points in the closure + /// body: if the type T can be expressed in terms of external regions, + /// we know it outlives the points in the closure body. That + /// just leaves the free regions. + /// + /// The idea then is to lower the `T: 'X` constraint into multiple + /// bounds -- e.g., if `'X` is the union of two free lifetimes, + /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. + #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] + fn try_promote_type_test( + &self, + infcx: &InferCtxt<'tcx>, + type_test: &TypeTest<'tcx>, + propagated_outlives_requirements: &mut Vec>, + ) -> bool { + let tcx = infcx.tcx; + let TypeTest { generic_kind, lower_bound, span: blame_span, verify_bound: _ } = *type_test; + + let generic_ty = generic_kind.to_ty(tcx); + let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { + return false; + }; + + let r_scc = self.constraint_sccs.scc(lower_bound); + debug!( + "lower_bound = {:?} r_scc={:?} universe={:?}", + lower_bound, + r_scc, + self.max_nameable_universe(r_scc) + ); + // If the type test requires that `T: 'a` where `'a` is a + // placeholder from another universe, that effectively requires + // `T: 'static`, so we have to propagate that requirement. + // + // It doesn't matter *what* universe because the promoted `T` will + // always be in the root universe. + if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { + debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); + let static_r = self.universal_regions().fr_static; + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject, + outlived_free_region: static_r, + blame_span, + category: ConstraintCategory::Boring, + }); + + // we can return here -- the code below might push add'l constraints + // but they would all be weaker than this one. + return true; + } + + // For each region outlived by lower_bound find a non-local, + // universal region (it may be the same region) and add it to + // `ClosureOutlivesRequirement`. + let mut found_outlived_universal_region = false; + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + found_outlived_universal_region = true; + debug!("universal_region_outlived_by ur={:?}", ur); + let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); + debug!(?non_local_ub); + + // This is slightly too conservative. To show T: '1, given `'2: '1` + // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to + // avoid potential non-determinism we approximate this by requiring + // T: '1 and T: '2. + for upper_bound in non_local_ub { + debug_assert!(self.universal_regions().is_universal_region(upper_bound)); + debug_assert!(!self.universal_regions().is_local_free_region(upper_bound)); + + let requirement = ClosureOutlivesRequirement { + subject, + outlived_free_region: upper_bound, + blame_span, + category: ConstraintCategory::Boring, + }; + debug!(?requirement, "adding closure requirement"); + propagated_outlives_requirements.push(requirement); + } + } + // If we succeed to promote the subject, i.e. it only contains non-local regions, + // and fail to prove the type test inside of the closure, the `lower_bound` has to + // also be at least as large as some universal region, as the type test is otherwise + // trivial. + assert!(found_outlived_universal_region); + true + } + + /// When we promote a type test `T: 'r`, we have to replace all region + /// variables in the type `T` with an equal universal region from the + /// closure signature. + /// This is not always possible, so this is a fallible process. + #[instrument(level = "debug", skip(self, infcx), ret)] + fn try_promote_type_test_subject( + &self, + infcx: &InferCtxt<'tcx>, + ty: Ty<'tcx>, + ) -> Option> { + let tcx = infcx.tcx; + let mut failed = false; + let ty = fold_regions(tcx, ty, |r, _depth| { + let r_vid = self.to_region_vid(r); + let r_scc = self.constraint_sccs.scc(r_vid); + + // The challenge is this. We have some region variable `r` + // whose value is a set of CFG points and universal + // regions. We want to find if that set is *equivalent* to + // any of the named regions found in the closure. + // To do so, we simply check every candidate `u_r` for equality. + self.scc_values + .universal_regions_outlived_by(r_scc) + .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r)) + .find(|&u_r| self.eval_equal(u_r, r_vid)) + .map(|u_r| ty::Region::new_var(tcx, u_r)) + // In case we could not find a named region to map to, + // we will return `None` below. + .unwrap_or_else(|| { + failed = true; + r + }) + }); + + debug!("try_promote_type_test_subject: folded ty = {:?}", ty); + + // This will be true if we failed to promote some region. + if failed { + return None; + } + + Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) + } + + /// Like `universal_upper_bound`, but returns an approximation more suitable + /// for diagnostics. If `r` contains multiple disjoint universal regions + /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. + /// This corresponds to picking named regions over unnamed regions + /// (e.g. picking early-bound regions over a closure late-bound region). + /// + /// This means that the returned value may not be a true upper bound, since + /// only 'static is known to outlive disjoint universal regions. + /// Therefore, this method should only be used in diagnostic code, + /// where displaying *some* named universal region is better than + /// falling back to 'static. + #[instrument(level = "debug", skip(self))] + pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { + debug!("{}", self.region_value_str(r)); + + // Find the smallest universal region that contains all other + // universal regions within `region`. + let mut lub = self.universal_regions().fr_fn_body; + let r_scc = self.constraint_sccs.scc(r); + let static_r = self.universal_regions().fr_static; + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur); + debug!(?ur, ?lub, ?new_lub); + // The upper bound of two non-static regions is static: this + // means we know nothing about the relationship between these + // two regions. Pick a 'better' one to use when constructing + // a diagnostic + if ur != static_r && lub != static_r && new_lub == static_r { + // Prefer the region with an `external_name` - this + // indicates that the region is early-bound, so working with + // it can produce a nicer error. + if self.region_definition(ur).external_name.is_some() { + lub = ur; + } else if self.region_definition(lub).external_name.is_some() { + // Leave lub unchanged + } else { + // If we get here, we don't have any reason to prefer + // one region over the other. Just pick the + // one with the lower index for now. + lub = std::cmp::min(ur, lub); + } + } else { + lub = new_lub; + } + } + + debug!(?r, ?lub); + + lub + } + + /// Tests if `test` is true when applied to `lower_bound` at + /// `point`. + fn eval_verify_bound( + &self, + infcx: &InferCtxt<'tcx>, + generic_ty: Ty<'tcx>, + lower_bound: RegionVid, + verify_bound: &VerifyBound<'tcx>, + ) -> bool { + debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound); + + match verify_bound { + VerifyBound::IfEq(verify_if_eq_b) => { + self.eval_if_eq(infcx, generic_ty, lower_bound, *verify_if_eq_b) + } + + VerifyBound::IsEmpty => { + let lower_bound_scc = self.constraint_sccs.scc(lower_bound); + self.scc_values.elements_contained_in(lower_bound_scc).next().is_none() + } + + VerifyBound::OutlivedBy(r) => { + let r_vid = self.to_region_vid(*r); + self.eval_outlives(r_vid, lower_bound) + } + + VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { + self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) + }), + + VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { + self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) + }), + } + } + + fn eval_if_eq( + &self, + infcx: &InferCtxt<'tcx>, + generic_ty: Ty<'tcx>, + lower_bound: RegionVid, + verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>, + ) -> bool { + let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty); + let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b); + match test_type_match::extract_verify_if_eq(infcx.tcx, &verify_if_eq_b, generic_ty) { + Some(r) => { + let r_vid = self.to_region_vid(r); + self.eval_outlives(r_vid, lower_bound) + } + None => false, + } + } + + /// This is a conservative normalization procedure. It takes every + /// free region in `value` and replaces it with the + /// "representative" of its SCC (see `scc_representatives` field). + /// We are guaranteed that if two values normalize to the same + /// thing, then they are equal; this is a conservative check in + /// that they could still be equal even if they normalize to + /// different results. (For example, there might be two regions + /// with the same value that are not in the same SCC). + /// + /// N.B., this is not an ideal approach and I would like to revisit + /// it. However, it works pretty well in practice. In particular, + /// this is needed to deal with projection outlives bounds like + /// + /// ```text + /// >::Item: '1 + /// ``` + /// + /// In particular, this routine winds up being important when + /// there are bounds like `where >::Item: 'b` in the + /// environment. In this case, if we can show that `'0 == 'a`, + /// and that `'b: '1`, then we know that the clause is + /// satisfied. In such cases, particularly due to limitations of + /// the trait solver =), we usually wind up with a where-clause like + /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as + /// a constraint, and thus ensures that they are in the same SCC. + /// + /// So why can't we do a more correct routine? Well, we could + /// *almost* use the `relate_tys` code, but the way it is + /// currently setup it creates inference variables to deal with + /// higher-ranked things and so forth, and right now the inference + /// context is not permitted to make more inference variables. So + /// we use this kind of hacky solution. + fn normalize_to_scc_representatives(&self, tcx: TyCtxt<'tcx>, value: T) -> T + where + T: TypeFoldable>, + { + fold_regions(tcx, value, |r, _db| { + let vid = self.to_region_vid(r); + let scc = self.constraint_sccs.scc(vid); + let repr = self.scc_representative(scc); + ty::Region::new_var(tcx, repr) + }) + } + + /// Evaluate whether `sup_region == sub_region`. + /// + /// Panics if called before `solve()` executes, + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + pub(crate) fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool { + self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1) + } + + /// Evaluate whether `sup_region: sub_region`. + /// + /// Panics if called before `solve()` executes, + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + #[instrument(skip(self), level = "debug", ret)] + pub(crate) fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool { + debug!( + "sup_region's value = {:?} universal={:?}", + self.region_value_str(sup_region), + self.universal_regions().is_universal_region(sup_region), + ); + debug!( + "sub_region's value = {:?} universal={:?}", + self.region_value_str(sub_region), + self.universal_regions().is_universal_region(sub_region), + ); + + let sub_region_scc = self.constraint_sccs.scc(sub_region); + let sup_region_scc = self.constraint_sccs.scc(sup_region); + + if sub_region_scc == sup_region_scc { + debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC"); + return true; + } + + let fr_static = self.universal_regions().fr_static; + + // If we are checking that `'sup: 'sub`, and `'sub` contains + // some placeholder that `'sup` cannot name, then this is only + // true if `'sup` outlives static. + // + // Avoid infinite recursion if `sub_region` is already `'static` + if sub_region != fr_static + && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) + { + debug!( + "sub universe `{sub_region_scc:?}` is not nameable \ + by super `{sup_region_scc:?}`, promoting to static", + ); + + return self.eval_outlives(sup_region, fr_static); + } + + // Both the `sub_region` and `sup_region` consist of the union + // of some number of universal regions (along with the union + // of various points in the CFG; ignore those points for + // now). Therefore, the sup-region outlives the sub-region if, + // for each universal region R1 in the sub-region, there + // exists some region R2 in the sup-region that outlives R1. + let universal_outlives = + self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| { + self.scc_values + .universal_regions_outlived_by(sup_region_scc) + .any(|r2| self.universal_region_relations.outlives(r2, r1)) + }); + + if !universal_outlives { + debug!("sub region contains a universal region not present in super"); + return false; + } + + // Now we have to compare all the points in the sub region and make + // sure they exist in the sup region. + + if self.universal_regions().is_universal_region(sup_region) { + // Micro-opt: universal regions contain all points. + debug!("super is universal and hence contains all points"); + return true; + } + + debug!("comparison between points in sup/sub"); + + self.scc_values.contains_points(sup_region_scc, sub_region_scc) + } + + /// Once regions have been propagated, this method is used to see + /// whether any of the constraints were too strong. In particular, + /// we want to check for a case where a universally quantified + /// region exceeded its bounds. Consider: + /// ```compile_fail + /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } + /// ``` + /// In this case, returning `x` requires `&'a u32 <: &'b u32` + /// and hence we establish (transitively) a constraint that + /// `'a: 'b`. The `propagate_constraints` code above will + /// therefore add `end('a)` into the region for `'b` -- but we + /// have no evidence that `'b` outlives `'a`, so we want to report + /// an error. + /// + /// If `propagated_outlives_requirements` is `Some`, then we will + /// push unsatisfied obligations into there. Otherwise, we'll + /// report them as errors. + fn check_universal_regions( + &self, + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + for (fr, fr_definition) in self.definitions.iter_enumerated() { + debug!(?fr, ?fr_definition); + match fr_definition.origin { + NllRegionVariableOrigin::FreeRegion => { + // Go through each of the universal regions `fr` and check that + // they did not grow too large, accumulating any requirements + // for our caller into the `outlives_requirements` vector. + self.check_universal_region( + fr, + &mut propagated_outlives_requirements, + errors_buffer, + ); + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + self.check_bound_universal_region(fr, placeholder, errors_buffer); + } + + NllRegionVariableOrigin::Existential { .. } => { + // nothing to check here + } + } + } + } + + /// Checks if Polonius has found any unexpected free region relations. + /// + /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent + /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a` + /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL + /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`. + /// + /// More details can be found in this blog post by Niko: + /// + /// + /// In the canonical example + /// ```compile_fail + /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } + /// ``` + /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a + /// constraint that `'a: 'b`. It is an error that we have no evidence that this + /// constraint holds. + /// + /// If `propagated_outlives_requirements` is `Some`, then we will + /// push unsatisfied obligations into there. Otherwise, we'll + /// report them as errors. + fn check_polonius_subset_errors( + &self, + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + polonius_output: &PoloniusOutput, + ) { + debug!( + "check_polonius_subset_errors: {} subset_errors", + polonius_output.subset_errors.len() + ); + + // Similarly to `check_universal_regions`: a free region relation, which was not explicitly + // declared ("known") was found by Polonius, so emit an error, or propagate the + // requirements for our caller into the `propagated_outlives_requirements` vector. + // + // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the + // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with + // the rest of the NLL infrastructure. The "subset origin" is the "longer free region", + // and the "superset origin" is the outlived "shorter free region". + // + // Note: Polonius will produce a subset error at every point where the unexpected + // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful + // for diagnostics in the future, e.g. to point more precisely at the key locations + // requiring this constraint to hold. However, the error and diagnostics code downstream + // expects that these errors are not duplicated (and that they are in a certain order). + // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or + // anonymous lifetimes for example, could give these names differently, while others like + // the outlives suggestions or the debug output from `#[rustc_regions]` would be + // duplicated. The polonius subset errors are deduplicated here, while keeping the + // CFG-location ordering. + // We can iterate the HashMap here because the result is sorted afterwards. + #[allow(rustc::potential_query_instability)] + let mut subset_errors: Vec<_> = polonius_output + .subset_errors + .iter() + .flat_map(|(_location, subset_errors)| subset_errors.iter()) + .collect(); + subset_errors.sort(); + subset_errors.dedup(); + + for &(longer_fr, shorter_fr) in subset_errors.into_iter() { + debug!( + "check_polonius_subset_errors: subset_error longer_fr={:?},\ + shorter_fr={:?}", + longer_fr, shorter_fr + ); + + let propagated = self.try_propagate_universal_region_error( + longer_fr.into(), + shorter_fr.into(), + &mut propagated_outlives_requirements, + ); + if propagated == RegionRelationCheckResult::Error { + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr: longer_fr.into(), + shorter_fr: shorter_fr.into(), + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: true, + }); + } + } + + // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has + // a more complete picture on how to separate this responsibility. + for (fr, fr_definition) in self.definitions.iter_enumerated() { + match fr_definition.origin { + NllRegionVariableOrigin::FreeRegion => { + // handled by polonius above + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + self.check_bound_universal_region(fr, placeholder, errors_buffer); + } + + NllRegionVariableOrigin::Existential { .. } => { + // nothing to check here + } + } + } + } + + /// The largest universe of any region nameable from this SCC. + pub(super) fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex { + self.scc_annotations[scc].max_nameable_universe() + } + + /// Checks the final value for the free region `fr` to see if it + /// grew too large. In particular, examine what `end(X)` points + /// wound up in `fr`'s final value; for each `end(X)` where `X != + /// fr`, we want to check that `fr: X`. If not, that's either an + /// error, or something we have to propagate to our creator. + /// + /// Things that are to be propagated are accumulated into the + /// `outlives_requirements` vector. + #[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")] + fn check_universal_region( + &self, + longer_fr: RegionVid, + propagated_outlives_requirements: &mut Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + let longer_fr_scc = self.constraint_sccs.scc(longer_fr); + + // Because this free region must be in the ROOT universe, we + // know it cannot contain any bound universes. + assert!(self.max_nameable_universe(longer_fr_scc).is_root()); + + // Only check all of the relations for the main representative of each + // SCC, otherwise just check that we outlive said representative. This + // reduces the number of redundant relations propagated out of + // closures. + // Note that the representative will be a universal region if there is + // one in this SCC, so we will always check the representative here. + let representative = self.scc_representative(longer_fr_scc); + if representative != longer_fr { + if let RegionRelationCheckResult::Error = self.check_universal_region_relation( + longer_fr, + representative, + propagated_outlives_requirements, + ) { + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr, + shorter_fr: representative, + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: true, + }); + } + return; + } + + // Find every region `o` such that `fr: o` + // (because `fr` includes `end(o)`). + let mut error_reported = false; + for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { + if let RegionRelationCheckResult::Error = self.check_universal_region_relation( + longer_fr, + shorter_fr, + propagated_outlives_requirements, + ) { + // We only report the first region error. Subsequent errors are hidden so as + // not to overwhelm the user, but we do record them so as to potentially print + // better diagnostics elsewhere... + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr, + shorter_fr, + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: !error_reported, + }); + + error_reported = true; + } + } + } + + /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate + /// the constraint outward (e.g. to a closure environment), but if that fails, there is an + /// error. + fn check_universal_region_relation( + &self, + longer_fr: RegionVid, + shorter_fr: RegionVid, + propagated_outlives_requirements: &mut Option<&mut Vec>>, + ) -> RegionRelationCheckResult { + // If it is known that `fr: o`, carry on. + if self.universal_region_relations.outlives(longer_fr, shorter_fr) { + RegionRelationCheckResult::Ok + } else { + // If we are not in a context where we can't propagate errors, or we + // could not shrink `fr` to something smaller, then just report an + // error. + // + // Note: in this case, we use the unapproximated regions to report the + // error. This gives better error messages in some cases. + self.try_propagate_universal_region_error( + longer_fr, + shorter_fr, + propagated_outlives_requirements, + ) + } + } + + /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's + /// creator. If we cannot, then the caller should report an error to the user. + fn try_propagate_universal_region_error( + &self, + longer_fr: RegionVid, + shorter_fr: RegionVid, + propagated_outlives_requirements: &mut Option<&mut Vec>>, + ) -> RegionRelationCheckResult { + if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { + // Shrink `longer_fr` until we find some non-local regions. + // We'll call them `longer_fr-` -- they are ever so slightly smaller than + // `longer_fr`. + let longer_fr_minus = self.universal_region_relations.non_local_lower_bounds(longer_fr); + + debug!("try_propagate_universal_region_error: fr_minus={:?}", longer_fr_minus); + + // If we don't find a any non-local regions, we should error out as there is nothing + // to propagate. + if longer_fr_minus.is_empty() { + return RegionRelationCheckResult::Error; + } + + let best_blame = self.best_blame_constraint( + longer_fr, + NllRegionVariableOrigin::FreeRegion, + shorter_fr, + ); + let OutlivesConstraint { category, span, .. } = best_blame.constraint(); + + // Grow `shorter_fr` until we find some non-local regions. + // We will always find at least one: `'static`. We'll call + // them `shorter_fr+` -- they're ever so slightly larger + // than `shorter_fr`. + let shorter_fr_plus = + self.universal_region_relations.non_local_upper_bounds(shorter_fr); + debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus); + + // We then create constraints `longer_fr-: shorter_fr+` that may or may not + // be propagated (see below). + let mut constraints = vec![]; + for fr_minus in longer_fr_minus { + for shorter_fr_plus in &shorter_fr_plus { + constraints.push((fr_minus, *shorter_fr_plus)); + } + } + + // We only need to propagate at least one of the constraints for + // soundness. However, we want to avoid arbitrary choices here + // and currently don't support returning OR constraints. + // + // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`, + // we propagate only those. + // + // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`: + // a --> b --> d + // \ + // \-> c + // Here, `shorter_fr+` of `'a` == `['b, 'c]`. + // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of + // `'d: 'b` and could reject valid code. + // + // So we filter the constraints to regions already outlived by `longer_fr-`, but if + // the filter yields an empty set, we fall back to the original one. + let subset: Vec<_> = constraints + .iter() + .filter(|&&(fr_minus, shorter_fr_plus)| { + self.eval_outlives(fr_minus, shorter_fr_plus) + }) + .copied() + .collect(); + let propagated_constraints = if subset.is_empty() { constraints } else { subset }; + debug!( + "try_propagate_universal_region_error: constraints={:?}", + propagated_constraints + ); + + assert!( + !propagated_constraints.is_empty(), + "Expected at least one constraint to propagate here" + ); + + for (fr_minus, fr_plus) in propagated_constraints { + // Push the constraint `long_fr-: shorter_fr+` + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject: ClosureOutlivesSubject::Region(fr_minus), + outlived_free_region: fr_plus, + blame_span: *span, + category: *category, + }); + } + return RegionRelationCheckResult::Propagated; + } + + RegionRelationCheckResult::Error + } + + fn check_bound_universal_region( + &self, + longer_fr: RegionVid, + placeholder: ty::PlaceholderRegion<'tcx>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,); + + let longer_fr_scc = self.constraint_sccs.scc(longer_fr); + debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); + + // If we have some bound universal region `'a`, then the only + // elements it can contain is itself -- we don't know anything + // else about it! + if let Some(error_element) = self + .scc_values + .elements_contained_in(longer_fr_scc) + .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) + { + let illegally_outlived_r = self.region_from_element(longer_fr, &error_element); + // Stop after the first error, it gets too noisy otherwise, and does not provide more information. + errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion { + longer_fr, + illegally_outlived_r, + }); + } else { + debug!("check_bound_universal_region: all bounds satisfied"); + } + } + + pub(crate) fn constraint_path_between_regions( + &self, + from_region: RegionVid, + to_region: RegionVid, + ) -> Option>> { + if from_region == to_region { + bug!("Tried to find a path between {from_region:?} and itself!"); + } + self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0) + } + + /// Walks the graph of constraints (where `'a: 'b` is considered + /// an edge `'a -> 'b`) to find a path from `from_region` to + /// `to_region`. + /// + /// Returns: a series of constraints as well as the region `R` + /// that passed the target test. + /// If `include_static_outlives_all` is `true`, then the synthetic + /// outlives constraints `'static -> a` for every region `a` are + /// considered in the search, otherwise they are ignored. + #[instrument(skip(self, target_test), ret)] + pub(crate) fn constraint_path_to( + &self, + from_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, + ) -> Option<(Vec>, RegionVid)> { + self.find_constraint_path_between_regions_inner( + true, + from_region, + &target_test, + include_placeholder_static, + ) + .or_else(|| { + self.find_constraint_path_between_regions_inner( + false, + from_region, + &target_test, + include_placeholder_static, + ) + }) + } + + /// The constraints we get from equating the hidden type of each use of an opaque + /// with its final hidden type may end up getting preferred over other, potentially + /// longer constraint paths. + /// + /// Given that we compute the final hidden type by relying on this existing constraint + /// path, this can easily end up hiding the actual reason for why we require these regions + /// to be equal. + /// + /// To handle this, we first look at the path while ignoring these constraints and then + /// retry while considering them. This is not perfect, as the `from_region` may have already + /// been partially related to its argument region, so while we rely on a member constraint + /// to get a complete path, the most relevant step of that path already existed before then. + fn find_constraint_path_between_regions_inner( + &self, + ignore_opaque_type_constraints: bool, + from_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, + ) -> Option<(Vec>, RegionVid)> { + let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); + context[from_region] = Trace::StartRegion; + + let fr_static = self.universal_regions().fr_static; + + // Use a deque so that we do a breadth-first search. We will + // stop at the first match, which ought to be the shortest + // path (fewest constraints). + let mut deque = VecDeque::new(); + deque.push_back(from_region); + + while let Some(r) = deque.pop_front() { + debug!( + "constraint_path_to: from_region={:?} r={:?} value={}", + from_region, + r, + self.region_value_str(r), + ); + + // Check if we reached the region we were looking for. If so, + // we can reconstruct the path that led to it and return it. + if target_test(r) { + let mut result = vec![]; + let mut p = r; + // This loop is cold and runs at the end, which is why we delay + // `OutlivesConstraint` construction until now. + loop { + match context[p] { + Trace::FromGraph(c) => { + p = c.sup; + result.push(*c); + } + + Trace::FromStatic(sub) => { + let c = OutlivesConstraint { + sup: fr_static, + sub, + locations: Locations::All(DUMMY_SP), + span: DUMMY_SP, + category: ConstraintCategory::Internal, + variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, + }; + p = c.sup; + result.push(c); + } + + Trace::StartRegion => { + result.reverse(); + return Some((result, r)); + } + + Trace::NotVisited => { + bug!("found unvisited region {:?} on path to {:?}", p, r) + } + } + } + } + + // Otherwise, walk over the outgoing constraints and + // enqueue any regions we find, keeping track of how we + // reached them. + + // A constraint like `'r: 'x` can come from our constraint + // graph. + + // Always inline this closure because it can be hot. + let mut handle_trace = #[inline(always)] + |sub, trace| { + if let Trace::NotVisited = context[sub] { + context[sub] = trace; + deque.push_back(sub); + } + }; + + // If this is the `'static` region and the graph's direction is normal, then set up the + // Edges iterator to return all regions (#53178). + if r == fr_static && self.constraint_graph.is_normal() { + for sub in self.constraint_graph.outgoing_edges_from_static() { + handle_trace(sub, Trace::FromStatic(sub)); + } + } else { + let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints); + // This loop can be hot. + for constraint in edges { + match constraint.category { + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + if !include_placeholder_static => + { + debug!("Ignoring illegal placeholder constraint: {constraint:?}"); + continue; + } + ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => { + debug!("Ignoring member constraint: {constraint:?}"); + continue; + } + _ => {} + } + + debug_assert_eq!(constraint.sup, r); + handle_trace(constraint.sub, Trace::FromGraph(constraint)); + } + } + } + + None + } + + /// Finds some region R such that `fr1: R` and `R` is live at `location`. + #[instrument(skip(self), level = "trace", ret)] + pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { + trace!(scc = ?self.constraint_sccs.scc(fr1)); + trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1))); + self.constraint_path_to(fr1, |r| { + trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); + self.liveness_constraints.is_live_at(r, location) + }, true).unwrap().1 + } + + /// Get the region outlived by `longer_fr` and live at `element`. + fn region_from_element( + &self, + longer_fr: RegionVid, + element: &RegionElement<'tcx>, + ) -> RegionVid { + match *element { + RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), + RegionElement::RootUniversalRegion(r) => r, + RegionElement::PlaceholderRegion(error_placeholder) => self + .definitions + .iter_enumerated() + .find_map(|(r, definition)| match definition.origin { + NllRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), + _ => None, + }) + .unwrap(), + } + } + + /// Get the region definition of `r`. + pub(crate) fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { + &self.definitions[r] + } + + /// Check if the SCC of `r` contains `upper`, a free region. + pub(crate) fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { + let r_scc = self.constraint_sccs.scc(r); + self.scc_values.contains_free_region(r_scc, upper) + } + + pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> { + &self.universal_region_relations.universal_regions + } + + /// Tries to find the best constraint to blame for the fact that + /// `R: from_region`, where `R` is some region that meets + /// `target_test`. This works by following the constraint graph, + /// creating a constraint path that forces `R` to outlive + /// `from_region`, and then finding the best choices within that + /// path to blame. + #[instrument(level = "debug", skip(self))] + pub(crate) fn best_blame_constraint( + &self, + from_region: RegionVid, + from_region_origin: NllRegionVariableOrigin<'tcx>, + to_region: RegionVid, + ) -> BestBlame<'tcx> { + assert!(from_region != to_region, "Trying to blame a region for itself!"); + + let path = self.constraint_path_between_regions(from_region, to_region).unwrap(); + + // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`, + // redirect search towards `'unnameable`. + let due_to_placeholder_outlives = path.iter().find_map(|c| { + if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category { + Some(unnameable) + } else { + None + } + }); + + // Edge case: it's possible that `'from_region` is an unnameable placeholder. + let mut path = if let Some(unnameable) = due_to_placeholder_outlives + && unnameable != from_region + { + // We ignore the extra edges due to unnameable placeholders to get + // an explanation that was present in the original constraint graph. + self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0 + } else { + path + }; + + debug!( + "path={:#?}", + path.iter() + .map(|c| format!( + "{:?} ({:?}: {:?})", + c, + self.constraint_sccs.scc(c.sup), + self.constraint_sccs.scc(c.sub), + )) + .collect::>() + ); + + // When reporting an error, there is typically a chain of constraints leading from some + // "source" region which must outlive some "target" region. + // In most cases, we prefer to "blame" the constraints closer to the target -- + // but there is one exception. When constraints arise from higher-ranked subtyping, + // we generally prefer to blame the source value, + // as the "target" in this case tends to be some type annotation that the user gave. + // Therefore, if we find that the region origin is some instantiation + // of a higher-ranked region, we start our search from the "source" point + // rather than the "target", and we also tweak a few other things. + // + // An example might be this bit of Rust code: + // + // ```rust + // let x: fn(&'static ()) = |_| {}; + // let y: for<'a> fn(&'a ()) = x; + // ``` + // + // In MIR, this will be converted into a combination of assignments and type ascriptions. + // In particular, the 'static is imposed through a type ascription: + // + // ```rust + // x = ...; + // AscribeUserType(x, fn(&'static ()) + // y = x; + // ``` + // + // We wind up ultimately with constraints like + // + // ```rust + // !a: 'temp1 // from the `y = x` statement + // 'temp1: 'temp2 + // 'temp2: 'static // from the AscribeUserType + // ``` + // + // and here we prefer to blame the source (the y = x statement). + let blame_source = match from_region_origin { + NllRegionVariableOrigin::FreeRegion => true, + NllRegionVariableOrigin::Placeholder(_) => false, + // `'existential: 'whatever` never results in a region error by itself. + // We may always infer it to `'static` afterall. This means while an error + // path may go through an existential, these existentials are never the + // `from_region`. + NllRegionVariableOrigin::Existential { name: _ } => { + unreachable!("existentials can outlive everything") + } + }; + + // To pick a constraint to blame, we organize constraints by how interesting we expect them + // to be in diagnostics, then pick the most interesting one closest to either the source or + // the target on our constraint path. + let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| { + // Try to avoid blaming constraints from desugarings, since they may not clearly match + // match what users have written. As an exception, allow blaming returns generated by + // `?` desugaring, since the correspondence is fairly clear. + let category = if let Some(kind) = constraint.span.desugaring_kind() + && (kind != DesugaringKind::QuestionMark + || !matches!(constraint.category, ConstraintCategory::Return(_))) + { + ConstraintCategory::Boring + } else { + constraint.category + }; + + let interest = match category { + // Returns usually provide a type to blame and have specially written diagnostics, + // so prioritize them. + ConstraintCategory::Return(_) => 0, + // Unsizing coercions are interesting, since we have a note for that: + // `BorrowExplanation::add_object_lifetime_default_note`. + // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue + // #131008 for an example of where we currently don't emit it but should. + // Once the note is handled properly, this case should be removed. Until then, it + // should be as limited as possible; the note is prone to false positives and this + // constraint usually isn't best to blame. + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: _, + unsize_to: Some(unsize_ty), + is_implicit_coercion: true, + } if to_region == self.universal_regions().fr_static + // Mirror the note's condition, to minimize how often this diverts blame. + && let ty::Adt(_, args) = unsize_ty.kind() + && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) + // Mimic old logic for this, to minimize false positives in tests. + && !path + .iter() + .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) => + { + 1 + } + // Between other interesting constraints, order by their position on the `path`. + ConstraintCategory::Yield + | ConstraintCategory::UseAsConst + | ConstraintCategory::UseAsStatic + | ConstraintCategory::TypeAnnotation( + AnnotationSource::Ascription + | AnnotationSource::Declaration + | AnnotationSource::OpaqueCast, + ) + | ConstraintCategory::Cast { .. } + | ConstraintCategory::CallArgument(_) + | ConstraintCategory::CopyBound + | ConstraintCategory::SizedBound + | ConstraintCategory::Assignment + | ConstraintCategory::Usage + | ConstraintCategory::ClosureUpvar(_) => 2, + // Generic arguments are unlikely to be what relates regions together + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, + // We handle predicates and opaque types specially; don't prioritize them here. + ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, + // `Boring` constraints can correspond to user-written code and have useful spans, + // but don't provide any other useful information for diagnostics. + ConstraintCategory::Boring => 5, + // `BoringNoLocation` constraints can point to user-written code, but are less + // specific, and are not used for relations that would make sense to blame. + ConstraintCategory::BoringNoLocation => 6, + // Do not blame internal constraints if we can avoid it. Never blame + // the `'region: 'static` constraints introduced by placeholder outlives. + ConstraintCategory::Internal => 7, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8, + ConstraintCategory::SolverRegionConstraint(_) => 9, + }; + + debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); + + interest + }; + + let best_choice = if blame_source { + path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 + } else { + path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 + }; + + debug!(?best_choice, ?blame_source); + + let best_blame_idx = if let Some(next) = path.get(best_choice + 1) + && matches!(path[best_choice].category, ConstraintCategory::Return(_)) + && next.category == ConstraintCategory::OpaqueType + { + // The return expression is being influenced by the return type being + // impl Trait, point at the return type and not the return expr. + best_choice + 1 + } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal) + && let Some(field) = path.iter().find_map(|p| { + if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None } + }) + { + path[best_choice].category = + ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); + best_choice + } else { + best_choice + }; + + assert!( + !matches!( + path[best_blame_idx].category, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + ), + "Illegal placeholder constraint blamed; should have redirected to other region relation" + ); + + BestBlame { path, idx: best_blame_idx } + } + + pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + // Query canonicalization can create local superuniverses (for example in + // `InferCtx::query_response_instantiation_guess`), but they don't have an associated + // `UniverseInfo` explaining why they were created. + // This can cause ICEs if these causes are accessed in diagnostics, for example in issue + // #114907 where this happens via liveness and dropck outlives results. + // Therefore, we return a default value in case that happens, which should at worst emit a + // suboptimal error, instead of the ICE. + self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other) + } + + /// Tries to find the terminator of the loop in which the region 'r' resides. + /// Returns the location of the terminator if found. + pub(crate) fn find_loop_terminator_location( + &self, + r: RegionVid, + body: &Body<'_>, + ) -> Option { + let scc = self.constraint_sccs.scc(r); + let locations = self.scc_values.locations_outlived_by(scc); + for location in locations { + let bb = &body[location.block]; + if let Some(terminator) = &bb.terminator + // terminator of a loop should be TerminatorKind::FalseUnwind + && let TerminatorKind::FalseUnwind { .. } = terminator.kind + { + return Some(location); + } + } + None + } + + /// Access to the SCC constraint graph. + /// This can be used to quickly under-approximate the regions which are equal to each other + /// and their relative orderings. + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + pub(crate) fn constraint_sccs(&self) -> &ConstraintSccs { + &self.constraint_sccs + } + + /// Returns the representative `RegionVid` for a given SCC. + /// See `RegionTracker` for how a region variable ID is chosen. + /// + /// It is a hacky way to manage checking regions for equality, + /// since we can 'canonicalize' each region to the representative + /// of its SCC and be sure that -- if they have the same repr -- + /// they *must* be equal (though not having the same repr does not + /// mean they are unequal). + fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid { + self.scc_annotations[scc].representative.rvid() + } + + pub(crate) fn liveness_constraints(&self) -> &LivenessValues { + &self.liveness_constraints + } + + /// Returns whether the `loan_idx` is live at the given `location`: whether its issuing + /// region is contained within the type of a variable that is live at this point. + /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. + pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { + let point = self.liveness_constraints.point_from_location(location); + self.liveness_constraints.is_loan_live_at(loan_idx, point) + } +} From 270556173cf237adfe7e6c35f8bead526a9700f6 Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Tue, 22 Sep 2026 18:26:44 -0700 Subject: [PATCH 0728/1309] Adjust for Arm64EC name mangling when checking for exported symbols --- compiler/rustc_codegen_ssa/src/back/symbol_edit.rs | 5 ++++- .../rmake.rs | 14 ++++++++++---- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs index 490c634a1845a..fa6fc1368e133 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_edit.rs @@ -503,7 +503,10 @@ fn coff_collect_impl<'data, Coff: CoffHeader>( if strip_underscore { name = name.strip_prefix('_').unwrap_or(&name).to_string(); } - if !exported.contains(&name) { + let is_exported = exported.contains(&name) + || (header.machine() == pe::IMAGE_FILE_MACHINE_ARM64EC + && name.strip_prefix('#').is_some_and(|name| exported.contains(name))); + if !is_exported { out.insert(name); } } diff --git a/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs b/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs index 38cf724ee7d1b..0b3f445a6ec70 100644 --- a/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs +++ b/tests/run-make/staticlib-rename-internal-symbols-coff/rmake.rs @@ -153,8 +153,6 @@ fn check_coff_symbols( ) { // ImageSymbol is 18 bytes; ImageSymbolEx (bigobj) is 20. let sym_size = std::mem::size_of::(); - // i686 decorates symbol names with a leading underscore. - let strip_underscore = header.machine() == pe::IMAGE_FILE_MACHINE_I386; let Ok(symbols) = header.symbols(data) else { return }; let strings = symbols.strings(); let symtab_base = header.pointer_to_symbol_table() as usize; @@ -179,8 +177,16 @@ fn check_coff_symbols( } let Ok(name_bytes) = symbol.name(strings) else { continue }; let Ok(mut name) = str::from_utf8(name_bytes).map(String::from) else { continue }; - if strip_underscore { - name = name.strip_prefix('_').unwrap_or(&name).to_string(); + + // Adjust for various symbol decorations. + match header.machine() { + pe::IMAGE_FILE_MACHINE_I386 => { + name = name.strip_prefix('_').unwrap_or(&name).to_string(); + } + pe::IMAGE_FILE_MACHINE_ARM64EC => { + name = name.strip_prefix('#').unwrap_or(&name).to_string(); + } + _ => {} } if EXPORTED.contains(&name.as_str()) { From 5e2db49550ee899e9c9227436b3b77863a043abd Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 22 Sep 2026 14:59:51 -0700 Subject: [PATCH 0729/1309] revert "don't calculate dtors if the self ty has impossible bounds" This reverts commit 644839ab44dbc1507ebe1bb055d9b01e308e7067, reversing changes made to 73cf3019a83292f82c49dd12c81a9ce39635563e. --- .../src/check/always_applicable.rs | 41 +------------------ compiler/rustc_hir_analysis/src/check/mod.rs | 12 +----- compiler/rustc_middle/src/ty/util.rs | 12 ------ .../150387.rs} | 6 +-- .../153947.rs} | 7 +--- 5 files changed, 5 insertions(+), 73 deletions(-) rename tests/{ui/dropck/overlapping_impossible_drop_min_specialization.rs => crashes/150387.rs} (84%) rename tests/{ui/dropck/overlapping_impossible_drop.rs => crashes/153947.rs} (83%) diff --git a/compiler/rustc_hir_analysis/src/check/always_applicable.rs b/compiler/rustc_hir_analysis/src/check/always_applicable.rs index b098a6c186457..fd46e94fd9cb7 100644 --- a/compiler/rustc_hir_analysis/src/check/always_applicable.rs +++ b/compiler/rustc_hir_analysis/src/check/always_applicable.rs @@ -8,7 +8,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::codes::*; use rustc_errors::{ErrorGuaranteed, struct_span_code_err}; use rustc_infer::infer::{RegionResolutionError, TyCtxtInferExt}; -use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; +use rustc_infer::traits::{ObligationCause, ObligationCauseCode}; use rustc_middle::ty::util::CheckRegions; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, TypingMode}; use rustc_span::{span_bug, sym}; @@ -133,45 +133,6 @@ pub(crate) fn check_negative_auto_trait_impl<'tcx>( } } -/// Checks if the self ty's where-clauses are able to be proven. For instance, if we have multiple -/// overlapping drop impls, and we have `[T]: Sized` on both the impls and the self ty, we shouldn't -/// error or ICE, since neither the ADT nor the impls are nameable in practice. -/// -/// We already emit errors for the case where the impossible bound exists only on the self ty, or -/// only on the impl(s). -pub(crate) fn is_impossible_self_ty(tcx: TyCtxt<'_>, adt_did: LocalDefId) -> bool { - let clauses = tcx.clauses_of(adt_did).clauses; - if clauses.is_empty() { - return false; - } - - // Be conservative in cases where we have `W` and a method like `Self: Sized`, - // since that method *may* have some substitutions where the predicates hold. - // - // This replicates the logic we use in coherence. - let infcx = tcx - .infer_ctxt() - .ignoring_regions() - .with_next_trait_solver(true) - .enable_next_solver_overflow_fcw(false) - .build(TypingMode::Coherence); - let param_env = ty::ParamEnv::empty(); - let args = infcx.fresh_args_for_item(tcx.def_span(adt_did), adt_did.to_def_id()); - - let obligations = clauses.iter().map(|(clause, span)| { - Obligation::new( - tcx, - ObligationCause::dummy_with_span(*span), - param_env, - ty::EarlyBinder::bind(tcx, *clause).instantiate(tcx, args).skip_norm_wip(), - ) - }); - - let ocx = ObligationCtxt::new(&infcx); - ocx.register_obligations(obligations); - ocx.try_evaluate_obligations().has_errors() -} - fn ensure_impl_params_and_item_params_correspond<'tcx>( tcx: TyCtxt<'tcx>, impl_def_id: LocalDefId, diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs index fa2b3e9f25342..9eaaecaa02227 100644 --- a/compiler/rustc_hir_analysis/src/check/mod.rs +++ b/compiler/rustc_hir_analysis/src/check/mod.rs @@ -125,11 +125,7 @@ pub(super) fn provide(providers: &mut Providers) { } fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - let dtor = tcx.calculate_dtor( - def_id, - always_applicable::check_drop_impl, - always_applicable::is_impossible_self_ty, - ); + let dtor = tcx.calculate_dtor(def_id, always_applicable::check_drop_impl); if dtor.is_none() && tcx.features().async_drop() { if let Some(async_dtor) = adt_async_destructor(tcx, def_id) { // When type has AsyncDrop impl, but doesn't have Drop impl, generate error @@ -141,11 +137,7 @@ fn adt_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option } fn adt_async_destructor(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Option { - let result = tcx.calculate_async_dtor( - def_id, - always_applicable::check_drop_impl, - always_applicable::is_impossible_self_ty, - ); + let result = tcx.calculate_async_dtor(def_id, always_applicable::check_drop_impl); // Async drop in libstd/libcore would become insta-stable — catch that mistake. if result.is_some() && tcx.features().staged_api() { span_bug!(tcx.def_span(def_id), "don't use async drop in libstd, it becomes insta-stable"); diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index db983038e1af9..31b7b719fa9cf 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -377,7 +377,6 @@ impl<'tcx> TyCtxt<'tcx> { self, adt_did: LocalDefId, validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>, - impossible_self_ty: impl Fn(Self, LocalDefId) -> bool, ) -> Option { let drop_trait = self.lang_items().drop_trait()?; self.ensure_result().coherent_trait(drop_trait).ok()?; @@ -395,11 +394,6 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - if impossible_self_ty(self, adt_did) { - // The self ty is unnameable, so it can't be constructed in the first place. - continue; - } - let Some(&item_id) = self.associated_item_def_ids(impl_did).first() else { self.dcx() .span_delayed_bug(self.def_span(impl_did), "Drop impl without drop function"); @@ -430,7 +424,6 @@ impl<'tcx> TyCtxt<'tcx> { self, adt_did: LocalDefId, validate: impl Fn(Self, LocalDefId) -> Result<(), ErrorGuaranteed>, - impossible_self_ty: impl Fn(Self, LocalDefId) -> bool, ) -> Option { let async_drop_trait = self.lang_items().async_drop_trait()?; self.ensure_result().coherent_trait(async_drop_trait).ok()?; @@ -448,11 +441,6 @@ impl<'tcx> TyCtxt<'tcx> { continue; } - if impossible_self_ty(self, adt_did) { - // The self ty is unnameable, so it can't be constructed in the first place. - continue; - } - if let Some(old_impl_did) = dtor_candidate { self.dcx() .struct_span_err(self.def_span(impl_did), "multiple async drop impls found") diff --git a/tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs b/tests/crashes/150387.rs similarity index 84% rename from tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs rename to tests/crashes/150387.rs index e201c75f4f4b3..b29ce143fb4ea 100644 --- a/tests/ui/dropck/overlapping_impossible_drop_min_specialization.rs +++ b/tests/crashes/150387.rs @@ -1,7 +1,4 @@ -//@ check-pass - -// Regression test for #150387 - +//@ known-bug: #150387 #![feature(min_specialization)] #![allow(dead_code)] @@ -13,5 +10,4 @@ impl Drop for Thing where [T]: Sized { impl Drop for Thing where [T]: Sized { fn drop(&mut self) {} } - fn main() {} diff --git a/tests/ui/dropck/overlapping_impossible_drop.rs b/tests/crashes/153947.rs similarity index 83% rename from tests/ui/dropck/overlapping_impossible_drop.rs rename to tests/crashes/153947.rs index 6200572b9b72e..39bc8c074cfc0 100644 --- a/tests/ui/dropck/overlapping_impossible_drop.rs +++ b/tests/crashes/153947.rs @@ -1,9 +1,5 @@ -//@ check-pass - -// Regression test for #153947 - +//@ known-bug: #153947 #![expect(drop_bounds)] - pub struct Thing(T) where [T]: Sized, Self: Drop; impl Drop for Thing where [T]: Sized, Self: Drop { fn drop(&mut self) {} @@ -11,5 +7,4 @@ impl Drop for Thing where [T]: Sized, Self: Drop { impl Drop for Thing where [T]: Sized, Self: Drop { fn drop(&mut self) {} } - fn main() {} From a18393e284772b14529f788bbd72ad5c9ca57795 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 23 Sep 2026 18:20:40 +0200 Subject: [PATCH 0730/1309] update miri tests --- .../fail/async-shared-mutable.stack.stderr | 8 +++- .../fail/async-shared-mutable.tree.stderr | 8 +++- .../fail/both_borrows/closure-captured-ref.rs | 18 ++++++++ .../closure-captured-ref.stack.stderr | 26 ++++++++++++ .../closure-captured-ref.tree.stderr | 41 +++++++++++++++++++ .../tests/pass/both_borrows/maybe_dangling.rs | 14 ------- 6 files changed, 97 insertions(+), 18 deletions(-) create mode 100644 src/tools/miri/tests/fail/both_borrows/closure-captured-ref.rs create mode 100644 src/tools/miri/tests/fail/both_borrows/closure-captured-ref.stack.stderr create mode 100644 src/tools/miri/tests/fail/both_borrows/closure-captured-ref.tree.stderr diff --git a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr index 4435541bc0a1c..bdd004d5da99f 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.stack.stderr @@ -9,8 +9,12 @@ LL | *x = 1; help: was created by a Unique retag at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | let x = &mut 0u8; - | ^^^^^^^^ +LL | / core::future::poll_fn(move |_| { +LL | | *x = 1; +LL | | Poll::<()>::Pending +LL | | }) +LL | | .await + | |______________^ help: was later invalidated at offsets [RANGE] by a SharedReadOnly retag --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr index bbb62a7e27b2b..f9e75082758dd 100644 --- a/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr +++ b/src/tools/miri/tests/fail/async-shared-mutable.tree.stderr @@ -10,8 +10,12 @@ LL | *x = 1; help: the accessed tag was created here, in the initial state Reserved --> tests/fail/async-shared-mutable.rs:LL:CC | -LL | let x = &mut 0u8; - | ^^^^^^^^ +LL | / core::future::poll_fn(move |_| { +LL | | *x = 1; +LL | | Poll::<()>::Pending +LL | | }) +LL | | .await + | |______________^ help: the accessed tag later transitioned to Unique due to a child write access at offsets [RANGE] --> tests/fail/async-shared-mutable.rs:LL:CC | diff --git a/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.rs b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.rs new file mode 100644 index 0000000000000..3b4c7f425ee36 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.rs @@ -0,0 +1,18 @@ +//@revisions: stack tree +//@[tree]compile-flags: -Zmiri-tree-borrows + +//@[stack]error-in-other-file: protected +//@[tree]error-in-other-file: forbidden + +// A reference in a closure is treated like a reference in a struct. +fn main() { + fn invoke(f: impl FnOnce()) { + // The closure has captured a reference that will be freed while `invoke` runs. + f() + } + + let p = Box::leak(Box::new(0i32)); + invoke(move || { + drop(unsafe { Box::from_raw(p) }); + }); +} diff --git a/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.stack.stderr b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.stack.stderr new file mode 100644 index 0000000000000..d7b2888106650 --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.stack.stderr @@ -0,0 +1,26 @@ +error: Undefined Behavior: deallocating while item [Unique for ] is strongly protected + --> RUSTLIB/alloc/src/boxed.rs:LL:CC + | +LL | self.1.deallocate(From::from(ptr.cast()), layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information + = note: stack backtrace: + 0: as std::ops::Drop>::drop + at RUSTLIB/alloc/src/boxed.rs:LL:CC + 1: std::ptr::drop_glue::> - shim(Some(std::boxed::Box)) + at RUSTLIB/core/src/ptr/mod.rs:LL:CC + 2: std::mem::drop::> + at RUSTLIB/core/src/mem/mod.rs:LL:CC + 3: main::{closure#0} + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + 4: main::invoke::<{closure@tests/fail/both_borrows/closure-captured-ref.rs:LL:CC}> + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + 5: main + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.tree.stderr b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.tree.stderr new file mode 100644 index 0000000000000..b7c284969438a --- /dev/null +++ b/src/tools/miri/tests/fail/both_borrows/closure-captured-ref.tree.stderr @@ -0,0 +1,41 @@ +error: Undefined Behavior: deallocation through at ALLOC[0x0] is forbidden + --> RUSTLIB/alloc/src/boxed.rs:LL:CC + | +LL | self.1.deallocate(From::from(ptr.cast()), layout); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Undefined Behavior occurred here + | + = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental + = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/tree-borrows.md for further information + = help: the allocation of the accessed tag also contains the strongly protected tag + = help: the strongly protected tag disallows deallocations +help: the accessed tag was created here + --> tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + | +LL | drop(unsafe { Box::from_raw(p) }); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: the strongly protected tag was created here, in the initial state Reserved + --> tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + | +LL | invoke(move || { + | ____________^ +LL | | drop(unsafe { Box::from_raw(p) }); +LL | | }); + | |_____^ + = note: stack backtrace: + 0: as std::ops::Drop>::drop + at RUSTLIB/alloc/src/boxed.rs:LL:CC + 1: std::ptr::drop_glue::> - shim(Some(std::boxed::Box)) + at RUSTLIB/core/src/ptr/mod.rs:LL:CC + 2: std::mem::drop::> + at RUSTLIB/core/src/mem/mod.rs:LL:CC + 3: main::{closure#0} + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + 4: main::invoke::<{closure@tests/fail/both_borrows/closure-captured-ref.rs:LL:CC}> + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + 5: main + at tests/fail/both_borrows/closure-captured-ref.rs:LL:CC + +note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace + +error: aborting due to 1 previous error + diff --git a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs index 2d37344d24072..028dcef8fa2d3 100644 --- a/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs +++ b/src/tools/miri/tests/pass/both_borrows/maybe_dangling.rs @@ -14,7 +14,6 @@ fn main() { reference(); write_through_shared_ref(); large(); - closure(); } fn boxy() { @@ -65,16 +64,3 @@ fn large() { // Used to be rejected due to faulty logic for the "does this fit the address space" check. let _x: MaybeDangling<&i8> = unsafe { mem::transmute(usize::MAX - 127) }; } - -// A closure acts like MaybeDangling. -fn closure() { - fn invoke(f: impl FnOnce()) { - // The closure has captured a reference that will be freed while `invoke` runs. - f() - } - - let p = Box::leak(Box::new(0i32)); - invoke(move || { - drop(unsafe { Box::from_raw(p) }); - }); -} From e9824e4145a1be3aa78354393bb7351f5d656d98 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Tue, 22 Sep 2026 16:31:53 -0700 Subject: [PATCH 0731/1309] properly decrement available_depth on cycles and provisional cache hits --- .../rustc_type_ir/src/search_graph/mod.rs | 39 +++++++++++-------- .../overflow/cycle-required-depth.rs | 27 +++++++++++++ .../overflow/cycle-required-depth.stderr | 21 ++++++++++ .../provisional-cache-required-depth.rs | 27 +++++++++++++ .../provisional-cache-required-depth.stderr | 21 ++++++++++ 5 files changed, 118 insertions(+), 17 deletions(-) create mode 100644 tests/ui/traits/next-solver/overflow/cycle-required-depth.rs create mode 100644 tests/ui/traits/next-solver/overflow/cycle-required-depth.stderr create mode 100644 tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.rs create mode 100644 tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.stderr diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index c081898f26f56..228b6c34b06ed 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -628,8 +628,8 @@ pub struct SearchGraph, X: Cx = ::Cx> { /// don't need to track the nested goals used while computing a provisional /// cache entry. enum UpdateParentGoalCtxt<'a, X: Cx> { - Ordinary { nested_goals: &'a NestedGoals, min_reachable_available_depth: AvailableDepth }, - CycleOnStack(X::Input), + Ordinary { nested_goals: &'a NestedGoals }, + CycleOnStack { head: X::Input }, ProvisionalCacheHit, } @@ -653,9 +653,12 @@ impl, X: Cx> SearchGraph { heads: impl Iterator, encountered_overflow: bool, context: UpdateParentGoalCtxt<'_, X>, + min_reachable_available_depth: AvailableDepth, ) { if let Some((parent_index, parent)) = stack.last_mut_with_index() { parent.encountered_overflow |= encountered_overflow; + parent.min_reached_available_depth = + parent.min_reached_available_depth.min(min_reachable_available_depth); for (head_index, head) in heads { if let Some(candidate_usages) = &mut parent.candidate_usages { @@ -679,13 +682,11 @@ impl, X: Cx> SearchGraph { } } let parent_depends_on_cycle = match context { - UpdateParentGoalCtxt::Ordinary { nested_goals, min_reachable_available_depth } => { - parent.min_reached_available_depth = - parent.min_reached_available_depth.min(min_reachable_available_depth); + UpdateParentGoalCtxt::Ordinary { nested_goals } => { parent.nested_goals.extend_from_child(step_kind_from_parent, nested_goals); !nested_goals.is_empty() } - UpdateParentGoalCtxt::CycleOnStack(head) => { + UpdateParentGoalCtxt::CycleOnStack { head } => { // We lookup provisional cache entries before detecting cycles. // We therefore can't use a global cache entry if it contains a cycle // whose head is in the provisional cache. @@ -811,7 +812,9 @@ impl, X: Cx> SearchGraph { // - A // - BA cycle // - CB :x: - if let Some(result) = self.lookup_provisional_cache(input, step_kind_from_parent) { + if let Some(result) = + self.lookup_provisional_cache(input, step_kind_from_parent, available_depth) + { return result; } @@ -839,7 +842,9 @@ impl, X: Cx> SearchGraph { // avoid iterating over the stack in case a goal has already been computed. // This may not have an actual performance impact and we could reorder them // as it may reduce the number of `nested_goals` we need to track. - if let Some(result) = self.check_cycle_on_stack(cx, input, step_kind_from_parent) { + if let Some(result) = + self.check_cycle_on_stack(cx, input, step_kind_from_parent, available_depth) + { debug_assert!(validate_cache.is_none(), "global cache and cycle on stack: {input:?}"); return result; } @@ -874,10 +879,8 @@ impl, X: Cx> SearchGraph { step_kind_from_parent, evaluation_result.heads.iter(), evaluation_result.encountered_overflow, - UpdateParentGoalCtxt::Ordinary { - nested_goals: &evaluation_result.nested_goals, - min_reachable_available_depth: available_depth - evaluation_result.required_depth, - }, + UpdateParentGoalCtxt::Ordinary { nested_goals: &evaluation_result.nested_goals }, + available_depth - evaluation_result.required_depth, ); let result = evaluation_result.result; @@ -1119,6 +1122,7 @@ impl, X: Cx> SearchGraph { &mut self, input: X::Input, step_kind_from_parent: PathKind, + available_depth: AvailableDepth, ) -> Option { if !D::ENABLE_PROVISIONAL_CACHE { return None; @@ -1157,6 +1161,7 @@ impl, X: Cx> SearchGraph { heads.iter(), encountered_overflow, UpdateParentGoalCtxt::ProvisionalCacheHit, + available_depth, ); debug!(?head_index, ?path_from_head, "provisional cache hit"); return Some(result); @@ -1278,10 +1283,8 @@ impl, X: Cx> SearchGraph { step_kind_from_parent, heads, encountered_overflow, - UpdateParentGoalCtxt::Ordinary { - nested_goals, - min_reachable_available_depth: available_depth - required_depth, - }, + UpdateParentGoalCtxt::Ordinary { nested_goals }, + available_depth - required_depth, ); debug!(?required_depth, "global cache hit"); @@ -1294,6 +1297,7 @@ impl, X: Cx> SearchGraph { cx: X, input: X::Input, step_kind_from_parent: PathKind, + available_depth: AvailableDepth, ) -> Option { let head_index = self.stack.find(input)?; // We have a nested goal which directly relies on a goal deeper in the stack. @@ -1312,7 +1316,8 @@ impl, X: Cx> SearchGraph { step_kind_from_parent, iter::once((head_index, head)), false, - UpdateParentGoalCtxt::CycleOnStack(input), + UpdateParentGoalCtxt::CycleOnStack { head: input }, + available_depth, ); // Return the provisional result or, if we're in the first iteration, diff --git a/tests/ui/traits/next-solver/overflow/cycle-required-depth.rs b/tests/ui/traits/next-solver/overflow/cycle-required-depth.rs new file mode 100644 index 0000000000000..105460eee8013 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/cycle-required-depth.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +// We must properly decrement available_depth when encountering cycles. +// Proving `Foo: Send` results in a cycle: +// - Foo: Send +// ->PhantomData: Send +// ->Foo: Send +// and if we cache this result with too small of a required depth, the second +// `require` call will succeed with the cached result where it would fail if +// the goal were freshly evaluated. + +#![recursion_limit = "6"] + +use std::marker::PhantomData; + +pub struct Foo(PhantomData); +pub struct W(T); + +fn require() {} + +fn main() { + require::(); + require::>>>>>(); + //~^ WARN overflow evaluating the requirement `W>>>>: Send` + //~| WARN this was previously accepted by the compiler but is being phased out +} diff --git a/tests/ui/traits/next-solver/overflow/cycle-required-depth.stderr b/tests/ui/traits/next-solver/overflow/cycle-required-depth.stderr new file mode 100644 index 0000000000000..15e121053c22d --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/cycle-required-depth.stderr @@ -0,0 +1,21 @@ +warning: overflow evaluating the requirement `W>>>>: Send` + --> $DIR/cycle-required-depth.rs:24:5 + | +LL | require::>>>>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: which requires `W>>>: Send` + = note: which requires `W>>: Send` + = note: which requires `W>: Send` + = note: which requires `W: Send` + = note: which requires `Foo: Send` + = note: and so on... + = help: consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved + = help: or consider increasing the recursion limit by adding a `#![recursion_limit = "12"]` attribute to your crate (`cycle_required_depth`) + = note: this lint is attached to the whole crate and can't be disabled on a per-function basis + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #159228 + = note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + diff --git a/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.rs b/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.rs new file mode 100644 index 0000000000000..ad070e2d276a3 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.rs @@ -0,0 +1,27 @@ +//@ compile-flags: -Znext-solver +//@ check-pass + +#![recursion_limit = "6"] +use std::marker::PhantomData; + +// We need to decrement available_depth on provisional cache hits. +// e.g., in the following example: +// A: Send, avail = 6 +// -> PhantomData: Send, avail = 5 +// -> A: Send, avail = 4 +// -> B: Send, avail = 5 +// -> C: Send, avail = 4 +// -> PhantomData: Send, provisional cache hit, avail = 4 if we don't decrement +struct A(PhantomData, B); +struct B(C); +struct C(PhantomData); +struct W(T); + +fn require() {} + +fn main() { + require::(); + require::>>>>(); + //~^ WARN overflow evaluating the requirement `W>>>: Send` + //~| WARN this was previously accepted by the compiler but is being phased out +} diff --git a/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.stderr b/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.stderr new file mode 100644 index 0000000000000..a4ee2a2d87078 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/provisional-cache-required-depth.stderr @@ -0,0 +1,21 @@ +warning: overflow evaluating the requirement `W>>>: Send` + --> $DIR/provisional-cache-required-depth.rs:24:5 + | +LL | require::>>>>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: which requires `W>>: Send` + = note: which requires `W>: Send` + = note: which requires `W: Send` + = note: which requires `A: Send` + = note: which requires `B: Send` + = note: and so on... + = help: consider adding a manual `impl` of auto traits like `Send` for intermediate types, if auto traits are involved + = help: or consider increasing the recursion limit by adding a `#![recursion_limit = "12"]` attribute to your crate (`provisional_cache_required_depth`) + = note: this lint is attached to the whole crate and can't be disabled on a per-function basis + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #159228 + = note: `#[warn(recursion_depth_exceeding_limit)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + From e5b84474ef937005a0f22d768c998017ceafc37e Mon Sep 17 00:00:00 2001 From: Lucas Sunsi Abreu Date: Wed, 23 Sep 2026 14:59:25 -0300 Subject: [PATCH 0732/1309] Add regression test for trait predicate with escaping bounds Co-authored-by: Philip Sampaio Co-authored-by: Bruno Gomes --- .../trait-predicate-with-escaping-bounds.rs | 16 +++++++++ ...rait-predicate-with-escaping-bounds.stderr | 34 +++++++++++++++++++ 2 files changed, 50 insertions(+) create mode 100644 tests/ui/traits/trait-predicate-with-escaping-bounds.rs create mode 100644 tests/ui/traits/trait-predicate-with-escaping-bounds.stderr diff --git a/tests/ui/traits/trait-predicate-with-escaping-bounds.rs b/tests/ui/traits/trait-predicate-with-escaping-bounds.rs new file mode 100644 index 0000000000000..0aac6bae5fe99 --- /dev/null +++ b/tests/ui/traits/trait-predicate-with-escaping-bounds.rs @@ -0,0 +1,16 @@ +//! Regression test for . +//@ check-fail + +struct StatSeries {} + +impl StatSeries { + fn new(headers: [H; N]) -> () //~ ERROR: cannot find value `N` in this scope [E0425] + where + String: for<'a> From<&'a H>, + { + } +} + +fn main() { + let series = StatSeries::new([""]); //~ ERROR: the trait bound `for<'a> String: From<&'a &str>` is not satisfied [E0277] +} diff --git a/tests/ui/traits/trait-predicate-with-escaping-bounds.stderr b/tests/ui/traits/trait-predicate-with-escaping-bounds.stderr new file mode 100644 index 0000000000000..dd1b793eedb10 --- /dev/null +++ b/tests/ui/traits/trait-predicate-with-escaping-bounds.stderr @@ -0,0 +1,34 @@ +error[E0425]: cannot find value `N` in this scope + --> $DIR/trait-predicate-with-escaping-bounds.rs:7:28 + | +LL | fn new(headers: [H; N]) -> () + | ^ not found in this scope + +error[E0277]: the trait bound `for<'a> String: From<&'a &str>` is not satisfied + --> $DIR/trait-predicate-with-escaping-bounds.rs:15:34 + | +LL | let series = StatSeries::new([""]); + | --------------- ^^^^ the trait `for<'a> From<&'a &str>` is not implemented for `String` + | | + | required by a bound introduced by this call + | + = help: `String` implements trait `From`: + From<&String> + From<&mut str> + From<&str> + From> + From> + From +note: required by a bound in `StatSeries::new` + --> $DIR/trait-predicate-with-escaping-bounds.rs:9:17 + | +LL | impl StatSeries { +LL | fn new(headers: [H; N]) -> () +LL | where +LL | String: for<'a> From<&'a H>, + | ^^^^^^^^^^^^^^^^^^^ required by this bound in `StatSeries::new` + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0277, E0425. +For more information about an error, try `rustc --explain E0277`. From b6f9bfc9ff8f5f8880e2787a59e84d68c4805a41 Mon Sep 17 00:00:00 2001 From: ltdk Date: Mon, 12 Aug 2024 22:24:51 -0400 Subject: [PATCH 0733/1309] Additional NonZero conversions --- library/core/src/num/nonzero.rs | 163 +++++++++++++++++- .../issue-71394-no-from-impl.stderr | 2 +- 2 files changed, 162 insertions(+), 3 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d0ae6c31267f3..20ff01eb30c31 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1,6 +1,6 @@ //! Definitions of integer that is known not to equal zero. -use super::{IntErrorKind, ParseIntError}; +use super::{IntErrorKind, ParseIntError, TryFromIntError}; use crate::clone::{TrivialClone, UseCloned}; use crate::cmp::Ordering; use crate::hash::{Hash, Hasher}; @@ -9,7 +9,7 @@ use crate::num::imp; use crate::ops::{BitOr, BitOrAssign, Div, DivAssign, Neg, Rem, RemAssign}; use crate::panic::{RefUnwindSafe, UnwindSafe}; use crate::str::FromStr; -use crate::{fmt, intrinsics, ptr, ub_checks}; +use crate::{fmt, intrinsics, ptr, slice, ub_checks}; /// A marker trait for primitive types which can be zero. /// @@ -305,6 +305,114 @@ where } } +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> From<&'a NonZero> for &'a T +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: &'a NonZero) -> &'a T { + nonzero.as_ref() + } +} + +// FIXME: see library/std/tests/slice-from-array-issue-113238.rs +/* +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> From<&'a [NonZero]> for &'a [T] +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: &'a [NonZero]) -> &'a [T] { + nonzero.as_zeroable() + } +} +impl [NonZero] +where + T: ZeroablePrimitive, +{ + /// Implementation of `From<&[NonZero]> for &[T]`. + #[must_use] + #[inline] + fn as_zeroable(&self) -> &[T] { + // SAFETY: `repr(transparent)` ensures that `NonZero` has same layout as `T`, and thus + // `[NonZero]` has same layout as `[T]` + unsafe { &*(slice::from_raw_parts(self.as_ptr().cast::(), self.len())) } + } +} +*/ + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl From<[NonZero; N]> for [T; N] +where + T: ZeroablePrimitive, +{ + #[inline] + fn from(nonzero: [NonZero; N]) -> [T; N] { + nonzero.into_zeroable() + } +} + +// FIXME: can't detect that ZeroablePrimitive is a sealed trait +macro_rules! impl_ref_try_from { + ($($t:ty),* $(,)?) => { + $( + #[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] + impl<'a> TryFrom<&'a $t> for &'a NonZero<$t> { + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: &'a $t) -> Result<&'a NonZero<$t>, TryFromIntError> { + NonZero::from_ref(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } + } + )* + } +} + +impl_ref_try_from! { + u8, + u16, + u32, + u64, + u128, + usize, + i8, + i16, + i32, + i64, + i128, + isize, + char, +} + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl<'a, T> TryFrom<&'a [T]> for &'a [NonZero] +where + T: ZeroablePrimitive, +{ + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: &'a [T]) -> Result<&'a [NonZero], TryFromIntError> { + NonZero::from_slice(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } +} + +#[stable(feature = "more_from_nonzero", since = "CURRENT_RUSTC_VERSION")] +impl TryFrom<[T; N]> for [NonZero; N] +where + T: ZeroablePrimitive, +{ + type Error = TryFromIntError; + + #[inline] + fn try_from(zeroable: [T; N]) -> Result<[NonZero; N], TryFromIntError> { + NonZero::from_array(zeroable).ok_or(TryFromIntError(IntErrorKind::Zero)) + } +} + #[stable(feature = "nonzero_bitor", since = "1.45.0")] #[rustc_const_unstable(feature = "const_ops", issue = "143802")] const impl BitOr for NonZero @@ -460,6 +568,45 @@ where } } + /// Implementation of `From<&NonZero> for &T`. + #[must_use] + #[inline] + fn as_ref(&self) -> &T { + // SAFETY: `repr(transparent)` ensures that `NonZero` has same layout as `T` + unsafe { &*(ptr::from_ref(self).cast::()) } + } + + /// Implementation of `TryFrom<&T> for &NonZero`. + #[must_use] + #[inline] + fn from_ref(n: &T) -> Option<&Self> { + // SAFETY: Memory layout optimization guarantees that `Option>` has + // the same layout and size as `T`, with `0` representing `None`. + let opt_n = unsafe { &*(ptr::from_ref(n).cast::>()) }; + + opt_n.as_ref() + } + + /// Implementation of `TryFrom<&[T]> for &[NonZero]`. + #[must_use] + #[inline] + fn from_slice(n: &[T]) -> Option<&[Self]> { + if n.iter().all(|x| NonZero::new(*x).is_some()) { + // SAFETY: We explicitly checked that all elements are nonzero, and because of `repr(transparent)` + // the layout remains unchanged + Some(unsafe { slice::from_raw_parts(n.as_ptr().cast::>(), n.len()) }) + } else { + None + } + } + + /// Implementation of `TryFrom<[T; N]> for [NonZero; N]`. + #[must_use] + #[inline] + fn from_array(n: [T; N]) -> Option<[Self; N]> { + n.try_map(NonZero::new) + } + /// Returns the contained value as a primitive type. #[stable(feature = "nonzero", since = "1.28.0")] #[rustc_const_stable(feature = "const_nonzero_get", since = "1.34.0")] @@ -487,6 +634,18 @@ where } } +impl [NonZero; N] +where + T: ZeroablePrimitive, +{ + /// Implementation of `From<[NonZero; N]> for [T; N]`. + #[must_use] + #[inline] + fn into_zeroable(self) -> [T; N] { + self.map(NonZero::get) + } +} + macro_rules! nonzero_integer { ( #[$stability:meta] diff --git a/tests/ui/suggestions/issue-71394-no-from-impl.stderr b/tests/ui/suggestions/issue-71394-no-from-impl.stderr index b8a240f7f07c5..e3d01bd588a4f 100644 --- a/tests/ui/suggestions/issue-71394-no-from-impl.stderr +++ b/tests/ui/suggestions/issue-71394-no-from-impl.stderr @@ -13,7 +13,7 @@ LL | let _: &[i8] = data.into(); `[T; 6]` implements `From<(T, T, T, T, T, T)>` `[T; 7]` implements `From<(T, T, T, T, T, T, T)>` `[T; 8]` implements `From<(T, T, T, T, T, T, T, T)>` - and 7 others + and 8 others = note: required for `&[u8]` to implement `Into<&[i8]>` error: aborting due to 1 previous error From 20b6fd622136db582c32a964e3cec9a56030af0d Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Wed, 23 Sep 2026 20:06:33 +0000 Subject: [PATCH 0734/1309] Address review feedback Only check `SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag` if CFI is actually enabled. Use `is_sanitizer_cfi_minimal_runtime_enabled()` helper within `link.rs`. --- compiler/rustc_codegen_ssa/src/back/link.rs | 2 +- compiler/rustc_session/src/session.rs | 6 +++--- tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs | 1 - tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr | 4 +--- 4 files changed, 5 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs index 7c8bb4f59dfba..3a405f275cf4b 100644 --- a/compiler/rustc_codegen_ssa/src/back/link.rs +++ b/compiler/rustc_codegen_ssa/src/back/link.rs @@ -1764,7 +1764,7 @@ fn add_sanitizer_libraries( && (sess.opts.unstable_opts.sanitizer_cfi_diag.unwrap_or(false) || sess.opts.unstable_opts.sanitizer_cfi_recover.unwrap_or(false)) { - if sess.opts.unstable_opts.sanitizer_cfi_minimal_runtime.unwrap_or(false) { + if sess.is_sanitizer_cfi_minimal_runtime_enabled() { link_sanitizer_runtime(sess, flavor, linker, "ubsan_minimal"); } else { link_sanitizer_runtime(sess, flavor, linker, "ubsan"); diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index a209219758026..cea3a32729b98 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1688,12 +1688,12 @@ fn validate_commandline_args_with_session_available(sess: &Session) { } } - // LLVM CFI minimal runtime requires CFI Recover or CFI Diag. + // LLVM CFI minimal runtime requires CFI recovery or CFI diagnostics. if sess.is_sanitizer_cfi_minimal_runtime_enabled() { if !sess.is_sanitizer_cfi_enabled() { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfi); - } - if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) { + } else if !(sess.is_sanitizer_cfi_recover_enabled() || sess.is_sanitizer_cfi_diag_enabled()) + { sess.dcx().emit_err(diagnostics::SanitizerCfiMinimalRuntimeRequiresCfiRecoverOrDiag); } } diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs index 13b296b4329ee..cb68734608ac7 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.rs @@ -8,4 +8,3 @@ #![no_main] //~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` -//~? ERROR `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` diff --git a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr index 251d0d0817631..5cb83e40dc0c4 100644 --- a/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr +++ b/tests/ui/sanitizer/cfi/minimal-runtime-requires-cfi.stderr @@ -1,6 +1,4 @@ error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer=cfi` -error: `-Zsanitizer-cfi-minimal-runtime` requires `-Zsanitizer-cfi-recover` or `-Zsanitizer-cfi-diag` - -error: aborting due to 2 previous errors +error: aborting due to 1 previous error From 976fcac712d75fc7d9d32e8278a77eae96a07f67 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 09:26:46 +0000 Subject: [PATCH 0735/1309] inline `discriminant_value` calls --- .../src/deriving/generic/mod.rs | 78 ++++++++----------- ...ring_eq.direct.runtime-optimized.after.mir | 8 +- ...ng_eq.with_let.runtime-optimized.after.mir | 8 +- tests/ui/derives/deriving-all-codegen.stdout | 76 ++++++++---------- tests/ui/stats/macro-stats.stderr | 2 +- 5 files changed, 70 insertions(+), 102 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b9888f2773699..6900eb00478ab 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -176,7 +176,7 @@ use std::iter::once; use std::ops::Not; -use std::{iter, vec}; +use std::vec; pub(crate) use Substructure::*; pub(crate) use rustc_ast as ast; @@ -1061,46 +1061,33 @@ impl<'a> MethodDef<'a> { let selflike_args = self.get_selflike_args(cx, trait_); - let prefixes = iter::once("__self".to_string()) - .chain((1..selflike_args.len()).map(|arg_count| format!("__arg{arg_count}"))) - .collect::>(); + let prefixes: &[&str] = match selflike_args.len() { + 1 => &["__self"], + 2 => &["__self", "__arg1"], + _ => unreachable!(), + }; - // Build a series of let statements mapping each selflike_arg - // to its discriminant value. + // Maps each selflike_arg to its discriminant value. // - // e.g. for `PartialEq::eq` builds two statements: + // e.g. for `PartialEq::eq` it builds: // ``` - // let __self_discr = ::core::intrinsics::discriminant_value(self); - // let __arg1_discr = ::core::intrinsics::discriminant_value(other); + // ::core::intrinsics::discriminant_value(self); // self_expr + // ::core::intrinsics::discriminant_value(other); // other_selflike_expr // ``` - let get_discr_pieces = || { - let discr_idents = prefixes - .iter() - .map(|name| Ident::from_str_and_span(&format!("{name}_discr"), span)); - - let mut discr_exprs = - discr_idents.clone().map(|ident| cx.expr_addr_of(span, cx.expr_ident(span, ident))); - + let get_discr_field_info = || { + let mut discr_exprs = selflike_args.iter().map(|selflike_arg| { + let call = deriving::call_intrinsic( + cx, + span, + sym::discriminant_value, + thin_vec![selflike_arg.clone()], + ); + cx.expr_addr_of(span, call) + }); let self_expr = discr_exprs.next().unwrap(); let other_selflike_expr = discr_exprs.next(); - debug_assert!(discr_exprs.next().is_none()); - - let discr_field = - FieldInfo { span, name: None, self_expr, other_selflike_expr, maybe_scalar: true }; - let discr_let_stmts: ThinVec<_> = iter::zip(discr_idents, &selflike_args) - .map(|(ident, selflike_arg)| { - let variant_value = deriving::call_intrinsic( - cx, - span, - sym::discriminant_value, - thin_vec![selflike_arg.clone()], - ); - cx.stmt_let(span, false, ident, variant_value) - }) - .collect(); - - (discr_field, discr_let_stmts) + FieldInfo { span, name: None, self_expr, other_selflike_expr, maybe_scalar: true } }; // There are some special cases involving fieldless enums where no @@ -1113,11 +1100,12 @@ impl<'a> MethodDef<'a> { // If the type is fieldless and the trait uses the discriminant and // there are multiple variants, we need just an operation on // the discriminant(s). - let (discr_field, mut discr_let_stmts) = get_discr_pieces(); - let mut discr_check = - self.call_substructure_method(cx, trait_, EnumDiscr(discr_field, None)); - discr_let_stmts.append(&mut discr_check.0); - return BlockOrExpr(discr_let_stmts, discr_check.1); + let discr_field = get_discr_field_info(); + return self.call_substructure_method( + cx, + trait_, + EnumDiscr(discr_field, None), + ); } FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => { return self.call_substructure_method( @@ -1226,16 +1214,14 @@ impl<'a> MethodDef<'a> { // to add a discriminant check operation before the match. Otherwise, the match // is enough. if unify_fieldless_variants && variants.len() > 1 { - let (discr_field, mut discr_let_stmts) = get_discr_pieces(); + let discr_field = get_discr_field_info(); // Combine a discriminant check with the match. - let mut discr_check_plus_match = self.call_substructure_method( + self.call_substructure_method( cx, trait_, EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), - ); - discr_let_stmts.append(&mut discr_check_plus_match.0); - BlockOrExpr(discr_let_stmts, discr_check_plus_match.1) + ) } else { BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args))) } @@ -1249,7 +1235,7 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, struct_path: ast::Path, struct_def: &'a VariantData, - prefixes: &[String], + prefixes: &[&str], ) -> ThinVec { prefixes .iter() @@ -1323,7 +1309,7 @@ impl<'a> TraitDef<'a> { &self, cx: &ExtCtxt<'_>, struct_def: &'a VariantData, - prefixes: &[String], + prefixes: &[&str], ) -> Vec { self.create_fields(struct_def, |i, _struct_field, sp| { prefixes diff --git a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir index b1bbceae330c7..f7faefcc1bf7b 100644 --- a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.direct.runtime-optimized.after.mir @@ -7,11 +7,7 @@ fn direct(_1: Option) -> bool { let mut _2: isize; scope 2 { scope 3 (inlined ::eq) { - let _3: i8; - scope 4 { - scope 5 { - } - } + let mut _3: i8; } } } @@ -30,7 +26,7 @@ fn direct(_1: Option) -> bool { bb2: { StorageLive(_3); _3 = discriminant(((_1 as Some).0: std::cmp::Ordering)); - _0 = Eq(copy _3, const 0_i8); + _0 = Eq(move _3, const 0_i8); StorageDead(_3); goto -> bb3; } diff --git a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir index 86ef69b9a4cd5..2f0233e353c2f 100644 --- a/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir +++ b/tests/mir-opt/pre-codegen/const_promotion_option_ordering_eq.with_let.runtime-optimized.after.mir @@ -9,11 +9,7 @@ fn with_let(_1: Option) -> bool { let mut _2: isize; scope 3 { scope 4 (inlined ::eq) { - let _3: i8; - scope 5 { - scope 6 { - } - } + let mut _3: i8; } } } @@ -33,7 +29,7 @@ fn with_let(_1: Option) -> bool { bb2: { StorageLive(_3); _3 = discriminant(((_1 as Some).0: std::cmp::Ordering)); - _0 = Eq(copy _3, const 0_i8); + _0 = Eq(move _3, const 0_i8); StorageDead(_3); goto -> bb3; } diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index 92d5030372518..c2cd34d89aee4 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -1176,8 +1176,8 @@ impl ::core::default::Default for Fieldless { impl ::core::hash::Hash for Fieldless { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state) + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state) } } #[automatically_derived] @@ -1186,9 +1186,8 @@ impl ::core::marker::StructuralPartialEq for Fieldless { } impl ::core::cmp::PartialEq for Fieldless { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) } } #[automatically_derived] @@ -1205,9 +1204,8 @@ impl ::core::cmp::PartialOrd for Fieldless { impl ::core::cmp::Ord for Fieldless { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr) + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)) } } @@ -1263,8 +1261,8 @@ impl ::core::default::Default for Mixed { impl ::core::hash::Hash for Mixed { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { Mixed::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), Mixed::S { d1: __self_0, d2: __self_1 } => { @@ -1281,9 +1279,8 @@ impl ::core::marker::StructuralPartialEq for Mixed { } impl ::core::cmp::PartialEq for Mixed { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { (Mixed::R(__self_0), Mixed::R(__arg1_0)) => __self_0 == __arg1_0, @@ -1317,8 +1314,6 @@ impl ::core::cmp::PartialOrd for Mixed { impl ::core::cmp::Ord for Mixed { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); match (self, other) { (Mixed::R(__self_0), Mixed::R(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), @@ -1329,7 +1324,9 @@ impl ::core::cmp::Ord for Mixed { ::core::cmp::Ord::cmp(__self_1, __arg1_1), cmp => cmp, }, - _ => ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr), + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1352,9 +1349,8 @@ impl ::core::marker::StructuralPartialEq for ReorderEnum { } impl ::core::cmp::PartialEq for ReorderEnum { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => __self_0 == __arg1_0, @@ -1373,10 +1369,8 @@ impl ::core::cmp::PartialOrd for ReorderEnum { #[inline] fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - match ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr) { + match ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => match (self, other) { (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => @@ -1443,8 +1437,8 @@ impl ::core::fmt::Debug for Fielded { impl ::core::hash::Hash for Fielded { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { Fielded::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), Fielded::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), @@ -1458,9 +1452,8 @@ impl ::core::marker::StructuralPartialEq for Fielded { } impl ::core::cmp::PartialEq for Fielded { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { (Fielded::X(__self_0), Fielded::X(__arg1_0)) => __self_0 == __arg1_0, @@ -1495,8 +1488,6 @@ impl ::core::cmp::PartialOrd for Fielded { impl ::core::cmp::Ord for Fielded { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); match (self, other) { (Fielded::X(__self_0), Fielded::X(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), @@ -1504,7 +1495,9 @@ impl ::core::cmp::Ord for Fielded { ::core::cmp::Ord::cmp(__self_0, __arg1_0), (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - _ => ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr), + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1548,8 +1541,8 @@ impl ::core::hash::Hash for EnumGeneric { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { - let __self_discr = ::core::intrinsics::discriminant_value(self); - ::core::hash::Hash::hash(&__self_discr, state); + ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), + state); match self { EnumGeneric::One(__self_0) => ::core::hash::Hash::hash(__self_0, state), @@ -1567,9 +1560,8 @@ impl ::core::cmp::PartialEq for EnumGeneric { #[inline] fn eq(&self, other: &Self) -> bool { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); - __self_discr == __arg1_discr && + ::core::intrinsics::discriminant_value(self) == + ::core::intrinsics::discriminant_value(other) && match (self, other) { (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => __self_0 == __arg1_0, @@ -1596,16 +1588,14 @@ impl #[inline] fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); match (self, other) { (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), _ => - ::core::cmp::PartialOrd::partial_cmp(&__self_discr, - &__arg1_discr), + ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } @@ -1614,14 +1604,14 @@ impl ::core::cmp::Ord for EnumGeneric { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { - let __self_discr = ::core::intrinsics::discriminant_value(self); - let __arg1_discr = ::core::intrinsics::discriminant_value(other); match (self, other) { (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - _ => ::core::cmp::Ord::cmp(&__self_discr, &__arg1_discr), + _ => + ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), + &::core::intrinsics::discriminant_value(other)), } } } diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index 95567e20db3bf..efc3785878c39 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -3,7 +3,7 @@ macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- macro-stats #[derive(Clone)] 8 67 8.4 1_909 238.6 -macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 +macro-stats #[derive(Hash)] 2 17 8.5 536 268.0 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 505 505.0 macro-stats #[derive(Default)] 2 16 8.0 409 204.5 From 921a20a428263db4cf492cab836c48c42fe54da4 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 10:17:26 +0000 Subject: [PATCH 0736/1309] small stuff --- .../src/deriving/generic/mod.rs | 23 ++++++++----------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 6900eb00478ab..51270222f0e3b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -294,7 +294,7 @@ pub(crate) enum Substructure<'a> { /// variants has any fields). AllFieldlessEnum(&'a ast::EnumDef), - /// Matching variants of the enum: variant index, ast::Variant, + /// Matching variants of the enum: ast::Variant, /// fields: the field name is only non-`None` in the case of a struct /// variant. EnumMatching(&'a ast::Variant, Vec), @@ -587,7 +587,6 @@ impl<'a> TraitDef<'a> { let mut where_clause = ast::WhereClause::default(); where_clause.span = generics.where_clause.span; let ctxt = self.span.ctxt(); - let span = generics.span.with_ctxt(ctxt); // Create the generic parameters let params: ThinVec<_> = generics @@ -716,7 +715,7 @@ impl<'a> TraitDef<'a> { } } - let trait_generics = Generics { params, where_clause, span }; + let trait_generics = Generics { params, where_clause, span: generics.span.with_ctxt(ctxt) }; // Create the reference to the trait. let trait_ref = cx.trait_ref(self.path.clone()); @@ -741,8 +740,6 @@ impl<'a> TraitDef<'a> { let path = cx.path_all(type_ident.span.with_ctxt(ctxt), false, vec![type_ident], self_params); let self_type = cx.ty_path(path); - let rustc_const_unstable = - cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); let mut attrs = thin_vec![cx.attr_word(sym::automatically_derived, self.span),]; @@ -750,6 +747,9 @@ impl<'a> TraitDef<'a> { // Other crates don't need stability attributes, so adding them is not useful, but libcore needs them // on all const trait impls. if self.is_const && cx.ecfg.features.staged_api() { + let rustc_const_unstable = + cx.path_ident(self.span, Ident::new(sym::rustc_const_unstable, self.span)); + // #[rustc_const_unstable(feature = "derive_const", issue = "118304")] attrs.push( cx.attr_nested( @@ -1173,9 +1173,7 @@ impl<'a> MethodDef<'a> { let first_fieldless = variants.iter().find(|v| v.data.fields().is_empty()); let default = match first_fieldless { Some(v) if unify_fieldless_variants => { - // We need a default case that handles all the fieldless - // variants. The index and actual variant aren't meaningful in - // this case, so just use dummy values. + // We need a default case that handles all the fieldless variants. Some( self.call_substructure_method(cx, trait_, EnumMatching(v, Vec::new())) .into_expr(cx, span), @@ -1183,7 +1181,7 @@ impl<'a> MethodDef<'a> { } _ if variants.len() > 1 && selflike_args.len() > 1 => { // Because we know that all the arguments will match if we reach - // the match expression we add the unreachable intrinsics as the + // the match expression we add the unreachable intrinsic as the // result of the default which should help llvm in optimizing it. Some(deriving::call_unreachable(cx, span)) } @@ -1205,7 +1203,7 @@ impl<'a> MethodDef<'a> { let match_arg = if selflike_args.len() == 1 { selflike_args.pop().unwrap() } else { - cx.expr(span, ast::ExprKind::Tup(selflike_args)) + cx.expr_tuple(span, selflike_args) }; cx.expr_match(span, match_arg, match_arms) }; @@ -1242,9 +1240,8 @@ impl<'a> TraitDef<'a> { .map(|prefix| { let pieces_iter = struct_def.fields().iter().enumerate().map(|(i, struct_field)| { - let sp = struct_field.span.with_ctxt(self.span.ctxt()); let ident = self.mk_pattern_ident(prefix, i); - let path = ident.with_span_pos(sp); + let path = ident.with_span_pos(struct_field.span); (struct_field.ident, cx.pat_ident(path.span, path)) }); @@ -1277,7 +1274,7 @@ impl<'a> TraitDef<'a> { fn create_fields(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec where - F: Fn(usize, &ast::FieldDef, Span) -> Vec>, + F: Fn(usize, &ast::FieldDef, Span) -> Vec>, { struct_def .fields() From 42bc8afbffe5600113b77988cff6df84237aa0c2 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 10:57:36 +0000 Subject: [PATCH 0737/1309] move helper methods away from `TraitDef` --- .../src/deriving/generic/mod.rs | 295 +++++++++--------- 1 file changed, 140 insertions(+), 155 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 51270222f0e3b..a2d33a07222dd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -812,16 +812,17 @@ impl<'a> TraitDef<'a> { from_scratch: bool, is_packed: bool, ) -> Box { + let span = self.span; let field_tys = struct_def.fields().iter().map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, StaticStruct(struct_def)) + method_def.call_substructure_method(cx, span, StaticStruct(struct_def)) } else { - method_def.expand_struct_method_body(cx, self, struct_def, is_packed) + method_def.expand_struct_method_body(cx, span, struct_def, is_packed) }; - method_def.create_method(cx, self, body) + method_def.create_method(cx, span, body) }); self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) @@ -843,12 +844,12 @@ impl<'a> TraitDef<'a> { let methods = self.methods.iter().filter_map(|method_def| { let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, StaticEnum(enum_def)) + method_def.call_substructure_method(cx, self.span, StaticEnum(enum_def)) } else { - method_def.expand_enum_method_body(cx, self, enum_def, type_ident) + method_def.expand_enum_method_body(cx, self.span, enum_def, type_ident) }; - method_def.create_method(cx, self, body) + method_def.create_method(cx, self.span, body) }); let is_packed = false; // enums are never packed @@ -860,10 +861,10 @@ impl<'a> MethodDef<'a> { fn call_substructure_method( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, + span: Span, substructure: Substructure<'_>, ) -> BlockOrExpr { - (self.combine_substructure)(cx, trait_.span, substructure) + (self.combine_substructure)(cx, span, substructure) } fn is_static(&self) -> bool { @@ -872,11 +873,9 @@ impl<'a> MethodDef<'a> { /// Expressions for `&self` and also any other /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). - fn get_selflike_args(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ThinVec> { + fn get_selflike_args(&self, cx: &ExtCtxt<'_>, span: Span) -> ThinVec> { assert!(self.explicit_self); - let span = trait_.span; - once(cx.expr_self(span)) .chain(self.nonself_args.iter().filter_map(|(ty, name)| match ty { Ref(Self_, _) => Some(cx.expr_ident(span, Ident::new(*name, span))), @@ -888,14 +887,13 @@ impl<'a> MethodDef<'a> { fn create_method( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'_>, + span: Span, body: BlockOrExpr, ) -> Option> { // `assert_fields_are_eq` has an empty default implementation if body.0.is_empty() && body.1.is_none() && self.name == sym::assert_fields_are_eq { return None; } - let span = trait_.span; // Create the generics that aren't for `Self`. let fn_generics = self.generics.clone(); @@ -989,15 +987,15 @@ impl<'a> MethodDef<'a> { fn expand_struct_method_body<'b>( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'b>, + span: Span, struct_def: &'b VariantData, is_packed: bool, ) -> BlockOrExpr { - let selflike_args = self.get_selflike_args(cx, trait_); + let selflike_args = self.get_selflike_args(cx, span); let selflike_fields = - trait_.create_struct_field_access_fields(cx, &selflike_args, struct_def, is_packed); - self.call_substructure_method(cx, trait_, Struct(struct_def, selflike_fields)) + create_struct_field_access_fields(span, cx, &selflike_args, struct_def, is_packed); + self.call_substructure_method(cx, span, Struct(struct_def, selflike_fields)) } /// ``` @@ -1038,11 +1036,10 @@ impl<'a> MethodDef<'a> { fn expand_enum_method_body<'b>( &self, cx: &ExtCtxt<'_>, - trait_: &TraitDef<'b>, + span: Span, enum_def: &'b EnumDef, type_ident: Ident, ) -> BlockOrExpr { - let span = trait_.span; let variants = &enum_def.variants; // Traits that unify fieldless variants always use the discriminant(s). @@ -1059,7 +1056,7 @@ impl<'a> MethodDef<'a> { return BlockOrExpr(ThinVec::new(), Some(expr)); } - let selflike_args = self.get_selflike_args(cx, trait_); + let selflike_args = self.get_selflike_args(cx, span); let prefixes: &[&str] = match selflike_args.len() { 1 => &["__self"], @@ -1103,27 +1100,19 @@ impl<'a> MethodDef<'a> { let discr_field = get_discr_field_info(); return self.call_substructure_method( cx, - trait_, + span, EnumDiscr(discr_field, None), ); } FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => { - return self.call_substructure_method( - cx, - trait_, - AllFieldlessEnum(enum_def), - ); + return self.call_substructure_method(cx, span, AllFieldlessEnum(enum_def)); } FieldlessVariantsStrategy::Default => (), } } else if let [variant] = variants.as_slice() { // If there is a single variant, we don't need an operation on // the discriminant(s). Just use the most degenerate result. - return self.call_substructure_method( - cx, - trait_, - EnumMatching(variant, Vec::new()), - ); + return self.call_substructure_method(cx, span, EnumMatching(variant, Vec::new())); } } @@ -1139,12 +1128,12 @@ impl<'a> MethodDef<'a> { // A single arm has form (&VariantK, &VariantK, ...) => BodyK // (see "Final wrinkle" note below for why.) - let fields = trait_.create_struct_pattern_fields(cx, &variant.data, &prefixes); + let fields = create_struct_pattern_fields(span, cx, &variant.data, &prefixes); - let sp = variant.span.with_ctxt(trait_.span.ctxt()); + let sp = variant.span.with_ctxt(span.ctxt()); let variant_path = cx.path(sp, vec![type_ident, variant.ident]); let mut subpats = - trait_.create_struct_patterns(cx, variant_path, &variant.data, &prefixes); + create_struct_patterns(span, cx, variant_path, &variant.data, &prefixes); // `(VariantK, VariantK, ...)` or just `VariantK`. let single_pat = if subpats.len() == 1 { @@ -1163,7 +1152,7 @@ impl<'a> MethodDef<'a> { // Build up code associated with such a case. let substructure = EnumMatching(variant, fields); let arm_expr = - self.call_substructure_method(cx, trait_, substructure).into_expr(cx, span); + self.call_substructure_method(cx, span, substructure).into_expr(cx, span); cx.arm(span, single_pat, arm_expr) }) @@ -1175,7 +1164,7 @@ impl<'a> MethodDef<'a> { Some(v) if unify_fieldless_variants => { // We need a default case that handles all the fieldless variants. Some( - self.call_substructure_method(cx, trait_, EnumMatching(v, Vec::new())) + self.call_substructure_method(cx, span, EnumMatching(v, Vec::new())) .into_expr(cx, span), ) } @@ -1217,7 +1206,7 @@ impl<'a> MethodDef<'a> { // Combine a discriminant check with the match. self.call_substructure_method( cx, - trait_, + span, EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), ) } else { @@ -1227,132 +1216,128 @@ impl<'a> MethodDef<'a> { } // general helper methods. -impl<'a> TraitDef<'a> { - fn create_struct_patterns( - &self, - cx: &ExtCtxt<'_>, - struct_path: ast::Path, - struct_def: &'a VariantData, - prefixes: &[&str], - ) -> ThinVec { +fn create_struct_patterns( + span: Span, + cx: &ExtCtxt<'_>, + struct_path: ast::Path, + struct_def: &VariantData, + prefixes: &[&str], +) -> ThinVec { + prefixes + .iter() + .map(|prefix| { + let pieces_iter = struct_def.fields().iter().enumerate().map(|(i, struct_field)| { + let ident = mk_pattern_ident(span, prefix, i); + let path = ident.with_span_pos(struct_field.span); + (struct_field.ident, cx.pat_ident(path.span, path)) + }); + + let struct_path = struct_path.clone(); + match *struct_def { + VariantData::Struct { .. } => { + let field_pats = pieces_iter + .map(|(ident, pat)| ast::PatField { + ident: ident.expect("a braced struct with unnamed fields in `derive`"), + is_shorthand: false, + attrs: ast::AttrVec::new(), + id: ast::DUMMY_NODE_ID, + span: pat.span.with_ctxt(span.ctxt()), + pat: Box::new(pat), + is_placeholder: false, + }) + .collect(); + cx.pat_struct(span, struct_path, field_pats) + } + VariantData::Tuple(..) => { + let subpats = pieces_iter.map(|(_, subpat)| subpat).collect(); + cx.pat_tuple_struct(span, struct_path, subpats) + } + VariantData::Unit(..) => cx.pat_path(span, struct_path), + } + }) + .collect() +} + +fn create_fields(span: Span, struct_def: &VariantData, mk_exprs: F) -> Vec +where + F: Fn(usize, &ast::FieldDef, Span) -> Vec>, +{ + struct_def + .fields() + .iter() + .enumerate() + .map(|(i, struct_field)| { + // For this field, get an expr for each selflike_arg. E.g. for + // `PartialEq::eq`, one for each of `&self` and `other`. + let span = struct_field.span.with_ctxt(span.ctxt()); + let mut exprs: Vec<_> = mk_exprs(i, struct_field, span); + let self_expr = exprs.remove(0); + debug_assert!(exprs.len() <= 1); + FieldInfo { + span, + name: struct_field.ident, + self_expr, + other_selflike_expr: exprs.pop(), + maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(), + } + }) + .collect() +} + +fn mk_pattern_ident(span: Span, prefix: &str, i: usize) -> Ident { + Ident::from_str_and_span(&format!("{prefix}_{i}"), span) +} + +fn create_struct_pattern_fields( + span: Span, + cx: &ExtCtxt<'_>, + struct_def: &VariantData, + prefixes: &[&str], +) -> Vec { + create_fields(span, struct_def, |i, _struct_field, sp| { prefixes .iter() .map(|prefix| { - let pieces_iter = - struct_def.fields().iter().enumerate().map(|(i, struct_field)| { - let ident = self.mk_pattern_ident(prefix, i); - let path = ident.with_span_pos(struct_field.span); - (struct_field.ident, cx.pat_ident(path.span, path)) - }); - - let struct_path = struct_path.clone(); - match *struct_def { - VariantData::Struct { .. } => { - let field_pats = pieces_iter - .map(|(ident, pat)| ast::PatField { - ident: ident - .expect("a braced struct with unnamed fields in `derive`"), - is_shorthand: false, - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - span: pat.span.with_ctxt(self.span.ctxt()), - pat: Box::new(pat), - is_placeholder: false, - }) - .collect(); - cx.pat_struct(self.span, struct_path, field_pats) - } - VariantData::Tuple(..) => { - let subpats = pieces_iter.map(|(_, subpat)| subpat).collect(); - cx.pat_tuple_struct(self.span, struct_path, subpats) - } - VariantData::Unit(..) => cx.pat_path(self.span, struct_path), - } + let ident = mk_pattern_ident(span, prefix, i); + cx.expr_path(cx.path_ident(sp, ident)) }) .collect() - } + }) +} - fn create_fields(&self, struct_def: &'a VariantData, mk_exprs: F) -> Vec - where - F: Fn(usize, &ast::FieldDef, Span) -> Vec>, - { - struct_def - .fields() +fn create_struct_field_access_fields( + span: Span, + cx: &ExtCtxt<'_>, + selflike_args: &[Box], + struct_def: &VariantData, + is_packed: bool, +) -> Vec { + create_fields(span, struct_def, |i, struct_field, sp| { + selflike_args .iter() - .enumerate() - .map(|(i, struct_field)| { - // For this field, get an expr for each selflike_arg. E.g. for - // `PartialEq::eq`, one for each of `&self` and `other`. - let span = struct_field.span.with_ctxt(self.span.ctxt()); - let mut exprs: Vec<_> = mk_exprs(i, struct_field, span); - let self_expr = exprs.remove(0); - debug_assert!(exprs.len() <= 1); - FieldInfo { - span, - name: struct_field.ident, - self_expr, - other_selflike_expr: exprs.pop(), - maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(), + .map(|selflike_arg| { + // Note: we must use `struct_field.span` rather than `sp` in the + // `unwrap_or_else` case otherwise the hygiene is wrong and we get + // "field `0` of struct `Point` is private" errors on tuple + // structs. + let mut field_expr = cx.expr( + sp, + ast::ExprKind::Field( + selflike_arg.clone(), + struct_field.ident.unwrap_or_else(|| { + Ident::from_str_and_span(&i.to_string(), struct_field.span) + }), + ), + ); + if is_packed { + // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`, + // causing a copy instead of a (potentially misaligned) reference. + field_expr = cx.expr_block( + cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]), + ); } + cx.expr_addr_of(sp, field_expr) }) .collect() - } - - fn mk_pattern_ident(&self, prefix: &str, i: usize) -> Ident { - Ident::from_str_and_span(&format!("{prefix}_{i}"), self.span) - } - - fn create_struct_pattern_fields( - &self, - cx: &ExtCtxt<'_>, - struct_def: &'a VariantData, - prefixes: &[&str], - ) -> Vec { - self.create_fields(struct_def, |i, _struct_field, sp| { - prefixes - .iter() - .map(|prefix| { - let ident = self.mk_pattern_ident(prefix, i); - cx.expr_path(cx.path_ident(sp, ident)) - }) - .collect() - }) - } - - fn create_struct_field_access_fields( - &self, - cx: &ExtCtxt<'_>, - selflike_args: &[Box], - struct_def: &'a VariantData, - is_packed: bool, - ) -> Vec { - self.create_fields(struct_def, |i, struct_field, sp| { - selflike_args - .iter() - .map(|selflike_arg| { - // Note: we must use `struct_field.span` rather than `sp` in the - // `unwrap_or_else` case otherwise the hygiene is wrong and we get - // "field `0` of struct `Point` is private" errors on tuple - // structs. - let mut field_expr = cx.expr( - sp, - ast::ExprKind::Field( - selflike_arg.clone(), - struct_field.ident.unwrap_or_else(|| { - Ident::from_str_and_span(&i.to_string(), struct_field.span) - }), - ), - ); - if is_packed { - // Fields in packed structs are wrapped in a block, e.g. `&{self.0}`, - // causing a copy instead of a (potentially misaligned) reference. - field_expr = cx.expr_block( - cx.block(struct_field.span, thin_vec![cx.stmt_expr(field_expr)]), - ); - } - cx.expr_addr_of(sp, field_expr) - }) - .collect() - }) - } + }) } From b5c30bea730f1e84e24a8d71e0a306116e38495c Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 19:09:38 +0000 Subject: [PATCH 0738/1309] inline `expand_struct/enum_def` --- .../src/deriving/generic/mod.rs | 106 ++++++------------ 1 file changed, 32 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index a2d33a07222dd..6f89752eef0d9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -462,14 +462,30 @@ impl<'a> TraitDef<'a> { push: &mut dyn FnMut(Box), from_scratch: bool, ) { + let span = self.span; let is_packed = matches!( AttributeParser::parse_limited_sym(cx.sess, &item.attrs, &[sym::repr]), Some(Attribute::Parsed(AttributeKind::Repr { reprs, .. })) if reprs.iter().any(|(x, _)| matches!(x, ReprPacked(..))) ); let mut newitem = match &item.kind { - ast::ItemKind::Struct(ident, generics, struct_def) => { - self.expand_struct_def(cx, struct_def, *ident, generics, from_scratch, is_packed) + ast::ItemKind::Union(..) if !self.supports_unions => { + cx.dcx().emit_err(diagnostics::DeriveUnion { span }); + return; + } + ast::ItemKind::Struct(ident, generics, struct_def) + | ast::ItemKind::Union(ident, generics, struct_def) => { + let fields = struct_def.fields().iter(); + let methods = self.methods.iter().filter_map(|method_def| { + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method(cx, span, StaticStruct(struct_def)) + } else { + method_def.expand_struct_method_body(cx, span, struct_def, is_packed) + }; + + method_def.create_method(cx, span, body) + }); + self.create_derived_impl(cx, *ident, generics, fields, methods, is_packed) } ast::ItemKind::Enum(ident, generics, enum_def) => { // We can skip generating the impl here, because `repr(packed)` @@ -479,22 +495,17 @@ impl<'a> TraitDef<'a> { if is_packed { return; } - self.expand_enum_def(cx, enum_def, *ident, generics, from_scratch) - } - ast::ItemKind::Union(ident, generics, struct_def) => { - if self.supports_unions { - self.expand_struct_def( - cx, - struct_def, - *ident, - generics, - from_scratch, - is_packed, - ) - } else { - cx.dcx().emit_err(diagnostics::DeriveUnion { span: self.span }); - return; - } + let fields = enum_def.variants.iter().flat_map(|variant| variant.data.fields()); + let methods = self.methods.iter().filter_map(|method_def| { + let body = if from_scratch || method_def.is_static() { + method_def.call_substructure_method(cx, span, StaticEnum(enum_def)) + } else { + method_def.expand_enum_method_body(cx, span, enum_def, *ident) + }; + + method_def.create_method(cx, span, body) + }); + self.create_derived_impl(cx, *ident, generics, fields, methods, is_packed) } _ => unreachable!(), }; @@ -558,7 +569,7 @@ impl<'a> TraitDef<'a> { cx: &ExtCtxt<'_>, type_ident: Ident, generics: &Generics, - field_tys: impl Iterator, + fields: impl Iterator, methods: impl Iterator>, is_packed: bool, ) -> Box { @@ -666,8 +677,8 @@ impl<'a> TraitDef<'a> { .collect(); if !ty_param_names.is_empty() { - for field_ty in field_tys { - let field_ty_params = find_type_parameters(field_ty, &ty_param_names, cx); + for field in fields { + let field_ty_params = find_type_parameters(&field.ty, &ty_param_names, cx); for field_ty_param in field_ty_params { // if we have already handled this type, skip it @@ -802,59 +813,6 @@ impl<'a> TraitDef<'a> { }), ) } - - fn expand_struct_def( - &self, - cx: &ExtCtxt<'_>, - struct_def: &'a VariantData, - type_ident: Ident, - generics: &Generics, - from_scratch: bool, - is_packed: bool, - ) -> Box { - let span = self.span; - let field_tys = struct_def.fields().iter().map(|field| &*field.ty); - - let methods = self.methods.iter().filter_map(|method_def| { - let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, span, StaticStruct(struct_def)) - } else { - method_def.expand_struct_method_body(cx, span, struct_def, is_packed) - }; - - method_def.create_method(cx, span, body) - }); - - self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) - } - - fn expand_enum_def( - &self, - cx: &ExtCtxt<'_>, - enum_def: &'a EnumDef, - type_ident: Ident, - generics: &Generics, - from_scratch: bool, - ) -> Box { - let field_tys = enum_def - .variants - .iter() - .flat_map(|variant| variant.data.fields()) - .map(|field| &*field.ty); - - let methods = self.methods.iter().filter_map(|method_def| { - let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self.span, StaticEnum(enum_def)) - } else { - method_def.expand_enum_method_body(cx, self.span, enum_def, type_ident) - }; - - method_def.create_method(cx, self.span, body) - }); - - let is_packed = false; // enums are never packed - self.create_derived_impl(cx, type_ident, generics, field_tys, methods, is_packed) - } } impl<'a> MethodDef<'a> { From d736fe1c6f86457af68f29f631653a2764340554 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 19:32:48 +0000 Subject: [PATCH 0739/1309] remove unused, untested `associated_types` --- .../src/deriving/clone.rs | 2 -- .../src/deriving/const_param_ty.rs | 1 - .../rustc_builtin_macros/src/deriving/copy.rs | 1 - .../src/deriving/debug.rs | 1 - .../src/deriving/default.rs | 1 - .../rustc_builtin_macros/src/deriving/eq.rs | 1 - .../rustc_builtin_macros/src/deriving/from.rs | 1 - .../src/deriving/generic/mod.rs | 26 +------------------ .../rustc_builtin_macros/src/deriving/hash.rs | 1 - .../rustc_builtin_macros/src/deriving/ord.rs | 1 - .../src/deriving/partial_eq.rs | 2 -- .../src/deriving/partial_ord.rs | 1 - 12 files changed, 1 insertion(+), 38 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 7cce8a2a46269..95ad579f015fb 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -68,7 +68,6 @@ pub(crate) fn expand_deriving_clone( additional_bounds: bounds.clone(), supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Unsafe(DUMMY_SP), // `TrivialClone` is not part of an API guarantee, so it shouldn't @@ -96,7 +95,6 @@ pub(crate) fn expand_deriving_clone( fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: substructure, }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs index 69041a60027d3..c693cbb66fee9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -20,7 +20,6 @@ pub(crate) fn expand_deriving_const_param_ty( additional_bounds: smallvec![path_std!(cx, span, cmp::Eq)], supports_unions: false, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/copy.rs b/compiler/rustc_builtin_macros/src/deriving/copy.rs index 5badeb7e1877e..4ce8598e96711 100644 --- a/compiler/rustc_builtin_macros/src/deriving/copy.rs +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -20,7 +20,6 @@ pub(crate) fn expand_deriving_copy( additional_bounds: SmallVec::new(), supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 66e9b3ed82bcc..45e3dd2d0f760 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -41,7 +41,6 @@ pub(crate) fn expand_deriving_debug( item.kind.ident().unwrap() )), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 866ffc74da436..92d15efa05a95 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -49,7 +49,6 @@ pub(crate) fn expand_deriving_default( } }), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index 1083b37cbf248..bcf2e310596f4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -40,7 +40,6 @@ pub(crate) fn expand_deriving_eq( fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(cs_total_eq_assert), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 64cc917302935..5980e43298fff 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -115,7 +115,6 @@ pub(crate) fn expand_deriving_from( BlockOrExpr::new_expr(expr) }), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 6f89752eef0d9..e600a0982157c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -220,8 +220,6 @@ pub(crate) struct TraitDef<'a> { pub methods: SmallVec<[MethodDef<'a>; 1]>, - pub associated_types: SmallVec<[(Ident, Ty); 1]>, - pub is_const: bool, /// The safety of the `impl`. @@ -573,28 +571,6 @@ impl<'a> TraitDef<'a> { methods: impl Iterator>, is_packed: bool, ) -> Box { - // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem` - let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { - Box::new(ast::AssocItem { - id: ast::DUMMY_NODE_ID, - span: self.span, - vis: ast::Visibility { - span: self.span.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, - }, - attrs: ast::AttrVec::new(), - kind: ast::AssocItemKind::Type(Box::new(ast::TyAlias { - defaultness: ast::Defaultness::Implicit, - ident, - generics: Generics::default(), - after_where_clause: ast::WhereClause::default(), - bounds: ThinVec::new(), - ty: Some(type_def.to_ty(cx, self.span)), - })), - tokens: None, - }) - }); - let mut where_clause = ast::WhereClause::default(); where_clause.span = generics.where_clause.span; let ctxt = self.span.ctxt(); @@ -809,7 +785,7 @@ impl<'a> TraitDef<'a> { })), constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, self_ty: self_type, - items: methods.chain(associated_types).collect(), + items: methods.collect(), }), ) } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 55c1d338c5d2d..158bb77ef30fa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -48,7 +48,6 @@ pub(crate) fn expand_deriving_hash( fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(hash_substructure), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 8851dd994a542..a2527d3d6f36d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -39,7 +39,6 @@ pub(crate) fn expand_deriving_ord( discr_then_data )), }], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 5c8a6225fa91b..ccad49c1897c3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -29,7 +29,6 @@ pub(crate) fn expand_deriving_partial_eq( // a second check here would lead to redundant error messages. supports_unions: true, methods: SmallVec::new(), - associated_types: SmallVec::new(), is_const: false, safety: Safety::Default, document: true, @@ -57,7 +56,6 @@ pub(crate) fn expand_deriving_partial_eq( additional_bounds: SmallVec::new(), supports_unions: false, methods, - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 35e93b254565f..18e5e55c2d036 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -69,7 +69,6 @@ pub(crate) fn expand_deriving_partial_ord( additional_bounds: smallvec![], supports_unions: false, methods: smallvec![partial_cmp_def], - associated_types: SmallVec::new(), is_const, safety: Safety::Default, document: true, From 327639df5e32f0e33d40ff25e578aea74307ebe7 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 21 Sep 2026 21:23:09 +0000 Subject: [PATCH 0740/1309] use `Self` instead of `type_ident` once more --- .../src/deriving/generic/mod.rs | 6 +- tests/ui/associated-types/issue-38821.rs | 4 +- tests/ui/associated-types/issue-38821.stderr | 32 +++--- tests/ui/derives/deriving-all-codegen.stdout | 106 +++++++++--------- 4 files changed, 75 insertions(+), 73 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index e600a0982157c..64149f96aaf48 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -498,7 +498,7 @@ impl<'a> TraitDef<'a> { let body = if from_scratch || method_def.is_static() { method_def.call_substructure_method(cx, span, StaticEnum(enum_def)) } else { - method_def.expand_enum_method_body(cx, span, enum_def, *ident) + method_def.expand_enum_method_body(cx, span, enum_def) }; method_def.create_method(cx, span, body) @@ -972,7 +972,6 @@ impl<'a> MethodDef<'a> { cx: &ExtCtxt<'_>, span: Span, enum_def: &'b EnumDef, - type_ident: Ident, ) -> BlockOrExpr { let variants = &enum_def.variants; @@ -1065,7 +1064,8 @@ impl<'a> MethodDef<'a> { let fields = create_struct_pattern_fields(span, cx, &variant.data, &prefixes); let sp = variant.span.with_ctxt(span.ctxt()); - let variant_path = cx.path(sp, vec![type_ident, variant.ident]); + let variant_path = + cx.path(sp, vec![Ident::new(kw::SelfUpper, span), variant.ident]); let mut subpats = create_struct_patterns(span, cx, variant_path, &variant.data, &prefixes); diff --git a/tests/ui/associated-types/issue-38821.rs b/tests/ui/associated-types/issue-38821.rs index 35c371235e640..227599204cc1f 100644 --- a/tests/ui/associated-types/issue-38821.rs +++ b/tests/ui/associated-types/issue-38821.rs @@ -32,8 +32,6 @@ pub trait Column: Expression {} //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied -//~| ERROR the trait bound `::SqlType: NotNull` is not satisfied pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied @@ -44,6 +42,8 @@ pub enum ColumnInsertValue where //~^ ERROR the trait bound `::SqlType: IntoNullable` is not satisfied { Expression(Col, Expr), + //~^ ERROR the trait bound `::SqlType: NotNull` is not satisfied + //~| ERROR the trait bound `::SqlType: NotNull` is not satisfied Default(Col), } diff --git a/tests/ui/associated-types/issue-38821.stderr b/tests/ui/associated-types/issue-38821.stderr index 050054ad704bc..ad59184366ae1 100644 --- a/tests/ui/associated-types/issue-38821.stderr +++ b/tests/ui/associated-types/issue-38821.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:1 + --> $DIR/issue-38821.rs:35:1 | LL | pub enum ColumnInsertValue where | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -17,7 +17,7 @@ LL | Expr: Expression::Nullable>, ::SqlType: IntoNullable` is not satisfied - --> $DIR/issue-38821.rs:43:22 + --> $DIR/issue-38821.rs:41:22 | LL | Expr: Expression::Nullable>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` @@ -82,7 +82,7 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -98,7 +98,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Debug` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -132,7 +132,7 @@ LL | Expr: Expression::Nullable>, ::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ---- in this derive macro expansion @@ -148,7 +148,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Copy` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ---- in this derive macro expansion @@ -211,7 +211,7 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -227,7 +227,7 @@ LL | impl IntoNullable for T { | | | unsatisfied trait bound introduced here note: required for `ColumnInsertValue` to implement `Clone` - --> $DIR/issue-38821.rs:37:10 + --> $DIR/issue-38821.rs:35:10 | LL | #[derive(Debug, Copy, Clone)] | ----- in this derive macro expansion @@ -303,10 +303,13 @@ LL | impl IntoNullable for T { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:10 + --> $DIR/issue-38821.rs:44:5 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | Expression(Col, Expr), + | ^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -315,13 +318,15 @@ LL | impl IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `::SqlType: NotNull` is not satisfied - --> $DIR/issue-38821.rs:23:23 + --> $DIR/issue-38821.rs:44:5 | LL | #[derive(Debug, Copy, Clone)] - | ^^^^^ the trait `NotNull` is not implemented for `::SqlType` + | ----- in this derive macro expansion +... +LL | Expression(Col, Expr), + | ^^^^^^^^^^^^^^^^^^^^^ the trait `NotNull` is not implemented for `::SqlType` | note: required for `::SqlType` to implement `IntoNullable` --> $DIR/issue-38821.rs:9:18 @@ -330,7 +335,6 @@ LL | impl IntoNullable for T { | ------- ^^^^^^^^^^^^ ^ | | | unsatisfied trait bound introduced here - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 18 previous errors diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index c2cd34d89aee4..05412aca82360 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -1018,7 +1018,7 @@ impl ::core::clone::Clone for Enum1 { #[inline] fn clone(&self) -> Self { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => Self::Single { x: ::core::clone::Clone::clone(__self_0) }, } } @@ -1028,7 +1028,7 @@ impl ::core::fmt::Debug for Enum1 { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => ::core::fmt::Formatter::debug_struct_field1_finish(f, "Single", "x", &__self_0), } @@ -1039,7 +1039,7 @@ impl ::core::hash::Hash for Enum1 { #[inline] fn hash<__H: ::core::hash::Hasher>(&self, state: &mut __H) { match self { - Enum1::Single { x: __self_0 } => + Self::Single { x: __self_0 } => ::core::hash::Hash::hash(__self_0, state), } } @@ -1051,7 +1051,7 @@ impl ::core::cmp::PartialEq for Enum1 { #[inline] fn eq(&self, other: &Self) -> bool { match (self, other) { - (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + (Self::Single { x: __self_0 }, Self::Single { x: __arg1_0 }) => __self_0 == __arg1_0, } } @@ -1078,7 +1078,7 @@ impl ::core::cmp::Ord for Enum1 { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { - (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) => + (Self::Single { x: __self_0 }, Self::Single { x: __arg1_0 }) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), } } @@ -1241,12 +1241,12 @@ impl ::core::fmt::Debug for Mixed { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Mixed::P => ::core::fmt::Formatter::write_str(f, "P"), - Mixed::Q => ::core::fmt::Formatter::write_str(f, "Q"), - Mixed::R(__self_0) => + Self::P => ::core::fmt::Formatter::write_str(f, "P"), + Self::Q => ::core::fmt::Formatter::write_str(f, "Q"), + Self::R(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "R", &__self_0), - Mixed::S { d1: __self_0, d2: __self_1 } => + Self::S { d1: __self_0, d2: __self_1 } => ::core::fmt::Formatter::debug_struct_field2_finish(f, "S", "d1", __self_0, "d2", &__self_1), } @@ -1264,8 +1264,8 @@ impl ::core::hash::Hash for Mixed { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); match self { - Mixed::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Mixed::S { d1: __self_0, d2: __self_1 } => { + Self::R(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::S { d1: __self_0, d2: __self_1 } => { ::core::hash::Hash::hash(__self_0, state); ::core::hash::Hash::hash(__self_1, state) } @@ -1282,9 +1282,9 @@ impl ::core::cmp::PartialEq for Mixed { ::core::intrinsics::discriminant_value(self) == ::core::intrinsics::discriminant_value(other) && match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + (Self::R(__self_0), Self::R(__arg1_0)) => __self_0 == __arg1_0, - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + (Self::S { d1: __self_0, d2: __self_1 }, Self::S { d1: __arg1_0, d2: __arg1_1 }) => __self_0 == __arg1_0 && __self_1 == __arg1_1, _ => true, @@ -1315,9 +1315,9 @@ impl ::core::cmp::Ord for Mixed { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { - (Mixed::R(__self_0), Mixed::R(__arg1_0)) => + (Self::R(__self_0), Self::R(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S { + (Self::S { d1: __self_0, d2: __self_1 }, Self::S { d1: __arg1_0, d2: __arg1_1 }) => match ::core::cmp::Ord::cmp(__self_0, __arg1_0) { ::core::cmp::Ordering::Equal => @@ -1352,12 +1352,12 @@ impl ::core::cmp::PartialEq for ReorderEnum { ::core::intrinsics::discriminant_value(self) == ::core::intrinsics::discriminant_value(other) && match (self, other) { - (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => + (Self::A(__self_0), Self::A(__arg1_0)) => __self_0 == __arg1_0, - (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) => + (Self::C(__self_0), Self::C(__arg1_0)) => __self_0 == __arg1_0, - (ReorderEnum::G(__self_0, __self_1, __self_2), - ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) => + (Self::G(__self_0, __self_1, __self_2), + Self::G(__arg1_0, __arg1_1, __arg1_2)) => __self_1 == __arg1_1 && __self_0 == __arg1_0 && __self_2 == __arg1_2, _ => true, @@ -1373,12 +1373,12 @@ impl ::core::cmp::PartialOrd for ReorderEnum { &::core::intrinsics::discriminant_value(other)) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) => match (self, other) { - (ReorderEnum::A(__self_0), ReorderEnum::A(__arg1_0)) => + (Self::A(__self_0), Self::A(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (ReorderEnum::C(__self_0), ReorderEnum::C(__arg1_0)) => + (Self::C(__self_0), Self::C(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (ReorderEnum::G(__self_0, __self_1, __self_2), - ReorderEnum::G(__arg1_0, __arg1_1, __arg1_2)) => + (Self::G(__self_0, __self_1, __self_2), + Self::G(__arg1_0, __arg1_1, __arg1_2)) => match ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0) { ::core::option::Option::Some(::core::cmp::Ordering::Equal) @@ -1407,11 +1407,11 @@ impl ::core::clone::Clone for Fielded { #[inline] fn clone(&self) -> Self { match self { - Fielded::X(__self_0) => + Self::X(__self_0) => Self::X(::core::clone::Clone::clone(__self_0)), - Fielded::Y(__self_0) => + Self::Y(__self_0) => Self::Y(::core::clone::Clone::clone(__self_0)), - Fielded::Z(__self_0) => + Self::Z(__self_0) => Self::Z(::core::clone::Clone::clone(__self_0)), } } @@ -1421,13 +1421,13 @@ impl ::core::fmt::Debug for Fielded { #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - Fielded::X(__self_0) => + Self::X(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "X", &__self_0), - Fielded::Y(__self_0) => + Self::Y(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Y", &__self_0), - Fielded::Z(__self_0) => + Self::Z(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Z", &__self_0), } @@ -1440,9 +1440,9 @@ impl ::core::hash::Hash for Fielded { ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); match self { - Fielded::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Fielded::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), - Fielded::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::X(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Y(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Z(__self_0) => ::core::hash::Hash::hash(__self_0, state), } } } @@ -1455,11 +1455,11 @@ impl ::core::cmp::PartialEq for Fielded { ::core::intrinsics::discriminant_value(self) == ::core::intrinsics::discriminant_value(other) && match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + (Self::X(__self_0), Self::X(__arg1_0)) => __self_0 == __arg1_0, - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + (Self::Y(__self_0), Self::Y(__arg1_0)) => __self_0 == __arg1_0, - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + (Self::Z(__self_0), Self::Z(__arg1_0)) => __self_0 == __arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } } @@ -1489,11 +1489,11 @@ impl ::core::cmp::Ord for Fielded { #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { - (Fielded::X(__self_0), Fielded::X(__arg1_0)) => + (Self::X(__self_0), Self::X(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) => + (Self::Y(__self_0), Self::Y(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) => + (Self::Z(__self_0), Self::Z(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), _ => ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), @@ -1510,9 +1510,9 @@ impl ::core::clone::Clone #[inline] fn clone(&self) -> Self { match self { - EnumGeneric::One(__self_0) => + Self::One(__self_0) => Self::One(::core::clone::Clone::clone(__self_0)), - EnumGeneric::Two(__self_0) => + Self::Two(__self_0) => Self::Two(::core::clone::Clone::clone(__self_0)), } } @@ -1527,10 +1527,10 @@ impl ::core::fmt::Debug for #[inline] fn fmt(&self, f: &mut ::core::fmt::Formatter) -> ::core::fmt::Result { match self { - EnumGeneric::One(__self_0) => + Self::One(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "One", &__self_0), - EnumGeneric::Two(__self_0) => + Self::Two(__self_0) => ::core::fmt::Formatter::debug_tuple_field1_finish(f, "Two", &__self_0), } @@ -1544,10 +1544,8 @@ impl ::core::hash::Hash for ::core::hash::Hash::hash(&::core::intrinsics::discriminant_value(self), state); match self { - EnumGeneric::One(__self_0) => - ::core::hash::Hash::hash(__self_0, state), - EnumGeneric::Two(__self_0) => - ::core::hash::Hash::hash(__self_0, state), + Self::One(__self_0) => ::core::hash::Hash::hash(__self_0, state), + Self::Two(__self_0) => ::core::hash::Hash::hash(__self_0, state), } } } @@ -1563,9 +1561,9 @@ impl ::core::intrinsics::discriminant_value(self) == ::core::intrinsics::discriminant_value(other) && match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => + (Self::One(__self_0), Self::One(__arg1_0)) => __self_0 == __arg1_0, - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => + (Self::Two(__self_0), Self::Two(__arg1_0)) => __self_0 == __arg1_0, _ => unsafe { ::core::intrinsics::unreachable() } } @@ -1589,9 +1587,9 @@ impl fn partial_cmp(&self, other: &Self) -> ::core::option::Option<::core::cmp::Ordering> { match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => + (Self::One(__self_0), Self::One(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => + (Self::Two(__self_0), Self::Two(__arg1_0)) => ::core::cmp::PartialOrd::partial_cmp(__self_0, __arg1_0), _ => ::core::cmp::PartialOrd::partial_cmp(&::core::intrinsics::discriminant_value(self), @@ -1605,9 +1603,9 @@ impl ::core::cmp::Ord for #[inline] fn cmp(&self, other: &Self) -> ::core::cmp::Ordering { match (self, other) { - (EnumGeneric::One(__self_0), EnumGeneric::One(__arg1_0)) => + (Self::One(__self_0), Self::One(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), - (EnumGeneric::Two(__self_0), EnumGeneric::Two(__arg1_0)) => + (Self::Two(__self_0), Self::Two(__arg1_0)) => ::core::cmp::Ord::cmp(__self_0, __arg1_0), _ => ::core::cmp::Ord::cmp(&::core::intrinsics::discriminant_value(self), @@ -1630,8 +1628,8 @@ impl ::core::cmp::PartialEq for NonCopyEnum { #[inline] fn eq(&self, other: &Self) -> bool { match (self, other) { - (NonCopyEnum::NonCopyField(__self_0), - NonCopyEnum::NonCopyField(__arg1_0)) => __self_0 == __arg1_0, + (Self::NonCopyField(__self_0), Self::NonCopyField(__arg1_0)) => + __self_0 == __arg1_0, } } } From ec57172476e16cd0f3e9ca260c761b5bae046cc6 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 22 Sep 2026 09:02:01 +0000 Subject: [PATCH 0741/1309] add `cx.expr_ident_sym` --- compiler/rustc_builtin_macros/src/deriving/debug.rs | 6 +++--- compiler/rustc_builtin_macros/src/deriving/from.rs | 4 ++-- compiler/rustc_builtin_macros/src/deriving/generic/mod.rs | 2 +- compiler/rustc_builtin_macros/src/deriving/hash.rs | 7 ++----- compiler/rustc_builtin_macros/src/deriving/partial_ord.rs | 2 +- compiler/rustc_expand/src/build.rs | 3 +++ 6 files changed, 12 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 45e3dd2d0f760..d490c61e4f5ad 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -49,7 +49,7 @@ pub(crate) fn expand_deriving_debug( } fn formatter_ident(cx: &ExtCtxt<'_>, span: Span) -> Box { - cx.expr_ident(span, Ident::new(sym::character('f'), span)) + cx.expr_ident_sym(span, sym::character('f')) } fn show_substructure( @@ -194,9 +194,9 @@ fn show_substructure( args.push(fmt); args.push(name); if is_struct { - args.push(cx.expr_ident(span, Ident::new(sym::names, span))); + args.push(cx.expr_ident_sym(span, sym::names)); } - args.push(cx.expr_ident(span, Ident::new(sym::values, span))); + args.push(cx.expr_ident_sym(span, sym::values)); let expr = cx.expr_call_global(span, fn_path_debug_internal, args); let mut stmts = ThinVec::with_capacity(2); diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 5980e43298fff..d9a9a30692731 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -97,14 +97,14 @@ pub(crate) fn expand_deriving_from( thin_vec![cx.field_imm( span, field.ident.unwrap(), - cx.expr_ident(span, Ident::new(sym::value, span)) + cx.expr_ident_sym(span, sym::value) )], ), // Self(value) VariantData::Tuple(_, _) => cx.expr_call_ident( span, self_kw, - thin_vec![cx.expr_ident(span, Ident::new(sym::value, span))], + thin_vec![cx.expr_ident_sym(span, sym::value)], ), variant => { cx.dcx().bug(format!("Invalid derive(From) ADT variant: {variant:?}")); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 64149f96aaf48..e9b4a6f279bea 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -812,7 +812,7 @@ impl<'a> MethodDef<'a> { once(cx.expr_self(span)) .chain(self.nonself_args.iter().filter_map(|(ty, name)| match ty { - Ref(Self_, _) => Some(cx.expr_ident(span, Ident::new(*name, span))), + Ref(Self_, _) => Some(cx.expr_ident_sym(span, *name)), _ => None, })) .collect() diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 158bb77ef30fa..0ed46a1116a4e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -60,11 +60,8 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_ let call_hash = |span, expr| { let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]); let hash_path = cx.expr_path(cx.path_global(span, strs)); - let expr = cx.expr_call( - span, - hash_path, - thin_vec![expr, cx.expr_ident(span, Ident::new(sym::state, span))], - ); + let expr = + cx.expr_call(span, hash_path, thin_vec![expr, cx.expr_ident_sym(span, sym::state)]); cx.stmt_expr(expr) }; diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 18e5e55c2d036..f33a7bc0ac657 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -25,7 +25,7 @@ pub(crate) fn expand_deriving_partial_ord( let default_substructure = combine_substructure(|cx, span, substr| cs_partial_cmp(cx, span, substr, discr_then_data)); let simple_substructure = combine_substructure(|cx, span, _| { - cs_partial_cmp_simple(cx, span, cx.expr_ident(span, Ident::new(sym::other, span))) + cs_partial_cmp_simple(cx, span, cx.expr_ident_sym(span, sym::other)) }); let is_simple = match &item.kind { // For unit structs/zero-variant enums, the default generated code is better. diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 0e9d9ec5e8b7e..d744388f4bf3b 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -310,6 +310,9 @@ impl<'a> ExtCtxt<'a> { pub fn expr_self(&self, span: Span) -> Box { self.expr_ident(span, Ident::new(kw::SelfLower, span)) } + pub fn expr_ident_sym(&self, span: Span, sym: Symbol) -> Box { + self.expr_ident(span, Ident::new(sym, span)) + } pub fn expr_macro_call(&self, span: Span, call: Box) -> Box { self.expr(span, ast::ExprKind::MacCall(call)) From 839f431478ef806742eb149eb339839a2814f378 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 22 Sep 2026 10:33:09 +0000 Subject: [PATCH 0742/1309] remove the `FieldInfo` from `EnumDiscr` --- .../src/deriving/generic/mod.rs | 43 ++-------------- .../rustc_builtin_macros/src/deriving/hash.rs | 16 +++--- .../rustc_builtin_macros/src/deriving/mod.rs | 5 ++ .../src/deriving/partial_eq.rs | 50 +++++++------------ .../src/deriving/partial_ord.rs | 11 ++-- 5 files changed, 44 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index e9b4a6f279bea..e1a9f7e095164 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -297,10 +297,9 @@ pub(crate) enum Substructure<'a> { /// variant. EnumMatching(&'a ast::Variant, Vec), - /// The discriminant of an enum. The first field is a `FieldInfo` for the discriminants, as - /// if they were fields. The second field is the expression to combine the + /// The discriminant of an enum. The field is the expression to combine the /// discriminant expression with; it will be `None` if no match is necessary. - EnumDiscr(FieldInfo, Option>), + EnumDiscr(Option>), /// A static method where `Self` is a struct. StaticStruct(&'a ast::VariantData), @@ -997,29 +996,6 @@ impl<'a> MethodDef<'a> { _ => unreachable!(), }; - // Maps each selflike_arg to its discriminant value. - // - // e.g. for `PartialEq::eq` it builds: - // ``` - // ::core::intrinsics::discriminant_value(self); // self_expr - // ::core::intrinsics::discriminant_value(other); // other_selflike_expr - // ``` - let get_discr_field_info = || { - let mut discr_exprs = selflike_args.iter().map(|selflike_arg| { - let call = deriving::call_intrinsic( - cx, - span, - sym::discriminant_value, - thin_vec![selflike_arg.clone()], - ); - cx.expr_addr_of(span, call) - }); - let self_expr = discr_exprs.next().unwrap(); - let other_selflike_expr = discr_exprs.next(); - - FieldInfo { span, name: None, self_expr, other_selflike_expr, maybe_scalar: true } - }; - // There are some special cases involving fieldless enums where no // match is necessary. let all_fieldless = variants.iter().all(|v| v.data.fields().is_empty()); @@ -1030,12 +1006,7 @@ impl<'a> MethodDef<'a> { // If the type is fieldless and the trait uses the discriminant and // there are multiple variants, we need just an operation on // the discriminant(s). - let discr_field = get_discr_field_info(); - return self.call_substructure_method( - cx, - span, - EnumDiscr(discr_field, None), - ); + return self.call_substructure_method(cx, span, EnumDiscr(None)); } FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless => { return self.call_substructure_method(cx, span, AllFieldlessEnum(enum_def)); @@ -1135,14 +1106,8 @@ impl<'a> MethodDef<'a> { // to add a discriminant check operation before the match. Otherwise, the match // is enough. if unify_fieldless_variants && variants.len() > 1 { - let discr_field = get_discr_field_info(); - // Combine a discriminant check with the match. - self.call_substructure_method( - cx, - span, - EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), - ) + self.call_substructure_method(cx, span, EnumDiscr(Some(get_match_expr(selflike_args)))) } else { BlockOrExpr(ThinVec::new(), Some(get_match_expr(selflike_args))) } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 0ed46a1116a4e..6c9f56261f817 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -1,11 +1,11 @@ use rustc_ast::{Mutability, Safety}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::path_std; +use crate::deriving::{call_discriminant_value, path_std}; pub(crate) fn expand_deriving_hash( cx: &ExtCtxt<'_>, @@ -56,7 +56,7 @@ pub(crate) fn expand_deriving_hash( hash_trait_def.expand(cx, item, push); } -fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { +fn hash_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { let call_hash = |span, expr| { let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]); let hash_path = cx.expr_path(cx.path_global(span, strs)); @@ -71,12 +71,14 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_ fields.into_iter().map(|field| call_hash(field.span, field.self_expr)).collect(); (stmts, None) } - EnumDiscr(discr_field, match_expr) => { - assert!(discr_field.other_selflike_expr.is_none()); - let stmts = thin_vec![call_hash(discr_field.span, discr_field.self_expr)]; + EnumDiscr(match_expr) => { + let stmts = thin_vec![call_hash( + span, + cx.expr_addr_of(span, call_discriminant_value(cx, span, kw::SelfLower)) + )]; (stmts, match_expr) } - _ => cx.dcx().span_bug(trait_span, "unexpected substructure in `derive(Hash)`"), + _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(Hash)`"), }; BlockOrExpr::new_mixed(stmts, match_expr) diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 66d4a61b97fdc..333908ccb1844 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -87,6 +87,11 @@ fn call_intrinsic( cx.expr_call_global(span, path, args) } +/// Constructs an expression that calls the `discriminant_value` intrinsic. +fn call_discriminant_value(cx: &ExtCtxt<'_>, span: Span, arg: Symbol) -> Box { + call_intrinsic(cx, span, sym::discriminant_value, thin_vec![cx.expr_ident_sym(span, arg)]) +} + /// Constructs an expression that calls the `unreachable` intrinsic. fn call_unreachable(cx: &ExtCtxt<'_>, span: Span) -> Box { let call = call_intrinsic(cx, span, sym::unreachable, ThinVec::new()); diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index ccad49c1897c3..02b3dbabd3393 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -1,11 +1,11 @@ use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, Mutability, Safety}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::path_std; +use crate::deriving::{call_discriminant_value, path_std}; /// Expands a `#[derive(PartialEq)]` attribute into an implementation for the /// target item. @@ -121,8 +121,18 @@ fn get_substructure_equality_expr( ) -> BlockOrExpr { BlockOrExpr::new_expr(match substructure { EnumMatching(.., fields) | Struct(.., fields) => { - let combine = move |acc, field| { - let rhs = get_field_equality_expr(cx, field); + let combine = move |acc, field: &FieldInfo| { + let rhs = field + .other_selflike_expr + .as_ref() + .expect("not exactly 2 arguments in `derive(PartialEq)`"); + + let rhs = cx.expr_binary( + field.span, + BinOpKind::Eq, + wrap_block_expr(cx, peel_refs(&field.self_expr)), + wrap_block_expr(cx, peel_refs(rhs)), + ); match acc { // Combine the previous comparison with the current field // using logical AND. @@ -142,43 +152,21 @@ fn get_substructure_equality_expr( // If there are no fields, treat as always equal. .unwrap_or_else(|| cx.expr_bool(span, true)) } - EnumDiscr(disc, match_expr) => { - let lhs = get_field_equality_expr(cx, &disc); + EnumDiscr(match_expr) => { + let self_expr = call_discriminant_value(cx, span, kw::SelfLower); + let other_selflike_expr = call_discriminant_value(cx, span, sym::other); + let lhs = cx.expr_binary(span, BinOpKind::Eq, self_expr, other_selflike_expr); let Some(match_expr) = match_expr else { return BlockOrExpr::new_expr(lhs); }; // Compare the discriminant first (cheaper), then the rest of the // fields. - cx.expr_binary(disc.span, BinOpKind::And, lhs, match_expr.clone()) + cx.expr_binary(span, BinOpKind::And, lhs, match_expr) } _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(PartialEq)`"), }) } -/// Generates an equality comparison expression for a single struct or enum -/// field. -/// -/// This function produces an AST expression that compares the `self` and -/// `other` values for a field using `==`. It removes any leading references -/// from both sides for readability. If the field is a block expression, it is -/// wrapped in parentheses to ensure valid syntax. -/// -/// # Panics -/// -/// Panics if there are not exactly two arguments to compare (should be `self` -/// and `other`). -fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> Box { - let rhs = - field.other_selflike_expr.as_ref().expect("not exactly 2 arguments in `derive(PartialEq)`"); - - cx.expr_binary( - field.span, - BinOpKind::Eq, - wrap_block_expr(cx, peel_refs(&field.self_expr)), - wrap_block_expr(cx, peel_refs(rhs)), - ) -} - /// Removes all leading immutable references from an expression. /// /// This is used to strip away any number of leading `&` from an expression diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index f33a7bc0ac657..7600d0c8e4e48 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -1,11 +1,11 @@ use rustc_ast::{Expr, ItemKind, Safety, ast}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, sym}; +use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::{path_std, pathvec}; +use crate::deriving::{call_discriminant_value, path_std, pathvec}; pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, @@ -234,8 +234,11 @@ pub(crate) fn cmp_body( fields.rfold(base_expr, op) } - EnumDiscr(discr_field, match_expr) => { - let discr_check_expr = single(discr_field); + EnumDiscr(match_expr) => { + let self_expr = cx.expr_addr_of(span, call_discriminant_value(cx, span, kw::SelfLower)); + let other_expr = cx.expr_addr_of(span, call_discriminant_value(cx, span, sym::other)); + let args = thin_vec![self_expr, other_expr]; + let discr_check_expr = cx.expr_call_global(span, method_path, args); if let Some(match_expr) = match_expr { combine(span, match_expr, discr_check_expr) } else { From bf645be9673f7c291ff2b7f7103b38253b12b7a0 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 22 Sep 2026 11:53:08 +0000 Subject: [PATCH 0743/1309] simplify the `rfold` call --- .../src/deriving/partial_ord.rs | 42 ++++++++----------- 1 file changed, 17 insertions(+), 25 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 7600d0c8e4e48..46e4ec510bd7f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -147,16 +147,8 @@ pub(crate) fn cmp_body( }; let equal_path = cx.path_global(span, cx.std_path(&[sym::cmp, sym::Ordering, sym::Equal])); - // The basic case: a field expression for one or more selflike args. E.g. - // for `Ord::cmp` this is something like `Ord::cmp(&self.x, &other.x)`. - let single = |field: FieldInfo| { - let other_expr = field.other_selflike_expr.expect("not exactly 2 arguments in `derive`"); - let args = thin_vec![field.self_expr, other_expr]; - cx.expr_call_global(field.span, method_path.clone(), args) - }; - - // The combination of two field expressions. E.g. for `PartialEq::eq` this - // is something like ` && `. + // The combination of two field expressions. E.g. for `Ord::cmp` this + // is something like ` && `. let combine = |span, mut expr1: Box, expr2| { // For `PartialOrd` (`Ord` works the same but without the `Some` wrapping), // when the item is an enum, this expands to @@ -212,27 +204,27 @@ pub(crate) fn cmp_body( match substructure { EnumMatching(.., all_fields) | Struct(_, all_fields) => { - let mut fields = all_fields.into_iter(); - let base_field = fields.next_back(); + let op = |old, field: FieldInfo| { + // The basic case: a field expression for one or more selflike args. E.g. + // for `Ord::cmp` this is something like `Ord::cmp(&self.x, &other.x)`. + let other_expr = + field.other_selflike_expr.expect("not exactly 2 arguments in `derive`"); + let args = thin_vec![field.self_expr, other_expr]; + let new = cx.expr_call_global(field.span, method_path.clone(), args); + match old { + Some(old) => Some(combine(field.span, old, new)), + None => Some(new), + } + }; - let Some(base_field) = base_field else { + all_fields.into_iter().rfold(None, op).unwrap_or_else(|| { // The fallback case for a struct or enum variant with no fields. let mut expr = cx.expr_path(equal_path); if is_partial_ord { expr = cx.expr_some(span, expr) }; - return expr; - }; - - let base_expr = single(base_field); - - let op = |old, field: FieldInfo| { - let span = field.span; - let new = single(field); - combine(span, old, new) - }; - - fields.rfold(base_expr, op) + expr + }) } EnumDiscr(match_expr) => { let self_expr = cx.expr_addr_of(span, call_discriminant_value(cx, span, kw::SelfLower)); From 2196ae3e483a86e9989a23e644ad3167e636ed04 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Tue, 22 Sep 2026 19:05:31 +0000 Subject: [PATCH 0744/1309] remove the local version of `Ty` --- .../src/deriving/clone.rs | 4 +- .../src/deriving/debug.rs | 11 ++-- .../src/deriving/default.rs | 7 +-- .../rustc_builtin_macros/src/deriving/eq.rs | 4 +- .../rustc_builtin_macros/src/deriving/from.rs | 12 ++--- .../src/deriving/generic/mod.rs | 29 +++++----- .../src/deriving/generic/ty.rs | 53 ------------------- .../rustc_builtin_macros/src/deriving/hash.rs | 8 +-- .../rustc_builtin_macros/src/deriving/mod.rs | 14 ++++- .../rustc_builtin_macros/src/deriving/ord.rs | 6 +-- .../src/deriving/partial_eq.rs | 6 +-- .../src/deriving/partial_ord.rs | 10 ++-- compiler/rustc_expand/src/build.rs | 11 ++++ 13 files changed, 74 insertions(+), 101 deletions(-) delete mode 100644 compiler/rustc_builtin_macros/src/deriving/generic/ty.rs diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 95ad579f015fb..370c0ceeda909 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -4,7 +4,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -90,7 +89,8 @@ pub(crate) fn expand_deriving_clone( generics: cx.empty_generics(span), explicit_self: true, nonself_args: SmallVec::new(), - ret_ty: Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: substructure, diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index d490c61e4f5ad..2f3d2058773d8 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -4,7 +4,6 @@ use rustc_session::config::FmtDebug; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -16,7 +15,12 @@ pub(crate) fn expand_deriving_debug( is_const: bool, ) { // &mut ::std::fmt::Formatter - let fmtr = Ref(Box::new(Path(path_std!(cx, span, fmt::Formatter))), ast::Mutability::Mut); + let fmtr = cx.ty_ref( + span, + cx.ty_path(path_std!(cx, span, fmt::Formatter)), + None, + ast::Mutability::Mut, + ); let trait_def = TraitDef { span, @@ -30,7 +34,8 @@ pub(crate) fn expand_deriving_debug( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(fmtr, sym::character('f'))], - ret_ty: Path(path_std!(cx, span, fmt::Result)), + has_other_selflike_arg: false, + ret_ty: cx.ty_path(path_std!(cx, span, fmt::Result)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 92d15efa05a95..28526bdef6b9d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -7,8 +7,8 @@ use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; use smallvec::SmallVec; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; +use crate::deriving::new_path; use crate::diagnostics; pub(crate) fn expand_deriving_default( @@ -22,7 +22,7 @@ pub(crate) fn expand_deriving_default( let trait_def = TraitDef { span, - path: new_path(cx, span, &[kw::Default, sym::Default], &[]), + path: new_path(cx, span, &[kw::Default, sym::Default], vec![]), skip_path_as_bound: has_a_default_variant(item), needs_copy_as_bound_if_packed: false, additional_bounds: SmallVec::new(), @@ -32,7 +32,8 @@ pub(crate) fn expand_deriving_default( generics: cx.empty_generics(span), explicit_self: false, nonself_args: SmallVec::new(), - ret_ty: Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index bcf2e310596f4..da38045994c7f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -4,7 +4,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::path_std; @@ -29,7 +28,8 @@ pub(crate) fn expand_deriving_eq( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![], - ret_ty: Unit, + has_other_selflike_arg: false, + ret_ty: cx.ty_unit(span), attributes: thin_vec![ // This method will never be called, so doing codegen etc. for it is unnecessary. // We prevent this by adding `#[inline]`, which improves compile-time. diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index d9a9a30692731..df95ccd99f3e6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -5,9 +5,8 @@ use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::pathvec; +use crate::deriving::{new_path, pathvec}; use crate::diagnostics; /// Generate an implementation of the `From` trait, provided that `item` @@ -47,12 +46,12 @@ pub(crate) fn expand_deriving_from( _ => cx.dcx().bug("Invalid derive(From) ADT input"), }; - let from_type = Ty::AstTy(match field { + let from_type = match field { Ok(ref field) => field.ty.clone(), Err(guar) => cx.ty(span, ast::TyKind::Err(guar)), - }); + }; - let path = new_path(cx, span, pathvec!(convert::From), &[from_type.clone()]); + let path = new_path(cx, span, pathvec!(convert::From), vec![from_type.clone()]); // Generate code like this: // @@ -76,7 +75,8 @@ pub(crate) fn expand_deriving_from( generics: cx.empty_generics(span), explicit_self: false, nonself_args: smallvec![(from_type, sym::value)], - ret_ty: Ty::Self_, + has_other_selflike_arg: false, + ret_ty: cx.ty_self(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, span, substructure| { diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index e1a9f7e095164..71329da76c481 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -174,7 +174,6 @@ //! ) //! ``` -use std::iter::once; use std::ops::Not; use std::vec; @@ -192,12 +191,9 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; -use ty::{Ref, Self_, Ty}; use crate::{deriving, diagnostics}; -pub(crate) mod ty; - pub(crate) struct TraitDef<'a> { /// The span for the current #[derive(Foo)] header. pub span: Span, @@ -239,10 +235,13 @@ pub(crate) struct MethodDef<'a> { pub explicit_self: bool, /// Arguments other than the self argument. - pub nonself_args: SmallVec<[(Ty, Symbol); 1]>, + pub nonself_args: SmallVec<[(Box, Symbol); 1]>, + + /// Whether this method has another arg of type `&self`. + pub has_other_selflike_arg: bool, /// Returns type - pub ret_ty: Ty, + pub ret_ty: Box, pub attributes: ast::AttrVec, @@ -809,12 +808,12 @@ impl<'a> MethodDef<'a> { fn get_selflike_args(&self, cx: &ExtCtxt<'_>, span: Span) -> ThinVec> { assert!(self.explicit_self); - once(cx.expr_self(span)) - .chain(self.nonself_args.iter().filter_map(|(ty, name)| match ty { - Ref(Self_, _) => Some(cx.expr_ident_sym(span, *name)), - _ => None, - })) - .collect() + let self_expr = cx.expr_self(span); + if self.has_other_selflike_arg { + thin_vec![self_expr, cx.expr_ident_sym(span, self.nonself_args[0].1)] + } else { + thin_vec![self_expr] + } } fn create_method( @@ -841,16 +840,16 @@ impl<'a> MethodDef<'a> { let args = self_arg .into_iter() .chain(self.nonself_args.iter().map(|(ty, name)| { - let ast_ty = ty.to_ty(cx, span); + let ast_ty = ty.clone(); let ident = Ident::new(*name, span); cx.param(span, ident, ast_ty) })) .collect(); - let ret_type = if let Ty::Unit = &self.ret_ty { + let ret_type = if self.ret_ty.kind.is_unit() { ast::FnRetTy::Default(span) } else { - ast::FnRetTy::Ty(self.ret_ty.to_ty(cx, span)) + ast::FnRetTy::Ty(self.ret_ty.clone()) }; let method_ident = Ident::new(self.name, span); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs deleted file mode 100644 index 8f2de7a46fa18..0000000000000 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ /dev/null @@ -1,53 +0,0 @@ -//! A mini version of ast::Ty, which is easier to use, and features an explicit `Self` type to use -//! when specifying impls to be derived. - -use std::iter::once; - -pub(crate) use Ty::*; -use rustc_ast::{self as ast, GenericArg}; -use rustc_expand::base::ExtCtxt; -use rustc_span::{Ident, Span, Symbol, kw}; -use thin_vec::ThinVec; - -pub(crate) fn new_path(cx: &ExtCtxt<'_>, span: Span, path: &[Symbol], params: &[Ty]) -> ast::Path { - let idents = path.iter().map(|s| Ident::new(*s, span)); - let tys = params.iter().map(|t| t.to_ty(cx, span)); - let params = tys.map(GenericArg::Type).collect(); - - let idents = once(Ident::new(kw::DollarCrate, span)).chain(idents).collect(); - cx.path_all(span, false, idents, params) -} - -/// A type. Supports pointers, Self, literals, unit or an arbitrary AST path. -#[derive(Clone)] -pub(crate) enum Ty { - Self_, - /// A reference. - Ref(Box, ast::Mutability), - /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type - /// parameter, and things like `i32` - Path(ast::Path), - /// For () return types. - Unit, - /// An arbitrary type. - AstTy(Box), -} - -pub(crate) fn self_ref() -> Ty { - Ref(Box::new(Self_), ast::Mutability::Not) -} - -impl Ty { - pub(crate) fn to_ty(&self, cx: &ExtCtxt<'_>, span: Span) -> Box { - match self { - Ref(ty, mutbl) => { - let raw_ty = ty.to_ty(cx, span); - cx.ty_ref(span, raw_ty, None, *mutbl) - } - Path(p) => cx.ty_path(p.clone()), - Self_ => cx.ty_path(cx.path_ident(span, Ident::new(kw::SelfUpper, span))), - Unit => cx.ty(span, ast::TyKind::Tup(ThinVec::new())), - AstTy(ty) => ty.clone(), - } - } -} diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 6c9f56261f817..3d3023b39955d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -3,7 +3,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::{ThinVec, thin_vec}; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::{call_discriminant_value, path_std}; @@ -18,7 +17,7 @@ pub(crate) fn expand_deriving_hash( let typaram = Ident::new(sym::__H, span); - let arg = cx.path_ident(span, typaram); + let arg = cx.ty_path(cx.path_ident(span, typaram)); let param = { let path = path_std!(cx, span, hash::Hasher); @@ -42,8 +41,9 @@ pub(crate) fn expand_deriving_hash( name: sym::hash, generics, explicit_self: true, - nonself_args: smallvec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], - ret_ty: Unit, + nonself_args: smallvec![(cx.ty_ref(span, arg, None, Mutability::Mut), sym::state)], + has_other_selflike_arg: false, + ret_ty: cx.ty_unit(span), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(hash_substructure), diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index 333908ccb1844..c4af6ac16bdc6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -1,9 +1,11 @@ //! The compiler code necessary to implement the `#[derive]` extensions. +use std::iter::once; + use rustc_ast as ast; use rustc_ast::{GenericArg, MetaItem}; use rustc_expand::base::{Annotatable, ExpandResult, ExtCtxt, MultiItemModifier}; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use thin_vec::{ThinVec, thin_vec}; macro pathvec($($rest:ident)::+) {{ @@ -11,7 +13,7 @@ macro pathvec($($rest:ident)::+) {{ }} macro path_std($cx: expr, $span: expr, $($x:tt)*) { - generic::ty::new_path($cx, $span, pathvec!( $($x)* ), &[] ) + new_path($cx, $span, pathvec!( $($x)* ), vec![] ) } pub(crate) mod clone; @@ -115,3 +117,11 @@ fn assert_ty_bounds( let assert_path = cx.path_all(span, true, cx.std_path(assert_path), vec![GenericArg::Type(ty)]); stmts.push(cx.stmt_let_type_only(span, cx.ty_path(assert_path))); } + +fn new_path(cx: &ExtCtxt<'_>, span: Span, path: &[Symbol], params: Vec>) -> ast::Path { + let idents = path.iter().map(|s| Ident::new(*s, span)); + let params = params.into_iter().map(GenericArg::Type).collect(); + + let idents = once(Ident::new(kw::DollarCrate, span)).chain(idents).collect(); + cx.path_all(span, false, idents, params) +} diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index a2527d3d6f36d..c20bfc81bd409 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -3,7 +3,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Span, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::partial_ord::{OrdlikeDerive, cmp_body, discr_data_order}; use crate::deriving::path_std; @@ -28,8 +27,9 @@ pub(crate) fn expand_deriving_ord( name: sym::cmp, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(path_std!(cx, span, cmp::Ordering)), + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, + ret_ty: cx.ty_path(path_std!(cx, span, cmp::Ordering)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(|cx, span, substr| cs_cmp( diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 02b3dbabd3393..377a32dcca4f0 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -3,7 +3,6 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::{call_discriminant_value, path_std}; @@ -41,8 +40,9 @@ pub(crate) fn expand_deriving_partial_eq( name: sym::eq, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(cx.path_ident(span, Ident::new(sym::bool, span))), + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, + ret_ty: cx.ty_path(cx.path_ident(span, Ident::new(sym::bool, span))), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(get_substructure_equality_expr), diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 46e4ec510bd7f..8c3e2ee58f8e2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -3,9 +3,8 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::*; use crate::deriving::generic::*; -use crate::deriving::{call_discriminant_value, path_std, pathvec}; +use crate::deriving::{call_discriminant_value, new_path, path_std, pathvec}; pub(crate) fn expand_deriving_partial_ord( cx: &ExtCtxt<'_>, @@ -14,8 +13,8 @@ pub(crate) fn expand_deriving_partial_ord( push: &mut dyn FnMut(Box), is_const: bool, ) { - let ordering_ty = Path(path_std!(cx, span, cmp::Ordering)); - let ret_ty = Path(new_path(cx, span, pathvec!(option::Option), &[ordering_ty])); + let ordering_ty = cx.ty_path(path_std!(cx, span, cmp::Ordering)); + let ret_ty = cx.ty_path(new_path(cx, span, pathvec!(option::Option), vec![ordering_ty])); // Order in which to perform matching let discr_then_data = discr_data_order(item); @@ -54,7 +53,8 @@ pub(crate) fn expand_deriving_partial_ord( name: sym::partial_cmp, generics: cx.empty_generics(span), explicit_self: true, - nonself_args: smallvec![(self_ref(), sym::other)], + nonself_args: smallvec![(cx.ty_self_ref(span), sym::other)], + has_other_selflike_arg: true, ret_ty, attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index d744388f4bf3b..9a93d82a4fe4c 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -125,6 +125,17 @@ impl<'a> ExtCtxt<'a> { self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) } + pub fn ty_unit(&self, span: Span) -> Box { + self.ty(span, ast::TyKind::Tup(ThinVec::new())) + } + + pub fn ty_self(&self, span: Span) -> Box { + self.ty_path(self.path_ident(span, Ident::new(kw::SelfUpper, span))) + } + pub fn ty_self_ref(&self, span: Span) -> Box { + self.ty_ref(span, self.ty_self(span), None, ast::Mutability::Not) + } + pub fn typaram( &self, span: Span, From ff571c3bfde3c68c0535c7ce388387176210cbe3 Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 14 Aug 2026 15:26:11 +1000 Subject: [PATCH 0745/1309] Simplify `core::cmp::{smallest, largest}` Implementation Adjust implementation to reduce MIR generated. --- library/core/src/cmp.rs | 89 ++++++++++++++++++----------------------- 1 file changed, 40 insertions(+), 49 deletions(-) diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index a7c22a195e5d2..2792c7cde57be 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -1967,24 +1967,19 @@ macro impl_tuples($($mac:ident,)+) { } /// Implementation detail for [`smallest`] and [`largest`]. -/// Marker indicating that `Self` is a tuple where all members are of the same type. +/// Marker indicating that `Self` is a tuple where all members are of the type `T`. +/// Cannot be an associated type as we require the empty tuple to implement this trait +/// for all types `T`. #[diagnostic::on_unimplemented(message = "`{Self}` is not a homogeneous tuple")] #[unstable(feature = "cmp_splat_internals", issue = "160728")] #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] -const trait HomogeneousTuple: crate::marker::Tuple { - /// The type of each item in this tuple. - type Item; -} +const trait HomogeneousTuple: crate::marker::Tuple {} /// Implements [`HomogeneousTuple`] for a provided tuple. -macro impl_homogeneous_tuple($($($x:ident,)+)?) { - $( - #[unstable(feature = "cmp_splat_internals", issue = "160728")] - #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] - const impl HomogeneousTuple for ($(${ignore($x)}T,)+) { - type Item = T; - } - )? +macro impl_homogeneous_tuple($($x:ident,)*) { + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl HomogeneousTuple for ($(${ignore($x)}T,)*) { } } impl_tuples! { @@ -2040,36 +2035,34 @@ impl_tuples! { #[expect(private_bounds, reason = "`SmallestArgs` is an internal implementation detail")] #[cfg(not(test))] // FIXME: splat interacts poorly with the double linking of `core` in tests pub const fn smallest( - #[rustc_splat] args: impl [const] SmallestArgs, + v1: T, + #[rustc_splat] args: impl [const] SmallestArgs, ) -> T { - SmallestArgs::smallest(args) + SmallestArgs::smallest(v1, args) } /// Implementation detail for [`smallest`]. #[diagnostic::on_unimplemented(message = "`{Self}` is not a valid set of arguments for `smallest`")] #[unstable(feature = "cmp_splat_internals", issue = "160728")] #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] -const trait SmallestArgs: HomogeneousTuple { +const trait SmallestArgs: HomogeneousTuple { /// Reduces all elements of a homogeneous tuple to its smallest value. - fn smallest(self) -> Self::Item; + fn smallest(v1: T, args: Self) -> T; } /// Implements [`SmallestArgs`] for a provided tuple if applicable. -macro impl_smallest_args($($x:ident, $($($y:ident,)+)?)?) { - $( - #[unstable(feature = "cmp_splat_internals", issue = "160728")] - #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] - const impl SmallestArgs for (T, $($(${ignore($y)}T,)+)?) - $(where T: [const] Destruct + [const] Ord, $(${ignore($y)})+)? - { - #[inline] - fn smallest(self) -> Self::Item { - let ($x, $($($y,)+)?) = self; - $($(let $x = $x.min($y);)+)? - $x - } +macro impl_smallest_args($($x:ident,)*) { + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl SmallestArgs for ($(${ignore($x)}T,)*) + where + T: [const] Destruct + [const] Ord, + { + #[inline(always)] // improves unoptimised codegen + fn smallest(v1: T, ($($x,)*): Self) -> T { + v1$(.min($x))* } - )? + } } impl_tuples! { @@ -2125,36 +2118,34 @@ impl_tuples! { #[expect(private_bounds, reason = "`LargestArgs` is an internal implementation detail")] #[cfg(not(test))] // FIXME: splat interacts poorly with the double linking of `core` in tests pub const fn largest( - #[rustc_splat] args: impl [const] LargestArgs, + v1: T, + #[rustc_splat] args: impl [const] LargestArgs, ) -> T { - LargestArgs::largest(args) + LargestArgs::largest(v1, args) } /// Implementation detail for [`largest`]. #[diagnostic::on_unimplemented(message = "`{Self}` is not a valid set of arguments for `largest`")] #[unstable(feature = "cmp_splat_internals", issue = "160728")] #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] -const trait LargestArgs: HomogeneousTuple { +const trait LargestArgs: HomogeneousTuple { /// Reduces all elements of a homogeneous tuple to its largest value. - fn largest(self) -> Self::Item; + fn largest(v1: T, args: Self) -> T; } /// Implements [`LargestArgs`] for a provided tuple if applicable. -macro impl_largest_args($($x:ident, $($($y:ident,)+)?)?) { - $( - #[unstable(feature = "cmp_splat_internals", issue = "160728")] - #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] - const impl LargestArgs for (T, $($(${ignore($y)}T,)+)?) - $(where T: [const] Destruct + [const] Ord, $(${ignore($y)})+)? - { - #[inline] - fn largest(self) -> Self::Item { - let ($x, $($($y,)+)?) = self; - $($(let $x = $x.max($y);)+)? - $x - } +macro impl_largest_args($($x:ident,)*) { + #[unstable(feature = "cmp_splat_internals", issue = "160728")] + #[rustc_const_unstable(feature = "cmp_splat_internals", issue = "160728")] + const impl LargestArgs for ($(${ignore($x)}T,)*) + where + T: [const] Destruct + [const] Ord, + { + #[inline(always)] // improves unoptimised codegen + fn largest(v1: T, ($($x,)*): Self) -> T { + v1$(.max($x))* } - )? + } } impl_tuples! { From d0706de50ad597884c2adec5ae8a0314481bb5bd Mon Sep 17 00:00:00 2001 From: Zac Harrold Date: Fri, 14 Aug 2026 15:27:39 +1000 Subject: [PATCH 0746/1309] Add `mir-opt` test documenting optimized MIR generated --- ....min_direct_u8.runtime-optimized.after.mir | 19 +++++++++++ ...in_splatted_u8.runtime-optimized.after.mir | 23 +++++++++++++ tests/mir-opt/pre-codegen/cmp_splat.rs | 33 +++++++++++++++++++ 3 files changed, 75 insertions(+) create mode 100644 tests/mir-opt/pre-codegen/cmp_splat.min_direct_u8.runtime-optimized.after.mir create mode 100644 tests/mir-opt/pre-codegen/cmp_splat.min_splatted_u8.runtime-optimized.after.mir create mode 100644 tests/mir-opt/pre-codegen/cmp_splat.rs diff --git a/tests/mir-opt/pre-codegen/cmp_splat.min_direct_u8.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/cmp_splat.min_direct_u8.runtime-optimized.after.mir new file mode 100644 index 0000000000000..16d011eeddf2b --- /dev/null +++ b/tests/mir-opt/pre-codegen/cmp_splat.min_direct_u8.runtime-optimized.after.mir @@ -0,0 +1,19 @@ +// MIR for `min_direct_u8` after runtime-optimized + +fn min_direct_u8(_1: u8, _2: u8) -> u8 { + debug x => _1; + debug y => _2; + let mut _0: u8; + scope 1 (inlined std::cmp::min::) { + scope 2 (inlined std::cmp::impls::::min) { + } + } + + bb0: { + _0 = integer_min::(move _1, move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } +} diff --git a/tests/mir-opt/pre-codegen/cmp_splat.min_splatted_u8.runtime-optimized.after.mir b/tests/mir-opt/pre-codegen/cmp_splat.min_splatted_u8.runtime-optimized.after.mir new file mode 100644 index 0000000000000..270d217153870 --- /dev/null +++ b/tests/mir-opt/pre-codegen/cmp_splat.min_splatted_u8.runtime-optimized.after.mir @@ -0,0 +1,23 @@ +// MIR for `min_splatted_u8` after runtime-optimized + +fn min_splatted_u8(_1: u8, _2: u8) -> u8 { + debug x => _1; + debug y => _2; + let mut _0: u8; + scope 1 (inlined smallest::) { + scope 2 (inlined <(u8,) as std::cmp::SmallestArgs>::smallest) { + scope 3 { + scope 4 (inlined std::cmp::impls::::min) { + } + } + } + } + + bb0: { + _0 = integer_min::(move _1, move _2) -> [return: bb1, unwind unreachable]; + } + + bb1: { + return; + } +} diff --git a/tests/mir-opt/pre-codegen/cmp_splat.rs b/tests/mir-opt/pre-codegen/cmp_splat.rs new file mode 100644 index 0000000000000..ac4d1989ff3c6 --- /dev/null +++ b/tests/mir-opt/pre-codegen/cmp_splat.rs @@ -0,0 +1,33 @@ +#![feature(cmp_splat)] + +// Comparing the MIR of a splat-compatible function with it's direct counterpart. +// This test is to ensure MIR optimizations are able to remove the added layers +// of indirection. + +// EMIT_MIR cmp_splat.min_direct_u8.runtime-optimized.after.mir +pub fn min_direct_u8(x: u8, y: u8) -> u8 { + // CHECK-LABEL: fn min_direct_u8( + // CHECK: debug x => _1; + // CHECK: debug y => _2; + // CHECK: bb0: { + // CHECK-NEXT: _0 = integer_min::(move _1, move _2) -> [return: bb1, unwind unreachable]; + // CHECK-NEXT: } + // CHECK: bb1: { + // CHECK-NEXT: return; + // CHECK-NEXT: } + std::cmp::min(x, y) +} + +// EMIT_MIR cmp_splat.min_splatted_u8.runtime-optimized.after.mir +pub fn min_splatted_u8(x: u8, y: u8) -> u8 { + // CHECK-LABEL: fn min_splatted_u8( + // CHECK: debug x => _1; + // CHECK: debug y => _2; + // CHECK: bb0: { + // CHECK-NEXT: _0 = integer_min::(move _1, move _2) -> [return: bb1, unwind unreachable]; + // CHECK-NEXT: } + // CHECK: bb1: { + // CHECK-NEXT: return; + // CHECK-NEXT: } + std::cmp::smallest(x, y) +} From 1e185bdebcd14907a6d868bcb99715b581117d04 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Sep 2026 16:45:41 +1000 Subject: [PATCH 0747/1309] Remove `StashKey::AssociatedTypeSuggestion` Currently it's used in a really hacky way: a diagnostic with an empty message and some suggestions is stashed. Later on it might be retrieved and its suggestions extracted. It uses `Level::Allow` so that it isn't printed by `emit_stashed_diagnostics` at shutdown if it hasn't been retrieved. This isn't a normal stashed diagnostic, more just a case of "save some information that might be useful for diagnostics later". We can record the information more simply and directly. This commit adds `paths_matching_assoc_types` fields to `Resolver` and `ResolverGlobalCtxt`. These store the spans of the paths of interest. The new subdiagnostic `AssocTypeWithSameName` is used to construct the relevant suggestions when they are needed. Much nicer. The old approach removed the stashed diagnostic and the new approach doesn't remove the set entry, so a single span could conceivably match more than once, presumably a good thing, though this doesn't show up in the test suite. --- compiler/rustc_errors/src/lib.rs | 1 - .../src/hir_ty_lowering/dyn_trait.rs | 21 ++++++++----------- compiler/rustc_middle/src/middle/resolve.rs | 3 +++ compiler/rustc_resolve/src/late.rs | 13 +++--------- compiler/rustc_resolve/src/lib.rs | 4 ++++ .../rustc_trait_selection/src/diagnostics.rs | 12 +++++++++++ .../traits/fulfillment_errors.rs | 19 +++++++++-------- 7 files changed, 41 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 25a82b22707cc..97b8557b95ef6 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -384,7 +384,6 @@ pub enum StashKey { /// FRU syntax MaybeFruTypo, CallAssocMethod, - AssociatedTypeSuggestion, UndeterminedMacroResolution, /// Used by `Parser::maybe_recover_trailing_expr` ExprInPat, diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs index a3cba8ce15fda..9123afd5986f5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/dyn_trait.rs @@ -2,10 +2,7 @@ use rustc_ast::TraitObjectSyntax; use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_errors::codes::*; -use rustc_errors::{ - Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, StashKey, Suggestions, - struct_span_code_err, -}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, struct_span_code_err}; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, HirId}; @@ -17,6 +14,7 @@ use rustc_middle::ty::{ }; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::{ErrorGuaranteed, Span}; +use rustc_trait_selection::diagnostics::AssocTypeWithSameName; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::error_reporting::traits::suggestions::NextTypeParamName; use rustc_trait_selection::traits; @@ -655,15 +653,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { poly_trait_ref.trait_ref.trait_def_id(), &mut diag, ); - // In case there is an associated type with the same name - // Add the suggestion to this error - if let Some(mut sugg) = - self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion) - && let Suggestions::Enabled(ref mut s1) = diag.suggestions - && let Suggestions::Enabled(ref mut s2) = sugg.suggestions + // If there is an associated type with the same name, add the suggestion to this error. + if self + .tcx() + .resolutions(()) + .paths_matching_assoc_types + .contains(&span.with_parent(None)) { - s1.append(s2); - sugg.cancel(); + diag.subdiagnostic(AssocTypeWithSameName { span: span.shrink_to_lo() }); } Some(diag.emit_err()) } else { diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs index 8267cde89ad27..491fec97db6c1 100644 --- a/compiler/rustc_middle/src/middle/resolve.rs +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -180,6 +180,9 @@ pub struct ResolverGlobalCtxt { /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. pub proc_macros: Vec, + /// Path spans where the ident matches an associated type for an enclosing trait. Used to + /// improve certain error messages. + pub paths_matching_assoc_types: UnordSet, /// Mapping from ident span to path span for paths that don't exist as written, but that /// exist under `std`. For example, wrote `str::from_utf8` instead of `std::str::from_utf8`. pub confused_type_with_std_module: FxIndexMap, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8c4a9babe2213..cb6642a696504 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -22,7 +22,7 @@ use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagArgValue, Diagnostic, ErrorGuaranteed, IntoDiagArg, MultiSpan, - StashKey, Suggestions, elided_lifetime_in_path_suggestion, pluralize, + Suggestions, elided_lifetime_in_path_suggestion, pluralize, }; use rustc_hir::def::Namespace::{self, *}; use rustc_hir::def::{CtorKind, DefKind, NonMacroAttrKind, PerNS}; @@ -4823,7 +4823,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { source, ) { Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => { - // if we also have an associated type that matches the ident, stash a suggestion + // If we also have an associated type that matches the ident, record that. if let Some(items) = self.diag_metadata.current_trait_assoc_items && let [Segment { ident, .. }] = path && items.iter().any(|item| { @@ -4836,14 +4836,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }) { - let mut diag = self.r.tcx.dcx().struct_allow(""); - diag.span_suggestion_verbose( - path_span.shrink_to_lo(), - "there is an associated type with the same name", - "Self::", - Applicability::MaybeIncorrect, - ); - diag.stash(path_span, StashKey::AssociatedTypeSuggestion); + self.r.paths_matching_assoc_types.insert(path_span.with_parent(None)); } if source.is_expected(res) || res == Res::Err { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7c80a892fa131..a913149733614 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1529,6 +1529,7 @@ pub struct Resolver<'ra, 'tcx> { /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. proc_macros: Vec = Vec::new(), + paths_matching_assoc_types: UnordSet, confused_type_with_std_module: FxIndexMap, /// Names of items that were stripped out via cfg with their corresponding cfg meta item. @@ -1892,6 +1893,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { invocation_parents, trait_impls: Default::default(), confused_type_with_std_module: Default::default(), + paths_matching_assoc_types: Default::default(), stripped_cfg_items: Default::default(), effective_visibilities: Default::default(), macro_reachable_adts: Default::default(), @@ -1970,6 +1972,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let glob_map = self.glob_map; let main_def = self.main_def; let confused_type_with_std_module = self.confused_type_with_std_module; + let paths_matching_assoc_types = self.paths_matching_assoc_types; let effective_visibilities = self.effective_visibilities; let stripped_cfg_items = self @@ -2000,6 +2003,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { trait_impls: self.trait_impls, proc_macros, confused_type_with_std_module, + paths_matching_assoc_types, doc_link_resolutions: self.doc_link_resolutions, doc_link_traits_in_scope: self.doc_link_traits_in_scope, all_macro_rules: self.all_macro_rules, diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 4b7be976cdb30..80ffbba041ccd 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -2083,3 +2083,15 @@ pub(crate) struct NonGenericOpaqueTypeParam<'a, 'tcx> { }")] pub param_span: Span, } + +#[derive(Subdiagnostic)] +#[suggestion( + "there is an associated type with the same name", + style = "verbose", + code = "Self::", + applicability = "maybe-incorrect" +)] +pub struct AssocTypeWithSameName { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 4cb5465b5bbee..062b087413e4f 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -13,8 +13,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::codes::*; use rustc_errors::{ - Applicability, Diag, ErrorGuaranteed, MultiSpan, StashKey, StringPart, Sublevel, Suggestions, - msg, pluralize, struct_span_code_err, + Applicability, Diag, ErrorGuaranteed, MultiSpan, StringPart, Sublevel, msg, pluralize, + struct_span_code_err, }; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_hir::intravisit::Visitor; @@ -42,7 +42,8 @@ use tracing::{debug, instrument}; use super::suggestions::get_explanation_based_on_obligation; use super::{ArgKind, CandidateSimilarity, GetSafeTransmuteErrorAndReason, ImplCandidate}; use crate::diagnostics::{ - ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, CoroClosureNotFn, + AssocTypeWithSameName, ClosureFnMutLabel, ClosureFnOnceLabel, ClosureKindMismatch, + CoroClosureNotFn, }; use crate::error_reporting::TypeErrCtxt; use crate::error_reporting::infer::TyCategory; @@ -3107,13 +3108,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); self.suggest_unsized_bound_if_applicable(err, obligation); if let Some(span) = err.span.primary_span() - && let Some(mut diag) = - self.dcx().steal_non_err(span, StashKey::AssociatedTypeSuggestion) - && let Suggestions::Enabled(ref mut s1) = err.suggestions - && let Suggestions::Enabled(ref mut s2) = diag.suggestions + && self + .tcx + .resolutions(()) + .paths_matching_assoc_types + .contains(&span.with_parent(None)) { - s1.append(s2); - diag.cancel() + err.subdiagnostic(AssocTypeWithSameName { span: span.shrink_to_lo() }); } } } From 983c56db1bbbd2111cbe3761bb039e007d706a1d Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 01:12:03 +0200 Subject: [PATCH 0748/1309] `rustc_dump_symbol_name`: add demangling information as a note instead --- compiler/rustc_symbol_mangling/src/test.rs | 9 +- .../doc_examples/rustc_dump_symbol_name.rs | 2 +- .../rustc_dump_symbol_name.stderr | 33 +- .../dyn-compat-symbol-mangling.rs | 4 +- .../dyn-compat-symbol-mangling.v0.stderr | 21 +- tests/ui/splat/splat-mangling.default.stderr | 154 ++--- tests/ui/splat/splat-mangling.legacy.stderr | 154 ++--- tests/ui/splat/splat-mangling.rs | 64 +- tests/ui/splat/splat-mangling.v0.stderr | 154 ++--- tests/ui/symbol-names/basic.legacy.stderr | 21 +- tests/ui/symbol-names/basic.rs | 8 +- tests/ui/symbol-names/basic.v0.stderr | 21 +- .../const-generics-demangling.legacy.stderr | 78 +-- .../symbol-names/const-generics-demangling.rs | 32 +- .../const-generics-demangling.v0.stderr | 78 +-- .../const-generics-str-demangling.rs | 24 +- .../const-generics-str-demangling.stderr | 116 ++-- .../const-generics-structural-demangling.rs | 35 +- ...onst-generics-structural-demangling.stderr | 176 ++---- tests/ui/symbol-names/foreign-types.rs | 4 +- tests/ui/symbol-names/foreign-types.stderr | 21 +- tests/ui/symbol-names/impl1.legacy.stderr | 59 +- tests/ui/symbol-names/impl1.rs | 24 +- tests/ui/symbol-names/impl1.v0.stderr | 59 +- .../ui/symbol-names/issue-60925.legacy.stderr | 21 +- tests/ui/symbol-names/issue-60925.rs | 8 +- tests/ui/symbol-names/issue-60925.v0.stderr | 21 +- .../ui/symbol-names/issue-75326.legacy.stderr | 21 +- tests/ui/symbol-names/issue-75326.rs | 8 +- tests/ui/symbol-names/issue-75326.v0.stderr | 21 +- tests/ui/symbol-names/trait-objects.rs | 12 +- tests/ui/symbol-names/trait-objects.v0.stderr | 59 +- tests/ui/symbol-names/types.legacy.stderr | 553 ++++++------------ tests/ui/symbol-names/types.rs | 232 ++++---- tests/ui/symbol-names/types.v0.stderr | 553 ++++++------------ .../symbol-names/types.verbose-legacy.stderr | 553 ++++++------------ 36 files changed, 1177 insertions(+), 2236 deletions(-) diff --git a/compiler/rustc_symbol_mangling/src/test.rs b/compiler/rustc_symbol_mangling/src/test.rs index 646a916fb5085..f9a17cd0c40ad 100644 --- a/compiler/rustc_symbol_mangling/src/test.rs +++ b/compiler/rustc_symbol_mangling/src/test.rs @@ -32,13 +32,16 @@ pub fn dump_symbol_names_and_def_paths(tcx: TyCtxt<'_>) { let args = tcx.erase_and_anonymize_regions(args); let instance = Instance::new_raw(def_id, args); let mangled = tcx.symbol_name(instance); + let def_span = tcx.def_span(def_id); + let span = span.to(def_span); - tcx.dcx().span_err(span, format!("symbol-name({mangled})")); + let mut err = tcx.dcx().struct_span_err(span, format!("symbol-name({mangled})")); if let Ok(demangling) = rustc_demangle::try_demangle(mangled.name) { - tcx.dcx().span_err(span, format!("demangling({demangling})")); - tcx.dcx().span_err(span, format!("demangling-alt({demangling:#})")); + err.note(format!("demangling({demangling})")); + err.note(format!("demangling-alt({demangling:#})")); } + err.emit_err(); } if let Some(&span) = find_attr!(tcx, id.def_id, RustcDumpDefPath(span) => span) { diff --git a/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.rs b/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.rs index 7c5750d1936db..ac62614bfe050 100644 --- a/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.rs +++ b/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.rs @@ -1,5 +1,5 @@ //@ dont-require-annotations: ERROR -//@ compile-flags: --crate-type lib -Z ui-testing=no +//@ compile-flags: --crate-type lib --crate-name crate_name -Z ui-testing=no //@ build-fail #![feature(rustc_attrs)] diff --git a/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.stderr b/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.stderr index a1d298909fae6..c97275b533331 100644 --- a/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.stderr +++ b/tests/ui/attributes/doc_examples/rustc_dump_symbol_name.stderr @@ -1,32 +1,27 @@ -error: symbol-name(_RNvCsCRATE_HASH_22rustc_dump_symbol_name7mangled) +error: symbol-name(_RNvCsCRATE_HASH_10crate_name7mangled) --> $DIR/rustc_dump_symbol_name.rs:7:1 | -7 | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(rustc_dump_symbol_name[6981ee133444a33d]::mangled) - --> $DIR/rustc_dump_symbol_name.rs:7:1 - | -7 | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(rustc_dump_symbol_name::mangled) - --> $DIR/rustc_dump_symbol_name.rs:7:1 +7 | / #[rustc_dump_symbol_name] +8 | | fn mangled() {} + | |____________^ | -7 | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(crate_name[8cfd4c3bf0e8f389]::mangled) + = note: demangling-alt(crate_name::mangled) error: symbol-name(no_mangle) --> $DIR/rustc_dump_symbol_name.rs:10:1 | -10 | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +10 | / #[rustc_dump_symbol_name] +11 | | #[unsafe(no_mangle)] +12 | | fn no_mangle() {} + | |______________^ error: symbol-name(abort) --> $DIR/rustc_dump_symbol_name.rs:15:5 | -15 | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +15 | / #[rustc_dump_symbol_name] +16 | | fn abort(); + | |_______________^ -error: aborting due to 5 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs index d467d5e0def02..2a28022b8844e 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs @@ -21,8 +21,8 @@ trait Trait { #[rustc_dump_symbol_name] //~^ ERROR symbol-name(_RMCs -//~| ERROR demangling(>) +//~| NOTE demangling(>) impl dyn Trait {} fn main() {} diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr index d87ed6292608e..945b005e10c50 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.v0.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RMCsCRATE_HASH_3symDNtB_5Traitp1NKj0_EL_) --> $DIR/dyn-compat-symbol-mangling.rs:22:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/dyn-compat-symbol-mangling.rs:22:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/dyn-compat-symbol-mangling.rs:22:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl dyn Trait {} + | |_____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/splat/splat-mangling.default.stderr b/tests/ui/splat/splat-mangling.default.stderr index ebe82cea89b62..d57d73ff019c2 100644 --- a/tests/ui/splat/splat-mangling.default.stderr +++ b/tests/ui/splat/splat-mangling.default.stderr @@ -1,146 +1,90 @@ error: symbol-name(_RMNvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwThmEEuE) --> $DIR/splat-mangling.rs:22:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:22:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:22:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFThmEEuE) --> $DIR/splat-mangling.rs:32:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:32:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:32:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs0_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTThmEEEuE) --> $DIR/splat-mangling.rs:42:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:42:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:42:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |______________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs1_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTThmEEEuE) --> $DIR/splat-mangling.rs:52:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:52:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:52:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_______________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs2_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFwTmaEEuE) --> $DIR/splat-mangling.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn(#[rustc_splat] (u32, i8))> {} + | |__________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs3_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFTmaEEuE) --> $DIR/splat-mangling.rs:72:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:72:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:72:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn((u32, i8))> {} + | |___________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs4_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTmaEdEuE) --> $DIR/splat-mangling.rs:82:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:82:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:82:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs5_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTmaEdEuE) --> $DIR/splat-mangling.rs:92:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:92:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:92:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 24 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/splat/splat-mangling.legacy.stderr b/tests/ui/splat/splat-mangling.legacy.stderr index 526fd04f0f951..17525117e687e 100644 --- a/tests/ui/splat/splat-mangling.legacy.stderr +++ b/tests/ui/splat/splat-mangling.legacy.stderr @@ -1,146 +1,90 @@ error: symbol-name(_ZN14splat_mangling4main72Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u8$C$u32$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:22:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:22:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:22:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) error: symbol-name(_ZN14splat_mangling4main38Type$LT$fn$LP$$LP$u8$C$u32$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:32:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:32:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:32:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) error: symbol-name(_ZN14splat_mangling4main83Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$$LP$u8$C$u32$RP$$C$$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:42:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:42:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:42:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |______________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) error: symbol-name(_ZN14splat_mangling4main49Type$LT$fn$LP$$LP$$LP$u8$C$u32$RP$$C$$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:52:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:52:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:52:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_______________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) error: symbol-name(_ZN14splat_mangling4main86Type$LT$$BP$const$u20$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u32$C$i8$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>::hCRATE_HASH) - --> $DIR/splat-mangling.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>) - --> $DIR/splat-mangling.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn(#[rustc_splat] (u32, i8))> {} + | |__________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>) error: symbol-name(_ZN14splat_mangling4main52Type$LT$$BP$const$u20$fn$LP$$LP$u32$C$i8$RP$$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:72:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type<*const fn((u32,i8))>::hCRATE_HASH) - --> $DIR/splat-mangling.rs:72:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type<*const fn((u32,i8))>) - --> $DIR/splat-mangling.rs:72:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn((u32, i8))> {} + | |___________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type<*const fn((u32,i8))>::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type<*const fn((u32,i8))>) error: symbol-name(_ZN14splat_mangling4main78Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u32$C$i8$RP$$C$f64$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:82:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:82:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:82:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) error: symbol-name(_ZN14splat_mangling4main44Type$LT$fn$LP$$LP$u32$C$i8$RP$$C$f64$RP$$GT$17hCRATE_HASHE) --> $DIR/splat-mangling.rs:92:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(splat_mangling::main::Type::hCRATE_HASH) - --> $DIR/splat-mangling.rs:92:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(splat_mangling::main::Type) - --> $DIR/splat-mangling.rs:92:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(splat_mangling::main::Type::hCRATE_HASH) + = note: demangling-alt(splat_mangling::main::Type) -error: aborting due to 24 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/splat/splat-mangling.rs b/tests/ui/splat/splat-mangling.rs index b6e2fd3ecd47e..982d070199c7d 100644 --- a/tests/ui/splat/splat-mangling.rs +++ b/tests/ui/splat/splat-mangling.rs @@ -21,80 +21,80 @@ fn main() { // FIXME(splat, legacy mangling): the first comma is in the wrong place #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main72Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u8$C$u32$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMNvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwThmEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main38Type$LT$fn$LP$$LP$u8$C$u32$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMs_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFThmEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main83Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$$LP$u8$C$u32$RP$$C$$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMs0_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTThmEEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main49Type$LT$fn$LP$$LP$$LP$u8$C$u32$RP$$C$$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMs1_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTThmEEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main86Type$LT$$BP$const$u20$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u32$C$i8$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>) + //[legacy]~| NOTE demangling(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type<*const fn(, #[rustc_splat](u32,i8))>) //[v0,default]~^^^^ ERROR symbol-name(_RMs2_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFwTmaEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type<*const fn(#[rustc_splat] (u32, i8))> {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main52Type$LT$$BP$const$u20$fn$LP$$LP$u32$C$i8$RP$$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type<*const fn((u32,i8))>:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type<*const fn((u32,i8))>) + //[legacy]~| NOTE demangling(splat_mangling::main::Type<*const fn((u32,i8))>:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type<*const fn((u32,i8))>) //[v0,default]~^^^^ ERROR symbol-name(_RMs3_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFTmaEEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type<*const fn((u32, i8))> {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main78Type$LT$fn$LP$$C$$u20$$u23$$u5b$rustc_splat$u5d$$LP$u32$C$i8$RP$$C$f64$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMs4_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTmaEdEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} #[rustfmt::skip] #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN14splat_mangling4main44Type$LT$fn$LP$$LP$u32$C$i8$RP$$C$f64$RP$$GT - //[legacy]~| ERROR demangling(splat_mangling::main::Type:: - //[legacy]~| ERROR demangling-alt(splat_mangling::main::Type) + //[legacy]~| NOTE demangling(splat_mangling::main::Type:: + //[legacy]~| NOTE demangling-alt(splat_mangling::main::Type) //[v0,default]~^^^^ ERROR symbol-name(_RMs5_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTmaEdEuE) - //[v0,default]~| ERROR demangling(>) + //[v0,default]~| NOTE demangling(>) impl Type {} } diff --git a/tests/ui/splat/splat-mangling.v0.stderr b/tests/ui/splat/splat-mangling.v0.stderr index ebe82cea89b62..d57d73ff019c2 100644 --- a/tests/ui/splat/splat-mangling.v0.stderr +++ b/tests/ui/splat/splat-mangling.v0.stderr @@ -1,146 +1,90 @@ error: symbol-name(_RMNvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwThmEEuE) --> $DIR/splat-mangling.rs:22:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:22:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:22:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFThmEEuE) --> $DIR/splat-mangling.rs:32:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:32:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:32:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs0_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTThmEEEuE) --> $DIR/splat-mangling.rs:42:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:42:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:42:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |______________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs1_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTThmEEEuE) --> $DIR/splat-mangling.rs:52:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:52:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:52:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_______________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs2_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFwTmaEEuE) --> $DIR/splat-mangling.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn(#[rustc_splat] (u32, i8))> {} + | |__________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs3_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypePFTmaEEuE) --> $DIR/splat-mangling.rs:72:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:72:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:72:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const fn((u32, i8))> {} + | |___________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs4_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFwTmaEdEuE) --> $DIR/splat-mangling.rs:82:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:82:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:82:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs5_NvCsCRATE_HASH_14splat_mangling4mainINtB_4TypeFTmaEdEuE) --> $DIR/splat-mangling.rs:92:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/splat-mangling.rs:92:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/splat-mangling.rs:92:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 24 previous errors +error: aborting due to 8 previous errors diff --git a/tests/ui/symbol-names/basic.legacy.stderr b/tests/ui/symbol-names/basic.legacy.stderr index 9c30ebdf30b88..a50a7702a7f29 100644 --- a/tests/ui/symbol-names/basic.legacy.stderr +++ b/tests/ui/symbol-names/basic.legacy.stderr @@ -1,20 +1,13 @@ error: symbol-name(_ZN5basic4main17hd30beb15618b9d64E) --> $DIR/basic.rs:8:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(basic::main::hd30beb15618b9d64) - --> $DIR/basic.rs:8:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(basic::main) - --> $DIR/basic.rs:8:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn main() { + | |_________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(basic::main::hd30beb15618b9d64) + = note: demangling-alt(basic::main) error: def-path(main) --> $DIR/basic.rs:15:1 @@ -22,5 +15,5 @@ error: def-path(main) LL | #[rustc_dump_def_path] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/symbol-names/basic.rs b/tests/ui/symbol-names/basic.rs index d4c23f988384a..bd717f3edd077 100644 --- a/tests/ui/symbol-names/basic.rs +++ b/tests/ui/symbol-names/basic.rs @@ -7,11 +7,11 @@ #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN5basic4main -//[legacy]~| ERROR demangling(basic::main -//[legacy]~| ERROR demangling-alt(basic::main) +//[legacy]~| NOTE demangling(basic::main +//[legacy]~| NOTE demangling-alt(basic::main) //[v0]~^^^^ ERROR symbol-name(_RNv - //[v0]~| ERROR demangling(basic[ - //[v0]~| ERROR demangling-alt(basic::main) + //[v0]~| NOTE demangling(basic[ + //[v0]~| NOTE demangling-alt(basic::main) #[rustc_dump_def_path] //[legacy]~^ ERROR def-path(main) //[v0]~^^ ERROR def-path(main) diff --git a/tests/ui/symbol-names/basic.v0.stderr b/tests/ui/symbol-names/basic.v0.stderr index 6a9da17eebe03..d4df8d74ca5f8 100644 --- a/tests/ui/symbol-names/basic.v0.stderr +++ b/tests/ui/symbol-names/basic.v0.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RNvCsCRATE_HASH_5basic4main) --> $DIR/basic.rs:8:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(basic[a90d658f4748b9d1]::main) - --> $DIR/basic.rs:8:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(basic::main) - --> $DIR/basic.rs:8:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn main() { + | |_________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(basic[a90d658f4748b9d1]::main) + = note: demangling-alt(basic::main) error: def-path(main) --> $DIR/basic.rs:15:1 @@ -22,5 +15,5 @@ error: def-path(main) LL | #[rustc_dump_def_path] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 4 previous errors +error: aborting due to 2 previous errors diff --git a/tests/ui/symbol-names/const-generics-demangling.legacy.stderr b/tests/ui/symbol-names/const-generics-demangling.legacy.stderr index a2331da13c414..de3fbf0443585 100644 --- a/tests/ui/symbol-names/const-generics-demangling.legacy.stderr +++ b/tests/ui/symbol-names/const-generics-demangling.legacy.stderr @@ -1,74 +1,46 @@ error: symbol-name(_ZN1c21Unsigned$LT$11_u8$GT$1f17h[HASH]E) --> $DIR/const-generics-demangling.rs:13:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(c::Unsigned<11_u8>::f::h[HASH]) - --> $DIR/const-generics-demangling.rs:13:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(c::Unsigned<11_u8>::f) - --> $DIR/const-generics-demangling.rs:13:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(c::Unsigned<11_u8>::f::h[HASH]) + = note: demangling-alt(c::Unsigned<11_u8>::f) error: symbol-name(_ZN1c22Signed$LT$.152_i16$GT$1f17h[HASH]E) --> $DIR/const-generics-demangling.rs:26:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(c::Signed<.152_i16>::f::h[HASH]) - --> $DIR/const-generics-demangling.rs:26:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(c::Signed<.152_i16>::f) - --> $DIR/const-generics-demangling.rs:26:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(c::Signed<.152_i16>::f::h[HASH]) + = note: demangling-alt(c::Signed<.152_i16>::f) error: symbol-name(_ZN1c13Bool$LT$_$GT$1f17h[HASH]E) --> $DIR/const-generics-demangling.rs:39:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(c::Bool<_>::f::h[HASH]) - --> $DIR/const-generics-demangling.rs:39:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(c::Bool<_>::f) - --> $DIR/const-generics-demangling.rs:39:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(c::Bool<_>::f::h[HASH]) + = note: demangling-alt(c::Bool<_>::f) error: symbol-name(_ZN1c13Char$LT$_$GT$1f17h[HASH]E) --> $DIR/const-generics-demangling.rs:52:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(c::Char<_>::f::h[HASH]) - --> $DIR/const-generics-demangling.rs:52:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(c::Char<_>::f) - --> $DIR/const-generics-demangling.rs:52:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(c::Char<_>::f::h[HASH]) + = note: demangling-alt(c::Char<_>::f) -error: aborting due to 12 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/symbol-names/const-generics-demangling.rs b/tests/ui/symbol-names/const-generics-demangling.rs index e32ab180fab28..7a0c4bd8ccb37 100644 --- a/tests/ui/symbol-names/const-generics-demangling.rs +++ b/tests/ui/symbol-names/const-generics-demangling.rs @@ -12,11 +12,11 @@ pub struct Unsigned; impl Unsigned<11> { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name(_RNvMCs - //[v0]~| ERROR demangling(>::f) + //[v0]~| NOTE demangling(>::f) //[legacy]~^^^^ ERROR symbol-name(_ZN1c21Unsigned$LT$11_u8$GT$ - //[legacy]~| ERROR demangling(c::Unsigned<11_u8>::f:: - //[legacy]~| ERROR demangling-alt(c::Unsigned<11_u8>::f) + //[legacy]~| NOTE demangling(c::Unsigned<11_u8>::f:: + //[legacy]~| NOTE demangling-alt(c::Unsigned<11_u8>::f) fn f() {} } @@ -25,11 +25,11 @@ pub struct Signed; impl Signed<-152> { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name(_RNvMs_Cs - //[v0]~| ERROR demangling(>::f) + //[v0]~| NOTE demangling(>::f) //[legacy]~^^^^ ERROR symbol-name(_ZN1c22Signed$LT$.152_i16$GT$ - //[legacy]~| ERROR demangling(c::Signed<.152_i16>::f:: - //[legacy]~| ERROR demangling-alt(c::Signed<.152_i16>::f) + //[legacy]~| NOTE demangling(c::Signed<.152_i16>::f:: + //[legacy]~| NOTE demangling-alt(c::Signed<.152_i16>::f) fn f() {} } @@ -38,11 +38,11 @@ pub struct Bool; impl Bool { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name(_RNvMs0_Cs - //[v0]~| ERROR demangling(>::f) + //[v0]~| NOTE demangling(>::f) //[legacy]~^^^^ ERROR symbol-name(_ZN1c13Bool$LT$_$GT$ - //[legacy]~| ERROR demangling(c::Bool<_>::f:: - //[legacy]~| ERROR demangling-alt(c::Bool<_>::f) + //[legacy]~| NOTE demangling(c::Bool<_>::f:: + //[legacy]~| NOTE demangling-alt(c::Bool<_>::f) fn f() {} } @@ -51,11 +51,11 @@ pub struct Char; impl Char<'∂'> { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name(_RNvMs1_Cs - //[v0]~| ERROR demangling(>::f) + //[v0]~| NOTE demangling(>::f) //[legacy]~^^^^ ERROR symbol-name(_ZN1c13Char$LT$_$GT$ - //[legacy]~| ERROR demangling(c::Char<_>::f:: - //[legacy]~| ERROR demangling-alt(c::Char<_>::f) + //[legacy]~| NOTE demangling(c::Char<_>::f:: + //[legacy]~| NOTE demangling-alt(c::Char<_>::f) fn f() {} } diff --git a/tests/ui/symbol-names/const-generics-demangling.v0.stderr b/tests/ui/symbol-names/const-generics-demangling.v0.stderr index 25fe5873389e7..8e69a1a1d80ea 100644 --- a/tests/ui/symbol-names/const-generics-demangling.v0.stderr +++ b/tests/ui/symbol-names/const-generics-demangling.v0.stderr @@ -1,74 +1,46 @@ error: symbol-name(_RNvMCsCRATE_HASH_1cINtB_8UnsignedKhb_E1f) --> $DIR/const-generics-demangling.rs:13:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>::f) - --> $DIR/const-generics-demangling.rs:13:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>::f) - --> $DIR/const-generics-demangling.rs:13:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>::f) + = note: demangling-alt(>::f) error: symbol-name(_RNvMs_CsCRATE_HASH_1cINtB_6SignedKsn98_E1f) --> $DIR/const-generics-demangling.rs:26:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>::f) - --> $DIR/const-generics-demangling.rs:26:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>::f) - --> $DIR/const-generics-demangling.rs:26:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>::f) + = note: demangling-alt(>::f) error: symbol-name(_RNvMs0_CsCRATE_HASH_1cINtB_4BoolKb1_E1f) --> $DIR/const-generics-demangling.rs:39:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>::f) - --> $DIR/const-generics-demangling.rs:39:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>::f) - --> $DIR/const-generics-demangling.rs:39:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>::f) + = note: demangling-alt(>::f) error: symbol-name(_RNvMs1_CsCRATE_HASH_1cINtB_4CharKc2202_E1f) --> $DIR/const-generics-demangling.rs:52:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>::f) - --> $DIR/const-generics-demangling.rs:52:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>::f) - --> $DIR/const-generics-demangling.rs:52:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn f() {} + | |__________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>::f) + = note: demangling-alt(>::f) -error: aborting due to 12 previous errors +error: aborting due to 4 previous errors diff --git a/tests/ui/symbol-names/const-generics-str-demangling.rs b/tests/ui/symbol-names/const-generics-str-demangling.rs index 90a79fd5bf7d9..789034283d956 100644 --- a/tests/ui/symbol-names/const-generics-str-demangling.rs +++ b/tests/ui/symbol-names/const-generics-str-demangling.rs @@ -8,38 +8,38 @@ pub struct Str; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"abc"> {} #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"'"> {} #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"\t\n"> {} #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"∂ü"> {} #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"საჭმელად_გემრიელი_სადილი"> {} #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜"> {} fn main() {} diff --git a/tests/ui/symbol-names/const-generics-str-demangling.stderr b/tests/ui/symbol-names/const-generics-str-demangling.stderr index 09c3f7ca743fa..7221b89a7c7a8 100644 --- a/tests/ui/symbol-names/const-generics-str-demangling.stderr +++ b/tests/ui/symbol-names/const-generics-str-demangling.stderr @@ -1,110 +1,68 @@ error: symbol-name(_RMCsCRATE_HASH_1cINtB_3StrKRe616263_E) --> $DIR/const-generics-str-demangling.rs:9:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:9:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:9:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"abc"> {} + | |_______________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs_CsCRATE_HASH_1cINtB_3StrKRe27_E) --> $DIR/const-generics-str-demangling.rs:15:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:15:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"'"> {} + | |_____________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:15:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs0_CsCRATE_HASH_1cINtB_3StrKRe090a_E) --> $DIR/const-generics-str-demangling.rs:21:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:21:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:21:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"\t\n"> {} + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs1_CsCRATE_HASH_1cINtB_3StrKRee28882c3bc_E) --> $DIR/const-generics-str-demangling.rs:27:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:27:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:27:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"∂ü"> {} + | |______________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs2_CsCRATE_HASH_1cINtB_3StrKRee183a1e18390e183ade1839be18394e1839ae18390e183935fe18392e18394e1839be183a0e18398e18394e1839ae183985fe183a1e18390e18393e18398e1839ae18398_E) --> $DIR/const-generics-str-demangling.rs:33:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:33:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"საჭმელად_გემრიელი_სადილი"> {} + | |____________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:33:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs3_CsCRATE_HASH_1cINtB_3StrKRef09f908af09fa688f09fa686f09f90ae20c2a720f09f90b6f09f9192e29895f09f94a520c2a720f09fa7a1f09f929bf09f929af09f9299f09f929c_E) --> $DIR/const-generics-str-demangling.rs:39:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-str-demangling.rs:39:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-str-demangling.rs:39:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Str<"🐊🦈🦆🐮 § 🐶👒☕🔥 § 🧡💛💚💙💜"> {} + | |____________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 18 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.rs b/tests/ui/symbol-names/const-generics-structural-demangling.rs index a9a11d0ea8a4f..467861c4b8348 100644 --- a/tests/ui/symbol-names/const-generics-structural-demangling.rs +++ b/tests/ui/symbol-names/const-generics-structural-demangling.rs @@ -12,8 +12,8 @@ pub struct RefByte; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl RefByte<{ &123 }> {} // FIXME(eddyb) this was supposed to be `RefMutZst` with `&mut []`, @@ -22,24 +22,24 @@ pub struct RefZst; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl RefZst<{ &[] }> {} pub struct Array3Bytes; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Array3Bytes<{ [1, 2, 3] }> {} pub struct TupleByteBool; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl TupleByteBool<{ (1, false) }> {} #[derive(PartialEq, Eq, ConstParamTy)] @@ -54,16 +54,16 @@ pub struct OptionUsize>; // the `core` disambiguator hash away there, but not here. #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(::None}>>) +//~| NOTE demangling +//~| NOTE demangling-alt(::None}>>) impl OptionUsize<{ MyOption::None }> {} // HACK(eddyb) the full mangling is only in `.stderr` because we can normalize // the `core` disambiguator hash away there, but not here. #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(::Some(0)}>>) +//~| NOTE demangling +//~| NOTE demangling-alt(::Some(0)}>>) impl OptionUsize<{ MyOption::Some(0) }> {} #[derive(PartialEq, Eq, ConstParamTy)] @@ -76,8 +76,8 @@ pub struct Foo_; #[rustc_dump_symbol_name] //~^ ERROR symbol-name -//~| ERROR demangling -//~| ERROR demangling-alt(>) +//~| NOTE demangling +//~| NOTE demangling-alt(>) impl Foo_<{ Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] } }> {} // NOTE(eddyb) this tests specifically the use of disambiguators in field names, @@ -92,10 +92,13 @@ macro duplicate_field_name_test($x:ident) { #[rustc_dump_symbol_name] //~^ ERROR symbol-name - //~| ERROR demangling - //~| ERROR demangling-alt(>) + //~| NOTE demangling + //~| NOTE demangling-alt(>) impl Bar_<{ Bar { $x: 123, x: 4096 } }> {} } duplicate_field_name_test!(x); +//~^ NOTE in this expansion +//~| NOTE in this expansion +//~| NOTE in this expansion fn main() {} diff --git a/tests/ui/symbol-names/const-generics-structural-demangling.stderr b/tests/ui/symbol-names/const-generics-structural-demangling.stderr index 19deb1af31418..f018629879bac 100644 --- a/tests/ui/symbol-names/const-generics-structural-demangling.stderr +++ b/tests/ui/symbol-names/const-generics-structural-demangling.stderr @@ -1,161 +1,95 @@ error: symbol-name(_RMCsCRATE_HASH_1cINtB_7RefByteKRh7b_E) --> $DIR/const-generics-structural-demangling.rs:13:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:13:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:13:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl RefByte<{ &123 }> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs_CsCRATE_HASH_1cINtB_6RefZstKRAEE) --> $DIR/const-generics-structural-demangling.rs:23:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:23:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:23:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl RefZst<{ &[] }> {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs0_CsCRATE_HASH_1cINtB_11Array3BytesKAh1_h2_h3_EE) --> $DIR/const-generics-structural-demangling.rs:31:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:31:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:31:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Array3Bytes<{ [1, 2, 3] }> {} + | |_______________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs1_CsCRATE_HASH_1cINtB_13TupleByteBoolKTh1_b0_EE) --> $DIR/const-generics-structural-demangling.rs:39:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:39:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:39:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl TupleByteBool<{ (1, false) }> {} + | |__________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs2_CsCRATE_HASH_1cINtB_11OptionUsizeKVNtINtB_8MyOptionjE4NoneUE) --> $DIR/const-generics-structural-demangling.rs:55:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(::None}>>) - --> $DIR/const-generics-structural-demangling.rs:55:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl OptionUsize<{ MyOption::None }> {} + | |____________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(::None}>>) - --> $DIR/const-generics-structural-demangling.rs:55:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(::None}>>) + = note: demangling-alt(::None}>>) error: symbol-name(_RMs3_CsCRATE_HASH_1cINtB_11OptionUsizeKVNtINtB_8MyOptionjE4SomeTj0_EE) --> $DIR/const-generics-structural-demangling.rs:63:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(::Some(0usize)}>>) - --> $DIR/const-generics-structural-demangling.rs:63:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(::Some(0)}>>) - --> $DIR/const-generics-structural-demangling.rs:63:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl OptionUsize<{ MyOption::Some(0) }> {} + | |_______________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(::Some(0usize)}>>) + = note: demangling-alt(::Some(0)}>>) error: symbol-name(_RMs4_CsCRATE_HASH_1cINtB_4Foo_KVNtB_3FooS1sRe616263_2chc78_5sliceRAh1_h2_h3_EEE) --> $DIR/const-generics-structural-demangling.rs:77:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:77:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:77:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Foo_<{ Foo { s: "abc", ch: 'x', slice: &[1, 2, 3] } }> {} + | |___________________________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsd_CsCRATE_HASH_1cINtB_4Bar_KVNtB_3BarS1xh7b_s_1xt1000_EE) --> $DIR/const-generics-structural-demangling.rs:93:5 | -LL | macro duplicate_field_name_test($x:ident) { -... -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | macro duplicate_field_name_test($x:ident) { ... -LL | duplicate_field_name_test!(x); - | ----------------------------- in this macro invocation - -error: demangling(>) - --> $DIR/const-generics-structural-demangling.rs:93:5 - | -LL | macro duplicate_field_name_test($x:ident) { -... -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | duplicate_field_name_test!(x); - | ----------------------------- in this macro invocation - -error: demangling-alt(>) - --> $DIR/const-generics-structural-demangling.rs:93:5 - | -LL | macro duplicate_field_name_test($x:ident) { -... -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ -... -LL | duplicate_field_name_test!(x); - | ----------------------------- in this macro invocation - -error: aborting due to 24 previous errors +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Bar_<{ Bar { $x: 123, x: 4096 } }> {} + | |___________________________________________^ +LL | } +LL | duplicate_field_name_test!(x); + | ----------------------------- in this macro invocation + | + = note: demangling(>) + = note: demangling-alt(>) + +error: aborting due to 8 previous errors diff --git a/tests/ui/symbol-names/foreign-types.rs b/tests/ui/symbol-names/foreign-types.rs index b7851a06ed067..32337f0455cae 100644 --- a/tests/ui/symbol-names/foreign-types.rs +++ b/tests/ui/symbol-names/foreign-types.rs @@ -15,8 +15,8 @@ struct Check(T); #[rustc_dump_symbol_name] //~^ ERROR symbol-name(_RMCs -//~| ERROR demangling(>) +//~| NOTE demangling(>) impl Check {} fn main() {} diff --git a/tests/ui/symbol-names/foreign-types.stderr b/tests/ui/symbol-names/foreign-types.stderr index b0af84801795f..7c1c6b2c5f540 100644 --- a/tests/ui/symbol-names/foreign-types.stderr +++ b/tests/ui/symbol-names/foreign-types.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RMCsCRATE_HASH_13foreign_typesINtB_5CheckNtB_11ForeignTypeE) --> $DIR/foreign-types.rs:16:1 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/foreign-types.rs:16:1 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/foreign-types.rs:16:1 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Check {} + | |_______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/symbol-names/impl1.legacy.stderr b/tests/ui/symbol-names/impl1.legacy.stderr index 87a2837e01920..72b6ecb73b52f 100644 --- a/tests/ui/symbol-names/impl1.legacy.stderr +++ b/tests/ui/symbol-names/impl1.legacy.stderr @@ -1,20 +1,13 @@ error: symbol-name(_ZN5impl13foo3Foo3bar17) --> $DIR/impl1.rs:14:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(impl1::foo::Foo::bar::) - --> $DIR/impl1.rs:14:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(impl1::foo::Foo::bar) - --> $DIR/impl1.rs:14:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn bar() { } + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(impl1::foo::Foo::bar::) + = note: demangling-alt(impl1::foo::Foo::bar) error: def-path(foo::Foo::bar) --> $DIR/impl1.rs:21:9 @@ -25,20 +18,13 @@ LL | #[rustc_dump_def_path] error: symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz17) --> $DIR/impl1.rs:32:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(impl1::bar::::baz::) - --> $DIR/impl1.rs:32:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn baz() { } + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(impl1::bar::::baz) - --> $DIR/impl1.rs:32:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(impl1::bar::::baz::) + = note: demangling-alt(impl1::bar::::baz) error: def-path(bar::::baz) --> $DIR/impl1.rs:39:9 @@ -49,20 +35,13 @@ LL | #[rustc_dump_def_path] error: symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method17) --> $DIR/impl1.rs:62:13 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::) - --> $DIR/impl1.rs:62:13 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) - --> $DIR/impl1.rs:62:13 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn method(&self) {} + | |____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method::) + = note: demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:69:13 @@ -70,5 +49,5 @@ error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTra LL | #[rustc_dump_def_path] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/symbol-names/impl1.rs b/tests/ui/symbol-names/impl1.rs index 5902df54b486f..be2ce5f82a1e4 100644 --- a/tests/ui/symbol-names/impl1.rs +++ b/tests/ui/symbol-names/impl1.rs @@ -13,11 +13,11 @@ mod foo { impl Foo { #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN5impl13foo3Foo3bar - //[legacy]~| ERROR demangling(impl1::foo::Foo::bar - //[legacy]~| ERROR demangling-alt(impl1::foo::Foo::bar) + //[legacy]~| NOTE demangling(impl1::foo::Foo::bar + //[legacy]~| NOTE demangling-alt(impl1::foo::Foo::bar) //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs - //[v0]~| ERROR demangling(::bar) + //[v0]~| NOTE demangling(::bar) #[rustc_dump_def_path] //[legacy]~^ ERROR def-path(foo::Foo::bar) //[v0]~^^ ERROR def-path(foo::Foo::bar) @@ -31,11 +31,11 @@ mod bar { impl Foo { #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN5impl13bar33_$LT$impl$u20$impl1..foo..Foo$GT$3baz - //[legacy]~| ERROR demangling(impl1::bar::::baz - //[legacy]~| ERROR demangling-alt(impl1::bar::::baz) + //[legacy]~| NOTE demangling(impl1::bar::::baz + //[legacy]~| NOTE demangling-alt(impl1::bar::::baz) //[v0]~^^^^ ERROR symbol-name(_RNvMNtCs - //[v0]~| ERROR demangling(::baz) + //[v0]~| NOTE demangling(::baz) #[rustc_dump_def_path] //[legacy]~^ ERROR def-path(bar::::baz) //[v0]~^^ ERROR def-path(bar::::baz) @@ -61,11 +61,11 @@ fn main() { impl Bar for [&'_ (dyn Foo + AutoTrait); 3] { #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN209_$LT$$u5b$$RF$dyn$u20$impl1..Foo$u2b$Assoc$u20$$u3d$$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RF$u8$C$$u20$...$RP$$u2b$impl1..AutoTrait$u3b$$u20$3$u5d$$u20$as$u20$impl1..main..$u7b$$u7b$closure$u7d$$u7d$..Bar$GT$6method - //[legacy]~| ERROR demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method - //[legacy]~| ERROR demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) + //[legacy]~| NOTE demangling(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method + //[legacy]~| NOTE demangling-alt(<[&dyn impl1::Foo+Assoc = extern "C" fn(&u8, ::.)+impl1::AutoTrait; 3] as impl1::main::{{closure}}::Bar>::method) //[v0]~^^^^ ERROR symbol-name(_RNvXNCNvCs - //[v0]~| ERROR demangling(<[&dyn - //[v0]~| ERROR demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) + //[v0]~| NOTE demangling(<[&dyn + //[v0]~| NOTE demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) #[rustc_dump_def_path] //[legacy]~^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) //[v0]~^^ ERROR def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) diff --git a/tests/ui/symbol-names/impl1.v0.stderr b/tests/ui/symbol-names/impl1.v0.stderr index 77319825b1770..95c01cdeef4fd 100644 --- a/tests/ui/symbol-names/impl1.v0.stderr +++ b/tests/ui/symbol-names/impl1.v0.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13fooNtB_3Foo3bar) --> $DIR/impl1.rs:14:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(::bar) - --> $DIR/impl1.rs:14:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(::bar) - --> $DIR/impl1.rs:14:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn bar() { } + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(::bar) + = note: demangling-alt(::bar) error: def-path(foo::Foo::bar) --> $DIR/impl1.rs:21:9 @@ -25,20 +18,13 @@ LL | #[rustc_dump_def_path] error: symbol-name(_RNvMNtCsCRATE_HASH_5impl13barNtNtB_3foo3Foo3baz) --> $DIR/impl1.rs:32:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(::baz) - --> $DIR/impl1.rs:32:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn baz() { } + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(::baz) - --> $DIR/impl1.rs:32:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(::baz) + = note: demangling-alt(::baz) error: def-path(bar::::baz) --> $DIR/impl1.rs:39:9 @@ -49,20 +35,13 @@ LL | #[rustc_dump_def_path] error: symbol-name(_RNvXNCNvCsCRATE_HASH_5impl14mains_0ARDNtB_3Foop5AssocFG_KCRL0_hvEuNtB_9AutoTraitEL_j3_NtB_3Bar6method) --> $DIR/impl1.rs:62:13 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<[&dyn impl1[d5591eb39db23cbb]::Foo extern "C" fn(&'a u8, ...)> + impl1[d5591eb39db23cbb]::AutoTrait; 3usize] as impl1[d5591eb39db23cbb]::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:62:13 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) - --> $DIR/impl1.rs:62:13 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn method(&self) {} + | |____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(<[&dyn impl1[d5591eb39db23cbb]::Foo extern "C" fn(&'a u8, ...)> + impl1[d5591eb39db23cbb]::AutoTrait; 3usize] as impl1[d5591eb39db23cbb]::main::{closure#1}::Bar>::method) + = note: demangling-alt(<[&dyn impl1::Foo extern "C" fn(&'a u8, ...)> + impl1::AutoTrait; 3] as impl1::main::{closure#1}::Bar>::method) error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTrait; 3] as main::{closure#1}::Bar>::method) --> $DIR/impl1.rs:69:13 @@ -70,5 +49,5 @@ error: def-path(<[&dyn Foo extern "C" fn(&'a u8, ...)> + AutoTra LL | #[rustc_dump_def_path] | ^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 12 previous errors +error: aborting due to 6 previous errors diff --git a/tests/ui/symbol-names/issue-60925.legacy.stderr b/tests/ui/symbol-names/issue-60925.legacy.stderr index 0411d70119235..787c681bcce68 100644 --- a/tests/ui/symbol-names/issue-60925.legacy.stderr +++ b/tests/ui/symbol-names/issue-60925.legacy.stderr @@ -1,20 +1,13 @@ error: symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo17heb0a993da0d0e50cE) --> $DIR/issue-60925.rs:21:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(issue_60925::foo::Foo::foo::heb0a993da0d0e50c) - --> $DIR/issue-60925.rs:21:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(issue_60925::foo::Foo::foo) - --> $DIR/issue-60925.rs:21:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | pub(crate) fn foo() { + | |___________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(issue_60925::foo::Foo::foo::heb0a993da0d0e50c) + = note: demangling-alt(issue_60925::foo::Foo::foo) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/symbol-names/issue-60925.rs b/tests/ui/symbol-names/issue-60925.rs index 76552d88880e5..28206b69d4fd4 100644 --- a/tests/ui/symbol-names/issue-60925.rs +++ b/tests/ui/symbol-names/issue-60925.rs @@ -20,11 +20,11 @@ mod foo { impl Foo { #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN11issue_609253foo37Foo$LT$issue_60925..llv$u6d$..Foo$GT$3foo - //[legacy]~| ERROR demangling(issue_60925::foo::Foo::foo - //[legacy]~| ERROR demangling-alt(issue_60925::foo::Foo::foo) + //[legacy]~| NOTE demangling(issue_60925::foo::Foo::foo + //[legacy]~| NOTE demangling-alt(issue_60925::foo::Foo::foo) //[v0]~^^^^ ERROR symbol-name - //[v0]~| ERROR demangling - //[v0]~| ERROR demangling-alt(>::foo) + //[v0]~| NOTE demangling + //[v0]~| NOTE demangling-alt(>::foo) pub(crate) fn foo() { for _ in 0..0 { for _ in &[crate::dummy()] { diff --git a/tests/ui/symbol-names/issue-60925.v0.stderr b/tests/ui/symbol-names/issue-60925.v0.stderr index 587ee1090ade3..f82e4a422cda6 100644 --- a/tests/ui/symbol-names/issue-60925.v0.stderr +++ b/tests/ui/symbol-names/issue-60925.v0.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RNvMNtCsCRATE_HASH_11issue_609253fooINtB_3FooNtNtB_4llvm3FooE3foo) --> $DIR/issue-60925.rs:21:9 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>::foo) - --> $DIR/issue-60925.rs:21:9 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>::foo) - --> $DIR/issue-60925.rs:21:9 +LL | / #[rustc_dump_symbol_name] +... | +LL | | pub(crate) fn foo() { + | |___________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>::foo) + = note: demangling-alt(>::foo) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/symbol-names/issue-75326.legacy.stderr b/tests/ui/symbol-names/issue-75326.legacy.stderr index c4b248427c7e4..a312b7cf0b69b 100644 --- a/tests/ui/symbol-names/issue-75326.legacy.stderr +++ b/tests/ui/symbol-names/issue-75326.legacy.stderr @@ -1,20 +1,13 @@ error: symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next17SYMBOL_HASH) --> $DIR/issue-75326.rs:41:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling( as issue_75326::Iterator2>::next::SYMBOL_HASH) - --> $DIR/issue-75326.rs:41:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt( as issue_75326::Iterator2>::next) - --> $DIR/issue-75326.rs:41:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn next(&mut self) -> Option { + | |____________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling( as issue_75326::Iterator2>::next::SYMBOL_HASH) + = note: demangling-alt( as issue_75326::Iterator2>::next) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/symbol-names/issue-75326.rs b/tests/ui/symbol-names/issue-75326.rs index 7810483f5f39f..4871bac2d68cf 100644 --- a/tests/ui/symbol-names/issue-75326.rs +++ b/tests/ui/symbol-names/issue-75326.rs @@ -40,11 +40,11 @@ where #[rustc_dump_symbol_name] //[legacy]~^ ERROR symbol-name(_ZN72_$LT$issue_75326..Foo$LT$I$C$E$GT$$u20$as$u20$issue_75326..Iterator2$GT$4next - //[legacy]~| ERROR demangling( as issue_75326::Iterator2>::next - //[legacy]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) + //[legacy]~| NOTE demangling( as issue_75326::Iterator2>::next + //[legacy]~| NOTE demangling-alt( as issue_75326::Iterator2>::next) //[v0]~^^^^ ERROR symbol-name - //[v0]~| ERROR demangling - //[v0]~| ERROR demangling-alt( as issue_75326::Iterator2>::next) + //[v0]~| NOTE demangling + //[v0]~| NOTE demangling-alt( as issue_75326::Iterator2>::next) fn next(&mut self) -> Option { self.find(|_| true) } diff --git a/tests/ui/symbol-names/issue-75326.v0.stderr b/tests/ui/symbol-names/issue-75326.v0.stderr index d07a85730a2b2..af95044e8ea20 100644 --- a/tests/ui/symbol-names/issue-75326.v0.stderr +++ b/tests/ui/symbol-names/issue-75326.v0.stderr @@ -1,20 +1,13 @@ error: symbol-name(_RNvXINICsCRATE_HASH_11issue_75326s_0pppEINtB_3FooppENtB_9Iterator24nextB_) --> $DIR/issue-75326.rs:41:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling( as issue_75326[189ebc60e18860d7]::Iterator2>::next) - --> $DIR/issue-75326.rs:41:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt( as issue_75326::Iterator2>::next) - --> $DIR/issue-75326.rs:41:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn next(&mut self) -> Option { + | |____________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling( as issue_75326[189ebc60e18860d7]::Iterator2>::next) + = note: demangling-alt( as issue_75326::Iterator2>::next) -error: aborting due to 3 previous errors +error: aborting due to 1 previous error diff --git a/tests/ui/symbol-names/trait-objects.rs b/tests/ui/symbol-names/trait-objects.rs index 9f9178c6b0743..7a6f340d11a6b 100644 --- a/tests/ui/symbol-names/trait-objects.rs +++ b/tests/ui/symbol-names/trait-objects.rs @@ -14,8 +14,8 @@ trait Bar { impl Bar for &dyn FnMut(&u8) { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name - //[v0]~| ERROR demangling - //[v0]~| ERROR demangling-alt + //[v0]~| NOTE demangling + //[v0]~| NOTE demangling-alt fn method(&self) {} } @@ -26,8 +26,8 @@ trait Foo { impl Foo for &(dyn FnMut(&u8) + for<'b> Send) { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name - //[v0]~| ERROR demangling - //[v0]~| ERROR demangling-alt + //[v0]~| NOTE demangling + //[v0]~| NOTE demangling-alt fn method(&self) {} } @@ -38,8 +38,8 @@ trait Baz { impl Baz for &(dyn for<'b> Send + FnMut(&u8)) { #[rustc_dump_symbol_name] //[v0]~^ ERROR symbol-name - //[v0]~| ERROR demangling - //[v0]~| ERROR demangling-alt + //[v0]~| NOTE demangling + //[v0]~| NOTE demangling-alt fn method(&self) {} } diff --git a/tests/ui/symbol-names/trait-objects.v0.stderr b/tests/ui/symbol-names/trait-objects.v0.stderr index b0cd9c9e7e3f2..e1c4ef9313902 100644 --- a/tests/ui/symbol-names/trait-objects.v0.stderr +++ b/tests/ui/symbol-names/trait-objects.v0.stderr @@ -1,56 +1,35 @@ error: symbol-name(_RNvXCsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuEL_NtB_3Bar6method) --> $DIR/trait-objects.rs:15:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3c073c57f94bedc2]::Bar>::method) - --> $DIR/trait-objects.rs:15:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method) - --> $DIR/trait-objects.rs:15:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn method(&self) {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects[3c073c57f94bedc2]::Bar>::method) + = note: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> as trait_objects::Bar>::method) error: symbol-name(_RNvXs_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtB_6marker4SendEL_NtB_3Foo6method) --> $DIR/trait-objects.rs:27:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Foo>::method) - --> $DIR/trait-objects.rs:27:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn method(&self) {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method) - --> $DIR/trait-objects.rs:27:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Foo>::method) + = note: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Foo>::method) error: symbol-name(_RNvXs0_CsCRATE_HASH_13trait_objectsRDG_INtNtNtCsCRATE_HASH_4core3ops8function5FnMutTRL0_hEEp6OutputuNtNtB_6marker4SendEL_NtB_3Baz6method) --> $DIR/trait-objects.rs:39:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Baz>::method) - --> $DIR/trait-objects.rs:39:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method) - --> $DIR/trait-objects.rs:39:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | fn method(&self) {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(<&dyn for<'a> core[HASH]::ops::function::FnMut<(&'a u8,), Output = ()> + core[HASH]::marker::Send as trait_objects[3c073c57f94bedc2]::Baz>::method) + = note: demangling-alt(<&dyn for<'a> core::ops::function::FnMut<(&'a u8,), Output = ()> + core::marker::Send as trait_objects::Baz>::method) -error: aborting due to 9 previous errors +error: aborting due to 3 previous errors diff --git a/tests/ui/symbol-names/types.legacy.stderr b/tests/ui/symbol-names/types.legacy.stderr index a9922d9a957f9..7aab974703452 100644 --- a/tests/ui/symbol-names/types.legacy.stderr +++ b/tests/ui/symbol-names/types.legacy.stderr @@ -1,524 +1,321 @@ error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E) --> $DIR/types.rs:17:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:17:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:17:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E) --> $DIR/types.rs:26:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:26:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:26:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E) --> $DIR/types.rs:35:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:35:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:35:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E) --> $DIR/types.rs:44:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:44:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:44:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E) --> $DIR/types.rs:53:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:53:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:53:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E) --> $DIR/types.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E) --> $DIR/types.rs:71:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:71:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:71:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E) --> $DIR/types.rs:80:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:80:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:80:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E) --> $DIR/types.rs:89:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:89:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:89:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E) --> $DIR/types.rs:98:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:98:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:98:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f16$GT$17h[HASH]E) --> $DIR/types.rs:107:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:107:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:107:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E) --> $DIR/types.rs:116:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:116:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:116:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E) --> $DIR/types.rs:125:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:125:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:125:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b16Type$LT$f128$GT$17h[HASH]E) --> $DIR/types.rs:134:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:134:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:134:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E) --> $DIR/types.rs:143:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:143:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:143:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E) --> $DIR/types.rs:152:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:152:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:152:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:161:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<()>::h[HASH]) - --> $DIR/types.rs:161:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<()>) - --> $DIR/types.rs:161:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<()> {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<()>::h[HASH]) + = note: demangling-alt(a::b::Type<()>) error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:170:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,)>::h[HASH]) - --> $DIR/types.rs:170:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8,)> {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,)>) - --> $DIR/types.rs:170:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,)>) error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E) --> $DIR/types.rs:179:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,u16)>::h[HASH]) - --> $DIR/types.rs:179:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,u16)>) - --> $DIR/types.rs:179:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16)> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,u16)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,u16)>) error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E) --> $DIR/types.rs:188:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) - --> $DIR/types.rs:188:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,u16,u32)>) - --> $DIR/types.rs:188:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16, u32)> {} + | |_____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,u16,u32)>) error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E) --> $DIR/types.rs:197:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<*const u8>::h[HASH]) - --> $DIR/types.rs:197:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<*const u8>) - --> $DIR/types.rs:197:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const u8> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<*const u8>::h[HASH]) + = note: demangling-alt(a::b::Type<*const u8>) error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E) --> $DIR/types.rs:206:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<*mut u8>::h[HASH]) - --> $DIR/types.rs:206:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<*mut u8>) - --> $DIR/types.rs:206:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*mut u8> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<*mut u8>::h[HASH]) + = note: demangling-alt(a::b::Type<*mut u8>) error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E) --> $DIR/types.rs:215:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<&str>::h[HASH]) - --> $DIR/types.rs:215:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&str> {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<&str>) - --> $DIR/types.rs:215:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<&str>::h[HASH]) + = note: demangling-alt(a::b::Type<&str>) error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E) --> $DIR/types.rs:224:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<&mut str>::h[HASH]) - --> $DIR/types.rs:224:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<&mut str>) - --> $DIR/types.rs:224:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&mut str> {} + | |_______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<&mut str>::h[HASH]) + = note: demangling-alt(a::b::Type<&mut str>) error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:233:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[u8; 0]>::h[HASH]) - --> $DIR/types.rs:233:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; 0]> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[u8; 0]>) - --> $DIR/types.rs:233:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[u8; 0]>::h[HASH]) + = note: demangling-alt(a::b::Type<[u8; 0]>) error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:242:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:242:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:242:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:251:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:251:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_____________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:251:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:260:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[T; N]>::h[HASH]) - --> $DIR/types.rs:260:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[T; N]>) - --> $DIR/types.rs:260:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[T; N]> {} + | |________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[T; N]>::h[HASH]) + = note: demangling-alt(a::b::Type<[T; N]>) error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:271:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[u8; 0]>::h[HASH]) - --> $DIR/types.rs:271:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[u8; 0]>) - --> $DIR/types.rs:271:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; ZERO]> {} + | |_________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[u8; 0]>::h[HASH]) + = note: demangling-alt(a::b::Type<[u8; 0]>) -error: aborting due to 87 previous errors +error: aborting due to 29 previous errors diff --git a/tests/ui/symbol-names/types.rs b/tests/ui/symbol-names/types.rs index f1789cba6abe6..c74f44bd5394a 100644 --- a/tests/ui/symbol-names/types.rs +++ b/tests/ui/symbol-names/types.rs @@ -16,265 +16,265 @@ pub fn b() { #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$bool$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMNvCsCRATE_HASH_1a1bINtB_4TypebE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$char$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs_NvCsCRATE_HASH_1a1bINtB_4TypecE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b14Type$LT$i8$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs0_NvCsCRATE_HASH_1a1bINtB_4TypeaE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i16$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs1_NvCsCRATE_HASH_1a1bINtB_4TypesE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i32$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs2_NvCsCRATE_HASH_1a1bINtB_4TypelE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$i64$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs3_NvCsCRATE_HASH_1a1bINtB_4TypexE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b14Type$LT$u8$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs4_NvCsCRATE_HASH_1a1bINtB_4TypehE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u16$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs5_NvCsCRATE_HASH_1a1bINtB_4TypetE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u32$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs6_NvCsCRATE_HASH_1a1bINtB_4TypemE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$u64$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs7_NvCsCRATE_HASH_1a1bINtB_4TypeyE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f16$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs8_NvCsCRATE_HASH_1a1bINtB_4TypeC3f16E) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f32$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMs9_NvCsCRATE_HASH_1a1bINtB_4TypefE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$f64$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMsa_NvCsCRATE_HASH_1a1bINtB_4TypedE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b16Type$LT$f128$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMsb_NvCsCRATE_HASH_1a1bINtB_4TypeC4f128E) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b15Type$LT$str$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMsc_NvCsCRATE_HASH_1a1bINtB_4TypeeE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b17Type$LT$$u21$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMsd_NvCsCRATE_HASH_1a1bINtB_4TypezE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<()>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<()>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<()>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<()>) //[v0]~^^^^ ERROR symbol-name(_RMse_NvCsCRATE_HASH_1a1bINtB_4TypeuE) - //[v0]~| ERROR ::b::Type<()>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<()>>) + //[v0]~| NOTE demangling-alt(>) impl Type<()> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,)>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,)>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<(u8,)>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<(u8,)>) //[v0]~^^^^ ERROR symbol-name(_RMsf_NvCsCRATE_HASH_1a1bINtB_4TypeThEE) - //[v0]~| ERROR ::b::Type<(u8,)>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<(u8,)>>) + //[v0]~| NOTE demangling-alt(>) impl Type<(u8,)> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,u16)>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,u16)>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<(u8,u16)>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<(u8,u16)>) //[v0]~^^^^ ERROR symbol-name(_RMsg_NvCsCRATE_HASH_1a1bINtB_4TypeThtEE) - //[v0]~| ERROR ::b::Type<(u8, u16)>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<(u8, u16)>>) + //[v0]~| NOTE demangling-alt(>) impl Type<(u8, u16)> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<(u8,u16,u32)>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<(u8,u16,u32)>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<(u8,u16,u32)>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<(u8,u16,u32)>) //[v0]~^^^^ ERROR symbol-name(_RMsh_NvCsCRATE_HASH_1a1bINtB_4TypeThtmEE) - //[v0]~| ERROR ::b::Type<(u8, u16, u32)>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<(u8, u16, u32)>>) + //[v0]~| NOTE demangling-alt(>) impl Type<(u8, u16, u32)> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<*const u8>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<*const u8>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<*const u8>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<*const u8>) //[v0]~^^^^ ERROR symbol-name(_RMsi_NvCsCRATE_HASH_1a1bINtB_4TypePhE) - //[v0]~| ERROR ::b::Type<*const u8>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<*const u8>>) + //[v0]~| NOTE demangling-alt(>) impl Type<*const u8> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<*mut u8>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<*mut u8>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<*mut u8>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<*mut u8>) //[v0]~^^^^ ERROR symbol-name(_RMsj_NvCsCRATE_HASH_1a1bINtB_4TypeOhE) - //[v0]~| ERROR ::b::Type<*mut u8>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<*mut u8>>) + //[v0]~| NOTE demangling-alt(>) impl Type<*mut u8> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<&str>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<&str>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<&str>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<&str>) //[v0]~^^^^ ERROR symbol-name(_RMsk_NvCsCRATE_HASH_1a1bINtB_4TypeReE) - //[v0]~| ERROR ::b::Type<&str>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<&str>>) + //[v0]~| NOTE demangling-alt(>) impl Type<&str> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<&mut str>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<&mut str>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<&mut str>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<&mut str>) //[v0]~^^^^ ERROR symbol-name(_RMsl_NvCsCRATE_HASH_1a1bINtB_4TypeQeE) - //[v0]~| ERROR ::b::Type<&mut str>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<&mut str>>) + //[v0]~| NOTE demangling-alt(>) impl Type<&mut str> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[u8; 0]>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[u8; 0]>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<[u8; 0]>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<[u8; 0]>) //[v0]~^^^^ ERROR symbol-name(_RMsm_NvCsCRATE_HASH_1a1bINtB_4TypeAhj0_E) - //[v0]~| ERROR ::b::Type<[u8; 0usize]>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<[u8; 0usize]>>) + //[v0]~| NOTE demangling-alt(>) impl Type<[u8; 0]> {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMsn_NvCsCRATE_HASH_1a1bINtB_4TypeFEuE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type) //[v0]~^^^^ ERROR symbol-name(_RMso_NvCsCRATE_HASH_1a1bINtB_4TypeFUKCEuE) - //[v0]~| ERROR ::b::Type>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type>) + //[v0]~| NOTE demangling-alt(>) impl Type {} #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[T; N]>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[T; N]>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<[T; N]>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<[T; N]>) //[v0]~^^^^ ERROR symbol-name(_RMsp_NvCsCRATE_HASH_1a1bINtB_4TypeAppEB_) - //[v0]~| ERROR ::b::Type<[_; _]>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<[_; _]>>) + //[v0]~| NOTE demangling-alt(>) impl Type<[T; N]> {} const ZERO: usize = 0; #[rustc_dump_symbol_name] //[legacy,verbose-legacy]~^ ERROR symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$ - //[legacy,verbose-legacy]~| ERROR demangling(a::b::Type<[u8; 0]>:: - //[legacy,verbose-legacy]~| ERROR demangling-alt(a::b::Type<[u8; 0]>) + //[legacy,verbose-legacy]~| NOTE demangling(a::b::Type<[u8; 0]>:: + //[legacy,verbose-legacy]~| NOTE demangling-alt(a::b::Type<[u8; 0]>) //[v0]~^^^^ ERROR symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB_4TypeAhj0_E) - //[v0]~| ERROR ::b::Type<[u8; 0usize]>>) - //[v0]~| ERROR demangling-alt(>) + //[v0]~| NOTE ::b::Type<[u8; 0usize]>>) + //[v0]~| NOTE demangling-alt(>) impl Type<[u8; ZERO]> {} } diff --git a/tests/ui/symbol-names/types.v0.stderr b/tests/ui/symbol-names/types.v0.stderr index 4ac96ca19a53a..841f88ffb0e35 100644 --- a/tests/ui/symbol-names/types.v0.stderr +++ b/tests/ui/symbol-names/types.v0.stderr @@ -1,524 +1,321 @@ error: symbol-name(_RMNvCsCRATE_HASH_1a1bINtB_4TypebE) --> $DIR/types.rs:17:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:17:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:17:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs_NvCsCRATE_HASH_1a1bINtB_4TypecE) --> $DIR/types.rs:26:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:26:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:26:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs0_NvCsCRATE_HASH_1a1bINtB_4TypeaE) --> $DIR/types.rs:35:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:35:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:35:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs1_NvCsCRATE_HASH_1a1bINtB_4TypesE) --> $DIR/types.rs:44:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:44:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:44:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs2_NvCsCRATE_HASH_1a1bINtB_4TypelE) --> $DIR/types.rs:53:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:53:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:53:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs3_NvCsCRATE_HASH_1a1bINtB_4TypexE) --> $DIR/types.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs4_NvCsCRATE_HASH_1a1bINtB_4TypehE) --> $DIR/types.rs:71:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:71:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:71:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs5_NvCsCRATE_HASH_1a1bINtB_4TypetE) --> $DIR/types.rs:80:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:80:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:80:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs6_NvCsCRATE_HASH_1a1bINtB_4TypemE) --> $DIR/types.rs:89:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:89:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:89:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs7_NvCsCRATE_HASH_1a1bINtB_4TypeyE) --> $DIR/types.rs:98:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:98:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:98:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs8_NvCsCRATE_HASH_1a1bINtB_4TypeC3f16E) --> $DIR/types.rs:107:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:107:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:107:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMs9_NvCsCRATE_HASH_1a1bINtB_4TypefE) --> $DIR/types.rs:116:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:116:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:116:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsa_NvCsCRATE_HASH_1a1bINtB_4TypedE) --> $DIR/types.rs:125:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:125:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:125:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsb_NvCsCRATE_HASH_1a1bINtB_4TypeC4f128E) --> $DIR/types.rs:134:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:134:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:134:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsc_NvCsCRATE_HASH_1a1bINtB_4TypeeE) --> $DIR/types.rs:143:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:143:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:143:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsd_NvCsCRATE_HASH_1a1bINtB_4TypezE) --> $DIR/types.rs:152:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:152:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:152:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMse_NvCsCRATE_HASH_1a1bINtB_4TypeuE) --> $DIR/types.rs:161:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:161:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:161:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<()> {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsf_NvCsCRATE_HASH_1a1bINtB_4TypeThEE) --> $DIR/types.rs:170:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:170:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8,)> {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:170:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsg_NvCsCRATE_HASH_1a1bINtB_4TypeThtEE) --> $DIR/types.rs:179:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:179:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:179:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16)> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsh_NvCsCRATE_HASH_1a1bINtB_4TypeThtmEE) --> $DIR/types.rs:188:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:188:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:188:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16, u32)> {} + | |_____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsi_NvCsCRATE_HASH_1a1bINtB_4TypePhE) --> $DIR/types.rs:197:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:197:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:197:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const u8> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsj_NvCsCRATE_HASH_1a1bINtB_4TypeOhE) --> $DIR/types.rs:206:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:206:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:206:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*mut u8> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsk_NvCsCRATE_HASH_1a1bINtB_4TypeReE) --> $DIR/types.rs:215:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:215:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&str> {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:215:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsl_NvCsCRATE_HASH_1a1bINtB_4TypeQeE) --> $DIR/types.rs:224:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:224:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:224:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&mut str> {} + | |_______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsm_NvCsCRATE_HASH_1a1bINtB_4TypeAhj0_E) --> $DIR/types.rs:233:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:233:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; 0]> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:233:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsn_NvCsCRATE_HASH_1a1bINtB_4TypeFEuE) --> $DIR/types.rs:242:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:242:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:242:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMso_NvCsCRATE_HASH_1a1bINtB_4TypeFUKCEuE) --> $DIR/types.rs:251:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:251:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_____________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:251:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsp_NvCsCRATE_HASH_1a1bINtB_4TypeAppEB_) --> $DIR/types.rs:260:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:260:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:260:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[T; N]> {} + | |________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) error: symbol-name(_RMsq_NvCsCRATE_HASH_1a1bINtB_4TypeAhj0_E) --> $DIR/types.rs:271:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(>) - --> $DIR/types.rs:271:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(>) - --> $DIR/types.rs:271:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; ZERO]> {} + | |_________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(>) + = note: demangling-alt(>) -error: aborting due to 87 previous errors +error: aborting due to 29 previous errors diff --git a/tests/ui/symbol-names/types.verbose-legacy.stderr b/tests/ui/symbol-names/types.verbose-legacy.stderr index a9922d9a957f9..7aab974703452 100644 --- a/tests/ui/symbol-names/types.verbose-legacy.stderr +++ b/tests/ui/symbol-names/types.verbose-legacy.stderr @@ -1,524 +1,321 @@ error: symbol-name(_ZN1a1b16Type$LT$bool$GT$17h[HASH]E) --> $DIR/types.rs:17:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:17:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:17:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b16Type$LT$char$GT$17h[HASH]E) --> $DIR/types.rs:26:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:26:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:26:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b14Type$LT$i8$GT$17h[HASH]E) --> $DIR/types.rs:35:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:35:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:35:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i16$GT$17h[HASH]E) --> $DIR/types.rs:44:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:44:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:44:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i32$GT$17h[HASH]E) --> $DIR/types.rs:53:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:53:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:53:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$i64$GT$17h[HASH]E) --> $DIR/types.rs:62:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:62:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:62:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b14Type$LT$u8$GT$17h[HASH]E) --> $DIR/types.rs:71:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:71:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:71:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u16$GT$17h[HASH]E) --> $DIR/types.rs:80:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:80:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:80:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u32$GT$17h[HASH]E) --> $DIR/types.rs:89:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:89:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:89:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$u64$GT$17h[HASH]E) --> $DIR/types.rs:98:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:98:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:98:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f16$GT$17h[HASH]E) --> $DIR/types.rs:107:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:107:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:107:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f32$GT$17h[HASH]E) --> $DIR/types.rs:116:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:116:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:116:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$f64$GT$17h[HASH]E) --> $DIR/types.rs:125:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:125:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:125:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b16Type$LT$f128$GT$17h[HASH]E) --> $DIR/types.rs:134:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:134:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:134:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b15Type$LT$str$GT$17h[HASH]E) --> $DIR/types.rs:143:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:143:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |__________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:143:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b17Type$LT$$u21$$GT$17h[HASH]E) --> $DIR/types.rs:152:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:152:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:152:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b20Type$LT$$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:161:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<()>::h[HASH]) - --> $DIR/types.rs:161:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<()>) - --> $DIR/types.rs:161:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<()> {} + | |_________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<()>::h[HASH]) + = note: demangling-alt(a::b::Type<()>) error: symbol-name(_ZN1a1b25Type$LT$$LP$u8$C$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:170:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,)>::h[HASH]) - --> $DIR/types.rs:170:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8,)> {} + | |____________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,)>) - --> $DIR/types.rs:170:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,)>) error: symbol-name(_ZN1a1b28Type$LT$$LP$u8$C$u16$RP$$GT$17h[HASH]E) --> $DIR/types.rs:179:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,u16)>::h[HASH]) - --> $DIR/types.rs:179:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,u16)>) - --> $DIR/types.rs:179:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16)> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,u16)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,u16)>) error: symbol-name(_ZN1a1b34Type$LT$$LP$u8$C$u16$C$u32$RP$$GT$17h[HASH]E) --> $DIR/types.rs:188:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) - --> $DIR/types.rs:188:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<(u8,u16,u32)>) - --> $DIR/types.rs:188:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<(u8, u16, u32)> {} + | |_____________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<(u8,u16,u32)>::h[HASH]) + = note: demangling-alt(a::b::Type<(u8,u16,u32)>) error: symbol-name(_ZN1a1b28Type$LT$$BP$const$u20$u8$GT$17h[HASH]E) --> $DIR/types.rs:197:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<*const u8>::h[HASH]) - --> $DIR/types.rs:197:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<*const u8>) - --> $DIR/types.rs:197:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*const u8> {} + | |________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<*const u8>::h[HASH]) + = note: demangling-alt(a::b::Type<*const u8>) error: symbol-name(_ZN1a1b26Type$LT$$BP$mut$u20$u8$GT$17h[HASH]E) --> $DIR/types.rs:206:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<*mut u8>::h[HASH]) - --> $DIR/types.rs:206:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<*mut u8>) - --> $DIR/types.rs:206:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<*mut u8> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<*mut u8>::h[HASH]) + = note: demangling-alt(a::b::Type<*mut u8>) error: symbol-name(_ZN1a1b19Type$LT$$RF$str$GT$17h[HASH]E) --> $DIR/types.rs:215:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<&str>::h[HASH]) - --> $DIR/types.rs:215:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&str> {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<&str>) - --> $DIR/types.rs:215:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<&str>::h[HASH]) + = note: demangling-alt(a::b::Type<&str>) error: symbol-name(_ZN1a1b27Type$LT$$RF$mut$u20$str$GT$17h[HASH]E) --> $DIR/types.rs:224:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<&mut str>::h[HASH]) - --> $DIR/types.rs:224:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<&mut str>) - --> $DIR/types.rs:224:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<&mut str> {} + | |_______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<&mut str>::h[HASH]) + = note: demangling-alt(a::b::Type<&mut str>) error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:233:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[u8; 0]>::h[HASH]) - --> $DIR/types.rs:233:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; 0]> {} + | |______________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[u8; 0]>) - --> $DIR/types.rs:233:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[u8; 0]>::h[HASH]) + = note: demangling-alt(a::b::Type<[u8; 0]>) error: symbol-name(_ZN1a1b22Type$LT$fn$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:242:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:242:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:242:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |___________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b60Type$LT$unsafe$u20$extern$u20$$u22$C$u22$$u20$fn$LP$$RP$$GT$17h[HASH]E) --> $DIR/types.rs:251:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type::h[HASH]) - --> $DIR/types.rs:251:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type {} + | |_____________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type) - --> $DIR/types.rs:251:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type::h[HASH]) + = note: demangling-alt(a::b::Type) error: symbol-name(_ZN1a1b34Type$LT$$u5b$T$u3b$$u20$N$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:260:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[T; N]>::h[HASH]) - --> $DIR/types.rs:260:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[T; N]>) - --> $DIR/types.rs:260:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[T; N]> {} + | |________________________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[T; N]>::h[HASH]) + = note: demangling-alt(a::b::Type<[T; N]>) error: symbol-name(_ZN1a1b35Type$LT$$u5b$u8$u3b$$u20$0$u5d$$GT$17h[HASH]E) --> $DIR/types.rs:271:5 | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling(a::b::Type<[u8; 0]>::h[HASH]) - --> $DIR/types.rs:271:5 - | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - -error: demangling-alt(a::b::Type<[u8; 0]>) - --> $DIR/types.rs:271:5 +LL | / #[rustc_dump_symbol_name] +... | +LL | | impl Type<[u8; ZERO]> {} + | |_________________________^ | -LL | #[rustc_dump_symbol_name] - | ^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: demangling(a::b::Type<[u8; 0]>::h[HASH]) + = note: demangling-alt(a::b::Type<[u8; 0]>) -error: aborting due to 87 previous errors +error: aborting due to 29 previous errors From 9c77e1eaf7e342ab850b786c9ac61ea3e75aeba1 Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Thu, 24 Sep 2026 01:58:09 +0200 Subject: [PATCH 0749/1309] Adding safety comment on the unsafe in BTreeMap drop --- library/alloc/src/collections/btree/map.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index 1f479569705f8..fc194639c5468 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -206,7 +206,8 @@ pub struct BTreeMap< unsafe impl<#[may_dangle] K, #[may_dangle] V, A: AllocatorClone> Drop for BTreeMap { fn drop(&mut self) { if self.root.is_some() { - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` is not used after this and none of its fields are dropped again: + // `alloc` is `ManuallyDrop` and `root` has no drop glue. drop(unsafe { ptr::read(self) }.into_iter()) } else { // SAFETY: With no root there are no nodes to free, so only the allocator needs From 733daee361a47583ace352b2030c802e21898810 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Tue, 22 Sep 2026 13:16:35 +1000 Subject: [PATCH 0750/1309] Use fewer FFI calls to check the target CPU's features The existing code makes a separate FFI call to `MCSubtargetInfo::checkFeatures` for each feature-dependency of the feature being checked, and also performs string-manipulation on the C++ side to add a leading '+' to each feature name. What we can do instead is prepare a single string on the Rust side in the form `"+foo,+bar,+baz,"` for each Rust target feature, and pass that string to LLVM. LLVM already knows how to check that all of the listed features are present. (The trailing comma is not a problem, because `SubtargetFeatures::Split` will automatically discard empty substrings after splitting on commas.) --- .../src/back/owned_mc_subtarget_info.rs | 17 +++++++++++++---- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 5 +++-- compiler/rustc_codegen_llvm/src/llvm_util.rs | 14 +++----------- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 7 ++++--- 4 files changed, 23 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs index f57368e755add..1a85f1458d258 100644 --- a/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs +++ b/compiler/rustc_codegen_llvm/src/back/owned_mc_subtarget_info.rs @@ -4,7 +4,7 @@ use std::ptr::NonNull; use rustc_data_structures::small_c_str::SmallCStr; use crate::diagnostics::LlvmError; -use crate::llvm; +use crate::{llvm, llvm_util}; /// Responsible for safely creating and disposing llvm::MCSubtargetInfo via ffi functions. /// Not cloneable as there is no clone function for llvm::MCSubtargetInfo. @@ -28,11 +28,20 @@ impl OwnedMCSubtargetInfo { .ok_or_else(|| LlvmError::CreateMCSubtargetInfo { triple: SmallCStr::from(triple) }) } - pub(crate) fn has_feature(&self, feature: &CStr) -> bool { - // SAFETY: `new` ensures we have a valid pointer created by + pub(crate) fn has_features(&self, features: llvm_util::LLVMFeature<'_>) -> bool { + // Convert to a feature string expected by LLVM's `SubtargetFeatures`. + // All of the required LLVM features must be enabled. + // (The trailing comma is OK, as `SubtargetFeatures::Split` discards empty substrings.) + let features = features.into_iter().flat_map(|feat| ["+", feat, ","]).collect::(); + + // SAFETY: `info_unique` is a valid pointer created by // `llvm::LLVMRustCreateMCSubtargetInfo`. unsafe { - llvm::LLVMRustMCSubtargetInfoHasFeature(self.info_unique.as_ref(), feature.as_ptr()) + llvm::LLVMRustMCSubtargetInfoCheckFeatures( + self.info_unique.as_ref(), + features.as_ptr(), + features.len(), + ) } } } diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 07381745afe84..655a79e341bd1 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -2422,9 +2422,10 @@ unsafe extern "C" { Features: *const c_char, ) -> *mut MCSubtargetInfo; - pub(crate) fn LLVMRustMCSubtargetInfoHasFeature( + pub(crate) fn LLVMRustMCSubtargetInfoCheckFeatures( MCInfo: &MCSubtargetInfo, - Feature: *const c_char, + Features: *const c_uchar, // See "PTR_LEN_STR". + FeaturesLen: usize, ) -> bool; pub(crate) fn LLVMRustDisposeMCSubtargetInfo(MCInfo: ptr::NonNull); diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 5c0ad95fc4e43..9e37205f230ac 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -361,17 +361,9 @@ pub(crate) fn target_config(sess: &EarlySession) -> TargetConfig { // do *not* consider the `-Ctarget-feature`s here (that's why we passed `for_cfg: true` // to `global_llvm_features` above) because that will be handled later in // `internal_target_features`. - if let Some(feat) = to_llvm_features(&sess.target, feature) { - // All the LLVM features this expands to must be enabled. - for llvm_feature in feat { - let cstr = SmallCStr::new(llvm_feature); - // `has_feature` is moderately expensive. On targets with many - // features (e.g. x86) these calls take a non-trivial fraction of runtime - // when compiling very small programs. - if !mc_subtarget_info.has_feature(&cstr) { - return false; - } - } + if let Some(feat) = to_llvm_features(&sess.target, feature) + && mc_subtarget_info.has_features(feat) + { true } else { false diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 35d5597795a9e..beb63ad61493c 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -107,9 +107,10 @@ LLVMRustCreateMCSubtargetInfo(const char *TripleStr, const char *CPU, #endif } -extern "C" bool LLVMRustMCSubtargetInfoHasFeature(MCSubtargetInfo *MCInfo, - const char *Feature) { - return MCInfo->checkFeatures(std::string("+") + Feature); +extern "C" bool LLVMRustMCSubtargetInfoCheckFeatures(MCSubtargetInfo *MCInfo, + const char *Features, + size_t FeaturesLen) { + return MCInfo->checkFeatures(StringRef{Features, FeaturesLen}); } extern "C" void LLVMRustDisposeMCSubtargetInfo(MCSubtargetInfo *MCInfo) { From 603ca3fbf97a90478114056d068965e6c3a45ec4 Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 24 Sep 2026 09:11:43 +0800 Subject: [PATCH 0751/1309] Add regression tests for await macro suggestions --- .../await-keyword/await-macro-rustfix.rs | 22 ++++++++ .../await-keyword/await-macro-rustfix.stderr | 50 +++++++++++++++++++ 2 files changed, 72 insertions(+) create mode 100644 tests/ui/async-await/await-keyword/await-macro-rustfix.rs create mode 100644 tests/ui/async-await/await-keyword/await-macro-rustfix.stderr diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.rs b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs new file mode 100644 index 0000000000000..e9fc64bf6b92e --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs @@ -0,0 +1,22 @@ +//@ edition: 2024 + +// Replacing `await!(...)` must preserve grouping and any following `?`. + +use std::future::ready; + +async fn check() -> Result<(), ()> { + let future = ready(1); + let _: i32 = await!(future); + //~^ ERROR incorrect use of `await` + let _: i32 = await!(ready(1)); + //~^ ERROR incorrect use of `await` + let _: i32 = await!(ready(Ok::(1)))?; + //~^ ERROR incorrect use of `await` + let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); + //~^ ERROR incorrect use of `await` + Ok(()) +} + +fn main() { + let _ = check(); +} diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr new file mode 100644 index 0000000000000..02a60fff3371f --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr @@ -0,0 +1,50 @@ +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:9:18 + | +LL | let _: i32 = await!(future); + | ^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(future); +LL + let _: i32 = future.await); + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:11:18 + | +LL | let _: i32 = await!(ready(1)); + | ^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(ready(1)); +LL + let _: i32 = ready(1).await); + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:13:18 + | +LL | let _: i32 = await!(ready(Ok::(1)))?; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(ready(Ok::(1)))?; +LL + let _: i32 = ready(Ok::(1)).await)?; + | + +error: incorrect use of `await` + --> $DIR/await-macro-rustfix.rs:15:18 + | +LL | let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: `await` is a postfix operation + | +LL - let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); +LL + let _: i32 = &mut ready(1).await /* keep */); + | + +error: aborting due to 4 previous errors + From 3ea2995de898fd22bd562c286cc4d7b26176cc30 Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 24 Sep 2026 09:22:16 +0800 Subject: [PATCH 0752/1309] Fix incorrect use of await in parser suggestion --- .../rustc_parse/src/parser/diagnostics.rs | 29 ++++++++++++------- .../await-keyword/await-macro-rustfix.fixed | 23 +++++++++++++++ .../await-keyword/await-macro-rustfix.rs | 1 + .../await-keyword/await-macro-rustfix.stderr | 16 +++++----- .../incorrect-syntax-suggestions.stderr | 8 ++--- 5 files changed, 55 insertions(+), 22 deletions(-) create mode 100644 tests/ui/async-await/await-keyword/await-macro-rustfix.fixed diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 928518c88fec6..0630a65e56cb4 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -3,7 +3,7 @@ use std::ops::{Deref, DerefMut}; use ast::token::IdentKind; use rustc_ast::token::{self, Lit, LitKind, Token, TokenKind}; -use rustc_ast::util::parser::AssocOp; +use rustc_ast::util::parser::{AssocOp, ExprPrecedence}; use rustc_ast::{ self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AttrVec, BinOpKind, BindingMode, Block, BlockCheckMode, Expr, ExprKind, GenericArg, GenericArgs, Generics, Item, ItemKind, @@ -1719,26 +1719,35 @@ impl<'a> Parser<'a> { &mut self, await_sp: Span, ) -> PResult<'a, Box> { - let (hi, expr, is_question) = if self.token == token::Bang { + let (hi, expr_span, is_question) = if self.token == token::Bang { // Handle `await!()`. self.recover_await_macro()? } else { self.recover_await_prefix(await_sp)? }; - let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, &expr, is_question); + let (sp, guar) = self.error_on_incorrect_await(await_sp, hi, expr_span, is_question); let expr = self.mk_expr_err(await_sp.to(sp), guar); self.maybe_recover_from_bad_qpath(expr) } - fn recover_await_macro(&mut self) -> PResult<'a, (Span, Box, bool)> { + fn recover_await_macro(&mut self) -> PResult<'a, (Span, Span, bool)> { self.expect(exp!(Bang))?; self.expect(exp!(OpenParen))?; + let open = self.prev_token.span; let expr = self.parse_expr()?; self.expect(exp!(CloseParen))?; - Ok((self.prev_token.span, expr, false)) + let close = self.prev_token.span; + // Keep parentheses when needed for `.await`, e.g. `(&mut future).await`. + // Use the delimiters to preserve any comments around the operand. + let expr_span = if expr.precedence() < ExprPrecedence::Unambiguous { + open.to(close) + } else { + open.shrink_to_hi().to(close.shrink_to_lo()) + }; + Ok((close, expr_span, false)) } - fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Box, bool)> { + fn recover_await_prefix(&mut self, await_sp: Span) -> PResult<'a, (Span, Span, bool)> { let is_question = self.eat(exp!(Question)); // Handle `await? `. let expr = if self.token == token::OpenBrace { // Handle `await { }`. @@ -1752,22 +1761,22 @@ impl<'a> Parser<'a> { err.span_label(await_sp, format!("while parsing this incorrect await expression")); err })?; - Ok((expr.span, expr, is_question)) + Ok((expr.span, expr.span, is_question)) } fn error_on_incorrect_await( &self, lo: Span, hi: Span, - expr: &Expr, + expr_span: Span, is_question: bool, ) -> (Span, ErrorGuaranteed) { let span = lo.to(hi); let guar = self.dcx().emit_err(IncorrectAwait { span, suggestion: AwaitSuggestion { - removal: lo.until(expr.span), - dot_await: expr.span.shrink_to_hi(), + removal: lo.until(expr_span), + dot_await: expr_span.shrink_to_hi().to(hi.shrink_to_hi()), question_mark: if is_question { "?" } else { "" }, }, }); diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed b/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed new file mode 100644 index 0000000000000..2946c05ad51b5 --- /dev/null +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.fixed @@ -0,0 +1,23 @@ +//@ run-rustfix +//@ edition: 2024 + +// Replacing `await!(...)` must preserve grouping and any following `?`. + +use std::future::ready; + +async fn check() -> Result<(), ()> { + let future = ready(1); + let _: i32 = future.await; + //~^ ERROR incorrect use of `await` + let _: i32 = ready(1).await; + //~^ ERROR incorrect use of `await` + let _: i32 = ready(Ok::(1)).await?; + //~^ ERROR incorrect use of `await` + let _: i32 = (/* keep */ &mut ready(1) /* keep */).await; + //~^ ERROR incorrect use of `await` + Ok(()) +} + +fn main() { + let _ = check(); +} diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.rs b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs index e9fc64bf6b92e..7272a2084843d 100644 --- a/tests/ui/async-await/await-keyword/await-macro-rustfix.rs +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.rs @@ -1,3 +1,4 @@ +//@ run-rustfix //@ edition: 2024 // Replacing `await!(...)` must preserve grouping and any following `?`. diff --git a/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr index 02a60fff3371f..42a1bdfdafcaa 100644 --- a/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr +++ b/tests/ui/async-await/await-keyword/await-macro-rustfix.stderr @@ -1,5 +1,5 @@ error: incorrect use of `await` - --> $DIR/await-macro-rustfix.rs:9:18 + --> $DIR/await-macro-rustfix.rs:10:18 | LL | let _: i32 = await!(future); | ^^^^^^^^^^^^^^ @@ -7,11 +7,11 @@ LL | let _: i32 = await!(future); help: `await` is a postfix operation | LL - let _: i32 = await!(future); -LL + let _: i32 = future.await); +LL + let _: i32 = future.await; | error: incorrect use of `await` - --> $DIR/await-macro-rustfix.rs:11:18 + --> $DIR/await-macro-rustfix.rs:12:18 | LL | let _: i32 = await!(ready(1)); | ^^^^^^^^^^^^^^^^ @@ -19,11 +19,11 @@ LL | let _: i32 = await!(ready(1)); help: `await` is a postfix operation | LL - let _: i32 = await!(ready(1)); -LL + let _: i32 = ready(1).await); +LL + let _: i32 = ready(1).await; | error: incorrect use of `await` - --> $DIR/await-macro-rustfix.rs:13:18 + --> $DIR/await-macro-rustfix.rs:14:18 | LL | let _: i32 = await!(ready(Ok::(1)))?; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -31,11 +31,11 @@ LL | let _: i32 = await!(ready(Ok::(1)))?; help: `await` is a postfix operation | LL - let _: i32 = await!(ready(Ok::(1)))?; -LL + let _: i32 = ready(Ok::(1)).await)?; +LL + let _: i32 = ready(Ok::(1)).await?; | error: incorrect use of `await` - --> $DIR/await-macro-rustfix.rs:15:18 + --> $DIR/await-macro-rustfix.rs:16:18 | LL | let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,7 +43,7 @@ LL | let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); help: `await` is a postfix operation | LL - let _: i32 = await!(/* keep */ &mut ready(1) /* keep */); -LL + let _: i32 = &mut ready(1).await /* keep */); +LL + let _: i32 = (/* keep */ &mut ready(1) /* keep */).await; | error: aborting due to 4 previous errors diff --git a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr index 0ccde7d8709f1..a6ec0b3f8542d 100644 --- a/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr +++ b/tests/ui/async-await/await-keyword/incorrect-syntax-suggestions.stderr @@ -187,7 +187,7 @@ LL | let _ = await!(bar()); help: `await` is a postfix operation | LL - let _ = await!(bar()); -LL + let _ = bar().await); +LL + let _ = bar().await; | error: incorrect use of `await` @@ -199,7 +199,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: incorrect use of `await` @@ -211,7 +211,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: incorrect use of `await` @@ -223,7 +223,7 @@ LL | let _ = await!(bar())?; help: `await` is a postfix operation | LL - let _ = await!(bar())?; -LL + let _ = bar().await)?; +LL + let _ = bar().await?; | error: expected expression, found `=>` From dc39f011b8ebb2ee32511de7ffca1b47ad3454fd Mon Sep 17 00:00:00 2001 From: eleocraft Date: Thu, 24 Sep 2026 05:01:45 +0200 Subject: [PATCH 0753/1309] making clamp_magnitude functions const + adding clamp_magnitude to NonZero --- library/core/src/num/f128.rs | 5 ++-- library/core/src/num/f16.rs | 5 ++-- library/core/src/num/f32.rs | 6 ++--- library/core/src/num/f64.rs | 6 ++--- library/core/src/num/int_macros.rs | 7 ++--- library/core/src/num/nonzero.rs | 26 +++++++++++++++++++ .../coretests/tests/num/clamp_magnitude.rs | 8 +++--- 7 files changed, 46 insertions(+), 17 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index db05d7fdc5087..e53e4df1ea43d 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1544,9 +1544,10 @@ impl f128 { /// ``` #[inline] #[unstable(feature = "clamp_magnitude", issue = "148519")] - #[must_use = "this returns the clamped value and does not modify the original"] + #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[must_use = "method returns a new number and does not mutate the original value"] #[expect(clippy::neg_cmp_op_on_partial_ord, reason = "NaN is also invalid")] - pub fn clamp_magnitude(self, limit: f128) -> f128 { + pub const fn clamp_magnitude(self, limit: f128) -> f128 { assert!(limit >= 0.0, "limit must be non-negative and not NaN"); let limit = limit.abs(); // Canonicalises -0.0 to 0.0 self.clamp(-limit, limit) diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 273ef3688ca5f..4ad41bd6cfa4b 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1530,9 +1530,10 @@ impl f16 { /// ``` #[inline] #[unstable(feature = "clamp_magnitude", issue = "148519")] - #[must_use = "this returns the clamped value and does not modify the original"] + #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[must_use = "method returns a new number and does not mutate the original value"] #[expect(clippy::neg_cmp_op_on_partial_ord, reason = "NaN is also invalid")] - pub fn clamp_magnitude(self, limit: f16) -> f16 { + pub const fn clamp_magnitude(self, limit: f16) -> f16 { assert!(limit >= 0.0, "limit must be non-negative and not NaN"); let limit = limit.abs(); // Canonicalises -0.0 to 0.0 self.clamp(-limit, limit) diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index d3dea38dc2fcf..2dc3ddf31cac5 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1699,11 +1699,11 @@ impl f32 { /// assert_eq!(2.0f32.clamp_magnitude(3.0), 2.0); /// assert_eq!((-2.0f32).clamp_magnitude(3.0), -2.0); /// ``` - #[must_use = "this returns the clamped value and does not modify the original"] - #[unstable(feature = "clamp_magnitude", issue = "148519")] #[inline] + #[unstable(feature = "clamp_magnitude", issue = "148519")] + #[must_use = "method returns a new number and does not mutate the original value"] #[expect(clippy::neg_cmp_op_on_partial_ord, reason = "NaN is also invalid")] - pub fn clamp_magnitude(self, limit: f32) -> f32 { + pub const fn clamp_magnitude(self, limit: f32) -> f32 { assert!(limit >= 0.0, "limit must be non-negative and not NaN"); let limit = limit.abs(); // Canonicalises -0.0 to 0.0 self.clamp(-limit, limit) diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 7c5082749cd11..cd3cfe1bd4c60 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1677,11 +1677,11 @@ impl f64 { /// assert_eq!(2.0f64.clamp_magnitude(3.0), 2.0); /// assert_eq!((-2.0f64).clamp_magnitude(3.0), -2.0); /// ``` - #[must_use = "this returns the clamped value and does not modify the original"] - #[unstable(feature = "clamp_magnitude", issue = "148519")] #[inline] + #[unstable(feature = "clamp_magnitude", issue = "148519")] + #[must_use = "method returns a new number and does not mutate the original value"] #[expect(clippy::neg_cmp_op_on_partial_ord, reason = "NaN is also invalid")] - pub fn clamp_magnitude(self, limit: f64) -> f64 { + pub const fn clamp_magnitude(self, limit: f64) -> f64 { assert!(limit >= 0.0, "limit must be non-negative and not NaN"); let limit = limit.abs(); // Canonicalises -0.0 to 0.0 self.clamp(-limit, limit) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index bb37a734824fa..2328fb1e03a31 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3968,10 +3968,11 @@ macro_rules! int_impl { #[doc = concat!("assert_eq!(80", stringify!($SelfT), ".clamp_magnitude(100), 80);")] #[doc = concat!("assert_eq!(-80", stringify!($SelfT), ".clamp_magnitude(100), -80);")] /// ``` - #[must_use = "this returns the clamped value and does not modify the original"] - #[unstable(feature = "clamp_magnitude", issue = "148519")] #[inline] - pub fn clamp_magnitude(self, limit: $UnsignedT) -> Self { + #[must_use = "method returns a new number and does not mutate the original value"] + #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[unstable(feature = "clamp_magnitude", issue = "148519")] + pub const fn clamp_magnitude(self, limit: $UnsignedT) -> Self { if let Ok(limit) = core::convert::TryInto::<$SelfT>::try_into(limit) { self.clamp(-limit, limit) } else { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d0ae6c31267f3..37223932a0b0f 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -2454,6 +2454,32 @@ macro_rules! nonzero_integer_signedness_dependent_methods { unsafe { NonZero::new_unchecked(self.get().cast_unsigned()) } } + /// clamps this number to a symmetric range centred around zero. the method clamps the number's magnitude (absolute value) to be at most `limit`. + /// + /// this is functionally equivalent to `self.clamp(-limit, limit)`, but is more + /// explicit about the intent. + /// + /// # Examples + /// + /// ``` + /// #![feature(clamp_magnitude)] + /// # use std::num::NonZero; + /// # + #[doc = concat!("let limit = NonZero::<", stringify!($Uint), ">::new(100).unwrap();")] + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(120).unwrap().clamp_magnitude(limit), NonZero::new(100).unwrap());")] + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(-120).unwrap().clamp_magnitude(limit), NonZero::new(-100).unwrap());")] + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(80).unwrap().clamp_magnitude(limit), NonZero::new(80).unwrap());")] + #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(-80).unwrap().clamp_magnitude(limit), NonZero::new(-80).unwrap());")] + /// ``` + #[inline] + #[must_use = "method returns a new number and does not mutate the original value"] + #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[unstable(feature = "clamp_magnitude", issue = "148519")] + pub const fn clamp_magnitude(self, limit: NonZero<$Uint>) -> Self { + // SAFETY: a non-zero value clamped to the magnitude of a non-zero value is still non-zero. + unsafe { Self::new_unchecked(self.get().clamp_magnitude(limit.get())) } + } + }; } diff --git a/library/coretests/tests/num/clamp_magnitude.rs b/library/coretests/tests/num/clamp_magnitude.rs index 0f96e55f6914e..b8ba402a6660a 100644 --- a/library/coretests/tests/num/clamp_magnitude.rs +++ b/library/coretests/tests/num/clamp_magnitude.rs @@ -115,25 +115,25 @@ fn test_clamp_magnitude_f64() { } #[test] -#[should_panic(expected = "limit must be non-negative")] +#[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f32_panic_negative_limit() { let _ = 1.0f32.clamp_magnitude(-1.0); } #[test] -#[should_panic(expected = "limit must be non-negative")] +#[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f64_panic_negative_limit() { let _ = 1.0f64.clamp_magnitude(-1.0); } #[test] -#[should_panic] +#[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f32_panic_nan_limit() { let _ = 1.0f32.clamp_magnitude(f32::NAN); } #[test] -#[should_panic] +#[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f64_panic_nan_limit() { let _ = 1.0f64.clamp_magnitude(f64::NAN); } From 2ed1e372dae36015873ba21a8ab6e8252d442af1 Mon Sep 17 00:00:00 2001 From: Yukang Date: Thu, 24 Sep 2026 10:49:27 +0800 Subject: [PATCH 0754/1309] Fix applicability level for cfg suggestion --- compiler/rustc_parse/src/diagnostics.rs | 4 ++-- compiler/rustc_parse/src/parser/diagnostics.rs | 10 ++++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index c080fc9e95df7..54d91eca01327 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -1656,8 +1656,8 @@ pub(crate) enum ExpectedSemiSugg { style = "short" )] ChangeToSemi(#[primary_span] Span), - #[suggestion("add `;` here", code = ";", applicability = "machine-applicable", style = "short")] - AddSemi(#[primary_span] Span), + #[suggestion("add `;` here", code = ";", style = "short")] + AddSemi(#[primary_span] Span, #[applicability] Applicability), } #[derive(Diagnostic)] diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 928518c88fec6..5f2052dc48e7b 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -439,7 +439,7 @@ impl<'a> Parser<'a> { span, token: self.token, unexpected_token_label: Some(self.token.span), - sugg: ExpectedSemiSugg::AddSemi(span), + sugg: ExpectedSemiSugg::AddSemi(span, Applicability::MachineApplicable), }); return Ok(guar); } @@ -723,7 +723,8 @@ impl<'a> Parser<'a> { span, token: self.token, unexpected_token_label: Some(self.token.span), - sugg: ExpectedSemiSugg::AddSemi(span), + // A semicolon may discard the intended return value of a cfg-gated tail expression. + sugg: ExpectedSemiSugg::AddSemi(span, Applicability::MaybeIncorrect), }); let attr_span = match &expr.attrs[..] { [] => unreachable!(), @@ -755,7 +756,7 @@ impl<'a> Parser<'a> { (expr.span.shrink_to_lo(), "{ ".to_string()), (expr.span.shrink_to_hi(), " }".to_string()), ], - Applicability::MachineApplicable, + Applicability::MaybeIncorrect, ); // Special handling for `#[cfg(...)]` chains @@ -811,7 +812,8 @@ impl<'a> Parser<'a> { "it seems like you are trying to provide different expressions depending on \ `cfg`, consider using `if cfg!(..)`", sugg, - Applicability::MachineApplicable, + // Unlike `#[cfg]`, `if cfg!` still checks disabled branches. + Applicability::MaybeIncorrect, ); } } From c614782ce4a59e46e11e8179e44d0a1ef7063045 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Thu, 24 Sep 2026 04:34:41 +0000 Subject: [PATCH 0755/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 3670d2532bdf51abbe0b8fea22284d7ca340ffe3. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 89c3e1334a546..b9900a7795af4 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -88638df1e741778019e42fcdf307072865d19501 +3670d2532bdf51abbe0b8fea22284d7ca340ffe3 From ec11203ad6328e1ffd83d3dbb22a2e6c3d75cb45 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 24 Sep 2026 08:08:44 +0200 Subject: [PATCH 0756/1309] temporarily disable broken test on freebsd --- .../tests/pass/shims/available-parallelism-miri-num-cpus.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs index 0d96bc2f5e737..fa83de8bc127e 100644 --- a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs +++ b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs @@ -1,4 +1,6 @@ //@compile-flags: -Zmiri-num-cpus=1024 +// FIXME: Disabled on FreeBSD due to +//@ignore-target: freebsd use std::num::NonZero; use std::thread::available_parallelism; From 8231458b2933cec3316be630127ececee8e96944 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 11 Aug 2026 10:50:56 +0200 Subject: [PATCH 0757/1309] Remove an unnecessary derive --- compiler/rustc_hir/src/hir.rs | 2 +- src/librustdoc/clean/mod.rs | 4 ++-- src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs | 2 +- src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs | 3 ++- 4 files changed, 6 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 203f2bb935133..c8023c7721be3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4072,7 +4072,7 @@ pub struct Variant<'hir> { pub span: Span, } -#[derive(Copy, Clone, PartialEq, Debug, StableHash)] +#[derive(Copy, Clone, Debug, StableHash)] pub enum UseKind { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 1078f48855fbf..2220d34cc1b53 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -181,7 +181,7 @@ fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool { if let hir::Node::Item(item) = tcx.hir_node_by_def_id(import_id) && let hir::ItemKind::Use(_, use_kind) = item.kind { - use_kind == hir::UseKind::Glob + matches!(use_kind, hir::UseKind::Glob) } else { false } @@ -3232,7 +3232,7 @@ fn clean_use_statement_inner<'tcx>( // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ let path = clean_path(path, cx); - let inner = if kind == hir::UseKind::Glob { + let inner = if matches!(kind, hir::UseKind::Glob) { if !denied { let mut visited = DefIdSet::default(); if let Some(items) = inline::try_inline_glob( diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 4e982e8fb86f3..2fb4fe8be50d9 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { let def_path = cx.get_def_path(def_id); if module && let [.., module_name] = &*def_path { - if kind == UseKind::Glob { + if matches!(kind, UseKind::Glob) { diag.help(format!("remove this import and use associated constants `{module_name}::` from the primitive type instead")); } else { diag.help("remove this import").note(format!( diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 5bc73d0a5d2d0..1fe5e87c46ef2 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -86,7 +86,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { // We ignore macro exports. And `ListStem` uses, which aren't interesting. fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { if let ItemKind::Use(path, kind) = item.kind { - let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || kind == UseKind::ListStem; + let ignore = + matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || matches!(kind, UseKind::ListStem); if ignore { return true; } From 1cf068a433e88a975573bd0c9d75ce1f4cce818b Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 11 Aug 2026 11:45:03 +0200 Subject: [PATCH 0758/1309] Pull nested import printing out into a method --- compiler/rustc_hir_pretty/src/lib.rs | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ddd1a296ecd35..2ff977628a16e 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -612,18 +612,7 @@ impl<'a> State<'a> { let (cb, ib) = self.head("use"); self.print_path(path, false); - match kind { - hir::UseKind::Single(ident) => { - if path.segments.last().unwrap().ident != ident { - self.space(); - self.word_space("as"); - self.print_ident(ident); - } - self.word(";"); - } - hir::UseKind::Glob => self.word("::*;"), - hir::UseKind::ListStem => self.word("::{};"), - } + self.print_use_kind(path, kind); self.end(ib); self.end(cb); } @@ -818,6 +807,21 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Item(item)) } + fn print_use_kind(&mut self, path: &hir::UsePath<'_>, kind: hir::UseKind) { + match kind { + hir::UseKind::Single(ident) => { + if path.segments.last().unwrap().ident != ident { + self.space(); + self.word_space("as"); + self.print_ident(ident); + } + self.word(";"); + } + hir::UseKind::Glob => self.word("::*;"), + hir::UseKind::ListStem => self.word("::{};"), + } + } + fn print_trait_ref(&mut self, t: &hir::TraitRef<'_>) { self.print_path(t.path, false); } From 19a3542a4830ee4e9a0d01488689bdd914702904 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 12 Aug 2026 16:01:10 +0200 Subject: [PATCH 0759/1309] Extract res -> PerNS logic into a method --- compiler/rustc_ast_lowering/src/item.rs | 17 ++--------------- compiler/rustc_hir/src/def.rs | 19 +++++++++++++++++++ 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 33b73ed30c518..8cf7846b89194 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -9,7 +9,7 @@ use rustc_hir::{self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateO use rustc_middle::ty::data_structures::IndexMap; use rustc_span::def_id::{DefId, LocalDefId}; use rustc_span::edit_distance::find_best_match_for_name; -use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, span_bug, sym}; +use rustc_span::{DUMMY_SP, DesugaringKind, Ident, Span, Symbol, kw, sym}; use smallvec::SmallVec; use thin_vec::ThinVec; use tracing::instrument; @@ -583,20 +583,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = self.expect_full_res(id); let res = self.lower_res(res); // Put the result in the appropriate namespace. - let res = match res { - Res::Def(DefKind::Mod | DefKind::Trait, _) => { - PerNS { type_ns: Some(res), value_ns: None, macro_ns: None } - } - Res::Def(DefKind::Enum, _) => { - PerNS { type_ns: None, value_ns: Some(res), macro_ns: None } - } - Res::Err => { - // Propagate the error to all namespaces, just to be sure. - let err = Some(Res::Err); - PerNS { type_ns: err, value_ns: err, macro_ns: err } - } - _ => span_bug!(path.span, "bad glob res {:?}", res), - }; + let res = res.in_namespace(); let path = Path { segments, span: path.span }; let path = self.lower_use_path(res, &path, ParamMode::Explicit); hir::ItemKind::Use(path, hir::UseKind::Glob) diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index 34a7c389d5158..a16c55a53bf09 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -587,6 +587,25 @@ pub enum Res { Err, } +impl Res { + pub fn in_namespace(self) -> PerNS> { + match self { + Res::Def(DefKind::Mod | DefKind::Trait, _) => { + PerNS { type_ns: Some(self), value_ns: None, macro_ns: None } + } + Res::Def(DefKind::Enum, _) => { + PerNS { type_ns: None, value_ns: Some(self), macro_ns: None } + } + Res::Err => { + // Propagate the error to all namespaces, just to be sure. + let err = Some(Res::Err); + PerNS { type_ns: err, value_ns: err, macro_ns: err } + } + _ => panic!("bad path segment res {self:?}"), + } + } +} + impl IntoDiagArg for Res { fn into_diag_arg(self, _: &mut Option) -> DiagArgValue { DiagArgValue::Str(Cow::Borrowed(self.descr())) From 6dc404096d5ccce13f71295b681b2b33b73e0497 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 13 Aug 2026 09:35:35 +0200 Subject: [PATCH 0760/1309] Remove an argument that is the same everywhere --- compiler/rustc_resolve/src/check_unused.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index fdac03a8f7163..68fbb139e9041 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -89,7 +89,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // Check later. return; } - self.unused_import(self.base_id).add(id); + self.unused_import().add(id); } else { // This trait import is definitely used, in a way other than // method resolution. @@ -111,19 +111,19 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { if let ast::UseTreeKind::Nested { ref items, .. } = use_tree.kind { if items.is_empty() { - self.unused_import(self.base_id).add(id); + self.unused_import().add(id); } } else { self.check_import(id, def_id); } } - fn unused_import(&mut self, id: ast::NodeId) -> &mut UnusedImport { + fn unused_import(&mut self) -> &mut UnusedImport { let use_tree_id = self.base_id; let use_tree = self.base_use_tree.unwrap().clone(); let item_span = self.item_span; - self.unused_imports.entry(id).or_insert_with(|| UnusedImport { + self.unused_imports.entry(self.base_id).or_insert_with(|| UnusedImport { use_tree, use_tree_id, item_span, @@ -140,7 +140,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) ) { - self.unused_import(self.base_id).add(id); + self.unused_import().add(id); } } ast::UseTreeKind::Nested { ref items, .. } => self.check_imports_as_underscore(items), From f3ad84dfb98f5d64e02ee2b01793cbd15979da03 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 14 Aug 2026 15:48:17 +0200 Subject: [PATCH 0761/1309] Remove a level of indentation and make later filtering easier --- compiler/rustc_lint/src/builtin.rs | 63 +++++++++++++++--------------- 1 file changed, 32 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index bba993ee3f052..bf92b0a0c55d3 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1148,40 +1148,41 @@ impl UnreachablePub { exportable: bool, ) { let mut applicability = Applicability::MachineApplicable; - if cx.tcx.visibility(def_id).is_public() && !cx.effective_visibilities.is_reachable(def_id) + if !cx.tcx.visibility(def_id).is_public() || cx.effective_visibilities.is_reachable(def_id) { - // prefer suggesting `pub(super)` instead of `pub(crate)` when possible, - // except when `pub(super) == pub(crate)` - let new_vis = if let Some(ty::Visibility::Restricted(restricted_did)) = - cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| { - effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable) - }) - && let parent_parent = cx - .tcx - .parent_module_from_def_id(cx.tcx.parent_module_from_def_id(def_id).into()) - && *restricted_did == parent_parent - && !restricted_did.to_def_id().is_crate_root() - { - "pub(super)" - } else { - "pub(crate)" - }; + return; + } - if vis_span.from_expansion() { - applicability = Applicability::MaybeIncorrect; - } - let def_span = cx.tcx.def_span(def_id); - cx.emit_span_lint( - UNREACHABLE_PUB, - def_span, - BuiltinUnreachablePub { - what, - new_vis, - suggestion: (vis_span, applicability), - help: exportable, - }, - ); + // prefer suggesting `pub(super)` instead of `pub(crate)` when possible, + // except when `pub(super) == pub(crate)` + let new_vis = if let Some(ty::Visibility::Restricted(restricted_did)) = + cx.effective_visibilities.effective_vis(def_id).map(|effective_vis| { + effective_vis.at_level(rustc_middle::middle::privacy::Level::Reachable) + }) + && let parent_parent = + cx.tcx.parent_module_from_def_id(cx.tcx.parent_module_from_def_id(def_id).into()) + && *restricted_did == parent_parent + && !restricted_did.to_def_id().is_crate_root() + { + "pub(super)" + } else { + "pub(crate)" + }; + + if vis_span.from_expansion() { + applicability = Applicability::MaybeIncorrect; } + let def_span = cx.tcx.def_span(def_id); + cx.emit_span_lint( + UNREACHABLE_PUB, + def_span, + BuiltinUnreachablePub { + what, + new_vis, + suggestion: (vis_span, applicability), + help: exportable, + }, + ); } } From dddbe9075636c5daad428b3ae532d803e71d12e8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 11 Aug 2026 10:50:56 +0200 Subject: [PATCH 0762/1309] Remove an unnecessary derive --- clippy_lints/src/legacy_numeric_constants.rs | 2 +- clippy_lints/src/redundant_pub_crate.rs | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index 4e982e8fb86f3..2fb4fe8be50d9 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -85,7 +85,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { let def_path = cx.get_def_path(def_id); if module && let [.., module_name] = &*def_path { - if kind == UseKind::Glob { + if matches!(kind, UseKind::Glob) { diag.help(format!("remove this import and use associated constants `{module_name}::` from the primitive type instead")); } else { diag.help("remove this import").note(format!( diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs index 5bc73d0a5d2d0..1fe5e87c46ef2 100644 --- a/clippy_lints/src/redundant_pub_crate.rs +++ b/clippy_lints/src/redundant_pub_crate.rs @@ -86,7 +86,8 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { // We ignore macro exports. And `ListStem` uses, which aren't interesting. fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { if let ItemKind::Use(path, kind) = item.kind { - let ignore = matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || kind == UseKind::ListStem; + let ignore = + matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || matches!(kind, UseKind::ListStem); if ignore { return true; } From f8f1dc284d48ec282abd94e9d43d4c3de149117c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9C=9D=E5=80=89=E6=B0=B4=E5=B8=8C?= Date: Wed, 23 Sep 2026 23:59:51 +0800 Subject: [PATCH 0763/1309] Enable EII tests for cg_gcc --- tests/ui/eii/default/call_default.rs | 1 - tests/ui/eii/default/call_default_panics.rs | 1 - tests/ui/eii/default/call_impl.rs | 1 - tests/ui/eii/default/local_crate.rs | 1 - tests/ui/eii/default/local_crate_explicit.rs | 1 - tests/ui/eii/default/local_crate_explicit.stderr | 2 +- tests/ui/eii/duplicate/both_decl_and_impl.rs | 1 - tests/ui/eii/duplicate/both_decl_and_impl.stderr | 8 ++++---- tests/ui/eii/duplicate/duplicate1.rs | 1 - tests/ui/eii/duplicate/duplicate2.rs | 1 - tests/ui/eii/duplicate/duplicate3.rs | 1 - tests/ui/eii/duplicate/dylib_default_duplicate.rs | 1 - tests/ui/eii/duplicate/dylib_default_duplicate.stderr | 2 +- tests/ui/eii/duplicate/multiple_impls.rs | 1 - tests/ui/eii/duplicate/multiple_impls.stderr | 8 ++++---- tests/ui/eii/eii_impl_with_contract.rs | 1 - tests/ui/eii/linking/codegen_cross_crate.rs | 1 - tests/ui/eii/linking/codegen_single_crate.rs | 1 - tests/ui/eii/linking/same-symbol.rs | 1 - tests/ui/eii/linking/track_caller_cross_crate.rs | 1 - tests/ui/eii/privacy1.rs | 1 - tests/ui/eii/shadow_builtin.rs | 1 - tests/ui/eii/shadow_builtin.stderr | 6 +++--- tests/ui/eii/static/argument_required.rs | 1 - tests/ui/eii/static/argument_required.stderr | 2 +- tests/ui/eii/static/cross_crate_decl.rs | 1 - tests/ui/eii/static/cross_crate_def.rs | 1 - tests/ui/eii/static/default.rs | 1 - tests/ui/eii/static/default_apple.rs | 1 - tests/ui/eii/static/default_apple.stderr | 2 +- tests/ui/eii/static/default_cross_crate.rs | 1 - tests/ui/eii/static/default_cross_crate_explicit.rs | 1 - tests/ui/eii/static/default_explicit.rs | 1 - tests/ui/eii/static/duplicate.rs | 1 - tests/ui/eii/static/duplicate.stderr | 2 +- tests/ui/eii/static/mismatch_fn_static.rs | 1 - tests/ui/eii/static/mismatch_fn_static.stderr | 2 +- tests/ui/eii/static/mismatch_mut.rs | 1 - tests/ui/eii/static/mismatch_mut.stderr | 4 ++-- tests/ui/eii/static/mismatch_mut2.rs | 1 - tests/ui/eii/static/mismatch_mut2.stderr | 2 +- tests/ui/eii/static/mismatch_safety.rs | 1 - tests/ui/eii/static/mismatch_safety.stderr | 2 +- tests/ui/eii/static/mismatch_safety2.rs | 1 - tests/ui/eii/static/mismatch_safety2.stderr | 2 +- tests/ui/eii/static/mismatch_static_fn.rs | 1 - tests/ui/eii/static/mismatch_static_fn.stderr | 2 +- tests/ui/eii/static/mut.rs | 1 - tests/ui/eii/static/mut.stderr | 2 +- tests/ui/eii/static/same_address.rs | 1 - tests/ui/eii/static/simple.rs | 1 - tests/ui/eii/static/subtype.rs | 1 - tests/ui/eii/static/subtype_wrong.rs | 1 - tests/ui/eii/static/subtype_wrong.stderr | 2 +- tests/ui/eii/static/wrong_ty.rs | 1 - tests/ui/eii/static/wrong_ty.stderr | 4 ++-- tests/ui/eii/track_caller.rs | 1 - 57 files changed, 27 insertions(+), 67 deletions(-) diff --git a/tests/ui/eii/default/call_default.rs b/tests/ui/eii/default/call_default.rs index 7769ae00bb0f5..db5b7da45d470 100644 --- a/tests/ui/eii/default/call_default.rs +++ b/tests/ui/eii/default/call_default.rs @@ -3,7 +3,6 @@ //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/call_default_panics.rs b/tests/ui/eii/default/call_default_panics.rs index d027748b0ffb3..526e71856046b 100644 --- a/tests/ui/eii/default/call_default_panics.rs +++ b/tests/ui/eii/default/call_default_panics.rs @@ -5,7 +5,6 @@ //@ run-pass //@ needs-unwind //@ exec-env:RUST_BACKTRACE=1 -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // A small test to make sure that unwinding works properly. diff --git a/tests/ui/eii/default/call_impl.rs b/tests/ui/eii/default/call_impl.rs index 4b64033a940f5..7f7d5d0163cfb 100644 --- a/tests/ui/eii/default/call_impl.rs +++ b/tests/ui/eii/default/call_impl.rs @@ -4,7 +4,6 @@ //@ aux-build: impl1.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate.rs b/tests/ui/eii/default/local_crate.rs index d6e992c409453..bf97c8bd2fd68 100644 --- a/tests/ui/eii/default/local_crate.rs +++ b/tests/ui/eii/default/local_crate.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate_explicit.rs b/tests/ui/eii/default/local_crate_explicit.rs index 7c29fa0edd6ae..c2e52f8bd174a 100644 --- a/tests/ui/eii/default/local_crate_explicit.rs +++ b/tests/ui/eii/default/local_crate_explicit.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests EIIs with default implementations. diff --git a/tests/ui/eii/default/local_crate_explicit.stderr b/tests/ui/eii/default/local_crate_explicit.stderr index d80acf14c516d..51b4d9b545b3d 100644 --- a/tests/ui/eii/default/local_crate_explicit.stderr +++ b/tests/ui/eii/default/local_crate_explicit.stderr @@ -1,5 +1,5 @@ warning: function `decl1` is never used - --> $DIR/local_crate_explicit.rs:11:8 + --> $DIR/local_crate_explicit.rs:10:8 | LL | pub fn decl1(x: u64) { | ^^^^^ diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.rs b/tests/ui/eii/duplicate/both_decl_and_impl.rs index a2fc571d3f497..9cf122e40aac3 100644 --- a/tests/ui/eii/duplicate/both_decl_and_impl.rs +++ b/tests/ui/eii/duplicate/both_decl_and_impl.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that one item can't both define and impl an EII at the same time diff --git a/tests/ui/eii/duplicate/both_decl_and_impl.stderr b/tests/ui/eii/duplicate/both_decl_and_impl.stderr index 1cec485a90cff..d109eaee95a5e 100644 --- a/tests/ui/eii/duplicate/both_decl_and_impl.stderr +++ b/tests/ui/eii/duplicate/both_decl_and_impl.stderr @@ -1,23 +1,23 @@ error: a single item cannot both declare and implement EIIs - --> $DIR/both_decl_and_impl.rs:11:1 + --> $DIR/both_decl_and_impl.rs:10:1 | LL | #[eii] | ^^^^^^ error: only a small subset of attributes are supported on externally implementable items - --> $DIR/both_decl_and_impl.rs:21:1 + --> $DIR/both_decl_and_impl.rs:20:1 | LL | fn d(x: u64) {} | ^^^^^^^^^^^^ | note: this attribute is not supported - --> $DIR/both_decl_and_impl.rs:20:1 + --> $DIR/both_decl_and_impl.rs:19:1 | LL | #[c] | ^^^^ error: `#[c]` function required, but not found - --> $DIR/both_decl_and_impl.rs:16:4 + --> $DIR/both_decl_and_impl.rs:15:4 | LL | fn c(x: u64); | ^ expected because `#[c]` was declared here in crate `both_decl_and_impl` diff --git a/tests/ui/eii/duplicate/duplicate1.rs b/tests/ui/eii/duplicate/duplicate1.rs index 54803f31c85f4..9dc9038bec059 100644 --- a/tests/ui/eii/duplicate/duplicate1.rs +++ b/tests/ui/eii/duplicate/duplicate1.rs @@ -2,7 +2,6 @@ //@[dylib] needs-crate-type: dylib //@ aux-build: impl1.rs //@ aux-build: impl2.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // tests that EIIs error properly, even if the conflicting implementations live in another crate. diff --git a/tests/ui/eii/duplicate/duplicate2.rs b/tests/ui/eii/duplicate/duplicate2.rs index 8b4d7c4913c91..95121e1e6d9b8 100644 --- a/tests/ui/eii/duplicate/duplicate2.rs +++ b/tests/ui/eii/duplicate/duplicate2.rs @@ -1,7 +1,6 @@ //@ aux-build: impl1.rs //@ aux-build: impl2.rs //@ aux-build: impl3.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests the error message when there are multiple implementations of an EII in many crates. diff --git a/tests/ui/eii/duplicate/duplicate3.rs b/tests/ui/eii/duplicate/duplicate3.rs index 96d6543130ccb..d50b87865109b 100644 --- a/tests/ui/eii/duplicate/duplicate3.rs +++ b/tests/ui/eii/duplicate/duplicate3.rs @@ -2,7 +2,6 @@ //@ aux-build: impl2.rs //@ aux-build: impl3.rs //@ aux-build: impl4.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests the error message when there are multiple implementations of an EII in many crates. diff --git a/tests/ui/eii/duplicate/dylib_default_duplicate.rs b/tests/ui/eii/duplicate/dylib_default_duplicate.rs index 5480bb13b4a49..a72a137eb9709 100644 --- a/tests/ui/eii/duplicate/dylib_default_duplicate.rs +++ b/tests/ui/eii/duplicate/dylib_default_duplicate.rs @@ -1,7 +1,6 @@ //@ aux-build: dylib_default.rs //@ needs-crate-type: dylib //@ compile-flags: --emit link -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Regression test for https://github.com/rust-lang/rust/issues/156320. diff --git a/tests/ui/eii/duplicate/dylib_default_duplicate.stderr b/tests/ui/eii/duplicate/dylib_default_duplicate.stderr index 04c6a13710e28..91c90edb02449 100644 --- a/tests/ui/eii/duplicate/dylib_default_duplicate.stderr +++ b/tests/ui/eii/duplicate/dylib_default_duplicate.stderr @@ -1,5 +1,5 @@ error: multiple implementations of `#[eii1]` - --> $DIR/dylib_default_duplicate.rs:15:1 + --> $DIR/dylib_default_duplicate.rs:14:1 | LL | fn other(x: u64) { | ^^^^^^^^^^^^^^^^ first implemented here in crate `dylib_default_duplicate` diff --git a/tests/ui/eii/duplicate/multiple_impls.rs b/tests/ui/eii/duplicate/multiple_impls.rs index 3e541cb16b131..8f1feaa530adb 100644 --- a/tests/ui/eii/duplicate/multiple_impls.rs +++ b/tests/ui/eii/duplicate/multiple_impls.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that one item can't implement two EIIs diff --git a/tests/ui/eii/duplicate/multiple_impls.stderr b/tests/ui/eii/duplicate/multiple_impls.stderr index efeec635c859a..b2e8871d2087a 100644 --- a/tests/ui/eii/duplicate/multiple_impls.stderr +++ b/tests/ui/eii/duplicate/multiple_impls.stderr @@ -1,17 +1,17 @@ error: a single item cannot implement multiple EIIs - --> $DIR/multiple_impls.rs:15:1 + --> $DIR/multiple_impls.rs:14:1 | LL | #[b] | ^^^^ error: a single item cannot implement multiple EIIs - --> $DIR/multiple_impls.rs:29:1 + --> $DIR/multiple_impls.rs:28:1 | LL | #[d] | ^^^^ error: `#[a]` function required, but not found - --> $DIR/multiple_impls.rs:8:4 + --> $DIR/multiple_impls.rs:7:4 | LL | fn a(x: u64); | ^ expected because `#[a]` was declared here in crate `multiple_impls` @@ -19,7 +19,7 @@ LL | fn a(x: u64); = help: expected at least one implementation in crate `multiple_impls` or any of its dependencies error: `#[c]` static required, but not found - --> $DIR/multiple_impls.rs:21:7 + --> $DIR/multiple_impls.rs:20:7 | LL | #[eii(c)] | ^ expected because `#[c]` was declared here in crate `multiple_impls` diff --git a/tests/ui/eii/eii_impl_with_contract.rs b/tests/ui/eii/eii_impl_with_contract.rs index 1789ec92ea60d..a33d7a0c23751 100644 --- a/tests/ui/eii/eii_impl_with_contract.rs +++ b/tests/ui/eii/eii_impl_with_contract.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu diff --git a/tests/ui/eii/linking/codegen_cross_crate.rs b/tests/ui/eii/linking/codegen_cross_crate.rs index ab0d4d4b9eb25..f11c8a04661b6 100644 --- a/tests/ui/eii/linking/codegen_cross_crate.rs +++ b/tests/ui/eii/linking/codegen_cross_crate.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: codegen_cross_crate_other_crate.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in another crate. diff --git a/tests/ui/eii/linking/codegen_single_crate.rs b/tests/ui/eii/linking/codegen_single_crate.rs index 4faa30a79040f..81b56cd4261ba 100644 --- a/tests/ui/eii/linking/codegen_single_crate.rs +++ b/tests/ui/eii/linking/codegen_single_crate.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in the same crate. diff --git a/tests/ui/eii/linking/same-symbol.rs b/tests/ui/eii/linking/same-symbol.rs index 02518f6bced03..57af6357f3de4 100644 --- a/tests/ui/eii/linking/same-symbol.rs +++ b/tests/ui/eii/linking/same-symbol.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu #![feature(extern_item_impls)] diff --git a/tests/ui/eii/linking/track_caller_cross_crate.rs b/tests/ui/eii/linking/track_caller_cross_crate.rs index e8ba5dc2b864b..b8d0d53336c39 100644 --- a/tests/ui/eii/linking/track_caller_cross_crate.rs +++ b/tests/ui/eii/linking/track_caller_cross_crate.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: track_caller_cross_other_crate.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that `#[track_caller]` on an EII declaration in one crate is derived diff --git a/tests/ui/eii/privacy1.rs b/tests/ui/eii/privacy1.rs index 95544ae867d89..e342441546513 100644 --- a/tests/ui/eii/privacy1.rs +++ b/tests/ui/eii/privacy1.rs @@ -1,7 +1,6 @@ //@ run-pass //@ check-run-results //@ aux-build: other_crate_privacy1.rs -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether re-exports work. diff --git a/tests/ui/eii/shadow_builtin.rs b/tests/ui/eii/shadow_builtin.rs index cd4c14514dc46..f9447b85273af 100644 --- a/tests/ui/eii/shadow_builtin.rs +++ b/tests/ui/eii/shadow_builtin.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in the same crate. diff --git a/tests/ui/eii/shadow_builtin.stderr b/tests/ui/eii/shadow_builtin.stderr index 33f60b2d2f13f..bdb580785d15c 100644 --- a/tests/ui/eii/shadow_builtin.stderr +++ b/tests/ui/eii/shadow_builtin.stderr @@ -1,5 +1,5 @@ error[E0659]: `inline` is ambiguous - --> $DIR/shadow_builtin.rs:11:3 + --> $DIR/shadow_builtin.rs:10:3 | LL | #[inline] | ^^^^^^ ambiguous name @@ -7,14 +7,14 @@ LL | #[inline] = note: ambiguous because of a name conflict with a builtin attribute = note: `inline` could refer to a built-in attribute note: `inline` could also refer to the attribute macro defined here - --> $DIR/shadow_builtin.rs:7:1 + --> $DIR/shadow_builtin.rs:6:1 | LL | #[eii(inline)] | ^^^^^^^^^^^^^^ = help: use `crate::inline` to refer to this attribute macro unambiguously error: `#[inline]` function required, but not found - --> $DIR/shadow_builtin.rs:7:7 + --> $DIR/shadow_builtin.rs:6:7 | LL | #[eii(inline)] | ^^^^^^ expected because `#[inline]` was declared here in crate `shadow_builtin` diff --git a/tests/ui/eii/static/argument_required.rs b/tests/ui/eii/static/argument_required.rs index 9b00dcf194387..e8f66e083e983 100644 --- a/tests/ui/eii/static/argument_required.rs +++ b/tests/ui/eii/static/argument_required.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/argument_required.stderr b/tests/ui/eii/static/argument_required.stderr index 9e5ee398f77d8..9f722d2065e1e 100644 --- a/tests/ui/eii/static/argument_required.stderr +++ b/tests/ui/eii/static/argument_required.stderr @@ -1,5 +1,5 @@ error: `#[eii]` requires the name as an explicit argument when used on a static - --> $DIR/argument_required.rs:7:1 + --> $DIR/argument_required.rs:6:1 | LL | #[eii] | ^^^^^^ diff --git a/tests/ui/eii/static/cross_crate_decl.rs b/tests/ui/eii/static/cross_crate_decl.rs index 75333c48e40ef..ba038102099f5 100644 --- a/tests/ui/eii/static/cross_crate_decl.rs +++ b/tests/ui/eii/static/cross_crate_decl.rs @@ -2,7 +2,6 @@ //@ check-run-results //@ aux-build: cross_crate_decl.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration in another crate. diff --git a/tests/ui/eii/static/cross_crate_def.rs b/tests/ui/eii/static/cross_crate_def.rs index 19dbdaadeef05..0461c1dfe7398 100644 --- a/tests/ui/eii/static/cross_crate_def.rs +++ b/tests/ui/eii/static/cross_crate_def.rs @@ -4,7 +4,6 @@ //@ check-run-results //@ aux-build: cross_crate_def.rs //@ compile-flags: -O -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether calling EIIs works with the declaration and definition in another crate. diff --git a/tests/ui/eii/static/default.rs b/tests/ui/eii/static/default.rs index beb777cc32e82..c4e2208337914 100644 --- a/tests/ui/eii/static/default.rs +++ b/tests/ui/eii/static/default.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_apple.rs b/tests/ui/eii/static/default_apple.rs index f638ee480f4cb..38446a2d17150 100644 --- a/tests/ui/eii/static/default_apple.rs +++ b/tests/ui/eii/static/default_apple.rs @@ -1,5 +1,4 @@ //@ only-apple -//@ ignore-backends: gcc #![feature(extern_item_impls)] #![crate_type = "lib"] diff --git a/tests/ui/eii/static/default_apple.stderr b/tests/ui/eii/static/default_apple.stderr index d4ced5948970d..3fbcde6dbb9a5 100644 --- a/tests/ui/eii/static/default_apple.stderr +++ b/tests/ui/eii/static/default_apple.stderr @@ -1,5 +1,5 @@ error: `#[eii]` cannot be used on statics with a value on Apple targets - --> $DIR/default_apple.rs:7:25 + --> $DIR/default_apple.rs:6:25 | LL | pub static DECL1: u64 = 5; | ^ diff --git a/tests/ui/eii/static/default_cross_crate.rs b/tests/ui/eii/static/default_cross_crate.rs index 9d6df257ffbef..a53c73876d977 100644 --- a/tests/ui/eii/static/default_cross_crate.rs +++ b/tests/ui/eii/static/default_cross_crate.rs @@ -3,7 +3,6 @@ //@ aux-build: decl_with_default.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_cross_crate_explicit.rs b/tests/ui/eii/static/default_cross_crate_explicit.rs index 6ad015b9b601b..4835e2ed323ab 100644 --- a/tests/ui/eii/static/default_cross_crate_explicit.rs +++ b/tests/ui/eii/static/default_cross_crate_explicit.rs @@ -4,7 +4,6 @@ //@ aux-build: impl_default_override.rs //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/default_explicit.rs b/tests/ui/eii/static/default_explicit.rs index 8237b18106031..bc3f44e7e01b5 100644 --- a/tests/ui/eii/static/default_explicit.rs +++ b/tests/ui/eii/static/default_explicit.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // FIXME(#157649): static EII defaults currently fail to link on Apple targets. diff --git a/tests/ui/eii/static/duplicate.rs b/tests/ui/eii/static/duplicate.rs index a8db02f33051d..54cab82f617e7 100644 --- a/tests/ui/eii/static/duplicate.rs +++ b/tests/ui/eii/static/duplicate.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/duplicate.stderr b/tests/ui/eii/static/duplicate.stderr index 270664c8c74c6..e967e9c4e65c8 100644 --- a/tests/ui/eii/static/duplicate.stderr +++ b/tests/ui/eii/static/duplicate.stderr @@ -1,5 +1,5 @@ error: multiple implementations of `#[hello]` - --> $DIR/duplicate.rs:11:1 + --> $DIR/duplicate.rs:10:1 | LL | static HELLO_IMPL1: u64 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^ first implemented here in crate `duplicate` diff --git a/tests/ui/eii/static/mismatch_fn_static.rs b/tests/ui/eii/static/mismatch_fn_static.rs index 8d8fa5b4d06c4..49003388526f8 100644 --- a/tests/ui/eii/static/mismatch_fn_static.rs +++ b/tests/ui/eii/static/mismatch_fn_static.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_fn_static.stderr b/tests/ui/eii/static/mismatch_fn_static.stderr index e8fa5f85b1f13..e8be6ccb7ef57 100644 --- a/tests/ui/eii/static/mismatch_fn_static.stderr +++ b/tests/ui/eii/static/mismatch_fn_static.stderr @@ -1,5 +1,5 @@ error: `#[hello]` must be used on a function - --> $DIR/mismatch_fn_static.rs:10:1 + --> $DIR/mismatch_fn_static.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_mut.rs b/tests/ui/eii/static/mismatch_mut.rs index 61c806fb976ca..b0e35b2bf84dc 100644 --- a/tests/ui/eii/static/mismatch_mut.rs +++ b/tests/ui/eii/static/mismatch_mut.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_mut.stderr b/tests/ui/eii/static/mismatch_mut.stderr index 537ac0de3c3a2..0812652a6a1bc 100644 --- a/tests/ui/eii/static/mismatch_mut.stderr +++ b/tests/ui/eii/static/mismatch_mut.stderr @@ -1,11 +1,11 @@ error: `#[eii]` cannot be used on mutable statics - --> $DIR/mismatch_mut.rs:7:1 + --> $DIR/mismatch_mut.rs:6:1 | LL | #[eii(hello)] | ^^^^^^^^^^^^^ error: mutability does not match with the definition of`#[hello]` - --> $DIR/mismatch_mut.rs:11:1 + --> $DIR/mismatch_mut.rs:10:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_mut2.rs b/tests/ui/eii/static/mismatch_mut2.rs index ff21af5f0d714..f083e713d1769 100644 --- a/tests/ui/eii/static/mismatch_mut2.rs +++ b/tests/ui/eii/static/mismatch_mut2.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_mut2.stderr b/tests/ui/eii/static/mismatch_mut2.stderr index 6ac3df57697db..b4b953d61a23f 100644 --- a/tests/ui/eii/static/mismatch_mut2.stderr +++ b/tests/ui/eii/static/mismatch_mut2.stderr @@ -1,5 +1,5 @@ error: mutability does not match with the definition of`#[hello]` - --> $DIR/mismatch_mut2.rs:10:1 + --> $DIR/mismatch_mut2.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_safety.rs b/tests/ui/eii/static/mismatch_safety.rs index b8d503adc2d21..667c6fff14189 100644 --- a/tests/ui/eii/static/mismatch_safety.rs +++ b/tests/ui/eii/static/mismatch_safety.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_safety.stderr b/tests/ui/eii/static/mismatch_safety.stderr index d4fa85778ae11..19a3b0dd86639 100644 --- a/tests/ui/eii/static/mismatch_safety.stderr +++ b/tests/ui/eii/static/mismatch_safety.stderr @@ -1,5 +1,5 @@ error: safety does not match with the definition of`#[hello]` - --> $DIR/mismatch_safety.rs:10:1 + --> $DIR/mismatch_safety.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_safety2.rs b/tests/ui/eii/static/mismatch_safety2.rs index 412e2a694c1fc..5240184f6ada5 100644 --- a/tests/ui/eii/static/mismatch_safety2.rs +++ b/tests/ui/eii/static/mismatch_safety2.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_safety2.stderr b/tests/ui/eii/static/mismatch_safety2.stderr index 6957a6202b614..c49f55f2b911a 100644 --- a/tests/ui/eii/static/mismatch_safety2.stderr +++ b/tests/ui/eii/static/mismatch_safety2.stderr @@ -1,5 +1,5 @@ error: static items cannot be declared with `unsafe` safety qualifier outside of `extern` block - --> $DIR/mismatch_safety2.rs:11:1 + --> $DIR/mismatch_safety2.rs:10:1 | LL | unsafe static HELLO_IMPL: u64 = 5; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/eii/static/mismatch_static_fn.rs b/tests/ui/eii/static/mismatch_static_fn.rs index 06e3d95b7cdcb..b4fd139959d68 100644 --- a/tests/ui/eii/static/mismatch_static_fn.rs +++ b/tests/ui/eii/static/mismatch_static_fn.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mismatch_static_fn.stderr b/tests/ui/eii/static/mismatch_static_fn.stderr index 639e3cfa3beb3..56ea50c00fdd0 100644 --- a/tests/ui/eii/static/mismatch_static_fn.stderr +++ b/tests/ui/eii/static/mismatch_static_fn.stderr @@ -1,5 +1,5 @@ error: `#[hello]` must be used on a static - --> $DIR/mismatch_static_fn.rs:10:1 + --> $DIR/mismatch_static_fn.rs:9:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/static/mut.rs b/tests/ui/eii/static/mut.rs index 4c9d84061fb25..c351a6df8fbd2 100644 --- a/tests/ui/eii/static/mut.rs +++ b/tests/ui/eii/static/mut.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/mut.stderr b/tests/ui/eii/static/mut.stderr index cd3a0ca23c7f4..299737d1f07b6 100644 --- a/tests/ui/eii/static/mut.stderr +++ b/tests/ui/eii/static/mut.stderr @@ -1,5 +1,5 @@ error: `#[eii]` cannot be used on mutable statics - --> $DIR/mut.rs:7:1 + --> $DIR/mut.rs:6:1 | LL | #[eii(hello)] | ^^^^^^^^^^^^^ diff --git a/tests/ui/eii/static/same_address.rs b/tests/ui/eii/static/same_address.rs index de316b9f5f9ff..a49ffd9a552b7 100644 --- a/tests/ui/eii/static/same_address.rs +++ b/tests/ui/eii/static/same_address.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs and their declarations share the same address diff --git a/tests/ui/eii/static/simple.rs b/tests/ui/eii/static/simple.rs index a592609e9153a..84d49bcef638a 100644 --- a/tests/ui/eii/static/simple.rs +++ b/tests/ui/eii/static/simple.rs @@ -1,6 +1,5 @@ //@ run-pass //@ check-run-results -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests whether EIIs work on statics diff --git a/tests/ui/eii/static/subtype.rs b/tests/ui/eii/static/subtype.rs index 4553d7b8c59c0..a417838e2f7b0 100644 --- a/tests/ui/eii/static/subtype.rs +++ b/tests/ui/eii/static/subtype.rs @@ -1,5 +1,4 @@ //@ check-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/subtype_wrong.rs b/tests/ui/eii/static/subtype_wrong.rs index ac975592a0f08..9d67d7b458cc7 100644 --- a/tests/ui/eii/static/subtype_wrong.rs +++ b/tests/ui/eii/static/subtype_wrong.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/subtype_wrong.stderr b/tests/ui/eii/static/subtype_wrong.stderr index a20074947c15d..77a1353aecc32 100644 --- a/tests/ui/eii/static/subtype_wrong.stderr +++ b/tests/ui/eii/static/subtype_wrong.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/subtype_wrong.rs:13:1 + --> $DIR/subtype_wrong.rs:12:1 | LL | static HELLO_IMPL: for<'a> fn(&'a u8) -> &'a u8 = |_| todo!(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other diff --git a/tests/ui/eii/static/wrong_ty.rs b/tests/ui/eii/static/wrong_ty.rs index 40b7859b06b01..4f320603c512f 100644 --- a/tests/ui/eii/static/wrong_ty.rs +++ b/tests/ui/eii/static/wrong_ty.rs @@ -1,4 +1,3 @@ -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that mismatching types of the declaration and definition are rejected diff --git a/tests/ui/eii/static/wrong_ty.stderr b/tests/ui/eii/static/wrong_ty.stderr index 5095513527747..b7569ea82b77f 100644 --- a/tests/ui/eii/static/wrong_ty.stderr +++ b/tests/ui/eii/static/wrong_ty.stderr @@ -1,11 +1,11 @@ error[E0806]: static `HELLO_IMPL` has a type that is incompatible with the declaration of `#[hello]` - --> $DIR/wrong_ty.rs:13:1 + --> $DIR/wrong_ty.rs:12:1 | LL | static HELLO_IMPL: bool = true; | ^^^^^^^^^^^^^^^^^^^^^^^ | note: expected this because of this attribute - --> $DIR/wrong_ty.rs:12:1 + --> $DIR/wrong_ty.rs:11:1 | LL | #[hello] | ^^^^^^^^ diff --git a/tests/ui/eii/track_caller.rs b/tests/ui/eii/track_caller.rs index 5e298fba9675a..52807428f20d0 100644 --- a/tests/ui/eii/track_caller.rs +++ b/tests/ui/eii/track_caller.rs @@ -1,5 +1,4 @@ //@ run-pass -//@ ignore-backends: gcc // FIXME(#125418): linking on Windows GNU targets is not yet supported. //@ ignore-windows-gnu // Tests that `#[track_caller]` on an EII declaration is threaded through both From 67afe3876d125429c626a3d92199480c992df385 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 23 Sep 2026 22:47:46 +0200 Subject: [PATCH 0764/1309] Update rustc version to `2026-09-24` --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f3106ee20c331..a7774784e3afa 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-22" +channel = "nightly-2026-09-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 5ed0180b646917d5bd4c414ab6ffa5d3e9d317f0 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 8 Jul 2026 18:03:01 +0000 Subject: [PATCH 0765/1309] Build a new incr comp session dir from scratch every time Rather than copying the old incr comp dir and then modifying it. This saves a copy/hardlink for files that are modified. And it removes the need for accurate work product tracking to avoid accumulating cruft, which is non-trivial. We don't accurately track the pre-LTO bitcode files for ThinLTO for example. --- .../rustc_codegen_cranelift/src/driver/aot.rs | 1 - compiler/rustc_codegen_llvm/src/back/lto.rs | 36 +- compiler/rustc_codegen_ssa/src/back/write.rs | 50 ++- compiler/rustc_codegen_ssa/src/base.rs | 4 + compiler/rustc_codegen_ssa/src/lib.rs | 2 - compiler/rustc_incremental/src/diagnostics.rs | 22 -- compiler/rustc_incremental/src/lib.rs | 3 +- compiler/rustc_incremental/src/persist/fs.rs | 338 +++++++----------- .../rustc_incremental/src/persist/fs/tests.rs | 27 +- .../rustc_incremental/src/persist/load.rs | 43 +-- compiler/rustc_incremental/src/persist/mod.rs | 2 +- .../rustc_incremental/src/persist/save.rs | 19 +- .../src/persist/work_product.rs | 24 +- compiler/rustc_interface/src/queries.rs | 1 - compiler/rustc_metadata/src/rmeta/encoder.rs | 5 +- compiler/rustc_session/src/session.rs | 9 +- .../run-make/incremental-session-gc/rmake.rs | 3 - 17 files changed, 216 insertions(+), 373 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index cd82df386f5ce..73d4adf8e3cf2 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -140,7 +140,6 @@ fn emit_module( bytecode: None, assembly: None, llvm_ir: None, - links_from_incr_cache: Vec::new(), }) } diff --git a/compiler/rustc_codegen_llvm/src/back/lto.rs b/compiler/rustc_codegen_llvm/src/back/lto.rs index cb12c103834af..d52e34d30fb7d 100644 --- a/compiler/rustc_codegen_llvm/src/back/lto.rs +++ b/compiler/rustc_codegen_llvm/src/back/lto.rs @@ -463,23 +463,29 @@ fn thin_lto( info!("thin LTO data created"); - let (key_map_path, prev_key_map, curr_key_map) = if let Some(ref incr_comp_session_dir) = - cgcx.incr_comp_session_dir + let new_key_map_path = cgcx + .new_incr_comp_session_dir + .as_ref() + .map(|dir| dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME)); + + let prev_key_map = if let Some(ref old_incr_comp_session_dir) = + cgcx.old_incr_comp_session_dir { - let path = incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME); + let old_path = old_incr_comp_session_dir.join(THIN_LTO_KEYS_INCR_COMP_FILE_NAME); + // If the previous file was deleted, or we get an IO error // reading the file, then we'll just use `None` as the // prev_key_map, which will force the code to be recompiled. - let prev = - if path.exists() { ThinLTOKeysMap::load_from_file(&path).ok() } else { None }; - let curr = ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names); - (Some(path), prev, curr) + if old_path.exists() { ThinLTOKeysMap::load_from_file(&old_path).ok() } else { None } + } else { + assert!(green_modules.is_empty()); + None + }; + let curr_key_map = if cgcx.new_incr_comp_session_dir.is_some() { + ThinLTOKeysMap::from_thin_lto_modules(&data, &thin_modules, &module_names) } else { - // If we don't compile incrementally, we don't need to load the - // import data from LLVM. assert!(green_modules.is_empty()); - let curr = ThinLTOKeysMap::default(); - (None, None, curr) + ThinLTOKeysMap::default() }; info!("thin LTO cache key map loaded"); info!("prev_key_map: {:#?}", prev_key_map); @@ -500,7 +506,8 @@ fn thin_lto( if let (Some(prev_key_map), true) = (prev_key_map.as_ref(), green_modules.contains_key(module_name)) { - assert!(cgcx.incr_comp_session_dir.is_some()); + assert!(cgcx.old_incr_comp_session_dir.is_some()); + assert!(cgcx.new_incr_comp_session_dir.is_some()); // If a module exists in both the current and the previous session, // and has the same LTO cache key in both sessions, then we can re-use it @@ -508,7 +515,6 @@ fn thin_lto( let work_product = green_modules[module_name].clone(); copy_jobs.push(work_product); info!(" - {}: re-used", module_name); - assert!(cgcx.incr_comp_session_dir.is_some()); continue; } } @@ -518,8 +524,8 @@ fn thin_lto( } // Save the current ThinLTO import information for the next compilation - // session, overwriting the previous serialized data (if any). - if let Some(path) = key_map_path + // session. + if let Some(path) = new_key_map_path && let Err(err) = curr_key_map.save_to_file(&path) { write::llvm_err(dcx, LlvmError::WriteThinLtoKey { err }); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 0f609464593dc..7633ae31af38f 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -15,7 +15,9 @@ use rustc_errors::{ Level, MultiSpan, Style, Sublevel, Suggestions, catch_fatal_errors, }; use rustc_fs_util::link_or_copy; -use rustc_incremental::{copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess}; +use rustc_incremental::{ + copy_cgu_workproduct_to_incr_comp_cache_dir, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess, +}; use rustc_macros::{Decodable, Encodable}; use rustc_metadata::fs::copy_to_stdout; use rustc_middle::dep_graph::{WorkProduct, WorkProductMap}; @@ -351,9 +353,12 @@ pub struct CodegenContext { /// Directory into which should the LLVM optimization remarks be written. /// If `None`, they will be written to stderr. pub remark_dir: Option, + /// The previous incremental compilation session directory, or None if we + /// are not compiling incrementally or there is no previous session. + pub old_incr_comp_session_dir: Option, /// The incremental compilation session directory, or None if we are not /// compiling incrementally - pub incr_comp_session_dir: Option, + pub new_incr_comp_session_dir: Option, /// `Some(limit)` if the codegen should be run in parallel. /// /// Depends on [`WriteBackendMethods::supports_parallel()`] and `--jobs-backend`. @@ -497,7 +502,6 @@ fn copy_all_cgu_workproducts_to_incr_comp_cache_dir( incr_comp_session.unwrap(), &module.name, files.as_slice(), - &module.links_from_incr_cache, ); work_products.insert(id, product); } @@ -839,7 +843,7 @@ fn execute_optimize_work_item( // save our module to disk first. let bitcode = if cgcx.module_config.emit_pre_lto_bc { let filename = pre_lto_bitcode_filename(&module.name); - cgcx.incr_comp_session_dir.as_ref().map(|path| path.join(&filename)) + cgcx.new_incr_comp_session_dir.as_ref().map(|path| path.join(&filename)) } else { None }; @@ -886,11 +890,9 @@ fn execute_copy_from_cache_work_item( let dcx = DiagCtxt::new(Box::new(shared_emitter)); let dcx = dcx.handle(); - let incr_comp_session_dir = cgcx.incr_comp_session_dir.as_ref().unwrap(); - - let mut links_from_incr_cache = Vec::new(); + let incr_comp_session_dir = cgcx.old_incr_comp_session_dir.as_ref().unwrap(); - let mut load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { + let load_from_incr_comp_dir = |output_path: PathBuf, saved_path: &str| { let source_file_in_incr_comp_dir = incr_comp_session_dir.join(saved_path); debug!( "copying preexisting module `{}` from {:?} to {}", @@ -899,10 +901,7 @@ fn execute_copy_from_cache_work_item( output_path.display() ); match link_or_copy(&source_file_in_incr_comp_dir, &output_path) { - Ok(_) => { - links_from_incr_cache.push(source_file_in_incr_comp_dir); - Some(output_path) - } + Ok(_) => Some(output_path), Err(error) => { dcx.emit_err(diagnostics::CopyPathBuf { source_file: source_file_in_incr_comp_dir, @@ -925,7 +924,7 @@ fn execute_copy_from_cache_work_item( load_from_incr_comp_dir(dwarf_obj_out, saved_dwarf_object_file) }); - let mut load_from_incr_cache = |perform, output_type: OutputType| { + let load_from_incr_cache = |perform, output_type: OutputType| { if perform { let saved_file = module.source.saved_files.get(output_type.extension())?; let output_path = cgcx.output_filenames.temp_path_for_cgu(output_type, &module.name); @@ -953,7 +952,6 @@ fn execute_copy_from_cache_work_item( } CompiledModule { - links_from_incr_cache, kind: ModuleKind::Regular, name: module.name, object, @@ -1294,10 +1292,15 @@ fn start_executing_work( time_trace: sess.opts.unstable_opts.llvm_time_trace, remark: sess.opts.cg.remark.clone(), remark_dir, - incr_comp_session_dir: tcx + old_incr_comp_session_dir: tcx + .incr_comp_session + .as_ref() + .and_then(|incr_comp_session| incr_comp_session.old_session_directory.as_deref()) + .map(ToOwned::to_owned), + new_incr_comp_session_dir: tcx .incr_comp_session .as_ref() - .map(|incr_comp_session| (&*incr_comp_session.session_directory).to_owned()), + .map(|incr_comp_session| (&*incr_comp_session.new_session_directory).to_owned()), output_filenames: Arc::clone(tcx.output_filenames(())), module_config: regular_config, opt_level, @@ -2262,7 +2265,22 @@ pub(crate) fn submit_pre_lto_module_to_llvm( module: CachedModuleCodegen, ) { let filename = pre_lto_bitcode_filename(&module.name); + let old_bitcode_path = + in_old_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename).unwrap(); let bitcode_path = in_incr_comp_dir_sess(tcx.incr_comp_session.unwrap(), &filename); + + match link_or_copy(&old_bitcode_path, &bitcode_path) { + Ok(_) => {} + Err(error) => { + tcx.sess.dcx().emit_err(diagnostics::CopyPathBuf { + source_file: old_bitcode_path, + output_path: bitcode_path, + error, + }); + return; + } + } + // Schedule the module to be loaded drop( coordinator diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index de921a9cb0d1e..2c15a55c84334 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -877,6 +877,10 @@ pub fn codegen_crate< source: cgu.previous_work_product(tcx), }, ); + // This will unwind if there are errors, which triggers our `AbortCodegenOnDrop` + // guard. Unfortunately, just skipping the `submit_pre_lto_module_to_llvm` makes + // compilation hang on post-monomorphization errors. + tcx.dcx().abort_if_errors(); } CguReuse::PostLto => { submit_post_lto_module_to_llvm( diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 1272b26ca0612..5ae8ba4f7fded 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -114,7 +114,6 @@ impl ModuleCodegen { bytecode, assembly, llvm_ir, - links_from_incr_cache: Vec::new(), } } } @@ -129,7 +128,6 @@ pub struct CompiledModule { pub bytecode: Option, pub assembly: Option, // --emit=asm pub llvm_ir: Option, // --emit=llvm-ir, llvm-bc is in bytecode - pub links_from_incr_cache: Vec, } impl CompiledModule { diff --git a/compiler/rustc_incremental/src/diagnostics.rs b/compiler/rustc_incremental/src/diagnostics.rs index 6e291b7ea3abb..b9ac4662dcbdc 100644 --- a/compiler/rustc_incremental/src/diagnostics.rs +++ b/compiler/rustc_incremental/src/diagnostics.rs @@ -169,21 +169,6 @@ pub(crate) struct DeleteLock<'a> { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag( - "hard linking files in the incremental compilation cache failed. copying files instead. consider moving the cache directory to a file system which supports hard linking in session dir `{$path}`" -)] -pub(crate) struct HardLinkFailed<'a> { - pub path: &'a Path, -} - -#[derive(Diagnostic)] -#[diag("failed to delete partly initialized session dir `{$path}`: {$err}")] -pub(crate) struct DeletePartial<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag("did not finalize incremental compilation session directory `{$path}`: {$err}")] #[help("the next build will not be able to reuse work from this compilation")] @@ -266,13 +251,6 @@ pub(crate) struct CopyWorkProductToCache<'a> { pub err: std::io::Error, } -#[derive(Diagnostic)] -#[diag("file-system error deleting outdated file `{$path}`: {$err}")] -pub(crate) struct DeleteWorkProduct<'a> { - pub path: &'a Path, - pub err: std::io::Error, -} - #[derive(Diagnostic)] #[diag( "corrupt incremental compilation artifact found at `{$path}`. This file will automatically be ignored and deleted. If you see this message repeatedly or can provoke it without manually manipulating the compiler's artifacts, please file an issue. The incremental compilation system relies on hardlinks and filesystem locks behaving correctly, and may not deal well with OS crashes, so whatever information you can provide about your filesystem or other state may be very relevant" diff --git a/compiler/rustc_incremental/src/lib.rs b/compiler/rustc_incremental/src/lib.rs index 83646cb086d8d..b5470d224ffbd 100644 --- a/compiler/rustc_incremental/src/lib.rs +++ b/compiler/rustc_incremental/src/lib.rs @@ -3,6 +3,7 @@ // tidy-alphabetical-start #![deny(missing_docs)] #![feature(file_buffered)] +#![feature(try_blocks)] // tidy-alphabetical-end mod assert_dep_graph; @@ -11,7 +12,7 @@ mod persist; pub use persist::{ copy_cgu_workproduct_to_incr_comp_cache_dir, finalize_session_directory, in_incr_comp_dir_sess, - load_query_result_cache, save_work_product_index, setup_dep_graph, + in_old_incr_comp_dir_sess, load_query_result_cache, save_work_product_index, setup_dep_graph, }; use rustc_middle::util::Providers; diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs index 374e0b0dd6d1a..3f896584eaef2 100644 --- a/compiler/rustc_incremental/src/persist/fs.rs +++ b/compiler/rustc_incremental/src/persist/fs.rs @@ -1,14 +1,14 @@ //! This module manages how the incremental compilation cache is represented in //! the file system. //! -//! Incremental compilation caches are managed according to a copy-on-write -//! strategy: Once a complete, consistent cache version is finalized, it is -//! never modified. Instead, when a subsequent compilation session is started, -//! the compiler will allocate a new version of the cache that starts out as -//! a copy of the previous version. Then only this new copy is modified and it -//! will not be visible to other processes until it is finalized. This ensures -//! that multiple compiler processes can be executed concurrently for the same -//! crate without interfering with each other or blocking each other. +//! Incremental compilation caches are managed according to a rebuild from +//! scratch strategy: Once a complete, consistent cache version is finalized, it +//! is never modified. Instead, when a subsequent compilation session is started, +//! the compiler will allocate a new version of the cache that starts out empty. +//! Then only this new directory is written to and it will not be visible to +//! other processes until it is finalized. This ensures that multiple compiler +//! processes can be executed concurrently for the same crate without +//! interfering with each other or blocking each other. //! //! More concretely this is implemented via the following protocol: //! @@ -22,12 +22,12 @@ //! considered finalized if the "-working" suffix in the directory name has //! been replaced by the SVH of the crate. //! 3. Once the compiler has found a valid, finalized session directory, it will -//! hard-link/copy its contents into the new "-working" directory. If all -//! goes well, it will have its own, private copy of the source directory and -//! subsequently not have to worry about synchronizing with other compiler -//! processes. +//! obtain a shared lock on the directory. If this succeeds, it will have +//! read-only access to the old session directory without having to worry +//! about synchronizing with other compiler processes. //! 4. Now the compiler can do its normal compilation process, which involves -//! reading and updating its private session directory. +//! writing to its private session directory. Possibly by hardlinking +//! existing files from the old session directory if they haven't changed. //! 5. When compilation finishes without errors, the private session directory //! will be in a state where it can be used as input for other compilation //! sessions. That is, it will contain a dependency graph and cache artifacts @@ -71,23 +71,15 @@ //! //! Another case that has to be considered is what happens if one process //! deletes a finalized session directory that another process is currently -//! trying to copy from. This case is also handled via the lock file. Before -//! a process starts copying a finalized session directory, it will acquire a -//! shared lock on the directory's lock file. Any garbage collecting process, -//! on the other hand, will acquire an exclusive lock on the lock file. -//! Thus, if a directory is being collected, any reader process will fail -//! acquiring the shared lock and will leave the directory alone. Conversely, -//! if a collecting process can't acquire the exclusive lock because the -//! directory is currently being read from, it will leave collecting that -//! directory to another process at a later point in time. -//! The exact same scheme is also used when reading the metadata hashes file -//! from an extern crate. When a crate is compiled, the hash values of its -//! metadata are stored in a file in its session directory. When the -//! compilation session of another crate imports the first crate's metadata, -//! it also has to read in the accompanying metadata hashes. It thus will access -//! the finalized session directory of all crates it links to and while doing -//! so, it will also place a read lock on that the respective session directory -//! so that it won't be deleted while the metadata hashes are loaded. +//! reading from. This case is also handled via the lock file. Before a process +//! starts reading from a finalized session directory, it will acquire a shared +//! lock on the directory's lock file. Any garbage collecting process, on the +//! other hand, will acquire an exclusive lock on the lock file. Thus, if a +//! directory is being collected, any reader process will fail acquiring the +//! shared lock and will leave the directory alone. Conversely, if a collecting +//! process can't acquire the exclusive lock because the directory is currently +//! being read from, it will leave collecting that directory to another process +//! at a later point in time. //! //! ## Preconditions //! @@ -110,11 +102,11 @@ use std::time::{Duration, SystemTime, UNIX_EPOCH}; use rand::{RngCore, rng}; use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN}; -use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; +use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::svh::Svh; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_data_structures::{base_n, flock}; -use rustc_fs_util::{LinkOrCopy, link_or_copy, try_canonicalize}; +use rustc_fs_util::try_canonicalize; use rustc_middle::dep_graph::WorkProduct; use rustc_session::config::OutputType; use rustc_session::{IncrCompSession, Session, StableCrateId}; @@ -138,6 +130,11 @@ const QUERY_CACHE_FILENAME: &str = "query-cache.bin"; // case-sensitive (as opposed to base64, for example). const INT_ENCODE_BASE: usize = base_n::CASE_INSENSITIVE; +/// Returns the path to a previous session's dependency graph. +pub(crate) fn old_dep_graph_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, DEP_GRAPH_FILENAME) +} + /// Returns the path to a session's dependency graph. pub(crate) fn dep_graph_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, DEP_GRAPH_FILENAME) @@ -151,10 +148,19 @@ pub(crate) fn staging_dep_graph_path(incr_comp_session: &IncrCompSession) -> Pat in_incr_comp_dir_sess(incr_comp_session, STAGING_DEP_GRAPH_FILENAME) } +pub(crate) fn old_work_products_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, WORK_PRODUCTS_FILENAME) +} + pub(crate) fn work_products_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, WORK_PRODUCTS_FILENAME) } +/// Returns the path to a previous session's query cache. +pub(crate) fn old_query_cache_path(incr_comp_session: &IncrCompSession) -> Option { + in_old_incr_comp_dir_sess(incr_comp_session, QUERY_CACHE_FILENAME) +} + /// Returns the path to a session's query cache. pub(crate) fn query_cache_path(incr_comp_session: &IncrCompSession) -> PathBuf { in_incr_comp_dir_sess(incr_comp_session, QUERY_CACHE_FILENAME) @@ -182,10 +188,19 @@ fn lock_file_path(session_dir: &Path) -> PathBuf { crate_dir.join(&directory_name[0..dash_indices[2]]).with_extension(&LOCK_FILE_EXT[1..]) } +/// Returns the path for a given filename within the incremental compilation directory +/// in the previous session. +pub fn in_old_incr_comp_dir_sess( + incr_comp_session: &IncrCompSession, + file_name: &str, +) -> Option { + incr_comp_session.old_session_directory.as_ref().map(|dir| dir.join(file_name)) +} + /// Returns the path for a given filename within the incremental compilation directory /// in the current session. pub fn in_incr_comp_dir_sess(incr_comp_session: &IncrCompSession, file_name: &str) -> PathBuf { - incr_comp_session.session_directory.join(file_name) + incr_comp_session.new_session_directory.join(file_name) } /// Allocates the private session directory. @@ -230,62 +245,30 @@ pub(crate) fn prepare_session_directory( } }; - let mut source_directories_already_tried = FxHashSet::default(); - - loop { - // Generate a session directory of the form: - // - // {incr-comp-dir}/{crate-name-and-disambiguator}/s-{timestamp}-{random}-working - let session_directory = generate_session_dir_path(&crate_dir); - debug!("session-dir: {}", session_directory.display()); - - // Lock the new session directory. If this fails, return an - // error without retrying - let (session_directory, lock_file_path) = - lock_and_create_directory(sess, &session_directory); - - // Find a suitable source directory to copy from. Ignore those that we - // have already tried before. - let source_directory = find_source_directory(&crate_dir, &source_directories_already_tried); - - let Some(source_directory) = source_directory else { - // There's nowhere to copy from, we're done - debug!( - "no source directory found. Continuing with empty session \ - directory." - ); - - return IncrCompSession { session_directory }; - }; - - debug!("attempting to copy data from source: {}", source_directory.display()); - - // Try copying over all files from the source directory - if let Ok(allows_links) = copy_files(sess, &session_directory, &source_directory) { - debug!("successfully copied data from: {}", source_directory.display()); + // Generate a session directory of the form: + // + // {incr-comp-dir}/{crate-name-and-disambiguator}/s-{timestamp}-{random}-working + let new_session_dir = generate_session_dir_path(&crate_dir); + debug!("session-dir: {}", new_session_dir.display()); - if !allows_links { - sess.dcx().emit_warn(diagnostics::HardLinkFailed { path: &session_directory }); - } - - return IncrCompSession { session_directory }; - } else { - debug!("copying failed - trying next directory"); + // Lock the new session directory. If this fails, return an + // error without retrying + let new_session_directory = lock_directory(sess, &new_session_dir, true /* new_session */) + .expect("should emit fatal error on lock fail"); - // Something went wrong while trying to copy/link files from the - // source directory. Try again with a different one. - source_directories_already_tried.insert(source_directory); + // Find a suitable source directory to copy from. Ignore those that we + // have already tried before. + let old_source_directory = find_source_directory(sess, &crate_dir); - // Try to remove the session directory we just allocated. We don't - // know if there's any garbage in it from the failed copy action. - if let Err(err) = std_fs::remove_dir_all(&*session_directory) { - sess.dcx().emit_warn(diagnostics::DeletePartial { path: &session_directory, err }); - } + let old_session_directory = if let Some(old_source_directory) = old_source_directory { + debug!("attempting to use: {}", old_source_directory.display()); + Some(old_source_directory) + } else { + debug!("no source directory found. Continuing with empty session directory."); + None + }; - delete_session_dir_lock_file(sess, &lock_file_path); - drop(session_directory); - } - } + IncrCompSession { old_session_directory, new_session_directory } } /// This function finalizes and thus 'publishes' the session directory by @@ -301,13 +284,13 @@ pub fn finalize_session_directory( if sess.opts.incremental.is_none() { return; } - let incr_comp_session = incr_comp_session.unwrap(); + let mut incr_comp_session = incr_comp_session.unwrap(); // The svh is always produced when incr. comp. is enabled. let svh = svh.unwrap(); let _timer = sess.timer("incr_comp_finalize_session_directory"); - let incr_comp_session_dir = &*incr_comp_session.session_directory; + let incr_comp_session_dir = &*incr_comp_session.new_session_directory; debug!("finalize_session_directory() - session directory: {}", incr_comp_session_dir.display()); @@ -367,77 +350,28 @@ pub fn finalize_session_directory( } } - let _ = garbage_collect_session_directories( - sess, - &incr_comp_session, - false, // keep_most_recent - ); -} + // Unlock the old session directory now that we will no longer read from it. + incr_comp_session.old_session_directory = None; -pub(crate) fn delete_all_session_dir_contents( - incr_comp_session: &IncrCompSession, -) -> io::Result<()> { - let sess_dir_iterator = incr_comp_session.session_directory.read_dir()?; - for entry in sess_dir_iterator { - let entry = entry?; - safe_remove_file(&entry.path())? - } - Ok(()) + let _ = garbage_collect_session_directories(sess, &incr_comp_session); } -fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result { - // We acquire a shared lock on the lock file of the directory, so that - // nobody deletes it out from under us while we are reading from it. - let lock_file_path = lock_file_path(source_dir); - - // not exclusive - let Ok(_lock) = flock::Lock::try_lock( - &lock_file_path, - false, // don't create - false, - ) else { - // Could not acquire the lock, don't try to copy from here - return Err(()); - }; - - let Ok(source_dir_iterator) = source_dir.read_dir() else { - return Err(()); - }; - - let mut files_linked = 0; - let mut files_copied = 0; - - for entry in source_dir_iterator { - match entry { - Ok(entry) => { - let file_name = entry.file_name(); - - let target_file_path = target_dir.join(file_name); - let source_path = entry.path(); - - debug!("copying into session dir: {}", source_path.display()); - match link_or_copy(source_path, target_file_path) { - Ok(LinkOrCopy::Link) => files_linked += 1, - Ok(LinkOrCopy::Copy) => files_copied += 1, - Err(_) => return Err(()), - } +pub(crate) fn invalidate_old_session_dir(sess: &Session, incr_comp_session: &mut IncrCompSession) { + if let Some(old_incr_comp_session_dir) = incr_comp_session.old_session_directory.take() { + let res = try { + let sess_dir_iterator = old_incr_comp_session_dir.read_dir()?; + for entry in sess_dir_iterator { + let entry = entry?; + safe_remove_file(&entry.path())? } - Err(_) => return Err(()), + }; + if let Err(err) = res { + sess.dcx().emit_err(diagnostics::DeleteIncompatible { + path: (*old_incr_comp_session_dir).to_owned(), + err, + }); } } - - if sess.opts.unstable_opts.incremental_info { - eprintln!( - "[incremental] session directory: \ - {files_linked} files hard-linked" - ); - eprintln!( - "[incremental] session directory: \ - {files_copied} files copied" - ); - } - - Ok(files_linked > 0 || files_copied == 0) } /// Generates unique directory path of the form: @@ -470,33 +404,44 @@ fn create_dir(sess: &Session, path: &Path, dir_tag: &str) { } } -/// Allocate the lock-file, lock it and create the session directory. -fn lock_and_create_directory(sess: &Session, session_dir: &Path) -> (flock::LockedDir, PathBuf) { +/// Allocate the lock-file, lock it and create the session directory if requested. +fn lock_directory( + sess: &Session, + session_dir: &Path, + new_session: bool, +) -> Option { let lock_file_path = lock_file_path(session_dir); debug!("lock_directory() - lock_file: {}", lock_file_path.display()); match flock::LockedDir::try_lock( session_dir.to_owned(), &lock_file_path, - true, // create the lock file - true, + new_session, // create + new_session, // exclusive ) { - // the lock should be exclusive Ok(lock) => { // Now that we have the lock, we can actually create the session // directory - create_dir(sess, &session_dir, "session"); + if new_session { + create_dir(sess, &session_dir, "session"); + } - (lock, lock_file_path) + Some(lock) } Err(lock_err) => { let is_unsupported_lock = flock::Lock::error_unsupported(&lock_err); - sess.dcx().emit_fatal(diagnostics::CreateLock { + let diag = diagnostics::CreateLock { lock_err, session_dir, is_unsupported_lock, is_cargo: rustc_session::utils::was_invoked_from_cargo(), - }); + }; + if new_session { + sess.dcx().emit_fatal(diag); + } else { + sess.dcx().emit_warn(diag); + None + } } } } @@ -507,24 +452,18 @@ fn delete_session_dir_lock_file(sess: &Session, lock_file_path: &Path) { } } -/// Finds the most recent published session directory that is not in the -/// ignore-list. -fn find_source_directory( - crate_dir: &Path, - source_directories_already_tried: &FxHashSet, -) -> Option { +/// Finds the most recent published session directory. +fn find_source_directory(sess: &Session, crate_dir: &Path) -> Option { let iter = crate_dir .read_dir() .unwrap() // FIXME .filter_map(|e| e.ok().map(|e| e.path())); - find_source_directory_in_iter(iter, source_directories_already_tried) + find_source_directory_in_iter(iter) + .and_then(|session_dir| lock_directory(sess, &session_dir, false /* new_session */)) } -fn find_source_directory_in_iter( - iter: I, - source_directories_already_tried: &FxHashSet, -) -> Option +fn find_source_directory_in_iter(iter: I) -> Option where I: Iterator, { @@ -538,10 +477,7 @@ where continue; }; - if source_directories_already_tried.contains(&session_dir) - || !is_session_directory(&directory_name) - || !is_finalized(&directory_name) - { + if !is_session_directory(&directory_name) || !is_finalized(&directory_name) { debug!("find_source_directory_in_iter - ignoring"); continue; } @@ -619,11 +555,10 @@ fn is_old_enough_to_be_collected(timestamp: SystemTime) -> bool { pub(crate) fn garbage_collect_session_directories( sess: &Session, incr_comp_session: &IncrCompSession, - keep_most_recent: bool, ) -> io::Result<()> { debug!("garbage_collect_session_directories() - begin"); - let session_directory = &*incr_comp_session.session_directory; + let session_directory = &*incr_comp_session.new_session_directory; debug!( "garbage_collect_session_directories() - session directory: {}", @@ -760,10 +695,7 @@ pub(crate) fn garbage_collect_session_directories( ); // Note that we are holding on to the lock - return Some(( - (timestamp, crate_directory.join(directory_name)), - Some(lock), - )); + return Some((crate_directory.join(directory_name), lock)); } Err(_) => { debug!( @@ -818,25 +750,22 @@ pub(crate) fn garbage_collect_session_directories( } None }); - let deletion_candidates = deletion_candidates.into(); // Delete all but the most recent of the candidates - all_except_maybe_most_recent(deletion_candidates, keep_most_recent).into_items().all( - |(path, lock)| { - debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); + deletion_candidates.all(|(path, lock)| { + debug!("garbage_collect_session_directories() - deleting `{}`", path.display()); - if let Err(err) = std_fs::remove_dir_all(&path) { - sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); - } else { - delete_session_dir_lock_file(sess, &lock_file_path(&path)); - } + if let Err(err) = std_fs::remove_dir_all(&path) { + sess.dcx().emit_warn(diagnostics::FinalizedGcFailed { path: &path, err }); + } else { + delete_session_dir_lock_file(sess, &lock_file_path(&path)); + } - // Let's make it explicit that the file lock is released at this point, - // or rather, that we held on to it until here - drop(lock); - true - }, - ); + // Let's make it explicit that the file lock is released at this point, + // or rather, that we held on to it until here + drop(lock); + true + }); Ok(()) } @@ -851,21 +780,6 @@ fn delete_old(sess: &Session, path: &Path) { } } -fn all_except_maybe_most_recent( - deletion_candidates: UnordMap<(SystemTime, PathBuf), Option>, - keep_most_recent: bool, -) -> UnordMap> { - let most_recent = keep_most_recent - .then(|| deletion_candidates.items().map(|(&(timestamp, _), _)| timestamp).max()) - .flatten(); - - deletion_candidates - .into_items() - .filter(|&((timestamp, _), _)| Some(timestamp) != most_recent) - .map(|((_, path), lock)| (path, lock)) - .collect() -} - fn safe_remove_file(p: &Path) -> io::Result<()> { match std_fs::remove_file(p) { Err(err) if err.kind() == io::ErrorKind::NotFound => Ok(()), diff --git a/compiler/rustc_incremental/src/persist/fs/tests.rs b/compiler/rustc_incremental/src/persist/fs/tests.rs index 75b573dd4944a..112afd8c7bd1d 100644 --- a/compiler/rustc_incremental/src/persist/fs/tests.rs +++ b/compiler/rustc_incremental/src/persist/fs/tests.rs @@ -1,25 +1,5 @@ use super::*; -#[test] -fn test_all_except_most_recent() { - let input: UnordMap<_, Option> = UnordMap::from_iter([ - ((UNIX_EPOCH + Duration::new(4, 0), PathBuf::from("4")), None), - ((UNIX_EPOCH + Duration::new(1, 0), PathBuf::from("1")), None), - ((UNIX_EPOCH + Duration::new(5, 0), PathBuf::from("5")), None), - ((UNIX_EPOCH + Duration::new(3, 0), PathBuf::from("3")), None), - ((UNIX_EPOCH + Duration::new(2, 0), PathBuf::from("2")), None), - ]); - assert_eq!( - all_except_maybe_most_recent(input, true) - .into_items() - .map(|(path, _)| path) - .into_sorted_stable_ord(), - vec![PathBuf::from("1"), PathBuf::from("2"), PathBuf::from("3"), PathBuf::from("4")] - ); - - assert!(all_except_maybe_most_recent(UnordMap::default(), true).is_empty()); -} - #[test] fn test_timestamp_serialization() { for i in 0..1_000u64 { @@ -31,8 +11,6 @@ fn test_timestamp_serialization() { #[test] fn test_find_source_directory_in_iter() { - let already_visited = FxHashSet::default(); - // Find newest assert_eq!( find_source_directory_in_iter( @@ -42,7 +20,6 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-svh") ] .into_iter(), - &already_visited ), Some(PathBuf::from("crate-dir/s-3234-0000-svh")) ); @@ -56,13 +33,12 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-svh") ] .into_iter(), - &already_visited ), Some(PathBuf::from("crate-dir/s-2234-0000-svh")) ); // Handle empty - assert_eq!(find_source_directory_in_iter([].into_iter(), &already_visited), None); + assert_eq!(find_source_directory_in_iter([].into_iter()), None); // Handle only working assert_eq!( @@ -73,7 +49,6 @@ fn test_find_source_directory_in_iter() { PathBuf::from("crate-dir/s-1234-0000-working") ] .into_iter(), - &already_visited ), None ); diff --git a/compiler/rustc_incremental/src/persist/load.rs b/compiler/rustc_incremental/src/persist/load.rs index fb83149e65b22..76e0bf92c6f0f 100644 --- a/compiler/rustc_incremental/src/persist/load.rs +++ b/compiler/rustc_incremental/src/persist/load.rs @@ -16,8 +16,8 @@ use rustc_span::Symbol; use tracing::{debug, warn}; use super::data::*; +use super::file_format; use super::fs::*; -use super::{file_format, work_product}; use crate::diagnostics; use crate::persist::file_format::{OpenFile, OpenFileError}; @@ -32,15 +32,6 @@ enum LoadResult { IoError { path: PathBuf, err: io::Error }, } -fn delete_dirty_work_product( - sess: &Session, - incr_comp_session: &IncrCompSession, - swp: SerializedWorkProduct, -) { - debug!("delete_dirty_work_product({:?})", swp); - work_product::delete_workproduct_files(sess, incr_comp_session, &swp.work_product); -} - fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadResult { assert!(sess.opts.incremental.is_some()); @@ -48,12 +39,16 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe // Calling `sess.incr_comp_session_dir()` will panic if `sess.opts.incremental.is_none()`. // Fortunately, we just checked that this isn't the case. - let path = dep_graph_path(incr_comp_session); + let Some(path) = old_dep_graph_path(incr_comp_session) else { + return LoadResult::DataOutOfDate; + }; let expected_hash = sess.opts.dep_tracking_hash(false); let mut prev_work_products = UnordMap::default(); - let work_products_path = work_products_path(incr_comp_session); + let Some(work_products_path) = old_work_products_path(incr_comp_session) else { + return LoadResult::DataOutOfDate; + }; if let Ok(OpenFile { mmap, start_pos }) = file_format::open_incremental_file(sess, &work_products_path) @@ -68,7 +63,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe for swp in work_products { let all_files_exist = swp.work_product.saved_files.items().all(|(_, path)| { - let exists = in_incr_comp_dir_sess(incr_comp_session, path).exists(); + let exists = in_old_incr_comp_dir_sess(incr_comp_session, path).unwrap().exists(); if !exists && sess.opts.unstable_opts.incremental_info { eprintln!("incremental: could not find file for work product: {path}",); } @@ -80,7 +75,7 @@ fn load_dep_graph(sess: &Session, incr_comp_session: &IncrCompSession) -> LoadRe prev_work_products.insert(swp.id, swp.work_product); } else { debug!("reconcile_work_products: some file for {:?} does not exist", swp); - delete_dirty_work_product(sess, incr_comp_session, swp); + return LoadResult::DataOutOfDate; } } } @@ -134,7 +129,9 @@ pub fn load_query_result_cache( let _prof_timer = sess.prof.generic_activity("incr_comp_load_query_result_cache"); - let path = query_cache_path(incr_comp_session); + let Some(path) = old_query_cache_path(incr_comp_session) else { + return Some(OnDiskCache::new_empty()); + }; match file_format::open_incremental_file(sess, &path) { Ok(OpenFile { mmap, start_pos }) => { let cache = OnDiskCache::new(sess, mmap, start_pos).unwrap_or_else(|()| { @@ -190,16 +187,12 @@ pub fn setup_dep_graph( } // `load_dep_graph` can only be called after `prepare_session_directory`. - let incr_comp_session = prepare_session_directory(sess, crate_name, stable_crate_id); + let mut incr_comp_session = prepare_session_directory(sess, crate_name, stable_crate_id); // Try to load the previous session's dep graph and work products. let load_result = load_dep_graph(sess, &incr_comp_session); sess.time("incr_comp_garbage_collect_session_directories", || { - if let Err(e) = garbage_collect_session_directories( - sess, - &incr_comp_session, - true, // keep_most_recent - ) { + if let Err(e) = garbage_collect_session_directories(sess, &incr_comp_session) { warn!( "Error while trying to garbage collect incremental compilation \ cache directory: {e}", @@ -213,15 +206,11 @@ pub fn setup_dep_graph( let (prev_graph, prev_work_products) = match load_result { LoadResult::IoError { path, err } => { sess.dcx().emit_warn(diagnostics::LoadDepGraph { path, err }); + invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } LoadResult::DataOutOfDate => { - if let Err(err) = delete_all_session_dir_contents(&incr_comp_session) { - sess.dcx().emit_err(diagnostics::DeleteIncompatible { - path: dep_graph_path(&incr_comp_session), - err, - }); - } + invalidate_old_session_dir(sess, &mut incr_comp_session); Default::default() } LoadResult::Ok { prev_graph, prev_work_products } => (prev_graph, prev_work_products), diff --git a/compiler/rustc_incremental/src/persist/mod.rs b/compiler/rustc_incremental/src/persist/mod.rs index 7d486cc394b80..fb318357b26cb 100644 --- a/compiler/rustc_incremental/src/persist/mod.rs +++ b/compiler/rustc_incremental/src/persist/mod.rs @@ -10,7 +10,7 @@ mod load; mod save; mod work_product; -pub use fs::{finalize_session_directory, in_incr_comp_dir_sess}; +pub use fs::{finalize_session_directory, in_incr_comp_dir_sess, in_old_incr_comp_dir_sess}; pub use load::{load_query_result_cache, setup_dep_graph}; pub(crate) use save::save_dep_graph; pub use save::save_work_product_index; diff --git a/compiler/rustc_incremental/src/persist/save.rs b/compiler/rustc_incremental/src/persist/save.rs index 12f674fe2a859..46f47d6c8623c 100644 --- a/compiler/rustc_incremental/src/persist/save.rs +++ b/compiler/rustc_incremental/src/persist/save.rs @@ -11,7 +11,7 @@ use tracing::debug; use super::data::*; use super::fs::*; -use super::{clean, file_format, work_product}; +use super::{clean, file_format}; use crate::assert_dep_graph::assert_dep_graph; use crate::diagnostics; @@ -112,23 +112,6 @@ pub fn save_work_product_index( e.finish() }); - // We also need to clean out old work-products, as not all of them are - // deleted during invalidation. Some object files don't change their - // content, they are just not needed anymore. - let previous_work_products = dep_graph.previous_work_products(); - for (id, wp) in previous_work_products.to_sorted_stable_ord() { - if !new_work_products.contains_key(id) { - work_product::delete_workproduct_files(sess, incr_comp_session.unwrap(), wp); - debug_assert!( - !wp.saved_files.items().all(|(_, path)| in_incr_comp_dir_sess( - incr_comp_session.unwrap(), - path - ) - .exists()) - ); - } - } - // Check that we did not delete one of the current work-products: debug_assert!({ new_work_products.items().all(|(_, wp)| { diff --git a/compiler/rustc_incremental/src/persist/work_product.rs b/compiler/rustc_incremental/src/persist/work_product.rs index 7bb66fee4d1a3..0aaa9aa8e96c2 100644 --- a/compiler/rustc_incremental/src/persist/work_product.rs +++ b/compiler/rustc_incremental/src/persist/work_product.rs @@ -1,9 +1,8 @@ -//! Functions for saving and removing intermediate [work products]. +//! Function for saving intermediate [work products]. //! //! [work products]: WorkProduct -use std::fs as std_fs; -use std::path::{Path, PathBuf}; +use std::path::Path; use rustc_data_structures::unord::UnordMap; use rustc_fs_util::link_or_copy; @@ -23,7 +22,6 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( incr_comp_session: &IncrCompSession, cgu_name: &str, files: &[(&'static str, &Path)], - known_links: &[PathBuf], ) -> (WorkProductId, WorkProduct) { debug!(?cgu_name, ?files); assert!(sess.opts.incremental.is_some()); @@ -32,10 +30,6 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( for (ext, path) in files { let file_name = format!("{cgu_name}.{ext}"); let path_in_incr_dir = in_incr_comp_dir_sess(incr_comp_session, &file_name); - if known_links.contains(&path_in_incr_dir) { - let _ = saved_files.insert(ext.to_string(), file_name); - continue; - } match link_or_copy(path, &path_in_incr_dir) { Ok(_) => { let _ = saved_files.insert(ext.to_string(), file_name); @@ -55,17 +49,3 @@ pub fn copy_cgu_workproduct_to_incr_comp_cache_dir( let work_product_id = WorkProductId::from_cgu_name(cgu_name); (work_product_id, work_product) } - -/// Removes files for a given work product. -pub(crate) fn delete_workproduct_files( - sess: &Session, - incr_comp_session: &IncrCompSession, - work_product: &WorkProduct, -) { - for (_, path) in work_product.saved_files.items().into_sorted_stable_ord() { - let path = in_incr_comp_dir_sess(incr_comp_session, path); - if let Err(err) = std_fs::remove_file(&path) { - sess.dcx().emit_warn(diagnostics::DeleteWorkProduct { path: &path, err }); - } - } -} diff --git a/compiler/rustc_interface/src/queries.rs b/compiler/rustc_interface/src/queries.rs index 2f196c5e5d609..759297bc69592 100644 --- a/compiler/rustc_interface/src/queries.rs +++ b/compiler/rustc_interface/src/queries.rs @@ -101,7 +101,6 @@ impl Linker { incr_comp_session.as_ref().unwrap(), WorkProduct::METADATA_WORKPRODUCT_CGU_NAME, &[(OutputType::Metadata.extension(), path)], - &[], ); work_products.insert(id, product); } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 8481db9d3c523..f64b2913d40d9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2502,14 +2502,15 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // If the metadata dep-node is green, try to reuse the saved work product. if tcx.dep_graph.is_fully_enabled() + && let incr_comp_session = tcx.incr_comp_session.unwrap() + && let Some(old_incr_comp_session_dir) = &incr_comp_session.old_session_directory && let work_product_id = WorkProductId::from_cgu_name(WorkProduct::METADATA_WORKPRODUCT_CGU_NAME) && let Some(work_product) = tcx.dep_graph.previous_work_product(&work_product_id) && tcx.dep_graph.try_mark_green(tcx, &dep_node).is_some() { let saved_path = &work_product.saved_files[OutputType::Metadata.extension()]; - let incr_comp_session_dir = &tcx.incr_comp_session.unwrap().session_directory; - let source_file_in_incr_dir = &incr_comp_session_dir.join(saved_path); + let source_file_in_incr_dir = &old_incr_comp_session_dir.join(saved_path); debug!("copying preexisting metadata from {source_file_in_incr_dir:?} to {path:?}"); match rustc_fs_util::link_or_copy(&source_file_in_incr_dir, path) { Ok(_) => {} diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index acfbb08b9b630..0ebf5dd1b99a1 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -1841,10 +1841,11 @@ fn validate_commandline_args_with_session_available(sess: &Session) { /// Holds data on the current incremental compilation session, if there is one. pub struct IncrCompSession { - /// The directory containing all cached data. Cached data from a previous - /// session can be read out of it and new data for the current session will - /// be written into it. - pub session_directory: flock::LockedDir, + /// The directory from which cached data of a previous session can be read. + pub old_session_directory: Option, + /// The directory to which cached data for the current session can be + /// written to. + pub new_session_directory: flock::LockedDir, } /// A wrapper around an [`DiagCtxt`] that is used for early error emissions. diff --git a/tests/run-make/incremental-session-gc/rmake.rs b/tests/run-make/incremental-session-gc/rmake.rs index 341a21690f215..405708abb7e3c 100644 --- a/tests/run-make/incremental-session-gc/rmake.rs +++ b/tests/run-make/incremental-session-gc/rmake.rs @@ -12,14 +12,12 @@ fn main() { compile(); let mut previous = session_dir(); - rfs::write(previous.join("sentinel"), "previous session"); for _ in 0..2 { compile(); let current = session_dir(); assert_ne!(previous, current); assert!(!previous.exists(), "superseded session was not collected: {previous:?}"); - assert_eq!(rfs::read_to_string(current.join("sentinel")), "previous session"); previous = current; } @@ -36,7 +34,6 @@ fn main() { let current = session_dir(); assert_ne!(previous, newer); assert!(!newer.exists(), "superseded session was not collected: {previous:?}"); - assert_eq!(rfs::read_to_string(current.join("sentinel")), "previous session"); } fn session_dir() -> PathBuf { From caadd686be32b2116709820c231ca09bc66ceac5 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 4 Sep 2026 11:37:27 +0800 Subject: [PATCH 0766/1309] dont lower depth for coroutine witness and rigid opaques in auto trait proving --- .../src/solve/eval_ctxt/mod.rs | 130 +++++++++++++++--- .../src/solve/project_goals/mod.rs | 12 +- ...ower-depth-for-witness-and-rigid-opaque.rs | 31 +++++ 3 files changed, 145 insertions(+), 28 deletions(-) create mode 100644 tests/ui/traits/next-solver/overflow/dont-lower-depth-for-witness-and-rigid-opaque.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index ae5cf61aac91e..823e606eea0a0 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -636,12 +636,119 @@ where source: GoalSource, goal: Goal, ) -> Result, NoSolutionOrRerunNonErased> { - let (normalization_nested_goals, goal_evaluation) = - self.evaluate_goal_raw(source, goal, LowerAvailableDepth::Yes)?; + let (normalization_nested_goals, goal_evaluation) = self.evaluate_goal_raw(source, goal)?; assert!(normalization_nested_goals.is_empty()); Ok(goal_evaluation) } + fn evaluate_in_search_graph( + &mut self, + canonical_goal: I::CanonicalInput, + step_kind: PathKind, + ) -> (Result, NoSolution>, AccessedOpaques) { + let increase_depth_for_nested = + match canonical_goal.canonical.value.goal.predicate.kind().skip_binder() { + // We don't lower the available depth for the `NormalizesTo` goal, as evaluating + // it is an extra step only exists in the new solver that behaves like a function + // call rather than an independent nested goal evaluation. So, decreasing the + // available depth may end up regressions which hit the recursion limits for crates + // compiled well with the old solver. + ty::PredicateKind::NormalizesTo(_) => LowerAvailableDepth::No, + // We also don't lower depth for witness and rigid opaque when proving auto traits. + // This is to mitigate the overflow FCW warnings in deeply nested async calls. + // See #159228. + // + // We're eventually going to remove the witness type so it's okay to ignore the + // depth. + // For rigid opaques, revealing hidden types can be viewed as normalization so it's + // consistent with the `NormalizesTo` reasoning above. + ty::PredicateKind::Clause(ty::ClauseKind::Trait(pred)) => { + if self.cx().trait_is_auto(pred.trait_ref.def_id) { + match pred.self_ty().kind() { + ty::CoroutineWitness(..) => LowerAvailableDepth::No, + ty::Alias( + ty::IsRigid::Yes, + ty::AliasTy { kind: ty::Opaque { def_id, .. }, .. }, + ) => { + // We only want to skip lowering depth when the proving is done via + // auto trait leakage. If the goal can be proved via item bounds, + // we should lower depth faithfully. + // + // FIXME: We can have param env candidates via TAIT or RTN. + // Ideally we'd instead lower the depth for the nested goal instead. + // Implementing this is a bit harder. + if self + .cx() + .item_self_bounds(def_id.into()) + .skip_binder() + .into_iter() + .any(|bound| { + bound + .as_trait_clause() + .is_some_and(|b| b.def_id() == pred.def_id()) + }) + { + LowerAvailableDepth::Yes + } else { + LowerAvailableDepth::No + } + } + ty::Bool + | ty::Char + | ty::Int(..) + | ty::Uint(..) + | ty::Float(..) + | ty::Str + | ty::Pat(..) + | ty::FnPtr(..) + | ty::Array(..) + | ty::Slice(..) + | ty::RawPtr(..) + | ty::Never + | ty::Tuple(..) + | ty::UnsafeBinder(_) + | ty::Param(..) + | ty::Placeholder(..) + | ty::Bound(..) + | ty::Infer(..) + | ty::Alias(_, _) + | ty::Ref(_, _, _) + | ty::Adt(_, _) + | ty::Foreign(_) + | ty::Dynamic(..) + | ty::Error(_) + | ty::FnDef(..) + | ty::Closure(..) + | ty::CoroutineClosure(..) + | ty::Coroutine(..) => LowerAvailableDepth::Yes, + } + } else { + LowerAvailableDepth::Yes + } + } + ty::PredicateKind::Clause(ty::ClauseKind::HostEffect(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstArgHasType(_, _)) + | ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(_)) + | ty::PredicateKind::Subtype(_) + | ty::PredicateKind::Coerce(_) + | ty::PredicateKind::DynCompatible(_) + | ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) + | ty::PredicateKind::Clause(ty::ClauseKind::ConstEvaluatable(_)) + | ty::PredicateKind::ConstEquate(_, _) + | ty::PredicateKind::Ambiguous => LowerAvailableDepth::Yes, + }; + self.search_graph.evaluate_goal( + self.cx(), + canonical_goal, + step_kind, + increase_depth_for_nested, + &mut inspect::ProofTreeBuilder::new_noop(), + ) + } + /// Recursively evaluates `goal`, returning the nested goals in case /// the nested goal is a `NormalizesTo` goal. /// @@ -653,7 +760,6 @@ where &mut self, source: GoalSource, goal: Goal, - increase_depth_for_nested: LowerAvailableDepth, ) -> Result<(NestedNormalizationGoals, GoalEvaluation), NoSolutionOrRerunNonErased> { // We only care about one entry per `OpaqueTypeKey` here, // so we only canonicalize the lookup table and ignore @@ -719,13 +825,8 @@ where TypingMode::ErasedNotCoherence(MayBeErased), ); - let (canonical_result, accessed_opaques) = self.search_graph.evaluate_goal( - self.cx(), - canonical_goal, - step_kind, - increase_depth_for_nested, - &mut inspect::ProofTreeBuilder::new_noop(), - ); + let (canonical_result, accessed_opaques) = + self.evaluate_in_search_graph(canonical_goal, step_kind); let should_rerun = should_rerun_after_erased_canonicalization( accessed_opaques, @@ -759,13 +860,8 @@ where let (orig_values, canonical_goal) = canonicalize_goal(self.delegate, goal, &opaque_types, typing_mode); - let (canonical_result, accessed_opaques) = self.search_graph.evaluate_goal( - self.cx(), - canonical_goal, - step_kind, - increase_depth_for_nested, - &mut inspect::ProofTreeBuilder::new_noop(), - ); + let (canonical_result, accessed_opaques) = + self.evaluate_in_search_graph(canonical_goal, step_kind); assert!( !accessed_opaques.might_rerun(), "we run without TypingMode::ErasedNotCoherence, so opaques are available, and we don't retry if the outer typing mode is ErasedNotCoherence: {accessed_opaques:?} after {goal:?}" diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs index db326e6d736a4..9d6b8875071ba 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs @@ -3,7 +3,6 @@ mod free_alias; mod inherent; mod opaque_types; -use rustc_type_ir::search_graph::LowerAvailableDepth; use rustc_type_ir::solve::QueryResultOrRerunNonErased; use rustc_type_ir::{self as ty, Interner, ProjectionClause}; use tracing::{instrument, trace}; @@ -70,16 +69,7 @@ where let ( NestedNormalizationGoals(nested_goals), GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ }, - ) = self.evaluate_goal_raw( - GoalSource::TypeRelating, - normalizes_to, - // We don't lower thr available depth for this `NormalizesTo` goal, as evaluating - // it is an extra step only exists in the new solver that behaves like a function - // call rather than an independent nested goal evaluation. So, decreasing the - // available depth may end up regressions which hit the recursion limits for crates - // compiled well with the old solver. - LowerAvailableDepth::No, - )?; + ) = self.evaluate_goal_raw(GoalSource::TypeRelating, normalizes_to)?; trace!(?nested_goals); diff --git a/tests/ui/traits/next-solver/overflow/dont-lower-depth-for-witness-and-rigid-opaque.rs b/tests/ui/traits/next-solver/overflow/dont-lower-depth-for-witness-and-rigid-opaque.rs new file mode 100644 index 0000000000000..c4d493ec0f8d2 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/dont-lower-depth-for-witness-and-rigid-opaque.rs @@ -0,0 +1,31 @@ +//@ compile-flags: -Znext-solver +//@ edition: 2024 +//@ check-pass + +// We don't increase recursion depth when proving auto traits for witness +// and rigid opaques. This is to mitigate the FCW warnings in deeply nested +// async calls. See #159228. + +#![recursion_limit = "6"] + +async fn foo1() {} + +async fn foo2() { + foo1().await +} +async fn foo3() { + foo2().await +} +async fn foo4() { + foo3().await +} + +async fn foo5() { + foo4().await +} + +fn assert_send(_: T) {} + +fn main() { + assert_send(foo5()); +} From 2e46fb447a8dc1c0fbf0b03c06509fbd65e4b34a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Sep 2026 13:00:28 +0200 Subject: [PATCH 0767/1309] Merge commit 'ffb7eef504d4d9507583825e8e411d283c4e357e' --- .github/workflows/ci.yml | 4 +++- .github/workflows/stdarch.yml | 6 ++++-- Readme.md | 2 +- build_system/src/abi_test.rs | 2 +- build_system/src/utils.rs | 6 +++--- doc/tips.md | 2 +- rust-toolchain => rust-toolchain.toml | 2 +- 7 files changed, 14 insertions(+), 10 deletions(-) rename rust-toolchain => rust-toolchain.toml (70%) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2f5cc409e363d..f37123c124c74 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -52,7 +52,9 @@ jobs: - name: Install packages # `llvm-14-tools` is needed to install the `FileCheck` binary which is used for asm tests. - run: sudo apt-get install ninja-build ripgrep llvm-14-tools llvm + run: | + sudo apt-get update + sudo apt-get install ninja-build ripgrep llvm-14-tools llvm - name: Install the libraries needed to build librsvg if: ${{ contains(matrix.commands, '--projects') }} diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 17d6449c85e08..34499c6e7b522 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -96,14 +96,16 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! diff --git a/Readme.md b/Readme.md index 9a7c624c9bc22..14c0e3ad0f21c 100644 --- a/Readme.md +++ b/Readme.md @@ -154,7 +154,7 @@ If you compiled `cg_gcc` in debug mode (aka you didn't pass `--release` to `./y. You can do the same manually (although we don't recommend it): ```bash -$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs +$ LIBRARY_PATH="[gcc-path value]" LD_LIBRARY_PATH="[gcc-path value]" rustc +$(cat $CG_GCCJIT_DIR/rust-toolchain.toml | grep 'channel' | cut -d '=' -f 2 | sed 's/"//g' | sed 's/ //g') -Cpanic=abort -Zcodegen-backend=$CG_GCCJIT_DIR/target/release/librustc_codegen_gcc.so --sysroot $CG_GCCJIT_DIR/build_sysroot/sysroot my_crate.rs ``` ## Environment variables diff --git a/build_system/src/abi_test.rs b/build_system/src/abi_test.rs index a85886d87f365..9fc06dc8dbc04 100644 --- a/build_system/src/abi_test.rs +++ b/build_system/src/abi_test.rs @@ -34,7 +34,7 @@ pub fn run() -> Result<(), String> { .map_err(|err| format!("Git clone failed with message: {err:?}!"))?; // Configure abi-cafe to use the exact same rustc version we use - this is crucial. // Otherwise, the concept of ABI compatibility becomes meanignless. - std::fs::copy("rust-toolchain", "clones/abi-cafe/rust-toolchain") + std::fs::copy("rust-toolchain.toml", "clones/abi-cafe/rust-toolchain.toml") .expect("Could not copy toolchain configs!"); // Get the backend path. // We will use the *debug* build of the backend - it has more checks enabled. diff --git a/build_system/src/utils.rs b/build_system/src/utils.rs index 4c67156a85fb2..dda44e4d16d41 100644 --- a/build_system/src/utils.rs +++ b/build_system/src/utils.rs @@ -242,9 +242,9 @@ fn rustc_version_info_inner( } pub fn get_toolchain() -> Result { - let content = match fs::read_to_string("rust-toolchain") { + let content = match fs::read_to_string("rust-toolchain.toml") { Ok(content) => content, - Err(_) => return Err("No `rust-toolchain` file found".to_string()), + Err(_) => return Err("No `rust-toolchain.toml` file found".to_string()), }; match content .split('\n') @@ -259,7 +259,7 @@ pub fn get_toolchain() -> Result { .next() { Some(toolchain) => Ok(toolchain.to_string()), - None => Err("Couldn't find `channel` in `rust-toolchain` file".to_string()), + None => Err("Couldn't find `channel` in `rust-toolchain.toml` file".to_string()), } } diff --git a/doc/tips.md b/doc/tips.md index dc40ee4d39952..28964f66403bf 100644 --- a/doc/tips.md +++ b/doc/tips.md @@ -41,7 +41,7 @@ COLLECT_NO_DEMANGLE=1 ### How to use a custom-build rustc * Build the stage2 compiler (`rustup toolchain link debug-current build/x86_64-unknown-linux-gnu/stage2`). - * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain`. + * Clean and rebuild the codegen with `debug-current` in the file `rust-toolchain.toml`. ### How to use a custom sysroot source path diff --git a/rust-toolchain b/rust-toolchain.toml similarity index 70% rename from rust-toolchain rename to rust-toolchain.toml index 0c81f7c7c7398..a7774784e3afa 100644 --- a/rust-toolchain +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-18" +channel = "nightly-2026-09-24" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From ec51dae63f95027d6acb731b759de05698892551 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Fri, 17 Apr 2026 14:13:43 +0200 Subject: [PATCH 0768/1309] Check the entire library and cg_clif workspaces for permitted deps in tidy We ship the entire library workspace in the rust-src component, so even if the standard library doesn't depend on a crate, having it in the library workspace still increases the amount of storage a rust install takes. And for cg_clif I personally want to keep deps to a minimum even those not for the backend itself. --- src/tools/tidy/src/deps.rs | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 65a7890a5ecc2..2c3a47228ac3f 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -96,10 +96,11 @@ pub(crate) struct WorkspaceInfo<'a> { /// The list of license exceptions. pub(crate) exceptions: ExceptionList, /// Optionally: - /// * A list of crates for which dependencies need to be explicitly allowed. + /// * A list of crates for which dependencies need to be explicitly allowed + /// or None to check the entire workspace. /// * The list of allowed dependencies. /// * The source code location of the allowed dependencies list - crates_and_deps: Option<(&'a [&'a str], &'a [&'a str], ListLocation)>, + crates_and_deps: Option<(Option<&'a [&'a str]>, &'a [&'a str], ListLocation)>, /// Submodules required for the workspace pub(crate) submodules: &'a [&'a str], } @@ -114,7 +115,7 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ path: ".", exceptions: EXCEPTIONS, crates_and_deps: Some(( - &["rustc-main"], + Some(&["rustc-main"]), PERMITTED_RUSTC_DEPENDENCIES, PERMITTED_RUSTC_DEPS_LOCATION, )), @@ -124,7 +125,7 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ path: "library", exceptions: EXCEPTIONS_STDLIB, crates_and_deps: Some(( - &["sysroot"], + None, PERMITTED_STDLIB_DEPENDENCIES, PERMITTED_STDLIB_DEPS_LOCATION, )), @@ -140,7 +141,7 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ path: "compiler/rustc_codegen_cranelift", exceptions: EXCEPTIONS_CRANELIFT, crates_and_deps: Some(( - &["rustc_codegen_cranelift"], + None, PERMITTED_CRANELIFT_DEPENDENCIES, PERMITTED_CRANELIFT_DEPS_LOCATION, )), @@ -664,7 +665,7 @@ pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) { } check_license_exceptions(&metadata, path, exceptions, &mut check); if let Some((crates, permitted_deps, location)) = crates_and_deps { - let descr = crates.get(0).unwrap_or(&path); + let descr = crates.map_or(path, |crates| crates.get(0).unwrap_or(&path)); check_permitted_dependencies( &metadata, descr, @@ -927,15 +928,21 @@ fn check_permitted_dependencies( metadata: &Metadata, descr: &str, permitted_dependencies: &[&'static str], - restricted_dependency_crates: &[&'static str], + restricted_dependency_crates: Option<&[&'static str]>, permitted_location: ListLocation, check: &mut RunningCheck, ) { let mut has_permitted_dep_error = false; let mut deps = HashSet::new(); - for to_check in restricted_dependency_crates { - let to_check = pkg_from_name(metadata, to_check); - deps_of(metadata, &to_check.id, &mut deps); + if let Some(restricted_dependency_crates) = restricted_dependency_crates { + for to_check in restricted_dependency_crates { + let to_check = pkg_from_name(metadata, to_check); + deps_of(metadata, &to_check.id, &mut deps); + } + } else { + for to_check in &metadata.packages { + deps_of(metadata, &to_check.id, &mut deps); + } } // Check that the PERMITTED_DEPENDENCIES does not have unused entries. From a8210e14e787b3e6574414e09ea5f35cdc0e8e0c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 24 Sep 2026 13:17:00 +0200 Subject: [PATCH 0769/1309] rustdoc: Fix where-clause placement of free const items --- src/librustdoc/html/render/print_item.rs | 15 ++++---- .../constant/const-value-display.rs | 4 +-- .../constant/generic-const-items.rs | 21 ++++++++++++ .../constant/show-const-contents.rs | 34 ++++++++----------- 4 files changed, 45 insertions(+), 29 deletions(-) diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index 46dba0253766a..bf781410008fe 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -2017,13 +2017,11 @@ fn item_constant( write!( w, - "{vis}const {name}{generics}: {typ}{where_clause}", + "{vis}const {name}{generics}: {typ}", vis = visibility_print_with_space(it, cx), name = it.name.unwrap(), generics = print_generics(generics, cx), typ = print_type(ty, cx), - where_clause = - print_where_clause(generics, cx, 0, Ending::NoNewline).maybe_display(), )?; // FIXME: The code below now prints @@ -2039,9 +2037,7 @@ fn item_constant( let is_literal = c.is_literal(tcx); let expr = c.expr(tcx); if value.is_some() || is_literal { - write!(w, " = {expr};", expr = Escape(&expr))?; - } else { - w.write_str(";")?; + write!(w, " = {expr}", expr = Escape(&expr))?; } if !is_literal && let Some(value) = &value { @@ -2051,9 +2047,14 @@ fn item_constant( if value_lowercase != expr_lowercase && value_lowercase.trim_end_matches("i32") != expr_lowercase { - write!(w, " // {value}", value = Escape(value))?; + write!(w, " /* {value} */", value = Escape(value))?; } } + + print_where_clause(generics, cx, 0, Ending::NoNewline).maybe_display().fmt(w)?; + + w.write_str(";")?; + Ok::<(), fmt::Error>(()) })?; diff --git a/tests/rustdoc-html/constant/const-value-display.rs b/tests/rustdoc-html/constant/const-value-display.rs index 658978a3490b1..12259e1089edc 100644 --- a/tests/rustdoc-html/constant/const-value-display.rs +++ b/tests/rustdoc-html/constant/const-value-display.rs @@ -1,9 +1,9 @@ #![crate_name = "foo"] //@ has 'foo/constant.HOUR_IN_SECONDS.html' -//@ has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _; // 3_600u64' +//@ has - '//*[@class="rust item-decl"]//code' 'pub const HOUR_IN_SECONDS: u64 = _ /* 3_600u64 */;' pub const HOUR_IN_SECONDS: u64 = 60 * 60; //@ has 'foo/constant.NEGATIVE.html' -//@ has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _; // -3_600i64' +//@ has - '//*[@class="rust item-decl"]//code' 'pub const NEGATIVE: i64 = _ /* -3_600i64 */;' pub const NEGATIVE: i64 = -60 * 60; diff --git a/tests/rustdoc-html/constant/generic-const-items.rs b/tests/rustdoc-html/constant/generic-const-items.rs index 31c300f2ff1e1..353f9c2dc6230 100644 --- a/tests/rustdoc-html/constant/generic-const-items.rs +++ b/tests/rustdoc-html/constant/generic-const-items.rs @@ -1,6 +1,8 @@ #![feature(generic_const_items)] #![allow(incomplete_features)] +// (Here we hide the RHS because it's not a literal) +// //@ has 'generic_const_items/constant.K.html' //@ has - '//*[@class="rust item-decl"]//code' \ // "pub const K<'a, T: 'a + Copy, const N: usize>: Option<[T; N]> \ @@ -10,6 +12,25 @@ pub const K<'a, T: 'a + Copy, const N: usize>: Option<[T; N]> = None where String: From; +// Ensure that we render the where-clause *after* the RHS. +// +//@ has 'generic_const_items/constant.Q.html' +//@ has - '//*[@class="rust item-decl"]//code' \ +// "pub const Q: i32 = 0 \ +// where \ +// for<'_delay> i32: Copy;" +pub const Q: i32 = 0 where for<'_delay> i32: Copy; + +// Ensure that we properly insert the fake comment containing the value +// between the expression and the where-clause. +// +//@ has 'generic_const_items/constant.C.html' +//@ has - '//*[@class="rust item-decl"]//code' \ +// "pub const C<'a>: u8 = _ /* 2u8 */ \ +// where \ +// &'a (): Sized;" +pub const C<'a>: u8 = 1 + 1 where &'a (): Sized; + //@ has generic_const_items/trait.Trait.html pub trait Trait { //@ has - '//*[@id="associatedconstant.C"]' \ diff --git a/tests/rustdoc-html/constant/show-const-contents.rs b/tests/rustdoc-html/constant/show-const-contents.rs index 6d2701693ceff..e5d056ac0ba46 100644 --- a/tests/rustdoc-html/constant/show-const-contents.rs +++ b/tests/rustdoc-html/constant/show-const-contents.rs @@ -1,67 +1,61 @@ // Test that the contents of constants are displayed as part of the // documentation. -//@ hasraw show_const_contents/constant.CONST_S.html 'show this' -//@ !hasraw show_const_contents/constant.CONST_S.html '; //' +//@ hasraw show_const_contents/constant.CONST_S.html '"show this";' pub const CONST_S: &'static str = "show this"; //@ hasraw show_const_contents/constant.CONST_I32.html '= 42;' -//@ !hasraw show_const_contents/constant.CONST_I32.html '; //' pub const CONST_I32: i32 = 42; //@ hasraw show_const_contents/constant.CONST_I32_HEX.html '= 0x42;' -//@ !hasraw show_const_contents/constant.CONST_I32_HEX.html '; //' pub const CONST_I32_HEX: i32 = 0x42; //@ hasraw show_const_contents/constant.CONST_NEG_I32.html '= -42;' -//@ !hasraw show_const_contents/constant.CONST_NEG_I32.html '; //' pub const CONST_NEG_I32: i32 = -42; //@ hasraw show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '= 42i32;' -//@ !hasraw show_const_contents/constant.CONST_EQ_TO_VALUE_I32.html '// 42i32' pub const CONST_EQ_TO_VALUE_I32: i32 = 42i32; -//@ hasraw show_const_contents/constant.CONST_CALC_I32.html '= _; // 43i32' +//@ hasraw show_const_contents/constant.CONST_CALC_I32.html '= _ /* 43i32 */;' pub const CONST_CALC_I32: i32 = 42 + 1; //@ !hasraw show_const_contents/constant.CONST_REF_I32.html '= &42;' -//@ !hasraw show_const_contents/constant.CONST_REF_I32.html '; //' +//@ !hasraw show_const_contents/constant.CONST_REF_I32.html '= _;' pub const CONST_REF_I32: &'static i32 = &42; -//@ hasraw show_const_contents/constant.CONST_I32_MAX.html '= i32::MAX; // 2_147_483_647i32' +//@ hasraw show_const_contents/constant.CONST_I32_MAX.html '= i32::MAX /* 2_147_483_647i32 */;' pub const CONST_I32_MAX: i32 = i32::MAX; //@ !hasraw show_const_contents/constant.UNIT.html '= ();' -//@ !hasraw show_const_contents/constant.UNIT.html '; //' pub const UNIT: () = (); pub struct MyType(i32); //@ !hasraw show_const_contents/constant.MY_TYPE.html '= MyType(42);' -//@ !hasraw show_const_contents/constant.MY_TYPE.html '; //' +//@ !hasraw show_const_contents/constant.MY_TYPE.html '= _;' pub const MY_TYPE: MyType = MyType(42); pub struct MyTypeWithStr(&'static str); -//@ !hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html '= MyTypeWithStr("show this");' -//@ !hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html '; //' +//@ !hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html \ +// '= MyTypeWithStr("show this");' +//@ !hasraw show_const_contents/constant.MY_TYPE_WITH_STR.html '= _;' pub const MY_TYPE_WITH_STR: MyTypeWithStr = MyTypeWithStr("show this"); -//@ hasraw show_const_contents/constant.PI.html '= 3.14159265358979323846264338327950288_f32;' -//@ hasraw show_const_contents/constant.PI.html '; // 3.14159274f32' +//@ hasraw show_const_contents/constant.PI.html \ +// '= 3.14159265358979323846264338327950288_f32 /* 3.14159274f32 */;' pub use std::f32::consts::PI; - -//@ hasraw show_const_contents/constant.MAX.html '= i32::MAX; // 2_147_483_647i32' +//@ hasraw show_const_contents/constant.MAX.html '= i32::MAX /* 2_147_483_647i32 */;' #[allow(deprecated, deprecated_in_future)] pub use std::i32::MAX; macro_rules! int_module { - ($T:ident) => ( + ($T:ident) => { pub const MIN: $T = $T::MIN; - ) + }; } -//@ hasraw show_const_contents/constant.MIN.html '= i16::MIN; // -32_768i16' +//@ hasraw show_const_contents/constant.MIN.html '= i16::MIN /* -32_768i16 */;' int_module!(i16); //@ has show_const_contents/constant.ESCAPE.html //pre '= r#""#;' From 96b181cdac89beb9ae230078007d4789dd68712e Mon Sep 17 00:00:00 2001 From: Jakub Chlanda Date: Thu, 3 Sep 2026 10:11:56 +0000 Subject: [PATCH 0770/1309] tests: Run more pauth tests in CI and make them pass Some pauth tests have ended up failing since they were not run in CI. Make them run and make them pass. --- tests/assembly-llvm/pauth-basic.rs | 2 +- tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs | 1 - tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs | 2 ++ .../pauth/pauth-extern-c-direct-indirect-call.rs | 4 +++- tests/codegen-llvm/pauth/pauth-extern-c.rs | 1 - tests/codegen-llvm/pauth/pauth-extern-weak-global.rs | 1 - tests/codegen-llvm/pauth/pauth-init-fini.rs | 1 - tests/ui/statics/crt-static-pauthtest.rs | 3 +-- tests/ui/target_modifiers/auxiliary/pauth.rs | 3 ++- .../incompatible_pauth.error_generated.stderr | 4 ---- tests/ui/target_modifiers/incompatible_pauth.rs | 6 +++--- 11 files changed, 12 insertions(+), 16 deletions(-) diff --git a/tests/assembly-llvm/pauth-basic.rs b/tests/assembly-llvm/pauth-basic.rs index e240e1317f3a3..34b9c4b5c328c 100644 --- a/tests/assembly-llvm/pauth-basic.rs +++ b/tests/assembly-llvm/pauth-basic.rs @@ -1,8 +1,8 @@ //@ add-minicore //@ assembly-output: emit-asm -//@ only-pauthtest //@ revisions: aarch64_unknown_linux_pauthtest //@ [aarch64_unknown_linux_pauthtest] compile-flags: --target=aarch64-unknown-linux-pauthtest +//@ [aarch64_unknown_linux_pauthtest] compile-flags: -Copt-level=3 //@ [aarch64_unknown_linux_pauthtest] needs-llvm-components: aarch64 #![feature(no_core, lang_items)] diff --git a/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs b/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs index 04af1b66140dd..513850f1dd4db 100644 --- a/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs +++ b/tests/codegen-llvm/pauth/pauth-attr-cli-flags.rs @@ -1,5 +1,4 @@ // ignore-tidy-file-linelength -//@ only-pauthtest //@ revisions: DEFAULT ALL DISABLE_JUMP DISABLE_AUTH_TRAPS DISABLE_CALLS DISABLE_INDIRCT_GOTOS DISABLE_RETURNS DISABLE_INTRINSICS DISABLE_TYPEINFO DISABLE_VT_PTR_ADDR DISABLE_VT_PTR_TYPE NONE //@ add-minicore diff --git a/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs b/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs index 2751494b9de7a..24ab1abb10e67 100644 --- a/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs +++ b/tests/codegen-llvm/pauth/pauth-attr-special-funcs.rs @@ -3,6 +3,8 @@ // Make sure that compiler generated functions (main wrapper and __rust_try) also have ptrauth // attributes set correctly. Rustc only generates __rust_try at O0, so use that opt level for the // test. +// Cannot be converted to minicore: catch_unwind is a std API and is what causes rustc to generate +// the __rust_try wrapper this test is checking. //@ needs-llvm-components: aarch64 diff --git a/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs b/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs index 643b428339b73..d01815954b237 100644 --- a/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs +++ b/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs @@ -1,10 +1,12 @@ //@ add-minicore // ignore-tidy-linelength -//@ only-pauthtest //@ revisions: O0_PAUTH O3_PAUTH //@ [O0_PAUTH] needs-llvm-components: aarch64 //@ [O0_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 +// O3_PAUTH relies on an InstCombine fold that removes the redundant `ptrauth` bundle from calls. +// That fold first shipped in LLVM 22, gate this revision accordingly. +//@ [O3_PAUTH] min-llvm-version: 22 //@ [O3_PAUTH] needs-llvm-components: aarch64 //@ [O3_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 diff --git a/tests/codegen-llvm/pauth/pauth-extern-c.rs b/tests/codegen-llvm/pauth/pauth-extern-c.rs index b22cf6943a804..07e27965e9ebf 100644 --- a/tests/codegen-llvm/pauth/pauth-extern-c.rs +++ b/tests/codegen-llvm/pauth/pauth-extern-c.rs @@ -1,5 +1,4 @@ // ignore-tidy-file-linelength -//@ only-pauthtest //@ add-minicore //@ revisions: O0_PAUTH O3_PAUTH O0_PAUTH-ELF-GOT O3_PAUTH-ELF-GOT O0_NO_PAUTH O3_NO_PAUTH diff --git a/tests/codegen-llvm/pauth/pauth-extern-weak-global.rs b/tests/codegen-llvm/pauth/pauth-extern-weak-global.rs index a83298dd5725c..b7c1f5fd06479 100644 --- a/tests/codegen-llvm/pauth/pauth-extern-weak-global.rs +++ b/tests/codegen-llvm/pauth/pauth-extern-weak-global.rs @@ -1,5 +1,4 @@ // ignore-tidy-linelength -//@ only-pauthtest //@ revisions: O0_PAUTH O3_PAUTH O0_NO_PAUTH O3_NO_PAUTH //@ add-minicore diff --git a/tests/codegen-llvm/pauth/pauth-init-fini.rs b/tests/codegen-llvm/pauth/pauth-init-fini.rs index b54006e56f1f4..5550100ae7f92 100644 --- a/tests/codegen-llvm/pauth/pauth-init-fini.rs +++ b/tests/codegen-llvm/pauth/pauth-init-fini.rs @@ -1,6 +1,5 @@ // ignore-tidy-file-linelength //@ add-minicore -//@ only-pauthtest //@ revisions: O0_PAUTH O3_PAUTH O0_PAUTH-ADDR-DISC O3_PAUTH-ADDR-DISC O0_PAUTH-NO-INIT-FINI O3_PAUTH-NO-INIT-FINI //@ [O0_PAUTH] needs-llvm-components: aarch64 diff --git a/tests/ui/statics/crt-static-pauthtest.rs b/tests/ui/statics/crt-static-pauthtest.rs index bc5badc600d88..a3fed7f9379ef 100644 --- a/tests/ui/statics/crt-static-pauthtest.rs +++ b/tests/ui/statics/crt-static-pauthtest.rs @@ -1,9 +1,8 @@ //@ compile-flags: -C target-feature=+crt-static --target aarch64-unknown-linux-pauthtest //@ needs-llvm-components: aarch64 -//@ only-pauthtest - #![feature(no_core)] +#![no_core] #![no_main] //~? ERROR pointer authentication requires dynamic linking. Statically linked libc is incompatible, disable it using `-C target-feature=-crt-static` diff --git a/tests/ui/target_modifiers/auxiliary/pauth.rs b/tests/ui/target_modifiers/auxiliary/pauth.rs index 761f4a520a4d2..32bd7651c0b44 100644 --- a/tests/ui/target_modifiers/auxiliary/pauth.rs +++ b/tests/ui/target_modifiers/auxiliary/pauth.rs @@ -1,6 +1,7 @@ //@ compile-flags: --target aarch64-unknown-linux-pauthtest -Zpointer-authentication=+calls,+init-fini //@ needs-llvm-components: aarch64 -//@ only-pauthtest +//@ no-prefer-dynamic +//@ ignore-backends: gcc #![feature(no_core)] #![crate_type = "rlib"] diff --git a/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr b/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr index ddc05e4b55322..1e9390d37e822 100644 --- a/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr +++ b/tests/ui/target_modifiers/incompatible_pauth.error_generated.stderr @@ -1,8 +1,4 @@ error: mixing `-Zpointer-authentication` will cause an ABI mismatch in crate `incompatible_pauth` - --> $DIR/incompatible_pauth.rs:14:1 - | -LL | #![feature(no_core)] - | ^ | = help: the `-Zpointer-authentication` flag modifies the ABI so Rust crates compiled with different values of this flag cannot be used together safely = note: `-Zpointer-authentication=+calls,-init-fini` in this crate is incompatible with `-Zpointer-authentication=+calls,+init-fini` in dependency `pauth` diff --git a/tests/ui/target_modifiers/incompatible_pauth.rs b/tests/ui/target_modifiers/incompatible_pauth.rs index 6fe77a6916568..302e845e8bd4f 100644 --- a/tests/ui/target_modifiers/incompatible_pauth.rs +++ b/tests/ui/target_modifiers/incompatible_pauth.rs @@ -9,12 +9,12 @@ //@ [ok_reverse_order] check-pass //@ [error_generated] compile-flags: -Zpointer-authentication=+calls,-init-fini //@ needs-llvm-components: aarch64 -//@ only-pauthtest +//@ ignore-backends: gcc #![feature(no_core)] -//[error_generated]~^ ERROR mixing `-Zpointer-authentication` will cause an ABI mismatch in crate -//`incompatible_pauth` #![crate_type = "rlib"] #![no_core] extern crate pauth; + +//[error_generated]~? ERROR mixing `-Zpointer-authentication` will cause an ABI mismatch in crate `incompatible_pauth` From 9f3299ed68109f94e6a718e9571d02400cb6ba80 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Thu, 24 Sep 2026 13:01:16 +0200 Subject: [PATCH 0771/1309] rustdoc: Fix where-clause placement of checked type aliases --- src/librustdoc/html/render/print_item.rs | 54 ++++++++----------- .../typedef/checked-type-aliases.rs | 9 ++++ .../typedef-inner-variants-lazy_type_alias.rs | 7 +-- .../where.golf_type_alias_decl.html | 5 +- tests/rustdoc-html/where.rs | 2 +- 5 files changed, 40 insertions(+), 37 deletions(-) create mode 100644 tests/rustdoc-html/typedef/checked-type-aliases.rs diff --git a/src/librustdoc/html/render/print_item.rs b/src/librustdoc/html/render/print_item.rs index bf781410008fe..f6d5ada07f364 100644 --- a/src/librustdoc/html/render/print_item.rs +++ b/src/librustdoc/html/render/print_item.rs @@ -1296,79 +1296,71 @@ fn item_trait_alias( fn item_type_alias(cx: &Context<'_>, it: &clean::Item, t: &clean::TypeAlias) -> impl fmt::Display { fmt::from_fn(|w| { + let def_id = it.def_id().unwrap(); + wrap_item(w, |w| { render_attributes_in_code(w, it, "", cx)?; write!( w, - "{vis}type {name}{generics}{where_clause} = {type_};", + "{vis}type {name}{generics}", vis = visibility_print_with_space(it, cx), name = it.name.unwrap(), generics = print_generics(&t.generics, cx), - where_clause = - print_where_clause(&t.generics, cx, 0, Ending::Newline).maybe_display(), - type_ = print_type(&t.type_, cx), - ) + )?; + + let type_ = print_type(&t.type_, cx); + let where_clause = + print_where_clause(&t.generics, cx, 0, Ending::NoNewline).maybe_display(); + + if cx.tcx().type_alias_is_checked(def_id) { + write!(w, " = {type_}{where_clause}") + } else { + write!(w, "{where_clause} = {type_}") + }?; + + w.write_str(";") })?; write!(w, "{}", document(cx, it, None, HeadingOffset::H2))?; if let Some(inner_type) = &t.inner_type { - write!(w, "{}", write_section_heading("Aliased Type", "aliased-type", None, ""),)?; + write!(w, "{}", write_section_heading("Aliased Type", "aliased-type", None, ""))?; + + let ty = cx.tcx().type_of(def_id).instantiate_identity().skip_norm_wip(); + let adt_def_id = ty.ty_adt_def().unwrap().did(); match inner_type { clean::TypeAliasInnerType::Enum { variants, is_non_exhaustive } => { - let ty = cx - .tcx() - .type_of(it.def_id().unwrap()) - .instantiate_identity() - .skip_norm_wip(); - let enum_def_id = ty.ty_adt_def().unwrap().did(); - DisplayEnum { variants, generics: &t.generics, is_non_exhaustive: *is_non_exhaustive, - def_id: enum_def_id, + def_id: adt_def_id, } .render_into(cx, it, true, w)?; } clean::TypeAliasInnerType::Union { fields } => { - let ty = cx - .tcx() - .type_of(it.def_id().unwrap()) - .instantiate_identity() - .skip_norm_wip(); - let union_def_id = ty.ty_adt_def().unwrap().did(); - ItemUnion { cx, it, fields, generics: &t.generics, is_type_alias: true, - def_id: union_def_id, + def_id: adt_def_id, } .render_into(w)?; } clean::TypeAliasInnerType::Struct { ctor_kind, fields } => { - let ty = cx - .tcx() - .type_of(it.def_id().unwrap()) - .instantiate_identity() - .skip_norm_wip(); - let struct_def_id = ty.ty_adt_def().unwrap().did(); - DisplayStruct { ctor_kind: *ctor_kind, generics: &t.generics, fields, - def_id: struct_def_id, + def_id: adt_def_id, } .render_into(cx, it, true, w)?; } } } else { - let def_id = it.item_id.expect_def_id(); // Render any items associated directly to this alias, as otherwise they // won't be visible anywhere in the docs. It would be nice to also show // associated items from the aliased type (see discussion in #32077), but diff --git a/tests/rustdoc-html/typedef/checked-type-aliases.rs b/tests/rustdoc-html/typedef/checked-type-aliases.rs new file mode 100644 index 0000000000000..c61c262bb6f10 --- /dev/null +++ b/tests/rustdoc-html/typedef/checked-type-aliases.rs @@ -0,0 +1,9 @@ +#![feature(checked_type_aliases)] +#![expect(incomplete_features)] +#![crate_name = "it"] + +//@ has it/type.Alias.html '//pre[@class="rust item-decl"]' \ +// "type Alias = (T, i32) where String: From;" +pub type Alias = (T, i32) +where + String: From; diff --git a/tests/rustdoc-html/typedef/typedef-inner-variants-lazy_type_alias.rs b/tests/rustdoc-html/typedef/typedef-inner-variants-lazy_type_alias.rs index 53203504fd225..70023c7cf81f4 100644 --- a/tests/rustdoc-html/typedef/typedef-inner-variants-lazy_type_alias.rs +++ b/tests/rustdoc-html/typedef/typedef-inner-variants-lazy_type_alias.rs @@ -13,14 +13,15 @@ pub struct Pair { //@ count - '//*[@id="aliased-type"]' 1 //@ count - '//*[@id="variants"]' 0 //@ count - '//*[@id="fields"]' 1 -//@ count - '//div[@class="where"]' 0 +//@ count - '//span[@class="where"]' 0 pub type ReversedTypesPair = Pair; //@ has 'inner_types_lazy/type.ReadWrite.html' //@ count - '//*[@id="aliased-type"]' 1 //@ count - '//*[@id="variants"]' 0 //@ count - '//*[@id="fields"]' 1 -//@ count - '//div[@class="where"]' 2 +//@ count - '//span[@class="where"]' 1 +//@ count - '//div[@class="where"]' 1 pub type ReadWrite = Pair where R: std::io::Read, @@ -30,5 +31,5 @@ where //@ count - '//*[@id="aliased-type"]' 1 //@ count - '//*[@id="variants"]' 0 //@ count - '//*[@id="fields"]' 1 -//@ count - '//div[@class="where"]' 0 +//@ count - '//span[@class="where"]' 0 pub type VecPair = Pair, Vec>; diff --git a/tests/rustdoc-html/where.golf_type_alias_decl.html b/tests/rustdoc-html/where.golf_type_alias_decl.html index ab60bb262daf2..76234bd1c0239 100644 --- a/tests/rustdoc-html/where.golf_type_alias_decl.html +++ b/tests/rustdoc-html/where.golf_type_alias_decl.html @@ -1,2 +1,3 @@ -pub type Golf<T>

= (T, T); \ No newline at end of file +pub type Golf<T> +where + T: Clone = (T, T); \ No newline at end of file diff --git a/tests/rustdoc-html/where.rs b/tests/rustdoc-html/where.rs index aa1d61a0a1814..470af1a371462 100644 --- a/tests/rustdoc-html/where.rs +++ b/tests/rustdoc-html/where.rs @@ -68,6 +68,6 @@ pub enum Foxtrot { Foxtrot1(F) } impl MyTrait for Foxtrotwhere F: MyTrait {} //@ has foo/type.Golf.html '//pre[@class="rust item-decl"]' \ -// "type Golfwhere T: Clone, = (T, T)" +// "type Golf where T: Clone = (T, T);" //@ snapshot golf_type_alias_decl - '//*[@class="rust item-decl"]/code' pub type Golf where T: Clone = (T, T); From 79d6180478938373ab2de2bb4430e4522c0b906c Mon Sep 17 00:00:00 2001 From: ding-young Date: Sun, 17 Nov 2024 15:07:10 +0900 Subject: [PATCH 0772/1309] fix panic on failure to format generics in enum - related issues: #5738, #6137, #6318, #6378 - instead of calling unwrap(), restore original snippet when we fail to format generics in enum - we need to propagate this rewrite failure later --- src/tools/rustfmt/src/items.rs | 10 +++++++--- .../source/crash-on-enum-generics/issue_5738.rs | 13 +++++++++++++ .../source/crash-on-enum-generics/issue_6137.rs | 3 +++ .../source/crash-on-enum-generics/issue_6318.rs | 13 +++++++++++++ .../target/crash-on-enum-generics/issue_5738.rs | 13 +++++++++++++ .../target/crash-on-enum-generics/issue_6137.rs | 3 +++ .../target/crash-on-enum-generics/issue_6318.rs | 12 ++++++++++++ 7 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs create mode 100644 src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6137.rs create mode 100644 src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs create mode 100644 src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs create mode 100644 src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6137.rs create mode 100644 src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 07ce0b6e58ecb..85db4a873fbff 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -556,9 +556,13 @@ impl<'a> FmtVisitor<'a> { // make a span that starts right after `enum Foo` mk_sp(ident.span.hi(), body_start), last_line_width(&enum_header, self.get_context().config.tab_spaces()), - ) - .unwrap(); - self.push_str(&generics_str); + ); + + if let Some(generics_str) = generics_str { + self.push_str(&generics_str); + } else { + self.push_str(self.snippet(mk_sp(ident.span.hi(), body_start))); + } self.last_pos = body_start; diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs new file mode 100644 index 0000000000000..bdba3b1094401 --- /dev/null +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs @@ -0,0 +1,13 @@ +enum Node where P::>>>>>>>>>>>>>>>>>>>>>>>: { + Cons, +} + +enum En6 +where + T: Tr1>>>>>>>>>>>>>>>>>>>>>>>, +{ + V0, + V1, + V2, + V3, +} diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6137.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6137.rs new file mode 100644 index 0000000000000..a8c75f8e17976 --- /dev/null +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6137.rs @@ -0,0 +1,3 @@ +enum MZReaderType< + D: DeconvolutedCentroidLike + Default + From + BuildFromArrayMap=DeconvolutedPeak +> {} diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs new file mode 100644 index 0000000000000..787225f4aae0f --- /dev/null +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs @@ -0,0 +1,13 @@ +// rustfmt-max_width: 80 +fn my_fn() { + enum MyEnum + where + SomeTypeA___: SomeTrait__< + _A, + Archived = , + >>::Archived, + >, + { + } +} diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs new file mode 100644 index 0000000000000..4a9dd0d8a1c9b --- /dev/null +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs @@ -0,0 +1,13 @@ +enum Node where P::>>>>>>>>>>>>>>>>>>>>>>>: { + Cons, +} + +enum En6 +where + T: Tr1>>>>>>>>>>>>>>>>>>>>>>>, +{ + V0, + V1, + V2, + V3, +} diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6137.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6137.rs new file mode 100644 index 0000000000000..a8c75f8e17976 --- /dev/null +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6137.rs @@ -0,0 +1,3 @@ +enum MZReaderType< + D: DeconvolutedCentroidLike + Default + From + BuildFromArrayMap=DeconvolutedPeak +> {} diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs new file mode 100644 index 0000000000000..6f3b9275349c1 --- /dev/null +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs @@ -0,0 +1,12 @@ +// rustfmt-max_width: 80 +fn my_fn() { + enum MyEnum + where + SomeTypeA___: SomeTrait__< + _A, + Archived = , + >>::Archived, + >, + {} +} From bc92c8603bd63970451f7fe3dac6af2c60e7e8ca Mon Sep 17 00:00:00 2001 From: ding-young Date: Fri, 29 Nov 2024 17:55:34 +0900 Subject: [PATCH 0773/1309] refactor visit_enum - introduce format_enum that returns Rewrite - early return when it fails to format the generics in enum --- src/tools/rustfmt/src/items.rs | 41 ++++++++++++------- src/tools/rustfmt/src/visitor.rs | 2 - .../crash-on-enum-generics/issue_5738.rs | 2 +- .../crash-on-enum-generics/issue_6318.rs | 1 + .../crash-on-enum-generics/issue_5738.rs | 2 +- .../crash-on-enum-generics/issue_6318.rs | 4 +- 6 files changed, 32 insertions(+), 20 deletions(-) diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 85db4a873fbff..60d8d8963c524 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -528,21 +528,21 @@ impl<'a> FmtVisitor<'a> { self.push_rewrite(struct_parts.span, rewrite); } - pub(crate) fn visit_enum( + fn format_enum( &mut self, ident: symbol::Ident, vis: &ast::Visibility, enum_def: &ast::EnumDef, generics: &ast::Generics, span: Span, - ) { + ) -> Option { let enum_header = format_header(&self.get_context(), "enum ", ident, vis, self.block_indent); - self.push_str(&enum_header); let enum_snippet = self.snippet(span); let brace_pos = enum_snippet.find_uncommented("{").unwrap(); let body_start = span.lo() + BytePos(brace_pos as u32 + 1); + let generics_str = format_generics( &self.get_context(), generics, @@ -556,25 +556,36 @@ impl<'a> FmtVisitor<'a> { // make a span that starts right after `enum Foo` mk_sp(ident.span.hi(), body_start), last_line_width(&enum_header, self.get_context().config.tab_spaces()), - ); - - if let Some(generics_str) = generics_str { - self.push_str(&generics_str); - } else { - self.push_str(self.snippet(mk_sp(ident.span.hi(), body_start))); - } - - self.last_pos = body_start; + )?; match self.format_variant_list(enum_def, body_start, span.hi()) { - Some(ref s) if enum_def.variants.is_empty() => self.push_str(s), - rw => { - self.push_rewrite(mk_sp(body_start, span.hi()), rw); + Some(ref s) if enum_def.variants.is_empty() => { + Some(format!("{enum_header}{generics_str}{s}")) + } + Some(rw) => { + let indent = self.block_indent.to_string(self.config); + self.block_indent = self.block_indent.block_unindent(self.config); + Some(format!("{enum_header}{generics_str}\n{indent}{rw}")) + } + None => { self.block_indent = self.block_indent.block_unindent(self.config); + None } } } + pub(crate) fn visit_enum( + &mut self, + ident: symbol::Ident, + vis: &ast::Visibility, + enum_def: &ast::EnumDef, + generics: &ast::Generics, + span: Span, + ) { + let rewrite = self.format_enum(ident, vis, enum_def, generics, span); + self.push_rewrite(span, rewrite); + } + // Format the body of an enum definition fn format_variant_list( &mut self, diff --git a/src/tools/rustfmt/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs index 5043038d4fc09..7824963bb4ff6 100644 --- a/src/tools/rustfmt/src/visitor.rs +++ b/src/tools/rustfmt/src/visitor.rs @@ -527,9 +527,7 @@ impl<'b, 'a: 'b> FmtVisitor<'a> { self.visit_struct(&StructParts::from_item(item)); } ast::ItemKind::Enum(ident, ref generics, ref def) => { - self.format_missing_with_indent(source!(self, item.span).lo()); self.visit_enum(ident, &item.vis, def, generics, item.span); - self.last_pos = source!(self, item.span).hi(); } ast::ItemKind::Mod(safety, ident, ref mod_kind) => { self.format_missing_with_indent(source!(self, item.span).lo()); diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs index bdba3b1094401..70d211f0e8108 100644 --- a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_5738.rs @@ -8,6 +8,6 @@ where { V0, V1, - V2, + V2, // left unformatted since formatting where clause fails V3, } diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs index 787225f4aae0f..73471f3eee1a2 100644 --- a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6318.rs @@ -8,6 +8,7 @@ fn my_fn() { Option<[u8; 4]>, >>::Archived, >, + // left unformatted since formatting where clause fails { } } diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs index 4a9dd0d8a1c9b..70d211f0e8108 100644 --- a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_5738.rs @@ -8,6 +8,6 @@ where { V0, V1, - V2, + V2, // left unformatted since formatting where clause fails V3, } diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs index 6f3b9275349c1..73471f3eee1a2 100644 --- a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6318.rs @@ -8,5 +8,7 @@ fn my_fn() { Option<[u8; 4]>, >>::Archived, >, - {} + // left unformatted since formatting where clause fails + { + } } From da10331482bf3fe3aaf812e6892d6e12021c13ac Mon Sep 17 00:00:00 2001 From: Seoyoung Lee Date: Sun, 5 Oct 2025 23:47:04 +0900 Subject: [PATCH 0774/1309] add test case for issue#6571 --- .../source/crash-on-enum-generics/issue_6571.rs | 14 ++++++++++++++ .../target/crash-on-enum-generics/issue_6571.rs | 14 ++++++++++++++ 2 files changed, 28 insertions(+) create mode 100644 src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6571.rs create mode 100644 src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6571.rs diff --git a/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6571.rs b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6571.rs new file mode 100644 index 0000000000000..b28d50f583184 --- /dev/null +++ b/src/tools/rustfmt/tests/source/crash-on-enum-generics/issue_6571.rs @@ -0,0 +1,14 @@ +pub enum TestEnum< + T: std::collections::HashMap>> + Clone + Default + PartialEq + Eq + std::fmt::Debug + serde::Serialize + serde::Deserialize<'static> + Send + Sync + 'static = std::collections::HashMap>>, +> { + Variant1(T), + Variant2 { field: T }, +} + +// More realistic example from real codebase +pub enum ElementInit< + P: wrt_foundation::MemoryProvider + Clone + Default + PartialEq + Eq = wrt_foundation::NoStdProvider<1024>, +> { + FuncIndices(crate::WasmVec), + Expressions(crate::WasmVec, P>), +} diff --git a/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6571.rs b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6571.rs new file mode 100644 index 0000000000000..b28d50f583184 --- /dev/null +++ b/src/tools/rustfmt/tests/target/crash-on-enum-generics/issue_6571.rs @@ -0,0 +1,14 @@ +pub enum TestEnum< + T: std::collections::HashMap>> + Clone + Default + PartialEq + Eq + std::fmt::Debug + serde::Serialize + serde::Deserialize<'static> + Send + Sync + 'static = std::collections::HashMap>>, +> { + Variant1(T), + Variant2 { field: T }, +} + +// More realistic example from real codebase +pub enum ElementInit< + P: wrt_foundation::MemoryProvider + Clone + Default + PartialEq + Eq = wrt_foundation::NoStdProvider<1024>, +> { + FuncIndices(crate::WasmVec), + Expressions(crate::WasmVec, P>), +} From f3b4f0f80c74e8ed19e38b14608effb51e7d339a Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Tue, 25 Aug 2026 07:25:17 +0700 Subject: [PATCH 0775/1309] Stabilize `Result::into_{ok,err}` Tracking issue: https://github.com/rust-lang/rust/issues/61695 --- compiler/rustc_arena/src/lib.rs | 2 +- compiler/rustc_data_structures/src/lib.rs | 2 +- compiler/rustc_hir_analysis/src/lib.rs | 2 +- compiler/rustc_trait_selection/src/lib.rs | 2 +- library/alloc/src/lib.rs | 1 - library/alloctests/lib.rs | 1 - library/core/src/result.rs | 8 ++------ library/coretests/tests/lib.rs | 1 - library/std/src/lib.rs | 1 - src/tools/clippy/clippy_lints/src/lib.rs | 2 +- src/tools/clippy/clippy_utils/src/lib.rs | 2 +- 11 files changed, 8 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index 0fc1f96dfe469..f2c6ffe44cdfd 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -11,13 +11,13 @@ #![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine. #![allow(internal_features)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] #![doc(test(no_crate_inject, attr(deny(warnings))))] #![feature(decl_macro)] #![feature(dropck_eyepatch)] #![feature(rustc_attrs)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end use std::alloc::Layout; diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 041763f57fc9e..4ebd6ef9f92b3 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -12,6 +12,7 @@ #![allow(rustc::potential_query_instability)] #![cfg_attr(bootstrap, feature(allocator_api))] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(not(bootstrap), feature(allocator_ext))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] @@ -35,7 +36,6 @@ #![feature(thread_id_value)] #![feature(trusted_len)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // This allows derive macros to reference this crate diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index dbbf068185c23..c0abcc3a6119a 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -57,12 +57,12 @@ This API is completely unstable and subject to change. // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(default_field_values)] #![feature(gen_blocks)] #![feature(iter_intersperse)] #![feature(slice_partition_dedup)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // These are used by Clippy. diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index bbaf683f4288a..a5cb7d0c7bb1a 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -12,6 +12,7 @@ // tidy-alphabetical-start #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] @@ -20,7 +21,6 @@ #![feature(iterator_try_reduce)] #![feature(option_into_flat_iter)] #![feature(try_blocks)] -#![feature(unwrap_infallible)] #![feature(yeet_expr)] #![recursion_limit = "512"] // For rustdoc // tidy-alphabetical-end diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index de6830a514656..5e4b3b3d536f6 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -186,7 +186,6 @@ #![feature(ub_checks)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] #![feature(write_all_vectored)] #![feature(wtf8_internals)] // tidy-alphabetical-end diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 76550081a703c..a5f46099173c0 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -50,7 +50,6 @@ #![feature(trusted_random_access)] #![feature(try_reserve_kind)] #![feature(try_trait_v2)] -#![feature(unwrap_infallible)] #![feature(wtf8_internals)] // tidy-alphabetical-end // diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 472d568c5cf66..da6be4d6d48a0 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -1343,8 +1343,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_good_news() -> Result { /// Ok("this is fine".into()) /// } @@ -1352,7 +1350,7 @@ impl Result { /// let s: String = only_good_news().into_ok(); /// println!("{s}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] @@ -1379,8 +1377,6 @@ impl Result { /// # Examples /// /// ``` - /// # #![feature(unwrap_infallible)] - /// /// fn only_bad_news() -> Result { /// Err("Oops, it failed".into()) /// } @@ -1388,7 +1384,7 @@ impl Result { /// let error: String = only_bad_news().into_err(); /// println!("{error}"); /// ``` - #[unstable(feature = "unwrap_infallible", issue = "61695")] + #[stable(feature = "unwrap_infallible", since = "CURRENT_RUSTC_VERSION")] #[inline] #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 69bc6edd1b833..c52357da0279d 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -130,7 +130,6 @@ #![feature(uint_gather_scatter_bits)] #![feature(unicode_internals)] #![feature(unsize)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end #![allow(internal_features)] #![deny(implicit_provenance_casts)] diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d59d204d6e144..bfdfb6ba9a4fd 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -313,7 +313,6 @@ #![feature(try_blocks)] #![feature(try_trait_v2)] #![feature(type_alias_impl_trait)] -#![feature(unwrap_infallible)] // tidy-alphabetical-end // // Library features (core): diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 435f787f7012f..87bb44875aee9 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -8,9 +8,9 @@ #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::literal_string_with_formatting_args, clippy::must_use_candidate)] #![warn( diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 0030f1cdc8208..5579dd1fc62d8 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -1,7 +1,7 @@ +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(deref_patterns)] #![feature(macro_metavar_expr)] #![feature(rustc_private)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( From 7d5d73724a1ae1524a7a0a08ee313310614cb4d4 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Tue, 25 Aug 2026 07:25:17 +0700 Subject: [PATCH 0776/1309] Stabilize `Result::into_{ok,err}` Tracking issue: https://github.com/rust-lang/rust/issues/61695 --- clippy_lints/src/lib.rs | 2 +- clippy_utils/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 435f787f7012f..87bb44875aee9 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -8,9 +8,9 @@ #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] #![cfg_attr(bootstrap, feature(never_type))] +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::literal_string_with_formatting_args, clippy::must_use_candidate)] #![warn( diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 0030f1cdc8208..5579dd1fc62d8 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -1,7 +1,7 @@ +#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(deref_patterns)] #![feature(macro_metavar_expr)] #![feature(rustc_private)] -#![feature(unwrap_infallible)] #![recursion_limit = "512"] #![expect(clippy::missing_errors_doc, clippy::missing_panics_doc, clippy::must_use_candidate)] #![warn( From 8e8371121c32b1649ef81fb9f61f2848e692b0ba Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 17 Aug 2026 14:47:59 +0200 Subject: [PATCH 0777/1309] Split path segment stability checking out into a separate method --- compiler/rustc_passes/src/stability.rs | 168 +++++++++++++------------ 1 file changed, 90 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 1148aac51f3e8..87e034f52451b 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_feature::{EnabledLangFeature, EnabledLibFeature, UNSTABLE_LANG_FEATURES}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModId}; +use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ self as hir, AmbigArg, Constness, FieldDef, HirId, Item, ItemKind, Path, TraitRef, Ty, TyKind, @@ -954,90 +954,102 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if item_is_allowed { // The item itself is allowed; check whether the path there is also allowed. - let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = - self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { - StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { - allowed_through_unstable_modules - } - _ => None, - }); + self.check_path_segments(path, id, method_span, def_id); + } + } - // Check parent modules stability as well if the item the path refers to is itself - // stable. We only emit errors for unstable path segments if the item is stable - // or allowed because stability is often inherited, so the most common case is that - // both the segments and the item are unstable behind the same feature flag. - // - // We check here rather than in `visit_path_segment` to prevent visiting the last - // path segment twice - // - // We include special cases via #[rustc_allowed_through_unstable_modules] for items - // that were accidentally stabilized through unstable paths before this check was - // added, such as `core::intrinsics::transmute` - let parents = path.segments.iter().rev().skip(1); - for path_segment in parents { - if let Some(def_id) = path_segment.res.opt_def_id() { - match is_allowed_through_unstable_modules { - None => { - // Emit a hard stability error if this path is not stable. - - // use `None` for id to prevent deprecation check - self.tcx.check_stability_allow_unstable( - def_id, - None, - path_segment.ident.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, - ); - } - Some((message, suggestion)) => { - // Call the stability check directly so that we can control which - // diagnostic is emitted. - let eval_result = self.tcx.eval_stability_allow_unstable( - def_id, - None, + intravisit::walk_path(self, path) + } +} + +impl<'tcx> Checker<'tcx> { + /// Check parent modules stability as well if the item the path refers to is itself + /// stable. We only emit errors for unstable path segments if the item is stable + /// or allowed because stability is often inherited, so the most common case is that + /// both the segments and the item are unstable behind the same feature flag. + /// + /// We check here rather than in `visit_path_segment` to prevent visiting the last + /// path segment twice + /// + /// We include special cases via `#[rustc_allowed_through_unstable_modules]` for items + /// that were accidentally stabilized through unstable paths before this check was + /// added, such as `core::intrinsics::transmute` + fn check_path_segments( + &mut self, + path: &Path<'tcx>, + id: HirId, + method_span: Option, + def_id: DefId, + ) { + let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = + self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { + StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { + allowed_through_unstable_modules + } + _ => None, + }); + + let parents = path.segments.iter().rev().skip(1); + for path_segment in parents { + if let Some(def_id) = path_segment.res.opt_def_id() { + match is_allowed_through_unstable_modules { + None => { + // Emit a hard stability error if this path is not stable. + + // use `None` for id to prevent deprecation check + self.tcx.check_stability_allow_unstable( + def_id, + None, + path_segment.ident.span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, + ); + } + Some((message, suggestion)) => { + // Call the stability check directly so that we can control which + // diagnostic is emitted. + let eval_result = self.tcx.eval_stability_allow_unstable( + def_id, + None, + path.span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, + ); + let is_allowed = matches!(eval_result, EvalResult::Allow); + if !is_allowed { + // Show a deprecation message. + let [.., intrinsics_module, _intrinsic] = path.segments else { + span_bug!( path.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, - ); - let is_allowed = matches!(eval_result, EvalResult::Allow); - if !is_allowed { - // Show a deprecation message. - let [.., intrinsics_module, _intrinsic] = path.segments else { - span_bug!( - path.span, - "no module for `is_allowed_through_unstable_modules` intrinsic {path:?}" - ) - }; - let diag = diagnostics::RustcAtumSuggestion { - message, - import_span: path.span, - unstable_mod_span: { intrinsics_module.ident.span }, - module: intrinsics_module.ident, - suggestion, - }; - self.tcx.emit_node_span_lint( - DEPRECATED, - id, - method_span.unwrap_or(path.span), - diag, - ); - } - } + "no module for `is_allowed_through_unstable_modules` intrinsic {path:?}" + ) + }; + let diag = diagnostics::RustcAtumSuggestion { + message, + import_span: path.span, + unstable_mod_span: { intrinsics_module.ident.span }, + module: intrinsics_module.ident, + suggestion, + }; + self.tcx.emit_node_span_lint( + DEPRECATED, + id, + method_span.unwrap_or(path.span), + diag, + ); } } } } } - - intravisit::walk_path(self, path) } } From 8abb71dfd248075095abd628319c3db2254b42cd Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Sep 2026 14:28:27 +0200 Subject: [PATCH 0778/1309] Avoid passing a hir::Import around everywhere --- src/librustdoc/clean/inline.rs | 9 +++++---- src/librustdoc/clean/mod.rs | 37 +++++++++++++++++++++++----------- 2 files changed, 30 insertions(+), 16 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2fbfae88918a0..08b065f183787 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModId}; -use rustc_hir::{self as hir, Mutability, find_attr}; +use rustc_hir::{self as hir, HirId, Mutability, find_attr}; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; @@ -184,7 +184,8 @@ pub(crate) fn try_inline_glob( current_mod: LocalModId, visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, - import: &hir::Item<'_>, + import_id: LocalDefId, + import_hir_id: HirId, ) -> Option> { let did = res.opt_def_id()?; if did.is_local() { @@ -203,7 +204,7 @@ pub(crate) fn try_inline_glob( .filter_map(|child| child.res.opt_def_id()) .filter(|&def_id| !cx.tcx.is_doc_hidden(def_id)) .collect(); - let attrs = cx.tcx.hir_attrs(import.hir_id()); + let attrs = cx.tcx.hir_attrs(import_hir_id); let mut items = build_module_items( cx, did, @@ -211,7 +212,7 @@ pub(crate) fn try_inline_glob( visited, inlined_names, Some(&reexports), - Some((attrs, Some(import.owner_id.def_id))), + Some((attrs, Some(import_id))), ); items.retain(|item| { if let Some(name) = item.name { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 2220d34cc1b53..b3f6617479f21 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -38,12 +38,11 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, In use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::codes::*; use rustc_errors::{FatalError, struct_span_code_err}; -use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::attrs::{AttributeKind, DocAttribute, DocInline}; use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, HirId, PredicateOrigin, find_attr}; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::middle::resolve::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -125,7 +124,9 @@ pub(crate) fn clean_doc_module<'tcx>( let hir::UsePath { segments, span, .. } = *path; let path = hir::Path { segments, res: *res, span }; clean_use_statement_inner( - import, + import.span, + import.owner_id.def_id, + import.hir_id(), Some(name), &path, kind, @@ -3158,13 +3159,24 @@ fn clean_use_statement<'tcx>( let hir::UsePath { segments, ref res, span } = *path; for res in res.present_items() { let path = hir::Path { segments, res, span }; - items.append(&mut clean_use_statement_inner(import, name, &path, kind, cx, inlined_names)); + items.append(&mut clean_use_statement_inner( + import.span, + import.owner_id.def_id, + import.hir_id(), + name, + &path, + kind, + cx, + inlined_names, + )); } items } fn clean_use_statement_inner<'tcx>( - import: &hir::Item<'tcx>, + import_span: rustc_span::Span, + import_id: LocalDefId, + import_hir_id: HirId, name: Option, path: &hir::Path<'_>, kind: hir::UseKind, @@ -3177,20 +3189,20 @@ fn clean_use_statement_inner<'tcx>( // We need this comparison because some imports (for std types for example) // are "inserted" as well but directly by the compiler and they should not be // taken into account. - if import.span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { + if import_span.ctxt().outer_expn_data().kind == ExpnKind::AstPass(AstPass::StdImports) { return Vec::new(); } - let visibility = cx.tcx.visibility(import.owner_id); - let attrs = cx.tcx.hir_attrs(import.hir_id()); + let visibility = cx.tcx.visibility(import_id); + let attrs = cx.tcx.hir_attrs(import_hir_id); let inline_attr = find_attr!( attrs, Doc(d) if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline) => d ) .and_then(|d| d.inline.first()); let pub_underscore = visibility.is_public() && name == Some(kw::Underscore); - let current_mod = cx.tcx.parent_module_from_def_id(import.owner_id.def_id); - let import_def_id = import.owner_id.def_id; + let current_mod = cx.tcx.parent_module_from_def_id(import_id); + let import_def_id = import_id; // The parent of the module in which this import resides. This // is the same as `current_mod` if that's already the top @@ -3212,7 +3224,7 @@ fn clean_use_statement_inner<'tcx>( E0780, "anonymous imports cannot be inlined" ) - .with_span_label(import.span, "anonymous import") + .with_span_label(import_span, "anonymous import") .emit(); } @@ -3241,7 +3253,8 @@ fn clean_use_statement_inner<'tcx>( current_mod, &mut visited, inlined_names, - import, + import_id, + import_hir_id, ) { return items; } From d39377200900c271840f44f0d14d4d1cc2f81723 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 14 Sep 2026 17:25:02 +0200 Subject: [PATCH 0779/1309] Only pass down the information actually needed --- compiler/rustc_passes/src/stability.rs | 31 ++++++++++++-------------- 1 file changed, 14 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 87e034f52451b..a442d655fb124 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -570,8 +570,8 @@ struct Checker<'tcx> { } impl<'tcx> Checker<'tcx> { - fn unstable_reexport_span(&self, item: &'tcx hir::Item<'tcx>) -> Option { - let attrs = self.tcx.hir_attrs(item.hir_id()); + fn unstable_reexport_span(&self, hir_id: HirId) -> Option { + let attrs = self.tcx.hir_attrs(hir_id); let (stability, span) = find_attr!(attrs, Stability { stability, span } => (*stability, *span))?; @@ -624,14 +624,14 @@ impl<'tcx> Checker<'tcx> { fn record_unstable_reexport( &mut self, - item: &'tcx hir::Item<'tcx>, + hir_id: HirId, attr_span: Span, span: Span, has_target: bool, all_targets_stable: bool, ) { let entry = self.unstable_reexports.entry(attr_span).or_insert(UnstableReexport { - hir_id: item.hir_id(), + hir_id, span, has_target: false, all_targets_stable: true, @@ -641,31 +641,28 @@ impl<'tcx> Checker<'tcx> { entry.all_targets_stable &= all_targets_stable; } - fn check_single_unstable_reexport( - &mut self, - item: &'tcx hir::Item<'tcx>, - path: &'tcx UsePath<'tcx>, - ) { - let Some(attr_span) = self.unstable_reexport_span(item) else { + fn check_single_unstable_reexport(&mut self, hir_id: HirId, path: &'tcx UsePath<'tcx>) { + let Some(attr_span) = self.unstable_reexport_span(hir_id) else { return; }; let (has_target, all_targets_stable) = self.classify_reexport_targets(path.res.present_items()); - self.record_unstable_reexport(item, attr_span, path.span, has_target, all_targets_stable); + self.record_unstable_reexport(hir_id, attr_span, path.span, has_target, all_targets_stable); } fn check_glob_unstable_reexport( &mut self, - item: &'tcx hir::Item<'tcx>, + hir_id: HirId, + glob_def_id: LocalDefId, path: &'tcx UsePath<'tcx>, ) { - let Some(attr_span) = self.unstable_reexport_span(item) else { + let Some(attr_span) = self.unstable_reexport_span(hir_id) else { return; }; - let glob_def_id = item.owner_id.def_id.to_def_id(); + let glob_def_id = glob_def_id.to_def_id(); let targets = self .tcx @@ -678,7 +675,7 @@ impl<'tcx> Checker<'tcx> { let (has_target, all_targets_stable) = self.classify_reexport_targets(targets); - self.record_unstable_reexport(item, attr_span, path.span, has_target, all_targets_stable); + self.record_unstable_reexport(hir_id, attr_span, path.span, has_target, all_targets_stable); } fn containing_module_is_unstable(&self) -> bool { @@ -737,14 +734,14 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if self.tcx.features().staged_api() && self.tcx.local_visibility(item.owner_id.def_id).is_public() => { - self.check_single_unstable_reexport(item, path); + self.check_single_unstable_reexport(item.hir_id(), path); } hir::ItemKind::Use(path, hir::UseKind::Glob) if self.tcx.features().staged_api() && self.tcx.local_visibility(item.owner_id.def_id).is_public() => { - self.check_glob_unstable_reexport(item, path); + self.check_glob_unstable_reexport(item.hir_id(), item.owner_id.def_id, path); } // For implementations of traits, check the stability of each item From b8a917a93c35d017182799d40e2261b63bf34ae8 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 10 Sep 2026 16:20:47 +0200 Subject: [PATCH 0780/1309] Simplify a condition that mostly did the same in both arms --- src/librustdoc/visit_ast.rs | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index ee30c6d153c0b..bbd29e9727acc 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -425,21 +425,14 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { renamed = None; } let key = (item.owner_id.def_id, renamed); - if let Some(import_id) = import_id { - self.modules - .last_mut() - .unwrap() - .items - .entry(key) - .and_modify(|v| v.import_ids.push(import_id)) - .or_insert_with(|| ItemEntry { item, renamed, import_ids: vec![import_id] }); - } else { - self.modules - .last_mut() - .unwrap() - .items - .insert(key, ItemEntry { item, renamed, import_ids: Vec::new() }); - } + self.modules + .last_mut() + .unwrap() + .items + .entry(key) + .or_insert_with(|| ItemEntry { item, renamed, import_ids: vec![] }) + .import_ids + .extend(import_id); } } From c36cdecd0d73f780945d67e619ebf026280f75c2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Fri, 18 Sep 2026 16:26:06 +0200 Subject: [PATCH 0781/1309] Pull rustdoc use tree visiting logic out into a separate method --- src/librustdoc/visit_ast.rs | 99 ++++++++++++++++++++----------------- 1 file changed, 54 insertions(+), 45 deletions(-) diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index bbd29e9727acc..a0c2c251a4a8c 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -481,51 +481,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { hir::ItemKind::GlobalAsm { .. } => {} hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} hir::ItemKind::Use(path, kind) => { - for res in path.res.present_items() { - // Struct and variant constructors and proc macro stubs always show up alongside - // their definitions, we've already processed them so just discard these. - if should_ignore_res(res) { - continue; - } - - let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id)); - - // If there was a private module in the current path then don't bother inlining - // anything as it will probably be stripped anyway. - if is_pub && self.inside_public_path { - let please_inline = if let Some(res_did) = res.opt_def_id() - && matches!(tcx.def_kind(res_did), DefKind::Macro(MacroKinds::BANG)) - { - crate::clean::macro_reexport_is_inline( - tcx, - item.owner_id.def_id, - res_did, - ) - } else { - find_attr!( - attrs, - Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) - ) - }; - let ident = match kind { - hir::UseKind::Single(ident) => Some(ident.name), - hir::UseKind::Glob => None, - hir::UseKind::ListStem => unreachable!(), - }; - if self.maybe_inline_local( - item.owner_id.def_id, - res, - ident, - please_inline, - import_id, - ) { - debug!("Inlining {:?}", item.owner_id.def_id); - continue; - } - } - self.add_to_current_mod(item, renamed, import_id); - } + self.visit_tree_inner(item, renamed, import_id, is_pub, path, kind); } hir::ItemKind::Macro(_, macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, @@ -579,6 +535,59 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } + fn visit_tree_inner( + &mut self, + item: &'tcx hir::Item<'tcx>, + renamed: Option, + import_id: Option, + is_pub: bool, + path: &hir::UsePath<'_>, + kind: hir::UseKind, + ) { + let tcx = self.cx.tcx; + for res in path.res.present_items() { + // Struct and variant constructors and proc macro stubs always show up alongside + // their definitions, we've already processed them so just discard these. + if should_ignore_res(res) { + continue; + } + + let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id)); + + // If there was a private module in the current path then don't bother inlining + // anything as it will probably be stripped anyway. + if is_pub && self.inside_public_path { + let please_inline = if let Some(res_did) = res.opt_def_id() + && matches!(tcx.def_kind(res_did), DefKind::Macro(MacroKinds::BANG)) + { + crate::clean::macro_reexport_is_inline(tcx, item.owner_id.def_id, res_did) + } else { + find_attr!( + attrs, + Doc(d) + if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) + ) + }; + let ident = match kind { + hir::UseKind::Single(ident) => Some(ident.name), + hir::UseKind::Glob => None, + hir::UseKind::ListStem => unreachable!(), + }; + if self.maybe_inline_local( + item.owner_id.def_id, + res, + ident, + please_inline, + import_id, + ) { + debug!("Inlining {:?}", item.owner_id.def_id); + continue; + } + } + self.add_to_current_mod(item, renamed, import_id); + } + } + fn visit_foreign_item_inner( &mut self, item: &'tcx hir::ForeignItem<'_>, From cb4d648f48c3c617818cf3881df1dd7bb19375db Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Aug 2026 11:55:08 +0200 Subject: [PATCH 0782/1309] Handle use item collection in the late resolution visitor --- compiler/rustc_resolve/src/late.rs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 8c4a9babe2213..75f397b685fea 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -846,6 +846,9 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// `use` injections are delayed for better placement and deduplication. use_injections: Vec>, + + /// All `use` and `extern crate` items, in the order in which they are visited. + use_items: Vec<&'ast Item>, } impl<'ra, 'tcx> AsRef> for LateResolutionVisitor<'_, '_, 'ra, 'tcx> { @@ -1571,6 +1574,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { in_func_body: false, lifetime_uses: Default::default(), use_injections: Vec::new(), + use_items: Vec::new(), } } @@ -3047,6 +3051,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ), ItemKind::Use(use_tree) => { + self.use_items.push(item); let maybe_exported = match use_tree.kind { UseTreeKind::Simple(_) | UseTreeKind::Glob(_) => MaybeExported::Ok(item.id), UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis), @@ -3092,7 +3097,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); } - ItemKind::ExternCrate(..) => {} + ItemKind::ExternCrate(..) => self.use_items.push(item), ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => { panic!("unexpanded macro in resolve!") @@ -5674,13 +5679,11 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// Walks the whole crate in DFS order, visiting each item, counting the declared number of /// lifetime generic parameters and function parameters. Also collects all `use` and /// `extern crate` items so that `check_unused` doesn't need to walk the crate again. -struct ItemInfoCollector<'a, 'ast, 'ra, 'tcx> { +struct ItemInfoCollector<'a, 'ra, 'tcx> { r: &'a mut Resolver<'ra, 'tcx>, - /// All `use` and `extern crate` items, in the order in which they are visited. - use_items: Vec<&'ast Item>, } -impl ItemInfoCollector<'_, '_, '_, '_> { +impl ItemInfoCollector<'_, '_, '_> { fn collect_fn_info(&mut self, decl: &FnDecl, id: NodeId) { self.r .delegation_fn_sigs @@ -5714,8 +5717,8 @@ fn required_generic_args_suggestion(generics: &ast::Generics) -> Option if required.is_empty() { None } else { Some(format!("<{}>", required.join(", "))) } } -impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, 'ast, '_, '_> { - fn visit_item(&mut self, item: &'ast Item) { +impl Visitor<'_> for ItemInfoCollector<'_, '_, '_> { + fn visit_item(&mut self, item: &Item) { if let Some(generics) = item.opt_generics() { let def_id = self.r.owner_def_id(item.id); let count = generics @@ -5739,16 +5742,14 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, 'ast, '_, '_> { } } - ItemKind::Use(..) | ItemKind::ExternCrate(..) => { - self.use_items.push(item); - } - ItemKind::Mod(..) | ItemKind::Static(..) | ItemKind::ConstBlock(..) | ItemKind::MacroDef(..) | ItemKind::GlobalAsm(..) | ItemKind::MacCall(..) + | ItemKind::Use(..) + | ItemKind::ExternCrate(..) | ItemKind::DelegationMac(..) | ItemKind::TyAlias(..) | ItemKind::Const(..) @@ -5769,7 +5770,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, 'ast, '_, '_> { visit::walk_item(self, item) } - fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) { + fn visit_assoc_item(&mut self, item: &AssocItem, ctxt: AssocCtxt) { if let AssocItemKind::Fn(Fn { sig, .. }) = &item.kind { self.collect_fn_info(&sig.decl, item.id); } @@ -5791,14 +5792,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { krate: &'ast Crate, ) -> (Vec<&'ast Item>, Vec>) { with_owner(self, CRATE_NODE_ID, |this| { - let mut info_collector = ItemInfoCollector { r: this, use_items: Vec::new() }; + let mut info_collector = ItemInfoCollector { r: this }; visit::walk_crate(&mut info_collector, krate); - let use_items = info_collector.use_items; let mut late_resolution_visitor = LateResolutionVisitor::new(this); late_resolution_visitor .resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); visit::walk_crate(&mut late_resolution_visitor, krate); - let LateResolutionVisitor { use_injections, diag_metadata, .. } = + let LateResolutionVisitor { use_injections, diag_metadata, use_items, .. } = late_resolution_visitor; for (id, span) in diag_metadata.unused_labels.iter() { this.lint_buffer.buffer_lint( From 594525f8915c0377c3ddbadfa94f7795f6886650 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 3 Aug 2026 10:18:26 +0200 Subject: [PATCH 0783/1309] Don't create an owner per import, lower them as part of their surrounding scope instead --- compiler/rustc_ast_lowering/src/lib.rs | 3 +- compiler/rustc_middle/src/middle/resolve.rs | 4 +-- .../rustc_resolve/src/build_reduced_graph.rs | 25 +++++++------ compiler/rustc_resolve/src/check_unused.rs | 35 ++++++++++--------- compiler/rustc_resolve/src/def_collector.rs | 4 ++- .../src/effective_visibilities.rs | 7 +++- compiler/rustc_resolve/src/imports.rs | 7 +++- compiler/rustc_resolve/src/lib.rs | 7 +++- 8 files changed, 56 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 8513ee39855d0..e6479d1e4f4bc 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1029,7 +1029,8 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_import_res(&self, id: NodeId, span: Span) -> PerNS> { debug_assert_eq!(id, self.curr_owner.owner.id); - let per_ns = self.curr_owner.owner.import_res.map(|res| res.map(|res| self.lower_res(res))); + let per_ns = + self.curr_owner.owner.import_res[&id].map(|res| res.map(|res| self.lower_res(res))); if per_ns.is_empty() { // Propagate the error to all namespaces, just to be sure. self.dcx().span_delayed_bug(span, "no resolution for an import"); diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs index 8267cde89ad27..3bd95a132ab56 100644 --- a/compiler/rustc_middle/src/middle/resolve.rs +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -207,8 +207,8 @@ pub struct PerOwnerResolverData<'tcx> { pub trait_map: NodeMap<&'tcx [TraitCandidate<'tcx>]> = Default::default(), - /// Resolution for import nodes, which have multiple resolutions in different namespaces. - pub import_res: PerNS>> = Default::default(), + /// Resolutions for import nodes, which have multiple resolutions in different namespaces. + pub import_res: NodeMap>>> = Default::default(), /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap> = Default::default(), diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 7ddf916bc7b6b..09d7f5dd11006 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -759,19 +759,18 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { ast::UseTreeKind::Nested { ref items, .. } => { for tree in items { let id = tree.id; - self.with_owner(id, None, DefKind::Use, use_tree.span(), |this, feed| { - this.build_reduced_graph_for_use_tree( - item, - &tree.inner, - id, - &prefix, - true, - false, - vis, - root_span, - feed, - ) - }); + let feed = self.create_def(id, None, DefKind::Use, use_tree.span()); + self.build_reduced_graph_for_use_tree( + item, + &tree.inner, + id, + &prefix, + true, + false, + vis, + root_span, + feed, + ); } // Empty groups `a::b::{}` are turned into synthetic `self` imports diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 68fbb139e9041..daa816c276482 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -38,13 +38,14 @@ use rustc_lint_defs::builtin::{ use rustc_span::{DUMMY_SP, Ident, Span, kw}; use crate::imports::{Import, ImportKind}; -use crate::{DeclKind, IdentKey, LateDecl, Resolver, diagnostics, module_to_string}; +use crate::{DeclKind, IdentKey, LateDecl, Resolver, diagnostics, module_to_string, with_owner}; struct UnusedImport { use_tree: ast::UseTree, use_tree_id: ast::NodeId, item_span: Span, unused: UnordSet, + use_tree_def_id: LocalDefId, } impl UnusedImport { @@ -59,7 +60,6 @@ struct UnusedImportCheckVisitor<'a, 'ra, 'tcx> { unused_imports: FxIndexMap, extern_crate_items: Vec, base_use_tree: Option<&'a ast::UseTree>, - base_id: ast::NodeId, item_span: Span, } @@ -95,14 +95,13 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // method resolution. // FIXME(#120456) - is `swap_remove` correct? self.r.maybe_unused_trait_imports.swap_remove(&def_id); - if let Some(i) = self.unused_imports.get_mut(&self.base_id) { + if let Some(i) = self.unused_imports.get_mut(&self.r.current_owner.id) { i.unused.remove(&id); } } } - fn check_use_tree(&mut self, use_tree: &'a ast::UseTree, id: ast::NodeId) { - let def_id = self.r.owner_def_id(id); + fn check_use_tree(&mut self, use_tree: &'a ast::UseTree, id: ast::NodeId, def_id: LocalDefId) { if self.r.effective_visibilities.is_exported(def_id) { self.check_import_as_underscore(use_tree, id); self.r.maybe_unused_trait_imports.swap_remove(&def_id); @@ -119,15 +118,16 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { } fn unused_import(&mut self) -> &mut UnusedImport { - let use_tree_id = self.base_id; + let use_tree_id = self.r.current_owner.id; let use_tree = self.base_use_tree.unwrap().clone(); let item_span = self.item_span; - self.unused_imports.entry(self.base_id).or_insert_with(|| UnusedImport { + self.unused_imports.entry(use_tree_id).or_insert_with(|| UnusedImport { use_tree, use_tree_id, item_span, unused: Default::default(), + use_tree_def_id: self.r.current_owner.def_id, }) } @@ -136,7 +136,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { ast::UseTreeKind::Simple(Some(ident)) => { if ident.name == kw::Underscore && !matches!( - self.r.owners[&id].import_res.type_ns, + self.r.current_owner.import_res[&id].type_ns, Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) ) { @@ -243,6 +243,12 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { } } +impl<'a, 'ra, 'tcx> AsMut> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { + self.r + } +} + impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { fn visit_item(&mut self, item: &'a ast::Item) { self.item_span = item.span_with_attributes(); @@ -254,9 +260,8 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // Use the base UseTree's NodeId as the item id // This allows the grouping of all the lints in the same item ast::ItemKind::Use(use_tree) => { - self.base_id = item.id; self.base_use_tree = Some(use_tree); - self.check_use_tree(use_tree, item.id); + self.check_use_tree(use_tree, item.id, self.r.current_owner.def_id); } &ast::ItemKind::ExternCrate(orig_name, ident) => { self.extern_crate_items.push(ExternCrateToLint { @@ -276,7 +281,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { } fn visit_use_tree_and_id(&mut self, tree: &'a ast::UseTreeAndId) { - self.check_use_tree(&tree.inner, tree.id); + self.check_use_tree(&tree.inner, tree.id, self.r.local_def_id(tree.id)); visit::walk_use_tree_and_id(self, tree); } } @@ -462,12 +467,11 @@ impl Resolver<'_, '_> { unused_imports: Default::default(), extern_crate_items: Default::default(), base_use_tree: None, - base_id: ast::DUMMY_NODE_ID, item_span: DUMMY_SP, }; // `use_items` is in crate DFS order, so diagnostics and side effects are unchanged. for item in use_items { - visitor.visit_item(item); + with_owner(&mut visitor, item.id, |visitor| visitor.visit_item(item)) } visitor.report_unused_extern_crate_items(maybe_unused_extern_crates); @@ -502,9 +506,8 @@ impl Resolver<'_, '_> { let test_module_span = if tcx.sess.is_test_crate() { None } else { - let parent_module = visitor.r.get_nearest_non_block_module( - visitor.r.owner_def_id(unused.use_tree_id).to_def_id(), - ); + let parent_module = + visitor.r.get_nearest_non_block_module(unused.use_tree_def_id.to_def_id()); match module_to_string(parent_module) { Some(module) if module == "test" diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index ee35d23691628..f3329c3d0398e 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -200,7 +200,9 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(_) => { return self.with_owner(i.id, None, DefKind::Use, i.span, |this, feed| { - this.brg_visit_item(i, feed); + this.with_parent(feed.def_id(), |this| { + this.brg_visit_item(i, feed); + }) }); } ItemKind::MacCall(..) => { diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index 335abe38d9954..3fb75e1261da8 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -109,7 +109,12 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { for (decl, eff_vis) in visitor.import_effective_visibilities.iter() { let DeclKind::Import { import, .. } = decl.kind else { unreachable!() }; if let Some(def_id) = import.def_id() { - r.effective_visibilities.update_eff_vis(def_id, eff_vis, r.tcx) + r.effective_visibilities.update_eff_vis(def_id, eff_vis, r.tcx); + let root = r.owners[&import.root_id].def_id; + // The `unreachable_pub` lint also needs to know whether any of the nested entries are + // exported by this use statement. + // FIXME: We could compute this lazily in `unreachable_pub` directly, but this is less invasive. + r.effective_visibilities.update_eff_vis(root, eff_vis, r.tcx); } if decl.ambiguity.get().is_some() && eff_vis.is_public_at_level(Level::Reexported) { exported_ambiguities.insert(*decl); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index a19207d6fbacc..938a6cb29032f 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1645,7 +1645,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // purposes it's good enough to just favor one over the other. self.per_ns_mut(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { - this.owners.get_mut(&import_id).unwrap().import_res[ns] = Some(binding.res()); + this.owners + .get_mut(&import.root_id) + .unwrap() + .import_res + .entry(import_id) + .or_default()[ns] = Some(binding.res()); } }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 7c80a892fa131..6521722f3c95d 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1675,7 +1675,12 @@ impl<'tcx> Resolver<'_, 'tcx> { /// Get the `DefId` of a child of the current owner fn local_def_id(&self, node: NodeId) -> LocalDefId { - self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) + self.opt_local_def_id(node).unwrap_or_else(|| { + panic!( + "no entry for node id `{node:?}` in owner {:?}, available: {:#?}", + self.current_owner.def_id, self.current_owner.node_id_to_def_id + ) + }) } /// Adds a definition with a parent definition. From 76f5a56f7c03898418bf837a08fe30914c4c15a4 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 13 Aug 2026 09:54:04 +0200 Subject: [PATCH 0784/1309] Stop special casing Use items in ast indexing --- compiler/rustc_ast_lowering/src/lib.rs | 61 +++------------------ compiler/rustc_middle/src/middle/resolve.rs | 3 - 2 files changed, 7 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index e6479d1e4f4bc..9121bd1accfca 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -666,28 +666,6 @@ fn index_ast<'tcx>( let item = mem::replace(item, *dummy); self.insert(item.id, node(Box::new(item))); } - - #[tracing::instrument(level = "trace", skip(self))] - fn visit_item_id_use_tree( - &mut self, - tree: &UseTree, - parent: LocalDefId, - items: &mut SmallVec<[Box; 1]>, - ) { - match tree.kind { - UseTreeKind::Glob(_) | UseTreeKind::Simple(_) => {} - UseTreeKind::Nested { items: ref nested_vec, span } => { - for nested in nested_vec { - let id = nested.id; - self.insert(id, AstOwner::NestedUseTree(parent)); - items.push(self.make_dummy(id, span, ItemKind::MacCall)); - - let def_id = self.owners[&id].def_id; - self.visit_item_id_use_tree(&nested.inner, def_id, items); - } - } - } - } } impl MutVisitor for Indexer<'_, '_> { @@ -697,37 +675,13 @@ fn index_ast<'tcx>( } fn flat_map_item(&mut self, mut item: Box) -> SmallVec<[Box; 1]> { - let def_id = self.owners[&item.id].def_id; mut_visit::walk_item(self, &mut *item); let dummy = self.make_dummy(item.id, item.span, ItemKind::MacCall); - let mut items = smallvec![dummy]; - if let ItemKind::Use(ref use_tree) = item.kind { - self.visit_item_id_use_tree(use_tree, def_id, &mut items); - } + let items = smallvec![dummy]; self.insert(item.id, AstOwner::Item(item)); items } - fn flat_map_stmt(&mut self, stmt: Stmt) -> SmallVec<[Stmt; 1]> { - let Stmt { id, span, kind } = stmt; - let mut id = Some(id); - mut_visit::walk_flat_map_stmt_kind(self, kind) - .into_iter() - .map(|kind| { - // Expanding the current statement is a nested `use` item, - // it is expanded into several flat `use` items. - // Create new NodeIds for the corresponding statements - // as two statements cannot have the same. - let id = id.take().unwrap_or_else(|| { - let next = self.next_node_id; - self.next_node_id.increment_by(1); - next - }); - Stmt { id, kind, span } - }) - .collect() - } - fn visit_assoc_item(&mut self, item: &mut AssocItem, ctxt: visit::AssocCtxt) { mut_visit::walk_assoc_item(self, item, ctxt); match ctxt { @@ -754,12 +708,12 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { let ast_index = tcx.index_ast(()); let resolver_and_node = ast_index.get(def_id).map(Steal::steal); - let fallback_to_ancestor = |parent_id| { + let fallback_to_ancestor = || { // The item did not exist in the AST, it was created while lowering another item. - // `parent_id` may be different from the direct parent of `def_id`, - // for instance use-trees are lowered by the first sibling. + + let parent_id = tcx.local_parent(def_id); let mut parent_info = tcx.lower_to_hir(parent_id); - if let hir::MaybeOwner::NonOwner(hir_id) = parent_info { + while let hir::MaybeOwner::NonOwner(hir_id) = parent_info { // `parent_id` could also not be a owner either. // For instance if `def_id` is an enum variant field, // the direct parent is the enum variant. @@ -782,7 +736,7 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { // `ast_index` does not contain all definitions, only up-to the highest // `LocalDefId` which has a non-trivial `AstOwner`. Gracefully handle // other definitions, in particular those nested inside this highest definition. - return fallback_to_ancestor(tcx.local_parent(def_id)); + return fallback_to_ancestor(); }; fn with_lctx<'hir>( @@ -816,10 +770,9 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { AstOwner::ForeignItem(item) => with_lctx(tcx, &*resolver, item.id, |lctx| { hir::OwnerNode::ForeignItem(lctx.lower_foreign_item(item)) }), - AstOwner::NestedUseTree(owner_id) => fallback_to_ancestor(*owner_id), // The item existed in the AST, but is not a HIR owner. // Fetch the correct information from its parent. - AstOwner::NonOwner => fallback_to_ancestor(tcx.local_parent(def_id)), + AstOwner::NonOwner => fallback_to_ancestor(), }; tcx.sess.time("drop_ast", || mem::drop(node)); diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs index 3bd95a132ab56..14a2743a47671 100644 --- a/compiler/rustc_middle/src/middle/resolve.rs +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -330,9 +330,6 @@ pub type DocLinkResMap = FxIndexMap<(Symbol, Namespace), Option>>; pub enum AstOwner { /// This definition does not correspond to a HIR owner. NonOwner, - /// This definition corresponds to a nested `use` tree. - /// The `LocalDefId` points to its HIR owner. - NestedUseTree(LocalDefId), Crate(Box), Item(Box), TraitItem(Box), From f8945454cf9d47533a5220fec6e9bdf5ee748350 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 5 Aug 2026 13:22:35 +0200 Subject: [PATCH 0785/1309] Make use trees in HIR be a tree again --- compiler/rustc_ast_lowering/src/index.rs | 7 + compiler/rustc_ast_lowering/src/item.rs | 103 ++----- compiler/rustc_ast_lowering/src/lib.rs | 60 ++-- compiler/rustc_hir/src/hir.rs | 43 ++- compiler/rustc_hir/src/intravisit.rs | 28 +- compiler/rustc_hir/src/lib.rs | 2 + .../rustc_hir_analysis/src/check_unused.rs | 11 +- compiler/rustc_hir_pretty/src/lib.rs | 25 +- .../src/method/prelude_edition_lints.rs | 9 +- compiler/rustc_lint/src/builtin.rs | 4 - compiler/rustc_lint/src/internal.rs | 5 +- .../src/unqualified_local_imports.rs | 2 +- compiler/rustc_middle/src/hir/map.rs | 6 +- compiler/rustc_middle/src/hir/mod.rs | 1 + compiler/rustc_middle/src/middle/privacy.rs | 4 +- .../src/thir/pattern/check_match.rs | 2 +- compiler/rustc_passes/src/check_export.rs | 16 +- compiler/rustc_passes/src/input_stats.rs | 14 +- compiler/rustc_passes/src/reachable.rs | 1 + compiler/rustc_passes/src/stability.rs | 270 ++++++++++-------- tests/ui/lint/unreachable_pub.stderr | 4 +- tests/ui/unpretty/exhaustive.hir.stdout | 4 +- 22 files changed, 316 insertions(+), 305 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index b00e98891d5e7..31aad5093591f 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -150,6 +150,13 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_body(body); } + fn visit_use(&mut self, tree: &'hir UseTree<'hir>, hir_id: HirId) { + if !hir_id.is_owner() { + self.insert(tree.prefix.span, hir_id, Node::NestedUseTree(tree)); + } + intravisit::walk_use(self, tree, hir_id); + } + fn visit_param(&mut self, param: &'hir Param<'hir>) { let node = Node::Param(param); self.insert(param.pat.span, param.hir_id, node); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 8cf7846b89194..b3198237d350e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -4,7 +4,7 @@ use rustc_ast::*; use rustc_attr_ir::target::Target; use rustc_attr_ir::{AttributeKind, EiiImplResolution, find_attr}; use rustc_errors::{E0570, ErrorGuaranteed, struct_span_code_err}; -use rustc_hir::def::{DefKind, PerNS, Res}; +use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, HirId, ImplItemImplKind, LifetimeSource, PredicateOrigin}; use rustc_middle::ty::data_structures::IndexMap; use rustc_span::def_id::{DefId, LocalDefId}; @@ -195,11 +195,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::ItemKind::ExternCrate(*orig_name, ident) } ItemKind::Use(use_tree) => { - // Start with an empty prefix. - let prefix = - Path { segments: ThinVec::new(), span: use_tree.prefix.span.shrink_to_lo() }; - - self.lower_use_tree(use_tree, &prefix, id, vis_span, attrs) + hir::ItemKind::Use(self.lower_use_tree(use_tree, id, vis_span, attrs)) } ItemKind::Static(ast::StaticItem { ident, @@ -549,13 +545,12 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_use_tree( &mut self, tree: &UseTree, - prefix: &Path, id: NodeId, vis_span: Span, attrs: &'hir [rustc_attr_ir::Attribute], - ) -> hir::ItemKind<'hir> { + ) -> hir::UseTree<'hir> { let path = &tree.prefix; - let segments = prefix.segments.iter().chain(path.segments.iter()).cloned().collect(); + let segments = path.segments.iter().cloned().collect(); match tree.kind { UseTreeKind::Simple(rename) => { @@ -577,7 +572,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = self.lower_import_res(id, path.span); let path = self.lower_use_path(res, &path, ParamMode::Explicit); let ident = self.lower_ident(ident); - hir::ItemKind::Use(path, hir::UseKind::Single(ident)) + hir::UseTree { prefix: path, kind: hir::UseKind::Single(ident) } } UseTreeKind::Glob(_) => { let res = self.expect_full_res(id); @@ -586,84 +581,24 @@ impl<'hir> LoweringContext<'_, 'hir> { let res = res.in_namespace(); let path = Path { segments, span: path.span }; let path = self.lower_use_path(res, &path, ParamMode::Explicit); - hir::ItemKind::Use(path, hir::UseKind::Glob) + hir::UseTree { prefix: path, kind: hir::UseKind::Glob } } UseTreeKind::Nested { items: ref trees, .. } => { - // Nested imports are desugared into simple imports. - // So, if we start with - // - // ``` - // pub(x) use foo::{a, b}; - // ``` - // - // we will create three items: - // - // ``` - // pub(x) use foo::a; - // pub(x) use foo::b; - // pub(x) use foo::{}; // <-- this is called the `ListStem` - // ``` - // - // The first two are produced by recursively invoking - // `lower_use_tree` (and indeed there may be things - // like `use foo::{a::{b, c}}` and so forth). They - // wind up being directly added to - // `self.items`. However, the structure of this - // function also requires us to return one item, and - // for that we return the `{}` import (called the - // `ListStem`). - - let span = prefix.span.to(path.span); - let prefix = Path { segments, span }; - - // Add all the nested `PathListItem`s to the HIR. - for use_tree in trees { + let res = self.expect_full_res(id); + let res = self.lower_res(res); + // Put the result in the appropriate namespace. + let res = res.in_namespace(); + let prefix = self.lower_use_path(res, &path, ParamMode::Explicit); + let items = self.arena.alloc_from_iter(trees.iter().map(|use_tree| { let id = use_tree.id; - let owner_id = self.owner_id(id); - - // Each `use` import is an item and thus are owners of the - // names in the path. Up to this point the nested import is - // the current owner, since we want each desugared import to - // own its own names, we have to adjust the owner before - // lowering the rest of the import. - self.with_hir_id_owner(id, |this| { - // `prefix` is lowered multiple times, but in different HIR owners. - // So each segment gets renewed `HirId` with the same - // `ItemLocalId` and the new owner. (See `lower_node_id`) - let kind = - this.lower_use_tree(&use_tree.inner, &prefix, id, vis_span, attrs); - if !attrs.is_empty() { - this.curr_owner.attrs.insert(hir::ItemLocalId::ZERO, attrs); - } - - let item = hir::Item { - owner_id, - kind, - vis_span, - span: this.lower_span(use_tree.inner.span()), - eii: find_attr!(attrs, EiiImpl(..) | EiiDeclaration(..)), - }; - hir::OwnerNode::Item(this.arena.alloc(item)) - }); - } + let hir_id = self.lower_node_id(id); + if !attrs.is_empty() { + self.curr_owner.attrs.insert(hir_id.local_id, attrs); + } + (self.lower_use_tree(&use_tree.inner, id, vis_span, attrs), hir_id) + })); - // Condition should match `build_reduced_graph_for_use_tree`. - let path = if trees.is_empty() - && !(prefix.segments.is_empty() - || prefix.segments.len() == 1 - && prefix.segments[0].ident.name == kw::PathRoot) - { - // For empty lists we need to lower the prefix so it is checked for things - // like stability later. - let res = self.lower_import_res(id, span); - self.lower_use_path(res, &prefix, ParamMode::Explicit) - } else { - // For non-empty lists we can just drop all the data, the prefix is already - // present in HIR as a part of nested imports. - let span = self.lower_span(span); - self.arena.alloc(hir::UsePath { res: PerNS::default(), segments: &[], span }) - }; - hir::ItemKind::Use(path, hir::UseKind::ListStem) + hir::UseTree { prefix, kind: hir::UseKind::Nested { items } } } } } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9121bd1accfca..d2748ad4632f1 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -54,7 +54,6 @@ use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::TaggedRef; -use rustc_data_structures::unord::ExtendUnord; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; @@ -724,7 +723,8 @@ fn lower_to_hir(tcx: TyCtxt<'_>, def_id: LocalDefId) -> hir::MaybeOwner<'_> { let parent_info = parent_info.unwrap(); *parent_info.children.get(&def_id).unwrap_or_else(|| { - panic!( + span_bug!( + tcx.source_span(def_id), "{:?} does not appear in children of {:?}", def_id, parent_info.nodes.node().def_id() @@ -881,43 +881,6 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::OwnerId { def_id: self.resolver.owners[&node].def_id } } - /// Freshen the `LoweringContext` and ready it to lower a nested item. - /// The lowered item is registered into `self.curr_owner.children`. - /// - /// This function sets up `HirId` lowering infrastructure, - /// and stashes the per-owner state to avoid pollution by the closure. - #[instrument(level = "debug", skip(self, f))] - fn with_hir_id_owner( - &mut self, - owner: NodeId, - f: impl FnOnce(&mut Self) -> hir::OwnerNode<'hir>, - ) { - let child_owner = PerOwnerLoweringState::new(self.resolver, owner); - let parent_owner = mem::replace(&mut self.curr_owner, child_owner); - - // Do not reset `next_node_id` and `node_id_to_def_id`: - // we want `f` to be able to refer to the `LocalDefId`s that the caller created. - // and the caller to refer to some of the subdefinitions' nodes' `LocalDefId`s. - - // Always allocate the first `HirId` for the owner itself. - #[cfg(debug_assertions)] - self.curr_owner - .relowering_checker - .assert_node_is_not_relowered(owner, hir::ItemLocalId::ZERO); - - let item = f(self); - let completed_child_owner = mem::replace(&mut self.curr_owner, parent_owner); - let owner_id = completed_child_owner.owner_id(); - let info = completed_child_owner.into_owner_info(self.tcx, item); - - self.curr_owner - .children - .extend_unord(info.children.items().map(|(&def_id, &info)| (def_id, info))); - - debug_assert!(!self.curr_owner.children.contains_key(&owner_id.def_id)); - self.curr_owner.children.insert(owner_id.def_id, hir::MaybeOwner::Owner(info)); - } - /// This method allocates a new `HirId` for the given `NodeId`. /// Take care not to call this method if the resulting `HirId` is then not /// actually used in the HIR, as that would trigger an assertion in the @@ -981,9 +944,22 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_import_res(&self, id: NodeId, span: Span) -> PerNS> { - debug_assert_eq!(id, self.curr_owner.owner.id); - let per_ns = - self.curr_owner.owner.import_res[&id].map(|res| res.map(|res| self.lower_res(res))); + let per_ns = self + .curr_owner + .owner + .import_res + .get(&id) + .unwrap_or_else(|| { + let sp = self.tcx.source_span(self.curr_owner.owner.def_id); + self.tcx.dcx().span_delayed_bug( + sp, + "no import_res entry for import, \ + this should only happen if it already errored in resolve", + ); + &PerNS { value_ns: None, type_ns: None, macro_ns: None } + }) + .map(|res| res.map(|res| self.lower_res(res))); + if per_ns.is_empty() { // Propagate the error to all namespaces, just to be sure. self.dcx().span_delayed_bug(span, "no resolution for an import"); diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index c8023c7721be3..1c552bd4c459e 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4073,7 +4073,31 @@ pub struct Variant<'hir> { } #[derive(Copy, Clone, Debug, StableHash)] -pub enum UseKind { +pub struct UseTree<'hir> { + pub prefix: &'hir UsePath<'hir>, + pub kind: UseKind<'hir>, +} + +impl UseTree<'_> { + pub fn resolutions(&self) -> impl Iterator>> { + Box::new(std::iter::iter!(|| { + match self.kind { + UseKind::Glob => yield self.prefix.res, + UseKind::Single(_) => yield self.prefix.res, + UseKind::Nested { items } => { + for (item, _) in items { + for res in item.resolutions() { + yield res; + } + } + } + } + })()) + } +} + +#[derive(Copy, Clone, Debug, StableHash)] +pub enum UseKind<'hir> { /// One import, e.g., `use foo::bar` or `use foo::bar as baz`. /// Also produced for each element of a list `use`, e.g. /// `use foo::{a, b}` lowers to `use foo::a; use foo::b;`. @@ -4085,10 +4109,8 @@ pub enum UseKind { /// Glob import, e.g., `use foo::*`. Glob, - /// Degenerate list import, e.g., `use foo::{a, b}` produces - /// an additional `use foo::{}` for performing checks such as - /// unstable feature gating. May be removed in the future. - ListStem, + /// `use prefix::{...}` + Nested { items: &'hir [(UseTree<'hir>, HirId)] }, } /// References to traits in impls. @@ -4267,7 +4289,7 @@ impl<'hir> Item<'hir> { expect_extern_crate, (Option, Ident), ItemKind::ExternCrate(s, ident), (*s, *ident); - expect_use, (&'hir UsePath<'hir>, UseKind), ItemKind::Use(p, uk), (p, *uk); + expect_use, UseTree<'hir>, ItemKind::Use(ut), *ut; expect_static, (Mutability, Ident, &'hir Ty<'hir>, BodyId), ItemKind::Static(mutbl, ident, ty, body), (*mutbl, *ident, ty, *body); @@ -4520,7 +4542,7 @@ pub enum ItemKind<'hir> { /// or just /// /// `use foo::bar::baz;` (with `as baz` implicitly on the right). - Use(&'hir UsePath<'hir>, UseKind), + Use(UseTree<'hir>), /// A `static` item. Static(Mutability, Ident, &'hir Ty<'hir>, BodyId), @@ -4615,7 +4637,7 @@ impl ItemKind<'_> { pub fn ident(&self) -> Option { match *self { ItemKind::ExternCrate(_, ident) - | ItemKind::Use(_, UseKind::Single(ident)) + | ItemKind::Use(UseTree { kind: UseKind::Single(ident), .. }) | ItemKind::Static(_, ident, ..) | ItemKind::Const(ident, ..) | ItemKind::Fn { ident, .. } @@ -4628,7 +4650,7 @@ impl ItemKind<'_> { | ItemKind::Trait { ident, .. } | ItemKind::TraitAlias(_, ident, ..) => Some(ident), - ItemKind::Use(_, UseKind::Glob | UseKind::ListStem) + ItemKind::Use(UseTree { kind: UseKind::Glob | UseKind::Nested { .. }, .. }) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } | ItemKind::Impl(_) @@ -4885,6 +4907,7 @@ impl<'hir> From> for Node<'hir> { pub enum Node<'hir> { Param(&'hir Param<'hir>), Item(&'hir Item<'hir>), + NestedUseTree(&'hir UseTree<'hir>), ForeignItem(&'hir ForeignItem<'hir>), TraitItem(&'hir TraitItem<'hir>), ImplItem(&'hir ImplItem<'hir>), @@ -4950,6 +4973,7 @@ impl<'hir> Node<'hir> { Node::TraitItem(TraitItem { ident, .. }) | Node::ImplItem(ImplItem { ident, .. }) | Node::ForeignItem(ForeignItem { ident, .. }) + | Node::NestedUseTree(UseTree { kind: UseKind::Single(ident), .. }) | Node::Field(FieldDef { ident, .. }) | Node::Variant(Variant { ident, .. }) | Node::PathSegment(PathSegment { ident, .. }) => Some(*ident), @@ -4977,6 +5001,7 @@ impl<'hir> Node<'hir> { | Node::Ty(..) | Node::TraitRef(..) | Node::OpaqueTy(..) + | Node::NestedUseTree(_) | Node::Infer(..) | Node::WherePredicate(..) | Node::TestBinderForall(..) diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index fc8324fb443f8..afe08288ccc7e 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -421,8 +421,8 @@ pub trait Visitor<'v>: Sized { ) -> Self::Result { walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, path: &'v UsePath<'v>, hir_id: HirId) -> Self::Result { - walk_use(self, path, hir_id) + fn visit_use(&mut self, tree: &'v UseTree<'v>, hir_id: HirId) -> Self::Result { + walk_use(self, tree, hir_id) } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result { walk_trait_item(self, ti) @@ -550,12 +550,8 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: visit_opt!(visitor, visit_name, orig_name); try_visit!(visitor.visit_ident(ident)); } - ItemKind::Use(ref path, kind) => { - try_visit!(visitor.visit_use(path, item.hir_id())); - match kind { - UseKind::Single(ident) => try_visit!(visitor.visit_ident(ident)), - UseKind::Glob | UseKind::ListStem => {} - } + ItemKind::Use(ref tree) => { + try_visit!(visitor.visit_use(tree, item.hir_id())); } ItemKind::Static(_, ident, ref typ, body) => { try_visit!(visitor.visit_ident(ident)); @@ -1268,13 +1264,25 @@ pub fn walk_fn_kind<'v, V: Visitor<'v>>(visitor: &mut V, function_kind: FnKind<' pub fn walk_use<'v, V: Visitor<'v>>( visitor: &mut V, - path: &'v UsePath<'v>, + tree: &'v UseTree<'v>, hir_id: HirId, ) -> V::Result { - let UsePath { segments, ref res, span } = *path; + visitor.visit_id(hir_id); + let UseTree { prefix, kind } = *tree; + let UsePath { segments, ref res, span } = *prefix; for res in res.present_items() { try_visit!(visitor.visit_path(&Path { segments, res, span }, hir_id)); } + + match kind { + UseKind::Single(ident) => try_visit!(visitor.visit_ident(ident)), + UseKind::Glob => {} + UseKind::Nested { items } => { + for (tree, id) in items { + try_visit!(visitor.visit_use(tree, *id)); + } + } + } V::Result::output() } diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 5a23d23e4f622..40c907efcfeb0 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -12,6 +12,8 @@ #![feature(derive_const)] #![feature(exhaustive_patterns)] #![feature(final_associated_functions)] +#![feature(iter_macro)] +#![feature(yield_expr)] #![recursion_limit = "256"] // tidy-alphabetical-end diff --git a/compiler/rustc_hir_analysis/src/check_unused.rs b/compiler/rustc_hir_analysis/src/check_unused.rs index f6be7a27cc8cf..d8dafd509cf24 100644 --- a/compiler/rustc_hir_analysis/src/check_unused.rs +++ b/compiler/rustc_hir_analysis/src/check_unused.rs @@ -44,16 +44,15 @@ pub(super) fn check_unused_traits(tcx: TyCtxt<'_>, (): ()) { if used_trait_imports.contains(&id) { continue; } - let item = tcx.hir_expect_item(id); - if item.span.is_dummy() { + let span = tcx.def_span(id); + if span.is_dummy() { continue; } - let (path, _) = item.expect_use(); tcx.emit_node_span_lint( UNUSED_IMPORTS, - item.hir_id(), - path.span, - UnusedImport { tcx, span: path.span }, + tcx.local_def_id_to_hir_id(id), + span, + UnusedImport { tcx, span }, ); } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 2ff977628a16e..39bed2d2e2ae4 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -215,6 +215,7 @@ impl<'a> State<'a> { Node::LetStmt(a) => self.print_local_decl(a), Node::Crate(..) => panic!("cannot print Crate"), Node::WherePredicate(pred) => self.print_where_predicate(pred), + Node::NestedUseTree(tree) => self.print_use_tree(tree), Node::TestBinderForall(_) => panic!("cannot print Node::TestBinderForall"), Node::TestBinderExists(_) => panic!("cannot print Node::TestBinderExists"), Node::TestBinderBoundTypeConstraint(_) => { @@ -608,11 +609,11 @@ impl<'a> State<'a> { self.end(ib); self.end(cb); } - hir::ItemKind::Use(path, kind) => { + hir::ItemKind::Use(ref tree) => { let (cb, ib) = self.head("use"); - self.print_path(path, false); - self.print_use_kind(path, kind); + self.print_use_tree(tree); + self.word(";"); self.end(ib); self.end(cb); } @@ -807,18 +808,26 @@ impl<'a> State<'a> { self.ann.post(self, AnnNode::Item(item)) } - fn print_use_kind(&mut self, path: &hir::UsePath<'_>, kind: hir::UseKind) { + fn print_use_tree(&mut self, tree: &hir::UseTree<'_>) { + let hir::UseTree { prefix, kind } = *tree; + self.print_path(prefix, false); match kind { hir::UseKind::Single(ident) => { - if path.segments.last().unwrap().ident != ident { + if tree.prefix.segments.last().unwrap().ident != ident { self.space(); self.word_space("as"); self.print_ident(ident); } - self.word(";"); } - hir::UseKind::Glob => self.word("::*;"), - hir::UseKind::ListStem => self.word("::{};"), + hir::UseKind::Glob => self.word("::*"), + hir::UseKind::Nested { items } => { + self.word("::{"); + for (item, _) in items { + self.print_use_tree(item); + self.word(","); + } + self.word("}"); + } } } diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index 4587e9726a9d7..ed61d557385dd 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -441,23 +441,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Find an identifier with which this trait was imported (note that `_` doesn't count). for item in import_items.iter() { - let (_, kind) = item.expect_use(); - match kind { + match item.expect_use().kind { hir::UseKind::Single(ident) => { if ident.name != kw::Underscore { return Some(format!("{}", ident.name)); } } hir::UseKind::Glob => return None, // Glob import, so just use its name. - hir::UseKind::ListStem => unreachable!(), + hir::UseKind::Nested { .. } => unreachable!(), } } // All that is left is `_`! We need to use the full path. It doesn't matter which one we // pick, so just take the first one. match import_items[0].kind { - ItemKind::Use(path, _) => { - Some(join_path_idents(path.segments.iter().map(|seg| seg.ident))) + ItemKind::Use(tree) => { + Some(join_path_idents(tree.prefix.segments.iter().map(|seg| seg.ident))) } _ => { span_bug!(span, "unexpected item kind, expected a use: {:?}", import_items[0].kind); diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index bf92b0a0c55d3..69ac09e650c16 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -1188,10 +1188,6 @@ impl UnreachablePub { impl<'tcx> LateLintPass<'tcx> for UnreachablePub { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { - // Do not warn for fake `use` statements. - if let hir::ItemKind::Use(_, hir::UseKind::ListStem) = &item.kind { - return; - } self.perform_lint(cx, "item", item.owner_id.def_id, item.vis_span, true); } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 2646131bb59cd..3185a8ed8c6e2 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -42,6 +42,7 @@ impl LateLintPass<'_> for DefaultHashTypes { if matches!( cx.tcx.hir_node(hir_id), hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(..), .. }) + | hir::Node::NestedUseTree(_) ) { // Don't lint imports, only actual usages. return; @@ -408,7 +409,9 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let rustc_hir::ItemKind::Use(path, kind) = item.kind else { return }; + let rustc_hir::ItemKind::Use(hir::UseTree { prefix: path, kind }) = item.kind else { + return; + }; let is_mod_inherent = |res: Res| { res.opt_def_id() diff --git a/compiler/rustc_lint/src/unqualified_local_imports.rs b/compiler/rustc_lint/src/unqualified_local_imports.rs index 0bfca85b59b34..73fecba6d02f2 100644 --- a/compiler/rustc_lint/src/unqualified_local_imports.rs +++ b/compiler/rustc_lint/src/unqualified_local_imports.rs @@ -45,7 +45,7 @@ declare_lint_pass!(UnqualifiedLocalImports => [UNQUALIFIED_LOCAL_IMPORTS]); impl<'tcx> LateLintPass<'tcx> for UnqualifiedLocalImports { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let hir::ItemKind::Use(path, _kind) = item.kind else { return }; + let hir::ItemKind::Use(hir::UseTree { prefix: path, .. }) = item.kind else { return }; // Check the type and value namespace resolutions for a local crate. let is_local_import = matches!( path.res.type_ns, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 664c85980addd..6b31decf3b19b 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -793,6 +793,7 @@ impl<'tcx> TyCtxt<'tcx> { } Node::Crate(..) => String::from("(root_crate)"), Node::WherePredicate(_) => node_str("where predicate"), + Node::NestedUseTree(_) => node_str("use"), Node::PreciseCapturingNonLifetimeArg(_param) => node_str("parameter"), Node::TestBinderForall(_) => node_str("forall"), Node::TestBinderExists(_) => node_str("exists"), @@ -1000,10 +1001,10 @@ impl<'tcx> TyCtxt<'tcx> { } // Other cases. Node::Item(item) => match &item.kind { - ItemKind::Use(path, _) => { + ItemKind::Use(use_tree) => { // Ensure that the returned span has the item's SyntaxContext, and not the // SyntaxContext of the path. - path.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span) + use_tree.prefix.span.find_ancestor_in_same_ctxt(item.span).unwrap_or(item.span) } _ => { if let Some(ident) = item.kind.ident() { @@ -1072,6 +1073,7 @@ impl<'tcx> TyCtxt<'tcx> { Node::Crate(item) => item.spans.inner_span, Node::WherePredicate(pred) => pred.span, Node::PreciseCapturingNonLifetimeArg(param) => param.ident.span, + Node::NestedUseTree(tree) => tree.prefix.span, Node::TestBinderForall(forall) => forall.span, Node::TestBinderExists(exists) => exists.span, Node::TestBinderBoundTypeConstraint(bound_type) => bound_type.span, diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index d899ba0190f00..02865e81c4c69 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -344,6 +344,7 @@ impl<'tcx> TyCtxt<'tcx> { | Node::Synthetic | Node::Err(_) | Node::Ctor(_) + | Node::NestedUseTree(_) | Node::Lifetime(_) | Node::GenericParam(_) | Node::Crate(_) diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index a59e690541bc4..9685ac89011e5 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -8,7 +8,7 @@ use std::hash::Hash; use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; use rustc_hir::def::DefKind; -use rustc_hir::{ItemKind, Node, UseKind}; +use rustc_hir::{ItemKind, Node, UseKind, UseTree}; use rustc_macros::StableHash; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_span::span_bug; @@ -189,7 +189,7 @@ impl EffectiveVisibilities { let nominal_vis = tcx.visibility(def_id); if ev.reachable.greater_than(nominal_vis, tcx) { if let Node::Item(item) = tcx.hir_node_by_def_id(def_id) - && let ItemKind::Use(_, UseKind::Glob) = item.kind + && let ItemKind::Use(UseTree { kind: UseKind::Glob, .. }) = item.kind { // Glob import visibilities can be increased by other // more public glob imports in cases of ambiguity. diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 381ebdcc15037..52de3f094e15b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -1065,7 +1065,7 @@ fn find_fallback_pattern_typo<'tcx>( if let DefKind::Use = cx.tcx.def_kind(item.owner_id) { // Look for consts being re-exported. let item = cx.tcx.hir_expect_item(item.owner_id.def_id); - let hir::ItemKind::Use(path, _) = item.kind else { + let hir::ItemKind::Use(hir::UseTree { prefix: path, .. }) = item.kind else { continue; }; if let Some(value_ns) = path.res.value_ns diff --git a/compiler/rustc_passes/src/check_export.rs b/compiler/rustc_passes/src/check_export.rs index 15a1084686718..dbb6d4b72d432 100644 --- a/compiler/rustc_passes/src/check_export.rs +++ b/compiler/rustc_passes/src/check_export.rs @@ -132,13 +132,15 @@ impl<'tcx> Visitor<'tcx> for ExportableItemCollector<'tcx> { | hir::ItemKind::TyAlias(..) => { self.add_exportable(def_id); } - hir::ItemKind::Use(path, _) => { - for res in path.res.present_items() { - // Only local items are exportable. - if let Some(res_id) = res.opt_def_id() - && let Some(res_id) = res_id.as_local() - { - self.add_exportable(res_id); + hir::ItemKind::Use(tree) => { + for res in tree.resolutions() { + for res in res.present_items() { + // Only local items are exportable. + if let Some(res_id) = res.opt_def_id() + && let Some(res_id) = res_id.as_local() + { + self.add_exportable(res_id); + } } } } diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index d47acf230ffe4..cb034da7b26bc 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -448,16 +448,24 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, p: &'v hir::UsePath<'v>, _hir_id: HirId) { + fn visit_use(&mut self, tree: &'v hir::UseTree<'v>, _hir_id: HirId) { // This is `visit_use`, but the type is `Path` so record it that way. - self.record("Path", None, p); + self.record("Path", None, tree); // Don't call `hir_visit::walk_use(self, p, hir_id)`: it calls // `visit_path` up to three times, once for each namespace result in // `p.res`, by building temporary `Path`s that are not part of the real // HIR, which causes `p` to be double- or triple-counted. Instead just // walk the path internals (i.e. the segments) directly. - let hir::Path { span: _, res: _, segments } = *p; + let hir::Path { span: _, res: _, segments } = *tree.prefix; ast_visit::walk_list!(self, visit_path_segment, segments); + match tree.kind { + hir::UseKind::Single(_) | hir::UseKind::Glob => {} + hir::UseKind::Nested { items } => { + for (tree, id) in items { + self.visit_use(tree, *id); + } + } + } } fn visit_trait_item(&mut self, ti: &'v hir::TraitItem<'v>) { diff --git a/compiler/rustc_passes/src/reachable.rs b/compiler/rustc_passes/src/reachable.rs index 30881ddf8f4a9..1bd2ca7792e7e 100644 --- a/compiler/rustc_passes/src/reachable.rs +++ b/compiler/rustc_passes/src/reachable.rs @@ -301,6 +301,7 @@ impl<'tcx> ReachableContext<'tcx> { | Node::Field(_) | Node::Ty(_) | Node::Crate(_) + | Node::NestedUseTree(_) | Node::Synthetic | Node::OpaqueTy(..) => {} _ => { diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index a442d655fb124..f0bdf91445c1f 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::{ExtendUnord, UnordMap, UnordSet}; use rustc_feature::{EnabledLangFeature, EnabledLibFeature, UNSTABLE_LANG_FEATURES}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId, LocalModId}; +use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalModId}; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ self as hir, AmbigArg, Constness, FieldDef, HirId, Item, ItemKind, Path, TraitRef, Ty, TyKind, @@ -730,20 +730,6 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { self.tcx.check_stability(def_id, Some(item.hir_id()), item.span, None); } - hir::ItemKind::Use(path, hir::UseKind::Single(_)) - if self.tcx.features().staged_api() - && self.tcx.local_visibility(item.owner_id.def_id).is_public() => - { - self.check_single_unstable_reexport(item.hir_id(), path); - } - - hir::ItemKind::Use(path, hir::UseKind::Glob) - if self.tcx.features().staged_api() - && self.tcx.local_visibility(item.owner_id.def_id).is_public() => - { - self.check_glob_unstable_reexport(item.hir_id(), item.owner_id.def_id, path); - } - // For implementations of traits, check the stability of each item // individually as it's possible to have a stable trait with unstable // items. @@ -905,36 +891,81 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { intravisit::walk_poly_trait_ref(self, t); } - fn visit_use(&mut self, path: &'tcx UsePath<'tcx>, hir_id: HirId) { - let res = path.res; - - // A use item can import something from two namespaces at the same time. - // For deprecation/stability we don't want to warn twice. - // This specifically happens with constructors for unit/tuple structs. - if let Some(ty_ns_res) = res.type_ns - && let Some(value_ns_res) = res.value_ns - && let Some(type_ns_did) = ty_ns_res.opt_def_id() - && let Some(value_ns_did) = value_ns_res.opt_def_id() - && let DefKind::Ctor(.., _) = self.tcx.def_kind(value_ns_did) - && self.tcx.parent(value_ns_did) == type_ns_did - { - // Only visit the value namespace path when we've detected a duplicate, - // not the type namespace path. - let UsePath { segments, res: _, span } = *path; - self.visit_path(&Path { segments, res: value_ns_res, span }, hir_id); - - // Though, visit the macro namespace if it exists, - // regardless of the checks above relating to constructors. - if let Some(res) = res.macro_ns { - self.visit_path(&Path { segments, res, span }, hir_id); + fn visit_use(&mut self, tree: &'tcx hir::UseTree<'tcx>, hir_id: HirId) { + let mut v = vec![]; + + #[instrument(skip(visitor))] + fn recurse<'tcx>( + visitor: &mut Checker<'tcx>, + tree: &'tcx hir::UseTree<'tcx>, + hir_id: HirId, + stack: &mut Vec<&'tcx [hir::PathSegment<'tcx>]>, + ) { + let UsePath { segments, res, span } = *tree.prefix; + + match tree.kind { + hir::UseKind::Single(_) | hir::UseKind::Glob => { + if visitor.tcx.features().staged_api() + && visitor.tcx.local_visibility(def_id).is_public() + { + if let hir::UseKind::Single(_) = tree.kind { + visitor.check_single_unstable_reexport(hir_id, tree.prefix); + } else { + visitor.check_glob_unstable_reexport(hir_id, def_id, tree.prefix); + } + } + // A use item can import something from two namespaces at the same time. + // For deprecation/stability we don't want to warn twice. + // This specifically happens with constructors for unit/tuple structs. + if let Some(res) = res.value_ns.or(res.type_ns) { + visitor.check_path(&Path { segments, res, span }, hir_id, stack); + } + + // Though, visit the macro namespace if it exists, + // regardless of the checks above relating to constructors. + if let Some(res) = res.macro_ns { + visitor.check_path(&Path { segments, res, span }, hir_id, stack); + } + } + hir::UseKind::Nested { items } => { + stack.push(tree.prefix.segments); + if items.is_empty() { + // need to handle `use foo::bar::{};` + visitor.check_path( + &Path { + segments, + res: segments.last().map_or(Res::Err, |seg| seg.res), + span, + }, + hir_id, + stack, + ); + } else { + for (tree, id) in items { + recurse(visitor, tree, *id, stack); + } + } + stack.pop(); + } } - } else { - // if there's no duplicate, just walk as normal - intravisit::walk_use(self, path, hir_id) } + recurse(self, tree, hir_id, &mut v); } fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) { + self.check_path(path, id, &[]); + + intravisit::walk_path(self, path) + } +} + +impl<'tcx> Checker<'tcx> { + fn check_path( + &mut self, + path: &hir::Path<'tcx>, + id: hir::HirId, + prefix: &[&[hir::PathSegment<'tcx>]], + ) { if let Some(def_id) = path.res.opt_def_id() { let method_span = path.segments.last().map(|s| s.ident.span); let item_is_allowed = self.tcx.check_stability_allow_unstable( @@ -951,15 +982,31 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { if item_is_allowed { // The item itself is allowed; check whether the path there is also allowed. - self.check_path_segments(path, id, method_span, def_id); + let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = + self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { + StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { + allowed_through_unstable_modules + } + _ => None, + }); + let segments = prefix + .into_iter() + .flat_map(|i| i.into_iter()) + .chain(path.segments.iter().rev().skip(1).rev()); + let intrinsics_module = segments.clone().last(); + for segment in segments { + self.check_path_segments( + path.span, + segment, + intrinsics_module, + id, + method_span, + is_allowed_through_unstable_modules, + ); + } } } - - intravisit::walk_path(self, path) } -} - -impl<'tcx> Checker<'tcx> { /// Check parent modules stability as well if the item the path refers to is itself /// stable. We only emit errors for unstable path segments if the item is stable /// or allowed because stability is often inherited, so the most common case is that @@ -973,76 +1020,69 @@ impl<'tcx> Checker<'tcx> { /// added, such as `core::intrinsics::transmute` fn check_path_segments( &mut self, - path: &Path<'tcx>, + span: Span, + path_segment: &hir::PathSegment<'_>, + intrinsics_module: Option<&hir::PathSegment<'_>>, id: HirId, method_span: Option, - def_id: DefId, + is_allowed_through_unstable_modules: Option<(Symbol, Symbol)>, ) { - let is_allowed_through_unstable_modules: Option<(Symbol, Symbol)> = - self.tcx.lookup_stability(def_id).and_then(|stab| match stab.level { - StabilityLevel::Stable { allowed_through_unstable_modules, .. } => { - allowed_through_unstable_modules - } - _ => None, - }); + // The item itself is allowed; check whether the path there is also allowed. - let parents = path.segments.iter().rev().skip(1); - for path_segment in parents { - if let Some(def_id) = path_segment.res.opt_def_id() { - match is_allowed_through_unstable_modules { - None => { - // Emit a hard stability error if this path is not stable. + if let Some(def_id) = path_segment.res.opt_def_id() { + match is_allowed_through_unstable_modules { + None => { + // Emit a hard stability error if this path is not stable. - // use `None` for id to prevent deprecation check - self.tcx.check_stability_allow_unstable( - def_id, - None, - path_segment.ident.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, - ); - } - Some((message, suggestion)) => { - // Call the stability check directly so that we can control which - // diagnostic is emitted. - let eval_result = self.tcx.eval_stability_allow_unstable( - def_id, - None, - path.span, - None, - if is_unstable_reexport(self.tcx, id) { - AllowUnstable::Yes - } else { - AllowUnstable::No - }, + // use `None` for id to prevent deprecation check + self.tcx.check_stability_allow_unstable( + def_id, + None, + path_segment.ident.span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, + ); + } + Some((message, suggestion)) => { + // Call the stability check directly so that we can control which + // diagnostic is emitted. + let eval_result = self.tcx.eval_stability_allow_unstable( + def_id, + None, + span, + None, + if is_unstable_reexport(self.tcx, id) { + AllowUnstable::Yes + } else { + AllowUnstable::No + }, + ); + let is_allowed = matches!(eval_result, EvalResult::Allow); + if !is_allowed { + // Show a deprecation message. + let intrinsics_module = intrinsics_module.unwrap_or_else(|| { + span_bug!( + span, + "no module for `is_allowed_through_unstable_modules` intrinsic {path_segment:?}" + ) + }); + let diag = diagnostics::RustcAtumSuggestion { + message, + import_span: span, + unstable_mod_span: { intrinsics_module.ident.span }, + module: intrinsics_module.ident, + suggestion, + }; + self.tcx.emit_node_span_lint( + DEPRECATED, + id, + method_span.unwrap_or(span), + diag, ); - let is_allowed = matches!(eval_result, EvalResult::Allow); - if !is_allowed { - // Show a deprecation message. - let [.., intrinsics_module, _intrinsic] = path.segments else { - span_bug!( - path.span, - "no module for `is_allowed_through_unstable_modules` intrinsic {path:?}" - ) - }; - let diag = diagnostics::RustcAtumSuggestion { - message, - import_span: path.span, - unstable_mod_span: { intrinsics_module.ident.span }, - module: intrinsics_module.ident, - suggestion, - }; - self.tcx.emit_node_span_lint( - DEPRECATED, - id, - method_span.unwrap_or(path.span), - diag, - ); - } } } } @@ -1055,10 +1095,7 @@ impl<'tcx> Checker<'tcx> { /// See issue #94972 for details on why this is a special case fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { // Get the LocalDefId so we can lookup the item to check the kind. - let Some(owner) = id.as_owner() else { - return false; - }; - let def_id = owner.def_id; + let def_id = id.owner.def_id; let Some(stab) = tcx.lookup_stability(def_id) else { return false; @@ -1070,7 +1107,10 @@ fn is_unstable_reexport(tcx: TyCtxt<'_>, id: hir::HirId) -> bool { } // If this is a path that isn't a use, we don't need to do anything special - if !matches!(tcx.hir_expect_item(def_id).kind, ItemKind::Use(..)) { + if !matches!( + tcx.hir_node(id), + hir::Node::Item(hir::Item { kind: ItemKind::Use(..), .. }) | hir::Node::NestedUseTree(_) + ) { return false; } diff --git a/tests/ui/lint/unreachable_pub.stderr b/tests/ui/lint/unreachable_pub.stderr index 34b48a1fbb5b0..aba13f624288d 100644 --- a/tests/ui/lint/unreachable_pub.stderr +++ b/tests/ui/lint/unreachable_pub.stderr @@ -14,10 +14,10 @@ LL | #![warn(unreachable_pub)] | ^^^^^^^^^^^^^^^ warning: unreachable `pub` item - --> $DIR/unreachable_pub.rs:11:24 + --> $DIR/unreachable_pub.rs:11:13 | LL | pub use std::env::{Args}; // braced-use has different item spans than unbraced - | --- ^^^^ + | --- ^^^^^^^^ | | | help: consider restricting its visibility: `pub(crate)` | diff --git a/tests/ui/unpretty/exhaustive.hir.stdout b/tests/ui/unpretty/exhaustive.hir.stdout index 1b18e00c951c8..025314709cf6c 100644 --- a/tests/ui/unpretty/exhaustive.hir.stdout +++ b/tests/ui/unpretty/exhaustive.hir.stdout @@ -403,9 +403,7 @@ mod items { } /// ItemKind::Use mod item_use { - use ::{}; - use crate::expressions; - use crate::items::item_use; + use crate::{expressions,items::item_use,}; use core::*; } /// ItemKind::Static From 59e1fa5500748784b1ea0866e750e19ceee30578 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 18 Aug 2026 11:14:42 +0200 Subject: [PATCH 0786/1309] Preserve nested use tree DefIds to HIR --- compiler/rustc_ast_lowering/src/index.rs | 2 +- compiler/rustc_ast_lowering/src/item.rs | 3 +- compiler/rustc_hir/src/hir.rs | 4 +- compiler/rustc_hir/src/intravisit.rs | 13 ++- compiler/rustc_hir_pretty/src/lib.rs | 2 +- compiler/rustc_lint/src/internal.rs | 104 ++++++++++++++--------- compiler/rustc_passes/src/input_stats.rs | 6 +- compiler/rustc_passes/src/stability.rs | 9 +- src/librustdoc/visit_ast.rs | 2 +- 9 files changed, 89 insertions(+), 56 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs index 31aad5093591f..3795673d53ba1 100644 --- a/compiler/rustc_ast_lowering/src/index.rs +++ b/compiler/rustc_ast_lowering/src/index.rs @@ -150,7 +150,7 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> { self.visit_body(body); } - fn visit_use(&mut self, tree: &'hir UseTree<'hir>, hir_id: HirId) { + fn visit_use(&mut self, tree: &'hir UseTree<'hir>, hir_id: HirId, _def_id: LocalDefId) { if !hir_id.is_owner() { self.insert(tree.prefix.span, hir_id, Node::NestedUseTree(tree)); } diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b3198237d350e..6ec5903c5fb3b 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -592,10 +592,11 @@ impl<'hir> LoweringContext<'_, 'hir> { let items = self.arena.alloc_from_iter(trees.iter().map(|use_tree| { let id = use_tree.id; let hir_id = self.lower_node_id(id); + let def_id = self.curr_owner.owner.node_id_to_def_id[&id]; if !attrs.is_empty() { self.curr_owner.attrs.insert(hir_id.local_id, attrs); } - (self.lower_use_tree(&use_tree.inner, id, vis_span, attrs), hir_id) + (self.lower_use_tree(&use_tree.inner, id, vis_span, attrs), hir_id, def_id) })); hir::UseTree { prefix, kind: hir::UseKind::Nested { items } } diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 1c552bd4c459e..96af15b29b807 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -4085,7 +4085,7 @@ impl UseTree<'_> { UseKind::Glob => yield self.prefix.res, UseKind::Single(_) => yield self.prefix.res, UseKind::Nested { items } => { - for (item, _) in items { + for (item, _, _) in items { for res in item.resolutions() { yield res; } @@ -4110,7 +4110,7 @@ pub enum UseKind<'hir> { Glob, /// `use prefix::{...}` - Nested { items: &'hir [(UseTree<'hir>, HirId)] }, + Nested { items: &'hir [(UseTree<'hir>, HirId, LocalDefId)] }, } /// References to traits in impls. diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index afe08288ccc7e..5b7555cd73938 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -421,7 +421,12 @@ pub trait Visitor<'v>: Sized { ) -> Self::Result { walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, tree: &'v UseTree<'v>, hir_id: HirId) -> Self::Result { + fn visit_use( + &mut self, + tree: &'v UseTree<'v>, + hir_id: HirId, + _def_id: LocalDefId, + ) -> Self::Result { walk_use(self, tree, hir_id) } fn visit_trait_item(&mut self, ti: &'v TraitItem<'v>) -> Self::Result { @@ -551,7 +556,7 @@ pub fn walk_item<'v, V: Visitor<'v>>(visitor: &mut V, item: &'v Item<'v>) -> V:: try_visit!(visitor.visit_ident(ident)); } ItemKind::Use(ref tree) => { - try_visit!(visitor.visit_use(tree, item.hir_id())); + try_visit!(visitor.visit_use(tree, item.hir_id(), item.owner_id.def_id)); } ItemKind::Static(_, ident, ref typ, body) => { try_visit!(visitor.visit_ident(ident)); @@ -1278,8 +1283,8 @@ pub fn walk_use<'v, V: Visitor<'v>>( UseKind::Single(ident) => try_visit!(visitor.visit_ident(ident)), UseKind::Glob => {} UseKind::Nested { items } => { - for (tree, id) in items { - try_visit!(visitor.visit_use(tree, *id)); + for (tree, id, def_id) in items { + try_visit!(visitor.visit_use(tree, *id, *def_id)); } } } diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index 39bed2d2e2ae4..ea2735a2a70c0 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -822,7 +822,7 @@ impl<'a> State<'a> { hir::UseKind::Glob => self.word("::*"), hir::UseKind::Nested { items } => { self.word("::{"); - for (item, _) in items { + for (item, _, _) in items { self.print_use_tree(item); self.word(","); } diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index 3185a8ed8c6e2..b36326b86ac9a 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -409,53 +409,79 @@ impl<'tcx> LateLintPass<'tcx> for TypeIr { } fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx hir::Item<'tcx>) { - let rustc_hir::ItemKind::Use(hir::UseTree { prefix: path, kind }) = item.kind else { + let rustc_hir::ItemKind::Use(tree) = item.kind else { return; }; - let is_mod_inherent = |res: Res| { - res.opt_def_id() - .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id)) - }; + check_use(cx, tree, vec![]); - // Path segments except for the final. - if let Some(seg) = path.segments.iter().find(|seg| is_mod_inherent(seg.res)) { - cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage); - } - // Final path resolutions, like `use rustc_type_ir::inherent` - else if let Some(type_ns) = path.res.type_ns - && is_mod_inherent(type_ns) - { - cx.emit_span_lint( - USAGE_OF_TYPE_IR_INHERENT, - path.segments.last().unwrap().ident.span, - TypeIrInherentUsage, - ); - } + fn check_use<'tcx>( + cx: &LateContext<'_>, + tree: hir::UseTree<'tcx>, + mut prefix: Vec<&'tcx hir::PathSegment<'tcx>>, + ) { + let is_mod_inherent = |res: Res| { + res.opt_def_id() + .is_some_and(|def_id| cx.tcx.is_diagnostic_item(sym::type_ir_inherent, def_id)) + }; + + prefix.extend(tree.prefix.segments); + + match tree.kind { + rustc_hir::UseKind::Single(_) | rustc_hir::UseKind::Glob => {} + rustc_hir::UseKind::Nested { items } => { + for (nested, _, _) in items { + check_use(cx, *nested, prefix.clone()) + } + } + } - let (lo, hi, snippet) = match path.segments { - [.., penultimate, segment] if is_mod_inherent(penultimate.res) => { - (segment.ident.span, item.kind.ident().unwrap().span, "*") + // Path segments except for the final. + if let Some(seg) = prefix.iter().find(|seg| is_mod_inherent(seg.res)) { + cx.emit_span_lint(USAGE_OF_TYPE_IR_INHERENT, seg.ident.span, TypeIrInherentUsage); } - [.., segment] - if let Some(type_ns) = path.res.type_ns - && is_mod_inherent(type_ns) - && let rustc_hir::UseKind::Single(ident) = kind => + // Final path resolutions, like `use rustc_type_ir::inherent` + else if let Some(type_ns) = tree.prefix.res.type_ns + && is_mod_inherent(type_ns) { - let (lo, snippet) = - match cx.tcx.sess.source_map().span_to_snippet(path.span).as_deref() { - Ok("self") => (path.span, "*"), - _ => (segment.ident.span.shrink_to_hi(), "::*"), - }; - (lo, if segment.ident == ident { lo } else { ident.span }, snippet) + cx.emit_span_lint( + USAGE_OF_TYPE_IR_INHERENT, + prefix.last().unwrap().ident.span, + TypeIrInherentUsage, + ); } - _ => return, - }; - cx.emit_span_lint( - NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, - path.span, - NonGlobImportTypeIrInherent { suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), snippet }, - ); + + let (lo, hi, snippet) = match prefix { + [.., penultimate, segment] + if is_mod_inherent(penultimate.res) + && let rustc_hir::UseKind::Single(ident) = tree.kind => + { + (segment.ident.span, ident.span, "*") + } + [.., segment] + if let Some(type_ns) = tree.prefix.res.type_ns + && is_mod_inherent(type_ns) + && let rustc_hir::UseKind::Single(ident) = tree.kind => + { + let (lo, snippet) = + match cx.tcx.sess.source_map().span_to_snippet(tree.prefix.span).as_deref() + { + Ok("self") => (tree.prefix.span, "*"), + _ => (segment.ident.span.shrink_to_hi(), "::*"), + }; + (lo, if segment.ident == ident { lo } else { ident.span }, snippet) + } + _ => return, + }; + cx.emit_span_lint( + NON_GLOB_IMPORT_OF_TYPE_IR_INHERENT, + tree.prefix.span, + NonGlobImportTypeIrInherent { + suggestion: lo.eq_ctxt(hi).then(|| lo.to(hi)), + snippet, + }, + ); + } } fn check_path( diff --git a/compiler/rustc_passes/src/input_stats.rs b/compiler/rustc_passes/src/input_stats.rs index cb034da7b26bc..d8524efb35bc2 100644 --- a/compiler/rustc_passes/src/input_stats.rs +++ b/compiler/rustc_passes/src/input_stats.rs @@ -448,7 +448,7 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { hir_visit::walk_fn(self, fk, fd, b, id) } - fn visit_use(&mut self, tree: &'v hir::UseTree<'v>, _hir_id: HirId) { + fn visit_use(&mut self, tree: &'v hir::UseTree<'v>, _hir_id: HirId, _def_id: LocalDefId) { // This is `visit_use`, but the type is `Path` so record it that way. self.record("Path", None, tree); // Don't call `hir_visit::walk_use(self, p, hir_id)`: it calls @@ -461,8 +461,8 @@ impl<'v> hir_visit::Visitor<'v> for StatCollector<'v> { match tree.kind { hir::UseKind::Single(_) | hir::UseKind::Glob => {} hir::UseKind::Nested { items } => { - for (tree, id) in items { - self.visit_use(tree, *id); + for (tree, id, def_id) in items { + self.visit_use(tree, *id, *def_id); } } } diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index f0bdf91445c1f..0cac0f5129c8a 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -891,7 +891,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { intravisit::walk_poly_trait_ref(self, t); } - fn visit_use(&mut self, tree: &'tcx hir::UseTree<'tcx>, hir_id: HirId) { + fn visit_use(&mut self, tree: &'tcx hir::UseTree<'tcx>, hir_id: HirId, def_id: LocalDefId) { let mut v = vec![]; #[instrument(skip(visitor))] @@ -899,6 +899,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { visitor: &mut Checker<'tcx>, tree: &'tcx hir::UseTree<'tcx>, hir_id: HirId, + def_id: LocalDefId, stack: &mut Vec<&'tcx [hir::PathSegment<'tcx>]>, ) { let UsePath { segments, res, span } = *tree.prefix; @@ -941,15 +942,15 @@ impl<'tcx> Visitor<'tcx> for Checker<'tcx> { stack, ); } else { - for (tree, id) in items { - recurse(visitor, tree, *id, stack); + for (tree, id, def_id) in items { + recurse(visitor, tree, *id, *def_id, stack); } } stack.pop(); } } } - recurse(self, tree, hir_id, &mut v); + recurse(self, tree, hir_id, def_id, &mut v); } fn visit_path(&mut self, path: &hir::Path<'tcx>, id: hir::HirId) { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index a0c2c251a4a8c..b2f740af8bb28 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -648,7 +648,7 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { // Handled in `visit_item_inner` } - fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId) { + fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId, _: LocalDefid) { // Handled in `visit_item_inner` } From 9f9771dc7efc10a47a3fc82d6cd5d686902f4b54 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 12 Aug 2026 13:05:03 +0200 Subject: [PATCH 0787/1309] Make clippy handle HIR use trees --- .../clippy_lints/src/disallowed_types.rs | 9 +- .../src/ifs/branches_sharing_code.rs | 7 +- .../clippy_lints/src/item_name_repetitions.rs | 7 +- .../src/legacy_numeric_constants.rs | 47 +++++--- .../clippy/clippy_lints/src/macro_use.rs | 6 +- .../clippy_lints/src/min_ident_chars.rs | 28 ++++- .../src/missing_enforced_import_rename.rs | 78 +++++++------ .../clippy_lints/src/redundant_pub_crate.rs | 11 +- .../clippy_lints/src/std_instead_of_core.rs | 104 ++++++++++++++---- .../clippy_lints/src/unused_trait_names.rs | 45 +++++--- .../clippy_lints/src/wildcard_imports.rs | 43 ++++++-- .../clippy/clippy_utils/src/hir_utils.rs | 23 ++-- src/tools/clippy/clippy_utils/src/lib.rs | 1 + src/tools/clippy/clippy_utils/src/paths.rs | 14 ++- ...conf_missing_enforced_import_rename.stderr | 8 +- .../tests/ui/redundant_pub_crate.stderr | 4 +- .../clippy/tests/ui/wildcard_imports.fixed | 2 +- .../clippy/tests/ui/wildcard_imports.stderr | 2 +- .../wildcard_imports_2021.edition2018.fixed | 2 +- .../wildcard_imports_2021.edition2018.stderr | 2 +- .../wildcard_imports_2021.edition2021.fixed | 2 +- .../wildcard_imports_2021.edition2021.stderr | 2 +- 22 files changed, 307 insertions(+), 140 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/disallowed_types.rs b/src/tools/clippy/clippy_lints/src/disallowed_types.rs index 2236e613b1472..fb2e70844865d 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_types.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_types.rs @@ -5,7 +5,7 @@ use clippy_utils::paths::PathNS; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; +use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -107,8 +107,11 @@ pub fn def_kind_predicate(def_kind: DefKind) -> bool { impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind - && let Some(res) = path.res.type_ns + if let ItemKind::Use(UseTree { + prefix, + kind: UseKind::Single(_), + }) = &item.kind + && let Some(res) = prefix.res.type_ns { self.check_res_emit(cx, &res, item.span); } diff --git a/src/tools/clippy/clippy_lints/src/ifs/branches_sharing_code.rs b/src/tools/clippy/clippy_lints/src/ifs/branches_sharing_code.rs index ff4683349ad88..de361e0d88d3c 100644 --- a/src/tools/clippy/clippy_lints/src/ifs/branches_sharing_code.rs +++ b/src/tools/clippy/clippy_lints/src/ifs/branches_sharing_code.rs @@ -11,7 +11,7 @@ use core::iter; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{ - Arm, Block, Expr, ExprKind, HirId, HirIdSet, ItemKind, LetStmt, Node, Stmt, StmtKind, UseKind, intravisit, + Arm, Block, Expr, ExprKind, HirId, HirIdSet, ItemKind, LetStmt, Node, Stmt, StmtKind, UseKind, UseTree, intravisit, }; use rustc_lint::LateContext; use rustc_span::hygiene::walk_chain; @@ -259,7 +259,10 @@ fn eq_binding_names(cx: &LateContext<'_>, s: &Stmt<'_>, names: &[(HirId, Symbol) | ItemKind::Const(ident, ..) | ItemKind::Fn { ident, .. } | ItemKind::TyAlias(ident, ..) - | ItemKind::Use(_, UseKind::Single(ident)) + | ItemKind::Use(UseTree { + kind: UseKind::Single(ident), + .. + }) | ItemKind::Mod(ident, _) = item.kind => { *name == ident.name diff --git a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs index 8c604aadc811e..67f9a51cd1c1f 100644 --- a/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs +++ b/src/tools/clippy/clippy_lints/src/item_name_repetitions.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case}; use clippy_utils::{is_bool, is_from_proc_macro}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Body, EnumDef, FieldDef, Item, ItemKind, QPath, TyKind, UseKind, Variant, VariantData}; +use rustc_hir::{Body, EnumDef, FieldDef, Item, ItemKind, QPath, TyKind, UseKind, UseTree, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::symbol::Symbol; @@ -531,7 +531,10 @@ impl LateLintPass<'_> for ItemNameRepetitions { | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) - | ItemKind::Use(_, UseKind::Single(ident)) => ident, + | ItemKind::Use(UseTree { + kind: UseKind::Single(ident), + .. + }) => ident, ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } diff --git a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs index 2fb4fe8be50d9..d19110ee8d4aa 100644 --- a/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs +++ b/src/tools/clippy/clippy_lints/src/legacy_numeric_constants.rs @@ -5,8 +5,7 @@ use clippy_utils::source::SpanExt as _; use clippy_utils::{is_from_proc_macro, sym}; use hir::def_id::DefId; use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; +use rustc_hir::{self as hir, ExprKind, Item, ItemKind, QPath, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Symbol; use rustc_span::symbol::kw; @@ -44,18 +43,26 @@ impl LegacyNumericConstants { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv.into() } } -} -impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + match tree.kind { + UseKind::Single(_) | UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, ..) in items { + self.check_use_tree(cx, tree); + } + return; + }, + } + + let prefix = tree.prefix; // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. - if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind - && !item.span.in_external_macro(cx.sess().source_map()) - // use `present_items` because it could be in either type_ns or value_ns - && let Some(res) = path.res.present_items().next() - && let Some(def_id) = res.opt_def_id() - && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) + if !tree.prefix.span.in_external_macro(cx.sess().source_map()) + // use `present_items` because it could be in either type_ns or value_ns + && let Some(res) = prefix.res.present_items().next() + && let Some(def_id) = res.opt_def_id() + && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) { let module = if is_integer_module(cx, def_id) { true @@ -68,14 +75,14 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { span_lint_and_then( cx, LEGACY_NUMERIC_CONSTANTS, - path.span, + prefix.span, if module { "importing legacy numeric constants" } else { "importing a legacy numeric constant" }, |diag| { - if let UseKind::Single(ident) = kind + if let UseKind::Single(ident) = tree.kind && ident.name == kw::Underscore { diag.help("remove this import"); @@ -85,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { let def_path = cx.get_def_path(def_id); if module && let [.., module_name] = &*def_path { - if matches!(kind, UseKind::Glob) { + if matches!(tree.kind, UseKind::Glob) { diag.help(format!("remove this import and use associated constants `{module_name}::` from the primitive type instead")); } else { diag.help("remove this import").note(format!( @@ -94,13 +101,21 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { } } else if let [.., module_name, name] = &*def_path { diag.help( - format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead") - ); + format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead") + ); } }, ); } } +} + +impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree); + } + } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { // `std::::` check diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 6f06e8665decc..2d5605371ac1a 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -4,7 +4,7 @@ use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, AmbigArg}; +use rustc_hir::{self as hir, AmbigArg, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Span; use rustc_span::edition::Edition; @@ -96,11 +96,11 @@ impl MacroUseImports { impl LateLintPass<'_> for MacroUseImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if cx.sess().opts.edition >= Edition::Edition2018 - && let hir::ItemKind::Use(path, _kind) = &item.kind + && let hir::ItemKind::Use(UseTree { prefix, .. }) = &item.kind && let hir_id = item.hir_id() && let attrs = cx.tcx.hir_attrs(hir_id) && let Some(mac_attr_span) = find_attr!(attrs, MacroUse {span, ..} => *span) - && let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns + && let Some(Res::Def(DefKind::Mod, id)) = prefix.res.type_ns && !id.is_local() { for kid in cx.tcx.module_children(id) { diff --git a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs index e5a292806259d..ee546528020ac 100644 --- a/src/tools/clippy/clippy_lints/src/min_ident_chars.rs +++ b/src/tools/clippy/clippy_lints/src/min_ident_chars.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir::{ FieldDef, HirId, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, Node, Pat, PatKind, TraitFn, TraitItem, - TraitItemKind, UseKind, Variant, + TraitItemKind, UseKind, UseTree, Variant, }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::{Ident, Symbol}; @@ -112,6 +112,24 @@ impl MinIdentChars { }); } } + + fn check_tree(&self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + match tree.kind { + UseKind::Single(ident) => { + if tree.prefix.segments.last().is_some_and(|p| p.ident.span != ident.span) + && let Some(missing) = self.check_sym(ident.name) + { + self.emit(cx, ident, missing); + } + }, + UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, _, _) in items { + self.check_tree(cx, tree); + } + }, + } + } } impl LateLintPass<'_> for MinIdentChars { @@ -132,17 +150,15 @@ impl LateLintPass<'_> for MinIdentChars { | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) => ident, - ItemKind::Use(path, UseKind::Single(ident)) - if path.segments.last().is_some_and(|p| p.ident.span != ident.span) => - { - ident + ItemKind::Use(ref tree) => { + self.check_tree(cx, tree); + return; }, ItemKind::ExternCrate(..) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } | ItemKind::Impl(_) - | ItemKind::Use(..) | ItemKind::TestBinderConstraints { .. } => return, }; if let Some(missing) = self.check_sym(ident.name) diff --git a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs index bb40f50bef098..aa4892280b007 100644 --- a/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs +++ b/src/tools/clippy/clippy_lints/src/missing_enforced_import_rename.rs @@ -5,7 +5,7 @@ use clippy_utils::source::SpanExt as _; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::{Item, ItemKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; @@ -66,41 +66,55 @@ impl ImportRename { .collect(), } } + + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + let hi = match tree.kind { + UseKind::Single(ident) => ident.span.hi(), + UseKind::Glob => return, + UseKind::Nested { items } => { + for (tree, ..) in items { + self.check_use_tree(cx, tree); + } + return; + }, + }; + // use `present_items` because it could be in any of type_ns, value_ns, macro_ns + for res in tree.prefix.res.present_items() { + if let Res::Def(_, id) = res + && let Some(name) = self.renames.get(&id) + // Remove semicolon since it is not present for nested imports + && let span_without_semi = cx.sess().source_map().span_until_char(tree.prefix.span.with_hi(hi), ';') + && let Some(snip) = span_without_semi.get_text(cx) + && let Some(import) = match snip.split_once(" as ") { + None => Some(snip.as_str()), + Some((import, rename)) => { + let trimmed_rename = rename.trim(); + if trimmed_rename == "_" || trimmed_rename == name.as_str() { + None + } else { + Some(import.trim()) + } + }, + } + { + span_lint_and_sugg( + cx, + MISSING_ENFORCED_IMPORT_RENAMES, + span_without_semi, + "this import should be renamed", + "try", + format!("{import} as {name}"), + Applicability::MachineApplicable, + ); + } + } + } } impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { - // use `present_items` because it could be in any of type_ns, value_ns, macro_ns - for res in path.res.present_items() { - if let Res::Def(_, id) = res - && let Some(name) = self.renames.get(&id) - // Remove semicolon since it is not present for nested imports - && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';') - && let Some(snip) = span_without_semi.get_text(cx) - && let Some(import) = match snip.split_once(" as ") { - None => Some(snip.as_str()), - Some((import, rename)) => { - let trimmed_rename = rename.trim(); - if trimmed_rename == "_" || trimmed_rename == name.as_str() { - None - } else { - Some(import.trim()) - } - }, - } - { - span_lint_and_sugg( - cx, - MISSING_ENFORCED_IMPORT_RENAMES, - span_without_semi, - "this import should be renamed", - "try", - format!("{import} as {name}"), - Applicability::MachineApplicable, - ); - } - } + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree) } } } diff --git a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs index 1fe5e87c46ef2..e1ee75521b4c0 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_pub_crate.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_span::def_id::CRATE_MOD_ID; @@ -83,11 +83,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } } -// We ignore macro exports. And `ListStem` uses, which aren't interesting. +// We ignore macro exports. fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { - if let ItemKind::Use(path, kind) = item.kind { - let ignore = - matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || matches!(kind, UseKind::ListStem); + if let ItemKind::Use(tree) = item.kind { + let ignore = tree + .resolutions() + .any(|res| matches!(res.macro_ns, Some(Res::Def(DefKind::Macro(_), _)))); if ignore { return true; } diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 24ef61c2ca9c3..25839a4e0b003 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -6,10 +6,10 @@ use clippy_utils::paths::{PathNS, lookup_path}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Block, Body, HirId, Path, PathSegment, StabilityLevel, StableSince}; +use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, StabilityLevel, StableSince, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext as _, impl_lint_pass}; use rustc_span::symbol::kw; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; declare_clippy_lint! { /// ### What it does @@ -95,6 +95,10 @@ impl_lint_pass!(StdReexports => [ pub struct StdReexports { lint_points: Option<(Span, Vec)>, msrv: Msrv, + /// Imports are handled manually, as they are a tree, not a linear path. + /// If one element in a nested import wants to change the shared start of the import, + /// but another element does not, then we shouldn't emit a suggestion. + in_import: bool, } impl StdReexports { @@ -102,6 +106,7 @@ impl StdReexports { Self { lint_points: Option::default(), msrv: conf.msrv.into(), + in_import: false, } } @@ -113,38 +118,63 @@ impl StdReexports { _ => emit_lints(cx, self.lint_points.replace((krate, vec![lint_point]))), } } -} -#[derive(Debug)] -enum LintPoint { - Available(Span, &'static Lint, &'static str, &'static str), - Conflict, -} + fn walk_import<'tcx>(&mut self, cx: &LateContext<'tcx>, tree: &UseTree<'tcx>, prefix: &[PathSegment<'tcx>]) { + match tree.kind { + UseKind::Single(_) => { + let segments: Vec<_> = prefix + .iter() + .copied() + .chain(tree.prefix.segments.iter().copied()) + .collect(); + for res in tree.prefix.res.present_items() { + self.check_path_segments( + cx, + &Path { + span: tree.prefix.span, + res, + segments: &segments[..], + }, + ); + } + }, + UseKind::Glob => {}, + UseKind::Nested { items } => { + let segments: Vec<_> = prefix + .iter() + .copied() + .chain(tree.prefix.segments.iter().copied()) + .collect(); + for (nested, _, _) in items { + self.walk_import(cx, nested, &segments); + } + }, + } + } -impl<'tcx> LateLintPass<'tcx> for StdReexports { - fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) { + fn check_path_segments(&mut self, cx: &LateContext<'_>, path: &Path<'_>) { if let Res::Def(def_kind, def_id) = path.res && !matches!(def_kind, DefKind::Macro(_)) - && let Some(first_segment) = get_first_segment(path) - && let Res::Def(DefKind::Mod, crate_def_id) = first_segment.res + && let Some((res, ident)) = get_first_segment(path.segments) + && let Res::Def(DefKind::Mod, crate_def_id) = res && crate_def_id.is_crate_root() && is_stable(cx, def_id, self.msrv) && !path.span.in_external_macro(cx.sess().source_map()) - && !is_from_proc_macro(cx, &first_segment.ident) + && !is_from_proc_macro(cx, &ident) && let Some(last_segment) = path.segments.last() { - let (lint, used_mod, replace_with) = match first_segment.ident.name { + let (lint, used_mod, replace_with) = match ident.name { sym::std => match cx.tcx.crate_name(def_id.krate) { sym::core => (STD_INSTEAD_OF_CORE, "std", "core"), sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"), _ => { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; }, }, sym::alloc if cx.tcx.crate_name(def_id.krate) == sym::core => (ALLOC_INSTEAD_OF_CORE, "alloc", "core"), _ => { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; }, }; @@ -153,17 +183,47 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { // the target crate. `std::collections::Bound` for instance reaches `core::ops::Bound` // through a legacy re-export, and `core::collections` does not exist. if !resolves_in(cx, path, def_kind, def_id, replace_with) { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; } self.lint_if_finish( cx, - first_segment.ident.span, + ident.span, LintPoint::Available(last_segment.ident.span, lint, used_mod, replace_with), ); } } +} + +#[derive(Debug)] +enum LintPoint { + Available(Span, &'static Lint, &'static str, &'static str), + Conflict, +} + +impl<'tcx> LateLintPass<'tcx> for StdReexports { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { + if let ItemKind::Use(tree) = item.kind { + if let UseKind::Nested { items } = tree.kind { + for (nested, _, _) in items { + self.walk_import(cx, nested, tree.prefix.segments); + } + self.in_import = true; + } + } + } + + fn check_item_post(&mut self, _: &LateContext<'_>, _: &Item<'_>) { + self.in_import = false; + } + + fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'_>, _: HirId) { + if self.in_import { + return; + } + self.check_path_segments(cx, path); + } fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &Block<'tcx>) { emit_lints(cx, self.lint_points.take()); @@ -256,11 +316,11 @@ fn resolves_in(cx: &LateContext<'_>, path: &Path<'_>, def_kind: DefKind, def_id: /// /// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`] /// is returned. -fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { - match path.segments { +fn get_first_segment<'tcx>(segments: &'tcx [PathSegment<'tcx>]) -> Option<(Res, Ident)> { + match segments { // A global path will have PathRoot as the first segment. In this case, return the segment after. - [x, y, ..] if x.ident.name == kw::PathRoot => Some(y), - [x, ..] => Some(x), + [x, y, ..] if x.ident.name == kw::PathRoot => Some((y.res, y.ident)), + [x, ..] => Some((x.res, x.ident)), _ => None, } } diff --git a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs index ce40f6785c7f5..eea7ae72ab16f 100644 --- a/src/tools/clippy/clippy_lints/src/unused_trait_names.rs +++ b/src/tools/clippy/clippy_lints/src/unused_trait_names.rs @@ -4,7 +4,8 @@ use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::{self, Msrv}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{Item, ItemKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::Visibility; use rustc_span::symbol::kw; @@ -53,21 +54,29 @@ impl UnusedTraitNames { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv.into() } } -} -impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if !item.span.from_expansion() - && let ItemKind::Use(path, UseKind::Single(ident)) = item.kind - // Ignore imports that already use Underscore - && ident.name != kw::Underscore + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>, def_id: LocalDefId) { + let ident = match tree.kind { + UseKind::Single(ident) => ident, + UseKind::Glob => return, + UseKind::Nested { items } => { + for (tree, _, def_id) in items { + self.check_use_tree(cx, tree, *def_id); + } + return; + }, + }; + let prefix = tree.prefix; + if + // Ignore imports that already use Underscore + ident.name != kw::Underscore // Only check traits - && let Some(Res::Def(DefKind::Trait, _)) = path.res.type_ns - && cx.tcx.resolutions(()).maybe_unused_trait_imports.contains(&item.owner_id.def_id) + && let Some(Res::Def(DefKind::Trait, _)) = prefix.res.type_ns + && cx.tcx.resolutions(()).maybe_unused_trait_imports.contains(&def_id) // Only check this import if it is visible to its module only (no pub, pub(crate), ...) - && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id) - && cx.tcx.local_visibility(item.owner_id.def_id) == Visibility::Restricted(module) - && let Some(last_segment) = path.segments.last() + && let module = cx.tcx.parent_module_from_def_id(def_id) + && cx.tcx.local_visibility(def_id) == Visibility::Restricted(module) + && let Some(last_segment) = prefix.segments.last() && self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS) && !is_from_proc_macro(cx, &last_segment.ident) { @@ -99,3 +108,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { } } } + +impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if !item.span.from_expansion() + && let ItemKind::Use(tree) = &item.kind + { + self.check_use_tree(cx, tree, item.owner_id.def_id); + } + } +} diff --git a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs index 16721fbe77a4e..e724e1f25615b 100644 --- a/src/tools/clippy/clippy_lints/src/wildcard_imports.rs +++ b/src/tools/clippy/clippy_lints/src/wildcard_imports.rs @@ -5,11 +5,12 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, PathSegment, UseKind}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{HirId, Item, ItemKind, PathSegment, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty; -use rustc_span::BytePos; use rustc_span::symbol::kw; +use rustc_span::{BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -125,9 +126,27 @@ impl LateLintPass<'_> for WildcardImports { if cx.tcx.local_visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module) && !self.warn_on_all { return; } - if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind - && (self.warn_on_all || !self.check_exceptions(cx, item, use_path.segments)) - && let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&item.owner_id.def_id) + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree, item.hir_id(), item.owner_id.def_id); + } + } +} + +impl WildcardImports { + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>, hir_id: HirId, def_id: LocalDefId) { + match tree.kind { + UseKind::Single(_) => return, + UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, id, def_id) in items { + self.check_use_tree(cx, tree, *id, *def_id); + } + return; + }, + } + let use_path = tree.prefix; + if (self.warn_on_all || !self.check_exceptions(cx, use_path.span, hir_id, use_path.segments)) + && let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&def_id) && !used_imports.is_empty() // Already handled by `unused_imports` && !used_imports.contains(&kw::Underscore) { @@ -144,10 +163,14 @@ impl LateLintPass<'_> for WildcardImports { // formatting like `use _ :: *;`, we extend it up to, but not including the // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we // can just use the end of the item span - let mut span = use_path.span.with_hi(item.span.hi()); + let mut span = use_path.span; if snippet(cx, span, "").ends_with(';') { - span = use_path.span.with_hi(item.span.hi() - BytePos(1)); + span = use_path.span.with_hi(span.hi() - BytePos(1)); } + while !snippet(cx, span, "").ends_with('*') { + span = use_path.span.with_hi(span.hi() + BytePos(1)); + } + (span, false) }; @@ -179,11 +202,11 @@ impl LateLintPass<'_> for WildcardImports { } impl WildcardImports { - fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { - item.span.from_expansion() + fn check_exceptions(&self, cx: &LateContext<'_>, span: Span, hir_id: HirId, segments: &[PathSegment<'_>]) -> bool { + span.from_expansion() || is_prelude_import(segments) || is_allowed_via_config(segments, self.allowed_segments) - || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id())) + || (is_super_only_import(segments) && is_in_test(cx.tcx, hir_id)) } } diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index cf7777d037d9b..7e49702de8632 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -15,7 +15,7 @@ use rustc_hir::{ GenericParam, GenericParamKind, GenericParamSource, Generics, HirId, HirIdMap, InlineAsmOperand, ItemId, ItemKind, LetExpr, Lifetime, LifetimeKind, LifetimeParamKind, Node, ParamName, Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PreciseCapturingArgKind, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, - TyFieldPath, TyKind, TyPat, TyPatKind, UseKind, WherePredicate, WherePredicateKind, + TyFieldPath, TyKind, TyPat, TyPatKind, UseKind, UseTree, WherePredicate, WherePredicateKind, }; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::LateContext; @@ -245,14 +245,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ItemKind::TyAlias(l_ident, l_generics, l_ty), ItemKind::TyAlias(r_ident, r_generics, r_ty)) => { l_ident.name == r_ident.name && self.eq_generics(l_generics, r_generics) && self.eq_ty(l_ty, r_ty) }, - (ItemKind::Use(l_path, l_kind), ItemKind::Use(r_path, r_kind)) => { - self.eq_path_segments(l_path.segments, r_path.segments) - && match (l_kind, r_kind) { - (UseKind::Single(l_ident), UseKind::Single(r_ident)) => l_ident.name == r_ident.name, - (UseKind::Glob, UseKind::Glob) | (UseKind::ListStem, UseKind::ListStem) => true, - _ => false, - } - }, + (ItemKind::Use(ref l_tree), ItemKind::Use(ref r_tree)) => self.eq_use_tree(l_tree, r_tree), (ItemKind::Mod(l_ident, l_mod), ItemKind::Mod(r_ident, r_mod)) => { l_ident.name == r_ident.name && over(l_mod.item_ids, r_mod.item_ids, |l, r| self.eq_item(*l, *r)) }, @@ -264,6 +257,18 @@ impl HirEqInterExpr<'_, '_, '_> { eq } + fn eq_use_tree(&mut self, l_tree: &UseTree<'_>, r_tree: &UseTree<'_>) -> bool { + self.eq_path_segments(l_tree.prefix.segments, r_tree.prefix.segments) + && match (l_tree.kind, r_tree.kind) { + (UseKind::Single(l_ident), UseKind::Single(r_ident)) => l_ident.name == r_ident.name, + (UseKind::Glob, UseKind::Glob) => true, + (UseKind::Nested { items: l_items }, UseKind::Nested { items: r_items }) => { + over(l_items, r_items, |(l, _, _), (r, _, _)| self.eq_use_tree(l, r)) + }, + _ => false, + } + } + fn eq_fn_sig(&mut self, left: &FnSig<'_>, right: &FnSig<'_>) -> bool { left.header.safety == right.header.safety && left.header.constness == right.header.constness diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 0030f1cdc8208..81d8ab4fb3ec7 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2802,6 +2802,7 @@ pub fn expr_use_sites<'tcx>( | Node::TraitRef(_) | Node::Ty(_) | Node::TyPat(_) + | Node::NestedUseTree(_) | Node::WherePredicate(_) | Node::TestBinderForall(_) | Node::TestBinderExists(_) diff --git a/src/tools/clippy/clippy_utils/src/paths.rs b/src/tools/clippy/clippy_utils/src/paths.rs index a97295d952949..090d9c2962b50 100644 --- a/src/tools/clippy/clippy_utils/src/paths.rs +++ b/src/tools/clippy/clippy_utils/src/paths.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Namespace::{MacroNS, TypeNS, ValueNS}; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{ItemKind, Node, UseKind}; +use rustc_hir::{ItemKind, Node, UseKind, UseTree}; use rustc_lint::LateContext; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::HasTyCtxt; @@ -308,13 +308,17 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n match item_kind { ItemKind::Mod(_, r#mod) => r#mod.item_ids.iter().find_map(|&item_id| { let item = tcx.hir_item(item_id); - if let ItemKind::Use(path, UseKind::Single(ident)) = item.kind { + if let ItemKind::Use(UseTree { + prefix, + kind: UseKind::Single(ident), + }) = item.kind + { if ident.name == name { let opt_def_id = |ns: Option| ns.and_then(|res| res.opt_def_id()); match ns { - PathNS::Type => opt_def_id(path.res.type_ns), - PathNS::Value => opt_def_id(path.res.value_ns), - PathNS::Macro => opt_def_id(path.res.macro_ns), + PathNS::Type => opt_def_id(prefix.res.type_ns), + PathNS::Value => opt_def_id(prefix.res.value_ns), + PathNS::Macro => opt_def_id(prefix.res.macro_ns), PathNS::Field => None, PathNS::Arbitrary => unreachable!(), } diff --git a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr index 139331d176198..ff6b1b8822a7b 100644 --- a/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr +++ b/src/tools/clippy/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr @@ -8,10 +8,10 @@ LL | use std::process::{Child as Kid, exit as wrong_exit}; = help: to override `-D warnings` add `#[allow(clippy::missing_enforced_import_renames)]` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:7:1 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:7:5 | LL | use std::thread::sleep; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::thread::sleep as thread_sleep` + | ^^^^^^^^^^^^^^^^^^ help: try: `std::thread::sleep as thread_sleep` error: this import should be renamed --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:11:11 @@ -32,10 +32,10 @@ LL | sync :: Mutex, | ^^^^^^^^^^^^^ help: try: `sync :: Mutex as StdMutie` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:21:5 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:21:9 | LL | use std::collections::BTreeMap as OopsWrongRename; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::collections::BTreeMap as Map` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::collections::BTreeMap as Map` error: aborting due to 6 previous errors diff --git a/src/tools/clippy/tests/ui/redundant_pub_crate.stderr b/src/tools/clippy/tests/ui/redundant_pub_crate.stderr index b6542e1db0902..37edb6a51ac98 100644 --- a/src/tools/clippy/tests/ui/redundant_pub_crate.stderr +++ b/src/tools/clippy/tests/ui/redundant_pub_crate.stderr @@ -138,10 +138,10 @@ LL | pub(crate) use m5_1::*; | help: consider using: `pub` error: pub(crate) import inside private module - --> tests/ui/redundant_pub_crate.rs:138:27 + --> tests/ui/redundant_pub_crate.rs:138:5 | LL | pub(crate) use m5_1::{*}; - | ---------- ^ + | ----------^^^^^^^^^^^^^^^ | | | help: consider using: `pub` diff --git a/src/tools/clippy/tests/ui/wildcard_imports.fixed b/src/tools/clippy/tests/ui/wildcard_imports.fixed index 27d01e6573b85..a2854d3f1b0fe 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports.fixed @@ -200,7 +200,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/src/tools/clippy/tests/ui/wildcard_imports.stderr b/src/tools/clippy/tests/ui/wildcard_imports.stderr index 26434656a509e..1ec063fa14f5b 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:203:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:205:9 diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed index 46abaa91a1c2f..e4a1a32ca2271 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -194,7 +194,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr index 873ce41b04f49..84f26820c63f6 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:199:9 diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed index 46abaa91a1c2f..e4a1a32ca2271 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -194,7 +194,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr index 873ce41b04f49..84f26820c63f6 100644 --- a/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/src/tools/clippy/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:199:9 From 695095ae9431ad9541914948fcf469a4aeaca83a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 18 Aug 2026 13:07:57 +0200 Subject: [PATCH 0788/1309] Make rustdoc handle HIR use trees --- src/librustdoc/clean/mod.rs | 203 +++++++++++++------ src/librustdoc/passes/propagate_stability.rs | 4 +- src/librustdoc/visit_ast.rs | 119 +++++++---- 3 files changed, 231 insertions(+), 95 deletions(-) diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index b3f6617479f21..64c6d46cea355 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -40,7 +40,7 @@ use rustc_errors::codes::*; use rustc_errors::{FatalError, struct_span_code_err}; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::attrs::{AttributeKind, DocAttribute, DocInline}; -use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; +use rustc_hir::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; use rustc_hir::{self as hir, HirId, PredicateOrigin, find_attr}; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; @@ -63,6 +63,14 @@ use crate::core::DocContext; use crate::formats::item_type::ItemType; use crate::visit_ast; +#[derive(Copy, Clone, Debug)] +enum ImportLowerMode { + Everything, + GlobsOnly, + NoGlobs, +} + +#[instrument(level = "trace", skip(cx))] pub(crate) fn clean_doc_module<'tcx>( doc: &visit_ast::Module<'tcx>, cx: &mut DocContext<'tcx>, @@ -100,9 +108,6 @@ pub(crate) fn clean_doc_module<'tcx>( items.extend(doc.items.values().flat_map( |visit_ast::ItemEntry { item, renamed, import_ids }| { // First, lower everything other than glob imports. - if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - return Vec::new(); - } let v = clean_maybe_renamed_item(cx, item, *renamed, import_ids); for item in &v { if let Some(name) = item.name @@ -118,20 +123,26 @@ pub(crate) fn clean_doc_module<'tcx>( |((_, renamed), visit_ast::InlinedForeign { res, import_id })| { let Some(def_id) = res.opt_def_id() else { return Vec::new() }; let name = renamed.unwrap_or_else(|| cx.tcx.item_name(def_id)); - let import = cx.tcx.hir_expect_item(*import_id); - match import.kind { - hir::ItemKind::Use(path, kind) => { - let hir::UsePath { segments, span, .. } = *path; - let path = hir::Path { segments, res: *res, span }; - clean_use_statement_inner( - import.span, - import.owner_id.def_id, - import.hir_id(), + let import = cx.tcx.hir_node_by_def_id(*import_id); + match import { + hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(tree), .. }) + | hir::Node::NestedUseTree(tree) => { + let hir::UsePath { segments, span, .. } = *tree.prefix; + let path = hir::UsePath { + segments, + res: PerNS { value_ns: Some(*res), type_ns: None, macro_ns: None }, + span, + }; + clean_use_statement( + *import_id, + cx.tcx.local_def_id_to_hir_id(*import_id), + tree.prefix.span, Some(name), &path, - kind, + tree.kind, cx, &mut Default::default(), + ImportLowerMode::Everything, ) } _ => unreachable!(), @@ -141,8 +152,18 @@ pub(crate) fn clean_doc_module<'tcx>( items.extend(doc.items.values().flat_map( |visit_ast::ItemEntry { item, renamed, import_ids: _ }| { // Now we actually lower the imports, skipping everything else. - if let hir::ItemKind::Use(path, hir::UseKind::Glob) = item.kind { - clean_use_statement(item, *renamed, path, hir::UseKind::Glob, cx, &mut inserted) + if let hir::ItemKind::Use(tree) = item.kind { + clean_use_statement( + item.owner_id.def_id, + item.hir_id(), + item.span, + *renamed, + tree.prefix, + tree.kind, + cx, + &mut inserted, + ImportLowerMode::GlobsOnly, + ) } else { // skip everything else Vec::new() @@ -179,10 +200,10 @@ pub(crate) fn clean_doc_module<'tcx>( } fn is_glob_import(tcx: TyCtxt<'_>, import_id: LocalDefId) -> bool { - if let hir::Node::Item(item) = tcx.hir_node_by_def_id(import_id) - && let hir::ItemKind::Use(_, use_kind) = item.kind + if let hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(tree), .. }) + | hir::Node::NestedUseTree(tree) = tcx.hir_node_by_def_id(import_id) { - matches!(use_kind, hir::UseKind::Glob) + matches!(tree.kind, hir::UseKind::Glob) } else { false } @@ -1680,10 +1701,32 @@ fn first_non_private<'tcx>( 'reexps: for reexp in child.reexport_chain.iter() { if let Some(use_def_id) = reexp.id() && let Some(local_use_def_id) = use_def_id.as_local() - && let hir::Node::Item(item) = cx.tcx.hir_node_by_def_id(local_use_def_id) - && let hir::ItemKind::Use(path, hir::UseKind::Single(_)) = item.kind + && let hir::Node::Item(hir::Item { kind: hir::ItemKind::Use(tree), .. }) + | hir::Node::NestedUseTree(tree) = + cx.tcx.hir_node_by_def_id(local_use_def_id) + && let hir::UseKind::Single(_) = tree.kind { - for res in path.res.present_items() { + let mut segments = tree.prefix.segments.to_vec(); + let mut span = tree.prefix.span; + let mut parent = cx.tcx.local_parent(local_use_def_id); + loop { + match cx.tcx.hir_node_by_def_id(parent) { + hir::Node::Item(hir::Item { + kind: hir::ItemKind::Use(tree), .. + }) => { + span = tree.prefix.span.to(span); + segments.splice(0..0, tree.prefix.segments.iter().copied()); + break; + } + hir::Node::NestedUseTree(tree) => { + span = tree.prefix.span.to(span); + segments.splice(0..0, tree.prefix.segments.iter().copied()); + parent = cx.tcx.local_parent(local_use_def_id); + } + _ => break, + } + } + for res in tree.prefix.res.present_items() { if let Res::Def(DefKind::Ctor(..), _) | Res::SelfCtor(..) = res { continue; } @@ -1696,7 +1739,7 @@ fn first_non_private<'tcx>( { break 'reexps; } - last_path_res = Some((path, res)); + last_path_res = Some((segments, span, res)); continue 'reexps; } } @@ -1707,13 +1750,8 @@ fn first_non_private<'tcx>( // // 1. We found a public reexport. // 2. We didn't find a public reexport so it's the "end type" path. - if let Some((new_path, _)) = last_path_res { - return Some(first_non_private_clean_path( - cx, - path, - new_path.segments, - new_path.span, - )); + if let Some((segments, span, _)) = last_path_res { + return Some(first_non_private_clean_path(cx, path, &segments, span)); } // If `last_path_res` is `None`, it can mean two things: // @@ -2744,12 +2782,20 @@ fn clean_unsafe_binder_ty<'tcx>( UnsafeBinderTy { generic_params, ty } } +#[instrument(level = "trace", skip(tcx), ret)] pub(crate) fn reexport_chain( tcx: TyCtxt<'_>, import_def_id: LocalDefId, target_def_id: DefId, ) -> &[Reexport] { - for child in tcx.module_children_local(tcx.local_parent(import_def_id)) { + let mut module_id = import_def_id; + loop { + module_id = tcx.local_parent(module_id); + if !matches!(tcx.def_kind(module_id), DefKind::Use) { + break; + } + } + for child in tcx.module_children_local(module_id) { if child.res.opt_def_id() == Some(target_def_id) && child.reexport_chain.first().and_then(|r| r.id()) == Some(import_def_id.to_def_id()) { @@ -2893,14 +2939,17 @@ fn clean_maybe_renamed_item<'tcx>( // generate an impl placeholder and not a "real" impl item. return clean_impl(impl_, item.owner_id.def_id, cx, renamed.is_some()); } - ItemKind::Use(path, kind) => { + ItemKind::Use(tree) => { return clean_use_statement( - item, + item.owner_id.def_id, + item.hir_id(), + item.span, get_name(cx.tcx, item, renamed), - path, - kind, + tree.prefix, + tree.kind, cx, &mut FxHashSet::default(), + ImportLowerMode::NoGlobs, ); } _ => {} @@ -3148,38 +3197,76 @@ fn clean_extern_crate<'tcx>( } fn clean_use_statement<'tcx>( - import: &hir::Item<'tcx>, + import_def_id: LocalDefId, + import_hir_id: HirId, + import_span: rustc_span::Span, name: Option, - path: &hir::UsePath<'tcx>, - kind: hir::UseKind, + path: &hir::UsePath<'_>, + kind: hir::UseKind<'tcx>, cx: &mut DocContext<'tcx>, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, + mode: ImportLowerMode, ) -> Vec { - let mut items = Vec::new(); - let hir::UsePath { segments, ref res, span } = *path; - for res in res.present_items() { - let path = hir::Path { segments, res, span }; - items.append(&mut clean_use_statement_inner( - import.span, - import.owner_id.def_id, - import.hir_id(), - name, - &path, - kind, - cx, - inlined_names, - )); - } - items + let name = match (kind, mode) { + (hir::UseKind::Single(n), ImportLowerMode::Everything | ImportLowerMode::NoGlobs) => { + name.or(Some(n.name)) + } + (hir::UseKind::Glob, ImportLowerMode::NoGlobs) + | (hir::UseKind::Single(_), ImportLowerMode::GlobsOnly) => return vec![], + (hir::UseKind::Glob, ImportLowerMode::Everything | ImportLowerMode::GlobsOnly) => name, + (hir::UseKind::Nested { items }, _) => { + let mut all = vec![]; + for (tree, hir_id, def_id) in items { + let mut segments = path.segments.to_vec(); + segments.extend(tree.prefix.segments.iter()); + if segments.last().unwrap().ident.name == kw::SelfLower { + segments.pop(); + } + let path = hir::UsePath { + segments: &segments, + res: tree.prefix.res, + span: path.span.to(tree.prefix.span), + }; + all.append(&mut clean_use_statement( + *def_id, + *hir_id, + tree.prefix.span, + None, + &path, + tree.kind, + cx, + inlined_names, + mode, + )); + } + return all; + } + }; + path.res + .present_items() + .flat_map(|res| { + let path = hir::Path { span: path.span, res, segments: path.segments }; + clean_use_statement_leaf( + import_def_id, + import_hir_id, + import_span, + name, + &path, + kind, + cx, + inlined_names, + ) + }) + .collect() } -fn clean_use_statement_inner<'tcx>( - import_span: rustc_span::Span, +fn clean_use_statement_leaf<'tcx>( import_id: LocalDefId, import_hir_id: HirId, + import_span: rustc_span::Span, name: Option, path: &hir::Path<'_>, - kind: hir::UseKind, + kind: hir::UseKind<'tcx>, cx: &mut DocContext<'tcx>, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, ) -> Vec { @@ -3262,6 +3349,8 @@ fn clean_use_statement_inner<'tcx>( Import::new_glob(resolve_use_source(cx, path), true) } else { let name = name.unwrap(); + let name = if name == kw::SelfLower { path.last() } else { name }; + if inline_attr.is_none() && let Res::Def(DefKind::Mod, did) = path.res && !did.is_local() diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index 9afde1e6195e7..cff1e7fa46dbb 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -37,9 +37,9 @@ impl DocFolder for StabilityPropagator<'_, '_> { matches!( self.cx.tcx.hir_node(hir_id), rustc_hir::Node::Item(rustc_hir::Item { - kind: rustc_hir::ItemKind::Use(_, rustc_hir::UseKind::Glob), + kind: rustc_hir::ItemKind::Use(tree), .. - }) + }) | rustc_hir::Node::NestedUseTree(tree) if matches!(tree.kind, rustc_hir::UseKind::Glob) ) }); let own_stability = if let Some(item_stab) = item_stability diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index b2f740af8bb28..1b903d5a17092 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -5,18 +5,17 @@ use std::mem; use rustc_ast::attr::AttributeExt; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_hir as hir; use rustc_hir::attrs::DocInline; use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet}; use rustc_hir::intravisit::{Visitor, walk_body, walk_item}; -use rustc_hir::{Node, find_attr}; +use rustc_hir::{self as hir, HirId, Node, find_attr}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::Span; use rustc_span::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalModId}; use rustc_span::symbol::{Symbol, kw}; -use tracing::debug; +use tracing::{debug, instrument, trace}; use crate::clean::reexport_chain; use crate::clean::utils::{inherits_doc_hidden, should_ignore_res}; @@ -119,6 +118,16 @@ fn def_id_to_path(tcx: TyCtxt<'_>, did: DefId) -> Vec { std::iter::once(crate_name).chain(relative).collect() } +#[derive(Copy, Clone)] +enum GlobMode { + // Globs and everything else + Everything, + // Skip all globs + NoGlob, + // Skip all items except for globs + Only, +} + pub(crate) struct RustdocVisitor<'a, 'tcx> { cx: &'a mut core::DocContext<'tcx>, view_item_stack: LocalDefIdSet, @@ -129,6 +138,7 @@ pub(crate) struct RustdocVisitor<'a, 'tcx> { modules: Vec>, is_importable_from_parent: bool, inside_body: bool, + glob_mode: GlobMode, } impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { @@ -153,6 +163,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { modules: vec![om], is_importable_from_parent: true, inside_body: false, + glob_mode: GlobMode::Everything, } } @@ -202,31 +213,31 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { /// This method will go through the given module items in two passes: /// 1. The items which are not glob imports/reexports. /// 2. The glob imports/reexports. + #[instrument(level = "debug", skip(self))] fn visit_mod_contents(&mut self, def_id: LocalDefId, m: &'tcx hir::Mod<'tcx>) { - debug!("Going through module {m:?}"); // Keep track of if there were any private modules in the path. let orig_inside_public_path = self.inside_public_path; self.inside_public_path &= self.cx.tcx.local_visibility(def_id).is_public(); // Reimplementation of `walk_mod` because we need to do it in two passes (explanations in // the second loop): + let old_glob_mode = mem::replace(&mut self.glob_mode, GlobMode::NoGlob); for &i in m.item_ids { let item = self.cx.tcx.hir_item(i); - if !matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - self.visit_item(item); - } + self.visit_item(item); } + self.glob_mode = GlobMode::Only; for &i in m.item_ids { let item = self.cx.tcx.hir_item(i); // To match the way import precedence works, visit glob imports last. // Later passes in rustdoc will de-duplicate by name and kind, so if glob- // imported items appear last, then they'll be the ones that get discarded. - if matches!(item.kind, hir::ItemKind::Use(_, hir::UseKind::Glob)) { - self.visit_item(item); + if matches!(item.kind, hir::ItemKind::Use(..)) { + self.visit_item_inner(item, None, None); } } + self.glob_mode = old_glob_mode; self.inside_public_path = orig_inside_public_path; - debug!("Leaving module {m:?}"); } /// Tries to resolve the target of a `pub use` statement and inlines the @@ -238,6 +249,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { /// and follows different rules. /// /// Returns `true` if the target has been inlined. + #[instrument(level = "debug", skip(self), ret)] fn maybe_inline_local( &mut self, def_id: LocalDefId, @@ -246,9 +258,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { please_inline: bool, import_id: Option, ) -> bool { - debug!("maybe_inline_local (renamed: {renamed:?}) res: {res:?}"); - if renamed == Some(kw::Underscore) { + debug!("not inlining `_` reexports"); // We never inline `_` reexports. return false; } @@ -259,6 +270,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let tcx = self.cx.tcx; let Some(ori_res_did) = res.opt_def_id() else { + debug!("no resolution"); return false; }; @@ -273,11 +285,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { && use_attrs.iter().any(|attr| attr.is_doc_hidden())); if is_no_inline { + debug!("doc::no_inline or doc::hidden"); return false; } let is_glob = renamed.is_none(); let is_hidden = !document_hidden && tcx.is_doc_hidden(ori_res_did); + debug!(?is_hidden, ?is_glob); let Some(res_did) = ori_res_did.as_local() else { // For cross-crate impl inlining we need to know whether items are // reachable in documentation -- a previously unreachable item can be @@ -301,10 +315,12 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { }; let is_private = !self.cx.cache.effective_visibilities.is_directly_public(tcx, ori_res_did); + debug!(?is_private); let item = tcx.hir_node_by_def_id(res_did); if !please_inline { let inherits_hidden = !document_hidden && inherits_doc_hidden(tcx, res_did, None); + debug!(?inherits_hidden); // Only inline if requested or if the item would otherwise be stripped. if (!is_private && !inherits_hidden) || ( is_hidden && @@ -328,23 +344,30 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { return false; } + trace!(?item); + let inlined = match item { // Bang macros are handled a bit on their because of how they are handled by the // compiler. If they have `#[doc(hidden)]` and the re-export doesn't have // `#[doc(inline)]`, then we don't inline it. - Node::Item(_) if is_bang_macro && !please_inline && !is_glob && is_hidden => { + Node::NestedUseTree(..) | Node::Item(_) + if is_bang_macro && !please_inline && !is_glob && is_hidden => + { return false; } Node::Item(&hir::Item { kind: hir::ItemKind::Mod(_, m), .. }) if is_glob => { let prev = mem::replace(&mut self.inlining, true); + let prev_glob = mem::replace(&mut self.glob_mode, GlobMode::Everything); for &i in m.item_ids { let i = tcx.hir_item(i); self.visit_item_inner(i, None, Some(import_id.unwrap_or(def_id))); } + self.glob_mode = prev_glob; self.inlining = prev; true } Node::Item(it) if !is_glob => { + debug!("inlining item"); let prev = mem::replace(&mut self.inlining, true); self.visit_item_inner(it, renamed, Some(import_id.unwrap_or(def_id))); self.inlining = prev; @@ -369,6 +392,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { /// /// This function takes into account the entire re-export `use` chain, so it needs the /// ID of the "leaf" `use` and the ID of the "root" item. + #[instrument(level = "debug", skip(self), ret)] fn reexport_public_and_not_hidden( &self, import_def_id: LocalDefId, @@ -384,6 +408,8 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { .map(|id| id.expect_local()) .nth(1) .unwrap_or(target_def_id); + debug!(?item_def_id); + item_def_id != import_def_id && self.cx.cache.effective_visibilities.is_directly_public(tcx, item_def_id.to_def_id()) && !tcx.is_doc_hidden(item_def_id) @@ -404,6 +430,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } #[inline] + #[instrument(level = "debug", skip(self))] fn add_to_current_mod( &mut self, item: &'tcx hir::Item<'_>, @@ -436,13 +463,13 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } + #[instrument(level = "debug", skip(self))] fn visit_item_inner( &mut self, item: &'tcx hir::Item<'_>, renamed: Option, import_id: Option, ) { - debug!("visiting item {item:?}"); if self.inside_body { // Only impls can be "seen" outside a body. For example: // @@ -479,9 +506,16 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { // If we're inlining, skip private items. _ if self.inlining && !is_pub => {} hir::ItemKind::GlobalAsm { .. } => {} - hir::ItemKind::Use(_, hir::UseKind::ListStem) => {} - hir::ItemKind::Use(path, kind) => { - self.visit_tree_inner(item, renamed, import_id, is_pub, path, kind); + hir::ItemKind::Use(ref tree) => { + self.visit_use_inner( + item, + renamed, + import_id, + is_pub, + item.owner_id.def_id, + item.hir_id(), + tree, + ); } hir::ItemKind::Macro(_, macro_def, _) => { // `#[macro_export] macro_rules!` items are handled separately in `visit()`, @@ -535,24 +569,26 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { } } - fn visit_tree_inner( + #[instrument(level = "debug", skip(self))] + fn visit_use_inner( &mut self, item: &'tcx hir::Item<'tcx>, renamed: Option, import_id: Option, is_pub: bool, - path: &hir::UsePath<'_>, - kind: hir::UseKind, + def_id: LocalDefId, + hir_id: HirId, + tree: &hir::UseTree<'tcx>, ) { let tcx = self.cx.tcx; - for res in path.res.present_items() { + for res in tree.prefix.res.present_items() { // Struct and variant constructors and proc macro stubs always show up alongside // their definitions, we've already processed them so just discard these. if should_ignore_res(res) { continue; } - let attrs = tcx.hir_attrs(tcx.local_def_id_to_hir_id(item.owner_id.def_id)); + let attrs = tcx.hir_attrs(hir_id); // If there was a private module in the current path then don't bother inlining // anything as it will probably be stripped anyway. @@ -560,7 +596,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let please_inline = if let Some(res_did) = res.opt_def_id() && matches!(tcx.def_kind(res_did), DefKind::Macro(MacroKinds::BANG)) { - crate::clean::macro_reexport_is_inline(tcx, item.owner_id.def_id, res_did) + crate::clean::macro_reexport_is_inline(tcx, def_id, res_did) } else { find_attr!( attrs, @@ -568,19 +604,24 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) ) }; - let ident = match kind { - hir::UseKind::Single(ident) => Some(ident.name), - hir::UseKind::Glob => None, - hir::UseKind::ListStem => unreachable!(), + let ident = match (tree.kind, self.glob_mode) { + (hir::UseKind::Single(ident), GlobMode::NoGlob | GlobMode::Everything) => { + Some(ident.name) + } + (hir::UseKind::Glob, GlobMode::Only | GlobMode::Everything) => None, + (hir::UseKind::Single(_), GlobMode::Only) + | (hir::UseKind::Glob, GlobMode::NoGlob) => continue, + (hir::UseKind::Nested { items }, _) => { + for (tree, hir_id, def_id) in items { + self.visit_use_inner( + item, renamed, import_id, is_pub, *def_id, *hir_id, tree, + ); + } + continue; + } }; - if self.maybe_inline_local( - item.owner_id.def_id, - res, - ident, - please_inline, - import_id, - ) { - debug!("Inlining {:?}", item.owner_id.def_id); + if self.maybe_inline_local(def_id, res, ident, please_inline, import_id) { + debug!("Inlining {:?}", def_id); continue; } } @@ -629,6 +670,7 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { self.cx.tcx } + #[instrument(level = "debug", skip(self))] fn visit_item(&mut self, i: &'tcx hir::Item<'tcx>) { self.visit_item_inner(i, None, None); let new_value = self.is_importable_from_parent @@ -648,7 +690,12 @@ impl<'tcx> Visitor<'tcx> for RustdocVisitor<'_, 'tcx> { // Handled in `visit_item_inner` } - fn visit_use(&mut self, _: &hir::UsePath<'tcx>, _: hir::HirId, _: LocalDefid) { + fn visit_use( + &mut self, + _: &hir::UseTree<'tcx>, + _: hir::HirId, + _: rustc_span::def_id::LocalDefId, + ) { // Handled in `visit_item_inner` } From a7c90ba2fa97d987b2b879e94f4243b437e066ac Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 19 Aug 2026 18:08:39 +0200 Subject: [PATCH 0789/1309] Remove redundant assert --- compiler/rustc_metadata/src/rmeta/decoder.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 2f41ca1a77511..b7fe5fb2475c6 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1436,7 +1436,6 @@ impl CrateMetadata { // Structure and variant constructors don't have any attributes encoded for them, // but we assume that someone passing a constructor ID actually wants to look at // the attributes on the corresponding struct or variant. - assert_eq!(def_key.disambiguated_data.data, DefPathData::Ctor); let parent_id = def_key.parent.expect("no parent for a constructor"); self.root .tables From b3a14edebc6d2666564b8d485ce84800db979fa7 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Wed, 12 Aug 2026 13:05:03 +0200 Subject: [PATCH 0790/1309] Make clippy handle HIR use trees --- clippy_lints/src/disallowed_types.rs | 9 +- clippy_lints/src/ifs/branches_sharing_code.rs | 7 +- clippy_lints/src/item_name_repetitions.rs | 7 +- clippy_lints/src/legacy_numeric_constants.rs | 47 +++++--- clippy_lints/src/macro_use.rs | 6 +- clippy_lints/src/min_ident_chars.rs | 28 ++++- .../src/missing_enforced_import_rename.rs | 78 +++++++------ clippy_lints/src/redundant_pub_crate.rs | 11 +- clippy_lints/src/std_instead_of_core.rs | 104 ++++++++++++++---- clippy_lints/src/unused_trait_names.rs | 45 +++++--- clippy_lints/src/wildcard_imports.rs | 43 ++++++-- clippy_utils/src/hir_utils.rs | 23 ++-- clippy_utils/src/lib.rs | 1 + clippy_utils/src/paths.rs | 14 ++- ...conf_missing_enforced_import_rename.stderr | 8 +- tests/ui/redundant_pub_crate.stderr | 4 +- tests/ui/wildcard_imports.fixed | 2 +- tests/ui/wildcard_imports.stderr | 2 +- .../wildcard_imports_2021.edition2018.fixed | 2 +- .../wildcard_imports_2021.edition2018.stderr | 2 +- .../wildcard_imports_2021.edition2021.fixed | 2 +- .../wildcard_imports_2021.edition2021.stderr | 2 +- 22 files changed, 307 insertions(+), 140 deletions(-) diff --git a/clippy_lints/src/disallowed_types.rs b/clippy_lints/src/disallowed_types.rs index 2236e613b1472..fb2e70844865d 100644 --- a/clippy_lints/src/disallowed_types.rs +++ b/clippy_lints/src/disallowed_types.rs @@ -5,7 +5,7 @@ use clippy_utils::paths::PathNS; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind}; +use rustc_hir::{AmbigArg, Item, ItemKind, PolyTraitRef, PrimTy, Ty, TyKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::Span; @@ -107,8 +107,11 @@ pub fn def_kind_predicate(def_kind: DefKind) -> bool { impl<'tcx> LateLintPass<'tcx> for DisallowedTypes { fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind - && let Some(res) = path.res.type_ns + if let ItemKind::Use(UseTree { + prefix, + kind: UseKind::Single(_), + }) = &item.kind + && let Some(res) = prefix.res.type_ns { self.check_res_emit(cx, &res, item.span); } diff --git a/clippy_lints/src/ifs/branches_sharing_code.rs b/clippy_lints/src/ifs/branches_sharing_code.rs index ff4683349ad88..de361e0d88d3c 100644 --- a/clippy_lints/src/ifs/branches_sharing_code.rs +++ b/clippy_lints/src/ifs/branches_sharing_code.rs @@ -11,7 +11,7 @@ use core::iter; use core::ops::ControlFlow; use rustc_errors::Applicability; use rustc_hir::{ - Arm, Block, Expr, ExprKind, HirId, HirIdSet, ItemKind, LetStmt, Node, Stmt, StmtKind, UseKind, intravisit, + Arm, Block, Expr, ExprKind, HirId, HirIdSet, ItemKind, LetStmt, Node, Stmt, StmtKind, UseKind, UseTree, intravisit, }; use rustc_lint::LateContext; use rustc_span::hygiene::walk_chain; @@ -259,7 +259,10 @@ fn eq_binding_names(cx: &LateContext<'_>, s: &Stmt<'_>, names: &[(HirId, Symbol) | ItemKind::Const(ident, ..) | ItemKind::Fn { ident, .. } | ItemKind::TyAlias(ident, ..) - | ItemKind::Use(_, UseKind::Single(ident)) + | ItemKind::Use(UseTree { + kind: UseKind::Single(ident), + .. + }) | ItemKind::Mod(ident, _) = item.kind => { *name == ident.name diff --git a/clippy_lints/src/item_name_repetitions.rs b/clippy_lints/src/item_name_repetitions.rs index 8c604aadc811e..67f9a51cd1c1f 100644 --- a/clippy_lints/src/item_name_repetitions.rs +++ b/clippy_lints/src/item_name_repetitions.rs @@ -3,7 +3,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_help, span_lint_hir}; use clippy_utils::str_utils::{camel_case_split, count_match_end, count_match_start, to_camel_case, to_snake_case}; use clippy_utils::{is_bool, is_from_proc_macro}; use rustc_data_structures::fx::FxHashSet; -use rustc_hir::{Body, EnumDef, FieldDef, Item, ItemKind, QPath, TyKind, UseKind, Variant, VariantData}; +use rustc_hir::{Body, EnumDef, FieldDef, Item, ItemKind, QPath, TyKind, UseKind, UseTree, Variant, VariantData}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::symbol::Symbol; @@ -531,7 +531,10 @@ impl LateLintPass<'_> for ItemNameRepetitions { | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) - | ItemKind::Use(_, UseKind::Single(ident)) => ident, + | ItemKind::Use(UseTree { + kind: UseKind::Single(ident), + .. + }) => ident, ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } diff --git a/clippy_lints/src/legacy_numeric_constants.rs b/clippy_lints/src/legacy_numeric_constants.rs index 2fb4fe8be50d9..d19110ee8d4aa 100644 --- a/clippy_lints/src/legacy_numeric_constants.rs +++ b/clippy_lints/src/legacy_numeric_constants.rs @@ -5,8 +5,7 @@ use clippy_utils::source::SpanExt as _; use clippy_utils::{is_from_proc_macro, sym}; use hir::def_id::DefId; use rustc_errors::Applicability; -use rustc_hir as hir; -use rustc_hir::{ExprKind, Item, ItemKind, QPath, UseKind}; +use rustc_hir::{self as hir, ExprKind, Item, ItemKind, QPath, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Symbol; use rustc_span::symbol::kw; @@ -44,18 +43,26 @@ impl LegacyNumericConstants { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv.into() } } -} -impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + match tree.kind { + UseKind::Single(_) | UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, ..) in items { + self.check_use_tree(cx, tree); + } + return; + }, + } + + let prefix = tree.prefix; // Integer modules are "TBD" deprecated, and the contents are too, // so lint on the `use` statement directly. - if let ItemKind::Use(path, kind @ (UseKind::Single(_) | UseKind::Glob)) = item.kind - && !item.span.in_external_macro(cx.sess().source_map()) - // use `present_items` because it could be in either type_ns or value_ns - && let Some(res) = path.res.present_items().next() - && let Some(def_id) = res.opt_def_id() - && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) + if !tree.prefix.span.in_external_macro(cx.sess().source_map()) + // use `present_items` because it could be in either type_ns or value_ns + && let Some(res) = prefix.res.present_items().next() + && let Some(def_id) = res.opt_def_id() + && self.msrv.meets(cx, msrvs::NUMERIC_ASSOCIATED_CONSTANTS) { let module = if is_integer_module(cx, def_id) { true @@ -68,14 +75,14 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { span_lint_and_then( cx, LEGACY_NUMERIC_CONSTANTS, - path.span, + prefix.span, if module { "importing legacy numeric constants" } else { "importing a legacy numeric constant" }, |diag| { - if let UseKind::Single(ident) = kind + if let UseKind::Single(ident) = tree.kind && ident.name == kw::Underscore { diag.help("remove this import"); @@ -85,7 +92,7 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { let def_path = cx.get_def_path(def_id); if module && let [.., module_name] = &*def_path { - if matches!(kind, UseKind::Glob) { + if matches!(tree.kind, UseKind::Glob) { diag.help(format!("remove this import and use associated constants `{module_name}::` from the primitive type instead")); } else { diag.help("remove this import").note(format!( @@ -94,13 +101,21 @@ impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { } } else if let [.., module_name, name] = &*def_path { diag.help( - format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead") - ); + format!("remove this import and use the associated constant `{module_name}::{name}` from the primitive type instead") + ); } }, ); } } +} + +impl<'tcx> LateLintPass<'tcx> for LegacyNumericConstants { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree); + } + } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { // `std::::` check diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 6f06e8665decc..2d5605371ac1a 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -4,7 +4,7 @@ use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{self as hir, AmbigArg}; +use rustc_hir::{self as hir, AmbigArg, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_span::Span; use rustc_span::edition::Edition; @@ -96,11 +96,11 @@ impl MacroUseImports { impl LateLintPass<'_> for MacroUseImports { fn check_item(&mut self, cx: &LateContext<'_>, item: &hir::Item<'_>) { if cx.sess().opts.edition >= Edition::Edition2018 - && let hir::ItemKind::Use(path, _kind) = &item.kind + && let hir::ItemKind::Use(UseTree { prefix, .. }) = &item.kind && let hir_id = item.hir_id() && let attrs = cx.tcx.hir_attrs(hir_id) && let Some(mac_attr_span) = find_attr!(attrs, MacroUse {span, ..} => *span) - && let Some(Res::Def(DefKind::Mod, id)) = path.res.type_ns + && let Some(Res::Def(DefKind::Mod, id)) = prefix.res.type_ns && !id.is_local() { for kid in cx.tcx.module_children(id) { diff --git a/clippy_lints/src/min_ident_chars.rs b/clippy_lints/src/min_ident_chars.rs index e5a292806259d..ee546528020ac 100644 --- a/clippy_lints/src/min_ident_chars.rs +++ b/clippy_lints/src/min_ident_chars.rs @@ -7,7 +7,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; use rustc_hir::{ FieldDef, HirId, ImplItem, ImplItemImplKind, ImplItemKind, Item, ItemKind, Node, Pat, PatKind, TraitFn, TraitItem, - TraitItemKind, UseKind, Variant, + TraitItemKind, UseKind, UseTree, Variant, }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::{Ident, Symbol}; @@ -112,6 +112,24 @@ impl MinIdentChars { }); } } + + fn check_tree(&self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + match tree.kind { + UseKind::Single(ident) => { + if tree.prefix.segments.last().is_some_and(|p| p.ident.span != ident.span) + && let Some(missing) = self.check_sym(ident.name) + { + self.emit(cx, ident, missing); + } + }, + UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, _, _) in items { + self.check_tree(cx, tree); + } + }, + } + } } impl LateLintPass<'_> for MinIdentChars { @@ -132,17 +150,15 @@ impl LateLintPass<'_> for MinIdentChars { | ItemKind::TraitAlias(_, ident, ..) | ItemKind::TyAlias(ident, ..) | ItemKind::Union(ident, ..) => ident, - ItemKind::Use(path, UseKind::Single(ident)) - if path.segments.last().is_some_and(|p| p.ident.span != ident.span) => - { - ident + ItemKind::Use(ref tree) => { + self.check_tree(cx, tree); + return; }, ItemKind::ExternCrate(..) | ItemKind::ForeignMod { .. } | ItemKind::GlobalAsm { .. } | ItemKind::Impl(_) - | ItemKind::Use(..) | ItemKind::TestBinderConstraints { .. } => return, }; if let Some(missing) = self.check_sym(ident.name) diff --git a/clippy_lints/src/missing_enforced_import_rename.rs b/clippy_lints/src/missing_enforced_import_rename.rs index bb40f50bef098..aa4892280b007 100644 --- a/clippy_lints/src/missing_enforced_import_rename.rs +++ b/clippy_lints/src/missing_enforced_import_rename.rs @@ -5,7 +5,7 @@ use clippy_utils::source::SpanExt as _; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdMap; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::{Item, ItemKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty::TyCtxt; use rustc_span::Symbol; @@ -66,41 +66,55 @@ impl ImportRename { .collect(), } } + + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>) { + let hi = match tree.kind { + UseKind::Single(ident) => ident.span.hi(), + UseKind::Glob => return, + UseKind::Nested { items } => { + for (tree, ..) in items { + self.check_use_tree(cx, tree); + } + return; + }, + }; + // use `present_items` because it could be in any of type_ns, value_ns, macro_ns + for res in tree.prefix.res.present_items() { + if let Res::Def(_, id) = res + && let Some(name) = self.renames.get(&id) + // Remove semicolon since it is not present for nested imports + && let span_without_semi = cx.sess().source_map().span_until_char(tree.prefix.span.with_hi(hi), ';') + && let Some(snip) = span_without_semi.get_text(cx) + && let Some(import) = match snip.split_once(" as ") { + None => Some(snip.as_str()), + Some((import, rename)) => { + let trimmed_rename = rename.trim(); + if trimmed_rename == "_" || trimmed_rename == name.as_str() { + None + } else { + Some(import.trim()) + } + }, + } + { + span_lint_and_sugg( + cx, + MISSING_ENFORCED_IMPORT_RENAMES, + span_without_semi, + "this import should be renamed", + "try", + format!("{import} as {name}"), + Applicability::MachineApplicable, + ); + } + } + } } impl LateLintPass<'_> for ImportRename { fn check_item(&mut self, cx: &LateContext<'_>, item: &Item<'_>) { - if let ItemKind::Use(path, UseKind::Single(_)) = &item.kind { - // use `present_items` because it could be in any of type_ns, value_ns, macro_ns - for res in path.res.present_items() { - if let Res::Def(_, id) = res - && let Some(name) = self.renames.get(&id) - // Remove semicolon since it is not present for nested imports - && let span_without_semi = cx.sess().source_map().span_until_char(item.span, ';') - && let Some(snip) = span_without_semi.get_text(cx) - && let Some(import) = match snip.split_once(" as ") { - None => Some(snip.as_str()), - Some((import, rename)) => { - let trimmed_rename = rename.trim(); - if trimmed_rename == "_" || trimmed_rename == name.as_str() { - None - } else { - Some(import.trim()) - } - }, - } - { - span_lint_and_sugg( - cx, - MISSING_ENFORCED_IMPORT_RENAMES, - span_without_semi, - "this import should be renamed", - "try", - format!("{import} as {name}"), - Applicability::MachineApplicable, - ); - } - } + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree) } } } diff --git a/clippy_lints/src/redundant_pub_crate.rs b/clippy_lints/src/redundant_pub_crate.rs index 1fe5e87c46ef2..e1ee75521b4c0 100644 --- a/clippy_lints/src/redundant_pub_crate.rs +++ b/clippy_lints/src/redundant_pub_crate.rs @@ -1,7 +1,7 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_span::def_id::CRATE_MOD_ID; @@ -83,11 +83,12 @@ impl<'tcx> LateLintPass<'tcx> for RedundantPubCrate { } } -// We ignore macro exports. And `ListStem` uses, which aren't interesting. +// We ignore macro exports. fn is_ignorable_export<'tcx>(item: &'tcx Item<'tcx>) -> bool { - if let ItemKind::Use(path, kind) = item.kind { - let ignore = - matches!(path.res.macro_ns, Some(Res::Def(DefKind::Macro(_), _))) || matches!(kind, UseKind::ListStem); + if let ItemKind::Use(tree) = item.kind { + let ignore = tree + .resolutions() + .any(|res| matches!(res.macro_ns, Some(Res::Def(DefKind::Macro(_), _)))); if ignore { return true; } diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 24ef61c2ca9c3..25839a4e0b003 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -6,10 +6,10 @@ use clippy_utils::paths::{PathNS, lookup_path}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Block, Body, HirId, Path, PathSegment, StabilityLevel, StableSince}; +use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, StabilityLevel, StableSince, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext as _, impl_lint_pass}; use rustc_span::symbol::kw; -use rustc_span::{Span, Symbol, sym}; +use rustc_span::{Ident, Span, Symbol, sym}; declare_clippy_lint! { /// ### What it does @@ -95,6 +95,10 @@ impl_lint_pass!(StdReexports => [ pub struct StdReexports { lint_points: Option<(Span, Vec)>, msrv: Msrv, + /// Imports are handled manually, as they are a tree, not a linear path. + /// If one element in a nested import wants to change the shared start of the import, + /// but another element does not, then we shouldn't emit a suggestion. + in_import: bool, } impl StdReexports { @@ -102,6 +106,7 @@ impl StdReexports { Self { lint_points: Option::default(), msrv: conf.msrv.into(), + in_import: false, } } @@ -113,38 +118,63 @@ impl StdReexports { _ => emit_lints(cx, self.lint_points.replace((krate, vec![lint_point]))), } } -} -#[derive(Debug)] -enum LintPoint { - Available(Span, &'static Lint, &'static str, &'static str), - Conflict, -} + fn walk_import<'tcx>(&mut self, cx: &LateContext<'tcx>, tree: &UseTree<'tcx>, prefix: &[PathSegment<'tcx>]) { + match tree.kind { + UseKind::Single(_) => { + let segments: Vec<_> = prefix + .iter() + .copied() + .chain(tree.prefix.segments.iter().copied()) + .collect(); + for res in tree.prefix.res.present_items() { + self.check_path_segments( + cx, + &Path { + span: tree.prefix.span, + res, + segments: &segments[..], + }, + ); + } + }, + UseKind::Glob => {}, + UseKind::Nested { items } => { + let segments: Vec<_> = prefix + .iter() + .copied() + .chain(tree.prefix.segments.iter().copied()) + .collect(); + for (nested, _, _) in items { + self.walk_import(cx, nested, &segments); + } + }, + } + } -impl<'tcx> LateLintPass<'tcx> for StdReexports { - fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'tcx>, _: HirId) { + fn check_path_segments(&mut self, cx: &LateContext<'_>, path: &Path<'_>) { if let Res::Def(def_kind, def_id) = path.res && !matches!(def_kind, DefKind::Macro(_)) - && let Some(first_segment) = get_first_segment(path) - && let Res::Def(DefKind::Mod, crate_def_id) = first_segment.res + && let Some((res, ident)) = get_first_segment(path.segments) + && let Res::Def(DefKind::Mod, crate_def_id) = res && crate_def_id.is_crate_root() && is_stable(cx, def_id, self.msrv) && !path.span.in_external_macro(cx.sess().source_map()) - && !is_from_proc_macro(cx, &first_segment.ident) + && !is_from_proc_macro(cx, &ident) && let Some(last_segment) = path.segments.last() { - let (lint, used_mod, replace_with) = match first_segment.ident.name { + let (lint, used_mod, replace_with) = match ident.name { sym::std => match cx.tcx.crate_name(def_id.krate) { sym::core => (STD_INSTEAD_OF_CORE, "std", "core"), sym::alloc => (STD_INSTEAD_OF_ALLOC, "std", "alloc"), _ => { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; }, }, sym::alloc if cx.tcx.crate_name(def_id.krate) == sym::core => (ALLOC_INSTEAD_OF_CORE, "alloc", "core"), _ => { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; }, }; @@ -153,17 +183,47 @@ impl<'tcx> LateLintPass<'tcx> for StdReexports { // the target crate. `std::collections::Bound` for instance reaches `core::ops::Bound` // through a legacy re-export, and `core::collections` does not exist. if !resolves_in(cx, path, def_kind, def_id, replace_with) { - self.lint_if_finish(cx, first_segment.ident.span, LintPoint::Conflict); + self.lint_if_finish(cx, ident.span, LintPoint::Conflict); return; } self.lint_if_finish( cx, - first_segment.ident.span, + ident.span, LintPoint::Available(last_segment.ident.span, lint, used_mod, replace_with), ); } } +} + +#[derive(Debug)] +enum LintPoint { + Available(Span, &'static Lint, &'static str, &'static str), + Conflict, +} + +impl<'tcx> LateLintPass<'tcx> for StdReexports { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &Item<'tcx>) { + if let ItemKind::Use(tree) = item.kind { + if let UseKind::Nested { items } = tree.kind { + for (nested, _, _) in items { + self.walk_import(cx, nested, tree.prefix.segments); + } + self.in_import = true; + } + } + } + + fn check_item_post(&mut self, _: &LateContext<'_>, _: &Item<'_>) { + self.in_import = false; + } + + fn check_path(&mut self, cx: &LateContext<'tcx>, path: &Path<'_>, _: HirId) { + if self.in_import { + return; + } + self.check_path_segments(cx, path); + } fn check_block_post(&mut self, cx: &LateContext<'tcx>, _: &Block<'tcx>) { emit_lints(cx, self.lint_points.take()); @@ -256,11 +316,11 @@ fn resolves_in(cx: &LateContext<'_>, path: &Path<'_>, def_kind: DefKind, def_id: /// /// If this is a global path (such as `::std::fmt::Debug`), then the segment after [`kw::PathRoot`] /// is returned. -fn get_first_segment<'tcx>(path: &Path<'tcx>) -> Option<&'tcx PathSegment<'tcx>> { - match path.segments { +fn get_first_segment<'tcx>(segments: &'tcx [PathSegment<'tcx>]) -> Option<(Res, Ident)> { + match segments { // A global path will have PathRoot as the first segment. In this case, return the segment after. - [x, y, ..] if x.ident.name == kw::PathRoot => Some(y), - [x, ..] => Some(x), + [x, y, ..] if x.ident.name == kw::PathRoot => Some((y.res, y.ident)), + [x, ..] => Some((x.res, x.ident)), _ => None, } } diff --git a/clippy_lints/src/unused_trait_names.rs b/clippy_lints/src/unused_trait_names.rs index ce40f6785c7f5..eea7ae72ab16f 100644 --- a/clippy_lints/src/unused_trait_names.rs +++ b/clippy_lints/src/unused_trait_names.rs @@ -4,7 +4,8 @@ use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::{self, Msrv}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, UseKind}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{Item, ItemKind, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::Visibility; use rustc_span::symbol::kw; @@ -53,21 +54,29 @@ impl UnusedTraitNames { pub fn new(conf: &'static Conf) -> Self { Self { msrv: conf.msrv.into() } } -} -impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { - fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { - if !item.span.from_expansion() - && let ItemKind::Use(path, UseKind::Single(ident)) = item.kind - // Ignore imports that already use Underscore - && ident.name != kw::Underscore + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>, def_id: LocalDefId) { + let ident = match tree.kind { + UseKind::Single(ident) => ident, + UseKind::Glob => return, + UseKind::Nested { items } => { + for (tree, _, def_id) in items { + self.check_use_tree(cx, tree, *def_id); + } + return; + }, + }; + let prefix = tree.prefix; + if + // Ignore imports that already use Underscore + ident.name != kw::Underscore // Only check traits - && let Some(Res::Def(DefKind::Trait, _)) = path.res.type_ns - && cx.tcx.resolutions(()).maybe_unused_trait_imports.contains(&item.owner_id.def_id) + && let Some(Res::Def(DefKind::Trait, _)) = prefix.res.type_ns + && cx.tcx.resolutions(()).maybe_unused_trait_imports.contains(&def_id) // Only check this import if it is visible to its module only (no pub, pub(crate), ...) - && let module = cx.tcx.parent_module_from_def_id(item.owner_id.def_id) - && cx.tcx.local_visibility(item.owner_id.def_id) == Visibility::Restricted(module) - && let Some(last_segment) = path.segments.last() + && let module = cx.tcx.parent_module_from_def_id(def_id) + && cx.tcx.local_visibility(def_id) == Visibility::Restricted(module) + && let Some(last_segment) = prefix.segments.last() && self.msrv.meets(cx, msrvs::UNDERSCORE_IMPORTS) && !is_from_proc_macro(cx, &last_segment.ident) { @@ -99,3 +108,13 @@ impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { } } } + +impl<'tcx> LateLintPass<'tcx> for UnusedTraitNames { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if !item.span.from_expansion() + && let ItemKind::Use(tree) = &item.kind + { + self.check_use_tree(cx, tree, item.owner_id.def_id); + } + } +} diff --git a/clippy_lints/src/wildcard_imports.rs b/clippy_lints/src/wildcard_imports.rs index 16721fbe77a4e..e724e1f25615b 100644 --- a/clippy_lints/src/wildcard_imports.rs +++ b/clippy_lints/src/wildcard_imports.rs @@ -5,11 +5,12 @@ use clippy_utils::source::{snippet, snippet_with_applicability}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::{Item, ItemKind, PathSegment, UseKind}; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{HirId, Item, ItemKind, PathSegment, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; use rustc_middle::ty; -use rustc_span::BytePos; use rustc_span::symbol::kw; +use rustc_span::{BytePos, Span}; declare_clippy_lint! { /// ### What it does @@ -125,9 +126,27 @@ impl LateLintPass<'_> for WildcardImports { if cx.tcx.local_visibility(item.owner_id.def_id) != ty::Visibility::Restricted(module) && !self.warn_on_all { return; } - if let ItemKind::Use(use_path, UseKind::Glob) = &item.kind - && (self.warn_on_all || !self.check_exceptions(cx, item, use_path.segments)) - && let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&item.owner_id.def_id) + if let ItemKind::Use(tree) = &item.kind { + self.check_use_tree(cx, tree, item.hir_id(), item.owner_id.def_id); + } + } +} + +impl WildcardImports { + fn check_use_tree(&mut self, cx: &LateContext<'_>, tree: &UseTree<'_>, hir_id: HirId, def_id: LocalDefId) { + match tree.kind { + UseKind::Single(_) => return, + UseKind::Glob => {}, + UseKind::Nested { items } => { + for (tree, id, def_id) in items { + self.check_use_tree(cx, tree, *id, *def_id); + } + return; + }, + } + let use_path = tree.prefix; + if (self.warn_on_all || !self.check_exceptions(cx, use_path.span, hir_id, use_path.segments)) + && let Some(used_imports) = cx.tcx.resolutions(()).glob_map.get(&def_id) && !used_imports.is_empty() // Already handled by `unused_imports` && !used_imports.contains(&kw::Underscore) { @@ -144,10 +163,14 @@ impl LateLintPass<'_> for WildcardImports { // formatting like `use _ :: *;`, we extend it up to, but not including the // `;`. In nested imports, like `use _::{inner::*, _}` there is no `;` and we // can just use the end of the item span - let mut span = use_path.span.with_hi(item.span.hi()); + let mut span = use_path.span; if snippet(cx, span, "").ends_with(';') { - span = use_path.span.with_hi(item.span.hi() - BytePos(1)); + span = use_path.span.with_hi(span.hi() - BytePos(1)); } + while !snippet(cx, span, "").ends_with('*') { + span = use_path.span.with_hi(span.hi() + BytePos(1)); + } + (span, false) }; @@ -179,11 +202,11 @@ impl LateLintPass<'_> for WildcardImports { } impl WildcardImports { - fn check_exceptions(&self, cx: &LateContext<'_>, item: &Item<'_>, segments: &[PathSegment<'_>]) -> bool { - item.span.from_expansion() + fn check_exceptions(&self, cx: &LateContext<'_>, span: Span, hir_id: HirId, segments: &[PathSegment<'_>]) -> bool { + span.from_expansion() || is_prelude_import(segments) || is_allowed_via_config(segments, self.allowed_segments) - || (is_super_only_import(segments) && is_in_test(cx.tcx, item.hir_id())) + || (is_super_only_import(segments) && is_in_test(cx.tcx, hir_id)) } } diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index cf7777d037d9b..7e49702de8632 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -15,7 +15,7 @@ use rustc_hir::{ GenericParam, GenericParamKind, GenericParamSource, Generics, HirId, HirIdMap, InlineAsmOperand, ItemId, ItemKind, LetExpr, Lifetime, LifetimeKind, LifetimeParamKind, Node, ParamName, Pat, PatExpr, PatExprKind, PatField, PatKind, Path, PathSegment, PreciseCapturingArgKind, PrimTy, QPath, Stmt, StmtKind, StructTailExpr, TraitBoundModifiers, Ty, - TyFieldPath, TyKind, TyPat, TyPatKind, UseKind, WherePredicate, WherePredicateKind, + TyFieldPath, TyKind, TyPat, TyPatKind, UseKind, UseTree, WherePredicate, WherePredicateKind, }; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::LateContext; @@ -245,14 +245,7 @@ impl HirEqInterExpr<'_, '_, '_> { (ItemKind::TyAlias(l_ident, l_generics, l_ty), ItemKind::TyAlias(r_ident, r_generics, r_ty)) => { l_ident.name == r_ident.name && self.eq_generics(l_generics, r_generics) && self.eq_ty(l_ty, r_ty) }, - (ItemKind::Use(l_path, l_kind), ItemKind::Use(r_path, r_kind)) => { - self.eq_path_segments(l_path.segments, r_path.segments) - && match (l_kind, r_kind) { - (UseKind::Single(l_ident), UseKind::Single(r_ident)) => l_ident.name == r_ident.name, - (UseKind::Glob, UseKind::Glob) | (UseKind::ListStem, UseKind::ListStem) => true, - _ => false, - } - }, + (ItemKind::Use(ref l_tree), ItemKind::Use(ref r_tree)) => self.eq_use_tree(l_tree, r_tree), (ItemKind::Mod(l_ident, l_mod), ItemKind::Mod(r_ident, r_mod)) => { l_ident.name == r_ident.name && over(l_mod.item_ids, r_mod.item_ids, |l, r| self.eq_item(*l, *r)) }, @@ -264,6 +257,18 @@ impl HirEqInterExpr<'_, '_, '_> { eq } + fn eq_use_tree(&mut self, l_tree: &UseTree<'_>, r_tree: &UseTree<'_>) -> bool { + self.eq_path_segments(l_tree.prefix.segments, r_tree.prefix.segments) + && match (l_tree.kind, r_tree.kind) { + (UseKind::Single(l_ident), UseKind::Single(r_ident)) => l_ident.name == r_ident.name, + (UseKind::Glob, UseKind::Glob) => true, + (UseKind::Nested { items: l_items }, UseKind::Nested { items: r_items }) => { + over(l_items, r_items, |(l, _, _), (r, _, _)| self.eq_use_tree(l, r)) + }, + _ => false, + } + } + fn eq_fn_sig(&mut self, left: &FnSig<'_>, right: &FnSig<'_>) -> bool { left.header.safety == right.header.safety && left.header.constness == right.header.constness diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 0030f1cdc8208..81d8ab4fb3ec7 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2802,6 +2802,7 @@ pub fn expr_use_sites<'tcx>( | Node::TraitRef(_) | Node::Ty(_) | Node::TyPat(_) + | Node::NestedUseTree(_) | Node::WherePredicate(_) | Node::TestBinderForall(_) | Node::TestBinderExists(_) diff --git a/clippy_utils/src/paths.rs b/clippy_utils/src/paths.rs index a97295d952949..090d9c2962b50 100644 --- a/clippy_utils/src/paths.rs +++ b/clippy_utils/src/paths.rs @@ -11,7 +11,7 @@ use rustc_data_structures::fx::FxHashMap; use rustc_hir::def::Namespace::{MacroNS, TypeNS, ValueNS}; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{ItemKind, Node, UseKind}; +use rustc_hir::{ItemKind, Node, UseKind, UseTree}; use rustc_lint::LateContext; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::layout::HasTyCtxt; @@ -308,13 +308,17 @@ fn local_item_child_by_name(tcx: TyCtxt<'_>, local_id: LocalDefId, ns: PathNS, n match item_kind { ItemKind::Mod(_, r#mod) => r#mod.item_ids.iter().find_map(|&item_id| { let item = tcx.hir_item(item_id); - if let ItemKind::Use(path, UseKind::Single(ident)) = item.kind { + if let ItemKind::Use(UseTree { + prefix, + kind: UseKind::Single(ident), + }) = item.kind + { if ident.name == name { let opt_def_id = |ns: Option| ns.and_then(|res| res.opt_def_id()); match ns { - PathNS::Type => opt_def_id(path.res.type_ns), - PathNS::Value => opt_def_id(path.res.value_ns), - PathNS::Macro => opt_def_id(path.res.macro_ns), + PathNS::Type => opt_def_id(prefix.res.type_ns), + PathNS::Value => opt_def_id(prefix.res.value_ns), + PathNS::Macro => opt_def_id(prefix.res.macro_ns), PathNS::Field => None, PathNS::Arbitrary => unreachable!(), } diff --git a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr index 139331d176198..ff6b1b8822a7b 100644 --- a/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr +++ b/tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.stderr @@ -8,10 +8,10 @@ LL | use std::process::{Child as Kid, exit as wrong_exit}; = help: to override `-D warnings` add `#[allow(clippy::missing_enforced_import_renames)]` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:7:1 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:7:5 | LL | use std::thread::sleep; - | ^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::thread::sleep as thread_sleep` + | ^^^^^^^^^^^^^^^^^^ help: try: `std::thread::sleep as thread_sleep` error: this import should be renamed --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:11:11 @@ -32,10 +32,10 @@ LL | sync :: Mutex, | ^^^^^^^^^^^^^ help: try: `sync :: Mutex as StdMutie` error: this import should be renamed - --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:21:5 + --> tests/ui-toml/missing_enforced_import_rename/conf_missing_enforced_import_rename.rs:21:9 | LL | use std::collections::BTreeMap as OopsWrongRename; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `use std::collections::BTreeMap as Map` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `std::collections::BTreeMap as Map` error: aborting due to 6 previous errors diff --git a/tests/ui/redundant_pub_crate.stderr b/tests/ui/redundant_pub_crate.stderr index b6542e1db0902..37edb6a51ac98 100644 --- a/tests/ui/redundant_pub_crate.stderr +++ b/tests/ui/redundant_pub_crate.stderr @@ -138,10 +138,10 @@ LL | pub(crate) use m5_1::*; | help: consider using: `pub` error: pub(crate) import inside private module - --> tests/ui/redundant_pub_crate.rs:138:27 + --> tests/ui/redundant_pub_crate.rs:138:5 | LL | pub(crate) use m5_1::{*}; - | ---------- ^ + | ----------^^^^^^^^^^^^^^^ | | | help: consider using: `pub` diff --git a/tests/ui/wildcard_imports.fixed b/tests/ui/wildcard_imports.fixed index 27d01e6573b85..a2854d3f1b0fe 100644 --- a/tests/ui/wildcard_imports.fixed +++ b/tests/ui/wildcard_imports.fixed @@ -200,7 +200,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/tests/ui/wildcard_imports.stderr b/tests/ui/wildcard_imports.stderr index 26434656a509e..1ec063fa14f5b 100644 --- a/tests/ui/wildcard_imports.stderr +++ b/tests/ui/wildcard_imports.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports.rs:203:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports.rs:205:9 diff --git a/tests/ui/wildcard_imports_2021.edition2018.fixed b/tests/ui/wildcard_imports_2021.edition2018.fixed index 46abaa91a1c2f..e4a1a32ca2271 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.fixed +++ b/tests/ui/wildcard_imports_2021.edition2018.fixed @@ -194,7 +194,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/tests/ui/wildcard_imports_2021.edition2018.stderr b/tests/ui/wildcard_imports_2021.edition2018.stderr index 873ce41b04f49..84f26820c63f6 100644 --- a/tests/ui/wildcard_imports_2021.edition2018.stderr +++ b/tests/ui/wildcard_imports_2021.edition2018.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:199:9 diff --git a/tests/ui/wildcard_imports_2021.edition2021.fixed b/tests/ui/wildcard_imports_2021.edition2021.fixed index 46abaa91a1c2f..e4a1a32ca2271 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.fixed +++ b/tests/ui/wildcard_imports_2021.edition2021.fixed @@ -194,7 +194,7 @@ fn test_reexported() { #[rustfmt::skip] fn test_weird_formatting() { - use crate:: in_fn_test::exported; + use crate:: in_fn_test::exported ; //~^ wildcard_imports use crate:: fn_mod::foo; diff --git a/tests/ui/wildcard_imports_2021.edition2021.stderr b/tests/ui/wildcard_imports_2021.edition2021.stderr index 873ce41b04f49..84f26820c63f6 100644 --- a/tests/ui/wildcard_imports_2021.edition2021.stderr +++ b/tests/ui/wildcard_imports_2021.edition2021.stderr @@ -89,7 +89,7 @@ error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:197:9 | LL | use crate:: in_fn_test:: * ; - | ^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` + | ^^^^^^^^^^^^^^^^^^^^^^^ help: try: `crate:: in_fn_test::exported` error: usage of wildcard import --> tests/ui/wildcard_imports_2021.rs:199:9 From 744b8fd5b9994ee27c4da28944c1d5cd61b62c7d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 18 May 2026 03:08:03 +0200 Subject: [PATCH 0791/1309] Add new `try_from_instead_of_from_str` lint --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/lib.rs | 2 + .../src/try_from_instead_of_from_str.rs | 220 ++++++++++++++++++ clippy_utils/src/sym.rs | 1 + tests/ui/try_from_instead_of_from_str.fixed | 122 ++++++++++ tests/ui/try_from_instead_of_from_str.rs | 127 ++++++++++ tests/ui/try_from_instead_of_from_str.stderr | 117 ++++++++++ 8 files changed, 591 insertions(+) create mode 100644 clippy_lints/src/try_from_instead_of_from_str.rs create mode 100644 tests/ui/try_from_instead_of_from_str.fixed create mode 100644 tests/ui/try_from_instead_of_from_str.rs create mode 100644 tests/ui/try_from_instead_of_from_str.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f5eb09e5247..8ca73d91ad8e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7647,6 +7647,7 @@ Released 2018-09-13 [`trivial_regex`]: https://rust-lang.github.io/rust-clippy/main/index.html#trivial_regex [`trivially_copy_pass_by_ref`]: https://rust-lang.github.io/rust-clippy/main/index.html#trivially_copy_pass_by_ref [`try_err`]: https://rust-lang.github.io/rust-clippy/main/index.html#try_err +[`try_from_instead_of_from_str`]: https://rust-lang.github.io/rust-clippy/main/index.html#try_from_instead_of_from_str [`tuple_array_conversions`]: https://rust-lang.github.io/rust-clippy/main/index.html#tuple_array_conversions [`type_complexity`]: https://rust-lang.github.io/rust-clippy/main/index.html#type_complexity [`type_id_on_box`]: https://rust-lang.github.io/rust-clippy/main/index.html#type_id_on_box diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index 2258ae7659285..bdd7e311113c2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -762,6 +762,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::transmute::UNSOUND_COLLECTION_TRANSMUTE_INFO, crate::transmute::USELESS_TRANSMUTE_INFO, crate::transmute::WRONG_TRANSMUTE_INFO, + crate::try_from_instead_of_from_str::TRY_FROM_INSTEAD_OF_FROM_STR_INFO, crate::tuple_array_conversions::TUPLE_ARRAY_CONVERSIONS_INFO, crate::types::BORROWED_BOX_INFO, crate::types::BOX_COLLECTION_INFO, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index e1a1055b609dd..ad00908a9a3be 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -367,6 +367,7 @@ mod toplevel_ref_arg; mod trailing_empty_array; mod trait_bounds; mod transmute; +mod try_from_instead_of_from_str; mod tuple_array_conversions; mod types; mod unconditional_recursion; @@ -862,6 +863,7 @@ rustc_lint::late_lint_methods!( ManualPopIf: manual_pop_if::ManualPopIf = manual_pop_if::ManualPopIf::new(tcx, conf), ManualNoopWaker: manual_noop_waker::ManualNoopWaker = manual_noop_waker::ManualNoopWaker::new(conf), ByteCharSlice: byte_char_slices::ByteCharSlice = byte_char_slices::ByteCharSlice, + TryFromInsteadOfFromStr: try_from_instead_of_from_str::TryFromInsteadOfFromStr = try_from_instead_of_from_str::TryFromInsteadOfFromStr::new(conf), ManualAssertEq: manual_assert_eq::ManualAssertEq = manual_assert_eq::ManualAssertEq, WithCapacityZero: with_capacity_zero::WithCapacityZero = with_capacity_zero::WithCapacityZero, RefPatterns: ref_patterns::RefPatterns = ref_patterns::RefPatterns, diff --git a/clippy_lints/src/try_from_instead_of_from_str.rs b/clippy_lints/src/try_from_instead_of_from_str.rs new file mode 100644 index 0000000000000..e8b9b256224b0 --- /dev/null +++ b/clippy_lints/src/try_from_instead_of_from_str.rs @@ -0,0 +1,220 @@ +use clippy_config::Conf; +use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::paths::{PathNS, lookup_path}; +use clippy_utils::source::snippet_opt; +use clippy_utils::sym; +use clippy_utils::ty::{implements_trait, ty_from_hir_ty}; +use rustc_errors::Applicability; +use rustc_hir::def_id::LocalDefId; +use rustc_hir::{BodyId, GenericArg, Impl, ImplItemKind, Item, ItemKind, LifetimeKind, TraitRef, Ty}; +use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; +use rustc_span::symbol::kw; + +use core::ops::ControlFlow; + +declare_clippy_lint! { + /// ### What it does + /// + /// Checks for implementations of `TryFrom<&str>` which could be implementations of `FromStr`. + /// + /// ### Why is this bad? + /// + /// `FromStr` is the idiomatic trait for parsing a string and should be preferred over `TryFrom` + /// when doing so. Implementing `FromStr` allows the the use of `str::parse` to make the intent + /// of the conversion clearer at the conversion site. + /// + /// ### Known problems + /// + /// It's not always possible to convert a `TryFrom<&str>` implementation into a `FromStr` one. + /// For example: + /// + /// ```no_run + /// # struct T; + /// // Cannot be converted into a `FromStr` impl because the `Error` + /// // associated type has a lifetime, which cannot be constrained in + /// // `FromStr`. + /// impl<'a> TryFrom<&'a str> for T { + /// type Error = &'a str; + /// + /// fn try_from(_value: &str) -> Result { + /// Ok(T) + /// } + /// } + /// ``` + /// + /// ### Example + /// + /// ```no_run + /// # struct MyType; + /// # struct MyError; + /// impl TryFrom<&str> for MyType { + /// type Error = MyError; + /// fn try_from(value: &str) -> Result { + /// # Ok(MyType) + /// } + /// } + /// ``` + /// + /// Use instead: + /// + /// ```no_run + /// # use std::str::FromStr; + /// # struct MyType; + /// # struct MyError; + /// impl FromStr for MyType { + /// type Err = MyError; + /// fn from_str(value: &str) -> Result { + /// # Ok(MyType) + /// } + /// } + /// ``` + #[clippy::version = "1.100.0"] + pub TRY_FROM_INSTEAD_OF_FROM_STR, + style, + "TryFrom instead of FromStr" +} + +impl_lint_pass!(TryFromInsteadOfFromStr => [TRY_FROM_INSTEAD_OF_FROM_STR]); + +pub struct TryFromInsteadOfFromStr { + avoid_breaking_exported_api: bool, +} + +impl TryFromInsteadOfFromStr { + pub fn new(conf: &'static Conf) -> Self { + Self { + avoid_breaking_exported_api: conf.avoid_breaking_exported_api, + } + } +} + +struct LifetimeVisitor { + forbidden_lifetime: LocalDefId, +} + +impl<'tcx> rustc_hir::intravisit::Visitor<'tcx> for LifetimeVisitor { + type Result = ControlFlow<(), ()>; + + fn visit_lifetime(&mut self, lifetime: &'tcx rustc_hir::Lifetime) -> Self::Result { + if let LifetimeKind::Param(def_id) = lifetime.kind + && def_id == self.forbidden_lifetime + { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + } +} + +// In this function, we check that the error type doesn't use the same lifetime as +// `TryFrom<&'a str>`. +// +// This is not generalizable as it is specialized for the `TryFrom<&str>` implementation. +fn check_lifetimes(ty: &Ty<'_>, imp: &Impl<'_>, trait_ref: &TraitRef<'_>) -> bool { + let Some(forbidden_lifetime) = get_try_from_str_lifetime(trait_ref) else { + // No lifetime on the `TryFrom::Error` associated type. + return true; + }; + + let mut visitor = LifetimeVisitor { forbidden_lifetime }; + + if rustc_hir::intravisit::walk_unambig_ty(&mut visitor, ty).is_break() + || rustc_hir::intravisit::walk_unambig_ty(&mut visitor, imp.self_ty).is_break() + { + return false; + } + + // And finally we check that the `&str` lifetime is not used in the impl generics. + imp.generics + .predicates + .iter() + .all(|pred| rustc_hir::intravisit::walk_where_predicate(&mut visitor, pred).is_continue()) +} + +fn get_impl_items<'tcx>(cx: &LateContext<'tcx>, imp: &Impl<'_>) -> Option<(&'tcx Ty<'tcx>, BodyId)> { + let &[item1, item2] = &imp.items else { return None }; + match ( + cx.tcx.hir_expect_impl_item(item1.owner_id.def_id).kind, + cx.tcx.hir_expect_impl_item(item2.owner_id.def_id).kind, + ) { + (ImplItemKind::Type(ty), ImplItemKind::Fn(_, body_id)) + | (ImplItemKind::Fn(_, body_id), ImplItemKind::Type(ty)) => Some((ty, body_id)), + _ => None, + } +} + +fn get_try_from_str_lifetime(trait_ref: &TraitRef<'_>) -> Option { + if let Some(segment) = trait_ref.path.segments.last() + && let Some(args) = segment.args + && let Some(ty) = args.args.iter().find_map(|arg| match arg { + GenericArg::Type(ty) => Some(ty), + _ => None, + }) + && let rustc_hir::TyKind::Ref(lifetime, ..) = ty.kind + && lifetime.ident.name != kw::UnderscoreLifetime + && let LifetimeKind::Param(def_id) = lifetime.kind + { + Some(def_id) + } else { + None + } +} + +impl<'tcx> LateLintPass<'tcx> for TryFromInsteadOfFromStr { + fn check_item(&mut self, cx: &LateContext<'tcx>, item: &'tcx Item<'tcx>) { + if let ItemKind::Impl(imp) = &item.kind + && let Some(of_trait) = imp.of_trait + // It should only have an associated type (`Error`) and a method (`try_from`). + && let Some((err_ty, fn_body)) = get_impl_items(cx, imp) + && let Some(trait_def_id) = of_trait.trait_ref.trait_def_id() + && let impl_def_id = item.owner_id.to_def_id() + && let trait_ref = cx.tcx.impl_trait_ref(impl_def_id) + && let instantiated_trait_ref = trait_ref.instantiate_identity().skip_normalization() + // We check if the "from" item is a non-mutable `&str`. + && let [_, from_arg] = &**instantiated_trait_ref.args + && let Some(from_ty) = from_arg.as_type() + && from_ty.is_imm_ref_str() + // We check that the trait is `TryFrom`. + && cx.tcx.is_diagnostic_item(sym::TryFrom, trait_def_id) + // We check that our type doesn't already implement `FromStr`. + && !lookup_path(cx.tcx, PathNS::Type, &[sym::core, sym::str, sym::FromStr]) + .into_iter() + .any(|def_id| { + implements_trait(cx, ty_from_hir_ty(cx, imp.self_ty), def_id, &[]) + }) + // We check that the lifetime used by `TryFrom::Error` is not used anywhere else. + && check_lifetimes(err_ty, imp, &of_trait.trait_ref) + // We retrieve all snippets for lint suggestion. + && let Some(fn_body) = snippet_opt(cx, cx.tcx.hir_span_with_body(fn_body.hir_id)) + && let Some(err_ty) = snippet_opt(cx, err_ty.span) + && let Some(generics) = snippet_opt(cx, imp.generics.span) + && let Some(self_ty) = snippet_opt(cx, imp.self_ty.span) + { + let suggestion = format!( + "\ +impl{generics} core::str::FromStr for {self_ty} {{ + type Err = {err_ty}; + + fn from_str(value: &str) -> Result {fn_body} +}}" + ); + span_lint_and_then( + cx, + TRY_FROM_INSTEAD_OF_FROM_STR, + item.span, + "`TryFrom` could be `FromStr`", + |diag| { + let applicability = if self.avoid_breaking_exported_api { + Applicability::Unspecified + } else { + Applicability::MaybeIncorrect + }; + diag.span_suggestion(item.span, "replace with", suggestion, applicability); + if self.avoid_breaking_exported_api { + diag.help("`FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes"); + } + }, + ); + } + } +} diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index 8f03003eeb0ac..0a349c6e68b51 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -64,6 +64,7 @@ generate! { Error, File, FileType, + FromStr, FsOpenOptions, FsPermissions, HashMapEntry, diff --git a/tests/ui/try_from_instead_of_from_str.fixed b/tests/ui/try_from_instead_of_from_str.fixed new file mode 100644 index 0000000000000..062f274a2afb1 --- /dev/null +++ b/tests/ui/try_from_instead_of_from_str.fixed @@ -0,0 +1,122 @@ +#![warn(clippy::try_from_instead_of_from_str)] +#![allow(dead_code, clippy::elidable_lifetime_names)] + +struct MyType; + +impl core::str::FromStr for MyType { + type Err = (); + + fn from_str(value: &str) -> Result { + Ok(MyType) + } +} + +struct Bar; + +impl core::str::FromStr for Bar { + type Err = &'static str; + + fn from_str(value: &str) -> Result { + Ok(Bar) + } +} + +struct Tarte<'a>(&'a ()); + +// We ensure that we generate the `impl<'a>` generics correctly and that +// lifetimes on the `Self` type are allowed. +impl<'a> core::str::FromStr for Tarte<'a> { + type Err = &'static str; + + fn from_str(value: &str) -> Result { + Ok(Tarte(&())) + } +} + +struct Foo; + +// Should not generate a warning because the `Error` associated type +// has a lifetime, which cannot be constrained in `FromStr`. +impl<'a> TryFrom<&'a str> for Foo { + type Error = &'a str; + fn try_from(_value: &str) -> Result { + Ok(Foo) + } +} + +struct Foo2; + +// Same here. The `Error` associated type has a lifetime so no suggestion. +impl<'a> TryFrom<&'a str> for Foo2 { + type Error = Tarte<'a>; + + fn try_from(_value: &str) -> Result { + Ok(Foo2) + } +} + +struct Lifetime1; + +struct LifetimeErr1<'a>(&'a ()); + +// This should not lint because the error type uses an unconstrained lifetime (`'a`). +impl<'a> TryFrom<&'a str> for Lifetime1 { + type Error = LifetimeErr1<'a>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime1) + } +} + +struct Lifetime2; +struct LifetimeErr2(T); + +// This should not lint because the error type uses an unconstrained lifetime (`'a` in `&'a i8`). +impl<'a> TryFrom<&'a str> for Lifetime2 { + type Error = LifetimeErr2 fn(&'b u32, &'a i8)>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime2) + } +} + +struct Lifetime3; + +// This one should lint because there is no unconstrained lifetimes (`dyn` and `for`). +impl core::str::FromStr for Lifetime3 { + type Err = LifetimeErr2 fn(&'b u32)>; + + fn from_str(value: &str) -> Result { + Ok(Lifetime3) + } +} + +struct Lifetime4(T); + +// This one should lint because there is no unconstrained lifetimes (constrained by `Self`). +impl<'a> core::str::FromStr for Lifetime4<&'a ()> { + type Err = LifetimeErr2<&'a ()>; + + fn from_str(value: &str) -> Result { + Ok(Lifetime4(&())) + } +} + +// Should not lint because it already implements `FromStr`. +struct Already; + +impl TryFrom<&str> for Already { + type Error = (); + fn try_from(_value: &str) -> Result { + Ok(Already) + } +} + +impl std::str::FromStr for Already { + type Err = (); + fn from_str(_s: &str) -> Result { + Ok(Already) + } +} + +fn main() {} diff --git a/tests/ui/try_from_instead_of_from_str.rs b/tests/ui/try_from_instead_of_from_str.rs new file mode 100644 index 0000000000000..e2e969fac95eb --- /dev/null +++ b/tests/ui/try_from_instead_of_from_str.rs @@ -0,0 +1,127 @@ +#![warn(clippy::try_from_instead_of_from_str)] +#![allow(dead_code, clippy::elidable_lifetime_names)] + +struct MyType; + +impl TryFrom<&str> for MyType { + //~^ try_from_instead_of_from_str + + type Error = (); + fn try_from(_value: &str) -> Result { + Ok(MyType) + } +} + +struct Bar; + +impl TryFrom<&str> for Bar { + //~^ try_from_instead_of_from_str + + type Error = &'static str; + fn try_from(_value: &str) -> Result { + Ok(Bar) + } +} + +struct Tarte<'a>(&'a ()); + +// We ensure that we generate the `impl<'a>` generics correctly and that +// lifetimes on the `Self` type are allowed. +impl<'a> TryFrom<&str> for Tarte<'a> { + //~^ try_from_instead_of_from_str + + type Error = &'static str; + fn try_from(_value: &str) -> Result { + Ok(Tarte(&())) + } +} + +struct Foo; + +// Should not generate a warning because the `Error` associated type +// has a lifetime, which cannot be constrained in `FromStr`. +impl<'a> TryFrom<&'a str> for Foo { + type Error = &'a str; + fn try_from(_value: &str) -> Result { + Ok(Foo) + } +} + +struct Foo2; + +// Same here. The `Error` associated type has a lifetime so no suggestion. +impl<'a> TryFrom<&'a str> for Foo2 { + type Error = Tarte<'a>; + + fn try_from(_value: &str) -> Result { + Ok(Foo2) + } +} + +struct Lifetime1; + +struct LifetimeErr1<'a>(&'a ()); + +// This should not lint because the error type uses an unconstrained lifetime (`'a`). +impl<'a> TryFrom<&'a str> for Lifetime1 { + type Error = LifetimeErr1<'a>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime1) + } +} + +struct Lifetime2; +struct LifetimeErr2(T); + +// This should not lint because the error type uses an unconstrained lifetime (`'a` in `&'a i8`). +impl<'a> TryFrom<&'a str> for Lifetime2 { + type Error = LifetimeErr2 fn(&'b u32, &'a i8)>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime2) + } +} + +struct Lifetime3; + +// This one should lint because there is no unconstrained lifetimes (`dyn` and `for`). +impl TryFrom<&str> for Lifetime3 { + //~^ try_from_instead_of_from_str + type Error = LifetimeErr2 fn(&'b u32)>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime3) + } +} + +struct Lifetime4(T); + +// This one should lint because there is no unconstrained lifetimes (constrained by `Self`). +impl<'a> TryFrom<&str> for Lifetime4<&'a ()> { + //~^ try_from_instead_of_from_str + type Error = LifetimeErr2<&'a ()>; + + fn try_from(_value: &str) -> Result { + Ok(Lifetime4(&())) + } +} + +// Should not lint because it already implements `FromStr`. +struct Already; + +impl TryFrom<&str> for Already { + type Error = (); + fn try_from(_value: &str) -> Result { + Ok(Already) + } +} + +impl std::str::FromStr for Already { + type Err = (); + fn from_str(_s: &str) -> Result { + Ok(Already) + } +} + +fn main() {} diff --git a/tests/ui/try_from_instead_of_from_str.stderr b/tests/ui/try_from_instead_of_from_str.stderr new file mode 100644 index 0000000000000..72e194d1b37b0 --- /dev/null +++ b/tests/ui/try_from_instead_of_from_str.stderr @@ -0,0 +1,117 @@ +error: `TryFrom` could be `FromStr` + --> tests/ui/try_from_instead_of_from_str.rs:6:1 + | +LL | / impl TryFrom<&str> for MyType { +LL | | +LL | | +LL | | type Error = (); +... | +LL | | } + | |_^ + | + = help: `FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes + = note: `-D clippy::try-from-instead-of-from-str` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::try_from_instead_of_from_str)]` +help: replace with + | +LL + impl core::str::FromStr for MyType { +LL + type Err = (); +LL + +LL + fn from_str(value: &str) -> Result { +LL + Ok(MyType) +LL + } +LL + } + | + +error: `TryFrom` could be `FromStr` + --> tests/ui/try_from_instead_of_from_str.rs:17:1 + | +LL | / impl TryFrom<&str> for Bar { +LL | | +LL | | +LL | | type Error = &'static str; +... | +LL | | } + | |_^ + | + = help: `FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes +help: replace with + | +LL + impl core::str::FromStr for Bar { +LL + type Err = &'static str; +LL + +LL + fn from_str(value: &str) -> Result { +LL + Ok(Bar) +LL + } +LL + } + | + +error: `TryFrom` could be `FromStr` + --> tests/ui/try_from_instead_of_from_str.rs:30:1 + | +LL | / impl<'a> TryFrom<&str> for Tarte<'a> { +LL | | +LL | | +LL | | type Error = &'static str; +... | +LL | | } + | |_^ + | + = help: `FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes +help: replace with + | +LL + impl<'a> core::str::FromStr for Tarte<'a> { +LL + type Err = &'static str; +LL + +LL + fn from_str(value: &str) -> Result { +LL + Ok(Tarte(&())) +LL + } +LL + } + | + +error: `TryFrom` could be `FromStr` + --> tests/ui/try_from_instead_of_from_str.rs:89:1 + | +LL | / impl TryFrom<&str> for Lifetime3 { +LL | | +LL | | type Error = LifetimeErr2 fn(&'b u32)>; +... | +LL | | } + | |_^ + | + = help: `FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes +help: replace with + | +LL + impl core::str::FromStr for Lifetime3 { +LL + type Err = LifetimeErr2 fn(&'b u32)>; +LL + +LL + fn from_str(value: &str) -> Result { +LL + Ok(Lifetime3) +LL + } +LL + } + | + +error: `TryFrom` could be `FromStr` + --> tests/ui/try_from_instead_of_from_str.rs:101:1 + | +LL | / impl<'a> TryFrom<&str> for Lifetime4<&'a ()> { +LL | | +LL | | type Error = LifetimeErr2<&'a ()>; +... | +LL | | } + | |_^ + | + = help: `FromStr` can also be implemented alongside `TryFrom` if you want to avoid breaking changes +help: replace with + | +LL + impl<'a> core::str::FromStr for Lifetime4<&'a ()> { +LL + type Err = LifetimeErr2<&'a ()>; +LL + +LL + fn from_str(value: &str) -> Result { +LL + Ok(Lifetime4(&())) +LL + } +LL + } + | + +error: aborting due to 5 previous errors + From fc538ecc32511eb73230edf12960ca4f8f977be7 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Thu, 24 Sep 2026 15:58:46 +0200 Subject: [PATCH 0792/1309] Add PermittedDeps type --- src/tools/tidy/src/deps.rs | 63 +++++++++++++++++++++++++------------- 1 file changed, 41 insertions(+), 22 deletions(-) diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs index 2c3a47228ac3f..e1a5495f81954 100644 --- a/src/tools/tidy/src/deps.rs +++ b/src/tools/tidy/src/deps.rs @@ -95,16 +95,34 @@ pub(crate) struct WorkspaceInfo<'a> { pub(crate) path: &'a str, /// The list of license exceptions. pub(crate) exceptions: ExceptionList, - /// Optionally: - /// * A list of crates for which dependencies need to be explicitly allowed - /// or None to check the entire workspace. - /// * The list of allowed dependencies. - /// * The source code location of the allowed dependencies list - crates_and_deps: Option<(Option<&'a [&'a str]>, &'a [&'a str], ListLocation)>, + /// The list of dependencies that are allowed. If None, any crate with an + /// acceptable license is allowed. + allowed_deps: Option>, /// Submodules required for the workspace pub(crate) submodules: &'a [&'a str], } +#[derive(Clone, Copy)] +struct PermittedDeps<'a> { + /// A list of crates for which dependencies need to be explicitly allowed + /// or None to check the entire workspace. + roots: Option<&'a [&'a str]>, + /// The list of allowed dependencies. + deps: &'a [&'a str], + /// The source code location of the allowed dependencies list. + deps_loc: ListLocation, +} + +impl<'a> PermittedDeps<'a> { + const fn new( + roots: Option<&'a [&'a str]>, + deps: &'a [&'a str], + deps_loc: ListLocation, + ) -> Self { + Self { roots, deps, deps_loc } + } +} + const WORKSPACE_LOCATION: ListLocation = location!(+4); /// The workspaces to check for licensing and optionally permitted dependencies. @@ -114,7 +132,7 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ WorkspaceInfo { path: ".", exceptions: EXCEPTIONS, - crates_and_deps: Some(( + allowed_deps: Some(PermittedDeps::new( Some(&["rustc-main"]), PERMITTED_RUSTC_DEPENDENCIES, PERMITTED_RUSTC_DEPS_LOCATION, @@ -124,7 +142,7 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ WorkspaceInfo { path: "library", exceptions: EXCEPTIONS_STDLIB, - crates_and_deps: Some(( + allowed_deps: Some(PermittedDeps::new( None, PERMITTED_STDLIB_DEPENDENCIES, PERMITTED_STDLIB_DEPS_LOCATION, @@ -134,13 +152,13 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ WorkspaceInfo { path: "library/stdarch", exceptions: EXCEPTIONS_STDARCH, - crates_and_deps: None, + allowed_deps: None, submodules: &[], }, WorkspaceInfo { path: "compiler/rustc_codegen_cranelift", exceptions: EXCEPTIONS_CRANELIFT, - crates_and_deps: Some(( + allowed_deps: Some(PermittedDeps::new( None, PERMITTED_CRANELIFT_DEPENDENCIES, PERMITTED_CRANELIFT_DEPS_LOCATION, @@ -150,19 +168,19 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ WorkspaceInfo { path: "compiler/rustc_codegen_gcc", exceptions: EXCEPTIONS_GCC, - crates_and_deps: None, + allowed_deps: None, submodules: &[], }, WorkspaceInfo { path: "src/bootstrap", exceptions: EXCEPTIONS_BOOTSTRAP, - crates_and_deps: None, + allowed_deps: None, submodules: &[], }, WorkspaceInfo { path: "src/tools/cargo", exceptions: EXCEPTIONS_CARGO, - crates_and_deps: None, + allowed_deps: None, submodules: &["src/tools/cargo"], }, // FIXME uncomment once all deps are vendored @@ -179,25 +197,25 @@ pub(crate) const WORKSPACES: &[WorkspaceInfo<'static>] = &[ WorkspaceInfo { path: "src/tools/rust-analyzer", exceptions: EXCEPTIONS_RUST_ANALYZER, - crates_and_deps: None, + allowed_deps: None, submodules: &[], }, WorkspaceInfo { path: "src/tools/rustbook", exceptions: EXCEPTIONS_RUSTBOOK, - crates_and_deps: None, + allowed_deps: None, submodules: &["src/doc/book", "src/doc/reference"], }, WorkspaceInfo { path: "src/tools/rustc-perf", exceptions: EXCEPTIONS_RUSTC_PERF, - crates_and_deps: None, + allowed_deps: None, submodules: &["src/tools/rustc-perf"], }, WorkspaceInfo { path: "tests/run-make-cargo/uefi-qemu/uefi_qemu_test", exceptions: EXCEPTIONS_UEFI_QEMU_TEST, - crates_and_deps: None, + allowed_deps: None, submodules: &[], }, ]; @@ -639,7 +657,8 @@ pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) { check_proc_macro_dep_list(root, cargo, bless, &mut check); - for &WorkspaceInfo { path, exceptions, crates_and_deps, submodules } in WORKSPACES { + for &WorkspaceInfo { path, exceptions, allowed_deps: crates_and_deps, submodules } in WORKSPACES + { if has_missing_submodule(root, submodules, tidy_ctx.is_running_on_ci()) { continue; } @@ -664,14 +683,14 @@ pub fn check(root: &Path, cargo: &Path, tidy_ctx: TidyCtx) { check.error(format!("{path} is part of another workspace ({} != {}), remove from `WORKSPACES` ({WORKSPACE_LOCATION})", absolute_root.display(), absolute_root_real.display())); } check_license_exceptions(&metadata, path, exceptions, &mut check); - if let Some((crates, permitted_deps, location)) = crates_and_deps { - let descr = crates.map_or(path, |crates| crates.get(0).unwrap_or(&path)); + if let Some(PermittedDeps { roots, deps: permitted_deps, deps_loc }) = crates_and_deps { + let descr = roots.map_or(path, |roots| roots.get(0).unwrap_or(&path)); check_permitted_dependencies( &metadata, descr, permitted_deps, - crates, - location, + roots, + deps_loc, &mut check, ); } From 2160998a06d10879cb4fb790f32ecde1eb317186 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Wed, 9 Sep 2026 13:52:30 -0700 Subject: [PATCH 0793/1309] Refactor CodeGen Pipeline Setup into a Single Function This patch refactors setup of the LegacyPassManager for CodeGen into a single function. This simplifies some things (lifetime for the LegacyPM object), but is primarily aimed at enabling rustc to use the new runCodeGenPipeline abstraction (introduced in LLVM 24) which handles all of these details within LLVM and additionally defaults to the NewPM when a target opts-in/the correct LLVM flag is passed. --- compiler/rustc_codegen_llvm/src/back/write.rs | 5 +- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 15 +---- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 65 +++++++++---------- 3 files changed, 31 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index dd2dbdff6b82c..c7cfa87d86e5e 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -72,17 +72,14 @@ fn write_output_file<'ll>( std::ptr::null() }; let result = unsafe { - let pm = llvm::LLVMCreatePassManager(); - llvm::LLVMAddAnalysisPasses(target, pm); - llvm::LLVMRustAddLibraryInfo(target, pm, m, no_builtins); llvm::LLVMRustWriteOutputFile( target, - pm, m, output_c.as_ptr(), dwo_output_ptr, file_type, verify_llvm_ir, + no_builtins, ) }; diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 655a79e341bd1..eca5fe429f541 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -715,8 +715,6 @@ unsafe extern "C" { } #[repr(C)] pub(crate) struct Builder<'a>(InvariantOpaque<'a>); -#[repr(C)] -pub(crate) struct PassManager<'a>(InvariantOpaque<'a>); unsafe extern "C" { pub type TargetMachine; } @@ -1637,11 +1635,6 @@ unsafe extern "C" { /// Writes a module to the specified path. Returns 0 on success. pub(crate) fn LLVMWriteBitcodeToFile(M: &Module, Path: *const c_char) -> c_int; - /// Creates a legacy pass manager -- only used for final codegen. - pub(crate) fn LLVMCreatePassManager<'a>() -> &'a mut PassManager<'a>; - - pub(crate) fn LLVMAddAnalysisPasses<'a>(T: &'a TargetMachine, PM: &PassManager<'a>); - pub(crate) fn LLVMGetHostCPUFeatures() -> *mut c_char; pub(crate) fn LLVMDisposeMessage(message: *mut c_char); @@ -2430,20 +2423,14 @@ unsafe extern "C" { pub(crate) fn LLVMRustDisposeMCSubtargetInfo(MCInfo: ptr::NonNull); - pub(crate) fn LLVMRustAddLibraryInfo<'a>( - T: &TargetMachine, - PM: &PassManager<'a>, - M: &'a Module, - DisableSimplifyLibCalls: bool, - ); pub(crate) fn LLVMRustWriteOutputFile<'a>( T: &'a TargetMachine, - PM: *mut PassManager<'a>, M: &'a Module, Output: *const c_char, DwoOutput: *const c_char, FileType: FileType, VerifyIR: bool, + DisableSimplifyLibCalls: bool, ) -> LLVMRustResult; pub(crate) fn LLVMRustOptimize<'a>( M: &'a Module, diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index beb63ad61493c..5c510a74078c2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -447,30 +447,6 @@ extern "C" LLVMTargetMachineRef LLVMRustCreateTargetMachine( return wrap(TM); } -// Unfortunately, the LLVM C API doesn't provide a way to create the -// TargetLibraryInfo pass, so we use this method to do so. -extern "C" void LLVMRustAddLibraryInfo(LLVMTargetMachineRef T, - LLVMPassManagerRef PMR, LLVMModuleRef M, - bool DisableSimplifyLibCalls) { - auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); - TargetOptions *Options = &unwrap(T)->Options; - auto TLII = TargetLibraryInfoImpl(TargetTriple); - if (DisableSimplifyLibCalls) - TLII.disableAllFunctions(); - unwrap(PMR)->add(new TargetLibraryInfoWrapperPass(TLII)); -#if LLVM_VERSION_GE(24, 0) - // LLVM 24 removed TargetOptions::EABIVersion and ExceptionModel; the EABI - // version and exception model are now derived from the target triple and - // module flags respectively instead. - unwrap(PMR)->add(new RuntimeLibraryInfoWrapper(Options->MCOptions.ABIName, - Options->VecLib)); -#elif LLVM_VERSION_GE(22, 0) - unwrap(PMR)->add(new RuntimeLibraryInfoWrapper( - TargetTriple, Options->ExceptionModel, Options->FloatABIType, - Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib)); -#endif -} - extern "C" void LLVMRustSetLLVMOptions(int Argc, char **Argv) { // Initializing the command-line options more than once is not allowed. So, // check if they've already been initialized. (This could happen if we're @@ -500,10 +476,31 @@ static CodeGenFileType fromRust(LLVMRustFileType Type) { } extern "C" LLVMRustResult -LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, - LLVMModuleRef M, const char *Path, const char *DwoPath, - LLVMRustFileType RustFileType, bool VerifyIR) { - llvm::legacy::PassManager *PM = unwrap(PMR); +LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, + const char *Path, const char *DwoPath, + LLVMRustFileType RustFileType, bool VerifyIR, + bool DisableSimplifyLibCalls) { + llvm::legacy::PassManager PM; + + PM.add(createTargetTransformInfoWrapperPass( + unwrap(Target)->getTargetIRAnalysis())); + + auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); + TargetOptions *Options = &unwrap(Target)->Options; + auto TLII = TargetLibraryInfoImpl(TargetTriple); + if (DisableSimplifyLibCalls) + TLII.disableAllFunctions(); + PM.add(new TargetLibraryInfoWrapperPass(TLII)); +#if LLVM_VERSION_GE(24, 0) + PM.add(new RuntimeLibraryInfoWrapper( + Options->ExceptionModel, Options->EABIVersion, Options->MCOptions.ABIName, + Options->VecLib)); +#elif LLVM_VERSION_GE(22, 0) + PM.add(new RuntimeLibraryInfoWrapper( + TargetTriple, Options->ExceptionModel, Options->FloatABIType, + Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib)); +#endif + auto FileType = fromRust(RustFileType); std::string ErrorInfo; @@ -527,17 +524,13 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMPassManagerRef PMR, return LLVMRustResult::Failure; } auto DBOS = buffer_ostream(DOS); - unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR); - PM->run(*unwrap(M)); + unwrap(Target)->addPassesToEmitFile(PM, BOS, &DBOS, FileType, !VerifyIR); + PM.run(*unwrap(M)); } else { - unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR); - PM->run(*unwrap(M)); + unwrap(Target)->addPassesToEmitFile(PM, BOS, nullptr, FileType, !VerifyIR); + PM.run(*unwrap(M)); } - // Apparently `addPassesToEmitFile` adds a pointer to our on-the-stack output - // stream (OS), so the only real safe place to delete this is here? Don't we - // wish this was written in Rust? - LLVMDisposePassManager(PMR); return LLVMRustResult::Success; } From 288a941096948e3a6d9e85b7628dcf9b12cab633 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 24 Sep 2026 16:53:39 +0200 Subject: [PATCH 0794/1309] add jank leak check test --- ...straint-from-nested-projection.next.stderr | 22 +++++++++++++ .../constraint-from-nested-projection.rs | 33 +++++++++++++++++++ 2 files changed, 55 insertions(+) create mode 100644 tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr create mode 100644 tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs diff --git a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr new file mode 100644 index 0000000000000..bf3e6943f0d5a --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr @@ -0,0 +1,22 @@ +error[E0283]: type annotations needed + --> $DIR/constraint-from-nested-projection.rs:31:5 + | +LL | pick::<(), _>(); + | ^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `pick` + | +note: multiple `impl`s satisfying `(): Pick<_>` found + --> $DIR/constraint-from-nested-projection.rs:25:1 + | +LL | impl RequiresProject<'a>> Pick for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Pick for T {} + | ^^^^^^^^^^^^^^^^^^^^^^^ +note: required by a bound in `pick` + --> $DIR/constraint-from-nested-projection.rs:28:12 + | +LL | fn pick, U>() {} + | ^^^^^^^ required by this bound in `pick` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs new file mode 100644 index 0000000000000..fda0fa7efa57c --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs @@ -0,0 +1,33 @@ +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@[old] check-pass + +// Evaluate in the old solver does apply constraints from nested `Projection` obligations, +// as they can constrain otherwise unconstrained inference variables. This also allows +// `Projection` goals to otherwise influence its parent obligation by returning constraints +// from matching the impl header. +// +// The new solver entirely ignores region constraints from nested goals in the leak check. +// This is the one case where the the implementation of the new solver will actually weaken +// the leak check. + +trait ProjectStatic<'a> { + type Assoc; +} +impl ProjectStatic<'static> for () { + type Assoc = u32; +} + +trait RequiresProject<'a> {} +impl<'a, T: ProjectStatic<'a, Assoc = u32>> RequiresProject<'a> for T {} + +trait Pick {} +impl RequiresProject<'a>> Pick for T {} +impl Pick for T {} + +fn pick, U>() {} + +fn main() { + pick::<(), _>(); + //[next]~^ ERROR: type annotations needed +} From dc7db04ab19b66846f7f0d082495151b13593bd7 Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Thu, 24 Sep 2026 07:53:15 -0700 Subject: [PATCH 0795/1309] feedback --- .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 30 ++++++++++++------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 5c510a74078c2..303c0456833ad 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -480,9 +480,10 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, const char *Path, const char *DwoPath, LLVMRustFileType RustFileType, bool VerifyIR, bool DisableSimplifyLibCalls) { - llvm::legacy::PassManager PM; + std::unique_ptr PM = + std::make_unique(); - PM.add(createTargetTransformInfoWrapperPass( + PM->add(createTargetTransformInfoWrapperPass( unwrap(Target)->getTargetIRAnalysis())); auto TargetTriple = Triple(unwrap(M)->getTargetTriple()); @@ -490,13 +491,15 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, auto TLII = TargetLibraryInfoImpl(TargetTriple); if (DisableSimplifyLibCalls) TLII.disableAllFunctions(); - PM.add(new TargetLibraryInfoWrapperPass(TLII)); + PM->add(new TargetLibraryInfoWrapperPass(TLII)); #if LLVM_VERSION_GE(24, 0) - PM.add(new RuntimeLibraryInfoWrapper( - Options->ExceptionModel, Options->EABIVersion, Options->MCOptions.ABIName, - Options->VecLib)); + // LLVM 24 removed TargetOptions::EABIVersion and ExceptionModel; the EABI + // version and exception model are now derived from the target triple and + // module flags respectively instead. + PM->add(new RuntimeLibraryInfoWrapper(Options->MCOptions.ABIName, + Options->VecLib)); #elif LLVM_VERSION_GE(22, 0) - PM.add(new RuntimeLibraryInfoWrapper( + PM->add(new RuntimeLibraryInfoWrapper( TargetTriple, Options->ExceptionModel, Options->FloatABIType, Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib)); #endif @@ -524,13 +527,18 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, return LLVMRustResult::Failure; } auto DBOS = buffer_ostream(DOS); - unwrap(Target)->addPassesToEmitFile(PM, BOS, &DBOS, FileType, !VerifyIR); - PM.run(*unwrap(M)); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR); + PM->run(*unwrap(M)); } else { - unwrap(Target)->addPassesToEmitFile(PM, BOS, nullptr, FileType, !VerifyIR); - PM.run(*unwrap(M)); + unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR); + PM->run(*unwrap(M)); } + // TargetMachine::addPassesToEmitFile stores a pointer to the output stream + // in a couple of places inside of the object. Explicitly delete the PM here + // to ensure that the output stream always outlives the PM. + PM.reset(); + return LLVMRustResult::Success; } From 5f463ae6f6cfb8eaab1e9bae204bddc2ae87f48a Mon Sep 17 00:00:00 2001 From: Aiden Grossman Date: Thu, 24 Sep 2026 08:11:02 -0700 Subject: [PATCH 0796/1309] more lifetime fixes --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index 303c0456833ad..f73ca2ea30c16 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -516,6 +516,9 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, return LLVMRustResult::Failure; } + // TargetMachine::addPassesToEmitFile stores pointers to the output streams + // in a couple of places inside of the object. Explicitly delete the PM after + // we call run() to avoid dangling references. auto BOS = buffer_ostream(OS); if (DwoPath) { auto DOS = raw_fd_ostream(DwoPath, EC, sys::fs::OF_None); @@ -529,16 +532,13 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, auto DBOS = buffer_ostream(DOS); unwrap(Target)->addPassesToEmitFile(*PM, BOS, &DBOS, FileType, !VerifyIR); PM->run(*unwrap(M)); + PM.reset(); } else { unwrap(Target)->addPassesToEmitFile(*PM, BOS, nullptr, FileType, !VerifyIR); PM->run(*unwrap(M)); + PM.reset(); } - // TargetMachine::addPassesToEmitFile stores a pointer to the output stream - // in a couple of places inside of the object. Explicitly delete the PM here - // to ensure that the output stream always outlives the PM. - PM.reset(); - return LLVMRustResult::Success; } From a391456e06ca69e27fed704e3c597a608109aea1 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Tue, 15 Sep 2026 19:59:01 +0000 Subject: [PATCH 0797/1309] Split out RegionInferenceContext into an UnsolvedRegionInferenceContext --- compiler/rustc_borrowck/src/nll.rs | 22 +- .../rustc_borrowck/src/region_infer/mod.rs | 2 +- .../src/region_infer/region_context.rs | 2723 +++++++++-------- 3 files changed, 1394 insertions(+), 1353 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 00f28ecd1cfeb..31fa9dd2ee64e 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -26,7 +26,7 @@ use crate::polonius::PoloniusContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, }; -use crate::region_infer::RegionInferenceContext; +use crate::region_infer::{RegionInferenceContext, UnsolvedRegionInferenceContext}; use crate::type_check::MirTypeckRegionConstraints; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::universal_regions::UniversalRegions; @@ -96,14 +96,14 @@ pub(crate) fn compute_closure_requirements_modulo_opaques<'tcx>( &universal_region_relations, infcx, ); - let mut regioncx = RegionInferenceContext::new( + let regioncx = UnsolvedRegionInferenceContext::new( &infcx, lowered_constraints, universal_region_relations.clone(), location_map, ); - let (closure_region_requirements, _nll_errors) = regioncx.solve(infcx, body, None); + let (_, closure_region_requirements, _nll_errors) = regioncx.solve(infcx, body, None); closure_region_requirements } @@ -161,13 +161,6 @@ pub(crate) fn compute_regions<'tcx>( ); } - let mut regioncx = RegionInferenceContext::new( - infcx, - lowered_constraints, - universal_region_relations, - location_map, - ); - // If requested: dump NLL facts, and run legacy polonius analysis. let polonius_output = polonius_facts.as_ref().and_then(|polonius_facts| { if infcx.tcx.sess.opts.unstable_opts.nll_facts { @@ -189,8 +182,15 @@ pub(crate) fn compute_regions<'tcx>( } }); + let regioncx = UnsolvedRegionInferenceContext::new( + infcx, + lowered_constraints, + universal_region_relations, + location_map, + ); + // Solve the region constraints. - let (closure_region_requirements, nll_errors) = + let (regioncx, closure_region_requirements, nll_errors) = regioncx.solve(infcx, body, polonius_output.clone()); NllOutput { diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index 8c589113ad5b2..b547d24c7198c 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -261,7 +261,7 @@ fn sccs_info<'tcx>(infcx: &BorrowckInferCtxt<'tcx>, sccs: &ConstraintSccs) { #[derive(Clone, Debug)] pub(crate) struct BestBlame<'tcx> { - /// See docs on [`RegionInferenceContext::best_blame_constraint`] for what this is. + /// See docs on [`RegionInferenceContextInner::best_blame_constraint`] for what this is. path: Vec>, /// Index into `path` of the constraint most relevant to report to users. idx: usize, diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index a6a86a2d9cd0b..af0f48526b4fe 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -1,4 +1,5 @@ use std::collections::VecDeque; +use std::ops::{Deref, DerefMut}; use std::rc::Rc; use rustc_data_structures::frozen::Frozen; @@ -20,10 +21,10 @@ use tracing::{debug, instrument, trace}; use crate::constraints::graph::NormalConstraintGraph; use crate::constraints::{ConstraintSccIndex, OutlivesConstraint, OutlivesConstraintSet}; +use crate::consumers::PoloniusOutput; use crate::dataflow::BorrowIndex; use crate::diagnostics::{RegionErrorKind, RegionErrors, UniverseInfo}; use crate::handle_placeholders::{LoweredConstraints, RegionTracker}; -use crate::polonius::legacy::PoloniusOutput; use crate::region_infer::values::{LivenessValues, RegionElement, RegionValues}; use crate::region_infer::{ BestBlame, ConstraintSccs, RegionDefinition, RegionRelationCheckResult, Trace, TypeTest, @@ -37,7 +38,8 @@ use crate::{ ClosureOutlivesSubjectTy, ClosureRegionRequirements, }; -pub struct RegionInferenceContext<'tcx> { +/// Contains the data for `RegionInferenceContext` and `UnsolvedRegionInferenceContext`. +pub struct RegionInferenceContextInner<'tcx> { /// Contains the definition for every region variable. Region /// variables are identified by their index (`RegionVid`). The /// definition contains information about where the region came @@ -73,102 +75,49 @@ pub struct RegionInferenceContext<'tcx> { /// you first find which scc it is a part of. pub(super) scc_values: RegionValues<'tcx, ConstraintSccIndex>, - /// Type constraints that we check after solving. - pub(super) type_tests: Vec>, - /// Information about how the universally quantified regions in /// scope on this function relate to one another. pub(super) universal_region_relations: Frozen>, } -impl<'tcx> RegionInferenceContext<'tcx> { - /// Creates a new region inference context with a total of - /// `num_region_variables` valid inference variables; the first N - /// of those will be constant regions representing the free - /// regions defined in `universal_regions`. - /// - /// The `outlives_constraints` and `type_tests` are an initial set - /// of constraints produced by the MIR type check. - pub(crate) fn new( - infcx: &BorrowckInferCtxt<'tcx>, - lowered_constraints: LoweredConstraints<'tcx>, - universal_region_relations: Frozen>, - location_map: Rc, - ) -> Self { - let universal_regions = &universal_region_relations.universal_regions; - - let LoweredConstraints { - constraint_sccs, - definitions, - outlives_constraints, - scc_annotations, - type_tests, - liveness_constraints, - universe_causes, - placeholder_indices, - } = lowered_constraints; - - debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); - debug!("outlives constraints: {:#?}", outlives_constraints); - debug!("placeholder_indices: {:#?}", placeholder_indices); - debug!("type tests: {:#?}", type_tests); - - let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); - - if cfg!(debug_assertions) { - sccs_info(infcx, &constraint_sccs); - } +/// This contains data around region constraints and liveness, up to and after solving. +/// All data is immutable. +pub struct RegionInferenceContext<'tcx> { + data: Frozen>, +} - let mut scc_values = - RegionValues::new(location_map, universal_regions.len(), placeholder_indices); +impl<'tcx> Deref for RegionInferenceContext<'tcx> { + type Target = RegionInferenceContextInner<'tcx>; - // Initializes the region variables with their initial live points. - for (region, definition) in definitions.iter_enumerated() { - let scc = constraint_sccs.scc(region); + fn deref(&self) -> &Self::Target { + &self.data + } +} - // For each universally quantified region (lifetime parameter). The - // first N variables always correspond to the regions appearing in the - // function signature (both named and anonymous) and in where-clauses. - match definition.origin { - // For each free, universally quantified region X: - NllRegionVariableOrigin::FreeRegion => { - // Add `end(X)` into the set for X. - scc_values.add_free_region(scc, region); - } +/// This contains data around region constraints and liveness, up to solving. +/// Calling `solve` returns a new immutable `RegionInferenceContext`. +pub(crate) struct UnsolvedRegionInferenceContext<'tcx> { + pub(super) data: RegionInferenceContextInner<'tcx>, - NllRegionVariableOrigin::Placeholder(placeholder) => { - scc_values.add_placeholder(scc, placeholder); - } + /// Type constraints that we check after solving. + pub(super) type_tests: Vec>, +} - NllRegionVariableOrigin::Existential { .. } => { - // For existential, regions, nothing to do. - } - } +impl<'tcx> Deref for UnsolvedRegionInferenceContext<'tcx> { + type Target = RegionInferenceContextInner<'tcx>; - // Initially copy the liveness constraints of any region that - // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. - // - // These values will later be propagated during [`Self::propagate_constraints()`]. - // The values include any live-at-all-points constraints added previously in `liveness::generate`. - if let Some(liveness) = liveness_constraints.point_liveness(region) { - scc_values.merge_liveness(scc, liveness) - } - } + fn deref(&self) -> &Self::Target { + &self.data + } +} - Self { - definitions, - liveness_constraints, - constraints: outlives_constraints, - constraint_graph, - constraint_sccs, - scc_annotations, - universe_causes, - scc_values, - type_tests, - universal_region_relations, - } +impl<'tcx> DerefMut for UnsolvedRegionInferenceContext<'tcx> { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.data } +} +impl<'tcx> RegionInferenceContextInner<'tcx> { /// Returns an iterator over all the region indices. pub(crate) fn regions(&self) -> impl Iterator + 'tcx { self.definitions.indices() @@ -230,124 +179,735 @@ impl<'tcx> RegionInferenceContext<'tcx> { self.scc_values.placeholders_contained_in(scc) } - /// Performs region inference and report errors if we see any - /// unsatisfiable constraints. If this is a closure, returns the - /// region requirements to propagate to our creator, if any. - #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] - pub(crate) fn solve( - &mut self, - infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, - polonius_output: Option>, - ) -> (Option>, RegionErrors<'tcx>) { - let mir_def_id = body.source.def_id(); - self.propagate_constraints(); - - let mut errors_buffer = RegionErrors::new(infcx.tcx); - - // If this is a nested body, we propagate unsatisfied - // outlives constraints to the parent body instead of - // eagerly erroing. - let mut propagated_outlives_requirements = - infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - - self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); - - debug!(?errors_buffer); - debug!(?propagated_outlives_requirements); + /// Like `universal_upper_bound`, but returns an approximation more suitable + /// for diagnostics. If `r` contains multiple disjoint universal regions + /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. + /// This corresponds to picking named regions over unnamed regions + /// (e.g. picking early-bound regions over a closure late-bound region). + /// + /// This means that the returned value may not be a true upper bound, since + /// only 'static is known to outlive disjoint universal regions. + /// Therefore, this method should only be used in diagnostic code, + /// where displaying *some* named universal region is better than + /// falling back to 'static. + #[instrument(level = "debug", skip(self))] + pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { + debug!("{}", self.region_value_str(r)); - // In Polonius mode, the errors about missing universal region relations are in the output - // and need to be emitted or propagated. Otherwise, we need to check whether the - // constraints were too strong, and if so, emit or propagate those errors. - if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { - self.check_polonius_subset_errors( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - polonius_output - .as_ref() - .expect("Polonius output is unavailable despite `-Z polonius`"), - ); - } else { - self.check_universal_regions( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - ); + // Find the smallest universal region that contains all other + // universal regions within `region`. + let mut lub = self.universal_regions().fr_fn_body; + let r_scc = self.constraint_sccs.scc(r); + let static_r = self.universal_regions().fr_static; + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur); + debug!(?ur, ?lub, ?new_lub); + // The upper bound of two non-static regions is static: this + // means we know nothing about the relationship between these + // two regions. Pick a 'better' one to use when constructing + // a diagnostic + if ur != static_r && lub != static_r && new_lub == static_r { + // Prefer the region with an `external_name` - this + // indicates that the region is early-bound, so working with + // it can produce a nicer error. + if self.region_definition(ur).external_name.is_some() { + lub = ur; + } else if self.region_definition(lub).external_name.is_some() { + // Leave lub unchanged + } else { + // If we get here, we don't have any reason to prefer + // one region over the other. Just pick the + // one with the lower index for now. + lub = std::cmp::min(ur, lub); + } + } else { + lub = new_lub; + } } - debug!(?errors_buffer); - - let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); + debug!(?r, ?lub); - if propagated_outlives_requirements.is_empty() { - (None, errors_buffer) - } else { - let num_external_vids = self.universal_regions().num_global_and_external_regions(); - ( - Some(ClosureRegionRequirements { - num_external_vids, - outlives_requirements: propagated_outlives_requirements, - }), - errors_buffer, - ) - } + lub } - /// Propagate the region constraints: this will grow the values - /// for each region variable until all the constraints are - /// satisfied. Note that some values may grow **too** large to be - /// feasible, but we check this later. - #[instrument(skip(self), level = "debug")] - fn propagate_constraints(&mut self) { - debug!("constraints={:#?}", { - let mut constraints: Vec<_> = self.outlives_constraints().collect(); - constraints.sort_by_key(|c| (c.sup, c.sub)); - constraints - .into_iter() - .map(|c| (c, self.constraint_sccs.scc(c.sup), self.constraint_sccs.scc(c.sub))) - .collect::>() - }); - - // To propagate constraints, we walk the DAG induced by the - // SCC. For each SCC `A`, we visit its successors and compute - // their values, then we union all those values to get our - // own. This one-shot approach works because iteration is in - // dependency order. I.e. a chain A: B: C will visit C, B, A. - for scc_a in self.constraint_sccs.all_sccs() { - // Walk each SCC `B` such that `A: B`... - for &scc_b in self.constraint_sccs.successors(scc_a) { - debug!(?scc_b); - self.scc_values.add_region(scc_a, scc_b); - } - } + /// The largest universe of any region nameable from this SCC. + pub(super) fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex { + self.scc_annotations[scc].max_nameable_universe() } - /// Returns `true` if all the placeholders in the value of `scc_b` are nameable - /// in `scc_a`. Used during constraint propagation, and only once - /// the value of `scc_b` has been computed. - fn can_name_all_placeholders( + pub(crate) fn constraint_path_between_regions( &self, - scc_a: ConstraintSccIndex, - scc_b: ConstraintSccIndex, - ) -> bool { - self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) + from_region: RegionVid, + to_region: RegionVid, + ) -> Option>> { + if from_region == to_region { + bug!("Tried to find a path between {from_region:?} and itself!"); + } + self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0) } - /// Once regions have been propagated, this method is used to see - /// whether the "type tests" produced by typeck were satisfied; - /// type tests encode type-outlives relationships like `T: - /// 'a`. See `TypeTest` for more details. - fn check_type_tests( + /// Walks the graph of constraints (where `'a: 'b` is considered + /// an edge `'a -> 'b`) to find a path from `from_region` to + /// `to_region`. + /// + /// Returns: a series of constraints as well as the region `R` + /// that passed the target test. + /// If `include_static_outlives_all` is `true`, then the synthetic + /// outlives constraints `'static -> a` for every region `a` are + /// considered in the search, otherwise they are ignored. + #[instrument(skip(self, target_test), ret)] + pub(crate) fn constraint_path_to( &self, - infcx: &InferCtxt<'tcx>, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - let tcx = infcx.tcx; - - // Sometimes we register equivalent type-tests that would - // result in basically the exact same error being reported to - // the user. Avoid that. - let mut deduplicate_errors = FxIndexSet::default(); + from_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, + ) -> Option<(Vec>, RegionVid)> { + self.find_constraint_path_between_regions_inner( + true, + from_region, + &target_test, + include_placeholder_static, + ) + .or_else(|| { + self.find_constraint_path_between_regions_inner( + false, + from_region, + &target_test, + include_placeholder_static, + ) + }) + } + + /// The constraints we get from equating the hidden type of each use of an opaque + /// with its final hidden type may end up getting preferred over other, potentially + /// longer constraint paths. + /// + /// Given that we compute the final hidden type by relying on this existing constraint + /// path, this can easily end up hiding the actual reason for why we require these regions + /// to be equal. + /// + /// To handle this, we first look at the path while ignoring these constraints and then + /// retry while considering them. This is not perfect, as the `from_region` may have already + /// been partially related to its argument region, so while we rely on a member constraint + /// to get a complete path, the most relevant step of that path already existed before then. + fn find_constraint_path_between_regions_inner( + &self, + ignore_opaque_type_constraints: bool, + from_region: RegionVid, + target_test: impl Fn(RegionVid) -> bool, + include_placeholder_static: bool, + ) -> Option<(Vec>, RegionVid)> { + let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); + context[from_region] = Trace::StartRegion; + + let fr_static = self.universal_regions().fr_static; + + // Use a deque so that we do a breadth-first search. We will + // stop at the first match, which ought to be the shortest + // path (fewest constraints). + let mut deque = VecDeque::new(); + deque.push_back(from_region); + + while let Some(r) = deque.pop_front() { + debug!( + "constraint_path_to: from_region={:?} r={:?} value={}", + from_region, + r, + self.region_value_str(r), + ); + + // Check if we reached the region we were looking for. If so, + // we can reconstruct the path that led to it and return it. + if target_test(r) { + let mut result = vec![]; + let mut p = r; + // This loop is cold and runs at the end, which is why we delay + // `OutlivesConstraint` construction until now. + loop { + match context[p] { + Trace::FromGraph(c) => { + p = c.sup; + result.push(*c); + } + + Trace::FromStatic(sub) => { + let c = OutlivesConstraint { + sup: fr_static, + sub, + locations: Locations::All(DUMMY_SP), + span: DUMMY_SP, + category: ConstraintCategory::Internal, + variance_info: ty::VarianceDiagInfo::default(), + from_closure: false, + }; + p = c.sup; + result.push(c); + } + + Trace::StartRegion => { + result.reverse(); + return Some((result, r)); + } + + Trace::NotVisited => { + bug!("found unvisited region {:?} on path to {:?}", p, r) + } + } + } + } + + // Otherwise, walk over the outgoing constraints and + // enqueue any regions we find, keeping track of how we + // reached them. + + // A constraint like `'r: 'x` can come from our constraint + // graph. + + // Always inline this closure because it can be hot. + let mut handle_trace = #[inline(always)] + |sub, trace| { + if let Trace::NotVisited = context[sub] { + context[sub] = trace; + deque.push_back(sub); + } + }; + + // If this is the `'static` region and the graph's direction is normal, then set up the + // Edges iterator to return all regions (#53178). + if r == fr_static && self.constraint_graph.is_normal() { + for sub in self.constraint_graph.outgoing_edges_from_static() { + handle_trace(sub, Trace::FromStatic(sub)); + } + } else { + let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints); + // This loop can be hot. + for constraint in edges { + match constraint.category { + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + if !include_placeholder_static => + { + debug!("Ignoring illegal placeholder constraint: {constraint:?}"); + continue; + } + ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => { + debug!("Ignoring member constraint: {constraint:?}"); + continue; + } + _ => {} + } + + debug_assert_eq!(constraint.sup, r); + handle_trace(constraint.sub, Trace::FromGraph(constraint)); + } + } + } + + None + } + + /// Finds some region R such that `fr1: R` and `R` is live at `location`. + #[instrument(skip(self), level = "trace", ret)] + pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { + trace!(scc = ?self.constraint_sccs.scc(fr1)); + trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1))); + self.constraint_path_to(fr1, |r| { + trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); + self.liveness_constraints.is_live_at(r, location) + }, true).unwrap().1 + } + + /// Get the region definition of `r`. + pub(crate) fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { + &self.definitions[r] + } + + /// Check if the SCC of `r` contains `upper`, a free region. + pub(crate) fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { + let r_scc = self.constraint_sccs.scc(r); + self.scc_values.contains_free_region(r_scc, upper) + } + + pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> { + &self.universal_region_relations.universal_regions + } + + /// Tries to find the best constraint to blame for the fact that + /// `R: from_region`, where `R` is some region that meets + /// `target_test`. This works by following the constraint graph, + /// creating a constraint path that forces `R` to outlive + /// `from_region`, and then finding the best choices within that + /// path to blame. + #[instrument(level = "debug", skip(self))] + pub(crate) fn best_blame_constraint( + &self, + from_region: RegionVid, + from_region_origin: NllRegionVariableOrigin<'tcx>, + to_region: RegionVid, + ) -> BestBlame<'tcx> { + assert!(from_region != to_region, "Trying to blame a region for itself!"); + + let path = self.constraint_path_between_regions(from_region, to_region).unwrap(); + + // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`, + // redirect search towards `'unnameable`. + let due_to_placeholder_outlives = path.iter().find_map(|c| { + if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category { + Some(unnameable) + } else { + None + } + }); + + // Edge case: it's possible that `'from_region` is an unnameable placeholder. + let mut path = if let Some(unnameable) = due_to_placeholder_outlives + && unnameable != from_region + { + // We ignore the extra edges due to unnameable placeholders to get + // an explanation that was present in the original constraint graph. + self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0 + } else { + path + }; + + debug!( + "path={:#?}", + path.iter() + .map(|c| format!( + "{:?} ({:?}: {:?})", + c, + self.constraint_sccs.scc(c.sup), + self.constraint_sccs.scc(c.sub), + )) + .collect::>() + ); + + // When reporting an error, there is typically a chain of constraints leading from some + // "source" region which must outlive some "target" region. + // In most cases, we prefer to "blame" the constraints closer to the target -- + // but there is one exception. When constraints arise from higher-ranked subtyping, + // we generally prefer to blame the source value, + // as the "target" in this case tends to be some type annotation that the user gave. + // Therefore, if we find that the region origin is some instantiation + // of a higher-ranked region, we start our search from the "source" point + // rather than the "target", and we also tweak a few other things. + // + // An example might be this bit of Rust code: + // + // ```rust + // let x: fn(&'static ()) = |_| {}; + // let y: for<'a> fn(&'a ()) = x; + // ``` + // + // In MIR, this will be converted into a combination of assignments and type ascriptions. + // In particular, the 'static is imposed through a type ascription: + // + // ```rust + // x = ...; + // AscribeUserType(x, fn(&'static ()) + // y = x; + // ``` + // + // We wind up ultimately with constraints like + // + // ```rust + // !a: 'temp1 // from the `y = x` statement + // 'temp1: 'temp2 + // 'temp2: 'static // from the AscribeUserType + // ``` + // + // and here we prefer to blame the source (the y = x statement). + let blame_source = match from_region_origin { + NllRegionVariableOrigin::FreeRegion => true, + NllRegionVariableOrigin::Placeholder(_) => false, + // `'existential: 'whatever` never results in a region error by itself. + // We may always infer it to `'static` afterall. This means while an error + // path may go through an existential, these existentials are never the + // `from_region`. + NllRegionVariableOrigin::Existential { name: _ } => { + unreachable!("existentials can outlive everything") + } + }; + + // To pick a constraint to blame, we organize constraints by how interesting we expect them + // to be in diagnostics, then pick the most interesting one closest to either the source or + // the target on our constraint path. + let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| { + // Try to avoid blaming constraints from desugarings, since they may not clearly match + // match what users have written. As an exception, allow blaming returns generated by + // `?` desugaring, since the correspondence is fairly clear. + let category = if let Some(kind) = constraint.span.desugaring_kind() + && (kind != DesugaringKind::QuestionMark + || !matches!(constraint.category, ConstraintCategory::Return(_))) + { + ConstraintCategory::Boring + } else { + constraint.category + }; + + let interest = match category { + // Returns usually provide a type to blame and have specially written diagnostics, + // so prioritize them. + ConstraintCategory::Return(_) => 0, + // Unsizing coercions are interesting, since we have a note for that: + // `BorrowExplanation::add_object_lifetime_default_note`. + // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue + // #131008 for an example of where we currently don't emit it but should. + // Once the note is handled properly, this case should be removed. Until then, it + // should be as limited as possible; the note is prone to false positives and this + // constraint usually isn't best to blame. + ConstraintCategory::Cast { + is_raw_ptr_dyn_type_cast: _, + unsize_to: Some(unsize_ty), + is_implicit_coercion: true, + } if to_region == self.universal_regions().fr_static + // Mirror the note's condition, to minimize how often this diverts blame. + && let ty::Adt(_, args) = unsize_ty.kind() + && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) + // Mimic old logic for this, to minimize false positives in tests. + && !path + .iter() + .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) => + { + 1 + } + // Between other interesting constraints, order by their position on the `path`. + ConstraintCategory::Yield + | ConstraintCategory::UseAsConst + | ConstraintCategory::UseAsStatic + | ConstraintCategory::TypeAnnotation( + AnnotationSource::Ascription + | AnnotationSource::Declaration + | AnnotationSource::OpaqueCast, + ) + | ConstraintCategory::Cast { .. } + | ConstraintCategory::CallArgument(_) + | ConstraintCategory::CopyBound + | ConstraintCategory::SizedBound + | ConstraintCategory::Assignment + | ConstraintCategory::Usage + | ConstraintCategory::ClosureUpvar(_) => 2, + // Generic arguments are unlikely to be what relates regions together + ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, + // We handle predicates and opaque types specially; don't prioritize them here. + ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, + // `Boring` constraints can correspond to user-written code and have useful spans, + // but don't provide any other useful information for diagnostics. + ConstraintCategory::Boring => 5, + // `BoringNoLocation` constraints can point to user-written code, but are less + // specific, and are not used for relations that would make sense to blame. + ConstraintCategory::BoringNoLocation => 6, + // Do not blame internal constraints if we can avoid it. Never blame + // the `'region: 'static` constraints introduced by placeholder outlives. + ConstraintCategory::Internal => 7, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8, + ConstraintCategory::SolverRegionConstraint(_) => 9, + }; + + debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); + + interest + }; + + let best_choice = if blame_source { + path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 + } else { + path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 + }; + + debug!(?best_choice, ?blame_source); + + let best_blame_idx = if let Some(next) = path.get(best_choice + 1) + && matches!(path[best_choice].category, ConstraintCategory::Return(_)) + && next.category == ConstraintCategory::OpaqueType + { + // The return expression is being influenced by the return type being + // impl Trait, point at the return type and not the return expr. + best_choice + 1 + } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal) + && let Some(field) = path.iter().find_map(|p| { + if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None } + }) + { + path[best_choice].category = + ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); + best_choice + } else { + best_choice + }; + + assert!( + !matches!( + path[best_blame_idx].category, + ConstraintCategory::OutlivesUnnameablePlaceholder(_) + ), + "Illegal placeholder constraint blamed; should have redirected to other region relation" + ); + + BestBlame { path, idx: best_blame_idx } + } + + pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { + // Query canonicalization can create local superuniverses (for example in + // `InferCtx::query_response_instantiation_guess`), but they don't have an associated + // `UniverseInfo` explaining why they were created. + // This can cause ICEs if these causes are accessed in diagnostics, for example in issue + // #114907 where this happens via liveness and dropck outlives results. + // Therefore, we return a default value in case that happens, which should at worst emit a + // suboptimal error, instead of the ICE. + self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other) + } + + /// Tries to find the terminator of the loop in which the region 'r' resides. + /// Returns the location of the terminator if found. + pub(crate) fn find_loop_terminator_location( + &self, + r: RegionVid, + body: &Body<'_>, + ) -> Option { + let scc = self.constraint_sccs.scc(r); + let locations = self.scc_values.locations_outlived_by(scc); + for location in locations { + let bb = &body[location.block]; + if let Some(terminator) = &bb.terminator + // terminator of a loop should be TerminatorKind::FalseUnwind + && let TerminatorKind::FalseUnwind { .. } = terminator.kind + { + return Some(location); + } + } + None + } + + /// Access to the SCC constraint graph. + /// This can be used to quickly under-approximate the regions which are equal to each other + /// and their relative orderings. + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + pub(crate) fn constraint_sccs(&self) -> &ConstraintSccs { + &self.constraint_sccs + } + + pub(crate) fn liveness_constraints(&self) -> &LivenessValues { + &self.liveness_constraints + } + + /// Returns whether the `loan_idx` is live at the given `location`: whether its issuing + /// region is contained within the type of a variable that is live at this point. + /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. + pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { + let point = self.liveness_constraints.point_from_location(location); + self.liveness_constraints.is_loan_live_at(loan_idx, point) + } +} + +impl<'tcx> UnsolvedRegionInferenceContext<'tcx> { + /// Creates a new region inference context with a total of + /// `num_region_variables` valid inference variables; the first N + /// of those will be constant regions representing the free + /// regions defined in `universal_regions`. + /// + /// The `outlives_constraints` and `type_tests` are an initial set + /// of constraints produced by the MIR type check. + pub(crate) fn new( + infcx: &BorrowckInferCtxt<'tcx>, + lowered_constraints: LoweredConstraints<'tcx>, + universal_region_relations: Frozen>, + location_map: Rc, + ) -> Self { + let universal_regions = &universal_region_relations.universal_regions; + + let LoweredConstraints { + constraint_sccs, + definitions, + outlives_constraints, + scc_annotations, + type_tests, + liveness_constraints, + universe_causes, + placeholder_indices, + } = lowered_constraints; + + debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); + debug!("outlives constraints: {:#?}", outlives_constraints); + debug!("placeholder_indices: {:#?}", placeholder_indices); + debug!("type tests: {:#?}", type_tests); + + let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); + + if cfg!(debug_assertions) { + sccs_info(infcx, &constraint_sccs); + } + + let mut scc_values = + RegionValues::new(location_map, universal_regions.len(), placeholder_indices); + + // Initializes the region variables with their initial live points. + for (region, definition) in definitions.iter_enumerated() { + let scc = constraint_sccs.scc(region); + + // For each universally quantified region (lifetime parameter). The + // first N variables always correspond to the regions appearing in the + // function signature (both named and anonymous) and in where-clauses. + match definition.origin { + // For each free, universally quantified region X: + NllRegionVariableOrigin::FreeRegion => { + // Add `end(X)` into the set for X. + scc_values.add_free_region(scc, region); + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + scc_values.add_placeholder(scc, placeholder); + } + + NllRegionVariableOrigin::Existential { .. } => { + // For existential, regions, nothing to do. + } + } + + // Initially copy the liveness constraints of any region that + // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. + // + // These values will later be propagated during [`Self::propagate_constraints()`]. + // The values include any live-at-all-points constraints added previously in `liveness::generate`. + if let Some(liveness) = liveness_constraints.point_liveness(region) { + scc_values.merge_liveness(scc, liveness) + } + } + + Self { + data: RegionInferenceContextInner { + definitions, + liveness_constraints, + constraints: outlives_constraints, + constraint_graph, + constraint_sccs, + scc_annotations, + universe_causes, + universal_region_relations, + scc_values, + }, + type_tests, + } + } + + /// Performs region inference and report errors if we see any + /// unsatisfiable constraints. If this is a closure, returns the + /// region requirements to propagate to our creator, if any. + #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] + pub(crate) fn solve( + mut self, + infcx: &InferCtxt<'tcx>, + body: &Body<'tcx>, + polonius_output: Option>, + ) -> (RegionInferenceContext<'tcx>, Option>, RegionErrors<'tcx>) + { + let mir_def_id = body.source.def_id(); + self.propagate_constraints(); + + let mut errors_buffer = RegionErrors::new(infcx.tcx); + + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + + self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); + + debug!(?errors_buffer); + debug!(?propagated_outlives_requirements); + + // In Polonius mode, the errors about missing universal region relations are in the output + // and need to be emitted or propagated. Otherwise, we need to check whether the + // constraints were too strong, and if so, emit or propagate those errors. + if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { + self.check_polonius_subset_errors( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + polonius_output + .as_ref() + .expect("Polonius output is unavailable despite `-Z polonius`"), + ); + } else { + self.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); + } + + debug!(?errors_buffer); + + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); + if propagated_outlives_requirements.is_empty() { + (RegionInferenceContext { data: Frozen::freeze(self.data) }, None, errors_buffer) + } else { + let num_external_vids = self.universal_regions().num_global_and_external_regions(); + ( + RegionInferenceContext { data: Frozen::freeze(self.data) }, + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), + errors_buffer, + ) + } + } + + /// Propagate the region constraints: this will grow the values + /// for each region variable until all the constraints are + /// satisfied. Note that some values may grow **too** large to be + /// feasible, but we check this later. + #[instrument(skip(self), level = "debug")] + fn propagate_constraints(&mut self) { + debug!("constraints={:#?}", { + let mut constraints: Vec<_> = self.outlives_constraints().collect(); + constraints.sort_by_key(|c| (c.sup, c.sub)); + constraints + .into_iter() + .map(|c| (c, self.constraint_sccs.scc(c.sup), self.constraint_sccs.scc(c.sub))) + .collect::>() + }); + + // To propagate constraints, we walk the DAG induced by the + // SCC. For each SCC `A`, we visit its successors and compute + // their values, then we union all those values to get our + // own. This one-shot approach works because iteration is in + // dependency order. I.e. a chain A: B: C will visit C, B, A. + for scc_a in self.constraint_sccs.all_sccs() { + // Walk each SCC `B` such that `A: B`... + for &scc_b in self.data.constraint_sccs.successors(scc_a) { + debug!(?scc_b); + self.data.scc_values.add_region(scc_a, scc_b); + } + } + } + + /// Returns `true` if all the placeholders in the value of `scc_b` are nameable + /// in `scc_a`. Used during constraint propagation, and only once + /// the value of `scc_b` has been computed. + fn can_name_all_placeholders( + &self, + scc_a: ConstraintSccIndex, + scc_b: ConstraintSccIndex, + ) -> bool { + self.scc_annotations[scc_a].can_name_all_placeholders(self.scc_annotations[scc_b]) + } + + /// Once regions have been propagated, this method is used to see + /// whether the "type tests" produced by typeck were satisfied; + /// type tests encode type-outlives relationships like `T: + /// 'a`. See `TypeTest` for more details. + fn check_type_tests( + &self, + infcx: &InferCtxt<'tcx>, + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + let tcx = infcx.tcx; + + // Sometimes we register equivalent type-tests that would + // result in basically the exact same error being reported to + // the user. Avoid that. + let mut deduplicate_errors = FxIndexSet::default(); let mut failed_type_tests = Vec::new(); for type_test in &self.type_tests { @@ -397,1254 +957,747 @@ impl<'tcx> RegionInferenceContext<'tcx> { .collect(); // If `G: 'static` failed at this span, then same-span `G: 'a` failures are weaker. - for (erased_generic_kind, type_test) in failed_type_tests { - if self.constraint_sccs.scc(type_test.lower_bound) != static_scc - && static_bound_errors.contains(&(erased_generic_kind, type_test.span)) - { - continue; - } - - // Skip duplicate-ish errors. - if deduplicate_errors.insert(( - erased_generic_kind, - type_test.lower_bound, - type_test.span, - )) { - debug!( - "check_type_test: reporting error for erased_generic_kind={:?}, \ - lower_bound_region={:?}, \ - type_test.span={:?}", - erased_generic_kind, type_test.lower_bound, type_test.span, - ); - - errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); - } - } - } - - /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot - /// prove to be satisfied. If this is a closure, we will attempt to - /// "promote" this type-test into our `ClosureRegionRequirements` and - /// hence pass it up the creator. To do this, we have to phrase the - /// type-test in terms of external free regions, as local free - /// regions are not nameable by the closure's creator. - /// - /// Promotion works as follows: we first check that the type `T` - /// contains only regions that the creator knows about. If this is - /// true, then -- as a consequence -- we know that all regions in - /// the type `T` are free regions that outlive the closure body. If - /// false, then promotion fails. - /// - /// Once we've promoted T, we have to "promote" `'X` to some region - /// that is "external" to the closure. Generally speaking, a region - /// may be the union of some points in the closure body as well as - /// various free lifetimes. We can ignore the points in the closure - /// body: if the type T can be expressed in terms of external regions, - /// we know it outlives the points in the closure body. That - /// just leaves the free regions. - /// - /// The idea then is to lower the `T: 'X` constraint into multiple - /// bounds -- e.g., if `'X` is the union of two free lifetimes, - /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. - #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] - fn try_promote_type_test( - &self, - infcx: &InferCtxt<'tcx>, - type_test: &TypeTest<'tcx>, - propagated_outlives_requirements: &mut Vec>, - ) -> bool { - let tcx = infcx.tcx; - let TypeTest { generic_kind, lower_bound, span: blame_span, verify_bound: _ } = *type_test; - - let generic_ty = generic_kind.to_ty(tcx); - let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { - return false; - }; - - let r_scc = self.constraint_sccs.scc(lower_bound); - debug!( - "lower_bound = {:?} r_scc={:?} universe={:?}", - lower_bound, - r_scc, - self.max_nameable_universe(r_scc) - ); - // If the type test requires that `T: 'a` where `'a` is a - // placeholder from another universe, that effectively requires - // `T: 'static`, so we have to propagate that requirement. - // - // It doesn't matter *what* universe because the promoted `T` will - // always be in the root universe. - if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { - debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); - let static_r = self.universal_regions().fr_static; - propagated_outlives_requirements.push(ClosureOutlivesRequirement { - subject, - outlived_free_region: static_r, - blame_span, - category: ConstraintCategory::Boring, - }); - - // we can return here -- the code below might push add'l constraints - // but they would all be weaker than this one. - return true; - } - - // For each region outlived by lower_bound find a non-local, - // universal region (it may be the same region) and add it to - // `ClosureOutlivesRequirement`. - let mut found_outlived_universal_region = false; - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - found_outlived_universal_region = true; - debug!("universal_region_outlived_by ur={:?}", ur); - let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); - debug!(?non_local_ub); - - // This is slightly too conservative. To show T: '1, given `'2: '1` - // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to - // avoid potential non-determinism we approximate this by requiring - // T: '1 and T: '2. - for upper_bound in non_local_ub { - debug_assert!(self.universal_regions().is_universal_region(upper_bound)); - debug_assert!(!self.universal_regions().is_local_free_region(upper_bound)); - - let requirement = ClosureOutlivesRequirement { - subject, - outlived_free_region: upper_bound, - blame_span, - category: ConstraintCategory::Boring, - }; - debug!(?requirement, "adding closure requirement"); - propagated_outlives_requirements.push(requirement); - } - } - // If we succeed to promote the subject, i.e. it only contains non-local regions, - // and fail to prove the type test inside of the closure, the `lower_bound` has to - // also be at least as large as some universal region, as the type test is otherwise - // trivial. - assert!(found_outlived_universal_region); - true - } - - /// When we promote a type test `T: 'r`, we have to replace all region - /// variables in the type `T` with an equal universal region from the - /// closure signature. - /// This is not always possible, so this is a fallible process. - #[instrument(level = "debug", skip(self, infcx), ret)] - fn try_promote_type_test_subject( - &self, - infcx: &InferCtxt<'tcx>, - ty: Ty<'tcx>, - ) -> Option> { - let tcx = infcx.tcx; - let mut failed = false; - let ty = fold_regions(tcx, ty, |r, _depth| { - let r_vid = self.to_region_vid(r); - let r_scc = self.constraint_sccs.scc(r_vid); - - // The challenge is this. We have some region variable `r` - // whose value is a set of CFG points and universal - // regions. We want to find if that set is *equivalent* to - // any of the named regions found in the closure. - // To do so, we simply check every candidate `u_r` for equality. - self.scc_values - .universal_regions_outlived_by(r_scc) - .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r)) - .find(|&u_r| self.eval_equal(u_r, r_vid)) - .map(|u_r| ty::Region::new_var(tcx, u_r)) - // In case we could not find a named region to map to, - // we will return `None` below. - .unwrap_or_else(|| { - failed = true; - r - }) - }); - - debug!("try_promote_type_test_subject: folded ty = {:?}", ty); - - // This will be true if we failed to promote some region. - if failed { - return None; - } - - Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) - } - - /// Like `universal_upper_bound`, but returns an approximation more suitable - /// for diagnostics. If `r` contains multiple disjoint universal regions - /// (e.g. 'a and 'b in `fn foo<'a, 'b> { ... }`, we pick the lower-numbered region. - /// This corresponds to picking named regions over unnamed regions - /// (e.g. picking early-bound regions over a closure late-bound region). - /// - /// This means that the returned value may not be a true upper bound, since - /// only 'static is known to outlive disjoint universal regions. - /// Therefore, this method should only be used in diagnostic code, - /// where displaying *some* named universal region is better than - /// falling back to 'static. - #[instrument(level = "debug", skip(self))] - pub(crate) fn approx_universal_upper_bound(&self, r: RegionVid) -> RegionVid { - debug!("{}", self.region_value_str(r)); - - // Find the smallest universal region that contains all other - // universal regions within `region`. - let mut lub = self.universal_regions().fr_fn_body; - let r_scc = self.constraint_sccs.scc(r); - let static_r = self.universal_regions().fr_static; - for ur in self.scc_values.universal_regions_outlived_by(r_scc) { - let new_lub = self.universal_region_relations.postdom_upper_bound(lub, ur); - debug!(?ur, ?lub, ?new_lub); - // The upper bound of two non-static regions is static: this - // means we know nothing about the relationship between these - // two regions. Pick a 'better' one to use when constructing - // a diagnostic - if ur != static_r && lub != static_r && new_lub == static_r { - // Prefer the region with an `external_name` - this - // indicates that the region is early-bound, so working with - // it can produce a nicer error. - if self.region_definition(ur).external_name.is_some() { - lub = ur; - } else if self.region_definition(lub).external_name.is_some() { - // Leave lub unchanged - } else { - // If we get here, we don't have any reason to prefer - // one region over the other. Just pick the - // one with the lower index for now. - lub = std::cmp::min(ur, lub); - } - } else { - lub = new_lub; - } - } - - debug!(?r, ?lub); - - lub - } - - /// Tests if `test` is true when applied to `lower_bound` at - /// `point`. - fn eval_verify_bound( - &self, - infcx: &InferCtxt<'tcx>, - generic_ty: Ty<'tcx>, - lower_bound: RegionVid, - verify_bound: &VerifyBound<'tcx>, - ) -> bool { - debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound); - - match verify_bound { - VerifyBound::IfEq(verify_if_eq_b) => { - self.eval_if_eq(infcx, generic_ty, lower_bound, *verify_if_eq_b) - } - - VerifyBound::IsEmpty => { - let lower_bound_scc = self.constraint_sccs.scc(lower_bound); - self.scc_values.elements_contained_in(lower_bound_scc).next().is_none() - } - - VerifyBound::OutlivedBy(r) => { - let r_vid = self.to_region_vid(*r); - self.eval_outlives(r_vid, lower_bound) + for (erased_generic_kind, type_test) in failed_type_tests { + if self.constraint_sccs.scc(type_test.lower_bound) != static_scc + && static_bound_errors.contains(&(erased_generic_kind, type_test.span)) + { + continue; } - VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { - self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) - }), - - VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { - self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) - }), - } - } + // Skip duplicate-ish errors. + if deduplicate_errors.insert(( + erased_generic_kind, + type_test.lower_bound, + type_test.span, + )) { + debug!( + "check_type_test: reporting error for erased_generic_kind={:?}, \ + lower_bound_region={:?}, \ + type_test.span={:?}", + erased_generic_kind, type_test.lower_bound, type_test.span, + ); - fn eval_if_eq( - &self, - infcx: &InferCtxt<'tcx>, - generic_ty: Ty<'tcx>, - lower_bound: RegionVid, - verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>, - ) -> bool { - let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty); - let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b); - match test_type_match::extract_verify_if_eq(infcx.tcx, &verify_if_eq_b, generic_ty) { - Some(r) => { - let r_vid = self.to_region_vid(r); - self.eval_outlives(r_vid, lower_bound) + errors_buffer.push(RegionErrorKind::TypeTestError { type_test: type_test.clone() }); } - None => false, } } - /// This is a conservative normalization procedure. It takes every - /// free region in `value` and replaces it with the - /// "representative" of its SCC (see `scc_representatives` field). - /// We are guaranteed that if two values normalize to the same - /// thing, then they are equal; this is a conservative check in - /// that they could still be equal even if they normalize to - /// different results. (For example, there might be two regions - /// with the same value that are not in the same SCC). - /// - /// N.B., this is not an ideal approach and I would like to revisit - /// it. However, it works pretty well in practice. In particular, - /// this is needed to deal with projection outlives bounds like + /// Invoked when we have some type-test (e.g., `T: 'X`) that we cannot + /// prove to be satisfied. If this is a closure, we will attempt to + /// "promote" this type-test into our `ClosureRegionRequirements` and + /// hence pass it up the creator. To do this, we have to phrase the + /// type-test in terms of external free regions, as local free + /// regions are not nameable by the closure's creator. /// - /// ```text - /// >::Item: '1 - /// ``` + /// Promotion works as follows: we first check that the type `T` + /// contains only regions that the creator knows about. If this is + /// true, then -- as a consequence -- we know that all regions in + /// the type `T` are free regions that outlive the closure body. If + /// false, then promotion fails. /// - /// In particular, this routine winds up being important when - /// there are bounds like `where >::Item: 'b` in the - /// environment. In this case, if we can show that `'0 == 'a`, - /// and that `'b: '1`, then we know that the clause is - /// satisfied. In such cases, particularly due to limitations of - /// the trait solver =), we usually wind up with a where-clause like - /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as - /// a constraint, and thus ensures that they are in the same SCC. + /// Once we've promoted T, we have to "promote" `'X` to some region + /// that is "external" to the closure. Generally speaking, a region + /// may be the union of some points in the closure body as well as + /// various free lifetimes. We can ignore the points in the closure + /// body: if the type T can be expressed in terms of external regions, + /// we know it outlives the points in the closure body. That + /// just leaves the free regions. /// - /// So why can't we do a more correct routine? Well, we could - /// *almost* use the `relate_tys` code, but the way it is - /// currently setup it creates inference variables to deal with - /// higher-ranked things and so forth, and right now the inference - /// context is not permitted to make more inference variables. So - /// we use this kind of hacky solution. - fn normalize_to_scc_representatives(&self, tcx: TyCtxt<'tcx>, value: T) -> T - where - T: TypeFoldable>, - { - fold_regions(tcx, value, |r, _db| { - let vid = self.to_region_vid(r); - let scc = self.constraint_sccs.scc(vid); - let repr = self.scc_representative(scc); - ty::Region::new_var(tcx, repr) - }) - } + /// The idea then is to lower the `T: 'X` constraint into multiple + /// bounds -- e.g., if `'X` is the union of two free lifetimes, + /// `'1` and `'2`, then we would create `T: '1` and `T: '2`. + #[instrument(level = "debug", skip(self, infcx, propagated_outlives_requirements))] + fn try_promote_type_test( + &self, + infcx: &InferCtxt<'tcx>, + type_test: &TypeTest<'tcx>, + propagated_outlives_requirements: &mut Vec>, + ) -> bool { + let tcx = infcx.tcx; + let TypeTest { generic_kind, lower_bound, span: blame_span, verify_bound: _ } = *type_test; - /// Evaluate whether `sup_region == sub_region`. - /// - /// Panics if called before `solve()` executes, - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - pub(crate) fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool { - self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1) - } + let generic_ty = generic_kind.to_ty(tcx); + let Some(subject) = self.try_promote_type_test_subject(infcx, generic_ty) else { + return false; + }; - /// Evaluate whether `sup_region: sub_region`. - /// - /// Panics if called before `solve()` executes, - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - #[instrument(skip(self), level = "debug", ret)] - pub(crate) fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool { - debug!( - "sup_region's value = {:?} universal={:?}", - self.region_value_str(sup_region), - self.universal_regions().is_universal_region(sup_region), - ); + let r_scc = self.constraint_sccs.scc(lower_bound); debug!( - "sub_region's value = {:?} universal={:?}", - self.region_value_str(sub_region), - self.universal_regions().is_universal_region(sub_region), + "lower_bound = {:?} r_scc={:?} universe={:?}", + lower_bound, + r_scc, + self.max_nameable_universe(r_scc) ); - - let sub_region_scc = self.constraint_sccs.scc(sub_region); - let sup_region_scc = self.constraint_sccs.scc(sup_region); - - if sub_region_scc == sup_region_scc { - debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC"); - return true; - } - - let fr_static = self.universal_regions().fr_static; - - // If we are checking that `'sup: 'sub`, and `'sub` contains - // some placeholder that `'sup` cannot name, then this is only - // true if `'sup` outlives static. + // If the type test requires that `T: 'a` where `'a` is a + // placeholder from another universe, that effectively requires + // `T: 'static`, so we have to propagate that requirement. // - // Avoid infinite recursion if `sub_region` is already `'static` - if sub_region != fr_static - && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) - { - debug!( - "sub universe `{sub_region_scc:?}` is not nameable \ - by super `{sup_region_scc:?}`, promoting to static", - ); - - return self.eval_outlives(sup_region, fr_static); - } - - // Both the `sub_region` and `sup_region` consist of the union - // of some number of universal regions (along with the union - // of various points in the CFG; ignore those points for - // now). Therefore, the sup-region outlives the sub-region if, - // for each universal region R1 in the sub-region, there - // exists some region R2 in the sup-region that outlives R1. - let universal_outlives = - self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| { - self.scc_values - .universal_regions_outlived_by(sup_region_scc) - .any(|r2| self.universal_region_relations.outlives(r2, r1)) + // It doesn't matter *what* universe because the promoted `T` will + // always be in the root universe. + if let Some(p) = self.scc_values.placeholders_contained_in(r_scc).next() { + debug!("encountered placeholder in higher universe: {:?}, requiring 'static", p); + let static_r = self.universal_regions().fr_static; + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject, + outlived_free_region: static_r, + blame_span, + category: ConstraintCategory::Boring, }); - if !universal_outlives { - debug!("sub region contains a universal region not present in super"); - return false; - } - - // Now we have to compare all the points in the sub region and make - // sure they exist in the sup region. - - if self.universal_regions().is_universal_region(sup_region) { - // Micro-opt: universal regions contain all points. - debug!("super is universal and hence contains all points"); + // we can return here -- the code below might push add'l constraints + // but they would all be weaker than this one. return true; } - debug!("comparison between points in sup/sub"); - - self.scc_values.contains_points(sup_region_scc, sub_region_scc) - } - - /// Once regions have been propagated, this method is used to see - /// whether any of the constraints were too strong. In particular, - /// we want to check for a case where a universally quantified - /// region exceeded its bounds. Consider: - /// ```compile_fail - /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } - /// ``` - /// In this case, returning `x` requires `&'a u32 <: &'b u32` - /// and hence we establish (transitively) a constraint that - /// `'a: 'b`. The `propagate_constraints` code above will - /// therefore add `end('a)` into the region for `'b` -- but we - /// have no evidence that `'b` outlives `'a`, so we want to report - /// an error. - /// - /// If `propagated_outlives_requirements` is `Some`, then we will - /// push unsatisfied obligations into there. Otherwise, we'll - /// report them as errors. - fn check_universal_regions( - &self, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - for (fr, fr_definition) in self.definitions.iter_enumerated() { - debug!(?fr, ?fr_definition); - match fr_definition.origin { - NllRegionVariableOrigin::FreeRegion => { - // Go through each of the universal regions `fr` and check that - // they did not grow too large, accumulating any requirements - // for our caller into the `outlives_requirements` vector. - self.check_universal_region( - fr, - &mut propagated_outlives_requirements, - errors_buffer, - ); - } + // For each region outlived by lower_bound find a non-local, + // universal region (it may be the same region) and add it to + // `ClosureOutlivesRequirement`. + let mut found_outlived_universal_region = false; + for ur in self.scc_values.universal_regions_outlived_by(r_scc) { + found_outlived_universal_region = true; + debug!("universal_region_outlived_by ur={:?}", ur); + let non_local_ub = self.universal_region_relations.non_local_upper_bounds(ur); + debug!(?non_local_ub); - NllRegionVariableOrigin::Placeholder(placeholder) => { - self.check_bound_universal_region(fr, placeholder, errors_buffer); - } + // This is slightly too conservative. To show T: '1, given `'2: '1` + // and `'3: '1` we only need to prove that T: '2 *or* T: '3, but to + // avoid potential non-determinism we approximate this by requiring + // T: '1 and T: '2. + for upper_bound in non_local_ub { + debug_assert!(self.universal_regions().is_universal_region(upper_bound)); + debug_assert!(!self.universal_regions().is_local_free_region(upper_bound)); - NllRegionVariableOrigin::Existential { .. } => { - // nothing to check here - } + let requirement = ClosureOutlivesRequirement { + subject, + outlived_free_region: upper_bound, + blame_span, + category: ConstraintCategory::Boring, + }; + debug!(?requirement, "adding closure requirement"); + propagated_outlives_requirements.push(requirement); } } + // If we succeed to promote the subject, i.e. it only contains non-local regions, + // and fail to prove the type test inside of the closure, the `lower_bound` has to + // also be at least as large as some universal region, as the type test is otherwise + // trivial. + assert!(found_outlived_universal_region); + true } - /// Checks if Polonius has found any unexpected free region relations. - /// - /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent - /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a` - /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL - /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`. - /// - /// More details can be found in this blog post by Niko: - /// - /// - /// In the canonical example - /// ```compile_fail - /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } - /// ``` - /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a - /// constraint that `'a: 'b`. It is an error that we have no evidence that this - /// constraint holds. - /// - /// If `propagated_outlives_requirements` is `Some`, then we will - /// push unsatisfied obligations into there. Otherwise, we'll - /// report them as errors. - fn check_polonius_subset_errors( + /// When we promote a type test `T: 'r`, we have to replace all region + /// variables in the type `T` with an equal universal region from the + /// closure signature. + /// This is not always possible, so this is a fallible process. + #[instrument(level = "debug", skip(self, infcx), ret)] + fn try_promote_type_test_subject( &self, - mut propagated_outlives_requirements: Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - polonius_output: &PoloniusOutput, - ) { - debug!( - "check_polonius_subset_errors: {} subset_errors", - polonius_output.subset_errors.len() - ); + infcx: &InferCtxt<'tcx>, + ty: Ty<'tcx>, + ) -> Option> { + let tcx = infcx.tcx; + let mut failed = false; + let ty = fold_regions(tcx, ty, |r, _depth| { + let r_vid = self.to_region_vid(r); + let r_scc = self.constraint_sccs.scc(r_vid); - // Similarly to `check_universal_regions`: a free region relation, which was not explicitly - // declared ("known") was found by Polonius, so emit an error, or propagate the - // requirements for our caller into the `propagated_outlives_requirements` vector. - // - // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the - // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with - // the rest of the NLL infrastructure. The "subset origin" is the "longer free region", - // and the "superset origin" is the outlived "shorter free region". - // - // Note: Polonius will produce a subset error at every point where the unexpected - // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful - // for diagnostics in the future, e.g. to point more precisely at the key locations - // requiring this constraint to hold. However, the error and diagnostics code downstream - // expects that these errors are not duplicated (and that they are in a certain order). - // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or - // anonymous lifetimes for example, could give these names differently, while others like - // the outlives suggestions or the debug output from `#[rustc_regions]` would be - // duplicated. The polonius subset errors are deduplicated here, while keeping the - // CFG-location ordering. - // We can iterate the HashMap here because the result is sorted afterwards. - #[allow(rustc::potential_query_instability)] - let mut subset_errors: Vec<_> = polonius_output - .subset_errors - .iter() - .flat_map(|(_location, subset_errors)| subset_errors.iter()) - .collect(); - subset_errors.sort(); - subset_errors.dedup(); + // The challenge is this. We have some region variable `r` + // whose value is a set of CFG points and universal + // regions. We want to find if that set is *equivalent* to + // any of the named regions found in the closure. + // To do so, we simply check every candidate `u_r` for equality. + self.scc_values + .universal_regions_outlived_by(r_scc) + .filter(|&u_r| !self.universal_regions().is_local_free_region(u_r)) + .find(|&u_r| self.eval_equal(u_r, r_vid)) + .map(|u_r| ty::Region::new_var(tcx, u_r)) + // In case we could not find a named region to map to, + // we will return `None` below. + .unwrap_or_else(|| { + failed = true; + r + }) + }); - for &(longer_fr, shorter_fr) in subset_errors.into_iter() { - debug!( - "check_polonius_subset_errors: subset_error longer_fr={:?},\ - shorter_fr={:?}", - longer_fr, shorter_fr - ); + debug!("try_promote_type_test_subject: folded ty = {:?}", ty); - let propagated = self.try_propagate_universal_region_error( - longer_fr.into(), - shorter_fr.into(), - &mut propagated_outlives_requirements, - ); - if propagated == RegionRelationCheckResult::Error { - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr: longer_fr.into(), - shorter_fr: shorter_fr.into(), - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: true, - }); - } + // This will be true if we failed to promote some region. + if failed { + return None; } - // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has - // a more complete picture on how to separate this responsibility. - for (fr, fr_definition) in self.definitions.iter_enumerated() { - match fr_definition.origin { - NllRegionVariableOrigin::FreeRegion => { - // handled by polonius above - } + Some(ClosureOutlivesSubject::Ty(ClosureOutlivesSubjectTy::bind(tcx, ty))) + } - NllRegionVariableOrigin::Placeholder(placeholder) => { - self.check_bound_universal_region(fr, placeholder, errors_buffer); - } + /// Tests if `test` is true when applied to `lower_bound` at + /// `point`. + fn eval_verify_bound( + &self, + infcx: &InferCtxt<'tcx>, + generic_ty: Ty<'tcx>, + lower_bound: RegionVid, + verify_bound: &VerifyBound<'tcx>, + ) -> bool { + debug!("eval_verify_bound(lower_bound={:?}, verify_bound={:?})", lower_bound, verify_bound); - NllRegionVariableOrigin::Existential { .. } => { - // nothing to check here - } + match verify_bound { + VerifyBound::IfEq(verify_if_eq_b) => { + self.eval_if_eq(infcx, generic_ty, lower_bound, *verify_if_eq_b) } - } - } - /// The largest universe of any region nameable from this SCC. - pub(super) fn max_nameable_universe(&self, scc: ConstraintSccIndex) -> UniverseIndex { - self.scc_annotations[scc].max_nameable_universe() - } + VerifyBound::IsEmpty => { + let lower_bound_scc = self.constraint_sccs.scc(lower_bound); + self.scc_values.elements_contained_in(lower_bound_scc).next().is_none() + } - /// Checks the final value for the free region `fr` to see if it - /// grew too large. In particular, examine what `end(X)` points - /// wound up in `fr`'s final value; for each `end(X)` where `X != - /// fr`, we want to check that `fr: X`. If not, that's either an - /// error, or something we have to propagate to our creator. - /// - /// Things that are to be propagated are accumulated into the - /// `outlives_requirements` vector. - #[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")] - fn check_universal_region( - &self, - longer_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - let longer_fr_scc = self.constraint_sccs.scc(longer_fr); + VerifyBound::OutlivedBy(r) => { + let r_vid = self.to_region_vid(*r); + self.eval_outlives(r_vid, lower_bound) + } - // Because this free region must be in the ROOT universe, we - // know it cannot contain any bound universes. - assert!(self.max_nameable_universe(longer_fr_scc).is_root()); + VerifyBound::AnyBound(verify_bounds) => verify_bounds.iter().any(|verify_bound| { + self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) + }), - // Only check all of the relations for the main representative of each - // SCC, otherwise just check that we outlive said representative. This - // reduces the number of redundant relations propagated out of - // closures. - // Note that the representative will be a universal region if there is - // one in this SCC, so we will always check the representative here. - let representative = self.scc_representative(longer_fr_scc); - if representative != longer_fr { - if let RegionRelationCheckResult::Error = self.check_universal_region_relation( - longer_fr, - representative, - propagated_outlives_requirements, - ) { - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr, - shorter_fr: representative, - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: true, - }); - } - return; + VerifyBound::AllBounds(verify_bounds) => verify_bounds.iter().all(|verify_bound| { + self.eval_verify_bound(infcx, generic_ty, lower_bound, verify_bound) + }), } + } - // Find every region `o` such that `fr: o` - // (because `fr` includes `end(o)`). - let mut error_reported = false; - for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { - if let RegionRelationCheckResult::Error = self.check_universal_region_relation( - longer_fr, - shorter_fr, - propagated_outlives_requirements, - ) { - // We only report the first region error. Subsequent errors are hidden so as - // not to overwhelm the user, but we do record them so as to potentially print - // better diagnostics elsewhere... - errors_buffer.push(RegionErrorKind::RegionError { - longer_fr, - shorter_fr, - fr_origin: NllRegionVariableOrigin::FreeRegion, - is_reported: !error_reported, - }); - - error_reported = true; + fn eval_if_eq( + &self, + infcx: &InferCtxt<'tcx>, + generic_ty: Ty<'tcx>, + lower_bound: RegionVid, + verify_if_eq_b: ty::Binder<'tcx, VerifyIfEq<'tcx>>, + ) -> bool { + let generic_ty = self.normalize_to_scc_representatives(infcx.tcx, generic_ty); + let verify_if_eq_b = self.normalize_to_scc_representatives(infcx.tcx, verify_if_eq_b); + match test_type_match::extract_verify_if_eq(infcx.tcx, &verify_if_eq_b, generic_ty) { + Some(r) => { + let r_vid = self.to_region_vid(r); + self.eval_outlives(r_vid, lower_bound) } + None => false, } } - /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate - /// the constraint outward (e.g. to a closure environment), but if that fails, there is an - /// error. - fn check_universal_region_relation( - &self, - longer_fr: RegionVid, - shorter_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - ) -> RegionRelationCheckResult { - // If it is known that `fr: o`, carry on. - if self.universal_region_relations.outlives(longer_fr, shorter_fr) { - RegionRelationCheckResult::Ok - } else { - // If we are not in a context where we can't propagate errors, or we - // could not shrink `fr` to something smaller, then just report an - // error. - // - // Note: in this case, we use the unapproximated regions to report the - // error. This gives better error messages in some cases. - self.try_propagate_universal_region_error( - longer_fr, - shorter_fr, - propagated_outlives_requirements, - ) - } + /// This is a conservative normalization procedure. It takes every + /// free region in `value` and replaces it with the + /// "representative" of its SCC (see `scc_representatives` field). + /// We are guaranteed that if two values normalize to the same + /// thing, then they are equal; this is a conservative check in + /// that they could still be equal even if they normalize to + /// different results. (For example, there might be two regions + /// with the same value that are not in the same SCC). + /// + /// N.B., this is not an ideal approach and I would like to revisit + /// it. However, it works pretty well in practice. In particular, + /// this is needed to deal with projection outlives bounds like + /// + /// ```text + /// >::Item: '1 + /// ``` + /// + /// In particular, this routine winds up being important when + /// there are bounds like `where >::Item: 'b` in the + /// environment. In this case, if we can show that `'0 == 'a`, + /// and that `'b: '1`, then we know that the clause is + /// satisfied. In such cases, particularly due to limitations of + /// the trait solver =), we usually wind up with a where-clause like + /// `T: Foo<'a>` in scope, which thus forces `'0 == 'a` to be added as + /// a constraint, and thus ensures that they are in the same SCC. + /// + /// So why can't we do a more correct routine? Well, we could + /// *almost* use the `relate_tys` code, but the way it is + /// currently setup it creates inference variables to deal with + /// higher-ranked things and so forth, and right now the inference + /// context is not permitted to make more inference variables. So + /// we use this kind of hacky solution. + fn normalize_to_scc_representatives(&self, tcx: TyCtxt<'tcx>, value: T) -> T + where + T: TypeFoldable>, + { + fold_regions(tcx, value, |r, _db| { + let vid = self.to_region_vid(r); + let scc = self.constraint_sccs.scc(vid); + let repr = self.scc_representative(scc); + ty::Region::new_var(tcx, repr) + }) } - /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's - /// creator. If we cannot, then the caller should report an error to the user. - fn try_propagate_universal_region_error( - &self, - longer_fr: RegionVid, - shorter_fr: RegionVid, - propagated_outlives_requirements: &mut Option<&mut Vec>>, - ) -> RegionRelationCheckResult { - if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { - // Shrink `longer_fr` until we find some non-local regions. - // We'll call them `longer_fr-` -- they are ever so slightly smaller than - // `longer_fr`. - let longer_fr_minus = self.universal_region_relations.non_local_lower_bounds(longer_fr); - - debug!("try_propagate_universal_region_error: fr_minus={:?}", longer_fr_minus); + /// Evaluate whether `sup_region == sub_region`. + /// + /// Panics if called before `solve()` executes, + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + pub(crate) fn eval_equal(&self, r1: RegionVid, r2: RegionVid) -> bool { + self.eval_outlives(r1, r2) && self.eval_outlives(r2, r1) + } - // If we don't find a any non-local regions, we should error out as there is nothing - // to propagate. - if longer_fr_minus.is_empty() { - return RegionRelationCheckResult::Error; - } + /// Evaluate whether `sup_region: sub_region`. + /// + /// Panics if called before `solve()` executes, + // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. + #[instrument(skip(self), level = "debug", ret)] + pub(crate) fn eval_outlives(&self, sup_region: RegionVid, sub_region: RegionVid) -> bool { + debug!( + "sup_region's value = {:?} universal={:?}", + self.region_value_str(sup_region), + self.universal_regions().is_universal_region(sup_region), + ); + debug!( + "sub_region's value = {:?} universal={:?}", + self.region_value_str(sub_region), + self.universal_regions().is_universal_region(sub_region), + ); - let best_blame = self.best_blame_constraint( - longer_fr, - NllRegionVariableOrigin::FreeRegion, - shorter_fr, - ); - let OutlivesConstraint { category, span, .. } = best_blame.constraint(); + let sub_region_scc = self.constraint_sccs.scc(sub_region); + let sup_region_scc = self.constraint_sccs.scc(sup_region); - // Grow `shorter_fr` until we find some non-local regions. - // We will always find at least one: `'static`. We'll call - // them `shorter_fr+` -- they're ever so slightly larger - // than `shorter_fr`. - let shorter_fr_plus = - self.universal_region_relations.non_local_upper_bounds(shorter_fr); - debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus); + if sub_region_scc == sup_region_scc { + debug!("{sup_region:?}: {sub_region:?} holds trivially; they are in the same SCC"); + return true; + } - // We then create constraints `longer_fr-: shorter_fr+` that may or may not - // be propagated (see below). - let mut constraints = vec![]; - for fr_minus in longer_fr_minus { - for shorter_fr_plus in &shorter_fr_plus { - constraints.push((fr_minus, *shorter_fr_plus)); - } - } + let fr_static = self.universal_regions().fr_static; - // We only need to propagate at least one of the constraints for - // soundness. However, we want to avoid arbitrary choices here - // and currently don't support returning OR constraints. - // - // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`, - // we propagate only those. - // - // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`: - // a --> b --> d - // \ - // \-> c - // Here, `shorter_fr+` of `'a` == `['b, 'c]`. - // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of - // `'d: 'b` and could reject valid code. - // - // So we filter the constraints to regions already outlived by `longer_fr-`, but if - // the filter yields an empty set, we fall back to the original one. - let subset: Vec<_> = constraints - .iter() - .filter(|&&(fr_minus, shorter_fr_plus)| { - self.eval_outlives(fr_minus, shorter_fr_plus) - }) - .copied() - .collect(); - let propagated_constraints = if subset.is_empty() { constraints } else { subset }; + // If we are checking that `'sup: 'sub`, and `'sub` contains + // some placeholder that `'sup` cannot name, then this is only + // true if `'sup` outlives static. + // + // Avoid infinite recursion if `sub_region` is already `'static` + if sub_region != fr_static + && !self.can_name_all_placeholders(sup_region_scc, sub_region_scc) + { debug!( - "try_propagate_universal_region_error: constraints={:?}", - propagated_constraints - ); - - assert!( - !propagated_constraints.is_empty(), - "Expected at least one constraint to propagate here" + "sub universe `{sub_region_scc:?}` is not nameable \ + by super `{sup_region_scc:?}`, promoting to static", ); - for (fr_minus, fr_plus) in propagated_constraints { - // Push the constraint `long_fr-: shorter_fr+` - propagated_outlives_requirements.push(ClosureOutlivesRequirement { - subject: ClosureOutlivesSubject::Region(fr_minus), - outlived_free_region: fr_plus, - blame_span: *span, - category: *category, - }); - } - return RegionRelationCheckResult::Propagated; + return self.eval_outlives(sup_region, fr_static); } - RegionRelationCheckResult::Error - } + // Both the `sub_region` and `sup_region` consist of the union + // of some number of universal regions (along with the union + // of various points in the CFG; ignore those points for + // now). Therefore, the sup-region outlives the sub-region if, + // for each universal region R1 in the sub-region, there + // exists some region R2 in the sup-region that outlives R1. + let universal_outlives = + self.scc_values.universal_regions_outlived_by(sub_region_scc).all(|r1| { + self.scc_values + .universal_regions_outlived_by(sup_region_scc) + .any(|r2| self.universal_region_relations.outlives(r2, r1)) + }); - fn check_bound_universal_region( - &self, - longer_fr: RegionVid, - placeholder: ty::PlaceholderRegion<'tcx>, - errors_buffer: &mut RegionErrors<'tcx>, - ) { - debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,); + if !universal_outlives { + debug!("sub region contains a universal region not present in super"); + return false; + } - let longer_fr_scc = self.constraint_sccs.scc(longer_fr); - debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); + // Now we have to compare all the points in the sub region and make + // sure they exist in the sup region. - // If we have some bound universal region `'a`, then the only - // elements it can contain is itself -- we don't know anything - // else about it! - if let Some(error_element) = self - .scc_values - .elements_contained_in(longer_fr_scc) - .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) - { - let illegally_outlived_r = self.region_from_element(longer_fr, &error_element); - // Stop after the first error, it gets too noisy otherwise, and does not provide more information. - errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion { - longer_fr, - illegally_outlived_r, - }); - } else { - debug!("check_bound_universal_region: all bounds satisfied"); + if self.universal_regions().is_universal_region(sup_region) { + // Micro-opt: universal regions contain all points. + debug!("super is universal and hence contains all points"); + return true; } - } - pub(crate) fn constraint_path_between_regions( - &self, - from_region: RegionVid, - to_region: RegionVid, - ) -> Option>> { - if from_region == to_region { - bug!("Tried to find a path between {from_region:?} and itself!"); - } - self.constraint_path_to(from_region, |to| to == to_region, true).map(|o| o.0) + debug!("comparison between points in sup/sub"); + + self.scc_values.contains_points(sup_region_scc, sub_region_scc) } - /// Walks the graph of constraints (where `'a: 'b` is considered - /// an edge `'a -> 'b`) to find a path from `from_region` to - /// `to_region`. + /// Once regions have been propagated, this method is used to see + /// whether any of the constraints were too strong. In particular, + /// we want to check for a case where a universally quantified + /// region exceeded its bounds. Consider: + /// ```compile_fail + /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } + /// ``` + /// In this case, returning `x` requires `&'a u32 <: &'b u32` + /// and hence we establish (transitively) a constraint that + /// `'a: 'b`. The `propagate_constraints` code above will + /// therefore add `end('a)` into the region for `'b` -- but we + /// have no evidence that `'b` outlives `'a`, so we want to report + /// an error. /// - /// Returns: a series of constraints as well as the region `R` - /// that passed the target test. - /// If `include_static_outlives_all` is `true`, then the synthetic - /// outlives constraints `'static -> a` for every region `a` are - /// considered in the search, otherwise they are ignored. - #[instrument(skip(self, target_test), ret)] - pub(crate) fn constraint_path_to( + /// If `propagated_outlives_requirements` is `Some`, then we will + /// push unsatisfied obligations into there. Otherwise, we'll + /// report them as errors. + fn check_universal_regions( &self, - from_region: RegionVid, - target_test: impl Fn(RegionVid) -> bool, - include_placeholder_static: bool, - ) -> Option<(Vec>, RegionVid)> { - self.find_constraint_path_between_regions_inner( - true, - from_region, - &target_test, - include_placeholder_static, - ) - .or_else(|| { - self.find_constraint_path_between_regions_inner( - false, - from_region, - &target_test, - include_placeholder_static, - ) - }) + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + for (fr, fr_definition) in self.definitions.iter_enumerated() { + debug!(?fr, ?fr_definition); + match fr_definition.origin { + NllRegionVariableOrigin::FreeRegion => { + // Go through each of the universal regions `fr` and check that + // they did not grow too large, accumulating any requirements + // for our caller into the `outlives_requirements` vector. + self.check_universal_region( + fr, + &mut propagated_outlives_requirements, + errors_buffer, + ); + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + self.check_bound_universal_region(fr, placeholder, errors_buffer); + } + + NllRegionVariableOrigin::Existential { .. } => { + // nothing to check here + } + } + } } - /// The constraints we get from equating the hidden type of each use of an opaque - /// with its final hidden type may end up getting preferred over other, potentially - /// longer constraint paths. + /// Checks if Polonius has found any unexpected free region relations. /// - /// Given that we compute the final hidden type by relying on this existing constraint - /// path, this can easily end up hiding the actual reason for why we require these regions - /// to be equal. + /// In Polonius terms, a "subset error" (or "illegal subset relation error") is the equivalent + /// of NLL's "checking if any region constraints were too strong": a placeholder origin `'a` + /// was unexpectedly found to be a subset of another placeholder origin `'b`, and means in NLL + /// terms that the "longer free region" `'a` outlived the "shorter free region" `'b`. /// - /// To handle this, we first look at the path while ignoring these constraints and then - /// retry while considering them. This is not perfect, as the `from_region` may have already - /// been partially related to its argument region, so while we rely on a member constraint - /// to get a complete path, the most relevant step of that path already existed before then. - fn find_constraint_path_between_regions_inner( + /// More details can be found in this blog post by Niko: + /// + /// + /// In the canonical example + /// ```compile_fail + /// fn foo<'a, 'b>(x: &'a u32) -> &'b u32 { x } + /// ``` + /// returning `x` requires `&'a u32 <: &'b u32` and hence we establish (transitively) a + /// constraint that `'a: 'b`. It is an error that we have no evidence that this + /// constraint holds. + /// + /// If `propagated_outlives_requirements` is `Some`, then we will + /// push unsatisfied obligations into there. Otherwise, we'll + /// report them as errors. + fn check_polonius_subset_errors( &self, - ignore_opaque_type_constraints: bool, - from_region: RegionVid, - target_test: impl Fn(RegionVid) -> bool, - include_placeholder_static: bool, - ) -> Option<(Vec>, RegionVid)> { - let mut context = IndexVec::from_elem(Trace::NotVisited, &self.definitions); - context[from_region] = Trace::StartRegion; - - let fr_static = self.universal_regions().fr_static; + mut propagated_outlives_requirements: Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + polonius_output: &PoloniusOutput, + ) { + debug!( + "check_polonius_subset_errors: {} subset_errors", + polonius_output.subset_errors.len() + ); - // Use a deque so that we do a breadth-first search. We will - // stop at the first match, which ought to be the shortest - // path (fewest constraints). - let mut deque = VecDeque::new(); - deque.push_back(from_region); + // Similarly to `check_universal_regions`: a free region relation, which was not explicitly + // declared ("known") was found by Polonius, so emit an error, or propagate the + // requirements for our caller into the `propagated_outlives_requirements` vector. + // + // Polonius doesn't model regions ("origins") as CFG-subsets or durations, but the + // `longer_fr` and `shorter_fr` terminology will still be used here, for consistency with + // the rest of the NLL infrastructure. The "subset origin" is the "longer free region", + // and the "superset origin" is the outlived "shorter free region". + // + // Note: Polonius will produce a subset error at every point where the unexpected + // `longer_fr`'s "placeholder loan" is contained in the `shorter_fr`. This can be helpful + // for diagnostics in the future, e.g. to point more precisely at the key locations + // requiring this constraint to hold. However, the error and diagnostics code downstream + // expects that these errors are not duplicated (and that they are in a certain order). + // Otherwise, diagnostics messages such as the ones giving names like `'1` to elided or + // anonymous lifetimes for example, could give these names differently, while others like + // the outlives suggestions or the debug output from `#[rustc_regions]` would be + // duplicated. The polonius subset errors are deduplicated here, while keeping the + // CFG-location ordering. + // We can iterate the HashMap here because the result is sorted afterwards. + #[allow(rustc::potential_query_instability)] + let mut subset_errors: Vec<_> = polonius_output + .subset_errors + .iter() + .flat_map(|(_location, subset_errors)| subset_errors.iter()) + .collect(); + subset_errors.sort(); + subset_errors.dedup(); - while let Some(r) = deque.pop_front() { + for &(longer_fr, shorter_fr) in subset_errors.into_iter() { debug!( - "constraint_path_to: from_region={:?} r={:?} value={}", - from_region, - r, - self.region_value_str(r), + "check_polonius_subset_errors: subset_error longer_fr={:?},\ + shorter_fr={:?}", + longer_fr, shorter_fr ); - // Check if we reached the region we were looking for. If so, - // we can reconstruct the path that led to it and return it. - if target_test(r) { - let mut result = vec![]; - let mut p = r; - // This loop is cold and runs at the end, which is why we delay - // `OutlivesConstraint` construction until now. - loop { - match context[p] { - Trace::FromGraph(c) => { - p = c.sup; - result.push(*c); - } - - Trace::FromStatic(sub) => { - let c = OutlivesConstraint { - sup: fr_static, - sub, - locations: Locations::All(DUMMY_SP), - span: DUMMY_SP, - category: ConstraintCategory::Internal, - variance_info: ty::VarianceDiagInfo::default(), - from_closure: false, - }; - p = c.sup; - result.push(c); - } - - Trace::StartRegion => { - result.reverse(); - return Some((result, r)); - } - - Trace::NotVisited => { - bug!("found unvisited region {:?} on path to {:?}", p, r) - } - } - } + let propagated = self.try_propagate_universal_region_error( + longer_fr.into(), + shorter_fr.into(), + &mut propagated_outlives_requirements, + ); + if propagated == RegionRelationCheckResult::Error { + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr: longer_fr.into(), + shorter_fr: shorter_fr.into(), + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: true, + }); } + } - // Otherwise, walk over the outgoing constraints and - // enqueue any regions we find, keeping track of how we - // reached them. - - // A constraint like `'r: 'x` can come from our constraint - // graph. - - // Always inline this closure because it can be hot. - let mut handle_trace = #[inline(always)] - |sub, trace| { - if let Trace::NotVisited = context[sub] { - context[sub] = trace; - deque.push_back(sub); - } - }; - - // If this is the `'static` region and the graph's direction is normal, then set up the - // Edges iterator to return all regions (#53178). - if r == fr_static && self.constraint_graph.is_normal() { - for sub in self.constraint_graph.outgoing_edges_from_static() { - handle_trace(sub, Trace::FromStatic(sub)); - } - } else { - let edges = self.constraint_graph.outgoing_edges_from_graph(r, &self.constraints); - // This loop can be hot. - for constraint in edges { - match constraint.category { - ConstraintCategory::OutlivesUnnameablePlaceholder(_) - if !include_placeholder_static => - { - debug!("Ignoring illegal placeholder constraint: {constraint:?}"); - continue; - } - ConstraintCategory::OpaqueType if ignore_opaque_type_constraints => { - debug!("Ignoring member constraint: {constraint:?}"); - continue; - } - _ => {} - } + // Handle the placeholder errors as usual, until the chalk-rustc-polonius triumvirate has + // a more complete picture on how to separate this responsibility. + for (fr, fr_definition) in self.definitions.iter_enumerated() { + match fr_definition.origin { + NllRegionVariableOrigin::FreeRegion => { + // handled by polonius above + } - debug_assert_eq!(constraint.sup, r); - handle_trace(constraint.sub, Trace::FromGraph(constraint)); + NllRegionVariableOrigin::Placeholder(placeholder) => { + self.check_bound_universal_region(fr, placeholder, errors_buffer); + } + + NllRegionVariableOrigin::Existential { .. } => { + // nothing to check here } } } - - None - } - - /// Finds some region R such that `fr1: R` and `R` is live at `location`. - #[instrument(skip(self), level = "trace", ret)] - pub(crate) fn find_sub_region_live_at(&self, fr1: RegionVid, location: Location) -> RegionVid { - trace!(scc = ?self.constraint_sccs.scc(fr1)); - trace!(universe = ?self.max_nameable_universe(self.constraint_sccs.scc(fr1))); - self.constraint_path_to(fr1, |r| { - trace!(?r, liveness_constraints=?self.liveness_constraints.pretty_print_live_points(r)); - self.liveness_constraints.is_live_at(r, location) - }, true).unwrap().1 } - /// Get the region outlived by `longer_fr` and live at `element`. - fn region_from_element( + /// Checks the final value for the free region `fr` to see if it + /// grew too large. In particular, examine what `end(X)` points + /// wound up in `fr`'s final value; for each `end(X)` where `X != + /// fr`, we want to check that `fr: X`. If not, that's either an + /// error, or something we have to propagate to our creator. + /// + /// Things that are to be propagated are accumulated into the + /// `outlives_requirements` vector. + #[instrument(skip(self, propagated_outlives_requirements, errors_buffer), level = "debug")] + fn check_universal_region( &self, longer_fr: RegionVid, - element: &RegionElement<'tcx>, - ) -> RegionVid { - match *element { - RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), - RegionElement::RootUniversalRegion(r) => r, - RegionElement::PlaceholderRegion(error_placeholder) => self - .definitions - .iter_enumerated() - .find_map(|(r, definition)| match definition.origin { - NllRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), - _ => None, - }) - .unwrap(), - } - } - - /// Get the region definition of `r`. - pub(crate) fn region_definition(&self, r: RegionVid) -> &RegionDefinition<'tcx> { - &self.definitions[r] - } - - /// Check if the SCC of `r` contains `upper`, a free region. - pub(crate) fn upper_bound_in_region_scc(&self, r: RegionVid, upper: RegionVid) -> bool { - let r_scc = self.constraint_sccs.scc(r); - self.scc_values.contains_free_region(r_scc, upper) - } + propagated_outlives_requirements: &mut Option<&mut Vec>>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + let longer_fr_scc = self.constraint_sccs.scc(longer_fr); - pub(crate) fn universal_regions(&self) -> &UniversalRegions<'tcx> { - &self.universal_region_relations.universal_regions - } + // Because this free region must be in the ROOT universe, we + // know it cannot contain any bound universes. + assert!(self.max_nameable_universe(longer_fr_scc).is_root()); - /// Tries to find the best constraint to blame for the fact that - /// `R: from_region`, where `R` is some region that meets - /// `target_test`. This works by following the constraint graph, - /// creating a constraint path that forces `R` to outlive - /// `from_region`, and then finding the best choices within that - /// path to blame. - #[instrument(level = "debug", skip(self))] - pub(crate) fn best_blame_constraint( - &self, - from_region: RegionVid, - from_region_origin: NllRegionVariableOrigin<'tcx>, - to_region: RegionVid, - ) -> BestBlame<'tcx> { - assert!(from_region != to_region, "Trying to blame a region for itself!"); + // Only check all of the relations for the main representative of each + // SCC, otherwise just check that we outlive said representative. This + // reduces the number of redundant relations propagated out of + // closures. + // Note that the representative will be a universal region if there is + // one in this SCC, so we will always check the representative here. + let representative = self.scc_representative(longer_fr_scc); + if representative != longer_fr { + if let RegionRelationCheckResult::Error = self.check_universal_region_relation( + longer_fr, + representative, + propagated_outlives_requirements, + ) { + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr, + shorter_fr: representative, + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: true, + }); + } + return; + } - let path = self.constraint_path_between_regions(from_region, to_region).unwrap(); + // Find every region `o` such that `fr: o` + // (because `fr` includes `end(o)`). + let mut error_reported = false; + for shorter_fr in self.scc_values.universal_regions_outlived_by(longer_fr_scc) { + if let RegionRelationCheckResult::Error = self.check_universal_region_relation( + longer_fr, + shorter_fr, + propagated_outlives_requirements, + ) { + // We only report the first region error. Subsequent errors are hidden so as + // not to overwhelm the user, but we do record them so as to potentially print + // better diagnostics elsewhere... + errors_buffer.push(RegionErrorKind::RegionError { + longer_fr, + shorter_fr, + fr_origin: NllRegionVariableOrigin::FreeRegion, + is_reported: !error_reported, + }); - // If we are passing through a constraint added because we reached an unnameable placeholder `'unnameable`, - // redirect search towards `'unnameable`. - let due_to_placeholder_outlives = path.iter().find_map(|c| { - if let ConstraintCategory::OutlivesUnnameablePlaceholder(unnameable) = c.category { - Some(unnameable) - } else { - None + error_reported = true; } - }); + } + } - // Edge case: it's possible that `'from_region` is an unnameable placeholder. - let mut path = if let Some(unnameable) = due_to_placeholder_outlives - && unnameable != from_region - { - // We ignore the extra edges due to unnameable placeholders to get - // an explanation that was present in the original constraint graph. - self.constraint_path_to(from_region, |r| r == unnameable, false).unwrap().0 + /// Checks that we can prove that `longer_fr: shorter_fr`. If we can't we attempt to propagate + /// the constraint outward (e.g. to a closure environment), but if that fails, there is an + /// error. + fn check_universal_region_relation( + &self, + longer_fr: RegionVid, + shorter_fr: RegionVid, + propagated_outlives_requirements: &mut Option<&mut Vec>>, + ) -> RegionRelationCheckResult { + // If it is known that `fr: o`, carry on. + if self.universal_region_relations.outlives(longer_fr, shorter_fr) { + RegionRelationCheckResult::Ok } else { - path - }; - - debug!( - "path={:#?}", - path.iter() - .map(|c| format!( - "{:?} ({:?}: {:?})", - c, - self.constraint_sccs.scc(c.sup), - self.constraint_sccs.scc(c.sub), - )) - .collect::>() - ); - - // When reporting an error, there is typically a chain of constraints leading from some - // "source" region which must outlive some "target" region. - // In most cases, we prefer to "blame" the constraints closer to the target -- - // but there is one exception. When constraints arise from higher-ranked subtyping, - // we generally prefer to blame the source value, - // as the "target" in this case tends to be some type annotation that the user gave. - // Therefore, if we find that the region origin is some instantiation - // of a higher-ranked region, we start our search from the "source" point - // rather than the "target", and we also tweak a few other things. - // - // An example might be this bit of Rust code: - // - // ```rust - // let x: fn(&'static ()) = |_| {}; - // let y: for<'a> fn(&'a ()) = x; - // ``` - // - // In MIR, this will be converted into a combination of assignments and type ascriptions. - // In particular, the 'static is imposed through a type ascription: - // - // ```rust - // x = ...; - // AscribeUserType(x, fn(&'static ()) - // y = x; - // ``` - // - // We wind up ultimately with constraints like - // - // ```rust - // !a: 'temp1 // from the `y = x` statement - // 'temp1: 'temp2 - // 'temp2: 'static // from the AscribeUserType - // ``` - // - // and here we prefer to blame the source (the y = x statement). - let blame_source = match from_region_origin { - NllRegionVariableOrigin::FreeRegion => true, - NllRegionVariableOrigin::Placeholder(_) => false, - // `'existential: 'whatever` never results in a region error by itself. - // We may always infer it to `'static` afterall. This means while an error - // path may go through an existential, these existentials are never the - // `from_region`. - NllRegionVariableOrigin::Existential { name: _ } => { - unreachable!("existentials can outlive everything") - } - }; + // If we are not in a context where we can't propagate errors, or we + // could not shrink `fr` to something smaller, then just report an + // error. + // + // Note: in this case, we use the unapproximated regions to report the + // error. This gives better error messages in some cases. + self.try_propagate_universal_region_error( + longer_fr, + shorter_fr, + propagated_outlives_requirements, + ) + } + } - // To pick a constraint to blame, we organize constraints by how interesting we expect them - // to be in diagnostics, then pick the most interesting one closest to either the source or - // the target on our constraint path. - let constraint_interest = |constraint: &OutlivesConstraint<'tcx>| { - // Try to avoid blaming constraints from desugarings, since they may not clearly match - // match what users have written. As an exception, allow blaming returns generated by - // `?` desugaring, since the correspondence is fairly clear. - let category = if let Some(kind) = constraint.span.desugaring_kind() - && (kind != DesugaringKind::QuestionMark - || !matches!(constraint.category, ConstraintCategory::Return(_))) - { - ConstraintCategory::Boring - } else { - constraint.category - }; + /// Attempt to propagate a region error (e.g. `'a: 'b`) that is not met to a closure's + /// creator. If we cannot, then the caller should report an error to the user. + fn try_propagate_universal_region_error( + &self, + longer_fr: RegionVid, + shorter_fr: RegionVid, + propagated_outlives_requirements: &mut Option<&mut Vec>>, + ) -> RegionRelationCheckResult { + if let Some(propagated_outlives_requirements) = propagated_outlives_requirements { + // Shrink `longer_fr` until we find some non-local regions. + // We'll call them `longer_fr-` -- they are ever so slightly smaller than + // `longer_fr`. + let longer_fr_minus = self.universal_region_relations.non_local_lower_bounds(longer_fr); - let interest = match category { - // Returns usually provide a type to blame and have specially written diagnostics, - // so prioritize them. - ConstraintCategory::Return(_) => 0, - // Unsizing coercions are interesting, since we have a note for that: - // `BorrowExplanation::add_object_lifetime_default_note`. - // FIXME(dianne): That note shouldn't depend on a coercion being blamed; see issue - // #131008 for an example of where we currently don't emit it but should. - // Once the note is handled properly, this case should be removed. Until then, it - // should be as limited as possible; the note is prone to false positives and this - // constraint usually isn't best to blame. - ConstraintCategory::Cast { - is_raw_ptr_dyn_type_cast: _, - unsize_to: Some(unsize_ty), - is_implicit_coercion: true, - } if to_region == self.universal_regions().fr_static - // Mirror the note's condition, to minimize how often this diverts blame. - && let ty::Adt(_, args) = unsize_ty.kind() - && args.iter().any(|arg| arg.as_type().is_some_and(|ty| ty.is_trait())) - // Mimic old logic for this, to minimize false positives in tests. - && !path - .iter() - .any(|c| matches!(c.category, ConstraintCategory::TypeAnnotation(_))) => - { - 1 - } - // Between other interesting constraints, order by their position on the `path`. - ConstraintCategory::Yield - | ConstraintCategory::UseAsConst - | ConstraintCategory::UseAsStatic - | ConstraintCategory::TypeAnnotation( - AnnotationSource::Ascription - | AnnotationSource::Declaration - | AnnotationSource::OpaqueCast, - ) - | ConstraintCategory::Cast { .. } - | ConstraintCategory::CallArgument(_) - | ConstraintCategory::CopyBound - | ConstraintCategory::SizedBound - | ConstraintCategory::Assignment - | ConstraintCategory::Usage - | ConstraintCategory::ClosureUpvar(_) => 2, - // Generic arguments are unlikely to be what relates regions together - ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, - // We handle predicates and opaque types specially; don't prioritize them here. - ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, - // `Boring` constraints can correspond to user-written code and have useful spans, - // but don't provide any other useful information for diagnostics. - ConstraintCategory::Boring => 5, - // `BoringNoLocation` constraints can point to user-written code, but are less - // specific, and are not used for relations that would make sense to blame. - ConstraintCategory::BoringNoLocation => 6, - // Do not blame internal constraints if we can avoid it. Never blame - // the `'region: 'static` constraints introduced by placeholder outlives. - ConstraintCategory::Internal => 7, - ConstraintCategory::OutlivesUnnameablePlaceholder(_) => 8, - ConstraintCategory::SolverRegionConstraint(_) => 9, - }; + debug!("try_propagate_universal_region_error: fr_minus={:?}", longer_fr_minus); - debug!("constraint {constraint:?} category: {category:?}, interest: {interest:?}"); + // If we don't find a any non-local regions, we should error out as there is nothing + // to propagate. + if longer_fr_minus.is_empty() { + return RegionRelationCheckResult::Error; + } - interest - }; + let best_blame = self.best_blame_constraint( + longer_fr, + NllRegionVariableOrigin::FreeRegion, + shorter_fr, + ); + let OutlivesConstraint { category, span, .. } = best_blame.constraint(); - let best_choice = if blame_source { - path.iter().enumerate().rev().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 - } else { - path.iter().enumerate().min_by_key(|(_, c)| constraint_interest(c)).unwrap().0 - }; + // Grow `shorter_fr` until we find some non-local regions. + // We will always find at least one: `'static`. We'll call + // them `shorter_fr+` -- they're ever so slightly larger + // than `shorter_fr`. + let shorter_fr_plus = + self.universal_region_relations.non_local_upper_bounds(shorter_fr); + debug!("try_propagate_universal_region_error: shorter_fr_plus={:?}", shorter_fr_plus); - debug!(?best_choice, ?blame_source); + // We then create constraints `longer_fr-: shorter_fr+` that may or may not + // be propagated (see below). + let mut constraints = vec![]; + for fr_minus in longer_fr_minus { + for shorter_fr_plus in &shorter_fr_plus { + constraints.push((fr_minus, *shorter_fr_plus)); + } + } - let best_blame_idx = if let Some(next) = path.get(best_choice + 1) - && matches!(path[best_choice].category, ConstraintCategory::Return(_)) - && next.category == ConstraintCategory::OpaqueType - { - // The return expression is being influenced by the return type being - // impl Trait, point at the return type and not the return expr. - best_choice + 1 - } else if path[best_choice].category == ConstraintCategory::Return(ReturnConstraint::Normal) - && let Some(field) = path.iter().find_map(|p| { - if let ConstraintCategory::ClosureUpvar(f) = p.category { Some(f) } else { None } - }) - { - path[best_choice].category = - ConstraintCategory::Return(ReturnConstraint::ClosureUpvar(field)); - best_choice - } else { - best_choice - }; + // We only need to propagate at least one of the constraints for + // soundness. However, we want to avoid arbitrary choices here + // and currently don't support returning OR constraints. + // + // If any of the `shorter_fr+` regions are already outlived by `longer_fr-`, + // we propagate only those. + // + // Consider this example (`'b: 'a` == `a -> b`), where we try to propagate `'d: 'a`: + // a --> b --> d + // \ + // \-> c + // Here, `shorter_fr+` of `'a` == `['b, 'c]`. + // Propagating `'d: 'b` is correct and should occur; `'d: 'c` is redundant because of + // `'d: 'b` and could reject valid code. + // + // So we filter the constraints to regions already outlived by `longer_fr-`, but if + // the filter yields an empty set, we fall back to the original one. + let subset: Vec<_> = constraints + .iter() + .filter(|&&(fr_minus, shorter_fr_plus)| { + self.eval_outlives(fr_minus, shorter_fr_plus) + }) + .copied() + .collect(); + let propagated_constraints = if subset.is_empty() { constraints } else { subset }; + debug!( + "try_propagate_universal_region_error: constraints={:?}", + propagated_constraints + ); - assert!( - !matches!( - path[best_blame_idx].category, - ConstraintCategory::OutlivesUnnameablePlaceholder(_) - ), - "Illegal placeholder constraint blamed; should have redirected to other region relation" - ); + assert!( + !propagated_constraints.is_empty(), + "Expected at least one constraint to propagate here" + ); - BestBlame { path, idx: best_blame_idx } - } + for (fr_minus, fr_plus) in propagated_constraints { + // Push the constraint `long_fr-: shorter_fr+` + propagated_outlives_requirements.push(ClosureOutlivesRequirement { + subject: ClosureOutlivesSubject::Region(fr_minus), + outlived_free_region: fr_plus, + blame_span: *span, + category: *category, + }); + } + return RegionRelationCheckResult::Propagated; + } - pub(crate) fn universe_info(&self, universe: ty::UniverseIndex) -> UniverseInfo<'tcx> { - // Query canonicalization can create local superuniverses (for example in - // `InferCtx::query_response_instantiation_guess`), but they don't have an associated - // `UniverseInfo` explaining why they were created. - // This can cause ICEs if these causes are accessed in diagnostics, for example in issue - // #114907 where this happens via liveness and dropck outlives results. - // Therefore, we return a default value in case that happens, which should at worst emit a - // suboptimal error, instead of the ICE. - self.universe_causes.get(&universe).cloned().unwrap_or_else(UniverseInfo::other) + RegionRelationCheckResult::Error } - /// Tries to find the terminator of the loop in which the region 'r' resides. - /// Returns the location of the terminator if found. - pub(crate) fn find_loop_terminator_location( + fn check_bound_universal_region( &self, - r: RegionVid, - body: &Body<'_>, - ) -> Option { - let scc = self.constraint_sccs.scc(r); - let locations = self.scc_values.locations_outlived_by(scc); - for location in locations { - let bb = &body[location.block]; - if let Some(terminator) = &bb.terminator - // terminator of a loop should be TerminatorKind::FalseUnwind - && let TerminatorKind::FalseUnwind { .. } = terminator.kind - { - return Some(location); - } + longer_fr: RegionVid, + placeholder: ty::PlaceholderRegion<'tcx>, + errors_buffer: &mut RegionErrors<'tcx>, + ) { + debug!("check_bound_universal_region(fr={:?}, placeholder={:?})", longer_fr, placeholder,); + + let longer_fr_scc = self.constraint_sccs.scc(longer_fr); + debug!("check_bound_universal_region: longer_fr_scc={:?}", longer_fr_scc,); + + // If we have some bound universal region `'a`, then the only + // elements it can contain is itself -- we don't know anything + // else about it! + if let Some(error_element) = self + .scc_values + .elements_contained_in(longer_fr_scc) + .find(|e| *e != RegionElement::PlaceholderRegion(placeholder)) + { + let illegally_outlived_r = self.region_from_element(longer_fr, &error_element); + // Stop after the first error, it gets too noisy otherwise, and does not provide more information. + errors_buffer.push(RegionErrorKind::PlaceholderOutlivesIllegalRegion { + longer_fr, + illegally_outlived_r, + }); + } else { + debug!("check_bound_universal_region: all bounds satisfied"); } - None } - /// Access to the SCC constraint graph. - /// This can be used to quickly under-approximate the regions which are equal to each other - /// and their relative orderings. - // This is `pub` because it's used by unstable external borrowck data users, see `consumers.rs`. - pub(crate) fn constraint_sccs(&self) -> &ConstraintSccs { - &self.constraint_sccs + /// Get the region outlived by `longer_fr` and live at `element`. + fn region_from_element( + &self, + longer_fr: RegionVid, + element: &RegionElement<'tcx>, + ) -> RegionVid { + match *element { + RegionElement::Location(l) => self.find_sub_region_live_at(longer_fr, l), + RegionElement::RootUniversalRegion(r) => r, + RegionElement::PlaceholderRegion(error_placeholder) => self + .definitions + .iter_enumerated() + .find_map(|(r, definition)| match definition.origin { + NllRegionVariableOrigin::Placeholder(p) if p == error_placeholder => Some(r), + _ => None, + }) + .unwrap(), + } } /// Returns the representative `RegionVid` for a given SCC. @@ -1658,16 +1711,4 @@ impl<'tcx> RegionInferenceContext<'tcx> { fn scc_representative(&self, scc: ConstraintSccIndex) -> RegionVid { self.scc_annotations[scc].representative.rvid() } - - pub(crate) fn liveness_constraints(&self) -> &LivenessValues { - &self.liveness_constraints - } - - /// Returns whether the `loan_idx` is live at the given `location`: whether its issuing - /// region is contained within the type of a variable that is live at this point. - /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. - pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { - let point = self.liveness_constraints.point_from_location(location); - self.liveness_constraints.is_loan_live_at(loan_idx, point) - } } From 89c19342a93489cdd3d3a5b75f769bbd5250e9e1 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Sep 2026 16:26:25 +0200 Subject: [PATCH 0798/1309] Correctly check that an item is not `doc(hidden)`, including its parents, before generating a jump to def link --- src/librustdoc/html/format.rs | 13 +++++++++- .../jump-to-def/auxiliary/hidden-links.rs | 6 +++++ .../rustdoc-html/jump-to-def/hidden-links.rs | 26 +++++++++++++++++++ 3 files changed, 44 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs create mode 100644 tests/rustdoc-html/jump-to-def/hidden-links.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index cadfd37f9f35f..28d056588e17a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -552,6 +552,17 @@ fn make_href( url_parts.finish() } +fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool { + loop { + if tcx.is_doc_hidden(def_id) { + return true; + } else if def_id.is_crate_root() { + return false; + } + def_id = tcx.parent(def_id); + } +} + pub(crate) fn href_with_root_path( original_did: DefId, cx: &Context<'_>, @@ -590,7 +601,7 @@ pub(crate) fn href_with_root_path( // If we are generating an href for the "jump to def" feature, then the only case we want // to ignore is if the item is `doc(hidden)` because we can't link to it. if root_path.is_some() { - if tcx.is_doc_hidden(original_did) { + if inherits_doc_hidden(tcx, original_did) { return Err(HrefError::Private); } } else if !cache.effective_visibilities.is_directly_public(tcx, did) diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs b/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs new file mode 100644 index 0000000000000..c0817746a375e --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs @@ -0,0 +1,6 @@ +#[doc(hidden)] +pub mod error { + pub struct Foo; +} + +pub struct Bar; diff --git a/tests/rustdoc-html/jump-to-def/hidden-links.rs b/tests/rustdoc-html/jump-to-def/hidden-links.rs new file mode 100644 index 0000000000000..41d2a6e37c13e --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/hidden-links.rs @@ -0,0 +1,26 @@ +// This checks that if the item is not directly `doc(hidden)` but instead a parent +// is, we don't generate a link as it would lead to non-existing files. + +//@ compile-flags: -Zunstable-options --generate-link-to-definition +//@ aux-build:hidden-links.rs +//@ build-aux-docs + +#![crate_name = "foo"] + +extern crate hidden_links; + +//@ has 'src/foo/hidden-links.rs.html' + +fn foo() { + // In here, only `Bar` should be linked as `Foo` has a `doc(hidden)` parent and + // is not reexported. So there should be only one link. + + // Because our XPath handler is very bad, I can't look for `not(@id)` so instead, + // we count how many `` we have in total (line numbers are ``). + //@ count - '//pre/code/a' 7 + // Then we count the number of lines. The diff should be one (no way to test that either..). + //@ count - '//pre/code/a[@id]' 6 + //@ has - '//pre/code/a[@href="../../hidden_links/struct.Bar.html"]' 'Bar' + let x = hidden_links::error::Foo; + let x = hidden_links::Bar; +} From 8aa21475d1b01e6f780b5dcb268dd6bbf32a2d63 Mon Sep 17 00:00:00 2001 From: Bee Date: Thu, 24 Sep 2026 18:16:57 +0100 Subject: [PATCH 0799/1309] Add `f16` inline ASM support to `spirv.rs` --- compiler/rustc_target/src/asm/spirv.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_target/src/asm/spirv.rs b/compiler/rustc_target/src/asm/spirv.rs index c050c4e36b70e..19b1c37b3bfdb 100644 --- a/compiler/rustc_target/src/asm/spirv.rs +++ b/compiler/rustc_target/src/asm/spirv.rs @@ -35,7 +35,7 @@ impl SpirVInlineAsmRegClass { ) -> &'static [(InlineAsmType, Option)] { match self { Self::reg => { - types! { _: I8, I16, I32, I64, F32, F64; } + types! { _: I8, I16, I32, I64, F16, F32, F64; } } } } From e0b4fd01c723c594f02026981e9d6634cf801a27 Mon Sep 17 00:00:00 2001 From: gmes23 Date: Thu, 24 Sep 2026 13:55:01 -0400 Subject: [PATCH 0800/1309] Fix provisional cache cleanup after trait evaluation failure --- .../rustc_trait_selection/src/traits/select/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index cf8672814ff70..99016d37e49c9 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -3082,16 +3082,16 @@ impl<'tcx> ProvisionalEvaluationCache<'tcx> { /// Invoked when the node with dfn `dfn` does not get a successful /// result. This will clear out any provisional cache entries - /// that were added since `dfn` was created. This is because the - /// provisional entries are things which must assume that the - /// things on the stack at the time of their creation succeeded -- - /// since the failing node is presently at the top of the stack, - /// these provisional entries must either depend on it or some - /// ancestor of it. + /// originating from nodes visited before this node (`from_dfn < dfn`). + /// This is because the provisional entries are things which must + /// assume that the things on the stack at the time of their creation + /// succeeded -- since the failing node is presently at the top of + /// the stack, these provisional entries must either depend on it or + /// some ancestor of it. fn on_failure(&self, dfn: usize) { debug!(?dfn, "on_failure"); self.map.borrow_mut().retain(|key, eval| { - if !eval.from_dfn >= dfn { + if eval.from_dfn < dfn { debug!("on_failure: removing {:?}", key); false } else { From db4d334408af5e18bc39515b416addf9e263af1b Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Thu, 24 Sep 2026 13:50:10 -0400 Subject: [PATCH 0801/1309] cleanup: clean up more dependencies that are unused Some were wholly unused, others were unused other than as dev-deps but specified as regular dependencies. This cleans things up a little bit. I used an LLM to smoke out the candidates for this cleanup, but the rest was done by hand. --- Cargo.lock | 1 - src/tools/build-manifest/Cargo.toml | 1 - src/tools/jsondoclint/Cargo.toml | 4 +++- src/tools/remote-test-client/Cargo.toml | 2 +- src/tools/replace-version-placeholder/Cargo.toml | 1 - 5 files changed, 4 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f35ce252b78e..99c2914ff343d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3440,7 +3440,6 @@ name = "replace-version-placeholder" version = "0.1.0" dependencies = [ "tidy", - "walkdir", ] [[package]] diff --git a/src/tools/build-manifest/Cargo.toml b/src/tools/build-manifest/Cargo.toml index 0b766a3e557c5..0900afd6594fe 100644 --- a/src/tools/build-manifest/Cargo.toml +++ b/src/tools/build-manifest/Cargo.toml @@ -16,5 +16,4 @@ rayon = "1.5.1" hex = "0.4.2" [build-dependencies] -serde = "1" serde_json = "1" diff --git a/src/tools/jsondoclint/Cargo.toml b/src/tools/jsondoclint/Cargo.toml index 848c0b37ae94e..e835549878834 100644 --- a/src/tools/jsondoclint/Cargo.toml +++ b/src/tools/jsondoclint/Cargo.toml @@ -9,7 +9,9 @@ edition = "2024" anyhow = "1.0.62" clap = { version = "4.0.15", features = ["derive"] } fs-err = "2.8.1" -rustc-hash = "2.0.0" rustdoc-json-types = { version = "0.1.0", path = "../../rustdoc-json-types" } serde = { version = "1.0", features = ["derive"] } serde_json = "1.0.85" + +[dev-dependencies] +rustc-hash = "2.0.0" diff --git a/src/tools/remote-test-client/Cargo.toml b/src/tools/remote-test-client/Cargo.toml index 6fe690ba20380..70a6e896a01ab 100644 --- a/src/tools/remote-test-client/Cargo.toml +++ b/src/tools/remote-test-client/Cargo.toml @@ -3,5 +3,5 @@ name = "remote-test-client" version = "0.1.0" edition = "2021" -[dependencies] +[dev-dependencies] assert_cmd = "2" diff --git a/src/tools/replace-version-placeholder/Cargo.toml b/src/tools/replace-version-placeholder/Cargo.toml index 346ce6bd1dbfd..e581194fcf09f 100644 --- a/src/tools/replace-version-placeholder/Cargo.toml +++ b/src/tools/replace-version-placeholder/Cargo.toml @@ -7,4 +7,3 @@ edition = "2021" [dependencies] tidy = { path = "../tidy" } -walkdir = "2" From c01bd38bc07f4212de7f7781011bc24d510383af Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Wed, 9 Sep 2026 12:28:44 -0400 Subject: [PATCH 0802/1309] tests: accept more efficient simd output from LLVM 24 A recent change caused LLVM to identify `vpmov*, vpblend*` type instructions and merges them into single `vblendv*` instructions. --- tests/assembly-llvm/simd-intrinsic-select.rs | 71 +++++++++++++------- 1 file changed, 48 insertions(+), 23 deletions(-) diff --git a/tests/assembly-llvm/simd-intrinsic-select.rs b/tests/assembly-llvm/simd-intrinsic-select.rs index ca942f82ba5a3..073372b9deb7a 100644 --- a/tests/assembly-llvm/simd-intrinsic-select.rs +++ b/tests/assembly-llvm/simd-intrinsic-select.rs @@ -1,11 +1,17 @@ +// ignore-tidy-file-linelength //@ add-minicore -//@ revisions: x86-avx2 x86-avx512 aarch64 +//@ revisions: x86-avx2 x86-avx-512-llvm23 x86-avx-512 aarch64 //@ [x86-avx2] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel //@ [x86-avx2] compile-flags: -C target-feature=+avx2 //@ [x86-avx2] needs-llvm-components: x86 -//@ [x86-avx512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel -//@ [x86-avx512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq -//@ [x86-avx512] needs-llvm-components: x86 +//@ [x86-avx-512-llvm23] max-llvm-major-version: 23 +//@ [x86-avx-512-llvm23] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx-512-llvm23] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx-512-llvm23] needs-llvm-components: x86 +//@ [x86-avx-512] min-llvm-version: 24 +//@ [x86-avx-512] compile-flags: --target=x86_64-unknown-linux-gnu -C llvm-args=-x86-asm-syntax=intel +//@ [x86-avx-512] compile-flags: -C target-feature=+avx512f,+avx512vl,+avx512bw,+avx512dq +//@ [x86-avx-512] needs-llvm-components: x86 //@ [aarch64] compile-flags: --target=aarch64-unknown-linux-gnu //@ [aarch64] needs-llvm-components: aarch64 //@ assembly-output: emit-asm @@ -34,9 +40,13 @@ pub unsafe extern "C" fn select_i8x16(mask: m8x16, a: i8x16, b: i8x16) -> i8x16 // x86-avx2-NOT: vpsllw // x86-avx2: vpblendvb xmm0, xmm2, xmm1, xmm0 // - // x86-avx512-NOT: vpsllw - // x86-avx512: vpmovb2m k1, xmm0 - // x86-avx512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 + // x86-avx-512-llvm23-NOT: vpsllw + // x86-avx-512-llvm23: vpmovb2m k1, xmm0 + // x86-avx-512-llvm23-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 + // + // x86-avx-512-NOT: vpsllw + // x86-avx-512: vpmovb2m k1, xmm0 + // x86-avx-512-NEXT: vpblendmb xmm0 {k1}, xmm2, xmm1 // // aarch64-NOT: shl // aarch64: cmlt v0.16b, v0.16b, #0 @@ -50,9 +60,12 @@ pub unsafe extern "C" fn select_f32x4(mask: m32x4, a: f32x4, b: f32x4) -> f32x4 // x86-avx2-NOT: vpslld // x86-avx2: vblendvps xmm0, xmm2, xmm1, xmm0 // - // x86-avx512-NOT: vpslld - // x86-avx512: vpmovd2m k1, xmm0 - // x86-avx512-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1 + // x86-avx-512-llvm23-NOT: vpslld + // x86-avx-512-llvm23: vpmovd2m k1, xmm0 + // x86-avx-512-llvm23-NEXT: vblendmps xmm0 {k1}, xmm2, xmm1 + // + // x86-avx-512-NOT: vpslld + // x86-avx-512: vblendvps xmm0, xmm2, xmm1, xmm0 // // aarch64-NOT: shl // aarch64: cmlt v0.4s, v0.4s, #0 @@ -66,9 +79,12 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 // x86-avx2-NOT: vpsllq // x86-avx2: vblendvpd xmm0, xmm2, xmm1, xmm0 // - // x86-avx512-NOT: vpsllq - // x86-avx512: vpmovq2m k1, xmm0 - // x86-avx512-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1 + // x86-avx-512-llvm23-NOT: vpsllq + // x86-avx-512-llvm23: vpmovq2m k1, xmm0 + // x86-avx-512-llvm23-NEXT: vblendmpd xmm0 {k1}, xmm2, xmm1 + // + // x86-avx-512-NOT: vpsllq + // x86-avx-512: vblendvpd xmm0, xmm2, xmm1, xmm0 // // aarch64-NOT: shl // aarch64: cmlt v0.2d, v0.2d, #0 @@ -77,29 +93,38 @@ pub unsafe extern "C" fn select_f64x2(mask: m64x2, a: f64x2, b: f64x2) -> f64x2 } // x86-avx2-LABEL: select_f64x4 -// x86-avx512-LABEL: select_f64x4 +// x86-avx-512-llvm23-LABEL: select_f64x4 +// x86-avx-512-LABEL: select_f64x4 #[no_mangle] -#[cfg(any(x86_avx2, x86_avx512))] +#[cfg(any(x86_avx2, x86_avx_512, x86_avx_512_llvm23))] pub unsafe extern "C" fn select_f64x4(mask: m64x4, a: f64x4, b: f64x4) -> f64x4 { // The parameter is a 256 bit vector which in the C abi is only valid for avx targets. // // x86-avx2-NOT: vpsllq // x86-avx2: vblendvpd ymm0, ymm2, ymm1, ymm0 // - // x86-avx512-NOT: vpsllq - // x86-avx512: vpmovq2m k1, ymm0 - // x86-avx512-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1 + // x86-avx-512-llvm23-NOT: vpsllq + // x86-avx-512-llvm23: vpmovq2m k1, ymm0 + // x86-avx-512-llvm23-NEXT: vblendmpd ymm0 {k1}, ymm2, ymm1 + // + // x86-avx-512-NOT: vpsllq + // x86-avx-512: vblendvpd ymm0, ymm2, ymm1, ymm0 simd_select(mask, a, b) } -// x86-avx512-LABEL: select_f64x8 +// x86-avx-512-llvm23-LABEL: select_f64x8 +// x86-avx-512-LABEL: select_f64x8 #[no_mangle] -#[cfg(x86_avx512)] +#[cfg(any(x86_avx_512, x86_avx_512_llvm23))] pub unsafe extern "C" fn select_f64x8(mask: m64x8, a: f64x8, b: f64x8) -> f64x8 { // The parameter is a 256 bit vector which in the C abi is only valid for avx512 targets. // - // x86-avx512-NOT: vpsllq - // x86-avx512: vpmovq2m k1, zmm0 - // x86-avx512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 + // x86-avx-512-llvm23-NOT: vpsllq + // x86-avx-512-llvm23: vpmovq2m k1, zmm0 + // x86-avx-512-llvm23-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 + // + // x86-avx-512-NOT: vpsllq + // x86-avx-512: vpmovq2m k1, zmm0 + // x86-avx-512-NEXT: vblendmpd zmm0 {k1}, zmm2, zmm1 simd_select(mask, a, b) } From d6d250c7dd35b423f519e0948f373ab279f8276c Mon Sep 17 00:00:00 2001 From: eleocraft Date: Thu, 24 Sep 2026 21:27:29 +0200 Subject: [PATCH 0803/1309] adding coretests and fixing docs Adding tests addressing the changes in coretests/tests/num/clamp_magnitude.rs --- library/core/src/num/nonzero.rs | 6 +- .../coretests/tests/num/clamp_magnitude.rs | 95 +++++++++++++++++++ 2 files changed, 99 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 37223932a0b0f..513166bf12cae 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -2454,9 +2454,11 @@ macro_rules! nonzero_integer_signedness_dependent_methods { unsafe { NonZero::new_unchecked(self.get().cast_unsigned()) } } - /// clamps this number to a symmetric range centred around zero. the method clamps the number's magnitude (absolute value) to be at most `limit`. + /// Clamps this number to a symmetric range centred around zero. /// - /// this is functionally equivalent to `self.clamp(-limit, limit)`, but is more + /// The method clamps the number's magnitude (absolute value) to be at most `limit`. + /// + /// This is functionally equivalent to `self.clamp(-limit, limit)`, but is more /// explicit about the intent. /// /// # Examples diff --git a/library/coretests/tests/num/clamp_magnitude.rs b/library/coretests/tests/num/clamp_magnitude.rs index b8ba402a6660a..11ae7a7549111 100644 --- a/library/coretests/tests/num/clamp_magnitude.rs +++ b/library/coretests/tests/num/clamp_magnitude.rs @@ -1,3 +1,5 @@ +use core::num::*; + macro_rules! check_int_clamp { ($t:ty, $ut:ty) => { let min = <$t>::MIN; @@ -32,6 +34,16 @@ macro_rules! check_int_clamp { // Limit larger than type max (uN > iN::MAX) assert_eq!(max.clamp_magnitude(max_u), max); assert_eq!(min.clamp_magnitude(max_u), min); + + // Const clamping + const C1: $t = (100 as $t).clamp_magnitude(50); + assert_eq!(C1, 50); + const C2: $t = (-100 as $t).clamp_magnitude(50); + assert_eq!(C2, -50); + const C3: $t = (30 as $t).clamp_magnitude(50); + assert_eq!(C3, 30); + const C4: $t = (-30 as $t).clamp_magnitude(50); + assert_eq!(C4, -30); }; } @@ -65,6 +77,79 @@ fn test_clamp_magnitude_isize() { check_int_clamp!(isize, usize); } +macro_rules! check_nonzero_clamp { + ($t:ty, $ut:ty) => { + let min = <$t>::MIN; + let max = <$t>::MAX; + let max_u = <$ut>::MAX; + + // Basic clamping + let lim = <$ut>::new(50).unwrap(); + assert_eq!(<$t>::new(100).unwrap().clamp_magnitude(lim), <$t>::new(50).unwrap()); + assert_eq!(<$t>::new(-100).unwrap().clamp_magnitude(lim), <$t>::new(-50).unwrap()); + assert_eq!(<$t>::new(30).unwrap().clamp_magnitude(lim), <$t>::new(30).unwrap()); + assert_eq!(<$t>::new(-30).unwrap().clamp_magnitude(lim), <$t>::new(-30).unwrap()); + + // Exact boundary + assert_eq!(<$t>::new(50).unwrap().clamp_magnitude(lim), <$t>::new(50).unwrap()); + assert_eq!(<$t>::new(-50).unwrap().clamp_magnitude(lim), <$t>::new(-50).unwrap()); + + // MIN/MAX values + // Symmetric range [-MAX, MAX] + assert_eq!(max.clamp_magnitude(max.try_into().unwrap()), max); + assert_eq!(min.clamp_magnitude(max.try_into().unwrap()), -max); + + // Full range (limit covers MIN) + let min_abs = min.unsigned_abs(); + assert_eq!(min.clamp_magnitude(min_abs), min); + + // Limit larger than type max (uN > iN::MAX) + assert_eq!(max.clamp_magnitude(max_u), max); + assert_eq!(min.clamp_magnitude(max_u), min); + + // Const clamping + const LIM: $ut = <$ut>::new(50).unwrap(); + const C1: $t = <$t>::new(100).unwrap().clamp_magnitude(LIM); + assert_eq!(C1, <$t>::new(50).unwrap()); + const C2: $t = <$t>::new(-100).unwrap().clamp_magnitude(LIM); + assert_eq!(C2, <$t>::new(-50).unwrap()); + const C3: $t = <$t>::new(30).unwrap().clamp_magnitude(LIM); + assert_eq!(C3, <$t>::new(30).unwrap()); + const C4: $t = <$t>::new(-30).unwrap().clamp_magnitude(LIM); + assert_eq!(C4, <$t>::new(-30).unwrap()); + }; +} + +#[test] +fn test_clamp_magnitude_nonzero_i8() { + check_nonzero_clamp!(NonZeroI8, NonZeroU8); +} + +#[test] +fn test_clamp_magnitude_nonzero_i16() { + check_nonzero_clamp!(NonZeroI16, NonZeroU16); +} + +#[test] +fn test_clamp_magnitude_nonzero_i32() { + check_nonzero_clamp!(NonZeroI32, NonZeroU32); +} + +#[test] +fn test_clamp_magnitude_nonzero_i64() { + check_nonzero_clamp!(NonZeroI64, NonZeroU64); +} + +#[test] +fn test_clamp_magnitude_nonzero_i128() { + check_nonzero_clamp!(NonZeroI128, NonZeroU128); +} + +#[test] +fn test_clamp_magnitude_nonzero_isize() { + check_nonzero_clamp!(NonZeroIsize, NonZeroUsize); +} + macro_rules! check_float_clamp { ($t:ty) => { // Basic clamping @@ -101,6 +186,16 @@ macro_rules! check_float_clamp { let huge = 1e30; assert_eq!(max.clamp_magnitude(huge), huge); assert_eq!(min.clamp_magnitude(huge), -huge); + + // Const clamping + const C1: $t = (5.0 as $t).clamp_magnitude(3.0); + assert_eq!(C1, 3.0); + const C2: $t = (-5.0 as $t).clamp_magnitude(3.0); + assert_eq!(C2, -3.0); + const C3: $t = (2.0 as $t).clamp_magnitude(3.0); + assert_eq!(C3, 2.0); + const C4: $t = (-2.0 as $t).clamp_magnitude(3.0); + assert_eq!(C4, -2.0); }; } From 4de84d7f2a2c490a83a4ff33a61aab9387d967b4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Thu, 24 Sep 2026 22:15:20 +0200 Subject: [PATCH 0804/1309] Correctly handle `impl` items when checking if an item parents have `doc(hidden)` --- src/librustdoc/html/format.rs | 61 +++++++++++++++---- .../jump-to-def/auxiliary/hidden-links.rs | 13 ++++ .../rustdoc-html/jump-to-def/hidden-links.rs | 31 +++++++--- 3 files changed, 85 insertions(+), 20 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 28d056588e17a..4ee91d411903a 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -19,7 +19,7 @@ use rustc_hir::def::{DefKind, MacroKinds}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_hir::{ConstStability, StabilityLevel, StableSince}; use rustc_metadata::creader::CStore; -use rustc_middle::ty::{self, TyCtxt, TypingMode}; +use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_span::symbol::kw; use rustc_span::{Ident, Symbol}; use tracing::{debug, trace}; @@ -410,17 +410,28 @@ fn generate_macro_def_id_path( Ok(HrefInfo { url, kind: item_type, rust_path: path }) } +/// Takes an impl `DefId` and return the self `Ty` of the impl. +fn impl_self_ty(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Ty<'_> { + use rustc_middle::traits::ObligationCause; + use rustc_middle::ty; + use rustc_trait_selection::infer::TyCtxtInferExt; + use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; + + let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); + let ty = tcx.type_of(impl_def_id); + infcx + .at(&ObligationCause::dummy(), tcx.param_env(impl_def_id)) + .query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip())) + .map(|resolved| infcx.deeply_resolve_ignoring_regions(resolved.value).skip_binder()) + .unwrap_or(ty.skip_binder()) +} + fn generate_item_def_id_path( mut def_id: DefId, original_def_id: DefId, cx: &Context<'_>, root_path: Option<&str>, ) -> Result { - use rustc_middle::traits::ObligationCause; - use rustc_middle::ty; - use rustc_trait_selection::infer::TyCtxtInferExt; - use rustc_trait_selection::traits::query::normalize::QueryNormalizeExt; - let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); let mut prim = None; @@ -428,13 +439,7 @@ fn generate_item_def_id_path( // No need to try to infer the actual parent item if it's not an associated item from the `impl` // block. if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { - let infcx = tcx.infer_ctxt().build(TypingMode::non_body_analysis()); - let ty = tcx.type_of(def_id); - let ty = infcx - .at(&ObligationCause::dummy(), tcx.param_env(def_id)) - .query_normalize(ty::Binder::dummy(ty.instantiate_identity().skip_norm_wip())) - .map(|resolved| infcx.deeply_resolve_ignoring_regions(resolved.value).skip_binder()) - .unwrap_or(ty.skip_binder()); + let ty = impl_self_ty(tcx, def_id); // If this is a dyn trait, we want to get the actual trait from which the method comes from. // Since a `dyn trait` (as of 2026) can only be composed of a trait plus auto traits, we // look for the trait and ignore auto traits. @@ -552,12 +557,42 @@ fn make_href( url_parts.finish() } +fn ty_inherits_doc_hidden<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> bool { + match ty.kind() { + // If this is a dyn trait, we want to get the actual trait from which the method comes from. + // Since a `dyn trait` (as of 2026) can only be composed of a trait plus auto traits, we + // look for the trait and ignore auto traits. + ty::Dynamic(traits, _) => traits + .iter() + .find_map(|trait_| match trait_.skip_binder() { + ty::ExistentialPredicate::Trait(t) => Some(inherits_doc_hidden(tcx, t.def_id)), + ty::ExistentialPredicate::Projection(p) => { + Some(inherits_doc_hidden(tcx, p.trait_ref(tcx).def_id)) + } + ty::ExistentialPredicate::AutoTrait(_) => None, + }) + .unwrap_or(false), + ty::Adt(adt, _) => inherits_doc_hidden(tcx, adt.did()), + ty::Foreign(def_id) => inherits_doc_hidden(tcx, *def_id), + ty::Ref(_, ty, _) => ty_inherits_doc_hidden(tcx, *ty), + // For now we consider that everything doesn't inherit `#[doc(hidden)]`. To be confirmed + // later. + _ => false, + } +} + fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool { loop { if tcx.is_doc_hidden(def_id) { return true; } else if def_id.is_crate_root() { return false; + } else if let DefKind::Impl { of_trait } = tcx.def_kind(def_id) { + // `impl` blocks stand a bit on their own: unless they have `#[doc(hidden)]` directly + // on them, they don't inherit it from the parent context. + // Instead we check that the `Self` item and the trait aren't hidden. + return ty_inherits_doc_hidden(tcx, impl_self_ty(tcx, def_id)) + || (of_trait && inherits_doc_hidden(tcx, tcx.impl_trait_id(def_id))); } def_id = tcx.parent(def_id); } diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs b/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs index c0817746a375e..342a4765f4f7d 100644 --- a/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs +++ b/tests/rustdoc-html/jump-to-def/auxiliary/hidden-links.rs @@ -1,6 +1,19 @@ #[doc(hidden)] pub mod error { pub struct Foo; + + pub trait HiddenTrait { + fn hidden(&self) {} + } } pub struct Bar; +pub trait PubTrait { + fn public(&self) {} +} + +impl crate::error::HiddenTrait for crate::error::Foo {} +impl crate::error::HiddenTrait for Bar {} + +impl PubTrait for crate::error::Foo {} +impl PubTrait for Bar {} diff --git a/tests/rustdoc-html/jump-to-def/hidden-links.rs b/tests/rustdoc-html/jump-to-def/hidden-links.rs index 41d2a6e37c13e..848265f38f514 100644 --- a/tests/rustdoc-html/jump-to-def/hidden-links.rs +++ b/tests/rustdoc-html/jump-to-def/hidden-links.rs @@ -11,16 +11,33 @@ extern crate hidden_links; //@ has 'src/foo/hidden-links.rs.html' +// Because our XPath handler is very bad, I can't look for `not(@id)` so instead, +// we count how many `` we have in total (line numbers are ``). +//@ count - '//pre/code/a' 21 +// Then we count the `` of lines. The diff should be the number of non-line `` (no +// better way to test that either..). +//@ count - '//pre/code/a[@id]' 13 + +//@ has - '//pre/code/a[@href="../../hidden_links/trait.PubTrait.html"]' 'PubTrait' +use hidden_links::{PubTrait, error::HiddenTrait}; + fn foo() { // In here, only `Bar` should be linked as `Foo` has a `doc(hidden)` parent and // is not reexported. So there should be only one link. - // Because our XPath handler is very bad, I can't look for `not(@id)` so instead, - // we count how many `` we have in total (line numbers are ``). - //@ count - '//pre/code/a' 7 - // Then we count the number of lines. The diff should be one (no way to test that either..). - //@ count - '//pre/code/a[@id]' 6 - //@ has - '//pre/code/a[@href="../../hidden_links/struct.Bar.html"]' 'Bar' + // This one should not generate any link. let x = hidden_links::error::Foo; - let x = hidden_links::Bar; + //@ has - '//pre/code/a[@href="../../hidden_links/struct.Bar.html"]' 'Bar' + let y = hidden_links::Bar; + + // `x` and `y` generate a link every time... + //@ count - '//pre/code/a[@href="#29"]' 2 + //@ count - '//pre/code/a[@href="#31"]' 2 + // FIXME(GuillaumeGomez): This is a bug, it should link the trait method on the item's page, + // not on the trait's (and so `x.public()`) should not link. + //@ count - '//pre/code/a[@href="../../hidden_links/trait.PubTrait.html#method.public"]' 2 + x.hidden(); + y.hidden(); + x.public(); + y.public(); } From 3026ffe0c4f6c42a2f82005a377ab74f4fdfead3 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 25 Jul 2026 22:42:32 +0200 Subject: [PATCH 0805/1309] make SPARC `Complex` ABI GCC-compatible In clang >= 23 the ABI for complex is incompatible with GCC. This has been fixed in https://github.com/llvm/llvm-project/pull/212340 and will be part of clang 24 --- compiler/rustc_target/src/callconv/sparc.rs | 57 +++++++++++++++++---- tests/codegen-llvm/complex-abi.rs | 23 ++++----- 2 files changed, 57 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_target/src/callconv/sparc.rs b/compiler/rustc_target/src/callconv/sparc.rs index dc4d4a7f51225..d367efaf746f0 100644 --- a/compiler/rustc_target/src/callconv/sparc.rs +++ b/compiler/rustc_target/src/callconv/sparc.rs @@ -1,20 +1,42 @@ -use rustc_abi::{BackendRepr, Float, HasDataLayout, Primitive, TyAbiInterface}; +use rustc_abi::{ + BackendRepr, Float, HasDataLayout, Integer, Numeric, Primitive, RegKind, TyAbiInterface, +}; -use crate::callconv::{ArgAbi, FnAbi}; +use crate::callconv::{ArgAbi, ArgAttribute, CastTarget, FnAbi, Reg}; -fn classify<'a, Ty>(arg: &mut ArgAbi<'a, Ty>) { - if arg.layout.is_aggregate() { - arg.make_indirect(); - } else if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr +fn classify_shared<'a, Ty>(val: &mut ArgAbi<'a, Ty>) { + if val.layout.is_aggregate() { + val.make_indirect(); + } else if let BackendRepr::Scalar(scalar) = val.layout.backend_repr && scalar.primitive() == Primitive::Float(Float::F128) { - // Always pass f128 indirectly. - arg.make_indirect(); + // f128 is passed and returned indirectly. + val.make_indirect(); } else { - arg.extend_integer_width_to(32); + val.extend_integer_width_to(32); } } +fn classify_complex_ret<'a, Ty>(ret: &mut ArgAbi<'a, Ty>, component: Numeric) { + let reg = Reg { kind: component.reg_kind(), size: component.size() }; + let mut cast = CastTarget::pair(reg, reg); + + match component { + Numeric::Float(Float::F128) => { + // Mark `_Complex long double` as inreg to get the right behavior, + // consistent with clang `SparcV8ABIInfo::classifyReturnType`. + cast.attrs.set(ArgAttribute::InReg); + } + Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) => { + let size = ret.layout.size; + cast = CastTarget::from(Reg { kind: RegKind::Integer, size }); + } + _ => { /* default behavior */ } + } + + ret.cast_to(cast); +} + fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, @@ -29,7 +51,16 @@ where return; } - classify(arg); + if let Some(component) = arg.layout.complex_number(cx) { + if let Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) = component { + arg.cast_to(Reg { kind: RegKind::Integer, size: 2 * component.size() }); + } else { + arg.make_indirect(); + } + return; + } + + classify_shared(arg) } pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>) @@ -38,7 +69,11 @@ where C: HasDataLayout, { if !fn_abi.ret.is_ignore() { - classify(&mut fn_abi.ret); + if let Some(component) = fn_abi.ret.layout.complex_number(cx) { + classify_complex_ret(&mut fn_abi.ret, component); + } else { + classify_shared(&mut fn_abi.ret); + }; } for arg in fn_abi.args.iter_mut() { diff --git a/tests/codegen-llvm/complex-abi.rs b/tests/codegen-llvm/complex-abi.rs index c900c3debd504..3235627e9ca5f 100644 --- a/tests/codegen-llvm/complex-abi.rs +++ b/tests/codegen-llvm/complex-abi.rs @@ -61,9 +61,11 @@ //@ [CSKY] compile-flags: --target csky-unknown-linux-gnuabiv2 //@ [CSKY] needs-llvm-components: csky -//@ revisions: SPARC64 +//@ revisions: SPARC64 SPARC //@ [SPARC64] compile-flags: --target sparc64-unknown-linux-gnu //@ [SPARC64] needs-llvm-components: sparc +//@ [SPARC] compile-flags: --target sparc-unknown-linux-gnu +//@ [SPARC] needs-llvm-components: sparc //@ revisions: POWERPC64LE POWERPC64 AIX //@ [POWERPC64LE] compile-flags: --target powerpc64le-unknown-linux-gnu @@ -75,10 +77,6 @@ // FIXME: the below revisions are deliberately disabled for now. -// revisions: SPARC -// [SPARC] compile-flags: --target sparc-unknown-linux-gnu -// [SPARC] needs-llvm-components: sparc - // revisions: POWERPC // [POWERPC] compile-flags: --target powerpc-unknown-linux-gnu // [POWERPC] needs-llvm-components: powerpc @@ -155,7 +153,7 @@ pub extern "C" fn cplx_f32(x: Complex) -> Complex { // RISCV64: define{{.*}} { float, float } @cplx_f32({ float, float } {{.*}}) // S390X: define{{.*}} void @cplx_f32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} { float, float } @cplx_f32({ float, float } {{.*}}) - // SPARC: define{{.*}} { float, float } @cplx_f32(ptr {{.*}} byval({ float, float }) {{.*}}) + // SPARC: define{{.*}} { float, float } @cplx_f32(ptr {{.*}} dereferenceable(8) {{.*}}) // WASM32: define{{.*}} void @cplx_f32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_f32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} i64 @cplx_f32(ptr {{.*}} byval([8 x i8]) {{.*}}) @@ -189,7 +187,7 @@ pub extern "C" fn cplx_f64(x: Complex) -> Complex { // RISCV64: define{{.*}} { double, double } @cplx_f64({ double, double } {{.*}}) // S390X: define{{.*}} void @cplx_f64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} { double, double } @cplx_f64({ double, double } {{.*}}) - // SPARC: define{{.*}} { double, double } @cplx_f64(ptr {{.*}} byval({ double, double }) {{.*}}) + // SPARC: define{{.*}} { double, double } @cplx_f64(ptr {{.*}} dereferenceable(16) {{.*}}) // WASM32: define{{.*}} void @cplx_f64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_f64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} void @cplx_f64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) @@ -204,6 +202,7 @@ pub extern "C" fn cplx_f64(x: Complex) -> Complex { pub extern "C" fn cplx_f128(x: Complex) -> Complex { // AARCH64: define{{.*}} [2 x fp128] {{.*}}) // I686: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}} byval([32 x i8]) {{.*}}) + // SPARC: define{{.*}} inreg { fp128, fp128 } @cplx_f128(ptr {{.*}} dereferenceable(32) {{.*}}) // WASM32: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}} byval([32 x i8]) {{.*}}) @@ -237,7 +236,7 @@ pub extern "C" fn cplx_i8(x: Complex) -> Complex { // RISCV64: define{{.*}} i64 @cplx_i8(i64{{.*}}) // S390X: define{{.*}} void @cplx_i8(ptr {{.*}} sret([2 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} i16 @cplx_i8(i16{{.*}}) - // SPARC: define{{.*}} { i8, i8 } @cplx_i8(ptr {{.*}} byval({ i8, i8 }) {{.*}}) + // SPARC: define{{.*}} i16 @cplx_i8(i16{{.*}}) // WASM32: define{{.*}} void @cplx_i8(ptr {{.*}} sret([2 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_i8(ptr {{.*}} sret([2 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} i16 @cplx_i8(ptr {{.*}} byval([2 x i8]) {{.*}}) @@ -271,7 +270,7 @@ pub extern "C" fn cplx_i16(x: Complex) -> Complex { // RISCV64: define{{.*}} i64 @cplx_i16(i64{{.*}}) // S390X: define{{.*}} void @cplx_i16(ptr {{.*}} sret([4 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} i32 @cplx_i16(i32{{.*}}) - // SPARC: define{{.*}} { i16, i16 } @cplx_i16(ptr {{.*}} byval({ i16, i16 }) {{.*}}) + // SPARC: define{{.*}} i32 @cplx_i16(i32{{.*}}) // WASM32: define{{.*}} void @cplx_i16(ptr {{.*}} sret([4 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_i16(ptr {{.*}} sret([4 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} i32 @cplx_i16(ptr {{.*}} byval([4 x i8]) {{.*}}) @@ -305,7 +304,7 @@ pub extern "C" fn cplx_i32(x: Complex) -> Complex { // RISCV64: define{{.*}} i64 @cplx_i32(i64 {{.*}}) // S390X: define{{.*}} void @cplx_i32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} i64 @cplx_i32(i64 {{.*}}) - // SPARC: define{{.*}} { i32, i32 } @cplx_i32(ptr {{.*}} byval({ i32, i32 }) {{.*}}) + // SPARC: define{{.*}} i64 @cplx_i32(i64 {{.*}}) // WASM32: define{{.*}} void @cplx_i32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_i32(ptr {{.*}} sret([8 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} i64 @cplx_i32(ptr {{.*}} byval([8 x i8]) {{.*}}) @@ -339,7 +338,7 @@ pub extern "C" fn cplx_i64(x: Complex) -> Complex { // RISCV64: define{{.*}} [2 x i64] @cplx_i64([2 x i64] {{.*}}) // S390X: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define{{.*}} { i64, i64 } @cplx_i64({ i64, i64 } {{.*}}) - // SPARC: define{{.*}} { i64, i64 } @cplx_i64(ptr {{.*}} byval({ i64, i64 }) {{.*}}) + // SPARC: define{{.*}} { i64, i64 } @cplx_i64(ptr {{.*}} dereferenceable(16) {{.*}}) // WASM32: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) @@ -378,7 +377,7 @@ pub extern "C" fn wrapper_cplx_i64( // RISCV64: define{{.*}} [2 x i64] @wrapper_cplx_i64([2 x i64] {{.*}}) // S390X: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // SPARC64: define { i64, i64 } @wrapper_cplx_i64({ i64, i64 } {{.*}}) - // SPARC: define{{.*}} { i64, i64 } @wrapper_cplx_i64(ptr {{.*}} byval({ i64, i64 }) {{.*}}) + // SPARC: define{{.*}} { i64, i64 } @wrapper_cplx_i64(ptr {{.*}} dereferenceable(16) {{.*}}) // WASM32: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // WIN32_GNU: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) From 876f7a0c297de344e33b7d85c86d20a24731322a Mon Sep 17 00:00:00 2001 From: ultrabear Date: Thu, 24 Sep 2026 14:05:52 -0700 Subject: [PATCH 0806/1309] Tweak Layout::from_size_align_unchecked safety comment --- library/core/src/alloc/layout.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/alloc/layout.rs b/library/core/src/alloc/layout.rs index edf266174bd4e..0ae297ad294e4 100644 --- a/library/core/src/alloc/layout.rs +++ b/library/core/src/alloc/layout.rs @@ -122,7 +122,7 @@ impl Layout { /// /// # Safety /// - /// This function is unsafe as it does not verify the preconditions from + /// The arguments passed must meet the preconditions from /// [`Layout::from_size_align`]. #[stable(feature = "alloc_layout", since = "1.28.0")] #[rustc_const_stable(feature = "const_alloc_layout_unchecked", since = "1.36.0")] From e01dc94337d6873e5c7df8afa4b3fd6ab97aca25 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 18 Sep 2026 09:40:36 +1000 Subject: [PATCH 0807/1309] Some `emit_diagnostic` improvements There is one match arm handling some `ForceWarning` cases and another arm handling the remaining `ForceWarning` case and also `Expect`. They can be rearranged into one arm handling `ForceWarning` and one arm handling `Expect`. Also fix some comments: - `ForceWarning` no longer has a field. - Clarify the `LintExpectationId` location. - The one about deduplication was inverted. --- compiler/rustc_errors/src/lib.rs | 27 +++++++++++++++------------ compiler/rustc_middle/src/lint.rs | 2 +- 2 files changed, 16 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 97b8557b95ef6..df9ce5f0673b8 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1258,7 +1258,11 @@ impl DiagCtxtInner { }; } } - ForceWarning if diagnostic.lint_id.is_none() => {} // `ForceWarning(Some(...))` is below, with `Expect` + ForceWarning => { + if let Some(lint_id) = diagnostic.lint_id { + self.fulfilled_expectations.insert(lint_id); + } + } Warning => { if !self.flags.can_emit_warnings { // We are not emitting warnings. @@ -1279,14 +1283,12 @@ impl DiagCtxtInner { } return None; } - Expect | ForceWarning => { + Expect => { self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap()); - if let Expect = diagnostic.level { - // Nothing emitted here for expected lints. - TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); - self.suppressed_expected_diag = true; - return None; - } + // Nothing emitted here for expected lints. + TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); + self.suppressed_expected_diag = true; + return None; } } @@ -1313,7 +1315,7 @@ impl DiagCtxtInner { ) && mem::replace(&mut self.emitted_recursion_depth_exceeding_limit, true) }); - // Only emit the diagnostic if we've been asked to deduplicate or + // Only emit the diagnostic if deduplication is disabled or we // haven't already emitted an equivalent diagnostic. if !silence_recursion_depth_exceeded_limit && !(self.flags.deduplicate_diagnostics && already_emitted) @@ -1580,8 +1582,8 @@ pub enum Level { /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation /// from finishing. /// - /// Requires a [`LintExpectationId`] for expected lint diagnostics. In all other cases this - /// should be `None`. + /// Requires the corresponding `DiagInner::lint_id` to be `Some` for expected lint diagnostics, + /// and `None` in all other cases. ForceWarning, /// A warning about the code being compiled. Does not prevent compilation from finishing. @@ -1605,7 +1607,8 @@ pub enum Level { /// Only used for lints. Allow, - /// Only used for lints. Requires a [`LintExpectationId`] for silencing the lints. + /// Only used for lints. Requires the corresponding `DiagInner::lint_id` to be `Some` to + /// silence the lints. Expect, } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 820375ada47a5..5d631acc1b528 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -477,7 +477,7 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( // emitted or we'll get a `must_produce_diag` ICE. // // When is a diagnostic *eventually* emitted? Well, that is determined by 2 factors: - // 1. If the corresponding `rustc_errors::Level` is beyond warning, i.e. `ForceWarning(_)` + // 1. If the corresponding `rustc_errors::Level` is beyond warning, i.e. `ForceWarning` // or `Error`, then the diagnostic will be emitted regardless of CLI options. // 2. If the corresponding `rustc_errors::Level` is warning, then that can be affected by // `-A warnings` or `--cap-lints=xxx` on the command line. In which case, the diagnostic From 4fc112e765339c75e13bfc8b849b2a4274a90aaf Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 22 Sep 2026 12:48:55 +1000 Subject: [PATCH 0808/1309] Remove an out-of-date FIXME comment I think the ship has sailed on the "every error should have an error code" idea and it's not worth pretending otherwise. --- compiler/rustc_errors/src/lib.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index df9ce5f0673b8..33db5577baeb5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -1018,7 +1018,6 @@ impl<'a> DiagCtxtHandle<'a> { self.create_fatal(fatal).emit_fatal() } - // FIXME: This method should be removed (every error should have an associated error code). #[track_caller] pub fn struct_err(self, msg: impl Into) -> Diag<'a> { Diag::new(self, Error, msg) From 980e0f01b82c028766868159eab37628bd277b8c Mon Sep 17 00:00:00 2001 From: eleocraft Date: Fri, 25 Sep 2026 02:06:26 +0200 Subject: [PATCH 0809/1309] moving div_ceil() to associated items macro --- library/core/src/num/nonzero.rs | 62 ++++++++++++++++----------------- 1 file changed, 30 insertions(+), 32 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 595f3d2248190..e12e8c7dffc43 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -1573,38 +1573,6 @@ macro_rules! nonzero_integer_signedness_dependent_impls { *self = *self % other; } } - - impl NonZero<$Int> { - /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. - /// - /// The result is guaranteed to be non-zero. - /// - /// # Examples - /// - /// ``` - /// # use std::num::NonZero; - #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ").unwrap();")] - #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX).unwrap();")] - /// assert_eq!(one.div_ceil(max), one); - /// - #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ").unwrap();")] - #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ").unwrap();")] - /// assert_eq!(three.div_ceil(two), two); - /// ``` - #[stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")] - #[rustc_const_stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")] - #[must_use = "this returns the result of the operation, \ - without modifying the original"] - #[inline] - pub const fn div_ceil(self, rhs: Self) -> Self { - // An implementation of the function without calculating the remainder. - // It is better than the implementation for normal integers, but it can only - // be used here because of the possibility to subtract by one without overflow. - let v = (self.get() - 1) / rhs.get() + 1; - // SAFETY: ceiled division of two positive integers can never be zero. - unsafe { Self::new_unchecked(v) } - } - } }; // Impls for signed nonzero types only. (signed $Int:ty) => { @@ -1772,6 +1740,36 @@ macro_rules! nonzero_integer_signedness_dependent_methods { unsafe { Self::new_unchecked(self.get().unchecked_add(other)) } } + /// Calculates the quotient of `self` and `rhs`, rounding the result towards positive infinity. + /// + /// The result is guaranteed to be non-zero. + /// + /// # Examples + /// + /// ``` + /// # use std::num::NonZero; + #[doc = concat!("let one = NonZero::new(1", stringify!($Int), ").unwrap();")] + #[doc = concat!("let max = NonZero::new(", stringify!($Int), "::MAX).unwrap();")] + /// assert_eq!(one.div_ceil(max), one); + /// + #[doc = concat!("let two = NonZero::new(2", stringify!($Int), ").unwrap();")] + #[doc = concat!("let three = NonZero::new(3", stringify!($Int), ").unwrap();")] + /// assert_eq!(three.div_ceil(two), two); + /// ``` + #[stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")] + #[rustc_const_stable(feature = "unsigned_nonzero_div_ceil", since = "1.92.0")] + #[must_use = "this returns the result of the operation, \ + without modifying the original"] + #[inline] + pub const fn div_ceil(self, rhs: Self) -> Self { + // An implementation of the function without calculating the remainder. + // It is better than the implementation for normal integers, but it can only + // be used here because of the possibility to subtract by one without overflow. + let v = (self.get() - 1) / rhs.get() + 1; + // SAFETY: ceiled division of two positive integers can never be zero. + unsafe { Self::new_unchecked(v) } + } + /// Returns the smallest power of two greater than or equal to `self`. /// Checks for overflow and returns [`None`] /// if the next power of two is greater than the type’s maximum value. From 391ff9139c54d4b4a8fd62c9c83ac8663da3dbb5 Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 25 Sep 2026 09:42:33 +0800 Subject: [PATCH 0810/1309] Add regression test for lock guard must-use suggestions --- .../must-use-lock-guard-issue-162843.rs | 15 +++++ .../must-use-lock-guard-issue-162843.stderr | 55 +++++++++++++++++++ 2 files changed, 70 insertions(+) create mode 100644 tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs create mode 100644 tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs new file mode 100644 index 0000000000000..10ab5d75a05fa --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs @@ -0,0 +1,15 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/162843. +//! Ignoring a synchronization guard should suggest a binding that keeps the lock held. +#![deny(unused_must_use)] + +use std::sync::{Mutex, RwLock}; + +fn main() { + let mutex = Mutex::new(0); + mutex.lock().unwrap(); //~ ERROR unused `std::sync::MutexGuard` that must be used + mutex.lock(); //~ ERROR unused `Result` that must be used + + let rwlock = RwLock::new(0); + rwlock.read().unwrap(); //~ ERROR unused `std::sync::RwLockReadGuard` that must be used + rwlock.write().unwrap(); //~ ERROR unused `std::sync::RwLockWriteGuard` that must be used +} diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr new file mode 100644 index 0000000000000..0e06555d20f9d --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr @@ -0,0 +1,55 @@ +error: unused `std::sync::MutexGuard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:9:5 + | +LL | mutex.lock().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^ + | + = note: if unused the Mutex will immediately unlock +note: the lint level is defined here + --> $DIR/must-use-lock-guard-issue-162843.rs:3:9 + | +LL | #![deny(unused_must_use)] + | ^^^^^^^^^^^^^^^ +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = mutex.lock().unwrap(); + | +++++++ + +error: unused `Result` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:10:5 + | +LL | mutex.lock(); + | ^^^^^^^^^^^^ + | + = note: this `Result` may be an `Err` variant, which should be handled +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = mutex.lock(); + | +++++++ + +error: unused `std::sync::RwLockReadGuard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:13:5 + | +LL | rwlock.read().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if unused the RwLock will immediately unlock +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = rwlock.read().unwrap(); + | +++++++ + +error: unused `std::sync::RwLockWriteGuard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:14:5 + | +LL | rwlock.write().unwrap(); + | ^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: if unused the RwLock will immediately unlock +help: use `let _ = ...` to ignore the resulting value + | +LL | let _ = rwlock.write().unwrap(); + | +++++++ + +error: aborting due to 4 previous errors + From e10ba5d3d9f2879f5b47e66659792ad179d5ff1f Mon Sep 17 00:00:00 2001 From: Roland Xu Date: Fri, 25 Sep 2026 10:21:45 +0800 Subject: [PATCH 0811/1309] Add test for issue 163293 --- .../pub-reexport-extern-std-issue-163293.rs | 5 +++ ...ub-reexport-extern-std-issue-163293.stderr | 32 +++++++++++++++++++ 2 files changed, 37 insertions(+) create mode 100644 tests/ui/pub/pub-reexport-extern-std-issue-163293.rs create mode 100644 tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr diff --git a/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs b/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs new file mode 100644 index 0000000000000..ad3a07bbd5f07 --- /dev/null +++ b/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs @@ -0,0 +1,5 @@ +pub use std as x; + +//@ edition: 2015 + +fn main() {} diff --git a/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr b/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr new file mode 100644 index 0000000000000..880a871601e55 --- /dev/null +++ b/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr @@ -0,0 +1,32 @@ +error[E0365]: extern crate `std` is private and cannot be re-exported + --> $DIR/pub-reexport-extern-std-issue-163293.rs:1:9 + | +LL | pub use std as x; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 + = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default +help: consider making the `extern crate` item publicly accessible + | +LL | pub pub use std as x; + | +++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0365`. +Future incompatibility report: Future breakage diagnostic: +error[E0365]: extern crate `std` is private and cannot be re-exported + --> $DIR/pub-reexport-extern-std-issue-163293.rs:1:9 + | +LL | pub use std as x; + | ^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #127909 + = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default +help: consider making the `extern crate` item publicly accessible + | +LL | pub pub use std as x; + | +++ + From fae5137f869e18b6390b59a17c5c5f130608761f Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Thu, 24 Sep 2026 22:27:51 -0400 Subject: [PATCH 0812/1309] Update cargo submodule --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 98a09e7e7d628..3d7cf6e937d61 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 98a09e7e7d62850f14e5b6132101fc1edd19a16f +Subproject commit 3d7cf6e937d6127d0f49881bf689c560b36d35c4 From b10ccb8e2e3e3ddcd2fcc92d97c8ade0814e488e Mon Sep 17 00:00:00 2001 From: Roland Xu Date: Fri, 25 Sep 2026 10:35:19 +0800 Subject: [PATCH 0813/1309] Don't emit sugg for pub-reexport extern std --- compiler/rustc_resolve/src/diagnostics/mod.rs | 2 +- compiler/rustc_resolve/src/imports.rs | 7 +++++-- tests/ui/pub/pub-reexport-extern-std-issue-163293.rs | 2 ++ tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr | 8 -------- 4 files changed, 8 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index d17e01425d2c9..38981426837c4 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -840,7 +840,7 @@ pub(crate) struct PrivateExternCrateReexport { style = "verbose", applicability = "maybe-incorrect" )] - pub sugg: Span, + pub sugg: Option, } #[derive(Subdiagnostic)] diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index 938a6cb29032f..5cd45c5de5230 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1673,8 +1673,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { if let Some(extern_crate_id) = pub_use_of_private_extern_crate_hack(import.summary(), decl) { let ImportKind::Single { id, .. } = import.kind else { unreachable!() }; - let sugg = self.tcx.source_span(extern_crate_id).shrink_to_lo(); - let diagnostic = crate::diagnostics::PrivateExternCrateReexport { ident, sugg }; + let sugg = self.tcx.source_span(extern_crate_id); + let diagnostic = crate::diagnostics::PrivateExternCrateReexport { + ident, + sugg: sugg.can_be_used_for_suggestions().then(|| sugg.shrink_to_lo()), + }; return Some(BufferedEarlyLint { lint_id: LintId::of(PUB_USE_OF_PRIVATE_EXTERN_CRATE), node_id: id, diff --git a/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs b/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs index ad3a07bbd5f07..9189ca2fb41b7 100644 --- a/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs +++ b/tests/ui/pub/pub-reexport-extern-std-issue-163293.rs @@ -1,4 +1,6 @@ pub use std as x; +//~^ ERROR extern crate `std` is private and cannot be re-exported +//~^^ WARN this was previously accepted by the compiler but is being phased out //@ edition: 2015 diff --git a/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr b/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr index 880a871601e55..ee5ba1fc80aa9 100644 --- a/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr +++ b/tests/ui/pub/pub-reexport-extern-std-issue-163293.stderr @@ -7,10 +7,6 @@ LL | pub use std as x; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #127909 = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default -help: consider making the `extern crate` item publicly accessible - | -LL | pub pub use std as x; - | +++ error: aborting due to 1 previous error @@ -25,8 +21,4 @@ LL | pub use std as x; = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #127909 = note: `#[deny(pub_use_of_private_extern_crate)]` (part of `#[deny(future_incompatible)]`) on by default -help: consider making the `extern crate` item publicly accessible - | -LL | pub pub use std as x; - | +++ From 569a8d245bb1bf56e0e3a7ab9bebf808009e9a27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Fri, 25 Sep 2026 02:53:43 +0000 Subject: [PATCH 0814/1309] Use span context to point at item of field that introduced bound requirement ``` note: required because it appears within the type `ListS` --> $DIR/deep-bad-copy-reason.rs:10:5 | LL | pub struct ListS { ... LL | opaque: OpaqueListContents, | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field ``` --- .../src/error_reporting/traits/suggestions.rs | 15 +++-- tests/ui/associated-consts/issue-58022.stderr | 4 +- .../issue-70935-complex-spans.stderr | 4 +- .../issue-72590-type-error-sized.stderr | 5 +- .../async-await/pin-needed-to-poll-2.stderr | 4 +- .../auto-trait-phantom-data-bounds.stderr | 14 ++--- .../builtin-superkinds-in-metadata.stderr | 4 +- tests/ui/coherence/deep-bad-copy-reason.rs | 4 +- .../ui/coherence/deep-bad-copy-reason.stderr | 5 +- tests/ui/deref/pin-impl-deref.stderr | 8 +-- tests/ui/did_you_mean/recursion_limit.stderr | 56 ++++++++++--------- tests/ui/dst/dst-bad-deep-2.stderr | 4 +- tests/ui/dst/dst-bad-deep.stderr | 5 +- tests/ui/error-codes/E0277-2.stderr | 15 ++--- tests/ui/extern/extern-types-unsized.stderr | 15 ++--- .../feature-gate-offset-of-slice.stderr | 5 +- .../feature-gate-trivial_bounds.stderr | 5 +- tests/ui/mut/mutable-enum-indirect.stderr | 4 +- tests/ui/offset-of/offset-of-dst-field.stderr | 5 +- tests/ui/pin-ergonomics/pin-pattern.stderr | 4 +- .../recursion/recursive-requirements.stderr | 15 ++--- tests/ui/sized-hierarchy/impls.stderr | 24 ++++---- tests/ui/statics/unsized_type2.stderr | 10 ++-- .../unsizing-wfcheck-issue-127299.stderr | 5 +- tests/ui/suggestions/suggest-pin-macro.stderr | 5 +- .../ui/threads-sendsync/rc-is-not-send.stderr | 9 ++- ...-level-send-bound-check-issue-40827.stderr | 18 +++--- tests/ui/traits/cycle-cache-err-60010.stderr | 10 ++-- .../ui/traits/enum-negative-send-impl.stderr | 5 +- .../ui/traits/enum-negative-sync-impl.stderr | 5 +- tests/ui/traits/issue-7013.stderr | 5 +- .../negated-auto-traits-error.stderr | 4 +- ...field-location-issue-146016.current.stderr | 25 ++++----- ...nd-field-location-issue-146016.next.stderr | 25 ++++----- .../opaque-trait-size-error-5883.stderr | 5 +- tests/ui/traits/suggest-where-clause.stderr | 4 +- .../trivial-unsized-projection-2.bad.stderr | 8 +-- ...rivial-unsized-projection-2.bad_new.stderr | 4 +- ...ck-default-trait-impl-negation-sync.stderr | 10 ++-- .../typeck/typeck-unsafe-always-share.stderr | 5 +- .../issue-50940-with-feature.stderr | 4 +- tests/ui/unsized-locals/unsized-exprs.stderr | 8 +-- tests/ui/unsized/unsized-enum2.stderr | 16 +++--- tests/ui/unsized/unsized-struct.stderr | 4 +- tests/ui/unsized/unsized3.stderr | 20 +++---- tests/ui/wf/let-pat-inferred-non-wf.stderr | 4 +- 46 files changed, 201 insertions(+), 241 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 7dccf278ac9b1..ff9db46445135 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -4456,7 +4456,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let msg = msg(); match tcx.opt_item_ident(def.did()) { Some(ident) => { - let mut spans = MultiSpan::from(ident.span); + let mut spans = MultiSpan::new(); if def.did().is_local() && let Some(pred) = predicate.as_trait_clause() { @@ -4465,13 +4465,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); for field in def.all_fields() { if field.ty(tcx, args).skip_norm_wip() == field_ty { - spans.push_span_label( - tcx.def_span(field.did), - "required by this field", - ); + let sp = tcx.def_span(field.did); + spans.push_primary_span(sp); + spans.push_span_label(sp, "required by this field"); } } } + if spans.has_primary_spans() { + spans.push_span_context(ident.span); + } else { + spans.push_primary_span(ident.span); + spans.push_span_label(ident.span, ""); + } err.span_note(spans, msg); } None => { diff --git a/tests/ui/associated-consts/issue-58022.stderr b/tests/ui/associated-consts/issue-58022.stderr index 2ef3083d0e925..e006fe8145b23 100644 --- a/tests/ui/associated-consts/issue-58022.stderr +++ b/tests/ui/associated-consts/issue-58022.stderr @@ -6,10 +6,10 @@ LL | fn new(slice: &[u8; Self::SIZE]) -> Self { | = help: within `Bar<[u8]>`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `Bar<[u8]>` - --> $DIR/issue-58022.rs:8:12 + --> $DIR/issue-58022.rs:8:27 | LL | pub struct Bar(T); - | ^^^ - required by this field + | ^ required by this field = note: the return type of a function must have a statically known size error[E0790]: cannot refer to the associated constant on trait without specifying the corresponding `impl` type diff --git a/tests/ui/async-await/issue-70935-complex-spans.stderr b/tests/ui/async-await/issue-70935-complex-spans.stderr index 9f8f1461bd309..52c4acf02745f 100644 --- a/tests/ui/async-await/issue-70935-complex-spans.stderr +++ b/tests/ui/async-await/issue-70935-complex-spans.stderr @@ -8,10 +8,10 @@ LL | fn foo(x: NotSync) -> impl Future + Send { note: required because it appears within the type `PhantomData<*mut ()>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `NotSync` - --> $DIR/issue-70935-complex-spans.rs:9:8 + --> $DIR/issue-70935-complex-spans.rs:9:16 | LL | struct NotSync(PhantomData<*mut ()>); - | ^^^^^^^ -------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^ required by this field = note: required for `&NotSync` to implement `Send` note: required because it's used within this closure --> $DIR/issue-70935-complex-spans.rs:18:13 diff --git a/tests/ui/async-await/issue-72590-type-error-sized.stderr b/tests/ui/async-await/issue-72590-type-error-sized.stderr index 70f615f03186e..91c220c8d29c7 100644 --- a/tests/ui/async-await/issue-72590-type-error-sized.stderr +++ b/tests/ui/async-await/issue-72590-type-error-sized.stderr @@ -18,13 +18,12 @@ LL | async fn frob(self) {} | = help: within `Foo`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `Foo` - --> $DIR/issue-72590-type-error-sized.rs:5:8 + --> $DIR/issue-72590-type-error-sized.rs:7:5 | LL | struct Foo { - | ^^^ LL | foo: Nonexistent, LL | other: str - | ---------- required by this field + | ^^^^^^^^^^ required by this field = help: unsized fn params are gated as an unstable feature help: function arguments must have a statically known size, borrowed types always have a known size | diff --git a/tests/ui/async-await/pin-needed-to-poll-2.stderr b/tests/ui/async-await/pin-needed-to-poll-2.stderr index b7ca47ac4dde2..d373d95ff5b4b 100644 --- a/tests/ui/async-await/pin-needed-to-poll-2.stderr +++ b/tests/ui/async-await/pin-needed-to-poll-2.stderr @@ -9,10 +9,10 @@ LL | Pin::new(&mut self.sleep).poll(cx) = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `Sleep` - --> $DIR/pin-needed-to-poll-2.rs:8:8 + --> $DIR/pin-needed-to-poll-2.rs:8:14 | LL | struct Sleep(std::marker::PhantomPinned); - | ^^^^^ -------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `Pin::::new` --> $SRC_DIR/core/src/pin.rs:LL:COL diff --git a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr index c37695411d736..aeb36182e898f 100644 --- a/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr +++ b/tests/ui/auto-traits/auto-trait-phantom-data-bounds.stderr @@ -14,12 +14,11 @@ LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} note: required because it appears within the type `PhantomData<&T>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Guard<'_, T>` - --> $DIR/auto-trait-phantom-data-bounds.rs:12:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:13:5 | LL | struct Guard<'a, T: 'a> { - | ^^^^^ LL | _marker: PhantomData<&'a T>, - | --------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `is_zen` --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | @@ -46,17 +45,16 @@ LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {} note: required because it appears within the type `PhantomData<&T>` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Guard<'_, T>` - --> $DIR/auto-trait-phantom-data-bounds.rs:12:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:13:5 | LL | struct Guard<'a, T: 'a> { - | ^^^^^ LL | _marker: PhantomData<&'a T>, - | --------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required because it appears within the type `Nested>` - --> $DIR/auto-trait-phantom-data-bounds.rs:16:8 + --> $DIR/auto-trait-phantom-data-bounds.rs:16:18 | LL | struct Nested(T); - | ^^^^^^ - required by this field + | ^ required by this field note: required by a bound in `is_zen` --> $DIR/auto-trait-phantom-data-bounds.rs:18:14 | diff --git a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr index ff26f715d158e..6ba9d93452357 100644 --- a/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr +++ b/tests/ui/builtin-superkinds/builtin-superkinds-in-metadata.stderr @@ -5,10 +5,10 @@ LL | impl RequiresRequiresShareAndSend for X { } | ^^^^ `T` cannot be sent between threads safely | note: required because it appears within the type `X` - --> $DIR/builtin-superkinds-in-metadata.rs:9:8 + --> $DIR/builtin-superkinds-in-metadata.rs:9:13 | LL | struct X(T); - | ^ - required by this field + | ^ required by this field note: required by a bound in `RequiresRequiresShareAndSend` --> $DIR/auxiliary/trait_superkinds_in_metadata.rs:7:58 | diff --git a/tests/ui/coherence/deep-bad-copy-reason.rs b/tests/ui/coherence/deep-bad-copy-reason.rs index d93a46f1fcb1a..ed335205e73e7 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.rs +++ b/tests/ui/coherence/deep-bad-copy-reason.rs @@ -5,11 +5,11 @@ extern "Rust" { } pub struct ListS { - //~^ NOTE: required because it appears within the type len: usize, data: [T; 0], opaque: OpaqueListContents, - //~^ NOTE required by this field + //~^ NOTE: required because it appears within the type + //~| NOTE: required by this field } pub struct Interned<'a, T>(&'a T); diff --git a/tests/ui/coherence/deep-bad-copy-reason.stderr b/tests/ui/coherence/deep-bad-copy-reason.stderr index 198ea1d75e388..b5abd2cbd7b85 100644 --- a/tests/ui/coherence/deep-bad-copy-reason.stderr +++ b/tests/ui/coherence/deep-bad-copy-reason.stderr @@ -21,13 +21,12 @@ LL | pub struct List<'tcx, T>(Interned<'tcx, ListS>); | = help: within `ListS`, the trait `Sized` is not implemented for `OpaqueListContents` note: required because it appears within the type `ListS` - --> $DIR/deep-bad-copy-reason.rs:7:12 + --> $DIR/deep-bad-copy-reason.rs:10:5 | LL | pub struct ListS { - | ^^^^^ ... LL | opaque: OpaqueListContents, - | -------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required by an implicit `Sized` bound in `Interned` --> $DIR/deep-bad-copy-reason.rs:15:25 | diff --git a/tests/ui/deref/pin-impl-deref.stderr b/tests/ui/deref/pin-impl-deref.stderr index 5e0e0aa06715b..985a816309c0b 100644 --- a/tests/ui/deref/pin-impl-deref.stderr +++ b/tests/ui/deref/pin-impl-deref.stderr @@ -41,10 +41,10 @@ LL | impl_deref_mut(r_pin) = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `MyPinType` - --> $DIR/pin-impl-deref.rs:15:8 + --> $DIR/pin-impl-deref.rs:15:18 | LL | struct MyPinType(core::marker::PhantomPinned); - | ^^^^^^^^^ --------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field = note: required for `Pin<&MyPinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 @@ -63,10 +63,10 @@ LL | impl_deref_mut(r_pin) = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `MyPinType` - --> $DIR/pin-impl-deref.rs:15:8 + --> $DIR/pin-impl-deref.rs:15:18 | LL | struct MyPinType(core::marker::PhantomPinned); - | ^^^^^^^^^ --------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field = note: required for `Pin<&mut MyPinType>` to implement `DerefMut` note: required by a bound in `impl_deref_mut` --> $DIR/pin-impl-deref.rs:22:27 diff --git a/tests/ui/did_you_mean/recursion_limit.stderr b/tests/ui/did_you_mean/recursion_limit.stderr index 7960efec9957e..5ff75c32c1684 100644 --- a/tests/ui/did_you_mean/recursion_limit.stderr +++ b/tests/ui/did_you_mean/recursion_limit.stderr @@ -1,82 +1,84 @@ error[E0275]: overflow evaluating the requirement `J: Send` --> $DIR/recursion_limit.rs:34:5 | +LL | macro_rules! link { +... LL | is_send::(); | ^^^^^^^^^^^^^^ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "20"]` attribute to your crate (`recursion_limit`) note: required because it appears within the type `I` - --> $DIR/recursion_limit.rs:23:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { I, J } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `H` - --> $DIR/recursion_limit.rs:22:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { H, I } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `G` - --> $DIR/recursion_limit.rs:21:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { G, H } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `F` - --> $DIR/recursion_limit.rs:20:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { F, G } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `E` - --> $DIR/recursion_limit.rs:19:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { E, F } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `D` - --> $DIR/recursion_limit.rs:18:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { D, E } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `C` - --> $DIR/recursion_limit.rs:17:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { C, D } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `B` - --> $DIR/recursion_limit.rs:16:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { B, C } - | ^ + | -------------- in this macro invocation note: required because it appears within the type `A` - --> $DIR/recursion_limit.rs:15:9 + --> $DIR/recursion_limit.rs:11:24 | LL | enum $id { $id($t) } - | -- required by this field + | ^^ required by this field ... LL | link! { A, B } - | ^ + | -------------- in this macro invocation note: required by a bound in `is_send` --> $DIR/recursion_limit.rs:31:14 | diff --git a/tests/ui/dst/dst-bad-deep-2.stderr b/tests/ui/dst/dst-bad-deep-2.stderr index 790e6dff9b5ef..fd6e7be576c7d 100644 --- a/tests/ui/dst/dst-bad-deep-2.stderr +++ b/tests/ui/dst/dst-bad-deep-2.stderr @@ -6,10 +6,10 @@ LL | let h: &Fat> = &Fat(*g); | = help: within `Fat<[isize]>`, the trait `Sized` is not implemented for `[isize]` note: required because it appears within the type `Fat<[isize]>` - --> $DIR/dst-bad-deep-2.rs:6:8 + --> $DIR/dst-bad-deep-2.rs:6:23 | LL | struct Fat(T); - | ^^^ - required by this field + | ^ required by this field = note: all function arguments must have a statically known size = help: unsized fn params are gated as an unstable feature diff --git a/tests/ui/dst/dst-bad-deep.stderr b/tests/ui/dst/dst-bad-deep.stderr index bf9baa8e7e3c9..874a762220913 100644 --- a/tests/ui/dst/dst-bad-deep.stderr +++ b/tests/ui/dst/dst-bad-deep.stderr @@ -6,12 +6,11 @@ LL | let h: &Fat> = &Fat { ptr: *g }; | = help: within `Fat>`, the trait `Sized` is not implemented for `[isize]` note: required because it appears within the type `Fat<[isize]>` - --> $DIR/dst-bad-deep.rs:6:8 + --> $DIR/dst-bad-deep.rs:7:5 | LL | struct Fat { - | ^^^ LL | ptr: T - | ------ required by this field + | ^^^^^^ required by this field = note: structs must have a statically known size to be initialized error: aborting due to 1 previous error diff --git a/tests/ui/error-codes/E0277-2.stderr b/tests/ui/error-codes/E0277-2.stderr index 9cf2d5c4fcc65..30b62ab6f46a3 100644 --- a/tests/ui/error-codes/E0277-2.stderr +++ b/tests/ui/error-codes/E0277-2.stderr @@ -6,26 +6,23 @@ LL | is_send::(); | = help: within `Foo`, the trait `Send` is not implemented for `*const u8` note: required because it appears within the type `Baz` - --> $DIR/E0277-2.rs:9:8 + --> $DIR/E0277-2.rs:10:5 | LL | struct Baz { - | ^^^ LL | x: *const u8 - | ------------ required by this field + | ^^^^^^^^^^^^ required by this field note: required because it appears within the type `Bar` - --> $DIR/E0277-2.rs:5:8 + --> $DIR/E0277-2.rs:6:5 | LL | struct Bar { - | ^^^ LL | baz: Baz - | -------- required by this field + | ^^^^^^^^ required by this field note: required because it appears within the type `Foo` - --> $DIR/E0277-2.rs:1:8 + --> $DIR/E0277-2.rs:2:5 | LL | struct Foo { - | ^^^ LL | bar: Bar - | -------- required by this field + | ^^^^^^^^ required by this field note: required by a bound in `is_send` --> $DIR/E0277-2.rs:13:15 | diff --git a/tests/ui/extern/extern-types-unsized.stderr b/tests/ui/extern/extern-types-unsized.stderr index c4c919cd646b4..d25cc9d6e71bf 100644 --- a/tests/ui/extern/extern-types-unsized.stderr +++ b/tests/ui/extern/extern-types-unsized.stderr @@ -23,13 +23,12 @@ LL | assert_sized::(); | = help: within `Foo`, the trait `Sized` is not implemented for `A` note: required because it appears within the type `Foo` - --> $DIR/extern-types-unsized.rs:9:8 + --> $DIR/extern-types-unsized.rs:11:5 | LL | struct Foo { - | ^^^ LL | x: u8, LL | tail: A, - | ------- required by this field + | ^^^^^^^ required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | @@ -48,13 +47,12 @@ LL | assert_sized::>(); | = help: within `Bar`, the trait `Sized` is not implemented for `A` note: required because it appears within the type `Bar` - --> $DIR/extern-types-unsized.rs:14:8 + --> $DIR/extern-types-unsized.rs:16:5 | LL | struct Bar { - | ^^^ LL | x: u8, LL | tail: T, - | ------- required by this field + | ^^^^^^^ required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | @@ -86,13 +84,12 @@ LL | assert_sized::>>(); | = help: within `Bar>`, the trait `Sized` is not implemented for `A` note: required because it appears within the type `Bar` - --> $DIR/extern-types-unsized.rs:14:8 + --> $DIR/extern-types-unsized.rs:16:5 | LL | struct Bar { - | ^^^ LL | x: u8, LL | tail: T, - | ------- required by this field + | ^^^^^^^ required by this field note: required by an implicit `Sized` bound in `assert_sized` --> $DIR/extern-types-unsized.rs:19:17 | diff --git a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr index 4ac4472b78e0e..71f6ea2afacc2 100644 --- a/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr +++ b/tests/ui/feature-gates/feature-gate-offset-of-slice.stderr @@ -14,13 +14,12 @@ LL | offset_of!(T, y); | = help: within `S`, the trait `Sized` is not implemented for `[i32]` note: required because it appears within the type `S` - --> $DIR/feature-gate-offset-of-slice.rs:3:8 + --> $DIR/feature-gate-offset-of-slice.rs:6:5 | LL | struct S { - | ^ ... LL | c: [i32], - | -------- required by this field + | ^^^^^^^^ required by this field error[E0277]: the size for values of type `[i32]` cannot be known at compilation time --> $DIR/feature-gate-offset-of-slice.rs:25:5 diff --git a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr index 76695064dec16..01f61ad7b9934 100644 --- a/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr +++ b/tests/ui/feature-gates/feature-gate-trivial_bounds.stderr @@ -137,12 +137,11 @@ LL | fn unsized_local() where Dst: Sized { | = help: within `Dst<(dyn A + 'static)>`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Dst<(dyn A + 'static)>` - --> $DIR/feature-gate-trivial_bounds.rs:48:8 + --> $DIR/feature-gate-trivial_bounds.rs:49:5 | LL | struct Dst { - | ^^^ LL | x: X, - | ---- required by this field + | ^^^^ required by this field help: add `#![feature(trivial_bounds)]` to the crate attributes to enable | LL + #![feature(trivial_bounds)] diff --git a/tests/ui/mut/mutable-enum-indirect.stderr b/tests/ui/mut/mutable-enum-indirect.stderr index 40ece8bce9ab5..7d7145b669997 100644 --- a/tests/ui/mut/mutable-enum-indirect.stderr +++ b/tests/ui/mut/mutable-enum-indirect.stderr @@ -12,10 +12,10 @@ help: within `&Foo`, the trait `Sync` is not implemented for `NoSync` LL | struct NoSync; | ^^^^^^^^^^^^^ note: required because it appears within the type `Foo` - --> $DIR/mutable-enum-indirect.rs:11:6 + --> $DIR/mutable-enum-indirect.rs:11:14 | LL | enum Foo { A(NoSync) } - | ^^^ ------ required by this field + | ^^^^^^ required by this field = note: required because it appears within the type `&Foo` note: required by a bound in `bar` --> $DIR/mutable-enum-indirect.rs:13:11 diff --git a/tests/ui/offset-of/offset-of-dst-field.stderr b/tests/ui/offset-of/offset-of-dst-field.stderr index 1bceb3c409177..cfc72f62a04b0 100644 --- a/tests/ui/offset-of/offset-of-dst-field.stderr +++ b/tests/ui/offset-of/offset-of-dst-field.stderr @@ -54,13 +54,12 @@ LL | offset_of!(Delta, z); | = help: within `Alpha`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `Alpha` - --> $DIR/offset-of-dst-field.rs:6:8 + --> $DIR/offset-of-dst-field.rs:9:5 | LL | struct Alpha { - | ^^^^^ ... LL | z: [u8], - | ------- required by this field + | ^^^^^^^ required by this field error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/offset-of-dst-field.rs:51:5 diff --git a/tests/ui/pin-ergonomics/pin-pattern.stderr b/tests/ui/pin-ergonomics/pin-pattern.stderr index 5262de183e749..578620f48ce11 100644 --- a/tests/ui/pin-ergonomics/pin-pattern.stderr +++ b/tests/ui/pin-ergonomics/pin-pattern.stderr @@ -33,10 +33,10 @@ LL | (&pin mut x,): &'a mut (&'a pin mut Foo,), = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `Foo` - --> $DIR/pin-pattern.rs:11:8 + --> $DIR/pin-pattern.rs:11:15 | LL | struct Foo(T); - | ^^^ - required by this field + | ^ required by this field help: consider restricting type parameter `T` with trait `Unpin` | LL | fn tuple_ref_pin_mut_pat_and_mut_of_tuple_pin_mut_ty<'a, T: std::marker::Unpin>( diff --git a/tests/ui/recursion/recursive-requirements.stderr b/tests/ui/recursion/recursive-requirements.stderr index d4197eded7d28..527baa431a95b 100644 --- a/tests/ui/recursion/recursive-requirements.stderr +++ b/tests/ui/recursion/recursive-requirements.stderr @@ -6,12 +6,11 @@ LL | let _: AssertSync = unimplemented!(); | = help: within `Foo`, the trait `Sync` is not implemented for `*const Bar` note: required because it appears within the type `Foo` - --> $DIR/recursive-requirements.rs:5:12 + --> $DIR/recursive-requirements.rs:6:5 | LL | pub struct Foo { - | ^^^ LL | bar: *const Bar, - | --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field note: required by a bound in `AssertSync` --> $DIR/recursive-requirements.rs:3:22 | @@ -26,22 +25,20 @@ LL | let _: AssertSync = unimplemented!(); | = help: within `Foo`, the trait `Sync` is not implemented for `*const Foo` note: required because it appears within the type `Bar` - --> $DIR/recursive-requirements.rs:10:12 + --> $DIR/recursive-requirements.rs:11:5 | LL | pub struct Bar { - | ^^^ LL | foo: *const Foo, - | --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field note: required because it appears within the type `PhantomData` --> $SRC_DIR/core/src/marker.rs:LL:COL note: required because it appears within the type `Foo` - --> $DIR/recursive-requirements.rs:5:12 + --> $DIR/recursive-requirements.rs:7:5 | LL | pub struct Foo { - | ^^^ LL | bar: *const Bar, LL | phantom: PhantomData, - | ------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `AssertSync` --> $DIR/recursive-requirements.rs:3:22 | diff --git a/tests/ui/sized-hierarchy/impls.stderr b/tests/ui/sized-hierarchy/impls.stderr index 1e0f234ce19a4..dc30a3ea998f8 100644 --- a/tests/ui/sized-hierarchy/impls.stderr +++ b/tests/ui/sized-hierarchy/impls.stderr @@ -289,10 +289,10 @@ LL | needs_sized::(); | = help: within `StructAllFieldsMetaSized`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `StructAllFieldsMetaSized` - --> $DIR/impls.rs:235:12 + --> $DIR/impls.rs:235:39 | LL | struct StructAllFieldsMetaSized { x: [u8], y: [u8] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ ------- ------- required by this field + | ^^^^^^^ ^^^^^^^ required by this field | | | required by this field note: required by a bound in `needs_sized` @@ -309,10 +309,10 @@ LL | needs_sized::(); | = help: within `StructAllFieldsUnsized`, the trait `Sized` is not implemented for `main::Foo` note: required because it appears within the type `StructAllFieldsUnsized` - --> $DIR/impls.rs:243:12 + --> $DIR/impls.rs:243:37 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ ------ ------ required by this field + | ^^^^^^ ^^^^^^ required by this field | | | required by this field note: required by a bound in `needs_sized` @@ -329,10 +329,10 @@ LL | needs_metasized::(); | = help: within `StructAllFieldsUnsized`, the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` note: required because it appears within the type `StructAllFieldsUnsized` - --> $DIR/impls.rs:243:12 + --> $DIR/impls.rs:243:37 | LL | struct StructAllFieldsUnsized { x: Foo, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ ------ ------ required by this field + | ^^^^^^ ^^^^^^ required by this field | | | required by this field note: required by a bound in `needs_metasized` @@ -349,10 +349,10 @@ LL | needs_sized::(); | = help: within `StructLastFieldMetaSized`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `StructLastFieldMetaSized` - --> $DIR/impls.rs:252:12 + --> $DIR/impls.rs:252:47 | LL | struct StructLastFieldMetaSized { x: u32, y: [u8] } - | ^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by this field + | ^^^^^^^ required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -367,10 +367,10 @@ LL | needs_sized::(); | = help: within `StructLastFieldUnsized`, the trait `Sized` is not implemented for `main::Foo` note: required because it appears within the type `StructLastFieldUnsized` - --> $DIR/impls.rs:259:12 + --> $DIR/impls.rs:259:45 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ ------ required by this field + | ^^^^^^ required by this field note: required by a bound in `needs_sized` --> $DIR/impls.rs:13:19 | @@ -385,10 +385,10 @@ LL | needs_metasized::(); | = help: within `StructLastFieldUnsized`, the nightly-only, unstable trait `MetaSized` is not implemented for `main::Foo` note: required because it appears within the type `StructLastFieldUnsized` - --> $DIR/impls.rs:259:12 + --> $DIR/impls.rs:259:45 | LL | struct StructLastFieldUnsized { x: u32, y: Foo } - | ^^^^^^^^^^^^^^^^^^^^^^ ------ required by this field + | ^^^^^^ required by this field note: required by a bound in `needs_metasized` --> $DIR/impls.rs:16:23 | diff --git a/tests/ui/statics/unsized_type2.stderr b/tests/ui/statics/unsized_type2.stderr index 5bccabf0bc133..ff00f028ab038 100644 --- a/tests/ui/statics/unsized_type2.stderr +++ b/tests/ui/statics/unsized_type2.stderr @@ -6,12 +6,11 @@ LL | pub static WITH_ERROR: Foo = Foo { version: 0 }; | = help: within `Foo`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `Foo` - --> $DIR/unsized_type2.rs:5:12 + --> $DIR/unsized_type2.rs:6:5 | LL | pub struct Foo { - | ^^^ LL | pub version: str, - | ---------------- required by this field + | ^^^^^^^^^^^^^^^^ required by this field = note: statics and constants must have a statically known size error[E0308]: mismatched types @@ -28,12 +27,11 @@ LL | pub static WITH_ERROR: Foo = Foo { version: 0 }; | = help: within `Foo`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `Foo` - --> $DIR/unsized_type2.rs:5:12 + --> $DIR/unsized_type2.rs:6:5 | LL | pub struct Foo { - | ^^^ LL | pub version: str, - | ---------------- required by this field + | ^^^^^^^^^^^^^^^^ required by this field = note: structs must have a statically known size to be initialized error: aborting due to 3 previous errors diff --git a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr index 1467de675be56..09dcff7827545 100644 --- a/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr +++ b/tests/ui/statics/unsizing-wfcheck-issue-127299.stderr @@ -30,12 +30,11 @@ LL | static FOO: &Lint = &Lint { desc: "desc" }; = help: within `&'static Lint`, the trait `Sync` is not implemented for `(dyn Qux + 'static)` = note: required because it appears within the type `&'static (dyn Qux + 'static)` note: required because it appears within the type `Lint` - --> $DIR/unsizing-wfcheck-issue-127299.rs:7:12 + --> $DIR/unsizing-wfcheck-issue-127299.rs:8:5 | LL | pub struct Lint { - | ^^^^ LL | pub desc: &'static dyn Qux, - | -------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field = note: required because it appears within the type `&'static Lint` = note: shared static variables must have a type that implements `Sync` diff --git a/tests/ui/suggestions/suggest-pin-macro.stderr b/tests/ui/suggestions/suggest-pin-macro.stderr index c1877fae753c8..e9c9d3a5f8450 100644 --- a/tests/ui/suggestions/suggest-pin-macro.stderr +++ b/tests/ui/suggestions/suggest-pin-macro.stderr @@ -7,12 +7,11 @@ LL | dummy(test1.get_mut()); = note: consider using the `pin!` macro consider using `Box::pin` if you need to access the pinned value outside of the current scope note: required because it appears within the type `Test` - --> $DIR/suggest-pin-macro.rs:5:8 + --> $DIR/suggest-pin-macro.rs:6:5 | LL | struct Test { - | ^^^^ LL | _marker: PhantomPinned, - | ---------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `Pin::<&'a mut T>::get_mut` --> $SRC_DIR/core/src/pin.rs:LL:COL diff --git a/tests/ui/threads-sendsync/rc-is-not-send.stderr b/tests/ui/threads-sendsync/rc-is-not-send.stderr index 03e4b582cd0eb..db9e263b9e383 100644 --- a/tests/ui/threads-sendsync/rc-is-not-send.stderr +++ b/tests/ui/threads-sendsync/rc-is-not-send.stderr @@ -15,17 +15,16 @@ LL | | }); | = help: within `{closure@$DIR/rc-is-not-send.rs:25:19: 25:26}`, the trait `Send` is not implemented for `Rc<()>` note: required because it appears within the type `Port<()>` - --> $DIR/rc-is-not-send.rs:7:8 + --> $DIR/rc-is-not-send.rs:7:16 | LL | struct Port(Rc); - | ^^^^ ----- required by this field + | ^^^^^ required by this field note: required because it appears within the type `Foo` - --> $DIR/rc-is-not-send.rs:10:8 + --> $DIR/rc-is-not-send.rs:11:5 | LL | struct Foo { - | ^^^ LL | _x: Port<()>, - | ------------ required by this field + | ^^^^^^^^^^^^ required by this field note: required because `x` is used within this closure --> $DIR/rc-is-not-send.rs:27:17 | diff --git a/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr b/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr index bd4cabc78c990..c8e89b5d0bc66 100644 --- a/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr +++ b/tests/ui/trait-bounds/deep-level-send-bound-check-issue-40827.stderr @@ -8,18 +8,17 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | = help: within `Bar`, the trait `Sync` is not implemented for `Rc` note: required because it appears within the type `Bar` - --> $DIR/deep-level-send-bound-check-issue-40827.rs:6:6 + --> $DIR/deep-level-send-bound-check-issue-40827.rs:7:7 | LL | enum Bar { - | ^^^ LL | A(Rc), - | ------- required by this field + | ^^^^^^^ required by this field = note: required for `Arc` to implement `Send` note: required because it appears within the type `Foo` - --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:8 + --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:12 | LL | struct Foo(Arc); - | ^^^ -------- required by this field + | ^^^^^^^^ required by this field note: required by a bound in `f` --> $DIR/deep-level-send-bound-check-issue-40827.rs:11:9 | @@ -36,18 +35,17 @@ LL | f(Foo(Arc::new(Bar::B(None)))); | = help: within `Bar`, the trait `Send` is not implemented for `Rc` note: required because it appears within the type `Bar` - --> $DIR/deep-level-send-bound-check-issue-40827.rs:6:6 + --> $DIR/deep-level-send-bound-check-issue-40827.rs:7:7 | LL | enum Bar { - | ^^^ LL | A(Rc), - | ------- required by this field + | ^^^^^^^ required by this field = note: required for `Arc` to implement `Send` note: required because it appears within the type `Foo` - --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:8 + --> $DIR/deep-level-send-bound-check-issue-40827.rs:4:12 | LL | struct Foo(Arc); - | ^^^ -------- required by this field + | ^^^^^^^^ required by this field note: required by a bound in `f` --> $DIR/deep-level-send-bound-check-issue-40827.rs:11:9 | diff --git a/tests/ui/traits/cycle-cache-err-60010.stderr b/tests/ui/traits/cycle-cache-err-60010.stderr index 3aa7ac98d6100..4c23e37651e7e 100644 --- a/tests/ui/traits/cycle-cache-err-60010.stderr +++ b/tests/ui/traits/cycle-cache-err-60010.stderr @@ -16,12 +16,11 @@ note: required because it appears within the type `Runtime` LL | struct Runtime { | ^^^^^^^ note: required because it appears within the type `RootDatabase` - --> $DIR/cycle-cache-err-60010.rs:20:8 + --> $DIR/cycle-cache-err-60010.rs:21:5 | LL | struct RootDatabase { - | ^^^^^^^^^^^^ LL | _runtime: Runtime, - | ------------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required for `RootDatabase` to implement `SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:43:9 | @@ -57,12 +56,11 @@ note: required because it appears within the type `Runtime` LL | struct Runtime { | ^^^^^^^ note: required because it appears within the type `RootDatabase` - --> $DIR/cycle-cache-err-60010.rs:20:8 + --> $DIR/cycle-cache-err-60010.rs:21:5 | LL | struct RootDatabase { - | ^^^^^^^^^^^^ LL | _runtime: Runtime, - | ------------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field note: required for `RootDatabase` to implement `SourceDatabase` --> $DIR/cycle-cache-err-60010.rs:43:9 | diff --git a/tests/ui/traits/enum-negative-send-impl.stderr b/tests/ui/traits/enum-negative-send-impl.stderr index 645d6d856eb1c..63f5f7c26f7d2 100644 --- a/tests/ui/traits/enum-negative-send-impl.stderr +++ b/tests/ui/traits/enum-negative-send-impl.stderr @@ -12,12 +12,11 @@ help: within `Container`, the trait `Send` is not implemented for `NoSend` LL | struct NoSend; | ^^^^^^^^^^^^^ note: required because it appears within the type `Container` - --> $DIR/enum-negative-send-impl.rs:12:6 + --> $DIR/enum-negative-send-impl.rs:13:16 | LL | enum Container { - | ^^^^^^^^^ LL | WithNoSend(NoSend), - | ------ required by this field + | ^^^^^^ required by this field note: required by a bound in `requires_send` --> $DIR/enum-negative-send-impl.rs:16:21 | diff --git a/tests/ui/traits/enum-negative-sync-impl.stderr b/tests/ui/traits/enum-negative-sync-impl.stderr index 8fdfbe6876266..3658711a22bd2 100644 --- a/tests/ui/traits/enum-negative-sync-impl.stderr +++ b/tests/ui/traits/enum-negative-sync-impl.stderr @@ -12,12 +12,11 @@ help: within `Container`, the trait `Sync` is not implemented for `NoSync` LL | struct NoSync; | ^^^^^^^^^^^^^ note: required because it appears within the type `Container` - --> $DIR/enum-negative-sync-impl.rs:12:6 + --> $DIR/enum-negative-sync-impl.rs:13:16 | LL | enum Container { - | ^^^^^^^^^ LL | WithNoSync(NoSync), - | ------ required by this field + | ^^^^^^ required by this field note: required by a bound in `requires_sync` --> $DIR/enum-negative-sync-impl.rs:16:21 | diff --git a/tests/ui/traits/issue-7013.stderr b/tests/ui/traits/issue-7013.stderr index 8621072272259..93ee5c7c372aa 100644 --- a/tests/ui/traits/issue-7013.stderr +++ b/tests/ui/traits/issue-7013.stderr @@ -8,12 +8,11 @@ LL | let a = A {v: Box::new(B{v: None}) as Box}; note: required because it appears within the type `Option>>` --> $SRC_DIR/core/src/option.rs:LL:COL note: required because it appears within the type `B` - --> $DIR/issue-7013.rs:8:8 + --> $DIR/issue-7013.rs:9:5 | LL | struct B { - | ^ LL | v: Option>> - | ------------------------- required by this field + | ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this field = note: required for the cast from `Box` to `Box` error: aborting due to 1 previous error diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr index 356e0b9c18cd6..64e9dae2633b8 100644 --- a/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr +++ b/tests/ui/traits/negative-impls/negated-auto-traits-error.stderr @@ -109,10 +109,10 @@ help: within `Outer2`, the trait `Send` is not implemented for LL | struct TestType; | ^^^^^^^^^^^^^^^ note: required because it appears within the type `Outer2` - --> $DIR/negated-auto-traits-error.rs:12:8 + --> $DIR/negated-auto-traits-error.rs:12:18 | LL | struct Outer2(T); - | ^^^^^^ - required by this field + | ^ required by this field = note: required for `std::ptr::Unique>` to implement `Send` note: required because it appears within the type `Box>` --> $SRC_DIR/alloc/src/boxed.rs:LL:COL diff --git a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr index 1aad4cb4c7685..5366c04cb537b 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr @@ -6,13 +6,12 @@ LL | require_send::>(); | = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:24:8 + --> $DIR/non-send-field-location-issue-146016.rs:26:5 | LL | struct Record { - | ^^^^^^ LL | unrelated: u8, LL | value: T, - | -------- required by this field + | ^^^^^^^^ required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -27,20 +26,18 @@ LL | require_send::>(); | = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:24:8 + --> $DIR/non-send-field-location-issue-146016.rs:26:5 | LL | struct Record { - | ^^^^^^ LL | unrelated: u8, LL | value: T, - | -------- required by this field + | ^^^^^^^^ required by this field note: required because it appears within the type `Nested<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:29:8 + --> $DIR/non-send-field-location-issue-146016.rs:30:5 | LL | struct Nested { - | ^^^^^^ LL | value: Record, - | ---------------- required by this field + | ^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -55,13 +52,12 @@ LL | require_send::>(); | = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Multiple<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:33:6 + --> $DIR/non-send-field-location-issue-146016.rs:35:14 | LL | enum Multiple { - | ^^^^^^^^ LL | Empty, LL | Values { first: T, second: T }, - | -------- --------- required by this field + | ^^^^^^^^ ^^^^^^^^^ required by this field | | | required by this field note: required by a bound in `require_send` @@ -85,13 +81,12 @@ LL | | }); | = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Foo` - --> $DIR/non-send-field-location-issue-146016.rs:19:6 + --> $DIR/non-send-field-location-issue-146016.rs:21:11 | LL | enum Foo { - | ^^^ LL | Case(i32), LL | Case2(Bar), - | --- required by this field + | ^^^ required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure --> $DIR/non-send-field-location-issue-146016.rs:55:41 diff --git a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr index 1aad4cb4c7685..5366c04cb537b 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr @@ -6,13 +6,12 @@ LL | require_send::>(); | = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:24:8 + --> $DIR/non-send-field-location-issue-146016.rs:26:5 | LL | struct Record { - | ^^^^^^ LL | unrelated: u8, LL | value: T, - | -------- required by this field + | ^^^^^^^^ required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -27,20 +26,18 @@ LL | require_send::>(); | = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:24:8 + --> $DIR/non-send-field-location-issue-146016.rs:26:5 | LL | struct Record { - | ^^^^^^ LL | unrelated: u8, LL | value: T, - | -------- required by this field + | ^^^^^^^^ required by this field note: required because it appears within the type `Nested<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:29:8 + --> $DIR/non-send-field-location-issue-146016.rs:30:5 | LL | struct Nested { - | ^^^^^^ LL | value: Record, - | ---------------- required by this field + | ^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `require_send` --> $DIR/non-send-field-location-issue-146016.rs:38:20 | @@ -55,13 +52,12 @@ LL | require_send::>(); | = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Multiple<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:33:6 + --> $DIR/non-send-field-location-issue-146016.rs:35:14 | LL | enum Multiple { - | ^^^^^^^^ LL | Empty, LL | Values { first: T, second: T }, - | -------- --------- required by this field + | ^^^^^^^^ ^^^^^^^^^ required by this field | | | required by this field note: required by a bound in `require_send` @@ -85,13 +81,12 @@ LL | | }); | = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Foo` - --> $DIR/non-send-field-location-issue-146016.rs:19:6 + --> $DIR/non-send-field-location-issue-146016.rs:21:11 | LL | enum Foo { - | ^^^ LL | Case(i32), LL | Case2(Bar), - | --- required by this field + | ^^^ required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure --> $DIR/non-send-field-location-issue-146016.rs:55:41 diff --git a/tests/ui/traits/opaque-trait-size-error-5883.stderr b/tests/ui/traits/opaque-trait-size-error-5883.stderr index 1cb25b281ce84..dac937cda187d 100644 --- a/tests/ui/traits/opaque-trait-size-error-5883.stderr +++ b/tests/ui/traits/opaque-trait-size-error-5883.stderr @@ -6,12 +6,11 @@ LL | ) -> Struct { | = help: within `Struct`, the trait `Sized` is not implemented for `(dyn A + 'static)` note: required because it appears within the type `Struct` - --> $DIR/opaque-trait-size-error-5883.rs:4:8 + --> $DIR/opaque-trait-size-error-5883.rs:5:5 | LL | struct Struct { - | ^^^^^^ LL | r: dyn A + 'static - | ------------------ required by this field + | ^^^^^^^^^^^^^^^^^^ required by this field = note: the return type of a function must have a statically known size error[E0277]: the size for values of type `(dyn A + 'static)` cannot be known at compilation time diff --git a/tests/ui/traits/suggest-where-clause.stderr b/tests/ui/traits/suggest-where-clause.stderr index e56c7cd518bd2..307db55034ee6 100644 --- a/tests/ui/traits/suggest-where-clause.stderr +++ b/tests/ui/traits/suggest-where-clause.stderr @@ -25,10 +25,10 @@ LL | mem::size_of::>(); | ^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `Misc` - --> $DIR/suggest-where-clause.rs:3:8 + --> $DIR/suggest-where-clause.rs:3:23 | LL | struct Misc(T); - | ^^^^ - required by this field + | ^ required by this field note: required by an implicit `Sized` bound in `std::mem::size_of` --> $SRC_DIR/core/src/mem/mod.rs:LL:COL help: consider removing the `?Sized` bound to make the type parameter `Sized` diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr index 183ae5fb79139..16f1ceaf7e67f 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad.stderr @@ -6,10 +6,10 @@ LL | const FOO: ::Assert = todo!(); | = help: within `Tail`, the trait `Sized` is not implemented for `[()]` note: required because it appears within the type `Tail` - --> $DIR/trivial-unsized-projection-2.rs:17:8 + --> $DIR/trivial-unsized-projection-2.rs:17:13 | LL | struct Tail([()]); - | ^^^^ ---- required by this field + | ^^^^ required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | @@ -31,10 +31,10 @@ LL | const FOO: ::Assert = todo!(); | = help: within `Tail`, the trait `Sized` is not implemented for `[()]` note: required because it appears within the type `Tail` - --> $DIR/trivial-unsized-projection-2.rs:17:8 + --> $DIR/trivial-unsized-projection-2.rs:17:13 | LL | struct Tail([()]); - | ^^^^ ---- required by this field + | ^^^^ required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | diff --git a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr index b97ce9567813b..a58cebabf75d8 100644 --- a/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr +++ b/tests/ui/traits/trivial-unsized-projection-2.bad_new.stderr @@ -12,10 +12,10 @@ LL | const FOO: ::Assert = todo!(); | = help: within `Tail`, the trait `Sized` is not implemented for `[()]` note: required because it appears within the type `Tail` - --> $DIR/trivial-unsized-projection-2.rs:17:8 + --> $DIR/trivial-unsized-projection-2.rs:17:13 | LL | struct Tail([()]); - | ^^^^ ---- required by this field + | ^^^^ required by this field note: required by a bound in `Bad::Assert` --> $DIR/trivial-unsized-projection-2.rs:14:15 | diff --git a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr index 00ad61a6d7794..7d437f3a564f3 100644 --- a/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr +++ b/tests/ui/typeck/typeck-default-trait-impl-negation-sync.stderr @@ -23,12 +23,11 @@ LL | is_sync::(); | = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell` note: required because it appears within the type `MyTypeWUnsafe` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:21:8 + --> $DIR/typeck-default-trait-impl-negation-sync.rs:22:4 | LL | struct MyTypeWUnsafe { - | ^^^^^^^^^^^^^ LL | t: UnsafeCell - | ----------------- required by this field + | ^^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `is_sync` --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 | @@ -47,12 +46,11 @@ help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed` LL | struct Managed; | ^^^^^^^^^^^^^^ note: required because it appears within the type `MyTypeManaged` - --> $DIR/typeck-default-trait-impl-negation-sync.rs:25:8 + --> $DIR/typeck-default-trait-impl-negation-sync.rs:26:4 | LL | struct MyTypeManaged { - | ^^^^^^^^^^^^^ LL | t: Managed - | ---------- required by this field + | ^^^^^^^^^^ required by this field note: required by a bound in `is_sync` --> $DIR/typeck-default-trait-impl-negation-sync.rs:29:15 | diff --git a/tests/ui/typeck/typeck-unsafe-always-share.stderr b/tests/ui/typeck/typeck-unsafe-always-share.stderr index 6239db91b52e8..c626bc5d5c1c0 100644 --- a/tests/ui/typeck/typeck-unsafe-always-share.stderr +++ b/tests/ui/typeck/typeck-unsafe-always-share.stderr @@ -38,12 +38,11 @@ LL | test(ms); | = help: within `MySync`, the trait `Sync` is not implemented for `UnsafeCell` note: required because it appears within the type `MySync` - --> $DIR/typeck-unsafe-always-share.rs:8:8 + --> $DIR/typeck-unsafe-always-share.rs:9:5 | LL | struct MySync { - | ^^^^^^ LL | u: UnsafeCell - | ---------------- required by this field + | ^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `test` --> $DIR/typeck-unsafe-always-share.rs:15:12 | diff --git a/tests/ui/unsized-locals/issue-50940-with-feature.stderr b/tests/ui/unsized-locals/issue-50940-with-feature.stderr index a0d7e9c6cba31..f51e2663f7424 100644 --- a/tests/ui/unsized-locals/issue-50940-with-feature.stderr +++ b/tests/ui/unsized-locals/issue-50940-with-feature.stderr @@ -6,10 +6,10 @@ LL | A as fn(str) -> A; | = help: within `A`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `A` - --> $DIR/issue-50940-with-feature.rs:4:12 + --> $DIR/issue-50940-with-feature.rs:4:25 | LL | struct A(X); - | ^ - required by this field + | ^ required by this field = note: the return type of a function must have a statically known size error: aborting due to 1 previous error diff --git a/tests/ui/unsized-locals/unsized-exprs.stderr b/tests/ui/unsized-locals/unsized-exprs.stderr index 8d6156446d26f..ffc53fae4062f 100644 --- a/tests/ui/unsized-locals/unsized-exprs.stderr +++ b/tests/ui/unsized-locals/unsized-exprs.stderr @@ -6,10 +6,10 @@ LL | udrop::>(A { 0: *foo() }); | = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `A<[u8]>` - --> $DIR/unsized-exprs.rs:3:8 + --> $DIR/unsized-exprs.rs:3:21 | LL | struct A(X); - | ^ - required by this field + | ^ required by this field note: unsized values must be place expressions and cannot be put in temporaries --> $DIR/unsized-exprs.rs:19:22 | @@ -24,10 +24,10 @@ LL | udrop::>(A(*foo())); | = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]` note: required because it appears within the type `A<[u8]>` - --> $DIR/unsized-exprs.rs:3:8 + --> $DIR/unsized-exprs.rs:3:21 | LL | struct A(X); - | ^ - required by this field + | ^ required by this field note: unsized values must be place expressions and cannot be put in temporaries --> $DIR/unsized-exprs.rs:21:22 | diff --git a/tests/ui/unsized/unsized-enum2.stderr b/tests/ui/unsized/unsized-enum2.stderr index 20cf2556c5df7..e790e74b41b00 100644 --- a/tests/ui/unsized/unsized-enum2.stderr +++ b/tests/ui/unsized/unsized-enum2.stderr @@ -322,10 +322,10 @@ LL | VI(Path1), | = help: within `Path1`, the trait `Sized` is not implemented for `(dyn PathHelper1 + 'static)` note: required because it appears within the type `Path1` - --> $DIR/unsized-enum2.rs:16:8 + --> $DIR/unsized-enum2.rs:16:14 | LL | struct Path1(dyn PathHelper1); - | ^^^^^ --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -345,10 +345,10 @@ LL | VJ{x: Path2}, | = help: within `Path2`, the trait `Sized` is not implemented for `(dyn PathHelper2 + 'static)` note: required because it appears within the type `Path2` - --> $DIR/unsized-enum2.rs:17:8 + --> $DIR/unsized-enum2.rs:17:14 | LL | struct Path2(dyn PathHelper2); - | ^^^^^ --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -368,10 +368,10 @@ LL | VK(isize, Path3), | = help: within `Path3`, the trait `Sized` is not implemented for `(dyn PathHelper3 + 'static)` note: required because it appears within the type `Path3` - --> $DIR/unsized-enum2.rs:18:8 + --> $DIR/unsized-enum2.rs:18:14 | LL | struct Path3(dyn PathHelper3); - | ^^^^^ --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size @@ -391,10 +391,10 @@ LL | VL{u: isize, x: Path4}, | = help: within `Path4`, the trait `Sized` is not implemented for `(dyn PathHelper4 + 'static)` note: required because it appears within the type `Path4` - --> $DIR/unsized-enum2.rs:19:8 + --> $DIR/unsized-enum2.rs:19:14 | LL | struct Path4(dyn PathHelper4); - | ^^^^^ --------------- required by this field + | ^^^^^^^^^^^^^^^ required by this field = note: no field of an enum variant may have a dynamically sized type = help: change the field's type to have a statically known size help: borrowed types always have a statically known size diff --git a/tests/ui/unsized/unsized-struct.stderr b/tests/ui/unsized/unsized-struct.stderr index d7d392cf9e5f6..81c70eb8c61b1 100644 --- a/tests/ui/unsized/unsized-struct.stderr +++ b/tests/ui/unsized/unsized-struct.stderr @@ -33,10 +33,10 @@ LL | fn bar2() { is_sized::>() } | this type parameter needs to be `Sized` | note: required because it appears within the type `Bar` - --> $DIR/unsized-struct.rs:11:8 + --> $DIR/unsized-struct.rs:11:25 | LL | struct Bar { data: T } - | ^^^ ------- required by this field + | ^^^^^^^ required by this field note: required by a bound in `is_sized` --> $DIR/unsized-struct.rs:1:15 | diff --git a/tests/ui/unsized/unsized3.stderr b/tests/ui/unsized/unsized3.stderr index 547bb9ca62e34..477f1737d15c8 100644 --- a/tests/ui/unsized/unsized3.stderr +++ b/tests/ui/unsized/unsized3.stderr @@ -55,12 +55,11 @@ LL | f5(x1); | required by a bound introduced by this call | note: required because it appears within the type `S` - --> $DIR/unsized3.rs:28:8 + --> $DIR/unsized3.rs:29:5 | LL | struct S { - | ^ LL | x: X, - | ---- required by this field + | ^^^^ required by this field note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 | @@ -85,12 +84,11 @@ LL | f5(&(*x1, 34)); | ^^ doesn't have a size known at compile-time | note: required because it appears within the type `S` - --> $DIR/unsized3.rs:28:8 + --> $DIR/unsized3.rs:29:5 | LL | struct S { - | ^ LL | x: X, - | ---- required by this field + | ^^^^ required by this field = note: only the last element of a tuple may have a dynamically sized type help: consider removing the `?Sized` bound to make the type parameter `Sized` | @@ -107,12 +105,11 @@ LL | f5(&(32, *x1)); | ^^^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `S` - --> $DIR/unsized3.rs:28:8 + --> $DIR/unsized3.rs:29:5 | LL | struct S { - | ^ LL | x: X, - | ---- required by this field + | ^^^^ required by this field = note: required because it appears within the type `({integer}, S)` = note: tuples must have a statically known size to be initialized help: consider removing the `?Sized` bound to make the type parameter `Sized` @@ -132,12 +129,11 @@ LL | f5(&(32, *x1)); | required by a bound introduced by this call | note: required because it appears within the type `S` - --> $DIR/unsized3.rs:28:8 + --> $DIR/unsized3.rs:29:5 | LL | struct S { - | ^ LL | x: X, - | ---- required by this field + | ^^^^ required by this field = note: required because it appears within the type `({integer}, S)` note: required by an implicit `Sized` bound in `f5` --> $DIR/unsized3.rs:24:7 diff --git a/tests/ui/wf/let-pat-inferred-non-wf.stderr b/tests/ui/wf/let-pat-inferred-non-wf.stderr index d05ed37578820..b9059df11ed8e 100644 --- a/tests/ui/wf/let-pat-inferred-non-wf.stderr +++ b/tests/ui/wf/let-pat-inferred-non-wf.stderr @@ -51,10 +51,10 @@ LL | let [S(ref x)]; | = help: within `S`, the trait `Sized` is not implemented for `str` note: required because it appears within the type `S` - --> $DIR/let-pat-inferred-non-wf.rs:8:8 + --> $DIR/let-pat-inferred-non-wf.rs:8:21 | LL | struct S(T); - | ^ - required by this field + | ^ required by this field = note: slice and array elements must have `Sized` type error: aborting due to 6 previous errors From 76384db023d5844f27d8568a9214a5014d7facde Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Fri, 25 Sep 2026 04:34:55 +0000 Subject: [PATCH 0815/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 0d38a842626a6e3b70e2c1efd76a8f22d2556d73. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index b9900a7795af4..ab61f3f74a54a 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -3670d2532bdf51abbe0b8fea22284d7ca340ffe3 +0d38a842626a6e3b70e2c1efd76a8f22d2556d73 From 6846fe9a097dd8baf0af6113272159768cb56bb9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 24 Sep 2026 00:38:00 +1000 Subject: [PATCH 0816/1309] Fix `Diverges` When it was added in PR 37412 it was a simple three-value lattice type implementing `PartialOrd`/`Ord`, and also implementing `BitAnd`/`BitOr` using `min`/`max`. This all made sense. Then in PR 64592 the `Always` variant got a span and a custom note added. This makes the meaning of all those operations much murkier. And the `is_always` method gained an alarming comment: > Enum comparison ignores the contents of fields, so we just fill them > in with garbage here. This is false! Enum comparison does use the contents of fields. This commit removes the `PartialOrd`/`Ord` impls and redoes `BitAnd`/`BitOr` in a way that preserves existing behaviour without relying on `span` and `custom_note` ordering. In the `Always`/`Always` case we now always use the fields from `self`; this is potentially different to the old behaviour but in practice no test outputs are affected, and at most some error messages might be slightly different. This helps with the next commit by removing some `Span` ordering operations. --- compiler/rustc_hir_typeck/src/diverges.rs | 29 ++++++++++++++++------- 1 file changed, 20 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs index 1a10e19d0a5e9..15ce40d417af2 100644 --- a/compiler/rustc_hir_typeck/src/diverges.rs +++ b/compiler/rustc_hir_typeck/src/diverges.rs @@ -1,13 +1,13 @@ -use std::{cmp, ops}; +use std::ops; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::Span; /// Tracks whether executing a node may exit normally (versus /// return/break/panic, which "diverge", leaving dead code in their /// wake). Tracked semi-automatically (through type variables marked /// as diverging), with some manual adjustments for control-flow /// primitives (approximating a CFG). -#[derive(Copy, Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Copy, Clone, Debug, PartialEq, Eq)] pub(crate) enum Diverges { /// Potentially unknown, some cases converge, /// others require a CFG to determine them. @@ -40,14 +40,28 @@ pub(crate) enum Diverges { impl ops::BitAnd for Diverges { type Output = Self; fn bitand(self, other: Self) -> Self { - cmp::min(self, other) + match (self, other) { + (x @ Self::Maybe, _) => x, + (_, x @ Self::Maybe) => x, + // Using `span`/`custom_note` from `self` seems to give better error messages. + (x @ Self::Always { .. }, Self::Always { .. }) => x, + (Self::WarnedAlways, x) => x, + (x, Self::WarnedAlways) => x, + } } } impl ops::BitOr for Diverges { type Output = Self; fn bitor(self, other: Self) -> Self { - cmp::max(self, other) + match (self, other) { + (x @ Self::WarnedAlways, _) => x, + (_, x @ Self::WarnedAlways) => x, + // Using `span`/`custom_note` from `self` seems to give better error messages. + (x @ Self::Always { .. }, Self::Always { .. }) => x, + (Self::Maybe, x) => x, + (x, Self::Maybe) => x, + } } } @@ -70,9 +84,6 @@ impl Diverges { } pub(super) fn is_always(self) -> bool { - // Enum comparison ignores the - // contents of fields, so we just - // fill them in with garbage here. - self >= Diverges::Always { span: DUMMY_SP, custom_note: None } + matches!(self, Diverges::WarnedAlways | Diverges::Always { .. }) } } From dbc472b15467e68cb138282a1b0af8b8cfc3f995 Mon Sep 17 00:00:00 2001 From: Roland Xu Date: Fri, 25 Sep 2026 13:15:25 +0800 Subject: [PATCH 0817/1309] Use get to avoid ICE on unresolved imports --- compiler/rustc_resolve/src/check_unused.rs | 2 +- .../ui/imports/unused-import-issue-163294.rs | 9 ++++++++ .../imports/unused-import-issue-163294.stderr | 23 +++++++++++++++++++ 3 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 tests/ui/imports/unused-import-issue-163294.rs create mode 100644 tests/ui/imports/unused-import-issue-163294.stderr diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index daa816c276482..aac244ad6cf22 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -136,7 +136,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { ast::UseTreeKind::Simple(Some(ident)) => { if ident.name == kw::Underscore && !matches!( - self.r.current_owner.import_res[&id].type_ns, + self.r.current_owner.import_res.get(&id).and_then(|res| res.type_ns), Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) ) { diff --git a/tests/ui/imports/unused-import-issue-163294.rs b/tests/ui/imports/unused-import-issue-163294.rs new file mode 100644 index 0000000000000..7793f1da760e2 --- /dev/null +++ b/tests/ui/imports/unused-import-issue-163294.rs @@ -0,0 +1,9 @@ +//@ edition: 2015 + +#![deny(unused_imports)] + +pub use core as _; +//~^ ERROR unresolved import `core` +//~^^ ERROR unused import: `core as _` + +fn main() {} diff --git a/tests/ui/imports/unused-import-issue-163294.stderr b/tests/ui/imports/unused-import-issue-163294.stderr new file mode 100644 index 0000000000000..ebb319562189a --- /dev/null +++ b/tests/ui/imports/unused-import-issue-163294.stderr @@ -0,0 +1,23 @@ +error[E0432]: unresolved import `core` + --> $DIR/unused-import-issue-163294.rs:5:9 + | +LL | pub use core as _; + | ----^^^^^ + | | + | no `core` in the root + +error: unused import: `core as _` + --> $DIR/unused-import-issue-163294.rs:5:9 + | +LL | pub use core as _; + | ^^^^^^^^^ + | +note: the lint level is defined here + --> $DIR/unused-import-issue-163294.rs:3:9 + | +LL | #![deny(unused_imports)] + | ^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0432`. From c57dbadb03995c00217b91306e416c5fc2de08d7 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 25 Sep 2026 08:40:20 +0300 Subject: [PATCH 0818/1309] Review: use Option instead of a bool flag, inline `switch_to_non_det_mode` --- compiler/rustc_hir_id/src/definitions.rs | 26 +++++-------------- .../src/rmeta/def_path_hash_map.rs | 2 +- 2 files changed, 8 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index a06e8336db2e4..8f60f8ce3a01c 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -59,8 +59,7 @@ impl LocalDefIdMap { #[derive(Debug, Default)] pub struct DefPathToIndexMap { pub det_part: DefPathHashMap, - pub non_det_part: SortedMap, - non_det_mode: bool, + pub non_det_part: Option>, } impl DefPathToIndexMap { @@ -68,13 +67,7 @@ impl DefPathToIndexMap { pub fn get(&self, hash: &Hash64) -> Option { match self.det_part.get(hash) { Some(index) => Some(index), - None => { - if self.non_det_mode { - self.non_det_part.get(hash).copied() - } else { - None - } - } + None => self.non_det_part.as_ref().and_then(|map| map.get(hash).copied()), } } @@ -84,22 +77,17 @@ impl DefPathToIndexMap { /// def index into `det_part` when we are in non-deterministic mode. #[inline] pub fn insert(&mut self, hash: &Hash64, index: DefIndex) -> Option { - match self.non_det_mode { - false => self.det_part.insert(hash, &index), - true => { + match self.non_det_part.as_mut() { + None => self.det_part.insert(hash, &index), + Some(map) => { if let Some(existing) = self.det_part.get(hash) { return Some(existing); } - self.non_det_part.insert(*hash, index) + map.insert(*hash, index) } } } - - #[inline] - pub fn switch_to_non_det_mode(&mut self) { - self.non_det_mode = true; - } } #[derive(Debug)] @@ -308,7 +296,7 @@ impl Definitions { /// This function indicates that def ids allocations are non-deterministic after /// it was called. pub fn commit_end_of_determinism(&mut self) { - self.def_path_hash_to_index.switch_to_non_det_mode(); + self.def_path_hash_to_index.non_det_part = Some(Default::default()); } #[inline(always)] diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 1092d56a331f6..923c07cd764c9 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -43,7 +43,7 @@ impl<'a, 'tcx> Encodable> for DefPathHashMapRef<'tcx> { e.emit_usize(bytes.len()); e.emit_raw_bytes(bytes); - map.non_det_part.range(..).encode(e); + map.non_det_part.as_ref().unwrap_or(&Default::default()).range(..).encode(e); } DefPathHashMapRef::OwnedFromMetadata(..) => { panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") From 1b504b3a0b30df3b18224def8e102f815901e3fa Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 25 Sep 2026 08:48:08 +0300 Subject: [PATCH 0819/1309] Review: use `or_else` instead of matches --- compiler/rustc_hir_id/src/definitions.rs | 7 +++---- compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs | 5 +---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 8f60f8ce3a01c..263ea4a026e2d 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -65,10 +65,9 @@ pub struct DefPathToIndexMap { impl DefPathToIndexMap { #[inline] pub fn get(&self, hash: &Hash64) -> Option { - match self.det_part.get(hash) { - Some(index) => Some(index), - None => self.non_det_part.as_ref().and_then(|map| map.get(hash).copied()), - } + self.det_part + .get(hash) + .or_else(|| self.non_det_part.as_ref().and_then(|map| map.get(hash).copied())) } /// This insert function does not behave like regular `insert` of a `HashMap`, diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 923c07cd764c9..7f625d59fa784 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -23,10 +23,7 @@ impl DefPathHashMapRef<'_> { match self { DefPathHashMapRef::OwnedFromMetadata(det_map, non_det_map) => { let hash = &def_path_hash.local_hash(); - match det_map.get(hash) { - Some(index) => Some(index), - None => non_det_map.get(hash).copied(), - } + det_map.get(hash).or_else(|| non_det_map.get(hash).copied()) } DefPathHashMapRef::BorrowedFromTcx(_) => { panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization") From 956cc84bae470d2a674a3e2a0f2f769173741e50 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Fri, 25 Sep 2026 08:53:18 +0300 Subject: [PATCH 0820/1309] Review: pass hash by value --- compiler/rustc_hir_id/src/definitions.rs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 263ea4a026e2d..d177630e7a8fc 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -64,10 +64,10 @@ pub struct DefPathToIndexMap { impl DefPathToIndexMap { #[inline] - pub fn get(&self, hash: &Hash64) -> Option { + pub fn get(&self, hash: Hash64) -> Option { self.det_part - .get(hash) - .or_else(|| self.non_det_part.as_ref().and_then(|map| map.get(hash).copied())) + .get(&hash) + .or_else(|| self.non_det_part.as_ref().and_then(|map| map.get(&hash).copied())) } /// This insert function does not behave like regular `insert` of a `HashMap`, @@ -75,15 +75,15 @@ impl DefPathToIndexMap { /// def index for local hash before panicking. So we can do not actually insert /// def index into `det_part` when we are in non-deterministic mode. #[inline] - pub fn insert(&mut self, hash: &Hash64, index: DefIndex) -> Option { + pub fn insert(&mut self, hash: Hash64, index: DefIndex) -> Option { match self.non_det_part.as_mut() { - None => self.det_part.insert(hash, &index), + None => self.det_part.insert(&hash, &index), Some(map) => { - if let Some(existing) = self.det_part.get(hash) { + if let Some(existing) = self.det_part.get(&hash) { return Some(existing); } - map.insert(*hash, index) + map.insert(hash, index) } } } @@ -372,7 +372,7 @@ impl Definitions { // Check for hash collisions of DefPathHashes. These should be // exceedingly rare. if let Some(existing) = - self.def_path_hash_to_index.insert(&local_hash, def_id.local_def_index) + self.def_path_hash_to_index.insert(local_hash, def_id.local_def_index) { let def_path1 = self.def_path(LocalDefId { local_def_index: existing }); let def_path2 = self.def_path(def_id); @@ -460,7 +460,7 @@ impl Definitions { pub fn local_def_path_hash_to_def_id(&self, hash: DefPathHash) -> Option { debug_assert!(hash.stable_crate_id() == self.stable_crate_id); self.def_path_hash_to_index - .get(&hash.local_hash()) + .get(hash.local_hash()) .map(|local_def_index| LocalDefId { local_def_index }) } From e47397562a314cd744e354899738e2b4baf9a713 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 25 Sep 2026 15:30:27 +1000 Subject: [PATCH 0821/1309] Remove `rustc_codegen_ssa::back::write::Diagnostic` It's a cut down version of `rustc_errors::DiagInner` that avoids `Span`. It exists because `Span` used to not impl `Send` and so couldn't be sent from codegen threads to the main thread. But that's no longer true and we can send `DiagInner`s directly now. --- compiler/rustc_codegen_ssa/src/back/write.rs | 78 ++------------------ 1 file changed, 7 insertions(+), 71 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 147e4c43c7103..d53f6278fa253 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -4,15 +4,15 @@ use std::panic::AssertUnwindSafe; use std::path::{Path, PathBuf}; use std::sync::Arc; use std::sync::mpsc::{Receiver, Sender, channel}; -use std::{assert_matches, fs, io, mem, str, thread}; +use std::{assert_matches, fs, io, str, thread}; use rustc_abi::Size; use rustc_data_structures::jobserver::{self, Acquired}; use rustc_data_structures::profiling::{SelfProfilerRef, VerboseTimingGuard}; use rustc_errors::emitter::Emitter; use rustc_errors::{ - Diag, DiagArgMap, DiagCtxt, DiagCtxtHandle, DiagMessage, ErrCode, FatalError, FatalErrorMarker, - Level, MultiSpan, Style, Sublevel, Suggestions, catch_fatal_errors, + Diag, DiagCtxt, DiagCtxtHandle, DiagInner, FatalError, FatalErrorMarker, Level, + catch_fatal_errors, }; use rustc_fs_util::link_or_copy; use rustc_incremental::{ @@ -1191,31 +1191,6 @@ pub(crate) enum ThinLtoMessage { /// process another codegen unit. pub struct CguMessage; -// A cut-down version of `rustc_errors::DiagInner` that impls `Send`, which -// can be used to send diagnostics from codegen threads to the main thread. -// It's missing the following fields from `rustc_errors::DiagInner`. -// - `span`: it doesn't impl `Send`. -// - `suggestions`: it doesn't impl `Send`, and isn't used for codegen -// diagnostics. -// - `is_lint`: lints aren't relevant during codegen. -// - `emitted_at`: not used for codegen diagnostics. -struct Diagnostic { - span: Vec, - level: Level, - messages: Vec<(DiagMessage, Style)>, - code: Option, - children: Vec, - args: DiagArgMap, -} - -// A cut-down version of `rustc_errors::Subdiag` that impls `Send`. It's -// missing the following fields from `rustc_errors::Subdiag`. -// - `span`: it doesn't impl `Send`. -struct Subdiagnostic { - level: Sublevel, - messages: Vec<(DiagMessage, Style)>, -} - #[derive(PartialEq, Clone, Copy, Debug)] enum MainThreadState { /// Doing nothing. @@ -1952,7 +1927,7 @@ fn spawn_thin_lto_work( } enum SharedEmitterMessage { - Diagnostic(Diagnostic), + Diagnostic(DiagInner), InlineAsmError(InlineAsmError), Fatal(String), } @@ -1990,29 +1965,8 @@ impl SharedEmitter { } impl Emitter for SharedEmitter { - fn emit_diagnostic(&mut self, mut diag: rustc_errors::DiagInner) { - // Check that we aren't missing anything interesting when converting to - // the cut-down local `DiagInner`. - assert!(!diag.span.has_span_labels()); - assert_eq!(diag.suggestions, Suggestions::Enabled(vec![])); - assert_eq!(diag.is_lint, None); - // No sensible check for `diag.emitted_at`. - - let args = mem::take(&mut diag.args); - drop( - self.sender.send(SharedEmitterMessage::Diagnostic(Diagnostic { - span: diag.span.primary_spans().iter().map(|span| span.data()).collect::>(), - level: diag.level(), - messages: diag.messages, - code: diag.code, - children: diag - .children - .into_iter() - .map(|child| Subdiagnostic { level: child.level, messages: child.messages }) - .collect(), - args, - })), - ); + fn emit_diagnostic(&mut self, diag: DiagInner) { + drop(self.sender.send(SharedEmitterMessage::Diagnostic(diag))); } fn source_map(&self) -> Option<&SourceMap> { @@ -2037,26 +1991,8 @@ impl SharedEmitterMain { match message { Ok(SharedEmitterMessage::Diagnostic(diag)) => { - // The diagnostic has been received on the main thread. - // Convert it back to a full `Diagnostic` and emit. let dcx = sess.dcx(); - let mut d = - rustc_errors::DiagInner::new_with_messages(diag.level, diag.messages); - d.span = MultiSpan::from_spans( - diag.span.into_iter().map(|span| span.span()).collect(), - ); - d.code = diag.code; // may be `None`, that's ok - d.children = diag - .children - .into_iter() - .map(|sub| rustc_errors::Subdiag { - level: sub.level, - messages: sub.messages, - span: MultiSpan::new(), - }) - .collect(); - d.args = diag.args; - dcx.emit_diagnostic(d); + dcx.emit_diagnostic(diag); sess.dcx().abort_if_errors(); } Ok(SharedEmitterMessage::InlineAsmError(inner)) => { From f01eea524cbbe0168703fef7a0df23a4fa96ca69 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Fri, 25 Sep 2026 15:42:16 +1000 Subject: [PATCH 0822/1309] Remove the `SpanData` in `InlineAsmError` By just storing `lo` and `hi` instead. --- compiler/rustc_codegen_llvm/src/back/write.rs | 17 +++++++---------- compiler/rustc_codegen_ssa/src/back/write.rs | 14 ++++++++++---- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index dd2dbdff6b82c..c18759bc65076 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -22,7 +22,7 @@ use rustc_fs_util::{link_or_copy, path_to_c_string}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; use rustc_session::config::{self, Lto, OutputType, Passes, SplitDwarfKind, SwitchWithOptPath}; -use rustc_span::{BytePos, InnerSpan, Pos, RemapPathScopeComponents, SpanData, SyntaxContext}; +use rustc_span::{BytePos, DUMMY_SP, InnerSpan, Pos, RemapPathScopeComponents}; use rustc_target::spec::{CodeModel, FloatAbi, RelocModel, SanitizerSet, SplitDebuginfo, TlsModel}; use tracing::{debug, trace}; @@ -406,15 +406,12 @@ fn report_inline_asm( // In LTO build we may get srcloc values from other crates which are invalid // since they use a different source map. To be safe we just suppress these // in LTO builds. - let span = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) { - SpanData::default() + let (lo, hi) = if cookie == 0 || matches!(cgcx.lto, Lto::Fat | Lto::Thin) { + (DUMMY_SP.lo(), DUMMY_SP.hi()) } else { - SpanData { - lo: BytePos::from_u32(cookie as u32), - hi: BytePos::from_u32((cookie >> 32) as u32), - ctxt: SyntaxContext::root(), - parent: None, - } + let lo = BytePos::from_u32(cookie as u32); + let hi = BytePos::from_u32((cookie >> 32) as u32); + (lo, hi) }; let level = match level { llvm::DiagnosticLevel::Error => Level::Error, @@ -422,7 +419,7 @@ fn report_inline_asm( llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; let msg = msg.trim_prefix("error: ").to_string(); - InlineAsmError { span, msg, level, source } + InlineAsmError { lo, hi, msg, level, source } } unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) { diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index d53f6278fa253..d3c8110025185 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -27,7 +27,7 @@ use rustc_session::config::{ }; use rustc_session::{IncrCompSession, Session}; use rustc_span::source_map::SourceMap; -use rustc_span::{FileName, InnerSpan, Span, SpanData, bug}; +use rustc_span::{BytePos, FileName, InnerSpan, Span, SyntaxContext, bug}; use rustc_structures::CrateType; use rustc_target::spec::{MergeFunctions, SanitizerSet}; use tracing::debug; @@ -1933,7 +1933,12 @@ enum SharedEmitterMessage { } pub struct InlineAsmError { - pub span: SpanData, + // We store byte positions rather than a `Span` because this error is created on a codegen + // thread which doesn't have access to the span interner within the session globals. The byte + // positions are converted to a `Span` once they reach a thread with access to the span + // interner. + pub lo: BytePos, + pub hi: BytePos, pub msg: String, pub level: Level, pub source: Option<(String, Vec)>, @@ -1998,8 +2003,9 @@ impl SharedEmitterMain { Ok(SharedEmitterMessage::InlineAsmError(inner)) => { assert_matches!(inner.level, Level::Error | Level::Warning | Level::Note); let mut err = Diag::new(sess.dcx(), inner.level, inner.msg); - if !inner.span.is_dummy() { - err.span(inner.span.span()); + let span = Span::new(inner.lo, inner.hi, SyntaxContext::root(), None); + if !span.is_dummy() { + err.span(span); } // Point to the generated assembly if it is available. From 4b538231e35e6edbc13ed012dd788a8f432d73fd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 25 Sep 2026 09:32:43 +0200 Subject: [PATCH 0823/1309] ty::CoroutineClosure is more a closure than a coroutine --- compiler/rustc_middle/src/ty/sty.rs | 2 +- compiler/rustc_type_ir/src/ty_kind.rs | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 01549c3e3fd53..243ad73e3dfb8 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2190,7 +2190,7 @@ impl<'tcx> Ty<'tcx> { def.flags().contains(AdtFlags::IS_MAYBE_DANGLING) || def.flags().contains(AdtFlags::IS_MANUALLY_DROP) } - ty::Coroutine(..) | ty::CoroutineClosure(..) => true, + ty::Coroutine(..) => true, _ => false, } } diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 68a1b479830e2..35f8897afd4c4 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -259,7 +259,9 @@ pub enum TyKind { /// `ClosureArgs` for more details. Closure(I::ClosureId, I::GenericArgs), - /// The anonymous type of a closure. Used to represent the type of `async |a| a`. + /// The anonymous type of an async closure. Used to represent the type of `async |a| a`. + /// + /// This type itself is not a coroutine, it just represents a closure that returns one. /// /// Coroutine-closure args contain both the - potentially instantiated - generic /// parameters of its parent and some synthetic parameters. See the documentation From 79cbf77c912d0209615051164f1227cac6c483b5 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 20 Sep 2026 21:16:48 +0200 Subject: [PATCH 0824/1309] run windows-fs tests natively --- src/tools/miri/src/shims/windows/fs.rs | 5 +++- .../miri/tests/pass-dep/shims/windows-fs.rs | 23 +++++++++++-------- 2 files changed, 18 insertions(+), 10 deletions(-) diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index 9aae6677faeb2..6a9963159b1bc 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -377,7 +377,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let attributes = if file_type.is_dir() { this.eval_windows_u32("c", "FILE_ATTRIBUTE_DIRECTORY") } else if file_type.is_file() { - this.eval_windows_u32("c", "FILE_ATTRIBUTE_NORMAL") + // Normal files seem to have the "archive" attribute. There's also + // `FILE_ATTRIBUTE_NORMAL` but that's for files without any other attribute which, + // apparently, is not normal. + this.eval_windows_u32("c", "FILE_ATTRIBUTE_ARCHIVE") } else { this.eval_windows_u32("c", "FILE_ATTRIBUTE_DEVICE") }; diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index 80f8ef9359d3b..ecac238240872 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -1,5 +1,7 @@ //@only-target: windows # this directly tests windows-only functions //@compile-flags: -Zmiri-disable-isolation +//@run-native + #![allow(nonstandard_style)] use std::io::{ErrorKind, Read, Seek, SeekFrom, Write}; @@ -19,15 +21,19 @@ use windows_sys::Win32::Foundation::{ }; use windows_sys::Win32::Storage::FileSystem::{ BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, DeleteFileW, - FILE_ALLOCATION_INFO, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_NORMAL, FILE_BEGIN, - FILE_CURRENT, FILE_END_OF_FILE_INFO, FILE_FLAG_BACKUP_SEMANTICS, FILE_FLAG_OPEN_REPARSE_POINT, - FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, FileAllocationInfo, FileEndOfFileInfo, - FlushFileBuffers, GetFileInformationByHandle, MoveFileExW, OPEN_ALWAYS, OPEN_EXISTING, - SetFileInformationByHandle, SetFilePointerEx, + FILE_ALLOCATION_INFO, FILE_ATTRIBUTE_ARCHIVE, FILE_ATTRIBUTE_DIRECTORY, FILE_ATTRIBUTE_NORMAL, + FILE_BEGIN, FILE_CURRENT, FILE_END_OF_FILE_INFO, FILE_FLAG_BACKUP_SEMANTICS, + FILE_FLAG_OPEN_REPARSE_POINT, FILE_SHARE_DELETE, FILE_SHARE_READ, FILE_SHARE_WRITE, + FileAllocationInfo, FileEndOfFileInfo, FlushFileBuffers, GetFileInformationByHandle, + MoveFileExW, OPEN_ALWAYS, OPEN_EXISTING, SetFileInformationByHandle, SetFilePointerEx, }; use windows_sys::Win32::System::IO::IO_STATUS_BLOCK; use windows_sys::Win32::System::Threading::GetCurrentProcess; +// Windows seems to usually but not always set FILE_ATTRIBUTE_ARCHIVE for new files. +// So we accept either "ARCHIVE" or "NORMAL". +const REGULAR_FILE: u32 = FILE_ATTRIBUTE_ARCHIVE | FILE_ATTRIBUTE_NORMAL; + fn main() { unsafe { test_create_dir_file(); @@ -87,9 +93,8 @@ unsafe fn test_create_normal_file() { if GetFileInformationByHandle(handle, &mut info) == 0 { panic!("Failed to get file information: {}", GetLastError()) }; - // FIXME: this test is wrong, somehow. It doesn't pass when run natively. - // - assert!(info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL != 0); + assert!(info.dwFileAttributes & REGULAR_FILE != 0); + assert!(info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY == 0); if CloseHandle(handle) == 0 { panic!("Failed to close file") }; @@ -121,7 +126,7 @@ unsafe fn test_create_normal_file() { if GetFileInformationByHandle(handle, &mut info) == 0 { panic!("Failed to get file information: {}", GetLastError()) }; - assert!(info.dwFileAttributes & FILE_ATTRIBUTE_NORMAL != 0); + assert!(info.dwFileAttributes & REGULAR_FILE != 0); if CloseHandle(handle) == 0 { panic!("Failed to close file") }; From a579f7e4b5bd444a569b18ac26e9b4ab52fcc338 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Fri, 25 Sep 2026 08:14:05 +0000 Subject: [PATCH 0825/1309] Add -Ctarget-feature=-crt-static to CFI minimal runtime tests --- tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs | 2 +- tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs index aacea1ee65dd2..689c141811f60 100644 --- a/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs +++ b/tests/ui/target_modifiers/auxiliary/cfi-minimal-runtime.rs @@ -1,6 +1,6 @@ //@ no-prefer-dynamic //@ needs-sanitizer-cfi -//@ compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime +//@ compile-flags: -Clto -Ctarget-feature=-crt-static -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime #![feature(no_core)] #![crate_type = "rlib"] diff --git a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs index 45c6ad7b521a3..fe2be11e6a3d5 100644 --- a/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs +++ b/tests/ui/target_modifiers/sanitizer-cfi-minimal-runtime.rs @@ -2,6 +2,7 @@ //@ needs-sanitizer-cfi //@ aux-build:cfi-minimal-runtime.rs +//@ compile-flags: -Ctarget-feature=-crt-static //@ revisions: ok wrong_flag wrong_sanitizer //@[ok] compile-flags: -Clto -Zsanitizer=cfi -Zsanitizer-cfi-recover -Zsanitizer-cfi-minimal-runtime From 88f108876abc1a08946bfe15ea4fb14287db6da7 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 25 Sep 2026 13:04:03 +0200 Subject: [PATCH 0826/1309] rename GCA features --- compiler/rustc_ast/src/ast.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 16 +++---- compiler/rustc_ast_passes/src/feature_gate.rs | 10 ++-- .../src/attributes/semantics.rs | 2 +- compiler/rustc_feature/src/removed.rs | 6 ++- compiler/rustc_feature/src/unstable.rs | 26 +++++------ compiler/rustc_hir/src/hir.rs | 2 +- .../src/check/compare_impl_item.rs | 4 +- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/generics_of.rs | 2 +- .../src/hir_ty_lowering/bounds.rs | 4 +- .../src/hir_ty_lowering/errors.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 12 ++--- compiler/rustc_middle/src/queries.rs | 2 +- compiler/rustc_middle/src/traits/mod.rs | 2 +- compiler/rustc_middle/src/ty/assoc.rs | 2 +- compiler/rustc_middle/src/ty/context.rs | 6 +-- .../src/builder/expr/as_constant.rs | 6 +-- .../src/thir/pattern/const_to_pat.rs | 8 ++-- .../src/solve/eval_ctxt/mod.rs | 2 +- compiler/rustc_parse/src/parser/path.rs | 2 +- .../rustc_resolve/src/diagnostics/impls.rs | 2 +- compiler/rustc_resolve/src/diagnostics/mod.rs | 2 +- compiler/rustc_resolve/src/ident.rs | 4 +- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 8 ++-- compiler/rustc_span/src/symbol.rs | 4 ++ .../traits/fulfillment_errors.rs | 3 +- .../src/traits/const_evaluatable.rs | 2 +- .../src/traits/dyn_compatibility.rs | 8 ++-- .../src/traits/normalize.rs | 2 +- .../src/traits/select/mod.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 6 +-- compiler/rustc_type_ir/src/const_kind.rs | 2 +- compiler/rustc_type_ir/src/inherent.rs | 2 +- library/core/src/marker.rs | 2 +- library/std/src/lib.rs | 2 +- src/doc/rustc-dev-guide/src/const-generics.md | 6 +-- src/doc/rustc-dev-guide/src/normalization.md | 2 +- ...neric-const-args.md => gca-const-items.md} | 12 ++--- ...ic-const-args.md => gca-macroless-args.md} | 24 +++++----- ...c-const-args.md => gca-macroless-items.md} | 32 ++++++------- ...c-const-args.md => gca-min-const-items.md} | 18 ++++---- .../language-features/generic-const-exprs.md | 6 +-- .../language-features/generic-const-items.md | 4 +- src/tools/clippy/CHANGELOG.md | 2 +- src/tools/clippy/clippy_utils/src/consts.rs | 2 +- .../clippy/tests/ui/crashes/mgca-16691.rs | 2 +- ...duplication_in_bounds_assoc_const_eq.fixed | 2 +- ...it_duplication_in_bounds_assoc_const_eq.rs | 2 +- src/tools/rustfmt/tests/source/gca.rs | 4 +- src/tools/rustfmt/tests/target/gca.rs | 4 +- tests/crashes/138009.rs | 2 +- tests/crashes/149809.rs | 2 +- tests/crashes/150049.rs | 2 +- tests/crashes/150749.rs | 2 +- tests/debuginfo/associated-const-bindings.rs | 2 +- tests/pretty/gca-macro.pp | 2 +- tests/pretty/gca-macro.rs | 2 +- .../ice-associated-const-equality-105952.rs | 2 +- .../auxiliary/assoc-const-equality.rs | 2 +- .../type-const-associated-const-no-body.rs | 2 +- .../rustdoc-html/type-const-free-in-array.rs | 2 +- .../type-const-inherent-with-body.rs | 2 +- .../associated-constant-not-allowed-102467.rs | 2 +- ...-const-equality-region-var-hash-ice.stderr | 2 +- ...oc-const-equality-unexpected-region.stderr | 2 +- ...ociated-const-type-parameter-arrays.stderr | 2 +- tests/ui/associated-consts/issue-110933.rs | 2 +- tests/ui/associated-consts/issue-47814.stderr | 2 +- .../type-const-in-array-len-wrong-type.rs | 4 +- .../type-const-in-array-len.rs | 2 +- .../associated-item-duplicate-bounds.stderr | 2 +- .../duplicate-bound-err.rs | 2 +- .../associated-type-bounds/duplicate-bound.rs | 2 +- .../associated-types-eq-2.stderr | 8 ++-- .../type-const-inherent-impl-normalize.rs | 2 +- .../type-const-inherent-impl-normalize.stderr | 4 +- .../resolved-region-var-max-universe.rs | 2 +- tests/ui/attributes/malformed-attrs.rs | 2 +- .../index-oob-ice-83993.stderr | 4 +- .../associated-const-bindings/ambiguity.rs | 2 +- .../assoc-const-ty-mismatch.rs | 2 +- .../associated-const-bindings/assoc-const.rs | 2 +- .../bound-var-in-ty-not-wf.rs | 2 +- .../bound-var-in-ty.rs | 2 +- .../coexisting-with-type-binding.rs | 2 +- .../associated-const-bindings/coherence.rs | 2 +- .../const-bound-to-assoc-ty-99828.stderr | 2 +- .../const-projection-err.rs | 2 +- .../const_evaluatable_unchecked.rs | 2 +- ...dyn-compat-assoc-const-ty-mentions-self.rs | 2 +- .../dyn-compat-basic.rs | 2 +- .../dyn-compat-const-mismatch.rs | 2 +- ...ompat-const-param-default-mentions-self.rs | 2 +- ...ection-behind-trait-alias-mentions-self.rs | 2 +- ...rojection-from-supertrait-mentions-self.rs | 2 +- .../dyn-compat-generic-assoc-const.rs | 2 +- .../dyn-compat-non-type-assoc-const.rs | 2 +- ...und-on-assoc-const-allowed-and-enforced.rs | 2 +- ...elf-const-projections-in-assoc-const-ty.rs | 4 +- ...ompat-self-const-projections-in-methods.rs | 2 +- ...-const-projections-in-supertrait-bounds.rs | 2 +- .../dyn-compat-symbol-mangling.rs | 2 +- .../dyn-compat-unspecified-assoc-consts.rs | 2 +- ...yn-const-projection-escaping-bound-vars.rs | 2 +- .../equality-unused-issue-126729.rs | 2 +- .../equality_bound_with_infer.rs | 2 +- .../esc-bound-var-in-ty.rs | 2 +- .../issue-102335-const.rs | 2 +- .../issue-105330.stderr | 4 +- .../issue-93835.stderr | 4 +- ...with-generic-in-ace-no-feature-gate.stderr | 2 +- .../mismatched-types-with-generic-in-ace.rs | 2 +- .../associated-const-bindings/missing.rs | 2 +- .../normalization-via-param-env.rs | 2 +- .../associated-const-bindings/param-in-ty.rs | 2 +- .../projection-unspecified-but-bounded.rs | 2 +- .../associated-const-bindings/supertraits.rs | 2 +- .../unbraced-enum-variant.rs | 2 +- .../unconstrained_impl_param.stderr | 2 +- .../using-fnptr-as-type_const.rs | 2 +- .../wf-mismatch-1.rs | 2 +- .../wf-mismatch-2.rs | 2 +- .../wf-mismatch-3.rs | 2 +- .../const-arg-in-const-arg.min.stderr | 46 +++++++++---------- .../const-argument-if-length.min.stderr | 2 +- ...st-argument-non-static-lifetime.min.stderr | 2 +- .../complex-generic-default-expr.min.stderr | 4 +- ...const_arg_trivial_macro_expansion-4.stderr | 6 +-- .../early/macro_rules-braces.stderr | 8 ++-- ...ial-const-arg-macro-nested-braces-2.stderr | 2 +- ...ivial-const-arg-macro-nested-braces.stderr | 2 +- .../trivial-const-arg-nested-braces.stderr | 2 +- .../fn-item-as-const-arg-137084.rs | 2 +- ...s-on-failed-eval-with-vars-fail.old.stderr | 6 +-- ...ambiguous-on-failed-eval-with-vars-fail.rs | 4 +- .../gca/ambiguous-on-failed-eval-with-vars.rs | 6 +-- tests/ui/const-generics/gca/assoc-const.rs | 2 +- .../gca/basic-different-definitions.rs | 4 +- tests/ui/const-generics/gca/basic.rs | 4 +- tests/ui/const-generics/gca/coherence-fail.rs | 2 +- tests/ui/const-generics/gca/coherence-ok.rs | 2 +- ...onst-pattern-field-type-mismatch-162394.rs | 6 +-- .../gca/const-reference-to-constructor.rs | 4 +- ...dyn-compat-generic-non-type-assoc-const.rs | 4 +- .../gca/dyn-non-type-assoc-const-binding.rs | 2 +- .../gca/gca-anon-const-rejected.rs | 4 +- .../const-generics/gca/gca-macro-fn-call.rs | 6 +-- .../const-generics/gca/generic-free-const.rs | 6 +-- .../const-generics/gca/generic-param-rhs.rs | 2 +- .../gca/non-type-equality-fail.rs | 2 +- .../gca/non-type-equality-ok.rs | 8 ++-- .../gca/path-to-non-type-const.rs | 6 +-- .../const-generics/gca/require-next-solver.rs | 4 +- .../gca/require-next-solver.stderr | 6 +-- .../ui/const-generics/gca/rhs-but-not-root.rs | 4 +- ...suggest-const-item-for-generic-expr.stderr | 6 +-- .../gca/wf-inherentimpl.old.stderr | 6 +-- .../ui/const-generics/gca/wf-inherentimpl.rs | 4 +- ...ay-size-in-generic-struct-param.min.stderr | 4 +- .../auxiliary/non_local_type_const.rs | 2 +- .../generic_const_exprs/bad-multiply.stderr | 2 +- .../dependence_lint.full.stderr | 4 +- .../direct-inline-const-generic-default.rs | 2 +- ...bute-missing-in-dependent-crate-ice.stderr | 2 +- .../feature-gate-generic_const_exprs.stderr | 2 +- .../issue-72787.min.stderr | 8 ++-- ...sue-72819-generic-in-const-eval.min.stderr | 2 +- .../generic_const_exprs/issue-74713.stderr | 2 +- ...xt-solver-gce-incompatible-issue-158428.rs | 4 +- .../generic_const_exprs/non-local-const.rs | 2 +- .../trivial-anon-const-use-cases.min.stderr | 2 +- .../inherent-type-const.rs | 2 +- .../ice-151186-fn-ptr-in-where-clause.rs | 2 +- tests/ui/const-generics/ice-68875.stderr | 2 +- ...ics-type_name-as-const-argument.min.stderr | 2 +- tests/ui/const-generics/issue-46511.stderr | 2 +- .../issues/issue-56445-2.stderr | 2 +- .../issues/issue-56445-3.stderr | 2 +- .../issues/issue-67375.min.stderr | 2 +- .../issues/issue-67945-1.min.stderr | 4 +- .../issues/issue-67945-2.min.stderr | 2 +- .../issues/issue-67945-3.min.stderr | 2 +- .../issues/issue-67945-4.min.stderr | 2 +- .../issues/issue-68366.min.stderr | 2 +- .../issue-76701-ty-param-in-const.stderr | 4 +- .../const-generics/issues/issue-80062.stderr | 2 +- .../const-generics/issues/issue-80375.stderr | 2 +- .../legacy-const-generics-bad.stderr | 2 +- .../mgca/adt_expr_arg_simple.rs | 2 +- .../mgca/adt_expr_arg_simple.stderr | 2 +- .../mgca/adt_expr_arg_tuple_expr_fail.rs | 4 +- .../mgca/adt_expr_erroneuous_inits.rs | 2 +- .../mgca/adt_expr_fields_type_check.rs | 2 +- .../mgca/adt_expr_infers_from_value.rs | 6 +-- .../mgca/adt_expr_unit_enum_extra_field.rs | 2 +- .../mgca/adt_expr_unit_struct_extra_field.rs | 2 +- .../mgca/ambiguous-assoc-const.rs | 2 +- .../mgca/array-const-arg-len-mismatch.rs | 2 +- .../mgca/array-const-arg-type-mismatch.rs | 2 +- .../const-generics/mgca/array-expr-complex.rs | 2 +- .../const-generics/mgca/array-expr-empty.rs | 2 +- .../const-generics/mgca/array-expr-simple.rs | 2 +- ...array-expr-type-mismatch-in-where-bound.rs | 2 +- .../mgca/array-expr-with-assoc-const.rs | 2 +- .../mgca/array-expr-with-macro.rs | 2 +- .../mgca/array-expr-with-struct.rs | 2 +- .../mgca/array-expr-with-tuple.rs | 4 +- .../mgca/array-with-wrong-tuple-type.rs | 4 +- .../mgca/array_elem_type_mismatch.rs | 4 +- .../mgca/array_expr_arg_complex.rs | 2 +- .../mgca/assoc-const-projection-in-bound.rs | 2 +- .../mgca/assoc-const-without-type_const.rs | 2 +- tests/ui/const-generics/mgca/assoc-const.rs | 2 +- ...non-const-def-id-on-const-arg-with-anon.rs | 2 +- .../mgca/bad-const-arg-fn-154539.rs | 2 +- tests/ui/const-generics/mgca/bad-gca-macro.rs | 2 +- .../mgca/bad-impl-trait-with-apit.rs | 2 +- .../mgca/bad-type_const-syntax.rs | 4 +- .../mgca/bad-type_const-syntax.stderr | 12 ++--- .../mgca/braced-const-infer-in-body.rs | 4 +- .../const-generics/mgca/braced-const-infer.rs | 2 +- .../concrete-expr-with-generics-in-env.rs | 2 +- ...const-arg-coherence-conflicting-methods.rs | 2 +- .../const-arg-mismatched-literal-suffix.rs | 2 +- .../mgca/const-ctor-overflow-eval.rs | 2 +- .../mgca/const-ctor-with-error.rs | 2 +- tests/ui/const-generics/mgca/const-ctor.rs | 4 +- .../const-param-in-nested-inline-const-arg.rs | 2 +- .../mgca/cyclic-type-const-151251.rs | 2 +- .../mgca/double-inline-const.rs | 2 +- .../mgca/double-inline-const.stderr | 2 +- ...ed-path-not-accidentally-stabilized.stderr | 2 +- .../mgca/early-bound-param-lt-bad.rs | 2 +- .../mgca/early-bound-param-lt-bad.stderr | 2 +- .../mgca/explicit_anon_consts.rs | 2 +- .../mgca/explicit_anon_consts.stderr | 14 +++--- .../explicit_anon_consts_literals_hack.rs | 2 +- .../mgca/free-const-recursive.rs | 4 +- .../mgca/gca-macro-correct-rib.rs | 2 +- .../mgca/gca-macro-feature-gate.rs | 2 +- .../mgca/gca-macro-feature-gate.stderr | 6 +-- .../mgca/gca-macro-infer-as-type.rs | 2 +- .../mgca/gca-macro-multiple-exprs.rs | 2 +- ...eric-args-on-enum-variant-segments-fail.rs | 2 +- .../generic-args-on-enum-variant-segments.rs | 2 +- ...eneric_const_items-mismatched-array-len.rs | 2 +- ...onst_parameter_types-inferred-array-len.rs | 2 +- .../mgca/generic_const_type_mismatch.rs | 2 +- .../mgca/higher-ranked-lts-bad.rs | 2 +- .../mgca/higher-ranked-lts-good.rs | 2 +- .../infer-vars-in-const-args-conflicting.rs | 4 +- .../mgca/infer-vars-in-const-args-correct.rs | 4 +- .../mgca/inherent-alias-default.rs | 2 +- .../mgca/inherent-const-gating.rs | 2 +- .../mgca/invalid-array-in-tuple.rs | 4 +- .../invalid-gca-macro-owner-issue-159172.rs | 2 +- .../mgca/late-bound-param-lt-bad.rs | 2 +- .../mgca/macro-const-arg-infer.rs | 2 +- .../mgca/missing_generic_params.rs | 2 +- ...ixed-direct-anon-expression-diagnostics.rs | 2 +- ...-direct-anon-expression-diagnostics.stderr | 2 +- .../mgca/multi_braced_gca_macro.rs | 2 +- .../ui/const-generics/mgca/negated-literal.rs | 2 +- .../non-local-const-without-type_const.rs | 2 +- .../mgca/none-as-usize-const-arg.rs | 2 +- .../mgca/nonsensical-negated-literal.rs | 4 +- .../opaque-ty-assoc-const-equality-117923.rs | 2 +- tests/ui/const-generics/mgca/paren.rs | 2 +- .../printing_valtrees_supports_non_values.rs | 2 +- .../mgca/projection-const-recursive.rs | 2 +- .../const-generics/mgca/projection-error.rs | 2 +- ...solution-with-inherent-associated-types.rs | 2 +- .../mgca/selftyalias-containing-param.rs | 2 +- .../mgca/selftyalias-containing-param.stderr | 2 +- tests/ui/const-generics/mgca/selftyparam.rs | 2 +- .../ui/const-generics/mgca/selftyparam.stderr | 2 +- ...lized-direct-const-with-anon-const-body.rs | 2 +- .../mgca/size-of-generic-ptr-in-array-len.rs | 2 +- .../size-of-generic-ptr-in-array-len.stderr | 2 +- .../const-generics/mgca/static-const-arg.rs | 4 +- .../mgca/struct-ctor-in-array-len.rs | 4 +- .../mgca/struct_expr_with_macros.rs | 2 +- .../mgca/suggest-direct-const.fixed | 2 +- .../mgca/suggest-direct-const.rs | 2 +- .../mgca/syntactic-type-mismatch.rs | 2 +- .../mgca/synth-gen-arg-ice-158152.rs | 2 +- .../mgca/trait-assoc-fn-as-const-arg.rs | 2 +- .../mgca/tuple_ctor_arg_simple.rs | 2 +- .../mgca/tuple_ctor_complex_args.rs | 2 +- .../mgca/tuple_ctor_complex_args.stderr | 2 +- .../mgca/tuple_ctor_erroneous.rs | 2 +- .../mgca/tuple_ctor_in_array_len.rs | 2 +- .../const-generics/mgca/tuple_ctor_nested.rs | 2 +- .../mgca/tuple_ctor_type_relative.rs | 2 +- .../mgca/tuple_expr_arg_bad-issue-151048.rs | 2 +- .../mgca/tuple_expr_arg_complex.rs | 2 +- .../mgca/tuple_expr_arg_complex.stderr | 2 +- .../mgca/tuple_expr_arg_macroless.rs | 4 +- .../mgca/tuple_expr_arg_mismatch_type.rs | 2 +- .../mgca/tuple_expr_arg_simple.rs | 2 +- .../tuple_expr_arg_unbounded_assoc_const.rs | 2 +- .../mgca/tuple_expr_type_mismatch.rs | 4 +- .../type-const-assoc-const-without-body.rs | 2 +- .../mgca/type-const-associated-default.rs | 2 +- .../mgca/type-const-ctor-148953.rs | 2 +- .../type-const-free-anon-const-mismatch.rs | 2 +- .../type-const-free-value-type-mismatch.rs | 2 +- .../type-const-free-value-used-in-body.rs | 2 +- ...const-inherent-assoc-const-without-body.rs | 2 +- ...type-const-inherent-value-type-mismatch.rs | 2 +- .../mgca/type-const-suggestion.rs | 2 +- .../mgca/type-const-used-in-trait.rs | 2 +- .../mgca/type-const-value-type-mismatch.rs | 2 +- .../mgca/type_as_const_in_array_len.rs | 2 +- .../mgca/type_const-adt-expr-missing-field.rs | 4 +- .../mgca/type_const-array-return.rs | 2 +- .../mgca/type_const-generic-param-in-type.rs | 2 +- .../mgca/type_const-incemental-compile.rs | 2 +- .../type_const-inherent-const-omitted-type.rs | 2 +- .../type_const-mismatched-type-incremental.rs | 2 +- .../mgca/type_const-mismatched-types.rs | 2 +- .../mgca/type_const-not-constparamty.rs | 2 +- .../mgca/type_const-on-generic-expr.rs | 2 +- .../mgca/type_const-on-generic-expr.stderr | 4 +- .../mgca/type_const-on-generic_expr-2.rs | 2 +- .../mgca/type_const-on-generic_expr-2.stderr | 6 +-- .../type_const-only-in-impl-omitted-type.rs | 2 +- .../mgca/type_const-only-in-impl.rs | 2 +- .../mgca/type_const-only-in-trait.rs | 2 +- .../ui/const-generics/mgca/type_const-pub.rs | 2 +- .../mgca/type_const-recursive.rs | 2 +- .../ui/const-generics/mgca/type_const-use.rs | 2 +- .../mgca/type_const_in_pattern.rs | 2 +- .../mgca/type_const_in_pattern_too_generic.rs | 2 +- .../unbraced_const_block_const_arg_gated.rs | 2 +- ...nbraced_const_block_const_arg_gated.stderr | 14 +++--- .../mgca/unconstrained-type-params.rs | 2 +- .../mgca/unexpected-fn-item-in-array.rs | 2 +- .../mgca/unexpected-type-for-constructor.rs | 4 +- .../mgca/unmarked-free-const.rs | 2 +- .../mgca/unused_speculative_def_id.rs | 2 +- .../const-generics/mgca/valtree-leaf-const.rs | 6 +-- .../mgca/wrapped_array_elem_type_mismatch.rs | 2 +- .../mgca/wrong_type_const_arr_diag.rs | 2 +- .../mgca/wrong_type_const_arr_diag_trait.rs | 2 +- .../tuple_with_infer_arg.rs | 2 +- .../complex-expression.stderr | 14 +++--- .../forbid-non-static-lifetimes.stderr | 4 +- .../forbid-self-no-normalize.stderr | 2 +- .../self-ty-in-const-1.stderr | 4 +- .../self-ty-in-const-2.stderr | 2 +- ...r-lifetime-in-const-generic-default.stderr | 2 +- ...ams-in-ct-in-ty-param-lazy-norm.min.stderr | 2 +- tests/ui/const-generics/paren.stderr | 10 ++-- .../issue-89013-no-kw.stderr | 2 +- .../parser-error-recovery/issue-89013.stderr | 2 +- .../const-generics/renamed-feature-gates.rs | 21 +++++++++ .../renamed-feature-gates.stderr | 39 ++++++++++++++++ ...peat_expr_hack_gives_right_generics.stderr | 4 +- ...st_const_for_array.gca_const_items.stderr} | 0 ...onst_for_array.gca_min_const_items.stderr} | 0 .../const-generics/suggest_const_for_array.rs | 6 +-- .../type-const-ice-issue-151631.rs | 2 +- .../type-relative-path-144547.min.stderr | 2 +- .../type-relative-path-144547.rs | 2 +- tests/ui/consts/const-eval/size-of-t.stderr | 2 +- .../generics/const-type-ice-154334.rs | 2 +- .../hir-crate-items-before-lowering-ices.rs | 2 +- .../inside-const-body-ice-155300.rs | 2 +- .../ui/delegation/wrong-fn-kind-ice-159127.rs | 2 +- ...ture-gate-associated_const_equality.stderr | 2 +- ...rgs.rs => feature-gate-gca-const-items.rs} | 4 +- ...rr => feature-gate-gca-const-items.stderr} | 4 +- ....rs => feature-gate-gca-macroless-args.rs} | 0 ...=> feature-gate-gca-macroless-args.stderr} | 8 ++-- ...-gate-gca-macroless-items.macroful.stderr} | 2 +- ...rs => feature-gate-gca-macroless-items.rs} | 8 ++-- ...rs => feature-gate-gca-min-const-items.rs} | 2 +- ...> feature-gate-gca-min-const-items.stderr} | 16 +++---- .../feature-gate-mgca-type-const-syntax.rs | 4 +- ...feature-gate-mgca-type-const-syntax.stderr | 10 ++-- .../assoc-const-bindings.rs | 2 +- .../assoc-const-no-infer-ice-115806.rs | 2 +- .../type-const-nested-assoc-const.rs | 2 +- .../param-in-ct-in-ty-param-default.stderr | 2 +- .../issue-64173-unused-lifetimes.stderr | 4 +- .../no-name-for-DefPath-issue-133426.stderr | 2 +- .../object-lifetime-default-inherent-gac.rs | 4 +- .../parallel-rustc/fn-sig-cycle-ice-154056.rs | 2 +- .../recover-assoc-const-constraint.stderr | 4 +- tests/ui/resolve/issue-39559.stderr | 2 +- .../assoc-const-projection-issue-151878.rs | 2 +- .../overlap-due-to-unsatisfied-const-bound.rs | 2 +- tests/ui/supertrait-shadowing/assoc-const.rs | 2 +- .../supertrait-shadowing/common-ancestor-2.rs | 2 +- .../supertrait-shadowing/common-ancestor-3.rs | 2 +- .../supertrait-shadowing/common-ancestor.rs | 2 +- .../no-common-ancestor-2.rs | 2 +- .../no-common-ancestor.rs | 2 +- tests/ui/supertrait-shadowing/out-of-scope.rs | 2 +- .../ui/supertrait-shadowing/type-dependent.rs | 2 +- ...ault.rs => gca-min-const-items-default.rs} | 2 +- .../traits/final/final-on-assoc-type-const.rs | 2 +- .../dont-ice-on-assoc-projection.stderr | 2 +- .../next-solver/normalize-const-item-type.rs | 4 +- .../non_scalar_alignment_value.rs | 2 +- .../transmute-from-const-args-ice-150457.rs | 4 +- .../lack-of-wfcheck-gat-generic-const-args.rs | 2 +- .../lack-of-wfcheck-generic-const-args.rs | 4 +- .../recursive-lazy-type-alias-ice-152633.rs | 4 +- .../pattern_types/assoc_const.default.stderr | 8 ++-- ...struct-exprs-tuple-call-pretty-printing.rs | 2 +- ...ct-exprs-tuple-call-pretty-printing.stdout | 2 +- .../use/import_trait_associated_item_bad.rs | 2 +- 417 files changed, 734 insertions(+), 669 deletions(-) rename src/doc/unstable-book/src/language-features/{generic-const-args.md => gca-const-items.md} (75%) rename src/doc/unstable-book/src/language-features/{macroless-generic-const-args.md => gca-macroless-args.md} (56%) rename src/doc/unstable-book/src/language-features/{macroless-const-item-generic-const-args.md => gca-macroless-items.md} (52%) rename src/doc/unstable-book/src/language-features/{min-generic-const-args.md => gca-min-const-items.md} (85%) create mode 100644 tests/ui/const-generics/renamed-feature-gates.rs create mode 100644 tests/ui/const-generics/renamed-feature-gates.stderr rename tests/ui/const-generics/{suggest_const_for_array.generic_const_args.stderr => suggest_const_for_array.gca_const_items.stderr} (100%) rename tests/ui/const-generics/{suggest_const_for_array.min_generic_const_args.stderr => suggest_const_for_array.gca_min_const_items.stderr} (100%) rename tests/ui/feature-gates/{feature-gate-generic-const-args.rs => feature-gate-gca-const-items.rs} (63%) rename tests/ui/feature-gates/{feature-gate-generic-const-args.stderr => feature-gate-gca-const-items.stderr} (60%) rename tests/ui/feature-gates/{feature-gate-macroless-generic-const-args.rs => feature-gate-gca-macroless-args.rs} (100%) rename tests/ui/feature-gates/{feature-gate-macroless-generic-const-args.stderr => feature-gate-gca-macroless-args.stderr} (70%) rename tests/ui/feature-gates/{feature-gate-macroless_const_item_generic_const_args.macroful.stderr => feature-gate-gca-macroless-items.macroful.stderr} (84%) rename tests/ui/feature-gates/{feature-gate-macroless_const_item_generic_const_args.rs => feature-gate-gca-macroless-items.rs} (71%) rename tests/ui/feature-gates/{feature-gate-min-generic-const-args.rs => feature-gate-gca-min-const-items.rs} (83%) rename tests/ui/feature-gates/{feature-gate-min-generic-const-args.stderr => feature-gate-gca-min-const-items.stderr} (69%) rename tests/ui/traits/associated_type_bound/{generic-const-args-default.rs => gca-min-const-items-default.rs} (84%) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index 2f1a547e05a48..bd1db99c3766b 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -2402,7 +2402,7 @@ pub struct BorrowedFnSig<'a> { /// * the `G = Ty` in `Trait = Ty>` /// * the `A: Bound` in `Trait` /// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy` -/// * the `C = { Ct }` in `Trait` (feature `min_generic_const_args`) +/// * the `C = { Ct }` in `Trait` (feature `gca_min_const_items`) /// * the `f(..): Bound` in `Trait` (feature `return_type_notation`) #[derive(Clone, Encodable, Decodable, Debug, Walkable)] pub struct AssocItemConstraint { diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index d2748ad4632f1..b10279d71e566 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1403,7 +1403,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // type and value namespaces. If we resolved the path in the value namespace, we // transform it into a generic const argument. // - // Note that even under `#![feature(min_generic_const_args)]`, only plain paths + // Note that even under `#![feature(gca_min_const_items)]`, only plain paths // to constants are allowed - e.g. `A::` and // `A::>` are disallowed (they must be wrapped in `{ }`). // @@ -1420,7 +1420,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let ct = self.arena.alloc(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } - TyKind::GcaMacro(expr) if self.tcx.features().min_generic_const_args() => { + TyKind::GcaMacro(expr) if self.tcx.features().gca_min_const_items() => { let ct = match self.can_lower_expr_to_const_arg_direct( expr, DirectConstArgContext::MacrolessMinGenericConstArgs, @@ -2558,7 +2558,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // We cannot just match on `ExprKind::Underscore` as `(_)` is represented as // `ExprKind::Paren(ExprKind::Underscore)` and should also be lowered to `GenericArg::Infer` // - // FIXME(macroless_generic_const_args): Handling of underscores should be moved into + // FIXME(gca_macroless_args): Handling of underscores should be moved into // lower_expr_to_const_arg_direct. It is left here as retaining compatibility of what is // currently allowed on stable gets hairy and annoying otherwise. match c.value.peel_parens().kind { @@ -2632,7 +2632,7 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, ) -> hir::ConstItemRhs<'hir> { let is_direct = |body| { - if self.tcx.features().macroless_const_item_generic_const_args() { + if self.tcx.features().gca_macroless_items() { self.can_lower_expr_to_const_arg_direct( body, DirectConstArgContext::MacrolessMinGenericConstArgs, @@ -2645,7 +2645,7 @@ impl<'hir> LoweringContext<'_, 'hir> { matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. }) } }; - if self.tcx.features().min_generic_const_args() + if self.tcx.features().gca_min_const_items() && let Some(body) = body && is_direct(body) { @@ -2658,9 +2658,9 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn ambient_direct_const_arg_context(&self) -> DirectConstArgContext { - if self.tcx.features().macroless_generic_const_args() { + if self.tcx.features().gca_macroless_args() { DirectConstArgContext::MacrolessMinGenericConstArgs - } else if self.tcx.features().min_generic_const_args() { + } else if self.tcx.features().gca_min_const_items() { DirectConstArgContext::MinGenericConstArgs } else { DirectConstArgContext::Stable @@ -2965,7 +2965,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn lower_anon_const_to_const_arg(&mut self, anon: &AnonConst) -> hir::ConstArg<'hir> { // Stable only allows one nesting of blocks for directly represented paths. mGCA allows // arbitrarily many, and are handled inside lower_expr_to_const_arg_direct for consistency. - let expr = if self.tcx.features().macroless_generic_const_args() { + let expr = if self.tcx.features().gca_macroless_args() { &anon.value } else { anon.value.maybe_unwrap_block() diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index c1134e1dd7300..9d0ca67ce93d5 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -442,12 +442,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(final_associated_functions, "`final` on trait functions is experimental"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); gate_all!(frontmatter, "frontmatters are experimental"); + gate_all!(gca_min_const_items, "unbraced const blocks as const args are experimental"); gate_all!(gen_blocks, "gen blocks are experimental"); gate_all!(generic_const_items, "generic const items are experimental"); gate_all!(global_registration, "global registration is experimental"); gate_all!(guard_patterns, "guard patterns are experimental", "consider using match arm guards"); gate_all!(impl_restriction, "`impl` restrictions are experimental"); - gate_all!(min_generic_const_args, "unbraced const blocks as const args are experimental"); gate_all!(more_qualified_paths, "usage of qualified paths in this context is experimental"); gate_all!(move_expr, "`move(expr)` syntax is experimental"); gate_all!(mut_ref, "mutable by-reference bindings are experimental"); @@ -490,9 +490,9 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { "named parameters in parenthesized generic argument lists are experimental" ); - // `associated_const_equality` will be stabilized as part of `min_generic_const_args`. + // `associated_const_equality` will be stabilized as part of `gca_min_const_items`. for &span in spans.get(&sym::associated_const_equality).into_flat_iter() { - gate!(visitor, min_generic_const_args, span, "associated const equality is incomplete"); + gate!(visitor, gca_min_const_items, span, "associated const equality is incomplete"); } // Negative bounds are *super* internal. We require `-Zinternal-testing-features` *and* @@ -703,13 +703,13 @@ fn check_features_requiring_new_solver(sess: &Session, features: &Features) { if let Some(gca_span) = features .enabled_lang_features() .iter() - .find(|feat| feat.gate_name == sym::generic_const_args) + .find(|feat| feat.gate_name == sym::gca_const_items) .map(|feat| feat.attr_sp) { #[allow(rustc::symbol_intern_string_literal)] sess.dcx().emit_err(diagnostics::MissingDependentFeatures { parent_span: gca_span, - parent: sym::generic_const_args, + parent: sym::gca_const_items, missing: String::from("-Znext-solver=globally"), }); } diff --git a/compiler/rustc_attr_parsing/src/attributes/semantics.rs b/compiler/rustc_attr_parsing/src/attributes/semantics.rs index bc3fee8bc0ba3..6c4cd5ef667c8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/semantics.rs +++ b/compiler/rustc_attr_parsing/src/attributes/semantics.rs @@ -28,6 +28,6 @@ impl NoArgsAttributeParser for AlwaysGcaParser { const PATH: &[Symbol] = &[sym::rustc_always_gca]; const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::AssocConst(AssocCtxt::Trait))]); - const STABILITY: AttributeStability = unstable!(min_generic_const_args); + const STABILITY: AttributeStability = unstable!(gca_min_const_items); const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::AlwaysGca; } diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 403617f7bfa6f..5e89a060e3335 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -63,7 +63,7 @@ declare_features! ( (removed, allow_fail, "1.60.0", Some(46488), Some("removed due to no clear use cases"), 93416), /// Allows users to enforce equality of associated constants `TraitImpl`. (removed, associated_const_equality, "1.94.0", Some(92827), - Some("merged into `min_generic_const_args`")), + Some("merged into `gca_min_const_items`")), (removed, await_macro, "1.38.0", Some(50547), Some("subsumed by `.await` syntax"), 62293), /// Allows using `box` in patterns (RFC 469). @@ -167,6 +167,7 @@ declare_features! ( ), 133768 ), + (removed, generic_const_args, "CURRENT_RUSTC_VERSION", Some(151972), Some("renamed to `gca_const_items`")), (removed, import_shadowing, "1.0.0", None, None), /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (removed, in_band_lifetimes, "1.61.0", Some(44524), @@ -192,9 +193,12 @@ declare_features! ( which is available from cargo build scripts with `cargo:rustc-link-arg` now"), 83820), (removed, macro_reexport, "1.0.0", Some(29638), Some("subsumed by `pub use`"), 49982), + (removed, macroless_const_item_generic_const_args, "CURRENT_RUSTC_VERSION", Some(162540), Some("renamed to `gca_macroless_items`")), + (removed, macroless_generic_const_args, "CURRENT_RUSTC_VERSION", Some(159006), Some("renamed to `gca_macroless_args`")), /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. (removed, main, "1.53.0", Some(29634), None, 84217), (removed, managed_boxes, "1.0.0", None, None), + (removed, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980), Some("renamed to `gca_min_const_items`")), /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), Some("removed in favor of full type_alias_impl_trait"), 87564), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index a020ff315e470..49489c0ed903d 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -546,10 +546,18 @@ declare_features! ( (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. (unstable, frontmatter, "1.88.0", Some(136889)), + /// Allows using generics in more complex const expressions, based on definitional equality. + (incomplete, gca_const_items, "1.95.0", Some(151972)), + /// Allows directly represented gca_const_items without the `gca!` macro. + (incomplete, gca_macroless_args, "1.99.0", Some(159006)), + /// Allows directly represented gca_const_items as the rhs of const items without the + /// `gca!` macro. + (incomplete, gca_macroless_items, "CURRENT_RUSTC_VERSION", Some(162540)), + /// Enables the generic const args MVP (paths to type const items and constructors + /// for ADTs and primitives). + (incomplete, gca_min_const_items, "1.84.0", Some(132980)), /// Allows defining gen blocks and `gen fn`. (unstable, gen_blocks, "1.75.0", Some(117078)), - /// Allows using generics in more complex const expressions, based on definitional equality. - (incomplete, generic_const_args, "1.95.0", Some(151972)), /// Allows non-trivial generic constants which have to be shown to successfully evaluate /// to a value by being part of an item signature. (incomplete, generic_const_exprs, "1.56.0", Some(76560)), @@ -609,19 +617,11 @@ declare_features! ( (unstable, macro_metavar_expr, "1.61.0", Some(83527)), /// Provides a way to concatenate identifiers using metavariable expressions. (unstable, macro_metavar_expr_concat, "1.81.0", Some(124225)), - /// Allows directly represented generic_const_args as the rhs of const items without the - /// `gca!` macro. - (incomplete, macroless_const_item_generic_const_args, "CURRENT_RUSTC_VERSION", Some(162540)), - /// Allows directly represented generic_const_args without the `gca!` macro. - (incomplete, macroless_generic_const_args, "1.99.0", Some(159006)), /// Allows `#[marker]` on certain traits allowing overlapping implementations. (unstable, marker_trait_attr, "1.30.0", Some(29864)), /// Allows additional const parameter types, such as [u8; 10] or user defined types. /// User defined types must not have fields more private than the type itself. (unstable, min_adt_const_params, "1.96.0", Some(154042)), - /// Enables the generic const args MVP (paths to type const items and constructors - /// for ADTs and primitives). - (incomplete, min_generic_const_args, "1.84.0", Some(132980)), /// A minimal, sound subset of specialization intended to be used by the /// standard library until the soundness issues with specialization /// are fixed. @@ -859,8 +859,8 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ /// Some features require one or more other features to be enabled. pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ - (sym::generic_const_args, &[sym::min_generic_const_args]), - (sym::macroless_generic_const_args, &[sym::min_generic_const_args]), - (sym::macroless_const_item_generic_const_args, &[sym::min_generic_const_args]), + (sym::gca_const_items, &[sym::gca_min_const_items]), + (sym::gca_macroless_args, &[sym::gca_min_const_items]), + (sym::gca_macroless_items, &[sym::gca_min_const_items]), (sym::unsized_const_params, &[sym::adt_const_params]), ]; diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a613b992367e2..f55ab2a0ccbcc 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -3093,7 +3093,7 @@ pub enum ImplItemKind<'hir> { /// * the `G = Ty` in `Trait = Ty>` /// * the `A: Bound` in `Trait` /// * the `RetTy` in `Trait(ArgTy, ArgTy) -> RetTy` -/// * the `C = { Ct }` in `Trait` (feature `min_generic_const_args`) +/// * the `C = { Ct }` in `Trait` (feature `gca_min_const_items`) /// * the `f(..): Bound` in `Trait` (feature `return_type_notation`) #[derive(Debug, Clone, Copy, StableHash)] pub struct AssocItemConstraint<'hir> { diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index af380929c446e..204b6f913cb8b 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -2162,8 +2162,8 @@ pub(super) fn compare_const_directness<'tcx>( if trait_is_gca == impl_is_gca { return Ok(()); } - // feature(generic_const_args) is allowed to impl non-GCA traits with a GCA const - if tcx.features().generic_const_args() && !trait_is_gca && impl_is_gca { + // feature(gca_const_items) is allowed to impl non-GCA traits with a GCA const + if tcx.features().gca_const_items() && !trait_is_gca && impl_is_gca { return Ok(()); } diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0a1787a23c893..541ea012bb354 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -1289,7 +1289,7 @@ pub(super) fn check_const_item<'tcx>( tcx.require_lang_item(LangItem::ConstParamTy, span), ); } - // FIXME(min_generic_const_args): We *might* want to move this check to `type_of`, so we can + // FIXME(gca_min_const_items): We *might* want to move this check to `type_of`, so we can // return `ty::Error` if it references invalid params. However, doing so is hard, because // `type_of` doesn't know if it's a direct const - `const_of_item` determines that, and // `const_of_item` calls `type_of`. diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8f693221b0fd2..c3cc3bcd6cd0c 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1803,7 +1803,7 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin debug_assert_matches!(const_arg.kind, hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) if *def_id == def); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().min_generic_const_args() { + } else if tcx.features().gca_min_const_items() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index ee4e7471ee434..9605c777e55a9 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -224,7 +224,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Node::AnonConst, or whether it will be represented directly, so it must generate a // DefId. If it ends up being direct, this DefId is then attached to the top-level // ConstArg, which is what we are seeing here. - debug_assert!(tcx.features().min_generic_const_args()); + debug_assert!(tcx.features().gca_min_const_items()); // Forward to the real parent. Some(tcx.local_parent(def_id)) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs index 4bfe93f5949f7..0b7df89551da8 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/bounds.rs @@ -558,9 +558,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { if let ty::AssocTag::Const = assoc_tag && !self.tcx().is_direct_const(assoc_item.def_id) - && !tcx.features().generic_const_args() + && !tcx.features().gca_const_items() { - if tcx.features().min_generic_const_args() { + if tcx.features().gca_min_const_items() { let err = self.dcx().struct_span_err( constraint.span, "use of trait associated const not defined as `#[rustc_always_gca]`", diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index f2cf4743d76b6..bee062b27e0f5 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && let Some(hir_ty) = constraint.ty() && let ty = self.lower_ty(hir_ty) && (ty.is_enum() || ty.references_error()) - && tcx.features().min_generic_const_args() + && tcx.features().gca_min_const_items() { Some(diagnostics::AssocKindMismatchWrapInBracesSugg { lo: hir_ty.span.shrink_to_lo(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 36b5f6c268e74..e9dc2a61d698d 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -419,7 +419,7 @@ impl<'tcx> ForbidParamUsesFolder<'tcx> { "generic `Self` types are currently not permitted in anonymous constants" } ForbidParamContext::ConstArgument => { - if self.tcx.features().generic_const_args() { + if self.tcx.features().gca_const_items() { "generic parameters in const blocks are not allowed; use a named `const` item instead" } else { "generic parameters may not be used in const operations" @@ -442,15 +442,15 @@ impl<'tcx> ForbidParamUsesFolder<'tcx> { } } if matches!(self.context, ForbidParamContext::ConstArgument) { - if self.tcx.features().generic_const_args() { + if self.tcx.features().gca_const_items() { diag.help("consider factoring the expression into a `type const` item and use it as the const argument instead"); - } else if self.tcx.features().min_generic_const_args() { - diag.help("add `#![feature(generic_const_args)]` and extract the expression into a `type const` item"); + } else if self.tcx.features().gca_min_const_items() { + diag.help("add `#![feature(gca_const_items)]` and extract the expression into a `type const` item"); } else if self.tcx.sess.is_nightly_build() { diag.help( "add `#![feature(generic_const_exprs)]` to allow generic const expressions", ); - diag.help("alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item"); + diag.help("alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item"); } } diag.emit_err() @@ -3127,7 +3127,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { span: Span, ) -> Result<(), ErrorGuaranteed> { let tcx = self.tcx(); - if tcx.features().generic_const_args() || alias_const.is_direct_const(tcx) { + if tcx.features().gca_const_items() || alias_const.is_direct_const(tcx) { Ok(()) } else { let mut err = self diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index 925fc8d06e326..ddaf12f9812aa 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -289,7 +289,7 @@ rustc_queries! { /// Returns the const of the RHS of a (free or assoc) const item, if it is a `type const`, or if /// it is a directly represented `const` (i.e. a const with a `gca!` RHS, or a const that - /// `feature(macroless_generic_const_args)` has decided is direct). + /// `feature(gca_macroless_args)` has decided is direct). /// /// When a const item is used in a type-level expression, like in equality for an assoc const /// projection, this allows us to retrieve the typesystem-appropriate representation of the diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5520b059f5678..d97fede2b6eb8 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -993,7 +993,7 @@ pub enum MethodViolation { /// Reasons an associated const might not be dyn compatible. #[derive(Clone, Debug, PartialEq, Eq, Hash, StableHash)] pub enum AssocConstViolation { - /// Unstable feature `min_generic_const_args` wasn't enabled. + /// Unstable feature `gca_min_const_items` wasn't enabled. FeatureNotEnabled, /// Not defined as a type-level associated const. diff --git a/compiler/rustc_middle/src/ty/assoc.rs b/compiler/rustc_middle/src/ty/assoc.rs index a3ccbc7742df4..e52d74f4c23fe 100644 --- a/compiler/rustc_middle/src/ty/assoc.rs +++ b/compiler/rustc_middle/src/ty/assoc.rs @@ -143,7 +143,7 @@ impl AssocItem { match self.kind { ty::AssocKind::Type { .. } => true, ty::AssocKind::Const { .. } => { - tcx.features().generic_const_args() || tcx.is_direct_const(self.def_id) + tcx.features().gca_const_items() || tcx.is_direct_const(self.def_id) } ty::AssocKind::Fn { .. } => false, } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9edb12949f4cf..b4104d997137f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -110,8 +110,8 @@ impl<'tcx> rustc_type_ir::inherent::Features> for &'tcx rustc_featu self.generic_const_exprs() } - fn generic_const_args(self) -> bool { - self.generic_const_args() + fn gca_const_items(self) -> bool { + self.gca_const_items() } fn coroutine_clone(self) -> bool { @@ -1030,7 +1030,7 @@ impl<'tcx> TyCtxt<'tcx> { /// because it has a directly represented RHS, or is a trait definition that is marked as /// requiring its implementation to have a directly represented RHS. /// - /// Note: Be very careful with using this method - under `generic_const_args`, a trait can + /// Note: Be very careful with using this method - under `gca_const_items`, a trait can /// declare a regular const, but an `impl` could implement it with a directly represented const /// (a la refinement). This method would return false in such a case. pub fn is_direct_const(self, def_id: DefId) -> bool { diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 43936770ff762..854cd37ae61d3 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -94,13 +94,13 @@ pub(crate) fn as_constant_inner<'tcx>( if tcx.is_direct_const(def_id) { return Some(get_kind(def_id, def_kind)); } - // Under generic_const_args, `def_id` might be a regular const declared in a trait, + // Under gca_const_items, `def_id` might be a regular const declared in a trait, // but is `impl`d as a directly represented const. We do not know whether it is // here, so we must use type system normalization for all const projections. - // FIXME(generic_const_args): there's a lot to consider here! `Const::Ty` uses + // FIXME(gca_const_items): there's a lot to consider here! `Const::Ty` uses // valtrees and `Const::Unevaluated` does not, we should revisit this before // stabilization. - if tcx.features().generic_const_args() + if tcx.features().gca_const_items() && let kind @ ty::AliasConstKind::Projection { .. } = get_kind(def_id, def_kind) { return Some(kind); diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 3aec71f400de3..0a040b7e7a756 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -136,16 +136,16 @@ impl<'tcx> ConstToPat<'tcx> { return self.mk_err(err, ty); }; - // Under generic_const_args, `alias_const` might be a regular const declared in a trait, but + // Under gca_const_items, `alias_const` might be a regular const declared in a trait, but // is `impl`d as a directly represented const. We do not know whether it is here, so we must - // use type system normalization for all consts under generic_const_args. + // use type system normalization for all consts under gca_const_items. // // We probably want to always use type system normalization on stable too, but that would be // a breaking change (in addition to needing significant improvements to diagnostics), so - // right now, we limit this to just generic_const_args. + // right now, we limit this to just gca_const_items. // // See: https://github.com/rust-lang/project-const-generics/issues/105 - let const_value = if self.tcx.features().generic_const_args() + let const_value = if self.tcx.features().gca_const_items() || alias_const.kind.is_direct_const(self.tcx) { let Ok(normalize) = self diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 7397d43a48a00..c87539a6941cb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1434,7 +1434,7 @@ where self.eq(param_env, expected_term, evaluated.into())?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } - None if self.cx().features().generic_const_args() => { + None if self.cx().features().gca_const_items() => { // HACK(khyperia): calling `deeply_resolve_ignoring_regions` here shouldn't be necessary, // `try_evaluate_const` calls `deeply_resolve_ignoring_regions` already. However, we want // to check `has_non_region_infer` against the type with vars resolved (i.e. check diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 0ac12d6f392b2..615d1bb221cc9 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -859,7 +859,7 @@ impl<'a> Parser<'a> { true } ast::ExprKind::ConstBlock(_) => { - self.psess.gated_spans.gate(sym::min_generic_const_args, expr.span); + self.psess.gated_spans.gate(sym::gca_min_const_items, expr.span); true } _ => false, diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 331c948c66403..2ea2f52c696ba 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1333,7 +1333,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { name, param_kind: is_type, help: self.tcx.sess.is_nightly_build() - && !self.tcx.features().min_generic_const_args(), + && !self.tcx.features().gca_min_const_items(), is_gca, help_gca: is_gca, help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index d17e01425d2c9..d85024603ad33 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -429,7 +429,7 @@ pub(crate) struct ParamInNonTrivialAnonConst { )] pub(crate) help_gca: bool, #[help( - "alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item" + "alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item" )] pub(crate) help_suggest_gca: bool, } diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 9faedfeac571b..d743093aae92f 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1658,7 +1658,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.generic_const_args(), + is_gca: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1750,7 +1750,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.generic_const_args(), + is_gca: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 70e1a6f93eba1..e1787eadf5fb9 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5232,7 +5232,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() - || self.r.features.min_generic_const_args() + || self.r.features.gca_min_const_items() || is_trivial_const_arg { ConstantHasGenerics::Yes diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3dbb1b7fff662..84c07d0fb0f44 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4164,11 +4164,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, help: self.r.tcx.sess.is_nightly_build() - && !self.r.features.min_generic_const_args(), - is_gca: self.r.features.generic_const_args(), - help_gca: self.r.features.generic_const_args(), + && !self.r.features.gca_min_const_items(), + is_gca: self.r.features.gca_const_items(), + help_gca: self.r.features.gca_const_items(), help_suggest_gca: self.r.tcx.sess.is_nightly_build() - && !self.r.features.generic_const_args(), + && !self.r.features.gca_const_items(), }) } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index b490362a34ee4..e62ad42875248 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1067,6 +1067,10 @@ symbols! { future_trait, fxsr, gca, + gca_const_items, + gca_macroless_args, + gca_macroless_items, + gca_min_const_items, gdb_script_file, ge, gen_blocks, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 062b087413e4f..63b0733b0a095 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3984,8 +3984,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, span: Span, ) -> Result, ErrorGuaranteed> { - if !self.tcx.features().generic_const_exprs() - && !self.tcx.features().min_generic_const_args() + if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca_min_const_items() { let guar = self .dcx() diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 9bcbf393dd05b..9acc0682e6641 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -84,7 +84,7 @@ pub fn is_const_evaluatable<'tcx>( } _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), } - } else if tcx.features().min_generic_const_args() { + } else if tcx.features().gca_min_const_items() { // This is a sanity check to make sure that non-generics consts are checked to // be evaluatable in case they aren't cchecked elsewhere. This will NOT error // if the const uses generics, as desired. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index 59f3ebfcce33e..c598e0ef8a8bd 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -368,10 +368,10 @@ pub fn dyn_compatibility_violations_for_assoc_item( let mut errors = Vec::new(); - if tcx.features().min_generic_const_args() { + if tcx.features().gca_min_const_items() { if !tcx.generics_of(item.def_id).is_own_empty() { errors.push(AssocConstViolation::Generic); - } else if !tcx.is_always_gca(item.def_id) && !tcx.features().generic_const_args() { + } else if !tcx.is_always_gca(item.def_id) && !tcx.features().gca_const_items() { errors.push(AssocConstViolation::NonType); } @@ -790,7 +790,7 @@ enum AllowSelfProjections { /// associated type of the current trait, since we retain the value of those associated /// types in the trait object type itself. /// -/// The same thing holds for associated consts under feature `min_generic_const_args`. +/// The same thing holds for associated consts under feature `gca_min_const_items`. /// /// ```rust,ignore (example) /// trait SuperTrait { @@ -914,7 +914,7 @@ impl<'tcx> TypeVisitor> for IllegalSelfTypeVisitor<'tcx> { ty::ConstKind::Alias( _, ty::AliasConst { kind: ty::AliasConstKind::Projection { def_id }, args, .. }, - ) if self.tcx.features().min_generic_const_args() => { + ) if self.tcx.features().gca_min_const_items() => { match self.allow_self_projections { AllowSelfProjections::Yes => { let trait_def_id = self.tcx.parent(def_id); diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index c220b35dd5f7d..5a66fafd57361 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -479,7 +479,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx }; // Note that the Projection/Inherent/Free cases are unreachable on stable, - // unless a `min_generic_const_args` feature gate error has already + // unless a `gca_min_const_items` feature gate error has already // been emitted earlier in compilation. // // That's because we can only end up with an Alias ty::Const for a const item diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 7ee6eec3e1c44..2d79a738c76c2 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -1209,7 +1209,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // terms of `Fn` etc, but we could probably make this more // precise still. // - // FIXME(min_generic_const_args): Consider consts as well? + // FIXME(gca_min_const_items): Consider consts as well? let unbound_input_types = stack.fresh_trait_pred.skip_binder().trait_ref.args.types().any(|ty| ty.is_fresh()); diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index ba33270c2adba..955ab1799a794 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1090,9 +1090,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { ty::ConstKind::Alias(_, alias_const) => { if !c.has_escaping_bound_vars() { // Skip type consts as mGCA doesn't support evaluatable clauses - if !alias_const.kind.is_direct_const(tcx) - && !tcx.features().generic_const_args() - { + if !alias_const.kind.is_direct_const(tcx) && !tcx.features().gca_const_items() { let predicate = ty::Binder::dummy(ty::PredicateKind::Clause( ty::ClauseKind::ConstEvaluatable(c), )); @@ -1171,7 +1169,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::ConstKind::Value(val) => { // FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased - if tcx.features().min_generic_const_args() { + if tcx.features().gca_min_const_items() { match val.ty.kind() { ty::Adt(adt_def, args) => { let adt_val = val.destructure_adt_const(); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index f66322e034814..d969cca3dcda2 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -281,7 +281,7 @@ pub enum AnonConstKind { GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters /// - /// under `feature(min_generic_const_args)`, these may be inline consts as well, and should be + /// under `feature(gca_min_const_items)`, these may be inline consts as well, and should be /// treated the same as anon consts. MCG, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 26d094817ba09..28b733a865358 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -590,7 +590,7 @@ pub trait ParamEnv: Copy + Debug + Hash + Eq + TypeFoldable { pub trait Features: Copy { fn generic_const_exprs(self) -> bool; - fn generic_const_args(self) -> bool; + fn gca_const_items(self) -> bool; fn coroutine_clone(self) -> bool; diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index e67c7114d6d6a..514c2aa1c9bd1 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1080,7 +1080,7 @@ pub trait Tuple {} /// const FOO: usize = gca!(BAR::); /// ``` #[rustc_builtin_macro(gca)] -#[unstable(feature = "min_generic_const_args", issue = "132980")] +#[unstable(feature = "gca_min_const_items", issue = "132980")] #[macro_export] macro_rules! gca { ($($arg:tt)*) => { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index d59d204d6e144..bfb28b62d2089 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -759,7 +759,7 @@ pub use core::concat_bytes; )] #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; -#[unstable(feature = "min_generic_const_args", issue = "132980")] +#[unstable(feature = "gca_min_const_items", issue = "132980")] pub use core::gca; #[stable(feature = "matches_macro", since = "1.42.0")] pub use core::matches; diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 9e26a174d8cf6..74e78aab145a1 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -81,7 +81,7 @@ type Alias = [u8; ANON]; When we go through HIR ty lowering for the array type in `Alias`, we will lower the array length too, and feed `type_of(ANON) -> usize`. This will effectively set the type of the `ANON` const item during some later part of the compiler rather than when constructing the HIR. -After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Unevaluated` with the `DefId` of the `AnonConst`. This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `min_generic_const_args` is enabled). +After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Unevaluated` with the `DefId` of the `AnonConst`. This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `gca_min_const_items` is enabled). This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. @@ -141,7 +141,7 @@ In some sense we only allow generic parameters here when they are semantically u In the previous example the anon const can be evaluated for any type parameter `T` because raw pointers to sized types always have the same size (e.g. `8` on 64bit platforms). When detecting that we evaluated an anon const that syntactically contained generic parameters, but did not actually depend on them for evaluation to succeed, we emit the [`const_evaluatable_unchecked` FCW][cec_fcw]. -This is intended to become a hard error once we stabilize more ways of using generic parameters in const arguments, for example `min_generic_const_args` or (the now dead) `generic_const_exprs`. +This is intended to become a hard error once we stabilize more ways of using generic parameters in const arguments, for example `gca_min_const_items` or (the now dead) `generic_const_exprs`. The implementation for this FCW can be found here: [`const_eval_resolve_for_typeck`] @@ -182,7 +182,7 @@ It is currently unclear what the right way to make `generic_const_parameter_type `generic_const_exprs` would have allowed for anon consts with types referencing generic parameters, but that design wound up unworkable. -`min_generic_const_args` will allow for some expressions (for example array construction) to be representable without an anon const and therefore without running into these issues, though whether this is *enough* has yet to be determined. +`gca_min_const_items` will allow for some expressions (for example array construction) to be representable without an anon const and therefore without running into these issues, though whether this is *enough* has yet to be determined. ## Checking types of const arguments diff --git a/src/doc/rustc-dev-guide/src/normalization.md b/src/doc/rustc-dev-guide/src/normalization.md index 05484a672aaf3..cefd92999d9e5 100644 --- a/src/doc/rustc-dev-guide/src/normalization.md +++ b/src/doc/rustc-dev-guide/src/normalization.md @@ -155,7 +155,7 @@ fn bar() { ``` This is likely to change as const generics functionality is improved. -For example, `feature(associated_const_equality)` and `feature(min_generic_const_args)` both require handling const aliases similarly to types (without an anonymous constant wrapping all const args). +For example, `feature(associated_const_equality)` and `feature(gca_min_const_items)` both require handling const aliases similarly to types (without an anonymous constant wrapping all const args). ## What is normalization diff --git a/src/doc/unstable-book/src/language-features/generic-const-args.md b/src/doc/unstable-book/src/language-features/gca-const-items.md similarity index 75% rename from src/doc/unstable-book/src/language-features/generic-const-args.md rename to src/doc/unstable-book/src/language-features/gca-const-items.md index c496c50bf0400..e773f3bdec03d 100644 --- a/src/doc/unstable-book/src/language-features/generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/gca-const-items.md @@ -1,4 +1,4 @@ -# generic_const_args +# gca_const_items Allows using generics in more complex const expressions, based on definitional equality. @@ -11,23 +11,23 @@ The tracking issue for this feature is: [#151972] Warning: This feature is incomplete; its design and syntax may change. This feature enables many of the same use cases supported by [generic_const_exprs], -but based on the machinery developed for [min_generic_const_args]. In a way, it is +but based on the machinery developed for [gca_min_const_items]. In a way, it is meant to be an interim successor for GCE (though it might not currently support all the valid cases that supported by GCE). See also: [generic_const_items] -[min_generic_const_args]: min-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md [generic_const_exprs]: generic-const-exprs.md [generic_const_items]: generic-const-items.md ## Examples - + ```rust,ignore (requires-Z-next-solver) #![feature(generic_const_items)] -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] #![expect(incomplete_features)] type const ADD1: usize = const { N + 1 }; diff --git a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md b/src/doc/unstable-book/src/language-features/gca-macroless-args.md similarity index 56% rename from src/doc/unstable-book/src/language-features/macroless-generic-const-args.md rename to src/doc/unstable-book/src/language-features/gca-macroless-args.md index fadc2260bfbdc..d81b202d9dd3c 100644 --- a/src/doc/unstable-book/src/language-features/macroless-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/gca-macroless-args.md @@ -1,6 +1,6 @@ -# macroless_generic_const_args +# gca_macroless_args -Enables using `#![feature(min_generic_const_args)]` without the `gca!` macro. +Enables using `#![feature(gca_min_const_items)]` without the `gca!` macro. The tracking issue for this feature is: [#159006] @@ -11,23 +11,23 @@ The tracking issue for this feature is: [#159006] Warning: This feature is incomplete; its design and syntax may change. Related features: -- [min_generic_const_args]. See that doc for what the `gca!` is. This feature enables +- [gca_min_const_items]. See that doc for what the `gca!` is. This feature enables support for directly represented const arguments without the macro. -- [macroless_const_item_generic_const_args]. For a version of this feature that works for const arguments +- [gca_macroless_items]. For a version of this feature that works for const arguments as the right hand side of a const item. -[min_generic_const_args]: min-generic-const-args.md -[macroless_const_item_generic_const_args]: macroless-const-item-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md +[gca_macroless_items]: gca-macroless-items.md ## Examples -Here is an example from [min_generic_const_args]: +Here is an example from [gca_min_const_items]: -[min_generic_const_args]: min-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md ```rust #![allow(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Bar { #[rustc_always_gca] @@ -49,11 +49,11 @@ struct Foo { } ``` -Using `#![feature(macroless_generic_const_args)]` enables you to write the above without the macro: +Using `#![feature(gca_macroless_args)]` enables you to write the above without the macro: ```rust #![allow(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] trait Bar { #[rustc_always_gca] @@ -65,7 +65,7 @@ trait Bar { struct Baz; impl Bar for Baz { - // note these still need a macro, macroless for these is `macroless_const_item_generic_const_args` + // note these still need a macro, macroless for these is `gca_macroless_items` const VAL: usize = core::gca!(2); const VAL2: usize = core::gca!(const { Self::VAL * 2 }); } diff --git a/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md b/src/doc/unstable-book/src/language-features/gca-macroless-items.md similarity index 52% rename from src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md rename to src/doc/unstable-book/src/language-features/gca-macroless-items.md index feb03a633d1bd..d683adc0b1349 100644 --- a/src/doc/unstable-book/src/language-features/macroless-const-item-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/gca-macroless-items.md @@ -1,6 +1,6 @@ -# macroless_generic_const_args +# gca_macroless_args -Enables implementing const items under `#![feature(min_generic_const_args)]` and `#![feature(generic_const_args)]` without the `gca!` macro. +Enables implementing const items under `#![feature(gca_min_const_items)]` and `#![feature(gca_const_items)]` without the `gca!` macro. The tracking issue for this feature is: [#162540] @@ -11,26 +11,26 @@ The tracking issue for this feature is: [#162540] Warning: This feature is incomplete; its design and syntax may change. Related features: -- [min_generic_const_args]. See that doc for what the `gca!` is. This feature enables +- [gca_min_const_items]. See that doc for what the `gca!` is. This feature enables support for directly represented const arguments as the rhs of const items without the macro. -- [macroless_generic_const_args]. For a version of this feature that works for const arguments in other +- [gca_macroless_args]. For a version of this feature that works for const arguments in other positions -[min_generic_const_args]: min-generic-const-args.md -[macroless_generic_const_args]: macroless-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md +[gca_macroless_args]: gca-macroless-args.md ## Examples -Here is an example from [min_generic_const_args]: +Here is an example from [gca_min_const_items]: -[min_generic_const_args]: min-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md ```rust,ignore (needs new solver) #![allow(incomplete_features)] #![feature( - min_generic_const_args, - generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_const_items, + gca_macroless_args, generic_const_items, )] @@ -48,15 +48,15 @@ fn foo() { } ``` -Using `#![feature(macroless_const_item_generic_const_args)]` enables you to write the above without the macro: +Using `#![feature(gca_macroless_items)]` enables you to write the above without the macro: ```rust,ignore (needs new solver) #![allow(incomplete_features)] #![feature( - min_generic_const_args, - generic_const_args, - macroless_generic_const_args, - macroless_const_item_generic_const_args, + gca_min_const_items, + gca_const_items, + gca_macroless_args, + gca_macroless_items, generic_const_items, )] diff --git a/src/doc/unstable-book/src/language-features/min-generic-const-args.md b/src/doc/unstable-book/src/language-features/gca-min-const-items.md similarity index 85% rename from src/doc/unstable-book/src/language-features/min-generic-const-args.md rename to src/doc/unstable-book/src/language-features/gca-min-const-items.md index 920bc0e36c1ba..4027e782714ed 100644 --- a/src/doc/unstable-book/src/language-features/min-generic-const-args.md +++ b/src/doc/unstable-book/src/language-features/gca-min-const-items.md @@ -1,4 +1,4 @@ -# min_generic_const_args +# gca_min_const_items Enables the generic const args MVP (paths to direct const items and constructors for ADTs and primitives). @@ -15,12 +15,12 @@ and uses a different approach for implementation. It is intentionally more restr cases that make the `generic_const_exprs` hard to implement properly. See [Feature background][feature_background] for more details. -Related features: [macroless_generic_const_args], [generic_const_args], [generic_const_items]. +Related features: [gca_macroless_args], [gca_const_items], [generic_const_items]. [feature_background]: https://github.com/rust-lang/project-const-generics/blob/main/documents/min_const_generics_plan.md [generic_const_exprs]: generic-const-exprs.md -[macroless_generic_const_args]: macroless-generic-const-args.md -[generic_const_args]: generic-const-args.md +[gca_macroless_args]: gca-macroless-args.md +[gca_const_items]: gca-const-items.md [generic_const_items]: generic-const-items.md ## `gca!` macro @@ -34,9 +34,9 @@ expression "directly", i.e. without an anon const, in a way that is visible to t (Note that plain paths to generic parameters are always represented directly, without `gca!`, as this already works on stable) -See [macroless_generic_const_args] as a feature to disable the requirement of writing `gca!`. +See [gca_macroless_args] as a feature to disable the requirement of writing `gca!`. -[macroless_generic_const_args]: macroless-generic-const-args.md +[gca_macroless_args]: gca-macroless-args.md ## direct const items @@ -45,7 +45,7 @@ Constants with a direct right-hand side are allowed to be used in type contexts, ```compile_fail #![allow(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] const X: usize = core::gca!(1); const Y: usize = 1; @@ -60,7 +60,7 @@ struct Foo { ```rust #![allow(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Bar { #[rustc_always_gca] @@ -114,7 +114,7 @@ Use of const functions is allowed: ```rust #![allow(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] const VAL: usize = 1; diff --git a/src/doc/unstable-book/src/language-features/generic-const-exprs.md b/src/doc/unstable-book/src/language-features/generic-const-exprs.md index 2085ed8fed0cc..645a2df3ebad4 100644 --- a/src/doc/unstable-book/src/language-features/generic-const-exprs.md +++ b/src/doc/unstable-book/src/language-features/generic-const-exprs.md @@ -12,10 +12,10 @@ The tracking issue for this feature is: [#76560] Warning: This feature is incomplete; its design and syntax may change. -See also: [min_generic_const_args], [generic_const_args] +See also: [gca_min_const_items], [gca_const_items] -[min_generic_const_args]: min-generic-const-args.md -[generic_const_args]: generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md +[gca_const_items]: gca-const-items.md ## Examples diff --git a/src/doc/unstable-book/src/language-features/generic-const-items.md b/src/doc/unstable-book/src/language-features/generic-const-items.md index c856c9f135aff..ddf8f445ae859 100644 --- a/src/doc/unstable-book/src/language-features/generic-const-items.md +++ b/src/doc/unstable-book/src/language-features/generic-const-items.md @@ -11,11 +11,11 @@ The tracking issue for this feature is: [#113521] Warning: This feature is an [experiment] and lacks an RFC. There are no guarantees that it will ever be stabilized. -See also: [generic_const_exprs], [min_generic_const_args]. +See also: [generic_const_exprs], [gca_min_const_items]. [experiment]: https://lang-team.rust-lang.org/how_to/experiment.html [generic_const_exprs]: generic-const-exprs.md -[min_generic_const_args]: min-generic-const-args.md +[gca_min_const_items]: gca-min-const-items.md ## Examples diff --git a/src/tools/clippy/CHANGELOG.md b/src/tools/clippy/CHANGELOG.md index 37f5eb09e5247..e79efa20fd534 100644 --- a/src/tools/clippy/CHANGELOG.md +++ b/src/tools/clippy/CHANGELOG.md @@ -318,7 +318,7 @@ Current stable, released 2026-05-28 [#16685](https://github.com/rust-lang/rust-clippy/pull/16685) * [`nonminimal_bool`] fix ICE in `swap_binop()` by using the proper `TypeckResults` [#16659](https://github.com/rust-lang/rust-clippy/pull/16659) -* Fix ICE when using the `min_generic_const_args` incomplete feature +* Fix ICE when using the `gca_min_const_items` incomplete feature [#16692](https://github.com/rust-lang/rust-clippy/pull/16692) ### Documentation Improvements diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 890fc7cb4e947..a9d269ac83271 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -871,7 +871,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { { did }, - // TODO: revisit when feature `min_generic_const_args` is stabilized. In the meantime, + // TODO: revisit when feature `gca_min_const_items` is stabilized. In the meantime, // `TyCtxt::const_eval_resolve()` will trigger an ICE when evaluating the body of the // `type const` definition. _ if let Res::Def(DefKind::Const | DefKind::AssocConst, did) = self.typeck.qpath_res(qpath, id) diff --git a/src/tools/clippy/tests/ui/crashes/mgca-16691.rs b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs index 554528905fc85..4da9a8b60d1a3 100644 --- a/src/tools/clippy/tests/ui/crashes/mgca-16691.rs +++ b/src/tools/clippy/tests/ui/crashes/mgca-16691.rs @@ -1,6 +1,6 @@ //@ check-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed index dc1d663a9393b..d887aac9c0378 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait AssocConstTrait { #[rustc_always_gca] diff --git a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs index 669e0fbdd3809..feeec8e421f1d 100644 --- a/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs +++ b/src/tools/clippy/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait AssocConstTrait { #[rustc_always_gca] diff --git a/src/tools/rustfmt/tests/source/gca.rs b/src/tools/rustfmt/tests/source/gca.rs index ab394c21b8b32..0c63def96916f 100644 --- a/src/tools/rustfmt/tests/source/gca.rs +++ b/src/tools/rustfmt/tests/source/gca.rs @@ -1,8 +1,8 @@ -// gca! is a built-in macro relevant to min_generic_const_args; its contents should be formatted as +// gca! is a built-in macro relevant to gca_min_const_items; its contents should be formatted as // if its contents were passed through unchanged (the macro changes the semantics of the contained // expression, the syntax is unchanged) -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/src/tools/rustfmt/tests/target/gca.rs b/src/tools/rustfmt/tests/target/gca.rs index 8110bb0d2c827..db8936ed64c43 100644 --- a/src/tools/rustfmt/tests/target/gca.rs +++ b/src/tools/rustfmt/tests/target/gca.rs @@ -1,8 +1,8 @@ -// gca! is a built-in macro relevant to min_generic_const_args; its contents should be formatted as +// gca! is a built-in macro relevant to gca_min_const_items; its contents should be formatted as // if its contents were passed through unchanged (the macro changes the semantics of the contained // expression, the syntax is unchanged) -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/crashes/138009.rs b/tests/crashes/138009.rs index 494e3fb827ddb..9b44b6148eab5 100644 --- a/tests/crashes/138009.rs +++ b/tests/crashes/138009.rs @@ -1,5 +1,5 @@ //@ known-bug: #138009 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/crashes/149809.rs b/tests/crashes/149809.rs index b1172b72b17cd..0b8f6338734d3 100644 --- a/tests/crashes/149809.rs +++ b/tests/crashes/149809.rs @@ -1,5 +1,5 @@ //@ known-bug: #149809 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(inherent_associated_types)] use std::gca; diff --git a/tests/crashes/150049.rs b/tests/crashes/150049.rs index 994e257a28d59..23cb868c8099a 100644 --- a/tests/crashes/150049.rs +++ b/tests/crashes/150049.rs @@ -1,5 +1,5 @@ //@ known-bug: #150049 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(inherent_associated_types)] use std::gca; diff --git a/tests/crashes/150749.rs b/tests/crashes/150749.rs index 8e4e413236c82..fa13c49ef564a 100644 --- a/tests/crashes/150749.rs +++ b/tests/crashes/150749.rs @@ -1,5 +1,5 @@ //@ known-bug: #150749 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/debuginfo/associated-const-bindings.rs b/tests/debuginfo/associated-const-bindings.rs index 171d457925522..ca0693d4e389f 100644 --- a/tests/debuginfo/associated-const-bindings.rs +++ b/tests/debuginfo/associated-const-bindings.rs @@ -10,7 +10,7 @@ //@ cdb-command:dv /t /n local //@ cdb-check:struct ref$ > > > local = [...] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(unused_variables, incomplete_features)] use std::gca; diff --git a/tests/pretty/gca-macro.pp b/tests/pretty/gca-macro.pp index 8912d790b337a..271b92b0e319e 100644 --- a/tests/pretty/gca-macro.pp +++ b/tests/pretty/gca-macro.pp @@ -2,7 +2,7 @@ #![no_std] //@ pretty-mode:expanded //@ pp-exact:gca-macro.pp -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] extern crate std; #[prelude_import] use ::std::prelude::rust_2015::*; diff --git a/tests/pretty/gca-macro.rs b/tests/pretty/gca-macro.rs index 248fd4424e1da..decc72e18b4bf 100644 --- a/tests/pretty/gca-macro.rs +++ b/tests/pretty/gca-macro.rs @@ -1,6 +1,6 @@ //@ pretty-mode:expanded //@ pp-exact:gca-macro.pp -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs b/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs index 5c47382ef536d..236aba80544db 100644 --- a/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs +++ b/tests/rustdoc-html/constant/ice-associated-const-equality-105952.rs @@ -1,7 +1,7 @@ //! Regression test for #![crate_name = "foo"] -#![feature(min_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, adt_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs b/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs index 64cfc129d09ce..62aa7697e18a1 100644 --- a/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs +++ b/tests/rustdoc-html/inline_cross/auxiliary/assoc-const-equality.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] pub fn accept(_: impl Trait) {} diff --git a/tests/rustdoc-html/type-const-associated-const-no-body.rs b/tests/rustdoc-html/type-const-associated-const-no-body.rs index 101e4b48a9c9c..99e1ed3b6add7 100644 --- a/tests/rustdoc-html/type-const-associated-const-no-body.rs +++ b/tests/rustdoc-html/type-const-associated-const-no-body.rs @@ -2,7 +2,7 @@ //! and #![crate_name = "foo"] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] pub trait Tr { diff --git a/tests/rustdoc-html/type-const-free-in-array.rs b/tests/rustdoc-html/type-const-free-in-array.rs index 3fd6b21e34eea..e78fc9844758b 100644 --- a/tests/rustdoc-html/type-const-free-in-array.rs +++ b/tests/rustdoc-html/type-const-free-in-array.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/rustdoc-html/type-const-inherent-with-body.rs b/tests/rustdoc-html/type-const-inherent-with-body.rs index 030ca8608a02d..dd0bb079a7072 100644 --- a/tests/rustdoc-html/type-const-inherent-with-body.rs +++ b/tests/rustdoc-html/type-const-inherent-with-body.rs @@ -1,5 +1,5 @@ #![crate_name = "foo"] -#![feature(min_generic_const_args, macroless_generic_const_args, inherent_associated_types)] +#![feature(gca_min_const_items, gca_macroless_args, inherent_associated_types)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs b/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs index af6899571d631..513687646f043 100644 --- a/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs +++ b/tests/rustdoc-ui/associated-constant-not-allowed-102467.rs @@ -2,7 +2,7 @@ // It ensures that the expected error is displayed. #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait T { type A: S = 34>; diff --git a/tests/ui/associated-consts/assoc-const-equality-region-var-hash-ice.stderr b/tests/ui/associated-consts/assoc-const-equality-region-var-hash-ice.stderr index d70cb19a95523..79faf6b4e5653 100644 --- a/tests/ui/associated-consts/assoc-const-equality-region-var-hash-ice.stderr +++ b/tests/ui/associated-consts/assoc-const-equality-region-var-hash-ice.stderr @@ -21,7 +21,7 @@ LL | fn foo() -> dyn Trait<'r, K = {}> { | ^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0308]: mismatched types diff --git a/tests/ui/associated-consts/assoc-const-equality-unexpected-region.stderr b/tests/ui/associated-consts/assoc-const-equality-unexpected-region.stderr index 6e38e3e41acbf..be308e7540386 100644 --- a/tests/ui/associated-consts/assoc-const-equality-unexpected-region.stderr +++ b/tests/ui/associated-consts/assoc-const-equality-unexpected-region.stderr @@ -25,7 +25,7 @@ LL | impl dyn TraitA<'_> where (): TraitA<'a, K = 0> {} | ^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates diff --git a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr index 2170857fd7994..b007bd6694628 100644 --- a/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr +++ b/tests/ui/associated-consts/associated-const-type-parameter-arrays.stderr @@ -6,7 +6,7 @@ LL | let _array: [u32; ::Y]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/issue-110933.rs b/tests/ui/associated-consts/issue-110933.rs index 8c3fc59af1bb1..59e123bb0e509 100644 --- a/tests/ui/associated-consts/issue-110933.rs +++ b/tests/ui/associated-consts/issue-110933.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] pub trait Trait { diff --git a/tests/ui/associated-consts/issue-47814.stderr b/tests/ui/associated-consts/issue-47814.stderr index b59603861d2e8..4d6efef3b82c0 100644 --- a/tests/ui/associated-consts/issue-47814.stderr +++ b/tests/ui/associated-consts/issue-47814.stderr @@ -10,7 +10,7 @@ note: not a concrete type LL | impl<'a> ArpIPv4<'a> { | ^^^^^^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs index bb5e7ad4be181..64fb443bc8042 100644 --- a/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs +++ b/tests/ui/associated-consts/type-const-in-array-len-wrong-type.rs @@ -1,7 +1,7 @@ #![feature( generic_const_exprs, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, inherent_associated_types )] diff --git a/tests/ui/associated-consts/type-const-in-array-len.rs b/tests/ui/associated-consts/type-const-in-array-len.rs index b4cf05a618255..b2d291c1ff45b 100644 --- a/tests/ui/associated-consts/type-const-in-array-len.rs +++ b/tests/ui/associated-consts/type-const-in-array-len.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args, inherent_associated_types)] +#![feature(gca_min_const_items, gca_macroless_args, inherent_associated_types)] use std::gca; diff --git a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr index 28bf0e8fb3327..60dbbcbe458fe 100644 --- a/tests/ui/associated-item/associated-item-duplicate-bounds.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-bounds.stderr @@ -6,7 +6,7 @@ LL | links: [u32; A::LINKS], // Shouldn't suggest bounds already there. | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/associated-type-bounds/duplicate-bound-err.rs b/tests/ui/associated-type-bounds/duplicate-bound-err.rs index 5dc2ad6a3a56c..f9acdbf3c5e6e 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound-err.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound-err.rs @@ -1,6 +1,6 @@ //@ edition: 2024 -#![feature(min_generic_const_args, type_alias_impl_trait, return_type_notation)] +#![feature(gca_min_const_items, type_alias_impl_trait, return_type_notation)] #![expect(incomplete_features)] #![allow(refining_impl_trait_internal)] diff --git a/tests/ui/associated-type-bounds/duplicate-bound.rs b/tests/ui/associated-type-bounds/duplicate-bound.rs index 68f9c373cd49c..b9025682e2920 100644 --- a/tests/ui/associated-type-bounds/duplicate-bound.rs +++ b/tests/ui/associated-type-bounds/duplicate-bound.rs @@ -1,7 +1,7 @@ //@ edition: 2024 //@ run-pass -#![feature(min_generic_const_args, return_type_notation)] +#![feature(gca_min_const_items, return_type_notation)] #![expect(incomplete_features)] #![allow(dead_code, refining_impl_trait_internal, type_alias_bounds)] diff --git a/tests/ui/associated-types/associated-types-eq-2.stderr b/tests/ui/associated-types/associated-types-eq-2.stderr index 9be346516c892..fdcfb8cd53f98 100644 --- a/tests/ui/associated-types/associated-types-eq-2.stderr +++ b/tests/ui/associated-types/associated-types-eq-2.stderr @@ -8,7 +8,7 @@ LL | | = 42, T2 = Qux, T3 = usize> for Bar { | |____^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -18,7 +18,7 @@ LL | impl Tr3 for Qux { | ^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -28,7 +28,7 @@ LL | impl Tr3<42, T2 = 42, T3 = usize> for Bar { | ^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -38,7 +38,7 @@ LL | impl Tr3 for Bar { | ^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0229]: associated item constraints are not allowed here diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs index 8a0d14554d201..2b9f08d72588a 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.rs +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.rs @@ -1,7 +1,7 @@ struct S; impl S { const LEN: usize = std::gca!(1); - //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] + //~^ ERROR: use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR: expected expression, found `gca!()` fn arr() { [8; Self::LEN] diff --git a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr index 9ee66984529de..167f2587978e1 100644 --- a/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr +++ b/tests/ui/associated-types/type-const-inherent-impl-normalize.stderr @@ -1,11 +1,11 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/type-const-inherent-impl-normalize.rs:3:24 | LL | const LEN: usize = std::gca!(1); | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs index 378af46decb96..ef1a5ca74c546 100644 --- a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs @@ -8,7 +8,7 @@ // The missing `T` in `check` is intentional. It makes HIR ty lowering emit an // error while still leaving behind the region constraint that used to ICE. -#![feature(min_generic_const_args, inherent_associated_types, generic_const_items)] +#![feature(gca_min_const_items, inherent_associated_types, generic_const_items)] use std::gca; diff --git a/tests/ui/attributes/malformed-attrs.rs b/tests/ui/attributes/malformed-attrs.rs index 36ad21a54bd51..e27516d5a60d8 100644 --- a/tests/ui/attributes/malformed-attrs.rs +++ b/tests/ui/attributes/malformed-attrs.rs @@ -9,7 +9,7 @@ #![feature(dropck_eyepatch)] #![feature(export_stable)] #![allow(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(ffi_const, ffi_pure)] #![feature(coverage_attribute)] #![feature(sanitize)] diff --git a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr index d42a098be25cd..e2b989c9c5d1e 100644 --- a/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr +++ b/tests/ui/const-generics/adt_const_params/index-oob-ice-83993.stderr @@ -6,7 +6,7 @@ LL | let x: &'b (); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/index-oob-ice-83993.rs:18:17 @@ -16,7 +16,7 @@ LL | let _: &'b (); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs index a8d66c950a064..f566feec0e416 100644 --- a/tests/ui/const-generics/associated-const-bindings/ambiguity.rs +++ b/tests/ui/const-generics/associated-const-bindings/ambiguity.rs @@ -1,7 +1,7 @@ // We used to say "ambiguous associated type" on ambiguous associated consts. // Ensure that we now use the correct label. -#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, gca_min_const_items, unsized_const_params)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/assoc-const-ty-mismatch.rs b/tests/ui/const-generics/associated-const-bindings/assoc-const-ty-mismatch.rs index 1092733a8e2ef..f750f3bbca8af 100644 --- a/tests/ui/const-generics/associated-const-bindings/assoc-const-ty-mismatch.rs +++ b/tests/ui/const-generics/associated-const-bindings/assoc-const-ty-mismatch.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features, unused)] pub trait Foo { diff --git a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs index d7e5ce3229dfd..f63c5a24200ad 100644 --- a/tests/ui/const-generics/associated-const-bindings/assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/assoc-const.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(unused, incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs index a3dc049c144f2..28b10f2b266a3 100644 --- a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs +++ b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty-not-wf.rs @@ -1,7 +1,7 @@ // Check that we eventually catch types of assoc const bounds // (containing late-bound vars) that are ill-formed. #![feature( - min_generic_const_args, + gca_min_const_items, adt_const_params, const_param_ty_trait, generic_const_parameter_types diff --git a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs index 729d4256d4baf..5049d6ba2f0e6 100644 --- a/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/bound-var-in-ty.rs @@ -4,7 +4,7 @@ //@ check-pass #![feature( - min_generic_const_args, + gca_min_const_items, adt_const_params, const_param_ty_trait, generic_const_parameter_types diff --git a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs index f6fa6ece02ad9..f3b309075d772 100644 --- a/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs +++ b/tests/ui/const-generics/associated-const-bindings/coexisting-with-type-binding.rs @@ -5,7 +5,7 @@ //@ check-pass -#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, gca_min_const_items, unsized_const_params)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/coherence.rs b/tests/ui/const-generics/associated-const-bindings/coherence.rs index d5764bfc93b61..35e14f4c7b780 100644 --- a/tests/ui/const-generics/associated-const-bindings/coherence.rs +++ b/tests/ui/const-generics/associated-const-bindings/coherence.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/const-bound-to-assoc-ty-99828.stderr b/tests/ui/const-generics/associated-const-bindings/const-bound-to-assoc-ty-99828.stderr index 692e511fb469e..e58d64778ff17 100644 --- a/tests/ui/const-generics/associated-const-bindings/const-bound-to-assoc-ty-99828.stderr +++ b/tests/ui/const-generics/associated-const-bindings/const-bound-to-assoc-ty-99828.stderr @@ -5,7 +5,7 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator + '_ { | ^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected type, found constant diff --git a/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs b/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs index 8d876e2ca3582..86a67e67799de 100644 --- a/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs +++ b/tests/ui/const-generics/associated-const-bindings/const-projection-err.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] trait TraitWAssocConst { diff --git a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs index 7f7aec0ebcdd5..d231129613911 100644 --- a/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs +++ b/tests/ui/const-generics/associated-const-bindings/const_evaluatable_unchecked.rs @@ -4,7 +4,7 @@ // // issue: //@ check-pass -#![feature(min_generic_const_args, associated_type_defaults)] +#![feature(gca_min_const_items, associated_type_defaults)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs index f393a4910cd8d..318db40badad8 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-assoc-const-ty-mentions-self.rs @@ -6,7 +6,7 @@ #![feature(adt_const_params)] #![feature(generic_const_items)] #![feature(generic_const_parameter_types)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(const_param_ty_trait)] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs index cddb6eb88e937..88a227b066110 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-basic.rs @@ -3,7 +3,7 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs index c38431c8e1d78..e4bbccae17064 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-mismatch.rs @@ -1,6 +1,6 @@ // Ensure that we actually enforce equality constraints found in trait object types. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs index b6d67f8fd8b19..0f154dfc718e4 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-param-default-mentions-self.rs @@ -1,7 +1,7 @@ // Test that we force users to explicitly specify const arguments for const parameters that // have defaults if the default mentions the `Self` type parameter. -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs index 1171744f8e774..59bbc71722ed1 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-behind-trait-alias-mentions-self.rs @@ -5,7 +5,7 @@ // The author of the trait object type can't fix this unlike the supertrait bound // equivalent where they just need to explicitly specify the assoc const. -#![feature(min_generic_const_args, macroless_generic_const_args, trait_alias)] +#![feature(gca_min_const_items, gca_macroless_args, trait_alias)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs index 1a417be8ea451..ea5b150e83ba2 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-const-projection-from-supertrait-mentions-self.rs @@ -1,7 +1,7 @@ // Test that we force users to explicitly specify associated constants (via bindings) // which reference the `Self` type parameter. -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] trait X: Y { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-generic-assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-generic-assoc-const.rs index 05e8aeea5ed5a..8d6bc2e5131ec 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-generic-assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-generic-assoc-const.rs @@ -3,7 +3,7 @@ //@ dont-require-annotations: NOTE -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs index 9036de88bd355..aaede20d6fa6b 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-non-type-assoc-const.rs @@ -2,7 +2,7 @@ //@ dont-require-annotations: NOTE -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs index 2d282ace5436a..15b218e966707 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-bound-on-assoc-const-allowed-and-enforced.rs @@ -2,7 +2,7 @@ // reference the `Self` type parameter (contrary to methods) and that such where clauses are // actually enforced. -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs index 53746231f46d7..728e79fc62597 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-assoc-const-ty.rs @@ -6,8 +6,8 @@ #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, const_param_ty_trait, generic_const_parameter_types )] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs index 7cd8d6ef36302..524f0dd5cac68 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-methods.rs @@ -11,7 +11,7 @@ // correct values from the type assoc consts). //@ run-pass -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs index 256c9feeb6771..05e03eb0b2256 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-self-const-projections-in-supertrait-bounds.rs @@ -4,7 +4,7 @@ //@ dont-require-annotations: NOTE -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] trait Trait: SuperTrait<{ Self::N }> { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs index 2a28022b8844e..9525e20406173 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-symbol-mangling.rs @@ -10,7 +10,7 @@ //\@[legacy] normalize-stderr: "h[[:xdigit:]]{16}" -> "h[HASH]" //@ [v0] normalize-stderr: "sym\[.*?\]" -> "sym[HASH]" -#![feature(min_generic_const_args, rustc_attrs)] +#![feature(gca_min_const_items, rustc_attrs)] #![expect(incomplete_features)] #![crate_name = "sym"] diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs index 6c4c8ccc35572..efbbb07317e1c 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-compat-unspecified-assoc-consts.rs @@ -2,7 +2,7 @@ // be specified in the corresp. trait object type (barring exceptions) similiar to associated // types. Check that we reject code that doesn't provide the necessary bindings. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs b/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs index d498f52003b48..d772e027d9e7c 100644 --- a/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs +++ b/tests/ui/const-generics/associated-const-bindings/dyn-const-projection-escaping-bound-vars.rs @@ -2,7 +2,7 @@ //! (#151642) //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait2<'a> { diff --git a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs index 0b4e871ceb5c6..5afa1251a67ce 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality-unused-issue-126729.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] #![deny(dead_code)] diff --git a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs index 3027357d0fb7e..8acbf1f0f45d3 100644 --- a/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs +++ b/tests/ui/const-generics/associated-const-bindings/equality_bound_with_infer.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs index 5a4ea95eae189..611612036de8b 100644 --- a/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/esc-bound-var-in-ty.rs @@ -2,7 +2,7 @@ // the type of assoc consts used in an equality bound. #![feature( adt_const_params, - min_generic_const_args, + gca_min_const_items, unsized_const_params, generic_const_parameter_types )] diff --git a/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs b/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs index cfbca73dd531b..c1ec53437a6f1 100644 --- a/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs +++ b/tests/ui/const-generics/associated-const-bindings/issue-102335-const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] trait T { diff --git a/tests/ui/const-generics/associated-const-bindings/issue-105330.stderr b/tests/ui/const-generics/associated-const-bindings/issue-105330.stderr index 06900404ec34e..cabdd6bd9d0fa 100644 --- a/tests/ui/const-generics/associated-const-bindings/issue-105330.stderr +++ b/tests/ui/const-generics/associated-const-bindings/issue-105330.stderr @@ -22,7 +22,7 @@ LL | fn foo>() { | ^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -32,7 +32,7 @@ LL | fn main>() { | ^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0562]: `impl Trait` is not allowed in impl headers diff --git a/tests/ui/const-generics/associated-const-bindings/issue-93835.stderr b/tests/ui/const-generics/associated-const-bindings/issue-93835.stderr index 990d22bba4de6..c19e949139725 100644 --- a/tests/ui/const-generics/associated-const-bindings/issue-93835.stderr +++ b/tests/ui/const-generics/associated-const-bindings/issue-93835.stderr @@ -23,7 +23,7 @@ LL | type_ascribe!(p, a>); | ^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -33,7 +33,7 @@ LL | type_ascribe!(p, a>); | ^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace-no-feature-gate.stderr b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace-no-feature-gate.stderr index d2f28a62e04e3..16ed4ecb1df8b 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace-no-feature-gate.stderr +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace-no-feature-gate.stderr @@ -15,7 +15,7 @@ LL | fn take0(_: impl Owner = { N }>) {} | ^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs index 9ef5c902062e3..1746531bae2c6 100644 --- a/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs +++ b/tests/ui/const-generics/associated-const-bindings/mismatched-types-with-generic-in-ace.rs @@ -1,4 +1,4 @@ -#![feature(generic_const_items, min_generic_const_args)] +#![feature(generic_const_items, gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/associated-const-bindings/missing.rs b/tests/ui/const-generics/associated-const-bindings/missing.rs index 22b565cb27d20..0bc2efb35d2e2 100644 --- a/tests/ui/const-generics/associated-const-bindings/missing.rs +++ b/tests/ui/const-generics/associated-const-bindings/missing.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features, unused)] pub trait Foo { diff --git a/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs b/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs index d013eb164065f..209eb73421d6c 100644 --- a/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs +++ b/tests/ui/const-generics/associated-const-bindings/normalization-via-param-env.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] // Regression test for normalizing const projections diff --git a/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs b/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs index d7c6426d7bc38..db4b809597fd5 100644 --- a/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs +++ b/tests/ui/const-generics/associated-const-bindings/param-in-ty.rs @@ -1,7 +1,7 @@ // Regression test for issue #108271. // Detect and reject generic params in the type of assoc consts used in an equality bound. #![feature( - min_generic_const_args, + gca_min_const_items, adt_const_params, unsized_const_params, generic_const_parameter_types, diff --git a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs index 572e50862988b..61062681d20da 100644 --- a/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs +++ b/tests/ui/const-generics/associated-const-bindings/projection-unspecified-but-bounded.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] // Issue 110549 diff --git a/tests/ui/const-generics/associated-const-bindings/supertraits.rs b/tests/ui/const-generics/associated-const-bindings/supertraits.rs index d0647b62adb2e..ee8fe9bcd1e58 100644 --- a/tests/ui/const-generics/associated-const-bindings/supertraits.rs +++ b/tests/ui/const-generics/associated-const-bindings/supertraits.rs @@ -4,7 +4,7 @@ //@ check-pass #![feature( - min_generic_const_args, + gca_min_const_items, adt_const_params, const_param_ty_trait, generic_const_parameter_types diff --git a/tests/ui/const-generics/associated-const-bindings/unbraced-enum-variant.rs b/tests/ui/const-generics/associated-const-bindings/unbraced-enum-variant.rs index f2b581412a727..f706b44007552 100644 --- a/tests/ui/const-generics/associated-const-bindings/unbraced-enum-variant.rs +++ b/tests/ui/const-generics/associated-const-bindings/unbraced-enum-variant.rs @@ -1,5 +1,5 @@ //@ edition:2015 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] pub enum Mode { diff --git a/tests/ui/const-generics/associated-const-bindings/unconstrained_impl_param.stderr b/tests/ui/const-generics/associated-const-bindings/unconstrained_impl_param.stderr index c34674604b51d..8ca341e4b23f1 100644 --- a/tests/ui/const-generics/associated-const-bindings/unconstrained_impl_param.stderr +++ b/tests/ui/const-generics/associated-const-bindings/unconstrained_impl_param.stderr @@ -5,7 +5,7 @@ LL | impl Trait for () where (U,): AssocConst {} | ^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0207]: the type parameter `U` is not constrained by the impl trait, self type, or predicates diff --git a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs index b8eebfa3697e5..e9c4fb0584b81 100644 --- a/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs +++ b/tests/ui/const-generics/associated-const-bindings/using-fnptr-as-type_const.rs @@ -1,7 +1,7 @@ // Regression test for #119783 #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs index d098350c34734..1b7dd61a27125 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-1.rs @@ -1,7 +1,7 @@ //! Check that we correctly handle associated const bindings //! in `impl Trait` where the RHS is a const param (#151642). -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs index 67bfa9e6656ae..a23ddef117fdd 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-2.rs @@ -1,7 +1,7 @@ //! Check that we correctly handle associated const bindings //! in `dyn Trait` where the RHS is a const param (#151642). -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs index 0180aa4694f67..29cadda23761f 100644 --- a/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs +++ b/tests/ui/const-generics/associated-const-bindings/wf-mismatch-3.rs @@ -1,7 +1,7 @@ //! Check that we correctly handle associated const bindings //! where the RHS is a normalizable const projection (#151642). -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr index 9ab0a3f137d74..102afaa9a0da2 100644 --- a/tests/ui/const-generics/const-arg-in-const-arg.min.stderr +++ b/tests/ui/const-generics/const-arg-in-const-arg.min.stderr @@ -6,7 +6,7 @@ LL | let _: [u8; foo::()]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:16:23 @@ -16,7 +16,7 @@ LL | let _: [u8; bar::()]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:18:23 @@ -26,7 +26,7 @@ LL | let _: [u8; faz::<'a>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:20:23 @@ -36,7 +36,7 @@ LL | let _: [u8; baz::<'a>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:21:23 @@ -46,7 +46,7 @@ LL | let _: [u8; faz::<'b>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:23:23 @@ -56,7 +56,7 @@ LL | let _: [u8; baz::<'b>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:27:23 @@ -66,7 +66,7 @@ LL | let _ = [0; bar::()]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:29:23 @@ -76,7 +76,7 @@ LL | let _ = [0; faz::<'a>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:31:23 @@ -86,7 +86,7 @@ LL | let _ = [0; baz::<'a>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:32:23 @@ -96,7 +96,7 @@ LL | let _ = [0; faz::<'b>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:34:23 @@ -106,7 +106,7 @@ LL | let _ = [0; baz::<'b>(&())]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:35:24 @@ -116,7 +116,7 @@ LL | let _: Foo<{ foo::() }>; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:36:24 @@ -126,7 +126,7 @@ LL | let _: Foo<{ bar::() }>; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:38:24 @@ -136,7 +136,7 @@ LL | let _: Foo<{ faz::<'a>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:40:24 @@ -146,7 +146,7 @@ LL | let _: Foo<{ baz::<'a>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:41:24 @@ -156,7 +156,7 @@ LL | let _: Foo<{ faz::<'b>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:43:24 @@ -166,7 +166,7 @@ LL | let _: Foo<{ baz::<'b>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:44:27 @@ -176,7 +176,7 @@ LL | let _ = Foo::<{ foo::() }>; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:45:27 @@ -186,7 +186,7 @@ LL | let _ = Foo::<{ bar::() }>; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:47:27 @@ -196,7 +196,7 @@ LL | let _ = Foo::<{ faz::<'a>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:49:27 @@ -206,7 +206,7 @@ LL | let _ = Foo::<{ baz::<'a>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:50:27 @@ -216,7 +216,7 @@ LL | let _ = Foo::<{ faz::<'b>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const-arg-in-const-arg.rs:52:27 @@ -226,7 +226,7 @@ LL | let _ = Foo::<{ baz::<'b>(&()) }>; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0747]: unresolved item provided when a constant was expected --> $DIR/const-arg-in-const-arg.rs:16:23 diff --git a/tests/ui/const-generics/const-argument-if-length.min.stderr b/tests/ui/const-generics/const-argument-if-length.min.stderr index f6046db879ee0..c52d79a6f67bf 100644 --- a/tests/ui/const-generics/const-argument-if-length.min.stderr +++ b/tests/ui/const-generics/const-argument-if-length.min.stderr @@ -6,7 +6,7 @@ LL | pad: [u8; is_zst::()], | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/const-argument-if-length.rs:16:12 diff --git a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr index 4adcdf836c891..21f7e72f7dcb7 100644 --- a/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr +++ b/tests/ui/const-generics/const-argument-non-static-lifetime.min.stderr @@ -6,7 +6,7 @@ LL | let _: &'a (); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr index 71ca2b2888644..a24200f54b170 100644 --- a/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr +++ b/tests/ui/const-generics/defaults/complex-generic-default-expr.min.stderr @@ -6,7 +6,7 @@ LL | struct Foo; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-generic-default-expr.rs:9:62 @@ -16,7 +16,7 @@ LL | struct Bar() }>(T); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr index d4d95168caf28..2ad49111e26e6 100644 --- a/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr +++ b/tests/ui/const-generics/early/const_arg_trivial_macro_expansion-4.stderr @@ -11,7 +11,7 @@ LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const_arg_trivial_macro_expansion-4.rs:7:9 @@ -26,7 +26,7 @@ LL | fn foo() -> Foo<{ arg!{} arg!{} }> { loop {} } | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/const_arg_trivial_macro_expansion-4.rs:15:46 @@ -36,7 +36,7 @@ LL | fn bar() -> [(); { empty!{}; N }] { loop {} } | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/early/macro_rules-braces.stderr b/tests/ui/const-generics/early/macro_rules-braces.stderr index 410b26d823bcc..f5a300026a51b 100644 --- a/tests/ui/const-generics/early/macro_rules-braces.stderr +++ b/tests/ui/const-generics/early/macro_rules-braces.stderr @@ -28,7 +28,7 @@ LL | let _: foo!({{ N }}); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:36:19 @@ -38,7 +38,7 @@ LL | let _: bar!({ N }); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:41:20 @@ -48,7 +48,7 @@ LL | let _: baz!({{ N }}); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/macro_rules-braces.rs:46:19 @@ -58,7 +58,7 @@ LL | let _: biz!({ N }); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr index 334b72a2f8416..927f0af668fa3 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces-2.stderr @@ -11,7 +11,7 @@ LL | fn foo() -> A<{{ y!() }}> { | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr index 068091e6cc933..5d5319d0b8af7 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-macro-nested-braces.stderr @@ -11,7 +11,7 @@ LL | fn foo() -> A<{ y!() }> { | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr index 7c831d4353643..168661e6d85b4 100644 --- a/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr +++ b/tests/ui/const-generics/early/trivial-const-arg-nested-braces.stderr @@ -6,7 +6,7 @@ LL | fn foo() -> A<{ { N } }> { | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/fn-item-as-const-arg-137084.rs b/tests/ui/const-generics/fn-item-as-const-arg-137084.rs index 0d8d2effc3da0..cec3c881cc710 100644 --- a/tests/ui/const-generics/fn-item-as-const-arg-137084.rs +++ b/tests/ui/const-generics/fn-item-as-const-arg-137084.rs @@ -1,7 +1,7 @@ // Regression test for https://github.com/rust-lang/rust/issues/137084 // Previously caused ICE when using function item as const generic argument -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] fn a() {} diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr index 4306110c8433d..f3cb4a06cddc8 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr @@ -1,8 +1,8 @@ -error: `generic_const_args` requires -Znext-solver=globally to be enabled +error: `gca_const_items` requires -Znext-solver=globally to be enabled --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:9:5 | -LL | generic_const_args, - | ^^^^^^^^^^^^^^^^^^ +LL | gca_const_items, + | ^^^^^^^^^^^^^^^ | = help: enable all of these features diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index a178a0f0d0b95..e24b11dbb1746 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -5,8 +5,8 @@ // removes the restriction that -Znext-solver must be enabled) #![feature( - min_generic_const_args, - generic_const_args, + gca_min_const_items, + gca_const_items, //[old]~^ ERROR next-solver generic_const_items )] diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars.rs index 3d78566e15c92..fc1f174280acd 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars.rs @@ -2,9 +2,9 @@ //@ compile-flags: -Znext-solver #![feature( - min_generic_const_args, - macroless_generic_const_args, - generic_const_args, + gca_min_const_items, + gca_macroless_args, + gca_const_items, generic_const_items )] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/gca/assoc-const.rs b/tests/ui/const-generics/gca/assoc-const.rs index 316084e5b8cf9..d4b933d6a4aef 100644 --- a/tests/ui/const-generics/gca/assoc-const.rs +++ b/tests/ui/const-generics/gca/assoc-const.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, generic_const_args)] +#![feature(gca_min_const_items, gca_const_items)] use std::gca; diff --git a/tests/ui/const-generics/gca/basic-different-definitions.rs b/tests/ui/const-generics/gca/basic-different-definitions.rs index 215b28c985113..52797d142d400 100644 --- a/tests/ui/const-generics/gca/basic-different-definitions.rs +++ b/tests/ui/const-generics/gca/basic-different-definitions.rs @@ -2,8 +2,8 @@ //@ compile-flags: -Znext-solver #![feature(generic_const_items)] -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/gca/basic.rs b/tests/ui/const-generics/gca/basic.rs index c6158023a1be5..d432f733b69c5 100644 --- a/tests/ui/const-generics/gca/basic.rs +++ b/tests/ui/const-generics/gca/basic.rs @@ -2,8 +2,8 @@ //@ compile-flags: -Znext-solver #![feature(generic_const_items)] -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/gca/coherence-fail.rs b/tests/ui/const-generics/gca/coherence-fail.rs index 9b92fec952ce9..8fed4f8fa655d 100644 --- a/tests/ui/const-generics/gca/coherence-fail.rs +++ b/tests/ui/const-generics/gca/coherence-fail.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(generic_const_items, min_generic_const_args, generic_const_args)] +#![feature(generic_const_items, gca_min_const_items, gca_const_items)] #![expect(incomplete_features)] // computing the same value with different constant items but same generic arguments should fail diff --git a/tests/ui/const-generics/gca/coherence-ok.rs b/tests/ui/const-generics/gca/coherence-ok.rs index 4ea66eb8e290d..7db4d22604bf0 100644 --- a/tests/ui/const-generics/gca/coherence-ok.rs +++ b/tests/ui/const-generics/gca/coherence-ok.rs @@ -1,6 +1,6 @@ //@ check-pass //@ compile-flags: -Znext-solver -#![feature(generic_const_items, min_generic_const_args, generic_const_args)] +#![feature(generic_const_items, gca_min_const_items, gca_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs index 181693c365255..7600c4882a91c 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs @@ -1,9 +1,9 @@ //@ compile-flags: -Znext-solver=globally #![allow(incomplete_features)] -#![feature(macroless_generic_const_args)] -#![feature(macroless_const_item_generic_const_args)] -#![feature(generic_const_args, min_generic_const_args)] +#![feature(gca_macroless_args)] +#![feature(gca_macroless_items)] +#![feature(gca_const_items, gca_min_const_items)] #![feature(min_adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/gca/const-reference-to-constructor.rs b/tests/ui/const-generics/gca/const-reference-to-constructor.rs index bafaf9f532545..5f7cb70bf7017 100644 --- a/tests/ui/const-generics/gca/const-reference-to-constructor.rs +++ b/tests/ui/const-generics/gca/const-reference-to-constructor.rs @@ -1,8 +1,8 @@ //@ check-pass //@ compile-flags: -Znext-solver //! https://github.com/rust-lang/rust/issues/162923 -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] enum T::B as u8 }> { A = 2, B, diff --git a/tests/ui/const-generics/gca/dyn-compat-generic-non-type-assoc-const.rs b/tests/ui/const-generics/gca/dyn-compat-generic-non-type-assoc-const.rs index ec32c7c8b1062..51c04bb47928a 100644 --- a/tests/ui/const-generics/gca/dyn-compat-generic-non-type-assoc-const.rs +++ b/tests/ui/const-generics/gca/dyn-compat-generic-non-type-assoc-const.rs @@ -1,10 +1,10 @@ // Ensure that traits with generic non-type associated consts are dyn *in*compatible, -// even when non-type associated const equality is enabled by `generic_const_args`. +// even when non-type associated const equality is enabled by `gca_const_items`. //@ dont-require-annotations: NOTE //@ compile-flags: -Znext-solver=globally -#![feature(generic_const_args, generic_const_items, min_generic_const_args)] +#![feature(gca_const_items, generic_const_items, gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/gca/dyn-non-type-assoc-const-binding.rs b/tests/ui/const-generics/gca/dyn-non-type-assoc-const-binding.rs index bf764b829ab6d..2ae6aac08234c 100644 --- a/tests/ui/const-generics/gca/dyn-non-type-assoc-const-binding.rs +++ b/tests/ui/const-generics/gca/dyn-non-type-assoc-const-binding.rs @@ -1,7 +1,7 @@ //@ check-pass //@ compile-flags: -Znext-solver=globally -#![feature(min_generic_const_args, generic_const_args)] +#![feature(gca_min_const_items, gca_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs index 9cb0891127dd8..c1bffd959b887 100644 --- a/tests/ui/const-generics/gca/gca-anon-const-rejected.rs +++ b/tests/ui/const-generics/gca/gca-anon-const-rejected.rs @@ -1,8 +1,8 @@ //@ compile-flags: -Znext-solver // Test that anonymous const blocks using generic parameters are rejected -// under `generic_const_args`. Users should use named const items instead: +// under `gca_const_items`. Users should use named const items instead: // `const FOO: usize = N + 1;` -#![feature(generic_const_args, min_generic_const_args, generic_const_items)] +#![feature(gca_const_items, gca_min_const_items, generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.rs b/tests/ui/const-generics/gca/gca-macro-fn-call.rs index f4a604e2b4700..6035c14e5eb75 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.rs +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.rs @@ -1,6 +1,6 @@ //! Regression test for #157152. //! -//! Under `min_generic_const_args` with `macroless_generic_const_args`, a braced const +//! Under `gca_min_const_items` with `gca_macroless_args`, a braced const //! argument containing an associated-function call (e.g. `FieldName::len()`, as generated //! by `tracing`'s logging macros as `FieldName<{ FieldName::len(name) }>`) was lowered as //! a tuple-struct constructor. Lowering the callee's `Self` type `FieldName`, written @@ -13,8 +13,8 @@ //! tuple-variant constructor (unions, primitives, foreign types), not just structs. //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, macroless_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] +#![feature(gca_const_items)] #![feature(extern_types)] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/gca/generic-free-const.rs b/tests/ui/const-generics/gca/generic-free-const.rs index 8fef5931db1ca..d5793323b510c 100644 --- a/tests/ui/const-generics/gca/generic-free-const.rs +++ b/tests/ui/const-generics/gca/generic-free-const.rs @@ -2,9 +2,9 @@ //@ compile-flags: -Znext-solver #![feature( - min_generic_const_args, - macroless_generic_const_args, - generic_const_args, + gca_min_const_items, + gca_macroless_args, + gca_const_items, generic_const_items )] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/gca/generic-param-rhs.rs b/tests/ui/const-generics/gca/generic-param-rhs.rs index 19a57347a9056..d0e9f077c111d 100644 --- a/tests/ui/const-generics/gca/generic-param-rhs.rs +++ b/tests/ui/const-generics/gca/generic-param-rhs.rs @@ -1,5 +1,5 @@ //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, generic_const_args)] +#![feature(gca_min_const_items, gca_const_items)] #![expect(incomplete_features)] fn foo() {} diff --git a/tests/ui/const-generics/gca/non-type-equality-fail.rs b/tests/ui/const-generics/gca/non-type-equality-fail.rs index 1ea34829c6c6a..9dbf1db99d1d5 100644 --- a/tests/ui/const-generics/gca/non-type-equality-fail.rs +++ b/tests/ui/const-generics/gca/non-type-equality-fail.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args, generic_const_args)] +#![feature(gca_min_const_items, gca_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/gca/non-type-equality-ok.rs b/tests/ui/const-generics/gca/non-type-equality-ok.rs index ae7c069ea55f5..742672238a088 100644 --- a/tests/ui/const-generics/gca/non-type-equality-ok.rs +++ b/tests/ui/const-generics/gca/non-type-equality-ok.rs @@ -2,10 +2,10 @@ //@ compile-flags: -Znext-solver #![feature( - min_generic_const_args, - macroless_generic_const_args, - macroless_const_item_generic_const_args, - generic_const_args, + gca_min_const_items, + gca_macroless_args, + gca_macroless_items, + gca_const_items, generic_const_items )] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/gca/path-to-non-type-const.rs b/tests/ui/const-generics/gca/path-to-non-type-const.rs index 53382fe4aa247..b28d4ab4943de 100644 --- a/tests/ui/const-generics/gca/path-to-non-type-const.rs +++ b/tests/ui/const-generics/gca/path-to-non-type-const.rs @@ -2,9 +2,9 @@ //@ compile-flags: -Znext-solver #![feature( - min_generic_const_args, - macroless_generic_const_args, - generic_const_args, + gca_min_const_items, + gca_macroless_args, + gca_const_items, inherent_associated_types )] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/gca/require-next-solver.rs b/tests/ui/const-generics/gca/require-next-solver.rs index ffe3141b0f28a..ce2fdea3a6328 100644 --- a/tests/ui/const-generics/gca/require-next-solver.rs +++ b/tests/ui/const-generics/gca/require-next-solver.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] //~^ ERROR next-solver fn main() {} diff --git a/tests/ui/const-generics/gca/require-next-solver.stderr b/tests/ui/const-generics/gca/require-next-solver.stderr index 677c37610d842..717b561993a17 100644 --- a/tests/ui/const-generics/gca/require-next-solver.stderr +++ b/tests/ui/const-generics/gca/require-next-solver.stderr @@ -1,8 +1,8 @@ -error: `generic_const_args` requires -Znext-solver=globally to be enabled +error: `gca_const_items` requires -Znext-solver=globally to be enabled --> $DIR/require-next-solver.rs:2:12 | -LL | #![feature(generic_const_args)] - | ^^^^^^^^^^^^^^^^^^ +LL | #![feature(gca_const_items)] + | ^^^^^^^^^^^^^^^ | = help: enable all of these features diff --git a/tests/ui/const-generics/gca/rhs-but-not-root.rs b/tests/ui/const-generics/gca/rhs-but-not-root.rs index 4f355c84e4875..b1cf364a66299 100644 --- a/tests/ui/const-generics/gca/rhs-but-not-root.rs +++ b/tests/ui/const-generics/gca/rhs-but-not-root.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(generic_const_items)] -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.stderr b/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.stderr index 3727cc4551e6e..27d6c5d4c8557 100644 --- a/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.stderr +++ b/tests/ui/const-generics/gca/suggest-const-item-for-generic-expr.stderr @@ -6,7 +6,7 @@ LL | fn as_bytes(&self) -> &[u8; size_of::()] { | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/suggest-const-item-for-generic-expr.rs:16:31 @@ -16,7 +16,7 @@ LL | fn foo() -> [u8; size_of::()] { | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/suggest-const-item-for-generic-expr.rs:21:34 @@ -26,7 +26,7 @@ LL | fn bar() -> [u8; N + 1] { | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr index 5a9dd515868b9..71e9bcdf38a09 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr +++ b/tests/ui/const-generics/gca/wf-inherentimpl.old.stderr @@ -1,8 +1,8 @@ -error: `generic_const_args` requires -Znext-solver=globally to be enabled +error: `gca_const_items` requires -Znext-solver=globally to be enabled --> $DIR/wf-inherentimpl.rs:6:12 | -LL | #![feature(generic_const_args, min_generic_const_args)] - | ^^^^^^^^^^^^^^^^^^ +LL | #![feature(gca_const_items, gca_min_const_items)] + | ^^^^^^^^^^^^^^^ | = help: enable all of these features diff --git a/tests/ui/const-generics/gca/wf-inherentimpl.rs b/tests/ui/const-generics/gca/wf-inherentimpl.rs index 8248c7b01832a..afced2edbb89e 100644 --- a/tests/ui/const-generics/gca/wf-inherentimpl.rs +++ b/tests/ui/const-generics/gca/wf-inherentimpl.rs @@ -3,8 +3,8 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature(inherent_associated_types)] -#![feature(generic_const_args, min_generic_const_args)] -//[old]~^ ERROR `generic_const_args` requires -Znext-solver=globally to be enabled +#![feature(gca_const_items, gca_min_const_items)] +//[old]~^ ERROR `gca_const_items` requires -Znext-solver=globally to be enabled use std::gca; struct Foo; impl Foo { diff --git a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr index a507159a778f0..15016c747d8a9 100644 --- a/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/array-size-in-generic-struct-param.min.stderr @@ -6,7 +6,7 @@ LL | struct ArithArrayLen([u32; 0 + N]); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/array-size-in-generic-struct-param.rs:23:15 @@ -16,7 +16,7 @@ LL | arr: [u8; CFG.arr_size], | = help: const parameters may only be used as standalone arguments here, i.e. `CFG` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: `Config` is forbidden as the type of a const generic parameter --> $DIR/array-size-in-generic-struct-param.rs:21:21 diff --git a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs index b4401b182be4e..b99d84d84847f 100644 --- a/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs +++ b/tests/ui/const-generics/generic_const_exprs/auxiliary/non_local_type_const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr b/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr index 5f9ecc8fc701f..e349ab78e4838 100644 --- a/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr +++ b/tests/ui/const-generics/generic_const_exprs/bad-multiply.stderr @@ -6,7 +6,7 @@ LL | SmallVec<{ D * 2 }>:, | = help: const parameters may only be used as standalone arguments here, i.e. `D` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0747]: constant provided when a type was expected --> $DIR/bad-multiply.rs:7:14 diff --git a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr index 6bfe4d60a54b3..810a87c35aed8 100644 --- a/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr +++ b/tests/ui/const-generics/generic_const_exprs/dependence_lint.full.stderr @@ -6,7 +6,7 @@ LL | let _: [u8; size_of::<*mut T>()]; // error on stable, error with gce | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/dependence_lint.rs:22:37 @@ -16,7 +16,7 @@ LL | let _: [u8; if true { size_of::() } else { 3 }]; // error on stable, | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item warning: cannot use constants which depend on generic parameters in types --> $DIR/dependence_lint.rs:10:9 diff --git a/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs b/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs index 358d0d997cae8..3e01e8ae37f75 100644 --- a/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs +++ b/tests/ui/const-generics/generic_const_exprs/direct-inline-const-generic-default.rs @@ -3,7 +3,7 @@ // Regression test for https://github.com/rust-lang/rust/issues/159063. #![feature(generic_const_exprs)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] struct S; diff --git a/tests/ui/const-generics/generic_const_exprs/feature-attribute-missing-in-dependent-crate-ice.stderr b/tests/ui/const-generics/generic_const_exprs/feature-attribute-missing-in-dependent-crate-ice.stderr index d322775a5d974..bd811c72e83d6 100644 --- a/tests/ui/const-generics/generic_const_exprs/feature-attribute-missing-in-dependent-crate-ice.stderr +++ b/tests/ui/const-generics/generic_const_exprs/feature-attribute-missing-in-dependent-crate-ice.stderr @@ -10,7 +10,7 @@ note: not a concrete type LL | impl aux::FromSlice for Wrapper { | ^^^^^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr index 4d8118d0ad530..e2b74b61b2043 100644 --- a/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr +++ b/tests/ui/const-generics/generic_const_exprs/feature-gate-generic_const_exprs.stderr @@ -6,7 +6,7 @@ LL | type Arr = [u8; N - 1]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr index 392a7c5ec3914..15db638d1ae45 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-72787.min.stderr @@ -6,7 +6,7 @@ LL | Condition<{ LHS <= RHS }>: True | = help: const parameters may only be used as standalone arguments here, i.e. `LHS` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:11:24 @@ -16,7 +16,7 @@ LL | Condition<{ LHS <= RHS }>: True | = help: const parameters may only be used as standalone arguments here, i.e. `RHS` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:23:25 @@ -26,7 +26,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | = help: const parameters may only be used as standalone arguments here, i.e. `I` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/issue-72787.rs:23:36 @@ -36,7 +36,7 @@ LL | IsLessOrEqual<{ 8 - I }, { 8 - J }>: True, | = help: const parameters may only be used as standalone arguments here, i.e. `J` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr index 345a7b381645f..fa711a917a666 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-72819-generic-in-const-eval.min.stderr @@ -6,7 +6,7 @@ LL | where Assert::<{N < usize::MAX / 2}>: IsTrue, | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr index 5cc02160d1878..9d03a11fc581d 100644 --- a/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr +++ b/tests/ui/const-generics/generic_const_exprs/issue-74713.stderr @@ -6,7 +6,7 @@ LL | let _: &'a (); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0308]: mismatched types --> $DIR/issue-74713.rs:3:10 diff --git a/tests/ui/const-generics/generic_const_exprs/next-solver-gce-incompatible-issue-158428.rs b/tests/ui/const-generics/generic_const_exprs/next-solver-gce-incompatible-issue-158428.rs index 8a23a68bc1810..5290c994ce692 100644 --- a/tests/ui/const-generics/generic_const_exprs/next-solver-gce-incompatible-issue-158428.rs +++ b/tests/ui/const-generics/generic_const_exprs/next-solver-gce-incompatible-issue-158428.rs @@ -1,8 +1,8 @@ //@ run-pass //@ compile-flags: -Znext-solver=globally -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] #![feature(generic_const_exprs)] //~^ WARN: `feature(generic_const_exprs)` is not supported with the next-generation trait solver //@ normalize-stderr: "(--> ).*/tests/ui/const-generics/generic_const_exprs" -> "$1$$DIR" diff --git a/tests/ui/const-generics/generic_const_exprs/non-local-const.rs b/tests/ui/const-generics/generic_const_exprs/non-local-const.rs index 16fdab0f9e7f4..0d3e0770818fb 100644 --- a/tests/ui/const-generics/generic_const_exprs/non-local-const.rs +++ b/tests/ui/const-generics/generic_const_exprs/non-local-const.rs @@ -1,7 +1,7 @@ // regression test for #133808. //@ aux-build:non_local_type_const.rs -#![feature(min_generic_const_args, macroless_generic_const_args, generic_const_exprs)] +#![feature(gca_min_const_items, gca_macroless_args, generic_const_exprs)] #![allow(incomplete_features)] #![crate_type = "lib"] extern crate non_local_type_const; diff --git a/tests/ui/const-generics/generic_const_exprs/trivial-anon-const-use-cases.min.stderr b/tests/ui/const-generics/generic_const_exprs/trivial-anon-const-use-cases.min.stderr index 1d62f1da03ea7..885cad3846ec3 100644 --- a/tests/ui/const-generics/generic_const_exprs/trivial-anon-const-use-cases.min.stderr +++ b/tests/ui/const-generics/generic_const_exprs/trivial-anon-const-use-cases.min.stderr @@ -6,7 +6,7 @@ LL | stuff: [u8; { S + 1 }], // `S + 1` is NOT a valid const expression in t | = help: const parameters may only be used as standalone arguments here, i.e. `S` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs index 97edbef7df10d..b4fe7a9a5da2a 100644 --- a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs +++ b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs @@ -3,7 +3,7 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature( - min_generic_const_args, + gca_min_const_items, generic_const_parameter_types, inherent_associated_types, min_adt_const_params, diff --git a/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs index fb9831d493465..47b85b142e033 100644 --- a/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs +++ b/tests/ui/const-generics/ice-151186-fn-ptr-in-where-clause.rs @@ -1,6 +1,6 @@ // Regression test for https://github.com/rust-lang/rust/issues/151186 -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] trait Maybe {} diff --git a/tests/ui/const-generics/ice-68875.stderr b/tests/ui/const-generics/ice-68875.stderr index 6cca0090cdaeb..ca01b2e643143 100644 --- a/tests/ui/const-generics/ice-68875.stderr +++ b/tests/ui/const-generics/ice-68875.stderr @@ -5,7 +5,7 @@ LL | data: &'a [u8; Self::SIZE], | ^^^^ | = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr index f24817668e411..d865ecb6275b2 100644 --- a/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr +++ b/tests/ui/const-generics/intrinsics-type_name-as-const-argument.min.stderr @@ -6,7 +6,7 @@ LL | T: Trait<{ std::intrinsics::type_name::() }>, | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: `&'static str` is forbidden as the type of a const generic parameter --> $DIR/intrinsics-type_name-as-const-argument.rs:9:22 diff --git a/tests/ui/const-generics/issue-46511.stderr b/tests/ui/const-generics/issue-46511.stderr index 766c0a7ff596f..74a1eb5779289 100644 --- a/tests/ui/const-generics/issue-46511.stderr +++ b/tests/ui/const-generics/issue-46511.stderr @@ -6,7 +6,7 @@ LL | _a: [u8; std::mem::size_of::<&'a mut u8>()] | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-46511.rs:3:12 diff --git a/tests/ui/const-generics/issues/issue-56445-2.stderr b/tests/ui/const-generics/issues/issue-56445-2.stderr index f13f4fd0a36db..fa9a0d83201a6 100644 --- a/tests/ui/const-generics/issues/issue-56445-2.stderr +++ b/tests/ui/const-generics/issues/issue-56445-2.stderr @@ -10,7 +10,7 @@ note: not a concrete type LL | impl<'a> OnDiskDirEntry<'a> { | ^^^^^^^^^^^^^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-56445-3.stderr b/tests/ui/const-generics/issues/issue-56445-3.stderr index 4e1300969487b..4e5c491dbe8d0 100644 --- a/tests/ui/const-generics/issues/issue-56445-3.stderr +++ b/tests/ui/const-generics/issues/issue-56445-3.stderr @@ -5,7 +5,7 @@ LL | ram: [u8; Self::SIZE], | ^^^^ | = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67375.min.stderr b/tests/ui/const-generics/issues/issue-67375.min.stderr index cee31a88b181c..757220e53dcac 100644 --- a/tests/ui/const-generics/issues/issue-67375.min.stderr +++ b/tests/ui/const-generics/issues/issue-67375.min.stderr @@ -6,7 +6,7 @@ LL | inner: [(); { [|_: &T| {}; 0].len() }], | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: type parameter `T` is never used --> $DIR/issue-67375.rs:5:12 diff --git a/tests/ui/const-generics/issues/issue-67945-1.min.stderr b/tests/ui/const-generics/issues/issue-67945-1.min.stderr index 932ab653f2ca9..a0c4676443b73 100644 --- a/tests/ui/const-generics/issues/issue-67945-1.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-1.min.stderr @@ -6,7 +6,7 @@ LL | let x: S = MaybeUninit::uninit(); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/issue-67945-1.rs:13:45 @@ -16,7 +16,7 @@ LL | let b = &*(&x as *const _ as *const S); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-1.rs:7:12 diff --git a/tests/ui/const-generics/issues/issue-67945-2.min.stderr b/tests/ui/const-generics/issues/issue-67945-2.min.stderr index c73ddd35369b1..adc2cd09d26dc 100644 --- a/tests/ui/const-generics/issues/issue-67945-2.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-2.min.stderr @@ -5,7 +5,7 @@ LL | let x: Option> = None; | ^^^^ | = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-67945-3.min.stderr b/tests/ui/const-generics/issues/issue-67945-3.min.stderr index 9f726ed8e5e14..1ab37d3b2c466 100644 --- a/tests/ui/const-generics/issues/issue-67945-3.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-3.min.stderr @@ -6,7 +6,7 @@ LL | let x: Option = None; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-3.rs:9:12 diff --git a/tests/ui/const-generics/issues/issue-67945-4.min.stderr b/tests/ui/const-generics/issues/issue-67945-4.min.stderr index 94873bc45c440..a6e3755088c92 100644 --- a/tests/ui/const-generics/issues/issue-67945-4.min.stderr +++ b/tests/ui/const-generics/issues/issue-67945-4.min.stderr @@ -6,7 +6,7 @@ LL | let x: Option> = None; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: type parameter `S` is never used --> $DIR/issue-67945-4.rs:8:12 diff --git a/tests/ui/const-generics/issues/issue-68366.min.stderr b/tests/ui/const-generics/issues/issue-68366.min.stderr index 89bd073e4011b..8d10b83b7bcb2 100644 --- a/tests/ui/const-generics/issues/issue-68366.min.stderr +++ b/tests/ui/const-generics/issues/issue-68366.min.stderr @@ -6,7 +6,7 @@ LL | impl Collatz<{Some(N)}> {} | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: `Option` is forbidden as the type of a const generic parameter --> $DIR/issue-68366.rs:9:25 diff --git a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr index 289e9f59b697e..6e00aa40f6014 100644 --- a/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr +++ b/tests/ui/const-generics/issues/issue-76701-ty-param-in-const.stderr @@ -6,7 +6,7 @@ LL | fn ty_param() -> [u8; std::mem::size_of::()] { | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/issue-76701-ty-param-in-const.rs:6:42 @@ -16,7 +16,7 @@ LL | fn const_param() -> [u8; N + 1] { | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/issues/issue-80062.stderr b/tests/ui/const-generics/issues/issue-80062.stderr index bff3886d6328b..5d804bf8ef8b2 100644 --- a/tests/ui/const-generics/issues/issue-80062.stderr +++ b/tests/ui/const-generics/issues/issue-80062.stderr @@ -6,7 +6,7 @@ LL | let _: [u8; sof::()]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/issues/issue-80375.stderr b/tests/ui/const-generics/issues/issue-80375.stderr index 552bdc6618785..d2adadad7ace4 100644 --- a/tests/ui/const-generics/issues/issue-80375.stderr +++ b/tests/ui/const-generics/issues/issue-80375.stderr @@ -6,7 +6,7 @@ LL | struct MyArray([u8; COUNT + 1]); | = help: const parameters may only be used as standalone arguments here, i.e. `COUNT` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/legacy-const-generics-bad.stderr b/tests/ui/const-generics/legacy-const-generics-bad.stderr index df686f6484c75..80d807c3f822a 100644 --- a/tests/ui/const-generics/legacy-const-generics-bad.stderr +++ b/tests/ui/const-generics/legacy-const-generics-bad.stderr @@ -18,7 +18,7 @@ LL | legacy_const_generics::foo(0, N + 1, 2); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 32714ca551fbc..112cf5563a59e 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 0213c447b59ca..96f8461b9cb82 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs index 6fbef3704991e..c488b90aec14b 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs @@ -1,6 +1,6 @@ #![feature( - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, adt_const_params, unsized_const_params )] diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs index f11bd2e51660b..20bac03fab1c0 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] #![crate_type = "lib"] diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs index ecb68b53fcb65..38eb04760c598 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index 3db15a2aef49c..30b8ca3dd2752 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -2,8 +2,8 @@ #![feature( generic_const_items, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, adt_const_params, generic_const_parameter_types, const_param_ty_trait @@ -42,5 +42,5 @@ fn main() { struct PC { _0: PhantomData, } -// FIXME(min_generic_const_args): this shouldn't have to do silly (expr,).0 hacks +// FIXME(gca_min_const_items): this shouldn't have to do silly (expr,).0 hacks const PC: PC = (PC { _0: PhantomData:: },).0; diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs index 6ae942c8dc06d..d48b5cb9e7100 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] enum E { diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs index ef0b885388f7e..0eaadd1a9b31d 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs b/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs index ff828f6323fba..24d4a7dadeb68 100644 --- a/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs +++ b/tests/ui/const-generics/mgca/ambiguous-assoc-const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] trait Tr { diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index 78e9c0821fa88..134a82e9d3490 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -3,7 +3,7 @@ //! Ensure that providing an array const arg with the wrong number of elements //! doesn't ICE or silently cause UB. #![expect(incomplete_features)] -#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] #![feature(unsized_const_params, generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs index 3b36017445b59..def077e4d292d 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index be3b85e2bd240..1c96c492b3cfd 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -1,7 +1,7 @@ //@ revisions: r1 r2 r3 #![expect(incomplete_features)] -#![feature(min_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array-expr-empty.rs b/tests/ui/const-generics/mgca/array-expr-empty.rs index d37c6f2fcfe35..41dfb5e6f8747 100644 --- a/tests/ui/const-generics/mgca/array-expr-empty.rs +++ b/tests/ui/const-generics/mgca/array-expr-empty.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] fn takes_empty_array() {} //~^ ERROR: expected type, found `]` diff --git a/tests/ui/const-generics/mgca/array-expr-simple.rs b/tests/ui/const-generics/mgca/array-expr-simple.rs index 3a096d98e7fa0..eba86898c41a1 100644 --- a/tests/ui/const-generics/mgca/array-expr-simple.rs +++ b/tests/ui/const-generics/mgca/array-expr-simple.rs @@ -1,6 +1,6 @@ //@ run-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array_u32() {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index be12837c4481f..a7582258de2f5 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -1,5 +1,5 @@ //! regression test for -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![feature(adt_const_params)] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs index 356c48085adb0..85ef64c498a4c 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs @@ -1,6 +1,6 @@ //@ run-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array() {} diff --git a/tests/ui/const-generics/mgca/array-expr-with-macro.rs b/tests/ui/const-generics/mgca/array-expr-with-macro.rs index 24e9280e543e7..db768339118f3 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-macro.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-macro.rs @@ -1,6 +1,6 @@ //@ run-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] macro_rules! make_array { diff --git a/tests/ui/const-generics/mgca/array-expr-with-struct.rs b/tests/ui/const-generics/mgca/array-expr-with-struct.rs index 4cc958a9f0273..1d4c051e53f0b 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-struct.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-struct.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] #![allow(dead_code)] diff --git a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs index 4e5124a6d7ae1..f429ca20ce832 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature( - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, adt_const_params, unsized_const_params )] diff --git a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs index 138f3c41d6799..a4131a22337aa 100644 --- a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs +++ b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs @@ -1,7 +1,7 @@ #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, unsized_const_params )] #![allow(incomplete_features)] diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs index b8cbbed030fe5..aa6385c28ded0 100644 --- a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs @@ -3,8 +3,8 @@ #![feature( adt_const_params, generic_const_parameter_types, - min_generic_const_args, - macroless_generic_const_args + gca_min_const_items, + gca_macroless_args )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs index 76534f12d80c8..7edeb25f30e48 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, adt_const_params, unsized_const_params)] +#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs index 9601cbc997f45..7997cff84c510 100644 --- a/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs +++ b/tests/ui/const-generics/mgca/assoc-const-projection-in-bound.rs @@ -1,7 +1,7 @@ //! regression test for //@ run-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(dead_code)] use std::gca; diff --git a/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs index e3c37cac7a696..a3117bc5387ce 100644 --- a/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs +++ b/tests/ui/const-generics/mgca/assoc-const-without-type_const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] pub trait Tr { diff --git a/tests/ui/const-generics/mgca/assoc-const.rs b/tests/ui/const-generics/mgca/assoc-const.rs index 8a2a02ee096f6..786e2557cce8f 100644 --- a/tests/ui/const-generics/mgca/assoc-const.rs +++ b/tests/ui/const-generics/mgca/assoc-const.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] pub trait Tr { diff --git a/tests/ui/const-generics/mgca/auxiliary/anon-const-def-id-on-const-arg-with-anon.rs b/tests/ui/const-generics/mgca/auxiliary/anon-const-def-id-on-const-arg-with-anon.rs index c1ebfc18e0816..c25ce5a03b73e 100644 --- a/tests/ui/const-generics/mgca/auxiliary/anon-const-def-id-on-const-arg-with-anon.rs +++ b/tests/ui/const-generics/mgca/auxiliary/anon-const-def-id-on-const-arg-with-anon.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] pub struct S; // this is a directly represented anon const... it's a bit weird. diff --git a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs index a4ad2cccaa544..aca8016ff0235 100644 --- a/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs +++ b/tests/ui/const-generics/mgca/bad-const-arg-fn-154539.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/bad-gca-macro.rs b/tests/ui/const-generics/mgca/bad-gca-macro.rs index 50f2ebe65e818..db4fc5ded6926 100644 --- a/tests/ui/const-generics/mgca/bad-gca-macro.rs +++ b/tests/ui/const-generics/mgca/bad-gca-macro.rs @@ -1,7 +1,7 @@ //@ edition: 2024 //! Reject direct const arguments in value/type positions without unrelated brace suggestions. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![deny(unused_braces)] use std::gca; diff --git a/tests/ui/const-generics/mgca/bad-impl-trait-with-apit.rs b/tests/ui/const-generics/mgca/bad-impl-trait-with-apit.rs index 1ecf303dbb695..f2fbdc913ceae 100644 --- a/tests/ui/const-generics/mgca/bad-impl-trait-with-apit.rs +++ b/tests/ui/const-generics/mgca/bad-impl-trait-with-apit.rs @@ -1,7 +1,7 @@ // Regression test for issue #155834 #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs index c0391d54e423d..8a8cdce52e768 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.rs +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.rs @@ -11,11 +11,11 @@ struct S; impl Tr for S { const N: usize = core::gca!(0); - //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] + //~^ ERROR: use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS //~| ERROR: expected expression, found `gca!()` constant const M: usize = std::gca!(0); - //~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] + //~^ ERROR: use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR: implementation of a `#[rustc_always_gca]` must have a `gca!` RHS //~| ERROR: expected expression, found `gca!()` constant } diff --git a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr index 0e8c2f4971a41..13c6eddd54364 100644 --- a/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr +++ b/tests/ui/const-generics/mgca/bad-type_const-syntax.stderr @@ -1,21 +1,21 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/bad-type_const-syntax.rs:13:22 | LL | const N: usize = core::gca!(0); | ^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/bad-type_const-syntax.rs:17:22 | LL | const M: usize = std::gca!(0); | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `rustc_always_gca` attribute is an experimental feature @@ -25,7 +25,7 @@ LL | #[rustc_always_gca] | ^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `rustc_always_gca` attribute is an experimental feature @@ -35,7 +35,7 @@ LL | #[rustc_always_gca] | ^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant diff --git a/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs b/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs index 38851a6e5130f..4fb4d54a9275e 100644 --- a/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs +++ b/tests/ui/const-generics/mgca/braced-const-infer-in-body.rs @@ -1,7 +1,7 @@ //! Regression test for: https://github.com/rust-lang/rust/issues/160798 #![crate_type = "lib"] -#![feature(min_generic_const_args)] -#![feature(macroless_generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_macroless_args)] use std::gca; diff --git a/tests/ui/const-generics/mgca/braced-const-infer.rs b/tests/ui/const-generics/mgca/braced-const-infer.rs index ad68bb499f084..afee161c7ce88 100644 --- a/tests/ui/const-generics/mgca/braced-const-infer.rs +++ b/tests/ui/const-generics/mgca/braced-const-infer.rs @@ -1,5 +1,5 @@ //! Regression test for https://github.com/rust-lang/rust/issues/153198 -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features, rust_2021_compatibility)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs index 9f6a62aa60e17..c72ce06ceb194 100644 --- a/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs +++ b/tests/ui/const-generics/mgca/concrete-expr-with-generics-in-env.rs @@ -1,7 +1,7 @@ //@ check-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs index e19b71153b1e5..58da2bc86bee6 100644 --- a/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs +++ b/tests/ui/const-generics/mgca/const-arg-coherence-conflicting-methods.rs @@ -1,7 +1,7 @@ // Regression test for #140729 #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs index c4e941edbb4de..8a26ae568e3b8 100644 --- a/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs +++ b/tests/ui/const-generics/mgca/const-arg-mismatched-literal-suffix.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs index 75e936ee8f5e3..5272f6fe0c97b 100644 --- a/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs +++ b/tests/ui/const-generics/mgca/const-ctor-overflow-eval.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/const-ctor-with-error.rs b/tests/ui/const-generics/mgca/const-ctor-with-error.rs index c72feb65b959f..9272b07b01048 100644 --- a/tests/ui/const-generics/mgca/const-ctor-with-error.rs +++ b/tests/ui/const-generics/mgca/const-ctor-with-error.rs @@ -1,6 +1,6 @@ // to ensure it does not ices like before -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/const-ctor.rs b/tests/ui/const-generics/mgca/const-ctor.rs index 4d95fc5013dde..361edb1d25165 100644 --- a/tests/ui/const-generics/mgca/const-ctor.rs +++ b/tests/ui/const-generics/mgca/const-ctor.rs @@ -5,8 +5,8 @@ //@ check-pass #![feature( - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, adt_const_params, generic_const_parameter_types, const_param_ty_trait diff --git a/tests/ui/const-generics/mgca/const-param-in-nested-inline-const-arg.rs b/tests/ui/const-generics/mgca/const-param-in-nested-inline-const-arg.rs index e8af7e00b470a..6d74d66874240 100644 --- a/tests/ui/const-generics/mgca/const-param-in-nested-inline-const-arg.rs +++ b/tests/ui/const-generics/mgca/const-param-in-nested-inline-const-arg.rs @@ -1,5 +1,5 @@ //@compile-flags: -Znext-solver=globally -#![feature(generic_const_args, min_generic_const_args)] +#![feature(gca_const_items, gca_min_const_items)] struct S; fn foo(_: S<{ const { const { N } } }>) {} diff --git a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs index 7c0a6c9f7771b..af873ec558071 100644 --- a/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs +++ b/tests/ui/const-generics/mgca/cyclic-type-const-151251.rs @@ -1,6 +1,6 @@ //@ needs-rustc-debug-assertions -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(generic_const_exprs)] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/mgca/double-inline-const.rs b/tests/ui/const-generics/mgca/double-inline-const.rs index 9bfbd1819c695..0528fdbac7928 100644 --- a/tests/ui/const-generics/mgca/double-inline-const.rs +++ b/tests/ui/const-generics/mgca/double-inline-const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] struct S; diff --git a/tests/ui/const-generics/mgca/double-inline-const.stderr b/tests/ui/const-generics/mgca/double-inline-const.stderr index c0ae0392562a2..846ef73ff7793 100644 --- a/tests/ui/const-generics/mgca/double-inline-const.stderr +++ b/tests/ui/const-generics/mgca/double-inline-const.stderr @@ -9,7 +9,7 @@ note: not a concrete type | LL | impl S { | ^^^^ - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/double-wrapped-path-not-accidentally-stabilized.stderr b/tests/ui/const-generics/mgca/double-wrapped-path-not-accidentally-stabilized.stderr index aecb2b6681b43..78663c8cfc855 100644 --- a/tests/ui/const-generics/mgca/double-wrapped-path-not-accidentally-stabilized.stderr +++ b/tests/ui/const-generics/mgca/double-wrapped-path-not-accidentally-stabilized.stderr @@ -6,7 +6,7 @@ LL | f::<{ { N } }>(); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.rs b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.rs index 0ee2b4eb45f62..a78c7df160847 100644 --- a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.rs +++ b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr index 511c888ee24f0..89006708b86c8 100644 --- a/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr +++ b/tests/ui/const-generics/mgca/early-bound-param-lt-bad.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | T: Trait | ^^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.rs b/tests/ui/const-generics/mgca/explicit_anon_consts.rs index 3c7c1da90ed39..956ab43a1fdd7 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.rs +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.rs @@ -1,4 +1,4 @@ -#![feature(generic_const_items, min_generic_const_args)] +#![feature(generic_const_items, gca_min_const_items)] #![expect(incomplete_features)] // library crates exercise weirder code paths around // DefIds which were created for const args. diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr index ad533df5138f5..39747b074550e 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts.stderr +++ b/tests/ui/const-generics/mgca/explicit_anon_consts.stderr @@ -40,7 +40,7 @@ error: generic parameters may not be used in const operations LL | const ITEM3: usize = gca!(const { N }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:61:31 @@ -48,7 +48,7 @@ error: generic parameters may not be used in const operations LL | T3: Trait, | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:71:58 @@ -56,7 +56,7 @@ error: generic parameters may not be used in const operations LL | struct Default3; | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:30:27 @@ -64,7 +64,7 @@ error: generic parameters may not be used in const operations LL | let _3 = [(); const { N }]; | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:35:26 @@ -72,7 +72,7 @@ error: generic parameters may not be used in const operations LL | let _6: [(); const { N }] = todo!(); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:13:41 @@ -80,7 +80,7 @@ error: generic parameters may not be used in const operations LL | type Adt3 = Foo; | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/explicit_anon_consts.rs:21:42 @@ -88,7 +88,7 @@ error: generic parameters may not be used in const operations LL | type Arr3 = [(); const { N }]; | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 13 previous errors diff --git a/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs b/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs index f5e07d1891f40..a38430b49f4fd 100644 --- a/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs +++ b/tests/ui/const-generics/mgca/explicit_anon_consts_literals_hack.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, adt_const_params)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/mgca/free-const-recursive.rs b/tests/ui/const-generics/mgca/free-const-recursive.rs index 3fdeb37aa5d5d..54e55772e1ef3 100644 --- a/tests/ui/const-generics/mgca/free-const-recursive.rs +++ b/tests/ui/const-generics/mgca/free-const-recursive.rs @@ -4,9 +4,9 @@ // Regression test for -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] -#![cfg_attr(gca, feature(generic_const_args))] +#![cfg_attr(gca, feature(gca_const_items))] use std::gca; diff --git a/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs b/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs index b03bbb7faacc3..b8ac0c86f51cb 100644 --- a/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs +++ b/tests/ui/const-generics/mgca/gca-macro-correct-rib.rs @@ -1,5 +1,5 @@ //! make sure TyKind::GcaMacro resolves properly with the correct ribs and doesn't ICE -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs b/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs index 1f4d302110490..324c0d417f1d5 100644 --- a/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs +++ b/tests/ui/const-generics/mgca/gca-macro-feature-gate.rs @@ -1,5 +1,5 @@ fn foo(_: [(); std::gca!(N)]) {} -//~^ ERROR use of unstable library feature `min_generic_const_args` +//~^ ERROR use of unstable library feature `gca_min_const_items` //~| ERROR expected expression, found `gca!()` constant //~| ERROR generic parameters may not be used in const operations fn main() {} diff --git a/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr b/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr index 70586b9b288b4..2a9a4cb0fe23c 100644 --- a/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr +++ b/tests/ui/const-generics/mgca/gca-macro-feature-gate.stderr @@ -1,11 +1,11 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/gca-macro-feature-gate.rs:1:32 | LL | fn foo(_: [(); std::gca!(N)]) {} | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: generic parameters may not be used in const operations @@ -16,7 +16,7 @@ LL | fn foo(_: [(); std::gca!(N)]) {} | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: expected expression, found `gca!()` constant --> $DIR/gca-macro-feature-gate.rs:1:32 diff --git a/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs index 155626ad9d47f..a234c3ad70fc0 100644 --- a/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs +++ b/tests/ui/const-generics/mgca/gca-macro-infer-as-type.rs @@ -1,6 +1,6 @@ //! `gca!(_)` used to be allowed to infer to a type as a compiler implementation quirk. Since it //! uses explicit const argument syntax, it is now rejected when passed as a type argument -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs index 518fc63d68bb9..3ca7243c97a63 100644 --- a/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs +++ b/tests/ui/const-generics/mgca/gca-macro-multiple-exprs.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; struct S; fn foo(_: S) {} diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs index 4f71ad857cf5a..9642a066ad32b 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(adt_const_params, unsized_const_params)] use std::gca; #[derive(PartialEq, Eq, std::marker::ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs index 94782da82f150..f89dd4b87f32a 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index fad1703e3bfee..009722fbe93a5 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -1,6 +1,6 @@ //! Regression test for #160553 (used to ICE) #![allow(incomplete_features)] -#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] #![feature(generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs index eb32077dcfaca..075237a2094b5 100644 --- a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, min_generic_const_args, generic_const_parameter_types)] +#![feature(min_adt_const_params, gca_min_const_items, generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index 55443874a36d1..aecd2b81b1c02 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -4,7 +4,7 @@ adt_const_params, generic_const_items, generic_const_parameter_types, - min_generic_const_args, + gca_min_const_items, const_param_ty_trait )] diff --git a/tests/ui/const-generics/mgca/higher-ranked-lts-bad.rs b/tests/ui/const-generics/mgca/higher-ranked-lts-bad.rs index 368644b641dff..15a565df39f9a 100644 --- a/tests/ui/const-generics/mgca/higher-ranked-lts-bad.rs +++ b/tests/ui/const-generics/mgca/higher-ranked-lts-bad.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/higher-ranked-lts-good.rs b/tests/ui/const-generics/mgca/higher-ranked-lts-good.rs index 5b455bb1e71e6..e6eef04cc8082 100644 --- a/tests/ui/const-generics/mgca/higher-ranked-lts-good.rs +++ b/tests/ui/const-generics/mgca/higher-ranked-lts-good.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/infer-vars-in-const-args-conflicting.rs b/tests/ui/const-generics/mgca/infer-vars-in-const-args-conflicting.rs index 7baf7c23cc42b..51f504ab141b6 100644 --- a/tests/ui/const-generics/mgca/infer-vars-in-const-args-conflicting.rs +++ b/tests/ui/const-generics/mgca/infer-vars-in-const-args-conflicting.rs @@ -6,8 +6,8 @@ #![allow(incomplete_features)] #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, generic_const_parameter_types )] diff --git a/tests/ui/const-generics/mgca/infer-vars-in-const-args-correct.rs b/tests/ui/const-generics/mgca/infer-vars-in-const-args-correct.rs index dfa1ae436aa7a..b52bb74d9be90 100644 --- a/tests/ui/const-generics/mgca/infer-vars-in-const-args-correct.rs +++ b/tests/ui/const-generics/mgca/infer-vars-in-const-args-correct.rs @@ -9,8 +9,8 @@ #![allow(incomplete_features)] #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, generic_const_parameter_types, unsized_const_params )] diff --git a/tests/ui/const-generics/mgca/inherent-alias-default.rs b/tests/ui/const-generics/mgca/inherent-alias-default.rs index 2ef400454a195..74f494ecf2496 100644 --- a/tests/ui/const-generics/mgca/inherent-alias-default.rs +++ b/tests/ui/const-generics/mgca/inherent-alias-default.rs @@ -3,7 +3,7 @@ //! the generic args are in Self format at that point, not in impl format, so the result can't be //! used with the Self-format args. However, it does not instantiate the result, it just does //! ensure_ok(). This test just makes sure that codepath is hit in tests. -#![feature(min_generic_const_args, inherent_associated_types)] +#![feature(gca_min_const_items, inherent_associated_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/inherent-const-gating.rs b/tests/ui/const-generics/mgca/inherent-const-gating.rs index f4328435dc578..5b1d458c65884 100644 --- a/tests/ui/const-generics/mgca/inherent-const-gating.rs +++ b/tests/ui/const-generics/mgca/inherent-const-gating.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] struct S; diff --git a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs index e22ccf3480650..69c45462fb011 100644 --- a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs +++ b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs @@ -1,7 +1,7 @@ #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, unsized_const_params )] #![allow(incomplete_features)] diff --git a/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs index 0b0f30fd5b9fe..dd096a5d665cd 100644 --- a/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs +++ b/tests/ui/const-generics/mgca/invalid-gca-macro-owner-issue-159172.rs @@ -1,5 +1,5 @@ //@ revisions: ty expr -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/late-bound-param-lt-bad.rs b/tests/ui/const-generics/mgca/late-bound-param-lt-bad.rs index 5c57bdfb9024e..b7928a9a85ad4 100644 --- a/tests/ui/const-generics/mgca/late-bound-param-lt-bad.rs +++ b/tests/ui/const-generics/mgca/late-bound-param-lt-bad.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/macro-const-arg-infer.rs b/tests/ui/const-generics/mgca/macro-const-arg-infer.rs index 010b1c240e2a6..c5180fa596162 100644 --- a/tests/ui/const-generics/mgca/macro-const-arg-infer.rs +++ b/tests/ui/const-generics/mgca/macro-const-arg-infer.rs @@ -1,5 +1,5 @@ //! Regression test for https://github.com/rust-lang/rust/issues/153198 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/missing_generic_params.rs b/tests/ui/const-generics/mgca/missing_generic_params.rs index 2c28b0f038e6a..c370f34228888 100644 --- a/tests/ui/const-generics/mgca/missing_generic_params.rs +++ b/tests/ui/const-generics/mgca/missing_generic_params.rs @@ -7,7 +7,7 @@ // is only possible within bodies. So a delayed // bug was generated with no error ever reported. -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] trait Trait {} impl Trait for [(); N] {} diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs index b4214f5f74e89..995f715984d54 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs @@ -2,7 +2,7 @@ //! things that must be an anon const, are currently less than ideal. This test merely asserts the //! current (bad) state of diagnostics, so we can track improvements over time. -#![feature(min_generic_const_args, min_adt_const_params)] +#![feature(gca_min_const_items, min_adt_const_params)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr index 920143d33626f..4d5f071037f97 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | f::<{ (N, 1 + 1) }>(); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/multi_braced_gca_macro.rs b/tests/ui/const-generics/mgca/multi_braced_gca_macro.rs index ecf6bba056a1a..ff659659ece61 100644 --- a/tests/ui/const-generics/mgca/multi_braced_gca_macro.rs +++ b/tests/ui/const-generics/mgca/multi_braced_gca_macro.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] struct Foo; diff --git a/tests/ui/const-generics/mgca/negated-literal.rs b/tests/ui/const-generics/mgca/negated-literal.rs index a7651822b0a83..4c23cc3f73f85 100644 --- a/tests/ui/const-generics/mgca/negated-literal.rs +++ b/tests/ui/const-generics/mgca/negated-literal.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(adt_const_params, min_generic_const_args)] +#![feature(adt_const_params, gca_min_const_items)] #![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs index d136668b9f90f..4efceb48c4c3f 100644 --- a/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs +++ b/tests/ui/const-generics/mgca/non-local-const-without-type_const.rs @@ -1,6 +1,6 @@ // Just a test of the error message (it's different for non-local consts) //@ aux-build:non_local_const.rs -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] extern crate non_local_const; fn main() { diff --git a/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs b/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs index d691aaaa6cf88..5a0f61463d348 100644 --- a/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs +++ b/tests/ui/const-generics/mgca/none-as-usize-const-arg.rs @@ -1,7 +1,7 @@ // Regression test for https://github.com/rust-lang/rust/issues/150969 #![feature(generic_const_exprs)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index 80833153bd469..c5f3a6caeb112 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,7 +1,7 @@ #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, unsized_const_params )] #![expect(incomplete_features)] diff --git a/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs b/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs index 71112d632b5d8..bc8ae3f7b8b7a 100644 --- a/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs +++ b/tests/ui/const-generics/mgca/opaque-ty-assoc-const-equality-117923.rs @@ -1,6 +1,6 @@ //! Regression test for . //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features, dead_code)] use std::gca; diff --git a/tests/ui/const-generics/mgca/paren.rs b/tests/ui/const-generics/mgca/paren.rs index df60c06531755..18738c0f515fb 100644 --- a/tests/ui/const-generics/mgca/paren.rs +++ b/tests/ui/const-generics/mgca/paren.rs @@ -1,6 +1,6 @@ //@ check-pass //! See also: tests/ui/const-generics/paren.rs -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs index 12a1feefeeac0..6888a45c3bd3f 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs @@ -2,7 +2,7 @@ //@ edition: 2024 #![allow(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, core::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/projection-const-recursive.rs b/tests/ui/const-generics/mgca/projection-const-recursive.rs index 4a4b0c918e80a..ec0bdffcce16a 100644 --- a/tests/ui/const-generics/mgca/projection-const-recursive.rs +++ b/tests/ui/const-generics/mgca/projection-const-recursive.rs @@ -3,7 +3,7 @@ // Regression test for -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/projection-error.rs b/tests/ui/const-generics/mgca/projection-error.rs index 656416d31a3e1..0c570b983da91 100644 --- a/tests/ui/const-generics/mgca/projection-error.rs +++ b/tests/ui/const-generics/mgca/projection-error.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] // Regression test for #140642. Test that normalizing const aliases diff --git a/tests/ui/const-generics/mgca/resolution-with-inherent-associated-types.rs b/tests/ui/const-generics/mgca/resolution-with-inherent-associated-types.rs index 60d6858e88b27..aeddc7322d2f3 100644 --- a/tests/ui/const-generics/mgca/resolution-with-inherent-associated-types.rs +++ b/tests/ui/const-generics/mgca/resolution-with-inherent-associated-types.rs @@ -4,7 +4,7 @@ //@compile-flags: --crate-type=lib #![expect(incomplete_features)] -#![feature(inherent_associated_types, min_generic_const_args, macroless_generic_const_args)] +#![feature(inherent_associated_types, gca_min_const_items, gca_macroless_args)] trait Trait {} struct Struct; diff --git a/tests/ui/const-generics/mgca/selftyalias-containing-param.rs b/tests/ui/const-generics/mgca/selftyalias-containing-param.rs index 5ab39799078fa..085a7fed0c7a2 100644 --- a/tests/ui/const-generics/mgca/selftyalias-containing-param.rs +++ b/tests/ui/const-generics/mgca/selftyalias-containing-param.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] struct S([(); N]); diff --git a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr index 26e7b495b4406..9b1cc7d43d80a 100644 --- a/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr +++ b/tests/ui/const-generics/mgca/selftyalias-containing-param.stderr @@ -9,7 +9,7 @@ note: not a concrete type | LL | impl S { | ^^^^ - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/selftyparam.rs b/tests/ui/const-generics/mgca/selftyparam.rs index 58433405b8ca0..21215d89e8aa3 100644 --- a/tests/ui/const-generics/mgca/selftyparam.rs +++ b/tests/ui/const-generics/mgca/selftyparam.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Tr { diff --git a/tests/ui/const-generics/mgca/selftyparam.stderr b/tests/ui/const-generics/mgca/selftyparam.stderr index 11e23efb4a127..1235009465f89 100644 --- a/tests/ui/const-generics/mgca/selftyparam.stderr +++ b/tests/ui/const-generics/mgca/selftyparam.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | fn foo() -> [(); const { let _: Self; 1 }]; | ^^^^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/serialized-direct-const-with-anon-const-body.rs b/tests/ui/const-generics/mgca/serialized-direct-const-with-anon-const-body.rs index 985e14fddb676..de742379f4afa 100644 --- a/tests/ui/const-generics/mgca/serialized-direct-const-with-anon-const-body.rs +++ b/tests/ui/const-generics/mgca/serialized-direct-const-with-anon-const-body.rs @@ -8,7 +8,7 @@ //! *another*, unrelated, anon const). This test checks that case, a directly-represented //! fake-anon-const directly containing another anon const. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] extern crate anon_const_def_id_on_const_arg_with_anon; fn main() { diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs index 706b880680fe2..9a4d4ca05be33 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs @@ -1,6 +1,6 @@ //! regression test for #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] fn foo() { [0; size_of::<*mut T>()]; diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index e28cde6f63342..1abfff9518f44 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -16,7 +16,7 @@ error: generic parameters may not be used in const operations LL | [0; const { size_of::<*mut T>() }]; | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/static-const-arg.rs b/tests/ui/const-generics/mgca/static-const-arg.rs index cc97267b4726e..db4518904dff5 100644 --- a/tests/ui/const-generics/mgca/static-const-arg.rs +++ b/tests/ui/const-generics/mgca/static-const-arg.rs @@ -1,8 +1,8 @@ // Regression test for #132986. -// FIXME(min_generic_const_args): using statics as direct const arguments should error instead of +// FIXME(gca_min_const_items): using statics as direct const arguments should error instead of // ICEing until const eval can evaluate statics to valtrees for const generics. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs index e8f4a806e3847..8d3392ea04880 100644 --- a/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs +++ b/tests/ui/const-generics/mgca/struct-ctor-in-array-len.rs @@ -1,11 +1,11 @@ // Regression test for https://github.com/rust-lang/rust/issues/141738 // // Using a struct constructor as an array repeat count with -// `min_generic_const_args` used to ICE with "unexpected `DefKind` +// `gca_min_const_items` used to ICE with "unexpected `DefKind` // for const alias to resolve to: Ctor(Struct, Const)". // It should now produce a proper type error. -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] struct S; diff --git a/tests/ui/const-generics/mgca/struct_expr_with_macros.rs b/tests/ui/const-generics/mgca/struct_expr_with_macros.rs index b59a730664888..22763dc1b8528 100644 --- a/tests/ui/const-generics/mgca/struct_expr_with_macros.rs +++ b/tests/ui/const-generics/mgca/struct_expr_with_macros.rs @@ -3,7 +3,7 @@ // Test that the def collector makes `AnonConst`s not `InlineConst`s even // when the const block is obscured via macros. -#![feature(min_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, adt_const_params)] #![expect(incomplete_features)] macro_rules! const_block { diff --git a/tests/ui/const-generics/mgca/suggest-direct-const.fixed b/tests/ui/const-generics/mgca/suggest-direct-const.fixed index 044d875f1b4bb..871e76da217cf 100644 --- a/tests/ui/const-generics/mgca/suggest-direct-const.fixed +++ b/tests/ui/const-generics/mgca/suggest-direct-const.fixed @@ -1,6 +1,6 @@ //! Regression test for //@ run-rustfix -#![feature(min_generic_const_args, inherent_associated_types)] +#![feature(gca_min_const_items, inherent_associated_types)] #![allow(dead_code)] mod impl_item { diff --git a/tests/ui/const-generics/mgca/suggest-direct-const.rs b/tests/ui/const-generics/mgca/suggest-direct-const.rs index e4f394e9c18bd..09abdcc7a713d 100644 --- a/tests/ui/const-generics/mgca/suggest-direct-const.rs +++ b/tests/ui/const-generics/mgca/suggest-direct-const.rs @@ -1,6 +1,6 @@ //! Regression test for //@ run-rustfix -#![feature(min_generic_const_args, inherent_associated_types)] +#![feature(gca_min_const_items, inherent_associated_types)] #![allow(dead_code)] mod impl_item { diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs index bb0349ccb604a..f14309f7492f4 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -1,7 +1,7 @@ // This test ensures proper diagnostics emission during HIR ty lowering // See https://github.com/rust-lang/rust/issues/153254 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs b/tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs index 62be08195bb2c..e9b4da9eeaa4b 100644 --- a/tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs +++ b/tests/ui/const-generics/mgca/synth-gen-arg-ice-158152.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] trait A {} trait Trait {} diff --git a/tests/ui/const-generics/mgca/trait-assoc-fn-as-const-arg.rs b/tests/ui/const-generics/mgca/trait-assoc-fn-as-const-arg.rs index 167f60bf1bbf6..907394cc37769 100644 --- a/tests/ui/const-generics/mgca/trait-assoc-fn-as-const-arg.rs +++ b/tests/ui/const-generics/mgca/trait-assoc-fn-as-const-arg.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] // Regression test for #138088. trait Bar { diff --git a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs index c769ea0dc4d01..da66ce8195d0f 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] #![allow(dead_code)] diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs index bd9d77eee3a85..42ebe44172b05 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 481afef0ee4e4..925572c27cb0b 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -10,7 +10,7 @@ error: generic parameters may not be used in const operations LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index abe225e3f9291..db158f3f38b00 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs b/tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs index 9d4067c08ba18..2f2b2229cf8c5 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_in_array_len.rs @@ -1,6 +1,6 @@ //! Regression test for -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] pub struct S(); diff --git a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs index 97c5b294798a4..096f56d9512a8 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs index 4593780c14219..6a5c28bca6898 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs @@ -1,5 +1,5 @@ //@ run-pass -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs index 3f221db5d6ec5..50abdd97e908f 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] struct Y { diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index ea0edad9e673f..2b39a8b585faf 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, adt_const_params, unsized_const_params)] +#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index 045b9dd790919..e6f004b2f9d68 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -22,7 +22,7 @@ error: generic parameters may not be used in const operations LL | takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 4 previous errors diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs index e684e34792070..2b67665d7281b 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs @@ -1,8 +1,8 @@ //@ check-pass #![feature( - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, adt_const_params, unsized_const_params )] diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs index 87accb01c2912..780b757c0df1c 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] pub fn takes_nested_tuple() { diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index b4e664e1ca680..8c4f64adf34dc 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args, adt_const_params, unsized_const_params)] +#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs index 753185b35f0b3..7d8a1a1264bd9 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] // Regression test for an ICE in privacy checking while walking the `T` qself // of `T::ASSOC` inside a tuple const argument. diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs index 95b0d836e53fc..e67a5a0a72e54 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -2,8 +2,8 @@ #![expect(incomplete_features)] #![feature( adt_const_params, - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, unsized_const_params )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs index d41110e594514..2b178dd7304e1 100644 --- a/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs +++ b/tests/ui/const-generics/mgca/type-const-assoc-const-without-body.rs @@ -1,6 +1,6 @@ //@ needs-rustc-debug-assertions -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type-const-associated-default.rs b/tests/ui/const-generics/mgca/type-const-associated-default.rs index f2591248269cc..4f3742450dbdc 100644 --- a/tests/ui/const-generics/mgca/type-const-associated-default.rs +++ b/tests/ui/const-generics/mgca/type-const-associated-default.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; trait Trait { diff --git a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs index 774cab562cb61..67d1b765a9b9a 100644 --- a/tests/ui/const-generics/mgca/type-const-ctor-148953.rs +++ b/tests/ui/const-generics/mgca/type-const-ctor-148953.rs @@ -7,7 +7,7 @@ //@ check-pass -#![feature(min_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, adt_const_params)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs index 3b76abd2edc3c..79e05a7cdbc1b 100644 --- a/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-anon-const-mismatch.rs @@ -1,6 +1,6 @@ //@ compile-flags: -Zvalidate-mir -Znext-solver -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs index f49ac09ea3fcc..4338cae6e14a2 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-type-mismatch.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) diff --git a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs index 509bf3debc878..46523341928a2 100644 --- a/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs +++ b/tests/ui/const-generics/mgca/type-const-free-value-used-in-body.rs @@ -1,6 +1,6 @@ // Regression test for https://github.com/rust-lang/rust/issues/154748 and https://github.com/rust-lang/rust/issues/154750 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] //@ compile-flags: --emit=mir diff --git a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs index 0b83889ec764d..1f33de65a690f 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs +++ b/tests/ui/const-generics/mgca/type-const-inherent-assoc-const-without-body.rs @@ -1,6 +1,6 @@ //@ needs-rustc-debug-assertions -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] impl S { //~ ERROR cannot find type `S` in this scope diff --git a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs index 3a0fdd6bfd0ea..d772f36cd12fe 100644 --- a/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-inherent-value-type-mismatch.rs @@ -5,7 +5,7 @@ //@[next] compile-flags: -Znext-solver //@ compile-flags: -Zvalidate-mir -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type-const-suggestion.rs b/tests/ui/const-generics/mgca/type-const-suggestion.rs index 036d16b0e529d..64e8f04411cb2 100644 --- a/tests/ui/const-generics/mgca/type-const-suggestion.rs +++ b/tests/ui/const-generics/mgca/type-const-suggestion.rs @@ -1,6 +1,6 @@ //! Regression test for . -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs index 1f921960710c5..1d2edb8bc730b 100644 --- a/tests/ui/const-generics/mgca/type-const-used-in-trait.rs +++ b/tests/ui/const-generics/mgca/type-const-used-in-trait.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs index 0a9f90e90de7f..b81f672190c6f 100644 --- a/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/type-const-value-type-mismatch.rs @@ -5,7 +5,7 @@ //@[next] compile-flags: -Znext-solver //@ compile-flags: -Zvalidate-mir -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_as_const_in_array_len.rs b/tests/ui/const-generics/mgca/type_as_const_in_array_len.rs index 398bcb16aa621..1c4a15a1880e5 100644 --- a/tests/ui/const-generics/mgca/type_as_const_in_array_len.rs +++ b/tests/ui/const-generics/mgca/type_as_const_in_array_len.rs @@ -1,6 +1,6 @@ //! Regression test for -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] #![expect(incomplete_features)] struct B(Box<[u8; C]>); diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs index 421b6b4cb5993..46c661cfb96ce 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -1,8 +1,8 @@ // Regression test for https://github.com/rust-lang/rust/issues/154632 #![feature(generic_const_exprs)] -#![feature(min_generic_const_args)] -#![feature(macroless_generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_macroless_args)] #![feature(generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-array-return.rs b/tests/ui/const-generics/mgca/type_const-array-return.rs index ed27f0df8599b..384b06a3479b6 100644 --- a/tests/ui/const-generics/mgca/type_const-array-return.rs +++ b/tests/ui/const-generics/mgca/type_const-array-return.rs @@ -1,7 +1,7 @@ //@ check-pass // This test should compile without an ICE. #![expect(incomplete_features)] -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index d8c1627858257..80293325d8800 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -1,7 +1,7 @@ //@ revisions: nogate gate //@ [gate] check-pass #![expect(incomplete_features)] -#![feature(adt_const_params, unsized_const_params, min_generic_const_args, generic_const_items)] +#![feature(adt_const_params, unsized_const_params, gca_min_const_items, generic_const_items)] #![cfg_attr(gate, feature(generic_const_parameter_types))] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs index 7f82050044fad..80fd1e69a8e6c 100644 --- a/tests/ui/const-generics/mgca/type_const-incemental-compile.rs +++ b/tests/ui/const-generics/mgca/type_const-incemental-compile.rs @@ -4,7 +4,7 @@ // This lead to collector.rs to try and evaluate a type_const // which will fail since they do not have bodies. #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs index 32d052204ee27..16c5006b09ee1 100644 --- a/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-inherent-const-omitted-type.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs index 620c49cc6fe0f..b1b2b02290c72 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-type-incremental.rs @@ -1,7 +1,7 @@ //! Regression test for //! //@ incremental -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs index d4169868903b2..74ebd058bc2e5 100644 --- a/tests/ui/const-generics/mgca/type_const-mismatched-types.rs +++ b/tests/ui/const-generics/mgca/type_const-mismatched-types.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs index bc26ee967f573..0df41ed571ff3 100644 --- a/tests/ui/const-generics/mgca/type_const-not-constparamty.rs +++ b/tests/ui/const-generics/mgca/type_const-not-constparamty.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs index ce6ca6cf01bf0..80b687c3f1ff6 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr index 545675ead06a5..290c2da0007a9 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic-expr.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | const FREE1: usize = gca!(const { std::mem::size_of::() }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic-expr.rs:9:51 @@ -12,7 +12,7 @@ error: generic parameters may not be used in const operations LL | const FREE2: usize = gca!(const { I + 1 }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs index 59898c76f4e78..905d180d2d568 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args, generic_const_items)] +#![feature(gca_min_const_items, generic_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr index 4eb207e110fdb..a1bb1578afa4c 100644 --- a/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr +++ b/tests/ui/const-generics/mgca/type_const-on-generic_expr-2.stderr @@ -4,7 +4,7 @@ error: generic parameters may not be used in const operations LL | const N1: usize = gca!(const { std::mem::size_of::() }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:20:52 @@ -12,7 +12,7 @@ error: generic parameters may not be used in const operations LL | const N2: usize = gca!(const { I + 1 }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/type_const-on-generic_expr-2.rs:22:40 @@ -20,7 +20,7 @@ error: generic parameters may not be used in const operations LL | const N3: usize = gca!(const { 2 & X }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 3 previous errors diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs index 5a716807fc3e4..395c7356b73b1 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl-omitted-type.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs index f536e810348d8..4f728466f0016 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-impl.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-impl.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs index 687adf8371272..ecd4a2ad9acc9 100644 --- a/tests/ui/const-generics/mgca/type_const-only-in-trait.rs +++ b/tests/ui/const-generics/mgca/type_const-only-in-trait.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-pub.rs b/tests/ui/const-generics/mgca/type_const-pub.rs index 9499e7e952384..d58d22a2d90e7 100644 --- a/tests/ui/const-generics/mgca/type_const-pub.rs +++ b/tests/ui/const-generics/mgca/type_const-pub.rs @@ -3,7 +3,7 @@ // This is because reachability also tried to evaluate the #[type_const] which // requires the item have a body. #[type_const] do not have bodies. #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-recursive.rs b/tests/ui/const-generics/mgca/type_const-recursive.rs index c7178da8f437c..0c3e1563f401e 100644 --- a/tests/ui/const-generics/mgca/type_const-recursive.rs +++ b/tests/ui/const-generics/mgca/type_const-recursive.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-use.rs b/tests/ui/const-generics/mgca/type_const-use.rs index e8900e0d4e69e..4b03442210aa1 100644 --- a/tests/ui/const-generics/mgca/type_const-use.rs +++ b/tests/ui/const-generics/mgca/type_const-use.rs @@ -1,7 +1,7 @@ //@ check-pass // This test should compile without an ICE. #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const_in_pattern.rs b/tests/ui/const-generics/mgca/type_const_in_pattern.rs index 52d824343c2a6..57ad683978c80 100644 --- a/tests/ui/const-generics/mgca/type_const_in_pattern.rs +++ b/tests/ui/const-generics/mgca/type_const_in_pattern.rs @@ -1,5 +1,5 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] #![allow(irrefutable_let_patterns)] diff --git a/tests/ui/const-generics/mgca/type_const_in_pattern_too_generic.rs b/tests/ui/const-generics/mgca/type_const_in_pattern_too_generic.rs index 891e627780d4e..7e5437f7f902c 100644 --- a/tests/ui/const-generics/mgca/type_const_in_pattern_too_generic.rs +++ b/tests/ui/const-generics/mgca/type_const_in_pattern_too_generic.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs index 9e6370c485a0b..ea884f0d81623 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.rs @@ -35,7 +35,7 @@ fn generic() { const NON_TYPE_CONST: usize = const { 1 }; const TYPE_CONST: usize = gca!(const { 1 }); -//~^ ERROR: use of unstable library feature `min_generic_const_args` [E0658] +//~^ ERROR: use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR: expected expression, found `gca!()` constant static STATIC: usize = const { 1 }; diff --git a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr index 8467c3abdc942..162e54ad08264 100644 --- a/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr +++ b/tests/ui/const-generics/mgca/unbraced_const_block_const_arg_gated.stderr @@ -1,11 +1,11 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/unbraced_const_block_const_arg_gated.rs:37:27 | LL | const TYPE_CONST: usize = gca!(const { 1 }); | ^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental @@ -15,7 +15,7 @@ LL | const PARAM_TY: Inner, | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental @@ -25,7 +25,7 @@ LL | const DEFAULT: usize = const { 1 }, | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental @@ -35,7 +35,7 @@ LL | type NormalTy = Inner; | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental @@ -45,7 +45,7 @@ LL | let _: Inner; | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: unbraced const blocks as const args are experimental @@ -55,7 +55,7 @@ LL | generic::(); | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant diff --git a/tests/ui/const-generics/mgca/unconstrained-type-params.rs b/tests/ui/const-generics/mgca/unconstrained-type-params.rs index 7b9688f53818f..f5c64d981ae3a 100644 --- a/tests/ui/const-generics/mgca/unconstrained-type-params.rs +++ b/tests/ui/const-generics/mgca/unconstrained-type-params.rs @@ -1,6 +1,6 @@ //! Regression test for https://github.com/rust-lang/rust/issues/146906 -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Trait {} diff --git a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs index 6260607d8a711..6cc57c7939240 100644 --- a/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs +++ b/tests/ui/const-generics/mgca/unexpected-fn-item-in-array.rs @@ -1,6 +1,6 @@ // Make sure we don't ICE when encountering an fn item during lowering in mGCA. -#![feature(min_generic_const_args, macroless_generic_const_args)] +#![feature(gca_min_const_items, gca_macroless_args)] trait A {} diff --git a/tests/ui/const-generics/mgca/unexpected-type-for-constructor.rs b/tests/ui/const-generics/mgca/unexpected-type-for-constructor.rs index 2cf96ac5359dd..fc8ad6067918d 100644 --- a/tests/ui/const-generics/mgca/unexpected-type-for-constructor.rs +++ b/tests/ui/const-generics/mgca/unexpected-type-for-constructor.rs @@ -2,8 +2,8 @@ //@ compile-flags: -Znext-solver=globally //@ check-fail -#![feature(macroless_generic_const_args)] -#![feature(generic_const_args, min_generic_const_args)] +#![feature(gca_macroless_args)] +#![feature(gca_const_items, gca_min_const_items)] const C_INNER: (*const u8, u8) = (None::, None::); //~^ ERROR mismatched types //~| ERROR mismatched types diff --git a/tests/ui/const-generics/mgca/unmarked-free-const.rs b/tests/ui/const-generics/mgca/unmarked-free-const.rs index 04cf63b71ed07..e22470642889c 100644 --- a/tests/ui/const-generics/mgca/unmarked-free-const.rs +++ b/tests/ui/const-generics/mgca/unmarked-free-const.rs @@ -1,6 +1,6 @@ // regression test, used to ICE -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/mgca/unused_speculative_def_id.rs b/tests/ui/const-generics/mgca/unused_speculative_def_id.rs index e617daba24b68..442682e442fdf 100644 --- a/tests/ui/const-generics/mgca/unused_speculative_def_id.rs +++ b/tests/ui/const-generics/mgca/unused_speculative_def_id.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, generic_const_exprs, generic_const_items)] +#![feature(gca_min_const_items, generic_const_exprs, generic_const_items)] #![expect(incomplete_features)] // Previously we would create a `DefId` to represent the const argument to `A` diff --git a/tests/ui/const-generics/mgca/valtree-leaf-const.rs b/tests/ui/const-generics/mgca/valtree-leaf-const.rs index e372e89fe5e50..7760c622539df 100644 --- a/tests/ui/const-generics/mgca/valtree-leaf-const.rs +++ b/tests/ui/const-generics/mgca/valtree-leaf-const.rs @@ -1,8 +1,8 @@ //@ compile-flags: -Znext-solver -#![feature(macroless_generic_const_args)] -#![feature(generic_const_args)] -#![feature(min_generic_const_args)] +#![feature(gca_macroless_args)] +#![feature(gca_const_items)] +#![feature(gca_min_const_items)] const TUPLE: (&'static str, &'static str) = ("a", true); //~^ ERROR mismatched type diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs index c2414b0fb8648..a80f602fbf96a 100644 --- a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] struct ArrWrap; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs index d0b6aa5dfab5a..f5d3c06d7bc8e 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs @@ -1,6 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(incomplete_features)] struct TakesArr; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs index 02268c4e37d7e..225d3ef226cba 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs @@ -1,6 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params, trivial_bounds)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] #![allow(incomplete_features)] trait Trait { diff --git a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs index 081e0db80997c..675cecc68f884 100644 --- a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs +++ b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, min_generic_const_args, macroless_generic_const_args)] +#![feature(min_adt_const_params, gca_min_const_items, gca_macroless_args)] struct S; diff --git a/tests/ui/const-generics/min_const_generics/complex-expression.stderr b/tests/ui/const-generics/min_const_generics/complex-expression.stderr index 96d67fb642a66..2a7d7a35fce9e 100644 --- a/tests/ui/const-generics/min_const_generics/complex-expression.stderr +++ b/tests/ui/const-generics/min_const_generics/complex-expression.stderr @@ -6,7 +6,7 @@ LL | struct Break0([u8; { N + 1 }]); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:13:40 @@ -16,7 +16,7 @@ LL | struct Break1([u8; { { N } }]); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:17:17 @@ -26,7 +26,7 @@ LL | let _: [u8; N + 1]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:22:17 @@ -36,7 +36,7 @@ LL | let _ = [0; N + 1]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:26:45 @@ -46,7 +46,7 @@ LL | struct BreakTy0(T, [u8; { size_of::<*mut T>() }]); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:29:47 @@ -56,7 +56,7 @@ LL | struct BreakTy1(T, [u8; { { size_of::<*mut T>() } }]); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/complex-expression.rs:33:32 @@ -66,7 +66,7 @@ LL | let _: [u8; size_of::<*mut T>() + 1]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item warning: cannot use constants which depend on generic parameters in types --> $DIR/complex-expression.rs:38:17 diff --git a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr index c8def64d8f2a4..7f203f8afb13b 100644 --- a/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr +++ b/tests/ui/const-generics/min_const_generics/forbid-non-static-lifetimes.stderr @@ -6,7 +6,7 @@ LL | test::<{ let _: &'a (); 3 },>(); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/forbid-non-static-lifetimes.rs:21:16 @@ -16,7 +16,7 @@ LL | [(); (|_: &'a u8| (), 0).1]; | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr index d8dd17f0c8ffe..87cac5849df89 100644 --- a/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr +++ b/tests/ui/const-generics/min_const_generics/forbid-self-no-normalize.stderr @@ -10,7 +10,7 @@ note: not a concrete type LL | impl BindsParam for ::Assoc { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr index 2350453634541..4e3cf9b6d21fe 100644 --- a/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-1.stderr @@ -6,7 +6,7 @@ LL | fn t1() -> [u8; std::mem::size_of::()]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic `Self` types are currently not permitted in anonymous constants --> $DIR/self-ty-in-const-1.rs:12:41 @@ -20,7 +20,7 @@ note: not a concrete type LL | impl Bar { | ^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr index a8aa970929d5e..8af5a4bd0d388 100644 --- a/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr +++ b/tests/ui/const-generics/min_const_generics/self-ty-in-const-2.stderr @@ -10,7 +10,7 @@ note: not a concrete type LL | impl Baz for Bar { | ^^^^^^ = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr index 11212a1b2e4ad..989378cd313aa 100644 --- a/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr +++ b/tests/ui/const-generics/outer-lifetime-in-const-generic-default.stderr @@ -6,7 +6,7 @@ LL | let x: &'a (); | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr index 534e30b7fdab5..0c8aac63dd87f 100644 --- a/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr +++ b/tests/ui/const-generics/params-in-ct-in-ty-param-lazy-norm.min.stderr @@ -12,7 +12,7 @@ LL | struct Foo()]>(T, U); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0128]: generic parameter defaults cannot reference parameters before they are declared --> $DIR/params-in-ct-in-ty-param-lazy-norm.rs:8:21 diff --git a/tests/ui/const-generics/paren.stderr b/tests/ui/const-generics/paren.stderr index fafcf126b903a..a0ee4a0683e37 100644 --- a/tests/ui/const-generics/paren.stderr +++ b/tests/ui/const-generics/paren.stderr @@ -6,7 +6,7 @@ LL | let _: [u32; (N)] = [5; _]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/paren.rs:14:21 @@ -16,7 +16,7 @@ LL | let _: [u32; { (N) }] = [5; _]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/paren.rs:15:22 @@ -26,7 +26,7 @@ LL | let _: [u32; { { N } }] = [5; _]; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/paren.rs:24:21 @@ -36,7 +36,7 @@ LL | let _: Thing<{ (N) }> = Thing; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/paren.rs:25:22 @@ -46,7 +46,7 @@ LL | let _: Thing<{ { N } }> = Thing; | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0573]: cannot find type `N` in this scope --> $DIR/paren.rs:21:19 diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr index 9c956d79a7bba..bd6a9911bbcb0 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013-no-kw.stderr @@ -5,7 +5,7 @@ LL | impl Foo for Bar { | ^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0229]: associated item constraints are not allowed here diff --git a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr index 4a4ff098dc4ba..1b9f771f0bb18 100644 --- a/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr +++ b/tests/ui/const-generics/parser-error-recovery/issue-89013.stderr @@ -17,7 +17,7 @@ LL | impl Foo for Bar { | ^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0229]: associated item constraints are not allowed here diff --git a/tests/ui/const-generics/renamed-feature-gates.rs b/tests/ui/const-generics/renamed-feature-gates.rs new file mode 100644 index 0000000000000..2fdad8a19bd24 --- /dev/null +++ b/tests/ui/const-generics/renamed-feature-gates.rs @@ -0,0 +1,21 @@ +#![feature(min_generic_const_args)] +//~^ ERROR feature has been removed +//~| NOTE feature has been removed +//~| NOTE removed in +//~| NOTE renamed to `gca_min_const_items` +#![feature(generic_const_args)] +//~^ ERROR feature has been removed +//~| NOTE feature has been removed +//~| NOTE removed in +//~| NOTE renamed to `gca_const_items` +#![feature(macroless_generic_const_args)] +//~^ ERROR feature has been removed +//~| NOTE feature has been removed +//~| NOTE removed in +//~| NOTE renamed to `gca_macroless_args` +#![feature(macroless_const_item_generic_const_args)] +//~^ ERROR feature has been removed +//~| NOTE feature has been removed +//~| NOTE removed in +//~| NOTE renamed to `gca_macroless_items` +fn main() {} diff --git a/tests/ui/const-generics/renamed-feature-gates.stderr b/tests/ui/const-generics/renamed-feature-gates.stderr new file mode 100644 index 0000000000000..b5478b7412f0e --- /dev/null +++ b/tests/ui/const-generics/renamed-feature-gates.stderr @@ -0,0 +1,39 @@ +error[E0557]: feature has been removed + --> $DIR/renamed-feature-gates.rs:1:12 + | +LL | #![feature(min_generic_const_args)] + | ^^^^^^^^^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION + = note: renamed to `gca_min_const_items` + +error[E0557]: feature has been removed + --> $DIR/renamed-feature-gates.rs:6:12 + | +LL | #![feature(generic_const_args)] + | ^^^^^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION + = note: renamed to `gca_const_items` + +error[E0557]: feature has been removed + --> $DIR/renamed-feature-gates.rs:11:12 + | +LL | #![feature(macroless_generic_const_args)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION + = note: renamed to `gca_macroless_args` + +error[E0557]: feature has been removed + --> $DIR/renamed-feature-gates.rs:16:12 + | +LL | #![feature(macroless_const_item_generic_const_args)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed + | + = note: removed in CURRENT_RUSTC_VERSION + = note: renamed to `gca_macroless_items` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0557`. diff --git a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr index 627ffb15c56a6..a0dc7043a8966 100644 --- a/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr +++ b/tests/ui/const-generics/repeat_expr_hack_gives_right_generics.stderr @@ -6,7 +6,7 @@ LL | bar::<{ [1; N] }>(); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/repeat_expr_hack_gives_right_generics.rs:22:19 @@ -16,7 +16,7 @@ LL | bar::<{ [1; { N + 1 }] }>(); | = help: const parameters may only be used as standalone arguments here, i.e. `N` = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 2 previous errors diff --git a/tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr b/tests/ui/const-generics/suggest_const_for_array.gca_const_items.stderr similarity index 100% rename from tests/ui/const-generics/suggest_const_for_array.generic_const_args.stderr rename to tests/ui/const-generics/suggest_const_for_array.gca_const_items.stderr diff --git a/tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr b/tests/ui/const-generics/suggest_const_for_array.gca_min_const_items.stderr similarity index 100% rename from tests/ui/const-generics/suggest_const_for_array.min_generic_const_args.stderr rename to tests/ui/const-generics/suggest_const_for_array.gca_min_const_items.stderr diff --git a/tests/ui/const-generics/suggest_const_for_array.rs b/tests/ui/const-generics/suggest_const_for_array.rs index b85491130c9e8..252917f644ad7 100644 --- a/tests/ui/const-generics/suggest_const_for_array.rs +++ b/tests/ui/const-generics/suggest_const_for_array.rs @@ -1,7 +1,7 @@ -//@revisions: min_generic_const_args generic_const_args regular +//@revisions: gca_min_const_items gca_const_items regular #![crate_type = "lib"] -#![cfg_attr(min_generic_const_args, feature(min_generic_const_args))] -#![cfg_attr(generic_const_args, feature(min_generic_const_args))] +#![cfg_attr(gca_min_const_items, feature(gca_min_const_items))] +#![cfg_attr(gca_const_items, feature(gca_min_const_items))] fn example() {} diff --git a/tests/ui/const-generics/type-const-ice-issue-151631.rs b/tests/ui/const-generics/type-const-ice-issue-151631.rs index 6133feba70a3b..b1f73d619e204 100644 --- a/tests/ui/const-generics/type-const-ice-issue-151631.rs +++ b/tests/ui/const-generics/type-const-ice-issue-151631.rs @@ -1,6 +1,6 @@ // issue: //@ compile-flags: -Znext-solver -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/const-generics/type-relative-path-144547.min.stderr b/tests/ui/const-generics/type-relative-path-144547.min.stderr index 798d377ea4374..28c1ade6ccce7 100644 --- a/tests/ui/const-generics/type-relative-path-144547.min.stderr +++ b/tests/ui/const-generics/type-relative-path-144547.min.stderr @@ -5,7 +5,7 @@ LL | type SupportedArray = [T; ::SUPPORTED_S | ^^^^^^^^^^^^^^ | = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/type-relative-path-144547.rs b/tests/ui/const-generics/type-relative-path-144547.rs index 35722efd17fd4..84e68437aa9b9 100644 --- a/tests/ui/const-generics/type-relative-path-144547.rs +++ b/tests/ui/const-generics/type-relative-path-144547.rs @@ -2,7 +2,7 @@ //@ revisions: min mgca //@[mgca] check-pass -#![cfg_attr(mgca, feature(min_generic_const_args, macroless_generic_const_args))] +#![cfg_attr(mgca, feature(gca_min_const_items, gca_macroless_args))] trait UnderlyingImpl { type InfoType: LevelInfo; diff --git a/tests/ui/consts/const-eval/size-of-t.stderr b/tests/ui/consts/const-eval/size-of-t.stderr index c2183dc99a7db..0265597e4016c 100644 --- a/tests/ui/consts/const-eval/size-of-t.stderr +++ b/tests/ui/consts/const-eval/size-of-t.stderr @@ -6,7 +6,7 @@ LL | let _arr: [u8; size_of::()]; | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/delegation/generics/const-type-ice-154334.rs b/tests/ui/delegation/generics/const-type-ice-154334.rs index 3d2d8ca3ed7fd..77365f4466877 100644 --- a/tests/ui/delegation/generics/const-type-ice-154334.rs +++ b/tests/ui/delegation/generics/const-type-ice-154334.rs @@ -1,7 +1,7 @@ //@ check-pass //@ compile-flags: --crate-type=lib -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(fn_delegation)] #![feature(adt_const_params)] #![feature(unsized_const_params)] diff --git a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs index cbe6cdd06df7e..f757c5efa61a6 100644 --- a/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs +++ b/tests/ui/delegation/hir-crate-items-before-lowering-ices.rs @@ -1,7 +1,7 @@ //@ revisions: ice_155125 ice_155127 ice_155128 ice_155164 ice_155202 //@[ice_155202] edition: 2018.. -#![feature(min_generic_const_args, fn_delegation)] +#![feature(gca_min_const_items, fn_delegation)] #[cfg(ice_155125)] mod ice_155125 { diff --git a/tests/ui/delegation/inside-const-body-ice-155300.rs b/tests/ui/delegation/inside-const-body-ice-155300.rs index 224f84845b354..29a926170ca3a 100644 --- a/tests/ui/delegation/inside-const-body-ice-155300.rs +++ b/tests/ui/delegation/inside-const-body-ice-155300.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(fn_delegation)] use std::gca; diff --git a/tests/ui/delegation/wrong-fn-kind-ice-159127.rs b/tests/ui/delegation/wrong-fn-kind-ice-159127.rs index e1cde084600fd..b01cfffb560a6 100644 --- a/tests/ui/delegation/wrong-fn-kind-ice-159127.rs +++ b/tests/ui/delegation/wrong-fn-kind-ice-159127.rs @@ -1,5 +1,5 @@ #![feature(fn_delegation)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr index 096755701931c..aaf92e6dc2e0e 100644 --- a/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr +++ b/tests/ui/feature-gates/feature-gate-associated_const_equality.stderr @@ -5,7 +5,7 @@ LL | fn foo>() {} | ^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-gca-const-items.rs similarity index 63% rename from tests/ui/feature-gates/feature-gate-generic-const-args.rs rename to tests/ui/feature-gates/feature-gate-gca-const-items.rs index e5bc617d96e4d..e1851ee275738 100644 --- a/tests/ui/feature-gates/feature-gate-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-gca-const-items.rs @@ -1,10 +1,10 @@ -#![feature(generic_const_items, min_generic_const_args)] +#![feature(generic_const_items, gca_min_const_items)] #![expect(incomplete_features)] use std::gca; const INC: usize = gca!(const { N + 1 }); //~^ ERROR generic parameters may not be used in const operations -//~| HELP add `#![feature(generic_const_args)]` +//~| HELP add `#![feature(gca_const_items)]` fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-gca-const-items.stderr similarity index 60% rename from tests/ui/feature-gates/feature-gate-generic-const-args.stderr rename to tests/ui/feature-gates/feature-gate-gca-const-items.stderr index 7d4c5a67c56a6..2650908e29de8 100644 --- a/tests/ui/feature-gates/feature-gate-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-gca-const-items.stderr @@ -1,10 +1,10 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-generic-const-args.rs:6:49 + --> $DIR/feature-gate-gca-const-items.rs:6:49 | LL | const INC: usize = gca!(const { N + 1 }); | ^ | - = help: add `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: add `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/feature-gates/feature-gate-macroless-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-gca-macroless-args.rs similarity index 100% rename from tests/ui/feature-gates/feature-gate-macroless-generic-const-args.rs rename to tests/ui/feature-gates/feature-gate-gca-macroless-args.rs diff --git a/tests/ui/feature-gates/feature-gate-macroless-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-gca-macroless-args.stderr similarity index 70% rename from tests/ui/feature-gates/feature-gate-macroless-generic-const-args.stderr rename to tests/ui/feature-gates/feature-gate-gca-macroless-args.stderr index 956c983894518..9dbb7108bfb4e 100644 --- a/tests/ui/feature-gates/feature-gate-macroless-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-gca-macroless-args.stderr @@ -1,21 +1,21 @@ error: generic parameters may not be used in const operations - --> $DIR/feature-gate-macroless-generic-const-args.rs:8:29 + --> $DIR/feature-gate-gca-macroless-args.rs:8:29 | LL | fn foo() -> [u8; ::ASSOC] { | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0658]: the `rustc_always_gca` attribute is an experimental feature - --> $DIR/feature-gate-macroless-generic-const-args.rs:2:7 + --> $DIR/feature-gate-gca-macroless-args.rs:2:7 | LL | #[rustc_always_gca] | ^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr b/tests/ui/feature-gates/feature-gate-gca-macroless-items.macroful.stderr similarity index 84% rename from tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr rename to tests/ui/feature-gates/feature-gate-gca-macroless-items.macroful.stderr index d49f65acd5a0e..a2e924cb94f76 100644 --- a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.macroful.stderr +++ b/tests/ui/feature-gates/feature-gate-gca-macroless-items.macroful.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/feature-gate-macroless_const_item_generic_const_args.rs:24:11 + --> $DIR/feature-gate-gca-macroless-items.rs:24:11 | LL | let a: [(); <() as Trait>::ASSOC::] | ------------------------------- expected due to this diff --git a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs b/tests/ui/feature-gates/feature-gate-gca-macroless-items.rs similarity index 71% rename from tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs rename to tests/ui/feature-gates/feature-gate-gca-macroless-items.rs index a967dffcd39af..6924ea8985ae8 100644 --- a/tests/ui/feature-gates/feature-gate-macroless_const_item_generic_const_args.rs +++ b/tests/ui/feature-gates/feature-gate-gca-macroless-items.rs @@ -3,13 +3,13 @@ //@ compile-flags: -Znext-solver #![feature( - min_generic_const_args, - generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_const_items, + gca_macroless_args, generic_const_items, )] -#![cfg_attr(macroless, feature(macroless_const_item_generic_const_args))] +#![cfg_attr(macroless, feature(gca_macroless_items))] trait Trait { const ASSOC: usize; diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs b/tests/ui/feature-gates/feature-gate-gca-min-const-items.rs similarity index 83% rename from tests/ui/feature-gates/feature-gate-min-generic-const-args.rs rename to tests/ui/feature-gates/feature-gate-gca-min-const-items.rs index 07f278f04591a..581c60db02aee 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.rs +++ b/tests/ui/feature-gates/feature-gate-gca-min-const-items.rs @@ -7,7 +7,7 @@ trait Trait { // FIXME(mgca): add suggestion for mgca to this error fn foo() -> [u8; std::gca!(::ASSOC)] { //~^ ERROR generic parameters may not be used in const operations - //~| ERROR: use of unstable library feature `min_generic_const_args` [E0658] + //~| ERROR: use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR: expected expression, found `gca!()` loop {} } diff --git a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr b/tests/ui/feature-gates/feature-gate-gca-min-const-items.stderr similarity index 69% rename from tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr rename to tests/ui/feature-gates/feature-gate-gca-min-const-items.stderr index f709affb8a819..13f24a86d25ee 100644 --- a/tests/ui/feature-gates/feature-gate-min-generic-const-args.stderr +++ b/tests/ui/feature-gates/feature-gate-gca-min-const-items.stderr @@ -1,35 +1,35 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` - --> $DIR/feature-gate-min-generic-const-args.rs:8:28 +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-min-const-items.rs:8:28 | LL | fn foo() -> [u8; std::gca!(::ASSOC)] { | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: generic parameters may not be used in const operations - --> $DIR/feature-gate-min-generic-const-args.rs:8:39 + --> $DIR/feature-gate-gca-min-const-items.rs:8:39 | LL | fn foo() -> [u8; std::gca!(::ASSOC)] { | ^ cannot perform const operation using `T` | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0658]: the `rustc_always_gca` attribute is an experimental feature - --> $DIR/feature-gate-min-generic-const-args.rs:2:7 + --> $DIR/feature-gate-gca-min-const-items.rs:2:7 | LL | #[rustc_always_gca] | ^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant - --> $DIR/feature-gate-min-generic-const-args.rs:8:28 + --> $DIR/feature-gate-gca-min-const-items.rs:8:28 | LL | fn foo() -> [u8; std::gca!(::ASSOC)] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs index 8da5824d9c49c..3c2c2cb90e52a 100644 --- a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.rs @@ -1,5 +1,5 @@ const FOO: u8 = std::gca!(10); -//~^ ERROR use of unstable library feature `min_generic_const_args` [E0658] +//~^ ERROR use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR expected expression, found `gca!()` constant trait Bar { @@ -10,7 +10,7 @@ trait Bar { impl Bar for bool { const BAR: bool = std::gca!(false); - //~^ ERROR use of unstable library feature `min_generic_const_args` [E0658] + //~^ ERROR use of unstable library feature `gca_min_const_items` [E0658] //~| ERROR expected expression, found `gca!()` constant //~| ERROR implementation of a `#[rustc_always_gca]` must have a `gca!` RHS } diff --git a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr index 3ee23f4883e05..d8a4682aa0298 100644 --- a/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr +++ b/tests/ui/feature-gates/feature-gate-mgca-type-const-syntax.stderr @@ -1,21 +1,21 @@ -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/feature-gate-mgca-type-const-syntax.rs:1:17 | LL | const FOO: u8 = std::gca!(10); | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error[E0658]: use of unstable library feature `min_generic_const_args` +error[E0658]: use of unstable library feature `gca_min_const_items` --> $DIR/feature-gate-mgca-type-const-syntax.rs:12:23 | LL | const BAR: bool = std::gca!(false); | ^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant @@ -31,7 +31,7 @@ LL | #[rustc_always_gca] | ^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: expected expression, found `gca!()` constant diff --git a/tests/ui/generic-const-items/assoc-const-bindings.rs b/tests/ui/generic-const-items/assoc-const-bindings.rs index 2e0929a56867c..794dfaba890c0 100644 --- a/tests/ui/generic-const-items/assoc-const-bindings.rs +++ b/tests/ui/generic-const-items/assoc-const-bindings.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(generic_const_items, min_generic_const_args)] +#![feature(generic_const_items, gca_min_const_items)] #![feature(adt_const_params, const_param_ty_trait, generic_const_parameter_types)] #![expect(incomplete_features)] diff --git a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs index d1b88db9466ef..e5b09c1440720 100644 --- a/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs +++ b/tests/ui/generic-const-items/assoc-const-no-infer-ice-115806.rs @@ -1,6 +1,6 @@ // ICE: assertion failed: !value.has_infer() // issue: rust-lang/rust#115806 -#![feature(adt_const_params, min_generic_const_args, unsized_const_params)] +#![feature(adt_const_params, gca_min_const_items, unsized_const_params)] #![feature(associated_type_defaults)] #![allow(incomplete_features)] diff --git a/tests/ui/generic-const-items/type-const-nested-assoc-const.rs b/tests/ui/generic-const-items/type-const-nested-assoc-const.rs index 4d91d7edc8f16..574757ddf1e18 100644 --- a/tests/ui/generic-const-items/type-const-nested-assoc-const.rs +++ b/tests/ui/generic-const-items/type-const-nested-assoc-const.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(generic_const_items, min_generic_const_args)] +#![feature(generic_const_items, gca_min_const_items)] #![allow(incomplete_features)] use std::gca; diff --git a/tests/ui/generics/param-in-ct-in-ty-param-default.stderr b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr index 71db114cb8738..9d9c9102cde5b 100644 --- a/tests/ui/generics/param-in-ct-in-ty-param-default.stderr +++ b/tests/ui/generics/param-in-ct-in-ty-param-default.stderr @@ -6,7 +6,7 @@ LL | struct Foo()]>(T, U); | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr index 2aef26cf44151..c78c3e9df86de 100644 --- a/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr +++ b/tests/ui/lifetimes/issue-64173-unused-lifetimes.stderr @@ -6,7 +6,7 @@ LL | beta: [(); foo::<&'a ()>()], | = note: lifetime parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: lifetime parameter `'s` is never used --> $DIR/issue-64173-unused-lifetimes.rs:3:12 @@ -23,7 +23,7 @@ LL | array: [(); size_of::<&Self>()], | ^^^^ | = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error[E0392]: lifetime parameter `'a` is never used --> $DIR/issue-64173-unused-lifetimes.rs:15:12 diff --git a/tests/ui/lowering/no-name-for-DefPath-issue-133426.stderr b/tests/ui/lowering/no-name-for-DefPath-issue-133426.stderr index 3d1233cdd019e..9454fbb60853a 100644 --- a/tests/ui/lowering/no-name-for-DefPath-issue-133426.stderr +++ b/tests/ui/lowering/no-name-for-DefPath-issue-133426.stderr @@ -5,7 +5,7 @@ LL | fn b(_: impl Iterator) {} | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0614]: type `!` cannot be dereferenced diff --git a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs index 8e77c40b113d9..4976961825ca1 100644 --- a/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs +++ b/tests/ui/object-lifetime/object-lifetime-default-inherent-gac.rs @@ -5,8 +5,8 @@ // FIXME: Ideally, this test would be check-pass. See below for details. #![feature( - min_generic_const_args, - macroless_generic_const_args, + gca_min_const_items, + gca_macroless_args, inherent_associated_types, generic_const_items )] diff --git a/tests/ui/parallel-rustc/fn-sig-cycle-ice-154056.rs b/tests/ui/parallel-rustc/fn-sig-cycle-ice-154056.rs index fb930ad349e0e..eb6f97855bc6a 100644 --- a/tests/ui/parallel-rustc/fn-sig-cycle-ice-154056.rs +++ b/tests/ui/parallel-rustc/fn-sig-cycle-ice-154056.rs @@ -2,7 +2,7 @@ //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(return_type_notation)] trait IntFactory { diff --git a/tests/ui/parser/recover/recover-assoc-const-constraint.stderr b/tests/ui/parser/recover/recover-assoc-const-constraint.stderr index 766acd0398d2b..c8fd3e24aab70 100644 --- a/tests/ui/parser/recover/recover-assoc-const-constraint.stderr +++ b/tests/ui/parser/recover/recover-assoc-const-constraint.stderr @@ -5,7 +5,7 @@ LL | bar::(); | ^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: associated const equality is incomplete @@ -15,7 +15,7 @@ LL | bar::(); | ^^^^^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error: aborting due to 2 previous errors diff --git a/tests/ui/resolve/issue-39559.stderr b/tests/ui/resolve/issue-39559.stderr index 71e763820a279..6f9fb8377da79 100644 --- a/tests/ui/resolve/issue-39559.stderr +++ b/tests/ui/resolve/issue-39559.stderr @@ -6,7 +6,7 @@ LL | entries: [T; D::dim()], | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 1 previous error diff --git a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs index 6db3ebceb1cff..4a1db04ca2560 100644 --- a/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs +++ b/tests/ui/sanitizer/cfi/assoc-const-projection-issue-151878.rs @@ -4,7 +4,7 @@ //@ build-pass //@ no-prefer-dynamic -#![feature(min_generic_const_args, macroless_generic_const_args, associated_type_defaults)] +#![feature(gca_min_const_items, gca_macroless_args, associated_type_defaults)] #![expect(incomplete_features)] use std::gca; diff --git a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs index 33b3aa4cd2430..0fd9673fbbd0c 100644 --- a/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs +++ b/tests/ui/specialization/overlap-due-to-unsatisfied-const-bound.rs @@ -1,6 +1,6 @@ // Regression test for #140571. The compiler used to ICE -#![feature(min_generic_const_args, specialization)] +#![feature(gca_min_const_items, specialization)] use std::gca; diff --git a/tests/ui/supertrait-shadowing/assoc-const.rs b/tests/ui/supertrait-shadowing/assoc-const.rs index 9e49004e7c836..94247f62215c8 100644 --- a/tests/ui/supertrait-shadowing/assoc-const.rs +++ b/tests/ui/supertrait-shadowing/assoc-const.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(dead_code)] use std::gca; diff --git a/tests/ui/supertrait-shadowing/common-ancestor-2.rs b/tests/ui/supertrait-shadowing/common-ancestor-2.rs index 4844b0a43aa89..6ae70524f5623 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-2.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] diff --git a/tests/ui/supertrait-shadowing/common-ancestor-3.rs b/tests/ui/supertrait-shadowing/common-ancestor-3.rs index c815919c7e318..b2fc6ca24909c 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor-3.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor-3.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] diff --git a/tests/ui/supertrait-shadowing/common-ancestor.rs b/tests/ui/supertrait-shadowing/common-ancestor.rs index e89167c9215fd..eaab705fac807 100644 --- a/tests/ui/supertrait-shadowing/common-ancestor.rs +++ b/tests/ui/supertrait-shadowing/common-ancestor.rs @@ -1,7 +1,7 @@ //@ run-pass #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![warn(resolving_to_items_shadowing_supertrait_items)] #![warn(shadowing_supertrait_items)] #![allow(dead_code)] diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs index 3462ac4e37d4d..0fd9f2804fde0 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs +++ b/tests/ui/supertrait-shadowing/no-common-ancestor-2.rs @@ -1,5 +1,5 @@ #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; use std::mem::size_of; diff --git a/tests/ui/supertrait-shadowing/no-common-ancestor.rs b/tests/ui/supertrait-shadowing/no-common-ancestor.rs index 73209c015f8f5..b66cee7db957c 100644 --- a/tests/ui/supertrait-shadowing/no-common-ancestor.rs +++ b/tests/ui/supertrait-shadowing/no-common-ancestor.rs @@ -1,5 +1,5 @@ #![feature(supertrait_item_shadowing)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::mem::size_of; diff --git a/tests/ui/supertrait-shadowing/out-of-scope.rs b/tests/ui/supertrait-shadowing/out-of-scope.rs index fc967e525dc40..6e69e0e3278ec 100644 --- a/tests/ui/supertrait-shadowing/out-of-scope.rs +++ b/tests/ui/supertrait-shadowing/out-of-scope.rs @@ -1,6 +1,6 @@ //@ run-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![allow(dead_code)] use std::mem::size_of; diff --git a/tests/ui/supertrait-shadowing/type-dependent.rs b/tests/ui/supertrait-shadowing/type-dependent.rs index b2c31b352deee..4b387c5760577 100644 --- a/tests/ui/supertrait-shadowing/type-dependent.rs +++ b/tests/ui/supertrait-shadowing/type-dependent.rs @@ -2,7 +2,7 @@ // Makes sure we can shadow with type-dependent associated item syntax. -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(supertrait_item_shadowing)] #![allow(dead_code)] diff --git a/tests/ui/traits/associated_type_bound/generic-const-args-default.rs b/tests/ui/traits/associated_type_bound/gca-min-const-items-default.rs similarity index 84% rename from tests/ui/traits/associated_type_bound/generic-const-args-default.rs rename to tests/ui/traits/associated_type_bound/gca-min-const-items-default.rs index b53d0bb359c02..b262376c9a2d8 100644 --- a/tests/ui/traits/associated_type_bound/generic-const-args-default.rs +++ b/tests/ui/traits/associated_type_bound/gca-min-const-items-default.rs @@ -1,7 +1,7 @@ //! Regression test for //@ check-pass -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait Bar {} diff --git a/tests/ui/traits/final/final-on-assoc-type-const.rs b/tests/ui/traits/final/final-on-assoc-type-const.rs index 5c248fa57a8c2..ac38243609d81 100644 --- a/tests/ui/traits/final/final-on-assoc-type-const.rs +++ b/tests/ui/traits/final/final-on-assoc-type-const.rs @@ -1,6 +1,6 @@ // This is a regression test for . #![feature(final_associated_functions)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![expect(incomplete_features)] trait Uwu { final type Ovo; diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr index 8334fdae94856..e8c1f597e0cd8 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr +++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr @@ -5,7 +5,7 @@ LL | impl Foo for T where T: Bar {} | ^^^^^^^^^ | = note: see issue #132980 for more information - = help: add `#![feature(min_generic_const_args)]` to the crate attributes to enable + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0119]: conflicting implementations of trait `Foo` for type `()` diff --git a/tests/ui/traits/next-solver/normalize-const-item-type.rs b/tests/ui/traits/next-solver/normalize-const-item-type.rs index 3b70e8718488b..bcf8933dc5d5d 100644 --- a/tests/ui/traits/next-solver/normalize-const-item-type.rs +++ b/tests/ui/traits/next-solver/normalize-const-item-type.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Znext-solver #![feature(generic_const_items)] -#![feature(min_generic_const_args)] -#![feature(generic_const_args)] +#![feature(gca_min_const_items)] +#![feature(gca_const_items)] use std::gca; use std::marker::PhantomData; diff --git a/tests/ui/transmutability/non_scalar_alignment_value.rs b/tests/ui/transmutability/non_scalar_alignment_value.rs index ffc0e186978c1..24e97a2a55356 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.rs +++ b/tests/ui/transmutability/non_scalar_alignment_value.rs @@ -1,4 +1,4 @@ -#![feature(min_generic_const_args, macroless_generic_const_args, transmutability)] +#![feature(gca_min_const_items, gca_macroless_args, transmutability)] mod assert { use std::mem::{Assume, TransmuteFrom}; diff --git a/tests/ui/transmutability/transmute-from-const-args-ice-150457.rs b/tests/ui/transmutability/transmute-from-const-args-ice-150457.rs index 8c1b709127b06..38dd85638edc0 100644 --- a/tests/ui/transmutability/transmute-from-const-args-ice-150457.rs +++ b/tests/ui/transmutability/transmute-from-const-args-ice-150457.rs @@ -1,4 +1,4 @@ -//! Ensure `TransmuteFrom` with `min_generic_const_args` doesn't ICE +//! Ensure `TransmuteFrom` with `gca_min_const_items` doesn't ICE //! during well-formedness checking. //! //! Regression test for . @@ -6,7 +6,7 @@ //@ check-pass #![feature(transmutability)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::mem::{Assume, TransmuteFrom}; diff --git a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs b/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs index 58bc4daedfcc1..6a6b0d2d6b799 100644 --- a/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs +++ b/tests/ui/type-alias/lack-of-wfcheck-gat-generic-const-args.rs @@ -3,7 +3,7 @@ //@ compile-flags: -Znext-solver=globally -#![feature(generic_const_args, min_generic_const_args)] +#![feature(gca_const_items, gca_min_const_items)] #![expect(incomplete_features)] // * dyn incompatible due to GAT diff --git a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs index afca550944ffc..12ceef3932eb1 100644 --- a/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs +++ b/tests/ui/type-alias/lack-of-wfcheck-generic-const-args.rs @@ -1,11 +1,11 @@ -// Demonstrate that generic_const_args changes the behavior for dyn trait aliases +// Demonstrate that gca_const_items changes the behavior for dyn trait aliases // with non-type associated consts: the associated const must be specified. //@ revisions: no_gca gca //@ compile-flags: -Znext-solver=globally //@ [no_gca] check-pass -#![cfg_attr(gca, feature(generic_const_args, min_generic_const_args))] +#![cfg_attr(gca, feature(gca_const_items, gca_min_const_items))] #![cfg_attr(gca, expect(incomplete_features))] type UnsatTraitBound0 = [str]; // `str: Sized` unsatisfied diff --git a/tests/ui/type-alias/recursive-lazy-type-alias-ice-152633.rs b/tests/ui/type-alias/recursive-lazy-type-alias-ice-152633.rs index 285dda667792d..b39cc02ea7151 100644 --- a/tests/ui/type-alias/recursive-lazy-type-alias-ice-152633.rs +++ b/tests/ui/type-alias/recursive-lazy-type-alias-ice-152633.rs @@ -1,9 +1,9 @@ -//! Ensure a self-referencing lazy type alias with `min_generic_const_args` +//! Ensure a self-referencing lazy type alias with `gca_min_const_items` //! doesn't ICE during normalization. //! //! Regression test for . -#![feature(checked_type_aliases, min_generic_const_args, macroless_generic_const_args)] +#![feature(checked_type_aliases, gca_min_const_items, gca_macroless_args)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr index 678a154659481..088495e408f97 100644 --- a/tests/ui/type/pattern_types/assoc_const.default.stderr +++ b/tests/ui/type/pattern_types/assoc_const.default.stderr @@ -6,7 +6,7 @@ LL | fn foo(_: pattern_type!(u32 is ::START..=::END) | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/assoc_const.rs:17:61 @@ -16,7 +16,7 @@ LL | fn foo(_: pattern_type!(u32 is ::START..=::END) | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/assoc_const.rs:20:40 @@ -26,7 +26,7 @@ LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: generic parameters may not be used in const operations --> $DIR/assoc_const.rs:20:51 @@ -36,7 +36,7 @@ LL | fn bar(_: pattern_type!(u32 is T::START..=T::END)) {} | = note: type parameters may not be used in const expressions = help: add `#![feature(generic_const_exprs)]` to allow generic const expressions - = help: alternatively, you can use `#![feature(generic_const_args)]` and extract the expression into a `type const` item + = help: alternatively, you can use `#![feature(gca_const_items)]` and extract the expression into a `type const` item error: aborting due to 4 previous errors diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs index c8ae449d13856..a155d9ade5cf3 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs @@ -1,7 +1,7 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![feature(min_generic_const_args, macroless_generic_const_args, adt_const_params)] +#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] #![expect(incomplete_features)] #![allow(dead_code)] diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout index 974ffd3b9c4e1..c2c79249a6bd4 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout @@ -3,7 +3,7 @@ #![expect(incomplete_features)] #![allow(dead_code)] -#![attr = Feature([min_generic_const_args#0, macroless_generic_const_args#0, +#![attr = Feature([gca_min_const_items#0, gca_macroless_args#0, adt_const_params#0])] extern crate std; #[attr = PreludeImport] diff --git a/tests/ui/use/import_trait_associated_item_bad.rs b/tests/ui/use/import_trait_associated_item_bad.rs index cb45004e4e335..35f57c5f15a1d 100644 --- a/tests/ui/use/import_trait_associated_item_bad.rs +++ b/tests/ui/use/import_trait_associated_item_bad.rs @@ -1,4 +1,4 @@ -#![feature(import_trait_associated_functions, min_generic_const_args, macroless_generic_const_args)] +#![feature(import_trait_associated_functions, gca_min_const_items, gca_macroless_args)] #![allow(incomplete_features)] trait Trait { From e80eea1b01431d9a1ff957b2f5b0ebba47b0963f Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Fri, 25 Sep 2026 13:04:03 +0200 Subject: [PATCH 0827/1309] rename GCA features --- CHANGELOG.md | 2 +- clippy_utils/src/consts.rs | 2 +- tests/ui/crashes/mgca-16691.rs | 2 +- tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed | 2 +- tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 37f5eb09e5247..e79efa20fd534 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -318,7 +318,7 @@ Current stable, released 2026-05-28 [#16685](https://github.com/rust-lang/rust-clippy/pull/16685) * [`nonminimal_bool`] fix ICE in `swap_binop()` by using the proper `TypeckResults` [#16659](https://github.com/rust-lang/rust-clippy/pull/16659) -* Fix ICE when using the `min_generic_const_args` incomplete feature +* Fix ICE when using the `gca_min_const_items` incomplete feature [#16692](https://github.com/rust-lang/rust-clippy/pull/16692) ### Documentation Improvements diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 890fc7cb4e947..a9d269ac83271 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -871,7 +871,7 @@ impl<'tcx> ConstEvalCtxt<'tcx> { { did }, - // TODO: revisit when feature `min_generic_const_args` is stabilized. In the meantime, + // TODO: revisit when feature `gca_min_const_items` is stabilized. In the meantime, // `TyCtxt::const_eval_resolve()` will trigger an ICE when evaluating the body of the // `type const` definition. _ if let Res::Def(DefKind::Const | DefKind::AssocConst, did) = self.typeck.qpath_res(qpath, id) diff --git a/tests/ui/crashes/mgca-16691.rs b/tests/ui/crashes/mgca-16691.rs index 554528905fc85..4da9a8b60d1a3 100644 --- a/tests/ui/crashes/mgca-16691.rs +++ b/tests/ui/crashes/mgca-16691.rs @@ -1,6 +1,6 @@ //@ check-pass #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] use std::gca; diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed index dc1d663a9393b..d887aac9c0378 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.fixed @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait AssocConstTrait { #[rustc_always_gca] diff --git a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs index 669e0fbdd3809..feeec8e421f1d 100644 --- a/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs +++ b/tests/ui/trait_duplication_in_bounds_assoc_const_eq.rs @@ -1,6 +1,6 @@ #![deny(clippy::trait_duplication_in_bounds)] #![expect(incomplete_features)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] trait AssocConstTrait { #[rustc_always_gca] From 3193a0e7a3ab162a5468cef914d6ca2f031b39b4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torbj=C3=B8rn=20Yttersian?= Date: Fri, 25 Sep 2026 13:13:03 +0200 Subject: [PATCH 0828/1309] Fix docs in core::slice - Add a comma after the conditional clause in `split_at_checked` and `split_at_mut_checked` - "equals to" -> "equals" in `swap` --- library/core/src/slice/mod.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index fa4d6d9f90946..d89d212111527 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -885,7 +885,7 @@ impl [T] { /// Swaps two elements in the slice. /// - /// If `a` equals to `b`, it's guaranteed that elements won't change value. + /// If `a` equals `b`, it's guaranteed that elements won't change value. /// /// # Arguments /// @@ -2125,7 +2125,7 @@ impl [T] { /// Divides one slice into two at an index, returning `None` if the slice is /// too short. /// - /// If `mid ≤ len` returns a pair of slices where the first will contain all + /// If `mid ≤ len`, returns a pair of slices where the first will contain all /// indices from `[0, mid)` (excluding the index `mid` itself) and the /// second will contain all indices from `[mid, len)` (excluding the index /// `len` itself). @@ -2174,7 +2174,7 @@ impl [T] { /// Divides one mutable slice into two at an index, returning `None` if the /// slice is too short. /// - /// If `mid ≤ len` returns a pair of slices where the first will contain all + /// If `mid ≤ len`, returns a pair of slices where the first will contain all /// indices from `[0, mid)` (excluding the index `mid` itself) and the /// second will contain all indices from `[mid, len)` (excluding the index /// `len` itself). From a2c55f864870b929a296a070dd1203f9674177f6 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Fri, 25 Sep 2026 08:14:22 -0400 Subject: [PATCH 0829/1309] Bump to 1.101.0 https://forge.rust-lang.org/release/process.html#bump-the-stable-version-number-friday-the-week-before --- src/version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/version b/src/version index 7a9fecd3f0ede..f19e66773133d 100644 --- a/src/version +++ b/src/version @@ -1 +1 @@ -1.100.0 +1.101.0 From 5237e38fddf1699ea6186400c17c0a32b71fb836 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2026 17:48:28 +0300 Subject: [PATCH 0830/1309] Support -Z merge-functions with gcc and add stack-protector asm tests This is a part of the stack-protector work. Adding support for merge-functions is not strictly needed, but it does prevent breakage if the GCC function merging logic changes. Not adding tests for -Z merge-functions since I don't see any such tests for the LLVM side of it. --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 11 +- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 7 +- compiler/rustc_session/src/options.rs | 1 + compiler/rustc_session/src/session.rs | 10 +- src/bootstrap/src/core/build_steps/test.rs | 6 + .../builder/cli_paths/snapshots/x_test.snap | 3 + .../snapshots/x_test_skip_coverage.snap | 3 + .../snapshots/x_test_skip_coverage_map.snap | 3 + .../snapshots/x_test_skip_coverage_run.snap | 3 + .../snapshots/x_test_skip_tests_coverage.snap | 3 + .../cli_paths/snapshots/x_test_tests.snap | 3 + .../snapshots/x_test_tests_skip_coverage.snap | 3 + src/bootstrap/src/core/builder/mod.rs | 1 + src/bootstrap/src/core/builder/tests.rs | 2 + src/tools/compiletest/src/common.rs | 1 + src/tools/compiletest/src/runtest.rs | 3 +- .../stack-protector-heuristics-effect.rs | 331 ++++++++++++++++++ 18 files changed, 384 insertions(+), 12 deletions(-) create mode 100644 tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 0628171e488b3..4850a5fc5ca31 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -9,7 +9,9 @@ use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::config::NATIVE_CPU; use rustc_session::{EarlySession, Session}; -use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector, Target}; +use rustc_target::spec::{ + Arch, MergeFunctions, RelocModel, StackProbeType, StackProtector, Target, +}; fn gcc_features_by_flags(sess: &EarlySession, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -220,6 +222,13 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { StackProtector::None => (), } + match sess.merge_functions() { + MergeFunctions::Disabled | MergeFunctions::Trampolines => { + context.add_command_line_option("-fno-ipa-icf-functions"); + } + MergeFunctions::Aliases => {} + } + match sess.target.stack_probes { StackProbeType::None => (), StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 9e37205f230ac..9cfa74ffd019d 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -120,7 +120,7 @@ unsafe fn configure_llvm(sess: &EarlySession) { add("-generate-arange-section", false); } - match sess.opts.unstable_opts.merge_functions.unwrap_or(sess.target.merge_functions) { + match sess.merge_functions() { MergeFunctions::Disabled | MergeFunctions::Trampolines => {} MergeFunctions::Aliases => { add("-mergefunc-use-aliases", false); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 147e4c43c7103..f87bfa34ddc8b 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -244,12 +244,7 @@ impl ModuleConfig { // backends (again, NVPTX). Therefore, allow targets to opt out of // the MergeFunctions pass, but otherwise keep the pass enabled (at // O2 and O3) since it can be useful for reducing code size. - merge_functions: match sess - .opts - .unstable_opts - .merge_functions - .unwrap_or(sess.target.merge_functions) - { + merge_functions: match sess.merge_functions() { MergeFunctions::Disabled => false, MergeFunctions::Trampolines | MergeFunctions::Aliases => { use config::OptLevel::*; diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..61b7d792d9a08 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2643,6 +2643,7 @@ options! { maximal_hir_to_mir_coverage: bool = (false, parse_bool, [TRACKED], "save as much information as possible about the correspondence between MIR and HIR \ as source scopes (default: no)"), + #[rustc_lint_opt_deny_field_access("use `Session::merge_functions` instead of this field")] merge_functions: Option = (None, parse_merge_functions, [TRACKED], "control the operation of the MergeFunctions LLVM pass, taking \ the same values as the target option of the same name"), diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 3b60a13b8e6f2..060e614e82180 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -28,9 +28,9 @@ use rustc_span::{RealFileName, Span, Symbol}; use rustc_structures::{CrateType, Limit}; use rustc_target::asm::InlineAsmArch; use rustc_target::spec::{ - Arch, CfgAbi, CodeModel, DebuginfoKind, Os, PanicStrategy, RelocModel, RelroLevel, - SanitizerSet, SmallDataThresholdSupport, SplitDebuginfo, StackProtector, SymbolVisibility, - Target, TargetTuple, TlsModel, apple, + Arch, CfgAbi, CodeModel, DebuginfoKind, MergeFunctions, Os, PanicStrategy, RelocModel, + RelroLevel, SanitizerSet, SmallDataThresholdSupport, SplitDebuginfo, StackProtector, + SymbolVisibility, Target, TargetTuple, TlsModel, apple, }; use crate::code_stats::CodeStats; @@ -423,6 +423,10 @@ impl EarlySession { .sanitizer .combine_with_defaults(self.target.options.default_sanitizers) } + + pub fn merge_functions(&self) -> MergeFunctions { + self.opts.unstable_opts.merge_functions.unwrap_or(self.target.merge_functions) + } } /// Some info about the backend, returned by `CodegenBackend::init` and put into the `Session`. diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index cd647eb32f515..3006fddbbe662 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -2040,6 +2040,12 @@ test!(BuildStd { default: false }); +test!(AssemblyGcc { + path: "tests/assembly-gcc", + mode: CompiletestMode::Assembly, + suite: "assembly-gcc", + default: true +}); test!(AssemblyLlvm { path: "tests/assembly-llvm", mode: CompiletestMode::Assembly, diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap index 32ed54050dc3d..787686b117cd2 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test.snap @@ -23,6 +23,9 @@ expression: test [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap index d1cdf81a14e08..879114ffc8170 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage.snap @@ -20,6 +20,9 @@ expression: test --skip=coverage [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap index df4b8a2ce1299..a30e3a2407937 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_map.snap @@ -23,6 +23,9 @@ expression: test --skip=coverage-map [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap index 75992df8aa616..12e0a3233f7ea 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_coverage_run.snap @@ -23,6 +23,9 @@ expression: test --skip=coverage-run [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap index a44052fac41f9..3b07718b8aecf 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_skip_tests_coverage.snap @@ -20,6 +20,9 @@ expression: test --skip=tests/coverage [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap index c0105510ae416..6db9443b8543c 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests.snap @@ -20,6 +20,9 @@ expression: test tests [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap index d1a90ca426918..ab4e9e6f7d997 100644 --- a/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap +++ b/src/bootstrap/src/core/builder/cli_paths/snapshots/x_test_tests_skip_coverage.snap @@ -17,6 +17,9 @@ expression: test tests --skip=coverage [Test] test::CodegenUnits targets: [aarch64-unknown-linux-gnu] - Suite(tests/codegen-units) +[Test] test::AssemblyGcc + targets: [aarch64-unknown-linux-gnu] + - Suite(tests/assembly-gcc) [Test] test::AssemblyLlvm targets: [aarch64-unknown-linux-gnu] - Suite(tests/assembly-llvm) diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0593f30946320..c221a976b2698 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -886,6 +886,7 @@ impl<'a> Builder<'a> { test::MirOpt, test::CodegenLlvm, test::CodegenUnits, + test::AssemblyGcc, test::AssemblyLlvm, test::Incremental, test::Debuginfo, diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index cc6ac39672950..dd1beb65e7fe0 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -1943,6 +1943,7 @@ mod snapshot { [test] compiletest-mir-opt 1 [test] compiletest-codegen-llvm 1 [test] compiletest-codegen-units 1 + [test] compiletest-assembly-gcc 1 [test] compiletest-assembly-llvm 1 [test] compiletest-incremental 1 [test] compiletest-debuginfo 1 @@ -2124,6 +2125,7 @@ mod snapshot { [test] compiletest-mir-opt 2 [test] compiletest-codegen-llvm 2 [test] compiletest-codegen-units 2 + [test] compiletest-assembly-gcc 2 [test] compiletest-assembly-llvm 2 [test] compiletest-incremental 2 [test] compiletest-debuginfo 2 diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 8c580d3520dfd..1968f5eb73d4e 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -60,6 +60,7 @@ impl TestMode { string_enum! { #[derive(Clone, Copy, PartialEq, Debug)] pub(crate) enum TestSuite { + AssemblyGcc => "assembly-gcc", AssemblyLlvm => "assembly-llvm", CodegenLlvm => "codegen-llvm", CodegenUnits => "codegen-units", diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index c728e56cf639d..0bb8a7003589c 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1604,7 +1604,8 @@ impl<'test> TestCx<'test> { // Exhaustively match all other suites. // Note that some suites never actually use this method, so the // return value for those suites is not necessarily meaningful. - TestSuite::AssemblyLlvm + TestSuite::AssemblyGcc + | TestSuite::AssemblyLlvm | TestSuite::BuildStd | TestSuite::CodegenLlvm | TestSuite::CodegenUnits diff --git a/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs new file mode 100644 index 0000000000000..f9ddea2afedbd --- /dev/null +++ b/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs @@ -0,0 +1,331 @@ +//@ revisions: all strong basic none missing +//@ assembly-output: emit-asm +//@ ignore-apple slightly different policy on stack protection of arrays +//@ ignore-msvc stack check code uses different function names +//@ ignore-nvptx64 stack protector is not supported +//@ ignore-wasm32-unknown-unknown +//@ [all] compile-flags: -Z stack-protector=all +//@ [strong] compile-flags: -Z stack-protector=strong +//@ [basic] compile-flags: -Z stack-protector=basic +//@ [none] compile-flags: -Z stack-protector=none +//@ compile-flags: -C opt-level=2 -Z merge-functions=disabled + +#![crate_type = "lib"] +#![allow(internal_features)] +#![feature(unsized_fn_params)] + +// CHECK-LABEL: "emptyfn" +#[no_mangle] +pub fn emptyfn() { + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "array_char" +#[no_mangle] +pub fn array_char(f: fn(*const char)) { + let a = ['c'; 1]; + let b = ['d'; 3]; + let c = ['e'; 15]; + + f(&a as *const _); + f(&b as *const _); + f(&c as *const _); + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "array_u8_1" +#[no_mangle] +pub fn array_u8_1(f: fn(*const u8)) { + let a = [0u8; 1]; + f(&a as *const _); + + // The 'strong' heuristic adds stack protection to functions with local + // array variables regardless of their size. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "array_u8_small" +#[no_mangle] +pub fn array_u8_small(f: fn(*const u8)) { + let a = [0u8; 2]; + let b = [0u8; 7]; + f(&a as *const _); + f(&b as *const _); + + // Small arrays do not lead to stack protection by the 'basic' heuristic. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "array_u8_large" +#[no_mangle] +pub fn array_u8_large(f: fn(*const u8)) { + let a = [0u8; 9]; + f(&a as *const _); + + // Since `a` is a byte array with size greater than 8, the basic heuristic + // will also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +#[derive(Copy, Clone)] +pub struct ByteSizedNewtype(u8); + +// CHECK-LABEL: "array_bytesizednewtype_9" +#[no_mangle] +pub fn array_bytesizednewtype_9(f: fn(*const ByteSizedNewtype)) { + let a = [ByteSizedNewtype(0); 9]; + f(&a as *const _); + + // Since `a` is a byte array in the GCC output, the basic heuristic will + // also protect this function. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "local_var_addr_used_indirectly" +#[no_mangle] +pub fn local_var_addr_used_indirectly(f: fn(bool)) { + let a = 5; + let a_addr = &a as *const _ as usize; + f(a_addr & 0x10 == 0); + + // This function takes the address of a local variable taken. Although this + // address is never used as a way to refer to stack memory, the `strong` + // heuristic adds stack smash protection. This is also the case in C++: + // ``` + // cat << EOF | g++ -O2 -fstack-protector-strong -S -x c++ - -o - | grep stack_chk + // #include + // void f(void (*g)(bool)) { + // int32_t x; + // g((reinterpret_cast(&x) & 0x10U) == 0); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "local_string_addr_taken" +#[no_mangle] +pub fn local_string_addr_taken(f: fn(&String)) { + let x = String::new(); + f(&x); + + // Taking the address of the local variable `x` leads to stack smash + // protection. It does not matter that the reference is not mut. + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub trait SelfByRef { + fn f(&self) -> i32; +} + +impl SelfByRef for i32 { + fn f(&self) -> i32 { + return self + 1; + } +} + +// CHECK-LABEL: "local_var_addr_taken_used_locally_only" +#[no_mangle] +pub fn local_var_addr_taken_used_locally_only(factory: fn() -> i32, sink: fn(i32)) { + let x = factory(); + let g = x.f(); + sink(g); + + // Even though the local variable conceptually has its address taken, as + // it's passed by reference to the trait function, the use of the reference + // is easily inlined. There is therefore no stack smash protection even with + // the `strong` heuristic. + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +pub struct Gigastruct { + does: u64, + not: u64, + have: u64, + array: u64, + members: u64, +} + +// CHECK-LABEL: "local_large_var_moved" +#[no_mangle] +pub fn local_large_var_moved(f: fn(Gigastruct)) { + let x = Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }; + f(x); + + // Even though the local variable conceptually doesn't have its address + // taken, it's so large that the "move" is implemented with a reference to a + // stack-local variable in the ABI. Consequently, this function *is* + // protected. This is also the case for rvalue-references in C++, + // regardless of struct size: + // ``` + // cat < + // #include + // void f(void (*g)(uint64_t&&)) { + // uint64_t x; + // g(std::move(x)); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "local_large_var_cloned" +#[no_mangle] +pub fn local_large_var_cloned(f: fn(Gigastruct)) { + f(Gigastruct { does: 0, not: 1, have: 2, array: 3, members: 4 }); + + // A new instance of `Gigastruct` is passed to `f()`, without any apparent + // connection to this stack frame. Still, since instances of `Gigastruct` + // are sufficiently large, it is allocated in the caller stack frame and + // passed as a pointer. As such, this function is *also* protected, just + // like `local_large_var_moved`. + // + // This matches clang++ behavior, but not g++ behavior. + // + // In any case, both options are fine from a specification point of view, there + // is no "user-accessible pointer", and there is no strong reason to avoid generating + // a canary in this case, since it doesn't seem to be one of the performance-critical + // cases in which avoiding generating a canary is important. + // + // ``` + // cat < + // #include + // struct Gigastruct { uint64_t a, b, c, d, e; }; + // void f(void (*g)(Gigastruct)) { + // g(Gigastruct{}); + // } + // EOF + // ``` + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +extern "C" { + // Difference between LLVM and GCC: LLVM will not generate stack protection + // for "external" calls to alloca, but gcc will. See the matching test for + // stack-protector-heuristics-effect under assembly-llvm. + // + // This is a difference in heuristics and therefore fine. + // + // Check that rustc_codegen_gcc matches gcc behavior. + + fn alloca(size: usize) -> *mut (); +} + +// CHECK-LABEL: "alloca_small_compile_time_constant_arg" +#[no_mangle] +pub fn alloca_small_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(8) }); + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "alloca_large_compile_time_constant_arg" +#[no_mangle] +pub fn alloca_large_compile_time_constant_arg(f: fn(*mut ())) { + f(unsafe { alloca(9) }); + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// CHECK-LABEL: "alloca_dynamic_arg" +#[no_mangle] +pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { + f(unsafe { alloca(n) }); + + // all: __stack_chk_fail + // strong: __stack_chk_fail + // basic: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} + +// The question then is: in what ways can Rust code generate array-`alloca` +// GCC instructions? This appears to only be generated by +// rustc_codegen_ssa::traits::Builder::array_alloca() through +// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT +// this is support for the "unsized locals" unstable feature: +// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. + +// CHECK-LABEL: "unsized_fn_param" +#[no_mangle] +pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { + let n = if l { 1 } else { 2 }; + f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from + + // Even though slices are conceptually passed by-value both into this + // function and into `f()`, this is implemented with pass-by-reference + // using a suitably constructed fat-pointer (as if the functions + // accepted &[u8]). This function therefore doesn't need dynamic array + // alloca, and is therefore not protected by the `strong` or `basic` + // heuristics. + + // all: __stack_chk_fail + // strong-NOT: __stack_chk_fail + // basic-NOT: __stack_chk_fail + // none-NOT: __stack_chk_fail + // missing-NOT: __stack_chk_fail +} From 1ff212ebb3ce2fbca5228c1f09929a77323ecda9 Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2026 17:48:28 +0300 Subject: [PATCH 0831/1309] Support -Z merge-functions with gcc and add stack-protector asm tests This is a part of the stack-protector work. Adding support for merge-functions is not strictly needed, but it does prevent breakage if the GCC function merging logic changes. Not adding tests for -Z merge-functions since I don't see any such tests for the LLVM side of it. --- src/gcc_util.rs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 0628171e488b3..4850a5fc5ca31 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -9,7 +9,9 @@ use rustc_codegen_ssa::target_features; use rustc_data_structures::smallvec::{SmallVec, smallvec}; use rustc_session::config::NATIVE_CPU; use rustc_session::{EarlySession, Session}; -use rustc_target::spec::{Arch, RelocModel, StackProbeType, StackProtector, Target}; +use rustc_target::spec::{ + Arch, MergeFunctions, RelocModel, StackProbeType, StackProtector, Target, +}; fn gcc_features_by_flags(sess: &EarlySession, features: &mut Vec) { target_features::retpoline_features_by_flags(sess, features); @@ -220,6 +222,13 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { StackProtector::None => (), } + match sess.merge_functions() { + MergeFunctions::Disabled | MergeFunctions::Trampolines => { + context.add_command_line_option("-fno-ipa-icf-functions"); + } + MergeFunctions::Aliases => {} + } + match sess.target.stack_probes { StackProbeType::None => (), StackProbeType::Inline | StackProbeType::InlineOrCall { .. } => { From c6dc51196d5d387cf44837e9d75212462fb07e4f Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2026 22:01:39 +0300 Subject: [PATCH 0832/1309] address comments by bjorn3 --- compiler/rustc_codegen_gcc/src/gcc_util.rs | 7 ++-- compiler/rustc_target/src/spec/mod.rs | 7 ++++ .../stack-protector-heuristics-effect.rs | 32 +++---------------- .../stack-protector-heuristics-effect.rs | 29 ++--------------- 4 files changed, 20 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs index 4850a5fc5ca31..90d08d13a080a 100644 --- a/compiler/rustc_codegen_gcc/src/gcc_util.rs +++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs @@ -223,10 +223,13 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { } match sess.merge_functions() { - MergeFunctions::Disabled | MergeFunctions::Trampolines => { + MergeFunctions::Disabled => { context.add_command_line_option("-fno-ipa-icf-functions"); } - MergeFunctions::Aliases => {} + // GCC always merges functions with trampolines rather than aliases, so we don't + // need to differentiate MergeFunctions::Trampolines and MergeFunctions::Aliases + // as trampolines are allowed either way. + MergeFunctions::Trampolines | MergeFunctions::Aliases => {} } match sess.target.stack_probes { diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 42d817c7daa31..2d7cd049eb61c 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -927,8 +927,15 @@ impl ToJson for SmallDataThresholdSupport { crate::target_spec_enum! { pub enum MergeFunctions { + /// Disable function merging entirely. Disabled = "disabled", + /// Allow function merging via trampolines (i.e., functions can be implemented + /// in terms of a jump to an unrelated function with identical behavior), but + /// not via object-format-level global aliases. Trampolines = "trampolines", + /// (Default) allow function merging via either trampolines or (object format + /// level) global aliases. LLVM will normally use global aliases for merging, but + /// trampolines are also permissible. Aliases = "aliases", } diff --git a/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs index f9ddea2afedbd..c8945ed96b3ee 100644 --- a/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly-gcc/stack-protector/stack-protector-heuristics-effect.rs @@ -235,7 +235,8 @@ pub fn local_large_var_cloned(f: fn(Gigastruct)) { // In any case, both options are fine from a specification point of view, there // is no "user-accessible pointer", and there is no strong reason to avoid generating // a canary in this case, since it doesn't seem to be one of the performance-critical - // cases in which avoiding generating a canary is important. + // cases in which avoiding generating a canary is important, so it seems that + // rustc should keep the clang-like behavior of generating a canary here. // // ``` // cat <::from(&s[0..n])); // slice-copy with Box::from - - // Even though slices are conceptually passed by-value both into this - // function and into `f()`, this is implemented with pass-by-reference - // using a suitably constructed fat-pointer (as if the functions - // accepted &[u8]). This function therefore doesn't need dynamic array - // alloca, and is therefore not protected by the `strong` or `basic` - // heuristics. - - // all: __stack_chk_fail - // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail - // none-NOT: __stack_chk_fail - // missing-NOT: __stack_chk_fail -} +// rustc can currently (as of 1.98) not generate variable-sized allocas, except for +// variable-sized scalable vector types, so their interaction with stack-protector +// does not need to be tested. diff --git a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs index 3728ff3adf105..56cf0035e25bf 100644 --- a/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs +++ b/tests/assembly-llvm/stack-protector/stack-protector-heuristics-effect.rs @@ -317,29 +317,6 @@ pub fn alloca_dynamic_arg(f: fn(*mut ()), n: usize) { // missing-NOT: __stack_chk_fail } -// The question then is: in what ways can Rust code generate array-`alloca` -// LLVM instructions? This appears to only be generated by -// rustc_codegen_ssa::traits::Builder::array_alloca() through -// rustc_codegen_ssa::mir::operand::OperandValue::store_unsized(). FWICT -// this is support for the "unsized locals" unstable feature: -// https://doc.rust-lang.org/unstable-book/language-features/unsized-locals.html. - -// CHECK-LABEL: unsized_fn_param{{:|\[}} -#[no_mangle] -pub fn unsized_fn_param(s: [u8], l: bool, f: fn([u8])) { - let n = if l { 1 } else { 2 }; - f(*Box::<[u8]>::from(&s[0..n])); // slice-copy with Box::from - - // Even though slices are conceptually passed by-value both into this - // function and into `f()`, this is implemented with pass-by-reference - // using a suitably constructed fat-pointer (as if the functions - // accepted &[u8]). This function therefore doesn't need dynamic array - // alloca, and is therefore not protected by the `strong` or `basic` - // heuristics. - - // all: __stack_chk_fail - // strong-NOT: __stack_chk_fail - // basic-NOT: __stack_chk_fail - // none-NOT: __stack_chk_fail - // missing-NOT: __stack_chk_fail -} +// rustc can currently (as of 1.98) not generate variable-sized allocas, except for +// variable-sized scalable vector types, so their interaction with stack-protector +// does not need to be tested. From 26c112b79ccd4d8a06996ebb32c5af3b927f1aba Mon Sep 17 00:00:00 2001 From: Ariel Ben-Yehuda Date: Thu, 24 Sep 2026 22:01:39 +0300 Subject: [PATCH 0833/1309] address comments by bjorn3 --- src/gcc_util.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/gcc_util.rs b/src/gcc_util.rs index 4850a5fc5ca31..90d08d13a080a 100644 --- a/src/gcc_util.rs +++ b/src/gcc_util.rs @@ -223,10 +223,13 @@ pub fn new_context<'gcc>(sess: &Session) -> Context<'gcc> { } match sess.merge_functions() { - MergeFunctions::Disabled | MergeFunctions::Trampolines => { + MergeFunctions::Disabled => { context.add_command_line_option("-fno-ipa-icf-functions"); } - MergeFunctions::Aliases => {} + // GCC always merges functions with trampolines rather than aliases, so we don't + // need to differentiate MergeFunctions::Trampolines and MergeFunctions::Aliases + // as trampolines are allowed either way. + MergeFunctions::Trampolines | MergeFunctions::Aliases => {} } match sess.target.stack_probes { From bf9971d353ccc52291d892e1a988b68a36ec0ad6 Mon Sep 17 00:00:00 2001 From: ltdk Date: Fri, 25 Sep 2026 08:58:22 -0400 Subject: [PATCH 0834/1309] Update mailmap for Clar Fon --- .mailmap | 3 +++ 1 file changed, 3 insertions(+) diff --git a/.mailmap b/.mailmap index 32fbff098127d..38ea8431e8814 100644 --- a/.mailmap +++ b/.mailmap @@ -144,6 +144,9 @@ Christian Poveda <31802960+christianpoveda@users.noreply.github. Christian Poveda Christian Vallentin Christoffer Buchholz +Clar Fon +Clar Fon +Clar Fon Clark Gaebel Clement Miao Clément Renault From d744bc3feb7c201d7f192fc63b358ba887913a93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 10:49:53 +0200 Subject: [PATCH 0835/1309] remove the location map Rc we can pass it by reference when we have it (loan traversal), and use the one in regioncx's LivenessValues when we don't have it already in scope (MIR dump traversal) --- compiler/rustc_borrowck/src/nll.rs | 2 +- .../src/polonius/constraints.rs | 17 +++++++--------- compiler/rustc_borrowck/src/polonius/dump.rs | 20 ++++++++++--------- compiler/rustc_borrowck/src/polonius/mod.rs | 11 ++++------ .../src/region_infer/region_context.rs | 2 +- .../rustc_borrowck/src/region_infer/values.rs | 15 +++++--------- 6 files changed, 29 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 31fa9dd2ee64e..956f3125de970 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -156,7 +156,7 @@ pub(crate) fn compute_regions<'tcx>( &universal_region_relations.universal_regions, body, move_data, - Rc::clone(&location_map), + &location_map, borrow_set, ); } diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 68e851c05ace3..d445d2e8ef96d 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,5 +1,3 @@ -use std::rc::Rc; - use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_index::IndexVec; use rustc_middle::mir::{Body, Location}; @@ -41,8 +39,6 @@ pub(super) struct LocalizedNode { /// The localized constraint graph indexes the physical and logical edges to lazily compute a given /// node's successors during traversal. pub(super) struct LocalizedConstraintGraph { - location_map: Rc, - /// The actual, physical, edges we have recorded for a given node. We localize them on-demand /// when traversing from the node to the successor region. edges: FxHashMap>, @@ -67,7 +63,7 @@ pub(super) trait LocalizedConstraintGraphVisitor { impl LocalizedConstraintGraph { /// Traverses the constraints and returns the indexed graph of edges per node. pub(super) fn new<'tcx>( - location_map: Rc, + location_map: &DenseLocationMap, outlives_constraints: impl Iterator>, ) -> Self { let mut edges: FxHashMap<_, SmallVec<[RegionVid; 4]>> = FxHashMap::default(); @@ -96,7 +92,7 @@ impl LocalizedConstraintGraph { } } - LocalizedConstraintGraph { location_map, edges, logical_edges } + LocalizedConstraintGraph { edges, logical_edges } } /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered @@ -105,6 +101,7 @@ impl LocalizedConstraintGraph { &self, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, + location_map: &DenseLocationMap, liveness_source: &mut impl LivenessSource, visitor: &mut impl LocalizedConstraintGraphVisitor, ) { @@ -119,7 +116,7 @@ impl LocalizedConstraintGraph { let start_node = LocalizedNode { region: loan.region, - point: self.location_map.point_from_location(loan.reserve_location), + point: location_map.point_from_location(loan.reserve_location), }; visited.insert(start_node); stack.push(start_node); @@ -127,7 +124,7 @@ impl LocalizedConstraintGraph { while let Some(node) = stack.pop() { let liveness = liveness_source.liveness_for_region(node.region); // We've reached a node we haven't visited before. - let location = self.location_map.to_location(node.point); + let location = location_map.to_location(node.point); visitor.on_node_traversed(loan_idx, node, liveness.is_live_at(node.point)); // When we find a _new_ successor, we'd like to @@ -183,7 +180,7 @@ impl LocalizedConstraintGraph { for successor_block in body[location.block].terminator().successors() { let next_location = Location { block: successor_block, statement_index: 0 }; - let next_point = self.location_map.point_from_location(next_location); + let next_point = location_map.point_from_location(next_location); if liveness.is_live_at(next_point) { successor_found(LocalizedNode { region: node.region, @@ -226,7 +223,7 @@ impl LocalizedConstraintGraph { statement_index: body[pred_block].statements.len(), }; let previous_point = - self.location_map.point_from_location(previous_location); + location_map.point_from_location(previous_location); successor_found(LocalizedNode { region: node.region, point: previous_point, diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index fb4c6fbcc9da9..c32b118a9a1cc 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -5,7 +5,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; -use rustc_mir_dataflow::points::PointIndex; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; @@ -71,7 +71,8 @@ pub(crate) fn dump_polonius_mir<'tcx>( }; let mut collector = MirDumpCollector::default(); if let Some(graph) = &polonius_context.graph { - graph.traverse(body, borrow_set, &mut liveness_source, &mut collector); + let location_map = regioncx.liveness_constraints().location_map(); + graph.traverse(body, borrow_set, location_map, &mut liveness_source, &mut collector); } let extra_data = &|pass_where, out: &mut dyn io::Write| { @@ -172,7 +173,7 @@ fn emit_polonius_dump<'tcx>( "POLONIUS_CONSTRAINTS" => { edge_count = emit_mermaid_constraint_graph( borrow_set, - regioncx.liveness_constraints(), + regioncx.liveness_constraints().location_map(), &collector.constraints, out, )?; @@ -271,7 +272,7 @@ fn emit_polonius_mir<'tcx>( out, )?; - let liveness = regioncx.liveness_constraints(); + let location_map = regioncx.liveness_constraints().location_map(); // Add localized outlives constraints match pass_where { @@ -281,8 +282,8 @@ fn emit_polonius_mir<'tcx>( for constraint in localized_outlives_constraints { let LocalizedOutlivesConstraint { source, from, target, to } = constraint; - let from = liveness.location_from_point(*from); - let to = liveness.location_from_point(*to); + let from = location_map.to_location(*from); + let to = location_map.to_location(*to); writeln!(out, "| {source:?} at {from:?} -> {target:?} at {to:?}")?; } writeln!(out, "|")?; @@ -462,12 +463,12 @@ fn emit_mermaid_nll_sccs<'tcx>( /// region, and loan introductions. fn emit_mermaid_constraint_graph<'tcx>( borrow_set: &BorrowSet<'tcx>, - liveness: &LivenessValues, + location_map: &DenseLocationMap, localized_outlives_constraints: &[LocalizedOutlivesConstraint], out: &mut dyn io::Write, ) -> io::Result { let node_label = |region: RegionVid, point: PointIndex| { - let location = liveness.location_from_point(point); + let location = location_map.to_location(point); node_name(region, location) }; @@ -533,6 +534,7 @@ fn emit_loan_reachability( reachability: &FxIndexMap>, out: &mut dyn io::Write, ) -> io::Result<()> { + let location_map = liveness.location_map(); for (loan, _) in borrow_set.iter_enumerated() { let Some(reachability) = reachability.get(&loan) else { continue; @@ -553,7 +555,7 @@ fn emit_loan_reachability( for (idx, node) in reachability.iter().enumerate() { writeln!(out, "
  • ")?; - let location = liveness.location_from_point(node.point); + let location = location_map.to_location(node.point); let kind = if idx == 0 { "starts in" } else { "reaches" }; writeln!( out, diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 73133b6ca0811..b19bc6a42db7e 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -39,8 +39,6 @@ pub(crate) mod legacy; mod liveness; mod liveness_constraints; -use std::rc::Rc; - use rustc_data_structures::fx::FxHashSet; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; @@ -143,7 +141,7 @@ impl<'tcx> PoloniusContext<'tcx> { universal_regions: &UniversalRegions<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, - location_map: Rc, + location_map: &DenseLocationMap, borrow_set: &BorrowSet<'tcx>, ) { // We don't need to prepare the graph (index NLL constraints, etc.) if we have no loans to @@ -152,8 +150,7 @@ impl<'tcx> PoloniusContext<'tcx> { // From the outlives constraints, liveness, and variances, we can compute reachability // on the lazy localized constraint graph to trace the liveness of loans, for the next // step in the chain (the NLL loan scope and active loans computations). - let graph = - LocalizedConstraintGraph::new(Rc::clone(&location_map), outlives_constraints); + let graph = LocalizedConstraintGraph::new(location_map, outlives_constraints); let local_use_map = self .local_use_map @@ -163,7 +160,7 @@ impl<'tcx> PoloniusContext<'tcx> { std::mem::take(&mut self.deferred_locals_for_liveness); let mut live_loans = LiveLoans::new(location_map.num_points(), borrow_set.len()); let comp = - LivenessComputation::new(infcx, body, &location_map, move_data, &local_use_map); + LivenessComputation::new(infcx, body, location_map, move_data, &local_use_map); let mut liveness_source = DeferredLivenessSource { liveness, live_region_variances: &mut self.live_region_variances, @@ -172,7 +169,7 @@ impl<'tcx> PoloniusContext<'tcx> { comp, }; let mut visitor = LoanLivenessVisitor { live_loans: &mut live_loans }; - graph.traverse(body, borrow_set, &mut liveness_source, &mut visitor); + graph.traverse(body, borrow_set, location_map, &mut liveness_source, &mut visitor); liveness.record_live_loans(live_loans); // The graph can be traversed again during MIR dumping, so we store it here. diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index af0f48526b4fe..eedfe7d73c644 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -694,7 +694,7 @@ impl<'tcx> RegionInferenceContextInner<'tcx> { /// region is contained within the type of a variable that is live at this point. /// Note: for now, the sets of live loans is only available when using `-Zpolonius=next`. pub(crate) fn is_loan_live_at(&self, loan_idx: BorrowIndex, location: Location) -> bool { - let point = self.liveness_constraints.point_from_location(location); + let point = self.liveness_constraints.location_map().point_from_location(location); self.liveness_constraints.is_loan_live_at(loan_idx, point) } } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 800f72275b052..709eddf6e985f 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -191,16 +191,6 @@ impl LivenessValues { ) } - #[inline] - pub(crate) fn point_from_location(&self, location: Location) -> PointIndex { - self.location_map.point_from_location(location) - } - - #[inline] - pub(crate) fn location_from_point(&self, point: PointIndex) -> Location { - self.location_map.to_location(point) - } - /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active /// loans dataflow computations. pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) { @@ -214,6 +204,11 @@ impl LivenessValues { .expect("Accessing live loans requires `-Zpolonius=next`") .contains(point, loan_idx) } + + #[inline] + pub(crate) fn location_map(&self) -> &DenseLocationMap { + &self.location_map + } } /// Maps from `ty::PlaceholderRegion` values that are used in the rest of From c9bcd7ad67abb7c751a3972072b2a0e827492e64 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 10:55:52 +0200 Subject: [PATCH 0836/1309] more comment --- compiler/rustc_borrowck/src/polonius/liveness.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 9cbaa2d6ddc4d..df06cc2af7f5a 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -57,7 +57,9 @@ impl<'a> RegionLiveness<'a> { } /// The data needed to compute region liveness on-demand while traversing the localized outlives -/// constraint graph to compute loan liveness. +/// constraint graph to compute loan liveness. Each region comes from a local's type, so this holds +/// mostly the locals and drop-liveness specifics about their type, to be used as inputs to the +/// `LivenessComputation` giving us the region liveness. #[derive(Default)] pub(crate) struct DeferredLocals<'tcx> { /// For each region, the local whose liveness is deferred. From e34a4bc024394fe99fff455b19add57bf5ed5991 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 11:57:19 +0200 Subject: [PATCH 0837/1309] rename `DeferredLocals` to `DeferredRegionLiveness` we're really deferring the region liveness computation to become on-demand, "deferred locals" is slightly inaccurate in that some of the local's type data is also necessary for drop-liveness. we can focus on the output of the computation rather than its inputs. it also allows us to rename the suboptimal set of locals `deferred` colliding with `deferred_locals` --- .../rustc_borrowck/src/polonius/liveness.rs | 4 ++-- compiler/rustc_borrowck/src/polonius/mod.rs | 13 ++++++------- .../src/type_check/liveness/trace.rs | 19 +++++++++---------- 3 files changed, 17 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index df06cc2af7f5a..c87ba2045adff 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -61,7 +61,7 @@ impl<'a> RegionLiveness<'a> { /// mostly the locals and drop-liveness specifics about their type, to be used as inputs to the /// `LivenessComputation` giving us the region liveness. #[derive(Default)] -pub(crate) struct DeferredLocals<'tcx> { +pub(crate) struct DeferredRegionLiveness<'tcx> { /// For each region, the local whose liveness is deferred. /// /// Importantly, because of MIR renumbering, this will always be a 1:1 relationship. @@ -71,7 +71,7 @@ pub(crate) struct DeferredLocals<'tcx> { drop_args_by_local: IndexVec>>>, } -impl<'tcx> DeferredLocals<'tcx> { +impl<'tcx> DeferredRegionLiveness<'tcx> { pub(crate) fn defer_local( &mut self, tcx: TyCtxt<'tcx>, diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index b19bc6a42db7e..49c6c7f5a5067 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -52,7 +52,7 @@ pub(crate) use self::dump::dump_polonius_mir; pub(crate) use self::liveness_constraints::record_live_region_variance; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; -pub(crate) use crate::polonius::liveness::DeferredLocals; +pub(crate) use crate::polonius::liveness::DeferredRegionLiveness; use crate::polonius::liveness::{LivenessSource, RegionLiveness}; use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::{LivenessComputation, LocalUseMap}; @@ -103,7 +103,7 @@ pub(crate) struct PoloniusContext<'tcx> { /// diagnostics, to focus on the locals we consider relevant and match NLL diagnostics. pub(crate) boring_nll_locals: FxHashSet, - pub(crate) deferred_locals_for_liveness: DeferredLocals<'tcx>, + pub(crate) deferred_liveness: DeferredRegionLiveness<'tcx>, pub(crate) local_use_map: Option, } @@ -156,8 +156,7 @@ impl<'tcx> PoloniusContext<'tcx> { .local_use_map .as_ref() .expect("local use map should be computed before loan liveness"); - let deferred_locals_for_liveness = - std::mem::take(&mut self.deferred_locals_for_liveness); + let deferred_liveness = std::mem::take(&mut self.deferred_liveness); let mut live_loans = LiveLoans::new(location_map.num_points(), borrow_set.len()); let comp = LivenessComputation::new(infcx, body, location_map, move_data, &local_use_map); @@ -165,7 +164,7 @@ impl<'tcx> PoloniusContext<'tcx> { liveness, live_region_variances: &mut self.live_region_variances, universal_regions, - deferred_locals_for_liveness, + deferred_liveness, comp, }; let mut visitor = LoanLivenessVisitor { live_loans: &mut live_loans }; @@ -185,14 +184,14 @@ struct DeferredLivenessSource<'a, 'tcx> { liveness: &'a mut LivenessValues, live_region_variances: &'a mut LiveRegionVariances, universal_regions: &'a UniversalRegions<'tcx>, - deferred_locals_for_liveness: DeferredLocals<'tcx>, + deferred_liveness: DeferredRegionLiveness<'tcx>, comp: LivenessComputation<'a, 'tcx>, } impl<'a> LivenessSource for DeferredLivenessSource<'a, '_> { #[inline] fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { - self.deferred_locals_for_liveness.compute_deferred_local( + self.deferred_liveness.compute_deferred_local( region, self.universal_regions, &mut self.liveness, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 21b2e0f304b05..37347bc9c9e16 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -18,7 +18,7 @@ use rustc_trait_selection::traits::query::dropck_outlives; use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOpOutput}; use tracing::debug; -use crate::polonius::{DeferredLocals, LiveRegionVariances, record_live_region_variance}; +use crate::polonius::{DeferredRegionLiveness, LiveRegionVariances, record_live_region_variance}; use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::local_use_map::LocalUseMap; use crate::type_check::liveness::make_all_regions_live; @@ -64,16 +64,15 @@ pub(super) fn trace<'tcx>( let mut results = LivenessResults::new(typeck, comp); - let mut deferred_locals = DeferredLocals::default(); - results.record_legacy_polonius_drop_facts(relevant_live_locals, &deferred); results.compute_for_all_locals(relevant_live_locals); - results.dropck_boring_locals(boring_locals, &deferred, &mut deferred_locals); + let mut deferred_liveness = DeferredRegionLiveness::default(); + results.dropck_boring_locals(boring_locals, &deferred, &mut deferred_liveness); if let Some(polonius_context) = &mut typeck.polonius_context { - polonius_context.deferred_locals_for_liveness = deferred_locals; + polonius_context.deferred_liveness = deferred_liveness; polonius_context.local_use_map = Some(local_use_map); } } @@ -198,10 +197,10 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { &mut self, boring_locals: &[Local], deferred: &FxIndexSet, - deferred_locals: &mut DeferredLocals<'tcx>, + deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { for &local in boring_locals { - self.dropck_boring_local(local, deferred, deferred_locals); + self.dropck_boring_local(local, deferred, deferred_liveness); } } @@ -209,7 +208,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { &mut self, local: Local, deferred: &FxIndexSet, - deferred_locals: &mut DeferredLocals<'tcx>, + deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { let typeck = &mut *self.typeck; let local_ty = self.comp.body.local_decls[local].ty; @@ -220,7 +219,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // Calculating drop-liveness is expensive, but we can skip it when we know that there // are *no* drops (which is relatively cheap). if deferred.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { - deferred_locals.defer_local( + deferred_liveness.defer_local( typeck.infcx.tcx, typeck.universal_regions, local, @@ -264,7 +263,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { } // Finally, we mark that this local is deferred, including the drop kinds. - deferred_locals.defer_local( + deferred_liveness.defer_local( typeck.infcx.tcx, typeck.universal_regions, local, From c0d719b96ffe7035519980a7e46e147949645e47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 12:04:23 +0200 Subject: [PATCH 0838/1309] use the now available name `deferred_locals` rename the various `deferred` to mention locals, now that `DeferredLocals` doesn't use `deferred_locals` --- .../src/type_check/liveness/mod.rs | 12 +++++++----- .../src/type_check/liveness/trace.rs | 18 +++++++++--------- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 905547c7dce51..1d081973a42ca 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -82,11 +82,13 @@ pub(super) fn generate<'tcx>( let (polonius_relevant, _) = compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - let boring: FxHashSet<_> = boring_locals.iter().copied().collect(); - let deferred = - polonius_relevant.into_iter().filter(|local| boring.contains(local)).collect(); - typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring; - deferred + let boring_nll_locals: FxHashSet<_> = boring_locals.iter().copied().collect(); + let deferred_polonius_locals = polonius_relevant + .into_iter() + .filter(|local| boring_nll_locals.contains(local)) + .collect(); + typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring_nll_locals; + deferred_polonius_locals }; trace::trace( diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 37347bc9c9e16..d8baca376b0af 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -46,13 +46,13 @@ pub(super) fn trace<'tcx>( move_data: &MoveData<'tcx>, relevant_live_locals: &[Local], boring_locals: &[Local], - deferred: &FxIndexSet, + deferred_locals: &FxIndexSet, ) { let _timer = typeck.tcx().prof.generic_activity("borrowck_liveness_trace"); // The use map must also cover the deferred locals: their liveness is computed later, from // this same map, when the loan liveness traversal first reaches one of their regions. - let use_map_locals = relevant_live_locals.iter().chain(deferred).copied(); + let use_map_locals = relevant_live_locals.iter().chain(deferred_locals).copied(); let local_use_map = LocalUseMap::build(use_map_locals, location_map, typeck.body); let comp = LivenessComputation::new( typeck.infcx, @@ -64,12 +64,12 @@ pub(super) fn trace<'tcx>( let mut results = LivenessResults::new(typeck, comp); - results.record_legacy_polonius_drop_facts(relevant_live_locals, &deferred); + results.record_legacy_polonius_drop_facts(relevant_live_locals, &deferred_locals); results.compute_for_all_locals(relevant_live_locals); let mut deferred_liveness = DeferredRegionLiveness::default(); - results.dropck_boring_locals(boring_locals, &deferred, &mut deferred_liveness); + results.dropck_boring_locals(boring_locals, &deferred_locals, &mut deferred_liveness); if let Some(polonius_context) = &mut typeck.polonius_context { polonius_context.deferred_liveness = deferred_liveness; @@ -196,18 +196,18 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { fn dropck_boring_locals( &mut self, boring_locals: &[Local], - deferred: &FxIndexSet, + deferred_locals: &FxIndexSet, deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { for &local in boring_locals { - self.dropck_boring_local(local, deferred, deferred_liveness); + self.dropck_boring_local(local, deferred_locals, deferred_liveness); } } fn dropck_boring_local( &mut self, local: Local, - deferred: &FxIndexSet, + deferred_locals: &FxIndexSet, deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { let typeck = &mut *self.typeck; @@ -218,7 +218,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // in turn would have skipped calculating dropck *at all* for locals without drop-liveness. // Calculating drop-liveness is expensive, but we can skip it when we know that there // are *no* drops (which is relatively cheap). - if deferred.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { + if deferred_locals.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { deferred_liveness.defer_local( typeck.infcx.tcx, typeck.universal_regions, @@ -237,7 +237,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { let drop_data = dropck_local(&typeck.infcx, &mut self.drop_data, local_ty, local_span); // We are done with *truly* boring locals. - if !deferred.contains(&local) { + if !deferred_locals.contains(&local) { return; } From a17bea344901ad8e67ad34dbb2e1227dee17585c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 12:06:56 +0200 Subject: [PATCH 0839/1309] collapse interesting construct --- compiler/rustc_borrowck/src/type_check/liveness/mod.rs | 8 +++----- compiler/rustc_borrowck/src/type_check/liveness/trace.rs | 3 ++- 2 files changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 1d081973a42ca..b2e8ef5304e4f 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -69,15 +69,13 @@ pub(super) fn generate<'tcx>( // for now. // FIXME: this NLL optimization idea, to reduce work to relevant locals only, still makes sense // for polonius, and should be investigated to improve liveness performance. - let deferred_locals = 'deferred: { + let deferred_locals = if typeck.polonius_context.is_none() || typeck.borrow_set.len() == 0 { // If we aren't going to be using the additional liveness information, // don't even bother computing the larger relevant set. // Similarly, since this liveness information is ultimately used for *loan* // liveness, we don't need to compute it when there are no loans. - if typeck.polonius_context.is_none() || typeck.borrow_set.len() == 0 { - break 'deferred FxIndexSet::default(); - } - + FxIndexSet::default() + } else { let free_regions = typeck.universal_regions.universal_regions_iter().collect(); let (polonius_relevant, _) = compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index d8baca376b0af..d8a7990f86b9c 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -218,7 +218,8 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // in turn would have skipped calculating dropck *at all* for locals without drop-liveness. // Calculating drop-liveness is expensive, but we can skip it when we know that there // are *no* drops (which is relatively cheap). - if deferred_locals.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { + if deferred_locals.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() + { deferred_liveness.defer_local( typeck.infcx.tcx, typeck.universal_regions, From 63b65639dad919ee1d0a7b45535e5c88769b1e76 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 14:36:43 +0200 Subject: [PATCH 0840/1309] micro-optimize gathering polonius-relevant locals by not calling `compute_relevant_live_locals`: - remove free regions hashset allocation - remove unused boring locals allocation - remove relevant locals vec allocation - directly build relevant locals with nll_boring locals filtering we could also optimize the boring nll locals hashset but it's unclear whether it's worth it compared to when it's being iterated. --- .../src/type_check/liveness/mod.rs | 32 +++++++++++++++---- 1 file changed, 25 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index b2e8ef5304e4f..735fd68a2b1d2 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -76,15 +76,33 @@ pub(super) fn generate<'tcx>( // liveness, we don't need to compute it when there are no loans. FxIndexSet::default() } else { - let free_regions = typeck.universal_regions.universal_regions_iter().collect(); - let (polonius_relevant, _) = - compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - + // As described above, we can defer computing liveness for the regions that are + // NLL-boring-and-polonius-relevant. Let's find these. + // + // Note that this is basically a simplified version of `compute_relevant_live_locals` + // avoiding the allocations that are unnecessary in our more limited use-case. + let tcx = typeck.tcx(); + let universal_regions = typeck.universal_regions; let boring_nll_locals: FxHashSet<_> = boring_locals.iter().copied().collect(); - let deferred_polonius_locals = polonius_relevant - .into_iter() - .filter(|local| boring_nll_locals.contains(local)) + let deferred_polonius_locals = typeck + .body + .local_decls + .iter_enumerated() + .filter_map(|(local, decl)| { + // The polonius-relevant locals are the ones whose types do not only contain + // universal regions. + if boring_nll_locals.contains(&local) + && !tcx.all_free_regions_meet(&decl.ty, |r| { + universal_regions.is_universal_region(r.as_var()) + }) + { + Some(local) + } else { + None + } + }) .collect(); + typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring_nll_locals; deferred_polonius_locals }; From bf6b17e48c4e62578b7566cfb6069e7b753fc19d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 16:03:11 +0200 Subject: [PATCH 0841/1309] slight cleanups in `DeferredRegionLiveness` --- compiler/rustc_borrowck/src/polonius/liveness.rs | 7 ++++--- compiler/rustc_borrowck/src/polonius/mod.rs | 2 +- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index c87ba2045adff..346f3622ebdbb 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -72,6 +72,8 @@ pub(crate) struct DeferredRegionLiveness<'tcx> { } impl<'tcx> DeferredRegionLiveness<'tcx> { + /// We want to defer computing the liveness of the region in the local's type, so we store the + /// necessary inputs to do that later. pub(crate) fn defer_local( &mut self, tcx: TyCtxt<'tcx>, @@ -88,7 +90,6 @@ impl<'tcx> DeferredRegionLiveness<'tcx> { // Then, we want to map all the regions contained within this local to // the local itself. Later, when asked for liveness of a given region, // we can trace liveness for the local containing it. - let by_region = &mut self.by_region; tcx.for_each_free_region(&local_ty, |region| { // See note in `VarianceExtractor::record_variance`. if region.is_bound() || region.is_erased() { @@ -97,7 +98,7 @@ impl<'tcx> DeferredRegionLiveness<'tcx> { let vid = universal_regions.to_region_vid(region); // Because of MIR renumbering, we should always have a 1:1 mapping // between a region and a local. - let previous = by_region.insert(vid, local); + let previous = self.by_region.insert(vid, local); debug_assert!( previous.is_none(), "{vid:?} is in the type of both {previous:?} and {local:?}, but \ @@ -108,7 +109,7 @@ impl<'tcx> DeferredRegionLiveness<'tcx> { /// For a given region, compute the liveness for the local containing it, if it is deferred. #[inline] - pub(crate) fn compute_deferred_local( + pub(crate) fn ensure_deferred_liveness( &mut self, region: RegionVid, universal_regions: &UniversalRegions<'tcx>, diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 49c6c7f5a5067..664bcedfc5ef2 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -191,7 +191,7 @@ struct DeferredLivenessSource<'a, 'tcx> { impl<'a> LivenessSource for DeferredLivenessSource<'a, '_> { #[inline] fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { - self.deferred_liveness.compute_deferred_local( + self.deferred_liveness.ensure_deferred_liveness( region, self.universal_regions, &mut self.liveness, From b835ee0686a26772ce8896ac729db5fc3e27914f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Thu, 24 Sep 2026 16:05:39 +0200 Subject: [PATCH 0842/1309] cleanup in `dropck_boring_local` --- .../rustc_borrowck/src/type_check/liveness/trace.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index d8a7990f86b9c..05bd139934e4d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -200,14 +200,15 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { for &local in boring_locals { - self.dropck_boring_local(local, deferred_locals, deferred_liveness); + let is_local_deferred = deferred_locals.contains(&local); + self.dropck_boring_local(local, is_local_deferred, deferred_liveness); } } fn dropck_boring_local( &mut self, local: Local, - deferred_locals: &FxIndexSet, + is_local_deferred: bool, deferred_liveness: &mut DeferredRegionLiveness<'tcx>, ) { let typeck = &mut *self.typeck; @@ -218,8 +219,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // in turn would have skipped calculating dropck *at all* for locals without drop-liveness. // Calculating drop-liveness is expensive, but we can skip it when we know that there // are *no* drops (which is relatively cheap). - if deferred_locals.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() - { + if is_local_deferred && self.comp.local_use_map.drops(local).next().is_none() { deferred_liveness.defer_local( typeck.infcx.tcx, typeck.universal_regions, @@ -238,7 +238,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { let drop_data = dropck_local(&typeck.infcx, &mut self.drop_data, local_ty, local_span); // We are done with *truly* boring locals. - if !deferred_locals.contains(&local) { + if !is_local_deferred { return; } From 3f2e9ee8614715d3579ae7571985663e6de8f4e3 Mon Sep 17 00:00:00 2001 From: eleocraft Date: Fri, 25 Sep 2026 15:26:40 +0200 Subject: [PATCH 0843/1309] Applying requested changes Adding mod clamp_magnitude in coretests/num/mod.rs Activating feature(clamp_magnitude) in coretests/lib.rs Adding test coverage for f16, f128, and NaN as well as zero cases Modifying nonzero and int_macros documentation for better readablity --- library/core/src/num/int_macros.rs | 6 +- library/core/src/num/nonzero.rs | 26 ++++++-- library/coretests/tests/lib.rs | 1 + .../coretests/tests/num/clamp_magnitude.rs | 62 ++++++++++++++++--- library/coretests/tests/num/mod.rs | 1 + 5 files changed, 78 insertions(+), 18 deletions(-) diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index 2328fb1e03a31..1d272c0e5632e 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -3964,13 +3964,13 @@ macro_rules! int_impl { /// ``` /// #![feature(clamp_magnitude)] #[doc = concat!("assert_eq!(120", stringify!($SelfT), ".clamp_magnitude(100), 100);")] - #[doc = concat!("assert_eq!(-120", stringify!($SelfT), ".clamp_magnitude(100), -100);")] + #[doc = concat!("assert_eq!((-120", stringify!($SelfT), ").clamp_magnitude(100), -100);")] #[doc = concat!("assert_eq!(80", stringify!($SelfT), ".clamp_magnitude(100), 80);")] - #[doc = concat!("assert_eq!(-80", stringify!($SelfT), ".clamp_magnitude(100), -80);")] + #[doc = concat!("assert_eq!((-80", stringify!($SelfT), ").clamp_magnitude(100), -80);")] /// ``` #[inline] #[must_use = "method returns a new number and does not mutate the original value"] - #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[unstable(feature = "clamp_magnitude", issue = "148519")] pub const fn clamp_magnitude(self, limit: $UnsignedT) -> Self { if let Ok(limit) = core::convert::TryInto::<$SelfT>::try_into(limit) { diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index 513166bf12cae..d7b451c53f059 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -2468,14 +2468,30 @@ macro_rules! nonzero_integer_signedness_dependent_methods { /// # use std::num::NonZero; /// # #[doc = concat!("let limit = NonZero::<", stringify!($Uint), ">::new(100).unwrap();")] - #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(120).unwrap().clamp_magnitude(limit), NonZero::new(100).unwrap());")] - #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(-120).unwrap().clamp_magnitude(limit), NonZero::new(-100).unwrap());")] - #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(80).unwrap().clamp_magnitude(limit), NonZero::new(80).unwrap());")] - #[doc = concat!("assert_eq!(NonZero::<", stringify!($Int), ">::new(-80).unwrap().clamp_magnitude(limit), NonZero::new(-80).unwrap());")] + /// + /// assert_eq!( + #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(120).unwrap().clamp_magnitude(limit),")] + #[doc = "\tNonZero::new(100).unwrap(),"] + /// ); + /// + /// assert_eq!( + #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(-120).unwrap().clamp_magnitude(limit),")] + #[doc = "\tNonZero::new(-100).unwrap(),"] + /// ); + /// + /// assert_eq!( + #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(80).unwrap().clamp_magnitude(limit),")] + #[doc = "\tNonZero::new(80).unwrap(),"] + /// ); + /// + /// assert_eq!( + #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(-80).unwrap().clamp_magnitude(limit),")] + #[doc = "\tNonZero::new(-80).unwrap(),"] + /// ); /// ``` #[inline] #[must_use = "method returns a new number and does not mutate the original value"] - #[rustc_const_unstable(feature = "clamp_magnitude", issue = "148519")] + #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[unstable(feature = "clamp_magnitude", issue = "148519")] pub const fn clamp_magnitude(self, limit: NonZero<$Uint>) -> Self { // SAFETY: a non-zero value clamped to the magnitude of a non-zero value is still non-zero. diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 69bc6edd1b833..40543ee794ee7 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -15,6 +15,7 @@ #![feature(cfg_overflow_checks)] #![feature(cfg_target_has_reliable_f16_f128)] #![feature(char_internals)] +#![feature(clamp_magnitude)] #![feature(clamp_to)] #![feature(clone_to_uninit)] #![feature(cmp_minmax)] diff --git a/library/coretests/tests/num/clamp_magnitude.rs b/library/coretests/tests/num/clamp_magnitude.rs index 11ae7a7549111..5bccc4ad45e20 100644 --- a/library/coretests/tests/num/clamp_magnitude.rs +++ b/library/coretests/tests/num/clamp_magnitude.rs @@ -1,5 +1,7 @@ use core::num::*; +use crate::num::assert_biteq; + macro_rules! check_int_clamp { ($t:ty, $ut:ty) => { let min = <$t>::MIN; @@ -151,7 +153,7 @@ fn test_clamp_magnitude_nonzero_isize() { } macro_rules! check_float_clamp { - ($t:ty) => { + ($t:ty, $huge: expr) => { // Basic clamping assert_eq!((5.0 as $t).clamp_magnitude(3.0), 3.0); assert_eq!((-5.0 as $t).clamp_magnitude(3.0), -3.0); @@ -163,10 +165,13 @@ macro_rules! check_float_clamp { assert_eq!((-3.0 as $t).clamp_magnitude(3.0), -3.0); // Zero cases - assert_eq!((0.0 as $t).clamp_magnitude(1.0), 0.0); - assert_eq!((-0.0 as $t).clamp_magnitude(1.0), 0.0); - assert_eq!((5.0 as $t).clamp_magnitude(0.0), 0.0); - assert_eq!((-5.0 as $t).clamp_magnitude(0.0), 0.0); + type Float = $t; + assert_biteq!((0.0 as $t).clamp_magnitude(1.0), 0.0); + assert_biteq!((-0.0 as $t).clamp_magnitude(1.0), -0.0); + assert_biteq!((5.0 as $t).clamp_magnitude(0.0), 0.0); + assert_biteq!((-5.0 as $t).clamp_magnitude(0.0), -0.0); + assert_biteq!((5.0 as $t).clamp_magnitude(-0.0), 0.0); + assert_biteq!((-5.0 as $t).clamp_magnitude(-0.0), -0.0); // Special values - Infinity let inf = <$t>::INFINITY; @@ -183,9 +188,12 @@ macro_rules! check_float_clamp { let max = <$t>::MAX; let min = <$t>::MIN; // Large limit - let huge = 1e30; - assert_eq!(max.clamp_magnitude(huge), huge); - assert_eq!(min.clamp_magnitude(huge), -huge); + assert_eq!(max.clamp_magnitude($huge), $huge); + assert_eq!(min.clamp_magnitude($huge), -$huge); + + // NaN + let nan = <$t>::NAN; + assert!(nan.clamp_magnitude(1.0).is_nan()); // Const clamping const C1: $t = (5.0 as $t).clamp_magnitude(3.0); @@ -199,14 +207,30 @@ macro_rules! check_float_clamp { }; } +#[test] +fn test_clamp_magnitude_f16() { + check_float_clamp!(f16, 1e3); +} + #[test] fn test_clamp_magnitude_f32() { - check_float_clamp!(f32); + check_float_clamp!(f32, 1e30); } #[test] fn test_clamp_magnitude_f64() { - check_float_clamp!(f64); + check_float_clamp!(f64, 1e300); +} + +#[test] +fn test_clamp_magnitude_f128() { + check_float_clamp!(f128, 1e3000); +} + +#[test] +#[should_panic(expected = "limit must be non-negative and not NaN")] +fn test_clamp_magnitude_f16_panic_negative_limit() { + let _ = 1.0f16.clamp_magnitude(-1.0); } #[test] @@ -221,6 +245,18 @@ fn test_clamp_magnitude_f64_panic_negative_limit() { let _ = 1.0f64.clamp_magnitude(-1.0); } +#[test] +#[should_panic(expected = "limit must be non-negative and not NaN")] +fn test_clamp_magnitude_f128_panic_negative_limit() { + let _ = 1.0f128.clamp_magnitude(-1.0); +} + +#[test] +#[should_panic(expected = "limit must be non-negative and not NaN")] +fn test_clamp_magnitude_f16_panic_nan_limit() { + let _ = 1.0f16.clamp_magnitude(f16::NAN); +} + #[test] #[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f32_panic_nan_limit() { @@ -232,3 +268,9 @@ fn test_clamp_magnitude_f32_panic_nan_limit() { fn test_clamp_magnitude_f64_panic_nan_limit() { let _ = 1.0f64.clamp_magnitude(f64::NAN); } + +#[test] +#[should_panic(expected = "limit must be non-negative and not NaN")] +fn test_clamp_magnitude_f128_panic_nan_limit() { + let _ = 1.0f128.clamp_magnitude(f128::NAN); +} diff --git a/library/coretests/tests/num/mod.rs b/library/coretests/tests/num/mod.rs index b1c3001790f07..f892734d8b95d 100644 --- a/library/coretests/tests/num/mod.rs +++ b/library/coretests/tests/num/mod.rs @@ -24,6 +24,7 @@ mod u8; mod bignum; mod carryless_mul; mod cast; +mod clamp_magnitude; mod complex; mod const_from; mod dec2flt; From 0f125fae31e2edec291b23707f0ee9eed9753202 Mon Sep 17 00:00:00 2001 From: Paul Murphy Date: Thu, 24 Sep 2026 14:07:24 -0500 Subject: [PATCH 0844/1309] Ensure llvm worker threads have sufficient stack space The rustc driver sets the default stack size to 16MB, however worker threads spawned by the backend will use std's default stack size (usually 2MB). Pass through the stack size chosen by the driver to the backend, and explicitly request the stack size. --- compiler/rustc_codegen_ssa/src/back/write.rs | 23 ++++++++++++++++++-- compiler/rustc_interface/src/interface.rs | 3 +++ compiler/rustc_interface/src/util.rs | 2 +- compiler/rustc_session/src/config.rs | 5 +++++ compiler/rustc_session/src/options.rs | 1 + 5 files changed, 31 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 147e4c43c7103..6f74218fc4085 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -998,6 +998,7 @@ fn do_thin_lto( exported_symbols_for_lto: &[String], each_linked_rlib_for_lto: &[PathBuf], needs_thin_lto: Vec>, + stack_size: usize, ) -> Vec { let _timer = prof.verbose_generic_activity("LLVM_thinlto"); @@ -1088,6 +1089,7 @@ fn do_thin_lto( Arc::clone(&tm_factory), coordinator_send.clone(), item, + stack_size, ); used_token_count += 1; } @@ -1280,6 +1282,8 @@ fn start_executing_work( None }; + let stack_size = sess.opts.recommended_stack_size; + let cgcx = CodegenContext { crate_types: tcx.crate_types().to_vec(), lto: sess.lto(), @@ -1542,6 +1546,7 @@ fn start_executing_work( coordinator_send.clone(), &mut llvm_start_time, item, + stack_size, ); } } @@ -1567,6 +1572,7 @@ fn start_executing_work( coordinator_send.clone(), &mut llvm_start_time, item, + stack_size, ); } else { // There is no unstarted work, so let the main thread @@ -1610,6 +1616,7 @@ fn start_executing_work( coordinator_send.clone(), &mut llvm_start_time, item, + stack_size, ); running_with_own_token += 1; } @@ -1778,6 +1785,7 @@ fn start_executing_work( &exported_symbols_for_lto, &[], needs_thin_lto, + stack_size, )); } else { if let Some(allocator_module) = allocator_module.take() { @@ -1873,6 +1881,7 @@ fn spawn_work<'a, B: WriteBackendMethods>( coordinator_send: Sender>, llvm_start_time: &mut Option>, work: WorkItem, + stack_size: usize, ) { if llvm_start_time.is_none() { *llvm_start_time = Some(prof.verbose_generic_activity("LLVM_passes")); @@ -1906,7 +1915,11 @@ fn spawn_work<'a, B: WriteBackendMethods>( }; drop(coordinator_send.send(msg)); }; - std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread"); + std::thread::Builder::new() + .name(name) + .stack_size(stack_size) + .spawn(f) + .expect("failed to spawn work thread"); } fn spawn_thin_lto_work( @@ -1916,6 +1929,7 @@ fn spawn_thin_lto_work( tm_factory: TargetMachineFactoryFn, coordinator_send: Sender, work: ThinLtoWorkItem, + stack_size: usize, ) { let cgcx = cgcx.clone(); let prof = prof.clone(); @@ -1948,7 +1962,11 @@ fn spawn_thin_lto_work( }; drop(coordinator_send.send(msg)); }; - std::thread::Builder::new().name(name).spawn(f).expect("failed to spawn work thread"); + std::thread::Builder::new() + .name(name) + .stack_size(stack_size) + .spawn(f) + .expect("failed to spawn work thread"); } enum SharedEmitterMessage { @@ -2189,6 +2207,7 @@ impl OngoingCodegen { &crate_info.exported_symbols_for_lto, &crate_info.each_linked_rlib_file_for_lto, needs_thin_lto, + sess.opts.recommended_stack_size, ), allocator_module: None, } diff --git a/compiler/rustc_interface/src/interface.rs b/compiler/rustc_interface/src/interface.rs index 3e73bdbf5985f..7a6a49f37278a 100644 --- a/compiler/rustc_interface/src/interface.rs +++ b/compiler/rustc_interface/src/interface.rs @@ -450,6 +450,9 @@ pub fn run_compiler(config: Config, f: impl FnOnce(&Compiler) -> R + Se config.using_internal_features, ); + // STACK_SIZE is setup in run_in_thread_pool_with_globals, before arriving here. + sess.opts.recommended_stack_size = *util::STACK_SIZE.get().unwrap(); + let target_config = codegen_backend.target_config(&sess); // Store all of the target features in the session. diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs index 912f13929a349..d58b7bfddfc6d 100644 --- a/compiler/rustc_interface/src/util.rs +++ b/compiler/rustc_interface/src/util.rs @@ -21,6 +21,7 @@ use rustc_metadata::{DylibError, EncodedMetadata, load_symbol_from_dylib}; use rustc_middle::dep_graph::WorkProductMap; use rustc_middle::ty::{CurrentGcx, TyCtxt}; use rustc_query_impl::{CollectActiveJobsKind, collect_active_query_jobs}; +pub use rustc_session::config::DEFAULT_STACK_SIZE; use rustc_session::config::{ Cfg, Jobs, OutFileName, OutputFilenames, OutputTypes, Sysroot, host_tuple, }; @@ -142,7 +143,6 @@ pub(crate) fn check_abi_required_features(sess: &Session) { } pub static STACK_SIZE: OnceLock = OnceLock::new(); -pub const DEFAULT_STACK_SIZE: usize = 17 * 1024 * 1024; fn init_stack_size(early_dcx: &EarlyDiagCtxt) -> usize { // Obey the environment setting or default diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 753a4ed0d779a..798dcaf969965 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -51,6 +51,9 @@ mod native_libs; mod print_request; pub mod sigpipe; +/// A recommended stack size for worker threads spawned within a session. +pub const DEFAULT_STACK_SIZE: usize = 17 * 1024 * 1024; + /// Special CPU name requesting the CPU of the current host. pub const NATIVE_CPU: &str = "native"; @@ -1516,6 +1519,7 @@ impl Default for Options { target_modifiers: BTreeMap::default(), mitigation_coverage_map: Default::default(), jobs: Jobs { frontend: None, backend: None, linker: LinkerJobs::Default }, + recommended_stack_size: DEFAULT_STACK_SIZE, } } } @@ -3074,6 +3078,7 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M target_modifiers: collected_options.target_modifiers, mitigation_coverage_map: collected_options.mitigations, jobs, + recommended_stack_size: DEFAULT_STACK_SIZE, } } diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..5333bec0d58f4 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -438,6 +438,7 @@ top_level_options!( color: ColorConfig [UNTRACKED], verbose: bool [TRACKED_NO_CRATE_HASH], jobs: Jobs [UNTRACKED], + recommended_stack_size: usize [UNTRACKED], } ); From 9379da62b25d050b6aeb8caa80cea550e9e68635 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Fri, 25 Sep 2026 18:01:50 +0200 Subject: [PATCH 0845/1309] Don't imply incorrect things about `Global` in the docs of `System` --- library/std/src/alloc.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c6f94944006c9..cf5011c6eed5a 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -102,8 +102,14 @@ use crate::{hint, mem, ptr}; /// } /// ``` /// +/// Note that this does *not* mean you can deallocate allocations from [`Global`] +/// with [`System`] (or vice-versa), as the [`Global`] allocator is special in +/// the compiler. For more details, see the relevant docs about +/// [`#[global_allocator]`][global_allocator]. +/// /// You can also define your own wrapper around `System` if you'd like, such as -/// keeping track of the number of all bytes allocated: +/// keeping track of the number of all bytes allocated (note that due to +/// optimizations, this may not be accurate): /// /// ```rust /// use std::alloc::{System, GlobalAlloc, Layout}; @@ -140,6 +146,8 @@ use crate::{hint, mem, ptr}; /// global allocator has been selected for a Rust program. For example if a Rust /// program opts in to using jemalloc as the global allocator, `System` will /// still allocate memory using `malloc` and `HeapAlloc`. +/// +/// [global_allocator]: GlobalAlloc#the-global_allocator-attribute #[stable(feature = "alloc_system_type", since = "1.28.0")] #[derive(Copy, Debug)] #[derive_const(Clone, Default)] From 21c62776cd1f7ce9a6b06744313d6282f1d0c21a Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 21 Sep 2026 22:02:30 +0200 Subject: [PATCH 0846/1309] Fix invalid jump to def link when `#[rustc_allow_incoherent_impl]` is involved --- src/librustdoc/html/format.rs | 109 ++++++++++++++++-- .../jump-to-def/auxiliary/incoherent_impl1.rs | 18 +++ .../jump-to-def/auxiliary/incoherent_impl2.rs | 5 + .../jump-to-def/incoherent_impl.rs | 24 ++++ 4 files changed, 149 insertions(+), 7 deletions(-) create mode 100644 tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl1.rs create mode 100644 tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl2.rs create mode 100644 tests/rustdoc-html/jump-to-def/incoherent_impl.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4ee91d411903a..da88172c688f5 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -426,6 +426,81 @@ fn impl_self_ty(tcx: TyCtxt<'_>, impl_def_id: DefId) -> Ty<'_> { .unwrap_or(ty.skip_binder()) } +fn transitive_reexport_path(tcx: TyCtxt<'_>, def_id: DefId) -> Option> { + transitive_reexport_path_inner(tcx, def_id, &mut Vec::new()) +} + +/// Simplified implementation of `rustc_middle::ty::print::pretty::try_print_visible_def_path_recur`. +fn transitive_reexport_path_inner( + tcx: TyCtxt<'_>, + def_id: DefId, + callers: &mut Vec, +) -> Option> { + use rustc_hir::def_id::ModId; + use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; + + if let Some(cnum) = def_id.as_crate_root() { + return Some(vec![tcx.crate_name(cnum)]); + } + + let visible_parent_map = tcx.visible_parent_map(()); + let mut cur_def_key = tcx.def_key(def_id); + + // For a constructor, we want the name of its parent rather than . + if let DefPathData::Ctor = cur_def_key.disambiguated_data.data { + let parent = DefId { + krate: def_id.krate, + index: cur_def_key + .parent + .expect("`DefPathData::Ctor` / `VariantData` missing a parent"), + }; + + cur_def_key = tcx.def_key(parent); + } + + let visible_parent = visible_parent_map.get(&def_id).cloned()?; + // FIXME: Should we also check for private items? + if tcx.is_doc_hidden(visible_parent) { + return None; + } + + let actual_parent = tcx.opt_parent(def_id); + let mut data = cur_def_key.disambiguated_data.data; + match data { + DefPathData::TypeNs(ref mut name) if Some(visible_parent) != actual_parent => { + // Item might be re-exported several times, but filter for the one + // that's public and whose identifier isn't `_`. + let reexport = tcx + .module_children(ModId::new_unchecked(visible_parent)) + .iter() + .filter(|child| child.res.opt_def_id() == Some(def_id)) + .find(|child| child.vis.is_public() && child.ident.name != kw::Underscore) + .map(|child| child.ident.name); + + if let Some(new_name) = reexport { + *name = new_name; + } else { + // There is no name that is public and isn't `_`, so bail. + return None; + } + } + // Re-exported `extern crate`. + DefPathData::CrateRoot => { + data = DefPathData::TypeNs(tcx.crate_name(def_id.krate)); + } + _ => {} + } + + if callers.contains(&visible_parent) { + return None; + } + callers.push(visible_parent); + let mut path = transitive_reexport_path_inner(tcx, visible_parent, callers)?; + callers.pop(); + path.push(DisambiguatedDefPathData { data, disambiguator: 0 }.as_sym(false)); + Some(path) +} + fn generate_item_def_id_path( mut def_id: DefId, original_def_id: DefId, @@ -435,10 +510,13 @@ fn generate_item_def_id_path( let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); let mut prim = None; + let mut maybe_have_impl_not_in_def_crate = false; // No need to try to infer the actual parent item if it's not an associated item from the `impl` // block. - if def_id != original_def_id && matches!(tcx.def_kind(def_id), DefKind::Impl { .. }) { + if def_id != original_def_id + && let DefKind::Impl { of_trait } = tcx.def_kind(def_id) + { let ty = impl_self_ty(tcx, def_id); // If this is a dyn trait, we want to get the actual trait from which the method comes from. // Since a `dyn trait` (as of 2026) can only be composed of a trait plus auto traits, we @@ -454,18 +532,35 @@ fn generate_item_def_id_path( def_id = trait_def_id; } else if let Some(new_def_id) = ty.ty_adt_def().map(|adt| adt.did()) { def_id = new_def_id; + maybe_have_impl_not_in_def_crate = !of_trait + && !original_def_id.is_local() + && !def_id.is_local() + && def_id.krate != original_def_id.krate; } else { prim = PrimitiveType::from_ty(ty); } } - let mut fqp = vec![crate_name]; - let shortty = if let Some(prim) = prim { - fqp.push(prim.as_sym()); - ItemType::Primitive + let (shortty, fqp) = if let Some(prim) = prim { + (ItemType::Primitive, vec![crate_name, prim.as_sym()]) } else { - fqp.append(&mut clean::inline::item_relative_path(tcx, def_id)); - ItemType::from_def_id(def_id, tcx) + ( + ItemType::from_def_id(def_id, tcx), + if maybe_have_impl_not_in_def_crate + // We have a method, not coming from a trait, implemented from a different crate + // where the original item is defined. So in short, the item is using + // `#[rustc_allow_incoherent_impl]` and we need to keep the non-final item path. + // Sadly if we use `item_relative_path` which uses `def_path`, it renders the final + // item path and not the intermediate one. + && let Some(fqp) = transitive_reexport_path(tcx, def_id) + { + fqp + } else { + let mut fqp = vec![crate_name]; + fqp.append(&mut clean::inline::item_relative_path(tcx, def_id)); + fqp + }, + ) }; let module_fqp = to_module_fqp(shortty, &fqp); diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl1.rs b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl1.rs new file mode 100644 index 0000000000000..a67fe5ab7eee3 --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl1.rs @@ -0,0 +1,18 @@ +//@ aux-build: incoherent_impl2.rs +//@ build-aux-docs + +#![feature(rustc_attrs)] +#![allow(internal_features)] + +extern crate incoherent_impl2 as baz; + +pub mod error { + pub use baz::Error; +} + +impl baz::Error { + #[rustc_allow_incoherent_impl] + pub fn new() -> Self { + Self + } +} diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl2.rs b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl2.rs new file mode 100644 index 0000000000000..d04c24de248eb --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl2.rs @@ -0,0 +1,5 @@ +#![feature(rustc_attrs)] +#![allow(internal_features)] + +#[rustc_has_incoherent_inherent_impls] +pub struct Error; diff --git a/tests/rustdoc-html/jump-to-def/incoherent_impl.rs b/tests/rustdoc-html/jump-to-def/incoherent_impl.rs new file mode 100644 index 0000000000000..d1aeea39e7aa9 --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/incoherent_impl.rs @@ -0,0 +1,24 @@ +// This test ensures that we generate correct links when we target a method implemented +// with `#[rustc_allow_incoherent_impl]` in a different crate than where the type is defined. +// Regression test for . + +//@ aux-build: incoherent_impl1.rs +//@ build-aux-docs +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +extern crate incoherent_impl1 as bar; + +//@ has 'src/foo/incoherent_impl.rs.html' +//@ has - '//pre//a[@href="../../incoherent_impl1/error/struct.Error.html#method.new"]' 'new' +//@ has - '//pre//a[@href="../../incoherent_impl2/struct.Error.html"]' 'Error' + +// Now we check that the target files exist and contain the information we want. +//@ has 'incoherent_impl1/error/struct.Error.html' +//@ has - '//*[@id="method.new"]' 'pub fn new() -> Self' +//@ has 'incoherent_impl2/struct.Error.html' + +fn foo() { + let x = bar::error::Error::new(); +} From 3e574ad92e6fb0461d7559b461b22aaa26aa3848 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Fri, 25 Sep 2026 17:29:07 +0200 Subject: [PATCH 0847/1309] Add some docs to `Global` --- library/alloc/src/alloc.rs | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index ccac980706571..a900ed91d720c 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -49,8 +49,27 @@ unsafe extern "Rust" { /// to the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// -/// Note: while this type is unstable, the functionality it provides can be -/// accessed through the [free functions in `alloc`](self#functions). +/// Similar to [`alloc`], [`dealloc`], and the other global allocation functions, +/// the way in which calls are forwarded to the allocator registered with +/// `#[global_allocator]` is unspecified. See their safety docs for more information. +/// +/// This allocator must be treated like an opaque allocator that only guarantees +/// the contract described in the docs of [`Allocator`], as well as the following +/// things: +/// * All instances of `Global` are [*equivalent*]. +/// * Allocations from `Global` are only invalidated by calls to de-/reallocating functions. +/// If no such call is made, then the allocation will live for the rest of the program. +/// * The global allocation functions are equivalent to the methods on `Global`, except +/// that they disallow zero-sized allocations, and implicitly ignore any returned +/// excess size. +/// +/// Note that the current implementation of `Global` does not take advantage of +/// some features of [`Allocator`], such as zero-sized allocations (which currently always +/// return a dangling pointer) and overallocating. +/// +/// This may change in the future. You must not rely on it for correctness! +/// +/// [*equivalent*]: Allocator#equivalent-allocators #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[derive(Copy, Debug)] #[derive_const(Clone, Default)] From c89c55dd149a01e7192a1b3cb49409d1949db1be Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Fri, 25 Sep 2026 18:35:56 +0200 Subject: [PATCH 0848/1309] sanitizers.md: improve text --- src/doc/rustc-dev-guide/src/sanitizers.md | 40 +++++++++++------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/sanitizers.md b/src/doc/rustc-dev-guide/src/sanitizers.md index 65e1c0c705057..5d242b8ac5d4a 100644 --- a/src/doc/rustc-dev-guide/src/sanitizers.md +++ b/src/doc/rustc-dev-guide/src/sanitizers.md @@ -1,33 +1,33 @@ # Sanitizers support -The rustc compiler contains support for following sanitizers: +The Rust compiler contains support for following sanitizers: -* [AddressSanitizer][clang-asan] a faster memory error detector. - Can detect out-of-bounds access to heap, stack, and globals, use after free, use - after return, double free, invalid free, memory leaks. -* [ControlFlowIntegrity][clang-cfi] LLVM Control Flow Integrity (CFI) provides +* [AddressSanitizer][clang-asan], a faster memory error detector. + It can detect out-of-bounds access to heap, stack, and globals, use after free, use + after return, double free, invalid free, and memory leaks. +* [ControlFlowIntegrity][clang-cfi], LLVM Control Flow Integrity (CFI), provides forward-edge control flow protection. -* [Hardware-assisted AddressSanitizer][clang-hwasan] a tool similar to - AddressSanitizer but based on partial hardware assistance. -* [KernelControlFlowIntegrity][clang-kcfi] LLVM Kernel Control Flow Integrity - (KCFI) provides forward-edge control flow protection for operating systems kernels. -* [LeakSanitizer][clang-lsan] a run-time memory leak detector. -* [MemorySanitizer][clang-msan] a detector of uninitialized reads. -* [ThreadSanitizer][clang-tsan] a fast data race detector. +* [Hardware-assisted AddressSanitizer][clang-hwasan] is similar to + AddressSanitizer, but is based on partial hardware assistance. +* [KernelControlFlowIntegrity][clang-kcfi], LLVM Kernel Control Flow Integrity + (KCFI), provides forward-edge control flow protection for operating system kernels. +* [LeakSanitizer][clang-lsan], a run-time memory leak detector. +* [MemorySanitizer][clang-msan], a detector of uninitialized reads. +* [ThreadSanitizer][clang-tsan], a fast data race detector. ## How to use the sanitizers? -To enable a sanitizer compile with `-Z sanitizer=...` option, where value is one -of `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory` or `thread`. +To enable a sanitizer, compile with `-Z sanitizer=...` option, where value is one +of `address`, `cfi`, `hwaddress`, `kcfi`, `leak`, `memory`, or `thread`. For more details on how to use sanitizers, -please refer to the sanitizer flag in [The Unstable Book]. +refer to the sanitizer flag in [The Unstable Book]. [The Unstable Book]: https://doc.rust-lang.org/unstable-book -## How are sanitizers implemented in rustc? +## How sanitizers are implemented in rustc The implementation of sanitizers (except CFI) relies almost entirely on LLVM. -The rustc is an integration point for LLVM compile time instrumentation passes +The Rust compiler is an integration point for LLVM compile time instrumentation passes and runtime libraries. Highlight of the most important aspects of the implementation: @@ -42,7 +42,7 @@ Highlight of the most important aspects of the implementation: The runtimes are [placed into target libdir][sanitizer-copy]. * During LLVM code generation, the functions intended for instrumentation are - [marked][sanitizer-attribute] with appropriate LLVM attribute: + [marked][sanitizer-attribute] with an appropriate LLVM attribute: `SanitizeAddress`, `SanitizeHWAddress`, `SanitizeMemory`, or `SanitizeThread`. By default, all functions are instrumented, but this behaviour can be changed with `#[sanitize(xyz = "on|off|")]`. @@ -57,7 +57,7 @@ Highlight of the most important aspects of the implementation: passes][sanitizer-pass], different for each sanitizer. Instrumentation passes are invoked after optimization passes. -* When producing an executable, the sanitizer specific runtime library is +* When producing an executable, the sanitizer-specific runtime library is [linked in][sanitizer-link]. The libraries are searched for in the target libdir. First, the search is relative to the overridden system root, and subsequently, @@ -83,7 +83,7 @@ Sanitizers are validated by code generation tests in [`tests/ui/sanitizer/`][test-ui] directory. Testing sanitizer functionality requires the sanitizer runtimes (built when -`build.sanitizer = true` in `bootstrap.toml`) and target providing support for particular a sanitizer. +`build.sanitizer = true` in `bootstrap.toml`) and a target providing support for particular a sanitizer. When a sanitizer is unsupported on a given target, sanitizer tests will be ignored. This behaviour is controlled by compiletest `needs-sanitizer-*` directives. From 564f208ba98347c4cdaef867c0ac6b570b6d3b2d Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:36:06 +0200 Subject: [PATCH 0849/1309] compiler: remove rustc_hir attr re-exports --- Cargo.lock | 7 +++++++ compiler/rustc_borrowck/Cargo.toml | 1 + .../src/diagnostics/conflict_errors.rs | 7 ++++--- compiler/rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/mutability_errors.rs | 2 +- compiler/rustc_borrowck/src/nll.rs | 2 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_borrowck/src/universal_regions.rs | 2 +- compiler/rustc_codegen_cranelift/src/base.rs | 2 +- compiler/rustc_codegen_cranelift/src/constant.rs | 8 ++++---- .../rustc_codegen_cranelift/src/driver/aot.rs | 2 +- .../rustc_codegen_cranelift/src/inline_asm.rs | 2 +- compiler/rustc_codegen_cranelift/src/lib.rs | 1 + compiler/rustc_codegen_cranelift/src/linkage.rs | 2 +- compiler/rustc_codegen_cranelift/src/main_shim.rs | 2 +- compiler/rustc_codegen_gcc/src/attributes.rs | 4 ++-- compiler/rustc_codegen_gcc/src/base.rs | 3 +-- compiler/rustc_codegen_gcc/src/callee.rs | 2 +- compiler/rustc_codegen_gcc/src/consts.rs | 2 +- compiler/rustc_codegen_gcc/src/lib.rs | 1 + compiler/rustc_codegen_gcc/src/mono_item.rs | 2 +- compiler/rustc_codegen_llvm/src/base.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- .../rustc_codegen_llvm/src/builder/autodiff.rs | 2 +- compiler/rustc_codegen_llvm/src/callee.rs | 4 ++-- compiler/rustc_codegen_llvm/src/consts.rs | 4 ++-- compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_llvm/src/mono_item.rs | 2 +- .../src/assert_module_sources.rs | 5 ++--- compiler/rustc_codegen_ssa/src/back/linker.rs | 2 +- .../rustc_codegen_ssa/src/back/symbol_export.rs | 6 ++---- compiler/rustc_codegen_ssa/src/base.rs | 9 +++++---- compiler/rustc_codegen_ssa/src/codegen_attrs.rs | 4 ++-- compiler/rustc_codegen_ssa/src/common.rs | 4 ++-- compiler/rustc_codegen_ssa/src/lib.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 4 ++-- compiler/rustc_codegen_ssa/src/mir/naked_asm.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/operand.rs | 2 +- compiler/rustc_codegen_ssa/src/mono_item.rs | 2 +- compiler/rustc_codegen_ssa/src/size_of_val.rs | 2 +- compiler/rustc_codegen_ssa/src/target_features.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/builder.rs | 2 +- compiler/rustc_codegen_ssa/src/traits/declare.rs | 2 +- compiler/rustc_hir/src/lib.rs | 6 ------ compiler/rustc_hir_analysis/src/check/check.rs | 3 ++- compiler/rustc_hir_analysis/src/collect/dump.rs | 3 ++- compiler/rustc_hir_typeck/Cargo.toml | 1 + compiler/rustc_hir_typeck/src/callee.rs | 5 +++-- compiler/rustc_hir_typeck/src/check.rs | 2 +- compiler/rustc_hir_typeck/src/closure.rs | 2 +- compiler/rustc_hir_typeck/src/coercion.rs | 4 ++-- compiler/rustc_hir_typeck/src/demand.rs | 3 ++- compiler/rustc_hir_typeck/src/expr.rs | 10 +++++++--- compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- .../rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_hir_typeck/src/inline_asm.rs | 2 +- compiler/rustc_hir_typeck/src/loops.rs | 3 ++- compiler/rustc_hir_typeck/src/method/confirm.rs | 15 +++++++-------- .../src/method/prelude_edition_lints.rs | 2 +- compiler/rustc_hir_typeck/src/method/probe.rs | 5 +++-- compiler/rustc_hir_typeck/src/method/suggest.rs | 9 ++++----- compiler/rustc_hir_typeck/src/naked_functions.rs | 3 ++- compiler/rustc_hir_typeck/src/pat.rs | 2 +- compiler/rustc_hir_typeck/src/upvar.rs | 5 +++-- compiler/rustc_hir_typeck/src/writeback.rs | 3 ++- compiler/rustc_interface/Cargo.toml | 1 + compiler/rustc_interface/src/limits.rs | 2 +- compiler/rustc_interface/src/passes.rs | 5 ++--- compiler/rustc_lint/src/nonstandard_style.rs | 4 ++-- compiler/rustc_lint/src/types/literal.rs | 3 ++- compiler/rustc_lint/src/utils.rs | 3 ++- compiler/rustc_macros/src/lib.rs | 2 +- compiler/rustc_mir_build/Cargo.toml | 1 + .../rustc_mir_build/src/builder/custom/mod.rs | 4 ++-- .../src/builder/expr/as_constant.rs | 2 +- compiler/rustc_mir_build/src/builder/expr/into.rs | 2 +- .../rustc_mir_build/src/builder/matches/mod.rs | 2 +- .../rustc_mir_build/src/builder/matches/test.rs | 2 +- compiler/rustc_mir_build/src/builder/mod.rs | 3 ++- compiler/rustc_mir_build/src/check_tail_calls.rs | 2 +- compiler/rustc_mir_build/src/check_unsafety.rs | 5 +++-- compiler/rustc_mir_build/src/thir/constant.rs | 2 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 10 +++++----- compiler/rustc_mir_build/src/thir/cx/mod.rs | 5 +++-- .../src/thir/pattern/const_to_pat.rs | 4 ++-- compiler/rustc_mir_transform/Cargo.toml | 1 + .../rustc_mir_transform/src/check_alignment.rs | 2 +- .../src/check_call_recursion.rs | 2 +- compiler/rustc_mir_transform/src/check_enums.rs | 2 +- compiler/rustc_mir_transform/src/check_inline.rs | 3 +-- compiler/rustc_mir_transform/src/check_null.rs | 2 +- .../rustc_mir_transform/src/check_pointers.rs | 2 +- .../rustc_mir_transform/src/coroutine/layout.rs | 5 +++-- compiler/rustc_mir_transform/src/coroutine/mod.rs | 2 +- .../rustc_mir_transform/src/coverage/query.rs | 4 ++-- .../rustc_mir_transform/src/cross_crate_inline.rs | 4 ++-- .../rustc_mir_transform/src/elaborate_drop.rs | 2 +- compiler/rustc_mir_transform/src/inline.rs | 4 ++-- compiler/rustc_mir_transform/src/instsimplify.rs | 4 ++-- .../rustc_mir_transform/src/known_panics_lint.rs | 3 ++- compiler/rustc_mir_transform/src/liveness.rs | 2 +- compiler/rustc_mir_transform/src/pass_manager.rs | 2 +- compiler/rustc_mir_transform/src/shim.rs | 2 +- .../src/shim/async_destructor_ctor.rs | 2 +- compiler/rustc_mir_transform/src/sroa.rs | 2 +- compiler/rustc_mir_transform/src/validate.rs | 4 ++-- compiler/rustc_passes/src/lang_items.rs | 3 ++- compiler/rustc_public_bridge/Cargo.toml | 1 + compiler/rustc_public_bridge/src/context/impls.rs | 4 ++-- compiler/rustc_sanitizers/Cargo.toml | 1 + .../src/cfi/typeid/itanium_cxx_abi/encode.rs | 2 +- .../src/cfi/typeid/itanium_cxx_abi/transform.rs | 5 +++-- 114 files changed, 192 insertions(+), 166 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c2914ff343d..9cd6677ebbc3e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3734,6 +3734,7 @@ dependencies = [ "itertools", "polonius-engine", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_graphviz", @@ -4181,6 +4182,7 @@ dependencies = [ "itertools", "rustc_abi", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4266,6 +4268,7 @@ dependencies = [ "rustc_ast_lowering", "rustc_ast_passes", "rustc_ast_pretty", + "rustc_attr_ir", "rustc_attr_parsing", "rustc_borrowck", "rustc_builtin_macros", @@ -4476,6 +4479,7 @@ dependencies = [ "rustc_apfloat", "rustc_arena", "rustc_ast", + "rustc_attr_ir", "rustc_data_structures", "rustc_errors", "rustc_hir", @@ -4518,6 +4522,7 @@ dependencies = [ "rustc_abi", "rustc_arena", "rustc_ast", + "rustc_attr_ir", "rustc_const_eval", "rustc_data_structures", "rustc_errors", @@ -4702,6 +4707,7 @@ name = "rustc_public_bridge" version = "0.0.0" dependencies = [ "rustc_abi", + "rustc_attr_ir", "rustc_crate_store", "rustc_data_structures", "rustc_hir", @@ -4766,6 +4772,7 @@ dependencies = [ "bitflags", "libc", "rustc_abi", + "rustc_attr_ir", "rustc_data_structures", "rustc_hir", "rustc_middle", diff --git a/compiler/rustc_borrowck/Cargo.toml b/compiler/rustc_borrowck/Cargo.toml index 647a47def1f52..e961cf61b6478 100644 --- a/compiler/rustc_borrowck/Cargo.toml +++ b/compiler/rustc_borrowck/Cargo.toml @@ -9,6 +9,7 @@ either = "1.5.0" itertools = "0.15" polonius-engine = "0.13.0" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_graphviz = { path = "../rustc_graphviz" } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f4b2ceb850666..2de98fd971bda 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -5,15 +5,16 @@ use std::ops::ControlFlow; use either::Either; use hir::{ClosureKind, Path}; +use rustc_attr_ir::diagnostic::{CustomDiagnostic, FormatArgs}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, MultiSpan, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FormatArgs}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr}; -use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, PatField, find_attr}; +use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, PatField}; use rustc_index::bit_set::DenseBitSet; use rustc_infer::traits::TraitErrors; use rustc_middle::hir::nested_filter::OnlyBodies; diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c8abc2689ff7f..9b36b448903a2 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -3,10 +3,10 @@ use std::collections::BTreeMap; use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::formatting::DiagMessageAddArg; use rustc_errors::{Applicability, Diag, DiagMessage, MultiSpan, listify, msg}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, Namespace}; use rustc_hir::{ self as hir, CoroutineKind, GenericBound, WhereBoundPredicate, WherePredicateKind, diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 7a614db25d668..245e340a7d877 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -3,8 +3,8 @@ use core::ops::ControlFlow; use either::Either; use hir::{ExprKind, Param}; use rustc_abi::FieldIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; use rustc_hir::{self as hir, BindingMode, ByRef, Expr, Node}; diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 31fa9dd2ee64e..dbbec2c29b2a3 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -6,8 +6,8 @@ use std::rc::Rc; use std::str::FromStr; use polonius_engine::{Algorithm, AllFacts, Output}; +use rustc_attr_ir::find_attr; use rustc_data_structures::frozen::Frozen; -use rustc_hir::find_attr; use rustc_index::IndexSlice; use rustc_middle::mir::pretty::PrettyPrintMirOptions; use rustc_middle::mir::{Body, MirDumper, PassWhere, Promoted}; diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a886187783b86..14a09337bf78e 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -4,11 +4,11 @@ use std::rc::Rc; use std::{fmt, iter, mem}; use rustc_abi::FieldIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::frozen::Frozen; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_index::{IndexSlice, IndexVec}; diff --git a/compiler/rustc_borrowck/src/universal_regions.rs b/compiler/rustc_borrowck/src/universal_regions.rs index 1d55c8f940b83..7a666726cecc3 100644 --- a/compiler/rustc_borrowck/src/universal_regions.rs +++ b/compiler/rustc_borrowck/src/universal_regions.rs @@ -14,10 +14,10 @@ use std::cell::Cell; use std::iter; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_errors::Diag; use rustc_hir::BodyOwnerKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_index::IndexVec; diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 638463b5cb438..e752189130290 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -5,10 +5,10 @@ use cranelift_codegen::ir::UserFuncName; use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; use cranelift_module::ModuleError; use rustc_ast::InlineAsmOptions; +use rustc_attr_ir::lang_items::LangItem; use rustc_codegen_ssa::base::is_call_from_compiler_builtins_to_upstream_monomorphization; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::DiagCtxtHandle; -use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs index e2b0035361733..f1e4fd818ebeb 100644 --- a/compiler/rustc_codegen_cranelift/src/constant.rs +++ b/compiler/rustc_codegen_cranelift/src/constant.rs @@ -293,8 +293,8 @@ fn data_id_for_static( .abi .bytes(); - let linkage = if import_linkage == rustc_hir::attrs::Linkage::ExternalWeak - || import_linkage == rustc_hir::attrs::Linkage::WeakAny + let linkage = if import_linkage == rustc_attr_ir::Linkage::ExternalWeak + || import_linkage == rustc_attr_ir::Linkage::WeakAny { Linkage::Preemptible } else { @@ -344,8 +344,8 @@ fn data_id_for_static( let linkage = if definition { crate::linkage::get_static_linkage(tcx, def_id) - } else if attrs.linkage == Some(rustc_hir::attrs::Linkage::ExternalWeak) - || attrs.linkage == Some(rustc_hir::attrs::Linkage::WeakAny) + } else if attrs.linkage == Some(rustc_attr_ir::Linkage::ExternalWeak) + || attrs.linkage == Some(rustc_attr_ir::Linkage::WeakAny) { Linkage::Preemptible } else { diff --git a/compiler/rustc_codegen_cranelift/src/driver/aot.rs b/compiler/rustc_codegen_cranelift/src/driver/aot.rs index 73d4adf8e3cf2..a62dff641cfec 100644 --- a/compiler/rustc_codegen_cranelift/src/driver/aot.rs +++ b/compiler/rustc_codegen_cranelift/src/driver/aot.rs @@ -10,6 +10,7 @@ use std::time::Instant; use cranelift_object::{ObjectBuilder, ObjectModule}; use rustc_ast::expand::allocator::AllocatorMethod; +use rustc_attr_ir::Linkage as RLinkage; use rustc_codegen_ssa::back::lto::ThinModule; use rustc_codegen_ssa::back::write::{ CodegenContext, FatLtoInput, ModuleConfig, SharedEmitter, TargetMachineFactoryFn, ThinLtoInput, @@ -18,7 +19,6 @@ use rustc_codegen_ssa::traits::{ExtraBackendMethods, WriteBackendMethods}; use rustc_codegen_ssa::{CompiledModule, ModuleCodegen, ModuleKind}; use rustc_data_structures::profiling::SelfProfilerRef; use rustc_errors::{DiagCtxt, DiagCtxtHandle}; -use rustc_hir::attrs::Linkage as RLinkage; use rustc_middle::dep_graph::WorkProduct; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mono::{MonoItem, MonoItemData, Visibility}; diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs index cd2b06cc1defb..b2bf856e7bcee 100644 --- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs +++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs @@ -5,7 +5,7 @@ use std::fmt::Write; use cranelift_codegen::isa::CallConv; use rustc_abi::CanonAbi; use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar as ConstScalar}; use rustc_middle::ty::layout::FnAbiOf; use rustc_span::sym; diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs index 6629cc834bbd6..a30dd1c3ebef3 100644 --- a/compiler/rustc_codegen_cranelift/src/lib.rs +++ b/compiler/rustc_codegen_cranelift/src/lib.rs @@ -12,6 +12,7 @@ extern crate rustc_abi; extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_codegen_ssa; extern crate rustc_const_eval; extern crate rustc_data_structures; diff --git a/compiler/rustc_codegen_cranelift/src/linkage.rs b/compiler/rustc_codegen_cranelift/src/linkage.rs index e373268d76b76..aac3e2cf54b99 100644 --- a/compiler/rustc_codegen_cranelift/src/linkage.rs +++ b/compiler/rustc_codegen_cranelift/src/linkage.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::Linkage as RLinkage; +use rustc_attr_ir::Linkage as RLinkage; use rustc_middle::mono::{MonoItem, Visibility}; use crate::prelude::*; diff --git a/compiler/rustc_codegen_cranelift/src/main_shim.rs b/compiler/rustc_codegen_cranelift/src/main_shim.rs index b69db582a04ca..75dbfb1228d91 100644 --- a/compiler/rustc_codegen_cranelift/src/main_shim.rs +++ b/compiler/rustc_codegen_cranelift/src/main_shim.rs @@ -1,5 +1,5 @@ use cranelift_frontend::{FunctionBuilder, FunctionBuilderContext}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::{AssocTag, GenericArg, Unnormalized}; use rustc_session::config::EntryFnType; use rustc_span::{DUMMY_SP, Ident}; diff --git a/compiler/rustc_codegen_gcc/src/attributes.rs b/compiler/rustc_codegen_gcc/src/attributes.rs index 41db5e83bdcc9..2e9bf42874148 100644 --- a/compiler/rustc_codegen_gcc/src/attributes.rs +++ b/compiler/rustc_codegen_gcc/src/attributes.rs @@ -4,8 +4,8 @@ use gccjit::Function; #[cfg(feature = "master")] use rustc_abi::{CanonAbi, InterruptKind}; #[cfg(feature = "master")] -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::InstructionSetAttr; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::InstructionSetAttr; #[cfg(feature = "master")] use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 0dd46558ed796..07214096b3e49 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -4,11 +4,10 @@ use std::time::Instant; #[cfg(feature = "master")] use gccjit::VarAttribute; use gccjit::{CType, FunctionType, GlobalKind}; +use rustc_attr_ir::{AttributeKind, Linkage, find_attr}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; -use rustc_hir::attrs::{AttributeKind, Linkage}; -use rustc_hir::find_attr; use rustc_middle::dep_graph; #[cfg(feature = "master")] use rustc_middle::mono::Visibility; diff --git a/compiler/rustc_codegen_gcc/src/callee.rs b/compiler/rustc_codegen_gcc/src/callee.rs index d3f412180da55..21a0bbb4030bb 100644 --- a/compiler/rustc_codegen_gcc/src/callee.rs +++ b/compiler/rustc_codegen_gcc/src/callee.rs @@ -106,7 +106,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) // This is a monomorphization of a generic function. if !(cx.tcx.sess.opts.share_generics() || tcx.codegen_instance_attrs(instance.def).inline - == rustc_hir::attrs::InlineAttr::Never) + == rustc_attr_ir::InlineAttr::Never) { // When not sharing generics, all instances are in the same // crate and have hidden visibility. diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index 8576dfe079163..c58ab6d2a9bef 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -4,10 +4,10 @@ use std::ops::Range; use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs index 7abbda4a37dc1..f30004c8561f7 100644 --- a/compiler/rustc_codegen_gcc/src/lib.rs +++ b/compiler/rustc_codegen_gcc/src/lib.rs @@ -25,6 +25,7 @@ extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; diff --git a/compiler/rustc_codegen_gcc/src/mono_item.rs b/compiler/rustc_codegen_gcc/src/mono_item.rs index d8170fbb085a7..9aa015658fe42 100644 --- a/compiler/rustc_codegen_gcc/src/mono_item.rs +++ b/compiler/rustc_codegen_gcc/src/mono_item.rs @@ -1,8 +1,8 @@ use gccjit::Function; #[cfg(feature = "master")] use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; -use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index 6e7c31f7743d7..cf278694399f3 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -13,12 +13,12 @@ use std::time::Instant; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_hir::attrs::Linkage; use rustc_middle::dep_graph; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrs, SanitizerFnAttrs}; use rustc_middle::mono::Visibility; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index abc71f450a515..477cc25ee6f26 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -8,13 +8,13 @@ pub(crate) mod gpu_offload; use libc::{c_char, c_uint}; use rustc_abi::{self as abi, Align, CanonAbi, Size, WrappingRange}; +use rustc_attr_ir::{AttributeKind, UnrollAttr}; use rustc_codegen_ssa::MemFlags; use rustc_codegen_ssa::common::{IntPredicate, RealPredicate, SynchronizationScope, TypeKind}; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceRef; use rustc_codegen_ssa::traits::*; use rustc_data_structures::small_c_str::SmallCStr; -use rustc_hir::attrs::{AttributeKind, UnrollAttr}; use rustc_hir::def_id::DefId; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::ty::layout::{ diff --git a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs index 4860c79095c28..03058ba02d9dc 100644 --- a/compiler/rustc_codegen_llvm/src/builder/autodiff.rs +++ b/compiler/rustc_codegen_llvm/src/builder/autodiff.rs @@ -2,13 +2,13 @@ use std::ptr; use rustc_ast::expand::autodiff_attrs::{DiffActivity, DiffMode}; use rustc_ast::expand::typetree::FncTree; +use rustc_attr_ir::RustcAutodiff; use rustc_codegen_ssa::common::TypeKind; use rustc_codegen_ssa::mir::IntrinsicResult; use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue}; use rustc_codegen_ssa::mir::place::PlaceValue; use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, ReturnSlot}; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::RustcAutodiff; use rustc_middle::ty; use rustc_middle::ty::{PseudoCanonicalInput, Ty, TyCtxt, TypingEnv}; use rustc_span::bug; diff --git a/compiler/rustc_codegen_llvm/src/callee.rs b/compiler/rustc_codegen_llvm/src/callee.rs index c64c9ee3266c1..df18b029b02c0 100644 --- a/compiler/rustc_codegen_llvm/src/callee.rs +++ b/compiler/rustc_codegen_llvm/src/callee.rs @@ -4,6 +4,7 @@ //! and methods are represented as just a fn ptr and not a full //! closure. +use rustc_attr_ir::InlineAttr; use rustc_codegen_ssa::common; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Instance, TypeVisitableExt}; @@ -98,8 +99,7 @@ pub(crate) fn get_fn<'ll, 'tcx>(cx: &CodegenCx<'ll, 'tcx>, instance: Instance<'t let is_hidden = if is_generic { // This is a monomorphization of a generic function. if !(cx.tcx.sess.opts.share_generics() - || tcx.codegen_instance_attrs(instance.def).inline - == rustc_hir::attrs::InlineAttr::Never) + || tcx.codegen_instance_attrs(instance.def).inline == InlineAttr::Never) { // When not sharing generics, all instances are in the same // crate and have hidden visibility. diff --git a/compiler/rustc_codegen_llvm/src/consts.rs b/compiler/rustc_codegen_llvm/src/consts.rs index bbb1141a92e89..ec58c3cb6ad7a 100644 --- a/compiler/rustc_codegen_llvm/src/consts.rs +++ b/compiler/rustc_codegen_llvm/src/consts.rs @@ -1,10 +1,10 @@ use std::ops::Range; use rustc_abi::{Align, ExternAbi, HasDataLayout, Primitive, Scalar, Size, WrappingRange}; +use rustc_attr_ir::Linkage; +use rustc_attr_ir::lang_items::LangItem; use rustc_codegen_ssa::common; use rustc_codegen_ssa::traits::*; -use rustc_hir::attrs::Linkage; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs index fee852106c9b7..7665c824f1c48 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/gdb.rs @@ -1,9 +1,9 @@ // .debug_gdb_scripts binary section. use rustc_abi::Align; +use rustc_attr_ir::DebuggerVisualizerType; use rustc_codegen_ssa::base::collect_debugger_visualizers_transitive; use rustc_codegen_ssa::traits::*; -use rustc_hir::attrs::DebuggerVisualizerType; use rustc_hir::def_id::LOCAL_CRATE; use rustc_session::config::DebugInfo; use rustc_span::bug; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 454347a5e041e..3163139ba1f04 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -6,6 +6,7 @@ use rustc_abi::{ AddressSpace, Align, BackendRepr, CVariadicStatus, Float, HasDataLayout, NumScalableVectors, Primitive, Size, WrappingRange, }; +use rustc_attr_ir::find_attr; use rustc_codegen_ssa::RetagInfo; use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh}; use rustc_codegen_ssa::common::{IntPredicate, TypeKind}; @@ -16,7 +17,6 @@ use rustc_codegen_ssa::mir::place::{PlaceRef, PlaceValue}; use rustc_codegen_ssa::traits::*; use rustc_hir as hir; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::find_attr; use rustc_lint_defs::builtin::DEPRECATED_LLVM_INTRINSIC; use rustc_middle::mir::BinOp; use rustc_middle::ty::consts::ConstExt; diff --git a/compiler/rustc_codegen_llvm/src/mono_item.rs b/compiler/rustc_codegen_llvm/src/mono_item.rs index a25624550e3ad..6d9a35d5fea89 100644 --- a/compiler/rustc_codegen_llvm/src/mono_item.rs +++ b/compiler/rustc_codegen_llvm/src/mono_item.rs @@ -2,8 +2,8 @@ use std::borrow::Cow; use std::ffi::CString; use rustc_abi::AddressSpace; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::traits::*; -use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; diff --git a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs index a25131c5ff9b4..431783552bcd0 100644 --- a/compiler/rustc_codegen_ssa/src/assert_module_sources.rs +++ b/compiler/rustc_codegen_ssa/src/assert_module_sources.rs @@ -26,11 +26,10 @@ use std::borrow::Cow; use std::fmt; +use rustc_attr_ir::{CguFields, CguKind, find_attr}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::{DiagArgValue, IntoDiagArg}; -use rustc_hir::attrs::{CguFields, CguKind}; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::mono::CodegenUnitNameBuilder; use rustc_middle::ty::TyCtxt; use rustc_session::Session; @@ -87,7 +86,7 @@ struct AssertModuleSource<'tcx> { } impl<'tcx> AssertModuleSource<'tcx> { - fn check_attrs(&mut self, attrs: &[hir::Attribute]) { + fn check_attrs(&mut self, attrs: &[rustc_attr_ir::Attribute]) { for &(span, cgu_fields) in find_attr!(attrs, RustcCguTestAttr(e) => e) .into_flat_iter() diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index 2b9ed32f22773..e08a825aa7019 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -5,7 +5,7 @@ use std::path::{Path, PathBuf}; use std::{env, iter, mem, str}; use find_msvc_tools; -use rustc_hir::attrs::WindowsSubsystemKind; +use rustc_attr_ir::WindowsSubsystemKind; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE}; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::{ diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index c0e525471aeeb..d754095e28220 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -315,7 +315,7 @@ fn exported_generic_symbols_provider_local<'tcx>( .any(|o| matches!(o, rustc_session::config::Offload::Device(_))); if export_generics || is_device_offload { - use rustc_hir::attrs::Linkage; + use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_middle::mono::{MonoItem, Visibility}; use rustc_middle::ty::InstanceKind; @@ -386,9 +386,7 @@ fn exported_generic_symbols_provider_local<'tcx>( let item_is_offload = is_offload_instance(mono_item); if !item_is_offload && !tcx.sess.opts.share_generics() { - if tcx.codegen_fn_attrs(mono_item.def_id()).inline - == rustc_hir::attrs::InlineAttr::Never - { + if tcx.codegen_fn_attrs(mono_item.def_id()).inline == InlineAttr::Never { // this is OK, we explicitly allow sharing inline(never) across crates even // without share-generics. } else { diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index 8743d703940ec..f9dfd04faf2ac 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -9,14 +9,15 @@ use rustc_ast::expand::allocator::{ ALLOC_ERROR_HANDLER, ALLOCATOR_METHODS, AllocatorKind, AllocatorMethod, AllocatorMethodInput, AllocatorTy, }; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::target::Target; +use rustc_attr_ir::{DebuggerVisualizerType, EiiDecl, EiiImpl, OptimizeAttr, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::profiling::{get_resident_set_size, print_time_passes_entry}; use rustc_data_structures::sync::{IntoDynSyncSend, par_map}; use rustc_data_structures::unord::UnordMap; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{DebuggerVisualizerType, EiiDecl, EiiImpl, OptimizeAttr}; +use rustc_hir as hir; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE}; -use rustc_hir::{ItemId, Target, find_attr}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile; use rustc_middle::middle::dependency_format::{Dependencies, Linkage}; @@ -404,7 +405,7 @@ pub(crate) fn codegen_instance<'a, 'tcx: 'a, Bx: BuilderMethods<'a, 'tcx>>( mir::codegen_mir::(cx, instance); } -pub fn codegen_global_asm<'tcx, Cx>(cx: &mut Cx, item_id: ItemId) +pub fn codegen_global_asm<'tcx, Cx>(cx: &mut Cx, item_id: hir::ItemId) where Cx: LayoutOf<'tcx, LayoutOfResult = TyAndLayout<'tcx>> + AsmCodegenMethods<'tcx>, { diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs index 008b10c784d87..9bdafe70fb553 100644 --- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs +++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs @@ -53,7 +53,7 @@ struct InterestingAttributeDiagnosticSpans { no_mangle: Option, } -/// Process the builtin attrs ([`hir::Attribute`]) on the item. +/// Process the builtin attrs ([`rustc_attr_ir::Attribute`]) on the item. /// Many of them directly translate to codegen attrs. fn process_builtin_attrs( tcx: TyCtxt<'_>, @@ -66,7 +66,7 @@ fn process_builtin_attrs( let parsed_attrs = attrs .iter() - .filter_map(|attr| if let hir::Attribute::Parsed(attr) = attr { Some(attr) } else { None }); + .filter_map(|attr| if let Attribute::Parsed(attr) = attr { Some(attr) } else { None }); for attr in parsed_attrs { match attr { AttributeKind::Cold => codegen_fn_attrs.flags |= CodegenFnAttrFlags::COLD, diff --git a/compiler/rustc_codegen_ssa/src/common.rs b/compiler/rustc_codegen_ssa/src/common.rs index 4b54235cf71bc..9338a6b3769ed 100644 --- a/compiler/rustc_codegen_ssa/src/common.rs +++ b/compiler/rustc_codegen_ssa/src/common.rs @@ -1,8 +1,8 @@ #![allow(non_camel_case_types)] +use rustc_attr_ir::PeImportNameType; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::{DllCallingConvention, DllImport, DllImportSymbolType}; -use rustc_hir::attrs::PeImportNameType; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::mir::interpret::{GlobalAlloc, PointerArithmetic, Scalar}; use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{self, Instance, ScalarInt, TyCtxt}; diff --git a/compiler/rustc_codegen_ssa/src/lib.rs b/compiler/rustc_codegen_ssa/src/lib.rs index 4237898c52a6d..af37694136d24 100644 --- a/compiler/rustc_codegen_ssa/src/lib.rs +++ b/compiler/rustc_codegen_ssa/src/lib.rs @@ -18,11 +18,11 @@ use std::path::{Path, PathBuf}; use std::sync::Arc; use rustc_abi::Size; +use rustc_attr_ir::{CfgEntry, WindowsSubsystemKind}; use rustc_crate_store::{self as cstore, CrateSource}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_hir::CRATE_HIR_ID; -use rustc_hir::attrs::{CfgEntry, WindowsSubsystemKind}; use rustc_hir::def_id::CrateNum; use rustc_lint_defs::builtin::{LINKER_INFO, LINKER_MESSAGES}; use rustc_macros::{Decodable, Encodable}; diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index f99009a0f4243..6dbf9185eaebd 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -7,9 +7,9 @@ use rustc_abi::{ }; use rustc_ast as ast; use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece}; +use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::packed::Pu128; -use rustc_hir::attrs::AttributeKind; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint_defs::builtin::TAIL_CALL_TRACK_CALLER; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; use rustc_middle::mir::{self, AssertKind, InlineAsmMacro, SwitchTargets, UnwindTerminateReason}; diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 3162463d222ee..2fa6f3fc06550 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -1,5 +1,5 @@ use rustc_abi::{BackendRepr, Float, Integer, Primitive, RegKind}; -use rustc_hir::attrs::{InstructionSetAttr, Linkage}; +use rustc_attr_ir::{InstructionSetAttr, Linkage}; use rustc_hir::def_id::LOCAL_CRATE; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; use rustc_middle::mir::{self, InlineAsmOperand, START_BLOCK}; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index d11ba53e58c89..e017220c549b0 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -5,7 +5,7 @@ use rustc_abi as abi; use rustc_abi::{ Align, BackendRepr, FIRST_VARIANT, FieldIdx, Primitive, Size, TagEncoding, VariantIdx, Variants, }; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; use rustc_middle::ty::consts::ConstExt; diff --git a/compiler/rustc_codegen_ssa/src/mono_item.rs b/compiler/rustc_codegen_ssa/src/mono_item.rs index f2cd9e228f282..5150b8da8ff4d 100644 --- a/compiler/rustc_codegen_ssa/src/mono_item.rs +++ b/compiler/rustc_codegen_ssa/src/mono_item.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::Linkage; +use rustc_attr_ir::Linkage; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mono::{MonoItem, MonoItemData, Visibility}; use rustc_middle::ty::layout::HasTyCtxt; diff --git a/compiler/rustc_codegen_ssa/src/size_of_val.rs b/compiler/rustc_codegen_ssa/src/size_of_val.rs index d49dc61fc66fb..2467a2354a3dd 100644 --- a/compiler/rustc_codegen_ssa/src/size_of_val.rs +++ b/compiler/rustc_codegen_ssa/src/size_of_val.rs @@ -1,7 +1,7 @@ //! Computing the size and alignment of a value. use rustc_abi::{Align, WrappingRange}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; use rustc_middle::ty::{self, Ty}; use rustc_span::{DUMMY_SP, Span, bug}; diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b630155c144ea..3c9d5a4d633c3 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -1,6 +1,6 @@ +use rustc_attr_ir::InstructionSetAttr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_data_structures::unord::{UnordMap, UnordSet}; -use rustc_hir::attrs::InstructionSetAttr; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; use rustc_lint_defs::builtin::{AARCH64_SOFTFLOAT_NEON, X86_SOFTFLOAT_SSE}; diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index b7b694922bcfa..b6fdcb21bf2d4 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -3,7 +3,7 @@ use std::ops::Deref; use rustc_abi::{Align, Scalar, Size, WrappingRange}; use rustc_ast::expand::typetree::{FncTree, TypeTree}; -use rustc_hir::attrs::AttributeKind; +use rustc_attr_ir::AttributeKind; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrs; use rustc_middle::mir; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout}; diff --git a/compiler/rustc_codegen_ssa/src/traits/declare.rs b/compiler/rustc_codegen_ssa/src/traits/declare.rs index fc978024b8414..0a49678330b5a 100644 --- a/compiler/rustc_codegen_ssa/src/traits/declare.rs +++ b/compiler/rustc_codegen_ssa/src/traits/declare.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::Linkage; +use rustc_attr_ir::Linkage; use rustc_hir::def_id::DefId; use rustc_middle::mono::Visibility; use rustc_middle::ty::Instance; diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 40c907efcfeb0..92ef008610098 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -28,12 +28,6 @@ mod target_impls; #[doc(no_inline)] pub use hir::*; -// FIXME: Remove this use tree, replace by `rustc_attr_ir` imports -#[doc(hidden)] -pub use rustc_attr_ir::{ - self as attrs, Attribute, ConstStability, DefaultBodyStability, Stability, StabilityLevel, - StableSince, find_attr, target::Target, -}; pub use rustc_hir_id::*; pub use rustc_span::def_id; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index f35b901633fcb..ee151399bd849 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -3,13 +3,14 @@ use std::ops::ControlFlow; use rustc_abi::{ExternAbi, FieldIdx, MAX_SIMD_LANES, ScalableElt}; use rustc_attr_ir::ReprAttr::ReprPacked; +use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::unord::{UnordMap, UnordSet}; use rustc_errors::codes::*; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; use rustc_hir as hir; use rustc_hir::def::{CtorKind, DefKind}; -use rustc_hir::{Node, find_attr, intravisit}; +use rustc_hir::{Node, intravisit}; use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, ObligationCauseCode, TraitErrors, WellFormedLoc}; use rustc_lint_defs::builtin::{ diff --git a/compiler/rustc_hir_analysis/src/collect/dump.rs b/compiler/rustc_hir_analysis/src/collect/dump.rs index af6e689c33e13..9bf62e2846b9d 100644 --- a/compiler/rustc_hir_analysis/src/collect/dump.rs +++ b/compiler/rustc_hir_analysis/src/collect/dump.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{find_attr, intravisit}; +use rustc_hir::intravisit; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ObjectLifetimeDefault; use rustc_middle::ty::{self, TyCtxt, TypeVisitableExt, Unnormalized}; diff --git a/compiler/rustc_hir_typeck/Cargo.toml b/compiler/rustc_hir_typeck/Cargo.toml index 0e00615170aa2..840441ed3bbfa 100644 --- a/compiler/rustc_hir_typeck/Cargo.toml +++ b/compiler/rustc_hir_typeck/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs index a539898b8fced..025c64896edb7 100644 --- a/compiler/rustc_hir_typeck/src/callee.rs +++ b/compiler/rustc_hir_typeck/src/callee.rs @@ -2,12 +2,13 @@ use std::iter; use rustc_abi::{CanonAbi, ExternAbi}; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, StashKey, msg}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{self, CtorKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, find_attr}; +use rustc_hir::{self as hir, HirId}; use rustc_hir_analysis::autoderef::Autoderef; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes}; use rustc_infer::traits::{Obligation, ObligationCause, ObligationCauseCode}; diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 60fc0b8f9b214..4f6345e04070b 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -1,7 +1,7 @@ use std::cell::RefCell; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir_analysis::check::check_function_signature; use rustc_infer::infer::RegionVariableOrigin; diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs index 5c993141faadc..79b4eff9153b0 100644 --- a/compiler/rustc_hir_typeck/src/closure.rs +++ b/compiler/rustc_hir_typeck/src/closure.rs @@ -4,9 +4,9 @@ use std::iter; use std::ops::ControlFlow; use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::ErrorGuaranteed; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, InferResult}; use rustc_infer::traits::{ObligationCauseCode, PredicateObligations}; diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs index c13e68fea210d..af00194a95bf0 100644 --- a/compiler/rustc_hir_typeck/src/coercion.rs +++ b/compiler/rustc_hir_typeck/src/coercion.rs @@ -37,11 +37,11 @@ use std::ops::{ControlFlow, Deref}; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, struct_span_code_err}; use rustc_hir as hir; -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_infer::infer::relate::RelateResult; diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 55eecef732aa4..11fe876209ef2 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -1,7 +1,8 @@ +use rustc_attr_ir::find_attr; use rustc_errors::{Applicability, Diag, MultiSpan, listify, pluralize}; +use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::intravisit::Visitor; -use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_middle::ty::adjustment::AllowTwoPhase; use rustc_middle::ty::error::{ExpectedFound, TypeError}; diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index 8944d6a47488a..dbe5a51b25b45 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -8,6 +8,8 @@ use rustc_abi::{FIRST_VARIANT, FieldIdx}; use rustc_ast as ast; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_data_structures::thin_vec::ThinVec; use rustc_data_structures::unord::UnordMap; @@ -17,10 +19,9 @@ use rustc_errors::{ struct_span_code_err, }; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{ExprKind, HirId, QPath, find_attr, is_range_literal}; +use rustc_hir::{ExprKind, HirId, QPath, is_range_literal}; use rustc_hir_analysis::diagnostics::{NoFieldOnType, NoVariantNamed}; use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin}; @@ -56,7 +57,10 @@ use crate::{ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { pub(crate) fn precedence(&self, expr: &hir::Expr<'_>) -> ExprPrecedence { let has_attr = |id: HirId| -> bool { - self.tcx.hir_attrs(id).iter().any(hir::Attribute::is_prefix_attr_for_suggestions) + self.tcx + .hir_attrs(id) + .iter() + .any(rustc_attr_ir::Attribute::is_prefix_attr_for_suggestions) }; // Special case: range expressions are desugared to struct literals in HIR, diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs index 15383cd8a2a53..1ad6225a8c467 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs @@ -2,12 +2,12 @@ use std::collections::hash_map::Entry; use std::slice; use rustc_abi::FieldIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, Level, MultiSpan, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 789d06722f897..16aad0b91cb46 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3,12 +3,12 @@ use std::{fmt, iter}; use itertools::Itertools; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, a_or_an, listify, pluralize}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 68bb5e0a592bf..3450a0d29a86f 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -5,9 +5,9 @@ use core::iter; use hir::def_id::LocalDefId; use itertools::Itertools; use rustc_ast::util::parser::ExprPrecedence; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::packed::Pu128; use rustc_errors::{Applicability, Diag, MultiSpan, listify, msg}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; use rustc_hir::intravisit::Visitor; use rustc_hir::{ diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 04613cc33e54d..b3c7071199963 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -1,9 +1,9 @@ use rustc_abi::FieldIdx; use rustc_ast::InlineAsmTemplatePiece; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexSet; use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::ASM_SUB_REGISTER; use rustc_middle::ty::consts::ConstExt; diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index 3ce6c34176101..3fa3e067c6662 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -2,11 +2,12 @@ use std::collections::BTreeMap; use std::fmt; use Context::*; +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{Destination, Node, find_attr}; +use rustc_hir::{Destination, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::DesugaringKind; diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs index c3f18926143b9..4518e419aea0f 100644 --- a/compiler/rustc_hir_typeck/src/method/confirm.rs +++ b/compiler/rustc_hir_typeck/src/method/confirm.rs @@ -1,9 +1,8 @@ use std::fmt::Debug; use std::ops::Deref; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir as hir; -use rustc_hir::GenericArg; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir_analysis::hir_ty_lowering::generics::{ check_generic_arg_count_for_value_path, lower_generic_args, @@ -450,23 +449,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { &mut self, preceding_args: &[ty::GenericArg<'tcx>], param: &ty::GenericParamDef, - arg: &GenericArg<'_>, + arg: &hir::GenericArg<'_>, ) -> ty::GenericArg<'tcx> { match (¶m.kind, arg) { - (GenericParamDefKind::Lifetime, GenericArg::Lifetime(lt)) => self + (GenericParamDefKind::Lifetime, hir::GenericArg::Lifetime(lt)) => self .cfcx .fcx .lowerer() .lower_lifetime(lt, RegionInferReason::Param(param)) .into(), - (GenericParamDefKind::Type { .. }, GenericArg::Type(ty)) => { + (GenericParamDefKind::Type { .. }, hir::GenericArg::Type(ty)) => { // We handle the ambig portions of `Ty` in the match arms below self.cfcx.lower_ty(ty.as_unambig_ty()).raw.into() } - (GenericParamDefKind::Type { .. }, GenericArg::Infer(inf)) => { + (GenericParamDefKind::Type { .. }, hir::GenericArg::Infer(inf)) => { self.cfcx.lower_ty(&inf.to_ty()).raw.into() } - (GenericParamDefKind::Const { .. }, GenericArg::Const(ct)) => self + (GenericParamDefKind::Const { .. }, hir::GenericArg::Const(ct)) => self .cfcx // We handle the ambig portions of `ConstArg` in the match arms below .lower_const_arg( @@ -478,7 +477,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> { .skip_norm_wip(), ) .into(), - (GenericParamDefKind::Const { .. }, GenericArg::Infer(inf)) => { + (GenericParamDefKind::Const { .. }, hir::GenericArg::Infer(inf)) => { self.cfcx.ct_infer(Some(param), inf.span).into() } (kind, arg) => { diff --git a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs index ed61d557385dd..7a60c7472cf45 100644 --- a/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs +++ b/compiler/rustc_hir_typeck/src/method/prelude_edition_lints.rs @@ -3,9 +3,9 @@ use std::fmt::Write; use hir::def_id::DefId; use hir::{HirId, ItemKind}; use rustc_ast::join_path_idents; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_lint::{ARRAY_INTO_ITER, BOXED_SLICE_INTO_ITER}; use rustc_lint_defs::builtin::{RUST_2021_PRELUDE_COLLISIONS, RUST_2024_PRELUDE_COLLISIONS}; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 58e482adff190..178585984cf27 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -3,12 +3,13 @@ use std::cmp::max; use std::ops::Deref; use std::{assert_matches, debug_assert_matches}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::sso::SsoHashSet; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, ExprKind, HirId, Node, find_attr}; +use rustc_hir::{self as hir, ExprKind, HirId, Node}; use rustc_hir_analysis::autoderef::{self, Autoderef}; use rustc_infer::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse}; use rustc_infer::infer::{BoundRegionConversionTime, DefineOpaqueTypes, InferOk, TyCtxtInferExt}; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e074ebf01bda4..86bc6eeebc189 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -9,6 +9,9 @@ use std::path::PathBuf; use hir::Expr; use rustc_ast::ast::Mutability; +use rustc_attr_ir::diagnostic::CustomDiagnostic; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::unord::UnordSet; @@ -16,14 +19,10 @@ use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, MultiSpan, StashKey, StringPart, listify, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::diagnostic::CustomDiagnostic; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{ - self as hir, ExprKind, HirId, Node, PathSegment, QPath, find_attr, is_range_literal, -}; +use rustc_hir::{self as hir, ExprKind, HirId, Node, PathSegment, QPath, is_range_literal}; use rustc_infer::infer::{BoundRegionConversionTime, RegionVariableOrigin}; use rustc_middle::ty::fast_reject::{DeepRejectCtxt, TreatParams, simplify_type}; use rustc_middle::ty::print::{ diff --git a/compiler/rustc_hir_typeck/src/naked_functions.rs b/compiler/rustc_hir_typeck/src/naked_functions.rs index e241cd0797cc9..ce4893ce94b1f 100644 --- a/compiler/rustc_hir_typeck/src/naked_functions.rs +++ b/compiler/rustc_hir_typeck/src/naked_functions.rs @@ -1,9 +1,10 @@ //! Checks validity of naked functions. +use rustc_attr_ir::find_attr; use rustc_hir as hir; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::Visitor; -use rustc_hir::{ExprKind, HirIdSet, StmtKind, find_attr}; +use rustc_hir::{ExprKind, HirIdSet, StmtKind}; use rustc_middle::ty::TyCtxt; use rustc_span::{Span, span_bug}; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 298ea7da5d0e3..16c51ca625dcd 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -3,13 +3,13 @@ use std::{assert_matches, cmp}; use rustc_abi::FieldIdx; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashMap; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, Level, MultiSpan, pluralize, struct_span_code_err, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::{CtorKind, DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::pat_util::EnumerateAndAdjustIterator; diff --git a/compiler/rustc_hir_typeck/src/upvar.rs b/compiler/rustc_hir_typeck/src/upvar.rs index 0443d48c597f1..d0fcef549f018 100644 --- a/compiler/rustc_hir_typeck/src/upvar.rs +++ b/compiler/rustc_hir_typeck/src/upvar.rs @@ -33,13 +33,14 @@ use std::iter; use rustc_abi::FIRST_VARIANT; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::{ExtendUnord, UnordSet}; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, Visitor}; -use rustc_hir::{self as hir, HirId, find_attr}; +use rustc_hir::{self as hir, HirId}; use rustc_lint_defs::builtin::RUST_2021_INCOMPATIBLE_CLOSURE_CAPTURES; use rustc_middle::hir::place::{Place, PlaceBase, PlaceWithHirId, Projection, ProjectionKind}; use rustc_middle::mir::FakeReadCause; diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 5ae65ad26f916..19414d7466061 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -11,12 +11,13 @@ use std::mem; use std::ops::ControlFlow; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; use rustc_data_structures::unord::ExtendUnord; use rustc_errors::{E0720, ErrorGuaranteed}; use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{self, InferKind, Visitor}; -use rustc_hir::{self as hir, AmbigArg, HirId, find_attr}; +use rustc_hir::{self as hir, AmbigArg, HirId}; use rustc_infer::traits::solve::Goal; use rustc_middle::traits::ObligationCause; use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCoercion}; diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index cbf961f4cc58b..ebbecc4ba6867 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -10,6 +10,7 @@ rustc_ast = { path = "../rustc_ast" } rustc_ast_lowering = { path = "../rustc_ast_lowering" } rustc_ast_passes = { path = "../rustc_ast_passes" } rustc_ast_pretty = { path = "../rustc_ast_pretty" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_attr_parsing = { path = "../rustc_attr_parsing" } rustc_borrowck = { path = "../rustc_borrowck" } rustc_builtin_macros = { path = "../rustc_builtin_macros" } diff --git a/compiler/rustc_interface/src/limits.rs b/compiler/rustc_interface/src/limits.rs index 8f116cfdf6a86..a0791bb22df6d 100644 --- a/compiler/rustc_interface/src/limits.rs +++ b/compiler/rustc_interface/src/limits.rs @@ -8,7 +8,7 @@ //! Users can override these limits via an attribute on the crate like //! `#![recursion_limit="22"]`. This pass just looks for those attributes. -use rustc_hir::{Attribute, find_attr}; +use rustc_attr_ir::{Attribute, find_attr}; use rustc_middle::query::Providers; use rustc_session::{Limits, Session}; use rustc_structures::Limit; diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 610eb5fd099d2..d0df60d13feff 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -6,6 +6,7 @@ use std::sync::{Arc, LazyLock, OnceLock}; use std::{env, fs, iter}; use rustc_ast as ast; +use rustc_attr_ir::{Attribute, AttributeKind, find_attr}; use rustc_attr_parsing::{AttributeParser, ShouldEmit}; use rustc_codegen_ssa::traits::CodegenBackend; use rustc_codegen_ssa::{CompiledModules, CrateInfo}; @@ -21,10 +22,8 @@ use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_expand::base::{ExtCtxt, LintStoreExpand}; use rustc_feature::Features; use rustc_fs_util::try_canonicalize; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{LOCAL_CRATE, StableCrateId, StableCrateIdMap}; use rustc_hir::definitions::Definitions; -use rustc_hir::{Attribute, find_attr}; use rustc_incremental::setup_dep_graph; use rustc_lint::{BufferedEarlyLint, EarlyCheckNode, LintStore, unerased_lint_store}; use rustc_metadata::EncodedMetadata; @@ -1403,7 +1402,7 @@ pub(crate) fn parse_crate_name( attrs: &[ast::Attribute], emit_errors: ShouldEmit, ) -> Option<(Symbol, Span)> { - let rustc_hir::Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) = + let Attribute::Parsed(AttributeKind::CrateName { name, name_span, .. }) = AttributeParser::parse_limited_sym_should_emit( sess, attrs, diff --git a/compiler/rustc_lint/src/nonstandard_style.rs b/compiler/rustc_lint/src/nonstandard_style.rs index 551843947b758..66478f052d68b 100644 --- a/compiler/rustc_lint/src/nonstandard_style.rs +++ b/compiler/rustc_lint/src/nonstandard_style.rs @@ -1,13 +1,13 @@ use rustc_abi::ExternAbi; use rustc_ast as ast; -use rustc_attr_ir::{AttributeKind, ReprAttr, find_attr}; +use rustc_attr_ir::{Attribute, AttributeKind, ReprAttr, find_attr}; use rustc_attr_parsing::AttributeParser; use rustc_errors::{Applicability, Diag, DiagCtxtHandle, Diagnostic, Level}; use rustc_hir as hir; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{Attribute, GenericParamKind, PatExprKind, PatKind}; +use rustc_hir::{GenericParamKind, PatExprKind, PatKind}; use rustc_lint_defs::{declare_lint, declare_lint_pass}; use rustc_middle::hir::nested_filter::All; use rustc_middle::ty::AssocContainer; diff --git a/compiler/rustc_lint/src/types/literal.rs b/compiler/rustc_lint/src/types/literal.rs index f01d0190fb812..40681664e4437 100644 --- a/compiler/rustc_lint/src/types/literal.rs +++ b/compiler/rustc_lint/src/types/literal.rs @@ -3,8 +3,9 @@ use rustc_abi::{Integer, Size}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{DoubleS, HalfS, IeeeFloat, QuadS, Semantics, SingleS}; use rustc_ast as ast; +use rustc_attr_ir as attrs; use rustc_hir as hir; -use rustc_hir::{HirId, attrs}; +use rustc_hir::HirId; use rustc_middle::ty; use rustc_middle::ty::Ty; use rustc_middle::ty::layout::IntegerExt; diff --git a/compiler/rustc_lint/src/utils.rs b/compiler/rustc_lint/src/utils.rs index e3c0198775433..19b9dcc5a7267 100644 --- a/compiler/rustc_lint/src/utils.rs +++ b/compiler/rustc_lint/src/utils.rs @@ -1,4 +1,5 @@ -use rustc_hir::{Expr, ExprKind, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_hir::{Expr, ExprKind}; use rustc_span::sym; use crate::LateContext; diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f632862dc4627..09c5717c21213 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -225,7 +225,7 @@ pub fn msg(input: TokenStream) -> TokenStream { decl_derive! { [PrintAttribute] => /// Derives `PrintAttribute` for `AttributeKind`. - /// This macro is pretty specific to `rustc_hir::attrs` and likely not that useful in + /// This macro is pretty specific to `rustc_attr_ir` and likely not that useful in /// other places. It's deriving something close to `Debug` without printing some extraneous /// things like spans. print_attribute::print_attribute diff --git a/compiler/rustc_mir_build/Cargo.toml b/compiler/rustc_mir_build/Cargo.toml index ee858550c978f..94574384c1a12 100644 --- a/compiler/rustc_mir_build/Cargo.toml +++ b/compiler/rustc_mir_build/Cargo.toml @@ -10,6 +10,7 @@ rustc_abi = { path = "../rustc_abi" } rustc_apfloat = "0.2.0" rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_mir_build/src/builder/custom/mod.rs b/compiler/rustc_mir_build/src/builder/custom/mod.rs index bca258bf2ba61..f6c8658544b43 100644 --- a/compiler/rustc_mir_build/src/builder/custom/mod.rs +++ b/compiler/rustc_mir_build/src/builder/custom/mod.rs @@ -16,10 +16,10 @@ //! "top-level" constructs can be found in the `parse` submodule, while the parsing for statements, //! terminators, and everything below can be found in the `parse::instruction` submodule. //! - +use rustc_attr_ir as attrs; use rustc_data_structures::fx::FxHashMap; +use rustc_hir::HirId; use rustc_hir::def_id::DefId; -use rustc_hir::{HirId, attrs}; use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir::*; use rustc_middle::thir::*; diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs index 43936770ff762..eafbada566717 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs @@ -2,7 +2,7 @@ use rustc_abi::Size; use rustc_ast as ast; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_middle::mir; use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, Scalar}; diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 2fa0027f969c7..3a2e750d4904b 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -2,9 +2,9 @@ use rustc_abi::FieldIdx; use rustc_ast::{AsmMacro, InlineAsmOptions}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty}; diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index f9c399797a400..1e65ddf3372a9 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -11,8 +11,8 @@ use std::{debug_assert_matches, mem}; use itertools::Itertools; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{BindingMode, ByRef, LetStmt, LocalSource, Node}; use rustc_middle::middle::region::{self, TempLifetime}; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_build/src/builder/matches/test.rs b/compiler/rustc_mir_build/src/builder/matches/test.rs index 2e4d80d6d140d..d116806fc0b73 100644 --- a/compiler/rustc_mir_build/src/builder/matches/test.rs +++ b/compiler/rustc_mir_build/src/builder/matches/test.rs @@ -7,9 +7,9 @@ use std::sync::Arc; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_hir::RangeEnd; -use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::mir::*; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, GenericArg, Ty, TyCtxt}; diff --git a/compiler/rustc_mir_build/src/builder/mod.rs b/compiler/rustc_mir_build/src/builder/mod.rs index ba079eb726c3c..93114b59ed647 100644 --- a/compiler/rustc_mir_build/src/builder/mod.rs +++ b/compiler/rustc_mir_build/src/builder/mod.rs @@ -24,12 +24,13 @@ use itertools::Itertools; use rustc_abi::{ExternAbi, FieldIdx}; use rustc_apfloat::Float; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::sorted_map::SortedIndexMultiMap; use rustc_errors::ErrorGuaranteed; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node, find_attr}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, ItemLocalId, Node}; use rustc_index::bit_set::GrowableBitSet; use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs index 298e7898af7f8..5d421f6c3c885 100644 --- a/compiler/rustc_mir_build/src/check_tail_calls.rs +++ b/compiler/rustc_mir_build/src/check_tail_calls.rs @@ -1,6 +1,6 @@ use rustc_abi::ExternAbi; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::CRATE_DEF_ID; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e8cc5dc0edfd3..7b253390b53b6 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -2,10 +2,11 @@ use std::borrow::Cow; use std::mem; use rustc_ast::AsmMacro; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::DiagArgValue; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability, find_attr}; +use rustc_hir::{self as hir, BindingMode, ByRef, HirId, Mutability}; use rustc_lint_defs::builtin::{DEPRECATED_SAFE_2024, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE}; use rustc_middle::middle::codegen_fn_attrs::{TargetFeature, TargetFeatureKind}; use rustc_middle::thir::visit::Visitor; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index fa2b149f71926..a669e09475232 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,6 +1,6 @@ use rustc_abi::Size; use rustc_ast::{self as ast, UintTy}; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_span::bug; diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index 5bad7bec531c9..ce800491b9842 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -1,12 +1,12 @@ use itertools::Itertools; use rustc_abi::{FIRST_VARIANT, FieldIdx, Size, VariantIdx}; use rustc_ast::UnsafeBinderCastKind; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{AttributeKind, HasAttrs, find_attr}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{AttributeKind, HasAttrs}; +use rustc_hir::HirId; use rustc_hir::def::{CtorKind, CtorOf, DefKind, Res}; -use rustc_hir::{HirId, find_attr}; use rustc_index::Idx; use rustc_middle::hir::place::{ Place as HirPlace, PlaceBase as HirPlaceBase, ProjectionKind as HirProjectionKind, @@ -61,8 +61,8 @@ fn parsed_attrs(id: HirId, tcx: TyCtxt<'_>) -> ThinVec { HasAttrs::get_attrs(id, &tcx) .into_iter() .filter_map(|attr| match attr { - hir::Attribute::Parsed(attrkind) => Some(attrkind.clone()), - hir::Attribute::Unparsed(_) => None, + rustc_attr_ir::Attribute::Parsed(attrkind) => Some(attrkind.clone()), + rustc_attr_ir::Attribute::Unparsed(_) => None, }) .collect() } diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs index 28d10eeca2294..ad1227bb51df0 100644 --- a/compiler/rustc_mir_build/src/thir/cx/mod.rs +++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs @@ -2,12 +2,13 @@ //! structures into the THIR. The `builder` is generally ignorant of the tcx, //! etc., and instead goes through the `Cx` for most of its work. +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::steal::Steal; use rustc_errors::ErrorGuaranteed; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::{self as hir, HirId, find_attr}; +use rustc_hir::{self as hir, HirId}; use rustc_middle::thir::*; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::bug; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index 3aec71f400de3..4617831d593dd 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -2,11 +2,11 @@ use core::ops::ControlFlow; use rustc_abi::{FieldIdx, VariantIdx}; use rustc_apfloat::Float; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_errors::{Diag, msg}; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::find_attr; use rustc_index::Idx; use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; diff --git a/compiler/rustc_mir_transform/Cargo.toml b/compiler/rustc_mir_transform/Cargo.toml index 4d157391ed4b0..1697992960177 100644 --- a/compiler/rustc_mir_transform/Cargo.toml +++ b/compiler/rustc_mir_transform/Cargo.toml @@ -10,6 +10,7 @@ itertools = "0.15" rustc_abi = { path = "../rustc_abi" } rustc_arena = { path = "../rustc_arena" } rustc_ast = { path = "../rustc_ast" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_const_eval = { path = "../rustc_const_eval" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_errors = { path = "../rustc_errors" } diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs index 56fae176360a1..326936acb82cf 100644 --- a/compiler/rustc_mir_transform/src/check_alignment.rs +++ b/compiler/rustc_mir_transform/src/check_alignment.rs @@ -1,5 +1,5 @@ use rustc_abi::Align; -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::interpret::Scalar; use rustc_middle::mir::visit::PlaceContext; diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs index 9627f8988f283..101658808d949 100644 --- a/compiler/rustc_mir_transform/src/check_call_recursion.rs +++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs @@ -1,9 +1,9 @@ use std::ops::ControlFlow; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::graph::iterate::{ NodeStatus, TriColorDepthFirstSearch, TriColorVisitor, }; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_lint_defs::builtin::UNCONDITIONAL_RECURSION; use rustc_middle::mir::{self, BasicBlock, BasicBlocks, Body, Terminator, TerminatorKind}; diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs index ff62572cf2825..e6bc8949a6cad 100644 --- a/compiler/rustc_mir_transform/src/check_enums.rs +++ b/compiler/rustc_mir_transform/src/check_enums.rs @@ -1,6 +1,6 @@ use rustc_abi::{Scalar, Size, TagEncoding, Variants, WrappingRange}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/check_inline.rs b/compiler/rustc_mir_transform/src/check_inline.rs index c267fb171fba5..bea0d5c81eb2f 100644 --- a/compiler/rustc_mir_transform/src/check_inline.rs +++ b/compiler/rustc_mir_transform/src/check_inline.rs @@ -1,9 +1,8 @@ //! Check that a body annotated with `#[rustc_force_inline]` will not fail to inline based on its //! definition alone (irrespective of any specific caller). -use rustc_hir::attrs::InlineAttr; +use rustc_attr_ir::{InlineAttr, find_attr}; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::{Body, TerminatorKind}; use rustc_middle::ty; diff --git a/compiler/rustc_mir_transform/src/check_null.rs b/compiler/rustc_mir_transform/src/check_null.rs index ab2c48f0eb1e8..37443fed005d7 100644 --- a/compiler/rustc_mir_transform/src/check_null.rs +++ b/compiler/rustc_mir_transform/src/check_null.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext}; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/check_pointers.rs b/compiler/rustc_mir_transform/src/check_pointers.rs index a8c2626757e05..7c24e3d29c50a 100644 --- a/compiler/rustc_mir_transform/src/check_pointers.rs +++ b/compiler/rustc_mir_transform/src/check_pointers.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index 84359e710fe23..ab500d12b8aa3 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -24,10 +24,11 @@ use std::ops; use itertools::izip; use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxHashSet; use rustc_errors::pluralize; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::{self as hir, find_attr}; +use rustc_hir as hir; use rustc_index::bit_set::{BitMatrix, DenseBitSet}; use rustc_index::{Idx, IndexVec}; use rustc_infer::traits::TraitErrors; diff --git a/compiler/rustc_mir_transform/src/coroutine/mod.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs index 0608458d5e80c..a678e94994aa5 100644 --- a/compiler/rustc_mir_transform/src/coroutine/mod.rs +++ b/compiler/rustc_mir_transform/src/coroutine/mod.rs @@ -63,8 +63,8 @@ use drop::{ pub(super) use layout::mir_coroutine_witnesses; use layout::{CoroutineSavedLocals, compute_layout, locals_live_across_suspend_points}; use rustc_abi::{FieldIdx, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{self as hir, CoroutineDesugaring, CoroutineKind}; use rustc_index::bit_set::{BitMatrix, DenseBitSet}; use rustc_index::{Idx, IndexVec, indexvec}; diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs index a4d39f09b724d..2784e864e65e4 100644 --- a/compiler/rustc_mir_transform/src/coverage/query.rs +++ b/compiler/rustc_mir_transform/src/coverage/query.rs @@ -1,6 +1,6 @@ -use rustc_hir::attrs::CoverageAttrKind; +use rustc_attr_ir::{CoverageAttrKind, find_attr}; +use rustc_hir as hir; use rustc_hir::def::DefKind; -use rustc_hir::{self as hir, find_attr}; use rustc_index::bit_set::DenseBitSet; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::mir::coverage::{ diff --git a/compiler/rustc_mir_transform/src/cross_crate_inline.rs b/compiler/rustc_mir_transform/src/cross_crate_inline.rs index 8a4e7740650fc..a3aed4934374e 100644 --- a/compiler/rustc_mir_transform/src/cross_crate_inline.rs +++ b/compiler/rustc_mir_transform/src/cross_crate_inline.rs @@ -1,7 +1,7 @@ -use rustc_hir::attrs::InlineAttr; +use rustc_attr_ir::{InlineAttr, find_attr}; +use rustc_hir as hir; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalDefId; -use rustc_hir::{self as hir, find_attr}; use rustc_middle::mir::visit::Visitor; use rustc_middle::mir::*; use rustc_middle::query::Providers; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index 0786d0cf42ba4..d97441420e63f 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -2,8 +2,8 @@ use std::{fmt, iter, mem}; use itertools::Itertools; use rustc_abi::{FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{CoroutineDesugaring, CoroutineKind}; use rustc_index::Idx; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 3fd414579e6bb..f8df2eabdaf0d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -4,9 +4,9 @@ use std::ops::{Range, RangeFrom}; use std::{debug_assert_matches, iter}; use rustc_abi::{ExternAbi, FieldIdx}; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{InlineAttr, OptimizeAttr}; use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{InlineAttr, OptimizeAttr}; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; use rustc_index::Idx; diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index 9a39bd8d75d24..e02e29a2e23e0 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -1,8 +1,8 @@ //! Performs various peephole optimizations. use rustc_abi::{ExternAbi, Integer}; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index 1c598af1af98e..e25ed11d7a265 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -5,11 +5,12 @@ use std::fmt::Debug; use rustc_abi::{BackendRepr, FieldIdx, HasDataLayout, Size, TargetDataLayout, VariantIdx}; +use rustc_attr_ir::find_attr; use rustc_const_eval::const_eval::DummyMachine; use rustc_const_eval::interpret::{ImmTy, InterpCx, InterpResult, Projectable, Scalar, interp_ok}; use rustc_data_structures::fx::FxHashSet; +use rustc_hir::HirId; use rustc_hir::def::DefKind; -use rustc_hir::{HirId, find_attr}; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::UNCONDITIONAL_PANIC; diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index dc716c1886102..fcc1b6d8aaa30 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -1,8 +1,8 @@ use rustc_abi::FieldIdx; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry}; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_hir::find_attr; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::{UNUSED_ASSIGNMENTS, UNUSED_VARIABLES}; diff --git a/compiler/rustc_mir_transform/src/pass_manager.rs b/compiler/rustc_mir_transform/src/pass_manager.rs index 0e707688d72b4..f3f65a070e500 100644 --- a/compiler/rustc_mir_transform/src/pass_manager.rs +++ b/compiler/rustc_mir_transform/src/pass_manager.rs @@ -2,8 +2,8 @@ use std::cell::RefCell; use std::collections::hash_map::Entry; use std::sync::atomic::Ordering; +use rustc_attr_ir::OptimizeAttr; use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; -use rustc_hir::attrs::OptimizeAttr; use rustc_hir::def_id::DefId; use rustc_middle::mir::{Body, MirDumper, MirPhase, RuntimePhase}; use rustc_middle::ty::TyCtxt; diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index 1ddd77b9c16ce..a2a9f6c37456f 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -1,9 +1,9 @@ use std::{assert_matches, fmt, iter}; use rustc_abi::{ExternAbi, FIRST_VARIANT, FieldIdx, VariantIdx}; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_index::{Idx, IndexVec}; use rustc_middle::mir::visit::{MutVisitor, PlaceContext}; diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 1d91bc1cab988..0570895532370 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -1,4 +1,4 @@ -use rustc_hir::attrs::lang_items::LangItem; +use rustc_attr_ir::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource}; use rustc_index::{Idx, IndexVec}; diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs index 4ed824db17718..591c84bb17689 100644 --- a/compiler/rustc_mir_transform/src/sroa.rs +++ b/compiler/rustc_mir_transform/src/sroa.rs @@ -1,6 +1,6 @@ use rustc_abi::FieldIdx; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; -use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_index::bit_set::{DenseBitSet, GrowableBitSet}; use rustc_middle::mir::visit::*; diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs index b11c5c8d1da5a..28a508bde9eca 100644 --- a/compiler/rustc_mir_transform/src/validate.rs +++ b/compiler/rustc_mir_transform/src/validate.rs @@ -1,9 +1,9 @@ //! Validates the MIR to ensure that invariants are upheld. use rustc_abi::{ExternAbi, FIRST_VARIANT, Size}; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_infer::infer::TyCtxtInferExt; diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 0306a0bc349af..cc5bf5bcb1976 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -315,7 +315,8 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { /// Extracts the first `lang = "$name"` out of a list of attributes. /// The `#[panic_handler]` attribute is also extracted out when found. /// -/// This function is used for `ast::Attribute`, for `hir::Attribute` use the `find_attr!` macro with `AttributeKind::Lang` +/// This function is used for `ast::Attribute`, for `rustc_attr_ir::Attribute` +/// use `find_attr!(attrs, Lang(lang_item))`. pub(crate) fn extract_ast(attrs: &[rustc_ast::ast::Attribute]) -> Option<(Symbol, Span)> { attrs.iter().find_map(|attr| { Some(match attr { diff --git a/compiler/rustc_public_bridge/Cargo.toml b/compiler/rustc_public_bridge/Cargo.toml index d131f217cc617..820ab720e3ce3 100644 --- a/compiler/rustc_public_bridge/Cargo.toml +++ b/compiler/rustc_public_bridge/Cargo.toml @@ -6,6 +6,7 @@ edition = "2024" [dependencies] # tidy-alphabetical-start rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_crate_store = { path = "../rustc_crate_store" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index c653aac541c2a..f8ab16a54b451 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -5,9 +5,9 @@ use std::iter; use rustc_abi::{Endian, Layout, ReprOptions}; +use rustc_attr_ir::Attribute; +use rustc_attr_ir::lang_items::LangItem; use rustc_crate_store::ForeignModule; -use rustc_hir::Attribute; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::{BinOp, Body, Const as MirConst, ConstValue, UnOp}; diff --git a/compiler/rustc_sanitizers/Cargo.toml b/compiler/rustc_sanitizers/Cargo.toml index 75270e00ecc5b..4cad88f14537f 100644 --- a/compiler/rustc_sanitizers/Cargo.toml +++ b/compiler/rustc_sanitizers/Cargo.toml @@ -8,6 +8,7 @@ edition = "2024" bitflags = "2.5.0" libc = "0.2" rustc_abi = { path = "../rustc_abi" } +rustc_attr_ir = { path = "../rustc_attr_ir" } rustc_data_structures = { path = "../rustc_data_structures" } rustc_hir = { path = "../rustc_hir" } rustc_middle = { path = "../rustc_middle" } diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index 0b3beb329e0f8..ec21973d21e93 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -8,10 +8,10 @@ use std::fmt::Write as _; use rustc_abi::{ExternAbi, Integer}; +use rustc_attr_ir::find_attr; use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, CASE_INSENSITIVE, ToBaseN}; use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; -use rustc_hir::find_attr; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs index 017e35056f45b..e5b4628374ce5 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/transform.rs @@ -6,8 +6,9 @@ use std::iter; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::{self as hir, find_attr}; +use rustc_attr_ir::find_attr; +use rustc_attr_ir::lang_items::LangItem; +use rustc_hir as hir; use rustc_middle::ty::{ self, AssocContainer, ExistentialPredicateStableCmpExt as _, Instance, IntTy, List, TraitRef, Ty, TyCtxt, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, UintTy, From bab2d8322dedfd57844eed94a1e64561ec1ad479 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:36:06 +0200 Subject: [PATCH 0850/1309] compiler: remove rustc_hir attr re-exports --- src/attributes.rs | 4 ++-- src/base.rs | 3 +-- src/callee.rs | 2 +- src/consts.rs | 2 +- src/lib.rs | 1 + src/mono_item.rs | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/attributes.rs b/src/attributes.rs index 41db5e83bdcc9..2e9bf42874148 100644 --- a/src/attributes.rs +++ b/src/attributes.rs @@ -4,8 +4,8 @@ use gccjit::Function; #[cfg(feature = "master")] use rustc_abi::{CanonAbi, InterruptKind}; #[cfg(feature = "master")] -use rustc_hir::attrs::InlineAttr; -use rustc_hir::attrs::InstructionSetAttr; +use rustc_attr_ir::InlineAttr; +use rustc_attr_ir::InstructionSetAttr; #[cfg(feature = "master")] use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; #[cfg(feature = "master")] diff --git a/src/base.rs b/src/base.rs index 0dd46558ed796..07214096b3e49 100644 --- a/src/base.rs +++ b/src/base.rs @@ -4,11 +4,10 @@ use std::time::Instant; #[cfg(feature = "master")] use gccjit::VarAttribute; use gccjit::{CType, FunctionType, GlobalKind}; +use rustc_attr_ir::{AttributeKind, Linkage, find_attr}; use rustc_codegen_ssa::ModuleCodegen; use rustc_codegen_ssa::base::maybe_create_entry_wrapper; use rustc_codegen_ssa::mono_item::MonoItemExt; -use rustc_hir::attrs::{AttributeKind, Linkage}; -use rustc_hir::find_attr; use rustc_middle::dep_graph; #[cfg(feature = "master")] use rustc_middle::mono::Visibility; diff --git a/src/callee.rs b/src/callee.rs index d3f412180da55..21a0bbb4030bb 100644 --- a/src/callee.rs +++ b/src/callee.rs @@ -106,7 +106,7 @@ pub fn get_fn<'gcc, 'tcx>(cx: &CodegenCx<'gcc, 'tcx>, instance: Instance<'tcx>) // This is a monomorphization of a generic function. if !(cx.tcx.sess.opts.share_generics() || tcx.codegen_instance_attrs(instance.def).inline - == rustc_hir::attrs::InlineAttr::Never) + == rustc_attr_ir::InlineAttr::Never) { // When not sharing generics, all instances are in the same // crate and have hidden visibility. diff --git a/src/consts.rs b/src/consts.rs index 8576dfe079163..c58ab6d2a9bef 100644 --- a/src/consts.rs +++ b/src/consts.rs @@ -4,10 +4,10 @@ use std::ops::Range; use gccjit::{FnAttribute, VarAttribute, Visibility}; use gccjit::{Function, GlobalKind, LValue, RValue, ToRValue, Type}; use rustc_abi::{self as abi, Align, HasDataLayout, Primitive, Size, WrappingRange}; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::traits::{ BaseTypeCodegenMethods, ConstCodegenMethods, StaticCodegenMethods, }; -use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; diff --git a/src/lib.rs b/src/lib.rs index 7abbda4a37dc1..f30004c8561f7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -25,6 +25,7 @@ extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_codegen_ssa; extern crate rustc_data_structures; extern crate rustc_errors; diff --git a/src/mono_item.rs b/src/mono_item.rs index d8170fbb085a7..9aa015658fe42 100644 --- a/src/mono_item.rs +++ b/src/mono_item.rs @@ -1,8 +1,8 @@ use gccjit::Function; #[cfg(feature = "master")] use gccjit::{FnAttribute, GlobalKind, ToRValue, Type, VarAttribute}; +use rustc_attr_ir::Linkage; use rustc_codegen_ssa::traits::PreDefineCodegenMethods; -use rustc_hir::attrs::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; From c0db53adc1d47d57240d47be6fe21f7c0ee55f42 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:36:17 +0200 Subject: [PATCH 0851/1309] fix clippy imports --- .../src/arbitrary_source_item_ordering.rs | 7 +++---- .../src/doc/doc_suspicious_footnotes.rs | 4 ++-- .../clippy_lints/src/functions/must_use.rs | 4 ++-- .../clippy/clippy_lints/src/incompatible_msrv.rs | 4 ++-- .../src/methods/string_from_utf8_as_bytes.rs | 2 +- .../clippy_lints/src/needless_pass_by_value.rs | 5 +++-- .../clippy_lints/src/std_instead_of_core.rs | 3 ++- src/tools/clippy/clippy_utils/src/lib.rs | 16 +++++++++++++--- src/tools/clippy/clippy_utils/src/msrvs.rs | 4 ++-- .../clippy_utils/src/qualify_min_const_fn.rs | 4 ++-- 10 files changed, 32 insertions(+), 21 deletions(-) diff --git a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs index 5da0323167fe6..c65ea5e5ae9fd 100644 --- a/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/src/tools/clippy/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -6,15 +6,14 @@ use clippy_config::types::{ }; use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_cfg_test; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_hir::{ - Attribute, FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, - VariantData, + FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext, impl_lint_pass}; use rustc_middle::ty::{AssocKind, TyCtxt}; -use rustc_span::{Ident, Symbol, bug}; use rustc_span::def_id::LocalModId; +use rustc_span::{Ident, Symbol, bug}; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs index 6c117ad2a4df8..b2b6bbe3e4b20 100644 --- a/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/src/tools/clippy/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::attr::AttributeExt as _; use rustc_ast::token::{CommentKind, DocFragmentKind}; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::{AttrStyle, Attribute}; +use rustc_hir::AttrStyle; use rustc_lint::{LateContext, LintContext as _}; use std::ops::Range; diff --git a/src/tools/clippy/clippy_lints/src/functions/must_use.rs b/src/tools/clippy/clippy_lints/src/functions/must_use.rs index bca9705f6ed59..4f47f158c7b73 100644 --- a/src/tools/clippy/clippy_lints/src/functions/must_use.rs +++ b/src/tools/clippy/clippy_lints/src/functions/must_use.rs @@ -1,9 +1,9 @@ use hir::FnSig; -use rustc_attr_ir::find_attr; +use rustc_attr_ir::{Attribute, find_attr}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, Attribute, QPath}; +use rustc_hir::{self as hir, QPath}; use rustc_lint::unused::must_use::MustUsePath; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs index a09b3aa0135f8..600f627c03d37 100644 --- a/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs +++ b/src/tools/clippy/clippy_lints/src/incompatible_msrv.rs @@ -2,9 +2,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::Msrv; use clippy_utils::{is_in_const_context, is_in_test, sym}; -use rustc_attr_ir::{RustcVersion, find_attr}; +use rustc_attr_ir::{RustcVersion, StabilityLevel, StableSince, find_attr}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, StabilityLevel, StableSince}; +use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId}; diff --git a/src/tools/clippy/clippy_lints/src/methods/string_from_utf8_as_bytes.rs b/src/tools/clippy/clippy_lints/src/methods/string_from_utf8_as_bytes.rs index 97506d795cd72..f71ffd3a488e0 100644 --- a/src/tools/clippy/clippy_lints/src/methods/string_from_utf8_as_bytes.rs +++ b/src/tools/clippy/clippy_lints/src/methods/string_from_utf8_as_bytes.rs @@ -4,8 +4,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::{method_calls, sym}; use rustc_ast::BorrowKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs index d6f30e1865853..2420ef889ee74 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs @@ -5,12 +5,13 @@ use clippy_utils::ty::{implements_trait, implements_trait_with_env_from_iter, is use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{is_self, peel_hir_ty_options, strip_pat_refs, sym}; use rustc_abi::ExternAbi; +use rustc_attr_ir::Attribute; use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Attribute, BindingMode, Body, ExprKind, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, Mutability, Node, - PatKind, QPath, TyKind, + BindingMode, Body, ExprKind, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath, + TyKind, }; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs index 25839a4e0b003..432d84a87ee17 100644 --- a/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs +++ b/src/tools/clippy/clippy_lints/src/std_instead_of_core.rs @@ -3,10 +3,11 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::Msrv; use clippy_utils::paths::{PathNS, lookup_path}; +use rustc_attr_ir::{StabilityLevel, StableSince}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, StabilityLevel, StableSince, UseKind, UseTree}; +use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext as _, impl_lint_pass}; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol, sym}; diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 81d8ab4fb3ec7..9fd934cac7ecf 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -82,9 +82,9 @@ use itertools::Itertools as _; use rustc_abi::Integer; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_ast::{LitIntType, join_path_syms}; -use rustc_attr_ir::CfgEntry; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::lang_items::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_attr_ir::{CfgEntry, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexmap; use rustc_data_structures::packed::Pu128; @@ -99,7 +99,6 @@ use rustc_hir::{ FieldDef, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, HirIdSet, Impl, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, Variant, def, - find_attr, }; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext as _}; @@ -1672,7 +1671,18 @@ pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 { (u << amt) >> amt } -pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { +/// Checks if an attribute is present. +/// +/// NOTE: this does not work for most attributes: +/// - parsed attributes: use `find_attr!` for these +/// - tool attributes: these have multi-segmented names +/// (and diagnostic attrs are parsed anyway) +/// +/// At this time, these only work for lint attributes (allow, warn, etc) +/// and derive helpers. +/// +/// FIXME: remove after lint attributes are parsed +pub fn has_attr(attrs: &[rustc_attr_ir::Attribute], symbol: Symbol) -> bool { attrs.iter().any(|attr| attr.has_name(symbol)) } diff --git a/src/tools/clippy/clippy_utils/src/msrvs.rs b/src/tools/clippy/clippy_utils/src/msrvs.rs index 5f30692a677af..9bb9bcce51762 100644 --- a/src/tools/clippy/clippy_utils/src/msrvs.rs +++ b/src/tools/clippy/clippy_utils/src/msrvs.rs @@ -1,12 +1,12 @@ use crate::{is_in_const_context, sym}; use rustc_ast::Attribute; use rustc_ast::attr::AttributeExt; -use rustc_attr_ir::RustcVersion; +use rustc_attr_ir::{RustcVersion, StabilityLevel, StableSince}; use rustc_attr_parsing::parse_version; use rustc_data_structures::smallvec::SmallVec; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{Constness, HirId, StabilityLevel, StableSince}; +use rustc_hir::{Constness, HirId}; use rustc_lint::LateContext; use rustc_middle::ty::TyCtxt; use rustc_session::Session; diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs index 5249daedd269e..33853a3c5ed91 100644 --- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs +++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs @@ -4,11 +4,11 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::{self, Msrv}; -use rustc_attr_ir::RustcVersion; use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{RustcVersion, StableSince}; use rustc_const_eval::check_consts::ConstCx; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, StableSince}; +use rustc_hir::{self as hir, HirId}; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::Obligation; use rustc_lint::LateContext; From 53f980627aa9d7253f215beb81e89f4bb1aca5be Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:36:17 +0200 Subject: [PATCH 0852/1309] fix clippy imports --- .../src/arbitrary_source_item_ordering.rs | 7 +++---- clippy_lints/src/doc/doc_suspicious_footnotes.rs | 4 ++-- clippy_lints/src/functions/must_use.rs | 4 ++-- clippy_lints/src/incompatible_msrv.rs | 4 ++-- .../src/methods/string_from_utf8_as_bytes.rs | 2 +- clippy_lints/src/needless_pass_by_value.rs | 5 +++-- clippy_lints/src/std_instead_of_core.rs | 3 ++- clippy_utils/src/lib.rs | 16 +++++++++++++--- clippy_utils/src/msrvs.rs | 4 ++-- clippy_utils/src/qualify_min_const_fn.rs | 4 ++-- 10 files changed, 32 insertions(+), 21 deletions(-) diff --git a/clippy_lints/src/arbitrary_source_item_ordering.rs b/clippy_lints/src/arbitrary_source_item_ordering.rs index 5da0323167fe6..c65ea5e5ae9fd 100644 --- a/clippy_lints/src/arbitrary_source_item_ordering.rs +++ b/clippy_lints/src/arbitrary_source_item_ordering.rs @@ -6,15 +6,14 @@ use clippy_config::types::{ }; use clippy_utils::diagnostics::span_lint_and_note; use clippy_utils::is_cfg_test; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_hir::{ - Attribute, FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, - VariantData, + FieldDef, ImplItemId, IsAuto, Item, ItemKind, Mod, OwnerId, QPath, TraitItemId, TyKind, Variant, VariantData, }; use rustc_lint::{LateContext, LateLintPass, LintContext, impl_lint_pass}; use rustc_middle::ty::{AssocKind, TyCtxt}; -use rustc_span::{Ident, Symbol, bug}; use rustc_span::def_id::LocalModId; +use rustc_span::{Ident, Symbol, bug}; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/doc/doc_suspicious_footnotes.rs b/clippy_lints/src/doc/doc_suspicious_footnotes.rs index 6c117ad2a4df8..b2b6bbe3e4b20 100644 --- a/clippy_lints/src/doc/doc_suspicious_footnotes.rs +++ b/clippy_lints/src/doc/doc_suspicious_footnotes.rs @@ -1,9 +1,9 @@ use clippy_utils::diagnostics::span_lint_and_then; use rustc_ast::attr::AttributeExt as _; use rustc_ast::token::{CommentKind, DocFragmentKind}; -use rustc_attr_ir::AttributeKind; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_errors::Applicability; -use rustc_hir::{AttrStyle, Attribute}; +use rustc_hir::AttrStyle; use rustc_lint::{LateContext, LintContext as _}; use std::ops::Range; diff --git a/clippy_lints/src/functions/must_use.rs b/clippy_lints/src/functions/must_use.rs index bca9705f6ed59..4f47f158c7b73 100644 --- a/clippy_lints/src/functions/must_use.rs +++ b/clippy_lints/src/functions/must_use.rs @@ -1,9 +1,9 @@ use hir::FnSig; -use rustc_attr_ir::find_attr; +use rustc_attr_ir::{Attribute, find_attr}; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::def_id::DefIdSet; -use rustc_hir::{self as hir, Attribute, QPath}; +use rustc_hir::{self as hir, QPath}; use rustc_lint::unused::must_use::MustUsePath; use rustc_lint::{LateContext, LintContext as _}; use rustc_middle::ty::{self, Ty}; diff --git a/clippy_lints/src/incompatible_msrv.rs b/clippy_lints/src/incompatible_msrv.rs index a09b3aa0135f8..600f627c03d37 100644 --- a/clippy_lints/src/incompatible_msrv.rs +++ b/clippy_lints/src/incompatible_msrv.rs @@ -2,9 +2,9 @@ use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::msrvs::Msrv; use clippy_utils::{is_in_const_context, is_in_test, sym}; -use rustc_attr_ir::{RustcVersion, find_attr}; +use rustc_attr_ir::{RustcVersion, StabilityLevel, StableSince, find_attr}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId, StabilityLevel, StableSince}; +use rustc_hir::{self as hir, AmbigArg, Expr, ExprKind, HirId}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::def_id::{CrateNum, DefId}; diff --git a/clippy_lints/src/methods/string_from_utf8_as_bytes.rs b/clippy_lints/src/methods/string_from_utf8_as_bytes.rs index 97506d795cd72..f71ffd3a488e0 100644 --- a/clippy_lints/src/methods/string_from_utf8_as_bytes.rs +++ b/clippy_lints/src/methods/string_from_utf8_as_bytes.rs @@ -4,8 +4,8 @@ use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; use clippy_utils::source::{snippet_with_applicability, snippet_with_context}; use clippy_utils::{method_calls, sym}; use rustc_ast::BorrowKind; +use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; diff --git a/clippy_lints/src/needless_pass_by_value.rs b/clippy_lints/src/needless_pass_by_value.rs index d6f30e1865853..2420ef889ee74 100644 --- a/clippy_lints/src/needless_pass_by_value.rs +++ b/clippy_lints/src/needless_pass_by_value.rs @@ -5,12 +5,13 @@ use clippy_utils::ty::{implements_trait, implements_trait_with_env_from_iter, is use clippy_utils::visitors::{Descend, for_each_expr_without_closures}; use clippy_utils::{is_self, peel_hir_ty_options, strip_pat_refs, sym}; use rustc_abi::ExternAbi; +use rustc_attr_ir::Attribute; use rustc_attr_ir::lang_items::LangItem; use rustc_errors::{Applicability, Diag}; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Attribute, BindingMode, Body, ExprKind, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, Mutability, Node, - PatKind, QPath, TyKind, + BindingMode, Body, ExprKind, FnDecl, GenericArg, HirId, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath, + TyKind, }; use rustc_hir_typeck::expr_use_visitor as euv; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; diff --git a/clippy_lints/src/std_instead_of_core.rs b/clippy_lints/src/std_instead_of_core.rs index 25839a4e0b003..432d84a87ee17 100644 --- a/clippy_lints/src/std_instead_of_core.rs +++ b/clippy_lints/src/std_instead_of_core.rs @@ -3,10 +3,11 @@ use clippy_utils::diagnostics::{span_lint_and_help, span_lint_and_sugg}; use clippy_utils::is_from_proc_macro; use clippy_utils::msrvs::Msrv; use clippy_utils::paths::{PathNS, lookup_path}; +use rustc_attr_ir::{StabilityLevel, StableSince}; use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Namespace, Res}; use rustc_hir::def_id::DefId; -use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, StabilityLevel, StableSince, UseKind, UseTree}; +use rustc_hir::{Block, Body, HirId, Item, ItemKind, Path, PathSegment, UseKind, UseTree}; use rustc_lint::{LateContext, LateLintPass, Lint, LintContext as _, impl_lint_pass}; use rustc_span::symbol::kw; use rustc_span::{Ident, Span, Symbol, sym}; diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 81d8ab4fb3ec7..9fd934cac7ecf 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -82,9 +82,9 @@ use itertools::Itertools as _; use rustc_abi::Integer; use rustc_ast::ast::{self, LitKind, RangeLimits}; use rustc_ast::{LitIntType, join_path_syms}; -use rustc_attr_ir::CfgEntry; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::lang_items::LangItem::{OptionNone, OptionSome, ResultErr, ResultOk}; +use rustc_attr_ir::{CfgEntry, find_attr}; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::indexmap; use rustc_data_structures::packed::Pu128; @@ -99,7 +99,6 @@ use rustc_hir::{ FieldDef, FnDecl, FnRetTy, GenericArg, GenericArgs, HirId, HirIdMap, HirIdSet, Impl, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MatchSource, Mutability, Node, OwnerId, OwnerNode, Param, Pat, PatExpr, PatExprKind, PatKind, Path, PathSegment, QPath, Stmt, StmtKind, TraitFn, TraitItem, TraitItemKind, TraitRef, TyKind, UnOp, Variant, def, - find_attr, }; use rustc_lexer::{FrontmatterAllowed, TokenKind, tokenize}; use rustc_lint::{LateContext, Level, Lint, LintContext as _}; @@ -1672,7 +1671,18 @@ pub fn clip(tcx: TyCtxt<'_>, u: u128, ity: UintTy) -> u128 { (u << amt) >> amt } -pub fn has_attr(attrs: &[hir::Attribute], symbol: Symbol) -> bool { +/// Checks if an attribute is present. +/// +/// NOTE: this does not work for most attributes: +/// - parsed attributes: use `find_attr!` for these +/// - tool attributes: these have multi-segmented names +/// (and diagnostic attrs are parsed anyway) +/// +/// At this time, these only work for lint attributes (allow, warn, etc) +/// and derive helpers. +/// +/// FIXME: remove after lint attributes are parsed +pub fn has_attr(attrs: &[rustc_attr_ir::Attribute], symbol: Symbol) -> bool { attrs.iter().any(|attr| attr.has_name(symbol)) } diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 5f30692a677af..9bb9bcce51762 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -1,12 +1,12 @@ use crate::{is_in_const_context, sym}; use rustc_ast::Attribute; use rustc_ast::attr::AttributeExt; -use rustc_attr_ir::RustcVersion; +use rustc_attr_ir::{RustcVersion, StabilityLevel, StableSince}; use rustc_attr_parsing::parse_version; use rustc_data_structures::smallvec::SmallVec; use rustc_hir::def::DefKind; use rustc_hir::def_id::DefId; -use rustc_hir::{Constness, HirId, StabilityLevel, StableSince}; +use rustc_hir::{Constness, HirId}; use rustc_lint::LateContext; use rustc_middle::ty::TyCtxt; use rustc_session::Session; diff --git a/clippy_utils/src/qualify_min_const_fn.rs b/clippy_utils/src/qualify_min_const_fn.rs index 5249daedd269e..33853a3c5ed91 100644 --- a/clippy_utils/src/qualify_min_const_fn.rs +++ b/clippy_utils/src/qualify_min_const_fn.rs @@ -4,11 +4,11 @@ // differ from the time of `rustc` even if the name stays the same. use crate::msrvs::{self, Msrv}; -use rustc_attr_ir::RustcVersion; use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{RustcVersion, StableSince}; use rustc_const_eval::check_consts::ConstCx; use rustc_hir::def_id::DefId; -use rustc_hir::{self as hir, HirId, StableSince}; +use rustc_hir::{self as hir, HirId}; use rustc_infer::infer::TyCtxtInferExt as _; use rustc_infer::traits::Obligation; use rustc_lint::LateContext; From b01a2f8f4f52a55067695e7a185f9368c9ea9026 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 12:41:28 +0200 Subject: [PATCH 0853/1309] fix rustdoc imports --- src/librustdoc/clean/cfg.rs | 25 +++--- src/librustdoc/clean/cfg/tests.rs | 2 +- src/librustdoc/clean/inline.rs | 19 ++--- src/librustdoc/clean/mod.rs | 28 ++++--- src/librustdoc/clean/simplify.rs | 2 +- src/librustdoc/clean/types.rs | 23 +++--- src/librustdoc/clean/utils.rs | 5 +- src/librustdoc/doctest.rs | 4 +- src/librustdoc/doctest/rust.rs | 4 +- src/librustdoc/formats/cache.rs | 2 +- src/librustdoc/html/format.rs | 2 +- src/librustdoc/html/render/context.rs | 3 +- src/librustdoc/html/render/mod.rs | 12 +-- src/librustdoc/html/render/search_index.rs | 2 +- src/librustdoc/json/conversions.rs | 80 +++++++++++-------- src/librustdoc/json/ids.rs | 2 +- src/librustdoc/lib.rs | 1 + .../passes/collect_intra_doc_links.rs | 4 +- src/librustdoc/passes/collect_trait_impls.rs | 3 +- src/librustdoc/passes/propagate_doc_cfg.rs | 17 ++-- src/librustdoc/passes/propagate_stability.rs | 2 +- src/librustdoc/visit_ast.rs | 4 +- 22 files changed, 132 insertions(+), 114 deletions(-) diff --git a/src/librustdoc/clean/cfg.rs b/src/librustdoc/clean/cfg.rs index db63dbaa24663..b43d50b19b2a0 100644 --- a/src/librustdoc/clean/cfg.rs +++ b/src/librustdoc/clean/cfg.rs @@ -8,13 +8,11 @@ use std::sync::Arc; use std::{fmt, mem, ops}; use itertools::Either; -use rustc_data_structures::fx::FxHashMap; -use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; -use rustc_hir as hir; -use rustc_hir::Attribute; -use rustc_hir::attrs::{ +use rustc_attr_ir::{ AttributeKind, CfgEntry, CfgHideShow, DocCfgHideShow, DocCfgHideShowValue, HideOrShow, }; +use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_middle::ty::TyCtxt; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{DUMMY_SP, Span}; @@ -835,7 +833,10 @@ fn handle_auto_cfg_hide_show(cfg_info: &mut CfgInfo, attr: &CfgHideShow) { } } -pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator + Clone>( +pub(crate) fn extract_cfg_from_attrs< + 'a, + I: Iterator + Clone, +>( attrs: I, tcx: TyCtxt<'_>, cfg_info: &mut CfgInfo, @@ -868,7 +869,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator let mut doc_cfg = attrs .clone() .filter_map(|attr| match attr { - Attribute::Parsed(AttributeKind::Doc(d)) if !d.cfg.is_empty() => Some(d), + rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) if !d.cfg.is_empty() => Some(d), _ => None, }) .peekable(); @@ -892,7 +893,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator // We get all `doc(auto_cfg)`, `cfg` and `target_feature` attributes. for attr in attrs { - if let Attribute::Parsed(AttributeKind::Doc(d)) = attr { + if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { for (new_value, span) in &d.auto_cfg_change { if check_changed_auto_active_status( &mut changed_auto_active_status, @@ -918,7 +919,11 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator handle_auto_cfg_hide_show(cfg_info, value); } } - } else if let hir::Attribute::Parsed(AttributeKind::TargetFeature { features, .. }) = attr { + } else if let rustc_attr_ir::Attribute::Parsed(AttributeKind::TargetFeature { + features, + .. + }) = attr + { // Treat `#[target_feature(enable = "feat")]` attributes as if they were // `#[doc(cfg(target_feature = "feat"))]` attributes as well. for (feature, _) in features { @@ -930,7 +935,7 @@ pub(crate) fn extract_cfg_from_attrs<'a, I: Iterator } continue; } else if !cfg_info.parent_is_doc_cfg - && let hir::Attribute::Parsed(AttributeKind::CfgTrace(cfgs)) = attr + && let rustc_attr_ir::Attribute::Parsed(AttributeKind::CfgTrace(cfgs)) = attr { for (new_cfg, _) in cfgs { cfg_info.current_cfg &= Cfg(new_cfg.clone()); diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs index a1c25d4251823..e7c6d1ff1b6c4 100644 --- a/src/librustdoc/clean/cfg/tests.rs +++ b/src/librustdoc/clean/cfg/tests.rs @@ -1,5 +1,5 @@ +use rustc_attr_ir::CfgEntry; use rustc_data_structures::thin_vec::thin_vec; -use rustc_hir::attrs::CfgEntry; use rustc_span::{DUMMY_SP, create_default_session_globals_then}; use super::*; diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 08b065f183787..ea29a66c958a3 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -3,11 +3,12 @@ use std::iter::once; use std::sync::Arc; +use rustc_attr_ir::{DocInline, find_attr}; use rustc_data_structures::fx::FxHashSet; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdSet, LocalDefId, LocalModId}; -use rustc_hir::{self as hir, HirId, Mutability, find_attr}; +use rustc_hir::{self as hir, HirId, Mutability}; use rustc_metadata::creader::{CStore, LoadedMacro}; use rustc_middle::ty::fast_reject::SimplifiedType; use rustc_middle::ty::{self, TyCtxt}; @@ -42,7 +43,7 @@ pub(crate) fn try_inline( cx: &mut DocContext<'_>, res: Res, name: Symbol, - attrs: Option<(&[hir::Attribute], Option)>, + attrs: Option<(&[rustc_attr_ir::Attribute], Option)>, visited: &mut DefIdSet, ) -> Option> { fn try_inline_inner( @@ -230,7 +231,7 @@ pub(crate) fn try_inline_glob( } } -pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [hir::Attribute] { +pub(crate) fn load_attrs<'hir>(tcx: TyCtxt<'hir>, did: DefId) -> &'hir [rustc_attr_ir::Attribute] { // FIXME: all uses should use `find_attr`! #[allow(deprecated)] tcx.get_all_attrs(did) @@ -401,7 +402,7 @@ fn build_type_alias( pub(crate) fn build_impls( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[hir::Attribute], Option)>, + attrs: Option<(&[rustc_attr_ir::Attribute], Option)>, ret: &mut Vec, ) { let tcx = cx.tcx; @@ -433,8 +434,8 @@ pub(crate) fn build_impls( pub(crate) fn merge_attrs( tcx: TyCtxt<'_>, - old_attrs: &[hir::Attribute], - new_attrs: Option<(&[hir::Attribute], Option)>, + old_attrs: &[rustc_attr_ir::Attribute], + new_attrs: Option<(&[rustc_attr_ir::Attribute], Option)>, cfg_info: &mut CfgInfo, ) -> (clean::Attributes, Option>) { // NOTE: If we have additional attributes (from a re-export), @@ -462,7 +463,7 @@ pub(crate) fn merge_attrs( pub(crate) fn build_impl( cx: &mut DocContext<'_>, did: DefId, - attrs: Option<(&[hir::Attribute], Option)>, + attrs: Option<(&[rustc_attr_ir::Attribute], Option)>, ret: &mut Vec, ) { if !cx.inlined.insert(did.into()) { @@ -717,7 +718,7 @@ fn build_module_items( visited: &mut DefIdSet, inlined_names: &mut FxHashSet<(ItemType, Symbol)>, allowed_def_ids: Option<&DefIdSet>, - attrs: Option<(&[hir::Attribute], Option)>, + attrs: Option<(&[rustc_attr_ir::Attribute], Option)>, ) -> Vec { let mut items = Vec::new(); @@ -785,7 +786,7 @@ fn build_module_items( && find_attr!( load_attrs(cx.tcx, reexport_def_id), Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == hir::attrs::DocInline::NoInline) + if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::NoInline) ) { // We don't inline foreign `use`. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 64c6d46cea355..9b3c3d01557e0 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -34,15 +34,15 @@ use std::borrow::Cow; use std::collections::BTreeMap; use std::mem; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{AttributeKind, DocAttribute, DocInline, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, IndexEntry}; use rustc_data_structures::thin_vec::ThinVec; use rustc_errors::codes::*; use rustc_errors::{FatalError, struct_span_code_err}; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{AttributeKind, DocAttribute, DocInline}; use rustc_hir::def::{CtorKind, DefKind, MacroKinds, PerNS, Res}; use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{self as hir, HirId, PredicateOrigin, find_attr}; +use rustc_hir::{self as hir, HirId, PredicateOrigin}; use rustc_hir_analysis::{lower_const_arg_for_rustdoc, lower_ty}; use rustc_middle::middle::resolve::Reexport; use rustc_middle::middle::resolve_bound_vars as rbv; @@ -1121,7 +1121,7 @@ fn clean_fn_or_proc_macro<'tcx>( /// This is needed to make it more "readable" when documenting functions using /// `rustc_legacy_const_generics`. More information in /// . -fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[hir::Attribute]) { +fn clean_fn_decl_legacy_const_generics(func: &mut Function, attrs: &[rustc_attr_ir::Attribute]) { let Some(indexes) = find_attr!(attrs, RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes) else { return; @@ -2811,7 +2811,7 @@ fn get_all_import_attributes<'hir>( import_def_id: LocalDefId, target_def_id: DefId, is_inline: bool, -) -> Vec<(Cow<'hir, hir::Attribute>, Option)> { +) -> Vec<(Cow<'hir, rustc_attr_ir::Attribute>, Option)> { let mut attrs = Vec::new(); let mut first = true; for def_id in reexport_chain(cx.tcx, import_def_id, target_def_id) @@ -2857,17 +2857,17 @@ fn get_all_import_attributes<'hir>( /// * `doc(no_inline)` /// * `doc(hidden)` fn add_without_unwanted_attributes<'hir>( - attrs: &mut Vec<(Cow<'hir, hir::Attribute>, Option)>, - new_attrs: &'hir [hir::Attribute], + attrs: &mut Vec<(Cow<'hir, rustc_attr_ir::Attribute>, Option)>, + new_attrs: &'hir [rustc_attr_ir::Attribute], is_inline: bool, import_parent: Option, ) { for attr in new_attrs { match attr { - hir::Attribute::Parsed(AttributeKind::DocComment { .. }) => { + rustc_attr_ir::Attribute::Parsed(AttributeKind::DocComment { .. }) => { attrs.push((Cow::Borrowed(attr), import_parent)); } - hir::Attribute::Parsed(AttributeKind::Doc(d)) => { + rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) => { // Remove attributes from `normal` that should not be inherited by `use` re-export. let DocAttribute { first_span: _, @@ -2902,13 +2902,15 @@ fn add_without_unwanted_attributes<'hir>( } attr.aliases = aliases.clone(); attrs.push(( - Cow::Owned(hir::Attribute::Parsed(AttributeKind::Doc(Box::new(attr)))), + Cow::Owned(rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(Box::new( + attr, + )))), import_parent, )); } // We discard `#[cfg(...)]` attributes unless we're inlining - hir::Attribute::Parsed(AttributeKind::CfgTrace(..)) if !is_inline => {} + rustc_attr_ir::Attribute::Parsed(AttributeKind::CfgTrace(..)) if !is_inline => {} // We keep all other attributes _ => { attrs.push((Cow::Borrowed(attr), import_parent)); @@ -3169,7 +3171,7 @@ fn clean_extern_crate<'tcx>( && attrs.iter().any(|a| { matches!( a, - hir::Attribute::Parsed(AttributeKind::Doc(d)) + rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline)) }) && !cx.is_json_output(); @@ -3324,7 +3326,7 @@ fn clean_use_statement_leaf<'tcx>( || pub_underscore || attrs.iter().any(|a| matches!( a, - hir::Attribute::Parsed(AttributeKind::Doc(d)) + rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) if d.hidden.is_some() || d.inline.first().is_some_and(|(i, _)| *i == DocInline::NoInline) )); diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs index 98c09d1134fe6..a6d6005a18118 100644 --- a/src/librustdoc/clean/simplify.rs +++ b/src/librustdoc/clean/simplify.rs @@ -11,10 +11,10 @@ //! This module attempts to reconstruct the original where and/or parameter //! bounds by special casing scenarios such as these. Fun! +use rustc_attr_ir::lang_items::LangItem; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_middle::ty::{TyCtxt, Unnormalized}; diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs index 1b5968e20e4b4..fd804b1e5831e 100644 --- a/src/librustdoc/clean/types.rs +++ b/src/librustdoc/clean/types.rs @@ -8,14 +8,17 @@ use arrayvec::ArrayVec; use itertools::Either; use rustc_abi::{ExternAbi, VariantIdx}; use rustc_ast as ast; +use rustc_attr_ir::lang_items::LangItem; +use rustc_attr_ir::{ + AttributeKind, ConstStability, DeprecatedSince, Deprecation, DocAttribute, Stability, + StableSince, find_attr, +}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir as hir; -use rustc_hir::attrs::lang_items::LangItem; -use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, DocAttribute}; use rustc_hir::def::{CtorKind, DefKind, MacroKinds, Res}; use rustc_hir::def_id::{CrateNum, DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::{Attribute, BodyId, ConstStability, Mutability, Stability, StableSince, find_attr}; +use rustc_hir::{BodyId, Mutability}; use rustc_index::IndexVec; use rustc_metadata::rendered_const; use rustc_middle::ty::fast_reject::SimplifiedType; @@ -426,7 +429,7 @@ impl Item { // versions; the paths that are exposed through it are "deprecated" because they // were never supposed to work at all. let stab = self.stability(tcx)?; - if let rustc_hir::StabilityLevel::Stable { + if let rustc_attr_ir::StabilityLevel::Stable { allowed_through_unstable_modules: Some((note, _)), .. } = stab.level @@ -1061,7 +1064,7 @@ pub struct RenderedLink { #[derive(Clone, Debug, Default)] pub(crate) struct Attributes { pub(crate) doc_strings: Vec, - pub(crate) other_attrs: ThinVec, + pub(crate) other_attrs: ThinVec, } impl Attributes { @@ -1073,13 +1076,13 @@ impl Attributes { find_attr!(&self.other_attrs, Doc(d) if d.hidden.is_some()) } - pub(crate) fn from_hir(attrs: &[hir::Attribute]) -> Attributes { + pub(crate) fn from_hir(attrs: &[rustc_attr_ir::Attribute]) -> Attributes { Attributes::from_hir_iter(attrs.iter().map(|attr| (attr, None)), false) } pub(crate) fn from_hir_with_additional( - attrs: &[hir::Attribute], - (additional_attrs, def_id): (&[hir::Attribute], DefId), + attrs: &[rustc_attr_ir::Attribute], + (additional_attrs, def_id): (&[rustc_attr_ir::Attribute], DefId), ) -> Attributes { // Additional documentation should be shown before the original documentation. let attrs1 = additional_attrs.iter().map(|attr| (attr, Some(def_id))); @@ -1088,7 +1091,7 @@ impl Attributes { } pub(crate) fn from_hir_iter<'a>( - attrs: impl Iterator)>, + attrs: impl Iterator)>, doc_only: bool, ) -> Attributes { let (doc_strings, other_attrs) = attrs_to_doc_fragments(attrs, doc_only); @@ -1118,7 +1121,7 @@ impl Attributes { let mut aliases = FxIndexSet::default(); for attr in &self.other_attrs { - if let Attribute::Parsed(AttributeKind::Doc(d)) = attr { + if let rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) = attr { for (alias, _) in &d.aliases { aliases.insert(*alias); } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 012c4997db9c1..d8a3fa6bed22c 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -7,12 +7,11 @@ use rustc_ast as ast; use rustc_ast::join_path_idents; use rustc_ast::token::{Token, TokenKind}; use rustc_ast::tokenstream::TokenTree; +use rustc_attr_ir::{DocAttribute, find_attr}; use rustc_data_structures::thin_vec::{ThinVec, thin_vec}; use rustc_hir as hir; -use rustc_hir::attrs::DocAttribute; use rustc_hir::def::{DefKind, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId}; -use rustc_hir::find_attr; use rustc_metadata::rendered_const; use rustc_middle::mir; use rustc_middle::ty::{self, GenericArgKind, GenericArgsRef, TyCtxt, TypeVisitableExt}; @@ -580,7 +579,7 @@ pub(crate) fn find_nearest_parent_module(tcx: TyCtxt<'_>, def_id: DefId) -> Opti } } -/// This function exists because it runs on `hir::Attributes` whereas the other is a +/// This function exists because it runs on `rustc_attr_ir::Attributes` whereas the other is a /// `clean::Attributes` method. pub(crate) fn has_doc_flag bool>( tcx: TyCtxt<'_>, diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 0ecbc5927cf48..72895e1f2462f 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -18,12 +18,12 @@ use std::{panic, str}; pub(crate) use make::{BuildDocTestBuilder, DocTestBuilder}; pub(crate) use markdown::test as test_markdown; use proc_macro2::{TokenStream, TokenTree}; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxHasher, FxIndexMap, FxIndexSet}; use rustc_errors::emitter::HumanReadableErrorType; use rustc_errors::{ColorConfig, DiagCtxtHandle}; -use rustc_hir::attrs::AttributeKind; +use rustc_hir::CRATE_HIR_ID; use rustc_hir::def_id::LOCAL_CRATE; -use rustc_hir::{Attribute, CRATE_HIR_ID}; use rustc_interface::interface; use rustc_lint as lint; use rustc_middle::ty::TyCtxt; diff --git a/src/librustdoc/doctest/rust.rs b/src/librustdoc/doctest/rust.rs index 13f705f9c3f47..352e9a1f6adb2 100644 --- a/src/librustdoc/doctest/rust.rs +++ b/src/librustdoc/doctest/rust.rs @@ -5,8 +5,8 @@ use std::str::FromStr; use std::sync::Arc; use proc_macro2::{TokenStream, TokenTree}; +use rustc_attr_ir::{AttributeKind, CfgEntry}; use rustc_attr_parsing::eval_config_entry; -use rustc_hir::attrs::{AttributeKind, CfgEntry}; use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId}; use rustc_hir::{self as hir, CRATE_HIR_ID, intravisit}; use rustc_middle::hir::nested_filter; @@ -131,7 +131,7 @@ impl HirCollector<'_> { // 1. Collect `#[target_feature(...)]`. // 2. Collect `#[doc(test(attr(...)))]`. for attr in hir_attrs.iter() { - let hir::Attribute::Parsed(attr) = attr else { continue }; + let rustc_attr_ir::Attribute::Parsed(attr) = attr else { continue }; if let AttributeKind::TargetFeature { features, .. } = attr { for (feature, _) in features { found_features += 1; diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index c89c3dbd3fbf5..39baca1b4c0cd 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -1,7 +1,7 @@ use std::mem; +use rustc_attr_ir::StabilityLevel; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_hir::StabilityLevel; use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet}; use rustc_metadata::creader::CStore; use rustc_middle::ty::{self, TyCtxt}; diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 4ee91d411903a..cef9dff51b7aa 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -13,11 +13,11 @@ use std::{iter, slice}; use itertools::{Either, Itertools}; use rustc_abi::ExternAbi; use rustc_ast::join_path_syms; +use rustc_attr_ir::{ConstStability, StabilityLevel, StableSince}; use rustc_data_structures::fx::FxHashSet; use rustc_hir as hir; use rustc_hir::def::{DefKind, MacroKinds}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{ConstStability, StabilityLevel, StableSince}; use rustc_metadata::creader::CStore; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_span::symbol::kw; diff --git a/src/librustdoc/html/render/context.rs b/src/librustdoc/html/render/context.rs index d00b705d3766c..f828327b4b985 100644 --- a/src/librustdoc/html/render/context.rs +++ b/src/librustdoc/html/render/context.rs @@ -7,9 +7,8 @@ use std::sync::mpsc::{Receiver, channel}; use askama::Template; use rustc_ast::join_path_syms; +use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_hir::Attribute; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def_id::{DefIdMap, LOCAL_CRATE}; use rustc_middle::ty::TyCtxt; use rustc_session::Session; diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index a9ecf6d66d001..35947921dc145 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -51,12 +51,14 @@ use askama::Template; use indexmap::IndexMap; use itertools::Either; use rustc_ast::join_path_syms; +use rustc_attr_ir::{ + AttributeKind, ConstStability, DeprecatedSince, Deprecation, RustcVersion, StabilityLevel, + StableSince, find_attr, +}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_hir as hir; -use rustc_hir::attrs::{AttributeKind, DeprecatedSince, Deprecation, RustcVersion}; +use rustc_hir::Mutability; use rustc_hir::def::DefKind; use rustc_hir::def_id::{DefId, DefIdSet}; -use rustc_hir::{ConstStability, Mutability, StabilityLevel, StableSince}; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, TyCtxt}; use rustc_span::DUMMY_SP; @@ -3021,7 +3023,7 @@ pub(super) fn render_attributes_in_code_with_options( render_code_attribute(&prefix, "#[doc(hidden)]", w)?; } for attr in &item.attrs.other_attrs { - let hir::Attribute::Parsed(kind) = attr else { continue }; + let rustc_attr_ir::Attribute::Parsed(kind) = attr else { continue }; let attr = match kind { AttributeKind::LinkSection { name, .. } => { Cow::Owned(format!("#[unsafe(link_section = {})]", Escape(&format!("{name:?}")))) @@ -3089,7 +3091,7 @@ fn repr_attribute<'tcx>( // - the item is annotated with internal attribute `#[rustc_pub_transparent]` if repr.transparent() { let is_public = 'is_public: { - if hir::find_attr!(tcx, def_id, AttributeKind::RustcPubTransparent(_)) { + if find_attr!(tcx, def_id, RustcPubTransparent(_)) { break 'is_public true; } diff --git a/src/librustdoc/html/render/search_index.rs b/src/librustdoc/html/render/search_index.rs index b459ead9481cb..38e91050fc9bc 100644 --- a/src/librustdoc/html/render/search_index.rs +++ b/src/librustdoc/html/render/search_index.rs @@ -11,10 +11,10 @@ use ::serde::de::{self, Deserializer, Error as _}; use ::serde::ser::{SerializeSeq, Serializer}; use ::serde::{Deserialize, Serialize}; use rustc_ast::join_path_syms; +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap}; use rustc_data_structures::thin_vec::ThinVec; use rustc_hir::def_id::{CrateNum, DefIndex, LOCAL_CRATE}; -use rustc_hir::find_attr; use rustc_middle::ty::TyCtxt; use rustc_span::def_id::DefId; use rustc_span::sym; diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 588a61f8ad3cc..814e26b035d5a 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -4,15 +4,15 @@ use rustc_abi::ExternAbi; use rustc_ast::ast; -use rustc_data_structures::fx::FxHashSet; -use rustc_data_structures::thin_vec::ThinVec; -use rustc_hir as hir; -use rustc_hir::attrs::{ +use rustc_attr_ir::{ self, DeprecatedSince, DocAttribute, DocCfgHideShow, DocInline, HideOrShow, RustcVersion, + find_attr, }; +use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::thin_vec::ThinVec; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::DefId; -use rustc_hir::{HeaderSafety, Safety, find_attr, intravisit}; +use rustc_hir::{HeaderSafety, Safety, intravisit}; use rustc_hir_pretty::PpAnn; use rustc_metadata::rendered_const; use rustc_middle::ty::{self, TyCtxt}; @@ -222,9 +222,9 @@ impl FromClean>> for Visibility { } } -impl FromClean for Deprecation { - fn from_clean(deprecation: &attrs::Deprecation, _renderer: &JsonRenderer<'_>) -> Self { - let attrs::Deprecation { since, note, suggestion: _ } = deprecation; +impl FromClean for Deprecation { + fn from_clean(deprecation: &rustc_attr_ir::Deprecation, _renderer: &JsonRenderer<'_>) -> Self { + let rustc_attr_ir::Deprecation { since, note, suggestion: _ } = deprecation; let since = match since { DeprecatedSince::RustcVersion(version) => Some(version.to_string()), DeprecatedSince::Future => Some("TBD".to_string()), @@ -235,45 +235,48 @@ impl FromClean for Deprecation { } } -impl FromClean for Stability { - fn from_clean(stab: &hir::Stability, _renderer: &JsonRenderer<'_>) -> Self { +impl FromClean for Stability { + fn from_clean(stab: &rustc_attr_ir::Stability, _renderer: &JsonRenderer<'_>) -> Self { let feature = stab.feature.to_string(); let level = match stab.level { - hir::StabilityLevel::Stable { since, .. } => StabilityLevel::Stable { + rustc_attr_ir::StabilityLevel::Stable { since, .. } => StabilityLevel::Stable { since: match since { - hir::StableSince::Version(since) => Some(since.to_string()), - hir::StableSince::Current => Some(RustcVersion::CURRENT.to_string()), + rustc_attr_ir::StableSince::Version(since) => Some(since.to_string()), + rustc_attr_ir::StableSince::Current => Some(RustcVersion::CURRENT.to_string()), // Match rustdoc HTML: malformed stable-since values are omitted. - hir::StableSince::Err(_) => None, + rustc_attr_ir::StableSince::Err(_) => None, }, }, - hir::StabilityLevel::Unstable { .. } => StabilityLevel::Unstable, + rustc_attr_ir::StabilityLevel::Unstable { .. } => StabilityLevel::Unstable, }; Stability { feature, level } } } -impl FromClean for Stability { - fn from_clean(stab: &hir::ConstStability, _renderer: &JsonRenderer<'_>) -> Self { +impl FromClean for Stability { + fn from_clean(stab: &rustc_attr_ir::ConstStability, _renderer: &JsonRenderer<'_>) -> Self { let feature = stab.feature.to_string(); let level = match stab.level { - hir::StabilityLevel::Stable { since, .. } => StabilityLevel::Stable { + rustc_attr_ir::StabilityLevel::Stable { since, .. } => StabilityLevel::Stable { since: match since { - hir::StableSince::Version(since) => Some(since.to_string()), - hir::StableSince::Current => Some(RustcVersion::CURRENT.to_string()), + rustc_attr_ir::StableSince::Version(since) => Some(since.to_string()), + rustc_attr_ir::StableSince::Current => Some(RustcVersion::CURRENT.to_string()), // Match rustdoc HTML: malformed stable-since values are omitted. - hir::StableSince::Err(_) => None, + rustc_attr_ir::StableSince::Err(_) => None, }, }, - hir::StabilityLevel::Unstable { .. } => StabilityLevel::Unstable, + rustc_attr_ir::StabilityLevel::Unstable { .. } => StabilityLevel::Unstable, }; Stability { feature, level } } } -impl FromClean for Box { - fn from_clean(stab: &hir::DefaultBodyStability, _renderer: &JsonRenderer<'_>) -> Self { - let hir::StabilityLevel::Unstable { .. } = stab.level else { +impl FromClean for Box { + fn from_clean( + stab: &rustc_attr_ir::DefaultBodyStability, + _renderer: &JsonRenderer<'_>, + ) -> Self { + let rustc_attr_ir::StabilityLevel::Unstable { .. } = stab.level else { bug!( "unexpected stable default-body stability, \ there's no stable equivalent of `#[rustc_default_body_unstable]`" @@ -1013,15 +1016,18 @@ impl FromClean for ItemKind { fn default_body_stability_for_def_id( tcx: TyCtxt<'_>, def_id: DefId, -) -> Option { +) -> Option { let stability = tcx.lookup_default_body_stability(def_id)?; match stability.level { - hir::StabilityLevel::Unstable { .. } => Some(stability), - hir::StabilityLevel::Stable { .. } => None, + rustc_attr_ir::StabilityLevel::Unstable { .. } => Some(stability), + rustc_attr_ir::StabilityLevel::Stable { .. } => None, } } -fn const_stability_for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option { +fn const_stability_for_def_id( + tcx: TyCtxt<'_>, + def_id: DefId, +) -> Option { if !tcx.is_conditionally_const(def_id) { // The item cannot be conditionally-const. No const stability here. // @@ -1064,7 +1070,7 @@ fn const_stability_for_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option, def_id: DefId) -> Option) -> Vec { - use attrs::AttributeKind as AK; +fn maybe_from_hir_attr( + attr: &rustc_attr_ir::Attribute, + item_id: ItemId, + tcx: TyCtxt<'_>, +) -> Vec { + use rustc_attr_ir::AttributeKind as AK; let kind = match attr { - hir::Attribute::Parsed(kind) => kind, + rustc_attr_ir::Attribute::Parsed(kind) => kind, - hir::Attribute::Unparsed(_) => { + rustc_attr_ir::Attribute::Unparsed(_) => { // FIXME: We should handle `#[doc(hidden)]`. return vec![other_attr(tcx, attr)]; } @@ -1242,7 +1252,7 @@ fn maybe_from_hir_attr(attr: &hir::Attribute, item_id: ItemId, tcx: TyCtxt<'_>) }] } -fn other_attr(tcx: TyCtxt<'_>, attr: &hir::Attribute) -> Attribute { +fn other_attr(tcx: TyCtxt<'_>, attr: &rustc_attr_ir::Attribute) -> Attribute { let mut s = rustc_hir_pretty::attribute_to_string( &(&tcx as &dyn intravisit::HirTyCtxt<'_>) as &dyn PpAnn, attr, diff --git a/src/librustdoc/json/ids.rs b/src/librustdoc/json/ids.rs index 31043b8028f02..6c3e05e5d7399 100644 --- a/src/librustdoc/json/ids.rs +++ b/src/librustdoc/json/ids.rs @@ -5,9 +5,9 @@ //! [`rustdoc_json_types::Item`] doesn't correspond exactly to what //! other phases think of as an "item". +use rustc_attr_ir::find_attr; use rustc_data_structures::fx::FxHashMap; use rustc_hir::def_id::DefId; -use rustc_hir::find_attr; use rustc_span::Symbol; use rustdoc_json_types as types; diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index 24427ff5cb3d3..b907c3ef2cb11 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -32,6 +32,7 @@ extern crate rustc_abi; extern crate rustc_ast; extern crate rustc_ast_pretty; +extern crate rustc_attr_ir; extern crate rustc_attr_parsing; extern crate rustc_data_structures; extern crate rustc_driver; diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index 1f6d15147dcb3..d7815e64178a7 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -8,14 +8,14 @@ use std::mem; use std::ops::Range; use rustc_ast::util::comments::may_have_doc_links; +use rustc_attr_ir::{Attribute, AttributeKind, find_attr}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, DiagMessage}; -use rustc_hir::attrs::AttributeKind; use rustc_hir::def::Namespace::*; use rustc_hir::def::{DefKind, MacroKinds, Namespace, PerNS}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE}; -use rustc_hir::{Attribute, Mutability, Safety, find_attr}; +use rustc_hir::{Mutability, Safety}; use rustc_lint::Lint; use rustc_middle::ty; use rustc_middle::ty::{Ty, TyCtxt}; diff --git a/src/librustdoc/passes/collect_trait_impls.rs b/src/librustdoc/passes/collect_trait_impls.rs index 1bfac8e67748c..8720e09bd85cd 100644 --- a/src/librustdoc/passes/collect_trait_impls.rs +++ b/src/librustdoc/passes/collect_trait_impls.rs @@ -3,11 +3,10 @@ //! For example, if a crate defines a struct that implements a trait, //! this pass will note that the struct implements that trait. +use rustc_attr_ir::{Attribute, AttributeKind, DocAttribute, find_attr}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::FatalError; -use rustc_hir::attrs::{AttributeKind, DocAttribute}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; -use rustc_hir::{Attribute, find_attr}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::kw; use tracing::debug; diff --git a/src/librustdoc/passes/propagate_doc_cfg.rs b/src/librustdoc/passes/propagate_doc_cfg.rs index 0d16141fa09a1..64306c0a6104c 100644 --- a/src/librustdoc/passes/propagate_doc_cfg.rs +++ b/src/librustdoc/passes/propagate_doc_cfg.rs @@ -2,9 +2,8 @@ //! //! [RFC 3631]: https://rust-lang.github.io/rfcs/3631-rustdoc-cfgs-handling.html +use rustc_attr_ir::{Attribute, AttributeKind, DocAttribute, find_attr}; use rustc_data_structures::fx::FxHashMap; -use rustc_hir::attrs::{AttributeKind, DocAttribute}; -use rustc_hir::{Attribute, find_attr}; use rustc_span::{ExpnKind, MacroKind}; use crate::clean::inline::{load_attrs, merge_attrs}; @@ -89,14 +88,12 @@ impl CfgPropagator<'_, '_> { // We also need to merge an item attributes with its parent's in case it's a macro with // the `#[macro_export]` attribute, because it might not be defined at crate root. else if matches!(item.kind, ItemKind::MacroItem(_, _)) - && item.inner.attrs.other_attrs.iter().any(|attr| { - matches!( - attr, - rustc_hir::Attribute::Parsed( - rustc_hir::attrs::AttributeKind::MacroExport { .. } - ) - ) - }) + && item + .inner + .attrs + .other_attrs + .iter() + .any(|attr| matches!(attr, Attribute::Parsed(AttributeKind::MacroExport { .. }))) { for parent_def_id in &item.cfg_parent_ids_for_detached_item(self.cx.tcx) { let mut parent_attrs = Vec::new(); diff --git a/src/librustdoc/passes/propagate_stability.rs b/src/librustdoc/passes/propagate_stability.rs index cff1e7fa46dbb..8aa24e0474890 100644 --- a/src/librustdoc/passes/propagate_stability.rs +++ b/src/librustdoc/passes/propagate_stability.rs @@ -6,8 +6,8 @@ //! [`core::error`] module is marked as stable since 1.81.0, so we want to show //! [`core::error::Error`] as stable since 1.81.0 as well. +use rustc_attr_ir::{Stability, StabilityLevel}; use rustc_hir::def_id::CRATE_DEF_ID; -use rustc_hir::{Stability, StabilityLevel}; use crate::clean::{Crate, Item, ItemId, ItemKind}; use crate::core::DocContext; diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index 1b903d5a17092..c0f28a933a3a5 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -4,12 +4,12 @@ use std::mem; use rustc_ast::attr::AttributeExt; +use rustc_attr_ir::{DocInline, find_attr}; use rustc_data_structures::fx::{FxHashSet, FxIndexMap}; -use rustc_hir::attrs::DocInline; use rustc_hir::def::{DefKind, MacroKinds, Res}; use rustc_hir::def_id::{DefId, DefIdMap, LocalDefId, LocalDefIdSet}; use rustc_hir::intravisit::{Visitor, walk_body, walk_item}; -use rustc_hir::{self as hir, HirId, Node, find_attr}; +use rustc_hir::{self as hir, HirId, Node}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::Span; From 6b815eea126e0847c4bab67b267c053c3c1474e5 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Thu, 24 Sep 2026 14:50:50 +0200 Subject: [PATCH 0854/1309] fix miri imports --- src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs | 2 +- src/tools/miri/src/helpers.rs | 2 +- src/tools/miri/src/lib.rs | 1 + src/tools/miri/src/machine.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 2 +- 5 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs index df349667a47c9..f2875548d08d5 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs @@ -1,5 +1,5 @@ use rustc_abi::Size; -use rustc_hir::find_attr; +use rustc_attr_ir::find_attr; use rustc_middle::mir::Mutability; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty}; diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index 11f1fa2eb170d..b0ff200c0614b 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -1085,7 +1085,7 @@ pub(crate) fn windows_check_buffer_size((success, len): (bool, u64)) -> u32 { /// Check whether the local crate has the `#![no_core]` attribute. pub fn is_no_core(tcx: TyCtxt<'_>) -> bool { - rustc_hir::find_attr!(tcx, crate, NoCore) + rustc_attr_ir::find_attr!(tcx, crate, NoCore) } /// We don't support 16-bit systems, so let's have ergonomic conversion from `u32` to `usize`. diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index ffbe6609e023f..d1b3e1a1cf1f6 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -62,6 +62,7 @@ extern crate rustc_abi; extern crate rustc_apfloat; extern crate rustc_ast; +extern crate rustc_attr_ir; extern crate rustc_codegen_ssa; extern crate rustc_const_eval; extern crate rustc_data_structures; diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index beed8df7ef350..fa025f839057f 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -18,7 +18,7 @@ use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[allow(unused)] use rustc_data_structures::static_assert_size; -use rustc_hir::attrs::{InlineAttr, Linkage}; +use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_hir::def::DefKind; use rustc_log::tracing; use rustc_middle::middle::codegen_fn_attrs::TargetFeatureKind; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 25c659f7b3ae9..f9ca42dfa0e1f 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -5,7 +5,7 @@ use std::path::Path; use rustc_abi::{Align, ExternAbi, Size}; use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE; use rustc_data_structures::either::Either; -use rustc_hir::attrs::Linkage; +use rustc_attr_ir::Linkage; use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; From 4be7838f6c5a007db6dbda69c85443a914a1db5c Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Fri, 25 Sep 2026 10:45:09 +0200 Subject: [PATCH 0855/1309] make sure to use proper admonations in the book --- .remarkrc | 1 + book/src/continuous_integration/README.md | 3 +- book/src/development/README.md | 6 ++- book/src/development/adding_lints.md | 3 +- book/src/development/basics.md | 3 +- .../development/common_tools_writing_lints.md | 4 +- book/src/development/emitting_lints.md | 6 ++- book/src/development/infrastructure/README.md | 3 +- .../development/infrastructure/backport.md | 6 ++- .../infrastructure/changelog_update.md | 3 +- .../src/development/infrastructure/release.md | 6 ++- book/src/development/infrastructure/sync.md | 42 +++++++++++-------- book/src/development/macro_expansions.md | 3 +- .../proposals/syntax-tree-patterns.md | 12 ++++-- book/src/development/type_checking.md | 3 +- book/src/development/writing_tests.md | 6 ++- book/src/installation.md | 3 +- book/src/lints.md | 6 ++- book/src/usage.md | 18 +++++--- lintcheck/README.md | 6 ++- 20 files changed, 92 insertions(+), 51 deletions(-) diff --git a/.remarkrc b/.remarkrc index 04b82b8cc581f..43d1b4f22734c 100644 --- a/.remarkrc +++ b/.remarkrc @@ -5,6 +5,7 @@ ["remark-lint-list-item-indent", false], ["remark-lint-no-literal-urls", false], ["remark-lint-no-shortcut-reference-link", false], + ["remark-lint-no-undefined-references", {"allow": ["!NOTE", "!TIP", "!IMPORTANT", "!WARNING", "!CAUTION"]}], ["remark-lint-maximum-line-length", 120] ], "settings": { diff --git a/book/src/continuous_integration/README.md b/book/src/continuous_integration/README.md index e5c3673bde451..2a28c4f30f130 100644 --- a/book/src/continuous_integration/README.md +++ b/book/src/continuous_integration/README.md @@ -8,7 +8,8 @@ We recommend to use Clippy from the same toolchain, that you use for compiling your crate for maximum compatibility. E.g. if your crate is compiled with the `stable` toolchain, you should also use `stable` Clippy. -> _Note:_ New Clippy lints are first added to the `nightly` toolchain. If you +> [!NOTE] +> New Clippy lints are first added to the `nightly` toolchain. If you > want to help with improving Clippy and have CI resources left, please consider > adding a `nightly` Clippy check to your CI and report problems like false > positives back to us. With that we can fix bugs early, before they can get to diff --git a/book/src/development/README.md b/book/src/development/README.md index b33cdc00ead67..bc490426a88ce 100644 --- a/book/src/development/README.md +++ b/book/src/development/README.md @@ -4,7 +4,8 @@ Hello fellow Rustacean! If you made it here, you're probably interested in making Clippy better by contributing to it. In that case, welcome to the project! -> _Note:_ If you're just interested in using Clippy, there's nothing to see from +> [!NOTE] +> If you're just interested in using Clippy, there's nothing to see from > this point onward, and you should return to one of the earlier chapters. ## Getting started @@ -46,7 +47,8 @@ also a good idea to give the [stability guarantees][rfc_stability] and quick read. The lint categories are also described [earlier in this book](../lints.md). -> _Note:_ Some higher level things about contributing to Clippy are still +> [!NOTE] +> Some higher level things about contributing to Clippy are still > covered in the [`CONTRIBUTING.md`] document. Some of those will be moved to > the book over time, like: > - Finding something to fix diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index f1d1bbf93b59f..65226500c88ae 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -144,7 +144,8 @@ should pass on its own. When we commit our lint, we need to commit the generated `.stderr` and if applicable `.fixed` files, too. In general, you should only commit files changed by `cargo bless` for the specific lint you are creating/editing. -> _Note:_ you can run multiple test files by specifying a comma separated list: +> [!NOTE] +> you can run multiple test files by specifying a comma separated list: > `TESTNAME=foo_functions,test2,test3`. ### Cargo lints diff --git a/book/src/development/basics.md b/book/src/development/basics.md index 9f9ec09969578..0261fcdf6fae8 100644 --- a/book/src/development/basics.md +++ b/book/src/development/basics.md @@ -72,7 +72,8 @@ cargo bless For example, this is necessary if you fix a typo in an error message of a lint, or if you modify a test file to add a test case. -> _Note:_ This command may update more files than you intended. In that case +> [!NOTE] +> This command may update more files than you intended. In that case > only commit the files you wanted to update. [UI test]: https://rustc-dev-guide.rust-lang.org/tests/adding.html#ui-test-walkthrough diff --git a/book/src/development/common_tools_writing_lints.md b/book/src/development/common_tools_writing_lints.md index 1b02e3ced6b76..f588601ec9d0b 100644 --- a/book/src/development/common_tools_writing_lints.md +++ b/book/src/development/common_tools_writing_lints.md @@ -216,7 +216,9 @@ functions to deal with macros: return; } ``` - > Note: Code that is not from expansion is in the "root" context. So any spans + + > [!NOTE] + > Code that is not from expansion is in the "root" context. So any spans > where `from_expansion` returns `true` can be assumed to have the same > context. And so just using `span.from_expansion()` is often good enough. diff --git a/book/src/development/emitting_lints.md b/book/src/development/emitting_lints.md index 9ce56f0fc9dcf..4a03b004c5454 100644 --- a/book/src/development/emitting_lints.md +++ b/book/src/development/emitting_lints.md @@ -24,7 +24,8 @@ By far the most common method used for Clippy lints is [`check_expr` method][late_check_expr], this is because Rust is an expression language and, more often than not, the lint we want to work on must examine expressions. -> _Note:_ If you don't fully understand what expressions are in Rust, take a +> [!NOTE] +> If you don't fully understand what expressions are in Rust, take a > look at the official documentation on [expressions][rust_expressions] Other common ones include the [`check_fn` method][late_check_fn] and the @@ -65,7 +66,8 @@ impl<'tcx> LateLintPass<'tcx> for LintName { } ``` -> Note: The message should be matter of fact and avoid capitalization and +> [!NOTE] +> The message should be matter of fact and avoid capitalization and > punctuation. If multiple sentences are needed, the messages should probably be > split up into an error + a help / note / suggestion message. diff --git a/book/src/development/infrastructure/README.md b/book/src/development/infrastructure/README.md index 3b2a253999629..a8c82c17e42a4 100644 --- a/book/src/development/infrastructure/README.md +++ b/book/src/development/infrastructure/README.md @@ -15,5 +15,6 @@ Version](release.md) section. During a release cycle a changelog entry for the next release has to be written. The format of that and how to do that is documented in the [Changelog Update](changelog_update.md) section. -> _Note:_ The Clippy CI should also be described in this chapter, but for now is +> [!NOTE] +> The Clippy CI should also be described in this chapter, but for now is > left as a TODO. diff --git a/book/src/development/infrastructure/backport.md b/book/src/development/infrastructure/backport.md index 47ea6a412c503..3999525311c3f 100644 --- a/book/src/development/infrastructure/backport.md +++ b/book/src/development/infrastructure/backport.md @@ -5,7 +5,8 @@ Backports in Clippy are rare and should be approved by the Clippy team. For example, a backport is done, if a crucial ICE was fixed or a lint is broken to a point, that it has to be disabled, before landing on stable. -> Note: If you think a PR should be backported you can label it with +> [!NOTE] +> If you think a PR should be backported you can label it with > `beta-nominated`. This has to be done before the Thursday the week before the > release. @@ -45,7 +46,8 @@ some explanation and are quite subjective. Good judgement is required. ## Preparation -> Note: All commands in this chapter will be run in the Rust clone. +> [!NOTE] +> All commands in this chapter will be run in the Rust clone. Follow the instructions in [defining remotes] to define the `clippy-upstream` remote in the Rust repository. diff --git a/book/src/development/infrastructure/changelog_update.md b/book/src/development/infrastructure/changelog_update.md index 4652d71a9ea33..58d681176d1a8 100644 --- a/book/src/development/infrastructure/changelog_update.md +++ b/book/src/development/infrastructure/changelog_update.md @@ -93,7 +93,8 @@ Look for the [`beta-accepted`] label and make sure to also include the PRs with that label in the changelog. If you can, remove the `beta-accepted` labels **after** the changelog PR was merged. -> _Note:_ Some of those PRs might even get backported to the previous `beta`. +> [!NOTE] +> Some of those PRs might even get backported to the previous `beta`. > Those have to be included in the changelog of the _previous_ release. ### 5. Update `clippy::version` attributes diff --git a/book/src/development/infrastructure/release.md b/book/src/development/infrastructure/release.md index a429e0d953c46..3091e994fd0fb 100644 --- a/book/src/development/infrastructure/release.md +++ b/book/src/development/infrastructure/release.md @@ -1,6 +1,7 @@ # Release a new Clippy Version -> _NOTE:_ This document is probably only relevant to you, if you're a member of +> [!NOTE] +> This document is probably only relevant to you, if you're a member of > the Clippy team. Clippy is released together with stable Rust releases. The dates for these @@ -103,7 +104,8 @@ The `clippy_utils` crate is published to `crates.io` without any stability guarantees. To do this, after the [sync] and the release is done, switch back to the `upstream/master` branch and publish `clippy_utils`: -> Note: The Rustup PR bumping the nightly and Clippy version **must** be merged +> [!NOTE] +> The Rustup PR bumping the nightly and Clippy version **must** be merged > before doing this. ```bash diff --git a/book/src/development/infrastructure/sync.md b/book/src/development/infrastructure/sync.md index c2b62b092dd71..f938306ab2b12 100644 --- a/book/src/development/infrastructure/sync.md +++ b/book/src/development/infrastructure/sync.md @@ -40,19 +40,22 @@ sudo chmod --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subt sudo chown --reference=/usr/lib/git-core/git-subtree~ /usr/lib/git-core/git-subtree ``` -> _Note:_ The first time running `git subtree push` a cache has to be built. +> [!NOTE] +> The first time running `git subtree push` a cache has to be built. > This involves going through the complete Clippy history once. For this you > have to increase the stack limit though, which you can do with `ulimit -s > 60000`. Make sure to run the `ulimit` command from the same session you call > git subtree. -> _Note:_ If you are a Debian user, `dash` is the shell used by default for +> [!NOTE] +> If you are a Debian user, `dash` is the shell used by default for > scripts instead of `sh`. This shell has a hardcoded recursion limit set to > 1,000. In order to make this process work, you need to force the script to run > `bash` instead. You can do this by editing the first line of the `git-subtree` > script and changing `sh` to `bash`. -> Note: The following sections assume that you have set up remotes following the +> [!NOTE] +> The following sections assume that you have set up remotes following the > instructions in [defining remotes]. [gitgitgadget-pr]: https://github.com/gitgitgadget/git/pull/493 @@ -67,22 +70,25 @@ to be run inside the `rust` directory): 2. Checkout the commit from the latest available nightly. You can get it using `rustup check`. 3. Sync the changes to the rust-copy of Clippy to your Clippy fork: - ```bash - # Be sure to either use a net-new branch, e.g. `rustup`, or delete the branch beforehand - # because changes cannot be fast forwarded and you have to run this command again. - git subtree push -P src/tools/clippy clippy-local rustup - ``` + ```bash + # Be sure to either use a net-new branch, e.g. `rustup`, or delete the branch beforehand + # because changes cannot be fast forwarded and you have to run this command again. + git subtree push -P src/tools/clippy clippy-local rustup + ``` + +> [!NOTE] +> Most of the time you have to create a merge commit in the +> `rust-clippy` repo (this has to be done in the Clippy repo, not in the +> rust-copy of Clippy): +> ```bash +> git fetch upstream # assuming upstream is the rust-lang/rust remote +> git switch rustup +> git merge upstream/main --no-ff +> ``` +> +> This is one of the few instances where a merge commit is allowed in +> a PR. - > _Note:_ Most of the time you have to create a merge commit in the - > `rust-clippy` repo (this has to be done in the Clippy repo, not in the - > rust-copy of Clippy): - ```bash - git fetch upstream # assuming upstream is the rust-lang/rust remote - git switch rustup - git merge upstream/main --no-ff - ``` - > Note: This is one of the few instances where a merge commit is allowed in - > a PR. 4. Bump the nightly version in the Clippy repository by running these commands: ```bash cargo dev sync update_nightly diff --git a/book/src/development/macro_expansions.md b/book/src/development/macro_expansions.md index 63a96dc373f31..655c38ff3305f 100644 --- a/book/src/development/macro_expansions.md +++ b/book/src/development/macro_expansions.md @@ -172,7 +172,8 @@ point the user to the relevant code in case of a compile error. However, for Clippy this is inconvenient, because most of the time *we don't* want to lint proc macro-generated code and this makes it impossible to tell what is and isn't proc macro code. -> NOTE: this is specifically only an issue when a proc macro explicitly sets the span to that of an **input span**. +> [!NOTE] +> this is specifically only an issue when a proc macro explicitly sets the span to that of an **input span**. > > For example, other common ways of creating `TokenStream`s, such as `"fn foo() {...}".parse::()`, > sets each token's span to `Span::call_site()`, which already marks the span as coming from a proc macro diff --git a/book/src/development/proposals/syntax-tree-patterns.md b/book/src/development/proposals/syntax-tree-patterns.md index 92fbf733a8faf..83d25e42cdac6 100644 --- a/book/src/development/proposals/syntax-tree-patterns.md +++ b/book/src/development/proposals/syntax-tree-patterns.md @@ -133,7 +133,8 @@ The `pattern!` macro call expands to a function `my_pattern` that expects a syntax tree expression as its argument and returns an `Option` that indicates whether the pattern matched. -> Note: The result type is explained in more detail in [a later +> [!NOTE] +> The result type is explained in more detail in [a later > section](#the-result-type). For now, it's enough to know that the result is > `Some` if the pattern matched and `None` otherwise. @@ -482,7 +483,8 @@ differences: The code below shows a simplified version of the current PatternTree: -> Note: The current implementation can be found +> [!NOTE] +> The current implementation can be found > [here](https://github.com/fkohlgrueber/pattern-matching/blob/dfb3bc9fbab69cec7c91e72564a63ebaa2ede638/pattern-match/src/pattern_tree.rs#L50-L96). @@ -516,7 +518,8 @@ pub enum BlockType { The `Alt`, `Seq` and `Opt` structs look like these: -> Note: The current implementation can be found +> [!NOTE] +> The current implementation can be found > [here](https://github.com/fkohlgrueber/pattern-matching/blob/dfb3bc9fbab69cec7c91e72564a63ebaa2ede638/pattern-match/src/matchers.rs#L35-L60). ```rust,ignore @@ -562,7 +565,8 @@ the `Expr` enum is `Any` and therefore doesn't support repetition (`*`). As another example, `Array( Lit(_)* )` is a valid pattern because the parameter of `Array` is of type `Seq` which allows sequences and repetitions. -> Note: names in the pattern syntax correspond to *PatternTree* enum +> [!NOTE] +> names in the pattern syntax correspond to *PatternTree* enum > **variants**. For example, the `Lit` in the pattern above refers to the `Lit` > variant of the `Expr` enum (`Expr::Lit`), not the `Lit` enum. diff --git a/book/src/development/type_checking.md b/book/src/development/type_checking.md index e92e766988858..655480e2eed25 100644 --- a/book/src/development/type_checking.md +++ b/book/src/development/type_checking.md @@ -12,7 +12,8 @@ The lint context [`LateContext`][LateContext] and [`TypeckResults`][TypeckResult in `LateLintPass`. They allow us to jump to type definitions and other compilation stages such as HIR. -> Note: `LateContext.typeck_results`'s return value is [`TypeckResults`][TypeckResults] +> [!NOTE] +> `LateContext.typeck_results`'s return value is [`TypeckResults`][TypeckResults] > and is created in the type checking step, it includes useful information such as types of > expressions, ways to resolve methods and so on. diff --git a/book/src/development/writing_tests.md b/book/src/development/writing_tests.md index 1da54322fcf72..6f8ca138d65ee 100644 --- a/book/src/development/writing_tests.md +++ b/book/src/development/writing_tests.md @@ -141,7 +141,8 @@ error: aborting due to 3 previous errors Note the *failures* label at the top of the fragment, we'll get rid of it (saving this output) in the next section. -> _Note:_ You can run multiple test files by specifying a comma separated list: +> [!NOTE] +> You can run multiple test files by specifying a comma separated list: > `TESTNAME=foo_functions,bar_methods,baz_structs`. ### `cargo bless` @@ -162,7 +163,8 @@ our lint, we need to commit the generated `.stderr` files, too. In general, you should only commit files changed by `cargo bless` for the specific lint you are creating/editing. -> _Note:_ If the generated `.stderr`, and `.fixed` files are empty, +> [!NOTE] +> If the generated `.stderr`, and `.fixed` files are empty, > they should be removed. ## `toml` Tests diff --git a/book/src/installation.md b/book/src/installation.md index d54fff9deba18..2445d09b35af3 100644 --- a/book/src/installation.md +++ b/book/src/installation.md @@ -4,7 +4,8 @@ If you're using `rustup` to install and manage your Rust toolchains, Clippy is usually **already installed**. In that case you can skip this chapter and go to the [Usage] chapter. -> Note: If you used the `minimal` profile when installing a Rust toolchain, +> [!NOTE] +> If you used the `minimal` profile when installing a Rust toolchain, > Clippy is not automatically installed. ## Using Rustup diff --git a/book/src/lints.md b/book/src/lints.md index 8943274a38e81..ce04872f2be43 100644 --- a/book/src/lints.md +++ b/book/src/lints.md @@ -73,7 +73,8 @@ the whole group with `#![warn(clippy::pedantic)]` in the `lib.rs`/`main.rs` of your crate. This lint group is for Clippy power users that want an in depth check of their code. -> _Note:_ Instead of enabling the whole group (like Clippy itself does), you may +> [!NOTE] +> Instead of enabling the whole group (like Clippy itself does), you may > want to cherry-pick lints out of the pedantic group. If you enable this group, expect to also use `#[allow]` attributes generously @@ -87,7 +88,8 @@ using certain parts of the Rust language. It is **not** recommended to enable the whole group, but rather cherry-pick lints that are useful for your code base and your use case. -> _Note:_ Clippy will produce a warning if it finds a +> [!NOTE] +> Clippy will produce a warning if it finds a > `#![warn(clippy::restriction)]` attribute in your code! Lints from this group will restrict you in some way. If you enable a restriction diff --git a/book/src/usage.md b/book/src/usage.md index a7e07e9e92d68..1ab1782525a12 100644 --- a/book/src/usage.md +++ b/book/src/usage.md @@ -4,7 +4,8 @@ This chapter describes how to use Clippy to get the most out of it. Clippy can be used as a `cargo` subcommand or, like `rustc`, directly with the `clippy-driver` binary. -> _Note:_ This chapter assumes that you have Clippy installed already. If you're +> [!NOTE] +> This chapter assumes that you have Clippy installed already. If you're > not sure, take a look at the [Installation] chapter. ## Cargo subcommand @@ -23,7 +24,8 @@ lint group `clippy::all`. You might want to use even more lints, or you may not agree with every Clippy lint, and for that there are ways to configure lint levels. -> _Note:_ Clippy is meant to be used with a generous sprinkling of +> [!NOTE] +> Clippy is meant to be used with a generous sprinkling of > `#[allow(..)]`s through your code. So if you disagree with a lint, don't feel > bad disabling them for parts of your code or the whole project. @@ -57,7 +59,8 @@ CARGO_BUILD_WARNINGS=deny cargo clippy warnings = "deny" ``` -> _Note:_ Using `CARGO_BUILD_WARNINGS=deny` (or `-D warnings`) will cause your build to fail if **any** warnings +> [!NOTE] +> Using `CARGO_BUILD_WARNINGS=deny` (or `-D warnings`) will cause your build to fail if **any** warnings > are found in your code. That includes warnings found by rustc (e.g. > `dead_code`, etc.) @@ -103,7 +106,8 @@ The second group is the `restriction` group. This group contains lints that this group won't allow you to use `.unwrap()` in your code. You may want to look through the lints in this group and enable the ones that fit your need. -> _Note:_ You shouldn't enable the whole lint group, but cherry-pick lints from +> [!NOTE] +> You shouldn't enable the whole lint group, but cherry-pick lints from > this group. Some lints in this group will even contradict other Clippy lints! #### Too many lints @@ -113,7 +117,8 @@ group. Some people prefer to disable this group completely and then cherry-pick some lints they like from this group. The same is of course possible with every other of Clippy's lint groups. -> _Note:_ We try to keep the warn-by-default groups free from false positives +> [!NOTE] +> We try to keep the warn-by-default groups free from false positives > (FP). If you find that a lint wrongly triggers, please report it in an issue > (if there isn't an issue for that FP already) @@ -167,7 +172,8 @@ Clippy can also be used in projects that do not use cargo. To do so, run clippy-driver --edition 2018 -Cpanic=abort foo.rs ``` -> _Note:_ `clippy-driver` is designed for running Clippy and should not be used +> [!NOTE] +> `clippy-driver` is designed for running Clippy and should not be used > as a general replacement for `rustc`. `clippy-driver` may produce artifacts > that are not optimized as expected, for example. diff --git a/lintcheck/README.md b/lintcheck/README.md index 47a96e0a03c9c..c0409d512d6d5 100644 --- a/lintcheck/README.md +++ b/lintcheck/README.md @@ -33,7 +33,8 @@ the 200 recently most downloaded crates: cargo lintcheck popular -n 200 custom.toml ``` -> Note: Lintcheck isn't sandboxed. Only use it to check crates that you trust or +> [!NOTE] +> Lintcheck isn't sandboxed. Only use it to check crates that you trust or > sandbox it manually. ### Configuring the Crate Sources @@ -78,7 +79,8 @@ You can run `cargo lintcheck --fix` which will run Clippy with `--fix` and print a warning if Clippy's suggestions fail to apply (if the resulting code does not build). This lets us spot bad suggestions or false positives automatically in some cases. -> Note: Fix mode implies `--all-targets`, so it can fix as much code as it can. +> [!NOTE] +> Fix mode implies `--all-targets`, so it can fix as much code as it can. Please note that the target dir should be cleaned afterwards since Clippy will modify the downloaded sources which can lead to unexpected results when running lintcheck again afterwards. From 999b4aaa959fc886e272249c63bd6cdc85a119bf Mon Sep 17 00:00:00 2001 From: Rachel Barker Date: Thu, 17 Sep 2026 16:57:10 +0100 Subject: [PATCH 0856/1309] Fix maximum read/write/send length on non-{Mac, Windows} platforms On most platforms, `send` takes a `size_t` length, but returns an `ssize_t` count of bytes written. This means that the actual limit is `ssize_t::MAX`, not `size_t::MAX`. QNX has a bug on top of this, where the returned length appears to be converted to a C `int` and back, resulting in the wrong return value if the length is >= 2^31 bytes. --- library/std/src/sys/fd/unix.rs | 16 ++++++---- .../std/src/sys/net/connection/socket/mod.rs | 24 +++++++++++--- .../src/sys/net/connection/socket/tests.rs | 31 +++++++++++++++---- .../src/sys/net/connection/socket/windows.rs | 2 +- 4 files changed, 55 insertions(+), 18 deletions(-) diff --git a/library/std/src/sys/fd/unix.rs b/library/std/src/sys/fd/unix.rs index aa84f6bc28023..6ebbc6afc1661 100644 --- a/library/std/src/sys/fd/unix.rs +++ b/library/std/src/sys/fd/unix.rs @@ -72,12 +72,16 @@ pub struct FileDesc(OwnedFd); // // On Apple targets however, apparently the 64-bit libc is either buggy or // intentionally showing odd behavior by rejecting any read with a size -// larger than INT_MAX. To handle both of these the read size is capped on -// both platforms. -const READ_LIMIT: usize = if cfg!(target_vendor = "apple") { - libc::c_int::MAX as usize -} else { - libc::ssize_t::MAX as usize +// larger than INT_MAX. +// +// Meanwhile on QNX, reads/writes/sends larger than INT_MAX return the wrong +// number of bytes written (eg, writing 2^31 bytes returns (2^64 - 2^31) instead +// of the correct byte count). +const READ_LIMIT: usize = cfg_select! { + any(target_vendor = "apple", target_os = "nto", target_os = "qnx") => { + libc::c_int::MAX as usize + } + _ => libc::ssize_t::MAX as usize, }; #[cfg(any( diff --git a/library/std/src/sys/net/connection/socket/mod.rs b/library/std/src/sys/net/connection/socket/mod.rs index 4e5de0209ad24..55db60fde694d 100644 --- a/library/std/src/sys/net/connection/socket/mod.rs +++ b/library/std/src/sys/net/connection/socket/mod.rs @@ -36,8 +36,26 @@ cfg_select! { use netc as c; +// Similarly to reads (see READ_LIMIT), the `send` syscall on most platforms +// takes a `size_t` length, but returns an `ssize_t` of bytes written. So the +// actual maximum number of bytes we can send in one call is SSIZE_MAX. +// +// On Apple targets however, apparently the 64-bit libc is either buggy or +// intentionally showing odd behavior by rejecting send calls with a size +// larger than INT_MAX. So cap the send size to INT_MAX. +// +// Meanwhile on QNX, reads/writes/sends larger than INT_MAX return the wrong +// number of bytes written (eg, writing 2^31 bytes returns (2^64 - 2^31) instead +// of the correct byte count). +// +// On Windows, the relevant syscall takes an `i32` (unlike for read/write!), +// so we need to clamp to i32::MAX. const MAX_SEND_LEN: usize = - if cfg!(target_vendor = "apple") { c_int::MAX as usize } else { ::MAX as usize }; + cfg_select! { + any(target_vendor = "apple", target_os = "nto", target_os = "qnx") => c_int::MAX as usize, + target_os = "windows" => i32::MAX as usize, + _ => libc::ssize_t::MAX as usize, + }; cfg_select! { any( @@ -717,8 +735,6 @@ impl UdpSocket { self.inner.peek_from(buf) } - // `MAX_SEND_LEN` is `usize::MAX` off Apple/Windows, where the guard is a no-op. - #[allow(clippy::absurd_extreme_comparisons)] pub fn send_to(&self, buf: &[u8], dst: &SocketAddr) -> io::Result { if buf.len() > MAX_SEND_LEN { return Err(io::Error::from_raw_os_error(c::EMSGSIZE)); @@ -872,8 +888,6 @@ impl UdpSocket { self.inner.peek(buf) } - // `MAX_SEND_LEN` is `usize::MAX` off Apple/Windows, where the guard is a no-op. - #[allow(clippy::absurd_extreme_comparisons)] pub fn send(&self, buf: &[u8]) -> io::Result { if buf.len() > MAX_SEND_LEN { return Err(io::Error::from_raw_os_error(c::EMSGSIZE)); diff --git a/library/std/src/sys/net/connection/socket/tests.rs b/library/std/src/sys/net/connection/socket/tests.rs index e6f02d7a93859..cc072420b754b 100644 --- a/library/std/src/sys/net/connection/socket/tests.rs +++ b/library/std/src/sys/net/connection/socket/tests.rs @@ -18,13 +18,32 @@ fn no_lookup_host_duplicates() { ); } -// #115325: on Apple, `send` rejects a length > `c_int::MAX` with `EINVAL`, so -// the clamp must not regress to the unbounded `wrlen_t::MAX`. +// On non-Windows platforms, the maximum valid length to pass into `send` is +// not the same as the maximum of the *type* used for the length. Ensure that +// the proper maximum is used, and that we do not regress to simply clamping to +// `wrlen_t::MAX` +// +// On Apple (per 115325), `send` takes a `size_t` length, but rejects any +// length > `c_int::MAX` with `EINVAL`. +// +// On QNX, `send` with length > `c_int::MAX` returns an incorrect count of bytes +// written. +// +// On Windows, `send` takes an `i32` length and returns an `i32`. +// +// On other platforms, `send` takes a `size_t` and returns an `ssize_t`, so +// sends larger then `ssize_t::MAX` will (maybe silently) return bad lengths. #[test] fn max_send_len_within_platform_limit() { - if cfg!(target_vendor = "apple") { - assert_eq!(MAX_SEND_LEN, c_int::MAX as usize); - } else { - assert_eq!(MAX_SEND_LEN, ::MAX as usize); + cfg_select! { + any(target_vendor = "apple", target_os = "nto", target_os = "qnx") => { + assert_eq!(MAX_SEND_LEN, c_int::MAX as usize); + } + target_os = "windows" => { + assert_eq!(MAX_SEND_LEN, i32::MAX as usize); + } + _ => { + assert_eq!(MAX_SEND_LEN, libc::ssize_t::MAX as usize); + } } } diff --git a/library/std/src/sys/net/connection/socket/windows.rs b/library/std/src/sys/net/connection/socket/windows.rs index 8b98d0d31e507..e9d5336001fd8 100644 --- a/library/std/src/sys/net/connection/socket/windows.rs +++ b/library/std/src/sys/net/connection/socket/windows.rs @@ -309,7 +309,7 @@ impl Socket { ) -> io::Result<(usize, SocketAddr)> { let mut storage = unsafe { mem::zeroed::() }; let mut addrlen = size_of_val(&storage) as netc::socklen_t; - let length = cmp::min(buf.len(), ::MAX as usize) as wrlen_t; + let length = cmp::min(buf.len(), super::MAX_SEND_LEN) as wrlen_t; // On unix when a socket is shut down all further reads return 0, so we // do the same on windows to map a shut down socket to returning EOF. From 424d9ecb1a15b239ea85bcbb9126b12cfd5f6277 Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 11 May 2026 14:57:33 -0400 Subject: [PATCH 0857/1309] Convert crate hash to use metadata instead of HIR --- compiler/rustc_ast_lowering/src/lib.rs | 2 +- compiler/rustc_crate_store/src/cstore.rs | 4 + compiler/rustc_data_structures/src/svh.rs | 4 + compiler/rustc_driver_impl/src/lib.rs | 8 +- compiler/rustc_hir/src/hir.rs | 10 + compiler/rustc_interface/src/passes.rs | 9 +- compiler/rustc_metadata/src/creader.rs | 39 +++- compiler/rustc_metadata/src/locator.rs | 2 +- compiler/rustc_metadata/src/rmeta/decoder.rs | 51 +++-- .../src/rmeta/decoder/cstore_impl.rs | 4 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 196 ++++++++++++++---- compiler/rustc_metadata/src/rmeta/mod.rs | 41 +++- .../rustc_metadata/src/rmeta/parameterized.rs | 1 + compiler/rustc_middle/src/hir/map.rs | 56 ++++- compiler/rustc_middle/src/ty/context.rs | 21 ++ compiler/rustc_session/src/options.rs | 3 + .../crate-hash-dep-extra-filename/a.rs | 7 + .../crate-hash-dep-extra-filename/b.rs | 9 + .../crate-hash-dep-extra-filename/rmake.rs | 89 ++++++++ .../run-make/crate-hash-metadata-flag/foo.rs | 7 + .../crate-hash-metadata-flag/rmake.rs | 41 ++++ .../metadata-stub-incremental-reuse/foo.rs | 3 + .../metadata-stub-incremental-reuse/rmake.rs | 33 +++ .../foo.rs | 16 ++ .../rmake.rs | 43 ++++ .../v1.rs | 12 ++ .../v2.rs | 13 ++ .../changing_macro.rs | 15 ++ .../proc-macro-env-changes-crate-hash/foo.rs | 9 + .../rmake.rs | 56 +++++ .../changing_macro.rs | 18 ++ .../foo.rs | 9 + .../rmake.rs | 64 ++++++ 33 files changed, 818 insertions(+), 77 deletions(-) create mode 100644 tests/run-make/crate-hash-dep-extra-filename/a.rs create mode 100644 tests/run-make/crate-hash-dep-extra-filename/b.rs create mode 100644 tests/run-make/crate-hash-dep-extra-filename/rmake.rs create mode 100644 tests/run-make/crate-hash-metadata-flag/foo.rs create mode 100644 tests/run-make/crate-hash-metadata-flag/rmake.rs create mode 100644 tests/run-make/metadata-stub-incremental-reuse/foo.rs create mode 100644 tests/run-make/metadata-stub-incremental-reuse/rmake.rs create mode 100644 tests/run-make/proc-macro-dep-source-changes-crate-hash/foo.rs create mode 100644 tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs create mode 100644 tests/run-make/proc-macro-dep-source-changes-crate-hash/v1.rs create mode 100644 tests/run-make/proc-macro-dep-source-changes-crate-hash/v2.rs create mode 100644 tests/run-make/proc-macro-env-changes-crate-hash/changing_macro.rs create mode 100644 tests/run-make/proc-macro-env-changes-crate-hash/foo.rs create mode 100644 tests/run-make/proc-macro-env-changes-crate-hash/rmake.rs create mode 100644 tests/run-make/proc-macro-global-asm-changes-crate-hash/changing_macro.rs create mode 100644 tests/run-make/proc-macro-global-asm-changes-crate-hash/foo.rs create mode 100644 tests/run-make/proc-macro-global-asm-changes-crate-hash/rmake.rs diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index b10279d71e566..4bc61a22b3b3d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -253,7 +253,7 @@ impl<'a, 'hir> PerOwnerLoweringState<'a, 'hir> { let nodes = hir::OwnerNodes { opt_hash: bodies_hash, nodes, bodies }; let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque }; - let opt_hash = tcx.needs_hir_hash().then(|| { + let opt_hash = tcx.needs_owner_info_hash().then(|| { tcx.with_stable_hashing_context(|mut hcx| { let mut stable_hasher = StableHasher::new(); bodies_hash.unwrap().stable_hash(&mut hcx, &mut stable_hasher); diff --git a/compiler/rustc_crate_store/src/cstore.rs b/compiler/rustc_crate_store/src/cstore.rs index fba2fc288f5a9..c8fe5562bdd59 100644 --- a/compiler/rustc_crate_store/src/cstore.rs +++ b/compiler/rustc_crate_store/src/cstore.rs @@ -4,9 +4,11 @@ use std::any::Any; use std::path::PathBuf; +use std::sync::OnceLock; use rustc_abi::ExternAbi; use rustc_attr_ir::{CfgEntry, PeImportNameType}; +use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{self, AppendOnlyIndexVec, FreezeLock}; use rustc_hir_id::definitions::{DefKey, DefPath, Definitions}; use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash}; @@ -220,6 +222,8 @@ pub struct Untracked { pub definitions: FreezeLock, /// The interned [StableCrateId]s. pub stable_crate_ids: FreezeLock, + /// The hash of the local crate as computed in metadata encoding. + pub local_crate_hash: OnceLock, } impl Untracked { diff --git a/compiler/rustc_data_structures/src/svh.rs b/compiler/rustc_data_structures/src/svh.rs index 67594f6dae79d..0b80c655d8a5a 100644 --- a/compiler/rustc_data_structures/src/svh.rs +++ b/compiler/rustc_data_structures/src/svh.rs @@ -32,6 +32,10 @@ impl Svh { pub fn to_hex(self) -> String { format!("{:032x}", self.hash.as_u128()) } + + pub fn as_fingerprint(self) -> Fingerprint { + self.hash + } } impl fmt::Display for Svh { diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index fce99655f54ab..210f04a115831 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -315,10 +315,6 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) tcx.ensure_ok().analysis(()); - if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { - dump_feature_usage_metrics(tcx, metrics_dir); - } - if callbacks.after_analysis(compiler, tcx) == Compilation::Stop { return None; } @@ -331,6 +327,10 @@ pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) let linker = Linker::codegen_and_build_linker(tcx, codegen_backend); + if let Some(metrics_dir) = &sess.opts.unstable_opts.metrics_dir { + dump_feature_usage_metrics(tcx, metrics_dir); + } + tcx.report_unused_features(); Some(linker) diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index f55ab2a0ccbcc..5cfce366bbb23 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -1405,6 +1405,16 @@ impl<'tcx> OwnerInfo<'tcx> { pub fn node(&self) -> OwnerNode<'tcx> { self.nodes.node() } + + // A fingerprint that identifies the contents of the OwnerInfo. + // It only depends on `nodes` and `attrs` because `parenting` and `trait_map` are + // deterministically calculated from `nodes` and `attrs`. + #[inline] + pub fn fingerprint(&self) -> Fingerprint { + let body = self.nodes.opt_hash.expect("HIR hash requested without needs_hir_hash"); + let attrs = self.attrs.opt_hash.expect("HIR hash requested without needs_hir_hash"); + body.combine(attrs) + } } #[derive(Copy, Clone, Debug, StableHash)] diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 610eb5fd099d2..da0ebce5be045 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -960,8 +960,13 @@ pub fn create_and_enter_global_ctxt FnOnce(TyCtxt<'tcx>) -> T>( let definitions = FreezeLock::new(Definitions::new(stable_crate_id)); let stable_crate_ids = FreezeLock::new(StableCrateIdMap::default()); - let untracked = - Untracked { cstore, source_span: AppendOnlyIndexVec::new(), definitions, stable_crate_ids }; + let untracked = Untracked { + cstore, + source_span: AppendOnlyIndexVec::new(), + definitions, + stable_crate_ids, + local_crate_hash: OnceLock::new(), + }; // We're constructing the HIR here; we don't care what we will // read, since we haven't even constructed the *input* to diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index ad8264078348b..aea843ac0384c 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -143,6 +143,10 @@ enum CrateOrigin<'a> { parent_private: bool, /// Dependency info about this crate. dep: &'a CrateDep, + /// The dependency's `-C extra-filename`, used to narrow the search for it on disk. Stored + /// separately from `dep` because it is encoded outside the hashed crate root; see + /// `CrateRootUnhashed::dep_extra_filenames`. + dep_extra_filename: &'a str, }, /// Injected by `rustc`. Injected, @@ -169,6 +173,14 @@ impl<'a> CrateOrigin<'a> { } } + /// Return the dependency's `-C extra-filename`, if any. + fn dep_extra_filename(&self) -> Option<&'a str> { + match self { + CrateOrigin::IndirectDependency { dep_extra_filename, .. } => Some(dep_extra_filename), + _ => None, + } + } + /// `Some(true)` if the dependency is private or its parent is private, `Some(false)` if the /// dependency is not private, `None` if it could not be determined. fn private_dep(&self) -> Option { @@ -582,7 +594,8 @@ impl CStore { let Library { source, metadata } = lib; let crate_root = metadata.get_root(); - let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_root().hash()); + let unhashed = metadata.get_root_unhashed(); + let host_hash = host_lib.as_ref().map(|lib| lib.metadata.get_crate_hash()); let private_dep = self.is_private_dep(&tcx.sess.opts.externs, name, private_dep); // Claim this crate number and cache it @@ -635,6 +648,7 @@ impl CStore { tcx, metadata, crate_root, + unhashed, raw_proc_macros, cnum, cnum_map, @@ -777,7 +791,7 @@ impl CStore { let dep = origin.dep(); let hash = dep.map(|d| d.hash); let host_hash = dep.map(|d| d.host_hash).flatten(); - let extra_filename = dep.map(|d| &d.extra_filename[..]); + let extra_filename = origin.dep_extra_filename(); let path_kind = if dep.is_some() { PathKind::Dependency } else { PathKind::Crate }; let private_dep = origin.private_dep(); @@ -858,10 +872,11 @@ impl CStore { // against a hash, we could load a crate which has the same hash // as an already loaded crate. If this is the case prevent // duplicates by just using the first crate. - let root = library.metadata.get_root(); + let root_name = library.metadata.get_root().name(); + let root_hash = library.metadata.get_crate_hash(); let mut result = LoadResult::Loaded(library); for (cnum, data) in self.iter_crate_data() { - if data.name() == root.name() && root.hash() == data.hash() { + if data.name() == root_name && data.hash() == root_hash { assert!(locator.hash.is_none()); info!("load success, going to previous cnum: {}", cnum); result = LoadResult::Previous(cnum); @@ -895,15 +910,26 @@ impl CStore { // We map 0 and all other holes in the map to our parent crate. The "additional" // self-dependencies should be harmless. let deps = crate_root.decode_crate_deps(metadata); + // Encoded outside the hashed crate root; see `CrateRootUnhashed::dep_extra_filenames`. + // Holds one entry per dep after the unused `LOCAL_CRATE` slot, so it lines up with `deps` + // once that slot is skipped. + let dep_extra_filenames = metadata.get_dep_extra_filenames(); + assert_eq!( + dep_extra_filenames.len(), + deps.len() + 1, + "expected one dep_extra_filename per crate dep, plus the unused LOCAL_CRATE slot", + ); let mut crate_num_map = CrateNumMap::with_capacity(1 + deps.len()); crate_num_map.push(krate); - for dep in deps { + for (dep, dep_extra_filename) in + deps.zip(dep_extra_filenames.iter().skip(1).map(String::as_str)) + { info!( "resolving dep `{}`->`{}` hash: `{}` extra filename: `{}` private {}", crate_root.name(), dep.name, dep.hash, - dep.extra_filename, + dep_extra_filename, dep.is_private, ); let dep_kind = match dep_kind { @@ -918,6 +944,7 @@ impl CStore { dep_root_for_errors, parent_private: parent_is_private, dep: &dep, + dep_extra_filename, }, )?; crate_num_map.push(cnum); diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs index 23b51dfbf62c6..38da6561ecb38 100644 --- a/compiler/rustc_metadata/src/locator.rs +++ b/compiler/rustc_metadata/src/locator.rs @@ -724,7 +724,7 @@ impl<'a> CrateLocator<'a> { return None; } - let hash = header.hash; + let hash = metadata.get_crate_hash(); if let Some(expected_hash) = self.hash { if hash != expected_hash { info!("Rejecting via hash: expected {} got {}", expected_hash, hash); diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index b7fe5fb2475c6..27b36c23daf46 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -95,6 +95,8 @@ pub(crate) struct CrateMetadata { // --- Some data pre-decoded from the metadata blob, usually for performance --- /// Data about the top-level items in a crate, as well as various crate-level metadata. root: CrateRoot, + /// Crate-level metadata that is not in the SVH. + unhashed: CrateRootUnhashed, /// Trait impl data. /// FIXME: Used only from queries and can use query cache, /// so pre-decoding can probably be avoided. @@ -694,8 +696,7 @@ impl MetadataBlob { } let found_version = - LazyValue::::from_position(NonZero::new(METADATA_HEADER.len() + 8).unwrap()) - .decode(self); + LazyValue::::from_position(NonZero::new(VERSION_OFFSET).unwrap()).decode(self); if rustc_version(cfg_version) != found_version { return Err(Some(found_version)); } @@ -704,8 +705,13 @@ impl MetadataBlob { } fn root_pos(&self) -> NonZero { - let offset = METADATA_HEADER.len(); - let pos_bytes = self[offset..][..8].try_into().unwrap(); + let pos_bytes = self[ROOT_POS_OFFSET..][..8].try_into().unwrap(); + let pos = u64::from_le_bytes(pos_bytes); + NonZero::new(pos as usize).unwrap() + } + + fn unhashed_pos(&self) -> NonZero { + let pos_bytes = self[UNHASHED_POS_OFFSET..][..8].try_into().unwrap(); let pos = u64::from_le_bytes(pos_bytes); NonZero::new(pos as usize).unwrap() } @@ -720,12 +726,28 @@ impl MetadataBlob { LazyValue::::from_position(pos).decode(self) } + pub(crate) fn get_root_unhashed(&self) -> CrateRootUnhashed { + let pos = self.unhashed_pos(); + LazyValue::::from_position(pos).decode(self) + } + + pub(crate) fn get_dep_extra_filenames(&self) -> IndexVec { + self.get_root_unhashed().dep_extra_filenames + } + + pub(crate) fn get_crate_hash(&self) -> Svh { + let bytes: [u8; CRATE_HASH_LEN] = + self[CRATE_HASH_OFFSET..][..CRATE_HASH_LEN].try_into().unwrap(); + Svh::new(Fingerprint::from_le_bytes(bytes)) + } + pub(crate) fn list_crate_metadata( &self, out: &mut dyn io::Write, ls_kinds: &[String], ) -> io::Result<()> { let root = self.get_root(); + let extra_filename = self.get_root_unhashed().extra_filename; let all_ls_kinds = vec![ "root".to_owned(), @@ -740,11 +762,11 @@ impl MetadataBlob { match &**kind { "root" => { writeln!(out, "Crate info:")?; - writeln!(out, "name {}{}", root.name(), root.extra_filename)?; + writeln!(out, "name {}{}", root.name(), extra_filename)?; writeln!( out, "hash {} stable_crate_id {:?}", - root.hash(), + self.get_crate_hash(), root.stable_crate_id )?; writeln!(out, "proc_macro {:?}", root.proc_macro_data.is_some())?; @@ -778,10 +800,15 @@ impl MetadataBlob { writeln!(out, "=External Dependencies=")?; let dylib_dependency_formats = root.dylib_dependency_formats.decode(self).collect::>(); + // `extra_filename` is stored outside the hashed root; see + // `CrateRootUnhashed::dep_extra_filenames`. + let dep_extra_filenames = self.get_dep_extra_filenames(); for (i, dep) in root.crate_deps.decode(self).enumerate() { - let CrateDep { name, extra_filename, hash, host_hash, kind, is_private } = - dep; + let CrateDep { name, hash, host_hash, kind, is_private } = dep; let number = i + 1; + let extra_filename = dep_extra_filenames + .get(CrateNum::new(number)) + .map_or("", |name| name.as_str()); writeln!( out, @@ -952,10 +979,6 @@ impl CrateRoot { self.header.name } - pub(crate) fn hash(&self) -> Svh { - self.header.hash - } - pub(crate) fn stable_crate_id(&self) -> StableCrateId { self.stable_crate_id } @@ -1930,6 +1953,7 @@ impl CrateMetadata { tcx: TyCtxt<'_>, blob: MetadataBlob, root: CrateRoot, + unhashed: CrateRootUnhashed, raw_proc_macros: Option<&'static [ProcMacroClient]>, cnum: CrateNum, cnum_map: CrateNumMap, @@ -1953,6 +1977,7 @@ impl CrateMetadata { let mut cdata = CrateMetadata { blob, root, + unhashed, trait_impls, incoherent_impls: Default::default(), raw_proc_macros, @@ -2094,7 +2119,7 @@ impl CrateMetadata { } pub(crate) fn hash(&self) -> Svh { - self.root.header.hash + self.blob.get_crate_hash() } pub(crate) fn has_async_drops(&self) -> bool { diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs index 79bfb15eefac1..154cf4f060a9e 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs @@ -376,12 +376,12 @@ provide! { tcx, def_id, other, cdata, } native_libraries => { cdata.get_native_libraries(tcx).collect() } foreign_modules => { cdata.get_foreign_modules(tcx).map(|m| (m.def_id, m)).collect() } - crate_hash => { cdata.root.header.hash } + crate_hash => { cdata.hash() } crate_host_hash => { cdata.host_hash } crate_name => { cdata.root.header.name } num_extern_def_ids => { cdata.num_def_ids() } - extra_filename => { tcx.arena.alloc_str(&cdata.root.extra_filename) } + extra_filename => { tcx.arena.alloc_str(&cdata.unhashed.extra_filename) } traits => { tcx.arena.alloc_from_iter(cdata.get_traits(tcx)) } trait_impls_in_crate => { tcx.arena.alloc_from_iter(cdata.get_trait_impls(tcx)) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 629efc498863b..f9343cb35f174 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2,14 +2,19 @@ use std::borrow::Borrow; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fs::File; -use std::io::{Read, Seek, Write}; +use std::hash::Hasher; +use std::io::{Read, Seek, SeekFrom, Write}; +use std::ops::Deref; use std::path::{Path, PathBuf}; use std::rc::Rc; -use std::sync::Arc; +use std::sync::{Arc, Mutex}; use rustc_attr_ir::{AttributeKind, EncodeCrossCrate, find_attr}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::memmap::{Mmap, MmapMut}; +use rustc_data_structures::owned_slice::slice_owned; +use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_data_structures::sync::{par_for_each_in, par_join}; use rustc_data_structures::temp_dir::MaybeTempDir; use rustc_data_structures::thousands::usize_with_underscores; @@ -17,7 +22,9 @@ use rustc_hir as hir; use rustc_hir::def_id::{CRATE_DEF_ID, LOCAL_CRATE, LocalDefId, LocalDefIdSet}; use rustc_hir::definitions::DefPathData; use rustc_hir_pretty::id_to_string; +use rustc_index::IndexVec; use rustc_middle::dep_graph::{WorkProduct, WorkProductId}; +use rustc_middle::hir::map::compute_hir_hash; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::mir::interpret; use rustc_middle::query::Providers; @@ -25,7 +32,8 @@ use rustc_middle::traits::specialization_graph; use rustc_middle::ty::AssocContainer; use rustc_middle::ty::codec::TyEncoder; use rustc_middle::ty::fast_reject::{self, TreatParams}; -use rustc_serialize::{Decodable, Decoder, Encodable, Encoder, opaque}; +use rustc_serialize::opaque::FileEncoder; +use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_session::config::mitigation_coverage::DeniedPartialMitigation; use rustc_session::config::{OptLevel, OutputType, TargetModifier}; use rustc_span::def_id::CRATE_MOD_ID; @@ -42,7 +50,8 @@ use crate::eii::EiiMapEncodedKeyValue; use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { - opaque: opaque::FileEncoder<'a>, + opaque: FileEncoder<'a>, + metadata_hasher: Arc>, tcx: TyCtxt<'tcx>, feat: &'tcx rustc_feature::Features, tables: TableBuilders, @@ -606,7 +615,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { adapted.encode(&mut self.opaque) } - fn encode_crate_root(&mut self) -> LazyValue { + fn encode_crate_root(&mut self) -> (LazyValue, LazyValue) { let tcx = self.tcx; let mut stats: Vec<(&'static str, usize)> = Vec::with_capacity(32); @@ -727,17 +736,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let denied_partial_mitigations = stat!("denied-partial-mitigations", || self .encode_enabled_denied_partial_mitigations()); - let root = stat!("final", || { + let root = stat!("crate-root", || { let attrs = tcx.hir_krate_attrs(); self.lazy(CrateRoot { header: CrateHeader { name: tcx.crate_name(LOCAL_CRATE), triple: tcx.sess.opts.target_triple.clone(), - hash: tcx.crate_hash(LOCAL_CRATE), is_proc_macro_crate: proc_macro_data.is_some(), is_stub: false, }, - extra_filename: tcx.sess.opts.cg.extra_filename.clone(), + stable_crate_id: tcx.stable_crate_id(LOCAL_CRATE), required_panic_strategy: tcx.required_panic_strategy(LOCAL_CRATE), panic_in_drop_strategy: tcx.sess.opts.unstable_opts.panic_in_drop, @@ -789,6 +797,34 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { }) }); + // By default the crate hash (SVH) is derived from the encoded metadata bytes. With + // `-Z metadata-crate-hash=no` we instead store the legacy HIR-based hash, which the + // `crate_hash` query computes directly without consulting `local_crate_hash`. + let hash = if tcx.sess.opts.unstable_opts.metadata_crate_hash { + self.opaque.flush(); + Svh::new(self.metadata_hasher.lock().unwrap().clone().finish()) + } else { + tcx.crate_hash(LOCAL_CRATE) + }; + tcx.untracked().local_crate_hash.set(hash).expect("local_crate_hash set twice"); + + let unhashed = stat!("final", || { + // Indexed by dependency `CrateNum`, matching the numbering `encode_crate_deps` uses. + // Slot 0 (`LOCAL_CRATE`) is filler; this crate's own value is `extra_filename`. + let mut dep_extra_filenames = IndexVec::from_elem_n(String::new(), 1); + if !self.is_proc_macro { + for &cnum in self.tcx.crates(()).iter() { + let idx = dep_extra_filenames.push(self.tcx.extra_filename(cnum).to_owned()); + assert_eq!(idx, cnum, "dep_extra_filenames must be indexed by CrateNum"); + } + } + + self.lazy(CrateRootUnhashed { + extra_filename: self.tcx.sess.opts.cg.extra_filename.clone(), + dep_extra_filenames, + }) + }); + let total_bytes = self.position(); let computed_total_bytes: usize = stats.iter().map(|(_, size)| size).sum(); @@ -852,7 +888,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { eprint!("{s}"); } - root + (root, unhashed) } } @@ -2109,7 +2145,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { hash: self.tcx.crate_hash(cnum), host_hash: self.tcx.crate_host_hash(cnum), kind: self.tcx.crate_dep_kind(cnum), - extra_filename: self.tcx.extra_filename(cnum).to_owned(), is_private: self.tcx.is_private_dep(cnum), }; (cnum, dep) @@ -2479,22 +2514,6 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { // there's no need to do dep-graph tracking for any of it. tcx.dep_graph.assert_ignored(); - // Generate the metadata stub manually, as that is a small file compared to full metadata. - if let Some(ref_path) = ref_path { - let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata_stub"); - - with_encode_metadata_header(tcx, ref_path, |ecx| { - let header: LazyValue = ecx.lazy(CrateHeader { - name: tcx.crate_name(LOCAL_CRATE), - triple: tcx.sess.opts.target_triple.clone(), - hash: tcx.crate_hash(LOCAL_CRATE), - is_proc_macro_crate: false, - is_stub: true, - }); - header.position.get() - }) - } - let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata"); let dep_node = tcx.metadata_dep_node(); @@ -2515,6 +2534,30 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { Ok(_) => {} Err(err) => tcx.dcx().emit_fatal(FailCreateFileEncoder { err }), }; + + // Read the SVH from the old metadata header. + let file = std::fs::File::open(&source_file_in_incr_dir).unwrap(); + let mmap = unsafe { Mmap::map(file) }.unwrap(); + let owned = slice_owned(mmap, Deref::deref); + let blob = MetadataBlob::new(owned); + let hash = blob.expect("file already created").get_crate_hash(); + tcx.untracked().local_crate_hash.set(hash).expect("local_crate_hash set twice"); + + // Generate the metadata stub manually, as that is a small file compared to full metadata. + if let Some(ref_path) = ref_path { + let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata_stub"); + + with_encode_metadata_header(tcx, ref_path, |ecx| { + let header: LazyValue = ecx.lazy(CrateHeader { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + is_proc_macro_crate: false, + is_stub: true, + }); + (header.position.get(), 0) + }) + } + return; }; @@ -2540,7 +2583,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { with_encode_metadata_header(tcx, path, |ecx| { // Encode all the entries and extra information in the crate, // culminating in the `CrateRoot` which points to all of it. - let root = ecx.encode_crate_root(); + let (root, unhashed) = ecx.encode_crate_root(); // Flush buffer to ensure backing file has the correct size. ecx.opaque.flush(); @@ -2551,25 +2594,72 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path, ref_path: Option<&Path>) { ecx.opaque.file().metadata().unwrap().len(), ); - root.position.get() + (root.position.get(), unhashed.position.get()) }) }, None, ); + + // Generate the metadata stub manually, as that is a small file compared to full metadata. + if let Some(ref_path) = ref_path { + let _prof_timer = tcx.prof.verbose_generic_activity("generate_crate_metadata_stub"); + + with_encode_metadata_header(tcx, ref_path, |ecx| { + let header: LazyValue = ecx.lazy(CrateHeader { + name: tcx.crate_name(LOCAL_CRATE), + triple: tcx.sess.opts.target_triple.clone(), + is_proc_macro_crate: false, + is_stub: true, + }); + (header.position.get(), 0) + }) + } } fn with_encode_metadata_header( tcx: TyCtxt<'_>, path: &Path, - f: impl FnOnce(&mut EncodeContext<'_, '_>) -> usize, + f: impl FnOnce(&mut EncodeContext<'_, '_>) -> (usize, usize), ) { - let mut encoder = opaque::FileEncoder::new(path) - .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err })); + // By default the crate hash (SVH) is computed from the bytes of the encoded metadata, + // Under `-Z metadata-crate-hash=no` the SVH comes from the legacy `crate_hash` query instead and + // this hasher is never consulted, so we skip seeding it and feeding metadata bytes into it. + let metadata_crate_hash = tcx.sess.opts.unstable_opts.metadata_crate_hash; + let stable_hasher = Arc::new(Mutex::new(StableHasher::new())); + if metadata_crate_hash { + let hir_body_hash = compute_hir_hash(tcx); + tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = stable_hasher.lock().unwrap(); + // Add dep_tracking_hash to ensure the SVH changes when any tracked flag changes. + tcx.sess.opts.dep_tracking_hash(true).stable_hash(&mut hcx, &mut *hasher); + // Add HIR hash for untracked elements, e.g. DefKind::GlobalAsm. + hir_body_hash.stable_hash(&mut hcx, &mut *hasher); + }); + } + + // Feed every flushed byte into `stable_hasher` so the SVH covers the entire encoded metadata. + let mut flush_strategy = { + let stable_hasher = Arc::clone(&stable_hasher); + move |bytes: &[u8]| stable_hasher.lock().unwrap().write(bytes) + }; + + let mut encoder = if metadata_crate_hash { + FileEncoder::with_flush_strategy(path, &mut flush_strategy) + } else { + FileEncoder::new(path) + } + .unwrap_or_else(|err| tcx.dcx().emit_fatal(FailCreateFileEncoder { err })); encoder.emit_raw_bytes(METADATA_HEADER); // Will be filled with the root position after encoding everything. encoder.emit_raw_bytes(&0u64.to_le_bytes()); + // Same with unhashed_position. + encoder.emit_raw_bytes(&0u64.to_le_bytes()); + + // Same with crate_hash. + encoder.emit_raw_bytes(&Fingerprint::ZERO.to_le_bytes()); + let source_map_files = tcx.sess.source_map().files(); let source_file_cache = (Arc::clone(&source_map_files[0]), 0); let required_source_files = Some(FxIndexSet::default()); @@ -2577,6 +2667,7 @@ fn with_encode_metadata_header( let mut ecx = EncodeContext { opaque: encoder, + metadata_hasher: Arc::clone(&stable_hasher), tcx, feat: tcx.features(), tables: Default::default(), @@ -2595,7 +2686,7 @@ fn with_encode_metadata_header( // Encode the rustc version string in a predictable location. rustc_version(tcx.sess.cfg_version).encode(&mut ecx); - let root_position = f(&mut ecx); + let (root_position, unhashed_position) = f(&mut ecx); // Make sure we report any errors from writing to the file. // If we forget this, compilation can succeed with an incomplete rmeta file, @@ -2604,23 +2695,48 @@ fn with_encode_metadata_header( tcx.dcx().emit_fatal(FailWriteFile { path: &path, err }); } - let file = ecx.opaque.file(); + let mut file = ecx.opaque.file(); + // We will return to this position after writing the root position and crate hash. + let pos_before_seek = file.stream_position().unwrap(); + if let Err(err) = encode_root_position(file, root_position) { tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); } + + if let Err(err) = encode_unhashed_position(file, unhashed_position) { + tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); + } + + let hash = tcx + .untracked() + .local_crate_hash + .get() + .copied() + .expect("local_crate_hash set during encoding"); + if let Err(err) = encode_crate_hash(file, hash) { + tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); + } + + if let Err(err) = file.seek(SeekFrom::Start(pos_before_seek)) { + tcx.dcx().emit_fatal(FailWriteFile { path: ecx.opaque.path(), err }); + } } fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { - // We will return to this position after writing the root position. - let pos_before_seek = file.stream_position().unwrap(); + file.seek(SeekFrom::Start(ROOT_POS_OFFSET as u64))?; + file.write_all(&pos.to_le_bytes())?; + Ok(()) +} - // Encode the root position. - let header = METADATA_HEADER.len(); - file.seek(std::io::SeekFrom::Start(header as u64))?; +fn encode_unhashed_position(mut file: &File, pos: usize) -> Result<(), std::io::Error> { + file.seek(SeekFrom::Start(UNHASHED_POS_OFFSET as u64))?; file.write_all(&pos.to_le_bytes())?; + Ok(()) +} - // Return to the position where we are before writing the root position. - file.seek(std::io::SeekFrom::Start(pos_before_seek))?; +fn encode_crate_hash(mut file: &File, hash: Svh) -> Result<(), std::io::Error> { + file.seek(SeekFrom::Start(CRATE_HASH_OFFSET as u64))?; + file.write_all(&hash.as_fingerprint().to_le_bytes())?; Ok(()) } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index 99429647bd26c..e3f3257acc137 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -1,4 +1,5 @@ use std::marker::PhantomData; +use std::mem::size_of; use std::num::NonZero; use decoder::LazyDecoder; @@ -12,6 +13,7 @@ use rustc_ast as ast; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::{Stability, StrippedCfgItem}; use rustc_crate_store::{CrateDepKind, ForeignModule, LinkagePreference, NativeLib}; +use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::svh::Svh; use rustc_hir as hir; @@ -60,15 +62,27 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String { /// Metadata encoding version. /// N.B., increment this if you change the format of metadata such that /// the rustc version can't be found to compare with `rustc_version()`. -const METADATA_VERSION: u8 = 10; +const METADATA_VERSION: u8 = 11; /// Metadata header which includes `METADATA_VERSION`. /// -/// This header is followed by the length of the compressed data, then -/// the position of the `CrateRoot`, which is encoded as a 64-bit little-endian -/// unsigned integer, and further followed by the rustc version string. +/// This header is followed by the `CrateRoot` and `CrateRootUnhashed` positions +/// which represent the hashed and unhashed metadata contents respectively, the +/// crate hash (SVH), and the rustc version string. See the offset constants +/// below for the exact layout. pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION]; +/// Fixed-size fields encoded immediately after `METADATA_HEADER`, in order: +/// `CrateRoot` position (u64), `CrateRootUnhashed` position (u64), crate hash +/// (`Fingerprint`/SVH), then the variable-length rustc version string. +const ROOT_POS_OFFSET: usize = METADATA_HEADER.len(); +const ROOT_POS_LEN: usize = size_of::(); +const UNHASHED_POS_OFFSET: usize = ROOT_POS_OFFSET + ROOT_POS_LEN; +const UNHASHED_POS_LEN: usize = size_of::(); +const CRATE_HASH_OFFSET: usize = UNHASHED_POS_OFFSET + UNHASHED_POS_LEN; +const CRATE_HASH_LEN: usize = size_of::(); +const VERSION_OFFSET: usize = CRATE_HASH_OFFSET + CRATE_HASH_LEN; + /// A value of type T referred to by its absolute position /// in the metadata, and which can be decoded lazily. /// @@ -213,7 +227,6 @@ pub enum ProcMacroKind { #[derive(MetadataEncodable, BlobDecodable)] pub(crate) struct CrateHeader { pub(crate) triple: TargetTuple, - pub(crate) hash: Svh, pub(crate) name: Symbol, /// Whether this is the header for a proc-macro crate. /// @@ -250,7 +263,6 @@ pub(crate) struct CrateRoot { /// A header used to detect if this is the right crate to load. header: CrateHeader, - extra_filename: String, stable_crate_id: StableCrateId, required_panic_strategy: Option, panic_in_drop_strategy: PanicStrategy, @@ -308,6 +320,18 @@ pub(crate) struct CrateRoot { specialization_enabled_in: bool, } +/// A separate struct for extra metadata that must be encoded *after* +/// the main crate hash is finalized. +#[derive(MetadataEncodable, LazyDecodable)] +pub(crate) struct CrateRootUnhashed { + extra_filename: String, + + /// The `-C extra-filename` of each dependency, indexed by the `CrateNum` they had in *this* + /// crate's encoding. The `LOCAL_CRATE` slot is unused filler so that dependency `CrateNum`s + /// can index this directly; this crate's own value is `extra_filename` above. + dep_extra_filenames: IndexVec, +} + /// On-disk representation of `DefId`. /// This creates a type-safe way to enforce that we remap the CrateNum between the on-disk /// representation and the compilation session. @@ -332,13 +356,16 @@ impl RawDefId { } } +/// A dependency record, as stored in the hashed [`CrateRoot`]. +/// +/// Note the absence of the dependency's `-C extra-filename`: it lives in +/// [`CrateRootUnhashed::dep_extra_filenames`] instead, deliberately outside the hash. #[derive(Encodable, BlobDecodable)] pub(crate) struct CrateDep { pub name: Symbol, pub hash: Svh, pub host_hash: Option, pub kind: CrateDepKind, - pub extra_filename: String, pub is_private: bool, } diff --git a/compiler/rustc_metadata/src/rmeta/parameterized.rs b/compiler/rustc_metadata/src/rmeta/parameterized.rs index a6a937a56ed50..670d875f885c9 100644 --- a/compiler/rustc_metadata/src/rmeta/parameterized.rs +++ b/compiler/rustc_metadata/src/rmeta/parameterized.rs @@ -78,6 +78,7 @@ trivially_parameterized_over_tcx! { crate::rmeta::CrateDep, crate::rmeta::CrateHeader, crate::rmeta::CrateRoot, + crate::rmeta::CrateRootUnhashed, crate::rmeta::IncoherentImpls, crate::rmeta::ProcMacroKind, crate::rmeta::RawDefId, diff --git a/compiler/rustc_middle/src/hir/map.rs b/compiler/rustc_middle/src/hir/map.rs index 6b31decf3b19b..ea266e0032add 100644 --- a/compiler/rustc_middle/src/hir/map.rs +++ b/compiler/rustc_middle/src/hir/map.rs @@ -11,7 +11,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::svh::Svh; use rustc_data_structures::sync::{DynSend, DynSync, par_for_each_in, try_par_for_each_in}; use rustc_hir::def::{DefKind, Res}; -use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalModId}; +use rustc_hir::def_id::{DefId, LocalDefId, LocalModId}; use rustc_hir::definitions::{DefKey, DefPath, DefPathHash}; use rustc_hir::intravisit::Visitor; use rustc_hir::lints::DelayedLints; @@ -19,6 +19,7 @@ use rustc_hir::*; use rustc_span::def_id::{CRATE_MOD_ID, StableCrateId}; use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol, bug, kw, span_bug, with_metavar_spans}; +use crate::hir::def_id::LOCAL_CRATE; use crate::hir::{ModuleItems, ProjectedMaybeOwner, nested_filter}; use crate::middle::debugger_visualizer::DebuggerVisualizerFile; use crate::query::{IntoQueryKey, LocalCrate}; @@ -1163,7 +1164,47 @@ impl<'tcx> intravisit::HirTyCtxt<'tcx> for TyCtxt<'tcx> { } pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { + // `-Z metadata-crate-hash=no` opts back into computing the SVH from the HIR rather than + // from the encoded crate metadata. This is a safety fallback for the metadata-based hashing. + if !tcx.sess.opts.unstable_opts.metadata_crate_hash { + return legacy_crate_hash(tcx); + } + + // If metadata is being encoded, the crate hash has already been computed as part of the + // metadata encoding. + if tcx.needs_metadata() { + *tcx.untracked() + .local_crate_hash + .get() + .expect("crate_hash(LOCAL_CRATE) called before metadata encoding") + } else { + // When metadata isn't encoded, use an HIR based approximation. Encoding metadata for a + // dylib/binary is expensive and fragile. These fields are enough to identify the session. + let hir_body_hash = compute_hir_hash(tcx); + + let upstream_crates = upstream_crates(tcx); + + let crate_hash: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut stable_hasher = StableHasher::new(); + hir_body_hash.stable_hash(&mut hcx, &mut stable_hasher); + upstream_crates.stable_hash(&mut hcx, &mut stable_hasher); + tcx.sess.opts.dep_tracking_hash(true).stable_hash(&mut hcx, &mut stable_hasher); + tcx.stable_crate_id(LOCAL_CRATE).stable_hash(&mut hcx, &mut stable_hasher); + + stable_hasher.finish() + }); + + Svh::new(crate_hash) + } +} + +/// Only reached when `-Z metadata-crate-hash=no` reverts to the pre-metadata-hashing behavior. +/// The HIR-based hashing scheme here matches the `crate_hash` query as it existed before this PR. +/// (The resulting SVH still differs from a pre-PR compiler, because `metadata_crate_hash` is a +/// `[TRACKED]` option and therefore contributes to the dep-tracking hash hashed in below.) +fn legacy_crate_hash(tcx: TyCtxt<'_>) -> Svh { let krate = tcx.hir_crate_items(()); + let upstream_crates = upstream_crates(tcx); let resolutions = tcx.resolutions(()); @@ -1239,6 +1280,19 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, _: LocalCrate) -> Svh { Svh::new(crate_hash) } +/// Compute the new, metadata-oriented HIR hash for the full crate. +/// +/// Unlike the legacy hash (see [`legacy_crate_hash`]), this is an order-independent combine of each +/// owner's fingerprint, so it does not depend on the iteration order of the owners. It becomes part +/// of the `crate_hash` which is stored in the crate metadata. +pub fn compute_hir_hash(tcx: TyCtxt<'_>) -> Fingerprint { + tcx.hir_crate_items(()) + .owners() + .filter_map(|owner| Some(tcx.lower_to_hir(owner.def_id).as_owner()?.fingerprint())) + .reduce(Fingerprint::combine_commutative) + .expect("HIR hash requested without any content") +} + fn upstream_crates(tcx: TyCtxt<'_>) -> Vec<(StableCrateId, Svh)> { let mut upstream_crates: Vec<_> = tcx .crates(()) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b4104d997137f..5cd7322ced683 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1157,6 +1157,27 @@ impl<'tcx> TyCtxt<'tcx> { || self.sess.opts.unstable_opts.metrics_dir.is_some() } + /// Whether the combined per-owner HIR hash (`OwnerInfo::opt_hash`, which folds `parenting`, + /// `trait_map` and `children` on top of the node/attr hashes) needs to be computed during + /// lowering. + /// + /// This is a strict subset of [`Self::needs_hir_hash`]: notably it drops the plain + /// `needs_metadata` case. With metadata-based crate hashing (the default) the crate hash is + /// built from the encoded metadata plus each owner's cheaper `OwnerInfo::fingerprint` (just the + /// node and attr sub-hashes), so the combined hash is never read and computing it is wasted + /// work. It is still required for: + /// - `-Z metadata-crate-hash=no`, where `crate_hash` falls back to hashing each `OwnerInfo`; + /// - incremental, where the `lower_to_hir` result is fingerprinted for red/green tracking; + /// - debug assertions, where every query result is fingerprinted to catch nondeterminism. + /// + /// The `needs_hir_hash()` conjunct guarantees the node/attr sub-hashes it folds in are present. + pub fn needs_owner_info_hash(self) -> bool { + self.needs_hir_hash() + && (!self.sess.opts.unstable_opts.metadata_crate_hash + || self.sess.opts.incremental.is_some() + || cfg!(debug_assertions)) + } + #[inline] pub fn stable_crate_id(self, crate_num: CrateNum) -> StableCrateId { if crate_num == LOCAL_CRATE { diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 13fc598d86bfa..11f150b65687f 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -2648,6 +2648,9 @@ options! { the same values as the target option of the same name"), meta_stats: bool = (false, parse_bool, [UNTRACKED], "gather metadata statistics (default: no)"), + metadata_crate_hash: bool = (true, parse_bool, [TRACKED], + "compute the crate hash (SVH) from the encoded crate metadata; set to `no` to \ + revert to computing it from the HIR (default: yes)"), metrics_dir: Option = (None, parse_opt_pathbuf, [UNTRACKED], "the directory metrics emitted by rustc are dumped into (implicitly enables default set of metrics)"), min_function_alignment: Option = (None, parse_align, [TRACKED], diff --git a/tests/run-make/crate-hash-dep-extra-filename/a.rs b/tests/run-make/crate-hash-dep-extra-filename/a.rs new file mode 100644 index 0000000000000..7da56d12511aa --- /dev/null +++ b/tests/run-make/crate-hash-dep-extra-filename/a.rs @@ -0,0 +1,7 @@ +pub fn f() -> u32 { + 1 +} + +pub struct S { + pub field: u32, +} diff --git a/tests/run-make/crate-hash-dep-extra-filename/b.rs b/tests/run-make/crate-hash-dep-extra-filename/b.rs new file mode 100644 index 0000000000000..2e8656738e61f --- /dev/null +++ b/tests/run-make/crate-hash-dep-extra-filename/b.rs @@ -0,0 +1,9 @@ +extern crate a; + +pub fn g() -> u32 { + a::f() +} + +pub fn make() -> a::S { + a::S { field: 2 } +} diff --git a/tests/run-make/crate-hash-dep-extra-filename/rmake.rs b/tests/run-make/crate-hash-dep-extra-filename/rmake.rs new file mode 100644 index 0000000000000..e5e4cfe56c31c --- /dev/null +++ b/tests/run-make/crate-hash-dep-extra-filename/rmake.rs @@ -0,0 +1,89 @@ +//@ needs-target-std +// +// A dependency's `extra_filename` is only a hint for locating it on disk, not +// part of its identity: the crate loader treats two libraries with equal SVHs +// as the same crate. Verifies that changing the `extra_filename` of a +// dependency does not change the crate hash of its dependents. +// See https://github.com/rust-lang/rust/issues/94878 and PR #154724. + +use run_make_support::{diff, rfs, rustc}; + +fn build_a(dir: &str, extra_filename: &str) -> String { + // Build `a` into `dir` under the given `-C extra-filename`, and return the + // path of the rlib it produced. + let mut cmd = rustc(); + cmd.input("a.rs").crate_name("a").crate_type("rlib").out_dir(dir); + if !extra_filename.is_empty() { + cmd.arg(format!("-Cextra-filename={extra_filename}")); + } + cmd.run(); + format!("{dir}/liba{extra_filename}.rlib") +} + +fn build_b(dir: &str, a_rlib: &str) -> String { + // Build `b` against the given build of `a`, then dump `b`'s SVH. Every + // build of `b` is invoked identically; only which `a` it links differs. + rustc() + .input("b.rs") + .crate_name("b") + .crate_type("rlib") + .extern_("a", a_rlib) + .out_dir(dir) + .run(); + svh(&format!("{dir}/libb.rlib")) +} + +fn svh(rlib: &str) -> String { + // Only the `hash` line of the `-Zls=root` dump. The rest of the dump lists + // the dependencies, and their `extra_filename`s are exactly what varies + // here, so comparing it whole would differ for uninteresting reasons. + let dump = rustc().arg("-Zls=root").input(rlib).run().stdout_utf8(); + dump.lines() + .find(|line| line.starts_with("hash ")) + .expect("`-Zls=root` printed no `hash` line") + .to_owned() +} + +fn main() { + rfs::create_dir("a-one"); + rfs::create_dir("a-two"); + rfs::create_dir("a-here"); + rfs::create_dir("a-there"); + rfs::create_dir("b-one"); + rfs::create_dir("b-two"); + rfs::create_dir("b-here"); + rfs::create_dir("b-there"); + rfs::create_dir("b-one-again"); + + // Two builds of `a` from byte-identical sources, differing only in + // `-C extra-filename`. + let a_one = build_a("a-one", "-one"); + let a_two = build_a("a-two", "-two"); + + // A crate's own `extra_filename` is already excluded from its own SVH, so + // the two builds of `a` must hash identically. Without this the rest of + // the test would prove nothing, because `b` would be entitled to change + // on account of `a` having changed. + let a_one_svh = svh(&a_one); + diff().expected_text("a-one", &a_one_svh).actual_text("a-two", svh(&a_two)).run(); + + // The property under test: `a`'s `extra_filename` must not reach `b`'s SVH. + let b_one = build_b("b-one", &a_one); + let b_two = build_b("b-two", &a_two); + diff().expected_text("b-one", &b_one).actual_text("b-two", b_two).run(); + + // Those two builds also read `a` from different directories, so pin that a + // dependency's *path* does not move `b`'s SVH either. This is what makes + // the comparison above attributable to `extra_filename`. + let a_here = build_a("a-here", ""); + let a_there = build_a("a-there", ""); + let b_here = build_b("b-here", &a_here); + let b_there = build_b("b-there", &a_there); + diff().expected_text("b-here", &b_here).actual_text("b-there", b_there).run(); + + // Sanity: rebuilding `b` against the original `a` reproduces its SVH, so + // the comparisons above are not passing by accident of metadata encoding + // being non-deterministic. + let b_one_again = build_b("b-one-again", &a_one); + diff().expected_text("b-one", &b_one).actual_text("b-one-again", b_one_again).run(); +} diff --git a/tests/run-make/crate-hash-metadata-flag/foo.rs b/tests/run-make/crate-hash-metadata-flag/foo.rs new file mode 100644 index 0000000000000..08fd8d55b09d9 --- /dev/null +++ b/tests/run-make/crate-hash-metadata-flag/foo.rs @@ -0,0 +1,7 @@ +pub fn foo() -> u32 { + 42 +} + +pub struct Bar { + pub x: u32, +} diff --git a/tests/run-make/crate-hash-metadata-flag/rmake.rs b/tests/run-make/crate-hash-metadata-flag/rmake.rs new file mode 100644 index 0000000000000..342a2c565e8c3 --- /dev/null +++ b/tests/run-make/crate-hash-metadata-flag/rmake.rs @@ -0,0 +1,41 @@ +// `-Z metadata-crate-hash=no` is the safety fallback that reverts the crate hash (SVH) +// computation from the encoded crate metadata back to the legacy HIR-based scheme. This test +// checks that the flag actually changes the SVH for an otherwise identical crate, and that each +// mode is deterministic. + +//@ ignore-cross-compile + +use run_make_support::{diff, rfs, rustc}; + +/// Build `foo.rs` into `dir` (optionally with the legacy hashing flag) and return the +/// `-Zls=root` metadata dump, which includes the crate hash (SVH). +fn build_in(dir: &str, metadata_crate_hash: bool) -> String { + let mut cmd = rustc(); + cmd.input("foo.rs").crate_type("rlib").out_dir(dir); + if !metadata_crate_hash { + cmd.arg("-Zmetadata-crate-hash=no"); + } + cmd.run(); + rustc().arg("-Zls=root").input(format!("{dir}/libfoo.rlib")).run().stdout_utf8() +} + +fn main() { + rfs::create_dir("default"); + rfs::create_dir("legacy"); + rfs::create_dir("default_again"); + rfs::create_dir("legacy_again"); + + let default = build_in("default", true); + let legacy = build_in("legacy", false); + + // The SVH (printed by `-Zls=root`) must differ between the metadata-based default and the + // legacy HIR-based scheme. + diff().expected_text("default", &default).actual_text("legacy", &legacy).run_fail(); + + // Each mode must be deterministic. + let default_again = build_in("default_again", true); + diff().expected_text("default", &default).actual_text("default_again", default_again).run(); + + let legacy_again = build_in("legacy_again", false); + diff().expected_text("legacy", &legacy).actual_text("legacy_again", legacy_again).run(); +} diff --git a/tests/run-make/metadata-stub-incremental-reuse/foo.rs b/tests/run-make/metadata-stub-incremental-reuse/foo.rs new file mode 100644 index 0000000000000..7bc9267915469 --- /dev/null +++ b/tests/run-make/metadata-stub-incremental-reuse/foo.rs @@ -0,0 +1,3 @@ +pub fn foo() -> u32 { + 42 +} diff --git a/tests/run-make/metadata-stub-incremental-reuse/rmake.rs b/tests/run-make/metadata-stub-incremental-reuse/rmake.rs new file mode 100644 index 0000000000000..e76433c97d159 --- /dev/null +++ b/tests/run-make/metadata-stub-incremental-reuse/rmake.rs @@ -0,0 +1,33 @@ +//@ needs-target-std +// +// Under `-Zembed-metadata=no` the rlib carries only a metadata stub, which +// rustc writes as a separate file alongside the full metadata. Recompiling +// with `-C incremental` can reuse the full metadata from a work product, and +// the stub must still be produced on that path. + +use run_make_support::{rfs, rustc}; + +fn build(out_dir: &str, incremental: &str) { + rustc() + .input("foo.rs") + .crate_name("foo") + .crate_type("lib") + .emit("dep-info,metadata,link") + .arg("-Zembed-metadata=no") + .incremental(incremental) + .out_dir(out_dir) + .run(); +} + +fn main() { + rfs::create_dir("out"); + rfs::create_dir("incr"); + + // Populates the incremental session directory, including the `metadata` + // work product. + build("out", "incr"); + + // Recompiling from unchanged sources marks the metadata dep-node green and + // reuses that work product. + build("out", "incr"); +} diff --git a/tests/run-make/proc-macro-dep-source-changes-crate-hash/foo.rs b/tests/run-make/proc-macro-dep-source-changes-crate-hash/foo.rs new file mode 100644 index 0000000000000..d645ab8680949 --- /dev/null +++ b/tests/run-make/proc-macro-dep-source-changes-crate-hash/foo.rs @@ -0,0 +1,16 @@ +// Consumer crate. Byte-identical across all invocations of the test; +// only the tokens spliced in by `#[derive(ChangingDerive)]` change between +// builds, driven by which version of the proc-macro is on disk. + +#![crate_type = "rlib"] + +extern crate changing_macro; + +use changing_macro::ChangingDerive; + +#[derive(ChangingDerive)] +pub struct Foo; + +pub fn answer() -> u32 { + ANSWER +} diff --git a/tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs b/tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs new file mode 100644 index 0000000000000..9f7706cfc83e3 --- /dev/null +++ b/tests/run-make/proc-macro-dep-source-changes-crate-hash/rmake.rs @@ -0,0 +1,43 @@ +// Verifies that when the *source* of a proc-macro dependency changes (so the +// tokens it emits in the consumer crate change), the consumer crate's +// crate_hash / SVH changes. +// See https://github.com/rust-lang/rust/issues/94878 and PR #154724. + +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + +use run_make_support::{diff, rfs, rustc}; + +fn build_in(dir: &str, macro_src: &str) -> String { + // Build the proc-macro and the consumer into `dir`, then dump the + // consumer's crate metadata root (which includes the SVH). + rustc() + .input(macro_src) + .crate_name("changing_macro") + .crate_type("proc-macro") + .out_dir(dir) + .run(); + rustc().input("foo.rs").library_search_path(dir).out_dir(dir).run(); + rustc().arg("-Zls=root").input(format!("{dir}/libfoo.rlib")).run().stdout_utf8() +} + +fn main() { + rfs::create_dir("v1"); + rfs::create_dir("v2"); + rfs::create_dir("v1_again"); + + // Build the consumer against proc-macro v1, then against v2. foo.rs is + // byte-identical across builds; only the tokens spliced in by the derive + // differ. + let v1 = build_in("v1", "v1.rs"); + let v2 = build_in("v2", "v2.rs"); + // The SVH (printed by `-Zls=root`) must differ between the two builds. + diff().expected_text("v1", &v1).actual_text("v2", v2).run_fail(); + + // Sanity: rebuilding against v1 reproduces the original dump, so the + // difference above is genuinely caused by the proc-macro source change + // and not by non-determinism in metadata encoding. + let v1_again = build_in("v1_again", "v1.rs"); + diff().expected_text("v1", &v1).actual_text("v1_again", v1_again).run(); +} diff --git a/tests/run-make/proc-macro-dep-source-changes-crate-hash/v1.rs b/tests/run-make/proc-macro-dep-source-changes-crate-hash/v1.rs new file mode 100644 index 0000000000000..056e3f142212c --- /dev/null +++ b/tests/run-make/proc-macro-dep-source-changes-crate-hash/v1.rs @@ -0,0 +1,12 @@ +// First version of the proc-macro. Emits `pub const ANSWER: u32 = 1;`. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ChangingDerive)] +pub fn changing_derive(_input: TokenStream) -> TokenStream { + "pub const ANSWER: u32 = 1;".parse().unwrap() +} diff --git a/tests/run-make/proc-macro-dep-source-changes-crate-hash/v2.rs b/tests/run-make/proc-macro-dep-source-changes-crate-hash/v2.rs new file mode 100644 index 0000000000000..c739934013967 --- /dev/null +++ b/tests/run-make/proc-macro-dep-source-changes-crate-hash/v2.rs @@ -0,0 +1,13 @@ +// Second version of the proc-macro. Source has changed: it now emits +// `pub const ANSWER: u32 = 2;`. Crate name and exported macro name match v1. + +#![crate_type = "proc-macro"] + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro_derive(ChangingDerive)] +pub fn changing_derive(_input: TokenStream) -> TokenStream { + "pub const ANSWER: u32 = 2;".parse().unwrap() +} diff --git a/tests/run-make/proc-macro-env-changes-crate-hash/changing_macro.rs b/tests/run-make/proc-macro-env-changes-crate-hash/changing_macro.rs new file mode 100644 index 0000000000000..53c6e17bafad2 --- /dev/null +++ b/tests/run-make/proc-macro-env-changes-crate-hash/changing_macro.rs @@ -0,0 +1,15 @@ +// A proc-macro whose output depends on the value of `PROC_MACRO_DEP_TOKEN` +// at the time the *consumer* crate is compiled. The source of this crate is +// stable across the test; only the env var differs between runs. + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn emit_token(_input: TokenStream) -> TokenStream { + let value = std::env::var("PROC_MACRO_DEP_TOKEN").unwrap(); + // Emit a constant whose value embeds the env var, so the tokens the + // consumer ends up with depend on the env var. + format!("pub const TOKEN: &str = {value:?};").parse().unwrap() +} diff --git a/tests/run-make/proc-macro-env-changes-crate-hash/foo.rs b/tests/run-make/proc-macro-env-changes-crate-hash/foo.rs new file mode 100644 index 0000000000000..04279a659397e --- /dev/null +++ b/tests/run-make/proc-macro-env-changes-crate-hash/foo.rs @@ -0,0 +1,9 @@ +#![crate_type = "rlib"] + +extern crate changing_macro; + +changing_macro::emit_token!(); + +pub fn get() -> &'static str { + TOKEN +} diff --git a/tests/run-make/proc-macro-env-changes-crate-hash/rmake.rs b/tests/run-make/proc-macro-env-changes-crate-hash/rmake.rs new file mode 100644 index 0000000000000..7893177a2fb11 --- /dev/null +++ b/tests/run-make/proc-macro-env-changes-crate-hash/rmake.rs @@ -0,0 +1,56 @@ +// Verifies that when a proc-macro's *output* changes without its source +// changing — here, because the proc-macro reads an environment variable at +// expansion time and we vary that variable between consumer builds — the +// consumer crate's crate_hash / SVH changes. +// +// Companion to `proc-macro-dep-source-changes-crate-hash`: that test covers +// the case where the proc-macro source (and therefore its compiled metadata) +// changes; this test covers the case where only the tokens produced during +// expansion change. Both must invalidate the consumer's crate_hash. +// +// Note: the env var is read at consumer-compile time (when the proc-macro +// runs), so we set it on the `rustc` invocation that builds `foo.rs`, not on +// the one that builds the proc-macro itself. +// See https://github.com/rust-lang/rust/issues/94878 and PR #154724. + +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + +use run_make_support::{diff, rfs, rustc}; + +const ENV_VAR: &str = "PROC_MACRO_DEP_TOKEN"; + +fn build_in(dir: &str, value: &str) -> String { + // The proc-macro is built once per build, but its source is identical; + // what differs is the value of ENV_VAR seen during expansion in the + // consumer build. + rustc() + .input("changing_macro.rs") + .crate_name("changing_macro") + .crate_type("proc-macro") + .out_dir(dir) + .run(); + rustc().input("foo.rs").library_search_path(dir).out_dir(dir).env(ENV_VAR, value).run(); + rustc().arg("-Zls=root").input(format!("{dir}/libfoo.rlib")).run().stdout_utf8() +} + +fn main() { + rfs::create_dir("a"); + rfs::create_dir("b"); + rfs::create_dir("a_again"); + + // Build the consumer twice with the same proc-macro source but different + // values of ENV_VAR. foo.rs is byte-identical; only the tokens spliced in + // by the derive differ. + let a = build_in("a", "first"); + let b = build_in("b", "second"); + // The SVH (printed by `-Zls=root`) must differ between the two builds. + diff().expected_text("a", &a).actual_text("b", b).run_fail(); + + // Sanity: rebuilding with the original env value reproduces the original + // dump, so the difference above is genuinely caused by the env change and + // not by non-determinism in metadata encoding. + let a_again = build_in("a_again", "first"); + diff().expected_text("a", &a).actual_text("a_again", a_again).run(); +} diff --git a/tests/run-make/proc-macro-global-asm-changes-crate-hash/changing_macro.rs b/tests/run-make/proc-macro-global-asm-changes-crate-hash/changing_macro.rs new file mode 100644 index 0000000000000..7949ffb7d189d --- /dev/null +++ b/tests/run-make/proc-macro-global-asm-changes-crate-hash/changing_macro.rs @@ -0,0 +1,18 @@ +// A proc-macro that emits a `core::arch::global_asm!` block whose template +// depends on `PROC_MACRO_ASM_TOKEN`, read at expansion time. The source of +// this crate is stable across the test; only the env var differs between +// runs, so the only thing that changes in the consumer is the asm template +// spliced in by the macro. +// +// The body is a pure assembler comment, so it assembles to nothing on every +// target we test on. + +extern crate proc_macro; + +use proc_macro::TokenStream; + +#[proc_macro] +pub fn emit_global_asm(_input: TokenStream) -> TokenStream { + let value = std::env::var("PROC_MACRO_ASM_TOKEN").unwrap(); + format!(r##"core::arch::global_asm!("# {}");"##, value).parse().unwrap() +} diff --git a/tests/run-make/proc-macro-global-asm-changes-crate-hash/foo.rs b/tests/run-make/proc-macro-global-asm-changes-crate-hash/foo.rs new file mode 100644 index 0000000000000..f2c6a4905e182 --- /dev/null +++ b/tests/run-make/proc-macro-global-asm-changes-crate-hash/foo.rs @@ -0,0 +1,9 @@ +// Consumer crate. Byte-identical across all invocations of the test; +// only the asm template inside the `global_asm!` block spliced in by +// `changing_macro::emit_global_asm!` differs between builds. + +#![crate_type = "rlib"] + +extern crate changing_macro; + +changing_macro::emit_global_asm!(); diff --git a/tests/run-make/proc-macro-global-asm-changes-crate-hash/rmake.rs b/tests/run-make/proc-macro-global-asm-changes-crate-hash/rmake.rs new file mode 100644 index 0000000000000..d8d2a5a803c6a --- /dev/null +++ b/tests/run-make/proc-macro-global-asm-changes-crate-hash/rmake.rs @@ -0,0 +1,64 @@ +// Verifies that when a proc-macro emits a `global_asm!` block whose template +// changes between builds (here driven by an env var read at expansion time), +// the consumer crate's crate_hash / SVH changes. +// +// This exercises an item kind (`DefKind::GlobalAsm`) whose body lives only +// in HIR and is *not* recorded in any way by the metadata encoder: +// `should_encode_span`, `should_encode_attrs`, `should_encode_visibility`, +// `should_encode_generics`, `should_encode_type` and `should_encode_mir` are +// all false for `GlobalAsm`, and `def_kind.has_codegen_attrs()` is false too +// (see `compiler/rustc_metadata/src/rmeta/encoder.rs`). All that ends up in +// the rmeta byte stream for a `global_asm!` invocation is the fixed-size +// `DefKind::GlobalAsm` enum discriminant in the def_kind table, which is +// identical regardless of the asm template's contents. The asm template +// itself is only read out of HIR later by `MonoItem::GlobalAsm` codegen in +// `rustc_monomorphize::collector`. +// +// Companion to `proc-macro-dep-source-changes-crate-hash` and +// `proc-macro-env-changes-crate-hash`. +// See https://github.com/rust-lang/rust/issues/94878 and PR #154724. + +//@ ignore-cross-compile +//@ needs-crate-type: proc-macro +//@ ignore-musl (FIXME: can't find `-lunwind`) + +use run_make_support::{diff, rfs, rustc}; + +const ENV_VAR: &str = "PROC_MACRO_ASM_TOKEN"; + +fn build_in(dir: &str, value: &str) -> String { + // The proc-macro is built once per build, but its source is identical; + // what differs is the value of ENV_VAR seen during expansion in the + // consumer build. + rustc() + .input("changing_macro.rs") + .crate_name("changing_macro") + .crate_type("proc-macro") + .out_dir(dir) + .run(); + rustc().input("foo.rs").library_search_path(dir).out_dir(dir).env(ENV_VAR, value).run(); + rustc().arg("-Zls=root").input(format!("{dir}/libfoo.rlib")).run().stdout_utf8() +} + +fn main() { + rfs::create_dir("a"); + rfs::create_dir("b"); + rfs::create_dir("a_again"); + + // Build the consumer twice with the same proc-macro source but different + // values of ENV_VAR. foo.rs is byte-identical; only the asm template + // spliced in by `emit_global_asm!` differs. + let a = build_in("a", "first"); + let b = build_in("b", "second"); + // The SVH (printed by `-Zls=root`) must differ between the two builds. + // Under PR #154724 without an HIR-hash contribution, the rmeta encoder + // writes no bytes that depend on the asm template, so the two SVHs are + // identical and this `run_fail` fails (the dumps match). + diff().expected_text("a", &a).actual_text("b", b).run_fail(); + + // Sanity: rebuilding with the original env value reproduces the original + // dump, so the difference above is genuinely caused by the env change + // and not by non-determinism in metadata encoding. + let a_again = build_in("a_again", "first"); + diff().expected_text("a", &a).actual_text("a_again", a_again).run(); +} From 79ee8dc08073a0abf93d2b494ac5c1be11d4342e Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Thu, 2 Jul 2026 14:59:41 -0400 Subject: [PATCH 0858/1309] Hash metadata with XXH3-128 instead of SipHash-128 for the crate SVH MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The SVH is computed by hashing the entire encoded metadata blob, and SipHash-128 (~2.5 Ir/byte) dominated the cost — it accounted for the whole of the measured regression on metadata-heavy crates. Switch the byte pass to XXH3-128, which is ~10x cheaper per byte on its runtime-detected AVX2 path. XXH3 is non-cryptographic, which is fine here: the SVH is only a change detector, must be reproducible (so it is never keyed secretly, meaning even the previous SipHash use was not collision-resistant), and compiling a crate already executes its build scripts and proc-macros, so the crate author is trusted regardless. The untracked supplements (dep-tracking hash and the HIR hash for e.g. DefKind::GlobalAsm) are still folded in via a StableHasher fingerprint, so coverage is unchanged. twox-hash 2.x is already in the dependency graph via ruzstd; this only adds a direct edge (xxhash3_128 + std features for the runtime SIMD dispatch). --- Cargo.lock | 1 + compiler/rustc_metadata/Cargo.toml | 1 + compiler/rustc_metadata/src/rmeta/encoder.rs | 34 +++++++++++++------- 3 files changed, 24 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 99c2914ff343d..b5fb5057716ac 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4428,6 +4428,7 @@ dependencies = [ "rustc_target", "tempfile", "tracing", + "twox-hash 2.1.2", ] [[package]] diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index e036c2d7e23c9..900dad3be1d35 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -34,6 +34,7 @@ rustc_structures = { path = "../rustc_structures" } rustc_target = { path = "../rustc_target" } tempfile = "3.7.1" tracing = "0.1" +twox-hash = { version = "2", default-features = false, features = ["xxhash3_128", "std"] } # tidy-alphabetical-end [target.'cfg(target_os = "aix")'.dependencies] diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index f9343cb35f174..afa5646bea80e 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -2,7 +2,6 @@ use std::borrow::Borrow; use std::cell::RefCell; use std::collections::hash_map::Entry; use std::fs::File; -use std::hash::Hasher; use std::io::{Read, Seek, SeekFrom, Write}; use std::ops::Deref; use std::path::{Path, PathBuf}; @@ -44,6 +43,7 @@ use rustc_span::{ }; use rustc_structures::CrateType; use tracing::{debug, instrument, trace}; +use twox_hash::XxHash3_128; use crate::diagnostics::{FailCreateFileEncoder, FailWriteFile}; use crate::eii::EiiMapEncodedKeyValue; @@ -51,7 +51,7 @@ use crate::rmeta::*; pub(super) struct EncodeContext<'a, 'tcx> { opaque: FileEncoder<'a>, - metadata_hasher: Arc>, + metadata_hasher: Arc>, tcx: TyCtxt<'tcx>, feat: &'tcx rustc_feature::Features, tables: TableBuilders, @@ -802,7 +802,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // `crate_hash` query computes directly without consulting `local_crate_hash`. let hash = if tcx.sess.opts.unstable_opts.metadata_crate_hash { self.opaque.flush(); - Svh::new(self.metadata_hasher.lock().unwrap().clone().finish()) + Svh::new(Fingerprint::from_le_bytes( + self.metadata_hasher.lock().unwrap().finish_128().to_le_bytes(), + )) } else { tcx.crate_hash(LOCAL_CRATE) }; @@ -2625,22 +2627,30 @@ fn with_encode_metadata_header( // Under `-Z metadata-crate-hash=no` the SVH comes from the legacy `crate_hash` query instead and // this hasher is never consulted, so we skip seeding it and feeding metadata bytes into it. let metadata_crate_hash = tcx.sess.opts.unstable_opts.metadata_crate_hash; - let stable_hasher = Arc::new(Mutex::new(StableHasher::new())); + // The SVH is an XXH3-128 digest of the encoded metadata bytes. XXH3 is a fast, non-cryptographic + // hash; that is sufficient here because the SVH is only a change detector, is never keyed + // secretly (it must be reproducible), and compiling a crate already runs its build scripts and + // proc-macros, so the crate author is trusted regardless. + let metadata_hasher = Arc::new(Mutex::new(XxHash3_128::new())); if metadata_crate_hash { + // Fold in inputs that are not part of the encoded metadata bytes, reduced to a single + // fingerprint via the stable hasher and then mixed into the byte digest. let hir_body_hash = compute_hir_hash(tcx); - tcx.with_stable_hashing_context(|mut hcx| { - let mut hasher = stable_hasher.lock().unwrap(); + let supplement: Fingerprint = tcx.with_stable_hashing_context(|mut hcx| { + let mut hasher = StableHasher::new(); // Add dep_tracking_hash to ensure the SVH changes when any tracked flag changes. - tcx.sess.opts.dep_tracking_hash(true).stable_hash(&mut hcx, &mut *hasher); + tcx.sess.opts.dep_tracking_hash(true).stable_hash(&mut hcx, &mut hasher); // Add HIR hash for untracked elements, e.g. DefKind::GlobalAsm. - hir_body_hash.stable_hash(&mut hcx, &mut *hasher); + hir_body_hash.stable_hash(&mut hcx, &mut hasher); + hasher.finish() }); + metadata_hasher.lock().unwrap().write(&supplement.to_le_bytes()); } - // Feed every flushed byte into `stable_hasher` so the SVH covers the entire encoded metadata. + // Feed every flushed byte into `metadata_hasher` so the SVH covers the entire encoded metadata. let mut flush_strategy = { - let stable_hasher = Arc::clone(&stable_hasher); - move |bytes: &[u8]| stable_hasher.lock().unwrap().write(bytes) + let metadata_hasher = Arc::clone(&metadata_hasher); + move |bytes: &[u8]| metadata_hasher.lock().unwrap().write(bytes) }; let mut encoder = if metadata_crate_hash { @@ -2667,7 +2677,7 @@ fn with_encode_metadata_header( let mut ecx = EncodeContext { opaque: encoder, - metadata_hasher: Arc::clone(&stable_hasher), + metadata_hasher: Arc::clone(&metadata_hasher), tcx, feat: tcx.features(), tables: Default::default(), From d432494d3808d6002c1afe0130d2fe89b2a447fb Mon Sep 17 00:00:00 2001 From: Jake Drew <25826535+jakedrew@users.noreply.github.com> Date: Fri, 25 Sep 2026 21:32:57 +0200 Subject: [PATCH 0859/1309] Comment that `dying_next` is too costly to inline --- library/alloc/src/collections/btree/map.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/library/alloc/src/collections/btree/map.rs b/library/alloc/src/collections/btree/map.rs index fc194639c5468..a05345fe45508 100644 --- a/library/alloc/src/collections/btree/map.rs +++ b/library/alloc/src/collections/btree/map.rs @@ -205,6 +205,8 @@ pub struct BTreeMap< #[stable(feature = "btree_drop", since = "1.7.0")] unsafe impl<#[may_dangle] K, #[may_dangle] V, A: AllocatorClone> Drop for BTreeMap { fn drop(&mut self) { + // Skip `into_iter` for an empty map: `dying_next` is too costly to inline, so the + // empty drop isn't optimised away (see #161375). if self.root.is_some() { // SAFETY: `self` is not used after this and none of its fields are dropped again: // `alloc` is `ManuallyDrop` and `root` has no drop glue. From d29d9059f933a1a0c604699457654573aaa7da83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 25 Sep 2026 19:44:08 +0200 Subject: [PATCH 0860/1309] use `inner` for the `RegionInferenceContextInner` fields --- .../src/region_infer/region_context.rs | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index af0f48526b4fe..3e13ae1b032a5 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -83,21 +83,21 @@ pub struct RegionInferenceContextInner<'tcx> { /// This contains data around region constraints and liveness, up to and after solving. /// All data is immutable. pub struct RegionInferenceContext<'tcx> { - data: Frozen>, + inner: Frozen>, } impl<'tcx> Deref for RegionInferenceContext<'tcx> { type Target = RegionInferenceContextInner<'tcx>; fn deref(&self) -> &Self::Target { - &self.data + &self.inner } } /// This contains data around region constraints and liveness, up to solving. /// Calling `solve` returns a new immutable `RegionInferenceContext`. pub(crate) struct UnsolvedRegionInferenceContext<'tcx> { - pub(super) data: RegionInferenceContextInner<'tcx>, + pub(super) inner: RegionInferenceContextInner<'tcx>, /// Type constraints that we check after solving. pub(super) type_tests: Vec>, @@ -107,13 +107,13 @@ impl<'tcx> Deref for UnsolvedRegionInferenceContext<'tcx> { type Target = RegionInferenceContextInner<'tcx>; fn deref(&self) -> &Self::Target { - &self.data + &self.inner } } impl<'tcx> DerefMut for UnsolvedRegionInferenceContext<'tcx> { fn deref_mut(&mut self) -> &mut Self::Target { - &mut self.data + &mut self.inner } } @@ -774,7 +774,7 @@ impl<'tcx> UnsolvedRegionInferenceContext<'tcx> { } Self { - data: RegionInferenceContextInner { + inner: RegionInferenceContextInner { definitions, liveness_constraints, constraints: outlives_constraints, @@ -838,11 +838,11 @@ impl<'tcx> UnsolvedRegionInferenceContext<'tcx> { let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); if propagated_outlives_requirements.is_empty() { - (RegionInferenceContext { data: Frozen::freeze(self.data) }, None, errors_buffer) + (RegionInferenceContext { inner: Frozen::freeze(self.inner) }, None, errors_buffer) } else { let num_external_vids = self.universal_regions().num_global_and_external_regions(); ( - RegionInferenceContext { data: Frozen::freeze(self.data) }, + RegionInferenceContext { inner: Frozen::freeze(self.inner) }, Some(ClosureRegionRequirements { num_external_vids, outlives_requirements: propagated_outlives_requirements, @@ -874,9 +874,9 @@ impl<'tcx> UnsolvedRegionInferenceContext<'tcx> { // dependency order. I.e. a chain A: B: C will visit C, B, A. for scc_a in self.constraint_sccs.all_sccs() { // Walk each SCC `B` such that `A: B`... - for &scc_b in self.data.constraint_sccs.successors(scc_a) { + for &scc_b in self.inner.constraint_sccs.successors(scc_a) { debug!(?scc_b); - self.data.scc_values.add_region(scc_a, scc_b); + self.inner.scc_values.add_region(scc_a, scc_b); } } } From dd39de778bdad176ffc6ee037921fe593aea3030 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 25 Sep 2026 19:48:26 +0200 Subject: [PATCH 0861/1309] reduce field visibility --- compiler/rustc_borrowck/src/region_infer/dump_mir.rs | 2 +- .../src/region_infer/region_context.rs | 12 ++++++------ 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs index 68f822aac403a..72e16b4b86dfc 100644 --- a/compiler/rustc_borrowck/src/region_infer/dump_mir.rs +++ b/compiler/rustc_borrowck/src/region_infer/dump_mir.rs @@ -68,7 +68,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { with_msg: &mut dyn FnMut(&str) -> io::Result<()>, ) -> io::Result<()> { for region in self.definitions.indices() { - let value = self.liveness_constraints.pretty_print_live_points(region); + let value = self.liveness_constraints().pretty_print_live_points(region); if value != "{}" { with_msg(&format!("{region:?} live at {value}"))?; } diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index 3e13ae1b032a5..fb1f2a1ff106a 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -50,7 +50,7 @@ pub struct RegionInferenceContextInner<'tcx> { /// regions, these start out empty and steadily grow, though for /// each universally quantified region R they start out containing /// the entire CFG and `end(R)`. - pub(super) liveness_constraints: LivenessValues, + liveness_constraints: LivenessValues, /// The outlives constraints computed by the type-check. pub(super) constraints: Frozen>, @@ -58,17 +58,17 @@ pub struct RegionInferenceContextInner<'tcx> { /// The constraint-set, but in graph form, making it easy to traverse /// the constraints adjacent to a particular region. Used to construct /// the SCC (see `constraint_sccs`) and for error reporting. - pub(super) constraint_graph: Frozen, + constraint_graph: Frozen, /// The SCC computed from `constraints` and the constraint /// graph. We have an edge from SCC A to SCC B if `A: B`. Used to /// compute the values of each region. pub(super) constraint_sccs: ConstraintSccs, - pub(super) scc_annotations: IndexVec, + scc_annotations: IndexVec, /// Map universe indexes to information on why we created it. - pub(super) universe_causes: FxIndexMap>, + universe_causes: FxIndexMap>, /// The final inferred values of the region variables; we compute /// one value per SCC. To get the value for any given *region*, @@ -97,10 +97,10 @@ impl<'tcx> Deref for RegionInferenceContext<'tcx> { /// This contains data around region constraints and liveness, up to solving. /// Calling `solve` returns a new immutable `RegionInferenceContext`. pub(crate) struct UnsolvedRegionInferenceContext<'tcx> { - pub(super) inner: RegionInferenceContextInner<'tcx>, + inner: RegionInferenceContextInner<'tcx>, /// Type constraints that we check after solving. - pub(super) type_tests: Vec>, + type_tests: Vec>, } impl<'tcx> Deref for UnsolvedRegionInferenceContext<'tcx> { From 14cd34f24f2937780d2db142e7b054c6df92e546 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 25 Sep 2026 20:32:00 +0200 Subject: [PATCH 0862/1309] move functions that panic on the unsolved regioncx --- .../src/region_infer/region_context.rs | 42 +++++++++---------- 1 file changed, 20 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index fb1f2a1ff106a..c12330ce2ad82 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -94,6 +94,26 @@ impl<'tcx> Deref for RegionInferenceContext<'tcx> { } } +impl RegionInferenceContext<'_> { + /// Returns `true` if the region `r` contains the point `p`. + pub(crate) fn region_contains_point(&self, r: RegionVid, p: Location) -> bool { + let scc = self.constraint_sccs.scc(r); + self.scc_values.contains_point(scc, p) + } + + /// Returns the lowest statement index in `start..=end` which is not contained by `r`. + pub(crate) fn first_non_contained_inclusive( + &self, + r: RegionVid, + block: BasicBlock, + start: usize, + end: usize, + ) -> Option { + let scc = self.constraint_sccs.scc(r); + self.scc_values.first_non_contained_inclusive(scc, block, start, end) + } +} + /// This contains data around region constraints and liveness, up to solving. /// Calling `solve` returns a new immutable `RegionInferenceContext`. pub(crate) struct UnsolvedRegionInferenceContext<'tcx> { @@ -143,28 +163,6 @@ impl<'tcx> RegionInferenceContextInner<'tcx> { self.universal_regions().annotate(tcx, err) } - /// Returns `true` if the region `r` contains the point `p`. - /// - /// Panics if called before `solve()` executes, - pub(crate) fn region_contains_point(&self, r: RegionVid, p: Location) -> bool { - let scc = self.constraint_sccs.scc(r); - self.scc_values.contains_point(scc, p) - } - - /// Returns the lowest statement index in `start..=end` which is not contained by `r`. - /// - /// Panics if called before `solve()` executes. - pub(crate) fn first_non_contained_inclusive( - &self, - r: RegionVid, - block: BasicBlock, - start: usize, - end: usize, - ) -> Option { - let scc = self.constraint_sccs.scc(r); - self.scc_values.first_non_contained_inclusive(scc, block, start, end) - } - /// Returns access to the value of `r` for debugging purposes. pub(crate) fn region_value_str(&self, r: RegionVid) -> String { let scc = self.constraint_sccs.scc(r); From 005e44466e2d4549c556421e62e411fbca68242a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 25 Sep 2026 21:12:17 +0200 Subject: [PATCH 0863/1309] make unique entry point to regioncx creation we previously always created an unsolved regioncx to immediately solve it, but can create the solved regioncx in a single step. this is done by merging `UnsolvedRegionInferenceContext`'s `new` and `solve` into one constructor. --- compiler/rustc_borrowck/src/nll.rs | 16 +- .../src/region_infer/region_context.rs | 310 +++++++++--------- 2 files changed, 165 insertions(+), 161 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 31fa9dd2ee64e..dd751c5b074b6 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -26,7 +26,7 @@ use crate::polonius::PoloniusContext; use crate::polonius::legacy::{ PoloniusFacts, PoloniusFactsExt, PoloniusLocationTable, PoloniusOutput, }; -use crate::region_infer::{RegionInferenceContext, UnsolvedRegionInferenceContext}; +use crate::region_infer::RegionInferenceContext; use crate::type_check::MirTypeckRegionConstraints; use crate::type_check::free_region_relations::UniversalRegionRelations; use crate::universal_regions::UniversalRegions; @@ -96,14 +96,15 @@ pub(crate) fn compute_closure_requirements_modulo_opaques<'tcx>( &universal_region_relations, infcx, ); - let regioncx = UnsolvedRegionInferenceContext::new( + let (_, closure_region_requirements, _nll_errors) = RegionInferenceContext::solve( &infcx, lowered_constraints, universal_region_relations.clone(), location_map, + body, + None, ); - let (_, closure_region_requirements, _nll_errors) = regioncx.solve(infcx, body, None); closure_region_requirements } @@ -182,17 +183,16 @@ pub(crate) fn compute_regions<'tcx>( } }); - let regioncx = UnsolvedRegionInferenceContext::new( + // Solve the region constraints. + let (regioncx, closure_region_requirements, nll_errors) = RegionInferenceContext::solve( infcx, lowered_constraints, universal_region_relations, location_map, + body, + polonius_output.clone(), ); - // Solve the region constraints. - let (regioncx, closure_region_requirements, nll_errors) = - regioncx.solve(infcx, body, polonius_output.clone()); - NllOutput { regioncx, polonius_input: polonius_facts.map(Box::new), diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index c12330ce2ad82..20b6616073f57 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -94,7 +94,163 @@ impl<'tcx> Deref for RegionInferenceContext<'tcx> { } } -impl RegionInferenceContext<'_> { +impl<'tcx> RegionInferenceContext<'tcx> { + /// Performs region inference and report errors if we see any + /// unsatisfiable constraints. If this is a closure, returns the + /// region requirements to propagate to our creator, if any. + #[instrument( + skip(infcx, lowered_constraints, location_map, body, polonius_output), + level = "debug" + )] + pub(crate) fn solve( + infcx: &BorrowckInferCtxt<'tcx>, + lowered_constraints: LoweredConstraints<'tcx>, + universal_region_relations: Frozen>, + location_map: Rc, + body: &Body<'tcx>, + polonius_output: Option>, + ) -> (RegionInferenceContext<'tcx>, Option>, RegionErrors<'tcx>) + { + // 1. We first prepare the data needed for the `UnsolvedRegionInferenceContext` to do the + // solving work. + let universal_regions = &universal_region_relations.universal_regions; + + let LoweredConstraints { + constraint_sccs, + definitions, + outlives_constraints, + scc_annotations, + type_tests, + liveness_constraints, + universe_causes, + placeholder_indices, + } = lowered_constraints; + + debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); + debug!("outlives constraints: {:#?}", outlives_constraints); + debug!("placeholder_indices: {:#?}", placeholder_indices); + debug!("type tests: {:#?}", type_tests); + + let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); + + if cfg!(debug_assertions) { + sccs_info(infcx, &constraint_sccs); + } + + let mut scc_values = + RegionValues::new(location_map, universal_regions.len(), placeholder_indices); + + // Initializes the region variables with their initial live points. + for (region, definition) in definitions.iter_enumerated() { + let scc = constraint_sccs.scc(region); + + // For each universally quantified region (lifetime parameter). The + // first N variables always correspond to the regions appearing in the + // function signature (both named and anonymous) and in where-clauses. + match definition.origin { + // For each free, universally quantified region X: + NllRegionVariableOrigin::FreeRegion => { + // Add `end(X)` into the set for X. + scc_values.add_free_region(scc, region); + } + + NllRegionVariableOrigin::Placeholder(placeholder) => { + scc_values.add_placeholder(scc, placeholder); + } + + NllRegionVariableOrigin::Existential { .. } => { + // For existential, regions, nothing to do. + } + } + + // Initially copy the liveness constraints of any region that + // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. + // + // These values will later be propagated during + // [`UnsolvedRegionInferenceContext::propagate_constraints()`]. + // The values include any live-at-all-points constraints added previously in `liveness::generate`. + if let Some(liveness) = liveness_constraints.point_liveness(region) { + scc_values.merge_liveness(scc, liveness) + } + } + + let mut unsolved_regioncx = UnsolvedRegionInferenceContext { + inner: RegionInferenceContextInner { + definitions, + liveness_constraints, + constraints: outlives_constraints, + constraint_graph, + constraint_sccs, + scc_annotations, + universe_causes, + universal_region_relations, + scc_values, + }, + type_tests, + }; + + // 2. And now we can do the actual solving, the region inference. + let mir_def_id = body.source.def_id(); + unsolved_regioncx.propagate_constraints(); + + let mut errors_buffer = RegionErrors::new(infcx.tcx); + + // If this is a nested body, we propagate unsatisfied + // outlives constraints to the parent body instead of + // eagerly erroing. + let mut propagated_outlives_requirements = + infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); + + unsolved_regioncx.check_type_tests( + infcx, + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); + + debug!(?errors_buffer); + debug!(?propagated_outlives_requirements); + + // In Polonius mode, the errors about missing universal region relations are in the output + // and need to be emitted or propagated. Otherwise, we need to check whether the + // constraints were too strong, and if so, emit or propagate those errors. + if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { + unsolved_regioncx.check_polonius_subset_errors( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + polonius_output + .as_ref() + .expect("Polonius output is unavailable despite `-Z polonius`"), + ); + } else { + unsolved_regioncx.check_universal_regions( + propagated_outlives_requirements.as_mut(), + &mut errors_buffer, + ); + } + + debug!(?errors_buffer); + + let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); + if propagated_outlives_requirements.is_empty() { + ( + RegionInferenceContext { inner: Frozen::freeze(unsolved_regioncx.inner) }, + None, + errors_buffer, + ) + } else { + let num_external_vids = + unsolved_regioncx.universal_regions().num_global_and_external_regions(); + ( + RegionInferenceContext { inner: Frozen::freeze(unsolved_regioncx.inner) }, + Some(ClosureRegionRequirements { + num_external_vids, + outlives_requirements: propagated_outlives_requirements, + }), + errors_buffer, + ) + } + } + /// Returns `true` if the region `r` contains the point `p`. pub(crate) fn region_contains_point(&self, r: RegionVid, p: Location) -> bool { let scc = self.constraint_sccs.scc(r); @@ -698,158 +854,6 @@ impl<'tcx> RegionInferenceContextInner<'tcx> { } impl<'tcx> UnsolvedRegionInferenceContext<'tcx> { - /// Creates a new region inference context with a total of - /// `num_region_variables` valid inference variables; the first N - /// of those will be constant regions representing the free - /// regions defined in `universal_regions`. - /// - /// The `outlives_constraints` and `type_tests` are an initial set - /// of constraints produced by the MIR type check. - pub(crate) fn new( - infcx: &BorrowckInferCtxt<'tcx>, - lowered_constraints: LoweredConstraints<'tcx>, - universal_region_relations: Frozen>, - location_map: Rc, - ) -> Self { - let universal_regions = &universal_region_relations.universal_regions; - - let LoweredConstraints { - constraint_sccs, - definitions, - outlives_constraints, - scc_annotations, - type_tests, - liveness_constraints, - universe_causes, - placeholder_indices, - } = lowered_constraints; - - debug!("universal_regions: {:#?}", universal_region_relations.universal_regions); - debug!("outlives constraints: {:#?}", outlives_constraints); - debug!("placeholder_indices: {:#?}", placeholder_indices); - debug!("type tests: {:#?}", type_tests); - - let constraint_graph = Frozen::freeze(outlives_constraints.graph(definitions.len())); - - if cfg!(debug_assertions) { - sccs_info(infcx, &constraint_sccs); - } - - let mut scc_values = - RegionValues::new(location_map, universal_regions.len(), placeholder_indices); - - // Initializes the region variables with their initial live points. - for (region, definition) in definitions.iter_enumerated() { - let scc = constraint_sccs.scc(region); - - // For each universally quantified region (lifetime parameter). The - // first N variables always correspond to the regions appearing in the - // function signature (both named and anonymous) and in where-clauses. - match definition.origin { - // For each free, universally quantified region X: - NllRegionVariableOrigin::FreeRegion => { - // Add `end(X)` into the set for X. - scc_values.add_free_region(scc, region); - } - - NllRegionVariableOrigin::Placeholder(placeholder) => { - scc_values.add_placeholder(scc, placeholder); - } - - NllRegionVariableOrigin::Existential { .. } => { - // For existential, regions, nothing to do. - } - } - - // Initially copy the liveness constraints of any region that - // has them, setting `scc_values[scc(region)] |= liveness_constraints[region]`. - // - // These values will later be propagated during [`Self::propagate_constraints()`]. - // The values include any live-at-all-points constraints added previously in `liveness::generate`. - if let Some(liveness) = liveness_constraints.point_liveness(region) { - scc_values.merge_liveness(scc, liveness) - } - } - - Self { - inner: RegionInferenceContextInner { - definitions, - liveness_constraints, - constraints: outlives_constraints, - constraint_graph, - constraint_sccs, - scc_annotations, - universe_causes, - universal_region_relations, - scc_values, - }, - type_tests, - } - } - - /// Performs region inference and report errors if we see any - /// unsatisfiable constraints. If this is a closure, returns the - /// region requirements to propagate to our creator, if any. - #[instrument(skip(self, infcx, body, polonius_output), level = "debug")] - pub(crate) fn solve( - mut self, - infcx: &InferCtxt<'tcx>, - body: &Body<'tcx>, - polonius_output: Option>, - ) -> (RegionInferenceContext<'tcx>, Option>, RegionErrors<'tcx>) - { - let mir_def_id = body.source.def_id(); - self.propagate_constraints(); - - let mut errors_buffer = RegionErrors::new(infcx.tcx); - - // If this is a nested body, we propagate unsatisfied - // outlives constraints to the parent body instead of - // eagerly erroing. - let mut propagated_outlives_requirements = - infcx.tcx.is_typeck_child(mir_def_id).then(Vec::new); - - self.check_type_tests(infcx, propagated_outlives_requirements.as_mut(), &mut errors_buffer); - - debug!(?errors_buffer); - debug!(?propagated_outlives_requirements); - - // In Polonius mode, the errors about missing universal region relations are in the output - // and need to be emitted or propagated. Otherwise, we need to check whether the - // constraints were too strong, and if so, emit or propagate those errors. - if infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled() { - self.check_polonius_subset_errors( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - polonius_output - .as_ref() - .expect("Polonius output is unavailable despite `-Z polonius`"), - ); - } else { - self.check_universal_regions( - propagated_outlives_requirements.as_mut(), - &mut errors_buffer, - ); - } - - debug!(?errors_buffer); - - let propagated_outlives_requirements = propagated_outlives_requirements.unwrap_or_default(); - if propagated_outlives_requirements.is_empty() { - (RegionInferenceContext { inner: Frozen::freeze(self.inner) }, None, errors_buffer) - } else { - let num_external_vids = self.universal_regions().num_global_and_external_regions(); - ( - RegionInferenceContext { inner: Frozen::freeze(self.inner) }, - Some(ClosureRegionRequirements { - num_external_vids, - outlives_requirements: propagated_outlives_requirements, - }), - errors_buffer, - ) - } - } - /// Propagate the region constraints: this will grow the values /// for each region variable until all the constraints are /// satisfied. Note that some values may grow **too** large to be From 29c3e371d1e0e08515f1643061bfd7c848b398ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Fri, 25 Sep 2026 22:22:20 +0200 Subject: [PATCH 0864/1309] update comment and visibility --- compiler/rustc_borrowck/src/region_infer/region_context.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index 20b6616073f57..f5b49083da835 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -271,8 +271,7 @@ impl<'tcx> RegionInferenceContext<'tcx> { } /// This contains data around region constraints and liveness, up to solving. -/// Calling `solve` returns a new immutable `RegionInferenceContext`. -pub(crate) struct UnsolvedRegionInferenceContext<'tcx> { +struct UnsolvedRegionInferenceContext<'tcx> { inner: RegionInferenceContextInner<'tcx>, /// Type constraints that we check after solving. From 49276b0ec28e161e7f2aa86bfb345f8bf0ed9493 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 6 Aug 2026 16:59:59 +0000 Subject: [PATCH 0865/1309] Detect bad number of generics caused by bad derive When a derive macro expands the annotated item's name directly using `quote!`, it keep the item's Span context (instead of having a new context). This means that the generic Span context machinery which provides feedback that an error happened due to a derive doesn't kick in. If a derive macro isn't written to take into account the existence of type parameters, an error for "mismatched number of type parameters" will be emitted. We now detect the case when this happens due to the derive macro, and customize the output to point that out, as well as avoid giving suggestions that will always be wrong. --- .../wrong_number_of_generic_args.rs | 25 +++++++++++--- .../src/hir_ty_lowering/generics.rs | 2 ++ .../derives/auxiliary/derive-no-generics.rs | 34 +++++++++++++++++++ .../derive-macro-unsupported-type-params.rs | 13 +++++++ ...erive-macro-unsupported-type-params.stderr | 28 +++++++++++++++ 5 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 tests/ui/derives/auxiliary/derive-no-generics.rs create mode 100644 tests/ui/derives/derive-macro-unsupported-type-params.rs create mode 100644 tests/ui/derives/derive-macro-unsupported-type-params.stderr diff --git a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs index 6717d11d0f3de..f2b166e0b2a01 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics/wrong_number_of_generic_args.rs @@ -3,7 +3,7 @@ use rustc_errors::codes::*; use rustc_errors::{Applicability, Diag, Diagnostic, MultiSpan, pluralize}; use rustc_hir as hir; use rustc_middle::ty::{self as ty, AssocItem, AssocItems, TyCtxt}; -use rustc_span::def_id::DefId; +use rustc_span::def_id::{DefId, LocalDefId}; use tracing::debug; /// Handles the `wrong number of type / lifetime / ... arguments` family of error messages. @@ -30,6 +30,9 @@ pub(crate) struct WrongNumberOfGenericArgs<'a, 'tcx> { /// DefId of the generic type pub(crate) def_id: DefId, + + /// DefId of the type that contains the generic + pub(crate) cx_def_id: LocalDefId, } // Provides information about the kind of arguments that were provided for @@ -94,6 +97,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { params_offset: usize, gen_args: &'a hir::GenericArgs<'a>, def_id: DefId, + cx_def_id: LocalDefId, ) -> Self { let angle_brackets = if gen_args.span_ext().is_none() { if gen_args.is_empty() { AngleBrackets::Missing } else { AngleBrackets::Implied } @@ -110,6 +114,7 @@ impl<'a, 'tcx> WrongNumberOfGenericArgs<'a, 'tcx> { params_offset, gen_args, def_id, + cx_def_id, } } @@ -1163,10 +1168,20 @@ impl<'a> Diagnostic<'a> for WrongNumberOfGenericArgs<'_, '_> { err.code(E0107); err.span(self.path_segment.ident.span); - self.notify(&mut err); - self.suggest(&mut err); - self.show_definition(&mut err); - self.note_synth_provided(&mut err); + let cx_span = self.tcx.def_span(self.cx_def_id); + if cx_span.in_derive_expansion() { + // Very likely this is a botched `derive` which passes the iten name straight + // through, but doesn't support type parameters. + err.span_label( + cx_span.ctxt().outer_expn_data().call_site, + "this derive macro might not support items with generic parameters", + ); + } else { + self.notify(&mut err); + self.suggest(&mut err); + self.show_definition(&mut err); + self.note_synth_provided(&mut err); + } err } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs index 5f14b32dcabb1..9eda20fa0d9c4 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/generics.rs @@ -503,6 +503,7 @@ pub(crate) fn check_generic_arg_count( has_self as usize, gen_args, def_id, + cx.item_def_id(), )); Err(reported) @@ -617,6 +618,7 @@ pub(crate) fn check_generic_arg_count( params_offset, gen_args, def_id, + cx.item_def_id(), )) .emit_err_unless_delay(all_params_are_binded || has_invalid_bound) }); diff --git a/tests/ui/derives/auxiliary/derive-no-generics.rs b/tests/ui/derives/auxiliary/derive-no-generics.rs new file mode 100644 index 0000000000000..ea9a2e5b1c89a --- /dev/null +++ b/tests/ui/derives/auxiliary/derive-no-generics.rs @@ -0,0 +1,34 @@ +#![feature(proc_macro_quote)] + +extern crate proc_macro; + +use proc_macro::{TokenStream, TokenTree, quote}; + +#[proc_macro_derive(A)] +pub fn derive(item: TokenStream) -> TokenStream { + let mut tokens = item.into_iter(); + let _enum = tokens.next(); + let name = tokens.next().unwrap(); + let _ = tokens.next().unwrap(); + let _ = tokens.next().unwrap(); + let _ = tokens.next().unwrap(); + let TokenTree::Group(group) = tokens.next().unwrap() else { panic!() }; + let mut group = group.stream().into_iter(); + let variant = group.next().unwrap(); + let TokenTree::Group(args) = group.next().unwrap() else { panic!() }; + let arg = args.stream().into_iter().next().unwrap(); + let tokens = quote! { + trait X {} + impl X for $name {} + + impl $name { + fn foo(&self) { + if let Self :: $variant(val) = self { + let _: $arg = val; + } + } + } + + }; + tokens +} diff --git a/tests/ui/derives/derive-macro-unsupported-type-params.rs b/tests/ui/derives/derive-macro-unsupported-type-params.rs new file mode 100644 index 0000000000000..d80064b4eb094 --- /dev/null +++ b/tests/ui/derives/derive-macro-unsupported-type-params.rs @@ -0,0 +1,13 @@ +//@ proc-macro: derive-no-generics.rs +#![crate_type = "lib"] + +#[macro_use] +extern crate derive_no_generics; + +#[derive(A)] +enum A { + //~^ ERROR: missing generics for enum `A` + //~| ERROR: missing generics for enum `A` + Variant(T), + //~^ ERROR: cannot find type `T` in this scope +} diff --git a/tests/ui/derives/derive-macro-unsupported-type-params.stderr b/tests/ui/derives/derive-macro-unsupported-type-params.stderr new file mode 100644 index 0000000000000..e57490e79cc9f --- /dev/null +++ b/tests/ui/derives/derive-macro-unsupported-type-params.stderr @@ -0,0 +1,28 @@ +error[E0425]: cannot find type `T` in this scope + --> $DIR/derive-macro-unsupported-type-params.rs:11:13 + | +LL | Variant(T), + | ^ not found in this scope + +error[E0107]: missing generics for enum `A` + --> $DIR/derive-macro-unsupported-type-params.rs:8:6 + | +LL | #[derive(A)] + | - this derive macro might not support items with generic parameters +LL | enum A { + | ^ + +error[E0107]: missing generics for enum `A` + --> $DIR/derive-macro-unsupported-type-params.rs:8:6 + | +LL | #[derive(A)] + | - this derive macro might not support items with generic parameters +LL | enum A { + | ^ + | + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 3 previous errors + +Some errors have detailed explanations: E0107, E0425. +For more information about an error, try `rustc --explain E0107`. From fcf74ea7379fb7dfb943e0d2d6090f44f7a665b2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 22 Sep 2026 10:24:58 +1000 Subject: [PATCH 0866/1309] Merge `ForceWarning`/`Allow`/`Expect` into `Warning` Because they're all just special cases of warnings. This requires introducing a new `Option` field to `Warning` that describes the special case behaviour; the `DiagInner::lint_id` field also gets merged in. Specific nice things about this: - Removes some unreachable match arms for `Allow`/`Expect`. - Removes the hacky upgrading of `Allow`/`Expect` to `Warning` in `emit_future_breakage_report`. - The types now have structure that used to be maintained by comments and assertions. E.g. it's now impossible to not have a `lint_id` for an `expect` lint. (I always found the `DiagInner::lint_id` field confusing; it's clearer now.) - There's a nice comment on `EmissionOverride` summarizing all the different cases. - A little less code overall. --- compiler/rustc_builtin_macros/src/test.rs | 2 +- compiler/rustc_codegen_llvm/src/back/write.rs | 2 +- compiler/rustc_codegen_ssa/src/back/write.rs | 2 +- .../src/annotate_snippet_emitter_writer.rs | 4 +- compiler/rustc_errors/src/diagnostic.rs | 45 ++--- compiler/rustc_errors/src/json.rs | 16 +- compiler/rustc_errors/src/lib.rs | 176 +++++++++--------- .../rustc_expand/src/proc_macro_server.rs | 2 +- compiler/rustc_lint/src/context.rs | 12 +- compiler/rustc_middle/src/lint.rs | 33 ++-- compiler/rustc_passes/src/dead.rs | 8 +- src/tools/miri/src/diagnostics.rs | 2 +- src/tools/rustfmt/src/parse/session.rs | 8 +- 13 files changed, 137 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 42dbc801bfb5a..010462e5551e0 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -411,7 +411,7 @@ fn not_testable_error(cx: &ExtCtxt<'_>, is_bench: bool, attr_sp: Span, item: Opt let level = match item.map(|i| &i.kind) { // These were a warning before #92959 and need to continue being that to avoid breaking // stable user code (#94508). - Some(ast::ItemKind::MacCall(_)) => Level::Warning, + Some(ast::ItemKind::MacCall(_)) => Level::Warning(None), _ => Level::Error, }; let mut err = Diag::new(dcx, level, msg); diff --git a/compiler/rustc_codegen_llvm/src/back/write.rs b/compiler/rustc_codegen_llvm/src/back/write.rs index dd2dbdff6b82c..deaa78fcda003 100644 --- a/compiler/rustc_codegen_llvm/src/back/write.rs +++ b/compiler/rustc_codegen_llvm/src/back/write.rs @@ -418,7 +418,7 @@ fn report_inline_asm( }; let level = match level { llvm::DiagnosticLevel::Error => Level::Error, - llvm::DiagnosticLevel::Warning => Level::Warning, + llvm::DiagnosticLevel::Warning => Level::Warning(None), llvm::DiagnosticLevel::Note | llvm::DiagnosticLevel::Remark => Level::Note, }; let msg = msg.trim_prefix("error: ").to_string(); diff --git a/compiler/rustc_codegen_ssa/src/back/write.rs b/compiler/rustc_codegen_ssa/src/back/write.rs index 147e4c43c7103..093f801915dab 100644 --- a/compiler/rustc_codegen_ssa/src/back/write.rs +++ b/compiler/rustc_codegen_ssa/src/back/write.rs @@ -2060,7 +2060,7 @@ impl SharedEmitterMain { sess.dcx().abort_if_errors(); } Ok(SharedEmitterMessage::InlineAsmError(inner)) => { - assert_matches!(inner.level, Level::Error | Level::Warning | Level::Note); + assert_matches!(inner.level, Level::Error | Level::Warning(None) | Level::Note); let mut err = Diag::new(sess.dcx(), inner.level, inner.msg); if !inner.span.is_dummy() { err.span(inner.span.span()); diff --git a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs index d7e38148806f7..15a435357544d 100644 --- a/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs +++ b/compiler/rustc_errors/src/annotate_snippet_emitter_writer.rs @@ -124,12 +124,10 @@ fn annotation_level_for_level(level: Level) -> annotate_snippets::level::Level<' annotate_snippets::Level::ERROR.with_name("error: internal compiler error") } Level::Fatal | Level::Error => annotate_snippets::level::ERROR, - Level::ForceWarning | Level::Warning => annotate_snippets::Level::WARNING, + Level::Warning(_) => annotate_snippets::Level::WARNING, Level::Note => annotate_snippets::Level::NOTE, Level::Help => annotate_snippets::Level::HELP, Level::FailureNote => annotate_snippets::Level::NOTE.no_name(), - Level::Allow => panic!("Should not call with Allow"), - Level::Expect => panic!("Should not call with Expect"), } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9688f99abfebb..efd5ead56b36f 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -10,7 +10,7 @@ use rustc_ast::attr::version::RustcVersion; use rustc_data_structures::stable_hash::StableHasher; use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg}; use rustc_hashes::Hash128; -use rustc_lint_defs::{Applicability, LintExpectationId}; +use rustc_lint_defs::Applicability; use rustc_macros::{Decodable, Encodable}; use rustc_span::{Span, Spanned, Symbol}; use tracing::debug; @@ -190,7 +190,6 @@ pub struct DiagInner { pub messages: Vec<(DiagMessage, Style)>, pub code: Option, - pub lint_id: Option, pub span: MultiSpan, pub children: Vec, pub suggestions: Suggestions, @@ -212,7 +211,6 @@ impl DiagInner { pub fn new_with_messages(level: Level, messages: Vec<(DiagMessage, Style)>) -> Self { DiagInner { level, - lint_id: None, messages, code: None, span: MultiSpan::new(), @@ -234,13 +232,7 @@ impl DiagInner { match self.level { Level::Bug | Level::Fatal | Level::Error | Level::DelayedBug => true, - Level::ForceWarning - | Level::Warning - | Level::Note - | Level::Help - | Level::FailureNote - | Level::Allow - | Level::Expect => false, + Level::Warning(_) | Level::Note | Level::Help | Level::FailureNote => false, } } @@ -254,16 +246,6 @@ impl DiagInner { self.is_lint.as_ref().and_then(|is| is.rust_version) } - pub(crate) fn is_force_warn(&self) -> bool { - match self.level { - Level::ForceWarning => { - assert!(self.is_lint.is_some()); - true - } - _ => false, - } - } - pub(crate) fn sub( &mut self, level: Sublevel, @@ -307,7 +289,6 @@ impl DiagInner { level, messages, code, - lint_id: _, // ignore span, children, suggestions, @@ -317,8 +298,16 @@ impl DiagInner { emitted_at: _, // ignore } = self; - let hashed_parts = - (level, messages, code, span, children, suggestions, args.as_slice(), is_lint); + let hashed_parts = ( + std::mem::discriminant(level), // ignore the field within `Warning` + messages, + code, + span, + children, + suggestions, + args.as_slice(), + is_lint, + ); let mut hasher = StableHasher::new(); hashed_parts.hash(&mut hasher); @@ -1099,16 +1088,6 @@ impl<'a> Diag<'a> { self } } - with_fn! { with_lint_id, - /// Add an argument. - pub fn lint_id( - &mut self, - id: LintExpectationId, - ) -> &mut Self { - self.lint_id = Some(id); - self - } } - with_fn! { with_primary_message, /// Add a primary message. pub fn primary_message(&mut self, msg: impl Into) -> &mut Self { diff --git a/compiler/rustc_errors/src/json.rs b/compiler/rustc_errors/src/json.rs index 1f5a8c2fe94a6..59d79754314c1 100644 --- a/compiler/rustc_errors/src/json.rs +++ b/compiler/rustc_errors/src/json.rs @@ -136,20 +136,8 @@ impl Emitter for JsonEmitter { fn emit_future_breakage_report(&mut self, diags: Vec) { let data: Vec> = diags .into_iter() - .map(|mut diag| { - // Allowed or expected lints don't normally (by definition) emit a lint - // but future incompat lints are special and are emitted anyway. - // - // So to avoid ICEs and confused users we "upgrade" the lint level for - // those `FutureBreakageItem` to warn. - if matches!(diag.level, crate::Level::Allow | crate::Level::Expect) { - diag.level = crate::Level::Warning; - } - FutureBreakageItem { - diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic( - diag, self, - )), - } + .map(|diag| FutureBreakageItem { + diagnostic: EmitTyped::Diagnostic(Diagnostic::from_errors_diagnostic(diag, self)), }) .collect(); let report = FutureIncompatReport { future_incompat_report: data }; diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 33db5577baeb5..4cc5d5c230d15 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -350,9 +350,8 @@ struct DiagCtxtInner { future_breakage_diagnostics: Vec, - /// expected diagnostic will have the level `Expect` which additionally - /// carries the [`LintExpectationId`] of the expectation that can be - /// marked as fulfilled. This is a collection of all [`LintExpectationId`]s + /// Any `expect` lint will carry the [`LintExpectationId`] of the expectation that can be + /// marked as fulfilled. This field is a collection of all [`LintExpectationId`]s /// that have been marked as fulfilled this way. /// /// Emitting expectations after having stolen this field can happen. In particular, an @@ -612,7 +611,7 @@ impl<'a> DiagCtxtHandle<'a> { DelayedBug => { return self.dcx.inner.borrow_mut().emit_diagnostic(diag, self.tainted_with_errors); } - ForceWarning | Warning | Note | Help | FailureNote | Allow | Expect => None, + Warning(_) | Note | Help | FailureNote => None, }; // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic @@ -787,12 +786,12 @@ impl<'a> DiagCtxtHandle<'a> { match (errors.len(), warnings.len()) { (0, 0) => return, (0, _) => { - // Use `ForceWarning` rather than `Warning` to guarantee emission, e.g. with a - // configuration like `--cap-lints allow --force-warn bare_trait_objects`. - inner.emit_diagnostic( - DiagInner::new(ForceWarning, DiagMessage::Str(warnings)), - None, + // Force emission so this message always prints. + let diag = DiagInner::new( + Warning(Some(EmissionOverride::Forced { lint_id: None })), + DiagMessage::Str(warnings), ); + inner.emit_diagnostic(diag, None); } (_, 0) => { inner.emit_diagnostic(DiagInner::new(Error, errors), self.tainted_with_errors); @@ -918,6 +917,17 @@ impl<'a> DiagCtxtHandle<'a> { inner.emitter.emit_unused_externs(lint_level, unused_externs) } + /// We need to make sure that submitted expectation ids are correctly fulfilled, suppressed, + /// and stored between compilation sessions. To avoid doing these steps manually, we create a + /// dummy diagnostic and emit it as usual, which will be suppressed and stored like a normal + /// expected lint diagnostic. + #[track_caller] + pub fn fulfill_expectation(self, expectation: impl Into) { + let emission_override = Some(EmissionOverride::Expected { lint_id: expectation.into() }); + let msg = "this is a dummy diagnostic, to submit and store an expectation"; + Diag::new(self, Warning(emission_override), msg).emit() + } + /// This methods steals all [`LintExpectationId`]s that are stored inside /// [`DiagCtxtInner`] and indicate that the linked expectation has been fulfilled. #[must_use] @@ -1077,7 +1087,7 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn struct_warn(self, msg: impl Into) -> Diag<'a> { - Diag::new(self, Warning, msg) + Diag::new(self, Warning(None), msg) } #[track_caller] @@ -1101,7 +1111,7 @@ impl<'a> DiagCtxtHandle<'a> { #[track_caller] pub fn create_warn(self, warning: impl Diagnostic<'a>) -> Diag<'a> { - warning.into_diag(self, Warning) + warning.into_diag(self, Warning(None)) } #[track_caller] @@ -1142,16 +1152,6 @@ impl<'a> DiagCtxtHandle<'a> { pub fn emit_note(self, note: impl Diagnostic<'a>) { self.create_note(note).emit() } - - #[track_caller] - pub fn struct_allow(self, msg: impl Into) -> Diag<'a> { - Diag::new(self, Allow, msg) - } - - #[track_caller] - pub fn struct_expect(self, msg: impl Into, id: LintExpectationId) -> Diag<'a> { - Diag::new(self, Expect, msg).with_lint_id(id) - } } impl DiagCtxtInner { @@ -1185,13 +1185,13 @@ impl DiagCtxtInner { let has_errors = !self.err_guars.is_empty(); for (_, stashed_diagnostics) in mem::take(&mut self.stashed_diagnostics).into_iter() { for (_, (diag, _guar, _thread)) in stashed_diagnostics { - if !diag.is_error() { - // Unless they're forced, don't flush stashed warnings when - // there are errors, to avoid causing warning overload. The - // stash would've been stolen already if it were important. - if !diag.is_force_warn() && has_errors { - continue; - } + // When there are errors, skip flushing of stashed unforced warnings, to avoid + // warning overload. (They would have been stolen already if they were important.) + if has_errors + && let Warning(emission_override) = diag.level + && !matches!(emission_override, Some(EmissionOverride::Forced { .. })) + { + continue; } guar = guar.or(self.emit_diagnostic(diag, None)); } @@ -1206,10 +1206,10 @@ impl DiagCtxtInner { taint: Option<&Cell>>, ) -> Option { if diagnostic.has_future_breakage() { - // Future breakages aren't emitted if they're `Level::Allow` or - // `Level::Expect`, but they still need to be constructed and - // stashed below, so they'll trigger the must_produce_diag check. - assert_matches!(diagnostic.level, Error | ForceWarning | Warning | Allow | Expect); + // About the `allow`/`expect` lint sub-cases of `Warning`: future breakages aren't + // emitted for them, but they still need to be handled below so they'll trigger the + // `must_produce_diag` check. + assert_matches!(diagnostic.level, Error | Warning(_)); self.future_breakage_diagnostics.push(diagnostic.clone()); } @@ -1257,38 +1257,37 @@ impl DiagCtxtInner { }; } } - ForceWarning => { - if let Some(lint_id) = diagnostic.lint_id { - self.fulfilled_expectations.insert(lint_id); - } - } - Warning => { - if !self.flags.can_emit_warnings { - // We are not emitting warnings. - if diagnostic.has_future_breakage() { - // The side-effect is at the top of this method. + Warning(emission_override) => { + match emission_override { + None => { + if !self.flags.can_emit_warnings { + // We are not emitting warnings. + if diagnostic.has_future_breakage() { + // The side-effect is at the top of this method. + TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); + } + return None; + } + } + Some(EmissionOverride::Forced { lint_id: None }) => {} + Some(EmissionOverride::Forced { lint_id: Some(lint_id) }) => { + self.fulfilled_expectations.insert(lint_id); + } + Some(EmissionOverride::Allowed) => { + assert!(diagnostic.has_future_breakage()); TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); + self.suppressed_expected_diag = true; + return None; + } + Some(EmissionOverride::Expected { lint_id }) => { + self.fulfilled_expectations.insert(lint_id); + TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); + self.suppressed_expected_diag = true; + return None; } - return None; } } Note | Help | FailureNote => {} - Allow => { - // Nothing emitted for allowed lints. - if diagnostic.has_future_breakage() { - // The side-effect is at the top of this method. - TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); - self.suppressed_expected_diag = true; - } - return None; - } - Expect => { - self.fulfilled_expectations.insert(diagnostic.lint_id.unwrap()); - // Nothing emitted here for expected lints. - TRACK_DIAGNOSTIC(diagnostic, &mut |_| None); - self.suppressed_expected_diag = true; - return None; - } } if let (Some(msrv), Some(diag_msrv)) = (self.msrv, diagnostic.rust_version()) @@ -1344,7 +1343,7 @@ impl DiagCtxtInner { if is_error { self.deduplicated_err_count += 1; - } else if matches!(diagnostic.level, ForceWarning | Warning) { + } else if matches!(diagnostic.level, Warning(_)) { self.deduplicated_warn_count += 1; } self.has_printed = true; @@ -1545,19 +1544,45 @@ impl DelayedDiagInner { } } +/// Special emission behaviours on warning diagnostics. Combines with `DiagInner::is_lint` in the +/// following ways. +/// +/// | case | is_lint | `Option` field in `Warning` +/// | ---- | ------- | --------------------------------------------- +/// | ordinary non-lint diagnostic | None | None +/// | warning-count summary | None | Some(Forced { lint_id: None }) +/// | N/A | None | Some(Forced { lint_id: Some(lint_id) }) +/// | dummy expectation fulfillment | None | Some(Expected { lint_id }) +/// | N/A | None | Some(Allowed) +/// | ordinary `warn` lint | Some | None +/// | `warn` lint at `force-warn` | Some | Some(Forced { lint_id: None }) +/// | `expect` lint at `force-warn` | Some | Some(Forced { lint_id: Some(lint_id) }) +/// | `expect` lint | Some | Some(Expected { lint_id }) +/// | `allow` lint with future breakage | Some | Some(Allowed) +/// +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, Encodable, Decodable)] +pub enum EmissionOverride { + /// Cases where emission is forced. + Forced { lint_id: Option }, + + /// Used for `allow` lints with future breakage. (Allow lints without future breakage are + /// ignored and therefore never need an `EmissionOverride` value.) + Allowed, + + /// Used for `expect` lints. + Expected { lint_id: LintExpectationId }, +} + /// | Level | is_error | usable emit fns | Top-level | Used in lints? /// | ----- | -------- | --------------- | --------- | -------------- /// | Bug | yes | emit, emit_bug | yes | - /// | Fatal | yes | emit, emit_fatal | yes | - /// | Error | yes | emit, emit_err | yes | yes /// | DelayedBug | yes | emit, emit_err | yes | - -/// | ForceWarning | - | emit | yes | lint-only /// | Warning | - | emit | yes | yes /// | Note | - | emit | rare | - /// | Help | - | emit | don't use | - /// | FailureNote | - | emit | rare | - -/// | Allow | - | emit | yes | lint-only -/// | Expect | - | emit | yes | lint-only /// #[derive(Copy, PartialEq, Eq, Clone, Hash, Debug, Encodable, Decodable)] pub enum Level { @@ -1578,16 +1603,9 @@ pub enum Level { /// that should only be reached when compiling erroneous code. DelayedBug, - /// A `force-warn` lint warning about the code being compiled. Does not prevent compilation - /// from finishing. - /// - /// Requires the corresponding `DiagInner::lint_id` to be `Some` for expected lint diagnostics, - /// and `None` in all other cases. - ForceWarning, - /// A warning about the code being compiled. Does not prevent compilation from finishing. - /// Will be skipped if `can_emit_warnings` is false. - Warning, + /// Might not be emitted, depending on the value of `EmissionOverride` and `can_emit_warnings`. + Warning(Option), /// A rarely-used level for output that isn't an error or a warning. Note, @@ -1602,13 +1620,6 @@ pub enum Level { /// Similar to `Note`, but even rarer. Lacks the a trailing blank line that all other /// diagnostics have. Also, when printed for human consumption it doesn't have a `note:` label. FailureNote, - - /// Only used for lints. - Allow, - - /// Only used for lints. Requires the corresponding `DiagInner::lint_id` to be `Some` to - /// silence the lints. - Expect, } impl fmt::Display for Level { @@ -1622,16 +1633,15 @@ impl Level { match self { Bug | DelayedBug => "error: internal compiler error", Fatal | Error => "error", - ForceWarning | Warning => "warning", + Warning(_) => "warning", Note => "note", Help => "help", FailureNote => "failure-note", - Allow | Expect => unreachable!(), } } - pub fn is_failure_note(&self) -> bool { - matches!(*self, FailureNote) + pub fn is_failure_note(self) -> bool { + matches!(self, FailureNote) } } diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 1ecf808f78839..ce6a0d7548be1 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -407,7 +407,7 @@ impl ToInternal for Level { fn to_internal(self) -> rustc_errors::Level { match self { Level::Error => rustc_errors::Level::Error, - Level::Warning => rustc_errors::Level::Warning, + Level::Warning => rustc_errors::Level::Warning(None), Level::Note => rustc_errors::Level::Note, Level::Help => rustc_errors::Level::Help, _ => unreachable!("unknown proc_macro::Level variant: {:?}", self), diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs index a7ded8a82b5dc..15c60c920ce37 100644 --- a/compiler/rustc_lint/src/context.rs +++ b/compiler/rustc_lint/src/context.rs @@ -547,17 +547,7 @@ pub trait LintContext { /// retrieved from the current lint pass. Buffered or manually created ids can /// cause ICEs. fn fulfill_expectation(&self, expectation: Self::LintExpectationId) { - // We need to make sure that submitted expectation ids are correctly fulfilled suppressed - // and stored between compilation sessions. To not manually do these steps, we simply create - // a dummy diagnostic and emit it as usual, which will be suppressed and stored like a - // normal expected lint diagnostic. - self.sess() - .dcx() - .struct_expect( - "this is a dummy diagnostic, to submit and store an expectation", - expectation.into(), - ) - .emit(); + self.sess().dcx().fulfill_expectation(expectation); } } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 5d631acc1b528..3655d4594aa38 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp::min; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diag, DiagLocation, Diagnostic, MultiSpan}; +use rustc_errors::{Diag, DiagLocation, Diagnostic, EmissionOverride, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_lint_defs::{ EditionFcw, FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, @@ -416,7 +416,7 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( let err_level = match level { Level::Allow => { if has_future_breakage { - rustc_errors::Level::Allow + rustc_errors::Level::Warning(Some(EmissionOverride::Allowed)) } else { return; } @@ -426,13 +426,17 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( // we can't return early like in the case for `Level::Allow` because we still // need the lint diagnostic to be emitted to `rustc_error::DiagCtxtInner`. // - // We can also not mark the lint expectation as fulfilled here right away, as it - // can still be cancelled in the decorate function. All of this means that we simply - // create a `Diag` and continue as we would for warnings. - rustc_errors::Level::Expect + // We also cannot mark the lint expectation as fulfilled here right away, because + // it can still be cancelled in the decorate function. So we create a `Diag` and + // continue as we would for `Level::Warn`. + rustc_errors::Level::Warning(Some(EmissionOverride::Expected { + lint_id: lint_id.unwrap(), + })) } - Level::ForceWarn => rustc_errors::Level::ForceWarning, - Level::Warn => rustc_errors::Level::Warning, + Level::ForceWarn => { + rustc_errors::Level::Warning(Some(EmissionOverride::Forced { lint_id })) + } + Level::Warn => rustc_errors::Level::Warning(None), Level::Deny | Level::Forbid => rustc_errors::Level::Error, }; @@ -477,12 +481,13 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( // emitted or we'll get a `must_produce_diag` ICE. // // When is a diagnostic *eventually* emitted? Well, that is determined by 2 factors: - // 1. If the corresponding `rustc_errors::Level` is beyond warning, i.e. `ForceWarning` - // or `Error`, then the diagnostic will be emitted regardless of CLI options. + // 1. If the corresponding `rustc_errors::Level` is beyond warning, i.e. `Error`, then the + // diagnostic will be emitted regardless of CLI options. // 2. If the corresponding `rustc_errors::Level` is warning, then that can be affected by // `-A warnings` or `--cap-lints=xxx` on the command line. In which case, the diagnostic // will be emitted if `can_emit_warnings` is true. - let skip = err_level == rustc_errors::Level::Warning && !sess.dcx().can_emit_warnings(); + let skip = + err_level == rustc_errors::Level::Warning(None) && !sess.dcx().can_emit_warnings(); let mut err: Diag<'_> = if !skip { decorate(sess.dcx(), err_level) @@ -495,7 +500,8 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( if let Some(span) = span && err.span.primary_span().is_none() { - // We can't use `err.span()` because it overwrites the labels, so we need to do it manually. + // We can't use `err.span()` because it overwrites the labels, so we need to do it + // manually. for primary in span.primary_spans() { err.span.push_primary_span(*primary); } @@ -503,9 +509,6 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( err.span.push_span_diag(*label_span, label.clone()); } } - if let Some(lint_id) = lint_id { - err.lint_id(lint_id); - } if disable_suggestions { // Any suggestions made here are likely to be incorrect, so anything we diff --git a/compiler/rustc_passes/src/dead.rs b/compiler/rustc_passes/src/dead.rs index bd1bdf7cc0646..ffa3a7443ecc4 100644 --- a/compiler/rustc_passes/src/dead.rs +++ b/compiler/rustc_passes/src/dead.rs @@ -1172,13 +1172,7 @@ impl<'tcx> DeadVisitor<'tcx> { && let (_, Some(expectation)) = self.def_lint_level_plus(node) { // Same mechanism as LintContext::fulfill_expectation. - self.tcx - .dcx() - .struct_expect( - "this is a dummy diagnostic, to submit and store an expectation", - expectation.into(), - ) - .emit(); + self.tcx.dcx().fulfill_expectation(expectation); } }; diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 4d25aed007416..793c7d6f0401b 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -569,7 +569,7 @@ fn report_msg<'tcx>( let tcx = machine.tcx; let level = match diag_level { DiagLevel::Error => Level::Error, - DiagLevel::Warning => Level::Warning, + DiagLevel::Warning => Level::Warning(None), DiagLevel::Note => Level::Note, }; let mut err = Diag::new(tcx.sess.dcx(), level, title); diff --git a/src/tools/rustfmt/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs index 83a77e73cb7ea..c61b43492ce9e 100644 --- a/src/tools/rustfmt/src/parse/session.rs +++ b/src/tools/rustfmt/src/parse/session.rs @@ -418,7 +418,7 @@ mod tests { Some(ignore_list), ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span)); emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 0); assert_eq!(can_reset_errors.load(Ordering::Acquire), true); @@ -439,7 +439,7 @@ mod tests { None, ); let span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); - let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(span)); + let non_fatal_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(span)); emitter.emit_diagnostic(non_fatal_diagnostic); assert_eq!(num_emitted_errors.load(Ordering::Acquire), 1); assert_eq!(can_reset_errors.load(Ordering::Acquire), false); @@ -467,8 +467,8 @@ mod tests { ); let bar_span = MultiSpan::from_span(mk_sp(BytePos(0), BytePos(1))); let foo_span = MultiSpan::from_span(mk_sp(BytePos(21), BytePos(22))); - let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(bar_span)); - let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning, Some(foo_span)); + let bar_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(bar_span)); + let foo_diagnostic = build_diagnostic(DiagnosticLevel::Warning(None), Some(foo_span)); let fatal_diagnostic = build_diagnostic(DiagnosticLevel::Fatal, None); emitter.emit_diagnostic(bar_diagnostic); emitter.emit_diagnostic(foo_diagnostic); From cbc8109b3ba8afaf01b7cb2f90103ffc8f046422 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Fri, 25 Sep 2026 14:49:14 -0700 Subject: [PATCH 0867/1309] Specialize `advance_back_by` like the forward version We specialized `advance_by` in #141086, so it makes sense to have `advance_back_by` use the same trick in reverse, i.e. `try_rfold`. This also updates `nth_back` to mirror `nth`, and the rest of the `DoubleEndedIterator` methods already match `Iterator`. --- library/core/src/iter/traits/double_ended.rs | 50 ++++++++++++++++---- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/library/core/src/iter/traits/double_ended.rs b/library/core/src/iter/traits/double_ended.rs index a7c8ec9319a07..3c3db756d91ea 100644 --- a/library/core/src/iter/traits/double_ended.rs +++ b/library/core/src/iter/traits/double_ended.rs @@ -189,13 +189,49 @@ pub const trait DoubleEndedIterator: [const] Iterator { where Self::Item: [const] Destruct, { - for i in 0..n { - if self.next_back().is_none() { - // SAFETY: `i` is always less than `n`. - return Err(unsafe { NonZero::new_unchecked(n - i) }); + /// Helper trait to specialize `advance_back_by` via `try_rfold` for `Sized` iterators. + + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const trait SpecAdvanceBackBy { + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero>; + } + + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecAdvanceBackBy for I + where + I::Item: [const] Destruct, + { + default fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + for i in 0..n { + if self.next_back().is_none() { + // SAFETY: `i` is always less than `n`. + return Err(unsafe { NonZero::new_unchecked(n - i) }); + } + } + Ok(()) } } - Ok(()) + + #[rustc_const_unstable(feature = "const_iter", issue = "92476")] + const impl SpecAdvanceBackBy for I + where + I::Item: [const] Destruct, + { + fn spec_advance_back_by(&mut self, n: usize) -> Result<(), NonZero> { + let Some(n) = NonZero::new(n) else { + return Ok(()); + }; + + let res = self.try_rfold(n, const |n, _| NonZero::new(n.get() - 1)); + + match res { + None => Ok(()), + Some(n) => Err(n), + } + } + } + + self.spec_advance_back_by(n) } /// Returns the `n`th element from the end of the iterator. @@ -245,9 +281,7 @@ pub const trait DoubleEndedIterator: [const] Iterator { where Self::Item: [const] Destruct, { - if self.advance_back_by(n).is_err() { - return None; - } + self.advance_back_by(n).ok()?; self.next_back() } From 1d910ae376cf35835481f15cfab1561bc25a5e1b Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sat, 26 Sep 2026 00:28:04 +0200 Subject: [PATCH 0868/1309] simplify ndk compiler test --- src/bootstrap/src/utils/cc_detect/tests.rs | 52 +++++----------------- 1 file changed, 11 insertions(+), 41 deletions(-) diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs index b31850759687a..34c7901d077e1 100644 --- a/src/bootstrap/src/utils/cc_detect/tests.rs +++ b/src/bootstrap/src/utils/cc_detect/tests.rs @@ -7,11 +7,8 @@ use crate::core::session::Session; use crate::utils::tests::TestCtx; #[test] -fn test_ndk_compiler_c() { +fn test_ndk_compiler() { let ndk_path = PathBuf::from("/ndk"); - let target_triple = "arm-unknown-linux-android"; - let expected_triple_translated = "armv7a-unknown-linux-android"; - let expected_compiler = format!("{}21-{}", expected_triple_translated, Language::C.clang()); let host_tag = if cfg!(target_os = "macos") { "darwin-x86_64" } else if cfg!(target_os = "windows") { @@ -19,50 +16,23 @@ fn test_ndk_compiler_c() { } else { "linux-x86_64" }; - let expected_path = ndk_path - .join("toolchains") - .join("llvm") - .join("prebuilt") - .join(host_tag) - .join("bin") - .join(&expected_compiler); - let result = ndk_compiler(Language::C, target_triple, &ndk_path); - assert_eq!(result, expected_path); -} -#[test] -fn test_ndk_compiler_cpp() { - let ndk_path = PathBuf::from("/ndk"); - let target_triple = "arm-unknown-linux-android"; - let expected_triple_translated = "armv7a-unknown-linux-android"; - let expected_compiler = - format!("{}21-{}", expected_triple_translated, Language::CPlusPlus.clang()); - let host_tag = if cfg!(target_os = "macos") { - "darwin-x86_64" - } else if cfg!(target_os = "windows") { - "windows-x86_64" - } else { - "linux-x86_64" - }; - let expected_path = ndk_path - .join("toolchains") - .join("llvm") - .join("prebuilt") - .join(host_tag) - .join("bin") - .join(&expected_compiler); - let result = ndk_compiler(Language::CPlusPlus, target_triple, &ndk_path); - assert_eq!(result, expected_path); + for (language, compiler) in [ + (Language::C, "armv7a-unknown-linux-android21-clang"), + (Language::CPlusPlus, "armv7a-unknown-linux-android21-clang++"), + ] { + let expected = + ndk_path.join("toolchains/llvm/prebuilt").join(host_tag).join("bin").join(compiler); + + assert_eq!(ndk_compiler(language, "arm-unknown-linux-android", &ndk_path), expected); + } } #[test] -fn test_language_gcc() { +fn test_language_compiler_names() { assert_eq!(Language::C.gcc(), "gcc"); assert_eq!(Language::CPlusPlus.gcc(), "g++"); -} -#[test] -fn test_language_clang() { assert_eq!(Language::C.clang(), "clang"); assert_eq!(Language::CPlusPlus.clang(), "clang++"); } From eb7e04db8ae77067bc713443573f4232b3680c73 Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Sat, 26 Sep 2026 00:44:05 +0200 Subject: [PATCH 0869/1309] Disable RA diagnostics due to many false positives --- src/tools/miri/etc/rust_analyzer_zed.json | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/miri/etc/rust_analyzer_zed.json b/src/tools/miri/etc/rust_analyzer_zed.json index e5ff400e989e7..f2debc2000acb 100644 --- a/src/tools/miri/etc/rust_analyzer_zed.json +++ b/src/tools/miri/etc/rust_analyzer_zed.json @@ -19,6 +19,10 @@ "--message-format=json" ] }, + "diagnostics": { + // RA reports false errors due to + "enable": false + }, "cargo": { "extraEnv": { "MIRI_AUTO_OPS": "no", From 465889bc3355eea0179a6ccb103f13053dd21a37 Mon Sep 17 00:00:00 2001 From: Ashutosh1910 Date: Sun, 13 Sep 2026 12:00:51 +0530 Subject: [PATCH 0870/1309] compiletest: stream output of executor process when --no-capture is set --- src/tools/compiletest/src/runtest/run_make.rs | 46 ++++++++++++++----- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/src/tools/compiletest/src/runtest/run_make.rs b/src/tools/compiletest/src/runtest/run_make.rs index 862f38d97c8cf..f91f3a521d865 100644 --- a/src/tools/compiletest/src/runtest/run_make.rs +++ b/src/tools/compiletest/src/runtest/run_make.rs @@ -7,6 +7,7 @@ use camino::{Utf8Path, Utf8PathBuf}; use super::{ProcRes, TestCx, disable_error_reporting}; use crate::common::TestSuite; +use crate::read2::Truncated; use crate::util::{ArgFileCommand, copy_dir_all, dylib_env_var}; impl TestCx<'_> { @@ -175,8 +176,6 @@ impl TestCx<'_> { let mut cmd = Command::new(&recipe_bin); cmd.current_dir(&rmake_out_dir) - .stdout(Stdio::piped()) - .stderr(Stdio::piped()) // Provide the target-specific env var that is used to record dylib search paths. For // example, this could be `LD_LIBRARY_PATH` on some linux distros but `PATH` on Windows. .env("LD_LIB_PATH_ENVVAR", dylib_env_var()) @@ -337,16 +336,39 @@ impl TestCx<'_> { } } - let proc = disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`")); - let (Output { stdout, stderr, status }, truncated) = self.read2_abbreviated(proc); - let stdout = String::from_utf8_lossy(&stdout).into_owned(); - let stderr = String::from_utf8_lossy(&stderr).into_owned(); - // This conditions on `status.success()` so we don't print output twice on error. - // NOTE: this code is called from an executor thread, so it's hidden by default unless --no-capture is passed. - self.dump_output(status.success(), &cmd.get_program().to_string_lossy(), &stdout, &stderr); - if !status.success() { - let res = ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) }; - self.fatal_proc_rec("rmake recipe failed to complete", &res); + if self.config.capture { + cmd.stdout(Stdio::piped()).stderr(Stdio::piped()); + let proc = disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`")); + let (Output { stdout, stderr, status }, truncated) = self.read2_abbreviated(proc); + let stdout = String::from_utf8_lossy(&stdout).into_owned(); + let stderr = String::from_utf8_lossy(&stderr).into_owned(); + // This conditions on `status.success()` so we don't print output twice on error. + self.dump_output( + status.success(), + &cmd.get_program().to_string_lossy(), + &stdout, + &stderr, + ); + if !status.success() { + let res = + ProcRes { status, stdout, stderr, truncated, cmdline: format!("{:?}", cmd) }; + self.fatal_proc_rec("rmake recipe failed to complete", &res); + } + } else { + // When --no-capture is passed, we don't need to capture the output and just wait for the process to finish + let mut proc = + disable_error_reporting(|| cmd.spawn().expect("failed to spawn `rmake`")); + let status = proc.wait().expect("failed to wait for `rmake`"); + if !status.success() { + let res = ProcRes { + status, + stdout: String::new(), + stderr: String::new(), + truncated: Truncated::No, + cmdline: format!("{:?}", cmd), + }; + self.fatal_proc_rec("rmake recipe failed to complete", &res); + } } } } From 4326cf73a3a45bd95c47a576fb696dea793023eb Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Sep 2026 22:15:02 +1000 Subject: [PATCH 0871/1309] Remove `PartialOrd`/`Ord` impls for `Span`/`SpanData` `Span` and `SpanData` encode four fields: `lo`/`hi`, `ctxt`, and `parent`. `ctxt` and `parent` have unorderable types. Both types ignore `ctxt` and `parent` for `PartialOrd`/`Ord`. But their `PartialEq`/`Eq` impls do *not* ignore those fields. This eq/ord inconsistency is a bug. It was introduced in #123165. The idea of ordering spans in general is dubious, because of `ctxt` and `parent`. But the idea of ordering spans just with `lo`/`hi` is fine. Therefore, this commit does the following. - Removes the `PartialOrd`/`Ord` impls for `Span`/`SpanData` - Adds a `Span::lo_hi` method which can be used in lots of places where span locations are involved in sorting. E.g. `xs.sort_by_key(|span| span.lo_hi())` - Adds `OrdSpan`, a newtype around `Span` that impls `PartialEq`/`Eq`/`PartialOrd`/`Ord` using `lo_hi`. This is for storing spans in ordered types like `BTreeMap`. Note also that some `sort`+`dedup` combinations might not remove all duplicates with the old eq/ord inconsistency. These now all do the right thing, which could affect some error messages, though in practice nothing in the test suite is affected. --- Cargo.lock | 1 - .../rustc_attr_parsing/src/attributes/repr.rs | 9 ++-- .../src/diagnostics/conflict_errors.rs | 6 +-- .../src/diagnostics/explain_borrow.rs | 4 +- .../rustc_borrowck/src/diagnostics/mod.rs | 2 +- .../src/diagnostics/move_errors.rs | 4 +- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- compiler/rustc_error_messages/src/lib.rs | 2 +- compiler/rustc_errors/src/diagnostic.rs | 2 +- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/hir_ty_lowering/errors.rs | 20 ++++----- compiler/rustc_hir_typeck/src/loops.rs | 19 +++++---- .../rustc_hir_typeck/src/method/suggest.rs | 31 +++++++------- compiler/rustc_hir_typeck/src/writeback.rs | 2 +- compiler/rustc_interface/src/passes.rs | 2 +- compiler/rustc_lint/src/builtin.rs | 4 +- compiler/rustc_lint/src/non_ascii_idents.rs | 10 ++--- compiler/rustc_middle/src/mono.rs | 10 ++--- compiler/rustc_middle/src/traits/mod.rs | 24 +++++------ .../rustc_mir_build/src/check_unsafety.rs | 2 +- .../src/thir/pattern/check_match.rs | 2 +- .../src/check_call_recursion.rs | 2 +- .../src/graph_checks/statics.rs | 2 +- compiler/rustc_passes/src/check_attr.rs | 2 +- .../src/handle_cycle_error.rs | 2 +- .../rustc_resolve/src/diagnostics/impls.rs | 12 +++--- compiler/rustc_resolve/src/ident.rs | 5 ++- compiler/rustc_resolve/src/imports.rs | 6 +-- .../rustc_resolve/src/late/diagnostics.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 4 +- compiler/rustc_span/Cargo.toml | 1 - compiler/rustc_span/src/lib.rs | 35 ++++++---------- compiler/rustc_span/src/span_encoding.rs | 41 +++++++++++++++++++ .../nice_region_error/static_impl_trait.rs | 9 ++-- .../src/error_reporting/infer/region.rs | 17 +++++--- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/html/macro_expansion.rs | 2 +- .../src/disallowed_script_idents.rs | 2 +- .../clippy/clippy_lints/src/format_args.rs | 4 +- .../clippy_lints/src/implicit_hasher.rs | 10 ++--- .../src/implied_bounds_in_impls.rs | 6 ++- .../src/macro_metavars_in_unsafe.rs | 6 +-- .../clippy/clippy_lints/src/macro_use.rs | 12 +++--- .../clippy_lints/src/methods/map_unwrap_or.rs | 2 +- .../src/methods/unnecessary_fold.rs | 2 +- .../src/multiple_unsafe_ops_per_block.rs | 2 +- .../clippy_lints/src/operators/cmp_owned.rs | 2 +- .../clippy/clippy_lints/src/useless_vec.rs | 9 ++-- src/tools/miri/src/shims/foreign_items.rs | 14 +++---- 49 files changed, 210 insertions(+), 165 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5f35ce252b78e..063ee6b9850b4 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4819,7 +4819,6 @@ version = "0.0.0" dependencies = [ "bitflags", "blake3", - "derive-where", "indexmap", "itoa", "md-5", diff --git a/compiler/rustc_attr_parsing/src/attributes/repr.rs b/compiler/rustc_attr_parsing/src/attributes/repr.rs index 6115ed207d98c..bc4f9d20545fc 100644 --- a/compiler/rustc_attr_parsing/src/attributes/repr.rs +++ b/compiler/rustc_attr_parsing/src/attributes/repr.rs @@ -4,6 +4,7 @@ use rustc_attr_ir::IntType::{SignedInt, UnsignedInt}; use rustc_attr_ir::ReprAttr; use rustc_feature::AttributeStability; use rustc_session::diagnostics::feature_err; +use rustc_span::OrdSpan; use super::prelude::*; use crate::diagnostics; @@ -272,7 +273,7 @@ fn parse_alignment(node: &LitKind, cx: &AcceptContext<'_, '_>) -> Result); +pub(crate) struct RustcAlignParser(Option<(Align, OrdSpan)>); impl RustcAlignParser { const PATH: &[Symbol] = &[sym::rustc_align]; @@ -293,7 +294,7 @@ impl RustcAlignParser { }; match parse_alignment(&lit.kind, cx) { - Ok(literal) => self.0 = Ord::max(self.0, Some((literal, cx.attr_span))), + Ok(literal) => self.0 = Ord::max(self.0, Some((literal, OrdSpan(cx.attr_span)))), Err(message) => { cx.emit_err(diagnostics::InvalidAlignmentValue { span: lit.span, @@ -318,7 +319,7 @@ impl AttributeParser for RustcAlignParser { fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { let (align, span) = self.0?; - Some(AttributeKind::RustcAlign { align, span }) + Some(AttributeKind::RustcAlign { align, span: span.0 }) } } @@ -342,6 +343,6 @@ impl AttributeParser for RustcAlignStaticParser { fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option { let (align, span) = self.0.0?; - Some(AttributeKind::RustcAlign { align, span }) + Some(AttributeKind::RustcAlign { align, span: span.0 }) } } diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index f4b2ceb850666..132f074f9e0f9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -893,7 +893,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .errors .iter() .map(|error| error.span) - .any(|sp| span < sp && !sp.contains(span)) + .any(|sp| span.lo_hi() < sp.lo_hi() && !sp.contains(span)) }) { show_assign_sugg = true; if all_init_spans.iter().any(|init_span| !init_span.contains(span)) @@ -929,7 +929,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let mut shown = false; let mut shown_condition_value = false; for error in visitor.errors { - if error.span < span && !error.span.overlaps(span) { + if error.span.lo_hi() < span.lo_hi() && !error.span.overlaps(span) { // When we have a case like `match-cfg-fake-edges.rs`, we don't want to mention // match arms coming after the primary span because they aren't relevant: // ``` @@ -950,7 +950,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } if !shown { for sp in &reachable_spans { - if *sp < span && !sp.overlaps(span) { + if sp.lo_hi() < span.lo_hi() && !sp.overlaps(span) { err.span_label(*sp, "binding initialized here in some conditions"); } } diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index f431374de37ba..7537e2f9f1495 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -419,8 +419,8 @@ impl<'tcx> BorrowExplanation<'tcx> { _ => None, }) .collect::>(); - preds.sort(); - preds.dedup(); + preds.sort_by_key(|span| span.lo_hi()); + preds.dedup_by_key(|span| span.lo_hi()); if !preds.is_empty() { let s = if preds.len() == 1 { "" } else { "s" }; err.span_note( diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs index c8abc2689ff7f..523db527d0cf9 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mod.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs @@ -123,7 +123,7 @@ impl<'diag, 'tcx> BorrowckDiagnosticsBuffer<'diag, 'tcx> { } if !self.buffered_diags.is_empty() { - self.buffered_diags.sort_by_key(|(sort_span, _)| *sort_span); + self.buffered_diags.sort_by_key(|(sort_span, _)| sort_span.lo_hi()); for (_, diag) in self.buffered_diags.drain(..) { diag.emit(); } diff --git a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs index aa62d6aaa0751..4d65410455118 100644 --- a/compiler/rustc_borrowck/src/diagnostics/move_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/move_errors.rs @@ -1206,8 +1206,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { suggestions.push((binding_span.shrink_to_lo(), msg, "ref ".to_string())); } } - suggestions.sort_unstable_by_key(|&(span, _, _)| span); - suggestions.dedup_by_key(|&mut (span, _, _)| span); + suggestions.sort_unstable_by_key(|&(span, _, _)| span.lo_hi()); + suggestions.dedup_by_key(|&mut (span, _, _)| span.lo_hi()); for (span, msg, suggestion) in suggestions { err.span_suggestion_verbose(span, msg, suggestion, Applicability::MachineApplicable); } diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index a886187783b86..b3032662fb3e4 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -318,7 +318,7 @@ impl<'tcx> MirTypeckRegionConstraints<'tcx> { /// required to hold. Normally, this is at a particular point which /// created the obligation, but for constraints that the user gave, we /// want the constraint to hold at all points. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)] pub enum Locations { /// Indicates that a type constraint should always be true. This /// is particularly important in the new borrowck analysis for diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index bedcfe998b638..cb3b43aafa155 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -101,7 +101,7 @@ impl MultiSpan { } pub fn from_spans(mut vec: Vec) -> MultiSpan { - vec.sort(); + vec.sort_by_key(|span| span.lo_hi()); MultiSpan { primary_spans: vec, span_labels: vec![], span_context: vec![] } } diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9688f99abfebb..3f879b5f2effb 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -972,7 +972,7 @@ impl<'a> Diag<'a> { .map(|(span, snippet)| SubstitutionPart { snippet, span }) .collect::>(); - parts.sort_unstable_by_key(|part| part.span); + parts.sort_unstable_by_key(|part| part.span.lo_hi()); assert!(!parts.is_empty()); debug_assert_eq!( diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index 8f693221b0fd2..66605e9de6ec0 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -240,7 +240,7 @@ fn bad_placeholder<'cx, 'tcx>( ) -> Diag<'cx> { let kind = if kind.ends_with('s') { format!("{kind}es") } else { format!("{kind}s") }; - spans.sort(); + spans.sort_by_key(|span| span.lo_hi()); cx.dcx().create_err(diagnostics::PlaceholderNotAllowedItemSignatures { spans, kind }) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index f2cf4743d76b6..de22c157ee5d1 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -18,7 +18,7 @@ use rustc_middle::ty::{ }; use rustc_session::diagnostics::feature_err; use rustc_span::edit_distance::find_best_match_for_name; -use rustc_span::{BytePos, DUMMY_SP, Ident, Span, Symbol, bug, kw, sym}; +use rustc_span::{BytePos, DUMMY_SP, Ident, OrdSpan, Span, Symbol, bug, kw, sym}; use rustc_trait_selection::error_reporting::traits::report_dyn_incompatibility; use rustc_trait_selection::traits::{ FulfillmentError, dyn_compatibility_violations_for_assoc_item, @@ -943,22 +943,22 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { return err.emit_err(); } - let mut bound_spans: SortedMap> = Default::default(); + let mut bound_spans: SortedMap> = Default::default(); let mut bound_span_label = |self_ty: Ty<'_>, obligation: &str, quiet: &str| { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); match self_ty.kind() { // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => { - bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) - } + ty::Adt(def, _) => bound_spans + .get_mut_or_insert_default(OrdSpan(tcx.def_span(def.did()))) + .push(msg), // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { bound_spans - .get_mut_or_insert_default(tcx.def_span(tr.def_id)) + .get_mut_or_insert_default(OrdSpan(tcx.def_span(tr.def_id))) .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) @@ -969,7 +969,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => { bound_spans - .get_mut_or_insert_default(tcx.def_span(*def_id)) + .get_mut_or_insert_default(OrdSpan(tcx.def_span(*def_id))) .push(format!("`{quiet}`")); } _ => {} @@ -1034,7 +1034,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); for (span, mut bounds) in bound_spans { - if !tcx.sess.source_map().is_span_accessible(span) { + if !tcx.sess.source_map().is_span_accessible(span.0) { continue; } bounds.sort(); @@ -1045,7 +1045,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { [bounds @ .., last] => format!("doesn't satisfy {} or {last}", bounds.join(", ")), [] => unreachable!(), }; - err.span_label(span, msg); + err.span_label(span.0, msg); } add_def_label(&mut err); err.emit_err() @@ -1315,7 +1315,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { ); } } - suggestions.sort_by_key(|&(span, _)| span); + suggestions.sort_by_key(|&(span, _)| span.lo_hi()); // There are cases where one bound points to a span within another bound's span, like when // you have code like the following (#115019), so we skip providing a suggestion in those // cases to avoid having a malformed suggestion. diff --git a/compiler/rustc_hir_typeck/src/loops.rs b/compiler/rustc_hir_typeck/src/loops.rs index 3ce6c34176101..6b1354002c943 100644 --- a/compiler/rustc_hir_typeck/src/loops.rs +++ b/compiler/rustc_hir_typeck/src/loops.rs @@ -10,7 +10,7 @@ use rustc_hir::{Destination, Node, find_attr}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::TyCtxt; use rustc_span::hygiene::DesugaringKind; -use rustc_span::{BytePos, Span, span_bug}; +use rustc_span::{BytePos, OrdSpan, Span, span_bug}; use crate::diagnostics::{ BreakInsideClosure, BreakInsideCoroutine, BreakNonLoop, ConstContinueBadLabel, @@ -79,7 +79,7 @@ struct CheckLoopVisitor<'tcx> { // such as adding a label for an `if`. // e.g. `if 'foo: {}` would be incorrect. cx_stack: Vec, - block_breaks: BTreeMap, + block_breaks: BTreeMap, } pub(crate) fn check<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId, body: &'tcx hir::Body<'tcx>) { @@ -377,12 +377,13 @@ impl<'hir> CheckLoopVisitor<'hir> { UnlabeledBlock { label_span, wrap_end } if br_cx_kind == BreakContextKind::Break && label_span.eq_ctxt(break_span) => { - let block = self.block_breaks.entry(label_span).or_insert_with(|| BlockInfo { - name: br_cx_kind.to_string(), - spans: vec![], - suggs: vec![], - wrap_end, - }); + let block = + self.block_breaks.entry(OrdSpan(label_span)).or_insert_with(|| BlockInfo { + name: br_cx_kind.to_string(), + spans: vec![], + suggs: vec![], + wrap_end, + }); block.spans.push(span); block.suggs.push(break_span); } @@ -423,7 +424,7 @@ impl<'hir> CheckLoopVisitor<'hir> { name: &block.name, is_break: true, suggestion: Some(OutsideLoopSuggestion { - block_span: *s, + block_span: s.0, break_spans: block.suggs.clone(), block_prefix: if block.wrap_end.is_some() { "{ 'block: " } else { "'block: " }, wrap_end: block.wrap_end, diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index e074ebf01bda4..615b755c39845 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -33,7 +33,7 @@ use rustc_middle::ty::print::{ use rustc_middle::ty::{self, GenericArgKind, IsSuggestable, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::def_id::DefIdSet; use rustc_span::{ - DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, Span, Symbol, bug, + DUMMY_SP, ErrorGuaranteed, ExpnKind, FileName, Ident, MacroKind, OrdSpan, Span, Symbol, bug, edit_distance, kw, sym, }; use rustc_trait_selection::error_reporting::traits::DefIdOrName; @@ -890,12 +890,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { source: SelfSource<'tcx>, unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>, static_candidates: &[CandidateSource], - ) -> Result<(bool, bool, bool, bool, SortedMap>), ()> { + ) -> Result<(bool, bool, bool, bool, SortedMap>), ()> { let mut restrict_type_params = false; let mut suggested_derive = false; let mut unsatisfied_bounds = false; let mut custom_span_label = !static_candidates.is_empty(); - let mut bound_spans: SortedMap> = Default::default(); + let mut bound_spans: SortedMap> = Default::default(); let tcx = self.tcx; if item_ident.name == sym::count && self.is_slice_ty(rcvr_ty, span) { @@ -1137,7 +1137,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { rcvr_ty: Ty<'tcx>, item_ident: Ident, item_kind: &str, - bound_spans: SortedMap>, + bound_spans: SortedMap>, unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>, ) { let mut ty_span = match rcvr_ty.kind() { @@ -1179,6 +1179,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { None }; for (span, mut bounds) in bound_spans { + let span = span.0; if !self.tcx.sess.source_map().is_span_accessible(span) { continue; } @@ -1715,7 +1716,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { suggested_derive: &mut bool, unsatisfied_bounds: &mut bool, custom_span_label: &mut bool, - bound_spans: &mut SortedMap>, + bound_spans: &mut SortedMap>, ) { let tcx = self.tcx; let rcvr_ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path()); @@ -1800,16 +1801,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let msg = format!("`{}`", if obligation.len() > 50 { quiet } else { obligation }); match self_ty.kind() { // Point at the type that couldn't satisfy the bound. - ty::Adt(def, _) => { - bound_spans.get_mut_or_insert_default(tcx.def_span(def.did())).push(msg) - } + ty::Adt(def, _) => bound_spans + .get_mut_or_insert_default(OrdSpan(tcx.def_span(def.did()))) + .push(msg), // Point at the trait object that couldn't satisfy the bound. ty::Dynamic(preds, _) => { for pred in preds.iter() { match pred.skip_binder() { ty::ExistentialPredicate::Trait(tr) => { bound_spans - .get_mut_or_insert_default(tcx.def_span(tr.def_id)) + .get_mut_or_insert_default(OrdSpan(tcx.def_span(tr.def_id))) .push(msg.clone()); } ty::ExistentialPredicate::Projection(_) @@ -1820,7 +1821,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { // Point at the closure that couldn't satisfy the bound. ty::Closure(def_id, _) => { bound_spans - .get_mut_or_insert_default(tcx.def_span(*def_id)) + .get_mut_or_insert_default(OrdSpan(tcx.def_span(*def_id))) .push(format!("`{quiet}`")); } _ => {} @@ -2030,7 +2031,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } } let mut spanned_predicates: Vec<_> = spanned_predicates.into_iter().collect(); - spanned_predicates.sort_by_key(|(span, _)| *span); + spanned_predicates.sort_by_key(|(span, _)| span.lo_hi()); for (_, (primary_spans, span_labels, predicates)) in spanned_predicates { let mut tracker = TraitBoundDuplicateTracker::new(); let mut all_trait_bounds_for_rcvr = true; @@ -3572,7 +3573,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, trait_pred: ty::TraitClause<'tcx>, adt: ty::AdtDef<'tcx>, - ) -> Option> { + ) -> Option> { let diagnostic_name = self.tcx.get_diagnostic_name(trait_pred.def_id())?; let can_derive = match diagnostic_name { @@ -3610,7 +3611,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut derives = Vec::new(); let self_name = self_ty.to_string(); - let self_span = self.tcx.def_span(adt.did()); + let self_span = OrdSpan(self.tcx.def_span(adt.did())); for super_trait in supertraits(self.tcx, ty::Binder::dummy(trait_pred.trait_ref)) { if let Some(parent_diagnostic_name) = self.tcx.get_diagnostic_name(super_trait.def_id()) @@ -3628,7 +3629,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { &self, err: &mut Diag<'_>, unsatisfied_predicates: &UnsatisfiedPredicates<'tcx>, - ) -> Vec<(String, Span, Symbol)> { + ) -> Vec<(String, OrdSpan, Symbol)> { let mut derives = Vec::new(); let mut traits = Vec::new(); for (pred, _, _) in unsatisfied_predicates { @@ -3692,7 +3693,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { continue; } } - derives_grouped.push((self_name, self_span, trait_name.to_string())); + derives_grouped.push((self_name, self_span.0, trait_name.to_string())); } for (self_name, self_span, traits) in &derives_grouped { diff --git a/compiler/rustc_hir_typeck/src/writeback.rs b/compiler/rustc_hir_typeck/src/writeback.rs index 5ae65ad26f916..c19c25228fb42 100644 --- a/compiler/rustc_hir_typeck/src/writeback.rs +++ b/compiler/rustc_hir_typeck/src/writeback.rs @@ -499,7 +499,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> { } if !errors_buffer.is_empty() { - errors_buffer.sort_by_key(|diag| diag.span.primary_span()); + errors_buffer.sort_by_key(|diag| diag.span.primary_span().map(Span::lo_hi)); for err in errors_buffer { err.emit(); } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 610eb5fd099d2..f21888b1de5e0 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -434,7 +434,7 @@ fn early_lint_checks(tcx: TyCtxt<'_>, (): ()) { // Gate identifiers containing invalid Unicode codepoints that were recovered during lexing. sess.psess.bad_unicode_identifiers.with_lock(|identifiers| { for (ident, mut spans) in identifiers.drain(..) { - spans.sort(); + spans.sort_by_key(|span| span.lo_hi()); if ident == sym::ferris { enum FerrisFix { SnakeCase, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index bba993ee3f052..0688dcf2fcaf2 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2163,8 +2163,8 @@ impl<'tcx> LateLintPass<'tcx> for ExplicitOutlivesRequirements { // Due to macros, there might be several predicates with the same span // and we only want to suggest removing them once. - lint_spans.sort_unstable(); - lint_spans.dedup(); + lint_spans.sort_unstable_by_key(|span| span.lo_hi()); + lint_spans.dedup_by_key(|span| span.lo_hi()); cx.emit_span_lint( EXPLICIT_OUTLIVES_REQUIREMENTS, diff --git a/compiler/rustc_lint/src/non_ascii_idents.rs b/compiler/rustc_lint/src/non_ascii_idents.rs index 416b8717a7dc3..588a9e1130f76 100644 --- a/compiler/rustc_lint/src/non_ascii_idents.rs +++ b/compiler/rustc_lint/src/non_ascii_idents.rs @@ -2,7 +2,7 @@ use rustc_ast as ast; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordMap; use rustc_lint_defs::{declare_lint, declare_lint_pass}; -use rustc_span::Symbol; +use rustc_span::{OrdSpan, Symbol}; use unicode_security::general_security_profile::IdentifierType; use crate::diagnostics::{ @@ -180,7 +180,7 @@ impl EarlyLintPass for NonAsciiIdents { // We will soon sort, so the initial order does not matter. #[allow(rustc::potential_query_instability)] let mut symbols: Vec<_> = symbols.iter().collect(); - symbols.sort_by_key(|k| k.1); + symbols.sort_by_key(|k| k.1.lo_hi()); for &(ref symbol, &sp) in symbols.iter() { let symbol_str = symbol.as_str(); if symbol_str.is_ascii() { @@ -342,7 +342,7 @@ impl EarlyLintPass for NonAsciiIdents { .collect::>(); // we're sorting the output here. - let mut lint_reports: BTreeMap<(Span, Vec), AugmentedScriptSet> = + let mut lint_reports: BTreeMap<(OrdSpan, Vec), AugmentedScriptSet> = BTreeMap::new(); // The end result is put in `lint_reports` which is sorted. @@ -368,7 +368,7 @@ impl EarlyLintPass for NonAsciiIdents { // We sort primitive chars here and can use unstable sort ch_list.sort_unstable(); ch_list.dedup(); - lint_reports.insert((sp, ch_list), augment_script_set); + lint_reports.insert((OrdSpan(sp), ch_list), augment_script_set); } for ((sp, ch_list), script_set) in lint_reports { @@ -382,7 +382,7 @@ impl EarlyLintPass for NonAsciiIdents { } cx.emit_span_lint( MIXED_SCRIPT_CONFUSABLES, - sp, + sp.0, MixedScriptConfusables { set: script_set.to_string(), includes }, ); } diff --git a/compiler/rustc_middle/src/mono.rs b/compiler/rustc_middle/src/mono.rs index a54ca4faf81ee..cf567fa1c8999 100644 --- a/compiler/rustc_middle/src/mono.rs +++ b/compiler/rustc_middle/src/mono.rs @@ -15,7 +15,7 @@ use rustc_hir::ItemId; use rustc_hir::def_id::{CrateNum, DefId, DefIdSet, LOCAL_CRATE}; use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use rustc_session::config::OptLevel; -use rustc_span::{Span, Symbol}; +use rustc_span::{OrdSpan, Span, Symbol}; use rustc_target::spec::SymbolVisibility; use tracing::debug; @@ -528,7 +528,7 @@ impl<'tcx> CodegenUnit<'tcx> { // The codegen tests rely on items being process in the same order as // they appear in the file, so for local items, we sort by span first #[derive(PartialEq, Eq, PartialOrd, Ord)] - struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); + struct ItemSortKey<'tcx>(Option, SymbolName<'tcx>); // We only want to take HirIds of user-defines instances into account. // The others don't matter for the codegen tests and can even make item @@ -560,9 +560,9 @@ impl<'tcx> CodegenUnit<'tcx> { } fn item_sort_key<'tcx>(tcx: TyCtxt<'tcx>, item: MonoItem<'tcx>) -> ItemSortKey<'tcx> { ItemSortKey( - local_item_id(item) - .map(|def_id| tcx.def_span(def_id).find_ancestor_not_from_macro()) - .flatten(), + local_item_id(item).and_then(|def_id| { + tcx.def_span(def_id).find_ancestor_not_from_macro().map(OrdSpan) + }), item.symbol_name(tcx), ) } diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 5520b059f5678..828a1ee79a06b 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -21,7 +21,7 @@ use rustc_macros::{ Decodable, Encodable, StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, }; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_span::{DUMMY_SP, Span, Symbol, sym}; +use rustc_span::{DUMMY_SP, OrdSpan, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; @@ -863,15 +863,15 @@ impl DynCompatibilityViolation { | Self::SupertraitConst(_) => DynCompatibilityViolationSolution::None, Self::Method( name, - MethodViolation::StaticMethod(Some((add_self_sugg, make_sized_sugg))), + MethodViolation::StaticMethod(Some(((add_s, add_sp), (make_s, make_sp)))), _, ) => DynCompatibilityViolationSolution::AddSelfOrMakeSized { name: *name, - add_self_sugg: add_self_sugg.clone(), - make_sized_sugg: make_sized_sugg.clone(), + add_self_sugg: (add_s.clone(), OrdSpan(*add_sp)), + make_sized_sugg: (make_s.clone(), OrdSpan(*make_sp)), }, Self::Method(name, MethodViolation::UndispatchableReceiver(Some((span, lt))), _) => { - DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span, *lt) + DynCompatibilityViolationSolution::ChangeToRefSelf(*name, OrdSpan(*span), *lt) } Self::Method(name, ..) | Self::AssocConst(name, ..) | Self::GenericAssocTy(name, _) => { DynCompatibilityViolationSolution::MoveToAnotherTrait(*name) @@ -901,15 +901,15 @@ impl DynCompatibilityViolation { } } -#[derive(Clone, Debug, PartialEq, Eq, Hash, PartialOrd, Ord)] +#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)] pub enum DynCompatibilityViolationSolution { None, AddSelfOrMakeSized { name: Symbol, - add_self_sugg: (String, Span), - make_sized_sugg: (String, Span), + add_self_sugg: (String, OrdSpan), + make_sized_sugg: (String, OrdSpan), }, - ChangeToRefSelf(Symbol, Span, Symbol), + ChangeToRefSelf(Symbol, OrdSpan, Symbol), MoveToAnotherTrait(Symbol), } @@ -923,7 +923,7 @@ impl DynCompatibilityViolationSolution { make_sized_sugg, } => { err.span_suggestion_verbose( - add_self_sugg.1, + add_self_sugg.1.0, format!( "consider turning `{name}` into a method by giving it a `&self` argument, \ so that it is accessible through the trait object's vtable", @@ -932,7 +932,7 @@ impl DynCompatibilityViolationSolution { Applicability::MaybeIncorrect, ); err.span_suggestion_verbose( - make_sized_sugg.1, + make_sized_sugg.1.0, format!( "alternatively, consider constraining `{name}` so it is explicitly marked \ as not applying to trait objects", @@ -943,7 +943,7 @@ impl DynCompatibilityViolationSolution { } DynCompatibilityViolationSolution::ChangeToRefSelf(name, span, lt) => { err.span_suggestion_verbose( - span, + span.0, format!("consider changing method `{name}`'s `self` parameter to be `&self`"), format!("&{lt}{}self", if lt != sym::empty { " " } else { "" }), Applicability::MachineApplicable, diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs index e8cc5dc0edfd3..eebdabd4e7300 100644 --- a/compiler/rustc_mir_build/src/check_unsafety.rs +++ b/compiler/rustc_mir_build/src/check_unsafety.rs @@ -1104,7 +1104,7 @@ pub(crate) fn check_unsafety(tcx: TyCtxt<'_>, def: LocalDefId) { // Visit the body. visitor.visit_expr(&thir[expr]); - warnings.sort_by_key(|w| w.block_span); + warnings.sort_by_key(|w| w.block_span.lo_hi()); for UnusedUnsafeWarning { hir_id, block_span, enclosing_unsafe } in warnings { let block_span = tcx.sess.source_map().guess_head_span(block_span); tcx.emit_node_span_lint( diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs index 381ebdcc15037..8fa5a10a9100b 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs @@ -412,7 +412,7 @@ impl<'p, 'tcx> MatchVisitor<'p, 'tcx> { { let mut redundant_subpats = redundant_subpats.clone(); // Emit lints in the order in which they occur in the file. - redundant_subpats.sort_unstable_by_key(|(pat, _)| pat.data().span); + redundant_subpats.sort_unstable_by_key(|(pat, _)| pat.data().span.lo_hi()); for (pat, explanation) in redundant_subpats { report_unreachable_pattern(cx, arm.arm_data, pat, &explanation, None) } diff --git a/compiler/rustc_mir_transform/src/check_call_recursion.rs b/compiler/rustc_mir_transform/src/check_call_recursion.rs index 9627f8988f283..c90d230a19ffb 100644 --- a/compiler/rustc_mir_transform/src/check_call_recursion.rs +++ b/compiler/rustc_mir_transform/src/check_call_recursion.rs @@ -79,7 +79,7 @@ fn check_recursion<'tcx>( return; } - vis.reachable_recursive_calls.sort(); + vis.reachable_recursive_calls.sort_by_key(|span| span.lo_hi()); let sp = tcx.def_span(def_id); let hir_id = tcx.local_def_id_to_hir_id(def_id); diff --git a/compiler/rustc_monomorphize/src/graph_checks/statics.rs b/compiler/rustc_monomorphize/src/graph_checks/statics.rs index 4a6416843fded..e954077f27972 100644 --- a/compiler/rustc_monomorphize/src/graph_checks/statics.rs +++ b/compiler/rustc_monomorphize/src/graph_checks/statics.rs @@ -100,7 +100,7 @@ pub(super) fn check_static_initializers_are_acyclic<'tcx, 'a, 'b>( // Emit errors for all cycles for nodes in nodes_of_sccs.iter_mut().filter(|nodes| is_cyclic(nodes)) { // We sort the nodes by their Span to have consistent error line numbers - nodes.sort_by_key(|node| tcx.def_span(statics[node.index()])); + nodes.sort_by_key(|node| tcx.def_span(statics[node.index()]).lo_hi()); let head_def = statics[nodes[0].index()]; let head_span = tcx.def_span(head_def); diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4926ec9872d3b..9d05a4d7ca89a 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1210,7 +1210,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { if !reprs.is_empty() { let sorted_reprs = { let mut to_sort = reprs.to_owned(); - to_sort.sort_unstable(); + to_sort.sort_unstable_by_key(|(attr, span)| (*attr, span.lo_hi())); to_sort }; diff --git a/compiler/rustc_query_impl/src/handle_cycle_error.rs b/compiler/rustc_query_impl/src/handle_cycle_error.rs index 83e95b9195580..3f70fc2a6b833 100644 --- a/compiler/rustc_query_impl/src/handle_cycle_error.rs +++ b/compiler/rustc_query_impl/src/handle_cycle_error.rs @@ -223,7 +223,7 @@ fn recursive_type_error( let start_index = item_and_field_ids .iter() .enumerate() - .min_by_key(|&(_, &(id, _))| tcx.def_span(id)) + .min_by_key(|&(_, &(id, _))| tcx.def_span(id).lo_hi()) .unwrap() .0; item_and_field_ids.rotate_left(start_index); diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 331c948c66403..29802b0db0264 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -346,9 +346,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { self.lint_buffer.buffer_lint( MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS, CRATE_NODE_ID, - span_use, + span_use.0, diagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths { - definition: span_def, + definition: span_def.0, }, ); } @@ -943,11 +943,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let BindingError { name, target, origin, could_be_path } = binding_error; let mut target_sp = target.iter().map(|pat| pat.span).collect::>(); - target_sp.sort(); - target_sp.dedup(); + target_sp.sort_by_key(|sp| sp.lo_hi()); + target_sp.dedup_by_key(|sp| sp.lo_hi()); let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::>(); - origin_sp.sort(); - origin_sp.dedup(); + origin_sp.sort_by_key(|sp| sp.lo_hi()); + origin_sp.dedup_by_key(|sp| sp.lo_hi()); let msp = MultiSpan::from_spans(target_sp.clone()); let mut err = self.dcx().create_err(diagnostics::VariableIsNotBoundInAllPatterns { diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index 9faedfeac571b..5b6bf203501f7 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -10,7 +10,7 @@ use rustc_middle::middle::resolve::PartialRes; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext}; -use rustc_span::{Ident, Span, bug, kw, span_bug, sym}; +use rustc_span::{Ident, OrdSpan, Span, bug, kw, span_bug, sym}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -1393,7 +1393,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && let DeclKind::Import { import, .. } = binding.kind && matches!(import.kind, ImportKind::MacroExport) { - self.macro_expanded_macro_export_errors.insert((path_span, binding.span)); + self.macro_expanded_macro_export_errors + .insert((OrdSpan(path_span), OrdSpan(binding.span))); } self.record_use(ident, binding, used); diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index a19207d6fbacc..718b9e7305521 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -20,7 +20,7 @@ use rustc_middle::ty::Visibility; use rustc_session::diagnostics::feature_err; use rustc_span::edit_distance::find_best_match_for_name; use rustc_span::hygiene::LocalExpnId; -use rustc_span::{Ident, Span, Symbol, kw, span_bug, sym}; +use rustc_span::{Ident, OrdSpan, Span, Symbol, kw, span_bug, sym}; use tracing::debug; use crate::Namespace::{self, *}; @@ -1757,7 +1757,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { && !other_binding.is_ambiguity_recursive(); if is_redundant { redundant_span[ns] = - Some((other_binding.span, other_binding.is_import())); + Some((OrdSpan(other_binding.span), other_binding.is_import())); } } Err(_) => is_redundant = false, @@ -1777,7 +1777,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { let ident = source; let subs = redundant_spans .into_iter() - .map(|(span, is_imported)| match (span.is_dummy(), is_imported) { + .map(|(OrdSpan(span), is_imported)| match (span.is_dummy(), is_imported) { (false, true) => { diagnostics::RedundantImportSub::ImportedHere { span, ident } } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 3dbb1b7fff662..f39cbc911edfe 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -113,7 +113,7 @@ fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, Str } /// Description of an elided lifetime. -#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)] +#[derive(Copy, Clone, PartialEq, Eq, Debug)] pub(super) struct MissingLifetime { /// Used to overwrite the resolution with the suggestion, to avoid cascading errors. pub id: NodeId, diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index a913149733614..74ff5e3868e44 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -69,7 +69,7 @@ use rustc_middle::query::Providers; use rustc_middle::ty::{self, RegisteredTools, TyCtxt, TyCtxtFeed, Visibility}; use rustc_span::def_id::{LocalModId, ModId}; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, span_bug, sym}; +use rustc_span::{DUMMY_SP, Ident, OrdSpan, Span, Symbol, bug, kw, span_bug, sym}; use rustc_structures::CrateType; use smallvec::{SmallVec, smallvec}; use tracing::{debug, instrument}; @@ -1431,7 +1431,7 @@ pub struct Resolver<'ra, 'tcx> { /// Visibility path resolution failures are delayed until all modules are collected. delayed_vis_resolution_errors: Vec> = Vec::new(), /// Crate-local macro expanded `macro_export` referred to by a module-relative path. - macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(), + macro_expanded_macro_export_errors: BTreeSet<(OrdSpan, OrdSpan)> = BTreeSet::new(), arenas: &'ra WorkerLocal>, dummy_decl: Decl<'ra>, diff --git a/compiler/rustc_span/Cargo.toml b/compiler/rustc_span/Cargo.toml index 7889e53315361..f8e5e2b48b5f0 100644 --- a/compiler/rustc_span/Cargo.toml +++ b/compiler/rustc_span/Cargo.toml @@ -7,7 +7,6 @@ edition = "2024" # tidy-alphabetical-start bitflags = "2.4.1" blake3 = "1.5.2" -derive-where = "1.2.7" indexmap = { version = "2.0.0" } itoa = "1.0" md5 = { package = "md-5", version = "0.10.0" } diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index 20950c1a5ff87..b03c70726f1b8 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -32,7 +32,6 @@ // this crate without this line making `rustc_span` available. extern crate self as rustc_span; -use derive_where::derive_where; use rustc_data_structures::stable_hash::StableHashCtxt; use rustc_data_structures::{AtomicRef, outline}; use rustc_macros::{Decodable, Encodable, StableHash}; @@ -60,7 +59,7 @@ pub mod def_id; use def_id::{CrateNum, DefId, DefIndex, LOCAL_CRATE, LocalDefId, StableCrateId}; pub mod edit_distance; mod span_encoding; -pub use span_encoding::{DUMMY_SP, Span}; +pub use span_encoding::{DUMMY_SP, OrdSpan, Span}; pub mod symbol; pub use symbol::{ @@ -74,7 +73,6 @@ pub mod profiling; pub mod macros; use std::borrow::Cow; -use std::cmp::{self, Ordering}; use std::fmt::Display; use std::hash::Hash; use std::io::{self, Read}; @@ -82,7 +80,7 @@ use std::ops::{Add, Range, Sub}; use std::path::{Path, PathBuf}; use std::str::FromStr; use std::sync::Arc; -use std::{fmt, iter}; +use std::{cmp, fmt, iter}; pub use macros::{bug, span_bug}; use md5::{Digest, Md5}; @@ -684,22 +682,20 @@ impl FileName { /// sent to other threads, but some pieces of performance infra run in a separate thread. /// Using `Span` is generally preferred. #[derive(Clone, Copy, Hash, PartialEq, Eq)] -#[derive_where(PartialOrd, Ord)] pub struct SpanData { pub lo: BytePos, pub hi: BytePos, /// Information about where the macro came from, if this piece of /// code was created by a macro expansion. - #[derive_where(skip)] - // `SyntaxContext` does not implement `Ord`. - // The other fields are enough to determine in-file order. pub ctxt: SyntaxContext, - #[derive_where(skip)] - // `LocalDefId` does not implement `Ord`. - // The other fields are enough to determine in-file order. pub parent: Option, } +// `SyntaxContext` and `LocalDefId` aren't orderable. See the equivalent negative impls for `Span` +// for more details. +impl !PartialOrd for SpanData {} +impl !Ord for SpanData {} + impl SpanData { #[inline] pub fn span(&self) -> Span { @@ -740,17 +736,6 @@ impl Default for SpanData { } } -impl PartialOrd for Span { - fn partial_cmp(&self, rhs: &Self) -> Option { - Some(self.cmp(rhs)) - } -} -impl Ord for Span { - fn cmp(&self, rhs: &Self) -> Ordering { - Ord::cmp(&self.data(), &rhs.data()) - } -} - impl Span { #[inline] pub fn lo(self) -> BytePos { @@ -773,6 +758,12 @@ impl Span { self.map_ctxt(|_| ctxt) } + #[inline] + pub fn lo_hi(self) -> (BytePos, BytePos) { + let data = self.data(); + (data.lo, data.hi) + } + #[inline] pub fn is_visible(self, sm: &SourceMap) -> bool { !self.is_dummy() && sm.is_span_accessible(self) diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index 64280d5ce4b5e..af6f219b4e58e 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -1,3 +1,6 @@ +use std::cmp::Ordering; +use std::hash::Hash; + use rustc_data_structures::fx::FxIndexSet; use rustc_data_structures::stable_hash::RawSpan; // This code is very hot and uses lots of arithmetic, avoid overflow checks for performance. @@ -85,6 +88,12 @@ pub struct Span { ctxt_or_parent_or_marker: u16, } +// `SyntaxContext` (`SpanData::ctxt`) and `LocalDefId` (within `SpanData::parent`) aren't orderable. +// If you want to order spans just on `lo`/`hi`, use explicit comparisons involving `Span::lo_hi`. +// Or you can wrap your span within `OrdSpan` which impls `PartialOrd`/`Ord` via `Span::lo_hi`. +impl !PartialOrd for Span {} +impl !Ord for Span {} + // Convenience structures for all span formats. #[derive(Clone, Copy)] struct InlineCtxt { @@ -456,6 +465,38 @@ impl Span { } } +/// Span wrapper that provides equality and ordering based only on the `lo`/`hi` fields. Exists +/// because `Span` doesn't impl `PartialOrd`/`Ord` due to the `ctxt` and `parent` fields being +/// unorderable. Useful when storing things in source code order, e.g. in a `BTreeMap`. +#[derive(Clone, Copy, Debug)] +pub struct OrdSpan(pub Span); + +impl PartialEq for OrdSpan { + fn eq(&self, rhs: &Self) -> bool { + // Ignores `ctxt` and `parent` because they are unorderable. + self.0.lo_hi() == rhs.0.lo_hi() + } +} + +impl Eq for OrdSpan {} + +impl PartialOrd for OrdSpan { + fn partial_cmp(&self, rhs: &Self) -> Option { + Some(self.cmp(rhs)) + } +} + +impl Ord for OrdSpan { + fn cmp(&self, rhs: &Self) -> Ordering { + // Ignores `ctxt` and `parent` because they are unorderable. + self.0.lo_hi().cmp(&rhs.0.lo_hi()) + } +} + +// `OrdSpan` is typically stored in types that rely on ordering, such as `BTreeMap` or `SortedMap`. +// Hashing shouldn't be necessary. +impl !Hash for OrdSpan {} + #[derive(Default)] pub(crate) struct SpanInterner { spans: FxIndexSet, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs index 166c320cda28a..e79a05328f132 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/static_impl_trait.rs @@ -73,16 +73,17 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { if mention_influencer { spans.push(sup_origin.span()); } - // We dedup the spans *ignoring* expansion context. - spans.sort(); - spans.dedup_by_key(|span| (span.lo(), span.hi())); + // We sort and dedup the spans *ignoring* expansion context. + spans.sort_by_key(|span| span.lo_hi()); + spans.dedup_by_key(|span| span.lo_hi()); // We try to make the output have fewer overlapping spans if possible. let require_span = if sup_origin.span().overlaps(return_sp) { sup_origin.span() } else { return_sp }; let spans_empty = spans.is_empty(); - let require_as_note = spans.iter().any(|sp| sp.overlaps(return_sp) || *sp > return_sp); + let require_as_note = + spans.iter().any(|sp| sp.overlaps(return_sp) || sp.lo_hi() > return_sp.lo_hi()); let bound = if let SubregionOrigin::RelateParamBound(_, _, Some(bound)) = sub_origin { Some(*bound) } else { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index b9f70cea5f5ab..59ce72eef48fc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -210,12 +210,17 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; // sort the errors by span, for better error message stability. - errors.sort_by_key(|u| match *u { - RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), - RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), - RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => rvo.span(), - RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(), + errors.sort_by_key(|u| { + match *u { + RegionResolutionError::ConcreteFailure(ref sro, _, _) => sro.span(), + RegionResolutionError::GenericBoundFailure(ref sro, _, _) => sro.span(), + RegionResolutionError::SubSupConflict(_, ref rvo, _, _, _, _, _) => rvo.span(), + RegionResolutionError::UpperBoundUniverseConflict(_, ref rvo, _, _, _) => { + rvo.span() + } + RegionResolutionError::CannotNormalize(_, ref sro) => sro.span(), + } + .lo_hi() }); errors } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2fbfae88918a0..b55c9acdf5b15 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -346,7 +346,7 @@ pub(super) fn build_function(cx: &mut DocContext<'_>, def_id: DefId) -> Box ExpandedCodeVisitor<'ast> { } fn compute_expanded(mut self) -> FxHashMap> { - self.expanded_codes.sort_unstable_by(|item1, item2| item1.span.cmp(&item2.span)); + self.expanded_codes.sort_unstable_by_key(|item| item.span.lo_hi()); let mut expanded: FxHashMap> = FxHashMap::default(); for ExpandedCodeInfo { span, code, original_span, .. } in self.expanded_codes { if let Ok(lines) = self.source_map.span_to_lines(span) diff --git a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs index 93f079f7351db..fe0e8c98b46e0 100644 --- a/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs +++ b/src/tools/clippy/clippy_lints/src/disallowed_script_idents.rs @@ -77,7 +77,7 @@ impl EarlyLintPass for DisallowedScriptIdents { // Sort by `Span` so that error messages make sense with respect to the // order of identifier locations in the code. let mut symbols: Vec<_> = symbols.iter().collect(); - symbols.sort_unstable_by_key(|k| k.1); + symbols.sort_unstable_by_key(|k| k.1.lo_hi()); for &(symbol, &span) in &symbols { // Note: `symbol.as_str()` is an expensive operation, thus should not be called diff --git a/src/tools/clippy/clippy_lints/src/format_args.rs b/src/tools/clippy/clippy_lints/src/format_args.rs index 22be9d8367daa..a072e3dfff503 100644 --- a/src/tools/clippy/clippy_lints/src/format_args.rs +++ b/src/tools/clippy/clippy_lints/src/format_args.rs @@ -610,8 +610,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { .any(|(span, _)| self.cx.sess().source_map().is_multiline(*span)); // Suggest removing each argument only once, for example in `format!("{0} {0}", arg)`. - fixes.sort_unstable_by_key(|(span, _)| *span); - fixes.dedup_by_key(|(span, _)| *span); + fixes.sort_unstable_by_key(|(span, _)| span.lo_hi()); + fixes.dedup_by_key(|(span, _)| span.lo_hi()); span_lint_and_then( self.cx, diff --git a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs index 02f8170fedc27..b511caf6b5299 100644 --- a/src/tools/clippy/clippy_lints/src/implicit_hasher.rs +++ b/src/tools/clippy/clippy_lints/src/implicit_hasher.rs @@ -9,7 +9,7 @@ use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{Ty, TypeckResults}; -use rustc_span::Span; +use rustc_span::{OrdSpan, Span}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{IntoSpan as _, SpanExt as _, snippet, snippet_with_context}; @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { format!("{}<{}, S>", target.type_name(), target.type_arguments()), ), ]; - suggestions.extend(vis.suggestions); + suggestions.extend(vis.suggestions.into_iter().map(|(span, s)| (span.0, s))); diag.multipart_suggestion( "add a type parameter for `BuildHasher`", @@ -295,7 +295,7 @@ struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, target: &'b ImplicitHasherType<'tcx>, - suggestions: BTreeMap, + suggestions: BTreeMap, } impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { @@ -337,7 +337,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { match method.ident.name { sym::new => { - self.suggestions.insert(e.span, format!("{container_name}::default()")); + self.suggestions.insert(OrdSpan(e.span), format!("{container_name}::default()")); }, sym::with_capacity => { let (arg_snippet, _) = snippet_with_context( @@ -350,7 +350,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { &mut Applicability::MaybeIncorrect, ); self.suggestions.insert( - e.span, + OrdSpan(e.span), format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())"), ); }, diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs index 73e430fa08d6b..8b6c99cc122c9 100644 --- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs +++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs @@ -1,3 +1,5 @@ +use std::cmp::max_by_key; + use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; @@ -96,7 +98,9 @@ fn emit_lint( // `<>` needs to be added if there aren't yet any generic arguments or constraints let needs_angle_brackets = bound.args.is_empty() && bound.constraints.is_empty(); let insert_span = match (bound.args, bound.constraints) { - ([.., arg], [.., constraint]) => arg.span().max(constraint.span).shrink_to_hi(), + ([.., arg], [.., constraint]) => { + max_by_key(arg.span(), constraint.span, |span| span.lo_hi()).shrink_to_hi() + } ([.., arg], []) => arg.span().shrink_to_hi(), ([], [.., constraint]) => constraint.span.shrink_to_hi(), ([], []) => bound.span.shrink_to_hi(), diff --git a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs index 8242c383140a6..82af5d67e6f23 100644 --- a/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/src/tools/clippy/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; -use rustc_span::{Span, SyntaxContext}; +use rustc_span::{OrdSpan, Span, SyntaxContext}; use std::collections::BTreeMap; use std::collections::btree_map::Entry; @@ -106,7 +106,7 @@ pub struct ExprMetavarsInUnsafe { /// } /// } /// ``` - metavar_expns: BTreeMap, + metavar_expns: BTreeMap, } impl ExprMetavarsInUnsafe { @@ -180,7 +180,7 @@ impl<'tcx> Visitor<'tcx> for BodyVisitor<'_, 'tcx> { } else if ctxt.is_root() && self.expn_depth > 0 { let unsafe_block = self.macro_unsafe_blocks.last().copied(); - match (self.lint.metavar_expns.entry(e.span), unsafe_block) { + match (self.lint.metavar_expns.entry(OrdSpan(e.span)), unsafe_block) { (Entry::Vacant(e), None) => { e.insert(MetavarState::ReferencedInSafe); }, diff --git a/src/tools/clippy/clippy_lints/src/macro_use.rs b/src/tools/clippy/clippy_lints/src/macro_use.rs index 6f06e8665decc..9efc3b2edb515 100644 --- a/src/tools/clippy/clippy_lints/src/macro_use.rs +++ b/src/tools/clippy/clippy_lints/src/macro_use.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, AmbigArg}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; -use rustc_span::Span; +use rustc_span::{OrdSpan, Span}; use rustc_span::edition::Edition; use std::collections::BTreeMap; @@ -151,7 +151,7 @@ impl LateLintPass<'_> for MacroUseImports { if !check_dup.contains(&(*item).to_string()) { used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -175,7 +175,7 @@ impl LateLintPass<'_> for MacroUseImports { .collect::>(); used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -187,7 +187,7 @@ impl LateLintPass<'_> for MacroUseImports { let rest = rest.to_vec(); used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -215,11 +215,11 @@ impl LateLintPass<'_> for MacroUseImports { cx, MACRO_USE_IMPORTS, *hir_id, - *span, + span.0, "`macro_use` attributes are no longer needed in the Rust 2018 edition", |diag| { diag.span_suggestion( - *span, + span.0, "remove the attribute and import the macro directly, try", format!("use {import};"), Applicability::MaybeIncorrect, diff --git a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs index b58ceb263be22..7dfe8202a12d4 100644 --- a/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs +++ b/src/tools/clippy/clippy_lints/src/methods/map_unwrap_or.rs @@ -187,7 +187,7 @@ impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { // If we haven't found a reference yet, check if this references // one of the locals that was moved in the `unwrap_or` argument. // We are only interested in exprs that appear before the `unwrap_or` call. - if expr.span < self.unwrap_or_span + if expr.span.lo_hi() < self.unwrap_or_span.lo_hi() && let ExprKind::Path(ref path) = expr.kind && let QPath::Resolved(_, path) = path && let Res::Local(local_id) = path.res diff --git a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs index edb1c9c53ded7..c7207bb4dd4bc 100644 --- a/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs +++ b/src/tools/clippy/clippy_lints/src/methods/unnecessary_fold.rs @@ -373,7 +373,7 @@ fn check_option_fold<'tcx>( // `.iter().fold(` -> `.as_ref().map_or(`, drop the accumulator // parameter, and substitute `init` for each use of the accumulator. - acc_uses.sort(); + acc_uses.sort_by_key(|span| span.lo_hi()); let mut parts = vec![ ( recv.span.with_lo(option_expr.span.hi()).with_hi(init.span.lo()), diff --git a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs index bf649ff5e249c..19c3abd2576f6 100644 --- a/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/src/tools/clippy/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -122,7 +122,7 @@ impl<'tcx> UnsafeExprCollector<'tcx> { .into_iter() .map(|(span, msg)| (msg, span)) .collect::>(); - unsafe_ops.sort_unstable(); + unsafe_ops.sort_unstable_by_key(|(s, span)| (*s, span.lo_hi())); unsafe_ops } diff --git a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs index 968f6ad679b59..47708e8f02d19 100644 --- a/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs +++ b/src/tools/clippy/clippy_lints/src/operators/cmp_owned.rs @@ -111,7 +111,7 @@ fn check_op(cx: &LateContext<'_>, outer: &Expr<'_>, expr: &Expr<'_>, other: &Exp } else { let span = expr.span.to(other.span); - let cmp_span = if other.span < expr.span { + let cmp_span = if other.span.lo_hi() < expr.span.lo_hi() { other.span.between(expr.span) } else { expr.span.between(other.span) diff --git a/src/tools/clippy/clippy_lints/src/useless_vec.rs b/src/tools/clippy/clippy_lints/src/useless_vec.rs index 3d2f47cee4670..0b526010d2cce 100644 --- a/src/tools/clippy/clippy_lints/src/useless_vec.rs +++ b/src/tools/clippy/clippy_lints/src/useless_vec.rs @@ -16,7 +16,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pa use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; -use rustc_span::{DesugaringKind, Span}; +use rustc_span::{DesugaringKind, OrdSpan, Span}; pub struct UselessVec { too_large_for_stack: u64, @@ -41,7 +41,7 @@ pub struct UselessVec { /// the first `vec![1, 2]` (which is shared with the other expn) to an array which indeed would /// work, we get a false positive warning on the `$v.push(3)` which really requires `$v` to /// be a vector. - span_to_state: BTreeMap, + span_to_state: BTreeMap, allow_in_test: bool, } @@ -223,7 +223,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { }, }; - if let Entry::Vacant(entry) = self.span_to_state.entry(vec_span) { + if let Entry::Vacant(entry) = self.span_to_state.entry(OrdSpan(vec_span)) { entry.insert(VecState::Change { suggest_ty, vec_snippet, @@ -232,7 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } }, VecToArray::Impossible => { - self.span_to_state.insert(vec_span, VecState::NoChange); + self.span_to_state.insert(OrdSpan(vec_span), VecState::NoChange); }, } } @@ -246,6 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { expr_hir_id, } = state { + let span = span.0; span_lint_hir_and_then(cx, USELESS_VEC, expr_hir_id, span, "useless use of `vec!`", |diag| { let help_msg = format!("you can use {} directly", suggest_ty.desc()); // If the `vec!` macro contains comment, better not make the suggestion machine applicable as it diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 25c659f7b3ae9..5587fbbcaed1f 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -171,15 +171,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Make sure we are consistent wrt what is 'first' and 'second'. let original_span = - tcx.def_span(original.instance.def_id()).data(); - let span = tcx.def_span(def_id).data(); - if original_span < span { + tcx.def_span(original.instance.def_id()); + let span = tcx.def_span(def_id); + if original_span.lo_hi() < span.lo_hi() { throw_machine_stop!( TerminationInfo::MultipleSymbolDefinitions { link_name, - first: original_span, + first: original_span.data(), first_crate: tcx.crate_name(original.cnum), - second: span, + second: span.data(), second_crate: tcx.crate_name(cnum), } ); @@ -187,9 +187,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_machine_stop!( TerminationInfo::MultipleSymbolDefinitions { link_name, - first: span, + first: span.data(), first_crate: tcx.crate_name(cnum), - second: original_span, + second: original_span.data(), second_crate: tcx.crate_name(original.cnum), } ); From a0f3d38a294a28956d999097741bba0f55765ae9 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 23 Sep 2026 22:15:02 +1000 Subject: [PATCH 0872/1309] Remove `PartialOrd`/`Ord` impls for `Span`/`SpanData` `Span` and `SpanData` encode four fields: `lo`/`hi`, `ctxt`, and `parent`. `ctxt` and `parent` have unorderable types. Both types ignore `ctxt` and `parent` for `PartialOrd`/`Ord`. But their `PartialEq`/`Eq` impls do *not* ignore those fields. This eq/ord inconsistency is a bug. It was introduced in #123165. The idea of ordering spans in general is dubious, because of `ctxt` and `parent`. But the idea of ordering spans just with `lo`/`hi` is fine. Therefore, this commit does the following. - Removes the `PartialOrd`/`Ord` impls for `Span`/`SpanData` - Adds a `Span::lo_hi` method which can be used in lots of places where span locations are involved in sorting. E.g. `xs.sort_by_key(|span| span.lo_hi())` - Adds `OrdSpan`, a newtype around `Span` that impls `PartialEq`/`Eq`/`PartialOrd`/`Ord` using `lo_hi`. This is for storing spans in ordered types like `BTreeMap`. Note also that some `sort`+`dedup` combinations might not remove all duplicates with the old eq/ord inconsistency. These now all do the right thing, which could affect some error messages, though in practice nothing in the test suite is affected. --- clippy_lints/src/disallowed_script_idents.rs | 2 +- clippy_lints/src/format_args.rs | 4 ++-- clippy_lints/src/implicit_hasher.rs | 10 +++++----- clippy_lints/src/implied_bounds_in_impls.rs | 6 +++++- clippy_lints/src/macro_metavars_in_unsafe.rs | 6 +++--- clippy_lints/src/macro_use.rs | 12 ++++++------ clippy_lints/src/methods/map_unwrap_or.rs | 2 +- clippy_lints/src/methods/unnecessary_fold.rs | 2 +- clippy_lints/src/multiple_unsafe_ops_per_block.rs | 2 +- clippy_lints/src/operators/cmp_owned.rs | 2 +- clippy_lints/src/useless_vec.rs | 9 +++++---- 11 files changed, 31 insertions(+), 26 deletions(-) diff --git a/clippy_lints/src/disallowed_script_idents.rs b/clippy_lints/src/disallowed_script_idents.rs index 93f079f7351db..fe0e8c98b46e0 100644 --- a/clippy_lints/src/disallowed_script_idents.rs +++ b/clippy_lints/src/disallowed_script_idents.rs @@ -77,7 +77,7 @@ impl EarlyLintPass for DisallowedScriptIdents { // Sort by `Span` so that error messages make sense with respect to the // order of identifier locations in the code. let mut symbols: Vec<_> = symbols.iter().collect(); - symbols.sort_unstable_by_key(|k| k.1); + symbols.sort_unstable_by_key(|k| k.1.lo_hi()); for &(symbol, &span) in &symbols { // Note: `symbol.as_str()` is an expensive operation, thus should not be called diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 22be9d8367daa..a072e3dfff503 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -610,8 +610,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { .any(|(span, _)| self.cx.sess().source_map().is_multiline(*span)); // Suggest removing each argument only once, for example in `format!("{0} {0}", arg)`. - fixes.sort_unstable_by_key(|(span, _)| *span); - fixes.dedup_by_key(|(span, _)| *span); + fixes.sort_unstable_by_key(|(span, _)| span.lo_hi()); + fixes.dedup_by_key(|(span, _)| span.lo_hi()); span_lint_and_then( self.cx, diff --git a/clippy_lints/src/implicit_hasher.rs b/clippy_lints/src/implicit_hasher.rs index 02f8170fedc27..b511caf6b5299 100644 --- a/clippy_lints/src/implicit_hasher.rs +++ b/clippy_lints/src/implicit_hasher.rs @@ -9,7 +9,7 @@ use rustc_hir_analysis::lower_ty; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{Ty, TypeckResults}; -use rustc_span::Span; +use rustc_span::{OrdSpan, Span}; use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::{IntoSpan as _, SpanExt as _, snippet, snippet_with_context}; @@ -94,7 +94,7 @@ impl<'tcx> LateLintPass<'tcx> for ImplicitHasher { format!("{}<{}, S>", target.type_name(), target.type_arguments()), ), ]; - suggestions.extend(vis.suggestions); + suggestions.extend(vis.suggestions.into_iter().map(|(span, s)| (span.0, s))); diag.multipart_suggestion( "add a type parameter for `BuildHasher`", @@ -295,7 +295,7 @@ struct ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { cx: &'a LateContext<'tcx>, maybe_typeck_results: Option<&'tcx TypeckResults<'tcx>>, target: &'b ImplicitHasherType<'tcx>, - suggestions: BTreeMap, + suggestions: BTreeMap, } impl<'a, 'b, 'tcx> ImplicitHasherConstructorVisitor<'a, 'b, 'tcx> { @@ -337,7 +337,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { match method.ident.name { sym::new => { - self.suggestions.insert(e.span, format!("{container_name}::default()")); + self.suggestions.insert(OrdSpan(e.span), format!("{container_name}::default()")); }, sym::with_capacity => { let (arg_snippet, _) = snippet_with_context( @@ -350,7 +350,7 @@ impl<'tcx> Visitor<'tcx> for ImplicitHasherConstructorVisitor<'_, '_, 'tcx> { &mut Applicability::MaybeIncorrect, ); self.suggestions.insert( - e.span, + OrdSpan(e.span), format!("{container_name}::with_capacity_and_hasher({arg_snippet}, Default::default())"), ); }, diff --git a/clippy_lints/src/implied_bounds_in_impls.rs b/clippy_lints/src/implied_bounds_in_impls.rs index 73e430fa08d6b..8b6c99cc122c9 100644 --- a/clippy_lints/src/implied_bounds_in_impls.rs +++ b/clippy_lints/src/implied_bounds_in_impls.rs @@ -1,3 +1,5 @@ +use std::cmp::max_by_key; + use clippy_utils::diagnostics::span_lint_and_then; use clippy_utils::source::snippet; use rustc_errors::{Applicability, SuggestionStyle}; @@ -96,7 +98,9 @@ fn emit_lint( // `<>` needs to be added if there aren't yet any generic arguments or constraints let needs_angle_brackets = bound.args.is_empty() && bound.constraints.is_empty(); let insert_span = match (bound.args, bound.constraints) { - ([.., arg], [.., constraint]) => arg.span().max(constraint.span).shrink_to_hi(), + ([.., arg], [.., constraint]) => { + max_by_key(arg.span(), constraint.span, |span| span.lo_hi()).shrink_to_hi() + } ([.., arg], []) => arg.span().shrink_to_hi(), ([], [.., constraint]) => constraint.span.shrink_to_hi(), ([], []) => bound.span.shrink_to_hi(), diff --git a/clippy_lints/src/macro_metavars_in_unsafe.rs b/clippy_lints/src/macro_metavars_in_unsafe.rs index 8242c383140a6..82af5d67e6f23 100644 --- a/clippy_lints/src/macro_metavars_in_unsafe.rs +++ b/clippy_lints/src/macro_metavars_in_unsafe.rs @@ -7,7 +7,7 @@ use rustc_hir::def_id::LocalDefId; use rustc_hir::intravisit::{Visitor, walk_block, walk_expr, walk_stmt}; use rustc_hir::{BlockCheckMode, Expr, ExprKind, HirId, Stmt, UnsafeSource}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; -use rustc_span::{Span, SyntaxContext}; +use rustc_span::{OrdSpan, Span, SyntaxContext}; use std::collections::BTreeMap; use std::collections::btree_map::Entry; @@ -106,7 +106,7 @@ pub struct ExprMetavarsInUnsafe { /// } /// } /// ``` - metavar_expns: BTreeMap, + metavar_expns: BTreeMap, } impl ExprMetavarsInUnsafe { @@ -180,7 +180,7 @@ impl<'tcx> Visitor<'tcx> for BodyVisitor<'_, 'tcx> { } else if ctxt.is_root() && self.expn_depth > 0 { let unsafe_block = self.macro_unsafe_blocks.last().copied(); - match (self.lint.metavar_expns.entry(e.span), unsafe_block) { + match (self.lint.metavar_expns.entry(OrdSpan(e.span)), unsafe_block) { (Entry::Vacant(e), None) => { e.insert(MetavarState::ReferencedInSafe); }, diff --git a/clippy_lints/src/macro_use.rs b/clippy_lints/src/macro_use.rs index 6f06e8665decc..9efc3b2edb515 100644 --- a/clippy_lints/src/macro_use.rs +++ b/clippy_lints/src/macro_use.rs @@ -6,7 +6,7 @@ use rustc_errors::Applicability; use rustc_hir::def::{DefKind, Res}; use rustc_hir::{self as hir, AmbigArg}; use rustc_lint::{LateContext, LateLintPass, LintContext as _, impl_lint_pass}; -use rustc_span::Span; +use rustc_span::{OrdSpan, Span}; use rustc_span::edition::Edition; use std::collections::BTreeMap; @@ -151,7 +151,7 @@ impl LateLintPass<'_> for MacroUseImports { if !check_dup.contains(&(*item).to_string()) { used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -175,7 +175,7 @@ impl LateLintPass<'_> for MacroUseImports { .collect::>(); used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -187,7 +187,7 @@ impl LateLintPass<'_> for MacroUseImports { let rest = rest.to_vec(); used.entry(( (*root).to_string(), - span, + OrdSpan(*span), hir_id.local_id, cx.tcx.def_path_hash(hir_id.owner.def_id.into()), )) @@ -215,11 +215,11 @@ impl LateLintPass<'_> for MacroUseImports { cx, MACRO_USE_IMPORTS, *hir_id, - *span, + span.0, "`macro_use` attributes are no longer needed in the Rust 2018 edition", |diag| { diag.span_suggestion( - *span, + span.0, "remove the attribute and import the macro directly, try", format!("use {import};"), Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/methods/map_unwrap_or.rs b/clippy_lints/src/methods/map_unwrap_or.rs index b58ceb263be22..7dfe8202a12d4 100644 --- a/clippy_lints/src/methods/map_unwrap_or.rs +++ b/clippy_lints/src/methods/map_unwrap_or.rs @@ -187,7 +187,7 @@ impl<'tcx> Visitor<'tcx> for ReferenceVisitor<'_, 'tcx> { // If we haven't found a reference yet, check if this references // one of the locals that was moved in the `unwrap_or` argument. // We are only interested in exprs that appear before the `unwrap_or` call. - if expr.span < self.unwrap_or_span + if expr.span.lo_hi() < self.unwrap_or_span.lo_hi() && let ExprKind::Path(ref path) = expr.kind && let QPath::Resolved(_, path) = path && let Res::Local(local_id) = path.res diff --git a/clippy_lints/src/methods/unnecessary_fold.rs b/clippy_lints/src/methods/unnecessary_fold.rs index edb1c9c53ded7..c7207bb4dd4bc 100644 --- a/clippy_lints/src/methods/unnecessary_fold.rs +++ b/clippy_lints/src/methods/unnecessary_fold.rs @@ -373,7 +373,7 @@ fn check_option_fold<'tcx>( // `.iter().fold(` -> `.as_ref().map_or(`, drop the accumulator // parameter, and substitute `init` for each use of the accumulator. - acc_uses.sort(); + acc_uses.sort_by_key(|span| span.lo_hi()); let mut parts = vec![ ( recv.span.with_lo(option_expr.span.hi()).with_hi(init.span.lo()), diff --git a/clippy_lints/src/multiple_unsafe_ops_per_block.rs b/clippy_lints/src/multiple_unsafe_ops_per_block.rs index bf649ff5e249c..19c3abd2576f6 100644 --- a/clippy_lints/src/multiple_unsafe_ops_per_block.rs +++ b/clippy_lints/src/multiple_unsafe_ops_per_block.rs @@ -122,7 +122,7 @@ impl<'tcx> UnsafeExprCollector<'tcx> { .into_iter() .map(|(span, msg)| (msg, span)) .collect::>(); - unsafe_ops.sort_unstable(); + unsafe_ops.sort_unstable_by_key(|(s, span)| (*s, span.lo_hi())); unsafe_ops } diff --git a/clippy_lints/src/operators/cmp_owned.rs b/clippy_lints/src/operators/cmp_owned.rs index 968f6ad679b59..47708e8f02d19 100644 --- a/clippy_lints/src/operators/cmp_owned.rs +++ b/clippy_lints/src/operators/cmp_owned.rs @@ -111,7 +111,7 @@ fn check_op(cx: &LateContext<'_>, outer: &Expr<'_>, expr: &Expr<'_>, other: &Exp } else { let span = expr.span.to(other.span); - let cmp_span = if other.span < expr.span { + let cmp_span = if other.span.lo_hi() < expr.span.lo_hi() { other.span.between(expr.span) } else { expr.span.between(other.span) diff --git a/clippy_lints/src/useless_vec.rs b/clippy_lints/src/useless_vec.rs index 3d2f47cee4670..0b526010d2cce 100644 --- a/clippy_lints/src/useless_vec.rs +++ b/clippy_lints/src/useless_vec.rs @@ -16,7 +16,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, LetStmt, Mutability, Node, Pa use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; -use rustc_span::{DesugaringKind, Span}; +use rustc_span::{DesugaringKind, OrdSpan, Span}; pub struct UselessVec { too_large_for_stack: u64, @@ -41,7 +41,7 @@ pub struct UselessVec { /// the first `vec![1, 2]` (which is shared with the other expn) to an array which indeed would /// work, we get a false positive warning on the `$v.push(3)` which really requires `$v` to /// be a vector. - span_to_state: BTreeMap, + span_to_state: BTreeMap, allow_in_test: bool, } @@ -223,7 +223,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { }, }; - if let Entry::Vacant(entry) = self.span_to_state.entry(vec_span) { + if let Entry::Vacant(entry) = self.span_to_state.entry(OrdSpan(vec_span)) { entry.insert(VecState::Change { suggest_ty, vec_snippet, @@ -232,7 +232,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { } }, VecToArray::Impossible => { - self.span_to_state.insert(vec_span, VecState::NoChange); + self.span_to_state.insert(OrdSpan(vec_span), VecState::NoChange); }, } } @@ -246,6 +246,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessVec { expr_hir_id, } = state { + let span = span.0; span_lint_hir_and_then(cx, USELESS_VEC, expr_hir_id, span, "useless use of `vec!`", |diag| { let help_msg = format!("you can use {} directly", suggest_ty.desc()); // If the `vec!` macro contains comment, better not make the suggestion machine applicable as it From 1b8ac4710bdf796e1b37d66024dbbec06f4e337b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 24 Sep 2026 18:48:08 +1000 Subject: [PATCH 0873/1309] Remove `Span::source_equal` It can be replaced with `Span::lo_hi` + `==`. --- .../src/diagnostics/conflict_errors.rs | 2 +- compiler/rustc_hir_typeck/src/demand.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs | 2 +- compiler/rustc_lint/src/non_fmt_panic.rs | 2 +- .../rustc_mir_transform/src/coverage/spans.rs | 4 ++-- compiler/rustc_span/src/lib.rs | 16 +++++----------- .../error_reporting/traits/fulfillment_errors.rs | 3 ++- 7 files changed, 13 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 132f074f9e0f9..ec751d6b3e199 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -2544,7 +2544,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { if let hir::ExprKind::MethodCall(body_call, recv, ..) = ex.kind && body_call.ident.name == sym::next - && recv.span.source_equal(self.expr_span) + && recv.span.lo_hi() == self.expr_span.lo_hi() { self.body_expr = Some(ex); } diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 55eecef732aa4..efe3b4efc0ff1 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -734,7 +734,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { match (parent, error) { (hir::Node::LetStmt(hir::LetStmt { ty: Some(ty), init: Some(init), .. }), _) - if init.hir_id == current_hir_id && !ty.span.source_equal(init.span) => + if init.hir_id == current_hir_id && ty.span.lo_hi() != init.span.lo_hi() => { // Point at `let` assignment type. err.span_label(ty.span, "expected due to this"); diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs index 789d06722f897..29b1d5fe315e8 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs @@ -3311,7 +3311,7 @@ impl<'a, 'tcx> ArgsCtxt<'a, 'tcx> { // Sometimes macros mess up the spans, so do not normalize the // arg span to equal the error span, because that's less useful // than pointing out the arg expr in the wrong context. - if normalized_span.source_equal(self.call_metadata.error_span) { + if normalized_span.lo_hi() == self.call_metadata.error_span.lo_hi() { span } else { normalized_span diff --git a/compiler/rustc_lint/src/non_fmt_panic.rs b/compiler/rustc_lint/src/non_fmt_panic.rs index 6598110cbfa8f..6fd65af794ac6 100644 --- a/compiler/rustc_lint/src/non_fmt_panic.rs +++ b/compiler/rustc_lint/src/non_fmt_panic.rs @@ -367,5 +367,5 @@ fn is_arg_inside_call(arg: Span, call: Span) -> bool { // panic call in the source file, to avoid invalid suggestions when macros are involved. // We specifically check for the spans to not be identical, as that happens sometimes when // proc_macros lie about spans and apply the same span to all the tokens they produce. - call.contains(arg) && !call.source_equal(arg) + call.contains(arg) && call.lo_hi() != arg.lo_hi() } diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs index ade8bb7865dda..9aa5f3b9f5ab2 100644 --- a/compiler/rustc_mir_transform/src/coverage/spans.rs +++ b/compiler/rustc_mir_transform/src/coverage/spans.rs @@ -50,7 +50,7 @@ pub(super) fn extract_refined_covspans<'tcx>( // Discard any spans not contained within the function body span. // Also discard any spans that fill the entire body, because they tend // to represent compiler-inserted code, e.g. implicitly returning `()`. - if !body_span.contains(covspan_span) || body_span.source_equal(covspan_span) { + if !body_span.contains(covspan_span) || body_span.lo_hi() == covspan_span.lo_hi() { return false; } @@ -91,7 +91,7 @@ pub(super) fn extract_refined_covspans<'tcx>( // preferring the one with the most-dominated BCB. // (Ideally we should try to preserve _all_ non-dominating BCBs, but that // requires a lot more complexity in the span refiner, for little benefit.) - covspans.dedup_by(|b, a| a.span.source_equal(b.span)); + covspans.dedup_by_key(|a| a.span.lo_hi()); // Sort the holes, and merge overlapping/adjacent holes. let mut holes = node.hole_spans.iter().copied().map(|span| Hole { span }).collect::>(); diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs index b03c70726f1b8..ddec29eca6517 100644 --- a/compiler/rustc_span/src/lib.rs +++ b/compiler/rustc_span/src/lib.rs @@ -758,6 +758,10 @@ impl Span { self.map_ctxt(|_| ctxt) } + /// When to use this: + /// - Use it instead of `==` for span equality comparisons when either span could be generated + /// code and you only care that they point to the same bytes of source text. + /// - Use it (possibly via `OrdSpan`) for span ordering comparisons of any kind. #[inline] pub fn lo_hi(self) -> (BytePos, BytePos) { let data = self.data(); @@ -852,16 +856,6 @@ impl Span { span.lo <= other.hi && other.lo <= span.hi } - /// Returns `true` if the spans are equal with regards to the source text. - /// - /// Use this instead of `==` when either span could be generated code, - /// and you only care that they point to the same bytes of source text. - pub fn source_equal(self, other: Span) -> bool { - let span = self.data(); - let other = other.data(); - span.lo == other.lo && span.hi == other.hi - } - /// Returns `Some(span)`, where the start is trimmed by the end of `other`. pub fn trim_start(self, other: Span) -> Option { let span = self.data(); @@ -1075,7 +1069,7 @@ impl Span { } let expn_data = ctxt.outer_expn_data(); - let is_recursive = expn_data.call_site.source_equal(prev_span); + let is_recursive = expn_data.call_site.lo_hi() == prev_span.lo_hi(); prev_span = self; self = expn_data.call_site; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 062b087413e4f..0da4b7d9030b4 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -1178,7 +1178,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { type Result = ControlFlow<&'v hir::Expr<'v>>; fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) -> Self::Result { if let hir::ExprKind::Match(expr, _arms, hir::MatchSource::TryDesugar(_)) = ex.kind - && ex.span.with_lo(ex.span.hi() - BytePos(1)).source_equal(self.search_span) + && ex.span.with_lo(ex.span.hi() - BytePos(1)).lo_hi() + == self.search_span.lo_hi() && let hir::ExprKind::Call(_, [expr, ..]) = expr.kind { ControlFlow::Break(expr) From d35f696938801bcdada7ce07b691610579a61265 Mon Sep 17 00:00:00 2001 From: Yukang Date: Fri, 25 Sep 2026 12:17:55 +0800 Subject: [PATCH 0874/1309] fix unused_must_use suggestion for scenario which may need to keep value --- compiler/rustc_lint/src/diagnostics.rs | 21 ++++++ compiler/rustc_lint/src/unused/must_use.rs | 73 +++++++++++++++---- .../lint/unused/must-use-box-from-raw.stderr | 6 +- .../must-use-lock-guard-issue-162843.fixed | 41 +++++++++++ .../must-use-lock-guard-issue-162843.rs | 40 ++++++++-- .../must-use-lock-guard-issue-162843.stderr | 56 ++++++++------ .../must_use-result-unit-uninhabited.stderr | 6 +- tests/ui/lint/unused/unused-async.stderr | 12 +-- 8 files changed, 197 insertions(+), 58 deletions(-) create mode 100644 tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 98a11f8e1df08..464423b303f4f 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -2709,6 +2709,27 @@ pub(crate) enum UnusedDefSuggestion { #[suggestion_part(code = ";")] after_span: Span, }, + #[suggestion( + "use `let _unused = ...` to ignore the resulting value without dropping it immediately", + style = "verbose", + code = "let _unused = ", + applicability = "maybe-incorrect" + )] + BindingExpr { + #[primary_span] + span: Span, + }, + #[multipart_suggestion( + "use `let _unused = ...` to ignore the resulting value without dropping it immediately", + style = "verbose", + applicability = "maybe-incorrect" + )] + BindingBlockTailExpr { + #[suggestion_part(code = "let _unused = ")] + before_span: Span, + #[suggestion_part(code = ";")] + after_span: Span, + }, } // Needed because of def_path_str diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index dab842a688ae1..89e3981b965f2 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -299,6 +299,9 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } + let ty = cx.typeck_results().expr_ty(expr); + let needs_binding = ty.has_significant_drop(cx.tcx, cx.typing_env()); + if let hir::ExprKind::Match(await_expr, _arms, hir::MatchSource::AwaitDesugar) = expr.kind && let ty = cx.typeck_results().expr_ty(await_expr) && let ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id: future_def_id }, .. }) = ty.kind() @@ -314,6 +317,7 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { "output of future returned by ", "", expr_is_from_block, + needs_binding, ) { // We have a bare `foo().await;` on an opaque type from an async function that was @@ -321,19 +325,26 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { return; } - let ty = cx.typeck_results().expr_ty(expr); - let must_use_result = is_ty_must_use(cx, ty, expr); let type_lint_emitted_or_trivial = match must_use_result { IsTyMustUse::Yes(path) => { - emit_must_use_untranslated(cx, &path, "", "", 1, false, expr_is_from_block); + emit_must_use_untranslated( + cx, + &path, + "", + "", + 1, + false, + expr_is_from_block, + needs_binding, + ); true } IsTyMustUse::Trivial => true, IsTyMustUse::No => false, }; - let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block); + let fn_warned = check_fn_must_use(cx, expr, expr_is_from_block, needs_binding); if !fn_warned && type_lint_emitted_or_trivial { // We don't warn about unused unit or uninhabited types. @@ -415,7 +426,12 @@ impl<'tcx> LateLintPass<'tcx> for UnusedResults { /// Checks if `expr` is a \[method\] call expression marked as `#[must_use]` and emits a lint if so. /// Returns `true` if the lint has been emitted. -fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expr_is_from_block: bool) -> bool { +fn check_fn_must_use( + cx: &LateContext<'_>, + expr: &hir::Expr<'_>, + expr_is_from_block: bool, + needs_binding: bool, +) -> bool { let maybe_def_id = match expr.kind { hir::ExprKind::Call(callee, _) => { if let hir::ExprKind::Path(ref qpath) = callee.kind @@ -434,9 +450,15 @@ fn check_fn_must_use(cx: &LateContext<'_>, expr: &hir::Expr<'_>, expr_is_from_bl }; match maybe_def_id { - Some(def_id) => { - check_must_use_def(cx, def_id, expr.span, "return value of ", "", expr_is_from_block) - } + Some(def_id) => check_must_use_def( + cx, + def_id, + expr.span, + "return value of ", + "", + expr_is_from_block, + needs_binding, + ), None => false, } } @@ -455,6 +477,7 @@ fn check_must_use_def( descr_pre_path: &str, descr_post_path: &str, expr_is_from_block: bool, + needs_binding: bool, ) -> bool { is_def_must_use(cx, def_id, span) .map(|must_use_path| { @@ -466,6 +489,7 @@ fn check_must_use_def( 1, false, expr_is_from_block, + needs_binding, ) }) .is_some() @@ -480,6 +504,7 @@ fn emit_must_use_untranslated( plural_len: usize, is_inner: bool, expr_is_from_block: bool, + needs_binding: bool, ) { let plural_suffix = pluralize!(plural_len); @@ -494,6 +519,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Pinned(path) => { @@ -506,6 +532,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Opaque(path) => { @@ -518,6 +545,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::TraitObject(path) => { @@ -530,6 +558,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::TupleElement(elems) => { @@ -543,6 +572,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } } @@ -556,6 +586,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::ControlFlow(path) => { @@ -568,6 +599,7 @@ fn emit_must_use_untranslated( plural_len, true, expr_is_from_block, + needs_binding, ); } MustUsePath::Array(path, len) => { @@ -580,6 +612,7 @@ fn emit_must_use_untranslated( plural_len.saturating_add(usize::try_from(*len).unwrap_or(usize::MAX)), true, expr_is_from_block, + needs_binding, ); } MustUsePath::Closure(span) => { @@ -615,14 +648,24 @@ fn emit_must_use_untranslated( cx, def_id: *def_id, note: *reason, - suggestion: (!is_inner).then_some(if expr_is_from_block { - UnusedDefSuggestion::BlockTailExpr { - before_span: suggestion_span.shrink_to_lo(), - after_span: suggestion_span.shrink_to_hi(), - } + suggestion: if is_inner { + None } else { - UnusedDefSuggestion::NormalExpr { span: suggestion_span.shrink_to_lo() } - }), + let lo = suggestion_span.shrink_to_lo(); + let hi = suggestion_span.shrink_to_hi(); + Some(match (needs_binding, expr_is_from_block) { + (true, true) => UnusedDefSuggestion::BindingBlockTailExpr { + before_span: lo, + after_span: hi, + }, + (true, false) => UnusedDefSuggestion::BindingExpr { span: lo }, + (false, true) => UnusedDefSuggestion::BlockTailExpr { + before_span: lo, + after_span: hi, + }, + (false, false) => UnusedDefSuggestion::NormalExpr { span: lo }, + }) + }, }, ); } diff --git a/tests/ui/lint/unused/must-use-box-from-raw.stderr b/tests/ui/lint/unused/must-use-box-from-raw.stderr index 4898db7fe3ddd..7eab99e97cd82 100644 --- a/tests/ui/lint/unused/must-use-box-from-raw.stderr +++ b/tests/ui/lint/unused/must-use-box-from-raw.stderr @@ -10,10 +10,10 @@ note: the lint level is defined here | LL | #![warn(unused_must_use)] | ^^^^^^^^^^^^^^^ -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = Box::from_raw(ptr); - | +++++++ +LL | let _unused = Box::from_raw(ptr); + | +++++++++++++ warning: 1 warning emitted diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed new file mode 100644 index 0000000000000..13289df3677fd --- /dev/null +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.fixed @@ -0,0 +1,41 @@ +//@ run-rustfix +//! Regression test for https://github.com/rust-lang/rust/issues/162843. +//! Must-use values with nontrivial drop should suggest a binding that preserves drop timing. +#![deny(unused_must_use)] + +use std::sync::Mutex; + +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) {} +} + +#[must_use] +fn guard() -> Guard { + Guard +} + +#[must_use] +fn value() -> u8 { + 0 +} + +#[must_use] +fn vec_values() -> Vec { + vec![1, 2, 3] +} + +#[must_use] +fn box_value() -> Box { + Box::new(0) +} + +fn main() { + let mutex = Mutex::new(0); + let _unused = mutex.lock().unwrap(); //~ ERROR unused `std::sync::MutexGuard` that must be used + let _unused = guard(); //~ ERROR unused return value of `guard` that must be used + let _ = value(); //~ ERROR unused return value of `value` that must be used + let _ = vec_values(); //~ ERROR unused return value of `vec_values` that must be used + let _ = box_value(); //~ ERROR unused return value of `box_value` that must be used +} diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs index 10ab5d75a05fa..1b0de8242a7a7 100644 --- a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.rs @@ -1,15 +1,41 @@ +//@ run-rustfix //! Regression test for https://github.com/rust-lang/rust/issues/162843. -//! Ignoring a synchronization guard should suggest a binding that keeps the lock held. +//! Must-use values with nontrivial drop should suggest a binding that preserves drop timing. #![deny(unused_must_use)] -use std::sync::{Mutex, RwLock}; +use std::sync::Mutex; + +struct Guard; + +impl Drop for Guard { + fn drop(&mut self) {} +} + +#[must_use] +fn guard() -> Guard { + Guard +} + +#[must_use] +fn value() -> u8 { + 0 +} + +#[must_use] +fn vec_values() -> Vec { + vec![1, 2, 3] +} + +#[must_use] +fn box_value() -> Box { + Box::new(0) +} fn main() { let mutex = Mutex::new(0); mutex.lock().unwrap(); //~ ERROR unused `std::sync::MutexGuard` that must be used - mutex.lock(); //~ ERROR unused `Result` that must be used - - let rwlock = RwLock::new(0); - rwlock.read().unwrap(); //~ ERROR unused `std::sync::RwLockReadGuard` that must be used - rwlock.write().unwrap(); //~ ERROR unused `std::sync::RwLockWriteGuard` that must be used + guard(); //~ ERROR unused return value of `guard` that must be used + value(); //~ ERROR unused return value of `value` that must be used + vec_values(); //~ ERROR unused return value of `vec_values` that must be used + box_value(); //~ ERROR unused return value of `box_value` that must be used } diff --git a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr index 0e06555d20f9d..8fa5c693f2561 100644 --- a/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr +++ b/tests/ui/lint/unused/must-use-lock-guard-issue-162843.stderr @@ -1,55 +1,63 @@ error: unused `std::sync::MutexGuard` that must be used - --> $DIR/must-use-lock-guard-issue-162843.rs:9:5 + --> $DIR/must-use-lock-guard-issue-162843.rs:36:5 | LL | mutex.lock().unwrap(); | ^^^^^^^^^^^^^^^^^^^^^ | = note: if unused the Mutex will immediately unlock note: the lint level is defined here - --> $DIR/must-use-lock-guard-issue-162843.rs:3:9 + --> $DIR/must-use-lock-guard-issue-162843.rs:4:9 | LL | #![deny(unused_must_use)] | ^^^^^^^^^^^^^^^ -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = mutex.lock().unwrap(); - | +++++++ +LL | let _unused = mutex.lock().unwrap(); + | +++++++++++++ -error: unused `Result` that must be used - --> $DIR/must-use-lock-guard-issue-162843.rs:10:5 +error: unused return value of `guard` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:37:5 | -LL | mutex.lock(); - | ^^^^^^^^^^^^ +LL | guard(); + | ^^^^^^^ + | +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately + | +LL | let _unused = guard(); + | +++++++++++++ + +error: unused return value of `value` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:38:5 + | +LL | value(); + | ^^^^^^^ | - = note: this `Result` may be an `Err` variant, which should be handled help: use `let _ = ...` to ignore the resulting value | -LL | let _ = mutex.lock(); +LL | let _ = value(); | +++++++ -error: unused `std::sync::RwLockReadGuard` that must be used - --> $DIR/must-use-lock-guard-issue-162843.rs:13:5 +error: unused return value of `vec_values` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:39:5 | -LL | rwlock.read().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^ +LL | vec_values(); + | ^^^^^^^^^^^^ | - = note: if unused the RwLock will immediately unlock help: use `let _ = ...` to ignore the resulting value | -LL | let _ = rwlock.read().unwrap(); +LL | let _ = vec_values(); | +++++++ -error: unused `std::sync::RwLockWriteGuard` that must be used - --> $DIR/must-use-lock-guard-issue-162843.rs:14:5 +error: unused return value of `box_value` that must be used + --> $DIR/must-use-lock-guard-issue-162843.rs:40:5 | -LL | rwlock.write().unwrap(); - | ^^^^^^^^^^^^^^^^^^^^^^^ +LL | box_value(); + | ^^^^^^^^^^^ | - = note: if unused the RwLock will immediately unlock help: use `let _ = ...` to ignore the resulting value | -LL | let _ = rwlock.write().unwrap(); +LL | let _ = box_value(); | +++++++ -error: aborting due to 4 previous errors +error: aborting due to 5 previous errors diff --git a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr index 230c97092b526..13c51a588fb03 100644 --- a/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr +++ b/tests/ui/lint/unused/must_use-result-unit-uninhabited.stderr @@ -75,10 +75,10 @@ LL | self.generate(); | ^^^^^^^^^^^^^^^ | = note: this `Result` may be an `Err` variant, which should be handled -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = self.generate(); - | +++++++ +LL | let _unused = self.generate(); + | +++++++++++++ error: aborting due to 7 previous errors diff --git a/tests/ui/lint/unused/unused-async.stderr b/tests/ui/lint/unused/unused-async.stderr index e93a40658f3c2..43bc73d2758c1 100644 --- a/tests/ui/lint/unused/unused-async.stderr +++ b/tests/ui/lint/unused/unused-async.stderr @@ -17,10 +17,10 @@ error: unused return value of `foo` that must be used LL | foo(); | ^^^^^ | -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = foo(); - | +++++++ +LL | let _unused = foo(); + | +++++++++++++ error: unused output of future returned by `foo` that must be used --> $DIR/unused-async.rs:33:5 @@ -47,10 +47,10 @@ error: unused return value of `bar` that must be used LL | bar(); | ^^^^^ | -help: use `let _ = ...` to ignore the resulting value +help: use `let _unused = ...` to ignore the resulting value without dropping it immediately | -LL | let _ = bar(); - | +++++++ +LL | let _unused = bar(); + | +++++++++++++ error: unused implementer of `Future` that must be used --> $DIR/unused-async.rs:37:5 From 8f40c2a16bac9ce168bccda960ea7655bc1483c8 Mon Sep 17 00:00:00 2001 From: Yukang Date: Mon, 21 Sep 2026 10:11:17 +0800 Subject: [PATCH 0875/1309] Filter with accessbility before find match for name --- .../rustc_resolve/src/diagnostics/impls.rs | 36 ++++++++++++------- .../nested-module-typo-issue-131366.fixed | 10 ++++++ .../nested-module-typo-issue-131366.rs | 10 ++++++ .../nested-module-typo-issue-131366.stderr | 13 ++++++- 4 files changed, 56 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index ee13092abd68e..dfef1e7cb92cb 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1033,6 +1033,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { Res::Def(k, _) => matches_kind(k), _ => false, }, + &|_| true, ) && let Res::Def(kind, mut def_id) = suggestion.res { if let DefKind::Ctor(_, _) = kind { @@ -1603,6 +1604,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope: &ParentScope<'ra>, ident: Ident, filter_fn: &impl Fn(Res) -> bool, + suggestion_filter: &impl Fn(&TypoSuggestion) -> bool, ) -> Option { let mut suggestions = Vec::new(); self.add_scope_set_candidates( @@ -1613,6 +1615,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { filter_fn, ); + // Some candidates cannot be decided from the `Res` alone (e.g. they need + // re-resolution or visibility checks), filter them out before picking the + // best name match. + suggestions.retain(suggestion_filter); + // Make sure error reporting is deterministic. suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str())); @@ -1965,6 +1972,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope, ident, is_expected, + &|_| true, ); self.add_typo_suggestion(err, suggestion, ident.span); self.detect_derive_attribute(err, ident, parent_scope, sugg_span); @@ -3034,18 +3042,22 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { parent_scope, ident, &|res| matches!(res, Res::Def(DefKind::Mod | DefKind::Enum, _)), - ) - && let Ok(binding) = self.cm().resolve_ident_in_module( - ModuleOrUniformRoot::Module(module), - Ident::new(candidate.candidate, ident.span), - TypeNS, - parent_scope, - None, - ignore_decl, - ignore_import, - ) - && self.is_accessible_from(binding.vis(), parent_scope.module) - { + &|candidate| { + self.cm() + .resolve_ident_in_module( + ModuleOrUniformRoot::Module(module), + Ident::new(candidate.candidate, ident.span), + TypeNS, + parent_scope, + None, + ignore_decl, + ignore_import, + ) + .is_ok_and(|binding| { + self.is_accessible_from(binding.vis(), parent_scope.module) + }) + }, + ) { Some(( vec![(ident.span, Ident::new(candidate.candidate, ident.span).to_string())], format!( diff --git a/tests/ui/imports/nested-module-typo-issue-131366.fixed b/tests/ui/imports/nested-module-typo-issue-131366.fixed index a84119fe93a8b..ff1c4eb2532b2 100644 --- a/tests/ui/imports/nested-module-typo-issue-131366.fixed +++ b/tests/ui/imports/nested-module-typo-issue-131366.fixed @@ -33,4 +33,14 @@ macro_rules! import { import!(collections); //~^ ERROR unresolved import `local::collection` +mod accessible { + pub mod collections { + pub struct Item; + } + use collections as collection; +} +// The closer match is a private alias, so suggest the accessible module instead. +use accessible::collections::Item as AccessibleItem; +//~^ ERROR unresolved import `accessible::collectio` + fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.rs b/tests/ui/imports/nested-module-typo-issue-131366.rs index 2f269da41b209..2d0e81e2e0e3a 100644 --- a/tests/ui/imports/nested-module-typo-issue-131366.rs +++ b/tests/ui/imports/nested-module-typo-issue-131366.rs @@ -33,4 +33,14 @@ macro_rules! import { import!(collection); //~^ ERROR unresolved import `local::collection` +mod accessible { + pub mod collections { + pub struct Item; + } + use collections as collection; +} +// The closer match is a private alias, so suggest the accessible module instead. +use accessible::collectio::Item as AccessibleItem; +//~^ ERROR unresolved import `accessible::collectio` + fn main() {} diff --git a/tests/ui/imports/nested-module-typo-issue-131366.stderr b/tests/ui/imports/nested-module-typo-issue-131366.stderr index 922b9219a7854..1173fc1fb5c57 100644 --- a/tests/ui/imports/nested-module-typo-issue-131366.stderr +++ b/tests/ui/imports/nested-module-typo-issue-131366.stderr @@ -42,6 +42,17 @@ help: an enum with a similar name exists LL | use local::Choices::First; | + +error[E0432]: unresolved import `accessible::collectio` + --> $DIR/nested-module-typo-issue-131366.rs:43:17 + | +LL | use accessible::collectio::Item as AccessibleItem; + | ^^^^^^^^^ could not find `collectio` in `accessible` + | +help: a module with a similar name exists + | +LL | use accessible::collections::Item as AccessibleItem; + | ++ + error[E0432]: unresolved import `crate::root_modul` --> $DIR/nested-module-typo-issue-131366.rs:27:12 | @@ -64,6 +75,6 @@ help: a module with a similar name exists LL | import!(collections); | + -error: aborting due to 6 previous errors +error: aborting due to 7 previous errors For more information about this error, try `rustc --explain E0432`. From 3631ff3d02d9278a1bf878f0ed94be226833ed63 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 14 Sep 2026 14:53:57 +0200 Subject: [PATCH 0876/1309] make semicolon_in_expressions_from_non_local_macros not report-in-deps --- compiler/rustc_lint_defs/src/builtin.rs | 2 +- .../foreign-crate.stderr | 16 ---------------- 2 files changed, 1 insertion(+), 17 deletions(-) diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2a0901e0243b6..22eb1471bd572 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -3024,7 +3024,7 @@ declare_lint! { "trailing semicolon in macro body used as expression", @future_incompatible = FutureIncompatibleInfo { reason: fcw!(FutureReleaseError #79813), - report_in_deps: true, + report_in_deps: false, }; } diff --git a/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.stderr b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.stderr index b335df57496ef..9414364bfa6d9 100644 --- a/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.stderr +++ b/tests/ui/lint/semicolon-in-expressions-from-macros/foreign-crate.stderr @@ -15,19 +15,3 @@ LL | #![deny(semicolon_in_expressions_from_non_local_macros)] error: aborting due to 1 previous error -Future incompatibility report: Future breakage diagnostic: -error: trailing semicolon in macro used in expression position - --> $DIR/foreign-crate.rs:8:13 - | -LL | let _ = foreign_crate::my_macro!(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #79813 -note: the lint level is defined here - --> $DIR/foreign-crate.rs:2:9 - | -LL | #![deny(semicolon_in_expressions_from_non_local_macros)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - = note: this error originates in the macro `foreign_crate::my_macro` (in Nightly builds, run with -Z macro-backtrace for more info) - From 47f1cc50f5f13da841285728b8c45e79debbda1f Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Sat, 5 Sep 2026 15:42:24 +0200 Subject: [PATCH 0877/1309] Add socket2, integrate socket2 sockets in TCP socket shim Shimmed TCP sockets are now always backed by a host socket. Before `connect` or `listen` is invoked on the shimmed socket, we just have a `socket2::Socket`. This is socket is then coverted to a `mio::TcpStream` or `mio::TcpListener` after encountering a `connect` or `listen`, respectively. Furthermore, a socket can always be viewed as a `socket2::SockRef`. This allows us to support more socket options than mio provides on its TCP socket abstractions. --- src/tools/miri/Cargo.lock | 11 + src/tools/miri/Cargo.toml | 1 + src/tools/miri/priroda/Cargo.lock | 11 + src/tools/miri/src/shims/unix/socket.rs | 18 +- src/tools/miri/src/shims/unix/tcp_socket.rs | 567 +++++++++++------- .../pass-dep/libc/libc-socket-no-blocking.rs | 92 ++- .../miri/tests/pass-dep/libc/libc-socket.rs | 184 +++++- 7 files changed, 635 insertions(+), 249 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 166d45491242c..c71ec790d39fe 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1020,6 +1020,7 @@ dependencies = [ "serde", "serde_json", "smallvec", + "socket2", "tempfile", "ui_test", ] @@ -1484,6 +1485,16 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "spanned" version = "0.4.1" diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index de4687715c06b..9f2a1e884fd70 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -28,6 +28,7 @@ directories = "6" bitflags = "2.6" serde_json = { version = "1.0", optional = true } mio = { version = "1.1.1", features = ["os-poll", "net"] } +socket2 = "0.6.5" [target.'cfg(unix)'.dependencies] libc = "0.2" diff --git a/src/tools/miri/priroda/Cargo.lock b/src/tools/miri/priroda/Cargo.lock index 8d4272630e08a..7b8ec9b0f08e6 100644 --- a/src/tools/miri/priroda/Cargo.lock +++ b/src/tools/miri/priroda/Cargo.lock @@ -688,6 +688,7 @@ dependencies = [ "rand 0.10.2", "serde", "smallvec", + "socket2", ] [[package]] @@ -1115,6 +1116,16 @@ version = "1.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +[[package]] +name = "socket2" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" +dependencies = [ + "libc", + "windows-sys", +] + [[package]] name = "spanned" version = "0.4.1" diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index 8c442df216a47..ce1f5c06b6b2c 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -10,14 +10,6 @@ use crate::shims::unix::socket_address::EvalContextExt as _; use crate::shims::unix::tcp_socket::TcpSocket; use crate::*; -#[derive(Debug, PartialEq)] -pub enum SocketFamily { - // IPv4 internet protocols - IPv4, - // IPv6 internet protocols - IPv6, -} - /// Represents unix-specific socket file descriptions. /// /// Not to be confused with Unix domain sockets. @@ -204,9 +196,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let family = if domain == this.eval_libc_i32("AF_INET") { - SocketFamily::IPv4 + socket2::Domain::IPV4 } else if domain == this.eval_libc_i32("AF_INET6") { - SocketFamily::IPv6 + socket2::Domain::IPV6 } else { throw_unsup_format!( "socket: domain {:#x} is unsupported, only AF_INET and \ @@ -229,8 +221,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } + let socket = match TcpSocket::new(family, is_non_block) { + Ok(socket) => socket, + Err(e) => return this.set_errno_and_return_neg1_i32(e), + }; let fds = &mut this.machine.fds; - let fd = fds.new_ref(TcpSocket::new(family, is_non_block)); + let fd = fds.new_ref(socket); interp_ok(Scalar::from_i32(fds.insert(fd))) } diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index b59174cd71c2d..db0010beaa46b 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -1,7 +1,7 @@ use std::cell::{Cell, RefCell, RefMut}; use std::io; use std::io::Read; -use std::net::{Ipv4Addr, Shutdown, SocketAddr, SocketAddrV4}; +use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::sync::atomic::AtomicBool; use std::time::Duration; @@ -14,7 +14,7 @@ use rustc_target::spec::Os; use crate::shims::files::{EvalContextExt as _, FdNum, FileDescription, FileDescriptionRef}; use crate::shims::sig::Varargs; use crate::shims::unix::UnixFileDescription; -use crate::shims::unix::socket::{SocketFamily, UnixSocketFileDescription}; +use crate::shims::unix::socket::UnixSocketFileDescription; use crate::*; /// On Linux a TCP socket is initally in the TCP_CLOSE state: @@ -35,12 +35,10 @@ const INITIAL_TCP_SOCKET_READINESS: Readiness = #[derive(Debug)] enum SocketState { /// No syscall after `socket` has been made. - Initial, - /// The `bind` syscall has been called on the socket. - /// This is only reachable from the [`SocketState::Initial`] state. - Bound(SocketAddr), + Initial(socket2::Socket), /// The `listen` syscall has been called on the socket. - /// This is only reachable from the [`SocketState::Bound`] state. + /// This is reachable from the [`SocketState::Initial`] and the + /// [`SocketState::Listening`] states. Listening(TcpListener), /// The `connect` syscall has been called and we weren't yet able /// to ensure the connection is established. This is only reachable @@ -59,17 +57,55 @@ enum SocketState { /// and thus nothing (except destroying the socket) should be /// supported when a socket is in this state. ConnectionFailed(TcpStream), + /// The socket state machine is transitioning between two states + /// which contain an underlying host socket. This state is never + /// observable, it's only needed as a placeholder state to safely + /// acquire ownership of the underlying host socket. + // FIXME: This would not be needed with `replace_with`, but sadly + // this isn't part of the standard library and we don't want to add + // an extra dependency for this. + None, +} + +impl SocketState { + /// View the underlying host socket as a [`socket2::SockRef`]. + /// + /// **Note**: Potentially blocking operations need to be performed on the + /// underlying [`TcpStream`] and [`TcpListener`] as it would break the mio + /// poll on Windows hosts when performed directly on the [`socket2::SockRef`]. + fn as_socket_ref<'a>(&'a self) -> socket2::SockRef<'a> { + match self { + SocketState::Initial(socket) => socket.into(), + SocketState::Listening(listener) => listener.into(), + SocketState::Connecting(stream) + | SocketState::Connected(stream) + | SocketState::ConnectionFailed(stream) => stream.into(), + SocketState::None => unreachable!(), + } + } + + /// Invoke `cb` with a [`socket2::SockRef`] to the underlying host socket. + /// + /// **Note**: Potentially blocking operations need to be performed on the + /// underlying [`TcpStream`] and [`TcpListener`] as it would break the mio + /// poll on Windows hosts when performed directly on the [`socket2::SockRef`]. + fn with_socket_ref<'a, T>(&'a self, cb: impl FnOnce(socket2::SockRef<'a>) -> T) -> T { + let socket = self.as_socket_ref(); + cb(socket) + } } #[derive(Debug)] pub(super) struct TcpSocket { /// Family of the socket, used to ensure socket only binds/connects to address of /// same family. - family: SocketFamily, + family: socket2::Domain, /// Current state of the inner socket. state: RefCell, /// Whether this fd is non-blocking or not. is_non_block: Cell, + /// Whether the socket is implicitly or explicitly bound to an address. + is_bound: Cell, /// The current blocking I/O readiness of the file description. io_readiness: RefCell, /// [`Some`] when the socket had an async error which has not yet been fetched via `SO_ERROR`. @@ -91,17 +127,31 @@ pub(super) struct TcpSocket { } impl TcpSocket { - pub fn new(family: SocketFamily, is_non_block: bool) -> Self { - TcpSocket { + pub fn new(family: socket2::Domain, is_non_block: bool) -> io::Result { + let socket = + socket2::Socket::new(family, socket2::Type::STREAM, Some(socket2::Protocol::TCP))?; + // The underlying host socket needs to be non-blocking. The actual + // blocking mode of the socket is stored in `is_non_block`. + socket.set_nonblocking(true)?; + + // We don't add the newly created socket to the blocking I/O manager + // until we can create a mio TcpStream or TcpListener because + // `socket2::Socket` doesn't implement `mio::Source`. + // This is fine since the readiness of a TCP socket (at least under Linux) + // does have a static initial readiness until `connect` or `listen` is + // invoked on it. + + Ok(TcpSocket { family, - state: RefCell::new(SocketState::Initial), + state: RefCell::new(SocketState::Initial(socket)), is_non_block: Cell::new(is_non_block), + is_bound: Cell::new(false), io_readiness: RefCell::new(INITIAL_TCP_SOCKET_READINESS), error: RefCell::new(None), read_timeout: Cell::new(None), write_timeout: Cell::new(None), watched: ReadinessWatched::default(), - } + }) } } @@ -251,98 +301,158 @@ impl UnixSocketFileDescription for TcpSocket { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "bind")?; - let mut state = self.state.borrow_mut(); + let address_family = match &address { + SocketAddr::V4(_) => socket2::Domain::IPV4, + SocketAddr::V6(_) => socket2::Domain::IPV6, + }; - match *state { - SocketState::Initial => { - let address_family = match &address { - SocketAddr::V4(_) => SocketFamily::IPv4, - SocketAddr::V6(_) => SocketFamily::IPv6, - }; + if self.family != address_family { + // Attempted to bind an address from a family that doesn't match + // the family of the socket. + let err = if matches!(ecx.tcx.sess.target.os, Os::Linux | Os::Android) { + // Linux man page states that `EINVAL` is used when there is an address family mismatch. + // See + LibcError("EINVAL") + } else { + // POSIX man page states that `EAFNOSUPPORT` should be used when there is an address + // family mismatch. + // See + LibcError("EAFNOSUPPORT") + }; + return interp_ok(Err(err)); + } - if self.family != address_family { - // Attempted to bind an address from a family that doesn't match - // the family of the socket. - let err = if matches!(ecx.tcx.sess.target.os, Os::Linux | Os::Android) { - // Linux man page states that `EINVAL` is used when there is an address family mismatch. - // See - LibcError("EINVAL") - } else { - // POSIX man page states that `EAFNOSUPPORT` should be used when there is an address - // family mismatch. - // See - LibcError("EAFNOSUPPORT") - }; - return interp_ok(Err(err)); - } + let state = self.state.borrow(); + let socket = state.as_socket_ref(); - *state = SocketState::Bound(address); - } - SocketState::Connecting(_) | SocketState::Connected(_) => - throw_unsup_format!( - "bind: tcp socket is already connected and binding a - connected socket is unsupported" - ), - SocketState::Bound(_) | SocketState::Listening(_) => - throw_unsup_format!( - "bind: tcp socket is already bound and binding a socket \ - multiple times is unsupported" - ), - SocketState::ConnectionFailed(_) => unreachable!(), + // `bind` is a non-blocking operation for TCP sockets. + if let Err(e) = socket.bind(&socket2::SockAddr::from(address)) { + return interp_ok(Err(IoError::HostError(e))); } + // The socket has been explicitly bound to a local address. + self.is_bound.set(true); + interp_ok(Ok(())) } fn listen<'tcx>( self: FileDescriptionRef, communicate_allowed: bool, - // Since the backlog value is just a performance hint we can ignore it. - _backlog: i32, + backlog: i32, ecx: &mut MiriInterpCx<'tcx>, ) -> InterpResult<'tcx, Result<(), IoError>> { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "listen")?; - let mut state = self.state.borrow_mut(); + let state = self.state.borrow(); - match *state { - SocketState::Bound(socket_addr) => - match TcpListener::bind(socket_addr) { - Ok(listener) => { - *state = SocketState::Listening(listener); - drop(state); - - // After invoking `listen` on a TCP socket, it transitions out of the - // TCP_CLOSE state which affects the socket's readiness. Because we - // register the socket afterwards to the blocking I/O manager, we just - // clear its readiness here as the blocking I/O manager will update its - // readiness accordingly. - self.io_readiness.replace(Readiness::EMPTY); - ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; - - // Register the socket to the blocking I/O manager because - // we now have an associated host socket. - ecx.machine.blocking_io.register(self); - } - Err(e) => return interp_ok(Err(IoError::HostError(e))), - }, - SocketState::Initial => { - throw_unsup_format!( - "listen: listening on a tcp socket which isn't bound is unsupported" - ) - } - SocketState::Listening(_) => { - throw_unsup_format!( - "listen: listening on a tcp socket multiple times is unsupported" - ) - } - SocketState::Connecting(_) | SocketState::Connected(_) => { - throw_unsup_format!("listen: listening on a connected tcp socket is unsupported") + // We'll only attempt to invoke `listen` on the socket if it's not already + // connected because POSIX specifies that EINVAL should be returned in this + // case. + let socket = match &*state { + SocketState::Initial(_) | SocketState::Listening(_) => state.as_socket_ref(), + // POSIX states that connected sockets cannot start listening, + // so we can return early here to simplify the remaining shim. + SocketState::Connecting(_) | SocketState::Connected(_) => + return interp_ok(Err(LibcError("EINVAL"))), + SocketState::ConnectionFailed(_) | SocketState::None => unreachable!(), + }; + + // Despite not being specified by POSIX, on most of our supported Unix-like platforms + // (confirmed on Linux, macOS, FreeBSD, and Solaris) TCP sockets get implicitly bound + // to the unspecified address at a random port when `listen` is invoked on an unbound + // socket. Thus, Miri models the same non-POSIX behavior and treats a socket as bound + // once `listen` has successfully been invoked on an unbound socket. + + if cfg!(windows) && !self.is_bound.get() { + // Implicitly binding a TCP socket by invoking `listen` on an + // unbound socket causes EINVAL on Windows hosts. We thus + // explicitly bind the socket to an unspecified address with + // a random port before listening. + // + // When the subsequent `listen` fails we behave incorrectly + // because a previously unbound socket is now bound. However, + // since `listen` can only fail for system resource errors + // (e.g., ENOBUFS) this isn't a problem in reality. + + let address = if self.family == socket2::Domain::IPV4 { + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, /* port */ 0)) + } else { + SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::UNSPECIFIED, + /* port */ 0, + /* flowinfo */ 0, + /* scope_id */ 0, + )) + }; + + if let Err(e) = socket.bind(&socket2::SockAddr::from(address)) { + return interp_ok(Err(IoError::HostError(e))); } - SocketState::ConnectionFailed(_) => unreachable!(), + + // We just explicitly bound the socket to a local address. + self.is_bound.set(true); + } + + if let Err(e) = socket.listen(backlog) { + return interp_ok(Err(IoError::HostError(e))); } + // As mentioned above, we treat listening sockets as implicitly bound to a + // local address if they weren't already bound before the `listen` invocation. + self.is_bound.set(true); + + if let SocketState::Listening(_) = &*state { + // The socket was already listening; we just changed the backlog. + // The socket is already registered to the blocking I/O manager + // and we also don't need to perform a state transition. + return interp_ok(Ok(())); + } + + drop(state); + + // Temporarily use dummy state to take ownership of the underlying socket. + let SocketState::Initial(socket) = self.state.replace(SocketState::None) else { + unreachable!() + }; + + // FIXME: Rustfmt has a bug where it incorrectly removes the outer braces of {{ .. }} inside + // a `cfg_select!` block. See . + #[rustfmt::skip] + let listener = cfg_select! { + // Turn the `socket2::Socket` into a `mio::TcpListener`. + // We follow Tokio's TCP socket implementation: + // See + // SAFETY: mio specifies that it is safe to use `from_raw_fd` and + // `from_raw_socket` as long as it's ensured that the socket is non-blocking. + // Because we immediately make the socket non-blocking after creation, that + // is always guaranteed. + + unix => {{ + use std::os::fd::{IntoRawFd, FromRawFd}; + let raw_fd = socket.into_raw_fd(); + unsafe { TcpListener::from_raw_fd(raw_fd) } + }}, + windows => {{ + use std::os::windows::io::{IntoRawSocket, FromRawSocket}; + let raw_socket = socket.into_raw_socket(); + unsafe { TcpListener::from_raw_socket(raw_socket) } + }}, + _ => unreachable!("unsupported host platform") + }; + + self.state.replace(SocketState::Listening(listener)); + + // Clear the "artificial" readiness as we are about to put the blocking + // I/O manager in charge of handling readiness. + self.io_readiness.replace(Readiness::EMPTY); + ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; + + // Register the socket to the blocking I/O manager. Can only happen + // now that we have created a mio TcpListener. + ecx.machine.blocking_io.register(self); + interp_ok(Ok(())) } @@ -394,52 +504,110 @@ impl UnixSocketFileDescription for TcpSocket { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "connect")?; - match &*self.state.borrow() { - SocketState::Initial => { /* fall-through to below */ } + let state = self.state.borrow(); + + // We'll only attempt to invoke `connect` on the socket if it's not already + // connected or listening because POSIX specifies error codes which should + // be returned in those cases. + let socket = match &*state { + SocketState::Initial(socket) => socket, + SocketState::Listening(_) => { + let err = if matches!(ecx.tcx.sess.target.os, Os::Linux | Os::Android) { + // Linux-like targets return EISCONN when attempting to invoke + // `connect` on an already listening socket. + // See + LibcError("EISCONN") + } else { + // POSIX specifies to return EOPNOTSUPP when attempting to invoke + // `connect` on an already listening socket. + // See + LibcError("EOPNOTSUPP") + }; + return finish.call(ecx, Err(err)); + } + // The socket is already connected. + // Subsequent connection attempts return EISCONN for TCP sockets. + SocketState::Connected(_) => return finish.call(ecx, Err(LibcError("EISCONN"))), // The socket is already in a connecting state. + // Subsequent connection attempts return EALREADY for TCP sockets. SocketState::Connecting(_) => return finish.call(ecx, Err(LibcError("EALREADY"))), - // We don't return EISCONN for already connected sockets, for which we're - // sure that the connection is established, since TCP sockets are usually - // allowed to be connected multiple times. - _ => - throw_unsup_format!( - "connect: connecting is only supported for tcp sockets which are neither \ - bound, listening nor already connected" - ), + SocketState::ConnectionFailed(_) | SocketState::None => unreachable!(), + }; + + let result = socket.connect(&socket2::SockAddr::from(address)); + + drop(state); + + // Boolean whether the connection attempt "failed" because it could not be + // completed immediately without blocking. + let is_in_progress = result.as_ref().is_err_and(|e| { + // On Windows hosts non-blocking connects fail with EWOULDBLOCK when the connection cannot + // be established immediately, while on Unix-like hosts they fail with EINPROGRESS. + matches!(e.kind(), io::ErrorKind::WouldBlock | io::ErrorKind::InProgress) + }); + + if !is_in_progress && let Err(e) = result { + // There was a "real" error during connection establishment. + return finish.call(ecx, Err(IoError::HostError(e))); } - // This begins establishing the connection, but does not block until the stream is fully connected. - // We deal with that below. - match TcpStream::connect(address) { - Ok(stream) => { - *self.state.borrow_mut() = SocketState::Connecting(stream); - - // After invoking `connect` on a TCP socket, it transitions out of the - // TCP_CLOSE state which affects the socket's readiness. Because we - // register the socket afterwards to the blocking I/O manager, we just - // clear its readiness here as the blocking I/O manager will update its - // readiness accordingly. - self.io_readiness.replace(Readiness::EMPTY); - ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; - - // Register the socket to the blocking I/O manager because - // we now have an associated host socket. - ecx.machine.blocking_io.register(self.clone()); - } - Err(e) => return finish.call(ecx, Err(IoError::HostError(e))), + // Temporarily use dummy state to take ownership of the underlying socket. + let SocketState::Initial(socket) = self.state.replace(SocketState::None) else { + unreachable!() }; + // FIXME: Rustfmt has a bug where it incorrectly removes the outer braces of {{ .. }} inside + // a `cfg_select!` block. See . + #[rustfmt::skip] + let stream = cfg_select! { + // Turn the `socket2::Socket` into a `mio::TcpStream`. + // We follow Tokio's TCP socket implementation: + // See + // SAFETY: mio specifies that it is safe to use `from_raw_fd` and + // `from_raw_socket` as long as it's ensured that the socket is non-blocking. + // Because we immediately make the socket non-blocking after creation, that + // is always guaranteed. + + unix => {{ + use std::os::fd::{IntoRawFd, FromRawFd}; + let raw_fd = socket.into_raw_fd(); + unsafe { TcpStream::from_raw_fd(raw_fd) } + }}, + windows => {{ + use std::os::windows::io::{IntoRawSocket, FromRawSocket}; + let raw_socket = socket.into_raw_socket(); + unsafe { TcpStream::from_raw_socket(raw_socket) } + }}, + _ => unreachable!("unsupported host platform") + }; + + self.state.replace(SocketState::Connecting(stream)); + // Connecting sockets are implicitly bound to a local address. + self.is_bound.set(true); + + // Clear the "artificial" readiness as we are about to put the blocking + // I/O manager in charge of handling readiness. + self.io_readiness.replace(Readiness::EMPTY); + ecx.update_fd_readiness(self.clone(), ReadinessUpdateFlags::DEFAULT)?; + + // Register the socket to the blocking I/O manager. Can only happen + // now that we have created a mio TcpStream. + ecx.machine.blocking_io.register(self.clone()); + if self.is_non_block.get() { // We have a non-blocking socket and thus don't want to block until // the connection is established. - // Since the [`TcpStream::connect`] function of mio hides the EINPROGRESS - // we just always return EINPROGRESS and check whether the connection succeeded - // once we want to use the connected socket. - finish.call(ecx, Err(LibcError("EINPROGRESS"))) + if is_in_progress { + finish.call(ecx, Err(LibcError("EINPROGRESS"))) + } else { + finish.call(ecx, Ok(())) + } } else { // The socket is in blocking mode and thus the connect call should block - // until the connection with the server is established. + // until the connection with the server is established. A potential + // EWOULDBLOCK or EINPROGRESS error code is ignored as we emulate a + // blocking socket. if self.write_timeout.get().is_some() { // Some Unixes like Linux also apply the SO_SNDTIMEO socket option @@ -647,19 +815,7 @@ impl UnixSocketFileDescription for TcpSocket { let option_value = ecx.ptr_to_mplace(value_ptr, ecx.machine.layouts.u32); let ttl = ecx.read_scalar(&option_value)?.to_u32()?; - let result = match &*self.state.borrow() { - SocketState::Initial | SocketState::Bound(_) => - throw_unsup_format!( - "setsockopt: setting option IP_TTL on level IPPROTO_IP is only supported \ - on connected and listening tcp sockets" - ), - SocketState::Listening(listener) => listener.set_ttl(ttl), - SocketState::Connecting(stream) | SocketState::Connected(stream) => - stream.set_ttl(ttl), - SocketState::ConnectionFailed(_) => unreachable!(), - }; - - return match result { + return match self.state.borrow().with_socket_ref(|s| s.set_ttl_v4(ttl)) { Ok(_) => interp_ok(Ok(())), Err(e) => interp_ok(Err(IoError::HostError(e))), }; @@ -679,18 +835,7 @@ impl UnixSocketFileDescription for TcpSocket { let option_value = ecx.ptr_to_mplace(value_ptr, ecx.machine.layouts.i32); let nodelay = ecx.read_scalar(&option_value)?.to_i32()? != 0; - let result = match &*self.state.borrow() { - SocketState::Initial | SocketState::Bound(_) | SocketState::Listening(_) => - throw_unsup_format!( - "setsockopt: setting option TCP_NODELAY on level IPPROTO_TCP is only supported \ - on connected tcp sockets" - ), - SocketState::Connecting(stream) | SocketState::Connected(stream) => - stream.set_nodelay(nodelay), - SocketState::ConnectionFailed(_) => unreachable!(), - }; - - return match result { + return match self.state.borrow().with_socket_ref(|s| s.set_tcp_nodelay(nodelay)) { Ok(_) => interp_ok(Ok(())), Err(e) => interp_ok(Err(IoError::HostError(e))), }; @@ -772,19 +917,7 @@ impl UnixSocketFileDescription for TcpSocket { let opt_ip_ttl = ecx.eval_libc_i32("IP_TTL"); if option == opt_ip_ttl { - let ttl = match &*self.state.borrow() { - SocketState::Initial | SocketState::Bound(_) => - throw_unsup_format!( - "getsockopt: reading option IP_TTL on level IPPROTO_IP is only supported \ - on connected and listening tcp sockets" - ), - SocketState::Listening(listener) => listener.ttl(), - SocketState::Connecting(stream) | SocketState::Connected(stream) => - stream.ttl(), - SocketState::ConnectionFailed(_) => unreachable!(), - }; - - let ttl = match ttl { + let ttl = match self.state.borrow().with_socket_ref(|s| s.ttl_v4()) { Ok(ttl) => ttl, Err(e) => return interp_ok(Err(IoError::HostError(e))), }; @@ -802,18 +935,7 @@ impl UnixSocketFileDescription for TcpSocket { let opt_tcp_nodelay = ecx.eval_libc_i32("TCP_NODELAY"); if option == opt_tcp_nodelay { - let nodelay = match &*self.state.borrow() { - SocketState::Initial | SocketState::Bound(_) | SocketState::Listening(_) => - throw_unsup_format!( - "getsockopt: reading option TCP_NODELAY on level IPPROTO_TCP is only supported \ - on connected tcp sockets" - ), - SocketState::Connecting(stream) | SocketState::Connected(stream) => - stream.nodelay(), - SocketState::ConnectionFailed(_) => unreachable!(), - }; - - let nodelay = match nodelay { + let nodelay = match self.state.borrow().with_socket_ref(|s| s.tcp_nodelay()) { Ok(nodelay) => nodelay, Err(e) => return interp_ok(Err(IoError::HostError(e))), }; @@ -843,52 +965,45 @@ impl UnixSocketFileDescription for TcpSocket { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "getsockname")?; - let state = self.state.borrow(); + if !self.is_bound.get() { + // Since Windows returns EINVAL when invoking `getsockname` on + // a socket which hasn't been bound yet, we need to manually + // return an unspecified address here. - let address = match &*state { - SocketState::Bound(address) => { - if address.port() == 0 { - // The socket is bound to a zero-port which means it gets assigned a random - // port. Since we don't yet have an underlying socket, we don't know what this - // random port will be and thus this is unsupported. - throw_unsup_format!( - "getsockname: when the port is 0, getting the tcp socket address before \ - calling `listen` or `connect` is unsupported" - ) - } + let address = if self.family == socket2::Domain::IPV4 { + SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, /* port */ 0)) + } else { + SocketAddr::V6(SocketAddrV6::new( + Ipv6Addr::UNSPECIFIED, + /* port */ 0, + /* flowinfo */ 0, + /* scope_id */ 0, + )) + }; + return interp_ok(Ok(address)); + } - *address - } - SocketState::Listening(listener) => - match listener.local_addr() { - Ok(address) => address, - Err(e) => return interp_ok(Err(IoError::HostError(e))), - }, - SocketState::Connecting(stream) | SocketState::Connected(stream) => { - if cfg!(windows) && matches!(&*state, SocketState::Connecting(_)) { - // FIXME: On Windows hosts `TcpStream::local_addr` returns `0.0.0.0:0` whilst - // the socket is connecting: - // - // This is problematic because UNIX targets could expect a real local address even - // for a connecting non-blocking socket. - - static DEDUP: AtomicBool = AtomicBool::new(false); - if !DEDUP.swap(true, std::sync::atomic::Ordering::Relaxed) { - ecx.emit_diagnostic(NonHaltingDiagnostic::ConnectingSocketGetsockname); - } - } - match stream.local_addr() { - Ok(address) => address, - Err(e) => return interp_ok(Err(IoError::HostError(e))), - } + let state = self.state.borrow(); + let socket = state.as_socket_ref(); + + if cfg!(windows) + && let SocketState::Connecting(_) = &*state + { + // FIXME: On Windows hosts `getsockname` returns `0.0.0.0:0` whilst the socket is connecting: + // + // This is problematic because UNIX targets could expect a real local address even + // for a connecting non-blocking socket. + + static DEDUP: AtomicBool = AtomicBool::new(false); + if !DEDUP.swap(true, std::sync::atomic::Ordering::Relaxed) { + ecx.emit_diagnostic(NonHaltingDiagnostic::ConnectingSocketGetsockname); } - // For non-bound sockets the POSIX manual says the returned address is unspecified. - // Often this is 0.0.0.0:0 and thus we set it to this value. - SocketState::Initial => SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 0)), - SocketState::ConnectionFailed(_) => unreachable!(), - }; + } - interp_ok(Ok(address)) + match socket.local_addr() { + Ok(address) => interp_ok(Ok(address.as_socket().unwrap())), + Err(e) => interp_ok(Err(IoError::HostError(e))), + } } fn getpeername<'tcx>( @@ -1077,14 +1192,16 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { }; let family = match addr { - SocketAddr::V4(_) => SocketFamily::IPv4, - SocketAddr::V6(_) => SocketFamily::IPv6, + SocketAddr::V4(_) => socket2::Domain::IPV4, + SocketAddr::V6(_) => socket2::Domain::IPV6, }; let fd = this.machine.fds.new_ref(TcpSocket { family, state: RefCell::new(SocketState::Connected(stream)), is_non_block: Cell::new(is_client_sock_nonblock), + // Connected sockets are implicitly bound to a local address. + is_bound: Cell::new(true), io_readiness: RefCell::new(Readiness::EMPTY), error: RefCell::new(None), read_timeout: Cell::new(None), @@ -1484,13 +1601,11 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // The connection is established. // Temporarily use dummy state to take ownership of the stream. - let mut state = socket.state.borrow_mut(); - let SocketState::Connecting(stream) = std::mem::replace(&mut*state, SocketState::Initial) else { + let SocketState::Connecting(stream) = socket.state.replace(SocketState::None) else { // At the start of the function we ensured that we're currently connecting. unreachable!() }; - *state = SocketState::Connected(stream); - drop(state); + socket.state.replace(SocketState::Connected(stream)); action.call(this, Ok(())) } ), @@ -1523,16 +1638,10 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// state because we know that `socket` can no longer successfully establish a /// connection. fn update_last_error(&self, socket: &FileDescriptionRef) { - let mut state = socket.state.borrow_mut(); - - let new_error = match &*state { - SocketState::Listening(listener) => - listener.take_error().expect("Reading SO_ERROR should not fail"), - SocketState::Connecting(stream) | SocketState::Connected(stream) => - stream.take_error().expect("Reading SO_ERROR should not fail"), - SocketState::Initial | SocketState::Bound(_) | SocketState::ConnectionFailed(_) => None, - }; + let state = socket.state.borrow(); + let new_error = + state.as_socket_ref().take_error().expect("Reading SO_ERROR should not fail"); let Some(new_error) = new_error else { return }; // Store the error such that we can return it when @@ -1545,13 +1654,13 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // specification, the socket is now in an unspecified state. // We thus change the socket state to `ConnectionFailed`. + drop(state); + // Temporarily use dummy state to take ownership of the stream. - let SocketState::Connecting(stream) = - std::mem::replace(&mut *state, SocketState::Initial) - else { + let SocketState::Connecting(stream) = socket.state.replace(SocketState::None) else { unreachable!() }; - *state = SocketState::ConnectionFailed(stream); + socket.state.replace(SocketState::ConnectionFailed(stream)); } } } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs index de718feb47990..451e9feef3b55 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs @@ -58,6 +58,9 @@ fn main() { test_getpeername_ipv4_nonblock(); test_getpeername_ipv4_nonblock_no_peer(); + + test_listen_connecting(); + test_connect_connecting(); } /// Test that setting the O_NONBLOCK flag changes the blocking state of a socket. @@ -231,9 +234,10 @@ fn test_connect_nonblock() { loop { // There should be no error during async connection. - let errno = net::getsockopt::(client_sockfd, libc::SOL_SOCKET, libc::SO_ERROR) - .unwrap(); - assert_eq!(errno, 0); + let so_error = + net::getsockopt::(client_sockfd, libc::SOL_SOCKET, libc::SO_ERROR) + .unwrap(); + assert_eq!(so_error, 0); let result = net::sockname_ipv4(|storage, len| unsafe { libc::getpeername(client_sockfd, storage, len) @@ -769,9 +773,9 @@ fn test_getpeername_ipv4_nonblock_no_peer() { assert_eq!(err.kind(), ErrorKind::InProgress); // There should be no error during async connection. - let errno = + let so_error = net::getsockopt::(client_sockfd, libc::SOL_SOCKET, libc::SO_ERROR).unwrap(); - assert_eq!(errno, 0); + assert_eq!(so_error, 0); // Since we're never accepting the connection, the socket should never be // successfully connected and thus we should be unable to read the peername. @@ -782,3 +786,81 @@ fn test_getpeername_ipv4_nonblock_no_peer() { }; assert_eq!(err.kind(), ErrorKind::NotConnected); } + +/// Test that `listen` returns EINVAL for a non-blocking IPv4 +/// socket which is stuck at connecting to a remote address. +fn test_listen_connecting() { + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + unsafe { + // Change client socket to be non-blocking. + errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); + } + + // We cannot attempt to connect to a localhost address because + // it could be the case that a socket from another test is + // currently listening on `localhost:12321` because we bind to + // random ports everywhere. For `192.0.2.1` we know that nothing is + // listening because it's a blackhole address: + // + // The port `12321` is just a random non-zero port because Windows + // and Apple hosts return EADDRNOTAVAIL when attempting to connect to + // a zero port. + let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); + + // Non-blocking connect should fail with EINPROGRESS. + let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InProgress); + + // There should be no error during async connection. + let so_error = + net::getsockopt::(client_sockfd, libc::SOL_SOCKET, libc::SO_ERROR).unwrap(); + assert_eq!(so_error, 0); + + // Connecting sockets cannot start listening, thus the operation should + // fail with EINVAL. + let err = unsafe { errno_result(libc::listen(client_sockfd, 16)).unwrap_err() }; + // Check that it is the right error. + assert_eq!(err.raw_os_error(), Some(libc::EINVAL)); +} + +/// Test that invoking `connect` on an already connecting client +/// TCP socket returns EALREADY. +fn test_connect_connecting() { + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + unsafe { + // Change client socket to be non-blocking. + errno_check(libc::fcntl(client_sockfd, libc::F_SETFL, libc::O_NONBLOCK)); + } + + // We cannot attempt to connect to a localhost address because + // it could be the case that a socket from another test is + // currently listening on `localhost:12321` because we bind to + // random ports everywhere. For `192.0.2.1` we know that nothing is + // listening because it's a blackhole address: + // + // The port `12321` is just a random non-zero port because Windows + // and Apple hosts return EADDRNOTAVAIL when attempting to connect to + // a zero port. + let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); + + // Non-blocking connect should fail with EINPROGRESS. + let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::InProgress); + + // There should be no error during async connection. + let so_error = + net::getsockopt::(client_sockfd, libc::SOL_SOCKET, libc::SO_ERROR).unwrap(); + assert_eq!(so_error, 0); + + // Create a socket which listens on `addr`. + let (_, addr) = net::make_listener_ipv4().unwrap(); + + let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + // The standard library doesn't provide an error kind for EALREADY; + // we thus cannot assert the correct error kind. + assert_eq!(err.raw_os_error(), Some(libc::EALREADY)); +} diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs index 85d6302a0175d..d581f358cac95 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket.rs @@ -33,10 +33,17 @@ fn main() { } test_bind_ipv4_invalid_addr_len(); test_bind_ipv6(); + test_bind_twice(); + test_bind_connected(); + test_bind_listening(); test_listen(); + test_listen_connected(); + test_listen_listening(); test_accept_connect(); test_connect_error(); + test_connect_connected(); + test_connect_listening(); test_send_peek_recv(); test_write_read(); test_readv(); @@ -47,6 +54,7 @@ fn main() { test_getsockname_ipv4_unbound(); test_getsockname_ipv4_connect(); test_getsockname_ipv6(); + test_getsockname_ipv6_unbound(); test_getpeername_ipv4(); test_getpeername_ipv6(); @@ -236,21 +244,123 @@ fn test_bind_ipv6() { } } -fn test_listen() { +/// Test that invoking `bind` on an already bound TCP socket +/// returns EINVAL. +fn test_bind_twice() { let sockfd = unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; let addr = net::sock_addr_ipv4(net::IPV4_LOCALHOST, 0); - unsafe { + let err = unsafe { errno_check(libc::bind( sockfd, (&addr as *const libc::sockaddr_in).cast::(), size_of::() as libc::socklen_t, )); - } + errno_result(libc::bind( + sockfd, + (&addr as *const libc::sockaddr_in).cast::(), + size_of::() as libc::socklen_t, + )) + .unwrap_err() + }; + // Check that it is the right error. + assert_eq!(err.raw_os_error(), Some(libc::EINVAL)); +} + +/// Test that invoking `bind` on an already connected client +/// TCP socket returns EINVAL. +fn test_bind_connected() { + let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + net::connect_ipv4(client_sockfd, addr).unwrap(); + net::accept_ipv4(server_sockfd).unwrap(); + + let addr = net::sock_addr_ipv4(net::IPV4_LOCALHOST, 0); + let err = unsafe { + errno_result(libc::bind( + client_sockfd, + (&addr as *const libc::sockaddr_in).cast::(), + size_of::() as libc::socklen_t, + )) + .unwrap_err() + }; + // Check that it is the right error. + assert_eq!(err.raw_os_error(), Some(libc::EINVAL)); +} + +/// Test that invoking `bind` on an already listening server +/// TCP socket returns EINVAL. +fn test_bind_listening() { + let server_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; unsafe { - errno_check(libc::listen(sockfd, 16)); + errno_check(libc::listen(server_sockfd, 16)); } + + let addr = net::sock_addr_ipv4(net::IPV4_LOCALHOST, 0); + let err = unsafe { + errno_result(libc::bind( + server_sockfd, + (&addr as *const libc::sockaddr_in).cast::(), + size_of::() as libc::socklen_t, + )) + .unwrap_err() + }; + // Check that it is the right error. + assert_eq!(err.raw_os_error(), Some(libc::EINVAL)); +} + +/// Test that a socket can start listening. This also tests +/// whether sockets are bound implicitly after `listen` has been +/// invoked on them. +fn test_listen() { + let sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + unsafe { errno_check(libc::listen(sockfd, 16)) }; + + let (_, sock_addr) = + net::sockname_ipv4(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }) + .unwrap(); + + // Libc representation of an unspecified IPv4 address with zero port. + let addr = net::sock_addr_ipv4([0, 0, 0, 0], 0); + + // Ensure that the socket got implicitly bound to the unspecified + // local address with a non-zero port. + assert!(sock_addr.sin_port > 0); + assert_eq!(addr.sin_family, sock_addr.sin_family); + assert_eq!(addr.sin_addr.s_addr, sock_addr.sin_addr.s_addr); +} + +/// Test that `listen` returns EINVAL for a client TCP socket which +/// is already connected to a peer socket. +fn test_listen_connected() { + let (server_sockfd, addr) = net::make_listener_ipv4().unwrap(); + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + net::connect_ipv4(client_sockfd, addr).unwrap(); + net::accept_ipv4(server_sockfd).unwrap(); + + // Connected sockets cannot start listening, thus the operation should + // fail with EINVAL. + let err = unsafe { errno_result(libc::listen(client_sockfd, 16)).unwrap_err() }; + // Check that it is the right error. + assert_eq!(err.raw_os_error(), Some(libc::EINVAL)); +} + +/// Test that `listen` succeeds for a server TCP socket which is already +/// listening. +fn test_listen_listening() { + let (server_sockfd, _) = net::make_listener_ipv4().unwrap(); + + // Invoking `listen` multiple times should be allowed as it can be used to change + // the backlog value. + unsafe { errno_check(libc::listen(server_sockfd, 16)) }; } /// Test accepting connections by running a server in a separate thread and connecting clients @@ -318,6 +428,46 @@ fn test_connect_error() { )); } +/// Test that invoking `connect` on an already connected client +/// TCP socket returns EISCONN. +fn test_connect_connected() { + let (server_sockfd1, addr1) = net::make_listener_ipv4().unwrap(); + let (_, addr2) = net::make_listener_ipv4().unwrap(); + let client_sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET, libc::SOCK_STREAM, 0)).unwrap() }; + + net::connect_ipv4(client_sockfd, addr1).unwrap(); + net::accept_ipv4(server_sockfd1).unwrap(); + + let err = net::connect_ipv4(client_sockfd, addr2).unwrap_err(); + // The standard library doesn't provide an error kind for EISCONN; + // we thus cannot assert the correct error kind. + assert_eq!(err.raw_os_error(), Some(libc::EISCONN)); +} + +/// Test that invoking `connect` on an already listening server +/// TCP socket returns EOPNOTSUPP on non-Linux-like targets and +/// EISCONN on Linux-like targets. +fn test_connect_listening() { + let (_, addr1) = net::make_listener_ipv4().unwrap(); + let (server_sockfd2, _) = net::make_listener_ipv4().unwrap(); + + let err = net::connect_ipv4(server_sockfd2, addr1).unwrap_err(); + + if cfg!(any(target_os = "linux", target_os = "android")) { + // Linux-like targets return EISCONN when attempting to invoke + // `connect` on an already listening socket. + + // The standard library doesn't provide an error kind for EISCONN; + // we thus cannot assert the correct error kind. + assert_eq!(err.raw_os_error(), Some(libc::EISCONN)); + } else { + // POSIX specifies EOPNOTSUPP when attempting to invoke + // `connect` on an already listening socket. + assert_eq!(err.raw_os_error(), Some(libc::EOPNOTSUPP)); + } +} + /// Test sending bytes into a connected stream and then peeking and receiving /// them from the other end. /// We especially want to test that the peeking doesn't remove the bytes from @@ -606,6 +756,32 @@ fn test_getsockname_ipv6() { assert_eq!(addr.sin6_addr.s6_addr, sock_addr.sin6_addr.s6_addr); } +/// Test the `getsockname` syscall on an IPv6 socket which is not bound. +/// The `getsockname` syscall should return [::]:0 with flowinfo and scope id +/// of zero. +fn test_getsockname_ipv6_unbound() { + let sockfd = + unsafe { errno_result(libc::socket(libc::AF_INET6, libc::SOCK_STREAM, 0)).unwrap() }; + + let (_, sock_addr) = + net::sockname_ipv6(|storage, len| unsafe { libc::getsockname(sockfd, storage, len) }) + .unwrap(); + + // Libc representation of an unspecified IPv6 address with zero port, flowinfo and scope id. + let addr = net::sock_addr_full_ipv6( + [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], + /* port */ 0, + /* flowinfo */ 0, + /* scope_id */ 0, + ); + + assert_eq!(addr.sin6_family, sock_addr.sin6_family); + assert_eq!(addr.sin6_port, sock_addr.sin6_port); + assert_eq!(addr.sin6_flowinfo, sock_addr.sin6_flowinfo); + assert_eq!(addr.sin6_scope_id, sock_addr.sin6_scope_id); + assert_eq!(addr.sin6_addr.s6_addr, sock_addr.sin6_addr.s6_addr); +} + /// Test the `getpeername` syscall on an IPv4 socket. /// For a connected socket, the `getpeername` syscall should /// return the same address as the socket was connected to. From 9afae373d778e65aa19de7ba5c79d6946d6b1001 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Sep 2026 09:41:08 +0200 Subject: [PATCH 0878/1309] avoid re-opening RefCells quite so often --- src/tools/miri/src/shims/unix/tcp_socket.rs | 67 +++++++++++---------- 1 file changed, 34 insertions(+), 33 deletions(-) diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index db0010beaa46b..394f80a151f06 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -1,9 +1,9 @@ use std::cell::{Cell, RefCell, RefMut}; -use std::io; use std::io::Read; use std::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr, SocketAddrV4, SocketAddrV6}; use std::sync::atomic::AtomicBool; use std::time::Duration; +use std::{io, mem}; use mio::event::Source; use mio::net::{TcpListener, TcpStream}; @@ -83,16 +83,6 @@ impl SocketState { SocketState::None => unreachable!(), } } - - /// Invoke `cb` with a [`socket2::SockRef`] to the underlying host socket. - /// - /// **Note**: Potentially blocking operations need to be performed on the - /// underlying [`TcpStream`] and [`TcpListener`] as it would break the mio - /// poll on Windows hosts when performed directly on the [`socket2::SockRef`]. - fn with_socket_ref<'a, T>(&'a self, cb: impl FnOnce(socket2::SockRef<'a>) -> T) -> T { - let socket = self.as_socket_ref(); - cb(socket) - } } #[derive(Debug)] @@ -153,6 +143,16 @@ impl TcpSocket { watched: ReadinessWatched::default(), }) } + + /// Invoke `cb` with a [`socket2::SockRef`] to the underlying host socket. + /// + /// **Note**: Potentially blocking operations need to be performed on the + /// underlying [`TcpStream`] and [`TcpListener`] as it would break the mio + /// poll on Windows hosts when performed directly on the [`socket2::SockRef`]. + fn with_socket_ref(&self, cb: impl FnOnce(socket2::SockRef<'_>) -> T) -> T { + let state = self.state.borrow(); + cb(state.as_socket_ref()) + } } impl FileDescription for TcpSocket { @@ -345,7 +345,7 @@ impl UnixSocketFileDescription for TcpSocket { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "listen")?; - let state = self.state.borrow(); + let mut state = self.state.borrow_mut(); // We'll only attempt to invoke `listen` on the socket if it's not already // connected because POSIX specifies that EINVAL should be returned in this @@ -410,10 +410,8 @@ impl UnixSocketFileDescription for TcpSocket { return interp_ok(Ok(())); } - drop(state); - // Temporarily use dummy state to take ownership of the underlying socket. - let SocketState::Initial(socket) = self.state.replace(SocketState::None) else { + let SocketState::Initial(socket) = mem::replace(&mut *state, SocketState::None) else { unreachable!() }; @@ -442,7 +440,8 @@ impl UnixSocketFileDescription for TcpSocket { _ => unreachable!("unsupported host platform") }; - self.state.replace(SocketState::Listening(listener)); + *state = SocketState::Listening(listener); + drop(state); // Clear the "artificial" readiness as we are about to put the blocking // I/O manager in charge of handling readiness. @@ -504,7 +503,7 @@ impl UnixSocketFileDescription for TcpSocket { assert!(communicate_allowed, "cannot have `TcpSocket` with isolation enabled!"); ecx.ensure_not_failed(&self, "connect")?; - let state = self.state.borrow(); + let mut state = self.state.borrow_mut(); // We'll only attempt to invoke `connect` on the socket if it's not already // connected or listening because POSIX specifies error codes which should @@ -536,8 +535,6 @@ impl UnixSocketFileDescription for TcpSocket { let result = socket.connect(&socket2::SockAddr::from(address)); - drop(state); - // Boolean whether the connection attempt "failed" because it could not be // completed immediately without blocking. let is_in_progress = result.as_ref().is_err_and(|e| { @@ -552,7 +549,7 @@ impl UnixSocketFileDescription for TcpSocket { } // Temporarily use dummy state to take ownership of the underlying socket. - let SocketState::Initial(socket) = self.state.replace(SocketState::None) else { + let SocketState::Initial(socket) = mem::replace(&mut *state, SocketState::None) else { unreachable!() }; @@ -581,7 +578,9 @@ impl UnixSocketFileDescription for TcpSocket { _ => unreachable!("unsupported host platform") }; - self.state.replace(SocketState::Connecting(stream)); + *state = SocketState::Connecting(stream); + drop(state); + // Connecting sockets are implicitly bound to a local address. self.is_bound.set(true); @@ -815,7 +814,7 @@ impl UnixSocketFileDescription for TcpSocket { let option_value = ecx.ptr_to_mplace(value_ptr, ecx.machine.layouts.u32); let ttl = ecx.read_scalar(&option_value)?.to_u32()?; - return match self.state.borrow().with_socket_ref(|s| s.set_ttl_v4(ttl)) { + return match self.with_socket_ref(|s| s.set_ttl_v4(ttl)) { Ok(_) => interp_ok(Ok(())), Err(e) => interp_ok(Err(IoError::HostError(e))), }; @@ -835,7 +834,7 @@ impl UnixSocketFileDescription for TcpSocket { let option_value = ecx.ptr_to_mplace(value_ptr, ecx.machine.layouts.i32); let nodelay = ecx.read_scalar(&option_value)?.to_i32()? != 0; - return match self.state.borrow().with_socket_ref(|s| s.set_tcp_nodelay(nodelay)) { + return match self.with_socket_ref(|s| s.set_tcp_nodelay(nodelay)) { Ok(_) => interp_ok(Ok(())), Err(e) => interp_ok(Err(IoError::HostError(e))), }; @@ -917,7 +916,7 @@ impl UnixSocketFileDescription for TcpSocket { let opt_ip_ttl = ecx.eval_libc_i32("IP_TTL"); if option == opt_ip_ttl { - let ttl = match self.state.borrow().with_socket_ref(|s| s.ttl_v4()) { + let ttl = match self.with_socket_ref(|s| s.ttl_v4()) { Ok(ttl) => ttl, Err(e) => return interp_ok(Err(IoError::HostError(e))), }; @@ -935,7 +934,7 @@ impl UnixSocketFileDescription for TcpSocket { let opt_tcp_nodelay = ecx.eval_libc_i32("TCP_NODELAY"); if option == opt_tcp_nodelay { - let nodelay = match self.state.borrow().with_socket_ref(|s| s.tcp_nodelay()) { + let nodelay = match self.with_socket_ref(|s| s.tcp_nodelay()) { Ok(nodelay) => nodelay, Err(e) => return interp_ok(Err(IoError::HostError(e))), }; @@ -1598,14 +1597,17 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // In other words, we are assuming that there will be no spurious // wakeups while establishing the connection. - // The connection is established. + // The connection is established. Update the state. + let mut state = socket.state.borrow_mut(); // Temporarily use dummy state to take ownership of the stream. - let SocketState::Connecting(stream) = socket.state.replace(SocketState::None) else { + let SocketState::Connecting(stream) = mem::replace(&mut *state, SocketState::None) else { // At the start of the function we ensured that we're currently connecting. unreachable!() }; - socket.state.replace(SocketState::Connected(stream)); + *state = SocketState::Connected(stream); + drop(state); + action.call(this, Ok(())) } ), @@ -1638,7 +1640,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { /// state because we know that `socket` can no longer successfully establish a /// connection. fn update_last_error(&self, socket: &FileDescriptionRef) { - let state = socket.state.borrow(); + let mut state = socket.state.borrow_mut(); let new_error = state.as_socket_ref().take_error().expect("Reading SO_ERROR should not fail"); @@ -1654,13 +1656,12 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // specification, the socket is now in an unspecified state. // We thus change the socket state to `ConnectionFailed`. - drop(state); - // Temporarily use dummy state to take ownership of the stream. - let SocketState::Connecting(stream) = socket.state.replace(SocketState::None) else { + let SocketState::Connecting(stream) = mem::replace(&mut *state, SocketState::None) + else { unreachable!() }; - socket.state.replace(SocketState::ConnectionFailed(stream)); + *state = SocketState::ConnectionFailed(stream); } } } From fd41c62116d98b0068bfed00095824d8d3433c73 Mon Sep 17 00:00:00 2001 From: Yoh Deadfall Date: Sat, 26 Sep 2026 10:49:01 +0300 Subject: [PATCH 0879/1309] Disable rust-analyzer diagnostics for Helix --- src/tools/miri/etc/rust_analyzer_helix.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/tools/miri/etc/rust_analyzer_helix.toml b/src/tools/miri/etc/rust_analyzer_helix.toml index 1015b4baa6b09..3b31ec68774d6 100644 --- a/src/tools/miri/etc/rust_analyzer_helix.toml +++ b/src/tools/miri/etc/rust_analyzer_helix.toml @@ -17,6 +17,10 @@ overrideCommand = [ "--message-format=json", ] +[language-server.rust-analyzer.config.diagnostics] +# RA reports false errors due to +enable = false + [language-server.rust-analyzer.config.cargo.extraEnv] MIRI_AUTO_OPS = "no" MIRI_IN_RA = "1" From 8d8674117b8f1c3531c0860f3955ee6e816e7c18 Mon Sep 17 00:00:00 2001 From: tye-exe Date: Sat, 26 Sep 2026 08:26:50 +0000 Subject: [PATCH 0880/1309] Update expect messages in rust_const_eval * Update expect messages In rustc_const_eval/src/interpret/eval_context.rs * Simplify exception messages --- compiler/rustc_const_eval/src/interpret/eval_context.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs index 99218a30e16b1..a74b323c395e6 100644 --- a/compiler/rustc_const_eval/src/interpret/eval_context.rs +++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs @@ -285,12 +285,12 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { #[inline(always)] pub fn frame(&self) -> &Frame<'tcx, M::Provenance, M::FrameExtra> { - self.stack().last().expect("no call frames exist") + self.stack().last().expect("a call frame should exist") } #[inline(always)] pub fn frame_mut(&mut self) -> &mut Frame<'tcx, M::Provenance, M::FrameExtra> { - self.stack_mut().last_mut().expect("no call frames exist") + self.stack_mut().last_mut().expect("a call frame should exist") } #[inline(always)] From eccccf3a233bc9f7aa19d43fae48a2b9a17e9a60 Mon Sep 17 00:00:00 2001 From: tison Date: Sat, 26 Sep 2026 16:52:05 +0800 Subject: [PATCH 0881/1309] Stabilize SyncView Signed-off-by: tison --- library/core/src/sync/mod.rs | 2 +- library/core/src/sync/sync_view.rs | 71 +++++++------- library/std/src/lib.rs | 1 - library/std/src/sync/mod.rs | 2 +- library/std/tests/sync_view.rs | 93 +++++++++++++++++++ .../ui/explicit-tail-calls/callee_is_weird.rs | 2 +- 6 files changed, 131 insertions(+), 40 deletions(-) create mode 100644 library/std/tests/sync_view.rs diff --git a/library/core/src/sync/mod.rs b/library/core/src/sync/mod.rs index 6c2660263a705..bd85bffcf192a 100644 --- a/library/core/src/sync/mod.rs +++ b/library/core/src/sync/mod.rs @@ -4,5 +4,5 @@ pub mod atomic; mod sync_view; -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] pub use sync_view::SyncView; diff --git a/library/core/src/sync/sync_view.rs b/library/core/src/sync/sync_view.rs index f4822048d2153..5c1e24125cf74 100644 --- a/library/core/src/sync/sync_view.rs +++ b/library/core/src/sync/sync_view.rs @@ -47,8 +47,6 @@ use core::task::{Context, Poll}; /// functionality: /// /// ```ignore-wasm -/// #![feature(exclusive_wrapper)] -/// /// use std::sync::SyncView; /// use std::sync::mpsc::{self, Receiver}; /// use std::thread; @@ -91,7 +89,7 @@ use core::task::{Context, Poll}; /// for any value. This is a parallel with the fact that /// `&` and `&mut` references together can be thought of as a _compile-time_ /// version of a read-write lock. -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[doc(alias = "SyncWrapper")] #[doc(alias = "SyncCell")] #[doc(alias = "Unique")] @@ -105,10 +103,10 @@ pub struct SyncView { } // See `SyncView`'s docs for justification. -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] unsafe impl Sync for SyncView {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] const impl Default for SyncView where @@ -120,7 +118,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for SyncView { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> { f.debug_struct("SyncView").finish_non_exhaustive() @@ -129,8 +127,8 @@ impl fmt::Debug for SyncView { impl SyncView { /// Wrap a value in an `SyncView` - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn new(t: T) -> Self { @@ -138,8 +136,9 @@ impl SyncView { } /// Unwrap the value contained in the `SyncView` - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_allow_const_fn_unstable(const_precise_live_drops)] #[must_use] #[inline] pub const fn into_inner(self) -> T { @@ -154,8 +153,8 @@ impl SyncView { /// value, which means _unpinned_ `SyncView`s can produce _unpinned_ /// access to the underlying value, but _pinned_ `SyncView`s only /// produce _pinned_ access to the underlying value. - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> { @@ -167,8 +166,8 @@ impl SyncView { /// Build a _mutable_ reference to an `SyncView` from /// a _mutable_ reference to a `T`. This allows you to skip /// building an `SyncView` with [`SyncView::new`]. - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_mut(r: &'_ mut T) -> &'_ mut SyncView { @@ -179,8 +178,8 @@ impl SyncView { /// Build a _pinned mutable_ reference to an `SyncView` from /// a _pinned mutable_ reference to a `T`. This allows you to skip /// building an `SyncView` with [`SyncView::new`]. - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn from_pin_mut(r: Pin<&'_ mut T>) -> Pin<&'_ mut SyncView> { @@ -197,8 +196,8 @@ impl SyncView { /// value, which means _unpinned_ `SyncView`s can produce _unpinned_ /// access to the underlying value, but _pinned_ `SyncView`s only /// produce _pinned_ access to the underlying value. - #[unstable(feature = "exclusive_wrapper", issue = "98407")] - #[rustc_const_unstable(feature = "exclusive_wrapper", issue = "98407")] + #[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] + #[rustc_const_stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[must_use] #[inline] pub const fn as_pin_ref(self: Pin<&Self>) -> Pin<&T> { @@ -208,7 +207,7 @@ impl SyncView { } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl From for SyncView { #[inline] @@ -217,7 +216,7 @@ const impl From for SyncView { } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl FnOnce for SyncView where @@ -231,7 +230,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl FnMut for SyncView where @@ -243,7 +242,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_trait_impl", issue = "143874")] const impl Fn for SyncView where @@ -255,7 +254,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl AsyncFnOnce for SyncView where F: AsyncFnOnce, @@ -270,7 +269,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl AsyncFnMut for SyncView where F: AsyncFnMut, @@ -286,7 +285,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl AsyncFn for SyncView where F: Sync + AsyncFn, @@ -297,7 +296,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl Future for SyncView where T: Future + ?Sized, @@ -324,7 +323,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl AsRef for SyncView where @@ -337,7 +336,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl AsMut for SyncView where @@ -350,7 +349,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] const impl Clone for SyncView where @@ -367,10 +366,10 @@ where #[rustc_const_unstable(feature = "const_clone", issue = "142757")] const unsafe impl TrivialClone for SyncView where T: Sync + [const] TrivialClone {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl Copy for SyncView where T: Sync + Copy {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl PartialEq> for SyncView where @@ -383,14 +382,14 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl StructuralPartialEq for SyncView where T: Sync + StructuralPartialEq + ?Sized {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl Eq for SyncView where T: Sync + [const] Eq + ?Sized {} -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] impl Hash for SyncView where T: Sync + Hash + ?Sized, @@ -401,7 +400,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl PartialOrd> for SyncView where @@ -414,7 +413,7 @@ where } } -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl Ord for SyncView where diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index bfb28b62d2089..f716f49ffd60a 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -341,7 +341,6 @@ #![feature(error_generic_member_access)] #![feature(error_iter)] #![feature(exact_size_is_empty)] -#![feature(exclusive_wrapper)] #![feature(extend_one)] #![feature(float_gamma)] #![feature(float_minimum_maximum)] diff --git a/library/std/src/sync/mod.rs b/library/std/src/sync/mod.rs index 9426d9a684ef6..b138c1b946c92 100644 --- a/library/std/src/sync/mod.rs +++ b/library/std/src/sync/mod.rs @@ -179,7 +179,7 @@ #![cfg_attr(rustfmt, rustfmt::skip)] // These come from `core` & `alloc` and only in one flavor: no poisoning. -#[unstable(feature = "exclusive_wrapper", issue = "98407")] +#[stable(feature = "exclusive_wrapper", since = "CURRENT_RUSTC_VERSION")] pub use core::sync::SyncView; #[stable(feature = "rust1", since = "1.0.0")] pub use core::sync::atomic; diff --git a/library/std/tests/sync_view.rs b/library/std/tests/sync_view.rs new file mode 100644 index 0000000000000..1a21130f73fa2 --- /dev/null +++ b/library/std/tests/sync_view.rs @@ -0,0 +1,93 @@ +use core::sync::SyncView; +use std::cell::Cell; +use std::future::Future; +use std::marker::PhantomPinned; +use std::pin::{Pin, pin}; +use std::task::{Context, Poll, Waker}; + +const EMPTY: Vec = SyncView::new(Vec::new()).into_inner(); +const PROJECTED: u32 = { + let mut value = 41; + let view = SyncView::from_mut(&mut value); + *Pin::into_inner(Pin::new(view).as_pin_mut()) += 1; + let view = SyncView::from_pin_mut(Pin::new(&mut value)).get_mut(); + *Pin::new(&*view).as_pin_ref().get_ref() +}; + +fn require_sync(_: &T) {} + +fn call_mut(mut f: impl FnMut() -> u32) -> u32 { + f() +} + +fn call_shared(f: &impl Fn() -> u32) -> u32 { + f() +} + +fn complete(future: impl Future) -> u32 { + let mut context = Context::from_waker(Waker::noop()); + match pin!(future).poll(&mut context) { + Poll::Ready(value) => value, + Poll::Pending => panic!("expected an immediately ready future"), + } +} + +async fn call_async_once(f: impl AsyncFnOnce() -> u32) -> u32 { + f().await +} + +struct Pinned { + value: Cell, + _pin: PhantomPinned, +} + +#[test] +fn sync_view_const() { + assert!(EMPTY.is_empty()); + assert_eq!(PROJECTED, 42); +} + +#[test] +fn sync_view_access() { + let mut value = std::sync::SyncView::new(Cell::new(1)); + require_sync(&value); + value.as_mut().set(2); + assert_eq!(value.into_inner().get(), 2); + + let mut values = [1, 2]; + let view = SyncView::from_mut(&mut values[..]); + view.as_mut()[0] = 3; + assert_eq!(view.as_ref(), &[3, 2]); +} + +#[test] +fn sync_view_pinned_projection() { + let mut pinned = pin!(Pinned { value: Cell::new(4), _pin: PhantomPinned }); + let address = std::ptr::from_ref(pinned.as_ref().get_ref()); + let view = SyncView::from_pin_mut(pinned.as_mut()); + require_sync(view.as_ref().get_ref()); + let inner = view.as_pin_mut(); + assert_eq!(std::ptr::from_ref(inner.as_ref().get_ref()), address); + inner.value.set(5); + assert_eq!(pinned.value.get(), 5); +} + +#[test] +fn sync_view_forwarding() { + let counter = Cell::new(0); + let increment = SyncView::new(|| { + counter.set(counter.get() + 1); + counter.get() + }); + require_sync(&increment); + assert_eq!(call_mut(increment), 1); + assert_eq!(call_shared(&SyncView::new(|| 7)), 7); + + let future = SyncView::new(async { + std::future::ready(()).await; + counter.get() + }); + require_sync(&future); + assert_eq!(complete(future), 1); + assert_eq!(complete(call_async_once(SyncView::new(async || counter.get()))), 1); +} diff --git a/tests/ui/explicit-tail-calls/callee_is_weird.rs b/tests/ui/explicit-tail-calls/callee_is_weird.rs index 9e2b1fb8d4b55..5b08808a9ca71 100644 --- a/tests/ui/explicit-tail-calls/callee_is_weird.rs +++ b/tests/ui/explicit-tail-calls/callee_is_weird.rs @@ -1,4 +1,4 @@ -#![feature(explicit_tail_calls, exclusive_wrapper, fn_traits, unboxed_closures)] +#![feature(explicit_tail_calls, fn_traits, unboxed_closures)] #![expect(incomplete_features)] fn f() {} From 8c3ae6023e42df78c644e4040fd3a8bb15cd4616 Mon Sep 17 00:00:00 2001 From: Kurashina Hinata Date: Sat, 26 Sep 2026 18:07:13 +0900 Subject: [PATCH 0882/1309] Don't build format string suggestions from `concat!` offsets When a format string does not come directly from a string literal in the source, e.g. when it is produced by `concat!`, the parser's inner offsets are relative to the expanded string rather than to the source. The primary error span and the `RemoveRawIdent` suggestion already check `is_source_literal` before calling `fmt_span.from_inner`, but the `UsePositional`, `ReorderFormatParameter` and `AddMissingColon` suggestions did not. As a result, these suggestions could point into the middle of a multibyte character and ICE when rendered, or suggest a bogus argument copied from unrelated source text. Only emit them when the format string is a source literal, like the other suggestions do. The crash test is moved to `tests/ui/fmt`, with cases covering each of these suggestions. --- compiler/rustc_builtin_macros/src/format.rs | 26 ++++++---- tests/crashes/156101.rs | 4 -- ...format-args-concat-multibyte-suggestion.rs | 38 ++++++++++++++ ...at-args-concat-multibyte-suggestion.stderr | 52 +++++++++++++++++++ 4 files changed, 106 insertions(+), 14 deletions(-) delete mode 100644 tests/crashes/156101.rs create mode 100644 tests/ui/fmt/format-args-concat-multibyte-suggestion.rs create mode 100644 tests/ui/fmt/format-args-concat-multibyte-suggestion.stderr diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index e23c057f8a651..c58b7e234d4d6 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -339,7 +339,9 @@ fn make_format_args( parse::Suggestion::UsePositional => { let captured_arg_span = fmt_span.from_inner(InnerSpan::new(err.span.start, err.span.end)); - if let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) { + if is_source_literal + && let Ok(arg) = ecx.source_map().span_to_snippet(captured_arg_span) + { let span = match args.unnamed_args().last() { Some(arg) => arg.expr.span, None => fmt_span, @@ -360,17 +362,21 @@ fn make_format_args( } } parse::Suggestion::ReorderFormatParameter(span, replacement) => { - let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); - e.sugg_ = - Some(diagnostics::InvalidFormatStringSuggestion::ReorderFormatParameter { - span, - replacement, - }); + if is_source_literal { + let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); + e.sugg_ = + Some(diagnostics::InvalidFormatStringSuggestion::ReorderFormatParameter { + span, + replacement, + }); + } } parse::Suggestion::AddMissingColon(span) => { - let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); - e.sugg_ = - Some(diagnostics::InvalidFormatStringSuggestion::AddMissingColon { span }); + if is_source_literal { + let span = fmt_span.from_inner(InnerSpan::new(span.start, span.end)); + e.sugg_ = + Some(diagnostics::InvalidFormatStringSuggestion::AddMissingColon { span }); + } } parse::Suggestion::UseRustDebugPrintingMacro => { // This targets `println!("{=}", x);` and `println!("{0=}", x);` diff --git a/tests/crashes/156101.rs b/tests/crashes/156101.rs deleted file mode 100644 index c95361fab2ecc..0000000000000 --- a/tests/crashes/156101.rs +++ /dev/null @@ -1,4 +0,0 @@ -//@ known-bug: #156101 -fn main() { - format_args!(concat!("𐏿", "{f:?#}")); -} diff --git a/tests/ui/fmt/format-args-concat-multibyte-suggestion.rs b/tests/ui/fmt/format-args-concat-multibyte-suggestion.rs new file mode 100644 index 0000000000000..51504607d2b61 --- /dev/null +++ b/tests/ui/fmt/format-args-concat-multibyte-suggestion.rs @@ -0,0 +1,38 @@ +// Regression test for #156101. +// +// When the format string comes from `concat!`, the parser's inner offsets are relative to the +// expanded string, not to the source, so they must not be turned into spans in the source. +// Before the fix, suggestions built from those offsets went wrong in two ways: +// +// - If the span landed inside a multibyte character, rendering the suggestion caused an ICE. +// The `ReorderFormatParameter` and `AddMissingColon` cases below are padded so that the span +// falls inside `é` (2 bytes) or `𐏿` (4 bytes). +// - If the span landed on unrelated source text, `UsePositional` suggested a bogus argument +// copied from that text. +// +// After the fix, no suggestion is emitted for these format strings. + +fn main() { + // The original reproducer from the issue. + format_args!(concat!("𐏿", "{f:?#}")); + //~^ ERROR invalid format string + + // `Suggestion::ReorderFormatParameter` + format_args!(concat!("é", "aaa{:?#}"), 1); + //~^ ERROR invalid format string + format_args!(concat!("𐏿", "a{:?#}"), 1); + //~^ ERROR invalid format string + + // `Suggestion::AddMissingColon` + format_args!(concat!("é", "aaaa{x?}")); + //~^ ERROR invalid format string + format_args!(concat!("𐏿", "aa{x?}")); + //~^ ERROR invalid format string + + // `Suggestion::UsePositional`: these did not ICE, but before the fix they suggested a bogus + // argument taken from the `concat!` invocation instead of from the format string. + format_args!(concat!("{}{a.b}", "")); + //~^ ERROR invalid format string + format_args!(concat!("{}{a.0}", "")); + //~^ ERROR invalid format string +} diff --git a/tests/ui/fmt/format-args-concat-multibyte-suggestion.stderr b/tests/ui/fmt/format-args-concat-multibyte-suggestion.stderr new file mode 100644 index 0000000000000..5eb8a4848a612 --- /dev/null +++ b/tests/ui/fmt/format-args-concat-multibyte-suggestion.stderr @@ -0,0 +1,52 @@ +error: invalid format string: expected `}`, found `#` + --> $DIR/format-args-concat-multibyte-suggestion.rs:17:18 + | +LL | format_args!(concat!("𐏿", "{f:?#}")); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + +error: invalid format string: expected `}`, found `#` + --> $DIR/format-args-concat-multibyte-suggestion.rs:21:18 + | +LL | format_args!(concat!("é", "aaa{:?#}"), 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + +error: invalid format string: expected `}`, found `#` + --> $DIR/format-args-concat-multibyte-suggestion.rs:23:18 + | +LL | format_args!(concat!("𐏿", "a{:?#}"), 1); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `'}'` in format string + +error: invalid format string: expected `}`, found `?` + --> $DIR/format-args-concat-multibyte-suggestion.rs:27:18 + | +LL | format_args!(concat!("é", "aaaa{x?}")); + | ^^^^^^^^^^^^^^^^^^^^^^^^ expected `:` before `?` to format with `Debug` in format string + | + = note: to print `{`, you can escape it using `{{` + +error: invalid format string: expected `}`, found `?` + --> $DIR/format-args-concat-multibyte-suggestion.rs:29:18 + | +LL | format_args!(concat!("𐏿", "aa{x?}")); + | ^^^^^^^^^^^^^^^^^^^^^^ expected `:` before `?` to format with `Debug` in format string + | + = note: to print `{`, you can escape it using `{{` + +error: invalid format string: field access isn't supported + --> $DIR/format-args-concat-multibyte-suggestion.rs:34:18 + | +LL | format_args!(concat!("{}{a.b}", "")); + | ^^^^^^^^^^^^^^^^^^^^^^ not supported in format string + | + = note: consider moving this expression to a local variable and then using the local here instead + +error: invalid format string: tuple index access isn't supported + --> $DIR/format-args-concat-multibyte-suggestion.rs:36:18 + | +LL | format_args!(concat!("{}{a.0}", "")); + | ^^^^^^^^^^^^^^^^^^^^^^ not supported in format string + | + = note: consider moving this expression to a local variable and then using the local here instead + +error: aborting due to 7 previous errors + From 08793166b03bc268c09eff6ce50d669a2ad03ff4 Mon Sep 17 00:00:00 2001 From: Jakob Koschel Date: Sat, 26 Sep 2026 09:16:32 +0000 Subject: [PATCH 0883/1309] Limit CFI run-make test to Linux --- tests/run-make/sanitizer-cfi-runtime/rmake.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/tests/run-make/sanitizer-cfi-runtime/rmake.rs b/tests/run-make/sanitizer-cfi-runtime/rmake.rs index 3cad996a14054..a86e9084dff12 100644 --- a/tests/run-make/sanitizer-cfi-runtime/rmake.rs +++ b/tests/run-make/sanitizer-cfi-runtime/rmake.rs @@ -1,3 +1,5 @@ +// FIXME(#122848) Remove only-linux once OSX CFI binaries work +//@ only-linux //@ needs-sanitizer-support //@ needs-sanitizer-cfi //@ ignore-backends: gcc From a0de97917cf55252e6bd8506324b809386e439e9 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Tue, 25 Aug 2026 14:36:20 +0600 Subject: [PATCH 0884/1309] dont lint unused parens on a pattern that came from a macro argument parentheses around a pattern passed to a `macro_rules!` metavariable can be required by the matcher even though they are redundant once expanded, so suggesting their removal breaks the macro call. a `$p:pat_param` fragment never accepts a top-level `|` and neither does `$p:pat` before edition 2021. a metavariable keeps the call site syntax context while the code around it keeps the macro definition context, so compare the two and reuse the existing `avoid_or` flag when they differ. parens written inside a macro body share one context and keep linting as before. --- compiler/rustc_lint/src/unused.rs | 22 ++++++-- .../unused-parens-macro-pat-issue-86959.rs | 54 +++++++++++++++++++ 2 files changed, 71 insertions(+), 5 deletions(-) create mode 100644 tests/ui/lint/unused-parens-macro-pat-issue-86959.rs diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index 2651ce55281fe..e2dff59a92990 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -783,6 +783,14 @@ impl UnusedParens { } } + /// A pattern that a `macro_rules!` metavariable brings in from the call site keeps the call + /// site's syntax context, while the pattern's surroundings keep the macro's. Parentheses in + /// such a pattern can be required by the matcher even when they are redundant in the + /// expansion, so removing them would break the macro call. (Issue #86959) + fn pat_is_macro_arg(pat_span: Span, parent_span: Span) -> bool { + !pat_span.eq_ctxt(parent_span) + } + fn cast_followed_by_lt(&self, expr: &ast::Expr) -> Option { if let ExprKind::Binary(op, lhs, _rhs) = &expr.kind && (op.node == ast::BinOpKind::Lt || op.node == ast::BinOpKind::Shl) @@ -811,7 +819,8 @@ impl EarlyLintPass for UnusedParens { match e.kind { ExprKind::Let(ref pat, _, _, _) | ExprKind::ForLoop(ForLoop { ref pat, .. }) => { - self.check_unused_parens_pat(cx, pat, false, false, (true, true)); + let avoid_or = Self::pat_is_macro_arg(pat.span, e.span); + self.check_unused_parens_pat(cx, pat, avoid_or, false, (true, true)); } // We ignore parens in cases like `if (((let Some(0) = Some(1))))` because we already // handle a hard error for them during AST lowering in `lower_expr_mut`, but we still @@ -890,13 +899,15 @@ impl EarlyLintPass for UnusedParens { | Err(_) => {} // These are list-like patterns; parens can always be removed. TupleStruct(_, _, ps) | Tuple(ps) | Slice(ps) | Or(ps) => { - for p in ps { - self.check_unused_parens_pat(cx, p, false, false, keep_space); + for sub in ps { + let avoid_or = Self::pat_is_macro_arg(sub.span, p.span); + self.check_unused_parens_pat(cx, sub, avoid_or, false, keep_space); } } Struct(_, _, fps, _) => { for f in fps { - self.check_unused_parens_pat(cx, &f.pat, false, false, keep_space); + let avoid_or = Self::pat_is_macro_arg(f.pat.span, p.span); + self.check_unused_parens_pat(cx, &f.pat, avoid_or, false, keep_space); } } // Avoid linting on `i @ (p0 | .. | pn)`, #64106. @@ -938,7 +949,8 @@ impl EarlyLintPass for UnusedParens { } fn check_arm(&mut self, cx: &EarlyContext<'_>, arm: &ast::Arm) { - self.check_unused_parens_pat(cx, &arm.pat, false, false, (false, false)); + let avoid_or = Self::pat_is_macro_arg(arm.pat.span, arm.span); + self.check_unused_parens_pat(cx, &arm.pat, avoid_or, false, (false, false)); } fn check_ty(&mut self, cx: &EarlyContext<'_>, ty: &ast::Ty) { diff --git a/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs b/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs new file mode 100644 index 0000000000000..3e41cb22c5aad --- /dev/null +++ b/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs @@ -0,0 +1,54 @@ +//@ check-pass +//@ revisions: e2018 e2021 +//@[e2018] edition: 2018 +//@[e2021] edition: 2021 + +// Parentheses around a pattern handed to a `macro_rules!` metavariable can be required by the +// matcher even though they are redundant in the expanded pattern, so removing them breaks the +// macro call. rust-lang/rust#86959 + +#![deny(unused_parens)] + +macro_rules! match_pat { + ($p:pat) => { + match 'a' { + $p => {} + _ => {} + } + }; +} + +macro_rules! match_pat_param { + ($p:pat_param) => { + match 'a' { + $p => {} + _ => {} + } + }; +} + +macro_rules! if_let_pat { + ($p:pat) => { + if let $p = 'a' {} + }; +} + +macro_rules! nested_pat { + ($p:pat) => { + match Some(1) { + Some($p) => {} + _ => {} + } + }; +} + +fn main() { + // `$p:pat` only accepts a top-level `|` from edition 2021 onwards. + match_pat!(('a' | 'A')); + // `$p:pat_param` never accepts a top-level `|`, in any edition. + match_pat_param!(('a' | 'A')); + if_let_pat!(('a' | 'A')); + nested_pat!((1 | 2)); + // A leading `..=` is rejected by both fragment specifiers. rust-lang/rust#120737 + match_pat!((..='a' | 'z')); +} From 36c3cb96f64bd69cccb70b03afad4d1b30f0f36d Mon Sep 17 00:00:00 2001 From: Redddy Date: Sat, 26 Sep 2026 10:38:45 +0000 Subject: [PATCH 0885/1309] ConstKind::Unevaluated -> ConstKind::Alias --- src/doc/rustc-dev-guide/src/const-generics.md | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 9e26a174d8cf6..718c3d4014aa9 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -5,7 +5,7 @@ Most of the kinds of `ty::Const` that exist have direct parallels to kinds of types that exist, for example `ConstKind::Param` is equivalent to `TyKind::Param`. The main interesting points here are: -- [`ConstKind::Unevaluated`], which is equivalent to `TyKind::Alias` and in the long term should be renamed (as well as introducing an `AliasConstKind` to parallel `ty::AliasKind`). +- [`ConstKind::Alias`], which is equivalent to `TyKind::Alias`. - [`ConstKind::Value`], which is the final value of a `ty::Const` after monomorphization. This is somewhat similar to fully concrete things like `TyKind::Str` or `TyKind::ADT`. @@ -35,7 +35,7 @@ const ANON: usize = 1 + 1; type Alias = [u8; ANON]; ``` -Where the array length in `[u8; ANON]` isn't itself an anon const containing a usage of `ANON`, but a kind of "direct" usage of the `ANON` const item ([`ConstKind::Unevaluated`]). +Where the array length in `[u8; ANON]` isn't itself an anon const containing a usage of `ANON`, but a kind of "direct" usage of the `ANON` const item ([`ConstKind::Alias`]). Anon consts do not inherit any generic parameters of the item they are inside of: ```rust @@ -81,7 +81,7 @@ type Alias = [u8; ANON]; When we go through HIR ty lowering for the array type in `Alias`, we will lower the array length too, and feed `type_of(ANON) -> usize`. This will effectively set the type of the `ANON` const item during some later part of the compiler rather than when constructing the HIR. -After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Unevaluated` with the `DefId` of the `AnonConst`. This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `min_generic_const_args` is enabled). +After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Alias` with the `DefId` of the `AnonConst`. This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `min_generic_const_args` is enabled). This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. @@ -215,7 +215,7 @@ Proving `ConstArgHasType` goals is implemented by first computing the type of th A rough outline of how the type of a Const Argument may be computed: - [`ConstKind::Param(N)`][`ConstKind::Param`] can be looked up in the [`ParamEnv`] to find a `ConstArgHasType(N, ty)` clause - [`ConstKind::Value`] stores the type of the value inside itself so can trivially be accessed -- [`ConstKind::Unevaluated`] can have its type computed by calling the `type_of` query +- [`ConstKind::Alias`] can have its type computed by calling the `type_of` query - See the implementation of proving `ConstArgHasType` goals for more detailed information `ConstArgHasType` is *the* soundness critical way that we check Const Arguments have the correct type. @@ -241,7 +241,7 @@ Looking at the above example, this corresponds to `[u8; ANON]` being a well form [`ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html [`ConstKind::Infer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Infer [`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Param -[`ConstKind::Unevaluated`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Unevaluated +[`ConstKind::Alias`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html#variant.Alias [`ConstKind::Value`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Value [const_arg_has_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstArgHasType [`ParamEnv`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html From 5e11a2644c55d84f5fc90a9c2b64795c5c6714e1 Mon Sep 17 00:00:00 2001 From: Redddy Date: Sat, 26 Sep 2026 10:58:40 +0000 Subject: [PATCH 0886/1309] fix ConstKind link --- src/doc/rustc-dev-guide/src/const-generics.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 718c3d4014aa9..e8aa118337b64 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -238,11 +238,11 @@ what actually happens is a *type checking* error when type checking the anon con Looking at the above example, this corresponds to `[u8; ANON]` being a well formed type because `ANON` has type `usize`, but the *body* of `ANON` being illformed and resulting in a type checking error because `true` can't be returned from a const item of type `usize`. [ambig-unambig-ty-and-consts]: ./ambig-unambig-ty-and-consts.md -[`ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html -[`ConstKind::Infer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Infer -[`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Param +[`ConstKind`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html +[`ConstKind::Infer`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html#variant.Infer +[`ConstKind::Param`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html#variant.Param [`ConstKind::Alias`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html#variant.Alias -[`ConstKind::Value`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ConstKind.html#variant.Value +[`ConstKind::Value`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/consts/type.ConstKind.html#variant.Value [const_arg_has_type]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.ClauseKind.html#variant.ConstArgHasType [`ParamEnv`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.ParamEnv.html [`generics_of`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#impl-TyCtxt%3C'tcx%3E/method.generics_of From ff6341671f2ae918cd819c14d7d981a38c56911f Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Sat, 19 Sep 2026 12:15:24 +0600 Subject: [PATCH 0887/1309] add tests that the lint still fires outside the macro argument case --- ...-parens-macro-pat-issue-86959.e2018.stderr | 42 +++++++++++++++++++ ...-parens-macro-pat-issue-86959.e2021.stderr | 42 +++++++++++++++++++ .../unused-parens-macro-pat-issue-86959.rs | 29 ++++++++++++- 3 files changed, 112 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lint/unused-parens-macro-pat-issue-86959.e2018.stderr create mode 100644 tests/ui/lint/unused-parens-macro-pat-issue-86959.e2021.stderr diff --git a/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2018.stderr b/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2018.stderr new file mode 100644 index 0000000000000..4a04b5b3d1fe2 --- /dev/null +++ b/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2018.stderr @@ -0,0 +1,42 @@ +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:76:16 + | +LL | match_pat!(('a')); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-macro-pat-issue-86959.rs:9:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - match_pat!(('a')); +LL + match_pat!('a'); + | + +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:54:13 + | +LL | macro_rules! body_or_pat { +... +LL | ('a' | 'A') => {} + | ^^^^^^^^^^^ +... +LL | body_or_pat!(); + | -------------- in this macro invocation + +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:80:9 + | +LL | let (_x) = 1; + | ^ ^ + | +help: remove these parentheses + | +LL - let (_x) = 1; +LL + let _x = 1; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2021.stderr b/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2021.stderr new file mode 100644 index 0000000000000..4a04b5b3d1fe2 --- /dev/null +++ b/tests/ui/lint/unused-parens-macro-pat-issue-86959.e2021.stderr @@ -0,0 +1,42 @@ +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:76:16 + | +LL | match_pat!(('a')); + | ^ ^ + | +note: the lint level is defined here + --> $DIR/unused-parens-macro-pat-issue-86959.rs:9:9 + | +LL | #![deny(unused_parens)] + | ^^^^^^^^^^^^^ +help: remove these parentheses + | +LL - match_pat!(('a')); +LL + match_pat!('a'); + | + +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:54:13 + | +LL | macro_rules! body_or_pat { +... +LL | ('a' | 'A') => {} + | ^^^^^^^^^^^ +... +LL | body_or_pat!(); + | -------------- in this macro invocation + +error: unnecessary parentheses around pattern + --> $DIR/unused-parens-macro-pat-issue-86959.rs:80:9 + | +LL | let (_x) = 1; + | ^ ^ + | +help: remove these parentheses + | +LL - let (_x) = 1; +LL + let _x = 1; + | + +error: aborting due to 3 previous errors + diff --git a/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs b/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs index 3e41cb22c5aad..9db969f4635cd 100644 --- a/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs +++ b/tests/ui/lint/unused-parens-macro-pat-issue-86959.rs @@ -1,4 +1,3 @@ -//@ check-pass //@ revisions: e2018 e2021 //@[e2018] edition: 2018 //@[e2021] edition: 2021 @@ -42,6 +41,22 @@ macro_rules! nested_pat { }; } +// `body_or_pat!()` breaks the context leg. its a `PatKind::Or`, but the parens and the arm +// both come from the macro body so they share one `SyntaxContext`, `eq_ctxt` is true and +// `avoid_or` is false. these are the macro authors own parens, no metavariable involved, so +// removing them is safe. this is the case that matters most: `from_expansion()` is true here +// and `!eq_ctxt` is false, so if the gate were ever keyed on "are we inside a macro" instead +// of "did this cross a context boundary" it would be wrongly silenced. nothing else in the +// file detects that. +macro_rules! body_or_pat { + () => { + match 'a' { + ('a' | 'A') => {} //~ ERROR unnecessary parentheses around pattern + _ => {} + } + }; +} + fn main() { // `$p:pat` only accepts a top-level `|` from edition 2021 onwards. match_pat!(('a' | 'A')); @@ -51,4 +66,16 @@ fn main() { nested_pat!((1 | 2)); // A leading `..=` is rejected by both fragment specifiers. rust-lang/rust#120737 match_pat!((..='a' | 'z')); + + // `match_pat!(('a'))` breaks the or leg. `avoid_or` is true, since the pattern arrives + // through `$p:pat` and its `SyntaxContext` differs from the arms. but the inner pattern is + // `PatKind::Expr`, not `PatKind::Or`, so `unused.rs:676` never matches and the lint fires. + // the suggestion rewrites the call site to `match_pat!('a')`, which is right — `$p:pat` + // takes a bare literal. this guards against widening the gate to all patterns, or moving + // the `avoid_or` check above the `match inner.kind`. + match_pat!(('a')); //~ ERROR unnecessary parentheses around pattern + body_or_pat!(); + // `let (_x) = 1;` is the no-macro baseline for the `check_expr` call site, one of the four + // that went from a hardcoded `false` to a computed value. + let (_x) = 1; //~ ERROR unnecessary parentheses around pattern } From 46d3d7e8687d5564a445cd02d5ef05fe32917cf5 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 11:15:47 +0000 Subject: [PATCH 0888/1309] introduce `generic_param_to_arg` helper --- .../src/deriving/coerce_pointee.rs | 11 ++----- .../src/deriving/generic/mod.rs | 24 +++++++-------- .../src/deriving/reborrow.rs | 29 +++---------------- 3 files changed, 17 insertions(+), 47 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index ab9037331050e..fa341dc311863 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -43,15 +43,8 @@ pub(crate) fn expand_deriving_coerce_pointee( }; // Convert generic parameters (from the struct) into generic args. - let self_params: Vec<_> = generics - .params - .iter() - .map(|p| match p.kind { - GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(p.span(), p.ident)), - GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(p.span(), p.ident)), - GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(p.span(), p.ident)), - }) - .collect(); + let self_params: Vec<_> = + generics.params.iter().map(|p| generic_param_to_arg(cx, p, p.span())).collect(); let type_params: Vec<_> = generics .params .iter() diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 71329da76c481..73268f2a2e520 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -182,8 +182,8 @@ pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentKind, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; use rustc_ast::{ - AttrArgs, DelimArgs, EnumDef, Expr, GenericArg, GenericParamKind, Generics, Safety, SelfKind, - VariantData, + AttrArgs, DelimArgs, EnumDef, Expr, GenericArg, GenericParam, GenericParamKind, Generics, + Safety, SelfKind, VariantData, }; use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; @@ -708,17 +708,7 @@ impl<'a> TraitDef<'a> { let self_params: Vec<_> = generics .params .iter() - .map(|param| match param.kind { - GenericParamKind::Lifetime => { - GenericArg::Lifetime(cx.lifetime(param.ident.span.with_ctxt(ctxt), param.ident)) - } - GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(param.ident.span.with_ctxt(ctxt), param.ident)) - } - GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(param.ident.span.with_ctxt(ctxt), param.ident)) - } - }) + .map(|param| generic_param_to_arg(cx, param, param.ident.span.with_ctxt(ctxt))) .collect(); // Create the type of `self`. @@ -1239,3 +1229,11 @@ fn create_struct_field_access_fields( .collect() }) } + +pub(crate) fn generic_param_to_arg(cx: &ExtCtxt<'_>, p: &GenericParam, span: Span) -> GenericArg { + match p.kind { + GenericParamKind::Lifetime => GenericArg::Lifetime(cx.lifetime(span, p.ident)), + GenericParamKind::Type { .. } => GenericArg::Type(cx.ty_ident(span, p.ident)), + GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(span, p.ident)), + } +} diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index dc45b1a896bc9..30998ea74b578 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -37,15 +37,7 @@ pub(crate) fn expand_deriving_coerce_shared( return; }; - push_marker_impl( - cx, - span, - ident, - generics, - sym::CoerceShared, - vec![GenericArg::Type(target)], - push, - ); + push_marker_impl(cx, span, ident, generics, sym::CoerceShared, vec![target], push); } fn struct_def<'a>( @@ -114,7 +106,7 @@ fn push_marker_impl( ident: Ident, generics: &Generics, trait_name: Symbol, - trait_args: Vec, + trait_args: Vec>, push: &mut dyn FnMut(Box), ) { let mut trait_parts = path!(span, core::marker); @@ -122,21 +114,8 @@ fn push_marker_impl( let trait_path = cx.path_all(span, true, trait_parts, trait_args); let trait_ref = cx.trait_ref(trait_path); - let self_params: Vec<_> = generics - .params - .iter() - .map(|param| match param.kind { - GenericParamKind::Lifetime => { - GenericArg::Lifetime(cx.lifetime(param.span(), param.ident)) - } - GenericParamKind::Type { .. } => { - GenericArg::Type(cx.ty_ident(param.span(), param.ident)) - } - GenericParamKind::Const { .. } => { - GenericArg::Const(cx.const_ident(param.span(), param.ident)) - } - }) - .collect(); + let self_params: Vec<_> = + generics.params.iter().map(|p| generic_param_to_arg(cx, p, p.span())).collect(); let self_ty = cx.ty_path(cx.path_all(span, false, vec![ident], self_params)); push(cx.item( From 9fdcfdd5a19147574a8e55ec147ee38b624677e7 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Sep 2026 17:00:16 +0200 Subject: [PATCH 0889/1309] Option, Result: not all arguments passed to map_or are eagerly evaluated --- library/core/src/option.rs | 4 ++-- library/core/src/result.rs | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/library/core/src/option.rs b/library/core/src/option.rs index 2fe7c8c305afe..f53eb4a294194 100644 --- a/library/core/src/option.rs +++ b/library/core/src/option.rs @@ -1202,9 +1202,9 @@ impl Option { /// Returns the provided default result (if none), /// or applies a function to the contained value (if any). /// - /// Arguments passed to `map_or` are eagerly evaluated; if you are passing + /// The `default` argument passed to `map_or` is eagerly evaluated; if you are passing /// the result of a function call, it is recommended to use [`map_or_else`], - /// which is lazily evaluated. + /// which lazily evaluates `default`. /// /// [`map_or_else`]: Option::map_or_else /// diff --git a/library/core/src/result.rs b/library/core/src/result.rs index 472d568c5cf66..f1d412eeefcf3 100644 --- a/library/core/src/result.rs +++ b/library/core/src/result.rs @@ -842,9 +842,9 @@ impl Result { /// Returns the provided default (if [`Err`]), or /// applies a function to the contained value (if [`Ok`]). /// - /// Arguments passed to `map_or` are eagerly evaluated; if you are passing + /// The `default` argument passed to `map_or` is eagerly evaluated; if you are passing /// the result of a function call, it is recommended to use [`map_or_else`], - /// which is lazily evaluated. + /// which lazily evaluates `default`. /// /// [`map_or_else`]: Result::map_or_else /// From 3b2363d3cec7acb4a501ddd000992c40a2b59b72 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 26 Sep 2026 17:09:08 +0200 Subject: [PATCH 0890/1309] use is_some_and / is_none_or in a few more places --- compiler/rustc_ast_pretty/src/pprust/state.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- compiler/rustc_borrowck/src/polonius/liveness.rs | 2 +- compiler/rustc_codegen_ssa/src/back/symbol_export.rs | 5 ++--- compiler/rustc_const_eval/src/interpret/step.rs | 2 +- compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 2 +- compiler/rustc_mir_transform/src/liveness.rs | 4 ++-- compiler/rustc_passes/src/check_attr.rs | 2 +- compiler/rustc_passes/src/stability.rs | 2 +- compiler/rustc_resolve/src/late/diagnostics.rs | 2 +- 10 files changed, 12 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 6637ed356f557..70893c4982175 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -621,7 +621,7 @@ pub trait PrintState<'a>: std::ops::Deref + std::ops::Dere // Isolated, starts with #! and doesn't continue with `[` // See [rustc_lexer::strip_shebang] and [gather_comments] from pprust/state.rs for details if cmnt.style == CommentStyle::Isolated - && cmnt.lines.first().map_or(false, |l| l.starts_with("#!")) + && cmnt.lines.first().is_some_and(|l| l.starts_with("#!")) { let cmnt = self.next_comment().unwrap(); self.print_comment(cmnt); diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index f3667ac63de30..c35c7ab311572 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -347,7 +347,7 @@ fn borrowck_collect_region_constraints<'tcx>( let location_map = Rc::new(DenseLocationMap::new(body)); - let polonius_input = root_cx.consumer.as_ref().map_or(false, |c| c.polonius_input()) + let polonius_input = root_cx.consumer.as_ref().is_some_and(|c| c.polonius_input()) || infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled(); let mut polonius_facts = (polonius_input || PoloniusFacts::enabled(infcx.tcx)).then_some(PoloniusFacts::default()); diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 346f3622ebdbb..83f56082f27da 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -52,7 +52,7 @@ impl<'a> RegionLiveness<'a> { } pub(super) fn is_live_at(&self, point: PointIndex) -> bool { - self.live_points.map_or(false, |points| points.contains(point)) + self.live_points.is_some_and(|points| points.contains(point)) } } diff --git a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs index c0e525471aeeb..64e10d03185bb 100644 --- a/compiler/rustc_codegen_ssa/src/back/symbol_export.rs +++ b/compiler/rustc_codegen_ssa/src/back/symbol_export.rs @@ -354,9 +354,8 @@ fn exported_generic_symbols_provider_local<'tcx>( .types() .chain(did.into_iter().map(move |did| tcx.type_of(did).skip_binder())) .all(move |arg| { - arg.walk().all(|ty| { - ty.as_type().map_or(true, |ty| !is_local_to_current_crate(ty)) - }) + arg.walk() + .all(|ty| ty.as_type().is_none_or(|ty| !is_local_to_current_crate(ty))) }) }; diff --git a/compiler/rustc_const_eval/src/interpret/step.rs b/compiler/rustc_const_eval/src/interpret/step.rs index 561c2b79343ff..e9f1d06187cd6 100644 --- a/compiler/rustc_const_eval/src/interpret/step.rs +++ b/compiler/rustc_const_eval/src/interpret/step.rs @@ -583,7 +583,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { with_caller_location, &dest_place, target, - if fn_abi.map_or(false, |fn_abi| fn_abi.can_unwind) { + if fn_abi.is_some_and(|fn_abi| fn_abi.can_unwind) { unwind } else { mir::UnwindAction::Unreachable diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 16c4549bfbc6e..b3c005b963398 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1027,7 +1027,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .segments .last() .and_then(|seg| seg.args) - .map_or(false, |args| !args.constraints.is_empty()) + .is_some_and(|args| !args.constraints.is_empty()) { // Use the path to get the trait name string let trait_name = trait_ref diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index dc716c1886102..ba116be7e8488 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -415,7 +415,7 @@ fn find_self_assignments<'tcx>( // We ignore indirect self-assignment, because both occurrences of `dest` are uses. let is_indirect = checked_places .get(dest.as_ref()) - .map_or(false, |(_, projections)| is_indirect(projections)); + .is_some_and(|(_, projections)| is_indirect(projections)); if is_indirect { continue; } @@ -1100,7 +1100,7 @@ impl<'a, 'tcx> AssignmentResult<'a, 'tcx> { let outer_initializer_span = initializer_span.find_ancestor_in_same_ctxt(source_info.span); within.is_none() - && outer_initializer_span.map_or(true, |s| !s.contains(source_info.span)) + && outer_initializer_span.is_none_or(|s| !s.contains(source_info.span)) }); } diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 4926ec9872d3b..3e06b787a78be 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -1346,7 +1346,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { sym::expect, ]) && let Some(meta) = attr.meta_item_list() && meta.iter().any(|meta| { - meta.meta_item().map_or(false, |item| { + meta.meta_item().is_some_and(|item| { item.path == sym::linker_messages || item.path == sym::linker_info }) }) diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index 0cac0f5129c8a..d607d929b0db6 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -337,7 +337,7 @@ impl<'tcx> MissingStabilityAnnotations<'tcx> { } if stab.is_none() - && depr.map_or(false, |d| d.attr.is_since_rustc_version()) + && depr.is_some_and(|d| d.attr.is_since_rustc_version()) && let Some(span) = find_attr_span!(Deprecated) { self.tcx.dcx().emit_err(diagnostics::DeprecatedAttribute { span }); diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 84c07d0fb0f44..cdef92b389265 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -3577,7 +3577,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { None } }) - .map_or(false, |pos| pos > idx) + .is_some_and(|pos| pos > idx) }); let (insert_span, snippet) = match next_impl_param { From f5c85c8d3035f4818d1b0fb7bd59272a443f1d21 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Thu, 24 Sep 2026 13:13:54 +0200 Subject: [PATCH 0891/1309] Document `rustc_abi::VariantLayout` Follow-up to https://github.com/rust-lang/rust/pull/151742. --- compiler/rustc_abi/src/lib.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 56cfbf138af00..5322b451fc6e8 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2450,12 +2450,22 @@ pub enum AbiFromStrErr { NoExplicitUnwind, } +/// The layout information for a variant. +/// +/// For items with multiple variants ([`Variants::Multiple`]), the layout information of each +/// variant largely matches that of the overall item. So, instead of giving each one a new [`LayoutData`], +/// we use this struct, which stores only the information that differs between the variants. +/// +/// See for more context. // NOTE: This struct is generic over the FieldIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(StableHash))] pub struct VariantLayout { + // FIXME: ideally we'd remove these as variants should not have their own + // size or backend_repr. pub size: Size, pub backend_repr: BackendRepr, + pub field_offsets: IndexVec, fields_in_memory_order: IndexVec, largest_niche: Option, From 284af39d64d0fa81b70650e3609e83a7998d1532 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:04:48 +0200 Subject: [PATCH 0892/1309] Use a let-chain This whole section of the code deals with constructing an alternative layout, but large nesting makes the control flow seem more complex than it actually is. --- compiler/rustc_abi/src/layout.rs | 93 +++++++++++++++----------------- 1 file changed, 44 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index e8779d6ee6869..f808285edbef5 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -281,58 +281,53 @@ impl LayoutCalculator { // If the default field ordering does not give us a niche at the front then we do a second // run and bias niches to the right and then check which one is closer to one of the // struct's edges. - if let Ok(layout) = &layout { + if let Ok(layout) = &layout // Don't try to calculate an end-biased layout for unsizable structs, // otherwise we could end up with different layouts for // Foo and Foo which would break unsizing. - if !matches!(kind, StructKind::MaybeUnsized) { - if let Some(niche) = layout.largest_niche { - let head_space = niche.offset.bytes(); - let niche_len = niche.value.size(dl).bytes(); - let tail_space = layout.size.bytes() - head_space - niche_len; - - // This may end up doing redundant work if the niche is already in the last - // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial - // to get the unpadded size so we try anyway. - if fields.len() > 1 && head_space != 0 && tail_space > 0 { - let alt_layout = self - .univariant_biased(fields, repr, kind, NicheBias::End) - .expect("alt layout should always work"); - let alt_niche = alt_layout - .largest_niche - .expect("alt layout should have a niche like the regular one"); - let alt_head_space = alt_niche.offset.bytes(); - let alt_niche_len = alt_niche.value.size(dl).bytes(); - let alt_tail_space = - alt_layout.size.bytes() - alt_head_space - alt_niche_len; - - debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); - - let prefer_alt_layout = - alt_head_space > head_space && alt_head_space > tail_space; - - debug!( - "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ - layout: {}\n\ - alt_layout: {}\n", - layout.size.bytes(), - head_space, - niche_len, - tail_space, - alt_head_space, - alt_niche_len, - alt_tail_space, - layout.fields.count(), - prefer_alt_layout, - self.format_field_niches(layout, fields), - self.format_field_niches(&alt_layout, fields), - ); - - if prefer_alt_layout { - return Ok(alt_layout); - } - } - } + && !matches!(kind, StructKind::MaybeUnsized) + && let Some(niche) = layout.largest_niche + && let head_space = niche.offset.bytes() + && let niche_len = niche.value.size(dl).bytes() + && let tail_space = layout.size.bytes() - head_space - niche_len + // This may end up doing redundant work if the niche is already in the last + // field (e.g. a trailing bool) and there is tail padding. But it's non-trivial + // to get the unpadded size so we try anyway. + && (fields.len() > 1 && head_space != 0 && tail_space > 0) + { + let alt_layout = self + .univariant_biased(fields, repr, kind, NicheBias::End) + .expect("alt layout should always work"); + let alt_niche = alt_layout + .largest_niche + .expect("alt layout should have a niche like the regular one"); + let alt_head_space = alt_niche.offset.bytes(); + let alt_niche_len = alt_niche.value.size(dl).bytes(); + let alt_tail_space = alt_layout.size.bytes() - alt_head_space - alt_niche_len; + + debug_assert_eq!(layout.size.bytes(), alt_layout.size.bytes()); + + let prefer_alt_layout = alt_head_space > head_space && alt_head_space > tail_space; + + debug!( + "sz: {}, default_niche_at: {}+{}, default_tail_space: {}, alt_niche_at/head_space: {}+{}, alt_tail: {}, num_fields: {}, better: {}\n\ + layout: {}\n\ + alt_layout: {}\n", + layout.size.bytes(), + head_space, + niche_len, + tail_space, + alt_head_space, + alt_niche_len, + alt_tail_space, + layout.fields.count(), + prefer_alt_layout, + self.format_field_niches(layout, fields), + self.format_field_niches(&alt_layout, fields), + ); + + if prefer_alt_layout { + return Ok(alt_layout); } } layout From d2b3f9b61f30c99ad8de91d8f5d2caa901a592cc Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:12:02 +0200 Subject: [PATCH 0893/1309] Remove needless laziness Constructing these error variants is basically free --- compiler/rustc_abi/src/layout.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index f808285edbef5..89ee4a27e9c33 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -1479,15 +1479,13 @@ where }; // Compute the size and alignment of the vector - let size = elt - .size - .checked_mul(count.as_u64(), dl) - .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?; + let size = + elt.size.checked_mul(count.as_u64(), dl).ok_or(LayoutCalculatorError::SizeOverflow)?; let (repr, size, align) = match kind { SimdVectorKind::Scalable(number_of_vectors) => ( BackendRepr::SimdScalableVector { element, count, number_of_vectors }, size.checked_mul(number_of_vectors.0 as u64, dl) - .ok_or_else(|| LayoutCalculatorError::SizeOverflow)?, + .ok_or(LayoutCalculatorError::SizeOverflow)?, dl.rust_vector_align(size), ), // Non-power-of-two vectors have padding up to the next power-of-two. From 6c333a9e0dfc23d5ef889198e5198a814067e4b9 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:16:17 +0200 Subject: [PATCH 0894/1309] Move complex clauses to the where clause Having the generic list span multiple lines is quite jarring, and imo easy to confuse with the parameter list at a glance. --- compiler/rustc_abi/src/layout.rs | 114 ++++++++++----------- compiler/rustc_abi/src/layout/coroutine.rs | 16 +-- 2 files changed, 65 insertions(+), 65 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 89ee4a27e9c33..e867d4da7bf3e 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -239,20 +239,20 @@ impl LayoutCalculator { /// /// This uses dedicated code instead of [`Self::layout_of_struct_or_enum`], as coroutine /// fields may be shared between multiple variants (see the [`coroutine`] module for details). - pub fn coroutine< - 'a, - F: Deref> + fmt::Debug + Copy, - VariantIdx: Idx, - FieldIdx: Idx, - LocalIdx: Idx, - >( + pub fn coroutine<'a, F, VariantIdx, FieldIdx, LocalIdx>( &self, local_layouts: &IndexSlice, prefix_layouts: IndexVec, variant_fields: &IndexSlice>, storage_conflicts: &BitMatrix, tag_to_layout: impl Fn(Scalar) -> F, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + F: Deref> + fmt::Debug + Copy, + VariantIdx: Idx, + FieldIdx: Idx, + LocalIdx: Idx, + { coroutine::layout( self, local_layouts, @@ -263,17 +263,17 @@ impl LayoutCalculator { ) } - pub fn univariant< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + pub fn univariant<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); let layout = self.univariant_biased(fields, repr, kind, NicheBias::Start); // Enums prefer niches close to the beginning or the end of the variants so that other @@ -333,12 +333,7 @@ impl LayoutCalculator { layout } - pub fn layout_of_struct_or_enum< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + pub fn layout_of_struct_or_enum<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, @@ -347,7 +342,12 @@ impl LayoutCalculator { discr_range_of_repr: impl Fn(RangeFrom, RangeToInclusive) -> (Integer, bool), discriminants: impl Iterator, always_sized: bool, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let (present_first, present_second) = { let mut present_variants = variants.iter_enumerated().filter_map(|(i, v)| { if !repr.inhibit_enum_layout_opt() && absent(v) { None } else { Some(i) } @@ -387,16 +387,16 @@ impl LayoutCalculator { } } - pub fn layout_of_union< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + pub fn layout_of_union<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); let mut align = if repr.pack.is_some() { dl.i8_align } else { dl.aggregate_align }; let mut max_repr_align = repr.align; @@ -515,12 +515,7 @@ impl LayoutCalculator { } /// single-variant enums are just structs, if you think about it - fn layout_of_struct< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + fn layout_of_struct<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, @@ -528,7 +523,12 @@ impl LayoutCalculator { is_special_no_niche: bool, always_sized: bool, present_first: VariantIdx, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { // Struct, or univariant enum equivalent to a struct. // (Typechecking will reject discriminant-sizing attrs.) @@ -568,18 +568,18 @@ impl LayoutCalculator { Ok(st) } - fn layout_of_enum< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + fn layout_of_enum<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, variants: &IndexSlice>, discr_range_of_repr: impl Fn(RangeFrom, RangeToInclusive) -> (Integer, bool), discriminants: impl Iterator, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); // bail if the enum has an incoherent repr that cannot be computed if repr.packed() { @@ -1073,18 +1073,18 @@ impl LayoutCalculator { Ok(best_layout) } - fn univariant_biased< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug + Copy, - >( + fn univariant_biased<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, kind: StructKind, niche_bias: NicheBias, - ) -> LayoutCalculatorResult { + ) -> LayoutCalculatorResult + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug + Copy, + { let dl = self.cx.data_layout(); let pack = repr.pack; let mut align = if pack.is_some() { dl.i8_align } else { dl.aggregate_align }; @@ -1419,16 +1419,16 @@ impl LayoutCalculator { }) } - fn format_field_niches< - 'a, - FieldIdx: Idx, - VariantIdx: Idx, - F: Deref> + fmt::Debug, - >( + fn format_field_niches<'a, FieldIdx, VariantIdx, F>( &self, layout: &LayoutData, fields: &IndexSlice, - ) -> String { + ) -> String + where + FieldIdx: Idx, + VariantIdx: Idx, + F: Deref> + fmt::Debug, + { let dl = self.cx.data_layout(); let mut s = String::new(); for i in layout.fields.index_by_increasing_offset() { diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs index fd68d06c93829..4a1cb5bc86fc4 100644 --- a/compiler/rustc_abi/src/layout/coroutine.rs +++ b/compiler/rustc_abi/src/layout/coroutine.rs @@ -136,20 +136,20 @@ fn coroutine_saved_local_eligibility> + core::fmt::Debug + Copy, - VariantIdx: Idx, - FieldIdx: Idx, - LocalIdx: Idx, ->( +pub(super) fn layout<'a, F, VariantIdx, FieldIdx, LocalIdx>( calc: &super::LayoutCalculator, local_layouts: &IndexSlice, mut prefix_layouts: IndexVec, variant_fields: &IndexSlice>, storage_conflicts: &BitMatrix, tag_to_layout: impl Fn(Scalar) -> F, -) -> super::LayoutCalculatorResult { +) -> super::LayoutCalculatorResult +where + F: core::ops::Deref> + core::fmt::Debug + Copy, + VariantIdx: Idx, + FieldIdx: Idx, + LocalIdx: Idx, +{ use SavedLocalEligibility::*; let (ineligible_locals, assignments) = From 38d0d1762beed5cb5512c66a01ef918de3b47b62 Mon Sep 17 00:00:00 2001 From: Orson Peters Date: Sat, 20 Jun 2026 21:03:37 +0200 Subject: [PATCH 0895/1309] Guarantee 8 bytes of alignment of RawWakerVTable --- library/core/src/task/wake.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs index 473b185d24652..1dbd11426e57e 100644 --- a/library/core/src/task/wake.rs +++ b/library/core/src/task/wake.rs @@ -90,6 +90,8 @@ impl RawWaker { /// pointers to *different* functions can compare equal (since identical functions can be /// deduplicated within a codegen unit). /// +/// This struct is guaranteed to be aligned to at least 8 bytes. +/// /// # Thread safety /// If the [`RawWaker`] will be used to construct a [`Waker`] then /// these functions must all be thread-safe (even though [`RawWaker`] is @@ -106,6 +108,8 @@ impl RawWaker { #[stable(feature = "futures_api", since = "1.36.0")] #[allow(unpredictable_function_pointer_comparisons)] #[derive(PartialEq, Copy, Clone, Debug)] +// For bit-stuffing pointers we guarantee align >= 8. +#[repr(align(8))] pub struct RawWakerVTable { /// This function will be called when the [`RawWaker`] gets cloned, e.g. when /// the [`Waker`] in which the [`RawWaker`] is stored gets cloned. From 49577f8f4555c6e1f140958b2f6caf714266aa8f Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sat, 26 Sep 2026 14:24:16 -0400 Subject: [PATCH 0896/1309] GVN transmutes of Immediate::Uninit to Immediate::Uninit --- compiler/rustc_mir_transform/src/gvn.rs | 3 ++ tests/mir-opt/const_prop/maybe_uninit.rs | 7 ++++ ...maybe_uninit.u8_array_assume_init.GVN.diff | 36 +++++++++++++++++++ 3 files changed, 46 insertions(+) create mode 100644 tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 81a41be1c62da..b5fa022a527e5 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -725,6 +725,9 @@ impl<'body, 'a, 'tcx> VnState<'body, 'a, 'tcx> { } CastKind::Transmute | CastKind::Subtype => { let value = self.eval_to_const(value)?; + if value.is_immediate_uninit() { + return Some(ImmTy::uninit(ty).into()); + } // `offset` for immediates generally only supports projections that match the // type of the immediate. However, as a HACK, we exploit that it can also do // limited transmutes: it only works between types with the same layout, and diff --git a/tests/mir-opt/const_prop/maybe_uninit.rs b/tests/mir-opt/const_prop/maybe_uninit.rs index 649fea6252216..89c395a7be5bb 100644 --- a/tests/mir-opt/const_prop/maybe_uninit.rs +++ b/tests/mir-opt/const_prop/maybe_uninit.rs @@ -8,3 +8,10 @@ pub fn u8_array() -> [MaybeUninit; 8] { // CHECK: _0 = const ; [MaybeUninit::uninit(); 8] } + +// EMIT_MIR maybe_uninit.u8_array_assume_init.GVN.diff +pub fn u8_array_assume_init() -> [MaybeUninit; 8] { + // CHECK: fn u8_array_assume_init( + // CHECK: _0 = const ; + unsafe { MaybeUninit::uninit().assume_init() } +} diff --git a/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff new file mode 100644 index 0000000000000..e0c4af329fadc --- /dev/null +++ b/tests/mir-opt/const_prop/maybe_uninit.u8_array_assume_init.GVN.diff @@ -0,0 +1,36 @@ +- // MIR for `u8_array_assume_init` before GVN ++ // MIR for `u8_array_assume_init` after GVN + + fn u8_array_assume_init() -> [MaybeUninit; 8] { + let mut _0: [std::mem::MaybeUninit; 8]; + let mut _1: std::mem::MaybeUninit<[std::mem::MaybeUninit; 8]>; + scope 1 (inlined MaybeUninit::<[MaybeUninit; 8]>::uninit) { + } + scope 2 (inlined #[track_caller] MaybeUninit::<[MaybeUninit; 8]>::assume_init) { + scope 3 (inlined transmute_neo::; 8]>, [MaybeUninit; 8]>) { + } + } + + bb0: { + StorageLive(_1); +- _1 = MaybeUninit::<[MaybeUninit; 8]> { uninit: const () }; ++ _1 = const ; + goto -> bb1; + } + + bb1: { +- _0 = copy _1 as [std::mem::MaybeUninit; 8] (Transmute); ++ _0 = const ; + StorageDead(_1); + return; + } ++ } ++ ++ ALLOC0 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ ++ } ++ ++ ALLOC1 (size: 8, align: 1) { ++ __ __ __ __ __ __ __ __ │ ░░░░░░░░ + } + From faddebf35248c543587db20a2a1f8b558bd5b950 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 26 Sep 2026 14:43:04 -0400 Subject: [PATCH 0897/1309] Bump semver stamp --- src/bootstrap/stdlib-semver-check-stamp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/stdlib-semver-check-stamp b/src/bootstrap/stdlib-semver-check-stamp index a2f33f00e3ec3..fad994b27f122 100644 --- a/src/bootstrap/stdlib-semver-check-stamp +++ b/src/bootstrap/stdlib-semver-check-stamp @@ -2,4 +2,4 @@ Change this file to explicitly acknowledge making a breaking change to the Rust If this file is modified in the same PR as the breaking change, then CI will not fail due to the breaking change being detected by cargo-semver-checks. -Last change is for: https://github.com/rust-lang/rust/pull/162909 +Last change is for: https://github.com/rust-lang/rust/pull/158186 From 12f4d4e15c2227348c7e25aea2cdd0926db19286 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 11:17:39 +0000 Subject: [PATCH 0898/1309] remove the `path!` macro There are already way too many helpers to construct paths in this crate and this one is not very useful. --- .../src/deriving/coerce_pointee.rs | 17 ++++++----------- .../src/deriving/reborrow.rs | 11 ++++------- 2 files changed, 10 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index fa341dc311863..d915db0dd3b0d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -12,12 +12,10 @@ use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; +use crate::deriving::generic::*; +use crate::deriving::{new_path, path_std}; use crate::diagnostics; -macro_rules! path { - ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } -} - pub(crate) fn expand_deriving_coerce_pointee( cx: &ExtCtxt<'_>, span: Span, @@ -91,8 +89,7 @@ pub(crate) fn expand_deriving_coerce_pointee( let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),]; // # Validity assertion which will be checked later in `rustc_hir_analysis::coherence::builtins`. { - let trait_path = - cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]); + let trait_path = path_std!(cx, span, marker::CoercePointeeValidated); let trait_ref = cx.trait_ref(trait_path); push( cx.item( @@ -137,9 +134,7 @@ pub(crate) fn expand_deriving_coerce_pointee( ); } let mut add_impl_block = |generics, trait_symbol, trait_args| { - let mut parts = path!(span, core::ops); - parts.push(Ident::new(trait_symbol, span)); - let trait_path = cx.path_all(span, true, parts, trait_args); + let trait_path = new_path(cx, span, &[sym::ops, trait_symbol], trait_args); let trait_ref = cx.trait_ref(trait_path); let item = cx.item( span, @@ -189,7 +184,7 @@ pub(crate) fn expand_deriving_coerce_pointee( return; } let arg = GenericArg::Type(s_ty.clone()); - let unsize = cx.path_all(span, true, path!(span, core::marker::Unsize), vec![arg]); + let unsize = cx.path_all(span, true, cx.std_path(&[sym::marker, sym::Unsize]), vec![arg]); pointee.bounds.push(cx.trait_bound(unsize, false)); // Drop `#[pointee]` attribute since it should not be recognized outside `derive(CoercePointee)` pointee.attrs.retain(|attr| !attr.has_name(sym::pointee)); @@ -310,7 +305,7 @@ pub(crate) fn expand_deriving_coerce_pointee( impl_generics.params.insert(pointee_param_idx + 1, extra_param); // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. - let gen_args = vec![GenericArg::Type(alt_self_type)]; + let gen_args = vec![alt_self_type]; add_impl_block(impl_generics.clone(), sym::DispatchFromDyn, gen_args.clone()); add_impl_block(impl_generics, sym::CoerceUnsized, gen_args); } diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index 30998ea74b578..d25e77b136829 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -1,13 +1,12 @@ -use rustc_ast::{self as ast, AttrArgs, GenericArg, GenericParamKind, Generics, ItemKind, token}; +use rustc_ast::{self as ast, AttrArgs, GenericParamKind, Generics, ItemKind, token}; use rustc_errors::E0802; use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; use rustc_span::{Ident, Span, Symbol, sym}; use thin_vec::ThinVec; -macro_rules! path { - ($span:expr, $($part:ident)::*) => { vec![$(Ident::new(sym::$part, $span),)*] } -} +use crate::deriving::generic::*; +use crate::deriving::new_path; pub(crate) fn expand_deriving_reborrow( cx: &ExtCtxt<'_>, @@ -109,9 +108,7 @@ fn push_marker_impl( trait_args: Vec>, push: &mut dyn FnMut(Box), ) { - let mut trait_parts = path!(span, core::marker); - trait_parts.push(Ident::new(trait_name, span)); - let trait_path = cx.path_all(span, true, trait_parts, trait_args); + let trait_path = new_path(cx, span, &[sym::core, sym::marker, trait_name], trait_args); let trait_ref = cx.trait_ref(trait_path); let self_params: Vec<_> = From 345eb2c0a43aa80d939858c91df5d2d8e2724f30 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 12:18:08 +0000 Subject: [PATCH 0899/1309] add `generics_without_defaults` helper --- .../src/deriving/coerce_pointee.rs | 61 ++++++------------- .../src/deriving/generic/mod.rs | 21 +++++++ .../src/deriving/reborrow.rs | 33 +--------- 3 files changed, 41 insertions(+), 74 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index d915db0dd3b0d..2e73713a53293 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -2,8 +2,8 @@ use ast::HasAttrs; use rustc_ast::mut_visit::MutVisitor; use rustc_ast::visit::{BoundKind, Visitor}; use rustc_ast::{ - self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, - TraitBoundModifiers, VariantData, WherePredicate, + self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, TraitBoundModifiers, + VariantData, WherePredicate, }; use rustc_data_structures::flat_map_in_place::FlatMapInPlace; use rustc_errors::E0802; @@ -91,47 +91,22 @@ pub(crate) fn expand_deriving_coerce_pointee( { let trait_path = path_std!(cx, span, marker::CoercePointeeValidated); let trait_ref = cx.trait_ref(trait_path); - push( - cx.item( - span, - attrs.clone(), - ast::ItemKind::Impl(ast::Impl { - generics: Generics { - params: generics - .params - .iter() - .map(|p| match &p.kind { - GenericParamKind::Lifetime => { - cx.lifetime_param(p.span(), p.ident, p.bounds.clone()) - } - GenericParamKind::Type { default: _ } => { - cx.typaram(p.span(), p.ident, p.bounds.clone(), None) - } - GenericParamKind::Const { ty, span: _, default: _ } => cx - .const_param( - p.span(), - p.ident, - p.bounds.clone(), - ty.clone(), - None, - ), - }) - .collect(), - where_clause: generics.where_clause.clone(), - span: generics.span, - }, - of_trait: Some(Box::new(ast::TraitImplHeader { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Implicit, - trait_ref, - })), - constness: ast::Const::No, - self_ty: self_type.clone(), - items: ThinVec::new(), - }), - ), - ); + push(cx.item( + span, + attrs.clone(), + ast::ItemKind::Impl(ast::Impl { + generics: generics_without_defaults(generics), + of_trait: Some(Box::new(ast::TraitImplHeader { + safety: ast::Safety::Default, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Implicit, + trait_ref, + })), + constness: ast::Const::No, + self_ty: self_type.clone(), + items: ThinVec::new(), + }), + )); } let mut add_impl_block = |generics, trait_symbol, trait_args| { let trait_path = new_path(cx, span, &[sym::ops, trait_symbol], trait_args); diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 73268f2a2e520..4a1560bc79af7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1237,3 +1237,24 @@ pub(crate) fn generic_param_to_arg(cx: &ExtCtxt<'_>, p: &GenericParam, span: Spa GenericParamKind::Const { .. } => GenericArg::Const(cx.const_ident(span, p.ident)), } } + +pub(crate) fn generics_without_defaults(g: &Generics) -> Generics { + Generics { + params: g + .params + .iter() + .map(|p| { + let mut p = p.clone(); + match &mut p.kind { + ast::GenericParamKind::Const { default, .. } => *default = None, + ast::GenericParamKind::Type { default } => *default = None, + ast::GenericParamKind::Lifetime => {} + }; + p.attrs.clear(); + p + }) + .collect(), + where_clause: g.where_clause.clone(), + span: g.span, + } +} diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index d25e77b136829..8231e84f8299e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -1,4 +1,4 @@ -use rustc_ast::{self as ast, AttrArgs, GenericParamKind, Generics, ItemKind, token}; +use rustc_ast::{self as ast, AttrArgs, Generics, ItemKind, token}; use rustc_errors::E0802; use rustc_expand::base::ExtCtxt; use rustc_macros::Diagnostic; @@ -119,7 +119,7 @@ fn push_marker_impl( span, thin_vec::thin_vec![cx.attr_word(sym::automatically_derived, span)], ast::ItemKind::Impl(ast::Impl { - generics: impl_generics(cx, generics), + generics: generics_without_defaults(generics), of_trait: Some(Box::new(ast::TraitImplHeader { safety: ast::Safety::Default, polarity: ast::ImplPolarity::Positive, @@ -133,35 +133,6 @@ fn push_marker_impl( )); } -fn impl_generics(cx: &ExtCtxt<'_>, generics: &Generics) -> Generics { - // Rebuild the generic parameter declarations because defaults are allowed on structs but - // rejected on impls. Preserve lifetime, type, and const parameters and their bounds, const - // parameter types, and the where-clause, while omitting type and const defaults. - Generics { - params: generics - .params - .iter() - .map(|param| match ¶m.kind { - GenericParamKind::Lifetime => { - cx.lifetime_param(param.span(), param.ident, param.bounds.clone()) - } - GenericParamKind::Type { default: _ } => { - cx.typaram(param.span(), param.ident, param.bounds.clone(), None) - } - GenericParamKind::Const { ty, span: _, default: _ } => cx.const_param( - param.span(), - param.ident, - param.bounds.clone(), - ty.clone(), - None, - ), - }) - .collect(), - where_clause: generics.where_clause.clone(), - span: generics.span, - } -} - #[derive(Diagnostic)] #[diag("`derive({$trait_name})` is only supported for structs, not {$kind}s", code = E0802)] struct UnsupportedItem { From d9b202f6747c03994328597ece67e61dc8d8f196 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 13:18:50 +0000 Subject: [PATCH 0900/1309] add `item_trait_impl` helper --- .../src/deriving/coerce_pointee.rs | 41 +++++++------------ .../src/deriving/generic/mod.rs | 22 ++++------ .../src/deriving/reborrow.rs | 20 ++++----- compiler/rustc_expand/src/build.rs | 29 +++++++++++++ 4 files changed, 58 insertions(+), 54 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 2e73713a53293..9223006538f91 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -90,42 +90,29 @@ pub(crate) fn expand_deriving_coerce_pointee( // # Validity assertion which will be checked later in `rustc_hir_analysis::coherence::builtins`. { let trait_path = path_std!(cx, span, marker::CoercePointeeValidated); - let trait_ref = cx.trait_ref(trait_path); - push(cx.item( + push(cx.item_trait_impl( span, attrs.clone(), - ast::ItemKind::Impl(ast::Impl { - generics: generics_without_defaults(generics), - of_trait: Some(Box::new(ast::TraitImplHeader { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Implicit, - trait_ref, - })), - constness: ast::Const::No, - self_ty: self_type.clone(), - items: ThinVec::new(), - }), + generics_without_defaults(generics), + ast::Safety::Default, + false, + cx.trait_ref(trait_path), + self_type.clone(), + ThinVec::new(), )); } let mut add_impl_block = |generics, trait_symbol, trait_args| { let trait_path = new_path(cx, span, &[sym::ops, trait_symbol], trait_args); let trait_ref = cx.trait_ref(trait_path); - let item = cx.item( + let item = cx.item_trait_impl( span, attrs.clone(), - ast::ItemKind::Impl(ast::Impl { - generics, - of_trait: Some(Box::new(ast::TraitImplHeader { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Implicit, - trait_ref, - })), - constness: ast::Const::No, - self_ty: self_type.clone(), - items: ThinVec::new(), - }), + generics, + ast::Safety::Default, + false, + trait_ref, + self_type.clone(), + ThinVec::new(), ); push(item); }; diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 4a1560bc79af7..b6d5f42964e1f 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -188,7 +188,7 @@ use rustc_ast::{ use rustc_attr_ir::{Attribute, AttributeKind, ReprPacked}; use rustc_attr_parsing::AttributeParser; use rustc_expand::base::ExtCtxt; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; +use rustc_span::{Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; @@ -760,21 +760,15 @@ impl<'a> TraitDef<'a> { attrs.push(cx.attr_nested_word(sym::doc, sym::hidden, self.span)); } - cx.item( + cx.item_trait_impl( self.span, attrs, - ast::ItemKind::Impl(ast::Impl { - generics: trait_generics, - of_trait: Some(Box::new(ast::TraitImplHeader { - safety: self.safety, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Implicit, - trait_ref, - })), - constness: if self.is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, - self_ty: self_type, - items: methods.collect(), - }), + trait_generics, + self.safety, + self.is_const, + trait_ref, + self_type, + methods.collect(), ) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs index 8231e84f8299e..05ad76dbd1ff9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/reborrow.rs +++ b/compiler/rustc_builtin_macros/src/deriving/reborrow.rs @@ -115,21 +115,15 @@ fn push_marker_impl( generics.params.iter().map(|p| generic_param_to_arg(cx, p, p.span())).collect(); let self_ty = cx.ty_path(cx.path_all(span, false, vec![ident], self_params)); - push(cx.item( + push(cx.item_trait_impl( span, thin_vec::thin_vec![cx.attr_word(sym::automatically_derived, span)], - ast::ItemKind::Impl(ast::Impl { - generics: generics_without_defaults(generics), - of_trait: Some(Box::new(ast::TraitImplHeader { - safety: ast::Safety::Default, - polarity: ast::ImplPolarity::Positive, - defaultness: ast::Defaultness::Implicit, - trait_ref, - })), - constness: ast::Const::No, - self_ty, - items: ThinVec::new(), - }), + generics_without_defaults(generics), + ast::Safety::Default, + false, + trait_ref, + self_ty, + ThinVec::new(), )); } diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 9a93d82a4fe4c..03e6128cf84f1 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -702,6 +702,35 @@ impl<'a> ExtCtxt<'a> { }) } + pub fn item_trait_impl( + &self, + span: Span, + attrs: ast::AttrVec, + generics: ast::Generics, + safety: ast::Safety, + is_const: bool, + trait_ref: ast::TraitRef, + self_ty: Box, + items: ThinVec>, + ) -> Box { + self.item( + span, + attrs, + ast::ItemKind::Impl(ast::Impl { + generics, + of_trait: Some(Box::new(ast::TraitImplHeader { + safety, + polarity: ast::ImplPolarity::Positive, + defaultness: ast::Defaultness::Implicit, + trait_ref, + })), + constness: if is_const { ast::Const::Yes(DUMMY_SP) } else { ast::Const::No }, + self_ty, + items, + }), + ) + } + pub fn item_static( &self, span: Span, From d2ed22fc450dc873544e9ad6750690bac57acbf0 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 24 Sep 2026 22:15:09 +0000 Subject: [PATCH 0901/1309] remove redundant span argument In all cases, the passed span was already the span of the ident. --- .../src/deriving/coerce_pointee.rs | 2 +- .../src/deriving/generic/mod.rs | 2 +- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- compiler/rustc_expand/src/build.rs | 15 ++++----------- 4 files changed, 7 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs index 9223006538f91..7d0db12a450d6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs +++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs @@ -263,7 +263,7 @@ pub(crate) fn expand_deriving_coerce_pointee( } } - let extra_param = cx.typaram(span, Ident::new(sym::__S, span), self_bounds, None); + let extra_param = cx.typaram(Ident::new(sym::__S, span), self_bounds, None); impl_generics.params.insert(pointee_param_idx + 1, extra_param); // Add the impl blocks for `DispatchFromDyn` and `CoerceUnsized`. diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index b6d5f42964e1f..8b15920511aca 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -610,7 +610,7 @@ impl<'a> TraitDef<'a> { ) .collect(); - cx.typaram(span, param.ident, bounds, None) + cx.typaram(param.ident, bounds, None) } GenericParamKind::Const { ty, span, .. } => { let const_nodefault_kind = GenericParamKind::Const { diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 3d3023b39955d..3e0722988155c 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -21,7 +21,7 @@ pub(crate) fn expand_deriving_hash( let param = { let path = path_std!(cx, span, hash::Hasher); - cx.typaram(span, typaram, thin_vec![cx.trait_bound(path, false)], None) + cx.typaram(typaram, thin_vec![cx.trait_bound(path, false)], None) }; let generics = ast::Generics { diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 03e6128cf84f1..5f9d6b905601b 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -138,13 +138,12 @@ impl<'a> ExtCtxt<'a> { pub fn typaram( &self, - span: Span, ident: Ident, bounds: ast::GenericBounds, default: Option>, ) -> ast::GenericParam { ast::GenericParam { - ident: ident.with_span_pos(span), + ident, id: ast::DUMMY_NODE_ID, attrs: AttrVec::new(), bounds, @@ -154,15 +153,10 @@ impl<'a> ExtCtxt<'a> { } } - pub fn lifetime_param( - &self, - span: Span, - ident: Ident, - bounds: ast::GenericBounds, - ) -> ast::GenericParam { + pub fn lifetime_param(&self, ident: Ident, bounds: ast::GenericBounds) -> ast::GenericParam { ast::GenericParam { id: ast::DUMMY_NODE_ID, - ident: ident.with_span_pos(span), + ident, attrs: AttrVec::new(), bounds, is_placeholder: false, @@ -173,7 +167,6 @@ impl<'a> ExtCtxt<'a> { pub fn const_param( &self, - span: Span, ident: Ident, bounds: ast::GenericBounds, ty: Box, @@ -181,7 +174,7 @@ impl<'a> ExtCtxt<'a> { ) -> ast::GenericParam { ast::GenericParam { id: ast::DUMMY_NODE_ID, - ident: ident.with_span_pos(span), + ident, attrs: AttrVec::new(), bounds, is_placeholder: false, From dc45d5da4b621f1fb86046669b4ae71cfa3c9a07 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 24 Sep 2026 22:24:21 +0000 Subject: [PATCH 0902/1309] remove entirely unused `cx` methods --- compiler/rustc_expand/src/build.rs | 70 ------------------------------ 1 file changed, 70 deletions(-) diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 5f9d6b905601b..4c8ab40cf649a 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -268,10 +268,6 @@ impl<'a> ExtCtxt<'a> { self.stmt_local(local, span) } - pub fn stmt_semi(&self, expr: Box) -> ast::Stmt { - ast::Stmt { id: ast::DUMMY_NODE_ID, span: expr.span, kind: ast::StmtKind::Semi(expr) } - } - pub fn stmt_local(&self, local: Box, span: Span) -> ast::Stmt { ast::Stmt { id: ast::DUMMY_NODE_ID, kind: ast::StmtKind::Let(local), span } } @@ -371,12 +367,6 @@ impl<'a> ExtCtxt<'a> { ) -> Box { self.expr(span, ast::ExprKind::Call(expr, args)) } - pub fn expr_loop(&self, sp: Span, block: Box) -> Box { - self.expr(sp, ast::ExprKind::Loop(block, None, sp)) - } - pub fn expr_asm(&self, sp: Span, expr: Box) -> Box { - self.expr(sp, ast::ExprKind::InlineAsm(expr)) - } pub fn expr_call_ident( &self, span: Span, @@ -483,64 +473,17 @@ impl<'a> ExtCtxt<'a> { self.expr(sp, ast::ExprKind::Tup(exprs)) } - pub fn expr_unreachable(&self, span: Span) -> Box { - self.expr_macro_call( - span, - self.macro_call( - span, - self.path_global( - span, - [sym::std, sym::unreachable].map(|s| Ident::new(s, span)).to_vec(), - ), - Delimiter::Parenthesis, - TokenStream::default(), - ), - ) - } - pub fn expr_ok(&self, sp: Span, expr: Box) -> Box { let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); self.expr_call_global(sp, ok, thin_vec![expr]) } - pub fn expr_try(&self, sp: Span, head: Box) -> Box { - let ok = self.std_path(&[sym::result, sym::Result, sym::Ok]); - let ok_path = self.path_global(sp, ok); - let err = self.std_path(&[sym::result, sym::Result, sym::Err]); - let err_path = self.path_global(sp, err); - - let binding_variable = Ident::new(sym::__try_var, sp); - let binding_pat = self.pat_ident(sp, binding_variable); - let binding_expr = self.expr_ident(sp, binding_variable); - - // `Ok(__try_var)` pattern - let ok_pat = self.pat_tuple_struct(sp, ok_path, thin_vec![binding_pat.clone()]); - - // `Err(__try_var)` (pattern and expression respectively) - let err_pat = self.pat_tuple_struct(sp, err_path.clone(), thin_vec![binding_pat]); - let err_inner_expr = - self.expr_call(sp, self.expr_path(err_path), thin_vec![binding_expr.clone()]); - // `return Err(__try_var)` - let err_expr = self.expr(sp, ast::ExprKind::Ret(Some(err_inner_expr))); - - // `Ok(__try_var) => __try_var` - let ok_arm = self.arm(sp, ok_pat, binding_expr); - // `Err(__try_var) => return Err(__try_var)` - let err_arm = self.arm(sp, err_pat, err_expr); - - // `match head { Ok() => ..., Err() => ... }` - self.expr_match(sp, head, thin_vec![ok_arm, err_arm]) - } - pub fn pat(&self, span: Span, kind: PatKind) -> ast::Pat { ast::Pat { id: ast::DUMMY_NODE_ID, kind, span } } pub fn pat_wild(&self, span: Span) -> ast::Pat { self.pat(span, PatKind::Wild) } - pub fn pat_lit(&self, span: Span, expr: Box) -> ast::Pat { - self.pat(span, PatKind::Expr(expr)) - } pub fn pat_ident(&self, span: Span, ident: Ident) -> ast::Pat { self.pat_ident_binding_mode(span, ident, ast::BindingMode::NONE) } @@ -595,10 +538,6 @@ impl<'a> ExtCtxt<'a> { } } - pub fn arm_unreachable(&self, span: Span) -> ast::Arm { - self.arm(span, self.pat_wild(span), self.expr_unreachable(span)) - } - pub fn expr_match( &self, span: Span, @@ -655,15 +594,6 @@ impl<'a> ExtCtxt<'a> { self.lambda(span, vec![ident], body) } - pub fn lambda_stmts_1( - &self, - span: Span, - stmts: ThinVec, - ident: Ident, - ) -> Box { - self.lambda1(span, self.expr_block(self.block(span, stmts)), ident) - } - pub fn param(&self, span: Span, ident: Ident, ty: Box) -> ast::Param { let pat = Box::new(self.pat_ident(span, ident)); ast::Param { From 01d2c4087d4288f09e7e32fb91b0a9df75f7cafe Mon Sep 17 00:00:00 2001 From: conferatur <309554028+conferatur@users.noreply.github.com> Date: Sat, 26 Sep 2026 14:39:26 -0700 Subject: [PATCH 0903/1309] add automatically_derived documentation --- library/core/src/attribute_docs.rs | 74 ++++++++++++++++++++++++++++++ 1 file changed, 74 insertions(+) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 584e1583c9bdb..97629be8ec6ef 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -633,3 +633,77 @@ const _: () = (); /// /// [the `non_exhaustive` attribute]: ../reference/attributes/type_system.html#the-non_exhaustive-attribute const _: () = (); + +#[doc(attribute = "automatically_derived")] +// +/// The `automatically_derived` attribute is used to indicate that an `impl` block is automatically +/// generated by a [derive macro]. It has no direct effect, but it may be used by tools and +/// diagnostic lints, such as [Clippy], to detect these automatically generated implementations. +/// +/// Example: +/// +/// ```rust +/// // Given #[derive(Clone)] on struct Example, the derive macro may produce: +/// #[automatically_derived] +/// impl ::core::clone::Clone for Example { +/// fn clone(&self) -> Self { Example } +/// } +/// # struct Example; +/// ``` +/// +/// The attribute may only be applied to an `impl` block. +/// +/// Because code generated by a macro becomes part of the source code representation of the crate +/// that calls the macro, diagnostic lints for the expanded macro will be emitted in the caller's +/// workspace (whereas warnings generated while building dependencies not in the local workspace +/// are suppressed by Cargo). This may be undesirable, so the author of the macro can use the +/// `automatically_derived` attribute to hint to tools that the generated code is not written by the +/// caller (and that tools should not render warnings for it). +/// +/// For example, this `impl` block lacks `#[automatically_derived]`: +/// +/// ```rust +/// // Suppose this impl block is the output of a derive macro +/// impl ::core::cmp::PartialEq for Example { +/// fn eq(&self, other: &Self) -> bool { true } +/// fn ne(&self, other: &Self) -> bool { !(self == other) } +/// } +/// # struct Example; +/// ``` +/// +/// In the example above, Clippy will emit the following warning: +/// +/// ```text +/// warning: re-implementing `PartialEq::ne` is unnecessary +/// --> src/lib.rs:7:9 +/// | +/// 4 | fn ne(&self, other: &Self) -> bool { !(self == other) } +/// | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +/// | +/// = help: for further information visit https://rust-lang.github.io/rust-clippy/rust-1.98.0/index.html#partialeq_ne_impl +/// = note: `#[warn(clippy::partialeq_ne_impl)]` on by default +/// ``` +/// +/// However, if the derive macro were written so that it outputs `#[automatically_derived]` on the +/// `impl` block, as below, then Clippy will not emit the above `partialeq_ne_impl` lint: +/// +/// ```rust +/// // Suppose this impl block is the output of a derive macro +/// #[automatically_derived] +/// impl ::core::cmp::PartialEq for Example { +/// fn eq(&self, other: &Self) -> bool { true } +/// fn ne(&self, other: &Self) -> bool { !(self == other) } +/// } +/// # struct Example; +/// ``` +/// +/// The `automatically_derived` attribute should be preferred over the [`allow`] attribute for +/// suppressing unintended user-facing diagnostics in automatically generated code. +/// +/// For more information, see the Reference on [the `automatically_derived` attribute]. +/// +/// [`allow`]: ./attribute.allow.html +/// [derive macro]: ./attr.derive.html +/// [Clippy]: https://github.com/rust-lang/rust-clippy +/// [the `automatically_derived` attribute]: ../reference/attributes/derive.html#the-automatically_derived-attribute +const _: () = (); From e1dfc384188c45b8b43e6de7e61bcc7377d56ceb Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:58:47 +0200 Subject: [PATCH 0904/1309] Add `layout_of_` prefix to all the layout-calculating methods Improves consistency, and hopefully clarifies the purpose of previously-mysteriosly named methods like `univariant`. --- compiler/rustc_abi/src/layout.rs | 22 +++++++++++----------- compiler/rustc_abi/src/layout/coroutine.rs | 9 ++++++--- compiler/rustc_ty_utils/src/layout.rs | 14 +++++++------- 3 files changed, 24 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index e867d4da7bf3e..a10548d1a6059 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -178,7 +178,7 @@ impl LayoutCalculator { Self { cx } } - pub fn array_like( + pub fn layout_of_array_like( &self, element: &LayoutData, count_if_sized: Option, // None for slices @@ -201,7 +201,7 @@ impl LayoutCalculator { }) } - pub fn scalable_vector_type( + pub fn layout_of_scalable_vector_type( &self, element: F, count: u64, @@ -220,7 +220,7 @@ impl LayoutCalculator { ) } - pub fn simd_type( + pub fn layout_of_simd_type( &self, element: F, count: u64, @@ -239,7 +239,7 @@ impl LayoutCalculator { /// /// This uses dedicated code instead of [`Self::layout_of_struct_or_enum`], as coroutine /// fields may be shared between multiple variants (see the [`coroutine`] module for details). - pub fn coroutine<'a, F, VariantIdx, FieldIdx, LocalIdx>( + pub fn layout_of_coroutine<'a, F, VariantIdx, FieldIdx, LocalIdx>( &self, local_layouts: &IndexSlice, prefix_layouts: IndexVec, @@ -263,7 +263,7 @@ impl LayoutCalculator { ) } - pub fn univariant<'a, FieldIdx, VariantIdx, F>( + pub fn layout_of_univariant<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, @@ -275,7 +275,7 @@ impl LayoutCalculator { F: Deref> + fmt::Debug + Copy, { let dl = self.cx.data_layout(); - let layout = self.univariant_biased(fields, repr, kind, NicheBias::Start); + let layout = self.layout_of_univariant_biased(fields, repr, kind, NicheBias::Start); // Enums prefer niches close to the beginning or the end of the variants so that other // (smaller) data-carrying variants can be packed into the space after/before the niche. // If the default field ordering does not give us a niche at the front then we do a second @@ -296,7 +296,7 @@ impl LayoutCalculator { && (fields.len() > 1 && head_space != 0 && tail_space > 0) { let alt_layout = self - .univariant_biased(fields, repr, kind, NicheBias::End) + .layout_of_univariant_biased(fields, repr, kind, NicheBias::End) .expect("alt layout should always work"); let alt_niche = alt_layout .largest_niche @@ -540,7 +540,7 @@ impl LayoutCalculator { StructKind::MaybeUnsized }; - let mut st = self.univariant(&variants[v], repr, kind)?; + let mut st = self.layout_of_univariant(&variants[v], repr, kind)?; st.variants = Variants::Single { index: v }; if is_special_no_niche { @@ -608,7 +608,7 @@ impl LayoutCalculator { let mut variant_layouts = variants .iter() .map(|v| { - let st = self.univariant(v, repr, StructKind::AlwaysSized).ok()?; + let st = self.layout_of_univariant(v, repr, StructKind::AlwaysSized).ok()?; variants_info.push(VariantLayoutInfo { align_abi: st.align.abi }); @@ -810,7 +810,7 @@ impl LayoutCalculator { let mut layout_variants = variants .iter() .map(|field_layouts| { - let st = self.univariant( + let st = self.layout_of_univariant( field_layouts, repr, StructKind::Prefixed(min_ity.size(), prefix_align), @@ -1073,7 +1073,7 @@ impl LayoutCalculator { Ok(best_layout) } - fn univariant_biased<'a, FieldIdx, VariantIdx, F>( + fn layout_of_univariant_biased<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, repr: &ReprOptions, diff --git a/compiler/rustc_abi/src/layout/coroutine.rs b/compiler/rustc_abi/src/layout/coroutine.rs index 4a1cb5bc86fc4..c102fbb3e843c 100644 --- a/compiler/rustc_abi/src/layout/coroutine.rs +++ b/compiler/rustc_abi/src/layout/coroutine.rs @@ -171,8 +171,11 @@ where let promoted_layouts = ineligible_locals.iter().map(|local| local_layouts[local]); prefix_layouts.push(tag_to_layout(tag)); prefix_layouts.extend(promoted_layouts); - let prefix = - calc.univariant(&prefix_layouts, &ReprOptions::default(), StructKind::AlwaysSized)?; + let prefix = calc.layout_of_univariant( + &prefix_layouts, + &ReprOptions::default(), + StructKind::AlwaysSized, + )?; let (prefix_size, prefix_align) = (prefix.size, prefix.align); @@ -225,7 +228,7 @@ where }) .map(|local| local_layouts[*local]); - let mut variant = calc.univariant( + let mut variant = calc.layout_of_univariant( &variant_only_tys.collect::>(), &ReprOptions::default(), StructKind::Prefixed(prefix_size, prefix_align.abi), diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ef1241266cac6..ab9437abeb2ce 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -235,7 +235,7 @@ fn layout_of_uncached<'tcx>( let univariant = |tys: &[Ty<'tcx>], kind| { let fields = tys.iter().map(|ty| cx.layout_of(*ty)).try_collect::>()?; let repr = ReprOptions::default(); - map_layout(cx.calc.univariant(&fields, &repr, kind)) + map_layout(cx.calc.layout_of_univariant(&fields, &repr, kind)) }; debug_assert!(!ty.has_non_region_infer()); @@ -523,11 +523,11 @@ fn layout_of_uncached<'tcx>( .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?; let element = cx.layout_of(element)?; - map_layout(cx.calc.array_like(&element, Some(count)))? + map_layout(cx.calc.layout_of_array_like(&element, Some(count)))? } ty::Slice(element) => { let element = cx.layout_of(element)?; - map_layout(cx.calc.array_like(&element, None).map(|mut layout| { + map_layout(cx.calc.layout_of_array_like(&element, None).map(|mut layout| { // a randomly chosen value to distinguish slices layout.randomization_seed = Hash64::new(0x2dcba99c39784102); layout @@ -535,7 +535,7 @@ fn layout_of_uncached<'tcx>( } ty::Str => { let element = scalar(Int(I8, false)); - map_layout(cx.calc.array_like(&element, None).map(|mut layout| { + map_layout(cx.calc.layout_of_array_like(&element, None).map(|mut layout| { // another random value layout.randomization_seed = Hash64::new(0xc1325f37d127be22); layout @@ -586,7 +586,7 @@ fn layout_of_uncached<'tcx>( let layout = cx .calc - .coroutine( + .layout_of_coroutine( &local_layouts, prefix_layouts, &info.variant_fields, @@ -638,7 +638,7 @@ fn layout_of_uncached<'tcx>( }; let element_layout = cx.layout_of(element_ty)?; - map_layout(cx.calc.scalable_vector_type( + map_layout(cx.calc.layout_of_scalable_vector_type( element_layout, element_count as u64, number_of_vectors, @@ -683,7 +683,7 @@ fn layout_of_uncached<'tcx>( } } - map_layout(cx.calc.simd_type(e_ly, e_len, def.repr().packed()))? + map_layout(cx.calc.layout_of_simd_type(e_ly, e_len, def.repr().packed()))? } // ADTs. From c22ad42ed8423bb2c7872f01468830f9f9886d01 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 27 Sep 2026 04:36:24 +0000 Subject: [PATCH 0905/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to c23137133458bf7a49f4a55d3adb9e2c7c33bd79. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ab61f3f74a54a..2579ec7acaec9 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -0d38a842626a6e3b70e2c1efd76a8f22d2556d73 +c23137133458bf7a49f4a55d3adb9e2c7c33bd79 From b90cbcbabf4f0af8b4710f7d33fa0ee04337acc8 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 25 Sep 2026 10:32:29 +0000 Subject: [PATCH 0906/1309] Use StaticAllocator in more places --- library/alloc/src/boxed.rs | 2 +- library/alloc/src/rc.rs | 8 ++++---- library/alloc/src/sync.rs | 10 +++++----- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 64dee11196a84..7504763120532 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -2455,7 +2455,7 @@ impl + Unpin, R, A: Allocator> Coroutine for Box, R, A: Allocator> Coroutine for Pin> where - A: 'static, + A: StaticAllocator, { type Yield = G::Yield; type Return = G::Return; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rc.rs index 0571f50b8a23b..8cca09d1d4a8c 100644 --- a/library/alloc/src/rc.rs +++ b/library/alloc/src/rc.rs @@ -266,7 +266,7 @@ use core::ptr::{self, NonNull, drop_in_place}; use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout}; +use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] use crate::alloc::{AllocatorNightly, handle_alloc_error}; use crate::borrow::{Cow, ToOwned}; @@ -953,7 +953,7 @@ impl Rc { #[inline] pub fn pin_in(value: T, alloc: A) -> Pin where - A: 'static, + A: StaticAllocator, { // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Rc::new_in(value, alloc)) } @@ -2549,11 +2549,11 @@ impl Deref for Rc { // accordingly. Since this type is not fundamental, downstream crates cannot // provide malicious implementations of any of the traits relevant for `Pin`. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for Rc {} +unsafe impl PinSafePointer for Rc {} //#[unstable(feature = "unique_rc_arc", issue = "112566")] #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for UniqueRc {} +unsafe impl PinSafePointer for UniqueRc {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Rc {} diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs index 13e70a436234c..e412cee62d8f6 100644 --- a/library/alloc/src/sync.rs +++ b/library/alloc/src/sync.rs @@ -33,7 +33,7 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::sync::atomic::{self, Atomic}; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout}; +use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] use crate::alloc::{AllocatorNightly, handle_alloc_error}; use crate::borrow::{Cow, ToOwned}; @@ -893,7 +893,7 @@ impl Arc { #[inline] pub fn pin_in(data: T, alloc: A) -> Pin> where - A: 'static, + A: StaticAllocator, { // SAFETY: We own and create the pinned pointer. unsafe { Pin::new_unchecked(Arc::new_in(data, alloc)) } @@ -905,7 +905,7 @@ impl Arc { #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub fn try_pin_in(data: T, alloc: A) -> Result>, AllocError> where - A: 'static, + A: StaticAllocator, { // SAFETY: We own and create the pinned pointer. unsafe { Ok(Pin::new_unchecked(Arc::try_new_in(data, alloc)?)) } @@ -2580,7 +2580,7 @@ impl Deref for Arc { // crates cannot provide malicious implementations of any of the traits relevant // for `Pin`. #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for Arc {} +unsafe impl PinSafePointer for Arc {} #[unstable(feature = "deref_pure_trait", issue = "87121")] unsafe impl DerefPure for Arc {} @@ -5127,7 +5127,7 @@ impl Deref for UniqueArc { // #[unstable(feature = "unique_rc_arc", issue = "112566")] #[unstable(feature = "pin_coerce_unsized_trait", issue = "150112")] -unsafe impl PinSafePointer for UniqueArc {} +unsafe impl PinSafePointer for UniqueArc {} #[unstable(feature = "unique_rc_arc", issue = "112566")] impl DerefMut for UniqueArc { From c2c6786937a56462eff7f789db7c559ba8d83611 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Sun, 27 Sep 2026 09:32:09 +0200 Subject: [PATCH 0907/1309] simplify rust_log a bit --- compiler/rustc_log/src/lib.rs | 23 ++++------------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs index 9976690a0c1f1..fdf9c1be22067 100644 --- a/compiler/rustc_log/src/lib.rs +++ b/compiler/rustc_log/src/lib.rs @@ -130,25 +130,10 @@ where Err(VarError::NotUnicode(_value)) => return Err(Error::NonUnicodeColorValue), }; - let verbose_entry_exit = match cfg.verbose_entry_exit { - Ok(v) => &v != "0", - Err(_) => false, - }; - - let verbose_thread_ids = match cfg.verbose_thread_ids { - Ok(v) => &v == "1", - Err(_) => false, - }; - - let lines = match cfg.lines { - Ok(v) => &v == "1", - Err(_) => false, - }; - - let json = match cfg.json { - Ok(v) => &v == "1", - Err(_) => false, - }; + let verbose_entry_exit = cfg.verbose_entry_exit.is_ok_and(|v| v != "0"); + let verbose_thread_ids = cfg.verbose_thread_ids.is_ok_and(|v| v == "1"); + let lines = cfg.lines.is_ok_and(|v| v == "1"); + let json = cfg.json.is_ok_and(|v| v == "1"); let output_target: BoxMakeWriter = match cfg.output_target { Ok(v) => match File::options().create(true).write(true).truncate(true).open(&v) { From 75d4b23b6f27d9829539c2c2c98d30be98ef6491 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sosth=C3=A8ne=20Gu=C3=A9don?= Date: Sun, 27 Sep 2026 11:01:39 +0200 Subject: [PATCH 0908/1309] Fix link to the allocator-ext feature tracking issue This was missing in 4eb7bb33234293cbc0b4bebfc5e37e6eaffeddda --- src/doc/unstable-book/src/library-features/allocator-ext.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/unstable-book/src/library-features/allocator-ext.md b/src/doc/unstable-book/src/library-features/allocator-ext.md index f1e7551bdfa08..6e374f0743f89 100644 --- a/src/doc/unstable-book/src/library-features/allocator-ext.md +++ b/src/doc/unstable-book/src/library-features/allocator-ext.md @@ -1,8 +1,8 @@ # `allocator_ext` -The tracking issue for this feature is [#32838] +The tracking issue for this feature is: [#163177] -[#32838]: https://github.com/rust-lang/rust/issues/32838 +[#163177]: https://github.com/rust-lang/rust/issues/163177 ------------------------ From 188011ac2901b1762e8bb9a3baaf8338cc839e55 Mon Sep 17 00:00:00 2001 From: Raushan kumar Date: Thu, 9 Jul 2026 05:49:29 +0000 Subject: [PATCH 0909/1309] test(imports): add baseline regression for hidden extern crate suggestion --- .../auxiliary/macro-generated-extern-crate.rs | 3 +++ .../ui/imports/macro-generated-extern-crate.rs | 14 ++++++++++++++ .../macro-generated-extern-crate.stderr | 18 ++++++++++++++++++ 3 files changed, 35 insertions(+) create mode 100644 tests/ui/imports/auxiliary/macro-generated-extern-crate.rs create mode 100644 tests/ui/imports/macro-generated-extern-crate.rs create mode 100644 tests/ui/imports/macro-generated-extern-crate.stderr diff --git a/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs b/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs new file mode 100644 index 0000000000000..8a2c17266b7a9 --- /dev/null +++ b/tests/ui/imports/auxiliary/macro-generated-extern-crate.rs @@ -0,0 +1,3 @@ +pub trait MyTrait { + fn custom() {} +} diff --git a/tests/ui/imports/macro-generated-extern-crate.rs b/tests/ui/imports/macro-generated-extern-crate.rs new file mode 100644 index 0000000000000..a7b87efdd8fbe --- /dev/null +++ b/tests/ui/imports/macro-generated-extern-crate.rs @@ -0,0 +1,14 @@ +//@ edition: 2021 +//@ aux-build: macro-generated-extern-crate.rs + +const _: () = { + extern crate macro_generated_extern_crate as _my_crate; + impl _my_crate::MyTrait for Local {} +}; + +struct Local; + +fn main() { + Local::custom(); + //~^ ERROR no associated function or constant named `custom` found for struct `Local` +} diff --git a/tests/ui/imports/macro-generated-extern-crate.stderr b/tests/ui/imports/macro-generated-extern-crate.stderr new file mode 100644 index 0000000000000..7c022f715cac3 --- /dev/null +++ b/tests/ui/imports/macro-generated-extern-crate.stderr @@ -0,0 +1,18 @@ +error[E0599]: no associated function or constant named `custom` found for struct `Local` in the current scope + --> $DIR/macro-generated-extern-crate.rs:12:12 + | +LL | struct Local; + | ------------ associated function or constant `custom` not found for this struct +... +LL | Local::custom(); + | ^^^^^^ associated function or constant not found in `Local` + | + = help: items from traits can only be used if the trait is in scope +help: trait `MyTrait` which provides `custom` is implemented but not in scope; perhaps you want to import it + | +LL + use crate::_::_my_crate::MyTrait; + | + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0599`. From 2e4b8e5f17e7ce1bc95e35091eabe530f275a394 Mon Sep 17 00:00:00 2001 From: Raushan kumar Date: Thu, 9 Jul 2026 05:41:41 +0000 Subject: [PATCH 0910/1309] fix(metadata): demote unnameable `extern crate` items to `ExternCrateSource::Path` Use the `DefPath` to determine whether an `extern crate` item is globally nameable. `extern crate` items nested inside value namespaces cannot be referred to by a stable path outside their enclosing scope. Record them as `ExternCrateSource::Path` instead of `ExternCrateSource::Extern` so later path resolution does not reconstruct unnameable paths. --- compiler/rustc_metadata/src/creader.rs | 18 ++++- .../macro-generated-extern-crate.stderr | 2 +- .../uniform-paths/issue-87932.stderr | 2 +- tests/ui/traits/bound/same-crate-name.rs | 9 --- tests/ui/traits/bound/same-crate-name.stderr | 76 +++++-------------- .../ui/type/type-mismatch-same-crate-name.rs | 13 ++-- .../type/type-mismatch-same-crate-name.stderr | 33 +++----- 7 files changed, 52 insertions(+), 101 deletions(-) diff --git a/compiler/rustc_metadata/src/creader.rs b/compiler/rustc_metadata/src/creader.rs index aea843ac0384c..10693448ea685 100644 --- a/compiler/rustc_metadata/src/creader.rs +++ b/compiler/rustc_metadata/src/creader.rs @@ -15,7 +15,7 @@ use rustc_data_structures::sync::{self, FreezeReadGuard, FreezeWriteGuard}; use rustc_data_structures::unord::UnordMap; use rustc_expand::base::SyntaxExtension; use rustc_hir::def_id::{CrateNum, LOCAL_CRATE, LocalDefId, StableCrateId}; -use rustc_hir::definitions::Definitions; +use rustc_hir::definitions::{DefPathData, Definitions}; use rustc_index::IndexVec; use rustc_lint_defs as lint; use rustc_lint_defs::builtin::UNUSED_CRATE_DEPENDENCIES; @@ -1358,14 +1358,24 @@ impl CStore { let cnum = self.resolve_crate(tcx, name, item.span, dep_kind, CrateOrigin::Extern)?; - let path_len = definitions.def_path(def_id).data.len(); + let def_path = definitions.def_path(def_id); + // An extern crate is only globally nameable if every segment in its path + // is in the type namespace (i.e., it is purely nested inside modules). + // If any segment is in the value namespace (e.g. inside a fn or const), + // it is unnameable from outside that block. + let is_unnameable = + def_path.data.iter().any(|d| !matches!(d.data, DefPathData::TypeNs(_))); self.update_extern_crate( cnum, name, ExternCrate { - src: ExternCrateSource::Extern(def_id.to_def_id()), + src: if is_unnameable { + ExternCrateSource::Path + } else { + ExternCrateSource::Extern(def_id.to_def_id()) + }, span: item.span, - path_len, + path_len: if is_unnameable { usize::MAX } else { def_path.data.len() }, dependency_of: LOCAL_CRATE, }, ); diff --git a/tests/ui/imports/macro-generated-extern-crate.stderr b/tests/ui/imports/macro-generated-extern-crate.stderr index 7c022f715cac3..e103b185789ac 100644 --- a/tests/ui/imports/macro-generated-extern-crate.stderr +++ b/tests/ui/imports/macro-generated-extern-crate.stderr @@ -10,7 +10,7 @@ LL | Local::custom(); = help: items from traits can only be used if the trait is in scope help: trait `MyTrait` which provides `custom` is implemented but not in scope; perhaps you want to import it | -LL + use crate::_::_my_crate::MyTrait; +LL + use macro_generated_extern_crate::MyTrait; | error: aborting due to 1 previous error diff --git a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr index c408b747b506f..ff069320f413d 100644 --- a/tests/ui/rust-2018/uniform-paths/issue-87932.stderr +++ b/tests/ui/rust-2018/uniform-paths/issue-87932.stderr @@ -10,7 +10,7 @@ LL | A::deserialize(); = help: items from traits can only be used if the trait is in scope help: trait `Deserialize` which provides `deserialize` is implemented but not in scope; perhaps you want to import it | -LL + use ::deserialize::_a::Deserialize; +LL + use issue_87932_a::Deserialize; | error: aborting due to 1 previous error diff --git a/tests/ui/traits/bound/same-crate-name.rs b/tests/ui/traits/bound/same-crate-name.rs index acd4894612872..5de6620bf4856 100644 --- a/tests/ui/traits/bound/same-crate-name.rs +++ b/tests/ui/traits/bound/same-crate-name.rs @@ -32,15 +32,11 @@ fn main() { extern crate crate_a1 as a; a::try_foo(foo); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `implements_no_traits` has no impl for `Foo` a::try_foo(implements_no_traits); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `other_variant_implements_mismatched_trait` @@ -48,16 +44,11 @@ fn main() { // only for its `` variant. a::try_foo(other_variant_implements_mismatched_trait); //~^ ERROR E0277 - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree // We don't want to see the "version mismatch" help message here // because `ImplementsTraitForUsize` only has // impls for the correct trait where the path is not misleading. a::try_foo(other_variant_implements_correct_trait); //~^ ERROR E0277 - //~| HELP the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph - //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/traits/bound/same-crate-name.stderr b/tests/ui/traits/bound/same-crate-name.stderr index 9e5e110f8624e..27cad715b0738 100644 --- a/tests/ui/traits/bound/same-crate-name.stderr +++ b/tests/ui/traits/bound/same-crate-name.stderr @@ -1,23 +1,13 @@ -error[E0277]: the trait bound `Foo: main::a::Bar` is not satisfied +error[E0277]: the trait bound `Foo: crate_a1::Bar` is not satisfied --> $DIR/same-crate-name.rs:33:20 | LL | a::try_foo(foo); - | ---------- ^^^ the trait `main::a::Bar` is not implemented for `Foo` + | ---------- ^^^ the trait `crate_a1::Bar` is not implemented for `Foo` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + = note: `Foo` implements similarly named trait `crate_a2::Bar`, but not `crate_a1::Bar` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -28,26 +18,15 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `DoesNotImplementTrait: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:40:20 +error[E0277]: the trait bound `DoesNotImplementTrait: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:38:20 | LL | a::try_foo(implements_no_traits); - | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `DoesNotImplementTrait` + | ---------- ^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `DoesNotImplementTrait` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the trait that was imported - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -58,26 +37,16 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `ImplementsWrongTraitConditionally: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:49:20 +error[E0277]: the trait bound `ImplementsWrongTraitConditionally: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:45:20 | LL | a::try_foo(other_variant_implements_mismatched_trait); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsWrongTraitConditionally` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `ImplementsWrongTraitConditionally` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` + = note: `ImplementsWrongTraitConditionally` implements similarly named trait `crate_a2::Bar`, but not `crate_a1::Bar` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} @@ -88,26 +57,15 @@ note: required by a bound in `try_foo` LL | pub fn try_foo(x: impl Bar) {} | ^^^ required by this bound in `try_foo` -error[E0277]: the trait bound `ImplementsTraitForUsize: main::a::Bar` is not satisfied - --> $DIR/same-crate-name.rs:57:20 +error[E0277]: the trait bound `ImplementsTraitForUsize: crate_a1::Bar` is not satisfied + --> $DIR/same-crate-name.rs:51:20 | LL | a::try_foo(other_variant_implements_correct_trait); - | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `main::a::Bar` is not implemented for `ImplementsTraitForUsize` + | ---------- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `crate_a1::Bar` is not implemented for `ImplementsTraitForUsize` | | | required by a bound introduced by this call | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the trait that was imported - = help: you can use `cargo tree` to explore your dependency tree -help: the trait `main::a::Bar` is implemented for `ImplementsTraitForUsize` +help: the trait `crate_a1::Bar` is implemented for `ImplementsTraitForUsize` --> $DIR/auxiliary/crate_a1.rs:9:1 | LL | impl Bar for ImplementsTraitForUsize {} diff --git a/tests/ui/type/type-mismatch-same-crate-name.rs b/tests/ui/type/type-mismatch-same-crate-name.rs index df6d7aba8fd69..31fd47251660e 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.rs +++ b/tests/ui/type/type-mismatch-same-crate-name.rs @@ -16,17 +16,18 @@ fn main() { extern crate crate_a1 as a; a::try_foo(foo2); //~^ ERROR mismatched types - //~| NOTE expected `main::a::Foo`, found a different `main::a::Foo` + //~| NOTE expected `crate_a1::Foo`, found `crate_a2::Foo` //~| NOTE arguments to this function are incorrect - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| NOTE `crate_a2::Foo` and `crate_a1::Foo` have similar names, but are actually distinct types + //~| NOTE `crate_a2::Foo` is defined in crate `crate_a2` + //~| NOTE `crate_a1::Foo` is defined in crate `crate_a1` //~| NOTE function defined here - //~| HELP you can use `cargo tree` to explore your dependency tree a::try_bar(bar2); //~^ ERROR mismatched types - //~| NOTE expected trait `main::a::Bar`, found a different trait `main::a::Bar` + //~| NOTE expected trait `crate_a1::Bar`, found trait `crate_a2::Bar` //~| NOTE arguments to this function are incorrect - //~| NOTE there are multiple different versions of crate `crate_a1` in the dependency graph + //~| NOTE expected struct `Box<(dyn crate_a1::Bar + 'static)>` + //~| NOTE found struct `Box` //~| NOTE function defined here - //~| HELP you can use `cargo tree` to explore your dependency tree } } diff --git a/tests/ui/type/type-mismatch-same-crate-name.stderr b/tests/ui/type/type-mismatch-same-crate-name.stderr index 2913b994e9529..71648741c2dd5 100644 --- a/tests/ui/type/type-mismatch-same-crate-name.stderr +++ b/tests/ui/type/type-mismatch-same-crate-name.stderr @@ -2,21 +2,21 @@ error[E0308]: mismatched types --> $DIR/type-mismatch-same-crate-name.rs:17:20 | LL | a::try_foo(foo2); - | ---------- ^^^^ expected `main::a::Foo`, found a different `main::a::Foo` + | ---------- ^^^^ expected `crate_a1::Foo`, found `crate_a2::Foo` | | | arguments to this function are incorrect | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:1:1 + = note: `crate_a2::Foo` and `crate_a1::Foo` have similar names, but are actually distinct types +note: `crate_a2::Foo` is defined in crate `crate_a2` + --> $DIR/auxiliary/crate_a2.rs:1:1 | LL | pub struct Foo; - | ^^^^^^^^^^^^^^ this is the expected type - | - ::: $DIR/auxiliary/crate_a2.rs:1:1 + | ^^^^^^^^^^^^^^ +note: `crate_a1::Foo` is defined in crate `crate_a1` + --> $DIR/auxiliary/crate_a1.rs:1:1 | LL | pub struct Foo; - | -------------- this is the found type - = help: you can use `cargo tree` to explore your dependency tree + | ^^^^^^^^^^^^^^ note: function defined here --> $DIR/auxiliary/crate_a1.rs:10:8 | @@ -24,24 +24,15 @@ LL | pub fn try_foo(x: Foo){} | ^^^^^^^ error[E0308]: mismatched types - --> $DIR/type-mismatch-same-crate-name.rs:24:20 + --> $DIR/type-mismatch-same-crate-name.rs:25:20 | LL | a::try_bar(bar2); - | ---------- ^^^^ expected trait `main::a::Bar`, found a different trait `main::a::Bar` + | ---------- ^^^^ expected trait `crate_a1::Bar`, found trait `crate_a2::Bar` | | | arguments to this function are incorrect | -note: there are multiple different versions of crate `crate_a1` in the dependency graph - --> $DIR/auxiliary/crate_a1.rs:3:1 - | -LL | pub trait Bar {} - | ^^^^^^^^^^^^^ this is the expected trait - | - ::: $DIR/auxiliary/crate_a2.rs:3:1 - | -LL | pub trait Bar {} - | ------------- this is the found trait - = help: you can use `cargo tree` to explore your dependency tree + = note: expected struct `Box<(dyn crate_a1::Bar + 'static)>` + found struct `Box` note: function defined here --> $DIR/auxiliary/crate_a1.rs:11:8 | From e0f657c7d072e77cca5119ba214052a960ec0c6f Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Sun, 27 Sep 2026 13:14:10 +0200 Subject: [PATCH 0911/1309] Clarify some things in the docs of `Global` --- library/alloc/src/alloc.rs | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index a900ed91d720c..de65820cf9a75 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -43,30 +43,38 @@ unsafe extern "Rust" { fn __rust_no_alloc_shim_is_unstable_v2(); } -/// The global memory allocator. +/// A wrapper for the global allocator. /// /// This type implements the [`Allocator`] trait by forwarding calls /// to the allocator registered with the `#[global_allocator]` attribute /// if there is one, or the `std` crate’s default. /// +/// `Global` is not "the global allocator", but a wrapper for it. +/// If the global allocator used `Global`, it would call itself recursively. +/// To avoid this, `Global` does not implement [`GlobalAlloc`]. +/// /// Similar to [`alloc`], [`dealloc`], and the other global allocation functions, -/// the way in which calls are forwarded to the allocator registered with +/// when and how calls are forwarded to the allocator registered with /// `#[global_allocator]` is unspecified. See their safety docs for more information. /// -/// This allocator must be treated like an opaque allocator that only guarantees -/// the contract described in the docs of [`Allocator`], as well as the following -/// things: +/// In particular, even if you know which allocator was registered +/// as the global allocator, calling it directly is not the same as calling +/// `Global`. You cannot deallocate memory from one using the other. +/// +/// `Global` must be treated like an opaque allocator that only guarantees the contract +/// described in the docs of [`Allocator`], as well as the following: /// * All instances of `Global` are [*equivalent*]. /// * Allocations from `Global` are only invalidated by calls to de-/reallocating functions. /// If no such call is made, then the allocation will live for the rest of the program. -/// * The global allocation functions are equivalent to the methods on `Global`, except -/// that they disallow zero-sized allocations, and implicitly ignore any returned -/// excess size. +/// * The global allocation functions in the [`alloc`](self) module are equivalent to the +/// methods on `Global`, except that they disallow zero-sized allocations, and implicitly +/// ignore any returned excess size. +/// In particular, you may deallocate memory from [`alloc::alloc`](self::alloc) using +/// [`Global.deallocate`](Global::deallocate) and vice-versa. /// /// Note that the current implementation of `Global` does not take advantage of -/// some features of [`Allocator`], such as zero-sized allocations (which currently always +/// some features of [`Allocator`], such as zero-sized allocations (which currently /// return a dangling pointer) and overallocating. -/// /// This may change in the future. You must not rely on it for correctness! /// /// [*equivalent*]: Allocator#equivalent-allocators From fe4b0c623e484613f2df4286457965d60da6eaab Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 20:52:41 +0000 Subject: [PATCH 0912/1309] utilize the `cx` helpers where possible Most of these cases were found by searching for uses of `DUMMY_NODE_ID`. --- compiler/rustc_builtin_macros/src/asm.rs | 32 +--- compiler/rustc_builtin_macros/src/assert.rs | 24 +-- .../src/assert/context.rs | 31 +--- compiler/rustc_builtin_macros/src/autodiff.rs | 72 ++------ .../rustc_builtin_macros/src/edition_panic.rs | 28 +-- compiler/rustc_builtin_macros/src/gca.rs | 11 +- .../src/proc_macro_harness.rs | 1 + compiler/rustc_builtin_macros/src/test.rs | 166 +++++++++--------- .../src/test_binder_constraints.rs | 13 +- compiler/rustc_expand/src/build.rs | 3 +- tests/pretty/autodiff/autodiff_forward.pp | 48 +++-- tests/pretty/autodiff/autodiff_reverse.pp | 16 +- tests/pretty/autodiff/inherent_impl.pp | 4 +- 13 files changed, 165 insertions(+), 284 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs index 975b2c49b292d..845dc8ab544fc 100644 --- a/compiler/rustc_builtin_macros/src/asm.rs +++ b/compiler/rustc_builtin_macros/src/asm.rs @@ -588,13 +588,7 @@ pub(super) fn expand_asm<'cx>( return ExpandResult::Retry(()); }; let expr = match mac { - Ok(inline_asm) => Box::new(ast::Expr { - id: ast::DUMMY_NODE_ID, - kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)), - span: sp, - attrs: ast::AttrVec::new(), - tokens: None, - }), + Ok(inline_asm) => ecx.expr(sp, ast::ExprKind::InlineAsm(Box::new(inline_asm))), Err(guar) => DummyResult::raw_expr(sp, Some(guar)), }; MacEager::expr(expr) @@ -618,13 +612,7 @@ pub(super) fn expand_naked_asm<'cx>( return ExpandResult::Retry(()); }; let expr = match mac { - Ok(inline_asm) => Box::new(ast::Expr { - id: ast::DUMMY_NODE_ID, - kind: ast::ExprKind::InlineAsm(Box::new(inline_asm)), - span: sp, - attrs: ast::AttrVec::new(), - tokens: None, - }), + Ok(inline_asm) => ecx.expr(sp, ast::ExprKind::InlineAsm(Box::new(inline_asm))), Err(guar) => DummyResult::raw_expr(sp, Some(guar)), }; MacEager::expr(expr) @@ -648,17 +636,11 @@ pub(super) fn expand_global_asm<'cx>( return ExpandResult::Retry(()); }; match mac { - Ok(inline_asm) => MacEager::items(smallvec![Box::new(ast::Item { - attrs: ast::AttrVec::new(), - id: ast::DUMMY_NODE_ID, - kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)), - vis: ast::Visibility { - span: sp.shrink_to_lo(), - kind: ast::VisibilityKind::Inherited, - }, - span: sp, - tokens: None, - })]), + Ok(inline_asm) => MacEager::items(smallvec![ecx.item( + sp, + ast::AttrVec::new(), + ast::ItemKind::GlobalAsm(Box::new(inline_asm)) + )]), Err(guar) => DummyResult::any(sp, guar), } } diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs index 5f71e02d1350b..f5a582ddffcc5 100644 --- a/compiler/rustc_builtin_macros/src/assert.rs +++ b/compiler/rustc_builtin_macros/src/assert.rs @@ -1,8 +1,8 @@ mod context; use rustc_ast::token::Delimiter; -use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::{DelimArgs, Expr, ExprKind, MacCall, Path, PathSegment, UnOp, token}; +use rustc_ast::tokenstream::TokenStream; +use rustc_ast::{Expr, ExprKind, Path, UnOp, token}; use rustc_ast_pretty::pprust; use rustc_errors::PResult; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; @@ -34,14 +34,7 @@ pub(crate) fn expand_assert<'cx>( let panic_path = || { if use_panic_2021(span) { // On edition 2021, we always call `$crate::panic::panic_2021!()`. - Path { - span: call_site_span, - segments: cx - .std_path(&[sym::panic, sym::panic_2021]) - .into_iter() - .map(PathSegment::from_ident) - .collect(), - } + cx.path(call_site_span, cx.std_path(&[sym::panic, sym::panic_2021])) } else { // Before edition 2021, we call `panic!()` unqualified, // such that it calls either `std::panic!()` or `core::panic!()`. @@ -51,16 +44,9 @@ pub(crate) fn expand_assert<'cx>( // Simply uses the user provided message instead of generating custom outputs let expr = if let Some(tokens) = custom_message { - let then = cx.expr( + let then = cx.expr_macro_call( call_site_span, - ExprKind::MacCall(Box::new(MacCall { - path: panic_path(), - args: Box::new(DelimArgs { - dspan: DelimSpan::from_single(call_site_span), - delim: Delimiter::Parenthesis, - tokens, - }), - })), + cx.macro_call(call_site_span, panic_path(), Delimiter::Parenthesis, tokens), ); expr_if_not(cx, call_site_span, cond_expr, then, None) } diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs index cb3ea2475721e..11c97da0db5ad 100644 --- a/compiler/rustc_builtin_macros/src/assert/context.rs +++ b/compiler/rustc_builtin_macros/src/assert/context.rs @@ -1,8 +1,8 @@ use rustc_ast::token::{self, Delimiter, IdentKind}; use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree}; use rustc_ast::{ - BinOpKind, BorrowKind, DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, ItemKind, MacCall, MethodCall, - Mutability, Path, PathSegment, Stmt, StructRest, UnOp, UseTree, UseTreeAndId, UseTreeKind, + BinOpKind, BorrowKind, DUMMY_NODE_ID, DelimArgs, Expr, ExprKind, ItemKind, MacCall, Mutability, + Path, Stmt, StructRest, UnOp, UseTree, UseTreeAndId, UseTreeKind, }; use rustc_ast_pretty::pprust; use rustc_data_structures::fx::FxHashSet; @@ -382,20 +382,15 @@ impl<'cx, 'a> Context<'cx, 'a> { ); let try_capture_call = self .cx - .stmt_expr(expr_method_call( - self.cx, - PathSegment { - args: None, - id: DUMMY_NODE_ID, - ident: Ident::new(sym::try_capture, self.span), - }, - expr_paren(self.cx, self.span, self.cx.expr_addr_of(self.span, wrapper)), + .stmt_expr(self.cx.expr_method_call( + self.span, + self.cx.expr_paren(self.span, self.cx.expr_addr_of(self.span, wrapper)), + Ident::new(sym::try_capture, self.span), thin_vec![expr_addr_of_mut( self.cx, self.span, self.cx.expr_path(Path::from_ident(capture)), )], - self.span, )) .add_trailing_semicolon(); let local_bind_path = self.cx.expr_path(Path::from_ident(local_bind)); @@ -448,17 +443,3 @@ fn escape_to_fmt(s: &str) -> String { fn expr_addr_of_mut(cx: &ExtCtxt<'_>, sp: Span, e: Box) -> Box { cx.expr(sp, ExprKind::AddrOf(BorrowKind::Ref, Mutability::Mut, e)) } - -fn expr_method_call( - cx: &ExtCtxt<'_>, - seg: PathSegment, - receiver: Box, - args: ThinVec>, - span: Span, -) -> Box { - cx.expr(span, ExprKind::MethodCall(Box::new(MethodCall { seg, receiver, args, span }))) -} - -fn expr_paren(cx: &ExtCtxt<'_>, sp: Span, e: Box) -> Box { - cx.expr(sp, ExprKind::Paren(e)) -} diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 0c81b9080c6cf..1ccb2d60498dd 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -14,9 +14,8 @@ mod llvm_enzyme { use rustc_ast::tokenstream::*; use rustc_ast::visit::AssocCtxt::*; use rustc_ast::{ - self as ast, AngleBracketedArg, AngleBracketedArgs, AnonConst, AssocItemKind, BindingMode, - FnRetTy, FnSig, GenericArg, GenericArgs, GenericParamKind, Generics, ItemKind, - MetaItemInner, PatKind, Path, PathSegment, TyKind, Visibility, + self as ast, AnonConst, AssocItemKind, FnRetTy, FnSig, GenericArg, GenericParamKind, + Generics, ItemKind, MetaItemInner, PatKind, TyKind, Visibility, }; use rustc_attr_ir::RustcAutodiff; use rustc_expand::base::{Annotatable, ExtCtxt}; @@ -459,12 +458,7 @@ mod llvm_enzyme { Annotatable::Stmt(_) => { let mut d_fn = ecx.item(span, d_attrs, ItemKind::Fn(d_fn)); d_fn.vis = vis; - - Annotatable::Stmt(Box::new(ast::Stmt { - id: ast::DUMMY_NODE_ID, - kind: ast::StmtKind::Item(d_fn), - span, - })) + Annotatable::Stmt(Box::new(ecx.stmt_item(span, d_fn))) } _ => { unreachable!("item kind checked previously") @@ -591,35 +585,20 @@ mod llvm_enzyme { GenericParamKind::Type { .. } => { let path = ast::Path::from_ident(p.ident); let ty = ecx.ty_path(path); - Some(AngleBracketedArg::Arg(GenericArg::Type(ty))) + Some(GenericArg::Type(ty)) } GenericParamKind::Const { .. } => { let expr = ecx.expr_path(ast::Path::from_ident(p.ident)); let anon_const = AnonConst { id: ast::DUMMY_NODE_ID, value: expr }; - Some(AngleBracketedArg::Arg(GenericArg::Const(anon_const))) + Some(GenericArg::Const(anon_const)) } GenericParamKind::Lifetime => None, }) - .collect::>(); - - let args: AngleBracketedArgs = AngleBracketedArgs { span, args: generic_args }; - - let segment = PathSegment { - ident, - id: ast::DUMMY_NODE_ID, - args: Some(Box::new(GenericArgs::AngleBracketed(args))), - }; - - let segments = if is_impl { - thin_vec![ - PathSegment { ident: Ident::from_str("Self"), id: ast::DUMMY_NODE_ID, args: None }, - segment, - ] - } else { - thin_vec![segment] - }; + .collect::>(); - let path = Path { span, segments }; + let idents = + if is_impl { vec![Ident::new(kw::SelfUpper, span), ident] } else { vec![ident] }; + let path = ecx.path_all(span, false, idents, generic_args); ecx.expr_path(path) } @@ -727,12 +706,8 @@ mod llvm_enzyme { let name: String = format!("d{}_{}", old_name, i); new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); - *shadow_arg.pat = ast::Pat { - id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::NONE, ident, None), - span: shadow_arg.pat.span, - }; - d_inputs.push(shadow_arg.clone()); + *shadow_arg.pat = ecx.pat_ident(shadow_arg.pat.span, ident); + d_inputs.push(shadow_arg); } } DiffActivity::Dual @@ -758,12 +733,9 @@ mod llvm_enzyme { let name: String = format!("b{}_{}", old_name, i); new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); - *shadow_arg.pat = ast::Pat { - id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::NONE, ident, None), - span: shadow_arg.pat.span, - }; - d_inputs.push(shadow_arg.clone()); + + *shadow_arg.pat = ecx.pat_ident(shadow_arg.pat.span, ident); + d_inputs.push(shadow_arg); } } DiffActivity::Const => { @@ -798,18 +770,7 @@ mod llvm_enzyme { }; let name = "dret".to_string(); let ident = Ident::from_str_and_span(&name, ty.span); - let shadow_arg = ast::Param { - attrs: ThinVec::new(), - ty: ty.clone(), - pat: Box::new(ast::Pat { - id: ast::DUMMY_NODE_ID, - kind: PatKind::Ident(BindingMode::NONE, ident, None), - span: ty.span, - }), - id: ast::DUMMY_NODE_ID, - span: ty.span, - is_placeholder: false, - }; + let shadow_arg = ecx.param(ty.span, ident, ty); d_inputs.push(shadow_arg); new_inputs.push(name); } @@ -823,8 +784,7 @@ mod llvm_enzyme { FnRetTy::Ty(ref ty) => ty.clone(), FnRetTy::Default(span) => { // We want to return std::hint::black_box(()). - let kind = TyKind::Tup(ThinVec::new()); - let ty = Box::new(rustc_ast::Ty { kind, id: ast::DUMMY_NODE_ID, span }); + let ty = ecx.ty_unit(span); d_decl.output = FnRetTy::Ty(ty.clone()); assert!(matches!(x.ret_activity, DiffActivity::None)); // this won't be used below, so any type would be fine. diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs index ac5c43c660088..4c99ef9a9da26 100644 --- a/compiler/rustc_builtin_macros/src/edition_panic.rs +++ b/compiler/rustc_builtin_macros/src/edition_panic.rs @@ -1,6 +1,5 @@ use rustc_ast::token::Delimiter; -use rustc_ast::tokenstream::{DelimSpan, TokenStream}; -use rustc_ast::*; +use rustc_ast::tokenstream::TokenStream; use rustc_expand::base::*; use rustc_span::edition::Edition; use rustc_span::{Span, sym}; @@ -44,26 +43,15 @@ fn expand<'cx>( ) -> MacroExpanderResult<'cx> { let sp = cx.with_call_site_ctxt(sp); - ExpandResult::Ready(MacEager::expr( - cx.expr( + ExpandResult::Ready(MacEager::expr(cx.expr_macro_call( + sp, + cx.macro_call( sp, - ExprKind::MacCall(Box::new(MacCall { - path: Path { - span: sp, - segments: cx - .std_path(&[sym::panic, mac]) - .into_iter() - .map(PathSegment::from_ident) - .collect(), - }, - args: Box::new(DelimArgs { - dspan: DelimSpan::from_single(sp), - delim: Delimiter::Parenthesis, - tokens: tts, - }), - })), + cx.path(sp, cx.std_path(&[sym::panic, mac])), + Delimiter::Parenthesis, + tts, ), - )) + ))) } pub(crate) fn use_panic_2021(mut span: Span) -> bool { diff --git a/compiler/rustc_builtin_macros/src/gca.rs b/compiler/rustc_builtin_macros/src/gca.rs index ba26b16d06be5..9e117e06ea9fd 100644 --- a/compiler/rustc_builtin_macros/src/gca.rs +++ b/compiler/rustc_builtin_macros/src/gca.rs @@ -18,16 +18,9 @@ pub(crate) fn expand<'cx>( Err(err) => return ExpandResult::Ready(DummyResult::any(span, err)), }; - let id = ast::DUMMY_NODE_ID; ExpandResult::Ready(Box::new(base::MacEager { - expr: Some(Box::new(ast::Expr { - id, - kind: ast::ExprKind::GcaMacro(expr.clone()), - span, - attrs: Default::default(), - tokens: None, - })), - ty: Some(Box::new(ast::Ty { id, kind: ast::TyKind::GcaMacro(expr), span })), + expr: Some(cx.expr(span, ast::ExprKind::GcaMacro(expr.clone()))), + ty: Some(cx.ty(span, ast::TyKind::GcaMacro(expr))), ..Default::default() })) } diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs index 2fbce3638e021..ecf4f7e7fb1af 100644 --- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs +++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs @@ -339,6 +339,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> Box { let mut decls_static = cx.item_static( span, + ast::AttrVec::new(), Ident::new(sym::_DECLS, span), cx.ty_ref( span, diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index 42dbc801bfb5a..ac9f59caf0294 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -3,7 +3,7 @@ use std::{assert_matches, iter}; -use rustc_ast::{self as ast, GenericParamKind, Mutability, Safety, attr, join_path_idents}; +use rustc_ast::{self as ast, GenericParamKind, Mutability, attr, join_path_idents}; use rustc_ast_pretty::pprust; use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_attr_parsing::AttributeParser; @@ -263,76 +263,74 @@ pub(crate) fn expand_test_or_bench( let location_info = get_location_info(cx, fn_); - let mut test_const = - cx.item( + // static $ident: test::TestDescAndFn = + // We use a static because these things only exist to have references taken + // to them for the test case array. No reason to introduce tons of promoteds for that. + // Promoteds have the advantage that they can be merged to save space, but every one + // of these points to a different function so that will not happen. + let mut test_const = cx.item_static( + sp, + thin_vec![ + // #[cfg(test)] + cx.attr_nested_word(sym::cfg, sym::test, attr_sp), + // #[rustc_test_marker = "test_case_sort_key"] + cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), + // #[doc(hidden)] + cx.attr_nested_word(sym::doc, sym::hidden, attr_sp), + ], + Ident::new(fn_.ident.name, sp), + cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), + Mutability::Not, + // test::TestDescAndFn { + cx.expr_struct( sp, + test_path("TestDescAndFn"), thin_vec![ - // #[cfg(test)] - cx.attr_nested_word(sym::cfg, sym::test, attr_sp), - // #[rustc_test_marker = "test_case_sort_key"] - cx.attr_name_value_str(sym::rustc_test_marker, test_path_symbol, attr_sp), - // #[doc(hidden)] - cx.attr_nested_word(sym::doc, sym::hidden, attr_sp), - ], - // static $ident: test::TestDescAndFn = - // We use a static because these things only exist to have references taken - // to them for the test case array. No reason to introduce tons of promoteds for that. - // Promoteds have the advantage that they can be merged to save space, but every one - // of these points to a different function so that will not happen. - ast::ItemKind::Static( - ast::StaticItem { - ident: Ident::new(fn_.ident.name, sp), - ty: cx.ty(sp, ast::TyKind::Path(None, test_path("TestDescAndFn"))), - safety: Safety::Default, - mutability: Mutability::Not, - define_opaque: None, - eii_impl: None, - // test::TestDescAndFn { - expr: Some( - cx.expr_struct( - sp, - test_path("TestDescAndFn"), - thin_vec![ - // desc: test::TestDesc { - field( - "desc", - cx.expr_struct(sp, test_path("TestDesc"), thin_vec![ - // name: "path::to::test" - field( - "name", - cx.expr_call( - sp, - cx.expr_path(test_path("StaticTestName")), - thin_vec![cx.expr_str(sp, test_path_symbol)], - ), - ), - // ignore: true | false - field("ignore", cx.expr_bool(sp, should_ignore(&item)),), - // ignore_message: Some("...") | None - field( - "ignore_message", - if let Some(msg) = should_ignore_message(&item) { - cx.expr_some(sp, cx.expr_str(sp, msg)) - } else { - cx.expr_none(sp) - }, + // desc: test::TestDesc { + field( + "desc", + cx.expr_struct( + sp, + test_path("TestDesc"), + thin_vec![ + // name: "path::to::test" + field( + "name", + cx.expr_call( + sp, + cx.expr_path(test_path("StaticTestName")), + thin_vec![cx.expr_str(sp, test_path_symbol)], ), - // source_file: - field("source_file", cx.expr_str(sp, location_info.0)), - // start_line: start line of the test fn identifier. - field("start_line", cx.expr_usize(sp, location_info.1)), - // start_col: start column of the test fn identifier. - field("start_col", cx.expr_usize(sp, location_info.2)), - // end_line: end line of the test fn identifier. - field("end_line", cx.expr_usize(sp, location_info.3)), - // end_col: end column of the test fn identifier. - field("end_col", cx.expr_usize(sp, location_info.4)), - // compile_fail: true | false - field("compile_fail", cx.expr_bool(sp, false)), - // no_run: true | false - field("no_run", cx.expr_bool(sp, false)), - // should_panic: ... - field("should_panic", match should_panic(cx, &item) { + ), + // ignore: true | false + field("ignore", cx.expr_bool(sp, should_ignore(&item)),), + // ignore_message: Some("...") | None + field( + "ignore_message", + if let Some(msg) = should_ignore_message(&item) { + cx.expr_some(sp, cx.expr_str(sp, msg)) + } else { + cx.expr_none(sp) + }, + ), + // source_file: + field("source_file", cx.expr_str(sp, location_info.0)), + // start_line: start line of the test fn identifier. + field("start_line", cx.expr_usize(sp, location_info.1)), + // start_col: start column of the test fn identifier. + field("start_col", cx.expr_usize(sp, location_info.2)), + // end_line: end line of the test fn identifier. + field("end_line", cx.expr_usize(sp, location_info.3)), + // end_col: end column of the test fn identifier. + field("end_col", cx.expr_usize(sp, location_info.4)), + // compile_fail: true | false + field("compile_fail", cx.expr_bool(sp, false)), + // no_run: true | false + field("no_run", cx.expr_bool(sp, false)), + // should_panic: ... + field( + "should_panic", + match should_panic(cx, &item) { // test::ShouldPanic::No ShouldPanic::No => { cx.expr_path(should_panic_path("No")) @@ -347,9 +345,12 @@ pub(crate) fn expand_test_or_bench( cx.expr_path(should_panic_path("YesWithMessage")), thin_vec![cx.expr_str(sp, sym)], ), - },), - // test_type: ... - field("test_type", match test_type(cx) { + }, + ), + // test_type: ... + field( + "test_type", + match test_type(cx) { // test::TestType::UnitTest TestType::UnitTest => { cx.expr_path(test_type_path("UnitTest")) @@ -362,19 +363,18 @@ pub(crate) fn expand_test_or_bench( TestType::Unknown => { cx.expr_path(test_type_path("Unknown")) } - },), - // }, - ],), - ), - // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) - field("testfn", test_fn), // } - ], - ), // } + }, + ), + // }, + ], ), - } - .into(), - ), - ); + ), + // testfn: test::StaticTestFn(...) | test::StaticBenchFn(...) + field("testfn", test_fn), // } + ], + // } + ), + ); test_const.vis.kind = ast::VisibilityKind::Public; // extern crate test diff --git a/compiler/rustc_builtin_macros/src/test_binder_constraints.rs b/compiler/rustc_builtin_macros/src/test_binder_constraints.rs index d6a3649500c29..3e70e83bb0762 100644 --- a/compiler/rustc_builtin_macros/src/test_binder_constraints.rs +++ b/compiler/rustc_builtin_macros/src/test_binder_constraints.rs @@ -1,5 +1,5 @@ use rustc_ast::tokenstream::TokenStream; -use rustc_ast::{AttrVec, VisibilityKind, ast, token}; +use rustc_ast::{AttrVec, ast, token}; use rustc_expand::base::{DummyResult, ExpandResult, ExtCtxt, MacEager, MacroExpanderResult}; use rustc_span::Span; use smallvec::SmallVec; @@ -26,15 +26,8 @@ pub(crate) fn expand<'cx>( if p.token != token::Eof { cx.dcx().emit_err(diagnostics::OnlyOneArgument { span: p.token.span, name }); } - let item = Box::new(ast::Item { - attrs: AttrVec::default(), - id: ast::DUMMY_NODE_ID, - span, - vis: ast::Visibility { kind: VisibilityKind::Inherited, span: span.shrink_to_lo() }, - kind: ast::ItemKind::TestBinderConstraints(item), - tokens: None, - }); - rustc_expand::base::ExpandResult::Ready(Box::new(MacEager { + let item = cx.item(span, AttrVec::default(), ast::ItemKind::TestBinderConstraints(item)); + ExpandResult::Ready(Box::new(MacEager { expr: None, items: Some(SmallVec::from_buf([item])), ty: None, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 4c8ab40cf649a..ff2e64d996ba5 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -657,6 +657,7 @@ impl<'a> ExtCtxt<'a> { pub fn item_static( &self, span: Span, + attrs: ast::AttrVec, ident: Ident, ty: Box, mutability: ast::Mutability, @@ -664,7 +665,7 @@ impl<'a> ExtCtxt<'a> { ) -> Box { self.item( span, - AttrVec::new(), + attrs, ast::ItemKind::Static( ast::StaticItem { ident, diff --git a/tests/pretty/autodiff/autodiff_forward.pp b/tests/pretty/autodiff/autodiff_forward.pp index 746754637f5cd..0fb60061f6982 100644 --- a/tests/pretty/autodiff/autodiff_forward.pp +++ b/tests/pretty/autodiff/autodiff_forward.pp @@ -35,8 +35,8 @@ } #[rustc_autodiff(Forward, 1, Dual, Const, Dual)] pub fn df1(x: &[f64], bx_0: &[f64], y: f64) -> (f64, f64) { - ::core::intrinsics::autodiff(f1::<> as fn(_: &[f64], _: f64) -> f64, - df1::<>, (x, bx_0, y)) + ::core::intrinsics::autodiff(f1 as fn(_: &[f64], _: f64) -> f64, df1, + (x, bx_0, y)) } #[rustc_autodiff] pub fn f2(x: &[f64], y: f64) -> f64 { @@ -44,8 +44,8 @@ } #[rustc_autodiff(Forward, 1, Dual, Const, Const)] pub fn df2(x: &[f64], bx_0: &[f64], y: f64) -> f64 { - ::core::intrinsics::autodiff(f2::<> as fn(_: &[f64], _: f64) -> f64, - df2::<>, (x, bx_0, y)) + ::core::intrinsics::autodiff(f2 as fn(_: &[f64], _: f64) -> f64, df2, + (x, bx_0, y)) } #[rustc_autodiff] pub fn f3(x: &[f64], y: f64) -> f64 { @@ -53,33 +53,31 @@ } #[rustc_autodiff(Forward, 1, Dual, Const, Const)] pub fn df3(x: &[f64], bx_0: &[f64], y: f64) -> f64 { - ::core::intrinsics::autodiff(f3::<> as fn(_: &[f64], _: f64) -> f64, - df3::<>, (x, bx_0, y)) + ::core::intrinsics::autodiff(f3 as fn(_: &[f64], _: f64) -> f64, df3, + (x, bx_0, y)) } #[rustc_autodiff] pub fn f4() {} #[rustc_autodiff(Forward, 1, None)] -pub fn df4() -> () { - ::core::intrinsics::autodiff(f4::<> as fn(), df4::<>, ()) -} +pub fn df4() -> () { ::core::intrinsics::autodiff(f4 as fn(), df4, ()) } #[rustc_autodiff] pub fn f5(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } #[rustc_autodiff(Forward, 1, Const, Dual, Const)] pub fn df5_y(x: &[f64], y: f64, by_0: f64) -> f64 { - ::core::intrinsics::autodiff(f5::<> as fn(_: &[f64], _: f64) -> f64, - df5_y::<>, (x, y, by_0)) + ::core::intrinsics::autodiff(f5 as fn(_: &[f64], _: f64) -> f64, df5_y, + (x, y, by_0)) } #[rustc_autodiff(Forward, 1, Dual, Const, Const)] pub fn df5_x(x: &[f64], bx_0: &[f64], y: f64) -> f64 { - ::core::intrinsics::autodiff(f5::<> as fn(_: &[f64], _: f64) -> f64, - df5_x::<>, (x, bx_0, y)) + ::core::intrinsics::autodiff(f5 as fn(_: &[f64], _: f64) -> f64, df5_x, + (x, bx_0, y)) } #[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] pub fn df5_rev(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { - ::core::intrinsics::autodiff(f5::<> as fn(_: &[f64], _: f64) -> f64, - df5_rev::<>, (x, dx_0, y, dret)) + ::core::intrinsics::autodiff(f5 as fn(_: &[f64], _: f64) -> f64, df5_rev, + (x, dx_0, y, dret)) } struct DoesNotImplDefault; #[rustc_autodiff] @@ -88,14 +86,13 @@ } #[rustc_autodiff(Forward, 1, Const)] pub fn df6() -> DoesNotImplDefault { - ::core::intrinsics::autodiff(f6::<> as fn() -> DoesNotImplDefault, - df6::<>, ()) + ::core::intrinsics::autodiff(f6 as fn() -> DoesNotImplDefault, df6, ()) } #[rustc_autodiff] pub fn f7(x: f32) -> () {} #[rustc_autodiff(Forward, 1, Const, None)] pub fn df7(x: f32) -> () { - ::core::intrinsics::autodiff(f7::<> as fn(_: f32) -> (), df7::<>, (x,)) + ::core::intrinsics::autodiff(f7 as fn(_: f32) -> (), df7, (x,)) } #[no_mangle] #[rustc_autodiff] @@ -103,32 +100,31 @@ #[rustc_autodiff(Forward, 4, Dual, Dual)] fn f8_3(x: &f32, bx_0: &f32, bx_1: &f32, bx_2: &f32, bx_3: &f32) -> [f32; 5usize] { - ::core::intrinsics::autodiff(f8::<> as fn(_: &f32) -> f32, f8_3::<>, + ::core::intrinsics::autodiff(f8 as fn(_: &f32) -> f32, f8_3, (x, bx_0, bx_1, bx_2, bx_3)) } #[rustc_autodiff(Forward, 4, Dual, DualOnly)] fn f8_2(x: &f32, bx_0: &f32, bx_1: &f32, bx_2: &f32, bx_3: &f32) -> [f32; 4usize] { - ::core::intrinsics::autodiff(f8::<> as fn(_: &f32) -> f32, f8_2::<>, + ::core::intrinsics::autodiff(f8 as fn(_: &f32) -> f32, f8_2, (x, bx_0, bx_1, bx_2, bx_3)) } #[rustc_autodiff(Forward, 1, Dual, DualOnly)] fn f8_1(x: &f32, bx_0: &f32) -> f32 { - ::core::intrinsics::autodiff(f8::<> as fn(_: &f32) -> f32, f8_1::<>, - (x, bx_0)) + ::core::intrinsics::autodiff(f8 as fn(_: &f32) -> f32, f8_1, (x, bx_0)) } pub fn f9() { #[rustc_autodiff] fn inner(x: f32) -> f32 { x * x } #[rustc_autodiff(Forward, 1, Dual, Dual)] fn d_inner_2(x: f32, bx_0: f32) -> (f32, f32) { - ::core::intrinsics::autodiff(inner::<> as fn(_: f32) -> f32, - d_inner_2::<>, (x, bx_0)) + ::core::intrinsics::autodiff(inner as fn(_: f32) -> f32, d_inner_2, + (x, bx_0)) } #[rustc_autodiff(Forward, 1, Dual, DualOnly)] fn d_inner_1(x: f32, bx_0: f32) -> f32 { - ::core::intrinsics::autodiff(inner::<> as fn(_: f32) -> f32, - d_inner_1::<>, (x, bx_0)) + ::core::intrinsics::autodiff(inner as fn(_: f32) -> f32, d_inner_1, + (x, bx_0)) } } #[rustc_autodiff] diff --git a/tests/pretty/autodiff/autodiff_reverse.pp b/tests/pretty/autodiff/autodiff_reverse.pp index e2088e0ac13db..01ac5a5888cfc 100644 --- a/tests/pretty/autodiff/autodiff_reverse.pp +++ b/tests/pretty/autodiff/autodiff_reverse.pp @@ -28,21 +28,21 @@ } #[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] pub fn df1(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { - ::core::intrinsics::autodiff(f1::<> as fn(_: &[f64], _: f64) -> f64, - df1::<>, (x, dx_0, y, dret)) + ::core::intrinsics::autodiff(f1 as fn(_: &[f64], _: f64) -> f64, df1, + (x, dx_0, y, dret)) } #[rustc_autodiff] pub fn f2() {} #[rustc_autodiff(Reverse, 1, None)] -pub fn df2() { ::core::intrinsics::autodiff(f2::<> as fn(), df2::<>, ()) } +pub fn df2() { ::core::intrinsics::autodiff(f2 as fn(), df2, ()) } #[rustc_autodiff] pub fn f3(x: &[f64], y: f64) -> f64 { ::core::panicking::panic("not implemented") } #[rustc_autodiff(Reverse, 1, Duplicated, Const, Active)] pub fn df3(x: &[f64], dx_0: &mut [f64], y: f64, dret: f64) -> f64 { - ::core::intrinsics::autodiff(f3::<> as fn(_: &[f64], _: f64) -> f64, - df3::<>, (x, dx_0, y, dret)) + ::core::intrinsics::autodiff(f3 as fn(_: &[f64], _: f64) -> f64, df3, + (x, dx_0, y, dret)) } enum Foo { Reverse, } use Foo::Reverse; @@ -50,7 +50,7 @@ pub fn f4(x: f32) { ::core::panicking::panic("not implemented") } #[rustc_autodiff(Reverse, 1, Const, None)] pub fn df4(x: f32) { - ::core::intrinsics::autodiff(f4::<> as fn(_: f32), df4::<>, (x,)) + ::core::intrinsics::autodiff(f4 as fn(_: f32), df4, (x,)) } #[rustc_autodiff] pub fn f5(x: *const f32, y: &f32) { @@ -58,7 +58,7 @@ } #[rustc_autodiff(Reverse, 1, DuplicatedOnly, Duplicated, None)] pub unsafe fn df5(x: *const f32, dx_0: *mut f32, y: &f32, dy_0: &mut f32) { - ::core::intrinsics::autodiff(f5::<> as fn(_: *const f32, _: &f32), - df5::<>, (x, dx_0, y, dy_0)) + ::core::intrinsics::autodiff(f5 as fn(_: *const f32, _: &f32), df5, + (x, dx_0, y, dy_0)) } fn main() {} diff --git a/tests/pretty/autodiff/inherent_impl.pp b/tests/pretty/autodiff/inherent_impl.pp index d3a5a71b8bcbf..d175fbdecf1e0 100644 --- a/tests/pretty/autodiff/inherent_impl.pp +++ b/tests/pretty/autodiff/inherent_impl.pp @@ -30,7 +30,7 @@ } #[rustc_autodiff(Reverse, 1, Const, Active, Active)] fn df(&self, x: f64, dret: f64) -> (f64, f64) { - ::core::intrinsics::autodiff(Self::f::<> as - fn(_: &Self, _: f64) -> f64, Self::df::<>, (self, x, dret)) + ::core::intrinsics::autodiff(Self::f as fn(_: &Self, _: f64) -> f64, + Self::df, (self, x, dret)) } } From 063fab421198fd12baca04811229a4a89bfe953f Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 25 Sep 2026 21:05:38 +0000 Subject: [PATCH 0913/1309] rename "lambda" to "closure" Also inline `lambda0` and `lambda1` since they're only used once and are trivial wrappers around `lambda`. --- compiler/rustc_builtin_macros/src/test.rs | 7 ++++--- compiler/rustc_expand/src/build.rs | 14 +++----------- 2 files changed, 7 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index ac9f59caf0294..f2a9dd4f05be3 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -210,8 +210,9 @@ pub(crate) fn expand_test_or_bench( thin_vec![ // #[coverage(off)] // |__bench_fn_name| self::test::assert_test_result( - coverage_off(cx.lambda1( + coverage_off(cx.closure( sp, + vec![bencher_param], cx.expr_call( sp, cx.expr_path(test_path("assert_test_result")), @@ -224,7 +225,6 @@ pub(crate) fn expand_test_or_bench( ), ], ), - bencher_param, )), // ) ], ) @@ -235,8 +235,9 @@ pub(crate) fn expand_test_or_bench( thin_vec![ // #[coverage(off)] // || { - coverage_off(cx.lambda0( + coverage_off(cx.closure( sp, + vec![], // test::assert_test_result( cx.expr_call( sp, diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index ff2e64d996ba5..c9d71b8df1517 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -558,15 +558,15 @@ impl<'a> ExtCtxt<'a> { self.expr(span, ast::ExprKind::If(cond, self.block_expr(then), els)) } - pub fn lambda(&self, span: Span, ids: Vec, body: Box) -> Box { + pub fn closure(&self, span: Span, ids: Vec, body: Box) -> Box { let fn_decl = self.fn_decl( ids.iter().map(|id| self.param(span, *id, self.ty(span, ast::TyKind::Infer))).collect(), ast::FnRetTy::Default(span), ); // FIXME -- We are using `span` as the span of the `|...|` - // part of the lambda, but it probably (maybe?) corresponds to - // the entire lambda body. Probably we should extend the API + // part of the closure, but it probably (maybe?) corresponds to + // the entire closure body. Probably we should extend the API // here, but that's not entirely clear. self.expr( span, @@ -586,14 +586,6 @@ impl<'a> ExtCtxt<'a> { ) } - pub fn lambda0(&self, span: Span, body: Box) -> Box { - self.lambda(span, Vec::new(), body) - } - - pub fn lambda1(&self, span: Span, body: Box, ident: Ident) -> Box { - self.lambda(span, vec![ident], body) - } - pub fn param(&self, span: Span, ident: Ident, ty: Box) -> ast::Param { let pat = Box::new(self.pat_ident(span, ident)); ast::Param { From 7698a8693765d28ce6bcc4265971b43740fd9f67 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 21:19:35 +0000 Subject: [PATCH 0914/1309] remove trivial type annotations --- compiler/rustc_builtin_macros/src/autodiff.rs | 24 +++++++++---------- compiler/rustc_builtin_macros/src/format.rs | 2 +- compiler/rustc_builtin_macros/src/offload.rs | 2 +- 3 files changed, 14 insertions(+), 14 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 1ccb2d60498dd..a6e1e02540964 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -14,8 +14,8 @@ mod llvm_enzyme { use rustc_ast::tokenstream::*; use rustc_ast::visit::AssocCtxt::*; use rustc_ast::{ - self as ast, AnonConst, AssocItemKind, FnRetTy, FnSig, GenericArg, GenericParamKind, - Generics, ItemKind, MetaItemInner, PatKind, TyKind, Visibility, + self as ast, AnonConst, FnRetTy, FnSig, GenericArg, GenericParamKind, Generics, ItemKind, + MetaItemInner, PatKind, TyKind, Visibility, }; use rustc_attr_ir::RustcAutodiff; use rustc_expand::base::{Annotatable, ExtCtxt}; @@ -153,7 +153,7 @@ mod llvm_enzyme { } fn meta_item_inner_to_ts(t: &MetaItemInner, ts: &mut Vec) { - let comma: Token = Token::new(TokenKind::Comma, Span::default()); + let comma = Token::new(TokenKind::Comma, Span::default()); let val = first_ident(t); let t = Token::from_ast_ident(val); ts.push(TokenTree::Token(t, Spacing::Joint)); @@ -274,7 +274,7 @@ mod llvm_enzyme { // Now, if the user gave a width (vector aka batch-mode ad), then we copy it. // If it is not given, we default to 1 (scalar mode). let start_position; - let kind: LitKind = LitKind::Integer; + let kind = LitKind::Integer; let symbol; if meta_item_vec.len() >= 2 && let Some(width) = width(&meta_item_vec[1]) @@ -286,7 +286,7 @@ mod llvm_enzyme { symbol = sym::integer(1); } - let l: Lit = Lit { kind, symbol, suffix: None }; + let l = Lit { kind, symbol, suffix: None }; let t = Token::new(TokenKind::Literal(l), Span::default()); let comma = Token::new(TokenKind::Comma, Span::default()); ts.push(TokenTree::Token(t, Spacing::Joint)); @@ -305,9 +305,9 @@ mod llvm_enzyme { } // We remove the last, trailing comma. ts.pop(); - let ts: TokenStream = TokenStream::from_iter(ts); + let ts = TokenStream::from_iter(ts); - let x: RustcAutodiff = from_ast(ecx, &meta_item_vec, has_ret, mode); + let x = from_ast(ecx, &meta_item_vec, has_ret, mode); if !x.is_active() { // We encountered an error, so we return the original item. // This allows us to potentially parse other attributes. @@ -345,7 +345,7 @@ mod llvm_enzyme { let mut rustc_ad_attr = Box::new(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff))); - let ts2: Vec = vec![TokenTree::Token( + let ts2 = vec![TokenTree::Token( Token::new(TokenKind::Ident(sym::never, IdentKind::Normal), span), Spacing::Joint, )]; @@ -381,7 +381,7 @@ mod llvm_enzyme { let mut has_inline_never = false; // Don't add it multiple times: - let orig_annotatable: Annotatable = match item { + let orig_annotatable = match item { Annotatable::Item(ref mut iitem) => { if !iitem.attrs.iter().any(|a| same_attribute(&a.kind, &attr.kind)) { iitem.attrs.push(attr); @@ -438,7 +438,7 @@ mod llvm_enzyme { let d_annotatable = match &item { Annotatable::AssocItem(_, ctxt) => { - let assoc_item: AssocItemKind = ast::AssocItemKind::Fn(d_fn); + let assoc_item = ast::AssocItemKind::Fn(d_fn); let d_fn = Box::new(ast::AssocItem { attrs: d_attrs, id: ast::DUMMY_NODE_ID, @@ -703,7 +703,7 @@ mod llvm_enzyme { debug!("{:#?}", &shadow_arg.pat); panic!("not an ident?"); }; - let name: String = format!("d{}_{}", old_name, i); + let name = format!("d{}_{}", old_name, i); new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); *shadow_arg.pat = ecx.pat_ident(shadow_arg.pat.span, ident); @@ -730,7 +730,7 @@ mod llvm_enzyme { debug!("{:#?}", &shadow_arg.pat); panic!("not an ident?"); }; - let name: String = format!("b{}_{}", old_name, i); + let name = format!("b{}_{}", old_name, i); new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs index e23c057f8a651..e52da1136dd64 100644 --- a/compiler/rustc_builtin_macros/src/format.rs +++ b/compiler/rustc_builtin_macros/src/format.rs @@ -1107,7 +1107,7 @@ fn report_invalid_references( // for `println!("{7:7$}", 1);` indexes.sort(); indexes.dedup(); - let span: MultiSpan = if !parser.is_source_literal || parser.arg_places.is_empty() { + let span = if !parser.is_source_literal || parser.arg_places.is_empty() { MultiSpan::from_span(fmt_span) } else { MultiSpan::from_spans(invalid_refs.iter().filter_map(|&(_, span, _, _)| span).collect()) diff --git a/compiler/rustc_builtin_macros/src/offload.rs b/compiler/rustc_builtin_macros/src/offload.rs index 53bf0f4ca6b86..4da4ce4e4a505 100644 --- a/compiler/rustc_builtin_macros/src/offload.rs +++ b/compiler/rustc_builtin_macros/src/offload.rs @@ -148,7 +148,7 @@ pub(crate) fn expand_kernel( } // inline(never) attr - let ts: Vec = vec![TokenTree::Token( + let ts = vec![TokenTree::Token( Token::new(TokenKind::Ident(sym::never, IdentKind::Normal), span), Spacing::Joint, )]; From fe9b2e9ba52148c5e6fad49b37260020d42d88b3 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 26 Sep 2026 21:34:36 +0000 Subject: [PATCH 0915/1309] move `std_path` to `build.rs`, remove unused `def_site_path` It is much more similar to the methods there than to the methods in `base.rs`. --- compiler/rustc_expand/src/base.rs | 13 +------------ compiler/rustc_expand/src/build.rs | 9 +++++++++ 2 files changed, 10 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs index fda75319b087b..01e8cef49e445 100644 --- a/compiler/rustc_expand/src/base.rs +++ b/compiler/rustc_expand/src/base.rs @@ -1,6 +1,5 @@ use std::any::Any; use std::default::Default; -use std::iter; use std::path::PathBuf; use std::rc::Rc; use std::sync::Arc; @@ -24,7 +23,7 @@ use rustc_span::def_id::{CrateNum, DefId, LocalDefId, ModId}; use rustc_span::edition::Edition; use rustc_span::hygiene::{AstPass, ExpnData, ExpnKind, LocalExpnId, MacroKind}; use rustc_span::source_map::SourceMap; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; +use rustc_span::{DUMMY_SP, Ident, Span, Symbol}; use rustc_structures::{CollapseMacroDebuginfo, Limit}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; @@ -1324,16 +1323,6 @@ impl<'a> ExtCtxt<'a> { pub fn set_trace_macros(&mut self, x: bool) { self.ecfg.trace_mac = x } - pub fn std_path(&self, components: &[Symbol]) -> Vec { - let def_site = self.with_def_site_ctxt(DUMMY_SP); - iter::once(Ident::new(kw::DollarCrate, def_site)) - .chain(components.iter().map(|&s| Ident::new(s, def_site))) - .collect() - } - pub fn def_site_path(&self, components: &[Symbol]) -> Vec { - let def_site = self.with_def_site_ctxt(DUMMY_SP); - components.iter().map(|&s| Ident::new(s, def_site)).collect() - } pub fn check_unused_macros(&mut self) { self.resolver.check_unused_macros(); diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index c9d71b8df1517..34d4343ba9ba0 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -1,3 +1,5 @@ +use std::iter; + use rustc_ast::token::Delimiter; use rustc_ast::tokenstream::TokenStream; use rustc_ast::util::literal; @@ -11,6 +13,13 @@ use thin_vec::{ThinVec, thin_vec}; use crate::base::ExtCtxt; impl<'a> ExtCtxt<'a> { + pub fn std_path(&self, components: &[Symbol]) -> Vec { + let def_site = self.with_def_site_ctxt(DUMMY_SP); + iter::once(Ident::new(kw::DollarCrate, def_site)) + .chain(components.iter().map(|&s| Ident::new(s, def_site))) + .collect() + } + pub fn path(&self, span: Span, strs: Vec) -> ast::Path { self.path_all(span, false, strs, vec![]) } From 529a0ae6b90554e2aee8d8845ae169db0c0c56c8 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 27 Sep 2026 13:21:27 +0000 Subject: [PATCH 0916/1309] cleanup some `Vec`s in autodiff.rs `new_inputs` and `idents` are never read anywhere, several other `Vec`s are supposed to be `ThinVec`s instead. --- compiler/rustc_builtin_macros/src/autodiff.rs | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index a6e1e02540964..083d05d03a070 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -562,7 +562,7 @@ mod llvm_enzyme { let call_expr = ecx.expr_call( span, ecx.expr_path(enzyme_path), - vec![primal_fn_ptr, diff_path_expr, tuple_expr].into(), + thin_vec![primal_fn_ptr, diff_path_expr, tuple_expr], ); ecx.stmt_expr(call_expr) @@ -636,9 +636,7 @@ mod llvm_enzyme { assert!(sig.decl.inputs.len() == x.input_activity.len()); assert!(has_ret == x.has_ret_activity()); let mut d_decl = sig.decl.clone(); - let mut d_inputs = Vec::new(); - let mut new_inputs = Vec::new(); - let mut idents = Vec::new(); + let mut d_inputs = ThinVec::new(); let mut act_ret = ThinVec::new(); // We have two loops, a first one just to check the activities and types and possibly report @@ -704,7 +702,6 @@ mod llvm_enzyme { panic!("not an ident?"); }; let name = format!("d{}_{}", old_name, i); - new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); *shadow_arg.pat = ecx.pat_ident(shadow_arg.pat.span, ident); d_inputs.push(shadow_arg); @@ -731,7 +728,6 @@ mod llvm_enzyme { panic!("not an ident?"); }; let name = format!("b{}_{}", old_name, i); - new_inputs.push(name.clone()); let ident = Ident::from_str_and_span(&name, shadow_arg.pat.span); *shadow_arg.pat = ecx.pat_ident(shadow_arg.pat.span, ident); @@ -745,11 +741,6 @@ mod llvm_enzyme { panic!("Should not happen"); } } - if let PatKind::Ident(_, ident, _) = arg.pat.kind { - idents.push(ident); - } else { - panic!("not an ident?"); - } } let active_only_ret = x.ret_activity == DiffActivity::ActiveOnly; @@ -772,12 +763,11 @@ mod llvm_enzyme { let ident = Ident::from_str_and_span(&name, ty.span); let shadow_arg = ecx.param(ty.span, ident, ty); d_inputs.push(shadow_arg); - new_inputs.push(name); } _ => {} } } - d_decl.inputs = d_inputs.into(); + d_decl.inputs = d_inputs; if x.mode.is_fwd() { let ty = match d_decl.output { From 94685f0f1f064084ba758b7ca1dc0bf9de10ef9b Mon Sep 17 00:00:00 2001 From: Asger Hautop Drewsen Date: Sun, 27 Sep 2026 15:57:22 +0000 Subject: [PATCH 0917/1309] Implement Default for NumBuffer * Implement Default for NumBuffer * Make insta-stable --- library/core/src/fmt/num_buffer.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/library/core/src/fmt/num_buffer.rs b/library/core/src/fmt/num_buffer.rs index 5c29964b1cff8..62089e30a06e2 100644 --- a/library/core/src/fmt/num_buffer.rs +++ b/library/core/src/fmt/num_buffer.rs @@ -84,3 +84,10 @@ impl NumBuffer { NumBuffer { buf: T::DEFAULT, phantom: core::marker::PhantomData } } } + +#[stable(feature = "num_buffer_default", since = "CURRENT_RUSTC_VERSION")] +impl Default for NumBuffer { + fn default() -> Self { + Self::new() + } +} From b1d3d37f5fe8efef91cf3b1c93cee3e3cfbfeb38 Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Sun, 27 Sep 2026 18:50:45 +0200 Subject: [PATCH 0918/1309] Don't assert EINPROGRESS for non-blocking `connect` on TCP sockets When running on a native host, the `connect` might succeed immediately which would cause some of the non-blocking socket tests to fail. This assertion was only needed to ensure that the `connect` did not fail for any real reason. Thus, the assertion has been adjusted to not fail when the `connect` succeeds immediately. --- .../libc/libc-socket-no-blocking-epoll.rs | 11 +++---- .../pass-dep/libc/libc-socket-no-blocking.rs | 30 ++++++++++++++----- 2 files changed, 28 insertions(+), 13 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index c91f3474793e3..563c2a3842a19 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -57,9 +57,9 @@ fn test_connect_nonblock() { net::accept_ipv4(server_sockfd).unwrap(); }); - // Non-blocking connects always "fail" with EINPROGRESS. - let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InProgress); + let result = net::connect_ipv4(client_sockfd, addr); + // This might succeed immediately or return EINPROGRESS. + assert!(result.is_ok() || result.is_err_and(|e| e.kind() == ErrorKind::InProgress)); // Add client socket with WRITABLE interest to epoll. epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | EPOLLERR).unwrap(); @@ -145,9 +145,10 @@ fn test_connect_nonblock_err() { // a zero port. let addr = net::sock_addr_ipv4([127, 0, 1, 1], 12321); - // Non-blocking connect should fail with EINPROGRESS. let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InProgress); + // Since the address is not bound, the `connect` can never succeed + // immediately and thus it always "fails" with EINPROGRESS. + assert!(err.kind() == ErrorKind::InProgress); // Add interest for client socket. epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs index de718feb47990..4405b2a9fc947 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs @@ -225,8 +225,14 @@ fn test_connect_nonblock() { // Yield to server thread to ensure that it's currently accepting. thread::sleep(Duration::from_millis(10)); - // Non-blocking connects always "fail" with EINPROGRESS. - let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + let Err(err) = net::connect_ipv4(client_sockfd, addr) else { + // The connection could be established immediately. We don't + // need to enter the loop and check whether the connection could + // really be established. + return server_thread.join().unwrap(); + }; + // The connection could not be established immediately. The `connect` + // should thus return EINPROGRESS. assert_eq!(err.kind(), ErrorKind::InProgress); loop { @@ -667,9 +673,10 @@ fn test_getsockname_ipv4_connect_nonblock() { // a zero port. let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); - // Non-blocking connect should fail with EINPROGRESS. let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InProgress); + // Since we're connecting to a blackhole address, the `connect` can + // never succeed immediately and thus it always "fails" with EINPROGRESS. + assert!(err.kind() == ErrorKind::InProgress); let (_, sock_addr) = net::sockname_ipv4(|storage, len| unsafe { libc::getsockname(client_sockfd, storage, len) @@ -712,8 +719,14 @@ fn test_getpeername_ipv4_nonblock() { // Yield to server thread to ensure that it's currently accepting. thread::sleep(Duration::from_millis(10)); - // Non-blocking connects always "fail" with EINPROGRESS. - let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + let Err(err) = net::connect_ipv4(client_sockfd, addr) else { + // The connection could be established immediately. We don't + // need to enter the loop and check whether the connection could + // really be established. + return server_thread.join().unwrap(); + }; + // The connection could not be established immediately. The `connect` + // should thus return EINPROGRESS. assert_eq!(err.kind(), ErrorKind::InProgress); loop { @@ -764,9 +777,10 @@ fn test_getpeername_ipv4_nonblock_no_peer() { // a zero port. let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); - // Non-blocking connect should fail with EINPROGRESS. let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); - assert_eq!(err.kind(), ErrorKind::InProgress); + // Since we're connecting to a blackhole address, the `connect` can + // never succeed immediately and thus it always "fails" with EINPROGRESS. + assert!(err.kind() == ErrorKind::InProgress); // There should be no error during async connection. let errno = From 4ce013ca6530bd7cb74347879836b264b1d9d9d8 Mon Sep 17 00:00:00 2001 From: Valentyn Kit Date: Sun, 27 Sep 2026 20:52:15 +0300 Subject: [PATCH 0919/1309] Align the fallback message in panic location examples Use the same fallback string as the PanicInfo::location example in the PanicHookInfo::location and Location doc examples for consistency. --- library/core/src/panic/location.rs | 8 ++++---- library/std/src/panic.rs | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/library/core/src/panic/location.rs b/library/core/src/panic/location.rs index f37f5370997e1..63c6132c985a0 100644 --- a/library/core/src/panic/location.rs +++ b/library/core/src/panic/location.rs @@ -21,7 +21,7 @@ use crate::ptr::NonNull; /// if let Some(location) = panic_info.location() { /// println!("panic occurred in file '{}' at line {}", location.file(), location.line()); /// } else { -/// println!("panic occurred but can't get location information..."); +/// println!("panicked at unknown location"); /// } /// })); /// @@ -208,7 +208,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred in file '{}'", location.file()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// @@ -255,7 +255,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred at line {}", location.line()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// @@ -280,7 +280,7 @@ impl<'a> Location<'a> { /// if let Some(location) = panic_info.location() { /// println!("panic occurred at column {}", location.column()); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// diff --git a/library/std/src/panic.rs b/library/std/src/panic.rs index 23a4cabc320b0..2fef17041101c 100644 --- a/library/std/src/panic.rs +++ b/library/std/src/panic.rs @@ -151,7 +151,7 @@ impl<'a> PanicHookInfo<'a> { /// location.line(), /// ); /// } else { - /// println!("panic occurred but can't get location information..."); + /// println!("panicked at unknown location"); /// } /// })); /// From a7dd4a37beffe37511f753c7f9d6750dd5c672a9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 27 Sep 2026 20:19:44 +0200 Subject: [PATCH 0920/1309] Apply LTO to Cranelift and GCC codegen backends --- src/bootstrap/src/core/build_steps/compile.rs | 56 ++++++++++--------- 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index b1157ef381013..97e7280da1e37 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1251,31 +1251,7 @@ pub fn rustc_cargo( cargo.rustflag("-Zdefault-visibility=protected"); } - if is_lto_stage(build_compiler) { - match builder.config.rust_lto { - RustcLto::Thin | RustcLto::Fat => { - // Since using LTO for optimizing dylibs is currently experimental, - // we need to pass -Zdylib-lto. - cargo.rustflag("-Zdylib-lto"); - // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when - // compiling dylibs (and their dependencies), even when LTO is enabled for the - // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here. - let lto_type = match builder.config.rust_lto { - RustcLto::Thin => "thin", - RustcLto::Fat => "fat", - _ => unreachable!(), - }; - cargo.rustflag(&format!("-Clto={lto_type}")); - cargo.rustflag("-Cembed-bitcode=yes"); - } - RustcLto::ThinLocal => { /* Do nothing, this is the default */ } - RustcLto::Off => { - cargo.rustflag("-Clto=off"); - } - } - } else if builder.config.rust_lto == RustcLto::Off { - cargo.rustflag("-Clto=off"); - } + apply_dylib_lto(builder, build_compiler, cargo); // With LLD, we can use ICF (identical code folding) to reduce the executable size // of librustc_driver/rustc and to improve i-cache utilization. @@ -1308,6 +1284,34 @@ pub fn rustc_cargo( rustc_cargo_env(builder, cargo, target); } +fn apply_dylib_lto(builder: &Builder<'_>, build_compiler: &Compiler, cargo: &mut Cargo) { + if is_lto_stage(build_compiler) { + match builder.config.rust_lto { + RustcLto::Thin | RustcLto::Fat => { + // Since using LTO for optimizing dylibs is currently experimental, + // we need to pass -Zdylib-lto. + cargo.rustflag("-Zdylib-lto"); + // Cargo by default passes `-Cembed-bitcode=no` and doesn't pass `-Clto` when + // compiling dylibs (and their dependencies), even when LTO is enabled for the + // crate. Therefore, we need to override `-Clto` and `-Cembed-bitcode` here. + let lto_type = match builder.config.rust_lto { + RustcLto::Thin => "thin", + RustcLto::Fat => "fat", + _ => unreachable!(), + }; + cargo.rustflag(&format!("-Clto={lto_type}")); + cargo.rustflag("-Cembed-bitcode=yes"); + } + RustcLto::ThinLocal => { /* Do nothing, this is the default */ } + RustcLto::Off => { + cargo.rustflag("-Clto=off"); + } + } + } else if builder.config.rust_lto == RustcLto::Off { + cargo.rustflag("-Clto=off"); + } +} + fn rustc_cargo_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelection) { // Set some configuration variables picked up by build scripts and // the compiler alike @@ -1720,6 +1724,7 @@ impl CommandLineStep for GccCodegenBackend { Kind::Build, ); cargo.arg("--manifest-path").arg(builder.src.join("compiler/rustc_codegen_gcc/Cargo.toml")); + apply_dylib_lto(builder, &build_compiler, &mut cargo); let _guard = builder.msg(Kind::Build, "codegen backend gcc", Mode::Codegen, build_compiler, host); @@ -1790,6 +1795,7 @@ impl CommandLineStep for CraneliftCodegenBackend { cargo .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml")); + apply_dylib_lto(builder, &build_compiler, &mut cargo); let _guard = builder.msg( Kind::Build, From 37c0ed5ce88fedc68b0e120754e7968ad6646a87 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:46:11 +0200 Subject: [PATCH 0921/1309] Add docs --- compiler/rustc_abi/src/layout.rs | 13 +++++++++---- compiler/rustc_abi/src/lib.rs | 4 ++-- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index a10548d1a6059..3234ae0bbe6b9 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -263,6 +263,11 @@ impl LayoutCalculator { ) } + /// Compute the layout for a univariant (see [`Variants::Single`]). + /// + /// As a consumer of `rustc_abi`, you should only use this method for non-ADTs. + /// For structs and univariant enums, use [`Self::layout_of_struct`] instead + /// (it uses this function internally). pub fn layout_of_univariant<'a, FieldIdx, VariantIdx, F>( &self, fields: &IndexSlice, @@ -514,7 +519,10 @@ impl LayoutCalculator { }) } - /// single-variant enums are just structs, if you think about it + /// Calculate the layout for a struct, or a single-variant enum. + /// + /// They are the same thing, if you think about it + /// (Typechecking will reject discriminant-sizing attrs.) fn layout_of_struct<'a, FieldIdx, VariantIdx, F>( &self, repr: &ReprOptions, @@ -529,9 +537,6 @@ impl LayoutCalculator { VariantIdx: Idx, F: Deref> + fmt::Debug + Copy, { - // Struct, or univariant enum equivalent to a struct. - // (Typechecking will reject discriminant-sizing attrs.) - let dl = self.cx.data_layout(); let v = present_first; let kind = if is_enum || variants[v].is_empty() || always_sized { diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 56cfbf138af00..82225d580d414 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2027,10 +2027,10 @@ pub enum Variants { /// 2. the never type Empty, - /// The type has a single valid variant. + /// The type has a single valid variant. Such types are called "univariant". /// /// This is the case for: - /// 1. enums with a single inhabited variant + /// 1. enums with a single inhabited variant, aka. "univariant enums" /// 2. structs, unions, and non-ADTs (except coroutines; see below), /// as those can't have multiple variants Single { From 0858ecdbca0ac1ebc1ea9f81068069dc5fe7032e Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 18:46:11 +0200 Subject: [PATCH 0922/1309] `layout_of_struct`: rename the `present_first` param The name makes some sense at the callsite, but inside the function, the parameter refers to the `VariantIdx` that should be use for the newly-created layout, so name accordingly. Also move closer to the related `variants` param (Note: could consider passing `variants[present_first]` instead of `variants`, as that's the only way `variants` is used -- at the same type, passing `variants` seems more consistent with the rest of the file.) --- compiler/rustc_abi/src/layout.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index 3234ae0bbe6b9..e099290438080 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -378,10 +378,10 @@ impl LayoutCalculator { self.layout_of_struct( repr, variants, + present_first, is_enum, is_special_no_niche, always_sized, - present_first, ) } else { // At this point, we have handled all unions and @@ -527,10 +527,10 @@ impl LayoutCalculator { &self, repr: &ReprOptions, variants: &IndexSlice>, + variant_idx: VariantIdx, is_enum: bool, is_special_no_niche: bool, always_sized: bool, - present_first: VariantIdx, ) -> LayoutCalculatorResult where FieldIdx: Idx, @@ -538,7 +538,7 @@ impl LayoutCalculator { F: Deref> + fmt::Debug + Copy, { let dl = self.cx.data_layout(); - let v = present_first; + let v = variant_idx; let kind = if is_enum || variants[v].is_empty() || always_sized { StructKind::AlwaysSized } else { From 6668485ad973381aa256560c237e98ae334d27ee Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Sat, 26 Sep 2026 19:35:19 +0200 Subject: [PATCH 0923/1309] introduce `NicheOptimizations` This is a more type-safe alternative for the `niche_optimizations: bool` param --- compiler/rustc_abi/src/layout.rs | 13 +++++++------ compiler/rustc_abi/src/lib.rs | 12 ++++++++++++ compiler/rustc_ty_utils/src/layout.rs | 13 ++++++++----- 3 files changed, 27 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_abi/src/layout.rs b/compiler/rustc_abi/src/layout.rs index e099290438080..fa03fb87d02d1 100644 --- a/compiler/rustc_abi/src/layout.rs +++ b/compiler/rustc_abi/src/layout.rs @@ -11,8 +11,9 @@ use tracing::{debug, trace}; use crate::{ AbiAlign, Align, BackendLaneCount, BackendRepr, FieldsShape, HasDataLayout, IndexSlice, - IndexVec, Integer, LayoutData, Niche, NumScalableVectors, Primitive, ReprOptions, Scalar, Size, - StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, WrappingRange, + IndexVec, Integer, LayoutData, Niche, NicheOptimizations, NumScalableVectors, Primitive, + ReprOptions, Scalar, Size, StructKind, TagEncoding, TargetDataLayout, VariantLayout, Variants, + WrappingRange, }; mod coroutine; @@ -343,7 +344,7 @@ impl LayoutCalculator { repr: &ReprOptions, variants: &IndexSlice>, is_enum: bool, - is_special_no_niche: bool, + niche_optimizations: NicheOptimizations, discr_range_of_repr: impl Fn(RangeFrom, RangeToInclusive) -> (Integer, bool), discriminants: impl Iterator, always_sized: bool, @@ -380,7 +381,7 @@ impl LayoutCalculator { variants, present_first, is_enum, - is_special_no_niche, + niche_optimizations, always_sized, ) } else { @@ -529,7 +530,7 @@ impl LayoutCalculator { variants: &IndexSlice>, variant_idx: VariantIdx, is_enum: bool, - is_special_no_niche: bool, + niche_optimizations: NicheOptimizations, always_sized: bool, ) -> LayoutCalculatorResult where @@ -548,7 +549,7 @@ impl LayoutCalculator { let mut st = self.layout_of_univariant(&variants[v], repr, kind)?; st.variants = Variants::Single { index: v }; - if is_special_no_niche { + if niche_optimizations == NicheOptimizations::Disabled { let hide_niches = |scalar: &mut _| match scalar { Scalar::Initialized { value, valid_range } => { *valid_range = WrappingRange::full(value.size(dl)) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index 82225d580d414..ef34addace196 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2195,6 +2195,18 @@ impl Niche { } } +/// Whether niche optimizations should be performed during layout calculation. +/// +/// [`UnsafeCell`] and [`UnsafePinned`] both disable niche optimizations. +/// +/// [`UnsafeCell`]: std::cell::UnsafeCell +/// [`UnsafePinned`]: std::pin::UnsafePinned +#[derive(PartialEq, Eq, Clone, Copy)] +pub enum NicheOptimizations { + Enabled, + Disabled, +} + // NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone)] #[cfg_attr(feature = "nightly", derive(StableHash))] diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs index ab9437abeb2ce..1522ecbb55de9 100644 --- a/compiler/rustc_ty_utils/src/layout.rs +++ b/compiler/rustc_ty_utils/src/layout.rs @@ -5,8 +5,8 @@ use rustc_abi::Integer::{I8, I32}; use rustc_abi::Primitive::{self, Float, Int, Pointer}; use rustc_abi::{ AddressSpace, BackendRepr, FIRST_VARIANT, FieldIdx, FieldsShape, HasDataLayout, Layout, - LayoutCalculatorError, LayoutData, Niche, ReprOptions, Scalar, Size, StructKind, TagEncoding, - VariantIdx, Variants, WrappingRange, + LayoutCalculatorError, LayoutData, Niche, NicheOptimizations, ReprOptions, Scalar, Size, + StructKind, TagEncoding, VariantIdx, Variants, WrappingRange, }; use rustc_attr_ir::find_attr; use rustc_attr_ir::lang_items::LangItem; @@ -713,7 +713,10 @@ fn layout_of_uncached<'tcx>( } // UnsafeCell and UnsafePinned both disable niche optimizations - let is_special_no_niche = def.is_unsafe_cell() || def.is_unsafe_pinned(); + let niche_optimizations = match def.is_unsafe_cell() || def.is_unsafe_pinned() { + true => NicheOptimizations::Disabled, + false => NicheOptimizations::Enabled, + }; let discr_range_of_repr = |min: RangeFrom, max: RangeToInclusive| { abi::Integer::discr_range_of_repr(tcx, ty, &def.repr(), min.start, max.last) @@ -743,7 +746,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - is_special_no_niche, + niche_optimizations, discr_range_of_repr, discriminants_iter(), !maybe_unsized, @@ -772,7 +775,7 @@ fn layout_of_uncached<'tcx>( &def.repr(), &variants, def.is_enum(), - is_special_no_niche, + niche_optimizations, discr_range_of_repr, discriminants_iter(), !maybe_unsized, From dfa855cfca4f4e923916e7c0483042bf0d050697 Mon Sep 17 00:00:00 2001 From: Matilde Morrone Date: Sun, 27 Sep 2026 21:48:49 +0200 Subject: [PATCH 0924/1309] mailmap: add Matilde Morrone --- .mailmap | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.mailmap b/.mailmap index 32fbff098127d..62eadbcd29176 100644 --- a/.mailmap +++ b/.mailmap @@ -459,6 +459,8 @@ Mateusz Mikuła Mateusz Mikuła Mateusz Mikuła Mateusz Mikuła +Matilde Morrone +Matilde Morrone Matt Brubeck Matthew Auld Matthew Jasper From eb37f4f2a8710a074f3f7644a27da29428f7ee14 Mon Sep 17 00:00:00 2001 From: Aliaksei Semianiuk Date: Sun, 27 Sep 2026 00:03:49 +0500 Subject: [PATCH 0925/1309] Changelog for Clippy 1.99 --- CHANGELOG.md | 90 ++++++++++++++++++- clippy_lints/src/assert_is_empty.rs | 2 +- clippy_lints/src/bit_width.rs | 4 +- clippy_lints/src/block_scrutinee.rs | 2 +- .../src/nonnull_unchecked_on_box_ptr.rs | 2 +- 5 files changed, 94 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f6814f0a9c7ee..84f990511e3f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,95 @@ document. ## Unreleased / Beta / In Rust Nightly -[64c7431...master](https://github.com/rust-lang/rust-clippy/compare/64c7431...master) +[49e2f89...master](https://github.com/rust-lang/rust-clippy/compare/49e2f89...master) + +## Rust 1.99 + +Current stable, released 2026-10-01 + +[View all 123 merged pull requests](https://github.com/rust-lang/rust-clippy/pulls?q=merged%3A2026-06-27T20%3A01%3A42Z..2026-08-07T11%3A58%3A08Z+base%3Amaster) + +### New Lints + +* Added [`assert_is_empty`] to `pedantic` + [#17149](https://github.com/rust-lang/rust-clippy/pull/17149) +* Added [`nonnull_unchecked_on_box_ptr`] to `complexity` + [#17336](https://github.com/rust-lang/rust-clippy/pull/17336) +* Added [`block_scrutinee`] to `suspicious` + [#16855](https://github.com/rust-lang/rust-clippy/pull/16855) +* Added [`definition_in_module_root`] to `restriction` + [#16965](https://github.com/rust-lang/rust-clippy/pull/16965) +* Added [`rest_pattern_accessible_field`] to `restriction` + [#15000](https://github.com/rust-lang/rust-clippy/pull/15000) +* Added [`unnecessary_rest_pattern`] to `restriction` + [#15000](https://github.com/rust-lang/rust-clippy/pull/15000) +* Added [`manual_bit_width`] to `pedantic` + [#16902](https://github.com/rust-lang/rust-clippy/pull/16902) +* Added [`mismatched_bit_width_type`] to `suspicious` + [#16902](https://github.com/rust-lang/rust-clippy/pull/16902) + +### Enhancements + +* [`redundant_pattern_matching`] parenthesize guarded `matches!` suggestions so the autofix keeps + the original operator precedence + [#17287](https://github.com/rust-lang/rust-clippy/pull/17287) +* [`unwrap_or_default`] don't suggest `unwrap_or_default()` for a raw-pointer value below the 1.88 + MSRV that stabilized `Default` for raw pointers + [#17452](https://github.com/rust-lang/rust-clippy/pull/17452) +* [`clone_on_copy`] lint UFCS calls like `Clone::clone()` and `i32::clone()` + [#16972](https://github.com/rust-lang/rust-clippy/pull/16972) +* [`manual_div_ceil`] avoid suggestions that change the evaluation count of side-effectful divisors + [#17468](https://github.com/rust-lang/rust-clippy/pull/17468) +* [`float_cmp_const`] fix FN on `assert_eq!` + [#17024](https://github.com/rust-lang/rust-clippy/pull/17024) +* [`duration_suboptimal_units`] print the complete method name in the suggestion + [#17002](https://github.com/rust-lang/rust-clippy/pull/17002) +* [`min_ident_chars`] add an option to enforce the lint even when following the naming from the + trait + [#16741](https://github.com/rust-lang/rust-clippy/pull/16741) +* [`unnecessary_safety_comment`] handle compound assignments + [#17044](https://github.com/rust-lang/rust-clippy/pull/17044) +* [`big_endian_bytes`], [`host_endian_bytes`], [`little_endian_bytes`] lint method names (including + UFCS) rather than only calls + [#17363](https://github.com/rust-lang/rust-clippy/pull/17363) +* [`branches_sharing_code`] also lint `match` expressions whose arms end with the same expression + [#17313](https://github.com/rust-lang/rust-clippy/pull/17313) +* [`approx_constant`] add `EULER_GAMMA` and `GOLDEN_RATIO` constants + [#17441](https://github.com/rust-lang/rust-clippy/pull/17441) +* [`double_must_use`], [`let_underscore_must_use`], [`must_use_candidate`] determine `#[must_use]` + needs using the compiler algorithm + [#16633](https://github.com/rust-lang/rust-clippy/pull/16633) + +### False Positive Fixes + +* [`doc_paragraphs_missing_punctuation`] fix FP on images with an embedded link + [#16773](https://github.com/rust-lang/rust-clippy/pull/16773) +* [`multiple_unsafe_ops_per_block`] fix FP when taking a pointer to a mutable static without + reading, writing, or field-projecting into it + [#17461](https://github.com/rust-lang/rust-clippy/pull/17461) +* [`non_zero_suggestions`] fix FP when suggesting `NonZero` for signed integer div/rem + [#17385](https://github.com/rust-lang/rust-clippy/pull/17385) +* [`infinite_loop`] fix FP on `yield` inside gen blocks + [#17311](https://github.com/rust-lang/rust-clippy/pull/17311) + +### ICE Fixes + +* [`unnecessary_unwrap_unchecked`] fix ICE when resolving a path to a local variable + [#17353](https://github.com/rust-lang/rust-clippy/pull/17353) + +### Documentation Improvements + +* [`cargo_common_metadata`] update the link in the documentation + [#17435](https://github.com/rust-lang/rust-clippy/pull/17435) +* [`manual_c_str_literals`] add a clarifying note for the `as_ptr` suggestion + [#17282](https://github.com/rust-lang/rust-clippy/pull/17282) +* Fix accessible labels for the theme and version filters on the lint page + [#17434](https://github.com/rust-lang/rust-clippy/pull/17434) + +### Performance Improvements + +* [`nonstandard_macro_braces`] optimize by 99.97% + [#16808](https://github.com/rust-lang/rust-clippy/pull/16808) ## Rust 1.98 diff --git a/clippy_lints/src/assert_is_empty.rs b/clippy_lints/src/assert_is_empty.rs index 677a7d08c562d..6d9892af61854 100644 --- a/clippy_lints/src/assert_is_empty.rs +++ b/clippy_lints/src/assert_is_empty.rs @@ -65,7 +65,7 @@ declare_clippy_lint! { /// assert_eq!(items, [] as [i32; 0]); /// assert_ne!(items, [] as [i32; 0]); /// ``` - #[clippy::version = "1.98.0"] + #[clippy::version = "1.99.0"] pub ASSERT_IS_EMPTY, pedantic, "asserting on emptiness without showing the asserted value on failure" diff --git a/clippy_lints/src/bit_width.rs b/clippy_lints/src/bit_width.rs index cd08188866ead..2b7f41ff32591 100644 --- a/clippy_lints/src/bit_width.rs +++ b/clippy_lints/src/bit_width.rs @@ -25,7 +25,7 @@ declare_clippy_lint! { /// let x: u32 = 5; /// let bit_width = x.bit_width(); /// ``` - #[clippy::version = "1.98.0"] + #[clippy::version = "1.99.0"] pub MANUAL_BIT_WIDTH, pedantic, "manually reimplementing `bit_width`" @@ -49,7 +49,7 @@ declare_clippy_lint! { /// let x: u64 = 5; /// let bit_width = x.bit_width(); /// ``` - #[clippy::version = "1.98.0"] + #[clippy::version = "1.99.0"] pub MISMATCHED_BIT_WIDTH_TYPE, suspicious, "type mismatch in bit width calculation" diff --git a/clippy_lints/src/block_scrutinee.rs b/clippy_lints/src/block_scrutinee.rs index 2762f85b91029..03a8b7c318144 100644 --- a/clippy_lints/src/block_scrutinee.rs +++ b/clippy_lints/src/block_scrutinee.rs @@ -22,7 +22,7 @@ declare_clippy_lint! { /// ```rust,ignore /// if let Some(x) = { my_function() } { .. } /// ``` - #[clippy::version = "1.98.0"] + #[clippy::version = "1.99.0"] pub BLOCK_SCRUTINEE, suspicious, "warns when the scrutinee is wrapped in a block in older editions" diff --git a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs index 9263d0940a890..99f22b3ab033c 100644 --- a/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs +++ b/clippy_lints/src/nonnull_unchecked_on_box_ptr.rs @@ -30,7 +30,7 @@ declare_clippy_lint! { /// let one = Box::new(1); /// let ptr = Box::into_non_null(one); /// ``` - #[clippy::version = "1.98.0"] + #[clippy::version = "1.99.0"] pub NONNULL_UNCHECKED_ON_BOX_PTR, complexity, "checks for uses of `NonNull::new_unchecked` with `Box::into_raw`" From abcef063378fe6e3dbe990da7e0e395f86ff8876 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sun, 27 Sep 2026 20:53:55 +0000 Subject: [PATCH 0926/1309] Implement forced keywords (`k#`) * Implement forced keywords * Allow any identifier to be forced as a keyword even if not reserved --- compiler/rustc_ast/src/token.rs | 31 +++++++---- compiler/rustc_ast_passes/src/feature_gate.rs | 1 + compiler/rustc_ast_pretty/src/pprust/state.rs | 10 ++-- compiler/rustc_expand/src/mbe/macro_check.rs | 3 +- compiler/rustc_expand/src/mbe/macro_rules.rs | 6 +-- compiler/rustc_expand/src/mbe/metavar_expr.rs | 22 ++++++-- compiler/rustc_expand/src/mbe/quoted.rs | 9 ++-- compiler/rustc_expand/src/mbe/transcribe.rs | 16 ++---- .../rustc_expand/src/proc_macro_server.rs | 52 +++++++++++++------ compiler/rustc_feature/src/unstable.rs | 2 + compiler/rustc_lexer/src/lib.rs | 28 ++++++---- compiler/rustc_parse/src/lexer/mod.rs | 27 ++++++++++ .../rustc_parse/src/parser/diagnostics.rs | 21 ++++---- compiler/rustc_parse/src/parser/expr.rs | 10 ++-- compiler/rustc_parse/src/parser/item.rs | 3 +- compiler/rustc_parse/src/parser/mod.rs | 11 ++-- compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_span/src/symbol.rs | 6 +++ library/proc_macro/src/bridge/mod.rs | 30 ++++++++++- library/proc_macro/src/lib.rs | 8 +-- src/librustdoc/html/highlight.rs | 1 + .../crates/parser/src/lexed_str.rs | 2 + .../src/legacy_protocol/msg/flat.rs | 12 +++-- .../crates/proc-macro-srv/src/bridge.rs | 2 +- .../crates/proc-macro-srv/src/token_stream.rs | 34 +++++++----- tests/ui/parser/forced-keywords/basic.rs | 23 ++++++++ .../forced-keywords/decl-macro-matching.rs | 18 +++++++ .../decl-macro-matching.stderr | 47 +++++++++++++++++ .../feature-gate-forced-keywords.rs | 10 ++++ .../feature-gate-forced-keywords.stderr | 33 ++++++++++++ .../parser/forced-keywords/non-keyword-neg.rs | 12 +++++ .../forced-keywords/non-keyword-neg.stderr | 14 +++++ .../parser/forced-keywords/non-keyword-pos.rs | 14 +++++ .../forced-keywords/pre-2021-edition-fail.rs | 3 ++ .../pre-2021-edition-fail.stderr | 8 +++ .../forced-keywords/pre-2021-edition-pass.rs | 14 +++++ .../pre-2021-edition-pass.stderr | 20 +++++++ 37 files changed, 459 insertions(+), 106 deletions(-) create mode 100644 tests/ui/parser/forced-keywords/basic.rs create mode 100644 tests/ui/parser/forced-keywords/decl-macro-matching.rs create mode 100644 tests/ui/parser/forced-keywords/decl-macro-matching.stderr create mode 100644 tests/ui/parser/forced-keywords/feature-gate-forced-keywords.rs create mode 100644 tests/ui/parser/forced-keywords/feature-gate-forced-keywords.stderr create mode 100644 tests/ui/parser/forced-keywords/non-keyword-neg.rs create mode 100644 tests/ui/parser/forced-keywords/non-keyword-neg.stderr create mode 100644 tests/ui/parser/forced-keywords/non-keyword-pos.rs create mode 100644 tests/ui/parser/forced-keywords/pre-2021-edition-fail.rs create mode 100644 tests/ui/parser/forced-keywords/pre-2021-edition-fail.stderr create mode 100644 tests/ui/parser/forced-keywords/pre-2021-edition-pass.rs create mode 100644 tests/ui/parser/forced-keywords/pre-2021-edition-pass.stderr diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs index 07da107a55c58..20079dd039f6f 100644 --- a/compiler/rustc_ast/src/token.rs +++ b/compiler/rustc_ast/src/token.rs @@ -231,7 +231,7 @@ impl Lit { /// `Parser::eat_token_lit` (excluding unary negation). pub fn from_token(token: &Token) -> Option { match token.uninterpolate().kind { - Ident(name, IdentKind::Normal) if name.is_bool_lit() => { + Ident(name, IdentKind::Normal | IdentKind::ForcedKeyword) if name.is_bool_lit() => { Some(Lit::new(Bool, name, None)) } Literal(token_lit) => Some(token_lit), @@ -362,6 +362,7 @@ fn ident_can_begin_type(name: Symbol, span: Span, kind: IdentKind) -> bool { pub enum IdentKind { Normal, Raw, + ForcedKeyword, } impl IdentKind { @@ -369,12 +370,15 @@ impl IdentKind { match self { IdentKind::Normal => IdentPrintMode::Normal, IdentKind::Raw => IdentPrintMode::RawIdent, + IdentKind::ForcedKeyword => IdentPrintMode::ForcedKeywordIdent, } } + pub fn to_print_mode_lifetime(self) -> IdentPrintMode { match self { IdentKind::Normal => IdentPrintMode::Normal, IdentKind::Raw => IdentPrintMode::RawLifetime, + IdentKind::ForcedKeyword => unreachable!(), } } } @@ -637,7 +641,10 @@ impl Token { Token::new(TokenKind::Question, DUMMY_SP) } - /// Recovers a `Token` from an `Ident`. This creates a raw identifier if necessary. + /// Recovers a `Token` from an `Ident`. + /// + /// This creates a raw identifier if necessary. + /// It will never create a forced keyword. pub fn from_ast_ident(ident: sp::Ident) -> Self { let kind = if ident.is_raw_guess() { IdentKind::Raw } else { IdentKind::Normal }; Token::new(Ident(ident.name, kind), ident.span) @@ -763,7 +770,7 @@ impl Token { pub fn can_begin_const_arg(&self) -> bool { match self.kind { OpenBrace | Literal(..) | Minus => true, - Ident(name, IdentKind::Normal) if name.is_bool_lit() => true, + Ident(name, IdentKind::Normal | IdentKind::ForcedKeyword) if name.is_bool_lit() => true, OpenInvisible(InvisibleOrigin::MetaVar( MetaVarKind::Expr { .. } | MetaVarKind::Block | MetaVarKind::Literal, )) => true, @@ -812,7 +819,7 @@ impl Token { pub fn can_begin_literal_maybe_minus(&self) -> bool { match self.uninterpolate().kind { Literal(..) | Minus => true, - Ident(name, IdentKind::Normal) if name.is_bool_lit() => true, + Ident(name, IdentKind::Normal | IdentKind::ForcedKeyword) if name.is_bool_lit() => true, OpenInvisible(InvisibleOrigin::MetaVar(mv_kind)) => match mv_kind { MetaVarKind::Literal => true, MetaVarKind::Expr { can_begin_literal_maybe_minus, .. } => { @@ -962,7 +969,7 @@ impl Token { /// Returns `true` if the token is either a special identifier or a keyword. pub fn is_reserved_ident(&self) -> bool { - self.non_raw_ident().is_some_and(sp::Ident::is_reserved) + self.ident().is_some_and(|(id, kind)| ident_of_kind_is_reserved(id, kind)) } pub fn is_non_reserved_ident(&self) -> bool { @@ -970,15 +977,13 @@ impl Token { } pub fn non_reserved_ident(&self) -> Option { - self.ident() - .filter(|&(id, kind)| kind == IdentKind::Raw || !id.is_reserved()) - .map(|(id, _)| id) + self.ident().filter(|&(id, kind)| !ident_of_kind_is_reserved(id, kind)).map(|(id, _)| id) } /// If this token is a non-raw identifier, return the identifier in question. pub fn non_raw_ident(&self) -> Option { match self.ident() { - Some((id, IdentKind::Normal)) => Some(id), + Some((id, IdentKind::Normal | IdentKind::ForcedKeyword)) => Some(id), _ => None, } } @@ -1102,6 +1107,14 @@ impl PartialEq for Token { } } +pub fn ident_of_kind_is_reserved(id: sp::Ident, kind: IdentKind) -> bool { + match kind { + IdentKind::Normal => id.is_reserved(), + IdentKind::Raw => false, + IdentKind::ForcedKeyword => true, + } +} + #[derive(Debug, Copy, Clone, PartialEq, Eq, Encodable, Decodable, Hash, StableHash)] pub enum NtPatKind { // Matches or-patterns. Was written using `pat` in edition 2021 or later. diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 9d0ca67ce93d5..0232e83de841d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -441,6 +441,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) { gate_all!(explicit_tail_calls, "`become` expression is experimental"); gate_all!(final_associated_functions, "`final` on trait functions is experimental"); gate_all!(fn_delegation, "functions delegation is not yet fully implemented"); + gate_all!(forced_keywords, "forced keywords are experimental"); gate_all!(frontmatter, "frontmatters are experimental"); gate_all!(gca_min_const_items, "unbraced const blocks as const args are experimental"); gate_all!(gen_blocks, "gen blocks are experimental"); diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 6637ed356f557..5dcc8ce69c6d1 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -370,12 +370,10 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool { // IDENT|`fn`|`Self`|`pub` + `(`: `f(3)`, `fn(x: u8)`, `Self()`, `pub(crate)`, // but `let (a, b) = (1, 2)` needs a space after the `let` - (Tok(tk::Token { kind: tk::Ident(sym, kind), span }, _), Del(_, _, Parenthesis, _)) - if !Ident::new(*sym, *span).is_reserved() - || *sym == kw::Fn - || *sym == kw::SelfUpper - || *sym == kw::Pub - || matches!(kind, tk::IdentKind::Raw) => + (&Tok(tk::Token { kind: tk::Ident(sym, kind), span }, _), Del(_, _, Parenthesis, _)) + if kind == tk::IdentKind::Raw + || matches!(sym, kw::Fn | kw::SelfUpper | kw::Pub) + || !Ident::new(sym, span).is_reserved() => { false } diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs index e28044d7632a9..f070009fc3d57 100644 --- a/compiler/rustc_expand/src/mbe/macro_check.rs +++ b/compiler/rustc_expand/src/mbe/macro_check.rs @@ -397,7 +397,8 @@ fn check_nested_occurrences( ( NestedMacroState::Empty, &TokenTree::Token(Token { - kind: TokenKind::Ident(name, IdentKind::Normal), .. + kind: TokenKind::Ident(name, IdentKind::Normal | IdentKind::ForcedKeyword), + .. }), ) => { if name == kw::MacroRules { diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs index d762763b8dcea..12f308fc546c3 100644 --- a/compiler/rustc_expand/src/mbe/macro_rules.rs +++ b/compiler/rustc_expand/src/mbe/macro_rules.rs @@ -1750,7 +1750,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Eq | Or => IsInFollow::Yes, - Ident(name, IdentKind::Normal) if name == kw::If || name == kw::In => { + Ident(kw::If | kw::In, IdentKind::Normal | IdentKind::ForcedKeyword) => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), @@ -1764,7 +1764,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { match tok { TokenTree::Token(token) => match token.kind { FatArrow | Comma | Eq => IsInFollow::Yes, - Ident(name, IdentKind::Normal) if name == kw::If || name == kw::In => { + Ident(kw::If | kw::In, IdentKind::Normal | IdentKind::ForcedKeyword) => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), @@ -1792,7 +1792,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow { TokenTree::Token(token) => match token.kind { OpenBrace | OpenBracket | Comma | FatArrow | Colon | Eq | Gt | Shr | Semi | Or => IsInFollow::Yes, - Ident(name, IdentKind::Normal) if name == kw::As || name == kw::Where => { + Ident(kw::As | kw::Where, IdentKind::Normal | IdentKind::ForcedKeyword) => { IsInFollow::Yes } _ => IsInFollow::No(TOKENS), diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 9774165c73400..807d4fae6de15 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -9,7 +9,6 @@ use rustc_span::{Ident, Span, Symbol, sym}; use crate::diagnostics; -pub(crate) const RAW_IDENT_ERR: &str = "`${concat(..)}` currently does not support raw identifiers"; pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or string literal"; /// A meta-variable expression, for expansions based on properties of meta-variables. @@ -197,6 +196,10 @@ fn parse_concat<'psess>( } else { match parse_ident_from_token(psess, token) { Err(err) => { + // FIXME: Canceling this error means we emit a worse message when encountering + // raw identifiers (`r#ident`). However, we also don't want to forward + // (the current version of) this error as is since we also want to + // mentioning string literals as a valid token kind. err.cancel(); return Err(psess .dcx() @@ -281,9 +284,7 @@ fn parse_ident_from_token<'psess>( token: &Token, ) -> PResult<'psess, Ident> { if let Some((elem, kind)) = token.ident() { - if let IdentKind::Raw = kind { - return Err(psess.dcx().struct_span_err(elem.span, RAW_IDENT_ERR)); - } + validate_ident_kind(psess.dcx(), kind, elem.span)?; return Ok(elem); } let token_str = pprust::token_to_string(token); @@ -347,3 +348,16 @@ fn eat_dollar<'psess>( "meta-variables within meta-variable expressions must be referenced using a dollar sign", )) } + +pub(crate) fn validate_ident_kind<'a>( + dcx: rustc_errors::DiagCtxtHandle<'a>, + kind: IdentKind, + span: Span, +) -> PResult<'a, ()> { + let kind = match kind { + IdentKind::Normal => return Ok(()), + IdentKind::Raw => "raw identifiers", + IdentKind::ForcedKeyword => "forced keywords", + }; + Err(dcx.struct_span_err(span, format!("`${{concat(..)}}` currently does not support {kind}"))) +} diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index ff1607c9e4456..80e258e94510c 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -337,10 +337,13 @@ fn parse_tree<'a>( // `tree` is followed by an `ident`. This could be `$meta_var` or the `$crate` // special metavariable that names the crate of the invocation. - Some(tokenstream::TokenTree::Token(token, _)) if token.is_ident() => { - let (ident, kind) = token.ident().unwrap(); + Some(tokenstream::TokenTree::Token(token, _)) + if let Some((ident, kind)) = token.ident() => + { let span = ident.span.with_lo(dollar_span.lo()); - if ident.name == kw::Crate && matches!(kind, IdentKind::Normal) { + if let kw::Crate = ident.name + && let IdentKind::Normal | IdentKind::ForcedKeyword = kind + { TokenTree::token(token::Ident(kw::DollarCrate, kind), span) } else { TokenTree::MetaVar(span, ident) diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index 8d036972ad592..736a8d1de4c19 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -25,7 +25,7 @@ use crate::diagnostics::{ }; use crate::mbe::macro_parser::NamedMatch; use crate::mbe::macro_parser::NamedMatch::*; -use crate::mbe::metavar_expr::{MetaVarExprConcatElem, RAW_IDENT_ERR}; +use crate::mbe::metavar_expr::{MetaVarExprConcatElem, validate_ident_kind}; use crate::mbe::{self, KleeneOp, MetaVarExpr}; /// Context needed to perform transcription of metavariable expressions. @@ -1033,21 +1033,15 @@ fn extract_symbol_from_pnr<'a>( ) -> PResult<'a, Symbol> { match pnr { ParseNtResult::Ident(nt_ident, kind) => { - if let IdentKind::Raw = kind { - Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) - } else { - Ok(nt_ident.name) - } + validate_ident_kind(dcx, *kind, span_err)?; + Ok(nt_ident.name) } ParseNtResult::Tt(TokenTree::Token( Token { kind: TokenKind::Ident(symbol, kind), .. }, _, )) => { - if let IdentKind::Raw = kind { - Err(dcx.struct_span_err(span_err, RAW_IDENT_ERR)) - } else { - Ok(*symbol) - } + validate_ident_kind(dcx, *kind, span_err)?; + Ok(*symbol) } ParseNtResult::Tt(TokenTree::Token( Token { diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs index 1ecf808f78839..ae985050fe71e 100644 --- a/compiler/rustc_expand/src/proc_macro_server.rs +++ b/compiler/rustc_expand/src/proc_macro_server.rs @@ -11,7 +11,8 @@ use rustc_parse::lexer::{StripTokens, nfc_normalize}; use rustc_parse::parser::Parser; use rustc_parse::{exp, new_parser_from_source_str, source_str_to_stream}; use rustc_proc_macro::bridge::{ - DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, LitKind, Literal, Punct, TokenTree, server, + DelimSpan, Diagnostic, ExpnGlobals, Group, Ident, IdentKind, LitKind, Literal, Punct, + TokenTree, server, }; use rustc_proc_macro::{Delimiter, Level}; use rustc_session::Session; @@ -103,6 +104,26 @@ impl ToInternal for LitKind { } } +impl FromInternal for IdentKind { + fn from_internal(kind: tk::IdentKind) -> Self { + match kind { + tk::IdentKind::Normal => IdentKind::Normal, + tk::IdentKind::Raw => IdentKind::Raw, + tk::IdentKind::ForcedKeyword => IdentKind::ForcedKeyword, + } + } +} + +impl ToInternal for IdentKind { + fn to_internal(self) -> tk::IdentKind { + match self { + IdentKind::Normal => tk::IdentKind::Normal, + IdentKind::Raw => tk::IdentKind::Raw, + IdentKind::ForcedKeyword => tk::IdentKind::ForcedKeyword, + } + } +} + impl FromInternal for Vec> { fn from_internal(stream: TokenStream) -> Self { // Estimate the capacity as `stream.len()` rounded up to the next power @@ -127,7 +148,7 @@ impl FromInternal for Vec> { } trees.push(TokenTree::Group(Group { - delimiter: rustc_proc_macro::Delimiter::from_internal(delim), + delimiter: Delimiter::from_internal(delim), stream: Some(stream), span: DelimSpan { open: span.open, @@ -230,12 +251,12 @@ impl FromInternal for Vec> { tk::Ident(sym, kind) => trees.push(TokenTree::Ident(Ident { sym, - is_raw: matches!(kind, tk::IdentKind::Raw), + kind: IdentKind::from_internal(kind), span, })), tk::NtIdent(ident, kind) => trees.push(TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(kind, tk::IdentKind::Raw), + kind: IdentKind::from_internal(kind), span: ident.span, })), @@ -245,7 +266,7 @@ impl FromInternal for Vec> { TokenTree::Punct(Punct { ch: b'\'', joint: true, span }), TokenTree::Ident(Ident { sym: ident.name, - is_raw: matches!(kind, tk::IdentKind::Raw), + kind: IdentKind::from_internal(kind), span, }), ]); @@ -254,7 +275,7 @@ impl FromInternal for Vec> { let stream = TokenStream::token_alone(tk::Lifetime(ident.name, kind), ident.span); trees.push(TokenTree::Group(Group { - delimiter: rustc_proc_macro::Delimiter::None, + delimiter: Delimiter::None, stream: Some(stream), span: DelimSpan::from_single(span), })) @@ -286,7 +307,7 @@ impl FromInternal for Vec> { trees.push(TokenTree::Punct(Punct { ch: b'!', joint: false, span })); } trees.push(TokenTree::Group(Group { - delimiter: rustc_proc_macro::Delimiter::Bracket, + delimiter: Delimiter::Bracket, stream: Some(stream), span: DelimSpan::from_single(span), })); @@ -364,17 +385,16 @@ impl ToInternal> stream.unwrap_or_default(), )] } - TokenTree::Ident(self::Ident { sym, is_raw, span }) => { + TokenTree::Ident(Ident { sym, kind, span }) => { rustc.psess().symbol_gallery.insert(sym, span); - let kind = if is_raw { tk::IdentKind::Raw } else { tk::IdentKind::Normal }; - smallvec![tokenstream::TokenTree::token_alone(tk::Ident(sym, kind), span)] + smallvec![tokenstream::TokenTree::token_alone( + tk::Ident(sym, kind.to_internal()), + span + )] } - TokenTree::Literal(self::Literal { - kind: self::LitKind::Integer, - symbol, - suffix, - span, - }) if let Some(symbol) = symbol.as_str().strip_prefix('-') => { + TokenTree::Literal(self::Literal { kind: LitKind::Integer, symbol, suffix, span }) + if let Some(symbol) = symbol.as_str().strip_prefix('-') => + { let symbol = Symbol::intern(symbol); let integer = tk::TokenKind::lit(tk::Integer, symbol, suffix); let a = tokenstream::TokenTree::token_joint_hidden(tk::Minus, span); diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 49489c0ed903d..35c0a28a18f8f 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -542,6 +542,8 @@ declare_features! ( (incomplete, fn_delegation, "1.76.0", Some(118212)), /// Traits for function pointers and items (unstable, fn_static, "CURRENT_RUSTC_VERSION", Some(148768)), + /// Allows using forced keywords `k#fn`. + (unstable, forced_keywords, "CURRENT_RUSTC_VERSION", Some(153839)), /// Allows impls for the Freeze trait. (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs index dc6e3b1f358dc..043b7ad59d0a8 100644 --- a/compiler/rustc_lexer/src/lib.rs +++ b/compiler/rustc_lexer/src/lib.rs @@ -101,6 +101,9 @@ pub enum TokenKind { /// A raw identifier, e.g. "r#ident". RawIdent, + /// A forced keyword like `k#fn`. + ForcedKeywordIdent, + /// An unknown literal prefix, like `foo#`, `foo'`, `foo"`. Excludes /// literal prefixes that contain emoji, which are considered "invalid". /// @@ -574,7 +577,11 @@ impl<'a> Cursor<'a> { // Raw identifier, raw string literal or identifier. 'r' => match (self.first(), self.second()) { - ('#', c1) if is_id_start(c1) => self.raw_ident(), + ('#', c1) if is_id_start(c1) => { + self.bump(); // `#` + self.eat_identifier(); + RawIdent + } ('#', _) | ('"', _) => { let res = self.raw_double_quoted_string(1); let suffix_start = self.pos_within_token(); @@ -587,6 +594,16 @@ impl<'a> Cursor<'a> { _ => self.ident_or_unknown_prefix(), }, + // Forced keyword identifier or identifier. + 'k' => match (self.first(), self.second()) { + ('#', c1) if is_id_start(c1) => { + self.bump(); // `#` + self.eat_identifier(); + ForcedKeywordIdent + } + _ => self.ident_or_unknown_prefix(), + }, + // Byte literal, byte string literal, raw byte string literal or identifier. 'b' => self.c_or_byte_string( |terminated| ByteStr { terminated }, @@ -823,15 +840,6 @@ impl<'a> Cursor<'a> { Whitespace } - fn raw_ident(&mut self) -> TokenKind { - debug_assert!(self.prev() == 'r' && self.first() == '#' && is_id_start(self.second())); - // Eat "#" symbol. - self.bump(); - // Eat the identifier part of RawIdent. - self.eat_identifier(); - RawIdent - } - fn ident_or_unknown_prefix(&mut self) -> TokenKind { debug_assert!(is_id_start(self.prev())); // Start is already eaten, eat the rest of identifier. diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs index 787747ff5daf9..03d5634fc359c 100644 --- a/compiler/rustc_parse/src/lexer/mod.rs +++ b/compiler/rustc_parse/src/lexer/mod.rs @@ -240,6 +240,33 @@ impl<'psess, 'src> Lexer<'psess, 'src> { self.psess.raw_identifier_spans.push(span); token::Ident(sym, IdentKind::Raw) } + rustc_lexer::TokenKind::ForcedKeywordIdent => { + let span = self.mk_sp(start, self.pos); + + if span.edition().at_least_rust_2021() { + let sym = nfc_normalize(self.str_from(start + BytePos(2))); + self.psess.symbol_gallery.insert(sym, span); + self.psess.gated_spans.gate(sym::forced_keywords, span); + token::Ident(sym, IdentKind::ForcedKeyword) + } else { + // Reset the state so that only the `k` was consumed. + self.pos = start + BytePos(1); + self.cursor = Cursor::new(&str_before[1..], FrontmatterAllowed::No); + + self.psess.buffer_lint( + RUST_2021_PREFIXES_INCOMPATIBLE_SYNTAX, + span, + ast::CRATE_NODE_ID, + crate::diagnostics::ReservedPrefixLint { + subject: "this".into(), + kind: "forced keyword", + edition: Edition::Edition2021, + sugg: self.mk_sp(start, self.pos).shrink_to_hi(), + } + ); + self.ident(start) + } + } rustc_lexer::TokenKind::UnknownPrefix => { self.report_unknown_prefix(start); self.ident(start) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index bb8be3c9c509f..e7073a4d81978 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -243,18 +243,19 @@ impl<'a> Parser<'a> { None }; - let suggest_remove_comma = - if self.token == token::Comma && self.look_ahead(1, |t| t.is_ident()) { - if recover { - self.bump(); - recovered_ident = self.ident_or_err(false).ok(); - }; - - Some(SuggRemoveComma { span: bad_token.span }) - } else { - None + let suggest_remove_comma = if self.token == token::Comma + && let Some(ident) = self.look_ahead(1, Token::ident) + { + if recover { + self.bump(); + recovered_ident = Some(ident); }; + Some(SuggRemoveComma { span: bad_token.span }) + } else { + None + }; + let help_cannot_start_number = self.is_lit_bad_ident().map(|(len, valid_portion)| { let (invalid, valid) = self.token.span.split_at(len as u32); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a5c31672a2bc7..9e74a7b1ab38c 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -745,8 +745,7 @@ impl<'a> Parser<'a> { lo: Span, ) -> PResult<'a, Box> { let mut res = loop { - let has_question = if self.prev_token == TokenKind::Ident(kw::Return, IdentKind::Normal) - { + let has_question = if self.prev_token.is_keyword(kw::Return) { // We are using noexpect here because we don't expect a `?` directly after // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Question) @@ -758,7 +757,7 @@ impl<'a> Parser<'a> { e = self.mk_expr(lo.to(self.prev_token.span), ExprKind::Try(e)); continue; } - let has_dot = if self.prev_token == TokenKind::Ident(kw::Return, IdentKind::Normal) { + let has_dot = if self.prev_token.is_keyword(kw::Return) { // We are using noexpect here because we don't expect a `.` directly after // a `return` which could be suggested otherwise. self.eat_noexpect(&token::Dot) @@ -1447,6 +1446,7 @@ impl<'a> Parser<'a> { // or `async gen {}` and `async gen move {}` // FIXME: (async) gen closures aren't yet parsed. // FIXME(gen_blocks): Parse `gen async` and suggest swap + // FIXME(forced_keywords): Allow k#gen blocks prior to Rust 2024, too! if this.token_uninterpolated_span().at_least_rust_2024() && this.is_gen_block(kw::Gen, at_async as usize) { @@ -2092,7 +2092,9 @@ impl<'a> Parser<'a> { } }; match self.token.uninterpolate().kind { - token::Ident(name, IdentKind::Normal) if name.is_bool_lit() => { + token::Ident(name, IdentKind::Normal | IdentKind::ForcedKeyword) + if name.is_bool_lit() => + { self.bump(); Some(token::Lit::new(token::Bool, name, None)) } diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs index 3ec86dfacbd06..9fb16bc3fbf27 100644 --- a/compiler/rustc_parse/src/parser/item.rs +++ b/compiler/rustc_parse/src/parser/item.rs @@ -2507,8 +2507,7 @@ impl<'a> Parser<'a> { /// for better diagnostics and suggestions. fn parse_field_ident(&mut self, adt_ty: &str, lo: Span) -> PResult<'a, Ident> { let (ident, kind) = self.ident_or_err(true)?; - if kind == IdentKind::Normal - && ident.is_reserved() + if token::ident_of_kind_is_reserved(ident, kind) && !(ident.name == kw::Underscore && adt_ty == "enum") { let snapshot = self.create_snapshot_for_diagnostic(); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 50ded81e3eeec..99d5a1fa6f257 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -459,15 +459,17 @@ impl<'a> Parser<'a> { pub(crate) fn parse_ident_common(&mut self, recover: bool) -> PResult<'a, Ident> { let (ident, kind) = self.ident_or_err(recover)?; - if kind == IdentKind::Normal && ident.is_reserved() { + if token::ident_of_kind_is_reserved(ident, kind) { let err = self.expected_ident_found_err(); - if recover { + if recover && kind != IdentKind::ForcedKeyword { err.emit(); } else { return Err(err); } } + self.bump(); + Ok(ident) } @@ -722,7 +724,10 @@ impl<'a> Parser<'a> { self.is_keyword_ahead(0, &[kw::Const]) && self.look_ahead(1, |t| match t.uninterpolate().kind { - token::Ident(kw::Move | kw::Use | kw::Static, IdentKind::Normal) + token::Ident( + kw::Move | kw::Use | kw::Static, + IdentKind::Normal | IdentKind::ForcedKeyword, + ) | token::OrOr | token::Or => true, _ => false, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index 1ab07a626d1c0..f53cfc792bd69 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -353,7 +353,7 @@ impl<'a> Parser<'a> { matches!( &token.uninterpolate().kind, token::FatArrow // e.g. `a | => 0,`. - | token::Ident(kw::If, token::IdentKind::Normal) // e.g. `a | if expr`. + | token::Ident(kw::If, token::IdentKind::Normal | token::IdentKind::ForcedKeyword) // e.g. `a | if expr`. | token::Eq // e.g. `let a | = 0`. | token::Semi // e.g. `let a |;`. | token::Colon // e.g. `let a | :`. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e62ad42875248..93a83ddf213c1 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1028,6 +1028,7 @@ symbols! { forall, forbid, force_target_feature, + forced_keywords, forget, format_args, format_args_capture, @@ -2583,6 +2584,7 @@ impl fmt::Display for Ident { pub enum IdentPrintMode { Normal, RawIdent, + ForcedKeywordIdent, RawLifetime, } @@ -2643,6 +2645,10 @@ impl fmt::Display for IdentPrinter { f.write_str("r#")?; self.symbol } + IdentPrintMode::ForcedKeywordIdent => { + f.write_str("k#")?; + self.symbol + } IdentPrintMode::RawLifetime => { f.write_str("'r#")?; let s = self diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs index 0761549b2e30d..4b12ed0058847 100644 --- a/library/proc_macro/src/bridge/mod.rs +++ b/library/proc_macro/src/bridge/mod.rs @@ -222,6 +222,7 @@ mark_noop! { usize, Delimiter, LitKind, + IdentKind, Level, Bound, Range, @@ -385,11 +386,36 @@ compound_traits!(struct Punct { ch, joint, span }); #[derive(Copy, Clone, Eq, PartialEq)] pub struct Ident { pub sym: Symbol, - pub is_raw: bool, + pub kind: IdentKind, pub span: Span, } -compound_traits!(struct Ident { sym, is_raw, span }); +compound_traits!(struct Ident { sym, kind, span }); + +#[derive(Copy, Clone, Eq, PartialEq)] +pub enum IdentKind { + Normal, + Raw, + ForcedKeyword, +} + +impl IdentKind { + pub fn prefix(self) -> Option<&'static str> { + match self { + Self::Normal => None, + Self::Raw => Some("r#"), + Self::ForcedKeyword => Some("k#"), + } + } +} + +rpc_encode_decode!( + enum IdentKind { + Normal, + Raw, + ForcedKeyword, + } +); #[derive(Clone, Eq, PartialEq)] pub struct Literal { diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index b8ffcd53b25d8..e7519a8c018f2 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -1197,7 +1197,7 @@ impl Ident { pub fn new(string: &str, span: Span) -> Ident { Ident(bridge::Ident { sym: bridge::client::Symbol::new_ident(string, false), - is_raw: false, + kind: bridge::IdentKind::Normal, span: span.0, }) } @@ -1210,7 +1210,7 @@ impl Ident { pub fn new_raw(string: &str, span: Span) -> Ident { Ident(bridge::Ident { sym: bridge::client::Symbol::new_ident(string, true), - is_raw: true, + kind: bridge::IdentKind::Raw, span: span.0, }) } @@ -1234,8 +1234,8 @@ impl Ident { #[stable(feature = "proc_macro_lib2", since = "1.29.0")] impl fmt::Display for Ident { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - if self.0.is_raw { - f.write_str("r#")?; + if let Some(prefix) = self.0.kind.prefix() { + f.write_str(prefix)?; } fmt::Display::fmt(&self.0.sym, f) } diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 9c73e3b4ad687..6ef5de0b20aba 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -1297,6 +1297,7 @@ impl<'src> Classifier<'src> { TokenKind::RawIdent | TokenKind::UnknownPrefix | TokenKind::InvalidIdent => { Class::Ident(new_span(before, text, file_span)) } + TokenKind::ForcedKeywordIdent => Class::KeyWord, TokenKind::Lifetime { .. } | TokenKind::RawLifetime | TokenKind::UnknownPrefixLifetime => Class::Lifetime, diff --git a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs index ec994b731bf95..f449809911c90 100644 --- a/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs +++ b/src/tools/rust-analyzer/crates/parser/src/lexed_str.rs @@ -246,6 +246,8 @@ impl<'a> Converter<'a> { } rustc_lexer::TokenKind::RawIdent => IDENT, + #[cfg(feature = "in-rust-tree")] + rustc_lexer::TokenKind::ForcedKeywordIdent => ERROR, rustc_lexer::TokenKind::GuardedStrPrefix if self.edition.at_least_2024() => { // FIXME: rustc does something better for recovery. diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs index b9b6247b54fab..55ccc98f4f23e 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/legacy_protocol/msg/flat.rs @@ -699,14 +699,17 @@ impl<'a, T: SpanTransformer> proc_macro_srv::TokenTree::Ident(ident) => { let idx = self.ident.len() as u32; let id = self.token_id_of(ident.span); + // NOTE(forced_keywords): Let's not bother to preserve forced keywords in this + // legacy protocol. + let is_raw = matches!(ident.kind, proc_macro_srv::IdentKind::Raw); let text = if self.version >= EXTENDED_LEAF_DATA { self.intern(ident.sym.as_str()) - } else if ident.is_raw { + } else if is_raw { self.intern_owned(format!("r#{}", ident.sym.as_str(),)) } else { self.intern(ident.sym.as_str()) }; - self.ident.push(IdentRepr { id, text, is_raw: ident.is_raw }); + self.ident.push(IdentRepr { id, text, is_raw }); (idx << 2) | 0b11 } }; @@ -944,7 +947,10 @@ impl Reader<'_, T> { proc_macro_srv::TokenTree::Ident(proc_macro_srv::Ident { sym: Symbol::intern(text), span: read_span(repr.id), - is_raw: is_raw.yes(), + kind: match is_raw { + tt::IdentIsRaw::Yes => proc_macro_srv::IdentKind::Raw, + tt::IdentIsRaw::No => proc_macro_srv::IdentKind::Normal, + }, }) } other => panic!("bad tag: {other}"), diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/bridge.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/bridge.rs index fc62f9413a34e..e573e57c8b7b1 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/bridge.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/bridge.rs @@ -2,7 +2,7 @@ use rustc_proc_macro::bridge as pm_bridge; -pub use pm_bridge::{DelimSpan, Diagnostic, ExpnGlobals, LitKind}; +pub use pm_bridge::{DelimSpan, Diagnostic, ExpnGlobals, IdentKind, LitKind}; pub type TokenTree = pm_bridge::TokenTree, S, intern::Symbol>; diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/src/token_stream.rs b/src/tools/rust-analyzer/crates/proc-macro-srv/src/token_stream.rs index 5201bb6aeb86b..7038152ac2651 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/src/token_stream.rs +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/src/token_stream.rs @@ -7,7 +7,7 @@ use intern::Symbol; use rustc_lexer::{DocStyle, LiteralKind}; use rustc_proc_macro::Delimiter; -use crate::bridge::{DelimSpan, Group, Ident, LitKind, Literal, Punct, TokenTree}; +use crate::bridge::{DelimSpan, Group, Ident, IdentKind, LitKind, Literal, Punct, TokenTree}; /// Trait for allowing tests to parse tokenstreams with dynamic span ranges pub(crate) trait SpanLike { @@ -200,7 +200,7 @@ impl TokenStream { stream: Some(TokenStream::new(vec![ TokenTree::Ident(Ident { sym: Symbol::intern("doc"), - is_raw: false, + kind: IdentKind::Normal, span, }), TokenTree::Punct(Punct { ch: b'=', joint: false, span }), @@ -226,7 +226,7 @@ impl TokenStream { stream: Some(TokenStream::new(vec![ TokenTree::Ident(Ident { sym: Symbol::intern("doc"), - is_raw: false, + kind: IdentKind::Normal, span, }), TokenTree::Punct(Punct { ch: b'=', joint: false, span }), @@ -267,7 +267,7 @@ impl TokenStream { } rustc_lexer::TokenKind::Ident => tokenstream.push(TokenTree::Ident(Ident { sym: Symbol::intern(&s[range.clone()]), - is_raw: false, + kind: IdentKind::Normal, span: span.derive_ranged(range), })), rustc_lexer::TokenKind::InvalidIdent => { @@ -277,7 +277,15 @@ impl TokenStream { let range = range.start + 2..range.end; tokenstream.push(TokenTree::Ident(Ident { sym: Symbol::intern(&s[range.clone()]), - is_raw: true, + kind: IdentKind::Raw, + span: span.derive_ranged(range), + })) + } + rustc_lexer::TokenKind::ForcedKeywordIdent => { + let range = range.start + 2..range.end; + tokenstream.push(TokenTree::Ident(Ident { + sym: Symbol::intern(&s[range.clone()]), + kind: IdentKind::ForcedKeyword, span: span.derive_ranged(range), })) } @@ -298,7 +306,7 @@ impl TokenStream { })); tokenstream.push(TokenTree::Ident(Ident { sym: Symbol::intern(&s[range.clone()]), - is_raw: true, + kind: IdentKind::Raw, span: span.derive_ranged(range), })) } @@ -314,7 +322,7 @@ impl TokenStream { })); tokenstream.push(TokenTree::Ident(Ident { sym: Symbol::intern(&s[range.clone()]), - is_raw: false, + kind: IdentKind::Normal, span: span.derive_ranged(range), })) } @@ -484,9 +492,9 @@ fn display_token_tree( *emit_whitespace = !*joint; write!(f, "{}", *ch as char)?; } - TokenTree::Ident(Ident { sym, is_raw, span: _ }) => { - if *is_raw { - write!(f, "r#")?; + TokenTree::Ident(Ident { sym, kind, span: _ }) => { + if let Some(prefix) = kind.prefix() { + write!(f, "{prefix}")?; } write!(f, "{sym}")?; *emit_whitespace = true; @@ -613,10 +621,10 @@ fn debug_token_tree( *ch as char, if *joint { "[joint]" } else { "[alone]" } )?, - TokenTree::Ident(Ident { sym, is_raw, span }) => { + TokenTree::Ident(Ident { sym, kind, span }) => { write!(f, "IDENT {span:#?} ")?; - if *is_raw { - write!(f, "r#")?; + if let Some(prefix) = kind.prefix() { + write!(f, "{prefix}")?; } write!(f, "{sym}")?; } diff --git a/tests/ui/parser/forced-keywords/basic.rs b/tests/ui/parser/forced-keywords/basic.rs new file mode 100644 index 0000000000000..7a547b8f3d667 --- /dev/null +++ b/tests/ui/parser/forced-keywords/basic.rs @@ -0,0 +1,23 @@ +//@ edition: 2021.. +//@ check-pass +#![feature(forced_keywords)] + +k#mod module { + k#pub(k#in k#super) k#static _DATA: i32 = 0i8 k#as k#_; +} + +k#use ::std::process::Termination; + +k#fn main() -> k#impl k#self::Termination { + k#let k#true = k#false k#else { k#return }; + + k#let k#ref k#mut _x: (); + + k#const k#fn perform() -> k#impl Sized { + k#loop { + k#break k#match () { () k#if k#true => {} k#_ => {} }; + } + } + + perform(); +} diff --git a/tests/ui/parser/forced-keywords/decl-macro-matching.rs b/tests/ui/parser/forced-keywords/decl-macro-matching.rs new file mode 100644 index 0000000000000..dbe0be0527d2b --- /dev/null +++ b/tests/ui/parser/forced-keywords/decl-macro-matching.rs @@ -0,0 +1,18 @@ +// Demonstrate that decl macros can tell apart forced keywords from other kinds +// of identifiers when matching. +// +//@ edition: 2021.. +#![feature(forced_keywords)] + +macro_rules! accept { + (ForcedKeyword k#type) => {}; + (Normal type) => {}; +} + +accept!(ForcedKeyword type); //~ ERROR no rules expected keyword `type` +accept!(ForcedKeyword r#type); //~ ERROR no rules expected `r#type` +accept!(ForcedKeyword k#type); // OK + +accept!(Normal k#type); //~ ERROR no rules expected keyword `k#type` + +fn main() {} diff --git a/tests/ui/parser/forced-keywords/decl-macro-matching.stderr b/tests/ui/parser/forced-keywords/decl-macro-matching.stderr new file mode 100644 index 0000000000000..36659142776d9 --- /dev/null +++ b/tests/ui/parser/forced-keywords/decl-macro-matching.stderr @@ -0,0 +1,47 @@ +error: no rules expected keyword `type` + --> $DIR/decl-macro-matching.rs:12:23 + | +LL | macro_rules! accept { + | ------------------- when calling this macro +... +LL | accept!(ForcedKeyword type); + | ^^^^ no rules expected this token in macro call + | +note: while trying to match keyword `k#type` + --> $DIR/decl-macro-matching.rs:8:20 + | +LL | (ForcedKeyword k#type) => {}; + | ^^^^^^ + +error: no rules expected `r#type` + --> $DIR/decl-macro-matching.rs:13:23 + | +LL | macro_rules! accept { + | ------------------- when calling this macro +... +LL | accept!(ForcedKeyword r#type); + | ^^^^^^ no rules expected this token in macro call + | +note: while trying to match keyword `k#type` + --> $DIR/decl-macro-matching.rs:8:20 + | +LL | (ForcedKeyword k#type) => {}; + | ^^^^^^ + +error: no rules expected keyword `k#type` + --> $DIR/decl-macro-matching.rs:16:16 + | +LL | macro_rules! accept { + | ------------------- when calling this macro +... +LL | accept!(Normal k#type); + | ^^^^^^ no rules expected this token in macro call + | +note: while trying to match keyword `type` + --> $DIR/decl-macro-matching.rs:9:13 + | +LL | (Normal type) => {}; + | ^^^^ + +error: aborting due to 3 previous errors + diff --git a/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.rs b/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.rs new file mode 100644 index 0000000000000..39b52d382db9b --- /dev/null +++ b/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.rs @@ -0,0 +1,10 @@ +//@ edition: 2021.. + +k#fn main() {} //~ ERROR forced keywords are experimental + +#[cfg(false)] +k#fn start() {} //~ ERROR forced keywords are experimental + +macro_rules! discard { ($($tt:tt)*) => {} } + +discard!(k#static); //~ ERROR forced keywords are experimental diff --git a/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.stderr b/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.stderr new file mode 100644 index 0000000000000..0beb805832c83 --- /dev/null +++ b/tests/ui/parser/forced-keywords/feature-gate-forced-keywords.stderr @@ -0,0 +1,33 @@ +error[E0658]: forced keywords are experimental + --> $DIR/feature-gate-forced-keywords.rs:3:1 + | +LL | k#fn main() {} + | ^^^^ + | + = note: see issue #153839 for more information + = help: add `#![feature(forced_keywords)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: forced keywords are experimental + --> $DIR/feature-gate-forced-keywords.rs:6:1 + | +LL | k#fn start() {} + | ^^^^ + | + = note: see issue #153839 for more information + = help: add `#![feature(forced_keywords)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: forced keywords are experimental + --> $DIR/feature-gate-forced-keywords.rs:10:10 + | +LL | discard!(k#static); + | ^^^^^^^^ + | + = note: see issue #153839 for more information + = help: add `#![feature(forced_keywords)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/parser/forced-keywords/non-keyword-neg.rs b/tests/ui/parser/forced-keywords/non-keyword-neg.rs new file mode 100644 index 0000000000000..6bcba5d9e4b25 --- /dev/null +++ b/tests/ui/parser/forced-keywords/non-keyword-neg.rs @@ -0,0 +1,12 @@ +// You are intentionally allowed to force identifiers to be treated as keywords even if they aren't +// actually reserved. We must ensure that we never treat them as normal identifiers when parsing. +// +//@ edition: 2021.. +#![feature(forced_keywords)] + +fn scope() { + k#not_a_keyword() + //~^ ERROR expected expression, found `k#not_a_keyword` +} +fn k#trying_to_pass_as_a_normal_ident() {} +//~^ ERROR expected identifier, found `k#trying_to_pass_as_a_normal_ident` diff --git a/tests/ui/parser/forced-keywords/non-keyword-neg.stderr b/tests/ui/parser/forced-keywords/non-keyword-neg.stderr new file mode 100644 index 0000000000000..7d8a9f2183d93 --- /dev/null +++ b/tests/ui/parser/forced-keywords/non-keyword-neg.stderr @@ -0,0 +1,14 @@ +error: expected expression, found `k#not_a_keyword` + --> $DIR/non-keyword-neg.rs:8:5 + | +LL | k#not_a_keyword() + | ^^^^^^^^^^^^^^^ expected expression + +error: expected identifier, found `k#trying_to_pass_as_a_normal_ident` + --> $DIR/non-keyword-neg.rs:11:4 + | +LL | fn k#trying_to_pass_as_a_normal_ident() {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected identifier + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/forced-keywords/non-keyword-pos.rs b/tests/ui/parser/forced-keywords/non-keyword-pos.rs new file mode 100644 index 0000000000000..84d472bcb5d68 --- /dev/null +++ b/tests/ui/parser/forced-keywords/non-keyword-pos.rs @@ -0,0 +1,14 @@ +// Ensure that you are allowed to force *any* identifier to be treated as a keyword. +// +//@ edition: 2021.. +//@ check-pass +#![feature(forced_keywords)] + +macro_rules! discard { ($($tt:tt)*) => {} } + +discard!(k#not_a_keyword); // OK + +#[cfg(false)] +invoke!(k#arbitrary_string_of_chars); + +fn main() {} diff --git a/tests/ui/parser/forced-keywords/pre-2021-edition-fail.rs b/tests/ui/parser/forced-keywords/pre-2021-edition-fail.rs new file mode 100644 index 0000000000000..77d2712802548 --- /dev/null +++ b/tests/ui/parser/forced-keywords/pre-2021-edition-fail.rs @@ -0,0 +1,3 @@ +//@ edition: 2015..2021 + +k#fn main() {} //~ ERROR expected one of `!` or `::`, found `#` diff --git a/tests/ui/parser/forced-keywords/pre-2021-edition-fail.stderr b/tests/ui/parser/forced-keywords/pre-2021-edition-fail.stderr new file mode 100644 index 0000000000000..fefc3cafd2242 --- /dev/null +++ b/tests/ui/parser/forced-keywords/pre-2021-edition-fail.stderr @@ -0,0 +1,8 @@ +error: expected one of `!` or `::`, found `#` + --> $DIR/pre-2021-edition-fail.rs:3:2 + | +LL | k#fn main() {} + | ^ expected one of `!` or `::` + +error: aborting due to 1 previous error + diff --git a/tests/ui/parser/forced-keywords/pre-2021-edition-pass.rs b/tests/ui/parser/forced-keywords/pre-2021-edition-pass.rs new file mode 100644 index 0000000000000..63cf647a5c4c1 --- /dev/null +++ b/tests/ui/parser/forced-keywords/pre-2021-edition-pass.rs @@ -0,0 +1,14 @@ +//@ edition: 2015..2021 +//@ check-pass + +#![warn(rust_2021_prefixes_incompatible_syntax)] + +macro_rules! ensure { + ($tag:ident # $name:ident) => {}; +} + +ensure! { k#fn } +//~^ WARNING parsed as a forced keyword in Rust 2021 and onward +//~| WARNING this changes meaning in Rust 2021 + +fn main() {} diff --git a/tests/ui/parser/forced-keywords/pre-2021-edition-pass.stderr b/tests/ui/parser/forced-keywords/pre-2021-edition-pass.stderr new file mode 100644 index 0000000000000..f033a56ad49ae --- /dev/null +++ b/tests/ui/parser/forced-keywords/pre-2021-edition-pass.stderr @@ -0,0 +1,20 @@ +warning: this is parsed as a forced keyword in Rust 2021 and onward + --> $DIR/pre-2021-edition-pass.rs:10:11 + | +LL | ensure! { k#fn } + | ^^^^ + | + = warning: this changes meaning in Rust 2021 + = note: for more information, see +note: the lint level is defined here + --> $DIR/pre-2021-edition-pass.rs:4:9 + | +LL | #![warn(rust_2021_prefixes_incompatible_syntax)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +help: consider inserting whitespace here to avoid this + | +LL | ensure! { k #fn } + | + + +warning: 1 warning emitted + From 7c10734455ee9fd1cb197f3986687d37f0ef609f Mon Sep 17 00:00:00 2001 From: malezjaa Date: Wed, 16 Sep 2026 00:20:01 +0200 Subject: [PATCH 0927/1309] regression test for inherent associated const ICE --- .../ice-normalize-inherent-assoc-const.rs | 19 +++++++++++++++++++ .../ice-normalize-inherent-assoc-const.stderr | 15 +++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs create mode 100644 tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.stderr diff --git a/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs new file mode 100644 index 0000000000000..843e33bae0d81 --- /dev/null +++ b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs @@ -0,0 +1,19 @@ +//! Regression test for: https://github.com/rust-lang/rust/issues/142722. + +#![feature(trivial_bounds)] +#![feature(generic_const_exprs)] +#![feature(min_generic_const_args)] +#![feature(inherent_associated_types)] + +struct Foo; +impl Foo { + const ASSOC_C: usize = todo!(); + //~^ ERROR evaluation panicked: not yet implemented + fn foo() + where + [u8; Self::ASSOC_C]:, + { + } +} + +pub fn main() {} diff --git a/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.stderr b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.stderr new file mode 100644 index 0000000000000..5ce8a67bc7810 --- /dev/null +++ b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.stderr @@ -0,0 +1,15 @@ +error[E0080]: evaluation panicked: not yet implemented + --> $DIR/ice-normalize-inherent-assoc-const.rs:10:28 + | +LL | const ASSOC_C: usize = todo!(); + | ^^^^^^^ evaluation of `Foo::ASSOC_C` failed here + +note: erroneous constant encountered + --> $DIR/ice-normalize-inherent-assoc-const.rs:14:14 + | +LL | [u8; Self::ASSOC_C]:, + | ^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0080`. From 01594298297ece4e1f671722da02ed8c0e445eef Mon Sep 17 00:00:00 2001 From: malezjaa Date: Mon, 28 Sep 2026 00:03:56 +0200 Subject: [PATCH 0928/1309] update feature name --- .../ice-normalize-inherent-assoc-const.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs index 843e33bae0d81..a7b430f85a9a2 100644 --- a/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs +++ b/tests/ui/associated-inherent-types/ice-normalize-inherent-assoc-const.rs @@ -2,7 +2,7 @@ #![feature(trivial_bounds)] #![feature(generic_const_exprs)] -#![feature(min_generic_const_args)] +#![feature(gca_min_const_items)] #![feature(inherent_associated_types)] struct Foo; From 9dfa37154228fcc8ca0bb832d82b4ed363a34f01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 23:36:17 +0000 Subject: [PATCH 0929/1309] Tweak "expected/found" indentation for runtime symbols ``` error: invalid definition of the runtime `open` symbol used by the standard library --> $DIR/runtime-symbols-unix.rs:14:5 | LL | pub fn open() {} | ^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8, i32, ...) -> i32` (for the current target) found `fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "open")]`, or `#[link_name = "open"]` = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default ``` --- compiler/rustc_lint/src/diagnostics.rs | 6 ++-- .../rustc_macros/src/diagnostics/message.rs | 3 ++ tests/ui/lint/runtime-symbols-unix.stderr | 28 +++++++++---------- tests/ui/lint/runtime-symbols.stderr | 26 ++++++++--------- 4 files changed, 32 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 98a11f8e1df08..a5256db57eaa7 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -944,8 +944,7 @@ pub(crate) enum RedefiningRuntimeSymbolsDiag<'tcx> { "invalid definition of the runtime `{$symbol_name}` symbol used by the standard library" )] #[note( - "expected `{$expected_fn_sig}` (for the current target) - found `{$found_fn_sig}`" + "expected `{$expected_fn_sig}` (for the current target)\n{\" \"}found `{$found_fn_sig}`" )] #[help( "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" @@ -955,8 +954,7 @@ pub(crate) enum RedefiningRuntimeSymbolsDiag<'tcx> { "suspicious definition of the runtime `{$symbol_name}` symbol used by the standard library" )] #[note( - "expected `{$expected_fn_sig}` (for the current target) - found `{$found_fn_sig}`" + "expected `{$expected_fn_sig}` (for the current target)\n{\" \"}found `{$found_fn_sig}`" )] #[help( "either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = \"{$symbol_name}\")]`, or `#[link_name = \"{$symbol_name}\"]`" diff --git a/compiler/rustc_macros/src/diagnostics/message.rs b/compiler/rustc_macros/src/diagnostics/message.rs index 8eff9a4fa9e8a..404404bbc1cd0 100644 --- a/compiler/rustc_macros/src/diagnostics/message.rs +++ b/compiler/rustc_macros/src/diagnostics/message.rs @@ -173,6 +173,9 @@ fn verify_message_formatting(attr_span: Span, msg_span: Span, message: &str) { if line.is_empty() { continue; } + if line.trim().starts_with("{") && line.contains(&"found ") { + continue; + } let indent = line.chars().take_while(|c| *c == ' ').count(); if indent < start { span_err( diff --git a/tests/ui/lint/runtime-symbols-unix.stderr b/tests/ui/lint/runtime-symbols-unix.stderr index a1d036b95683c..18a6f34fa11cb 100644 --- a/tests/ui/lint/runtime-symbols-unix.stderr +++ b/tests/ui/lint/runtime-symbols-unix.stderr @@ -5,7 +5,7 @@ LL | pub fn open() {} | ^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8, i32, ...) -> i32` (for the current target) - found `fn()` + found `fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "open")]`, or `#[link_name = "open"]` = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default @@ -16,7 +16,7 @@ LL | pub fn read(); | ^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32, *mut c_void, usize) -> isize` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "read")]`, or `#[link_name = "read"]` error: invalid definition of the runtime `write` symbol used by the standard library @@ -26,7 +26,7 @@ LL | pub fn write(); | ^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32, *const c_void, usize) -> isize` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "write")]`, or `#[link_name = "write"]` error: invalid definition of the runtime `close` symbol used by the standard library @@ -36,7 +36,7 @@ LL | pub static close: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> i32` (for the current target) - found `()` + found `()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "close")]`, or `#[link_name = "close"]` error: invalid definition of the runtime `malloc` symbol used by the standard library @@ -46,7 +46,7 @@ LL | pub fn malloc(); | ^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(usize) -> *mut c_void` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "malloc")]`, or `#[link_name = "malloc"]` error: invalid definition of the runtime `realloc` symbol used by the standard library @@ -56,7 +56,7 @@ LL | pub fn realloc(); | ^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, usize) -> *mut c_void` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "realloc")]`, or `#[link_name = "realloc"]` error: invalid definition of the runtime `free` symbol used by the standard library @@ -66,7 +66,7 @@ LL | pub fn free(); | ^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void)` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "free")]`, or `#[link_name = "free"]` error: invalid definition of the runtime `exit` symbol used by the standard library @@ -76,7 +76,7 @@ LL | pub fn exit(); | ^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> !` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` warning: suspicious definition of the runtime `open` symbol used by the standard library @@ -86,7 +86,7 @@ LL | pub fn open(path: *const U8, oflag: usize, ...) -> c_int; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8, i32, ...) -> i32` (for the current target) - found `unsafe extern "C" fn(*const U8, usize, ...) -> i32` + found `unsafe extern "C" fn(*const U8, usize, ...) -> i32` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "open")]`, or `#[link_name = "open"]` = help: allow this lint if the signature is compatible = note: `#[warn(suspicious_runtime_symbol_definitions)]` on by default @@ -98,7 +98,7 @@ LL | pub fn free(ptr: *const U8); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void)` (for the current target) - found `unsafe extern "C" fn(*const U8)` + found `unsafe extern "C" fn(*const U8)` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "free")]`, or `#[link_name = "free"]` = help: allow this lint if the signature is compatible @@ -109,7 +109,7 @@ LL | pub fn exit(code: f32) -> !; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> !` (for the current target) - found `unsafe extern "C" fn(f32) -> !` + found `unsafe extern "C" fn(f32) -> !` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` = help: allow this lint if the signature is compatible @@ -120,7 +120,7 @@ LL | pub static exit2: Option !>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> !` (for the current target) - found `unsafe extern "C" fn(f32) -> !` + found `unsafe extern "C" fn(f32) -> !` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` = help: allow this lint if the signature is compatible @@ -131,7 +131,7 @@ LL | pub fn exit3(code: i32) -> i32; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> !` (for the current target) - found `unsafe extern "C" fn(i32) -> i32` + found `unsafe extern "C" fn(i32) -> i32` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` = help: allow this lint if the signature is compatible @@ -142,7 +142,7 @@ LL | pub fn exit4(code: i32); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(i32) -> !` (for the current target) - found `unsafe extern "C" fn(i32)` + found `unsafe extern "C" fn(i32)` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "exit")]`, or `#[link_name = "exit"]` = help: allow this lint if the signature is compatible diff --git a/tests/ui/lint/runtime-symbols.stderr b/tests/ui/lint/runtime-symbols.stderr index 0de419a684ba2..2ba5f6723797b 100644 --- a/tests/ui/lint/runtime-symbols.stderr +++ b/tests/ui/lint/runtime-symbols.stderr @@ -5,7 +5,7 @@ LL | pub fn memmove() {} | ^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void` (for the current target) - found `fn()` + found `fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memmove")]`, or `#[link_name = "memmove"]` = note: `#[deny(invalid_runtime_symbol_definitions)]` on by default @@ -16,7 +16,7 @@ LL | pub fn memset(); | ^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, i32, usize) -> *mut c_void` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memset")]`, or `#[link_name = "memset"]` error: invalid definition of the runtime `memcmp` symbol used by the standard library @@ -26,7 +26,7 @@ LL | pub fn memcmp(); | ^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32` (for the current target) - found `unsafe extern "C" fn()` + found `unsafe extern "C" fn()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcmp")]`, or `#[link_name = "memcmp"]` error: invalid definition of the runtime `strlen` symbol used by the standard library @@ -36,7 +36,7 @@ LL | pub static strlen: () = (); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8) -> usize` (for the current target) - found `()` + found `()` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]` error: invalid definition of the runtime `strlen` symbol used by the standard library @@ -46,7 +46,7 @@ LL | static strlen2: Option; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8) -> usize` (for the current target) - found `unsafe extern "C" fn(*const U8)` + found `unsafe extern "C" fn(*const U8)` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]` error: invalid definition of the runtime `memcpy` symbol used by the standard library @@ -56,7 +56,7 @@ LL | pub fn memcpy(dest: *mut c_void, src: *const c_void, n: usize) -> *mut | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void` (for the current target) - found `fn(*mut c_void, *const c_void, usize) -> *mut c_void` + found `fn(*mut c_void, *const c_void, usize) -> *mut c_void` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcpy")]`, or `#[link_name = "memcpy"]` error: invalid definition of the runtime `bcmp` symbol used by the standard library @@ -66,7 +66,7 @@ LL | pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32` (for the current target) - found `unsafe extern "C" fn(*const c_void, *const c_void, usize, ...) -> i32` + found `unsafe extern "C" fn(*const c_void, *const c_void, usize, ...) -> i32` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]` error: invalid definition of the runtime `bcmp` symbol used by the standard library @@ -76,7 +76,7 @@ LL | pub extern "C" fn bcmp_(s1: *const c_void, s2: *const c_void, n: usize) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32` (for the current target) - found `extern "C" fn(*const c_void, *const c_void, usize)` + found `extern "C" fn(*const c_void, *const c_void, usize)` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]` warning: suspicious definition of the runtime `memcpy` symbol used by the standard library @@ -86,7 +86,7 @@ LL | pub extern "C" fn memcpy(dest: *mut c_void, src: *const c_void, n: i64) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void` (for the current target) - found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void` + found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memcpy")]`, or `#[link_name = "memcpy"]` = help: allow this lint if the signature is compatible = note: `#[warn(suspicious_runtime_symbol_definitions)]` on by default @@ -98,7 +98,7 @@ LL | pub extern "C" fn memmove(dest: *mut c_void, src: *const c_void, n: i64 | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, *const c_void, usize) -> *mut c_void` (for the current target) - found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void` + found `extern "C" fn(*mut c_void, *const c_void, i64) -> *mut c_void` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memmove")]`, or `#[link_name = "memmove"]` = help: allow this lint if the signature is compatible @@ -109,7 +109,7 @@ LL | fn memset(s: *mut c_void, c: c_int, n: usize) -> f64; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*mut c_void, i32, usize) -> *mut c_void` (for the current target) - found `unsafe extern "C" fn(*mut c_void, i32, usize) -> f64` + found `unsafe extern "C" fn(*mut c_void, i32, usize) -> f64` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "memset")]`, or `#[link_name = "memset"]` = help: allow this lint if the signature is compatible @@ -120,7 +120,7 @@ LL | pub extern "C" fn bcmp_(s1: *const U8, s2: *const U8, n: usize) -> c_in | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const c_void, *const c_void, usize) -> i32` (for the current target) - found `extern "C" fn(*const U8, *const U8, usize) -> i32` + found `extern "C" fn(*const U8, *const U8, usize) -> i32` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "bcmp")]`, or `#[link_name = "bcmp"]` = help: allow this lint if the signature is compatible @@ -131,7 +131,7 @@ LL | pub extern "C" fn strlen(s: *const u64) -> usize { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: expected `unsafe extern "C" fn(*const U8) -> usize` (for the current target) - found `extern "C" fn(*const u64) -> usize` + found `extern "C" fn(*const u64) -> usize` = help: either fix the signature or remove any attributes like `#[unsafe(no_mangle)]`, `#[unsafe(export_name = "strlen")]`, or `#[link_name = "strlen"]` = help: allow this lint if the signature is compatible From 54e09fa7055add9864144576412017d1560d4413 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 18 Sep 2026 09:42:04 +0800 Subject: [PATCH 0930/1309] skip registering type outlives when non region infers exist --- .../eval_ctxt/solver_region_constraints.rs | 4 +++- .../rustc_next_trait_solver/src/solve/mod.rs | 21 +++++++++++-------- 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 10dd8585b09c4..5724834abf03c 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -164,7 +164,9 @@ where Or::new_leaf(PlaceholderTyOutlives(Ty::new_placeholder(self.cx(), *p), r, ())) } Alias(_, alias) => self.destructure_alias_outlives(*alias, r), - UnresolvedInferenceVariable(_) => Or::new_ambig(()), + UnresolvedInferenceVariable(_) => { + panic!("Shouldn't destructure type outlives when ty vars exist") + } Param(_) => panic!("Params should have been canonicalized to placeholders"), EscapingAlias(components) => self.destructure_components(components, r), } diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 1d7d2dd75c316..dddc78373b1b5 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -92,15 +92,6 @@ where let ty::OutlivesClause(ty, lt) = goal.predicate; let ty = self.normalize(GoalSource::Misc, goal.param_env, ty::Unnormalized::new_wip(ty))?; - if self.cx().assumptions_on_binders() { - use rustc_type_ir::region_constraint::RegionConstraint; - - let constraint = self.destructure_type_outlives(ty, lt); - self.register_solver_region_constraint(RegionConstraint::new_from_or(constraint)); - } else { - self.register_ty_outlives(ty, lt); - } - // The normalized type can still contain non-rigid higher ranked aliases if their // normalization ends up with ambiguity. Or we have non-rigid aliases inside rigid ones. // Infer vars may be resolved to types/consts containing non-rigid aliases later. @@ -109,6 +100,18 @@ where if ty.has_non_region_infer() || ty.has_non_rigid_aliases() { self.evaluate_added_goals_and_make_canonical_response(Certainty::AMBIGUOUS) } else { + // We drop region constraints in ambiguous response so there's no need to add them in + // the ambiguous branch. Also this guarantees we don't have ty vars when destructuring + // type outlives. + if self.cx().assumptions_on_binders() { + use rustc_type_ir::region_constraint::RegionConstraint; + + let constraint = self.destructure_type_outlives(ty, lt); + self.register_solver_region_constraint(RegionConstraint::new_from_or(constraint)); + } else { + self.register_ty_outlives(ty, lt); + } + self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) } } From 7809ec46cfd6927530cdf1da1e0c4515dd437ee5 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 18 Sep 2026 10:23:32 +0800 Subject: [PATCH 0931/1309] remove `None` assumptions --- .../rustc_hir_analysis/src/check/wfcheck.rs | 2 +- compiler/rustc_infer/src/infer/context.rs | 6 ++-- compiler/rustc_infer/src/infer/mod.rs | 33 ++++++++----------- .../src/canonical/mod.rs | 2 +- .../src/placeholder.rs | 2 +- .../src/solve/eval_ctxt/mod.rs | 16 ++++++--- compiler/rustc_type_ir/src/infer_ctxt.rs | 4 +-- .../rustc_type_ir/src/region_constraint.rs | 33 ++++--------------- 8 files changed, 39 insertions(+), 59 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/check/wfcheck.rs b/compiler/rustc_hir_analysis/src/check/wfcheck.rs index 0a1787a23c893..4e1bb89b18e6a 100644 --- a/compiler/rustc_hir_analysis/src/check/wfcheck.rs +++ b/compiler/rustc_hir_analysis/src/check/wfcheck.rs @@ -2433,7 +2433,7 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> { body.type_outlives, builder.freeze(), ); - self.infcx.insert_placeholder_assumptions(u, Some(assumptions)); + self.infcx.insert_placeholder_assumptions(u, assumptions); self.check_test_binder_body(body.value); let solver_region_constraint = self.infcx.get_solver_region_constraint(); let constraint = ty::region_constraint::eagerly_handle_placeholders_in_universe( diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 4d90e60736995..97f305f0699ca 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -49,7 +49,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn insert_placeholder_assumptions( &self, u: ty::UniverseIndex, - assumptions: Option>>, + assumptions: rustc_type_ir::region_constraint::Assumptions>, ) { self.insert_placeholder_assumptions(u, assumptions); } @@ -57,7 +57,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { fn get_placeholder_assumptions( &self, u: ty::UniverseIndex, - ) -> Option>> { + ) -> rustc_type_ir::region_constraint::Assumptions> { self.get_placeholder_assumptions(u) } @@ -189,7 +189,7 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { let u = self.universe(); self.placeholder_assumptions_for_next_solver .borrow_mut() - .insert(u, Some(rustc_type_ir::region_constraint::Assumptions::empty())); + .insert(u, rustc_type_ir::region_constraint::Assumptions::empty()); f(value) }) } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 267c36652656d..42c41164f7ad2 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -335,10 +335,7 @@ pub struct InferCtxt<'tcx> { // FIXME(-Zassumptions-on-binders): This and `universe` should probably be // in `InferCtxtInner` so they can participate in rollbacks and whatnot placeholder_assumptions_for_next_solver: RefCell< - FxIndexMap< - ty::UniverseIndex, - Option>>, - >, + FxIndexMap>>, >, next_trait_solver: bool, @@ -1579,28 +1576,26 @@ impl<'tcx> InferCtxt<'tcx> { pub fn insert_placeholder_assumptions( &self, u: ty::UniverseIndex, - assumptions: Option>>, + assumptions: rustc_type_ir::region_constraint::Assumptions>, ) { - if let Some(assumptions) = &assumptions { - assert!( - !assumptions.type_outlives.has_escaping_bound_vars(), - "assumptions has escaping bound vars, which is indicative of a bug in how assumptions are handled: {:?}", - assumptions.type_outlives - ); - assert!( - assumptions.region_outlives.base_edges().all(|r| !r.has_escaping_bound_vars()), - "assumptions has escaping bound vars, which is indicative of a bug in how assumptions are handled: {:?}", - assumptions.region_outlives - ); - } + assert!( + !assumptions.type_outlives.has_escaping_bound_vars(), + "assumptions has escaping bound vars, which is indicative of a bug in how assumptions are handled: {:?}", + assumptions.type_outlives + ); + assert!( + assumptions.region_outlives.base_edges().all(|r| !r.has_escaping_bound_vars()), + "assumptions has escaping bound vars, which is indicative of a bug in how assumptions are handled: {:?}", + assumptions.region_outlives + ); self.placeholder_assumptions_for_next_solver.borrow_mut().insert(u, assumptions); } pub fn get_placeholder_assumptions( &self, u: ty::UniverseIndex, - ) -> Option>> { - self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().as_ref().cloned() + ) -> rustc_type_ir::region_constraint::Assumptions> { + self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().clone() } pub fn get_solver_region_constraint(&self) -> SolverRegionConstraint<'tcx> { diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index 45ae4cadf519c..655ab64145db5 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -173,7 +173,7 @@ where // recreated universes here. delegate.insert_placeholder_assumptions( new_universe, - Some(rustc_type_ir::region_constraint::Assumptions::empty()), + rustc_type_ir::region_constraint::Assumptions::empty(), ); } } diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index c96aa90a10792..fdf702248196a 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -75,7 +75,7 @@ where // context to compute placeholder assumptions for the binders it enters. infcx.insert_placeholder_assumptions( *new, - Some(rustc_type_ir::region_constraint::Assumptions::empty()), + rustc_type_ir::region_constraint::Assumptions::empty(), ); } } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 7397d43a48a00..58b3b1fdc49cb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1293,12 +1293,18 @@ where ) -> U { self.delegate.enter_forall_without_assumptions(value, |value| { let u = self.delegate.universe(); - let assumptions = if self.cx().assumptions_on_binders() { - self.region_assumptions_for_placeholders_in_universe(value.clone(), u, param_env) - } else { - None + if self.cx().assumptions_on_binders() { + if let Some(assumptions) = self.region_assumptions_for_placeholders_in_universe( + value.clone(), + u, + param_env, + ) { + self.delegate.insert_placeholder_assumptions(u, assumptions); + } else { + todo!("shoudl retun ambiguity") + } }; - self.delegate.insert_placeholder_assumptions(u, assumptions); + f(self, value) }) } diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 22ebedd9f7e3c..706d6229a840d 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -407,12 +407,12 @@ pub trait InferCtxtLike: Sized { fn insert_placeholder_assumptions( &self, u: ty::UniverseIndex, - assumptions: Option>, + assumptions: crate::region_constraint::Assumptions, ); fn get_placeholder_assumptions( &self, u: ty::UniverseIndex, - ) -> Option>; + ) -> crate::region_constraint::Assumptions; fn get_solver_region_constraint( &self, ) -> crate::region_constraint::RegionConstraint; diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index e13ecb5e9575e..0becd7a68ef2f 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -715,7 +715,7 @@ fn pull_region_outlives_constraints_out_of_universe< infcx: &Infcx, constraint: RegionConstraint, u: UniverseIndex, - assumptions: &Option>, + assumptions: &Assumptions, ) -> RegionConstraint { assert!(max_universe(infcx, constraint.clone()) <= u); @@ -745,14 +745,6 @@ fn pull_region_outlives_constraints_out_of_universe< continue; } - let assumptions = match assumptions { - Some(assumptions) => assumptions, - None => { - pulled_constraints.push(Or::new_ambig(())); - continue; - } - }; - // The constraint may already be entailed by the assumptions of the binder we are // leaving, e.g. `for<'a, 'b> where 'b: 'a { 'b: 'a }`. There is nothing to lift into // a smaller universe in that case, and looking for lower universe candidates would @@ -875,7 +867,7 @@ fn rewrite_type_outlives_constraints_in_universe_for_eager_placeholder_handling< infcx: &Infcx, constraint: RegionConstraint, u: UniverseIndex, - assumptions: &Option>, + assumptions: &Assumptions, ) -> RegionConstraint { use LeafRegionConstraint::*; @@ -920,7 +912,7 @@ fn rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder ty: I::Ty, region: Region, u: UniverseIndex, - assumptions: &Option>, + assumptions: &Assumptions, ) -> Or { use LeafRegionConstraint::*; @@ -931,11 +923,6 @@ fn rewrite_placeholder_ty_outlives_constraints_in_universe_for_eager_placeholder return Or::new_leaf(PlaceholderTyOutlives(ty, region, ())); } - let assumptions = match assumptions { - Some(assumptions) => assumptions, - None => return Or::new_ambig(()), - }; - let mut candidates = vec![]; // There could be `!T: 'region` assumptions in the env even if `!T` is in a @@ -966,7 +953,7 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl infcx: &Infcx, bound_outlives: Binder, Region)>, u: UniverseIndex, - assumptions: &Option>, + assumptions: &Assumptions, ) -> Or { use LeafRegionConstraint::*; @@ -1016,14 +1003,6 @@ fn rewrite_alias_ty_outlives_constraints_in_universe_for_eager_placeholder_handl } } - let assumptions = match assumptions { - Some(assumptions) => assumptions, - None => { - candidates.push(Or::new_ambig(())); - return candidates.into_iter().fold(Or::new_false(), |acc, c| Or::build_or(acc, c)); - } - }; - // Actually look at the assumptions and matching our higher ranked alias outlives goal // against potentially higher ranked type outlives assumptions. candidates.push(alias_outlives_candidates_from_assumptions(infcx, bound_outlives, assumptions)); @@ -1274,14 +1253,14 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeRelation { self.infcx.enter_forall_with_empty_assumptions(a, |a| { let u = self.infcx.universe(); - self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); + self.infcx.insert_placeholder_assumptions(u, Assumptions::empty()); let b = self.infcx.instantiate_binder_with_infer(b); self.relate(a, b) })?; self.infcx.enter_forall_with_empty_assumptions(b, |b| { let u = self.infcx.universe(); - self.infcx.insert_placeholder_assumptions(u, Some(Assumptions::empty())); + self.infcx.insert_placeholder_assumptions(u, Assumptions::empty()); let a = self.infcx.instantiate_binder_with_infer(a); self.relate(a, b) })?; From d1f102f5a65d4a3fecf2bd0533afecffa6189e42 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 18 Sep 2026 12:00:13 +0800 Subject: [PATCH 0932/1309] force ambiguity when no assumptions --- compiler/rustc_infer/src/infer/context.rs | 6 ++++++ compiler/rustc_infer/src/infer/mod.rs | 9 ++++++++ .../src/solve/eval_ctxt/mod.rs | 16 +++++++------- .../eval_ctxt/solver_region_constraints.rs | 21 ++++++++++++++----- compiler/rustc_type_ir/src/infer_ctxt.rs | 2 ++ 5 files changed, 41 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_infer/src/infer/context.rs b/compiler/rustc_infer/src/infer/context.rs index 97f305f0699ca..38dab6ec4875d 100644 --- a/compiler/rustc_infer/src/infer/context.rs +++ b/compiler/rustc_infer/src/infer/context.rs @@ -1,4 +1,6 @@ //! Definition of `InferCtxtLike` from the librarified type layer. +use std::range::RangeInclusive; + use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::traits::ObligationCause; @@ -67,6 +69,10 @@ impl<'tcx> rustc_type_ir::InferCtxtLike for InferCtxt<'tcx> { self.get_solver_region_constraint().without_spans() } + fn has_placeholder_assumptions(&self, range: RangeInclusive) -> bool { + self.has_placeholder_assumptions(range) + } + fn overwrite_solver_region_constraint( &self, constraint: rustc_type_ir::region_constraint::RegionConstraint>, diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index 42c41164f7ad2..e02cc9a7acd1f 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -1,5 +1,6 @@ use std::cell::{Cell, RefCell}; use std::fmt; +use std::range::RangeInclusive; pub use at::DefineOpaqueTypes; use free_regions::RegionRelations; @@ -1598,6 +1599,14 @@ impl<'tcx> InferCtxt<'tcx> { self.placeholder_assumptions_for_next_solver.borrow().get(&u).unwrap().clone() } + pub fn has_placeholder_assumptions(&self, range: RangeInclusive) -> bool { + let assumptions = self.placeholder_assumptions_for_next_solver.borrow(); + // Walk around that `Step` trait is nightly only. + (range.start.index()..=range.last.index()) + .map(ty::UniverseIndex::from_usize) + .all(|u| assumptions.get(&u).is_some()) + } + pub fn get_solver_region_constraint(&self) -> SolverRegionConstraint<'tcx> { self.inner.borrow().solver_region_constraint_storage.get_constraint() } diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 58b3b1fdc49cb..8fc2a81ee4f52 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -1292,18 +1292,18 @@ where f: impl FnOnce(&mut Self, T) -> U, ) -> U { self.delegate.enter_forall_without_assumptions(value, |value| { + // Invariant: we shouldn't insert empty assumptions if assumptions computation fails. + // When handling placeholder constraints, we rely on vacancies to force ambiguity. let u = self.delegate.universe(); - if self.cx().assumptions_on_binders() { - if let Some(assumptions) = self.region_assumptions_for_placeholders_in_universe( + if self.cx().assumptions_on_binders() + && let Some(assumptions) = self.region_assumptions_for_placeholders_in_universe( value.clone(), u, param_env, - ) { - self.delegate.insert_placeholder_assumptions(u, assumptions); - } else { - todo!("shoudl retun ambiguity") - } - }; + ) + { + self.delegate.insert_placeholder_assumptions(u, assumptions); + } f(self, value) }) diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 5724834abf03c..d06675c25f904 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -115,12 +115,23 @@ where pub(super) fn eagerly_handle_placeholders(&mut self) -> Result { let constraint = self.delegate.get_solver_region_constraint(); - let smallest_universe = self.max_input_universe.index(); - let largest_universe = self.delegate.universe().index(); - debug!(?smallest_universe, largest_universe); + let smallest_universe = self.max_input_universe; + let largest_universe = self.delegate.universe(); + debug!("smallest_universe={smallest_universe:#?}, largest_universe={largest_universe:#?}"); + + // We rely on placeholder assumptions to evaluate region constraints with placeholders. + // But we can fail to compute assumptions due to unresolved type variables. In that case, + // we conservatively bail with ambiguity. + if !self + .delegate + .has_placeholder_assumptions(((smallest_universe + 1)..=largest_universe).into()) + { + return Ok(Certainty::AMBIGUOUS); + } - let constraint = ((smallest_universe + 1)..=largest_universe) - .map(|u| UniverseIndex::from_usize(u)) + // Walk around that `Step` trait is nightly only. + let constraint = ((smallest_universe.index() + 1)..=largest_universe.index()) + .map(UniverseIndex::from_usize) .rev() .fold(constraint, |constraint, u| { eagerly_handle_placeholders_in_universe(&**self.delegate, constraint, u) diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index 706d6229a840d..d50f6521441d5 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -1,5 +1,6 @@ use core::fmt; use std::hash::{Hash, Hasher}; +use std::range::RangeInclusive; use derive_where::derive_where; #[cfg(feature = "nightly")] @@ -413,6 +414,7 @@ pub trait InferCtxtLike: Sized { &self, u: ty::UniverseIndex, ) -> crate::region_constraint::Assumptions; + fn has_placeholder_assumptions(&self, range: RangeInclusive) -> bool; fn get_solver_region_constraint( &self, ) -> crate::region_constraint::RegionConstraint; From c9016225be3d651a527d2d86e75834d38615d7e0 Mon Sep 17 00:00:00 2001 From: Adwin White Date: Fri, 18 Sep 2026 12:46:51 +0800 Subject: [PATCH 0933/1309] yeet `propagate_ambiguity` --- .../src/infer/outlives/obligations.rs | 2 - .../src/solve/eval_ctxt/mod.rs | 6 +-- .../eval_ctxt/solver_region_constraints.rs | 2 - .../rustc_type_ir/src/region_constraint.rs | 47 +------------------ 4 files changed, 2 insertions(+), 55 deletions(-) diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs index 14f534a3e7eb0..4b833da8eeb59 100644 --- a/compiler/rustc_infer/src/infer/outlives/obligations.rs +++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs @@ -287,8 +287,6 @@ impl<'tcx> InferCtxt<'tcx> { &assumptions, ); debug!(?constraint); - let constraint = region_constraint::propagate_ambiguity(constraint); - debug!(?constraint); // FIXME(-Zassumptions-on-binders): actually implement OR as an OR for c in constraint.and_constraint.0.into_iter().chain( diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 8fc2a81ee4f52..4d74cbc339be3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -5,7 +5,7 @@ use std::ops::ControlFlow; use rustc_macros::StableHash; use rustc_type_ir::data_structures::HashSet; use rustc_type_ir::inherent::*; -use rustc_type_ir::region_constraint::{self, RegionConstraint}; +use rustc_type_ir::region_constraint::RegionConstraint; use rustc_type_ir::relate::Relate; use rustc_type_ir::relate::solver_relating::RelateExt; use rustc_type_ir::search_graph::{ @@ -1678,10 +1678,6 @@ where let region_constraints = if self.cx().assumptions_on_binders() { ExternalRegionConstraints::NextGen(if let Certainty::Yes = certainty { let constraint = self.delegate.get_solver_region_constraint(); - debug_assert_eq!( - constraint, - region_constraint::propagate_ambiguity(constraint.clone()) - ); constraint } else { RegionConstraint::new_true() diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index d06675c25f904..8a4d3fba99a39 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -8,7 +8,6 @@ use rustc_type_ir::outlives::{Component, push_outlives_components}; use rustc_type_ir::region_constraint::TransitiveRelationBuilder; use rustc_type_ir::region_constraint::{ And, Assumptions, LeafRegionConstraint, Or, eagerly_handle_placeholders_in_universe, - propagate_ambiguity, }; use rustc_type_ir::{ AliasTy, Binder, ClauseKind, Const, InferCtxtLike, Interner, Region, TypeVisitable, @@ -136,7 +135,6 @@ where .fold(constraint, |constraint, u| { eagerly_handle_placeholders_in_universe(&**self.delegate, constraint, u) }); - let constraint = propagate_ambiguity(constraint); debug!("final constraint={:?}", constraint); self.delegate.overwrite_solver_region_constraint(constraint.clone(), self.origin_span); diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 0becd7a68ef2f..e1b1d157ff85f 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -558,8 +558,7 @@ pub fn eagerly_handle_placeholders_in_universe, I: Interne ) } -/// Force the whole constraint to be ambiguous if it contains ambiguities which could -/// have caused the constraint to be `false` if they had been `false` themselves. -/// -/// For example if we have `'a: 'b AND ambig` it's possible that if we had more inference -/// information we could have produced a better region constraint than `ambig`, and that -/// constraint may then have gone on to be false, at which point we would have `'a: 'b AND false` -/// causing the whole constraint to be `false`. -/// -/// If we're not careful we can wind up returning `'a: 'b AND ambig` from passing trait solver -/// goals and then upon rerunning wind up returning `NoSolution` which would be dubious :3 -/// -/// This is inherently conservative and this method should be called as little as possible as it -/// can cause us to get ambiguities instead of `NoSolution` (for example if `'a: 'b` is `false`), -/// which can affect coherence, candidate selection, etc. -/// -/// FIXME(-Zassumptions-on-binders): this method should probably be trait-solver internal as it only -/// matters at trait solver query boundaries. We currently call it in more than just that location -#[instrument(level = "debug", ret)] -pub fn propagate_ambiguity( - constraint: RegionConstraint, -) -> RegionConstraint { - if let Some(ambig) = constraint.and_constraint.0.iter().find(|c| c.is_ambig()) { - return RegionConstraint::new_leaf(ambig.clone()); - } - - for and in constraint.or_constraint.0.iter() { - // FIXME(-Zassumptions-on-binders): This is overly conservative. If we have: - // `'a: 'b OR ambig` we don't necessarily want to propagate ambiguity here - // as we might end up with `'a: 'b` being satisfied in which case we unnecessarily - // errored here. - // - // It's fine if the `ambig` wound up being `false` as that wouldn't cause a goal to - // become `NoSolution`, it would instead result in us returning the `'a: 'b` constraint - // by itself. - // - // `rust-lang/project-assumptions-on-binders#21` - if let Some(ambig) = and.0.iter().find(|c| c.is_ambig()) { - return RegionConstraint::new_leaf(ambig.clone()); - } - } - - constraint -} - /// Handles converting region outlives constraints involving placeholders from `u` into OR constraints /// involving regions from smaller universes with known relationships to the placeholder. For example: /// ```ignore (not rust) From 742e775b72a5180317ff28efd58d7437d74be36a Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 28 Sep 2026 04:37:20 +0000 Subject: [PATCH 0934/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 22697761c6a01e8d12adcd91e4a5bc755596767a. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 2579ec7acaec9..ddf759b5d0c48 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -c23137133458bf7a49f4a55d3adb9e2c7c33bd79 +22697761c6a01e8d12adcd91e4a5bc755596767a From 5c42b6dc73bb5c9917c3c24eb7593a793ea90db4 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Mon, 28 Sep 2026 04:40:14 +0000 Subject: [PATCH 0935/1309] fmt --- src/tools/miri/src/machine.rs | 2 +- src/tools/miri/src/shims/foreign_items.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index fa025f839057f..65eb6e10d4518 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -14,11 +14,11 @@ use rustc_abi::{Align, ExternAbi, Size}; use rustc_apfloat::{Float, FloatConvert}; use rustc_ast::Mutability; use rustc_ast::expand::allocator::{self, SpecialAllocatorMethod}; +use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_data_structures::either::Either; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; #[allow(unused)] use rustc_data_structures::static_assert_size; -use rustc_attr_ir::{InlineAttr, Linkage}; use rustc_hir::def::DefKind; use rustc_log::tracing; use rustc_middle::middle::codegen_fn_attrs::TargetFeatureKind; diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index f9ca42dfa0e1f..fab412e6d92a8 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -4,8 +4,8 @@ use std::path::Path; use rustc_abi::{Align, ExternAbi, Size}; use rustc_ast::expand::allocator::NO_ALLOC_SHIM_IS_UNSTABLE; -use rustc_data_structures::either::Either; use rustc_attr_ir::Linkage; +use rustc_data_structures::either::Either; use rustc_hir::def::DefKind; use rustc_hir::def_id::CrateNum; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; From 4d0e645b0f85ba6dfa6027f41d8487f929ee63e0 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Mon, 28 Sep 2026 01:39:35 -0500 Subject: [PATCH 0936/1309] triagebot: Subscribe me to changes in test-float-parse --- triagebot.toml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 60098a038ea73..bad75dc51d740 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1185,6 +1185,10 @@ cc = ["@rust-lang/miri", "@RalfJung", "@oli-obk", "@lcnr"] message = "Some changes occurred in float parsing" cc = ["@tgross35"] +[mentions."src/tools/test-float-parse"] +message = "Some changes occurred in float parsing" +cc = ["@tgross35"] + [mentions."library/core/src/fmt/num.rs"] message = "Some changes occurred in integer formatting" cc = ["@tgross35"] From 070652c2496168942d40541a19a0d0f4473ebbee Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 27 Sep 2026 21:34:33 +0000 Subject: [PATCH 0937/1309] remove `ast::MutTy` --- compiler/rustc_ast/src/ast.rs | 37 ++++++------------- .../rustc_ast/src/expand/autodiff_attrs.rs | 2 +- compiler/rustc_ast/src/util/classify.rs | 8 ++-- compiler/rustc_ast/src/visit.rs | 1 - compiler/rustc_ast_lowering/src/lib.rs | 25 ++++++++----- compiler/rustc_ast_pretty/src/pprust/state.rs | 20 +++++----- compiler/rustc_builtin_macros/src/autodiff.rs | 21 +++++++---- compiler/rustc_expand/src/build.rs | 8 +--- compiler/rustc_lint/src/unused.rs | 4 +- .../rustc_parse/src/parser/diagnostics.rs | 4 +- compiler/rustc_parse/src/parser/ty.rs | 16 ++++---- compiler/rustc_resolve/src/late.rs | 8 ++-- .../rustc_resolve/src/late/diagnostics.rs | 18 ++++----- .../src/needless_arbitrary_self_type.rs | 6 +-- .../src/redundant_static_lifetimes.rs | 10 ++--- .../clippy/clippy_utils/src/ast_utils/mod.rs | 10 ++--- .../clippy_utils/src/check_proc_macro.rs | 6 +-- src/tools/rustfmt/src/types.rs | 28 +++++++------- 18 files changed, 110 insertions(+), 122 deletions(-) diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs index bd1db99c3766b..6a86e9af71826 100644 --- a/compiler/rustc_ast/src/ast.rs +++ b/compiler/rustc_ast/src/ast.rs @@ -651,8 +651,8 @@ impl Pat { PatKind::MacCall(mac) => TyKind::MacCall(mac.clone()), // `&mut? P` can be reinterpreted as `&mut? T` where `T` is `P` reparsed as a type. PatKind::Ref(pat, pinned, mutbl) => pat.to_ty().map(|ty| match pinned { - Pinnedness::Not => TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }), - Pinnedness::Pinned => TyKind::PinnedRef(None, MutTy { ty, mutbl: *mutbl }), + Pinnedness::Not => TyKind::Ref(None, ty, *mutbl), + Pinnedness::Pinned => TyKind::PinnedRef(None, ty, *mutbl), })?, // A slice/array pattern `[P]` can be reparsed as `[T]`, an unsized array, // when `P` can be reparsed as a type `T`. @@ -1507,7 +1507,7 @@ impl Expr { ExprKind::Paren(expr) => expr.to_ty().map(TyKind::Paren)?, ExprKind::AddrOf(BorrowKind::Ref, mutbl, expr) => { - expr.to_ty().map(|ty| TyKind::Ref(None, MutTy { ty, mutbl: *mutbl }))? + expr.to_ty().map(|ty| TyKind::Ref(None, ty, *mutbl))? } ExprKind::Repeat(expr, expr_len) => { @@ -2336,14 +2336,6 @@ impl LitKind { } } -// N.B., If you change this, you'll probably want to change the corresponding -// type structure in `middle/ty.rs` as well. -#[derive(Clone, Encodable, Decodable, Debug, Walkable)] -pub struct MutTy { - pub ty: Box, - pub mutbl: Mutability, -} - /// Represents a function's signature in a trait declaration, /// trait implementation, or free function. #[derive(Clone, Encodable, Decodable, Debug)] @@ -2470,8 +2462,7 @@ impl From> for Ty { impl Ty { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Ref(_, MutTy { ty, .. }) | TyKind::Ptr(MutTy { ty, .. }) = &final_ty.kind - { + while let TyKind::Ref(_, ty, _) | TyKind::Ptr(ty, ..) = &final_ty.kind { final_ty = ty; } final_ty @@ -2528,13 +2519,13 @@ pub enum TyKind { /// A fixed length array (`[T; n]`). Array(Box, AnonConst), /// A raw pointer (`*const T` or `*mut T`). - Ptr(MutTy), + Ptr(Box, Mutability), /// A reference (`&'a T` or `&'a mut T`). - Ref(#[visitable(extra = LifetimeCtxt::Ref)] Option, MutTy), + Ref(#[visitable(extra = LifetimeCtxt::Ref)] Option, Box, Mutability), /// A pinned reference (`&'a pin const T` or `&'a pin mut T`). /// /// Desugars into `Pin<&'a T>` or `Pin<&'a mut T>`. - PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option, MutTy), + PinnedRef(#[visitable(extra = LifetimeCtxt::Ref)] Option, Box, Mutability), /// A function pointer type (e.g., `fn(usize) -> bool`). FnPtr(Box), /// An unsafe existential lifetime binder (e.g., `unsafe<'a> &'a ()`). @@ -2979,12 +2970,10 @@ impl Param { if ident.name == kw::SelfLower { return match self.ty.kind { TyKind::ImplicitSelf => Some(respan(self.pat.span, SelfKind::Value(mutbl))), - TyKind::Ref(lt, MutTy { ref ty, mutbl }) if ty.kind.is_implicit_self() => { + TyKind::Ref(lt, ref ty, mutbl) if ty.kind.is_implicit_self() => { Some(respan(self.pat.span, SelfKind::Region(lt, mutbl))) } - TyKind::PinnedRef(lt, MutTy { ref ty, mutbl }) - if ty.kind.is_implicit_self() => - { + TyKind::PinnedRef(lt, ref ty, mutbl) if ty.kind.is_implicit_self() => { Some(respan(self.pat.span, SelfKind::Pinned(lt, mutbl))) } _ => Some(respan( @@ -3016,17 +3005,13 @@ impl Param { SelfKind::Value(mutbl) => (mutbl, infer_ty), SelfKind::Region(lt, mutbl) => ( Mutability::Not, - Box::new(Ty { - id: DUMMY_NODE_ID, - kind: TyKind::Ref(lt, MutTy { ty: infer_ty, mutbl }), - span, - }), + Box::new(Ty { id: DUMMY_NODE_ID, kind: TyKind::Ref(lt, infer_ty, mutbl), span }), ), SelfKind::Pinned(lt, mutbl) => ( Mutability::Not, Box::new(Ty { id: DUMMY_NODE_ID, - kind: TyKind::PinnedRef(lt, MutTy { ty: infer_ty, mutbl }), + kind: TyKind::PinnedRef(lt, infer_ty, mutbl), span, }), ), diff --git a/compiler/rustc_ast/src/expand/autodiff_attrs.rs b/compiler/rustc_ast/src/expand/autodiff_attrs.rs index c9a3275c4c97f..9db7802f1739f 100644 --- a/compiler/rustc_ast/src/expand/autodiff_attrs.rs +++ b/compiler/rustc_ast/src/expand/autodiff_attrs.rs @@ -160,7 +160,7 @@ pub fn valid_ty_for_activity(ty: &Box, activity: DiffActivity) -> bool { if matches!(activity, Active | ActiveOnly) { return true; } - matches!(ty.kind, TyKind::Ptr(_) | TyKind::Ref(..)) + matches!(ty.kind, TyKind::Ptr(..) | TyKind::Ref(..)) && matches!(activity, Duplicated | DuplicatedOnly) } pub fn valid_input_activity(mode: DiffMode, activity: DiffActivity) -> bool { diff --git a/compiler/rustc_ast/src/util/classify.rs b/compiler/rustc_ast/src/util/classify.rs index c4c181743543e..86a4073bd100f 100644 --- a/compiler/rustc_ast/src/util/classify.rs +++ b/compiler/rustc_ast/src/util/classify.rs @@ -262,10 +262,10 @@ fn type_trailing_braced_mac_call(mut ty: &ast::Ty) -> Option<&ast::MacCall> { break (mac.args.delim == Delimiter::Brace).then_some(mac); } - ast::TyKind::Ptr(mut_ty) - | ast::TyKind::Ref(_, mut_ty) - | ast::TyKind::PinnedRef(_, mut_ty) => { - ty = &mut_ty.ty; + ast::TyKind::Ptr(inner_ty, _) + | ast::TyKind::Ref(_, inner_ty, _) + | ast::TyKind::PinnedRef(_, inner_ty, _) => { + ty = inner_ty; } ast::TyKind::UnsafeBinder(binder) => { diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs index ec77de62607ce..e4813b9588409 100644 --- a/compiler/rustc_ast/src/visit.rs +++ b/compiler/rustc_ast/src/visit.rs @@ -542,7 +542,6 @@ macro_rules! common_visitor_and_walkers { MethodCall, ModKind, ModSpans, - MutTy, NormalAttr, Parens, ParenthesizedArgs, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4bc61a22b3b3d..395971fc4a36a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1527,14 +1527,14 @@ impl<'hir> LoweringContext<'_, 'hir> { TyKind::Infer => hir::TyKind::Infer(()), TyKind::Err(guar) => hir::TyKind::Err(*guar), TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty_alloc(ty, itctx)), - TyKind::Ptr(mt) => hir::TyKind::Ptr(self.lower_mt(mt, itctx)), - TyKind::Ref(region, mt) => { + TyKind::Ptr(ty, mutbl) => hir::TyKind::Ptr(self.lower_mt(ty, *mutbl, itctx)), + TyKind::Ref(region, ty, mutbl) => { let lifetime = self.lower_ty_direct_lifetime(t, *region); - hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)) + hir::TyKind::Ref(lifetime, self.lower_mt(ty, *mutbl, itctx)) } - TyKind::PinnedRef(region, mt) => { + TyKind::PinnedRef(region, ty, mutbl) => { let lifetime = self.lower_ty_direct_lifetime(t, *region); - let kind = hir::TyKind::Ref(lifetime, self.lower_mt(mt, itctx)); + let kind = hir::TyKind::Ref(lifetime, self.lower_mt(ty, *mutbl, itctx)); let span = self.lower_span(t.span); let arg = hir::Ty { kind, span, hir_id: self.next_id() }; let args = self.arena.alloc(hir::GenericArgs { @@ -1998,10 +1998,10 @@ impl<'hir> LoweringContext<'_, 'hir> { // Given we are only considering `ImplicitSelf` types, we needn't consider // the case where we have a mutable pattern to a reference as that would // no longer be an `ImplicitSelf`. - TyKind::Ref(_, mt) | TyKind::PinnedRef(_, mt) - if mt.ty.kind.is_implicit_self() => + TyKind::Ref(_, ty, mutbl) | TyKind::PinnedRef(_, ty, mutbl) + if ty.kind.is_implicit_self() => { - match mt.mutbl { + match mutbl { hir::Mutability::Not => hir::ImplicitSelfKind::RefImm, hir::Mutability::Mut => hir::ImplicitSelfKind::RefMut, } @@ -2473,8 +2473,13 @@ impl<'hir> LoweringContext<'_, 'hir> { .emit(); } - fn lower_mt(&mut self, mt: &MutTy, itctx: ImplTraitContext) -> hir::MutTy<'hir> { - hir::MutTy { ty: self.lower_ty_alloc(&mt.ty, itctx), mutbl: mt.mutbl } + fn lower_mt( + &mut self, + ty: &Ty, + mutbl: Mutability, + itctx: ImplTraitContext, + ) -> hir::MutTy<'hir> { + hir::MutTy { ty: self.lower_ty_alloc(ty, itctx), mutbl } } #[instrument(level = "debug", skip(self), ret)] diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs index 3ec9fdef4b0e6..b76502814dbb7 100644 --- a/compiler/rustc_ast_pretty/src/pprust/state.rs +++ b/compiler/rustc_ast_pretty/src/pprust/state.rs @@ -1346,20 +1346,23 @@ impl<'a> State<'a> { self.print_type(ty); self.word("]"); } - ast::TyKind::Ptr(mt) => { + ast::TyKind::Ptr(ty, mutbl) => { self.word("*"); - self.print_mt(mt, true); + self.print_mutability(*mutbl, true); + self.print_type(ty); } - ast::TyKind::Ref(lifetime, mt) => { + ast::TyKind::Ref(lifetime, ty, mutbl) => { self.word("&"); self.print_opt_lifetime(lifetime); - self.print_mt(mt, false); + self.print_mutability(*mutbl, false); + self.print_type(ty); } - ast::TyKind::PinnedRef(lifetime, mt) => { + ast::TyKind::PinnedRef(lifetime, ty, mutbl) => { self.word("&"); self.print_opt_lifetime(lifetime); self.word("pin "); - self.print_mt(mt, true); + self.print_mutability(*mutbl, true); + self.print_type(ty); } ast::TyKind::Never => { self.word("!"); @@ -2229,11 +2232,6 @@ impl<'a> State<'a> { } } - fn print_mt(&mut self, mt: &ast::MutTy, print_const: bool) { - self.print_mutability(mt.mutbl, print_const); - self.print_type(&mt.ty) - } - fn print_param(&mut self, input: &ast::Param, is_closure: bool) { let ib = self.ibox(INDENT_UNIT); diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs index 083d05d03a070..21f424836e476 100644 --- a/compiler/rustc_builtin_macros/src/autodiff.rs +++ b/compiler/rustc_builtin_macros/src/autodiff.rs @@ -473,11 +473,11 @@ mod llvm_enzyme { fn assure_mut_ref(ty: &ast::Ty) -> ast::Ty { let mut ty = ty.clone(); match ty.kind { - TyKind::Ptr(ref mut mut_ty) => { - mut_ty.mutbl = ast::Mutability::Mut; + TyKind::Ptr(_, ref mut mutbl) => { + *mutbl = ast::Mutability::Mut; } - TyKind::Ref(_, ref mut mut_ty) => { - mut_ty.mutbl = ast::Mutability::Mut; + TyKind::Ref(_, _, ref mut mutbl) => { + *mutbl = ast::Mutability::Mut; } _ => { panic!("unsupported type: {:?}", ty); @@ -510,10 +510,15 @@ mod llvm_enzyme { .map(|param| { let ty = match ¶m.ty.kind { TyKind::ImplicitSelf => self_ty(), - TyKind::Ref(lt, mt) if matches!(mt.ty.kind, TyKind::ImplicitSelf) => ecx - .ty(span, TyKind::Ref(*lt, ast::MutTy { ty: self_ty(), mutbl: mt.mutbl })), - TyKind::Ptr(mt) if matches!(mt.ty.kind, TyKind::ImplicitSelf) => { - ecx.ty(span, TyKind::Ptr(ast::MutTy { ty: self_ty(), mutbl: mt.mutbl })) + TyKind::Ref(lt, inner_ty, mutbl) + if matches!(inner_ty.kind, TyKind::ImplicitSelf) => + { + ecx.ty(span, TyKind::Ref(*lt, self_ty(), *mutbl)) + } + TyKind::Ptr(inner_ty, mutbl) + if matches!(inner_ty.kind, TyKind::ImplicitSelf) => + { + ecx.ty(span, TyKind::Ptr(self_ty(), *mutbl)) } _ => param.ty.clone(), }; diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs index 34d4343ba9ba0..2a4089b1213ab 100644 --- a/compiler/rustc_expand/src/build.rs +++ b/compiler/rustc_expand/src/build.rs @@ -77,10 +77,6 @@ impl<'a> ExtCtxt<'a> { }) } - pub fn ty_mt(&self, ty: Box, mutbl: ast::Mutability) -> ast::MutTy { - ast::MutTy { ty, mutbl } - } - pub fn ty(&self, span: Span, kind: ast::TyKind) -> Box { Box::new(ast::Ty { id: ast::DUMMY_NODE_ID, span, kind }) } @@ -127,11 +123,11 @@ impl<'a> ExtCtxt<'a> { lifetime: Option, mutbl: ast::Mutability, ) -> Box { - self.ty(span, ast::TyKind::Ref(lifetime, self.ty_mt(ty, mutbl))) + self.ty(span, ast::TyKind::Ref(lifetime, ty, mutbl)) } pub fn ty_ptr(&self, span: Span, ty: Box, mutbl: ast::Mutability) -> Box { - self.ty(span, ast::TyKind::Ptr(self.ty_mt(ty, mutbl))) + self.ty(span, ast::TyKind::Ptr(ty, mutbl)) } pub fn ty_unit(&self, span: Span) -> Box { diff --git a/compiler/rustc_lint/src/unused.rs b/compiler/rustc_lint/src/unused.rs index e2dff59a92990..361d1768087ea 100644 --- a/compiler/rustc_lint/src/unused.rs +++ b/compiler/rustc_lint/src/unused.rs @@ -1000,7 +1000,7 @@ impl EarlyLintPass for UnusedParens { self.with_self_ty_parens = false; } - ast::TyKind::Ref(_, mut_ty) | ast::TyKind::Ptr(mut_ty) => { + ast::TyKind::Ref(_, inner_ty, _) | ast::TyKind::Ptr(inner_ty, _) => { // If this type itself appears in no-bounds position, we propagate its // potentially tighter constraint or risk a false posive (issue 143653). let own_constraint = self.in_no_bounds_pos.get(&ty.id); @@ -1009,7 +1009,7 @@ impl EarlyLintPass for UnusedParens { Some(NoBoundsException::OneBound) => NoBoundsException::OneBound, None => NoBoundsException::OneBound, }; - self.in_no_bounds_pos.insert(mut_ty.ty.id, constraint); + self.in_no_bounds_pos.insert(inner_ty.id, constraint); } ast::TyKind::TraitObject(bounds, _) | ast::TyKind::ImplTrait(_, bounds) => { for i in 0..bounds.len() { diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index e7073a4d81978..fd4d012ebe2f9 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -1562,8 +1562,8 @@ impl<'a> Parser<'a> { self.bump(); // `+` let _bounds = self.parse_generic_bounds()?; let sub = match &ty.kind { - TyKind::Ref(_lifetime, mut_ty) => { - let lo = mut_ty.ty.span.shrink_to_lo(); + TyKind::Ref(_lifetime, inner_ty, _) => { + let lo = inner_ty.span.shrink_to_lo(); let hi = self.prev_token.span.shrink_to_hi(); BadTypePlusSub::AddParen { suggestion: AddParen { lo, hi } } } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 5450d23fbbc2e..29b83e006d195 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -2,9 +2,9 @@ use rustc_ast::token::{self, IdentKind, MetaVarKind, Token, TokenKind}; use rustc_ast::util::case::Case; use rustc_ast::{ self as ast, BoundAsyncness, BoundConstness, BoundPolarity, DUMMY_NODE_ID, FnPtrTy, FnRetTy, - GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, MutTy, Mutability, - Path, Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, - Ty, TyKind, UnsafeBinderTy, + GenericBound, GenericBounds, GenericParam, Generics, Lifetime, MacCall, Mutability, Path, + Pinnedness, PolyTraitRef, PreciseCapturingArg, TraitBoundModifiers, TraitObjectSyntax, Ty, + TyKind, UnsafeBinderTy, }; use rustc_errors::{Applicability, Diag, E0516, PResult}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; @@ -565,7 +565,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); err.emit(); - Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl })) + Ok(TyKind::Ref(Some(lt), ty, mutbl)) } Err(diag) => { diag.cancel(); @@ -626,7 +626,7 @@ impl<'a> Parser<'a> { ) .emit(); - return Ok(TyKind::Ptr(MutTy { ty, mutbl })); + return Ok(TyKind::Ptr(ty, mutbl)); } // This is unreachable because we always get into if above and return from it unreachable!("this could never happen") @@ -643,7 +643,7 @@ impl<'a> Parser<'a> { Mutability::Not }); let ty = self.parse_ty_no_plus()?; - Ok(TyKind::Ptr(MutTy { ty, mutbl })) + Ok(TyKind::Ptr(ty, mutbl)) } /// Parses an array (`[TYPE; EXPR]`) or slice (`[TYPE]`) type. @@ -761,8 +761,8 @@ impl<'a> Parser<'a> { } let ty = self.parse_ty_no_plus()?; Ok(match pinned { - Pinnedness::Not => TyKind::Ref(opt_lifetime, MutTy { ty, mutbl }), - Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, MutTy { ty, mutbl }), + Pinnedness::Not => TyKind::Ref(opt_lifetime, ty, mutbl), + Pinnedness::Pinned => TyKind::PinnedRef(opt_lifetime, ty, mutbl), }) } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..8eb2aea8a2604 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -923,7 +923,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc let prev = self.diag_metadata.current_trait_object; let prev_ty = self.diag_metadata.current_type_path; match &ty.kind { - TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => { + TyKind::Ref(None, ..) | TyKind::PinnedRef(None, ..) => { // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with // NodeId `ty.id`. // This span will be used in case of elision failure. @@ -2116,8 +2116,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { type Result = ControlFlow; fn visit_ty(&mut self, ty: &'ast ast::Ty) -> Self::Result { - if let ast::TyKind::Ref(None, mut_ty) = &ty.kind { - return ControlFlow::Break(mut_ty.ty.span.shrink_to_lo()); + if let ast::TyKind::Ref(None, inner_ty, _) = &ty.kind { + return ControlFlow::Break(inner_ty.span.shrink_to_lo()); } visit::walk_ty(self, ty) } @@ -2656,7 +2656,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> { fn visit_ty(&mut self, ty: &'ra Ty) { trace!("FindReferenceVisitor considering ty={:?}", ty); - if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind { + if let TyKind::Ref(lt, ..) | TyKind::PinnedRef(lt, ..) = ty.kind { // See if anything inside the &thing contains Self let mut visitor = SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false }; diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index cdef92b389265..700226a5c2207 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2924,7 +2924,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn extract_node_id(t: &Ty) -> Option { match t.kind { TyKind::Path(None, _) => Some(t.id), - TyKind::Ref(_, ref mut_ty) => extract_node_id(&mut_ty.ty), + TyKind::Ref(_, ref inner_ty, _) => extract_node_id(inner_ty), // This doesn't handle the remaining `Ty` variants as they are not // that commonly the self_type, it might be interesting to provide // support for those in future. @@ -4472,8 +4472,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .seen .iter() .filter_map(|ty| match &ty.kind { - TyKind::Ref(_, mut_ty) => { - let span = ty.span.with_hi(mut_ty.ty.span.lo()); + TyKind::Ref(_, inner_ty, _) => { + let span = ty.span.with_hi(inner_ty.span.lo()); Some((span, "&'a ".to_string())) } _ => None, @@ -4513,7 +4513,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { let mut ret_lt_finder = LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] }; ret_lt_finder.visit_ty(ret_ty); - if let [Ty { span, kind: TyKind::Ref(_, mut_ty), .. }] = + if let [Ty { span, kind: TyKind::Ref(_, inner_ty, _), .. }] = &ret_lt_finder.seen[..] { // We might have a situation like @@ -4521,7 +4521,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // but `lt.span` only points at `'_`, so to suggest `-> Option<()>` // we need to find a more accurate span to end up with // fn g<'a>(mut x: impl Iterator) -> Option<()> - sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())]; + sugg = vec![(span.with_hi(inner_ty.span.lo()), String::new())]; owned_sugg = true; } } @@ -4746,10 +4746,10 @@ struct LifetimeFinder<'ast> { impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> { fn visit_ty(&mut self, t: &'ast Ty) { - if let TyKind::Ref(_, mut_ty) | TyKind::PinnedRef(_, mut_ty) = &t.kind { + if let TyKind::Ref(_, ty, _) | TyKind::PinnedRef(_, ty, _) = &t.kind { self.seen.push(t); if t.span.lo() == self.lifetime.lo() { - self.found = Some(&mut_ty.ty); + self.found = Some(ty); } } walk_ty(self, t) @@ -4766,10 +4766,10 @@ impl<'ast> Visitor<'ast> for RefPrefixSpanFinder { if self.span.is_some() { return; } - if let TyKind::Ref(_, mut_ty) | TyKind::PinnedRef(_, mut_ty) = &t.kind + if let TyKind::Ref(_, inner_ty, _) | TyKind::PinnedRef(_, inner_ty, _) = &t.kind && t.span.lo() == self.lifetime.lo() { - self.span = Some(t.span.with_hi(mut_ty.ty.span.lo())); + self.span = Some(t.span.with_hi(inner_ty.span.lo())); return; } walk_ty(self, t); diff --git a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs index 5517228b6ef21..9d7b3c0d27224 100644 --- a/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/src/tools/clippy/clippy_lints/src/needless_arbitrary_self_type.rs @@ -74,11 +74,11 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { TyKind::Path(None, path) if let PatKind::Ident(BindingMode(ByRef::No, mutbl), _, _) = p.pat.kind => { (path, Mode::Value, mutbl) }, - TyKind::Ref(lifetime, mut_ty) - if let TyKind::Path(None, path) = &mut_ty.ty.kind + TyKind::Ref(lifetime, ty, mutbl) + if let TyKind::Path(None, path) = &ty.kind && let PatKind::Ident(BindingMode::NONE, _, _) = p.pat.kind => { - (path, Mode::Ref(*lifetime), mut_ty.mutbl) + (path, Mode::Ref(*lifetime), *mutbl) }, _ => return, }; diff --git a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs index 273ea7506431e..afbb8c0fa38d3 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_static_lifetimes.rs @@ -59,15 +59,15 @@ impl RedundantStaticLifetimes { } }, // This is what we are looking for ! - TyKind::Ref(ref optional_lifetime, ref borrow_type) => { + TyKind::Ref(ref optional_lifetime, ref borrow_type, mutbl) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { - match borrow_type.ty.kind { + match borrow_type.kind { TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) if lifetime.ident.name == kw::StaticLifetime => { - let snip = snippet(cx, borrow_type.ty.span, ""); - let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str()); + let snip = snippet(cx, borrow_type.span, ""); + let sugg = format!("&{}{snip}", mutbl.prefix_str()); span_lint_and_then(cx, REDUNDANT_STATIC_LIFETIMES, lifetime.ident.span, reason, |diag| { diag.span_suggestion( ty.span, @@ -80,7 +80,7 @@ impl RedundantStaticLifetimes { _ => {}, } } - Self::visit_type(&borrow_type.ty, cx, reason); + Self::visit_type(borrow_type, cx, reason); }, _ => {}, } diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs index 3c398d74ad7b4..0774fa729bc12 100644 --- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs @@ -867,12 +867,12 @@ fn eq_ty(l: &Ty, r: &Ty) -> bool { }, (Slice(l), Slice(r)) => eq_ty(l, r), (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), - (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), - (Ref(ll, l), Ref(rl, r)) => { - both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + (Ptr(l_ty, l_mutbl), Ptr(r_ty, r_mutbl)) => l_mutbl == r_mutbl && eq_ty(l_ty, r_ty), + (Ref(ll, l_ty, l_mutbl), Ref(rl, r_ty, r_mutbl)) => { + both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l_mutbl == r_mutbl && eq_ty(l_ty, r_ty) }, - (PinnedRef(ll, l), PinnedRef(rl, r)) => { - both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + (PinnedRef(ll, l_ty, l_mutbl), PinnedRef(rl, r_ty, r_mutbl)) => { + both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l_mutbl == r_mutbl && eq_ty(l_ty, r_ty) }, (FnPtr(l), FnPtr(r)) => { l.safety == r.safety diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index baff6a99fc9e0..ca79f79403e7d 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -431,12 +431,12 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { - use ast::{Extern, FnRetTy, MutTy, Safety, TraitObjectSyntax, TyKind}; + use ast::{Extern, FnRetTy, Safety, TraitObjectSyntax, TyKind}; match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ast_ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) | TyKind::PinnedRef(_, MutTy { ty, .. }) => { + TyKind::Ptr(ty, ..) => (Pat::Str("*"), ast_ty_search_pat(ty).1), + TyKind::Ref(_, ty, ..) | TyKind::PinnedRef(_, ty, ..) => { (Pat::Str("&"), ast_ty_search_pat(ty).1) }, TyKind::FnPtr(fn_ptr) => ( diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs index d119cd50c846a..fcf8321f18994 100644 --- a/src/tools/rustfmt/src/types.rs +++ b/src/tools/rustfmt/src/types.rs @@ -821,17 +821,17 @@ impl Rewrite for ast::Ty { } Ok(format!("{prefix}{res}")) } - ast::TyKind::Ptr(ref mt) => { - let prefix = match mt.mutbl { + ast::TyKind::Ptr(ref ty, mutbl) => { + let prefix = match mutbl { Mutability::Mut => "*mut ", Mutability::Not => "*const ", }; - rewrite_unary_prefix(context, prefix, &*mt.ty, shape) + rewrite_unary_prefix(context, prefix, &*ty, shape) } - ast::TyKind::Ref(ref lifetime, ref mt) - | ast::TyKind::PinnedRef(ref lifetime, ref mt) => { - let mut_str = format_mutability(mt.mutbl); + ast::TyKind::Ref(ref lifetime, ref ty, mutbl) + | ast::TyKind::PinnedRef(ref lifetime, ref ty, mutbl) => { + let mut_str = format_mutability(mutbl); let mut_len = mut_str.len(); let mut result = String::with_capacity(128); result.push('&'); @@ -866,12 +866,12 @@ impl Rewrite for ast::Ty { if let ast::TyKind::PinnedRef(..) = self.kind { result.push_str("pin "); - if ast::Mutability::Not == mt.mutbl { + if ast::Mutability::Not == mutbl { result.push_str("const "); } } - if ast::Mutability::Mut == mt.mutbl { + if ast::Mutability::Mut == mutbl { let mut_hi = context.snippet_provider.span_after(self.span(), "mut"); let before_mut_span = mk_sp(cmnt_lo, mut_hi - BytePos::from_usize(3)); if contains_comment(context.snippet(before_mut_span)) { @@ -889,12 +889,12 @@ impl Rewrite for ast::Ty { cmnt_lo = mut_hi; } - let before_ty_span = mk_sp(cmnt_lo, mt.ty.span.lo()); + let before_ty_span = mk_sp(cmnt_lo, ty.span.lo()); if contains_comment(context.snippet(before_ty_span)) { result = combine_strs_with_missing_comments( context, result.trim_end(), - &mt.ty.rewrite_result(context, shape)?, + &ty.rewrite_result(context, shape)?, before_ty_span, shape, true, @@ -905,7 +905,7 @@ impl Rewrite for ast::Ty { .width .checked_sub(used_width) .max_width_error(shape.width, self.span())?; - let ty_str = mt.ty.rewrite_result( + let ty_str = ty.rewrite_result( context, Shape::legacy(budget, shape.indent + used_width), )?; @@ -1333,9 +1333,9 @@ pub(crate) fn can_be_overflowed_type( ) -> bool { match ty.kind { ast::TyKind::Tup(..) => context.use_block_indent() && len == 1, - ast::TyKind::Ref(_, ref mutty) - | ast::TyKind::PinnedRef(_, ref mutty) - | ast::TyKind::Ptr(ref mutty) => can_be_overflowed_type(context, &*mutty.ty, len), + ast::TyKind::Ref(_, ref ty, _) + | ast::TyKind::PinnedRef(_, ref ty, _) + | ast::TyKind::Ptr(ref ty, _) => can_be_overflowed_type(context, &*ty, len), _ => false, } } From 0215cc24834b37d5d1a6f63b4b0afebed71b6232 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 27 Sep 2026 21:34:33 +0000 Subject: [PATCH 0938/1309] remove `ast::MutTy` --- clippy_lints/src/needless_arbitrary_self_type.rs | 6 +++--- clippy_lints/src/redundant_static_lifetimes.rs | 10 +++++----- clippy_utils/src/ast_utils/mod.rs | 10 +++++----- clippy_utils/src/check_proc_macro.rs | 6 +++--- 4 files changed, 16 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/needless_arbitrary_self_type.rs b/clippy_lints/src/needless_arbitrary_self_type.rs index 5517228b6ef21..9d7b3c0d27224 100644 --- a/clippy_lints/src/needless_arbitrary_self_type.rs +++ b/clippy_lints/src/needless_arbitrary_self_type.rs @@ -74,11 +74,11 @@ impl EarlyLintPass for NeedlessArbitrarySelfType { TyKind::Path(None, path) if let PatKind::Ident(BindingMode(ByRef::No, mutbl), _, _) = p.pat.kind => { (path, Mode::Value, mutbl) }, - TyKind::Ref(lifetime, mut_ty) - if let TyKind::Path(None, path) = &mut_ty.ty.kind + TyKind::Ref(lifetime, ty, mutbl) + if let TyKind::Path(None, path) = &ty.kind && let PatKind::Ident(BindingMode::NONE, _, _) = p.pat.kind => { - (path, Mode::Ref(*lifetime), mut_ty.mutbl) + (path, Mode::Ref(*lifetime), *mutbl) }, _ => return, }; diff --git a/clippy_lints/src/redundant_static_lifetimes.rs b/clippy_lints/src/redundant_static_lifetimes.rs index 273ea7506431e..afbb8c0fa38d3 100644 --- a/clippy_lints/src/redundant_static_lifetimes.rs +++ b/clippy_lints/src/redundant_static_lifetimes.rs @@ -59,15 +59,15 @@ impl RedundantStaticLifetimes { } }, // This is what we are looking for ! - TyKind::Ref(ref optional_lifetime, ref borrow_type) => { + TyKind::Ref(ref optional_lifetime, ref borrow_type, mutbl) => { // Match the 'static lifetime if let Some(lifetime) = *optional_lifetime { - match borrow_type.ty.kind { + match borrow_type.kind { TyKind::Path(..) | TyKind::Slice(..) | TyKind::Array(..) | TyKind::Tup(..) if lifetime.ident.name == kw::StaticLifetime => { - let snip = snippet(cx, borrow_type.ty.span, ""); - let sugg = format!("&{}{snip}", borrow_type.mutbl.prefix_str()); + let snip = snippet(cx, borrow_type.span, ""); + let sugg = format!("&{}{snip}", mutbl.prefix_str()); span_lint_and_then(cx, REDUNDANT_STATIC_LIFETIMES, lifetime.ident.span, reason, |diag| { diag.span_suggestion( ty.span, @@ -80,7 +80,7 @@ impl RedundantStaticLifetimes { _ => {}, } } - Self::visit_type(&borrow_type.ty, cx, reason); + Self::visit_type(borrow_type, cx, reason); }, _ => {}, } diff --git a/clippy_utils/src/ast_utils/mod.rs b/clippy_utils/src/ast_utils/mod.rs index 3c398d74ad7b4..0774fa729bc12 100644 --- a/clippy_utils/src/ast_utils/mod.rs +++ b/clippy_utils/src/ast_utils/mod.rs @@ -867,12 +867,12 @@ fn eq_ty(l: &Ty, r: &Ty) -> bool { }, (Slice(l), Slice(r)) => eq_ty(l, r), (Array(le, ls), Array(re, rs)) => eq_ty(le, re) && eq_expr(&ls.value, &rs.value), - (Ptr(l), Ptr(r)) => l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty), - (Ref(ll, l), Ref(rl, r)) => { - both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + (Ptr(l_ty, l_mutbl), Ptr(r_ty, r_mutbl)) => l_mutbl == r_mutbl && eq_ty(l_ty, r_ty), + (Ref(ll, l_ty, l_mutbl), Ref(rl, r_ty, r_mutbl)) => { + both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l_mutbl == r_mutbl && eq_ty(l_ty, r_ty) }, - (PinnedRef(ll, l), PinnedRef(rl, r)) => { - both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l.mutbl == r.mutbl && eq_ty(&l.ty, &r.ty) + (PinnedRef(ll, l_ty, l_mutbl), PinnedRef(rl, r_ty, r_mutbl)) => { + both(ll.as_ref(), rl.as_ref(), |l, r| eq_id(l.ident, r.ident)) && l_mutbl == r_mutbl && eq_ty(l_ty, r_ty) }, (FnPtr(l), FnPtr(r)) => { l.safety == r.safety diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index baff6a99fc9e0..ca79f79403e7d 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -431,12 +431,12 @@ fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { } fn ast_ty_search_pat(ty: &ast::Ty) -> (Pat, Pat) { - use ast::{Extern, FnRetTy, MutTy, Safety, TraitObjectSyntax, TyKind}; + use ast::{Extern, FnRetTy, Safety, TraitObjectSyntax, TyKind}; match &ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ast_ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) | TyKind::PinnedRef(_, MutTy { ty, .. }) => { + TyKind::Ptr(ty, ..) => (Pat::Str("*"), ast_ty_search_pat(ty).1), + TyKind::Ref(_, ty, ..) | TyKind::PinnedRef(_, ty, ..) => { (Pat::Str("&"), ast_ty_search_pat(ty).1) }, TyKind::FnPtr(fn_ptr) => ( From ac6f00d948bb31cca5661405e1a96529a7477e75 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 28 Sep 2026 07:35:44 +0000 Subject: [PATCH 0939/1309] remove `hir::MutTy` --- compiler/rustc_ast_lowering/src/lib.rs | 15 +++---------- .../src/diagnostics/conflict_errors.rs | 6 ++--- .../src/diagnostics/mutability_errors.rs | 5 ++--- .../src/diagnostics/region_name.rs | 11 ++++++---- compiler/rustc_hir/src/hir.rs | 18 +++++---------- compiler/rustc_hir/src/hir/tests.rs | 2 +- compiler/rustc_hir/src/intravisit.rs | 6 ++--- .../src/coherence/builtin/coerce_shared.rs | 6 ++--- .../src/collect/resolve_bound_vars.rs | 4 ++-- .../src/hir_ty_lowering/mod.rs | 8 +++---- compiler/rustc_hir_pretty/src/lib.rs | 15 +++++-------- compiler/rustc_hir_typeck/src/demand.rs | 6 ++--- .../rustc_hir_typeck/src/method/suggest.rs | 5 ++--- compiler/rustc_lint/src/builtin.rs | 2 +- compiler/rustc_lint/src/dangling.rs | 2 +- .../rustc_lint/src/disallowed_pass_by_ref.rs | 2 +- compiler/rustc_lint/src/lifetime_syntax.rs | 4 ++-- compiler/rustc_lint/src/ptr_nulls.rs | 2 +- .../src/raw_borrows_via_references.rs | 2 +- compiler/rustc_mir_transform/src/liveness.rs | 6 ++--- .../rustc_trait_selection/src/diagnostics.rs | 2 +- .../infer/nice_region_error/find_anon_type.rs | 2 +- .../trait_impl_difference.rs | 4 ++-- .../src/error_reporting/traits/suggestions.rs | 18 +++++++-------- .../src/traits/dyn_compatibility.rs | 4 ++-- src/librustdoc/clean/mod.rs | 6 ++--- .../src/casts/as_pointer_underscore.rs | 2 +- .../clippy_lints/src/casts/borrow_as_ptr.rs | 4 ++-- .../src/casts/manual_dangling_ptr.rs | 12 +++++----- .../clippy_lints/src/casts/ptr_as_ptr.rs | 6 ++--- .../src/casts/ptr_cast_constness.rs | 4 ++-- .../clippy_lints/src/casts/ref_as_ptr.rs | 6 ++--- .../src/casts/unnecessary_cast.rs | 6 ++--- .../clippy/clippy_lints/src/casts/zero_ptr.rs | 8 +++---- .../clippy/clippy_lints/src/dereference.rs | 8 +++---- .../clippy_lints/src/functions/ref_option.rs | 2 +- .../src/iter_without_into_iter.rs | 4 ++-- .../src/methods/needless_collect.rs | 2 +- .../src/methods/should_implement_trait.rs | 2 +- src/tools/clippy/clippy_lints/src/mut_mut.rs | 22 +++++++++---------- .../src/needless_pass_by_ref_mut.rs | 4 ++-- .../clippy_lints/src/pass_by_ref_or_value.rs | 4 ++-- .../clippy_lints/src/ptr/mut_from_ref.rs | 4 ++-- .../clippy/clippy_lints/src/ptr/ptr_arg.rs | 4 ++-- .../src/redundant_type_annotations.rs | 8 +++---- .../clippy/clippy_lints/src/ref_option_ref.rs | 8 +++---- .../clippy/clippy_lints/src/trait_bounds.rs | 4 ++-- .../src/transmute/transmute_ptr_to_ref.rs | 4 ++-- .../clippy_lints/src/types/borrowed_box.rs | 14 ++++++++---- .../clippy/clippy_lints/src/types/mod.rs | 12 +++++----- .../src/unnecessary_literal_bound.rs | 4 ++-- .../clippy_utils/src/check_proc_macro.rs | 6 ++--- .../clippy/clippy_utils/src/hir_utils.rs | 18 +++++++-------- src/tools/clippy/clippy_utils/src/lib.rs | 6 ++--- src/tools/clippy/clippy_utils/src/sugg.rs | 7 +++--- 55 files changed, 171 insertions(+), 187 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 395971fc4a36a..e30fdfcebfdb8 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1527,14 +1527,14 @@ impl<'hir> LoweringContext<'_, 'hir> { TyKind::Infer => hir::TyKind::Infer(()), TyKind::Err(guar) => hir::TyKind::Err(*guar), TyKind::Slice(ty) => hir::TyKind::Slice(self.lower_ty_alloc(ty, itctx)), - TyKind::Ptr(ty, mutbl) => hir::TyKind::Ptr(self.lower_mt(ty, *mutbl, itctx)), + TyKind::Ptr(ty, mutbl) => hir::TyKind::Ptr(self.lower_ty_alloc(ty, itctx), *mutbl), TyKind::Ref(region, ty, mutbl) => { let lifetime = self.lower_ty_direct_lifetime(t, *region); - hir::TyKind::Ref(lifetime, self.lower_mt(ty, *mutbl, itctx)) + hir::TyKind::Ref(lifetime, self.lower_ty_alloc(ty, itctx), *mutbl) } TyKind::PinnedRef(region, ty, mutbl) => { let lifetime = self.lower_ty_direct_lifetime(t, *region); - let kind = hir::TyKind::Ref(lifetime, self.lower_mt(ty, *mutbl, itctx)); + let kind = hir::TyKind::Ref(lifetime, self.lower_ty_alloc(ty, itctx), *mutbl); let span = self.lower_span(t.span); let arg = hir::Ty { kind, span, hir_id: self.next_id() }; let args = self.arena.alloc(hir::GenericArgs { @@ -2473,15 +2473,6 @@ impl<'hir> LoweringContext<'_, 'hir> { .emit(); } - fn lower_mt( - &mut self, - ty: &Ty, - mutbl: Mutability, - itctx: ImplTraitContext, - ) -> hir::MutTy<'hir> { - hir::MutTy { ty: self.lower_ty_alloc(ty, itctx), mutbl } - } - #[instrument(level = "debug", skip(self), ret)] fn lower_param_bounds( &mut self, diff --git a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs index 2de98fd971bda..f7256968c8276 100644 --- a/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/conflict_errors.rs @@ -4600,7 +4600,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { // `return_region`. Then use the `rustc_hir` type to get only // the lifetime span. match &fn_decl.inputs[index].kind { - hir::TyKind::Ref(lifetime, _) => { + hir::TyKind::Ref(lifetime, ..) => { // With access to the lifetime, we can get // the span of it. arguments.push((*argument, lifetime.ident.span)); @@ -4615,7 +4615,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .hir_node_by_def_id(alias_to) .expect_item() .expect_impl() - && let hir::TyKind::Ref(lifetime, _) = self_ty.kind + && let hir::TyKind::Ref(lifetime, ..) = self_ty.kind { arguments.push((*argument, lifetime.ident.span)); } @@ -4637,7 +4637,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let return_ty = sig.output().skip_binder(); let mut return_span = fn_decl.output.span(); if let hir::FnRetTy::Return(ty) = &fn_decl.output - && let hir::TyKind::Ref(lifetime, _) = ty.kind + && let hir::TyKind::Ref(lifetime, ..) = ty.kind { return_span = lifetime.ident.span; } diff --git a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs index 245e340a7d877..1182cdb5c2c6e 100644 --- a/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/mutability_errors.rs @@ -927,8 +927,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { if let Node::TraitItem(ti) = self.infcx.tcx.hir_node_by_def_id(f_in_trait) && let hir::TraitItemKind::Fn(sig, _) = ti.kind && let Some(ty) = sig.decl.inputs.get(local.index() - 1) - && let hir::TyKind::Ref(_, mut_ty) = ty.kind - && let hir::Mutability::Not = mut_ty.mutbl + && let hir::TyKind::Ref(_, _, hir::Mutability::Not) = ty.kind && sig.decl.implicit_self().has_implicit_self() { Some(ty.span) @@ -2020,7 +2019,7 @@ fn get_mut_span_in_struct_field<'tcx>( // Now we're dealing with the actual struct that we're going to suggest a change to, // we can expect a field that is an immutable reference to a type. && let hir::Node::Field(field) = tcx.hir_node_by_def_id(field.did.as_local()?) - && let hir::TyKind::Ref(lt, hir::MutTy { mutbl: hir::Mutability::Not, ty }) = field.ty.kind + && let hir::TyKind::Ref(lt, ty, hir::Mutability::Not) = field.ty.kind { return Some(lt.ident.span.between(ty.span)); } diff --git a/compiler/rustc_borrowck/src/diagnostics/region_name.rs b/compiler/rustc_borrowck/src/diagnostics/region_name.rs index 9436d31ba19e8..871b974d28eea 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_name.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_name.rs @@ -621,7 +621,10 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { // // & // - let's call the lifetime of this reference `'1` - (ty::Ref(region, referent_ty, _), hir::TyKind::Ref(_lifetime, referent_hir_ty)) => { + ( + ty::Ref(region, referent_ty, _), + hir::TyKind::Ref(_lifetime, referent_hir_ty, _), + ) => { if region.as_var() == needle_fr { // Just grab the first character, the `&`. let source_map = self.infcx.tcx.sess.source_map(); @@ -631,7 +634,7 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { } // Otherwise, let's descend into the referent types. - search_stack.push((*referent_ty, referent_hir_ty.ty)); + search_stack.push((*referent_ty, referent_hir_ty)); } // Match up something like `Foo<'1>` @@ -669,8 +672,8 @@ impl<'tcx> MirBorrowckCtxt<'_, '_, 'tcx> { search_stack.push((*elem_ty, elem_hir_ty)); } - (ty::RawPtr(mut_ty, _), hir::TyKind::Ptr(mut_hir_ty)) => { - search_stack.push((*mut_ty, mut_hir_ty.ty)); + (ty::RawPtr(inner_ty, _), hir::TyKind::Ptr(hir_ty, _)) => { + search_stack.push((*inner_ty, hir_ty)); } _ => { diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index 5cfce366bbb23..4f4ed83be06a3 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -2896,14 +2896,6 @@ impl fmt::Display for YieldSource { } } -// N.B., if you change this, you'll probably want to change the corresponding -// type structure in middle/ty.rs as well. -#[derive(Debug, Clone, Copy, StableHash)] -pub struct MutTy<'hir> { - pub ty: &'hir Ty<'hir>, - pub mutbl: Mutability, -} - /// Represents a function's signature in a trait declaration, /// trait implementation, or a free function. #[derive(Debug, Clone, Copy, StableHash)] @@ -3234,7 +3226,7 @@ impl<'hir> Ty<'hir> { impl<'hir> Ty<'hir, AmbigArg> { pub fn peel_refs(&self) -> &Ty<'hir> { let mut final_ty = self.as_unambig_ty(); - while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, ty, _) = &final_ty.kind { final_ty = ty; } final_ty @@ -3244,7 +3236,7 @@ impl<'hir> Ty<'hir, AmbigArg> { impl<'hir> Ty<'hir> { pub fn peel_refs(&self) -> &Self { let mut final_ty = self; - while let TyKind::Ref(_, MutTy { ty, .. }) = &final_ty.kind { + while let TyKind::Ref(_, ty, _) = &final_ty.kind { final_ty = ty; } final_ty @@ -3308,7 +3300,7 @@ impl<'hir> Ty<'hir> { ty.is_suggestable_infer_ty() || matches!(length.kind, ConstArgKind::Infer(..)) } TyKind::Tup(tys) => tys.iter().any(Self::is_suggestable_infer_ty), - TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => mut_ty.ty.is_suggestable_infer_ty(), + TyKind::Ptr(ty, _) | TyKind::Ref(_, ty, _) => ty.is_suggestable_infer_ty(), TyKind::Path(QPath::TypeRelative(ty, segment)) => { ty.is_suggestable_infer_ty() || are_suggestable_generic_args(segment.args().args) } @@ -3577,9 +3569,9 @@ pub enum TyKind<'hir, Unambig = ()> { /// A fixed length array (i.e., `[T; n]`). Array(&'hir Ty<'hir>, &'hir ConstArg<'hir>), /// A raw pointer (i.e., `*const T` or `*mut T`). - Ptr(MutTy<'hir>), + Ptr(&'hir Ty<'hir>, Mutability), /// A reference (i.e., `&'a T` or `&'a mut T`). - Ref(&'hir Lifetime, MutTy<'hir>), + Ref(&'hir Lifetime, &'hir Ty<'hir>, Mutability), /// A function pointer (e.g., `fn(usize) -> bool`). FnPtr(&'hir FnPtrTy<'hir>), /// An unsafe binder type (e.g. `unsafe<'a> Foo<'a>`). diff --git a/compiler/rustc_hir/src/hir/tests.rs b/compiler/rustc_hir/src/hir/tests.rs index 2ac33a369cbdd..d267533ea3cb1 100644 --- a/compiler/rustc_hir/src/hir/tests.rs +++ b/compiler/rustc_hir/src/hir/tests.rs @@ -21,7 +21,7 @@ macro_rules! define_tests { define_tests! { cast_never TyKind Never {} cast_tup TyKind Tup { 0: &[Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }] } - cast_ptr TyKind Ptr { 0: MutTy { ty: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, mutbl: Mutability::Not }} + cast_ptr TyKind Ptr { 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, 1: Mutability::Not } cast_array TyKind Array { 0: &Ty { span: DUMMY_SP, hir_id: HirId::INVALID, kind: TyKind::Never }, 1: &ConstArg { diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs index 5b7555cd73938..ad96fe492e6e7 100644 --- a/compiler/rustc_hir/src/intravisit.rs +++ b/compiler/rustc_hir/src/intravisit.rs @@ -1027,10 +1027,10 @@ pub fn walk_ty<'v, V: Visitor<'v>>(visitor: &mut V, typ: &'v Ty<'v, AmbigArg>) - match *kind { TyKind::Slice(ref ty) => try_visit!(visitor.visit_ty_unambig(ty)), - TyKind::Ptr(ref mutable_type) => try_visit!(visitor.visit_ty_unambig(mutable_type.ty)), - TyKind::Ref(ref lifetime, ref mutable_type) => { + TyKind::Ptr(ref ty, _) => try_visit!(visitor.visit_ty_unambig(ty)), + TyKind::Ref(ref lifetime, ref ty, _) => { try_visit!(visitor.visit_lifetime(lifetime)); - try_visit!(visitor.visit_ty_unambig(mutable_type.ty)); + try_visit!(visitor.visit_ty_unambig(ty)); } TyKind::Never => {} TyKind::Tup(tuple_element_types) => { diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index 6546e2bf322c0..4d685ec3c6810 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -130,14 +130,14 @@ fn first_explicit_lifetime_span_in_ambig_ty(ty: &hir::Ty<'_, hir::AmbigArg>) -> fn first_explicit_lifetime_span_in_ty(ty: &hir::Ty<'_>) -> Option { match ty.kind { - hir::TyKind::Ref(lifetime, mut_ty) => first_explicit_lifetime_span(lifetime) - .or_else(|| first_explicit_lifetime_span_in_ty(mut_ty.ty)), + hir::TyKind::Ref(lifetime, ty, _) => first_explicit_lifetime_span(lifetime) + .or_else(|| first_explicit_lifetime_span_in_ty(ty)), hir::TyKind::Slice(ty) | hir::TyKind::Array(ty, _) | hir::TyKind::Pat(ty, _) | hir::TyKind::FieldOf(ty, _) | hir::TyKind::View(ty, _) => first_explicit_lifetime_span_in_ty(ty), - hir::TyKind::Ptr(mut_ty) => first_explicit_lifetime_span_in_ty(mut_ty.ty), + hir::TyKind::Ptr(ty, _) => first_explicit_lifetime_span_in_ty(ty), hir::TyKind::Tup(tys) => tys.iter().find_map(first_explicit_lifetime_span_in_ty), hir::TyKind::Path(qpath) => first_explicit_lifetime_span_in_qpath(qpath), hir::TyKind::TraitObject(bounds, lifetime) => bounds diff --git a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs index a6cc61d2f7bfe..1dc6c1c96e93e 100644 --- a/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs +++ b/compiler/rustc_hir_analysis/src/collect/resolve_bound_vars.rs @@ -808,13 +808,13 @@ impl<'a, 'tcx> Visitor<'tcx> for BoundVarContext<'a, 'tcx> { LifetimeKind::Error(..) => {} } } - hir::TyKind::Ref(lifetime_ref, ref mt) => { + hir::TyKind::Ref(lifetime_ref, ref inner_ty, _) => { self.visit_lifetime(lifetime_ref); let scope = Scope::ObjectLifetimeDefault { lifetime: self.rbv.defs.get(&lifetime_ref.hir_id.local_id).copied(), s: self.scope, }; - self.with(scope, |this| this.visit_ty_unambig(mt.ty)); + self.with(scope, |this| this.visit_ty_unambig(inner_ty)); } hir::TyKind::TraitAscription(bounds) => { let scope = Scope::TraitRefBoundary { s: self.scope }; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e9dc2a61d698d..fe9a496f1200f 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3195,12 +3195,12 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { let result_ty = match &hir_ty.kind { hir::TyKind::InferDelegation(infer) => self.lower_delegation_ty(*infer), hir::TyKind::Slice(ty) => Ty::new_slice(tcx, self.lower_ty(ty)), - hir::TyKind::Ptr(mt) => Ty::new_ptr(tcx, self.lower_ty(mt.ty), mt.mutbl), - hir::TyKind::Ref(region, mt) => { + hir::TyKind::Ptr(ty, mutbl) => Ty::new_ptr(tcx, self.lower_ty(ty), *mutbl), + hir::TyKind::Ref(region, ty, mutbl) => { let r = self.lower_lifetime(region, RegionInferReason::Reference); debug!(?r); - let t = self.lower_ty(mt.ty); - Ty::new_ref(tcx, r, t, mt.mutbl) + let t = self.lower_ty(ty); + Ty::new_ref(tcx, r, t, *mutbl) } hir::TyKind::Never => tcx.types.never, hir::TyKind::Tup(fields) => { diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs index ea2735a2a70c0..d8c57bfbdb56b 100644 --- a/compiler/rustc_hir_pretty/src/lib.rs +++ b/compiler/rustc_hir_pretty/src/lib.rs @@ -396,14 +396,16 @@ impl<'a> State<'a> { self.print_type(ty); self.word("]"); } - hir::TyKind::Ptr(ref mt) => { + hir::TyKind::Ptr(ref ty, mutbl) => { self.word("*"); - self.print_mt(mt, true); + self.print_mutability(mutbl, true); + self.print_type(ty); } - hir::TyKind::Ref(lifetime, ref mt) => { + hir::TyKind::Ref(lifetime, ref ty, mutbl) => { self.word("&"); self.print_opt_lifetime(lifetime); - self.print_mt(mt, false); + self.print_mutability(mutbl, false); + self.print_type(ty); } hir::TyKind::Never => { self.word("!"); @@ -2568,11 +2570,6 @@ impl<'a> State<'a> { } } - fn print_mt(&mut self, mt: &hir::MutTy<'_>, print_const: bool) { - self.print_mutability(mt.mutbl, print_const); - self.print_type(mt.ty); - } - fn print_fn_output(&mut self, decl: &hir::FnDecl<'_>) { match decl.output { hir::FnRetTy::Return(ty) => { diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs index 11fe876209ef2..76eba93213608 100644 --- a/compiler/rustc_hir_typeck/src/demand.rs +++ b/compiler/rustc_hir_typeck/src/demand.rs @@ -894,18 +894,18 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { .inputs .iter() .filter_map(|ty| match ty.kind { - hir::TyKind::Ref(lt, mut_ty) if ty.span == *ty_span => Some((lt, mut_ty)), + hir::TyKind::Ref(lt, inner_ty, mutbl) if ty.span == *ty_span => Some((lt, inner_ty, mutbl)), _ => None, }) .next() { - let mut sugg = if ty_ref.1.mutbl.is_mut() { + let mut sugg = if ty_ref.2.is_mut() { // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028). vec![] } else { // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` vec![( - ty_ref.1.ty.span.shrink_to_lo(), + ty_ref.1.span.shrink_to_lo(), format!("{}mut ", if ty_ref.0.ident.span.is_empty() { "" } else { " " },), )] }; diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs index 86bc6eeebc189..6f4d5bd6c90fe 100644 --- a/compiler/rustc_hir_typeck/src/method/suggest.rs +++ b/compiler/rustc_hir_typeck/src/method/suggest.rs @@ -456,11 +456,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { && let hir::Node::Param(p) = self.tcx.parent_hir_node(b.hir_id) && let Some(decl) = self.tcx.parent_hir_node(p.hir_id).fn_decl() && let Some(ty) = decl.inputs.iter().find(|ty| ty.span == p.ty_span) - && let hir::TyKind::Ref(_, mut_ty) = &ty.kind - && let hir::Mutability::Not = mut_ty.mutbl + && let hir::TyKind::Ref(_, inner_ty, hir::Mutability::Not) = &ty.kind { err.span_suggestion_verbose( - mut_ty.ty.span.shrink_to_lo(), + inner_ty.span.shrink_to_lo(), msg, "mut ", Applicability::MachineApplicable, diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 69ac09e650c16..2a6ed40c096be 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -2649,7 +2649,7 @@ impl<'tcx> LateLintPass<'tcx> for DerefNullPtr { match &expr.kind { hir::ExprKind::Cast(expr, ty) => { - if let hir::TyKind::Ptr(_) = ty.kind { + if let hir::TyKind::Ptr(..) = ty.kind { return is_zero(expr) || is_null_ptr(cx, expr); } } diff --git a/compiler/rustc_lint/src/dangling.rs b/compiler/rustc_lint/src/dangling.rs index d06292d62730f..dbe20dbef3c87 100644 --- a/compiler/rustc_lint/src/dangling.rs +++ b/compiler/rustc_lint/src/dangling.rs @@ -101,7 +101,7 @@ impl<'tcx> LateLintPass<'tcx> for DanglingPointers { DanglingPointerSearcher { cx, inside_call_args: false }.visit_body(body); if let FnRetTy::Return(ret_ty) = &fn_decl.output - && let TyKind::Ptr(_) = ret_ty.kind + && let TyKind::Ptr(..) = ret_ty.kind { // get the return type of the function or closure let ty = match cx.tcx.type_of(def_id).instantiate_identity().skip_norm_wip().kind() { diff --git a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs index 5ecc4d4b07548..71d81e4512ca2 100644 --- a/compiler/rustc_lint/src/disallowed_pass_by_ref.rs +++ b/compiler/rustc_lint/src/disallowed_pass_by_ref.rs @@ -23,7 +23,7 @@ declare_lint_pass!(DisallowedPassByRef => [DISALLOWED_PASS_BY_REF]); impl<'tcx> LateLintPass<'tcx> for DisallowedPassByRef { fn check_ty(&mut self, cx: &LateContext<'_>, ty: &'tcx hir::Ty<'tcx, AmbigArg>) { match &ty.kind { - TyKind::Ref(_, hir::MutTy { ty: inner_ty, mutbl: hir::Mutability::Not }) => { + TyKind::Ref(_, inner_ty, hir::Mutability::Not) => { if cx.tcx.trait_impl_of_assoc(ty.hir_id.owner.to_def_id()).is_some() { return; } diff --git a/compiler/rustc_lint/src/lifetime_syntax.rs b/compiler/rustc_lint/src/lifetime_syntax.rs index 208965ede2c73..ea09ce79fd49d 100644 --- a/compiler/rustc_lint/src/lifetime_syntax.rs +++ b/compiler/rustc_lint/src/lifetime_syntax.rs @@ -564,8 +564,8 @@ impl<'tcx> Info<'tcx> { // FIXME: Ideally, we'd also remove the lifetime declaration. fn removing_span(&self) -> Span { let mut span = self.lifetime.ident.span; - if let hir::TyKind::Ref(_, mut_ty) = self.ty.kind { - span = span.until(mut_ty.ty.span); + if let hir::TyKind::Ref(_, ty, _) = self.ty.kind { + span = span.until(ty.span); } span } diff --git a/compiler/rustc_lint/src/ptr_nulls.rs b/compiler/rustc_lint/src/ptr_nulls.rs index 0c4dba0893fc4..c231bd4cc3b30 100644 --- a/compiler/rustc_lint/src/ptr_nulls.rs +++ b/compiler/rustc_lint/src/ptr_nulls.rs @@ -86,7 +86,7 @@ fn useless_check<'a, 'tcx: 'a>( return Some(UselessPtrNullChecksDiag::FnRet { fn_name }); } e = if let ExprKind::Cast(expr, t) = e.kind - && let TyKind::Ptr(_) = t.kind + && let TyKind::Ptr(..) = t.kind { had_at_least_one_cast = true; expr diff --git a/compiler/rustc_lint/src/raw_borrows_via_references.rs b/compiler/rustc_lint/src/raw_borrows_via_references.rs index 4db8f2a243678..74ab9ee39fadc 100644 --- a/compiler/rustc_lint/src/raw_borrows_via_references.rs +++ b/compiler/rustc_lint/src/raw_borrows_via_references.rs @@ -54,7 +54,7 @@ impl<'tcx> LateLintPass<'tcx> for RawBorrowsViaReferences { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &Expr<'_>) { if let ExprKind::Cast(exp, ty) = expr.kind && let ExprKind::AddrOf(BorrowKind::Ref, mutbl, addr_of_exp) = exp.kind - && let TyKind::Ptr(_) = ty.kind + && let TyKind::Ptr(..) = ty.kind && addr_of_exp.is_syntactic_place_expr() { let suggestion = if let Some(borrow_span) = diff --git a/compiler/rustc_mir_transform/src/liveness.rs b/compiler/rustc_mir_transform/src/liveness.rs index 5a7e9d3e5d0a7..7725daa276cc6 100644 --- a/compiler/rustc_mir_transform/src/liveness.rs +++ b/compiler/rustc_mir_transform/src/liveness.rs @@ -293,7 +293,7 @@ fn annotate_mut_binding_to_immutable_binding<'tcx>( local.as_usize() - if tcx.is_closure_like(body_def_id.to_def_id()) { 2 } else { 1 }; let fn_decl = tcx.hir_node_by_def_id(body_def_id).fn_decl()?; let ty = fn_decl.inputs[hir_param_index]; - let hir::TyKind::Ref(lt, mut_ty) = ty.kind else { return None }; + let hir::TyKind::Ref(lt, inner_ty, mutbl) = ty.kind else { return None }; // ... as a binding pattern. let hir_body = tcx.hir_maybe_body_owned_by(body_def_id)?; @@ -312,12 +312,12 @@ fn annotate_mut_binding_to_immutable_binding<'tcx>( // Changes to the parameter's type. let pre = if lt.ident.span.is_empty() { "" } else { " " }; - let ty_span = if mut_ty.mutbl.is_mut() { + let ty_span = if mutbl.is_mut() { // Leave `&'name mut Ty` and `&mut Ty` as they are (#136028). None } else { // `&'name Ty` -> `&'name mut Ty` or `&Ty` -> `&mut Ty` - Some(mut_ty.ty.span.shrink_to_lo()) + Some(inner_ty.span.shrink_to_lo()) }; return Some(diagnostics::UnusedAssignSuggestion { diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 80ffbba041ccd..09689af889799 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -2023,7 +2023,7 @@ pub fn impl_trait_overcapture_suggestion<'tcx>( ("(", ")") } Node::Ty(ty) => match ty.kind { - rustc_hir::TyKind::Ptr(_) | rustc_hir::TyKind::Ref(..) => ("(", ")"), + rustc_hir::TyKind::Ptr(..) | rustc_hir::TyKind::Ref(..) => ("(", ")"), // FIXME: RPITs are not allowed to be nested in `impl Fn() -> ...`, // but we eventually could support that, and that would necessitate // making this more sophisticated. diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs index e88038528189e..7079dd39fe64d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/find_anon_type.rs @@ -90,7 +90,7 @@ impl<'tcx> Visitor<'tcx> for FindNestedTypeVisitor<'tcx> { } } - hir::TyKind::Ref(lifetime, _) => { + hir::TyKind::Ref(lifetime, ..) => { // the lifetime of the Ref let hir_id = lifetime.hir_id; match self.tcx.named_bound_var(hir_id) { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 03baa5c2acbfb..8a14ad3a9c675 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -268,9 +268,9 @@ impl<'tcx> Visitor<'tcx> for TypeParamSpanVisitor<'tcx> { fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx, AmbigArg>) { match arg.kind { - hir::TyKind::Ref(_, ref mut_ty) => { + hir::TyKind::Ref(_, ref ty, _) => { // We don't want to suggest looking into borrowing `&T` or `&Self`. - if let Some(ambig_ty) = mut_ty.ty.try_as_ambig_ty() { + if let Some(ambig_ty) = ty.try_as_ambig_ty() { walk_ty(self, ambig_ty); } return; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index ff9db46445135..47d2b7a8c98d5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -2272,9 +2272,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // Skipping binder here, remapping below let mut suggested_ty = trait_pred.self_ty().skip_binder(); if let Some(mut hir_ty) = expr_finder.ty_result { - while let hir::TyKind::Ref(_, mut_ty) = &hir_ty.kind { + while let hir::TyKind::Ref(_, ref_ty, _) = &hir_ty.kind { count += 1; - let span = hir_ty.span.until(mut_ty.ty.span); + let span = hir_ty.span.until(ref_ty.span); suggestions.push((span, String::new())); let ty::Ref(_, inner_ty, _) = suggested_ty.kind() else { @@ -2282,7 +2282,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { }; suggested_ty = *inner_ty; - hir_ty = mut_ty.ty; + hir_ty = ref_ty; if maybe_suggest(suggested_ty, count, suggestions.clone()) { return true; @@ -2311,9 +2311,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { fn suggest_remove_ref_from_param(&self, param: &hir::Param<'_>, err: &mut Diag<'_>) -> bool { if let Some(decl) = self.tcx.parent_hir_node(param.hir_id).fn_decl() && let Some(input_ty) = decl.inputs.iter().find(|t| param.ty_span.contains(t.span)) - && let hir::TyKind::Ref(_, mut_ty) = input_ty.kind + && let hir::TyKind::Ref(_, ty, _) = input_ty.kind { - let ref_span = input_ty.span.until(mut_ty.ty.span); + let ref_span = input_ty.span.until(ty.span); match self.tcx.sess.source_map().span_to_snippet(ref_span) { Ok(snippet) if snippet.starts_with("&") => { err.span_suggestion_verbose( @@ -6830,11 +6830,11 @@ fn hint_missing_borrow<'tcx>( let mut span = arg.span.shrink_to_lo(); let mut left = found_refs.len() - expected_refs.len(); let mut ty = arg; - while let hir::TyKind::Ref(_, mut_ty) = &ty.kind + while let hir::TyKind::Ref(_, inner_ty, _) = &ty.kind && left > 0 { - span = span.with_hi(mut_ty.ty.span.lo()); - ty = mut_ty.ty; + span = span.with_hi(inner_ty.span.lo()); + ty = inner_ty; left -= 1; } if left == 0 { @@ -7304,7 +7304,7 @@ impl<'v> Visitor<'v> for FindTypeParam { // and suggest `T: ?Sized` regardless of their obligations. This is fine because the errors // in that case should make what happened clear enough. match ty.kind { - hir::TyKind::Ptr(_) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {} + hir::TyKind::Ptr(..) | hir::TyKind::Ref(..) | hir::TyKind::TraitObject(..) => {} hir::TyKind::Path(hir::QPath::Resolved(None, path)) if let [segment] = path.segments && segment.ident.name == self.param => diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index c598e0ef8a8bd..449f349aaf886 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -526,10 +526,10 @@ fn virtual_call_violations_for_method<'tcx>( { // If we have `self: &'a Ty`, get `'a`, so that we can suggest `&'a self`. let lt = match sig.decl.inputs[0].kind { - hir::TyKind::Ref(lt, _) if lt.ident.name == kw::UnderscoreLifetime => { + hir::TyKind::Ref(lt, ..) if lt.ident.name == kw::UnderscoreLifetime => { sym::empty } - hir::TyKind::Ref(lt, _) => lt.ident.name, + hir::TyKind::Ref(lt, ..) => lt.ident.name, _ => sym::empty, }; // Get the `Span` for all of `self: Ty`, not just `Ty`. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9b3c3d01557e0..09dbd279988f6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -1927,10 +1927,10 @@ pub(crate) fn clean_ty<'tcx>(ty: &hir::Ty<'_>, cx: &mut DocContext<'tcx>) -> Typ match ty.kind { TyKind::Never => Primitive(PrimitiveType::Never), - TyKind::Ptr(ref m) => RawPointer(m.mutbl, Box::new(clean_ty(m.ty, cx))), - TyKind::Ref(l, ref m) => { + TyKind::Ptr(inner_ty, mutbl) => RawPointer(mutbl, Box::new(clean_ty(inner_ty, cx))), + TyKind::Ref(l, inner_ty, mutbl) => { let lifetime = if l.is_anonymous() { None } else { Some(clean_lifetime(l, cx)) }; - BorrowedRef { lifetime, mutability: m.mutbl, type_: Box::new(clean_ty(m.ty, cx)) } + BorrowedRef { lifetime, mutability: mutbl, type_: Box::new(clean_ty(inner_ty, cx)) } } TyKind::Slice(ty) => Slice(Box::new(clean_ty(ty, cx))), TyKind::Pat(inner_ty, pat) => { diff --git a/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs b/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs index 3ab6693756f5a..63df64f4edb57 100644 --- a/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs +++ b/src/tools/clippy/clippy_lints/src/casts/as_pointer_underscore.rs @@ -3,7 +3,7 @@ use rustc_lint::LateContext; use rustc_middle::ty::Ty; pub fn check<'tcx>(cx: &LateContext<'tcx>, ty_into: Ty<'_>, cast_to_hir: &'tcx rustc_hir::Ty<'tcx>) { - if let rustc_hir::TyKind::Ptr(rustc_hir::MutTy { ty, .. }) = cast_to_hir.kind + if let rustc_hir::TyKind::Ptr(ty, _) = cast_to_hir.kind && matches!(ty.kind, rustc_hir::TyKind::Infer(())) { clippy_utils::diagnostics::span_lint_and_sugg( diff --git a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs index cb9f7f618d7f9..3db972278a8ad 100644 --- a/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/borrow_as_ptr.rs @@ -18,8 +18,8 @@ pub(super) fn check<'tcx>( cast_to: &'tcx Ty<'_>, msrv: Msrv, ) -> bool { - if let TyKind::Ptr(target) = cast_to.kind - && !matches!(target.ty.kind, TyKind::TraitObject(..)) + if let TyKind::Ptr(target, _) = cast_to.kind + && !matches!(target.kind, TyKind::TraitObject(..)) && let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind && !is_lint_allowed(cx, BORROW_AS_PTR, expr.hir_id) // Fix #9884 diff --git a/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs index 2b1b3c1b96fd3..030a22755cfd6 100644 --- a/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -11,21 +11,21 @@ use rustc_span::Spanned; use super::MANUAL_DANGLING_PTR; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) { - if let TyKind::Ptr(ref ptr_ty) = to.kind { + if let TyKind::Ptr(ref ptr_ty, mutbl) = to.kind { let init_expr = expr_or_init(cx, from); - if is_expr_const_aligned(cx, init_expr, ptr_ty.ty) + if is_expr_const_aligned(cx, init_expr, ptr_ty) && let Some(std_or_core) = std_or_core(cx) - && let pointee_ty = cx.typeck_results().node_type(ptr_ty.ty.hir_id) + && let pointee_ty = cx.typeck_results().node_type(ptr_ty.hir_id) && pointee_ty.is_sized(cx.tcx, cx.typing_env()) { - let sugg_fn = match ptr_ty.mutbl { + let sugg_fn = match mutbl { Mutability::Not => "ptr::dangling", Mutability::Mut => "ptr::dangling_mut", }; - let sugg = if let TyKind::Infer(()) = ptr_ty.ty.kind { + let sugg = if let TyKind::Infer(()) = ptr_ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = ptr_ty.ty.span.get_text(cx) { + } else if let Some(mut_ty_snip) = ptr_ty.span.get_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs index 61fe563512b60..bee8478a7bcc8 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_as_ptr.rs @@ -47,13 +47,13 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir.kind { TyKind::Infer(()) => String::new(), - TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer(())) { + TyKind::Ptr(inner_ty, _) => { + if matches!(inner_ty.kind, TyKind::Infer(())) { String::new() } else { format!( "::<{}>", - snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) + snippet_with_applicability(cx, inner_ty.span, "/* type */", &mut app) ) } }, diff --git a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs index 5f20efe2e3646..6107a0cb363d0 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ptr_cast_constness.rs @@ -52,8 +52,8 @@ pub(super) fn check<'tcx>( if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS) { let mut app = Applicability::MachineApplicable; let sugg = if let ExprKind::Cast(nested_from, nested_hir_ty) = cast_from_expr.kind - && let hir::TyKind::Ptr(ptr_ty) = nested_hir_ty.kind - && let hir::TyKind::Infer(()) = ptr_ty.ty.kind + && let hir::TyKind::Ptr(inner_ty, _) = nested_hir_ty.kind + && let hir::TyKind::Infer(()) = inner_ty.kind { // `(foo as *const _).cast_mut()` fails method name resolution // avoid this by `as`-ing the full type diff --git a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs index b850f7f41ed33..0e69445caf5f4 100644 --- a/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/ref_as_ptr.rs @@ -44,13 +44,13 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { TyKind::Infer(()) => String::new(), - TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer(())) { + TyKind::Ptr(inner_ty, _) => { + if matches!(inner_ty.kind, TyKind::Infer(())) { String::new() } else { format!( "::<{}>", - snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) + snippet_with_applicability(cx, inner_ty.span, "/* type */", &mut app) ) } }, diff --git a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs index c98fa1a5cba74..0b2ba1428b53a 100644 --- a/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs +++ b/src/tools/clippy/clippy_lints/src/casts/unnecessary_cast.rs @@ -35,13 +35,13 @@ pub(super) fn check<'tcx>( // Ignore casts to e.g. type aliases and infer types // - p as pointer_alias // - p as _ - && let TyKind::Ptr(to_pointee) = cast_to_hir.kind + && let TyKind::Ptr(to_pointee, _) = cast_to_hir.kind { - match to_pointee.ty.kind { + match to_pointee.kind { // Ignore casts to pointers that are aliases or cfg dependant, e.g. // - p as *const std::ffi::c_char (alias) // - p as *const std::os::raw::c_char (cfg dependant) - TyKind::Path(qpath) if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) => { + TyKind::Path(qpath) if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee) => { return false; }, // Ignore `p as *const _` diff --git a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs index 7f63a7336b1b0..8eba292d6fb99 100644 --- a/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs +++ b/src/tools/clippy/clippy_lints/src/casts/zero_ptr.rs @@ -9,19 +9,19 @@ use rustc_lint::LateContext; use super::ZERO_PTR; pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>, msrv: Msrv) { - if let TyKind::Ptr(ref mut_ty) = to.kind + if let TyKind::Ptr(ref ty, mutbl) = to.kind && is_integer_literal(from, 0) && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::PTR_NULL)) && let Some(std_or_core) = std_or_core(cx) { - let (msg, sugg_fn) = match mut_ty.mutbl { + let (msg, sugg_fn) = match mutbl { Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"), Mutability::Not => ("`0 as *const _` detected", "ptr::null"), }; - let sugg = if let TyKind::Infer(()) = mut_ty.ty.kind { + let sugg = if let TyKind::Infer(()) = ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_text(cx) { + } else if let Some(mut_ty_snip) = ty.span.get_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/src/tools/clippy/clippy_lints/src/dereference.rs b/src/tools/clippy/clippy_lints/src/dereference.rs index 50017eec7cf65..fa544da1ba3bd 100644 --- a/src/tools/clippy/clippy_lints/src/dereference.rs +++ b/src/tools/clippy/clippy_lints/src/dereference.rs @@ -853,14 +853,14 @@ impl TyCoercionStability { // Here `y1` and `y2` would resolve to different types, so the type `&Box<_>` is not stable when // switching to auto-dereferencing. fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self { - let TyKind::Ref(_, ty) = &ty.kind else { + let TyKind::Ref(_, ty, _) = &ty.kind else { return Self::None; }; let mut ty = ty; loop { - break match ty.ty.kind { - TyKind::Ref(_, ref ref_ty) => { + break match ty.kind { + TyKind::Ref(_, ref ref_ty, _) => { ty = ref_ty; continue; }, @@ -887,7 +887,7 @@ impl TyCoercionStability { }, TyKind::Slice(_) | TyKind::Array(..) - | TyKind::Ptr(_) + | TyKind::Ptr(..) | TyKind::FnPtr(_) | TyKind::Pat(..) | TyKind::FieldOf(..) diff --git a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs index 1afec00f94792..733f10b3506f8 100644 --- a/src/tools/clippy/clippy_lints/src/functions/ref_option.rs +++ b/src/tools/clippy/clippy_lints/src/functions/ref_option.rs @@ -16,7 +16,7 @@ fn check_ty<'a>(cx: &LateContext<'a>, param: &hir::Ty<'a>, param_ty: Ty<'a>, fix && let Some(gen_ty) = option_arg_ty(cx, *opt_ty) && !gen_ty.is_ref() // Need to gen the original spans, so first parsing mid, and hir parsing afterward - && let hir::TyKind::Ref(lifetime, hir::MutTy { ty, .. }) = param.kind + && let hir::TyKind::Ref(lifetime, ty, ..) = param.kind && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let (Some(first), Some(last)) = (path.segments.first(), path.segments.last()) && let Some(hir::GenericArgs { diff --git a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs index 3c49595f83216..771cdc1e47136 100644 --- a/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs +++ b/src/tools/clippy/clippy_lints/src/iter_without_into_iter.rs @@ -126,7 +126,7 @@ fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { impl LateLintPass<'_> for IterWithoutIntoIter { fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { if let ItemKind::Impl(imp) = item.kind - && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind + && let TyKind::Ref(_, self_ty_without_ref, _) = &imp.self_ty.kind && let Some(of_trait) = imp.of_trait && of_trait .trait_ref @@ -178,7 +178,7 @@ impl {self_ty_without_ref} {{ }} }} ", - self_ty_without_ref = snippet(cx, self_ty_without_ref.ty.span, ".."), + self_ty_without_ref = snippet(cx, self_ty_without_ref.span, ".."), ref_self = mtbl.ref_prefix_str(), iter_ty = snippet(cx, iter_assoc_span, ".."), ); diff --git a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs index 5e65c0f6f0c67..24bd9a2f1418d 100644 --- a/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs +++ b/src/tools/clippy/clippy_lints/src/methods/needless_collect.rs @@ -262,7 +262,7 @@ fn ty_is_fully_concrete(ty: &rustc_hir::Ty<'_>) -> bool { seg.args .is_none_or(|a| a.args.iter().all(generic_arg_is_fully_concrete)) }), - rustc_hir::TyKind::Ref(_, mut_ty) => ty_is_fully_concrete(mut_ty.ty), + rustc_hir::TyKind::Ref(_, ty, _) => ty_is_fully_concrete(ty), rustc_hir::TyKind::Slice(ty) | rustc_hir::TyKind::Array(ty, _) => ty_is_fully_concrete(ty), rustc_hir::TyKind::Tup(tys) => tys.iter().all(ty_is_fully_concrete), _ => true, diff --git a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs index 9e0d630461915..c233fe3f28ed5 100644 --- a/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs +++ b/src/tools/clippy/clippy_lints/src/methods/should_implement_trait.rs @@ -149,7 +149,7 @@ impl OutType { (Self::Unit, &FnRetTy::Return(ty)) if is_unit(ty) => true, (Self::Bool, &FnRetTy::Return(ty)) if is_bool(ty) => true, (Self::Any, &FnRetTy::Return(ty)) if !is_unit(ty) => true, - (Self::Ref, &FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)), + (Self::Ref, &FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(..)), _ => false, } } diff --git a/src/tools/clippy/clippy_lints/src/mut_mut.rs b/src/tools/clippy/clippy_lints/src/mut_mut.rs index 3b83a9ecd55c2..640044e4d6e21 100644 --- a/src/tools/clippy/clippy_lints/src/mut_mut.rs +++ b/src/tools/clippy/clippy_lints/src/mut_mut.rs @@ -98,26 +98,26 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_, AmbigArg>) { - if let TyKind::Ref(_, base) = ty.kind - && base.mutbl.is_mut() + if let TyKind::Ref(_, base, base_mutbl) = ty.kind + && base_mutbl.is_mut() && let ctxt = ty.span.ctxt() - && ctxt == base.ty.span.ctxt() + && ctxt == base.span.ctxt() { - if self.skip_id.replace(base.ty.hir_id) == Some(ty.hir_id) { + if self.skip_id.replace(base.hir_id) == Some(ty.hir_id) { return; } - if let TyKind::Ref(_, mut base2) = base.ty.kind - && base2.mutbl.is_mut() + if let TyKind::Ref(_, mut base2, base2_mutbl) = base.kind + && base2_mutbl.is_mut() { - while let TyKind::Ref(_, next) = base2.ty.kind - && next.mutbl.is_mut() - && ctxt == base2.ty.span.ctxt() + while let TyKind::Ref(_, next, next_mutbl) = base2.kind + && next_mutbl.is_mut() + && ctxt == base2.span.ctxt() { base2 = next; } if !ctxt.in_external_macro(cx.tcx.sess.source_map()) - && let Some(sp) = walk_span_to_context(base2.ty.span, ctxt) + && let Some(sp) = walk_span_to_context(base2.span, ctxt) { span_lint_and_then( cx, @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { "multiple successive mutable references", |diag| { diag.span_suggestion_verbose( - base.ty.span.until(sp), + base.span.until(sp), "use only a single mutable reference", "", Applicability::MaybeIncorrect, diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs index 5c6030d61f5f0..ce5040372c3cc 100644 --- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -266,9 +266,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { for input in unused { // If the argument is never used mutably, we emit the warning. let sp = input.span; - if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind { + if let rustc_hir::TyKind::Ref(_, inner_ty, _) = input.kind { let Some(after_mut_span) = cx.tcx.sess.source_map().span_extend_to_prev_str( - inner_ty.ty.span.shrink_to_lo(), + inner_ty.span.shrink_to_lo(), "mut", true, true, diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 70b5adb0a7390..4c541ead3d395 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -11,7 +11,7 @@ use rustc_data_structures::unord::UnordItems; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; +use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf as _; @@ -171,7 +171,7 @@ impl PassByRefOrValue { if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size - && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind + && let hir::TyKind::Ref(_, decl_ty, ..) = input.kind { if let Some(typeck) = cx.typeck_results // Don't lint if a raw pointer is created. diff --git a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs index 6cf4c8586f340..bc0fac8684cf1 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/mut_from_ref.rs @@ -48,8 +48,8 @@ struct LifetimeVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for LifetimeVisitor<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) { - if let TyKind::Ref(lt, ref m) = ty.kind { - self.result.push((lt, Some(m.mutbl), ty.span)); + if let TyKind::Ref(lt, _, mutbl) = ty.kind { + self.result.push((lt, Some(mutbl), ty.span)); } hir::intravisit::walk_ty(self, ty); } diff --git a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs index 4242b7f1f3224..4ead93478a86d 100644 --- a/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs +++ b/src/tools/clippy/clippy_lints/src/ptr/ptr_arg.rs @@ -207,8 +207,8 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .filter_map(move |(i, (ty, hir_ty))| { if let ty::Ref(_, ty, mutability) = *ty.kind() && let ty::Adt(adt, args) = *ty.kind() - && let TyKind::Ref(lt, ref ty) = hir_ty.kind - && let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind + && let TyKind::Ref(lt, ref inner_ty, _) = hir_ty.kind + && let TyKind::Path(QPath::Resolved(None, path)) = inner_ty.kind // Check that the name as typed matches the actual name of the type. // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec` && let [.., name] = path.segments diff --git a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs index b98a4c6b8b9cb..1d0db5d1ebe36 100644 --- a/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs +++ b/src/tools/clippy/clippy_lints/src/redundant_type_annotations.rs @@ -154,9 +154,9 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { let mut ty_kind = &ty.kind; // If the annotation is a ref we "peel" it - if let hir::TyKind::Ref(_, mut_ty) = &ty.kind { + if let hir::TyKind::Ref(_, inner_ty, _) = &ty.kind { is_ref = true; - ty_kind = &mut_ty.ty.kind; + ty_kind = &inner_ty.kind; } if let hir::TyKind::Path(ty_path) = ty_kind @@ -204,8 +204,8 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { // We only lint if the type annotation is an array type (e.g. &[u8; 4]). // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we // don't lint. - if let hir::TyKind::Ref(_, mut_ty) = ty.kind - && matches!(mut_ty.ty.kind, hir::TyKind::Array(..)) + if let hir::TyKind::Ref(_, inner_ty, _) = ty.kind + && matches!(inner_ty.kind, hir::TyKind::Array(..)) { span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); } diff --git a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs index 013225da010d7..bade37ee8438a 100644 --- a/src/tools/clippy/clippy_lints/src/ref_option_ref.rs +++ b/src/tools/clippy/clippy_lints/src/ref_option_ref.rs @@ -36,9 +36,8 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { - if let TyKind::Ref(_, ref mut_ty) = ty.kind - && mut_ty.mutbl == Mutability::Not - && let TyKind::Path(qpath) = &mut_ty.ty.kind + if let TyKind::Ref(_, ref ref_ty, Mutability::Not) = ty.kind + && let TyKind::Path(qpath) = &ref_ty.kind && let last = last_path_segment(qpath) && let Some(def_id) = last.res.opt_def_id() && cx.tcx.is_diagnostic_item(sym::Option, def_id) @@ -48,8 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { GenericArg::Type(inner_ty) => Some(inner_ty), _ => None, }) - && let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind - && inner_mut_ty.mutbl == Mutability::Not + && let TyKind::Ref(_, _, Mutability::Not) = inner_ty.kind { span_lint_and_sugg( cx, diff --git a/src/tools/clippy/clippy_lints/src/trait_bounds.rs b/src/tools/clippy/clippy_lints/src/trait_bounds.rs index 39b2b71a0d56d..58d434dc18e7d 100644 --- a/src/tools/clippy/clippy_lints/src/trait_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/trait_bounds.rs @@ -178,8 +178,8 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { - if let TyKind::Ref(.., mut_ty) = &ty.kind - && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind + if let TyKind::Ref(_, inner_ty, _) = &ty.kind + && let TyKind::TraitObject(bounds, ..) = inner_ty.kind && bounds.len() > 2 { // Build up a hash of every trait we've seen diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 1edd7f8baea96..a68291f06d3dd 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -88,9 +88,9 @@ pub(super) fn check<'tcx>( /// Gets the type `Bar` in `…::transmute`. fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> { if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)? - && let TyKind::Ref(_, ty) = &ty.kind + && let TyKind::Ref(_, inner_ty, _) = &ty.kind { - Some(ty.ty) + Some(inner_ty) } else { None } diff --git a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs index 3dffc164f991a..3aa4224c0e766 100644 --- a/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs +++ b/src/tools/clippy/clippy_lints/src/types/borrowed_box.rs @@ -3,16 +3,22 @@ use clippy_utils::source::snippet; use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{ - self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind, + self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, Mutability, Node, QPath, TyKind, }; use rustc_lint::LateContext; use super::BORROWED_BOX; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, mut_ty: &MutTy<'_>) -> bool { +pub(super) fn check( + cx: &LateContext<'_>, + hir_ty: &hir::Ty<'_>, + lt: &Lifetime, + inner_ty: &hir::Ty<'_>, + mutbl: Mutability, +) -> bool { // Ignore `&mut Box` types; see issue #2907 for details. - if mut_ty.mutbl == Mutability::Not - && let TyKind::Path(ref qpath) = mut_ty.ty.kind + if mutbl == Mutability::Not + && let TyKind::Path(ref qpath) = inner_ty.kind && let QPath::Resolved(None, path) = *qpath && let Some(def_id) = path.res.opt_def_id() && Some(def_id) == cx.tcx.lang_items().owned_box() diff --git a/src/tools/clippy/clippy_lints/src/types/mod.rs b/src/tools/clippy/clippy_lints/src/types/mod.rs index 45388800be4b6..f62ca8075f96f 100644 --- a/src/tools/clippy/clippy_lints/src/types/mod.rs +++ b/src/tools/clippy/clippy_lints/src/types/mod.rs @@ -14,8 +14,8 @@ use clippy_config::Conf; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MutTy, QPath, TraitFn, - TraitItem, TraitItemKind, TyKind, + Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, QPath, TraitFn, TraitItem, + TraitItemKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::Span; @@ -664,13 +664,13 @@ impl Types { owned_cow::check(cx, qpath, def_id); } }, - TyKind::Ref(lt, ref mut_ty) => { + TyKind::Ref(lt, ref inner_ty, mutbl) => { context.is_nested_call = true; - if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { - self.check_ty(cx, mut_ty.ty, context); + if !borrowed_box::check(cx, hir_ty, lt, inner_ty, mutbl) { + self.check_ty(cx, inner_ty, context); } }, - TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => { + TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(ty, ..) => { context.is_nested_call = true; self.check_ty(cx, ty, context); }, diff --git a/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs b/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs index db920fad53b4e..59987ad7ad817 100644 --- a/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs +++ b/src/tools/clippy/clippy_lints/src/unnecessary_literal_bound.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, Lit, MutTy, Mutability, PrimTy, Ty, TyKind, intravisit}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, Lit, Mutability, PrimTy, Ty, TyKind, intravisit}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; @@ -55,7 +55,7 @@ declare_clippy_lint! { declare_lint_pass!(UnnecessaryLiteralBound => [UNNECESSARY_LITERAL_BOUND]); fn extract_anonymous_ref<'tcx>(hir_ty: &Ty<'tcx>) -> Option<&'tcx Ty<'tcx>> { - let TyKind::Ref(lifetime, MutTy { ty, mutbl }) = hir_ty.kind else { + let TyKind::Ref(lifetime, ty, mutbl) = hir_ty.kind else { return None; }; diff --git a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs index ca79f79403e7d..828fb1d3313b4 100644 --- a/src/tools/clippy/clippy_utils/src/check_proc_macro.rs +++ b/src/tools/clippy/clippy_utils/src/check_proc_macro.rs @@ -23,7 +23,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, BoundConstness, BoundPolarity, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, - MatchSource, MutTy, Node, PatExpr, PatExprKind, PatKind, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, + MatchSource, Node, PatExpr, PatExprKind, PatKind, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, TraitImplHeader, TraitItem, TraitItemKind, TraitRef, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; @@ -391,8 +391,8 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { match ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::Ptr(ty, ..) => (Pat::Str("*"), ty_search_pat(ty).1), + TyKind::Ref(_, ty, ..) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::FnPtr(fn_ptr) => ( if fn_ptr.safety.is_unsafe() { Pat::Str("unsafe") diff --git a/src/tools/clippy/clippy_utils/src/hir_utils.rs b/src/tools/clippy/clippy_utils/src/hir_utils.rs index 04ace1727c82c..4ef0a795b4766 100644 --- a/src/tools/clippy/clippy_utils/src/hir_utils.rs +++ b/src/tools/clippy/clippy_utils/src/hir_utils.rs @@ -903,9 +903,9 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (TyKind::Slice(l_vec), TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), (TyKind::Array(lt, ll), TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), - (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), - (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { - l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) + (TyKind::Ptr(l_ty, l_mutbl), TyKind::Ptr(r_ty, r_mutbl)) => l_mutbl == r_mutbl && self.eq_ty(l_ty, r_ty), + (TyKind::Ref(_, l_ty, l_mutbl), TyKind::Ref(_, r_ty, r_mutbl)) => { + l_mutbl == r_mutbl && self.eq_ty(l_ty, r_ty) }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), (TyKind::Tup(l), TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), @@ -1617,14 +1617,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } self.hash_name(field.name); }, - TyKind::Ptr(mut_ty) => { - self.hash_ty(mut_ty.ty); - mut_ty.mutbl.hash(&mut self.s); + TyKind::Ptr(ty, mutbl) => { + self.hash_ty(ty); + mutbl.hash(&mut self.s); }, - TyKind::Ref(lifetime, mut_ty) => { + TyKind::Ref(lifetime, ty, mutbl) => { self.hash_lifetime(lifetime); - self.hash_ty(mut_ty.ty); - mut_ty.mutbl.hash(&mut self.s); + self.hash_ty(ty); + mutbl.hash(&mut self.s); }, TyKind::FnPtr(fn_ptr) => { fn_ptr.safety.hash(&mut self.s); diff --git a/src/tools/clippy/clippy_utils/src/lib.rs b/src/tools/clippy/clippy_utils/src/lib.rs index 9fd934cac7ecf..7a155b5885a8c 100644 --- a/src/tools/clippy/clippy_utils/src/lib.rs +++ b/src/tools/clippy/clippy_utils/src/lib.rs @@ -2304,8 +2304,8 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) let mut count = 0; loop { match &ty.kind { - TyKind::Ref(_, ref_ty) => { - ty = ref_ty.ty; + TyKind::Ref(_, inner_ty, _) => { + ty = inner_ty; count += 1; }, _ => break (ty, count), @@ -2316,7 +2316,7 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) /// Returns the base type for HIR references and pointers. pub fn peel_hir_ty_refs_and_ptrs<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { match &ty.kind { - TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => peel_hir_ty_refs_and_ptrs(mut_ty.ty), + TyKind::Ptr(inner_ty, _) | TyKind::Ref(_, inner_ty, _) => peel_hir_ty_refs_and_ptrs(inner_ty), _ => ty, } } diff --git a/src/tools/clippy/clippy_utils/src/sugg.rs b/src/tools/clippy/clippy_utils/src/sugg.rs index d2045c1346ee5..d05ae0b5c45b5 100644 --- a/src/tools/clippy/clippy_utils/src/sugg.rs +++ b/src/tools/clippy/clippy_utils/src/sugg.rs @@ -8,7 +8,7 @@ use rustc_ast::util::parser::AssocOp; use rustc_ast::{UnOp, ast}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Closure, ExprKind, HirId, MatchSource, MutTy, Node, TyKind}; +use rustc_hir::{self as hir, Closure, ExprKind, HirId, MatchSource, Node, TyKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::hir::place::ProjectionKind; @@ -815,9 +815,8 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let closure_body = cx.tcx.hir_body(body); // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`) // a type annotation is present if param `kind` is different from `TyKind::Infer` - let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind - { - matches!(ty.kind, TyKind::Ref(_, MutTy { .. })) + let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, ty, ..) = fn_decl.inputs[0].kind { + matches!(ty.kind, TyKind::Ref(..)) } else { false }; From e281ce20dea9d809cab78e35ec70cd51b64c0153 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 28 Sep 2026 07:35:44 +0000 Subject: [PATCH 0940/1309] remove `hir::MutTy` --- .../src/casts/as_pointer_underscore.rs | 2 +- clippy_lints/src/casts/borrow_as_ptr.rs | 4 ++-- clippy_lints/src/casts/manual_dangling_ptr.rs | 12 +++++----- clippy_lints/src/casts/ptr_as_ptr.rs | 6 ++--- clippy_lints/src/casts/ptr_cast_constness.rs | 4 ++-- clippy_lints/src/casts/ref_as_ptr.rs | 6 ++--- clippy_lints/src/casts/unnecessary_cast.rs | 6 ++--- clippy_lints/src/casts/zero_ptr.rs | 8 +++---- clippy_lints/src/dereference.rs | 8 +++---- clippy_lints/src/functions/ref_option.rs | 2 +- clippy_lints/src/iter_without_into_iter.rs | 4 ++-- clippy_lints/src/methods/needless_collect.rs | 2 +- .../src/methods/should_implement_trait.rs | 2 +- clippy_lints/src/mut_mut.rs | 22 +++++++++---------- clippy_lints/src/needless_pass_by_ref_mut.rs | 4 ++-- clippy_lints/src/pass_by_ref_or_value.rs | 4 ++-- clippy_lints/src/ptr/mut_from_ref.rs | 4 ++-- clippy_lints/src/ptr/ptr_arg.rs | 4 ++-- .../src/redundant_type_annotations.rs | 8 +++---- clippy_lints/src/ref_option_ref.rs | 8 +++---- clippy_lints/src/trait_bounds.rs | 4 ++-- .../src/transmute/transmute_ptr_to_ref.rs | 4 ++-- clippy_lints/src/types/borrowed_box.rs | 14 ++++++++---- clippy_lints/src/types/mod.rs | 12 +++++----- clippy_lints/src/unnecessary_literal_bound.rs | 4 ++-- clippy_utils/src/check_proc_macro.rs | 6 ++--- clippy_utils/src/hir_utils.rs | 18 +++++++-------- clippy_utils/src/lib.rs | 6 ++--- clippy_utils/src/sugg.rs | 7 +++--- 29 files changed, 99 insertions(+), 96 deletions(-) diff --git a/clippy_lints/src/casts/as_pointer_underscore.rs b/clippy_lints/src/casts/as_pointer_underscore.rs index 3ab6693756f5a..63df64f4edb57 100644 --- a/clippy_lints/src/casts/as_pointer_underscore.rs +++ b/clippy_lints/src/casts/as_pointer_underscore.rs @@ -3,7 +3,7 @@ use rustc_lint::LateContext; use rustc_middle::ty::Ty; pub fn check<'tcx>(cx: &LateContext<'tcx>, ty_into: Ty<'_>, cast_to_hir: &'tcx rustc_hir::Ty<'tcx>) { - if let rustc_hir::TyKind::Ptr(rustc_hir::MutTy { ty, .. }) = cast_to_hir.kind + if let rustc_hir::TyKind::Ptr(ty, _) = cast_to_hir.kind && matches!(ty.kind, rustc_hir::TyKind::Infer(())) { clippy_utils::diagnostics::span_lint_and_sugg( diff --git a/clippy_lints/src/casts/borrow_as_ptr.rs b/clippy_lints/src/casts/borrow_as_ptr.rs index cb9f7f618d7f9..3db972278a8ad 100644 --- a/clippy_lints/src/casts/borrow_as_ptr.rs +++ b/clippy_lints/src/casts/borrow_as_ptr.rs @@ -18,8 +18,8 @@ pub(super) fn check<'tcx>( cast_to: &'tcx Ty<'_>, msrv: Msrv, ) -> bool { - if let TyKind::Ptr(target) = cast_to.kind - && !matches!(target.ty.kind, TyKind::TraitObject(..)) + if let TyKind::Ptr(target, _) = cast_to.kind + && !matches!(target.kind, TyKind::TraitObject(..)) && let ExprKind::AddrOf(BorrowKind::Ref, mutability, e) = cast_expr.kind && !is_lint_allowed(cx, BORROW_AS_PTR, expr.hir_id) // Fix #9884 diff --git a/clippy_lints/src/casts/manual_dangling_ptr.rs b/clippy_lints/src/casts/manual_dangling_ptr.rs index 2b1b3c1b96fd3..030a22755cfd6 100644 --- a/clippy_lints/src/casts/manual_dangling_ptr.rs +++ b/clippy_lints/src/casts/manual_dangling_ptr.rs @@ -11,21 +11,21 @@ use rustc_span::Spanned; use super::MANUAL_DANGLING_PTR; pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>) { - if let TyKind::Ptr(ref ptr_ty) = to.kind { + if let TyKind::Ptr(ref ptr_ty, mutbl) = to.kind { let init_expr = expr_or_init(cx, from); - if is_expr_const_aligned(cx, init_expr, ptr_ty.ty) + if is_expr_const_aligned(cx, init_expr, ptr_ty) && let Some(std_or_core) = std_or_core(cx) - && let pointee_ty = cx.typeck_results().node_type(ptr_ty.ty.hir_id) + && let pointee_ty = cx.typeck_results().node_type(ptr_ty.hir_id) && pointee_ty.is_sized(cx.tcx, cx.typing_env()) { - let sugg_fn = match ptr_ty.mutbl { + let sugg_fn = match mutbl { Mutability::Not => "ptr::dangling", Mutability::Mut => "ptr::dangling_mut", }; - let sugg = if let TyKind::Infer(()) = ptr_ty.ty.kind { + let sugg = if let TyKind::Infer(()) = ptr_ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = ptr_ty.ty.span.get_text(cx) { + } else if let Some(mut_ty_snip) = ptr_ty.span.get_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/clippy_lints/src/casts/ptr_as_ptr.rs b/clippy_lints/src/casts/ptr_as_ptr.rs index 61fe563512b60..bee8478a7bcc8 100644 --- a/clippy_lints/src/casts/ptr_as_ptr.rs +++ b/clippy_lints/src/casts/ptr_as_ptr.rs @@ -47,13 +47,13 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir.kind { TyKind::Infer(()) => String::new(), - TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer(())) { + TyKind::Ptr(inner_ty, _) => { + if matches!(inner_ty.kind, TyKind::Infer(())) { String::new() } else { format!( "::<{}>", - snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) + snippet_with_applicability(cx, inner_ty.span, "/* type */", &mut app) ) } }, diff --git a/clippy_lints/src/casts/ptr_cast_constness.rs b/clippy_lints/src/casts/ptr_cast_constness.rs index 5f20efe2e3646..6107a0cb363d0 100644 --- a/clippy_lints/src/casts/ptr_cast_constness.rs +++ b/clippy_lints/src/casts/ptr_cast_constness.rs @@ -52,8 +52,8 @@ pub(super) fn check<'tcx>( if msrv.meets(cx, msrvs::POINTER_CAST_CONSTNESS) { let mut app = Applicability::MachineApplicable; let sugg = if let ExprKind::Cast(nested_from, nested_hir_ty) = cast_from_expr.kind - && let hir::TyKind::Ptr(ptr_ty) = nested_hir_ty.kind - && let hir::TyKind::Infer(()) = ptr_ty.ty.kind + && let hir::TyKind::Ptr(inner_ty, _) = nested_hir_ty.kind + && let hir::TyKind::Infer(()) = inner_ty.kind { // `(foo as *const _).cast_mut()` fails method name resolution // avoid this by `as`-ing the full type diff --git a/clippy_lints/src/casts/ref_as_ptr.rs b/clippy_lints/src/casts/ref_as_ptr.rs index b850f7f41ed33..0e69445caf5f4 100644 --- a/clippy_lints/src/casts/ref_as_ptr.rs +++ b/clippy_lints/src/casts/ref_as_ptr.rs @@ -44,13 +44,13 @@ pub(super) fn check<'tcx>( let mut app = Applicability::MachineApplicable; let turbofish = match &cast_to_hir_ty.kind { TyKind::Infer(()) => String::new(), - TyKind::Ptr(mut_ty) => { - if matches!(mut_ty.ty.kind, TyKind::Infer(())) { + TyKind::Ptr(inner_ty, _) => { + if matches!(inner_ty.kind, TyKind::Infer(())) { String::new() } else { format!( "::<{}>", - snippet_with_applicability(cx, mut_ty.ty.span, "/* type */", &mut app) + snippet_with_applicability(cx, inner_ty.span, "/* type */", &mut app) ) } }, diff --git a/clippy_lints/src/casts/unnecessary_cast.rs b/clippy_lints/src/casts/unnecessary_cast.rs index c98fa1a5cba74..0b2ba1428b53a 100644 --- a/clippy_lints/src/casts/unnecessary_cast.rs +++ b/clippy_lints/src/casts/unnecessary_cast.rs @@ -35,13 +35,13 @@ pub(super) fn check<'tcx>( // Ignore casts to e.g. type aliases and infer types // - p as pointer_alias // - p as _ - && let TyKind::Ptr(to_pointee) = cast_to_hir.kind + && let TyKind::Ptr(to_pointee, _) = cast_to_hir.kind { - match to_pointee.ty.kind { + match to_pointee.kind { // Ignore casts to pointers that are aliases or cfg dependant, e.g. // - p as *const std::ffi::c_char (alias) // - p as *const std::os::raw::c_char (cfg dependant) - TyKind::Path(qpath) if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee.ty) => { + TyKind::Path(qpath) if is_ty_alias(&qpath) || is_hir_ty_cfg_dependant(cx, to_pointee) => { return false; }, // Ignore `p as *const _` diff --git a/clippy_lints/src/casts/zero_ptr.rs b/clippy_lints/src/casts/zero_ptr.rs index 7f63a7336b1b0..8eba292d6fb99 100644 --- a/clippy_lints/src/casts/zero_ptr.rs +++ b/clippy_lints/src/casts/zero_ptr.rs @@ -9,19 +9,19 @@ use rustc_lint::LateContext; use super::ZERO_PTR; pub fn check(cx: &LateContext<'_>, expr: &Expr<'_>, from: &Expr<'_>, to: &Ty<'_>, msrv: Msrv) { - if let TyKind::Ptr(ref mut_ty) = to.kind + if let TyKind::Ptr(ref ty, mutbl) = to.kind && is_integer_literal(from, 0) && (!is_in_const_context(cx) || msrv.meets(cx, msrvs::PTR_NULL)) && let Some(std_or_core) = std_or_core(cx) { - let (msg, sugg_fn) = match mut_ty.mutbl { + let (msg, sugg_fn) = match mutbl { Mutability::Mut => ("`0 as *mut _` detected", "ptr::null_mut"), Mutability::Not => ("`0 as *const _` detected", "ptr::null"), }; - let sugg = if let TyKind::Infer(()) = mut_ty.ty.kind { + let sugg = if let TyKind::Infer(()) = ty.kind { format!("{std_or_core}::{sugg_fn}()") - } else if let Some(mut_ty_snip) = mut_ty.ty.span.get_text(cx) { + } else if let Some(mut_ty_snip) = ty.span.get_text(cx) { format!("{std_or_core}::{sugg_fn}::<{mut_ty_snip}>()") } else { return; diff --git a/clippy_lints/src/dereference.rs b/clippy_lints/src/dereference.rs index 50017eec7cf65..fa544da1ba3bd 100644 --- a/clippy_lints/src/dereference.rs +++ b/clippy_lints/src/dereference.rs @@ -853,14 +853,14 @@ impl TyCoercionStability { // Here `y1` and `y2` would resolve to different types, so the type `&Box<_>` is not stable when // switching to auto-dereferencing. fn for_hir_ty<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> Self { - let TyKind::Ref(_, ty) = &ty.kind else { + let TyKind::Ref(_, ty, _) = &ty.kind else { return Self::None; }; let mut ty = ty; loop { - break match ty.ty.kind { - TyKind::Ref(_, ref ref_ty) => { + break match ty.kind { + TyKind::Ref(_, ref ref_ty, _) => { ty = ref_ty; continue; }, @@ -887,7 +887,7 @@ impl TyCoercionStability { }, TyKind::Slice(_) | TyKind::Array(..) - | TyKind::Ptr(_) + | TyKind::Ptr(..) | TyKind::FnPtr(_) | TyKind::Pat(..) | TyKind::FieldOf(..) diff --git a/clippy_lints/src/functions/ref_option.rs b/clippy_lints/src/functions/ref_option.rs index 1afec00f94792..733f10b3506f8 100644 --- a/clippy_lints/src/functions/ref_option.rs +++ b/clippy_lints/src/functions/ref_option.rs @@ -16,7 +16,7 @@ fn check_ty<'a>(cx: &LateContext<'a>, param: &hir::Ty<'a>, param_ty: Ty<'a>, fix && let Some(gen_ty) = option_arg_ty(cx, *opt_ty) && !gen_ty.is_ref() // Need to gen the original spans, so first parsing mid, and hir parsing afterward - && let hir::TyKind::Ref(lifetime, hir::MutTy { ty, .. }) = param.kind + && let hir::TyKind::Ref(lifetime, ty, ..) = param.kind && let hir::TyKind::Path(hir::QPath::Resolved(_, path)) = ty.kind && let (Some(first), Some(last)) = (path.segments.first(), path.segments.last()) && let Some(hir::GenericArgs { diff --git a/clippy_lints/src/iter_without_into_iter.rs b/clippy_lints/src/iter_without_into_iter.rs index 3c49595f83216..771cdc1e47136 100644 --- a/clippy_lints/src/iter_without_into_iter.rs +++ b/clippy_lints/src/iter_without_into_iter.rs @@ -126,7 +126,7 @@ fn is_ty_exported(cx: &LateContext<'_>, ty: Ty<'_>) -> bool { impl LateLintPass<'_> for IterWithoutIntoIter { fn check_item(&mut self, cx: &LateContext<'_>, item: &rustc_hir::Item<'_>) { if let ItemKind::Impl(imp) = item.kind - && let TyKind::Ref(_, self_ty_without_ref) = &imp.self_ty.kind + && let TyKind::Ref(_, self_ty_without_ref, _) = &imp.self_ty.kind && let Some(of_trait) = imp.of_trait && of_trait .trait_ref @@ -178,7 +178,7 @@ impl {self_ty_without_ref} {{ }} }} ", - self_ty_without_ref = snippet(cx, self_ty_without_ref.ty.span, ".."), + self_ty_without_ref = snippet(cx, self_ty_without_ref.span, ".."), ref_self = mtbl.ref_prefix_str(), iter_ty = snippet(cx, iter_assoc_span, ".."), ); diff --git a/clippy_lints/src/methods/needless_collect.rs b/clippy_lints/src/methods/needless_collect.rs index 5e65c0f6f0c67..24bd9a2f1418d 100644 --- a/clippy_lints/src/methods/needless_collect.rs +++ b/clippy_lints/src/methods/needless_collect.rs @@ -262,7 +262,7 @@ fn ty_is_fully_concrete(ty: &rustc_hir::Ty<'_>) -> bool { seg.args .is_none_or(|a| a.args.iter().all(generic_arg_is_fully_concrete)) }), - rustc_hir::TyKind::Ref(_, mut_ty) => ty_is_fully_concrete(mut_ty.ty), + rustc_hir::TyKind::Ref(_, ty, _) => ty_is_fully_concrete(ty), rustc_hir::TyKind::Slice(ty) | rustc_hir::TyKind::Array(ty, _) => ty_is_fully_concrete(ty), rustc_hir::TyKind::Tup(tys) => tys.iter().all(ty_is_fully_concrete), _ => true, diff --git a/clippy_lints/src/methods/should_implement_trait.rs b/clippy_lints/src/methods/should_implement_trait.rs index 9e0d630461915..c233fe3f28ed5 100644 --- a/clippy_lints/src/methods/should_implement_trait.rs +++ b/clippy_lints/src/methods/should_implement_trait.rs @@ -149,7 +149,7 @@ impl OutType { (Self::Unit, &FnRetTy::Return(ty)) if is_unit(ty) => true, (Self::Bool, &FnRetTy::Return(ty)) if is_bool(ty) => true, (Self::Any, &FnRetTy::Return(ty)) if !is_unit(ty) => true, - (Self::Ref, &FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(_, _)), + (Self::Ref, &FnRetTy::Return(ty)) => matches!(ty.kind, hir::TyKind::Ref(..)), _ => false, } } diff --git a/clippy_lints/src/mut_mut.rs b/clippy_lints/src/mut_mut.rs index 3b83a9ecd55c2..640044e4d6e21 100644 --- a/clippy_lints/src/mut_mut.rs +++ b/clippy_lints/src/mut_mut.rs @@ -98,26 +98,26 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx hir::Ty<'_, AmbigArg>) { - if let TyKind::Ref(_, base) = ty.kind - && base.mutbl.is_mut() + if let TyKind::Ref(_, base, base_mutbl) = ty.kind + && base_mutbl.is_mut() && let ctxt = ty.span.ctxt() - && ctxt == base.ty.span.ctxt() + && ctxt == base.span.ctxt() { - if self.skip_id.replace(base.ty.hir_id) == Some(ty.hir_id) { + if self.skip_id.replace(base.hir_id) == Some(ty.hir_id) { return; } - if let TyKind::Ref(_, mut base2) = base.ty.kind - && base2.mutbl.is_mut() + if let TyKind::Ref(_, mut base2, base2_mutbl) = base.kind + && base2_mutbl.is_mut() { - while let TyKind::Ref(_, next) = base2.ty.kind - && next.mutbl.is_mut() - && ctxt == base2.ty.span.ctxt() + while let TyKind::Ref(_, next, next_mutbl) = base2.kind + && next_mutbl.is_mut() + && ctxt == base2.span.ctxt() { base2 = next; } if !ctxt.in_external_macro(cx.tcx.sess.source_map()) - && let Some(sp) = walk_span_to_context(base2.ty.span, ctxt) + && let Some(sp) = walk_span_to_context(base2.span, ctxt) { span_lint_and_then( cx, @@ -126,7 +126,7 @@ impl<'tcx> LateLintPass<'tcx> for MutMut { "multiple successive mutable references", |diag| { diag.span_suggestion_verbose( - base.ty.span.until(sp), + base.span.until(sp), "use only a single mutable reference", "", Applicability::MaybeIncorrect, diff --git a/clippy_lints/src/needless_pass_by_ref_mut.rs b/clippy_lints/src/needless_pass_by_ref_mut.rs index 5c6030d61f5f0..ce5040372c3cc 100644 --- a/clippy_lints/src/needless_pass_by_ref_mut.rs +++ b/clippy_lints/src/needless_pass_by_ref_mut.rs @@ -266,9 +266,9 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> { for input in unused { // If the argument is never used mutably, we emit the warning. let sp = input.span; - if let rustc_hir::TyKind::Ref(_, inner_ty) = input.kind { + if let rustc_hir::TyKind::Ref(_, inner_ty, _) = input.kind { let Some(after_mut_span) = cx.tcx.sess.source_map().span_extend_to_prev_str( - inner_ty.ty.span.shrink_to_lo(), + inner_ty.span.shrink_to_lo(), "mut", true, true, diff --git a/clippy_lints/src/pass_by_ref_or_value.rs b/clippy_lints/src/pass_by_ref_or_value.rs index 70b5adb0a7390..4c541ead3d395 100644 --- a/clippy_lints/src/pass_by_ref_or_value.rs +++ b/clippy_lints/src/pass_by_ref_or_value.rs @@ -11,7 +11,7 @@ use rustc_data_structures::unord::UnordItems; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; -use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, MutTy, Mutability, Node, PatKind}; +use rustc_hir::{BindingMode, Body, FnDecl, Impl, ItemKind, Mutability, Node, PatKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::adjustment::{Adjust, PointerCoercion}; use rustc_middle::ty::layout::LayoutOf as _; @@ -171,7 +171,7 @@ impl PassByRefOrValue { if is_copy(cx, ty) && let Some(size) = cx.layout_of(ty).ok().map(|l| l.size.bytes()) && size <= self.ref_min_size - && let hir::TyKind::Ref(_, MutTy { ty: decl_ty, .. }) = input.kind + && let hir::TyKind::Ref(_, decl_ty, ..) = input.kind { if let Some(typeck) = cx.typeck_results // Don't lint if a raw pointer is created. diff --git a/clippy_lints/src/ptr/mut_from_ref.rs b/clippy_lints/src/ptr/mut_from_ref.rs index 6cf4c8586f340..bc0fac8684cf1 100644 --- a/clippy_lints/src/ptr/mut_from_ref.rs +++ b/clippy_lints/src/ptr/mut_from_ref.rs @@ -48,8 +48,8 @@ struct LifetimeVisitor<'tcx> { impl<'tcx> Visitor<'tcx> for LifetimeVisitor<'tcx> { fn visit_ty(&mut self, ty: &'tcx hir::Ty<'tcx, hir::AmbigArg>) { - if let TyKind::Ref(lt, ref m) = ty.kind { - self.result.push((lt, Some(m.mutbl), ty.span)); + if let TyKind::Ref(lt, _, mutbl) = ty.kind { + self.result.push((lt, Some(mutbl), ty.span)); } hir::intravisit::walk_ty(self, ty); } diff --git a/clippy_lints/src/ptr/ptr_arg.rs b/clippy_lints/src/ptr/ptr_arg.rs index 4242b7f1f3224..4ead93478a86d 100644 --- a/clippy_lints/src/ptr/ptr_arg.rs +++ b/clippy_lints/src/ptr/ptr_arg.rs @@ -207,8 +207,8 @@ fn check_fn_args<'cx, 'tcx: 'cx>( .filter_map(move |(i, (ty, hir_ty))| { if let ty::Ref(_, ty, mutability) = *ty.kind() && let ty::Adt(adt, args) = *ty.kind() - && let TyKind::Ref(lt, ref ty) = hir_ty.kind - && let TyKind::Path(QPath::Resolved(None, path)) = ty.ty.kind + && let TyKind::Ref(lt, ref inner_ty, _) = hir_ty.kind + && let TyKind::Path(QPath::Resolved(None, path)) = inner_ty.kind // Check that the name as typed matches the actual name of the type. // e.g. `fn foo(_: &Foo)` shouldn't trigger the lint when `Foo` is an alias for `Vec` && let [.., name] = path.segments diff --git a/clippy_lints/src/redundant_type_annotations.rs b/clippy_lints/src/redundant_type_annotations.rs index b98a4c6b8b9cb..1d0db5d1ebe36 100644 --- a/clippy_lints/src/redundant_type_annotations.rs +++ b/clippy_lints/src/redundant_type_annotations.rs @@ -154,9 +154,9 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { let mut ty_kind = &ty.kind; // If the annotation is a ref we "peel" it - if let hir::TyKind::Ref(_, mut_ty) = &ty.kind { + if let hir::TyKind::Ref(_, inner_ty, _) = &ty.kind { is_ref = true; - ty_kind = &mut_ty.ty.kind; + ty_kind = &inner_ty.kind; } if let hir::TyKind::Path(ty_path) = ty_kind @@ -204,8 +204,8 @@ impl LateLintPass<'_> for RedundantTypeAnnotations { // We only lint if the type annotation is an array type (e.g. &[u8; 4]). // If instead it is a slice (e.g. &[u8]) it may not be redundant, so we // don't lint. - if let hir::TyKind::Ref(_, mut_ty) = ty.kind - && matches!(mut_ty.ty.kind, hir::TyKind::Array(..)) + if let hir::TyKind::Ref(_, inner_ty, _) = ty.kind + && matches!(inner_ty.kind, hir::TyKind::Array(..)) { span_lint(cx, REDUNDANT_TYPE_ANNOTATIONS, local.span, "redundant type annotation"); } diff --git a/clippy_lints/src/ref_option_ref.rs b/clippy_lints/src/ref_option_ref.rs index 013225da010d7..bade37ee8438a 100644 --- a/clippy_lints/src/ref_option_ref.rs +++ b/clippy_lints/src/ref_option_ref.rs @@ -36,9 +36,8 @@ declare_lint_pass!(RefOptionRef => [REF_OPTION_REF]); impl<'tcx> LateLintPass<'tcx> for RefOptionRef { fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { - if let TyKind::Ref(_, ref mut_ty) = ty.kind - && mut_ty.mutbl == Mutability::Not - && let TyKind::Path(qpath) = &mut_ty.ty.kind + if let TyKind::Ref(_, ref ref_ty, Mutability::Not) = ty.kind + && let TyKind::Path(qpath) = &ref_ty.kind && let last = last_path_segment(qpath) && let Some(def_id) = last.res.opt_def_id() && cx.tcx.is_diagnostic_item(sym::Option, def_id) @@ -48,8 +47,7 @@ impl<'tcx> LateLintPass<'tcx> for RefOptionRef { GenericArg::Type(inner_ty) => Some(inner_ty), _ => None, }) - && let TyKind::Ref(_, ref inner_mut_ty) = inner_ty.kind - && inner_mut_ty.mutbl == Mutability::Not + && let TyKind::Ref(_, _, Mutability::Not) = inner_ty.kind { span_lint_and_sugg( cx, diff --git a/clippy_lints/src/trait_bounds.rs b/clippy_lints/src/trait_bounds.rs index 39b2b71a0d56d..58d434dc18e7d 100644 --- a/clippy_lints/src/trait_bounds.rs +++ b/clippy_lints/src/trait_bounds.rs @@ -178,8 +178,8 @@ impl<'tcx> LateLintPass<'tcx> for TraitBounds { } fn check_ty(&mut self, cx: &LateContext<'tcx>, ty: &'tcx Ty<'tcx, AmbigArg>) { - if let TyKind::Ref(.., mut_ty) = &ty.kind - && let TyKind::TraitObject(bounds, ..) = mut_ty.ty.kind + if let TyKind::Ref(_, inner_ty, _) = &ty.kind + && let TyKind::TraitObject(bounds, ..) = inner_ty.kind && bounds.len() > 2 { // Build up a hash of every trait we've seen diff --git a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs index 1edd7f8baea96..a68291f06d3dd 100644 --- a/clippy_lints/src/transmute/transmute_ptr_to_ref.rs +++ b/clippy_lints/src/transmute/transmute_ptr_to_ref.rs @@ -88,9 +88,9 @@ pub(super) fn check<'tcx>( /// Gets the type `Bar` in `…::transmute`. fn get_explicit_type<'tcx>(path: &'tcx Path<'tcx>) -> Option<&'tcx hir::Ty<'tcx>> { if let GenericArg::Type(ty) = path.segments.last()?.args?.args.get(1)? - && let TyKind::Ref(_, ty) = &ty.kind + && let TyKind::Ref(_, inner_ty, _) = &ty.kind { - Some(ty.ty) + Some(inner_ty) } else { None } diff --git a/clippy_lints/src/types/borrowed_box.rs b/clippy_lints/src/types/borrowed_box.rs index 3dffc164f991a..3aa4224c0e766 100644 --- a/clippy_lints/src/types/borrowed_box.rs +++ b/clippy_lints/src/types/borrowed_box.rs @@ -3,16 +3,22 @@ use clippy_utils::source::snippet; use clippy_utils::sym; use rustc_errors::Applicability; use rustc_hir::{ - self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, MutTy, Mutability, Node, QPath, TyKind, + self as hir, GenericArg, GenericBounds, GenericParamKind, HirId, Lifetime, Mutability, Node, QPath, TyKind, }; use rustc_lint::LateContext; use super::BORROWED_BOX; -pub(super) fn check(cx: &LateContext<'_>, hir_ty: &hir::Ty<'_>, lt: &Lifetime, mut_ty: &MutTy<'_>) -> bool { +pub(super) fn check( + cx: &LateContext<'_>, + hir_ty: &hir::Ty<'_>, + lt: &Lifetime, + inner_ty: &hir::Ty<'_>, + mutbl: Mutability, +) -> bool { // Ignore `&mut Box` types; see issue #2907 for details. - if mut_ty.mutbl == Mutability::Not - && let TyKind::Path(ref qpath) = mut_ty.ty.kind + if mutbl == Mutability::Not + && let TyKind::Path(ref qpath) = inner_ty.kind && let QPath::Resolved(None, path) = *qpath && let Some(def_id) = path.res.opt_def_id() && Some(def_id) == cx.tcx.lang_items().owned_box() diff --git a/clippy_lints/src/types/mod.rs b/clippy_lints/src/types/mod.rs index 45388800be4b6..f62ca8075f96f 100644 --- a/clippy_lints/src/types/mod.rs +++ b/clippy_lints/src/types/mod.rs @@ -14,8 +14,8 @@ use clippy_config::Conf; use rustc_hir as hir; use rustc_hir::intravisit::FnKind; use rustc_hir::{ - Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, MutTy, QPath, TraitFn, - TraitItem, TraitItemKind, TyKind, + Body, FnDecl, FnRetTy, GenericArg, ImplItem, ImplItemKind, Item, ItemKind, LetStmt, QPath, TraitFn, TraitItem, + TraitItemKind, TyKind, }; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::Span; @@ -664,13 +664,13 @@ impl Types { owned_cow::check(cx, qpath, def_id); } }, - TyKind::Ref(lt, ref mut_ty) => { + TyKind::Ref(lt, ref inner_ty, mutbl) => { context.is_nested_call = true; - if !borrowed_box::check(cx, hir_ty, lt, mut_ty) { - self.check_ty(cx, mut_ty.ty, context); + if !borrowed_box::check(cx, hir_ty, lt, inner_ty, mutbl) { + self.check_ty(cx, inner_ty, context); } }, - TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(MutTy { ty, .. }) => { + TyKind::Slice(ty) | TyKind::Array(ty, _) | TyKind::Ptr(ty, ..) => { context.is_nested_call = true; self.check_ty(cx, ty, context); }, diff --git a/clippy_lints/src/unnecessary_literal_bound.rs b/clippy_lints/src/unnecessary_literal_bound.rs index db920fad53b4e..59987ad7ad817 100644 --- a/clippy_lints/src/unnecessary_literal_bound.rs +++ b/clippy_lints/src/unnecessary_literal_bound.rs @@ -4,7 +4,7 @@ use rustc_ast::ast::LitKind; use rustc_errors::Applicability; use rustc_hir::def::Res; use rustc_hir::intravisit::{FnKind, Visitor}; -use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, Lit, MutTy, Mutability, PrimTy, Ty, TyKind, intravisit}; +use rustc_hir::{Body, Expr, ExprKind, FnDecl, FnRetTy, Lit, Mutability, PrimTy, Ty, TyKind, intravisit}; use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; use rustc_span::Span; use rustc_span::def_id::LocalDefId; @@ -55,7 +55,7 @@ declare_clippy_lint! { declare_lint_pass!(UnnecessaryLiteralBound => [UNNECESSARY_LITERAL_BOUND]); fn extract_anonymous_ref<'tcx>(hir_ty: &Ty<'tcx>) -> Option<&'tcx Ty<'tcx>> { - let TyKind::Ref(lifetime, MutTy { ty, mutbl }) = hir_ty.kind else { + let TyKind::Ref(lifetime, ty, mutbl) = hir_ty.kind else { return None; }; diff --git a/clippy_utils/src/check_proc_macro.rs b/clippy_utils/src/check_proc_macro.rs index ca79f79403e7d..828fb1d3313b4 100644 --- a/clippy_utils/src/check_proc_macro.rs +++ b/clippy_utils/src/check_proc_macro.rs @@ -23,7 +23,7 @@ use rustc_hir::intravisit::FnKind; use rustc_hir::{ Block, BlockCheckMode, Body, BoundConstness, BoundPolarity, Closure, Destination, Expr, ExprKind, FieldDef, FnHeader, FnRetTy, HirId, Impl, ImplItem, ImplItemImplKind, ImplItemKind, IsAuto, Item, ItemKind, Lit, LoopSource, - MatchSource, MutTy, Node, PatExpr, PatExprKind, PatKind, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, + MatchSource, Node, PatExpr, PatExprKind, PatKind, Path, PolyTraitRef, QPath, Safety, TraitBoundModifiers, TraitImplHeader, TraitItem, TraitItemKind, TraitRef, Ty, TyKind, UnOp, UnsafeSource, Variant, VariantData, YieldSource, }; @@ -391,8 +391,8 @@ fn attr_search_pat(attr: &Attribute) -> (Pat, Pat) { fn ty_search_pat(ty: &Ty<'_>) -> (Pat, Pat) { match ty.kind { TyKind::Slice(..) | TyKind::Array(..) => (Pat::Str("["), Pat::Str("]")), - TyKind::Ptr(MutTy { ty, .. }) => (Pat::Str("*"), ty_search_pat(ty).1), - TyKind::Ref(_, MutTy { ty, .. }) => (Pat::Str("&"), ty_search_pat(ty).1), + TyKind::Ptr(ty, ..) => (Pat::Str("*"), ty_search_pat(ty).1), + TyKind::Ref(_, ty, ..) => (Pat::Str("&"), ty_search_pat(ty).1), TyKind::FnPtr(fn_ptr) => ( if fn_ptr.safety.is_unsafe() { Pat::Str("unsafe") diff --git a/clippy_utils/src/hir_utils.rs b/clippy_utils/src/hir_utils.rs index 04ace1727c82c..4ef0a795b4766 100644 --- a/clippy_utils/src/hir_utils.rs +++ b/clippy_utils/src/hir_utils.rs @@ -903,9 +903,9 @@ impl HirEqInterExpr<'_, '_, '_> { match (&left.kind, &right.kind) { (TyKind::Slice(l_vec), TyKind::Slice(r_vec)) => self.eq_ty(l_vec, r_vec), (TyKind::Array(lt, ll), TyKind::Array(rt, rl)) => self.eq_ty(lt, rt) && self.eq_const_arg(ll, rl), - (TyKind::Ptr(l_mut), TyKind::Ptr(r_mut)) => l_mut.mutbl == r_mut.mutbl && self.eq_ty(l_mut.ty, r_mut.ty), - (TyKind::Ref(_, l_rmut), TyKind::Ref(_, r_rmut)) => { - l_rmut.mutbl == r_rmut.mutbl && self.eq_ty(l_rmut.ty, r_rmut.ty) + (TyKind::Ptr(l_ty, l_mutbl), TyKind::Ptr(r_ty, r_mutbl)) => l_mutbl == r_mutbl && self.eq_ty(l_ty, r_ty), + (TyKind::Ref(_, l_ty, l_mutbl), TyKind::Ref(_, r_ty, r_mutbl)) => { + l_mutbl == r_mutbl && self.eq_ty(l_ty, r_ty) }, (TyKind::Path(l), TyKind::Path(r)) => self.eq_qpath(l, r), (TyKind::Tup(l), TyKind::Tup(r)) => over(l, r, |l, r| self.eq_ty(l, r)), @@ -1617,14 +1617,14 @@ impl<'a, 'tcx> SpanlessHash<'a, 'tcx> { } self.hash_name(field.name); }, - TyKind::Ptr(mut_ty) => { - self.hash_ty(mut_ty.ty); - mut_ty.mutbl.hash(&mut self.s); + TyKind::Ptr(ty, mutbl) => { + self.hash_ty(ty); + mutbl.hash(&mut self.s); }, - TyKind::Ref(lifetime, mut_ty) => { + TyKind::Ref(lifetime, ty, mutbl) => { self.hash_lifetime(lifetime); - self.hash_ty(mut_ty.ty); - mut_ty.mutbl.hash(&mut self.s); + self.hash_ty(ty); + mutbl.hash(&mut self.s); }, TyKind::FnPtr(fn_ptr) => { fn_ptr.safety.hash(&mut self.s); diff --git a/clippy_utils/src/lib.rs b/clippy_utils/src/lib.rs index 9fd934cac7ecf..7a155b5885a8c 100644 --- a/clippy_utils/src/lib.rs +++ b/clippy_utils/src/lib.rs @@ -2304,8 +2304,8 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) let mut count = 0; loop { match &ty.kind { - TyKind::Ref(_, ref_ty) => { - ty = ref_ty.ty; + TyKind::Ref(_, inner_ty, _) => { + ty = inner_ty; count += 1; }, _ => break (ty, count), @@ -2316,7 +2316,7 @@ pub fn peel_hir_ty_refs<'a>(mut ty: &'a hir::Ty<'a>) -> (&'a hir::Ty<'a>, usize) /// Returns the base type for HIR references and pointers. pub fn peel_hir_ty_refs_and_ptrs<'tcx>(ty: &'tcx hir::Ty<'tcx>) -> &'tcx hir::Ty<'tcx> { match &ty.kind { - TyKind::Ptr(mut_ty) | TyKind::Ref(_, mut_ty) => peel_hir_ty_refs_and_ptrs(mut_ty.ty), + TyKind::Ptr(inner_ty, _) | TyKind::Ref(_, inner_ty, _) => peel_hir_ty_refs_and_ptrs(inner_ty), _ => ty, } } diff --git a/clippy_utils/src/sugg.rs b/clippy_utils/src/sugg.rs index d2045c1346ee5..d05ae0b5c45b5 100644 --- a/clippy_utils/src/sugg.rs +++ b/clippy_utils/src/sugg.rs @@ -8,7 +8,7 @@ use rustc_ast::util::parser::AssocOp; use rustc_ast::{UnOp, ast}; use rustc_data_structures::fx::FxHashSet; use rustc_errors::Applicability; -use rustc_hir::{self as hir, Closure, ExprKind, HirId, MatchSource, MutTy, Node, TyKind}; +use rustc_hir::{self as hir, Closure, ExprKind, HirId, MatchSource, Node, TyKind}; use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId}; use rustc_lint::{EarlyContext, LateContext, LintContext}; use rustc_middle::hir::place::ProjectionKind; @@ -815,9 +815,8 @@ pub fn deref_closure_args(cx: &LateContext<'_>, closure: &hir::Expr<'_>) -> Opti let closure_body = cx.tcx.hir_body(body); // is closure arg a type annotated double reference (i.e.: `|x: &&i32| ...`) // a type annotation is present if param `kind` is different from `TyKind::Infer` - let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, MutTy { ty, .. }) = fn_decl.inputs[0].kind - { - matches!(ty.kind, TyKind::Ref(_, MutTy { .. })) + let closure_arg_is_type_annotated_double_ref = if let TyKind::Ref(_, ty, ..) = fn_decl.inputs[0].kind { + matches!(ty.kind, TyKind::Ref(..)) } else { false }; From 99cc8cf3c959e411c075eb8f7d3555590fa1a369 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Mon, 28 Sep 2026 15:48:41 +0800 Subject: [PATCH 0941/1309] document safety requirements for atomic intrinsics --- library/core/src/intrinsics/mod.rs | 190 ++++++++++++++++++++++++++--- 1 file changed, 174 insertions(+), 16 deletions(-) diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ecc8b66ec5785..2ff0777a2885d 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -95,7 +95,9 @@ use macros::intrinsic_dispatch_on_type; // These imports are used for simplifying intra-doc links #[allow(unused_imports)] #[cfg(all(target_has_atomic = "8", target_has_atomic = "32", target_has_atomic = "ptr"))] -use crate::sync::atomic::{self, AtomicBool, AtomicI32, AtomicIsize, AtomicU32, Ordering}; +use crate::sync::atomic::{ + self, AtomicBool, AtomicI32, AtomicIsize, AtomicPtr, AtomicU32, Ordering, +}; /// A type for atomic ordering parameters for intrinsics. This is a separate type from /// `atomic::Ordering` so that we can make it `ConstParamTy` and fix the values used here without a @@ -115,12 +117,28 @@ pub enum AtomicOrdering { // N.B., these intrinsics take raw pointers because they mutate aliased // memory, which is not valid for either `&` or `&mut`. -/// Stores a value if the current value is the same as the `old` value. +/// Stores a value if the current value is the same as the `old` value, +/// with the returned `T` being the previous value and the returned `bool` being +/// whether the exchange was successful. /// `T` must be an integer or pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::compare_exchange`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::compare_exchange`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange` method. /// For example, [`AtomicBool::compare_exchange`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::compare_exchange`]: AtomicI32::compare_exchange +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::compare_exchange`]: AtomicPtr::compare_exchange #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_cxchg< @@ -133,12 +151,28 @@ pub const unsafe fn atomic_cxchg< src: T, ) -> (T, bool); -/// Stores a value if the current value is the same as the `old` value. +/// Stores a value if the current value is the same as the `old` value, +/// with the returned `T` being the previous value and the returned `bool` being +/// whether the exchange was successful. /// `T` must be an integer or pointer type. The comparison may spuriously fail. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::compare_exchange_weak`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::compare_exchange_weak`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `compare_exchange_weak` method. /// For example, [`AtomicBool::compare_exchange_weak`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::compare_exchange_weak`]: AtomicI32::compare_exchange_weak +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::compare_exchange_weak`]: AtomicPtr::compare_exchange_weak #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_cxchgweak< @@ -156,18 +190,18 @@ pub const unsafe fn atomic_cxchgweak< /// /// # Safety /// -/// * If `VOLATILE` is `true`, this is equivalent to [Atomic::load_volatile]. +/// * If `VOLATILE` is `true`, this is equivalent to [`Atomic::load_volatile`]. /// Refer to the documentation of that method for safety requirements. /// -/// * If `VOLATILE` is `false`, this is equivalent to [Atomic::from_ptr] followed -/// by [Atomic::load]. Refer to the documentation of [Atomic::from_ptr] for safety requirements. +/// * If `VOLATILE` is `false`, this is equivalent to [`Atomic::from_ptr`] followed +/// by [`Atomic::load`]. Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `load` method. For example, [`AtomicBool::load`]. /// -/// [Atomic::load_volatile]: AtomicI32::load_volatile -/// [Atomic::from_ptr]: AtomicI32::from_ptr -/// [Atomic::load]: AtomicI32::load +/// [`Atomic::load_volatile`]: AtomicI32::load_volatile +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::load`]: AtomicI32::load #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_load( @@ -179,18 +213,18 @@ pub const unsafe fn atomic_load::store_volatile`]. /// Refer to the documentation of that method for safety requirements. /// -/// * If `VOLATILE` is `false`, this is equivalent to [Atomic::from_ptr] followed -/// by [Atomic::store]. Refer to the documentation of [Atomic::from_ptr] for safety requirements. +/// * If `VOLATILE` is `false`, this is equivalent to [`Atomic::from_ptr`] followed +/// by [`Atomic::store`]. Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. /// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `store` method. For example, [`AtomicBool::store`]. /// -/// [Atomic::store_volatile]: AtomicI32::store_volatile -/// [Atomic::from_ptr]: AtomicI32::from_ptr -/// [Atomic::store]: AtomicI32::store +/// [`Atomic::store_volatile`]: AtomicI32::store_volatile +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::store`]: AtomicI32::store #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_store( @@ -201,8 +235,22 @@ pub const unsafe fn atomic_store::from_ptr`] followed by [`Atomic::swap`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::swap`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `swap` method. For example, [`AtomicBool::swap`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::swap`]: AtomicI32::swap +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::swap`]: AtomicPtr::swap #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xchg(dst: *mut T, src: T) -> T; @@ -211,8 +259,22 @@ pub const unsafe fn atomic_xchg(dst: *mut T, /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_add`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::fetch_byte_add`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_add`]: AtomicI32::fetch_add +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::fetch_byte_add`]: AtomicPtr::fetch_byte_add #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xadd( @@ -224,8 +286,22 @@ pub const unsafe fn atomic_xadd( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_sub`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::fetch_byte_sub`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_sub`]: AtomicI32::fetch_sub +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::fetch_byte_sub`]: AtomicPtr::fetch_byte_sub #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xsub( @@ -237,8 +313,22 @@ pub const unsafe fn atomic_xsub( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_and`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::fetch_and`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_and`]: AtomicI32::fetch_and +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::fetch_and`]: AtomicPtr::fetch_and #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_and( @@ -250,8 +340,16 @@ pub const unsafe fn atomic_and( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_nand`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the -/// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. +/// [`atomic`] types via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_nand`]: AtomicI32::fetch_nand #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_nand( @@ -263,8 +361,22 @@ pub const unsafe fn atomic_nand( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_or`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::fetch_or`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_or`]: AtomicI32::fetch_or +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    ::fetch_or`]: AtomicPtr::fetch_or #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_or( @@ -276,8 +388,22 @@ pub const unsafe fn atomic_or( /// `T` must be an integer or pointer type. /// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type. /// +/// # Safety +/// +/// * If `T` is an integer type, this is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_xor`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// +/// * If `T` is a pointer type, this is equivalent to [`AtomicPtr

    ::from_ptr`] followed by [`AtomicPtr

    ::fetch_xor`], +/// where `P` is the pointee type of the pointer. +/// Refer to the documentation of [`AtomicPtr

    ::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_xor`]: AtomicI32::fetch_xor +/// [`AtomicPtr

    ::from_ptr`]: AtomicPtr::from_ptr +/// [`AtomicPtr

    >, &'a u32) -> &'a u32` ... +LL | impl

    Trait for Pin

    { +LL | // This should not hide `&Self`, which would cause this to compile. LL | fn method(self: Pin<&Self>, f: &u32) -> &u32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(Pin<&'1 Pin

    >, &'2 u32) -> &'1 u32` | diff --git a/tests/ui/traits/param-without-lifetime-constraint.stderr b/tests/ui/traits/param-without-lifetime-constraint.stderr index b8ec1fa5654a1..d5d83675a1e71 100644 --- a/tests/ui/traits/param-without-lifetime-constraint.stderr +++ b/tests/ui/traits/param-without-lifetime-constraint.stderr @@ -1,9 +1,11 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/param-without-lifetime-constraint.rs:14:5 | +LL | pub trait HaveRelationship { LL | fn get_relation(&self) -> To; | ----------------------------- expected `fn(&'1 Article) -> &'2 ProofReader` ... +LL | impl HaveRelationship<&ProofReader> for Article { LL | fn get_relation(&self) -> &ProofReader { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Article) -> &'1 ProofReader` | diff --git a/tests/ui/traits/self-without-lifetime-constraint.stderr b/tests/ui/traits/self-without-lifetime-constraint.stderr index a82ff8eb0c269..34cf99b3f0512 100644 --- a/tests/ui/traits/self-without-lifetime-constraint.stderr +++ b/tests/ui/traits/self-without-lifetime-constraint.stderr @@ -1,9 +1,11 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/self-without-lifetime-constraint.rs:46:5 | +LL | pub trait FromSql: Sized { LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), _>` ... +LL | impl FromSql for &str { LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), _>` | From 330b5d11cf9af448ad9542827e287885cc5605c6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Eduardo=20S=C3=A1nchez=20Mu=C3=B1oz?= Date: Tue, 29 Sep 2026 18:40:17 +0200 Subject: [PATCH 1008/1309] miri: implement again shims for LLVM intrinsics for `_mm_mulhi_epi16` and `_mm_mulhi_epu16` These are being used again (https://github.com/rust-lang/stdarch/pull/2219) due to performance regression of the generic implementation This partially reverts https://github.com/rust-lang/rust/pull/116609 --- src/tools/miri/src/intrinsics/x86/sse2.rs | 36 +++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/src/tools/miri/src/intrinsics/x86/sse2.rs b/src/tools/miri/src/intrinsics/x86/sse2.rs index b39bfcaedea59..d9ef809598765 100644 --- a/src/tools/miri/src/intrinsics/x86/sse2.rs +++ b/src/tools/miri/src/intrinsics/x86/sse2.rs @@ -1,4 +1,5 @@ use rustc_apfloat::ieee::Double; +use rustc_middle::mir; use rustc_span::Symbol; use super::{ @@ -272,6 +273,41 @@ pub(super) trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { pmaddwd(this, left, right, dest)?; } + // Used to implement the _mm_mulhi_epi16 and _mm_mulhi_epu16 functions. + "pmulh.w" | "pmulhu.w" => { + let [left, right] = this.check_shim_sig_llvm_intrinsic(link_name, args)?; + + let (left, left_len) = this.project_to_simd(left)?; + let (right, right_len) = this.project_to_simd(right)?; + let (dest, dest_len) = this.project_to_simd(dest)?; + + assert_eq!(dest_len, left_len); + assert_eq!(dest_len, right_len); + + for i in 0..dest_len { + let left = this.read_immediate(&this.project_index(&left, i)?)?; + let right = this.read_immediate(&this.project_index(&right, i)?)?; + let dest = this.project_index(&dest, i)?; + + // Widen the operands to avoid overflow + let twice_wide = this.layout_of(this.get_twice_wide_int_ty(left.layout.ty))?; + let left = this.int_to_int_or_float(&left, twice_wide)?; + let right = this.int_to_int_or_float(&right, twice_wide)?; + + // Multiply + let multiplied = this.binary_op(mir::BinOp::Mul, &left, &right)?; + // Keep the high half + let high = this.binary_op( + mir::BinOp::Shr, + &multiplied, + &ImmTy::from_uint(dest.layout.size.bits(), twice_wide), + )?; + + // Narrow back to the original type + let res = this.int_to_int_or_float(&high, dest.layout)?; + this.write_immediate(*res, &dest)?; + } + } _ => return interp_ok(EmulateItemResult::NotSupported), } interp_ok(EmulateItemResult::NeedsReturn) From 852ac9e50be7f4d6f4033c5881fea5a4814eb804 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 29 Sep 2026 18:40:59 +0200 Subject: [PATCH 1009/1309] Update rust-toolchain version needed --- rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain.toml b/rust-toolchain.toml index a7774784e3afa..63af0047e6e00 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-24" +channel = "nightly-2026-09-29" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From 14d09db59484630e56870e09a094254890b4b27f Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 29 Sep 2026 18:38:13 +0200 Subject: [PATCH 1010/1309] cycle handling: mirror old solver --- .../src/solve/eval_ctxt/mod.rs | 87 ++++++++----------- .../rustc_next_trait_solver/src/solve/mod.rs | 4 +- .../src/solve/normalizes_to.rs | 4 +- .../src/solve/project_goals/free_alias.rs | 4 +- .../src/solve/project_goals/inherent.rs | 4 +- .../src/solve/project_goals/mod.rs | 2 +- .../src/solve/project_goals/opaque_types.rs | 7 +- .../src/solve/fulfill/derive_errors.rs | 2 +- compiler/rustc_type_ir/src/solve/mod.rs | 24 ++--- .../sized-hierarchy/overflow.current.stderr | 12 +-- tests/ui/sized-hierarchy/overflow.next.stderr | 29 +++++++ tests/ui/sized-hierarchy/overflow.rs | 7 +- ...inductive-step-needed-trait.current.stderr | 6 +- ...-coinductive-step-needed-trait.next.stderr | 15 ++++ .../only-one-coinductive-step-needed-trait.rs | 4 +- ...one-coinductive-step-needed.current.stderr | 4 +- ...ly-one-coinductive-step-needed.next.stderr | 43 +++++++++ .../only-one-coinductive-step-needed.rs | 11 ++- 18 files changed, 166 insertions(+), 103 deletions(-) create mode 100644 tests/ui/sized-hierarchy/overflow.next.stderr create mode 100644 tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.next.stderr create mode 100644 tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.next.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index c841845392429..40febd26806a6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -63,6 +63,8 @@ enum CurrentGoalKind { /// These are currently the only goals whose impl where-clauses are considered to be /// productive steps. CoinductiveTrait, + /// A `ProjectionGoal`. These are temporarily special wrt to cycle handling. + Projection, // FIXME: Consider renaming `PredicateKind::NormalizesTo` to match with this /// Unlike other goals, `NormalizesTo` goals aren't independent goals but just implementation /// details for handling projections of associated terms. When we encounter a `Projection` goal @@ -89,6 +91,7 @@ impl CurrentGoalKind { CurrentGoalKind::Misc } } + ty::PredicateKind::Clause(ty::ClauseKind::Projection(_)) => CurrentGoalKind::Projection, ty::PredicateKind::NormalizesTo(_) => { CurrentGoalKind::ProjectionComputeAssocTermCandidate } @@ -428,46 +431,29 @@ where } /// Computes the `PathKind` for the step from the current goal to the - /// nested goal required due to `source`. + /// nested goal. See #136824 for a more detailed reasoning for this why we care about + /// the step from a goal to its nested goals. /// - /// See #136824 for a more detailed reasoning for this behavior. We - /// consider cycles to be coinductive if they 'step into' a where-clause - /// of a coinductive trait. We will likely extend this function in the future - /// and will need to clearly document it in the rustc-dev-guide before - /// stabilization. - pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind { - match source { - // We treat these goals as unknown for now. It is likely that most miscellaneous - // nested goals will be converted to an inductive variant in the future. - // - // Having unknown cycles is always the safer option, as changing that to either - // succeed or hard error is backwards compatible. If we incorrectly treat a cycle - // as inductive even though it should not be, it may be unsound during coherence and - // fixing it may cause inference breakage or introduce ambiguity. - GoalSource::Misc => PathKind::Unknown, - GoalSource::NormalizeGoal(path_kind) => path_kind, - GoalSource::ImplWhereBound => match self.current_goal_kind { - // We currently only consider a cycle coinductive if it steps - // into a where-clause of a coinductive trait. - CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive, - // We probably want to make all traits coinductive in the future, - // so we treat cycles involving where-clauses of not-yet coinductive - // traits as ambiguous for now. - CurrentGoalKind::Misc | CurrentGoalKind::ProjectionComputeAssocTermCandidate => { - PathKind::Unknown - } - }, - // Relating types is always unproductive. If we were to map proof trees to - // corecursive functions as explained in #136824, relating types never - // introduces a constructor which could cause the recursion to be guarded. - // - // FIXME(-Znext-solver=coinductive): For now we treat all inductive cycles as - // `Unknown`. See the comment in `fn initial_provisional_result`. - GoalSource::TypeRelating => PathKind::Unknown, - // These goal sources are likely unproductive and can be changed to - // `PathKind::Inductive`. Keeping them as unknown until we're confident - // about this and have an example where it is necessary. - GoalSource::AliasBoundConstCondition | GoalSource::AliasWellFormed => PathKind::Unknown, + /// For now we're entirely ignoring the reason why the current goal depends on the + /// nested goal and instead only depend on the current goal itself. This closely + /// matches the old solver. This is something we'll likely improve as we go forward + /// afterwards. + // FIXME(-Znext-solver=coinductive): Nothing interesting going on here right now + // and we're ignoring the goal source. We should change this going forward. + pub(super) fn step_kind_to_nested(&self, _source: GoalSource) -> PathKind { + match self.current_goal_kind { + // We currently consider a cycle involving a trait goal for a coinductive + // trait as coinductive as long as it otherwise only includes normalization. + CurrentGoalKind::CoinductiveTrait => PathKind::Coinductive, + // We do need to treat cycles involving only coinductive trait goals + // and normalization as coinductive due to trait-system-refactor-initiative#10. + CurrentGoalKind::ProjectionComputeAssocTermCandidate | CurrentGoalKind::Projection => { + PathKind::Unknown + } + // We probably want to make all traits coinductive in the future, + // so we treat cycles involving where-clauses of not-yet coinductive + // traits as ambiguous for now. + CurrentGoalKind::Misc => PathKind::ForcedAmbiguity, } } @@ -771,7 +757,7 @@ where let (goal, opaque_types) = self.delegate.deeply_resolve_via_unification_table((goal, opaque_types)); let typing_mode = self.typing_mode(); - let step_kind = self.step_kind_for_source(source); + let step_kind = self.step_kind_to_nested(source); let tracing_span = tracing::span!( Level::DEBUG, @@ -1109,11 +1095,8 @@ where source: GoalSource, mut goal: Goal, ) -> Result<(), NoSolutionOrRerunNonErased> { - goal.predicate = self.normalize( - GoalSource::NormalizeGoal(self.step_kind_for_source(source)), - goal.param_env, - ty::Unnormalized::new_wip(goal.predicate), - )?; + goal.predicate = + self.normalize(goal.param_env, ty::Unnormalized::new_wip(goal.predicate))?; self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); if let Some(GoalEvaluation { goal, certainty, has_changed: _, stalled_on }) = @@ -1339,10 +1322,12 @@ where let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?; for &goal in goals.iter() { let source = match goal.predicate.kind().skip_binder() { - ty::PredicateKind::Subtype { .. } - | ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { - GoalSource::TypeRelating + ty::PredicateKind::Clause(ty::ClauseKind::Projection(..)) => { + GoalSource::Normalization } + // FIXME(-Znext-solver=coinductive): subtyping goals should + // likely be unproductive + ty::PredicateKind::Subtype { .. } => GoalSource::Misc, // FIXME(-Znext-solver=coinductive): should these WF goals also be unproductive? ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(_)) => GoalSource::Misc, p => unreachable!("unexpected nested goal in `relate`: {p:?}"), @@ -1519,9 +1504,7 @@ where match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } - self.delegate.evaluate_const(param_env, alias_const, |ty| { - self.normalize(GoalSource::Misc, param_env, ty) - }) + self.delegate.evaluate_const(param_env, alias_const, |ty| self.normalize(param_env, ty)) } pub(super) fn evaluate_const_and_instantiate_projection_term( @@ -1803,7 +1786,6 @@ where pub(super) fn normalize>( &mut self, - source: GoalSource, param_env: I::ParamEnv, value: ty::Unnormalized, ) -> Result { @@ -1819,6 +1801,7 @@ where let infer_term = self.next_term_infer_of_alias_kind(alias_term); let pred = ty::ProjectionClause { projection_term: alias_term, term: infer_term }; let goal = Goal::new(self.cx(), param_env, pred); + let source = GoalSource::Normalization; self.inspect.add_goal(self.delegate, self.max_input_universe, source, goal); let GoalEvaluation { goal, certainty, has_changed: _, stalled_on } = self.evaluate_goal(source, goal, None)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index dddc78373b1b5..9ecb7619d7c93 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -90,7 +90,7 @@ where goal: Goal>, ) -> QueryResultOrRerunNonErased { let ty::OutlivesClause(ty, lt) = goal.predicate; - let ty = self.normalize(GoalSource::Misc, goal.param_env, ty::Unnormalized::new_wip(ty))?; + let ty = self.normalize(goal.param_env, ty::Unnormalized::new_wip(ty))?; // The normalized type can still contain non-rigid higher ranked aliases if their // normalization ends up with ambiguity. Or we have non-rigid aliases inside rigid ones. @@ -405,7 +405,7 @@ where ); // We normalize the self type to be able to relate it with // types from candidates. - self.add_goal(GoalSource::TypeRelating, projection_goal)?; + self.add_goal(GoalSource::Normalization, projection_goal)?; self.try_evaluate_added_goals()?; Ok(self.deeply_resolve_ignoring_regions(normalized_term)) } else { diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index 388b334ccf618..4203ae8c509cc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -439,7 +439,7 @@ where let term = match target_item_kind { ty::AliasTermKind::ProjectionTy { .. } => { let t = cx.type_of(target_item_def_id).instantiate(cx, target_args); - let t = ecx.normalize(GoalSource::Misc, goal.param_env, t)?; + let t = ecx.normalize(goal.param_env, t)?; t.into() } ty::AliasTermKind::ProjectionConst { def_id } @@ -447,7 +447,7 @@ where cx.const_of_item(ty::AliasConstKind::Projection { def_id }) => { let c = c.instantiate(cx, target_args); - let c = ecx.normalize(GoalSource::Misc, goal.param_env, c)?; + let c = ecx.normalize(goal.param_env, c)?; c.into() } ty::AliasTermKind::ProjectionConst { .. } => { diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs index 4481e1bc144ac..dfcc89b91a4f2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/free_alias.rs @@ -34,14 +34,14 @@ where let actual = match free_alias.kind { ty::AliasTermKind::FreeTy { def_id } => { let free = cx.type_of(def_id.into()).instantiate(cx, free_alias.args); - let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; + let free = self.normalize(goal.param_env, free)?; free.into() } ty::AliasTermKind::FreeConst { def_id } if let Some(free) = cx.const_of_item(ty::AliasConstKind::Free { def_id }) => { let free = free.instantiate(cx, free_alias.args); - let free = self.normalize(GoalSource::Misc, goal.param_env, free)?; + let free = self.normalize(goal.param_env, free)?; free.into() } diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs index d519d1e538f1a..45ece5a0589fb 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/inherent.rs @@ -45,7 +45,7 @@ where let normalized: I::Term = match inherent_kind { ty::AliasTermKind::InherentTy { def_id } => { let inherent = cx.type_of(def_id.into()).instantiate(cx, inherent_args); - let inherent = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; + let inherent = self.normalize(goal.param_env, inherent)?; inherent.into() } ty::AliasTermKind::InherentConstImpl { def_id } @@ -53,7 +53,7 @@ where cx.const_of_item(ty::AliasConstKind::InherentImpl { def_id }) => { let inherent = inherent.instantiate(cx, inherent_args); - let normalized_ct = self.normalize(GoalSource::Misc, goal.param_env, inherent)?; + let normalized_ct = self.normalize(goal.param_env, inherent)?; let normalized = normalized_ct.into(); let term = ty::AliasTerm::new_from_args(cx, inherent_kind, inherent_args); self.push_const_arg_has_type_goal(goal.param_env, term, normalized)?; diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs index 9d6b8875071ba..f6521e579d722 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/mod.rs @@ -69,7 +69,7 @@ where let ( NestedNormalizationGoals(nested_goals), GoalEvaluation { goal: _, certainty, stalled_on: _, has_changed: _ }, - ) = self.evaluate_goal_raw(GoalSource::TypeRelating, normalizes_to)?; + ) = self.evaluate_goal_raw(GoalSource::Normalization, normalizes_to)?; trace!(?nested_goals); diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs index 2f56056449779..048c8bb45361b 100644 --- a/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs +++ b/compiler/rustc_next_trait_solver/src/solve/project_goals/opaque_types.rs @@ -99,8 +99,7 @@ where _ => re, }) }); - let actual = - self.normalize(GoalSource::Misc, goal.param_env, actual)?; + let actual = self.normalize(goal.param_env, actual)?; self.eq(goal.param_env, expected, actual)?; } TypingMode::Coherence @@ -145,7 +144,7 @@ where _ => re, }) }); - let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; + let actual = self.normalize(goal.param_env, actual)?; self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) @@ -154,7 +153,7 @@ where TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { // FIXME: Add an assertion that opaque type storage is empty. let actual = cx.type_of(def_id.into()).instantiate(cx, opaque_ty.args); - let actual = self.normalize(GoalSource::Misc, goal.param_env, actual)?; + let actual = self.normalize(goal.param_env, actual)?; self.eq(goal.param_env, expected, actual)?; self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) .map_err(Into::into) diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index d30421a762ea9..5ccd7ff7ef55b 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -510,7 +510,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> { match (child_mode, nested_goal.source()) { ( ChildMode::Trait(_) | ChildMode::Host(_), - GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_), + GoalSource::Misc | GoalSource::Normalization, ) => { continue; } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index c6d88bb6603de..5d1472d5941f2 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -16,7 +16,6 @@ use tracing::debug; use crate::inherent::*; use crate::lang_items::SolverTraitLangItem; use crate::region_constraint::RegionConstraint; -use crate::search_graph::PathKind; use crate::{ self as ty, Canonical, CanonicalVarValues, CantBeErased, Const, ConstVid, FloatVid, GenericArgKind, InferConst, IntVid, Interner, TermKind, TyVid, TypingMode, Upcast, @@ -411,22 +410,15 @@ impl Goal { /// Why a specific goal has to be proven. /// -/// This is necessary as we treat nested goals different depending on -/// their source. This is used to decide whether a cycle is coinductive. -/// See the documentation of `EvalCtxt::step_kind_for_source` for more details -/// about this. +/// This is used by proof tree visitors, especially for diagnostics purposes. /// -/// It is also used by proof tree visitors, e.g. for diagnostics purposes. +/// FIXME(-Znext-solver=coinductive): This will also matter in the future when +/// deciding whether a step in a cycle is coinductive. We're currently still +/// matching the old solver behavior here for now, so the `GoalSource` is ignored. #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)] #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum GoalSource { Misc, - /// A nested goal required to prove that types are equal/subtypes. - /// This is always an unproductive step. - /// - /// This is also used for all `NormalizesTo` goals as we they are used - /// to relate types in `AliasRelate`. - TypeRelating, /// We're proving a where-bound of an impl. ImplWhereBound, /// Const conditions that need to hold for `[const]` alias bounds to hold. @@ -438,12 +430,8 @@ pub enum GoalSource { /// 2. for rigid projections's trait goal, /// 3. for GAT where clauses. AliasWellFormed, - /// In case normalizing aliases in nested goals cycles, eagerly normalizing these - /// aliases in the context of the parent may incorrectly change the cycle kind. - /// Normalizing aliases in goals therefore tracks the original path kind for this - /// nested goal. See the comment of the `ReplaceAliasWithInfer` visitor for more - /// details. - NormalizeGoal(PathKind), + /// Normalizing happens in the current context and is unproductive by itself. + Normalization, } #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, Goal)] diff --git a/tests/ui/sized-hierarchy/overflow.current.stderr b/tests/ui/sized-hierarchy/overflow.current.stderr index 9853be2a7f8e0..3573ee48db57c 100644 --- a/tests/ui/sized-hierarchy/overflow.current.stderr +++ b/tests/ui/sized-hierarchy/overflow.current.stderr @@ -1,11 +1,11 @@ error[E0275]: overflow evaluating the requirement `Element: MetaSized` - --> $DIR/overflow.rs:17:16 + --> $DIR/overflow.rs:15:16 | LL | struct Element(> as ParseTokens>::Output); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `Box` to implement `ParseTokens` - --> $DIR/overflow.rs:13:31 + --> $DIR/overflow.rs:11:31 | LL | impl ParseTokens for Box { | ------ ^^^^^^^^^^^ ^^^^^^ @@ -15,25 +15,25 @@ LL | impl ParseTokens for Box { = note: required for `Box>` to implement `ParseTokens` error[E0275]: overflow evaluating the requirement `Box: ParseTokens` - --> $DIR/overflow.rs:19:22 + --> $DIR/overflow.rs:18:22 | LL | impl ParseTokens for Element { | ^^^^^^^ | note: required for `Box>` to implement `ParseTokens` - --> $DIR/overflow.rs:13:31 + --> $DIR/overflow.rs:11:31 | LL | impl ParseTokens for Box { | ----------- ^^^^^^^^^^^ ^^^^^^ | | | unsatisfied trait bound introduced here note: required because it appears within the type `Element` - --> $DIR/overflow.rs:17:8 + --> $DIR/overflow.rs:15:8 | LL | struct Element(> as ParseTokens>::Output); | ^^^^^^^ note: required by a bound in `ParseTokens` - --> $DIR/overflow.rs:10:1 + --> $DIR/overflow.rs:8:1 | LL | / trait ParseTokens { LL | | type Output; diff --git a/tests/ui/sized-hierarchy/overflow.next.stderr b/tests/ui/sized-hierarchy/overflow.next.stderr new file mode 100644 index 0000000000000..69842a298f87f --- /dev/null +++ b/tests/ui/sized-hierarchy/overflow.next.stderr @@ -0,0 +1,29 @@ +error[E0275]: overflow evaluating the requirement `> as ParseTokens>::Output == _` + --> $DIR/overflow.rs:15:16 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating whether `> as ParseTokens>::Output` is well-formed + --> $DIR/overflow.rs:15:16 + | +LL | struct Element(> as ParseTokens>::Output); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `Element: MetaSized` + --> $DIR/overflow.rs:18:22 + | +LL | impl ParseTokens for Element { + | ^^^^^^^ + | +note: required by a bound in `ParseTokens` + --> $DIR/overflow.rs:8:1 + | +LL | / trait ParseTokens { +LL | | type Output; +LL | | } + | |_^ required by this bound in `ParseTokens` + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/sized-hierarchy/overflow.rs b/tests/ui/sized-hierarchy/overflow.rs index 31c2ca8a49171..f69f56ef898e2 100644 --- a/tests/ui/sized-hierarchy/overflow.rs +++ b/tests/ui/sized-hierarchy/overflow.rs @@ -1,8 +1,6 @@ //@ compile-flags: --crate-type=lib //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) -//@[current] check-fail -//@[next] check-pass //@[next] compile-flags: -Znext-solver use std::marker::PhantomData; @@ -15,8 +13,9 @@ impl ParseTokens for Box { } struct Element(> as ParseTokens>::Output); -//[current]~^ ERROR: overflow +//~^ ERROR: overflow +//[next]~| ERROR: overflow impl ParseTokens for Element { -//[current]~^ ERROR: overflow +//~^ ERROR: overflow type Output = (); } diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.current.stderr b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.current.stderr index 89b8b53c3f4d9..d6cd080cbfd0b 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.current.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.current.stderr @@ -1,18 +1,18 @@ error[E0275]: overflow evaluating the requirement `u32: SendIndir>` - --> $DIR/only-one-coinductive-step-needed-trait.rs:24:5 + --> $DIR/only-one-coinductive-step-needed-trait.rs:25:5 | LL | is_send::>(); | ^^^^^^^^^^^^^^^^^^^^^ | note: required for `Foo` to implement `Send` - --> $DIR/only-one-coinductive-step-needed-trait.rs:17:35 + --> $DIR/only-one-coinductive-step-needed-trait.rs:18:35 | LL | unsafe impl>> Send for Foo {} | ----------------- ^^^^ ^^^^^^ | | | unsatisfied trait bound introduced here note: required by a bound in `is_send` - --> $DIR/only-one-coinductive-step-needed-trait.rs:22:15 + --> $DIR/only-one-coinductive-step-needed-trait.rs:23:15 | LL | fn is_send() {} | ^^^^ required by this bound in `is_send` diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.next.stderr b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.next.stderr new file mode 100644 index 0000000000000..40ae37e495204 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `Foo: Send` + --> $DIR/only-one-coinductive-step-needed-trait.rs:25:15 + | +LL | is_send::>(); + | ^^^^^^^^ + | +note: required by a bound in `is_send` + --> $DIR/only-one-coinductive-step-needed-trait.rs:23:15 + | +LL | fn is_send() {} + | ^^^^ required by this bound in `is_send` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.rs b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.rs index 294156869284a..a8d23129fb87c 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed-trait.rs @@ -1,7 +1,6 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass // #136824 changed cycles to be coinductive if they have at least // one productive step, causing this test to pass with the new solver. @@ -12,6 +11,8 @@ // - `Foo: Send` cycle // // The old solver treats this cycle as inductive due to the `T: SendIndir` step. +// We later changed the new solver to temporarily be closer to the old solver +// again, so this now errors with both solvers. struct Foo(T); unsafe impl>> Send for Foo {} @@ -23,4 +24,5 @@ fn is_send() {} fn main() { is_send::>(); //[current]~^ ERROR overflow evaluating the requirement `u32: SendIndir>` + //[next]~^^ ERROR overflow evaluating the requirement `Foo: Send` } diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.current.stderr b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.current.stderr index ec21987805869..1d7916f32b1db 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.current.stderr +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.current.stderr @@ -1,11 +1,11 @@ error[E0275]: overflow evaluating the requirement `Foo: SendIndir` - --> $DIR/only-one-coinductive-step-needed.rs:17:15 + --> $DIR/only-one-coinductive-step-needed.rs:18:15 | LL | struct Foo( as Trait>::Assoc); | ^^^^^^^^^^^^^^^^^^^^^^^^ | note: required for `Foo` to implement `Trait` - --> $DIR/only-one-coinductive-step-needed.rs:26:20 + --> $DIR/only-one-coinductive-step-needed.rs:29:20 | LL | impl Trait for T { | --------- ^^^^^ ^ diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.next.stderr b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.next.stderr new file mode 100644 index 0000000000000..071945d760345 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.next.stderr @@ -0,0 +1,43 @@ +error[E0275]: overflow evaluating the requirement ` as Trait>::Assoc == _` + --> $DIR/only-one-coinductive-step-needed.rs:18:15 + | +LL | struct Foo( as Trait>::Assoc); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating whether ` as Trait>::Assoc` is well-formed + --> $DIR/only-one-coinductive-step-needed.rs:18:15 + | +LL | struct Foo( as Trait>::Assoc); + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `Foo: Send` + --> $DIR/only-one-coinductive-step-needed.rs:36:15 + | +LL | is_send::>(); + | ^^^^^^^^ + | +note: required by a bound in `is_send` + --> $DIR/only-one-coinductive-step-needed.rs:33:15 + | +LL | fn is_send() {} + | ^^^^ required by this bound in `is_send` + +error[E0275]: overflow evaluating the requirement `Foo: Sized` + --> $DIR/only-one-coinductive-step-needed.rs:36:15 + | +LL | is_send::>(); + | ^^^^^^^^ + | +note: required by an implicit `Sized` bound in `is_send` + --> $DIR/only-one-coinductive-step-needed.rs:33:12 + | +LL | fn is_send() {} + | ^ required by the implicit `Sized` requirement on this type parameter in `is_send` +help: consider relaxing the implicit `Sized` restriction + | +LL | fn is_send() {} + | ++++++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.rs b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.rs index e41f7d7f3ceb3..9a13c0e945339 100644 --- a/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.rs +++ b/tests/ui/traits/next-solver/cycles/coinduction/only-one-coinductive-step-needed.rs @@ -1,7 +1,6 @@ //@ revisions: current next //@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver -//@[next] check-pass // #136824 changed cycles to be coinductive if they have at least // one productive step, causing this test to pass with the new solver. @@ -12,10 +11,14 @@ // - `Foo: SendIndir`, via impl requires // - `Foo: Send` cycle // -// The old solver treats this cycle as inductive due to the `Foo: SendIndir` step. +// The old solver treats this cycle as inductive due to the `Foo: SendIndir` step. We've +// since changed the new solver to more closely match the old one here, also +// resulting in an inductive cycle for now. struct Foo( as Trait>::Assoc); -//[current]~^ ERROR overflow evaluating the requirement `Foo: SendIndir` +//[current]~^ ERROR: overflow evaluating the requirement `Foo: SendIndir` +//[next]~^^ ERROR: overflow evaluating the requirement ` as Trait>::Assoc == _` +//[next]~| ERROR: overflow evaluating whether ` as Trait>::Assoc` is well-formed trait SendIndir {} impl SendIndir for T {} @@ -31,4 +34,6 @@ fn is_send() {} fn main() { is_send::>(); + //[next]~^ ERROR: overflow evaluating the requirement `Foo: Send` + //[next]~| ERROR: overflow evaluating the requirement `Foo: Sized` } From 99055eee3a49e1bca06855cd3f066384728a370a Mon Sep 17 00:00:00 2001 From: David Carlier Date: Tue, 29 Sep 2026 18:26:29 +0100 Subject: [PATCH 1011/1309] Revert "Rollup merge of #120589 - devnexen:cpuaff_fbsd_upd, r=clarfonthey" This reverts commit 0a4206a71433bcad48d9447b080a874b1b06d54f, reversing changes made to 8f3a9a10173f6c52a20bb31e96ae903360733aaf. --- library/std/src/sys/thread/unix.rs | 40 +++++++++++++++++++++--------- 1 file changed, 28 insertions(+), 12 deletions(-) diff --git a/library/std/src/sys/thread/unix.rs b/library/std/src/sys/thread/unix.rs index 11fe569f8e0a9..b7908dea2b5de 100644 --- a/library/std/src/sys/thread/unix.rs +++ b/library/std/src/sys/thread/unix.rs @@ -162,7 +162,6 @@ pub fn available_parallelism() -> io::Result> { target_os = "hurd", target_os = "linux", target_os = "aix", - target_os = "freebsd", target_vendor = "apple", target_os = "cygwin", target_os = "redox", @@ -175,17 +174,9 @@ pub fn available_parallelism() -> io::Result> { #[cfg(any(target_os = "android", target_os = "linux"))] { quota = cgroups::quota().max(1); - } - - #[cfg(any(target_os = "android", target_os = "linux", target_os = "freebsd"))] - { - #[cfg(not(target_os = "freebsd"))] - type Cpuset = libc::cpu_set_t; - #[cfg(target_os = "freebsd")] - type Cpuset = libc::cpuset_t; - let mut set: Cpuset = unsafe { mem::zeroed() }; + let mut set: libc::cpu_set_t = unsafe { mem::zeroed() }; unsafe { - if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { + if libc::sched_getaffinity(0, size_of::(), &mut set) == 0 { let count = libc::CPU_COUNT(&set) as usize; let count = count.min(quota); @@ -210,9 +201,34 @@ pub fn available_parallelism() -> io::Result> { } } } - any(target_os = "dragonfly", target_os = "openbsd", target_os = "netbsd") => { + any( + target_os = "freebsd", + target_os = "dragonfly", + target_os = "openbsd", + target_os = "netbsd", + ) => { use crate::ptr; + #[cfg(target_os = "freebsd")] + { + let mut set: libc::cpuset_t = unsafe { mem::zeroed() }; + unsafe { + if libc::cpuset_getaffinity( + libc::CPU_LEVEL_WHICH, + libc::CPU_WHICH_PID, + -1, + size_of::(), + &mut set, + ) == 0 + { + let count = libc::CPU_COUNT(&set) as usize; + if count > 0 { + return Ok(NonZero::new_unchecked(count)); + } + } + } + } + #[cfg(target_os = "netbsd")] { unsafe { From 1cfc3914c5ce3fbfd9cf0408aadfd0f15d4dcd82 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Thu, 24 Sep 2026 11:39:25 +0200 Subject: [PATCH 1012/1309] disable toctou test for qnx --- library/std/src/fs/tests.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index db9a9f3f20b88..4afa0f444209a 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -3099,6 +3099,10 @@ fn test_dir_rename_file() { assert_eq!(b"bar", &buf); } +// FIXME: re-enable once QNX fixes TOCTOU bug for fs::remove_dir +// Note that it may get fixed in QNX 8 in a future libc release +// ... https://github.com/rust-lang/rust/issues/153781 +#[cfg_attr(any(target_os = "nto", target_os = "qnx"), ignore)] #[test] fn test_dir_remove_dir() { let tmpdir = tmpdir(); From 10448a35f3c8ac72c48bc970c70315199a134959 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 29 Sep 2026 13:56:37 -0400 Subject: [PATCH 1013/1309] Fix panic when casting from i128 to f16 --- src/int.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/int.rs b/src/int.rs index 4e4b911666143..de8762d1c06b4 100644 --- a/src/int.rs +++ b/src/int.rs @@ -954,6 +954,10 @@ impl<'gcc, 'tcx> CodegenCx<'gcc, 'tcx> { debug_assert!(value_type.dyncast_array().is_some()); let name_suffix = match self.type_kind(dest_typ) { + TypeKind::Half if dest_typ.is_compatible_with(self.type_f16()) => { + let value = self.int_to_float_cast(signed, value, self.float_type); + return self.context.new_cast(None, value, dest_typ); + } // cSpell:disable TypeKind::Float => "tisf", TypeKind::Double => "tidf", From b3cf6a588a32a09a10e286a193efcdd48f695dfc Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 29 Sep 2026 13:58:57 -0400 Subject: [PATCH 1014/1309] Install rustfmt stdarch CI workflow --- .github/workflows/stdarch.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 34499c6e7b522..4afb74a1f8cdd 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -32,6 +32,10 @@ jobs: - name: Setup rust toolchain run: rustup show + # The stdarch-gen-common tests run rustfmt. + - name: Install rustfmt + run: rustup component add rustfmt + - name: Setup rust cache uses: Swatinem/rust-cache@v2 From 5694cdbacc98ecae55341d8c1efcfa4052fe6c02 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Mon, 28 Sep 2026 12:08:59 +0330 Subject: [PATCH 1015/1309] merge candidate responses equal except for region constraints Co-authored-by: adwin Co-authored-by: lcnr Signed-off-by: Amirhossein Akhlaghpour --- .../rustc_next_trait_solver/src/solve/mod.rs | 59 +++++++++++++++++-- ...-candidates-modulo-regions-issue-162323.rs | 45 ++++++++++++++ 2 files changed, 100 insertions(+), 4 deletions(-) create mode 100644 tests/ui/traits/next-solver/projection-candidates-modulo-regions-issue-162323.rs diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 8d20bcf4c7a6d..00aa626504e48 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -79,6 +79,34 @@ fn has_only_region_constraints(response: ty::Canonical( + a: &CanonicalResponse, + b: &CanonicalResponse, +) -> bool { + let CanonicalResponse { + max_universe: a_max_universe, + var_kinds: a_var_kinds, + value: + Response { + var_values: a_var_values, + certainty: a_certainty, + external_constraints: a_external_constraints, + }, + } = a; + + let ExternalConstraintsData { region_constraints: _, opaque_types, normalization_nested_goals } = + &**a_external_constraints; + + a_max_universe == &b.max_universe + && a_var_kinds == &b.var_kinds + && a_var_values == &b.value.var_values + && a_certainty == &b.value.certainty + && opaque_types == &b.value.external_constraints.opaque_types + && normalization_nested_goals == &b.value.external_constraints.normalization_nested_goals +} + impl<'a, D, I> EvalCtxt<'a, D> where D: SolverDelegate, @@ -315,13 +343,36 @@ where candidate.result.value.certainty == Certainty::Yes && has_no_inference_or_external_constraints(candidate.result) }); - if let Some((i, c)) = always_applicable { - return Some((c.result, MergeCandidateInfo::AlwaysApplicable(i))); + + if let Some((i, candidate)) = always_applicable { + return Some((candidate.result, MergeCandidateInfo::AlwaysApplicable(i))); } let one: CanonicalResponse = candidates[0].result; - if candidates[1..].iter().all(|candidate| candidate.result == one) { - return Some((one, MergeCandidateInfo::EqualResponse)); + + if candidates[1..] + .iter() + .all(|candidate| equal_response_modulo_region_constraints(&one, &candidate.result)) + { + let region_constraints = &one.value.external_constraints.region_constraints; + if candidates[1..].iter().all(|candidate| { + &candidate.result.value.external_constraints.region_constraints + == region_constraints + }) { + return Some((one, MergeCandidateInfo::EqualResponse)); + } + + // If candidates differ only in region constraints, their merged region + // constraints are an `Or` of their respective constraints. If one of them + // has no region constraints, the `Or` constraint evaluates to `true`. + // + // This is a special case of `-Zassumptions-on-binders` and should be + // replaced eventually. + if let Some(candidate) = candidates.iter().find(|candidate| { + candidate.result.value.external_constraints.region_constraints.is_empty() + }) { + return Some((candidate.result, MergeCandidateInfo::EqualResponse)); + } } None diff --git a/tests/ui/traits/next-solver/projection-candidates-modulo-regions-issue-162323.rs b/tests/ui/traits/next-solver/projection-candidates-modulo-regions-issue-162323.rs new file mode 100644 index 0000000000000..779a097385622 --- /dev/null +++ b/tests/ui/traits/next-solver/projection-candidates-modulo-regions-issue-162323.rs @@ -0,0 +1,45 @@ +//@ check-pass +//@ compile-flags: -Znext-solver=globally + +// Two alias-bound candidates normalize `V` to `Input`, but differ in +// their region constraints. One candidate has no region constraints, +// allowing the responses to be merged. + +struct Input; + +struct MyRhs; + +trait Jac { + type V; + fn jacobian(&self, x: Self::V); +} + +impl Jac for MyRhs { + type V = Input; + + fn jacobian(&self, _: Self::V) {} +} + +struct MyEqns; + +trait EqnsRef<'a, ImplicitBounds = &'a ()> { + type Rhs: Jac; + + fn rhs(&'a self) -> Self::Rhs; +} + +impl<'a> EqnsRef<'a> for MyEqns { + type Rhs = MyRhs; + + fn rhs(&'a self) -> Self::Rhs { + MyRhs + } +} + +fn inner() -> impl for<'a> EqnsRef<'a, Rhs: Jac> { + MyEqns +} + +fn main() { + inner().rhs().jacobian(Input); +} From 36358d0b2a1acaa99008ca13d1e41eac4adb1009 Mon Sep 17 00:00:00 2001 From: eleocraft Date: Tue, 29 Sep 2026 20:20:16 +0200 Subject: [PATCH 1016/1309] gating f16 and f128 tests behind target_has_reliable --- library/coretests/tests/num/clamp_magnitude.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/coretests/tests/num/clamp_magnitude.rs b/library/coretests/tests/num/clamp_magnitude.rs index 5bccc4ad45e20..fdb605780a2c6 100644 --- a/library/coretests/tests/num/clamp_magnitude.rs +++ b/library/coretests/tests/num/clamp_magnitude.rs @@ -208,6 +208,7 @@ macro_rules! check_float_clamp { } #[test] +#[cfg(target_has_reliable_f16)] fn test_clamp_magnitude_f16() { check_float_clamp!(f16, 1e3); } @@ -223,11 +224,13 @@ fn test_clamp_magnitude_f64() { } #[test] +#[cfg(target_has_reliable_f128)] fn test_clamp_magnitude_f128() { check_float_clamp!(f128, 1e3000); } #[test] +#[cfg(target_has_reliable_f16)] #[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f16_panic_negative_limit() { let _ = 1.0f16.clamp_magnitude(-1.0); @@ -246,12 +249,14 @@ fn test_clamp_magnitude_f64_panic_negative_limit() { } #[test] +#[cfg(target_has_reliable_f128)] #[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f128_panic_negative_limit() { let _ = 1.0f128.clamp_magnitude(-1.0); } #[test] +#[cfg(target_has_reliable_f16)] #[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f16_panic_nan_limit() { let _ = 1.0f16.clamp_magnitude(f16::NAN); @@ -270,6 +275,7 @@ fn test_clamp_magnitude_f64_panic_nan_limit() { } #[test] +#[cfg(target_has_reliable_f128)] #[should_panic(expected = "limit must be non-negative and not NaN")] fn test_clamp_magnitude_f128_panic_nan_limit() { let _ = 1.0f128.clamp_magnitude(f128::NAN); From 0317026d59e470f8ca48e96d557bb3320931ba6b Mon Sep 17 00:00:00 2001 From: Crystal Durham Date: Mon, 31 Aug 2026 15:05:37 -0500 Subject: [PATCH 1017/1309] impl std::fs::{Home|Media}Dirs also includes: - std::env::split_paths_ref - std::os::{darwin|unix|windows}::{Home|Media}DirsExt --- library/std/src/env.rs | 51 ++ library/std/src/fs.rs | 7 + library/std/src/fs/dirs.rs | 588 ++++++++++++++++++ library/std/src/os/darwin/fs.rs | 7 + library/std/src/os/darwin/fs/dirs.rs | 313 ++++++++++ library/std/src/os/unix/fs.rs | 7 + library/std/src/os/unix/fs/dirs.rs | 585 +++++++++++++++++ library/std/src/os/windows/fs.rs | 7 + library/std/src/os/windows/fs/dirs.rs | 309 +++++++++ library/std/src/sys/fs/common.rs | 8 + library/std/src/sys/fs/hermit.rs | 2 +- library/std/src/sys/fs/mod.rs | 7 +- library/std/src/sys/fs/motor.rs | 2 +- library/std/src/sys/fs/solid.rs | 2 +- library/std/src/sys/fs/uefi.rs | 2 +- library/std/src/sys/fs/unix.rs | 4 + library/std/src/sys/fs/unsupported.rs | 2 +- library/std/src/sys/fs/vexos.rs | 2 + library/std/src/sys/fs/windows.rs | 1 + library/std/src/sys/pal/windows/c.rs | 45 ++ .../std/src/sys/pal/windows/c/bindings.txt | 7 + .../std/src/sys/pal/windows/c/windows_sys.rs | 8 + library/std/src/sys/pal/windows/compat.rs | 108 +++- library/std/src/sys/paths/mod.rs | 18 +- library/std/src/sys/paths/uefi.rs | 14 + library/std/src/sys/paths/unix.rs | 24 +- library/std/src/sys/paths/unsupported.rs | 14 +- library/std/src/sys/paths/windows.rs | 14 + 28 files changed, 2140 insertions(+), 18 deletions(-) create mode 100644 library/std/src/fs/dirs.rs create mode 100644 library/std/src/os/darwin/fs/dirs.rs create mode 100644 library/std/src/os/unix/fs/dirs.rs create mode 100644 library/std/src/os/windows/fs/dirs.rs diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 762ad071e967c..6e401113cb26e 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -502,6 +502,57 @@ impl fmt::Debug for SplitPaths<'_> { } } +/// An iterator that splits an environment variable into paths according to +/// platform-specific conventions. +/// +/// The iterator element type is &[Path]. +/// +/// This structure is created by [`env::split_paths_ref()`]. See its +/// documentation for more. +/// +/// [`env::split_paths_ref()`]: split_paths_ref +#[must_use = "iterators are lazy and do nothing unless consumed"] +#[unstable(feature = "env_split_paths_ref", issue = "none")] +pub struct SplitPathsRef<'a> { + inner: paths_imp::SplitPathsRef<'a>, +} + +/// Parses input according to platform conventions for the `PATH` +/// environment variable. +/// +/// Unlike [`split_paths`], this function does not allocate and instead yields +/// [`Path`]s borrowed from `unparsed`. Returns `None` on platforms that may +/// require allocations to handle `PATH` splitting conventions. +/// +/// # Platform-specific behavior +/// +/// Returns `Some` on Unix platforms and `None` on all other platforms. +/// Note that this [may change in the future][changes]. +/// +/// [changes]: io#platform-specific-behavior +#[unstable(feature = "env_split_paths_ref", issue = "none")] +pub fn split_paths_ref + ?Sized>(unparsed: &T) -> Option> { + Some(SplitPathsRef { inner: paths_imp::split_paths_ref(unparsed.as_ref())? }) +} + +#[unstable(feature = "env_split_paths_ref", issue = "none")] +impl<'a> Iterator for SplitPathsRef<'a> { + type Item = &'a Path; + fn next(&mut self) -> Option<&'a Path> { + self.inner.next() + } + fn size_hint(&self) -> (usize, Option) { + self.inner.size_hint() + } +} + +#[unstable(feature = "env_split_paths_ref", issue = "none")] +impl fmt::Debug for SplitPathsRef<'_> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("SplitPathsRef").finish_non_exhaustive() + } +} + /// The error type for operations on the `PATH` variable. Possibly returned from /// [`env::join_paths()`]. /// diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 8df809264a6dd..3a4f14c3306bc 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -49,6 +49,13 @@ use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner, fs as fs_imp}; use crate::time::SystemTime; use crate::{error, fmt}; +pub(crate) mod dirs; + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub use self::dirs::HomeDirs; +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub use self::dirs::MediaDirs; + /// An object providing access to an open file on the filesystem. /// /// An instance of a `File` can be read and/or written depending on what options diff --git a/library/std/src/fs/dirs.rs b/library/std/src/fs/dirs.rs new file mode 100644 index 0000000000000..f8b855c994ff2 --- /dev/null +++ b/library/std/src/fs/dirs.rs @@ -0,0 +1,588 @@ +use crate::path::{Path, PathBuf}; +use crate::sys::fs::{ExtraHomeDirs, ExtraMediaDirs}; + +/// Common user directory paths used for user-specific application files. +/// +/// It is not required that the user directories are accessible by the current +/// user, nor that there is a directory at that path. A robust application +/// should handle the case where user directories are incorrectly configured. +/// +/// Even when configured correctly, multiple paths may point to the same location. +/// You should not assume that a file written relative to one directory will not +/// conflict with the same relative path in a different home directory. +/// +/// # Platform-specific behavior +/// +/// As the filesystem conventions for discovering directories varies between +/// operating systems, constructors for `HomeDirs` that use the host platform's +/// conventions are provided as extension traits under the `std::os` module. +#[unstable(feature = "fs_home_dirs", issue = "162082")] +#[derive(Debug, Clone)] +pub struct HomeDirs { + pub(crate) cache: Option, + pub(crate) config: Option, + pub(crate) data: Option, + pub(crate) state: Option, + #[cfg_attr(not(unix), expect(dead_code, reason = "no extra home dirs"))] + pub(crate) extra: ExtraHomeDirs, +} + +/// Common user directory paths used for user-specific media files. +/// +/// It is not required that the media directories are accessible by the current +/// user, nor that there is a directory at that path. A robust application +/// should handle the case where media directories are incorrectly configured. +/// +/// Even when configured correctly, multiple paths may point to the same location. +/// You should not assume that a file written relative to one directory will not +/// conflict with the same relative path in a different media directory. +/// +/// # Platform-specific behavior +/// +/// As the filesystem conventions for discovering directories varies between +/// operating systems, constructors for `MediaDirs` that use the host platform's +/// conventions are provided as extension traits under the `std::os` module. +#[unstable(feature = "fs_media_dirs", issue = "162083")] +#[derive(Debug, Clone)] +pub struct MediaDirs { + pub(crate) desktop: Option, + pub(crate) documents: Option, + pub(crate) downloads: Option, + pub(crate) music: Option, + pub(crate) pictures: Option, + pub(crate) videos: Option, + #[cfg_attr(not(unix), expect(dead_code, reason = "no extra media dirs"))] + pub(crate) extra: ExtraMediaDirs, +} + +// NB: HomeDirs and MediaDirs intentionally do not implement Default. Self::empty() +// is a logical default, but users may also intuit the default to use default +// platform conventions. Omitting Default pushes users to explicitly choose. + +impl HomeDirs { + /// Create a known user directory set with no known directories. + /// + /// This is useful with the builder `set_*` methods to create a `HomeDirs` + /// with exactly the directories you want, without any other defaults. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn empty() -> Self { + Self { cache: None, config: None, data: None, state: None, extra: Default::default() } + } + + /// A base directory relative to which user-specific non-essential cache + /// data files should be stored. + /// + /// "Cache" files are temporary data that can be used to cache redundant + /// work of an application, but which can be discarded arbitrarily and + /// recreated as necessary. Files in this directory may potentially be + /// automatically purged any time they are not currently open, or they + /// may not, depending on system configuration. A robust application + /// should ensure that its caches do not grow without a reasonable bound. + /// + /// This is the same directory for all applications. Applications should + /// use a subdirectory for application-specific cache files. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `${XDG_CACHE_HOME:-$HOME/.cache}` | + /// | [Darwin] (macOS) | [`NSCachesDirectory`] (`$HOME/Library/Caches`) | + /// | [Windows] | [`{FOLDERID_LocalAppData}`] (`%LOCALAPPDATA%`) | + /// + /// Other paths can be configured via [`set_cache_home`](Self::set_cache_home). + /// + /// [XDG]: crate::os::unix::fs::HomeDirsExt + /// [Darwin]: crate::os::darwin::fs::HomeDirsExt + /// [Windows]: crate::os::windows::fs::HomeDirsExt + /// [`NSCachesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/cachesdirectory?language=objc + /// [`{FOLDERID_LocalAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_localappdata + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn cache_home(&self) -> Option<&Path> { + self.cache.as_deref() + } + + /// A base directory relative to which user-specific configuration files + /// should be stored. + /// + /// "Config" files are configuration managed by the user, either by editing + /// the files directly or through a managing application. Configuration is + /// generally expected to be meaningful to the user and portable enough to + /// back up and synchronize across the same user's account on multiple + /// systems. + /// + /// This is the same directory for all applications. Applications should + /// use a subdirectory for application-specific configuration files. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `${XDG_CONFIG_HOME:-$HOME/.config}` | + /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) | + /// | [Windows] | [`{FOLDERID_RoamingAppData}`] (`%APPDATA%`) | + /// + /// Other paths can be configured via [`set_config_home`](Self::set_config_home). + /// + /// [XDG]: crate::os::unix::fs::HomeDirsExt + /// [Darwin]: crate::os::darwin::fs::HomeDirsExt + /// [Windows]: crate::os::windows::fs::HomeDirsExt + /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc + /// [`{FOLDERID_RoamingAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_roamingappdata + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn config_home(&self) -> Option<&Path> { + self.config.as_deref() + } + + /// A base directory relative to which user-specific data files should be + /// stored. + /// + /// "Data" files are application-specific data that is meaningful to the + /// user in some way and does not implicitly rely on system configuration + /// or details of how the application is installed otherwise irrelevant to + /// the user. As such, data makes sense to back up and synchronize between + /// the same user's account on multiple systems. If a file is specific to + /// a single machine, it's probably [state](Self::state_home). + /// + /// This is the same directory for all applications. Applications should + /// use a subdirectory for application-specific data files. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `${XDG_DATA_HOME:-$HOME/.local/share}` | + /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) | + /// | [Windows] | [`{FOLDERID_RoamingAppData}`] (`%APPDATA%`) | + /// + /// Other paths can be configured via [`set_data_home`](Self::set_data_home). + /// + /// [XDG]: crate::os::unix::fs::HomeDirsExt + /// [Darwin]: crate::os::darwin::fs::HomeDirsExt + /// [Windows]: crate::os::windows::fs::HomeDirsExt + /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc + /// [`{FOLDERID_RoamingAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_roamingappdata + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn data_home(&self) -> Option<&Path> { + self.data.as_deref() + } + + /// A base directory relative to which user-specific state files should be + /// stored. + /// + /// "State" files are data that should persist between application restarts, + /// but which is not important nor portable enough to the user to synchronize + /// between multiple systems like [data](Self::data_home) are. Common examples + /// include history (such as logs, recently used files, etc) and any current + /// state of the application that should be reused (such as view, layout, open + /// files, undo history, etc). + /// + /// This is the same directory for all applications. Applications should + /// use a subdirectory for application-specific state files. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `${XDG_STATE_HOME:-$HOME/.local/state}` | + /// | [Darwin] (macOS) | [`NSApplicationSupportDirectory`] (`$HOME/Library/Application Support`) | + /// | [Windows] | [`{FOLDERID_LocalAppData}`] (`%LOCALAPPDATA%`) | + /// + /// Other paths can be configured via [`set_state_home`](Self::set_state_home). + /// + /// [XDG]: crate::os::unix::fs::HomeDirsExt + /// [Darwin]: crate::os::darwin::fs::HomeDirsExt + /// [Windows]: crate::os::windows::fs::HomeDirsExt + /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc + /// [`{FOLDERID_LocalAppData}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_localappdata + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn state_home(&self) -> Option<&Path> { + self.state.as_deref() + } +} + +impl MediaDirs { + /// Create a known user directory set with no known directories. + /// + /// This is useful with the builder `set_*` methods to create a `MediaDirs` + /// with exactly the directories you want, without any other defaults. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn empty() -> Self { + Self { + desktop: None, + documents: None, + downloads: None, + music: None, + pictures: None, + videos: None, + extra: Default::default(), + } + } + + /// The OS-recognized user "Desktop" directory, often the `Desktop` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir DESKTOP` (`$HOME/Desktop`) | + /// | [Darwin] (macOS) | [`NSDesktopDirectory`] (`$HOME/Desktop`) | + /// | [Windows] | [`{FOLDERID_Desktop}`] (`%USERPROFILE%\Desktop`) | + /// + /// Other paths can be configured via [`set_desktop`](Self::set_desktop). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSDesktopDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/desktopdirectory?language=objc + /// [`{FOLDERID_Desktop}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_desktop + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn desktop(&self) -> Option<&Path> { + self.desktop.as_deref() + } + + /// The OS-recognized user "Documents" directory, often the `Documents` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir DOCUMENTS` (`$HOME/Documents`) | + /// | [Darwin] (macOS) | [`NSDocumentDirectory`] (`$HOME/Documents`) | + /// | [Windows] | [`{FOLDERID_Documents}`] (`%USERPROFILE%\Documents`) | + /// + /// Other paths can be configured via [`set_documents`](Self::set_documents). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSDocumentDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/documentdirectory?language=objc + /// [`{FOLDERID_Documents}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_documents + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn documents(&self) -> Option<&Path> { + self.documents.as_deref() + } + + /// The OS-recognized user "Downloads" directory, often the `Downloads` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir DOWNLOAD` (`$HOME/Downloads`) | + /// | [Darwin] (macOS) | [`NSDownloadsDirectory`] (`$HOME/Downloads`) | + /// | [Windows] | [`{FOLDERID_Downloads}`] (`%USERPROFILE%\Downloads`) | + /// + /// Other paths can be configured via [`set_downloads`](Self::set_downloads). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSDownloadsDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/downloadsdirectory?language=objc + /// [`{FOLDERID_Downloads}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_downloads + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn downloads(&self) -> Option<&Path> { + self.downloads.as_deref() + } + + /// The OS-recognized user "Music" directory, often the `Music` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir MUSIC` (`$HOME/Music`) | + /// | [Darwin] (macOS) | [`NSMusicDirectory`] (`$HOME/Music`) | + /// | [Windows] | [`{FOLDERID_Music}`] (`%USERPROFILE%\Music`) | + /// + /// Other paths can be configured via [`set_music`](Self::set_music). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSMusicDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/musicdirectory?language=objc + /// [`{FOLDERID_Music}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_music + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn music(&self) -> Option<&Path> { + self.music.as_deref() + } + + /// The OS-recognized user "Pictures" directory, often the `Pictures` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir PICTURES` (`$HOME/Pictures`) | + /// | [Darwin] (macOS) | [`NSPicturesDirectory`] (`$HOME/Pictures`) | + /// | [Windows] | [`{FOLDERID_Pictures}`] (`%USERPROFILE%\Pictures`) | + /// + /// Other paths can be configured via [`set_pictures`](Self::set_pictures). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSPicturesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/picturesdirectory?language=objc + /// [`{FOLDERID_Pictures}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_pictures + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn pictures(&self) -> Option<&Path> { + self.pictures.as_deref() + } + + /// The OS-recognized user "Videos" directory, often the `Videos` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + /// + /// # Platform-specific behavior + /// + /// When constructed using platform-specific conventions, the value is: + /// + /// | OS | Path | + /// | -- | ---- | + /// | [XDG] (Linux) | `xdg-user-dir VIDEOS` (`$HOME/Videos`) | + /// | [Darwin] (macOS) | [`NSMoviesDirectory`] (`$HOME/Movies`) | + /// | [Windows] | [`{FOLDERID_Videos}`] (`%USERPROFILE%\Videos`) | + /// + /// Other paths can be configured via [`set_videos`](Self::set_videos). + /// + /// [XDG]: crate::os::unix::fs::MediaDirsExt + /// [Darwin]: crate::os::darwin::fs::MediaDirsExt + /// [Windows]: crate::os::windows::fs::MediaDirsExt + /// [`NSMoviesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/moviesdirectory?language=objc + /// [`{FOLDERID_Videos}`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_videos + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn videos(&self) -> Option<&Path> { + self.videos.as_deref() + } +} + +impl HomeDirs { + /// Set the path for [Self::cache_home]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn set_cache_home(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "cache home directory path must be absolute"); + self.cache = Some(path); + self + } + + /// Set the path for [Self::config_home]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn set_config_home(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "config home directory path must be absolute"); + self.config = Some(path); + self + } + + /// Set the path for [Self::data_home]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn set_data_home(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "data home directory path must be absolute"); + self.data = Some(path); + self + } + + /// Set the path for [Self::state_home]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + pub fn set_state_home(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "state home directory path must be absolute"); + self.state = Some(path); + self + } +} + +impl MediaDirs { + /// Set the path for [Self::desktop]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_desktop(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "desktop directory path must be absolute"); + self.desktop = Some(path); + self + } + + /// Set the path for [Self::documents]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_documents(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "documents directory path must be absolute"); + self.documents = Some(path); + self + } + + /// Set the path for [Self::downloads]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_downloads(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "downloads directory path must be absolute"); + self.downloads = Some(path); + self + } + + /// Set the path for [Self::music]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_music(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "music directory path must be absolute"); + self.music = Some(path); + self + } + + /// Set the path for [Self::pictures]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_pictures(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "pictures directory path must be absolute"); + self.pictures = Some(path); + self + } + + /// Set the path for [Self::videos]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + pub fn set_videos(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "videos directory path must be absolute"); + self.videos = Some(path); + self + } +} + +#[cfg(test)] +mod tests { + use super::*; + + fn test_dir(what: &str) -> PathBuf { + crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what) + } + + #[test] + fn test_home_dirs_field_hookup_matches() { + let mut dirs = HomeDirs::empty(); + + assert_eq!(dirs.config_home(), None); + assert_eq!(dirs.data_home(), None); + assert_eq!(dirs.state_home(), None); + assert_eq!(dirs.cache_home(), None); + + let config = test_dir("config"); + let data = test_dir("data"); + let state = test_dir("state"); + let cache = test_dir("cache"); + + dirs.set_config_home(config.clone()); + dirs.set_data_home(data.clone()); + dirs.set_state_home(state.clone()); + dirs.set_cache_home(cache.clone()); + + assert_eq!(dirs.config_home(), Some(config.as_ref())); + assert_eq!(dirs.data_home(), Some(data.as_ref())); + assert_eq!(dirs.state_home(), Some(state.as_ref())); + assert_eq!(dirs.cache_home(), Some(cache.as_ref())); + } + + #[test] + fn test_media_dirs_field_hookup_matches() { + let mut dirs = MediaDirs::empty(); + + assert_eq!(dirs.desktop(), None); + assert_eq!(dirs.documents(), None); + assert_eq!(dirs.downloads(), None); + assert_eq!(dirs.music(), None); + assert_eq!(dirs.pictures(), None); + assert_eq!(dirs.videos(), None); + + let desktop = test_dir("desktop"); + let documents = test_dir("documents"); + let downloads = test_dir("downloads"); + let music = test_dir("music"); + let pictures = test_dir("pictures"); + let videos = test_dir("videos"); + + dirs.set_desktop(desktop.clone()); + dirs.set_documents(documents.clone()); + dirs.set_downloads(downloads.clone()); + dirs.set_music(music.clone()); + dirs.set_pictures(pictures.clone()); + dirs.set_videos(videos.clone()); + + assert_eq!(dirs.desktop(), Some(desktop.as_ref())); + assert_eq!(dirs.documents(), Some(documents.as_ref())); + assert_eq!(dirs.downloads(), Some(downloads.as_ref())); + assert_eq!(dirs.music(), Some(music.as_ref())); + assert_eq!(dirs.pictures(), Some(pictures.as_ref())); + assert_eq!(dirs.videos(), Some(videos.as_ref())); + } +} diff --git a/library/std/src/os/darwin/fs.rs b/library/std/src/os/darwin/fs.rs index fc2869d6b13f6..b41391f19dccf 100644 --- a/library/std/src/os/darwin/fs.rs +++ b/library/std/src/os/darwin/fs.rs @@ -7,6 +7,13 @@ use crate::fs::{self, Metadata}; use crate::sys::{AsInner, AsInnerMut, IntoInner}; use crate::time::SystemTime; +mod dirs; + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub use dirs::HomeDirsExt; +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub use dirs::MediaDirsExt; + /// OS-specific extensions to [`fs::Metadata`]. /// /// [`fs::Metadata`]: crate::fs::Metadata diff --git a/library/std/src/os/darwin/fs/dirs.rs b/library/std/src/os/darwin/fs/dirs.rs new file mode 100644 index 0000000000000..6aaa910981b0b --- /dev/null +++ b/library/std/src/os/darwin/fs/dirs.rs @@ -0,0 +1,313 @@ +use crate::env; +use crate::fs::{HomeDirs, MediaDirs}; +use crate::io::{self, ErrorKind, const_error}; +use crate::path::PathBuf; + +/// Darwin-specific extensions to [`fs::HomeDirs`](HomeDirs). +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub impl(self) trait HomeDirsExt: Sized { + /// Load the standard user directory paths for the current user. + /// + /// On iOS, tvOS, watchOS, visionOS, and sandboxed macOS applications, + /// these directories are within the application's container. Outside + /// the sandbox, these are subdirectories of the `~/Library` directory on + /// macOS. + /// + /// The produced directory paths are not guaranteed to be the canonical + /// paths to the directories; they are allowed to be sandbox-redirected + /// paths as long as the directory is accessible there. + /// + /// The loaded common directories are: + /// + /// | `HomeDirs` | [`NSSearchPathDirectory`] | + /// | ---------- | ----------------------- | + /// | [`cache_home`] | [`NSCachesDirectory`] (`~/Library/Caches`) | + /// | [`config_home`] | [`NSApplicationSupportDirectory`] (`~/Library/Application Support`) | + /// | [`data_home`] | [`NSApplicationSupportDirectory`] (`~/Library/Application Support`) | + /// | [`state_home`] | [`NSApplicationSupportDirectory`] (`~/Library/Application Support`) | + /// + /// Note that the Application Support directory is used for the config, + /// data, and state directories. It is always possible for multiple user + /// directories to be configured to the same path, but this is the common + /// configuration on Apple platforms, making it even more important to not + /// assume files in different user directories cannot alias each other. + /// + /// # Errors + /// + /// Errors if the [user home](env::home_dir) cannot be determined. + // Errors due to the underlying sysdir(3) API should never occur, as + // - the user domain only has one directory for each search path; + // - the user domain always returns subdirectory paths of `~`; and + // - the username and OS defined path segments are always valid UTF-8. + /// + /// # Implementation-specific behavior + /// + /// Uses the `sysdir(3)` API from `libSystem` to discover the standard + /// user directories. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load additional common + /// directories not currently in this list. + /// + /// [`cache_home`]: HomeDirs::cache_home + /// [`config_home`]: HomeDirs::config_home + /// [`data_home`]: HomeDirs::data_home + /// [`state_home`]: HomeDirs::state_home + /// + /// [`NSSearchPathDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory?language=objc + /// [`NSCachesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/cachesdirectory?language=objc + /// [`NSApplicationSupportDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/applicationsupportdirectory?language=objc + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn sysdir() -> io::Result; +} + +/// Darwin-specific extensions to [`fs::MediaDirs`](MediaDirs). +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub impl(self) trait MediaDirsExt: Sized { + /// Load the standard user directory paths for the current user. + /// + /// The produced directory paths are not guaranteed to be the canonical + /// paths to the directories; they are allowed to be sandbox-redirected + /// paths as long as the directory is accessible there. + /// + /// The loaded common directories are: + /// + /// | `MediaDirs` | [`NSSearchPathDirectory`] | + /// | ---------- | ----------------------- | + /// | [`desktop`] | [`NSDesktopDirectory`] (`~/Desktop`) | + /// | [`documents`] | [`NSDocumentDirectory`] (`~/Documents`) | + /// | [`downloads`] | [`NSDownloadsDirectory`] (`~/Downloads`) | + /// | [`music`] | [`NSMusicDirectory`] (`~/Music`) | + /// | [`pictures`] | [`NSPicturesDirectory`] (`~/Pictures`) | + /// | [`videos`] | [`NSMoviesDirectory`] (`~/Movies`) | + /// + /// # Errors + /// + /// Errors if the the [user home](env::home_dir) cannot be determined. + // Errors due to the underlying sysdir(3) API should never occur, as + // - the user domain only has one directory for each search path; + // - the user domain always returns subdirectory paths of `~`; + // - the username plus OS defined path segments cannot exceed PATH_MAX; and + // - the username and OS defined path segments are always valid UTF-8. + /// + /// # Implementation-specific behavior + /// + /// Uses the `sysdir(3)` API from `libSystem` to discover the standard + /// user directories. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load additional common + /// directories not currently in this list. + /// + /// [`desktop`]: MediaDirs::desktop + /// [`documents`]: MediaDirs::documents + /// [`downloads`]: MediaDirs::downloads + /// [`music`]: MediaDirs::music + /// [`pictures`]: MediaDirs::pictures + /// [`videos`]: MediaDirs::videos + /// + /// [`NSSearchPathDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory?language=objc + /// [`NSDesktopDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/desktopdirectory?language=objc + /// [`NSDocumentDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/documentdirectory?language=objc + /// [`NSDownloadsDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/downloadsdirectory?language=objc + /// [`NSMusicDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/musicdirectory?language=objc + /// [`NSPicturesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/picturesdirectory?language=objc + /// [`NSMoviesDirectory`]: https://developer.apple.com/documentation/foundation/filemanager/searchpathdirectory/moviesdirectory?language=objc + #[unstable(feature = "fs_media_dirs", issue = "162083")] + fn sysdir() -> io::Result; +} + +fn user_home() -> io::Result { + env::home_dir() + .filter(|p| p.is_absolute()) + .ok_or(const_error!(ErrorKind::InvalidData, "home path not absolute")) +} + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +#[cfg(target_vendor = "apple")] +impl HomeDirsExt for HomeDirs { + fn sysdir() -> io::Result { + use libc::sysdir_search_path_directory_t::*; + + let mut dirs = HomeDirs::empty(); + let home = user_home()?; + + let caches = sys::get_user_dir(&home, SYSDIR_DIRECTORY_CACHES)?; + let application_support = sys::get_user_dir(&home, SYSDIR_DIRECTORY_APPLICATION_SUPPORT)?; + + dirs.cache = caches; + // Apple puts config/data/state all in Application Support + dirs.config = application_support.clone(); + dirs.data = application_support.clone(); + dirs.state = application_support; + + Ok(dirs) + } +} + +#[unstable(feature = "fs_media_dirs", issue = "162083")] +#[cfg(target_vendor = "apple")] +impl MediaDirsExt for MediaDirs { + fn sysdir() -> io::Result { + use libc::sysdir_search_path_directory_t::*; + + let mut dirs = MediaDirs::empty(); + let home = user_home()?; + + let desktop = sys::get_user_dir(&home, SYSDIR_DIRECTORY_DESKTOP)?; + let documents = sys::get_user_dir(&home, SYSDIR_DIRECTORY_DOCUMENT)?; + let downloads = sys::get_user_dir(&home, SYSDIR_DIRECTORY_DOWNLOADS)?; + let movies = sys::get_user_dir(&home, SYSDIR_DIRECTORY_MOVIES)?; + let music = sys::get_user_dir(&home, SYSDIR_DIRECTORY_MUSIC)?; + let pictures = sys::get_user_dir(&home, SYSDIR_DIRECTORY_PICTURES)?; + + dirs.desktop = desktop; + dirs.documents = documents; + dirs.downloads = downloads; + dirs.music = music; + dirs.pictures = pictures; + dirs.videos = movies; + + Ok(dirs) + } +} + +/// Safer wrapper around the sysdir(3) API +#[cfg(target_vendor = "apple")] +mod sys { + use crate::ffi::{CStr, c_char}; + use crate::io::{self, ErrorKind, const_error}; + use crate::path::{Path, PathBuf}; + + /// Get the path for a system directory using `sysdir(3)`. + pub fn get_user_dir( + home: &Path, + kind: libc::sysdir_search_path_directory_t, + ) -> io::Result> { + use libc::sysdir_search_path_domain_mask_t::SYSDIR_DOMAIN_MASK_USER; + + // SAFETY: SYSDIR_DOMAIN_MASK_USER < SYSDIR_DOMAIN_MASK_ALL + let mut iter = unsafe { Iter::new(home, kind, SYSDIR_DOMAIN_MASK_USER) }; + let Some(path) = iter.next() else { + return Ok(None); + }; + let path = path?; + + if iter.next().is_some() { + // more than one path returned (shouldn't happen for SYSDIR_DOMAIN_MASK_USER) + return Err(const_error!( + ErrorKind::InvalidData, + "multiple paths returned for standard user directory", + )); + } + + Ok(Some(path)) + } + + struct Iter<'a> { + home: &'a Path, + state: libc::sysdir_search_path_enumeration_state, + } + + impl Drop for Iter<'_> { + fn drop(&mut self) { + for _ in self {} + } + } + + impl<'a> Iter<'a> { + // SAFETY: `mask` must be <= `SYSDIR_DOMAIN_MASK_ALL` + pub unsafe fn new( + home: &'a Path, + kind: libc::sysdir_search_path_directory_t, + mask: libc::sysdir_search_path_domain_mask_t, + ) -> Self { + // SAFETY: forwarded to the caller + let state = unsafe { libc::sysdir_start_search_path_enumeration(kind, mask) }; + Self { home, state } + } + } + + impl Iterator for Iter<'_> { + type Item = io::Result; + + fn next(&mut self) -> Option> { + let mut buf = [0u8; libc::PATH_MAX as usize]; + if self.state != 0 { + // SAFETY: `self.state` is nonzero and comes from prior sysdir_{start|get_next}_search_path_enumeration call + // SAFETY: sysdir_get_next_search_path_enumeration will write at most `PATH_MAX` bytes to `path` + self.state = unsafe { + libc::sysdir_get_next_search_path_enumeration( + self.state, + buf.as_mut_ptr() as *mut c_char, + ) + }; + } + + if self.state == 0 { + // exhausted + return None; + } + + let Ok(path) = CStr::from_bytes_until_nul(&buf) else { + // should be impossible given home-relative paths, but be defensive + return Some(Err(const_error!( + ErrorKind::InvalidData, + "standard user directory path too long", + ))); + }; + + let Ok(path) = path.to_str() else { + // should be impossible on a working system, but be defensive + return Some(Err(const_error!( + ErrorKind::InvalidData, + "standard user directory path not valid UTF-8", + ))); + }; + + // expand `~` shorthand + Some(match path { + "~" => Ok(self.home.into()), + _ if path.starts_with("~/") => Ok(self.home.join(&path[2..])), + _ if path.starts_with("~") => Err(const_error!( + ErrorKind::InvalidData, + "standard user directory relative to different user", + )), + _ => { + let path = PathBuf::from(path); + if path.is_relative() { + Err(const_error!( + ErrorKind::InvalidData, + "standard user directory path not absolute", + )) + } else { + Ok(path) + } + } + }) + } + } +} + +#[cfg(test)] +#[cfg(target_vendor = "apple")] +mod tests { + use super::*; + + #[test] + fn can_fetch_sysdir_paths() { + let dirs = HomeDirs::sysdir().unwrap(); + assert!(dirs.cache_home().is_some()); + assert!(dirs.config_home().is_some()); + assert!(dirs.data_home().is_some()); + assert!(dirs.state_home().is_some()); + + let dirs = MediaDirs::sysdir().unwrap(); + assert!(dirs.desktop().is_some()); + assert!(dirs.documents().is_some()); + assert!(dirs.downloads().is_some()); + assert!(dirs.music().is_some()); + assert!(dirs.pictures().is_some()); + assert!(dirs.videos().is_some()); + } +} diff --git a/library/std/src/os/unix/fs.rs b/library/std/src/os/unix/fs.rs index b93f94225070a..fcafe1c29797f 100644 --- a/library/std/src/os/unix/fs.rs +++ b/library/std/src/os/unix/fs.rs @@ -22,6 +22,13 @@ use crate::{io, sys}; #[cfg(test)] mod tests; +pub(crate) mod dirs; + +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub use dirs::MediaDirsExt; +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub use dirs::{HomeDirsExt, XdgDirs}; + /// Unix-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { diff --git a/library/std/src/os/unix/fs/dirs.rs b/library/std/src/os/unix/fs/dirs.rs new file mode 100644 index 0000000000000..5d8e13c7a730a --- /dev/null +++ b/library/std/src/os/unix/fs/dirs.rs @@ -0,0 +1,585 @@ +use crate::env::{self, SplitPathsRef}; +use crate::ffi::{OsStr, OsString}; +use crate::fs::{self, HomeDirs, MediaDirs}; +use crate::io::{self, ErrorKind, const_error}; +use crate::path::{Path, PathBuf}; + +#[derive(Debug, Default, Clone)] +#[non_exhaustive] +pub struct ExtraHomeDirs { + runtime: Option, + config_path: Option, + data_path: Option, +} + +#[derive(Debug, Default, Clone)] +#[non_exhaustive] +pub struct ExtraMediaDirs { + templates: Option, +} + +/// XDG-specific extensions to [`fs::HomeDirs`](HomeDirs). +/// +/// The XDG conventions are defined by the Freedesktop.org project in the +/// [XDG Base Directory Specification][xdg-basedir]. These conventions have +/// been largely adopted by Linux distributions. +/// +/// The XDG conventions are written to be usable on any Unix-like filesystem, +/// thus this extension being provided in `os::unix` rather than `os::linux`. +/// However, while some tooling does use XDG conventions on macOS, note that +/// macOS has its own separate conventions for user directories. Consider +/// carefully what conventions your users will expect your application to +/// follow along with any legacy path compatibility you might need to support. +/// +/// [xdg-basedir]: https://specifications.freedesktop.org/basedir/ +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub impl(self) trait HomeDirsExt: Sized { + /// Load the user directory paths according to the + /// [XDG Base Directory Specification][xdg-basedir]. + /// + /// Each base directory path is set to the value of its corresponding + /// `XDG_*` environment variable (if it is set and non-empty), else to + /// the default value defined by the specification. + /// + /// | Field | Environment Variable | Default Value | + /// | ----- | -------------------- | ------------- | + /// | [`cache_home`] | `XDG_CACHE_HOME` | `$HOME/.cache` | + /// | [`config_home`] | `XDG_CONFIG_HOME` | `$HOME/.config` | + /// | [`data_home`] | `XDG_DATA_HOME` | `$HOME/.local/share` | + /// | [`state_home`] | `XDG_STATE_HOME` | `$HOME/.local/state` | + /// | [`runtime_home`] | `XDG_RUNTIME_DIR` | (see method docs) | + /// | [`config_dirs`] | `XDG_CONFIG_DIRS` | `/etc/xdg` | + /// | [`data_dirs`] | `XDG_DATA_DIRS` | `/usr/local/share/`, `/usr/share/` | + /// + /// Note that `$HOME` here means [`env::home_dir`], which uses + /// `$HOME` if set and non-empty, but falls back to the system password + /// database if it isn't set. + /// + /// All paths are required to be absolute. If a relative path is configured + /// by the environment, it is ignored and the default value is used instead. + /// + /// `config_dirs` and `data_dirs` are a list of delimited paths using the + /// [`env::split_paths`] delimiter. If some but not all paths in the list are + /// relative, those relative paths are ignored and the remaining absolute + /// paths are used. If there are no valid absolute paths, the default value + /// is used instead. + /// + /// # Errors + /// + /// Errors if the user's home directory cannot be determined. + /// + /// [xdg-basedir]: https://specifications.freedesktop.org/basedir/ + /// [`cache_home`]: HomeDirs::cache_home + /// [`config_home`]: HomeDirs::config_home + /// [`data_home`]: HomeDirs::data_home + /// [`state_home`]: HomeDirs::state_home + /// [`runtime_home`]: HomeDirsExt::runtime_home + /// [`config_dirs`]: HomeDirsExt::config_dirs + /// [`data_dirs`]: HomeDirsExt::data_dirs + /// [`env::split_paths`]: crate::env::split_paths + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn xdg() -> io::Result; + + /// A base directory relative to which user-specific runtime files + /// (such as sockets, named pipes, etc) should be stored. + /// + /// Files in this directory may be subjected to periodic clean-up. + /// Larger files should not be placed here, since it might reside in + /// runtime memory and cannot necessarily be swapped out to disk. + /// + /// This path does not have a default if not set. If it isn't set, + /// applications should fall back to a replacement directory with + /// similar capabilities and print a warning message. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn runtime_home(&self) -> Option<&Path>; + + /// A preference-ordered list of base directories to search for config + /// files *in addition to* [`config_home`]. + /// + /// The order of directories denotes their importance; the first directory + /// is the most important. Information defined relative to the more + /// important base directory takes precedent. [`config_home`] is not + /// necessarily present in this list, and is considered more important + /// than any base directory in this list. + /// + /// [`config_home`]: HomeDirs::config_home + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn config_dirs(&self) -> Option>; + + /// A preference-ordered list of base directories to search for data + /// files *in addition to* [`data_home`]. + /// + /// The order of directories denotes their importance; the first directory + /// is the most important. Information defined relative to the more + /// important base directory takes precedent. [`data_home`] is not + /// necessarily present in this list, and is considered more important + /// than any base directory in this list. + /// + /// [`data_home`]: HomeDirs::data_home + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn data_dirs(&self) -> Option>; + + /// Set the path for [Self::runtime_home]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn set_runtime_home(&mut self, path: PathBuf) -> &mut Self; + + /// Set the paths for [Self::config_dirs]. + /// + /// Takes one or more paths joined appropriately for the `PATH` environment + /// variable, as by [`env::join_paths`]. + /// + /// # Panics + /// + /// Panics if any of the provided paths are not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn set_config_dirs(&mut self, paths: OsString) -> &mut Self; + + /// Set the paths for [Self::data_dirs]. + /// + /// Takes one or more paths joined appropriately for the `PATH` environment + /// variable, as by [`env::join_paths`]. + /// + /// # Panics + /// + /// Panics if any of the provided paths are not absolute. + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn set_data_dirs(&mut self, paths: OsString) -> &mut Self; +} + +/// XDG-specific extensions to [`fs::MediaDirs`](MediaDirs). +/// +/// The XDG conventions are defined by the Freedesktop.org project through the +/// [xdg-user-dirs] tool. This configuration is generally present on desktop +/// Linux distributions, although adoption is less widespread than the base +/// directory specification. +/// +/// The XDG conventions are written to be usable on any Unix-like filesystem, +/// thus this extension being provided in `os::unix` rather than `os::linux`. +/// However, while some tooling does use XDG conventions on macOS, note that +/// macOS has its own separate conventions for user directories. Consider +/// carefully what conventions your users will expect your application to +/// follow along with any legacy path compatibility you might need to support. +/// +/// [xdg-user-dirs]: https://www.freedesktop.org/wiki/Software/xdg-user-dirs/ +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub impl(self) trait MediaDirsExt: Sized { + /// Load the user directory paths according to the [xdg-user-dirs] tool. + /// + /// This directly reads and parses the `$XDG_CONFIG_HOME/user-dirs.dirs` + /// file as defined and maintained by the [xdg-user-dirs] tool. + /// + /// # Errors + /// + /// Errors if the user's home directory cannot be determined or if the + /// `$XDG_CONFIG_HOME/user-dirs.dirs` file cannot be read. + /// + /// # Implementation-specific behavior + /// + /// Only the format maintained by xdg-user-dirs-update is supported. Any + /// configuration that does not match the expected format will result in + /// loading an unspecified path or `None` for that directory. To be more + /// specific: + /// + /// - Any line not in the format of `XDG_{NAME}_DIR={path}` where `{NAME}` + /// is one of `DESKTOP`, `DOWNLOAD`, `TEMPLATES`, `PUBLICSHARE`, + /// `DOCUMENTS`, `MUSIC`, `PICTURES`, or `VIDEOS` is ignored. + /// - `{path}` must be a `"`-quoted shell-escaped path. + /// - `{path}` may only start with `/` or `$HOME/`. A home-relative path + /// is returned relative to [`env::home_dir`]; shell expansion is not + /// performed. + /// - A directory set to just `$HOME` marks it as removed, and results in + /// a `None` value for that path. + /// - If shell expansion syntax other than a leading `$HOME` is present, + /// the produced directory path is unspecified. This is invalid config + /// according to the xdg-user-dirs tooling. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load paths that we currently + /// ignore, such as path formats that are not canonically supported by + /// xdg-user-dirs but which may occur in manually-edited `user-dirs.dirs`. + /// + /// [xdg-user-dirs]: https://www.freedesktop.org/wiki/Software/xdg-user-dirs/ + #[unstable(feature = "fs_media_dirs", issue = "162083")] + fn xdg() -> io::Result; + + /// The OS-privileged user "Templates" directory, often the `Templates` + /// folder in the user's home directory. + /// + /// As a media directory, this should typically be used as a default path + /// for file selection dialogs, not for automatically accessed file paths. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + fn templates(&self) -> Option<&Path>; + + /// Set the paths for [Self::templates]. + /// + /// # Panics + /// + /// Panics if the provided path is not absolute. + #[unstable(feature = "fs_media_dirs", issue = "162083")] + fn set_templates(&mut self, path: PathBuf) -> &mut Self; +} + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +#[derive(Debug)] +pub struct XdgDirs<'a>(SplitPathsRef<'a>); + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +impl HomeDirsExt for HomeDirs { + fn xdg() -> io::Result { + let mut dirs = HomeDirs::empty(); + let user_home = xdg::user_home()?; + + dirs.set_cache_home(xdg::dir_or_else(|| user_home.join(".cache"), "XDG_CACHE_HOME")); + dirs.set_config_home(xdg::dir_or_else(|| user_home.join(".config"), "XDG_CONFIG_HOME")); + dirs.set_data_home(xdg::dir_or_else(|| user_home.join(".local/share"), "XDG_DATA_HOME")); + dirs.set_state_home(xdg::dir_or_else(|| user_home.join(".local/state"), "XDG_STATE_HOME")); + if let Some(runtime) = xdg::dir("XDG_RUNTIME_DIR") { + dirs.set_runtime_home(runtime); + } + + dirs.set_config_dirs(xdg::dirs_or("/etc/xdg", "XDG_CONFIG_DIRS")); + dirs.set_data_dirs(xdg::dirs_or("/usr/local/share/:/usr/share/", "XDG_DATA_DIRS")); + + Ok(dirs) + } + + fn runtime_home(&self) -> Option<&Path> { + self.extra.runtime.as_deref() + } + + fn config_dirs(&self) -> Option> { + self.extra.config_path.as_deref().map(XdgDirs::new) + } + + fn data_dirs(&self) -> Option> { + self.extra.data_path.as_deref().map(XdgDirs::new) + } + + fn set_runtime_home(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "runtime directory path must be absolute"); + self.extra.runtime = Some(path); + self + } + + fn set_config_dirs(&mut self, paths: OsString) -> &mut Self { + for path in split_paths_ref(&paths) { + assert!(path.is_absolute(), "config directory paths must be absolute"); + } + self.extra.config_path = Some(paths); + self + } + + fn set_data_dirs(&mut self, paths: OsString) -> &mut Self { + for path in split_paths_ref(&paths) { + assert!(path.is_absolute(), "data directory paths must be absolute"); + } + self.extra.data_path = Some(paths); + self + } +} + +#[unstable(feature = "fs_media_dirs", issue = "162083")] +impl MediaDirsExt for MediaDirs { + fn xdg() -> io::Result { + let user_home = xdg::user_home()?; + let config_home = xdg::dir_or_else(|| user_home.join(".config"), "XDG_CONFIG_HOME"); + + let spec = match fs::read(config_home.join("user-dirs.dirs")) { + Ok(spec) => spec, + Err(e) if e.kind() == ErrorKind::NotFound => { + return Err(const_error!( + ErrorKind::NotFound, + "missing `$XDG_CONFIG_HOME/user-dirs.dirs`", + )); + } + Err(e) => return Err(e), + }; + + Ok(xdg::parse_user_dirs(&spec, &user_home)) + } + + fn templates(&self) -> Option<&Path> { + self.extra.templates.as_deref() + } + + fn set_templates(&mut self, path: PathBuf) -> &mut Self { + assert!(path.is_absolute(), "templates directory path must be absolute"); + self.extra.templates = Some(path); + self + } +} + +impl<'a> XdgDirs<'a> { + fn new(paths: &'a OsStr) -> Self { + XdgDirs(split_paths_ref(paths)) + } +} + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +impl<'a> Iterator for XdgDirs<'a> { + type Item = &'a Path; + + fn next(&mut self) -> Option { + self.0.next() + } +} + +fn split_paths_ref<'a>(paths: &'a OsStr) -> SplitPathsRef<'a> { + // returns Some on cfg(unix) + env::split_paths_ref(paths).unwrap() +} + +mod xdg { + use super::{MediaDirs, split_paths_ref}; + use crate::env::{self, join_paths, var_os}; + use crate::ffi::OsString; + use crate::io::{self, ErrorKind, const_error}; + use crate::ops::Deref; + use crate::os::unix::ffi::{OsStrExt, OsStringExt}; + use crate::path::{Path, PathBuf}; + + pub fn user_home() -> io::Result { + env::home_dir() + .filter(|p| p.is_absolute()) + .ok_or(const_error!(ErrorKind::InvalidData, "user home directory path not absolute")) + } + + pub fn dir(env: &str) -> Option { + var_os(env).filter(|s| !s.is_empty()).map(PathBuf::from).filter(|path| path.is_absolute()) + } + + pub fn dir_or_else(fallback: impl FnOnce() -> PathBuf, env: &str) -> PathBuf { + dir(env).unwrap_or_else(fallback) + } + + fn dirs(env: &str) -> Option { + let dirs = var_os(env).filter(|s| !s.is_empty())?; + if split_paths_ref(&dirs).all(|p| p.is_absolute()) { + return Some(dirs); + } + + struct DerefAsRef(pub T); + impl>, U: ?Sized> AsRef for DerefAsRef { + fn as_ref(&self) -> &U { + (*self.0).as_ref() + } + } + + let paths = split_paths_ref(&dirs).filter(|p| p.is_absolute()).map(DerefAsRef); + join_paths(paths).ok().filter(|s| !s.is_empty()) + } + + pub fn dirs_or(fallback: impl Into, env: &str) -> OsString { + dirs(env).unwrap_or_else(|| fallback.into()) + } + + pub fn parse_user_dirs<'a>(spec: &'a [u8], user_home: &Path) -> MediaDirs { + let mut dirs = MediaDirs::empty(); + + for (xdg, path) in + spec.split(|&b| b == b'\n').flat_map(|line| parse_user_dirs_line(line, user_home)) + { + // load the known user directories + match xdg { + b"XDG_DESKTOP_DIR" => dirs.desktop = path, + b"XDG_DOCUMENTS_DIR" => dirs.documents = path, + b"XDG_DOWNLOAD_DIR" => dirs.downloads = path, + b"XDG_MUSIC_DIR" => dirs.music = path, + b"XDG_PICTURES_DIR" => dirs.pictures = path, + b"XDG_VIDEOS_DIR" => dirs.videos = path, + b"XDG_TEMPLATES_DIR" => dirs.extra.templates = path, + b"XDG_PUBLICSHARE_DIR" => { + // we don't expose this directory yet as Windows also has a "public" directory + // and it's not yet clear if we want to expose this at the target-agnostic level + } + _ => { + // ignore unknown variable assignment + } + } + } + + dirs + } + + fn parse_user_dirs_line<'a>( + line: &'a [u8], + user_home: &Path, + ) -> Option<(&'a [u8], Option)> { + // trim whitespace + let trimmed = line.trim_ascii(); + // skip empty lines and comments + if trimmed.is_empty() || trimmed.starts_with(&[b'#']) { + return None; + } + + // only variable assignment lines are allowed; split on `=` + let mut split = trimmed.splitn(2, |&b| b == b'='); + // extract assignment parts; ignore lines not in this format + let var = split.next()?; + let val = split.next()?; + debug_assert_eq!(split.next(), None); + + // the path value is quoted; unquote it + let path = unquote(val, user_home)?; + + let path = Some(path) + // ignore non-absolute paths + .filter(|path| path.is_absolute()) + // setting to the home dir disables the directory configuration + .filter(|path| path != user_home); + + Some((var, path)) + } + + fn unquote(bytes: &[u8], user_home: &Path) -> Option { + let [b'"', rest @ .., b'"'] = bytes else { return None }; + + // setting to the home dir disables the directory configuration; + // if done symbolically, return None here and bypass later work + if matches!(rest, b"$HOME" | b"$HOME/") { + return None; + } + + let mut rest = rest; + let mut s = Vec::with_capacity(rest.len()); + + // expand leading $HOME + if rest.starts_with(b"$HOME/") { + s.extend_from_slice(user_home.as_os_str().as_bytes()); + if !user_home.has_trailing_sep() { + s.push(b'/'); + } + rest = &rest[6..]; + } + + loop { + let i = rest + .iter() + .position(|&b| matches!(b, b'"' | b'\\' | b'$' | b'`')) + .unwrap_or(rest.len()); + s.extend_from_slice(&rest[..i]); + match &rest[i..] { + [] => break, + [b'\\', c @ (b'"' | b'\\' | b'$' | b'`'), tail @ ..] => { + // supported escapes + s.push(*c); + rest = tail; + } + [b'"' | b'\\' | b'$' | b'`', ..] => { + // unsupported shell syntax + return None; + } + _ => { + if cfg!(debug_assertions) { + unreachable!() + } else { + return None; + } + } + } + } + + Some(PathBuf::from(OsString::from_vec(s))) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_fetch_xdg_base_dirs() { + let dirs = HomeDirs::xdg().unwrap(); + + assert!(dirs.cache_home().is_some()); + assert!(dirs.config_home().is_some()); + assert!(dirs.data_home().is_some()); + assert!(dirs.state_home().is_some()); + // dirs.runtime() may not exist + assert!(dirs.config_dirs().is_some()); + assert!(dirs.data_dirs().is_some()); + } + + #[test] + fn can_fetch_xdg_media_dirs() { + let dirs = match MediaDirs::xdg() { + Ok(dirs) => dirs, + Err(e) if e.kind() == ErrorKind::NotFound => { + // xdg-user-dirs not initialized on this system, skip the test + return; + } + Err(e) => panic!("failed to fetch xdg user dirs: {e:?}"), + }; + + // even when user-dirs.dirs is present, directories may be unset, + // so we can't assert anything about the dir paths here + let _ = dirs; + } + + #[test] + fn test_well_user_dirs_parsing() { + const TEST_USERDIRS: &'static str = r#" +# This file is written by xdg-user-dirs-update +# If you want to change or add directories, just edit the line you're +# interested in. All local changes will be retained on the next run. +# Format is XDG_xxx_DIR="$HOME/yyy", where yyy is a shell-escaped +# homedir-relative path, or XDG_xxx_DIR="/yyy", where /yyy is an +# absolute path. No other format is supported. +# +XDG_DESKTOP_DIR="$HOME/Desktop" +XDG_DOWNLOAD_DIR="$HOME/Downloads" +XDG_TEMPLATES_DIR="/pub/Templates" +XDG_PUBLICSHARE_DIR="/pub" +XDG_DOCUMENTS_DIR="$HOME/Documents" +XDG_MUSIC_DIR="$HOME/My \"Music\"" +XDG_PICTURES_DIR="$HOME/Pictures" +XDG_VIDEOS_DIR="$HOME" +"#; + + let dirs = xdg::parse_user_dirs(TEST_USERDIRS.as_bytes(), Path::new("/home/ferris")); + + assert_eq!(dirs.desktop(), Some("/home/ferris/Desktop".as_ref())); + assert_eq!(dirs.downloads(), Some("/home/ferris/Downloads".as_ref())); + assert_eq!(dirs.templates(), Some("/pub/Templates".as_ref())); + assert_eq!(dirs.documents(), Some("/home/ferris/Documents".as_ref())); + assert_eq!(dirs.music(), Some("/home/ferris/My \"Music\"".as_ref())); + assert_eq!(dirs.pictures(), Some("/home/ferris/Pictures".as_ref())); + assert_eq!(dirs.videos(), None); + } + + #[test] + fn test_ill_user_dirs_parsing() { + const TEST_USERDIRS: &'static str = r#" +# unquoted +XDG_DESKTOP_DIR=$HOME/Desktop +# mixed quoting +XDG_DOWNLOAD_DIR="$HOME"/"Downloads" +# non-HOME env +XDG_TEMPLATES_DIR="/home/$USER/Templates" +# missing PUBLICSHARE +# command substitution +XDG_DOCUMENTS_DIR="`pwd`/Documents" +# non-symbolic homedir disabled +XDG_MUSIC_DIR="/home/ferris" +# set multiple times +XDG_PICTURES_DIR="$HOME/Pictures1" +XDG_PICTURES_DIR="$HOME/Pictures2" +# relative path +XDG_VIDEOS_DIR="Videos" +"#; + + let dirs = xdg::parse_user_dirs(TEST_USERDIRS.as_bytes(), Path::new("/home/ferris")); + + assert_eq!(dirs.desktop(), None); + assert_eq!(dirs.downloads(), None); + assert_eq!(dirs.templates(), None); + assert_eq!(dirs.documents(), None); + assert_eq!(dirs.music(), None); + assert_eq!(dirs.pictures(), Some("/home/ferris/Pictures2".as_ref())); + assert_eq!(dirs.videos(), None); + } +} diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 21560638c1d0f..f452de6de449f 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -11,6 +11,13 @@ use crate::sys::{AsInner, AsInnerMut, FromInner, IntoInner}; use crate::time::SystemTime; use crate::{io, sys}; +mod dirs; + +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub use dirs::HomeDirsExt; +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub use dirs::MediaDirsExt; + /// Windows-specific extensions to [`fs::File`]. #[stable(feature = "file_offset", since = "1.15.0")] pub trait FileExt { diff --git a/library/std/src/os/windows/fs/dirs.rs b/library/std/src/os/windows/fs/dirs.rs new file mode 100644 index 0000000000000..52710375e6eb2 --- /dev/null +++ b/library/std/src/os/windows/fs/dirs.rs @@ -0,0 +1,309 @@ +use crate::fs::{HomeDirs, MediaDirs}; +use crate::io::{ErrorKind, const_error}; +use crate::path::PathBuf; +use crate::{env, io}; + +/// Windows-specific extensions to [`fs::HomeDirs`](HomeDirs). +#[unstable(feature = "fs_home_dirs", issue = "162082")] +pub impl(self) trait HomeDirsExt: Sized { + /// Load the known user folder paths from environment variables. + /// + /// The loaded known folders are: + /// + /// | `HomeDirs` | Environment Variable | + /// | ---------- | -------------------- | + /// | [`cache_home`] | `%LOCALAPPDATA%` (`%USERPROFILE%\AppData\Local`) | + /// | [`config_home`] | `%APPDATA%` (`%USERPROFILE%\AppData\Roaming`) | + /// | [`data_home`] | `%APPDATA%` (`%USERPROFILE%\AppData\Roaming`) | + /// | [`state_home`] | `%LOCALAPPDATA%` (`%USERPROFILE%\AppData\Local`) | + /// + /// Note that caches/state are both put in `AppData\Local`, and config/data + /// in `AppData\Roaming`. It is always possible for multiple user directories + /// to be configured to the same path, but this is the common configuration + /// on Windows platforms, making it even more important to not assume files + /// in different user directories cannot alias each other. + /// + /// # Errors + /// + /// Errors if `%APPDATA%` or `%LOCALAPPDATA%` are not set to absolute paths. + /// + /// # Implementation-specific behavior + /// + /// Windows keeps these environment variables updated to contain the paths + /// to the configured folder path, but it is possible for the environment + /// variables to not match the underlying system, such as when the user or + /// a program modifies the environment directly, or if the configuration + /// changed after the environment block was copied from the system. + /// + /// Unlike [`known_folders`](Self::known_folders), this does not require + /// `Shell32.dll` and thus does not require the overhead of linking in + /// DLLs that may result in Windows considering the application as a + /// graphical application. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load additional common + /// directories not currently in this list. + /// + /// [`cache_home`]: HomeDirs::cache_home + /// [`config_home`]: HomeDirs::config_home + /// [`data_home`]: HomeDirs::data_home + /// [`state_home`]: HomeDirs::state_home + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn appdata_env() -> io::Result; + + /// Load the known user folder paths using the [Known Folders] API. + /// + /// The loaded known folders are: + /// + /// | `HomeDirs` | [`KNOWNFOLDERID`] | + /// | ---------- | ----------------- | + /// | [`cache_home`] | [`FOLDERID_LocalAppData`] (`%LOCALAPPDATA%`) | + /// | [`config_home`] | [`FOLDERID_RoamingAppData`] (`%APPDATA%`) | + /// | [`data_home`] | [`FOLDERID_RoamingAppData`] (`%APPDATA%`) | + /// | [`state_home`] | [`FOLDERID_LocalAppData`] (`%LOCALAPPDATA%`) | + /// + /// Note that caches/state are both put in LocalAppData, and config/data + /// in RoamingAppData. It is always possible for multiple user directories + /// to be configured to the same path, but this is the common configuration + /// on Windows platforms, making it even more important to not assume files + /// in different user directories cannot alias each other. + /// + /// # Errors + /// + /// Errors if the underlying system discovery API returns an error. The + /// lack of a configured path is not considered an error and results in a + /// `None` value. + /// + /// # Implementation-specific behavior + /// + /// Calls [`SHGetKnownFolderPath`] for the current user once for each known + /// folder. Does not create the folder if missing. + /// + /// COM should be initialized on the thread that calls this function or + /// else it may return unexpected errors. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load additional common + /// directories not currently in this list. + /// + /// [Known Folders]: https://learn.microsoft.com/en-us/windows/win32/shell/known-folders + /// [`SHGetKnownFolderPath`]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath + /// [`KNOWNFOLDERID`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid + /// [`FOLDERID_LocalAppData`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_localappdata + /// [`FOLDERID_RoamingAppData`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_roamingappdata + /// [`cache_home`]: HomeDirs::cache_home + /// [`config_home`]: HomeDirs::config_home + /// [`data_home`]: HomeDirs::data_home + /// [`state_home`]: HomeDirs::state_home + #[unstable(feature = "fs_home_dirs", issue = "162082")] + fn known_folders() -> io::Result; +} + +/// Windows-specific extensions to [`fs::MediaDirs`](MediaDirs). +#[unstable(feature = "fs_media_dirs", issue = "162083")] +pub impl(self) trait MediaDirsExt: Sized { + /// Load the known user folder paths using the [Known Folders] API. + /// + /// The loaded known folders are: + /// + /// | `MediaDirs` | [`KNOWNFOLDERID`] | + /// | ---------- | ----------------- | + /// | [`desktop`] | [`FOLDERID_Desktop`] (`%USERPROFILE%\Desktop`) | + /// | [`documents`] | [`FOLDERID_Documents`] (`%USERPROFILE%\Documents`) | + /// | [`downloads`] | [`FOLDERID_Downloads`] (`%USERPROFILE%\Downloads`) | + /// | [`music`] | [`FOLDERID_Music`] (`%USERPROFILE%\Music`) | + /// | [`pictures`] | [`FOLDERID_Pictures`] (`%USERPROFILE%\Pictures`) | + /// | [`videos`] | [`FOLDERID_Videos`] (`%USERPROFILE%\Videos`) | + /// + /// # Errors + /// + /// Errors if the underlying system discovery API returns an error. The + /// lack of a configured path is not considered an error and results in a + /// `None` value. + /// + /// # Implementation-specific behavior + /// + /// Calls [`SHGetKnownFolderPath`] for the current user once for each known + /// folder. Does not create the folder if missing. + /// + /// COM should be initialized on the thread that calls this function or + /// else it may return unexpected errors. + /// + /// This behavior may change in the future. One example change that we + /// explicitly reserve the right to make is to load additional common + /// directories not currently in this list. + /// + /// [Known Folders]: https://learn.microsoft.com/en-us/windows/win32/shell/known-folders + /// [`SHGetKnownFolderPath`]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_core/nf-shlobj_core-shgetknownfolderpath + /// [`KNOWNFOLDERID`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid + /// [`FOLDERID_Desktop`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_desktop + /// [`FOLDERID_Documents`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_documents + /// [`FOLDERID_Downloads`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_downloads + /// [`FOLDERID_Music`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_music + /// [`FOLDERID_Pictures`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_pictures + /// [`FOLDERID_Videos`]: https://learn.microsoft.com/en-us/windows/win32/shell/knownfolderid#folderid_videos + /// [`desktop`]: MediaDirs::desktop + /// [`documents`]: MediaDirs::documents + /// [`downloads`]: MediaDirs::downloads + /// [`music`]: MediaDirs::music + /// [`pictures`]: MediaDirs::pictures + /// [`videos`]: MediaDirs::videos + #[unstable(feature = "fs_media_dirs", issue = "162083")] + fn known_folders() -> io::Result; +} + +#[cfg(windows)] +#[unstable(feature = "fs_home_dirs", issue = "162082")] +impl HomeDirsExt for HomeDirs { + fn appdata_env() -> io::Result { + let roaming_app_data = env::var_os("APPDATA") + .map(PathBuf::from) + .filter(|p| p.is_absolute()) + .ok_or(const_error!(ErrorKind::InvalidData, "non-absolute %APPDATA%"))?; + let local_app_data = env::var_os("LOCALAPPDATA") + .map(PathBuf::from) + .filter(|p| p.is_absolute()) + .ok_or(const_error!(ErrorKind::InvalidData, "non-absolute %LOCALAPPDATA%"))?; + + // AppData/Local -- system-local, doesn't make sense to sync to another + // AppData/Roaming -- data that makes sense to sync across machines + + let mut dirs = HomeDirs::empty(); + + dirs.cache = Some(local_app_data.clone()); + dirs.config = Some(roaming_app_data.clone()); + dirs.data = Some(roaming_app_data); + dirs.state = Some(local_app_data); + + Ok(dirs) + } + + fn known_folders() -> io::Result { + use crate::sys::c; + + let local_app_data = sys::get_known_folder_path(&c::FOLDERID_LocalAppData)?; + let roaming_app_data = sys::get_known_folder_path(&c::FOLDERID_RoamingAppData)?; + + // AppData/Local -- system-local, doesn't make sense to sync to another + // AppData/Roaming -- data that makes sense to sync across machines + + let mut dirs = HomeDirs::empty(); + + dirs.cache = local_app_data.clone(); + dirs.config = roaming_app_data.clone(); + dirs.data = roaming_app_data; + dirs.state = local_app_data; + + Ok(dirs) + } +} + +#[cfg(windows)] +#[unstable(feature = "fs_media_dirs", issue = "162083")] +impl MediaDirsExt for MediaDirs { + fn known_folders() -> io::Result { + use crate::sys::c; + + let desktop = sys::get_known_folder_path(&c::FOLDERID_Desktop)?; + let documents = sys::get_known_folder_path(&c::FOLDERID_Documents)?; + let downloads = sys::get_known_folder_path(&c::FOLDERID_Downloads)?; + let music = sys::get_known_folder_path(&c::FOLDERID_Music)?; + let pictures = sys::get_known_folder_path(&c::FOLDERID_Pictures)?; + let videos = sys::get_known_folder_path(&c::FOLDERID_Videos)?; + + let mut dirs = MediaDirs::empty(); + + dirs.desktop = desktop; + dirs.documents = documents; + dirs.downloads = downloads; + dirs.music = music; + dirs.pictures = pictures; + dirs.videos = videos; + + Ok(dirs) + } +} + +#[cfg(windows)] +mod sys { + use crate::io::{self, ErrorKind, const_error}; + use crate::path::PathBuf; + use crate::sys::{c, os2path}; + use crate::{ptr, slice}; + + /// Retrieve a known folder path from the Windows API. + pub fn get_known_folder_path(id: &c::GUID) -> io::Result> { + // Get the known folder path. hToken = NULL requests the current user + // scope, and we set KF_FLAG_DONT_VERIFY because it's a bit faster and + // we don't guarantee that the directories at the paths exist. + let mut pszPath = ptr::null_mut(); + // SAFETY: rfid/ppszPath are valid pointers, flags are appropriate, and + // a NULL hToken is supported by SHGetKnownFolderPath. + let hr = unsafe { + c::SHGetKnownFolderPath( + /* rfid */ id, + /* dwFlags */ c::KF_FLAG_DONT_VERIFY as _, + /* hToken */ ptr::null_mut(), + /* ppszPath */ &mut pszPath, + ) + }; + + let result = match hr { + c::S_OK => { + // SAFETY: pszPath was populated by a successful call to SHGetKnownFolderPath + // and is valid up to and including its nul terminator + let len = unsafe { c::lstrlenW(pszPath) }; + // SAFETY: *pszPath is valid up to and including its nul terminator + Ok(Some(os2path(unsafe { slice::from_raw_parts(pszPath, len as usize) }))) + } + c::E_FAIL => { + // This known folder id exists but does not have a path + if cfg!(debug_assertions) { + unreachable!("should not call get_known_folder_path on a virtual folder"); + } else { + Err(const_error!( + ErrorKind::InvalidInput, + "virtual known folders do not have paths" + )) + } + } + c::E_INVALIDARG => { + // This known folder id is not present on the system + Ok(None) + } + _ => { + // Miscellaneous error + Err(io::Error::from_raw_os_error(hr)) + } + }; + + // SAFETY: The caller is responsible for freeing the path returned by + // SHGetKnownFolderPath by calling CoTaskMemFree, whether it + // succeeds or not. + unsafe { c::CoTaskMemFree(pszPath.cast()) }; + + result + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn can_fetch_known_folder_paths() { + let dirs = HomeDirs::known_folders().unwrap(); + assert!(dirs.cache_home().is_some()); + assert!(dirs.config_home().is_some()); + assert!(dirs.data_home().is_some()); + assert!(dirs.state_home().is_some()); + + let dirs = MediaDirs::known_folders().unwrap(); + assert!(dirs.desktop().is_some()); + assert!(dirs.documents().is_some()); + assert!(dirs.downloads().is_some()); + assert!(dirs.music().is_some()); + assert!(dirs.pictures().is_some()); + assert!(dirs.videos().is_some()); + } +} diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 17b98a4506544..6f16946b79914 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -111,3 +111,11 @@ impl fmt::Debug for Dir { f.debug_struct("Dir").field("path", &self.path).finish() } } + +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct ExtraHomeDirs {} + +#[derive(Debug, Clone, Default)] +#[non_exhaustive] +pub struct ExtraMediaDirs {} diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs index 33feee4fc1c97..89f6989b9adbe 100644 --- a/library/std/src/sys/fs/hermit.rs +++ b/library/std/src/sys/fs/hermit.rs @@ -11,7 +11,7 @@ use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, Raw use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::{Dir, copy, exists}; +pub use crate::sys::fs::common::{Dir, ExtraHomeDirs, ExtraMediaDirs, copy, exists}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::io::DEFAULT_BUF_SIZE; use crate::sys::time::SystemTime; diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index b2666eb2a3da9..93b05b9859d28 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -47,6 +47,9 @@ cfg_select! { mod vexos; use vexos as imp; } + target_vendor = "apple" => { + mod darwin; + } _ => { mod unsupported; use unsupported as imp; @@ -61,8 +64,8 @@ pub fn with_native_path(path: &Path, f: &dyn Fn(&Path) -> io::Result) -> i } pub use imp::{ - Dir, DirBuilder, DirEntry, File, FileAttr, FilePermissions, FileTimes, FileType, OpenOptions, - ReadDir, + Dir, DirBuilder, DirEntry, ExtraHomeDirs, ExtraMediaDirs, File, FileAttr, FilePermissions, + FileTimes, FileType, OpenOptions, ReadDir, }; pub fn read_dir(path: &Path) -> io::Result { diff --git a/library/std/src/sys/fs/motor.rs b/library/std/src/sys/fs/motor.rs index 938d1537790a1..91cd90a6b0cb3 100644 --- a/library/std/src/sys/fs/motor.rs +++ b/library/std/src/sys/fs/motor.rs @@ -4,7 +4,7 @@ use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, RawFd}; use crate::path::{Path, PathBuf}; use crate::sys::fd::FileDesc; -pub use crate::sys::fs::common::{Dir, exists}; +pub use crate::sys::fs::common::{Dir, ExtraHomeDirs, ExtraMediaDirs, exists}; use crate::sys::time::SystemTime; use crate::sys::{ AsInner, AsInnerMut, FromInner, IntoInner, io_slices, io_slices_mut, map_motor_error, diff --git a/library/std/src/sys/fs/solid.rs b/library/std/src/sys/fs/solid.rs index bd963b1d2f038..dfdcacdcdf277 100644 --- a/library/std/src/sys/fs/solid.rs +++ b/library/std/src/sys/fs/solid.rs @@ -9,7 +9,7 @@ use crate::os::raw::{c_int, c_short}; use crate::os::solid::ffi::OsStrExt; use crate::path::{Path, PathBuf}; use crate::sync::Arc; -pub use crate::sys::fs::common::{Dir, exists}; +pub use crate::sys::fs::common::{Dir, ExtraHomeDirs, ExtraMediaDirs, exists}; use crate::sys::helpers::ignore_notfound; use crate::sys::pal::{abi, error}; use crate::sys::time::SystemTime; diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs index 08473e245cc8e..5d0c219586e0e 100644 --- a/library/std/src/sys/fs/uefi.rs +++ b/library/std/src/sys/fs/uefi.rs @@ -6,7 +6,7 @@ use crate::fs::TryLockError; use crate::hash::Hash; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; -pub use crate::sys::fs::common::{Dir, copy, remove_dir_all}; +pub use crate::sys::fs::common::{Dir, ExtraHomeDirs, ExtraMediaDirs, copy, remove_dir_all}; use crate::sys::pal::{helpers, unsupported}; use crate::sys::time::SystemTime; diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 613397e6903c1..691c491c6f7e5 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -50,6 +50,8 @@ use crate::fmt::{self, Write as _}; use crate::fs::TryLockError; use crate::io::{self, BorrowedCursor, Error, IoSlice, IoSliceMut, SeekFrom}; use crate::os::fd::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd}; +#[cfg(not(target_os = "wasi"))] +pub use crate::os::unix::fs::dirs::{ExtraHomeDirs, ExtraMediaDirs}; #[cfg(target_family = "unix")] use crate::os::unix::prelude::*; #[cfg(target_os = "wasi")] @@ -58,6 +60,8 @@ use crate::path::{Path, PathBuf}; use crate::sync::Arc; use crate::sys::fd::FileDesc; pub use crate::sys::fs::common::exists; +#[cfg(target_os = "wasi")] +pub use crate::sys::fs::common::{ExtraHomeDirs, ExtraMediaDirs}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::time::SystemTime; #[cfg(all(target_os = "linux", target_env = "gnu"))] diff --git a/library/std/src/sys/fs/unsupported.rs b/library/std/src/sys/fs/unsupported.rs index 512af27401dfe..26677c7c7410a 100644 --- a/library/std/src/sys/fs/unsupported.rs +++ b/library/std/src/sys/fs/unsupported.rs @@ -4,7 +4,7 @@ use crate::fs::TryLockError; use crate::hash::{Hash, Hasher}; use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom}; use crate::path::{Path, PathBuf}; -pub use crate::sys::fs::common::Dir; +pub use crate::sys::fs::common::{Dir, ExtraHomeDirs, ExtraMediaDirs}; use crate::sys::time::SystemTime; use crate::sys::unsupported; diff --git a/library/std/src/sys/fs/vexos.rs b/library/std/src/sys/fs/vexos.rs index 1357787c44c77..5043a4daa83b4 100644 --- a/library/std/src/sys/fs/vexos.rs +++ b/library/std/src/sys/fs/vexos.rs @@ -16,6 +16,8 @@ pub use unsupported_fs::{ symlink, unlink, }; +pub use crate::sys::fs::common::{ExtraHomeDirs, ExtraMediaDirs}; + /// VEXos file descriptor. /// /// This stores an opaque pointer to a [FatFs file object structure] managed by VEXos diff --git a/library/std/src/sys/fs/windows.rs b/library/std/src/sys/fs/windows.rs index b703ad9bd0ae8..0db5a8b9f9bfb 100644 --- a/library/std/src/sys/fs/windows.rs +++ b/library/std/src/sys/fs/windows.rs @@ -11,6 +11,7 @@ use crate::os::windows::io::{AsHandle, BorrowedHandle}; use crate::os::windows::prelude::*; use crate::path::{Path, PathBuf}; use crate::sync::Arc; +pub use crate::sys::fs::common::{ExtraHomeDirs, ExtraMediaDirs}; use crate::sys::handle::Handle; use crate::sys::pal::api::{self, WinError, set_file_information_by_handle}; use crate::sys::pal::{IoResult, fill_utf16_buf, to_u16s, truncate_utf16_at_nul}; diff --git a/library/std/src/sys/pal/windows/c.rs b/library/std/src/sys/pal/windows/c.rs index 432cd0425ac11..25031968a7e02 100644 --- a/library/std/src/sys/pal/windows/c.rs +++ b/library/std/src/sys/pal/windows/c.rs @@ -154,6 +154,9 @@ pub const MB_ERR_INVALID_CHARS: u32 = cu(windows_sys::MB_ERR_INVALID_CHARS); pub const CREATE_WAITABLE_TIMER_HIGH_RESOLUTION: u32 = cu(windows_sys::CREATE_WAITABLE_TIMER_HIGH_RESOLUTION); +// dwFlags --LoadLibraryExA +pub const LOAD_LIBRARY_SEARCH_SYSTEM32: u32 = cu(windows_sys::LOAD_LIBRARY_SEARCH_SYSTEM32); + // dwCreationDisposition -- CreateFile pub const CREATE_NEW: u32 = cu(windows_sys::CREATE_NEW); pub const OPEN_ALWAYS: u32 = cu(windows_sys::OPEN_ALWAYS); @@ -197,6 +200,16 @@ pub const WAIT_OBJECT_0: u32 = windows_sys::WAIT_OBJECT_0.cast_unsigned(); // LPPROGRESS_ROUTINE return value (DWORD) pub const PROGRESS_CONTINUE: u32 = cu(windows_sys::PROGRESS_CONTINUE); +// KNOWNFOLDERIDs (GUID) +pub const FOLDERID_Desktop: GUID = GUID::from_u128(0xb4bfcc3a_db2c_424c_b029_7fe99a87c641); +pub const FOLDERID_Documents: GUID = GUID::from_u128(0xfdd39ad0_238f_46af_adb4_6c85480369c7); +pub const FOLDERID_Downloads: GUID = GUID::from_u128(0x374de290_123f_4565_9164_39c4925e467b); +pub const FOLDERID_LocalAppData: GUID = GUID::from_u128(0xf1b32785_6fba_4fcf_9d55_7b8e7f157091); +pub const FOLDERID_Music: GUID = GUID::from_u128(0x4bd8d571_6d19_48d3_be97_422220080e43); +pub const FOLDERID_Pictures: GUID = GUID::from_u128(0x33e28130_4e1e_4676_835a_98395c3bc3bb); +pub const FOLDERID_RoamingAppData: GUID = GUID::from_u128(0x3eb685db_65f9_4cf6_a03a_e3ef65729f3d); +pub const FOLDERID_Videos: GUID = GUID::from_u128(0x18989b1d_99b5_455b_841c_ab7c74e4ddfc); + // Errors pub const ERROR_SUCCESS: u32 = cu(windows_sys::ERROR_SUCCESS); pub const ERROR_ACCESS_DENIED: u32 = cu(windows_sys::ERROR_ACCESS_DENIED); @@ -280,6 +293,17 @@ pub fn nt_success(status: NTSTATUS) -> bool { status >= 0 } +impl GUID { + pub const fn from_u128(uuid: u128) -> Self { + Self { + data1: (uuid >> 96) as u32, + data2: (uuid >> 80 & 0xffff) as u16, + data3: (uuid >> 64 & 0xffff) as u16, + data4: (uuid as u64).to_be_bytes(), + } + } +} + impl OBJECT_ATTRIBUTES { pub fn with_length() -> Self { Self { @@ -459,3 +483,24 @@ cfg_select! { unsafe extern "C" { pub fn atexit(cb: unsafe extern "C" fn()) -> c_int; } + +// Functions in DLLs that we want to lazily load +compat_fn_with_fallback! { + // Avoid eagerly linking shell32.dll, which marks the loading application as graphical. + #[lazy] + pub static SHELL32: &CStr = c"shell32"; + + pub fn SHGetKnownFolderPath(rfid : *const KNOWNFOLDERID, dwflags : u32, htoken : HANDLE, ppszpath : *mut PWSTR) -> HRESULT { + unsafe { SetLastError(ERROR_CALL_NOT_IMPLEMENTED as u32); E_NOTIMPL } + } +} + +compat_fn_with_fallback! { + // Only used with SHGetKnownFolderPath, so avoid eager load overhead. + #[lazy] + pub static OLE32: &CStr = c"ole32"; + + pub fn CoTaskMemFree(pv : *mut core::ffi::c_void) -> () { + // without OLE32 there's no COM alloc, so no-op COM free is fine + } +} diff --git a/library/std/src/sys/pal/windows/c/bindings.txt b/library/std/src/sys/pal/windows/c/bindings.txt index ebe4b8e128352..70af36f27907e 100644 --- a/library/std/src/sys/pal/windows/c/bindings.txt +++ b/library/std/src/sys/pal/windows/c/bindings.txt @@ -252,6 +252,8 @@ DNS_ERROR_ZONESCOPE_IS_REFERENCED DUPLICATE_CLOSE_SOURCE DUPLICATE_SAME_ACCESS DuplicateHandle +E_FAIL +E_INVALIDARG E_NOTIMPL ENABLE_AUTO_POSITION ENABLE_ECHO_INPUT @@ -2260,8 +2262,12 @@ IPV6_MREQ IPV6_MULTICAST_LOOP IPV6_V6ONLY IsThreadAFiber +KF_FLAG_DONT_VERIFY +KNOWNFOLDERID LINGER listen +LOAD_LIBRARY_SEARCH_SYSTEM32 +LoadLibraryExA LocalFree LOCKFILE_EXCLUSIVE_LOCK LOCKFILE_FAIL_IMMEDIATELY @@ -2350,6 +2356,7 @@ ReleaseSRWLockShared RemoveDirectoryW RtlGenRandom RtlNtStatusToDosError +S_OK SD_BOTH SD_RECEIVE SD_SEND diff --git a/library/std/src/sys/pal/windows/c/windows_sys.rs b/library/std/src/sys/pal/windows/c/windows_sys.rs index 34c4407296dcf..0c865494a6e7c 100644 --- a/library/std/src/sys/pal/windows/c/windows_sys.rs +++ b/library/std/src/sys/pal/windows/c/windows_sys.rs @@ -71,6 +71,7 @@ windows_link::link!("kernel32.dll" "system" fn InitOnceBeginInitialize(lpinitonc windows_link::link!("kernel32.dll" "system" fn InitOnceComplete(lpinitonce : LPINIT_ONCE, dwflags : u32, lpcontext : *const core::ffi::c_void) -> BOOL); windows_link::link!("kernel32.dll" "system" fn InitializeProcThreadAttributeList(lpattributelist : *mut _PROC_THREAD_ATTRIBUTE_LIST, dwattributecount : u32, dwflags : u32, lpsize : *mut usize) -> BOOL); windows_link::link!("kernel32.dll" "system" fn IsThreadAFiber() -> BOOL); +windows_link::link!("kernel32.dll" "system" fn LoadLibraryExA(lplibfilename : PCSTR, hfile : HANDLE, dwflags : u32) -> HMODULE); windows_link::link!("kernel32.dll" "system" fn LocalFree(hmem : HLOCAL) -> HLOCAL); windows_link::link!("kernel32.dll" "system" fn LockFileEx(hfile : HANDLE, dwflags : u32, dwreserved : u32, nnumberofbytestolocklow : u32, nnumberofbytestolockhigh : u32, lpoverlapped : *mut OVERLAPPED) -> BOOL); windows_link::link!("kernel32.dll" "system" fn MoveFileExW(lpexistingfilename : PCWSTR, lpnewfilename : PCWSTR, dwflags : u32) -> BOOL); @@ -2433,6 +2434,8 @@ impl Default for EXCEPTION_RECORD { } pub const EXCEPTION_STACK_OVERFLOW: i32 = -1073741571; pub const EXTENDED_STARTUPINFO_PRESENT: i32 = 524288; +pub const E_FAIL: HRESULT = 0x80004005_u32 as _; +pub const E_INVALIDARG: HRESULT = 0x80070057_u32 as _; pub const E_NOTIMPL: HRESULT = 0x80004001_u32 as _; pub const ExceptionCollidedUnwind: EXCEPTION_DISPOSITION = 3; pub const ExceptionContinueExecution: EXCEPTION_DISPOSITION = 0; @@ -2925,7 +2928,11 @@ impl Default for IP_MREQ { pub const IP_MULTICAST_LOOP: i32 = 11; pub const IP_MULTICAST_TTL: i32 = 10; pub const IP_TTL: i32 = 4; +pub const KF_FLAG_DONT_VERIFY: KNOWN_FOLDER_FLAG = 16384; +pub type KNOWNFOLDERID = GUID; +pub type KNOWN_FOLDER_FLAG = u32; pub type LINGER = linger; +pub const LOAD_LIBRARY_SEARCH_SYSTEM32: i32 = 2048; pub const LOCKFILE_EXCLUSIVE_LOCK: i32 = 2; pub const LOCKFILE_FAIL_IMMEDIATELY: i32 = 1; pub type LPBYTE = *mut u8; @@ -3295,6 +3302,7 @@ pub struct SYSTEM_INFO_0_0 { pub wProcessorArchitecture: u16, pub wReserved: u16, } +pub const S_OK: HRESULT = 0x0_u32 as _; pub const TCP_NODELAY: i32 = 1; pub const TIMER_ALL_ACCESS: i32 = 2031619; pub const TIMER_MODIFY_STATE: i32 = 2; diff --git a/library/std/src/sys/pal/windows/compat.rs b/library/std/src/sys/pal/windows/compat.rs index c465ceb2301ce..7e9f5bd108729 100644 --- a/library/std/src/sys/pal/windows/compat.rs +++ b/library/std/src/sys/pal/windows/compat.rs @@ -20,7 +20,8 @@ //! importing the same function unnecessarily. use crate::ffi::{CStr, c_void}; -use crate::ptr::NonNull; +use crate::ptr::{self, NonNull}; +use crate::sync::LazyLock; use crate::sys::c; // This uses a static initializer to preload some imported functions. @@ -118,6 +119,23 @@ impl Module { } } + /// Try to load a module handle. + /// + /// # SAFETY + /// + /// This should only be use for modules that exist for the lifetime of std. + pub unsafe fn load(name: &CStr) -> Option { + // SAFETY: A CStr is always null terminated. + unsafe { + let module = c::LoadLibraryExA( + /* lpLibFileName */ name.as_ptr().cast::(), + /* hReserved */ ptr::null_mut(), + /* dwFlags */ c::LOAD_LIBRARY_SEARCH_SYSTEM32, + ); + NonNull::new(module).map(Self) + } + } + // Try to get the address of a function. pub fn proc_address(self, name: &CStr) -> Option> { unsafe { @@ -131,6 +149,33 @@ impl Module { } } +unsafe impl Send for Module {} +unsafe impl Sync for Module {} + +type LazyLoadModule = impl FnOnce() -> Option + Send + Sync + 'static; + +#[define_opaque(LazyLoadModule)] +const fn lazy_load_module(name: &'static CStr) -> LazyLoadModule { + move || unsafe { Module::load(name) } +} + +/// Represents a loaded module. +/// +/// Note that the modules std depends on must not be unloaded. +/// Therefore a `Module` is always valid for the lifetime of std. +pub(in crate::sys) struct LazyModule(LazyLock, LazyLoadModule>); +impl LazyModule { + /// Create a lazy-loaded handle to a module. + pub const unsafe fn new(name: &'static CStr) -> Self { + Self(LazyLock::new(lazy_load_module(name))) + } + + /// Get the module handle, loading it if necessary. + pub fn load(&self) -> Option { + *LazyLock::force(&self.0) + } +} + /// Load a function or use a fallback implementation if that fails. macro_rules! compat_fn_with_fallback { (pub static $module:ident: &CStr = $name:expr; $( @@ -193,6 +238,67 @@ macro_rules! compat_fn_with_fallback { #[allow(unused)] $(#[$meta])* $vis use $symbol::call as $symbol; + )*); + (#[lazy] pub static $module:ident: &CStr = $name:expr; $( + $(#[$meta:meta])* + $vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) -> $rettype:ty $fallback_body:block + )*) => ( + pub static $module: &CStr = $name; + $( + $(#[$meta])* + pub mod $symbol { + #[allow(unused_imports)] + use super::*; + use crate::mem; + use crate::ffi::CStr; + use crate::sync::atomic::{Atomic, AtomicPtr, Ordering}; + use crate::sys::compat::{LazyModule, Module}; + + type F = unsafe extern "system" fn($($argtype),*) -> $rettype; + + /// `PTR` contains a function pointer to one of three functions. + /// It starts with the `load` function. + /// When that is called it attempts to load the requested symbol. + /// If it succeeds, `PTR` is set to the address of that symbol. + /// If it fails, then `PTR` is set to `fallback`. + static PTR: Atomic<*mut c_void> = AtomicPtr::new(load as unsafe extern "system" fn($($argname: $argtype),*) -> $rettype as *mut _); + + unsafe extern "system" fn load($($argname: $argtype),*) -> $rettype { + static MODULE: LazyModule = unsafe { LazyModule::new($module) }; + unsafe { + let func = load_from_module(MODULE.load()); + func($($argname),*) + } + } + + fn load_from_module(module: Option) -> F { + unsafe { + static SYMBOL_NAME: &CStr = ansi_str!(sym $symbol); + if let Some(f) = module.and_then(|m| m.proc_address(SYMBOL_NAME)) { + PTR.store(f.as_ptr(), Ordering::Relaxed); + mem::transmute(f) + } else { + PTR.store(fallback as unsafe extern "system" fn($($argname: $argtype),*) -> $rettype as *mut _, Ordering::Relaxed); + fallback + } + } + } + + #[allow(unused_variables)] + unsafe extern "system" fn fallback($($argname: $argtype),*) -> $rettype { + $fallback_body + } + + #[inline(always)] + pub unsafe fn call($($argname: $argtype),*) -> $rettype { + unsafe { + let func: F = mem::transmute(PTR.load(Ordering::Relaxed)); + func($($argname),*) + } + } + } + $(#[$meta])* + $vis use $symbol::call as $symbol; )*) } diff --git a/library/std/src/sys/paths/mod.rs b/library/std/src/sys/paths/mod.rs index 69c814ef06c06..865d06ae8644e 100644 --- a/library/std/src/sys/paths/mod.rs +++ b/library/std/src/sys/paths/mod.rs @@ -6,7 +6,8 @@ cfg_select! { mod imp { pub use super::hermit::{getcwd, temp_dir}; pub use super::unsupported::{ - JoinPathsError, SplitPaths, chdir, current_exe, home_dir, join_paths, split_paths, + JoinPathsError, SplitPaths, SplitPathsRef, chdir, current_exe, home_dir, + join_paths, split_paths, split_paths_ref, }; } } @@ -16,8 +17,8 @@ cfg_select! { mod unsupported; mod imp { pub use super::motor::{ - JoinPathsError, SplitPaths, chdir, current_exe, getcwd, home_dir, join_paths, - split_paths, temp_dir, + JoinPathsError, SplitPaths, SplitPathsRef, chdir, current_exe, getcwd, home_dir, + join_paths, split_paths, split_paths_ref, temp_dir, }; } } @@ -28,8 +29,8 @@ cfg_select! { mod imp { pub use super::sgx::chdir; pub use super::unsupported::{ - JoinPathsError, SplitPaths, current_exe, getcwd, home_dir, join_paths, split_paths, - temp_dir, + JoinPathsError, SplitPaths, SplitPathsRef, current_exe, getcwd, home_dir, + join_paths, split_paths, split_paths_ref, temp_dir, }; } } @@ -47,7 +48,8 @@ cfg_select! { mod unsupported; mod imp { pub use super::unsupported::{ - JoinPathsError, SplitPaths, current_exe, home_dir, join_paths, split_paths, + JoinPathsError, SplitPaths, SplitPathsRef, current_exe, home_dir, join_paths, + split_paths, split_paths_ref, }; pub use super::wasi::{chdir, getcwd, temp_dir}; } @@ -63,6 +65,6 @@ cfg_select! { } pub use imp::{ - JoinPathsError, SplitPaths, chdir, current_exe, getcwd, home_dir, join_paths, split_paths, - temp_dir, + JoinPathsError, SplitPaths, SplitPathsRef, chdir, current_exe, getcwd, home_dir, join_paths, + split_paths, split_paths_ref, temp_dir, }; diff --git a/library/std/src/sys/paths/uefi.rs b/library/std/src/sys/paths/uefi.rs index 7fddcfdff7724..d9dcd45267935 100644 --- a/library/std/src/sys/paths/uefi.rs +++ b/library/std/src/sys/paths/uefi.rs @@ -1,6 +1,7 @@ use r_efi::efi::protocols::{device_path, loaded_image_device_path}; use crate::ffi::{OsStr, OsString}; +use crate::marker::PhantomData; use crate::os::uefi::ffi::{OsStrExt, OsStringExt}; use crate::path::{self, PathBuf}; use crate::sys::pal::{helpers, unsupported_err}; @@ -71,6 +72,19 @@ impl<'a> Iterator for SplitPaths<'a> { } } +pub struct SplitPathsRef<'a>(!, PhantomData<&'a ()>); + +pub fn split_paths_ref(_unparsed: &OsStr) -> Option> { + None +} + +impl<'a> Iterator for SplitPathsRef<'a> { + type Item = &'a path::Path; + fn next(&mut self) -> Option<&'a path::Path> { + self.0 + } +} + #[derive(Debug)] pub struct JoinPathsError; diff --git a/library/std/src/sys/paths/unix.rs b/library/std/src/sys/paths/unix.rs index e023451b13c8c..cee799c36c79b 100644 --- a/library/std/src/sys/paths/unix.rs +++ b/library/std/src/sys/paths/unix.rs @@ -6,7 +6,7 @@ use libc::{c_char, c_int, c_void}; use crate::ffi::{CStr, OsStr, OsString}; use crate::os::unix::prelude::*; -use crate::path::{self, PathBuf}; +use crate::path::{self, Path, PathBuf}; use crate::sys::helpers::run_path_with_cstr; use crate::sys::pal::cvt; use crate::{fmt, io, iter, mem, ptr, slice, str}; @@ -76,6 +76,28 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { unparsed.as_bytes().split(is_separator).map(into_pathbuf) } +pub type SplitPathsRef<'a> = iter::Map< + slice::Split<'a, u8, impl FnMut(&u8) -> bool + 'static>, + impl FnMut(&[u8]) -> &'_ Path + 'static, +>; + +pub fn split_paths_ref(unparsed: &OsStr) -> Option> { + #[define_opaque(SplitPathsRef)] + fn split_paths_ref(unparsed: &OsStr) -> SplitPathsRef<'_> { + fn is_separator(&b: &u8) -> bool { + b == PATH_SEPARATOR + } + + fn into_path(part: &[u8]) -> &Path { + Path::new(OsStr::from_bytes(part)) + } + + unparsed.as_bytes().split(is_separator).map(into_path) + } + + Some(split_paths_ref(unparsed)) +} + #[derive(Debug)] pub struct JoinPathsError; diff --git a/library/std/src/sys/paths/unsupported.rs b/library/std/src/sys/paths/unsupported.rs index 024830a254fd7..204d6b0897e20 100644 --- a/library/std/src/sys/paths/unsupported.rs +++ b/library/std/src/sys/paths/unsupported.rs @@ -1,6 +1,6 @@ use crate::ffi::{OsStr, OsString}; use crate::marker::PhantomData; -use crate::path::{self, PathBuf}; +use crate::path::{self, Path, PathBuf}; use crate::sys::pal::unsupported; use crate::{fmt, io}; @@ -13,11 +13,16 @@ pub fn chdir(_: &path::Path) -> io::Result<()> { } pub struct SplitPaths<'a>(!, PhantomData<&'a ()>); +pub struct SplitPathsRef<'a>(!, PhantomData<&'a ()>); pub fn split_paths(_unparsed: &OsStr) -> SplitPaths<'_> { panic!("unsupported") } +pub fn split_paths_ref(_unparsed: &OsStr) -> Option> { + None +} + impl<'a> Iterator for SplitPaths<'a> { type Item = PathBuf; fn next(&mut self) -> Option { @@ -25,6 +30,13 @@ impl<'a> Iterator for SplitPaths<'a> { } } +impl<'a> Iterator for SplitPathsRef<'a> { + type Item = &'a Path; + fn next(&mut self) -> Option<&'a Path> { + self.0 + } +} + #[derive(Debug)] pub struct JoinPathsError; diff --git a/library/std/src/sys/paths/windows.rs b/library/std/src/sys/paths/windows.rs index 9b9316b2658c0..350a942124694 100644 --- a/library/std/src/sys/paths/windows.rs +++ b/library/std/src/sys/paths/windows.rs @@ -3,6 +3,7 @@ #![allow(nonstandard_style)] use crate::ffi::{OsStr, OsString}; +use crate::marker::PhantomData; use crate::os::windows::ffi::EncodeWide; use crate::os::windows::prelude::*; use crate::path::{self, PathBuf}; @@ -56,6 +57,19 @@ impl<'a> Iterator for SplitPaths<'a> { } } +pub struct SplitPathsRef<'a>(!, PhantomData<&'a ()>); + +pub fn split_paths_ref(_unparsed: &OsStr) -> Option> { + None +} + +impl<'a> Iterator for SplitPathsRef<'a> { + type Item = &'a path::Path; + fn next(&mut self) -> Option<&'a path::Path> { + self.0 + } +} + #[derive(Debug)] pub struct JoinPathsError; From 7d0907e746d13a832c36f134e9be9e1dc167b496 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 20:32:01 +0200 Subject: [PATCH 1018/1309] arch::breakpoint: update documentation --- library/core/src/arch.rs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index 737a643ef8659..a08901b19ecb4 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -65,9 +65,12 @@ pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))? /// to a trapping instruction (e.g. an undefined instruction) instead, or to some other form of /// target-specific abort that may or may not support convenient resumption. /// -/// The precise behavior and the precise instruction generated are not guaranteed, except that in -/// normal execution with no debug tooling involved this will not continue executing. +/// The precise behavior is not guaranteed, it depends on the architecture and operating system. +/// Not all architectures guarantee that a breakpoint instruction interrupts execution in the absence +/// of a debugger, and not all operating systems and execution environments guarantee that such an +/// interrupt aborts the current process. /// +/// The precise instruction is guaranteed only on the following targets: /// - On x86 targets, this produces an `int3` instruction. /// - On aarch64 targets, this produces a `brk #0xf000` instruction. // When stabilizing this, update the comment on `core::intrinsics::breakpoint`. From 583e737e941c2b46eeb1ce3c1859bd17a3034cc8 Mon Sep 17 00:00:00 2001 From: Jeff Schwab Date: Tue, 29 Sep 2026 15:04:55 -0400 Subject: [PATCH 1019/1309] Mark Rc strong/weak count methods must_use --- library/alloc/src/rcs/rc.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 8cca09d1d4a8c..1b779be08197f 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -1675,6 +1675,7 @@ impl Rc { /// } /// ``` #[inline] + #[must_use] #[unstable(feature = "arc_raw_get_strong", issue = "157021")] pub unsafe fn strong_count_from_raw(ptr: *const T) -> usize { // SAFETY: Upheld by caller. @@ -1875,6 +1876,7 @@ impl Rc { /// assert_eq!(1, Rc::weak_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "rc_counts", since = "1.15.0")] pub fn weak_count(this: &Self) -> usize { this.inner().weak() - 1 @@ -1893,6 +1895,7 @@ impl Rc { /// assert_eq!(2, Rc::strong_count(&five)); /// ``` #[inline] + #[must_use] #[stable(feature = "rc_counts", since = "1.15.0")] pub fn strong_count(this: &Self) -> usize { this.inner().strong() From 707f1c5d9dd4ea1b6a611d3b940a75c9f62750ba Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 21:20:45 +0200 Subject: [PATCH 1020/1309] update breakpoint asm test based on proposal by tgross35 --- library/core/src/arch.rs | 1 + tests/assembly-llvm/breakpoint.rs | 35 ++++++++++++++++++++++--------- 2 files changed, 26 insertions(+), 10 deletions(-) diff --git a/library/core/src/arch.rs b/library/core/src/arch.rs index a08901b19ecb4..04fc16f50085b 100644 --- a/library/core/src/arch.rs +++ b/library/core/src/arch.rs @@ -73,6 +73,7 @@ pub macro global_asm("assembly template", $(operands,)* $(options($(option),*))? /// The precise instruction is guaranteed only on the following targets: /// - On x86 targets, this produces an `int3` instruction. /// - On aarch64 targets, this produces a `brk #0xf000` instruction. +// When adding more items above, also add cases to the test in `tests/assembly-llvm/breakpoint.rs`. // When stabilizing this, update the comment on `core::intrinsics::breakpoint`. #[unstable(feature = "breakpoint", issue = "133724")] #[inline(always)] diff --git a/tests/assembly-llvm/breakpoint.rs b/tests/assembly-llvm/breakpoint.rs index d119b68e899ba..39ee26a4cf5d5 100644 --- a/tests/assembly-llvm/breakpoint.rs +++ b/tests/assembly-llvm/breakpoint.rs @@ -1,15 +1,30 @@ -//@ revisions: aarch64 x86_64 +//! Verify that the breakpoint operation emits the instructions we guarantee. + +//@ add-minicore //@ assembly-output: emit-asm -//@[aarch64] only-aarch64 -//@[x86_64] only-x86_64 +//@ revisions: AARCH64 I686 X86_64 +//@ [AARCH64] compile-flags: --target aarch64-unknown-linux-gnu +//@ [AARCH64] needs-llvm-components: aarch64 +//@ [I686] compile-flags: --target i686-unknown-linux-gnu +//@ [I686] needs-llvm-components: x86 +//@ [X86_64] compile-flags: --target x86_64-unknown-linux-gnu +//@ [X86_64] needs-llvm-components: x86 -#![feature(breakpoint)] #![crate_type = "lib"] +#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![no_core] + +extern crate minicore; + +#[rustc_intrinsic] +#[rustc_nounwind] +fn breakpoint(); -// CHECK-LABEL: use_bp -// aarch64: brk #0xf000 -// x86_64: int3 -#[inline(never)] -pub fn use_bp() { - core::arch::breakpoint(); +// CHECK-LABEL: call_breakpoint +// AARCH64: brk #0xf000 +// I686: int3 +// X86_64: int3 +#[unsafe(no_mangle)] +pub fn call_breakpoint() { + breakpoint(); } From 9c7e293ade2f5f80231d2ed44f6107ca882d05b6 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Tue, 29 Sep 2026 23:43:08 +0200 Subject: [PATCH 1021/1309] remove not in lintcheck existing dependencys that also are not an issue anylonger --- lintcheck/lintcheck_crates.toml | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/lintcheck/lintcheck_crates.toml b/lintcheck/lintcheck_crates.toml index d205c93c6362a..b11c9994e742c 100644 --- a/lintcheck/lintcheck_crates.toml +++ b/lintcheck/lintcheck_crates.toml @@ -41,9 +41,4 @@ once_cell = { name = 'once_cell', version = '1.19.0' } tokio = { name = 'tokio', version = '1.38.1' } [recursive] -ignore = [ - # Takes ~30s to lint - "combine", - # Has 1.2 million `clippy::match_same_arms`s - "unicode-normalization", -] +ignore = [] From 7b273a3554feabf68472b737cd674d7625edb4d8 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Tue, 29 Sep 2026 23:43:45 +0200 Subject: [PATCH 1022/1309] make downloading lintcheck crates paralell --- lintcheck/src/main.rs | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/lintcheck/src/main.rs b/lintcheck/src/main.rs index 67a7e80173614..7e1fe4995fd33 100644 --- a/lintcheck/src/main.rs +++ b/lintcheck/src/main.rs @@ -366,8 +366,13 @@ fn lintcheck(config: LintcheckConfig) { .collect_into(&mut lint_level_args); } + rayon::ThreadPoolBuilder::new() + .num_threads(config.max_jobs) + .build_global() + .unwrap(); + let crates: Vec = crates - .into_iter() + .into_par_iter() .filter(|krate| { if let Some(only_one_crate) = &config.only { krate.name == *only_one_crate @@ -386,16 +391,6 @@ fn lintcheck(config: LintcheckConfig) { std::process::exit(1); } - // run parallel with rayon - - // This helps when we check many small crates with dep-trees that don't have a lot of branches in - // order to achieve some kind of parallelism - - rayon::ThreadPoolBuilder::new() - .num_threads(config.max_jobs) - .build_global() - .unwrap(); - let server = config.recursive.then(|| { let _: io::Result<()> = fs::remove_dir_all(format!("{}/lintcheck/shared_target_dir/recursive", target_dir())); From b84f31e3bbc535bb2270aadf963d3913c3f3494e Mon Sep 17 00:00:00 2001 From: Austin Hou Date: Tue, 29 Sep 2026 15:05:12 -0700 Subject: [PATCH 1023/1309] Track all visited types in `has_non_owning_mutable_access`. Only `PhantomData` were tracked as visited, which caused types that could be reachable by several paths to be rewalked, while cycles with associated types caused stack overflow. --- clippy_utils/src/ty/mod.rs | 26 +++++++------- .../ui/crashes/double_ended_iterator_last.rs | 36 +++++++++++++++++++ 2 files changed, 49 insertions(+), 13 deletions(-) create mode 100644 tests/ui/crashes/double_ended_iterator_last.rs diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index ce753b6dd0c7d..1585ffb7022f0 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -1527,36 +1527,36 @@ pub fn has_non_owning_mutable_access<'tcx>(cx: &LateContext<'tcx>, iter_ty: Ty<' /// - A `PhantomData` type containing any of the previous. fn has_non_owning_mutable_access_inner<'tcx>( cx: &LateContext<'tcx>, - phantoms: &mut FxHashSet>, + visited: &mut FxHashSet>, ty: Ty<'tcx>, ) -> bool { + // Avoid cycles and repeated work by skipping types that have already been visited during this traversal. + if !visited.insert(ty) { + return false; + } match ty.kind() { - ty::Adt(adt_def, args) if adt_def.is_phantom_data() => { - phantoms.insert(ty) - && args - .types() - .any(|arg_ty| has_non_owning_mutable_access_inner(cx, phantoms, arg_ty)) - }, + ty::Adt(adt_def, args) if adt_def.is_phantom_data() => args + .types() + .any(|arg_ty| has_non_owning_mutable_access_inner(cx, visited, arg_ty)), ty::Adt(adt_def, args) => adt_def.all_fields().any(|field| { - has_non_owning_mutable_access_inner(cx, phantoms, normalize_ty(cx, field.ty(cx.tcx, args))) + has_non_owning_mutable_access_inner(cx, visited, normalize_ty(cx, field.ty(cx.tcx, args))) }), - ty::Array(elem_ty, _) | ty::Slice(elem_ty) => has_non_owning_mutable_access_inner(cx, phantoms, *elem_ty), + ty::Array(elem_ty, _) | ty::Slice(elem_ty) => has_non_owning_mutable_access_inner(cx, visited, *elem_ty), ty::RawPtr(pointee_ty, mutability) | ty::Ref(_, pointee_ty, mutability) => { mutability.is_mut() || !pointee_ty.is_freeze(cx.tcx, cx.typing_env()) }, ty::Closure(_, closure_args) => { matches!(closure_args.types().next_back(), - Some(captures) if has_non_owning_mutable_access_inner(cx, phantoms, captures)) + Some(captures) if has_non_owning_mutable_access_inner(cx, visited, captures)) }, ty::Tuple(tuple_args) => tuple_args .iter() - .any(|arg_ty| has_non_owning_mutable_access_inner(cx, phantoms, arg_ty)), + .any(|arg_ty| has_non_owning_mutable_access_inner(cx, visited, arg_ty)), _ => false, } } - let mut phantoms = FxHashSet::default(); - has_non_owning_mutable_access_inner(cx, &mut phantoms, iter_ty) + has_non_owning_mutable_access_inner(cx, &mut FxHashSet::default(), iter_ty) } /// Check if `ty` is slice-like, i.e., `&[T]`, `[T; N]`, or `Vec`. diff --git a/tests/ui/crashes/double_ended_iterator_last.rs b/tests/ui/crashes/double_ended_iterator_last.rs new file mode 100644 index 0000000000000..a97267cbc3e2e --- /dev/null +++ b/tests/ui/crashes/double_ended_iterator_last.rs @@ -0,0 +1,36 @@ +//@check-pass + +use std::marker::PhantomData; + +trait Trait { + type Assoc; +} + +struct A(::Assoc); + +struct X; + +impl Trait for X { + type Assoc = A; +} + +struct Iter(PhantomData); + +impl Iterator for Iter { + type Item = (); + + fn next(&mut self) -> Option<()> { + None + } +} + +impl DoubleEndedIterator for Iter { + fn next_back(&mut self) -> Option<()> { + None + } +} + +fn main() { + #[expect(clippy::double_ended_iterator_last)] + let _ = Iter::>(PhantomData).last(); +} From 4b0bbb5bd0876e5c0dc77a0b75f8813c2468c6a4 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 29 Sep 2026 18:15:03 -0400 Subject: [PATCH 1024/1309] Update cargo submodule --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 3d7cf6e937d61..f3865b2a4d1ac 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 3d7cf6e937d6127d0f49881bf689c560b36d35c4 +Subproject commit f3865b2a4d1acc5276f6b3c67d0e057f4dab3928 From 550132c3638c65932649dd2a073b94653256031e Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Sun, 27 Sep 2026 12:03:38 -0400 Subject: [PATCH 1025/1309] run replace-version-placeholder --- compiler/rustc_feature/src/accepted.rs | 4 ++-- compiler/rustc_feature/src/removed.rs | 12 +++++----- compiler/rustc_feature/src/unstable.rs | 12 +++++----- library/alloc/src/alloc.rs | 4 ++-- library/alloc/src/boxed.rs | 20 ++++++++-------- library/alloc/src/fmt.rs | 2 +- library/alloc/src/rcs/arc.rs | 4 ++-- library/alloc/src/rcs/rc.rs | 4 ++-- library/alloc/src/vec/mod.rs | 18 +++++++------- library/alloc/src/vec/partial_eq.rs | 6 ++--- library/core/src/alloc/mod.rs | 24 +++++++++---------- library/core/src/bool.rs | 4 ++-- library/core/src/cell.rs | 12 +++++----- library/core/src/clone.rs | 2 +- library/core/src/cmp.rs | 8 +++---- library/core/src/convert/mod.rs | 2 +- library/core/src/error.rs | 2 +- library/core/src/fmt/mod.rs | 4 ++-- library/core/src/marker.rs | 2 +- library/core/src/mem/drop_guard.rs | 14 +++++------ library/core/src/mem/mod.rs | 6 ++--- library/core/src/num/error.rs | 2 +- library/core/src/primitive_docs.rs | 2 +- library/core/src/slice/mod.rs | 4 ++-- library/core/src/str/mod.rs | 4 ++-- library/std/src/alloc.rs | 2 +- library/std/src/os/windows/process.rs | 8 +++---- library/std/src/path.rs | 2 +- library/std/src/sync/once.rs | 2 +- .../renamed-feature-gates.stderr | 8 +++---- 30 files changed, 100 insertions(+), 100 deletions(-) diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs index 37a3594e374ea..4eb7408244728 100644 --- a/compiler/rustc_feature/src/accepted.rs +++ b/compiler/rustc_feature/src/accepted.rs @@ -47,7 +47,7 @@ declare_features! ( /// Allows `#[target_feature(...)]` on aarch64 platforms (accepted, aarch64_target_feature, "1.61.0", Some(44839)), /// Allows `extern "custom" fn()`. - (accepted, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)), + (accepted, abi_custom, "1.100.0", Some(140829)), /// Allows using the `efiapi` ABI. (accepted, abi_efiapi, "1.68.0", Some(65815)), /// Allows the sysV64 ABI to be specified on all platforms @@ -336,7 +336,7 @@ declare_features! ( /// Allows specifying the whole-archive link modifier (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490)), /// Allows the `!` type. - (accepted, never_type, "CURRENT_RUSTC_VERSION", Some(35121)), + (accepted, never_type, "1.100.0", Some(35121)), /// Allows using non lexical lifetimes (RFC 2094). (accepted, nll, "1.63.0", Some(43234)), /// Allows using `#![no_std]`. diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs index 5e89a060e3335..eca2567ab20ff 100644 --- a/compiler/rustc_feature/src/removed.rs +++ b/compiler/rustc_feature/src/removed.rs @@ -55,7 +55,7 @@ declare_features! ( /// Allows using the `amdgpu-kernel` ABI. (removed, abi_amdgpu_kernel, "1.77.0", Some(51575), None, 120495), (removed, abi_c_cmse_nonsecure_call, "1.90.0", Some(81391), Some("renamed to abi_cmse_nonsecure_call"), 142146), - (removed, abi_unadjusted, "CURRENT_RUSTC_VERSION", None, Some("merged into link_llvm_intrinsics"), 161398), + (removed, abi_unadjusted, "1.100.0", None, Some("merged into link_llvm_intrinsics"), 161398), (removed, advanced_slice_patterns, "1.42.0", Some(62254), Some("merged into `#![feature(slice_patterns)]`"), 67712), (removed, allocator, "1.0.0", None, None), @@ -67,7 +67,7 @@ declare_features! ( (removed, await_macro, "1.38.0", Some(50547), Some("subsumed by `.await` syntax"), 62293), /// Allows using `box` in patterns (RFC 469). - (removed, box_patterns, "CURRENT_RUSTC_VERSION", Some(29641), Some("superseded by `deref_patterns`")), + (removed, box_patterns, "1.100.0", Some(29641), Some("superseded by `deref_patterns`")), /// Allows using the `box $expr` syntax. (removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`"), 108471), /// Allows capturing disjoint fields in a closure/coroutine (RFC 2229). @@ -167,7 +167,7 @@ declare_features! ( ), 133768 ), - (removed, generic_const_args, "CURRENT_RUSTC_VERSION", Some(151972), Some("renamed to `gca_const_items`")), + (removed, generic_const_args, "1.100.0", Some(151972), Some("renamed to `gca_const_items`")), (removed, import_shadowing, "1.0.0", None, None), /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`). (removed, in_band_lifetimes, "1.61.0", Some(44524), @@ -193,12 +193,12 @@ declare_features! ( which is available from cargo build scripts with `cargo:rustc-link-arg` now"), 83820), (removed, macro_reexport, "1.0.0", Some(29638), Some("subsumed by `pub use`"), 49982), - (removed, macroless_const_item_generic_const_args, "CURRENT_RUSTC_VERSION", Some(162540), Some("renamed to `gca_macroless_items`")), - (removed, macroless_generic_const_args, "CURRENT_RUSTC_VERSION", Some(159006), Some("renamed to `gca_macroless_args`")), + (removed, macroless_const_item_generic_const_args, "1.100.0", Some(162540), Some("renamed to `gca_macroless_items`")), + (removed, macroless_generic_const_args, "1.100.0", Some(159006), Some("renamed to `gca_macroless_args`")), /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls. (removed, main, "1.53.0", Some(29634), None, 84217), (removed, managed_boxes, "1.0.0", None, None), - (removed, min_generic_const_args, "CURRENT_RUSTC_VERSION", Some(132980), Some("renamed to `gca_min_const_items`")), + (removed, min_generic_const_args, "1.100.0", Some(132980), Some("renamed to `gca_min_const_items`")), /// Allows the use of type alias impl trait in function return positions (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), Some("removed in favor of full type_alias_impl_trait"), 87564), diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index cb6a1d39b1dd8..1af55be52abde 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -235,7 +235,7 @@ declare_features! ( /// Allows checking whether or not the backend correctly supports unstable float types. (internal, cfg_target_has_reliable_f16_f128, "1.88.0", None), /// Allows checking whether or not the backend correctly supports the unstable `f16b` type. - (internal, cfg_target_has_reliable_f16b, "CURRENT_RUSTC_VERSION", None), + (internal, cfg_target_has_reliable_f16b, "1.100.0", None), /// Allows checking whether or not the target might have thread support. (internal, cfg_target_has_threads, "1.99.0", None), /// Allows identifying the `compiler_builtins` crate. @@ -257,7 +257,7 @@ declare_features! ( /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406 (internal, link_cfg, "1.14.0", None), /// Allows using `#[link_name="__enzyme_*"]`. - (internal, link_enzyme_intrinsics, "CURRENT_RUSTC_VERSION", None), + (internal, link_enzyme_intrinsics, "1.100.0", None), /// Allows using `?Trait` trait bounds in more contexts. (internal, more_maybe_bounds, "1.82.0", None), /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver! @@ -273,7 +273,7 @@ declare_features! ( /// Allows using the `#[stable]` and `#[unstable]` attributes. (internal, staged_api, "1.0.0", None), /// Perma-unstable, only used in the test suite for binders (`for<'a>`). - (internal, test_binder_constraints, "CURRENT_RUSTC_VERSION", None), + (internal, test_binder_constraints, "1.100.0", None), /// Perma-unstable, only used to test the `incomplete_features` lint. (incomplete, test_incomplete_feature, "1.96.0", None), /// Added for testing unstable lints; perma-unstable. @@ -530,7 +530,7 @@ declare_features! ( /// Allow using 16-bit (half precision) floating point numbers. (unstable, f16, "1.78.0", Some(116909)), /// Allow using bfloat16 floating point numbers. - (unstable, f16b, "CURRENT_RUSTC_VERSION", Some(160630)), + (unstable, f16b, "1.100.0", Some(160630)), /// Allows the use of `#[ffi_const]` on foreign functions. (unstable, ffi_const, "1.45.0", Some(58328)), /// Allows the use of `#[ffi_pure]` on foreign functions. @@ -548,7 +548,7 @@ declare_features! ( /// Support delegating implementation of functions to other already implemented functions. (incomplete, fn_delegation, "1.76.0", Some(118212)), /// Traits for function pointers and items - (unstable, fn_static, "CURRENT_RUSTC_VERSION", Some(148768)), + (unstable, fn_static, "1.100.0", Some(148768)), /// Allows using forced keywords `k#fn`. (unstable, forced_keywords, "CURRENT_RUSTC_VERSION", Some(153839)), /// Allows impls for the Freeze trait. @@ -563,7 +563,7 @@ declare_features! ( (incomplete, gca_macroless_args, "1.99.0", Some(159006)), /// Allows directly represented gca_const_items as the rhs of const items without the /// `gca!` macro. - (incomplete, gca_macroless_items, "CURRENT_RUSTC_VERSION", Some(162540)), + (incomplete, gca_macroless_items, "1.100.0", Some(162540)), /// Enables the generic const args MVP (paths to type const items and constructors /// for ADTs and primitives). (incomplete, gca_min_const_items, "1.84.0", Some(132980)), diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index de65820cf9a75..2174c7df32fcd 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -78,7 +78,7 @@ unsafe extern "Rust" { /// This may change in the future. You must not rely on it for correctness! /// /// [*equivalent*]: Allocator#equivalent-allocators -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[derive(Copy, Debug)] #[derive_const(Clone, Default)] // the compiler needs to know when a Box uses the global allocator vs a custom one @@ -566,7 +566,7 @@ impl Global { } } -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe impl Allocator for Global { #[inline] diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7504763120532..beb6522e94bb0 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -235,7 +235,7 @@ pub use thin::ThinBox; // compiler or ICEs will happen. pub struct Box< T: ?Sized, - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] A: Allocator = Global, + #[stable(feature = "allocator_api", since = "1.100.0")] A: Allocator = Global, >(Unique, A); /// Monomorphic function for allocating an uninit `Box`. @@ -443,7 +443,7 @@ impl Box { /// let five = Box::new_in(5, System); /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[must_use] #[inline] pub fn new_in(x: T, alloc: A) -> Self { @@ -676,7 +676,7 @@ impl Box { /// let c = Box::write(uninit, 6); /// assert_eq!(*c, 6); /// ``` - #[stable(feature = "box_take", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "box_take", since = "1.100.0")] pub fn take(boxed: Self) -> (T, Box, A>) { // SAFETY: Reading out an initialised value & leaving behind a // box with uninit contents. @@ -704,7 +704,7 @@ impl Box { /// assert_eq!(*new, 14); /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "smart_pointer_map", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "smart_pointer_map", since = "1.100.0")] pub fn map(this: Self, f: impl FnOnce(T) -> U) -> Box { let (value, allocation) = Box::take(this); let (raw, alloc) = Box::into_non_null_with_allocator(allocation); @@ -1562,7 +1562,7 @@ impl Box { /// /// [memory layout]: self#memory-layout /// [considerations for unsafe code]: self#considerations-for-unsafe-code - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[inline] pub unsafe fn from_raw_in(raw: *mut T, alloc: A) -> Self { // SAFETY: Upheld by caller. @@ -1615,7 +1615,7 @@ impl Box { /// /// [memory layout]: self#memory-layout /// [considerations for unsafe code]: self#considerations-for-unsafe-code - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[inline] pub unsafe fn from_non_null_in(raw: NonNull, alloc: A) -> Self { // SAFETY: guaranteed by the caller. @@ -1665,7 +1665,7 @@ impl Box { /// /// [memory layout]: self#memory-layout #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn into_raw_with_allocator(b: Self) -> (*mut T, A) { @@ -1723,7 +1723,7 @@ impl Box { /// /// [memory layout]: self#memory-layout #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[inline] pub fn into_non_null_with_allocator(b: Self) -> (NonNull, A) { let (ptr, alloc) = Box::into_raw_with_allocator(b); @@ -1869,7 +1869,7 @@ impl Box { /// Note: this is an associated function, which means that you have /// to call it as `Box::allocator(&b)` instead of `b.allocator()`. This /// is so that there is no conflict with a method on the inner type. - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[inline] pub fn allocator(b: &Self) -> &A { &b.1 @@ -2490,7 +2490,7 @@ impl Error for Box { } } -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] unsafe impl Allocator for Box { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { diff --git a/library/alloc/src/fmt.rs b/library/alloc/src/fmt.rs index 0129b04137a50..334d49706dbb9 100644 --- a/library/alloc/src/fmt.rs +++ b/library/alloc/src/fmt.rs @@ -595,7 +595,7 @@ pub use core::fmt::Alignment; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::Error; -#[stable(feature = "fmt_numbuffer", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "fmt_numbuffer", since = "1.100.0")] pub use core::fmt::NumBuffer; #[stable(feature = "rust1", since = "1.0.0")] pub use core::fmt::{Arguments, write}; diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index e61ea5193eccb..4f612dc2bb19a 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -1210,7 +1210,7 @@ impl Arc { /// assert_eq!(*new, 14); /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "smart_pointer_map", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "smart_pointer_map", since = "1.100.0")] pub fn map(this: Self, f: impl FnOnce(&T) -> U) -> Arc { if size_of::() == size_of::() && align_of::() == align_of::() @@ -5148,7 +5148,7 @@ unsafe impl<#[may_dangle] T: ?Sized, A: Allocator> Drop for UniqueArc { } } -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] unsafe impl Allocator for Arc { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 8cca09d1d4a8c..5f29872d3ed67 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -1056,7 +1056,7 @@ impl Rc { /// assert_eq!(*new, 14); /// ``` #[cfg(not(no_global_oom_handling))] - #[stable(feature = "smart_pointer_map", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "smart_pointer_map", since = "1.100.0")] pub fn map(this: Self, f: impl FnOnce(&T) -> U) -> Rc { if size_of::() == size_of::() && align_of::() == align_of::() @@ -4741,7 +4741,7 @@ impl Drop for UniqueRcUninit { } } -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] unsafe impl Allocator for Rc { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index f837d963a572e..681f45609f2b3 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -438,7 +438,7 @@ mod sve_retain; #[doc(alias = "vector")] pub struct Vec< T, - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] A: Allocator = Global, + #[stable(feature = "allocator_api", since = "1.100.0")] A: Allocator = Global, > { buf: RawVec, len: usize, @@ -791,7 +791,7 @@ impl Vec { /// ``` #[cfg(not(no_global_oom_handling))] #[inline] - #[stable(feature = "vec_from_fn", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "vec_from_fn", since = "1.100.0")] pub fn from_fn(length: usize, f: F) -> Self where F: FnMut(usize) -> T, @@ -969,7 +969,7 @@ const impl Vec { /// assert_eq!(vec_units.capacity(), usize::MAX); /// ``` #[inline] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] pub fn with_capacity_in(capacity: usize, alloc: A) -> Self { Vec { buf: RawVec::with_capacity_in(capacity, alloc), len: 0 } } @@ -1061,7 +1061,7 @@ impl Vec { /// let vec: Vec = Vec::new_in(System); /// ``` #[inline] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "allocator_ext", issue = "163177")] pub const fn new_in(alloc: A) -> Self { Vec { buf: RawVec::new_in(alloc), len: 0 } @@ -1181,7 +1181,7 @@ impl Vec { /// } /// ``` #[inline] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_raw_parts_in( ptr: *mut T, @@ -1293,7 +1293,7 @@ impl Vec { /// } /// ``` #[inline] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe fn from_parts_in( ptr: NonNull, @@ -1346,7 +1346,7 @@ impl Vec { /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const fn into_raw_parts_with_allocator(self) -> (*mut T, usize, usize, A) { let mut me = ManuallyDrop::new(self); @@ -1395,7 +1395,7 @@ impl Vec { /// assert_eq!(rebuilt, [4294967295, 0, 1]); /// ``` #[must_use = "losing the pointer will leak memory"] - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const fn into_parts_with_allocator(self) -> (NonNull, usize, usize, A) { let (ptr, len, capacity, alloc) = self.into_raw_parts_with_allocator(); @@ -2114,7 +2114,7 @@ impl Vec { } /// Returns a reference to the underlying allocator. - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] #[inline] pub const fn allocator(&self) -> &A { diff --git a/library/alloc/src/vec/partial_eq.rs b/library/alloc/src/vec/partial_eq.rs index 2d5a839cc8c30..aad307c0a0a10 100644 --- a/library/alloc/src/vec/partial_eq.rs +++ b/library/alloc/src/vec/partial_eq.rs @@ -33,11 +33,11 @@ __impl_slice_eq1! { [] Cow<'_, [T]>, &[U] where T: Clone, #[stable(feature = "ru #[cfg(not(no_global_oom_handling))] __impl_slice_eq1! { [] Cow<'_, [T]>, &mut [U] where T: Clone, #[stable(feature = "rust1", since = "1.0.0")] } #[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [A: Allocator] Vec, Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "CURRENT_RUSTC_VERSION")] } +__impl_slice_eq1! { [A: Allocator] Vec, Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "1.100.0")] } #[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [] &[T], Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "CURRENT_RUSTC_VERSION")] } +__impl_slice_eq1! { [] &[T], Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "1.100.0")] } #[cfg(not(no_global_oom_handling))] -__impl_slice_eq1! { [] &mut [T], Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "CURRENT_RUSTC_VERSION")] } +__impl_slice_eq1! { [] &mut [T], Cow<'_, [U]> where U: Clone, #[stable(feature = "partialeq_cow_for_vec_and_slice", since = "1.100.0")] } __impl_slice_eq1! { const, [A: Allocator, const N: usize] Vec, [U; N], #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[stable(feature = "rust1", since = "1.0.0")] } __impl_slice_eq1! { const, [A: Allocator, const N: usize] Vec, &[U; N], #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] #[stable(feature = "rust1", since = "1.0.0")] } diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 11b9da3032ae7..a69c86d68a117 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -27,15 +27,15 @@ use crate::ptr::{self, NonNull}; /// that may be due to resource exhaustion or to /// something wrong when combining the given input arguments with this /// allocator. -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[derive(Copy, Clone, PartialEq, Eq, Debug)] pub struct AllocError; -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] impl Error for AllocError {} // (we need this for downstream impl of trait Error) -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] impl fmt::Display for AllocError { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.write_str("memory allocation failed") @@ -193,7 +193,7 @@ impl fmt::Display for AllocError { // and make sure they cannot be triggered before relaxing this: // https://rust.tf/156490 // https://rust.tf/159982 -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] pub const unsafe trait Allocator { /// Attempts to allocate a block of memory. @@ -228,7 +228,7 @@ pub const unsafe trait Allocator { /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] fn allocate(&self, layout: Layout) -> Result, AllocError>; /// Behaves like `allocate`, but also ensures that the returned memory is zero-initialized. @@ -246,7 +246,7 @@ pub const unsafe trait Allocator { /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { let ptr = self.allocate(layout)?; // SAFETY: `alloc` returns a valid memory block @@ -270,7 +270,7 @@ pub const unsafe trait Allocator { /// /// [*currently allocated*]: #currently-allocated-memory /// [*fit*]: #memory-fitting - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] unsafe fn deallocate(&self, ptr: NonNull, layout: Layout); /// Attempts to extend the memory block. @@ -312,7 +312,7 @@ pub const unsafe trait Allocator { /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] unsafe fn grow( &self, ptr: NonNull, @@ -373,7 +373,7 @@ pub const unsafe trait Allocator { /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] unsafe fn grow_zeroed( &self, ptr: NonNull, @@ -440,7 +440,7 @@ pub const unsafe trait Allocator { /// call the [`handle_alloc_error`] function, rather than directly invoking `panic!` or similar. /// /// [`handle_alloc_error`]: ../../alloc/alloc/fn.handle_alloc_error.html - #[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "allocator_api", since = "1.100.0")] unsafe fn shrink( &self, ptr: NonNull, @@ -574,7 +574,7 @@ pub unsafe trait AllocatorClone: Allocator + Clone {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub unsafe trait StaticAllocator: Allocator {} -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe impl Allocator for &A where @@ -630,7 +630,7 @@ where } } -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe impl Allocator for &mut A where diff --git a/library/core/src/bool.rs b/library/core/src/bool.rs index b3d7686b6336e..e4ca53b59323f 100644 --- a/library/core/src/bool.rs +++ b/library/core/src/bool.rs @@ -151,8 +151,8 @@ impl bool { /// /// [`true`]: ../std/keyword.true.html /// [`false`]: ../std/keyword.false.html - #[stable(feature = "bool_toggle", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "bool_toggle", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "bool_toggle", since = "1.100.0")] + #[rustc_const_stable(feature = "bool_toggle", since = "1.100.0")] #[inline] pub const fn toggle(&mut self) { *self = !*self; diff --git a/library/core/src/cell.rs b/library/core/src/cell.rs index 47312b2bd5649..3dcf033bbd757 100644 --- a/library/core/src/cell.rs +++ b/library/core/src/cell.rs @@ -2376,8 +2376,8 @@ impl UnsafeCell { /// assert_eq!(old, 5); /// ``` #[inline] - #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsafe_cell_access", since = "1.100.0")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "1.100.0")] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn replace(&self, value: T) -> T { // SAFETY: pointer comes from `&self` so naturally satisfies invariants. @@ -2518,8 +2518,8 @@ impl UnsafeCell { /// assert_eq!(val, &5); /// ``` #[inline] - #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsafe_cell_access", since = "1.100.0")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "1.100.0")] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_ref_unchecked(&self) -> &T { // SAFETY: pointer comes from `&self` so naturally satisfies ptr-to-ref invariants. @@ -2546,8 +2546,8 @@ impl UnsafeCell { /// assert_eq!(uc.into_inner(), 6); /// ``` #[inline] - #[stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] - #[rustc_const_stable(feature = "unsafe_cell_access", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "unsafe_cell_access", since = "1.100.0")] + #[rustc_const_stable(feature = "unsafe_cell_access", since = "1.100.0")] #[allow(clippy::mut_from_ref)] #[rustc_should_not_be_called_on_const_items] pub const unsafe fn as_mut_unchecked(&self) -> &mut T { diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs index 126ab37bc0b71..bd6d929c6d2b0 100644 --- a/library/core/src/clone.rs +++ b/library/core/src/clone.rs @@ -732,7 +732,7 @@ mod impls { bool char } - #[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_clone", issue = "142757")] const impl Clone for ! { #[inline] diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs index 2792c7cde57be..1b57bed2738f7 100644 --- a/library/core/src/cmp.rs +++ b/library/core/src/cmp.rs @@ -2409,7 +2409,7 @@ mod impls { ord_impl! { char usize u8 u16 u32 u64 u128 isize i8 i16 i32 i64 i128 } - #[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl PartialEq for ! { #[inline] @@ -2418,11 +2418,11 @@ mod impls { } } - #[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl Eq for ! {} - #[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl PartialOrd for ! { #[inline] @@ -2431,7 +2431,7 @@ mod impls { } } - #[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_cmp", issue = "143800")] const impl Ord for ! { #[inline] diff --git a/library/core/src/convert/mod.rs b/library/core/src/convert/mod.rs index 214c12686c204..b0f74a8afb598 100644 --- a/library/core/src/convert/mod.rs +++ b/library/core/src/convert/mod.rs @@ -886,7 +886,7 @@ const impl AsMut for str { /// } /// ``` /// -/// Note: Since [`!`] (the "never" type) was stabilized in Rust CURRENT_RUSTC_VERSION, it is +/// Note: Since [`!`] (the "never" type) was stabilized in Rust 1.100.0, it is /// preferred to use `!` directly unless targeting older Rust versions. `Infallible` may be /// deprecated in a future Rust version. #[stable(feature = "convert_infallible", since = "1.34.0")] diff --git a/library/core/src/error.rs b/library/core/src/error.rs index 7386c52849eab..1b640f2d99803 100644 --- a/library/core/src/error.rs +++ b/library/core/src/error.rs @@ -268,7 +268,7 @@ mod private { pub struct Internal; } -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] impl Error for ! {} // Copied from `any.rs`. diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 43dba18375992..55296a62e947a 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -2881,7 +2881,7 @@ macro_rules! fmt_refs { fmt_refs! { Debug, Display, Octal, Binary, LowerHex, UpperHex, LowerExp, UpperExp } -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] impl Debug for ! { #[inline] fn fmt(&self, _: &mut Formatter<'_>) -> Result { @@ -2889,7 +2889,7 @@ impl Debug for ! { } } -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] impl Display for ! { #[inline] fn fmt(&self, _: &mut Formatter<'_>) -> Result { diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index d1a68412247ef..530af0c3af656 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -480,7 +480,7 @@ marker_impls! { } -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] impl Copy for ! {} /// Shared references can be copied, but mutable references *cannot*! diff --git a/library/core/src/mem/drop_guard.rs b/library/core/src/mem/drop_guard.rs index 31f1f93b65378..81104ccce29f1 100644 --- a/library/core/src/mem/drop_guard.rs +++ b/library/core/src/mem/drop_guard.rs @@ -27,7 +27,7 @@ use crate::ops::{Deref, DerefMut}; /// // "Chashu likes tuna!!!" /// } /// ``` -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] #[doc(alias = "ScopeGuard")] #[doc(alias = "defer")] pub struct DropGuard @@ -54,7 +54,7 @@ where /// let value = String::from("Chashu likes tuna"); /// let guard = DropGuard::new(value, |s| println!("{s}")); /// ``` - #[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "drop_guard", since = "1.100.0")] #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")] #[must_use] pub const fn new(inner: T, f: F) -> Self { @@ -79,7 +79,7 @@ where /// let guard = DropGuard::new(value, |s| println!("{s}")); /// assert_eq!(DropGuard::dismiss(guard), "Nori likes chicken"); /// ``` - #[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "drop_guard", since = "1.100.0")] #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")] #[inline] pub const fn dismiss(guard: Self) -> T @@ -105,7 +105,7 @@ where } } -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl Deref for DropGuard where @@ -118,7 +118,7 @@ where } } -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl DerefMut for DropGuard where @@ -129,7 +129,7 @@ where } } -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] #[rustc_const_unstable(feature = "const_drop_guard", issue = "none")] const impl Drop for DropGuard where @@ -146,7 +146,7 @@ where } } -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] impl Debug for DropGuard where T: Debug, diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs index e149e2b4a7039..a22e52f3a3bc7 100644 --- a/library/core/src/mem/mod.rs +++ b/library/core/src/mem/mod.rs @@ -59,7 +59,7 @@ mod transmutability; pub use transmutability::{Assume, TransmuteFrom}; mod drop_guard; -#[stable(feature = "drop_guard", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "drop_guard", since = "1.100.0")] pub use drop_guard::DropGuard; // This one has to be a re-export (rather than wrapping the underlying intrinsic) so that we can do @@ -1708,8 +1708,8 @@ pub macro offset_of($Container:ty, $($fields:expr)+ $(,)?) { /// ``` /// /// [inhabited]: https://doc.rust-lang.org/reference/glossary.html#inhabited -#[stable(feature = "mem_conjure_zst", since = "CURRENT_RUSTC_VERSION")] -#[rustc_const_stable(feature = "mem_conjure_zst", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "mem_conjure_zst", since = "1.100.0")] +#[rustc_const_stable(feature = "mem_conjure_zst", since = "1.100.0")] #[rustc_allow_const_fn_unstable(const_type_name)] // type_name() called only at run time pub const unsafe fn conjure_zst() -> T { const_assert!( diff --git a/library/core/src/num/error.rs b/library/core/src/num/error.rs index d102c456f3b4a..6a8a2d5b636ed 100644 --- a/library/core/src/num/error.rs +++ b/library/core/src/num/error.rs @@ -34,7 +34,7 @@ impl fmt::Display for TryFromIntError { #[stable(feature = "try_from", since = "1.34.0")] impl Error for TryFromIntError {} -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] #[rustc_const_unstable(feature = "const_convert", issue = "143773")] const impl From for TryFromIntError { #[inline] diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 4b84a9de4ce72..5054afdc3490d 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -282,7 +282,7 @@ const _: () = (); /// todo!() as std::iter::Empty<_> /// } /// ``` -#[stable(feature = "never_type", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "never_type", since = "1.100.0")] const _: () = (); // Required to make auto trait impls render. diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs index d89d212111527..6deba9ce9752e 100644 --- a/library/core/src/slice/mod.rs +++ b/library/core/src/slice/mod.rs @@ -2801,7 +2801,7 @@ impl [T] { /// assert_eq!(b"hello".trim_prefix(prefix.as_bytes()), b"llo".as_ref()); /// ``` #[must_use = "returns the subslice without modifying the original"] - #[stable(feature = "trim_prefix_suffix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "trim_prefix_suffix", since = "1.100.0")] pub fn trim_prefix + ?Sized>(&self, prefix: &P) -> &[T] where T: PartialEq, @@ -2839,7 +2839,7 @@ impl [T] { /// assert_eq!(v.trim_suffix(&[50, 30]), &[10, 40, 30][..]); /// ``` #[must_use = "returns the subslice without modifying the original"] - #[stable(feature = "trim_prefix_suffix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "trim_prefix_suffix", since = "1.100.0")] pub fn trim_suffix + ?Sized>(&self, suffix: &P) -> &[T] where T: PartialEq, diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index 99eb935cb2715..017d3f50eba32 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -2556,7 +2556,7 @@ impl str { /// ``` #[must_use = "this returns the remaining substring as a new slice, \ without modifying the original"] - #[stable(feature = "trim_prefix_suffix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "trim_prefix_suffix", since = "1.100.0")] pub fn trim_prefix(&self, prefix: P) -> &str { prefix.strip_prefix_of(self).unwrap_or(self) } @@ -2591,7 +2591,7 @@ impl str { /// ``` #[must_use = "this returns the remaining substring as a new slice, \ without modifying the original"] - #[stable(feature = "trim_prefix_suffix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "trim_prefix_suffix", since = "1.100.0")] pub fn trim_suffix(&self, suffix: P) -> &str where for<'a> P::Searcher<'a>: ReverseSearcher<'a>, diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c6f94944006c9..fa977d16e2311 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -216,7 +216,7 @@ impl System { // The Allocator impl checks the layout size to be non-zero and forwards to the // platform functions in `std::sys::*::alloc`. -#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "allocator_api", since = "1.100.0")] unsafe impl Allocator for System { #[inline] fn allocate(&self, layout: Layout) -> Result, AllocError> { diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index 3e1fe13ee6fc2..bdd2a38f2a443 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -188,7 +188,7 @@ pub impl(self) trait CommandExt { /// /// /// [1]: - #[stable(feature = "windows_process_extensions_show_window", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "windows_process_extensions_show_window", since = "1.100.0")] fn show_window(&mut self, cmd_show: u16) -> &mut process::Command; /// Forces all arguments to be wrapped in quote (`"`) characters. @@ -453,20 +453,20 @@ impl CommandExt for process::Command { #[stable( feature = "windows_process_extensions_main_thread_handle", - since = "CURRENT_RUSTC_VERSION" + since = "1.100.0" )] pub impl(self) trait ChildExt { /// Extracts the main thread raw handle, without taking ownership #[stable( feature = "windows_process_extensions_main_thread_handle", - since = "CURRENT_RUSTC_VERSION" + since = "1.100.0" )] fn main_thread_handle(&self) -> BorrowedHandle<'_>; } #[stable( feature = "windows_process_extensions_main_thread_handle", - since = "CURRENT_RUSTC_VERSION" + since = "1.100.0" )] impl ChildExt for process::Child { fn main_thread_handle(&self) -> BorrowedHandle<'_> { diff --git a/library/std/src/path.rs b/library/std/src/path.rs index 1f45423bd8285..4eb3796ac026d 100644 --- a/library/std/src/path.rs +++ b/library/std/src/path.rs @@ -2770,7 +2770,7 @@ impl Path { /// assert_eq!(path.trim_prefix("/haha"), path); /// ``` #[must_use = "this returns the remaining path as a new path, without modifying the original"] - #[stable(feature = "trim_prefix_suffix", since = "CURRENT_RUSTC_VERSION")] + #[stable(feature = "trim_prefix_suffix", since = "1.100.0")] pub fn trim_prefix

    (&self, base: P) -> &Path where P: AsRef, diff --git a/library/std/src/sync/once.rs b/library/std/src/sync/once.rs index 9b555c32df99d..9b7dd3b78eac7 100644 --- a/library/std/src/sync/once.rs +++ b/library/std/src/sync/once.rs @@ -348,7 +348,7 @@ impl fmt::Debug for Once { } } -#[stable(feature = "once_default", since = "CURRENT_RUSTC_VERSION")] +#[stable(feature = "once_default", since = "1.100.0")] #[rustc_const_unstable(feature = "const_default", issue = "143894")] const impl Default for Once { /// Creates a new `Once` value, same as [`Once::new`]. diff --git a/tests/ui/const-generics/renamed-feature-gates.stderr b/tests/ui/const-generics/renamed-feature-gates.stderr index b5478b7412f0e..96e68daf5ac3a 100644 --- a/tests/ui/const-generics/renamed-feature-gates.stderr +++ b/tests/ui/const-generics/renamed-feature-gates.stderr @@ -4,7 +4,7 @@ error[E0557]: feature has been removed LL | #![feature(min_generic_const_args)] | ^^^^^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION + = note: removed in 1.100.0 = note: renamed to `gca_min_const_items` error[E0557]: feature has been removed @@ -13,7 +13,7 @@ error[E0557]: feature has been removed LL | #![feature(generic_const_args)] | ^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION + = note: removed in 1.100.0 = note: renamed to `gca_const_items` error[E0557]: feature has been removed @@ -22,7 +22,7 @@ error[E0557]: feature has been removed LL | #![feature(macroless_generic_const_args)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION + = note: removed in 1.100.0 = note: renamed to `gca_macroless_args` error[E0557]: feature has been removed @@ -31,7 +31,7 @@ error[E0557]: feature has been removed LL | #![feature(macroless_const_item_generic_const_args)] | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ feature has been removed | - = note: removed in CURRENT_RUSTC_VERSION + = note: removed in 1.100.0 = note: renamed to `gca_macroless_items` error: aborting due to 4 previous errors From 3b3eeb473cde96631b95bbc9cb3f33d2a38efca9 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 29 Sep 2026 07:18:09 -0400 Subject: [PATCH 1026/1309] bump-stage0 to 1.100 beta --- src/stage0 | 1181 ++++++++++++++++++++++++++-------------------------- 1 file changed, 582 insertions(+), 599 deletions(-) diff --git a/src/stage0 b/src/stage0 index 3426edfafbf16..65357a133fe09 100644 --- a/src/stage0 +++ b/src/stage0 @@ -13,605 +13,588 @@ nightly_branch=main # All changes below this comment will be overridden the next time the # tool is executed. -compiler_channel_manifest_hash=1612da194f5a1c699d7a20519341ed9aa62e29f28bf3f303ab6801e8e266b103 -compiler_git_commit_hash=cbae9b4cae2b108f6a3d18cfe6075714bb739463 -compiler_date=2026-08-30 +compiler_channel_manifest_hash=748739f565e7977153cc87b1bf606072e31088a751ed351c1a076cfc4ebd04ed +compiler_git_commit_hash=e3feeb59cd1bdd011a2bfcc0747b55125d9b8527 +compiler_date=2026-09-29 compiler_version=beta -rustfmt_channel_manifest_hash=d950b3b494cde6b8448964e1795a86530bff7ee5e729a48ed6341c6ec3ee5ad1 -rustfmt_git_commit_hash=fd7ed57dfd3bdebb745a1d8158638727b0e7047a -rustfmt_date=2026-08-30 +rustfmt_channel_manifest_hash=4ac7009a2d787fa804178e5a7a067b1f828f85623a160ef7cc417d378814ef3e +rustfmt_git_commit_hash=c1070d69382b8d2f2eb65119c738a77d9e324c9e +rustfmt_date=2026-09-29 rustfmt_version=nightly -dist/2026-08-30/rustc-beta-aarch64-apple-darwin.tar.gz=63da74142f0e917ccbc13cf182bae60d9ec3d545b712ac6150fe8b4e633a2c7a -dist/2026-08-30/rustc-beta-aarch64-apple-darwin.tar.xz=0c20c4730544923b2ba9ab4ccf98cd22db6759d1d6cc2e5b8c99662b953163ac -dist/2026-08-30/rustc-beta-aarch64-pc-windows-gnullvm.tar.gz=1d67701059998ff993a42c3781b2b735bf537d9db46bdb0b94e6cd9313f69b0c -dist/2026-08-30/rustc-beta-aarch64-pc-windows-gnullvm.tar.xz=093d13372b7bc06246e63a1e18aac59464e71939b951e14ae0ce500f467be92c -dist/2026-08-30/rustc-beta-aarch64-pc-windows-msvc.tar.gz=d1a51ad8e37b8f482c994527f7062a4b3ac9d1734be81b677a5e270ff121747e -dist/2026-08-30/rustc-beta-aarch64-pc-windows-msvc.tar.xz=f019195e5c72d6b6e699416d8851555965ccf5f108bddae999e9bf37fec19693 -dist/2026-08-30/rustc-beta-aarch64-unknown-freebsd.tar.gz=f9b8e19c81bb9cbb2c75d841f043b084aa9c3c239b359c761d02d255c16ec928 -dist/2026-08-30/rustc-beta-aarch64-unknown-freebsd.tar.xz=fd02f9f057e75b2f6e5c763dcad6dfd9ec39c8e03a40f2cffb82823edbb2da26 -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=1f44bbb85ebb6d4c218016661afa545a8e038f1b937e49f81bebd915ba10c608 -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=e2e2bf7f32709df924efe7b5f530781ea1428ce163e92270a3ee476b7b3a3d1a -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-musl.tar.gz=5452dc6c27dab927dab0afb5be5f300f1cc9af3c7ccfb88dd605227851fd65d7 -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-musl.tar.xz=1f7c588a39f096f7578fc6bca93f0c85ae40976cf26a51913070119a8b910e07 -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-ohos.tar.gz=8aa1b28d25e4c7a21d3fcb85254d1e2c169ff55b3536a290edacecb6c051ab4b -dist/2026-08-30/rustc-beta-aarch64-unknown-linux-ohos.tar.xz=27208aaaebbcea8e819d7d9fbf20dd994cc24f727dbee339d34e6a995e2b9864 -dist/2026-08-30/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=73f04b6601665531d79900f59a8f92f3e7a90f196d62e1ea10e20a3e6ca6f8f4 -dist/2026-08-30/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=64b0fb006d621f6003527b41e9e31f9141f3df09a0dfe979ee68054d1346016e -dist/2026-08-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=19e1f450d4aa8d169898170c9bcd2ab7fba9d3453a631c57a5148236805f101e -dist/2026-08-30/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=f7715866e5e05360279365dc39eefc96436a53f429cd5b283662a81634f7371f -dist/2026-08-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=2e765b6a53cabb0077ad4f8f563862d115c9f152165dc92615a727bdf0d2998b -dist/2026-08-30/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=09a111ae1c8861099a39d495fcea86c65780bb2b7a6c7bc19fff56915b4f11a5 -dist/2026-08-30/rustc-beta-i686-pc-windows-gnu.tar.gz=02d8f06789c7f48a19e31ddc7c3f8dab995197f7857d410f6df60dad1067b8cf -dist/2026-08-30/rustc-beta-i686-pc-windows-gnu.tar.xz=91bf9711b7551cb3caf6660824ad5c04f27ed9a0fd086211b3aed56628311d45 -dist/2026-08-30/rustc-beta-i686-pc-windows-msvc.tar.gz=70525d3d60e2ebddb9e7b3341314caa0df4e34bdfcb47bae46927fa13a6ed327 -dist/2026-08-30/rustc-beta-i686-pc-windows-msvc.tar.xz=59d9ecfad856f135df42afd957024ede0a3eb263a7ec4ffbf517e16696054d83 -dist/2026-08-30/rustc-beta-i686-unknown-linux-gnu.tar.gz=317c5379344a6e473a29e432d4aab7399ff3dbe86a72dd279c0c82c495d98c65 -dist/2026-08-30/rustc-beta-i686-unknown-linux-gnu.tar.xz=af6b78184886cff946f408dcd27ce4332fe39b514c49a6c285aa12ee8a895194 -dist/2026-08-30/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=0894c6b942bad197888f596f7d518595f5db700cc21089b39d9b923c0bc2c902 -dist/2026-08-30/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=d10527ec270b021405f4c7c8853296837efa3d4f1804d7e9aaf22c7f76b3ac8d -dist/2026-08-30/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=82edc27720b2001ef4ccfaa8638c839bd76ca9294723516749544a794a963f76 -dist/2026-08-30/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=efa4d683554b36de9d19d1aa6a6bcd39223e4b8726d5108895071169f976abf6 -dist/2026-08-30/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=453f91a3f885305cdc98ae91bb06fe0cd3bc2f2cad2db05ffc51a9957c5d7dd5 -dist/2026-08-30/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=acb98b89f961c5b309f54e6dd647f68c105f0f95aabbddbe6363055ab842fb4f -dist/2026-08-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=791dc39fa441ecbd5e976da99d988796ad5382f62a85856722dba4fdc4f81491 -dist/2026-08-30/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=005c0e756b757b0d49b6ec9777a9997799d5328f826a4d168a67994591323037 -dist/2026-08-30/rustc-beta-powerpc64-unknown-linux-musl.tar.gz=d3b6748b0471837b8f2f7118e739f4870f2875fb061253c71dbeadcb5a88253d -dist/2026-08-30/rustc-beta-powerpc64-unknown-linux-musl.tar.xz=9c681f8f3efd7f8130ee8c2a40c39d83f6bd58858e134c8df8bba2b65fc3da1a -dist/2026-08-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=3924195349e7b1b31f6334f0d07d66ca4f3c423fb57b8bdded25fa1746b4d1b1 -dist/2026-08-30/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=3f0decdada02b892f63920829a4af3541f149d44b162b3a98d2aa006f2bf47cb -dist/2026-08-30/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=c8c0a5745dfcecc41a52876a9658badf7a35417173f143f50a6d304eb99c4dd6 -dist/2026-08-30/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=47992ff2ff6725eac8e6322c1d76df258a54fc928cbcc8d175acfe16b5a4058f -dist/2026-08-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=91747193505f48d0eba8653bf14855c81999afefb632207eac3d7d6f355fd2bd -dist/2026-08-30/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=95f5717569d3b07ed6808c82a5a3849284ce9b404792806fc06356a11ae54895 -dist/2026-08-30/rustc-beta-riscv64gc-unknown-linux-musl.tar.gz=ff705b94a62127be2bbbaf20a036fd4d9c3fcc23b852bf50b814120637eb28d9 -dist/2026-08-30/rustc-beta-riscv64gc-unknown-linux-musl.tar.xz=da5837ddd0b7ab0b10be836fcf757ce117bbe54e57d7ce696c38e8779be64328 -dist/2026-08-30/rustc-beta-s390x-unknown-linux-gnu.tar.gz=7282b673f837c2998f70a47e44c67d2d88d75f55be6c363a43706f37acde0676 -dist/2026-08-30/rustc-beta-s390x-unknown-linux-gnu.tar.xz=2890fbd6092fac747d44f525623e77c87d5924a878d20be664e20068f729f01c -dist/2026-08-30/rustc-beta-sparcv9-sun-solaris.tar.gz=b1526015253711f6b54e5e2081e5503461ca94e66edffa3226899c357350475d -dist/2026-08-30/rustc-beta-sparcv9-sun-solaris.tar.xz=dc7adedded9d7c4022057709f33de27a6ace3d08a264f17bee7c8e1a92e975b8 -dist/2026-08-30/rustc-beta-x86_64-apple-darwin.tar.gz=9f06cb6793158449b822f07b86a2a57c73d12ad05dee33d188027ae20559f197 -dist/2026-08-30/rustc-beta-x86_64-apple-darwin.tar.xz=d506f9e4bfe7d3d223a88392d5416ac0203924e31b6e3f68a32adc1578d74e0b -dist/2026-08-30/rustc-beta-x86_64-pc-solaris.tar.gz=60825508456e01c09e82986c2c3574dd954e2fbdb16f20db1751437eb2294414 -dist/2026-08-30/rustc-beta-x86_64-pc-solaris.tar.xz=7aa295d6f6ab2eca3d72e1703bc533ac01908dd5080a859c7ab01003d0634d9d -dist/2026-08-30/rustc-beta-x86_64-pc-windows-gnu.tar.gz=01bda7ca1de22ac2881f0da5bd1db0c31500eab3e4b5273d16b581193788e32c -dist/2026-08-30/rustc-beta-x86_64-pc-windows-gnu.tar.xz=65229fa0b642f511ecae17f456d5a67aac0338adcb07ad0746eaec97cd0b2d25 -dist/2026-08-30/rustc-beta-x86_64-pc-windows-gnullvm.tar.gz=90021d8fc771da2febbc00152c6dd7c3b58845a9a522f74573a2acab9f55a016 -dist/2026-08-30/rustc-beta-x86_64-pc-windows-gnullvm.tar.xz=cec531ec82cd3630818985aa6e2e2afdd553e195c87c26873b914c2a159929a2 -dist/2026-08-30/rustc-beta-x86_64-pc-windows-msvc.tar.gz=2d41c0c375f565315155c80e0d241bd8ea132e994b5d87ded8a21302f29d5ab4 -dist/2026-08-30/rustc-beta-x86_64-pc-windows-msvc.tar.xz=6d82171d5e4453c466313f6541fbb62dc74d0c7863651413c687b7f4c27b2a4e -dist/2026-08-30/rustc-beta-x86_64-unknown-freebsd.tar.gz=0509d78b60e4743b1953f12a70a91adc7ef48cf886826dcb16e87695999c7699 -dist/2026-08-30/rustc-beta-x86_64-unknown-freebsd.tar.xz=a5714f58f8651919a51c8ce28536ce83f86fd7ac72bf067dd97189c1d389c07b -dist/2026-08-30/rustc-beta-x86_64-unknown-illumos.tar.gz=883ab0b98ded267ff1b7a8fd0d9ffc7529ff6a5e6b1e73c2168faf1c90d92ef0 -dist/2026-08-30/rustc-beta-x86_64-unknown-illumos.tar.xz=58178ca6b6c9ced54a0f7991fbd94f6d92c32eacffbf774444429ea46b1f58d3 -dist/2026-08-30/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=2a164be1423d98988d4c3e9c7635af9150a961b5fb3d2052517987266978fc65 -dist/2026-08-30/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=66764b74fe55573ea5884ac7ac98fd7e5bff95f4ee0f389e3f5ee07eb75e1623 -dist/2026-08-30/rustc-beta-x86_64-unknown-linux-musl.tar.gz=4b7216393d167874d030e24efd637717f8451c89506c4964220632556522e881 -dist/2026-08-30/rustc-beta-x86_64-unknown-linux-musl.tar.xz=645c594846ac499aa29bef08dacf4402f2479413fb98ab255419bbcbaa39440b -dist/2026-08-30/rustc-beta-x86_64-unknown-netbsd.tar.gz=a1044a20bd4e0894f94d0d2a2f2601bd9e8315be561bb196360950fc959c9ab0 -dist/2026-08-30/rustc-beta-x86_64-unknown-netbsd.tar.xz=c90e60e75e4d2420bb58df22483f028c92eead983b2a5f73e1c87f66196a80d1 -dist/2026-08-30/rust-std-beta-aarch64-apple-darwin.tar.gz=9f02f6d297a31bb6a6bca2648f7e6e381d386365ec2548619f200fce3d1d7109 -dist/2026-08-30/rust-std-beta-aarch64-apple-darwin.tar.xz=d8f4620f3672cae11fdb841a86d44215aeba2e656244286056f7742e966797e3 -dist/2026-08-30/rust-std-beta-aarch64-apple-ios.tar.gz=547510c49fc9c4d993ca76d7d2a38e6e0fc791a8b838fb30e246df78c3480ce8 -dist/2026-08-30/rust-std-beta-aarch64-apple-ios.tar.xz=b54fc751131000c13c58b2863ed238a6d6f750fdb1b1a5e6e1110e05bedc5f7e -dist/2026-08-30/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=c2c93323193b2f6d796934916c002c0d98203745c98458678d70eaff2546566d -dist/2026-08-30/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=ab88ae96f66a15ce8fb00296e8f7f292d31f941e89455529ee7544220187cdec -dist/2026-08-30/rust-std-beta-aarch64-apple-ios-sim.tar.gz=dff0cf3e961505ada60f6fad68cc5f5881b725bb7ef0f0d23b6ae4fb8722f5a1 -dist/2026-08-30/rust-std-beta-aarch64-apple-ios-sim.tar.xz=b6c00ebacb1758e8f3b830a054df06d120e270c4b2a0ef88866b06be2bb95e53 -dist/2026-08-30/rust-std-beta-aarch64-apple-tvos.tar.gz=7f6c1cb3f8b5870449fdbfe1139f27c93b810b1f52da01a93abb8c8656ecc14d -dist/2026-08-30/rust-std-beta-aarch64-apple-tvos.tar.xz=e40b47e96b7ad06f7e13fa0272b4b8014eb4799bd4c7237f35df513eb7eed7cf -dist/2026-08-30/rust-std-beta-aarch64-apple-tvos-sim.tar.gz=158c8066d75a93d770ca620ffb64b92d39630b401a909f17e99765b9871ec25c -dist/2026-08-30/rust-std-beta-aarch64-apple-tvos-sim.tar.xz=635d4e479727b51957b0bbfa14ac5ce7b3282ae146aa04a92ff28963cbf9635f -dist/2026-08-30/rust-std-beta-aarch64-apple-visionos.tar.gz=28f4a6e679995ac6b4037f29c9cdc161183012edb39e484d31ce24ef044128d5 -dist/2026-08-30/rust-std-beta-aarch64-apple-visionos.tar.xz=b3d6255fb1e052747ddf5c3b3484040cbf03dbc882e92cde98c8656442f84cc5 -dist/2026-08-30/rust-std-beta-aarch64-apple-visionos-sim.tar.gz=09facc091183c715daf223d9bd158d6333c6e3f837627bf318f2c0e1be0851b9 -dist/2026-08-30/rust-std-beta-aarch64-apple-visionos-sim.tar.xz=4943e00b8e0496786ec9c2bfa526da1f44aa162f874f7084f51c95c3ec3a44b1 -dist/2026-08-30/rust-std-beta-aarch64-apple-watchos.tar.gz=ba3e478886aa3b34101334e3ab9a3543a0f5e3d44f44efa48bc7b56c14a3951a -dist/2026-08-30/rust-std-beta-aarch64-apple-watchos.tar.xz=2e4e7035ab8464d8ba3775b66433b1888044394bf18343bbbb16304ada735368 -dist/2026-08-30/rust-std-beta-aarch64-apple-watchos-sim.tar.gz=7f8ffe07832cc648c8be54b79bc6923594a34e254245e07fe706fccd52b28195 -dist/2026-08-30/rust-std-beta-aarch64-apple-watchos-sim.tar.xz=343aef2c9816bd2007837916a8ee5101c1b0b97692066c5cf844a7230a42a346 -dist/2026-08-30/rust-std-beta-aarch64-linux-android.tar.gz=94b3a90192944d2483e2c4e3bf02a03e43b00540c16873d869a75b6e6d7a675e -dist/2026-08-30/rust-std-beta-aarch64-linux-android.tar.xz=e26b35a45e9d2331b4ee37f6f9b70f927dc89cd4b956ec76c556577c7b0fa1e4 -dist/2026-08-30/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=24eef069090edc04f787002c971bccbc328775b54d98e3ab63b247a4c1e0e99c -dist/2026-08-30/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=88cf54b25e9a76e303413bb6d32e064d784e6b83dc282a42d45983d57842ca08 -dist/2026-08-30/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=726999c2b5dbec5ca64e56abbce4d246dcb265d709df96d48a4653e863531ac7 -dist/2026-08-30/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=22e04ac2cd44daff5e5873f8492a1a3345f83034021923ff223cb3905c81e16b -dist/2026-08-30/rust-std-beta-aarch64-unknown-freebsd.tar.gz=9593926d80f8b3adfa59b2073f48234001d70c08225d03e0f128f0188d2878c3 -dist/2026-08-30/rust-std-beta-aarch64-unknown-freebsd.tar.xz=f43da9dc7737f5881391e92013f773c6fc3888dece33eac141797617d590ecc1 -dist/2026-08-30/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=9d177fcaf3805830b0b0a1661d3306509f5620195877185b0630193220a95feb -dist/2026-08-30/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=b1c017c1cc05c334f74dbf747d29e692cbf4bdb9c08d5778067266d7816841f4 -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=b443b40dbe16c1c0805778d34a652b16dd891e5d641ece48f988be00d4ae8c25 -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=295de2ccd9c9ffaf6648e76a4bd358289fc78ed0ed162d38a69632a6bfae240a -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=8fdf744594d28f7425df836f3ad3289ea052e26aa98e0d9659c8f03a85d9713a -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=e87932897c88f458d35e53873b2c019f2cebbf11e634689f8e9b97c9320adcd3 -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=33e0b8fbe21128edbaa3c2da91fac703107964f818624dd87a03179c9a6b4a62 -dist/2026-08-30/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=8c79addb67a5c8b8181fa25df85516bdc4fa69003c2f8c9e8a6c6c60eaba6920 -dist/2026-08-30/rust-std-beta-aarch64-unknown-none.tar.gz=39cafc68fb5044aa42fa274fc7c49bc210472d5cd97ed82cd09c98b73042f66d -dist/2026-08-30/rust-std-beta-aarch64-unknown-none.tar.xz=78c289e2984f4b99bb9caa4d61833dc94b0588be7aac2309c4c9cf5d75b56703 -dist/2026-08-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=b6012253ae93c1a13ea4e8cab50873c206056fd9325d26de402e45669950994d -dist/2026-08-30/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=d9fb182de0cffbb3a74fe309ba65d79323901da154e9766a88a569247f260d2a -dist/2026-08-30/rust-std-beta-aarch64-unknown-uefi.tar.gz=f54892f078518f520b32bf76a932cce2c450289cd70c826542477401109eb3dc -dist/2026-08-30/rust-std-beta-aarch64-unknown-uefi.tar.xz=672c8e38330262341209232c73bb600f2949b3d5a1f5c93d0a95e18539fb94de -dist/2026-08-30/rust-std-beta-arm-linux-androideabi.tar.gz=887d61d7764ea35bcb2fdd608940a0d3b0d888cd2b8c94f33d242ae71d2269d7 -dist/2026-08-30/rust-std-beta-arm-linux-androideabi.tar.xz=29f1dea85c828ae819c5ebca3d76dd451cf72e9498f9f207f3272162cc159cd1 -dist/2026-08-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=b735d7f9cfac1d3a7ad22e0b79979f78aeded3c538dee686728ff9e8c64d6787 -dist/2026-08-30/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=878c84e83139426b209f0ae84a898e005f499d38700f5d8446a6aa4ad81feabf -dist/2026-08-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=bdaf3e6c1fba51bd37e7d23b547642885b97e3e66e3e5805f60ee03332e1548d -dist/2026-08-30/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=26446f3d1d9e235e11ebe6e21e3c8bb23efe5e8d31671bf2d573af5e39ae7ba3 -dist/2026-08-30/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=21a1317f24f27d3c567c08c8306f3c97a38dad185bde37229e7c279adb52875f -dist/2026-08-30/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=51ad360481ab758d3023dc615351afba30cf99a162e3f207f5275b5995258412 -dist/2026-08-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=57d7204c68646f489e1db251e69d5fbb329e71954100a9a58bc4eea5bd526c34 -dist/2026-08-30/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=01b476bcd78cfc757d9687ad65cad8c15f4bc5bd2e3149a04314e1604257169a -dist/2026-08-30/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=3b94aba1d51f5a6f039a555122d358bdd8e8f3a1a13e3622842a56acd9e48765 -dist/2026-08-30/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=c814c2d7b7de9f97457932139960d40d869ae6783528a6e0d7edf3af0d34da2d -dist/2026-08-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=2783998a08bf439cc4f6113a2d7f454791a8437bc9bf9b8d3a9d991bf830eddf -dist/2026-08-30/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=bf7bb1f7e676b0f70786ba671a687701879a7b34f3ebee99e6faab139444c0ca -dist/2026-08-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=0d39dc704bb80630048ca2b6b3706c4e9bbf8c16a1eb24c41e2c818e2c89222d -dist/2026-08-30/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=98058d9812f279e9797e6e2163d706dfa6676647d6abd64efae52d9602978bfb -dist/2026-08-30/rust-std-beta-armv7-linux-androideabi.tar.gz=906e3d6b21ca38b6358a9c381aba7aa8e2894a2abe649d12dcef91cc5ab83dca -dist/2026-08-30/rust-std-beta-armv7-linux-androideabi.tar.xz=bd9c5e2dc8542dd0ebcdb53b40422d364aec9399b93b731879c5cada4947583b -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=a4f1149965d18e306ae5fb29382daa6b0e17b1667d8eae08f0342267d7aa6857 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=58121e6668b93a7bd853dff02ff26fe0c4f5e721f23acb7f092cbdac35835a87 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=7e3ce83fea162bd4eab433bf35402ecc2099a46afeb66b86ea5e54f0b53a93d5 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=4737ebecd9ded896ce25f72c7d2397759bd9243d7399bd6955b90e3fdb4c27d2 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=26d2c719cb467295e3effaeae939241325d6fdfd6d32784e90b6c955cf294ffc -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=d2ec9ee496d74deafee30846ce577333154d4c4221943d53129f3a4c8365118e -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=60007d5b87b54b4f500ce686b1c6740ab7641dda28676a9c56df7b9a36c34141 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=1befc6a2e3b6d7e23bc132ad6fcf4e59934d386e2e467dbbc5ec425d628db846 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=6ee69a47a0ce552fb9b69edeca089004c84de1d380ea45554964be8dc5b854d7 -dist/2026-08-30/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=6a594a15e7a1962f4417997d1b1fcdfe72a3786f019242567a915237a8f12112 -dist/2026-08-30/rust-std-beta-armv7a-none-eabi.tar.gz=af06b8910b044e0c804802c316904d53d0a6072d601353927bf5d733cbb10664 -dist/2026-08-30/rust-std-beta-armv7a-none-eabi.tar.xz=dda99a3c47b6fdaa000172e3a9f52876d168499a24e33716a1277a2c1d3e303b -dist/2026-08-30/rust-std-beta-armv7a-none-eabihf.tar.gz=42799d4c5f6b596b6f4c565358adacd2982433cf26f16bde99047f63b07ab97a -dist/2026-08-30/rust-std-beta-armv7a-none-eabihf.tar.xz=0cb9cfeae9a30ec848ef007dd9144398c66be3a755ffe94d9898f2da9057170c -dist/2026-08-30/rust-std-beta-armv7r-none-eabi.tar.gz=b248ea8f35a5557e53882f362ab00211f15124688f56e57474c66bece0bc5c77 -dist/2026-08-30/rust-std-beta-armv7r-none-eabi.tar.xz=9427d716b04a5b178788fead61b3b41abb4acf482bc3def3c1f9b3513243b156 -dist/2026-08-30/rust-std-beta-armv7r-none-eabihf.tar.gz=b8f8e1359af035a33afde195fe4c3de23412c950e216d1ecf6a80fe471f5eadc -dist/2026-08-30/rust-std-beta-armv7r-none-eabihf.tar.xz=1a8aa055f437a8e6dc258d60697f10664b2e28e74ee450d256fd38243730a101 -dist/2026-08-30/rust-std-beta-armv8r-none-eabihf.tar.gz=3b512dfdc3365c1e7d19e42755506a2aca6efa880d754d7838e69b19f6a8d607 -dist/2026-08-30/rust-std-beta-armv8r-none-eabihf.tar.xz=f12bca87642b53c9ef4672ad070913a411de0b772a1f4437b9a258a989d8298c -dist/2026-08-30/rust-std-beta-i586-unknown-linux-gnu.tar.gz=af08b969901c84b02a2501a667bd5cb89454a0817ba66c9fd9a00b03503c922c -dist/2026-08-30/rust-std-beta-i586-unknown-linux-gnu.tar.xz=ec871b92b19cef0f63baea61298575f50ee568046470d0bc12bfc7bee830e846 -dist/2026-08-30/rust-std-beta-i586-unknown-linux-musl.tar.gz=b6805cd6642b6b1de3e637581313cb26241526112114adca8157179948f967e4 -dist/2026-08-30/rust-std-beta-i586-unknown-linux-musl.tar.xz=5c2827bdd87154ce42ad9939dae78a022d3c3045f9b8698f60292e5ba0a0ff14 -dist/2026-08-30/rust-std-beta-i686-linux-android.tar.gz=c568edbc22aba9c2e2360bcf821e9c60894ef3836fc7846cff4c178b2d746fc9 -dist/2026-08-30/rust-std-beta-i686-linux-android.tar.xz=0bd654f6591c99d139bb83ab7e2699327697feddb12edec50bf4f834c0edcffc -dist/2026-08-30/rust-std-beta-i686-pc-windows-gnu.tar.gz=701a3087c3810884d3a83345d2ae8b3de6b1514fbf97bbed99a0421abf2fa2b1 -dist/2026-08-30/rust-std-beta-i686-pc-windows-gnu.tar.xz=b8e8bb023d34012e82d708a0d6e4a558c32f0e489b3eb381b88919aa554578fb -dist/2026-08-30/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=a36eafa511ea809368df67889b2fc0b5a18ed7c2a1e9b21118b160f2b8a63a5b -dist/2026-08-30/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=f1b0c50faf927e5ba97cf0533287cd132f1e3a2b9cb0338f7a56e1ed4311b0bb -dist/2026-08-30/rust-std-beta-i686-pc-windows-msvc.tar.gz=847c2c7aed2ca9f03bc2a8a46ce9b2e48e968e8bb9d947349f83ecde27464631 -dist/2026-08-30/rust-std-beta-i686-pc-windows-msvc.tar.xz=e49a11c577a0e860cfac07eaf0fe1a0f502ada16ec7c05c02d0c60293c8aff8d -dist/2026-08-30/rust-std-beta-i686-unknown-freebsd.tar.gz=c2435372ce00925ed17120ba1586b5d3dac6b4ce979e02698d87a74ad71a7a7e -dist/2026-08-30/rust-std-beta-i686-unknown-freebsd.tar.xz=113874727b99b497e5b346e908407f41b7b2f85cae272cc555dd3699fe8de8fb -dist/2026-08-30/rust-std-beta-i686-unknown-linux-gnu.tar.gz=78385dde39126b0eb524a3681bb8607c016110985ef0b2f2da00c86a5961d64d -dist/2026-08-30/rust-std-beta-i686-unknown-linux-gnu.tar.xz=52480e55a90a54d3174232b4b76f6aaef9055da0ed49733b19ea6c3b8a6db1ea -dist/2026-08-30/rust-std-beta-i686-unknown-linux-musl.tar.gz=350e1a7c2925462c4c2a8b796874f17fd0e284680f2dc2e930017b585ed661c0 -dist/2026-08-30/rust-std-beta-i686-unknown-linux-musl.tar.xz=fd62e7c69e1d0388aaeba25a9a65c8e327e60dbbc3f57948b9f7000981eb4172 -dist/2026-08-30/rust-std-beta-i686-unknown-uefi.tar.gz=41dd818f059414729cd8978a4b79995b765493885dd89a0587be88b83f844aa0 -dist/2026-08-30/rust-std-beta-i686-unknown-uefi.tar.xz=6fb74e7c1b4b20c8b28966e2ee89ab9b1208fb43f57d8f9fe91e5c5bdfa9e046 -dist/2026-08-30/rust-std-beta-loongarch32-unknown-none.tar.gz=5cf23bf844fd1157b9360303459beed6fb1ca77a2bdefd7d394a1d50385670f8 -dist/2026-08-30/rust-std-beta-loongarch32-unknown-none.tar.xz=d952d3f950b776c68528bba94c76a06fb2d55d363fcedeecb1155d6de3a31d3b -dist/2026-08-30/rust-std-beta-loongarch32-unknown-none-softfloat.tar.gz=1967abcc458e9f5efc46f052733490cde533ea074a3ddc0d2fcbf002be4ddc79 -dist/2026-08-30/rust-std-beta-loongarch32-unknown-none-softfloat.tar.xz=bcc63e232b44d653196104d93629ead81c19c1facd03d97207da744c353167d7 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=d8946832080fa2e13498bbe7e0cc5611f1c93da1a7b5e3b19c836d03fe784c15 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=fda84558d60dae4383d6556545bfd0f292f4ca7226db012948c3c2c32b514c6f -dist/2026-08-30/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=63e4aaee66fdf0444becbab59ecbd7a1955d27e5e7420507bfe78e482558a4e7 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=6bc088d81bf425614dea2f31fb0bcf229566cfd912078ba997e272492f5dfeb8 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-none.tar.gz=aed26cd5efdefbc5b636d3a31566c816eda9dde7061efff48b327254b2fc9653 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-none.tar.xz=dd470e7c8ed1a37cd140161988578a31297de2f3739a1d0a1994618f61c4c290 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=be92ce71185bb0bf4d0b220806e6d0251c80eb70d6ef133c205e8121863d0f41 -dist/2026-08-30/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=1417b6cf3730f228ac07f045b8ee6506c2df0d8ae7b262e61ea7625c2ee866af -dist/2026-08-30/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=1b10411f90f9ceb94ba6e901ea347a7b14c784250b26c7ebf578ea0f0f774c34 -dist/2026-08-30/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=5998d419985fe62e015ff1d01f83907a7606c28364c0edbf540db598dd446ec6 -dist/2026-08-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=efba4705562534e2f6ef97857cef856c4d1c88281cb307c7f6696bac05eac943 -dist/2026-08-30/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=d716a06bf4bc9ad2f2d3ae17997cc3b377b8dbd1dfefaf93ae7d4f8c6a913af8 -dist/2026-08-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=7576dd106e174a21eaad65bf48351233ad8cdec1c5f172f6531efc1edeb40f59 -dist/2026-08-30/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=e187119c3fda1b444c340f4d123f95fb23274b624683c844676a15ca2457c209 -dist/2026-08-30/rust-std-beta-powerpc64-unknown-linux-musl.tar.gz=43e4647b626a5c8eb34ef930c70b89ae1efc4d7cb93ea35ea91ab82d52e20ae5 -dist/2026-08-30/rust-std-beta-powerpc64-unknown-linux-musl.tar.xz=ca4204801a3326475c726e3916d9a89c1b8f4f9eb8f2115dac4f005f080355de -dist/2026-08-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=a5d389199f5e64c7f25a97cbd80082a9b07481d79bdea6052ccac4d5e46ee390 -dist/2026-08-30/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=8979ec9fa392b43e9e0e166a68dfb4a0fdf23e28bb54abcd305b5e0e99811a72 -dist/2026-08-30/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=39b9c96f6c01f8ad15e7b5e3cb1550258d9380ea43126c25745c38b7fdb57583 -dist/2026-08-30/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=cf68b7783e218d0b5fac2bc6a431b3c8dedbf016c10c510558771cbdb8c473a0 -dist/2026-08-30/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=adac96c3877930f85c8a9ae7a3afce44bf9030c1bf389dc3e21e7ab0c83c9cf7 -dist/2026-08-30/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=138e96b975fd2bcf54525775a02ab05e1f9ad80095d01116f33693b4359bf0d6 -dist/2026-08-30/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=e7be47333fba57452ed7bf22bdb165a60ea243f9a593df5e8eac32796b0d5d7f -dist/2026-08-30/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=9b4ed1df7fc906cac3f1c9bbb5e546b58e9c6402b9573c4f69c160df8c5e00b8 -dist/2026-08-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=43898c8585bea709bcd682eeea33e914ab8be343ca27dfb82c3524e5ece2d37c -dist/2026-08-30/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=af236521d4556f90cc003dd17f692de787befc62e8c2df11242262f7c2afff22 -dist/2026-08-30/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=2f8125c2d07bb57d821662f06b7eaf00d8b98a7386be372cbd6cd517eb6c6e7b -dist/2026-08-30/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=1a86efb62f35f60d7b1860c37430e039cecfdad2053f6e449577200d715cbe58 -dist/2026-08-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=6f09dc0d0bb9775d0f4b52277913e5fe8795c3d77e178e1682af563f3ab3a030 -dist/2026-08-30/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=0de9f4b1fe08f33dba23effeefa4695a4201094cc587bfdebfb4408e9d58cc8b -dist/2026-08-30/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.gz=dd2e782f2bda2c8f220727b85f8d702efb70977c2232c48bc5d9858264501de3 -dist/2026-08-30/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.xz=d1ba75a8d572591380bba39dd6fed42025f481642993329dc7c20479ea92a6b8 -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=d01ef2e3a1ec1c69b3a80aad302d066ea4fe406ff752c9b65f7ef1beebba0c22 -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=fb919571c31f43ef03b35908bf9ca85ba6bcc053ca289380ba2552c4e64104ba -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=b187f1deba8ea1bb3d3e793c3cb2a6b7f309940e4edbe8b406a023bce82d8785 -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=741cbbf9d91e955303f253ecd885168737dc01369feb33f738290668be01b146 -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=ed5c5a046e9896c7d9ad35c76db1c0216ed31c0661d30e29f3f7b5c8211aeb48 -dist/2026-08-30/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=1ae3c3dd12bc5e669d953521862fff3cec12b6f9f71bb8e3e7b24290d05114cd -dist/2026-08-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3d3bd0667e139054169ec2ece3d16219269c858ffef37c4e9615b5bcf1e3c83b -dist/2026-08-30/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=d350e91efad53a550ef8c825e7f7ce12e99bf250afd9a93ed9fd155b72287947 -dist/2026-08-30/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=eac3ec8b4eb9a3b9a127d2e6fffc4b4a752449eb7595950c9af0dc83ea969b72 -dist/2026-08-30/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=d081593cc03f52a6937fb3bef0a2103a02b43cb4705d1747b8b513e1f0983834 -dist/2026-08-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=17db3b6de8e015e9c572899bedea98996a47d725c59664e338053ed590e4e33b -dist/2026-08-30/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=2e79e7c3eb7515581a8bbee2d02dd8242d7d3d1529eb067a387338b2ae5a63e6 -dist/2026-08-30/rust-std-beta-sparcv9-sun-solaris.tar.gz=72474e747dbdc104c817c90e96e209cf4adc2a441aea37d9c6dc3f89ceaa1a5b -dist/2026-08-30/rust-std-beta-sparcv9-sun-solaris.tar.xz=65cb719203ec265623fffd66f905257c0eb284c0795e736adcc8dfd31750378d -dist/2026-08-30/rust-std-beta-thumbv6m-none-eabi.tar.gz=25f399a7944d8db8a44c49c0adfe7800fa4b12585c49fe2ed69a1b417571b786 -dist/2026-08-30/rust-std-beta-thumbv6m-none-eabi.tar.xz=02183d46df50acf3edbd6778eccf24e357f9d49d87ae0d8808ef47f98cfbfd51 -dist/2026-08-30/rust-std-beta-thumbv7a-none-eabi.tar.gz=839004d3d6ac180bec0e467a7bbd2ea1ddb47a0f29a92f8b2a074f628cfd0395 -dist/2026-08-30/rust-std-beta-thumbv7a-none-eabi.tar.xz=7b9b6c32078adb895fd07f3f72b2db25e9358bfa4a0470d7cfdc3cc7b5a827d4 -dist/2026-08-30/rust-std-beta-thumbv7a-none-eabihf.tar.gz=5e962fec3cc8661e9a62f15c688ac76bc83685e19c163d3b899ec423766429de -dist/2026-08-30/rust-std-beta-thumbv7a-none-eabihf.tar.xz=8db16b6186b89b3e9e0c5560a12bb09d08263e04aa0f9ee878d25dba9852447b -dist/2026-08-30/rust-std-beta-thumbv7em-none-eabi.tar.gz=0150636fdc64ec355916eec21d1dec8f5e73881dd21cb78907a2f06c14a896e8 -dist/2026-08-30/rust-std-beta-thumbv7em-none-eabi.tar.xz=9e4dc0a8492ea92703df7e00994c0e1728d2eb3152947e9b8550d6ae05a76d0d -dist/2026-08-30/rust-std-beta-thumbv7em-none-eabihf.tar.gz=fe3fd11562d4c428ae2757d42f17ee17bf9485c7e7fda2f6a54406ac6ae14444 -dist/2026-08-30/rust-std-beta-thumbv7em-none-eabihf.tar.xz=97735c5e6f77e59ca7540eb303eaa2432f632f867fc7567f1d25540504e889b6 -dist/2026-08-30/rust-std-beta-thumbv7m-none-eabi.tar.gz=e8afd6861c77eff9e8296e1846c01c06d6b83a858bf76099a79588f167999efb -dist/2026-08-30/rust-std-beta-thumbv7m-none-eabi.tar.xz=0421b81a17afc3af31e46a8bfe32a9b178a6a29ba58e25d71be991d1ab84babf -dist/2026-08-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=9612f99fa78f59fcaed30feb3c8660c3ff7e731011226d6114cc49e3f765bb2d -dist/2026-08-30/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=405ab112b26871dc310a7fe3c67d821544f48b4acace5d406c491529555cc890 -dist/2026-08-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=884b25035258fc7cfc7b2a0e95358553a3c7812954ec7a18dde82fd77cad24b4 -dist/2026-08-30/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=3648213c47d2e29931f4837914b3aa5d00575ffda7d75654c6d3cd1aece8474a -dist/2026-08-30/rust-std-beta-thumbv7r-none-eabi.tar.gz=680435027aab539feae6b3904717139e20640eb783c7da2ee31f3d06c1c6ac1d -dist/2026-08-30/rust-std-beta-thumbv7r-none-eabi.tar.xz=8fad51ba8f85f7762f40382c1a177c86f8b7ae1a23e41871f560449f34ac099a -dist/2026-08-30/rust-std-beta-thumbv7r-none-eabihf.tar.gz=0a187507505715a5a4497c0422adba69c03e496618e20023d46aa1a261a7e793 -dist/2026-08-30/rust-std-beta-thumbv7r-none-eabihf.tar.xz=b8bdb79d81f1fd5dbdc090b3306f4ec33673dcfe24350c44e1544d00bb8bbe42 -dist/2026-08-30/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=430646899a6bba8c9233eec0987224e2ed42b6cee3aa37ce12bd8aae66097a21 -dist/2026-08-30/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=36576d200890f00ba9e22cbdb337262ef12dc99271c8006832ebe0752c333ccb -dist/2026-08-30/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=2b3cdc315cfbb7bb1a55705cd30934ceb14b7b098ac9e9b86af2091acc1b46ed -dist/2026-08-30/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=ecbee4d541806d2f4559e53e4da549293f4bb881c2f5d99107043251a1f80790 -dist/2026-08-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=8f925d1d913c67ffd9d28c8d02b47aade2388472015f4917a0f3166a8a789bb7 -dist/2026-08-30/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=c9ba654ccafd0cf8e876770f3133ae143da10f37058978cb67a547f64aa5812f -dist/2026-08-30/rust-std-beta-thumbv8r-none-eabihf.tar.gz=615b2c19357545860fb64ec3b6715c004a4bf29299d8d2130b022acdc7c46ccc -dist/2026-08-30/rust-std-beta-thumbv8r-none-eabihf.tar.xz=27d47d56201190afbaf2e2339d3f56964ff59972a90c994ea551438ed4703eea -dist/2026-08-30/rust-std-beta-wasm32-unknown-emscripten.tar.gz=8ccf1bbfc69d4e8e452294a838adf848d32d57621350a7791d8ac8e1e72f8336 -dist/2026-08-30/rust-std-beta-wasm32-unknown-emscripten.tar.xz=5bd2be0368720436ace1cf02569ca50fa222f936bdda7761954108756151b3bb -dist/2026-08-30/rust-std-beta-wasm32-unknown-unknown.tar.gz=fbdcf8103c16966255aa5a1a65ed02fe6e39862ef2b6e6eade8af07d51654392 -dist/2026-08-30/rust-std-beta-wasm32-unknown-unknown.tar.xz=5c4f71b3be2808511727536c13b6af98fb61661c092031df3f24c568f8bd31d2 -dist/2026-08-30/rust-std-beta-wasm32-wasip1.tar.gz=254037cb663a97b20471a3c87f95d62d1be7b2810a35e53acb219a552e8b58fc -dist/2026-08-30/rust-std-beta-wasm32-wasip1.tar.xz=5f651662f78216db6d2db5a8ac7f8ed04349a82530c08aab2fe3b43b8ea8bf8a -dist/2026-08-30/rust-std-beta-wasm32-wasip1-threads.tar.gz=6093fe10ebfc96c45909e85ae72f98e4f8093cdf2ce9bd720ac1a1aabddbd60c -dist/2026-08-30/rust-std-beta-wasm32-wasip1-threads.tar.xz=175403a655dc2afa2f7b41bdaaac4cb371a6c5cd99a043178fa93f97ab02f604 -dist/2026-08-30/rust-std-beta-wasm32-wasip2.tar.gz=5248648157e3ec5c37d12a40caae0adac59aaae47438585e79a7fc91c294ddf3 -dist/2026-08-30/rust-std-beta-wasm32-wasip2.tar.xz=46705306104b7c5d25a15c0f3cc94f5e208d4da2b07eb516d63533194e901b5c -dist/2026-08-30/rust-std-beta-wasm32v1-none.tar.gz=746d7fa3e93d255a395baaf67d3d318e6419732698ab0089692bdbed5ec4a13b -dist/2026-08-30/rust-std-beta-wasm32v1-none.tar.xz=97d8daf857aa2da8f8daff5f7137c4cf442f3cf05a019b5608a20a4cf5e5d291 -dist/2026-08-30/rust-std-beta-x86_64-apple-darwin.tar.gz=8a5ca2b36f9f4b2ba1dfde1539e95c30a20173137b9822e7d0ec5b2c12aa89ec -dist/2026-08-30/rust-std-beta-x86_64-apple-darwin.tar.xz=2daa0aa9b738f036815b667c664e152750acbb9d14ab41e4ea994000867caae6 -dist/2026-08-30/rust-std-beta-x86_64-apple-ios.tar.gz=4eb04a86e00e50becf154d88eac41feeda32c76730297fd05178a1e941dce0ec -dist/2026-08-30/rust-std-beta-x86_64-apple-ios.tar.xz=80dd8be8e4c1a83b66a0cce6cb5bdea61640e471e755c314a549b56dad10d2d6 -dist/2026-08-30/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=5080a59c173281ec57ff14c32401cb769b1a577ae7710cc54c820120b35c5564 -dist/2026-08-30/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=fae0fb63364548777b9e644e83e3c6d7aeab37953efea5ac27cd2558c828a551 -dist/2026-08-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=fdc91ac8f59e98eac84f79059a486c2ada66890f22b7e66ef7e0b899f65b36e9 -dist/2026-08-30/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=9ead7033def70e9f455e4079d8a8b1c870f8871b80ae721a41f11e53106a6b64 -dist/2026-08-30/rust-std-beta-x86_64-linux-android.tar.gz=c143b388083353883d88d109db9131c1196d2874a0195b66aaa4427365bd4563 -dist/2026-08-30/rust-std-beta-x86_64-linux-android.tar.xz=f877fbc3b099bccfc531661cf4a5d67a69c0cf426b7d6d3269b4aefb85304f9e -dist/2026-08-30/rust-std-beta-x86_64-pc-solaris.tar.gz=719cb1ac855967c03120c7408d05d88ff101e34de40a65f2d37828f496a84eb6 -dist/2026-08-30/rust-std-beta-x86_64-pc-solaris.tar.xz=647430147f7b7903111ef24a90d2f326198ca70bfa0bb0ee5b1e76d297e9a81e -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=520d157e438e557e8f37792b9c59c913a732c77149b534a1c7d2769b52e932dd -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=830bf07e7f1b80e535ddfc2c269c8bd4ca3c63853faa6ba39c7360b0fad976d6 -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=74c1ea656656a624eb84650a833f6d4d3428230435c67ce0a92798a524c55124 -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=8866757f9e3508bd74c724c754511413697229daf50da755411ddc8f9de78fbc -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=8b3ed1fbdf18c25a2900568f9c974154750a187d5385e06537fc54c607e8e305 -dist/2026-08-30/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=f5250ac89f4ee3b68b86e125e64b2209360040189b39e34671aee03b9de3abad -dist/2026-08-30/rust-std-beta-x86_64-unknown-freebsd.tar.gz=711017150d461a85f3dcf28a37c7fa354ae08dbfa9ffa049576e71b224d7c189 -dist/2026-08-30/rust-std-beta-x86_64-unknown-freebsd.tar.xz=5f8a081aa1b6e7ab3bf88b6548ed55a0c1021b26060ee2655da38556b54a0e06 -dist/2026-08-30/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=40d0e66f5b6c1831684ec5c6946e2467e9c81c38d5a7ceffbdc9441397d6c214 -dist/2026-08-30/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=2632a2393f2f51884db1c07a3f193f19942bd20ab7a3bce6f654444028188aab -dist/2026-08-30/rust-std-beta-x86_64-unknown-illumos.tar.gz=bfe5417f3575d1fd0302e6caef380e33c71fc07ab1b9a98fc80d66cf8997006f -dist/2026-08-30/rust-std-beta-x86_64-unknown-illumos.tar.xz=bff9b2786581d340b0e801b085bdfb40d19309e07a99a97f92cf2016d77db81f -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=76d75f97d7b0f3421029d078473529de626d1413d5ac8c0473325c15f2765573 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=1ec3eb585a38de48d12e05f78c82394493c9c640f8c6fdf487cc8c29ca88742d -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.gz=7d12531568c430c670d4933955b767985504a88c3da513b832b857f28e59fbf2 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.xz=ade92cb3f5ca0088d93eeac74ec29b8532d285a730eb87350086e9cda4f7d60b -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.gz=6280a11a0e153f98dfbd4892a90ee60f086c812ded8177e21e6fa3fd9f733441 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.xz=51792543085e26437577f4c3cabd226571c9f9d5b85d142a4d7ec19b992c4bf2 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.gz=85bdd806ddf39fe35df389895b3c531df21b26dd60945f2b92a3f7f7627dfe77 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.xz=076be1c27da9f50254ed8ae748c0ebe01a21af0c47920e035ee25121327cc607 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=e0c5acc46aac350663adc8b6b73e097299a94574785baf5487181b321979b34a -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=f9470afacdce7db3d057bf13af6b6e45574b4c6cd8a1c75adbce2732ab61515e -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=f207346769473385b1efd771abcc0e2a95d73dc93e5039a0ce4cc329daf1e83b -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=25d752aed1d312ab614cd065826c688440aaca70cc7e67c4578ca82398f951f6 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=fc511b73ed5c0da3303efb8b5e01d6e4465cf028543a9ebcd5b1ba273e3e5104 -dist/2026-08-30/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=9ada977527a2fb632cfecd9414226664b47514adc988fbb0e3cb86cf1f81f81b -dist/2026-08-30/rust-std-beta-x86_64-unknown-netbsd.tar.gz=9268af9ae7ed919e0955a1162376ed84c65906304f3dcc64762a6f8dc764031c -dist/2026-08-30/rust-std-beta-x86_64-unknown-netbsd.tar.xz=49f7e2808660320fcde2f1ffe23d4e5d44f26c9d08124a97ffbd715d24c0d21e -dist/2026-08-30/rust-std-beta-x86_64-unknown-none.tar.gz=7f2dea659c4d5ff038118307cd2fc6286a95a6dc12a85686bd958806e3d49647 -dist/2026-08-30/rust-std-beta-x86_64-unknown-none.tar.xz=e96d78c8025876bdb25613fb81cf27b54803ab0a809d761909fc56e626153e1c -dist/2026-08-30/rust-std-beta-x86_64-unknown-redox.tar.gz=7874b37200d60c3986588f6178a623817acbcb66bbbfb9b81c9e4ae348cbc0bf -dist/2026-08-30/rust-std-beta-x86_64-unknown-redox.tar.xz=a6d454739b2fcd6728a7c19afc6e95e6ce2dfb02a569619a071b02b3fb7a6e33 -dist/2026-08-30/rust-std-beta-x86_64-unknown-uefi.tar.gz=6b4c4371089aa7d2be7dea927dfc623c9958998cf02952b8455dc4f05c466ba4 -dist/2026-08-30/rust-std-beta-x86_64-unknown-uefi.tar.xz=1dd395befcbdd4f379a2f78e498c15113e07934b46dfede8dc1075276d7c7cf2 -dist/2026-08-30/cargo-beta-aarch64-apple-darwin.tar.gz=9e761054280cc664f95355b3ff7c9828d6b98fcb63c6cc65b3ef07f78fa98a2c -dist/2026-08-30/cargo-beta-aarch64-apple-darwin.tar.xz=473eed6c6004b83a306c4fcf34002560c292050a6c25247a8c1cbe3ad05b93b4 -dist/2026-08-30/cargo-beta-aarch64-pc-windows-gnullvm.tar.gz=079698fcd5ee509d6b733e7119a8023d9b5e538ea526b64fb286cfdbb85fe16d -dist/2026-08-30/cargo-beta-aarch64-pc-windows-gnullvm.tar.xz=86018bbd5e4ce4a2ed6fe33c520fbdaa1e1cb93a86cc47f8fb8a84f139fbf77b -dist/2026-08-30/cargo-beta-aarch64-pc-windows-msvc.tar.gz=136513f5d9caa1d9a982c5731f07c52ed33ffcca18cf8c76f65b15193788f4df -dist/2026-08-30/cargo-beta-aarch64-pc-windows-msvc.tar.xz=faaa5028d993cfe8ad0c86b03e8ce2718bf20e8cee68d8185ecfa39cfa3870ad -dist/2026-08-30/cargo-beta-aarch64-unknown-freebsd.tar.gz=f9c7edc721b9e36377248325ec7944df39cf2ca005fb02a91a4994d717ad4783 -dist/2026-08-30/cargo-beta-aarch64-unknown-freebsd.tar.xz=581acbb17a497d6b76b99cc94833a33d72e104f2efff7d408d69550f912da462 -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=33647f90516de973cbfda8c553497ae5721e4412c4aecbdba1af4ff414093ca6 -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=9741da1d26464d27e5566220ac240ece0c94d95e0458e8e945c1d29cc198746b -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-musl.tar.gz=92e567bb8a7eeee6e001bd47b39263473d69a6591a9e64f9f48736a3ee631669 -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-musl.tar.xz=69bd4e038b62ca7a94d85b3673286fe9a2ff57d4fd750e35cc0f4edf2e74b701 -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-ohos.tar.gz=58627d33a59fcd84a33e71e121f267e675d78a181fdabd8bfd645b0c21e36c33 -dist/2026-08-30/cargo-beta-aarch64-unknown-linux-ohos.tar.xz=4dd725fb1d9eb9f7f1434edf563642dd4357b4622b7990ca835c62db9b26bf55 -dist/2026-08-30/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=86ca22788c633215cdd0ca96986136504dc7525c1d6d12da5d2d37944986ea21 -dist/2026-08-30/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=99f26d926f354f3a72fb422bcd8a2f0b8379ac727d5c3f16b57b433fe9f5d656 -dist/2026-08-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=681839287ba9bcccbff125e21f9b1381915ebf1e2748d558cf4ff1dcace861fe -dist/2026-08-30/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=cf1e4cb9ebb5c86ad2090a9f08862fc85ee00f0c0a4dce50df4e688112e2b3d7 -dist/2026-08-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=9cd65395b781a22ec66e2e49e78d5a972360c93b5da7ed22b837635c68899a0f -dist/2026-08-30/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=b3c6b3a99f537303f2419cf7379cbdbacb899a956ad0653b0726d558f893f481 -dist/2026-08-30/cargo-beta-i686-pc-windows-gnu.tar.gz=055b916329d7848a521f63cbe6c373a4ad94a36e9c2cefe155283bb67b2c655a -dist/2026-08-30/cargo-beta-i686-pc-windows-gnu.tar.xz=728142c61e80ed2884a41446fb5ef9784ae66c6a5ae01d34548ad3722bf17547 -dist/2026-08-30/cargo-beta-i686-pc-windows-msvc.tar.gz=902d87163289b5f7c8876d79b4bcf6a524f445007afb41478c3d446c47e8efd9 -dist/2026-08-30/cargo-beta-i686-pc-windows-msvc.tar.xz=f8c2377f283109ba8db1d15925ebf549a0297d33245d67efc2f178fbbc13a766 -dist/2026-08-30/cargo-beta-i686-unknown-linux-gnu.tar.gz=acb2edc9a1e93476848d22725017ca6c80906875cb3c3cd5f23972a9a96c109d -dist/2026-08-30/cargo-beta-i686-unknown-linux-gnu.tar.xz=6600fd8770b01333c808210c5fe794cac10f302e4d256d1c76d1ad3b86b2c63c -dist/2026-08-30/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=98b4d2d3c9684c4477cbab01edad84970f9bbef0032249800f48cb4aa6259eae -dist/2026-08-30/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=3ab812af126bc73f9da76ed94436b856b3a5b778a0594773217ede933c136e89 -dist/2026-08-30/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=d5058dc322f0f947bd5b8ac8644df85ff760797283d4cd62a08c6137fb1b31b8 -dist/2026-08-30/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=34dfe36b152df195bf161ebf151e7166096b8cf9581b8972b49b17cd9be6f101 -dist/2026-08-30/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=7402338613366b038279a45a2390a403fd7479cca7e38fae1614e3356b1ed17b -dist/2026-08-30/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=6637409067ce9667b02142a3866bacac5b378a7d3f4c1198ad63b8dd44e13683 -dist/2026-08-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=bef6d62721d7cb4a5e8d16b4ce8dd0b64100991ff86e4228ccfd2baef6bc1d13 -dist/2026-08-30/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=ab6ebfc224a8b5732b009ea5fcd082f6765ba92c1912b4507ad6b7020d366f31 -dist/2026-08-30/cargo-beta-powerpc64-unknown-linux-musl.tar.gz=07db627041a31120cb4c416ba8d8cd9497e496830568f06770aaf3bd2388cf89 -dist/2026-08-30/cargo-beta-powerpc64-unknown-linux-musl.tar.xz=c5438cb0e1df9c6dbfcb31d9b578d8421dffea54ce84fbb16619b57eaac22fac -dist/2026-08-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=9ec047abc63b03ade31cad80b0e3c247855ebbdeb42081f0e7d1cd0fa2d6a591 -dist/2026-08-30/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=59850205528f58ec1df682519b33d149dacfd34c6820188344166be741b6496a -dist/2026-08-30/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=b51d3d280d5c7db88697f5cf62a16bdf87debc3a36e169e1613b19c787684460 -dist/2026-08-30/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=42fed8ea76cdef7ef55cea3f5afa7b65bbbd0f64a7dd91c5128b4d0a459a1d61 -dist/2026-08-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=674a081bb7e9264aadd9877cd56e354023bacbd3d7645f47b5e56fd929b2893c -dist/2026-08-30/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=cad87b60d098bdc83f26039d2a7b01cecd72b454414423786e69d7830fbc2f11 -dist/2026-08-30/cargo-beta-riscv64gc-unknown-linux-musl.tar.gz=0020a7c5575ac0aed412219257ac4ed7af155ce4696382ee4a5b20113331b8e5 -dist/2026-08-30/cargo-beta-riscv64gc-unknown-linux-musl.tar.xz=ceb3b28ee22ad4b7e893583774680f5be45be9376fb56d23d48ac6201bc972e8 -dist/2026-08-30/cargo-beta-s390x-unknown-linux-gnu.tar.gz=59836d761c03a77477236199be5b0bd06d2ba5ab1d0f39176e1d7c8434eb45e2 -dist/2026-08-30/cargo-beta-s390x-unknown-linux-gnu.tar.xz=38dd22d489aecdf755bb667b4e79d2cb2ec8b6c2710d01686d600f1273e8d59e -dist/2026-08-30/cargo-beta-sparcv9-sun-solaris.tar.gz=c9df6b1cf54638837c2ab060d81241b1cc9c0fe415927c3df281a6c27a46fa5b -dist/2026-08-30/cargo-beta-sparcv9-sun-solaris.tar.xz=e1da5f2fc4dfa042c2819cc20ec8a7fe223aec9a3632899d83965b69c0742048 -dist/2026-08-30/cargo-beta-x86_64-apple-darwin.tar.gz=466f22d638541dfd8a067ae8b01d1d5ba3fe53e77191da3f3f676d4a90d88cca -dist/2026-08-30/cargo-beta-x86_64-apple-darwin.tar.xz=239a1222ddc7c24648f902799dfd258ae334a37f3f58675e94a62879fa51d302 -dist/2026-08-30/cargo-beta-x86_64-pc-solaris.tar.gz=7623f134d775dc42c669f1f23dbd22415036927efe13b183edfc303003d714e1 -dist/2026-08-30/cargo-beta-x86_64-pc-solaris.tar.xz=126bd01ff0c9bb942e211a8fdf6712199979c35d1b6b2b19bbd2a21fbbea966d -dist/2026-08-30/cargo-beta-x86_64-pc-windows-gnu.tar.gz=bfb4fedc712bceeaf74cf23245fd3efdd68728d77db8e04a32ddc329995bdd97 -dist/2026-08-30/cargo-beta-x86_64-pc-windows-gnu.tar.xz=b703ae1050c9a7ebb6b6ddb0523c59b2e5b38466716346e85e7c63c26588927b -dist/2026-08-30/cargo-beta-x86_64-pc-windows-gnullvm.tar.gz=562f4d368d2d854ac580e07738411afb563373e247514e944bcd98f9967319ae -dist/2026-08-30/cargo-beta-x86_64-pc-windows-gnullvm.tar.xz=f165e4bfef2e6bafeb4825961c0fc41ac7ac23d7457feb444dfb8c1e1e0d012c -dist/2026-08-30/cargo-beta-x86_64-pc-windows-msvc.tar.gz=9a3c7ad87e5f3b98d02167c449437c0aba21d174a6ecfa2f0e4817b8c93ad91c -dist/2026-08-30/cargo-beta-x86_64-pc-windows-msvc.tar.xz=831c421d5c5d187047920ccf7ce76300f4d9e3a36960e347d179f31b08f9b49f -dist/2026-08-30/cargo-beta-x86_64-unknown-freebsd.tar.gz=3dd99be35b587a0334d71bc92dfe15e06ff0a052d66782a2425895684dcfe669 -dist/2026-08-30/cargo-beta-x86_64-unknown-freebsd.tar.xz=e4220bc3ccfb034fb1b40d506c9a9637153c943e0a0f9dea4bd56065df2698cd -dist/2026-08-30/cargo-beta-x86_64-unknown-illumos.tar.gz=98de23e890441294de89857063f2810f81df29c02cb9da755793f78eaa8ca8fd -dist/2026-08-30/cargo-beta-x86_64-unknown-illumos.tar.xz=9dbc424c16bed26b8d2ea662c41f156ef14636cbc2006c36af151ea68c932551 -dist/2026-08-30/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=2d2cdc1af3afe2816da895ed1ef0f27a31ee31f938a9385864c0c8e1385a2ec9 -dist/2026-08-30/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=62bcbf31738317455017be5dadb592ce9a6b937bf61303c30c56d4f6d8f1ac3c -dist/2026-08-30/cargo-beta-x86_64-unknown-linux-musl.tar.gz=32247e6fb942d39444cab2b35ce2b64a44c84b2fa934acb781ea9c682f60f14b -dist/2026-08-30/cargo-beta-x86_64-unknown-linux-musl.tar.xz=8c155d690af2600d9a4dcf00d62b6a5f52524e999d25d02eb873a6ab28f373e5 -dist/2026-08-30/cargo-beta-x86_64-unknown-netbsd.tar.gz=c588c5407c06a36da78587b6ee7baddc72b45ecb6fac9290e333fd0eadab1152 -dist/2026-08-30/cargo-beta-x86_64-unknown-netbsd.tar.xz=09c84a0118c5d533b442f39c33265a04abb72133c94f662654095f984f0e85e8 -dist/2026-08-30/clippy-beta-aarch64-apple-darwin.tar.gz=cc03b3970d8e2f5b055fab29f46e9120fdd520f6db45a6213a699a9a4367997e -dist/2026-08-30/clippy-beta-aarch64-apple-darwin.tar.xz=7c6c789f64225fdc45aad2c8eb596aa679e855abb5c4d79573a458f2da7309ac -dist/2026-08-30/clippy-beta-aarch64-pc-windows-gnullvm.tar.gz=b404caee9abf7e945985ccd5379f0e2f41c3b7dbe6e999d722b55fdf9d08c6ac -dist/2026-08-30/clippy-beta-aarch64-pc-windows-gnullvm.tar.xz=36c9f84de6b071aa5f1c0bae438ae3ef132c4add9d35ee5a69e8a754501b568e -dist/2026-08-30/clippy-beta-aarch64-pc-windows-msvc.tar.gz=bebf9f956d1974779ab06d7bdd25a7ea053811523ba2ff4ae18267bad7c80494 -dist/2026-08-30/clippy-beta-aarch64-pc-windows-msvc.tar.xz=fb4274e7618fe49031cb6f4021a0e7dc4bf1ee8900eb45cef118600c8137ad4f -dist/2026-08-30/clippy-beta-aarch64-unknown-freebsd.tar.gz=79e922d0c5bbd69c86d7a459552e47511481eb5faee8a7a2eb893ccc5f7b6788 -dist/2026-08-30/clippy-beta-aarch64-unknown-freebsd.tar.xz=ed65f1ac492dafebfae2ee367135e1f56f57af9b2d284739fa57b18793e7386a -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=d4aa6c22318d181ff4ef17f0ef2b8aea6641efac232f8a074cf4948e76c68802 -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=1d679549e6cb70f5acac81d255aabfbb6afef0c94973747e791f27e1097dfb8a -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-musl.tar.gz=0fecf358ff0e7725ec6df42b194a1912b91b358aad683fc48d36b1768c88042f -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-musl.tar.xz=443cb8a078231aa3bba0b8082cd5f20ce36caee120d1060e8f3cf73fd05d8907 -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-ohos.tar.gz=f8b624585864c6bd679db4d505b8c84d46682b8cccb29fcd5bc5fcc74c7a79e7 -dist/2026-08-30/clippy-beta-aarch64-unknown-linux-ohos.tar.xz=8e09d294c73ff186be62d2db49a06240b6d66c674c81c2471646222a5d607e01 -dist/2026-08-30/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=106efc64c2e21abc149264e3a98c4b836c1430d0240f3489d5605a2cc17760fb -dist/2026-08-30/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=b45eaa6f6586aca7e622c5ad60ae9ec92ddd935dff5d6c94ba3a78e0dc6dc304 -dist/2026-08-30/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=8bb3d211d9d17c5acb2867cd154f3dcecdbfb36d723c05f35d91f2e33ea00067 -dist/2026-08-30/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=08c78ecc4b5489c5480fe6d3832298686f782f9e45bb265946b9bb1176733f54 -dist/2026-08-30/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=1875b1f3c267c634cd48933c98891a53b350f7142462cb56bfc6513326024c89 -dist/2026-08-30/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=a647ca6600707b40a1e97f7fd0e39bf43c863ea60224eb28beee0622f74253e3 -dist/2026-08-30/clippy-beta-i686-pc-windows-gnu.tar.gz=772d98712f108d6d7eb7730e26ec04e66a972daf3ac5352c30160e20c1861ba6 -dist/2026-08-30/clippy-beta-i686-pc-windows-gnu.tar.xz=d75cdb626c3104552b122e79d2ed07bad9ec04f084f58bde332d029feb3ae90d -dist/2026-08-30/clippy-beta-i686-pc-windows-msvc.tar.gz=e7ecdd93739741d769a1fb4ea33b9dd3c935008d7ad5e773d3673d5ea7dbd6d6 -dist/2026-08-30/clippy-beta-i686-pc-windows-msvc.tar.xz=8b1223c943d378e201e83d61298527e2d7307f96ce609c6e1a5483f086490bec -dist/2026-08-30/clippy-beta-i686-unknown-linux-gnu.tar.gz=f326afa8e228964581df0c4a0096eb33fc132df0254b2648f43f6589466e72bd -dist/2026-08-30/clippy-beta-i686-unknown-linux-gnu.tar.xz=7e868c12873c5e451ebdfe67e4474538a9d3f46d5dde8ad4139c8f5056a44685 -dist/2026-08-30/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=e185f345c34e54bc100b1df955c047b53db30b9b3b054a2cf5a264f0e3ae2405 -dist/2026-08-30/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=270c4f7d7763180bfb8a7dea1d97259398c9b7c6560fdd3b58192748ffb40cf2 -dist/2026-08-30/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=22d484c3ae2ade651e12ce943780b51da3b0dd6bf04c6f8403540cc7f382ced0 -dist/2026-08-30/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=a669d05d6efc4e77f05b417d00272f2a0221e05b37f921b9e0f9769a8b48830e -dist/2026-08-30/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=3d782e904a64856dcae5de5d2be509f2ccc3109e9067ddd540bc8e1049ea3ceb -dist/2026-08-30/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=dd867a9fca45df5ee0d3ef602802f8accaf9fcc1ab1fe52b74ea72e03b91d67f -dist/2026-08-30/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=a890aa398977d62b10513350e2c918fb41ffa76a2733b2f08ec829f15b8dfd0d -dist/2026-08-30/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=c8ae48e109ae2f4daf3c878056641acacc457618afe42c9af53eaa4bf9a4faff -dist/2026-08-30/clippy-beta-powerpc64-unknown-linux-musl.tar.gz=010d6114089273e267645340437d74b962c7f16ad21914b689100241e1e5879d -dist/2026-08-30/clippy-beta-powerpc64-unknown-linux-musl.tar.xz=1ff705f8d502081d85e8f85a177b4d00a3f102475c6148f7609040efe8f95cf0 -dist/2026-08-30/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=226cdb2a14e6f7ac8962326d6f0a4459a99d5f43ed6516f296da74a4c96504e5 -dist/2026-08-30/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=6f0d5341554b0b12be7138962ad1f02cf534b197923f791e8489e09c2ec0fa31 -dist/2026-08-30/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=aa41e1b12199dbe2597c1614908911bc936b77e4697d6f47a73e99b3fc6d3cbb -dist/2026-08-30/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=f0084a572996014050b886ea7defe6c6f3dbb8055c840c9f3e0f09474f1cd87e -dist/2026-08-30/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=35d0c03ff88bbc60059f1014c65f8803a5e649fcef0ffecf90c73db0b5e29d04 -dist/2026-08-30/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=f2233e50c2c976941b30f41859494c3b47a4a92022b50f924eb3aafbb10ad1c6 -dist/2026-08-30/clippy-beta-riscv64gc-unknown-linux-musl.tar.gz=8f34275dea87439be7c820cf5c239168c5641711e439afe873615ebc26e92f20 -dist/2026-08-30/clippy-beta-riscv64gc-unknown-linux-musl.tar.xz=7346c56c1ff8cadbb633d0890dfea12918344f035075a5ade3fb44869da7ce26 -dist/2026-08-30/clippy-beta-s390x-unknown-linux-gnu.tar.gz=064c99e94f0dd2da50e8445cba0f6bd3b6de9a78f860fde838097f26f93c0a86 -dist/2026-08-30/clippy-beta-s390x-unknown-linux-gnu.tar.xz=b5237ae854270214b81270f1a6dcd26fab19470b98450b8503a1647d83f19d66 -dist/2026-08-30/clippy-beta-sparcv9-sun-solaris.tar.gz=e8cb900135fcaecc87565e6279f3b50db957370b73f7bdaee39401bb2236ec93 -dist/2026-08-30/clippy-beta-sparcv9-sun-solaris.tar.xz=a1315c1d6b3ab19a6351527f07d62bc375d937571af49f1130b030440f96ad74 -dist/2026-08-30/clippy-beta-x86_64-apple-darwin.tar.gz=4adb22b7d502339fa505fe7ecf18167fd7a054e15211d28f78d7f27c05fcfb4c -dist/2026-08-30/clippy-beta-x86_64-apple-darwin.tar.xz=0e9c5bd310a8c6d797cc741a3368c4e18ebdd138fb0035bcec94ca3563fee966 -dist/2026-08-30/clippy-beta-x86_64-pc-solaris.tar.gz=ec8ea5558cd47e0324ab46fc8d7f06b55e3a5b015e1b06f7d8372ef63846e2e5 -dist/2026-08-30/clippy-beta-x86_64-pc-solaris.tar.xz=2ce6978bb89c20fd4d92d9a513c60ed8a4ecf243d68e9ed5e76a06f46374725c -dist/2026-08-30/clippy-beta-x86_64-pc-windows-gnu.tar.gz=269d4722bf8604755727de19c3e92932976797ee07a382a4241d598e11f1dcc3 -dist/2026-08-30/clippy-beta-x86_64-pc-windows-gnu.tar.xz=bd37185b9ea6c75df3fa873bb7bb961ea48cd7eb2e1e537df78fa23560a4e542 -dist/2026-08-30/clippy-beta-x86_64-pc-windows-gnullvm.tar.gz=7a84636be94207fe6bad2a162bb9f412944f07d87e65aaea8defa01500be420d -dist/2026-08-30/clippy-beta-x86_64-pc-windows-gnullvm.tar.xz=6f3cd9590fde49d3d32473d7363b8bd9e1298adb87dbef2fc8ba2aa6565cf7f8 -dist/2026-08-30/clippy-beta-x86_64-pc-windows-msvc.tar.gz=9d33b21d67155a006f8ba2de17892812519ce9ddbb6531656b314c710363f7d1 -dist/2026-08-30/clippy-beta-x86_64-pc-windows-msvc.tar.xz=a6805eaf9f9d0d5d9f98d6fafb4b4e96accfb2676acca907ee704f84745c5768 -dist/2026-08-30/clippy-beta-x86_64-unknown-freebsd.tar.gz=b8e66bc833089b1b23cd0e73c2e1b3409864d2b00c7ba533378b45eba07a8dc9 -dist/2026-08-30/clippy-beta-x86_64-unknown-freebsd.tar.xz=593633c48f833329e86613601cbb4db25071eb19b33a4561f7104c0cba86f03a -dist/2026-08-30/clippy-beta-x86_64-unknown-illumos.tar.gz=dbfa333d2cf958b0d39983bdf3fd2d55623903d82f34d70d06ad31561f51cf97 -dist/2026-08-30/clippy-beta-x86_64-unknown-illumos.tar.xz=53a0ec434ba0664dcd967d02a13daab11c23eb294b3e80befb80667f8983c586 -dist/2026-08-30/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=17a88086e382454d70bf08e33149b8e0ba97a34500b9f56dbbfd9ff4c3fc535d -dist/2026-08-30/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=b0237d0782a9b8938769e85dbbcf1a6eec91554f665b90acf00a60f4dd0714bf -dist/2026-08-30/clippy-beta-x86_64-unknown-linux-musl.tar.gz=2d7ff9aa37dbcfdec585dea69555c973430b7e6f4f6b55e450cb34c05b59baef -dist/2026-08-30/clippy-beta-x86_64-unknown-linux-musl.tar.xz=9ae39943b49d89ef53153b2921fe7dd6ed244acd5e39297ba7cf108c38ec644b -dist/2026-08-30/clippy-beta-x86_64-unknown-netbsd.tar.gz=7c8c9387e3f75a917dd721cf96a118cd8924baae1b476e9da545aa6c4cf06609 -dist/2026-08-30/clippy-beta-x86_64-unknown-netbsd.tar.xz=0d85f1338a69ad620c923bec29c3fcad6225f957578f0a41a11568c154e091aa -dist/2026-08-30/rust-beta-aarch64-pc-windows-gnullvm.msi=99a2ea82e19f436cdf4dec0f0aaf315c16a3229fb6d9b103ee9d1a2c06b74090 -dist/2026-08-30/rust-beta-aarch64-pc-windows-msvc.msi=c0a27c16075e29239e68b31d76946a41a452acce1140c1e509a189c2e3f56eff -dist/2026-08-30/rust-beta-i686-pc-windows-gnu.msi=8f742fd4920a3fcf5d41dc113f885e441f8681d83a745a5b12195c2782a4c93b -dist/2026-08-30/rust-beta-i686-pc-windows-msvc.msi=513fb7fe5d4289ddbb58260863ba3821d2cb2a3baabc0bea1a65ef2885c413ec -dist/2026-08-30/rust-beta-x86_64-pc-windows-gnu.msi=2d9f279983d1a50913e7777de880899143190413292801266b95ac2ed69a4e4e -dist/2026-08-30/rust-beta-x86_64-pc-windows-gnullvm.msi=5bf8e7568a27395a4b879dd6534c141a92cdf12536d1201a175d84453963699b -dist/2026-08-30/rust-beta-x86_64-pc-windows-msvc.msi=23463fbf570caf314427b3ff8e666a2d9b3cfdf7947aced459187eb59c645e48 -dist/2026-08-30/rust-beta-aarch64-apple-darwin.pkg=e933472ceac42d94982728bedda2976bc77da11805a236cd93cab0c159dafe5e -dist/2026-08-30/rust-beta-x86_64-apple-darwin.pkg=bb9d97c74eb28bae220ed548e46b91c478d66301801c51d4d170d45989d24cc1 -dist/2026-08-30/rustc-beta-src.tar.gz=baa6964c75882e0393efbed2f19e8303b46101336adfdf44bede282dae15ef0d -dist/2026-08-30/rustc-beta-src.tar.xz=f835b92620f3802afdaa41fa49de6e253c9db0de0234070833011ce65c14d0e2 -dist/2026-08-30/rustfmt-nightly-aarch64-apple-darwin.tar.gz=22d6733e4325fe6fa25399b651e77cd5ed1a7f370f7558aaa08e8b6447f55264 -dist/2026-08-30/rustfmt-nightly-aarch64-apple-darwin.tar.xz=fcc49f0698c09f8ff89ca044d0426dad2399da253d287c3aaabebf103b4a2820 -dist/2026-08-30/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=34a0e1f6d068d30cca9099c44736657de307ea3041970fde751aeda3781d02f7 -dist/2026-08-30/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=8f7955c05e2a5324fba961df617ca2d70d473565cd3389fcd52814e9cd5c4f65 -dist/2026-08-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=7df7e3f128e4d4f88a5777e9e736fce117f5f47ef8cb505713aba9db09b8cecc -dist/2026-08-30/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=094323c8a19c6840d13d9e3a1668c94dc249ff0c720634da1fef8cf844cded71 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-freebsd.tar.gz=bd932f456a46de862f1aa3fc5b936a5e364a714a6cb8b71c7cf3920f180177a0 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-freebsd.tar.xz=4c14e353f8f5982ba3b3828578e412f433ca3f16e94c9aa0f6efdf2949b53215 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=efb14d13c092a4dfd1d2229aaf850cb2e6c56bac9c31ec322e22f515050567da -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=7df63718528c050a0e306ab08979ca787b6f0522a442d34355cf683f3bb259f0 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=b0a231d0eb6bb006bfc144a954be07ed9886202967843b0e8475b19429902884 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=b98a8ba107231b4d8832d6f1cb679661e9ee0faf13c81dc3eaa576853580582c -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.gz=dec01a69341b8d512eb17ec28687b4ee43174de63e31a90b91e99b9eaf17e345 -dist/2026-08-30/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.xz=e598a9559c169794bec2443e7842e62728e09fcaa6614b1a3f5ebd6803f0ef6a -dist/2026-08-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=18a5a8ca79e449f7daf52f534cd2ab137e33204280ac7da35e0bd31f6ba2674e -dist/2026-08-30/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=00e6e3d4d555ee786545b5f0a542d7b5bb9260781a80e4598d50bdf856457a4a -dist/2026-08-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=421735da37fcf7a85c2bccb27b13c15105f98a95333734c1d383e18b7a01842c -dist/2026-08-30/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=a3936b0c6a67da7180c10554dbe6427beaf05480c40b3a57cc07082085987cc1 -dist/2026-08-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=817768d8aae4d3d09b952631982051eba84b889e87367c2d740a14e35261fb4f -dist/2026-08-30/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=5d905fdbcc0d3d2f5949c0e32980172fa8216a51974945248e293f8c81b58203 -dist/2026-08-30/rustfmt-nightly-i686-pc-windows-msvc.tar.gz=e2cae9d3e6b6c6cf72bf0e12510358984adb5f5279f49af8f4a29869614f0a84 -dist/2026-08-30/rustfmt-nightly-i686-pc-windows-msvc.tar.xz=bfb5472037dd5d1031384c70d58bf841ff4a9e33716b55d8384c47d27a31ac04 -dist/2026-08-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=b18fa3d4a5469b7736655c842af84ad44a07fbd6146669c6f2b5f5c3f26a4e33 -dist/2026-08-30/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=c7978ac60291efc21bc77c2aed4d14c0bbfd6dbccb461f0499202fe8b8dd0818 -dist/2026-08-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=e1e69785fadaa294f92d7f5e42b046a47c4b508a806804048c3c2b1cfcda25d1 -dist/2026-08-30/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=c6371931d1bbc56f94f17d55ef0e8a756388606599a6f8828b1269504b57f0ac -dist/2026-08-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=e2763a910eb0305fbad6200fdb70e21c80f6ce61a29c9ef6cfdd134e54fa149e -dist/2026-08-30/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=b8ff26519a2b6087969497e02e1a958b283b2dbd5741c5f9a531bfadb7f55b4e -dist/2026-08-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=f83eba99f2c4ca3c8e72debd3abfc81c4e8e12b78f33030a2ec0bca467ff1026 -dist/2026-08-30/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=9da6df6e5b98e59dad134fa7eb6fc74cdd7590799e5d77b885675d3301cb5ae5 -dist/2026-08-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=ab48c3b5e6a1c920d2776ada7f2c7a262c6456c70c4051c55f24067768f36011 -dist/2026-08-30/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=d6a6ff842d3004c14a39349c62453b5279085bcf44f2c3f101bba074249b6393 -dist/2026-08-30/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.gz=7790a116d7598a29c083e8defa140b3c69dff2fa8632abe16c0814e3fdceb771 -dist/2026-08-30/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.xz=090ff92dbd36a9d051e48545672099c40917f5cc781fad0075d1db73bacc9b6b -dist/2026-08-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=6a448b720e8b8904a7f6b160891dc711165b043aa2f2700f1001220841da7383 -dist/2026-08-30/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=47850b2456b8f28493268987e10ee2197f6bc49517b9338c469346e42c4ea524 -dist/2026-08-30/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=51fa8c6d2e9144b5086ebcd91580a7b2338e42294a0db614c2a5b40c2817f074 -dist/2026-08-30/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=09af68ab10528ac45be29d2d7671a5cbbd0c508d842c811448d1b1a0818e4ebe -dist/2026-08-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=4ba0481a7d6111f1197c44f9475ccfe814a32cd13ff218b7a6f96fa6b188dc07 -dist/2026-08-30/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=cb078f0a92905a6ce410866e2c0f93ecdc12fc2b17716e8ab503531b72cd2f41 -dist/2026-08-30/rustfmt-nightly-riscv64gc-unknown-linux-musl.tar.gz=5c8f989fc890a8d40b88d03002819dba392def655ff4a297eae83e24635599be -dist/2026-08-30/rustfmt-nightly-riscv64gc-unknown-linux-musl.tar.xz=ac6a2d15f43100e71a401f334eadc59d76e554fc7e2e4c67870c24f05c7ac682 -dist/2026-08-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=78f43dc32a140e6b84c5b50e319b5d779d8d3a6a63172df5b0a7df984cda2919 -dist/2026-08-30/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=cdc738d4e7db3489ec4be89db19fb6beeefedc09f0f99bfc3f4177e5a0e29e39 -dist/2026-08-30/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=8b04309e8d8ed92f52ee9656b0c3b694681c9c867bbadb781c14df8d2f25a189 -dist/2026-08-30/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=fa880983d380d71b52468551aeea00502c04a1c84c1976b82ad137031b63e61e -dist/2026-08-30/rustfmt-nightly-x86_64-apple-darwin.tar.gz=0faa8f222a300d58a8d815a49625202da2c93b89d655de9f8105fac8fa3b49c2 -dist/2026-08-30/rustfmt-nightly-x86_64-apple-darwin.tar.xz=860418646c51c8a4309b5f64700e9cddbaad55edd33776bce10341d069a4842b -dist/2026-08-30/rustfmt-nightly-x86_64-pc-solaris.tar.gz=70dd11166440c56c5d39ad393f22904b0d043c4e128ceed9b35276b1f7c88814 -dist/2026-08-30/rustfmt-nightly-x86_64-pc-solaris.tar.xz=0c0224c46c41018eee3fd6373a3a50869faca604acf5985627a43d381bd023bc -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=e3ae658cd8daf76fba66422c5b63d335a73c6d1abd0b0f6b88c385467779f876 -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=372750b8dca20904cc7716f6c999a581ecbf67537bbc1a340226cc4d1cf5f01f -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=3edebbe5ca7cc0e9cdac3dbd715caea022c890f2e16dc0798f8517c324dccc8b -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=bb6cb837ef4e0355b946a9e8af2d8a4e9a89e06f68f6a0f92adfdf56eef1d583 -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=7b5a4c70a3223e4987e216f9853833c87d347c5e4daf6328eda4f2e434e3dcc8 -dist/2026-08-30/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=4040814b80224dd9ee4ad051a491c5c7cb345ed41c2bce1070c13faf785cffb9 -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=529dcbadb35869dd2dd39e4b81929dcd5fc74d983e5544b61e66a663dfc40fda -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=20c86d4a327b5b227dddd1d9a900f5314f25728b5f1cbbf970d7a8bf2c8b039c -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=b6951008db1f2b95e35dd207bdf95040bb0bc6875a710a744d81a9769e24f91d -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=c502feb9fb19f971450201f5d396d9e622169884ab2fa42b14ca4685e2ec485e -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=76acd957f09291ee38b993aea1511d7ed4247fedeed07b90368efdd4cd216e3a -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=5a9b8925bfbe5c244e6f1c84ca821bad2227ec374db11f0d593830f2419742c8 -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=da93547e78b5b8d587e35d15df2eb789ad4f075bb82d4605b5f4abe49b7fe49d -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=688e31843695905b5e67b2a186fa4e509c860befc70ee533195710f784787b64 -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=229cd762e308882adbfaee3c50e1a32bf88a3e1c488ab9998558a90716340a45 -dist/2026-08-30/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=47e7a7cf0eebb9c62185e5506ff1aef012709b36c7433181d774b8cd1a75567c -dist/2026-08-30/rustc-nightly-aarch64-apple-darwin.tar.gz=25ffe92502f44e574a72b9493ee0b1a4e0e873c1c931f1a07aa0e478ceb170e1 -dist/2026-08-30/rustc-nightly-aarch64-apple-darwin.tar.xz=9d494a6b72761dee6ec3c0ec085d5b29838565ef45bbb67b097caf0aa4750304 -dist/2026-08-30/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=576b8ba2a8aab889df0e673d434402c38d22efcaa4a8cd2f005c01063cd80601 -dist/2026-08-30/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=dbd428ee786b17c9a91039a2274e01d1adf14d6af747f78c32d68a62a5752e35 -dist/2026-08-30/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=395f1fd4b0286f70d4d48d5b1aae4a8f7ceb0e0a916fdfb69cbe2c00a1cd31c6 -dist/2026-08-30/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=33fbd7251609d17dcedff1de1d6b34e5aa257411229e9e7c0066d51b3b22d23c -dist/2026-08-30/rustc-nightly-aarch64-unknown-freebsd.tar.gz=954f471480070c222a6316e1646770b6472c007b89f68ea61a713b153210b960 -dist/2026-08-30/rustc-nightly-aarch64-unknown-freebsd.tar.xz=9f19a67717d4710b3e445fbe84591da5fc5be7b6c6f07e5e5bbcf978243c4070 -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=d1cdfc3cbcb3f131b4307b83389da6c0385f733ef6c68e569f280c1d10bc6a18 -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=c967d3a8cf286f5197759160f90f823eb82c0dcfbdae4e43580c4e4336fee294 -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=667e1683c157443a221f00467c927651756a593f5bec5f438b55aaadd740dd27 -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=e4680cff6ef155809ede44b4c4a5f23ade8f920fd54e877ed93b6166010930cb -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-ohos.tar.gz=fd6c0c4450fe0b8f586452046c80b424935c1fa83181358c70c19b25ddb0dbed -dist/2026-08-30/rustc-nightly-aarch64-unknown-linux-ohos.tar.xz=b2c7e0cf7f1b71e141b248e62b7d10f0999f48fffcd6dc07318c3205c79ca505 -dist/2026-08-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=df20767bfd43a0fd4c5665ab4c0d0f0511b3356918f54b7c3074f6a1b7298aad -dist/2026-08-30/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=c43366c230813ae776aa094e3422a445b4a3d513f98ba6d7b78cb5ad2d0a2a8e -dist/2026-08-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=0c0c872b14aa8dc461989326b53c2692b46bc24bb8125d4f90e5b977f5db3bcc -dist/2026-08-30/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=82e0eceb946f0a69f2d766c3fe2a5467852caddff960a66c5fcf9d14fa6daf92 -dist/2026-08-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=4783a2cc2a99596fd187bad7f486f97018ffce918c34b4b022fd88f27053c967 -dist/2026-08-30/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=c078badef6ab76e69f0fcbe6ca76f1037cb64d67e5a1feecee898ef6aca91521 -dist/2026-08-30/rustc-nightly-i686-pc-windows-msvc.tar.gz=340b68ba0802676c99da1784b0f03eb9e3cd7f78cf40fa579f97601c07dacb24 -dist/2026-08-30/rustc-nightly-i686-pc-windows-msvc.tar.xz=ac4c0562021b4f3076b39856eb16ab288f3d16d25c557cf954ce66f389449f9e -dist/2026-08-30/rustc-nightly-i686-unknown-linux-gnu.tar.gz=5ac857921af0b1b8d290a059eeb1d510ad4cc5f450b513b26a11be67885558ee -dist/2026-08-30/rustc-nightly-i686-unknown-linux-gnu.tar.xz=a01fb1c1721998e3bffe377a15663e911bcaaf497fc2a7f1dbef06125466febd -dist/2026-08-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=46d1aa393ee0f736bf46cb6d8e975e66774a797a78918fc106cb1baf2115c1ee -dist/2026-08-30/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=66ea19498d78291393f20ad6313fdb2359b7a685bb358d28c498042f957b7ce9 -dist/2026-08-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=27e138e7e0ecff208f09780f6cb51d4447fb75b5891c2e961c3b380670bf43e2 -dist/2026-08-30/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=16bade7c4f0644f4474622591f1ae83be1c7d6ad86aa23f1cd0bc29959e41555 -dist/2026-08-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=44207e156b7d05f8ffd05394cd0a5f2c4cf290e8a7d4be07a95e6242be738f85 -dist/2026-08-30/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=98c9309ccd0bc473ab1c373232c0ad483ce959a9b7b31cfc0b948c0dcff4ae55 -dist/2026-08-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=bcaf935990ad326f9469b18514330bb219fac62773b1ca44cfd9f2639e22442e -dist/2026-08-30/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=68242588d61346c4001c4bade2daec0611f3f079fe1d1e5debf08746d8ca2217 -dist/2026-08-30/rustc-nightly-powerpc64-unknown-linux-musl.tar.gz=34e4d626d1e484c3d8bbe2be39a6324b0a02cfc60b7bf13c561e6c41eb6b3917 -dist/2026-08-30/rustc-nightly-powerpc64-unknown-linux-musl.tar.xz=8b35dd518df6b7225dc7b8da30ef9fce97181bf3781e69fbd5fca67833c54457 -dist/2026-08-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=66aca4805b3450a90bde12ddf6f2b9139fcab333bf4a33825d9bedf3842fccaa -dist/2026-08-30/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=6861be8d2ca2fe398e461ec1d68eb4b6e5a589b5eb39b60ca4083579a54ccc07 -dist/2026-08-30/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=7644e739c1afbe9a7be15878444e56340dbadea64f06799066e8d14c1e736ebf -dist/2026-08-30/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=fe4e05894da7fb3bff0d4cc725e0e80dc78fa55d97bbb0588ce5383fdec72407 -dist/2026-08-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=e59bb87d54ca41779b984fad84ad20144e4bb224ca187ca6a51ee1d15ec5bff4 -dist/2026-08-30/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=d997aa633692996dac26f68a246b3dff4a597595a08808dd965e01f05bc502b6 -dist/2026-08-30/rustc-nightly-riscv64gc-unknown-linux-musl.tar.gz=3d5692e095f9b23a05aa57b1de83fee4a6ab9ba1ba85f0d6a7a59997814f762c -dist/2026-08-30/rustc-nightly-riscv64gc-unknown-linux-musl.tar.xz=85b6a0d7e0405537ef929819b957a37723010e8cefa82c558a7d0c42e645fa59 -dist/2026-08-30/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=668c203cfeed5b0286a5928d9b98e289f0ec32fbaf21fe61534ac9bb5c9236fb -dist/2026-08-30/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=8fd2005a2f7233db1399af86d9c8b48b959b3627faa5c8a3dde1d6db67f72562 -dist/2026-08-30/rustc-nightly-sparcv9-sun-solaris.tar.gz=d8767b7abc10f45dcc53258adf4ca2c062d3f063f830791b6c475537a7009704 -dist/2026-08-30/rustc-nightly-sparcv9-sun-solaris.tar.xz=58ed2a29ed983d6dc632ea7dd68532fef902dbc44a68e2cd668323fa9676438d -dist/2026-08-30/rustc-nightly-x86_64-apple-darwin.tar.gz=27bd68fc60a35b8f56b538cfe9d3cafe156dba2b8cb25bc04d488505882157b6 -dist/2026-08-30/rustc-nightly-x86_64-apple-darwin.tar.xz=a452c953f1641c6d2ffaf59d129f38b7fa2c6f8c29882c3d82408b50e4c4c95e -dist/2026-08-30/rustc-nightly-x86_64-pc-solaris.tar.gz=c12868cc994812742945591b906f761f9a5ca0d09a809da69f3b0f7de731a707 -dist/2026-08-30/rustc-nightly-x86_64-pc-solaris.tar.xz=9974a6f3bf2b784771114ae846f7fb54746525e5dd921f4832410e40a00502b3 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=6ce5a31fd706d532679c5db6bfca375fb21f34df077bd7e182f6e38cfb852561 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=72cb129e77c6c8f48e82a82d894a5fdced57d74c8a7ade88589c3baf1385ef26 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=e896320dd35b2b43943a29491bacfc696d5e68c3c9a7c0a4fbab6cc57ca5afe7 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=93b8fcf4ed8aaa3a9ad1ed14086ed4bf44cc38db920f86eef0c1f42da37c9665 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=5368d930648a6f04b20967d6183e53925bb930d047271b3683cf3d663d893f23 -dist/2026-08-30/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=e696551fc4f4b0573c60750826ee93113a95a4ee7361af3752e49c5a386abf69 -dist/2026-08-30/rustc-nightly-x86_64-unknown-freebsd.tar.gz=c2ef207e1ebd2c408c91a63cffd5986ae01cf265e535947d12bc43a2015eae5f -dist/2026-08-30/rustc-nightly-x86_64-unknown-freebsd.tar.xz=5025d42e80e6d377a9dba466ef3e81ab817ff6e098c2bbde4923afedf0fd7893 -dist/2026-08-30/rustc-nightly-x86_64-unknown-illumos.tar.gz=876fbafdf17e645e870d4b6afcd5465ee155e910309cc91bad10dc885d178b0a -dist/2026-08-30/rustc-nightly-x86_64-unknown-illumos.tar.xz=f380f5b0a7ec8c537b8bd53528b3a407cd69449baf0d6c513f03c2de047ba3fd -dist/2026-08-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=4e010b6ff2f3923b31c44cfcd74d33389dd2de01521e4f22b90c58294fa490fa -dist/2026-08-30/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=d87f9b9bc000e028ce81b49d64352c59eccc99cbf282c9c3bc834a72d9aeaff1 -dist/2026-08-30/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=2332302e83712fa814b119bea274fdb1f70494fc7e8ea6a23c88f20bac3ac6fe -dist/2026-08-30/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=2a43c8666489856bf8ce91729c2eeceb88a3d38bc6cacccc8c598373afad1247 -dist/2026-08-30/rustc-nightly-x86_64-unknown-netbsd.tar.gz=094c2005eef2f8ca0e466da77af70f7b1cc6c837e8b2e933c26d66b8bee3e06d -dist/2026-08-30/rustc-nightly-x86_64-unknown-netbsd.tar.xz=a68f04797c3ae9db0e31d9670fa9ce17efd5ca3054bdc4de06ca97b143cb59f3 -dist/2026-08-30/rust-nightly-aarch64-pc-windows-gnullvm.msi=4334c750cc57337150cf11dad2b10c5d65f1866e7f672093550322fa696d888f -dist/2026-08-30/rust-nightly-aarch64-pc-windows-msvc.msi=b2c56f022de67eb6045b1137709a5055c139d88e9fae8175b932a7da1f2fc1d7 -dist/2026-08-30/rust-nightly-i686-pc-windows-msvc.msi=bb18feb2dfdd9495289b70a6bb41584489dfe14de19961fe32fe6d249ff60c7a -dist/2026-08-30/rust-nightly-x86_64-pc-windows-gnu.msi=18d50140987657604cbf1a980b2249243afc6a734f725475a25a3f96c0edf72c -dist/2026-08-30/rust-nightly-x86_64-pc-windows-gnullvm.msi=83cb268a0ee1c120357082f9711d2a5eb05e58d433bd52dabfabfcbb31df6200 -dist/2026-08-30/rust-nightly-x86_64-pc-windows-msvc.msi=b19b6e4ef4b022f183c45ebba60ea8b6bcbcb06c60345231fc602dc1aae0ba5a -dist/2026-08-30/rust-nightly-aarch64-apple-darwin.pkg=2fa1f66fd223a57405047c498614d71fd3bf087a98063e2f652c9899d2a5960a -dist/2026-08-30/rust-nightly-x86_64-apple-darwin.pkg=20a2d983a8ef414f2c61773f056bed1d300c24e5f65252c1a0b01fc230030e28 -dist/2026-08-30/rustc-nightly-src.tar.gz=a1768b2d3627caf5f7fbdf5918fc1586180a7a2f2076403d1cb4ab11ea3eaec6 -dist/2026-08-30/rustc-nightly-src.tar.xz=b03a014a5a4f8bb1d0fb14d9f01e3a5cb9df64c4d4208463f4a6b977d2287d9e +dist/2026-09-29/rustc-beta-aarch64-apple-darwin.tar.gz=08cb5170859d6ebf335c279df46cd8421e6478a0199d0cd2709c0afbe8a92dc2 +dist/2026-09-29/rustc-beta-aarch64-apple-darwin.tar.xz=5ec30352066404071c4c9a077e19b211e1e2865babec422c1b5305882fccb2f8 +dist/2026-09-29/rustc-beta-aarch64-pc-windows-gnullvm.tar.gz=24630c62a81890608c84b0c5d1ccba809c7414c9cfa6737b092bdcb3defb6797 +dist/2026-09-29/rustc-beta-aarch64-pc-windows-gnullvm.tar.xz=b9db7c497276274a7e5af4ae6666d4d77bb9ebe8a389513c1628488f4f86b950 +dist/2026-09-29/rustc-beta-aarch64-pc-windows-msvc.tar.gz=75b429e1d1f34317877ce3838e4e5c79ea579a051314fce9755ecd92782031e4 +dist/2026-09-29/rustc-beta-aarch64-pc-windows-msvc.tar.xz=04fb7d879ff7b00ed5cc3a054bfd8f4dfcbcc039c1000334db34284b6b7d0d27 +dist/2026-09-29/rustc-beta-aarch64-unknown-freebsd.tar.gz=4a4ece6cb6b686d844d3d93c6b5cc50dcc6fd1a2aac17d7ff7606cc3fe103980 +dist/2026-09-29/rustc-beta-aarch64-unknown-freebsd.tar.xz=2bfd413768c42feade1655007488e4cb913fc5b295763dd7835224e5a57ab198 +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-gnu.tar.gz=c60b31aec10e123a0c461b6f86b0f7d18dd22e706abe76ed4d9ea010c76e1fc1 +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-gnu.tar.xz=ecc23a873a11fcbe2b81e47763204f93a1f91e551c0fa8766262ffa2cc3d0538 +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-musl.tar.gz=1634c9acebc04a266987633062e0db4d4b5a92a568ae55cb146cffba8108038d +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-musl.tar.xz=4361c19fcc2cf8e26bb52489e7dd3e96500c6e6d54bbeaa1493d0b8c8d6a066e +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-ohos.tar.gz=318e6fae90b8da5cad5eea22d358b848746a8f4fcf60d164a2d630f03d12facf +dist/2026-09-29/rustc-beta-aarch64-unknown-linux-ohos.tar.xz=7d80d8a51de0f9a8f0af2ac170e5156a14dba2f3952946a845917f772e9c7dbb +dist/2026-09-29/rustc-beta-arm-unknown-linux-gnueabi.tar.gz=7dc6dcfa998512791269d52f9ee0097bfea867c3a02a54c676c88a69a40f8a23 +dist/2026-09-29/rustc-beta-arm-unknown-linux-gnueabi.tar.xz=b791b3ed832746088ed4ec8378f9b226a7900c4fd4cbe6436f7425191ef1013f +dist/2026-09-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.gz=0a1bab07aafcc98cbb130b81b3ad9eceff1194037110fc8ed7fa6650a572ab07 +dist/2026-09-29/rustc-beta-arm-unknown-linux-gnueabihf.tar.xz=677ee4e95a57d1e498ac4bd9ac05084675c03c58de6e85320d7d6d0c725e6ebc +dist/2026-09-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.gz=e7de0b8ec0715ee54866b533f22ffe23b560e58884228f145e0458a3dfb0450b +dist/2026-09-29/rustc-beta-armv7-unknown-linux-gnueabihf.tar.xz=6316b4bc4931c2811c90d7dff9df5bf7875531c6cf985c065f78b8a0577e370f +dist/2026-09-29/rustc-beta-i686-unknown-linux-gnu.tar.gz=8229d9b5bb6497abdedf15731c15c2ae85c8050bf0995a576685716e9d929ac8 +dist/2026-09-29/rustc-beta-i686-unknown-linux-gnu.tar.xz=428ba34f2281ddbb794a2062e446ca6e5b0cd90a84829186f769bb8d2190a28c +dist/2026-09-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.gz=04ab37c4e7e9dde5a2332975b6f7cfe6c02319e89f9bab2128945656ec81110a +dist/2026-09-29/rustc-beta-loongarch64-unknown-linux-gnu.tar.xz=50d6c00c82dfb7f10bd2c49057822e082c3bc1f6cb7a08e06ac2a5a350e1d1eb +dist/2026-09-29/rustc-beta-loongarch64-unknown-linux-musl.tar.gz=9fc8d551462b4a845c18f163c2787e256d00d4edcaca0721da63ab57002f418c +dist/2026-09-29/rustc-beta-loongarch64-unknown-linux-musl.tar.xz=ce74c12908e44b8b87fdb371533b6a81b5cbc8967e04209b833c87940f4a1420 +dist/2026-09-29/rustc-beta-powerpc-unknown-linux-gnu.tar.gz=e7417324e10e59b5768daa4b5cd01fe92a624739a9b450693fbd5902227a3561 +dist/2026-09-29/rustc-beta-powerpc-unknown-linux-gnu.tar.xz=68dbbc9c7f6c1f2725140c0edd58e3607cd31d4406e7514cb32b9a894f3af39e +dist/2026-09-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.gz=93b02c260b6ace5ea43fd716a100abfb2ed3de24a53e3032794c35858fb0f618 +dist/2026-09-29/rustc-beta-powerpc64-unknown-linux-gnu.tar.xz=e78037526d62c567cb2aa1336c0ed2bfde01e2948833c10a3585040dcf26f343 +dist/2026-09-29/rustc-beta-powerpc64-unknown-linux-musl.tar.gz=3ee5c15579228dc36bef6b254fc235ff57426be8dba7bb358beaed0f1791afc0 +dist/2026-09-29/rustc-beta-powerpc64-unknown-linux-musl.tar.xz=053fbdbfdce20029dedadf7218daabee5b181a69c20b46c2849970f9fa91a7a2 +dist/2026-09-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.gz=a0d9ad02f3f031d54080f3a64f97d099f38de9b324e3906ecd9f873f8353167f +dist/2026-09-29/rustc-beta-powerpc64le-unknown-linux-gnu.tar.xz=8a81d01e78892fbfadfb22b59c6264bcaf4343e36afa806d94b2c6f51eedde43 +dist/2026-09-29/rustc-beta-powerpc64le-unknown-linux-musl.tar.gz=5780592d8b617c2a2b3c1a0c142e71ba589ce5a6ca8d05840668ed9b0217e807 +dist/2026-09-29/rustc-beta-powerpc64le-unknown-linux-musl.tar.xz=e71f58d7383c5ce823ede7d7d032349a3616ec3c3fcae212786b24ec4e427fcd +dist/2026-09-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.gz=3f113901c2996c2bc39891cc6146fa4c2d8800029258186805b20a34dac0ab13 +dist/2026-09-29/rustc-beta-riscv64gc-unknown-linux-gnu.tar.xz=2b7bfe0f71378a76c4b5bc04224f728c02b0cf21d66999d86a33b754ff80b52a +dist/2026-09-29/rustc-beta-riscv64gc-unknown-linux-musl.tar.gz=b4e6d98741d7293f16ab9218e5492664765f43cbc7f8537b45ef6815ca83b0bb +dist/2026-09-29/rustc-beta-riscv64gc-unknown-linux-musl.tar.xz=98141ecd5a1426d8b168e5f181bacf083150895e446840d2243747159bdc3773 +dist/2026-09-29/rustc-beta-s390x-unknown-linux-gnu.tar.gz=5b821594334d8f9b1d07264df899f22fe7a041d7417618b8e7809973fd45ae22 +dist/2026-09-29/rustc-beta-s390x-unknown-linux-gnu.tar.xz=5c52006d530dbd13711e01402dc533c1d664f77e4f1c997179b900ce29ccc617 +dist/2026-09-29/rustc-beta-sparcv9-sun-solaris.tar.gz=7db0a06f0450e2f47ebae3912fff144d416cfe58877ff8996d1335af634bc7db +dist/2026-09-29/rustc-beta-sparcv9-sun-solaris.tar.xz=3d8c85b04fa3d1947840867c5ffb750ae341ad17982aca302abc754e43e1ff42 +dist/2026-09-29/rustc-beta-x86_64-apple-darwin.tar.gz=2bf2b522df594f578642b9c1670b265a02b937b48b5b47ace32a53ad7b569200 +dist/2026-09-29/rustc-beta-x86_64-apple-darwin.tar.xz=ed18e8348eba7bbc6adfd6b95292d802834022a243bd9739cfdbc5d69d8e7e2f +dist/2026-09-29/rustc-beta-x86_64-pc-solaris.tar.gz=cce6ce17920028ed75d83134bae4e02704bf497002b654ff629dedd8294a8335 +dist/2026-09-29/rustc-beta-x86_64-pc-solaris.tar.xz=6d5cb6a91f23044f79c73954bf392989d031412e4d6b43e18d4256d7a3c1fb0c +dist/2026-09-29/rustc-beta-x86_64-pc-windows-gnu.tar.gz=efea45514b6313626db60fa3e922fbd812454004c34c79e3770050826da93022 +dist/2026-09-29/rustc-beta-x86_64-pc-windows-gnu.tar.xz=5a32405ad9ffe040516efd73d961ca53f89c1cd8b4bd8eadb900caef8303e0c3 +dist/2026-09-29/rustc-beta-x86_64-pc-windows-gnullvm.tar.gz=6e911af2547846c6baa414b7d85288d954293df34b5cc87805aa6bb06570dc48 +dist/2026-09-29/rustc-beta-x86_64-pc-windows-gnullvm.tar.xz=e1ad982eccf000e89da01d6910cf918d2231e3cdcc3738f6696d3d57dfa5f353 +dist/2026-09-29/rustc-beta-x86_64-pc-windows-msvc.tar.gz=fd2d7a0809aa431f3f2365f6a98901f359514d47967067c936ba68bc47437d5c +dist/2026-09-29/rustc-beta-x86_64-pc-windows-msvc.tar.xz=ea968def39864e80a462e6be752a7fab2a8c9da7f14799b138ddf0e9bc1f534d +dist/2026-09-29/rustc-beta-x86_64-unknown-freebsd.tar.gz=87deb753d7a5af1afc02cc988d23ea0d42a9573b5e9abbed23ff8f345a91056e +dist/2026-09-29/rustc-beta-x86_64-unknown-freebsd.tar.xz=2dbaa50d6542748cd31dc9f13d4fb82874825634f027317b830121937b583d76 +dist/2026-09-29/rustc-beta-x86_64-unknown-illumos.tar.gz=f682c3ad10ae60d43e2a54a3f624782c9ef0ae61fb0e9ed95a867794e0bff256 +dist/2026-09-29/rustc-beta-x86_64-unknown-illumos.tar.xz=0ad43335ebc8b0d1dbdaa34aa53fbc0cba9a8186b5edac080f5a7bf7ed7cde7d +dist/2026-09-29/rustc-beta-x86_64-unknown-linux-gnu.tar.gz=c567617a07be89de49b009162604ef9bfe4bc542419d405c444e39714591f4de +dist/2026-09-29/rustc-beta-x86_64-unknown-linux-gnu.tar.xz=e562beb9a7ccda3e99c79b2f37149fe5dacdb1f3bb7bdb77ec94b1a947daf009 +dist/2026-09-29/rustc-beta-x86_64-unknown-linux-musl.tar.gz=cea2a33fbacd6b80a7e19592a2ca8f58eb1613589dbd8c906ae78b5723cebe6e +dist/2026-09-29/rustc-beta-x86_64-unknown-linux-musl.tar.xz=e0a1889de08bc4c91006e1d335ed7215257de80bbf6bae375906021ada6dd95b +dist/2026-09-29/rustc-beta-x86_64-unknown-netbsd.tar.gz=262db7c3e54259876fa7f03775b73a5f190cd4812060feac04c13a03db1c5343 +dist/2026-09-29/rustc-beta-x86_64-unknown-netbsd.tar.xz=547adcdda9c63d0f63f8351dee197ca843628bfb1f965e8305f947ca128a2f69 +dist/2026-09-29/rust-std-beta-aarch64-apple-darwin.tar.gz=12a712c301ab944900438c0da63b45ec133efea74b398e708faed172e2960042 +dist/2026-09-29/rust-std-beta-aarch64-apple-darwin.tar.xz=d9705141deb514ad2d721ae34174c33ab5b64ab7181294886cbbfdc3f9b999ae +dist/2026-09-29/rust-std-beta-aarch64-apple-ios.tar.gz=3a65781d05da1559788ea8bc2df4d84f12fdc4194cfcece0863ce786ead5ec13 +dist/2026-09-29/rust-std-beta-aarch64-apple-ios.tar.xz=728a2be2bbbacf3866e007d92b9f0857a9b7da0d0c47c16e296fba25839afbf4 +dist/2026-09-29/rust-std-beta-aarch64-apple-ios-macabi.tar.gz=b445edeeddab84fac96c089d73f3a87e485415583ddbff217092058c14c79c9b +dist/2026-09-29/rust-std-beta-aarch64-apple-ios-macabi.tar.xz=db73dd68d6a0458b7ab9e49f2e331a460f14eb4598af19f2a6f642b85db3c947 +dist/2026-09-29/rust-std-beta-aarch64-apple-ios-sim.tar.gz=09d2bbd7f44f6245ff9e7ffdccec0a491e9195075232cfca2f247329b0371aa8 +dist/2026-09-29/rust-std-beta-aarch64-apple-ios-sim.tar.xz=1faee83ec196e8a2876c06dd5377a542aac1aa32c7d3b00ecf31a3713b50555c +dist/2026-09-29/rust-std-beta-aarch64-apple-tvos.tar.gz=e8d1cd23d78eacb8a4be5cb465b94902b5351573b4c0a47073205ec4c8028397 +dist/2026-09-29/rust-std-beta-aarch64-apple-tvos.tar.xz=42f013a0c3ad79263d651b194dab7b08734f6a96dd5943535706f4a8990ca819 +dist/2026-09-29/rust-std-beta-aarch64-apple-tvos-sim.tar.gz=a5381d8ed927c6e1c720833462898ca6c4bdae6702e308352f0dc5698e3fb93f +dist/2026-09-29/rust-std-beta-aarch64-apple-tvos-sim.tar.xz=6ffd6d6d7bc230e28a78f7230b0b91fc71dda6af018feae186b0eb48910234c6 +dist/2026-09-29/rust-std-beta-aarch64-apple-visionos.tar.gz=90a82a478d671ed7269f7cfb5eeaa70cb914d9424dd741c7a2ad2b4a26840b6b +dist/2026-09-29/rust-std-beta-aarch64-apple-visionos.tar.xz=1c700b45a80f7304fe00977cb2fe46975ce16ac31494f2e5afc825465b475d02 +dist/2026-09-29/rust-std-beta-aarch64-apple-visionos-sim.tar.gz=50113f0e4b4cbd8c528978a6ead8fc3fcf15dc6b1c4bf97488a61da8d9245dfe +dist/2026-09-29/rust-std-beta-aarch64-apple-visionos-sim.tar.xz=fbd9564bbdd9d0d43fb00fe67a83fad16a58d4545982344bdbacad93dd53b110 +dist/2026-09-29/rust-std-beta-aarch64-apple-watchos.tar.gz=6ba080aa355f112b74c180ee6ef1ed182bad260f35e4816bf22f758af1782286 +dist/2026-09-29/rust-std-beta-aarch64-apple-watchos.tar.xz=979686c0acca1dfe4bbc1906bbb7dd268b90b9aac3dd97a06f105fbc3260f78d +dist/2026-09-29/rust-std-beta-aarch64-apple-watchos-sim.tar.gz=4d3459fa110abab0d95e1748f5426f162d746635529839d88360dd7c186a9a0b +dist/2026-09-29/rust-std-beta-aarch64-apple-watchos-sim.tar.xz=303623e7c027952c164dae9e8662c1141914a35c7af148de8e7b0cd813594384 +dist/2026-09-29/rust-std-beta-aarch64-linux-android.tar.gz=cf7c1de2dbdfd3ac05131e63cc6285c5d76e8ae85c186350a164ce1017a6a1c9 +dist/2026-09-29/rust-std-beta-aarch64-linux-android.tar.xz=790d34c2a756240cad1da2662132eb11ffa2b3e844ba639c3561aa5ba0d3ae97 +dist/2026-09-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.gz=dde06b88182f2f6bad4d7b2cfd40a99ecccac1fdc2dee3ef5e65f425e706484f +dist/2026-09-29/rust-std-beta-aarch64-pc-windows-gnullvm.tar.xz=f901b2689461d3b38b5f2eec0a6f5c6795ee3638da97a433c1fa84ecff11a082 +dist/2026-09-29/rust-std-beta-aarch64-pc-windows-msvc.tar.gz=943394d1133a8c82da94d97ae738472666a9ae4f2d04c504171d8bae34a13f21 +dist/2026-09-29/rust-std-beta-aarch64-pc-windows-msvc.tar.xz=6777866c103e45b453d7ad36d3addc3bfa09684b6e6e4abe18ea5ef782ade595 +dist/2026-09-29/rust-std-beta-aarch64-unknown-freebsd.tar.gz=5b2e8bf0dfa7a5be26a3d969c708e5181149982877a3d571d75ad2c118b56ef8 +dist/2026-09-29/rust-std-beta-aarch64-unknown-freebsd.tar.xz=b5146618aee2bdeea3f3da4c6afe4b07d6b8af0440f6d954985973d12dc7ec9e +dist/2026-09-29/rust-std-beta-aarch64-unknown-fuchsia.tar.gz=e92c49005a09ba23a21cc74364f30769997f7b6b81c2205ee7e9d9413fb38fb7 +dist/2026-09-29/rust-std-beta-aarch64-unknown-fuchsia.tar.xz=fca1e29e1856abe923cccef58d560074d2d5adac5211007c00e0657677ea7f57 +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.gz=9d02af2c761d752a1371e301753a432031984cfaf53d9812c8ce540bfbf6d716 +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-gnu.tar.xz=e991bfc2818af00b53cfac0535d094135712339b8f1289186a6d0f8d209ff351 +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-musl.tar.gz=405f757b12a00629b2f2dfd0ebf3c372d257047fd8ddf348088ed78235fc0e7b +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-musl.tar.xz=c8dd6d868b2f6b316433bb1849a809450bae0fab9305c60b2123816066e69d71 +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.gz=4fb73dd34675a6f27b6426f58ad7be879ff49ab8e98c3ce003e49651bbacee4a +dist/2026-09-29/rust-std-beta-aarch64-unknown-linux-ohos.tar.xz=a89e58073a28be60905bb7647f0e60b4520639f5460cfc3c6f1e25c581939864 +dist/2026-09-29/rust-std-beta-aarch64-unknown-none.tar.gz=b7bb5e2d07dfb49786bc1f9de858c3a41a6c4723df4e48152905616867389617 +dist/2026-09-29/rust-std-beta-aarch64-unknown-none.tar.xz=0c0fc594ad1d67be737ec709d3e10ed319d3e5a4263d1951a9bfe664bd2504b3 +dist/2026-09-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.gz=25ac7161cf32dad13f4bcefc64cedb25963f4f61995e9531650c8a2636536263 +dist/2026-09-29/rust-std-beta-aarch64-unknown-none-softfloat.tar.xz=440165cb33ab38c651e798c0ddca0195f36f7ab6de981c37b4f41c98c2cd6f38 +dist/2026-09-29/rust-std-beta-aarch64-unknown-uefi.tar.gz=b5ba39fce8b242d9f77fff252e0da2b4a8d455929d247ffeb522d063eccc3253 +dist/2026-09-29/rust-std-beta-aarch64-unknown-uefi.tar.xz=16915d999525cd8e1488d6378ded9c11f58b0390e2a03f0dfb89d32b3d2339c6 +dist/2026-09-29/rust-std-beta-arm-linux-androideabi.tar.gz=e1d3999e6ba68470df99c7836ce8c51232fb62785ea7c96c6b2a456d468655f2 +dist/2026-09-29/rust-std-beta-arm-linux-androideabi.tar.xz=c23e03c5eea7fc437413e6d539ffdf43bfaf2f00d9f13db2e4d789e3edb31527 +dist/2026-09-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.gz=db082f4b98dd53be4f32b618d5494ec2fc2af75ac571d7aa1e93edba18ecf30c +dist/2026-09-29/rust-std-beta-arm-unknown-linux-gnueabi.tar.xz=cdd51373266d628735f876c8acab3d658f1ec54fca4ef76511c45d7d555d598e +dist/2026-09-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.gz=62de66b7ac14a2d8b725be25b5f6af6246973ec5557ac631cff594177b1db726 +dist/2026-09-29/rust-std-beta-arm-unknown-linux-gnueabihf.tar.xz=fb86b6e2e3b556a63144c0cef982c200e2bca8d2d0a1db4b1374d0c7724107bd +dist/2026-09-29/rust-std-beta-arm-unknown-linux-musleabi.tar.gz=0f64d408c08361269324e8cea25053c5f542bda8b7afc5393a497808993254ea +dist/2026-09-29/rust-std-beta-arm-unknown-linux-musleabi.tar.xz=b05ec5e82bd8c93ceabbe2578dda16076e4b87daf315dc5baa54c8abd4e52ebf +dist/2026-09-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.gz=2effbb32422491890eb626dcf181cfb30499ba26c4f64d4a96c9e304c22dcde4 +dist/2026-09-29/rust-std-beta-arm-unknown-linux-musleabihf.tar.xz=24bb014666bfadb3256c390b36c2369a324077036eb2cc1c6e2be825d6e8d278 +dist/2026-09-29/rust-std-beta-arm64ec-pc-windows-msvc.tar.gz=932df0b6c8289fb46a9f056b70921a4b1b9400c136dd45c0561f190802d10c1b +dist/2026-09-29/rust-std-beta-arm64ec-pc-windows-msvc.tar.xz=fcf67570a855d2e396f0019492767c8fabf00b20ba614c8e00ee9c987fb06b31 +dist/2026-09-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.gz=4805f236f0122d3a67e736031b2b530e9c1c4d7a1cf65039d7118d50985fe033 +dist/2026-09-29/rust-std-beta-armv5te-unknown-linux-gnueabi.tar.xz=3ae97148bbabfee58ecd7db754eef720a084685d6df918713ee9103126f8b96b +dist/2026-09-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.gz=d5bc909741d6dabf577c4d26e9570e66a4fe0f7a253c61364f57bd3adf11c4d8 +dist/2026-09-29/rust-std-beta-armv5te-unknown-linux-musleabi.tar.xz=6bb41498459ce565e0c91228c41c23ba326cd4d964bb5554866cc350d30d2381 +dist/2026-09-29/rust-std-beta-armv7-linux-androideabi.tar.gz=04be64de9a88dc5fad743c7c9e3ece7ffa88fc8f6741bc7097011dafc3af867c +dist/2026-09-29/rust-std-beta-armv7-linux-androideabi.tar.xz=87450f7a9e275eb7dfd67e78eca210d867ce06e338b8a53eda0e5eebb2930b85 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.gz=9d2c987cf665bd8490e43e66611cfae292c5bb74aacf7d36129cd71cadfe06dc +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-gnueabi.tar.xz=0533fdb36d2e8ee0b1bf5274e000f7876ade0f6c6a289a4014b97bc41eb4b88d +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.gz=f6d92ec41459b974d5a1058b079560737261d263f218fa74982fb3d143117e02 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-gnueabihf.tar.xz=b7ea4246a4a35d36596edba6f808b351abf99e0c861abfc5623d7a7cf2a125e9 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.gz=004e933e4e1cf4c3bde0cb189b22c71bb58e84e9f9d0cab9288d46744c529b7d +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-musleabi.tar.xz=ceed6092180912b2e6bfa95cd7345d2a0da20aced84ef1626ee9945fa109b950 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.gz=4acecafc1bec8a97b67206557e340d6de7fa3f6a39baef49e704e203798f12b0 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-musleabihf.tar.xz=b79c57d00374db2f33708752d0c0c1ded34c9282c1a14b7a155f5c8ef49b96fd +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-ohos.tar.gz=2fd30887db6155ef25f02781322e79b6b69113f282e89b68e119677a3cf6c526 +dist/2026-09-29/rust-std-beta-armv7-unknown-linux-ohos.tar.xz=9d65af3b8227e2096f3f78cfa2207241d226ceacd6c5559d2ad682ab156c6842 +dist/2026-09-29/rust-std-beta-armv7a-none-eabi.tar.gz=141612e58714918c93ba2769723712e577c99e19b6d858e77d8677850e2dcf85 +dist/2026-09-29/rust-std-beta-armv7a-none-eabi.tar.xz=2bfe5040c6c62fec4e863428288baa735fc581ac2d7ff4a180b51e169db0f291 +dist/2026-09-29/rust-std-beta-armv7a-none-eabihf.tar.gz=5014575869a7ecf9c6a6c91cb69b97f6fb798d3836f0c1851a5a9128d380fc42 +dist/2026-09-29/rust-std-beta-armv7a-none-eabihf.tar.xz=84dd449ba61513a783e10ccdc4b40ebf02db42a435f306690f945b59a9b38274 +dist/2026-09-29/rust-std-beta-armv7r-none-eabi.tar.gz=bcb61efdf77fc8a3ac756a2989cb29e57519cbba6cd86eac5eed42799e6dab98 +dist/2026-09-29/rust-std-beta-armv7r-none-eabi.tar.xz=0cbdb7ea8c7c9505a3b8a9d055704d736ea9be344862ef3f335d4abc27bf9d21 +dist/2026-09-29/rust-std-beta-armv7r-none-eabihf.tar.gz=422ff4501a710a25cdc6569428320beff61c2840872af2d63dde98543cd795f6 +dist/2026-09-29/rust-std-beta-armv7r-none-eabihf.tar.xz=c26f216ca75b5ab3c9e837a55c6a0faa7ffc3a348125e6dc545def1ad92582b3 +dist/2026-09-29/rust-std-beta-armv8r-none-eabihf.tar.gz=44b08082e62a1469c30956d9b3c82053bf341cd15b36a9ad634d0b9061cb2702 +dist/2026-09-29/rust-std-beta-armv8r-none-eabihf.tar.xz=57eccc6e20abd4d9a95bbe0095401d8b64fca6829e11a0f4f0b4977bd5466b8e +dist/2026-09-29/rust-std-beta-i586-unknown-linux-gnu.tar.gz=c98675485760784593bfcc1c1239ace93b05a90649a37cf40c78ec76f54c9b6c +dist/2026-09-29/rust-std-beta-i586-unknown-linux-gnu.tar.xz=25c25743a6bcbdcf35b6a055b5bb4a7c3af73074bca1923d3b97dfb5b87d51a4 +dist/2026-09-29/rust-std-beta-i586-unknown-linux-musl.tar.gz=5f0a8c43f055eaffe5efe71b62f0ba276bed1afc158efd29f10b5ea064fcd881 +dist/2026-09-29/rust-std-beta-i586-unknown-linux-musl.tar.xz=5d73bfd5f7115ec5e67b07c0e978f4aab9e8f79adee879e917b29e01fb78ca76 +dist/2026-09-29/rust-std-beta-i686-linux-android.tar.gz=7cdb05e049ea8e32fad2cea069fa98181d5289dcb2d6322e5dc80d151ef31b66 +dist/2026-09-29/rust-std-beta-i686-linux-android.tar.xz=e127f07fd97a7fada184bdee50aa83002c7764d6a0b320aa10d6b2bd400b2786 +dist/2026-09-29/rust-std-beta-i686-pc-windows-gnu.tar.gz=3f9713c9e37aafd3ce7c825ccd9a145dd9c975841da6de6f0ce340ae2381ad24 +dist/2026-09-29/rust-std-beta-i686-pc-windows-gnu.tar.xz=ec6e784cd6d3dc3e76857654621a4072193945668287b9d7665eb5105878bf0b +dist/2026-09-29/rust-std-beta-i686-pc-windows-gnullvm.tar.gz=c174dc7ec2ef614eb6323f06e655eb86266c0b81e1d644e5e093d58af7806f5d +dist/2026-09-29/rust-std-beta-i686-pc-windows-gnullvm.tar.xz=ac9f8789b013c8ece9ba57a56bd05047b8b7134c7f3f13e616bca2b592ca5ab8 +dist/2026-09-29/rust-std-beta-i686-pc-windows-msvc.tar.gz=a4b5db143623d75352bab8f5154583b0ee8f3a4886062e9bd79675e956e528d7 +dist/2026-09-29/rust-std-beta-i686-pc-windows-msvc.tar.xz=cfde62235d503f2906d0aeb21a07b479d3765a4d6bff10c1e54fbd557937e089 +dist/2026-09-29/rust-std-beta-i686-unknown-freebsd.tar.gz=d7bbff8b33fd5d247a8bae9a3c83f879777c65651babd1cc7515c52668b0f43a +dist/2026-09-29/rust-std-beta-i686-unknown-freebsd.tar.xz=a22f726246f417641f5feda6ed2622749e375d03d11bb1be57072d74e286ff68 +dist/2026-09-29/rust-std-beta-i686-unknown-linux-gnu.tar.gz=0d90d3e128d0f378c4b8d948fa65e6d3f42c9eda9da023e9218b6d62cb3442d6 +dist/2026-09-29/rust-std-beta-i686-unknown-linux-gnu.tar.xz=5e78729655a70c60fe5c49a32a7f09418a720f7623d512dd260d04ad52645b8f +dist/2026-09-29/rust-std-beta-i686-unknown-linux-musl.tar.gz=1e10e1e648b38e1e5d102ba87c374937ee1eca7abf53d4abf4421c74e2583283 +dist/2026-09-29/rust-std-beta-i686-unknown-linux-musl.tar.xz=a716466a78991384a45d0f27c73a3268e4f1f709d27ea32474100a8cc9ac5736 +dist/2026-09-29/rust-std-beta-i686-unknown-uefi.tar.gz=f5168879aa790d8a823d98865b2abed8683ad998bc46cab8f92b3cb046c0b442 +dist/2026-09-29/rust-std-beta-i686-unknown-uefi.tar.xz=414e0fc0ff74ba42765954390114a14cdfb261dbcf82ffee03509421ac8b13f3 +dist/2026-09-29/rust-std-beta-loongarch32-unknown-none.tar.gz=f651fea2e64f49fb75f74e7b4a350fde8391808ddad903dea20f8af4e4f848b4 +dist/2026-09-29/rust-std-beta-loongarch32-unknown-none.tar.xz=cef214987ba5cff11f8a5c75b11a2bc4fd3be236e23ca98308addbdf83529232 +dist/2026-09-29/rust-std-beta-loongarch32-unknown-none-softfloat.tar.gz=1a2f03ff61944e81dfe485129f96084a8f0843da76ce62287bf6a70500f5644b +dist/2026-09-29/rust-std-beta-loongarch32-unknown-none-softfloat.tar.xz=39f6bd3be80e0ead123e2ac706d5da15e2c76a7fa1994de40817692d82bb7714 +dist/2026-09-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.gz=5012a90d4f9fcacbdf003f151cd6f3316defcd2283514526102834bbd74a8c8d +dist/2026-09-29/rust-std-beta-loongarch64-unknown-linux-gnu.tar.xz=b8d1bfd9c839ebc6b7c90b98b0be907f6246e69fc92eb48e85db4ed6c7dcbe0b +dist/2026-09-29/rust-std-beta-loongarch64-unknown-linux-musl.tar.gz=6569ec56c5f6fa26aff9883603cb9453504854fee82878b25b1b0d2cc9935e6b +dist/2026-09-29/rust-std-beta-loongarch64-unknown-linux-musl.tar.xz=2b087399ddcface9b4466a915bf99077adbd8849846498016d57a61c48236d5e +dist/2026-09-29/rust-std-beta-loongarch64-unknown-none.tar.gz=064352424fbc4bfb9637b2a5e45c7ac39d4c2acf937a48f5c8b71cc3b24cb615 +dist/2026-09-29/rust-std-beta-loongarch64-unknown-none.tar.xz=1f3bd23cb2fd4444efdbc15637a05ca8adeb18b2dfecdc5281ca92fdab40f6a1 +dist/2026-09-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.gz=cacb51b0256f0f30722f8b69c4cafaf79dc2e9d561ca4990e00ea450a49626d1 +dist/2026-09-29/rust-std-beta-loongarch64-unknown-none-softfloat.tar.xz=a6c1b71975918d172cf47017a2636a29814297ae79f80d223a83ac0cf17770d7 +dist/2026-09-29/rust-std-beta-nvptx64-nvidia-cuda.tar.gz=e8f0efcb638b971d12ff73cc32422ce944cb2816022dca9d875f1eae938319ca +dist/2026-09-29/rust-std-beta-nvptx64-nvidia-cuda.tar.xz=b40bcea95f0c915cf154ffdcbd1388156c2d3c1734b4b00e192869422dbe170c +dist/2026-09-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.gz=efffecff9289cb117cdf4e3fed6126b45a3a82040e0d5f44101ed52f0b38f274 +dist/2026-09-29/rust-std-beta-powerpc-unknown-linux-gnu.tar.xz=e12f25ed25788772becf9f44bca4e88eda5a1f21cf17f08b09cdfa728f90a764 +dist/2026-09-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.gz=e032b20d3f989cc8c74478871e6dceed4ce3fe3d0a7d232c15b8976e679f870c +dist/2026-09-29/rust-std-beta-powerpc64-unknown-linux-gnu.tar.xz=82e13804fce4dc6a36832873db80d5a4a43d9d8aee44c40c33c30a88227d5d44 +dist/2026-09-29/rust-std-beta-powerpc64-unknown-linux-musl.tar.gz=20a1312d8c162e7cb26ffe9ba89fa50cc92f4ca4bfa862e3bf2a540d3718a3d6 +dist/2026-09-29/rust-std-beta-powerpc64-unknown-linux-musl.tar.xz=6c2b3f2b17804994388a18f443470049bb63a785852456b27eac2a3320c03b31 +dist/2026-09-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.gz=b02de7909bdcfb397a6714fee31031f7039c129fcbf831816d12957217fc9c7a +dist/2026-09-29/rust-std-beta-powerpc64le-unknown-linux-gnu.tar.xz=a8d21a1e9f410be453757ca441d1872cec6a4c92aef1ea2111b4ee4a126a3db3 +dist/2026-09-29/rust-std-beta-powerpc64le-unknown-linux-musl.tar.gz=44be1a79c527831221deedfcfb0e0afd0d8c772102b90286dd9180c6f102dff9 +dist/2026-09-29/rust-std-beta-powerpc64le-unknown-linux-musl.tar.xz=d2305657826fd51a2c6480d8aa3d5fdf92d0f665770a83ee4c0f7f9ed0f0de65 +dist/2026-09-29/rust-std-beta-riscv32i-unknown-none-elf.tar.gz=f1c9e1c8dc22a6f1d784aec5b24922976972c1eeb56e7d587650e22d4eb0d601 +dist/2026-09-29/rust-std-beta-riscv32i-unknown-none-elf.tar.xz=7aaa2bde1cd84c38b13d24dafa47ab9083339795cac996437f41c7510426a562 +dist/2026-09-29/rust-std-beta-riscv32im-unknown-none-elf.tar.gz=f04d393d79727af08de12ca7d13fd41ec78120e3bcc30008f684508edff0f2af +dist/2026-09-29/rust-std-beta-riscv32im-unknown-none-elf.tar.xz=04c8d324b52253354cd7907693bce663b300c075f10a9a0668c29956a8cf8a24 +dist/2026-09-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.gz=2a8d5ffd86d7cf52d942933725653c6147ececd7f19a5d1ffee654a2cd1b8bdc +dist/2026-09-29/rust-std-beta-riscv32imac-unknown-none-elf.tar.xz=5399870b58683f7d4d35b80c7079e959a092ced21e6b56969a9e9c67e82acfde +dist/2026-09-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.gz=6693b6d5032b92eb844e4c7dfbd7f251dae9a13c8af74aaff015c9258367c292 +dist/2026-09-29/rust-std-beta-riscv32imafc-unknown-none-elf.tar.xz=cd1f07d5a147eb17ff4b6d77a9a9fc567d46a47ec00a1ae15d8ca0d48f12e5bb +dist/2026-09-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.gz=e783e12d4436d0976053f3c559096b4baf6f5a02d222c45f3cb40f59fbb91f53 +dist/2026-09-29/rust-std-beta-riscv32imc-unknown-none-elf.tar.xz=00564a08fd47392352f40d4b375a7ca565c8fee14f553bd526dbd88f049ad9a3 +dist/2026-09-29/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.gz=731b85413ebe28cad585e028bc77b78869e80ee0714f01b5e6a913d452ab6cb9 +dist/2026-09-29/rust-std-beta-riscv64a23-unknown-linux-gnu.tar.xz=25902d5d514f10984a67301e6281b7e7fae38af2d95879c1ae730485068e3d67 +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.gz=a776dd47f9381e67c9fee75db18df84cc2faf51d8691d23c393ea1514f257bbf +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-linux-gnu.tar.xz=9acd29f728562348bc380cc112cf56709ffd62e499d52e5ac9c0446a8c1731d2 +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-linux-musl.tar.gz=549702f03471fa57abd4b2d990b716fbc87274c8d0386afdc4ccadc7bc4dceff +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-linux-musl.tar.xz=574bd2d37d0c13be91082d9633af161ee3eb7572fd72c8959cc744672723cd1b +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.gz=1c52932e910cada292e4561fb2d469d75e48369292475a67221a49e80b06e0f4 +dist/2026-09-29/rust-std-beta-riscv64gc-unknown-none-elf.tar.xz=18c6df09267c26b5f5c3d55b0ca108aeb1c6cc4e286461baef7ad126f5ca208e +dist/2026-09-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.gz=3f42e1e761b319b3e348396c87c3b79f67783081b2ee0acbfcf72c29a5409fc1 +dist/2026-09-29/rust-std-beta-riscv64imac-unknown-none-elf.tar.xz=f5fe44aeb22ad3c00eef4f4a1bac56436ba59bc9336b901d88c0f781032dc954 +dist/2026-09-29/rust-std-beta-s390x-unknown-linux-gnu.tar.gz=88b170bcd8d3e26d422bc8ae7a525d8969878434acdb60c4d8f75ad4a6f5fb10 +dist/2026-09-29/rust-std-beta-s390x-unknown-linux-gnu.tar.xz=5cbcf61ee88f021d7570f360971a4781a48ace118b6c2047a6d71b6928ec874d +dist/2026-09-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.gz=5772cb9750380f03ef47f1502e82ac790237967d7dd2e3de2eaf6fb0fb723df8 +dist/2026-09-29/rust-std-beta-sparc64-unknown-linux-gnu.tar.xz=5f2fcaf8b81c370443b53989dd12f3885c299fd8009aaeefeafb63ffa8c2dc40 +dist/2026-09-29/rust-std-beta-sparcv9-sun-solaris.tar.gz=4bcae41b9149b8d7d3a968b7924fa60ca15ff014c997dffddf1073e3c756a48e +dist/2026-09-29/rust-std-beta-sparcv9-sun-solaris.tar.xz=1bcaae45605a3b9bc05265d48e4bf46bdae9d3a45c6e4cbab4de7df0ec76b73d +dist/2026-09-29/rust-std-beta-thumbv6m-none-eabi.tar.gz=c8668ef20b4a6bdf393082067ec753b9e7e7fdcb4215bfa159a8394e70ac62bf +dist/2026-09-29/rust-std-beta-thumbv6m-none-eabi.tar.xz=6aa054160722c4f887cd335f5e5549afe289f04e7abc5d6df95769a83be453d4 +dist/2026-09-29/rust-std-beta-thumbv7a-none-eabi.tar.gz=b28bd0f5ffebe62f944a3c5f17a9a73eab5c990201ea6961d530b769a69f8d3c +dist/2026-09-29/rust-std-beta-thumbv7a-none-eabi.tar.xz=ce529ebc58e8a757bdab3aee87d34a0c06dd59feca3b708aa97a97b79ca176b4 +dist/2026-09-29/rust-std-beta-thumbv7a-none-eabihf.tar.gz=bc94dbbfe23cf6adf1d34a8a6421480854eab76009a0d327d597f84c83c597d6 +dist/2026-09-29/rust-std-beta-thumbv7a-none-eabihf.tar.xz=96bb2b46a7b11d85ef347e2561730fabd1f56cbb334b5b4ebe8fd0a60fc980ec +dist/2026-09-29/rust-std-beta-thumbv7em-none-eabi.tar.gz=988b9a2c797874a96a155b152d2704624eea46e3ff76c9ee31081708661ee390 +dist/2026-09-29/rust-std-beta-thumbv7em-none-eabi.tar.xz=8c64f7dc6ac9d4b35a5683f6324cff0e1bf136b63dc7b0341f5b15570cd6ff37 +dist/2026-09-29/rust-std-beta-thumbv7em-none-eabihf.tar.gz=35fe10b86edb438efac8d9bb37992dc42758f84b82945fc5c115294c1645e997 +dist/2026-09-29/rust-std-beta-thumbv7em-none-eabihf.tar.xz=9ce5331218676dfe1cee5e975a7e9c56c30e051e4999cf4d7bcc89664aefbb60 +dist/2026-09-29/rust-std-beta-thumbv7m-none-eabi.tar.gz=d268977a2462bc3f8ee3a113965417313c8ce91de44700701bf89a1f485c1261 +dist/2026-09-29/rust-std-beta-thumbv7m-none-eabi.tar.xz=02cc4d5a04d190245b154769f6bf691ad82b2a37d5b6dcff98d25218f4da6508 +dist/2026-09-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.gz=6b5025117edb1c0f6e2a519d7a827c257371bcbfe8c1cd2cf194fd8e808fab18 +dist/2026-09-29/rust-std-beta-thumbv7neon-linux-androideabi.tar.xz=f6ee4b5ee7439a71c1ac02c428ccafd739fb59e4d7743c73218472c99d54747e +dist/2026-09-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.gz=a1a6e10b069cc010dc0d25d33e39bf09d2e902ba824951571b1ff6272c406a30 +dist/2026-09-29/rust-std-beta-thumbv7neon-unknown-linux-gnueabihf.tar.xz=1e5f603944d9a1565d7ec648298e126a8d039ca8112bc9f5f8c4e6b2bfbe6f40 +dist/2026-09-29/rust-std-beta-thumbv7r-none-eabi.tar.gz=36c4b0a0bfe975883763666d3cc6562ca9f98e1b8623dc6fb1d341390669b511 +dist/2026-09-29/rust-std-beta-thumbv7r-none-eabi.tar.xz=d087749ff3a16e4577ae93afac8635ce614cfd56c68d2f01e939a33ee07ee5c8 +dist/2026-09-29/rust-std-beta-thumbv7r-none-eabihf.tar.gz=fff03b17250ffc7c328b68b542d293da4d81ae16fda76b53ca87d2dbe03a9fd4 +dist/2026-09-29/rust-std-beta-thumbv7r-none-eabihf.tar.xz=e47e298a4f5583c447056566b2c559af073387024d74822d4f7d657396cbb842 +dist/2026-09-29/rust-std-beta-thumbv8m.base-none-eabi.tar.gz=6245b71146c9bf6892f87d36505f8f8b019f925a93e9e7382fb4c11ed7b92921 +dist/2026-09-29/rust-std-beta-thumbv8m.base-none-eabi.tar.xz=1190208ca7e613923db504b2f452c87f631934a9ff69c212824ec15e03a45a58 +dist/2026-09-29/rust-std-beta-thumbv8m.main-none-eabi.tar.gz=e2ae5641572df4bb08906d2b6e7f739eea79278333eb0c5547c49b0727c56dcb +dist/2026-09-29/rust-std-beta-thumbv8m.main-none-eabi.tar.xz=fe005ce3e6d13722a8a20e3ab668d44848ec97a3d7e275b74d60a84d8e421ee9 +dist/2026-09-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.gz=a53f0858a9105a0e1c675d7662838fa849266d19ce5e0f6a35f72e1d3c6d4294 +dist/2026-09-29/rust-std-beta-thumbv8m.main-none-eabihf.tar.xz=f229db4fd00f6995049a9e6e3cec6763dee8ce10daac63bc522013b121bc4973 +dist/2026-09-29/rust-std-beta-thumbv8r-none-eabihf.tar.gz=341a7f6420319fb33970a0904144734539e605a2323dfbf2b91169e53aafdcc8 +dist/2026-09-29/rust-std-beta-thumbv8r-none-eabihf.tar.xz=2f3cebd916bff44147582514eeabe207c693cdd5e058febe7d86e8c5c87ec598 +dist/2026-09-29/rust-std-beta-wasm32-unknown-emscripten.tar.gz=e8b45a1e9bc3b54f1047a1cdaf9f6b8af3a6750413e4da81d69f0590a6137348 +dist/2026-09-29/rust-std-beta-wasm32-unknown-emscripten.tar.xz=5c20fdc9b9429f2cf72b11e31fc401d81a5deed37f7bd15627d81db5f834b57b +dist/2026-09-29/rust-std-beta-wasm32-unknown-unknown.tar.gz=0796808b38d7517a28cfe7ba3eba5ecb037242a9abcc26390e1f1825467c7977 +dist/2026-09-29/rust-std-beta-wasm32-unknown-unknown.tar.xz=44dbce1c52229c875f22d98de17a78260892e4759b996e989d96ca58f22ea89c +dist/2026-09-29/rust-std-beta-wasm32-wasip1.tar.gz=79a9003e337d684054d8c6859c2118da6992f4ac7eeb8bebb790b763294902c0 +dist/2026-09-29/rust-std-beta-wasm32-wasip1.tar.xz=7d0bdf81bdfea1bb40a17055aa3077b0b7afb214a6826a92a462ac9006b6aafa +dist/2026-09-29/rust-std-beta-wasm32-wasip1-threads.tar.gz=1721f8d930563486f9f90572797b910643b4b0d62f1d89f90114568401d3da68 +dist/2026-09-29/rust-std-beta-wasm32-wasip1-threads.tar.xz=dc0968859fba0cf6ac6e2b50cb53b7790529e23e008a8407aeeb72b9939fa2e6 +dist/2026-09-29/rust-std-beta-wasm32-wasip2.tar.gz=f57b56c42f272d0daa2a8dfe5e0dc16d2ec696a820037bffece1cacdb664232a +dist/2026-09-29/rust-std-beta-wasm32-wasip2.tar.xz=e82fa595d0ee89331a1f862efd487beac1d29895f8eb061ad6b6d04049ebdb9c +dist/2026-09-29/rust-std-beta-wasm32-wasip3.tar.gz=6abca32199fc1bd072ef19d69c9884efe3dcb07c81d0260faa0ebb17e94617cf +dist/2026-09-29/rust-std-beta-wasm32-wasip3.tar.xz=f019b8b140d81aa18a01dff20170f07a381908196828870d3b4dfcbe915f9d34 +dist/2026-09-29/rust-std-beta-wasm32v1-none.tar.gz=777b38934c1f0e70e39e2fb55f3424f8dd77c54ad49c72340ba20cd4307d49c4 +dist/2026-09-29/rust-std-beta-wasm32v1-none.tar.xz=4c78b7da12168bb42a4df10aa269b7a5218eb086ad203e093a87c84f64b2756f +dist/2026-09-29/rust-std-beta-x86_64-apple-darwin.tar.gz=232d6824004015f32bbbb285c872030bdaf8bbf36cd259494f24f2802cac399a +dist/2026-09-29/rust-std-beta-x86_64-apple-darwin.tar.xz=63bf0f85ed80e97cac13f2edc54826829867b62b1758565c580a0680bf370bff +dist/2026-09-29/rust-std-beta-x86_64-apple-ios.tar.gz=23e8e77b11c0870bb486fcd76cee15db11587d3f47df20f220d69a46640ddd8f +dist/2026-09-29/rust-std-beta-x86_64-apple-ios.tar.xz=9f556cc01cd4abf0949c23f1ddc4209d7b92cdc1d521cb22403a4258eac0fdb0 +dist/2026-09-29/rust-std-beta-x86_64-apple-ios-macabi.tar.gz=d5e6bd07a5aa5346c1294d851466579d567ce1d1db16f6b9a40c20619958c8d5 +dist/2026-09-29/rust-std-beta-x86_64-apple-ios-macabi.tar.xz=c3d8808f3b17c81d6de7a8ee2486b5a837f67069e51ad29b0a3c2fa4ebaf4f0d +dist/2026-09-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.gz=72d8b973a20da182acb65479a067be9b4e8fc4e7f7eed41deeac27f8e2401737 +dist/2026-09-29/rust-std-beta-x86_64-fortanix-unknown-sgx.tar.xz=ec661a7156e6baab75839b55377d270a1151e6c432420683ad5a082571f37a77 +dist/2026-09-29/rust-std-beta-x86_64-linux-android.tar.gz=06c09a6a5e54e4da413cedcf0a178107f2d6cfc8082903b262a5db6c807b4a44 +dist/2026-09-29/rust-std-beta-x86_64-linux-android.tar.xz=d36c4d48fa72b2313ba29fc757c505e8a11c712cc779eda7ffa5062b2646907e +dist/2026-09-29/rust-std-beta-x86_64-pc-solaris.tar.gz=ca8ce15a7ae374cc46fde55808a54f94c197bcc9bb40448df06e09cef1257dae +dist/2026-09-29/rust-std-beta-x86_64-pc-solaris.tar.xz=f7c2208dec2c25805546258a81d361f250672ea51e0891254bee9f3c3f4e95ff +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-gnu.tar.gz=b8632646f82535baf39460a3a6ed6a6a92e33f31787efaaf4e6d655225c4f5a8 +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-gnu.tar.xz=ab6729530be4e5fbfa51e76f53f4dcf9c974e0ce6ed11556e8aeb831b1aecdc6 +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.gz=c76571599f894548491d95639bd75f551a3c614e8dfcf34dc6b38e1d3bf28474 +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-gnullvm.tar.xz=52dcb526a8ddeaa6081809401ff94a733128a5e4adf9feb1671744ca1134d817 +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-msvc.tar.gz=84c55c99e3a783136cd334db0fcd6cb6e6cc6d3fa997fedc87dd7620e094ca5d +dist/2026-09-29/rust-std-beta-x86_64-pc-windows-msvc.tar.xz=d7c46a39c354ca67f2197be455db7f3817cf35f476b8fac5c85e16c911cd291c +dist/2026-09-29/rust-std-beta-x86_64-unknown-freebsd.tar.gz=46331daca0d7bc83edd687190817d7b7b62f14fa037d9dd56c32314d10e1df29 +dist/2026-09-29/rust-std-beta-x86_64-unknown-freebsd.tar.xz=ac315cd71f957e6b555f98e7744bedf32ae06cecf8a688594d16dc11b0409e14 +dist/2026-09-29/rust-std-beta-x86_64-unknown-fuchsia.tar.gz=5ac6db26e1298837d5d660ca24be108c9fe569784ddb2061dd8b7afca06c4a1a +dist/2026-09-29/rust-std-beta-x86_64-unknown-fuchsia.tar.xz=0ccc6aa8a3746d143515882a33254fa67cead1e58fc3dbce191769f59fccb635 +dist/2026-09-29/rust-std-beta-x86_64-unknown-illumos.tar.gz=9547382b596806f8460bffd1fba4b21c87a809744b678d1379c821288256bfb7 +dist/2026-09-29/rust-std-beta-x86_64-unknown-illumos.tar.xz=a52fa0165572f08d7c0807b618b8841c9220065ff188095bdbf4bd4e9bb11771 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.gz=b8eaac057b7b4197941904f539ef4e01eb93daeaedd8b158b5a0a2d8e370ea26 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnu.tar.xz=9095fa52e354f1441568af9e3a9839b16268f7ae7707fd4bc48b2a2bcd1d547f +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.gz=956b82298d2f2c7e34e28d157ba41945d39865a23b9bbe20678d7ae31aa825b2 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnuasan.tar.xz=3ecf190a1c53ee9aea39f643ac62923835379f08f6503f4134459ebc5f610a08 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.gz=10576f120a98f153c7a68e62a565a92424917a36fe3cb017f4a657e236b3ff88 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnumsan.tar.xz=a009b119cc0d811e070dc329cf241b8b509d9a297faa68c5d2216b4e21f5ac50 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.gz=8d9aab19bea2b6b07f11e9a2bdc0058441e6f80f4d6e778c03cb5b52854c7aca +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnutsan.tar.xz=3507d9b8563db110eaae0253c5c041b62d42508696f1526b94b92fd28e200b14 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.gz=7dc3b370335b15345dc9f508c4f132d00a69fdf0feacbaaaaa2f93bd7cbf9ce7 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-gnux32.tar.xz=b8b24db68ff29f15c52fc70ee12cc6d10bcd65259c521876fb08892c8f67b980 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-musl.tar.gz=13da2b408f85665b37c6ba519cc4fbf8eeacae1dd6835f22edd800fa229d6f56 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-musl.tar.xz=61f986574cf89a091fc6563c0cef458e1c5618444364eb36751194b2da7f8da9 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.gz=48d5e6ffa8dc7319809a13ed109a8c5e43e9b17d5e6c9e88a57ec160068caae5 +dist/2026-09-29/rust-std-beta-x86_64-unknown-linux-ohos.tar.xz=962cc03687830996b02c8419b4f948b94b7f9b6c40a918212bfa9ba8a3186aea +dist/2026-09-29/rust-std-beta-x86_64-unknown-netbsd.tar.gz=93c518fd23ffc00d69f37e38b90033d76091b3946ee7ec82d906b78a4f7130e9 +dist/2026-09-29/rust-std-beta-x86_64-unknown-netbsd.tar.xz=a8922fe96c323e6ccf587a70841651143065e25d2ce465dea5e2d9ffb52fd42c +dist/2026-09-29/rust-std-beta-x86_64-unknown-none.tar.gz=4df5d869a75e754e1952b73fa78a4722fca53038325dd0e541887e8d0c8a7620 +dist/2026-09-29/rust-std-beta-x86_64-unknown-none.tar.xz=c37467acf1d25eaba261edff55a410a0104dd31b90f8158b10b6f2e369a6d9eb +dist/2026-09-29/rust-std-beta-x86_64-unknown-redox.tar.gz=8d245bade3f0fd036e16314190cf3a0ca535c75a4c97277e24135a9e76815156 +dist/2026-09-29/rust-std-beta-x86_64-unknown-redox.tar.xz=76392bc2afdd60a591b3114fb191deacf59388c21fb1d7ec1733f2f561778648 +dist/2026-09-29/rust-std-beta-x86_64-unknown-uefi.tar.gz=b17e48ee19a86057a7ebaeadd697a4dc86853cf9e66c4981e5043de9e3ce1c00 +dist/2026-09-29/rust-std-beta-x86_64-unknown-uefi.tar.xz=1cd2a4b32284ffb4d11bcd3fb561578f3d00c763c704a177e113af6899c22d0d +dist/2026-09-29/cargo-beta-aarch64-apple-darwin.tar.gz=f3066c859807c0ab69429ea69362654e18c21d26b2c482be436280bfad4b49e2 +dist/2026-09-29/cargo-beta-aarch64-apple-darwin.tar.xz=0bdc913f85f762ca2af5c9bd2d72a31865c102bc66bcc43250a7eae06208de49 +dist/2026-09-29/cargo-beta-aarch64-pc-windows-gnullvm.tar.gz=e2bde3311142eee8c4d822ff838778cbd2ef7d7f496f4dd4a0237756fd16964e +dist/2026-09-29/cargo-beta-aarch64-pc-windows-gnullvm.tar.xz=1c26e80d1529c17cf4ef6025ceb63490cd862ca9eb7c21fa043fa89d2ee1f0ff +dist/2026-09-29/cargo-beta-aarch64-pc-windows-msvc.tar.gz=2b71fb86fb57894c2fa83ae53522783fd9b5b654332ae7623eca3b153f4136e8 +dist/2026-09-29/cargo-beta-aarch64-pc-windows-msvc.tar.xz=5a8b4e3db041cafd58e59333f872cb1020f385d54269ea02ca7ca8a4ce45796a +dist/2026-09-29/cargo-beta-aarch64-unknown-freebsd.tar.gz=12d98333d9d48a97a6cf0bbb9b01cd4a215a51feaf81c5ddb4ac54ce3644814b +dist/2026-09-29/cargo-beta-aarch64-unknown-freebsd.tar.xz=89fc6ebdf93d553fc957a1adac94f9d83feabd5c84c364aa875f36a4d274e31d +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-gnu.tar.gz=173043d8b96bbd8149de521da3271123895af497379a278a87039cef644f5245 +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-gnu.tar.xz=69eae56c755c9d90a1e35d38e22d43b46e204913d237c5c2ea9001906a273db5 +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-musl.tar.gz=2590e51b526f771cc486a2ca15f89c7ccdf878bce18c7e03cf32b6116ab5483c +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-musl.tar.xz=8d1325965495214ac2894aa9062255e519397eded66a32e71b871eeea81dd930 +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-ohos.tar.gz=e18bfa187c668f15f48aa36fcb29d71791577132e829334dd3ac05d5b7cdd7f4 +dist/2026-09-29/cargo-beta-aarch64-unknown-linux-ohos.tar.xz=fc3d7339b87792efe262f8f0685bc97c42bda4ee21541d4d0719e1ba1fdba4a5 +dist/2026-09-29/cargo-beta-arm-unknown-linux-gnueabi.tar.gz=25a23eaf8af21d465d2b0ca6461281702c10339d968ff226e0c63dc6bf9950ae +dist/2026-09-29/cargo-beta-arm-unknown-linux-gnueabi.tar.xz=7544dd758d44668e985e93eb777bccead5f63bf98326ed7e003d2a68a59d4c4f +dist/2026-09-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.gz=016d2a04723930c835f7564bbf460978ec2ba9f497c5b94c6665ece36989aefd +dist/2026-09-29/cargo-beta-arm-unknown-linux-gnueabihf.tar.xz=4a40079a253cb349e41148b919b7e460e5eb6c659089dc4366c32cb343dab5c8 +dist/2026-09-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.gz=36b8677ec6fc857af1777e2f4a68c2cbe90a72b21f9afe2b4221593a76cd3748 +dist/2026-09-29/cargo-beta-armv7-unknown-linux-gnueabihf.tar.xz=816e1c6b3bdaf08b24514331b972d864a6b7bd8d63479fd154dd1608ac66f26e +dist/2026-09-29/cargo-beta-i686-unknown-linux-gnu.tar.gz=f374e9858d5d4294e9007986d4df7af0d15a57bef5862c289b818c3bf7bc8299 +dist/2026-09-29/cargo-beta-i686-unknown-linux-gnu.tar.xz=ebaa11b6203e20cb0a612c53aaa9a0ae5c275795c1737c4bebebb679cdabb485 +dist/2026-09-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.gz=e6816ee73290cf376b402ad6470eb2b68004a883b1b4294393a8966d7bdf1aa0 +dist/2026-09-29/cargo-beta-loongarch64-unknown-linux-gnu.tar.xz=b476bcd327cd838606b8482381c6fabf0ce97f518e3ab11b35a50827f2b18b51 +dist/2026-09-29/cargo-beta-loongarch64-unknown-linux-musl.tar.gz=b83080fee58cb9e72db9c8ac994724ff3a5bd2b7039eabbfa0cd9bc77d2d4532 +dist/2026-09-29/cargo-beta-loongarch64-unknown-linux-musl.tar.xz=889717547ec4cbb80d7f2d2e35b1b2b512c3e450ffa56a1bc27289fe285898d6 +dist/2026-09-29/cargo-beta-powerpc-unknown-linux-gnu.tar.gz=340d7ff13760dbb32148c8616dd7c7246870a7f091bda102902589a20dc8c2f0 +dist/2026-09-29/cargo-beta-powerpc-unknown-linux-gnu.tar.xz=29c10897c335e4bd2dde7848bf67bcc93b96e5911888524d0abb8704fb88a629 +dist/2026-09-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.gz=62fe339183294cdd58c5c90a6a1dff3a388dc2b054f2ef46babc127cb1dcaf11 +dist/2026-09-29/cargo-beta-powerpc64-unknown-linux-gnu.tar.xz=18ce8044103b232c245c8ad3ab92073a473740a897506c69f79c406b611263d1 +dist/2026-09-29/cargo-beta-powerpc64-unknown-linux-musl.tar.gz=fa3e4a74e3bcb12816049d51dcbd9103fd2136679c509b47b4a64f38686c46d9 +dist/2026-09-29/cargo-beta-powerpc64-unknown-linux-musl.tar.xz=d5efafc560f206af8e32d6a720c923e74443af1e5e30e8e9a5a06a38b2955534 +dist/2026-09-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.gz=07a1eb729d565b322c3f65d925cb98f125d8c031ea390e5537208fc831cdb627 +dist/2026-09-29/cargo-beta-powerpc64le-unknown-linux-gnu.tar.xz=fae744722b6f92d00dcf4325d1f5c7a59dbf3563f53318e772ac48ec330c7d2c +dist/2026-09-29/cargo-beta-powerpc64le-unknown-linux-musl.tar.gz=95e91adc5af521f58650ab88707c870952be0492e913c96df8dd3a816449f242 +dist/2026-09-29/cargo-beta-powerpc64le-unknown-linux-musl.tar.xz=d46a64931a0ff96ba7c80f3fb3edceee803d86458c72255b5037857e0ff86de5 +dist/2026-09-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.gz=05a6b30d13367ee0f13295ebad1ab19c41d6ef7e0658971b4857e2b423d04ac2 +dist/2026-09-29/cargo-beta-riscv64gc-unknown-linux-gnu.tar.xz=d64db7e154194aab5d689236a545e3a2f657a67339c0eff77581be6f1808e6f1 +dist/2026-09-29/cargo-beta-riscv64gc-unknown-linux-musl.tar.gz=88adb1c494bc36bc577bb13bae1efa5051481cfce96249c4d340ab7eca017c17 +dist/2026-09-29/cargo-beta-riscv64gc-unknown-linux-musl.tar.xz=8347b2a940db92e3af2c11208ad77c337f5dc856960656c179e19c2b17a161b5 +dist/2026-09-29/cargo-beta-s390x-unknown-linux-gnu.tar.gz=79070ab2fd6d93d37a1cdd11d24a1de15a887d5503086f1e64766a99796decb3 +dist/2026-09-29/cargo-beta-s390x-unknown-linux-gnu.tar.xz=b64e4cca016d3ffce2b1e6944cd249d4e93eab689c0d9cced01a798bc7e183e9 +dist/2026-09-29/cargo-beta-sparcv9-sun-solaris.tar.gz=fc1bfe106843c3b7f0affa77de936dfdb8b9f5a438176d9037aa0533e9b9c8ee +dist/2026-09-29/cargo-beta-sparcv9-sun-solaris.tar.xz=9e12971574167eff3830526f10db3e21cb817f4b28acdb10c42c7689cc2f9656 +dist/2026-09-29/cargo-beta-x86_64-apple-darwin.tar.gz=97072e5a8006d0a8932983a44b1dc0a7b56d46efc76fac6378315f43cfb2c556 +dist/2026-09-29/cargo-beta-x86_64-apple-darwin.tar.xz=d296336efa8cee66a03655cbd66e64709866fe98bc2aeabfdff88039b74eb800 +dist/2026-09-29/cargo-beta-x86_64-pc-solaris.tar.gz=96832f53757943d1c752dadb11fc122af8085317017d7263b73d413029ce9b1f +dist/2026-09-29/cargo-beta-x86_64-pc-solaris.tar.xz=091cd84168e3c9dd860bc0df58d07def0318e470c3459cd431fed713c0ab2616 +dist/2026-09-29/cargo-beta-x86_64-pc-windows-gnu.tar.gz=f99a145aa7938be5baae99302858b680e2c2ae3dd84e8434cc38de374967deaf +dist/2026-09-29/cargo-beta-x86_64-pc-windows-gnu.tar.xz=5bd7758064d9500c68fcfdd5a3a851d4dda40d3c870a83b9a70c93b46a8c8823 +dist/2026-09-29/cargo-beta-x86_64-pc-windows-gnullvm.tar.gz=06494aceb50c8bf0131639c52c62746b07ff2143b04d383be6f137277397a0ae +dist/2026-09-29/cargo-beta-x86_64-pc-windows-gnullvm.tar.xz=5923b97ac130c29f6f0ba96fdbf4b034a452a9d03ae78d8bd812e9d3eb304a80 +dist/2026-09-29/cargo-beta-x86_64-pc-windows-msvc.tar.gz=26736efdd0b4e09dd8e7ed421881fcd39e588b31c45129c011bd78d83e42c153 +dist/2026-09-29/cargo-beta-x86_64-pc-windows-msvc.tar.xz=9e72a3172d9638143bbb51c9cecfce7dfbe463644ca3e90cfbfb04a30561ed93 +dist/2026-09-29/cargo-beta-x86_64-unknown-freebsd.tar.gz=e9b9ecfda5fa944168f81c12ebbe2c127ab245f867d61d47197ae23ca8eb9c86 +dist/2026-09-29/cargo-beta-x86_64-unknown-freebsd.tar.xz=e7359e4d2a6e0ff4ac99fa49346f1e2ee4c64487bb2f35ef0b75fc497bb676bf +dist/2026-09-29/cargo-beta-x86_64-unknown-illumos.tar.gz=bc5382bc1853388dc1573f464bfc3393f41293b159826488b0096ce1dd87582a +dist/2026-09-29/cargo-beta-x86_64-unknown-illumos.tar.xz=46867f0df7b6b95f13598267c5e17a96aff1de929ea2b23fbedb30e7b24324da +dist/2026-09-29/cargo-beta-x86_64-unknown-linux-gnu.tar.gz=dc8dcdee80d7034b0ceadb64fb15608c7617022f4c0be595bffed3326f1bc7a8 +dist/2026-09-29/cargo-beta-x86_64-unknown-linux-gnu.tar.xz=6ed534d029be58d7c0fcebaba581166fee81167de58806540d9d6ffb0f68836d +dist/2026-09-29/cargo-beta-x86_64-unknown-linux-musl.tar.gz=ccace12c5ac38d428e107faf94c7945eeff7f72058910fe93f6514234feb0aef +dist/2026-09-29/cargo-beta-x86_64-unknown-linux-musl.tar.xz=03501cfc18b5dd937612ee76fbd57ded962da245f87aefe3bfa4f332afd9812f +dist/2026-09-29/cargo-beta-x86_64-unknown-netbsd.tar.gz=384f90d70932ba9babe4f9baae008cdf52ef7815a0052b7b6c73bece3f024aa6 +dist/2026-09-29/cargo-beta-x86_64-unknown-netbsd.tar.xz=3c4e43e90a741f1e10409b3cbe426ebe3d3506ad7196eb291c55c4ee060d9e19 +dist/2026-09-29/clippy-beta-aarch64-apple-darwin.tar.gz=aa278ec430f7939b2eb5da177a7e3229b92105ee9e7ad71d8ba7f04cf6f41a4a +dist/2026-09-29/clippy-beta-aarch64-apple-darwin.tar.xz=3929ed842657b6792f95b987e0deb630d96aeb98db9700493be148999390c5e7 +dist/2026-09-29/clippy-beta-aarch64-pc-windows-gnullvm.tar.gz=1272823dc9eeb737f03ec09313c09953d75fea3a848e695c8bc434c2ab53e062 +dist/2026-09-29/clippy-beta-aarch64-pc-windows-gnullvm.tar.xz=76155e48b475fc40bb31ad136725f00875385db2bf179fdb3979065c7a65282f +dist/2026-09-29/clippy-beta-aarch64-pc-windows-msvc.tar.gz=f79d2073573010aa0f1ee4a8579b17f3a1997dc96fc6652a8c8c19a566231eb0 +dist/2026-09-29/clippy-beta-aarch64-pc-windows-msvc.tar.xz=4b8303804318d731b61159959c93782f205a95d8a3aa14e1643b319b6fe9558e +dist/2026-09-29/clippy-beta-aarch64-unknown-freebsd.tar.gz=1028922c743c9170603eb76731be0d3d994873a2b5a47f6a46480eb339a14554 +dist/2026-09-29/clippy-beta-aarch64-unknown-freebsd.tar.xz=ac262e022b7b09669051a325e02eef2cb83087c25ffdee6f059e2069ef430e3f +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-gnu.tar.gz=bb1376c0de000c1e0efdaf8ecb9fa11b14a64a6fe99000ac391f828376ce2c12 +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-gnu.tar.xz=90d1d3895d777b2a473f8035d3264f374c9ca91fdeec32d78899ae0a5f33f0ad +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-musl.tar.gz=5a4cd4fa995f9ba8ef4f87001a87595c4a144f1af62b6a61ff2c5d4e2d90f7aa +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-musl.tar.xz=3775b95f01258fb108f323d031ba8920993d23746f62a6fe5b14add176833b05 +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-ohos.tar.gz=7759e690dcf0984c274dadb14d5601f64cecd21c833b44c93b24c509234bd697 +dist/2026-09-29/clippy-beta-aarch64-unknown-linux-ohos.tar.xz=21598de0d56cb2c0a259cec74bf4b45b1ae350a9d62296289e85f6648fff0427 +dist/2026-09-29/clippy-beta-arm-unknown-linux-gnueabi.tar.gz=a8db1b3308fd0764012d3e76bdf92a076749a04af6f3f139288a1b5f7aea6d3a +dist/2026-09-29/clippy-beta-arm-unknown-linux-gnueabi.tar.xz=746e5b548d3c57a9c42da80a02a5c2df0c2e025b2a8becf17ca1aab937d0bf27 +dist/2026-09-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.gz=6100df771233dbe2d31b9ca7ac202ecdefddb964687b9ea2b97799c58f2df8b1 +dist/2026-09-29/clippy-beta-arm-unknown-linux-gnueabihf.tar.xz=601693ede0315db0d92c6bc9c53f1f4d829d1a506001cd291fcb61c12c91ca09 +dist/2026-09-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.gz=a7cf7145fc885a7d0359e6f32f8d9a46bf2adbdf268823f1202647bc2a131fdc +dist/2026-09-29/clippy-beta-armv7-unknown-linux-gnueabihf.tar.xz=4b26189ee6eb3d78cce60be7a54d0d64f1a5bfb18dbabf30e829296ee09065a6 +dist/2026-09-29/clippy-beta-i686-unknown-linux-gnu.tar.gz=b73fe9b224653599b38a0a68cada53106276e749f5350871a1d549be5c147487 +dist/2026-09-29/clippy-beta-i686-unknown-linux-gnu.tar.xz=60fa35754a88f0f97e538b639c24237d651c11e1edb16c653536111e1a7f123b +dist/2026-09-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.gz=8a59dd0ce10cde5e714d3f8989fb1ebde1ac51d746e96a72d6239feae81d1568 +dist/2026-09-29/clippy-beta-loongarch64-unknown-linux-gnu.tar.xz=3e7d0761021dc58612054a575e202224645665f90fec0bf805998694a71c8fb9 +dist/2026-09-29/clippy-beta-loongarch64-unknown-linux-musl.tar.gz=f220e05c95906dfe8247ab7a3fb732a5444cba27facad044f50db4c04b62bff4 +dist/2026-09-29/clippy-beta-loongarch64-unknown-linux-musl.tar.xz=d9a7343dd0ee670a086a565a1013f647b3fd8061d4594d42cd2724d3cd52bb78 +dist/2026-09-29/clippy-beta-powerpc-unknown-linux-gnu.tar.gz=e025c6f5c822b45ddf5387dc9a42dcdca9f69be2546a020b2d4de2c07590b8c4 +dist/2026-09-29/clippy-beta-powerpc-unknown-linux-gnu.tar.xz=90d7b50a45274903c43d4d1c57c9ed5b4213c07563feed70caec38723df02bbf +dist/2026-09-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.gz=31aa57d681a3215023de663aafeea01e476be4e2a1f89345602e89eb3b1b5c03 +dist/2026-09-29/clippy-beta-powerpc64-unknown-linux-gnu.tar.xz=fc5dd5800afb155af741770c6111262e9a2b5817bbd8bc2ba06ba2daeb72c822 +dist/2026-09-29/clippy-beta-powerpc64-unknown-linux-musl.tar.gz=ab5edc689617c105a00941d3870b6490c62209d235d09b7f2d48b8ca460b62a5 +dist/2026-09-29/clippy-beta-powerpc64-unknown-linux-musl.tar.xz=77b9759b82d634222650a2ccf9160b654fc636be0b7fd4fac822728eaf1f7317 +dist/2026-09-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.gz=04f40458440c4222e49df829159f51fc667c10b0762181a535ff61cf120352be +dist/2026-09-29/clippy-beta-powerpc64le-unknown-linux-gnu.tar.xz=ebc8495543e025b2c6db795f665725ad62a2ddd17094f6725bf4e00cbbf25331 +dist/2026-09-29/clippy-beta-powerpc64le-unknown-linux-musl.tar.gz=ba6653802d14bd1586819ae5f9510b9a97e0ba6ebc062942264b52fc297fcff8 +dist/2026-09-29/clippy-beta-powerpc64le-unknown-linux-musl.tar.xz=7c3f65a1938dea882cfee18992a10cb23b58de801a191d0cbbf8c6cc6f9cd900 +dist/2026-09-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.gz=ad43d2a294308b1509151379c5a9bb40b064e13a841c2d34ed31537bd9eda3a0 +dist/2026-09-29/clippy-beta-riscv64gc-unknown-linux-gnu.tar.xz=d7f118d124d772ebe763780f8ab1cd0295562eccae944c5507500971eebc5352 +dist/2026-09-29/clippy-beta-riscv64gc-unknown-linux-musl.tar.gz=9bb458f695227868c03d21e15177210b067c7fea223c1ba877f3908cff85e673 +dist/2026-09-29/clippy-beta-riscv64gc-unknown-linux-musl.tar.xz=80de4f209ad908cb28921bedd07cbb1444cd7f25179a851c6a2285bfcb13e13e +dist/2026-09-29/clippy-beta-s390x-unknown-linux-gnu.tar.gz=1f3e61cac84317586d80f816465800299920d032548dc82ac6fdd554503d9f86 +dist/2026-09-29/clippy-beta-s390x-unknown-linux-gnu.tar.xz=98f16b6b0a8a6a4542a07d0ec06ae1a05cefdeacfe7398363c61af5b5ea0e3dd +dist/2026-09-29/clippy-beta-sparcv9-sun-solaris.tar.gz=d5876205c3b704883a464354e287ad485dd0677261d36c7adb3beb97509bf907 +dist/2026-09-29/clippy-beta-sparcv9-sun-solaris.tar.xz=b036fc21fa47b8bce0113a1ef74ff869a54ea06d8f3bc0058f4551c3daa1f089 +dist/2026-09-29/clippy-beta-x86_64-apple-darwin.tar.gz=d9f9860fa397ae78d9e6612240a05eedb917cf536ebdef03bfd4bee110feff58 +dist/2026-09-29/clippy-beta-x86_64-apple-darwin.tar.xz=b054e2bba8ea8b3994e48aa1ef9b121eb1760f1c9468da3dcd9ca8cbe05728b9 +dist/2026-09-29/clippy-beta-x86_64-pc-solaris.tar.gz=ab47ad303b93eae7fd933333a94e7b4f65f0119735b83b8eca83691e24f982bf +dist/2026-09-29/clippy-beta-x86_64-pc-solaris.tar.xz=2187367acea68f7bf09932f0cdb237e30e57a57aadcc388219f60aaf28ec4ea1 +dist/2026-09-29/clippy-beta-x86_64-pc-windows-gnu.tar.gz=97af8a6c3356b4d65d1f96f893e57100969ecfbb2e6c364a2380b07d154677ec +dist/2026-09-29/clippy-beta-x86_64-pc-windows-gnu.tar.xz=af7f0a59d0ae24d0dc8ab6424a781a65d5d0cb8b3253786daa908e1d43efa7eb +dist/2026-09-29/clippy-beta-x86_64-pc-windows-gnullvm.tar.gz=683647b7e096c4085162b0936c614e7151bd6e9e6c5da902a80e68b91d54f47a +dist/2026-09-29/clippy-beta-x86_64-pc-windows-gnullvm.tar.xz=9a3b7efc7dd8c84f8351f117bcad61423c2f2cae6c1782fd28361a6865d31abf +dist/2026-09-29/clippy-beta-x86_64-pc-windows-msvc.tar.gz=b487c66b5091b4a7446f70d9fe138b62a253aac4a8a7745151f8a2e0f0af2c77 +dist/2026-09-29/clippy-beta-x86_64-pc-windows-msvc.tar.xz=53c63e23c797c931401bfc23053b336ebb0e0e26d603cd817770daff8aa8fb8e +dist/2026-09-29/clippy-beta-x86_64-unknown-freebsd.tar.gz=1174a56bb2aab0c5f88b963a8d2d26fbb5d29ff3f3dab449c6848711641060c8 +dist/2026-09-29/clippy-beta-x86_64-unknown-freebsd.tar.xz=adbb076f2efe0532c7e6997ceab6c08e8e5c228774b0e9f844bc238c14663f90 +dist/2026-09-29/clippy-beta-x86_64-unknown-illumos.tar.gz=07047d9cf9e20e6cdf12f1a24706eaf6791d921df97430aea8a1fe37f6cfd6f1 +dist/2026-09-29/clippy-beta-x86_64-unknown-illumos.tar.xz=7720a8410c6c1814a60c9c1432190179aff2bcdba720cc1fe7863cfe9c4ef7e2 +dist/2026-09-29/clippy-beta-x86_64-unknown-linux-gnu.tar.gz=9a47312d7f06050e2a35f884a0fadb63994d9ce4c988db7055df9c3a18826db5 +dist/2026-09-29/clippy-beta-x86_64-unknown-linux-gnu.tar.xz=dc6cafdb56fa4c08d69fabb0fe55c2bfbd13f5452676b7ca7ea80b0feb0636b7 +dist/2026-09-29/clippy-beta-x86_64-unknown-linux-musl.tar.gz=681bc45997f340b2767e1fcdb98d77cd6331b435c0b9b94d3dae0d68d2afe628 +dist/2026-09-29/clippy-beta-x86_64-unknown-linux-musl.tar.xz=09933240e021562422512f9a01364a681fa5fbdc0518d53b2c84159cc160f64b +dist/2026-09-29/clippy-beta-x86_64-unknown-netbsd.tar.gz=7f09a6e7d2a3ca645d600f7b2836854240927b9b22ed5b90c2e19b18602f1bf9 +dist/2026-09-29/clippy-beta-x86_64-unknown-netbsd.tar.xz=6f55faa86ce658f28036f4828d00d9f3554a16bc4c08d338f90e46cc0b8290a8 +dist/2026-09-29/rust-beta-aarch64-pc-windows-gnullvm.msi=110b7787e72503c3d8f00bb83b4844ee5d86282006535978fabaeccd570b9446 +dist/2026-09-29/rust-beta-aarch64-pc-windows-msvc.msi=52095c3b2bb30c4444514adb315c441ae99a908fcd6dabf84df86e9fa547fdf2 +dist/2026-09-29/rust-beta-x86_64-pc-windows-gnu.msi=0dbeb0a4874799e29f61078c2ee7b52aa09f3892da449949562f7b834213d2af +dist/2026-09-29/rust-beta-x86_64-pc-windows-gnullvm.msi=67bb2a3bdf0efa223c1ec3961ca8bb3becd0dfec3dbba6c1664f3800c13f96c9 +dist/2026-09-29/rust-beta-x86_64-pc-windows-msvc.msi=f3832ded2d7dc6b8e344a8a05a58145753b7206409ab7989e4e175b000891bb5 +dist/2026-09-29/rust-beta-aarch64-apple-darwin.pkg=ba8205d70d4e7d9dac9fcbbb50e26a1c48d95f6d53115cd4f31b4894fb770f86 +dist/2026-09-29/rust-beta-x86_64-apple-darwin.pkg=821a0c24ed40c517f6b3cadc591a41e12f3dc17ee177d304d91adcc4d00d1557 +dist/2026-09-29/rustc-beta-src.tar.gz=1e970d860c77112674c08a4f6fe27c7f5f3eabdbaaabae7924872f37b0a6bc9f +dist/2026-09-29/rustc-beta-src.tar.xz=8c8dd7643b15e160e0ee62ce2ea2804c1c463954a983527335c9ad05e2d7a282 +dist/2026-09-29/rustfmt-nightly-aarch64-apple-darwin.tar.gz=3bd82067ee57ab38a80d21b212397e600b1cdfac4ffe67e064a0d4fc72696579 +dist/2026-09-29/rustfmt-nightly-aarch64-apple-darwin.tar.xz=105657de7a7e2989d0e1aa27655bad89689dfa702e6208072c04a5dc1f116dca +dist/2026-09-29/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.gz=e9ac24651a2dcd1b92c85ce3ca537ca4004d077d13d81a76c30543a2ff537ce8 +dist/2026-09-29/rustfmt-nightly-aarch64-pc-windows-gnullvm.tar.xz=12d0fed0b8caaea2fb0b63590a4dc2f96af71a54eb3ca113e09601a5e603fa7e +dist/2026-09-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.gz=2e4a7ba18c433714efdcce7b1b858a3128b10918f0b6c081225b5699ce095b4c +dist/2026-09-29/rustfmt-nightly-aarch64-pc-windows-msvc.tar.xz=da5ef1e3577b7c7817509115086de5f3b32d943b76ee3e5d3d555f88bc02b28e +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-freebsd.tar.gz=44446b6fae2d871a1b6af2100f4c0783b3f000b348a1536c5c4f23b82c8107ec +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-freebsd.tar.xz=7d37bb9b45eac9c1e2bbcc623da6dde1d653527d408292e913b4347f3622accb +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.gz=997a0e463191defc94ffa9405ba11a4a2bba1b220b40cef415a1a8d21e2e88f1 +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-gnu.tar.xz=2050f09bd2dffd324c3b949626c35830d16f2e92a680a8c7001a19287d3d1b54 +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.gz=479090aac278503503b41acf936c774c645343a33193e5c149f9db28a301edc9 +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-musl.tar.xz=87b3f386c5372dca8676065403c0123935c7a47c5e69579beecc040a0b67ba15 +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.gz=10da9a954bd0b76aab56c09ba01262eb87069ba18d67c36b982f3a5ca0ca3555 +dist/2026-09-29/rustfmt-nightly-aarch64-unknown-linux-ohos.tar.xz=f3db934402e31236c41188b5f85eab229e4cc8d108c9c33375e03bdd3b72bde3 +dist/2026-09-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.gz=9891c54c4cc027cb0e0edbf6c7b2d85a80287ff486074d8334cc0eea662fce48 +dist/2026-09-29/rustfmt-nightly-arm-unknown-linux-gnueabi.tar.xz=8ef63b3fbace26c9ae4045bf08d8bc2c60fc6fcac095bab34f0743f82729a15b +dist/2026-09-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.gz=fabf81e854b1e1220756f2cc04cb911bff886af1a84f306bd38eaf3d7bf6e0bf +dist/2026-09-29/rustfmt-nightly-arm-unknown-linux-gnueabihf.tar.xz=f47aac3590c165cd800be1526278bc06538fddfbadc2f2ea0288a16274a3b04f +dist/2026-09-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.gz=fe5a0792b5f3f34e4854e257f3edf27e30c90938568e4ff576d374e5a4800cfd +dist/2026-09-29/rustfmt-nightly-armv7-unknown-linux-gnueabihf.tar.xz=3ed3e957bbb5aeb4895cb5ddfcb93abd32a5c10982adb0724a3b91a578c9d5a5 +dist/2026-09-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.gz=d1e17fb001c32efa0455ce814ba35276e02de4fa41f858a1573f407ebfb79b21 +dist/2026-09-29/rustfmt-nightly-i686-unknown-linux-gnu.tar.xz=d673931f677d95884fcbdb9dd1d971588ad8209b12b9ec10338f2c9e1516479e +dist/2026-09-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.gz=96cf73ca815b8b5c912cb82e2ee2d75d1d60a11bda9fe242173b8a74335441b1 +dist/2026-09-29/rustfmt-nightly-loongarch64-unknown-linux-gnu.tar.xz=a1af935bc9d319a962f388cb9d52981ccc1adae9e79ad561c520f92994b5b4de +dist/2026-09-29/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.gz=a614c7570d2f7370761938d62a93cf231d6673f4cf51be1ec13a86d7857d8a26 +dist/2026-09-29/rustfmt-nightly-loongarch64-unknown-linux-musl.tar.xz=c7033f3846f19329e2d0c177cdc328387e9fd1d6738f44f3134fd73993e810e7 +dist/2026-09-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.gz=5a5c754617ff1d20b76c4f6a651bfbeb3446d133e2d7d1d151195d9c9709ba37 +dist/2026-09-29/rustfmt-nightly-powerpc-unknown-linux-gnu.tar.xz=efba88f943670d427859c411c71090e3c9c503400c527432bf0f4e45aa9a640d +dist/2026-09-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.gz=bdfd3bd37453fd6c8cf965b2ccc56d0db4131dcb232843ff8ccb744126d07581 +dist/2026-09-29/rustfmt-nightly-powerpc64-unknown-linux-gnu.tar.xz=36fb9e8d537d9439391b2eac5357bc93d422be396fe226c4e7ada987ae1cd0fd +dist/2026-09-29/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.gz=613aaa4c896802ad5065a846a0412e708ba4ec8d4cbb8c4cc268924edf50866d +dist/2026-09-29/rustfmt-nightly-powerpc64-unknown-linux-musl.tar.xz=d11268b84e0ad465d055208171268a63340724909916c9c4c8f2db7f77930406 +dist/2026-09-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.gz=3635e8a286ebf903e86b13e71a0c9da91b1cf08acd15fb529990e1bb01938994 +dist/2026-09-29/rustfmt-nightly-powerpc64le-unknown-linux-gnu.tar.xz=7ba06366c9cb6641d177d1fea1efc74b4a70145f4947aea57dc3161d21e3b53b +dist/2026-09-29/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.gz=64fa9295cd882e817a913046856e11e3980740efedbc9dce3c9154e38c9a1088 +dist/2026-09-29/rustfmt-nightly-powerpc64le-unknown-linux-musl.tar.xz=190e0db21d5bfb1e47a6448566b42429a386e8ced68eccf29c575e8a17774aa2 +dist/2026-09-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.gz=780db7ef6ffc4d4e3bf37588d111b2733b2f30b22d1247111a7b6d290ed7882a +dist/2026-09-29/rustfmt-nightly-riscv64gc-unknown-linux-gnu.tar.xz=0c55a5f391d9e032ec946bf2ea977b80514239c54109438e4ef17257bbae05e6 +dist/2026-09-29/rustfmt-nightly-riscv64gc-unknown-linux-musl.tar.gz=e9f3036825eae095bc415b485ad9397c96edc3481a258865db9d4b54e7cc9134 +dist/2026-09-29/rustfmt-nightly-riscv64gc-unknown-linux-musl.tar.xz=e4b3cac7c35db29013a22fa6e374011dea824909e3411ce4dabdb197344e0a9d +dist/2026-09-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.gz=c989d87883a750ae2e3d92366f22c0a55858dab9402260af5b2272b8b3eb10c2 +dist/2026-09-29/rustfmt-nightly-s390x-unknown-linux-gnu.tar.xz=e9cbc14a8c2a85229bd523a46982aaf50e242a810708f3ebb3eff2b89c8d1ddd +dist/2026-09-29/rustfmt-nightly-sparcv9-sun-solaris.tar.gz=9bcbe9b3c071008b490ecfc47e0b6007ef0577a488b71ffe829cac10c3f7b467 +dist/2026-09-29/rustfmt-nightly-sparcv9-sun-solaris.tar.xz=319876228cd9ba5319749c819fd127ff7fd9fb87e2886aa4eb97f14e13e95cf3 +dist/2026-09-29/rustfmt-nightly-x86_64-apple-darwin.tar.gz=a71ddea3e092dcd35a2b18c2538a7fc7df24b7fbde464e5b2a8014f86b24b843 +dist/2026-09-29/rustfmt-nightly-x86_64-apple-darwin.tar.xz=5b0ccd75907f3dc4a603cd60bbe87a11c3d75dc793adbdeb453fd385ef91df1f +dist/2026-09-29/rustfmt-nightly-x86_64-pc-solaris.tar.gz=26149456d7e5823901a3df9e5b4e49a93a04e02a536b324bfe2aa16dc5a5f4b6 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-solaris.tar.xz=874f59be83371e0371bd30ccd4abcfe038377c2544ee2c3c577b8a8882a28ee5 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.gz=bc002bd19c2d5c13692d8571c6a82cca5213dd5454e8f1d17215452683b612c3 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-gnu.tar.xz=09c04f5a4a7bf944b58b1b3a0a3142ac8450d7db5277028b881d7ab96242a0b9 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.gz=4af726ea96c30759085ad6886d3d0b0c429abb6ca68990c382f2490ec44cb022 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-gnullvm.tar.xz=77e0d096d1d241c238dd84266a0d32500f3dc0acf142a644012a99eb50fb00f7 +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.gz=294cf327a6af4a8a88ddd6c3bd74a9877afe0940b6a451675f67b10c20588c1d +dist/2026-09-29/rustfmt-nightly-x86_64-pc-windows-msvc.tar.xz=8d2be13b650f7ce0eea90ad26f7b8f5b02771d140ef4b13d3b50ca0a7fe53e21 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.gz=bb8a080ab727bf0503740763ce1eaadcedfd5f592b5462140d1038d397a973b7 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-freebsd.tar.xz=35dc1d5b43934cb35f390491d62c5ebb570005f64edc0baab6456bf2421a71d2 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-illumos.tar.gz=7af5c6a369e6bee9a0239a5c2ebb901dbec8a5b4ed7dbefcd54b84d72cdcf2e1 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-illumos.tar.xz=633ea7cccf1ff5d0999efcb16a35da4e47911ec276b03bf62db5e87b38e82e88 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.gz=cb4dc1c222f7cc67bb2a97418347fce26bdcec945567afc4867549901c9248ad +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-linux-gnu.tar.xz=243f7fd02c5e75bdbd2e35b0ff0ad916de1fe812bf05ae92e51e73f085ebf3bf +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.gz=864f2b4694d45c087f28a54096c5419970a8b7f21e8d60bcd34eef10c6505ab3 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-linux-musl.tar.xz=a461bbc1b5162ae9c7f0c6d96025b6eecf35f4f0bd472715a52937934049bd52 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.gz=11653a0860011db783741465f11dd6833325d1396a82518acb4024d9f65cc545 +dist/2026-09-29/rustfmt-nightly-x86_64-unknown-netbsd.tar.xz=ba8ac6446ce72fc0bad895759fe9fa281acabbf06ed676908b07a303849f1139 +dist/2026-09-29/rustc-nightly-aarch64-apple-darwin.tar.gz=f8bd07a928a00f5a58ecb90eaa3f5383deeca284ecd269c259dce96229c8dd9f +dist/2026-09-29/rustc-nightly-aarch64-apple-darwin.tar.xz=e76cb7ea5f41feb883ee7ed89bd71f48ec029eca9605d3aa757d952bd6a153be +dist/2026-09-29/rustc-nightly-aarch64-pc-windows-gnullvm.tar.gz=0c6136923cf94fa3910caa5440e2e68a4c517366154a57824a1e96f30da4fc81 +dist/2026-09-29/rustc-nightly-aarch64-pc-windows-gnullvm.tar.xz=bc94e0fe4523abe8ae134c068651b571e24ddb44a2ed7bbf40feff344d1668f0 +dist/2026-09-29/rustc-nightly-aarch64-pc-windows-msvc.tar.gz=1d0196716ec66f3a08092736407bcff0b5eeeb0ed9e700467f16959ca8167594 +dist/2026-09-29/rustc-nightly-aarch64-pc-windows-msvc.tar.xz=c08b4c0f3f5df85fb2a39a9e7748be6ce73bb4c17aa00549d3098a4e30738336 +dist/2026-09-29/rustc-nightly-aarch64-unknown-freebsd.tar.gz=3a513dd49f1fd8c80c8a9b51d68bf40a01a4fe6cf0c98a12420dc130e28c3a0d +dist/2026-09-29/rustc-nightly-aarch64-unknown-freebsd.tar.xz=3553abe463701c7b10bc853849e4273eb1f3a0d1d3c6e3d5dda106a41729e2ad +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.gz=23732a3568613f3a0b2b06ab28e1732282297399ddfa07baccaa67c12f50ebdf +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-gnu.tar.xz=651734f660be3f83022f4a627c920753e19e79a7e6c0ee1e6c41f4f78c59767d +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-musl.tar.gz=fa01fe14d03160af899bf60866613826f83a180a6b9eafacb0cf97380059ebf8 +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-musl.tar.xz=3a67ebd7e6083ba65598070c2097e322eab032d4a5084bb6a829a51d4923e6b8 +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-ohos.tar.gz=444251d96d77b80d3b8252ab13108ef053c9482340fbed582b1bef245c258b32 +dist/2026-09-29/rustc-nightly-aarch64-unknown-linux-ohos.tar.xz=1df09853d89ca89950dcf058933dd4d760d1aad172a67b9f60c5b25522f0fe40 +dist/2026-09-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.gz=61f9a4ade7f6daf6b5dfab631321b99625533bab506020594fbc9b6b7c1065c5 +dist/2026-09-29/rustc-nightly-arm-unknown-linux-gnueabi.tar.xz=21ccf42a6618c0b7c1db874566d1e1abe48556c6d8b45139f7c858583debdafa +dist/2026-09-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.gz=296d9251257c6b8a1225cc6cf5c422a790df5b9ccd2fb84d269bff701ee71928 +dist/2026-09-29/rustc-nightly-arm-unknown-linux-gnueabihf.tar.xz=d732c98eeefb447784ef6cb61c59fc919c3e48d4c291efff524cd9492a44e8ae +dist/2026-09-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.gz=5f50621c4463f2cd439922c2bb3b9d2e6af145bfe63aae0a2edec7073af7c758 +dist/2026-09-29/rustc-nightly-armv7-unknown-linux-gnueabihf.tar.xz=52af25e8af238a3fe660f984c1c1cd28f90355cb78d5ba6a967bba94377572ef +dist/2026-09-29/rustc-nightly-i686-unknown-linux-gnu.tar.gz=55f65a08943922d590639588d8c29a6fba4049b33f20332195d72a71a7af7d2e +dist/2026-09-29/rustc-nightly-i686-unknown-linux-gnu.tar.xz=e234eb2638f14654677955ecdf87fe369d439da77cd466e0154f673898bee09b +dist/2026-09-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.gz=70772d9f7de70d4f0ac082e266bfe582a9c20969be33482f3f3244aeca11ee57 +dist/2026-09-29/rustc-nightly-loongarch64-unknown-linux-gnu.tar.xz=4f021e104f149d5c128b646bfd7a889c3bef37322ace9a5759075b42cde2c193 +dist/2026-09-29/rustc-nightly-loongarch64-unknown-linux-musl.tar.gz=b771b86f7af7055f876cd842f70288d26f34c9fb594b7930a43d94d22e07e6f5 +dist/2026-09-29/rustc-nightly-loongarch64-unknown-linux-musl.tar.xz=bfa7b382ac38053d6cd2a5fbda87494168ce54bfad95b161c0bc3790e94d99bf +dist/2026-09-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.gz=576a6faa602ebc4eec32cc06209fe958f98ae584db2c8ba52c7d55bca258c16a +dist/2026-09-29/rustc-nightly-powerpc-unknown-linux-gnu.tar.xz=7a9563061646816f62ed10d8470ddc931d1df850342bca8a5e109dca445a487e +dist/2026-09-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.gz=d94deb2c8476421c2a223af821d7bda039ab853954e6e7eec3dc4235a4bd1de2 +dist/2026-09-29/rustc-nightly-powerpc64-unknown-linux-gnu.tar.xz=9d21d197013585e2cba456b76885c41e3b43a30c4004845fdc313eb33a38afcd +dist/2026-09-29/rustc-nightly-powerpc64-unknown-linux-musl.tar.gz=bab32e4293dd8052aa081aaa6643303d7b0aa4fbe3acbfd91c717a0bea776a5f +dist/2026-09-29/rustc-nightly-powerpc64-unknown-linux-musl.tar.xz=445b9ff411c8dc74cbc337b1b353c72dc75bc431eb997a36436e6b80987059ec +dist/2026-09-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.gz=c8ef38bc477c70fa0e7131c4971b52ae728524e80e29a2570dd5354d5dbe48f2 +dist/2026-09-29/rustc-nightly-powerpc64le-unknown-linux-gnu.tar.xz=afb3c35107b8e4cb6edb48cfa71113084d6fa5360b28127a0e8e1948fa2abc7e +dist/2026-09-29/rustc-nightly-powerpc64le-unknown-linux-musl.tar.gz=9ce50d28b324c020b5fdb37db1a5522ed5a59815a14cfc117177a6c0d98a0d73 +dist/2026-09-29/rustc-nightly-powerpc64le-unknown-linux-musl.tar.xz=9bed9c6990d3ae6b33e60ffa7b60d0e9f6020b24c2c8b5cf7fff61474c87c987 +dist/2026-09-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.gz=5ae5f61985ed5dae8cd9f6d7638afe4957ef1d860a8e819249fdac1d58750e93 +dist/2026-09-29/rustc-nightly-riscv64gc-unknown-linux-gnu.tar.xz=445bef041d5e64fdbd50ad4e883c6b831c4df8bc170f04f779fdccd5db553f02 +dist/2026-09-29/rustc-nightly-riscv64gc-unknown-linux-musl.tar.gz=57f862b615abeef4aa0988e9b023468230757454c30ff8af847a87f884e43f41 +dist/2026-09-29/rustc-nightly-riscv64gc-unknown-linux-musl.tar.xz=eaa6fd5bbb2a8e256e8f0a335f9b7ef33c60a40f0d4bae7a72ad1341809dc8aa +dist/2026-09-29/rustc-nightly-s390x-unknown-linux-gnu.tar.gz=1d2eb7ede0ef321f5a5eed1f19ff30c645048cad2dce1ee32a01fd473d07d529 +dist/2026-09-29/rustc-nightly-s390x-unknown-linux-gnu.tar.xz=892a029d3c60c9b037c073a02cad2c22247bfdf6c21ef94891eb5709ac85b3aa +dist/2026-09-29/rustc-nightly-sparcv9-sun-solaris.tar.gz=75ebd4fd6a89b3fa3529fecc6ab418a88aaea6f2085d2041bf7aa65cab57d1e7 +dist/2026-09-29/rustc-nightly-sparcv9-sun-solaris.tar.xz=56b8da62b8a49658c8a9a575bee49c28eaf955d21442e77c1740935f94d4b0bc +dist/2026-09-29/rustc-nightly-x86_64-apple-darwin.tar.gz=a1063ef2cf262f973c63358955bb1381fb37e73f154b44828b77091d3156a450 +dist/2026-09-29/rustc-nightly-x86_64-apple-darwin.tar.xz=99773bfc304755bc642fbc3617989bc62ee79f2265008c64d6ac15c514673f10 +dist/2026-09-29/rustc-nightly-x86_64-pc-solaris.tar.gz=b9c97ef49440e32d0f62012b1614b8e5cb9773efafeeec5517f82f6ef4f21623 +dist/2026-09-29/rustc-nightly-x86_64-pc-solaris.tar.xz=a286922465f006f15c802a8c1dce3c12ea73846a89006a917c86ebe20e605d7b +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-gnu.tar.gz=ad9a406b01931b98be6021e991899cc1fb028a121b35ffd0a30d8b9359e3b940 +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-gnu.tar.xz=8de44d3694475f3d7579f24d9d8c0dc66f927cd816db4cb572f81eb1e3eb5656 +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-gnullvm.tar.gz=404c667f59d56ac591e9d043ec0427ac2a676fd2a1825442efc3465fe48719f6 +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-gnullvm.tar.xz=f581783eb350436723bb5b4f12257dec703651b055998e3490f7af616e987479 +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-msvc.tar.gz=530917988010ccbe9a6449f5136ba01958d5f94e282a41834b10e7017da11b20 +dist/2026-09-29/rustc-nightly-x86_64-pc-windows-msvc.tar.xz=8ad2b5afbc056d7515626ac2aef4b81d992469f70ebf41701222cca1bc2bcd3b +dist/2026-09-29/rustc-nightly-x86_64-unknown-freebsd.tar.gz=b693055d8cd4da607549da8ed0a186876a3db81f3a27deba1872439d68748014 +dist/2026-09-29/rustc-nightly-x86_64-unknown-freebsd.tar.xz=b55c0de331ce5601970e8227a34ada46ec394a18a86b89700b50d369b6dd59d7 +dist/2026-09-29/rustc-nightly-x86_64-unknown-illumos.tar.gz=54a37b89c59f32e12225f183cb4b0cf2c79721fe5dc15f5801c9527d426b2df7 +dist/2026-09-29/rustc-nightly-x86_64-unknown-illumos.tar.xz=0cff97495e37bdb45230d2ce7d57ccf06b767f6fbbb7cf69df57ae1595b8511e +dist/2026-09-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.gz=ee5cf66faf459f360fb13c9898c2f588f5e04525ce29539c81147b3d0daaa3e8 +dist/2026-09-29/rustc-nightly-x86_64-unknown-linux-gnu.tar.xz=dba6569dd43bf3566bea07621fd270baac5ee75ca70a729c45bcef46f2725b9f +dist/2026-09-29/rustc-nightly-x86_64-unknown-linux-musl.tar.gz=ce2f90940e5911e475f10dc25f7f49a32a971b375bc5d990de4c729f3efde5e0 +dist/2026-09-29/rustc-nightly-x86_64-unknown-linux-musl.tar.xz=7a3b06231fb1604c465c241951cb6c2286d841bb175da13d933c24bc5822a2f5 +dist/2026-09-29/rustc-nightly-x86_64-unknown-netbsd.tar.gz=ce146f46f22b2cb210fbd5a2ce33511b309101f2e1e290db4319e8ed14894bf9 +dist/2026-09-29/rustc-nightly-x86_64-unknown-netbsd.tar.xz=9c787a33d96d02b05e1ad8eb0ce6da8de1f531a05e05199ac4ed8dff051314cb +dist/2026-09-29/rust-nightly-aarch64-pc-windows-gnullvm.msi=a4c6d25c32b5a0a751b53568185e1bb29b6701e9c78a3c964c99de435d5df5d2 +dist/2026-09-29/rust-nightly-aarch64-pc-windows-msvc.msi=1bcc25f2c3c3d154578d314d51488de9a5db11759a38703a6ecf8bb5a5d6d6a3 +dist/2026-09-29/rust-nightly-x86_64-pc-windows-gnu.msi=3f8abd777867a484177ebce45009325559fd89f56065c257cc12e05b679b1658 +dist/2026-09-29/rust-nightly-x86_64-pc-windows-gnullvm.msi=be77343c9728e594b2f355f0d1c03a42ecde8757b2ff4ce4cd6da95a4dbd3e34 +dist/2026-09-29/rust-nightly-x86_64-pc-windows-msvc.msi=a080cc47533ac72c19cbd2b309fab14f33ae11f7aca18feb7a1c955883df37e6 +dist/2026-09-29/rust-nightly-aarch64-apple-darwin.pkg=1485843b8c0f53e3b50dd277aef08d2669a01ce6485bacf202c8f24fbebaf623 +dist/2026-09-29/rust-nightly-x86_64-apple-darwin.pkg=62ef2681dc83414c208c981949efbfc007b9b9ac8ab1bee776b3ed42130f2fe5 +dist/2026-09-29/rustc-nightly-src.tar.gz=54f78062b491bb27ba1eeedcf59fe8f0ce7c4e30189613af34b711feb4839ff8 +dist/2026-09-29/rustc-nightly-src.tar.xz=5d38310ee84c42e638094781bf1ec5456977fdc64021a83c8e0779d04371159a From 4c11abbbd2daf20b8351e47091950a4d99e62973 Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 29 Sep 2026 07:40:38 -0400 Subject: [PATCH 1027/1309] Step cfg(bootstrap) --- compiler/rustc_arena/src/lib.rs | 1 - compiler/rustc_ast_ir/src/lib.rs | 1 - compiler/rustc_attr_ir/src/attribute_docs.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 1 - compiler/rustc_codegen_llvm/src/common.rs | 48 ++++++++--------- compiler/rustc_codegen_llvm/src/lib.rs | 1 - compiler/rustc_const_eval/src/lib.rs | 1 - compiler/rustc_data_structures/src/lib.rs | 4 +- compiler/rustc_driver_impl/src/lib.rs | 1 - compiler/rustc_hir/src/lib.rs | 1 - compiler/rustc_hir_analysis/src/lib.rs | 1 - compiler/rustc_hir_typeck/src/lib.rs | 2 - compiler/rustc_lint_defs/src/builtin.rs | 7 ++- compiler/rustc_macros/src/lib.rs | 1 - compiler/rustc_metadata/src/lib.rs | 1 - compiler/rustc_middle/src/lib.rs | 4 +- .../rustc_middle/src/ty/inhabitedness/mod.rs | 2 - compiler/rustc_mir_dataflow/src/lib.rs | 1 - compiler/rustc_mir_transform/src/inline.rs | 2 +- .../rustc_pattern_analysis/src/constructor.rs | 1 - compiler/rustc_resolve/src/late.rs | 2 - compiler/rustc_resolve/src/lib.rs | 1 - compiler/rustc_serialize/src/lib.rs | 1 - compiler/rustc_trait_selection/src/lib.rs | 1 - compiler/rustc_transmute/src/lib.rs | 1 - compiler/rustc_ty_utils/src/lib.rs | 1 - library/alloc/src/vec/mod.rs | 5 +- library/proc_macro/src/lib.rs | 1 - library/std/src/os/windows/process.rs | 15 ++---- src/librustdoc/doctest.rs | 52 +++++-------------- src/librustdoc/lib.rs | 3 +- src/tools/clippy/clippy_lints/src/lib.rs | 1 - src/tools/miri/src/lib.rs | 1 - 33 files changed, 49 insertions(+), 119 deletions(-) diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs index f2c6ffe44cdfd..4c9258b753d8f 100644 --- a/compiler/rustc_arena/src/lib.rs +++ b/compiler/rustc_arena/src/lib.rs @@ -10,7 +10,6 @@ // tidy-alphabetical-start #![allow(clippy::mut_from_ref)] // Arena allocators are one place where this pattern is fine. #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(bootstrap, feature(unwrap_infallible))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/compiler/rustc_ast_ir/src/lib.rs b/compiler/rustc_ast_ir/src/lib.rs index e919e7df99ee0..dc2bf67d338e7 100644 --- a/compiler/rustc_ast_ir/src/lib.rs +++ b/compiler/rustc_ast_ir/src/lib.rs @@ -7,7 +7,6 @@ // tidy-alphabetical-start #![cfg_attr(feature = "nightly", allow(internal_features))] -#![cfg_attr(feature = "nightly", cfg_attr(bootstrap, feature(never_type)))] #![cfg_attr(feature = "nightly", feature(rustc_attrs))] // tidy-alphabetical-end diff --git a/compiler/rustc_attr_ir/src/attribute_docs.rs b/compiler/rustc_attr_ir/src/attribute_docs.rs index a2b00c90b3028..975594771d3fb 100644 --- a/compiler/rustc_attr_ir/src/attribute_docs.rs +++ b/compiler/rustc_attr_ir/src/attribute_docs.rs @@ -12,7 +12,7 @@ macro_rules! include_example { }; } -#[cfg_attr(not(bootstrap), doc(attribute = "rustc_dump_clauses"))] +#[doc(attribute = "rustc_dump_clauses")] /// Dumps the list of [`ty::Clause`]s as computed by the [`clauses_of`] query. /// /// See [`AttributeKind::RustcDumpClauses`] for the internal representation of this attribute. diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c35c7ab311572..514c06141db73 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -2,7 +2,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(never_type))] #![feature(default_field_values)] #![feature(deref_patterns)] #![feature(file_buffered)] diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs index 7a05bf718663c..a5a4f0b3ddb25 100644 --- a/compiler/rustc_codegen_llvm/src/common.rs +++ b/compiler/rustc_codegen_llvm/src/common.rs @@ -67,30 +67,30 @@ pub(crate) fn maybe_sign_fn_ptr<'ll, 'tcx>( } /* -* A note on nomenclature of linking: "extern", "foreign", and "upcall". -* -* An "extern" is an LLVM symbol we wind up emitting an undefined external -* reference to. This means "we don't have the thing in this compilation unit, -* please make sure you link it in at runtime". This could be a reference to -* C code found in a C library, or rust code found in a rust crate. -* -* Most "externs" are implicitly declared (automatically) as a result of a -* user declaring an extern _module_ dependency; this causes the rust driver -* to locate an extern crate, scan its compilation metadata, and emit extern -* declarations for any symbols used by the declaring crate. -* -* A "foreign" is an extern that references C (or other non-rust ABI) code. -* There is no metadata to scan for extern references so in these cases either -* a header-digester like bindgen, or manual function prototypes, have to -* serve as declarators. So these are usually given explicitly as prototype -* declarations, in rust code, with ABI attributes on them noting which ABI to -* link via. -* -* An "upcall" is a foreign call generated by the compiler (not corresponding -* to any user-written call in the code) into the runtime library, to perform -* some helper task such as bringing a task to life, allocating memory, etc. -* -*/ + * A note on nomenclature of linking: "extern", "foreign", and "upcall". + * + * An "extern" is an LLVM symbol we wind up emitting an undefined external + * reference to. This means "we don't have the thing in this compilation unit, + * please make sure you link it in at runtime". This could be a reference to + * C code found in a C library, or rust code found in a rust crate. + * + * Most "externs" are implicitly declared (automatically) as a result of a + * user declaring an extern _module_ dependency; this causes the rust driver + * to locate an extern crate, scan its compilation metadata, and emit extern + * declarations for any symbols used by the declaring crate. + * + * A "foreign" is an extern that references C (or other non-rust ABI) code. + * There is no metadata to scan for extern references so in these cases either + * a header-digester like bindgen, or manual function prototypes, have to + * serve as declarators. So these are usually given explicitly as prototype + * declarations, in rust code, with ABI attributes on them noting which ABI to + * link via. + * + * An "upcall" is a foreign call generated by the compiler (not corresponding + * to any user-written call in the code) into the runtime library, to perform + * some helper task such as bringing a task to life, allocating memory, etc. + * + */ /// A structure representing an active landing pad for the duration of a basic /// block. diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs index 19bbf0cf3d8d8..93ef87eea026d 100644 --- a/compiler/rustc_codegen_llvm/src/lib.rs +++ b/compiler/rustc_codegen_llvm/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(trim_prefix_suffix))] #![feature(extern_types)] #![feature(file_buffered)] #![feature(impl_trait_in_assoc_type)] diff --git a/compiler/rustc_const_eval/src/lib.rs b/compiler/rustc_const_eval/src/lib.rs index a853dd63d3435..981813f13c97f 100644 --- a/compiler/rustc_const_eval/src/lib.rs +++ b/compiler/rustc_const_eval/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![feature(array_try_map)] #![feature(decl_macro)] #![feature(deref_patterns)] diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs index 4ebd6ef9f92b3..aae378939452b 100644 --- a/compiler/rustc_data_structures/src/lib.rs +++ b/compiler/rustc_data_structures/src/lib.rs @@ -10,12 +10,10 @@ #![allow(internal_features)] #![allow(rustc::default_hash_types)] #![allow(rustc::potential_query_instability)] -#![cfg_attr(bootstrap, feature(allocator_api))] -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(bootstrap, feature(unwrap_infallible))] -#![cfg_attr(not(bootstrap), feature(allocator_ext))] #![cfg_attr(test, feature(test))] #![deny(unsafe_op_in_unsafe_fn)] +#![feature(allocator_ext)] #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(auto_traits)] diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 210f04a115831..7940dc3978496 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(trim_prefix_suffix))] #![feature(decl_macro)] #![feature(file_buffered)] #![feature(panic_backtrace_config)] diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs index 92ef008610098..0f6041b44b2f2 100644 --- a/compiler/rustc_hir/src/lib.rs +++ b/compiler/rustc_hir/src/lib.rs @@ -3,7 +3,6 @@ //! [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(const_default)] diff --git a/compiler/rustc_hir_analysis/src/lib.rs b/compiler/rustc_hir_analysis/src/lib.rs index c0abcc3a6119a..1cd9d008194fc 100644 --- a/compiler/rustc_hir_analysis/src/lib.rs +++ b/compiler/rustc_hir_analysis/src/lib.rs @@ -56,7 +56,6 @@ This API is completely unstable and subject to change. */ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(default_field_values)] #![feature(gen_blocks)] diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs index 474a390171514..5efb2775c77fe 100644 --- a/compiler/rustc_hir_typeck/src/lib.rs +++ b/compiler/rustc_hir_typeck/src/lib.rs @@ -1,6 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] -#![cfg_attr(bootstrap, feature(trim_prefix_suffix))] #![feature(deref_patterns)] #![feature(iter_intersperse)] #![feature(iter_order_by)] diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 2a0901e0243b6..a722f0e103ea1 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -2825,8 +2825,7 @@ declare_lint! { /// /// ### Example /// - #[cfg_attr(bootstrap, doc = "```rust,ignore")] - #[cfg_attr(not(bootstrap), doc = "```rust,compile_fail")] + /// ```rust,compile_fail /// #![feature(staged_api)] /// #![stable(feature = "test", since = "1.0.0")] /// @@ -2837,9 +2836,9 @@ declare_lint! { /// pub use self::S as T; /// /// fn main() {} - #[doc = "```"] + /// ``` /// - #[cfg_attr(not(bootstrap), doc = "{{produces}}")] + /// {{produces}} /// /// ### Explanation /// diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index 09c5717c21213..d9fd054fdfdc4 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -3,7 +3,6 @@ rustc::default_hash_types, reason = "we like performance but can't use `rustc_data_structures`" )] -#![cfg_attr(bootstrap, feature(never_type))] #![deny( rustc::potential_query_instability, reason = "macros shall produce deterministic output/errors" diff --git a/compiler/rustc_metadata/src/lib.rs b/compiler/rustc_metadata/src/lib.rs index dd963fc8773c7..1706fece29a8b 100644 --- a/compiler/rustc_metadata/src/lib.rs +++ b/compiler/rustc_metadata/src/lib.rs @@ -1,6 +1,5 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(never_type))] #![feature(error_iter)] #![feature(file_buffered)] #![feature(gen_blocks)] diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index 5acf9e150bb5c..d964faa30b1f8 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,10 +27,8 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] -#![cfg_attr(bootstrap, feature(allocator_api))] -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(doc, feature(intra_doc_pointers))] -#![cfg_attr(not(bootstrap), feature(allocator_ext))] +#![feature(allocator_ext)] #![feature(associated_type_defaults)] #![feature(closure_track_caller)] #![feature(const_default)] diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 078a171491520..1133b87002450 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -5,7 +5,6 @@ //! //! # Example //! ```rust -#![cfg_attr(bootstrap, doc = "#![feature(never_type)]")] //! mod a { //! pub mod b { //! pub struct SecretlyUninhabited { @@ -175,7 +174,6 @@ impl<'tcx> Ty<'tcx> { /// /// # Example /// ``` - #[cfg_attr(bootstrap, doc = "#![feature(never_type)]")] /// # fn main() {} /// enum Void {} /// mod a { diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 07e42459c7a99..8e320e0982077 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -1,5 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![feature(associated_type_defaults)] #![feature(deref_patterns)] #![feature(exact_size_is_empty)] diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index 9547b5bb93dff..38021f4b76a4d 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -1161,7 +1161,7 @@ fn new_call_temp<'tcx>( * Integrates blocks from the callee function into the calling function. * Updates block indices, references to locals and other control flow * stuff. -*/ + */ struct Integrator<'a, 'tcx> { args: &'a [Local], new_locals: RangeFrom, diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs index 6deec10071a16..0f636f323e5fd 100644 --- a/compiler/rustc_pattern_analysis/src/constructor.rs +++ b/compiler/rustc_pattern_analysis/src/constructor.rs @@ -114,7 +114,6 @@ //! //! ```rust //! # #![feature(exhaustive_patterns)] -#![cfg_attr(feature = "rustc", cfg_attr(bootstrap, doc = "#![feature(never_type)]"))] //! # let x = None::; //! match x { //! None => {} diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 620e6d3cd9ac6..5e3c236de7fff 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -4097,7 +4097,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// `Result` could look like: /// ```rust /// # #![feature(never_patterns)] - #[cfg_attr(bootstrap, doc = "#![feature(never_type)]")] /// # fn bar(_x: u32) {} /// let foo: Result = Ok(0); /// match foo { @@ -4163,7 +4162,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { /// `Result` could look like: /// ```rust /// # #![feature(never_patterns)] - #[cfg_attr(bootstrap, doc = "#![feature(never_type)]")] /// # fn foo() -> Result { Ok(true) } /// let (Ok(x) | Err(&!)) = foo(); /// # let _ = x; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 772fdb8c9f14d..b496f1a0057c3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -8,7 +8,6 @@ // tidy-alphabetical-start #![allow(internal_features)] -#![cfg_attr(bootstrap, feature(trim_prefix_suffix))] #![feature(arbitrary_self_types)] #![feature(const_default)] #![feature(const_trait_impl)] diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs index ae7c3854d00b4..364ae2a10a1e7 100644 --- a/compiler/rustc_serialize/src/lib.rs +++ b/compiler/rustc_serialize/src/lib.rs @@ -3,7 +3,6 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::internal)] -#![cfg_attr(bootstrap, feature(never_type))] #![doc(test(attr(allow(unused_variables), deny(warnings))))] #![feature(core_intrinsics)] #![feature(min_specialization)] diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index a5cb7d0c7bb1a..9a3948f0ac440 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,7 +11,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index cb5a76b51df1b..a7b07529f0bd1 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -7,7 +7,6 @@ //! [`Condition`]s for the trait solver to discharge. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(test, feature(test))] #![feature(option_into_flat_iter)] // tidy-alphabetical-end diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs index ba37f7f72691a..2b4c17c5fb94c 100644 --- a/compiler/rustc_ty_utils/src/lib.rs +++ b/compiler/rustc_ty_utils/src/lib.rs @@ -5,7 +5,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(never_type))] #![feature(deref_patterns)] #![feature(iterator_try_collect)] #![feature(option_into_flat_iter)] diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 681f45609f2b3..8bcad62226a0b 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -436,10 +436,7 @@ mod sve_retain; #[rustc_insignificant_dtor] #[doc(alias = "list")] #[doc(alias = "vector")] -pub struct Vec< - T, - #[stable(feature = "allocator_api", since = "1.100.0")] A: Allocator = Global, -> { +pub struct Vec { buf: RawVec, len: usize, } diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs index a3709adfc2c37..886f258f8fe98 100644 --- a/library/proc_macro/src/lib.rs +++ b/library/proc_macro/src/lib.rs @@ -28,7 +28,6 @@ #![feature(rustc_attrs)] #![feature(extend_one)] #![feature(f16)] -#![cfg_attr(bootstrap, feature(mem_conjure_zst))] #![recursion_limit = "256"] #![allow(internal_features)] #![deny(ffi_unwind_calls)] diff --git a/library/std/src/os/windows/process.rs b/library/std/src/os/windows/process.rs index bdd2a38f2a443..971d88c65ea75 100644 --- a/library/std/src/os/windows/process.rs +++ b/library/std/src/os/windows/process.rs @@ -451,23 +451,14 @@ impl CommandExt for process::Command { } } -#[stable( - feature = "windows_process_extensions_main_thread_handle", - since = "1.100.0" -)] +#[stable(feature = "windows_process_extensions_main_thread_handle", since = "1.100.0")] pub impl(self) trait ChildExt { /// Extracts the main thread raw handle, without taking ownership - #[stable( - feature = "windows_process_extensions_main_thread_handle", - since = "1.100.0" - )] + #[stable(feature = "windows_process_extensions_main_thread_handle", since = "1.100.0")] fn main_thread_handle(&self) -> BorrowedHandle<'_>; } -#[stable( - feature = "windows_process_extensions_main_thread_handle", - since = "1.100.0" -)] +#[stable(feature = "windows_process_extensions_main_thread_handle", since = "1.100.0")] impl ChildExt for process::Child { fn main_thread_handle(&self) -> BorrowedHandle<'_> { self.handle.main_thread_handle() diff --git a/src/librustdoc/doctest.rs b/src/librustdoc/doctest.rs index 72895e1f2462f..c8d1cfd599909 100644 --- a/src/librustdoc/doctest.rs +++ b/src/librustdoc/doctest.rs @@ -423,33 +423,19 @@ pub(crate) fn run_tests( // `running 0 tests...`. if ran_edition_tests == 0 || !standalone_tests.is_empty() { standalone_tests.sort_by(|a, b| a.desc.name.as_slice().cmp(b.desc.name.as_slice())); - cfg_select! { - bootstrap => { - test::test_main_with_exit_callback(&test_args, standalone_tests, None, || { - let times = times.times_in_secs(); - // We ensure temp dir destructor is called. - std::mem::drop(temp_dir.take()); - if let Some((total_time, compilation_time)) = times { - test::print_merged_doctests_times(&test_args, total_time, compilation_time); - } - }); - } - _ => { - // We need a vector of `&TestDescAndFn`. - let standalone_test_refs = &standalone_tests.iter().collect::>(); - let exit = test::test_main(&test_args, standalone_test_refs); - let times = times.times_in_secs(); - // We ensure temp dir destructor is called. - std::mem::drop(standalone_tests); - std::mem::drop(temp_dir.take()); - if let Some((total_time, compilation_time)) = times { - test::print_merged_doctests_times(&test_args, total_time, compilation_time); - } - // Fall through on success, the caller may want to do more stuff. - if exit != std::process::ExitCode::SUCCESS { - exit.exit_process(); - } - } + // We need a vector of `&TestDescAndFn`. + let standalone_test_refs = &standalone_tests.iter().collect::>(); + let exit = test::test_main(&test_args, standalone_test_refs); + let times = times.times_in_secs(); + // We ensure temp dir destructor is called. + std::mem::drop(standalone_tests); + std::mem::drop(temp_dir.take()); + if let Some((total_time, compilation_time)) = times { + test::print_merged_doctests_times(&test_args, total_time, compilation_time); + } + // Fall through on success, the caller may want to do more stuff. + if exit != std::process::ExitCode::SUCCESS { + exit.exit_process(); } } else { // If the first condition branch exited successfully, it will @@ -1175,18 +1161,6 @@ fn generate_test_desc_and_fn( no_run: scraped_test.no_run(&rustdoc_options), test_type: test::TestType::DocTest, }, - #[cfg(bootstrap)] - testfn: test::DynTestFn(Box::new(move || { - doctest_run_fn( - &rustdoc_test_options, - &opts, - &test, - &scraped_test, - &rustdoc_options, - &unused_externs, - ) - })), - #[cfg(not(bootstrap))] testfn: test::DynTestFn(Arc::new(move || { doctest_run_fn( &rustdoc_test_options, diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b907c3ef2cb11..85bae04fcb2e8 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1,6 +1,4 @@ // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(trim_prefix_suffix))] -#![cfg_attr(not(bootstrap), feature(exitcode_exit_method))] #![doc( html_root_url = "https://doc.rust-lang.org/nightly/", html_playground_url = "https://play.rust-lang.org/" @@ -8,6 +6,7 @@ #![feature(ascii_char)] #![feature(ascii_char_variants)] #![feature(deref_patterns)] +#![feature(exitcode_exit_method)] #![feature(file_buffered)] #![feature(formatting_options)] #![feature(iter_intersperse)] diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs index 87bb44875aee9..0544f1bcac20f 100644 --- a/src/tools/clippy/clippy_lints/src/lib.rs +++ b/src/tools/clippy/clippy_lints/src/lib.rs @@ -7,7 +7,6 @@ #![feature(iter_partition_in_place)] #![feature(macro_metavar_expr)] #![feature(macro_metavar_expr_concat)] -#![cfg_attr(bootstrap, feature(never_type))] #![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(rustc_private)] #![feature(stmt_expr_attributes)] diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs index d1b3e1a1cf1f6..14684a5dcef84 100644 --- a/src/tools/miri/src/lib.rs +++ b/src/tools/miri/src/lib.rs @@ -14,7 +14,6 @@ #![feature(float_gamma)] #![feature(float_erf)] #![feature(map_try_insert)] -#![cfg_attr(bootstrap, feature(never_type))] #![feature(try_blocks)] #![feature(io_error_more)] #![feature(io_error_inprogress)] From 2eeeb39a9785812aa101e75486c88a7f5c4b0619 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 29 Sep 2026 22:41:25 +0000 Subject: [PATCH 1028/1309] Use more default field values in `Resolver` --- compiler/rustc_data_structures/src/fx.rs | 10 ++++- compiler/rustc_middle/src/middle/privacy.rs | 6 +-- compiler/rustc_resolve/src/lib.rs | 44 +++++++-------------- 3 files changed, 26 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_data_structures/src/fx.rs b/compiler/rustc_data_structures/src/fx.rs index cad775cc98641..76b2c428ec84d 100644 --- a/compiler/rustc_data_structures/src/fx.rs +++ b/compiler/rustc_data_structures/src/fx.rs @@ -28,7 +28,7 @@ macro_rules! define_stable_id_collections { } pub mod default { - use super::{FxBuildHasher, FxHashMap, FxHashSet}; + use super::{FxBuildHasher, FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; // FIXME: These two functions will become unnecessary after // lands and we start using the corresponding @@ -40,4 +40,12 @@ pub mod default { pub const fn fx_hash_set() -> FxHashSet { FxHashSet::with_hasher(FxBuildHasher) } + + pub const fn fx_index_map() -> FxIndexMap { + FxIndexMap::with_hasher(FxBuildHasher) + } + + pub const fn fx_index_set() -> FxIndexSet { + FxIndexSet::with_hasher(FxBuildHasher) + } } diff --git a/compiler/rustc_middle/src/middle/privacy.rs b/compiler/rustc_middle/src/middle/privacy.rs index 9685ac89011e5..3a008514f7d07 100644 --- a/compiler/rustc_middle/src/middle/privacy.rs +++ b/compiler/rustc_middle/src/middle/privacy.rs @@ -5,7 +5,7 @@ use std::cmp::Ordering; use std::hash::Hash; -use rustc_data_structures::fx::{FxIndexMap, IndexEntry}; +use rustc_data_structures::fx::{FxIndexMap, IndexEntry, default}; use rustc_data_structures::stable_hash::{StableHash, StableHashCtxt, StableHasher}; use rustc_hir::def::DefKind; use rustc_hir::{ItemKind, Node, UseKind, UseTree}; @@ -277,9 +277,9 @@ impl EffectiveVisibilities { } } -impl Default for EffectiveVisibilities { +const impl Default for EffectiveVisibilities { fn default() -> Self { - EffectiveVisibilities { map: Default::default() } + EffectiveVisibilities { map: default::fx_index_map() } } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 772fdb8c9f14d..fc151de0decf9 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1417,11 +1417,11 @@ pub struct Resolver<'ra, 'tcx> { extern_module_map: RwLock>>, /// Maps glob imports to the names of items actually imported. - glob_map: FxIndexMap>, + glob_map: FxIndexMap> = default::fx_index_map(), glob_error: Option = None, visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(), used_imports: FxHashSet = default::fx_hash_set(), - maybe_unused_trait_imports: FxIndexSet, + maybe_unused_trait_imports: FxIndexSet = default::fx_index_set(), /// Privacy errors are delayed until the end in order to deduplicate them. privacy_errors: Vec> = Vec::new(), @@ -1442,7 +1442,7 @@ pub struct Resolver<'ra, 'tcx> { builtin_macros: FxHashMap = default::fx_hash_map(), registered_attr_tools: &'tcx RegisteredTools, registered_lint_tools: &'tcx RegisteredTools, - macro_use_prelude: FxIndexMap>, + macro_use_prelude: FxIndexMap> = default::fx_index_map(), /// Eagerly populated map of all local macro definitions. local_macro_map: FxHashMap> = default::fx_hash_map(), /// Lazily populated cache of macro definitions loaded from external crates. @@ -1452,9 +1452,9 @@ pub struct Resolver<'ra, 'tcx> { non_macro_attr: &'ra Arc, local_macro_def_scopes: FxHashMap> = default::fx_hash_map(), ast_transform_scopes: FxHashMap> = default::fx_hash_map(), - unused_macros: FxIndexMap, + unused_macros: FxIndexMap = default::fx_index_map(), /// A map from the macro to all its potentially unused arms and the `LocalDefId` of the macro itself. - unused_macro_rules: FxIndexMap)>, + unused_macro_rules: FxIndexMap)> = default::fx_index_map(), proc_macro_stubs: FxHashSet = default::fx_hash_set(), /// Traces collected during macro resolution and validated when it's complete. single_segment_macro_resolutions: @@ -1521,25 +1521,25 @@ pub struct Resolver<'ra, 'tcx> { /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any. item_required_generic_args_suggestions: FxHashMap = default::fx_hash_map(), delegation_fn_sigs: LocalDefIdMap = Default::default(), - delegation_infos: FxIndexMap, - delegation_inherent_fn_map: FxIndexMap>, + delegation_infos: FxIndexMap = default::fx_index_map(), + delegation_inherent_fn_map: FxIndexMap> = default::fx_index_map(), main_def: Option = None, - trait_impls: FxIndexMap>, + trait_impls: FxIndexMap> = default::fx_index_map(), /// A list of proc macro LocalDefIds, written out in the order in which /// they are declared in the static array generated by proc_macro_harness. proc_macros: Vec = Vec::new(), - paths_matching_assoc_types: UnordSet, - confused_type_with_std_module: FxIndexMap, + paths_matching_assoc_types: UnordSet = Default::default(), + confused_type_with_std_module: FxIndexMap = default::fx_index_map(), /// Names of items that were stripped out via cfg with their corresponding cfg meta item. stripped_cfg_items: Vec> = Vec::new(), - effective_visibilities: EffectiveVisibilities, - macro_reachable_adts: FxIndexMap>, + effective_visibilities: EffectiveVisibilities = Default::default(), + macro_reachable_adts: FxIndexMap> = default::fx_index_map(), - doc_link_resolutions: FxIndexMap, - doc_link_traits_in_scope: FxIndexMap>, + doc_link_resolutions: FxIndexMap = default::fx_index_map(), + doc_link_traits_in_scope: FxIndexMap> = default::fx_index_map(), all_macro_rules: UnordSet = Default::default(), /// Invocation ids of all glob delegations. @@ -1852,9 +1852,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { local_module_map, extern_module_map: Default::default(), - glob_map: Default::default(), - maybe_unused_trait_imports: Default::default(), - arenas, dummy_decl: arenas.new_pub_def_decl(Res::Err, DUMMY_SP, LocalExpnId::ROOT), builtin_type_decls: PrimTy::ALL @@ -1883,31 +1880,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .collect(), registered_attr_tools, registered_lint_tools, - macro_use_prelude: Default::default(), extern_macro_map: Default::default(), dummy_ext_bang: arenas.alloc_macro(SyntaxExtension::dummy_bang(edition)), dummy_ext_derive: arenas.alloc_macro(SyntaxExtension::dummy_derive(edition)), non_macro_attr: arenas.alloc_macro(SyntaxExtension::non_macro_attr(edition)), - unused_macros: Default::default(), - unused_macro_rules: Default::default(), single_segment_macro_resolutions: Default::default(), multi_segment_macro_resolutions: Default::default(), lint_buffer: LintBuffer::default(), owners, current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID, CRATE_DEF_ID), invocation_parents, - trait_impls: Default::default(), - confused_type_with_std_module: Default::default(), - paths_matching_assoc_types: Default::default(), - stripped_cfg_items: Default::default(), - effective_visibilities: Default::default(), - macro_reachable_adts: Default::default(), - doc_link_resolutions: Default::default(), - doc_link_traits_in_scope: Default::default(), current_crate_outer_attr_insert_span, disambiguators: Default::default(), - delegation_infos: Default::default(), - delegation_inherent_fn_map: Default::default(), features: tcx.features(), .. }; From 728205bd952173da7d3dcf617205d78d7818b7f6 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Tue, 29 Sep 2026 22:55:17 -0400 Subject: [PATCH 1029/1309] Forbid `Reborrow` impls for types with destructors Construction of such types should never be so implicit. --- .../rustc_hir_analysis/src/coherence/builtin.rs | 15 ++++++++++++++- compiler/rustc_hir_analysis/src/diagnostics.rs | 7 ++++--- tests/ui/reborrow/reborrow-drop.rs | 14 ++++++++++++++ tests/ui/reborrow/reborrow-drop.stderr | 15 +++++++++++++++ 4 files changed, 47 insertions(+), 4 deletions(-) create mode 100644 tests/ui/reborrow/reborrow-drop.rs create mode 100644 tests/ui/reborrow/reborrow-drop.stderr diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs index efed5994f63fe..e7f20766bc8eb 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs @@ -115,7 +115,11 @@ fn visit_implementation_of_copy(checker: &Checker<'_>) -> Result<(), ErrorGuaran Err(CopyImplementationError::HasDestructor(did)) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; let impl_ = tcx.def_span(did); - Err(tcx.dcx().emit_err(diagnostics::CopyImplOnTypeWithDtor { span, impl_ })) + Err(tcx.dcx().emit_err(diagnostics::TraitImplOnTypeWithDtor { + span, + impl_, + trait_name: sym::Copy, + })) } Err(CopyImplementationError::HasUnsafeFields) => { let span = tcx.hir_expect_item(impl_did).expect_impl().self_ty.span; @@ -537,6 +541,15 @@ pub(crate) fn reborrow_info<'tcx>( assert_field_type_is_copy(tcx, &infcx, impl_did, param_env, field.ty, field.span)?; } + if let Some(did) = def.destructor(tcx).map(|dtor| dtor.did) { + let impl_ = tcx.def_span(did); + return Err(tcx.dcx().emit_err(diagnostics::TraitImplOnTypeWithDtor { + span, + impl_, + trait_name: sym::Reborrow, + })); + } + Ok(()) } diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index ff5f7dbb119f1..e4f7f2d9229fc 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -292,13 +292,14 @@ pub(crate) struct FieldAlreadyDeclaredNestedHelp { } #[derive(Diagnostic)] -#[diag("the trait `Copy` cannot be implemented for this type; the type has a destructor", code = E0184)] -pub(crate) struct CopyImplOnTypeWithDtor { +#[diag("the trait `{$trait_name}` cannot be implemented for this type; the type has a destructor", code = E0184)] +pub(crate) struct TraitImplOnTypeWithDtor { #[primary_span] - #[label("`Copy` not allowed on types with destructors")] + #[label("`{$trait_name}` not allowed on types with destructors")] pub span: Span, #[note("destructor declared here")] pub impl_: Span, + pub trait_name: Symbol, } #[derive(Diagnostic)] diff --git a/tests/ui/reborrow/reborrow-drop.rs b/tests/ui/reborrow/reborrow-drop.rs new file mode 100644 index 0000000000000..bc88bb79b9b4b --- /dev/null +++ b/tests/ui/reborrow/reborrow-drop.rs @@ -0,0 +1,14 @@ +//@ compile-flags: --crate-type=lib + +#![feature(reborrow)] + +use std::marker::Reborrow; + +struct MyMut<'a>(&'a mut ()); + +impl Reborrow for MyMut<'_> {} +//~^ ERROR the trait `Reborrow` cannot be implemented for this type; the type has a destructor [E0184] + +impl Drop for MyMut<'_> { + fn drop(&mut self) {} +} diff --git a/tests/ui/reborrow/reborrow-drop.stderr b/tests/ui/reborrow/reborrow-drop.stderr new file mode 100644 index 0000000000000..d35b36530d588 --- /dev/null +++ b/tests/ui/reborrow/reborrow-drop.stderr @@ -0,0 +1,15 @@ +error[E0184]: the trait `Reborrow` cannot be implemented for this type; the type has a destructor + --> $DIR/reborrow-drop.rs:9:1 + | +LL | impl Reborrow for MyMut<'_> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Reborrow` not allowed on types with destructors + | +note: destructor declared here + --> $DIR/reborrow-drop.rs:13:5 + | +LL | fn drop(&mut self) {} + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0184`. From a5e0df2d551723906c68eda7e0e7ce399db4629e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Sep 2026 16:47:32 +1000 Subject: [PATCH 1030/1309] Remove `rustc_middle::ty::cast::IntTy` Currently it covers "int-like" types: integers, integer inference variables, bools, chars, and C-like enums. It's a bit weird, especially the asymmetry between the fielded `U` and fieldless `I` variants. This commit merges it into `CastTy`, and adds an `is_int_like` method. Some of the checking is now more strict, accepting only ints where before it accepted int-likes (e.g. casting a bool to a ptr) in `TypeChecker::visit_rvalue` and `mir_cast_kind`. `CastCheck::do_check` already rejects these int-like cases, which means they can't occur in MIR built from THIR. The only way to hit the stricter checking is in custom MIR. The commit also removes some unused derives from `CastKind` and fixes a couple of stale comments. --- compiler/rustc_borrowck/src/type_check/mod.rs | 10 ++-- compiler/rustc_hir_typeck/src/cast.rs | 29 ++++----- compiler/rustc_middle/src/ty/cast.rs | 59 +++++++++---------- 3 files changed, 48 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0a6fb9d5da47a..0e8565aef3f0b 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1361,7 +1361,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => (), + (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int)) => (), _ => { span_mirbug!( self, @@ -1379,7 +1379,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => (), + (Some(CastTy::Int), Some(CastTy::Ptr(_))) => (), _ => { span_mirbug!( self, @@ -1396,7 +1396,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => (), + (Some(from), Some(to)) if from.is_int_like() && to.is_int_like() => (), _ => { span_mirbug!( self, @@ -1413,7 +1413,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::Int(_)), Some(CastTy::Float)) => (), + (Some(CastTy::Int), Some(CastTy::Float)) => (), _ => { span_mirbug!( self, @@ -1430,7 +1430,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { let cast_ty_from = CastTy::from_ty(ty_from); let cast_ty_to = CastTy::from_ty(*ty); match (cast_ty_from, cast_ty_to) { - (Some(CastTy::Float), Some(CastTy::Int(_))) => (), + (Some(CastTy::Float), Some(CastTy::Int)) => (), _ => { span_mirbug!( self, diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 02e6b8188a876..7eced89c95341 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -912,7 +912,6 @@ impl<'a, 'tcx> CastCheck<'tcx> { /// directly. coercion-cast is handled in check instead of here. fn do_check(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result> { use rustc_middle::ty::cast::CastTy::*; - use rustc_middle::ty::cast::IntTy::*; let (t_from, t_cast) = match (CastTy::from_ty(self.expr_ty), CastTy::from_ty(self.cast_ty)) { @@ -947,7 +946,7 @@ impl<'a, 'tcx> CastCheck<'tcx> { // a cast. ty::Ref(_, inner_ty, mutbl) => { return match t_cast { - Int(_) | Float => match *inner_ty.kind() { + Int | CEnum | Bool | Char | Float => match *inner_ty.kind() { ty::Int(_) | ty::Uint(_) | ty::Float(_) @@ -979,19 +978,21 @@ impl<'a, 'tcx> CastCheck<'tcx> { } match (t_from, t_cast) { // These types have invariants! can't cast into them. - (_, Int(CEnum) | FnPtr) => Err(CastError::NonScalar), + (_, CEnum | FnPtr) => Err(CastError::NonScalar), // * -> Bool - (_, Int(Bool)) => Err(CastError::CastToBool), + (_, Bool) => Err(CastError::CastToBool), // * -> Char - (Int(U(ty::UintTy::U8)), Int(Char)) => Ok(CastKind::U8CharCast), // u8-char-cast - (_, Int(Char)) => Err(CastError::CastToChar), + (Int, Char) if self.expr_ty == fcx.tcx.types.u8 => { + Ok(CastKind::U8CharCast) // u8-char-cast + } + (_, Char) => Err(CastError::CastToChar), // prim -> float,ptr - (Int(Bool) | Int(CEnum) | Int(Char), Float) => Err(CastError::NeedViaInt), + (Bool | CEnum | Char, Float) => Err(CastError::NeedViaInt), - (Int(Bool) | Int(CEnum) | Int(Char) | Float, Ptr(_)) | (Ptr(_) | FnPtr, Float) => { + (Bool | CEnum | Char | Float, Ptr(_)) | (Ptr(_) | FnPtr, Float) => { Err(CastError::IllegalCast) } @@ -999,24 +1000,24 @@ impl<'a, 'tcx> CastCheck<'tcx> { (Ptr(m_e), Ptr(m_c)) => self.check_ptr_ptr_cast(fcx, m_e, m_c), // ptr-ptr-cast // ptr-addr-cast - (Ptr(m_expr), Int(_)) => self.check_ptr_addr_cast(fcx, m_expr), + (Ptr(m_expr), Int) => self.check_ptr_addr_cast(fcx, m_expr), - (FnPtr, Int(_)) => { + (FnPtr, Int) => { // FIXME(#95489): there should eventually be a lint for these casts Ok(CastKind::FnPtrAddrCast) } // addr-ptr-cast - (Int(_), Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), + (Int, Ptr(mt)) => self.check_addr_ptr_cast(fcx, mt), // fn-ptr-cast (FnPtr, Ptr(mt)) => self.check_fptr_ptr_cast(fcx, mt), // enum -> int - (Int(CEnum), Int(_)) => self.check_enum_cast(fcx), + (CEnum, Int) => self.check_enum_cast(fcx), // prim -> prim - (Int(Char) | Int(Bool), Int(_)) => Ok(CastKind::PrimIntCast), + (Char | Bool, Int) => Ok(CastKind::PrimIntCast), - (Int(_) | Float, Int(_) | Float) => Ok(CastKind::NumericCast), + (Int | Float, Int | Float) => Ok(CastKind::NumericCast), } } diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index e53f53d5e5648..32af08eaaadb3 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -1,29 +1,20 @@ -// Helpers for handling cast expressions, used in both -// typeck and codegen. +// Helpers for handling cast expressions. -use rustc_macros::{StableHash, TyDecodable, TyEncodable}; use rustc_span::bug; use crate::mir; use crate::ty::{self, Ty}; -/// Types that are represented as ints. +/// Valid types for the result of a non-coercion cast #[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum IntTy { - U(ty::UintTy), - I, +pub enum CastTy<'tcx> { + /// `iN`, `uN`, and integer inference variables. + Int, + /// C-like (fieldless) enums. CEnum, Bool, Char, -} - -// Valid types for the result of a non-coercion cast -#[derive(Copy, Clone, Debug, PartialEq, Eq)] -pub enum CastTy<'tcx> { - /// Various types that are represented as ints and handled mostly - /// in the same way, merged for easier matching. - Int(IntTy), - /// Floating-point types. + /// `fN` and float inference variables. Float, /// Function pointers. FnPtr, @@ -32,8 +23,8 @@ pub enum CastTy<'tcx> { } /// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) -/// (or rustc_hir_analysis/check/cast.rs). -#[derive(Copy, Clone, Debug, TyEncodable, TyDecodable, StableHash)] +/// (or rustc_hir_typeck/src/cast.rs). +#[derive(Copy, Clone, Debug)] pub enum CastKind { PtrPtrCast, PtrAddrCast, @@ -52,19 +43,23 @@ impl<'tcx> CastTy<'tcx> { /// Casts like unsizing casts will return `None`. pub fn from_ty(t: Ty<'tcx>) -> Option> { match *t.kind() { - ty::Bool => Some(CastTy::Int(IntTy::Bool)), - ty::Char => Some(CastTy::Int(IntTy::Char)), - ty::Int(_) => Some(CastTy::Int(IntTy::I)), - ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int(IntTy::I)), - ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), - ty::Uint(u) => Some(CastTy::Int(IntTy::U(u))), - ty::Float(_) => Some(CastTy::Float), - ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::Int(IntTy::CEnum)), + ty::Bool => Some(CastTy::Bool), + ty::Char => Some(CastTy::Char), + ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)) => Some(CastTy::Int), + ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)) => Some(CastTy::Float), + ty::Adt(d, _) if d.is_enum() && d.is_payloadfree() => Some(CastTy::CEnum), ty::RawPtr(ty, mutbl) => Some(CastTy::Ptr(ty::TypeAndMut { ty, mutbl })), ty::FnPtr(..) => Some(CastTy::FnPtr), _ => None, } } + + pub fn is_int_like(self) -> bool { + match self { + CastTy::Int | CastTy::CEnum | CastTy::Bool | CastTy::Char => true, + CastTy::Float | CastTy::FnPtr | CastTy::Ptr(_) => false, + } + } } /// Returns `mir::CastKind` from the given parameters. @@ -72,15 +67,17 @@ pub fn mir_cast_kind<'tcx>(from_ty: Ty<'tcx>, cast_ty: Ty<'tcx>) -> mir::CastKin let from = CastTy::from_ty(from_ty); let cast = CastTy::from_ty(cast_ty); let cast_kind = match (from, cast) { - (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int(_))) => { + (Some(from), Some(cast)) if from.is_int_like() && cast.is_int_like() => { + mir::CastKind::IntToInt + } + (Some(CastTy::Ptr(_) | CastTy::FnPtr), Some(CastTy::Int)) => { mir::CastKind::PointerExposeProvenance } - (Some(CastTy::Int(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance, - (Some(CastTy::Int(_)), Some(CastTy::Int(_))) => mir::CastKind::IntToInt, + (Some(CastTy::Int), Some(CastTy::Ptr(_))) => mir::CastKind::PointerWithExposedProvenance, (Some(CastTy::FnPtr), Some(CastTy::Ptr(_))) => mir::CastKind::FnPtrToPtr, - (Some(CastTy::Float), Some(CastTy::Int(_))) => mir::CastKind::FloatToInt, - (Some(CastTy::Int(_)), Some(CastTy::Float)) => mir::CastKind::IntToFloat, + (Some(CastTy::Float), Some(CastTy::Int)) => mir::CastKind::FloatToInt, + (Some(CastTy::Int), Some(CastTy::Float)) => mir::CastKind::IntToFloat, (Some(CastTy::Float), Some(CastTy::Float)) => mir::CastKind::FloatToFloat, (Some(CastTy::Ptr(_)), Some(CastTy::Ptr(_))) => mir::CastKind::PtrToPtr, From 9bdf58f54fc2ec1fc735276789b103c81529dba6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Sep 2026 20:45:28 +1000 Subject: [PATCH 1031/1309] Move `rustc_middle::ty::cast::CastKind` It's not used in `rustc_middle`, it's only used in `rustc_hir_typeck` and clippy. (It's always good to remove things from `rustc_middle`.) --- compiler/rustc_hir_typeck/src/cast.rs | 18 +++++++++++++++++- compiler/rustc_middle/src/ty/cast.rs | 16 ---------------- .../transmutes_expressible_as_ptr_casts.rs | 3 +-- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs index 7eced89c95341..14cb73e28c871 100644 --- a/compiler/rustc_hir_typeck/src/cast.rs +++ b/compiler/rustc_hir_typeck/src/cast.rs @@ -39,7 +39,7 @@ use rustc_lint_defs::builtin::{TRIVIAL_CASTS, TRIVIAL_NUMERIC_CASTS}; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::mir::Mutability; use rustc_middle::ty::adjustment::AllowTwoPhase; -use rustc_middle::ty::cast::{CastKind, CastTy}; +use rustc_middle::ty::cast::CastTy; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeAndMut, TypeVisitableExt, Unnormalized, VariantDef, elaborate, @@ -52,6 +52,22 @@ use tracing::{debug, instrument}; use super::FnCtxt; use crate::{diagnostics, type_error_struct}; +/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) +/// (or rustc_hir_typeck/src/cast.rs). +#[derive(Copy, Clone, Debug)] +pub enum CastKind { + PtrPtrCast, + PtrAddrCast, + AddrPtrCast, + NumericCast, + EnumCast, + PrimIntCast, + U8CharCast, + ArrayPtrCast, + FnPtrPtrCast, + FnPtrAddrCast, +} + /// Reifies a cast check to be checked once we have full type information for /// a function context. #[derive(Debug)] diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index 32af08eaaadb3..fc8a6de5d232e 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -22,22 +22,6 @@ pub enum CastTy<'tcx> { Ptr(ty::TypeAndMut<'tcx>), } -/// Cast Kind. See [RFC 401](https://rust-lang.github.io/rfcs/0401-coercions.html) -/// (or rustc_hir_typeck/src/cast.rs). -#[derive(Copy, Clone, Debug)] -pub enum CastKind { - PtrPtrCast, - PtrAddrCast, - AddrPtrCast, - NumericCast, - EnumCast, - PrimIntCast, - U8CharCast, - ArrayPtrCast, - FnPtrPtrCast, - FnPtrAddrCast, -} - impl<'tcx> CastTy<'tcx> { /// Returns `Some` for integral/pointer casts. /// Casts like unsizing casts will return `None`. diff --git a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs index 18897fbb5b8f0..0f5adb8b983e2 100644 --- a/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs +++ b/src/tools/clippy/clippy_lints/src/transmute/transmutes_expressible_as_ptr_casts.rs @@ -4,10 +4,9 @@ use clippy_utils::sugg::Sugg; use rustc_ast::util::parser::ExprPrecedence; use rustc_errors::Applicability; use rustc_hir::{Expr, Node}; -use rustc_hir_typeck::cast::check_cast; +use rustc_hir_typeck::cast::{CastKind, check_cast}; use rustc_lint::LateContext; use rustc_middle::ty::Ty; -use rustc_middle::ty::cast::CastKind; /// Checks for `transmutes_expressible_as_ptr_casts` lint. /// Returns `true` if it's triggered, otherwise returns `false`. From f69dfad6d65f072818b77c17388c86215fbff6fb Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Wed, 30 Sep 2026 04:36:47 +0000 Subject: [PATCH 1032/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 5c543b0b8c73c7b72bc8284ced4fb22ead15734d. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 028e73378b28b..eb8c4fb20edfe 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5d8937173e7c40406c167f4e94737da8925333ad +5c543b0b8c73c7b72bc8284ced4fb22ead15734d From 62da50cc452bd8663c7f1824521cae4c4d38aad3 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:08:16 +1000 Subject: [PATCH 1033/1309] Change some `&mut` args to `&` --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 21ea02c8ff601..7a43fce90e715 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -406,7 +406,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { fn handle_rvalue( &self, rvalue: &Rvalue<'tcx>, - state: &mut State>, + state: &State>, ) -> ValueOrPlace> { let val = match rvalue { Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { @@ -617,7 +617,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { fn binary_op( &self, - state: &mut State>, + state: &State>, op: BinOp, left: &Operand<'tcx>, right: &Operand<'tcx>, @@ -677,7 +677,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { fn eval_operand( &self, op: &Operand<'tcx>, - state: &mut State>, + state: &State>, ) -> FlatSet> { let value = match self.handle_operand(op) { ValueOrPlace::Value(value) => value, From e3bc970807775bea850b9b51105f063ddd520aba Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:10:09 +1000 Subject: [PATCH 1034/1309] Remove an unnecessary lifetime --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 7a43fce90e715..af0cc0e44dca8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -234,11 +234,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { /// The effect of a successful function call return should not be /// applied here, see [`Analysis::apply_primary_terminator_effect`]. - fn handle_terminator<'mir>( - &self, - terminator: &'mir Terminator<'tcx>, - state: &mut State>, - ) { + fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State>) { match &terminator.kind { TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { // Effect is applied by `handle_call_return`. From 74bc419fdccea9844546f8b266f7d6632fb13289 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:21:41 +1000 Subject: [PATCH 1035/1309] Remove `assign_discr` It has a single call site, where it can be replaced with `insert_value_idx` because `flood_discr` and `find_discr` are already done. --- compiler/rustc_mir_dataflow/src/value_analysis.rs | 11 ----------- .../rustc_mir_transform/src/dataflow_const_prop.rs | 8 ++------ 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs index e213a295c0bd0..2acbbab220547 100644 --- a/compiler/rustc_mir_dataflow/src/value_analysis.rs +++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs @@ -214,17 +214,6 @@ impl State { } } - /// Helper method for assignments to a discriminant. - pub fn assign_discr(&mut self, target: PlaceRef<'_>, result: ValueOrPlace, map: &Map<'_>) - where - V: HasTop, - { - self.flood_discr(target, map); - if let Some(target) = map.find_discr(target) { - self.insert_idx(target, result, map); - } - } - /// Retrieve the value stored for a place, or `None` if it is not tracked. fn try_get(&self, place: PlaceRef<'_>, map: &Map<'_>) -> Option { let place = map.find(place)?; diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index af0cc0e44dca8..46e96b9158d0c 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -282,14 +282,10 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state: &mut State>, ) { state.flood_discr(place.as_ref(), &self.map); - if self.map.find_discr(place.as_ref()).is_some() { + if let Some(target) = self.map.find_discr(place.as_ref()) { let enum_ty = place.ty(self.local_decls, self.tcx).ty; if let Some(discr) = self.eval_discriminant(enum_ty, variant_index) { - state.assign_discr( - place.as_ref(), - ValueOrPlace::Value(FlatSet::Elem(discr)), - &self.map, - ); + state.insert_value_idx(target, FlatSet::Elem(discr), &self.map); } } } From befd45bb9862c85a5931a77a6888f413b64a963c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:46:29 +1000 Subject: [PATCH 1036/1309] Add and use `FlatSet::and_then` It's basically the same as `Option::and_then`. --- .../src/framework/lattice.rs | 11 ++++ .../src/dataflow_const_prop.rs | 57 +++++++------------ 2 files changed, 30 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_mir_dataflow/src/framework/lattice.rs b/compiler/rustc_mir_dataflow/src/framework/lattice.rs index 919e346bda747..4566d8e9732da 100644 --- a/compiler/rustc_mir_dataflow/src/framework/lattice.rs +++ b/compiler/rustc_mir_dataflow/src/framework/lattice.rs @@ -104,6 +104,17 @@ pub enum FlatSet { Top, } +impl FlatSet { + #[inline] + pub fn and_then(self, f: impl FnOnce(T) -> FlatSet) -> FlatSet { + match self { + FlatSet::Elem(elem) => f(elem), + FlatSet::Bottom => FlatSet::Bottom, + FlatSet::Top => FlatSet::Top, + } + } +} + impl JoinSemiLattice for FlatSet { fn join(&mut self, other: &Self) -> bool { let result = match (&*self, other) { diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 46e96b9158d0c..40d4fc3508301 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -405,36 +405,26 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; - match self.eval_operand(operand, state) { - FlatSet::Elem(op) => self - .ecx + self.eval_operand(operand, state).and_then(|op| { + self.ecx .int_to_int_or_float(&op, layout) .discard_err() - .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)), - FlatSet::Bottom => FlatSet::Bottom, - FlatSet::Top => FlatSet::Top, - } + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) + }) } Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { return ValueOrPlace::Value(FlatSet::Top); }; - match self.eval_operand(operand, state) { - FlatSet::Elem(op) => self - .ecx + self.eval_operand(operand, state).and_then(|op| { + self.ecx .float_to_float_or_int(&op, layout) .discard_err() - .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)), - FlatSet::Bottom => FlatSet::Bottom, - FlatSet::Top => FlatSet::Top, - } + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) + }) } Rvalue::Cast(CastKind::Transmute | CastKind::Subtype, operand, _) => { - match self.eval_operand(operand, state) { - FlatSet::Elem(op) => self.wrap_immediate(*op), - FlatSet::Bottom => FlatSet::Bottom, - FlatSet::Top => FlatSet::Top, - } + self.eval_operand(operand, state).and_then(|op| self.wrap_immediate(*op)) } Rvalue::BinaryOp(op, (left, right)) if !op.is_overflowing() => { // Overflows must be ignored here. @@ -449,15 +439,12 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { { return ValueOrPlace::Place(len); } - match self.eval_operand(operand, state) { - FlatSet::Elem(value) => self - .ecx + self.eval_operand(operand, state).and_then(|value| { + self.ecx .unary_op(*op, &value) .discard_err() - .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)), - FlatSet::Bottom => FlatSet::Bottom, - FlatSet::Top => FlatSet::Top, - } + .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)) + }) } Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map), Rvalue::Use(operand, _) => return self.handle_operand(operand), @@ -675,18 +662,12 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { ValueOrPlace::Value(value) => value, ValueOrPlace::Place(place) => state.get_idx(place, &self.map), }; - match value { - FlatSet::Top => FlatSet::Top, - FlatSet::Elem(scalar) => { - let ty = op.ty(self.local_decls, self.tcx); - self.tcx - .layout_of(self.typing_env.as_query_input(ty)) - .map_or(FlatSet::Top, |layout| { - FlatSet::Elem(ImmTy::from_scalar(scalar, layout)) - }) - } - FlatSet::Bottom => FlatSet::Bottom, - } + value.and_then(|scalar| { + let ty = op.ty(self.local_decls, self.tcx); + self.tcx + .layout_of(self.typing_env.as_query_input(ty)) + .map_or(FlatSet::Top, |layout| FlatSet::Elem(ImmTy::from_scalar(scalar, layout))) + }) } fn eval_discriminant(&self, enum_ty: Ty<'tcx>, variant_index: VariantIdx) -> Option { From fea72a058cda1988635b59e99290916942123ab8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 25 Aug 2026 21:48:15 +1000 Subject: [PATCH 1037/1309] Merge `ConstAnalysis::handle_rvalue` into `handle_assign` `handle_assign` handles several `Rvalue` variants, and then falls through to the only call site of `handle_rvalue`, which handles all the `Rvalue` variants. The `Use`, `CopyForDeref`, and `Aggregate` arms in `handle_rvalue` are unreachable because those variants are fully handled by `handle_assign` This commit just inlines and removes `handle_rvalue`, which makes the control flow simpler and avoids the unreachable arms. --- .../src/dataflow_const_prop.rs | 137 +++++++++--------- 1 file changed, 68 insertions(+), 69 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 40d4fc3508301..cacd5aab5b0e0 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -296,12 +296,13 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { rvalue: &Rvalue<'tcx>, state: &mut State>, ) { - match rvalue { + let result = match rvalue { Rvalue::Use(operand, _) => { state.flood(target.as_ref(), &self.map); if let Some(target) = self.map.find(target.as_ref()) { self.assign_operand(state, target, operand); } + return; } Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), Rvalue::Aggregate(kind, operands) => { @@ -347,27 +348,35 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state.insert_value_idx(discr_idx, FlatSet::Elem(discr_val), &self.map); } } + return; } - Rvalue::BinaryOp(op, (left, right)) if op.is_overflowing() => { - // Flood everything now, so we can use `insert_value_idx` directly later. - state.flood(target.as_ref(), &self.map); + Rvalue::BinaryOp(op, (left, right)) => { + if op.is_overflowing() { + // Flood everything now, so we can use `insert_value_idx` directly later. + state.flood(target.as_ref(), &self.map); - let Some(target) = self.map.find(target.as_ref()) else { return }; + let Some(target) = self.map.find(target.as_ref()) else { return }; - let value_target = self.map.apply(target, TrackElem::Field(0_u32.into())); - let overflow_target = self.map.apply(target, TrackElem::Field(1_u32.into())); + let value_target = self.map.apply(target, TrackElem::Field(0_u32.into())); + let overflow_target = self.map.apply(target, TrackElem::Field(1_u32.into())); - if value_target.is_some() || overflow_target.is_some() { - let (val, overflow) = self.binary_op(state, *op, left, right); + if value_target.is_some() || overflow_target.is_some() { + let (val, overflow) = self.binary_op(state, *op, left, right); - if let Some(value_target) = value_target { - // We have flooded `target` earlier. - state.insert_value_idx(value_target, val, &self.map); - } - if let Some(overflow_target) = overflow_target { - // We have flooded `target` earlier. - state.insert_value_idx(overflow_target, overflow, &self.map); + if let Some(value_target) = value_target { + // We have flooded `target` earlier. + state.insert_value_idx(value_target, val, &self.map); + } + if let Some(overflow_target) = overflow_target { + // We have flooded `target` earlier. + state.insert_value_idx(overflow_target, overflow, &self.map); + } } + return; + } else { + // Overflows must be ignored here. + let (val, _overflow) = self.binary_op(state, *op, left, right); + ValueOrPlace::Value(val) } } Rvalue::Cast( @@ -387,83 +396,73 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { { state.insert_value_idx(target_len, FlatSet::Elem(len.into()), &self.map); } + return; } - _ => { - let result = self.handle_rvalue(rvalue, state); - state.assign(target.as_ref(), result, &self.map); - } - } - } - - fn handle_rvalue( - &self, - rvalue: &Rvalue<'tcx>, - state: &State>, - ) -> ValueOrPlace> { - let val = match rvalue { Rvalue::Cast(CastKind::IntToInt | CastKind::IntToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { - return ValueOrPlace::Value(FlatSet::Top); - }; - self.eval_operand(operand, state).and_then(|op| { - self.ecx - .int_to_int_or_float(&op, layout) - .discard_err() - .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) - }) + ValueOrPlace::Value( + if let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) { + self.eval_operand(operand, state).and_then(|op| { + self.ecx + .int_to_int_or_float(&op, layout) + .discard_err() + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) + }) + } else { + FlatSet::Top + }, + ) } Rvalue::Cast(CastKind::FloatToInt | CastKind::FloatToFloat, operand, ty) => { - let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) else { - return ValueOrPlace::Value(FlatSet::Top); - }; - self.eval_operand(operand, state).and_then(|op| { - self.ecx - .float_to_float_or_int(&op, layout) - .discard_err() - .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) - }) + ValueOrPlace::Value( + if let Ok(layout) = self.tcx.layout_of(self.typing_env.as_query_input(*ty)) { + self.eval_operand(operand, state).and_then(|op| { + self.ecx + .float_to_float_or_int(&op, layout) + .discard_err() + .map_or(FlatSet::Top, |result| self.wrap_immediate(*result)) + }) + } else { + FlatSet::Top + }, + ) } Rvalue::Cast(CastKind::Transmute | CastKind::Subtype, operand, _) => { - self.eval_operand(operand, state).and_then(|op| self.wrap_immediate(*op)) - } - Rvalue::BinaryOp(op, (left, right)) if !op.is_overflowing() => { - // Overflows must be ignored here. - // The overflowing operators are handled in `handle_assign`. - let (val, _overflow) = self.binary_op(state, *op, left, right); - val + ValueOrPlace::Value( + self.eval_operand(operand, state).and_then(|op| self.wrap_immediate(*op)), + ) } Rvalue::UnaryOp(op, operand) => { if let UnOp::PtrMetadata = op && let Some(place) = operand.place() && let Some(len) = self.map.find_len(place.as_ref()) { - return ValueOrPlace::Place(len); + ValueOrPlace::Place(len) + } else { + ValueOrPlace::Value(self.eval_operand(operand, state).and_then(|value| { + self.ecx + .unary_op(*op, &value) + .discard_err() + .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)) + })) } - self.eval_operand(operand, state).and_then(|value| { - self.ecx - .unary_op(*op, &value) - .discard_err() - .map_or(FlatSet::Top, |val| self.wrap_immediate(*val)) - }) } - Rvalue::Discriminant(place) => state.get_discr(place.as_ref(), &self.map), - Rvalue::Use(operand, _) => return self.handle_operand(operand), - Rvalue::CopyForDeref(_) => bug!("`CopyForDeref` in runtime MIR"), + Rvalue::Discriminant(place) => { + ValueOrPlace::Value(state.get_discr(place.as_ref(), &self.map)) + } Rvalue::Ref(..) | Rvalue::Reborrow(..) | Rvalue::RawPtr(..) => { // We don't track such places. - return ValueOrPlace::TOP; + ValueOrPlace::TOP } Rvalue::Repeat(..) | Rvalue::ThreadLocalRef(..) | Rvalue::Cast(..) - | Rvalue::BinaryOp(..) - | Rvalue::Aggregate(..) | Rvalue::WrapUnsafeBinder(..) => { // No modification is possible through these r-values. - return ValueOrPlace::TOP; + ValueOrPlace::TOP } }; - ValueOrPlace::Value(val) + // For the arms that didn't return early. + state.assign(target.as_ref(), result, &self.map); } fn handle_constant(&self, constant: &ConstOperand<'tcx>) -> FlatSet { From 7891d159d13616ab19b767ae737d590f992cad55 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Aug 2026 12:07:12 +1000 Subject: [PATCH 1038/1309] Reduce visibilities --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index cacd5aab5b0e0..95978375f1ef6 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -725,7 +725,7 @@ struct Patch<'tcx> { } impl<'tcx> Patch<'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>) -> Self { + fn new(tcx: TyCtxt<'tcx>) -> Self { Self { tcx, before_effect: FxHashMap::default(), assignments: FxHashMap::default() } } @@ -742,7 +742,7 @@ struct Collector<'a, 'tcx> { } impl<'a, 'tcx> Collector<'a, 'tcx> { - pub(crate) fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: &'a Map<'tcx>) -> Self { + fn new(tcx: TyCtxt<'tcx>, body: &'a Body<'tcx>, map: &'a Map<'tcx>) -> Self { Self { patch: Patch::new(tcx), local_decls: &body.local_decls, From c18bf9c231f99cf1319372cb5df067459ff939f2 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Aug 2026 12:07:57 +1000 Subject: [PATCH 1039/1309] Replace a `matches!` with a method --- compiler/rustc_mir_transform/src/dataflow_const_prop.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 95978375f1ef6..0f1c8d859f7d8 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -625,7 +625,7 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { // Exactly one side is known, attempt some algebraic simplifications. (FlatSet::Elem(const_arg), _) | (_, FlatSet::Elem(const_arg)) => { let layout = const_arg.layout; - if !matches!(layout.backend_repr, rustc_abi::BackendRepr::Scalar(..)) { + if !layout.backend_repr.is_scalar() { return (FlatSet::Top, FlatSet::Top); } From 491b4c8e2bdb73b0c7051afeb8bf0d5a15e85956 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Wed, 26 Aug 2026 12:23:46 +1000 Subject: [PATCH 1040/1309] Inline and remove various `ConstAnalysis::handle_*` methods These all have a single call site and are tiny or small, and several are called from methods that are also tiny. (Too many small methods just spreads things out unnecessarily.) The only remaining `handle_*` methods are `handle_assign`, which is large, and `handle_operand`, which has multiple call sites. --- .../src/dataflow_const_prop.rs | 196 ++++++++---------- 1 file changed, 82 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs index 0f1c8d859f7d8..e52a9a847b119 100644 --- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs +++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs @@ -119,7 +119,51 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { _location: Location, ) { if state.is_reachable() { - self.handle_statement(statement, state); + match &statement.kind { + StatementKind::Assign((place, rvalue)) => { + self.handle_assign(*place, rvalue, state); + } + StatementKind::SetDiscriminant { place, variant_index } => { + let place = (**place).as_ref(); + state.flood_discr(place, &self.map); + if let Some(target) = self.map.find_discr(place) { + let enum_ty = place.ty(self.local_decls, self.tcx).ty; + if let Some(discr) = self.eval_discriminant(enum_ty, *variant_index) { + state.insert_value_idx(target, FlatSet::Elem(discr), &self.map); + } + } + } + StatementKind::Intrinsic(intrinsic) => { + match intrinsic { + NonDivergingIntrinsic::Assume(..) => { + // Could use this, but ignoring it is sound. + } + NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { + dst: _, + src: _, + count: _, + }) => { + // This statement represents `*dst = *src`, `count` times. + } + } + } + StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { + // StorageLive leaves the local in an uninitialized state. + // StorageDead makes it UB to access the local afterwards. + state.flood_with( + Place::from(*local).as_ref(), + &self.map, + FlatSet::::BOTTOM, + ); + } + StatementKind::ConstEvalCounter + | StatementKind::Nop + | StatementKind::FakeRead(..) + | StatementKind::PlaceMention(..) + | StatementKind::Coverage(..) + | StatementKind::BackwardIncompatibleDropHint { .. } + | StatementKind::AscribeUserType(..) => {} + } } } @@ -147,7 +191,34 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { _location: Location, ) { if state.is_reachable() { - self.handle_terminator(terminator, state) + match &terminator.kind { + TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { + // Effect is applied by `apply_call_return_effect`. + } + TerminatorKind::Drop { place, .. } => { + state.flood_with(place.as_ref(), &self.map, FlatSet::::BOTTOM); + } + TerminatorKind::Yield { .. } => { + // They would have an effect, but are not allowed in this phase. + bug!("encountered disallowed terminator"); + } + TerminatorKind::TailCall { .. } => { + // FIXME(explicit_tail_calls): determine if we need to do something here + // (probably not) + } + TerminatorKind::SwitchInt { .. } + | TerminatorKind::Goto { .. } + | TerminatorKind::UnwindResume + | TerminatorKind::UnwindTerminate(_) + | TerminatorKind::Return + | TerminatorKind::Unreachable + | TerminatorKind::Assert { .. } + | TerminatorKind::CoroutineDrop + | TerminatorKind::FalseEdge { .. } + | TerminatorKind::FalseUnwind { .. } => { + // These terminators have no effect on the analysis. + } + } } } @@ -158,7 +229,9 @@ impl<'tcx> Analysis<'tcx> for ConstAnalysis<'_, 'tcx> { return_places: CallReturnPlaces<'_, 'tcx>, ) { if state.is_reachable() { - self.handle_call_return(return_places, state) + return_places.for_each(|place| { + state.flood(place.as_ref(), &self.map); + }) } } } @@ -175,55 +248,15 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } - fn handle_statement(&self, statement: &Statement<'tcx>, state: &mut State>) { - match &statement.kind { - StatementKind::Assign((place, rvalue)) => { - self.handle_assign(*place, rvalue, state); - } - StatementKind::SetDiscriminant { place, variant_index } => { - self.handle_set_discriminant(**place, *variant_index, state); - } - StatementKind::Intrinsic(intrinsic) => { - self.handle_intrinsic(intrinsic); - } - StatementKind::StorageLive(local) | StatementKind::StorageDead(local) => { - // StorageLive leaves the local in an uninitialized state. - // StorageDead makes it UB to access the local afterwards. - state.flood_with( - Place::from(*local).as_ref(), - &self.map, - FlatSet::::BOTTOM, - ); - } - StatementKind::ConstEvalCounter - | StatementKind::Nop - | StatementKind::FakeRead(..) - | StatementKind::PlaceMention(..) - | StatementKind::Coverage(..) - | StatementKind::BackwardIncompatibleDropHint { .. } - | StatementKind::AscribeUserType(..) => {} - } - } - - fn handle_intrinsic(&self, intrinsic: &NonDivergingIntrinsic<'tcx>) { - match intrinsic { - NonDivergingIntrinsic::Assume(..) => { - // Could use this, but ignoring it is sound. - } - NonDivergingIntrinsic::CopyNonOverlapping(CopyNonOverlapping { - dst: _, - src: _, - count: _, - }) => { - // This statement represents `*dst = *src`, `count` times. - } - } - } - fn handle_operand(&self, operand: &Operand<'tcx>) -> ValueOrPlace> { match operand { Operand::RuntimeChecks(_) => ValueOrPlace::TOP, - Operand::Constant(constant) => ValueOrPlace::Value(self.handle_constant(constant)), + Operand::Constant(constant) => ValueOrPlace::Value( + constant + .const_ + .try_eval_scalar(self.tcx, self.typing_env) + .map_or(FlatSet::Top, FlatSet::Elem), + ), Operand::Copy(place) | Operand::Move(place) => { // On move, we would ideally flood the place with bottom. But with the current // framework this is not possible (similar to `InterpCx::eval_operand`). @@ -232,64 +265,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { } } - /// The effect of a successful function call return should not be - /// applied here, see [`Analysis::apply_primary_terminator_effect`]. - fn handle_terminator(&self, terminator: &Terminator<'tcx>, state: &mut State>) { - match &terminator.kind { - TerminatorKind::Call { .. } | TerminatorKind::InlineAsm { .. } => { - // Effect is applied by `handle_call_return`. - } - TerminatorKind::Drop { place, .. } => { - state.flood_with(place.as_ref(), &self.map, FlatSet::::BOTTOM); - } - TerminatorKind::Yield { .. } => { - // They would have an effect, but are not allowed in this phase. - bug!("encountered disallowed terminator"); - } - TerminatorKind::TailCall { .. } => { - // FIXME(explicit_tail_calls): determine if we need to do something here (probably - // not) - } - TerminatorKind::SwitchInt { .. } - | TerminatorKind::Goto { .. } - | TerminatorKind::UnwindResume - | TerminatorKind::UnwindTerminate(_) - | TerminatorKind::Return - | TerminatorKind::Unreachable - | TerminatorKind::Assert { .. } - | TerminatorKind::CoroutineDrop - | TerminatorKind::FalseEdge { .. } - | TerminatorKind::FalseUnwind { .. } => { - // These terminators have no effect on the analysis. - } - } - } - - fn handle_call_return( - &self, - return_places: CallReturnPlaces<'_, 'tcx>, - state: &mut State>, - ) { - return_places.for_each(|place| { - state.flood(place.as_ref(), &self.map); - }) - } - - fn handle_set_discriminant( - &self, - place: Place<'tcx>, - variant_index: VariantIdx, - state: &mut State>, - ) { - state.flood_discr(place.as_ref(), &self.map); - if let Some(target) = self.map.find_discr(place.as_ref()) { - let enum_ty = place.ty(self.local_decls, self.tcx).ty; - if let Some(discr) = self.eval_discriminant(enum_ty, variant_index) { - state.insert_value_idx(target, FlatSet::Elem(discr), &self.map); - } - } - } - fn handle_assign( &self, target: Place<'tcx>, @@ -465,13 +440,6 @@ impl<'a, 'tcx> ConstAnalysis<'a, 'tcx> { state.assign(target.as_ref(), result, &self.map); } - fn handle_constant(&self, constant: &ConstOperand<'tcx>) -> FlatSet { - constant - .const_ - .try_eval_scalar(self.tcx, self.typing_env) - .map_or(FlatSet::Top, FlatSet::Elem) - } - fn get_switch_int_edges<'mir>( &self, discr: &'mir Operand<'tcx>, From c81bc6ad96a7a843c686126c6238912bb27c4203 Mon Sep 17 00:00:00 2001 From: Samuel Tardieu Date: Thu, 28 May 2026 13:49:23 +0200 Subject: [PATCH 1041/1309] Move `clippy::exit` lint under `methods` --- clippy_lints/src/declared_lints.rs | 2 +- clippy_lints/src/exit.rs | 76 ------------------------------ clippy_lints/src/lib.rs | 2 - clippy_lints/src/methods/exit.rs | 24 ++++++++++ clippy_lints/src/methods/mod.rs | 55 +++++++++++++++++++++ 5 files changed, 80 insertions(+), 79 deletions(-) delete mode 100644 clippy_lints/src/exit.rs create mode 100644 clippy_lints/src/methods/exit.rs diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index da0bd90cc50c1..1729f9a3702f2 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -164,7 +164,6 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::excessive_nesting::EXCESSIVE_NESTING_INFO, crate::exhaustive_items::EXHAUSTIVE_ENUMS_INFO, crate::exhaustive_items::EXHAUSTIVE_STRUCTS_INFO, - crate::exit::EXIT_INFO, crate::explicit_write::EXPLICIT_WRITE_INFO, crate::extra_unused_type_parameters::EXTRA_UNUSED_TYPE_PARAMETERS_INFO, crate::fallible_impl_from::FALLIBLE_IMPL_FROM_INFO, @@ -383,6 +382,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::DOUBLE_ENDED_ITERATOR_LAST_INFO, crate::methods::DRAIN_COLLECT_INFO, crate::methods::ERR_EXPECT_INFO, + crate::methods::EXIT_INFO, crate::methods::EXPECT_FUN_CALL_INFO, crate::methods::EXPECT_USED_INFO, crate::methods::EXTEND_WITH_DRAIN_INFO, diff --git a/clippy_lints/src/exit.rs b/clippy_lints/src/exit.rs deleted file mode 100644 index 245d3bd8ec257..0000000000000 --- a/clippy_lints/src/exit.rs +++ /dev/null @@ -1,76 +0,0 @@ -use clippy_utils::diagnostics::span_lint; -use clippy_utils::sym; -use rustc_hir::{Expr, ExprKind, Item, ItemKind, OwnerNode}; -use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; - -declare_clippy_lint! { - /// ### What it does - /// Detects calls to the `exit()` function that are not in the `main` function. Calls to `exit()` - /// immediately terminate the program. - /// - /// ### Why restrict this? - /// `exit()` immediately terminates the program with no information other than an exit code. - /// This provides no means to troubleshoot a problem, and may be an unexpected side effect. - /// - /// Codebases may use this lint to require that all exits are performed either by panicking - /// (which produces a message, a code location, and optionally a backtrace) - /// or by calling `exit()` from `main()` (which is a single place to look). - /// - /// ### Good example - /// ```no_run - /// fn main() { - /// std::process::exit(0); - /// } - /// ``` - /// - /// ### Bad example - /// ```no_run - /// fn main() { - /// other_function(); - /// } - /// - /// fn other_function() { - /// std::process::exit(0); - /// } - /// ``` - /// - /// Use instead: - /// - /// ```ignore - /// // To provide a stacktrace and additional information - /// panic!("message"); - /// - /// // or a main method with a return - /// fn main() -> Result<(), i32> { - /// Ok(()) - /// } - /// ``` - #[clippy::version = "1.41.0"] - pub EXIT, - restriction, - "detects `std::process::exit` calls outside of `main`" -} - -declare_lint_pass!(Exit => [EXIT]); - -impl<'tcx> LateLintPass<'tcx> for Exit { - fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) { - if let ExprKind::Call(path_expr, [_]) = e.kind - && let ExprKind::Path(ref path) = path_expr.kind - && let Some(def_id) = cx.qpath_res(path, path_expr.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::process_exit, def_id) - && let parent = cx.tcx.hir_get_parent_item(e.hir_id) - && let OwnerNode::Item(Item{kind: ItemKind::Fn{ ident, .. }, ..}) = cx.tcx.hir_owner_node(parent) - // If the next item up is a function we check if it isn't named "main" - // and only then emit a linter warning - - // if you instead check for the parent of the `exit()` call being the entrypoint function, as this worked before, - // in compilation contexts like --all-targets (which include --tests), you get false positives - // because in a test context, main is not the entrypoint function - && ident.name != sym::main - && !e.span.in_external_macro(cx.tcx.sess.source_map()) - { - span_lint(cx, EXIT, e.span, "usage of `process::exit`"); - } - } -} diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 6d49f44b466b3..3e93e78cee63b 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -133,7 +133,6 @@ mod eta_reduction; mod excessive_bools; mod excessive_nesting; mod exhaustive_items; -mod exit; mod explicit_write; mod extra_unused_type_parameters; mod fallible_impl_from; @@ -690,7 +689,6 @@ rustc_lint::late_lint_methods!( Default: default::Default = ::default(), UnusedSelf: unused_self::UnusedSelf = unused_self::UnusedSelf::new(conf), DebugAssertWithMutCall: mutable_debug_assertion::DebugAssertWithMutCall = mutable_debug_assertion::DebugAssertWithMutCall, - Exit: exit::Exit = exit::Exit, ToDigitIsSome: to_digit_is_some::ToDigitIsSome = to_digit_is_some::ToDigitIsSome::new(conf), LargeStackArrays: large_stack_arrays::LargeStackArrays = large_stack_arrays::LargeStackArrays::new(conf), LargeConstArrays: large_const_arrays::LargeConstArrays = large_const_arrays::LargeConstArrays::new(conf), diff --git a/clippy_lints/src/methods/exit.rs b/clippy_lints/src/methods/exit.rs new file mode 100644 index 0000000000000..2c2f58abac2fc --- /dev/null +++ b/clippy_lints/src/methods/exit.rs @@ -0,0 +1,24 @@ +use clippy_utils::diagnostics::span_lint; +use clippy_utils::res::{MaybeDef as _, MaybeQPath as _}; +use clippy_utils::sym; +use rustc_hir::{Expr, Item, ItemKind, OwnerNode}; +use rustc_lint::LateContext; + +use super::EXIT; + +pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, func: &'tcx Expr<'_>) { + if func.res(cx).is_diag_item(cx, sym::process_exit) + && let parent = cx.tcx.hir_get_parent_item(expr.hir_id) + && let OwnerNode::Item(Item{kind: ItemKind::Fn{ ident, .. }, ..}) = cx.tcx.hir_owner_node(parent) + // If the next item up is a function we check if it isn't named "main" + // and only then emit a linter warning + + // if you instead check for the parent of the `exit()` call being the entrypoint function, as this worked before, + // in compilation contexts like --all-targets (which include --tests), you get false positives + // because in a test context, main is not the entrypoint function + && ident.name != sym::main + && !expr.span.in_external_macro(cx.tcx.sess.source_map()) + { + span_lint(cx, EXIT, expr.span, "usage of `process::exit`"); + } +} diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 342e258e2e764..8fd91f470c185 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -19,6 +19,7 @@ mod collapsible_str_replace; mod double_ended_iterator_last; mod drain_collect; mod err_expect; +mod exit; mod expect_fun_call; mod extend_with_drain; mod filetype_is_file; @@ -628,6 +629,54 @@ declare_clippy_lint! { r#"using `.err().expect("")` when `.expect_err("")` can be used"# } +declare_clippy_lint! { + /// ### What it does + /// Detects calls to the `exit()` function that are not in the `main` function. Calls to `exit()` + /// immediately terminate the program. + /// + /// ### Why restrict this? + /// `exit()` immediately terminates the program with no information other than an exit code. + /// This provides no means to troubleshoot a problem, and may be an unexpected side effect. + /// + /// Codebases may use this lint to require that all exits are performed either by panicking + /// (which produces a message, a code location, and optionally a backtrace) + /// or by calling `exit()` from `main()` (which is a single place to look). + /// + /// ### Good example + /// ```no_run + /// fn main() { + /// std::process::exit(0); + /// } + /// ``` + /// + /// ### Bad example + /// ```no_run + /// fn main() { + /// other_function(); + /// } + /// + /// fn other_function() { + /// std::process::exit(0); + /// } + /// ``` + /// + /// Use instead: + /// + /// ```ignore + /// // To provide a stacktrace and additional information + /// panic!("message"); + /// + /// // or a main method with a return + /// fn main() -> Result<(), i32> { + /// Ok(()) + /// } + /// ``` + #[clippy::version = "1.41.0"] + pub EXIT, + restriction, + "detects `std::process::exit` calls outside of `main`" +} + declare_clippy_lint! { /// ### What it does /// Checks for calls to `.expect(&format!(...))`, `.expect(foo(..))`, @@ -5019,6 +5068,7 @@ impl_lint_pass!(Methods => [ DOUBLE_ENDED_ITERATOR_LAST, DRAIN_COLLECT, ERR_EXPECT, + EXIT, EXPECT_FUN_CALL, EXPECT_USED, EXTEND_WITH_DRAIN, @@ -5231,6 +5281,11 @@ impl<'tcx> LateLintPass<'tcx> for Methods { } fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) { + if let ExprKind::Call(func, _) = expr.kind { + // The functions from this block perform their own macro context checks + exit::check(cx, expr, func); + } + if expr.span.from_expansion() { return; } From 9970383a9bece341e44dc49dc45b98e10a83e6dc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 1 Sep 2026 11:14:08 +1000 Subject: [PATCH 1042/1309] Document `Result` case for the `arena_cache` query modifier --- compiler/rustc_middle/src/query/arena_cached.rs | 14 ++++++++------ compiler/rustc_middle/src/query/modifiers.rs | 9 ++++++--- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_middle/src/query/arena_cached.rs b/compiler/rustc_middle/src/query/arena_cached.rs index 4ab2fbe914965..8faf6f68f49c9 100644 --- a/compiler/rustc_middle/src/query/arena_cached.rs +++ b/compiler/rustc_middle/src/query/arena_cached.rs @@ -5,13 +5,15 @@ use rustc_span::ErrorGuaranteed; use crate::ty::TyCtxt; -/// Helper trait that allows `arena_cache` queries to return `Option<&T>` -/// instead of `&Option`, and avoid allocating `None` in the arena. +/// Helper trait that allows `arena_cache` queries to return: +/// - `Option<&T>` instead of `&Option`, and avoid allocating `None` in the arena; or +/// - `Result<&T, ErrorGuaranteed>` instead of `&Result`, and avoid allocating +/// `Err(ErrorGuaranteed)` in the arena. /// -/// An arena-cached query must be declared to return a type that implements -/// this trait, i.e. either `&'tcx T` or `Option<&'tcx T>`. This trait then -/// determines the types returned by the provider and stored in the arena, -/// and provides a function to bridge between the three types. +/// An arena-cached query must be declared to return a type that implements this trait, i.e. +/// `&'tcx T`, `Option<&'tcx T>`, or `Result<&'tcx T, ErrorGuaranteed>`. This trait then determines +/// the types returned by the provider and stored in the arena, and provides a function to bridge +/// between the three types. pub trait ArenaCached<'tcx>: Sized { /// Type that is returned by the query provider. type Provided; diff --git a/compiler/rustc_middle/src/query/modifiers.rs b/compiler/rustc_middle/src/query/modifiers.rs index 4fd91caa94cd7..3e057e96ddb6b 100644 --- a/compiler/rustc_middle/src/query/modifiers.rs +++ b/compiler/rustc_middle/src/query/modifiers.rs @@ -1,4 +1,5 @@ -//! This contains documentation which is linked from query modifiers used in the `rustc_queries!` proc macro. +//! This contains documentation which is linked from query modifiers used in the `rustc_queries!` +//! proc macro. //! //! The dummy items in this module are used to enable hover documentation for //! modifier names in the query list, and to allow find-all-references to list @@ -10,10 +11,12 @@ /// # `arena_cache` query modifier /// /// Query return values must impl `Copy` and be small, but some queries must return values that -/// doesn't meet those criteria. Queries marked with this modifier have their values allocated in -/// an arena and the query returns a reference to the value. There are two cases. +/// don't meet those criteria. Queries marked with this modifier have their values allocated in +/// an arena and the query returns a reference to the value. There are three cases. /// - If the provider function returns `T` then the query will return `&'tcx T`. /// - If the provider function returns `Option` then the query will return `Option<&'tcx T>`. +/// - If the provider function returns `Result` then the query will return +/// `Result<&'tcx T, ErrorGuaranteed>`. /// /// The query plumbing takes care of the arenas and the type manipulations. pub(crate) struct arena_cache; From 424d2426b0a8c879f9f9bfe32c99064f18f27bf6 Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Mon, 3 Aug 2026 05:26:13 +0100 Subject: [PATCH 1043/1309] Attribute documentation for cfg_attr --- library/core/src/attribute_docs.rs | 47 ++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 97629be8ec6ef..ead2efbcf17c6 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -707,3 +707,50 @@ const _: () = (); /// [Clippy]: https://github.com/rust-lang/rust-clippy /// [the `automatically_derived` attribute]: ../reference/attributes/derive.html#the-automatically_derived-attribute const _: () = (); + +#[doc(attribute = "cfg_attr")] +// +/// The `cfg_attr` attribute is used to conditionally apply one or more attributes to an item. +/// +/// Example: +/// +/// ```rust +/// // This function is annotated with `#[test]` only on Linux platforms. +/// #[cfg_attr(target_os = "linux", test)] +/// fn my_function() { +/// // ... +/// } +/// ``` +/// +/// You can apply multiple attributes by separating them with commas: +/// +/// ```rust +/// #[cfg_attr(feature = "nightly", allow(dead_code), deny(unused_variables))] +/// // This function only gets the `allow(dead_code)` and `deny(unused_variables)` attributes when +/// // `feature = "nightly"` is active. +/// fn nightly_only_function() { +/// let x = 42; +/// } +/// ``` +/// +/// For complex conditions, you can combine `all(...)`, `any(...)`, and `not(...)`. +/// +/// * `all`: True if all given predicates are true. +/// * `any`: True if at least one of the given predicates is true. +/// * `not`: True if the predicate is false. +/// +/// ```rust +/// #[cfg_attr( +/// all(feature = "system", feature = "disk"), +/// doc = "For module documentation, both `system`, and `disk` need to be enabled.". +/// )] +/// mod my_module { +/// // ... +/// } +/// ``` +/// +/// For more information, see the Reference on [the `cfg_attr` attribute]. +/// +/// [the `cfg` attribute]: ../reference/conditional-compilation.html#the-cfg-attribute +/// [the `cfg_attr` attribute]: ../reference/conditional-compilation.html#the-cfg_attr-attribute +const _: () = (); From 63a9c85be6a73c6f4d3b4b8668172d2beb4fd8b2 Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Mon, 3 Aug 2026 05:52:36 +0100 Subject: [PATCH 1044/1309] fix CI failure --- library/core/src/attribute_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index ead2efbcf17c6..c5f7f80d7e1c5 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -751,6 +751,6 @@ const _: () = (); /// /// For more information, see the Reference on [the `cfg_attr` attribute]. /// -/// [the `cfg` attribute]: ../reference/conditional-compilation.html#the-cfg-attribute +/// [the `cfg` attribute]: ./attribute.cfg.html /// [the `cfg_attr` attribute]: ../reference/conditional-compilation.html#the-cfg_attr-attribute const _: () = (); From 1e418da6e6e04e21d020d5dbef0037d628d69029 Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Mon, 3 Aug 2026 08:28:44 +0100 Subject: [PATCH 1045/1309] fix merge conflict --- library/core/src/attribute_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index c5f7f80d7e1c5..c2eb34ffa8bcb 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -751,6 +751,6 @@ const _: () = (); /// /// For more information, see the Reference on [the `cfg_attr` attribute]. /// -/// [the `cfg` attribute]: ./attribute.cfg.html +/// [`cfg`]: ./attribute.cfg.html /// [the `cfg_attr` attribute]: ../reference/conditional-compilation.html#the-cfg_attr-attribute const _: () = (); From 52fd615ddc6c0df634756f153596c0bdc0bf0af3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 07:30:48 +0200 Subject: [PATCH 1046/1309] use cfg_select in a few more places --- src/tools/miri/src/shims/unix/fs.rs | 98 +++++++++++++++-------------- 1 file changed, 51 insertions(+), 47 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 98a7c2ff3c2cf..da9738868de27 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -387,15 +387,16 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { }) } - #[cfg(unix)] fn host_permissions_from_mode(&self, mode: u32) -> InterpResult<'tcx, fs::Permissions> { - use std::os::unix::fs::PermissionsExt; - interp_ok(fs::Permissions::from_mode(mode)) - } - - #[cfg(not(unix))] - fn host_permissions_from_mode(&self, _mode: u32) -> InterpResult<'tcx, fs::Permissions> { - throw_unsup_format!("setting file permissions is only supported on Unix hosts") + cfg_select! { + unix => { + use std::os::unix::fs::PermissionsExt; + interp_ok(fs::Permissions::from_mode(mode)) + } + _ => { + throw_unsup_format!("setting file permissions is only supported on Unix hosts") + } + } } } @@ -481,20 +482,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { )?; let mode = this.read_scalar(mode)?.to_u32()?; - #[cfg(unix)] - { - // Support all modes on UNIX host - use std::os::unix::fs::OpenOptionsExt; - options.mode(mode); - } - #[cfg(not(unix))] - { - // Only support default mode for non-UNIX (i.e. Windows) host - if mode != 0o666 { - throw_unsup_format!( - "non-default mode 0o{:o} is not supported on non-Unix hosts", - mode - ); + cfg_select! { + unix => { + // Support all modes on UNIX host + use std::os::unix::fs::OpenOptionsExt; + options.mode(mode); + } + _ => { + // Only support default mode for non-UNIX (i.e. Windows) host + if mode != 0o666 { + throw_unsup_format!( + "non-default mode 0o{:o} is not supported on non-Unix hosts", + mode + ); + } } } @@ -523,20 +524,21 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let o_nofollow = this.eval_libc_i32("O_NOFOLLOW"); if flag & o_nofollow == o_nofollow { flag &= !o_nofollow; - #[cfg(unix)] - { - use std::os::unix::fs::OpenOptionsExt; - options.custom_flags(libc::O_NOFOLLOW); - } - // Strictly speaking, this emulation is not equivalent to the O_NOFOLLOW flag behavior: - // the path could change between us checking it here and the later call to `open`. - // But it's good enough for Miri purposes. - #[cfg(not(unix))] - { - // O_NOFOLLOW only fails when the trailing component is a symlink; - // the entire rest of the path can still contain symlinks. - if path.is_symlink() { - return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + cfg_select! { + unix => { + use std::os::unix::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); + } + _ => { + // Strictly speaking, this emulation is not equivalent to the O_NOFOLLOW flag behavior: + // the path could change between us checking it here and the later call to `open`. + // But it's good enough for Miri purposes. + + // O_NOFOLLOW only fails when the trailing component is a symlink; + // the entire rest of the path can still contain symlinks. + if path.is_symlink() { + return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + } } } } @@ -618,15 +620,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { target_op: &OpTy<'tcx>, linkpath_op: &OpTy<'tcx>, ) -> InterpResult<'tcx, Scalar> { - #[cfg(unix)] fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> { - std::os::unix::fs::symlink(src, dst) - } - - #[cfg(windows)] - fn create_link(src: &Path, dst: &Path) -> std::io::Result<()> { - use std::os::windows::fs; - if src.is_dir() { fs::symlink_dir(src, dst) } else { fs::symlink_file(src, dst) } + cfg_select! { + unix => std::os::unix::fs::symlink(src, dst), + windows => { + use std::os::windows::fs; + // This is racy, but not much we can do about that. + if src.is_dir() { + fs::symlink_dir(src, dst) + } else { + fs::symlink_file(src, dst) + } + } + } } let this = self.eval_context_mut(); @@ -1859,9 +1865,6 @@ fn extract_sec_and_nsec<'tcx>( } fn file_type_to_mode_name(file_type: std::fs::FileType) -> &'static str { - #[cfg(unix)] - use std::os::unix::fs::FileTypeExt; - if file_type.is_file() { "S_IFREG" } else if file_type.is_dir() { @@ -1872,6 +1875,7 @@ fn file_type_to_mode_name(file_type: std::fs::FileType) -> &'static str { // Certain file types are only available when the host is a Unix system. #[cfg(unix)] { + use std::os::unix::fs::FileTypeExt; if file_type.is_socket() { return "S_IFSOCK"; } else if file_type.is_fifo() { From b02b23fa962b4fade108ea1e7988172fa8f624b3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 07:39:01 +0200 Subject: [PATCH 1047/1309] windows host: use FILE_FLAG_OPEN_REPARSE_POINT to implement O_NOFOLLOW --- src/tools/miri/Cargo.lock | 1 + src/tools/miri/Cargo.toml | 5 +++ src/tools/miri/priroda/Cargo.lock | 1 + src/tools/miri/src/shims/unix/fs.rs | 36 +++++++++++-------- .../tests/pass-dep/libc/libc-fs-symlink.rs | 1 - 5 files changed, 28 insertions(+), 16 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index c71ec790d39fe..8cffd4defac3d 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -1023,6 +1023,7 @@ dependencies = [ "socket2", "tempfile", "ui_test", + "windows-sys", ] [[package]] diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml index 9f2a1e884fd70..1c52d35bf5bb2 100644 --- a/src/tools/miri/Cargo.toml +++ b/src/tools/miri/Cargo.toml @@ -48,6 +48,11 @@ capstone = { version = "0.14", features = ["arch_x86", "full"], default-features [target.'cfg(all(target_os = "linux", target_pointer_width = "64", target_endian = "little"))'.dependencies] genmc-sys = { path = "./genmc-sys/", version = "0.1.0", optional = true } +[target.'cfg(windows)'.dependencies] +windows-sys = { version = "0.61", features = [ + "Win32_Storage_FileSystem", +] } + [dev-dependencies] ui_test = "0.30.2" colored = "3" diff --git a/src/tools/miri/priroda/Cargo.lock b/src/tools/miri/priroda/Cargo.lock index 7b8ec9b0f08e6..a690264e158fc 100644 --- a/src/tools/miri/priroda/Cargo.lock +++ b/src/tools/miri/priroda/Cargo.lock @@ -689,6 +689,7 @@ dependencies = [ "serde", "smallvec", "socket2", + "windows-sys", ] [[package]] diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index da9738868de27..6baf24442e747 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -394,6 +394,7 @@ trait EvalContextExtPrivate<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(fs::Permissions::from_mode(mode)) } _ => { + let _ = mode; throw_unsup_format!("setting file permissions is only supported on Unix hosts") } } @@ -522,23 +523,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let o_nofollow = this.eval_libc_i32("O_NOFOLLOW"); + let mut nofollow = false; if flag & o_nofollow == o_nofollow { flag &= !o_nofollow; + nofollow = true; cfg_select! { unix => { use std::os::unix::fs::OpenOptionsExt; options.custom_flags(libc::O_NOFOLLOW); } - _ => { - // Strictly speaking, this emulation is not equivalent to the O_NOFOLLOW flag behavior: - // the path could change between us checking it here and the later call to `open`. - // But it's good enough for Miri purposes. - - // O_NOFOLLOW only fails when the trailing component is a symlink; - // the entire rest of the path can still contain symlinks. - if path.is_symlink() { - return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); - } + windows => { + use std::os::windows::fs::OpenOptionsExt; + options.custom_flags( + windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT, + ); } } } @@ -554,11 +552,19 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(ErrorKind::PermissionDenied); } - let fd = options - .open(path) - .map(|file| this.machine.fds.insert_new(FileHandle { file, writable, readable })); - - interp_ok(Scalar::from_i32(this.try_unwrap_io_result(fd)?)) + let file = match options.open(path) { + Ok(file) => file, + Err(err) => return this.set_errno_and_return_neg1_i32(err), + }; + if nofollow && !cfg!(unix) { + // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just + // opens the symlink rather than the target. Turn that into an error. + if file.metadata().unwrap().is_symlink() { + return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + } + } + let fd = this.machine.fds.insert_new(FileHandle { file, writable, readable }); + interp_ok(Scalar::from_i32(fd)) } fn lseek( diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs index 4fe66c338a045..ca67324ee1da2 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs @@ -1,5 +1,4 @@ // Symlink tests are separate since they don't in general work on a Windows host. -//@ignore-host: windows # creating symlinks requires admin permissions on Windows //@ignore-target: windows # File handling is not implemented yet //@compile-flags: -Zmiri-disable-isolation //@run-native From 25fef8822285a3ac0aa6ebfe05a307573708478f Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 09:04:06 +0200 Subject: [PATCH 1048/1309] move libc-fs tests back together we need the test coverage for symlink handling on windows hosts --- .../tests/pass-dep/libc/libc-fs-symlink.rs | 81 ------------------- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 81 ++++++++++++++++--- 2 files changed, 72 insertions(+), 90 deletions(-) delete mode 100644 src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs deleted file mode 100644 index ca67324ee1da2..0000000000000 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-symlink.rs +++ /dev/null @@ -1,81 +0,0 @@ -// Symlink tests are separate since they don't in general work on a Windows host. -//@ignore-target: windows # File handling is not implemented yet -//@compile-flags: -Zmiri-disable-isolation -//@run-native - -use std::ffi::CString; -use std::io::ErrorKind; -use std::os::unix::ffi::OsStrExt; - -#[path = "../../utils/libc.rs"] -mod libc_utils; -#[path = "../../utils/mod.rs"] -mod utils; -use libc_utils::errno_result; - -fn main() { - test_readlink(); - test_nofollow_symlink(); -} - -fn test_readlink() { - let bytes = b"Hello, World!\n"; - let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); - let expected_path = path.as_os_str().as_bytes(); - - let symlink_path = utils::prepare("miri_test_fs_symlink.txt"); - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - - // Test that the expected string gets written to a buffer of proper - // length, and that a trailing null byte is not written. - let symlink_c_str = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); - let symlink_c_ptr = symlink_c_str.as_ptr(); - - // Make the buf one byte larger than it needs to be, - // and check that the last byte is not overwritten. - let mut large_buf = vec![0xFF; expected_path.len() + 1]; - let res = errno_result(unsafe { - libc::readlink(symlink_c_ptr, large_buf.as_mut_ptr().cast(), large_buf.len()) - }) - .unwrap(); - // Check that the resolved path was properly written into the buf. - assert_eq!(&large_buf[..(large_buf.len() - 1)], expected_path); - assert_eq!(large_buf.last(), Some(&0xFF)); - assert_eq!(res, (large_buf.len() - 1) as isize); - - // Test that the resolved path is truncated if the provided buffer - // is too small. - let mut small_buf = [0u8; 2]; - let res = errno_result(unsafe { - libc::readlink(symlink_c_ptr, small_buf.as_mut_ptr().cast(), small_buf.len()) - }) - .unwrap(); - assert_eq!(small_buf, &expected_path[..small_buf.len()]); - assert_eq!(res, small_buf.len() as isize); - - // Test that we report a proper error for a missing path. - let err = errno_result(unsafe { - libc::readlink( - c"MIRI_MISSING_FILE_NAME".as_ptr(), - small_buf.as_mut_ptr().cast(), - small_buf.len(), - ) - }) - .unwrap_err(); - assert_eq!(err.kind(), ErrorKind::NotFound); -} - -fn test_nofollow_symlink() { - let path = utils::prepare_with_content("test_nofollow_symlink_target.txt", b"Hello, World!\n"); - - let symlink_path = utils::prepare("test_nofollow_symlink.txt"); - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - - let symlink_cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); - - let err = errno_result(unsafe { - libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) - }) - .unwrap_err(); - assert_eq!(err.raw_os_error(), Some(libc::ELOOP)); -} diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index d5418d3612a42..05b95e3ac7f50 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -31,6 +31,7 @@ fn main() { test_file_open_unix_needs_three_args(); test_file_open_unix_extra_third_arg(); test_file_open_dir(); + test_file_open_nofollow(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); test_posix_mkstemp(); @@ -55,7 +56,6 @@ fn main() { test_futimens(); test_isatty(); test_read_and_uninit(); - test_nofollow_not_symlink(); #[cfg(target_os = "macos")] test_ioctl(); test_opendir_closedir(); @@ -77,6 +77,7 @@ fn main() { #[cfg(not(target_os = "solaris"))] test_pwritev(); test_pwrite(); + test_readlink(); test_linkat(); } @@ -297,6 +298,29 @@ fn test_file_open_dir() { // errno_check(unsafe { libc::close(fd) }); } +fn test_file_open_nofollow() { + let bytes = b"Hello, World!\n"; + let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); + let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); + let fd = + errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }) + .unwrap(); + errno_check(unsafe { libc::close(fd) }); + + let path = utils::prepare_with_content("miri_test_open_nofollow_symlink_target.txt", bytes); + + let symlink_path = utils::prepare("miri_test_open_nofollow_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + + let symlink_cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + + let err = errno_result(unsafe { + libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) + }) + .unwrap_err(); + assert_eq!(err.raw_os_error(), Some(libc::ELOOP)); +} + fn test_dup_stdout_stderr() { let bytes = b"hello dup fd\n"; unsafe { @@ -959,14 +983,6 @@ fn test_read_and_uninit() { } } -fn test_nofollow_not_symlink() { - let bytes = b"Hello, World!\n"; - let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); - let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); - let ret = unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }; - assert!(ret >= 0); -} - #[cfg(target_os = "macos")] fn test_ioctl() { let path = utils::prepare_with_content("miri_test_libc_ioctl.txt", &[]); @@ -1381,6 +1397,53 @@ fn test_pwrite() { assert_eq!(&write_buffer[0..bytes_written], &read_buffer[OFFSET..(bytes_written + OFFSET)]); } +fn test_readlink() { + let bytes = b"Hello, World!\n"; + let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); + let expected_path = path.as_os_str().as_bytes(); + + let symlink_path = utils::prepare("miri_test_fs_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + + // Test that the expected string gets written to a buffer of proper + // length, and that a trailing null byte is not written. + let symlink_c_str = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + let symlink_c_ptr = symlink_c_str.as_ptr(); + + // Make the buf one byte larger than it needs to be, + // and check that the last byte is not overwritten. + let mut large_buf = vec![0xFF; expected_path.len() + 1]; + let res = errno_result(unsafe { + libc::readlink(symlink_c_ptr, large_buf.as_mut_ptr().cast(), large_buf.len()) + }) + .unwrap(); + // Check that the resolved path was properly written into the buf. + assert_eq!(&large_buf[..(large_buf.len() - 1)], expected_path); + assert_eq!(large_buf.last(), Some(&0xFF)); + assert_eq!(res, (large_buf.len() - 1) as isize); + + // Test that the resolved path is truncated if the provided buffer + // is too small. + let mut small_buf = [0u8; 2]; + let res = errno_result(unsafe { + libc::readlink(symlink_c_ptr, small_buf.as_mut_ptr().cast(), small_buf.len()) + }) + .unwrap(); + assert_eq!(small_buf, &expected_path[..small_buf.len()]); + assert_eq!(res, small_buf.len() as isize); + + // Test that we report a proper error for a missing path. + let err = errno_result(unsafe { + libc::readlink( + c"MIRI_MISSING_FILE_NAME".as_ptr(), + small_buf.as_mut_ptr().cast(), + small_buf.len(), + ) + }) + .unwrap_err(); + assert_eq!(err.kind(), ErrorKind::NotFound); +} + fn test_linkat() { let source = utils::prepare_with_content("miri_test_libc_linkat_source.txt", b"hello"); let link = utils::prepare("miri_test_libc_linkat_link.txt"); From c3c4a0ab08f174bd126172594217aab7e2b4dcec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 09:26:22 +0200 Subject: [PATCH 1049/1309] unix open: reject opening directories --- src/tools/miri/src/shims/unix/fs.rs | 6 ++- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 42 ++++--------------- 2 files changed, 14 insertions(+), 34 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 6baf24442e747..a00e18be7eccb 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -556,10 +556,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { Ok(file) => file, Err(err) => return this.set_errno_and_return_neg1_i32(err), }; + let metadata = file.metadata().expect("a just-opened file should have metadata"); + if metadata.is_dir() { + throw_unsup_format!("open: opening directories is not supported"); + } if nofollow && !cfg!(unix) { // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just // opens the symlink rather than the target. Turn that into an error. - if file.metadata().unwrap().is_symlink() { + if metadata.is_symlink() { return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); } } diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 05b95e3ac7f50..f6b6dc2a141d3 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -27,10 +27,9 @@ fn main() { test_ftruncate::(libc::ftruncate); #[cfg(target_os = "linux")] test_ftruncate::(libc::ftruncate64); - test_file_open_unix_allow_two_args(); - test_file_open_unix_needs_three_args(); - test_file_open_unix_extra_third_arg(); - test_file_open_dir(); + test_file_open_allow_two_args(); + test_file_open_needs_three_args(); + test_file_open_extra_third_arg(); test_file_open_nofollow(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); @@ -252,15 +251,15 @@ fn test_statx_empty_path_on_pipe() { } } -fn test_file_open_unix_allow_two_args() { - let path = utils::prepare_with_content("test_file_open_unix_allow_two_args.txt", &[]); +fn test_file_open_allow_two_args() { + let path = utils::prepare_with_content("test_file_open_allow_two_args.txt", &[]); let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap(); } -fn test_file_open_unix_needs_three_args() { - let path = utils::prepare_with_content("test_file_open_unix_needs_three_args.txt", &[]); +fn test_file_open_needs_three_args() { + let path = utils::prepare_with_content("test_file_open_needs_three_args.txt", &[]); let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); let _fd = @@ -268,36 +267,13 @@ fn test_file_open_unix_needs_three_args() { .unwrap(); } -fn test_file_open_unix_extra_third_arg() { - let path = utils::prepare_with_content("test_file_open_unix_extra_third_arg.txt", &[]); +fn test_file_open_extra_third_arg() { + let path = utils::prepare_with_content("test_file_open_extra_third_arg.txt", &[]); let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap(); } -fn test_file_open_dir() { - let dir_path = utils::prepare_dir("miri_test_fs_dir"); - create_dir(&dir_path).unwrap(); - let dir_name = CString::new(dir_path.into_os_string().into_encoded_bytes()).unwrap(); - - // Opening it for read-write fails. The error code differs between Unix and Windows hosts. - let err = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDWR) }).unwrap_err(); - assert!( - [libc::EISDIR, libc::EPERM].contains(&err.raw_os_error().unwrap()), - "unexpected errno: {err}" - ); - - // Opening it for reading succeeds, but then reading fails. - // FIXME: currently does not behave as expected on Windows hosts. - // See . - // let fd = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDONLY) }).unwrap(); - // let mut buf = [0u8; 4]; - // let err = - // errno_result(unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) }).unwrap_err(); - // assert_eq!(err.raw_os_error().unwrap(), libc::EISDIR, "unexpected errno: {err}"); - // errno_check(unsafe { libc::close(fd) }); -} - fn test_file_open_nofollow() { let bytes = b"Hello, World!\n"; let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); From 1850727e71e76b703665c5c0c6aebc554bf8a67b Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Wed, 30 Sep 2026 09:00:09 +0100 Subject: [PATCH 1050/1309] fix ci Signed-off-by: Emmanuel Ugwu --- library/core/src/attribute_docs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index c2eb34ffa8bcb..a96c7a1388bd1 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -742,7 +742,7 @@ const _: () = (); /// ```rust /// #[cfg_attr( /// all(feature = "system", feature = "disk"), -/// doc = "For module documentation, both `system`, and `disk` need to be enabled.". +/// doc = "For module documentation, both `system`, and `disk` need to be enabled.", /// )] /// mod my_module { /// // ... From 654d6642d918149742558744798c2cdce3996999 Mon Sep 17 00:00:00 2001 From: lcnr Date: Wed, 30 Sep 2026 08:56:04 +0200 Subject: [PATCH 1051/1309] add regression test --- ...-requires-resolving-regions.current.stderr | 26 +++++++++++++++ .../cycle-requires-resolving-regions.rs | 33 +++++++++++++++++++ 2 files changed, 59 insertions(+) create mode 100644 tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.current.stderr create mode 100644 tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.rs diff --git a/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.current.stderr b/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.current.stderr new file mode 100644 index 0000000000000..477b0ba993104 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.current.stderr @@ -0,0 +1,26 @@ +error[E0275]: overflow evaluating the requirement `Foo<'_>: Send` + --> $DIR/cycle-requires-resolving-regions.rs:31:5 + | +LL | require::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`cycle_requires_resolving_regions`) +note: required for `Foo<'_>` to implement `Send` + --> $DIR/cycle-requires-resolving-regions.rs:23:17 + | +LL | unsafe impl<'a> Send for Foo<'a> + | ^^^^ ^^^^^^^ +LL | where +LL | Foo<'a>: Send, + | ---- unsatisfied trait bound introduced here + = note: 128 redundant requirements hidden + = note: required for `Foo<'static>` to implement `Send` +note: required by a bound in `require` + --> $DIR/cycle-requires-resolving-regions.rs:28:15 + | +LL | fn require() {} + | ^^^^ required by this bound in `require` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.rs b/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.rs new file mode 100644 index 0000000000000..2e1eaff4b9479 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/cycle-requires-resolving-regions.rs @@ -0,0 +1,33 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +// A test showcasing a behavior change in cycle detection between +// the old and new solver. The old solver detects cycles in both +// fulfill and in evaluate. The cycle detection in fulfillment +// does not resolve regions. Each occurance of the `Foo<'a>: Send` +// impl creates a fresh inference variable even if it is later +// constrainted to `'static`. This means we never detect a cycle. +// +// This is not an issue with builtin auto-trait impls as they don't +// create impl args instead, simply using the generic arguments of +// the self type directly. +// +// The new solver properly resolves regions. The old solver does resolve +// regions in `project`, so there we do detect cycles even if there are +// fresh region variables. + +struct Foo<'a>(&'a ()); + +unsafe impl<'a> Send for Foo<'a> +where + Foo<'a>: Send, +{} + +fn require() {} + +fn main() { + require::>(); + //[current]~^ ERROR: overflow evaluating the requirement `Foo<'_>: Send` +} From 8a0412044ec61eb8da030f9949862dfd66a47a03 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 10:44:19 +0200 Subject: [PATCH 1052/1309] replace awkward wording --- src/doc/rustc-dev-guide/src/external-repos.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index fe0c0385d5f63..6f756fc8b890d 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -56,7 +56,7 @@ you should include fixes for those in the rustc PR as well. The [josh] tool is an alternative to git subtrees, which manages git history in a different way and scales better to larger repositories. Specific tooling is required to work with josh. -We provide a helper [`rustc-josh-sync`][josh-sync] tool to help with the synchronization, described [below](#synchronizing-a-josh-subtree). +We provide a helper tool, [`rustc-josh-sync`][josh-sync], to help with the synchronization, described [below](#synchronizing-a-josh-subtree). ### Synchronizing a Josh subtree From b7448a39255dd818099fb81c183594b7c474ebe4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 21:54:04 +0200 Subject: [PATCH 1053/1309] add fstatat test --- src/tools/miri/src/shims/unix/fs.rs | 10 +- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 119 ++++++++++++++---- src/tools/miri/tests/utils/fs.rs | 13 +- 3 files changed, 110 insertions(+), 32 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index a00e18be7eccb..d67d601df36c9 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -20,14 +20,14 @@ use crate::shims::sig::Varargs; use crate::shims::unix::fd::{EvalContextExt as _, FlockOp, UnixFileDescription}; use crate::*; -/// An open directory stream, tracked by DirTable. +/// An open directory stream (`DIR`), tracked by DirTable. #[derive(Debug)] struct DirStream { - /// The directory reader on the host. + /// The directory stream on the host. read_dir: fs::ReadDir, - /// An FD number for the same handle. Unix directory streams have an "underlying FD" that - /// can be exposed; this is that FD. We also store the FD ID to catch cases where - /// the FD was closed and a different one re-opened. + /// Unix directory streams have an "underlying FD" that can be exposed; this is that FD. This is + /// not a reference; it *can* be separately closed, leading to UB if the DIR is used again. We + /// also store the FD ID to catch cases where the FD was closed and a different one re-opened. fd_num: FdNum, fd_id: FdId, /// The "special" entries that must still be yielded by the iterator. diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index f6b6dc2a141d3..af67ca16bd2f1 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -5,10 +5,11 @@ use std::ffi::{CStr, CString, OsString}; use std::fs::{self, File, canonicalize, create_dir, remove_dir, remove_file}; use std::io::{ErrorKind, Write}; +use std::mem::MaybeUninit; use std::os::unix::ffi::OsStrExt; use std::os::unix::io::AsRawFd; use std::path::PathBuf; -use std::ptr; +use std::{env, ptr}; #[path = "../../utils/mod.rs"] mod utils; @@ -49,7 +50,11 @@ fn main() { test_fallocate::(libc::fallocate64); #[cfg(target_os = "linux")] test_sync_file_range(); + test_opendir_closedir(); + test_readdir(); + test_dirfd(); test_fstat(); + test_fstatat(); test_stat(); test_lstat(); test_futimens(); @@ -57,9 +62,6 @@ fn main() { test_read_and_uninit(); #[cfg(target_os = "macos")] test_ioctl(); - test_opendir_closedir(); - test_readdir(); - test_dirfd(); #[cfg(target_os = "linux")] test_statx_on_file_path(); #[cfg(target_os = "linux")] @@ -116,8 +118,6 @@ fn assert_statx_matches_metadata(stx: &libc::statx, meta: &fs::Metadata, expecte #[cfg(target_os = "linux")] fn test_statx_on_file_descriptor() { - use std::mem::MaybeUninit; - let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx_fd.txt", bytes); let file = File::open(&path).unwrap(); @@ -157,18 +157,20 @@ fn test_statx_on_file_descriptor() { #[cfg(target_os = "linux")] fn test_statx_on_file_path() { - use std::mem::MaybeUninit; - let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx.txt", bytes); let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); let meta = fs::metadata(&path).unwrap(); + // Relative to working directory. unsafe { + let old_cwd = env::current_dir().unwrap(); + env::set_current_dir(path.parent().unwrap()).unwrap(); + let mut stx = MaybeUninit::::zeroed(); errno_check(libc::statx( libc::AT_FDCWD, - c_path.as_ptr(), + c"miri_test_libc_statx.txt".as_ptr(), 0, libc::STATX_BASIC_STATS | libc::STATX_BTIME, stx.as_mut_ptr(), @@ -176,6 +178,8 @@ fn test_statx_on_file_path() { let stx = stx.assume_init(); assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + + env::set_current_dir(old_cwd).unwrap(); } // Setting AT_EMPTY_PATH is fine even if the path is not actually empty. @@ -218,7 +222,7 @@ fn test_statx_empty_path_on_pipe() { let mut fds = [0; 2]; errno_check(libc::pipe(fds.as_mut_ptr())); - let mut statx_buf = std::mem::MaybeUninit::::zeroed(); + let mut statx_buf = MaybeUninit::::zeroed(); errno_check(libc::statx( fds[0], @@ -770,7 +774,6 @@ fn test_sync_file_range() { } fn test_fstat() { - use std::mem::MaybeUninit; use std::os::unix::io::AsRawFd; let path = utils::prepare_with_content("miri_test_libc_fstat.txt", b"hello"); @@ -789,17 +792,97 @@ fn test_fstat() { check_stat_fields(stat); remove_file(&path).unwrap(); + + // Test it on a pipe as well. + unsafe { + let mut fds = [0; 2]; + errno_check(libc::pipe(fds.as_mut_ptr())); + + let mut stat = MaybeUninit::::uninit(); + errno_check(libc::fstat(fds[0], stat.as_mut_ptr())); + let stat = stat.assume_init_ref(); + + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFIFO); + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + assert_eq!(stat.st_size, 0); + + errno_check(libc::close(fds[0])); + errno_check(libc::close(fds[1])); + } +} + +fn test_fstatat() { + let testdir = utils::prepare_dir("test_fstatat"); + fs::create_dir(&testdir).unwrap(); + let filename = "file.txt"; + let cfilename = c"file.txt"; + fs::write(testdir.join(filename), b"hello").unwrap(); + let absfilename = testdir.join(filename); + assert!(absfilename.is_absolute()); + + // The only way to get a dirfd in Miri currently is via a `dirfd`. Slightly silly, but whatever. + let dirstream = unsafe { libc::opendir(utils::into_c_string(&testdir).as_ptr()) }; + assert!(!dirstream.is_null()); + let dirfd = unsafe { libc::dirfd(dirstream) }; + + let checkstat = |stat: &libc::stat| { + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFREG); + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + assert_eq!(stat.st_size, 5); + check_stat_fields(stat); + }; + + // Relative to working directory. + let old_cwd = env::current_dir().unwrap(); + env::set_current_dir(&testdir).unwrap(); + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { libc::fstatat(libc::AT_FDCWD, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }); + checkstat(unsafe { stat.assume_init_ref() }); + env::set_current_dir(old_cwd).unwrap(); + + // Absolute path, dirfd is ignored. + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { + libc::fstatat( + 999, // dirfd + utils::into_c_string(&absfilename).as_ptr(), + stat.as_mut_ptr(), + 0, // flags + ) + }); + checkstat(unsafe { stat.assume_init_ref() }); + + // Relative to dirfd. + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { libc::fstatat(dirfd, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }); + checkstat(unsafe { stat.assume_init_ref() }); + + // Symlink following. + let linkname = testdir.join("link"); + std::os::unix::fs::symlink(&absfilename, &linkname).unwrap(); + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), 0) }); + checkstat(unsafe { stat.assume_init_ref() }); + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { + libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), libc::AT_SYMLINK_NOFOLLOW) + }); + let stat = unsafe { stat.assume_init_ref() }; + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFLNK); // not S_IFREG! + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + check_stat_fields(stat); + + errno_check(unsafe { libc::closedir(dirstream) }); } fn test_stat() { - use std::mem::MaybeUninit; // Also make sure we *do* follow symlinks. let path = utils::prepare_with_content("miri_test_libc_stat.txt", b"hello"); let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - let cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + let cpath = utils::into_c_string(symlink_path); let mut stat = MaybeUninit::::uninit(); errno_check(unsafe { libc::stat(cpath.as_ptr(), stat.as_mut_ptr()) }); @@ -816,13 +899,11 @@ fn test_stat() { } fn test_lstat() { - use std::mem::MaybeUninit; - let path = utils::prepare_with_content("miri_test_libc_lstat.txt", b"hello"); let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - let cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + let cpath = utils::into_c_string(&symlink_path); let mut stat = MaybeUninit::::uninit(); errno_check(unsafe { libc::lstat(cpath.as_ptr(), stat.as_mut_ptr()) }); @@ -839,7 +920,6 @@ fn test_lstat() { } fn test_futimens() { - use std::mem::MaybeUninit; use std::time::{SystemTime, UNIX_EPOCH}; let path = utils::prepare_with_content("miri_test_libc_futimens.txt", b"hello"); @@ -918,7 +998,6 @@ fn test_isatty() { } fn test_read_and_uninit() { - use std::mem::MaybeUninit; { // We test that libc::read initializes its buffer. let path = utils::prepare_with_content("pass-libc-read-and-uninit.txt", &[1u8, 2, 3]); @@ -926,7 +1005,7 @@ fn test_read_and_uninit() { unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); assert_ne!(fd, -1); - let mut buf: MaybeUninit = std::mem::MaybeUninit::uninit(); + let mut buf: MaybeUninit = MaybeUninit::uninit(); assert_eq!(libc::read(fd, buf.as_mut_ptr().cast::(), 1), 1); let buf = buf.assume_init(); assert_eq!(buf, 1); @@ -1042,8 +1121,6 @@ fn test_readdir() { } fn test_dirfd() { - use std::mem::MaybeUninit; - let path = utils::prepare_dir("miri_test_libc_opendir_closedir"); create_dir(&path).expect("create_dir failed"); let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index e312feda7e62b..2fe1f15836b36 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -1,15 +1,11 @@ -use std::ffi::OsString; +use std::ffi::{CStr, CString, OsString}; use std::path::PathBuf; use std::{fs, io}; use super::miri_extern; pub fn host_to_target_path(path: OsString) -> PathBuf { - use std::ffi::{CStr, CString}; - - // Once into_encoded_bytes is stable we can use it here. - // (Unstable features would need feature flags in each test...) - let path = CString::new(path.into_string().unwrap()).unwrap(); + let path = into_c_string(path); let mut out = Vec::with_capacity(1024); unsafe { @@ -52,3 +48,8 @@ pub fn prepare_dir(dirname: &str) -> PathBuf { fs::remove_dir_all(&path).ok(); path } + +/// Return a `CString` version of the given path. +pub fn into_c_string(path: impl Into) -> CString { + CString::new(path.into().into_string().unwrap()).unwrap() +} From 126eeb71e79efe2e2f600e12fef0254975fc0cd3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 10:45:04 +0200 Subject: [PATCH 1054/1309] reflow src/external-repos.md --- src/doc/rustc-dev-guide/src/external-repos.md | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index 6f756fc8b890d..c4f5663871898 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -27,12 +27,12 @@ The following external projects are managed using some form of a `subtree`: * [compiler-builtins](https://github.com/rust-lang/compiler-builtins) * [stdarch](https://github.com/rust-lang/stdarch) -In contrast to `submodule` dependencies -(see below for those), the `subtree` dependencies are just regular files and directories which can +In contrast to `submodule` dependencies (see below for those), +the `subtree` dependencies are just regular files and directories which can be updated in-tree. However, if possible, enhancements, bug fixes, etc. specific to these tools should be filed against the tools directly in their respective upstream repositories. -The exception is that when rustc changes are required to -implement a new tool feature or test, that should happen in one collective rustc PR. +The exception is that when rustc changes are required to implement a new tool feature or test, +that should happen in one collective rustc PR. Similarly, if your rustc changes break the build of some subtree dependency, you should include fixes for those in the rustc PR as well. @@ -103,20 +103,20 @@ Periodically the changes made to subtree based dependencies need to be synchroni repository and the upstream tool repositories. Subtree synchronizations are typically handled by the respective tool maintainers. -Other users -are welcome to submit synchronization PRs, however, in order to do so you will need to modify +Other users are welcome to submit synchronization PRs, +however, in order to do so you will need to modify your local git installation and follow a very precise set of instructions. -These instructions are documented, along with several useful tips and tricks, in the -[syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide. -The instructions are applicable for use with any subtree based tool, just be sure to -use the correct corresponding subtree directory and remote repository. +These instructions are documented, along with several useful tips and tricks, +in the [syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide. +The instructions are applicable for use with any subtree based tool, +just be sure to use the correct corresponding subtree directory and remote repository. The synchronization process goes in two directions: `subtree push` and `subtree pull`. A `subtree push` takes all the changes that happened to the copy in this repo and creates commits on the remote repo that match the local changes. -Every local commit that touched the subtree causes a commit on the remote repo, but -is modified to move the files from the specified directory to the tool repo root. +Every local commit that touched the subtree causes a commit on the remote repo, +but is modified to move the files from the specified directory to the tool repo root. A `subtree pull` takes all changes since the last `subtree pull` from the tool repo and adds these commits to the rustc repo along with a merge commit that moves @@ -142,8 +142,8 @@ that this is happening because you suddenly get thousands of commits that want t ### Creating a new subtree dependency -If you want to create a new subtree dependency from an existing repository, call (from this -repository's root directory!) +If you want to create a new subtree dependency from an existing repository, +call (from this repository's root directory!) ``` git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git master @@ -152,9 +152,9 @@ git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git This will create a new commit, which you may not rebase under any circumstances! Delete the commit and redo the operation if you need to rebase. -Now you're done, the `src/tools/clippy` directory behaves as if Clippy were -part of the rustc monorepo, so no one but you (or others that synchronize -subtrees) actually needs to use `git subtree`. +Now you're done, +the `src/tools/clippy` directory behaves as if Clippy were part of the rustc monorepo, +so no one but you (or others that synchronize subtrees) actually needs to use `git subtree`. ## External dependencies (submodules) @@ -168,14 +168,14 @@ Usage of submodules is discussed more in the [Using Git chapter](git.md#git-subm Some of the submodules are allowed to be in a "broken" state where they either don't build or their tests don't pass, e.g. the documentation books like [The Rust Reference]. -Maintainers of these projects will be notified -when the project is in a broken state, and they should fix them as soon as possible. +Maintainers of these projects will be notified when the project is in a broken state, +and they should fix them as soon as possible. The current status is tracked on the [toolstate website]. More information may be found on the Forge [Toolstate chapter]. In practice, it is very rare for documentation to have broken toolstate. -Breakage is not allowed in the beta and stable channels, and must be addressed -before the PR is merged. +Breakage is not allowed in the beta and stable channels, +and must be addressed before the PR is merged. They are also not allowed to be broken on `main` in the week leading up to the beta cut. [git submodules]: https://git-scm.com/book/en/v2/Git-Tools-Submodules From 4912ffd204e4442f21f910a3b10726d4ae747e00 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 22:04:40 +0200 Subject: [PATCH 1055/1309] use utils::into_c_string in more places --- .../miri/tests/fail-dep/libc/dirfd-closed.rs | 4 +- .../tests/fail-dep/libc/dirfd-replaced.rs | 4 +- .../libc-read-and-uninit-premature-eof.rs | 3 +- .../fail-dep/libc/open_wrong_var_arg_type.rs | 5 +- .../tests/fail/shims/input_arg_mismatch.rs | 5 +- .../tests/fail/shims/return_type_mismatch.rs | 5 +- .../shims/vararg_callee_signature_mismatch.rs | 5 +- .../tests/fail/shims/wrong_fixed_arg_count.rs | 5 +- .../pass-dep/libc/libc-fs-permissions.rs | 7 +- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 79 +++++++++---------- .../pass-dep/libc/libc-socket-invalid-addr.rs | 5 +- src/tools/miri/tests/utils/fs.rs | 9 +-- src/tools/miri/tests/utils/mod.rs | 7 ++ 13 files changed, 63 insertions(+), 80 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs index 7cab24bc4d4d9..b34a36babb2a9 100644 --- a/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-closed.rs @@ -1,9 +1,7 @@ //@ignore-target: windows # no libc //@compile-flags: -Zmiri-disable-isolation -use std::ffi::CString; use std::fs::create_dir; -use std::os::unix::ffi::OsStrExt; #[path = "../../utils/mod.rs"] mod utils; @@ -16,7 +14,7 @@ use libc_utils::errno_check; fn main() { let path = utils::prepare_dir("miri_test_libc_dirfd_closed"); create_dir(&path).expect("create_dir failed"); - let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let cpath = utils::into_c_string(path); let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; assert!(!dir.is_null()); diff --git a/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs index e5e2336e96d63..dd6d404874401 100644 --- a/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs +++ b/src/tools/miri/tests/fail-dep/libc/dirfd-replaced.rs @@ -1,9 +1,7 @@ //@ignore-target: windows # no libc //@compile-flags: -Zmiri-disable-isolation -use std::ffi::CString; use std::fs::create_dir; -use std::os::unix::ffi::OsStrExt; #[path = "../../utils/mod.rs"] mod utils; @@ -16,7 +14,7 @@ use libc_utils::{errno_check, errno_result}; fn main() { let path = utils::prepare_dir("miri_test_libc_dirfd_replaced"); create_dir(&path).expect("create_dir failed"); - let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let cpath = utils::into_c_string(path); let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; assert!(!dir.is_null()); diff --git a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs index 4400d52e59d6c..f3e96a9c26f75 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs @@ -4,7 +4,6 @@ // Short FD ops can affect the exact error message here //@compile-flags: -Zmiri-disable-isolation -Zmiri-no-short-fd-operations -use std::ffi::CString; use std::fs::remove_file; use std::mem::MaybeUninit; @@ -17,7 +16,7 @@ mod libc_utils; fn main() { let path = utils::prepare_with_content("fail-libc-read-and-uninit-premature-eof.txt", &[1u8, 2, 3]); - let cpath = CString::new(path.clone().into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(&path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); assert_ne!(fd, -1); diff --git a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs index 3382670b50f18..39d2acffc0708 100644 --- a/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs +++ b/src/tools/miri/tests/fail-dep/libc/open_wrong_var_arg_type.rs @@ -4,13 +4,10 @@ #![allow(invalid_runtime_symbol_definitions)] -use std::ffi::{CString, OsStr}; -use std::os::unix::ffi::OsStrExt; - use libc::open; fn main() { - let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let c_path = c"./text"; let _fd = unsafe { open(c_path.as_ptr(), libc::O_CREAT, /* should be mode_t */ 0u64) //~^ ERROR: /expected argument #3 to have type `(u32|i32)` but got incompatible type `u64`/ diff --git a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs index d355da73174e9..5fa07989c895f 100644 --- a/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/input_arg_mismatch.rs @@ -3,8 +3,7 @@ #![allow(suspicious_runtime_symbol_definitions)] -use std::ffi::{CString, OsStr, c_char, c_int}; -use std::os::unix::ffi::OsStrExt; +use std::ffi::{c_char, c_int}; extern "C" { fn open(path: *const c_char, oflag: c_int, ...) -> c_int; @@ -13,7 +12,7 @@ extern "C" { } fn main() { - let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let c_path = c"./text"; let fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) } as u32; diff --git a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs index bcde5d8040f59..1b22dfbd44872 100644 --- a/src/tools/miri/tests/fail/shims/return_type_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/return_type_mismatch.rs @@ -3,8 +3,7 @@ #![allow(suspicious_runtime_symbol_definitions)] -use std::ffi::{CString, OsStr, c_char, c_int, c_short}; -use std::os::unix::ffi::OsStrExt; +use std::ffi::{c_char, c_int, c_short}; extern "C" { fn open(path: *const c_char, oflag: c_int, ...) -> c_int; @@ -13,7 +12,7 @@ extern "C" { } fn main() { - let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let c_path = c"./text"; let fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) }; diff --git a/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs index ce0c6c289faf0..c00a1f0b22814 100644 --- a/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs +++ b/src/tools/miri/tests/fail/shims/vararg_callee_signature_mismatch.rs @@ -3,8 +3,7 @@ #![allow(invalid_runtime_symbol_definitions)] -use std::ffi::{CString, OsStr, c_char, c_int}; -use std::os::unix::ffi::OsStrExt; +use std::ffi::{c_char, c_int}; // Declare a variadic function as non-variadic. extern "C" { @@ -12,7 +11,7 @@ extern "C" { } fn main() { - let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let c_path = c"./text"; let _fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) //~^ ERROR: is a c-variadic function, but the caller is using a non-variadic signature diff --git a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs index 34f6ae24f3e1d..f4e7a02b838fa 100644 --- a/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs +++ b/src/tools/miri/tests/fail/shims/wrong_fixed_arg_count.rs @@ -3,15 +3,14 @@ #![allow(invalid_runtime_symbol_definitions)] -use std::ffi::{CString, OsStr, c_char, c_int}; -use std::os::unix::ffi::OsStrExt; +use std::ffi::{c_char, c_int}; extern "C" { fn open(path: *const c_char, ...) -> c_int; } fn main() { - let c_path = CString::new(OsStr::new("./text").as_bytes()).expect("CString::new failed"); + let c_path = c"./text"; let _fd = unsafe { open(c_path.as_ptr(), /* value does not matter */ 0) //~^ ERROR: takes 2 fixed (non-variadic) arguments, but 1 argument was given diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs index 819717fed8523..dd79c96e179c8 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs @@ -3,9 +3,8 @@ //@compile-flags: -Zmiri-disable-isolation //@run-native -use std::ffi::{CStr, CString}; +use std::ffi::CStr; use std::mem::MaybeUninit; -use std::os::unix::ffi::OsStrExt; #[path = "../../utils/mod.rs"] mod utils; @@ -28,7 +27,7 @@ fn getmod(path: &CStr) -> u32 { fn test_chmod() { let path = utils::prepare_with_content("miri_test_libc_chmod.txt", b"abcdef"); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(path); unsafe { errno_check(libc::chmod(c_path.as_ptr(), 0o777)) }; assert_eq!(getmod(&c_path), 0o777); @@ -38,7 +37,7 @@ fn test_chmod() { fn test_fchmod() { let path = utils::prepare_with_content("miri_test_libc_chmod.txt", b"abcdef"); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(path); let fd = unsafe { errno_result(libc::open(c_path.as_ptr(), libc::O_RDONLY)).unwrap() }; unsafe { errno_check(libc::fchmod(fd, 0o777)) }; diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index af67ca16bd2f1..cf25c13a78bcc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -159,7 +159,7 @@ fn test_statx_on_file_descriptor() { fn test_statx_on_file_path() { let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx.txt", bytes); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); let meta = fs::metadata(&path).unwrap(); // Relative to working directory. @@ -257,14 +257,14 @@ fn test_statx_empty_path_on_pipe() { fn test_file_open_allow_two_args() { let path = utils::prepare_with_content("test_file_open_allow_two_args.txt", &[]); - let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let name = utils::into_c_string(path); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap(); } fn test_file_open_needs_three_args() { let path = utils::prepare_with_content("test_file_open_needs_three_args.txt", &[]); - let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let name = utils::into_c_string(path); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o666) }) @@ -273,7 +273,7 @@ fn test_file_open_needs_three_args() { fn test_file_open_extra_third_arg() { let path = utils::prepare_with_content("test_file_open_extra_third_arg.txt", &[]); - let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let name = utils::into_c_string(path); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap(); } @@ -281,7 +281,7 @@ fn test_file_open_extra_third_arg() { fn test_file_open_nofollow() { let bytes = b"Hello, World!\n"; let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); - let cpath = CString::new(path.as_os_str().as_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }) .unwrap(); @@ -292,7 +292,7 @@ fn test_file_open_nofollow() { let symlink_path = utils::prepare("miri_test_open_nofollow_symlink.txt"); std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - let symlink_cpath = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + let symlink_cpath = utils::into_c_string(symlink_path); let err = errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) @@ -315,7 +315,7 @@ fn test_dup_stdout_stderr() { fn test_dup() { let bytes = b"dup and dup2"; let path = utils::prepare_with_content("miri_test_libc_dup.txt", bytes); - let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let name = utils::into_c_string(path); unsafe { let fd = errno_result(libc::open(name.as_ptr(), libc::O_RDONLY)).unwrap(); @@ -377,8 +377,8 @@ fn test_rename() { let file = File::create(&path1).unwrap(); drop(file); - let c_path1 = CString::new(path1.as_os_str().as_bytes()).expect("CString::new failed"); - let c_path2 = CString::new(path2.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path1 = utils::into_c_string(&path1); + let c_path2 = utils::into_c_string(&path2); // Renaming should succeed unsafe { libc::rename(c_path1.as_ptr(), c_path2.as_ptr()) }; @@ -408,7 +408,7 @@ fn test_ftruncate>( file.sync_all().unwrap(); assert_eq!(file.metadata().unwrap().len(), 5); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) }; // Truncate to a bigger size @@ -510,11 +510,11 @@ fn test_posix_mkstemp() { /// Test allocating variant of `realpath`. fn test_posix_realpath_alloc() { - use std::os::unix::ffi::{OsStrExt, OsStringExt}; + use std::os::unix::ffi::OsStringExt; let buf; let path = utils::prepare("miri_test_libc_posix_realpath_alloc"); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); // Create file. drop(File::create(&path).unwrap()); @@ -533,11 +533,10 @@ fn test_posix_realpath_alloc() { /// Test non-allocating variant of `realpath`. fn test_posix_realpath_noalloc() { - use std::ffi::{CStr, CString}; - use std::os::unix::ffi::OsStrExt; + use std::ffi::CStr; let path = utils::prepare("miri_test_libc_posix_realpath_noalloc"); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); let mut v = vec![0; libc::PATH_MAX as usize]; @@ -558,16 +557,12 @@ fn test_posix_realpath_noalloc() { /// Test failure cases for `realpath`. fn test_posix_realpath_errors() { - use std::ffi::CString; - use std::io::ErrorKind; - // Test nonexistent path returns an error. - let c_path = CString::new("./nothing_to_see_here").expect("CString::new failed"); + let c_path = c"./nothing_to_see_here"; let r = unsafe { libc::realpath(c_path.as_ptr(), std::ptr::null_mut()) }; assert!(r.is_null()); let e = std::io::Error::last_os_error(); assert_eq!(e.raw_os_error(), Some(libc::ENOENT)); - assert_eq!(e.kind(), ErrorKind::NotFound); } #[cfg(target_os = "linux")] @@ -619,7 +614,7 @@ fn test_posix_fallocate>( assert_eq!(ret, libc::EINVAL); // fd not writable - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(path); let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDONLY) }; let ret = unsafe { posix_fallocate(fd, T::from(0), T::from(10)) }; assert_eq!(ret, libc::EBADF); @@ -633,7 +628,7 @@ fn test_posix_fallocate>( file.sync_all().unwrap(); assert_eq!(file.metadata().unwrap().len(), 5); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); let fd = unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) }; // Allocate to a bigger size from offset 0 @@ -696,7 +691,7 @@ fn test_fallocate>( assert_eq!(err.raw_os_error().unwrap(), libc::EINVAL); // fd not writable - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(path); let fd = errno_result(unsafe { libc::open(c_path.as_ptr(), libc::O_RDONLY) }).unwrap(); let err = errno_result(unsafe { fallocate(fd, 0, T::from(0), T::from(10)) }).unwrap_err(); assert_eq!(err.raw_os_error().unwrap(), libc::EBADF); @@ -709,7 +704,7 @@ fn test_fallocate>( file.sync_all().unwrap(); assert_eq!(file.metadata().unwrap().len(), 5); - let c_path = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let c_path = utils::into_c_string(&path); let fd = errno_result(unsafe { libc::open(c_path.as_ptr(), libc::O_RDWR) }).unwrap(); // Allocate to a bigger size from offset 0 @@ -1001,7 +996,7 @@ fn test_read_and_uninit() { { // We test that libc::read initializes its buffer. let path = utils::prepare_with_content("pass-libc-read-and-uninit.txt", &[1u8, 2, 3]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); assert_ne!(fd, -1); @@ -1018,7 +1013,7 @@ fn test_read_and_uninit() { // 3 bytes (not 4) will be overwritten, and remaining byte will be left as-is. let data = [1u8, 2, 3]; let path = utils::prepare_with_content("pass-libc-read-and-uninit-2.txt", &data); - let cpath = CString::new(path.clone().into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(&path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); assert_ne!(fd, -1); @@ -1041,7 +1036,7 @@ fn test_read_and_uninit() { #[cfg(target_os = "macos")] fn test_ioctl() { let path = utils::prepare_with_content("miri_test_libc_ioctl.txt", &[]); - let name = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let name = utils::into_c_string(path); unsafe { // 100 surely is an invalid FD. @@ -1058,7 +1053,7 @@ fn test_opendir_closedir() { // dir should exist let path = utils::prepare_dir("miri_test_libc_opendir_closedir"); create_dir(&path).expect("create_dir failed"); - let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let cpath = utils::into_c_string(&path); let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; assert!(!dir.is_null()); errno_check(unsafe { libc::closedir(dir) }); @@ -1073,7 +1068,7 @@ fn test_opendir_closedir() { // open normal file as dir should fail let file_path = utils::prepare_with_content("test_not_a_dir.txt", b"hello"); - let cfile = CString::new(file_path.as_os_str().as_bytes()).expect("CString::new failed"); + let cfile = utils::into_c_string(&file_path); let dir: *mut libc::DIR = unsafe { libc::opendir(cfile.as_ptr()) }; assert!(dir.is_null()); let e = std::io::Error::last_os_error(); @@ -1094,7 +1089,7 @@ fn test_readdir() { write(&file1, b"content1").unwrap(); write(&file2, b"content2").unwrap(); - let c_path = CString::new(dir_path.as_os_str().as_bytes()).unwrap(); + let c_path = utils::into_c_string(&dir_path); unsafe { let dirp = libc::opendir(c_path.as_ptr()); @@ -1123,7 +1118,7 @@ fn test_readdir() { fn test_dirfd() { let path = utils::prepare_dir("miri_test_libc_opendir_closedir"); create_dir(&path).expect("create_dir failed"); - let cpath = CString::new(path.as_os_str().as_bytes()).expect("CString::new failed"); + let cpath = utils::into_c_string(path); let dir: *mut libc::DIR = unsafe { libc::opendir(cpath.as_ptr()) }; assert!(!dir.is_null()); @@ -1170,7 +1165,7 @@ pub fn check_stat_fields(stat: &libc::stat) { fn test_readv() { let file_contents = [1u8, 2, 3, 4, 5, 6]; let path = utils::prepare_with_content("pass-libc-readv.txt", &file_contents); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1206,7 +1201,7 @@ fn test_readv_empty_bufs() { } let path = utils::prepare_with_content("pass-libc-readv-empty-bufs.txt", &[1u8, 2, 3]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); unsafe { assert_eq!(errno_result(libc::readv(fd, ptr::null::(), 0)).unwrap(), 0) }; @@ -1220,7 +1215,7 @@ fn test_readv_empty_bufs() { fn test_preadv() { let file_contents = [1u8, 2, 3, 4, 5, 6]; let path = utils::prepare_with_content("pass-libc-preadv.txt", &file_contents); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1261,7 +1256,7 @@ fn test_preadv() { fn test_pread() { let file_contents = [1u8, 2, 3, 4, 5, 6]; let path = utils::prepare_with_content("pass-libc-pread.txt", &file_contents); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1288,7 +1283,7 @@ fn test_pread() { /// Test vectored writes with multiple buffers. fn test_writev() { let path = utils::prepare_with_content("pass-libc-writev.txt", &[]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1339,7 +1334,7 @@ fn test_writev_empty_bufs() { } let path = utils::prepare_with_content("pass-libc-writev-empty-bufs.txt", &[1u8, 2, 3]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); unsafe { @@ -1354,7 +1349,7 @@ fn test_writev_empty_bufs() { #[cfg(not(target_os = "solaris"))] fn test_pwritev() { let path = utils::prepare_with_content("pass-libc-pwritev.txt", &[]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1410,7 +1405,7 @@ fn test_pwritev() { /// Test writing with an offset. fn test_pwrite() { let path = utils::prepare_with_content("pass-libc-pwritev.txt", &[]); - let cpath = CString::new(path.into_os_string().into_encoded_bytes()).unwrap(); + let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1460,7 +1455,7 @@ fn test_readlink() { // Test that the expected string gets written to a buffer of proper // length, and that a trailing null byte is not written. - let symlink_c_str = CString::new(symlink_path.as_os_str().as_bytes()).unwrap(); + let symlink_c_str = utils::into_c_string(symlink_path); let symlink_c_ptr = symlink_c_str.as_ptr(); // Make the buf one byte larger than it needs to be, @@ -1501,8 +1496,8 @@ fn test_linkat() { let source = utils::prepare_with_content("miri_test_libc_linkat_source.txt", b"hello"); let link = utils::prepare("miri_test_libc_linkat_link.txt"); - let c_source = CString::new(source.as_os_str().as_bytes()).expect("CString::new failed"); - let c_link = CString::new(link.as_os_str().as_bytes()).expect("CString::new failed"); + let c_source = utils::into_c_string(&source); + let c_link = utils::into_c_string(&link); // Call linkat unsafe { diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.rs index 4e46870da204b..40a3a60068d90 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-invalid-addr.rs @@ -7,7 +7,6 @@ mod libc_utils; #[path = "../../utils/mod.rs"] mod utils; -use std::ffi::CString; use std::ptr; use libc_utils::*; @@ -15,8 +14,8 @@ use libc_utils::*; /// Test doing address resolution using the `getaddrinfo` syscall. /// This also tests freeing the address linked list using `freeaddrinfo`. fn main() { - let node_c_str = CString::new("this-is-not-a-valid-address").unwrap(); - let service_c_str = CString::new("8080").unwrap(); + let node_c_str = c"this-is-not-a-valid-address"; + let service_c_str = c"8080"; let mut hints: libc::addrinfo = unsafe { std::mem::zeroed() }; hints.ai_socktype = libc::SOCK_STREAM; diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index 2fe1f15836b36..b18622a1994d7 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -1,8 +1,8 @@ -use std::ffi::{CStr, CString, OsString}; +use std::ffi::{CStr, OsString}; use std::path::PathBuf; use std::{fs, io}; -use super::miri_extern; +use super::{into_c_string, miri_extern}; pub fn host_to_target_path(path: OsString) -> PathBuf { let path = into_c_string(path); @@ -48,8 +48,3 @@ pub fn prepare_dir(dirname: &str) -> PathBuf { fs::remove_dir_all(&path).ok(); path } - -/// Return a `CString` version of the given path. -pub fn into_c_string(path: impl Into) -> CString { - CString::new(path.into().into_string().unwrap()).unwrap() -} diff --git a/src/tools/miri/tests/utils/mod.rs b/src/tools/miri/tests/utils/mod.rs index f855f115e43dc..3fe655350776c 100644 --- a/src/tools/miri/tests/utils/mod.rs +++ b/src/tools/miri/tests/utils/mod.rs @@ -1,6 +1,8 @@ #![allow(dead_code)] #![allow(unused_imports)] +use std::ffi::{CString, OsString}; + #[macro_use] mod macros; @@ -12,6 +14,11 @@ pub use self::fs::*; pub use self::io::*; pub use self::miri_extern::*; +/// Return a `CString` version of the given string. +pub fn into_c_string(str: impl Into) -> CString { + CString::new(str.into().into_string().unwrap()).unwrap() +} + pub fn run_provenance_gc() { // SAFETY: No preconditions. The GC is fine to run at any time. unsafe { miri_run_provenance_gc() } From 5196402951e7b777c211d981518d55c0a91adec4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 22:27:18 +0200 Subject: [PATCH 1056/1309] organize and extend statx tests --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 139 ++++++++++++------ 1 file changed, 94 insertions(+), 45 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index cf25c13a78bcc..41c5a3ea3ea69 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -63,11 +63,9 @@ fn main() { #[cfg(target_os = "macos")] test_ioctl(); #[cfg(target_os = "linux")] - test_statx_on_file_path(); + test_statx(); #[cfg(target_os = "linux")] - test_statx_on_file_descriptor(); - #[cfg(target_os = "linux")] - test_statx_empty_path_on_pipe(); + test_statx_on_empty_path(); test_readv(); test_readv_empty_bufs(); #[cfg(not(target_os = "solaris"))] @@ -117,46 +115,7 @@ fn assert_statx_matches_metadata(stx: &libc::statx, meta: &fs::Metadata, expecte } #[cfg(target_os = "linux")] -fn test_statx_on_file_descriptor() { - let bytes = b"hello"; - let path = utils::prepare_with_content("miri_test_libc_statx_fd.txt", bytes); - let file = File::open(&path).unwrap(); - let meta = file.metadata().unwrap(); - - unsafe { - let mut stx = MaybeUninit::::zeroed(); - errno_check(libc::statx( - file.as_raw_fd(), - c"".as_ptr(), - libc::AT_EMPTY_PATH, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - stx.as_mut_ptr(), - )); - - let stx = stx.assume_init(); - assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); - } - - // If we don't set AT_EMPTY_PATH, we get an error. - unsafe { - let mut stx = MaybeUninit::::zeroed(); - let err = errno_result(libc::statx( - file.as_raw_fd(), - c"".as_ptr(), - 0, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - stx.as_mut_ptr(), - )) - .unwrap_err(); - assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); - } - - drop(file); - remove_file(&path).unwrap(); -} - -#[cfg(target_os = "linux")] -fn test_statx_on_file_path() { +fn test_statx() { let bytes = b"hello"; let path = utils::prepare_with_content("miri_test_libc_statx.txt", bytes); let c_path = utils::into_c_string(&path); @@ -213,11 +172,101 @@ fn test_statx_on_file_path() { assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); } + // Symlink following. + let symlinkpath = utils::prepare("miri_test_libc_statx.link"); + let c_symlinkpath = utils::into_c_string(&symlinkpath); + std::os::unix::fs::symlink(&path, &symlinkpath).unwrap(); + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + 999, // dirfd + c_symlinkpath.as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + let stx = stx.assume_init(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + 999, // dirfd + c_symlinkpath.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + let stx = stx.assume_init(); + assert!(stx.stx_mask & libc::STATX_TYPE != 0); + assert_eq!((stx.stx_mode as libc::mode_t) & libc::S_IFMT, libc::S_IFLNK); + assert!(stx.stx_mask & libc::STATX_MODE != 0); + assert_ne!((stx.stx_mode as libc::mode_t) & !libc::S_IFMT, 0); + } + + // Relative to a dirfd. + // The only way to get a dirfd in Miri currently is via a `dirfd`. Slightly silly, but whatever. + let dirstream = unsafe { libc::opendir(utils::into_c_string(path.parent().unwrap()).as_ptr()) }; + assert!(!dirstream.is_null()); + let dirfd = unsafe { libc::dirfd(dirstream) }; + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + dirfd, + c"miri_test_libc_statx.txt".as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + + let stx = stx.assume_init(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + errno_check(unsafe { libc::closedir(dirstream) }); + remove_file(&path).unwrap(); + remove_file(&symlinkpath).unwrap(); } #[cfg(target_os = "linux")] -fn test_statx_empty_path_on_pipe() { +fn test_statx_on_empty_path() { + let bytes = b"hello"; + let path = utils::prepare_with_content("miri_test_libc_statx_fd.txt", bytes); + let file = File::open(&path).unwrap(); + let meta = file.metadata().unwrap(); + + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + file.as_raw_fd(), + c"".as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + + let stx = stx.assume_init(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + + // If we don't set AT_EMPTY_PATH, we get an error. + unsafe { + let mut stx = MaybeUninit::::zeroed(); + let err = errno_result(libc::statx( + file.as_raw_fd(), + c"".as_ptr(), + 0, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); + } + + drop(file); + remove_file(&path).unwrap(); + + // Test it on a pipe as well. unsafe { let mut fds = [0; 2]; errno_check(libc::pipe(fds.as_mut_ptr())); From 96bffc439e559cd198f4e49482d442d56f26dbf4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 10:50:03 +0200 Subject: [PATCH 1057/1309] improve external-repos.md --- src/doc/rustc-dev-guide/src/external-repos.md | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index c4f5663871898..d2c1696fb48b0 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -29,7 +29,8 @@ The following external projects are managed using some form of a `subtree`: In contrast to `submodule` dependencies (see below for those), the `subtree` dependencies are just regular files and directories which can -be updated in-tree. However, if possible, enhancements, bug fixes, etc. specific +be updated in-tree. +However, if possible, enhancements, bug fixes, etc. specific to these tools should be filed against the tools directly in their respective upstream repositories. The exception is that when rustc changes are required to implement a new tool feature or test, that should happen in one collective rustc PR. @@ -103,12 +104,12 @@ Periodically the changes made to subtree based dependencies need to be synchroni repository and the upstream tool repositories. Subtree synchronizations are typically handled by the respective tool maintainers. -Other users are welcome to submit synchronization PRs, -however, in order to do so you will need to modify +Other users are welcome to submit synchronization PRs. +However, in order to do so, you will need to modify your local git installation and follow a very precise set of instructions. These instructions are documented, along with several useful tips and tricks, in the [syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide. -The instructions are applicable for use with any subtree based tool, +The instructions are applicable for use with any subtree-based tool; just be sure to use the correct corresponding subtree directory and remote repository. The synchronization process goes in two directions: `subtree push` and `subtree pull`. @@ -152,7 +153,7 @@ git subtree add -P src/tools/clippy https://github.com/rust-lang/rust-clippy.git This will create a new commit, which you may not rebase under any circumstances! Delete the commit and redo the operation if you need to rebase. -Now you're done, +Now you're done; the `src/tools/clippy` directory behaves as if Clippy were part of the rustc monorepo, so no one but you (or others that synchronize subtrees) actually needs to use `git subtree`. From ce15ffad43628de7030e5b66231c548bfb2d76e0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 10:50:10 +0200 Subject: [PATCH 1058/1309] reflow src/external-repos.md --- src/doc/rustc-dev-guide/src/external-repos.md | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/external-repos.md b/src/doc/rustc-dev-guide/src/external-repos.md index d2c1696fb48b0..0e23be130c403 100644 --- a/src/doc/rustc-dev-guide/src/external-repos.md +++ b/src/doc/rustc-dev-guide/src/external-repos.md @@ -28,8 +28,7 @@ The following external projects are managed using some form of a `subtree`: * [stdarch](https://github.com/rust-lang/stdarch) In contrast to `submodule` dependencies (see below for those), -the `subtree` dependencies are just regular files and directories which can -be updated in-tree. +the `subtree` dependencies are just regular files and directories which can be updated in-tree. However, if possible, enhancements, bug fixes, etc. specific to these tools should be filed against the tools directly in their respective upstream repositories. The exception is that when rustc changes are required to implement a new tool feature or test, @@ -105,8 +104,8 @@ repository and the upstream tool repositories. Subtree synchronizations are typically handled by the respective tool maintainers. Other users are welcome to submit synchronization PRs. -However, in order to do so, you will need to modify -your local git installation and follow a very precise set of instructions. +However, in order to do so, +you will need to modify your local git installation and follow a very precise set of instructions. These instructions are documented, along with several useful tips and tricks, in the [syncing subtree changes][clippy-sync-docs] section in Clippy's Contributing guide. The instructions are applicable for use with any subtree-based tool; From 2cf7527ce291ce1654f44a94b2b9f647d30a8540 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Tue, 29 Sep 2026 23:30:26 +0200 Subject: [PATCH 1059/1309] prefix all test files with miri --- .../libc-read-and-uninit-premature-eof.rs | 2 +- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 34 +++++++++---------- .../miri/tests/pass-dep/shims/windows-fs.rs | 22 ++++++------ .../miri/tests/pass-dep/tokio/file-io.rs | 4 +-- src/tools/miri/tests/utils/fs.rs | 4 +++ 5 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs index f3e96a9c26f75..aa9cbe4298105 100644 --- a/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs +++ b/src/tools/miri/tests/fail-dep/libc/libc-read-and-uninit-premature-eof.rs @@ -15,7 +15,7 @@ mod libc_utils; fn main() { let path = - utils::prepare_with_content("fail-libc-read-and-uninit-premature-eof.txt", &[1u8, 2, 3]); + utils::prepare_with_content("miri-libc-read-and-uninit-premature-eof.txt", &[1u8, 2, 3]); let cpath = utils::into_c_string(&path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 41c5a3ea3ea69..b3f063ef07cba 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -305,14 +305,14 @@ fn test_statx_on_empty_path() { } fn test_file_open_allow_two_args() { - let path = utils::prepare_with_content("test_file_open_allow_two_args.txt", &[]); + let path = utils::prepare_with_content("miri_test_file_open_allow_two_args.txt", &[]); let name = utils::into_c_string(path); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap(); } fn test_file_open_needs_three_args() { - let path = utils::prepare_with_content("test_file_open_needs_three_args.txt", &[]); + let path = utils::prepare_with_content("miri_test_file_open_needs_three_args.txt", &[]); let name = utils::into_c_string(path); let _fd = @@ -321,7 +321,7 @@ fn test_file_open_needs_three_args() { } fn test_file_open_extra_third_arg() { - let path = utils::prepare_with_content("test_file_open_extra_third_arg.txt", &[]); + let path = utils::prepare_with_content("miri_test_file_open_extra_third_arg.txt", &[]); let name = utils::into_c_string(path); let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap(); @@ -329,7 +329,7 @@ fn test_file_open_extra_third_arg() { fn test_file_open_nofollow() { let bytes = b"Hello, World!\n"; - let path = utils::prepare_with_content("test_nofollow_not_symlink.txt", bytes); + let path = utils::prepare_with_content("miri_test_nofollow_not_symlink.txt", bytes); let cpath = utils::into_c_string(path); let fd = errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }) @@ -856,7 +856,7 @@ fn test_fstat() { } fn test_fstatat() { - let testdir = utils::prepare_dir("test_fstatat"); + let testdir = utils::prepare_dir("miri_test_fstatat"); fs::create_dir(&testdir).unwrap(); let filename = "file.txt"; let cfilename = c"file.txt"; @@ -1029,7 +1029,7 @@ fn test_isatty() { libc::isatty(libc::STDERR_FILENO); // But when we open a file, it is definitely not a TTY. - let path = utils::prepare("notatty.txt"); + let path = utils::prepare("miri_notatty.txt"); let file = File::create(&path).unwrap(); assert_eq!(libc::isatty(file.as_raw_fd()), 0); @@ -1044,7 +1044,7 @@ fn test_isatty() { fn test_read_and_uninit() { { // We test that libc::read initializes its buffer. - let path = utils::prepare_with_content("pass-libc-read-and-uninit.txt", &[1u8, 2, 3]); + let path = utils::prepare_with_content("miri-pass-libc-read-and-uninit.txt", &[1u8, 2, 3]); let cpath = utils::into_c_string(path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); @@ -1061,7 +1061,7 @@ fn test_read_and_uninit() { // We test that if we requested to read 4 bytes, but actually read 3 bytes, then // 3 bytes (not 4) will be overwritten, and remaining byte will be left as-is. let data = [1u8, 2, 3]; - let path = utils::prepare_with_content("pass-libc-read-and-uninit-2.txt", &data); + let path = utils::prepare_with_content("miri-pass-libc-read-and-uninit-2.txt", &data); let cpath = utils::into_c_string(&path); unsafe { let fd = libc::open(cpath.as_ptr(), libc::O_RDONLY); @@ -1116,7 +1116,7 @@ fn test_opendir_closedir() { assert_eq!(e.kind(), ErrorKind::NotFound); // open normal file as dir should fail - let file_path = utils::prepare_with_content("test_not_a_dir.txt", b"hello"); + let file_path = utils::prepare_with_content("miri_test_not_a_dir.txt", b"hello"); let cfile = utils::into_c_string(&file_path); let dir: *mut libc::DIR = unsafe { libc::opendir(cfile.as_ptr()) }; assert!(dir.is_null()); @@ -1213,7 +1213,7 @@ pub fn check_stat_fields(stat: &libc::stat) { /// Test vectored reads with multiple buffers. fn test_readv() { let file_contents = [1u8, 2, 3, 4, 5, 6]; - let path = utils::prepare_with_content("pass-libc-readv.txt", &file_contents); + let path = utils::prepare_with_content("miri-pass-libc-readv.txt", &file_contents); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1249,7 +1249,7 @@ fn test_readv_empty_bufs() { return; } - let path = utils::prepare_with_content("pass-libc-readv-empty-bufs.txt", &[1u8, 2, 3]); + let path = utils::prepare_with_content("miri-pass-libc-readv-empty-bufs.txt", &[1u8, 2, 3]); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1263,7 +1263,7 @@ fn test_readv_empty_bufs() { #[cfg(not(target_os = "solaris"))] fn test_preadv() { let file_contents = [1u8, 2, 3, 4, 5, 6]; - let path = utils::prepare_with_content("pass-libc-preadv.txt", &file_contents); + let path = utils::prepare_with_content("miri-pass-libc-preadv.txt", &file_contents); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1304,7 +1304,7 @@ fn test_preadv() { /// Test reading with an offset. fn test_pread() { let file_contents = [1u8, 2, 3, 4, 5, 6]; - let path = utils::prepare_with_content("pass-libc-pread.txt", &file_contents); + let path = utils::prepare_with_content("miri-pass-libc-pread.txt", &file_contents); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }; assert_ne!(fd, -1); @@ -1331,7 +1331,7 @@ fn test_pread() { /// Test vectored writes with multiple buffers. fn test_writev() { - let path = utils::prepare_with_content("pass-libc-writev.txt", &[]); + let path = utils::prepare_with_content("miri-pass-libc-writev.txt", &[]); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1382,7 +1382,7 @@ fn test_writev_empty_bufs() { return; } - let path = utils::prepare_with_content("pass-libc-writev-empty-bufs.txt", &[1u8, 2, 3]); + let path = utils::prepare_with_content("miri-pass-libc-writev-empty-bufs.txt", &[1u8, 2, 3]); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1397,7 +1397,7 @@ fn test_writev_empty_bufs() { /// doesn't have `pwritev`. #[cfg(not(target_os = "solaris"))] fn test_pwritev() { - let path = utils::prepare_with_content("pass-libc-pwritev.txt", &[]); + let path = utils::prepare_with_content("miri-pass-libc-pwritev.txt", &[]); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); @@ -1453,7 +1453,7 @@ fn test_pwritev() { /// Test writing with an offset. fn test_pwrite() { - let path = utils::prepare_with_content("pass-libc-pwritev.txt", &[]); + let path = utils::prepare_with_content("miri-pass-libc-pwritev.txt", &[]); let cpath = utils::into_c_string(path); let fd = unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY) }; assert_ne!(fd, -1); diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index ecac238240872..b012b7328eaf3 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -77,7 +77,7 @@ unsafe fn test_create_dir_file() { } unsafe fn test_create_normal_file() { - let temp = utils::prepare("test_create_normal_file.txt"); + let temp = utils::prepare("miri_test_create_normal_file.txt"); let raw_path = to_wide_cstr(&temp); let handle = CreateFileW( raw_path.as_ptr(), @@ -134,7 +134,7 @@ unsafe fn test_create_normal_file() { /// Tests that CREATE_ALWAYS sets the error value correctly based on whether the file already exists unsafe fn test_create_always_twice() { - let temp = utils::prepare("test_create_always.txt"); + let temp = utils::prepare("miri_test_create_always.txt"); let raw_path = to_wide_cstr(&temp); let handle = CreateFileW( raw_path.as_ptr(), @@ -169,7 +169,7 @@ unsafe fn test_create_always_twice() { /// Tests that OPEN_ALWAYS sets the error value correctly based on whether the file already exists unsafe fn test_open_always_twice() { - let temp = utils::prepare("test_open_always.txt"); + let temp = utils::prepare("miri_test_open_always.txt"); let raw_path = to_wide_cstr(&temp); let handle = CreateFileW( raw_path.as_ptr(), @@ -228,7 +228,7 @@ unsafe fn test_open_always_twice() { // } unsafe fn test_delete_file() { - let temp = utils::prepare("test_delete_file.txt"); + let temp = utils::prepare("miri_test_delete_file.txt"); let raw_path = to_wide_cstr(&temp); let _ = fs::File::create(&temp).unwrap(); @@ -249,7 +249,7 @@ unsafe fn test_ntstatus_to_dos() { } unsafe fn test_file_read_write() { - let temp = utils::prepare("test_file_read_write.txt"); + let temp = utils::prepare("miri_test_file_read_write.txt"); let file = fs::File::create(&temp).unwrap(); let handle = file.as_raw_handle(); @@ -300,7 +300,7 @@ unsafe fn test_file_read_write() { } unsafe fn test_set_file_info() { - let temp = utils::prepare("test_set_file.txt"); + let temp = utils::prepare("miri_test_set_file.txt"); let mut file = fs::File::create(&temp).unwrap(); let handle = file.as_raw_handle(); @@ -326,7 +326,7 @@ unsafe fn test_set_file_info() { } unsafe fn test_dup_handle() { - let temp = utils::prepare("test_dup.txt"); + let temp = utils::prepare("miri_test_dup.txt"); let mut file1 = fs::File::options().read(true).write(true).create(true).open(&temp).unwrap(); @@ -359,7 +359,7 @@ unsafe fn test_dup_handle() { } unsafe fn test_file_seek() { - let temp = utils::prepare("test_file_seek.txt"); + let temp = utils::prepare("miri_test_file_seek.txt"); let mut file = fs::File::options().create(true).write(true).read(true).open(&temp).unwrap(); file.write_all(b"Hello, World!\n").unwrap(); @@ -384,7 +384,7 @@ unsafe fn test_file_seek() { } unsafe fn test_flush_buffers() { - let temp = utils::prepare("test_flush_buffers.txt"); + let temp = utils::prepare("miri_test_flush_buffers.txt"); let file = fs::File::options().create(true).write(true).read(true).open(&temp).unwrap(); if FlushFileBuffers(file.as_raw_handle()) == 0 { panic!("Failed to flush buffers"); @@ -397,8 +397,8 @@ unsafe fn test_flush_buffers() { } unsafe fn test_move_file() { - let temp = utils::prepare("test_move_file.txt"); - let temp_new = utils::prepare("test_move_file_new.txt"); + let temp = utils::prepare("miri_test_move_file.txt"); + let temp_new = utils::prepare("miri_test_move_file_new.txt"); let mut file = fs::File::options().create(true).write(true).open(&temp).unwrap(); file.write_all(b"Hello, World!\n").unwrap(); diff --git a/src/tools/miri/tests/pass-dep/tokio/file-io.rs b/src/tools/miri/tests/pass-dep/tokio/file-io.rs index 982768111a511..d7704af1402e9 100644 --- a/src/tools/miri/tests/pass-dep/tokio/file-io.rs +++ b/src/tools/miri/tests/pass-dep/tokio/file-io.rs @@ -17,7 +17,7 @@ async fn main() { } async fn test_create_and_write() -> io::Result<()> { - let path = utils::prepare("foo.txt"); + let path = utils::prepare("miri_tokio_test_create_and_write.txt"); let mut file = File::create(&path).await?; // Write 10 bytes to the file. @@ -34,7 +34,7 @@ async fn test_create_and_write() -> io::Result<()> { async fn test_create_and_read() -> io::Result<()> { let bytes = b"more bytes"; - let path = utils::prepare_with_content("foo.txt", bytes); + let path = utils::prepare_with_content("miri_tokio_test_create_and_read.txt", bytes); let mut file = OpenOptions::new().read(true).open(&path).await.unwrap(); let mut buffer = vec![]; diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index b18622a1994d7..afcd66dd16e58 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -28,6 +28,8 @@ pub fn tmp() -> PathBuf { /// Prepare: compute filename and make sure the file does not exist. pub fn prepare(filename: &str) -> PathBuf { + assert!(filename.starts_with("miri")); + let path = tmp().join(filename); // Clean the paths for robustness. fs::remove_file(&path).ok(); @@ -43,6 +45,8 @@ pub fn prepare_with_content(filename: &str, content: &[u8]) -> PathBuf { /// Prepare directory: compute directory name and make sure it does not exist. pub fn prepare_dir(dirname: &str) -> PathBuf { + assert!(dirname.starts_with("miri")); + let path = tmp().join(&dirname); // Clean the directory for robustness. fs::remove_dir_all(&path).ok(); From c6e51b3018f1315079ea2256c27672c21f429ded Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 07:51:58 +0200 Subject: [PATCH 1060/1309] implement fstatat and the equivalent parts of statx --- src/tools/miri/src/shims/files.rs | 19 +++- .../miri/src/shims/unix/foreign_items.rs | 8 ++ src/tools/miri/src/shims/unix/fs.rs | 103 ++++++++++++++++-- .../src/shims/unix/macos/foreign_items.rs | 8 ++ src/tools/miri/src/shims/windows/fs.rs | 11 +- 5 files changed, 135 insertions(+), 14 deletions(-) diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index cd7a7f4f0250b..d842f2f69b713 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -513,7 +513,24 @@ impl FileDescription for FileHandle { #[derive(Debug)] pub struct DirHandle { - pub(crate) dir: Dir, + pub(super) dir: Dir, + #[cfg(bootstrap)] + pub(super) fallback: std::path::PathBuf, + #[cfg(not(bootstrap))] + #[expect(unused)] + fallback: (), +} + +impl DirHandle { + pub fn open(path: &std::path::Path) -> io::Result { + #[cfg(bootstrap)] + let fallback = path.canonicalize()?; + #[cfg(not(bootstrap))] + let fallback = (); + + let dir = Dir::open(path)?; + Ok(DirHandle { dir, fallback }) + } } impl FileDescription for DirHandle { diff --git a/src/tools/miri/src/shims/unix/foreign_items.rs b/src/tools/miri/src/shims/unix/foreign_items.rs index f78c92de97bcc..54639db6e19cf 100644 --- a/src/tools/miri/src/shims/unix/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/foreign_items.rs @@ -404,6 +404,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = this.stat(path, buf)?; this.write_scalar(result, dest)?; } + "fstatat" => { + let [dirfd, path, buf, flags] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *_, *_, i32) -> i32), + (link_name, abi, args), + )?; + let result = this.fstatat(dirfd, path, buf, flags)?; + this.write_scalar(result, dest)?; + } "chmod" => { let [path, mode] = this.check_shim_sig( shim_sig!(extern "C" fn(*_, libc::mode_t) -> i32), diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index d67d601df36c9..1b9133785ed4a 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::ffi::OsString; -use std::fs::{self, Dir, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; +use std::fs::{self, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; use std::path::{self, Path}; use std::time::SystemTime; @@ -782,7 +782,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Reject if isolation is enabled. if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { this.reject_in_isolation("`fstat`", reject_with)?; - // Set error code as "EBADF" (bad fd) + // Set error code as "EBADF" (bad fd); "EACCESS" does not make much sense here. return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); } @@ -793,6 +793,83 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(Scalar::from_i32(this.write_stat_buf(metadata, buf_op)?)) } + fn fstatat( + &mut self, + dirfd_op: &OpTy<'tcx>, + path_op: &OpTy<'tcx>, + buf_op: &OpTy<'tcx>, + flags_op: &OpTy<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let this = self.eval_context_mut(); + + if !matches!( + &this.tcx.sess.target.os, + Os::MacOs | Os::FreeBsd | Os::Solaris | Os::Illumos | Os::Linux | Os::Android + ) { + panic!("`fstatat` should not be called on {}", this.tcx.sess.target.os); + } + + let dirfd = this.read_scalar(dirfd_op)?.to_i32()?; + let path = this.read_pointer(path_op)?; + let flags = this.read_scalar(flags_op)?.to_i32()?; + + // Reject if isolation is enabled. + if let IsolatedOp::Reject(reject_with) = this.machine.isolated_op { + this.reject_in_isolation("`fstatat`", reject_with)?; + return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); + } + + // Parse flags. + let mut flags = flags; + // AT_SYMLINK_NOFOLLOW + let at_symlink_nofollow = this.eval_libc_i32("AT_SYMLINK_NOFOLLOW"); + let symlink_nofollow_flag = flags & at_symlink_nofollow == at_symlink_nofollow; + flags &= !at_symlink_nofollow; + // Complain about unknown flags. + if flags != 0 { + throw_unsup_format!("unsupported flags for `fstatat`: {flags:#x}") + } + + let path = this.read_path_from_c_str(path)?.into_owned(); + let metadata = if path.is_empty() { + throw_unsup_format!("fstatat: empty path is not supported"); + } else if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { + // Either absolute path (dirfd is ignored) or relative to working directory. + FileMetadata::from_host( + this, + if symlink_nofollow_flag { path.symlink_metadata() } else { path.metadata() }, + )? + } else { + // relative to dirfd, which must be a directory handle + let Some(fd) = this.machine.fds.get(dirfd) else { + return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + }; + let Some(dir) = fd.downcast::() else { + return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + }; + + #[cfg(not(bootstrap))] + let metadata = if symlink_nofollow_flag { + dir.dir.symlink_metadata(path) + } else { + dir.dir.metadata(path) + }; + #[cfg(bootstrap)] + let metadata = if symlink_nofollow_flag { + dir.fallback.join(path).symlink_metadata() + } else { + dir.fallback.join(path).metadata() + }; + FileMetadata::from_host(this, metadata)? + }; + + let metadata = match metadata { + Ok(metadata) => metadata, + Err(err) => return this.set_errno_and_return_neg1_i32(err), + }; + interp_ok(Scalar::from_i32(this.write_stat_buf(metadata, buf_op)?)) + } + fn linux_statx( &mut self, dirfd_op: &OpTy<'tcx>, // Should be an `int` @@ -852,18 +929,30 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Either absolute path (dirfd is ignored) or relative to working directory. FileMetadata::from_host( this, - if symlink_nofollow_flag { fs::symlink_metadata(path) } else { fs::metadata(path) }, + if symlink_nofollow_flag { path.symlink_metadata() } else { path.metadata() }, )? } else { // relative to dirfd, which must be a directory handle let Some(fd) = this.machine.fds.get(dirfd) else { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(_dir) = fd.downcast::() else { + let Some(dir) = fd.downcast::() else { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - throw_unsup_format!("statx relative to a directory handle is not supported"); + #[cfg(not(bootstrap))] + let metadata = if symlink_nofollow_flag { + dir.dir.symlink_metadata(path) + } else { + dir.dir.metadata(path) + }; + #[cfg(bootstrap)] + let metadata = if symlink_nofollow_flag { + dir.fallback.join(path).symlink_metadata() + } else { + dir.fallback.join(path).metadata() + }; + FileMetadata::from_host(this, metadata)? }; let metadata = match metadata { @@ -1133,12 +1222,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in between above and here. One day, the standard library will support converting // between `Dir` and `ReadDir` (one of the two directions would suffice for our // needs), then we'll use that. - let Ok(dir) = Dir::open(name) else { + let Ok(dir) = DirHandle::open(&name) else { throw_unsup_format!( "cannot `opendir` this directory: failed to create directory handle" ); }; - let dir = this.machine.fds.new_ref(DirHandle { dir }); + let dir = this.machine.fds.new_ref(dir); let dir_fd_id = dir.id(); let dir_fd_num = this.machine.fds.insert(dir); diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index b33de1b713fea..25ff4fe43b659 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -65,6 +65,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let result = this.fstat(fd, buf)?; this.write_scalar(result, dest)?; } + "fstatat$INODE64" => { + let [dirfd, path, buf, flags] = this.check_shim_sig( + shim_sig!(extern "C" fn(i32, *_, *_, i32) -> i32), + (link_name, abi, args), + )?; + let result = this.fstatat(dirfd, path, buf, flags)?; + this.write_scalar(result, dest)?; + } "opendir$INODE64" => { let [name] = this.check_shim_sig_deprecated(abi, CanonAbi::C, link_name, args)?; let result = this.opendir(name)?; diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index ff8bad7a16423..6fc9d37070f67 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -1,7 +1,6 @@ -use std::fs::{self, Dir}; -use std::io; use std::io::SeekFrom; use std::time::SystemTime; +use std::{fs, io}; use bitflags::bitflags; use rustc_abi::Size; @@ -214,7 +213,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Open this as a directory. // FIXME: shouldn't we check `creation_disposition` here? We do know that it already // exists. - let dir = match Dir::open(&file_name) { + let dir = match DirHandle::open(&file_name) { Ok(dir) => dir, Err(e) => { if e.kind() == io::ErrorKind::NotADirectory { @@ -226,9 +225,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } }; #[cfg(bootstrap)] - let metadata = dir.metadata(); + let metadata = dir.dir.metadata(); #[cfg(not(bootstrap))] - let metadata = dir.self_metadata(); + let metadata = dir.dir.self_metadata(); if !metadata.unwrap().is_dir() { // This changed from a directory to a file. Retry. continue; @@ -239,7 +238,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; } - let fd_num = this.machine.fds.insert_new(DirHandle { dir }); + let fd_num = this.machine.fds.insert_new(dir); return interp_ok(Handle::File(fd_num)); } else { // Per the documentation: From 0b55b7b87e32bb3327991067d52d94d0577176e8 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Fri, 25 Sep 2026 10:41:38 +0200 Subject: [PATCH 1061/1309] add an msrv tip regarding const contexts, duplicate stabilitiy dates and how to test Co-authored-by: Samuel Tardieu --- book/src/development/adding_lints.md | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/book/src/development/adding_lints.md b/book/src/development/adding_lints.md index 65226500c88ae..9771e8cf58540 100644 --- a/book/src/development/adding_lints.md +++ b/book/src/development/adding_lints.md @@ -531,6 +531,16 @@ define_Conf! { Afterwards update the documentation for the book as described in [Adding configuration to a lint](#adding-configuration-to-a-lint). +> [!TIP] +> Please be aware that items in the standard library usually have two stability dates. +> One for regular and one for const contexts. +> For example `str::split_at` became stable in Rust 1.4 and const stable in 1.86. +> +> To fix this, use `clippy_utils::is_in_const_context(cx)` together with MSRV checks. +> `clippy_utils::std_or_core(cx)` can also be necessary +> if the suggestions MSRV differs between `std` and `core`. +> To test the suggestions, annotate a `const` function with `#[clippy::msrv]` before and after the MSRV. + ## Author lint If you have trouble implementing your lint, there is also the internal `author` From d69bb7aea3441316b530180964be033c146f3650 Mon Sep 17 00:00:00 2001 From: Frank Elsinga Date: Thu, 24 Sep 2026 01:02:34 +0200 Subject: [PATCH 1062/1309] make `swap_ptr_to_ref` msrv capable and add a note why the snipped might be UB Co-authored-by: Gri-ffin <82527700+Gri-ffin@users.noreply.github.com> --- book/src/lint_configuration.md | 1 + clippy_config/src/conf.rs | 1 + clippy_lints/src/lib.rs | 2 +- clippy_lints/src/swap_ptr_to_ref.rs | 42 ++++++++++++++++++----- clippy_utils/src/msrvs.rs | 5 ++- tests/ui/swap_ptr_to_ref.fixed | 27 +++++++++++++++ tests/ui/swap_ptr_to_ref.rs | 27 +++++++++++++++ tests/ui/swap_ptr_to_ref.stderr | 33 +++++++++++++++++- tests/ui/swap_ptr_to_ref_unfixable.rs | 12 +++++++ tests/ui/swap_ptr_to_ref_unfixable.stderr | 15 +++++++- 10 files changed, 152 insertions(+), 13 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index 0cb26a63f945a..dd754a5c01661 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -1006,6 +1006,7 @@ The minimum rust version that the project supports. Defaults to the `rust-versio * [`repeat_vec_with_capacity`](https://rust-lang.github.io/rust-clippy/main/index.html#repeat_vec_with_capacity) * [`same_item_push`](https://rust-lang.github.io/rust-clippy/main/index.html#same_item_push) * [`seek_from_current`](https://rust-lang.github.io/rust-clippy/main/index.html#seek_from_current) +* [`swap_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/main/index.html#swap_ptr_to_ref) * [`to_digit_is_some`](https://rust-lang.github.io/rust-clippy/main/index.html#to_digit_is_some) * [`transmute_ptr_to_ref`](https://rust-lang.github.io/rust-clippy/main/index.html#transmute_ptr_to_ref) * [`tuple_array_conversions`](https://rust-lang.github.io/rust-clippy/main/index.html#tuple_array_conversions) diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index eee24f76d2f58..5bbde19229372 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -714,6 +714,7 @@ define_Conf! { repeat_vec_with_capacity, same_item_push, seek_from_current, + swap_ptr_to_ref, to_digit_is_some, transmute_ptr_to_ref, tuple_array_conversions, diff --git a/clippy_lints/src/lib.rs b/clippy_lints/src/lib.rs index 3e93e78cee63b..c8d881f8f84f2 100644 --- a/clippy_lints/src/lib.rs +++ b/clippy_lints/src/lib.rs @@ -748,7 +748,7 @@ rustc_lint::late_lint_methods!( FormatPushString: format_push_string::FormatPushString = format_push_string::FormatPushString::new(format_args.clone()), LargeIncludeFile: large_include_file::LargeIncludeFile = large_include_file::LargeIncludeFile::new(conf), RcCloneInVecInit: rc_clone_in_vec_init::RcCloneInVecInit = rc_clone_in_vec_init::RcCloneInVecInit, - SwapPtrToRef: swap_ptr_to_ref::SwapPtrToRef = swap_ptr_to_ref::SwapPtrToRef, + SwapPtrToRef: swap_ptr_to_ref::SwapPtrToRef = swap_ptr_to_ref::SwapPtrToRef::new(conf), TypeParamMismatch: mismatching_type_param_order::TypeParamMismatch = mismatching_type_param_order::TypeParamMismatch, ReadZeroByteVec: read_zero_byte_vec::ReadZeroByteVec = read_zero_byte_vec::ReadZeroByteVec, DefaultIterEmpty: default_instead_of_iter_empty::DefaultIterEmpty = default_instead_of_iter_empty::DefaultIterEmpty, diff --git a/clippy_lints/src/swap_ptr_to_ref.rs b/clippy_lints/src/swap_ptr_to_ref.rs index e475f96bba975..f4d32af59e361 100644 --- a/clippy_lints/src/swap_ptr_to_ref.rs +++ b/clippy_lints/src/swap_ptr_to_ref.rs @@ -1,9 +1,12 @@ +use clippy_config::Conf; use clippy_utils::diagnostics::span_lint_and_then; +use clippy_utils::msrvs::{self, Msrv}; use clippy_utils::res::{MaybeDef as _, MaybeResPath as _}; use clippy_utils::source::snippet_with_context; +use clippy_utils::{is_in_const_context, std_or_core}; use rustc_errors::Applicability; use rustc_hir::{BorrowKind, Expr, ExprKind, Mutability, UnOp}; -use rustc_lint::{LateContext, LateLintPass, declare_lint_pass}; +use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_span::{Span, SyntaxContext, sym}; declare_clippy_lint! { @@ -36,7 +39,17 @@ declare_clippy_lint! { "call to `mem::swap` using pointer derived references" } -declare_lint_pass!(SwapPtrToRef => [SWAP_PTR_TO_REF]); +impl_lint_pass!(SwapPtrToRef => [SWAP_PTR_TO_REF]); + +pub struct SwapPtrToRef { + msrv: Msrv, +} + +impl SwapPtrToRef { + pub fn new(conf: &'static Conf) -> Self { + Self { msrv: conf.msrv.into() } + } +} impl LateLintPass<'_> for SwapPtrToRef { fn check_expr(&mut self, cx: &LateContext<'_>, e: &Expr<'_>) { @@ -53,23 +66,34 @@ impl LateLintPass<'_> for SwapPtrToRef { e.span, "call to `core::mem::swap` with a parameter derived from a raw pointer", |diag| { - if !((from_ptr1 && arg1_span.is_none()) || (from_ptr2 && arg2_span.is_none())) { + if !((from_ptr1 && arg1_span.is_none()) || (from_ptr2 && arg2_span.is_none())) + && let Some(sugg_method) = ptr_swap_is_possible(cx, self.msrv) + { let mut app = Applicability::MachineApplicable; let snip1 = snippet_with_context(cx, arg1_span.unwrap_or(arg1.span), ctxt, "..", &mut app).0; let snip2 = snippet_with_context(cx, arg2_span.unwrap_or(arg2.span), ctxt, "..", &mut app).0; - diag.span_suggestion( - e.span, - "use ptr::swap", - format!("core::ptr::swap({snip1}, {snip2})"), - app, - ); + diag.span_suggestion(e.span, "use ptr::swap", format!("{sugg_method}({snip1}, {snip2})"), app); } + diag.note("at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior"); }, ); } } } +/// Returns the path to `ptr::swap` if it can be used +fn ptr_swap_is_possible(cx: &LateContext<'_>, msrv: Msrv) -> Option<&'static str> { + // stability in regular / const context: + // - core::ptr::swap 1.6 / 1.85 + // - std::ptr::swap 1.0 / 1.85 + match (std_or_core(cx), is_in_const_context(cx)) { + (Some("core" | "std"), true) if msrv.meets(cx, msrvs::CONST_PTR_SWAP) => Some("core::ptr::swap"), + (Some("core" | "std"), false) if msrv.meets(cx, msrvs::CORE_PTR_SWAP) => Some("core::ptr::swap"), + (Some("std"), false) => Some("std::ptr::swap"), + (_, _) => None, + } +} + /// Checks if the expression converts a mutable pointer to a mutable reference. If it is, also /// returns the span of the pointer expression if it's suitable for making a suggestion. fn is_ptr_to_ref(cx: &LateContext<'_>, e: &Expr<'_>, ctxt: SyntaxContext) -> (bool, Option) { diff --git a/clippy_utils/src/msrvs.rs b/clippy_utils/src/msrvs.rs index 4f1d3fa00b08d..91583b493265f 100644 --- a/clippy_utils/src/msrvs.rs +++ b/clippy_utils/src/msrvs.rs @@ -35,7 +35,9 @@ msrv_aliases! { 1,88,0 { LET_CHAINS, AS_CHUNKS, RAW_PTR_DEFAULT } 1,87,0 { OS_STR_DISPLAY, INT_MIDPOINT, CONST_CHAR_IS_DIGIT, UNSIGNED_IS_MULTIPLE_OF, INTEGER_SIGN_CAST } 1,86,0 { VEC_POP_IF } - 1,85,0 { UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL, WAKER_NOOP, ABS_CONST, RADIANS_CONST, CONST_MEM_SWAP } + 1,85,0 { + UINT_FLOAT_MIDPOINT, CONST_SIZE_OF_VAL, WAKER_NOOP, ABS_CONST, RADIANS_CONST, CONST_MEM_SWAP, CONST_PTR_SWAP, + } 1,84,0 { CONST_OPTION_AS_SLICE, MANUAL_DANGLING_PTR } 1,83,0 { CONST_EXTERN_FN, CONST_FLOAT_BITS_CONV, CONST_FLOAT_CLASSIFY, CONST_MUT_REFS, CONST_UNWRAP } 1,82,0 { IS_NONE_OR, REPEAT_N, RAW_REF_OP, SPECIALIZED_TO_STRING_FOR_REFS } @@ -92,6 +94,7 @@ msrv_aliases! { 1,16,0 { STR_REPEAT, RESULT_UNWRAP_OR_DEFAULT } 1,15,0 { MAYBE_BOUND_IN_WHERE } 1,13,0 { QUESTION_MARK_OPERATOR } + 1,6,0 { CORE_PTR_SWAP } 1,3,0 { DURATION_FROM_MILLIS_SECS } } diff --git a/tests/ui/swap_ptr_to_ref.fixed b/tests/ui/swap_ptr_to_ref.fixed index ec46368a95aed..89a1a7da400c7 100644 --- a/tests/ui/swap_ptr_to_ref.fixed +++ b/tests/ui/swap_ptr_to_ref.fixed @@ -24,3 +24,30 @@ fn main() { core::mem::swap(y, z); } + +mod pr17777 { + #[clippy::msrv = "1.5.0"] + fn before_core_msrv(y: *mut u32, z: *mut u32) { + unsafe { + std::ptr::swap(y, z); + //~^ swap_ptr_to_ref + } + } + + #[clippy::msrv = "1.6.0"] + fn after_core_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::ptr::swap(y, z); + //~^ swap_ptr_to_ref + } + } + + // before const is in .._unfixable since there is no suggestion to be made but this still needs to warn + #[clippy::msrv = "1.85.0"] + const fn after_const_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::ptr::swap(y, z); + //~^ swap_ptr_to_ref + } + } +} diff --git a/tests/ui/swap_ptr_to_ref.rs b/tests/ui/swap_ptr_to_ref.rs index 6a903ddb006d2..6c037b3d9d502 100644 --- a/tests/ui/swap_ptr_to_ref.rs +++ b/tests/ui/swap_ptr_to_ref.rs @@ -24,3 +24,30 @@ fn main() { core::mem::swap(y, z); } + +mod pr17777 { + #[clippy::msrv = "1.5.0"] + fn before_core_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::mem::swap(&mut *y, &mut *z); + //~^ swap_ptr_to_ref + } + } + + #[clippy::msrv = "1.6.0"] + fn after_core_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::mem::swap(&mut *y, &mut *z); + //~^ swap_ptr_to_ref + } + } + + // before const is in .._unfixable since there is no suggestion to be made but this still needs to warn + #[clippy::msrv = "1.85.0"] + const fn after_const_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::mem::swap(&mut *y, &mut *z); + //~^ swap_ptr_to_ref + } + } +} diff --git a/tests/ui/swap_ptr_to_ref.stderr b/tests/ui/swap_ptr_to_ref.stderr index 6b851901f82e5..d547b9b5e07c4 100644 --- a/tests/ui/swap_ptr_to_ref.stderr +++ b/tests/ui/swap_ptr_to_ref.stderr @@ -4,6 +4,7 @@ error: call to `core::mem::swap` with a parameter derived from a raw pointer LL | core::mem::swap(&mut *y, &mut *z); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(y, z)` | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior = note: `-D clippy::swap-ptr-to-ref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::swap_ptr_to_ref)]` @@ -12,18 +13,48 @@ error: call to `core::mem::swap` with a parameter derived from a raw pointer | LL | core::mem::swap(&mut *y, &mut x); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(y, &mut x)` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior error: call to `core::mem::swap` with a parameter derived from a raw pointer --> tests/ui/swap_ptr_to_ref.rs:15:9 | LL | core::mem::swap(&mut x, &mut *y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(&mut x, y)` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior error: call to `core::mem::swap` with a parameter derived from a raw pointer --> tests/ui/swap_ptr_to_ref.rs:17:9 | LL | core::mem::swap(&mut *addr_of_mut!(x), &mut *addr_of_mut!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(addr_of_mut!(x), addr_of_mut!(x))` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior + +error: call to `core::mem::swap` with a parameter derived from a raw pointer + --> tests/ui/swap_ptr_to_ref.rs:32:13 + | +LL | core::mem::swap(&mut *y, &mut *z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `std::ptr::swap(y, z)` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior + +error: call to `core::mem::swap` with a parameter derived from a raw pointer + --> tests/ui/swap_ptr_to_ref.rs:40:13 + | +LL | core::mem::swap(&mut *y, &mut *z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(y, z)` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior + +error: call to `core::mem::swap` with a parameter derived from a raw pointer + --> tests/ui/swap_ptr_to_ref.rs:49:13 + | +LL | core::mem::swap(&mut *y, &mut *z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use ptr::swap: `core::ptr::swap(y, z)` + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior -error: aborting due to 4 previous errors +error: aborting due to 7 previous errors diff --git a/tests/ui/swap_ptr_to_ref_unfixable.rs b/tests/ui/swap_ptr_to_ref_unfixable.rs index 9c7cf27096ccf..e7854848d52c6 100644 --- a/tests/ui/swap_ptr_to_ref_unfixable.rs +++ b/tests/ui/swap_ptr_to_ref_unfixable.rs @@ -21,3 +21,15 @@ fn main() { //~^ swap_ptr_to_ref } } + +fn pr17777() { + // after const is fixable -> in that test + #[clippy::msrv = "1.84.0"] + #[expect(clippy::incompatible_msrv)] + const fn before_const_msrv(y: *mut u32, z: *mut u32) { + unsafe { + core::mem::swap(&mut *y, &mut *z); + //~^ swap_ptr_to_ref + } + } +} diff --git a/tests/ui/swap_ptr_to_ref_unfixable.stderr b/tests/ui/swap_ptr_to_ref_unfixable.stderr index 3bb9d87b70a57..c783bd4f576ec 100644 --- a/tests/ui/swap_ptr_to_ref_unfixable.stderr +++ b/tests/ui/swap_ptr_to_ref_unfixable.stderr @@ -4,6 +4,7 @@ error: call to `core::mem::swap` with a parameter derived from a raw pointer LL | core::mem::swap(addr_of_mut_to_ref!(x), &mut *y); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior = note: `-D clippy::swap-ptr-to-ref` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(clippy::swap_ptr_to_ref)]` @@ -12,12 +13,24 @@ error: call to `core::mem::swap` with a parameter derived from a raw pointer | LL | core::mem::swap(&mut *y, addr_of_mut_to_ref!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior error: call to `core::mem::swap` with a parameter derived from a raw pointer --> tests/ui/swap_ptr_to_ref_unfixable.rs:20:9 | LL | core::mem::swap(addr_of_mut_to_ref!(x), addr_of_mut_to_ref!(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior + +error: call to `core::mem::swap` with a parameter derived from a raw pointer + --> tests/ui/swap_ptr_to_ref_unfixable.rs:31:13 + | +LL | core::mem::swap(&mut *y, &mut *z); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: at least one parameter is derived from a pointer and may overlap with the other, causing undefined behavior -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors From 5b4591290c5e1ddb005d017d48564dde515287fe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:10:08 +0200 Subject: [PATCH 1063/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 7d2cd0fbc092625ea371da704f15f80216d2220e. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 6b9ce9470f137..af092f4d3417d 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -56fad885ebfb0447660870715da4dfa75deae93d +7d2cd0fbc092625ea371da704f15f80216d2220e From 6d2f74f4dc488511d65836f3bbc55826ffabff42 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 6 Jul 2026 16:46:15 +0200 Subject: [PATCH 1064/1309] Emit llvm `dereferenceable` in more cases on newer LLVM versions Specifically on llvm >= 23.0.0 emit llvm `dereferenceable` attribute even without `nofree`, since new semantics allow that. --- compiler/rustc_codegen_llvm/src/abi.rs | 6 ++-- tests/codegen-llvm/drop-in-place-noalias.rs | 9 ++++- tests/codegen-llvm/function-arguments.rs | 40 ++++++++++++++------- tests/codegen-llvm/llvm-writable.rs | 13 +++++-- 4 files changed, 51 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs index e16f34483a0c5..19e6a3314f20a 100644 --- a/compiler/rustc_codegen_llvm/src/abi.rs +++ b/compiler/rustc_codegen_llvm/src/abi.rs @@ -80,9 +80,11 @@ fn get_attrs<'ll>(this: &ArgAttributes, cx: &CodegenCx<'ll, '_>) -> SmallVec<[&' // Only apply remaining attributes when optimizing if cx.sess().opts.optimize != config::OptLevel::No { let deref = this.pointee_size.bytes(); - // dereferenceable in LLVM currently implies nofree, so only emit dereferenceable if nofree + // Prior to dereferenceable in LLVM + // implied nofree, so only emit dereferenceable on older versions of LLVM if nofree // is also set. - if deref != 0 && regular.contains(ArgAttribute::NoFree) { + let llvm_version = crate::llvm_util::get_version(); + if deref != 0 && (llvm_version >= (23, 0, 0) || regular.contains(ArgAttribute::NoFree)) { if regular.contains(ArgAttribute::NonNull) { attrs.push(llvm::CreateDereferenceableAttr(cx.llcx, deref)); } else { diff --git a/tests/codegen-llvm/drop-in-place-noalias.rs b/tests/codegen-llvm/drop-in-place-noalias.rs index 86e0caa1b287d..caa00bfa1c2c3 100644 --- a/tests/codegen-llvm/drop-in-place-noalias.rs +++ b/tests/codegen-llvm/drop-in-place-noalias.rs @@ -1,4 +1,10 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes +// +// LLVM23 changed the meaning of "dereferenceable", allowing us to apply it in more cases, +// see . +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 // Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. // Note that non-Unpin types should not get `noalias`, matching &mut behavior. @@ -9,7 +15,8 @@ use std::marker::PhantomPinned; // CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}(ptr noalias nofree noundef align 4 dereferenceable(12) %{{.+}}) -// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}}) +// LLVM22: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}}) +// LLVM23: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef align 4 dereferenceable(12) %{{.+}}) pub struct StructUnpin { a: i32, diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index ef056769b147d..47600826b814b 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -1,4 +1,11 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes +// +// LLVM23 changed the meaning of "dereferenceable", allowing us to apply it in more cases, +// see . +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 + #![crate_type = "lib"] #![feature(rustc_attrs)] #![feature(allocator_api, unsafe_unpin)] @@ -84,13 +91,15 @@ pub fn option_nonzero_int(x: Option>) -> Option> { #[no_mangle] pub fn readonly_borrow(_: &i32) {} -// CHECK: noundef nonnull align 4 ptr @readonly_borrow_ret() +// LLVM22: noundef nonnull align 4 ptr @readonly_borrow_ret() +// LLVM23: noundef align 4 dereferenceable(4) ptr @readonly_borrow_ret() #[no_mangle] pub fn readonly_borrow_ret() -> &'static i32 { loop {} } -// CHECK: @unsafe_borrow(ptr noundef nonnull align 2 %_1) +// LLVM22: @unsafe_borrow(ptr noundef nonnull align 2 %_1) +// LLVM23: @unsafe_borrow(ptr noundef align 2 dereferenceable(2) %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) {} @@ -104,16 +113,18 @@ pub fn mutable_unsafe_borrow(_: &mut UnsafeInner) {} #[no_mangle] pub fn mutable_borrow(_: &mut i32) {} -// CHECK: noundef nonnull align 4 ptr @mutable_borrow_ret() +// LLVM22: noundef nonnull align 4 ptr @mutable_borrow_ret() +// LLVM23: noundef align 4 dereferenceable(4) ptr @mutable_borrow_ret() #[no_mangle] pub fn mutable_borrow_ret() -> &'static mut i32 { loop {} } #[no_mangle] -// CHECK: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1) +// LLVM22: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1) +// LLVM23: @mutable_notunpin_borrow(ptr noundef align 4 dereferenceable(4) %_1) // This one is *not* `noalias` because it might be self-referential. -// It is also not `dereferenceable` due to +// It is also not `dereferenceable` prior to LLVM23 due to // . pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {} @@ -147,8 +158,9 @@ pub fn raw_struct(_: *const S) {} pub fn raw_option_nonnull_struct(_: Option>) {} // `Box` can get deallocated during execution of the function, so it should -// not get `dereferenceable`. -// CHECK: noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x) +// not get `nofree` (or `dereferenceable` prior to LLVM23). +// LLVM22: noundef nonnull align 4 ptr @_box(ptr noalias noundef nonnull align 4 %x) +// LLVM23: noundef align 4 dereferenceable(4) ptr @_box(ptr noalias noundef align 4 dereferenceable(4) %x) #[no_mangle] pub fn _box(x: Box) -> Box { x @@ -157,13 +169,15 @@ pub fn _box(x: Box) -> Box { // With a custom allocator, it should *not* have `noalias`. (See // for why.) The second argument is the allocator, // which is a reference here that still carries `noalias` as usual. -// CHECK: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias nofree noundef nonnull readonly{{( captures\(address, read_provenance\))?}} %x.1) +// LLVM22: @_box_custom(ptr noundef nonnull align 4 %x.0, ptr noalias nofree noundef nonnull readonly{{( captures\(address, read_provenance\))?}} %x.1) +// LLVM23: @_box_custom(ptr noundef align 4 dereferenceable(4) %x.0, ptr noalias nofree noundef nonnull readonly{{( captures\(address, read_provenance\))?}} %x.1) #[no_mangle] pub fn _box_custom(x: Box) { drop(x) } -// CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) +// LLVM22: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) +// LLVM23: noundef align 4 dereferenceable(4) ptr @notunpin_box(ptr noundef align 4 dereferenceable(4) %x) #[no_mangle] pub fn notunpin_box(x: Box) -> Box { x @@ -238,14 +252,16 @@ pub fn trait_box_pin1(_: Box) {} pub fn trait_box_pin2(_: Box) {} // Same for mutable references (with a non-zero minimal size so that we also see the -// `dereferenceable` disappear). +// `dereferenceable` disappear prior to llvm23). // CHECK: @trait_mutref(ptr noalias nofree noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref(_: &mut (i32, dyn Drop + Unpin + UnsafeUnpin)) {} -// CHECK: @trait_mutref_pin1(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// LLVM22: @trait_mutref_pin1(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// LLVM23: @trait_mutref_pin1(ptr noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref_pin1(_: &mut (i32, dyn Drop + Unpin)) {} -// CHECK: @trait_mutref_pin2(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// LLVM22: @trait_mutref_pin2(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// LLVM23: @trait_mutref_pin2(ptr noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref_pin2(_: &mut (i32, dyn Drop + UnsafeUnpin)) {} diff --git a/tests/codegen-llvm/llvm-writable.rs b/tests/codegen-llvm/llvm-writable.rs index 0c72fb8a1dd9f..81a952a6483d4 100644 --- a/tests/codegen-llvm/llvm-writable.rs +++ b/tests/codegen-llvm/llvm-writable.rs @@ -1,6 +1,13 @@ //! The tests here test that the `-Zllvm-writable` flag and //! the `#[rustc_no_writable]` attribute have the desired effect. +// //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -Zllvm-writable +// +// LLVM23 changed the meaning of "dereferenceable", allowing us to apply it in more cases, +// see . +//@ revisions: LLVM22 LLVM23 +//@ [LLVM22] max-llvm-major-version: 22 +//@ [LLVM23] min-llvm-version: 23 #![crate_type = "lib"] #![feature(rustc_attrs, unsafe_pinned)] @@ -16,11 +23,13 @@ pub fn mutable_unsafe_borrow(_: &mut std::cell::UnsafeCell) {} #[no_mangle] pub fn option_borrow_mut(_: Option<&mut i32>) {} -// CHECK: @box_moved(ptr noalias noundef nonnull align 4 %0) +// LLVM22: @box_moved(ptr noalias noundef nonnull align 4 %0) +// LLVM23: @box_moved(ptr noalias noundef align 4 dereferenceable(4) %0) #[no_mangle] pub fn box_moved(_: Box) {} -// CHECK: @unsafe_pinned_borrow_mut(ptr noundef nonnull align 4 %_1) +// LLVM22: @unsafe_pinned_borrow_mut(ptr noundef nonnull align 4 %_1) +// LLVM23: @unsafe_pinned_borrow_mut(ptr noundef align 4 dereferenceable(4) %_1) #[no_mangle] pub fn unsafe_pinned_borrow_mut(_: &mut std::pin::UnsafePinned) {} From f02d1d5224d53e14dabd1f1efd6b7de36ce480e6 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Sep 2026 11:30:42 +0200 Subject: [PATCH 1065/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-30 (5c543b0b8c73c7b72bc8284ced4fb22ead15734d). --- compiler/rustc_codegen_cranelift/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index 9e21c2ed9a9b2..a6468283e1270 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-28" +channel = "nightly-2026-09-30" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From f6e6de63d263f429a0318d82dc7f3cef15f9a895 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Sep 2026 11:50:49 +0200 Subject: [PATCH 1066/1309] Fix rustc test suite --- compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh index 5a1374fe56e09..648f68588e04b 100755 --- a/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh +++ b/compiler/rustc_codegen_cranelift/scripts/test_rustc_tests.sh @@ -164,6 +164,7 @@ rm -r tests/run-make/const-trait-stable-toolchain # same rm -r tests/run-make/print-request-help-stable-unstable # same rm -r tests/run-make/issue-149402-suggest-unresolve # same rm -r tests/run-make/const-destruct-stable-toolchain # same +rm -r tests/run-make/unstable-target-feature # same rm -r tests/run-make/incr-add-rust-src-component rm tests/ui/errors/remap-path-prefix-sysroot.rs # different sysroot source path rm -r tests/run-make/export # something about rustc version mismatches From bbf54426a22d640e4db1bafbf0e9d6b497cfe0aa Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Wed, 30 Sep 2026 11:53:33 +0200 Subject: [PATCH 1067/1309] Fix pushes --- compiler/rustc_codegen_cranelift/scripts/rustup.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index 80e9c4f78c4a6..8bd41f98ce550 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -2,7 +2,7 @@ set -e -export GIT_CONFIG_GLOBAL=../rust/josh.gitconfig +export GIT_CONFIG_GLOBAL=$(pwd)/../rust/josh.gitconfig export RUSTC_GIT=../rust case $1 in From 13035c1c803e33a62e1c8bea4a7ce0569f420cb4 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 30 Sep 2026 12:10:04 +0200 Subject: [PATCH 1068/1309] Iterate only once to get module inner attributes position --- compiler/rustc_resolve/src/late.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index ab595de3e39e7..3c7304e1dc92d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -2861,12 +2861,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } fn resolve_item(&mut self, item: &'ast Item) { + let mut mod_inner_attrs_start = None; match item.kind { ItemKind::Mod(..) => { // We only handle outer doc comments for modules here. let attrs = if let Some(pos) = item.attrs.iter().position(|a| { a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) }) { + mod_inner_attrs_start = Some(pos); &item.attrs[..pos] } else { &item.attrs @@ -2972,9 +2974,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { // Outer doc comments were already handled above, now we handle // inner doc comments. - let attrs = if let Some(pos) = item.attrs.iter().position(|a| { - a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) - }) { + let attrs = if let Some(pos) = mod_inner_attrs_start { &item.attrs[pos..] } else { &[] From 1a60c280cdbbe6ac28b56a170b00dfe8756f8026 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 30 Sep 2026 12:10:23 +0200 Subject: [PATCH 1069/1309] Run cg_gcc tests with the in-tree compiler --- src/bootstrap/src/core/build_steps/test.rs | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 3006fddbbe662..479e517038597 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -4530,20 +4530,19 @@ impl CommandLineStep for CodegenGCC { let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) }); + // We need to run the cg_gcc tests with the compiler against it links to, not with + // the build compiler. + let target_compiler = compilers.target_compiler(); + builder.ensure( - compile::Std::new(compilers.build_compiler(), target) + compile::Std::new(target_compiler, target) .extra_rust_args(&["-Csymbol-mangling-version=v0", "-Cpanic=abort"]), ); - let _guard = builder.msg_test( - "rustc_codegen_gcc", - compilers.target(), - compilers.target_compiler().stage, - ); - + let _guard = builder.msg_test("rustc_codegen_gcc", target, target_compiler.stage); let mut cargo = builder::Cargo::new( builder, - compilers.build_compiler(), + target_compiler, Mode::Codegen, // Must be codegen to ensure dlopen on compiled dylibs works SourceType::InTree, target, From c7e5a829435de510c3da410a7f4c5d8f8d6f5d1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Wed, 30 Sep 2026 12:10:33 +0200 Subject: [PATCH 1070/1309] Add `rustc_private` to cg_gcc examples --- compiler/rustc_codegen_gcc/example/mini_core.rs | 3 ++- compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs | 4 ++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 2d5a29ceb8191..3187526d719f2 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -10,7 +10,8 @@ auto_traits, freeze_impls, pattern_types, - thread_local + thread_local, + rustc_private )] #![no_core] #![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)] diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index ab841d51a7f53..c3dd745c23cc9 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -1,8 +1,8 @@ // Adapted from https://github.com/sunfishcode/mir2cranelift/blob/master/rust-examples/nocore-hello-world.rs #![feature( - no_core, unboxed_closures, lang_items, never_type, linkage, - extern_types, thread_local + no_core, unboxed_closures, lang_items, linkage, + extern_types, thread_local, rustc_private )] #![no_core] #![allow(dead_code, internal_features, non_camel_case_types)] From 5658d6b8087cc83c28459f2c02def2b57e3c1896 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 12:12:21 +0200 Subject: [PATCH 1071/1309] update lockfile --- Cargo.lock | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 39049cd7e2c6f..9894e374a0bf0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2558,8 +2558,10 @@ dependencies = [ "serde", "serde_json", "smallvec", + "socket2", "tempfile", "ui_test", + "windows-sys 0.61.2", ] [[package]] @@ -5472,9 +5474,9 @@ checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" [[package]] name = "socket2" -version = "0.6.3" +version = "0.6.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3a766e1110788c36f4fa1c2b71b387a7815aa65f88ce0229841826633d93723e" +checksum = "c3d1e2c7f27f8d4cb10542a02c49005dbd6e93095799d6f3be745fae9f8fedd4" dependencies = [ "libc", "windows-sys 0.61.2", From cce472e4ad75ebd99f4401ececf1a5607790245e Mon Sep 17 00:00:00 2001 From: Kokoro2336 <2529677678@qq.com> Date: Sat, 2 May 2026 14:45:25 +0800 Subject: [PATCH 1072/1309] feat: new lint unnecessary_as_slice. test: unnecessary_as_slice uitest. fix: CHANGELOG. test: allow unnecessary_as_slice in some uitests. fix: refine matching logic. test: supply non-receiver cases. fix: checking from_expansion(). fix: do not lint trait method. Update clippy_lints/src/methods/mod.rs Co-authored-by: Samuel Tardieu refactor: move the check to the inner. Update clippy_lints/src/methods/mod.rs Co-authored-by: Samuel Tardieu test: use expect instead of allow. retrigger the ci. fix: excluding as_ptr and as_mut_ptr. --- CHANGELOG.md | 1 + clippy_lints/src/declared_lints.rs | 1 + clippy_lints/src/methods/mod.rs | 26 ++++ .../src/methods/unnecessary_as_slice.rs | 43 +++++++ clippy_utils/src/sym.rs | 3 + tests/ui/into_iter_without_iter.rs | 1 + tests/ui/into_iter_without_iter.stderr | 12 +- tests/ui/needless_for_each_fixable.fixed | 3 +- tests/ui/needless_for_each_fixable.rs | 3 +- tests/ui/needless_for_each_fixable.stderr | 24 ++-- tests/ui/new_without_default.fixed | 6 +- tests/ui/new_without_default.rs | 6 +- tests/ui/new_without_default.stderr | 32 ++--- tests/ui/return_and_then.fixed | 2 +- tests/ui/return_and_then.rs | 2 +- tests/ui/unnecessary_as_slice.fixed | 113 ++++++++++++++++++ tests/ui/unnecessary_as_slice.rs | 113 ++++++++++++++++++ tests/ui/unnecessary_as_slice.stderr | 59 +++++++++ 18 files changed, 410 insertions(+), 40 deletions(-) create mode 100644 clippy_lints/src/methods/unnecessary_as_slice.rs create mode 100644 tests/ui/unnecessary_as_slice.fixed create mode 100644 tests/ui/unnecessary_as_slice.rs create mode 100644 tests/ui/unnecessary_as_slice.stderr diff --git a/CHANGELOG.md b/CHANGELOG.md index f6814f0a9c7ee..1959367849b4a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7670,6 +7670,7 @@ Released 2018-09-13 [`unit_hash`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_hash [`unit_return_expecting_ord`]: https://rust-lang.github.io/rust-clippy/main/index.html#unit_return_expecting_ord [`unknown_clippy_lints`]: https://rust-lang.github.io/rust-clippy/main/index.html#unknown_clippy_lints +[`unnecessary_as_slice`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_as_slice [`unnecessary_box_returns`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_box_returns [`unnecessary_cast`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_cast [`unnecessary_clippy_cfg`]: https://rust-lang.github.io/rust-clippy/main/index.html#unnecessary_clippy_cfg diff --git a/clippy_lints/src/declared_lints.rs b/clippy_lints/src/declared_lints.rs index da0bd90cc50c1..15872aa538e53 100644 --- a/clippy_lints/src/declared_lints.rs +++ b/clippy_lints/src/declared_lints.rs @@ -503,6 +503,7 @@ pub static LINTS: &[&::declare_clippy_lint::LintInfo] = &[ crate::methods::UNBUFFERED_BYTES_INFO, crate::methods::UNINIT_ASSUMED_INIT_INFO, crate::methods::UNIT_HASH_INFO, + crate::methods::UNNECESSARY_AS_SLICE_INFO, crate::methods::UNNECESSARY_FALLIBLE_CONVERSIONS_INFO, crate::methods::UNNECESSARY_FILTER_MAP_INFO, crate::methods::UNNECESSARY_FIND_MAP_INFO, diff --git a/clippy_lints/src/methods/mod.rs b/clippy_lints/src/methods/mod.rs index 342e258e2e764..1dc03351c8462 100644 --- a/clippy_lints/src/methods/mod.rs +++ b/clippy_lints/src/methods/mod.rs @@ -133,6 +133,7 @@ mod type_id_on_box; mod unbuffered_bytes; mod uninit_assumed_init; mod unit_hash; +mod unnecessary_as_slice; mod unnecessary_fallible_conversions; mod unnecessary_filter_map; mod unnecessary_first_then_check; @@ -4234,6 +4235,29 @@ declare_clippy_lint! { "hashing a unit value, which does nothing" } +declare_clippy_lint! { + /// ### What it does + /// Looks for unnecessary calls to `as_slice()` on `Vec`. + /// + /// ### Why is this bad? + /// Calling `as_slice()` on a `Vec` before calling a method on it may be unnecessary because `Vec`s auto-dereference as slices. + /// + /// ### Example + /// ```no_run + /// let v = vec![1, 2, 3]; + /// let v_len = v.as_slice().len(); + /// ``` + /// Use instead: + /// ```no_run + /// let v = vec![1, 2, 3]; + /// let v_len = v.len(); + /// ``` + #[clippy::version = "1.97.0"] + pub UNNECESSARY_AS_SLICE, + complexity, + "using `as_slice()` on a `Vec` when it is not necessary" +} + declare_clippy_lint! { /// ### What it does /// Checks for calls to `TryInto::try_into` and `TryFrom::try_from` when their infallible counterparts @@ -5139,6 +5163,7 @@ impl_lint_pass!(Methods => [ UNBUFFERED_BYTES, UNINIT_ASSUMED_INIT, UNIT_HASH, + UNNECESSARY_AS_SLICE, UNNECESSARY_FALLIBLE_CONVERSIONS, UNNECESSARY_FILTER_MAP, UNNECESSARY_FIND_MAP, @@ -5430,6 +5455,7 @@ impl Methods { } sliced_string_as_bytes::check(cx, expr, recv); }, + (sym::as_slice | sym::as_mut_slice, []) => unnecessary_as_slice::check(cx, expr, recv, name), (sym::as_mut | sym::as_ref, []) => useless_asref::check(cx, expr, name, recv), (sym::as_ptr, []) => manual_c_str_literals::check_as_ptr(cx, expr, recv, self.msrv), (sym::assume_init, []) => uninit_assumed_init::check(cx, expr, recv), diff --git a/clippy_lints/src/methods/unnecessary_as_slice.rs b/clippy_lints/src/methods/unnecessary_as_slice.rs new file mode 100644 index 0000000000000..ea7398094c57c --- /dev/null +++ b/clippy_lints/src/methods/unnecessary_as_slice.rs @@ -0,0 +1,43 @@ +use super::UNNECESSARY_AS_SLICE; +use clippy_utils::diagnostics::span_lint_and_sugg; +use clippy_utils::{get_parent_expr, sym}; +use rustc_errors::Applicability; +use rustc_hir::{Expr, ExprKind, PathSegment}; +use rustc_lint::LateContext; +use rustc_span::Symbol; + +pub(super) fn check(cx: &LateContext<'_>, expr: &Expr<'_>, recv: &Expr<'_>, name: Symbol) { + if !expr.span.from_expansion() + && let Some(parent_expr) = get_parent_expr(cx, expr) + // the parent is also a method call + && let ExprKind::MethodCall(PathSegment { ident: parent_method_ident, .. }, parent_recv, ..) = parent_expr.kind + // Excluding `as_ptr` and `as_mut_ptr` because they are commonly used to get raw pointers for FFI or unsafe code, and removing them might change the semantics of the code. + && !(parent_method_ident.name == sym::as_ptr || parent_method_ident.name == sym::as_mut_ptr) + // the parent's recv is the same as the current expr + && parent_recv.hir_id == expr.hir_id + // the parent is not a trait method + && let opt_fn_id = cx.typeck_results().type_dependent_def_id(parent_expr.hir_id) + && opt_fn_id.is_none_or(|fn_id| cx.tcx.trait_of_assoc(fn_id).is_none()) + // checking whether the recv is a `Vec` + && cx + .typeck_results() + .expr_ty(recv) + .peel_refs() + .ty_adt_def() + .is_some_and(|adt| cx.tcx.is_diagnostic_item(sym::Vec, adt.did())) + && let Some(as_slice_span) = expr.span.trim_start(recv.span) + { + let parent_method_name = parent_method_ident.name; + span_lint_and_sugg( + cx, + UNNECESSARY_AS_SLICE, + as_slice_span, + format!( + "this `{name}` is unnecessary because the following method (`{parent_method_name}`) can be called on `Vec` directly" + ), + format!("remove `{name}`"), + String::new(), + Applicability::MachineApplicable, + ); + } +} diff --git a/clippy_utils/src/sym.rs b/clippy_utils/src/sym.rs index b452c954e937b..a86603dd545a1 100644 --- a/clippy_utils/src/sym.rs +++ b/clippy_utils/src/sym.rs @@ -139,8 +139,11 @@ generate! { as_deref, as_deref_mut, as_mut, + as_mut_ptr, + as_mut_slice, as_path, as_ptr, + as_slice, as_str, assert_failed, author, diff --git a/tests/ui/into_iter_without_iter.rs b/tests/ui/into_iter_without_iter.rs index f0b86e5620e9b..9a41c0d48679c 100644 --- a/tests/ui/into_iter_without_iter.rs +++ b/tests/ui/into_iter_without_iter.rs @@ -1,6 +1,7 @@ //@no-rustfix: suggestions reference out of scope lifetimes/types //@aux-build:proc_macros.rs #![warn(clippy::into_iter_without_iter)] +#![expect(clippy::unnecessary_as_slice)] extern crate proc_macros; use std::iter::IntoIterator; diff --git a/tests/ui/into_iter_without_iter.stderr b/tests/ui/into_iter_without_iter.stderr index a033ff645f49a..63c9e1d469232 100644 --- a/tests/ui/into_iter_without_iter.stderr +++ b/tests/ui/into_iter_without_iter.stderr @@ -1,5 +1,5 @@ error: `IntoIterator` implemented for a reference type without an `iter` method - --> tests/ui/into_iter_without_iter.rs:9:1 + --> tests/ui/into_iter_without_iter.rs:10:1 | LL | / impl<'a> IntoIterator for &'a S1 { LL | | @@ -22,7 +22,7 @@ LL + } | error: `IntoIterator` implemented for a reference type without an `iter_mut` method - --> tests/ui/into_iter_without_iter.rs:17:1 + --> tests/ui/into_iter_without_iter.rs:18:1 | LL | / impl<'a> IntoIterator for &'a mut S1 { LL | | @@ -43,7 +43,7 @@ LL + } | error: `IntoIterator` implemented for a reference type without an `iter` method - --> tests/ui/into_iter_without_iter.rs:27:1 + --> tests/ui/into_iter_without_iter.rs:28:1 | LL | / impl<'a, T> IntoIterator for &'a S2 { LL | | @@ -64,7 +64,7 @@ LL + } | error: `IntoIterator` implemented for a reference type without an `iter_mut` method - --> tests/ui/into_iter_without_iter.rs:35:1 + --> tests/ui/into_iter_without_iter.rs:36:1 | LL | / impl<'a, T> IntoIterator for &'a mut S2 { LL | | @@ -85,7 +85,7 @@ LL + } | error: `IntoIterator` implemented for a reference type without an `iter_mut` method - --> tests/ui/into_iter_without_iter.rs:86:1 + --> tests/ui/into_iter_without_iter.rs:87:1 | LL | / impl<'a, T> IntoIterator for &mut S4<'a, T> { LL | | @@ -106,7 +106,7 @@ LL + } | error: `IntoIterator` implemented for a reference type without an `iter` method - --> tests/ui/into_iter_without_iter.rs:120:9 + --> tests/ui/into_iter_without_iter.rs:121:9 | LL | / impl<'a> IntoIterator for &'a Issue12037 { LL | | diff --git a/tests/ui/needless_for_each_fixable.fixed b/tests/ui/needless_for_each_fixable.fixed index d6c7e42e13d32..8a410bd7c4daa 100644 --- a/tests/ui/needless_for_each_fixable.fixed +++ b/tests/ui/needless_for_each_fixable.fixed @@ -3,7 +3,8 @@ clippy::let_unit_value, clippy::match_single_binding, clippy::needless_return, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::unnecessary_as_slice )] use std::collections::HashMap; diff --git a/tests/ui/needless_for_each_fixable.rs b/tests/ui/needless_for_each_fixable.rs index 9bb2e6cf07d24..ae8a6b70ab590 100644 --- a/tests/ui/needless_for_each_fixable.rs +++ b/tests/ui/needless_for_each_fixable.rs @@ -3,7 +3,8 @@ clippy::let_unit_value, clippy::match_single_binding, clippy::needless_return, - clippy::uninlined_format_args + clippy::uninlined_format_args, + clippy::unnecessary_as_slice )] use std::collections::HashMap; diff --git a/tests/ui/needless_for_each_fixable.stderr b/tests/ui/needless_for_each_fixable.stderr index 26d0da69c8559..121669d15072f 100644 --- a/tests/ui/needless_for_each_fixable.stderr +++ b/tests/ui/needless_for_each_fixable.stderr @@ -1,5 +1,5 @@ error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:14:5 + --> tests/ui/needless_for_each_fixable.rs:15:5 | LL | / v.iter().for_each(|elem| { LL | | @@ -18,7 +18,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:18:5 + --> tests/ui/needless_for_each_fixable.rs:19:5 | LL | / v.into_iter().for_each(|elem| { LL | | @@ -35,7 +35,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:23:5 + --> tests/ui/needless_for_each_fixable.rs:24:5 | LL | / [1, 2, 3].iter().for_each(|elem| { LL | | @@ -52,7 +52,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:29:5 + --> tests/ui/needless_for_each_fixable.rs:30:5 | LL | / hash_map.iter().for_each(|(k, v)| { LL | | @@ -69,7 +69,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:33:5 + --> tests/ui/needless_for_each_fixable.rs:34:5 | LL | / hash_map.iter_mut().for_each(|(k, v)| { LL | | @@ -86,7 +86,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:37:5 + --> tests/ui/needless_for_each_fixable.rs:38:5 | LL | / hash_map.keys().for_each(|k| { LL | | @@ -103,7 +103,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:41:5 + --> tests/ui/needless_for_each_fixable.rs:42:5 | LL | / hash_map.values().for_each(|v| { LL | | @@ -120,7 +120,7 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:49:5 + --> tests/ui/needless_for_each_fixable.rs:50:5 | LL | / my_vec().iter().for_each(|elem| { LL | | @@ -137,25 +137,25 @@ LL + } | error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:134:9 + --> tests/ui/needless_for_each_fixable.rs:135:9 | LL | rows.iter().for_each(|x| _ = v.push(x)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { _ = v.push(x) }` error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:141:9 + --> tests/ui/needless_for_each_fixable.rs:142:9 | LL | rows.iter().for_each(|x| do_something(x, 1u8)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for x in rows.iter() { do_something(x, 1u8); }` error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:148:5 + --> tests/ui/needless_for_each_fixable.rs:149:5 | LL | vec.iter().for_each(|v| println!("{v}")); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: try: `for v in vec.iter() { println!("{v}"); }` error: needless use of `for_each` - --> tests/ui/needless_for_each_fixable.rs:154:5 + --> tests/ui/needless_for_each_fixable.rs:155:5 | LL | / vec.iter().for_each(|elem| { LL | | diff --git a/tests/ui/new_without_default.fixed b/tests/ui/new_without_default.fixed index a9710996f7df5..6703d591ec6ff 100644 --- a/tests/ui/new_without_default.fixed +++ b/tests/ui/new_without_default.fixed @@ -1,5 +1,9 @@ #![warn(clippy::new_without_default)] -#![expect(clippy::extra_unused_lifetimes, clippy::missing_safety_doc)] +#![expect( + clippy::extra_unused_lifetimes, + clippy::missing_safety_doc, + clippy::unnecessary_as_slice +)] pub struct Foo; diff --git a/tests/ui/new_without_default.rs b/tests/ui/new_without_default.rs index d6a42036e4014..4bb3e92f9b07c 100644 --- a/tests/ui/new_without_default.rs +++ b/tests/ui/new_without_default.rs @@ -1,5 +1,9 @@ #![warn(clippy::new_without_default)] -#![expect(clippy::extra_unused_lifetimes, clippy::missing_safety_doc)] +#![expect( + clippy::extra_unused_lifetimes, + clippy::missing_safety_doc, + clippy::unnecessary_as_slice +)] pub struct Foo; diff --git a/tests/ui/new_without_default.stderr b/tests/ui/new_without_default.stderr index 63a9baa6c5a24..ce4fae3e293d5 100644 --- a/tests/ui/new_without_default.stderr +++ b/tests/ui/new_without_default.stderr @@ -1,5 +1,5 @@ error: you should consider adding a `Default` implementation for `Foo` - --> tests/ui/new_without_default.rs:7:5 + --> tests/ui/new_without_default.rs:11:5 | LL | / pub fn new() -> Foo { LL | | @@ -22,7 +22,7 @@ LL + } | error: you should consider adding a `Default` implementation for `Bar` - --> tests/ui/new_without_default.rs:17:5 + --> tests/ui/new_without_default.rs:21:5 | LL | / pub fn new() -> Self { LL | | @@ -43,7 +43,7 @@ LL + } | error: you should consider adding a `Default` implementation for `LtKo<'c>` - --> tests/ui/new_without_default.rs:83:5 + --> tests/ui/new_without_default.rs:87:5 | LL | / pub fn new() -> LtKo<'c> { LL | | @@ -64,7 +64,7 @@ LL + } | error: you should consider adding a `Default` implementation for `Const` - --> tests/ui/new_without_default.rs:117:5 + --> tests/ui/new_without_default.rs:121:5 | LL | / pub const fn new() -> Const { LL | | @@ -84,7 +84,7 @@ LL + } | error: you should consider adding a `Default` implementation for `NewNotEqualToDerive` - --> tests/ui/new_without_default.rs:178:5 + --> tests/ui/new_without_default.rs:182:5 | LL | / pub fn new() -> Self { LL | | @@ -105,7 +105,7 @@ LL + } | error: you should consider adding a `Default` implementation for `FooGenerics` - --> tests/ui/new_without_default.rs:188:5 + --> tests/ui/new_without_default.rs:192:5 | LL | / pub fn new() -> Self { LL | | @@ -126,7 +126,7 @@ LL + } | error: you should consider adding a `Default` implementation for `BarGenerics` - --> tests/ui/new_without_default.rs:197:5 + --> tests/ui/new_without_default.rs:201:5 | LL | / pub fn new() -> Self { LL | | @@ -147,7 +147,7 @@ LL + } | error: you should consider adding a `Default` implementation for `Foo` - --> tests/ui/new_without_default.rs:210:9 + --> tests/ui/new_without_default.rs:214:9 | LL | / pub fn new() -> Self { LL | | @@ -168,7 +168,7 @@ LL + } | error: you should consider adding a `Default` implementation for `MyStruct` - --> tests/ui/new_without_default.rs:257:5 + --> tests/ui/new_without_default.rs:261:5 | LL | / pub fn new() -> Self { LL | | @@ -191,7 +191,7 @@ LL + } | error: you should consider adding a `Default` implementation for `NewWithCfg` - --> tests/ui/new_without_default.rs:268:5 + --> tests/ui/new_without_default.rs:272:5 | LL | / pub fn new() -> Self { LL | | @@ -212,7 +212,7 @@ LL + } | error: you should consider adding a `Default` implementation for `NewWith2Cfgs` - --> tests/ui/new_without_default.rs:278:5 + --> tests/ui/new_without_default.rs:282:5 | LL | / pub fn new() -> Self { LL | | @@ -234,7 +234,7 @@ LL + } | error: you should consider adding a `Default` implementation for `NewWithExtraneous` - --> tests/ui/new_without_default.rs:287:5 + --> tests/ui/new_without_default.rs:291:5 | LL | / pub fn new() -> Self { LL | | @@ -254,7 +254,7 @@ LL + } | error: you should consider adding a `Default` implementation for `NewWithCfgAndExtraneous` - --> tests/ui/new_without_default.rs:297:5 + --> tests/ui/new_without_default.rs:301:5 | LL | / pub fn new() -> Self { LL | | @@ -275,7 +275,7 @@ LL + } | error: you should consider adding a `Default` implementation for `Foo` - --> tests/ui/new_without_default.rs:335:9 + --> tests/ui/new_without_default.rs:339:9 | LL | / pub fn new() -> Self LL | | @@ -302,7 +302,7 @@ LL + } | error: you should consider adding a `Default` implementation for `Bar` - --> tests/ui/new_without_default.rs:349:9 + --> tests/ui/new_without_default.rs:353:9 | LL | / pub fn new() -> Self LL | | @@ -328,7 +328,7 @@ LL + } | error: you should consider adding a `Default` implementation for `S` - --> tests/ui/new_without_default.rs:372:9 + --> tests/ui/new_without_default.rs:376:9 | LL | / pub fn new() -> S { LL | | diff --git a/tests/ui/return_and_then.fixed b/tests/ui/return_and_then.fixed index a0a6314038aa6..65272418bf21f 100644 --- a/tests/ui/return_and_then.fixed +++ b/tests/ui/return_and_then.fixed @@ -1,5 +1,5 @@ #![warn(clippy::return_and_then)] -#![expect(clippy::manual_filter)] +#![expect(clippy::manual_filter, clippy::unnecessary_as_slice)] fn main() { fn test_opt_block(opt: Option) -> Option { diff --git a/tests/ui/return_and_then.rs b/tests/ui/return_and_then.rs index 8ab52ed016dc1..0789b92bfbd09 100644 --- a/tests/ui/return_and_then.rs +++ b/tests/ui/return_and_then.rs @@ -1,5 +1,5 @@ #![warn(clippy::return_and_then)] -#![expect(clippy::manual_filter)] +#![expect(clippy::manual_filter, clippy::unnecessary_as_slice)] fn main() { fn test_opt_block(opt: Option) -> Option { diff --git a/tests/ui/unnecessary_as_slice.fixed b/tests/ui/unnecessary_as_slice.fixed new file mode 100644 index 0000000000000..6caa75937f180 --- /dev/null +++ b/tests/ui/unnecessary_as_slice.fixed @@ -0,0 +1,113 @@ +#![warn(clippy::unnecessary_as_slice)] +#![allow(clippy::const_is_empty, clippy::ptr_arg)] +#![expect(unused)] + +trait SliceExt { + fn my_len(&self) -> usize; +} + +impl SliceExt for [u32] { + fn my_len(&self) -> usize { + self.len() + } +} + +fn by_ref(vals: &mut Vec) { + let _ = vals.len(); + //~^ unnecessary_as_slice + let _ = vals.is_empty(); + //~^ unnecessary_as_slice + let _ = vals.iter(); + //~^ unnecessary_as_slice + let _ = vals.first(); + //~^ unnecessary_as_slice + + let _ = vals.len(); + //~^ unnecessary_as_slice + let _ = vals.is_empty(); + //~^ unnecessary_as_slice + let _ = vals.iter_mut(); + //~^ unnecessary_as_slice +} + +fn by_value(mut vals: Vec) { + let _ = vals.len(); + //~^ unnecessary_as_slice + let _ = vals.len(); + //~^ unnecessary_as_slice +} + +fn custom_trait_method(mut vals: Vec) { + let _ = vals.as_slice().my_len(); + let _ = vals.as_mut_slice().my_len(); +} + +fn no_lint_cases(vals: &mut Vec) { + // Don't lint as_slice() received by a value + let s = vals.as_slice(); + let _ = s.len(); + + fn takes_slice(_: &[u32]) {} + takes_slice(vals.as_slice()); + + let _ = vals.len(); + let _ = vals.is_empty(); + + fn non_recv(_: &[u32]) {} + // Don't lint as_slice() when it's not the receiver of the method call + non_recv(vals.as_slice()); + + // Don't lint if as_slice() is in a macro. + macro_rules! as_slice_in_macro { + ($vals:expr) => { + let _ = $vals.as_slice().len(); + let _ = $vals.as_mut_slice().len(); + }; + } + + as_slice_in_macro!(vals); + + trait NoLintTrait { + fn foo(&self) -> usize; + fn bar(&mut self) -> usize; + } + + impl NoLintTrait for Vec { + fn foo(&self) -> usize { + 1 + } + fn bar(&mut self) -> usize { + 2 + } + } + + impl NoLintTrait for [u32] { + fn foo(&self) -> usize { + 3 + } + fn bar(&mut self) -> usize { + 4 + } + } + + // Don't lint trait method calls. + let _ = vals.as_slice().foo(); + let _ = vals.as_mut_slice().bar(); +} + +fn no_lint_non_vec(vals: &[u32]) { + // vec_as_slice diagnostic item should only applies to Vec::as_slice + let _ = vals.len(); + let _ = vals.is_empty(); +} + +// Don't lint if the parent method is `as_ptr` or `as_mut_ptr` +fn no_lint_as_ptr(vals: &mut Vec) { + let _ = vals.as_ptr(); + let _ = vals.as_mut_ptr(); + + let _ = vals.as_slice().as_ptr(); + let _ = vals.as_mut_slice().as_mut_ptr(); +} + +fn main() {} diff --git a/tests/ui/unnecessary_as_slice.rs b/tests/ui/unnecessary_as_slice.rs new file mode 100644 index 0000000000000..ff8763555e12d --- /dev/null +++ b/tests/ui/unnecessary_as_slice.rs @@ -0,0 +1,113 @@ +#![warn(clippy::unnecessary_as_slice)] +#![allow(clippy::const_is_empty, clippy::ptr_arg)] +#![expect(unused)] + +trait SliceExt { + fn my_len(&self) -> usize; +} + +impl SliceExt for [u32] { + fn my_len(&self) -> usize { + self.len() + } +} + +fn by_ref(vals: &mut Vec) { + let _ = vals.as_slice().len(); + //~^ unnecessary_as_slice + let _ = vals.as_slice().is_empty(); + //~^ unnecessary_as_slice + let _ = vals.as_slice().iter(); + //~^ unnecessary_as_slice + let _ = vals.as_slice().first(); + //~^ unnecessary_as_slice + + let _ = vals.as_mut_slice().len(); + //~^ unnecessary_as_slice + let _ = vals.as_mut_slice().is_empty(); + //~^ unnecessary_as_slice + let _ = vals.as_mut_slice().iter_mut(); + //~^ unnecessary_as_slice +} + +fn by_value(mut vals: Vec) { + let _ = vals.as_slice().len(); + //~^ unnecessary_as_slice + let _ = vals.as_mut_slice().len(); + //~^ unnecessary_as_slice +} + +fn custom_trait_method(mut vals: Vec) { + let _ = vals.as_slice().my_len(); + let _ = vals.as_mut_slice().my_len(); +} + +fn no_lint_cases(vals: &mut Vec) { + // Don't lint as_slice() received by a value + let s = vals.as_slice(); + let _ = s.len(); + + fn takes_slice(_: &[u32]) {} + takes_slice(vals.as_slice()); + + let _ = vals.len(); + let _ = vals.is_empty(); + + fn non_recv(_: &[u32]) {} + // Don't lint as_slice() when it's not the receiver of the method call + non_recv(vals.as_slice()); + + // Don't lint if as_slice() is in a macro. + macro_rules! as_slice_in_macro { + ($vals:expr) => { + let _ = $vals.as_slice().len(); + let _ = $vals.as_mut_slice().len(); + }; + } + + as_slice_in_macro!(vals); + + trait NoLintTrait { + fn foo(&self) -> usize; + fn bar(&mut self) -> usize; + } + + impl NoLintTrait for Vec { + fn foo(&self) -> usize { + 1 + } + fn bar(&mut self) -> usize { + 2 + } + } + + impl NoLintTrait for [u32] { + fn foo(&self) -> usize { + 3 + } + fn bar(&mut self) -> usize { + 4 + } + } + + // Don't lint trait method calls. + let _ = vals.as_slice().foo(); + let _ = vals.as_mut_slice().bar(); +} + +fn no_lint_non_vec(vals: &[u32]) { + // vec_as_slice diagnostic item should only applies to Vec::as_slice + let _ = vals.len(); + let _ = vals.is_empty(); +} + +// Don't lint if the parent method is `as_ptr` or `as_mut_ptr` +fn no_lint_as_ptr(vals: &mut Vec) { + let _ = vals.as_ptr(); + let _ = vals.as_mut_ptr(); + + let _ = vals.as_slice().as_ptr(); + let _ = vals.as_mut_slice().as_mut_ptr(); +} + +fn main() {} diff --git a/tests/ui/unnecessary_as_slice.stderr b/tests/ui/unnecessary_as_slice.stderr new file mode 100644 index 0000000000000..80a4a201bf2dc --- /dev/null +++ b/tests/ui/unnecessary_as_slice.stderr @@ -0,0 +1,59 @@ +error: this `as_slice` is unnecessary because the following method (`len`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:16:17 + | +LL | let _ = vals.as_slice().len(); + | ^^^^^^^^^^^ help: remove `as_slice` + | + = note: `-D clippy::unnecessary-as-slice` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::unnecessary_as_slice)]` + +error: this `as_slice` is unnecessary because the following method (`is_empty`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:18:17 + | +LL | let _ = vals.as_slice().is_empty(); + | ^^^^^^^^^^^ help: remove `as_slice` + +error: this `as_slice` is unnecessary because the following method (`iter`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:20:17 + | +LL | let _ = vals.as_slice().iter(); + | ^^^^^^^^^^^ help: remove `as_slice` + +error: this `as_slice` is unnecessary because the following method (`first`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:22:17 + | +LL | let _ = vals.as_slice().first(); + | ^^^^^^^^^^^ help: remove `as_slice` + +error: this `as_mut_slice` is unnecessary because the following method (`len`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:25:17 + | +LL | let _ = vals.as_mut_slice().len(); + | ^^^^^^^^^^^^^^^ help: remove `as_mut_slice` + +error: this `as_mut_slice` is unnecessary because the following method (`is_empty`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:27:17 + | +LL | let _ = vals.as_mut_slice().is_empty(); + | ^^^^^^^^^^^^^^^ help: remove `as_mut_slice` + +error: this `as_mut_slice` is unnecessary because the following method (`iter_mut`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:29:17 + | +LL | let _ = vals.as_mut_slice().iter_mut(); + | ^^^^^^^^^^^^^^^ help: remove `as_mut_slice` + +error: this `as_slice` is unnecessary because the following method (`len`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:34:17 + | +LL | let _ = vals.as_slice().len(); + | ^^^^^^^^^^^ help: remove `as_slice` + +error: this `as_mut_slice` is unnecessary because the following method (`len`) can be called on `Vec` directly + --> tests/ui/unnecessary_as_slice.rs:36:17 + | +LL | let _ = vals.as_mut_slice().len(); + | ^^^^^^^^^^^^^^^ help: remove `as_mut_slice` + +error: aborting due to 9 previous errors + From 237cfc33046f007dce2985a1acdc3e56d0a74a98 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 22 Jul 2026 15:44:34 +0200 Subject: [PATCH 1073/1309] remove unnecessary panic --- compiler/rustc_middle/src/queries.rs | 4 +-- compiler/rustc_middle/src/query/keys.rs | 6 ++++ .../rustc_middle/src/ty/inhabitedness/mod.rs | 34 ++++++++----------- 3 files changed, 22 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/queries.rs b/compiler/rustc_middle/src/queries.rs index ddaf12f9812aa..d9d618519446d 100644 --- a/compiler/rustc_middle/src/queries.rs +++ b/compiler/rustc_middle/src/queries.rs @@ -2227,8 +2227,8 @@ rustc_queries! { } /// Do not call this query directly: invoke `Ty::is_opsem_inhabited` instead. - query is_opsem_inhabited_raw(env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>) -> bool { - desc { "computing whether `{}` is inhabited on the opsem level", env.value } + query is_opsem_inhabited_adt_cached(env: ty::PseudoCanonicalInput<'tcx, (ty::AdtDef<'tcx>, ty::GenericArgsRef<'tcx>)>) -> bool { + desc { "computing whether `{:?}` is inhabited on the opsem level", env.value } } query crate_dep_kind(_: CrateNum) -> CrateDepKind { diff --git a/compiler/rustc_middle/src/query/keys.rs b/compiler/rustc_middle/src/query/keys.rs index eae4148a30ed4..2bfe80f444090 100644 --- a/compiler/rustc_middle/src/query/keys.rs +++ b/compiler/rustc_middle/src/query/keys.rs @@ -308,6 +308,12 @@ impl<'tcx, T: QueryKey> QueryKey for ty::PseudoCanonicalInput<'tcx, T> { } } +impl<'tcx> QueryKey for (ty::AdtDef<'tcx>, ty::GenericArgsRef<'tcx>) { + fn default_span(&self, tcx: TyCtxt<'_>) -> Span { + tcx.def_span(self.0.did()) + } +} + impl QueryKey for Symbol { fn default_span(&self, _tcx: TyCtxt<'_>) -> Span { DUMMY_SP diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 078a171491520..820b29d078a3e 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -43,8 +43,6 @@ //! This code should only compile in modules where the uninhabitedness of `Foo` //! is visible. -use std::assert_matches; - use rustc_data_structures::fx::FxHashSet; use rustc_hir::def::DefKind; use rustc_span::bug; @@ -66,7 +64,7 @@ pub(crate) fn provide(providers: &mut Providers) { *providers = Providers { inhabited_predicate_for_def, inhabited_predicate_type, - is_opsem_inhabited_raw, + is_opsem_inhabited_adt_cached, ..*providers }; } @@ -273,7 +271,7 @@ struct OpsemInhabitedCtx<'tcx> { tcx: TyCtxt<'tcx>, typing_env: TypingEnv<'tcx>, /// IDs of ADTs that have been encountered in the current stack. - /// It's `None` unless we are inside the `is_opsem_inhabited_raw` query, + /// It's `None` unless we are inside the `is_opsem_inhabited_adt_cached` query, /// which is only invoked for more complex types. seen: Option>, /// If an ADT is encountered recursively within itself, then `stop_at_ref` @@ -332,7 +330,7 @@ impl<'tcx> OpsemInhabitedCtx<'tcx> { let base = tcx.instantiate_bound_regions_with_erased((*base).into()); self.is_inhabited_ty(base) } - ty::Adt(..) => self.is_inhabited_adt_ty(ty), + ty::Adt(def, args) => self.is_inhabited_adt_ty(def, args), ty::Error(_error_guaranteed) => { // We have a token proving there was an error, so we can return a dummy value. @@ -350,10 +348,11 @@ impl<'tcx> OpsemInhabitedCtx<'tcx> { } } - fn is_inhabited_adt_ty(&mut self, ty: Ty<'tcx>) -> bool { - let ty::Adt(adt_def, adt_args) = *ty.kind() else { - unreachable! {} - }; + fn is_inhabited_adt_ty( + &mut self, + adt_def: ty::AdtDef<'tcx>, + adt_args: ty::GenericArgsRef<'tcx>, + ) -> bool { let Self { tcx, typing_env, .. } = *self; if adt_def.is_union() { @@ -363,7 +362,8 @@ impl<'tcx> OpsemInhabitedCtx<'tcx> { let Some(seen) = self.seen.as_mut() else { // stop recursing, invoke the query. - return tcx.is_opsem_inhabited_raw(typing_env.as_query_input(ty)); + return tcx + .is_opsem_inhabited_adt_cached(typing_env.as_query_input((adt_def, adt_args))); }; let new_adt = seen.insert(adt_def.did()); @@ -393,17 +393,11 @@ impl<'tcx> OpsemInhabitedCtx<'tcx> { } } -fn is_opsem_inhabited_raw<'tcx>( +fn is_opsem_inhabited_adt_cached<'tcx>( tcx: TyCtxt<'tcx>, - env: ty::PseudoCanonicalInput<'tcx, Ty<'tcx>>, + env: ty::PseudoCanonicalInput<'tcx, (ty::AdtDef<'tcx>, ty::GenericArgsRef<'tcx>)>, ) -> bool { - let (ty, typing_env) = (env.value, env.typing_env); - assert_matches!( - ty.kind(), - ty::Adt(..), - "the query should only be invoked by `Ty::is_opsem_inhabited`" - ); - + let ((def, args), typing_env) = (env.value, env.typing_env); OpsemInhabitedCtx { tcx, typing_env, seen: Some(FxHashSet::default()), stop_at_ref: false } - .is_inhabited_adt_ty(ty) + .is_inhabited_adt_ty(def, args) } From 57be633d8ec117a312aed9183353a64cee7e522c Mon Sep 17 00:00:00 2001 From: Emmanuel Ugwu Date: Wed, 30 Sep 2026 12:37:56 +0100 Subject: [PATCH 1074/1309] address feedback Signed-off-by: Emmanuel Ugwu --- library/core/src/attribute_docs.rs | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index a96c7a1388bd1..9a70ea74345be 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -189,7 +189,7 @@ const _: () = (); /// /// For more information, see the Reference on [the `cfg` attribute]. /// -/// [`cfg_attr`]: ../reference/conditional-compilation.html#the-cfg_attr-attribute +/// [`cfg_attr`]: ./attribute.cfg_attr.html /// [the `cfg` attribute]: ../reference/conditional-compilation.html#the-cfg-attribute /// [`if`]: ./keyword.if.html const _: () = (); @@ -715,11 +715,9 @@ const _: () = (); /// Example: /// /// ```rust -/// // This function is annotated with `#[test]` only on Linux platforms. -/// #[cfg_attr(target_os = "linux", test)] -/// fn my_function() { -/// // ... -/// } +/// // The struct derives `Debug` when the `debug_impls` feature is enabled. +/// #[cfg_attr(feature = "debug_impls", derive(Debug))] +/// struct X; /// ``` /// /// You can apply multiple attributes by separating them with commas: @@ -742,7 +740,7 @@ const _: () = (); /// ```rust /// #[cfg_attr( /// all(feature = "system", feature = "disk"), -/// doc = "For module documentation, both `system`, and `disk` need to be enabled.", +/// doc = "These docs only show up if both `system`, and `disk` are enabled.", /// )] /// mod my_module { /// // ... From 937145bcebff9cafefdbad652b7463a8ed04fe1f Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Wed, 30 Sep 2026 09:18:45 -0400 Subject: [PATCH 1075/1309] PassWrapper: adapt for new PassPlugin load method Used to take a string&, now takes a StringRef and is lower-case. --- compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index beb63ad61493c..79b590ab854f2 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -775,7 +775,11 @@ extern "C" LLVMRustResult LLVMRustOptimize( SmallVector Plugins; PluginsStr.split(Plugins, ',', -1, false); for (auto PluginPath : Plugins) { +#if LLVM_VERSION_GE(24, 0) + auto Plugin = PassPlugin::load(PluginPath); +#else auto Plugin = PassPlugin::Load(PluginPath.str()); +#endif if (!Plugin) { auto Err = Plugin.takeError(); auto ErrMsg = llvm::toString(std::move(Err)); From 1161c07cf9e0d542c00426ec18eb706a73e317fb Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Wed, 30 Sep 2026 13:39:14 +0000 Subject: [PATCH 1076/1309] Some refactorings around metadata encoding --- compiler/rustc_metadata/src/rmeta/decoder.rs | 6 +- compiler/rustc_metadata/src/rmeta/encoder.rs | 254 ++++++++++--------- compiler/rustc_metadata/src/rmeta/mod.rs | 2 +- 3 files changed, 139 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 7dd920c7e39bd..5348ee0ccaac1 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -1544,10 +1544,12 @@ impl CrateMetadata { fn get_proc_macro_quoted_span(&self, tcx: TyCtxt<'_>, index: usize) -> Span { self.root - .tables + .proc_macro_data + .as_ref() + .expect("missing proc macro data") .proc_macro_quoted_spans .get(self, index) - .unwrap_or_else(|| panic!("Missing proc macro quoted span: {index:?}")) + .unwrap_or_else(|| panic!("missing proc macro quoted span: {index:?}")) .decode((self, tcx)) } diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index 40b61a52d2310..03493d0e1b6a9 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -404,35 +404,42 @@ impl<'a, 'tcx> TyEncoder<'tcx> for EncodeContext<'a, 'tcx> { // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. -macro_rules! record { +// Also those macros greatly simplify refactorings and modifications of writing to tables. +macro_rules! record_some_lazy { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ - { - let value = $value; - let lazy = $self.lazy(value); - $self.$tables.$table.set_some($def_id.index, lazy); - } + let value = $value; + let lazy = $self.lazy(value); + $self.$tables.$table.set_some($def_id.index, lazy); }}; } +macro_rules! record_some { + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { + $self.$tables.$table.set_some($def_id.index, $value) + }; +} + +macro_rules! record_value { + ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => { + $self.$tables.$table.set($def_id.index, $value) + }; +} + // Shorthand for `$self.$tables.$table.set_some($def_id.index, $self.lazy_array($value))`, which would // normally need extra variables to avoid errors about multiple mutable borrows. macro_rules! record_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ - { - let value = $value; - let lazy = $self.lazy_array(value); - $self.$tables.$table.set_some($def_id.index, lazy); - } + let value = $value; + let lazy = $self.lazy_array(value); + $self.$tables.$table.set_some($def_id.index, lazy); }}; } macro_rules! record_defaulted_array { ($self:ident.$tables:ident.$table:ident[$def_id:expr] <- $value:expr) => {{ - { - let value = $value; - let lazy = $self.lazy_array(value); - $self.$tables.$table.set($def_id.index, lazy); - } + let value = $value; + let lazy = $self.lazy_array(value); + $self.$tables.$table.set($def_id.index, lazy); }}; } @@ -527,18 +534,18 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for def_id in std::iter::once(CRATE_DEF_ID) .chain(self.tcx.resolutions(()).proc_macros.iter().copied()) { - let def_key = self.lazy(defs.def_key(def_id)); + let def_key = defs.def_key(def_id); let def_path_hash = defs.def_path_hash(def_id); - self.tables.def_keys.set_some(def_id.local_def_index, def_key); - self.tables - .def_path_hashes - .set(def_id.local_def_index, def_path_hash.local_hash().as_u64()); + let def_id = def_id.to_def_id(); + + record_some_lazy!(self.tables.def_keys[def_id] <- def_key); + record_value!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) } } else { for (def_index, def_key, def_path_hash) in defs.enumerated_keys_and_path_hashes() { - let def_key = self.lazy(def_key); - self.tables.def_keys.set_some(def_index, def_key); - self.tables.def_path_hashes.set(def_index, def_path_hash.local_hash().as_u64()); + let def_id = LocalDefId { local_def_index: def_index }.to_def_id(); + record_some_lazy!(self.tables.def_keys[def_id] <- def_key); + record_value!(self.tables.def_path_hashes[def_id] <- def_path_hash.local_hash().as_u64()) } } } @@ -1444,7 +1451,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if state.is_doc_hidden { attr_flags |= AttrFlags::IS_DOC_HIDDEN; } - self.tables.attr_flags.set(def_id.local_def_index, attr_flags); + + record_value!(self.tables.attr_flags[def_id.to_def_id()] <- attr_flags) } fn encode_def_ids(&mut self) { @@ -1461,7 +1469,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { for local_id in tcx.iter_local_def_id() { let def_id = local_id.to_def_id(); let def_kind = tcx.def_kind(local_id); - self.tables.def_kind.set_some(def_id.index, def_kind); + record_some!(self.tables.def_kind[def_id] <- def_kind); // The `DefCollector` will sometimes create unnecessary `DefId`s // for trivial const arguments which are directly lowered to @@ -1482,33 +1490,33 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { && let hir::Node::Field(field) = tcx.hir_node_by_def_id(local_id) && let Some(anon) = field.default { - record!(self.tables.default_fields[def_id] <- anon.def_id.to_def_id()); + record_some_lazy!(self.tables.default_fields[def_id] <- anon.def_id.to_def_id()); } if should_encode_span(def_kind) { let def_span = tcx.def_span(local_id); - record!(self.tables.def_span[def_id] <- def_span); + record_some_lazy!(self.tables.def_span[def_id] <- def_span); } if should_encode_attrs(def_kind) { self.encode_attrs(local_id); } if should_encode_expn_that_defined(def_kind) { - record!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); + record_some_lazy!(self.tables.expn_that_defined[def_id] <- self.tcx.expn_that_defined(def_id)); } if should_encode_span(def_kind) && let Some(ident_span) = tcx.def_ident_span(def_id) { - record!(self.tables.def_ident_span[def_id] <- ident_span); + record_some_lazy!(self.tables.def_ident_span[def_id] <- ident_span); } if def_kind.has_codegen_attrs() { - record!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); + record_some_lazy!(self.tables.codegen_fn_attrs[def_id] <- self.tcx.codegen_fn_attrs(def_id)); } if should_encode_visibility(def_kind) { let vis = self .tcx .local_visibility(local_id) .map_id(|mod_id| mod_id.to_local_def_id().local_def_index); - record!(self.tables.visibility[def_id] <- vis); + record_some_lazy!(self.tables.visibility[def_id] <- vis); } if should_encode_stability(def_kind) { self.encode_stability(def_id); @@ -1521,46 +1529,46 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { record_array!(self.tables.variances_of[def_id] <- v); } if should_encode_fn_sig(def_kind) { - record!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); + record_some_lazy!(self.tables.fn_sig[def_id] <- tcx.fn_sig(def_id)); } if should_encode_generics(def_kind) { let g = tcx.generics_of(def_id); - record!(self.tables.generics_of[def_id] <- g); - record!(self.tables.explicit_clauses_of[def_id] <- self.tcx.explicit_clauses_of(def_id)); + record_some_lazy!(self.tables.generics_of[def_id] <- g); + record_some_lazy!(self.tables.explicit_clauses_of[def_id] <- self.tcx.explicit_clauses_of(def_id)); let inferred_outlives = self.tcx.inferred_outlives_of(def_id); record_defaulted_array!(self.tables.inferred_outlives_of[def_id] <- inferred_outlives); for param in &g.own_params { if let ty::GenericParamDefKind::Const { has_default: true, .. } = param.kind { let default = self.tcx.const_param_default(param.def_id); - record!(self.tables.const_param_default[param.def_id] <- default); + record_some_lazy!(self.tables.const_param_default[param.def_id] <- default); } } } if tcx.is_conditionally_const(def_id) { - record!(self.tables.const_conditions[def_id] <- self.tcx.const_conditions(def_id)); + record_some_lazy!(self.tables.const_conditions[def_id] <- self.tcx.const_conditions(def_id)); } if should_encode_type(tcx, local_id, def_kind) { - record!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); + record_some_lazy!(self.tables.type_of[def_id] <- self.tcx.type_of(def_id)); } if should_encode_constness(def_kind) { let constness = self.tcx.constness(def_id); - self.tables.constness.set(def_id.index, constness); + record_value!(self.tables.constness[def_id] <- constness) } if let DefKind::Fn | DefKind::AssocFn = def_kind { let asyncness = tcx.asyncness(def_id); - self.tables.asyncness.set(def_id.index, asyncness); + record_value!(self.tables.asyncness[def_id] <- asyncness); record_array!(self.tables.fn_arg_idents[def_id] <- tcx.fn_arg_idents(def_id)); } if let Some(name) = tcx.intrinsic(def_id) { - record!(self.tables.intrinsic[def_id] <- name); + record_some_lazy!(self.tables.intrinsic[def_id] <- name); } if let DefKind::TyParam | DefKind::Trait = def_kind { let default = self.tcx.object_lifetime_default(def_id); - record!(self.tables.object_lifetime_default[def_id] <- default); + record_some_lazy!(self.tables.object_lifetime_default[def_id] <- default); } if let DefKind::Trait = def_kind { - record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); + record_some_lazy!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); record_defaulted_array!(self.tables.explicit_super_clauses_of[def_id] <- self.tcx.explicit_super_clauses_of(def_id).skip_binder()); record_defaulted_array!(self.tables.explicit_implied_clauses_of[def_id] <- @@ -1574,7 +1582,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if let DefKind::TraitAlias = def_kind { - record!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); + record_some_lazy!(self.tables.trait_def[def_id] <- self.tcx.trait_def(def_id)); record_defaulted_array!(self.tables.explicit_super_clauses_of[def_id] <- self.tcx.explicit_super_clauses_of(def_id).skip_binder()); record_defaulted_array!(self.tables.explicit_implied_clauses_of[def_id] <- @@ -1595,28 +1603,28 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let DefKind::Closure | DefKind::SyntheticCoroutineBody = def_kind && let Some(coroutine_kind) = self.tcx.coroutine_kind(def_id) { - self.tables.coroutine_kind.set(def_id.index, Some(coroutine_kind)) + record_value!(self.tables.coroutine_kind[def_id] <- Some(coroutine_kind)) } if def_kind == DefKind::Closure && tcx.type_of(def_id).skip_binder().is_coroutine_closure() { let coroutine_for_closure = self.tcx.coroutine_for_closure(def_id); - self.tables - .coroutine_for_closure - .set_some(def_id.index, coroutine_for_closure.into()); + record_some!(self.tables.coroutine_for_closure[def_id] <- coroutine_for_closure.into()); // If this async closure has a by-move body, record it too. if tcx.needs_coroutine_by_move_body_def_id(coroutine_for_closure) { - self.tables.coroutine_by_move_body_def_id.set_some( - coroutine_for_closure.index, - self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure).into(), - ); + let id = self.tcx.coroutine_by_move_body_def_id(coroutine_for_closure); + record_some!( + self.tables.coroutine_by_move_body_def_id[coroutine_for_closure] <- id.into() + ) } } if let DefKind::Static { .. } = def_kind { if !self.tcx.is_foreign_item(def_id) { match self.tcx.eval_static_initializer(def_id) { - Ok(data) => record!(self.tables.eval_static_initializer[def_id] <- data), + Ok(data) => { + record_some_lazy!(self.tables.eval_static_initializer[def_id] <- data) + } Err(err) => match err { interpret::ErrorHandled::Reported(_, _) => { self.tcx.dcx().delayed_bug(format!( @@ -1640,50 +1648,49 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.encode_info_for_macro(local_id); } if let DefKind::TyAlias = def_kind { - self.tables - .type_alias_is_checked - .set(def_id.index, self.tcx.type_alias_is_checked(def_id)); + record_value!(self.tables.type_alias_is_checked[def_id] <- self.tcx.type_alias_is_checked(def_id)); + if self.tcx.type_alias_is_checked(def_id) { - record!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); + record_some_lazy!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); } } if let DefKind::OpaqueTy = def_kind { self.encode_explicit_item_bounds(def_id); self.encode_explicit_item_self_bounds(def_id); - record!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id)); + record_some_lazy!(self.tables.opaque_ty_origin[def_id] <- self.tcx.opaque_ty_origin(def_id)); self.encode_precise_capturing_args(def_id); if tcx.is_conditionally_const(def_id) { record_defaulted_array!(self.tables.explicit_implied_const_bounds[def_id] <- tcx.explicit_implied_const_bounds(def_id).skip_binder()); } - record!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); + record_some_lazy!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); } if let DefKind::AssocTy = def_kind { let assoc_item = tcx.associated_item(def_id); match assoc_item.container { ty::AssocContainer::Trait => { - record!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); + record_some_lazy!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); } ty::AssocContainer::InherentImpl => { - record!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); + record_some_lazy!(self.tables.args_known_to_outlive_alias_params[def_id] <- tcx.args_known_to_outlive_alias_params(def_id)); } ty::AssocContainer::TraitImpl(_) => {} } } if let DefKind::AnonConst = def_kind { - record!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); + record_some_lazy!(self.tables.anon_const_kind[def_id] <- self.tcx.anon_const_kind(def_id)); } if let DefKind::Const | DefKind::AssocConst = def_kind { - record!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id)); + record_some_lazy!(self.tables.const_of_item[def_id] <- self.tcx.const_of_item(def_id)); } if tcx.impl_method_has_trait_impl_trait_tys(def_id) && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id) { - record!(self.tables.collect_return_position_impl_trait_in_trait_tys[def_id] <- table); + record_some_lazy!(self.tables.collect_return_position_impl_trait_in_trait_tys[def_id] <- table); } if let DefKind::Impl { .. } | DefKind::Trait = def_kind { let table = tcx.associated_types_for_impl_traits_in_trait_or_impl(def_id); - record!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table); + record_some_lazy!(self.tables.associated_types_for_impl_traits_in_trait_or_impl[def_id] <- table); } } @@ -1695,7 +1702,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } for (def_id, res_map) in &tcx.resolutions(()).doc_link_resolutions { - record!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map); + record_some_lazy!(self.tables.doc_link_resolutions[def_id.to_def_id()] <- res_map); } for (def_id, traits) in &tcx.resolutions(()).doc_link_traits_in_scope { @@ -1722,10 +1729,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let def_id = local_def_id.to_def_id(); let tcx = self.tcx; let adt_def = tcx.adt_def(def_id); - record!(self.tables.repr_options[def_id] <- adt_def.repr()); + record_some_lazy!(self.tables.repr_options[def_id] <- adt_def.repr()); let params_in_repr = self.tcx.params_in_repr(def_id); - record!(self.tables.params_in_repr[def_id] <- params_in_repr); + record_some_lazy!(self.tables.params_in_repr[def_id] <- params_in_repr); if adt_def.is_enum() { let module_children = tcx.module_children_local(local_def_id); @@ -1745,7 +1752,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { ctor: variant.ctor.map(|(kind, def_id)| (kind, def_id.index)), is_non_exhaustive: variant.is_field_list_non_exhaustive(), }; - record!(self.tables.variant_data[variant.def_id] <- data); + record_some_lazy!(self.tables.variant_data[variant.def_id] <- data); record_array!(self.tables.associated_item_or_field_def_ids[variant.def_id] <- variant.fields.iter().map(|f| { assert!(f.did.is_local()); @@ -1753,8 +1760,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { })); for field in &variant.fields { - self.tables.safety.set(field.did.index, field.safety); - record!( + record_value!(self.tables.safety[field.did] <- field.safety); + record_some_lazy!( self.tables.mut_restriction[field.did] <- field.mut_restriction ); } @@ -1762,16 +1769,16 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Some((CtorKind::Fn, ctor_def_id)) = variant.ctor { let fn_sig = tcx.fn_sig(ctor_def_id); // FIXME only encode signature for ctor_def_id - record!(self.tables.fn_sig[variant.def_id] <- fn_sig); + record_some_lazy!(self.tables.fn_sig[variant.def_id] <- fn_sig); } } if let Some(destructor) = tcx.adt_destructor(local_def_id) { - record!(self.tables.adt_destructor[def_id] <- destructor); + record_some_lazy!(self.tables.adt_destructor[def_id] <- destructor); } if let Some(destructor) = tcx.adt_async_destructor(local_def_id) { - record!(self.tables.adt_async_destructor[def_id] <- destructor); + record_some_lazy!(self.tables.adt_async_destructor[def_id] <- destructor); } } @@ -1787,7 +1794,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // items - we encode information about proc-macros later on. if self.is_proc_macro { // Encode this here because we don't do it in encode_def_ids. - record!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); + record_some_lazy!(self.tables.expn_that_defined[def_id] <- tcx.expn_that_defined(local_def_id)); } else { let module_children = tcx.module_children_local(local_def_id); @@ -1826,10 +1833,10 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let item = tcx.associated_item(def_id); if matches!(item.container, AssocContainer::Trait | AssocContainer::TraitImpl(_)) { - self.tables.defaultness.set(def_id.index, item.defaultness(tcx)); + record_value!(self.tables.defaultness[def_id] <- item.defaultness(tcx)); } - record!(self.tables.assoc_container[def_id] <- item.container); + record_some_lazy!(self.tables.assoc_container[def_id] <- item.container); if let AssocContainer::Trait = item.container && item.is_type() @@ -1842,7 +1849,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } } if let ty::AssocKind::Type { data: ty::AssocTypeData::Rpitit(rpitit_info) } = item.kind { - record!(self.tables.opt_rpitit_info[def_id] <- rpitit_info); + record_some_lazy!(self.tables.opt_rpitit_info[def_id] <- rpitit_info); if matches!(rpitit_info, ty::ImplTraitInTraitData::Trait { .. }) { record_array!( self.tables.assumed_wf_types_for_rpitit[def_id] @@ -1878,53 +1885,53 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { debug!("EntryBuilder::encode_mir({:?})", def_id); if encode_opt { - record!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); - self.tables - .cross_crate_inlinable - .set(def_id.to_def_id().index, self.tcx.cross_crate_inlinable(def_id)); - record!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] + record_some_lazy!(self.tables.optimized_mir[def_id.to_def_id()] <- tcx.optimized_mir(def_id)); + + record_value!(self.tables.cross_crate_inlinable[def_id.to_def_id()] <- self.tcx.cross_crate_inlinable(def_id)); + + record_some_lazy!(self.tables.closure_saved_names_of_captured_variables[def_id.to_def_id()] <- tcx.closure_saved_names_of_captured_variables(def_id)); if self.tcx.is_coroutine(def_id.to_def_id()) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { - record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); + record_some_lazy!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); } } let mut is_trivial = false; if encode_const { if let Some((val, ty)) = tcx.trivial_const(def_id) { is_trivial = true; - record!(self.tables.trivial_const[def_id.to_def_id()] <- (val, ty)); + record_some_lazy!(self.tables.trivial_const[def_id.to_def_id()] <- (val, ty)); } else { is_trivial = false; - record!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id)); + record_some_lazy!(self.tables.mir_for_ctfe[def_id.to_def_id()] <- tcx.mir_for_ctfe(def_id)); } // FIXME(generic_const_exprs): this feels wrong to have in `encode_mir` let abstract_const = tcx.thir_abstract_const(def_id); if let Ok(Some(abstract_const)) = abstract_const { - record!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const); + record_some_lazy!(self.tables.thir_abstract_const[def_id.to_def_id()] <- abstract_const); } if should_encode_const(tcx.def_kind(def_id)) { let qualifs = tcx.mir_const_qualif(def_id); - record!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); + record_some_lazy!(self.tables.mir_const_qualif[def_id.to_def_id()] <- qualifs); let body = tcx.hir_maybe_body_owned_by(def_id); if let Some(body) = body { let const_data = rendered_const(self.tcx, &body, def_id); - record!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); + record_some_lazy!(self.tables.rendered_const[def_id.to_def_id()] <- const_data); } } } if !is_trivial { - record!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); + record_some_lazy!(self.tables.promoted_mir[def_id.to_def_id()] <- tcx.promoted_mir(def_id)); } if self.tcx.is_coroutine(def_id.to_def_id()) && let Some(witnesses) = tcx.mir_coroutine_witnesses(def_id) { - record!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); + record_some_lazy!(self.tables.mir_coroutine_witnesses[def_id.to_def_id()] <- witnesses); } } @@ -1950,7 +1957,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // the stability attributes are even enabled before using their queries. if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { if let Some(stab) = self.tcx.lookup_stability(def_id) { - record!(self.tables.lookup_stability[def_id] <- stab) + record_some_lazy!(self.tables.lookup_stability[def_id] <- stab) } } } @@ -1961,7 +1968,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // the stability attributes are even enabled before using their queries. if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { if let Some(stab) = self.tcx.lookup_const_stability(def_id) { - record!(self.tables.lookup_const_stability[def_id] <- stab) + record_some_lazy!(self.tables.lookup_const_stability[def_id] <- stab) } } } @@ -1972,7 +1979,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { // the stability attributes are even enabled before using their queries. if self.feat.staged_api() || self.tcx.sess.opts.unstable_opts.force_unstable_if_unmarked { if let Some(stab) = self.tcx.lookup_default_body_stability(def_id) { - record!(self.tables.lookup_default_body_stability[def_id] <- stab) + record_some_lazy!(self.tables.lookup_default_body_stability[def_id] <- stab) } } } @@ -1980,7 +1987,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { #[instrument(level = "debug", skip(self))] fn encode_deprecation(&mut self, def_id: DefId) { if let Some(depr) = self.tcx.lookup_deprecation(def_id) { - record!(self.tables.lookup_deprecation_entry[def_id] <- depr); + record_some_lazy!(self.tables.lookup_deprecation_entry[def_id] <- depr); } } @@ -1989,8 +1996,8 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let (_, macro_def, _) = tcx.hir_expect_item(def_id).expect_macro(); - self.tables.is_macro_rules.set(def_id.local_def_index, macro_def.macro_rules); - record!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); + record_value!(self.tables.is_macro_rules[def_id.to_def_id()] <- macro_def.macro_rules); + record_some_lazy!(self.tables.macro_definition[def_id.to_def_id()] <- &*macro_def.body); } fn encode_native_libraries(&mut self) -> LazyArray { @@ -2039,24 +2046,20 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { let tcx = self.tcx; let proc_macro_decls_static = tcx.proc_macro_decls_static(()).unwrap().local_def_index; let stability = tcx.lookup_stability(CRATE_DEF_ID); - for (i, span) in self.tcx.sess.proc_macro_quoted_spans() { - let span = self.lazy(span); - self.tables.proc_macro_quoted_spans.set_some(i, span); - } - self.tables.def_kind.set_some(LOCAL_CRATE.as_def_id().index, DefKind::Mod); - record!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); + record_some!(self.tables.def_kind[LOCAL_CRATE.as_def_id()] <- DefKind::Mod); + record_some_lazy!(self.tables.def_span[LOCAL_CRATE.as_def_id()] <- tcx.def_span(LOCAL_CRATE.as_def_id())); self.encode_attrs(LOCAL_CRATE.as_def_id().expect_local()); let vis = tcx .local_visibility(CRATE_DEF_ID) .map_id(|mod_id| mod_id.to_local_def_id().local_def_index); - record!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- vis); + record_some_lazy!(self.tables.visibility[LOCAL_CRATE.as_def_id()] <- vis); if let Some(stability) = stability { - record!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability); + record_some_lazy!(self.tables.lookup_stability[LOCAL_CRATE.as_def_id()] <- stability); } self.encode_deprecation(LOCAL_CRATE.as_def_id()); if let Some(res_map) = tcx.resolutions(()).doc_link_resolutions.get(&CRATE_MOD_ID) { - record!(self.tables.doc_link_resolutions[LOCAL_CRATE.as_def_id()] <- res_map); + record_some_lazy!(self.tables.doc_link_resolutions[LOCAL_CRATE.as_def_id()] <- res_map); } if let Some(traits) = tcx.resolutions(()).doc_link_traits_in_scope.get(&CRATE_MOD_ID) { record_array!(self.tables.doc_link_traits_in_scope[LOCAL_CRATE.as_def_id()] <- traits); @@ -2103,20 +2106,33 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { def_key.disambiguated_data.data = DefPathData::MacroNs(name); let def_id = id.to_def_id(); - self.tables.def_kind.set_some(def_id.index, DefKind::Macro(macro_kind.into())); + record_some!(self.tables.def_kind[def_id] <- DefKind::Macro(macro_kind.into())); + self.encode_attrs(id); - record!(self.tables.def_keys[def_id] <- def_key); - record!(self.tables.def_ident_span[def_id] <- span); - record!(self.tables.def_span[def_id] <- span); - record!(self.tables.visibility[def_id] <- ty::Visibility::Public); + record_some_lazy!(self.tables.def_keys[def_id] <- def_key); + record_some_lazy!(self.tables.def_ident_span[def_id] <- span); + record_some_lazy!(self.tables.def_span[def_id] <- span); + record_some_lazy!(self.tables.visibility[def_id] <- ty::Visibility::Public); if let Some(stability) = stability { - record!(self.tables.lookup_stability[def_id] <- stability); + record_some_lazy!(self.tables.lookup_stability[def_id] <- stability); } } let macros = self.lazy_array(macros); - Some(ProcMacroData { proc_macro_decls_static, stability, macros }) + let mut proc_macro_quoted_spans = TableBuilder::default(); + for (i, span) in self.tcx.sess.proc_macro_quoted_spans() { + proc_macro_quoted_spans.set_some(i, self.lazy(span)); + } + + let proc_macro_quoted_spans = proc_macro_quoted_spans.encode(&mut self.opaque); + + Some(ProcMacroData { + proc_macro_decls_static, + stability, + macros, + proc_macro_quoted_spans, + }) } else { None } @@ -2263,15 +2279,13 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if of_trait { let header = tcx.impl_trait_header(def_id); - record!(self.tables.impl_trait_header[def_id] <- header); + record_some_lazy!(self.tables.impl_trait_header[def_id] <- header); let impl_is_fully_generic_for_reflection = tcx.impl_is_fully_generic_for_reflection(def_id); - self.tables - .impl_is_fully_generic_for_reflection - .set(def_id.index, impl_is_fully_generic_for_reflection); - self.tables.defaultness.set(def_id.index, tcx.defaultness(def_id)); + record_value!(self.tables.impl_is_fully_generic_for_reflection[def_id] <- impl_is_fully_generic_for_reflection); + record_value!(self.tables.defaultness[def_id] <- tcx.defaultness(def_id)); let trait_ref = header.trait_ref.instantiate_identity().skip_norm_wip(); let simplified_self_ty = fast_reject::simplify_type( @@ -2288,14 +2302,14 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { if let Ok(mut an) = trait_def.ancestors(tcx, def_id) && let Some(specialization_graph::Node::Impl(parent)) = an.nth(1) { - self.tables.impl_parent.set_some(def_id.index, parent.into()); + record_some!(self.tables.impl_parent[def_id] <- parent.into()); } // if this is an impl of `CoerceUnsized`, create its // "unsized info", else just store None if tcx.is_lang_item(trait_ref.def_id, LangItem::CoerceUnsized) { let coerce_unsized_info = tcx.coerce_unsized_info(def_id).unwrap(); - record!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info); + record_some_lazy!(self.tables.coerce_unsized_info[def_id] <- coerce_unsized_info); } } } diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index b70151604f679..f7a437043dade 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -214,6 +214,7 @@ pub(crate) struct ProcMacroData { proc_macro_decls_static: DefIndex, stability: Option, macros: LazyArray<(DefIndex, LazyValue)>, + proc_macro_quoted_spans: LazyTableSingleIdx>>, } #[derive(MetadataEncodable, LazyDecodable)] @@ -503,7 +504,6 @@ define_tables! { // `DefPathTable` up front, since we may only ever use a few // definitions from any given crate. def_keys: Table>, - proc_macro_quoted_spans: Table>, variant_data: Table>, assoc_container: Table>, macro_definition: Table>, From 06660e62a77abc3fe7c1b8bdfd6447513da0ece9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 15:26:43 +0200 Subject: [PATCH 1077/1309] simplify and clarify fs::set_permissions_nofollow tests --- library/std/src/fs.rs | 2 +- library/std/src/fs/tests.rs | 39 ++++++++++++++++--------------------- 2 files changed, 18 insertions(+), 23 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index 65b8ed634bc05..afc421ab82e86 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -3645,7 +3645,7 @@ pub fn set_permissions>(path: P, perm: Permissions) -> io::Result /// This function currently corresponds to the following underlying operations: /// * Android: returns [`Unsupported`] on all files. /// * Linux, BSD-based platforms, QNX, NTO: `fchmodat` with `AT_SYMLINK_NOFOLLOW`. -/// If that is not supported, we fall back to: +/// If that is not supported, we fall back to: /// * Unix-based platforms with symlinks: `open` with `O_NOFOLLOW` followed by /// [`fs::set_permissions`]. /// * Unix-based platforms without symlinks: `open` followed by [`fs::set_permissions`]. diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index db9a9f3f20b88..6ed1bdd29ebd2 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -613,12 +613,14 @@ fn set_get_unix_permissions() { assert_eq!(mask & metadata1.permissions().mode(), 0o0777); } +/// Test set_permissions_nofollow on a regular file. #[cfg(not(target_os = "android"))] #[test] fn set_get_permissions_nofollows() { let tmpdir = tmpdir(); let filename = tmpdir.join("set_get_unix_permissions_file"); check!(File::create(&filename)); + let file_metadata = check!(fs::metadata(&filename)); assert!(!file_metadata.permissions().readonly()); let mut permission_bits = file_metadata.permissions(); @@ -648,12 +650,8 @@ fn set_get_permissions_nofollows() { } } -// Only Windows and Unix support `fs::set_permissions_nofollow` +#[cfg(not(target_os = "android"))] #[test] -#[cfg(all( - any(windows, unix), - not(any(target_os = "espidf", target_os = "horizon", target_os = "wasi")) -))] fn set_get_permissions_nofollows_symlink() { #[cfg(not(windows))] use crate::os::unix::fs::symlink as symlink_file; @@ -667,14 +665,20 @@ fn set_get_permissions_nofollows_symlink() { check!(symlink_file(&filename, &symlink_name)); let init_symlink_metadata = check!(fs::symlink_metadata(&symlink_name)); - let mut init_symlink_permissions = init_symlink_metadata.permissions(); - + assert!(!init_symlink_metadata.permissions().readonly()); let init_target_metadata = check!(fs::metadata(&symlink_name)); - let init_target_permissions = init_target_metadata.permissions(); + assert!(!init_target_metadata.permissions().readonly()); // Set symlink permissions to readonly - init_symlink_permissions.set_readonly(true); - let result = fs::set_permissions_nofollow(&symlink_name, init_symlink_permissions); + let result = fs::set_permissions_nofollow(&symlink_name, { + let mut permissions = init_symlink_metadata.permissions(); + permissions.set_readonly(true); + permissions + }); + + // This should not change the permissions of the target! + let after_target_metadata = check!(fs::metadata(&symlink_name)); + assert_eq!(after_target_metadata.permissions(), init_target_metadata.permissions()); cfg_select! { any( @@ -687,16 +691,11 @@ fn set_get_permissions_nofollows_symlink() { target_os = "nto", target_os = "qnx" ) => { + // On these systems, it's confirmed the symlink itself is marked readonly + // https://superuser.com/questions/1099634/change-permissions-symbolic-link-mac-os assert_eq!(result.unwrap(), ()); - let after_target_metadata = check!(fs::metadata(&symlink_name)); - // We should expect the target file to not have its permission bits - // changed - assert_eq!(after_target_metadata.permissions(), init_target_permissions); - let after_symlink_metadata = check!(fs::symlink_metadata(&symlink_name)); - // On these systems, it's confirmed the symlink itself is marked readonly - // https://superuser.com/questions/1099634/change-permissions-symbolic-link-mac-os assert!(after_symlink_metadata.permissions().readonly()); // Reset the read-only bit under Windows 7: avoids the @@ -710,11 +709,7 @@ fn set_get_permissions_nofollows_symlink() { } } _ => { - let after_target_metadata = check!(fs::metadata(&symlink_name)); - // We should expect the target file to not have its permission bits - // changed - assert_eq!(after_target_metadata.permissions(), init_target_permissions); - + // Everywhere else, this just fails. let error_kind = result.unwrap_err().kind(); assert_eq!(error_kind, crate::io::ErrorKind::Unsupported); } From 7c35df5fd9c557cd4036a8d174027eb808547a21 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 27 Sep 2026 16:05:10 +0200 Subject: [PATCH 1078/1309] Remove #[linkage = "internal"] Rustc already defaults to this for regular items whenever possible. Overriding it would only lead to linker errors. And for depending on the exact codegen unit partitioning rustc uses, so there it is a bad idea to use it too. --- .../rustc_attr_parsing/src/attributes/link_attrs.rs | 3 --- compiler/rustc_codegen_gcc/tests/c/import_linkage.c | 1 - compiler/rustc_codegen_gcc/tests/c/static_linkage.c | 8 +------- .../rustc_codegen_gcc/tests/run/import_linkage.rs | 8 -------- .../rustc_codegen_gcc/tests/run/static_linkage.rs | 11 +---------- compiler/rustc_span/src/symbol.rs | 1 - .../linkage-attr-does-not-panic-llvm-issue-33992.rs | 3 --- tests/ui/linkage-attr/linkage3.stderr | 2 +- tests/ui/lint/inline-exported.rs | 4 ---- 9 files changed, 3 insertions(+), 38 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index f4d0fa35e3f47..bb5160db76ee8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -688,7 +688,6 @@ impl SingleAttributeParser for LinkageParser { "common", "extern_weak", "external", - "internal", "linkonce", "linkonce_odr", "weak", @@ -714,7 +713,6 @@ impl SingleAttributeParser for LinkageParser { sym::common => Linkage::Common, sym::extern_weak => Linkage::ExternalWeak, sym::external => Linkage::External, - sym::internal => Linkage::Internal, sym::linkonce => Linkage::LinkOnceAny, sym::linkonce_odr => Linkage::LinkOnceODR, sym::weak => Linkage::WeakAny, @@ -728,7 +726,6 @@ impl SingleAttributeParser for LinkageParser { sym::common, sym::extern_weak, sym::external, - sym::internal, sym::linkonce, sym::linkonce_odr, sym::weak, diff --git a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c index f2beb9603d08b..d725b86c6c14b 100644 --- a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c +++ b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c @@ -14,4 +14,3 @@ int32_t weak_value = 5; int32_t weak_odr_value = 6; int32_t common_value = 7; int32_t extern_weak_value = 8; -int32_t internal_value = 9; diff --git a/compiler/rustc_codegen_gcc/tests/c/static_linkage.c b/compiler/rustc_codegen_gcc/tests/c/static_linkage.c index 787e61f9cf105..66c77bd418b94 100644 --- a/compiler/rustc_codegen_gcc/tests/c/static_linkage.c +++ b/compiler/rustc_codegen_gcc/tests/c/static_linkage.c @@ -1,9 +1,6 @@ /* Strong definitions of the statics that `tests/run/static_linkage.rs` also defines, but weakly. * The linker has to keep these and drop the Rust ones; a backend that emits the Rust definitions - * as ordinary global symbols fails the link with a duplicate definition instead. - * - * `internal_static` is the opposite case: the Rust side keeps its own, and the two definitions - * coexist because the Rust one is local. */ + * as ordinary global symbols fails the link with a duplicate definition instead. */ #include @@ -12,7 +9,6 @@ int32_t weak_odr_static = 2; int32_t linkonce_static = 3; int32_t linkonce_odr_static = 4; int32_t common_static = 5; -int32_t internal_static = 200; /* `available_externally` promises the real definition lives elsewhere: a backend may read this one * or emit an equivalent copy of the Rust initializer, so the two have to hold the same value. */ @@ -31,7 +27,5 @@ int32_t c_read_all(void) return 14; if (common_static != 5) return 15; - if (internal_static != 200) - return 16; return 0; } diff --git a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs index bf5cb9e532799..33c9ef57e9599 100644 --- a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs @@ -35,11 +35,6 @@ extern "C" { static common_value: *const i32; #[linkage = "extern_weak"] static extern_weak_value: *const i32; - // An import is an undefined reference whatever the flavour says. Upstream bug: rustc lowers - // this one to an internal declaration, which LLVM's verifier rejects ("Global is external, but - // doesn't have external or weak linkage!") and which crashes cg_llvm at -O3. - #[linkage = "internal"] - static internal_value: *const i32; // Nothing defines this one, so it stays null instead of breaking the link. #[linkage = "extern_weak"] @@ -73,9 +68,6 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { if *extern_weak_value != 8 { return 8; } - if *internal_value != 9 { - return 9; - } if undefined_value as usize != 0 { return 10; } diff --git a/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs index 7b911c064d797..ba9e1fe4d2645 100644 --- a/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs @@ -7,8 +7,7 @@ // `tests/c/static_linkage.c`, which defines the overridable ones strongly. // // If `predefine_static` were to ignore its `linkage` argument outright, every static would come out as -// an ordinary global symbol: the overridable ones would clash with the C definitions at link time, and -// `internal` would export a symbol it should have kept private. +// an ordinary global symbol: the overridable ones would clash with the C definitions at link time. #![feature(linkage, no_core)] #![no_std] @@ -39,11 +38,6 @@ pub static linkonce_odr_static: i32 = 0; #[no_mangle] pub static mut common_static: i32 = 0; -// Private to this crate, so the C definition of the same name is a different object. -#[linkage = "internal"] -#[no_mangle] -pub static internal_static: i32 = 100; - // Not overridden by the C side: the definition here is the one that survives. #[linkage = "weak"] #[no_mangle] @@ -66,9 +60,6 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { return result; } - if internal_static != 100 { - return 1; - } if only_weak_static != 6 { return 2; } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3debf3248ff80..a7dbf7dc5e035 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1176,7 +1176,6 @@ symbols! { integer_max, integer_min, integral, - internal, internal_eq_trait_method_impls, internal_features, interrupt, diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index 0717a2d5a6c9e..d80236cae7c6d 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -7,9 +7,6 @@ #[linkage = "external"] pub static TEST2: bool = true; -#[linkage = "internal"] -pub static TEST3: bool = true; - #[cfg(not(target_env = "msvc"))] #[linkage = "linkonce"] pub static TEST4: bool = true; diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index aa25cd39ba291..45555eef3d120 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `linkage` attribute input LL | #[linkage = "foo"] | ^^^^^^^^^^----- | | - | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `internal`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` + | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` error: aborting due to 1 previous error diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs index 6a23cd58236ff..bacbd128cd632 100644 --- a/tests/ui/lint/inline-exported.rs +++ b/tests/ui/lint/inline-exported.rs @@ -22,7 +22,3 @@ fn external_linkage() {} #[inline] fn normal() {} - -#[inline] -#[linkage = "internal"] // not exported -fn internal_linkage() {} From 6d02b772e3930c415cf7990ffb5fbfb277bde796 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 27 Sep 2026 16:08:18 +0200 Subject: [PATCH 1079/1309] Remove #[linkage = "external"] Rustc already defaults to this for #[no_mangle]/#[export_name] items. There is no reason to explicitly use it. --- .../rustc_attr_parsing/src/attributes/link_attrs.rs | 3 --- compiler/rustc_codegen_gcc/tests/c/import_linkage.c | 1 - .../rustc_codegen_gcc/tests/run/import_linkage.rs | 5 ----- tests/codegen-llvm/direct-access-external-data.rs | 10 ---------- .../loongarch/direct-access-external-data.rs | 10 ---------- tests/run-make/linkage-attr-on-static/bar.rs | 2 +- tests/run-make/linkage-attr-on-static/rmake.rs | 2 ++ .../run-make/naked-symbol-visibility/a_rust_dylib.rs | 11 ----------- tests/run-make/naked-symbol-visibility/rmake.rs | 3 --- tests/ui/asm/naked-functions/naked-functions.rs | 2 +- tests/ui/linkage-attr/auxiliary/def_external.rs | 5 ----- tests/ui/linkage-attr/auxiliary/def_weak.rs | 5 +++++ .../linkage-attr-does-not-panic-llvm-issue-33992.rs | 3 --- tests/ui/linkage-attr/linkage-import.rs | 8 +++++--- tests/ui/linkage-attr/linkage3.stderr | 2 +- tests/ui/linkage-attr/linkage4.rs | 2 +- tests/ui/linkage-attr/linkage4.stderr | 2 +- tests/ui/lint/inline-exported.rs | 4 ++-- 18 files changed, 19 insertions(+), 61 deletions(-) delete mode 100644 tests/ui/linkage-attr/auxiliary/def_external.rs create mode 100644 tests/ui/linkage-attr/auxiliary/def_weak.rs diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index bb5160db76ee8..4796556819b4a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -687,7 +687,6 @@ impl SingleAttributeParser for LinkageParser { "available_externally", "common", "extern_weak", - "external", "linkonce", "linkonce_odr", "weak", @@ -712,7 +711,6 @@ impl SingleAttributeParser for LinkageParser { sym::available_externally => Linkage::AvailableExternally, sym::common => Linkage::Common, sym::extern_weak => Linkage::ExternalWeak, - sym::external => Linkage::External, sym::linkonce => Linkage::LinkOnceAny, sym::linkonce_odr => Linkage::LinkOnceODR, sym::weak => Linkage::WeakAny, @@ -725,7 +723,6 @@ impl SingleAttributeParser for LinkageParser { sym::available_externally, sym::common, sym::extern_weak, - sym::external, sym::linkonce, sym::linkonce_odr, sym::weak, diff --git a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c index d725b86c6c14b..48ab31d4c6ee2 100644 --- a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c +++ b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c @@ -6,7 +6,6 @@ #include -int32_t external_value = 1; int32_t available_externally_value = 2; int32_t linkonce_value = 3; int32_t linkonce_odr_value = 4; diff --git a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs index 33c9ef57e9599..ed9123a433973 100644 --- a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs @@ -19,8 +19,6 @@ extern crate mini_core; use mini_core::*; extern "C" { - #[linkage = "external"] - static external_value: *const i32; #[linkage = "available_externally"] static available_externally_value: *const i32; #[linkage = "linkonce"] @@ -44,9 +42,6 @@ extern "C" { #[no_mangle] extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { unsafe { - if *external_value != 1 { - return 1; - } if *available_externally_value != 2 { return 2; } diff --git a/tests/codegen-llvm/direct-access-external-data.rs b/tests/codegen-llvm/direct-access-external-data.rs index a151bb6012e1e..43ee290d3a058 100644 --- a/tests/codegen-llvm/direct-access-external-data.rs +++ b/tests/codegen-llvm/direct-access-external-data.rs @@ -22,15 +22,6 @@ unsafe extern "C" { // When "linkage" is used, we generate an indirection global. // Check dso_local is still applied to the actual global. - // CHECK: @EXTERNAL = external - // DEFAULT-SAME: dso_local - // PIE-NOT: dso_local - // DIRECT-SAME: dso_local - // INDIRECT-NOT: dso_local - // CHECK-SAME: global i8 - #[linkage = "external"] - safe static EXTERNAL: *const u32; - // CHECK: @WEAK = extern_weak // DEFAULT-SAME: dso_local // PIE-NOT: dso_local @@ -44,6 +35,5 @@ unsafe extern "C" { #[no_mangle] pub fn refer() { core::hint::black_box(VAR); - core::hint::black_box(EXTERNAL); core::hint::black_box(WEAK); } diff --git a/tests/codegen-llvm/loongarch/direct-access-external-data.rs b/tests/codegen-llvm/loongarch/direct-access-external-data.rs index de495d7fe9a72..e5b7124a722e2 100644 --- a/tests/codegen-llvm/loongarch/direct-access-external-data.rs +++ b/tests/codegen-llvm/loongarch/direct-access-external-data.rs @@ -20,15 +20,6 @@ unsafe extern "C" { // When "linkage" is used, we generate an indirection global. // Check dso_local is still applied to the actual global. - // CHECK: @EXTERNAL = external - // DEFAULT-NOT: dso_local - // PIE-NOT: dso_local - // DIRECT-SAME: dso_local - // INDIRECT-NOT: dso_local - // CHECK-SAME: global i8 - #[linkage = "external"] - safe static EXTERNAL: *const u32; - // CHECK: @WEAK = extern_weak // DEFAULT-NOT: dso_local // PIE-NOT: dso_local @@ -42,6 +33,5 @@ unsafe extern "C" { #[no_mangle] pub fn refer() { core::hint::black_box(VAR); - core::hint::black_box(EXTERNAL); core::hint::black_box(WEAK); } diff --git a/tests/run-make/linkage-attr-on-static/bar.rs b/tests/run-make/linkage-attr-on-static/bar.rs index 68607cbb65721..cbab76ba6f403 100644 --- a/tests/run-make/linkage-attr-on-static/bar.rs +++ b/tests/run-make/linkage-attr-on-static/bar.rs @@ -1,7 +1,7 @@ #![feature(linkage)] #[no_mangle] -#[linkage = "external"] +#[linkage = "weak"] static BAZ: i32 = 21; #[link(name = "foo", kind = "static")] diff --git a/tests/run-make/linkage-attr-on-static/rmake.rs b/tests/run-make/linkage-attr-on-static/rmake.rs index cd85542e9587d..f1cf80a2b0c5a 100644 --- a/tests/run-make/linkage-attr-on-static/rmake.rs +++ b/tests/run-make/linkage-attr-on-static/rmake.rs @@ -5,6 +5,8 @@ //@ ignore-cross-compile // Reason: the compiled binary is executed +//@ ignore-i686-pc-windows-gnu weak symbols broken with MinGW linker +//@ ignore-x86_64-pc-windows-gnu weak symbols broken with MinGW linker use run_make_support::{build_native_static_lib, run, rustc}; diff --git a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs index ce787f83ade6d..8d699a665ae24 100644 --- a/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs +++ b/tests/run-make/naked-symbol-visibility/a_rust_dylib.rs @@ -51,17 +51,6 @@ pub extern "C" fn public_naked_generic() -> u32 { naked_asm!("mov rax, {}", "ret", const T::COUNT) } -#[linkage = "external"] -extern "C" fn vanilla_external_linkage() -> u32 { - 42 -} - -#[unsafe(naked)] -#[linkage = "external"] -extern "C" fn naked_external_linkage() -> u32 { - naked_asm!("mov rax, 42", "ret") -} - #[cfg(not(windows))] #[linkage = "weak"] extern "C" fn vanilla_weak_linkage() -> u32 { diff --git a/tests/run-make/naked-symbol-visibility/rmake.rs b/tests/run-make/naked-symbol-visibility/rmake.rs index 69317c872f895..1acbe11dc4ae4 100644 --- a/tests/run-make/naked-symbol-visibility/rmake.rs +++ b/tests/run-make/naked-symbol-visibility/rmake.rs @@ -29,9 +29,6 @@ fn main() { // -Zshare-generics. global_function(&rdylib, "public_naked_generic"); - global_function(&rdylib, "vanilla_external_linkage"); - global_function(&rdylib, "naked_external_linkage"); - // FIXME: make this work on windows (gnu and msvc). See the PR // https://github.com/rust-lang/rust/pull/128362 for some approaches // that don't work diff --git a/tests/ui/asm/naked-functions/naked-functions.rs b/tests/ui/asm/naked-functions/naked-functions.rs index d994b1151514a..e7da65a169074 100644 --- a/tests/ui/asm/naked-functions/naked-functions.rs +++ b/tests/ui/asm/naked-functions/naked-functions.rs @@ -224,7 +224,7 @@ pub extern "C" fn compatible_doc_attributes() { naked_asm!("", options(raw)); } -#[linkage = "external"] +#[linkage = "weak"] #[unsafe(naked)] pub extern "C" fn compatible_linkage() { naked_asm!("", options(raw)); diff --git a/tests/ui/linkage-attr/auxiliary/def_external.rs b/tests/ui/linkage-attr/auxiliary/def_external.rs deleted file mode 100644 index 2300930e513af..0000000000000 --- a/tests/ui/linkage-attr/auxiliary/def_external.rs +++ /dev/null @@ -1,5 +0,0 @@ -#![feature(linkage)] -#![crate_type = "lib"] - -#[linkage="external"] -pub static EXTERN: u32 = 0; diff --git a/tests/ui/linkage-attr/auxiliary/def_weak.rs b/tests/ui/linkage-attr/auxiliary/def_weak.rs new file mode 100644 index 0000000000000..a8940f73c5536 --- /dev/null +++ b/tests/ui/linkage-attr/auxiliary/def_weak.rs @@ -0,0 +1,5 @@ +#![feature(linkage)] +#![crate_type = "lib"] + +#[linkage = "weak"] +pub static WEAK: u32 = 0; diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index d80236cae7c6d..a7209b71c7809 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -4,9 +4,6 @@ #![feature(linkage)] -#[linkage = "external"] -pub static TEST2: bool = true; - #[cfg(not(target_env = "msvc"))] #[linkage = "linkonce"] pub static TEST4: bool = true; diff --git a/tests/ui/linkage-attr/linkage-import.rs b/tests/ui/linkage-attr/linkage-import.rs index 838d1fc29a238..427a487ef1905 100644 --- a/tests/ui/linkage-attr/linkage-import.rs +++ b/tests/ui/linkage-attr/linkage-import.rs @@ -1,8 +1,10 @@ //@ build-pass -//@ aux-build:def_external.rs +//@ aux-build:def_weak.rs +//@ ignore-i686-pc-windows-gnu weak symbols broken with MinGW linker +//@ ignore-x86_64-pc-windows-gnu weak symbols broken with MinGW linker -extern crate def_external as dep; +extern crate def_weak as dep; fn main() { - println!("{:p}", &dep::EXTERN); + println!("{:p}", &dep::WEAK); } diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index 45555eef3d120..4a85c39009517 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `linkage` attribute input LL | #[linkage = "foo"] | ^^^^^^^^^^----- | | - | valid arguments are `available_externally`, `common`, `extern_weak`, `external`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` + | valid arguments are `available_externally`, `common`, `extern_weak`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` error: aborting due to 1 previous error diff --git a/tests/ui/linkage-attr/linkage4.rs b/tests/ui/linkage-attr/linkage4.rs index 3b935f9723dc1..25df81189d8f5 100644 --- a/tests/ui/linkage-attr/linkage4.rs +++ b/tests/ui/linkage-attr/linkage4.rs @@ -1,4 +1,4 @@ -#[linkage = "external"] +#[linkage = "weak"] static foo: isize = 0; //~^^ ERROR: the `linkage` attribute is experimental and not portable diff --git a/tests/ui/linkage-attr/linkage4.stderr b/tests/ui/linkage-attr/linkage4.stderr index a5970d100581a..2f04ceee5199d 100644 --- a/tests/ui/linkage-attr/linkage4.stderr +++ b/tests/ui/linkage-attr/linkage4.stderr @@ -1,7 +1,7 @@ error[E0658]: the `linkage` attribute is experimental and not portable across platforms --> $DIR/linkage4.rs:1:3 | -LL | #[linkage = "external"] +LL | #[linkage = "weak"] | ^^^^^^^ | = note: see issue #29603 for more information diff --git a/tests/ui/lint/inline-exported.rs b/tests/ui/lint/inline-exported.rs index bacbd128cd632..25ca5f0633079 100644 --- a/tests/ui/lint/inline-exported.rs +++ b/tests/ui/lint/inline-exported.rs @@ -17,8 +17,8 @@ fn export_name() {} #[inline] //~^ ERROR: `#[inline]` is ignored on externally exported functions -#[linkage = "external"] -fn external_linkage() {} +#[linkage = "weak"] +fn weak_linkage() {} #[inline] fn normal() {} From d731edabc063472a52ae5fea422aca122989e921 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Sun, 27 Sep 2026 16:20:51 +0200 Subject: [PATCH 1080/1309] Remove #[linkage = "common"] A common definition is like a weak definition except that it must be a zero-initialized static and when merging two common symbols with the same name, the size and alignment are set to the higher of both symbols. This is used for tentative definitions in C and doesn't have any reason to exist outside of that. This behavior doesn't work across dylibs and common symbols have inconsistent behavior across linkers [1]. It is also fragile to rely on getting the largest size of all common symbol definitions as a (possibly smaller) global definition can override it. Link: https://maskray.me/blog/all-about-common-symbols [1] --- compiler/rustc_attr_ir/src/data_structures.rs | 1 - .../rustc_attr_ir/src/encode_cross_crate.rs | 1 - .../src/attributes/link_attrs.rs | 3 --- compiler/rustc_codegen_gcc/src/base.rs | 19 ++++------------- compiler/rustc_codegen_gcc/src/consts.rs | 21 ++----------------- .../tests/c/import_linkage.c | 1 - .../tests/c/static_linkage.c | 3 --- .../tests/run/import_linkage.rs | 5 ----- .../tests/run/static_linkage.rs | 5 ----- .../tests/run/weak_function_linkage.rs | 3 --- compiler/rustc_codegen_llvm/src/base.rs | 1 - .../rustc_codegen_ssa/src/mir/naked_asm.rs | 1 - .../rustc_monomorphize/src/partitioning.rs | 1 - compiler/rustc_span/src/symbol.rs | 1 - .../codegen_attr_on_required_trait_method.rs | 2 +- ...degen_attr_on_required_trait_method.stderr | 2 +- .../common-linkage-non-zero-init.rs | 17 --------------- .../common-linkage-non-zero-init.stderr | 3 --- ...ge-attr-does-not-panic-llvm-issue-33992.rs | 2 +- tests/ui/linkage-attr/linkage3.stderr | 2 +- 20 files changed, 10 insertions(+), 84 deletions(-) delete mode 100644 tests/ui/linkage-attr/common-linkage-non-zero-init.rs delete mode 100644 tests/ui/linkage-attr/common-linkage-non-zero-init.stderr diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 712ed41ae7759..55c0bedb9c39c 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -283,7 +283,6 @@ impl StrippedCfgItem { #[derive(StableHash, PrintAttribute)] pub enum Linkage { AvailableExternally, - Common, ExternalWeak, External, Internal, diff --git a/compiler/rustc_attr_ir/src/encode_cross_crate.rs b/compiler/rustc_attr_ir/src/encode_cross_crate.rs index 66fbbc1e3cbf7..b6733e8c1db54 100644 --- a/compiler/rustc_attr_ir/src/encode_cross_crate.rs +++ b/compiler/rustc_attr_ir/src/encode_cross_crate.rs @@ -265,7 +265,6 @@ impl AttributeKind { Linkage(linkage, _) => match *linkage { crate::Linkage::Internal => false, crate::Linkage::AvailableExternally - | crate::Linkage::Common | crate::Linkage::External | crate::Linkage::ExternalWeak | crate::Linkage::LinkOnceAny diff --git a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs index 4796556819b4a..ed911a63eb7fe 100644 --- a/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/link_attrs.rs @@ -685,7 +685,6 @@ impl SingleAttributeParser for LinkageParser { ]); const TEMPLATE: AttributeTemplate = template!(NameValueStr: [ "available_externally", - "common", "extern_weak", "linkonce", "linkonce_odr", @@ -709,7 +708,6 @@ impl SingleAttributeParser for LinkageParser { // and don't have to be, LLVM treats them as no-ops. let linkage = match value { sym::available_externally => Linkage::AvailableExternally, - sym::common => Linkage::Common, sym::extern_weak => Linkage::ExternalWeak, sym::linkonce => Linkage::LinkOnceAny, sym::linkonce_odr => Linkage::LinkOnceODR, @@ -721,7 +719,6 @@ impl SingleAttributeParser for LinkageParser { name_value.value_span, &[ sym::available_externally, - sym::common, sym::extern_weak, sym::linkonce, sym::linkonce_odr, diff --git a/compiler/rustc_codegen_gcc/src/base.rs b/compiler/rustc_codegen_gcc/src/base.rs index 07214096b3e49..acf5c75e4d8cd 100644 --- a/compiler/rustc_codegen_gcc/src/base.rs +++ b/compiler/rustc_codegen_gcc/src/base.rs @@ -55,19 +55,14 @@ pub fn global_linkage_to_gcc(linkage: Linkage) -> GlobalKind { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => GlobalKind::Exported, + | Linkage::ExternalWeak => GlobalKind::Exported, } } /// The attribute a global *definition* needs on top of its [`GlobalKind`] to get this linkage. #[cfg(feature = "master")] pub fn global_linkage_attribute<'gcc>(linkage: Linkage) -> Option> { - match linkage { - Linkage::Common => Some(VarAttribute::Common), - _ if linkage_needs_weak_attribute(linkage) => Some(VarAttribute::Weak), - _ => None, - } + if linkage_needs_weak_attribute(linkage) { Some(VarAttribute::Weak) } else { None } } /// The type of a function *definition* with an explicit `#[linkage]`. @@ -85,17 +80,12 @@ pub fn linkage_to_gcc(linkage: Linkage) -> FunctionType { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => FunctionType::Exported, + | Linkage::ExternalWeak => FunctionType::Exported, } } /// Whether a definition with this linkage must carry the `weak` attribute, so that a strong /// definition in another object file wins over it instead of clashing with it. -/// -/// `common` is in here for functions only: GCC honours that attribute on a variable, but drops it -/// on a function, so a common function falls back to weak. Globals go through -/// `global_linkage_attribute` instead. #[cfg(feature = "master")] pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { match linkage { @@ -103,8 +93,7 @@ pub fn linkage_needs_weak_attribute(linkage: Linkage) -> bool { | Linkage::LinkOnceODR | Linkage::WeakAny | Linkage::WeakODR - | Linkage::ExternalWeak - | Linkage::Common => true, + | Linkage::ExternalWeak => true, Linkage::External | Linkage::AvailableExternally | Linkage::Internal => false, } } diff --git a/compiler/rustc_codegen_gcc/src/consts.rs b/compiler/rustc_codegen_gcc/src/consts.rs index c58ab6d2a9bef..0784064547e0f 100644 --- a/compiler/rustc_codegen_gcc/src/consts.rs +++ b/compiler/rustc_codegen_gcc/src/consts.rs @@ -13,8 +13,7 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_log::tracing::trace; use rustc_middle::middle::codegen_fn_attrs::{CodegenFnAttrFlags, CodegenFnAttrs}; use rustc_middle::mir::interpret::{ - self, Allocation, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, - read_target_uint, + self, ConstAllocation, CtfeProvenance, ErrorHandled, Scalar as InterpScalar, read_target_uint, }; use rustc_middle::mono::MonoItem; use rustc_middle::ty::layout::LayoutOf; @@ -113,12 +112,7 @@ impl<'gcc, 'tcx> StaticCodegenMethods for CodegenCx<'gcc, 'tcx> { // NOTE: Alignment from attributes has already been applied to the allocation. set_global_alignment(self, global, alloc.align); - // A common symbol is storage the linker allocates and zero-fills, so giving the definition - // an initializer — even an all-zero one — takes it back out of `.comm`. A non-zero one is - // kept: the symbol is then an ordinary definition, which is what GCC does with it too. - if attrs.linkage != Some(Linkage::Common) || !is_zero_initializer(alloc) { - global.global_set_initializer_rvalue(value); - } + global.global_set_initializer_rvalue(value); // As an optimization, all shared statics which do not have interior // mutability are placed into read-only memory. @@ -458,17 +452,6 @@ pub(crate) fn const_alloc_to_gcc_uncached<'gcc>( cx.const_struct(&llvals, true) } -/// Whether this allocation is all zeroes, and so needs no initializer to be spelled out. -fn is_zero_initializer(alloc: &Allocation) -> bool { - alloc.provenance().ptrs().is_empty() - // This `inspect` is okay: it is within the bounds of the allocation, there is no provenance - // to misread, and it does not affect interpreter execution. - && alloc - .inspect_with_uninit_and_ptr_outside_interpreter(0..alloc.size().bytes_usize()) - .iter() - .all(|&byte| byte == 0) -} - fn codegen_static_initializer<'gcc, 'tcx>( cx: &CodegenCx<'gcc, 'tcx>, def_id: DefId, diff --git a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c index 48ab31d4c6ee2..227fa1c848ddf 100644 --- a/compiler/rustc_codegen_gcc/tests/c/import_linkage.c +++ b/compiler/rustc_codegen_gcc/tests/c/import_linkage.c @@ -11,5 +11,4 @@ int32_t linkonce_value = 3; int32_t linkonce_odr_value = 4; int32_t weak_value = 5; int32_t weak_odr_value = 6; -int32_t common_value = 7; int32_t extern_weak_value = 8; diff --git a/compiler/rustc_codegen_gcc/tests/c/static_linkage.c b/compiler/rustc_codegen_gcc/tests/c/static_linkage.c index 66c77bd418b94..00360d8633e68 100644 --- a/compiler/rustc_codegen_gcc/tests/c/static_linkage.c +++ b/compiler/rustc_codegen_gcc/tests/c/static_linkage.c @@ -8,7 +8,6 @@ int32_t weak_static = 1; int32_t weak_odr_static = 2; int32_t linkonce_static = 3; int32_t linkonce_odr_static = 4; -int32_t common_static = 5; /* `available_externally` promises the real definition lives elsewhere: a backend may read this one * or emit an equivalent copy of the Rust initializer, so the two have to hold the same value. */ @@ -25,7 +24,5 @@ int32_t c_read_all(void) return 13; if (linkonce_odr_static != 4) return 14; - if (common_static != 5) - return 15; return 0; } diff --git a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs index ed9123a433973..58008ecbc9746 100644 --- a/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/import_linkage.rs @@ -29,8 +29,6 @@ extern "C" { static weak_value: *const i32; #[linkage = "weak_odr"] static weak_odr_value: *const i32; - #[linkage = "common"] - static common_value: *const i32; #[linkage = "extern_weak"] static extern_weak_value: *const i32; @@ -57,9 +55,6 @@ extern "C" fn main(_argc: i32, _argv: *const *const u8) -> i32 { if *weak_odr_value != 6 { return 6; } - if *common_value != 7 { - return 7; - } if *extern_weak_value != 8 { return 8; } diff --git a/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs index ba9e1fe4d2645..3c9303fa8cf16 100644 --- a/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/static_linkage.rs @@ -33,11 +33,6 @@ pub static linkonce_static: i32 = 0; #[no_mangle] pub static linkonce_odr_static: i32 = 0; -// `common` is only valid on a mutable global: LLVM rejects a constant one. -#[linkage = "common"] -#[no_mangle] -pub static mut common_static: i32 = 0; - // Not overridden by the C side: the definition here is the one that survives. #[linkage = "weak"] #[no_mangle] diff --git a/compiler/rustc_codegen_gcc/tests/run/weak_function_linkage.rs b/compiler/rustc_codegen_gcc/tests/run/weak_function_linkage.rs index 677f01353401a..406b85df10b02 100644 --- a/compiler/rustc_codegen_gcc/tests/run/weak_function_linkage.rs +++ b/compiler/rustc_codegen_gcc/tests/run/weak_function_linkage.rs @@ -41,9 +41,6 @@ extern "C" fn linkonce_odr_function() -> i32 { 4 } -// `#[linkage = "common"]` is absent on purpose: a common symbol is `SHN_COMMON`, which the object -// format only allows for objects, so no backend can give a function that linkage. - // Not overridden by the C side: the definition here is the one that runs. #[linkage = "weak"] #[no_mangle] diff --git a/compiler/rustc_codegen_llvm/src/base.rs b/compiler/rustc_codegen_llvm/src/base.rs index cf278694399f3..77cb37edec770 100644 --- a/compiler/rustc_codegen_llvm/src/base.rs +++ b/compiler/rustc_codegen_llvm/src/base.rs @@ -237,7 +237,6 @@ pub(crate) fn linkage_to_llvm(linkage: Linkage) -> llvm::Linkage { Linkage::WeakODR => llvm::Linkage::WeakODRLinkage, Linkage::Internal => llvm::Linkage::InternalLinkage, Linkage::ExternalWeak => llvm::Linkage::ExternalWeakLinkage, - Linkage::Common => llvm::Linkage::CommonLinkage, } } diff --git a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs index 2fa6f3fc06550..5433b9da6f2b6 100644 --- a/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs +++ b/compiler/rustc_codegen_ssa/src/mir/naked_asm.rs @@ -228,7 +228,6 @@ fn prefix_and_suffix<'tcx>( // LTO can fail when internal linkage is used. emit_fatal("naked functions may not have internal linkage") } - Linkage::Common => emit_fatal("Functions may not have common linkage"), Linkage::AvailableExternally => { // this would make the function equal an extern definition emit_fatal("Functions may not have available_externally linkage") diff --git a/compiler/rustc_monomorphize/src/partitioning.rs b/compiler/rustc_monomorphize/src/partitioning.rs index 43ce9634cc203..16df895b0f728 100644 --- a/compiler/rustc_monomorphize/src/partitioning.rs +++ b/compiler/rustc_monomorphize/src/partitioning.rs @@ -1252,7 +1252,6 @@ fn collect_and_partition_mono_items(tcx: TyCtxt<'_>, (): ()) -> MonoItemPartitio Linkage::WeakODR => "WeakODR", Linkage::Internal => "Internal", Linkage::ExternalWeak => "ExternalWeak", - Linkage::Common => "Common", }; output.push('['); diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a7dbf7dc5e035..a003f20e3512d 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -671,7 +671,6 @@ symbols! { cold_path, collapse_debuginfo, column, - common, compare_bytes, compare_exchange, compare_exchange_weak, diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs index 737ebf7f2b144..2ea4e0b5a395c 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.rs +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.rs @@ -11,7 +11,7 @@ trait Test { //~^ ERROR cannot be used on required trait methods [unused_attributes] //~| WARN previously accepted fn method2(&self); - #[linkage = "common"] + #[linkage = "weak"] //~^ ERROR `linkage` attribute cannot be used on required trait methods fn method3(&self); #[track_caller] diff --git a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr index b5452ba2882c0..729231956337d 100644 --- a/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr +++ b/tests/ui/attributes/codegen_attr_on_required_trait_method.stderr @@ -1,7 +1,7 @@ error: the `linkage` attribute cannot be used on required trait methods --> $DIR/codegen_attr_on_required_trait_method.rs:14:7 | -LL | #[linkage = "common"] +LL | #[linkage = "weak"] | ^^^^^^^ | = help: the `linkage` attribute can be applied to foreign functions, foreign statics, functions with a body, and statics diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs b/tests/ui/linkage-attr/common-linkage-non-zero-init.rs deleted file mode 100644 index 512616251c2f7..0000000000000 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.rs +++ /dev/null @@ -1,17 +0,0 @@ -//@ build-fail -//@ failure-status: 101 -//@ known-bug: #109681 -//@ ignore-wasm32 this appears to SIGABRT on wasm, not fail cleanly -//@ compile-flags: -Z verify-llvm-ir -//@ ignore-backends: gcc - -// This test verifies that we continue to hit the LLVM error for common linkage with non-zero -// initializers, since it generates invalid LLVM IR. -// Linkages are internal features marked as perma-unstable, so we don't need to fix the issue -// for now. -#![crate_type="lib"] -#![feature(linkage)] - -#[linkage = "common"] -#[no_mangle] -pub static TEST: bool = true; diff --git a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr b/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr deleted file mode 100644 index 93015bb2bac12..0000000000000 --- a/tests/ui/linkage-attr/common-linkage-non-zero-init.stderr +++ /dev/null @@ -1,3 +0,0 @@ -'common' global must have a zero initializer! -ptr @TEST -rustc-LLVM ERROR: Broken module found, compilation aborted! diff --git a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs index a7209b71c7809..e1ad2405b1df8 100644 --- a/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs +++ b/tests/ui/linkage-attr/linkage-attr-does-not-panic-llvm-issue-33992.rs @@ -1,6 +1,6 @@ //@ run-pass //@ ignore-apple -//@ ignore-wasm32 common linkage not implemented right now +//@ ignore-wasm32 linkonce linkage not working right now #![feature(linkage)] diff --git a/tests/ui/linkage-attr/linkage3.stderr b/tests/ui/linkage-attr/linkage3.stderr index 4a85c39009517..616f80df09c8b 100644 --- a/tests/ui/linkage-attr/linkage3.stderr +++ b/tests/ui/linkage-attr/linkage3.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `linkage` attribute input LL | #[linkage = "foo"] | ^^^^^^^^^^----- | | - | valid arguments are `available_externally`, `common`, `extern_weak`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` + | valid arguments are `available_externally`, `extern_weak`, `linkonce`, `linkonce_odr`, `weak` or `weak_odr` error: aborting due to 1 previous error From 54bb4907840cb61233377cbdb1fcb6dbb8968eac Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Wed, 30 Sep 2026 23:17:34 +0800 Subject: [PATCH 1081/1309] Revert "Route rustfmt repo backport nominations to zulip" This reverts commit b4260f44f5d8cd538718b9046eb51baaa1eb8f5e, reversing changes made to ec46636574fca6fce6014a143392f7d4a6d4d2ee. Since we can't actually do backports from rustfmt repo itself... --- src/tools/rustfmt/triagebot.toml | 51 -------------------------------- 1 file changed, 51 deletions(-) diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml index d156d2b70ae58..de28ad00a4272 100644 --- a/src/tools/rustfmt/triagebot.toml +++ b/src/tools/rustfmt/triagebot.toml @@ -102,57 +102,6 @@ add_labels = ["S-waiting-on-review"] # Documentation at: [shortcut] -# ------------------------------------------------------------------------------ -# Backport nominations (rustfmt repo side) -# ------------------------------------------------------------------------------ - -[notify-zulip."beta-nominated".rustfmt] -zulip_stream = 621384 # #t-rustfmt/backports -topic = "rustfmt#{number}: beta-nominated" -message_on_add = [ - """\ -@*T-rustfmt* @*T-rustfmt-contributors* PR rustfmt#{number} "{title}" has been nominated -for beta backport. -""", - """\ -/poll Approve beta backport of rustfmt#{number}? -approve -decline -don't know -""", -] -message_on_remove = "PR rustfmt#{number}'s beta-nomination has been removed." - -[notify-zulip."beta-accepted".rustfmt] -zulip_stream = 621384 # #t-rustfmt/backports -# Put it in the same thread as beta-nominated. -topic = "rustfmt#{number}: beta-nominated" -message_on_add = "PR rustfmt#{number} has been **accepted** for **beta** backport." - -[notify-zulip."stable-nominated".rustfmt] -zulip_stream = 621384 # #t-rustfmt/backports -topic = "rustfmt#{number}: stable-nominated" -message_on_add = [ - """\ -@*T-rustfmt* @*T-rustfmt-contributors* PR rustfmt#{number} "{title}" has been nominated -for stable backport. -""", - """\ -/poll Approve stable backport of rustfmt#{number}? -approve -approve (but does not justify new dot release on its own) -decline -don't know -""", -] -message_on_remove = "PR rustfmt#{number}'s stable-nomination has been removed." - -[notify-zulip."stable-accepted".rustfmt] -zulip_stream = 621384 # #t-rustfmt/backports -# Put it in the same thread as stable-nominated. -topic = "rustfmt#{number}: stable-nominated" -message_on_add = "PR rustfmt#{number} has been **accepted** for **stable** backport." - # ------------------------------------------------------------------------------ # PR assignments # ------------------------------------------------------------------------------ From 3c67da6404f8269505e8953c7db8fef04a5534ef Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:33:32 +0530 Subject: [PATCH 1082/1309] Cover macro export on macro_rules definitions --- tests/ui/attributes/macro_export_on_decl_macro.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/tests/ui/attributes/macro_export_on_decl_macro.rs b/tests/ui/attributes/macro_export_on_decl_macro.rs index e6fe66ac6c30e..413b844cc1b83 100644 --- a/tests/ui/attributes/macro_export_on_decl_macro.rs +++ b/tests/ui/attributes/macro_export_on_decl_macro.rs @@ -6,4 +6,10 @@ #[macro_export] //~ ERROR `#[macro_export]` has no effect on declarative macro definitions pub macro foo() {} +// `#[macro_export]` on `macro_rules!` is valid and should not emit unused_attributes +#[macro_export] +macro_rules! bar { + () => {}; +} + fn main() {} From 7f542b6a12648df131e1dc9406d3c763a5dc2d0e Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:33:33 +0530 Subject: [PATCH 1083/1309] Check declarative macro exports during attribute finalization --- .../src/attributes/macro_attrs.rs | 18 +++++++++++++-- .../rustc_attr_parsing/src/diagnostics.rs | 7 ++++++ compiler/rustc_passes/src/check_attr.rs | 23 +------------------ compiler/rustc_passes/src/diagnostics.rs | 7 ------ 4 files changed, 24 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index dde10225e652f..968a613209248 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -1,10 +1,12 @@ +use rustc_ast::ItemKind; use rustc_attr_ir::{MacroUseArgs, find_attr}; use rustc_feature::AttributeStability; -use rustc_lint_defs::builtin::INVALID_MACRO_EXPORT_ARGUMENTS; +use rustc_lint_defs::builtin::{INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES}; use rustc_structures::CollapseMacroDebuginfo; use super::prelude::*; -use crate::diagnostics::MacroOnlyAttribute; +use crate::context::ShouldEmit; +use crate::diagnostics::{MacroExport, MacroOnlyAttribute}; pub(crate) struct MacroEscapeParser; impl NoArgsAttributeParser for MacroEscapeParser { @@ -175,8 +177,20 @@ impl SingleAttributeParser for MacroExportParser { return None; } }; + Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros }) } + + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { + if cx.target != Target::MacroDef || matches!(cx.should_emit, ShouldEmit::Nothing) { + return; + } + + let item = cx.target_item.unwrap(); + if let ItemKind::MacroDef(_, macro_def) = &item.kind && !macro_def.macro_rules { + cx.emit_lint(UNUSED_ATTRIBUTES, MacroExport::OnDeclMacro, attr_span); + } + } } pub(crate) struct CollapseDebugInfoParser; diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index bf630c6bf91a0..879f8da67ae15 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -2063,3 +2063,10 @@ pub(crate) struct UnusedDuplicate { )] pub warning: bool, } + +#[derive(Diagnostic)] +pub(crate) enum MacroExport { + #[diag("`#[macro_export]` has no effect on declarative macro definitions")] + #[note("declarative macros follow the same exporting rules as regular items")] + OnDeclMacro, +} diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 3c920d14006bb..d6501ee672bff 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -207,9 +207,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } AttributeKind::Naked(..) => self.check_naked(hir_id, target), AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), - AttributeKind::MacroExport { span, .. } => { - self.check_macro_export(hir_id, *span, target) - } AttributeKind::RustcLegacyConstGenerics { attr_span, fn_indexes } => { self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes) } @@ -275,6 +272,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::LinkSection { .. } => (), AttributeKind::LoopMatch(..) => (), AttributeKind::MacroEscape => (), + AttributeKind::MacroExport { .. } => (), AttributeKind::MacroUse { .. } => (), AttributeKind::Marker => (), AttributeKind::MoveSizeLimit { .. } => (), @@ -1281,25 +1279,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - fn check_macro_export(&self, hir_id: HirId, attr_span: Span, target: Target) { - if target != Target::MacroDef { - return; - } - - // special case when `#[macro_export]` is applied to a macro 2.0 - let (_, macro_definition, _) = self.tcx.hir_node(hir_id).expect_item().expect_macro(); - let is_decl_macro = !macro_definition.macro_rules; - - if is_decl_macro { - self.tcx.emit_node_span_lint( - UNUSED_ATTRIBUTES, - hir_id, - attr_span, - diagnostics::MacroExport::OnDeclMacro, - ); - } - } - fn check_unused_attribute(&self, hir_id: HirId, attr: &Attribute) { // Warn on useless empty attributes. // FIXME(jdonszelmann): this lint should be moved to attribute parsing, see `AcceptContext::warn_empty_attribute` diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 7c82811f99276..76b00864c35fe 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -199,13 +199,6 @@ pub(crate) struct RustcForceInlineCoro { pub span: Span, } -#[derive(Diagnostic)] -pub(crate) enum MacroExport { - #[diag("`#[macro_export]` has no effect on declarative macro definitions")] - #[note("declarative macros follow the same exporting rules as regular items")] - OnDeclMacro, -} - #[derive(Subdiagnostic)] pub(crate) enum UnusedNote { #[note("attribute `{$name}` with an empty list has no effect")] From bf2b89cb1946c20726136606062caf1f79d2214f Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:53:05 +0530 Subject: [PATCH 1084/1309] Format macro export finalization check --- compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 968a613209248..8bca20cda67aa 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -187,7 +187,9 @@ impl SingleAttributeParser for MacroExportParser { } let item = cx.target_item.unwrap(); - if let ItemKind::MacroDef(_, macro_def) = &item.kind && !macro_def.macro_rules { + if let ItemKind::MacroDef(_, macro_def) = &item.kind + && !macro_def.macro_rules + { cx.emit_lint(UNUSED_ATTRIBUTES, MacroExport::OnDeclMacro, attr_span); } } From 1eb5c521ce0da5f66a184db06611ff41f7e28a44 Mon Sep 17 00:00:00 2001 From: Simon Sudarushkin <68971770+simonether@users.noreply.github.com> Date: Wed, 30 Sep 2026 21:41:24 +0500 Subject: [PATCH 1085/1309] Suggest `#[unsafe(no_mangle)]` for entry points in `no_std` binaries --- compiler/rustc_monomorphize/src/diagnostics.rs | 2 +- tests/ui/no_std/no-std-no-start-binary.stderr | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_monomorphize/src/diagnostics.rs b/compiler/rustc_monomorphize/src/diagnostics.rs index a1930dbea3cda..7635050603c41 100644 --- a/compiler/rustc_monomorphize/src/diagnostics.rs +++ b/compiler/rustc_monomorphize/src/diagnostics.rs @@ -96,7 +96,7 @@ pub(crate) struct EncounteredErrorWhileInstantiatingGlobalAsm { #[derive(Diagnostic)] #[diag("using `fn main` requires the standard library")] #[help( - "use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]`" + "use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[unsafe(no_mangle)]`" )] pub(crate) struct StartNotFound; diff --git a/tests/ui/no_std/no-std-no-start-binary.stderr b/tests/ui/no_std/no-std-no-start-binary.stderr index dd06c234da294..bc6ded80ff8fe 100644 --- a/tests/ui/no_std/no-std-no-start-binary.stderr +++ b/tests/ui/no_std/no-std-no-start-binary.stderr @@ -1,6 +1,6 @@ error: using `fn main` requires the standard library | - = help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[no_mangle]` + = help: use `#![no_main]` to bypass the Rust generated entrypoint and declare a platform specific entrypoint yourself, usually with `#[unsafe(no_mangle)]` error: aborting due to 1 previous error From cfa655ad24dbe4cd823f699ef9b52b5e95a0db43 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Wed, 30 Sep 2026 13:22:11 -0400 Subject: [PATCH 1086/1309] tests: accept noundef in a couple more places LLVM 24 got smarter and is able to mark some more things noundef, which showed up in some of our test checks. --- tests/codegen-llvm/sparc-struct-abi.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/codegen-llvm/sparc-struct-abi.rs b/tests/codegen-llvm/sparc-struct-abi.rs index 6a31fe0d37f15..f79814e4bb4f1 100644 --- a/tests/codegen-llvm/sparc-struct-abi.rs +++ b/tests/codegen-llvm/sparc-struct-abi.rs @@ -29,7 +29,7 @@ pub struct BoolFloat { f: f32, } -// CHECK: define inreg { i32, float } @structboolfloat() +// CHECK: define inreg{{( noundef)?}} { i32, float } @structboolfloat() // CHECK-NEXT: start: // CHECK-NEXT: ret { i32, float } { i32 16777216, float {{0x40091EB860000000|3.140000e\+00}} } #[no_mangle] @@ -48,7 +48,7 @@ pub struct ShortDouble { d: f64, } -// CHECK: define { i64, double } @structshortdouble() +// CHECK: define{{( noundef)?}} { i64, double } @structshortdouble() // CHECK-NEXT: start: // CHECK-NEXT: ret { i64, double } { i64 34621422135410688, double 3.140000e+00 } #[no_mangle] @@ -88,7 +88,7 @@ pub struct NestedStructs { b: FloatFloat, } -// CHECK: define inreg { float, float, float, float } @structnestestructs() +// CHECK: define inreg{{( noundef)?}} { float, float, float, float } @structnestestructs() // CHECK-NEXT: start: // CHECK-NEXT: ret { float, float, float, float } { float {{0x3FB99999A0000000|1.000000e-01}}, float {{0x3FF19999A0000000|1.100000e\+00}}, float {{0x40019999A0000000|2.200000e\+00}}, float {{0x400A666660000000|3.300000e\+00}} } #[no_mangle] From dd0f941012649493d4de018135ef47d4245b962c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sun, 26 Jul 2026 14:02:45 +0200 Subject: [PATCH 1087/1309] make mips64 `Complex` ABI GCC-compatible --- compiler/rustc_target/src/callconv/mips64.rs | 65 +++++++++++++++++++- tests/codegen-llvm/complex-abi.rs | 35 ++++++++--- 2 files changed, 89 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index 0e3ccf33c3ffe..e444e605d3b5a 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -1,6 +1,7 @@ use arrayvec::ArrayVec; use rustc_abi::{ - BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface, + BackendRepr, FieldsShape, Float, HasDataLayout, Integer, Numeric, Primitive, Reg, RegKind, + Size, TyAbiInterface, }; use crate::callconv::{ArgAbi, ArgAttribute, ArgExtension, CastTarget, FnAbi, PassMode, Uniform}; @@ -56,6 +57,22 @@ where let size = ret.layout.size; let bits = size.bits(); if bits <= 128 { + // NOTE: Complex is returned indirectly. + if let Some(component) = ret.layout.complex_number(cx) { + match component { + Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) => { + // Return a Complex<{integer}> packed into a single register when that fits. + ret.cast_to(Reg { kind: RegKind::Integer, size }); + } + _ => { + // Otherwise pass in 2 registers. + let reg = Reg { kind: component.reg_kind(), size: component.size() }; + ret.cast_to(CastTarget::pair(reg, reg)); + } + } + return; + } + // Unlike other architectures which return aggregates in registers, MIPS n64 limits the // use of float registers to structures (not unions) containing exactly one or two // float fields. @@ -103,6 +120,52 @@ where extend_integer_width_mips(arg, 64); } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { arg.make_indirect(); + } else if let Some(component) = arg.layout.complex_number(cx) + && !matches!(component, Numeric::Float(Float::F16)) + { + let slot = dl.pointer_size(); + let curr_offset = offset.align_to(align); + + const NUM_ARG_SLOTS: u64 = 8; + + match component { + Numeric::Float(Float::F16B) => unreachable!("Complex is not C-compatible"), + Numeric::Float(Float::F16) => unreachable!("not supported on mips64"), + Numeric::Float(Float::F32 | Float::F64) => { + // Only pass a Complex/Complex in FPRs when two argument slots are free. + if curr_offset.bytes() / slot.bytes() + 2 <= NUM_ARG_SLOTS { + // Both components claim a slot, even a Complex which could fit in one + // slot. + // + // FIXME(complex_numbers): c-variadic arguments are passed in GPRs, so need a + // special carve-out here and Complex is bitpacked into one 64-bit GPR. + *offset = curr_offset + slot * 2; + let unit = Reg { kind: RegKind::Float, size: component.size() }; + let cast_target = CastTarget::from(Uniform::new(unit, size)); + arg.cast_to(cast_target); + return; + } + + // Otherwise pack it into GPRs (or the stack) like an integer of the same size. + arg.cast_to_and_pad_i32(Uniform::new(Reg::i64(), size), pad_i32); + } + Numeric::Float(Float::F128) => { + // Complex is passed in 4 FPRs, but aligned to 16 so may need padding. + let reg = Reg { kind: RegKind::Float, size: arg.layout.field(cx, 0).size }; + arg.cast_to_and_pad_i32(CastTarget::pair(reg, reg), pad_i32); + } + Numeric::Int(Integer::I8 | Integer::I16 | Integer::I32, _) => { + // Cast Complex into i16, Complex to i32, etc. + let cast_target = CastTarget::from(Reg { kind: RegKind::Integer, size }); + // The inreg attribute makes the bits land in the right (upper) bits on BE targets. + arg.cast_to(cast_target.with_attrs(ArgAttribute::InReg.into())); + } + Numeric::Int(Integer::I64 | Integer::I128, _) => { + // Complex and Complex are passed as 2 separate arguments. + let cast_target = CastTarget::from(Reg { kind: RegKind::Integer, size }); + arg.cast_to(cast_target); + } + } } else { match arg.layout.fields { FieldsShape::Primitive => unreachable!(), diff --git a/tests/codegen-llvm/complex-abi.rs b/tests/codegen-llvm/complex-abi.rs index 3235627e9ca5f..c9e59f6f7eaa7 100644 --- a/tests/codegen-llvm/complex-abi.rs +++ b/tests/codegen-llvm/complex-abi.rs @@ -75,15 +75,21 @@ //@ [AIX] compile-flags: --target powerpc64-ibm-aix //@ [AIX] needs-llvm-components: powerpc +// NOTE: in clang <= 23 the Complex is passed incorrectly. +// See https://github.com/llvm/llvm-project/issues/212109. +//@ revisions: MIPS64 MIPS64EL +//@ [MIPS64] compile-flags: --target mips64-unknown-linux-gnuabi64 +//@ [MIPS64] needs-llvm-components: mips +//@ [MIPS64EL] compile-flags: --target mips64el-unknown-linux-gnuabi64 +//@ [MIPS64EL] needs-llvm-components: mips + // FIXME: the below revisions are deliberately disabled for now. // revisions: POWERPC // [POWERPC] compile-flags: --target powerpc-unknown-linux-gnu // [POWERPC] needs-llvm-components: powerpc -// revisions: MIPS64EL MIPS -// [MIPS64EL] compile-flags: --target mips64el-unknown-linux-gnuabi64 -// [MIPS64EL] needs-llvm-components: mips +// revisions: MIPS // [MIPS] compile-flags: --target mips-unknown-linux-gnu // [MIPS] needs-llvm-components: mips @@ -143,7 +149,8 @@ pub extern "C" fn cplx_f32(x: Complex) -> Complex { // I686: define{{.*}} i64 @cplx_f32(ptr {{.*}} byval([8 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} { float, float } @cplx_f32({ float, float } {{.*}}) // LOONGARCH64: define{{.*}} { float, float } @cplx_f32({ float, float } {{.*}}) - // MIPS64EL: define{{.*}} { float, float } @cplx_f32(float {{.*}}, float {{.*}}) + // MIPS64: define{{.*}} { float, float } @cplx_f32([2 x float] {{.*}}) + // MIPS64EL: define{{.*}} { float, float } @cplx_f32([2 x float] {{.*}}) // MIPS: define{{.*}} { float, float } @cplx_f32([2 x i32] {{.*}}) // NVPTX: define{{.*}} { float, float } @cplx_f32(ptr {{.*}} byval({ float, float }) {{.*}}) // POWERPC64: define{{.*}} { float, float } @cplx_f32({ float, float } %0) @@ -177,7 +184,8 @@ pub extern "C" fn cplx_f64(x: Complex) -> Complex { // I686: define{{.*}} void @cplx_f64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} { double, double } @cplx_f64({ double, double } {{.*}}) // LOONGARCH64: define{{.*}} { double, double } @cplx_f64({ double, double } {{.*}}) - // MIPS64EL: define{{.*}} { double, double } @cplx_f64(double {{.*}}, double {{.*}}) + // MIPS64: define{{.*}} { double, double } @cplx_f64([2 x double] {{.*}}) + // MIPS64EL: define{{.*}} { double, double } @cplx_f64([2 x double] {{.*}}) // MIPS: define{{.*}} { double, double } @cplx_f64(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}) // NVPTX: define{{.*}} { double, double } @cplx_f64(ptr {{.*}} byval({ double, double }) {{.*}}) // POWERPC64: define{{.*}} { double, double } @cplx_f64({ double, double } %0) @@ -202,6 +210,8 @@ pub extern "C" fn cplx_f64(x: Complex) -> Complex { pub extern "C" fn cplx_f128(x: Complex) -> Complex { // AARCH64: define{{.*}} [2 x fp128] {{.*}}) // I686: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}} byval([32 x i8]) {{.*}}) + // MIPS64: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, i32 %0, { fp128, fp128 } %1) + // MIPS64EL: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, i32 %0, { fp128, fp128 } %1) // SPARC: define{{.*}} inreg { fp128, fp128 } @cplx_f128(ptr {{.*}} dereferenceable(32) {{.*}}) // WASM32: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}}) // WASM64: define{{.*}} void @cplx_f128(ptr {{.*}} sret([32 x i8]) {{.*}}, ptr {{.*}}) @@ -226,7 +236,8 @@ pub extern "C" fn cplx_i8(x: Complex) -> Complex { // I686: define{{.*}} i16 @cplx_i8(ptr {{.*}} byval([2 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} i32 @cplx_i8(i32{{.*}}) // LOONGARCH64: define{{.*}} i64 @cplx_i8(i64{{.*}}) - // MIPS64EL: define{{.*}} { i8, i8 } @cplx_i8(i16 {{.*}}) + // MIPS64: define{{.*}} i16 @cplx_i8(i16 inreg {{.*}}) + // MIPS64EL: define{{.*}} i16 @cplx_i8(i16 inreg {{.*}}) // MIPS: define{{.*}} { i8, i8 } @cplx_i8(i16 {{.*}}) // NVPTX: define{{.*}} { i8, i8 } @cplx_i8(ptr {{.*}} byval({ i8, i8 }) {{.*}}) // POWERPC64: define{{.*}} { i8, i8 } @cplx_i8({ i8, i8 } %0) @@ -260,7 +271,8 @@ pub extern "C" fn cplx_i16(x: Complex) -> Complex { // I686: define{{.*}} i32 @cplx_i16(ptr {{.*}} byval([4 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} i32 @cplx_i16(i32 {{.*}}) // LOONGARCH64: define{{.*}} i64 @cplx_i16(i64{{.*}}) - // MIPS64EL: define{{.*}} { i16, i16 } @cplx_i16(i32 {{.*}}) + // MIPS64: define{{.*}} i32 @cplx_i16(i32 inreg {{.*}}) + // MIPS64EL: define{{.*}} i32 @cplx_i16(i32 inreg {{.*}}) // MIPS: define{{.*}} { i16, i16 } @cplx_i16(i32 {{.*}}) // NVPTX: define{{.*}} { i16, i16 } @cplx_i16(ptr {{.*}} byval({ i16, i16 }) {{.*}}) // POWERPC64: define{{.*}} { i16, i16 } @cplx_i16(i16 {{.*}}, i16 {{.*}}) @@ -294,7 +306,8 @@ pub extern "C" fn cplx_i32(x: Complex) -> Complex { // I686: define{{.*}} i64 @cplx_i32(ptr {{.*}} byval([8 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} [2 x i32] @cplx_i32([2 x i32] {{.*}}) // LOONGARCH64: define{{.*}} i64 @cplx_i32(i64 {{.*}}) - // MIPS64EL: define{{.*}} { i32, i32 } @cplx_i32(i64 {{.*}}) + // MIPS64: define{{.*}} i64 @cplx_i32(i64 inreg {{.*}}) + // MIPS64EL: define{{.*}} i64 @cplx_i32(i64 inreg {{.*}}) // MIPS: define{{.*}} { i32, i32 } @cplx_i32(i32 {{.*}}, i32 {{.*}}) // NVPTX: define{{.*}} { i32, i32 } @cplx_i32(ptr {{.*}} byval({ i32, i32 }) {{.*}}) // POWERPC64: define{{.*}} { i32, i32 } @cplx_i32({ i32, i32 } %0) @@ -328,7 +341,8 @@ pub extern "C" fn cplx_i64(x: Complex) -> Complex { // I686: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} void @cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // LOONGARCH64: define{{.*}} [2 x i64] @cplx_i64([2 x i64] {{.*}}) - // MIPS64EL: define{{.*}} { i64, i64 } @cplx_i64(i64 {{.*}}, i64 {{.*}}) + // MIPS64: define{{.*}} { i64, i64 } @cplx_i64(i128 {{.*}}) + // MIPS64EL: define{{.*}} { i64, i64 } @cplx_i64(i128 {{.*}}) // MIPS: define{{.*}} { i64, i64 } @cplx_i64(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}) // NVPTX: define{{.*}} { i64, i64 } @cplx_i64(ptr {{.*}} byval({ i64, i64 }) {{.*}}) // POWERPC64: define{{.*}} { i64, i64 } @cplx_i64({ i64, i64 } %0) @@ -367,7 +381,8 @@ pub extern "C" fn wrapper_cplx_i64( // I686: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}} byval([16 x i8]) {{.*}}) // LOONGARCH32: define{{.*}} void @wrapper_cplx_i64(ptr {{.*}} sret([16 x i8]) {{.*}}, ptr {{.*}}) // LOONGARCH64: define{{.*}} [2 x i64] @wrapper_cplx_i64([2 x i64] {{.*}}) - // MIPS64EL: define{{.*}} { i64, i64 } @wrapper_cplx_i64(i64 {{.*}}, i64 {{.*}}) + // MIPS64: define{{.*}} { i64, i64 } @wrapper_cplx_i64(i128 {{.*}}) + // MIPS64EL: define{{.*}} { i64, i64 } @wrapper_cplx_i64(i128 {{.*}}) // MIPS: define{{.*}} { i64, i64 } @wrapper_cplx_i64(i32 {{.*}}, i32 {{.*}}, i32 {{.*}}, i32 {{.*}}) // NVPTX: define{{.*}} { i64, i64 } @wrapper_cplx_i64(ptr {{.*}} byval({ i64, i64 }) {{.*}}) // POWERPC64: define{{.*}} { i64, i64 } @wrapper_cplx_i64({ i64, i64 } %0) From 7e835caa1e824ca5c6d13c27607bb7a2b5e4020a Mon Sep 17 00:00:00 2001 From: Shrey Shah Date: Tue, 29 Sep 2026 16:10:37 -0700 Subject: [PATCH 1088/1309] `items_after_test_module`: don't let derive expansions hide trailing items Items generated by a derive after a test module made the lint bail out, so a derived type placed after `mod tests` was never reported. Skip derive expansions and check the item the derive is attached to instead. --- clippy_lints/src/items_after_test_module.rs | 2 + .../after_derive.fixed | 82 +++++++++++++++++++ .../items_after_test_module/after_derive.rs | 82 +++++++++++++++++++ .../after_derive.stderr | 40 +++++++++ 4 files changed, 206 insertions(+) create mode 100644 tests/ui/items_after_test_module/after_derive.fixed create mode 100644 tests/ui/items_after_test_module/after_derive.rs create mode 100644 tests/ui/items_after_test_module/after_derive.stderr diff --git a/clippy_lints/src/items_after_test_module.rs b/clippy_lints/src/items_after_test_module.rs index 9cd71c62eb32a..3023141a852b7 100644 --- a/clippy_lints/src/items_after_test_module.rs +++ b/clippy_lints/src/items_after_test_module.rs @@ -75,6 +75,8 @@ impl LateLintPass<'_> for ItemsAfterTestModule { true } }) + // Ignore items generated by derive macros, we only check items present in the source code + .filter(|item| !item.span.in_derive_expansion()) .collect(); if let Some(last) = after.last() diff --git a/tests/ui/items_after_test_module/after_derive.fixed b/tests/ui/items_after_test_module/after_derive.fixed new file mode 100644 index 0000000000000..8c87cacf91b55 --- /dev/null +++ b/tests/ui/items_after_test_module/after_derive.fixed @@ -0,0 +1,82 @@ +//@aux-build:../auxiliary/proc_macro_derive.rs +#![warn(clippy::items_after_test_module)] + +extern crate proc_macro_derive; + +fn main() {} + +mod derive_after { + fn should_not_lint() {} + + #[derive(Debug, Clone, PartialEq)] + struct ShouldLint; + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } +} + +mod derive_and_fn_after { + fn should_not_lint() {} + + #[derive(Debug)] + struct ShouldLint; + + fn should_also_lint() {} + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } +} + +mod proc_macro_derive_after { + fn should_not_lint() {} + + #[derive(proc_macro_derive::DeriveSomething)] + struct ShouldLint; + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } +} + +mod derive_before { + #[derive(Debug, Clone)] + struct ShouldNotLint; + + #[cfg(test)] + mod tests { + #[test] + fn f() {} + } +} + +mod derive_and_macro_after { + macro_rules! item { + () => { + fn generated() {} + }; + } + + fn should_not_lint() {} + + #[cfg(test)] + mod tests { + #[test] + fn f() {} + } + + #[derive(Debug)] + struct ShouldNotLint; + + item!(); +} diff --git a/tests/ui/items_after_test_module/after_derive.rs b/tests/ui/items_after_test_module/after_derive.rs new file mode 100644 index 0000000000000..955908fecf73a --- /dev/null +++ b/tests/ui/items_after_test_module/after_derive.rs @@ -0,0 +1,82 @@ +//@aux-build:../auxiliary/proc_macro_derive.rs +#![warn(clippy::items_after_test_module)] + +extern crate proc_macro_derive; + +fn main() {} + +mod derive_after { + fn should_not_lint() {} + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } + + #[derive(Debug, Clone, PartialEq)] + struct ShouldLint; +} + +mod derive_and_fn_after { + fn should_not_lint() {} + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } + + #[derive(Debug)] + struct ShouldLint; + + fn should_also_lint() {} +} + +mod proc_macro_derive_after { + fn should_not_lint() {} + + #[cfg(test)] + mod tests { + //~^ items_after_test_module + #[test] + fn f() {} + } + + #[derive(proc_macro_derive::DeriveSomething)] + struct ShouldLint; +} + +mod derive_before { + #[derive(Debug, Clone)] + struct ShouldNotLint; + + #[cfg(test)] + mod tests { + #[test] + fn f() {} + } +} + +mod derive_and_macro_after { + macro_rules! item { + () => { + fn generated() {} + }; + } + + fn should_not_lint() {} + + #[cfg(test)] + mod tests { + #[test] + fn f() {} + } + + #[derive(Debug)] + struct ShouldNotLint; + + item!(); +} diff --git a/tests/ui/items_after_test_module/after_derive.stderr b/tests/ui/items_after_test_module/after_derive.stderr new file mode 100644 index 0000000000000..233c2a294910f --- /dev/null +++ b/tests/ui/items_after_test_module/after_derive.stderr @@ -0,0 +1,40 @@ +error: items after a test module + --> tests/ui/items_after_test_module/after_derive.rs:12:5 + | +LL | mod tests { + | ^^^^^^^^^ +... +LL | struct ShouldLint; + | ^^^^^^^^^^^^^^^^^ + | + = note: `-D clippy::items-after-test-module` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::items_after_test_module)]` + = help: move the items to before the test module was defined + +error: items after a test module + --> tests/ui/items_after_test_module/after_derive.rs:26:5 + | +LL | mod tests { + | ^^^^^^^^^ +... +LL | struct ShouldLint; + | ^^^^^^^^^^^^^^^^^ +LL | +LL | fn should_also_lint() {} + | ^^^^^^^^^^^^^^^^^^^^^ + | + = help: move the items to before the test module was defined + +error: items after a test module + --> tests/ui/items_after_test_module/after_derive.rs:42:5 + | +LL | mod tests { + | ^^^^^^^^^ +... +LL | struct ShouldLint; + | ^^^^^^^^^^^^^^^^^ + | + = help: move the items to before the test module was defined + +error: aborting due to 3 previous errors + From f25f4eb4cc94675eec2636bc0cf5bd9c2347a5b3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:22:33 +0200 Subject: [PATCH 1089/1309] sembr src/const-generics.md --- src/doc/rustc-dev-guide/src/const-generics.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index 349e9de9da120..d327ad150f330 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -27,7 +27,8 @@ struct Foo; type Alias = [u8; 1 + 1]; ``` -In this example we have a const argument of `1 + 1` (the array length) which is represented as an *anon const*. The desugaring would look something like: +In this example we have a const argument of `1 + 1` (the array length) which is represented as an *anon const*. +The desugaring would look something like: ```rust struct Foo; From dd00fa81f72e740f746e0331c32534511b711c06 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:24:22 +0200 Subject: [PATCH 1090/1309] manual sembr --- src/doc/rustc-dev-guide/src/const-generics.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index d327ad150f330..a5c7ec506be4c 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -82,9 +82,11 @@ type Alias = [u8; ANON]; When we go through HIR ty lowering for the array type in `Alias`, we will lower the array length too, and feed `type_of(ANON) -> usize`. This will effectively set the type of the `ANON` const item during some later part of the compiler rather than when constructing the HIR. -After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Alias` with the `DefId` of the `AnonConst`. This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `gca_min_const_items` is enabled). +After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Alias` with the `DefId` of the `AnonConst`. +This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `gca_generic_const_args` is enabled). -This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. +This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. +Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. ### Enforcing lack of generic parameters From 25a59cb72b49469d8bfd3150ffdb6b2e3de63d8c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:28:21 +0200 Subject: [PATCH 1091/1309] sometimes shortens lines, for looks --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 359deab6f6d7d..052036bb87f32 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -50,12 +50,12 @@ fn main() -> Result<()> { let old = fs::read_to_string(&path)?; let mut new = comply(&old); if cli.reflow_harder { - new = lengthen_lines(&new, cli.line_length_limit) + new = reformat_lines(&new, cli.line_length_limit) } if new == old { compliant.push(path.clone()); } else if cli.overwrite { - fs::write(&path, lengthen_lines(&new, cli.line_length_limit))?; + fs::write(&path, reformat_lines(&new, cli.line_length_limit))?; made_compliant.push(path.clone()); } else { not_compliant.push(path.clone()); @@ -133,7 +133,8 @@ fn comply(content: &str) -> String { new_content.join("\n") + "\n" } -fn lengthen_lines(content: &str, limit: usize) -> String { +// This reformats lines, so that changes of "fn comply" look more pretty +fn reformat_lines(content: &str, limit: usize) -> String { let content: Vec<_> = content.lines().map(std::borrow::ToOwned::to_owned).collect(); let mut new_content = content.clone(); let mut new_n = 0; @@ -277,7 +278,7 @@ r? @reviewer } #[test] -fn test_lengthen_lines() { +fn test_reformat_lines() { let original = "\ do not split short sentences @@ -342,7 +343,7 @@ html comment closing [a target]: https://example.com [another target]: https://example.com "; - assert_eq!(expected, lengthen_lines(original, 50)); + assert_eq!(expected, reformat_lines(original, 50)); } #[test] @@ -368,7 +369,7 @@ which could themselves be either base or derived. Each derived value has a dependency, on other values, which could themselves be either base or derived. "; - assert_eq!(expected, lengthen_lines(original, 100)) + assert_eq!(expected, reformat_lines(original, 100)) } #[test] @@ -387,7 +388,7 @@ encountering a cycle doesn't mean that we would get an infinite proof tree. Because of canonicalization of regions and inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. "; - assert_eq!(expected, lengthen_lines(original, 100)) + assert_eq!(expected, reformat_lines(original, 100)) } #[test] From 07ee9e01914150f5b81e9868fb3d63ffd2b6ee34 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:29:08 +0200 Subject: [PATCH 1092/1309] reflow src/building/bootstrapping/what-bootstrapping-does.md --- .../src/building/bootstrapping/what-bootstrapping-does.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md index 4572d001f12d3..fda9f29ae3ca9 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md @@ -15,8 +15,8 @@ See [bootstrap/README.md][bootstrap-internals] to read about bootstrap internals - Stage 3: the same-result test Compiling `rustc` is done in stages. -Here's a diagram, adapted from Jynn -Nelson's [talk on bootstrapping][rustconf22-talk] at RustConf 2022, +Here's a diagram, +adapted from Jynn Nelson's [talk on bootstrapping][rustconf22-talk] at RustConf 2022, with detailed explanations below. The `A`, `B`, `C`, and `D` show the ordering of the stages of bootstrapping. @@ -300,8 +300,8 @@ but `lib` will never be part of the search path. Since `lib/rustlib/` is part of the search path we have to be careful about which crates are included in it. -In particular, all crates except for the -standard library are built with the flag `-Z force-unstable-if-unmarked`, +In particular, +all crates except for the standard library are built with the flag `-Z force-unstable-if-unmarked`, which means that you have to use `#![feature(rustc_private)]` in order to load it (as opposed to the standard library, which is always available). From d3bfa9af7d334504301ea2941e07b8664cf08750 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 11:33:11 +0200 Subject: [PATCH 1093/1309] improve building/bootstrapping/what-bootstrapping-does.md --- .../bootstrapping/what-bootstrapping-does.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md index fda9f29ae3ca9..4fe42ebffd574 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md @@ -298,12 +298,12 @@ but `lib` will never be part of the search path. #### `-Z force-unstable-if-unmarked` -Since `lib/rustlib/` is part of the search path we have to be careful about -which crates are included in it. -In particular, -all crates except for the standard library are built with the flag `-Z force-unstable-if-unmarked`, -which means that you have to use `#![feature(rustc_private)]` in order to load it (as -opposed to the standard library, which is always available). +Since `lib/rustlib/` is part of the search path, +we have to be careful about which crates are included in it. +In particular, all crates, except for the standard library, +are built with the flag `-Z force-unstable-if-unmarked`, +meaning that you have to use `#![feature(rustc_private)]` in order to load it +(as opposed to the standard library, which is always available). The `-Z force-unstable-if-unmarked` flag has a variety of purposes to help enforce that the correct crates are marked as `unstable`. From bb523e8c4c51409742af9d6037cc157bab6ee7e6 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 12:02:06 +0200 Subject: [PATCH 1094/1309] make it one big test --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 76 ++++++++------------ 1 file changed, 30 insertions(+), 46 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 052036bb87f32..5ee0c3af1b4d6 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -240,6 +240,8 @@ o? whatever r? @reviewer r? @reviewer ~? diagnostic + +the queries that we do, as well as the **query DAG**. The "; let expected = " # some. heading @@ -273,6 +275,9 @@ whatever r? @reviewer r? @reviewer ~? diagnostic + +the queries that we do, as well as the **query DAG**. +The "; assert_eq!(expected, comply(original)); } @@ -309,6 +314,18 @@ html comment closing handle the indented well +split on comma (filler), of +current line + + split on comma (filler), of + current line + +split on +comma (filler), of next line + + split on + comma (filler), of next line + [a target]: https://example.com [another target]: https://example.com "; @@ -340,10 +357,22 @@ html comment closing handle the indented well +split on comma (filler), +of current line + + split on comma (filler), + of current line + +split on comma (filler), +of next line + + split on comma (filler), + of next line + [a target]: https://example.com [another target]: https://example.com "; - assert_eq!(expected, reformat_lines(original, 50)); + assert_eq!(expected, reformat_lines(original, 30)); } #[test] @@ -352,48 +381,3 @@ fn should_pass() { let original = "if you see `input isn't interesting! verify interesting-ness test`."; assert_eq!(original, comply(original)); } - -#[test] -fn split_on_comma_of_current_line() { - let original = " -Each derived value has a dependency, on other values, which could themselves be either base or -derived. - - Each derived value has a dependency, on other values, which could themselves be either base or - derived. -"; - let expected = " -Each derived value has a dependency, on other values, -which could themselves be either base or derived. - - Each derived value has a dependency, on other values, - which could themselves be either base or derived. -"; - assert_eq!(expected, reformat_lines(original, 100)) -} - -#[test] -fn split_on_comma_of_next_line() { - let original = " -Because of canonicalization of regions and -inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. - - Because of canonicalization of regions and - inference variables, encountering a cycle doesn't mean that we would get an infinite proof tree. -"; - let expected = " -Because of canonicalization of regions and inference variables, -encountering a cycle doesn't mean that we would get an infinite proof tree. - - Because of canonicalization of regions and inference variables, - encountering a cycle doesn't mean that we would get an infinite proof tree. -"; - assert_eq!(expected, reformat_lines(original, 100)) -} - -#[test] -fn should_split() { - let original = "the queries that we do, as well as the **query DAG**. The"; - let expected = "the queries that we do, as well as the **query DAG**.\nThe\n"; - assert_eq!(expected, comply(original)); -} From af57095aaaae2911a52d283c8af94e3579cdad20 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 12:02:53 +0200 Subject: [PATCH 1095/1309] shorten, to match the other fn, "comply" --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 5ee0c3af1b4d6..54c716959e154 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -50,12 +50,12 @@ fn main() -> Result<()> { let old = fs::read_to_string(&path)?; let mut new = comply(&old); if cli.reflow_harder { - new = reformat_lines(&new, cli.line_length_limit) + new = reformat(&new, cli.line_length_limit) } if new == old { compliant.push(path.clone()); } else if cli.overwrite { - fs::write(&path, reformat_lines(&new, cli.line_length_limit))?; + fs::write(&path, reformat(&new, cli.line_length_limit))?; made_compliant.push(path.clone()); } else { not_compliant.push(path.clone()); @@ -134,7 +134,7 @@ fn comply(content: &str) -> String { } // This reformats lines, so that changes of "fn comply" look more pretty -fn reformat_lines(content: &str, limit: usize) -> String { +fn reformat(content: &str, limit: usize) -> String { let content: Vec<_> = content.lines().map(std::borrow::ToOwned::to_owned).collect(); let mut new_content = content.clone(); let mut new_n = 0; @@ -372,7 +372,7 @@ of next line [a target]: https://example.com [another target]: https://example.com "; - assert_eq!(expected, reformat_lines(original, 30)); + assert_eq!(expected, reformat(original, 30)); } #[test] From 788454540d39e313eb6daf063b6feb45b693c4b1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 18:42:42 +0200 Subject: [PATCH 1096/1309] sembr src/diagnostics.md --- src/doc/rustc-dev-guide/src/diagnostics.md | 197 ++++++++++----------- 1 file changed, 98 insertions(+), 99 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index 0928f27940885..b807c7b381b5d 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -41,15 +41,15 @@ LL | more code - Primary and secondary spans underlying the users' code. These spans can optionally contain one or more labels. - Primary spans should have enough text to describe the problem in such a - way that if it were the only thing being displayed (for example, in an - IDE) it would still make sense. - Because it is "spatially aware" (it - points at the code), it can generally be more succinct than the error message. - - If cluttered output can be foreseen in cases when multiple span labels - overlap, it is a good idea to tweak the output appropriately. + way that if it were the only thing being displayed (for example, + in an IDE) it would still make sense. + Because it is "spatially aware" (it points at the code), + it can generally be more succinct than the error message. + - If cluttered output can be foreseen in cases when multiple span labels overlap, + it is a good idea to tweak the output appropriately. For example, the `if/else arms have incompatible types` error uses different - spans depending on whether the arms are all in the same line, if one of - the arms is empty and if none of those cases applies. + spans depending on whether the arms are all in the same line, + if one of the arms is empty and if none of those cases applies. - Sub-diagnostics. Any error can have multiple sub-diagnostics that look similar to the main part of the error. These are used for cases where the @@ -57,15 +57,15 @@ LL | more code If the order of the explanation can be "order free", leveraging secondary labels in the main diagnostic is preferred, as it is typically less verbose. -The text should be matter of fact and avoid capitalization and periods, unless -multiple sentences are _needed_: +The text should be matter of fact and avoid capitalization and periods, +unless multiple sentences are _needed_: ```txt error: the fobrulator needs to be krontrificated ``` -When code or an identifier must appear in a message or label, it should be -surrounded with backticks: +When code or an identifier must appear in a message or label, +it should be surrounded with backticks: ```txt error: the identifier `foo.bar` is invalid @@ -84,12 +84,12 @@ explanation would give more information than the error itself. A lot of the time it's better to put all the information in the emitted error itself. However, sometimes that would make the error verbose or there are too many possible -triggers to include useful information for all cases in the error, in which case -it's a good idea to add an explanation.[^estebank] +triggers to include useful information for all cases in the error, +in which case it's a good idea to add an explanation.[^estebank] As always, if you are not sure, just ask your reviewer! -If you decide to add a new error with an associated error code, please read -[this section][error-codes] for a guide and important details about the process. +If you decide to add a new error with an associated error code, +please read [this section][error-codes] for a guide and important details about the process. [^estebank]: This rule of thumb was suggested by **@estebank** [here][estebank-comment]. @@ -102,23 +102,23 @@ If you decide to add a new error with an associated error code, please read Some messages are emitted via [lints](#lints), where the user can control the level. Most diagnostics are hard-coded such that the user cannot control the level. -Usually it is obvious whether a diagnostic should be "fixed" or a lint, but -there are some grey areas. +Usually it is obvious whether a diagnostic should be "fixed" or a lint, +but there are some grey areas. Here are a few examples: - Borrow checker errors: these are fixed errors. The user cannot adjust the level of these diagnostics to silence the borrow checker. - Dead code: this is a lint. - While the user probably doesn't want dead code in - their crate, making this a hard error would make refactoring and development very painful. + While the user probably doesn't want dead code in their crate, + making this a hard error would make refactoring and development very painful. - [future-incompatible lints]: these are silenceable lints. It was decided that making them fixed errors would cause too much breakage, so warnings are instead emitted, and will eventually be turned into fixed (hard) errors. -Hard-coded warnings (those using methods like `span_warn`) should be avoided -for normal code, preferring to use lints instead. +Hard-coded warnings (those using methods like `span_warn`) should be avoided for normal code, +preferring to use lints instead. Some cases, such as warnings with CLI flags, will require the use of hard-coded warnings. See the `deny` [lint level](#diagnostic-levels) below for guidelines when to @@ -133,11 +133,11 @@ use an error-level lint instead of a fixed error. small – screen (which hasn't been cleaned for a while), cannot be understood by a normal programmer, who just came out of bed after a night partying, it's too complex. -- `Error`, `Warning`, `Note`, and `Help` messages start with a lowercase - letter and do not end with punctuation. +- `Error`, `Warning`, `Note`, + and `Help` messages start with a lowercase letter and do not end with punctuation. - Error messages should be succinct. - Users will see these error messages many - times, and more verbose descriptions can be viewed with the `--explain` flag. + Users will see these error messages many times, + and more verbose descriptions can be viewed with the `--explain` flag. That said, don't make it so terse that it's hard to understand. - The word "illegal" is illegal. Prefer "invalid" or a more specific word instead. @@ -145,8 +145,8 @@ use an error-level lint instead of a fixed error. [`rustc_errors::DiagCtxt`][DiagCtxt]'s `span_*` methods or a diagnostic struct's `#[primary_span]` to easily do this). Also `note` other spans that have contributed to the error if the span isn't too large. -- When emitting a message with span, try to reduce the span to the smallest - amount possible that still signifies the issue +- When emitting a message with span, + try to reduce the span to the smallest amount possible that still signifies the issue - Try not to emit multiple error messages for the same error. This may require detecting duplicates. - When the compiler has too little information for a specific error message, @@ -154,8 +154,8 @@ use an error-level lint instead of a fixed error. allow adding more information. For example, see [`#[rustc_on_unimplemented]`](#rustc_on_unimplemented). Use these annotations when available! -- Keep in mind that Rust's learning curve is rather steep, and that the - compiler messages are an important learning tool. +- Keep in mind that Rust's learning curve is rather steep, + and that the compiler messages are an important learning tool. - When talking about the compiler, call it `the compiler`, not `Rust` or `rustc`. - Use the [Oxford comma](https://en.wikipedia.org/wiki/Serial_comma) when writing lists of items. - When mentioning attributes, use this form whenever possible: "the `inline` attribute". @@ -168,8 +168,8 @@ From [RFC 0344], lint names should be consistent, with the following guidelines: The basic rule is: the lint name should make sense when read as "allow *lint-name*" or "allow *lint-name* items". -For example, "allow `deprecated` items" and "allow `dead_code`" makes sense, while "allow -`unsafe_block`" is ungrammatical (should be plural). +For example, "allow `deprecated` items" and "allow `dead_code`" makes sense, +while "allow `unsafe_block`" is ungrammatical (should be plural). - Lint names should state the bad thing being checked for, e.g. `deprecated`, so that `#[allow(deprecated)]` (items) reads correctly. @@ -180,8 +180,8 @@ For example, "allow `deprecated` items" and "allow `dead_code`" makes sense, whi This keeps lint names short. (Again, think "allow *lint-name* items".) -- If a lint applies to a specific grammatical class, mention that class and - use the plural form: use `unused_variables` rather than `unused_variable`. +- If a lint applies to a specific grammatical class, + mention that class and use the plural form: use `unused_variables` rather than `unused_variable`. This makes `#[allow(unused_variables)]` read correctly. - Lints that catch unnecessary, unused, or useless aspects of code should use @@ -200,12 +200,12 @@ Guidelines for different diagnostic levels: has decided to make a specific `warning` into an error. - `warning`: emitted when the compiler detects something odd about a program. - Care should be taken when adding warnings to avoid warning fatigue, and - avoid false-positives where there really isn't a problem with the code. + Care should be taken when adding warnings to avoid warning fatigue, + and avoid false-positives where there really isn't a problem with the code. Some examples of when it is appropriate to issue a warning: - - A situation where the user *should* take action, such as swap out a - deprecated item, or use a `Result`, but otherwise doesn't prevent compilation. + - A situation where the user *should* take action, such as swap out a deprecated item, + or use a `Result`, but otherwise doesn't prevent compilation. - Unnecessary syntax that can be removed without affecting the semantics of the code. For example, unused code, or unnecessary `unsafe`. - Code that is very likely to be incorrect, dangerous, or confusing, but the @@ -214,13 +214,13 @@ Guidelines for different diagnostic levels: `bindings_with_variant_name` (the user likely did not intend to create a binding in a pattern). - [Future-incompatible lints](#future-incompatible), where something was - accidentally or erroneously accepted in the past, but rejecting would - cause excessive breakage in the ecosystem. + accidentally or erroneously accepted in the past, + but rejecting would cause excessive breakage in the ecosystem. - Stylistic choices. For example, camel or snake case, or the `dyn` trait warning in the 2018 edition. These have a high bar to be added, and should only be used in exceptional circumstances. - Other stylistic choices should - either be allow-by-default lints, or part of other tools like Clippy or rustfmt. + Other stylistic choices should either be allow-by-default lints, + or part of other tools like Clippy or rustfmt. - `help`: emitted following an `error` or `warning` to give additional information to the user about how to solve their problem. @@ -247,8 +247,8 @@ Not to be confused with *lint levels*, whose guidelines are: Some examples: - A future-incompatible or edition-based lint that has graduated from the warning level. - - Something that has an extremely high confidence that is incorrect, but - still want an escape hatch to allow it to pass. + - Something that has an extremely high confidence that is incorrect, + but still want an escape hatch to allow it to pass. - `warn`: Equivalent to the `warning` diagnostic level. See `warning` above for guidelines. @@ -279,8 +279,8 @@ There are three main ways to find where a given error is emitted: constructed behind a relatively deep call-stack. Even then, it is a good way to get your bearings. - Invoking `rustc` with the nightly-only flag `-Z treat-err-as-bug=1` - will treat the first error being emitted as an Internal Compiler Error, which - allows you to get a stack trace at the point the error has been emitted. + will treat the first error being emitted as an Internal Compiler Error, + which allows you to get a stack trace at the point the error has been emitted. Change the `1` to something else if you wish to trigger on a later error. There are limitations with this approach: @@ -299,8 +299,8 @@ order things are happening. [`Span`][span] is the primary data structure in `rustc` used to represent a location in the code being compiled. -`Span`s are attached to most constructs in -HIR and MIR, allowing for more informative error reporting. +`Span`s are attached to most constructs in HIR and MIR, +allowing for more informative error reporting. [span]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html @@ -320,8 +320,8 @@ The [`rustc_errors`][errors] crate defines most of the utilities used for report Diagnostics can be implemented as types which implement the `Diagnostic` trait. This is preferred for new diagnostics as it enforces a separation between diagnostic emitting logic and the main code paths. -For less-complex diagnostics, the `Diagnostic` trait can be derived -- see [Diagnostic -structs][diagnostic-structs]. +For less-complex diagnostics, +the `Diagnostic` trait can be derived -- see [Diagnostic structs][diagnostic-structs]. Within the trait implementation, the APIs described below can be used as normal. [diagnostic-structs]: ./diagnostics/diagnostic-structs.md @@ -337,12 +337,11 @@ warnings, errors, fatal errors, suggestions, etc. In general, there are two classes of such methods: ones that emit an error directly and ones that allow finer control over what to emit. For example, -[`span_err`][spanerr] emits the given error message at the given `Span`, but -[`struct_span_err`][strspanerr] instead returns a [`Diag`][diag]. +[`span_err`][spanerr] emits the given error message at the given `Span`, +but [`struct_span_err`][strspanerr] instead returns a [`Diag`][diag]. Most of these methods will accept strings, but it is recommended that typed -identifiers for translatable diagnostics be used for new diagnostics (see -[Translation]). +identifiers for translatable diagnostics be used for new diagnostics (see [Translation]). [translation]: ./diagnostics/translation.md @@ -385,8 +384,8 @@ example-example-error = oh no! this is an error! ## Suggestions -In addition to telling the user exactly _why_ their code is wrong, it's -oftentimes furthermore possible to tell them how to fix it. +In addition to telling the user exactly _why_ their code is wrong, +it's oftentimes furthermore possible to tell them how to fix it. To this end, [`Diag`][diag] offers a structured suggestions API, which formats code suggestions pleasingly in the terminal, or (when the `--error-format json` flag @@ -398,8 +397,7 @@ Not all suggestions should be applied mechanically; they have a degree of confidence in the suggested code, from high (`Applicability::MachineApplicable`) to low (`Applicability::MaybeIncorrect`). Be conservative when choosing the level. -Use the [`span_suggestion`][span_suggestion] method of `Diag` to -make a suggestion. +Use the [`span_suggestion`][span_suggestion] method of `Diag` to make a suggestion. The last argument provides a hint to tools whether the suggestion is mechanically applicable or not. Suggestions point to one or more spans with corresponding code that will @@ -515,8 +513,8 @@ Some of the passes are: - Example: [`keyword_idents`] checks for identifiers that will become keywords in future editions, but is sensitive to identifiers used in macros. -- Early lint pass: Works on [AST nodes] after [macro expansion] and name - resolution, just before [AST lowering]. +- Early lint pass: Works on [AST nodes] after [macro expansion] and name resolution, + just before [AST lowering]. These lints are for purely syntactical lints. - Example: The [`unused_parens`] lint checks for parenthesized-expressions in situations where they are not needed, like an `if` condition. @@ -534,11 +532,11 @@ Some of the passes are: - Example: The [`arithmetic_overflow`] lint is emitted when it detects a constant value that may overflow. -Most lints work well via the pass systems, and they have a fairly -straightforward interface and easy way to integrate (mostly just implementing +Most lints work well via the pass systems, +and they have a fairly straightforward interface and easy way to integrate (mostly just implementing a specific `check` function). -However, some lints are easier to write when -they live on a specific code path anywhere in the compiler. +However, +some lints are easier to write when they live on a specific code path anywhere in the compiler. For example, the [`unused_mut`] lint is implemented in the borrow checker as it requires some information and state in the borrow checker. @@ -589,8 +587,8 @@ One benefit is that it is close to the dependency root, so it can be much faster [`rustc_lint_defs`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_lint_defs/index.html Every lint is implemented via a `struct` that implements the `LintPass` `trait` -(you can also implement one of the more specific lint pass traits, either -`EarlyLintPass` or `LateLintPass` depending on when is best for your lint to run). +(you can also implement one of the more specific lint pass traits, +either `EarlyLintPass` or `LateLintPass` depending on when is best for your lint to run). The trait implementation allows you to check certain syntactic constructs as the linter walks the AST. You can then choose to emit lints in a very similar way to compile errors. @@ -711,10 +709,11 @@ In general, future-incompatible code exists for two reasons: * The user has written unsound code that the compiler mistakenly accepted. While it is within Rust's backwards compatibility guarantees to fix the soundness hole (breaking the user's code), the lint is there to warn the user that this will happen -in some upcoming version of rustc *regardless of which edition the code uses*. This is the -meaning that rustc exclusively exposes to users as "future incompatible". +in some upcoming version of rustc *regardless of which edition the code uses*. +This is the meaning that rustc exclusively exposes to users as "future incompatible". * The user has written code that will either no longer compiler *or* will change -meaning in an upcoming *edition*. These are often called "edition lints" and can be +meaning in an upcoming *edition*. +These are often called "edition lints" and can be typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`) that are used to lint against code that will break if the user updates the crate's edition. See [migration lints](guides/editions.md#migration-lints) for more details. @@ -735,8 +734,8 @@ declare_lint! { Notice the `reason` field which describes why the future incompatible change is happening. This will change the diagnostic message the user receives as well as determine which lint groups the lint is added to. -In the example above, the lint is an "edition lint" -(since its "reason" is `EditionError`), signifying to the user that the use of anonymous +In the example above, the lint is an "edition lint" (since its "reason" is `EditionError`), +signifying to the user that the use of anonymous parameters will no longer compile in Rust 2018 and beyond. Inside [LintStore::register_lints][fi-lint-groupings], lints with `future_incompatible` @@ -745,16 +744,16 @@ an edition) or into the `future_incompatibility` lint group. [fi-lint-groupings]: https://github.com/rust-lang/rust/blob/51fd129ac12d5bfeca7d216c47b0e337bf13e0c2/compiler/rustc_lint/src/context.rs#L212-L237 -If you need a combination of options that's not supported by the -`declare_lint!` macro, you can always change the `declare_lint!` macro to support this. +If you need a combination of options that's not supported by the `declare_lint!` macro, +you can always change the `declare_lint!` macro to support this. ### Renaming or removing a lint If it is determined that a lint is either improperly named or no longer needed, -the lint must be registered for renaming or removal, which will trigger a warning if a user tries -to use the old lint name. -To declare a rename/remove, add a line with -[`store.register_renamed`] or [`store.register_removed`] to the code of the +the lint must be registered for renaming or removal, +which will trigger a warning if a user tries to use the old lint name. +To declare a rename/remove, +add a line with [`store.register_renamed`] or [`store.register_removed`] to the code of the [`rustc_lint::register_builtins`] function. ```rust,ignore @@ -785,15 +784,15 @@ add_lint_group!(sess, ``` This defines the `nonstandard_style` group which turns on the listed lints. -A user can turn on these lints with a `#![warn(nonstandard_style)]` attribute in -the source code, or by passing `-W nonstandard-style` on the command line. +A user can turn on these lints with a `#![warn(nonstandard_style)]` attribute in the source code, +or by passing `-W nonstandard-style` on the command line. Some lint groups are created automatically in `LintStore::register_lints`. For instance, any lint declared with `FutureIncompatibleInfo` where the reason is `FutureIncompatibilityReason::FutureReleaseError` (the default when -`@future_incompatible` is used in `declare_lint!`), will be added to -the `future_incompatible` lint group. +`@future_incompatible` is used in `declare_lint!`), +will be added to the `future_incompatible` lint group. Editions also have their own lint groups (e.g., `rust_2021_compatibility`) automatically generated for any lints signaling future-incompatible code that will break in the specified edition. @@ -813,15 +812,15 @@ The linting system automatically takes care of handling buffered lints later. [sessbl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/struct.Session.html#method.buffer_lint [parsebl]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_session/parse/struct.ParseSess.html#method.buffer_lint -Thus, to define a lint that runs early in the compilation, one defines a lint -like normal but invokes the lint with `buffer_lint`. +Thus, to define a lint that runs early in the compilation, +one defines a lint like normal but invokes the lint with `buffer_lint`. #### Linting even earlier in the compiler The parser (`rustc_ast`) is interesting in that it cannot have dependencies on any of the other `rustc*` crates. -In particular, it cannot depend on -`rustc_middle::lint` or `rustc_lint`, where all of the compiler linting infrastructure is defined. +In particular, it cannot depend on `rustc_middle::lint` or `rustc_lint`, +where all of the compiler linting infrastructure is defined. That's troublesome! To solve this, `rustc_ast` defines its own buffered lint type, which `ParseSess::buffer_lint` uses. @@ -841,20 +840,20 @@ $ rustc json_error_demo.rs --error-format json {"message":"For more information about this error, try `rustc --explain E0277`.","code":null,"level":"","spans":[],"children":[],"rendered":"For more information about this error, try `rustc --explain E0277`.\n"} ``` -Note that the output is a series of lines, each of which is a JSON -object, but the series of lines taken together is, unfortunately, not +Note that the output is a series of lines, each of which is a JSON object, +but the series of lines taken together is, unfortunately, not valid JSON, thwarting tools and tricks (such as [piping to `python3 -m json.tool`](https://docs.python.org/3/library/json.html#module-json.tool)) that require such. -(One speculates that this was intentional for LSP -performance purposes, so that each line/object can be sent as it is flushed?) +(One speculates that this was intentional for LSP performance purposes, +so that each line/object can be sent as it is flushed?) Also note the "rendered" field, which contains the "human" output as a string; this was introduced so that UI tests could both make use of -the structured JSON and see the "human" output (well, _sans_ colors) -without having to compile everything twice. +the structured JSON and see the "human" output (well, +_sans_ colors) without having to compile everything twice. -The "human" readable and the json format emitter can be found under -`rustc_errors`, both were moved from the `rustc_ast` crate to the +The "human" readable and the json format emitter can be found under `rustc_errors`, +both were moved from the `rustc_ast` crate to the [rustc_errors crate](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/index.html). The JSON emitter defines [its own `Diagnostic` @@ -937,16 +936,16 @@ If you can, you should use that instead. ### Filtering -To allow more targeted error messages, it is possible to filter the -application of these fields with `on`. +To allow more targeted error messages, +it is possible to filter the application of these fields with `on`. You can filter on the following boolean flags: - `crate_local`: whether the code causing the trait bound to not be fulfilled is part of the user's crate. This is used to avoid suggesting code changes that would require modifying a dependency. - `direct`: whether this is a user-specified rather than derived obligation. - - `from_desugaring`: whether we are in some kind of desugaring, like `?` - or a `try` block for example. + - `from_desugaring`: whether we are in some kind of desugaring, + like `?` or a `try` block for example. This flag can also be matched on, see below. You can match on the following names and values, using `name = "value"`: @@ -955,8 +954,8 @@ You can match on the following names and values, using `name = "value"`: - `from_desugaring`: Match against a particular variant of the `DesugaringKind` enum. The desugaring is identified by its variant name, for example `"QuestionMark"` for `?` desugaring, or `"TryBlock"` for `try` blocks. - - `Self` and any generic arguments of the trait, like `Self = "alloc::string::String"` - or `Rhs="i32"`. + - `Self` and any generic arguments of the trait, + like `Self = "alloc::string::String"` or `Rhs="i32"`. The compiler can provide several values to match on, for example: - the self_ty, pretty printed with and without type arguments resolved. From 2238f1bca22392ffa055e9f5bc06e4a8b8f0c27c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:03:37 +0200 Subject: [PATCH 1097/1309] improve diagnostics.md --- src/doc/rustc-dev-guide/src/diagnostics.md | 30 +++++++++++----------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/diagnostics.md b/src/doc/rustc-dev-guide/src/diagnostics.md index b807c7b381b5d..661e07af7189c 100644 --- a/src/doc/rustc-dev-guide/src/diagnostics.md +++ b/src/doc/rustc-dev-guide/src/diagnostics.md @@ -49,7 +49,7 @@ LL | more code it is a good idea to tweak the output appropriately. For example, the `if/else arms have incompatible types` error uses different spans depending on whether the arms are all in the same line, - if one of the arms is empty and if none of those cases applies. + if one of the arms is empty, and if none of those cases applies. - Sub-diagnostics. Any error can have multiple sub-diagnostics that look similar to the main part of the error. These are used for cases where the @@ -588,7 +588,7 @@ One benefit is that it is close to the dependency root, so it can be much faster Every lint is implemented via a `struct` that implements the `LintPass` `trait` (you can also implement one of the more specific lint pass traits, -either `EarlyLintPass` or `LateLintPass` depending on when is best for your lint to run). +either `EarlyLintPass` or `LateLintPass`, depending on when is best for your lint to run). The trait implementation allows you to check certain syntactic constructs as the linter walks the AST. You can then choose to emit lints in a very similar way to compile errors. @@ -698,25 +698,25 @@ declare_lint! { } ``` -### Future-incompatible lints +### future-incompatible lints The use of the term `future-incompatible` within the compiler has a slightly broader meaning than what rustc exposes to users of the compiler. -Inside rustc, future-incompatible lints are for signalling to the user that code they have -written may not compile in the future. +Inside rustc, +future-incompatible lints are for signalling to the user their code may not compile in the future. In general, future-incompatible code exists for two reasons: -* The user has written unsound code that the compiler mistakenly accepted. +* The code is unsound, and the compiler mistakenly accepted it. While it is within Rust's backwards compatibility guarantees to fix the soundness hole -(breaking the user's code), the lint is there to warn the user that this will happen -in some upcoming version of rustc *regardless of which edition the code uses*. -This is the meaning that rustc exclusively exposes to users as "future incompatible". -* The user has written code that will either no longer compiler *or* will change -meaning in an upcoming *edition*. -These are often called "edition lints" and can be -typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`) -that are used to lint against code that will break if the user updates the crate's edition. -See [migration lints](guides/editions.md#migration-lints) for more details. + (breaking the user's code), the lint is there to warn the user that this will happen + in some upcoming version of rustc *regardless of which edition the code uses*. + This is the meaning that rustc exclusively exposes to users as "future incompatible". +* The code will either no longer compile *or* will change + meaning in an upcoming *edition*. + These are often called "edition lints" and can be + typically seen in the various "edition compatibility" lint groups (e.g., `rust_2021_compatibility`) + that are used to lint against code that will break if the user updates the crate's edition. + See [migration lints](guides/editions.md#migration-lints) for more details. A future-incompatible lint should be declared with the `@future_incompatible` additional "field": From 56a6ee6d53d58e8cc685059766fd4aabc93f99e1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:15:00 +0200 Subject: [PATCH 1098/1309] sembr src/mir/index.md --- src/doc/rustc-dev-guide/src/mir/index.md | 92 ++++++++++++------------ 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md index b5b5b20500f39..a4075d1eae472 100644 --- a/src/doc/rustc-dev-guide/src/mir/index.md +++ b/src/doc/rustc-dev-guide/src/mir/index.md @@ -7,18 +7,18 @@ It is a radically simplified form of Rust that is used for certain flow-sensitive safety checks – notably the borrow checker! – and also for optimization and code generation. -If you'd like a very high-level introduction to MIR, as well as some -of the compiler concepts that it relies on (such as control-flow +If you'd like a very high-level introduction to MIR, +as well as some of the compiler concepts that it relies on (such as control-flow graphs and desugaring), you may enjoy the [rust-lang blog post that introduced MIR][blog]. [blog]: https://blog.rust-lang.org/2016/04/19/MIR.html ## Introduction to MIR -MIR is defined in the [`compiler/rustc_middle/src/mir/`][mir] module, but much of the code -that manipulates it is found in [`compiler/rustc_mir_build`][mirmanip_build], -[`compiler/rustc_mir_transform`][mirmanip_transform], and -[`compiler/rustc_mir_dataflow`][mirmanip_dataflow]. +MIR is defined in the [`compiler/rustc_middle/src/mir/`][mir] module, +but much of the code that manipulates it is found in [`compiler/rustc_mir_build`][mirmanip_build], +[`compiler/rustc_mir_transform`][mirmanip_transform], +and [`compiler/rustc_mir_dataflow`][mirmanip_dataflow]. [RFC 1211]: https://rust-lang.github.io/rfcs/1211-mir.html @@ -38,22 +38,22 @@ This section introduces the key concepts of MIR, summarized here: - **statements:** actions with one successor - **terminators:** actions with potentially multiple successors; always at the end of a block - (if you're not familiar with the term *basic block*, see the [background chapter][cfg]) -- **Locals:** Memory locations allocated on the stack (conceptually, at - least), such as function arguments, local variables, and temporaries. +- **Locals:** Memory locations allocated on the stack (conceptually, at least), + such as function arguments, local variables, and temporaries. These are identified by an index, written with a leading underscore, like `_1`. There is also a special "local" (`_0`) allocated to store the return value. - **Places:** expressions that identify a location in memory, like `_1` or `_1.f`. - **Rvalues:** expressions that produce a value. The "R" stands for the fact that these are the "right-hand side" of an assignment. - - **Operands:** the arguments to an rvalue, which can either be a - constant (like `22`) or a place (like `_1`). + - **Operands:** the arguments to an rvalue, + which can either be a constant (like `22`) or a place (like `_1`). You can get a feeling for how MIR is constructed by translating simple programs into MIR and reading the pretty printed output. -In fact, the playground makes this easy, since it supplies a MIR button that will -show you the MIR for your program. -Try putting this program into play -(or [clicking on this link][sample-play]), and then clicking the "MIR" button on the top: +In fact, the playground makes this easy, +since it supplies a MIR button that will show you the MIR for your program. +Try putting this program into play (or [clicking on this link][sample-play]), +and then clicking the "MIR" button on the top: [sample-play]: https://play.rust-lang.org/?gist=30074856e62e74e91f06abd19bd72ece&version=stable&edition=2021 @@ -83,8 +83,8 @@ We can use `rustc [filename].rs -Z mir-opt-level=0 --emit mir` to view unoptimiz This requires the nightly toolchain. -**Variable declarations.** If we drill in a bit, we'll see it begins -with a bunch of variable declarations. +**Variable declarations.** If we drill in a bit, +we'll see it begins with a bunch of variable declarations. They look like this: ```mir @@ -101,8 +101,8 @@ like `_0` or `_1`. We also intermingle the user's variables (e.g., `_1`) with temporary values (e.g., `_2` or `_3`). You can tell apart user-defined variables because they have debuginfo associated to them (see below). -**User variable debuginfo.** Below the variable declarations, we find the only -hint that `_1` represents a user variable: +**User variable debuginfo.** Below the variable declarations, +we find the only hint that `_1` represents a user variable: ```mir scope 1 { debug vec => _1; // in scope 1 at src/main.rs:2:9: 2:16 @@ -130,15 +130,15 @@ bb0: { } ``` -A basic block is defined by a series of **statements** and a final -**terminator**. In this case, there is one statement: +A basic block is defined by a series of **statements** and a final **terminator**. + In this case, there is one statement: ```mir StorageLive(_1); ``` -This statement indicates that the variable `_1` is "live", meaning -that it may be used later – this will persist until we encounter a +This statement indicates that the variable `_1` is "live", +meaning that it may be used later – this will persist until we encounter a `StorageDead(_1)` statement, which indicates that the variable `_1` is done being used. These "storage statements" are used by LLVM to allocate stack space. @@ -151,8 +151,8 @@ _1 = const >::new() -> bb2; Terminators are different from statements because they can have more than one successor – that is, control may flow to different places. Function calls like the call to `Vec::new` are always -terminators because of the possibility of unwinding, although in the -case of `Vec::new` we are able to see that indeed unwinding is not +terminators because of the possibility of unwinding, +although in the case of `Vec::new` we are able to see that indeed unwinding is not possible, and hence we list only one successor block, `bb2`. If we look ahead to `bb2`, we will see it looks like this: @@ -165,8 +165,8 @@ bb2: { } ``` -Here there are two statements: another `StorageLive`, introducing the `_3` -temporary, and then an assignment: +Here there are two statements: another `StorageLive`, introducing the `_3` temporary, +and then an assignment: ```mir _3 = &mut _1; @@ -179,8 +179,8 @@ Assignments in general have the form: ``` A place is an expression like `_3`, `_3.f` or `*_3` – it denotes a location in memory. -An **Rvalue** is an expression that creates a -value: in this case, the rvalue is a mutable borrow expression, which looks like `&mut `. +An **Rvalue** is an expression that creates a value: in this case, +the rvalue is a mutable borrow expression, which looks like `&mut `. So we can kind of define a grammar for rvalues like so: ```text @@ -194,21 +194,21 @@ So we can kind of define a grammar for rvalues like so: | move Place ``` -As you can see from this grammar, rvalues cannot be nested – they can -only reference places and constants. +As you can see from this grammar, +rvalues cannot be nested – they can only reference places and constants. Moreover, when you use a place, we indicate whether we are **copying it** (which requires that the place have a type `T` where `T: Copy`) or **moving it** (which works for a place of any type). -So, for example, if we had the expression `x -= a + b + c` in Rust, that would get compiled to two statements and a temporary: +So, for example, if we had the expression `x = a + b + c` in Rust, +that would get compiled to two statements and a temporary: ```mir TMP1 = a + b x = TMP1 + c ``` -([Try it and see][play-abc], though you may want to do release mode to skip -over the overflow checks.) +([Try it and see][play-abc], +though you may want to do release mode to skip over the overflow checks.) [play-abc]: https://play.rust-lang.org/?gist=1751196d63b2a71f8208119e59d8a5b6&version=stable @@ -225,8 +225,8 @@ but [you can read about those below](#promoted-constants)). - **Basic blocks**: The basic blocks are stored in the field [`Body::basic_blocks`][basicblocks]; this is a vector of [`BasicBlockData`] structures. - Nobody ever references a basic block directly: instead, we pass around [`BasicBlock`] - values, which are [newtype'd] indices into this vector. + Nobody ever references a basic block directly: instead, we pass around [`BasicBlock`] values, + which are [newtype'd] indices into this vector. - **Statements** are represented by the type [`Statement`]. - **Terminators** are represented by the [`Terminator`]. - **Locals** are represented by a [newtype'd] index type [`Local`]. @@ -240,8 +240,8 @@ but [you can read about those below](#promoted-constants)). These are represented by the [newtype'd] type [`ProjectionElem`]. So e.g. the place `_1.f` is a projection, with `f` being the "projection element" and `_1` being the base path. - `*_1` is also a projection, with the `*` being represented - by the [`ProjectionElem::Deref`] element. + `*_1` is also a projection, + with the `*` being represented by the [`ProjectionElem::Deref`] element. - **Rvalues** are represented by the enum [`Rvalue`]. - **Operands** are represented by the enum [`Operand`]. @@ -251,8 +251,8 @@ When code has reached the MIR stage, constants can generally come in two forms: *MIR constants* ([`mir::Constant`]) and *type system constants* ([`ty::Const`]). MIR constants are used as operands: in `x + CONST`, `CONST` is a MIR constant; similarly, in `x + 2`, `2` is a MIR constant. -Type system constants are used in -the type system, in particular for array lengths but also for const generics. +Type system constants are used in the type system, +in particular for array lengths but also for const generics. Generally, both kinds of constants can be "unevaluated" or "already evaluated". An unevaluated constant simply stores the `DefId` of what needs to be evaluated @@ -270,8 +270,8 @@ parameter is used as an operand. ### MIR constant values -In general, a MIR constant value (`mir::ConstValue`) was computed by evaluating -some constant the user wrote. +In general, +a MIR constant value (`mir::ConstValue`) was computed by evaluating some constant the user wrote. This [const evaluation](../const-eval.md) produces a very low-level representation of the result in terms of individual bytes. We call this an "indirect" constant (`mir::ConstValue::Indirect`) since the value @@ -280,8 +280,8 @@ is stored in-memory. However, storing everything in-memory would be awfully inefficient. Hence there are some other variants in `mir::ConstValue` that can represent certain simple and common values more efficiently. -In particular, everything that can be -directly written as a literal in Rust (integers, floats, chars, bools, but also +In particular, everything that can be directly written as a literal in Rust (integers, +floats, chars, bools, but also `"string literals"` and `b"byte string literals"`) has an optimized variant that avoids the full overhead of the in-memory representation. @@ -301,8 +301,8 @@ In other words, a specific value must only be representable in one specific way. For example, there is only one way to represent an array of two integers as a `ValTree`: `Branch([Leaf(first_int), Leaf(second_int)])`. Even though theoretically a `[u32; 2]` could be encoded in a `u64` and thus just be a -`Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree` -(and is very complex to do, so it is unlikely anyone is tempted to do so). +`Leaf(bits_of_two_u32)`, that is not a legal construction of `ValTree` (and is very complex to do, +so it is unlikely anyone is tempted to do so). These rules also mean that some values are not representable. There can be no `union`s in type level constants, From 7710f70fce3173d176546f26fbad0ef1693797e3 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:23:27 +0200 Subject: [PATCH 1099/1309] improve mir/index.md --- src/doc/rustc-dev-guide/src/mir/index.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md index a4075d1eae472..6854447b66928 100644 --- a/src/doc/rustc-dev-guide/src/mir/index.md +++ b/src/doc/rustc-dev-guide/src/mir/index.md @@ -131,7 +131,7 @@ bb0: { ``` A basic block is defined by a series of **statements** and a final **terminator**. - In this case, there is one statement: +In this case, there is one statement: ```mir StorageLive(_1); @@ -252,7 +252,7 @@ When code has reached the MIR stage, constants can generally come in two forms: MIR constants are used as operands: in `x + CONST`, `CONST` is a MIR constant; similarly, in `x + 2`, `2` is a MIR constant. Type system constants are used in the type system, -in particular for array lengths but also for const generics. +in particular for array lengths, but also for const generics. Generally, both kinds of constants can be "unevaluated" or "already evaluated". An unevaluated constant simply stores the `DefId` of what needs to be evaluated From 88e8e029744220d08adf28cf9b660603940ab754 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:23:35 +0200 Subject: [PATCH 1100/1309] reflow src/mir/index.md --- src/doc/rustc-dev-guide/src/mir/index.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/mir/index.md b/src/doc/rustc-dev-guide/src/mir/index.md index 6854447b66928..005dc0cac21d9 100644 --- a/src/doc/rustc-dev-guide/src/mir/index.md +++ b/src/doc/rustc-dev-guide/src/mir/index.md @@ -152,8 +152,8 @@ Terminators are different from statements because they can have more than one successor – that is, control may flow to different places. Function calls like the call to `Vec::new` are always terminators because of the possibility of unwinding, -although in the case of `Vec::new` we are able to see that indeed unwinding is not -possible, and hence we list only one successor block, `bb2`. +although in the case of `Vec::new` we are able to see that indeed unwinding is not possible, +and hence we list only one successor block, `bb2`. If we look ahead to `bb2`, we will see it looks like this: @@ -281,8 +281,8 @@ However, storing everything in-memory would be awfully inefficient. Hence there are some other variants in `mir::ConstValue` that can represent certain simple and common values more efficiently. In particular, everything that can be directly written as a literal in Rust (integers, -floats, chars, bools, but also -`"string literals"` and `b"byte string literals"`) has an optimized variant that +floats, chars, bools, +but also `"string literals"` and `b"byte string literals"`) has an optimized variant that avoids the full overhead of the in-memory representation. ### ValTrees From 062f7aca04ec3766deac14e1b138b19136f64011 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:24:12 +0200 Subject: [PATCH 1101/1309] sembr src/tracing.md --- src/doc/rustc-dev-guide/src/tracing.md | 83 +++++++++++++------------- 1 file changed, 42 insertions(+), 41 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index ae819003e1f3e..811e36bb21d7a 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -1,9 +1,9 @@ # Using tracing to debug the compiler -The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information -at many points. -These are very useful to at least narrow down the location of -a bug if not to find it entirely, or just to orient yourself as to why the +The compiler has a lot of [`debug!`] (or `trace!`) calls, +which print out logging information at many points. +These are very useful to at least narrow down the location of a bug if not to find it entirely, +or just to orient yourself as to why the compiler is doing a particular thing. [`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html @@ -66,8 +66,8 @@ RUSTC_LOG=rustc_borrowck[do_mir_borrowck] ### I don't want all calls -If you are compiling libcore, you likely don't want *all* borrowck dumps, but only one -for a specific function. +If you are compiling libcore, you likely don't want *all* borrowck dumps, +but only one for a specific function. You can filter function calls by their arguments by regexing them. ``` @@ -75,8 +75,8 @@ RUSTC_LOG=[do_mir_borrowck{id=\.\*from_utf8_unchecked\.\*}] ``` will only give you the logs of borrowchecking `from_utf8_unchecked`. -Note that you will -still get a short message per ignored `do_mir_borrowck`, but none of the things inside those calls. +Note that you will still get a short message per ignored `do_mir_borrowck`, +but none of the things inside those calls. This helps you in looking through the calls that are happening and helps you adjust your regex if you mistyped it. @@ -105,40 +105,41 @@ You can find a list of queries and their arguments in ## Broad module level filters -You can also use filters similar to the `log` crate's filters, which will enable -everything within a specific module. +You can also use filters similar to the `log` crate's filters, +which will enable everything within a specific module. This is often too verbose and too unstructured, so it is recommended to use function level filters. Your log filter can be just `debug` to get all `debug!` output and higher (e.g., it will also include `info!`), or `path::to::module` to get *all* -output (which will include `trace!`) from a particular module, or -`path::to::module=debug` to get `debug!` output and higher from a particular module. +output (which will include `trace!`) from a particular module, +or `path::to::module=debug` to get `debug!` output and higher from a particular module. -For example, to get the `debug!` output and higher for a specific module, you -can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs`. +For example, to get the `debug!` output and higher for a specific module, +you can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs`. All `debug!` output will then appear in standard error. Note that you can use a partial path and the filter will still work. For example, if you want to see `info!` output from only -`rustdoc::passes::collect_intra_doc_links`, you could use -`RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use +`rustdoc::passes::collect_intra_doc_links`, +you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra=info`. If you are developing rustdoc, use `RUSTDOC_LOG` instead. If you are developing Miri, use `MIRI_LOG` instead. You get the idea :) -See the [`tracing`] crate's docs, and specifically the docs for [`debug!`] to -see the full syntax you can use. -(Note: unlike the compiler, the [`tracing`] -crate and its examples use the `RUSTC_LOG` environment variable. +See the [`tracing`] crate's docs, +and specifically the docs for [`debug!`] to see the full syntax you can use. +(Note: unlike the compiler, +the [`tracing`] crate and its examples use the `RUSTC_LOG` environment variable. rustc, rustdoc, and other tools set custom environment variables.) -**Note that unless you use a very strict filter, the logger will emit a lot of -output, so use the most specific module(s) you can (comma-separated if -multiple)**. It's typically a good idea to pipe standard error to a file and +**Note that unless you use a very strict filter, the logger will emit a lot of output, +so use the most specific module(s) you can (comma-separated if +multiple)**. +It's typically a good idea to pipe standard error to a file and look at the log output with a text editor. So, to put it together: @@ -180,13 +181,13 @@ $ RUSTDOC_LOG=rustdoc=debug rustdoc +stage1 my-file.rs ## Log colors -By default, rustc (and other tools, like rustdoc and Miri) will be smart about -when to use ANSI colors in the log output. +By default, rustc (and other tools, +like rustdoc and Miri) will be smart about when to use ANSI colors in the log output. If they are outputting to a terminal, -they will use colors, and if they are outputting to a file or being piped -somewhere else, they will not. -However, it's hard to read log output in your -terminal unless you have a very strict filter, so you may want to pipe the +they will use colors, and if they are outputting to a file or being piped somewhere else, +they will not. +However, it's hard to read log output in your terminal unless you have a very strict filter, +so you may want to pipe the output to a pager like `less`. But then there won't be any colors, which makes it hard to pick out what you're looking for! @@ -201,18 +202,18 @@ So, if you want to enable colors when piping to `less`, use something similar to $ RUSTC_LOG=debug RUSTC_LOG_COLOR=always rustc +stage1 ... | less -R ``` -Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, not logs -from rustc functions that Miri calls. +Note that `MIRI_LOG_COLOR` will only color logs that come from Miri, +not logs from rustc functions that Miri calls. Use `RUSTC_LOG_COLOR` to color logs from rustc. ## How to keep or remove `debug!` and `trace!` calls from the resulting binary While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, calls to `debug!` and `trace!` are only included in the program if -`rust.debug-logging=true` is turned on in bootstrap.toml (it is -turned off by default), so if you don't see `DEBUG` logs, especially -if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see -`INFO` logs, make sure that `rust.debug-logging=true` is turned on in your bootstrap.toml. +`rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), +so if you don't see `DEBUG` logs, especially +if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, +make sure that `rust.debug-logging=true` is turned on in your bootstrap.toml. ## Logging etiquette and conventions @@ -220,11 +221,11 @@ Because calls to `debug!` are removed by default, in most cases, don't worry about the performance of adding "unnecessary" calls to `debug!` and leaving them in code you commit - they won't slow down the performance of what we ship. -That said, there can also be excessive tracing calls, especially -when they are redundant with other calls nearby or in functions called from here. +That said, there can also be excessive tracing calls, +especially when they are redundant with other calls nearby or in functions called from here. There is no perfect balance to hit here, and it is left to the reviewer's -discretion to decide whether to let you leave `debug!` statements in, or whether to ask -you to remove them before merging. +discretion to decide whether to let you leave `debug!` statements in, +or whether to ask you to remove them before merging. It may be preferable to use `trace!` over `debug!` for very noisy logs. @@ -243,8 +244,8 @@ If in the module `rustc::foo` you have a statement debug!(x = ?random_operation(tcx)); ``` -Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::foo`, then -`random_operation()` will run. +Then if someone runs a debug `rustc` with `RUSTC_LOG=rustc::foo`, +then `random_operation()` will run. `RUSTC_LOG` filters that do not enable this debug statement will not execute `random_operation`. This means that you should not put anything too expensive or likely to crash From bdd20078512c4aaf61271e050a14edf284b2dc28 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:29:23 +0200 Subject: [PATCH 1102/1309] improve tracing.md --- src/doc/rustc-dev-guide/src/tracing.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index 811e36bb21d7a..e3c492bbf80e4 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -209,11 +209,11 @@ Use `RUSTC_LOG_COLOR` to color logs from rustc. ## How to keep or remove `debug!` and `trace!` calls from the resulting binary While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, -calls to `debug!` and `trace!` are only included in the program if -`rust.debug-logging=true` is turned on in bootstrap.toml (it is turned off by default), +calls to `debug!` and `trace!` are only included in the program if you have +`rust.debug-logging = true` in bootstrap.toml (it is turned off by default), so if you don't see `DEBUG` logs, especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, -make sure that `rust.debug-logging=true` is turned on in your bootstrap.toml. +make sure that `rust.debug-logging` is turned on in your bootstrap.toml. ## Logging etiquette and conventions From e60b15334b90523d3167f80c897f581d040b9718 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:29:42 +0200 Subject: [PATCH 1103/1309] reflow src/tracing.md --- src/doc/rustc-dev-guide/src/tracing.md | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tracing.md b/src/doc/rustc-dev-guide/src/tracing.md index e3c492bbf80e4..0e2f29f698cba 100644 --- a/src/doc/rustc-dev-guide/src/tracing.md +++ b/src/doc/rustc-dev-guide/src/tracing.md @@ -3,8 +3,7 @@ The compiler has a lot of [`debug!`] (or `trace!`) calls, which print out logging information at many points. These are very useful to at least narrow down the location of a bug if not to find it entirely, -or just to orient yourself as to why the -compiler is doing a particular thing. +or just to orient yourself as to why the compiler is doing a particular thing. [`debug!`]: https://docs.rs/tracing/0.1/tracing/macro.debug.html @@ -120,8 +119,7 @@ you can run the compiler with `RUSTC_LOG=path::to::module=debug rustc my-file.rs All `debug!` output will then appear in standard error. Note that you can use a partial path and the filter will still work. -For example, if you want to see `info!` output from only -`rustdoc::passes::collect_intra_doc_links`, +For example, if you want to see `info!` output from only `rustdoc::passes::collect_intra_doc_links`, you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra_doc_links=info` *or* you could use `RUSTDOC_LOG=rustdoc::passes::collect_intra=info`. @@ -137,8 +135,7 @@ rustc, rustdoc, and other tools set custom environment variables.) **Note that unless you use a very strict filter, the logger will emit a lot of output, -so use the most specific module(s) you can (comma-separated if -multiple)**. +so use the most specific module(s) you can (comma-separated if multiple)**. It's typically a good idea to pipe standard error to a file and look at the log output with a text editor. @@ -187,8 +184,7 @@ If they are outputting to a terminal, they will use colors, and if they are outputting to a file or being piped somewhere else, they will not. However, it's hard to read log output in your terminal unless you have a very strict filter, -so you may want to pipe the -output to a pager like `less`. +so you may want to pipe the output to a pager like `less`. But then there won't be any colors, which makes it hard to pick out what you're looking for! You can override whether to have colors in log output with the `RUSTC_LOG_COLOR` @@ -211,8 +207,8 @@ Use `RUSTC_LOG_COLOR` to color logs from rustc. While calls to `error!`, `warn!` and `info!` are included in every build of the compiler, calls to `debug!` and `trace!` are only included in the program if you have `rust.debug-logging = true` in bootstrap.toml (it is turned off by default), -so if you don't see `DEBUG` logs, especially -if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, +so if you don't see `DEBUG` logs, +especially if you run the compiler with `RUSTC_LOG=rustc rustc some.rs` and only see `INFO` logs, make sure that `rust.debug-logging` is turned on in your bootstrap.toml. ## Logging etiquette and conventions From 543c24d4c85f95bf8bceebeb4993feb755300f6d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:46:39 +0200 Subject: [PATCH 1104/1309] sembr src/debuginfo/llvm-codegen.md --- src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md index 4f5bdaa1e6795..e72b94ea5b38e 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md @@ -1,13 +1,13 @@ # LLVM codegen -When Rust calls an LLVM `DIBuilder` function, LLVM translates the given information to a -["debug record"][dbg_record] that is format-agnostic. +When Rust calls an LLVM `DIBuilder` function, +LLVM translates the given information to a ["debug record"][dbg_record] that is format-agnostic. These records can be inspected in the LLVM-IR. [dbg_record]: https://llvm.org/docs/SourceLevelDebugging.html#debug-records -It is important to note that tags within the debug records are **always stored as DWARF tags**. If -the target calls for PDB debug info, during codegen the debug records will then be passed through +It is important to note that tags within the debug records are **always stored as DWARF tags**. +If the target calls for PDB debug info, during codegen the debug records will then be passed through [a module that translates the DWARF tags to their CodeView counterparts][cv]. [cv]:https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp From 1b5002dd2c6a81f4d025e1e0c752708034417d5d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:47:40 +0200 Subject: [PATCH 1105/1309] improve debuginfo/llvm-codegen.md --- src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md index e72b94ea5b38e..1cdc7c0929142 100644 --- a/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md +++ b/src/doc/rustc-dev-guide/src/debuginfo/llvm-codegen.md @@ -7,7 +7,7 @@ These records can be inspected in the LLVM-IR. [dbg_record]: https://llvm.org/docs/SourceLevelDebugging.html#debug-records It is important to note that tags within the debug records are **always stored as DWARF tags**. -If the target calls for PDB debug info, during codegen the debug records will then be passed through +If the target calls for PDB debug info, during codegen, the debug records will then be passed through [a module that translates the DWARF tags to their CodeView counterparts][cv]. [cv]:https://github.com/llvm/llvm-project/blob/main/llvm/lib/CodeGen/AsmPrinter/CodeViewDebug.cpp From 0529c625e19a43838d65cf93167b93ad7335b34c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:48:04 +0200 Subject: [PATCH 1106/1309] sembr src/profiling/with-perf.md --- .../src/profiling/with-perf.md | 64 +++++++++---------- 1 file changed, 31 insertions(+), 33 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/with-perf.md b/src/doc/rustc-dev-guide/src/profiling/with-perf.md index b55afed47fbdc..9c3cf1d88747c 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with-perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with-perf.md @@ -60,8 +60,8 @@ cargo install --locked addr2line --features="bin" ### Gathering a perf profile from a `perf.rust-lang.org` test Often we want to analyze a specific test from `perf.rust-lang.org`. -The easiest way to do that is to use the [rustc-perf] -benchmarking suite, this approach is described [here](with-rustc-perf.md). +The easiest way to do that is to use the [rustc-perf] benchmarking suite, +this approach is described [here](with-rustc-perf.md). Instead of using the benchmark suite CLI, you can also profile the benchmarks manually. First, you need to clone the [rustc-perf] repository: @@ -96,8 +96,8 @@ CARGO_INCREMENTAL=0 cargo + check Next: we want record the execution time for *just* the clap-rs crate, running cargo check. -I tend to use `cargo rustc` for this, since it -also allows me to add explicit flags, which we'll do later on. +I tend to use `cargo rustc` for this, since it also allows me to add explicit flags, +which we'll do later on. ```bash touch src/lib.rs @@ -106,8 +106,8 @@ CARGO_INCREMENTAL=0 perf record -F99 --call-graph dwarf cargo rustc --profile ch Note that final command: it's a doozy! It uses the `cargo rustc` command, which executes rustc with (potentially) additional options; -the `--profile check` and `--lib` options specify that we are doing a -`cargo check` execution, and that this is a library (not a binary). +the `--profile check` and `--lib` options specify that we are doing a `cargo check` execution, +and that this is a library (not a binary). At this point, we can use `perf` tooling to analyze the results. For example: @@ -121,14 +121,14 @@ In simple cases, that can be helpful. For more detailed examination, the [`perf-focus` tool][pf] can be helpful; it is covered below. **A note of caution.** Each of the rustc-perf tests is its own special snowflake. - In particular, some of them are not libraries, in which - case you would want to do `touch src/main.rs` and avoid passing `--lib`. + In particular, some of them are not libraries, + in which case you would want to do `touch src/main.rs` and avoid passing `--lib`. I'm not sure how best to tell which test is which to be honest. ### Gathering NLL data -If you want to profile an NLL run, you can just pass extra options to -the `cargo rustc` command, like so: +If you want to profile an NLL run, you can just pass extra options to the `cargo rustc` command, +like so: ```bash touch src/lib.rs @@ -152,8 +152,8 @@ To understand how it works, you have to know just a bit about perf. Basically, perf works by *sampling* your process on a regular basis (or whenever some event occurs). For each sample, perf gathers a backtrace. `perf focus` lets you write a regular expression that tests -which functions appear in that backtrace, and then tells you which -percentage of samples had a backtrace that met the regular expression. +which functions appear in that backtrace, +and then tells you which percentage of samples had a backtrace that met the regular expression. It's probably easiest to explain by walking through how I would analyze NLL performance. ### Installing `perf-focus` @@ -168,8 +168,7 @@ cargo install --locked perf-focus Let's say we've gathered the NLL data for a test. We'd like to know how much time it is spending in the MIR borrow-checker. -The "main" function of the MIR borrowck is called `do_mir_borrowck`, so we can do -this command: +The "main" function of the MIR borrowck is called `do_mir_borrowck`, so we can do this command: ```bash $ perf focus '{do_mir_borrowck}' @@ -179,22 +178,22 @@ Not Matches: 542 Percentage : 29% ``` -The `'{do_mir_borrowck}'` argument is called the **matcher**. It -specifies the test to be applied on the backtrace. +The `'{do_mir_borrowck}'` argument is called the **matcher**. +It specifies the test to be applied on the backtrace. In this case, the `{X}` indicates that there must be *some* function on the backtrace that meets the regular expression `X`. -In this case, that regex is just the name of the function we want -(in fact, it's a subset of the name; +In this case, that regex is just the name of the function we want (in fact, +it's a subset of the name; the full name includes a bunch of other stuff, like the module path). In this mode, perf-focus just prints out the percentage of samples where `do_mir_borrowck` was on the stack: in this case, 29%. -**A note about c++filt.** To get the data from `perf`, `perf focus` - currently executes `perf script` (perhaps there is a better way...). +**A note about c++filt.** To get the data from `perf`, + `perf focus` currently executes `perf script` (perhaps there is a better way...). I've sometimes found that `perf script` outputs C++ mangled names. This is annoying. You can tell by running `perf script | - head` yourself — if you see names like `5rustc6middle` instead of - `rustc::middle`, then you have the same problem. + head` yourself — if you see names like `5rustc6middle` instead of `rustc::middle`, + then you have the same problem. You can solve this by doing: ```bash @@ -203,10 +202,10 @@ perf script | c++filt | perf focus --from-stdin ... This will pipe the output from `perf script` through `c++filt` and should mostly convert those names into a more friendly format. -The `--from-stdin` flag to `perf focus` tells it to get its data from -stdin, rather than executing `perf focus`. -We should make this more convenient (at worst, maybe add a `c++filt` option to `perf focus`, or -just always use it — it's pretty harmless). +The `--from-stdin` flag to `perf focus` tells it to get its data from stdin, +rather than executing `perf focus`. +We should make this more convenient (at worst, maybe add a `c++filt` option to `perf focus`, +or just always use it — it's pretty harmless). ### Example: How much time does MIR borrowck spend solving traits? @@ -275,17 +274,16 @@ Usually "total" is the more interesting number, but not always. ### Relative percentages -By default, all in perf-focus are relative to the **total program -execution**. This is useful to help you keep perspective — often as -we drill down to find hot spots, we can lose sight of the fact that, +By default, all in perf-focus are relative to the **total program execution**. +This is useful to help you keep perspective — often as we drill down to find hot spots, +we can lose sight of the fact that, in terms of overall program execution, this "hot spot" is actually not important. It also ensures that percentages between different queries are easily compared against one another. -That said, sometimes it's useful to get relative percentages, so `perf -focus` offers a `--relative` option. +That said, sometimes it's useful to get relative percentages, +so `perf focus` offers a `--relative` option. In this case, the percentages are listed only for samples that match (vs all samples). -So for example we could get our percentages relative to the borrowck itself -like so: +So for example we could get our percentages relative to the borrowck itself like so: ```bash $ perf focus '{do_mir_borrowck}' --tree-callees --relative --tree-max-depth 1 --tree-min-percent 5 From b5297f7d92876e8cc848897b11028a9ba764977e Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:51:12 +0200 Subject: [PATCH 1107/1309] missing pauses --- src/doc/rustc-dev-guide/src/profiling/with-perf.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/profiling/with-perf.md b/src/doc/rustc-dev-guide/src/profiling/with-perf.md index 9c3cf1d88747c..1a3b986d8213b 100644 --- a/src/doc/rustc-dev-guide/src/profiling/with-perf.md +++ b/src/doc/rustc-dev-guide/src/profiling/with-perf.md @@ -283,7 +283,7 @@ It also ensures that percentages between different queries are easily compared a That said, sometimes it's useful to get relative percentages, so `perf focus` offers a `--relative` option. In this case, the percentages are listed only for samples that match (vs all samples). -So for example we could get our percentages relative to the borrowck itself like so: +So, for example, we could get our percentages relative to the borrowck itself like so: ```bash $ perf focus '{do_mir_borrowck}' --tree-callees --relative --tree-max-depth 1 --tree-min-percent 5 From 05c81327b84cd72c04206ffe20d22ff0cdee9b33 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:51:30 +0200 Subject: [PATCH 1108/1309] sembr src/effects.md --- src/doc/rustc-dev-guide/src/effects.md | 55 +++++++++++++------------- 1 file changed, 28 insertions(+), 27 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 9c54705e000fd..55e00d4acfad3 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -3,20 +3,20 @@ ## The `HostEffect` predicate [`HostEffectPredicate`]s are a kind of predicate from `[const] Tr` or `const Tr` bounds. -It has a trait reference, and a `constness` which could be `Maybe` or -`Const` depending on the bound. +It has a trait reference, +and a `constness` which could be `Maybe` or `Const` depending on the bound. Because `[const] Tr`, or rather `Maybe` bounds -apply differently based on whichever contexts they are in, they have different -behavior than normal bounds. +apply differently based on whichever contexts they are in, +they have different behavior than normal bounds. Where normal trait bounds on a function such as `T: Tr` are collected within the [`clauses_of`] query to be proven when a -function is called and to be assumed within the function, bounds such as -`T: [const] Tr` will behave as a normal trait bound and add `T: Tr` to the result +function is called and to be assumed within the function, +bounds such as `T: [const] Tr` will behave as a normal trait bound and add `T: Tr` to the result from `clauses_of`, but also adds a `HostEffectPredicate` to the [`const_conditions`] query. On the other hand, `T: const Tr` bounds do not change meaning across contexts, -therefore they will result in `HostEffect(T: Tr, const)` being added to -`clauses_of`, and not `const_conditions`. +therefore they will result in `HostEffect(T: Tr, const)` being added to `clauses_of`, +and not `const_conditions`. [`HostEffectPredicate`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/predicate/struct.HostEffectPredicate.html [`clauses_of`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.clauses_of @@ -34,14 +34,15 @@ fn foo() where T: Default {} We must be able to prove that `T` implements `Default`. In a similar vein, `const_conditions` represents a set of predicates that need to be proven to use -an item *in const contexts*. If we adjust the example above to use `const` trait bounds: +an item *in const contexts*. +If we adjust the example above to use `const` trait bounds: ```rust const fn foo() where T: [const] Default {} ``` -Then `foo` would get a `HostEffect(T: Default, maybe)` in the `const_conditions` -query, suggesting that in order to call `foo` from const contexts, one must +Then `foo` would get a `HostEffect(T: Default, maybe)` in the `const_conditions` query, +suggesting that in order to call `foo` from const contexts, one must prove that `T` has a const implementation of `Default`. ## Enforcement of `const_conditions` @@ -51,8 +52,8 @@ prove that `T` has a const implementation of `Default`. Every call in HIR from a const context (which includes `const fn` and `const` items) will check that `const_conditions` of the function we are calling hold. This is done in [`FnCtxt::enforce_context_effects`]. -Note that we don't check -if the function is only referred to but not called, as the following code needs to compile: +Note that we don't check if the function is only referred to but not called, +as the following code needs to compile: ```rust const fn hi() -> T { @@ -61,8 +62,8 @@ const fn hi() -> T { const X: fn() -> u32 = hi::; ``` -For a trait `impl` to be well-formed, we must be able to prove the -`const_conditions` of the trait from the `impl`'s environment. +For a trait `impl` to be well-formed, +we must be able to prove the `const_conditions` of the trait from the `impl`'s environment. This is checked in [`wfcheck::check_impl`]. Here's an example: @@ -79,8 +80,8 @@ impl const Foo for () {} Methods of trait impls must not have stricter bounds than the method of the trait that they are implementing. -To check that the methods are compatible, a -hybrid environment is constructed with the predicates of the `impl` plus the +To check that the methods are compatible, +a hybrid environment is constructed with the predicates of the `impl` plus the predicates of the trait method, and we attempt to prove the predicates of the impl method. We do the same for `const_conditions`: @@ -113,8 +114,8 @@ are revalidated again in [`Checker::revalidate_conditional_constness`]. ## `explicit_implied_const_bounds` on associated types and traits -Bounds on associated types, opaque types, and supertraits such as the following -have their bounds represented differently: +Bounds on associated types, opaque types, +and supertraits such as the following have their bounds represented differently: ```rust trait Foo: [const] PartialEq { @@ -132,8 +133,8 @@ bounds on functions), these bounds need to be proved at definition (at the impl, or when returning the opaque) but can be assumed for callers. The non-const equivalent of these bounds are called [`explicit_item_bounds`]. -These bounds are checked in [`compare_impl_item::check_type_bounds`] for HIR -typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and +These bounds are checked in [`compare_impl_item::check_type_bounds`] for HIR typeck, +[`evaluate_host_effect_from_item_bounds`] in the old solver and [`consider_additional_alias_assumptions`] in the new solver. [`explicit_item_bounds`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.TyCtxt.html#method.explicit_item_bounds @@ -147,11 +148,11 @@ typeck, [`evaluate_host_effect_from_item_bounds`] in the old solver and In general, we can prove a `HostEffect` predicate when either of these conditions are met: * The predicate can be assumed from caller bounds; -* The type has a `const` `impl` for the trait, *and* that const conditions on - the impl holds, *and* that the `explicit_implied_const_bounds` on the trait holds; or +* The type has a `const` `impl` for the trait, *and* that const conditions on the impl holds, + *and* that the `explicit_implied_const_bounds` on the trait holds; or * The type has a built-in implementation for the trait in const contexts. - For example, `Fn` may be implemented by function items if their const conditions - are satisfied, or `Destruct` is implemented in const contexts if the type can + For example, `Fn` may be implemented by function items if their const conditions are satisfied, + or `Destruct` is implemented in const contexts if the type can be dropped at compile time. [old solver]: https://doc.rust-lang.org/nightly/nightly-rustc/src/rustc_trait_selection/traits/effects.rs.html @@ -164,8 +165,8 @@ To be expanded later. ### The `#[rustc_non_const_trait_method]` attribute This is intended for internal (standard library) usage only. -With this attribute applied to a trait method, the compiler will not check the default body of this -method for ability to run in compile time. +With this attribute applied to a trait method, +the compiler will not check the default body of this method for ability to run in compile time. Users of the trait will also not be allowed to use this trait method in const contexts. This attribute is primarily used for constifying large traits such as `Iterator` without having to make all From 666f6480639c7f8ac32ef18d8d8144d0101350b5 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:54:41 +0200 Subject: [PATCH 1109/1309] missing pause --- src/doc/rustc-dev-guide/src/effects.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/effects.md b/src/doc/rustc-dev-guide/src/effects.md index 55e00d4acfad3..f6a11b435ad32 100644 --- a/src/doc/rustc-dev-guide/src/effects.md +++ b/src/doc/rustc-dev-guide/src/effects.md @@ -4,7 +4,7 @@ [`HostEffectPredicate`]s are a kind of predicate from `[const] Tr` or `const Tr` bounds. It has a trait reference, -and a `constness` which could be `Maybe` or `Const` depending on the bound. +and a `constness` which could be `Maybe` or `Const`, depending on the bound. Because `[const] Tr`, or rather `Maybe` bounds apply differently based on whichever contexts they are in, they have different behavior than normal bounds. From b3bd159fb9c6e8ac2e85b2eea1c4f03c67f7c212 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:54:46 +0200 Subject: [PATCH 1110/1309] sembr src/query.md --- src/doc/rustc-dev-guide/src/query.md | 38 +++++++++++++++------------- 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 471b445c14d5a..19145a5a7ad0f 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -9,16 +9,17 @@ Instead of entirely independent passes (parsing, type-checking, etc.), a set of function-like *queries* compute information about the input source. For example, -there is a query called `type_of` that, given the [`DefId`] of -some item, will compute the type of that item and return it to you. +there is a query called `type_of` that, given the [`DefId`] of some item, +will compute the type of that item and return it to you. [`DefId`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/def_id/struct.DefId.html [Overview of the compiler]: overview.md#queries -Query execution is *memoized*. The first time you invoke a -query, it will go do the computation, but the next time, the result is returned from a hashtable. -Moreover, query execution fits nicely into -*incremental computation*; the idea is roughly that, when you invoke a +Query execution is *memoized*. +The first time you invoke a query, +it will go do the computation, but the next time, the result is returned from a hashtable. +Moreover, query execution fits nicely into *incremental computation*; the idea is roughly that, +when you invoke a query, the result *may* be returned to you by loading stored data from disk.[^incr-comp-detail] When we execute a query, @@ -39,8 +40,8 @@ For example: - That query in turn would invoke something asking for the HIR. - This keeps going further and further back until we wind up doing the actual parsing. -Although this vision is not fully realized, large sections of the -compiler (for example, generating [MIR]) currently work exactly like this. +Although this vision is not fully realized, large sections of the compiler (for example, +generating [MIR]) currently work exactly like this. [^incr-comp-detail]: The [Incremental compilation in detail] chapter gives a more in-depth description of what queries are and how they work. @@ -65,22 +66,22 @@ let ty = tcx.type_of(some_def_id); So you may be wondering what happens when you invoke a query method. The answer is that, for each query, the compiler maintains a -cache – if your query has already been executed, then, the answer is -simple: we clone the return value out of the cache and return it +cache – if your query has already been executed, then, +the answer is simple: we clone the return value out of the cache and return it (therefore, you should try to ensure that the return types of queries are cheaply cloneable; insert an `Rc` if necessary). ### Providers -If, however, the query is *not* in the cache, then the compiler will -call the corresponding **provider** function. +If, however, the query is *not* in the cache, +then the compiler will call the corresponding **provider** function. A provider is a function implemented in a specific module and **manually registered** into either the [`Providers`][providers_struct] struct (for local crate queries) or the [`ExternProviders`][extern_providers_struct] struct (for external crate queries) during compiler initialization. The macro system generates both structs, -which act as function tables for all query implementations, where each -field is a function pointer to the actual provider. +which act as function tables for all query implementations, +where each field is a function pointer to the actual provider. **Note:** Both the `Providers` and `ExternProviders` structs are generated by macros and act as function tables for all query implementations. They are **not** Rust traits, but plain structs with function pointer fields. @@ -112,10 +113,11 @@ Providers take two arguments: the `tcx` and the query key. They return the result of the query. N.B. Most of the `rustc_*` crates only provide **local -providers**. Almost all **extern providers** wind up going through the -[`rustc_metadata` crate][rustc_metadata], which loads the information from the crate metadata. -But in some cases there are crates that -provide queries for *both* local and external crates, in which case +providers**. +Almost all **extern providers** wind up going through the [`rustc_metadata` crate][rustc_metadata], +which loads the information from the crate metadata. +But in some cases there are crates that provide queries for *both* local and external crates, +in which case they define both a `provide` and a `provide_extern` function, through [`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke. From 954e7c047db10a8b0501b439a6dae5fe061fb736 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:56:54 +0200 Subject: [PATCH 1111/1309] reflow src/query.md --- src/doc/rustc-dev-guide/src/query.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/query.md b/src/doc/rustc-dev-guide/src/query.md index 19145a5a7ad0f..a4b9eef02f13a 100644 --- a/src/doc/rustc-dev-guide/src/query.md +++ b/src/doc/rustc-dev-guide/src/query.md @@ -19,8 +19,8 @@ Query execution is *memoized*. The first time you invoke a query, it will go do the computation, but the next time, the result is returned from a hashtable. Moreover, query execution fits nicely into *incremental computation*; the idea is roughly that, -when you invoke a -query, the result *may* be returned to you by loading stored data from disk.[^incr-comp-detail] +when you invoke a query, +the result *may* be returned to you by loading stored data from disk.[^incr-comp-detail] When we execute a query, we also discover (at runtime!) what other queries it depends on. @@ -67,8 +67,8 @@ let ty = tcx.type_of(some_def_id); So you may be wondering what happens when you invoke a query method. The answer is that, for each query, the compiler maintains a cache – if your query has already been executed, then, -the answer is simple: we clone the return value out of the cache and return it -(therefore, you should try to ensure that the return types of queries +the answer is simple: we clone the return value out of the cache and return it (therefore, +you should try to ensure that the return types of queries are cheaply cloneable; insert an `Rc` if necessary). ### Providers @@ -117,8 +117,7 @@ providers**. Almost all **extern providers** wind up going through the [`rustc_metadata` crate][rustc_metadata], which loads the information from the crate metadata. But in some cases there are crates that provide queries for *both* local and external crates, -in which case -they define both a `provide` and a `provide_extern` function, through +in which case they define both a `provide` and a `provide_extern` function, through [`wasm_import_module_map`][wasm_import_module_map], that `rustc_driver` can invoke. [rustc_metadata]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_metadata/index.html From 6bc3868e7263a3602cd17364711dcf906da57ec4 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 19:57:15 +0200 Subject: [PATCH 1112/1309] sembr src/ty.md --- src/doc/rustc-dev-guide/src/ty.md | 88 +++++++++++++++---------------- 1 file changed, 44 insertions(+), 44 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index ef2ea37b7ca46..b9776523dd07f 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -1,8 +1,8 @@ # The `ty` module: representing types The `ty` module defines how the Rust compiler represents types internally. -It also defines the -*typing context* (`tcx` or `TyCtxt`), which is the central data structure in the compiler. +It also defines the *typing context* (`tcx` or `TyCtxt`), +which is the central data structure in the compiler. ## `ty::Ty` @@ -22,12 +22,13 @@ The distinction is important, so we will discuss it first before going into the The HIR in rustc can be thought of as the high-level intermediate representation. It is more or less the AST (see [this chapter](hir.md)) as it represents the -syntax that the user wrote, and is obtained after parsing and some *desugaring*. It has a -representation of types, but in reality it reflects more of what the user wrote, that is, what they +syntax that the user wrote, and is obtained after parsing and some *desugaring*. +It has a representation of types, +but in reality it reflects more of what the user wrote, that is, what they wrote so as to represent that type. -In contrast, `ty::Ty` represents the semantics of a type, that is, the *meaning* of what the user -wrote. +In contrast, `ty::Ty` represents the semantics of a type, that is, +the *meaning* of what the user wrote. For example, `rustc_hir::Ty` would record the fact that a user used the name `u32` twice in their program, but the `ty::Ty` would record the fact that both usages refer to the same type. @@ -46,16 +47,16 @@ That is, they have two different [`Span`s][span] (locations). **Example: `fn foo(x: &u32) -> &u32`** In addition, HIR might have information left out. -This type -`&u32` is incomplete, since in the full Rust type there is actually a lifetime, but we didn’t need +This type `&u32` is incomplete, +since in the full Rust type there is actually a lifetime, but we didn’t need to write those lifetimes. There are also some elision rules that insert information. The result may look like `fn foo<'a>(x: &'a u32) -> &'a u32`. In the HIR level, these things are not spelled out and you can say the picture is rather incomplete. However, at the `ty::Ty` level, these details are added and it is complete. -Moreover, we will have -exactly one `ty::Ty` for a given type, like `u32`, and that `ty::Ty` is used for all `u32`s in the +Moreover, we will have exactly one `ty::Ty` for a given type, +like `u32`, and that `ty::Ty` is used for all `u32`s in the whole program, not a specific usage, unlike `rustc_hir::Ty`. Here is a summary: @@ -74,8 +75,8 @@ Here is a summary: HIR is built directly from the AST, so it happens before any `ty::Ty` is produced. After HIR is built, some basic type inference and type checking is done. -During the type inference, we -figure out what the `ty::Ty` of everything is and we also check if the type of something is +During the type inference, +we figure out what the `ty::Ty` of everything is and we also check if the type of something is ambiguous. The `ty::Ty` is then used for type checking while making sure everything has the expected type. The [`hir_ty_lowering` module][hir_ty_lowering] is where the code responsible for @@ -102,8 +103,8 @@ Consider another example: `fn foo(x: T) -> u32`. Suppose that someone invokes `foo::(0)`. This means that `T` and `u32` (in this invocation) actually turns out to be the same type, so we would eventually end up with the same `ty::Ty` in the end, but we have distinct `rustc_hir::Ty`. -(This is a bit over-simplified, though, since during type checking, we would check the function -generically and would still have a `T` distinct from `u32`. +(This is a bit over-simplified, though, since during type checking, +we would check the function generically and would still have a `T` distinct from `u32`. Later, when doing code generation, we would always be handling "monomorphized" (fully substituted) versions of each function, and hence we would know what `T` represents (and specifically that it is `u32`).) @@ -125,8 +126,8 @@ Here the type `X` will vary depending on context, clearly. If you look at the `rustc_hir::Ty`, you will get back that `X` is an alias in both cases (though it will be mapped via name resolution to distinct aliases). -But if you look at the `ty::Ty` signature, it will be either `fn(u32) -> u32` -or `fn(i32) -> i32` (with type aliases fully expanded). +But if you look at the `ty::Ty` signature, +it will be either `fn(u32) -> u32` or `fn(i32) -> i32` (with type aliases fully expanded). ## `ty::Ty` implementation @@ -140,8 +141,7 @@ We always hide them within `Ty` and skip over it via `Deref` impls or methods. They are convenient hacks for efficiency and summarize information about the type that we may want to know, but they don’t come into the picture as much here. -Finally, [`Interned`](./memory.md) allows the `ty::Ty` to be a thin pointer-like -type. +Finally, [`Interned`](./memory.md) allows the `ty::Ty` to be a thin pointer-like type. This allows us to do cheap comparisons for equality, along with the other benefits of interning. [tykind]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_type_ir/ty_kind/enum.TyKind.html @@ -170,8 +170,8 @@ You can also find various common types in the `tcx` itself by accessing its fiel ## Comparing types Because types are interned, it is possible to compare them for equality efficiently using `==` -– however, this is almost never what you want to do unless you happen to be hashing and looking -for duplicates. +– however, +this is almost never what you want to do unless you happen to be hashing and looking for duplicates. This is because often in Rust there are multiple ways to represent the same type, particularly once inference is involved. @@ -182,11 +182,11 @@ diagnostics code). `==` on them will return `false` though, since they are different types. The simplest way to compare two types correctly requires an inference context (`infcx`). -If you have one, you can use `infcx.can_eq(param_env, ty1, ty2)` -to check whether the types can be made equal. +If you have one, you can use `infcx.can_eq(param_env, ty1, +ty2)` to check whether the types can be made equal. This is typically what you want to check during diagnostics, which is concerned with questions such -as whether two types can be assigned to each other, not whether they're represented identically in -the compiler's type-checking layer. +as whether two types can be assigned to each other, +not whether they're represented identically in the compiler's type-checking layer. When working with an inference context, you have to be careful to ensure that potential inference variables inside the types actually belong to that inference context. @@ -199,24 +199,24 @@ To compare them correctly, you have to normalize the types first. This is primarily a concern during HIR type checking and with all types from a `TyCtxt` query (for example from `tcx.type_of()`). -When a `FnCtxt` or an `ObligationCtxt` is available during type checking, `.normalize(ty)` -should be used on them to normalize the type. +When a `FnCtxt` or an `ObligationCtxt` is available during type checking, +`.normalize(ty)` should be used on them to normalize the type. After type checking, diagnostics code can use `tcx.normalize_erasing_regions(ty)`. There are also cases where using `==` on `Ty` is fine. -This is, for example, the case in late lints -or after monomorphization, since type checking has been completed, meaning all inference variables +This is, for example, the case in late lints or after monomorphization, +since type checking has been completed, meaning all inference variables are resolved and all regions have been erased. -In these cases, if you know that inference variables -or normalization won't be a concern, `#[allow]` or `#[expect]`ing the lint is recommended. +In these cases, if you know that inference variables or normalization won't be a concern, +`#[allow]` or `#[expect]`ing the lint is recommended. When diagnostics code does not have access to an inference context, it should be threaded through the function calls if one is available in some place (like during type checking). -If no inference context is available at all, then one can be created as described in -[type-inference]. -But this is only useful when the involved types (for example, if -they came from a query like `tcx.type_of()`) are actually substituted with fresh +If no inference context is available at all, +then one can be created as described in [type-inference]. +But this is only useful when the involved types (for example, +if they came from a query like `tcx.type_of()`) are actually substituted with fresh inference variables using [`fresh_args_for_item`]. This can be used to answer questions like "can `Vec` for any `T` be unified with `Vec`?". @@ -237,8 +237,8 @@ fn foo(x: Ty<'tcx>) { } ``` -The `kind` field is of type `TyKind<'tcx>`, which is an enum defining all of the different kinds of -types in the compiler. +The `kind` field is of type `TyKind<'tcx>`, +which is an enum defining all of the different kinds of types in the compiler. > N.B. inspecting the `kind` field on types during type inference can be risky, as there may be > inference variables and other things to consider, or sometimes types are not yet known and will @@ -247,8 +247,8 @@ types in the compiler. There are a lot of related types, and we’ll cover them in time (e.g regions/lifetimes, “substitutions”, etc). -There are many variants on the `TyKind` enum, which you can see by looking at its -[documentation][tykind]. +There are many variants on the `TyKind` enum, +which you can see by looking at its [documentation][tykind]. Here is a sampling: - [**Algebraic Data Types (ADTs)**][kindadt] An [*algebraic data type*][wikiadt] is a `struct`, @@ -264,8 +264,8 @@ Here is a sampling: - [**Array**][kindarray] Corresponds to `[T; n]`. - [**RawPtr**][kindrawptr] Corresponds to `*mut T` or `*const T`. - [**Ref**][kindref] `Ref` stands for safe references, `&'a mut T` or `&'a T`. - `Ref` has some - associated parts, like `Ty<'tcx>` which is the type that the reference references. + `Ref` has some associated parts, + like `Ty<'tcx>` which is the type that the reference references. `Region<'tcx>` is the lifetime or region of the reference and `Mutability` if the reference is mutable or not. - [**Param**][kindparam] Represents a type parameter (e.g. the `T` in `Vec`). @@ -314,15 +314,15 @@ which case the error should've been reported when that error type was produced). It's important to maintain this invariant because the whole point of the `Error` type is to suppress other errors -- i.e., we don't report them. If we were to produce an `Error` type without actually -emitting an error to the user, then this could cause later errors to be suppressed, and the -compilation might inadvertently succeed! +emitting an error to the user, then this could cause later errors to be suppressed, +and the compilation might inadvertently succeed! Sometimes there is a third case. You believe that an error has been reported, but you believe it would've been reported earlier in the compilation, not locally. In that case, you can create a "delayed bug" with [`delayed_bug`] or [`span_delayed_bug`]. -This will make a note that you expect -compilation to yield an error -- if, however, compilation should succeed, then it will trigger a +This will make a note that you expect compilation to yield an error -- if, +however, compilation should succeed, then it will trigger a compiler bug report. [`delayed_bug`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_errors/struct.DiagCtxt.html#method.delayed_bug From d1f4fd32329ac376362da6cb63f3bdb7450361b1 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 20:05:04 +0200 Subject: [PATCH 1113/1309] improve ty.md --- src/doc/rustc-dev-guide/src/ty.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty.md b/src/doc/rustc-dev-guide/src/ty.md index b9776523dd07f..887dd822e6b33 100644 --- a/src/doc/rustc-dev-guide/src/ty.md +++ b/src/doc/rustc-dev-guide/src/ty.md @@ -24,11 +24,11 @@ The HIR in rustc can be thought of as the high-level intermediate representation It is more or less the AST (see [this chapter](hir.md)) as it represents the syntax that the user wrote, and is obtained after parsing and some *desugaring*. It has a representation of types, -but in reality it reflects more of what the user wrote, that is, what they -wrote so as to represent that type. +but in reality, it reflects more of what the user wrote, +so as to represent that type. -In contrast, `ty::Ty` represents the semantics of a type, that is, -the *meaning* of what the user wrote. +In contrast, `ty::Ty` represents the semantics of a type; +that is, the *meaning* of what the user wrote. For example, `rustc_hir::Ty` would record the fact that a user used the name `u32` twice in their program, but the `ty::Ty` would record the fact that both usages refer to the same type. @@ -169,9 +169,9 @@ You can also find various common types in the `tcx` itself by accessing its fiel ## Comparing types -Because types are interned, it is possible to compare them for equality efficiently using `==` -– however, -this is almost never what you want to do unless you happen to be hashing and looking for duplicates. +Because types are interned, it is possible to compare them for equality efficiently using `==`. +However, this is almost never what you want to do, +unless you happen to be hashing and looking for duplicates. This is because often in Rust there are multiple ways to represent the same type, particularly once inference is involved. @@ -182,8 +182,8 @@ diagnostics code). `==` on them will return `false` though, since they are different types. The simplest way to compare two types correctly requires an inference context (`infcx`). -If you have one, you can use `infcx.can_eq(param_env, ty1, -ty2)` to check whether the types can be made equal. +If you have one, +you can use `infcx.can_eq(param_env, ty1, ty2)` to check whether the types can be made equal. This is typically what you want to check during diagnostics, which is concerned with questions such as whether two types can be assigned to each other, not whether they're represented identically in the compiler's type-checking layer. @@ -265,7 +265,7 @@ Here is a sampling: - [**RawPtr**][kindrawptr] Corresponds to `*mut T` or `*const T`. - [**Ref**][kindref] `Ref` stands for safe references, `&'a mut T` or `&'a T`. `Ref` has some associated parts, - like `Ty<'tcx>` which is the type that the reference references. + like `Ty<'tcx>`, which is the type that the reference references. `Region<'tcx>` is the lifetime or region of the reference and `Mutability` if the reference is mutable or not. - [**Param**][kindparam] Represents a type parameter (e.g. the `T` in `Vec`). From 96df2f56cedb8db17a70d01446d37c57559a349c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Wed, 30 Sep 2026 20:11:07 +0200 Subject: [PATCH 1114/1309] extraneous --- src/doc/rustc-dev-guide/src/const-generics.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/const-generics.md b/src/doc/rustc-dev-guide/src/const-generics.md index a5c7ec506be4c..2738782db9e48 100644 --- a/src/doc/rustc-dev-guide/src/const-generics.md +++ b/src/doc/rustc-dev-guide/src/const-generics.md @@ -83,7 +83,7 @@ When we go through HIR ty lowering for the array type in `Alias`, we will lower This will effectively set the type of the `ANON` const item during some later part of the compiler rather than when constructing the HIR. After all of this desugaring has taken place the final representation in the type system (ie as a `ty::Const`) is a `ConstKind::Alias` with the `DefId` of the `AnonConst`. -This is equivalent to how we would representa a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `gca_generic_const_args` is enabled). +This is equivalent to how we would represent a usage of an actual const item if we were to represent them without going through an anon const (e.g. when `gca_generic_const_args` is enabled). This allows the representation for const "aliases" to be the same as the representation of `TyKind::Alias`. Having a proper HIR body also allows for a *lot* of code re-use, e.g. we can reuse HIR typechecking and all of the lowering steps to MIR where we can then reuse const eval. From 109c9176424c1b03e00db6ee5a1b6cc2100c061c Mon Sep 17 00:00:00 2001 From: Lucas Sunsi Abreu Date: Thu, 17 Sep 2026 10:55:08 -0300 Subject: [PATCH 1115/1309] Fix ICE for ambiguous candidates on method probing The ICE was caused because the code assumed the import_ids would always be the same for all candidates, but it's not true. Sometimes the candidate is ambiguous with import_ids to be logged and sometimes the candidate is not ambigous and does not have the ids. Mixing the two (flag = true, without import_ids) ICEs. Co-authored-by: Philip Sampaio --- compiler/rustc_hir_typeck/src/method/probe.rs | 16 ++++++++++------ .../ambiguous-trait-with-mixed-import-paths.rs | 2 ++ ...mbiguous-trait-with-mixed-import-paths.stderr | 16 ++++++++++++++++ 3 files changed, 28 insertions(+), 6 deletions(-) create mode 100644 tests/ui/imports/ambiguous-trait-with-mixed-import-paths.stderr diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 02b3255e795ac..edfda911a0b98 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -2383,18 +2383,22 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> { } } - // They are all the same, so if any of them is ambiguous, we report the pick as ambiguous. - let is_ambiguously_imported = probes.iter().any(|(p, _)| match p.kind { - TraitCandidate { is_ambiguously_imported, .. } => is_ambiguously_imported, - _ => false, + // We try and find the ambiguous candidate in order to report the pick as ambiguous. + let ambiguous_candidate = probes.iter().find_map(|(p, _)| match p.kind { + TraitCandidate { is_ambiguously_imported: true, .. } => Some(p), + _ => None, }); + // If there isn't any, then we just use the first probe. + let (is_ambiguously_imported, candidate) = + ambiguous_candidate.map(|c| (true, *c)).unwrap_or_else(|| (false, probes[0].0)); + // FIXME: check the return type here somehow. // If so, just use this trait and call it a day. Some(Pick { - item: probes[0].0.item, + item: candidate.item, kind: TraitPick { is_ambiguously_imported }, - import_ids: probes[0].0.import_ids, + import_ids: candidate.import_ids, autoderefs: 0, autoref_or_ptr_adjustment: None, self_ty, diff --git a/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs index acc97a2491f8e..08f57d7feb7a3 100644 --- a/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs +++ b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.rs @@ -21,6 +21,8 @@ impl vis1::Visitor for Impl { fn visit_c(&self) { self.visit_b(); + //~^ WARN: use of ambiguously glob imported trait `Visitor` [ambiguous_glob_imported_traits] + //~| WARN: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! } } diff --git a/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.stderr b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.stderr new file mode 100644 index 0000000000000..d65f941f03671 --- /dev/null +++ b/tests/ui/imports/ambiguous-trait-with-mixed-import-paths.stderr @@ -0,0 +1,16 @@ +warning: use of ambiguously glob imported trait `Visitor` + --> $DIR/ambiguous-trait-with-mixed-import-paths.rs:23:14 + | +LL | use crate::{vis1::*, vis2::*}; + | ---- `Visitor` imported ambiguously here +... +LL | self.visit_b(); + | ^^^^^^^ + | + = help: import `Visitor` explicitly + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #152822 + = note: `#[warn(ambiguous_glob_imported_traits)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: 1 warning emitted + From 81b9a584dadce87f489ea638f77b20bb7da67307 Mon Sep 17 00:00:00 2001 From: Crystal Durham Date: Wed, 30 Sep 2026 14:43:13 -0500 Subject: [PATCH 1116/1309] remove dead cfg_select! arm --- library/std/src/sys/fs/mod.rs | 3 --- 1 file changed, 3 deletions(-) diff --git a/library/std/src/sys/fs/mod.rs b/library/std/src/sys/fs/mod.rs index 93b05b9859d28..ca5c28dcd88bd 100644 --- a/library/std/src/sys/fs/mod.rs +++ b/library/std/src/sys/fs/mod.rs @@ -47,9 +47,6 @@ cfg_select! { mod vexos; use vexos as imp; } - target_vendor = "apple" => { - mod darwin; - } _ => { mod unsupported; use unsupported as imp; From e7d3ffc2561a2eb564c6812d7a353caad28f5bdf Mon Sep 17 00:00:00 2001 From: Ian McCormack Date: Tue, 29 Sep 2026 15:11:37 -0400 Subject: [PATCH 1117/1309] Avoid long sequences of retags by emitting a loop. --- compiler/rustc_codegen_ssa/src/mir/retag.rs | 172 ++++++++++++++++---- 1 file changed, 139 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_codegen_ssa/src/mir/retag.rs b/compiler/rustc_codegen_ssa/src/mir/retag.rs index a71a57f02c82a..6a3316fa93992 100644 --- a/compiler/rustc_codegen_ssa/src/mir/retag.rs +++ b/compiler/rustc_codegen_ssa/src/mir/retag.rs @@ -14,9 +14,10 @@ use rustc_middle::mir::{Rvalue, WithRetag}; use rustc_middle::ty::layout::{HasTypingEnv, TyAndLayout}; use rustc_middle::ty::{self, Ty}; -use crate::mir::FunctionCx; +use crate::common::IntPredicate; use crate::mir::operand::{OperandRef, OperandRefBuilder, OperandValue}; use crate::mir::place::PlaceRef; +use crate::mir::{FunctionCx, bug}; use crate::traits::{ BaseTypeCodegenMethods, BuilderMethods, ConstCodegenMethods, StaticCodegenMethods, }; @@ -35,17 +36,31 @@ enum RetagPlan { /// Indicates that one or more fields or variants of this type /// contain pointers that need to be retagged. Recurse { - field_plans: FxIndexMap>, + field_plans: Option>, variant_plans: FxIndexMap>, }, } +/// The layout of the fields that need to be retagged. +/// +/// This mirrors [`FieldsShape`] but excludes unions, +/// which are never retagged, and primitives, which fall +/// into [`RetagPlan::EmitRetag`]. +#[derive(Debug)] +enum RetagFields { + Arbitrary(FxIndexMap>), + Array(Box>), +} + impl RetagPlan { /// A helper function to move a [`RetagPlan`] into a particular field. fn for_field(self, ix: FieldIdx) -> Self { let mut field_plans = FxIndexMap::default(); field_plans.insert(ix, self); - RetagPlan::Recurse { field_plans, variant_plans: FxIndexMap::default() } + RetagPlan::Recurse { + field_plans: Some(RetagFields::Arbitrary(field_plans)), + variant_plans: FxIndexMap::default(), + } } } @@ -84,21 +99,27 @@ impl<'a, 'tcx, V> RetagPlan { layout: TyAndLayout<'tcx>, is_fn_entry: bool, ) -> Option> { - let mut field_plans = FxIndexMap::default(); - let mut variant_plans = FxIndexMap::default(); - - match &layout.fields { - FieldsShape::Union(_) | FieldsShape::Primitive => {} - _ => { + let field_plans = match &layout.fields { + FieldsShape::Union(_) | FieldsShape::Primitive => None, + FieldsShape::Arbitrary { .. } => { + let mut field_plans = FxIndexMap::default(); for ix in layout.fields.index_by_increasing_offset() { let field_layout = layout.field(bx, ix); if let Some(plan) = Self::build(bx, field_layout, is_fn_entry) { field_plans.insert(FieldIdx::from_usize(ix), plan); } } + (!field_plans.is_empty()).then_some(RetagFields::Arbitrary(field_plans)) } - } + FieldsShape::Array { count, .. } if *count > 0 => { + let field_layout = layout.field(bx, 0); + Self::build(bx, field_layout, is_fn_entry) + .map(|plan| RetagFields::Array(Box::new(plan))) + } + FieldsShape::Array { .. } => None, + }; + let mut variant_plans = FxIndexMap::default(); match &layout.variants { Variants::Single { .. } | Variants::Empty => {} Variants::Multiple { variants, .. } => { @@ -111,7 +132,7 @@ impl<'a, 'tcx, V> RetagPlan { } } - (!field_plans.is_empty() || !variant_plans.is_empty()) + (field_plans.is_some() || !variant_plans.is_empty()) .then(|| RetagPlan::Recurse { field_plans, variant_plans }) } @@ -157,8 +178,10 @@ impl<'a, 'tcx, V> RetagPlan { field_plans.insert(FieldIdx::ONE, plan); } - (!field_plans.is_empty()) - .then(|| RetagPlan::Recurse { field_plans, variant_plans: FxIndexMap::default() }) + (!field_plans.is_empty()).then(|| RetagPlan::Recurse { + field_plans: Some(RetagFields::Arbitrary(field_plans)), + variant_plans: FxIndexMap::default(), + }) } /// Determines if a pointer needs to be retagged, when it points to @@ -418,21 +441,38 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } RetagPlan::Recurse { field_plans, variant_plans } => { let layout = curr_operand.layout; - for (ix, plan) in field_plans { - let inner_offset = layout.fields.offset(ix.as_usize()); - let field_offset = offset + inner_offset; - - let field_layout = curr_operand.layout.field(bx, ix.index()); - // Part of https://github.com/rust-lang/compiler-team/issues/838 - if curr_operand.layout.is_ssa_standalone() && !field_layout.is_ssa_standalone() - { - // FIXME: support vector types, requires insert_element as part of cg-ssa - // FIXME: Nothing should be looking at the *array* inside a `repr(simd)` type, - // as that array doesn't really exist. Perhaps this should be a `bug!`, - // with simd types handled before getting here? - } else { - let field_operand = curr_operand.extract_field(self, bx, ix.as_usize()); - self.retag_operand(bx, &plan, field_operand, builder, field_offset); + if let Some(plans) = field_plans { + let mut retag_field = |ix: FieldIdx, plan: &RetagPlan| { + let inner_offset = layout.fields.offset(ix.as_usize()); + let field_offset = offset + inner_offset; + let field_layout = curr_operand.layout.field(bx, ix.index()); + if curr_operand.layout.is_ssa_standalone() + && !field_layout.is_ssa_standalone() + { + // FIXME: Nothing should be looking at the *array* inside a `repr(simd)` type, + // as that array doesn't really exist. Perhaps this should be a `bug!`, + // with simd types handled before getting here? + } else { + let field_operand = curr_operand.extract_field(self, bx, ix.as_usize()); + self.retag_operand(bx, plan, field_operand, builder, field_offset); + } + }; + + match plans { + RetagFields::Arbitrary(field_plans) => { + for (ix, plan) in field_plans { + retag_field(*ix, plan); + } + } + RetagFields::Array(plan) => { + let FieldsShape::Array { count, .. } = layout.fields else { + bug!("Expected `FieldsShape::Array` but found {:?}", layout.fields); + }; + for idx in 0..count { + let idx = FieldIdx::from_usize(idx as usize); + retag_field(idx, plan) + } + } } } @@ -449,8 +489,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { self.retag_operand(bx, plan, variant_op, builder, offset); } } else { - // We create a temporary place to store the operand, because its value will differ - // depending on the variant that we have. + // We create a temporary place to store the operand, because its + // value will differ depending on the variant that we have. let scratch = PlaceRef::alloca(bx, curr_operand.layout); scratch.storage_live(bx); curr_operand.store_with_annotation(bx, scratch); @@ -487,9 +527,33 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.retag_mem(place.val.llval, info); } RetagPlan::Recurse { field_plans, variant_plans } => { - for (ix, plan) in field_plans { - let field_place = place.project_field(bx, ix.as_usize()); - self.retag_place(bx, &plan, field_place); + if let Some(field_plans) = field_plans { + let mut retag_field = |ix: FieldIdx, plan: &RetagPlan| { + let field_place = place.project_field(bx, ix.as_usize()); + self.retag_place(bx, plan, field_place); + }; + match field_plans { + RetagFields::Arbitrary(fields) => { + for (ix, plan) in fields { + retag_field(*ix, plan); + } + } + RetagFields::Array(plan) => { + let FieldsShape::Array { count, .. } = place.layout.fields else { + bug!( + "Expected `FieldsShape::Array` but found {:?}", + place.layout.fields + ); + }; + // When an array of N references needs to be retagged (e.g. `[&T; N]`), + // it is more efficient to emit a loop for large values of N than + // to emit N retags in succession. + within_loop(bx, count, |bx: &mut Bx, ix: Bx::Value| { + let field_place = place.project_index(bx, ix); + self.retag_place(bx, plan, field_place); + }); + } + } } if !variant_plans.is_empty() { let operand = bx.load_operand(place); @@ -534,3 +598,45 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { bx.switch_to_block(join_block); } } + +/// Creates a simple loop, iterating the specified number of times. +/// The dynamic value of the loop counter is passed as an argument +/// to the closure. +fn within_loop<'a, 'tcx, F, Bx: BuilderMethods<'a, 'tcx>>(bx: &mut Bx, max_iter: u64, mut op: F) +where + F: FnMut(&mut Bx, Bx::Value), +{ + // Avoid emitting a no-op loop + if max_iter == 0 { + return; + } + + // Initialize the loop counter to zero. + let counter_layout = bx.layout_of(bx.tcx().types.usize); + let counter_alloca = PlaceRef::alloca(bx, counter_layout); + counter_alloca.storage_live(bx); + bx.store_to_place(bx.const_usize(0), counter_alloca.val); + + // Jump to a new block for the body of the loop. + let loop_body = bx.append_sibling_block("retag_loop"); + bx.br(loop_body); + + bx.switch_to_block(loop_body); + + // Load the value of the counter, and pass it to the closure. + let curr_count = bx.load_from_place(bx.type_isize(), counter_alloca.val); + op(bx, curr_count); + + let next_count = bx.unchecked_uadd(curr_count, bx.const_usize(1)); + bx.store_to_place(next_count, counter_alloca.val); + + // If the next count is equal to the maximum number of + // iterations, then exit the loop. + let max_count = bx.const_usize(max_iter); + let loop_exit = bx.append_sibling_block("retag_loop_exit"); + let should_exit_loop = bx.icmp(IntPredicate::IntEQ, next_count, max_count); + bx.cond_br(should_exit_loop, loop_exit, loop_body); + + bx.switch_to_block(loop_exit); + counter_alloca.storage_dead(bx); +} From 262fa3180187370feae0ce7b5b066fb64f65c443 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 21:55:52 +0000 Subject: [PATCH 1118/1309] Provide more context on "not general enough" error Point at the source bound that was unmet when a HRTB is unmet. ``` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | LL | fn tuple_one() | --------- due to a where-clause on `tuple_one`... LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` ... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` ``` This increases the size of `ConstraintCategory`, which might be a perf regression. --- .../src/diagnostics/explain_borrow.rs | 2 +- .../src/diagnostics/region_errors.rs | 2 +- compiler/rustc_borrowck/src/lib.rs | 2 +- .../rustc_borrowck/src/region_infer/mod.rs | 4 +- .../src/region_infer/region_context.rs | 2 +- .../src/type_check/canonical.rs | 6 +- compiler/rustc_infer/src/infer/mod.rs | 12 +-- compiler/rustc_middle/src/mir/query.rs | 3 +- compiler/rustc_middle/src/traits/mod.rs | 6 +- .../rustc_trait_selection/src/diagnostics.rs | 2 +- .../nice_region_error/placeholder_error.rs | 43 +++++++++- .../src/error_reporting/infer/region.rs | 4 +- .../src/error_reporting/traits/suggestions.rs | 15 +++- .../traits/query/type_op/ascribe_user_type.rs | 2 +- .../associated-types-eq-hr.stderr | 81 +++++++++++++++---- ...outine-auto-trait-span-issue-155880.stderr | 9 ++- ...olved-typeck-results.no_assumptions.stderr | 18 ++++- ...ranked-auto-trait-12.no_assumptions.stderr | 9 ++- ...er-ranked-auto-trait-13.assumptions.stderr | 37 ++++++--- ...ranked-auto-trait-13.no_assumptions.stderr | 56 +++++++++---- ...ranked-auto-trait-15.no_assumptions.stderr | 18 ++++- ...er-ranked-auto-trait-16.assumptions.stderr | 18 ++++- ...ranked-auto-trait-16.no_assumptions.stderr | 18 ++++- ...-ranked-auto-trait-5.no_assumptions.stderr | 10 ++- .../issue-110963-early.no_assumptions.stderr | 20 ++++- ...ation-not-general-enough-ice-133252.stderr | 9 ++- ...n-with-leaking-placeholders.current.stderr | 10 ++- ...rtb-closure-suggest-type-annotation.stderr | 21 +++-- tests/ui/coroutine/auto-trait-regions.stderr | 18 ++++- .../ui/coroutine/resume-arg-late-bound.stderr | 9 ++- ...ot-checked-with-right-substitutions.stderr | 15 +++- ...hr-fn-ptr-trait-impl-mismatch-29061.stderr | 27 +++++-- ...tb-associated-type-leak-check-55731.stderr | 10 ++- ...n-ptr-impl-not-general-enough-57936.stderr | 9 ++- .../trait-bounds/hrtb-conflate-regions.stderr | 18 ++++- ...b-exists-forall-trait-contravariant.stderr | 10 ++- .../hrtb-exists-forall-trait-covariant.stderr | 10 ++- .../hrtb-exists-forall-trait-invariant.stderr | 10 ++- .../trait-bounds/hrtb-just-for-static.stderr | 9 ++- .../hrtb-perfect-forwarding.stderr | 10 ++- .../trait-bounds/issue-46989.stderr | 9 ++- .../trait-bounds/issue-59311.stderr | 34 ++++---- .../normalize-under-binder/issue-71955.stderr | 42 +++++++--- tests/ui/lifetimes/issue-105675.stderr | 54 ++++++++++--- tests/ui/lifetimes/issue-79187-2.stderr | 18 ++++- tests/ui/lifetimes/issue-79187.stderr | 18 ++++- .../lifetime-errors/issue_74400.stderr | 16 +++- .../closure-arg-type-mismatch.stderr | 18 ++++- .../closure-mismatch.current.stderr | 36 +++++++-- tests/ui/nll/ice-106874.stderr | 66 ++++++++++----- tests/ui/nll/issue-54302-cases.stderr | 28 +++++-- ...missing-universe-cause-issue-114907.stderr | 37 ++++++--- ...insensitive-scopes-issue-117146.nll.stderr | 18 ++++- ...sitive-scopes-issue-117146.polonius.stderr | 18 ++++- .../impl-fn-ignore-binder-via-bottom.stderr | 16 ++-- ...n-termination-lifetime-issue-148421.stderr | 5 ++ tests/ui/unboxed-closures/issue-30906.stderr | 9 ++- .../ui/where-clauses/where-for-self-2.stderr | 10 ++- 58 files changed, 793 insertions(+), 253 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs index 7537e2f9f1495..2bc361968a761 100644 --- a/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs +++ b/compiler/rustc_borrowck/src/diagnostics/explain_borrow.rs @@ -415,7 +415,7 @@ impl<'tcx> BorrowExplanation<'tcx> { let mut preds = path .iter() .filter_map(|constraint| match constraint.category { - ConstraintCategory::Predicate(pred) if !pred.is_dummy() => Some(pred), + ConstraintCategory::Predicate(pred, _) if !pred.is_dummy() => Some(pred), _ => None, }) .collect::>(); diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 0b9615634fe1e..c101191102979 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -58,7 +58,7 @@ impl<'tcx> ConstraintDescription for ConstraintCategory<'tcx> { ConstraintCategory::ClosureUpvar(_) => "closure capture ", ConstraintCategory::Usage => "this usage ", ConstraintCategory::SolverRegionConstraint(_) - | ConstraintCategory::Predicate(_) + | ConstraintCategory::Predicate(_, _) | ConstraintCategory::Boring | ConstraintCategory::BoringNoLocation | ConstraintCategory::Internal diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index c35c7ab311572..39361a886bd77 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -232,7 +232,7 @@ pub struct ClosureOutlivesRequirement<'tcx> { // Make sure this enum doesn't unintentionally grow #[cfg(target_pointer_width = "64")] -rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 16); +rustc_data_structures::static_assert_size!(ConstraintCategory<'_>, 24); /// The subject of a `ClosureOutlivesRequirement` -- that is, the thing /// that must outlive some region. diff --git a/compiler/rustc_borrowck/src/region_infer/mod.rs b/compiler/rustc_borrowck/src/region_infer/mod.rs index b547d24c7198c..60b258eca80df 100644 --- a/compiler/rustc_borrowck/src/region_infer/mod.rs +++ b/compiler/rustc_borrowck/src/region_infer/mod.rs @@ -275,11 +275,11 @@ impl<'tcx> BestBlame<'tcx> { .path .iter() .find_map(|constraint| { - if let ConstraintCategory::Predicate(predicate_span) = constraint.category { + if let ConstraintCategory::Predicate(predicate_span, def_id) = constraint.category { // We currently do not store the `DefId` in the `ConstraintCategory` // for performances reasons. The error reporting code used by NLL only // uses the span, so this doesn't cause any problems at the moment. - Some(ObligationCauseCode::WhereClause(CRATE_DEF_ID.to_def_id(), predicate_span)) + Some(ObligationCauseCode::WhereClause(def_id, predicate_span)) } else { None } diff --git a/compiler/rustc_borrowck/src/region_infer/region_context.rs b/compiler/rustc_borrowck/src/region_infer/region_context.rs index a6f7c19ff0c17..327acb7da3fb8 100644 --- a/compiler/rustc_borrowck/src/region_infer/region_context.rs +++ b/compiler/rustc_borrowck/src/region_infer/region_context.rs @@ -742,7 +742,7 @@ impl<'tcx> RegionInferenceContextInner<'tcx> { // Generic arguments are unlikely to be what relates regions together ConstraintCategory::TypeAnnotation(AnnotationSource::GenericArg) => 3, // We handle predicates and opaque types specially; don't prioritize them here. - ConstraintCategory::Predicate(_) | ConstraintCategory::OpaqueType => 4, + ConstraintCategory::Predicate(_, _) | ConstraintCategory::OpaqueType => 4, // `Boring` constraints can correspond to user-written code and have useful spans, // but don't provide any other useful information for diagnostics. ConstraintCategory::Boring => 5, diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs index 9e4a39873753c..b295a66ee74ee 100644 --- a/compiler/rustc_borrowck/src/type_check/canonical.rs +++ b/compiler/rustc_borrowck/src/type_check/canonical.rs @@ -142,15 +142,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> { #[instrument(level = "debug", skip(self))] pub(super) fn normalize_and_prove_instantiated_clauses( &mut self, - // Keep this parameter for now, in case we start using - // it in `ConstraintCategory` at some point. - _def_id: DefId, + def_id: DefId, instantiated_clauses: ty::InstantiatedClauses<'tcx>, locations: Locations, ) { for (clause, span) in instantiated_clauses { debug!(?span, ?clause); - let category = ConstraintCategory::Predicate(span); + let category = ConstraintCategory::Predicate(span, def_id); let clause = self.normalize_with_category(clause, locations, category); self.prove_clause(clause, locations, category); } diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs index e02cc9a7acd1f..a7ce6a4353b59 100644 --- a/compiler/rustc_infer/src/infer/mod.rs +++ b/compiler/rustc_infer/src/infer/mod.rs @@ -463,7 +463,7 @@ pub enum SubregionOrigin<'tcx> { trait_item_def_id: DefId, }, - AscribeUserTypeProvePredicate(Span), + AscribeUserTypeProvePredicate(Span, DefId), // FIXME(-Zassumptions-on-binders): this is a temporary hack until we support // proper diagnostics for solver region constraints. @@ -478,7 +478,9 @@ impl<'tcx> SubregionOrigin<'tcx> { pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self { Self::Subtype(type_trace) => type_trace.cause.to_constraint_category(), - Self::AscribeUserTypeProvePredicate(span) => ConstraintCategory::Predicate(*span), + Self::AscribeUserTypeProvePredicate(span, def_id) => { + ConstraintCategory::Predicate(*span, *def_id) + } Self::SolverRegionConstraint(span) => ConstraintCategory::SolverRegionConstraint(*span), _ => ConstraintCategory::BoringNoLocation, } @@ -1840,7 +1842,7 @@ impl<'tcx> SubregionOrigin<'tcx> { SubregionOrigin::Reborrow(a) => a, SubregionOrigin::ReferenceOutlivesReferent(_, a) => a, SubregionOrigin::CompareImplItemObligation { span, .. } => span, - SubregionOrigin::AscribeUserTypeProvePredicate(span) => span, + SubregionOrigin::AscribeUserTypeProvePredicate(span, _) => span, SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => parent.span(), SubregionOrigin::SolverRegionConstraint(a) => a, } @@ -1874,8 +1876,8 @@ impl<'tcx> SubregionOrigin<'tcx> { parent: Box::new(default()), }, - traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span) => { - SubregionOrigin::AscribeUserTypeProvePredicate(span) + traits::ObligationCauseCode::AscribeUserTypeProvePredicate(span, def_id) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span, def_id) } traits::ObligationCauseCode::ObjectTypeBound(ty, _reg) => { diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs index 616b1719359f1..2e84fd80f35e5 100644 --- a/compiler/rustc_middle/src/mir/query.rs +++ b/compiler/rustc_middle/src/mir/query.rs @@ -7,6 +7,7 @@ use rustc_errors::ErrorGuaranteed; use rustc_index::IndexVec; use rustc_index::bit_set::BitMatrix; use rustc_macros::{StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable}; +use rustc_span::def_id::DefId; use rustc_span::{Span, Symbol}; use super::{ConstValue, SourceInfo}; @@ -129,7 +130,7 @@ pub enum ConstraintCategory<'tcx> { /// A constraint from a user-written predicate /// with the provided span, written on the item /// with the given `DefId` - Predicate(Span), + Predicate(Span, DefId), /// A "boring" constraint (caused by the given location) is one that /// the user probably doesn't want to see described in diagnostics, diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index a50c5226c052d..493f6989f342c 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -137,8 +137,8 @@ impl<'tcx> ObligationCause<'tcx> { pub fn to_constraint_category(&self) -> ConstraintCategory<'tcx> { match self.code() { ObligationCauseCode::MatchImpl(cause, _) => cause.to_constraint_category(), - ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span) => { - ConstraintCategory::Predicate(*predicate_span) + ObligationCauseCode::AscribeUserTypeProvePredicate(predicate_span, def_id) => { + ConstraintCategory::Predicate(*predicate_span, *def_id) } _ => ConstraintCategory::BoringNoLocation, } @@ -402,7 +402,7 @@ pub enum ObligationCauseCode<'tcx> { output_ty: Option>, }, - AscribeUserTypeProvePredicate(Span), + AscribeUserTypeProvePredicate(Span, DefId), RustCall, diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 90f6faaad1dc1..d673b99d00d05 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1166,7 +1166,7 @@ impl<'tcx> ActualImplExplNotes<'tcx> { pub(crate) struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label("doesn't satisfy where-clause")] + #[label("unsatisfied where-clause on `{$def_id}`")] pub satisfy_span: Option, #[label("due to a where-clause on `{$def_id}`...")] pub where_span: Option, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index be5c2b3c96915..390e21e34ef4c 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -255,15 +255,43 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { ) -> Diag<'tcx> { let span = cause.span; + let mut code = cause.code(); + loop { + match code { + ObligationCauseCode::MatchImpl(inner_cause, _) => { + code = inner_cause.code(); + } + ObligationCauseCode::ImplDerived(derived) => { + code = &derived.derived.parent_code; + } + ObligationCauseCode::BuiltinDerived(derived) => { + code = &derived.parent_code; + } + ObligationCauseCode::WellFormedDerived(derived) => { + code = &derived.parent_code; + } + ObligationCauseCode::ImplDerivedHost(derived) => { + code = &derived.derived.parent_code; + } + ObligationCauseCode::BuiltinDerivedHost(derived) => { + code = &derived.parent_code; + } + _ => break, + } + } let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = if let ObligationCauseCode::WhereClause(def_id, span) - | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *cause.code() + | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code && def_id != CRATE_DEF_ID.to_def_id() { ( true, Some(span), - Some(self.tcx().def_span(def_id)), + Some( + self.tcx() + .opt_item_ident(def_id) + .map_or_else(|| self.tcx().def_span(def_id), |n| n.span), + ), None, self.tcx().def_path_str(def_id), ) @@ -356,6 +384,17 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut current_code = cause.code(); let mut coroutine_def_id = None; + if cause.body_def_id != CRATE_DEF_ID { + self.cx.note_obligation_cause_code( + cause.body_def_id, + &mut err, + actual_trait_ref, + self.tcx().param_env(cause.body_def_id), + cause.code(), + &mut vec![], + &mut Default::default(), + ); + } loop { match current_code { diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index e708900aad487..d356a62200cfd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -294,7 +294,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { SubregionOrigin::CheckAssociatedTypeBounds { ref parent, .. } => { self.note_region_origin(err, parent); } - SubregionOrigin::AscribeUserTypeProvePredicate(span) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span, _) => { RegionOriginNote::Plain { span, msg: msg!("...so that the where clause holds") } .add_to_diag(err); } @@ -551,7 +551,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); err } - SubregionOrigin::AscribeUserTypeProvePredicate(span) => { + SubregionOrigin::AscribeUserTypeProvePredicate(span, _) => { let instantiated = note_and_explain::RegionExplanation::new( self.tcx, generic_param_scope, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 47d2b7a8c98d5..9219c709eee83 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3832,7 +3832,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { true } - pub(super) fn note_obligation_cause_code( + pub(crate) fn note_obligation_cause_code( &self, body_def_id: LocalDefId, err: &mut Diag<'_>, @@ -3903,7 +3903,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { | ObligationCauseCode::ReturnNoExpression | ObligationCauseCode::Misc | ObligationCauseCode::WellFormed(..) - | ObligationCauseCode::MatchImpl(..) | ObligationCauseCode::ReturnValue(_) | ObligationCauseCode::BlockTailExpression(..) | ObligationCauseCode::AwaitableExpr(_) @@ -4418,6 +4417,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ObligationCauseCode::SharedStatic => { err.note("shared static variables must have a type that implements `Sync`"); } + ObligationCauseCode::MatchImpl(ref cause, _) => { + self.note_obligation_cause_code_inner( + body_def_id, + err, + predicate, + param_env, + &cause.code(), + obligated_types, + seen_requirements, + closure_capture_ty, + ); + } ObligationCauseCode::BuiltinDerived(ref data) => { let parent_trait_ref = self.deeply_resolve_ignoring_regions(data.parent_trait_pred); let ty = parent_trait_ref.skip_binder().self_ty(); diff --git a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs index b4ab3b9729fd3..2fcb7f1741f5a 100644 --- a/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs +++ b/compiler/rustc_trait_selection/src/traits/query/type_op/ascribe_user_type.rs @@ -109,7 +109,7 @@ fn relate_mir_and_user_args<'tcx>( let cause = ObligationCause::new( span, CRATE_DEF_ID, - ObligationCauseCode::AscribeUserTypeProvePredicate(clause_span), + ObligationCauseCode::AscribeUserTypeProvePredicate(clause_span, def_id), ); let instantiated_clause = ocx.normalize(&cause, param_env, instantiated_clause); diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 40a84eb25d384..70596cbab1225 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -43,58 +43,93 @@ LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` +... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` +... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ------------- unsatisfied where-clause on `tuple_one` +... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ------------- unsatisfied where-clause on `tuple_one` +... LL | tuple_one::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` +... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` +... LL | tuple_two::(); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -130,19 +165,31 @@ LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | -------------------------------------------- unsatisfied where-clause on `tuple_four` +... LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four`... +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | -------------------------------------------- unsatisfied where-clause on `tuple_four` +... LL | tuple_four::(); - | ^^^^^^^^^^^^^^^^^^^^^ implementation of `TheTrait` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr index 3048cc1d9c1c3..e7f5413cdaaa0 100644 --- a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -7,10 +7,15 @@ LL | | std::future::ready(x).await LL | | } | |_- this async fn captures a value whose type is not `Send` ... +LL | fn is_send(_: T) {} + | ------- ---- unsatisfied where-clause on `is_send` + | | + | due to a where-clause on `is_send`... +... LL | is_send(outer()) - | ^^^^^^^^^^^^^^^^ implementation of `Send` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...`Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr index 5a5bba352c69b..01b99e203c426 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -1,23 +1,33 @@ error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | +LL | fn send(_: T) {} + | ---- ---- unsatisfied where-clause on `send` + | | + | due to a where-clause on `send`... +... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); - | |______^ implementation of `FnOnce` is not general enough + | |______^ | - = note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | +LL | fn send(_: T) {} + | ---- ---- unsatisfied where-clause on `send` + | | + | due to a where-clause on `send`... +... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); - | |______^ implementation of `FnOnce` is not general enough + | |______^ | - = note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr index 63e71cbc40c75..fd91fd659ac4d 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -1,6 +1,11 @@ error: implementation of `Robot` is not general enough --> $DIR/higher-ranked-auto-trait-12.rs:31:20 | +LL | fn this_is_send(value: T) -> T { + | ------------ ---- unsatisfied where-clause on `this_is_send` + | | + | due to a where-clause on `this_is_send`... +... LL | let _my_task = this_is_send(async move { | ____________________^ LL | | let _my_iter = IRobot { @@ -9,9 +14,9 @@ LL | | robot: source, LL | | }; LL | | yield_now().await; LL | | }); - | |______^ implementation of `Robot` is not general enough + | |______^ | - = note: `Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... + = note: ...`Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot + Send + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr index f69218740dcca..abc8ba5e7afa3 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -1,39 +1,58 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index cfbdaa8ad4beb..7c8edb40ac62f 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -1,60 +1,88 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Callable` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Getter` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Callable` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index e8d1f585f0256..fa6dd575527f8 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | +LL | fn require_send(_x: T) {} + | ------------ ---- unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send`... +... LL | require_send(future); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&Vec,)>` help: consider adding an explicit type annotation to the closure's argument | @@ -14,10 +19,15 @@ LL | for _ in things.iter().map(|n: &Vec| n.iter()).flatten() { error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | +LL | fn require_send(_x: T) {} + | ------------ ---- unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send`... +... LL | require_send(future); - | ^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr index dc6183a45cef5..69e356703c9f0 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -1,23 +1,33 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | +LL | fn assert_send(_: T) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); - | |______^ implementation of `AsyncFnOnce` is not general enough + | |______^ | - = note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | +LL | fn assert_send(_: T) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); - | |______^ implementation of `AsyncFnOnce` is not general enough + | |______^ | - = note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr index dc6183a45cef5..69e356703c9f0 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -1,23 +1,33 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | +LL | fn assert_send(_: T) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); - | |______^ implementation of `AsyncFnOnce` is not general enough + | |______^ | - = note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | +LL | fn assert_send(_: T) {} + | ----------- ---- unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send`... +... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); - | |______^ implementation of `AsyncFnOnce` is not general enough + | |______^ | - = note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index 8fa3c7483c89d..ef743392cb014 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -4,9 +4,15 @@ error: implementation of `Send` is not general enough LL | / assert_send(async { LL | | call_me.call().await; LL | | }); - | |______^ implementation of `Send` is not general enough + | |______^ +... +LL | pub fn assert_send(_future: F) + | ----------- due to a where-clause on `assert_send`... +LL | where +LL | F: Future + Send, + | ---- unsatisfied where-clause on `assert_send` | - = note: `Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... + = note: ...`Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index 6b434ecca0109..be635809f1db7 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -10,9 +10,15 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ implementation of `Send` is not general enough + | |______^ +... +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn`... +LL | where +LL | F: Future + Send + 'static, + | ---- unsatisfied where-clause on `spawn` | - = note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` error: implementation of `Send` is not general enough @@ -27,9 +33,15 @@ LL | | if !hc.check().await { LL | | log_health_check_failure().await; LL | | } LL | | }); - | |______^ implementation of `Send` is not general enough + | |______^ +... +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn`... +LL | where +LL | F: Future + Send + 'static, + | ---- unsatisfied where-clause on `spawn` | - = note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index 7b840d54ed038..b5ea0003b1d63 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -2,9 +2,14 @@ error: implementation of `LoadQuery` is not general enough --> $DIR/implementation-not-general-enough-ice-133252.rs:9:9 | LL | force_send(async_load(¬_static)); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `LoadQuery` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | fn force_send(_: T) {} + | ---------- ---- unsatisfied where-clause on `force_send` + | | + | due to a where-clause on `force_send`... | - = note: `LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... + = note: ...`LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... = note: ...but `LoadQuery<'1>` is actually implemented for the type `&'1 u8`, for some specific lifetime `'1` error[E0597]: `not_static` does not live long enough diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index cdaa16ac9e807..3de229af2a077 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -1,14 +1,20 @@ error: implementation of `Foo` is not general enough --> $DIR/obligation-with-leaking-placeholders.rs:18:5 | +LL | fn needs_foo(_: T) + | --------- due to a where-clause on `needs_foo`... +LL | where +LL | for<'a> Wrap: Foo<'a>, + | ------- unsatisfied where-clause on `needs_foo` +... LL | / needs_foo(|x| { LL | | LL | | LL | | x.to_string(); LL | | }); - | |______^ implementation of `Foo` is not general enough + | |______^ | - = note: `Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... + = note: ...`Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr index 51691c35f795b..b918a5c5179c8 100644 --- a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -1,10 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner`... +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | ----------------------------------------- unsatisfied where-clause on `inner` +... LL | inner(buf, outer_closure) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,12 +20,17 @@ LL | let outer_closure = |buf: &mut [u8]| { error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner`... +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | -------------------- unsatisfied where-clause on `inner` +... LL | inner(buf, outer_closure) - | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | let outer_closure = |buf: &mut [u8]| { diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 75293b2f4a873..566f71d89c28d 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -1,13 +1,18 @@ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | +LL | fn assert_foo(f: T) {} + | ---------- --- unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo`... +... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); - | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + = note: ...`&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error[E0626]: borrow may still be in use when coroutine yields @@ -45,13 +50,18 @@ LL | let generator = #[coroutine] static move || { error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:51:5 | +LL | fn assert_foo(f: T) {} + | ---------- --- unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo`... +... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); - | ^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + = note: ...`Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index 0a6fb8dfcbb6c..bc1f1d29edd61 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -1,10 +1,15 @@ error: implementation of `Coroutine` is not general enough --> $DIR/resume-arg-late-bound.rs:15:5 | +LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} + | ---- ------------------------------- unsatisfied where-clause on `test` + | | + | due to a where-clause on `test`... +... LL | test(gen); - | ^^^^^^^^^ implementation of `Coroutine` is not general enough + | ^^^^^^^^^ | - = note: `{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... + = note: ...`{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 8ae308303b8a3..42aa33c0be186 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -1,11 +1,22 @@ error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | +LL | type Gat<'a>: for<'b> Lengthen>; + | --- ------------------------------- unsatisfied where-clause on `Gat::Gat` + | | + | due to a where-clause on `Gat::Gat`... +... LL | type Gat<'a> = &'a str; - | ^^^^^^^ implementation of `Lengthen` is not general enough + | ^^^^^^^ | - = note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... + = note: ...`Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` +note: required by a bound in `Gat::Gat` + --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 + | +LL | trait Gat { +LL | type Gat<'a>: for<'b> Lengthen>; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr index 19a63fb6fb6a6..7c3fcf47e6a40 100644 --- a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr +++ b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr @@ -1,28 +1,43 @@ error: implementation of `HR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:25:5 | +LL | fn hr(_: T) {} + | -- -- unsatisfied where-clause on `hr` + | | + | due to a where-clause on `hr`... +... LL | hr(not_hr_func); - | ^^^^^^^^^^^^^^^ implementation of `HR` is not general enough + | ^^^^^^^^^^^^^^^ | - = note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... + = note: ...`HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:27:5 | +LL | fn not_hr(_: T) {} + | ------ ----- unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr`... +... LL | not_hr(hr_func); - | ^^^^^^^^^^^^^^^ implementation of `NotHR` is not general enough + | ^^^^^^^^^^^^^^^ | - = note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...`NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:29:5 | +LL | fn not_hr(_: T) {} + | ------ ----- unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr`... +... LL | not_hr(hr_func2); - | ^^^^^^^^^^^^^^^^ implementation of `NotHR` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: `NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` + = note: ...`NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr index 40ac1d9d041be..eaa82c3f77871 100644 --- a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr +++ b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr @@ -1,13 +1,19 @@ error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/hrtb-associated-type-leak-check-55731.rs:49:5 | +LL | fn multi(_reducer: I) + | ----- due to a where-clause on `multi`... +LL | where +LL | I: for<'a> DistributedIteratorMulti<&'a ()>, + | ---------------------------------------- unsatisfied where-clause on `multi` +... LL | / multi(Map { LL | | i: Cloned(PhantomData), LL | | f: X, LL | | }); - | |______^ implementation of `DistributedIteratorMulti` is not general enough + | |______^ | - = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + = note: ...`DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr index c8d88b6243c4f..afed0bca3fffe 100644 --- a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr +++ b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr @@ -14,10 +14,15 @@ LL | trait X { error: implementation of `X` is not general enough --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:26:5 | +LL | fn indirect() { + | -------- - unsatisfied where-clause on `indirect` + | | + | due to a where-clause on `indirect`... +... LL | indirect::(); - | ^^^^^^^^^^^^^^^^^^^^^ implementation of `X` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^ | - = note: `X` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...`X` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 69c58c5919e11..830ed0638a80d 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -1,19 +1,29 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2`... +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | -------------------------------------- unsatisfied where-clause on `want_foo2` +... LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2`... +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | -------------------------------------- unsatisfied where-clause on `want_foo2` +... LL | fn b() { want_foo2::(); } - | ^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index 9697a270b8aa0..28ae64dff3e47 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -1,10 +1,16 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | +LL | fn foo() + | --- due to a where-clause on `foo`... +LL | where +LL | T: Trait fn(&'b u32)>, + | -------------------------- unsatisfied where-clause on `foo` +... LL | foo::<()>(); - | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | ^^^^^^^^^^^ | - = note: `()` must implement `Trait fn(&'b u32)>` + = note: ...`()` must implement `Trait fn(&'b u32)>` = note: ...but it actually implements `Trait`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index 385de795b18f0..4b9d7e1d7109e 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -1,10 +1,16 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-covariant.rs:33:5 | +LL | fn foo() + | --- due to a where-clause on `foo`... +LL | where +LL | T: Trait fn(fn(&'b u32))>, + | ------------------------------ unsatisfied where-clause on `foo` +... LL | foo::<()>(); - | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | ^^^^^^^^^^^ | - = note: `()` must implement `Trait fn(fn(&'b u32))>` + = note: ...`()` must implement `Trait fn(fn(&'b u32))>` = note: ...but it actually implements `Trait`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index cf64c2acdbe9c..45ff3ef758713 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -1,10 +1,16 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | +LL | fn foo() + | --- due to a where-clause on `foo`... +LL | where +LL | T: Trait fn(Cell<&'b u32>)>, + | -------------------------------- unsatisfied where-clause on `foo` +... LL | foo::<()>(); - | ^^^^^^^^^^^ implementation of `Trait` is not general enough + | ^^^^^^^^^^^ | - = note: `()` must implement `Trait fn(Cell<&'b u32>)>` + = note: ...`()` must implement `Trait fn(Cell<&'b u32>)>` = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index 697e85dc8c394..6ba3d119ccb94 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -1,10 +1,15 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | +LL | fn want_hrtb() + | --------- due to a where-clause on `want_hrtb`... +LL | where T : for<'a> Foo<&'a isize> + | ---------------------- unsatisfied where-clause on `want_hrtb` +... LL | want_hrtb::() - | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + = note: ...`StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... = note: ...but it actually implements `Foo<&'static isize>` error: lifetime may not live long enough diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index 327c0faa48287..db22eeb46aef0 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -56,10 +56,16 @@ LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 | +LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) + | ---------------- due to a where-clause on `foo_hrtb_bar_not`... +LL | where +LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | ---------------------- unsatisfied where-clause on `foo_hrtb_bar_not` +... LL | foo_hrtb_bar_not(&mut t); - | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Bar` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + = note: ...`T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` warning: function cannot return without recursing diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index c50e79dd4cc48..e1d900f20ce3b 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -1,10 +1,15 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-46989.rs:38:5 | +LL | fn assert_foo() {} + | ---------- --- unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo`... +... LL | assert_foo::(); - | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` + = note: ...`Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index f8f64dcc545bc..f7b72ec65db3f 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -1,15 +1,14 @@ error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | / pub fn crash(v: &V) -LL | | where -LL | | for<'a> &'a V: Trait + 'static, - | |____________________-----__________- due to a where-clause on `crash`... - | | - | doesn't satisfy where-clause -LL | { -LL | v.t(|| {}); - | ^^^^^^^^^^ +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash`... +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ----- unsatisfied where-clause on `crash` +LL | { +LL | v.t(|| {}); + | ^^^^^^^^^^ | = note: ...`Trait` would have to be implemented for the type `&'a V` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` @@ -17,15 +16,14 @@ LL | v.t(|| {}); error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | / pub fn crash(v: &V) -LL | | where -LL | | for<'a> &'a V: Trait + 'static, - | |____________________-----__________- due to a where-clause on `crash`... - | | - | doesn't satisfy where-clause -LL | { -LL | v.t(|| {}); - | ^^^^^^^^^^ +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash`... +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ----- unsatisfied where-clause on `crash` +LL | { +LL | v.t(|| {}); + | ^^^^^^^^^^ | = note: ...`Trait` would have to be implemented for the type `&'a V` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr index 3c6aab12bf137..fa524168e12e7 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr @@ -1,10 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 | +LL | fn foo( + | --- due to a where-clause on `foo`... +... +LL | F2: FnOnce(&::Output) -> bool + | --------------------------------------- unsatisfied where-clause on `foo` +... LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,12 +20,17 @@ LL | foo(bar, "string", |s: &&str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:45:5 | +LL | fn foo( + | --- due to a where-clause on `foo`... +... +LL | F2: FnOnce(&::Output) -> bool + | ---- unsatisfied where-clause on `foo` +... LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | foo(bar, "string", |s: &&str| s.len() == 5); @@ -28,10 +39,16 @@ LL | foo(bar, "string", |s: &&str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 | +LL | fn foo( + | --- due to a where-clause on `foo`... +... +LL | F2: FnOnce(&::Output) -> bool + | --------------------------------------- unsatisfied where-clause on `foo` +... LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -41,12 +58,17 @@ LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:48:5 | +LL | fn foo( + | --- due to a where-clause on `foo`... +... +LL | F2: FnOnce(&::Output) -> bool + | ---- unsatisfied where-clause on `foo` +... LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index db623761b268e..18960ff575a2a 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding explicit type annotations to the closure's arguments | @@ -14,10 +19,15 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding explicit type annotations to the closure's arguments @@ -28,10 +38,15 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -41,10 +56,15 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -54,10 +74,15 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -68,10 +93,15 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ----------------------- unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 9993de99b9e48..7029eeafef0eb 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187-2.rs:8:5 | +LL | fn take_foo(_: impl Foo) {} + | -------- --- unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo`... +... LL | take_foo(|a| a); - | ^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,10 +19,15 @@ LL | take_foo(|a: &i32| a); error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 | +LL | fn take_foo(_: impl Foo) {} + | -------- --- unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo`... +... LL | take_foo(|a| a); - | ^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index e08400481e470..3dbb6054a7ad3 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ------------ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,10 +19,15 @@ LL | let f = |_: &u32| (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ------------ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing`... +... LL | thing(f); - | ^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^ | - = note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 4dada6ff014ad..3a293cc4b2516 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -45,19 +45,27 @@ LL | fn g(data: &[T]) { error: implementation of `Fn` is not general enough --> $DIR/issue_74400.rs:12:5 | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - ----------- unsatisfied where-clause on `f` + | | + | due to a where-clause on `f`... +... LL | f(data, identity) - | ^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^^^^^^^ | - = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... + = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - due to a where-clause on `f`... - unsatisfied where-clause on `f` +... LL | f(data, identity) - | ^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^ | - = note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index ab52f3d3ee43e..856aba98d1c4c 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -66,19 +66,29 @@ LL | fn baz(_: F) {} error: implementation of `Fn` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | +LL | fn baz(_: F) {} + | --- ------------- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^ | - = note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...`fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | +LL | fn baz(_: F) {} + | --- ------------- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); - | ^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^ | - = note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + = note: ...`fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 82e3e4b0f78f2..0dbefa4b2aa19 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:12:5 | +LL | fn baz(_: T) {} + | --- --- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +... LL | baz(|_| ()); - | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,10 +19,15 @@ LL | baz(|_: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:12:5 | +LL | fn baz(_: T) {} + | --- --- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +... LL | baz(|_| ()); - | ^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,10 +37,15 @@ LL | baz(|_: &()| ()); error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:16:5 | +LL | fn baz(_: T) {} + | --- --- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +... LL | baz(|x| ()); - | ^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -40,10 +55,15 @@ LL | baz(|x: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:16:5 | +LL | fn baz(_: T) {} + | --- --- unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz`... +... LL | baz(|x| ()); - | ^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 45dd1557dd027..60f155eb45eb1 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -2,9 +2,14 @@ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:5 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct B(Rc); + | - - unsatisfied where-clause on `B` + | | + | due to a where-clause on `B`... | - = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` help: consider adding an explicit type annotation to the closure's argument | @@ -15,9 +20,14 @@ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:5 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct B(Rc); + | - - unsatisfied where-clause on `B` + | | + | due to a where-clause on `B`... | - = note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -69,11 +79,17 @@ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL + | + = note: due to a where-clause on `Rc`... + ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL + | + = note: unsatisfied where-clause on `Rc` + | + = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) @@ -83,11 +99,17 @@ error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL + | + = note: due to a where-clause on `Rc`... + ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL + | + = note: unsatisfied where-clause on `Rc` + | + = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) @@ -97,11 +119,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough - | - = note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct B(Rc); + | - - unsatisfied where-clause on `B` + | | + | due to a where-clause on `B`... + | + = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) @@ -111,11 +137,15 @@ error: implementation of `Fn` is not general enough --> $DIR/ice-106874.rs:8:7 | LL | A(B(C::new(D::new(move |st| f(st))))) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Fn` is not general enough - | - = note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | struct B(Rc); + | - - unsatisfied where-clause on `B` + | | + | due to a where-clause on `B`... + | + = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | A(B(C::new(D::new(move |st: &mut V| f(st))))) diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 6e8b69c4beebb..4c5535258f624 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -1,37 +1,49 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | +LL | fn ref_foo(&self) -> &'static T; + | ------- due to a where-clause on `RefFoo::ref_foo`... +... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` | - = note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + = note: ...`Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | +LL | fn ref_foo(&self) -> &'static T; + | ------- due to a where-clause on `RefFoo::ref_foo`... +... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` | - = note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + = note: ...`Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | +LL | fn ref_foo(&self) -> &'static T; + | ------- due to a where-clause on `RefFoo::ref_foo`... +... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` | - = note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + = note: ...`Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | +LL | fn ref_foo(&self) -> &'static T; + | ------- due to a where-clause on `RefFoo::ref_foo`... +... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `Foo` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` | - = note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + = note: ...`Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index d8922ef80e813..f0f407afd7601 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | +LL | fn accept(_: C) -> Handshake> { + | ------ ----------- unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept`... +... LL | accept(callback); - | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -14,10 +19,15 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | +LL | fn accept(_: C) -> Handshake> { + | ------ ----------- unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept`... +... LL | accept(callback); - | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -28,12 +38,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | +LL | struct Handshake { + | --------- ---- unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake`... +... LL | accept(callback); - | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument | LL | let callback = |_: &()| {}; @@ -42,10 +56,15 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | +LL | struct Handshake { + | --------- ---- unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake`... +... LL | accept(callback); - | ^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^ | - = note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 46e4fbea0d952..2e164c9b3abb7 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -28,9 +28,14 @@ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:14:5 | LL | bad(&b); - | ^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^ +... +LL | fn bad &()>(_: F) {} + | --- -------------- unsatisfied where-clause on `bad` + | | + | due to a where-clause on `bad`... | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -41,9 +46,14 @@ error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:14:5 | LL | bad(&b); - | ^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^ +... +LL | fn bad &()>(_: F) {} + | --- --- unsatisfied where-clause on `bad` + | | + | due to a where-clause on `bad`... | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 46e4fbea0d952..2e164c9b3abb7 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -28,9 +28,14 @@ error: implementation of `Fn` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:14:5 | LL | bad(&b); - | ^^^^^^^ implementation of `Fn` is not general enough + | ^^^^^^^ +... +LL | fn bad &()>(_: F) {} + | --- -------------- unsatisfied where-clause on `bad` + | | + | due to a where-clause on `bad`... | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -41,9 +46,14 @@ error: implementation of `FnOnce` is not general enough --> $DIR/location-insensitive-scopes-issue-117146.rs:14:5 | LL | bad(&b); - | ^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^ +... +LL | fn bad &()>(_: F) {} + | --- --- unsatisfied where-clause on `bad` + | | + | due to a where-clause on `bad`... | - = note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 804071a3e6f77..ced5c4b8058b0 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -1,21 +1,26 @@ error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | +LL | fn make_f() -> Self::F; + | ------ due to a where-clause on `Y::make_f`... +... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y::make_f` | - = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | +LL | trait Y { + | - due to a where-clause on `Y`... +... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ implementation of `Y` is not general enough + | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y` | - = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 @@ -25,7 +30,6 @@ LL | let _x = ::make_f(); | = note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` - = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 3 previous errors diff --git a/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr b/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr index f0bb77cfe4c8c..2703d276e41f7 100644 --- a/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr +++ b/tests/ui/typeck/main-termination-lifetime-issue-148421.stderr @@ -6,6 +6,11 @@ LL | fn main() -> Thing { Thing } | = note: `IsStatic` would have to be implemented for the type `&'0 ()`, for any lifetime `'0`... = note: ...but `IsStatic` is actually implemented for the type `&'1 ()`, for some specific lifetime `'1` +note: required for `Thing` to implement `Termination` + --> $DIR/main-termination-lifetime-issue-148421.rs:13:6 + | +LL | impl Termination for Thing where for<'a> &'a (): IsStatic { + | ^^^^^^^^^^^ ^^^^^ -------- unsatisfied trait bound introduced here error: aborting due to 1 previous error diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 0815ae1fb5a2b..fa61b3af02cf0 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -1,10 +1,15 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-30906.rs:18:5 | +LL | fn test FnOnce<(&'x str,)>>(_: F) {} + | ---- -------------------------- unsatisfied where-clause on `test` + | | + | due to a where-clause on `test`... +... LL | test(Compose(f, |_| {})); - | ^^^^^^^^^^^^^^^^^^^^^^^^ implementation of `FnOnce` is not general enough + | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + = note: ...`fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index f479210772194..378616d9aca57 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -1,10 +1,16 @@ error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:23:5 | +LL | fn foo(x: &T) + | --- due to a where-clause on `foo`... +LL | where +LL | for<'a> &'a T: Bar, + | --- unsatisfied where-clause on `foo` +... LL | foo(&X); - | ^^^^^^^ implementation of `Bar` is not general enough + | ^^^^^^^ | - = note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + = note: ...`&'0 u32` must implement `Bar`, for any lifetime `'0`... = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to 1 previous error From daa24324904fa6aa460a22de733068c8dcb0323d Mon Sep 17 00:00:00 2001 From: Mark Rousskov Date: Tue, 29 Sep 2026 08:13:20 -0400 Subject: [PATCH 1119/1309] Re-bless tests / adjust for new Cargo lints --- compiler/rustc/src/main.rs | 2 -- library/alloc/Cargo.toml | 4 ++++ library/panic_unwind/Cargo.toml | 3 +++ library/std/Cargo.toml | 4 ++++ library/std_detect/Cargo.toml | 4 ++++ library/sysroot/Cargo.toml | 5 +++++ src/tools/clippy/clippy_test_deps/Cargo.toml | 4 ++++ src/tools/miri/tests/deps/Cargo.toml | 4 ++++ src/tools/miri/tests/deps/cross-crate-items/Cargo.toml | 4 ++++ src/tools/rust-analyzer/Cargo.toml | 5 +++-- src/tools/rust-analyzer/crates/macros/Cargo.toml | 3 +++ .../crates/proc-macro-srv/proc-macro-test/Cargo.toml | 3 +++ .../rust-analyzer/lib/ungrammar/ungrammar2json/Cargo.toml | 3 +++ tests/ui/array-slice-vec/vec-res-add.stderr | 1 - ...st_equality_comparison_instead_of_pattern_matching.stderr | 4 ---- tests/ui/pattern/deref-patterns/implicit-const-deref.stderr | 1 - tests/ui/pattern/issue-115599.stderr | 1 - tests/ui/pattern/pattern-tyvar-2.stderr | 1 - 18 files changed, 44 insertions(+), 12 deletions(-) diff --git a/compiler/rustc/src/main.rs b/compiler/rustc/src/main.rs index 17f768f6dc54a..6609a19fa9e34 100644 --- a/compiler/rustc/src/main.rs +++ b/compiler/rustc/src/main.rs @@ -1,7 +1,5 @@ // We need this feature as it changes `dylib` linking behavior and allows us to link to `rustc_driver`. #![feature(rustc_private)] -// Several crates are depended upon but unused so that they are present in the sysroot -#![expect(unused_crate_dependencies)] use std::process::ExitCode; diff --git a/library/alloc/Cargo.toml b/library/alloc/Cargo.toml index b32e5e991cc74..a1071d2cde5f0 100644 --- a/library/alloc/Cargo.toml +++ b/library/alloc/Cargo.toml @@ -31,3 +31,7 @@ check-cfg = [ 'cfg(no_rc)', 'cfg(no_sync)', ] + +[lints.cargo] +# compiler-builtins is claimed unused? +unused_dependencies = "allow" diff --git a/library/panic_unwind/Cargo.toml b/library/panic_unwind/Cargo.toml index 72c1041b46795..3b7805a205492 100644 --- a/library/panic_unwind/Cargo.toml +++ b/library/panic_unwind/Cargo.toml @@ -18,3 +18,6 @@ unwind = { path = "../unwind" } [target.'cfg(not(all(windows, target_env = "msvc")))'.dependencies] libc = { version = "0.2", default-features = false } + +[lints.cargo] +unused_dependencies = "allow" diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index 1d35b42a53947..67eebd820ca59 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -167,3 +167,7 @@ check-cfg = [ 'cfg(target_has_reliable_f128)', 'cfg(target_has_reliable_f128_math)', ] + +[lints.cargo] +# panic_abort is not directly used but must be linked in +unused_dependencies = "allow" diff --git a/library/std_detect/Cargo.toml b/library/std_detect/Cargo.toml index a6785bb20555d..c03fff827d5cd 100644 --- a/library/std_detect/Cargo.toml +++ b/library/std_detect/Cargo.toml @@ -24,3 +24,7 @@ libc = { version = "0.2.0", default-features = false } [features] std_detect_env_override = [] + +[lints.cargo] +# libc is definitely used in code but the lint doesn't realize that (unclear why) +unused_dependencies = "allow" diff --git a/library/sysroot/Cargo.toml b/library/sysroot/Cargo.toml index 10562389d62d3..cef5532857b5e 100644 --- a/library/sysroot/Cargo.toml +++ b/library/sysroot/Cargo.toml @@ -32,3 +32,8 @@ optimize_for_size = ["std/optimize_for_size"] panic-unwind = ["std/panic-unwind"] profiler = ["dep:profiler_builtins"] windows_raw_dylib = ["std/windows_raw_dylib"] + +[lints.cargo] +# We expect some of these dependencies to not actually be used since this is +# just an aggregator crate. +unused_dependencies = "allow" diff --git a/src/tools/clippy/clippy_test_deps/Cargo.toml b/src/tools/clippy/clippy_test_deps/Cargo.toml index 880df6599c1e4..c3d236a17e1bb 100644 --- a/src/tools/clippy/clippy_test_deps/Cargo.toml +++ b/src/tools/clippy/clippy_test_deps/Cargo.toml @@ -18,3 +18,7 @@ itertools = "0.15" # Make sure we are not part of the rustc workspace. [workspace] + +[lints.cargo] +# Not all tests use all of the above dependencies +unused_dependencies = "allow" diff --git a/src/tools/miri/tests/deps/Cargo.toml b/src/tools/miri/tests/deps/Cargo.toml index a377141f98aaf..6b6d4a9e2f443 100644 --- a/src/tools/miri/tests/deps/Cargo.toml +++ b/src/tools/miri/tests/deps/Cargo.toml @@ -37,3 +37,7 @@ windows-sys = { version = "0.61", features = [ # Make sure we are not part of the rustc workspace. [workspace] members = ["cross-crate-items"] + +[lints.cargo] +# Not all tests use all of the above dependencies +unused_dependencies = "allow" diff --git a/src/tools/miri/tests/deps/cross-crate-items/Cargo.toml b/src/tools/miri/tests/deps/cross-crate-items/Cargo.toml index 1f9fc93cd5237..ca6818dc0fe25 100644 --- a/src/tools/miri/tests/deps/cross-crate-items/Cargo.toml +++ b/src/tools/miri/tests/deps/cross-crate-items/Cargo.toml @@ -5,3 +5,7 @@ edition = "2021" [dependencies] futures = { version = "0.3.0", default-features = false, features = ["alloc", "async-await"] } + +[lints.cargo] +# panic_abort is not directly used but must be linked in +unused_dependencies = "allow" diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml index d77e89df45e44..54e82148665b6 100644 --- a/src/tools/rust-analyzer/Cargo.toml +++ b/src/tools/rust-analyzer/Cargo.toml @@ -68,10 +68,8 @@ parser = { path = "./crates/parser", version = "0.0.0" } paths = { path = "./crates/paths", version = "0.0.0" } proc-macro-api = { path = "./crates/proc-macro-api", version = "0.0.0" } proc-macro-srv = { path = "./crates/proc-macro-srv", version = "0.0.0" } -proc-macro-srv-cli = { path = "./crates/proc-macro-srv-cli", version = "0.0.0" } profile = { path = "./crates/profile", version = "0.0.0" } project-model = { path = "./crates/project-model", version = "0.0.0" } -query-group = { package = "query-group-macro", path = "./crates/query-group-macro", version = "0.0.0" } span = { path = "./crates/span", version = "0.0.0" } stdx = { path = "./crates/stdx", version = "0.0.0" } syntax = { path = "./crates/syntax", version = "0.0.0" } @@ -167,6 +165,9 @@ hashbrown = { version = "0.17.0", features = [ # We need to freeze the version of the crate, as the raw-api feature is considered unstable dashmap = { version = "=6.2.1", features = ["raw-api", "inline"] } +[workspace.lints.cargo] +unused_dependencies = "allow" + [workspace.lints.rust] # remember to update RUSTFLAGS in ci.yml if you add something here diff --git a/src/tools/rust-analyzer/crates/macros/Cargo.toml b/src/tools/rust-analyzer/crates/macros/Cargo.toml index 8184cc6d1c03d..b0d0000268588 100644 --- a/src/tools/rust-analyzer/crates/macros/Cargo.toml +++ b/src/tools/rust-analyzer/crates/macros/Cargo.toml @@ -17,3 +17,6 @@ proc-macro2 = "1" quote = "1" syn = "2.0.9" synstructure = "0.13.0" + +[lints] +workspace = true diff --git a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml index 78630ddb4d7d8..668188340e5c8 100644 --- a/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml +++ b/src/tools/rust-analyzer/crates/proc-macro-srv/proc-macro-test/Cargo.toml @@ -11,3 +11,6 @@ doctest = false [build-dependencies] cargo_metadata = "0.23.0" + +[lints] +workspace = true diff --git a/src/tools/rust-analyzer/lib/ungrammar/ungrammar2json/Cargo.toml b/src/tools/rust-analyzer/lib/ungrammar/ungrammar2json/Cargo.toml index 0fa08bbbd0485..f17587e3f556c 100644 --- a/src/tools/rust-analyzer/lib/ungrammar/ungrammar2json/Cargo.toml +++ b/src/tools/rust-analyzer/lib/ungrammar/ungrammar2json/Cargo.toml @@ -10,3 +10,6 @@ edition = "2024" [dependencies] write-json = "0.1.1" ungrammar = { path = "../", version = "1.1.0" } + +[lints] +workspace = true diff --git a/tests/ui/array-slice-vec/vec-res-add.stderr b/tests/ui/array-slice-vec/vec-res-add.stderr index 6d5ad1d3c9694..4e13dbd0366d0 100644 --- a/tests/ui/array-slice-vec/vec-res-add.stderr +++ b/tests/ui/array-slice-vec/vec-res-add.stderr @@ -8,7 +8,6 @@ LL | let k = i + j; | note: `Vec` does not implement `Add` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is defined in another crate diff --git a/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr b/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr index ab823c8fc73b9..38440af675feb 100644 --- a/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr +++ b/tests/ui/consts/const_in_pattern/suggest_equality_comparison_instead_of_pattern_matching.stderr @@ -123,7 +123,6 @@ LL | V => {} | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -144,7 +143,6 @@ LL | if let V = vec![] {} | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -160,7 +158,6 @@ LL | let V = vec![] else { return; }; | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | @@ -176,7 +173,6 @@ LL | let V = Vec::new() else { return; }; | ^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | diff --git a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr index c03137fcc4151..7c176162ad184 100644 --- a/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr +++ b/tests/ui/pattern/deref-patterns/implicit-const-deref.stderr @@ -8,7 +8,6 @@ LL | EMPTY => {} | ^^^^^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec<()>` is not usable in patterns | diff --git a/tests/ui/pattern/issue-115599.stderr b/tests/ui/pattern/issue-115599.stderr index 280516deba14b..f776623ff75b2 100644 --- a/tests/ui/pattern/issue-115599.stderr +++ b/tests/ui/pattern/issue-115599.stderr @@ -8,7 +8,6 @@ LL | if let CONST_STRING = empty_str {} | ^^^^^^^^^^^^ constant of non-structural type | --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is not usable in patterns | diff --git a/tests/ui/pattern/pattern-tyvar-2.stderr b/tests/ui/pattern/pattern-tyvar-2.stderr index 4761a4e829b85..6676d5129872b 100644 --- a/tests/ui/pattern/pattern-tyvar-2.stderr +++ b/tests/ui/pattern/pattern-tyvar-2.stderr @@ -8,7 +8,6 @@ LL | fn foo(t: Bar) -> isize { match t { Bar::T1(_, Some(x)) => { return x * 3; | note: `Vec` does not implement `Mul<{integer}>` --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL - ::: $SRC_DIR/alloc/src/vec/mod.rs:LL:COL | = note: `Vec` is defined in another crate From 584a7104982f342831c45277c11e6bea6300a28b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 23:40:29 +0200 Subject: [PATCH 1120/1309] dynamically test for symlink permission --- src/tools/miri/ci/ci.sh | 2 + .../pass-dep/libc/libc-fs-permissions.rs | 2 +- .../pass-dep/libc/libc-fs-with-isolation.rs | 2 +- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 144 ++++++++++-------- .../pass-dep/libc/libc-fstat-non-file.rs | 2 +- src/tools/miri/tests/pass/shims/fs-symlink.rs | 50 ------ src/tools/miri/tests/pass/shims/fs.rs | 34 +++++ src/tools/miri/tests/utils/fs.rs | 37 ++++- 8 files changed, 157 insertions(+), 116 deletions(-) delete mode 100644 src/tools/miri/tests/pass/shims/fs-symlink.rs diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 0cf2c5293c339..52d634ba7c860 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -20,6 +20,8 @@ if ! rustc -vV | grep -q "^host: $HOST_TARGET\$"; then exit 1 fi +export CI=true # just to be sure that it is truly set + endgroup begingroup "Building Miri" diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs index dd79c96e179c8..7d81b56f8846f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-permissions.rs @@ -1,4 +1,4 @@ -//@ignore-target: windows # no libc +//@ignore-target: windows # libc bits exist, but we don't support them //@ignore-host: windows # needs unix PermissionExt //@compile-flags: -Zmiri-disable-isolation //@run-native diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs index 06a8cc7f4879a..d1a0a61a8ea36 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs-with-isolation.rs @@ -1,4 +1,4 @@ -//@ignore-target: windows # File handling is not implemented yet +//@ignore-target: windows # libc bits exist, but we don't support them //@compile-flags: -Zmiri-isolation-error=warn-nobacktrace //@normalize-stderr-test: "(stat(x)?)" -> "$$STAT" diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index b3f063ef07cba..c1f6a20b75dfc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -1,4 +1,4 @@ -//@ignore-target: windows # no libc +//@ignore-target: windows # libc bits exist, but we don't support them //@compile-flags: -Zmiri-disable-isolation //@run-native @@ -173,35 +173,38 @@ fn test_statx() { } // Symlink following. - let symlinkpath = utils::prepare("miri_test_libc_statx.link"); - let c_symlinkpath = utils::into_c_string(&symlinkpath); - std::os::unix::fs::symlink(&path, &symlinkpath).unwrap(); - unsafe { - let mut stx = MaybeUninit::::zeroed(); - errno_check(libc::statx( - 999, // dirfd - c_symlinkpath.as_ptr(), - libc::AT_EMPTY_PATH, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - stx.as_mut_ptr(), - )); - let stx = stx.assume_init(); - assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); - } - unsafe { - let mut stx = MaybeUninit::::zeroed(); - errno_check(libc::statx( - 999, // dirfd - c_symlinkpath.as_ptr(), - libc::AT_SYMLINK_NOFOLLOW, - libc::STATX_BASIC_STATS | libc::STATX_BTIME, - stx.as_mut_ptr(), - )); - let stx = stx.assume_init(); - assert!(stx.stx_mask & libc::STATX_TYPE != 0); - assert_eq!((stx.stx_mode as libc::mode_t) & libc::S_IFMT, libc::S_IFLNK); - assert!(stx.stx_mask & libc::STATX_MODE != 0); - assert_ne!((stx.stx_mode as libc::mode_t) & !libc::S_IFMT, 0); + if utils::have_symlink_permission() { + let symlinkpath = utils::prepare("miri_test_libc_statx.link"); + let c_symlinkpath = utils::into_c_string(&symlinkpath); + std::os::unix::fs::symlink(&path, &symlinkpath).unwrap(); + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + 999, // dirfd + c_symlinkpath.as_ptr(), + libc::AT_EMPTY_PATH, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + let stx = stx.assume_init(); + assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); + } + unsafe { + let mut stx = MaybeUninit::::zeroed(); + errno_check(libc::statx( + 999, // dirfd + c_symlinkpath.as_ptr(), + libc::AT_SYMLINK_NOFOLLOW, + libc::STATX_BASIC_STATS | libc::STATX_BTIME, + stx.as_mut_ptr(), + )); + let stx = stx.assume_init(); + assert!(stx.stx_mask & libc::STATX_TYPE != 0); + assert_eq!((stx.stx_mode as libc::mode_t) & libc::S_IFMT, libc::S_IFLNK); + assert!(stx.stx_mask & libc::STATX_MODE != 0); + assert_ne!((stx.stx_mode as libc::mode_t) & !libc::S_IFMT, 0); + } + remove_file(&symlinkpath).unwrap(); } // Relative to a dirfd. @@ -225,7 +228,6 @@ fn test_statx() { errno_check(unsafe { libc::closedir(dirstream) }); remove_file(&path).unwrap(); - remove_file(&symlinkpath).unwrap(); } #[cfg(target_os = "linux")] @@ -328,26 +330,29 @@ fn test_file_open_extra_third_arg() { } fn test_file_open_nofollow() { + // Regular files work like normal. let bytes = b"Hello, World!\n"; let path = utils::prepare_with_content("miri_test_nofollow_not_symlink.txt", bytes); let cpath = utils::into_c_string(path); let fd = errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }) .unwrap(); + let data = libc_utils::read_exact_array::<5>(fd).unwrap(); + assert!(bytes.starts_with(&data)); errno_check(unsafe { libc::close(fd) }); - let path = utils::prepare_with_content("miri_test_open_nofollow_symlink_target.txt", bytes); - - let symlink_path = utils::prepare("miri_test_open_nofollow_symlink.txt"); - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - - let symlink_cpath = utils::into_c_string(symlink_path); - - let err = errno_result(unsafe { - libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) - }) - .unwrap_err(); - assert_eq!(err.raw_os_error(), Some(libc::ELOOP)); + // But trying to open a symlink errors. + if utils::have_symlink_permission() { + let path = utils::prepare_with_content("miri_test_open_nofollow_symlink_target.txt", bytes); + let symlink_path = utils::prepare("miri_test_open_nofollow_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + let symlink_cpath = utils::into_c_string(symlink_path); + let err = errno_result(unsafe { + libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) + }) + .unwrap_err(); + assert_eq!(err.raw_os_error(), Some(libc::ELOOP)); + } } fn test_dup_stdout_stderr() { @@ -901,32 +906,39 @@ fn test_fstatat() { errno_check(unsafe { libc::fstatat(dirfd, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }); checkstat(unsafe { stat.assume_init_ref() }); - // Symlink following. - let linkname = testdir.join("link"); - std::os::unix::fs::symlink(&absfilename, &linkname).unwrap(); - let mut stat = MaybeUninit::::uninit(); - errno_check(unsafe { libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), 0) }); - checkstat(unsafe { stat.assume_init_ref() }); - let mut stat = MaybeUninit::::uninit(); - errno_check(unsafe { - libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), libc::AT_SYMLINK_NOFOLLOW) - }); - let stat = unsafe { stat.assume_init_ref() }; - assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFLNK); // not S_IFREG! - assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); - check_stat_fields(stat); + if utils::have_symlink_permission() { + // Symlink following. + let linkname = testdir.join("link"); + std::os::unix::fs::symlink(&absfilename, &linkname).unwrap(); + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), 0) }); + checkstat(unsafe { stat.assume_init_ref() }); + let mut stat = MaybeUninit::::uninit(); + errno_check(unsafe { + libc::fstatat(dirfd, c"link".as_ptr(), stat.as_mut_ptr(), libc::AT_SYMLINK_NOFOLLOW) + }); + let stat = unsafe { stat.assume_init_ref() }; + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFLNK); // not S_IFREG! + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + check_stat_fields(stat); + } errno_check(unsafe { libc::closedir(dirstream) }); } fn test_stat() { - // Also make sure we *do* follow symlinks. - let path = utils::prepare_with_content("miri_test_libc_stat.txt", b"hello"); - let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + let path = if utils::have_symlink_permission() { + // Also make sure we *do* follow symlinks. + let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + symlink_path + } else { + // Backup plan: just open the file directly. + path + }; - let cpath = utils::into_c_string(symlink_path); + let cpath = utils::into_c_string(&path); let mut stat = MaybeUninit::::uninit(); errno_check(unsafe { libc::stat(cpath.as_ptr(), stat.as_mut_ptr()) }); @@ -943,6 +955,10 @@ fn test_stat() { } fn test_lstat() { + if !utils::have_symlink_permission() { + return; + } + let path = utils::prepare_with_content("miri_test_libc_lstat.txt", b"hello"); let symlink_path = utils::prepare("miri_test_libc_lstat_symlink.txt"); std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); @@ -1495,6 +1511,10 @@ fn test_pwrite() { } fn test_readlink() { + if !utils::have_symlink_permission() { + return; + } + let bytes = b"Hello, World!\n"; let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); let expected_path = path.as_os_str().as_bytes(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fstat-non-file.rs b/src/tools/miri/tests/pass-dep/libc/libc-fstat-non-file.rs index cf848f1903311..097bb5a7699ec 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fstat-non-file.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fstat-non-file.rs @@ -1,4 +1,4 @@ -//@ignore-target: windows # No libc fstat on non-file FDs on Windows +//@ignore-target: windows # libc bits exist, but we don't support them //@compile-flags: -Zmiri-disable-isolation use std::mem::MaybeUninit; diff --git a/src/tools/miri/tests/pass/shims/fs-symlink.rs b/src/tools/miri/tests/pass/shims/fs-symlink.rs deleted file mode 100644 index 30cf234e7a0d1..0000000000000 --- a/src/tools/miri/tests/pass/shims/fs-symlink.rs +++ /dev/null @@ -1,50 +0,0 @@ -// Symlink tests are separate since they don't in general work on a Windows host. -//@ignore-host: windows # creating symlinks requires admin permissions on Windows -//@ignore-target: windows # File handling is not implemented yet -//@compile-flags: -Zmiri-disable-isolation - -use std::fs::{File, read_link, remove_file}; -use std::io::{Read, Result}; -use std::path::Path; - -#[path = "../../utils/mod.rs"] -mod utils; - -fn check_metadata(bytes: &[u8], path: &Path) -> Result<()> { - // Test that the file metadata is correct. - let metadata = path.metadata()?; - // `path` should point to a file. - assert!(metadata.is_file()); - // The size of the file must be equal to the number of written bytes. - assert_eq!(bytes.len() as u64, metadata.len()); - Ok(()) -} - -fn main() { - let bytes = b"Hello, World!\n"; - let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); - let symlink_path = utils::prepare("miri_test_fs_symlink.txt"); - - // Creating a symbolic link should succeed. - #[cfg(unix)] - std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); - #[cfg(windows)] - std::os::windows::fs::symlink_file(&path, &symlink_path).unwrap(); - // Test that the symbolic link has the same contents as the file. - let mut symlink_file = File::open(&symlink_path).unwrap(); - let mut contents = Vec::new(); - symlink_file.read_to_end(&mut contents).unwrap(); - assert_eq!(bytes, contents.as_slice()); - - // Test that metadata of a symbolic link (i.e., the file it points to) is correct. - check_metadata(bytes, &symlink_path).unwrap(); - // Test that the metadata of a symbolic link is correct when not following it. - assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink()); - // Check that we can follow the link. - assert_eq!(read_link(&symlink_path).unwrap(), path); - // Removing symbolic link should succeed. - remove_file(&symlink_path).unwrap(); - - // Removing file should succeed. - remove_file(&path).unwrap(); -} diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 1317c08376467..7466a534b0ca4 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -52,6 +52,7 @@ fn main() { test_canonicalize(); #[cfg(not(target_os = "solaris"))] // does not have flock test_flock(); + test_symlink(); test_hard_link(); test_readv_writev(); @@ -557,6 +558,39 @@ fn test_preadv_pwritev() { assert_eq!(written_bytes.as_slice(), &write_buffer[0..bytes_written]); } +fn test_symlink() { + if !utils::have_symlink_permission() { + return; + } + + let bytes = b"Hello, World!\n"; + let path = utils::prepare_with_content("miri_test_fs_link_target.txt", bytes); + let symlink_path = utils::prepare("miri_test_fs_symlink.txt"); + + // Creating a symbolic link should succeed. + #[cfg(unix)] + std::os::unix::fs::symlink(&path, &symlink_path).unwrap(); + #[cfg(windows)] + std::os::windows::fs::symlink_file(&path, &symlink_path).unwrap(); + // Test that the symbolic link has the same contents as the file. + let mut symlink_file = File::open(&symlink_path).unwrap(); + let mut contents = Vec::new(); + symlink_file.read_to_end(&mut contents).unwrap(); + assert_eq!(bytes, contents.as_slice()); + + // Test that metadata of a symbolic link (i.e., the file it points to) is correct. + check_metadata(bytes, &symlink_path).unwrap(); + // Test that the metadata of a symbolic link is correct when not following it. + assert!(symlink_path.symlink_metadata().unwrap().file_type().is_symlink()); + // Check that we can follow the link. + assert_eq!(fs::read_link(&symlink_path).unwrap(), path); + // Removing symbolic link should succeed. + remove_file(&symlink_path).unwrap(); + + // Removing file should succeed. + remove_file(&path).unwrap(); +} + fn test_hard_link() { let source = utils::prepare_with_content("miri_test_fs_hard_link_source.txt", b"hello"); let link = utils::prepare("miri_test_fs_hard_link_link.txt"); diff --git a/src/tools/miri/tests/utils/fs.rs b/src/tools/miri/tests/utils/fs.rs index afcd66dd16e58..9661b55ba43a8 100644 --- a/src/tools/miri/tests/utils/fs.rs +++ b/src/tools/miri/tests/utils/fs.rs @@ -1,6 +1,6 @@ use std::ffi::{CStr, OsString}; use std::path::PathBuf; -use std::{fs, io}; +use std::{env, fs, io}; use super::{into_c_string, miri_extern}; @@ -52,3 +52,38 @@ pub fn prepare_dir(dirname: &str) -> PathBuf { fs::remove_dir_all(&path).ok(); path } + +/// Windows makes things difficult by refusing create symlinks per default. GHA is configured to +/// allow them, but when people run the tests on their systems we'd prefer them to pass without +/// special setup. So we try to detect whether symlinks are working. To make things extra fun, this +/// can happen even if we *think* we are on Unix since the host could still be Windows. +pub fn have_symlink_permission() -> bool { + use std::sync::LazyLock; + + static HAVE_SYMLINK_PERMISSION: LazyLock = LazyLock::new(|| { + // Never skip any tests on CI. + if env::var_os("CI").is_some() { + return true; + } + + #[cfg(unix)] + use std::os::unix::fs::symlink as symlink_file; + #[cfg(windows)] + use std::os::windows::fs::symlink_file; + + let link = prepare("miri_have_symlink_permission_check_file"); + if symlink_file(r"nonexisting_target", &link).is_ok() { + // Looking pretty good. + fs::remove_file(link).unwrap(); + return true; + } + // Looking bad. But just to confirm, could we create a normal file? + if fs::write(&link, &[]).is_ok() { + // Normal file works, symlink did not -- looks like the Windows issue. + fs::remove_file(link).unwrap(); + return false; + } + panic!("unable to create files in tempdir"); + }); + *HAVE_SYMLINK_PERMISSION +} From 3aba6fc0eb421321789fc6e9891358fc2a6d1d03 Mon Sep 17 00:00:00 2001 From: ltdk Date: Wed, 30 Sep 2026 09:59:46 -0400 Subject: [PATCH 1121/1309] Add libs-nominated triagebot config --- triagebot.toml | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 611f7724f5cae..77acf0edda0a6 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -707,6 +707,16 @@ message_on_remove = "Issue #{number}'s nomination has been removed. Thanks all f message_on_close = "Issue #{number} has been closed. Thanks for participating!" message_on_reopen = "Issue #{number} has been reopened. Pinging @*T-types*." +[notify-zulip."I-libs-nominated"] +zulip_stream = 639962 # #t-libs/nominated +topic = "#{number}: {title}" +message_on_add = """\ +[#{number} "{title}"](https://github.com/rust-lang/rust/pull/{number}) has been nominated for discussion. +""" +message_on_remove = """\ +#{number} is no longer nominated. +""" + # ------------------------------------------------------------------------------ # Zulip notifications From 1ea0af2b635db880e64e9c1083d3f89c5d757fb5 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Thu, 1 Oct 2026 05:02:05 +0530 Subject: [PATCH 1122/1309] Skip deferred attribute checks when not emitting --- .../src/attributes/macro_attrs.rs | 3 +- compiler/rustc_attr_parsing/src/interface.rs | 34 ++++++++++--------- 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs index 8bca20cda67aa..8bb5e6b7fc270 100644 --- a/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs +++ b/compiler/rustc_attr_parsing/src/attributes/macro_attrs.rs @@ -5,7 +5,6 @@ use rustc_lint_defs::builtin::{INVALID_MACRO_EXPORT_ARGUMENTS, UNUSED_ATTRIBUTES use rustc_structures::CollapseMacroDebuginfo; use super::prelude::*; -use crate::context::ShouldEmit; use crate::diagnostics::{MacroExport, MacroOnlyAttribute}; pub(crate) struct MacroEscapeParser; @@ -182,7 +181,7 @@ impl SingleAttributeParser for MacroExportParser { } fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { - if cx.target != Target::MacroDef || matches!(cx.should_emit, ShouldEmit::Nothing) { + if cx.target != Target::MacroDef { return; } diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index df89ffe57b9a0..95412c34be371 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -510,23 +510,25 @@ impl<'sess> AttributeParser<'sess> { // Now that all attributes have been parsed, run the deferred checks. These can // inspect the fully parsed attributes via `FinalizeCheckContext::parsed_attrs`. - for (check, attr_span) in deferred_checks { - check( - &mut FinalizeCheckContext { - shared: SharedContext { - cx: self, - target_span, - target, - emit_lint: &mut emit_lint, - #[cfg(debug_assertions)] - has_lint_been_emitted: AtomicBool::new(false), + if !matches!(self.should_emit, ShouldEmit::Nothing) { + for (check, attr_span) in deferred_checks { + check( + &mut FinalizeCheckContext { + shared: SharedContext { + cx: self, + target_span, + target, + emit_lint: &mut emit_lint, + #[cfg(debug_assertions)] + has_lint_been_emitted: AtomicBool::new(false), + }, + all_attrs: &attr_paths, + parsed_attrs: &attributes, + target_item, }, - all_attrs: &attr_paths, - parsed_attrs: &attributes, - target_item, - }, - attr_span, - ); + attr_span, + ); + } } if !matches!(self.should_emit, ShouldEmit::Nothing) && target == Target::WherePredicate { From 82366d5fada2e3fcabc7361964e795f5710745c3 Mon Sep 17 00:00:00 2001 From: Mahdi Ali-Raihan Date: Wed, 30 Sep 2026 23:43:12 -0400 Subject: [PATCH 1123/1309] Provide better doc code example for UnixDatagram::bind_addr and UnixListener::bind_addr --- library/std/src/os/unix/net/datagram.rs | 7 +++---- library/std/src/os/unix/net/listener.rs | 7 +++---- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index e03ecd7eed9ea..0543de4b837f4 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -112,13 +112,12 @@ impl UnixDatagram { /// #[cfg_attr(target_family = "unix", doc = "```no_run")] #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] - /// use std::os::unix::net::{UnixDatagram}; + /// use std::os::unix::net::{SocketAddr, UnixDatagram}; /// /// fn main() -> std::io::Result<()> { - /// let sock1 = UnixDatagram::bind("path/to/socket")?; - /// let addr = sock1.local_addr()?; + /// let addr = SocketAddr::from_pathname("path/to/socket")?; /// - /// let sock2 = match UnixDatagram::bind_addr(&addr) { + /// let sock = match UnixDatagram::bind_addr(&addr) { /// Ok(sock) => sock, /// Err(err) => { /// println!("Couldn't bind: {err:?}"); diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index b7f8d25a85ae5..b51b61fc11cfe 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -119,13 +119,12 @@ impl UnixListener { /// #[cfg_attr(target_family = "unix", doc = "```no_run")] #[cfg_attr(not(target_family = "unix"), doc = "```ignore (needs unix)")] - /// use std::os::unix::net::{UnixListener}; + /// use std::os::unix::net::{SocketAddr, UnixListener}; /// /// fn main() -> std::io::Result<()> { - /// let listener1 = UnixListener::bind("path/to/socket")?; - /// let addr = listener1.local_addr()?; + /// let addr = SocketAddr::from_pathname("path/to/socket")?; /// - /// let listener2 = match UnixListener::bind_addr(&addr) { + /// let listener = match UnixListener::bind_addr(&addr) { /// Ok(sock) => sock, /// Err(err) => { /// println!("Couldn't bind: {err:?}"); From 9d32c0049a4672bb3ab824ec8fb5ba89ac7af7b0 Mon Sep 17 00:00:00 2001 From: Michael Howell Date: Wed, 30 Sep 2026 20:45:59 -0700 Subject: [PATCH 1124/1309] bootstrap: Enable rustdoc mergeable CCI for std and internal docs Takes a different approach to https://github.com/rust-lang/rust/pull/160098, where the internal docs are merged by bootstrap directly invoking rustdoc. This requires bootstrap to gather the list of metadata directories by inspecting cargo's fingerprint files (which aren't stable). The first commit is written by @camelid, but I wrote the other two. This feature is needed because: 1. The search index (that powers [web-based search](https://doc.rust-lang.org/nightly/nightly-rustc/?search=ty%20-%3E%20rustdoc%3A%3Atype)) needs to contain all of the crates in the nightly-rustc project. In particular, I'd prefer if it contained Clippy, Rustdoc, and Rustc, since those crates share type checker stuff and the ability to search all three at once is convenient. 2. For every crate that rustdoc *currently* documents, it has to load the search index from the doc output dir, and rebuild the search index with the new crate added to it. Loading the search index requires $O(\text{crates})$ work, so doing it once for every crate means we're doing $O(\text{crates}^2)$ work overall. 3. It would be more efficient, *instead*, if each crate wrote its data separately, and then the final search index was generated at the end by merging them all at once. Obviously, this would make the work linear instead of quadratic. For the record, Hoogle and Sherlodoc have a similar index-generating step. 4. We call this "Mergeable Cross-Crate-Information." Cargo stores it in the build directory, and supplies it to Rustdoc in a separate phase that runs after everything else. When we eventually stabilize this feature, it will be invisible to (most) end users. `cargo doc` will just be faster. 5. So, in order for crates to share their cross-crate info, we need them to share a build directory. 6. Tools, like Rustdoc and Cargo, don't normally share a build directory with Rustc. 7. To make them share a build directory while generating documentation, without forcing them to share a build directory while compiling, I added a new mode. --- This rustdoc feature is unstable but will be stabilized soon, and this is a good way of dogfooding it to make sure it works properly. It should have no effect on the generated docs, but it provides a significant speedup. For example, I measure a 3x speedup locally (3m 11s -> 1m 1s) for `x doc src/tools` -- note that this is with the latest rustdoc perf improvements (rust-lang/rust#159854). --- This reverts commit c84edb3d8cbd74af5df2cb06dbcb7c29d9743ff7. --- src/bootstrap/src/core/build_steps/compile.rs | 10 +- src/bootstrap/src/core/build_steps/dist.rs | 9 +- src/bootstrap/src/core/build_steps/doc.rs | 467 ++++++++++++++---- src/bootstrap/src/core/builder/cargo.rs | 6 + src/bootstrap/src/core/builder/mod.rs | 1 + src/bootstrap/src/core/builder/tests.rs | 114 ++--- src/bootstrap/src/core/session.rs | 2 +- 7 files changed, 417 insertions(+), 192 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 97e7280da1e37..816126b5405b8 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -2675,7 +2675,7 @@ pub fn run_cargo( let (filenames_vec, crate_types) = match msg { CargoMessage::CompilerArtifact { filenames, - target: CargoTarget { crate_types }, + target: CargoTarget { crate_types, .. }, .. } => { let mut f: Vec = filenames.into_iter().map(|s| s.into_owned()).collect(); @@ -2882,12 +2882,14 @@ pub fn stream_cargo( status.success() } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] pub struct CargoTarget<'a> { - crate_types: Vec>, + pub crate_types: Vec>, + #[serde(default)] + pub doc: bool, } -#[derive(Deserialize)] +#[derive(Deserialize, Debug)] #[serde(tag = "reason", rename_all = "kebab-case")] pub enum CargoMessage<'a> { CompilerArtifact { filenames: Vec>, target: CargoTarget<'a> }, diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 7073b334c414d..d2cd8c77bc9db 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -23,7 +23,7 @@ use crate::core::backend::CodegenBackendKind; use crate::core::build_steps::compile::{ get_codegen_backend_file, libgccjit_path_relative_to_cg_dir, normalize_codegen_backend_name, }; -use crate::core::build_steps::doc::DocumentationFormat; +use crate::core::build_steps::doc::{CompilerWithTools, DocumentationFormat}; use crate::core::build_steps::gcc::GccTargetPair; use crate::core::build_steps::llvm::{ LLVM_CI_LINK_TYPE_PATH, LlvmBuildStatus, LlvmKind, get_llvm_build_status, @@ -185,7 +185,7 @@ impl CommandLineStep for JsonDocs { } } -/// Builds the `rustc-docs` installer component. +/// Builds the `rustc-docs` component. /// Apart from the documentation of the `rustc_*` crates, it also includes the documentation of /// various in-tree helper tools (bootstrap, build_helper, tidy), /// and also rustc_private tools like rustdoc, clippy, miri or rustfmt. @@ -214,11 +214,12 @@ impl CommandLineStep for RustcDocs { fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.target; - builder.run_default_doc_steps(); + let combined_docs = + builder.ensure(CompilerWithTools::for_stage(builder, builder.top_stage, self.target)); let mut tarball = Tarball::new(builder, "rustc-docs", &target.triple); tarball.set_product_name("Rustc Documentation"); - tarball.add_bulk_dir(builder.compiler_doc_out(target), "share/doc/rust/html/rustc-docs"); + tarball.add_bulk_dir(combined_docs, "share/doc/rust/html/rustc-docs"); tarball.generate() } } diff --git a/src/bootstrap/src/core/build_steps/doc.rs b/src/bootstrap/src/core/build_steps/doc.rs index 2c64d7915c392..34e9b354bddb2 100644 --- a/src/bootstrap/src/core/build_steps/doc.rs +++ b/src/bootstrap/src/core/build_steps/doc.rs @@ -7,11 +7,13 @@ //! Everything here is basically just a shim around calling either `rustbook` or //! `rustdoc`. +use std::collections::HashSet; use std::io::{self, Write}; use std::path::{Path, PathBuf}; use std::{env, fs, mem}; use crate::core::build_steps::compile; +use crate::core::build_steps::compile::{CargoMessage, stream_cargo}; use crate::core::build_steps::tool::{ self, RustcPrivateCompilers, SourceType, Tool, prepare_tool_cargo, }; @@ -20,9 +22,9 @@ use crate::core::builder::{ crate_description, }; use crate::core::compiler::Compiler; -use crate::core::config::{Config, TargetSelection}; +use crate::core::config::TargetSelection; use crate::core::session::{FileType, Mode}; -use crate::utils::helpers::{submodule_path_of, symlink_dir, t, up_to_date}; +use crate::utils::helpers::{exit_process, submodule_path_of, symlink_dir, t, up_to_date}; macro_rules! book { ($($name:ident, $path:expr, $book_name:expr, $lang:expr ;)+) => { @@ -840,7 +842,6 @@ fn doc_std( .arg("--no-deps") .arg("--target-dir") .arg(&*target_dir.to_string_lossy()) - .arg("-Zskip-rustdoc-fingerprint") .arg("-Zrustdoc-map") .rustdocflag("--extern-html-root-url") .rustdocflag("std_detect=https://docs.rs/std_detect/latest/") @@ -871,7 +872,159 @@ pub fn prepare_doc_compiler( build_compiler } +/// Run rustdoc to merge cross-crate info metadata (like the search index) from individual +/// executions of rustdoc into `out_dir`. +/// The `json_files` parameter should contain paths to JSON file artifacts generated by previous +/// executions of `cargo doc`. +fn merge_rustdoc_cci( + builder: &Builder<'_>, + build_compiler: Compiler, + json_files: &[PathBuf], + out_dir: &Path, +) { + let mut cmd = builder.rustdoc_cmd(build_compiler); + + cmd.arg("--enable-index-page").arg("-Zunstable-options").arg("-o").arg(out_dir); + + if !builder.config.docs_minification { + cmd.arg("--disable-minification"); + } + + for json_file in json_files { + cmd.arg("--read-doc-meta-dir").arg(json_file.parent().unwrap()); + } + + cmd.run(builder); +} + +/// Generate the combined compiler + tools docs for a given toolchain. +/// This contains both the compiler docs, docs of rustc_private tools (miri, clippy, etc.), cargo +/// and also some bootstrap related tools (bootstrap itself, compiletest, tidy, etc.). +/// +/// It gets hosted at https://doc.rust-lang.org/nightly/nightly-rustc/index.html. +/// +/// Compiler documentation is distributed separately, so we make sure +/// we do not merge it with the other documentation from std, test and +/// proc_macros. This is largely just a wrapper around `cargo doc`. +/// +/// Returns a path to a directory with the generated documentation. +#[derive(Debug, Clone, Hash, PartialEq, Eq)] +pub struct CompilerWithTools { + build_compiler: Compiler, + target: TargetSelection, + stage: u32, +} + +impl CompilerWithTools { + /// Document `stage` compiler for the given `target`. + pub(crate) fn for_stage(builder: &Builder<'_>, stage: u32, target: TargetSelection) -> Self { + let build_compiler = prepare_doc_compiler(builder, target, stage); + Self { build_compiler, target, stage } + } +} + +impl CommandLineStep for CompilerWithTools { + type Output = PathBuf; + const IS_HOST: bool = true; + + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.alias("compiler-with-tools") + } + + fn is_default_step(builder: &Builder<'_>) -> bool { + builder.config.compiler_docs + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure(CompilerWithTools::for_stage( + run.builder, + run.builder.top_stage, + run.target, + )); + } + + fn run(self, builder: &Builder<'_>) -> Self::Output { + let CompilerWithTools { target, build_compiler, stage } = self; + + // This is the intended out directory for combined compiler documentation. + let out = builder.compiler_doc_out(target); + let _ = fs::remove_dir_all(&out); + + let _guard = + builder.msg(Kind::Doc, "compiler-with-tools", Mode::Rustc, build_compiler, target); + + let combined_docs = vec![ + builder.ensure(Rustc::for_stage(builder, stage, target)), + builder.ensure(Rustdoc::new(builder, target)), + builder.ensure(Rustfmt::new(builder, target)), + builder.ensure(Clippy::new(builder, target)), + builder.ensure(Miri::new(builder, target)), + builder.ensure(Cargo::new(builder, target)), + builder.ensure(Tidy::new(builder, target)), + builder.ensure(Bootstrap::new(builder, target)), + builder.ensure(BuildHelper::new(builder, target)), + builder.ensure(Compiletest::new(builder, target)), + builder.ensure(RunMakeSupport::new(builder, target)), + ]; + + if !builder.config.dry_run() { + // Now copy all the individual docs into a single directory + let mut json_files = vec![]; + for docs in combined_docs { + json_files.extend(docs.artifacts.json_files); + + // Doc directories to link to the shared output directory + // We add the host doc dirs, which should already be symlinked in the target + // docs dir at this point (see `merge_host_and_target_docs`). + let dirs_to_copy: Vec<_> = docs + .artifacts + .target_dirs + .iter() + .chain(docs.artifacts.host_dirs.iter()) + .map(|d| d.file_name().unwrap().to_str().unwrap()) + .collect(); + for dir in dirs_to_copy { + // Link the docs dir + let docs_dir = docs.out_dir.join(dir); + assert!(docs_dir.exists(), "Docs directory {docs_dir:?} does not exist."); + let out_docs_dir = out.join(dir); + builder.create_dir(&out_docs_dir); + builder.cp_link_r(&docs_dir, &out_docs_dir); + + // And the src dir + let src_dir = docs.out_dir.join("src").join(dir); + assert!(src_dir.exists(), "Docs source directory {src_dir:?} does not exist."); + let out_src_dir = out.join("src").join(dir); + builder.create_dir(&out_src_dir); + builder.cp_link_r(&src_dir, &out_src_dir); + } + } + // And finally merge all the CCI metadata + merge_rustdoc_cci(builder, build_compiler, &json_files, &out); + } + + // Handle `--open`. + builder.open_in_browser(out.join("index.html")); + out + } + + fn metadata(&self) -> Option { + Some(StepMetadata::doc("CompilerWithTools", self.target).built_by(self.build_compiler)) + } +} + +/// Output of a Doc step. +#[derive(Clone)] +pub struct BuiltDocs { + /// Target doc directory with the generated documentation. + out_dir: PathBuf, + /// Doc artifacts gathered from Cargo during the doc build. + artifacts: DocArtifacts, +} + /// Document the compiler for the given `target` using rustdoc from `build_compiler`. +/// +/// Return the path to the generated rustc documentation directory. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct Rustc { build_compiler: Compiler, @@ -901,7 +1054,7 @@ impl Rustc { } impl CommandLineStep for Rustc { - type Output = (); + type Output = BuiltDocs; const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { @@ -922,13 +1075,9 @@ impl CommandLineStep for Rustc { /// Compiler documentation is distributed separately, so we make sure /// we do not merge it with the other documentation from std, test and /// proc_macros. This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) -> Self::Output { let target = self.target; - // This is the intended out directory for compiler documentation. - let out = builder.compiler_doc_out(target); - t!(fs::create_dir_all(&out)); - // Build the standard library, so that proc-macros can use it. // (Normally, only the metadata would be necessary, but proc-macros are special since they run at compile-time.) let build_compiler = self.build_compiler; @@ -965,7 +1114,6 @@ impl CommandLineStep for Rustc { cargo.rustdocflag("--generate-macro-expansion"); compile::rustc_cargo(builder, &mut cargo, target, &build_compiler, &self.crates); - cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. // Do link to dependencies on `docs.rs` however using `rustdoc-map`. @@ -977,53 +1125,42 @@ impl CommandLineStep for Rustc { cargo.rustdocflag("--extern-html-root-url"); cargo.rustdocflag("ena=https://docs.rs/ena/latest/"); - let mut to_open = None; - - let out_dir = builder.stage_out(build_compiler, Mode::Rustc).join(target).join("doc"); + let cargo_target_dir = builder.stage_out(build_compiler, Mode::Rustc); + let target_doc_dir = cargo_target_dir.join(target).join("doc"); + let host_doc_dir = cargo_target_dir.join("doc"); for krate in &*self.crates { // Create all crate output directories first to make sure rustdoc uses // relative links. // FIXME: Cargo should probably do this itself. - let dir_name = krate.replace('-', "_"); - t!(fs::create_dir_all(out_dir.join(&*dir_name))); + let dir_name = normalize_doc_crate_name(krate); + t!(fs::create_dir_all(target_doc_dir.join(&*dir_name))); cargo.arg("-p").arg(krate); - if to_open.is_none() { - to_open = Some(dir_name); - } } - // This uses a shared directory so that librustdoc documentation gets - // correctly built and merged with the rustc documentation. - // - // This is needed because rustdoc is built in a different directory from - // rustc. rustdoc needs to be able to see everything, for example when - // merging the search index, or generating local (relative) links. - symlink_dir_force(&builder.config, &out, &out_dir); - // Cargo puts proc macros in `target/doc` even if you pass `--target` - // explicitly (https://github.com/rust-lang/cargo/issues/7677). - let proc_macro_out_dir = builder.stage_out(build_compiler, Mode::Rustc).join("doc"); - symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); - - cargo.into_cmd().run(builder); + let artifacts = create_docs_and_gather_artifacts(builder, cargo); + artifacts.sanity_check_crates(builder, self.crates.iter()); if !builder.config.dry_run() { - // Sanity check on linked compiler crates - for krate in &*self.crates { - let dir_name = krate.replace('-', "_"); - // Making sure the directory exists and is not empty. - assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); - } + merge_host_and_target_docs(builder, &artifacts, &host_doc_dir, &target_doc_dir); + merge_rustdoc_cci(builder, build_compiler, &artifacts.json_files, &target_doc_dir); } - if builder.paths.iter().any(|path| path.ends_with("compiler")) { - // For `x.py doc compiler --open`, open `rustc_middle` by default. - let index = out.join("rustc_middle").join("index.html"); - builder.open_in_browser(index); - } else if let Some(krate) = to_open { - // Let's open the first crate documentation page: - let index = out.join(krate).join("index.html"); + // We open rustc_middle as the default if invoked as `x.py doc --open RELEASES.md` + // with no particular explicit doc requested (e.g. library/core). + if builder.was_invoked_explicitly::(Kind::Doc) { + let index = if builder.paths.iter().any(|path| path.ends_with("compiler")) { + // For `x.py doc compiler --open`, open `rustc_middle` by default. + target_doc_dir.join("rustc_middle").join("index.html") + } else if let Some(krate) = self.crates.first() { + // Let's open the first crate documentation page: + target_doc_dir.join(normalize_doc_crate_name(krate)).join("index.html") + } else { + target_doc_dir.clone() + }; builder.open_in_browser(index); } + + BuiltDocs { out_dir: target_doc_dir, artifacts } } fn metadata(&self) -> Option { @@ -1031,6 +1168,145 @@ impl CommandLineStep for Rustc { } } +/// Stores generated documentation artifacts. +#[derive(Clone, Debug)] +struct DocArtifacts { + /// Directories with HTML docs for host (proc-macro) crates. + host_dirs: Vec, + /// Directories with HTML docs for target crates. + target_dirs: Vec, + /// JSON files used to create the final CCI index + json_files: Vec, +} + +impl DocArtifacts { + /// Ensure that all passed crates were documented. + fn sanity_check_crates(&self, builder: &Builder<'_>, crates: impl Iterator) + where + S: AsRef, + { + if builder.config.dry_run() { + return; + } + let crate_names: HashSet<&str> = self + .host_dirs + .iter() + .chain(self.target_dirs.iter()) + .filter_map(|d| d.file_name().and_then(|d| d.to_str())) + .collect(); + for krate in crates { + let krate = krate.as_ref(); + let krate = normalize_doc_crate_name(krate); + if !crate_names.contains(krate.as_str()) { + eprintln!("ERROR: crate {krate} was not documented!"); + exit_process(1); + } + } + } +} + +/// Run `cargo doc` and gather generated documentation artifacts. +fn create_docs_and_gather_artifacts(builder: &Builder<'_>, cargo: builder::Cargo) -> DocArtifacts { + let mut json_files = vec![]; + let mut host_dirs = vec![]; + let mut target_dirs = vec![]; + stream_cargo(builder, cargo, vec![], &mut |msg| { + let CargoMessage::CompilerArtifact { filenames, target } = msg else { + return; + }; + if !target.doc { + return; + } + // Note: An alternative way to check host docs would be to check whether the generated + // output is a child of the host doc directory (which we would have to pass to this + // function). + let is_host = target.crate_types.iter().any(|t| t == "proc-macro"); + for filename in filenames { + let path = Path::new(filename.as_ref()); + let Some(extension) = path.extension().and_then(|ext| ext.to_str()) else { + continue; + }; + let path = path.to_path_buf(); + if extension == "json" { + json_files.push(path.to_path_buf()); + } else if extension == "html" { + if is_host { + // doc//index.html -> doc/ + host_dirs.push(path.parent().unwrap().to_path_buf()); + } else { + target_dirs.push(path.parent().unwrap().to_path_buf()); + } + } + } + }); + DocArtifacts { host_dirs, target_dirs, json_files } +} + +/// Merge host and target documentation for a set of crates. +/// We pass `--target` when documenting, so Cargo will put the built documentation into two places: +/// - `target/doc` - contains documentation of host code, so proc macros +/// - `target//doc` - contains documentation of "normal" code +/// +/// See https://github.com/rust-lang/cargo/issues/7677. +/// +/// To produce a single unified documentation, we want to merge them together. +/// We do that by creating symlinks into the target doc dir that will point to the host doc +/// directories. +/// The target doc directory will then contain the combined docs. +fn merge_host_and_target_docs( + builder: &Builder<'_>, + docs: &DocArtifacts, + host_doc_dir: &Path, + target_doc_dir: &Path, +) { + // Sanity check that there is no host/target overlap + for dir in &docs.host_dirs { + let name = dir.file_name().and_then(|d| d.to_str()).unwrap(); + if let Some(target_dir) = docs.target_dirs.iter().find_map(|d| { + let dirname = d.file_name().and_then(|d| d.to_str())?; + if dirname == name { Some(d) } else { None } + }) { + eprintln!( + "ERROR: host docs directory `{name}` ({dir:?}) is also contained in target doc directory ({target_dir:?})" + ); + exit_process(1); + } + } + + let target_src_dir = target_doc_dir.join("src"); + let host_src_dir = host_doc_dir.join("src"); + + // Ideally, we would remove all previous symlinks here. + // However, some of the tools actually share the same build docs directory, so we shouldn't do + // that, otherwise they will invalidate one another. + + for host_docs_crate in &docs.host_dirs { + let dir_name = host_docs_crate.file_name().unwrap().to_str().unwrap(); + // Normalize crate name + let dir_name = normalize_doc_crate_name(dir_name); + + t!(symlink_dir(&builder.config, host_docs_crate, &target_doc_dir.join(&dir_name))); + + // Also symlink its source directory + let target_src_out = target_src_dir.join(&dir_name); + let host_src_out = host_src_dir.join(&dir_name); + t!(symlink_dir(&builder.config, &host_src_out, &target_src_out)); + } + + // Sanity check that all directories contain some documentation + for dir in docs.target_dirs.iter().chain(docs.host_dirs.iter()) { + // Making sure the directory exists and is not empty. + assert!(dir.exists(), "Doc directory {dir:?} does not exist"); + assert!(t!(dir.read_dir()).next().is_some(), "Doc directory {dir:?} is empty"); + } +} + +/// Normalizes crate name to get a name that is used to generate documentation on disk. +/// Turns `rustc-main` into `rustc_main`. +fn normalize_doc_crate_name(name: &str) -> String { + name.replace("-", "_") +} + macro_rules! tool_doc { ( $tool: ident, @@ -1048,46 +1324,53 @@ macro_rules! tool_doc { target: TargetSelection, } - impl CommandLineStep for $tool { - type Output = (); - const IS_HOST: bool = true; - - fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path($path) - } - - fn is_default_step(builder: &Builder<'_>) -> bool { - builder.config.compiler_docs - } - - fn make_run(run: RunConfig<'_>) { - let target = run.target; + impl $tool { + fn new(builder: &Builder<'_>, target: TargetSelection) -> $tool { let build_compiler = match $mode { Mode::ToolRustcPrivate => { // Rustdoc needs the rustc sysroot available to build. - let compilers = RustcPrivateCompilers::new(run.builder, run.builder.top_stage, target); + let compilers = RustcPrivateCompilers::new(builder, builder.top_stage, target); // Build rustc docs so that we generate relative links. - run.builder.ensure(Rustc::from_build_compiler(run.builder, compilers.build_compiler(), target)); + builder.ensure(Rustc::from_build_compiler(builder, compilers.build_compiler(), target)); compilers.build_compiler() } Mode::ToolTarget => { // when shipping multiple docs together in one folder, // they all need to use the same rustdoc version - prepare_doc_compiler(run.builder, run.builder.host_target, run.builder.top_stage) + prepare_doc_compiler(builder, builder.host_target, builder.top_stage) } _ => { panic!("Unexpected tool mode for documenting: {:?}", $mode); } }; + $tool { build_compiler, mode: $mode, target } + } + fn crates() -> &'static [&'static str] { + &$($crates)?[..] + } + } + + impl CommandLineStep for $tool { + type Output = BuiltDocs; + const IS_HOST: bool = true; - run.builder.ensure($tool { build_compiler, mode: $mode, target }); + fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { + run.path($path) + } + + fn is_default_step(builder: &Builder<'_>) -> bool { + builder.config.compiler_docs + } + + fn make_run(run: RunConfig<'_>) { + run.builder.ensure($tool::new(run.builder, run.target)); } /// Generates documentation for a tool. /// /// This is largely just a wrapper around `cargo doc`. - fn run(self, builder: &Builder<'_>) { + fn run(self, builder: &Builder<'_>) -> Self::Output { let mut source_type = SourceType::InTree; if let Some(submodule_path) = submodule_path_of(&builder, $path) { @@ -1097,10 +1380,6 @@ macro_rules! tool_doc { let $tool { build_compiler, mode, target } = self; - // This is the intended out directory for compiler documentation. - let out = builder.compiler_doc_out(target); - t!(fs::create_dir_all(&out)); - // Build cargo command. let mut cargo = prepare_tool_cargo( builder, @@ -1122,7 +1401,6 @@ macro_rules! tool_doc { cargo.allow_features(allow_features); } - cargo.arg("-Zskip-rustdoc-fingerprint"); // Only include compiler crates, no dependencies of those, such as `libc`. cargo.arg("--no-deps"); @@ -1130,9 +1408,9 @@ macro_rules! tool_doc { cargo.arg("--lib"); } - $(for krate in $crates { + for krate in $tool::crates() { cargo.arg("-p").arg(krate); - })? + } cargo.rustdocflag("--document-private-items"); // Since we always pass --document-private-items, there's no need to warn about linking to private items. @@ -1141,28 +1419,23 @@ macro_rules! tool_doc { cargo.rustdocflag("--show-type-layout"); cargo.rustdocflag("--generate-link-to-definition"); - let out_dir = builder.stage_out(build_compiler, mode).join(target).join("doc"); - $(for krate in $crates { - let dir_name = krate.replace("-", "_"); - t!(fs::create_dir_all(out_dir.join(&*dir_name))); - })? - - // Symlink compiler docs to the output directory of rustdoc documentation. - symlink_dir_force(&builder.config, &out, &out_dir); - let proc_macro_out_dir = builder.stage_out(build_compiler, mode).join("doc"); - symlink_dir_force(&builder.config, &out, &proc_macro_out_dir); + let cargo_target_dir = builder.stage_out(build_compiler, mode); + let target_doc_dir = cargo_target_dir.join(target).join("doc"); + let host_doc_dir = cargo_target_dir.join("doc"); + for krate in $tool::crates() { + let dir_name = normalize_doc_crate_name(krate); + t!(fs::create_dir_all(target_doc_dir.join(&*dir_name))); + } let _guard = builder.msg(Kind::Doc, stringify!($tool).to_lowercase(), None, build_compiler, target); - cargo.into_cmd().run(builder); + let artifacts = create_docs_and_gather_artifacts(builder, cargo); + artifacts.sanity_check_crates(builder, $tool::crates().iter()); if !builder.config.dry_run() { - // Sanity check on linked doc directories - $(for krate in $crates { - let dir_name = krate.replace("-", "_"); - // Making sure the directory exists and is not empty. - assert!(out.join(&*dir_name).read_dir().unwrap().next().is_some()); - })? + merge_host_and_target_docs(builder, &artifacts, &host_doc_dir, &target_doc_dir); + merge_rustdoc_cci(builder, build_compiler, &artifacts.json_files, &target_doc_dir); } + BuiltDocs { out_dir: target_doc_dir, artifacts } } fn metadata(&self) -> Option { @@ -1344,26 +1617,6 @@ impl CommandLineStep for UnstableBookGen { } } -fn symlink_dir_force(config: &Config, original: &Path, link: &Path) { - if config.dry_run() { - return; - } - if let Ok(m) = fs::symlink_metadata(link) { - if m.file_type().is_dir() { - t!(fs::remove_dir_all(link)); - } else { - // handle directory junctions on windows by falling back to - // `remove_dir`. - t!(fs::remove_file(link).or_else(|_| fs::remove_dir(link))); - } - } - - t!( - symlink_dir(config, original, link), - format!("failed to create link from {} -> {}", link.display(), original.display()) - ); -} - /// Builds the Rust compiler book. #[derive(Debug, Clone, Hash, PartialEq, Eq)] pub struct RustcBook { diff --git a/src/bootstrap/src/core/builder/cargo.rs b/src/bootstrap/src/core/builder/cargo.rs index 754f4a547bd74..98cfd58198a6c 100644 --- a/src/bootstrap/src/core/builder/cargo.rs +++ b/src/bootstrap/src/core/builder/cargo.rs @@ -723,6 +723,12 @@ impl Builder<'_> { } if cmd_kind == Kind::Doc { + // Will be stabilized soon -> let's dogfood it. + // No effect on doc output but massive doc-generation time improvements. + cargo.arg("-Zrustdoc-mergeable-info"); + + // FIXME: remove this directory clearing here, and do it explicitly in individua doc + // steps, to reduce dependency on implicit doc output paths. let my_out = match mode { // This is the intended out directory for compiler documentation. Mode::Rustc | Mode::ToolRustcPrivate | Mode::ToolBootstrap | Mode::ToolTarget => { diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index c221a976b2698..f8b4ebb5841c7 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -965,6 +965,7 @@ impl<'a> Builder<'a> { doc::CargoBook, doc::Clippy, doc::ClippyBook, + doc::CompilerWithTools, doc::Miri, doc::EmbeddedBook, doc::EditionGuide, diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index dd1beb65e7fe0..893fc4f7ee017 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -989,58 +989,6 @@ mod snapshot { ); } - #[test] - fn dist_compiler_docs() { - let ctx = TestCtx::new(); - insta::assert_snapshot!( - ctx.config("dist") - .path("rustc-docs") - .args(&["--set", "build.compiler-docs=true"]) - .render_steps(), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [doc] rustc 1 -> rustc 2 - [build] rustc 1 -> rustc 2 - [doc] rustc 1 -> Rustdoc 2 - [doc] rustc 1 -> Rustfmt 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] rustc 1 -> Cargo 2 - [doc] cargo (book) - [doc] rustc 1 -> Clippy 2 - [doc] clippy (book) - [doc] rustc 1 -> Miri 2 - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> Tidy 2 - [doc] rustc 1 -> Bootstrap 2 - [doc] rustc 1 -> releases 2 - [doc] rustc 1 -> RunMakeSupport 2 - [doc] rustc 1 -> BuildHelper 2 - [doc] rustc 1 -> Compiletest 2 - [build] rustc 0 -> RustInstaller 1 - " - ); - } - #[test] fn dist_extended() { let ctx = TestCtx::new(); @@ -1624,35 +1572,24 @@ mod snapshot { ctx .config("dist") .path("rustc-docs") - .render_steps(), @r" + .render_steps(), @" [build] llvm [build] rustc 0 -> rustc 1 [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] + [doc] rustc 1 -> rustc 2 [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 + [doc] rustc 1 -> Rustdoc 2 + [doc] rustc 1 -> Rustfmt 2 + [doc] rustc 1 -> Clippy 2 + [doc] rustc 1 -> Miri 2 + [doc] rustc 1 -> Cargo 2 + [doc] rustc 1 -> Tidy 2 + [doc] rustc 1 -> Bootstrap 2 + [doc] rustc 1 -> BuildHelper 2 + [doc] rustc 1 -> Compiletest 2 + [doc] rustc 1 -> RunMakeSupport 2 + [doc] rustc 1 -> CompilerWithTools 2 [build] rustc 0 -> RustInstaller 1 "); } @@ -2442,6 +2379,31 @@ mod snapshot { "); } + #[test] + fn doc_compiler_with_tools() { + let ctx = TestCtx::new(); + insta::assert_snapshot!( + ctx.config("doc") + .arg("compiler-with-tools") + .render_steps(), @" + [build] rustdoc 0 + [doc] rustc 0 -> rustc 1 + [build] llvm + [build] rustc 0 -> rustc 1 + [doc] rustc 0 -> Rustdoc 1 + [doc] rustc 0 -> Rustfmt 1 + [doc] rustc 0 -> Clippy 1 + [doc] rustc 0 -> Miri 1 + [doc] rustc 0 -> Cargo 1 + [doc] rustc 0 -> Tidy 1 + [doc] rustc 0 -> Bootstrap 1 + [doc] rustc 0 -> BuildHelper 1 + [doc] rustc 0 -> Compiletest 1 + [doc] rustc 0 -> RunMakeSupport 1 + [doc] rustc 0 -> CompilerWithTools 1 + "); + } + #[test] fn doc_cargo_stage_1() { let ctx = TestCtx::new(); diff --git a/src/bootstrap/src/core/session.rs b/src/bootstrap/src/core/session.rs index 4ad04df753d00..1808f1b8855bc 100644 --- a/src/bootstrap/src/core/session.rs +++ b/src/bootstrap/src/core/session.rs @@ -810,7 +810,7 @@ impl Session { self.out.join(target).join("json-doc") } - /// Output directory for all documentation for a target + /// Output directory for combined compiler + tools docs. pub(crate) fn compiler_doc_out(&self, target: TargetSelection) -> PathBuf { self.out.join(target).join("compiler-doc") } From 0e70786bbaea859c5304a31daf557b8ab8e4b402 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Wed, 30 Sep 2026 23:59:05 -0500 Subject: [PATCH 1125/1309] ping me for debugger visualizer changes --- triagebot.toml | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/triagebot.toml b/triagebot.toml index 611f7724f5cae..d214fafab04e1 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1554,6 +1554,21 @@ cc = ["@mejrs"] message = "Some changes occurred to diagnostic attributes." cc = ["@mejrs"] +[mentions."compiler/rustc_codegen_llvm/src/debuginfo"] +cc = ["@Walnut356"] +[mentions."src/etc/debugger_tester"] +cc = ["@Walnut356"] +[mentions."src/etc/natvis"] +cc = ["@Walnut356"] +[mentions."src/etc/gdb_lookup.py"] +cc = ["@Walnut356"] +[mentions."src/etc/gdb_providers.py"] +cc = ["@Walnut356"] +[mentions."src/etc/lldb_lookup.py"] +cc = ["@Walnut356"] +[mentions."src/etc/lldb_providers.py"] +cc = ["@Walnut356"] + [mentions."RELEASES.md"] message = """ `RELEASES.md` was changed. Upon merging, each section will be automatically synced with its \ From 1188653aeffa390376327267af7f19d684bba918 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Thu, 1 Oct 2026 00:12:34 -0500 Subject: [PATCH 1126/1309] create `debugger_visualizer` assign group --- triagebot.toml | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/triagebot.toml b/triagebot.toml index 611f7724f5cae..1ca1d6a11e396 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -1698,7 +1698,12 @@ ast_lowering = [ "@spastorino", ] debuginfo = [ - "@davidtwco" + "@davidtwco", + "@Walnut356", +] +debugger_visualizer = [ + "@Mark-Simulacrum", + "@Walnut356", ] fallback = [ "@Mark-Simulacrum", @@ -1778,6 +1783,13 @@ dep-bumps = [ "/src/doc/style-guide" = ["style-team"] "/src/doc/unstable-book" = ["compiler"] "/src/etc" = ["@Mark-Simulacrum"] +"/src/etc/gdb_load_rust_pretty_printers.py" = ["debugger_visualizer"] +"/src/etc/gdb_lookup.py" = ["debugger_visualizer"] +"/src/etc/gdb_providers.py" = ["debugger_visualizer"] +"/src/etc/lldb_lookup.py" = ["debugger_visualizer"] +"/src/etc/lldb_providers.py" = ["debugger_visualizer"] +"/src/etc/natvis" = ["debugger_visualizer"] +"/src/etc/rust_types.py" = ["debugger_visualizer"] "/src/librustdoc" = ["rustdoc"] "/src/llvm-project" = ["@cuviper"] "/src/rustdoc-json-types" = ["rustdoc"] From 1dae79f67e60770891da10ed8b9d702a551e3467 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Thu, 1 Oct 2026 09:57:22 +0600 Subject: [PATCH 1127/1309] add test for overcapture suggestion inside attribute macro expansion the test records what the compiler emits today: impl_trait_overcapture_suggestion anchors its suggestion on the opaque def span, which for an opaque inside an attribute macro expansion is the attribute itself, not a type position. the suggestion is machine-applicable, so edition migration applies it and produces error: expected item after attributes --- .../auxiliary/overcapture-attr-pm.rs | 7 ++ ...apture-suggestion-in-macro-issue-139567.rs | 36 +++++++ ...re-suggestion-in-macro-issue-139567.stderr | 97 +++++++++++++++++++ 3 files changed, 140 insertions(+) create mode 100644 tests/ui/impl-trait/precise-capturing/auxiliary/overcapture-attr-pm.rs create mode 100644 tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.rs create mode 100644 tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr diff --git a/tests/ui/impl-trait/precise-capturing/auxiliary/overcapture-attr-pm.rs b/tests/ui/impl-trait/precise-capturing/auxiliary/overcapture-attr-pm.rs new file mode 100644 index 0000000000000..1c2e196ccc619 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/auxiliary/overcapture-attr-pm.rs @@ -0,0 +1,7 @@ +extern crate proc_macro; +use proc_macro::TokenStream; + +#[proc_macro_attribute] +pub fn rpc(_attr: TokenStream, _item: TokenStream) -> TokenStream { + "pub fn generated(x: &u8) -> impl Sized { *x }".parse().unwrap() +} diff --git a/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.rs b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.rs new file mode 100644 index 0000000000000..761678281598a --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.rs @@ -0,0 +1,36 @@ +//@ edition: 2018 +//@ proc-macro: overcapture-attr-pm.rs + +#![allow(unused)] +#![deny(impl_trait_overcaptures)] + +#[overcapture_attr_pm::rpc] +pub fn from_attr_macro() {} +//~^^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +pub fn plain(x: &u8) -> impl Sized { *x } +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +macro_rules! mk { + ($ret:ty) => { + pub fn from_macro_rules(x: &u8) -> $ret { *x } + }; +} + +mk!(impl Sized); +//~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 +//~| WARN this changes meaning in Rust 2024 + +macro_rules! mk_body { + () => { + pub fn from_macro_body(x: &u8) -> impl Sized { *x } + //~^ ERROR `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + //~| WARN this changes meaning in Rust 2024 + }; +} + +mk_body!(); + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr new file mode 100644 index 0000000000000..ab6bd9c11733f --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr @@ -0,0 +1,97 @@ +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:7:1 + | +LL | #[overcapture_attr_pm::rpc] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:7:1 + | +LL | #[overcapture_attr_pm::rpc] + | ^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 + = warning: this changes meaning in Rust 2024 + = note: for more information, see +note: the lint level is defined here + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:5:9 + | +LL | #![deny(impl_trait_overcaptures)] + | ^^^^^^^^^^^^^^^^^^^^^^^ + = note: this error originates in the attribute macro `overcapture_attr_pm::rpc` (in Nightly builds, run with -Z macro-backtrace for more info) +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | #[overcapture_attr_pm::rpc] + use<> + | +++++++ + +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:12:25 + | +LL | pub fn plain(x: &u8) -> impl Sized { *x } + | ^^^^^^^^^^ + | +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:12:17 + | +LL | pub fn plain(x: &u8) -> impl Sized { *x } + | ^ + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | pub fn plain(x: &u8) -> impl Sized + use<> { *x } + | +++++++ + +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:22:5 + | +LL | macro_rules! mk { +... +LL | mk!(impl Sized); + | ^^^^^^^^^^ + | +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:18:36 + | +LL | pub fn from_macro_rules(x: &u8) -> $ret { *x } + | ^ +... +LL | mk!(impl Sized); + | --------------- in this macro invocation + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | mk!(impl Sized + use<>); + | +++++++ + +error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:28:43 + | +LL | macro_rules! mk_body { +LL | () => { +LL | pub fn from_macro_body(x: &u8) -> impl Sized { *x } + | ^^^^^^^^^^ +... +LL | mk_body!(); + | ---------- in this macro invocation + | +note: specifically, this lifetime is in scope but not mentioned in the type's bounds + --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:28:35 + | +LL | pub fn from_macro_body(x: &u8) -> impl Sized { *x } + | ^ +... +LL | mk_body!(); + | ---------- in this macro invocation + = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 + = warning: this changes meaning in Rust 2024 + = note: for more information, see +help: use the precise capturing `use<...>` syntax to make the captures explicit + | +LL | pub fn from_macro_body(x: &u8) -> impl Sized + use<> { *x } + | +++++++ + +error: aborting due to 4 previous errors + From 057e810a4e93f4bde88e1cc5cf4ea185d7dd2b92 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Thu, 1 Oct 2026 09:58:45 +0600 Subject: [PATCH 1128/1309] do not suggest precise capturing when the opaque span is inside a macro expansion impl_trait_overcapture_suggestion anchored every suggestion on tcx.def_span(opaque_def_id) with no expansion check. for an opaque created inside an attribute macro expansion that span is the attribute, which is not a type position, so applying the machine-applicable suggestion breaks the file the obvious patch of calling can_be_used_for_suggestions() on that span directly suppresses all suggestions including for ordinary code, because ast lowering stamps DesugaringKind::OpaqueTy onto the opaque span at compiler/rustc_ast_lowering/src/lib.rs:1825, making from_expansion() unconditionally true. the fix calls parent_callsite() to peel that single desugaring layer and asks can_be_used_for_suggestions() about the span underneath the guard sits at function entry rather than beside the rpit_span push because the apit rename and the generics-list insertion are anchored on the same span, so one check covers all three fixes https://github.com/rust-lang/rust/issues/139567 --- compiler/rustc_trait_selection/src/diagnostics.rs | 12 +++++++++++- ...ercapture-suggestion-in-macro-issue-139567.stderr | 8 -------- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 90f6faaad1dc1..112cbf68f8375 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1935,6 +1935,17 @@ pub fn impl_trait_overcapture_suggestion<'tcx>( fn_def_id: LocalDefId, captured_args: FxIndexSet, ) -> Option { + let rpit_span = tcx.def_span(opaque_def_id); + + // Every suggestion below is anchored on the opaque's span, so bail if that span is not one + // the user can edit. AST lowering marks it with the `impl Trait` desugaring, hence the + // question is about the span it desugared from: for an opaque created inside a macro + // expansion that span is the expansion site, which for an attribute macro is the attribute + // itself, where `+ use<..>` does not even parse. + if rpit_span.parent_callsite().is_some_and(|span| !span.can_be_used_for_suggestions()) { + return None; + } + let generics = tcx.generics_of(fn_def_id); let mut captured_lifetimes = FxIndexSet::default(); @@ -2036,7 +2047,6 @@ pub fn impl_trait_overcapture_suggestion<'tcx>( _ => ("", ""), }; - let rpit_span = tcx.def_span(opaque_def_id); if !lparen.is_empty() { suggs.push((rpit_span.shrink_to_lo(), lparen.to_string())); } diff --git a/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr index ab6bd9c11733f..9f70c2f075942 100644 --- a/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr +++ b/tests/ui/impl-trait/precise-capturing/overcapture-suggestion-in-macro-issue-139567.stderr @@ -18,10 +18,6 @@ note: the lint level is defined here LL | #![deny(impl_trait_overcaptures)] | ^^^^^^^^^^^^^^^^^^^^^^^ = note: this error originates in the attribute macro `overcapture_attr_pm::rpc` (in Nightly builds, run with -Z macro-backtrace for more info) -help: use the precise capturing `use<...>` syntax to make the captures explicit - | -LL | #[overcapture_attr_pm::rpc] + use<> - | +++++++ error: `impl Sized` will capture more lifetimes than possibly intended in edition 2024 --> $DIR/overcapture-suggestion-in-macro-issue-139567.rs:12:25 @@ -88,10 +84,6 @@ LL | mk_body!(); = note: all lifetimes in scope will be captured by `impl Trait`s in edition 2024 = warning: this changes meaning in Rust 2024 = note: for more information, see -help: use the precise capturing `use<...>` syntax to make the captures explicit - | -LL | pub fn from_macro_body(x: &u8) -> impl Sized + use<> { *x } - | +++++++ error: aborting due to 4 previous errors From 31b874075c5fdf252722ec4b952a9ea1d6ba6d62 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 15:55:59 +0200 Subject: [PATCH 1129/1309] Miri can do dirfd now --- library/std/src/sys/fs/unix.rs | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index cc40390fa6200..6cbf442c658b1 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1,7 +1,5 @@ #![allow(nonstandard_style)] #![allow(unsafe_op_in_unsafe_fn)] -// miri has some special hacks here that make things unused. -#![cfg_attr(miri, allow(unused))] #[cfg(test)] mod tests; @@ -988,7 +986,6 @@ impl Drop for DirStream { fn drop(&mut self) { // dirfd isn't supported everywhere #[cfg(not(any( - miri, target_os = "redox", target_os = "nto", target_os = "qnx", @@ -1030,16 +1027,13 @@ impl DirEntry { pub fn metadata(&self) -> io::Result { cfg_select! { // Use directory handle where possible - all( - any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "fuchsia", - target_os = "hurd", - target_os = "illumos", - target_vendor = "apple", - ), - not(miri) // no dirfd on Miri + any( + all(target_os = "linux", not(target_env = "musl")), + target_os = "android", + target_os = "fuchsia", + target_os = "hurd", + target_os = "illumos", + target_vendor = "apple", ) => { let fd = cvt(unsafe { dirfd(self.dir.dirp.0) })?; From 13b380dbe8c7663516961c877ec1736810054de6 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Oct 2026 14:39:05 +1000 Subject: [PATCH 1130/1309] Several small span improvements Limit changes: - Increase `MAX_CTXT`: it is currently `0b0111_1111_1111_1110` (~15 bits). But it only needs to be distinguishable from `CTXT_INTERNED_MARKER` (all 1s). So we can increase it to `0b1111_1111_1111_1110` (~16 bits). The old limit is rarely reached; the `uom` crate is an exception (it has 39k contexts) and we see a 1-2% instruction count reduction when building it. (This value was incorrectly reduced from ~16 bits to ~15 bits in e525e4f10a8 by me; apologies!) Renamings: - Rename `MAX_CTXT` as `MAX_CTXT_OR_PARENT` because it also relates to the parent field. - Remove the `BASE_` prefix from `BASE_LEN_INTERNED_MARKER` because it doesn't mean anything. Comments: - Update parts of the comment that predate the addition of the `parent` field, such as the frequency measurements. (In incremental builds, 20-40% internment due to non-root context and non-zero parent is common.) - Slightly clarify the meanings of the fields in the different forms, and add a paragraph quickly explaining which specific values distinguish the four forms. --- compiler/rustc_span/src/span_encoding.rs | 118 +++++++++++++---------- 1 file changed, 66 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_span/src/span_encoding.rs b/compiler/rustc_span/src/span_encoding.rs index af6f219b4e58e..cc67f34571b3b 100644 --- a/compiler/rustc_span/src/span_encoding.rs +++ b/compiler/rustc_span/src/span_encoding.rs @@ -13,69 +13,79 @@ use crate::{BytePos, SPAN_TRACK, SpanData}; /// A compressed span. /// -/// [`SpanData`] is 16 bytes, which is too big to stick everywhere. `Span` only -/// takes up 8 bytes, with less space for the length, parent and context. The -/// vast majority (99.9%+) of `SpanData` instances can be made to fit within -/// those 8 bytes. Any `SpanData` whose fields don't fit into a `Span` are -/// stored in a separate interner table, and the `Span` will index into that -/// table. Interning is rare enough that the cost is low, but common enough -/// that the code is exercised regularly. +/// [`SpanData`] is 16 bytes, which is too big to stick everywhere. `Span` is +/// only 8 bytes. A large majority of `SpanData` instances can be made to fit +/// within those 8 bytes. Any `SpanData` whose fields don't fit into a `Span` +/// are stored in a separate interner table, and the `Span` will index into +/// that table. /// /// An earlier version of this code used only 4 bytes for `Span`, but that was -/// slower because only 80--90% of spans could be stored inline (even less in -/// very large crates) and so the interner was used a lot more. That version of -/// the code also predated the storage of parents. +/// slower because many fewer spans could be stored inline and the interner was +/// used a lot more. That version of the code also predated the storage of +/// parents. +/// +/// Experiments with uncompressed spans yielded worse performance in most cases +/// because memory usage and cache miss rates are significantly higher without +/// compression. /// /// There are four different span forms. /// -/// Inline-context format (requires non-huge length, non-huge context, and no parent): -/// - `span.lo_or_index == span_data.lo` -/// - `span.len_with_tag_or_marker == len == span_data.hi - span_data.lo` (must be `<= MAX_LEN`) -/// - `span.ctxt_or_parent_or_marker == span_data.ctxt` (must be `<= MAX_CTXT`) +/// Inline-context format (requires ~15-bit length, ~16-bit context, and no parent): +/// - `span.lo_or_index` holds `span_data.lo` +/// - `span.len_with_tag_or_marker` holds `span_data.hi - span_data.lo` (must be `<= MAX_LEN`) +/// - `span.ctxt_or_parent_or_marker` holds `span_data.ctxt` (must be `<= MAX_CTXT_OR_PARENT`) /// -/// Inline-parent format (requires non-huge length, root context, and non-huge parent): -/// - `span.lo_or_index == span_data.lo` -/// - `span.len_with_tag_or_marker & !PARENT_TAG == len == span_data.hi - span_data.lo` -/// (must be `<= MAX_LEN`) -/// - `span.len_with_tag_or_marker` has top bit (`PARENT_TAG`) set -/// - `span.ctxt_or_parent_or_marker == span_data.parent` (must be `<= MAX_CTXT`) +/// Inline-parent format (requires ~15-bit length, root context, and ~16-bit parent): +/// - `span.lo_or_index` holds `span_data.lo` +/// - `span.len_with_tag_or_marker` holds `PARENT_TAG | (span_data.hi - span_data.lo)` +/// (the len part must be `<= MAX_LEN`) +/// - `span.ctxt_or_parent_or_marker` holds `span_data.parent` (must be `<= MAX_CTXT_OR_PARENT`) /// -/// Partially-interned format (requires non-huge context): -/// - `span.lo_or_index == index` (indexes into the interner table) -/// - `span.len_with_tag_or_marker == BASE_LEN_INTERNED_MARKER` -/// - `span.ctxt_or_parent_or_marker == span_data.ctxt` (must be `<= MAX_CTXT`) +/// Partially-interned format (requires ~16-bit context): +/// - `span.lo_or_index` holds the index into the interner table +/// - `span.len_with_tag_or_marker` is `LEN_INTERNED_MARKER` (all 1s) +/// - `span.ctxt_or_parent_or_marker` holds `span_data.ctxt` (must be `<= MAX_CTXT_OR_PARENT`) +/// - Requires looking in the interning table for lo and length, but the +/// context is stored inline as well as interned because context lookups are +/// often done in isolation. /// /// Fully-interned format (all cases not covered above): -/// - `span.lo_or_index == index` (indexes into the interner table) -/// - `span.len_with_tag_or_marker == BASE_LEN_INTERNED_MARKER` -/// - `span.ctxt_or_parent_or_marker == CTXT_INTERNED_MARKER` +/// - `span.lo_or_index` holds the index into the interner table +/// - `span.len_with_tag_or_marker` is `LEN_INTERNED_MARKER` (all 1s) +/// - `span.ctxt_or_parent_or_marker` is `CTXT_INTERNED_MARKER` (all 1s) /// -/// The partially-interned form requires looking in the interning table for -/// lo and length, but the context is stored inline as well as interned. -/// This is useful because context lookups are often done in isolation, and -/// inline lookups are quicker. +/// In short (see `match_span_kind!` for the code version of this): +/// - The absence/presence of `LEN_INTERNED_MARKER` in +/// `len_with_tag_or_marker` distinguishes the inline forms from the interned +/// forms. +/// - The absence/presence of the `PARENT_TAG` bit in +/// `len_with_tag_or_marker` distinguishes inline-context from inline-parent. +/// - The absence/presence of `CTXT_INTERNED_MARKER` in +/// `ctxt_or_parent_or_marker` distinguishes partially-interned from +/// fully-interned. /// /// Notes about the choice of field sizes: +/// /// - `lo` is 32 bits in both `Span` and `SpanData`, which means that `lo` /// values never cause interning. The number of bits needed for `lo` /// depends on the crate size. 32 bits allows up to 4 GiB of code in a crate. /// Having no compression on this field means there is no performance cliff /// if a crate exceeds a particular size. +/// /// - `len` is ~15 bits in `Span` (a u16, minus 1 bit for PARENT_TAG) and 32 /// bits in `SpanData`, which means that large `len` values will cause /// interning. The number of bits needed for `len` does not depend on the /// crate size. The most common numbers of bits for `len` are from 0 to 7, /// with a peak usually at 3 or 4, and then it drops off quickly from 8 -/// onwards. 15 bits is enough for 99.99%+ of cases, but larger values +/// onwards. 15 bits is enough for 99.9%+ of cases, but larger values /// (sometimes 20+ bits) might occur dozens of times in a typical crate. +/// /// - `ctxt_or_parent_or_marker` is 16 bits in `Span` and two 32 bit fields in -/// `SpanData`, which means intering will happen if `ctxt` is large, if +/// `SpanData`, which means interning will happen if `ctxt` is large, if /// `parent` is large, or if both values are non-zero. The number of bits /// needed for `ctxt` values depend partly on the crate size and partly on -/// the form of the code. No crates in `rustc-perf` need more than 15 bits -/// for `ctxt_or_parent_or_marker`, but larger crates might need more than 16 -/// bits. The number of bits needed for `parent` hasn't been measured, -/// because `parent` isn't currently used by default. +/// the form of the code. No crates in `rustc-perf` need more than 16 bits +/// for `ctxt`, but larger crates might. The same is true for `parent`. /// /// In order to reliably use parented spans in incremental compilation, /// accesses to `lo` and `hi` must introduce a dependency to the parent definition's span. @@ -181,7 +191,7 @@ impl PartiallyInterned { #[inline] fn span(index: u32, ctxt: u16) -> Span { let (lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker) = - (index, BASE_LEN_INTERNED_MARKER, ctxt); + (index, LEN_INTERNED_MARKER, ctxt); Span { lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker } } #[inline] @@ -198,7 +208,7 @@ impl Interned { #[inline] fn span(index: u32) -> Span { let (lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker) = - (index, BASE_LEN_INTERNED_MARKER, CTXT_INTERNED_MARKER); + (index, LEN_INTERNED_MARKER, CTXT_INTERNED_MARKER); Span { lo_or_index, len_with_tag_or_marker, ctxt_or_parent_or_marker } } #[inline] @@ -218,7 +228,7 @@ macro_rules! match_span_kind { PartiallyInterned($span3:ident) => $arm3:expr, Interned($span4:ident) => $arm4:expr, ) => { - if $span.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { + if $span.len_with_tag_or_marker != LEN_INTERNED_MARKER { if $span.len_with_tag_or_marker & PARENT_TAG == 0 { // Inline-context format. let $span1 = InlineCtxt::from_span($span); @@ -241,11 +251,14 @@ macro_rules! match_span_kind { } // `MAX_LEN` is chosen so that `PARENT_TAG | MAX_LEN` is distinct from -// `BASE_LEN_INTERNED_MARKER`. (If `MAX_LEN` was 1 higher, this wouldn't be true.) +// `LEN_INTERNED_MARKER`. (If `MAX_LEN` was 1 higher, this wouldn't be true.) const MAX_LEN: u32 = 0b0111_1111_1111_1110; -const MAX_CTXT: u32 = 0b0111_1111_1111_1110; const PARENT_TAG: u16 = 0b1000_0000_0000_0000; -const BASE_LEN_INTERNED_MARKER: u16 = 0b1111_1111_1111_1111; +const LEN_INTERNED_MARKER: u16 = 0b1111_1111_1111_1111; + +// `MAX_CTXT_OR_PARENT` is chosen so it's as big as possible while not equal to +// `CTXT_INTERNED_MARKER`. +const MAX_CTXT_OR_PARENT: u32 = 0b1111_1111_1111_1110; const CTXT_INTERNED_MARKER: u16 = 0b1111_1111_1111_1111; /// The dummy span has zero position, length, and context, and no parent. @@ -266,12 +279,12 @@ impl Span { // Small len and ctxt may enable one of fully inline formats (or may not). let (len, ctxt32) = (hi.0 - lo.0, ctxt.as_u32()); - if len <= MAX_LEN && ctxt32 <= MAX_CTXT { + if len <= MAX_LEN && ctxt32 <= MAX_CTXT_OR_PARENT { match parent { None => return InlineCtxt::span(lo.0, len as u16, ctxt32 as u16), Some(parent) => { let parent32 = parent.local_def_index.as_u32(); - if ctxt32 == 0 && parent32 <= MAX_CTXT { + if ctxt32 == 0 && parent32 <= MAX_CTXT_OR_PARENT { return InlineParent::span(lo.0, len as u16, parent32 as u16); } } @@ -282,7 +295,7 @@ impl Span { let index = |ctxt| { with_span_interner(|interner| interner.intern(&SpanData { lo, hi, ctxt, parent })) }; - if ctxt32 <= MAX_CTXT { + if ctxt32 <= MAX_CTXT_OR_PARENT { // Interned ctxt should never be read, so it can use any value. PartiallyInterned::span(index(SyntaxContext::from_u32(u32::MAX)), ctxt32 as u16) } else { @@ -335,7 +348,7 @@ impl Span { /// Returns `true` if this is a dummy span with any hygienic context. #[inline] pub fn is_dummy(self) -> bool { - if self.len_with_tag_or_marker != BASE_LEN_INTERNED_MARKER { + if self.len_with_tag_or_marker != LEN_INTERNED_MARKER { // Inline-context or inline-parent format. let lo = self.lo_or_index; let len = (self.len_with_tag_or_marker & !PARENT_TAG) as u32; @@ -358,7 +371,7 @@ impl Span { // so it makes sense to micro-optimize it to avoid `span.data()` and `Span::new()`. let new_ctxt = map(SyntaxContext::from_u16(span.ctxt)); let new_ctxt32 = new_ctxt.as_u32(); - return if new_ctxt32 <= MAX_CTXT { + return if new_ctxt32 <= MAX_CTXT_OR_PARENT { // Any small new context including zero will preserve the format. InlineCtxt::span(span.lo, span.len, new_ctxt32 as u16) } else { @@ -399,9 +412,10 @@ impl Span { pub fn eq_ctxt(self, other: Span) -> bool { match (self.inline_ctxt(), other.inline_ctxt()) { (Ok(ctxt1), Ok(ctxt2)) => ctxt1 == ctxt2, - // If `inline_ctxt` returns `Ok` the context is <= MAX_CTXT. - // If it returns `Err` the span is fully interned and the context is > MAX_CTXT. - // As these do not overlap an `Ok` and `Err` result cannot have an equal context. + // If `inline_ctxt` returns `Ok` the context is <= MAX_CTXT_OR_PARENT. + // If it returns `Err` the span is fully interned and the context + // is > MAX_CTXT_OR_PARENT. As these do not overlap an `Ok` and `Err` result cannot + // have an equal context. (Ok(_), Err(_)) | (Err(_), Ok(_)) => false, (Err(index1), Err(index2)) => with_span_interner(|interner| { interner.spans[index1].ctxt == interner.spans[index2].ctxt @@ -421,7 +435,7 @@ impl Span { None => return self, Some(parent) => { let parent32 = parent.local_def_index.as_u32(); - if span.ctxt == 0 && parent32 <= MAX_CTXT { + if span.ctxt == 0 && parent32 <= MAX_CTXT_OR_PARENT { return InlineParent::span(span.lo, span.len, parent32 as u16); } } From 576456671dd90827023a65ac63d44a1d7fda8f98 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Wed, 30 Sep 2026 10:32:18 +0100 Subject: [PATCH 1131/1309] `const impl PartialEq` for `f16b` --- library/core/src/num/bfloat.rs | 3 ++- tests/ui/float/f16b.rs | 17 ++++++++++++++++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/library/core/src/num/bfloat.rs b/library/core/src/num/bfloat.rs index 4937dd8448c60..203ededeb2c0a 100644 --- a/library/core/src/num/bfloat.rs +++ b/library/core/src/num/bfloat.rs @@ -133,7 +133,8 @@ impl Default for f16b { } #[unstable(feature = "f16b", issue = "160630")] -impl PartialEq for f16b { +#[rustc_const_unstable(feature = "const_cmp", issue = "143800")] +const impl PartialEq for f16b { #[inline] fn eq(&self, other: &Self) -> bool { widen(*self).eq(&widen(*other)) diff --git a/tests/ui/float/f16b.rs b/tests/ui/float/f16b.rs index ed143c2c2b2fa..0be9f07de5e05 100644 --- a/tests/ui/float/f16b.rs +++ b/tests/ui/float/f16b.rs @@ -8,7 +8,8 @@ //@ compile-flags: --check-cfg=cfg(target_has_reliable_f16b) -Copt-level=3 //@ run-pass -#![feature(f16b, cfg_target_has_reliable_f16b)] +#![feature(f16b, const_trait_impl, cfg_target_has_reliable_f16b)] +#![cfg_attr(target_has_reliable_f16b, feature(const_cmp))] extern crate core; @@ -22,6 +23,20 @@ const ONE: f16b = f16b::from_bits(0x3f80); #[cfg(target_has_reliable_f16b)] const ONE_BITS: u16 = ONE.to_bits(); +#[cfg(target_has_reliable_f16b)] +const _: () = { + let one = f16b::from_bits(0x3f80); + let two = f16b::from_bits(0x4000); + let positive_zero = f16b::from_bits(0x0000); + let negative_zero = f16b::from_bits(0x8000); + let nan = f16b::from_bits(0x7fc0); + + assert!(one == one); + assert!(one != two); + assert!(positive_zero == negative_zero); + assert!(nan != nan); +}; + #[cfg(target_has_reliable_f16b)] fn assert_traits() where From 3c0c34f3acd6a29e9f12ee906e03b4aa5111d9a7 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Thu, 1 Oct 2026 10:56:51 +0200 Subject: [PATCH 1132/1309] Make `AllocatorNightly` less clever --- library/alloc/src/alloc.rs | 22 ---------------------- library/alloc/src/boxed.rs | 5 ++++- library/alloc/src/rcs/arc.rs | 9 +++++++-- library/alloc/src/rcs/rc.rs | 9 +++++++-- library/core/src/alloc/mod.rs | 26 ++++++++++++++++++++++++++ library/std/src/alloc.rs | 4 ++++ 6 files changed, 48 insertions(+), 27 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index de65820cf9a75..a64cbb5785a03 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -703,27 +703,5 @@ pub mod __alloc_error_handler { } } -/// Allocator marker trait that is implemented only on `Global`, except when -/// the allocator feature gate is enabled (in which case it is implemented -/// for all allocators). -/// -/// This is to prevent stable code from e.g. constructing `Arc` -/// using the `From> for Arc` impl. -/// -/// Note that this trait cannot appear in specialization impls (even if not -/// specialized on). -/// -/// This trait should be used as a bound whenever a function constructing -/// a type with an `#[unstable] A: Allocator = Global` parameter may be -/// callable for `A != Global`. -#[marker] -#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] -#[doc(hidden)] -pub trait AllocatorNightly: Allocator {} - -#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] -#[unstable_feature_bound(allocator_ext)] -impl AllocatorNightly for A {} - #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] impl AllocatorNightly for Global {} diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs index 7504763120532..36af491af1bab 100644 --- a/library/alloc/src/boxed.rs +++ b/library/alloc/src/boxed.rs @@ -206,7 +206,7 @@ use core::task::{Context, Poll}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; -use crate::alloc::{AllocError, Allocator, Global, Layout, StaticAllocator}; +use crate::alloc::{AllocError, Allocator, AllocatorNightly, Global, Layout, StaticAllocator}; use crate::raw_vec::RawVec; #[cfg(not(no_global_oom_handling))] use crate::str::from_boxed_utf8_unchecked_in; @@ -2541,6 +2541,9 @@ unsafe impl Allocator for Box { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Box {} #[unstable(feature = "random", issue = "130703")] impl core::random::Rng for Box { diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index e61ea5193eccb..41e787ace9765 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -23,9 +23,11 @@ use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::sync::atomic::{self, Atomic}; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] -use crate::alloc::{AllocatorNightly, handle_alloc_error}; +use crate::alloc::handle_alloc_error; +use crate::alloc::{ + AllocError, Allocator, AllocatorClone, AllocatorNightly, Global, Layout, StaticAllocator, +}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; use crate::rc::is_dangling; @@ -5199,6 +5201,9 @@ unsafe impl Allocator for Arc { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Arc {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Arc {} diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 8cca09d1d4a8c..e9b4044163001 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -266,9 +266,11 @@ use core::ptr::{self, NonNull, drop_in_place}; use core::slice::from_raw_parts_mut; use core::{borrow, fmt, hint}; -use crate::alloc::{AllocError, Allocator, AllocatorClone, Global, Layout, StaticAllocator}; #[cfg(not(no_global_oom_handling))] -use crate::alloc::{AllocatorNightly, handle_alloc_error}; +use crate::alloc::handle_alloc_error; +use crate::alloc::{ + AllocError, Allocator, AllocatorClone, AllocatorNightly, Global, Layout, StaticAllocator, +}; use crate::borrow::{Cow, ToOwned}; use crate::boxed::Box; #[cfg(not(no_global_oom_handling))] @@ -4792,6 +4794,9 @@ unsafe impl Allocator for Rc { unsafe { (**self).shrink(ptr, old_layout, new_layout) } } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for Rc {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for Rc {} diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 11b9da3032ae7..9f671b739cb14 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -743,6 +743,13 @@ where } } +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl

    AllocatorNightly for core::pin::Pin

    where + P: core::ops::Deref + core::pin::PinSafePointer +{ +} + #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl AllocatorClone for &A {} @@ -753,3 +760,22 @@ unsafe impl StaticAllocator for &A {} #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] unsafe impl StaticAllocator for &mut A {} + +/// Allocator marker trait that is only implemented stably for `Global`. +/// +/// This trait is used as a bound whenever a function constructing +/// a type with an `#[unstable] A: Allocator = Global` parameter +/// may be callable for `A != Global`. +/// +/// This is to prevent stable code from e.g. constructing `Arc` +/// using the `From> for Arc` impl. +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +pub trait AllocatorNightly: Allocator {} + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for &A {} + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for &mut A {} diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index c6f94944006c9..fdca3d12ba3d4 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -504,3 +504,7 @@ pub mod __default_lib_allocator { } } } + +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] +#[unstable_feature_bound(allocator_ext)] +impl AllocatorNightly for System {} From 545535ea830501ff57ca16975f413b2f049571b8 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 1 Oct 2026 11:13:17 +0200 Subject: [PATCH 1133/1309] Bump nightly version -> 2026-10-01 --- clippy_utils/README.md | 2 +- rust-toolchain.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/clippy_utils/README.md b/clippy_utils/README.md index da5d9629f86f3..0ab653b4c65ad 100644 --- a/clippy_utils/README.md +++ b/clippy_utils/README.md @@ -8,7 +8,7 @@ This crate is only guaranteed to build with this `nightly` toolchain: ``` -nightly-2026-09-17 +nightly-2026-10-01 ``` diff --git a/rust-toolchain.toml b/rust-toolchain.toml index f5ae3fb5f52fc..45a4d2504495c 100644 --- a/rust-toolchain.toml +++ b/rust-toolchain.toml @@ -1,6 +1,6 @@ [toolchain] # begin autogenerated nightly -channel = "nightly-2026-09-17" +channel = "nightly-2026-10-01" # end autogenerated nightly components = ["cargo", "llvm-tools", "rust-src", "rust-std", "rustc", "rustc-dev", "rustfmt"] profile = "minimal" From 6ca8bab78c4b625042bd38f00a52f5c216d5140d Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 1 Oct 2026 11:13:21 +0200 Subject: [PATCH 1134/1309] Bump Clippy version -> 0.1.101 --- Cargo.toml | 2 +- clippy_config/Cargo.toml | 2 +- clippy_lints/Cargo.toml | 2 +- clippy_utils/Cargo.toml | 2 +- declare_clippy_lint/Cargo.toml | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index bcf2174ee35ab..653d7fd7fd65d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy" -version = "0.1.100" +version = "0.1.101" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/clippy_config/Cargo.toml b/clippy_config/Cargo.toml index e230f61d558a6..1ef5e94a8fa8a 100644 --- a/clippy_config/Cargo.toml +++ b/clippy_config/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_config" -version = "0.1.100" +version = "0.1.101" edition = "2024" publish = false diff --git a/clippy_lints/Cargo.toml b/clippy_lints/Cargo.toml index 568c15f8d5f53..a8c8e02d8c9bf 100644 --- a/clippy_lints/Cargo.toml +++ b/clippy_lints/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_lints" -version = "0.1.100" +version = "0.1.101" description = "A bunch of helpful lints to avoid common pitfalls in Rust" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" diff --git a/clippy_utils/Cargo.toml b/clippy_utils/Cargo.toml index bf1ea5a799ea9..047ae707eef9c 100644 --- a/clippy_utils/Cargo.toml +++ b/clippy_utils/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "clippy_utils" -version = "0.1.100" +version = "0.1.101" edition = "2024" description = "Helpful tools for writing lints, provided as they are used in Clippy" repository = "https://github.com/rust-lang/rust-clippy" diff --git a/declare_clippy_lint/Cargo.toml b/declare_clippy_lint/Cargo.toml index 682fc1be07006..c30452671f9c1 100644 --- a/declare_clippy_lint/Cargo.toml +++ b/declare_clippy_lint/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "declare_clippy_lint" -version = "0.1.100" +version = "0.1.101" edition = "2024" repository = "https://github.com/rust-lang/rust-clippy" license = "MIT OR Apache-2.0" From cef096d8b81d8e887713430f4d211c43e165729d Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Fri, 25 Sep 2026 00:38:30 +0200 Subject: [PATCH 1135/1309] Add native FreeBSD runner to CI --- src/tools/miri/.github/workflows/ci.yml | 25 ++++++++- src/tools/miri/ci/ci.sh | 9 +++- src/tools/miri/ci/vm-prepare.sh | 53 +++++++++++++++++++ src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 22 ++++++-- .../miri/tests/pass-dep/libc/libc-pipe.rs | 22 ++++++-- .../miri/tests/pass/shims/env/current_exe.rs | 1 + 6 files changed, 121 insertions(+), 11 deletions(-) create mode 100755 src/tools/miri/ci/vm-prepare.sh diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml index 8befdc5db3331..d21198cc60090 100644 --- a/src/tools/miri/.github/workflows/ci.yml +++ b/src/tools/miri/.github/workflows/ci.yml @@ -107,6 +107,27 @@ jobs: - name: clippy run: ./miri clippy -- -D warnings + test-vm-freebsd: + name: test (x86_64-unknown-freebsd) + env: + HOST_TARGET: x86_64-unknown-freebsd + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v6 + - uses: vmactions/freebsd-vm@v1 + with: + # Use FreeBSD 15.x + release: "15" + # We don't want to copy the modified source tree back to the host + # file system as this would just be a waste of time. + copyback: false + envs: HOST_TARGET + prepare: ./ci/vm-prepare.sh + run: | + # Source the cargo environment. + . "$HOME/.cargo/env" + ./ci/ci.sh + style: name: style checks runs-on: ubuntu-latest @@ -194,7 +215,7 @@ jobs: # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! # And they should be added below in `cron-fail-notify` as well. conclusion: - needs: [test, style, bootstrap, coverage, priroda] + needs: [test, test-vm-freebsd, style, bootstrap, coverage, priroda] # We need to ensure this job does *not* get skipped if its dependencies fail, # because a skipped job is considered a success by GitHub. So we have to # overwrite `if:`. We use `!cancelled()` to ensure the job does still not get run @@ -278,7 +299,7 @@ jobs: cron-fail-notify: name: cronjob failure notification runs-on: ubuntu-latest - needs: [test, style, bootstrap, coverage, priroda] + needs: [test, test-vm-freebsd, style, bootstrap, coverage, priroda] if: ${{ github.event_name == 'schedule' && failure() }} steps: # Send a Zulip notification diff --git a/src/tools/miri/ci/ci.sh b/src/tools/miri/ci/ci.sh index 52d634ba7c860..4fa2d4d91e094 100755 --- a/src/tools/miri/ci/ci.sh +++ b/src/tools/miri/ci/ci.sh @@ -1,4 +1,7 @@ -#!/bin/bash +#!/usr/bin/env bash +# Since FreeBSD stores user-installed binaries in `/usr/local/bin` we +# cannot use the `/bin/bash` shebang and instead use the the bash from PATH. + set -eu function begingroup { @@ -202,6 +205,10 @@ case $HOST_TARGET in # Extra tier 1 MANY_SEEDS=64 TEST_TARGET=i686-unknown-linux-gnu run_tests ;; + x86_64-unknown-freebsd) + # Host + MIR_OPT=1 MANY_SEEDS=64 TEST_BENCH=1 CARGO_MIRI_ENV=1 run_tests + ;; *) echo "FATAL: unknown host target: $HOST_TARGET" exit 1 diff --git a/src/tools/miri/ci/vm-prepare.sh b/src/tools/miri/ci/vm-prepare.sh new file mode 100755 index 0000000000000..12a8e0c67a82b --- /dev/null +++ b/src/tools/miri/ci/vm-prepare.sh @@ -0,0 +1,53 @@ +#!/bin/sh +# Prepare an environment in vmactions containers, which don't have many tools +# installed by default. +# +# This file is inspired from . +# It duplicates a lot of the logic in `.github/workflows/setup/action.yml`. + +set -eux + +uname -a +case $HOST_TARGET in + x86_64-unknown-freebsd) deps="pkg install -y libnghttp2 curl bash python" ;; + *) + echo "FATAL: unknown VM host target: $HOST_TARGET" + exit 1 + ;; +esac + +# Installs have been flaky so give them a retry. +count=0 +success=false +while [ $count -lt 3 ]; do + $deps && success=true || true + [ $success = true ] && break + sleep 3s + count=$(( count + 1)) +done + +if [ "$success" != true ]; then + echo "failed to install dependencies" + exit 1 +fi + +# Install rustup and latest stable toolchain. +curl --proto '=https' --tlsv1.2 -sSf --retry 5 https://sh.rustup.rs | sh -s -- \ + --profile minimal \ + --default-toolchain stable \ + --target "$HOST_TARGET" \ + -y + +# Source the cargo environment. +. "$HOME/.cargo/env" + +# Install the tools we need. +cargo install --locked -f rustup-toolchain-install-master hyperfine + +# Install "master" toolchain. +./miri toolchain + +# Show Rust version (miri toolchain). +rustup show +rustc -Vv +cargo -V diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index c1f6a20b75dfc..1745a75830a3f 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -351,7 +351,10 @@ fn test_file_open_nofollow() { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_CLOEXEC) }) .unwrap_err(); - assert_eq!(err.raw_os_error(), Some(libc::ELOOP)); + // FreeBSD returns EMLINK when encountering a symlink on the final path segment with O_NOFOLLOW + // while POSIX specifies returning ELOOP. Since this test is run on both native FreeBSD and native + // Linux hosts, we just assert that its either of those error codes. + assert!([libc::ELOOP, libc::EMLINK].contains(&err.raw_os_error().unwrap())); } } @@ -542,9 +545,9 @@ fn test_posix_mkstemp() { drop(file); remove_file(path).unwrap(); - // Test invalid inputs. We skip this on native macOS since macOS apparently does - // not bother to validate inputs. - if !cfg!(all(not(miri), target_vendor = "apple")) { + // Test invalid inputs. We skip this on native macOS and FreeBSD since those apparently + // don't bother to validate inputs. + if cfg!(miri) || !cfg!(any(target_vendor = "apple", target_os = "freebsd")) { let invalid_templates = vec!["foo", "barXX", "XXXXXXbaz", "whatXXXXXXever", "X"]; for t in invalid_templates { let ptr = CString::new(t).unwrap().into_raw(); @@ -687,6 +690,17 @@ fn test_posix_fallocate>( // Allocate to a bigger size from offset 0 let mut res = unsafe { posix_fallocate(fd, T::from(0), T::from(10)) }; + + if cfg!(all(not(miri), target_os = "freebsd")) { + // On native FreeBSD with a ZFS file system `posix_fallocate` isn't implemented + // and thus always returns EOPNOTSUPP. + if res == libc::EOPNOTSUPP { + // We don't have to execute the remaining tests since we'll always get EOPNOTSUPP. + // Thus, we exit early here. + return; + } + } + assert_eq!(res, 0); assert_eq!(file.metadata().unwrap().len(), 10); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs index e6d833b58defc..c42a850088760 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-pipe.rs @@ -115,6 +115,14 @@ fn test_pipe2() { /// Basic test for pipe fcntl's F_SETFL and F_GETFL flag. fn test_pipe_setfl_getfl() { + if cfg!(all(not(miri), target_os = "freebsd")) { + // FIXME: Pipes are bidirectional on FreeBSD but Miri's shim implements them as + // unidirectional channel. Until we implement FreeBSD's pipe extension in Miri + // we skip this test. + // See + return; + } + // Initialise pipe fds. let mut fds = [-1, -1]; errno_check(unsafe { libc::pipe(fds.as_mut_ptr()) }); @@ -184,10 +192,16 @@ fn test_pipe_fcntl_threaded() { errno_check(unsafe { libc::fcntl(fds[0], libc::F_SETFL, libc::O_NONBLOCK) }); // Check the new flag value while the main thread is still blocked on fds[0]. - assert_eq!( - errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(), - libc::O_NONBLOCK - ); + let flags = errno_result(unsafe { libc::fcntl(fds[0], libc::F_GETFL) }).unwrap(); + + if cfg!(target_os = "freebsd") { + // FreeBSD also reports readable/writable flags in F_GETFL. + // FIXME: check the exact flags, once Miri emulates them correctly. + // See . + assert!(flags & libc::O_NONBLOCK != 0); + } else { + assert_eq!(flags, libc::O_NONBLOCK) + } // The write below will unblock the `read` in main thread: even though // the socket is now "non-blocking", the shim needs to deal correctly diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 898a42b72d134..08eb1e949dfb7 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -1,4 +1,5 @@ //@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target +//@ignore-target: freebsd # On FreeBSD the standard library uses `sysctl` for this, which is not shimmed //@compile-flags: -Zmiri-disable-isolation use std::env; From 7d0683fd2f71a6629f80750867a3fdb87f2bb573 Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 1 Oct 2026 11:30:40 +0200 Subject: [PATCH 1136/1309] Update Cargo.lock --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9894e374a0bf0..6866b2c8e4d92 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -653,7 +653,7 @@ checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" [[package]] name = "clippy" -version = "0.1.100" +version = "0.1.101" dependencies = [ "anstream 0.6.21", "askama", @@ -694,7 +694,7 @@ dependencies = [ [[package]] name = "clippy_config" -version = "0.1.100" +version = "0.1.101" dependencies = [ "arrayvec", "clippy_utils", @@ -705,7 +705,7 @@ dependencies = [ [[package]] name = "clippy_lints" -version = "0.1.100" +version = "0.1.101" dependencies = [ "arrayvec", "cargo_metadata 0.23.1", @@ -735,7 +735,7 @@ dependencies = [ [[package]] name = "clippy_utils" -version = "0.1.100" +version = "0.1.101" dependencies = [ "arrayvec", "itertools", @@ -1148,7 +1148,7 @@ checksum = "a0afaad2b26fa326569eb264b1363e8ae3357618c43982b3f285f0774ce76b69" [[package]] name = "declare_clippy_lint" -version = "0.1.100" +version = "0.1.101" [[package]] name = "derive-where" From 3158ec2b73b405dcc1feee34cbe5b7955fd3c662 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Oct 2026 13:52:37 +1000 Subject: [PATCH 1137/1309] Store `Span` instead of `SpanData` As the comments explain, `Span` does not implement `Send` and so Miri had to store `SpanData` (which does implement `Send`) instead, so certain other types are `Send`. At least, that used to be true. When the serial rustc front-end was removed `Span` became `Send`. So now Miri can store `Span`, which is much more standard than storing `SpanData`. --- .../stacked_borrows/diagnostics.rs | 22 ++++++++-------- .../tree_borrows/diagnostics.rs | 13 +++------- src/tools/miri/src/concurrency/data_race.rs | 4 +-- .../miri/src/concurrency/vector_clock.rs | 7 +---- src/tools/miri/src/diagnostics.rs | 26 +++++++++---------- src/tools/miri/src/machine.rs | 12 +++------ src/tools/miri/src/shims/foreign_items.rs | 8 +++--- src/tools/miri/src/shims/sig.rs | 2 +- 8 files changed, 40 insertions(+), 54 deletions(-) diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs index 8f6a508e605a0..3dd8c710a0274 100644 --- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs @@ -2,7 +2,7 @@ use std::fmt; use rustc_abi::Size; use rustc_data_structures::fx::FxHashSet; -use rustc_span::{Span, SpanData}; +use rustc_span::Span; use smallvec::SmallVec; use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind}; @@ -33,12 +33,12 @@ struct Creation { } impl Creation { - fn generate_diagnostic(&self) -> (String, SpanData) { + fn generate_diagnostic(&self) -> (String, Span) { let tag = self.retag.new_tag; if let Some(perm) = self.retag.permission { ( format!("{tag:?} was created by a {perm:?} retag at offsets {}", self.retag.range), - self.span.data(), + self.span, ) } else { assert!(self.retag.range.size == Size::ZERO); @@ -47,7 +47,7 @@ impl Creation { "{tag:?} would have been created here, but this is a zero-size retag ({}) so the tag in question does not exist anywhere", self.retag.range, ), - self.span.data(), + self.span, ) } } @@ -68,7 +68,7 @@ enum InvalidationCause { } impl Invalidation { - fn generate_diagnostic(&self) -> (String, SpanData) { + fn generate_diagnostic(&self) -> (String, Span) { let message = if matches!( self.cause, InvalidationCause::Retag(_, RetagInfo { cause: RetagCause::FnEntry, .. }) @@ -85,7 +85,7 @@ impl Invalidation { self.tag, self.range, self.cause ) }; - (message, self.span.data()) + (message, self.span) } } @@ -107,9 +107,9 @@ struct Protection { #[derive(Clone)] pub struct TagHistory { - pub created: (String, SpanData), - pub invalidated: Option<(String, SpanData)>, - pub protected: Option<(String, SpanData)>, + pub created: (String, Span), + pub invalidated: Option<(String, Span)>, + pub protected: Option<(String, Span)>, } pub struct DiagnosticCxBuilder<'ecx, 'tcx> { @@ -342,7 +342,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { "{tag:?} was created here, as the root tag for {}", self.history.id ), - self.history.root.1.data(), + self.history.root.1, )) } else { None @@ -364,7 +364,7 @@ impl<'history, 'ecx, 'tcx> DiagnosticCx<'history, 'ecx, 'tcx> { }) .map(|protection| { let protected_tag = protection.tag; - (format!("{protected_tag:?} is this argument"), protection.span.data()) + (format!("{protected_tag:?} is this argument"), protection.span) }); Some(TagHistory { created, invalidated, protected }) diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs index 9d4c446b14f85..79c182f5b02a2 100644 --- a/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs +++ b/src/tools/miri/src/borrow_tracker/tree_borrows/diagnostics.rs @@ -2,7 +2,7 @@ use std::fmt; use std::ops::Range; use rustc_data_structures::fx::FxHashMap; -use rustc_span::{Span, SpanData}; +use rustc_span::Span; use crate::borrow_tracker::tree_borrows::perms::{PermTransition, Permission}; use crate::borrow_tracker::tree_borrows::tree::LocationState; @@ -115,12 +115,9 @@ pub struct History { } /// History formatted for use by `src/diagnostics.rs`. -/// -/// NOTE: needs to be `Send` because of a bound on `MachineStopType`, hence -/// the use of `SpanData` rather than `Span`. #[derive(Debug, Clone, Default)] pub struct HistoryData { - pub events: Vec<(Option, String)>, // includes creation + pub events: Vec<(Option, String)>, // includes creation } impl History { @@ -132,8 +129,6 @@ impl History { impl HistoryData { // Format events from `new_history` into those recorded by `self`. - // - // NOTE: also converts `Span` to `SpanData`. fn extend(&mut self, new_history: History, tag_name: &'static str, show_initial_state: bool) { let History { tag, created, events } = new_history; let this = format!("the {tag_name} tag {tag:?}"); @@ -143,7 +138,7 @@ impl HistoryData { maybe_msg_initial_state = if show_initial_state { &msg_initial_state } else { "" }, ); - self.events.push((Some(created.0.data()), msg_creation)); + self.events.push((Some(created.0), msg_creation)); for &Event { transition, is_foreign, @@ -161,7 +156,7 @@ impl HistoryData { None => format!("on every location previously accessed by this tag"), }; self.events.push(( - Some(span.data()), + Some(span), format!( "{this} later transitioned to {endpoint} due to a {access} {access_range_text}", endpoint = transition.endpoint() diff --git a/src/tools/miri/src/concurrency/data_race.rs b/src/tools/miri/src/concurrency/data_race.rs index c086f71c2dcaa..f9b2a0eece9b8 100644 --- a/src/tools/miri/src/concurrency/data_race.rs +++ b/src/tools/miri/src/concurrency/data_race.rs @@ -1184,12 +1184,12 @@ impl VClockAlloc { op1: RacingOp { action: other_access.description(None, other_size), thread_info: other_thread_info, - span: other_clock.as_slice()[other_thread.index()].span_data(), + span: other_clock.as_slice()[other_thread.index()].span, }, op2: RacingOp { action: access.description(ty, other_size.map(|_| access_size)), thread_info: active_thread_info, - span: active_clocks.clock.as_slice()[active_index.index()].span_data(), + span: active_clocks.clock.as_slice()[active_index.index()].span, }, }))? } diff --git a/src/tools/miri/src/concurrency/vector_clock.rs b/src/tools/miri/src/concurrency/vector_clock.rs index d7ea3b0c6ce3d..723dfd2965152 100644 --- a/src/tools/miri/src/concurrency/vector_clock.rs +++ b/src/tools/miri/src/concurrency/vector_clock.rs @@ -3,7 +3,7 @@ use std::fmt::Debug; use std::ops::{Index, Shr}; use rustc_index::Idx; -use rustc_span::{DUMMY_SP, Span, SpanData}; +use rustc_span::{DUMMY_SP, Span}; use smallvec::SmallVec; use super::data_race::NaReadType; @@ -103,11 +103,6 @@ impl VTimestamp { pub(super) fn set_read_type(&mut self, read_type: NaReadType) { self.time_and_read_type = Self::encode_time_and_read_type(self.time(), read_type); } - - #[inline] - pub(super) fn span_data(&self) -> SpanData { - self.span.data() - } } impl PartialEq for VTimestamp { diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs index 793c7d6f0401b..7c5b38e9a4891 100644 --- a/src/tools/miri/src/diagnostics.rs +++ b/src/tools/miri/src/diagnostics.rs @@ -5,7 +5,7 @@ use std::sync::Mutex; use rustc_abi::{Align, Size}; use rustc_data_structures::fx::{FxBuildHasher, FxHashSet}; use rustc_errors::{Diag, Level}; -use rustc_span::{DUMMY_SP, Span, SpanData, Symbol}; +use rustc_span::{DUMMY_SP, Span, Symbol}; use crate::borrow_tracker::stacked_borrows::diagnostics::TagHistory; use crate::borrow_tracker::tree_borrows::diagnostics as tree_diagnostics; @@ -41,14 +41,14 @@ pub enum TerminationInfo { LocalDeadlock, MultipleSymbolDefinitions { link_name: Symbol, - first: SpanData, + first: Span, first_crate: Symbol, - second: SpanData, + second: Span, second_crate: Symbol, }, SymbolShimClashing { link_name: Symbol, - span: SpanData, + span: Span, }, DataRace { involves_non_atomic: bool, @@ -64,7 +64,7 @@ pub enum TerminationInfo { pub struct RacingOp { pub action: String, pub thread_info: String, - pub span: SpanData, + pub span: Span, } impl fmt::Display for TerminationInfo { @@ -554,8 +554,8 @@ fn report_msg<'tcx>( diag_level: DiagLevel, title: String, span_msg: Vec, - notes: Vec<(Option, String)>, - helps: Vec<(Option, String)>, + notes: Vec<(Option, String)>, + helps: Vec<(Option, String)>, stacktrace: &[FrameInfo<'tcx>], thread: Option, machine: &MiriMachine<'tcx>, @@ -581,16 +581,16 @@ fn report_msg<'tcx>( } // Show note and help messages. - for (span_data, note) in notes { - if let Some(span_data) = span_data { - err.span_note(span_data.span(), note); + for (span, note) in notes { + if let Some(span) = span { + err.span_note(span, note); } else { err.note(note); } } - for (span_data, help) in helps { - if let Some(span_data) = span_data { - err.span_help(span_data.span(), help); + for (span, help) in helps { + if let Some(span) = span { + err.span_help(span, help); } else { err.help(help); } diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index 65eb6e10d4518..cba1df6b1d7d2 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -30,7 +30,7 @@ use rustc_middle::ty::layout::{ use rustc_middle::ty::{self, AtomicOrdering, Instance, Ty, TyCtxt}; use rustc_session::config::InliningThreshold; use rustc_span::def_id::{CrateNum, DefId}; -use rustc_span::{Span, SpanData, Symbol}; +use rustc_span::{Span, Symbol}; use rustc_symbol_mangling::mangle_internal_symbol; use rustc_target::callconv::FnAbi; use rustc_target::spec::{Arch, Os}; @@ -950,19 +950,15 @@ impl<'tcx> MiriMachine<'tcx> { Align::from_bytes(self.page_size).unwrap() } - pub(crate) fn allocated_span(&self, alloc_id: AllocId) -> Option { - self.allocation_spans - .borrow() - .get(&alloc_id) - .map(|(allocated, _deallocated)| allocated.data()) + pub(crate) fn allocated_span(&self, alloc_id: AllocId) -> Option { + self.allocation_spans.borrow().get(&alloc_id).map(|(allocated, _deallocated)| *allocated) } - pub(crate) fn deallocated_span(&self, alloc_id: AllocId) -> Option { + pub(crate) fn deallocated_span(&self, alloc_id: AllocId) -> Option { self.allocation_spans .borrow() .get(&alloc_id) .and_then(|(_allocated, deallocated)| *deallocated) - .map(Span::data) } fn init_allocation( diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index 66d65ead7c7bd..224cde622d17e 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -176,9 +176,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_machine_stop!( TerminationInfo::MultipleSymbolDefinitions { link_name, - first: original_span.data(), + first: original_span, first_crate: tcx.crate_name(original.cnum), - second: span.data(), + second: span, second_crate: tcx.crate_name(cnum), } ); @@ -186,9 +186,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_machine_stop!( TerminationInfo::MultipleSymbolDefinitions { link_name, - first: span.data(), + first: span, first_crate: tcx.crate_name(cnum), - second: original_span.data(), + second: original_span, second_crate: tcx.crate_name(original.cnum), } ); diff --git a/src/tools/miri/src/shims/sig.rs b/src/tools/miri/src/shims/sig.rs index 853f7381ccdf5..091f1f80d82f1 100644 --- a/src/tools/miri/src/shims/sig.rs +++ b/src/tools/miri/src/shims/sig.rs @@ -284,7 +284,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_machine_stop!(TerminationInfo::SymbolShimClashing { link_name, - span: this.tcx.def_span(instance.def_id()).data(), + span: this.tcx.def_span(instance.def_id()), }) } interp_ok(()) From fdc7532b310f64d44fd35b0c48f6fbcbde65e92d Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Oct 2026 12:07:09 +0200 Subject: [PATCH 1138/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 837b18aae097503892d7aab6c7ddce332a991a21. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index eb8c4fb20edfe..716d825e606bc 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -5c543b0b8c73c7b72bc8284ced4fb22ead15734d +837b18aae097503892d7aab6c7ddce332a991a21 From a8a811140a3fe3066859a8c2979142005b381641 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Oct 2026 11:33:12 +0200 Subject: [PATCH 1139/1309] Revert "temporarily disable broken test on freebsd" This reverts commit ab956667801480a745969fedced5dd5c92372a49. --- .../tests/pass/shims/available-parallelism-miri-num-cpus.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs index fa83de8bc127e..0d96bc2f5e737 100644 --- a/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs +++ b/src/tools/miri/tests/pass/shims/available-parallelism-miri-num-cpus.rs @@ -1,6 +1,4 @@ //@compile-flags: -Zmiri-num-cpus=1024 -// FIXME: Disabled on FreeBSD due to -//@ignore-target: freebsd use std::num::NonZero; use std::thread::available_parallelism; From 38c6e9545ded714c2ec24f493a72579cae0856a4 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Sep 2026 11:39:45 +1000 Subject: [PATCH 1140/1309] Clarify `OnceNote`/`OnceHelp` subdiag deduplication - Introduce `Subdiag::dedup_hash`, which mirrors `DiagInner::dedup_hash` and is necessary for the subsequent commits. - Change the name and structure of `not_yet_emitted` to be clearer. - Change `retain_mut` to `retain`; mutability isn't required. --- compiler/rustc_errors/src/diagnostic.rs | 15 +++++++++++++++ compiler/rustc_errors/src/lib.rs | 16 ++++++---------- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 362df06c404db..e8780cb8f4286 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -324,6 +324,21 @@ pub struct Subdiag { pub span: MultiSpan, } +impl Subdiag { + /// Hash used to determine if two subdiagnostics are the same. Used by + /// `DiagCtxtInner::emitted_diagnostics`. + pub(crate) fn dedup_hash(&self) -> Hash128 { + // Deconstruct to ensure all fields are considered. + let Subdiag { level, messages, span } = self; + + let hashed_parts = (level, messages, span); + + let mut hasher = StableHasher::new(); + hashed_parts.hash(&mut hasher); + hasher.finish() + } +} + /// Used for emitting structured error messages and other diagnostic information. /// Wraps a `DiagInner`, adding some useful things. /// - The `dcx` field, allowing it to (a) emit itself, and (b) do a drop check diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 4cc5d5c230d15..47473b568f58c 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -44,7 +44,6 @@ use emitter::{DynEmitter, Emitter}; use rustc_ast::attr::version::RustcVersion; use rustc_data_structures::AtomicRef; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, FxIndexSet}; -use rustc_data_structures::stable_hash::StableHasher; use rustc_data_structures::sync::{DynSend, Lock}; pub use rustc_error_messages::{ DiagArg, DiagArgFromDisplay, DiagArgMap, DiagArgName, DiagArgValue, DiagMessage, IntoDiagArg, @@ -1321,21 +1320,18 @@ impl DiagCtxtInner { debug!(?diagnostic); debug!(?self.emitted_diagnostics); - let not_yet_emitted = |sub: &mut Subdiag| { + let show_sub = |sub: &Subdiag| { debug!(?sub); match sub.level { Sublevel::Error | Sublevel::Warning | Sublevel::Note | Sublevel::Help => { - return true; + true + } + Sublevel::OnceNote | Sublevel::OnceHelp => { + self.emitted_diagnostics.insert(sub.dedup_hash()) } - Sublevel::OnceNote | Sublevel::OnceHelp => {} } - let mut hasher = StableHasher::new(); - sub.hash(&mut hasher); - let diagnostic_hash = hasher.finish(); - debug!(?diagnostic_hash); - self.emitted_diagnostics.insert(diagnostic_hash) }; - diagnostic.children.retain_mut(not_yet_emitted); + diagnostic.children.retain(show_sub); if already_emitted { let msg = "duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`"; diagnostic.sub(Sublevel::Note, msg, MultiSpan::new()); From f8df28d4555660e74a9e015f24804af0786b9413 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Sep 2026 14:36:52 +1000 Subject: [PATCH 1141/1309] Add a test demonstrating the problem Currently deduplication erroneously has no effect with incremental enabled because the span parent gets included in the hash used for deduplication. --- .../deduplicate-diagnostics-incr.dedup.stderr | 15 ++++++ .../deduplicate-diagnostics-incr.dup.stderr | 54 +++++++++++++++++++ ...plicate-diagnostics-incr.incr-dedup.stderr | 51 ++++++++++++++++++ ...duplicate-diagnostics-incr.incr-dup.stderr | 51 ++++++++++++++++++ .../deduplicate-diagnostics-incr.rs | 17 ++++++ 5 files changed, 188 insertions(+) create mode 100644 tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr create mode 100644 tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr create mode 100644 tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr create mode 100644 tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr create mode 100644 tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr new file mode 100644 index 0000000000000..e8fb5732febdc --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dedup.stderr @@ -0,0 +1,15 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr new file mode 100644 index 0000000000000..017884aff53a4 --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.dup.stderr @@ -0,0 +1,54 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr new file mode 100644 index 0000000000000..8cfd815b10d5f --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr new file mode 100644 index 0000000000000..8cfd815b10d5f --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr @@ -0,0 +1,51 @@ +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied + --> $DIR/deduplicate-diagnostics-incr.rs:11:11 + | +LL | #[global_allocator] + | ------------------- in this attribute macro expansion +LL | static A: usize = 0; + | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` + | +help: the trait `GlobalAllocator` is implemented for `System` + --> $SRC_DIR/std/src/alloc.rs:LL:COL + = note: required for `usize` to implement `GlobalAlloc` + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs new file mode 100644 index 0000000000000..daa42492686db --- /dev/null +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs @@ -0,0 +1,17 @@ +//! Test that span parents (which are incremental only) are ignored when deduplicating diagnostics. +//! Regression test for #162901. + +//@ revisions: dedup dup incr-dedup incr-dup +//@[dedup] compile-flags: -Z deduplicate-diagnostics=yes +//@[incr-dup] incremental +//@[incr-dedup] incremental +//@[incr-dedup] compile-flags: -Z deduplicate-diagnostics=yes + +#[global_allocator] +static A: usize = 0; +//[dedup,dup,incr-dedup,incr-dup]~^ ERROR E0277 +//[dup,incr-dedup,incr-dup]~| ERROR E0277 +//[dup,incr-dedup,incr-dup]~| ERROR E0277 +//[dup,incr-dedup,incr-dup]~| ERROR E0277 + +fn main() {} From 0efd8697df1eded0de98c28d2005a84a4d5bc46e Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Sep 2026 22:22:56 +1000 Subject: [PATCH 1142/1309] Fix `encoder_methods!` macro So it applies the `#[inline]` to every method, not just the first one. --- compiler/rustc_middle/src/query/on_disk_cache.rs | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 20c1c5c16c95c..738521b2005e0 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -929,10 +929,12 @@ impl<'tcx> TyEncoder<'tcx> for CacheEncoder<'tcx> { macro_rules! encoder_methods { ($($name:ident($ty:ty);)*) => { - #[inline] - $(fn $name(&mut self, value: $ty) { - self.encoder.$name(value) - })* + $( + #[inline] + fn $name(&mut self, value: $ty) { + self.encoder.$name(value) + } + )* } } From e9800d415d26588c0fc745cfceec5208b736dd7d Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Wed, 30 Sep 2026 11:31:37 +0200 Subject: [PATCH 1143/1309] Update documentaton of `PointeeInfo::size` --- compiler/rustc_abi/src/lib.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index df2dca6ec252b..3804f4281a9bb 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2354,9 +2354,12 @@ pub struct PointeeInfo { /// If `size` is not zero, then the pointer is either null or dereferenceable for this many bytes /// (independent of `safe`). /// - /// On a function argument, "dereferenceable" here means "dereferenceable for the entire duration - /// of this function call", i.e. it is UB for the memory that this pointer points to be freed - /// while this function is still running. + /// "Dereferenceable" means that it's sound to add a speculative (spurious) read of the pointer. + /// The backend is free to add such reads at will. (This is useful to hoist pointer reads out of + /// loops without proving that the loop executes at least once, for example.) + /// + /// This can be used in both argument and return position, in both cases it means + /// "dereferenceable right now" (function entry/return) (but could be freed any time later). pub size: Size, /// The pointer is guaranteed to be aligned this much (independent of `safe`). pub align: Align, From 678cc792b41a13a28bfef3445784b314e395e8a1 Mon Sep 17 00:00:00 2001 From: Waffle Lapkin Date: Mon, 28 Sep 2026 13:08:16 +0200 Subject: [PATCH 1144/1309] only set `dereferenceable` for `&Freeze` / `&mut Unpin` ... in order to comply with semantics where `dereferenceable` implies a spurious read. --- compiler/rustc_middle/src/ty/layout.rs | 51 +++++++++++++++------ tests/codegen-llvm/drop-in-place-noalias.rs | 9 +--- tests/codegen-llvm/function-arguments.rs | 19 +++----- tests/codegen-llvm/llvm-writable.rs | 3 +- 4 files changed, 46 insertions(+), 36 deletions(-) diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index 7952b97e94e13..8806bf992fc0e 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -1061,19 +1061,40 @@ where } ty::Ref(_, ty, mt) if offset.bytes() == 0 => { tcx.layout_of(typing_env.as_query_input(ty)).ok().map(|layout| { - let kind = match mt { + let kind; + let size; + + match mt { hir::Mutability::Not => { let frozen = optimize && ty.is_freeze(tcx, typing_env); - PointerKind::SharedRef { frozen } + kind = PointerKind::SharedRef { frozen }; + + // Set the `size` to zero for non-frozen shared references. + // + // `PointeeInfo::size` is defined to allow adding spurious reads. + // Adding spurious reads is only valid for `&Freeze` and `&mut Unpin` + // references, as otherwise the spurious read can invalidate aliasing + // references. + // + // See discussions in + // - https://github.com/rust-lang/unsafe-code-guidelines/issues/381 + // - https://github.com/llvm/llvm-project/pull/218413 + // - https://discourse.llvm.org/t/interaction-of-noalias-and-dereferenceable/66979 + size = layout.size * frozen as _; } hir::Mutability::Mut => { let unpin = optimize && ty.is_unpin(tcx, typing_env) && ty.is_unsafe_unpin(tcx, typing_env); - PointerKind::MutableRef { unpin } + kind = PointerKind::MutableRef { unpin }; + + // Set the `size` to zero for non-unpin unique references. + // See the above comment for reasons to do this. + size = layout.size * unpin as _; } }; - PointeeInfo { safe: Some(kind), size: layout.size, align: layout.align.abi } + + PointeeInfo { safe: Some(kind), size, align: layout.align.abi } }) } @@ -1081,16 +1102,18 @@ where if offset.bytes() == 0 && let Some(pointee) = this.ty.boxed_ty() => { - tcx.layout_of(typing_env.as_query_input(pointee)).ok().map(|layout| PointeeInfo { - safe: Some(PointerKind::Box { - // Same logic as for mutable references above. - unpin: optimize - && pointee.is_unpin(tcx, typing_env) - && pointee.is_unsafe_unpin(tcx, typing_env), - global: this.ty.is_box_global(tcx), - }), - size: layout.size, - align: layout.align.abi, + tcx.layout_of(typing_env.as_query_input(pointee)).ok().map(|layout| { + // Same logic as for mutable references above. + let unpin = optimize + && pointee.is_unpin(tcx, typing_env) + && pointee.is_unsafe_unpin(tcx, typing_env); + let size = layout.size * unpin as _; + + PointeeInfo { + safe: Some(PointerKind::Box { unpin, global: this.ty.is_box_global(tcx) }), + size, + align: layout.align.abi, + } }) } diff --git a/tests/codegen-llvm/drop-in-place-noalias.rs b/tests/codegen-llvm/drop-in-place-noalias.rs index caa00bfa1c2c3..86e0caa1b287d 100644 --- a/tests/codegen-llvm/drop-in-place-noalias.rs +++ b/tests/codegen-llvm/drop-in-place-noalias.rs @@ -1,10 +1,4 @@ //@ compile-flags: -Copt-level=3 -C no-prepopulate-passes -// -// LLVM23 changed the meaning of "dereferenceable", allowing us to apply it in more cases, -// see . -//@ revisions: LLVM22 LLVM23 -//@ [LLVM22] max-llvm-major-version: 22 -//@ [LLVM23] min-llvm-version: 23 // Tests that the compiler can apply `noalias` and other &mut attributes to `drop_in_place`. // Note that non-Unpin types should not get `noalias`, matching &mut behavior. @@ -15,8 +9,7 @@ use std::marker::PhantomPinned; // CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructUnpin{{.*}}(ptr noalias nofree noundef align 4 dereferenceable(12) %{{.+}}) -// LLVM22: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}}) -// LLVM23: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef align 4 dereferenceable(12) %{{.+}}) +// CHECK: define internal void @{{.*}}core{{.*}}ptr{{.*}}drop_in_place{{.*}}StructNotUnpin{{.*}}(ptr noundef nonnull align 4 %{{.+}}) pub struct StructUnpin { a: i32, diff --git a/tests/codegen-llvm/function-arguments.rs b/tests/codegen-llvm/function-arguments.rs index 47600826b814b..0a6d9fdefac39 100644 --- a/tests/codegen-llvm/function-arguments.rs +++ b/tests/codegen-llvm/function-arguments.rs @@ -98,8 +98,7 @@ pub fn readonly_borrow_ret() -> &'static i32 { loop {} } -// LLVM22: @unsafe_borrow(ptr noundef nonnull align 2 %_1) -// LLVM23: @unsafe_borrow(ptr noundef align 2 dereferenceable(2) %_1) +// CHECK: @unsafe_borrow(ptr noundef nonnull align 2 %_1) // unsafe interior means this isn't actually readonly and there may be aliases ... #[no_mangle] pub fn unsafe_borrow(_: &UnsafeInner) {} @@ -121,10 +120,9 @@ pub fn mutable_borrow_ret() -> &'static mut i32 { } #[no_mangle] -// LLVM22: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1) -// LLVM23: @mutable_notunpin_borrow(ptr noundef align 4 dereferenceable(4) %_1) +// CHECK: @mutable_notunpin_borrow(ptr noundef nonnull align 4 %_1) // This one is *not* `noalias` because it might be self-referential. -// It is also not `dereferenceable` prior to LLVM23 due to +// It is also not `dereferenceable` due to // . pub fn mutable_notunpin_borrow(_: &mut NotUnpin) {} @@ -176,8 +174,7 @@ pub fn _box_custom(x: Box) { drop(x) } -// LLVM22: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) -// LLVM23: noundef align 4 dereferenceable(4) ptr @notunpin_box(ptr noundef align 4 dereferenceable(4) %x) +// CHECK: noundef nonnull align 4 ptr @notunpin_box(ptr noundef nonnull align 4 %x) #[no_mangle] pub fn notunpin_box(x: Box) -> Box { x @@ -252,16 +249,14 @@ pub fn trait_box_pin1(_: Box) {} pub fn trait_box_pin2(_: Box) {} // Same for mutable references (with a non-zero minimal size so that we also see the -// `dereferenceable` disappear prior to llvm23). +// `dereferenceable` disappear). // CHECK: @trait_mutref(ptr noalias nofree noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref(_: &mut (i32, dyn Drop + Unpin + UnsafeUnpin)) {} -// LLVM22: @trait_mutref_pin1(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) -// LLVM23: @trait_mutref_pin1(ptr noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// CHECK: @trait_mutref_pin1(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref_pin1(_: &mut (i32, dyn Drop + Unpin)) {} -// LLVM22: @trait_mutref_pin2(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) -// LLVM23: @trait_mutref_pin2(ptr noundef align 4 dereferenceable(4){{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) +// CHECK: @trait_mutref_pin2(ptr noundef nonnull align 4{{( %_1.0)?}}, {{.+}} noalias nofree noundef readonly align {{.*}} dereferenceable({{.*}}){{( %_1.1)?}}) #[no_mangle] pub fn trait_mutref_pin2(_: &mut (i32, dyn Drop + UnsafeUnpin)) {} diff --git a/tests/codegen-llvm/llvm-writable.rs b/tests/codegen-llvm/llvm-writable.rs index 81a952a6483d4..a5f5359e96065 100644 --- a/tests/codegen-llvm/llvm-writable.rs +++ b/tests/codegen-llvm/llvm-writable.rs @@ -28,8 +28,7 @@ pub fn option_borrow_mut(_: Option<&mut i32>) {} #[no_mangle] pub fn box_moved(_: Box) {} -// LLVM22: @unsafe_pinned_borrow_mut(ptr noundef nonnull align 4 %_1) -// LLVM23: @unsafe_pinned_borrow_mut(ptr noundef align 4 dereferenceable(4) %_1) +// CHECK: @unsafe_pinned_borrow_mut(ptr noundef nonnull align 4 %_1) #[no_mangle] pub fn unsafe_pinned_borrow_mut(_: &mut std::pin::UnsafePinned) {} From 64f5516c3baf5d1e232dc67c65649970ff28b036 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Thu, 1 Oct 2026 12:43:47 +0200 Subject: [PATCH 1145/1309] Add `SplitPathsRef` implementation for motor --- library/std/src/sys/paths/motor.rs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/library/std/src/sys/paths/motor.rs b/library/std/src/sys/paths/motor.rs index 82f8a35e50db6..cd7605d6f2662 100644 --- a/library/std/src/sys/paths/motor.rs +++ b/library/std/src/sys/paths/motor.rs @@ -15,6 +15,16 @@ pub fn split_paths(unparsed: &OsStr) -> SplitPaths<'_> { unparsed.as_str().split(PATH_SEPARATOR).map(into_pathbuf as fn(&str) -> PathBuf) } +pub type SplitPathsRef<'a> = iter::Map, fn(&str) -> &path::Path>; + +pub fn split_paths_ref(unparsed: &OsStr) -> Option> { + fn as_path(part: &str) -> &path::Path { + part.as_ref() + } + + Some(unparsed.as_str().split(PATH_SEPARATOR).map(as_path as fn(&str) -> &path::Path)) +} + #[derive(Debug)] pub struct JoinPathsError; From 2599fb7e71f472b13f87c6d39d09f3df5ff55434 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 25 Sep 2026 23:49:09 +0200 Subject: [PATCH 1146/1309] Correctly handle `rustc_allow_incoherent_impl` on primitive methods --- src/librustdoc/html/format.rs | 16 +++++++++++- .../auxiliary/incoherent_impl_primitive.rs | 7 ++++++ .../jump-to-def/incoherent_impl-primitive.rs | 25 +++++++++++++++++++ 3 files changed, 47 insertions(+), 1 deletion(-) create mode 100644 tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs create mode 100644 tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index da88172c688f5..af7c6410a55b3 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -21,7 +21,7 @@ use rustc_hir::{ConstStability, StabilityLevel, StableSince}; use rustc_metadata::creader::CStore; use rustc_middle::ty::{self, Ty, TyCtxt, TypingMode}; use rustc_span::symbol::kw; -use rustc_span::{Ident, Symbol}; +use rustc_span::{Ident, Symbol, sym}; use tracing::{debug, trace}; use super::url_parts_builder::UrlPartsBuilder; @@ -537,11 +537,25 @@ fn generate_item_def_id_path( && !def_id.is_local() && def_id.krate != original_def_id.krate; } else { + // This hack is because primitive types are only documented in `core` and `std`. + // However, with `#[rustc_allow_incoherent_impl]`, a lot of primitive methods are + // implemented in `core`. Some of them are documented in `core` (like `[]::sort`) while + // others aren't (like `[]::to_vec`). So in case we're not documenting `core`, we link + // to `std`. + if !of_trait && crate_name != sym::core { + if ![sym::alloc, sym::std].contains(&crate_name) { + // We cannot link to this primitive's associated item as it's not part of + // `core`, `alloc` or `std` so returning early. + return Err(HrefError::UnnamableItem); + } + maybe_have_impl_not_in_def_crate = true; + } prim = PrimitiveType::from_ty(ty); } } let (shortty, fqp) = if let Some(prim) = prim { + let crate_name = if maybe_have_impl_not_in_def_crate { sym::std } else { crate_name }; (ItemType::Primitive, vec![crate_name, prim.as_sym()]) } else { ( diff --git a/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs new file mode 100644 index 0000000000000..98e9a5129417c --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/auxiliary/incoherent_impl_primitive.rs @@ -0,0 +1,7 @@ +#![feature(rustc_attrs)] +#![allow(internal_features)] + +impl [T] { + #[rustc_allow_incoherent_impl] + pub fn f(&self) {} +} diff --git a/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs b/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs new file mode 100644 index 0000000000000..9a4609953a178 --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/incoherent_impl-primitive.rs @@ -0,0 +1,25 @@ +// This test checks that outside of `core`/`alloc`/`std`, we don't link to incoherent method impl +// because there is no page to link to since primitive are only documented in `core` and `std`. + +//@ aux-build: incoherent_impl_primitive.rs +//@ build-aux-docs +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +#![crate_name = "foo"] + +extern crate incoherent_impl_primitive; + +//@ has 'src/foo/incoherent_impl-primitive.rs.html' + +// It should contain only the link to "first". Sadly, because of the limit, we cannot test +// if a link doesn't have an attribute so for now, we simply ensure that the number of `` +// (including both line numbers and jump to def links) is superior by one to the number of +// line ``. If so, we know there is only one jump to def link. +//@ count - '//pre/code/a' 7 +//@ count - '//pre/code/a[@id]' 6 +//@ has - '//pre/code/a[@href="{{channel}}/core/primitive.slice.html#method.first"]' 'first' + +fn foo() { + let x = ["a"].f(); + ["a"].first(); +} From f532587cb4a3e2f52ab0107a509f9cafe7a11aa9 Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Thu, 1 Oct 2026 18:23:22 +0700 Subject: [PATCH 1147/1309] Add union pattern reference change to relnotes --- RELEASES.md | 1 + 1 file changed, 1 insertion(+) diff --git a/RELEASES.md b/RELEASES.md index 77b58ce2bcf25..cd1f3ca7c3800 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -116,6 +116,7 @@ Compatibility Notes - [`semicolon_in_expressions_from_macros`: Lint on non-local macros too](https://github.com/rust-lang/rust/pull/159222) - [Split non-local `semicolon_in_expressions_from_macros` into a separate lint](https://github.com/rust-lang/rust/pull/159700) - In Cargo, incremental compilation is now disabled by default when running in CI. CI is detected via the `CI` environment variable. [#17220](https://github.com/rust-lang/cargo/pull/17220) +- [The Rust Reference no longer recommends using a single pattern to match a union alongside another value, such as in a manually-written tagged union](https://github.com/rust-lang/reference/pull/2303). This was because it was found that such code would, in some circumstances, result in the compiler reading the contents of the union before checking if the rest of the scrutinee matches the rest of the pattern. This can cause undefined behavior in code similar to what the reference previously recommended. From a44e8af588de848630400033c065516ca2125b99 Mon Sep 17 00:00:00 2001 From: Sinan Nalkaya Date: Thu, 1 Oct 2026 13:45:11 +0200 Subject: [PATCH 1148/1309] Move media & home dirs tests to fs tests. --- library/std/src/fs/dirs.rs | 67 ------------------------------------- library/std/src/fs/tests.rs | 63 ++++++++++++++++++++++++++++++++++ 2 files changed, 63 insertions(+), 67 deletions(-) diff --git a/library/std/src/fs/dirs.rs b/library/std/src/fs/dirs.rs index f8b855c994ff2..a9e11e37b2639 100644 --- a/library/std/src/fs/dirs.rs +++ b/library/std/src/fs/dirs.rs @@ -519,70 +519,3 @@ impl MediaDirs { self } } - -#[cfg(test)] -mod tests { - use super::*; - - fn test_dir(what: &str) -> PathBuf { - crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what) - } - - #[test] - fn test_home_dirs_field_hookup_matches() { - let mut dirs = HomeDirs::empty(); - - assert_eq!(dirs.config_home(), None); - assert_eq!(dirs.data_home(), None); - assert_eq!(dirs.state_home(), None); - assert_eq!(dirs.cache_home(), None); - - let config = test_dir("config"); - let data = test_dir("data"); - let state = test_dir("state"); - let cache = test_dir("cache"); - - dirs.set_config_home(config.clone()); - dirs.set_data_home(data.clone()); - dirs.set_state_home(state.clone()); - dirs.set_cache_home(cache.clone()); - - assert_eq!(dirs.config_home(), Some(config.as_ref())); - assert_eq!(dirs.data_home(), Some(data.as_ref())); - assert_eq!(dirs.state_home(), Some(state.as_ref())); - assert_eq!(dirs.cache_home(), Some(cache.as_ref())); - } - - #[test] - fn test_media_dirs_field_hookup_matches() { - let mut dirs = MediaDirs::empty(); - - assert_eq!(dirs.desktop(), None); - assert_eq!(dirs.documents(), None); - assert_eq!(dirs.downloads(), None); - assert_eq!(dirs.music(), None); - assert_eq!(dirs.pictures(), None); - assert_eq!(dirs.videos(), None); - - let desktop = test_dir("desktop"); - let documents = test_dir("documents"); - let downloads = test_dir("downloads"); - let music = test_dir("music"); - let pictures = test_dir("pictures"); - let videos = test_dir("videos"); - - dirs.set_desktop(desktop.clone()); - dirs.set_documents(documents.clone()); - dirs.set_downloads(downloads.clone()); - dirs.set_music(music.clone()); - dirs.set_pictures(pictures.clone()); - dirs.set_videos(videos.clone()); - - assert_eq!(dirs.desktop(), Some(desktop.as_ref())); - assert_eq!(dirs.documents(), Some(documents.as_ref())); - assert_eq!(dirs.downloads(), Some(downloads.as_ref())); - assert_eq!(dirs.music(), Some(music.as_ref())); - assert_eq!(dirs.pictures(), Some(pictures.as_ref())); - assert_eq!(dirs.videos(), Some(videos.as_ref())); - } -} diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 29c1aad06e98c..7f16e41dcf5d7 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1,6 +1,7 @@ use rand::RngCore; use super::Dir; +use super::dirs::{HomeDirs, MediaDirs}; use crate::fs::{self, File, FileTimes, OpenOptions, TryLockError, exists}; use crate::io::prelude::*; use crate::io::{BorrowedBuf, ErrorKind, SeekFrom}; @@ -3166,3 +3167,65 @@ fn test_dir_metadata() { assert!(!metadata.is_file()); assert!(metadata.is_symlink()); } + +fn root_test_dir(what: &str) -> PathBuf { + crate::env::current_dir().unwrap().ancestors().last().unwrap().join(what) +} + +#[test] +fn test_home_dirs_field_hookup_matches() { + let mut dirs = HomeDirs::empty(); + + assert_eq!(dirs.config_home(), None); + assert_eq!(dirs.data_home(), None); + assert_eq!(dirs.state_home(), None); + assert_eq!(dirs.cache_home(), None); + + let config = root_test_dir("config"); + let data = root_test_dir("data"); + let state = root_test_dir("state"); + let cache = root_test_dir("cache"); + + dirs.set_config_home(config.clone()); + dirs.set_data_home(data.clone()); + dirs.set_state_home(state.clone()); + dirs.set_cache_home(cache.clone()); + + assert_eq!(dirs.config_home(), Some(config.as_ref())); + assert_eq!(dirs.data_home(), Some(data.as_ref())); + assert_eq!(dirs.state_home(), Some(state.as_ref())); + assert_eq!(dirs.cache_home(), Some(cache.as_ref())); +} + +#[test] +fn test_media_dirs_field_hookup_matches() { + let mut dirs = MediaDirs::empty(); + + assert_eq!(dirs.desktop(), None); + assert_eq!(dirs.documents(), None); + assert_eq!(dirs.downloads(), None); + assert_eq!(dirs.music(), None); + assert_eq!(dirs.pictures(), None); + assert_eq!(dirs.videos(), None); + + let desktop = root_test_dir("desktop"); + let documents = root_test_dir("documents"); + let downloads = root_test_dir("downloads"); + let music = root_test_dir("music"); + let pictures = root_test_dir("pictures"); + let videos = root_test_dir("videos"); + + dirs.set_desktop(desktop.clone()); + dirs.set_documents(documents.clone()); + dirs.set_downloads(downloads.clone()); + dirs.set_music(music.clone()); + dirs.set_pictures(pictures.clone()); + dirs.set_videos(videos.clone()); + + assert_eq!(dirs.desktop(), Some(desktop.as_ref())); + assert_eq!(dirs.documents(), Some(documents.as_ref())); + assert_eq!(dirs.downloads(), Some(downloads.as_ref())); + assert_eq!(dirs.music(), Some(music.as_ref())); + assert_eq!(dirs.pictures(), Some(pictures.as_ref())); + assert_eq!(dirs.videos(), Some(videos.as_ref())); +} From 434157508f02ec9092907d63e220e971d6dc34ad Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 28 Sep 2026 15:42:03 +1000 Subject: [PATCH 1149/1309] Improve diagnostic deduplication By making it ignore the parent field of spans within the diagnostic. This is done with a new `DedupHashEncoder` type that uses the existing `Encoder`/`SpanEncoder` traits to traverse the fields within `DiagInner` and `Subdiag`. Fixes #162901. --- compiler/rustc_errors/src/dedup_hash.rs | 63 +++++++++++++++++++ compiler/rustc_errors/src/diagnostic.rs | 41 ++++++------ compiler/rustc_errors/src/lib.rs | 1 + ...plicate-diagnostics-incr.incr-dedup.stderr | 38 +---------- ...duplicate-diagnostics-incr.incr-dup.stderr | 3 + .../deduplicate-diagnostics-incr.rs | 6 +- typos.toml | 1 + 7 files changed, 92 insertions(+), 61 deletions(-) create mode 100644 compiler/rustc_errors/src/dedup_hash.rs diff --git a/compiler/rustc_errors/src/dedup_hash.rs b/compiler/rustc_errors/src/dedup_hash.rs new file mode 100644 index 0000000000000..b8b2da69bc1d3 --- /dev/null +++ b/compiler/rustc_errors/src/dedup_hash.rs @@ -0,0 +1,63 @@ +use std::hash::Hash; + +use rustc_data_structures::stable_hash::StableHasher; +use rustc_serialize::Encoder; +use rustc_span::def_id::{CrateNum, DefId, DefIndex}; +use rustc_span::{ByteSymbol, ExpnId, Span, SpanEncoder, Symbol, SyntaxContext}; + +/// Hasher used to determine if two diagnostics are the same and should be deduplicated. Used by +/// `DiagCtxtInner::emitted_diagnostics`. It's a stable hash with one special behaviour: parents of +/// spans within the diagnostics are ignored so that incremental and non-incremental compilation +/// get the same behaviour. +/// +/// Although this has nothing to do with encoding data to/from file, it is implemented on top of +/// `Encoder`/`SpanEncoder` because they provide traversals of all the relevant types used within +/// diagnostics. There is no corresponding decoder. +pub(crate) struct DedupHashEncoder(pub(crate) StableHasher); + +macro_rules! encoder_methods { + ($($name:ident($ty:ty);)*) => { + $( + #[inline] + fn $name(&mut self, value: $ty) { + value.hash(&mut self.0) + } + )* + } +} + +impl Encoder for DedupHashEncoder { + encoder_methods! { + emit_usize(usize); + emit_u128(u128); + emit_u64(u64); + emit_u32(u32); + emit_u16(u16); + emit_u8(u8); + + emit_isize(isize); + emit_i128(i128); + emit_i64(i64); + emit_i32(i32); + emit_i16(i16); + + emit_raw_bytes(&[u8]); + } +} + +impl SpanEncoder for DedupHashEncoder { + fn encode_span(&mut self, span: Span) { + // The raison d'être of `DedupHashEncoder` is to ignore `parent` here. + span.with_parent(None).hash(&mut self.0); + } + + encoder_methods! { + encode_symbol(Symbol); + encode_byte_symbol(ByteSymbol); + encode_expn_id(ExpnId); + encode_syntax_context(SyntaxContext); + encode_crate_num(CrateNum); + encode_def_index(DefIndex); + encode_def_id(DefId); + } +} diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index e8780cb8f4286..65dc8042fd409 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -12,9 +12,11 @@ use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg}; use rustc_hashes::Hash128; use rustc_lint_defs::Applicability; use rustc_macros::{Decodable, Encodable}; +use rustc_serialize::Encodable; use rustc_span::{Span, Spanned, Symbol}; use tracing::debug; +use crate::dedup_hash::DedupHashEncoder; use crate::{ CodeSuggestion, DiagCtxtHandle, DiagMessage, ErrCode, ErrorGuaranteed, ExplicitBug, Level, MultiSpan, StashKey, Style, Sublevel, Substitution, SubstitutionPart, SuggestionStyle, @@ -298,20 +300,22 @@ impl DiagInner { emitted_at: _, // ignore } = self; - let hashed_parts = ( - std::mem::discriminant(level), // ignore the field within `Warning` - messages, - code, - span, - children, - suggestions, - args.as_slice(), - is_lint, - ); + let mut e = DedupHashEncoder(StableHasher::new()); + + // We use `discriminant` because we want to ignore the field within `Warning`. + // `Encoder`/`SpanEncoder` can't traverse a `Discriminant` so we hash it directly. + std::mem::discriminant(level).hash(&mut e.0); + + // All the other fields are hashed via `encode`. + messages.encode(&mut e); + code.encode(&mut e); + span.encode(&mut e); + children.encode(&mut e); + suggestions.encode(&mut e); + args.encode(&mut e); + is_lint.encode(&mut e); - let mut hasher = StableHasher::new(); - hashed_parts.hash(&mut hasher); - hasher.finish() + e.0.finish() } } @@ -328,14 +332,9 @@ impl Subdiag { /// Hash used to determine if two subdiagnostics are the same. Used by /// `DiagCtxtInner::emitted_diagnostics`. pub(crate) fn dedup_hash(&self) -> Hash128 { - // Deconstruct to ensure all fields are considered. - let Subdiag { level, messages, span } = self; - - let hashed_parts = (level, messages, span); - - let mut hasher = StableHasher::new(); - hashed_parts.hash(&mut hasher); - hasher.finish() + let mut e = DedupHashEncoder(StableHasher::new()); + self.encode(&mut e); + e.0.finish() } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 47473b568f58c..a1ccefefbcb2a 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -69,6 +69,7 @@ use crate::timings::TimingRecord; pub mod annotate_snippet_emitter_writer; pub mod codes; mod decorate_diag; +mod dedup_hash; mod diagnostic; mod diagnostic_impls; pub mod emitter; diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr index 8cfd815b10d5f..e8fb5732febdc 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dedup.stderr @@ -10,42 +10,6 @@ help: the trait `GlobalAllocator` is implemented for `System` --> $SRC_DIR/std/src/alloc.rs:LL:COL = note: required for `usize` to implement `GlobalAlloc` -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/deduplicate-diagnostics-incr.rs:11:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` - | -help: the trait `GlobalAllocator` is implemented for `System` - --> $SRC_DIR/std/src/alloc.rs:LL:COL - = note: required for `usize` to implement `GlobalAlloc` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/deduplicate-diagnostics-incr.rs:11:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` - | -help: the trait `GlobalAllocator` is implemented for `System` - --> $SRC_DIR/std/src/alloc.rs:LL:COL - = note: required for `usize` to implement `GlobalAlloc` - -error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied - --> $DIR/deduplicate-diagnostics-incr.rs:11:11 - | -LL | #[global_allocator] - | ------------------- in this attribute macro expansion -LL | static A: usize = 0; - | ^^^^^ the nightly-only, unstable trait `GlobalAllocator` is not implemented for `usize` - | -help: the trait `GlobalAllocator` is implemented for `System` - --> $SRC_DIR/std/src/alloc.rs:LL:COL - = note: required for `usize` to implement `GlobalAlloc` - -error: aborting due to 4 previous errors +error: aborting due to 1 previous error For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr index 8cfd815b10d5f..017884aff53a4 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.incr-dup.stderr @@ -21,6 +21,7 @@ LL | static A: usize = 0; help: the trait `GlobalAllocator` is implemented for `System` --> $SRC_DIR/std/src/alloc.rs:LL:COL = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/deduplicate-diagnostics-incr.rs:11:11 @@ -33,6 +34,7 @@ LL | static A: usize = 0; help: the trait `GlobalAllocator` is implemented for `System` --> $SRC_DIR/std/src/alloc.rs:LL:COL = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied --> $DIR/deduplicate-diagnostics-incr.rs:11:11 @@ -45,6 +47,7 @@ LL | static A: usize = 0; help: the trait `GlobalAllocator` is implemented for `System` --> $SRC_DIR/std/src/alloc.rs:LL:COL = note: required for `usize` to implement `GlobalAlloc` + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 4 previous errors diff --git a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs index daa42492686db..72bed90bba4c7 100644 --- a/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs +++ b/tests/ui/diagnostic-flags/deduplicate-diagnostics-incr.rs @@ -10,8 +10,8 @@ #[global_allocator] static A: usize = 0; //[dedup,dup,incr-dedup,incr-dup]~^ ERROR E0277 -//[dup,incr-dedup,incr-dup]~| ERROR E0277 -//[dup,incr-dedup,incr-dup]~| ERROR E0277 -//[dup,incr-dedup,incr-dup]~| ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 +//[dup,incr-dup]~| ERROR E0277 fn main() {} diff --git a/typos.toml b/typos.toml index 8976759b3b259..215a971527e85 100644 --- a/typos.toml +++ b/typos.toml @@ -35,6 +35,7 @@ numer = "numer" # short for numerator, not a typo for "number" old-skool = "old-skool" # variant spelling of "old-school" optin = "optin" # short for opt-in publically = "publically" +raison = "raison" # part of the French phrase "raison d'être" rplace = "rplace" # short for R-place splitted = "splitted" sythetic = "sythetic" # typo in vendored LLVM sources From d4c82e70113dd1c14ae56930e744fd838a8217d9 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Oct 2026 12:26:55 +0200 Subject: [PATCH 1150/1309] freebsd: add FIXME for st_mode on a pipe --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 1745a75830a3f..5e3f1ffc0c491 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -866,7 +866,13 @@ fn test_fstat() { let stat = stat.assume_init_ref(); assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFIFO); - assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + if cfg!(target_os = "freebsd") { + // FIXME: Seems like FreeBSD does not set permissions for non-file-backed FDs. + // Miri currently gets this wrong. + // assert_eq!(stat.st_mode & !libc::S_IFMT, 0, "no permission should be set"); + } else { + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + } assert_eq!(stat.st_size, 0); errno_check(libc::close(fds[0])); From 9cab556c5b6c2a59f4b54d8cefacfa36e0350a1c Mon Sep 17 00:00:00 2001 From: WhySoBad <49595640+WhySoBad@users.noreply.github.com> Date: Thu, 1 Oct 2026 12:01:40 +0200 Subject: [PATCH 1151/1309] Handle ENETUNREACH in socket tests which connect to blackhole addresses --- .../libc/libc-socket-no-blocking-epoll.rs | 2 +- .../pass-dep/libc/libc-socket-no-blocking.rs | 30 ++++++++++++++++--- src/tools/miri/tests/pass/shims/socket.rs | 5 ++++ 3 files changed, 32 insertions(+), 5 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs index 563c2a3842a19..628f7f9493567 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking-epoll.rs @@ -148,7 +148,7 @@ fn test_connect_nonblock_err() { let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); // Since the address is not bound, the `connect` can never succeed // immediately and thus it always "fails" with EINPROGRESS. - assert!(err.kind() == ErrorKind::InProgress); + assert_eq!(err.kind(), ErrorKind::InProgress); // Add interest for client socket. epoll_ctl_add(epfd, client_sockfd, EPOLLOUT | EPOLLET | libc::EPOLLERR).unwrap(); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs index 0325fe06dab82..bea3b984beb3a 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-no-blocking.rs @@ -678,9 +678,14 @@ fn test_getsockname_ipv4_connect_nonblock() { let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + if err.kind() == ErrorKind::NetworkUnreachable { + // Since blackhole addresses are not part of the local address range + // they might not be reachable without internet connectivity. + return; + } // Since we're connecting to a blackhole address, the `connect` can // never succeed immediately and thus it always "fails" with EINPROGRESS. - assert!(err.kind() == ErrorKind::InProgress); + assert_eq!(err.kind(), ErrorKind::InProgress); let (_, sock_addr) = net::sockname_ipv4(|storage, len| unsafe { libc::getsockname(client_sockfd, storage, len) @@ -782,9 +787,14 @@ fn test_getpeername_ipv4_nonblock_no_peer() { let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + if err.kind() == ErrorKind::NetworkUnreachable { + // Since blackhole addresses are not part of the local address range + // they might not be reachable without internet connectivity. + return; + } // Since we're connecting to a blackhole address, the `connect` can // never succeed immediately and thus it always "fails" with EINPROGRESS. - assert!(err.kind() == ErrorKind::InProgress); + assert_eq!(err.kind(), ErrorKind::InProgress); // There should be no error during async connection. let so_error = @@ -823,8 +833,14 @@ fn test_listen_connecting() { // a zero port. let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); - // Non-blocking connect should fail with EINPROGRESS. let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + if err.kind() == ErrorKind::NetworkUnreachable { + // Since blackhole addresses are not part of the local address range + // they might not be reachable without internet connectivity. + return; + } + // Since we're connecting to a blackhole address, the `connect` can + // never succeed immediately and thus it always "fails" with EINPROGRESS. assert_eq!(err.kind(), ErrorKind::InProgress); // There should be no error during async connection. @@ -861,8 +877,14 @@ fn test_connect_connecting() { // a zero port. let addr = net::sock_addr_ipv4([192, 0, 2, 1], 12321); - // Non-blocking connect should fail with EINPROGRESS. let err = net::connect_ipv4(client_sockfd, addr).unwrap_err(); + if err.kind() == ErrorKind::NetworkUnreachable { + // Since blackhole addresses are not part of the local address range + // they might not be reachable without internet connectivity. + return; + } + // Since we're connecting to a blackhole address, the `connect` can + // never succeed immediately and thus it always "fails" with EINPROGRESS. assert_eq!(err.kind(), ErrorKind::InProgress); // There should be no error during async connection. diff --git a/src/tools/miri/tests/pass/shims/socket.rs b/src/tools/miri/tests/pass/shims/socket.rs index 1891e770a017f..91e75d32891b9 100644 --- a/src/tools/miri/tests/pass/shims/socket.rs +++ b/src/tools/miri/tests/pass/shims/socket.rs @@ -73,6 +73,11 @@ fn test_connect_with_timeout_error() { let before = Instant::now(); let err = TcpStream::connect_timeout(&address, timeout).unwrap_err(); + if err.kind() == ErrorKind::NetworkUnreachable { + // Since blackhole addresses are not part of the local address range + // they might not be reachable without internet connectivity. + return; + } assert_eq!(err.kind(), ErrorKind::TimedOut); assert!(before.elapsed() >= timeout); } From 7ede2187bab13dcc8a8ed17161d95a54aef3619e Mon Sep 17 00:00:00 2001 From: Joao Roberto Date: Thu, 1 Oct 2026 13:12:17 +0000 Subject: [PATCH 1152/1309] wfcheck: name the item that discards an unused type parameter * Name the item that discards an unused type parameter E0392 pointed at the mention of the parameter with a label saying it "is likely unused in the containing type", which doesn't say much. It's unclear what the containing type is meant to be, and we hedge with "likely" even though we can just go look. Track the outermost item that throws the argument away while collecting the usage spans, and name it instead. For ADTs that's a bivariant parameter in `variances_of`. Type aliases have no variances of their own, so expand them and check whether the parameter reaches a position that constrains it -- an alias can mention the parameter and still discard it by handing it to something else that ignores it. Free aliases go through `expand_free_alias_tys` rather than `type_of`, since a diverging one would otherwise recurse forever. When none of that pins down a culprit, fall back to saying the mention doesn't constrain the parameter instead of guessing. * Cover free alias types in the unused type parameter error A chain of free aliases used to hide the item doing the discarding, and the same alias applied to different arguments has to be expanded twice or a use of the parameter goes missing. The overflow case is worth a test of its own: with a growing argument there's no repeated alias to spot the divergence with, so the recursion limit is the only thing that stops the walk. * Simplify the unused type parameter diagnostic Variance and associated-type constraints are checked before this diagnostic runs. Restore the span collector and use a definite label without identifying which wrapper discards the parameter. Update the diagnostic expectations and test comments accordingly. --- .../rustc_hir_analysis/src/diagnostics.rs | 2 +- tests/ui/checked-type-alias/variance-1.stderr | 2 +- .../checked-type-alias/variance-overflow.rs | 11 +++ .../variance-overflow.stderr | 29 +++++++- ...riance-unused-param-through-alias-chain.rs | 25 +++++++ ...ce-unused-param-through-alias-chain.stderr | 34 +++++++++ .../ui/variance/variance-unused-type-param.rs | 25 +++++++ .../variance-unused-type-param.stderr | 70 ++++++++++++++++++- 8 files changed, 192 insertions(+), 6 deletions(-) create mode 100644 tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs create mode 100644 tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index 890d25f14b264..1b3d238b390bc 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -1737,7 +1737,7 @@ pub(crate) struct UnusedGenericParameter { pub span: Span, pub param_name: Ident, pub param_def_kind: &'static str, - #[label("`{$param_name}` is named here, but is likely unused in the containing type")] + #[label("`{$param_name}` is named here, but is not used in the type that wraps it")] pub usage_spans: Vec, #[subdiagnostic] pub help: UnusedGenericParameterHelp, diff --git a/tests/ui/checked-type-alias/variance-1.stderr b/tests/ui/checked-type-alias/variance-1.stderr index 5eb2f5d0673aa..40b59b43910e8 100644 --- a/tests/ui/checked-type-alias/variance-1.stderr +++ b/tests/ui/checked-type-alias/variance-1.stderr @@ -10,7 +10,7 @@ error[E0392]: type parameter `T` is never used --> $DIR/variance-1.rs:17:24 | LL | struct WrapDiscard<'a, T>(Discard<'a, T>); - | ^ - `T` is named here, but is likely unused in the containing type + | ^ - `T` is named here, but is not used in the type that wraps it | | | unused type parameter | diff --git a/tests/ui/checked-type-alias/variance-overflow.rs b/tests/ui/checked-type-alias/variance-overflow.rs index 0b5b58e083133..3da7da1ed425d 100644 --- a/tests/ui/checked-type-alias/variance-overflow.rs +++ b/tests/ui/checked-type-alias/variance-overflow.rs @@ -19,4 +19,15 @@ struct First(Second); type Second = Second; // diverging free alias type //~^ ERROR overflow normalizing the type alias `Second` +// The same applies when a diverging alias mentions a type parameter. The argument grows with +// every step, so there is no repeated `(DefId, args)` pair to detect the divergence with. +// Variance inference must stop at the recursion limit, and reporting the unused parameter +// must not restart the expansion. +type Diverging = Diverging<(T,)>; +//~^ ERROR overflow normalizing the type alias `Diverging< + +struct Wrap(Diverging); +//~^ ERROR type parameter `T` is never used +//~| ERROR overflow normalizing the type alias `Diverging< + fn main() {} diff --git a/tests/ui/checked-type-alias/variance-overflow.stderr b/tests/ui/checked-type-alias/variance-overflow.stderr index 35486ccdc169f..3ea61d9ade9f3 100644 --- a/tests/ui/checked-type-alias/variance-overflow.stderr +++ b/tests/ui/checked-type-alias/variance-overflow.stderr @@ -23,7 +23,34 @@ LL | type Second = Second; // diverging free alias type | = note: in case this is a recursive type alias, consider using a struct, enum, or union instead -error: aborting due to 3 previous errors +error[E0275]: overflow normalizing the type alias `Diverging<(((((((_,),),),),),),)>` + --> $DIR/variance-overflow.rs:26:1 + | +LL | type Diverging = Diverging<(T,)>; + | ^^^^^^^^^^^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-overflow.rs:29:13 + | +LL | struct Wrap(Diverging); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0275]: overflow normalizing the type alias `Diverging<(((((((_,),),),),),),)>` + --> $DIR/variance-overflow.rs:29:16 + | +LL | struct Wrap(Diverging); + | ^^^^^^^^^^^^ + | + = note: in case this is a recursive type alias, consider using a struct, enum, or union instead + +error: aborting due to 6 previous errors Some errors have detailed explanations: E0275, E0392. For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs new file mode 100644 index 0000000000000..22542e4142fb5 --- /dev/null +++ b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.rs @@ -0,0 +1,25 @@ +// A mention forwarded through free aliases still does not count as a use when the final type +// ignores the parameter. The diagnostic should label the original mention even though the +// intermediate aliases mention the parameter too. + +#![feature(checked_type_aliases)] + +struct Ignores {} +//~^ ERROR type parameter `T` is never used + +type Forward = Discard; +type Discard = Ignores; + +struct Wrap(Forward); +//~^ ERROR type parameter `T` is never used + +// An alias can occur with different arguments in the same type. Here `Repeat` preserves its +// parameter through `Id`, so the enclosing struct uses `T` only recursively. The unrelated +// `Id` must not hide that recursive use. +type Id = T; +type Repeat = (Id, Id); + +struct Recursive(Repeat>>); +//~^ ERROR type parameter `T` is only used recursively + +fn main() {} diff --git a/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr new file mode 100644 index 0000000000000..069916d57b514 --- /dev/null +++ b/tests/ui/checked-type-alias/variance-unused-param-through-alias-chain.stderr @@ -0,0 +1,34 @@ +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-param-through-alias-chain.rs:7:16 + | +LL | struct Ignores {} + | ^ unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-param-through-alias-chain.rs:13:13 + | +LL | struct Wrap(Forward); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: type parameter `T` is only used recursively + --> $DIR/variance-unused-param-through-alias-chain.rs:22:42 + | +LL | struct Recursive(Repeat>>); + | - ^ + | | + | type parameter must be used non-recursively in the definition + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = note: all type parameters must be used in a non-recursive way in order to constrain their variance + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0392`. diff --git a/tests/ui/variance/variance-unused-type-param.rs b/tests/ui/variance/variance-unused-type-param.rs index ef3c41ca5560c..bad994b5e280d 100644 --- a/tests/ui/variance/variance-unused-type-param.rs +++ b/tests/ui/variance/variance-unused-type-param.rs @@ -33,4 +33,29 @@ struct DoubleNothing { s: SomeStruct, } +// A mention nested inside another type argument still does not count as a use. +struct NestedNothing { +//~^ ERROR parameter `T` is never used + s: SomeStruct>, +} + +type Discard = (); +//~^ ERROR parameter `T` is never used + +struct ThroughTypeAlias(Discard); +//~^ ERROR parameter `T` is never used + +// Only the unused parameter should receive the diagnostic. +struct SecondUnused { a: A } +//~^ ERROR parameter `B` is never used + +struct UsesSecondUnused(SecondUnused); +//~^ ERROR parameter `T` is never used + +// The alias mentions `T`, but only to forward it to something that throws it away. +type Forward = SomeStruct; + +struct ThroughForwardingAlias(Forward); +//~^ ERROR parameter `T` is never used + fn main() {} diff --git a/tests/ui/variance/variance-unused-type-param.stderr b/tests/ui/variance/variance-unused-type-param.stderr index c747532e62836..d02addc5a5e53 100644 --- a/tests/ui/variance/variance-unused-type-param.stderr +++ b/tests/ui/variance/variance-unused-type-param.stderr @@ -69,11 +69,75 @@ LL | struct DoubleNothing { | ^ unused type parameter LL | LL | s: SomeStruct, - | - `T` is named here, but is likely unused in the containing type + | - `T` is named here, but is not used in the type that wraps it | = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead -error: aborting due to 8 previous errors +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:37:22 + | +LL | struct NestedNothing { + | ^ unused type parameter +LL | +LL | s: SomeStruct>, + | - `T` is named here, but is not used in the type that wraps it + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0091]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:42:14 + | +LL | type Discard = (); + | ^ unused type parameter + | + = help: consider removing `T` or referring to it in the body of the type alias + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:45:25 + | +LL | struct ThroughTypeAlias(Discard); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `B` is never used + --> $DIR/variance-unused-type-param.rs:49:24 + | +LL | struct SecondUnused { a: A } + | ^ unused type parameter + | + = help: consider removing `B`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `B` to be a const parameter, use `const B: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:52:25 + | +LL | struct UsesSecondUnused(SecondUnused); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error[E0392]: type parameter `T` is never used + --> $DIR/variance-unused-type-param.rs:58:31 + | +LL | struct ThroughForwardingAlias(Forward); + | ^ - `T` is named here, but is not used in the type that wraps it + | | + | unused type parameter + | + = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData` + = help: if you intended `T` to be a const parameter, use `const T: /* Type */` instead + +error: aborting due to 14 previous errors -For more information about this error, try `rustc --explain E0392`. +Some errors have detailed explanations: E0091, E0392. +For more information about an error, try `rustc --explain E0091`. From 3c02ed033b895541f14849d87df3c0bf8e2b387c Mon Sep 17 00:00:00 2001 From: Philipp Krones Date: Thu, 1 Oct 2026 11:42:46 +0200 Subject: [PATCH 1153/1309] Allow unresolvable names in cg_gcc/clippy.toml The `disallowed-method` lint gave: `gccjit::types::Type::add_attribute` does not refer to a reachable function because this function is behind a `cfg` gate and is not always available. --- compiler/rustc_codegen_gcc/clippy.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_gcc/clippy.toml b/compiler/rustc_codegen_gcc/clippy.toml index cf1593c691734..4ba3642756d4c 100644 --- a/compiler/rustc_codegen_gcc/clippy.toml +++ b/compiler/rustc_codegen_gcc/clippy.toml @@ -1,3 +1,3 @@ disallowed-methods = [ - { path = "gccjit::types::Type::add_attribute", reason = "go through `type_::apply_struct_attributes` instead: an attribute set directly on a type would not be part of the `CodegenCx::struct_types` cache key, so it would silently change every other use of that type" }, + { path = "gccjit::types::Type::add_attribute", reason = "go through `type_::apply_struct_attributes` instead: an attribute set directly on a type would not be part of the `CodegenCx::struct_types` cache key, so it would silently change every other use of that type", allow-invalid = true }, ] From d5a81cb799a32eacead6dd8536a2332c9e0dbae1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 1 Oct 2026 16:28:26 +0200 Subject: [PATCH 1154/1309] ignore hanging next-solver tests, remove unnecessary ignore test --- tests/ui/closures/supertrait-hint-cycle.rs | 4 ++++ .../object-soundness-requires-generalization.rs | 6 ++++-- ...2904.stderr => error-tainting-issue-122904.old.stderr} | 4 ++-- .../type-alias-impl-trait/error-tainting-issue-122904.rs | 6 ++++++ ...n-2.stderr => recursive-drop-elaboration-2.old.stderr} | 4 ++-- .../type-alias-impl-trait/recursive-drop-elaboration-2.rs | 5 +++++ ...ation.stderr => recursive-drop-elaboration.old.stderr} | 8 ++++---- .../type-alias-impl-trait/recursive-drop-elaboration.rs | 5 +++++ 8 files changed, 32 insertions(+), 10 deletions(-) rename tests/ui/type-alias-impl-trait/{error-tainting-issue-122904.stderr => error-tainting-issue-122904.old.stderr} (90%) rename tests/ui/type-alias-impl-trait/{recursive-drop-elaboration-2.stderr => recursive-drop-elaboration-2.old.stderr} (90%) rename tests/ui/type-alias-impl-trait/{recursive-drop-elaboration.stderr => recursive-drop-elaboration.old.stderr} (89%) diff --git a/tests/ui/closures/supertrait-hint-cycle.rs b/tests/ui/closures/supertrait-hint-cycle.rs index 52c24a414aca6..08dcde28217bd 100644 --- a/tests/ui/closures/supertrait-hint-cycle.rs +++ b/tests/ui/closures/supertrait-hint-cycle.rs @@ -1,4 +1,8 @@ //@ edition:2021 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] ignore-test: trait-system-refactor-initiative#242 //@ check-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs index 3ef6bea4fd5c9..da93a10d42df4 100644 --- a/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs +++ b/tests/ui/traits/next-solver/object-soundness-requires-generalization.rs @@ -1,5 +1,7 @@ -//@ compile-flags: -Znext-solver -//@ ignore-test (see #114196) +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass trait Trait { type Gat<'lt>; diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.old.stderr similarity index 90% rename from tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr rename to tests/ui/type-alias-impl-trait/error-tainting-issue-122904.old.stderr index c5e347e59de72..d90710081e4a2 100644 --- a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.stderr +++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.old.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/error-tainting-issue-122904.rs:12:1 + --> $DIR/error-tainting-issue-122904.rs:18:1 | LL | fn with_positive(fun: impl Fn(Alias<'_>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -11,7 +11,7 @@ LL | with_positive(|&n| ()); = note: `#[warn(unconditional_recursion)]` on by default error[E0507]: cannot move out of a shared reference - --> $DIR/error-tainting-issue-122904.rs:14:20 + --> $DIR/error-tainting-issue-122904.rs:20:20 | LL | with_positive(|&n| ()); | ^- diff --git a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs index a2de3957c0bd7..f17ce5fac3cb0 100644 --- a/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs +++ b/tests/ui/type-alias-impl-trait/error-tainting-issue-122904.rs @@ -1,6 +1,12 @@ // We previously didn't taint the borrowck result in this test, // causing an ICE later on. #![feature(type_alias_impl_trait)] + +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] ignore-test: trait-system-refactor-initiative#242 + trait T {} type Alias<'a> = impl T; diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.old.stderr similarity index 90% rename from tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr rename to tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.old.stderr index 94cd9a312ca12..ce26ccca3276b 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.old.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/recursive-drop-elaboration-2.rs:13:1 + --> $DIR/recursive-drop-elaboration-2.rs:18:1 | LL | fn with_positive(fun: impl Fn(Alias<'_>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -11,7 +11,7 @@ LL | with_positive(|&n| ()); = note: `#[warn(unconditional_recursion)]` on by default error[E0507]: cannot move out of a shared reference - --> $DIR/recursive-drop-elaboration-2.rs:15:20 + --> $DIR/recursive-drop-elaboration-2.rs:20:20 | LL | with_positive(|&n| ()); | ^- diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs index 5541c5267f39a..3a9d80a9f66e5 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration-2.rs @@ -1,5 +1,10 @@ //! Regression test for ICE #139556 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] ignore-test: trait-system-refactor-initiative#242 + #![feature(type_alias_impl_trait)] trait T {} diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.old.stderr similarity index 89% rename from tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr rename to tests/ui/type-alias-impl-trait/recursive-drop-elaboration.old.stderr index dc282f30b45b4..8bcd6d8dbdace 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.stderr +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.old.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/recursive-drop-elaboration.rs:13:1 + --> $DIR/recursive-drop-elaboration.rs:18:1 | LL | fn with_positive(fun: impl Fn(Alias<'_>)) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -11,7 +11,7 @@ LL | with_positive(|&n| ()); = note: `#[warn(unconditional_recursion)]` on by default error[E0507]: cannot move out of a shared reference - --> $DIR/recursive-drop-elaboration.rs:15:20 + --> $DIR/recursive-drop-elaboration.rs:20:20 | LL | with_positive(|&n| ()); | ^- @@ -25,7 +25,7 @@ LL + with_positive(|n| ()); | error[E0507]: cannot move out of a shared reference - --> $DIR/recursive-drop-elaboration.rs:22:20 + --> $DIR/recursive-drop-elaboration.rs:27:20 | LL | with_positive(|&a| ()); | ^- @@ -39,7 +39,7 @@ LL + with_positive(|a| ()); | error[E0580]: `main` function has wrong type - --> $DIR/recursive-drop-elaboration.rs:20:1 + --> $DIR/recursive-drop-elaboration.rs:25:1 | LL | type Alias<'a> = impl T; | ------ the found opaque type diff --git a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs index dd28732ebb281..5cabd6ab19031 100644 --- a/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs +++ b/tests/ui/type-alias-impl-trait/recursive-drop-elaboration.rs @@ -1,5 +1,10 @@ //! Regression test for #122904. +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] ignore-test: trait-system-refactor-initiative#242 + #![feature(type_alias_impl_trait)] trait T {} From a0a4029f95aaa6b5e6a7d3c1d6334ebf9cc7efa8 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 1 Oct 2026 16:47:36 +0200 Subject: [PATCH 1155/1309] add fast path to generalization --- .../rustc_infer/src/infer/relate/generalize.rs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_infer/src/infer/relate/generalize.rs b/compiler/rustc_infer/src/infer/relate/generalize.rs index 69ced9d3acb40..a81ec3d527a6e 100644 --- a/compiler/rustc_infer/src/infer/relate/generalize.rs +++ b/compiler/rustc_infer/src/infer/relate/generalize.rs @@ -3,7 +3,7 @@ use std::mem; use rustc_data_structures::sso::SsoHashMap; use rustc_hir::def_id::DefId; use rustc_middle::ty::error::TypeError; -use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeVisitableExt}; +use rustc_middle::ty::{self, InferConst, Term, Ty, TyCtxt, TypeFlags, TypeVisitableExt}; use rustc_span::{Span, bug}; use tracing::{debug, instrument, warn}; @@ -356,6 +356,15 @@ struct Generalizer<'me, 'tcx> { cache: SsoHashMap<(Ty<'tcx>, ty::Variance, bool), Ty<'tcx>>, } +/// Do we need to generalize this type? +const NEEDS_GENERALIZATION: TypeFlags = TypeFlags::from_bits( + TypeFlags::HAS_FREE_REGIONS.bits() + | TypeFlags::HAS_INFER.bits() + | TypeFlags::HAS_PLACEHOLDER.bits() + | TypeFlags::HAS_NON_RIGID_ALIAS.bits(), +) +.unwrap(); + impl<'tcx> Generalizer<'_, 'tcx> { /// Create an error that corresponds to the term kind in `root_term` fn cyclic_term_error(&self) -> TypeError<'tcx> { @@ -484,6 +493,10 @@ impl<'tcx> TypeRelation> for Generalizer<'_, 'tcx> { fn tys(&mut self, t: Ty<'tcx>, t2: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> { assert_eq!(t, t2); // we are misusing TypeRelation here; both LHS and RHS ought to be == + if !t.has_type_flags(NEEDS_GENERALIZATION) { + return Ok(t); + } + if let Some(&result) = self.cache.get(&(t, self.ambient_variance, self.in_alias)) { return Ok(result); } From 29df41c47187f735942d13900b784962ef1bc140 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 1 Oct 2026 17:51:47 +0200 Subject: [PATCH 1156/1309] fix `ValidateBoundVars` --- compiler/rustc_type_ir/src/binder.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 6722adfe24d5d..383e394c3a9e7 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -241,10 +241,10 @@ impl TypeVisitor for ValidateBoundVars { } fn visit_ty(&mut self, t: I::Ty) -> Self::Result { - if t.outer_exclusive_binder() < self.binder_index + if t.outer_exclusive_binder() <= self.binder_index || !self.visited.insert((self.binder_index, t)) { - return ControlFlow::Break(()); + return ControlFlow::Continue(()); } match t.kind() { ty::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ty) @@ -263,8 +263,8 @@ impl TypeVisitor for ValidateBoundVars { } fn visit_const(&mut self, c: Const) -> Self::Result { - if c.outer_exclusive_binder() < self.binder_index { - return ControlFlow::Break(()); + if c.outer_exclusive_binder() <= self.binder_index { + return ControlFlow::Continue(()); } match c.kind() { ty::ConstKind::Bound(debruijn, bound_const) From 545a884e44b98de95cbbbc62c8d15eddf36edf58 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Oct 2026 18:54:19 +0200 Subject: [PATCH 1157/1309] remove some unnecessary @only-on-host --- src/tools/miri/tests/native-lib/fail/function_not_in_so.rs | 1 - src/tools/miri/tests/native-lib/fail/invalid_retval.rs | 1 - src/tools/miri/tests/native-lib/fail/private_function.rs | 1 - src/tools/miri/tests/native-lib/fail/struct_not_extern_c.rs | 1 - 4 files changed, 4 deletions(-) diff --git a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs index a7df3e6118725..11a043156c07d 100644 --- a/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs +++ b/src/tools/miri/tests/native-lib/fail/function_not_in_so.rs @@ -1,6 +1,5 @@ // Only works on Unix targets //@ignore-target: windows wasm -//@only-on-host //@normalize-stderr-test: "OS `.*`" -> "$$OS" extern "C" { diff --git a/src/tools/miri/tests/native-lib/fail/invalid_retval.rs b/src/tools/miri/tests/native-lib/fail/invalid_retval.rs index e4bcbeb10926a..434309bfd7fbb 100644 --- a/src/tools/miri/tests/native-lib/fail/invalid_retval.rs +++ b/src/tools/miri/tests/native-lib/fail/invalid_retval.rs @@ -1,6 +1,5 @@ // Only works on Unix targets //@ignore-target: windows wasm -//@only-on-host //@normalize-stderr-test: "OS `.*`" -> "$$OS" extern "C" { diff --git a/src/tools/miri/tests/native-lib/fail/private_function.rs b/src/tools/miri/tests/native-lib/fail/private_function.rs index e54880e97dabc..40c579645a8c1 100644 --- a/src/tools/miri/tests/native-lib/fail/private_function.rs +++ b/src/tools/miri/tests/native-lib/fail/private_function.rs @@ -1,6 +1,5 @@ // Only works on Unix targets //@ignore-target: windows wasm -//@only-on-host //@normalize-stderr-test: "OS `.*`" -> "$$OS" extern "C" { diff --git a/src/tools/miri/tests/native-lib/fail/struct_not_extern_c.rs b/src/tools/miri/tests/native-lib/fail/struct_not_extern_c.rs index 27ae6c477a841..e6ba056a0af2e 100644 --- a/src/tools/miri/tests/native-lib/fail/struct_not_extern_c.rs +++ b/src/tools/miri/tests/native-lib/fail/struct_not_extern_c.rs @@ -1,6 +1,5 @@ // Only works on Unix targets //@ignore-target: windows wasm -//@only-on-host #![allow(improper_ctypes)] From a7709ec3b3181ea7d4acc612af50a132b42e8c0e Mon Sep 17 00:00:00 2001 From: Mads Marquart Date: Thu, 1 Oct 2026 18:23:50 +0200 Subject: [PATCH 1158/1309] Update LLVM submodule to latest release/23.x branch --- src/llvm-project | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/llvm-project b/src/llvm-project index 1b9c0d5ff9bbe..aab11ee0ea5ea 160000 --- a/src/llvm-project +++ b/src/llvm-project @@ -1 +1 @@ -Subproject commit 1b9c0d5ff9bbe7634aead059efe6b11a7eeba145 +Subproject commit aab11ee0ea5ea9a1d462ad0bc1fae9d9bb643019 From b923d1e13ade0197b11a670a296a38ddfebca469 Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 30 Sep 2026 22:03:17 -0500 Subject: [PATCH 1159/1309] ctfe: Constify the `abort` intrinsic This is a well-defined operation that we want to make use of in std/core, such as with `abort_immediate`. --- .../rustc_const_eval/src/const_eval/error.rs | 2 ++ .../src/const_eval/machine.rs | 6 +++- library/core/src/intrinsics/mod.rs | 2 +- src/tools/miri/src/intrinsics/mod.rs | 1 + tests/ui/consts/const-eval/const_panic.rs | 5 +++ tests/ui/consts/const-eval/const_panic.stderr | 32 +++++++++++-------- 6 files changed, 33 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs index 8532cad91b808..1cb6a8aed947d 100644 --- a/compiler/rustc_const_eval/src/const_eval/error.rs +++ b/compiler/rustc_const_eval/src/const_eval/error.rs @@ -30,6 +30,7 @@ pub enum ConstEvalErrKind { col: u32, file: Symbol, }, + Abort, WriteThroughImmutablePointer, /// Called `const_make_global` twice. ConstMakeGlobalPtrAlreadyMadeGlobal(AllocId), @@ -51,6 +52,7 @@ impl fmt::Display for ConstEvalErrKind { write!(f, "modifying a static's initial value from another static's initializer") } Panic { msg, .. } => write!(f, "evaluation panicked: {msg}"), + Abort => write!(f, "the program aborted execution"), RecursiveStatic => { write!(f, "encountered static that tried to access itself during initialization") } diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 843cd7cb4930d..3f7731ce95583 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -10,13 +10,13 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, IndexEntry}; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_hir::{CRATE_HIR_ID, HirId}; use rustc_lint_defs::builtin::LONG_RUNNING_CONST_EVAL; -use rustc_middle::mir; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::ReportedErrorInfo; use rustc_middle::query::TyCtxtAt; use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{self, FieldInfo, ScalarInt, Ty, TyCtxt}; +use rustc_middle::{mir, throw_machine_stop}; use rustc_span::{Span, Symbol, bug, span_bug, sym}; use rustc_target::callconv::FnAbi; use tracing::debug; @@ -484,6 +484,10 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // CTFE-specific intrinsics. match intrinsic_name { + sym::abort => { + // Note that `abort` is also hooked separately in Miri. + throw_machine_stop!(ConstEvalErrKind::Abort); + } sym::ptr_guaranteed_cmp => { let a = ecx.read_scalar(&args[0])?; let b = ecx.read_scalar(&args[1])?; diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 96999f154c42f..f44da9840b8e5 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -444,7 +444,7 @@ pub fn rustc_peek(_: T) -> T; /// The stabilization-track version of this intrinsic is [`core::process::abort_immediate`]. #[rustc_nounwind] #[rustc_intrinsic] -pub fn abort() -> !; +pub const fn abort() -> !; /// Informs the optimizer that this point in the code is not reachable, /// enabling further optimizations. diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 9a6bdb9b48dce..997339f66a51c 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -96,6 +96,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match intrinsic_name { // Basic control flow "abort" => { + // Note that `abort` is also hooked separately in CTFE. throw_machine_stop!(TerminationInfo::Abort( "the program aborted execution".to_owned() )); diff --git a/tests/ui/consts/const-eval/const_panic.rs b/tests/ui/consts/const-eval/const_panic.rs index e4f3a4eec1b1c..26eeec7778f7c 100644 --- a/tests/ui/consts/const-eval/const_panic.rs +++ b/tests/ui/consts/const-eval/const_panic.rs @@ -1,4 +1,5 @@ //@ edition:2015..2021 +#![feature(core_intrinsics)] #![allow(non_fmt_panics)] #![crate_type = "lib"] @@ -39,3 +40,7 @@ const W_CORE: () = core::panic!(MSG); const W2_CORE: () = core::panic!("{}", MSG); //~^ ERROR evaluation panicked + +// FIXME(abort_immediate): replace with the non-intrinsic version once available +const ABORT: () = core::intrinsics::abort(); +//~^ ERROR the program aborted execution diff --git a/tests/ui/consts/const-eval/const_panic.stderr b/tests/ui/consts/const-eval/const_panic.stderr index 8e0384b2f2af6..1288112f462fe 100644 --- a/tests/ui/consts/const-eval/const_panic.stderr +++ b/tests/ui/consts/const-eval/const_panic.stderr @@ -1,75 +1,81 @@ error[E0080]: evaluation panicked: cheese - --> $DIR/const_panic.rs:7:15 + --> $DIR/const_panic.rs:8:15 | LL | const Z: () = std::panic!("cheese"); | ^^^^^^^^^^^^^^^^^^^^^ evaluation of `Z` failed here error[E0080]: evaluation panicked: explicit panic - --> $DIR/const_panic.rs:10:16 + --> $DIR/const_panic.rs:11:16 | LL | const Z2: () = std::panic!(); | ^^^^^^^^^^^^^ evaluation of `Z2` failed here error[E0080]: evaluation panicked: internal error: entered unreachable code - --> $DIR/const_panic.rs:13:15 + --> $DIR/const_panic.rs:14:15 | LL | const Y: () = std::unreachable!(); | ^^^^^^^^^^^^^^^^^^^ evaluation of `Y` failed here error[E0080]: evaluation panicked: not implemented - --> $DIR/const_panic.rs:16:15 + --> $DIR/const_panic.rs:17:15 | LL | const X: () = std::unimplemented!(); | ^^^^^^^^^^^^^^^^^^^^^ evaluation of `X` failed here error[E0080]: evaluation panicked: hello - --> $DIR/const_panic.rs:19:15 + --> $DIR/const_panic.rs:20:15 | LL | const W: () = std::panic!(MSG); | ^^^^^^^^^^^^^^^^ evaluation of `W` failed here error[E0080]: evaluation panicked: hello - --> $DIR/const_panic.rs:22:16 + --> $DIR/const_panic.rs:23:16 | LL | const W2: () = std::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `W2` failed here error[E0080]: evaluation panicked: cheese - --> $DIR/const_panic.rs:25:20 + --> $DIR/const_panic.rs:26:20 | LL | const Z_CORE: () = core::panic!("cheese"); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `Z_CORE` failed here error[E0080]: evaluation panicked: explicit panic - --> $DIR/const_panic.rs:28:21 + --> $DIR/const_panic.rs:29:21 | LL | const Z2_CORE: () = core::panic!(); | ^^^^^^^^^^^^^^ evaluation of `Z2_CORE` failed here error[E0080]: evaluation panicked: internal error: entered unreachable code - --> $DIR/const_panic.rs:31:20 + --> $DIR/const_panic.rs:32:20 | LL | const Y_CORE: () = core::unreachable!(); | ^^^^^^^^^^^^^^^^^^^^ evaluation of `Y_CORE` failed here error[E0080]: evaluation panicked: not implemented - --> $DIR/const_panic.rs:34:20 + --> $DIR/const_panic.rs:35:20 | LL | const X_CORE: () = core::unimplemented!(); | ^^^^^^^^^^^^^^^^^^^^^^ evaluation of `X_CORE` failed here error[E0080]: evaluation panicked: hello - --> $DIR/const_panic.rs:37:20 + --> $DIR/const_panic.rs:38:20 | LL | const W_CORE: () = core::panic!(MSG); | ^^^^^^^^^^^^^^^^^ evaluation of `W_CORE` failed here error[E0080]: evaluation panicked: hello - --> $DIR/const_panic.rs:40:21 + --> $DIR/const_panic.rs:41:21 | LL | const W2_CORE: () = core::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `W2_CORE` failed here -error: aborting due to 12 previous errors +error[E0080]: the program aborted execution + --> $DIR/const_panic.rs:45:19 + | +LL | const ABORT: () = core::intrinsics::abort(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ABORT` failed here + +error: aborting due to 13 previous errors For more information about this error, try `rustc --explain E0080`. From 767210f85b306e7c3c3a920d143eeba3fba1419b Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 30 Sep 2026 22:03:17 -0500 Subject: [PATCH 1160/1309] core: Unstably constify `abort_immediate` For const-only code there isn't much of a reason to use this over `panic!()`, but having `abort_immediate` const will make it possible to reuse more code meant for runtime at comptime. The semantics are well-defined so this is pretty straightforward. --- library/core/src/process.rs | 3 ++- tests/ui/consts/const-eval/const_panic.rs | 5 ++--- tests/ui/consts/const-eval/const_panic.stderr | 9 ++++++--- 3 files changed, 10 insertions(+), 7 deletions(-) diff --git a/library/core/src/process.rs b/library/core/src/process.rs index 81481b2cba26e..2da752b42ee85 100644 --- a/library/core/src/process.rs +++ b/library/core/src/process.rs @@ -35,9 +35,10 @@ /// Other signals such as `SIGABRT`, `SIGTRAP`, `SIGSEGV`, and `SIGBUS` may be /// produced instead, depending on specifics. This is not an exhaustive list. #[unstable(feature = "abort_immediate", issue = "154601")] +#[rustc_const_unstable(feature = "abort_immediate", issue = "154601")] #[cold] #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[doc(alias = "halt")] -pub fn abort_immediate() -> ! { +pub const fn abort_immediate() -> ! { crate::intrinsics::abort() } diff --git a/tests/ui/consts/const-eval/const_panic.rs b/tests/ui/consts/const-eval/const_panic.rs index 26eeec7778f7c..e4fd30d2e1678 100644 --- a/tests/ui/consts/const-eval/const_panic.rs +++ b/tests/ui/consts/const-eval/const_panic.rs @@ -1,5 +1,5 @@ //@ edition:2015..2021 -#![feature(core_intrinsics)] +#![feature(abort_immediate)] #![allow(non_fmt_panics)] #![crate_type = "lib"] @@ -41,6 +41,5 @@ const W_CORE: () = core::panic!(MSG); const W2_CORE: () = core::panic!("{}", MSG); //~^ ERROR evaluation panicked -// FIXME(abort_immediate): replace with the non-intrinsic version once available -const ABORT: () = core::intrinsics::abort(); +const ABORT: () = core::process::abort_immediate(); //~^ ERROR the program aborted execution diff --git a/tests/ui/consts/const-eval/const_panic.stderr b/tests/ui/consts/const-eval/const_panic.stderr index 1288112f462fe..19d8f3ae1c106 100644 --- a/tests/ui/consts/const-eval/const_panic.stderr +++ b/tests/ui/consts/const-eval/const_panic.stderr @@ -71,10 +71,13 @@ LL | const W2_CORE: () = core::panic!("{}", MSG); | ^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `W2_CORE` failed here error[E0080]: the program aborted execution - --> $DIR/const_panic.rs:45:19 + --> $DIR/const_panic.rs:44:19 | -LL | const ABORT: () = core::intrinsics::abort(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ABORT` failed here +LL | const ABORT: () = core::process::abort_immediate(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ABORT` failed inside this call + | +note: inside `abort_immediate` + --> $SRC_DIR/core/src/process.rs:LL:COL error: aborting due to 13 previous errors From 4bf4c9478c083ec1ee3b0a375410cf545bf31eec Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Thu, 1 Oct 2026 19:14:29 +0200 Subject: [PATCH 1161/1309] make Linux current_exe work on non-Linux hosts --- src/tools/miri/src/shims/unix/fs.rs | 24 +++++++++++++------ .../miri/tests/pass/shims/env/current_exe.rs | 3 +-- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 1b9133785ed4a..0bf28103d102f 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -15,7 +15,7 @@ use rustc_target::spec::Os; use self::shims::time::system_time_to_duration; use crate::shims::FdId; use crate::shims::files::{DirHandle, FdNum, FileHandle}; -use crate::shims::os_str::bytes_to_os_str; +use crate::shims::os_str::{PathConversion, bytes_to_os_str}; use crate::shims::sig::Varargs; use crate::shims::unix::fd::{EvalContextExt as _, FlockOp, UnixFileDescription}; use crate::*; @@ -1711,7 +1711,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ) -> InterpResult<'tcx, i64> { let this = self.eval_context_mut(); - let pathname = this.read_path_from_c_str(this.read_pointer(pathname_op)?)?; + let pathname = this.read_os_str_from_c_str(this.read_pointer(pathname_op)?)?; let buf = this.read_pointer(buf_op)?; let bufsize = this.read_target_usize(bufsize_op)?; @@ -1722,16 +1722,26 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(-1); } - let result = std::fs::read_link(pathname); + // On Linux, special case `/proc/self/exe` so that `std::env::current_exe` works + // in cross-execution. + let result = if matches!(this.tcx.sess.target.os, Os::Linux) + && pathname.to_str() == Some("/proc/self/exe") + { + std::env::current_exe() + } else { + // We read `pathname` as `OsStr` above so we could do the /proc/self/exe check. + // But now we need a (host) path. + let pathname = this.convert_path(Cow::Borrowed(pathname), PathConversion::TargetToHost); + std::fs::read_link(pathname) + }; + match result { Ok(resolved) => { // 'readlink' truncates the resolved path if the provided buffer is not large // enough, and does *not* add a null terminator. That means we cannot use the usual // `write_path_to_c_str` and have to re-implement parts of it ourselves. - let resolved = this.convert_path( - Cow::Borrowed(resolved.as_ref()), - crate::shims::os_str::PathConversion::HostToTarget, - ); + let resolved = this + .convert_path(Cow::Borrowed(resolved.as_ref()), PathConversion::HostToTarget); let mut path_bytes = resolved.as_encoded_bytes(); let bufsize: usize = bufsize.try_into().unwrap(); if path_bytes.len() > bufsize { diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 08eb1e949dfb7..3c8cf8bcceebd 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -1,5 +1,4 @@ -//@only-on-host: the Linux std implementation opens /proc/self/exe, which doesn't work cross-target -//@ignore-target: freebsd # On FreeBSD the standard library uses `sysctl` for this, which is not shimmed +//@ignore-target: freebsd illumos solaris # we don't have the shims this needs here //@compile-flags: -Zmiri-disable-isolation use std::env; From 1956fd1ad0b401f0832575ebcfa306f7d5fd73c9 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Thu, 1 Oct 2026 22:17:11 +0200 Subject: [PATCH 1162/1309] x86: c-variadic functions don't use registers with `-Zregparm` --- compiler/rustc_target/src/callconv/x86.rs | 4 ++ tests/assembly-llvm/regparm-module-flag.rs | 76 ++++++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index efe88bff6504c..abb9f91fde161 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -206,7 +206,11 @@ pub(crate) fn fill_inregs<'a, Ty, C>( // An `extern "fastcall"` and `extern "vectorcall"` function always have 2 registers available. // Otherwise the `regparam` count (in the range 0..=3) determines the number of available // registers. If unspecified, no registers are used for argument passing. + // + // Functions that take a variable number of arguments continue to be passed all of their + // arguments on the stack. let mut free_regs = match opts.flavor { + _ if fn_abi.c_variadic => 0, Flavor::FastcallOrVectorcall => 2, Flavor::General { regparam } => u64::from(regparam.unwrap_or(0)), }; diff --git a/tests/assembly-llvm/regparm-module-flag.rs b/tests/assembly-llvm/regparm-module-flag.rs index 4a08bfdf85e5f..b1f76079c90fc 100644 --- a/tests/assembly-llvm/regparm-module-flag.rs +++ b/tests/assembly-llvm/regparm-module-flag.rs @@ -3,7 +3,8 @@ //@ add-minicore //@ assembly-output: emit-asm //@ compile-flags: -O --target=i686-unknown-linux-gnu -Crelocation-model=static -//@ revisions: REGPARM1 REGPARM2 REGPARM3 +//@ revisions: REGPARM0 REGPARM1 REGPARM2 REGPARM3 +//@[REGPARM0] compile-flags: -Zregparm=0 //@[REGPARM1] compile-flags: -Zregparm=1 //@[REGPARM2] compile-flags: -Zregparm=2 //@[REGPARM3] compile-flags: -Zregparm=3 @@ -16,13 +17,12 @@ extern crate minicore; use minicore::*; -unsafe extern "C" { - fn memset(p: *mut c_void, val: i32, len: usize) -> *mut c_void; - fn non_builtin_memset(p: *mut c_void, val: i32, len: usize) -> *mut c_void; -} - #[unsafe(no_mangle)] pub unsafe extern "C" fn entrypoint(len: usize, ptr: *mut c_void, val: i32) -> *mut c_void { + unsafe extern "C" { + fn memset(p: *mut c_void, val: i32, len: usize) -> *mut c_void; + } + // REGPARM1-LABEL: entrypoint // REGPARM1: movl %e{{.*}}, %ecx // REGPARM1: pushl @@ -49,6 +49,10 @@ pub unsafe extern "C" fn non_builtin_entrypoint( ptr: *mut c_void, val: i32, ) -> *mut c_void { + unsafe extern "C" { + fn non_builtin_memset(p: *mut c_void, val: i32, len: usize) -> *mut c_void; + } + // REGPARM1-LABEL: non_builtin_entrypoint // REGPARM1: movl %e{{.*}}, %ecx // REGPARM1: pushl @@ -68,3 +72,63 @@ pub unsafe extern "C" fn non_builtin_entrypoint( // REGPARM3: jmp non_builtin_memset unsafe { non_builtin_memset(ptr, val, len) } } + +#[unsafe(no_mangle)] +pub unsafe extern "C" fn test_i32() -> i32 { + extern "C" { + fn test_i32_sink(_: i32, _: i32, _: i32) -> i32; + } + + // REGPARM0-LABEL: test_i32 + // REGPARM0: subl $16, %esp + // REGPARM0: pushl $3 + // REGPARM0: pushl $2 + // REGPARM0: pushl $1 + // REGPARM0: calll test_i32_sink + // REGPARM0: addl $28, %esp + // REGPARM0: retl + + // REGPARM1-LABEL: test_i32 + // REGPARM1: subl $20, %esp + // REGPARM1: movl $1, %eax + // REGPARM1: pushl $3 + // REGPARM1: pushl $2 + // REGPARM1: calll test_i32_sink + // REGPARM1: addl $28, %esp + // REGPARM1: retl + + // REGPARM2-LABEL: test_i32 + // REGPARM2: subl $12, %esp + // REGPARM2: movl $1, %eax + // REGPARM2: movl $2, %edx + // REGPARM2: movl $3, (%esp) + // REGPARM2: calll test_i32_sink + // REGPARM2: addl $12, %esp + // REGPARM2: retl + + // REGPARM3-LABEL: test_i32 + // REGPARM3: movl $1, %eax + // REGPARM3: movl $2, %edx + // REGPARM3: movl $3, %ecx + // REGPARM3: jmp test_i32_sink + unsafe { test_i32_sink(1, 2, 3) } +} + +// A c-variadic function does not use registers for argument passing, +// even when not actually passing any c-variadic arguments. +#[unsafe(no_mangle)] +pub unsafe extern "C" fn test_i32_variadic() -> i32 { + extern "C" { + fn test_i32_variadic_sink(_: i32, _: i32, _: i32, ...) -> i32; + } + + // CHECK-LABEL: test_i32_variadic + // CHECK: subl $16, %esp + // CHECK: pushl $3 + // CHECK: pushl $2 + // CHECK: pushl $1 + // CHECK: calll test_i32_variadic_sink + // CHECK: addl $28, %esp + // CHECK: retl + unsafe { test_i32_variadic_sink(1, 2, 3) } +} From 14167187bbd399f0db2899581a604309071ef59b Mon Sep 17 00:00:00 2001 From: Zachary S Date: Wed, 30 Sep 2026 16:13:28 -0500 Subject: [PATCH 1163/1309] Add tests for `()`, `!`, and `bool`'s size and alignment to `coretests`. --- library/coretests/tests/mem.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/library/coretests/tests/mem.rs b/library/coretests/tests/mem.rs index 793c9f489e47f..845929ac54caf 100644 --- a/library/coretests/tests/mem.rs +++ b/library/coretests/tests/mem.rs @@ -10,6 +10,9 @@ use std::rc::Rc; #[test] fn size_of_basic() { + assert_eq!(size_of::<()>(), 0); + assert_eq!(size_of::(), 0); + assert_eq!(size_of::(), 1); assert_eq!(size_of::(), 1); assert_eq!(size_of::(), 2); assert_eq!(size_of::(), 4); @@ -47,6 +50,9 @@ fn size_of_val_basic() { #[test] fn align_of_basic() { + assert_eq!(align_of::<()>(), 1); + assert_eq!(align_of::(), 1); + assert_eq!(align_of::(), 1); assert_eq!(align_of::(), 1); assert_eq!(align_of::(), 2); assert_eq!(align_of::(), 4); From 5e04ccd901bb3e03cb3ef2208b9648af7667ef5c Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Thu, 1 Oct 2026 17:03:13 +1000 Subject: [PATCH 1164/1309] Add a single-entry parent `SpanData` cache For use in encoding, decoding, and stable hashing. It's a decent performance win on a number of benchmarks. --- compiler/rustc_middle/src/ich.rs | 42 +++++++++++++++---- .../rustc_middle/src/query/on_disk_cache.rs | 14 +++++-- compiler/rustc_middle/src/ty/context.rs | 7 ---- 3 files changed, 46 insertions(+), 17 deletions(-) diff --git a/compiler/rustc_middle/src/ich.rs b/compiler/rustc_middle/src/ich.rs index 6e0a855707f9d..feb162ad1e162 100644 --- a/compiler/rustc_middle/src/ich.rs +++ b/compiler/rustc_middle/src/ich.rs @@ -5,10 +5,11 @@ use rustc_data_structures::fingerprint::Fingerprint; use rustc_data_structures::stable_hash::{ RawDefId, RawSpan, StableHash, StableHashControls, StableHashCtxt, StableHasher, }; +use rustc_data_structures::sync::AppendOnlyIndexVec; use rustc_hir::def_id::{DefId, LocalDefId}; use rustc_session::Session; use rustc_span::source_map::SourceMap; -use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, Pos, Span}; +use rustc_span::{BytePos, CachingSourceMapView, DUMMY_SP, Pos, Span, SpanData}; // Very often, we are hashing something that does not need the `CachingSourceMapView`, so we // initialize it lazily. @@ -28,6 +29,7 @@ pub struct StableHashState<'a> { incremental_ignore_spans: bool, caching_source_map: CachingSourceMap<'a>, stable_hash_controls: StableHashControls, + source_span_cache: SourceSpanCache, } impl<'a> StableHashState<'a> { @@ -40,6 +42,7 @@ impl<'a> StableHashState<'a> { incremental_ignore_spans: sess.opts.unstable_opts.incremental_ignore_spans, caching_source_map: CachingSourceMap::Unused(sess.source_map()), stable_hash_controls: StableHashControls { hash_spans: hash_spans_initial }, + source_span_cache: SourceSpanCache::default(), } } @@ -62,11 +65,6 @@ impl<'a> StableHashState<'a> { } } - #[inline] - fn def_span(&self, def_id: LocalDefId) -> Span { - self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP) - } - #[inline] pub fn stable_hash_controls(&self) -> StableHashControls { self.stable_hash_controls @@ -119,7 +117,9 @@ impl<'a> StableHashCtxt for StableHashState<'a> { return; } - let parent = span.parent.map(|parent| self.def_span(parent).data_untracked()); + let parent = span + .parent + .map(|parent| self.source_span_cache.lookup(parent, &self.untracked.source_span)); if let Some(parent) = parent && parent.contains(span) { @@ -207,3 +207,31 @@ impl<'a> StableHashCtxt for StableHashState<'a> { self.stable_hash_controls } } + +/// A single-entry cache for a `SpanData`, to optimize a particular scenario: when iterating +/// through child spans (e.g. during encoding/decoding/hashing), many of those spans will have the +/// same parent span. In the case where that parent span is interned (e.g. the parent is a const +/// literal item exceeding MAX_LEN bytes of source code), this cache avoids having to fetch the +/// parent's `SpanData` from the interner (which involves TLS, locking, etc.) over and over. A +/// single entry is enough for an extremely high hit rate. +#[derive(Default)] +pub(crate) struct SourceSpanCache(Option<(LocalDefId, SpanData)>); + +impl SourceSpanCache { + #[inline] + pub(crate) fn lookup( + &mut self, + def_id: LocalDefId, + source_span: &AppendOnlyIndexVec, + ) -> SpanData { + if let Some(cache) = self.0 + && cache.0 == def_id + { + cache.1 + } else { + let span_data = source_span.get(def_id).unwrap_or(DUMMY_SP).data_untracked(); + self.0 = Some((def_id, span_data)); + span_data + } + } +} diff --git a/compiler/rustc_middle/src/query/on_disk_cache.rs b/compiler/rustc_middle/src/query/on_disk_cache.rs index 20c1c5c16c95c..e4274344a5d07 100644 --- a/compiler/rustc_middle/src/query/on_disk_cache.rs +++ b/compiler/rustc_middle/src/query/on_disk_cache.rs @@ -25,6 +25,7 @@ use rustc_span::{ }; use crate::dep_graph::{DepNodeIndex, QuerySideEffect, SerializedDepNodeIndex}; +use crate::ich::SourceSpanCache; use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState}; use crate::mir::{self, interpret}; use crate::mono::MonoItem; @@ -235,6 +236,7 @@ impl OnDiskCache { file_to_file_index, hygiene_context: Default::default(), symbol_index_table: Default::default(), + source_span_cache: Default::default(), query_values_index: Default::default(), side_effects_index: Default::default(), }; @@ -383,6 +385,7 @@ impl OnDiskCache { expn_data: &self.expn_data, foreign_expn_data: &self.foreign_expn_data, hygiene_context: &self.hygiene_context, + source_span_cache: SourceSpanCache::default(), }; f(&mut decoder) } @@ -403,6 +406,7 @@ pub struct CacheDecoder<'a, 'tcx> { expn_data: &'a UnhashMap, foreign_expn_data: &'a UnhashMap, hygiene_context: &'a HygieneDecodeContext, + source_span_cache: SourceSpanCache, } impl<'a, 'tcx> CacheDecoder<'a, 'tcx> { @@ -611,7 +615,9 @@ impl<'a, 'tcx> SpanDecoder for CacheDecoder<'a, 'tcx> { let dlo = u32::decode(self); let dto = u32::decode(self); - let enclosing = self.tcx.source_span_untracked(parent.unwrap()).data_untracked(); + let enclosing = self + .source_span_cache + .lookup(parent.unwrap(), &self.tcx.untracked().source_span); ( BytePos(enclosing.lo.0.wrapping_add(dlo)), BytePos(enclosing.lo.0.wrapping_add(dto)), @@ -744,6 +750,7 @@ pub struct CacheEncoder<'tcx> { hygiene_context: Rc>, // Used for both `Symbol`s and `ByteSymbol`s. symbol_index_table: FxHashMap, + source_span_cache: SourceSpanCache, query_values_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, side_effects_index: Vec<(SerializedDepNodeIndex, AbsoluteBytePos)>, @@ -845,8 +852,9 @@ impl<'tcx> SpanEncoder for CacheEncoder<'tcx> { return TAG_PARTIAL_SPAN.encode(self); } - let parent = - span_data.parent.map(|parent| self.tcx.source_span_untracked(parent).data_untracked()); + let parent = span_data + .parent + .map(|parent| self.source_span_cache.lookup(parent, &self.tcx.untracked().source_span)); if let Some(parent) = parent && parent.contains(span_data) { diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index b6e204dd52a11..e9ff8f094a3f8 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1426,13 +1426,6 @@ impl<'tcx> TyCtxt<'tcx> { self.untracked.definitions.read() } - /// Note that this is *untracked* and should only be used within the query - /// system if the result is otherwise tracked through queries - #[inline] - pub fn source_span_untracked(self, def_id: LocalDefId) -> Span { - self.untracked.source_span.get(def_id).unwrap_or(DUMMY_SP) - } - #[inline(always)] pub fn with_stable_hashing_context(self, f: impl FnOnce(StableHashState<'_>) -> R) -> R { f(StableHashState::new(self.sess, &self.untracked)) From da9fe25387b15599d714a6c93b38c49dc914cc2b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 08:05:47 +0200 Subject: [PATCH 1165/1309] getaddrinfo test: ensure we see both IPv4 and IPv6 --- src/tools/miri/tests/pass-dep/libc/libc-socket-address.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-socket-address.rs b/src/tools/miri/tests/pass-dep/libc/libc-socket-address.rs index bb34c7de73a7f..a53f35ad197a1 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-socket-address.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-socket-address.rs @@ -34,7 +34,8 @@ fn test_getaddrinfo_freeaddrinfo() { )); } let start = res; - let mut addr_count = 0; + let mut addr_count_v4 = 0; + let mut addr_count_v6 = 0; loop { unsafe { @@ -43,9 +44,9 @@ fn test_getaddrinfo_freeaddrinfo() { break; }; - addr_count += 1; match (*cur).ai_family as libc::c_int { libc::AF_INET => { + addr_count_v4 += 1; let (_, addr) = net::sockname_ipv4(|storage, len| { *(storage as *mut libc::sockaddr_in) = *cur.ai_addr.cast(); *len = (*res).ai_addrlen; @@ -59,6 +60,7 @@ fn test_getaddrinfo_freeaddrinfo() { assert_eq!(localhost_ipv4.sin_addr.s_addr, addr.sin_addr.s_addr); } libc::AF_INET6 => { + addr_count_v6 += 1; let (_, addr) = net::sockname_ipv6(|storage, len| { *(storage as *mut libc::sockaddr_in6) = *cur.ai_addr.cast(); *len = (*res).ai_addrlen; @@ -81,7 +83,7 @@ fn test_getaddrinfo_freeaddrinfo() { } // We expect an IPv4 and an IPv6 address. - assert!(addr_count == 2); + assert!(addr_count_v4 == 1 && addr_count_v6 == 1); unsafe { libc::freeaddrinfo(start.cast()); From b533b2617d100235c1c5398cf778b7d706bf31d8 Mon Sep 17 00:00:00 2001 From: landsharkiest Date: Fri, 2 Oct 2026 03:47:42 +0000 Subject: [PATCH 1166/1309] Add mul_add_relaxed methods for floating-point types --- compiler/rustc_span/src/symbol.rs | 1 + library/core/src/intrinsics/mod.rs | 12 +++ library/core/src/num/f128.rs | 39 +++++++++ library/core/src/num/f16.rs | 36 ++++++++ library/core/src/num/f32.rs | 41 +++++++++ library/core/src/num/f64.rs | 44 ++++++++++ tests/ui/intrinsics/float-mul-add-relaxed.rs | 87 ++++++++++++++++++++ 7 files changed, 260 insertions(+) create mode 100644 tests/ui/intrinsics/float-mul-add-relaxed.rs diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e62ad42875248..78b417f13bde7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -996,6 +996,7 @@ symbols! { fields, file, final_associated_functions, + float_mul_add_relaxed, float_to_int_unchecked, floorf16, floorf32, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ecc8b66ec5785..2f6a125cd5d79 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -1404,6 +1404,9 @@ pub const fn fmaf128(a: f128, b: f128, c: f128) -> f128; /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +/// +/// The stabilized version of this intrinsic is +/// [`f16::mul_add_relaxed`](../../std/primitive.f16.html#method.mul_add_relaxed) #[inline] #[rustc_intrinsic] #[rustc_nounwind] @@ -1420,6 +1423,9 @@ pub const fn fmuladdf16(a: f16, b: f16, c: f16) -> f16 { /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +/// +/// The stabilized version of this intrinsic is +/// [`f32::mul_add_relaxed`](../../std/primitive.f32.html#method.mul_add_relaxed) #[inline] #[rustc_intrinsic] #[rustc_nounwind] @@ -1436,6 +1442,9 @@ pub const fn fmuladdf32(a: f32, b: f32, c: f32) -> f32 { /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +/// +/// The stabilized version of this intrinsic is +/// [`f64::mul_add_relaxed`](../../std/primitive.f64.html#method.mul_add_relaxed) #[inline] #[rustc_intrinsic] #[rustc_nounwind] @@ -1452,6 +1461,9 @@ pub const fn fmuladdf64(a: f64, b: f64, c: f64) -> f64 { /// and add instructions. It is unspecified whether or not a fused operation /// is selected, and that may depend on optimization level and context, for /// example. +/// +/// The stabilized version of this intrinsic is +/// [`f128::mul_add_relaxed`](../../std/primitive.f128.html#method.mul_add_relaxed) #[inline] #[rustc_intrinsic] #[rustc_nounwind] diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index db05d7fdc5087..25ad64a12002c 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -1997,6 +1997,45 @@ impl f128 { intrinsics::fmaf128(self, a, b) } + /// Computes `(self * a) + b` with nondeterministic rounding. + /// + /// This is similar to [`mul_add`](Self::mul_add), but the intermediate + /// result may be rounded differently depending on the implementation. + /// The operation is either executed as a single fused multiply-add + /// instruction, or as separate multiply and add instructions. + /// + /// The choice of which one is used is unspecified and non-deterministic: + /// it may vary by target, optimization level, and surrounding code, and + /// even two invocations of this operation with the same inputs may + /// produce different results. + /// + /// # Examples + /// + /// ``` + /// #![feature(f128)] + /// #![feature(float_mul_add_relaxed)] + /// # #[cfg(any(miri, target_has_reliable_f128_math))] { // Miri uses softfloats, always works + /// + /// // When the fused and unfused operations round differently, either + /// // result may be returned: + /// // - 7.824090399073145653039910391751267e-37 is the fused result (one rounding) + /// // - 1.5046327690525280101999827676444745e-36 is the unfused result (two roundings) + /// let r = 0.1_f128.mul_add_relaxed(0.1_f128, -0.01_f128); + /// assert!( + /// r == 7.824090399073145653039910391751267e-37 + /// || r == 1.5046327690525280101999827676444745e-36 + /// ); + /// # } + /// ``` + #[inline] + #[rustc_allow_incoherent_impl] + #[doc(alias = "fmuladd")] + #[unstable(feature = "float_mul_add_relaxed", issue = "151770")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn mul_add_relaxed(self, a: f128, b: f128) -> f128 { + intrinsics::fmuladdf128(self, a, b) + } + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 273ef3688ca5f..7147802486d62 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -1983,6 +1983,42 @@ impl f16 { intrinsics::fmaf16(self, a, b) } + /// Computes `(self * a) + b` with nondeterministic rounding. + /// + /// This is similar to [`mul_add`](Self::mul_add), but the intermediate + /// result may be rounded differently depending on the implementation. + /// The operation is either executed as a single fused multiply-add + /// instruction, or as separate multiply and add instructions. + /// + /// The choice of which one is used is unspecified and non-deterministic: + /// it may vary by target, optimization level, and surrounding code, and + /// even two invocations of this operation with the same inputs may + /// produce different results. + /// + /// # Examples + /// + /// ``` + /// #![feature(f16)] + /// #![feature(float_mul_add_relaxed)] + /// # #[cfg(target_has_reliable_f16)] { + /// + /// // When the fused and unfused operations round differently, either + /// // result may be returned: + /// // - -7.03e-6 is the fused result (one rounding) + /// // - -7.6e-6 is the unfused result (two roundings) + /// let r = 0.1_f16.mul_add_relaxed(0.1_f16, -0.01_f16); + /// assert!(r == -7.03e-6 || r == -7.6e-6); + /// # } + /// ``` + #[inline] + #[rustc_allow_incoherent_impl] + #[doc(alias = "fmuladd")] + #[unstable(feature = "float_mul_add_relaxed", issue = "151770")] + #[must_use = "method returns a new number and does not mutate the original value"] + pub const fn mul_add_relaxed(self, a: f16, b: f16) -> f16 { + intrinsics::fmuladdf16(self, a, b) + } + /// Calculates Euclidean division, the matching method for `rem_euclid`. /// /// This computes the integer `n` such that diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index d3dea38dc2fcf..e2d13f8f12f2a 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -1880,6 +1880,47 @@ impl f32 { intrinsics::frem_algebraic(self, rhs) } + /// Computes `(self * a) + b` with nondeterministic rounding. + /// + /// This is similar to [`mul_add`], but the intermediate result may be + /// rounded differently depending on the implementation. The operation is + /// either executed as a single fused multiply-add instruction, or as + /// separate multiply and add instructions. + /// + /// The choice of which one is used is unspecified and non-deterministic: + /// it may vary by target, optimization level, and surrounding code, and + /// even two invocations of this operation with the same inputs may + /// produce different results. + /// + /// # Precision + /// + /// The result of this operation is not guaranteed: it is either the result + /// of [`mul_add`] (one rounding of the infinite-precision result) or of + /// `self * a + b` (two roundings, with an intermediate rounding of the + /// product). + /// + /// # Examples + /// + /// ``` + /// #![feature(float_mul_add_relaxed)] + /// + /// // When the fused and unfused operations round differently, either + /// // result may be returned: + /// // - 5.2154064e-10 is the fused result (one rounding) + /// // - 9.313226e-10 is the unfused result (two roundings) + /// let r = 0.1_f32.mul_add_relaxed(0.1_f32, -0.01_f32); + /// assert!(r == 5.2154064e-10 || r == 9.313226e-10); + /// ``` + /// + /// [`mul_add`]: ../std/primitive.f32.html#method.mul_add + #[must_use = "method returns a new number and does not mutate the original value"] + #[doc(alias = "fmuladd")] + #[unstable(feature = "float_mul_add_relaxed", issue = "151770")] + #[inline] + pub const fn mul_add_relaxed(self, a: f32, b: f32) -> f32 { + intrinsics::fmuladdf32(self, a, b) + } + /// Returns `self` if the value is not NaN, otherwise returns `replacement` /// if `self` is NaN. /// diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 7c5082749cd11..001172d9b84cb 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -1858,6 +1858,50 @@ impl f64 { intrinsics::frem_algebraic(self, rhs) } + /// Computes `(self * a) + b` with nondeterministic rounding. + /// + /// This is similar to [`mul_add`], but the intermediate result may be + /// rounded differently depending on the implementation. The operation is + /// either executed as a single fused multiply-add instruction, or as + /// separate multiply and add instructions. + /// + /// The choice of which one is used is unspecified and non-deterministic: + /// it may vary by target, optimization level, and surrounding code, and + /// even two invocations of this operation with the same inputs may + /// produce different results. + /// + /// # Precision + /// + /// The result of this operation is not guaranteed: it is either the result + /// of [`mul_add`] (one rounding of the infinite-precision result) or of + /// `self * a + b` (two roundings, with an intermediate rounding of the + /// product). + /// + /// # Examples + /// + /// ``` + /// #![feature(float_mul_add_relaxed)] + /// + /// // When the fused and unfused operations round differently, either + /// // result may be returned: + /// // - 9.020562075079397e-19 is the fused result (one rounding) + /// // - 1.734723475976807e-18 is the unfused result (two roundings) + /// # // FIXME(#114479): on `i586`, x87 excess precision gives neither allowed result + /// # #[cfg(not(all(target_arch = "x86", not(target_feature = "sse2"))))] { + /// let r = 0.1_f64.mul_add_relaxed(0.1_f64, -0.01_f64); + /// assert!(r == 9.020562075079397e-19 || r == 1.734723475976807e-18); + /// # } + /// ``` + /// + /// [`mul_add`]: ../std/primitive.f64.html#method.mul_add + #[must_use = "method returns a new number and does not mutate the original value"] + #[doc(alias = "fmuladd")] + #[unstable(feature = "float_mul_add_relaxed", issue = "151770")] + #[inline] + pub const fn mul_add_relaxed(self, a: f64, b: f64) -> f64 { + intrinsics::fmuladdf64(self, a, b) + } + /// Returns `self` if the value is not NaN, otherwise returns `replacement` /// if `self` is NaN. /// diff --git a/tests/ui/intrinsics/float-mul-add-relaxed.rs b/tests/ui/intrinsics/float-mul-add-relaxed.rs new file mode 100644 index 0000000000000..5ab9d52a88d48 --- /dev/null +++ b/tests/ui/intrinsics/float-mul-add-relaxed.rs @@ -0,0 +1,87 @@ +//@ run-pass +//@ compile-flags: -O + +// Check that `mul_add_relaxed` returns either the fused result (one rounding) +// or the unfused result (two roundings), including with optimizations enabled +// where the operation may be const-folded or lowered to a fused instruction. + +#![feature(float_mul_add_relaxed)] +#![feature(f16)] +#![feature(f128)] +#![feature(cfg_target_has_reliable_f16_f128)] +// `f16`/`f128` go unused on targets without reliable f16/f128 math, where the +// gated test functions below are compiled out. +#![allow(unused_features)] +// `target_has_reliable_*` are not "known" configs since they are unstable. +#![expect(unexpected_cfgs)] + +use std::assert_matches; +use std::hint::black_box; + +// On x86 without SSE2 (e.g. the i586 target), floating-point math is evaluated +// with x87 excess precision, so an inexact `mul_add_relaxed` may round to a +// value that is neither the `fN`-precise fused nor unfused result. Skip the +// exact-value checks there. +const EXCESS_PRECISION: bool = cfg!(all(target_arch = "x86", not(target_feature = "sse2"))); + +fn main() { + test_f32(); + test_f64(); + #[cfg(target_has_reliable_f16_math)] + test_f16(); + #[cfg(target_has_reliable_f128_math)] + test_f128(); +} + +fn test_f32() { + // Exactly representable results are the same whether or not the + // operation is fused. + assert_eq!(black_box(2.0_f32).mul_add_relaxed(3.0, 4.0), 10.0); + assert_eq!(black_box(1.0_f32).mul_add_relaxed(1.0, 1.0), 2.0); + + // `0.1 * 0.1` is inexact, so the fused (one rounding) and unfused (two + // roundings) results differ; either is allowed. + if !EXCESS_PRECISION { + let r = black_box(0.1_f32).mul_add_relaxed(0.1, -0.01); + assert_matches!(r, 5.2154064e-10 | 9.313226e-10); + } + + // Edge cases behave like `a * b + c` regardless of fusion. + assert!(black_box(f32::NAN).mul_add_relaxed(1.0, 1.0).is_nan()); + assert_eq!(black_box(f32::INFINITY).mul_add_relaxed(2.0, 1.0), f32::INFINITY); + assert!(black_box(0.0_f32).mul_add_relaxed(f32::INFINITY, 1.0).is_nan()); +} + +fn test_f64() { + assert_eq!(black_box(2.0_f64).mul_add_relaxed(3.0, 4.0), 10.0); + assert_eq!(black_box(1.0_f64).mul_add_relaxed(1.0, 1.0), 2.0); + + if !EXCESS_PRECISION { + let r = black_box(0.1_f64).mul_add_relaxed(0.1, -0.01); + assert_matches!(r, 9.020562075079397e-19 | 1.734723475976807e-18); + } + + assert!(black_box(f64::NAN).mul_add_relaxed(1.0, 1.0).is_nan()); + assert_eq!(black_box(f64::INFINITY).mul_add_relaxed(2.0, 1.0), f64::INFINITY); + assert!(black_box(0.0_f64).mul_add_relaxed(f64::INFINITY, 1.0).is_nan()); +} + +#[cfg(target_has_reliable_f16_math)] +fn test_f16() { + assert_eq!(black_box(2.0_f16).mul_add_relaxed(3.0, 4.0), 10.0); + assert_eq!(black_box(1.0_f16).mul_add_relaxed(1.0, 1.0), 2.0); + + assert!(black_box(f16::NAN).mul_add_relaxed(1.0, 1.0).is_nan()); + assert_eq!(black_box(f16::INFINITY).mul_add_relaxed(2.0, 1.0), f16::INFINITY); + assert!(black_box(0.0_f16).mul_add_relaxed(f16::INFINITY, 1.0).is_nan()); +} + +#[cfg(target_has_reliable_f128_math)] +fn test_f128() { + assert_eq!(black_box(2.0_f128).mul_add_relaxed(3.0, 4.0), 10.0); + assert_eq!(black_box(1.0_f128).mul_add_relaxed(1.0, 1.0), 2.0); + + assert!(black_box(f128::NAN).mul_add_relaxed(1.0, 1.0).is_nan()); + assert_eq!(black_box(f128::INFINITY).mul_add_relaxed(2.0, 1.0), f128::INFINITY); + assert!(black_box(0.0_f128).mul_add_relaxed(f128::INFINITY, 1.0).is_nan()); +} From e75273b0247664eded2f7bd482c76dc0adaaf149 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 2 Oct 2026 08:44:29 +0200 Subject: [PATCH 1167/1309] core: io: clean `unused_variables` lint under `no_io_statics` When building `core` with `--cfg no_io_statics`, the compiler warns: error: unused variable: `f` --> .../library/core/src/io/error/os_functions.rs:9:36 | 9 | pub(super) unsafe fn set_functions(f: &'static OsFunctions) { | ^ help: if this is intentional, prefix it with an underscore: `_f` | = note: `-D unused-variables` implied by `-D warnings` = help: to override `-D warnings` add `#[allow(unused_variables)]` Thus clean it up. Signed-off-by: Miguel Ojeda --- library/core/src/io/error/os_functions.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/io/error/os_functions.rs b/library/core/src/io/error/os_functions.rs index b34b7c7dc7926..fcc549f0fb643 100644 --- a/library/core/src/io/error/os_functions.rs +++ b/library/core/src/io/error/os_functions.rs @@ -6,7 +6,7 @@ use crate::fmt; /// The provided reference must point to data that is entirely constant; it must /// not be created during runtime. #[inline] -pub(super) unsafe fn set_functions(f: &'static OsFunctions) { +pub(super) unsafe fn set_functions(_f: &'static OsFunctions) { // FIXME: externally implementable items may allow for weak linkage, allowing // these methods to be overridden even when atomic pointers are not supported. } From 6d70bb1e20f9f9fb2c8e2b6950f137b3a51da5b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 08:47:06 +0200 Subject: [PATCH 1168/1309] bump rustc-build-sysroot --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6866b2c8e4d92..49ab9451ba5e0 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3493,9 +3493,9 @@ dependencies = [ [[package]] name = "rustc-build-sysroot" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "569d545953ee9a1ab9d3e9112e961739ff0cfd50bce06b126937395940be69c9" +checksum = "0d0ed7817483b026efc0492f4ccca177f00fb711537f37943cc412bbf12682b4" dependencies = [ "anyhow", "rustc_version", From 422a96488a92ff006110cddcafc85dabbc5f94f3 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 08:49:20 +0200 Subject: [PATCH 1169/1309] bump dependencies --- src/tools/miri/Cargo.lock | 222 +++++++++++++-------------- src/tools/miri/cargo-miri/Cargo.lock | 72 ++++----- src/tools/miri/priroda/Cargo.lock | 162 +++++++++---------- src/tools/miri/tests/deps/Cargo.lock | 65 ++++---- 4 files changed, 234 insertions(+), 287 deletions(-) diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock index 8cffd4defac3d..5037ac5b2c217 100644 --- a/src/tools/miri/Cargo.lock +++ b/src/tools/miri/Cargo.lock @@ -19,9 +19,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ "cipher", "cpubits", @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "bstr" @@ -105,9 +105,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "camino" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" dependencies = [ "serde_core", ] @@ -151,14 +151,14 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] name = "cc" -version = "1.4.4" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" dependencies = [ "find-msvc-tools", "jobserver", @@ -168,9 +168,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cfg_aliases" @@ -220,18 +220,18 @@ dependencies = [ [[package]] name = "clap" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "473c7e07f409a8d772161724aa8db6a765a2532a70f9667eeb7b49d3d02fbdca" +checksum = "aa8876b300ab35ba921adea3dfd70157a46249b33f95c9084ae5709785478946" dependencies = [ "clap_builder", ] [[package]] name = "clap_builder" -version = "4.6.6" +version = "4.6.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7b48fea5a88e9ae728a2dcbedbfc0e730f7d60da42e1cb049a83c9fb8b789889" +checksum = "ec0797fb7aeb1406c84efac526901f7ec3ead2124f946b494e72879d4b54704d" dependencies = [ "anstyle", "clap_lex", @@ -240,9 +240,9 @@ dependencies = [ [[package]] name = "clap_lex" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8d4a3bb8b1e0c1050499d1815f5ab16d04f0959b233085fb31653fbfc9d98f9" +checksum = "1c133bc6a41be0d194c306b5506d15e6feeea7b1d6604bd3f8310dfb2ca96486" [[package]] name = "cmake" @@ -259,7 +259,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -317,9 +317,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.16.4" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" dependencies = [ "encode_unicode", "libc", @@ -335,27 +335,27 @@ checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-common" @@ -368,9 +368,9 @@ dependencies = [ [[package]] name = "cxx" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "824894a4a85dca76d4c95c2b9098c036f5a29f627b30c12780774f6654e60974" +checksum = "13f6de320895f42e6e081abb5c7983bedcf0b6d0ff9323de0d33f620c8ac1199" dependencies = [ "cc", "cxx-build", @@ -383,9 +383,9 @@ dependencies = [ [[package]] name = "cxx-build" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ae0b651ea5b0000b19513aef5a03f194d7e3486f2d9258b658da8677fe9036" +checksum = "4fde53ca86b9704a943fef0f1e1d836239a6aedca5de3c65fa9f97ec0bd46d39" dependencies = [ "cc", "codespan-reporting", @@ -393,39 +393,39 @@ dependencies = [ "proc-macro2", "quote", "scratch", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] name = "cxxbridge-cmd" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb05f91d3fb8435d9bab6ac5ce6ac1868be774325fb7fb2a91be39393b21388e" +checksum = "07bae89236c811fd4d08ed3441759ac4ac98d752cbfd3de341315ba16ad20ec3" dependencies = [ "clap", "codespan-reporting", "indexmap", "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] name = "cxxbridge-flags" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bf293202e0e3e98495785745389e8d0755b217e66f19194a5c695c25e03282ef" +checksum = "49045042e5fced01b80742aba5508de82aa4f13677ed3fa2b4cda709c40c5918" [[package]] name = "cxxbridge-macro" -version = "1.0.199" +version = "1.0.202" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ca001d746947c7249ed9d332a10f7a59daedbafeb0ec68c5c18a7db7a93f6ccc" +checksum = "b181252e2e3d3b5d183afbdc033a3958b445eb3e1a0ae65fc3d4f5259f5da6fd" dependencies = [ "indexmap", "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -457,7 +457,7 @@ checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -513,9 +513,9 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "foldhash" @@ -567,17 +567,6 @@ dependencies = [ "git2", ] -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "getrandom" version = "0.3.4" @@ -631,9 +620,9 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ "typenum", ] @@ -750,9 +739,9 @@ checksum = "964de6e86d545b246d84badc0fef527924ace5134f30641c203ef52ba83f58d5" [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown", @@ -794,7 +783,7 @@ dependencies = [ "rustc-hash 2.1.3", "serde_core", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.21", "uuid", "windows", ] @@ -817,9 +806,9 @@ dependencies = [ [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -828,9 +817,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "levenshtein" @@ -888,9 +877,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.20" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ "libc", ] @@ -983,9 +972,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "log", @@ -1014,7 +1003,7 @@ dependencies = [ "measureme", "mio", "nix", - "rand 0.10.2", + "rand 0.10.3", "regex", "rustc_version", "serde", @@ -1088,9 +1077,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "owo-colors" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" +checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8" [[package]] name = "parking_lot" @@ -1247,9 +1236,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom 0.4.3", @@ -1292,13 +1281,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "getrandom 0.2.17", "libredox", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -1371,9 +1359,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ "bitflags", "errno", @@ -1437,7 +1425,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1470,9 +1458,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" [[package]] name = "slab" @@ -1482,9 +1470,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" [[package]] name = "socket2" @@ -1538,9 +1526,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -1549,13 +1537,13 @@ dependencies = [ [[package]] name = "synstructure" -version = "0.13.2" +version = "0.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "728a70f3dbaf5bab7f0c4b1ac8d7ae5ea60a4b5549c8a5914361c99147a709d2" +checksum = "901704edd0dfe137f1987838ee4f259e4e063c31371bdb423f7ae38ec6f77f02" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", ] [[package]] @@ -1591,11 +1579,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.21", ] [[package]] @@ -1611,13 +1599,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1714,9 +1702,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "unicode-width" @@ -1750,9 +1738,9 @@ checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" [[package]] name = "uuid" -version = "1.25.0" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -1788,9 +1776,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -1801,9 +1789,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1811,22 +1799,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] @@ -2001,30 +1989,30 @@ dependencies = [ [[package]] name = "yoke-derive" -version = "0.8.2" +version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de844c262c8848816172cef550288e7dc6c7b7814b4ee56b3e1553f275f1858e" +checksum = "ec8ebde2db3681e8c9980cc27822030e68752690ddfa9473e739aeb4dbde6d71" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" dependencies = [ "proc-macro2", "quote", @@ -2042,13 +2030,13 @@ dependencies = [ [[package]] name = "zerofrom-derive" -version = "0.1.7" +version = "0.1.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11532158c46691caf0f2593ea8358fed6bbf68a0315e80aae9bd41fbade684a1" +checksum = "f75b4683f6c7f45248d4d64056a24298c6281e0993356d7d1b4a1a962ef10d4a" dependencies = [ "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "synstructure", ] @@ -2082,7 +2070,7 @@ checksum = "34df6fc39dbd26ddc9c10e6a2984476e13acce22e64e4487636ef494369225da" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock index 5deb41b66ab8e..1db0a0e7061e3 100644 --- a/src/tools/miri/cargo-miri/Cargo.lock +++ b/src/tools/miri/cargo-miri/Cargo.lock @@ -10,15 +10,15 @@ checksum = "330a5ed07fa54e4702c9d6c4174f74427fc0ef6e214bbd677ae50a5099946470" [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "camino" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" dependencies = [ "serde_core", ] @@ -62,9 +62,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "directories" @@ -109,17 +109,6 @@ version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "getrandom" version = "0.4.3" @@ -139,9 +128,9 @@ checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" [[package]] name = "indexmap" -version = "2.14.0" +version = "2.14.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" +checksum = "cc4e190f5d26ca7051642629da2c52fc03bde85a03197c99408dcd291734c855" dependencies = [ "equivalent", "hashbrown", @@ -161,9 +150,9 @@ checksum = "3eaf3ede3fee6db1a4c2ee091bf8a8b4dccdc6d17f656fb07896ee72867612f2" [[package]] name = "libredox" -version = "0.1.20" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ "libc", ] @@ -218,20 +207,19 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "redox_users" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "getrandom 0.2.17", "libredox", "thiserror", ] [[package]] name = "rustc-build-sysroot" -version = "0.5.13" +version = "0.5.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "569d545953ee9a1ab9d3e9112e961739ff0cfd50bce06b126937395940be69c9" +checksum = "0d0ed7817483b026efc0492f4ccca177f00fb711537f37943cc412bbf12682b4" dependencies = [ "anyhow", "rustc_version", @@ -257,9 +245,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ "bitflags", "errno", @@ -341,9 +329,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -357,7 +345,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32497e9a4c7b38532efcdebeef879707aa9f794296a4f0244f6f69e9bc8574bd" dependencies = [ "fastrand", - "getrandom 0.4.3", + "getrandom", "once_cell", "rustix", "windows-sys", @@ -365,18 +353,18 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", @@ -385,9 +373,9 @@ dependencies = [ [[package]] name = "toml" -version = "1.1.4+spec-1.1.0" +version = "1.1.6+spec-1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3aace63f4bbcdfc2c965b059de67119c89c4017a70d633be6c104910f67056f5" +checksum = "920602543f0911ab71da12c50d59701da54c196d1a2bf5cb4b75667f137a406a" dependencies = [ "indexmap", "serde_core", @@ -424,9 +412,9 @@ checksum = "7d56353a2a665ad0f41a421187180aab746c8c325620617ad883a99a1cbe66d2" [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "walkdir" @@ -438,12 +426,6 @@ dependencies = [ "winapi-util", ] -[[package]] -name = "wasi" -version = "0.11.1+wasi-snapshot-preview1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" - [[package]] name = "winapi-util" version = "0.1.11" diff --git a/src/tools/miri/priroda/Cargo.lock b/src/tools/miri/priroda/Cargo.lock index a690264e158fc..a24d764a39d3a 100644 --- a/src/tools/miri/priroda/Cargo.lock +++ b/src/tools/miri/priroda/Cargo.lock @@ -19,9 +19,9 @@ checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" [[package]] name = "aes" -version = "0.9.2" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8eb277bec05f56a0e0591f155a484cbd0f4f07ff2905051a48c72f004f7ed58" +checksum = "35f0f96ce78e38c3dc6d8948aa8163d06385be74000f3c7a95bf1eef35d3ea32" dependencies = [ "cipher", "cpubits", @@ -82,9 +82,9 @@ dependencies = [ [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "bstr" @@ -105,9 +105,9 @@ checksum = "72f5acc6cb2ba439de613abc23857ec3d78374d8ed5ac84e9d11336e87da8649" [[package]] name = "camino" -version = "1.2.5" +version = "1.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bb1307f12aa967b5a58416e87b3653360e0fd614a016b6e970db08fecbb1b80d" +checksum = "bbbad30e4b4c14a39e3cc8aed085a12a327257c316619c93581e017bc52be591" dependencies = [ "serde_core", ] @@ -151,14 +151,14 @@ dependencies = [ "semver", "serde", "serde_json", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] name = "cc" -version = "1.4.4" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ad534f4357a5264cce5019c989cf66a4f0dc4e0d1b1d15f8aacec0ff7360273" +checksum = "f360145194ee8e21db5ee7f3fcd4fe52210864c75c985dae33218202c8bbe040" dependencies = [ "find-msvc-tools", "shlex", @@ -166,9 +166,9 @@ dependencies = [ [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cfg_aliases" @@ -178,9 +178,9 @@ checksum = "f079e83a288787bcd14a6aea84cee5c87a67c5a3e660c30f557a3d24761b3527" [[package]] name = "chacha20" -version = "0.10.1" +version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d524456ba66e72eb8b115ff89e01e497f8e6d11d78b70b1aa13c0fbd97540a81" +checksum = "65c35e4b699c7e15ccbe7ee35c005e4fc0a278d22238a2857e6ce2dadeda1b06" dependencies = [ "cfg-if", "cpufeatures", @@ -222,7 +222,7 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fa961b519f0b462e3a3b4a34b64d119eeaca1d59af726fe450bbba07a9fc0a1" dependencies = [ - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -269,9 +269,9 @@ checksum = "55b672471b4e9f9e95499ea597ff64941a309b2cdbffcc46f2cc5e2d971fd335" [[package]] name = "console" -version = "0.16.4" +version = "0.16.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fe5f465a4f6fee88fad41b85d990f84c835335e85b5d9e6e63e0d06d28cba7c" +checksum = "e96a4956774c13c126a8b5af4daa79384f4d826534c95a02d76afb39e2ab64e3" dependencies = [ "encode_unicode", "libc", @@ -287,27 +287,27 @@ checksum = "15b85f9c39137c3a891689859392b1bd49812121d0d61c9caf00d46ed5ce06ae" [[package]] name = "cpufeatures" -version = "0.3.0" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201" +checksum = "5ca28b0ae3115b884660db4118d803791fd6756b6e88f39c0f3f7859060d7566" dependencies = [ "libc", ] [[package]] name = "crossbeam-channel" -version = "0.5.16" +version = "0.5.17" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d85363c37faeca707aef026efa9f3b34d077bce547e48f770770625c6013679e" +checksum = "98b0cc327b5bc766e7fda9c9260cc0fa81b43a8e240440422dff70788e3f9ef1" dependencies = [ "crossbeam-utils", ] [[package]] name = "crossbeam-utils" -version = "0.8.22" +version = "0.8.23" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "61803da095bee82a81bb1a452ecc25d3b2f1416d1897eb86430c6159ef717c17" +checksum = "a31eee39dddec8330830986fcd7625edb5a24ec90ea038215273bbc3adb08ac6" [[package]] name = "crypto-common" @@ -397,9 +397,9 @@ checksum = "da7c62ceae207dd37ea5b845da6a0696c799f85e97da1ab5b7910be3c1c80223" [[package]] name = "find-msvc-tools" -version = "0.1.11" +version = "0.1.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d45db016d36b838f563236e9193d0ee6ce38f3f68b6c94e914b4929c96bbb890" +checksum = "aedcfb3409746eddb02b9e19ebda1c3394f759a152e48ee875a0844d1b955484" [[package]] name = "futures-core" @@ -425,17 +425,6 @@ dependencies = [ "slab", ] -[[package]] -name = "getrandom" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" -dependencies = [ - "cfg-if", - "libc", - "wasi", -] - [[package]] name = "getrandom" version = "0.3.4" @@ -468,9 +457,9 @@ checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7" [[package]] name = "hybrid-array" -version = "0.4.14" +version = "0.4.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b" +checksum = "27f864f10dfb56725ce5ce5472bc52252c8f93a4ab86327122cebf62c5f59a17" dependencies = [ "typenum", ] @@ -517,7 +506,7 @@ dependencies = [ "rustc-hash 2.1.3", "serde_core", "tempfile", - "thiserror 2.0.20", + "thiserror 2.0.21", "uuid", "windows", ] @@ -530,9 +519,9 @@ checksum = "8f42a60cbdf9a97f5d2305f08a87dc4e09308d1276d28c869c684d7777685682" [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -541,9 +530,9 @@ dependencies = [ [[package]] name = "lazy_static" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" +checksum = "20870f649af7073d53e38067b2a84312175d56ea15217e1b15bc83506ec50afb" [[package]] name = "levenshtein" @@ -588,9 +577,9 @@ dependencies = [ [[package]] name = "libredox" -version = "0.1.20" +version = "0.1.25" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d0a00925a9f930d679b6789b721e3a7f9ed110f41b86d2497caa780c3a070a" +checksum = "61ff90caf6077a803a240f62fdbe88645a890bbca49ef8174c3cb0404362171d" dependencies = [ "libc", ] @@ -656,9 +645,9 @@ dependencies = [ [[package]] name = "mio" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "log", @@ -685,7 +674,7 @@ dependencies = [ "measureme", "mio", "nix", - "rand 0.10.2", + "rand 0.10.3", "serde", "smallvec", "socket2", @@ -736,9 +725,9 @@ checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" [[package]] name = "owo-colors" -version = "4.3.0" +version = "4.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d211803b9b6b570f68772237e415a029d5a50c65d382910b879fb19d3271f94d" +checksum = "13c45bb4a6ae1280ec0803b1ef9d3455eb50f01efbbe1447ab020f1d54fba9d8" [[package]] name = "parking_lot" @@ -884,9 +873,9 @@ dependencies = [ [[package]] name = "rand" -version = "0.10.2" +version = "0.10.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7f5fa3a058cd35567ef9bfa5e75732bee0f9e4c55fa90477bef2dfcdbc4be80" +checksum = "65c9fb96cbc91e3478eaae79a69fcd3f1ae4ad052e471fe6732fff548984b4af" dependencies = [ "chacha20", "getrandom 0.4.3", @@ -929,13 +918,12 @@ dependencies = [ [[package]] name = "redox_users" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4e608c6638b9c18977b00b475ac1f28d14e84b27d8d42f70e0bf1e3dec127ac" +checksum = "60dc65c0ff1a7ae1294b0c67b9f14baf70b644404010370171787bfac1038fc0" dependencies = [ - "getrandom 0.2.17", "libredox", - "thiserror 2.0.20", + "thiserror 2.0.21", ] [[package]] @@ -1008,9 +996,9 @@ dependencies = [ [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ "bitflags", "errno", @@ -1068,7 +1056,7 @@ checksum = "e7a5d71263a5a7d47b41f6b3f06ba276f10cc18b0931f1799f710578e2309348" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1101,9 +1089,9 @@ checksum = "f8fadd59c855ef2080decdef8ff161eb6661b86933c9d82e5ba29dc602a55aba" [[package]] name = "siphasher" -version = "1.0.3" +version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ee5873ec9cce0195efcb7a4e9507a04cd49aec9c83d0389df45b1ef7ba2e649" +checksum = "33f4fe9184a62d842c9ef383018f3306d8ba224fd9d836f56d7288308847c256" [[package]] name = "slab" @@ -1113,9 +1101,9 @@ checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" [[package]] name = "smallvec" -version = "1.15.2" +version = "1.16.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ed6a63f02c8539c91a8685a86f4099661ba3da017932f6ebbea6de3f0fa7c90" +checksum = "f9395f0f0eee849a9b707b2f06bb92a6a422090e2123bb2ef8e87a0e61892a8e" [[package]] name = "socket2" @@ -1157,9 +1145,9 @@ dependencies = [ [[package]] name = "syn" -version = "3.0.3" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -1190,11 +1178,11 @@ dependencies = [ [[package]] name = "thiserror" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ec86235f5fcc2a73650310756d2ac5b138a5780bbbdfae3eeccec992c435ba4f" +checksum = "09e52cb86a36cede5cb101bf8908837b3e4c6e5e59fe7fd85c23fb56200d189e" dependencies = [ - "thiserror-impl 2.0.20", + "thiserror-impl 2.0.21", ] [[package]] @@ -1210,13 +1198,13 @@ dependencies = [ [[package]] name = "thiserror-impl" -version = "2.0.20" +version = "2.0.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bc04cd3e1236dd4a98afca4569f2deb3f120e5422a4023be2cb683f8486292af" +checksum = "fe5197923287db20a58125f0bc85c062f7f2c892de97b18c356f9efb14b28524" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn 3.0.6", ] [[package]] @@ -1303,9 +1291,9 @@ dependencies = [ [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "unicode-width" @@ -1321,9 +1309,9 @@ checksum = "81e544489bf3d8ef66c953931f56617f423cd4b5494be343d9b9d3dda037b9a3" [[package]] name = "uuid" -version = "1.25.0" +version = "1.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f053576934f05a761a402421fbbe3d425d9366f75f978806a037b3ca481abecc" +checksum = "2ef6dac1e96601b4fb3acccccff2139741fcb757cb9a36089bf5be91cfb285ce" dependencies = [ "getrandom 0.4.3", "js-sys", @@ -1353,9 +1341,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -1366,9 +1354,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -1376,22 +1364,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn 3.0.6", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] @@ -1540,18 +1528,18 @@ checksum = "1ebf944e87a7c253233ad6766e082e3cd714b5d03812acc24c318f549614536e" [[package]] name = "zerocopy" -version = "0.8.56" +version = "0.8.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "556764e583adb45a9f8d413c2a147fa7e8d821e48e12b14fd560b607998b75eb" +checksum = "6df92bf3d9227be3d53173901ddbffac2babc27ae50f397776ffd6dc33f800cb" dependencies = [ "zerocopy-derive", ] [[package]] name = "zerocopy-derive" -version = "0.8.56" +version = "0.8.59" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ab42fc20575779bd240faa45f94a74256f755c0fa9e89f0ede20d91d0cdfc1" +checksum = "ac4f328cf2f05d084e496c3e9c3f33ed0a183656a16e1fcec4d464d8373aec82" dependencies = [ "proc-macro2", "quote", diff --git a/src/tools/miri/tests/deps/Cargo.lock b/src/tools/miri/tests/deps/Cargo.lock index facfdee075bc4..7347118da591d 100644 --- a/src/tools/miri/tests/deps/Cargo.lock +++ b/src/tools/miri/tests/deps/Cargo.lock @@ -4,9 +4,9 @@ version = 4 [[package]] name = "bitflags" -version = "2.13.1" +version = "2.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b588b76d00fde79687d7646a9b5bdf3cc0f655e0bbd080335a95d7e96f3587da" +checksum = "3ded4057c258ba199e2d26386d3af3780957ecaee6c4ef4041c6b4b8b97c0b06" [[package]] name = "bumpalo" @@ -22,9 +22,9 @@ checksum = "fc652a48c352aef3ea3aed32080501cf3ef6ed5da78602a020c991775b0aff04" [[package]] name = "cfg-if" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" +checksum = "4e7648175b45a9a48536d676f68d918270699102aa8dab5496df06904c914600" [[package]] name = "cross-crate-items" @@ -93,7 +93,7 @@ checksum = "9fb9654ba8355388abeb8dcb4fc62f511300867002afc858860463bdd9fe0c44" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn", ] [[package]] @@ -171,15 +171,15 @@ dependencies = [ [[package]] name = "hermit-abi" -version = "0.5.2" +version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fc0fef456e4baa96da950455cd02c081ca953b141298e41db3fc7e36b1da849c" +checksum = "e17592d60ebacc7d5e169f4663c5f84f9161cc90328abcfe8456f41e4dfcb284" [[package]] name = "js-sys" -version = "0.3.104" +version = "0.3.106" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e0c1080212aad755ea003d18543e8768dd432c48819efd73a7bf1e39b7a5a3a" +checksum = "7883d941dae510fb2d978fc3fe018c71c9e2892fd38854de3e8b92c2e5ad9cc5" dependencies = [ "cfg-if", "futures-util", @@ -200,9 +200,9 @@ checksum = "32a66949e030da00e8c7d4434b251670a91556f4144941d37452769c25d58a53" [[package]] name = "mio" -version = "1.2.2" +version = "1.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30d65c71f1ce40ab09135ce117d742b9f8a19ff91a41a8b57ed50bc2de59c427" +checksum = "4b18443e9c262bfe8fa82f51666e2642c53393f7e5c27b3e1aeab922cff5b9d8" dependencies = [ "libc", "wasi 0.11.1+wasi-snapshot-preview1", @@ -290,9 +290,9 @@ checksum = "f8dcc9c7d52a811697d2151c701e0d08956f92b0e24136cf4cf27b57a6a0d9bf" [[package]] name = "rustix" -version = "1.1.4" +version = "1.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6fe4565b9518b83ef4f91bb47ce29620ca828bd32cb7e408f0062e9930ba190" +checksum = "891efababe418670775f199f0d233d84843c227a0949a883ce15b37c78d6629d" dependencies = [ "bitflags", "errno", @@ -335,20 +335,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.119" +version = "3.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "872831b642d1a07999a962a351ed35b955ea2cfc8f3862091e2a240a84f17297" -dependencies = [ - "proc-macro2", - "quote", - "unicode-ident", -] - -[[package]] -name = "syn" -version = "3.0.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3" +checksum = "8593e8e72159ed2257d083c7a454a85cbf854f37a0966d8d483aff8c8a3ebcee" dependencies = [ "proc-macro2", "quote", @@ -392,14 +381,14 @@ checksum = "78773a2a397f451582ce068015985c33193cf6dea8b74d2a639fe457b2f07b0e" dependencies = [ "proc-macro2", "quote", - "syn 3.0.3", + "syn", ] [[package]] name = "unicode-ident" -version = "1.0.24" +version = "1.0.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75" +checksum = "d245f478577f809a851594d02313b640fb437e0bb33866753cff937863096954" [[package]] name = "wasi" @@ -424,9 +413,9 @@ dependencies = [ [[package]] name = "wasm-bindgen" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1b70935747edd64d89de3efa29d73789b806c15798f8e7dca4d8ac356b50ce70" +checksum = "9bb54f33acc68fd454578d9820b0bde1a1a3d17aa17bb7b6595806d02886d409" dependencies = [ "cfg-if", "once_cell", @@ -437,9 +426,9 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77775f8f3f7217702089053b94958f8f54061a3f663417df76e19cbdcca29bc1" +checksum = "2e29d0c35b16e224a7eeb5cd2d25e3e1968fbd65604117b44d3b789d00ee8535" dependencies = [ "quote", "wasm-bindgen-macro-support", @@ -447,22 +436,22 @@ dependencies = [ [[package]] name = "wasm-bindgen-macro-support" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e11d33f857dc2fb11b8bc75aee111aa9cbeb12cd9f25efd3d4c2a3dd4e235284" +checksum = "6f501a8bc3719dba86ef8ae4728879c08001bea749eb1333ac5b91e040e2a6b7" dependencies = [ "bumpalo", "proc-macro2", "quote", - "syn 2.0.119", + "syn", "wasm-bindgen-shared", ] [[package]] name = "wasm-bindgen-shared" -version = "0.2.127" +version = "0.2.129" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7ef64dbcc55df09c7e5a46182d181c2cfa3e925f3da937ea764728b4bbb9dcbf" +checksum = "23f0c9c52aa7cd7d77769a4cfe2a9adb1b331f489a41d912ce14513d5ab995c6" dependencies = [ "unicode-ident", ] From d85a18bef9c79b4a4bef25d9044c8bd1b6ab1ab8 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Tue, 15 Sep 2026 02:31:59 +0900 Subject: [PATCH 1170/1309] Partially revert previous wrong fix and do some hack instead --- .../src/solve/fulfill.rs | 25 +++------ .../src/solve/fulfill/derive_errors.rs | 52 +++++++------------ ...ket-ambig-on-nonrigid-assoc-next-solver.rs | 23 ++++++++ 3 files changed, 48 insertions(+), 52 deletions(-) create mode 100644 tests/rustdoc-json/impls/blanket-ambig-on-nonrigid-assoc-next-solver.rs diff --git a/compiler/rustc_trait_selection/src/solve/fulfill.rs b/compiler/rustc_trait_selection/src/solve/fulfill.rs index 7d3c0a4a6c1f1..5e834c8c4059d 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill.rs @@ -18,7 +18,7 @@ use self::derive_errors::*; use super::Certainty; use super::delegate::SolverDelegate; use crate::error_reporting::InferCtxtErrorExt; -use crate::traits::{FulfillmentError, FulfillmentErrorCode, ScrubbedTraitError}; +use crate::traits::{FulfillmentError, ScrubbedTraitError}; mod derive_errors; @@ -157,8 +157,7 @@ where // the other case. TraitErrors::NoErrors } else { - let errors = collect_remaining_errors_impl(self, infcx); - TraitErrors::from_iter(errors.into_iter()) + TraitErrors::HasErrors(collect_remaining_errors_impl(self, infcx)) } } @@ -367,26 +366,14 @@ where cx.obligations .pending .drain(..) - .filter_map(|(obligation, _)| { - try_ambiguity_error_for_stalled(infcx, obligation).map(NextSolverError::Ambiguity) - }) + .map(|(obligation, _)| NextSolverError::Ambiguity(obligation)) .map(|e| E::from_solver_error(infcx, e)) .collect() } -// We evaluate stalled obligations while collecting remaining errors because a -// previously ambiguous goal may have become successful. In that case we emit a -// delayed bug instead of producing a fulfillment error. Store the diagnostic -// information here so error conversion does not reevaluate the goal. -pub struct NextSolverAmbiguityError<'tcx> { - root_obligation: PredicateObligation<'tcx>, - code: FulfillmentErrorCode<'tcx>, - refine_obligation: bool, -} - pub enum NextSolverError<'tcx> { TrueError(PredicateObligation<'tcx>), - Ambiguity(NextSolverAmbiguityError<'tcx>), + Ambiguity(PredicateObligation<'tcx>), } impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tcx> { @@ -395,8 +382,8 @@ impl<'tcx> FromSolverError<'tcx, NextSolverError<'tcx>> for FulfillmentError<'tc NextSolverError::TrueError(obligation) => { fulfillment_error_for_no_solution(infcx, obligation) } - NextSolverError::Ambiguity(ambiguity) => { - fulfillment_error_for_stalled(infcx, ambiguity) + NextSolverError::Ambiguity(obligation) => { + fulfillment_error_for_stalled(infcx, obligation) } } } diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs index 5ccd7ff7ef55b..7df3fa41a1df2 100644 --- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs +++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs @@ -14,7 +14,6 @@ use rustc_next_trait_solver::solve::{GoalEvaluation, MaybeInfo, SolverDelegateEv use rustc_span::{bug, span_bug}; use tracing::{instrument, trace}; -use super::NextSolverAmbiguityError; use crate::solve::delegate::SolverDelegate; use crate::solve::inspect::{self, InferCtxtProofTreeExt, ProofTreeVisitor}; use crate::solve::{Certainty, deeply_normalize_for_diagnostics}; @@ -84,25 +83,10 @@ pub(super) fn fulfillment_error_for_no_solution<'tcx>( } pub(super) fn fulfillment_error_for_stalled<'tcx>( - infcx: &InferCtxt<'tcx>, - ambiguity: NextSolverAmbiguityError<'tcx>, -) -> FulfillmentError<'tcx> { - let NextSolverAmbiguityError { root_obligation, code, refine_obligation } = ambiguity; - - let obligation = if refine_obligation { - find_best_leaf_obligation(infcx, &root_obligation, true) - } else { - root_obligation.clone() - }; - - FulfillmentError { obligation, code, root_obligation } -} - -pub(super) fn try_ambiguity_error_for_stalled<'tcx>( infcx: &InferCtxt<'tcx>, root_obligation: PredicateObligation<'tcx>, -) -> Option> { - let evaluation = infcx.probe(|_| { +) -> FulfillmentError<'tcx> { + let (code, refine_obligation) = infcx.probe(|_| { match <&SolverDelegate<'tcx>>::from(infcx).evaluate_root_goal( root_obligation.as_goal(), root_obligation.cause.span, @@ -116,7 +100,7 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( stalled_on_coroutines: _, }), .. - }) => Some((FulfillmentErrorCode::Ambiguity { overflow: None }, true)), + }) => (FulfillmentErrorCode::Ambiguity { overflow: None }, true), Ok(GoalEvaluation { certainty: Certainty::Maybe(MaybeInfo { @@ -126,7 +110,7 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( stalled_on_coroutines: _, }), .. - }) => Some(( + }) => ( FulfillmentErrorCode::Ambiguity { overflow: Some(suggest_increasing_limit) }, // Don't look into overflows because we treat overflows weirdly anyways. // We discard the inference constraints from overflowing goals, so @@ -135,17 +119,13 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( // // FIXME: We should probably just look into overflows here. false, - )), + ), Ok(GoalEvaluation { certainty: Certainty::Yes, .. }) => { - infcx.dcx().span_delayed_bug( - root_obligation.cause.span, - format!( - "did not expect successful goal when collecting ambiguity errors for `{:?}`", - infcx.deeply_resolve_ignoring_regions(root_obligation.predicate), - ), - ); - None - }, + // FIXME: We should ICE here. See the following links for details + // - + // - + (FulfillmentErrorCode::Ambiguity { overflow: None }, false) + } Err(_) => { span_bug!( root_obligation.cause.span, @@ -156,9 +136,15 @@ pub(super) fn try_ambiguity_error_for_stalled<'tcx>( } }); - let (code, refine_obligation) = evaluation?; - - Some(NextSolverAmbiguityError { root_obligation, code, refine_obligation }) + FulfillmentError { + obligation: if refine_obligation { + find_best_leaf_obligation(infcx, &root_obligation, true) + } else { + root_obligation.clone() + }, + code, + root_obligation, + } } #[instrument(level = "debug", skip(infcx), ret)] diff --git a/tests/rustdoc-json/impls/blanket-ambig-on-nonrigid-assoc-next-solver.rs b/tests/rustdoc-json/impls/blanket-ambig-on-nonrigid-assoc-next-solver.rs new file mode 100644 index 0000000000000..8f3af90a2598e --- /dev/null +++ b/tests/rustdoc-json/impls/blanket-ambig-on-nonrigid-assoc-next-solver.rs @@ -0,0 +1,23 @@ +//@ compile-flags: -Znext-solver + +// Regression test for + +pub trait Service { + type Future; +} + +pub trait ZebraService: Service {} + +impl ZebraService for MaybeVerify where + MaybeVerify: Service +{ +} + +pub struct Verifier; + +impl Service<()> for Verifier { + type Future = &'static (); +} + +//@ set blanket = "$.index[?(@.inner.impl.blanket_impl.generic=='MaybeVerify')].id" +//@ has "$.index[?(@.name=='Verifier')].inner.struct.impls[*]" $blanket From 3510be9a06e2eedb5be9a3cf7af10d646953bb04 Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 2 Oct 2026 07:45:10 +0000 Subject: [PATCH 1171/1309] Revert "doc: Fix external mention of signum() return value regarding NaNs" This reverts commit 88db34ad12223f211786050877bb6005cfcaa1e6. --- library/core/src/num/f128.rs | 4 ++-- library/core/src/num/f16.rs | 4 ++-- library/core/src/num/f32.rs | 4 ++-- library/core/src/num/f64.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index e53e4df1ea43d..d490ccd26f8e4 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -594,7 +594,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -620,7 +620,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f128)] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 4ad41bd6cfa4b..3d13c2016e9a8 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -588,7 +588,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -616,7 +616,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// #![feature(f16)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index 2dc3ddf31cac5..f48127df6ce9b 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -811,7 +811,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f32; @@ -836,7 +836,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index cd3cfe1bd4c60..0e02b1f912dcd 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -810,7 +810,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -835,7 +835,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return NaN for all NaNs). + /// if you need fully portable behavior (will return `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; From 5ec3896697c0be2d8f3dc029bab953777022829b Mon Sep 17 00:00:00 2001 From: Alice Ryhl Date: Fri, 2 Oct 2026 07:48:36 +0000 Subject: [PATCH 1172/1309] Use 'evaluates to' wording --- library/core/src/num/f128.rs | 4 ++-- library/core/src/num/f16.rs | 4 ++-- library/core/src/num/f32.rs | 4 ++-- library/core/src/num/f64.rs | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/f128.rs b/library/core/src/num/f128.rs index d490ccd26f8e4..b0b4dcda72a49 100644 --- a/library/core/src/num/f128.rs +++ b/library/core/src/num/f128.rs @@ -594,7 +594,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// #![feature(f128)] @@ -620,7 +620,7 @@ impl f128 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// #![feature(f128)] diff --git a/library/core/src/num/f16.rs b/library/core/src/num/f16.rs index 3d13c2016e9a8..8dff40dd77117 100644 --- a/library/core/src/num/f16.rs +++ b/library/core/src/num/f16.rs @@ -588,7 +588,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// #![feature(f16)] @@ -616,7 +616,7 @@ impl f16 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// #![feature(f16)] diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs index f48127df6ce9b..0a384a18cab41 100644 --- a/library/core/src/num/f32.rs +++ b/library/core/src/num/f32.rs @@ -811,7 +811,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// let f = 7.0_f32; @@ -836,7 +836,7 @@ impl f32 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// let f = 7.0f32; diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs index 0e02b1f912dcd..cc694d332b6a3 100644 --- a/library/core/src/num/f64.rs +++ b/library/core/src/num/f64.rs @@ -810,7 +810,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_positive` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == 1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; @@ -835,7 +835,7 @@ impl f64 { /// conserved over arithmetic operations, the result of `is_sign_negative` on /// a NaN might produce an unexpected or non-portable result. See the [specification /// of NaN bit patterns](f32#nan-bit-patterns) for more info. Use `self.signum() == -1.0` - /// if you need fully portable behavior (will return `false` for all NaNs). + /// if you need fully portable behavior (evaluates to `false` for all NaNs). /// /// ``` /// let f = 7.0_f64; From ee2a5dfe24b64c06dd2f2be31431822ac3f89860 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 2 Oct 2026 10:02:49 +0200 Subject: [PATCH 1173/1309] avoid trivial `fn map_bound` validations --- compiler/rustc_middle/src/ty/predicate.rs | 5 +++-- compiler/rustc_type_ir/src/binder.rs | 12 ++++++++++++ compiler/rustc_type_ir/src/inherent.rs | 18 +++++++++--------- compiler/rustc_type_ir/src/predicate.rs | 7 +++++-- 4 files changed, 29 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index 983293e81e5f9..b82fe2ac0e5ee 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -171,7 +171,7 @@ impl<'tcx> Clause<'tcx> { } pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> { - self.0.internee.map_bound(|kind| match kind { + self.0.internee.map_bound_no_validate_bound_vars(|kind| match kind { PredicateKind::Clause(clause) => clause, _ => unreachable!(), }) @@ -520,7 +520,8 @@ impl<'tcx> UpcastFrom, TraitClause<'tcx>> for Predicate<'tcx> { impl<'tcx> UpcastFrom, PolyTraitClause<'tcx>> for Predicate<'tcx> { fn upcast_from(from: PolyTraitClause<'tcx>, tcx: TyCtxt<'tcx>) -> Self { - from.map_bound(|p| PredicateKind::Clause(ClauseKind::Trait(p))).upcast(tcx) + from.map_bound_no_validate_bound_vars(|p| PredicateKind::Clause(ClauseKind::Trait(p))) + .upcast(tcx) } } diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index 6722adfe24d5d..7f88ad0b2d9c2 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -149,6 +149,18 @@ impl Binder { Binder { value, bound_vars } } + /// There are some uses of `map_bound` which are incredibly hot and trivially + /// correct. Only use this if this significantly improves the performance of + /// builds with debug assertions. + pub fn map_bound_no_validate_bound_vars>(self, f: F) -> Binder + where + F: FnOnce(T) -> U, + { + let Binder { value, bound_vars } = self; + let value = f(value); + Binder { value, bound_vars } + } + pub fn try_map_bound, E>(self, f: F) -> Result, E> where F: FnOnce(T) -> Result, diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index 28b733a865358..cb68b8032f7e1 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -490,25 +490,25 @@ pub trait Clause>: fn as_trait_clause(self) -> Option>> { self.kind() - .map_bound(|clause| if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None }) + .map_bound_no_validate_bound_vars(|clause| { + if let ty::ClauseKind::Trait(t) = clause { Some(t) } else { None } + }) .transpose() } fn as_host_effect_clause(self) -> Option>> { self.kind() - .map_bound( - |clause| if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None }, - ) + .map_bound_no_validate_bound_vars(|clause| { + if let ty::ClauseKind::HostEffect(t) = clause { Some(t) } else { None } + }) .transpose() } fn as_projection_clause(self) -> Option>> { self.kind() - .map_bound( - |clause| { - if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None } - }, - ) + .map_bound_no_validate_bound_vars(|clause| { + if let ty::ClauseKind::Projection(p) = clause { Some(p) } else { None } + }) .transpose() } diff --git a/compiler/rustc_type_ir/src/predicate.rs b/compiler/rustc_type_ir/src/predicate.rs index e66ef5fe99b4a..0ce9d68d88b4d 100644 --- a/compiler/rustc_type_ir/src/predicate.rs +++ b/compiler/rustc_type_ir/src/predicate.rs @@ -231,7 +231,7 @@ impl ty::Binder> { } pub fn self_ty(self) -> ty::Binder { - self.map_bound(|trait_ref| trait_ref.self_ty()) + self.map_bound_no_validate_bound_vars(|trait_ref| trait_ref.self_ty()) } #[inline] @@ -248,7 +248,10 @@ impl UpcastFrom> for TraitClause { impl UpcastFrom>> for ty::Binder> { fn upcast_from(from: ty::Binder>, _tcx: I) -> Self { - from.map_bound(|trait_ref| TraitClause { trait_ref, polarity: ClausePolarity::Positive }) + from.map_bound_no_validate_bound_vars(|trait_ref| TraitClause { + trait_ref, + polarity: ClausePolarity::Positive, + }) } } From 9270acb1bfd9b1b974ebcf92d0cb198622880a79 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Thu, 1 Oct 2026 02:07:58 +0000 Subject: [PATCH 1174/1309] Fix `TypeOutlives` fast-path --- compiler/rustc_trait_selection/src/solve/delegate.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e1043d53fa6fc..dcfd21297dc76 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -229,6 +229,10 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< } let ty = self.deeply_resolve_ignoring_regions(outlives.0); + if ty.has_non_rigid_aliases() { + return Outcome::NoFastPath; + } + let mut infer_collector = CollectNonRegionInfer { infers: Default::default(), visited: Default::default(), @@ -247,10 +251,6 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< ); } - if ty.has_non_rigid_aliases() { - return Outcome::NoFastPath; - } - self.0.register_type_outlives_constraint( outlives.0, outlives.1, From eb4108a9859ebfa071a57b9f7e90cc8815311996 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 11:47:13 +0200 Subject: [PATCH 1175/1309] Add mailmap entry --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index d72c2e39c26a3..33000e11dcefa 100644 --- a/.mailmap +++ b/.mailmap @@ -64,6 +64,7 @@ Arthur Cohen Arthur Silva Arthur Woimbée Artyom Pavlov +Austin K. Austin Seipp Ayaz Hafiz Aydin Kim aydin.kim From c39fbc44eb0f296a7ad161eee642e8bcd2a82235 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandra=20Gonz=C3=A1lez?= Date: Fri, 2 Oct 2026 12:00:55 +0200 Subject: [PATCH 1176/1309] Rename `rustc_driver::run_compiler` to `compiler_entrypoint` Having two `run_compiler` functions has always been confusing and not necessary at all, as they perform fairly different functions. Even more so because `rustc_driver::run_compiler` calls to `rustc_interface::run_compiler`. So it seems like a recursive function when it really isn't. --- compiler/rustc_driver_impl/src/lib.rs | 6 +++--- compiler/rustc_public/src/rustc_internal/mod.rs | 2 +- src/doc/rustc-dev-guide/examples/rustc-driver-example.rs | 4 ++-- .../examples/rustc-driver-interacting-with-the-ast.rs | 4 ++-- src/doc/rustc-dev-guide/src/compiler-debugging.md | 6 +++--- src/doc/rustc-dev-guide/src/rustc-driver/intro.md | 8 ++++---- src/tools/clippy/src/driver.rs | 6 +++--- src/tools/miri/priroda/src/main.rs | 2 +- src/tools/miri/src/bin/miri.rs | 2 +- tests/ui-fulldeps/compiler-calls.rs | 2 +- tests/ui-fulldeps/obtain-borrowck.rs | 2 +- tests/ui-fulldeps/polymorphic-drop-glue.rs | 2 +- 12 files changed, 23 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 7940dc3978496..959222b19c6e9 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -169,7 +169,7 @@ impl Callbacks for TimePassesCallbacks { } /// This is the primary entry point for rustc. -pub fn run_compiler(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) { +pub fn compiler_entrypoint(at_args: &[String], callbacks: &mut (dyn Callbacks + Send)) { let mut default_early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // Throw away the first argument, the name of the binary. @@ -1386,7 +1386,7 @@ static ICE_PATH: OnceLock> = OnceLock::new(); // This function should only be called from the ICE hook. // -// The intended behavior is that `run_compiler` will invoke `ice_path_with_config` early in the +// The intended behavior is that `compiler_entrypoint` will invoke `ice_path_with_config` early in the // initialization process to properly initialize the ICE_PATH static based on parsed CLI flags. // // Subsequent calls to either function will then return the proper ICE path as configured by @@ -1674,7 +1674,7 @@ pub fn main() -> ExitCode { install_ctrlc_handler(); let exit_code = - catch_with_exit_code(|| run_compiler(&args::raw_args(&early_dcx), &mut callbacks)); + catch_with_exit_code(|| compiler_entrypoint(&args::raw_args(&early_dcx), &mut callbacks)); if let Some(format) = callbacks.time_passes { let end_rss = get_resident_set_size(); diff --git a/compiler/rustc_public/src/rustc_internal/mod.rs b/compiler/rustc_public/src/rustc_internal/mod.rs index 49dc64572923a..744aa1ffdd314 100644 --- a/compiler/rustc_public/src/rustc_internal/mod.rs +++ b/compiler/rustc_public/src/rustc_internal/mod.rs @@ -168,7 +168,7 @@ macro_rules! optional { #[doc(hidden)] macro_rules! run_driver { ($args:expr, $callback:expr $(, $with_tcx:ident)?) => {{ - use rustc_driver::{Callbacks, Compilation, run_compiler}; + use rustc_driver::{Callbacks, Compilation, compiler_entrypoint}; use rustc_middle::ty::TyCtxt; use rustc_interface::interface; use rustc_public::rustc_internal; diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs index db6ac18578542..55665220c5f89 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-example.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{Compilation, run_compiler}; +use rustc_driver::{Compilation, compiler_entrypoint}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; @@ -87,7 +87,7 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn main() { - run_compiler( + compile_entrypoint( &[ // The first argument, which in practice contains the name of the binary being executed // (i.e. "rustc") is ignored by rustc. diff --git a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs index c0d7f977d3500..f3449e830c9b7 100644 --- a/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs +++ b/src/doc/rustc-dev-guide/examples/rustc-driver-interacting-with-the-ast.rs @@ -20,7 +20,7 @@ use std::path::Path; use std::sync::Arc; use rustc_ast_pretty::pprust::item_to_string; -use rustc_driver::{Compilation, run_compiler}; +use rustc_driver::{Compilation, compiler_entrypoint}; use rustc_interface::interface::{Compiler, Config}; use rustc_middle::ty::TyCtxt; @@ -94,7 +94,7 @@ impl rustc_driver::Callbacks for MyCallbacks { } fn main() { - run_compiler( + compiler_entrypoint( &[ // The first argument, which in practice contains the name of the binary being executed // (i.e. "rustc") is ignored by rustc. diff --git a/src/doc/rustc-dev-guide/src/compiler-debugging.md b/src/doc/rustc-dev-guide/src/compiler-debugging.md index 79f2145afce1b..3c355c0d3b972 100644 --- a/src/doc/rustc-dev-guide/src/compiler-debugging.md +++ b/src/doc/rustc-dev-guide/src/compiler-debugging.md @@ -75,7 +75,7 @@ stack backtrace: 34: >::with 35: rustc::ty::context::TyCtxt::create_and_enter 36: rustc_driver::driver::compile_input - 37: rustc_driver::run_compiler + 37: rustc_driver::compiler_entrypoint ``` If you set `debug = true`, you will get line numbers for the stack trace. @@ -93,7 +93,7 @@ stack backtrace: 33: rustc_driver::driver::compile_input at /home/user/rust/compiler/rustc_driver/src/driver.rs:1010 at /home/user/rust/compiler/rustc_driver/src/driver.rs:212 - 34: rustc_driver::run_compiler + 34: rustc_driver::compiler_entrypoint at /home/user/rust/compiler/rustc_driver/src/lib.rs:253 ``` @@ -181,7 +181,7 @@ stack backtrace: 9: rustc_typeck::check::FnCtxt::select_obligations_where_possible at /home/user/rust/compiler/rustc_typeck/src/check/mod.rs:2192 (~~~ IRRELEVANT PART OF BACKTRACE REMOVED BY ME ~~~) - 36: rustc_driver::run_compiler + 36: rustc_driver::compiler_entrypoint at /home/user/rust/compiler/rustc_driver/src/lib.rs:253 ``` diff --git a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md index 32d27d218197d..687b2d49d094a 100644 --- a/src/doc/rustc-dev-guide/src/rustc-driver/intro.md +++ b/src/doc/rustc-dev-guide/src/rustc-driver/intro.md @@ -6,7 +6,7 @@ The [`rustc_driver`] is essentially `rustc`'s `main` function. It acts as the glue for running the various phases of the compiler in the correct order, using the interface defined in the [`rustc_interface`] crate. Where possible, using [`rustc_driver`] rather than [`rustc_interface`] is recommended. -The main entry point of [`rustc_driver`] is [`rustc_driver::run_compiler`][rd_rc]. +The main entry point of [`rustc_driver`] is [`rustc_driver::compiler_entrypoint`][rd_ce]. This builder accepts the same command-line args as rustc as well as an implementation of [`Callbacks`] and a couple of other optional options. [`Callbacks`] is a `trait` that allows for custom compiler configuration, as well as allowing custom code to run after different phases of the compilation. @@ -23,7 +23,7 @@ Inside the `closure` you can use the `Compiler` to call various functions to com You can see a minimal example of how to use [`rustc_interface`] [here][example]. You can see an example of how to use the various functions using [`rustc_interface`] needs by looking at the `rustc_driver` implementation, -specifically [`rustc_driver_impl::run_compiler`][rdi_rc] +specifically [`rustc_driver_impl::compiler_entrypoint`][rdi_ce] (not to be confused with [`rustc_interface::run_compiler`][i_rc]). > **Warning:** By its very nature, the internal compiler APIs are always going @@ -36,5 +36,5 @@ specifically [`rustc_driver_impl::run_compiler`][rdi_rc] [`Callbacks`]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/trait.Callbacks.html [example]: https://github.com/rust-lang/rustc-dev-guide/blob/main/examples/rustc-interface-example.rs [i_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_interface/interface/fn.run_compiler.html -[rd_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.run_compiler.html -[rdi_rc]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.run_compiler.html +[rd_ce]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver/fn.compiler_entrypoint.html +[rdi_ce]: https://doc.rust-lang.org/nightly/nightly-rustc/rustc_driver_impl/fn.compiler_entrypoint.html diff --git a/src/tools/clippy/src/driver.rs b/src/tools/clippy/src/driver.rs index 16c3a6434f35a..e83fe592a7ca6 100644 --- a/src/tools/clippy/src/driver.rs +++ b/src/tools/clippy/src/driver.rs @@ -243,7 +243,7 @@ fn main() -> ExitCode { let mut args: Vec = orig_args.clone(); pass_sysroot_env_if_given(&mut args, sys_root_env); - rustc_driver::run_compiler(&args, &mut DefaultCallbacks); + rustc_driver::compiler_entrypoint(&args, &mut DefaultCallbacks); return ExitCode::SUCCESS; } @@ -304,9 +304,9 @@ fn main() -> ExitCode { let clippy_enabled = !cap_lints_allow && relevant_package && !info_query; if clippy_enabled { args.extend(clippy_args); - rustc_driver::run_compiler(&args, &mut ClippyCallbacks { clippy_args_var }); + rustc_driver::compiler_entrypoint(&args, &mut ClippyCallbacks { clippy_args_var }); } else { - rustc_driver::run_compiler(&args, &mut RustcCallbacks { clippy_args_var }); + rustc_driver::compiler_entrypoint(&args, &mut RustcCallbacks { clippy_args_var }); } ExitCode::SUCCESS }) diff --git a/src/tools/miri/priroda/src/main.rs b/src/tools/miri/priroda/src/main.rs index 3937b9ad03f4d..6fc62b4d6e04b 100644 --- a/src/tools/miri/priroda/src/main.rs +++ b/src/tools/miri/priroda/src/main.rs @@ -41,7 +41,7 @@ fn main() { args.push(find_sysroot()); } // FIXME: handle the same `-Z` flags that Miri accepts. - rustc_driver::run_compiler(&args, &mut PrirodaCompilerCalls::new(frontend)); + rustc_driver::compiler_entrypoint(&args, &mut PrirodaCompilerCalls::new(frontend)); } /// Frontend selected by Priroda-specific CLI flags. diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 7b3f166b3bf87..7c5bda3d628ce 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -366,7 +366,7 @@ fn run_compiler_and_exit( // Invoke compiler, catch any unwinding panics and handle return code. let exit_code = - rustc_driver::catch_with_exit_code(move || rustc_driver::run_compiler(args, callbacks)); + rustc_driver::catch_with_exit_code(move || rustc_driver::compiler_entrypoint(args, callbacks)); exit(if exit_code == ExitCode::SUCCESS { rustc_driver::EXIT_SUCCESS } else { diff --git a/tests/ui-fulldeps/compiler-calls.rs b/tests/ui-fulldeps/compiler-calls.rs index d6148dfec43ce..ea91f23213e1c 100644 --- a/tests/ui-fulldeps/compiler-calls.rs +++ b/tests/ui-fulldeps/compiler-calls.rs @@ -25,7 +25,7 @@ fn main() { let mut count = 1; let args = vec!["compiler-calls".to_string(), "foo.rs".to_string()]; rustc_driver::catch_fatal_errors(|| -> interface::Result<()> { - rustc_driver::run_compiler(&args, &mut TestCalls { count: &mut count }); + rustc_driver::compiler_entrypoint(&args, &mut TestCalls { count: &mut count }); Ok(()) }) .ok(); diff --git a/tests/ui-fulldeps/obtain-borrowck.rs b/tests/ui-fulldeps/obtain-borrowck.rs index d4a74d3b7dec8..950770d91fad1 100644 --- a/tests/ui-fulldeps/obtain-borrowck.rs +++ b/tests/ui-fulldeps/obtain-borrowck.rs @@ -50,7 +50,7 @@ fn main() -> ExitCode { rustc_args.push("-Zpolonius".to_owned()); let mut callbacks = CompilerCalls::default(); // Call the Rust compiler with our callbacks. - rustc_driver::run_compiler(&rustc_args, &mut callbacks); + rustc_driver::compiler_entrypoint(&rustc_args, &mut callbacks); }) } diff --git a/tests/ui-fulldeps/polymorphic-drop-glue.rs b/tests/ui-fulldeps/polymorphic-drop-glue.rs index 4d85d342d7395..a3ad05ef228e3 100644 --- a/tests/ui-fulldeps/polymorphic-drop-glue.rs +++ b/tests/ui-fulldeps/polymorphic-drop-glue.rs @@ -44,7 +44,7 @@ fn main() -> ExitCode { args.push("--crate-type=lib".to_owned()); args.push("drop_glue_polymorphic_const_generic_input.rs".to_owned()); - rustc_driver::run_compiler(&args, &mut CompilerCalls); + rustc_driver::compiler_entrypoint(&args, &mut CompilerCalls); }) } From 70ed6c35211dd1d39391403394322097346d0136 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Fri, 2 Oct 2026 12:01:08 +0200 Subject: [PATCH 1177/1309] Get `inputs_hir` directly from `decl` --- compiler/rustc_hir_typeck/src/check.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 4f6345e04070b..6fb75d0e182a4 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -63,7 +63,6 @@ pub(super) fn check_fn<'a, 'tcx>( }); // Add formal parameters. - let inputs_hir = tcx.hir_fn_decl_by_hir_id(fn_id).map(|decl| &decl.inputs); let inputs_fn = fn_sig.inputs().iter().copied(); for (idx, (param_ty, param)) in inputs_fn.chain(maybe_va_list).zip(body.params).enumerate() { // We checked the root's signature during wfcheck, but not the child. @@ -79,7 +78,7 @@ pub(super) fn check_fn<'a, 'tcx>( } // Check the pattern. - let ty: Option<&hir::Ty<'_>> = inputs_hir.and_then(|h| h.get(idx)); + let ty: Option<&hir::Ty<'_>> = decl.inputs.get(idx); let ty_span = ty.map(|ty| ty.span); fcx.check_pat_top(param.pat, param_ty, ty_span, None, None); if param.pat.is_never_pattern() { From d3c88b49c24f2506037e1099b80d6b61b2fcec41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 12:21:11 +0200 Subject: [PATCH 1178/1309] Add warning about debug assertions --- src/bootstrap/src/core/build_steps/test.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 479e517038597..4ea824525e1fc 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -4530,7 +4530,13 @@ impl CommandLineStep for CodegenGCC { let gcc = builder.ensure(Gcc { target_pair: GccTargetPair::for_native_build(target) }); - // We need to run the cg_gcc tests with the compiler against it links to, not with + if builder.config.rustc_debug_assertions { + eprintln!( + "WARNING: cg_gcc tests will likely fail when debug assertions are enabled for rustc" + ); + } + + // We need to run the cg_gcc tests with the compiler which it links against, not with // the build compiler. let target_compiler = compilers.target_compiler(); From 4b9666a948c7f1fbd406eb7817edb96479494dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 12:53:38 +0200 Subject: [PATCH 1179/1309] Rename `LLVM_PGO_CRATES` to `BACKEND_PGO_CRATES` --- src/bootstrap/src/core/build_steps/dist.rs | 6 ++++-- src/build_helper/src/lib.rs | 4 ++-- src/tools/opt-dist/src/training.rs | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 7073b334c414d..4f9c8ecd6c304 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1400,8 +1400,10 @@ fn prepare_source_tarball<'a>( builder.require_and_update_all_submodules(); // Vendor packages that are required by opt-dist to collect PGO profiles. - let pkgs_for_pgo_training = - build_helper::LLVM_PGO_CRATES.iter().chain(build_helper::RUSTC_PGO_CRATES).map(|pkg| { + let pkgs_for_pgo_training = build_helper::BACKEND_PGO_CRATES + .iter() + .chain(build_helper::RUSTC_PGO_CRATES) + .map(|pkg| { let mut manifest_path = builder.src.join("./src/tools/rustc-perf/collector/compile-benchmarks"); manifest_path.push(pkg); diff --git a/src/build_helper/src/lib.rs b/src/build_helper/src/lib.rs index e23a158ac0598..493ff92fbdbc3 100644 --- a/src/build_helper/src/lib.rs +++ b/src/build_helper/src/lib.rs @@ -11,8 +11,8 @@ pub mod stage0_parser; pub mod targets; pub mod util; -/// The default set of crates for opt-dist to collect LLVM profiles. -pub const LLVM_PGO_CRATES: &[&str] = &[ +/// The default set of crates for opt-dist to collect backend (LLVM, Cranelift) profiles. +pub const BACKEND_PGO_CRATES: &[&str] = &[ "syn-2.0.101", "cargo-0.87.1", "serde-1.0.219", diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index b8d54dc3ecac1..df5c1ff3c49d4 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -1,5 +1,5 @@ use anyhow::Context; -use build_helper::{LLVM_PGO_CRATES, RUSTC_PGO_CRATES}; +use build_helper::{BACKEND_PGO_CRATES, RUSTC_PGO_CRATES}; use camino::{Utf8Path, Utf8PathBuf}; use humansize::BINARY; @@ -109,6 +109,7 @@ fn log_profile_stats( pub fn llvm_benchmarks(env: &Environment) -> CmdBuilder { init_compiler_benchmarks(env, &["Debug", "Opt"], &["Full"], LLVM_PGO_CRATES) + init_compiler_benchmarks(env, &["Debug", "Opt"], &["Full"], BACKEND_PGO_CRATES) } // Here we're profiling the `rustc` frontend, so we also include `Check`. From ef2ad40c3e880772d2b6f80279ebd871bb6dbaec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 12:54:37 +0200 Subject: [PATCH 1180/1309] Add PGO config for Cranelift --- bootstrap.example.toml | 5 +++++ src/bootstrap/src/core/build_steps/compile.rs | 1 + src/bootstrap/src/core/build_steps/dist.rs | 1 + src/bootstrap/src/core/config/config.rs | 6 ++++++ src/bootstrap/src/core/config/toml/pgo.rs | 1 + 5 files changed, 14 insertions(+) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 7f4aac63f36a8..34ff4eb623917 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -1038,6 +1038,11 @@ # Instrument LLVM, so that when executed, it will gather profiles # Note: for LLVM specifically, this should be a directory, not a file path. #pgo.llvm.generate = "/tmp/profiles" +# Use the following profile to PGO optimize the Cranelift codegen backend. +#pgo.cranelift.use = "/tmp/profiles/foo.profraw" +# Instrument the Cranelift codegen backend, so that when executed, it will gather profiles +# to this path. +#pgo.cranelift.generate = "/tmp/profiles/foo.profraw" # ============================================================================= # Options for specific targets diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs index 97e7280da1e37..71121c1bfa865 100644 --- a/src/bootstrap/src/core/build_steps/compile.rs +++ b/src/bootstrap/src/core/build_steps/compile.rs @@ -1796,6 +1796,7 @@ impl CommandLineStep for CraneliftCodegenBackend { .arg("--manifest-path") .arg(builder.src.join("compiler/rustc_codegen_cranelift/Cargo.toml")); apply_dylib_lto(builder, &build_compiler, &mut cargo); + apply_pgo(builder, &mut cargo, build_compiler, &builder.config.cranelift_pgo); let _guard = builder.msg( Kind::Build, diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 4f9c8ecd6c304..7769670f60d44 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -3143,6 +3143,7 @@ impl CommandLineStep for ReproducibleArtifacts { &builder.config.rustdoc_pgo.use_profile, &builder.config.cargo_pgo.use_profile, &builder.config.clippy_pgo.use_profile, + &builder.config.cranelift_pgo.use_profile, ]; for profile in pgo_profiles { if let Some(path) = profile.as_ref() { diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs index f8b00094a0f4b..1e58d86024874 100644 --- a/src/bootstrap/src/core/config/config.rs +++ b/src/bootstrap/src/core/config/config.rs @@ -229,10 +229,13 @@ pub(crate) struct Config { pub rust_break_on_ice: bool, pub rust_parallel_frontend_threads: Option, pub rust_rustflags: Vec, + + // Note: modify the ReproducibleArtifacts step when adding new PGO configs here! pub rust_pgo: PgoConfig, pub rustdoc_pgo: PgoConfig, pub cargo_pgo: PgoConfig, pub clippy_pgo: PgoConfig, + pub cranelift_pgo: PgoConfig, pub stdlib_semver_baseline: Option, @@ -675,6 +678,7 @@ impl Config { rustdoc: pgo_rustdoc, cargo: pgo_cargo, clippy: pgo_clippy, + cranelift: pgo_cranelift, llvm: pgo_llvm, } = toml_pgo.unwrap_or_default(); @@ -732,6 +736,7 @@ impl Config { let pgo_rustdoc = init_pgo(pgo_rustdoc, "rustdoc"); let pgo_cargo = init_pgo(pgo_cargo, "cargo"); let pgo_clippy = init_pgo(pgo_clippy, "clippy"); + let pgo_cranelift = init_pgo(pgo_cranelift, "cranelift"); let bootstrap_override_lld = rust_bootstrap_override_lld.unwrap_or_default(); @@ -1426,6 +1431,7 @@ NOTE: Please add `--stage 2` to your command line, or if you're sure you want to compiletest_diff_tool: build_compiletest_diff_tool, config: toml_path, control_flow_guard: rust_control_flow_guard.unwrap_or(false), + cranelift_pgo: pgo_cranelift, datadir: install_datadir.map(PathBuf::from), deny_warnings, description: build_description, diff --git a/src/bootstrap/src/core/config/toml/pgo.rs b/src/bootstrap/src/core/config/toml/pgo.rs index befe589f192d3..0d69afdd13077 100644 --- a/src/bootstrap/src/core/config/toml/pgo.rs +++ b/src/bootstrap/src/core/config/toml/pgo.rs @@ -28,5 +28,6 @@ define_config! { cargo: Option = "cargo", clippy: Option = "clippy", llvm: Option = "llvm", + cranelift: Option = "cranelift", } } From 1df951222fb82dcaf964f57c2458fd7315eca59d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 12:54:53 +0200 Subject: [PATCH 1181/1309] PGO optimize Cranelift in `opt-dist` --- src/tools/opt-dist/src/exec.rs | 24 +++++++++++++++++++++++- src/tools/opt-dist/src/main.rs | 28 +++++++++++++++++++++++----- src/tools/opt-dist/src/training.rs | 17 ++++++++++++++++- 3 files changed, 62 insertions(+), 7 deletions(-) diff --git a/src/tools/opt-dist/src/exec.rs b/src/tools/opt-dist/src/exec.rs index d8ae5b49065b9..bd91e66c16423 100644 --- a/src/tools/opt-dist/src/exec.rs +++ b/src/tools/opt-dist/src/exec.rs @@ -8,7 +8,8 @@ use crate::environment::Environment; use crate::metrics::{load_metrics, record_metrics}; use crate::timer::TimerSection; use crate::training::{ - BoltProfile, ClippyPGOProfile, LlvmPGOProfile, RustcPGOProfile, RustdocPGOProfile, + BoltProfile, ClippyPGOProfile, CraneliftPGOProfile, LlvmPGOProfile, RustcPGOProfile, + RustdocPGOProfile, }; use crate::utils::io::normalize_path; @@ -136,6 +137,11 @@ impl Bootstrap { self } + pub fn with_cranelift(mut self) -> Self { + self.cmd = self.cmd.arg("rustc_codegen_cranelift"); + self + } + pub fn dist(env: &Environment, dist_args: &[String]) -> Self { let metrics_path = env.build_root().join("metrics.json"); let args = dist_args.iter().map(|arg| arg.as_str()).collect::>(); @@ -241,6 +247,22 @@ impl Bootstrap { self } + pub fn cranelift_pgo_instrument(mut self, profile_dir: &Utf8Path) -> Self { + self.cmd = self + .cmd + .arg("--set") + .arg(format!(r#"pgo.cranelift.generate="{}""#, normalize_path(profile_dir).as_str())); + self + } + + pub fn cranelift_pgo_optimize(mut self, profile: &CraneliftPGOProfile) -> Self { + self.cmd = self + .cmd + .arg("--set") + .arg(format!(r#"pgo.cranelift.use="{}""#, normalize_path(&profile.0).as_str())); + self + } + pub fn with_llvm_bolt_ldflags(mut self) -> Self { self.cmd = self.cmd.arg("--set").arg("llvm.ldflags=-Wl,-q"); self diff --git a/src/tools/opt-dist/src/main.rs b/src/tools/opt-dist/src/main.rs index 11560425e44c7..cd01b41f8c998 100644 --- a/src/tools/opt-dist/src/main.rs +++ b/src/tools/opt-dist/src/main.rs @@ -10,8 +10,8 @@ use crate::exec::{Bootstrap, cmd}; use crate::tests::run_tests; use crate::timer::Timer; use crate::training::{ - gather_bolt_profiles, gather_clippy_profiles, gather_llvm_profiles, gather_rustc_profiles, - gather_rustdoc_profiles, llvm_benchmarks, rustc_benchmarks, + gather_bolt_profiles, gather_clippy_profiles, gather_cranelift_profiles, gather_llvm_profiles, + gather_rustc_profiles, gather_rustdoc_profiles, llvm_benchmarks, rustc_benchmarks, }; use crate::utils::artifact_size::print_binary_sizes; use crate::utils::io::{copy_directory, reset_directory}; @@ -237,12 +237,13 @@ fn execute_pipeline( })?; let optimize_clippy = !is_fast_try_build(); + let optimize_cranelift = !is_fast_try_build(); // Stage 1: Build PGO instrumented rustc // We use a normal build of LLVM, because gathering PGO profiles for LLVM and `rustc` at the // same time can cause issues, because the host and in-tree LLVM versions can diverge. - let (rustc_pgo_profile, rustdoc_pgo_profile, clippy_pgo_profile) = - timer.section("Stage 1 (Rustc + rustdoc + cargo + clippy PGO)", |stage| { + let (rustc_pgo_profile, rustdoc_pgo_profile, clippy_pgo_profile, cranelift_pgo_profile) = timer + .section("Stage 1 (Rustc + rustdoc + cargo + clippy PGO)", |stage| { let rustc_profile_dir_root = env.artifact_dir().join("rustc-pgo"); stage.section("Build PGO instrumented rustc and LLVM", |section| { @@ -258,6 +259,10 @@ fn execute_pipeline( if optimize_clippy { builder = builder.with_clippy().clippy_pgo_instrument(&rustc_profile_dir_root); } + if optimize_cranelift { + builder = + builder.with_cranelift().cranelift_pgo_instrument(&rustc_profile_dir_root); + } if env.supports_shared_llvm() { // This first LLVM that we build will be thrown away after this stage, and it @@ -283,6 +288,13 @@ fn execute_pipeline( } else { None }; + let cranelift_profile = if optimize_cranelift { + stage.section("Gather cranelift profiles", |_| { + Ok(Some(gather_cranelift_profiles(env, &rustc_profile_dir_root)?)) + })? + } else { + None + }; print_free_disk_space()?; stage.section("Build PGO optimized rustc", |section| { @@ -295,6 +307,9 @@ fn execute_pipeline( if let Some(clippy_profile) = clippy_profile.as_ref() { cmd = cmd.with_clippy().clippy_pgo_optimize(clippy_profile); } + if let Some(cranelift_profile) = cranelift_profile.as_ref() { + cmd = cmd.with_cranelift().cranelift_pgo_optimize(cranelift_profile); + } if env.use_bolt() { cmd = cmd.with_rustc_bolt_ldflags(); } @@ -302,7 +317,7 @@ fn execute_pipeline( cmd.run(section) })?; - Ok((rustc_profile, rustdoc_profile, clippy_profile)) + Ok((rustc_profile, rustdoc_profile, clippy_profile, cranelift_profile)) })?; // Stage 2: Gather LLVM PGO profiles @@ -441,6 +456,9 @@ fn execute_pipeline( if let Some(clippy_pgo_profile) = clippy_pgo_profile { dist = dist.clippy_pgo_optimize(&clippy_pgo_profile); } + if let Some(cranelift_pgo_profile) = cranelift_pgo_profile { + dist = dist.cranelift_pgo_optimize(&cranelift_pgo_profile); + } // if LLVM is not built we'll have PGO optimized rustc dist = if env.supports_shared_llvm() || !env.build_llvm() { diff --git a/src/tools/opt-dist/src/training.rs b/src/tools/opt-dist/src/training.rs index df5c1ff3c49d4..88a22ffe569e4 100644 --- a/src/tools/opt-dist/src/training.rs +++ b/src/tools/opt-dist/src/training.rs @@ -108,10 +108,14 @@ fn log_profile_stats( } pub fn llvm_benchmarks(env: &Environment) -> CmdBuilder { - init_compiler_benchmarks(env, &["Debug", "Opt"], &["Full"], LLVM_PGO_CRATES) init_compiler_benchmarks(env, &["Debug", "Opt"], &["Full"], BACKEND_PGO_CRATES) } +fn cranelift_benchmarks(env: &Environment) -> CmdBuilder { + let cmd = init_compiler_benchmarks(env, &["Debug"], &["Full"], BACKEND_PGO_CRATES); + cmd.arg("--backends").arg("Cranelift") +} + // Here we're profiling the `rustc` frontend, so we also include `Check`. // The benchmark set includes various stress tests that put the frontend under pressure. pub fn rustc_benchmarks(env: &Environment) -> CmdBuilder { @@ -182,6 +186,17 @@ pub fn gather_clippy_profiles( gather_pgo_profiles(env, profile_root, "clippy", clippy_benchmarks(env)).map(ClippyPGOProfile) } +pub struct CraneliftPGOProfile(pub Utf8PathBuf); + +pub fn gather_cranelift_profiles( + env: &Environment, + profile_root: &Utf8Path, +) -> anyhow::Result { + log::info!("Running benchmarks with PGO instrumented cranelift codegen backend"); + gather_pgo_profiles(env, profile_root, "cranelift", cranelift_benchmarks(env)) + .map(CraneliftPGOProfile) +} + pub fn gather_pgo_profiles( env: &Environment, profile_root: &Utf8Path, From 1859636fd0ac1d7e523d60681d8c93e61582e6d9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alejandra=20Gonz=C3=A1lez?= Date: Fri, 2 Oct 2026 11:15:22 +0000 Subject: [PATCH 1182/1309] Change rustc_public `run` macro to also use `compiler_entrypoint` --- compiler/rustc_public/src/rustc_internal/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_public/src/rustc_internal/mod.rs b/compiler/rustc_public/src/rustc_internal/mod.rs index 744aa1ffdd314..d127a62862e78 100644 --- a/compiler/rustc_public/src/rustc_internal/mod.rs +++ b/compiler/rustc_public/src/rustc_internal/mod.rs @@ -199,7 +199,7 @@ macro_rules! run_driver { /// Runs the compiler against given target and tests it with `test_function` pub fn run(&mut self, args: &[String]) -> Result> { let compiler_result = rustc_driver::catch_fatal_errors(|| -> interface::Result::<()> { - run_compiler(&args, self); + compiler_entrypoint(&args, self); Ok(()) }); match (compiler_result, self.result.take()) { From 60f8e925ce0bd5fbc9cbdc6a3528885dbc057b06 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Fri, 2 Oct 2026 13:33:42 +0200 Subject: [PATCH 1183/1309] Remove variants from `feature-gate-autodiff-use` test --- .../feature-gate-autodiff-use.rs | 22 +++++++----------- .../feature-gate-autodiff-use.stable.stderr | 23 ------------------- ...tderr => feature-gate-autodiff-use.stderr} | 4 ++-- 3 files changed, 10 insertions(+), 39 deletions(-) delete mode 100644 tests/ui/feature-gates/feature-gate-autodiff-use.stable.stderr rename tests/ui/feature-gates/{feature-gate-autodiff-use.nightly.stderr => feature-gate-autodiff-use.stderr} (91%) diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.rs b/tests/ui/feature-gates/feature-gate-autodiff-use.rs index d97c06de7de5b..85608be4ac04a 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.rs +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.rs @@ -1,22 +1,16 @@ -//@ revisions: nightly stable -//@[nightly] only-nightly -//@[stable] only-stable - // This checks that without enabling the autodiff feature, we can't import std::autodiff::autodiff; #![crate_type = "lib"] use std::autodiff::autodiff_reverse; -//[nightly]~^ ERROR use of unstable library feature `autodiff` -//[stable]~^^ ERROR use of unstable library feature `autodiff` -//[stable]~| NOTE see issue #124509 for more information -//[stable]~| HELP add `#![feature(autodiff)]` to the crate attributes to enable -//[stable]~| NOTE this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +//~^ ERROR use of unstable library feature `autodiff` +//| NOTE see issue #124509 for more information +//| HELP add `#![feature(autodiff)]` to the crate attributes to enable +//| NOTE this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date #[autodiff_reverse(dfoo)] -//[nightly]~^ ERROR use of unstable library feature `autodiff` [E0658] -//[stable]~^^ ERROR use of unstable library feature `autodiff` [E0658] -//[stable]~| NOTE see issue #124509 for more information -//[stable]~| HELP add `#![feature(autodiff)]` to the crate attributes to enable -//[stable]~| NOTE this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +//~^ ERROR use of unstable library feature `autodiff` [E0658] +//| NOTE see issue #124509 for more information +//| HELP add `#![feature(autodiff)]` to the crate attributes to enable +//| NOTE this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date fn foo() {} diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.stable.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.stable.stderr deleted file mode 100644 index ca724632063d4..0000000000000 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.stable.stderr +++ /dev/null @@ -1,23 +0,0 @@ -error[E0658]: use of unstable library feature `autodiff` - --> $DIR/feature-gate-autodiff-use.rs:16:3 - | -LL | #[autodiff_reverse(dfoo)] - | ^^^^^^^^^^^^^^^^ - | - = note: see issue #124509 for more information - = help: add `#![feature(autodiff)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error[E0658]: use of unstable library feature `autodiff` - --> $DIR/feature-gate-autodiff-use.rs:9:5 - | -LL | use std::autodiff::autodiff_reverse; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: see issue #124509 for more information - = help: add `#![feature(autodiff)]` to the crate attributes to enable - = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date - -error: aborting due to 2 previous errors - -For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-autodiff-use.nightly.stderr b/tests/ui/feature-gates/feature-gate-autodiff-use.stderr similarity index 91% rename from tests/ui/feature-gates/feature-gate-autodiff-use.nightly.stderr rename to tests/ui/feature-gates/feature-gate-autodiff-use.stderr index ca724632063d4..94b9a065e491e 100644 --- a/tests/ui/feature-gates/feature-gate-autodiff-use.nightly.stderr +++ b/tests/ui/feature-gates/feature-gate-autodiff-use.stderr @@ -1,5 +1,5 @@ error[E0658]: use of unstable library feature `autodiff` - --> $DIR/feature-gate-autodiff-use.rs:16:3 + --> $DIR/feature-gate-autodiff-use.rs:11:3 | LL | #[autodiff_reverse(dfoo)] | ^^^^^^^^^^^^^^^^ @@ -9,7 +9,7 @@ LL | #[autodiff_reverse(dfoo)] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: use of unstable library feature `autodiff` - --> $DIR/feature-gate-autodiff-use.rs:9:5 + --> $DIR/feature-gate-autodiff-use.rs:5:5 | LL | use std::autodiff::autodiff_reverse; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 9b60c2ad0f07a0eadedc06fdebd858a9ee8a328b Mon Sep 17 00:00:00 2001 From: Yara Date: Tue, 15 Sep 2026 16:40:04 +0200 Subject: [PATCH 1184/1309] reflection: move type_id intrinsics to intrinsics::reflection --- .../rustc_hir_analysis/src/check/intrinsic.rs | 11 +- compiler/rustc_span/src/symbol.rs | 2 +- library/core/src/any.rs | 9 +- library/core/src/intrinsics/mod.rs | 177 +--------------- library/core/src/intrinsics/reflection.rs | 194 ++++++++++++++++++ library/core/src/mem/type_info.rs | 39 ++-- library/core/src/unit.rs | 2 +- library/coretests/tests/intrinsics.rs | 2 +- tests/mir-opt/inline/type_id_eq.rs | 2 +- .../rustc_public/check_allocation.rs | 2 +- 10 files changed, 229 insertions(+), 211 deletions(-) create mode 100644 library/core/src/intrinsics/reflection.rs diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index 88a93229296c2..168896a5c8d47 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -198,7 +198,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::truncf64 | sym::truncf128 | sym::type_id - | sym::type_id_non_exhaustive | sym::type_id_array_len | sym::type_id_element_ty | sym::type_id_eq @@ -207,16 +206,16 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::type_id_function_ptr | sym::type_id_generics | sym::type_id_is_signed + | sym::type_id_non_exhaustive | sym::type_id_points_mutably | sym::type_id_points_to - | sym::type_id_variants - | sym::type_id_vtable - | sym::type_name - | sym::type_id_type_of | sym::type_id_size_of - | sym::type_id_variants + | sym::type_id_type_of | sym::type_id_variant_name | sym::type_id_variant_non_exhaustive + | sym::type_id_variants + | sym::type_id_vtable + | sym::type_name | sym::ub_checks | sym::va_copy | sym::variant_count diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 3adfb62d1ce54..abf38d2847fb3 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2207,7 +2207,6 @@ symbols! { type_id_points_mutably, type_id_points_to, type_id_size_of, - type_name, type_id_type_of, type_id_variant_name, type_id_variant_non_exhaustive, @@ -2221,6 +2220,7 @@ symbols! { type_ir_interner, type_length_limit, type_macros, + type_name, type_privacy_lints, typed_swap_nonoverlapping, u8, diff --git a/library/core/src/any.rs b/library/core/src/any.rs index 85ff2fe1dd6ee..98563f9011f87 100644 --- a/library/core/src/any.rs +++ b/library/core/src/any.rs @@ -86,7 +86,8 @@ #![stable(feature = "rust1", since = "1.0.0")] -use crate::intrinsics::{self, type_id, type_id_vtable}; +use crate::intrinsics::reflection::{type_id, type_id_vtable}; +use crate::intrinsics::{self}; use crate::mem::transmute; use crate::mem::type_info::{TraitImpl, TypeKind}; use crate::{fmt, hash, ptr}; @@ -742,7 +743,7 @@ unsafe impl Sync for TypeId {} const impl PartialEq for TypeId { #[inline] fn eq(&self, other: &Self) -> bool { - crate::intrinsics::type_id_eq(*self, *other) + crate::intrinsics::reflection::type_id_eq(*self, *other) } } @@ -765,7 +766,7 @@ impl TypeId { #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_type_id", since = "1.91.0")] pub const fn of() -> TypeId { - const { intrinsics::type_id::() } + const { intrinsics::reflection::type_id::() } } /// Checks if the [TypeId] implements the trait. If it does it returns [TraitImpl] which can be used to build a fat pointer. @@ -903,7 +904,7 @@ impl fmt::Debug for TypeId { #[stable(feature = "type_name", since = "1.38.0")] #[rustc_const_unstable(feature = "const_type_name", issue = "63084")] pub const fn type_name() -> &'static str { - const { intrinsics::type_name::() } + const { intrinsics::reflection::type_name::() } } /// Returns the type name of the pointed-to value as a string slice. diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index 12cb3d2b6d8b4..34675bf8fc429 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -88,6 +88,7 @@ pub mod fallback; pub mod gpu; mod macros; pub mod mir; +pub mod reflection; pub mod simd; use macros::intrinsic_dispatch_on_type; @@ -2962,25 +2963,6 @@ pub const unsafe fn size_of_val(ptr: *const T) -> usize; #[rustc_intrinsic_const_stable_indirect] pub const unsafe fn align_of_val(ptr: *const T) -> usize; -#[rustc_intrinsic] -#[rustc_comptime] -#[unstable(feature = "core_intrinsics", issue = "none")] -/// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. -/// It can only be called at compile time, the backends do -/// not implement it. If it implements the trait the dyn metadata gets returned for vtable access. -pub fn type_id_vtable( - _id: crate::any::TypeId, - _trait: crate::any::TypeId, -) -> Option>; - -/// Compute the type information of a concrete type. -/// It can only be called at compile time, the backends do -/// not implement it. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; - /// Gets a static string slice containing the name of a type. /// /// Note that, unlike most intrinsics, this can only be called at compile-time @@ -2995,121 +2977,6 @@ pub fn type_id_type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; #[rustc_comptime] pub fn type_name() -> &'static str; -/// Gets an identifier which is globally unique to the specified type. This -/// function will return the same value for a type regardless of whichever -/// crate it is invoked in. -/// -/// Note that, unlike most intrinsics, this can only be called at compile-time -/// as backends do not have an implementation for it. The only caller (its -/// stable counterpart) wraps this intrinsic call in a `const` block so that -/// backends only see an evaluated constant. -/// -/// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. -#[rustc_nounwind] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_intrinsic] -#[rustc_comptime] -pub fn type_id() -> crate::any::TypeId; - -/// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the -/// same type. This is necessary because at const-eval time the actual discriminating -/// data is opaque and cannot be inspected directly. -/// -/// The stabilized version of this intrinsic is the [PartialEq] impl for [`core::any::TypeId`]. -#[rustc_nounwind] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_intrinsic] -#[rustc_do_not_const_check] -pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { - // SAFETY: we know `TypeId` is 16 bytes of initialized data. - // This is runtime-only code so we do not have to worry about provenance. - unsafe { crate::mem::transmute::<_, u128>(a) == crate::mem::transmute::<_, u128>(b) } -} - -/// Returns whether the type represented by this `TypeId` is a signed integer. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::is_signed`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_is_signed(_id: crate::any::TypeId) -> bool; - -/// Gets the length of the array represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::array_len`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_array_len(_id: crate::any::TypeId) -> usize; - -/// Gets the type of each element of the array or slice represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::element_ty`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_element_ty(_id: crate::any::TypeId) -> Option; - -/// Gets the size of the type represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_size_of(_id: crate::any::TypeId) -> Option; - -/// Gets the number of variants of the type represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_variants(_id: crate::any::TypeId) -> usize; - -/// Gets the name of the variant represented by the base `TypeId` and variant_idx. -/// -/// The more user-friendly version of this intrinsic is [`core::mem::type_info::VariantId::name`]. -/// -/// [`TypeId`]: crate::any::TypeId -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_variant_name(_base: crate::any::TypeId, _variant_index: usize) -> &'static str; - -/// Returns true when the variant represented by the base `TypeId` and variant_idx is non -/// exhaustive. -/// -/// The more user-friendly version of this intrinsic is -/// [`core::mem::type_info::VariantId::non_exhaustive`]. -/// -/// [`TypeId`]: crate::any::TypeId -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_variant_non_exhaustive(base: crate::any::TypeId, variant: usize) -> bool; - -/// Gets the number of fields at the given `variant_index` represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize; - -/// Gets the [`FieldRepresentingType`]'s `TypeId` at the given index of the type represented by this `TypeId`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::field`]. -/// -/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_field_representing_type( - _id: crate::any::TypeId, - _variant_index: usize, - _field_index: usize, -) -> crate::any::TypeId; - /// Gets the actual field `TypeId` of the [`FieldRepresentingType`]'s `TypeId`. /// /// The more user-friendly version of this intrinsic is [`core::mem::type_info::FieldId::type_id`]. @@ -3142,48 +3009,6 @@ pub fn field_representing_type_name(_frt_type_id: crate::any::TypeId) -> &'stati #[rustc_comptime] pub fn field_representing_type_offset(_frt_type_id: crate::any::TypeId) -> usize; -/// Given a `TypeId` that represents a function pointer returns an [`core::mem::type_info::FnPtr`]. -/// When called on something else this returns `None`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::function_ptr`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_function_ptr(_type_id: crate::any::TypeId) -> Option; - -/// Checks whether this type is non-exhaustive. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_non_exhaustive(_id: crate::any::TypeId) -> bool; - -/// Returns the list of generic args on this type. -/// Only meaningful for Adts, closures, ... Everything else returns an empty slice. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_generics(_id: crate::any::TypeId) -> &'static [crate::mem::type_info::Generic]; - -// FIXME(reflection): Pick a consistent naming scheme for the intrinsics. Right now we got -// type_id_, _type_id and intrinsics not mentioning type_id at all. -/// Given a `TypeId` that represents a pointer this returns the `TypeId` which that pointer -/// points to. When called on anything else this returns None. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::points_to`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_points_to(_id: crate::any::TypeId) -> Option; - -/// Given a `TypeId` that represents a pointer returns whether that pointer is mutable. -/// When called on anything else this returns `false`. -/// -/// The more user-friendly version of this intrinsic is [`core::any::TypeId::points_mutably`]. -#[rustc_intrinsic] -#[unstable(feature = "core_intrinsics", issue = "none")] -#[rustc_comptime] -pub fn type_id_points_mutably(_id: crate::any::TypeId) -> bool; - /// Lowers in MIR to `Rvalue::Aggregate` with `AggregateKind::RawPtr`. /// /// This is used to implement functions like `slice::from_raw_parts_mut` and diff --git a/library/core/src/intrinsics/reflection.rs b/library/core/src/intrinsics/reflection.rs new file mode 100644 index 0000000000000..f0e0f9d66e033 --- /dev/null +++ b/library/core/src/intrinsics/reflection.rs @@ -0,0 +1,194 @@ +//! Intrinsics for compile time reflection +//! +//! This are all methods operating on [`TypeId`](core::any::TypeId) which is the +//! entry point to all compile time reflection. + +use crate::ptr; + +/// Gets an identifier which is globally unique to the specified type. This +/// function will return the same value for a type regardless of whichever +/// crate it is invoked in. +/// +/// Note that, unlike most intrinsics, this can only be called at compile-time +/// as backends do not have an implementation for it. The only caller (its +/// stable counterpart) wraps this intrinsic call in a `const` block so that +/// backends only see an evaluated constant. +/// +/// The stabilized version of this intrinsic is [`core::any::TypeId::of`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_comptime] +pub fn type_id() -> crate::any::TypeId; + +/// Compute the type information of a concrete type. +/// It can only be called at compile time, the backends do +/// not implement it. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; + +/// Tests (at compile-time) if two [`crate::any::TypeId`] instances identify the +/// same type. This is necessary because at const-eval time the actual discriminating +/// data is opaque and cannot be inspected directly. +/// +/// The stabilized version of this intrinsic is the [PartialEq] impl for [`core::any::TypeId`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_do_not_const_check] +pub const fn type_id_eq(a: crate::any::TypeId, b: crate::any::TypeId) -> bool { + // SAFETY: we know `TypeId` is 16 bytes of initialized data. + // This is runtime-only code so we do not have to worry about provenance. + unsafe { crate::mem::transmute::<_, u128>(a) == crate::mem::transmute::<_, u128>(b) } +} + +#[rustc_intrinsic] +#[rustc_comptime] +#[unstable(feature = "core_intrinsics", issue = "none")] +/// Check if a type represented by a `TypeId` implements a trait represented by a `TypeId`. +/// It can only be called at compile time, the backends do +/// not implement it. If it implements the trait the dyn metadata gets returned for vtable access. +pub fn type_id_vtable( + _id: crate::any::TypeId, + _trait: crate::any::TypeId, +) -> Option>; + +/// Gets a static string slice containing the name of a type. +/// +/// Note that, unlike most intrinsics, this can only be called at compile-time +/// as backends do not have an implementation for it. The only caller (its +/// stable counterpart) wraps this intrinsic call in a `const` block so that +/// backends only see an evaluated constant. +/// +/// The stabilized version of this intrinsic is [`core::any::type_name`]. +#[rustc_nounwind] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_intrinsic] +#[rustc_comptime] +pub fn type_name() -> &'static str; + +/// Returns whether the type represented by this `TypeId` is a signed integer. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::is_signed`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_is_signed(_id: crate::any::TypeId) -> bool; + +/// Gets the length of the array represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::array_len`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_array_len(_id: crate::any::TypeId) -> usize; + +/// Gets the type of each element of the array or slice represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::element_ty`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_element_ty(_id: crate::any::TypeId) -> Option; + +/// Gets the size of the type represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::size`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_size_of(_id: crate::any::TypeId) -> Option; + +/// Gets the number of variants of the type represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::variants`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_variants(_id: crate::any::TypeId) -> usize; + +/// Gets the name of the variant represented by the base `TypeId` and variant_idx. +/// +/// The more user-friendly version of this intrinsic is [`core::mem::type_info::VariantId::name`]. +/// +/// [`TypeId`]: crate::any::TypeId +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_variant_name(_base: crate::any::TypeId, _variant_index: usize) -> &'static str; + +/// Returns true when the variant represented by the base `TypeId` and variant_idx is non +/// exhaustive. +/// +/// The more user-friendly version of this intrinsic is +/// [`core::mem::type_info::VariantId::non_exhaustive`]. +/// +/// [`TypeId`]: crate::any::TypeId +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_variant_non_exhaustive(base: crate::any::TypeId, variant: usize) -> bool; + +/// Gets the number of fields at the given `variant_index` represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::fields`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_fields(_id: crate::any::TypeId, _variant_index: usize) -> usize; + +/// Checks whether this type is non-exhaustive. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_non_exhaustive(_id: crate::any::TypeId) -> bool; + +/// Returns the list of generic args on this type. +/// Only meaningful for Adts, closures, ... Everything else returns an empty slice. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_generics(_id: crate::any::TypeId) -> &'static [crate::mem::type_info::Generic]; + +/// Gets the [`FieldRepresentingType`]'s `TypeId` at the given index of the type represented by this `TypeId`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::field`]. +/// +/// [`FieldRepresentingType`]: crate::field::FieldRepresentingType +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_field_representing_type( + _id: crate::any::TypeId, + _variant_index: usize, + _field_index: usize, +) -> crate::any::TypeId; + +/// Given a `TypeId` that represents a pointer this returns the `TypeId` which that pointer +/// points to. When called on anything else this returns None. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::points_to`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_points_to(_id: crate::any::TypeId) -> Option; + +/// Given a `TypeId` that represents a pointer returns whether that pointer is mutable. +/// When called on anything else this returns `false`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::points_mutably`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_points_mutably(_id: crate::any::TypeId) -> bool; + +/// Given a `TypeId` that represents a function pointer returns an [`core::mem::type_info::FnPtr`]. +/// When called on something else this returns `None`. +/// +/// The more user-friendly version of this intrinsic is [`core::any::TypeId::function_ptr`]. +#[rustc_intrinsic] +#[unstable(feature = "core_intrinsics", issue = "none")] +#[rustc_comptime] +pub fn type_id_function_ptr(_type_id: crate::any::TypeId) -> Option; diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index 1e96cf915e67d..71a9627c24f9c 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -2,10 +2,9 @@ //! runtime or const-eval processable way. use crate::any::TypeId; -use crate::fmt; -use crate::intrinsics; use crate::marker::PointeeSized; use crate::ptr::DynMetadata; +use crate::{fmt, intrinsics}; /// Compile-time type information. #[derive(Debug)] @@ -38,7 +37,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn info(self) -> Type { - intrinsics::type_id_type_of(self) + intrinsics::reflection::type_id_type_of(self) } } @@ -54,7 +53,7 @@ impl Type { #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] pub const fn of() -> Self { - const { intrinsics::type_id::().info() } + const { intrinsics::reflection::type_id::().info() } } } @@ -67,7 +66,7 @@ impl Type { #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] pub const fn of() -> TypeId { - const { intrinsics::type_id::() } + const { intrinsics::reflection::type_id::() } } /// Compile-time type information. @@ -272,7 +271,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn is_signed(self) -> bool { - intrinsics::type_id_is_signed(self) + intrinsics::reflection::type_id_is_signed(self) } /// When called on a `TypeId` representing an array or slice this returns the type of each @@ -291,7 +290,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn element_ty(self) -> Option { - intrinsics::type_id_element_ty(self) + intrinsics::reflection::type_id_element_ty(self) } /// When called on a `TypeId` representing an array this returns the length of the array in @@ -310,7 +309,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn array_len(self) -> usize { - intrinsics::type_id_array_len(self) + intrinsics::reflection::type_id_array_len(self) } /// Returns the size of the type represented by this `TypeId`. `None` if it is unsized. @@ -328,7 +327,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn size(self) -> Option { - intrinsics::type_id_size_of(self) + intrinsics::reflection::type_id_size_of(self) } /// Returns the number of variants of the type represented by this `TypeId`. @@ -354,7 +353,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn variants(self) -> usize { - intrinsics::type_id_variants(self) + intrinsics::reflection::type_id_variants(self) } // FIXME(reflection): make the errors nicer. This is a wider problem, @@ -416,7 +415,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn variant(self, variant_index: usize) -> VariantId { - intrinsics::type_id_fields(self, variant_index); + intrinsics::reflection::type_id_fields(self, variant_index); VariantId { base: self, variant: variant_index } } @@ -484,7 +483,7 @@ impl TypeId { // type we have) and add methods on that. It's the only way to really sensibly represent // things like `non_exhaustive` which can be applied to variants as well. pub fn fields(self, variant_index: usize) -> usize { - intrinsics::type_id_fields(self, variant_index) + intrinsics::reflection::type_id_fields(self, variant_index) } /// Returns the field representing type at the given index of the type represented by this `TypeId`. @@ -552,7 +551,7 @@ impl TypeId { #[rustc_comptime] pub fn field(self, variant_index: usize, field_index: usize) -> FieldId { FieldId { - frt_type_id: intrinsics::type_id_field_representing_type( + frt_type_id: intrinsics::reflection::type_id_field_representing_type( self, variant_index, field_index, @@ -566,7 +565,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn non_exhaustive(self) -> bool { - intrinsics::type_id_non_exhaustive(self) + intrinsics::reflection::type_id_non_exhaustive(self) } /// Returns a list of generic parameters of the type. @@ -575,7 +574,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn generics(self) -> &'static [Generic] { - intrinsics::type_id_generics(self) + intrinsics::reflection::type_id_generics(self) } /// Given a `TypeId` that represents a pointer this returns the `TypeId` @@ -600,7 +599,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn points_to(self) -> Option { - intrinsics::type_id_points_to(self) + intrinsics::reflection::type_id_points_to(self) } /// Given a `TypeId` that represents a pointer returns whether that pointer is mutable. @@ -620,7 +619,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn points_mutably(self) -> bool { - intrinsics::type_id_points_mutably(self) + intrinsics::reflection::type_id_points_mutably(self) } /// Given a `TypeId` that represents a function pointer returns an @@ -655,7 +654,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn function_ptr(self) -> Option { - intrinsics::type_id_function_ptr(self) + intrinsics::reflection::type_id_function_ptr(self) } } @@ -696,7 +695,7 @@ impl VariantId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn name(self) -> &'static str { - intrinsics::type_id_variant_name(self.base, self.variant) + intrinsics::reflection::type_id_variant_name(self.base, self.variant) } /// Returns whether this variant is marked with `#[non_exhaustive]`. @@ -704,7 +703,7 @@ impl VariantId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn non_exhaustive(self) -> bool { - intrinsics::type_id_variant_non_exhaustive(self.base, self.variant) + intrinsics::reflection::type_id_variant_non_exhaustive(self.base, self.variant) } } diff --git a/library/core/src/unit.rs b/library/core/src/unit.rs index 5d9c79538e371..6c746c939b84a 100644 --- a/library/core/src/unit.rs +++ b/library/core/src/unit.rs @@ -1,4 +1,4 @@ -use crate::intrinsics::type_id; +use crate::intrinsics::reflection::type_id; /// Collapses all unit items from an iterator into one. /// diff --git a/library/coretests/tests/intrinsics.rs b/library/coretests/tests/intrinsics.rs index e562f49b0a2fc..0fec76d3bd65a 100644 --- a/library/coretests/tests/intrinsics.rs +++ b/library/coretests/tests/intrinsics.rs @@ -1,7 +1,7 @@ use core::any::TypeId; use core::intrinsics::assume; use std::fmt::Debug; -use std::intrinsics::type_id_vtable; +use std::intrinsics::reflection::type_id_vtable; use std::option::Option; use std::ptr::DynMetadata; diff --git a/tests/mir-opt/inline/type_id_eq.rs b/tests/mir-opt/inline/type_id_eq.rs index 72348447cdc45..0d4e2ca20cf0e 100644 --- a/tests/mir-opt/inline/type_id_eq.rs +++ b/tests/mir-opt/inline/type_id_eq.rs @@ -3,7 +3,7 @@ //@ compile-flags: --crate-type=lib -C panic=abort use std::any::{Any, TypeId}; -use std::intrinsics::type_id_eq; +use std::intrinsics::reflection::type_id_eq; struct A { a: i32, diff --git a/tests/ui-fulldeps/rustc_public/check_allocation.rs b/tests/ui-fulldeps/rustc_public/check_allocation.rs index 356ea64729cb7..cd52ff6dbeff4 100644 --- a/tests/ui-fulldeps/rustc_public/check_allocation.rs +++ b/tests/ui-fulldeps/rustc_public/check_allocation.rs @@ -250,7 +250,7 @@ fn generate_input(path: &str) -> std::io::Result<()> { r#" #![feature(core_intrinsics)] #![expect(internal_features)] - use std::intrinsics::type_id; + use std::intrinsics::reflection::type_id; static LEN: usize = 2; static FOO: [&str; 2] = ["hi", "there"]; From f3f9adf7082e27e0b77b05ec3e2fdaee1badd056 Mon Sep 17 00:00:00 2001 From: Miguel Ojeda Date: Fri, 2 Oct 2026 14:48:46 +0200 Subject: [PATCH 1185/1309] tests: add test for warning-free builds of `core` under `no_io_statics` Similar to the existing tests for other `cfg`s like `no_fp_fmt_parse`, add one for `no_io_statics`. This should prevent issues like the one in the parent commit. Signed-off-by: Miguel Ojeda --- tests/run-make/core-no-io-statics/rmake.rs | 14 ++++++++++++++ 1 file changed, 14 insertions(+) create mode 100644 tests/run-make/core-no-io-statics/rmake.rs diff --git a/tests/run-make/core-no-io-statics/rmake.rs b/tests/run-make/core-no-io-statics/rmake.rs new file mode 100644 index 0000000000000..0e75dfa8c273c --- /dev/null +++ b/tests/run-make/core-no-io-statics/rmake.rs @@ -0,0 +1,14 @@ +// This test checks that the core library of Rust can be compiled when enabling +// `--cfg no_io_statics`. + +use run_make_support::{rustc, source_root}; + +fn main() { + rustc() + .edition("2024") + .arg("-Dwarnings") + .crate_type("rlib") + .input(source_root().join("library/core/src/lib.rs")) + .cfg("no_io_statics") + .run(); +} From b592ad4789301c2c84f5b9dc87861538d84a4f52 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 12:23:20 +0200 Subject: [PATCH 1186/1309] pick more sensible path for current_exe --- src/tools/miri/src/bin/miri.rs | 5 ++++- src/tools/miri/src/eval.rs | 3 +++ src/tools/miri/src/machine.rs | 6 +++++- src/tools/miri/src/shims/unix/fs.rs | 4 ++-- src/tools/miri/src/shims/unix/macos/foreign_items.rs | 8 +++++--- src/tools/miri/src/shims/windows/foreign_items.rs | 6 +++--- src/tools/miri/test-cargo-miri/run.args.stderr.ref | 2 +- .../miri/test-cargo-miri/run.custom-target-dir.stderr.ref | 2 +- src/tools/miri/test-cargo-miri/run.default.stderr.ref | 2 +- src/tools/miri/tests/pass/shims/env/args.stdout | 2 +- src/tools/miri/tests/pass/shims/env/current_exe.rs | 5 +++-- src/tools/miri/tests/pass/shims/env/current_exe.stdout | 1 + 12 files changed, 30 insertions(+), 16 deletions(-) create mode 100644 src/tools/miri/tests/pass/shims/env/current_exe.stdout diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 7b3f166b3bf87..a0f71a787a9f9 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -159,7 +159,10 @@ impl rustc_driver::Callbacks for MiriCompilerCalls { // Obtain and complete the Miri configuration. let mut config = self.miri_config.take().expect("after_analysis must only be called once"); // Add filename to `miri` arguments. - config.args.insert(0, tcx.sess.io.input.filestem().to_string()); + let file_name = tcx.sess.io.input.file_name(tcx.sess); + config.args.insert(0, file_name.prefer_local_unconditionally().to_string()); + // And configure the executable. + config.current_exe = file_name.into_local_path().and_then(|p| p.canonicalize().ok()); // Adjust working directory for interpretation. if let Some(cwd) = env::var_os("MIRI_CWD") { diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs index 6e2f300e37ce0..6e51ff42367dc 100644 --- a/src/tools/miri/src/eval.rs +++ b/src/tools/miri/src/eval.rs @@ -111,6 +111,8 @@ pub struct MiriConfig { pub set_env_vars: FxHashMap, /// Command-line arguments passed to the interpreted program. pub args: Vec, + /// The binary we pretend to be. + pub current_exe: Option, /// The seed to use when non-determinism or randomness are required (e.g. ptr-to-int cast, `getrandom()`). pub seed: Option, /// The stacked borrows pointer ids to report about. @@ -184,6 +186,7 @@ impl Default for MiriConfig { forwarded_env_vars: vec![], set_env_vars: FxHashMap::default(), args: vec![], + current_exe: None, seed: None, tracked_pointer_tags: FxHashSet::default(), tracked_alloc_ids: FxHashSet::default(), diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs index cba1df6b1d7d2..b1f816c92e6f9 100644 --- a/src/tools/miri/src/machine.rs +++ b/src/tools/miri/src/machine.rs @@ -4,7 +4,7 @@ use std::borrow::Cow; use std::cell::{Cell, RefCell}; use std::collections::BTreeMap; -use std::path::Path; +use std::path::{Path, PathBuf}; use std::rc::Rc; use std::{fmt, process}; @@ -537,6 +537,8 @@ pub struct MiriMachine<'tcx> { pub(crate) argc: Option, pub(crate) argv: Option, pub(crate) cmd_line: Option, + /// The binary we pretend to be. + pub(crate) current_exe: Option, /// TLS state. pub(crate) tls: TlsData<'tcx>, @@ -784,6 +786,7 @@ impl<'tcx> MiriMachine<'tcx> { argc: None, argv: None, cmd_line: None, + current_exe: config.current_exe.clone(), tls: TlsData::default(), isolated_op: config.isolated_op, validation: config.validation, @@ -1035,6 +1038,7 @@ impl VisitProvenance for MiriMachine<'_> { argc, argv, cmd_line, + current_exe: _, extern_statics, extern_statics_imports, extern_static_weak_import_default, diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 0bf28103d102f..9b5ed86013f70 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1724,10 +1724,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // On Linux, special case `/proc/self/exe` so that `std::env::current_exe` works // in cross-execution. - let result = if matches!(this.tcx.sess.target.os, Os::Linux) + let result = if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) && pathname.to_str() == Some("/proc/self/exe") { - std::env::current_exe() + this.machine.current_exe.clone().ok_or(ErrorKind::NotFound.into()) } else { // We read `pathname` as `OsStr` above so we could do the /proc/self/exe check. // But now we need a (host) path. diff --git a/src/tools/miri/src/shims/unix/macos/foreign_items.rs b/src/tools/miri/src/shims/unix/macos/foreign_items.rs index 25ff4fe43b659..95e21289e860d 100644 --- a/src/tools/miri/src/shims/unix/macos/foreign_items.rs +++ b/src/tools/miri/src/shims/unix/macos/foreign_items.rs @@ -150,9 +150,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let buf_ptr = this.read_pointer(buf)?; let bufsize = this.deref_pointer_as(bufsize, this.machine.layouts.u32)?; - // Using the host current_exe is a bit off, but consistent with Linux - // (where stdlib reads /proc/self/exe). - let path = std::env::current_exe().unwrap(); + let Some(path) = this.machine.current_exe.clone() else { + throw_unsup_format!( + "_NSGetExecutablePath only works when Miri is run on a file" + ) + }; let (written, size_needed) = this.write_path_to_c_str( &path, buf_ptr, diff --git a/src/tools/miri/src/shims/windows/foreign_items.rs b/src/tools/miri/src/shims/windows/foreign_items.rs index bb738621a4ad6..28fe4e86bb7b5 100644 --- a/src/tools/miri/src/shims/windows/foreign_items.rs +++ b/src/tools/miri/src/shims/windows/foreign_items.rs @@ -1106,9 +1106,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("`GetModuleFileNameW` only supports the NULL handle"); } - // Using the host current_exe is a bit off, but consistent with Linux - // (where stdlib reads /proc/self/exe). - let path = std::env::current_exe().unwrap(); + let Some(path) = this.machine.current_exe.clone() else { + throw_unsup_format!("GetModuleFileNameW only works when Miri is run on a file") + }; let (all_written, size_needed) = this.write_path_to_wide_str_truncated(&path, filename, size.into())?; diff --git a/src/tools/miri/test-cargo-miri/run.args.stderr.ref b/src/tools/miri/test-cargo-miri/run.args.stderr.ref index 01bb8952322b6..89ff818875d9e 100644 --- a/src/tools/miri/test-cargo-miri/run.args.stderr.ref +++ b/src/tools/miri/test-cargo-miri/run.args.stderr.ref @@ -1,4 +1,4 @@ -main +src/main.rs hello world "hello world" he\\llo\"world diff --git a/src/tools/miri/test-cargo-miri/run.custom-target-dir.stderr.ref b/src/tools/miri/test-cargo-miri/run.custom-target-dir.stderr.ref index 4395ff8879b96..2ef4d5db3f414 100644 --- a/src/tools/miri/test-cargo-miri/run.custom-target-dir.stderr.ref +++ b/src/tools/miri/test-cargo-miri/run.custom-target-dir.stderr.ref @@ -1,2 +1,2 @@ -main +src/main.rs --target-dir=target/custom-run diff --git a/src/tools/miri/test-cargo-miri/run.default.stderr.ref b/src/tools/miri/test-cargo-miri/run.default.stderr.ref index ba2906d0666cf..53af45d07e576 100644 --- a/src/tools/miri/test-cargo-miri/run.default.stderr.ref +++ b/src/tools/miri/test-cargo-miri/run.default.stderr.ref @@ -1 +1 @@ -main +src/main.rs diff --git a/src/tools/miri/tests/pass/shims/env/args.stdout b/src/tools/miri/tests/pass/shims/env/args.stdout index 9564f5a1aa056..4928237adc516 100644 --- a/src/tools/miri/tests/pass/shims/env/args.stdout +++ b/src/tools/miri/tests/pass/shims/env/args.stdout @@ -1 +1 @@ -args +tests/pass/shims/env/args.rs diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 3c8cf8bcceebd..36138bf9c4df7 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -3,6 +3,7 @@ use std::env; fn main() { - // The actual value we get is a bit odd: we get the Miri binary that interprets us. - env::current_exe().unwrap(); + let exe = env::current_exe().unwrap(); + assert!(exe.is_absolute()); + println!("{}", exe.file_name().unwrap().display()); } diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.stdout b/src/tools/miri/tests/pass/shims/env/current_exe.stdout new file mode 100644 index 0000000000000..316fe6d20b25d --- /dev/null +++ b/src/tools/miri/tests/pass/shims/env/current_exe.stdout @@ -0,0 +1 @@ +current_exe.rs From 6e2fd190b235245642eb3af50fecca51f420461b Mon Sep 17 00:00:00 2001 From: Wiktor Przetacznik <85874198+WiktorPrzetacznik@users.noreply.github.com> Date: Sat, 31 Aug 2024 16:13:11 +0200 Subject: [PATCH 1187/1309] Fix typo --- library/core/src/str/iter.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/str/iter.rs b/library/core/src/str/iter.rs index b221b98a7b791..60b9e81aaeff9 100644 --- a/library/core/src/str/iter.rs +++ b/library/core/src/str/iter.rs @@ -1284,7 +1284,7 @@ pub struct SplitAsciiWhitespace<'a> { } /// An iterator over the substrings of a string, -/// terminated by a substring matching to a predicate function +/// terminated by a substring matching to a predicate function. /// Unlike `Split`, it contains the matched part as a terminator /// of the subslice. /// From 02d1672d5b802f5b41d193b393b419643a096afb Mon Sep 17 00:00:00 2001 From: Wiktor Przetacznik <85874198+WiktorPrzetacznik@users.noreply.github.com> Date: Sat, 31 Aug 2024 16:21:02 +0200 Subject: [PATCH 1188/1309] Introduce layout section in Saturating Document layout of Saturating, similarly to Wrapping --- library/core/src/num/saturating.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/library/core/src/num/saturating.rs b/library/core/src/num/saturating.rs index efe96a9ab7494..88961a1a28de8 100644 --- a/library/core/src/num/saturating.rs +++ b/library/core/src/num/saturating.rs @@ -31,6 +31,10 @@ use crate::ops::{ /// /// assert_eq!(u32::MAX, (max + one).0); /// ``` +/// +/// # Layout +/// +/// `Saturating` is guaranteed to have the same layout and ABI as `T`. #[stable(feature = "saturating_int_impl", since = "1.74.0")] #[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Copy, Default, Hash)] #[repr(transparent)] From 4613f38cc5a7d50ab76bf93f1f3b76fdf0d89764 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Sat, 25 Jul 2026 15:06:31 -0400 Subject: [PATCH 1189/1309] Send -fno-lto when linker plugin LTO is not requested to avoid having GCC do LTO when using rustc_codegen_gcc --- compiler/rustc_codegen_ssa/src/back/linker.rs | 9 ++++++++- tests/run-make/fno-lto/main.rs | 1 + tests/run-make/fno-lto/rmake.rs | 17 +++++++++++++++++ tests/run-make/linker-warning/rmake.rs | 1 + 4 files changed, 27 insertions(+), 1 deletion(-) create mode 100644 tests/run-make/fno-lto/main.rs create mode 100644 tests/run-make/fno-lto/rmake.rs diff --git a/compiler/rustc_codegen_ssa/src/back/linker.rs b/compiler/rustc_codegen_ssa/src/back/linker.rs index e08a825aa7019..ffb9130ed1a08 100644 --- a/compiler/rustc_codegen_ssa/src/back/linker.rs +++ b/compiler/rustc_codegen_ssa/src/back/linker.rs @@ -900,7 +900,14 @@ impl<'a> Linker for GccLinker<'a> { fn linker_plugin_lto(&mut self) { match self.sess.opts.cg.linker_plugin_lto { LinkerPluginLto::Disabled => { - // Nothing to do + // GCC, when used as a linker, will perform LTO even without -flto when it sees + // object files with the GCC IR (which can happen when using rustc_codegen_gcc). + // Since the std is compiled with -Cembed-bitcode=yes, any program using the std + // will have the linker do LTO. + // So, we disable this with -fno-lto when linker plugin LTO is not requested. + if self.is_cc() && self.codegen_backend == "gcc" { + self.cc_arg("-fno-lto"); + } } LinkerPluginLto::LinkerPluginAuto => { self.push_linker_plugin_lto_args(None); diff --git a/tests/run-make/fno-lto/main.rs b/tests/run-make/fno-lto/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/fno-lto/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/fno-lto/rmake.rs b/tests/run-make/fno-lto/rmake.rs new file mode 100644 index 0000000000000..db6fe7e6797f5 --- /dev/null +++ b/tests/run-make/fno-lto/rmake.rs @@ -0,0 +1,17 @@ +//@ needs-target-std +//@ ignore-msvc +//@ ignore-wasm +//@ needs-backends: gcc + +use run_make_support::rustc; + +fn main() { + rustc().input("main.rs").print("link-args").run_unchecked().assert_stdout_contains("-fno-lto"); + + rustc() + .input("main.rs") + .arg("-Clinker-plugin-lto") + .print("link-args") + .run_unchecked() + .assert_stdout_not_contains("-fno-lto"); +} diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index b25d892507907..f1a561e1291a5 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -83,6 +83,7 @@ fn main() { .normalize("libpanic_abort", "libpanic_unwind") .normalize(r#""[^"]*\/symbols.o""#, "\"/symbols.o\"") .normalize(r#""[^"]*\/raw-dylibs""#, "\"/raw-dylibs\"") + .normalize("\"-fno-lto\" ", "") .run(); } From f04ffd943c5e148f882fd251757e227c3f19128c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 15:51:06 +0200 Subject: [PATCH 1190/1309] we have to normalize stderr as well --- src/tools/miri/test-cargo-miri/run-test.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py index f593a16df9869..925dc288f220a 100755 --- a/src/tools/miri/test-cargo-miri/run-test.py +++ b/src/tools/miri/test-cargo-miri/run-test.py @@ -35,7 +35,7 @@ def cargo_miri(cmd, quiet = True, targets = None): return args -def normalize_stdout(str): +def normalize_output(str): str = str.replace("src\\", "src/") # normalize paths across platforms str = re.sub("\\b\\d+\\.\\d+s\\b", "$TIME", str) # the time keeps changing, obviously return str @@ -71,8 +71,8 @@ def test(name, cmd, stdout_ref, stderr_ref, stdin=b'', env=None): env=p_env, ) (stdout, stderr) = p.communicate(input=stdin) - stdout = normalize_stdout(stdout.decode("UTF-8")) - stderr = stderr.decode("UTF-8") + stdout = normalize_output(stdout.decode("UTF-8")) + stderr = normalize_output(stderr.decode("UTF-8")) stdout_matches = check_output(stdout, stdout_ref, "stdout") stderr_matches = check_output(stderr, stderr_ref, "stderr") From fa05b785dbcab87ed50008fe4dc12b490c6eb982 Mon Sep 17 00:00:00 2001 From: Jules Bertholet Date: Tue, 16 Jun 2026 10:02:54 -0400 Subject: [PATCH 1191/1309] Distinguish `repr(C)` ZSTs from others in ABI compatibility rules Co-Authored-By: Brian Smith Co-Authored-By: Ralf Jung --- library/core/src/primitive_docs.rs | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs index 4b84a9de4ce72..ded60d48ac799 100644 --- a/library/core/src/primitive_docs.rs +++ b/library/core/src/primitive_docs.rs @@ -1829,9 +1829,23 @@ const _: () = (); /// call will be valid ABI-wise. The callee receives the result of transmuting the function pointer /// from `fn()` to `fn(i32)`; that transmutation is itself a well-defined operation, it's just /// almost certainly UB to later call that function pointer.) -/// - Any two types with size 0 and alignment 1 are ABI-compatible. -/// - A `repr(transparent)` type `T` is ABI-compatible with its unique non-trivial field, i.e., the -/// unique field that doesn't have size 0 and alignment 1 (if there is such a field). +/// - Any two types with "trivial ABI" are ABI-compatible. +/// A type has trivial ABI if is satisfies all of the following: +/// - It has size 0. +/// - It has alignment 1. +/// - One of the following apply: +/// - It is a `repr(Rust)` `struct`, `enum`, or `union` (regardless of its fields, +/// regardless of whether `repr(Rust)` is specified explicitly or used via the implicit default, +/// and possibly with additional `repr` modifiers such as `packed`). +/// - It is a [prim@tuple] (regardless of its fields, and including [`()`][prim@unit]). +/// - It is a `repr(transparent)` `struct`, `enum`, or `union`, and all fields have trivial ABI. +/// - It is an array, and its element type has trivial ABI. (This requirement applies even to arrays of length 0.) +/// - It is [the never type `!`][never]. +// - It is a pattern type or an unsafe binder type, and the inner type has trivial ABI. +// (These are still unstable so intentionally not included in the user-visible doc comment, as their rules may change.) +/// - It is a function item type or closure type. +/// - A `repr(transparent)` type is ABI-compatible with its unique field that does not have trivial ABI +/// (as defined above), if such a field exists. (Note that if no such field exists, then the `repr(transparent)` type itself has trivial ABI, so the case above applies.) /// - `i32` is ABI-compatible with `NonZero`, and similar for all other integer types. /// - If `T` is guaranteed to be subject to the [null pointer /// optimization](option/index.html#representation), and `E` is an enum satisfying the following From bc1da7a1e304a4f7ae1fb2b99020a65c2ae197b6 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 2 Oct 2026 16:24:24 +0200 Subject: [PATCH 1192/1309] yeet compare-mode-coherence --- src/doc/rustc-dev-guide/src/tests/directives.md | 3 +-- src/tools/compiletest/src/common.rs | 1 - src/tools/compiletest/src/runtest.rs | 3 --- .../tidy/src/tests_revision_unpaired_stdout_stderr.rs | 11 ++--------- 4 files changed, 3 insertions(+), 15 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/directives.md b/src/doc/rustc-dev-guide/src/tests/directives.md index 22735c124fb43..a12b602d9c2d6 100644 --- a/src/doc/rustc-dev-guide/src/tests/directives.md +++ b/src/doc/rustc-dev-guide/src/tests/directives.md @@ -148,8 +148,7 @@ Some examples of `X` in `ignore-X` or `only-X`: - When particular debuggers are being tested: `cdb`, `gdb`, `lldb` - When particular debugger versions are matched: `ignore-gdb-version` - When the [parallel frontend] is enabled: `ignore-parallel-frontend` -- Specific [compare modes]: `compare-mode-polonius`, - `compare-mode-next-solver`, `compare-mode-next-solver-coherence`, +- Specific [compare modes]: `compare-mode-polonius`, `compare-mode-next-solver`, `compare-mode-split-dwarf`, `compare-mode-split-dwarf-single` - The two different test modes used by coverage tests: `ignore-coverage-map`, `ignore-coverage-run` diff --git a/src/tools/compiletest/src/common.rs b/src/tools/compiletest/src/common.rs index 1968f5eb73d4e..5d0750ddb92b7 100644 --- a/src/tools/compiletest/src/common.rs +++ b/src/tools/compiletest/src/common.rs @@ -173,7 +173,6 @@ string_enum! { pub(crate) enum CompareMode { Polonius => "polonius", NextSolver => "next-solver", - NextSolverCoherence => "next-solver-coherence", SplitDwarf => "split-dwarf", SplitDwarfSingle => "split-dwarf-single", } diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs index 0bb8a7003589c..263c8d5aded54 100644 --- a/src/tools/compiletest/src/runtest.rs +++ b/src/tools/compiletest/src/runtest.rs @@ -1943,9 +1943,6 @@ impl<'test> TestCx<'test> { Some(CompareMode::NextSolver) => { compiler.args(&["-Znext-solver"]); } - Some(CompareMode::NextSolverCoherence) => { - compiler.args(&["-Znext-solver=coherence"]); - } Some(CompareMode::SplitDwarf) if self.config.target.contains("windows") => { compiler.args(&["-Csplit-debuginfo=unpacked", "-Zunstable-options"]); } diff --git a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs index 4d9cb55138afa..88dc1ce1ae0a7 100644 --- a/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs +++ b/src/tools/tidy/src/tests_revision_unpaired_stdout_stderr.rs @@ -10,15 +10,8 @@ use crate::walk::*; // Should be kept in sync with `CompareMode` in `src/tools/compiletest/src/common.rs`, // as well as `run`. -const IGNORES: &[&str] = &[ - "polonius", - "chalk", - "split-dwarf", - "split-dwarf-single", - "next-solver-coherence", - "next-solver", - "run", -]; +const IGNORES: &[&str] = + &["polonius", "chalk", "split-dwarf", "split-dwarf-single", "next-solver", "run"]; const EXTENSIONS: &[&str] = &["stdout", "stderr"]; const SPECIAL_TEST: &str = "tests/ui/command/need-crate-arg-ignore-tidy.x.rs"; From 180aa923c5f2629046e8cd1cb2a7bed7f873536f Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Sat, 5 Sep 2026 16:03:17 +0330 Subject: [PATCH 1193/1309] preserve overflow in builtin Field candidates Signed-off-by: Amirhossein Akhlaghpour --- .../src/solve/trait_goals.rs | 82 ++++++++++--------- .../field-projection-overflow-coherence.rs | 55 +++++++++++++ ...field-projection-overflow-coherence.stderr | 18 ++++ .../not-field-if-unsized.next.stderr | 24 +++++- .../not-field-if-unsized.old.stderr | 8 +- .../not-field-if-unsized.rs | 8 +- .../sized.next.stderr | 61 ++++++++++++-- .../field_representing_types/sized.old.stderr | 12 +-- tests/ui/field_representing_types/sized.rs | 16 ++-- 9 files changed, 210 insertions(+), 74 deletions(-) create mode 100644 tests/ui/field_representing_types/field-projection-overflow-coherence.rs create mode 100644 tests/ui/field_representing_types/field-projection-overflow-coherence.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 19a09e99c7d64..35d51fde8224a 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -903,47 +903,49 @@ where if goal.predicate.polarity != ty::ClausePolarity::Positive { return Err(NoSolution.into()); } - if let ty::Adt(def, args) = goal.predicate.self_ty().kind() - && let Some(FieldInfo { base, ty, .. }) = - def.field_representing_type_info(ecx.cx(), args) - && { - let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized); - // FIXME: add better support for builtin impls of traits that check for the bounds - // on the trait definition in std. - - // NOTE: these bounds have to be kept in sync with the definition of the `Field` - // trait in `library/core/src/field.rs` as well as the old trait solver `fn - // assemble_candidates_for_field_trait` in - // `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`. - ecx.add_goal( - GoalSource::ImplWhereBound, - Goal { - param_env: goal.param_env, - predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()), - }, - )?; - ecx.add_goal( - GoalSource::ImplWhereBound, - Goal { - param_env: goal.param_env, - predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()), - }, - )?; - // FIXME(field_projections): This function does some questionable incomplete stuff by - // returning `Err(NoSolution)` on ambiguity. - ecx.try_evaluate_added_goals()? == Certainty::Yes - } - && match base.kind() { - ty::Adt(def, _) => def.is_struct() && !def.is_packed(), - ty::Tuple(..) => true, - _ => false, - } - { - ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc) - .enter(|ecx| ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)) - } else { - Err(NoSolution.into()) + + let ty::Adt(def, args) = goal.predicate.self_ty().kind() else { + return Err(NoSolution.into()); + }; + + let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(ecx.cx(), args) + else { + return Err(NoSolution.into()); + }; + + match base.kind() { + ty::Adt(def, _) if def.is_struct() && !def.is_packed() => {} + ty::Tuple(..) => {} + _ => return Err(NoSolution.into()), } + + ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { + let sized_trait = ecx.cx().require_trait_lang_item(SolverTraitLangItem::Sized); + + // FIXME: add better support for builtin impls of traits that check for the bounds + // on the trait definition in std. + // + // NOTE: these bounds have to be kept in sync with the definition of the `Field` + // trait in `library/core/src/field.rs` as well as the old trait solver `fn + // assemble_candidates_for_field_trait` in + // `compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs`. + ecx.add_goal( + GoalSource::ImplWhereBound, + Goal { + param_env: goal.param_env, + predicate: TraitRef::new(ecx.cx(), sized_trait, [base]).upcast(ecx.cx()), + }, + )?; + ecx.add_goal( + GoalSource::ImplWhereBound, + Goal { + param_env: goal.param_env, + predicate: TraitRef::new(ecx.cx(), sized_trait, [ty]).upcast(ecx.cx()), + }, + )?; + + ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) + }) } } diff --git a/tests/ui/field_representing_types/field-projection-overflow-coherence.rs b/tests/ui/field_representing_types/field-projection-overflow-coherence.rs new file mode 100644 index 0000000000000..ea95e12a6d4bf --- /dev/null +++ b/tests/ui/field_representing_types/field-projection-overflow-coherence.rs @@ -0,0 +1,55 @@ +//@ edition: 2021 +//@ compile-flags: -Znext-solver -Arecursion_depth_exceeding_limit + +#![forbid(unsafe_code)] +#![feature(field_projections)] +#![allow(incomplete_features)] + +use core::field::{Field, field_of}; + +trait Chain { + type A; +} + +impl Chain for () { + type A = u8; +} + +struct Link(T); + +impl Chain for Link { + type A = ::A; +} + +type L4 = Link>>>; +type L16 = L4>>>; +type L64 = L16>>>; +type Deep = L64>>; // 192 links + +struct S { + f: ::A, +} + +trait Tr { + type Out; +} + +impl Tr for S +where + field_of!(S, f): Field, +{ + type Out = u8; +} + +impl Tr for S { //~ ERROR conflicting implementations of trait `Tr` + type Out = [u8; 16]; +} + +fn poly() -> as Tr>::Out { + 0 +} + +fn main() { + let v = poly::(); + println!("{:?}", v); +} diff --git a/tests/ui/field_representing_types/field-projection-overflow-coherence.stderr b/tests/ui/field_representing_types/field-projection-overflow-coherence.stderr new file mode 100644 index 0000000000000..d53819445a083 --- /dev/null +++ b/tests/ui/field_representing_types/field-projection-overflow-coherence.stderr @@ -0,0 +1,18 @@ +error[E0119]: conflicting implementations of trait `Tr` for type `S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + --> $DIR/field-projection-overflow-coherence.rs:44:1 + | +LL | / impl Tr for S +LL | | where +LL | | field_of!(S, f): Field, + | |______________________________- first implementation here +... +LL | impl Tr for S { + | ^^^^^^^^^^^^^^^^^^^ conflicting implementation for `S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` + | + = note: overflow evaluating the requirement `Link>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Chain` + = note: overflow evaluating the requirement `field_of!(S>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>, f): Field` + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`field_projection_overflow_coherence`) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr index 967f6115c1ac1..be6c49ceb6242 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr +++ b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr @@ -1,21 +1,37 @@ -error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time --> $DIR/not-field-if-unsized.rs:17:20 | LL | assert_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = help: within `field_of!(MyStruct, 0)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` +note: required because it appears within the type `MyStruct` + --> $DIR/not-field-if-unsized.rs:10:12 + | +LL | pub struct MyStruct(usize, dyn Trait); + | ^^^^^^^^ +note: required because it appears within the type `field_of!(MyStruct, 0)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` --> $DIR/not-field-if-unsized.rs:12:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` -error[E0277]: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied +error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time --> $DIR/not-field-if-unsized.rs:21:20 | LL | assert_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)` + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `field_of!(MyStruct, 1)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` +note: required because it appears within the type `MyStruct` + --> $DIR/not-field-if-unsized.rs:10:12 | +LL | pub struct MyStruct(usize, dyn Trait); + | ^^^^^^^^ +note: required because it appears within the type `field_of!(MyStruct, 1)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` --> $DIR/not-field-if-unsized.rs:12:20 | diff --git a/tests/ui/field_representing_types/not-field-if-unsized.old.stderr b/tests/ui/field_representing_types/not-field-if-unsized.old.stderr index 967f6115c1ac1..693f1353253bd 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.old.stderr +++ b/tests/ui/field_representing_types/not-field-if-unsized.old.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied --> $DIR/not-field-if-unsized.rs:17:20 | -LL | assert_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` +LL | ..._field::(); + | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` | note: required by a bound in `assert_field` --> $DIR/not-field-if-unsized.rs:12:20 @@ -13,8 +13,8 @@ LL | fn assert_field() {} error[E0277]: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied --> $DIR/not-field-if-unsized.rs:21:20 | -LL | assert_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)` +LL | ..._field::(); + | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)` | note: required by a bound in `assert_field` --> $DIR/not-field-if-unsized.rs:12:20 diff --git a/tests/ui/field_representing_types/not-field-if-unsized.rs b/tests/ui/field_representing_types/not-field-if-unsized.rs index 8f28443d7968c..82a3c385cb799 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.rs +++ b/tests/ui/field_representing_types/not-field-if-unsized.rs @@ -14,10 +14,10 @@ fn assert_field() {} fn main() { // FIXME(FRTs): this requires relaxing the `Base: ?Sized` bound in the // `Field` trait & compiler changes. - assert_field::(); - //~^ ERROR: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied [E0277] + assert_field::(); //[next]~ ERROR: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied [E0277] // FIXME(FRTs): improve this error message, point to the `dyn Trait` span. - assert_field::(); - //~^ ERROR: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied [E0277] + assert_field::(); //[next]~ ERROR: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied [E0277] } diff --git a/tests/ui/field_representing_types/sized.next.stderr b/tests/ui/field_representing_types/sized.next.stderr index ed7e6955c0762..a39538e4bc6c1 100644 --- a/tests/ui/field_representing_types/sized.next.stderr +++ b/tests/ui/field_representing_types/sized.next.stderr @@ -1,45 +1,90 @@ -error[E0277]: the trait bound `field_of!(Generic, count): Field` is not satisfied +error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/sized.rs:20:19 | +LL | fn generic() { + | - this type parameter needs to be `Sized` LL | impls_field::, count)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, count)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | +note: required because it appears within the type `Generic` + --> $DIR/sized.rs:14:12 + | +LL | pub struct Generic { + | ^^^^^^^ +note: required because it appears within the type `field_of!(Generic, count)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn generic() { +LL + fn generic() { + | -error[E0277]: the trait bound `field_of!(Generic, last): Field` is not satisfied +error[E0277]: the size for values of type `T` cannot be known at compilation time --> $DIR/sized.rs:22:19 | +LL | fn generic() { + | - this type parameter needs to be `Sized` +... LL | impls_field::, last)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, last)` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | +note: required because it appears within the type `Generic` + --> $DIR/sized.rs:14:12 | +LL | pub struct Generic { + | ^^^^^^^ +note: required because it appears within the type `field_of!(Generic, last)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` +help: consider removing the `?Sized` bound to make the type parameter `Sized` + | +LL - fn generic() { +LL + fn generic() { + | -error[E0277]: the trait bound `field_of!(MyDST, count): Field` is not satisfied +error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time --> $DIR/sized.rs:32:19 | LL | impls_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, count)` + | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | + = help: within `field_of!(MyDST, count)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` +note: required because it appears within the type `MyDST` + --> $DIR/sized.rs:9:12 + | +LL | pub struct MyDST { + | ^^^^^ +note: required because it appears within the type `field_of!(MyDST, count)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` -error[E0277]: the trait bound `field_of!(MyDST, last): Field` is not satisfied +error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time --> $DIR/sized.rs:34:19 | LL | impls_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, last)` + | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time + | + = help: within `field_of!(MyDST, last)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` +note: required because it appears within the type `MyDST` + --> $DIR/sized.rs:9:12 | +LL | pub struct MyDST { + | ^^^^^ +note: required because it appears within the type `field_of!(MyDST, last)` + --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 | diff --git a/tests/ui/field_representing_types/sized.old.stderr b/tests/ui/field_representing_types/sized.old.stderr index ed7e6955c0762..f86bf6ddd53ee 100644 --- a/tests/ui/field_representing_types/sized.old.stderr +++ b/tests/ui/field_representing_types/sized.old.stderr @@ -1,8 +1,8 @@ error[E0277]: the trait bound `field_of!(Generic, count): Field` is not satisfied --> $DIR/sized.rs:20:19 | -LL | impls_field::, count)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, count)` +LL | ...::, count)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, count)` | note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 @@ -13,8 +13,8 @@ LL | fn impls_field() {} error[E0277]: the trait bound `field_of!(Generic, last): Field` is not satisfied --> $DIR/sized.rs:22:19 | -LL | impls_field::, last)>(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, last)` +LL | ...d::, last)>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, last)` | note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 @@ -25,8 +25,8 @@ LL | fn impls_field() {} error[E0277]: the trait bound `field_of!(MyDST, count): Field` is not satisfied --> $DIR/sized.rs:32:19 | -LL | impls_field::(); - | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, count)` +LL | ...field::(); + | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, count)` | note: required by a bound in `impls_field` --> $DIR/sized.rs:38:19 diff --git a/tests/ui/field_representing_types/sized.rs b/tests/ui/field_representing_types/sized.rs index 22499e32f33b2..658dd5f24a131 100644 --- a/tests/ui/field_representing_types/sized.rs +++ b/tests/ui/field_representing_types/sized.rs @@ -17,10 +17,10 @@ pub struct Generic { } fn generic() { - impls_field::, count)>(); - //~^ ERROR: the trait bound `field_of!(Generic, count): Field` is not satisfied [E0277] - impls_field::, last)>(); - //~^ ERROR: the trait bound `field_of!(Generic, last): Field` is not satisfied [E0277] + impls_field::, count)>(); //[next]~ ERROR: the size for values of type `T` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(Generic, count): Field` is not satisfied [E0277] + impls_field::, last)>(); //[next]~ ERROR: the size for values of type `T` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(Generic, last): Field` is not satisfied [E0277] } fn ok() { @@ -29,10 +29,10 @@ fn ok() { } fn main() { - impls_field::(); - //~^ ERROR: the trait bound `field_of!(MyDST, count): Field` is not satisfied [E0277] - impls_field::(); - //~^ ERROR: the trait bound `field_of!(MyDST, last): Field` is not satisfied [E0277] + impls_field::(); //[next]~ ERROR: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(MyDST, count): Field` is not satisfied [E0277] + impls_field::(); //[next]~ ERROR: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time [E0277] + //[old]~^ ERROR: the trait bound `field_of!(MyDST, last): Field` is not satisfied [E0277] } fn impls_field() {} From a785a9fbc1e5d0eaad7ed85ad8d769399a5d49f9 Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Fri, 2 Oct 2026 17:09:40 +0330 Subject: [PATCH 1194/1309] make Field base kind invariant explicit Signed-off-by: Amirhossein Akhlaghpour --- compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 35d51fde8224a..32eecd4e44b38 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -915,8 +915,9 @@ where match base.kind() { ty::Adt(def, _) if def.is_struct() && !def.is_packed() => {} + ty::Adt(..) => return Err(NoSolution.into()), ty::Tuple(..) => {} - _ => return Err(NoSolution.into()), + _ => unreachable!(), } ecx.probe_builtin_trait_candidate(BuiltinImplSource::Misc).enter(|ecx| { From 01ad9b75b12127613f2616ff9569950cd54dbc8b Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Fri, 2 Oct 2026 18:45:48 +0330 Subject: [PATCH 1195/1309] update Field UI stderr after diagnostic change Signed-off-by: Amirhossein Akhlaghpour --- .../not-field-if-unsized.next.stderr | 8 +++---- .../sized.next.stderr | 24 ++++++++++++------- 2 files changed, 20 insertions(+), 12 deletions(-) diff --git a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr index be6c49ceb6242..e639d01dc176a 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr +++ b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr @@ -6,10 +6,10 @@ LL | assert_field::(); | = help: within `field_of!(MyStruct, 0)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required because it appears within the type `MyStruct` - --> $DIR/not-field-if-unsized.rs:10:12 + --> $DIR/not-field-if-unsized.rs:10:28 | LL | pub struct MyStruct(usize, dyn Trait); - | ^^^^^^^^ + | ^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyStruct, 0)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` @@ -26,10 +26,10 @@ LL | assert_field::(); | = help: within `field_of!(MyStruct, 1)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required because it appears within the type `MyStruct` - --> $DIR/not-field-if-unsized.rs:10:12 + --> $DIR/not-field-if-unsized.rs:10:28 | LL | pub struct MyStruct(usize, dyn Trait); - | ^^^^^^^^ + | ^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyStruct, 1)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` diff --git a/tests/ui/field_representing_types/sized.next.stderr b/tests/ui/field_representing_types/sized.next.stderr index a39538e4bc6c1..254603f09b960 100644 --- a/tests/ui/field_representing_types/sized.next.stderr +++ b/tests/ui/field_representing_types/sized.next.stderr @@ -7,10 +7,12 @@ LL | impls_field::, count)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `Generic` - --> $DIR/sized.rs:14:12 + --> $DIR/sized.rs:16:5 | LL | pub struct Generic { - | ^^^^^^^ +LL | count: usize, +LL | last: T, + | ^^^^^^^ required by this field note: required because it appears within the type `field_of!(Generic, count)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` @@ -34,10 +36,12 @@ LL | impls_field::, last)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `Generic` - --> $DIR/sized.rs:14:12 + --> $DIR/sized.rs:16:5 | LL | pub struct Generic { - | ^^^^^^^ +LL | count: usize, +LL | last: T, + | ^^^^^^^ required by this field note: required because it appears within the type `field_of!(Generic, last)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` @@ -59,10 +63,12 @@ LL | impls_field::(); | = help: within `field_of!(MyDST, count)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` note: required because it appears within the type `MyDST` - --> $DIR/sized.rs:9:12 + --> $DIR/sized.rs:11:5 | LL | pub struct MyDST { - | ^^^^^ +LL | count: usize, +LL | last: dyn Debug, + | ^^^^^^^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyDST, count)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` @@ -79,10 +85,12 @@ LL | impls_field::(); | = help: within `field_of!(MyDST, last)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` note: required because it appears within the type `MyDST` - --> $DIR/sized.rs:9:12 + --> $DIR/sized.rs:11:5 | LL | pub struct MyDST { - | ^^^^^ +LL | count: usize, +LL | last: dyn Debug, + | ^^^^^^^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyDST, last)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` From ef66a06b77c31837ffb1ed912ca4d92c1e8b8e0b Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Fri, 2 Oct 2026 17:21:02 +0200 Subject: [PATCH 1196/1309] run some more tests natively --- src/tools/miri/tests/pass/shims/env/current_dir.rs | 1 + src/tools/miri/tests/pass/shims/env/current_exe.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/tools/miri/tests/pass/shims/env/current_dir.rs b/src/tools/miri/tests/pass/shims/env/current_dir.rs index ca90912eabc54..e61ab32a9ea10 100644 --- a/src/tools/miri/tests/pass/shims/env/current_dir.rs +++ b/src/tools/miri/tests/pass/shims/env/current_dir.rs @@ -1,4 +1,5 @@ //@compile-flags: -Zmiri-disable-isolation +//@run-native use std::env; use std::io::ErrorKind; diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 36138bf9c4df7..1ba001094ff0c 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -1,5 +1,6 @@ //@ignore-target: freebsd illumos solaris # we don't have the shims this needs here //@compile-flags: -Zmiri-disable-isolation +//@run-native use std::env; fn main() { From b999348c3543e43ee0a47668bddd4662df21b8bb Mon Sep 17 00:00:00 2001 From: DeaconSteiner Date: Fri, 2 Oct 2026 09:25:49 -0600 Subject: [PATCH 1197/1309] Fix capitalisation issues in fmt documentation --- library/core/src/fmt/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs index 55296a62e947a..1f1b581c5e546 100644 --- a/library/core/src/fmt/mod.rs +++ b/library/core/src/fmt/mod.rs @@ -1611,7 +1611,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// fmt::write(&mut output, format_args!("Hello {}!", "world")) -/// .expect("Writing to a `String` should not fail"); +/// .expect("writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// @@ -1622,7 +1622,7 @@ pub trait UpperExp: PointeeSized { /// /// let mut output = String::new(); /// write!(&mut output, "Hello {}!", "world") -/// .expect("Writing to a `String` should not fail"); +/// .expect("writing to a `String` should not fail"); /// assert_eq!(output, "Hello world!"); /// ``` /// From df07926739a5d80e6b439a136ca34dce5d120657 Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 2 Oct 2026 15:42:30 +0000 Subject: [PATCH 1198/1309] explicitly handle tests that pass with -Znext-solver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Rémy Rakic --- ...terns-subtyping-ice-104779.current.stderr} | 10 +-- ...-patterns-subtyping-ice-104779.next.stderr | 14 ++++ ...que-types-patterns-subtyping-ice-104779.rs | 13 +++- ...err => require-next-solver.current.stderr} | 2 +- .../const-generics/gca/require-next-solver.rs | 6 +- tests/ui/error-codes/E0275.current.stderr | 37 +++++++++ tests/ui/error-codes/E0275.next.stderr | 16 ++++ tests/ui/error-codes/E0275.rs | 11 ++- tests/ui/error-codes/E0275.stderr | 20 ----- .../{rpit.stderr => rpit.current.stderr} | 2 +- tests/ui/explicit-tail-calls/rpit.rs | 7 +- .../issue-71955.current.stderr | 78 +++++++++++++++++++ .../normalize-under-binder/issue-71955.rs | 52 +++++++------ .../normalize-under-binder/issue-71955.stderr | 78 ------------------- ...captured-non-universal-region.infer.stderr | 2 +- ...ining-use-captured-non-universal-region.rs | 9 ++- ...aptured-non-universal-region.statik.stderr | 4 +- ...-ret-pos-invalid-binder.edition2015.stderr | 17 ++++ ...-ret-pos-invalid-binder.edition2024.stderr | 17 ++++ ...l-fn-in-ret-pos-invalid-binder.next.stderr | 26 +++++++ .../impl-fn-in-ret-pos-invalid-binder.rs | 16 ++++ .../impl-fn-in-ret-pos-invalid-binder.stderr | 17 ++++ ...fn-predefined-lifetimes.edition2015.stderr | 14 +++- ...fn-predefined-lifetimes.edition2024.stderr | 14 +++- .../impl-fn-predefined-lifetimes.rs | 27 +++++-- ...rr => recursive-ice-101862.current.stderr} | 4 +- .../recursive-ice-101862.next.stderr | 14 ++++ tests/ui/impl-trait/recursive-ice-101862.rs | 6 +- ...ound.stderr => early_bound.current.stderr} | 4 +- tests/ui/impl-trait/rpit/early_bound.rs | 6 +- ...non-defining-use-lifetimes.current.stderr} | 8 +- .../rpit/non-defining-use-lifetimes.rs | 10 ++- ...stderr => non-defining-use.current.stderr} | 4 +- tests/ui/impl-trait/rpit/non-defining-use.rs | 8 +- ...err => generator_capture_2.current.stderr} | 6 +- ...tor_capture_.rs => generator_capture_2.rs} | 8 +- ...not-async-closure-simplified.narrow.stderr | 8 +- ...iter-macro-not-async-closure-simplified.rs | 8 +- ...o-not-async-closure-simplified.wide.stderr | 8 +- ...er-macro-not-async-closure.current.stderr} | 48 ++++++------ .../iterators/iter-macro-not-async-closure.rs | 18 +++-- ...ranches.stderr => branches.current.stderr} | 2 +- .../ui/lazy-type-alias-impl-trait/branches.rs | 6 +- ...sion3.stderr => recursion3.current.stderr} | 4 +- .../lazy-type-alias-impl-trait/recursion3.rs | 8 +- ...derr => conflicting-bounds.current.stderr} | 2 +- tests/ui/lifetimes/conflicting-bounds.rs | 12 ++- ...trait-with-static-lifetime.current.stderr} | 8 +- ...erlap-marker-trait-with-static-lifetime.rs | 7 +- ...t-with-underscore-lifetime.current.stderr} | 8 +- ...p-marker-trait-with-underscore-lifetime.rs | 9 ++- .../pretty-print-opaque-no-feat.rs | 13 ++-- .../pretty-print-opaque-no-feat.stderr | 6 +- ...-closure-external-lifetime.current.stderr} | 4 +- ...d-in-closure-external-lifetime.next.stderr | 14 ++++ .../defined-in-closure-external-lifetime.rs | 13 +++- .../generic-not-strictly-equal.basic.stderr | 2 +- ...t-strictly-equal.member_constraints.stderr | 2 +- ...neric-not-strictly-equal.next_basic.stderr | 8 ++ ...ictly-equal.next_member_constraints.stderr | 8 ++ .../generic-not-strictly-equal.rs | 14 ++-- ... impl_trait_for_tait_bound.current.stderr} | 6 +- .../impl_trait_for_tait_bound.rs | 6 +- .../multiple-def-uses-in-one-fn-infer.rs | 15 ---- ...f-uses-in-one-fn-int-infer.current.stderr} | 2 +- .../multiple-def-uses-in-one-fn-int-infer.rs | 22 ++++++ ....stderr => param_mismatch4.current.stderr} | 2 +- .../type-alias-impl-trait/param_mismatch4.rs | 6 +- ...cal.stderr => reveal_local.current.stderr} | 4 +- .../ui/type-alias-impl-trait/reveal_local.rs | 6 +- ...taint-polymorphization-ice.current.stderr} | 2 +- .../taint-polymorphization-ice.rs | 23 ++++++ tests/ui/type-alias-impl-trait/taint.rs | 18 ----- 73 files changed, 638 insertions(+), 301 deletions(-) rename tests/ui/borrowck/{opaque-types-patterns-subtyping-ice-104779.stderr => opaque-types-patterns-subtyping-ice-104779.current.stderr} (75%) create mode 100644 tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.next.stderr rename tests/ui/const-generics/gca/{require-next-solver.stderr => require-next-solver.current.stderr} (85%) create mode 100644 tests/ui/error-codes/E0275.current.stderr create mode 100644 tests/ui/error-codes/E0275.next.stderr delete mode 100644 tests/ui/error-codes/E0275.stderr rename tests/ui/explicit-tail-calls/{rpit.stderr => rpit.current.stderr} (93%) create mode 100644 tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr delete mode 100644 tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr create mode 100644 tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2015.stderr create mode 100644 tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2024.stderr create mode 100644 tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.next.stderr create mode 100644 tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.rs create mode 100644 tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.stderr rename tests/ui/impl-trait/{recursive-ice-101862.stderr => recursive-ice-101862.current.stderr} (92%) create mode 100644 tests/ui/impl-trait/recursive-ice-101862.next.stderr rename tests/ui/impl-trait/rpit/{early_bound.stderr => early_bound.current.stderr} (85%) rename tests/ui/impl-trait/rpit/{non-defining-use-lifetimes.stderr => non-defining-use-lifetimes.current.stderr} (85%) rename tests/ui/impl-trait/rpit/{non-defining-use.stderr => non-defining-use.current.stderr} (94%) rename tests/ui/iterators/{generator_capture_.stderr => generator_capture_2.current.stderr} (80%) rename tests/ui/iterators/{generator_capture_.rs => generator_capture_2.rs} (70%) rename tests/ui/iterators/{iter-macro-not-async-closure.stderr => iter-macro-not-async-closure.current.stderr} (71%) rename tests/ui/lazy-type-alias-impl-trait/{branches.stderr => branches.current.stderr} (94%) rename tests/ui/lazy-type-alias-impl-trait/{recursion3.stderr => recursion3.current.stderr} (89%) rename tests/ui/lifetimes/{conflicting-bounds.stderr => conflicting-bounds.current.stderr} (91%) rename tests/ui/marker_trait_attr/{overlap-marker-trait-with-static-lifetime.stderr => overlap-marker-trait-with-static-lifetime.current.stderr} (77%) rename tests/ui/marker_trait_attr/{overlap-marker-trait-with-underscore-lifetime.stderr => overlap-marker-trait-with-underscore-lifetime.current.stderr} (74%) rename tests/ui/type-alias-impl-trait/{defined-in-closure-external-lifetime.stderr => defined-in-closure-external-lifetime.current.stderr} (86%) create mode 100644 tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.next.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_basic.stderr create mode 100644 tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_member_constraints.stderr rename tests/ui/type-alias-impl-trait/{impl_trait_for_tait_bound.stderr => impl_trait_for_tait_bound.current.stderr} (78%) delete mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs rename tests/ui/type-alias-impl-trait/{multiple-def-uses-in-one-fn-infer.stderr => multiple-def-uses-in-one-fn-int-infer.current.stderr} (86%) create mode 100644 tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.rs rename tests/ui/type-alias-impl-trait/{param_mismatch4.stderr => param_mismatch4.current.stderr} (90%) rename tests/ui/type-alias-impl-trait/{reveal_local.stderr => reveal_local.current.stderr} (86%) rename tests/ui/type-alias-impl-trait/{taint.stderr => taint-polymorphization-ice.current.stderr} (88%) create mode 100644 tests/ui/type-alias-impl-trait/taint-polymorphization-ice.rs delete mode 100644 tests/ui/type-alias-impl-trait/taint.rs diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.current.stderr similarity index 75% rename from tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr rename to tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.current.stderr index 887cb14a76935..1da79e2dbe7a9 100644 --- a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.stderr +++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.current.stderr @@ -1,5 +1,5 @@ warning: function cannot return without recursing - --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:12:1 + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:17:1 | LL | fn foo() -> impl Sized { | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing @@ -11,13 +11,13 @@ LL | match foo() { = note: `#[warn(unconditional_recursion)]` on by default error: higher-ranked subtype error - --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15 + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:20:15 | LL | match foo() { | ^^^^^ error: higher-ranked subtype error - --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:15:15 + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:20:15 | LL | match foo() { | ^^^^^ @@ -25,13 +25,13 @@ LL | match foo() { = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: higher-ranked subtype error - --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13 + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:23:13 | LL | Subtype::Bar => (), | ^^^^^^^^^^^^ error: higher-ranked subtype error - --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:18:13 + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:23:13 | LL | Subtype::Bar => (), | ^^^^^^^^^^^^ diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.next.stderr b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.next.stderr new file mode 100644 index 0000000000000..9693391617a2e --- /dev/null +++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.next.stderr @@ -0,0 +1,14 @@ +warning: function cannot return without recursing + --> $DIR/opaque-types-patterns-subtyping-ice-104779.rs:17:1 + | +LL | fn foo() -> impl Sized { + | ^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +... +LL | match foo() { + | ----- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs index b9e729bff62a0..eddd25e3e30e9 100644 --- a/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs +++ b/tests/ui/borrowck/opaque-types-patterns-subtyping-ice-104779.rs @@ -1,3 +1,8 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + // issue: rust-lang/rust#104779 // ICE region infer, IndexMap: key not found @@ -13,11 +18,11 @@ fn foo() -> impl Sized { //~^ WARN function cannot return without recursing loop { match foo() { - //~^ ERROR higher-ranked subtype error - //~^^ ERROR higher-ranked subtype error + //[current]~^ ERROR higher-ranked subtype error + //[current]~^^ ERROR higher-ranked subtype error Subtype::Bar => (), - //~^ ERROR higher-ranked subtype error - //~^^ ERROR higher-ranked subtype error + //[current]~^ ERROR higher-ranked subtype error + //[current]~^^ ERROR higher-ranked subtype error Supertype::Var(x) => {} } } diff --git a/tests/ui/const-generics/gca/require-next-solver.stderr b/tests/ui/const-generics/gca/require-next-solver.current.stderr similarity index 85% rename from tests/ui/const-generics/gca/require-next-solver.stderr rename to tests/ui/const-generics/gca/require-next-solver.current.stderr index 717b561993a17..06e32d0713b7e 100644 --- a/tests/ui/const-generics/gca/require-next-solver.stderr +++ b/tests/ui/const-generics/gca/require-next-solver.current.stderr @@ -1,5 +1,5 @@ error: `gca_const_items` requires -Znext-solver=globally to be enabled - --> $DIR/require-next-solver.rs:2:12 + --> $DIR/require-next-solver.rs:6:12 | LL | #![feature(gca_const_items)] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/require-next-solver.rs b/tests/ui/const-generics/gca/require-next-solver.rs index ce2fdea3a6328..2cd16ab13e70c 100644 --- a/tests/ui/const-generics/gca/require-next-solver.rs +++ b/tests/ui/const-generics/gca/require-next-solver.rs @@ -1,4 +1,8 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(gca_min_const_items)] #![feature(gca_const_items)] -//~^ ERROR next-solver +//[current]~^ ERROR next-solver fn main() {} diff --git a/tests/ui/error-codes/E0275.current.stderr b/tests/ui/error-codes/E0275.current.stderr new file mode 100644 index 0000000000000..cfefaac27188b --- /dev/null +++ b/tests/ui/error-codes/E0275.current.stderr @@ -0,0 +1,37 @@ +error[E0275]: overflow evaluating the requirement `Bar>>>>>>: Foo` + --> $DIR/E0275.rs:10:33 + | +LL | impl Foo for T where Bar: Foo {} + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) +note: required for `Bar>>>>>>>>>>>>` to implement `Foo` + --> $DIR/E0275.rs:10:9 + | +LL | impl Foo for T where Bar: Foo {} + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: 126 redundant requirements hidden + = note: required for `Bar` to implement `Foo` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0275.long-type-$LONG_TYPE_HASH.txt' + = note: consider using `--verbose` to print the full type name to the console + +error[E0275]: overflow evaluating the requirement `Bar>>>>>>: Foo` + --> $DIR/E0275.rs:13:14 + | +LL | fn is_foo() {} + | ^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) +note: required for `Bar>>>>>>>>>>>>` to implement `Foo` + --> $DIR/E0275.rs:10:9 + | +LL | impl Foo for T where Bar: Foo {} + | ^^^ ^ --- unsatisfied trait bound introduced here + = note: 126 redundant requirements hidden + = note: required for `T` to implement `Foo` + = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0275.long-type-$LONG_TYPE_HASH.txt' + = note: consider using `--verbose` to print the full type name to the console + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/error-codes/E0275.next.stderr b/tests/ui/error-codes/E0275.next.stderr new file mode 100644 index 0000000000000..d883d64dd2970 --- /dev/null +++ b/tests/ui/error-codes/E0275.next.stderr @@ -0,0 +1,16 @@ +error[E0275]: overflow evaluating the requirement `(): Foo` + --> $DIR/E0275.rs:16:14 + | +LL | is_foo::<()>(); + | ^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) +note: required by a bound in `is_foo` + --> $DIR/E0275.rs:13:14 + | +LL | fn is_foo() {} + | ^^^ required by this bound in `is_foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/error-codes/E0275.rs b/tests/ui/error-codes/E0275.rs index 98d4a3c01b9a2..e796b87b18784 100644 --- a/tests/ui/error-codes/E0275.rs +++ b/tests/ui/error-codes/E0275.rs @@ -1,9 +1,18 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + //@ compile-flags: -Zwrite-long-types-to-disk=yes trait Foo {} struct Bar(T); -impl Foo for T where Bar: Foo {} //~ ERROR E0275 +impl Foo for T where Bar: Foo {} +//[current]~^ ERROR E0275 +fn is_foo() {} +//[current]~^ ERROR E0275 fn main() { + is_foo::<()>(); + //[next]~^ ERROR E0275 } diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr deleted file mode 100644 index 36175f636d6fb..0000000000000 --- a/tests/ui/error-codes/E0275.stderr +++ /dev/null @@ -1,20 +0,0 @@ -error[E0275]: overflow evaluating the requirement `Bar>>>>>>: Foo` - --> $DIR/E0275.rs:6:33 - | -LL | impl Foo for T where Bar: Foo {} - | ^^^ - | - = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`) -note: required for `Bar>>>>>>>>>>>>` to implement `Foo` - --> $DIR/E0275.rs:6:9 - | -LL | impl Foo for T where Bar: Foo {} - | ^^^ ^ --- unsatisfied trait bound introduced here - = note: 126 redundant requirements hidden - = note: required for `Bar` to implement `Foo` - = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0275.long-type-$LONG_TYPE_HASH.txt' - = note: consider using `--verbose` to print the full type name to the console - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/explicit-tail-calls/rpit.stderr b/tests/ui/explicit-tail-calls/rpit.current.stderr similarity index 93% rename from tests/ui/explicit-tail-calls/rpit.stderr rename to tests/ui/explicit-tail-calls/rpit.current.stderr index 9c181db8b8019..ffb82c60ce844 100644 --- a/tests/ui/explicit-tail-calls/rpit.stderr +++ b/tests/ui/explicit-tail-calls/rpit.current.stderr @@ -1,5 +1,5 @@ error: mismatched signatures - --> $DIR/rpit.rs:14:5 + --> $DIR/rpit.rs:19:5 | LL | become foo(x, y); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit-tail-calls/rpit.rs b/tests/ui/explicit-tail-calls/rpit.rs index 0d1f2c78fd13d..550a88996072f 100644 --- a/tests/ui/explicit-tail-calls/rpit.rs +++ b/tests/ui/explicit-tail-calls/rpit.rs @@ -1,3 +1,8 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + #![feature(explicit_tail_calls)] #![expect(incomplete_features)] @@ -12,7 +17,7 @@ fn foo(x: u32, y: u32) -> u32 { fn bar(x: u32, y: u32) -> impl ToString { become foo(x, y); - //~^ ERROR mismatched signatures + //[current]~^ ERROR mismatched signatures } fn main() { diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr new file mode 100644 index 0000000000000..83a7a9836a1ad --- /dev/null +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr @@ -0,0 +1,78 @@ +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-71955.rs:47:5 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo`... +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ---------------------------------------------------------- unsatisfied where-clause on `foo` +... +LL | foo(bar, |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(bar, |s: &'b &'c str| s.len() == 5); + | +++++++++++++ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-71955.rs:47:5 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo`... +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ---- unsatisfied where-clause on `foo` +... +LL | foo(bar, |s| s.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(bar, |s: &'b &'c str| s.len() == 5); + | +++++++++++++ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-71955.rs:50:5 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo`... +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ---------------------------------------------------------- unsatisfied where-clause on `foo` +... +LL | foo(baz, |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(baz, |s: &'b Wrapper<'c>| s.0.len() == 5); + | +++++++++++++++++ + +error: implementation of `FnOnce` is not general enough + --> $DIR/issue-71955.rs:50:5 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo`... +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ---- unsatisfied where-clause on `foo` +... +LL | foo(baz, |s| s.0.len() == 5); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` +help: consider adding an explicit type annotation to the closure's argument + | +LL | foo(baz, |s: &'b Wrapper<'c>| s.0.len() == 5); + | +++++++++++++++++ + +error: aborting due to 4 previous errors + diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs index a44ed9e5ef59b..5f7e6cee4ebcf 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.rs @@ -1,34 +1,36 @@ -//@ check-fail -#![feature(rustc_attrs)] +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +// A regression test which failed with the old solver. The old solver +// ended up normalizing `>::Output` to `?t` because +// it did not eagerly prove the nested `F: Fn(&'s str) -> (&'s str, T)` +// where-clause. +// +// This means we don't map the `'!c` back to a bound var after +// inferring `?t`. We only normalize inside of binders with the new +// solver if the resulting term does not reference any inference +// variables which can later be constrained to mention something from +// the binder we're in. This is necessary as these placeholders would +// then leak from normalization. trait Parser<'s> { type Output; - - fn call(&self, input: &'s str) -> (&'s str, Self::Output); } impl<'s, F, T> Parser<'s> for F -where F: Fn(&'s str) -> (&'s str, T) { +where + F: Fn(&'s str) -> (&'s str, T), +{ type Output = T; - fn call(&self, input: &'s str) -> (&'s str, T) { - self(input) - } } -fn foo( - f1: F1, - base: &'static str, - f2: F2 -) +fn foo(f1: F1, f2: F2) where F1: for<'a> Parser<'a>, - F2: FnOnce(&::Output) -> bool + F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, { - let s: String = base.to_owned(); - let str_ref = s.as_ref(); - let (remaining, produced) = f1.call(str_ref); - assert!(f2(&produced)); - assert_eq!(remaining.len(), 0); } struct Wrapper<'a>(&'a str); @@ -42,10 +44,10 @@ fn main() { (&s[..1], Wrapper(&s[..])) } - foo(bar, "string", |s| s.len() == 5); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough - foo(baz, "string", |s| s.0.len() == 5); - //~^ ERROR implementation of `FnOnce` is not general enough - //~| ERROR implementation of `FnOnce` is not general enough + foo(bar, |s| s.len() == 5); + //[current]~^ ERROR implementation of `FnOnce` is not general enough + //[current]~| ERROR implementation of `FnOnce` is not general enough + foo(baz, |s| s.0.len() == 5); + //[current]~^ ERROR implementation of `FnOnce` is not general enough + //[current]~| ERROR implementation of `FnOnce` is not general enough } diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr deleted file mode 100644 index fa524168e12e7..0000000000000 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.stderr +++ /dev/null @@ -1,78 +0,0 @@ -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-71955.rs:45:5 - | -LL | fn foo( - | --- due to a where-clause on `foo`... -... -LL | F2: FnOnce(&::Output) -> bool - | --------------------------------------- unsatisfied where-clause on `foo` -... -LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` -help: consider adding an explicit type annotation to the closure's argument - | -LL | foo(bar, "string", |s: &&str| s.len() == 5); - | +++++++ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-71955.rs:45:5 - | -LL | fn foo( - | --- due to a where-clause on `foo`... -... -LL | F2: FnOnce(&::Output) -> bool - | ---- unsatisfied where-clause on `foo` -... -LL | foo(bar, "string", |s| s.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&&'1 str,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` -help: consider adding an explicit type annotation to the closure's argument - | -LL | foo(bar, "string", |s: &&str| s.len() == 5); - | +++++++ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-71955.rs:48:5 - | -LL | fn foo( - | --- due to a where-clause on `foo`... -... -LL | F2: FnOnce(&::Output) -> bool - | --------------------------------------- unsatisfied where-clause on `foo` -... -LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` -help: consider adding an explicit type annotation to the closure's argument - | -LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); - | ++++++++++++++ - -error: implementation of `FnOnce` is not general enough - --> $DIR/issue-71955.rs:48:5 - | -LL | fn foo( - | --- due to a where-clause on `foo`... -... -LL | F2: FnOnce(&::Output) -> bool - | ---- unsatisfied where-clause on `foo` -... -LL | foo(baz, "string", |s| s.0.len() == 5); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&Wrapper<'1>,)>`, for any lifetime `'1`... - = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` -help: consider adding an explicit type annotation to the closure's argument - | -LL | foo(baz, "string", |s: &Wrapper<'_>| s.0.len() == 5); - | ++++++++++++++ - -error: aborting due to 4 previous errors - diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr index ded9a92d8e8c4..df54bacefa07b 100644 --- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.infer.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/defining-use-captured-non-universal-region.rs:13:18 + --> $DIR/defining-use-captured-non-universal-region.rs:16:18 | LL | fn foo<'a>() -> impl Sized + 'a { | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs index e18302dc061a3..a2f127e7935ef 100644 --- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.rs @@ -1,15 +1,18 @@ // This was an ICE. See #110726. -//@ revisions: statik infer fixed +//@ revisions: statik infer fixed next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [fixed] check-pass +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![allow(unconditional_recursion)] fn foo<'a>() -> impl Sized + 'a { - #[cfg(statik)] + #[cfg(any(statik, next))] let i: i32 = foo::<'static>(); //[statik]~^ ERROR expected generic lifetime parameter, found `'static` - #[cfg(infer)] + #[cfg(any(infer, next))] let i: i32 = foo::<'_>(); //[infer]~^ ERROR expected generic lifetime parameter, found `'_` diff --git a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr index 43beb29f9ec46..0c84035485033 100644 --- a/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr +++ b/tests/ui/impl-trait/defining-use-captured-non-universal-region.statik.stderr @@ -1,9 +1,9 @@ error[E0792]: expected generic lifetime parameter, found `'static` - --> $DIR/defining-use-captured-non-universal-region.rs:9:18 + --> $DIR/defining-use-captured-non-universal-region.rs:12:18 | LL | fn foo<'a>() -> impl Sized + 'a { | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type -LL | #[cfg(statik)] +LL | #[cfg(any(statik, next))] LL | let i: i32 = foo::<'static>(); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2015.stderr b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2015.stderr new file mode 100644 index 0000000000000..d601a597067c0 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2015.stderr @@ -0,0 +1,17 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:43 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^^^^^^^^^^^^-- + | | + | `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:24 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2024.stderr b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2024.stderr new file mode 100644 index 0000000000000..d601a597067c0 --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.edition2024.stderr @@ -0,0 +1,17 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:43 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^^^^^^^^^^^^-- + | | + | `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:24 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.next.stderr b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.next.stderr new file mode 100644 index 0000000000000..2ec2c79e2e0de --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.next.stderr @@ -0,0 +1,26 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:43 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^^^^^^^^^^^^-- + | | + | `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:24 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^ + +error[E0275]: overflow evaluating the requirement `a<'a>::{opaque#0}<'a> == {closure@$DIR/impl-fn-in-ret-pos-invalid-binder.rs:14:5: 14:8}` + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:13:15 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`impl_fn_in_ret_pos_invalid_binder`) + +error: aborting due to 2 previous errors + +Some errors have detailed explanations: E0275, E0657. +For more information about an error, try `rustc --explain E0275`. diff --git a/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.rs b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.rs new file mode 100644 index 0000000000000..261a826b66c0d --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.rs @@ -0,0 +1,16 @@ +#![feature(impl_trait_in_fn_trait_return)] + +// A variant of `impl-fn-predefined-lifetimes.rs` which uses an explicit +// binder for the lifetime in the nested opaque type. This is intentionally +// not supported. + +fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + //~^ ERROR: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + |x| x +} + +fn _b<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { + a() +} + +fn main() {} diff --git a/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.stderr b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.stderr new file mode 100644 index 0000000000000..3e593a64ee77b --- /dev/null +++ b/tests/ui/impl-trait/impl-fn-in-ret-pos-invalid-binder.stderr @@ -0,0 +1,17 @@ +error[E0657]: `impl Trait` cannot capture higher-ranked lifetime from outer `impl Trait` + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:7:43 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^^^^^^^^^^^^-- + | | + | `impl Trait` implicitly captures all lifetimes in scope + | +note: lifetime declared here + --> $DIR/impl-fn-in-ret-pos-invalid-binder.rs:7:24 + | +LL | fn a<'a>() -> impl for<'b> Fn(&'a u8) -> (impl Sized + 'b) { + | ^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0657`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr index 94476bcfbe88e..6b32c4ba8795c 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2015.stderr @@ -1,11 +1,19 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:8:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:15:9 | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { | -- this generic parameter must be used with a generic lifetime parameter LL | |x| x | ^ -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/impl-fn-predefined-lifetimes.rs:25:9 + | +LL | fn c<'a>() -> impl Fn(&'a u8) -> (impl Sized + '_) { + | -- this generic parameter must be used with a generic lifetime parameter +LL | |x| x + | ^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr index 2f1eacb0c34fa..1bebc53d9ec47 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.edition2024.stderr @@ -1,11 +1,19 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/impl-fn-predefined-lifetimes.rs:8:9 + --> $DIR/impl-fn-predefined-lifetimes.rs:15:9 | -LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { +LL | fn a<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { | -- this generic parameter must be used with a generic lifetime parameter LL | |x| x | ^ -error: aborting due to 1 previous error +error[E0792]: expected generic lifetime parameter, found `'_` + --> $DIR/impl-fn-predefined-lifetimes.rs:25:9 + | +LL | fn c<'a>() -> impl Fn(&'a u8) -> (impl Sized + '_) { + | -- this generic parameter must be used with a generic lifetime parameter +LL | |x| x + | ^ + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0792`. diff --git a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs index b2963cc10fa85..a787b70505e7e 100644 --- a/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs +++ b/tests/ui/impl-trait/impl-fn-predefined-lifetimes.rs @@ -1,15 +1,32 @@ -//@revisions: edition2015 edition2024 +//@ revisions: edition2015 edition2024 next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[edition2015] edition:2015 //@[edition2024] edition:2024 +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(impl_trait_in_fn_trait_return)] -use std::fmt::Debug; -fn a<'a>() -> impl Fn(&'a u8) -> (impl Debug + '_) { +// In the old solver we only define the nested `impl Sized` +// inside of the closure, at which point `'a` is an external +// region. The edition does not matter except for the diagnostic. +// In both cases the inner opaque type captures `'a`. + +fn a<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { + |x| x + //[edition2015,edition2024]~^ ERROR expected generic lifetime parameter, found `'_` +} + +fn _b<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { + a() +} + +// `'_` gets inferred to `'a` here. +fn c<'a>() -> impl Fn(&'a u8) -> (impl Sized + '_) { |x| x - //~^ ERROR expected generic lifetime parameter, found `'_` + //[edition2015,edition2024]~^ ERROR expected generic lifetime parameter, found `'_` } -fn _b<'a>() -> impl Fn(&'a u8) -> (impl Debug + 'a) { +fn _d<'a>() -> impl Fn(&'a u8) -> (impl Sized + 'a) { a() } diff --git a/tests/ui/impl-trait/recursive-ice-101862.stderr b/tests/ui/impl-trait/recursive-ice-101862.current.stderr similarity index 92% rename from tests/ui/impl-trait/recursive-ice-101862.stderr rename to tests/ui/impl-trait/recursive-ice-101862.current.stderr index 85745c25e2bfa..2b885659e274b 100644 --- a/tests/ui/impl-trait/recursive-ice-101862.stderr +++ b/tests/ui/impl-trait/recursive-ice-101862.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic type parameter, found `&str` - --> $DIR/recursive-ice-101862.rs:6:19 + --> $DIR/recursive-ice-101862.rs:10:19 | LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { | --------------- this generic parameter must be used with a generic type parameter @@ -8,7 +8,7 @@ LL | vec![].append(&mut ice(x.as_ref())); | ^^^^^^^^^^^^^^^^^^^^ warning: function cannot return without recursing - --> $DIR/recursive-ice-101862.rs:4:1 + --> $DIR/recursive-ice-101862.rs:8:1 | LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing diff --git a/tests/ui/impl-trait/recursive-ice-101862.next.stderr b/tests/ui/impl-trait/recursive-ice-101862.next.stderr new file mode 100644 index 0000000000000..48b5831acc0c6 --- /dev/null +++ b/tests/ui/impl-trait/recursive-ice-101862.next.stderr @@ -0,0 +1,14 @@ +warning: function cannot return without recursing + --> $DIR/recursive-ice-101862.rs:8:1 + | +LL | pub fn ice(x: impl AsRef) -> impl IntoIterator { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot return without recursing +LL | +LL | vec![].append(&mut ice(x.as_ref())); + | --------------- recursive call site + | + = help: a `loop` may express intention better if this is on purpose + = note: `#[warn(unconditional_recursion)]` on by default + +warning: 1 warning emitted + diff --git a/tests/ui/impl-trait/recursive-ice-101862.rs b/tests/ui/impl-trait/recursive-ice-101862.rs index 02f95fe5604b2..117b3f0b8d089 100644 --- a/tests/ui/impl-trait/recursive-ice-101862.rs +++ b/tests/ui/impl-trait/recursive-ice-101862.rs @@ -1,10 +1,14 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass // issue: rust-lang/rust#101852 // ICE opaque type with non-universal region substs pub fn ice(x: impl AsRef) -> impl IntoIterator { //~^ WARN function cannot return without recursing vec![].append(&mut ice(x.as_ref())); - //~^ ERROR expected generic type parameter, found `&str` + //[current]~^ ERROR expected generic type parameter, found `&str` Vec::new() } diff --git a/tests/ui/impl-trait/rpit/early_bound.stderr b/tests/ui/impl-trait/rpit/early_bound.current.stderr similarity index 85% rename from tests/ui/impl-trait/rpit/early_bound.stderr rename to tests/ui/impl-trait/rpit/early_bound.current.stderr index d5eb229e3a75a..11b671545ad28 100644 --- a/tests/ui/impl-trait/rpit/early_bound.stderr +++ b/tests/ui/impl-trait/rpit/early_bound.current.stderr @@ -1,11 +1,11 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/early_bound.rs:6:36 + --> $DIR/early_bound.rs:10:36 | LL | let _ = identity::<&'a ()>(test(false)); | ^^^^^^^^^^^ expected `!`, got `&()` | note: previous use here - --> $DIR/early_bound.rs:3:29 + --> $DIR/early_bound.rs:7:29 | LL | fn test<'a: 'a>(n: bool) -> impl Sized + 'a { | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/rpit/early_bound.rs b/tests/ui/impl-trait/rpit/early_bound.rs index 0337f605e487b..30940def29ecb 100644 --- a/tests/ui/impl-trait/rpit/early_bound.rs +++ b/tests/ui/impl-trait/rpit/early_bound.rs @@ -1,10 +1,14 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass use std::convert::identity; fn test<'a: 'a>(n: bool) -> impl Sized + 'a { let true = n else { loop {} }; let _ = || { let _ = identity::<&'a ()>(test(false)); - //~^ ERROR concrete type differs from previous defining opaque type use + //[current]~^ ERROR concrete type differs from previous defining opaque type use }; loop {} } diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.current.stderr similarity index 85% rename from tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr rename to tests/ui/impl-trait/rpit/non-defining-use-lifetimes.current.stderr index d2a224601fbe6..024d2db71e340 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.stderr +++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'static` - --> $DIR/non-defining-use-lifetimes.rs:13:16 + --> $DIR/non-defining-use-lifetimes.rs:17:16 | LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { | -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type @@ -7,7 +7,7 @@ LL | let _: () = foo(Lt::<'static>::None); | ^^ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/non-defining-use-lifetimes.rs:22:16 + --> $DIR/non-defining-use-lifetimes.rs:26:16 | LL | fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { | -- this generic parameter must be used with a generic lifetime parameter @@ -15,13 +15,13 @@ LL | let _: () = foo(Lt::<'_>::None); | ^^ error: non-defining opaque type use in defining scope - --> $DIR/non-defining-use-lifetimes.rs:32:16 + --> $DIR/non-defining-use-lifetimes.rs:36:16 | LL | let _: () = foo(Lt::<'a>::None, Lt::<'a>::None); | ^^ | note: lifetime used multiple times - --> $DIR/non-defining-use-lifetimes.rs:31:58 + --> $DIR/non-defining-use-lifetimes.rs:35:58 | LL | fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b { | ^^ ^^ diff --git a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs index 5e04e6b091adc..68a99fb099074 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs +++ b/tests/ui/impl-trait/rpit/non-defining-use-lifetimes.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass // issue: #111935 #![allow(unconditional_recursion)] @@ -11,7 +15,7 @@ mod statik { // invalid defining use: Opaque<'static> := () fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { let _: () = foo(Lt::<'static>::None); - //~^ ERROR expected generic lifetime parameter, found `'static` + //[current]~^ ERROR expected generic lifetime parameter, found `'static` } } @@ -20,7 +24,7 @@ mod infer { // invalid defining use: Opaque<'_> := () fn foo<'a>(_: Lt<'a>) -> impl Sized + 'a { let _: () = foo(Lt::<'_>::None); - //~^ ERROR expected generic lifetime parameter, found `'_` + //[current]~^ ERROR expected generic lifetime parameter, found `'_` } } @@ -30,7 +34,7 @@ mod equal { // because of the use of equal lifetimes in args fn foo<'a, 'b>(_: Lt<'a>, _: Lt<'b>) -> impl Sized + 'a + 'b { let _: () = foo(Lt::<'a>::None, Lt::<'a>::None); - //~^ ERROR non-defining opaque type use in defining scope + //[current]~^ ERROR non-defining opaque type use in defining scope } } diff --git a/tests/ui/impl-trait/rpit/non-defining-use.stderr b/tests/ui/impl-trait/rpit/non-defining-use.current.stderr similarity index 94% rename from tests/ui/impl-trait/rpit/non-defining-use.stderr rename to tests/ui/impl-trait/rpit/non-defining-use.current.stderr index c2b1b0f824976..22909ccfd54b1 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use.stderr +++ b/tests/ui/impl-trait/rpit/non-defining-use.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic type parameter, found `u8` - --> $DIR/non-defining-use.rs:4:17 + --> $DIR/non-defining-use.rs:8:17 | LL | fn foo() -> impl Sized { | - this generic parameter must be used with a generic type parameter @@ -7,7 +7,7 @@ LL | let _: () = foo::(); | ^^^^^^^^^^^ error[E0792]: expected generic type parameter, found `u8` - --> $DIR/non-defining-use.rs:8:17 + --> $DIR/non-defining-use.rs:12:17 | LL | fn bar(val: T) -> impl Sized { | - this generic parameter must be used with a generic type parameter diff --git a/tests/ui/impl-trait/rpit/non-defining-use.rs b/tests/ui/impl-trait/rpit/non-defining-use.rs index 3ab0e0ee4e29f..2c4976004cb31 100644 --- a/tests/ui/impl-trait/rpit/non-defining-use.rs +++ b/tests/ui/impl-trait/rpit/non-defining-use.rs @@ -1,12 +1,16 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass // Regression test for #111935 that non-defining uses of RPIT result in errors #![allow(unconditional_recursion)] fn foo() -> impl Sized { - let _: () = foo::(); //~ ERROR expected generic type parameter, found `u8` + let _: () = foo::(); //[current]~ ERROR expected generic type parameter, found `u8` } fn bar(val: T) -> impl Sized { let _: u8 = bar(0u8); - //~^ ERROR expected generic type parameter, found `u8` + //[current]~^ ERROR expected generic type parameter, found `u8` val } diff --git a/tests/ui/iterators/generator_capture_.stderr b/tests/ui/iterators/generator_capture_2.current.stderr similarity index 80% rename from tests/ui/iterators/generator_capture_.stderr rename to tests/ui/iterators/generator_capture_2.current.stderr index 3d9647ae16f32..f4d0e9ff33240 100644 --- a/tests/ui/iterators/generator_capture_.stderr +++ b/tests/ui/iterators/generator_capture_2.current.stderr @@ -1,8 +1,8 @@ error[E0382]: use of moved value: `f` - --> $DIR/generator_capture_.rs:21:17 + --> $DIR/generator_capture_2.rs:27:17 | LL | let f = { - | - move occurs because `f` has type `{gen closure@$DIR/generator_capture_.rs:10:17: 10:24}`, which does not implement the `Copy` trait + | - move occurs because `f` has type `{gen closure@$DIR/generator_capture_2.rs:16:17: 16:24}`, which does not implement the `Copy` trait ... LL | let mut i = f(); | --- `f` moved due to this call @@ -11,7 +11,7 @@ LL | let mut i = f(); | ^ value used here after move | note: this value implements `FnOnce`, which causes it to be moved when called - --> $DIR/generator_capture_.rs:16:17 + --> $DIR/generator_capture_2.rs:22:17 | LL | let mut i = f(); | ^ diff --git a/tests/ui/iterators/generator_capture_.rs b/tests/ui/iterators/generator_capture_2.rs similarity index 70% rename from tests/ui/iterators/generator_capture_.rs rename to tests/ui/iterators/generator_capture_2.rs index f630bc64b974c..5277dbb203732 100644 --- a/tests/ui/iterators/generator_capture_.rs +++ b/tests/ui/iterators/generator_capture_2.rs @@ -1,3 +1,9 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] known-bug: trait-system-refactor-initiative#302 +//@[next] check-pass + // This test exercises lending behavior for iterator closures which is not yet supported. #![feature(iter_macro, yield_expr)] @@ -18,7 +24,7 @@ fn main() { assert_eq!(i.next(), Some('o')); assert_eq!(i.next(), Some('o')); assert_eq!(i.next(), None); - let mut i = f(); //~ ERROR use of moved value: `f` + let mut i = f(); //[current]~ ERROR use of moved value: `f` assert_eq!(i.next(), Some('f')); assert_eq!(i.next(), Some('o')); assert_eq!(i.next(), Some('o')); diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr b/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr index 4e0dabade2de0..7aaff4c7bf679 100644 --- a/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr +++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.narrow.stderr @@ -1,14 +1,14 @@ -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure-simplified.rs:27:21 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure-simplified.rs:31:21 | LL | call_async_once(f); | --------------- ^ unsatisfied trait bound | | | required by a bound introduced by this call | - = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}` + = help: the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:25:21: 25:28}` note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure-simplified.rs:18:28 + --> $DIR/iter-macro-not-async-closure-simplified.rs:22:28 | LL | ...pl AsyncFnOnce()) {} | ^^^^^^^^^^^^^ required by this bound in `call_async_once` diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs b/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs index 4fa14fda661cf..e8c31f0eed879 100644 --- a/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs +++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.rs @@ -7,9 +7,13 @@ // explanation is moved to the `help` instead of the span label. // //@ edition: 2024 -//@ revisions: narrow wide +//@ revisions: narrow wide next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[narrow] compile-flags: --diagnostic-width=20 //@[wide] compile-flags: --diagnostic-width=300 +//@[next] compile-flags: -Znext-solver +//@[next] known-bug: trait-system-refactor-initiative#302 +//@[next] check-pass #![feature(yield_expr, iter_macro)] @@ -25,5 +29,5 @@ fn main() { }}; call_async_once(f); - //~^ ERROR AsyncFnOnce()` is not satisfied + //[narrow,wide]~^ ERROR AsyncFnOnce()` is not satisfied } diff --git a/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr b/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr index a6c239c181b5f..60a94e070eaba 100644 --- a/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr +++ b/tests/ui/iterators/iter-macro-not-async-closure-simplified.wide.stderr @@ -1,13 +1,13 @@ -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure-simplified.rs:27:21 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure-simplified.rs:31:21 | LL | call_async_once(f); - | --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:21:21: 21:28}` + | --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure-simplified.rs:25:21: 25:28}` | | | required by a bound introduced by this call | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure-simplified.rs:18:28 + --> $DIR/iter-macro-not-async-closure-simplified.rs:22:28 | LL | fn call_async_once(_: impl AsyncFnOnce()) {} | ^^^^^^^^^^^^^ required by this bound in `call_async_once` diff --git a/tests/ui/iterators/iter-macro-not-async-closure.stderr b/tests/ui/iterators/iter-macro-not-async-closure.current.stderr similarity index 71% rename from tests/ui/iterators/iter-macro-not-async-closure.stderr rename to tests/ui/iterators/iter-macro-not-async-closure.current.stderr index 0d7bfaca8bab2..c896d226a7715 100644 --- a/tests/ui/iterators/iter-macro-not-async-closure.stderr +++ b/tests/ui/iterators/iter-macro-not-async-closure.current.stderr @@ -1,73 +1,73 @@ -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:25:34 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:31:34 | LL | let x = pin!(call_async_once(f)); - | --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | --------------- ^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | | | required by a bound introduced by this call | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:25:18 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:31:18 | LL | let x = pin!(call_async_once(f)); - | ^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | ^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:25:13 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:31:13 | LL | let x = pin!(call_async_once(f)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:25:13 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:31:13 | LL | let x = pin!(call_async_once(f)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:25:13 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:31:13 | LL | let x = pin!(call_async_once(f)); - | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` -error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}: AsyncFnOnce()` is not satisfied - --> $DIR/iter-macro-not-async-closure.rs:31:5 +error[E0277]: the trait bound `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}: AsyncFnOnce()` is not satisfied + --> $DIR/iter-macro-not-async-closure.rs:37:5 | LL | x.poll(&mut Context::from_waker(Waker::noop())); - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:19:21: 19:28}` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `AsyncFnOnce()` is not implemented for `{gen closure@$DIR/iter-macro-not-async-closure.rs:25:21: 25:28}` | note: required by a bound in `call_async_once` - --> $DIR/iter-macro-not-async-closure.rs:14:34 + --> $DIR/iter-macro-not-async-closure.rs:20:34 | LL | async fn call_async_once(f: impl AsyncFnOnce()) { | ^^^^^^^^^^^^^ required by this bound in `call_async_once` diff --git a/tests/ui/iterators/iter-macro-not-async-closure.rs b/tests/ui/iterators/iter-macro-not-async-closure.rs index c46be769b3a67..3cf9e2237d2e7 100644 --- a/tests/ui/iterators/iter-macro-not-async-closure.rs +++ b/tests/ui/iterators/iter-macro-not-async-closure.rs @@ -1,3 +1,9 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] known-bug: trait-system-refactor-initiative#302 +//@[next] check-pass + // This test ensures iterators created with the `iter!` macro are not // accidentally async closures. // @@ -23,11 +29,11 @@ fn main() { }}; let x = pin!(call_async_once(f)); - //~^ ERROR AsyncFnOnce()` is not satisfied - //~^^ ERROR AsyncFnOnce()` is not satisfied - //~^^^ ERROR AsyncFnOnce()` is not satisfied - //~^^^^ ERROR AsyncFnOnce()` is not satisfied - //~^^^^^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^^^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^^^^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^^^^^ ERROR AsyncFnOnce()` is not satisfied x.poll(&mut Context::from_waker(Waker::noop())); - //~^ ERROR AsyncFnOnce()` is not satisfied + //[current]~^ ERROR AsyncFnOnce()` is not satisfied } diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.stderr b/tests/ui/lazy-type-alias-impl-trait/branches.current.stderr similarity index 94% rename from tests/ui/lazy-type-alias-impl-trait/branches.stderr rename to tests/ui/lazy-type-alias-impl-trait/branches.current.stderr index 0cc727bc3ded4..793409b9c78e4 100644 --- a/tests/ui/lazy-type-alias-impl-trait/branches.stderr +++ b/tests/ui/lazy-type-alias-impl-trait/branches.current.stderr @@ -1,5 +1,5 @@ error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_` - --> $DIR/branches.rs:17:28 + --> $DIR/branches.rs:21:28 | LL | std::iter::empty().collect() | ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator` diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.rs b/tests/ui/lazy-type-alias-impl-trait/branches.rs index 30f9c08a27fd0..14be136872edb 100644 --- a/tests/ui/lazy-type-alias-impl-trait/branches.rs +++ b/tests/ui/lazy-type-alias-impl-trait/branches.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; @@ -15,7 +19,7 @@ fn bar(b: bool) -> Bar { vec![42_i32] } else { std::iter::empty().collect() - //~^ ERROR a value of type `Bar` cannot be built from an iterator over elements of type `_` + //[current]~^ ERROR a value of type `Bar` cannot be built from an iterator over elements of type `_` }; x } diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr b/tests/ui/lazy-type-alias-impl-trait/recursion3.current.stderr similarity index 89% rename from tests/ui/lazy-type-alias-impl-trait/recursion3.stderr rename to tests/ui/lazy-type-alias-impl-trait/recursion3.current.stderr index 0cbedfb69f85a..aa0061f5506be 100644 --- a/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr +++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.current.stderr @@ -1,5 +1,5 @@ error[E0369]: cannot add `{integer}` to `Foo` - --> $DIR/recursion3.rs:10:29 + --> $DIR/recursion3.rs:14:29 | LL | let x: u32 = foo(false) + 42; | ---------- ^ -- {integer} @@ -7,7 +7,7 @@ LL | let x: u32 = foo(false) + 42; | Foo error[E0369]: cannot add `{integer}` to `impl Debug` - --> $DIR/recursion3.rs:18:29 + --> $DIR/recursion3.rs:22:29 | LL | let x: u32 = bar(false) + 42; | ---------- ^ -- {integer} diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.rs b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs index 0b15484f7ef53..9119f651965f5 100644 --- a/tests/ui/lazy-type-alias-impl-trait/recursion3.rs +++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(type_alias_impl_trait)] type Foo = impl std::fmt::Debug; @@ -7,7 +11,7 @@ fn foo(b: bool) -> Foo { if b { return 42; } - let x: u32 = foo(false) + 42; //~ ERROR cannot add + let x: u32 = foo(false) + 42; //[current]~ ERROR cannot add 99 } @@ -15,7 +19,7 @@ fn bar(b: bool) -> impl std::fmt::Debug { if b { return 42; } - let x: u32 = bar(false) + 42; //~ ERROR cannot add + let x: u32 = bar(false) + 42; //[current]~ ERROR cannot add 99 } diff --git a/tests/ui/lifetimes/conflicting-bounds.stderr b/tests/ui/lifetimes/conflicting-bounds.current.stderr similarity index 91% rename from tests/ui/lifetimes/conflicting-bounds.stderr rename to tests/ui/lifetimes/conflicting-bounds.current.stderr index cd66eb5e3fea6..887850b1db711 100644 --- a/tests/ui/lifetimes/conflicting-bounds.stderr +++ b/tests/ui/lifetimes/conflicting-bounds.current.stderr @@ -1,7 +1,7 @@ error[E0283]: type annotations needed: cannot satisfy `Self: Gen<'source>` | note: multiple `impl`s or `where` clauses satisfying `Self: Gen<'source>` found - --> $DIR/conflicting-bounds.rs:3:1 + --> $DIR/conflicting-bounds.rs:13:1 | LL | pub trait Gen<'source> { | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/lifetimes/conflicting-bounds.rs b/tests/ui/lifetimes/conflicting-bounds.rs index 62240792afd76..7409c5f593e78 100644 --- a/tests/ui/lifetimes/conflicting-bounds.rs +++ b/tests/ui/lifetimes/conflicting-bounds.rs @@ -1,4 +1,14 @@ -//~ ERROR type annotations needed: cannot satisfy `Self: Gen<'source>` +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//[current]~^^^^ ERROR type annotations needed: cannot satisfy `Self: Gen<'source>` + +// This previously failed with ambiguity in the old solver and +// was added as a diagnostics test in #105285. The new solver +// is now able to uniquely chose one of the `ParamEnv` candidates +// as it does not result in any region constraints, causing this +// test to pass. pub trait Gen<'source> { type Output; diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.current.stderr similarity index 77% rename from tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.stderr rename to tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.current.stderr index fe4de540b513a..de37ee0744aec 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.stderr +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.current.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `&'static (): Marker` - --> $DIR/overlap-marker-trait-with-static-lifetime.rs:11:17 + --> $DIR/overlap-marker-trait-with-static-lifetime.rs:16:17 | LL | impl Marker for &'static () {} | ^^^^^^^^^^^ | note: multiple `impl`s satisfying `&'static (): Marker` found - --> $DIR/overlap-marker-trait-with-static-lifetime.rs:11:1 + --> $DIR/overlap-marker-trait-with-static-lifetime.rs:16:1 | LL | impl Marker for &'static () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | impl Marker for &'static () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed: cannot satisfy `&'static (): Marker` - --> $DIR/overlap-marker-trait-with-static-lifetime.rs:12:17 + --> $DIR/overlap-marker-trait-with-static-lifetime.rs:17:17 | LL | impl Marker for &'static () {} | ^^^^^^^^^^^ | note: multiple `impl`s satisfying `&'static (): Marker` found - --> $DIR/overlap-marker-trait-with-static-lifetime.rs:11:1 + --> $DIR/overlap-marker-trait-with-static-lifetime.rs:16:1 | LL | impl Marker for &'static () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs index 84297de364bb7..8c82f4e00d535 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-static-lifetime.rs @@ -1,4 +1,9 @@ -//@ known-bug: #89515 +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + +//@[current] known-bug: #89515 // // The trait solver cannot deal with ambiguous marker trait impls // if there are lifetimes involved. As we must not special-case any diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.current.stderr similarity index 74% rename from tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr rename to tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.current.stderr index 3cd59d6926eb4..0eee44be3631f 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.stderr +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.current.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `&(): Marker` - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:17 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:11:17 | LL | impl Marker for &'_ () {} | ^^^^^^ | note: multiple `impl`s satisfying `&(): Marker` found - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:11:1 | LL | impl Marker for &'_ () {} | ^^^^^^^^^^^^^^^^^^^^^^ @@ -13,13 +13,13 @@ LL | impl Marker for &'_ () {} | ^^^^^^^^^^^^^^^^^^^^^^ error[E0283]: type annotations needed: cannot satisfy `&(): Marker` - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:7:17 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:12:17 | LL | impl Marker for &'_ () {} | ^^^^^^ | note: multiple `impl`s satisfying `&(): Marker` found - --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:6:1 + --> $DIR/overlap-marker-trait-with-underscore-lifetime.rs:11:1 | LL | impl Marker for &'_ () {} | ^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs index eabce1aeff140..486c93456fe66 100644 --- a/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs +++ b/tests/ui/marker_trait_attr/overlap-marker-trait-with-underscore-lifetime.rs @@ -1,9 +1,14 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass + #![feature(marker_trait_attr)] #[marker] trait Marker {} -impl Marker for &'_ () {} //~ ERROR type annotations needed -impl Marker for &'_ () {} //~ ERROR type annotations needed +impl Marker for &'_ () {} //[current]~ ERROR type annotations needed +impl Marker for &'_ () {} //[current]~ ERROR type annotations needed fn main() {} diff --git a/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.rs b/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.rs index 955108a20744b..ae6bbacb4da9e 100644 --- a/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.rs +++ b/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.rs @@ -1,13 +1,12 @@ -//@ compile-flags: --crate-type=lib - pub trait Tr {} impl Tr for u32 {} pub fn foo() -> Box { - if true { - let x = foo(); - let y: Box = x; -//~^ ERROR: the size for values of type `impl Tr + ?Sized` cannot be known - } Box::new(1u32) } + +fn main() { + let _: Box = foo(); + //~^ ERROR: the size for values of type `impl Tr + ?Sized` cannot be known + +} diff --git a/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.stderr b/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.stderr index bbe19870937ee..532d133b78580 100644 --- a/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.stderr +++ b/tests/ui/sized-hierarchy/pretty-print-opaque-no-feat.stderr @@ -1,8 +1,8 @@ error[E0277]: the size for values of type `impl Tr + ?Sized` cannot be known at compilation time - --> $DIR/pretty-print-opaque-no-feat.rs:9:30 + --> $DIR/pretty-print-opaque-no-feat.rs:9:26 | -LL | let y: Box = x; - | ^ doesn't have a size known at compile-time +LL | let _: Box = foo(); + | ^^^^^ doesn't have a size known at compile-time | = help: the trait `Sized` is not implemented for `impl Tr + ?Sized` = note: required for the cast from `Box` to `Box` diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.current.stderr similarity index 86% rename from tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr rename to tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.current.stderr index 2210291d37b5a..f43fe9490644d 100644 --- a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr +++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/defined-in-closure-external-lifetime.rs:7:29 + --> $DIR/defined-in-closure-external-lifetime.rs:10:29 | LL | type Opaque<'x> = impl Sized + 'x; | -- this generic parameter must be used with a generic lifetime parameter @@ -8,7 +8,7 @@ LL | let _ = || { let _: Opaque<'s> = (); }; | ^^^^^^^^^^ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/defined-in-closure-external-lifetime.rs:16:34 + --> $DIR/defined-in-closure-external-lifetime.rs:20:34 | LL | type Opaque<'x> = impl Sized + 'x; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.next.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.next.stderr new file mode 100644 index 0000000000000..9d9437c6b8c27 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.next.stderr @@ -0,0 +1,14 @@ +error: non-defining use of `case1::Opaque<'_>` in the defining scope + --> $DIR/defined-in-closure-external-lifetime.rs:10:29 + | +LL | let _ = || { let _: Opaque<'s> = (); }; + | ^^^^^^^^^^ + +error: non-defining use of `case2::Opaque<'_>` in the defining scope + --> $DIR/defined-in-closure-external-lifetime.rs:20:23 + | +LL | let _ = || -> Opaque<'s> {}; + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs index bc3904eb4e5fe..3b6e62f91d78c 100644 --- a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs +++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs @@ -1,20 +1,25 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] mod case1 { type Opaque<'x> = impl Sized + 'x; #[define_opaque(Opaque)] - fn foo<'s>() -> Opaque<'s> { + fn foo<'s>() { let _ = || { let _: Opaque<'s> = (); }; - //~^ ERROR expected generic lifetime parameter, found `'_` + //[current]~^ ERROR expected generic lifetime parameter, found `'_` + //[next]~^^ ERROR non-defining use of `case1::Opaque<'_>` in the defining scope } } mod case2 { type Opaque<'x> = impl Sized + 'x; #[define_opaque(Opaque)] - fn foo<'s>() -> Opaque<'s> { + fn foo<'s>() { let _ = || -> Opaque<'s> {}; - //~^ ERROR expected generic lifetime parameter, found `'_` + //[current]~^ ERROR expected generic lifetime parameter, found `'_` + //[next]~^^ ERROR non-defining use of `case2::Opaque<'_>` in the defining scope } } diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr index 43e887f36c5fe..1f30bb83da9ae 100644 --- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/generic-not-strictly-equal.rs:34:5 + --> $DIR/generic-not-strictly-equal.rs:38:5 | LL | type Opaque<'a> = impl Copy + Captures<'a>; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr index 43e887f36c5fe..1f30bb83da9ae 100644 --- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/generic-not-strictly-equal.rs:34:5 + --> $DIR/generic-not-strictly-equal.rs:38:5 | LL | type Opaque<'a> = impl Copy + Captures<'a>; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_basic.stderr new file mode 100644 index 0000000000000..686c8a85d0009 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_basic.stderr @@ -0,0 +1,8 @@ +error: non-defining use of `Opaque<'_>` in the defining scope + --> $DIR/generic-not-strictly-equal.rs:28:18 + | +LL | let opaque = None::>; // let's call this lifetime '?1 + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_member_constraints.stderr new file mode 100644 index 0000000000000..686c8a85d0009 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.next_member_constraints.stderr @@ -0,0 +1,8 @@ +error: non-defining use of `Opaque<'_>` in the defining scope + --> $DIR/generic-not-strictly-equal.rs:28:18 + | +LL | let opaque = None::>; // let's call this lifetime '?1 + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs index 42f363d0e575b..e65eacbdcaa64 100644 --- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs +++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs @@ -9,7 +9,10 @@ // // See #113971 for details. -//@ revisions: basic member_constraints +//@ revisions: basic member_constraints next_basic next_member_constraints +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next_basic] compile-flags: -Znext-solver +//@[next_member_constraints] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] trait Captures<'a> {} @@ -21,18 +24,19 @@ fn relate(_: X, _: X) {} type Opaque<'a> = impl Copy + Captures<'a>; #[define_opaque(Opaque)] -fn test<'x>(_: Opaque<'x>) { +fn test<'x>() { let opaque = None::>; // let's call this lifetime '?1 + //[next_basic,next_member_constraints]~^ ERROR: non-defining use of `Opaque<'_>` in the defining scope - #[cfg(basic)] + #[cfg(any(basic, next_basic))] let hidden = None::; - #[cfg(member_constraints)] + #[cfg(any(member_constraints, next_member_constraints))] let hidden = None::<&'x u8>; ensure_outlives::<'x>(opaque); // outlives constraint: '?1: 'x relate(opaque, hidden); // defining use: Opaque<'?1> := u8 - //~^ ERROR expected generic lifetime parameter, found `'_` + //[basic,member_constraints]~^ ERROR expected generic lifetime parameter, found `'_` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.current.stderr similarity index 78% rename from tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr rename to tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.current.stderr index ee20c5e1c9b6d..31b9f179f8971 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.current.stderr @@ -1,16 +1,16 @@ error[E0277]: the trait bound `u32: Yay` is not satisfied - --> $DIR/impl_trait_for_tait_bound.rs:11:14 + --> $DIR/impl_trait_for_tait_bound.rs:15:14 | LL | is_yay::(); | ^^^ the trait `Yay` is not implemented for `u32` | help: the trait `Yay` is implemented for `Foo` - --> $DIR/impl_trait_for_tait_bound.rs:7:1 + --> $DIR/impl_trait_for_tait_bound.rs:11:1 | LL | impl Yay for Foo {} | ^^^^^^^^^^^^^^^^ note: required by a bound in `is_yay` - --> $DIR/impl_trait_for_tait_bound.rs:17:14 + --> $DIR/impl_trait_for_tait_bound.rs:21:14 | LL | fn is_yay() {} | ^^^ required by this bound in `is_yay` diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs index e0045df08ec7c..6860fc4132d89 100644 --- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs +++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; @@ -8,7 +12,7 @@ impl Yay for Foo {} #[define_opaque(Foo)] fn foo() { - is_yay::(); //~ ERROR: the trait bound `u32: Yay` is not satisfied + is_yay::(); //[current]~ ERROR: the trait bound `u32: Yay` is not satisfied is_debug::(); // OK is_yay::(); // OK is_debug::(); // OK diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs deleted file mode 100644 index 839ac47162382..0000000000000 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs +++ /dev/null @@ -1,15 +0,0 @@ -// https://github.com/rust-lang/rust/issues/73481 -// This test used to cause unsoundness, since one of the two possible -// resolutions was chosen at random instead of erroring due to conflicts. - -#![feature(type_alias_impl_trait)] - -type Y = impl std::fmt::Debug; - -#[define_opaque(Y)] -fn g() -> (Y, Y) { - //~^ ERROR concrete type differs from previous defining opaque type use - (42_i64, 60) -} - -fn main() {} diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.current.stderr similarity index 86% rename from tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr rename to tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.current.stderr index e044cbe819e8c..6901fc9257666 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.current.stderr @@ -1,5 +1,5 @@ error: concrete type differs from previous defining opaque type use - --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:17 + --> $DIR/multiple-def-uses-in-one-fn-int-infer.rs:17:17 | LL | fn g() -> (Y, Y) { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.rs new file mode 100644 index 0000000000000..48a7d73c3519a --- /dev/null +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-int-infer.rs @@ -0,0 +1,22 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +// https://github.com/rust-lang/rust/issues/73481 + +// This test previously compiled due to an unsoundness as `Y` +// was incorrectly inferred to be `i32`. The new solver now treats +// `Y` as a defining use and uses it to constrain `Y` to +// `i64` as well. + +#![feature(type_alias_impl_trait)] + +type Y = impl std::fmt::Debug; + +#[define_opaque(Y)] +fn g() -> (Y, Y) { + //[current]~^ ERROR concrete type differs from previous defining opaque type use + (42_i64, 60) +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr b/tests/ui/type-alias-impl-trait/param_mismatch4.current.stderr similarity index 90% rename from tests/ui/type-alias-impl-trait/param_mismatch4.stderr rename to tests/ui/type-alias-impl-trait/param_mismatch4.current.stderr index 647637ae32a7c..d1822fcdeb2f5 100644 --- a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr +++ b/tests/ui/type-alias-impl-trait/param_mismatch4.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/param_mismatch4.rs:13:12 + --> $DIR/param_mismatch4.rs:17:12 | LL | type Opq<'a> = impl Sized; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.rs b/tests/ui/type-alias-impl-trait/param_mismatch4.rs index bc32143d0eb1d..d671bccb1e13b 100644 --- a/tests/ui/type-alias-impl-trait/param_mismatch4.rs +++ b/tests/ui/type-alias-impl-trait/param_mismatch4.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass //! This test checks that when checking for opaque types that //! only differ in lifetimes, we handle the case of non-generic //! regions correctly. @@ -11,7 +15,7 @@ type Opq<'a> = impl Sized; #[define_opaque(Opq)] fn build<'a>() -> Opq<'a> { let _: Opq<'_> = (); - //~^ ERROR expected generic lifetime parameter, found `'_` + //[current]~^ ERROR expected generic lifetime parameter, found `'_` } fn main() {} diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.current.stderr similarity index 86% rename from tests/ui/type-alias-impl-trait/reveal_local.stderr rename to tests/ui/type-alias-impl-trait/reveal_local.current.stderr index bd0828885910b..bc01bcd4cfd17 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.stderr +++ b/tests/ui/type-alias-impl-trait/reveal_local.current.stderr @@ -1,12 +1,12 @@ error[E0283]: type annotations needed: cannot satisfy `Foo: Send` - --> $DIR/reveal_local.rs:23:15 + --> $DIR/reveal_local.rs:27:15 | LL | is_send::(); | ^^^ | = note: cannot satisfy `Foo: Send` note: required by a bound in `is_send` - --> $DIR/reveal_local.rs:7:15 + --> $DIR/reveal_local.rs:11:15 | LL | fn is_send() {} | ^^^^ required by this bound in `is_send` diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs index 1e1e118937b2b..30b5412392e6f 100644 --- a/tests/ui/type-alias-impl-trait/reveal_local.rs +++ b/tests/ui/type-alias-impl-trait/reveal_local.rs @@ -1,3 +1,7 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass #![feature(type_alias_impl_trait)] use std::fmt::Debug; @@ -21,7 +25,7 @@ fn not_gooder() -> Foo { // while we could know this from the hidden type, it would // need extra roundabout logic to support it. is_send::(); - //~^ ERROR: type annotations needed: cannot satisfy `Foo: Send` + //[current]~^ ERROR: type annotations needed: cannot satisfy `Foo: Send` x } diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint-polymorphization-ice.current.stderr similarity index 88% rename from tests/ui/type-alias-impl-trait/taint.stderr rename to tests/ui/type-alias-impl-trait/taint-polymorphization-ice.current.stderr index e2e34a5d1ba4b..22930611649c5 100644 --- a/tests/ui/type-alias-impl-trait/taint.stderr +++ b/tests/ui/type-alias-impl-trait/taint-polymorphization-ice.current.stderr @@ -1,5 +1,5 @@ error[E0792]: expected generic lifetime parameter, found `'_` - --> $DIR/taint.rs:14:17 + --> $DIR/taint-polymorphization-ice.rs:19:17 | LL | type Two<'a, 'b> = impl std::fmt::Debug; | -- this generic parameter must be used with a generic lifetime parameter diff --git a/tests/ui/type-alias-impl-trait/taint-polymorphization-ice.rs b/tests/ui/type-alias-impl-trait/taint-polymorphization-ice.rs new file mode 100644 index 0000000000000..bcdde44ecb724 --- /dev/null +++ b/tests/ui/type-alias-impl-trait/taint-polymorphization-ice.rs @@ -0,0 +1,23 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes + +// reported as rust-lang/rust#126896. This originally ICE'd +// with polymorphization. + +#![feature(type_alias_impl_trait)] +type Two<'a, 'b> = impl std::fmt::Debug; + +fn set(x: &mut isize) -> isize { + *x +} + +#[define_opaque(Two)] +fn d(x: Two) { + let c1 = || set(x); //[current]~ ERROR: expected generic lifetime parameter, found `'_` + c1; +} + +fn main() {} diff --git a/tests/ui/type-alias-impl-trait/taint.rs b/tests/ui/type-alias-impl-trait/taint.rs deleted file mode 100644 index 3d67c9bca4162..0000000000000 --- a/tests/ui/type-alias-impl-trait/taint.rs +++ /dev/null @@ -1,18 +0,0 @@ -//@ compile-flags: -Zvalidate-mir -Zinline-mir=yes - -// reported as rust-lang/rust#126896 - -#![feature(type_alias_impl_trait)] -type Two<'a, 'b> = impl std::fmt::Debug; - -fn set(x: &mut isize) -> isize { - *x -} - -#[define_opaque(Two)] -fn d(x: Two) { - let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_` - c1; -} - -fn main() {} From 22067c76adf3907e32e8a0b0380cb8be169e4c44 Mon Sep 17 00:00:00 2001 From: Aelin Reidel Date: Fri, 2 Oct 2026 18:15:42 +0200 Subject: [PATCH 1199/1309] callconv: mips64: Match GCC for alignment of 16-byte scalars Previously, the calling convention code would not register align 16-byte scalars to even/odd register pairs. It seems like GCC does not differentiate between integer and floating point scalars when calculating whether a scalar is aligned. To our understanding, the MIPS n64 ABI [1] would require doing so for integer and floating point parameters respectively [2], but GCC violates the specification here and will happily pass an f128 in an odd-even floating point register pair and therefore sometimes shift following integer arguments due to unnecessary (if the spec is to be believed) inserted integer padding. [1]: https://web.archive.org/web/20160121005457/http://techpubs.sgi.com/library/manuals/2000/007-2816-005/pdf/007-2816-005.pdf#page=20 [2]: "This requires that they be passed in even-odd floating point register pairs, even if doing so requires skipping a register parameter" --- compiler/rustc_target/src/callconv/mips64.rs | 13 ++++++++ .../mips64-abi/register-alignment.rs | 33 +++++++++++++++++++ 2 files changed, 46 insertions(+) create mode 100644 tests/codegen-llvm/mips64-abi/register-alignment.rs diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs index e444e605d3b5a..72c02f6dc04ca 100644 --- a/compiler/rustc_target/src/callconv/mips64.rs +++ b/compiler/rustc_target/src/callconv/mips64.rs @@ -118,6 +118,19 @@ where if !arg.layout.is_aggregate() { extend_integer_width_mips(arg, 64); + + // We always pad with an integer, even if the primitive is a float. This + // conflicts with our reading of the specification, which would require + // padding floats with floats and integers with integers. + // However, this implementation is consistent with GCC, which means we + // are compatible with the de-facto ABI on the platform. + if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr { + let kind = match scalar.primitive() { + Primitive::Int(_, _) | Primitive::Pointer(_) => RegKind::Integer, + Primitive::Float(_) => RegKind::Float, + }; + arg.cast_to_and_pad_i32(CastTarget::from(Reg { kind, size }), pad_i32); + } } else if arg.layout.pass_indirectly_in_non_rustic_abis(cx) { arg.make_indirect(); } else if let Some(component) = arg.layout.complex_number(cx) diff --git a/tests/codegen-llvm/mips64-abi/register-alignment.rs b/tests/codegen-llvm/mips64-abi/register-alignment.rs new file mode 100644 index 0000000000000..e7db7e2c05d4d --- /dev/null +++ b/tests/codegen-llvm/mips64-abi/register-alignment.rs @@ -0,0 +1,33 @@ +//@ add-minicore +//@ compile-flags: -Copt-level=3 +// +//@ revisions: mips64 mips64el +//@[mips64] compile-flags: --target mips64-unknown-linux-gnuabi64 +//@[mips64el] compile-flags: --target mips64el-unknown-linux-gnuabi64 +// +//@ needs-llvm-components: mips + +// Test that 16-byte scalars are correctly aligned in registers. + +#![feature(f128, lang_items, no_core)] +#![crate_type = "lib"] +#![no_core] + +extern crate minicore; +use minicore::*; + +// CHECK: @i128_gets_aligned(i8 %0, i32 %1, i128 %2) +#[no_mangle] +extern "C" fn i128_gets_aligned(arg0: u8, arg1: i128) {} + +// CHECK: @i128_is_aligned(i8 %0, i16 %1, i128 %2) +#[no_mangle] +extern "C" fn i128_is_aligned(arg0: u8, arg1: i16, arg2: i128) {} + +// CHECK: @f128_gets_aligned(i8 %0, i32 %1, fp128 %2) +#[no_mangle] +extern "C" fn f128_gets_aligned(arg0: u8, arg1: f128) {} + +// CHECK: @f128_is_aligned(i8 %0, float %1, fp128 %2) +#[no_mangle] +extern "C" fn f128_is_aligned(arg0: u8, arg1: f32, arg2: f128) {} From c76b52386058c6d907585e80bf8f817c3e0a6b94 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Wed, 30 Sep 2026 14:31:54 -0700 Subject: [PATCH 1200/1309] Update the minimum external LLVM to 22 Co-authored-by: Augie Fackler --- .../src/back/llvm_backend.rs | 7 +- compiler/rustc_codegen_llvm/src/builder.rs | 16 +- compiler/rustc_codegen_llvm/src/context.rs | 27 ---- compiler/rustc_codegen_llvm/src/intrinsic.rs | 147 ++++++------------ compiler/rustc_codegen_llvm/src/llvm_util.rs | 72 +++------ .../rustc_llvm/llvm-wrapper/PassWrapper.cpp | 49 +----- .../rustc_llvm/llvm-wrapper/RustWrapper.cpp | 34 ---- library/coretests/tests/num/floats.rs | 26 +--- src/bootstrap/src/core/build_steps/llvm.rs | 4 +- src/ci/docker/README.md | 8 +- .../Dockerfile | 14 +- .../test-x86_64-gnu-llvm-21/Dockerfile | 65 -------- .../test-x86_64-gnu-llvm-22/Dockerfile | 11 +- src/ci/docker/scripts/stage_2_test_set1.sh | 7 - src/ci/docker/scripts/stage_2_test_set2.sh | 17 -- src/ci/github-actions/jobs.yml | 45 ++---- tests/assembly-llvm/asm/loongarch-type.rs | 1 - tests/assembly-llvm/asm/powerpc-types.rs | 2 - tests/assembly-llvm/asm/sparc-types.rs | 1 - tests/assembly-llvm/asm/xtensa-types.rs | 1 - tests/assembly-llvm/bpf_unaligned.rs | 1 - tests/assembly-llvm/c-variadic/xtensa.rs | 1 - tests/assembly-llvm/cmse-clear-padding.rs | 1 - tests/assembly-llvm/tail-call-indirect.rs | 1 - tests/assembly-llvm/targets/targets-elf.rs | 3 - tests/codegen-llvm/amdgpu-addrspacecast.rs | 9 +- tests/codegen-llvm/const-vector.rs | 1 - .../issue-122600-ptr-discriminant-update.rs | 6 - .../pauth-extern-c-direct-indirect-call.rs | 3 - .../scalable-vectors/debuginfo.rs | 11 +- .../simd-intrinsic-generic-gather.rs | 14 +- .../simd-intrinsic-generic-masked-load.rs | 24 +-- .../simd-intrinsic-generic-masked-store.rs | 24 +-- .../simd-intrinsic-generic-scatter.rs | 14 +- tests/codegen-llvm/slp-vectorization-mul3.rs | 1 - tests/codegen-llvm/store-captures.rs | 1 - tests/codegen-llvm/tail-call-u128.rs | 1 - tests/codegen-llvm/vec_pop_push_noop.rs | 4 - tests/codegen-llvm/vecdeque_pop_push.rs | 4 - tests/ui/codegen/huge-stacks.rs | 1 - .../no-unsized-arguments.aarch64.stderr | 6 +- .../no-unsized-arguments.rs | 1 - .../no-unsized-arguments.x86.stderr | 6 +- .../no-unsized-arguments.x86_64.stderr | 6 +- tests/ui/explicit-tail-calls/support/basic.rs | 1 - .../ui/explicit-tail-calls/support/bystack.rs | 14 +- tests/ui/explicit-tail-calls/support/byval.rs | 14 +- .../feature-gate-xtensa-target-feature.rs | 1 - .../feature-gate-xtensa-target-feature.stderr | 2 +- tests/ui/float/minmax.rs | 22 --- 50 files changed, 171 insertions(+), 581 deletions(-) rename src/ci/docker/host-aarch64/{test-aarch64-gnu-llvm-21 => test-aarch64-gnu-llvm-22}/Dockerfile (89%) delete mode 100644 src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-21/Dockerfile delete mode 100644 tests/ui/float/minmax.rs diff --git a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs index 3f89777bb28db..8780af2f6d595 100644 --- a/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs +++ b/compiler/rustc_codegen_llvm/src/back/llvm_backend.rs @@ -208,11 +208,12 @@ impl CodegenBackend for LlvmCodegenBackend { // Intrinsics whose fallback body will not be used by the LLVM backend. let replaced_intrinsics = { #[rustfmt::skip] - let mut will_not_use_fallback = vec![ + let will_not_use_fallback = vec![ // These are mapped to LLVM intrinsics instead. sym::unchecked_funnel_shl, sym::unchecked_funnel_shr, sym::carrying_mul_add, + sym::carryless_mul, sym::integer_max, sym::integer_min, @@ -235,10 +236,6 @@ impl CodegenBackend for LlvmCodegenBackend { sym::copysignf16, sym::copysignf32, sym::copysignf64, sym::copysignf128, ]; - if llvm_util::get_version() >= (22, 0, 0) { - will_not_use_fallback.push(sym::carryless_mul); - } - will_not_use_fallback }; diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index dc89414940620..2823b26233557 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -919,9 +919,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { self.set_metadata_node(store, llvm::MD_nontemporal, &[one]); } } - if flags.contains(MemFlags::CAPTURES_READ_ONLY) - && crate::llvm_util::get_version() >= (22, 0, 0) - { + if flags.contains(MemFlags::CAPTURES_READ_ONLY) { assert!( self.type_kind(self.val_ty(val)) == TypeKind::Pointer, "CAPTURED_READ_ONLY is only supported on pointer stores" @@ -1903,14 +1901,10 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { return; } - if crate::llvm_util::get_version() >= (22, 0, 0) { - // LLVM 22 requires the lifetime intrinsic to act directly on the alloca, - // there can't be an addrspacecast in between. - let ptr = unsafe { llvm::LLVMRustStripPointerCasts(ptr) }; - self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[ptr]); - } else { - self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[self.cx.const_u64(size), ptr]); - } + // LLVM 22 requires the lifetime intrinsic to act directly on the alloca, + // there can't be an addrspacecast in between. + let ptr = unsafe { llvm::LLVMRustStripPointerCasts(ptr) }; + self.call_intrinsic(intrinsic, &[self.val_ty(ptr)], &[ptr]); } } impl<'a, 'll, CX: Borrow>> GenericBuilder<'a, 'll, CX> { diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index 0ce3bfe07c413..d64c8de6ed7aa 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -195,33 +195,6 @@ pub(crate) unsafe fn create_module<'ll>( let mut target_data_layout = sess.target.data_layout.to_string(); let llvm_version = llvm_util::get_version(); - if llvm_version < (22, 0, 0) { - if sess.target.arch == Arch::Avr { - // LLVM 22.0 updated the default layout on avr: https://github.com/llvm/llvm-project/pull/153010 - target_data_layout = target_data_layout.replace("n8:16", "n8") - } - if sess.target.arch == Arch::Nvptx64 { - // LLVM 22 updated the NVPTX layout to indicate 256-bit vector load/store: https://github.com/llvm/llvm-project/pull/155198 - target_data_layout = target_data_layout.replace("-i256:256", ""); - } - if sess.target.arch == Arch::PowerPC64 { - // LLVM 22 updated the ABI alignment for double on AIX: https://github.com/llvm/llvm-project/pull/144673 - target_data_layout = target_data_layout.replace("-f64:32:64", ""); - - // LLVM 22 fixed the data layout calculation for targets that default to ELFv1 - // when the ABI is set to ELFv2. With LLVM 21, the ELFv1 datalayout must be used, - // which will overalign function entries. - // https://github.com/llvm/llvm-project/pull/149725 - if sess.target.llvm_target == "powerpc64-unknown-linux-gnu" { - target_data_layout = target_data_layout.replace("-Fn32", "-Fi64"); - } - } - if sess.target.arch == Arch::AmdGpu { - // LLVM 22 specified ELF mangling in the amdgpu data layout: - // https://github.com/llvm/llvm-project/pull/163011 - target_data_layout = target_data_layout.replace("-m:e", ""); - } - } if llvm_version < (23, 0, 0) { if sess.target.arch == Arch::S390x { // LLVM 23 updated the s390x layout to specify the stack alignment: https://github.com/llvm/llvm-project/pull/176041 diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 3163139ba1f04..43608f7dc0771 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -192,7 +192,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { let simple = call_simple_intrinsic(self, name, args); let llval = match name { _ if simple.is_some() => simple.unwrap(), - // Need at least LLVM 22 for `min/maximumnum` to not crash LLVM. sym::minimum_number_nsz_f16 | sym::minimum_number_nsz_f32 | sym::minimum_number_nsz_f64 @@ -200,9 +199,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | sym::maximum_number_nsz_f16 | sym::maximum_number_nsz_f32 | sym::maximum_number_nsz_f64 - | sym::maximum_number_nsz_f128 - if llvm_version >= (22, 0, 0) => - { + | sym::maximum_number_nsz_f128 => { let intrinsic_name = if name.as_str().starts_with("min") { "llvm.minimumnum" } else { @@ -457,26 +454,6 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { pair } - // FIXME move into the branch below when LLVM 22 is the lowest version we support. - sym::carryless_mul if llvm_version >= (22, 0, 0) => { - let ty = args[0].layout.ty; - if !ty.is_integral() { - let err = tcx.dcx().emit_err(InvalidMonomorphization::BasicIntegerType { - span, - name, - ty, - }); - return IntrinsicResult::Err(err); - } - let (size, _) = ty.int_size_and_signed(self.tcx); - let width = size.bits(); - let llty = self.type_ix(width); - - let lhs = args[0].immediate(); - let rhs = args[1].immediate(); - self.call_intrinsic("llvm.clmul", &[llty], &[lhs, rhs]) - } - sym::ctlz | sym::ctlz_nonzero | sym::cttz @@ -484,6 +461,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { | sym::ctpop | sym::bswap | sym::bitreverse + | sym::carryless_mul | sym::integer_max | sym::integer_min | sym::saturating_add @@ -530,6 +508,11 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { sym::bitreverse => { self.call_intrinsic("llvm.bitreverse", &[llty], &[args[0].immediate()]) } + sym::carryless_mul => { + let lhs = args[0].immediate(); + let rhs = args[1].immediate(); + self.call_intrinsic("llvm.clmul", &[llty], &[lhs, rhs]) + } sym::integer_min | sym::integer_max => { let lhs = args[0].immediate(); let rhs = args[1].immediate(); @@ -2118,8 +2101,6 @@ fn generic_simd_intrinsic<'ll, 'tcx>( }; } - let llvm_version = crate::llvm_util::get_version(); - /// Converts a vector mask, where each element has a bit width equal to the data elements it is used with, /// down to an i1 based mask that can be used by llvm intrinsics. /// @@ -2666,22 +2647,16 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, element_ty0, in_len); - let args: &[&'ll Value] = if llvm_version < (22, 0, 0) { - let alignment = bx.const_i32(alignment as i32); - &[args[1].immediate(), alignment, mask, args[0].immediate()] - } else { - &[args[1].immediate(), mask, args[0].immediate()] - }; - - let call = - bx.call_intrinsic("llvm.masked.gather", &[llvm_elem_vec_ty, llvm_pointer_vec_ty], args); - if llvm_version >= (22, 0, 0) { - crate::attributes::apply_to_callsite( - call, - crate::llvm::AttributePlace::Argument(0), - &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], - ) - } + let call = bx.call_intrinsic( + "llvm.masked.gather", + &[llvm_elem_vec_ty, llvm_pointer_vec_ty], + &[args[1].immediate(), mask, args[0].immediate()], + ); + crate::attributes::apply_to_callsite( + call, + crate::llvm::AttributePlace::Argument(0), + &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], + ); return Ok(call); } @@ -2772,22 +2747,16 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, values_elem, values_len); - let args: &[&'ll Value] = if llvm_version < (22, 0, 0) { - let alignment = bx.const_i32(alignment as i32); - - &[args[1].immediate(), alignment, mask, args[2].immediate()] - } else { - &[args[1].immediate(), mask, args[2].immediate()] - }; - - let call = bx.call_intrinsic("llvm.masked.load", &[llvm_elem_vec_ty, llvm_pointer], args); - if llvm_version >= (22, 0, 0) { - crate::attributes::apply_to_callsite( - call, - crate::llvm::AttributePlace::Argument(0), - &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], - ) - } + let call = bx.call_intrinsic( + "llvm.masked.load", + &[llvm_elem_vec_ty, llvm_pointer], + &[args[1].immediate(), mask, args[2].immediate()], + ); + crate::attributes::apply_to_callsite( + call, + crate::llvm::AttributePlace::Argument(0), + &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], + ); return Ok(call); } @@ -2859,21 +2828,16 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, values_elem, values_len); - let args: &[&'ll Value] = if llvm_version < (22, 0, 0) { - let alignment = bx.const_i32(alignment as i32); - &[args[2].immediate(), args[1].immediate(), alignment, mask] - } else { - &[args[2].immediate(), args[1].immediate(), mask] - }; - - let call = bx.call_intrinsic("llvm.masked.store", &[llvm_elem_vec_ty, llvm_pointer], args); - if llvm_version >= (22, 0, 0) { - crate::attributes::apply_to_callsite( - call, - crate::llvm::AttributePlace::Argument(1), - &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], - ) - } + let call = bx.call_intrinsic( + "llvm.masked.store", + &[llvm_elem_vec_ty, llvm_pointer], + &[args[2].immediate(), args[1].immediate(), mask], + ); + crate::attributes::apply_to_callsite( + call, + crate::llvm::AttributePlace::Argument(1), + &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], + ); return Ok(call); } @@ -2949,24 +2913,17 @@ fn generic_simd_intrinsic<'ll, 'tcx>( // Type of the vector of elements: let llvm_elem_vec_ty = llvm_vector_ty(bx, element_ty0, in_len); - let args: &[&'ll Value] = if llvm_version < (22, 0, 0) { - let alignment = bx.const_i32(alignment as i32); - &[args[0].immediate(), args[1].immediate(), alignment, mask] - } else { - &[args[0].immediate(), args[1].immediate(), mask] - }; + let call = bx.call_intrinsic( "llvm.masked.scatter", &[llvm_elem_vec_ty, llvm_pointer_vec_ty], - args, + &[args[0].immediate(), args[1].immediate(), mask], + ); + crate::attributes::apply_to_callsite( + call, + crate::llvm::AttributePlace::Argument(1), + &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], ); - if llvm_version >= (22, 0, 0) { - crate::attributes::apply_to_callsite( - call, - crate::llvm::AttributePlace::Argument(1), - &[crate::llvm::CreateAlignmentAttr(bx.llcx, alignment)], - ) - } return Ok(call); } @@ -3448,17 +3405,11 @@ fn generic_simd_intrinsic<'ll, 'tcx>( &[vec_ty], &[args[0].immediate(), args[1].immediate(), args[2].immediate()], )), - sym::simd_carryless_mul => { - if crate::llvm_util::get_version() >= (22, 0, 0) { - Ok(bx.call_intrinsic( - llvm_intrinsic, - &[vec_ty], - &[args[0].immediate(), args[1].immediate()], - )) - } else { - span_bug!(span, "`simd_carryless_mul` needs LLVM 22 or higher"); - } - } + sym::simd_carryless_mul => Ok(bx.call_intrinsic( + llvm_intrinsic, + &[vec_ty], + &[args[0].immediate(), args[1].immediate()], + )), _ => unreachable!(), }; } diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 4db534b978330..a582e897eef9c 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -262,7 +262,7 @@ pub(crate) fn to_llvm_features<'a>(target: &Target, s: &'a str) -> Option None, // only existed in 18 // Withdrawn by ARM; removed from LLVM in 22 - "tme" if major >= 22 => None, + "tme" => None, s => Some(LLVMFeature::new(s)), } } @@ -270,10 +270,6 @@ pub(crate) fn to_llvm_features<'a>(target: &Target, s: &'a str) -> Option Some(LLVMFeature::new("fullfp16")), s => Some(LLVMFeature::new(s)), }, - Arch::Bpf => match s { - "allows-misaligned-mem-access" if major < 22 => None, - s => Some(LLVMFeature::new(s)), - }, Arch::Nvptx64 => match s { "sm_101" if major >= 24 => Some(LLVMFeature::new("sm_110")), "sm_101a" if major >= 24 => Some(LLVMFeature::new("sm_110a")), @@ -294,43 +290,30 @@ pub(crate) fn to_llvm_features<'a>(target: &Target, s: &'a str) -> Option Some(LLVMFeature::new("hasleoncasa")), s => Some(LLVMFeature::new(s)), }, - Arch::Wasm32 | Arch::Wasm64 => match s { - "gc" if major < 22 => None, + Arch::X86 | Arch::X86_64 => match s { + "sse4.2" => Some(LLVMFeature::with_dependencies( + "sse4.2", + smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")], + )), + "pclmulqdq" => Some(LLVMFeature::new("pclmul")), + "rdrand" => Some(LLVMFeature::new("rdrnd")), + "bmi1" => Some(LLVMFeature::new("bmi")), + "cmpxchg16b" => Some(LLVMFeature::new("cx16")), + "lahfsahf" => Some(LLVMFeature::new("sahf")), + "apxf" => Some(LLVMFeature::with_dependencies( + "egpr", + smallvec![ + TargetFeatureFoldStrength::Both("push2pop2"), + TargetFeatureFoldStrength::Both("ppx"), + TargetFeatureFoldStrength::Both("ndd"), + TargetFeatureFoldStrength::Both("ccmp"), + TargetFeatureFoldStrength::Both("cf"), + TargetFeatureFoldStrength::Both("nf"), + TargetFeatureFoldStrength::Both("zu"), + ], + )), s => Some(LLVMFeature::new(s)), }, - Arch::X86 | Arch::X86_64 => { - match s { - "sse4.2" => Some(LLVMFeature::with_dependencies( - "sse4.2", - smallvec![TargetFeatureFoldStrength::EnableOnly("crc32")], - )), - "pclmulqdq" => Some(LLVMFeature::new("pclmul")), - "rdrand" => Some(LLVMFeature::new("rdrnd")), - "bmi1" => Some(LLVMFeature::new("bmi")), - "cmpxchg16b" => Some(LLVMFeature::new("cx16")), - "lahfsahf" => Some(LLVMFeature::new("sahf")), - // Enable the evex512 target feature if an avx512 target feature is enabled. - s if s.starts_with("avx512") && major < 22 => Some(LLVMFeature::with_dependencies( - s, - smallvec![TargetFeatureFoldStrength::EnableOnly("evex512")], - )), - "avx10.1" if major < 22 => Some(LLVMFeature::new("avx10.1-512")), - "avx10.2" if major < 22 => Some(LLVMFeature::new("avx10.2-512")), - "apxf" => Some(LLVMFeature::with_dependencies( - "egpr", - smallvec![ - TargetFeatureFoldStrength::Both("push2pop2"), - TargetFeatureFoldStrength::Both("ppx"), - TargetFeatureFoldStrength::Both("ndd"), - TargetFeatureFoldStrength::Both("ccmp"), - TargetFeatureFoldStrength::Both("cf"), - TargetFeatureFoldStrength::Both("nf"), - TargetFeatureFoldStrength::Both("zu"), - ], - )), - s => Some(LLVMFeature::new(s)), - } - } _ => Some(LLVMFeature::new(s)), } } @@ -396,18 +379,11 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { let (major, _, _) = version; cfg.has_reliable_f16 = match (target_arch, target_os) { - // Unsupported (fixed in llvm22) - (Arch::Arm64EC, _) if major < 22 => false, // MinGW ABI bugs resolved in GCC 16 // but our toolchain hasn't been updated. (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != CfgAbi::Llvm => { false } - // Infinite recursion - (Arch::CSky, _) if major < 22 => false, // (fixed in llvm22) - (Arch::PowerPC | Arch::PowerPC64, _) if major < 22 => false, // (fixed in llvm22) - (Arch::Sparc | Arch::Sparc64, _) if major < 22 => false, // (fixed in llvm22) - (Arch::Wasm32 | Arch::Wasm64, _) if major < 22 => false, // (fixed in llvm22) // `f16` support only requires that symbols converting to and from `f32` are available. We // provide these in `compiler-builtins`, so `f16` should be available on all platforms that // do not have other ABI issues or LLVM crashes. @@ -447,8 +423,6 @@ fn update_target_reliable_float_cfg(target: &Target, cfg: &mut TargetConfig) { (Arch::PowerPC64, Os::Aix) => false, // ABI bugs on BE without +vsx . (Arch::PowerPC64, _) => cfg.internal_target_features.contains(&sym::vsx), - // ABI unsupported (fixed in llvm22) - (Arch::Sparc, _) if major < 22 => false, // MinGW ABI bugs (fixed in llvm23) (Arch::X86_64, Os::Windows) if *target_env == Env::Gnu && *target_abi != CfgAbi::Llvm && major < 23 => diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp index d16d9db799be1..3873701ae09ac 100644 --- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp @@ -5,10 +5,8 @@ #include "llvm/ADT/DenseSet.h" #include "llvm/ADT/SmallVector.h" #include "llvm/Analysis/Lint.h" -#include "llvm/Analysis/TargetLibraryInfo.h" -#if LLVM_VERSION_GE(22, 0) #include "llvm/Analysis/RuntimeLibcallInfo.h" -#endif +#include "llvm/Analysis/TargetLibraryInfo.h" #include "llvm/Bitcode/BitcodeWriter.h" #include "llvm/Bitcode/BitcodeWriterPass.h" #include "llvm/CodeGen/CommandFlags.h" @@ -24,12 +22,8 @@ #include "llvm/MC/TargetRegistry.h" #include "llvm/Object/ObjectFile.h" #include "llvm/Passes/PassBuilder.h" -#if LLVM_VERSION_GE(22, 0) -#include "llvm/Plugins/PassPlugin.h" -#else -#include "llvm/Passes/PassPlugin.h" -#endif #include "llvm/Passes/StandardInstrumentations.h" +#include "llvm/Plugins/PassPlugin.h" #include "llvm/Support/CBindingWrapping.h" #include "llvm/Support/FileSystem.h" #include "llvm/Support/Program.h" @@ -100,11 +94,7 @@ LLVMRustCreateMCSubtargetInfo(const char *TripleStr, const char *CPU, return nullptr; } -#if LLVM_VERSION_GE(22, 0) return TheTarget->createMCSubtargetInfo(Trip, CPU, Features); -#else - return TheTarget->createMCSubtargetInfo(Trip.str(), CPU, Features); -#endif } extern "C" bool LLVMRustMCSubtargetInfoCheckFeatures(MCSubtargetInfo *MCInfo, @@ -498,7 +488,7 @@ LLVMRustWriteOutputFile(LLVMTargetMachineRef Target, LLVMModuleRef M, // module flags respectively instead. PM->add(new RuntimeLibraryInfoWrapper(Options->MCOptions.ABIName, Options->VecLib)); -#elif LLVM_VERSION_GE(22, 0) +#else PM->add(new RuntimeLibraryInfoWrapper( TargetTriple, Options->ExceptionModel, Options->FloatABIType, Options->EABIVersion, Options->MCOptions.ABIName, Options->VecLib)); @@ -721,44 +711,25 @@ extern "C" LLVMRustResult LLVMRustOptimize( } std::optional PGOOpt; -#if LLVM_VERSION_LT(22, 0) - auto FS = vfs::getRealFileSystem(); -#endif if (PGOGenPath) { assert(!PGOUsePath && !PGOSampleUsePath); PGOOpt = PGOOptions( -#if LLVM_VERSION_GE(22, 0) PGOGenPath, "", "", "", PGOOptions::IRInstr, PGOOptions::NoCSAction, -#else - PGOGenPath, "", "", "", FS, PGOOptions::IRInstr, PGOOptions::NoCSAction, -#endif PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } else if (PGOUsePath) { assert(!PGOSampleUsePath); PGOOpt = PGOOptions( -#if LLVM_VERSION_GE(22, 0) PGOUsePath, "", "", "", PGOOptions::IRUse, PGOOptions::NoCSAction, -#else - PGOUsePath, "", "", "", FS, PGOOptions::IRUse, PGOOptions::NoCSAction, -#endif PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } else if (PGOSampleUsePath) { PGOOpt = -#if LLVM_VERSION_GE(22, 0) PGOOptions(PGOSampleUsePath, "", "", "", PGOOptions::SampleUse, -#else - PGOOptions(PGOSampleUsePath, "", "", "", FS, PGOOptions::SampleUse, -#endif PGOOptions::NoCSAction, PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } else if (DebugInfoForProfiling) { - PGOOpt = PGOOptions( -#if LLVM_VERSION_GE(22, 0) - "", "", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction, -#else - "", "", "", "", FS, PGOOptions::NoAction, PGOOptions::NoCSAction, -#endif - PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); + PGOOpt = + PGOOptions("", "", "", "", PGOOptions::NoAction, PGOOptions::NoCSAction, + PGOOptions::ColdFuncOpt::Default, DebugInfoForProfiling); } auto PB = PassBuilder(TM, PTO, PGOOpt, &PIC); @@ -1389,11 +1360,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, size_t num_modules, // being lifted from `lib/LTO/LTO.cpp` as well DenseMap PrevailingCopy; for (auto &I : Ret->Index) { -#if LLVM_VERSION_GE(22, 0) const auto &SummaryList = I.second.getSummaryList(); -#else - const auto &SummaryList = I.second.SummaryList; -#endif if (SummaryList.size() > 1) PrevailingCopy[I.first] = getFirstDefinitionForLinker(SummaryList); } @@ -1426,11 +1393,7 @@ LLVMRustCreateThinLTOData(LLVMRustThinLTOModule *modules, size_t num_modules, // linkage will stay as external, and internal will stay as internal. std::set ExportedGUIDs; for (auto &List : Ret->Index) { -#if LLVM_VERSION_GE(22, 0) const auto &SummaryList = List.second.getSummaryList(); -#else - const auto &SummaryList = List.second.SummaryList; -#endif for (auto &GVS : SummaryList) { if (GlobalValue::isLocalLinkage(GVS->linkage())) continue; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index bc8fa60b66a52..16c7daf66f095 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1164,16 +1164,10 @@ LLVMRustDICreateVectorType(LLVMDIBuilderRef Builder, uint64_t Size, uint32_t AlignInBits, LLVMMetadataRef Type, LLVMMetadataRef Subscripts, LLVMMetadataRef BitStride) { -#if LLVM_VERSION_GE(22, 0) return wrap(unwrap(Builder)->createVectorType( Size, AlignInBits, unwrapDI(Type), DINodeArray(unwrapDI(Subscripts)), unwrapDI(BitStride))); -#else - return wrap(unwrap(Builder)->createVectorType( - Size, AlignInBits, unwrapDI(Type), - DINodeArray(unwrapDI(Subscripts)))); -#endif } extern "C" LLVMMetadataRef @@ -1562,13 +1556,11 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( RemarkStreamer(std::move(RemarkStreamer)), LlvmRemarkStreamer(std::move(LlvmRemarkStreamer)) {} -#if LLVM_VERSION_GE(22, 0) ~RustDiagnosticHandler() { if (RemarkStreamer) { RemarkStreamer->releaseSerializer(); } } -#endif virtual bool handleDiagnostics(const DiagnosticInfo &DI) override { // If this diagnostic is one of the optimization remark kinds, we can @@ -1664,14 +1656,8 @@ extern "C" void LLVMRustContextConfigureDiagnosticHandler( // Do not delete the file after we gather remarks RemarkFile->keep(); -#if LLVM_VERSION_GE(22, 0) auto RemarkSerializer = remarks::createRemarkSerializer( llvm::remarks::Format::YAML, RemarkFile->os()); -#else - auto RemarkSerializer = remarks::createRemarkSerializer( - llvm::remarks::Format::YAML, remarks::SerializerMode::Separate, - RemarkFile->os()); -#endif if (Error E = RemarkSerializer.takeError()) { std::string Error = std::string("Cannot create remark serializer: ") + toString(std::move(E)); @@ -1777,16 +1763,12 @@ extern "C" LLVMValueRef LLVMRustConstPtrAuth(LLVMValueRef Ptr, uint32_t Key, AddrDiversity ? dyn_cast(unwrap(AddrDiversity)) : ConstantPointerNull::get(cast(C->getType())); assert(AddrDiv && "Failed to get Address Diversity"); -#if LLVM_VERSION_GE(22, 0) Constant *DeactivationSym = DeactivationSymbol ? dyn_cast(unwrap(DeactivationSymbol)) : ConstantPointerNull::get(PTy); assert(DeactivationSym && "Failed to get Deactivation Symbol"); return wrap(ConstantPtrAuth::get(C, KeyC, DiscC, AddrDiv, DeactivationSym)); -#else - return wrap(ConstantPtrAuth::get(C, KeyC, DiscC, AddrDiv)); -#endif } // Statically assert that the fixed metadata kind IDs declared in @@ -1885,7 +1867,6 @@ class RustSanitizerSpecialCaseList : public llvm::SpecialCaseList { std::vector SanitizerSections; -#if LLVM_VERSION_GE(22, 0) static bool matchSection(const Section &S, llvm::StringRef Name) { return S.matchName(Name); } @@ -1894,24 +1875,9 @@ class RustSanitizerSpecialCaseList : public llvm::SpecialCaseList { return S.getLastMatch(Prefix, Query, Category); } static unsigned getFileIndex(const Section &S) { return S.fileIndex(); } -#else - static bool matchSection(const Section &S, llvm::StringRef Name) { - return S.SectionMatcher && S.SectionMatcher->match(Name) != 0; - } - unsigned getLastMatch(const Section &S, llvm::StringRef Prefix, - llvm::StringRef Query, llvm::StringRef Category) const { - return llvm::SpecialCaseList::inSectionBlame(S.Entries, Prefix, Query, - Category); - } - static unsigned getFileIndex(const Section &S) { return S.FileIdx; } -#endif void createSanitizerSections() { -#if LLVM_VERSION_GE(22, 0) const auto &SecList = sections(); -#else - const auto &SecList = Sections; -#endif for (const auto &S : SecList) { uint32_t Mask = 0; diff --git a/library/coretests/tests/num/floats.rs b/library/coretests/tests/num/floats.rs index 7093687f04b15..84d645ce31f3c 100644 --- a/library/coretests/tests/num/floats.rs +++ b/library/coretests/tests/num/floats.rs @@ -727,15 +727,10 @@ float_test! { assert_biteq!(flt(9.0).min(black_box(Float::NAN)), 9.0); assert_biteq!(black_box(flt(-9.0)).min(Float::NAN), -9.0); assert!(Float::NAN.min(Float::NAN).is_nan()); - // FIXME(llvm21): LLVM miscompiles the fallback impl on aarch64 and likely other targets - // (https://github.com/llvm/llvm-project/issues/176624). When we require LLVM 22, - // remove the ui test `tests/ui/float/minmax.rs` and unconditionally enable the test here. - if cfg!(miri) { - assert_biteq!(Float::SNAN.min(black_box(9.0)), 9.0); - assert_biteq!(black_box(Float::SNAN).min(-9.0), -9.0); - assert_biteq!(flt(9.0).min(black_box(Float::SNAN)), 9.0); - assert_biteq!(black_box(flt(-9.0)).min(Float::SNAN), -9.0); - } + assert_biteq!(Float::SNAN.min(black_box(9.0)), 9.0); + assert_biteq!(black_box(Float::SNAN).min(-9.0), -9.0); + assert_biteq!(flt(9.0).min(black_box(Float::SNAN)), 9.0); + assert_biteq!(black_box(flt(-9.0)).min(Float::SNAN), -9.0); assert!(Float::SNAN.min(Float::SNAN).is_nan()); } } @@ -770,15 +765,10 @@ float_test! { assert_biteq!(flt(9.0).max(black_box(Float::NAN)), 9.0); assert_biteq!(black_box(flt(-9.0)).max(Float::NAN), -9.0); assert!(Float::NAN.max(Float::NAN).is_nan()); - // FIXME(llvm21): LLVM miscompiles the fallback impl on aarch64 and likely other targets - // (https://github.com/llvm/llvm-project/issues/176624). When we require LLVM 22, - // remove the ui test `tests/ui/float/minmax.rs` and unconditionally enable the test here. - if cfg!(miri) { - assert_biteq!(Float::SNAN.max(black_box(9.0)), 9.0); - assert_biteq!(black_box(Float::SNAN).max(-9.0), -9.0); - assert_biteq!(flt(9.0).max(black_box(Float::SNAN)), 9.0); - assert_biteq!(black_box(flt(-9.0)).max(Float::SNAN), -9.0); - } + assert_biteq!(Float::SNAN.max(black_box(9.0)), 9.0); + assert_biteq!(black_box(Float::SNAN).max(-9.0), -9.0); + assert_biteq!(flt(9.0).max(black_box(Float::SNAN)), 9.0); + assert_biteq!(black_box(flt(-9.0)).max(Float::SNAN), -9.0); assert!(Float::SNAN.max(Float::SNAN).is_nan()); } } diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs index 625b3959d3326..5dae391cc4bee 100644 --- a/src/bootstrap/src/core/build_steps/llvm.rs +++ b/src/bootstrap/src/core/build_steps/llvm.rs @@ -804,11 +804,11 @@ fn check_llvm_version(builder: &Builder<'_>, llvm_config: &Path) { let version = get_llvm_version(builder, llvm_config); let mut parts = version.split('.').take(2).filter_map(|s| s.parse::().ok()); if let (Some(major), Some(_minor)) = (parts.next(), parts.next()) - && major >= 21 + && major >= 22 { return; } - panic!("\n\nbad LLVM version: {version}, need >=21\n\n") + panic!("\n\nbad LLVM version: {version}, need >=22\n\n") } /// C/C++ debug info remap flags for LLVM build. diff --git a/src/ci/docker/README.md b/src/ci/docker/README.md index 8360c8e9d8b48..167121a5a000c 100644 --- a/src/ci/docker/README.md +++ b/src/ci/docker/README.md @@ -14,9 +14,9 @@ To run a specific CI job locally, you can use the `citool` Rust crate: cargo run --manifest-path src/ci/citool/Cargo.toml run-local ``` -For example, to run the `x86_64-gnu-llvm-21-1` job: +For example, to run the `x86_64-gnu-llvm-22-1` job: ``` -cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-21-1 +cargo run --manifest-path src/ci/citool/Cargo.toml run-local x86_64-gnu-llvm-22-1 ``` The job will output artifacts in an `obj/` dir at the root of a repository. Note @@ -27,10 +27,10 @@ Docker image executed in the given CI job. while locally, to the `obj/` directory. This is primarily to prevent strange linker errors when using multiple Docker images. -For some Linux workflows (for example `x86_64-gnu-llvm-21-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-21-3` workflow, you can run the following script: +For some Linux workflows (for example `x86_64-gnu-llvm-22-N`), the process is more involved. You will need to see which script is executed for the given workflow inside the [`jobs.yml`](../github-actions/jobs.yml) file and pass it through the `DOCKER_SCRIPT` environment variable. For example, to reproduce the `x86_64-gnu-llvm-22-3` workflow, you can run the following script: ``` -DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-21 +DOCKER_SCRIPT=x86_64-gnu-llvm3.sh ./src/ci/docker/run.sh x86_64-gnu-llvm-22 ``` ## Local Development diff --git a/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile b/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-22/Dockerfile similarity index 89% rename from src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile rename to src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-22/Dockerfile index fe6c2d40f5f5c..53030a098841d 100644 --- a/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-21/Dockerfile +++ b/src/ci/docker/host-aarch64/test-aarch64-gnu-llvm-22/Dockerfile @@ -1,4 +1,4 @@ -FROM ubuntu:25.10 +FROM ubuntu:26.04 ARG DEBIAN_FRONTEND=noninteractive @@ -15,10 +15,10 @@ RUN apt-get update && apt-get install -y --no-install-recommends \ cmake \ sudo \ gdb \ - llvm-21-tools \ - llvm-21-dev \ - lldb-21 \ - python3-lldb-21 \ + llvm-22-tools \ + llvm-22-dev \ + lldb-22 \ + python3-lldb-22 \ libedit-dev \ libssl-dev \ pkg-config \ @@ -43,11 +43,11 @@ ENV NO_DOWNLOAD_CI_LLVM="1" ENV EXTERNAL_LLVM="1" # Override the default debugger `discover` behavior -ENV LLDB_PATH="lldb-21" +ENV LLDB_PATH="lldb-22" # Using llvm-link-shared due to libffi issues -- see #34486 ENV RUST_CONFIGURE_ARGS="--build=aarch64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-21 \ + --llvm-root=/usr/lib/llvm-22 \ --enable-llvm-link-shared \ --set rust.randomize-layout=true \ --set rust.thin-lto-import-instr-limit=10" diff --git a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-21/Dockerfile b/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-21/Dockerfile deleted file mode 100644 index fc96735521077..0000000000000 --- a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-21/Dockerfile +++ /dev/null @@ -1,65 +0,0 @@ -FROM ubuntu:25.10 - -ARG DEBIAN_FRONTEND=noninteractive - -RUN apt-get update && apt-get install -y --no-install-recommends \ - bzip2 \ - g++ \ - gcc-multilib \ - make \ - ninja-build \ - file \ - curl \ - ca-certificates \ - python3 \ - git \ - cmake \ - sudo \ - gdb \ - llvm-21-tools \ - llvm-21-dev \ - libedit-dev \ - libssl-dev \ - pkg-config \ - zlib1g-dev \ - xz-utils \ - nodejs \ - mingw-w64 \ - # libgccjit dependencies - flex \ - libmpfr-dev \ - libgmp-dev \ - libmpc3 \ - libmpc-dev \ - && rm -rf /var/lib/apt/lists/* - -# Install powershell (universal package) so we can test x.ps1 on Linux -# FIXME: need a "universal" version that supports libicu74, but for now it still works to ignore that dep. -RUN curl -sL "https://github.com/PowerShell/PowerShell/releases/download/v7.3.1/powershell_7.3.1-1.deb_amd64.deb" > powershell.deb && \ - dpkg --ignore-depends=libicu72 -i powershell.deb && \ - rm -f powershell.deb - -COPY scripts/sccache.sh /scripts/ -RUN sh /scripts/sccache.sh - -# We are disabling CI LLVM since this builder is intentionally using a host -# LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM="1" -ENV EXTERNAL_LLVM="1" - -# Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ - --llvm-root=/usr/lib/llvm-21 \ - --enable-llvm-link-shared \ - --set rust.randomize-layout=true \ - --set rust.thin-lto-import-instr-limit=10" - -COPY scripts/shared.sh /scripts/ - -COPY scripts/x86_64-gnu-llvm.sh /scripts/ -COPY scripts/x86_64-gnu-llvm2.sh /scripts/ -COPY scripts/x86_64-gnu-llvm3.sh /scripts/ -COPY scripts/stage_2_test_set1.sh /scripts/ -COPY scripts/stage_2_test_set2.sh /scripts/ - -ENV SCRIPT="Must specify DOCKER_SCRIPT for this image" diff --git a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile b/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile index a22e8de90804f..e7191aa31c47b 100644 --- a/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile +++ b/src/ci/docker/host-x86_64/test-x86_64-gnu-llvm-22/Dockerfile @@ -44,16 +44,15 @@ RUN sh /scripts/sccache.sh # We are disabling CI LLVM since this builder is intentionally using a host # LLVM, rather than the typical src/llvm-project LLVM. -ENV NO_DOWNLOAD_CI_LLVM 1 -ENV EXTERNAL_LLVM 1 +ENV NO_DOWNLOAD_CI_LLVM="1" +ENV EXTERNAL_LLVM="1" # Using llvm-link-shared due to libffi issues -- see #34486 -ENV RUST_CONFIGURE_ARGS \ - --build=x86_64-unknown-linux-gnu \ +ENV RUST_CONFIGURE_ARGS="--build=x86_64-unknown-linux-gnu \ --llvm-root=/usr/lib/llvm-22 \ --enable-llvm-link-shared \ --set rust.randomize-layout=true \ - --set rust.thin-lto-import-instr-limit=10 + --set rust.thin-lto-import-instr-limit=10" COPY scripts/shared.sh /scripts/ @@ -63,4 +62,4 @@ COPY scripts/x86_64-gnu-llvm3.sh /scripts/ COPY scripts/stage_2_test_set1.sh /scripts/ COPY scripts/stage_2_test_set2.sh /scripts/ -ENV SCRIPT "Must specify DOCKER_SCRIPT for this image" +ENV SCRIPT="Must specify DOCKER_SCRIPT for this image" diff --git a/src/ci/docker/scripts/stage_2_test_set1.sh b/src/ci/docker/scripts/stage_2_test_set1.sh index 62b3c2c051a40..15d24533c388d 100755 --- a/src/ci/docker/scripts/stage_2_test_set1.sh +++ b/src/ci/docker/scripts/stage_2_test_set1.sh @@ -14,14 +14,7 @@ if [ "$PR_CI_JOB" == "1" ]; then SKIP_TIDY="--skip tidy" fi -# Skip intrinsic-test on LLVM 21 to avoid CI failures. -if [ "$LLVM_VERSION" = "21" ]; then - echo "LLVM_VERSION is 21; skipping intrinsic-test" - SKIP_INTRINSICS="--skip intrinsic-test" -fi - ../x.py --stage 2 test \ ${SKIP_TIDY:+$SKIP_TIDY} \ - ${SKIP_INTRINSICS:+$SKIP_INTRINSICS} \ --skip compiler \ --skip src diff --git a/src/ci/docker/scripts/stage_2_test_set2.sh b/src/ci/docker/scripts/stage_2_test_set2.sh index c0cdc31011378..5a954f5e9e63f 100755 --- a/src/ci/docker/scripts/stage_2_test_set2.sh +++ b/src/ci/docker/scripts/stage_2_test_set2.sh @@ -14,25 +14,8 @@ if [ "$PR_CI_JOB" == "1" ]; then SKIP_TIDY="--skip tidy" fi -# The combination of rust.randomize-layout and LLVM 21 is causing random -# SIGSEGV in the `hir-def` rust-analyzer tests. Since it seems to be fixed in -# LLVM 22, let's just disable this for now since it has been disruptive for -# CI. See https://github.com/rust-lang/rust/issues/156460. -if [[ "$CI_JOB_NAME" == *"llvm-21"* ]]; then - echo "CI_JOB_NAME contains 'llvm-21'; skipping rust-analyzer" - SKIP_RUST_ANALYZER="--skip src/tools/rust-analyzer" -fi - -# Skip intrinsic-test on LLVM 21 to avoid CI failures. -if [ "$LLVM_VERSION" = "21" ]; then - echo "LLVM_VERSION is 21; skipping intrinsic-test" - SKIP_INTRINSICS="--skip intrinsic-test" -fi - ../x.py --stage 2 test \ ${SKIP_TIDY:+$SKIP_TIDY} \ - ${SKIP_INTRINSICS:+$SKIP_INTRINSICS} \ - ${SKIP_RUST_ANALYZER:+$SKIP_RUST_ANALYZER} \ --skip tests \ --skip library \ --skip tidyselftest diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml index 0fdf50d20a255..57432451b9798 100644 --- a/src/ci/github-actions/jobs.yml +++ b/src/ci/github-actions/jobs.yml @@ -126,21 +126,21 @@ pr: # tidy. This speeds up the PR CI job by ~1 minute. SKIP_SUBMODULES: src/gcc <<: *job-linux-4c - - name: test-x86_64-gnu-llvm-21 + - name: test-x86_64-gnu-llvm-22 env: ENABLE_GCC_CODEGEN: "1" DOCKER_SCRIPT: x86_64-gnu-llvm.sh <<: *job-linux-4c - - name: test-aarch64-gnu-llvm-21-1 + - name: test-aarch64-gnu-llvm-22-1 env: - IMAGE: test-aarch64-gnu-llvm-21 - LLVM_VERSION: "21" + IMAGE: test-aarch64-gnu-llvm-22 + LLVM_VERSION: "22" DOCKER_SCRIPT: stage_2_test_set1.sh <<: *job-aarch64-linux - - name: test-aarch64-gnu-llvm-21-2 + - name: test-aarch64-gnu-llvm-22-2 env: - IMAGE: test-aarch64-gnu-llvm-21 - LLVM_VERSION: "21" + IMAGE: test-aarch64-gnu-llvm-22 + LLVM_VERSION: "22" DOCKER_SCRIPT: stage_2_test_set2.sh <<: *job-aarch64-linux - name: test-x86_64-gnu-tools @@ -428,40 +428,13 @@ auto: - name: test-x86_64-gnu-distcheck <<: *job-linux-4c - # The x86_64-gnu-llvm-21 job is split into multiple jobs to run tests in parallel. - # x86_64-gnu-llvm-21-1 skips tests that run in x86_64-gnu-llvm-21-{2,3}. - - name: test-x86_64-gnu-llvm-21-1 - env: - RUST_BACKTRACE: 1 - IMAGE: test-x86_64-gnu-llvm-21 - LLVM_VERSION: "21" - DOCKER_SCRIPT: stage_2_test_set2.sh - <<: *job-linux-4c - - # Skip tests that run in x86_64-gnu-llvm-21-{1,3} - - name: test-x86_64-gnu-llvm-21-2 - env: - RUST_BACKTRACE: 1 - IMAGE: test-x86_64-gnu-llvm-21 - LLVM_VERSION: "21" - DOCKER_SCRIPT: x86_64-gnu-llvm2.sh - <<: *job-linux-4c - - # Skip tests that run in x86_64-gnu-llvm-21-{1,2} - - name: test-x86_64-gnu-llvm-21-3 - env: - RUST_BACKTRACE: 1 - IMAGE: test-x86_64-gnu-llvm-21 - LLVM_VERSION: "21" - DOCKER_SCRIPT: x86_64-gnu-llvm3.sh - <<: *job-linux-4c - # The x86_64-gnu-llvm-22 job is split into multiple jobs to run tests in parallel. # x86_64-gnu-llvm-22-1 skips tests that run in x86_64-gnu-llvm-22-{2,3}. - name: test-x86_64-gnu-llvm-22-1 env: RUST_BACKTRACE: 1 IMAGE: test-x86_64-gnu-llvm-22 + LLVM_VERSION: "22" DOCKER_SCRIPT: stage_2_test_set2.sh <<: *job-linux-4c @@ -470,6 +443,7 @@ auto: env: RUST_BACKTRACE: 1 IMAGE: test-x86_64-gnu-llvm-22 + LLVM_VERSION: "22" DOCKER_SCRIPT: x86_64-gnu-llvm2.sh <<: *job-linux-4c @@ -478,6 +452,7 @@ auto: env: RUST_BACKTRACE: 1 IMAGE: test-x86_64-gnu-llvm-22 + LLVM_VERSION: "22" DOCKER_SCRIPT: x86_64-gnu-llvm3.sh <<: *job-linux-4c diff --git a/tests/assembly-llvm/asm/loongarch-type.rs b/tests/assembly-llvm/asm/loongarch-type.rs index 5efad583a39df..124d82c5d5d6c 100644 --- a/tests/assembly-llvm/asm/loongarch-type.rs +++ b/tests/assembly-llvm/asm/loongarch-type.rs @@ -8,7 +8,6 @@ //@[loongarch32r] compile-flags: --target loongarch32-unknown-none //@[loongarch32r] needs-llvm-components: loongarch -//@[loongarch32r] min-llvm-version: 22 //@[loongarch64] compile-flags: --target loongarch64-unknown-none //@[loongarch64] needs-llvm-components: loongarch diff --git a/tests/assembly-llvm/asm/powerpc-types.rs b/tests/assembly-llvm/asm/powerpc-types.rs index 1fbf4be0aa3c5..44e14b53b8c52 100644 --- a/tests/assembly-llvm/asm/powerpc-types.rs +++ b/tests/assembly-llvm/asm/powerpc-types.rs @@ -35,8 +35,6 @@ //@ compile-flags: -Zmerge-functions=disabled -Copt-level=3 //@ compile-flags: --check-cfg=cfg(altivec,vsx,power9,power9be) -// PowerPC `f16` was broken before LLVM 22 -//@ min-llvm-version: 22 #![feature(no_core, f16)] #![cfg_attr(vsx, feature(f128))] diff --git a/tests/assembly-llvm/asm/sparc-types.rs b/tests/assembly-llvm/asm/sparc-types.rs index e7f2d84e470a0..9fabd8dcdd09e 100644 --- a/tests/assembly-llvm/asm/sparc-types.rs +++ b/tests/assembly-llvm/asm/sparc-types.rs @@ -11,7 +11,6 @@ //@[sparc64] filecheck-flags: --check-prefix v9 //@ compile-flags: -Zmerge-functions=disabled -Copt-level=3 //@ compile-flags: --check-cfg=cfg(v9) -//@ min-llvm-version: 22 #![deny(unexpected_cfgs)] #![feature(no_core, asm_experimental_arch, f128)] diff --git a/tests/assembly-llvm/asm/xtensa-types.rs b/tests/assembly-llvm/asm/xtensa-types.rs index 69c22d22b8b9a..9419a78f9e07c 100644 --- a/tests/assembly-llvm/asm/xtensa-types.rs +++ b/tests/assembly-llvm/asm/xtensa-types.rs @@ -1,7 +1,6 @@ //@ add-minicore //@ assembly-output: emit-asm //@ compile-flags: --target xtensa-esp32-none-elf -Zmerge-functions=disabled -//@ min-llvm-version: 22 //@ needs-llvm-components: xtensa #![feature(no_core, lang_items, rustc_attrs, asm_experimental_arch)] diff --git a/tests/assembly-llvm/bpf_unaligned.rs b/tests/assembly-llvm/bpf_unaligned.rs index 466c3e411ec2c..ba221fff5bea9 100644 --- a/tests/assembly-llvm/bpf_unaligned.rs +++ b/tests/assembly-llvm/bpf_unaligned.rs @@ -1,7 +1,6 @@ //@ add-minicore //@ assembly-output: emit-asm //@ compile-flags: --target bpfel-unknown-none -C target_feature=+allows-misaligned-mem-access -//@ min-llvm-version: 22 //@ needs-llvm-components: bpf #![feature(no_core)] #![crate_type = "rlib"] diff --git a/tests/assembly-llvm/c-variadic/xtensa.rs b/tests/assembly-llvm/c-variadic/xtensa.rs index a070980cff3d6..31e3c427d4e05 100644 --- a/tests/assembly-llvm/c-variadic/xtensa.rs +++ b/tests/assembly-llvm/c-variadic/xtensa.rs @@ -1,6 +1,5 @@ //@ add-minicore //@ assembly-output: emit-asm -//@ min-llvm-version: 22 // //@ revisions: XTENSA //@ [XTENSA] compile-flags: -Copt-level=3 --target xtensa-esp32-none-elf diff --git a/tests/assembly-llvm/cmse-clear-padding.rs b/tests/assembly-llvm/cmse-clear-padding.rs index 93b10845ea511..271a844a6e82d 100644 --- a/tests/assembly-llvm/cmse-clear-padding.rs +++ b/tests/assembly-llvm/cmse-clear-padding.rs @@ -1,5 +1,4 @@ //@ add-minicore -//@ min-llvm-version: 22 //@ assembly-output: emit-asm //@ compile-flags: --target thumbv8m.main-none-eabi --crate-type lib -Copt-level=1 //@ needs-llvm-components: arm diff --git a/tests/assembly-llvm/tail-call-indirect.rs b/tests/assembly-llvm/tail-call-indirect.rs index 918283966b405..bdebb1f3c30e1 100644 --- a/tests/assembly-llvm/tail-call-indirect.rs +++ b/tests/assembly-llvm/tail-call-indirect.rs @@ -1,5 +1,4 @@ //@ add-minicore -//@ min-llvm-version: 22 //@ assembly-output: emit-asm //@ needs-llvm-components: x86 //@ compile-flags: --target=x86_64-unknown-linux-gnu diff --git a/tests/assembly-llvm/targets/targets-elf.rs b/tests/assembly-llvm/targets/targets-elf.rs index 971e9700035e5..f5c6277ff106c 100644 --- a/tests/assembly-llvm/targets/targets-elf.rs +++ b/tests/assembly-llvm/targets/targets-elf.rs @@ -845,9 +845,6 @@ //@ [xtensa_esp32s3_espidf] compile-flags: --target xtensa-esp32s3-espidf //@ [xtensa_esp32s3_espidf] needs-llvm-components: xtensa -// xtensa support requires a more recent LLVM. -//@ min-llvm-version: 22 - // Sanity-check that each target can produce assembly code. #![feature(no_core, lang_items)] diff --git a/tests/codegen-llvm/amdgpu-addrspacecast.rs b/tests/codegen-llvm/amdgpu-addrspacecast.rs index 144565f7e28ca..0b15c86d9d22b 100644 --- a/tests/codegen-llvm/amdgpu-addrspacecast.rs +++ b/tests/codegen-llvm/amdgpu-addrspacecast.rs @@ -3,23 +3,20 @@ //@ compile-flags: --crate-type=rlib --target=amdgcn-amd-amdhsa -Ctarget-cpu=gfx900 -O //@ needs-llvm-components: amdgpu //@ add-minicore -//@ revisions: LLVM21 LLVM22 -//@ [LLVM21] max-llvm-major-version: 21 -//@ [LLVM22] min-llvm-version: 22 #![feature(no_core)] #![no_core] extern crate minicore; -// Make sure that on LLVM 22, the alloca is passed directly to the lifetime intrinsics, +// Make sure that on LLVM 22+, the alloca is passed directly to the lifetime intrinsics, // not the addrspacecast. // CHECK-LABEL: @ref_of_local // CHECK: [[alloca:%[0-9]]] = alloca // CHECK: %i = addrspacecast ptr addrspace(5) [[alloca]] to ptr -// LLVM22: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[alloca]]) +// CHECK: call void @llvm.lifetime.start.p5(ptr addrspace(5) [[alloca]]) // CHECK: call void %f(ptr{{.*}}%i) -// LLVM22: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[alloca]]) +// CHECK: call void @llvm.lifetime.end.p5(ptr addrspace(5) [[alloca]]) #[no_mangle] pub fn ref_of_local(f: fn(&i32)) { let i = 0; diff --git a/tests/codegen-llvm/const-vector.rs b/tests/codegen-llvm/const-vector.rs index e9e6188f804c0..39492b38f63d4 100644 --- a/tests/codegen-llvm/const-vector.rs +++ b/tests/codegen-llvm/const-vector.rs @@ -1,5 +1,4 @@ //@ revisions: OPT0 OPT0_S390X -//@ min-llvm-version: 22 //@ [OPT0] ignore-s390x //@ [OPT0_S390X] only-s390x //@ [OPT0] compile-flags: -C no-prepopulate-passes -Copt-level=0 diff --git a/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs b/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs index 5b100d2cdc381..9115824669f27 100644 --- a/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs +++ b/tests/codegen-llvm/issues/issue-122600-ptr-discriminant-update.rs @@ -1,7 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ revisions: new old -//@ [old] max-llvm-major-version: 21 -//@ [new] min-llvm-version: 22 #![crate_type = "lib"] @@ -25,9 +22,6 @@ pub unsafe fn update(s: *mut State) { // CHECK-NOT: memcpy // CHECK-NOT: 75{{3|4}} - // old: %[[TAG:.+]] = load i8, ptr %s, align 1 - // old-NEXT: and i8 %[[TAG]], 1 - // CHECK-NOT: load // CHECK-NOT: store // CHECK-NOT: memcpy diff --git a/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs b/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs index d01815954b237..b47637a687bb0 100644 --- a/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs +++ b/tests/codegen-llvm/pauth/pauth-extern-c-direct-indirect-call.rs @@ -4,9 +4,6 @@ //@ [O0_PAUTH] needs-llvm-components: aarch64 //@ [O0_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=0 -// O3_PAUTH relies on an InstCombine fold that removes the redundant `ptrauth` bundle from calls. -// That fold first shipped in LLVM 22, gate this revision accordingly. -//@ [O3_PAUTH] min-llvm-version: 22 //@ [O3_PAUTH] needs-llvm-components: aarch64 //@ [O3_PAUTH] compile-flags: --target=aarch64-unknown-linux-pauthtest -C opt-level=3 diff --git a/tests/codegen-llvm/scalable-vectors/debuginfo.rs b/tests/codegen-llvm/scalable-vectors/debuginfo.rs index 8b2724f06f3e0..1ed7c37a49915 100644 --- a/tests/codegen-llvm/scalable-vectors/debuginfo.rs +++ b/tests/codegen-llvm/scalable-vectors/debuginfo.rs @@ -2,9 +2,6 @@ //@ only-aarch64 //@ only-linux //@ compile-flags: -Cdebuginfo=2 -Copt-level=0 -//@ revisions: POST-LLVM-22 PRE-LLVM-22 -//@ [PRE-LLVM-22] max-llvm-major-version: 21 -//@ [POST-LLVM-22] min-llvm-version: 22 #![crate_type = "lib"] #![allow(incomplete_features, internal_features)] @@ -59,8 +56,7 @@ struct svfloat64_t(f64); #[target_feature(enable = "sve")] pub fn locals() { // CHECK-DAG: name: "svbool_t",{{.*}}, baseType: ![[CT1:[0-9]+]] - // PRE-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]]) - // POST-LLVM-22-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]], bitStride: i64 1) + // CHECK-DAG: ![[CT1]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8:[0-9]+]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8:[0-9]+]], bitStride: i64 1) // CHECK-DAG: ![[ELTTYU8]] = !DIBasicType(name: "u8", size: 8, encoding: DW_ATE_unsigned) // CHECK-DAG: ![[ELTS8]] = !{![[REALELTS8:[0-9]+]]} // CHECK-DAG: ![[REALELTS8]] = !DISubrange(lowerBound: 0, upperBound: !DIExpression(DW_OP_constu, 8, DW_OP_bregx, 46, 0, DW_OP_mul, DW_OP_constu, 1, DW_OP_minus)) @@ -71,9 +67,8 @@ pub fn locals() { // CHECK-DAG: ![[ELTTYS8]] = !DIBasicType(name: "i8", size: 8, encoding: DW_ATE_signed) let s8: svint8_t; - // PRE-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT1:[0-9]+]] - // POST-LLVM-22-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]] - // POST-LLVM-22-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8]]) + // CHECK-DAG: name: "svuint8_t",{{.*}}, baseType: ![[CT8:[0-9]+]] + // CHECK-DAG: ![[CT8]] = !DICompositeType(tag: DW_TAG_array_type, baseType: ![[ELTTYU8]],{{.*}}, flags: DIFlagVector, elements: ![[ELTS8]]) let u8: svuint8_t; // CHECK-DAG: name: "svint16_t",{{.*}}, baseType: ![[CT16:[0-9]+]] diff --git a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-gather.rs b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-gather.rs index d79a9cf96ada3..643a3c984332c 100644 --- a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-gather.rs +++ b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-gather.rs @@ -1,9 +1,4 @@ -// - //@ compile-flags: -C no-prepopulate-passes -//@ revisions: LLVM21 LLVM22 -//@ [LLVM22] min-llvm-version: 22 -//@ [LLVM21] max-llvm-major-version: 21 // ignore-tidy-linelength #![crate_type = "lib"] @@ -28,8 +23,7 @@ pub unsafe fn gather_f32x2( ) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) - // LLVM22: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) + // CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) simd_gather(values, pointers, mask) } @@ -42,8 +36,7 @@ pub unsafe fn gather_f32x2_unsigned( ) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) - // LLVM22: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) + // CHECK: call <2 x float> @llvm.masked.gather.v2f32.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) simd_gather(values, pointers, mask) } @@ -56,7 +49,6 @@ pub unsafe fn gather_pf32x2( ) -> Vec2<*const f32> { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x ptr> @llvm.masked.gather.v2p0.v2p0(<2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]], <2 x ptr> {{.*}}) - // LLVM22: call <2 x ptr> @llvm.masked.gather.v2p0.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x ptr> {{.*}}) + // CHECK: call <2 x ptr> @llvm.masked.gather.v2p0.v2p0(<2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]], <2 x ptr> {{.*}}) simd_gather(values, pointers, mask) } diff --git a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-load.rs index ffe3851c5ad71..e0050431f5b47 100644 --- a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-load.rs +++ b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-load.rs @@ -1,7 +1,4 @@ //@ compile-flags: -C no-prepopulate-passes -//@ revisions: LLVM21 LLVM22 -//@ [LLVM22] min-llvm-version: 22 -//@ [LLVM21] max-llvm-major-version: 21 // ignore-tidy-linelength #![crate_type = "lib"] @@ -22,10 +19,7 @@ pub type Vec4 = Simd; pub unsafe fn load_f32x2(mask: Vec2, pointer: *const f32, values: Vec2) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 4, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^ - // LLVM22: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 4 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^^^ + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 4 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) // the align parameter should be equal to the alignment of the element type (assumed to be 4) simd_masked_load::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } @@ -39,10 +33,7 @@ pub unsafe fn load_f32x2_aligned( ) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 8, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^ - // LLVM22: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 8 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^^^ + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 8 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) // the align parameter should be equal to the size of the vector simd_masked_load::<_, _, _, { SimdAlign::Vector }>(mask, pointer, values) } @@ -56,10 +47,7 @@ pub unsafe fn load_f32x2_unaligned( ) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 1, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^ - // LLVM22: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 1 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) - // ^^^^^^^ + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 1 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) // the align parameter should be 1 simd_masked_load::<_, _, _, { SimdAlign::Unaligned }>(mask, pointer, values) } @@ -73,8 +61,7 @@ pub unsafe fn load_f32x2_unsigned( ) -> Vec2 { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 4, <2 x i1> [[B]], <2 x float> {{.*}}) - // LLVM22: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 4 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) + // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr align 4 {{.*}}, <2 x i1> [[B]], <2 x float> {{.*}}) simd_masked_load::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } @@ -87,7 +74,6 @@ pub unsafe fn load_pf32x4( ) -> Vec4<*const f32> { // CHECK: [[A:%[0-9]+]] = lshr <4 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1> - // LLVM21: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> [[B]], <4 x ptr> {{.*}}) - // LLVM22: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr align {{.*}} {{.*}}, <4 x i1> [[B]], <4 x ptr> {{.*}}) + // CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr align {{.*}} {{.*}}, <4 x i1> [[B]], <4 x ptr> {{.*}}) simd_masked_load::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } diff --git a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-store.rs index efeeceec09d12..d9bd214609962 100644 --- a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-store.rs +++ b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-masked-store.rs @@ -1,7 +1,4 @@ //@ compile-flags: -C no-prepopulate-passes -//@ revisions: LLVM21 LLVM22 -//@ [LLVM22] min-llvm-version: 22 -//@ [LLVM21] max-llvm-major-version: 21 // ignore-tidy-linelength #![crate_type = "lib"] @@ -22,10 +19,7 @@ pub type Vec4 = Simd; pub unsafe fn store_f32x2(mask: Vec2, pointer: *mut f32, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 4, <2 x i1> [[B]]) - // ^^^^^ - // LLVM22: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 4 {{.*}}, <2 x i1> [[B]]) - // ^^^^^^^ + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 4 {{.*}}, <2 x i1> [[B]]) // the align parameter should be equal to the alignment of the element type (assumed to be 4) simd_masked_store::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } @@ -35,10 +29,7 @@ pub unsafe fn store_f32x2(mask: Vec2, pointer: *mut f32, values: Vec2) pub unsafe fn store_f32x2_aligned(mask: Vec2, pointer: *mut f32, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 8, <2 x i1> [[B]]) - // ^^^^^ - // LLVM22: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 8 {{.*}}, <2 x i1> [[B]]) - // ^^^^^^^ + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 8 {{.*}}, <2 x i1> [[B]]) // the align parameter should be equal to the size of the vector simd_masked_store::<_, _, _, { SimdAlign::Vector }>(mask, pointer, values) } @@ -48,10 +39,7 @@ pub unsafe fn store_f32x2_aligned(mask: Vec2, pointer: *mut f32, values: Ve pub unsafe fn store_f32x2_unaligned(mask: Vec2, pointer: *mut f32, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 1, <2 x i1> [[B]]) - // ^^^^^ - // LLVM22: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 1 {{.*}}, <2 x i1> [[B]]) - // ^^^^^^^ + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 1 {{.*}}, <2 x i1> [[B]]) // the align parameter should be 1 simd_masked_store::<_, _, _, { SimdAlign::Unaligned }>(mask, pointer, values) } @@ -61,8 +49,7 @@ pub unsafe fn store_f32x2_unaligned(mask: Vec2, pointer: *mut f32, values: pub unsafe fn store_f32x2_unsigned(mask: Vec2, pointer: *mut f32, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 4, <2 x i1> [[B]]) - // LLVM22: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 4 {{.*}}, <2 x i1> [[B]]) + // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr align 4 {{.*}}, <2 x i1> [[B]]) simd_masked_store::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } @@ -71,7 +58,6 @@ pub unsafe fn store_f32x2_unsigned(mask: Vec2, pointer: *mut f32, values: V pub unsafe fn store_pf32x4(mask: Vec4, pointer: *mut *const f32, values: Vec4<*const f32>) { // CHECK: [[A:%[0-9]+]] = lshr <4 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <4 x i32> [[A]] to <4 x i1> - // LLVM21: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> [[B]]) - // LLVM22: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr align {{.*}} {{.*}}, <4 x i1> [[B]]) + // CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr align {{.*}} {{.*}}, <4 x i1> [[B]]) simd_masked_store::<_, _, _, { SimdAlign::Element }>(mask, pointer, values) } diff --git a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-scatter.rs b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-scatter.rs index 533fa429ae700..5c6f82d367cf0 100644 --- a/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-scatter.rs +++ b/tests/codegen-llvm/simd-intrinsic/simd-intrinsic-generic-scatter.rs @@ -1,9 +1,4 @@ -// - //@ compile-flags: -C no-prepopulate-passes -//@ revisions: LLVM21 LLVM22 -//@ [LLVM22] min-llvm-version: 22 -//@ [LLVM21] max-llvm-major-version: 21 // ignore-tidy-linelength #![crate_type = "lib"] @@ -24,8 +19,7 @@ pub type Vec4 = Simd; pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]] - // LLVM22: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] + // CHECK: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] simd_scatter(values, pointers, mask) } @@ -34,8 +28,7 @@ pub unsafe fn scatter_f32x2(pointers: Vec2<*mut f32>, mask: Vec2, values: V pub unsafe fn scatter_f32x2_unsigned(pointers: Vec2<*mut f32>, mask: Vec2, values: Vec2) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]] - // LLVM22: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] + // CHECK: call void @llvm.masked.scatter.v2f32.v2p0(<2 x float> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] simd_scatter(values, pointers, mask) } @@ -48,7 +41,6 @@ pub unsafe fn scatter_pf32x2( ) { // CHECK: [[A:%[0-9]+]] = lshr <2 x i32> {{.*}}, {{|splat \(i32 31\)}} // CHECK: [[B:%[0-9]+]] = trunc <2 x i32> [[A]] to <2 x i1> - // LLVM21: call void @llvm.masked.scatter.v2p0.v2p0(<2 x ptr> {{.*}}, <2 x ptr> {{.*}}, i32 {{.*}}, <2 x i1> [[B]] - // LLVM22: call void @llvm.masked.scatter.v2p0.v2p0(<2 x ptr> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] + // CHECK: call void @llvm.masked.scatter.v2p0.v2p0(<2 x ptr> {{.*}}, <2 x ptr> align {{.*}} {{.*}}, <2 x i1> [[B]] simd_scatter(values, pointers, mask) } diff --git a/tests/codegen-llvm/slp-vectorization-mul3.rs b/tests/codegen-llvm/slp-vectorization-mul3.rs index 38c0949b82713..1c40c6b28f3ff 100644 --- a/tests/codegen-llvm/slp-vectorization-mul3.rs +++ b/tests/codegen-llvm/slp-vectorization-mul3.rs @@ -1,7 +1,6 @@ //! Regression test for #142519 //@ only-x86_64 //@ compile-flags: -O -//@ min-llvm-version: 22 #![crate_type = "lib"] diff --git a/tests/codegen-llvm/store-captures.rs b/tests/codegen-llvm/store-captures.rs index 33d24032ee450..24cbb91cf29ee 100644 --- a/tests/codegen-llvm/store-captures.rs +++ b/tests/codegen-llvm/store-captures.rs @@ -1,4 +1,3 @@ -//@ min-llvm-version: 22 //@ compile-flags: -O -C no-prepopulate-passes #![crate_type = "lib"] diff --git a/tests/codegen-llvm/tail-call-u128.rs b/tests/codegen-llvm/tail-call-u128.rs index 25dfc47a2bfec..b3aab7d93d46c 100644 --- a/tests/codegen-llvm/tail-call-u128.rs +++ b/tests/codegen-llvm/tail-call-u128.rs @@ -1,6 +1,5 @@ //@ add-minicore //@ revisions: win linux -//@ min-llvm-version: 22 // //@ compile-flags: -Copt-level=3 //@[linux] compile-flags: --target x86_64-unknown-linux-gnu diff --git a/tests/codegen-llvm/vec_pop_push_noop.rs b/tests/codegen-llvm/vec_pop_push_noop.rs index 977c220b3baef..9bfc77eaa6fa3 100644 --- a/tests/codegen-llvm/vec_pop_push_noop.rs +++ b/tests/codegen-llvm/vec_pop_push_noop.rs @@ -1,7 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ revisions: new old -//@ [old] max-llvm-major-version: 21 -//@ [new] min-llvm-version: 22 #![crate_type = "lib"] @@ -10,7 +7,6 @@ pub fn noop(v: &mut Vec) { // CHECK-NOT: grow_one // CHECK-NOT: call - // old: tail call void @llvm.assume // CHECK-NOT: grow_one // CHECK-NOT: call // CHECK: {{ret|[}]}} diff --git a/tests/codegen-llvm/vecdeque_pop_push.rs b/tests/codegen-llvm/vecdeque_pop_push.rs index 6f9ad6674d6cd..7545a0b2e39c3 100644 --- a/tests/codegen-llvm/vecdeque_pop_push.rs +++ b/tests/codegen-llvm/vecdeque_pop_push.rs @@ -1,7 +1,4 @@ //@ compile-flags: -Copt-level=3 -//@ revisions: new old -//@ [old] max-llvm-major-version: 21 -//@ [new] min-llvm-version: 22 #![crate_type = "lib"] @@ -11,7 +8,6 @@ use std::collections::VecDeque; // CHECK-LABEL: @noop_back( pub fn noop_back(v: &mut VecDeque) { // CHECK-NOT: grow - // old: tail call void @llvm.assume // CHECK-NOT: grow // CHECK: ret if let Some(x) = v.pop_back() { diff --git a/tests/ui/codegen/huge-stacks.rs b/tests/ui/codegen/huge-stacks.rs index 790de95eb7416..f661d8728be1f 100644 --- a/tests/ui/codegen/huge-stacks.rs +++ b/tests/ui/codegen/huge-stacks.rs @@ -2,7 +2,6 @@ //@[optimized]compile-flags: -O //@ run-pass //@ only-64bit -//@ min-llvm-version: 22 // Regression test for https://github.com/rust-lang/rust/issues/83060 // Verifies a program is not miscompiled if it includes a 4GB array on the stack diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr index 33e190e1a4a7f..31ceec9afe081 100644 --- a/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.aarch64.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/no-unsized-arguments.rs:40:42 + --> $DIR/no-unsized-arguments.rs:39:42 | LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { | ^^^^ doesn't have a size known at compile-time @@ -11,7 +11,7 @@ LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { | + error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:33:5 + --> $DIR/no-unsized-arguments.rs:32:5 | LL | become unsized_argument(b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | become unsized_argument(b); = note: unsized argument of type `[u8]` error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:48:5 + --> $DIR/no-unsized-arguments.rs:47:5 | LL | become unsized_argument(*b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.rs b/tests/ui/explicit-tail-calls/no-unsized-arguments.rs index a0c5b53d8df0c..76a9a59c51a15 100644 --- a/tests/ui/explicit-tail-calls/no-unsized-arguments.rs +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.rs @@ -1,6 +1,5 @@ //@ add-minicore //@ ignore-backends: gcc -//@ min-llvm-version: 22 // //@ revisions: x86 x86_64 aarch64 // diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr index 33e190e1a4a7f..31ceec9afe081 100644 --- a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/no-unsized-arguments.rs:40:42 + --> $DIR/no-unsized-arguments.rs:39:42 | LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { | ^^^^ doesn't have a size known at compile-time @@ -11,7 +11,7 @@ LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { | + error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:33:5 + --> $DIR/no-unsized-arguments.rs:32:5 | LL | become unsized_argument(b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | become unsized_argument(b); = note: unsized argument of type `[u8]` error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:48:5 + --> $DIR/no-unsized-arguments.rs:47:5 | LL | become unsized_argument(*b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr index 33e190e1a4a7f..31ceec9afe081 100644 --- a/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr +++ b/tests/ui/explicit-tail-calls/no-unsized-arguments.x86_64.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation time - --> $DIR/no-unsized-arguments.rs:40:42 + --> $DIR/no-unsized-arguments.rs:39:42 | LL | extern "tail" fn unsized_argument(x: [u8]) -> u8 { | ^^^^ doesn't have a size known at compile-time @@ -11,7 +11,7 @@ LL | extern "tail" fn unsized_argument(x: &[u8]) -> u8 { | + error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:33:5 + --> $DIR/no-unsized-arguments.rs:32:5 | LL | become unsized_argument(b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -19,7 +19,7 @@ LL | become unsized_argument(b); = note: unsized argument of type `[u8]` error: unsized arguments cannot be used in a tail call - --> $DIR/no-unsized-arguments.rs:48:5 + --> $DIR/no-unsized-arguments.rs:47:5 | LL | become unsized_argument(*b); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/explicit-tail-calls/support/basic.rs b/tests/ui/explicit-tail-calls/support/basic.rs index d46dd726c0bd1..eb3041f106171 100644 --- a/tests/ui/explicit-tail-calls/support/basic.rs +++ b/tests/ui/explicit-tail-calls/support/basic.rs @@ -1,7 +1,6 @@ //@ build-pass //@ ignore-backends: gcc //@ add-minicore -//@ min-llvm-version: 22 // //@ revisions: i686 //@[i686] compile-flags: --target i686-unknown-linux-gnu diff --git a/tests/ui/explicit-tail-calls/support/bystack.rs b/tests/ui/explicit-tail-calls/support/bystack.rs index c89ad194f8ba1..8a9aa72bb5636 100644 --- a/tests/ui/explicit-tail-calls/support/bystack.rs +++ b/tests/ui/explicit-tail-calls/support/bystack.rs @@ -1,7 +1,6 @@ //@ build-pass //@ ignore-backends: gcc //@ add-minicore -//@ min-llvm-version: 22 // //@ revisions: i686 //@[i686] compile-flags: --target i686-unknown-linux-gnu @@ -33,6 +32,9 @@ //@ revisions: powerpc64 //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //@[powerpc64] needs-llvm-components: powerpc +// +// loongarch disabled musttail in LLVM 22, didn't come back in LLVM 23 +// //@ revisions: loongarch32 //@[loongarch32] compile-flags: --target loongarch32-unknown-none //@[loongarch32] needs-llvm-components: loongarch @@ -41,6 +43,7 @@ //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch //@[loongarch64] max-llvm-major-version: 21 +// //@ revisions: bpf //@[bpf] compile-flags: --target bpfeb-unknown-none //@[bpf] needs-llvm-components: bpf @@ -51,11 +54,12 @@ //@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda //@[nvptx64] needs-llvm-components: nvptx // -// Riscv does not support byval in LLVM 22 (but wil in LLVM 23) +// Riscv does not support byval in LLVM 22 (but does in LLVM 23+) // -// //@ revisions: riscv -// //@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu -// //@[riscv] needs-llvm-components: riscv +//@ revisions: riscv +//@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv] needs-llvm-components: riscv +//@[riscv] min-llvm-version: 23 // // Wasm needs a special target feature. // diff --git a/tests/ui/explicit-tail-calls/support/byval.rs b/tests/ui/explicit-tail-calls/support/byval.rs index e6f26b9292eb6..cea5f5a51aa9e 100644 --- a/tests/ui/explicit-tail-calls/support/byval.rs +++ b/tests/ui/explicit-tail-calls/support/byval.rs @@ -1,7 +1,6 @@ //@ build-pass //@ ignore-backends: gcc //@ add-minicore -//@ min-llvm-version: 22 // //@ revisions: i686 //@[i686] compile-flags: --target i686-unknown-linux-gnu @@ -33,6 +32,9 @@ //@ revisions: powerpc64 //@[powerpc64] compile-flags: --target powerpc64-unknown-linux-gnu //@[powerpc64] needs-llvm-components: powerpc +// +// loongarch dropped support for musttail in LLVM 22 and it didn't come back in 23 +// //@ revisions: loongarch32 //@[loongarch32] compile-flags: --target loongarch32-unknown-none //@[loongarch32] needs-llvm-components: loongarch @@ -41,6 +43,7 @@ //@[loongarch64] compile-flags: --target loongarch64-unknown-linux-gnu //@[loongarch64] needs-llvm-components: loongarch //@[loongarch64] max-llvm-major-version: 21 +// //@ revisions: bpf //@[bpf] compile-flags: --target bpfeb-unknown-none //@[bpf] needs-llvm-components: bpf @@ -51,11 +54,12 @@ //@[nvptx64] compile-flags: --target nvptx64-nvidia-cuda //@[nvptx64] needs-llvm-components: nvptx // -// Riscv does not support byval in LLVM 22 (but wil in LLVM 23) +// Riscv does not support byval in LLVM 22 (but does in LLVM 23+) // -// //@ revisions: riscv -// //@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu -// //@[riscv] needs-llvm-components: riscv +//@ revisions: riscv +//@[riscv] compile-flags: --target riscv64gc-unknown-linux-gnu +//@[riscv] needs-llvm-components: riscv +//@[riscv] min-llvm-version: 23 // // Wasm needs a special target feature. // diff --git a/tests/ui/feature-gates/feature-gate-xtensa-target-feature.rs b/tests/ui/feature-gates/feature-gate-xtensa-target-feature.rs index e9d6a35e0ab30..f08218fdae7f6 100644 --- a/tests/ui/feature-gates/feature-gate-xtensa-target-feature.rs +++ b/tests/ui/feature-gates/feature-gate-xtensa-target-feature.rs @@ -1,6 +1,5 @@ //@ add-minicore //@ needs-llvm-components: xtensa -//@ min-llvm-version: 22 //@ compile-flags: --target=xtensa-esp32-none-elf --crate-type=rlib //@ ignore-backends: gcc #![no_core] diff --git a/tests/ui/feature-gates/feature-gate-xtensa-target-feature.stderr b/tests/ui/feature-gates/feature-gate-xtensa-target-feature.stderr index 1854fbb3de4d2..d8dc56900f8f8 100644 --- a/tests/ui/feature-gates/feature-gate-xtensa-target-feature.stderr +++ b/tests/ui/feature-gates/feature-gate-xtensa-target-feature.stderr @@ -1,5 +1,5 @@ error[E0658]: the target feature `bool` is currently unstable - --> $DIR/feature-gate-xtensa-target-feature.rs:12:18 + --> $DIR/feature-gate-xtensa-target-feature.rs:11:18 | LL | #[target_feature(enable = "bool")] | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/float/minmax.rs b/tests/ui/float/minmax.rs deleted file mode 100644 index e6bac901d7922..0000000000000 --- a/tests/ui/float/minmax.rs +++ /dev/null @@ -1,22 +0,0 @@ -//FIXME(llvm21) This should be a library test, but old LLVM miscompiles things so we can't just -// test this properly everywhere. Once we require LLVM 22, remove this test and enable the -// commented-out tests in `library/coretests/tests/floats/mod.rs` instead. -//@ min-llvm-version: 22 -//@ run-pass - -use std::hint::black_box; - -const SNAN32: f32 = f32::from_bits(f32::NAN.to_bits() - 1); -const SNAN64: f64 = f64::from_bits(f64::NAN.to_bits() - 1); - -fn main() { - assert_eq!(SNAN32.min(black_box(9.0)), 9.0f32); - assert_eq!(black_box(SNAN32).min(-9.0), -9.0f32); - assert_eq!((9.0f32).min(black_box(SNAN32)), 9.0f32); - assert_eq!(black_box(-9.0f32).min(SNAN32), -9.0f32); - - assert_eq!(SNAN64.min(black_box(9.0)), 9.0f64); - assert_eq!(black_box(SNAN64).min(-9.0), -9.0f64); - assert_eq!((9.0f64).min(black_box(SNAN64)), 9.0f64); - assert_eq!(black_box(-9.0f64).min(SNAN64), -9.0f64); -} From a010cc6588ffc555722dc91cf98416a59f0426d9 Mon Sep 17 00:00:00 2001 From: itsjunetime Date: Fri, 2 Oct 2026 11:28:15 -0500 Subject: [PATCH 1201/1309] Add option to pass --frontend-threads to rustc-perf --- src/bootstrap/src/core/build_steps/perf.rs | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index e01ff61eb6f86..2ee8f1e921c1e 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -94,6 +94,11 @@ struct SharedOpts { #[clap(long, global = true)] database_path: Option, + + /// Comma-separated list of thread counts for the parallel frontend. Maps directly to the + /// `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1. + #[clap(long, global = true, value_delimiter = ',')] + frontend_threads: Vec, } #[derive(Clone, Copy, Debug, PartialEq, clap::ValueEnum)] @@ -257,4 +262,8 @@ fn apply_shared_opts(cmd: &mut BootstrapCommand, opts: &SharedOpts) { cmd.arg("--scenarios") .arg(opts.scenarios.iter().map(|p| p.to_string()).collect::>().join(",")); } + if !opts.frontend_threads.is_empty() { + cmd.arg("--frontend-threads") + .arg(opts.frontend_threads.iter().map(|p| p.to_string()).collect::>().join(",")); + } } From 0050bb2a1795a542f12fa20695d5da174347af14 Mon Sep 17 00:00:00 2001 From: itsjunetime Date: Fri, 2 Oct 2026 11:32:29 -0500 Subject: [PATCH 1202/1309] Regenerate completions --- src/etc/completions/x.fish | 4 ++++ src/etc/completions/x.ps1 | 4 ++++ src/etc/completions/x.py.fish | 4 ++++ src/etc/completions/x.py.ps1 | 4 ++++ src/etc/completions/x.py.sh | 24 ++++++++++++++++++++---- src/etc/completions/x.py.zsh | 4 ++++ src/etc/completions/x.sh | 24 ++++++++++++++++++++---- src/etc/completions/x.zsh | 4 ++++ 8 files changed, 64 insertions(+), 8 deletions(-) diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index 4ce38dd42033a..9a9142f3540ba 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -921,6 +921,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l database-path -r +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'host target of the stage0 compiler' -r -f @@ -961,6 +962,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l database-path -r +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'host target of the stage0 compiler' -r -f @@ -1001,6 +1003,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l database-path -r +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'host target of the stage0 compiler' -r -f @@ -1041,6 +1044,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l database-path -r +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'host target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index 61a4d0d65de91..9fe020c8e1cf6 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -1094,6 +1094,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1142,6 +1143,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1190,6 +1192,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1238,6 +1241,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 28b1767fc0e96..9f3056fdb3b63 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -921,6 +921,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l database-path -r +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'host target of the stage0 compiler' -r -f @@ -961,6 +962,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l database-path -r +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'host target of the stage0 compiler' -r -f @@ -1001,6 +1003,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l database-path -r +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'host target of the stage0 compiler' -r -f @@ -1041,6 +1044,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l database-path -r +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l frontend-threads -d 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'host target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 7178833189ac6..189b69df3c6f1 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -1094,6 +1094,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1142,6 +1143,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1190,6 +1192,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1238,6 +1241,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') + [CompletionResult]::new('--frontend-threads', '--frontend-threads', [CompletionResultType]::ParameterName, 'Comma-separated list of thread counts for the parallel frontend. Maps directly to the `-Zthreads` rustc option. If unspecified, `rustc-perf` uses only 1') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index f1b35e4cbc894..7bc3da600c2fe 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -3094,7 +3094,7 @@ _x.py() { return 0 ;; x.py__perf__benchmark) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3120,6 +3120,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3296,7 +3300,7 @@ _x.py() { return 0 ;; x.py__perf__cachegrind) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3322,6 +3326,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3688,7 +3696,7 @@ _x.py() { return 0 ;; x.py__perf__eprintln) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3714,6 +3722,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3890,7 +3902,7 @@ _x.py() { return 0 ;; x.py__perf__samply) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3916,6 +3928,10 @@ _x.py() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 8376e44746052..c06d0f316053a 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -1124,6 +1124,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1174,6 +1175,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1224,6 +1226,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1274,6 +1277,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh index be81e2e743e7c..a60e9083730e3 100644 --- a/src/etc/completions/x.sh +++ b/src/etc/completions/x.sh @@ -3094,7 +3094,7 @@ _x() { return 0 ;; x__perf__benchmark) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3120,6 +3120,10 @@ _x() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3296,7 +3300,7 @@ _x() { return 0 ;; x__perf__cachegrind) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3322,6 +3326,10 @@ _x() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3688,7 +3696,7 @@ _x() { return 0 ;; x__perf__eprintln) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3714,6 +3722,10 @@ _x() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3890,7 +3902,7 @@ _x() { return 0 ;; x__perf__samply) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --frontend-threads --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3916,6 +3928,10 @@ _x() { COMPREPLY=($(compgen -f "${cur}")) return 0 ;; + --frontend-threads) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index 3159859c1ea8e..21857db8899ab 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -1124,6 +1124,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1174,6 +1175,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1224,6 +1226,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1274,6 +1277,7 @@ _arguments "${_arguments_options[@]}" : \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ '--database-path=[]:DATABASE_PATH:_default' \ +'*--frontend-threads=[Comma-separated list of thread counts for the parallel frontend. Maps directly to the \`-Zthreads\` rustc option. If unspecified, \`rustc-perf\` uses only 1]:FRONTEND_THREADS:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ From d58b146cdef569d5d47db5ab31a44a1dcf3013ad Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Fri, 2 Oct 2026 22:58:19 +0530 Subject: [PATCH 1203/1309] Add doc inline validation tests --- tests/ui/rustdoc/doc-inline-validation.rs | 74 ++++++++++++++++ tests/ui/rustdoc/doc-inline-validation.stderr | 86 +++++++++++++++++++ 2 files changed, 160 insertions(+) create mode 100644 tests/ui/rustdoc/doc-inline-validation.rs create mode 100644 tests/ui/rustdoc/doc-inline-validation.stderr diff --git a/tests/ui/rustdoc/doc-inline-validation.rs b/tests/ui/rustdoc/doc-inline-validation.rs new file mode 100644 index 0000000000000..8a64f2bcf4284 --- /dev/null +++ b/tests/ui/rustdoc/doc-inline-validation.rs @@ -0,0 +1,74 @@ +//@ compile-flags: --crate-type lib + +// Valid use and extern crate targets +#[doc(inline)] +pub use std::vec::Vec; + +#[doc(no_inline)] +pub use std::string::String; + +#[doc(inline)] +pub extern crate std as my_std; + +#[doc(no_inline)] +pub extern crate core as my_core; + +// Repeated identical values +#[doc(inline)] +#[doc(inline)] +pub use std::option::Option; + +#[doc(no_inline)] +#[doc(no_inline)] +pub use std::result::Result; + +#[doc(inline, inline)] +pub use std::panic; + +// Conflicting values in both orders across separate attributes +#[doc(inline)] +//~^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +#[doc(no_inline)] +pub use std::fmt; + +#[doc(no_inline)] +//~^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +#[doc(inline)] +pub use std::io; + +// Conflicts within one doc list +#[doc(inline, no_inline)] +//~^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +pub use std::fs; + +// Invalid targets with relevant lint levels +#[deny(invalid_doc_attributes)] +#[doc(inline)] +//~^ ERROR this attribute can only be applied to a `use` item +pub fn fn_with_inline() {} + +#[allow(invalid_doc_attributes)] +#[doc(inline)] +pub fn fn_allowed() {} + +#[deny(invalid_doc_attributes)] +#[doc(no_inline)] +//~^ ERROR this attribute can only be applied to a `use` item +pub struct StructWithNoInline; + +// Conflict on an invalid target, preserving diagnostic precedence +#[deny(invalid_doc_attributes)] +#[doc(inline)] +//~^ ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes +#[doc(no_inline)] +pub struct ConflictOnStruct; + +// Malformed arguments without extra validation diagnostics +#[doc(inline = "foo")] +//~^ WARN didn't expect any arguments here +//~| WARN this was previously accepted +pub fn malformed_fn() {} diff --git a/tests/ui/rustdoc/doc-inline-validation.stderr b/tests/ui/rustdoc/doc-inline-validation.stderr new file mode 100644 index 0000000000000..f341273bf206f --- /dev/null +++ b/tests/ui/rustdoc/doc-inline-validation.stderr @@ -0,0 +1,86 @@ +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:29:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:35:7 + | +LL | #[doc(no_inline)] + | ^^^^^^^^^ this attribute... +... +LL | #[doc(inline)] + | ^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:42:7 + | +LL | #[doc(inline, no_inline)] + | ^^^^^^ ^^^^^^^^^ ...conflicts with this attribute + | | + | this attribute... + | + = help: remove one of the conflicting attributes + +error: this attribute can only be applied to a `use` item + --> $DIR/doc-inline-validation.rs:49:7 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +LL | +LL | pub fn fn_with_inline() {} + | ----------------------- not a `use` item + | + = note: read for more information +note: the lint level is defined here + --> $DIR/doc-inline-validation.rs:48:8 + | +LL | #[deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: this attribute can only be applied to a `use` item + --> $DIR/doc-inline-validation.rs:58:7 + | +LL | #[doc(no_inline)] + | ^^^^^^^^^ only applicable on `use` items +LL | +LL | pub struct StructWithNoInline; + | ----------------------------- not a `use` item + | + = note: read for more information +note: the lint level is defined here + --> $DIR/doc-inline-validation.rs:57:8 + | +LL | #[deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:64:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +warning: didn't expect any arguments here + --> $DIR/doc-inline-validation.rs:71:14 + | +LL | #[doc(inline = "foo")] + | ^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: `#[warn(invalid_doc_attributes)]` on by default + +error: aborting due to 6 previous errors; 1 warning emitted + From 99137e3ae613e0dc1a302278d37aa109a4b16d07 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Fri, 2 Oct 2026 23:31:10 +0530 Subject: [PATCH 1204/1309] Move doc inline validation to attribute parsing --- .../rustc_attr_parsing/src/attributes/doc.rs | 59 ++++++++++++++++--- .../rustc_attr_parsing/src/diagnostics.rs | 20 +++++++ compiler/rustc_passes/src/check_attr.rs | 57 ++---------------- compiler/rustc_passes/src/diagnostics.rs | 22 +------ 4 files changed, 77 insertions(+), 81 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 7aeedc1493027..129d3626e675e 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -2,26 +2,26 @@ use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; use rustc_attr_ir::target::Target; use rustc_attr_ir::{ AttributeKind, CfgEntry, CfgHideShow, DocAttribute, DocCfgHideShow, DocCfgHideShowValue, - DocInline, HideOrShow, + DocInline, HideOrShow, find_attr, }; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry}; -use rustc_errors::Applicability; +use rustc_errors::{Applicability, MultiSpan, msg}; use rustc_feature::AttributeStability; use rustc_lint_defs::builtin::{INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES}; use rustc_span::{Span, Symbol, edition, sym}; use super::prelude::{ALL_TARGETS, AllowedTargets}; -use super::{AcceptMapping, AttributeParser, template}; -use crate::context::{AcceptContext, FinalizeContext}; +use super::{AcceptMapping, AttributeParser, FinalizeCheckFn, template}; +use crate::context::{AcceptContext, FinalizeCheckContext, FinalizeContext}; use crate::diagnostics::{ AttrCrateLevelOnly, DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, DocAutoCfgHideShowExpectsList, DocAutoCfgHideShowNoIdentBeforeValues, DocAutoCfgHideShowUnexpectedItem, DocAutoCfgHideShowUnexpectedItemAfterValues, - DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocKeywordNotKeyword, DocTestLiteral, - DocTestTakesList, DocTestUnknown, DocUnknownAny, DocUnknownInclude, DocUnknownPasses, - DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, ExpectedNoArgs, - IllFormedAttributeInput, MalformedDoc, UnusedDuplicate, + DocAutoCfgHideShowValuesMix, DocAutoCfgWrongLiteral, DocInlineConflict, DocInlineOnlyUse, + DocKeywordNotKeyword, DocTestLiteral, DocTestTakesList, DocTestUnknown, DocUnknownAny, + DocUnknownInclude, DocUnknownPasses, DocUnknownPlugins, DocUnknownSpotlight, ExpectedNameValue, + ExpectedNoArgs, IllFormedAttributeInput, MalformedDoc, UnusedDuplicate, }; use crate::parser::{ ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, OwnedPathParser, @@ -741,6 +741,44 @@ impl DocParser { } } } + + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) { + let Some(doc) = find_attr!(cx.parsed_attrs, Doc(doc) => doc) else { + return; + }; + + let span = match doc.inline.as_slice() { + [] => return, + [(_, span)] => *span, + [(inline, span), rest @ ..] => { + for (inline2, span2) in rest { + if inline2 != inline { + let mut spans = MultiSpan::from_spans(vec![*span, *span2]); + spans.push_span_label(*span, msg!("this attribute...")); + spans.push_span_label( + *span2, + msg!("{\".\"}..conflicts with this attribute"), + ); + cx.emit_err(DocInlineConflict { spans }); + return; + } + } + *span + } + }; + + match cx.target { + Target::Use | Target::ExternCrate => {} + _ => { + let item_span = cx.target_span; + cx.emit_lint( + INVALID_DOC_ATTRIBUTES, + DocInlineOnlyUse { attr_span: span, item_span }, + span, + ); + } + } + } } impl AttributeParser for DocParser { @@ -816,4 +854,9 @@ impl AttributeParser for DocParser { None } } + + fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> { + let &(_, span) = self.attribute.inline.first()?; + Some((Self::finalize_check, span)) + } } diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index 879f8da67ae15..53004765a4bd0 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -292,6 +292,26 @@ pub(crate) struct DocTestLiteral; )] pub(crate) struct AttrCrateLevelOnly; +#[derive(Diagnostic)] +#[diag("conflicting doc inlining attributes")] +#[help("remove one of the conflicting attributes")] +pub(crate) struct DocInlineConflict { + #[primary_span] + pub spans: MultiSpan, +} + +#[derive(Diagnostic)] +#[diag("this attribute can only be applied to a `use` item")] +#[note( + "read for more information" +)] +pub(crate) struct DocInlineOnlyUse { + #[label("only applicable on `use` items")] + pub attr_span: Span, + #[label("not a `use` item")] + pub item_span: Span, +} + #[derive(Diagnostic)] #[diag("`#[diagnostic::do_not_recommend]` does not expect any arguments")] pub(crate) struct DoNotRecommendDoesNotExpectArgs; diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index d6501ee672bff..7db9ceae5ed7f 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -13,12 +13,12 @@ use rustc_attr_ir::diagnostic::Directive; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::target::{AssocCtxt, MethodKind, Target}; use rustc_attr_ir::{ - Attribute, AttributeKind, DocAttribute, DocInline, EiiDecl, EiiImpl, EiiImplResolution, - InlineAttr, OptimizeAttr, ReprAttr, find_attr, + Attribute, AttributeKind, DocAttribute, EiiDecl, EiiImpl, EiiImplResolution, InlineAttr, + OptimizeAttr, ReprAttr, find_attr, }; use rustc_attr_parsing::AttributeParser; use rustc_data_structures::thin_vec::ThinVec; -use rustc_errors::{DiagCtxtHandle, IntoDiagArg, MultiSpan, msg}; +use rustc_errors::{DiagCtxtHandle, IntoDiagArg}; use rustc_feature::BUILTIN_ATTRIBUTE_SET; use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModId; @@ -911,52 +911,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } } - /// Checks `#[doc(inline)]`/`#[doc(no_inline)]` attributes. - /// - /// A doc inlining attribute is invalid if it is applied to a non-`use` item, or - /// if there are conflicting attributes for one item. - /// - /// `specified_inline` is used to keep track of whether we have - /// already seen an inlining attribute for this item. - /// If so, `specified_inline` holds the value and the span of - /// the first `inline`/`no_inline` attribute. - fn check_doc_inline(&self, hir_id: HirId, target: Target, inline: &[(DocInline, Span)]) { - let span = match inline { - [] => return, - [(_, span)] => *span, - [(inline, span), rest @ ..] => { - for (inline2, span2) in rest { - if inline2 != inline { - let mut spans = MultiSpan::from_spans(vec![*span, *span2]); - spans.push_span_label(*span, msg!("this attribute...")); - spans.push_span_label( - *span2, - msg!("{\".\"}..conflicts with this attribute"), - ); - self.dcx().emit_err(diagnostics::DocInlineConflict { spans }); - return; - } - } - *span - } - }; - - match target { - Target::Use | Target::ExternCrate => {} - _ => { - self.tcx.emit_node_span_lint( - INVALID_DOC_ATTRIBUTES, - hir_id, - span, - diagnostics::DocInlineOnlyUse { - attr_span: span, - item_span: self.tcx.hir_span(hir_id), - }, - ); - } - } - } - fn check_doc_masked(&self, span: Span, hir_id: HirId, target: Target) { if target != Target::ExternCrate { self.tcx.emit_node_span_lint( @@ -1010,7 +964,8 @@ impl<'tcx> CheckAttrVisitor<'tcx> { // valid pretty much anywhere, not checked here? // FIXME: should we? hidden: _, - inline, + // already checked in attr_parsing + inline: _, // FIXME: currently unchecked cfg: _, // already checked in attr_parsing @@ -1063,8 +1018,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.check_doc_search_unbox(*span, hir_id); } - self.check_doc_inline(hir_id, target, inline); - if let Some(span) = masked { self.check_doc_masked(*span, hir_id, target); } diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 76b00864c35fe..7821a4143c63b 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -2,7 +2,7 @@ use std::io::Error; use std::path::{Path, PathBuf}; use rustc_errors::codes::*; -use rustc_errors::{Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, Level, MultiSpan, msg}; +use rustc_errors::{Diag, DiagCtxtHandle, DiagSymbolList, Diagnostic, Level, msg}; use rustc_macros::{Diagnostic, Subdiagnostic}; use rustc_middle::middle::resolve::MainDefinition; use rustc_middle::ty::Ty; @@ -75,26 +75,6 @@ pub(crate) struct DocSearchUnboxInvalid { pub span: Span, } -#[derive(Diagnostic)] -#[diag("conflicting doc inlining attributes")] -#[help("remove one of the conflicting attributes")] -pub(crate) struct DocInlineConflict { - #[primary_span] - pub spans: MultiSpan, -} - -#[derive(Diagnostic)] -#[diag("this attribute can only be applied to a `use` item")] -#[note( - "read for more information" -)] -pub(crate) struct DocInlineOnlyUse { - #[label("only applicable on `use` items")] - pub attr_span: Span, - #[label("not a `use` item")] - pub item_span: Span, -} - #[derive(Diagnostic)] #[diag("this attribute can only be applied to an `extern crate` item")] #[note( From bc8eca0bc494f59571f47e33a6b1b4c646c1b5a0 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Fri, 2 Oct 2026 23:41:20 +0530 Subject: [PATCH 1205/1309] Run rustdoc attribute checks before early abort --- src/librustdoc/core.rs | 7 ++-- src/librustdoc/lib.rs | 2 -- .../rustdoc-ui/lints/invalid-doc-attr.stderr | 34 +++++++++---------- tests/ui/rustdoc/doc-inline-validation.stderr | 26 +++++++------- 4 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs index db5e281f376ad..caf3fb9887c3e 100644 --- a/src/librustdoc/core.rs +++ b/src/librustdoc/core.rs @@ -367,13 +367,14 @@ pub(crate) fn run_global_ctxt( // NOTE: These are copy/pasted from typeck/lib.rs and should be kept in sync with those changes. tcx.sess.time("wf_checking", || tcx.ensure_ok().check_type_wf(())); + tcx.sess.time("check_mod_attrs", || { + tcx.hir_for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module)) + }); + rustc_interface::passes::emit_delayed_lints(tcx); tcx.dcx().abort_if_errors(); tcx.sess.time("missing_docs", || rustc_lint::check_crate(tcx)); - tcx.sess.time("check_mod_attrs", || { - tcx.hir_for_each_module(|module| tcx.ensure_ok().check_mod_attrs(module)) - }); rustc_passes::stability::check_unused_or_stable_features(tcx); let auto_traits = diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs index b907c3ef2cb11..e85e39711b181 100644 --- a/src/librustdoc/lib.rs +++ b/src/librustdoc/lib.rs @@ -1023,8 +1023,6 @@ fn main_args(early_dcx: &mut EarlyDiagCtxt, at_args: &[String]) { cache.crate_version = crate_version; - rustc_interface::passes::emit_delayed_lints(tcx); - if render_opts.dep_info().is_some() { rustc_interface::passes::write_dep_info(tcx); } diff --git a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr index 2e9b9f0a8cfbe..768328be1611d 100644 --- a/tests/rustdoc-ui/lints/invalid-doc-attr.stderr +++ b/tests/rustdoc-ui/lints/invalid-doc-attr.stderr @@ -1,19 +1,3 @@ -error: this attribute can only be applied to a `use` item - --> $DIR/invalid-doc-attr.rs:8:7 - | -LL | #[doc(inline)] - | ^^^^^^ only applicable on `use` items -LL | -LL | pub fn foo() {} - | ------------ not a `use` item - | - = note: read for more information -note: the lint level is defined here - --> $DIR/invalid-doc-attr.rs:1:9 - | -LL | #![deny(invalid_doc_attributes)] - | ^^^^^^^^^^^^^^^^^^^^^^ - error: conflicting doc inlining attributes --> $DIR/invalid-doc-attr.rs:18:7 | @@ -34,6 +18,11 @@ LL | pub struct Masked; | ----------------- not an `extern crate` item | = note: read for more information +note: the lint level is defined here + --> $DIR/invalid-doc-attr.rs:1:9 + | +LL | #![deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ error: this attribute cannot be applied to an `extern crate self` item --> $DIR/invalid-doc-attr.rs:28:7 @@ -59,6 +48,17 @@ LL | | pub extern crate self as reexport; | = note: read for more information +error: this attribute can only be applied to a `use` item + --> $DIR/invalid-doc-attr.rs:8:7 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +LL | +LL | pub fn foo() {} + | --------------- not a `use` item + | + = note: read for more information + error: this attribute can only be applied to a `use` item --> $DIR/invalid-doc-attr.rs:13:11 | @@ -66,7 +66,7 @@ LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items LL | LL | pub fn baz() {} - | ------------ not a `use` item + | --------------- not a `use` item | = note: read for more information diff --git a/tests/ui/rustdoc/doc-inline-validation.stderr b/tests/ui/rustdoc/doc-inline-validation.stderr index f341273bf206f..1e14e08691105 100644 --- a/tests/ui/rustdoc/doc-inline-validation.stderr +++ b/tests/ui/rustdoc/doc-inline-validation.stderr @@ -30,6 +30,17 @@ LL | #[doc(inline, no_inline)] | = help: remove one of the conflicting attributes +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:64:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +... +LL | #[doc(no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + error: this attribute can only be applied to a `use` item --> $DIR/doc-inline-validation.rs:49:7 | @@ -37,7 +48,7 @@ LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items LL | LL | pub fn fn_with_inline() {} - | ----------------------- not a `use` item + | -------------------------- not a `use` item | = note: read for more information note: the lint level is defined here @@ -53,7 +64,7 @@ LL | #[doc(no_inline)] | ^^^^^^^^^ only applicable on `use` items LL | LL | pub struct StructWithNoInline; - | ----------------------------- not a `use` item + | ------------------------------ not a `use` item | = note: read for more information note: the lint level is defined here @@ -62,17 +73,6 @@ note: the lint level is defined here LL | #[deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ -error: conflicting doc inlining attributes - --> $DIR/doc-inline-validation.rs:64:7 - | -LL | #[doc(inline)] - | ^^^^^^ this attribute... -... -LL | #[doc(no_inline)] - | ^^^^^^^^^ ...conflicts with this attribute - | - = help: remove one of the conflicting attributes - warning: didn't expect any arguments here --> $DIR/doc-inline-validation.rs:71:14 | From e9b0eeb99de66a2b85ecda546362b1dce9e7c9ba Mon Sep 17 00:00:00 2001 From: Trevor Gross Date: Wed, 30 Sep 2026 17:07:09 -0500 Subject: [PATCH 1206/1309] intrinsics: Rename `abort` to `abort_immediate` The semantics of `intrinsics::abort()` are closer to what we have unstably as `abort_immediate()` than to `process::abort()` or `libc::abort()`. Rename it to make more clear that the intrinsic is more of an intentional crash with platform-specific behavior than what `libc::abort()` tries to be (i.e. raising `SIGABRT`). --- .../example/mini_core.rs | 8 +++---- .../example/mini_core_hello_world.rs | 4 ++-- .../src/intrinsics/mod.rs | 2 +- .../build_system/src/fuzz/reduce.rs | 2 +- .../example/alloc_example.rs | 4 ++-- .../rustc_codegen_gcc/example/mini_core.rs | 10 ++++----- .../example/mini_core_hello_world.rs | 4 ++-- .../rustc_codegen_gcc/src/intrinsic/mod.rs | 2 +- .../rustc_codegen_gcc/tests/run/abort1.rs | 2 +- .../rustc_codegen_gcc/tests/run/abort2.rs | 2 +- .../tests/run/always_inline.rs | 2 +- compiler/rustc_codegen_llvm/src/builder.rs | 2 +- compiler/rustc_codegen_llvm/src/intrinsic.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/block.rs | 8 +++---- .../rustc_codegen_ssa/src/mir/intrinsic.rs | 6 +++--- compiler/rustc_codegen_ssa/src/mir/place.rs | 2 +- compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 4 ++-- .../rustc_codegen_ssa/src/traits/intrinsic.rs | 3 ++- .../src/const_eval/machine.rs | 4 ++-- .../rustc_hir_analysis/src/check/intrinsic.rs | 4 ++-- compiler/rustc_span/src/symbol.rs | 1 + library/alloc/src/collections/btree/mem.rs | 2 +- library/alloc/src/collections/btree/split.rs | 2 +- library/alloc/src/rcs/arc.rs | 9 ++++---- library/alloc/src/rcs/rc.rs | 11 +++++----- library/core/src/intrinsics/mod.rs | 21 ++++++++----------- library/core/src/panicking.rs | 14 ++++++------- library/core/src/process.rs | 2 +- library/core/src/slice/sort/shared/pivot.rs | 2 +- .../core/src/slice/sort/shared/smallsort.rs | 10 ++++----- .../core/src/slice/sort/stable/quicksort.rs | 2 +- .../core/src/slice/sort/unstable/quicksort.rs | 4 ++-- library/std/src/panicking.rs | 4 ++-- library/std/src/sys/exit.rs | 4 ++-- library/std/src/sys/pal/uefi/mod.rs | 4 ++-- library/std/src/sys/pal/unix/mod.rs | 4 ++-- library/std/src/sys/pal/unsupported/common.rs | 2 +- library/std/src/sys/pal/windows/mod.rs | 4 ++-- library/std/src/sys/pal/zkvm/mod.rs | 2 +- library/std/src/sys/personality/mod.rs | 2 +- .../stdarch/crates/core_arch/src/mips/mod.rs | 2 +- .../stdarch/crates/core_arch/src/nvptx/mod.rs | 2 +- .../crates/core_arch/src/powerpc/mod.rs | 2 +- .../crates/core_arch/src/wasm32/mod.rs | 2 +- .../src/language-features/intrinsics.md | 2 +- .../src/language-features/lang-items.md | 4 ++-- src/tools/miri/src/intrinsics/mod.rs | 4 ++-- .../fail/alloc/alloc_error_handler_custom.rs | 2 +- .../alloc/alloc_error_handler_custom.stderr | 4 ++-- .../fail/alloc/alloc_error_handler_no_std.rs | 2 +- .../alloc/alloc_error_handler_no_std.stderr | 4 ++-- src/tools/miri/tests/fail/panic/no_std.rs | 2 +- src/tools/miri/tests/fail/panic/no_std.stderr | 4 ++-- src/tools/rustfmt/tests/source/match.rs | 2 +- src/tools/rustfmt/tests/target/match.rs | 2 +- tests/assembly-llvm/mips-div-no-trap.rs | 6 +++--- tests/rustdoc-html/safe-intrinsic.rs | 6 +++--- tests/ui/consts/const-eval/const_panic.stderr | 2 +- .../proc-macro/auxiliary/derive-unstable.rs | 3 +-- tests/ui/process/signal-exit-status.rs | 2 +- 60 files changed, 119 insertions(+), 123 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs index 08adec96a079b..d6d82a9d2af69 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs @@ -497,7 +497,7 @@ pub trait FnMut: FnOnce { pub fn panic(_msg: &'static str) -> ! { unsafe { libc::puts("Panicking\n\0" as *const str as *const i8); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -539,7 +539,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { len, index, ); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -548,7 +548,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { fn panic_cannot_unwind() -> ! { unsafe { libc::puts("panic in a function that cannot unwind\n\0" as *const str as *const i8); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -688,7 +688,7 @@ pub union MaybeUninit { pub mod intrinsics { #[rustc_intrinsic] - pub fn abort() -> !; + pub fn abort_immediate() -> !; #[rustc_intrinsic] pub const fn size_of() -> usize; #[rustc_intrinsic] diff --git a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs index 9a710caae9cd1..c53ec2ec6710d 100644 --- a/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_cranelift/example/mini_core_hello_world.rs @@ -602,11 +602,11 @@ pub enum E2 { #[allow(unreachable_patterns)] fn check_niche_behavior() { if let E1::V2 { .. } = (E1::V1 { f: true }) { - intrinsics::abort(); + intrinsics::abort_immediate(); } if let E2::V1 { .. } = E2::V3:: { - intrinsics::abort(); + intrinsics::abort_immediate(); } } diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs index cf1c1f027e7f5..9c3182c944dc6 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs @@ -469,7 +469,7 @@ fn codegen_regular_intrinsic_call<'tcx>( let usize_layout = fx.layout_of(fx.tcx.types.usize); match intrinsic { - sym::abort => { + sym::abort_immediate => { fx.bcx.set_cold_block(fx.bcx.current_block().unwrap()); fx.bcx.ins().trap(TrapCode::user(2).unwrap()); return Ok(()); diff --git a/compiler/rustc_codegen_gcc/build_system/src/fuzz/reduce.rs b/compiler/rustc_codegen_gcc/build_system/src/fuzz/reduce.rs index 20715ab0e7c48..d1ed8fabbaf11 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/fuzz/reduce.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/fuzz/reduce.rs @@ -203,7 +203,7 @@ fn block_abort(file: &mut Vec, path: &PathBuf, cache: &mut ResultCache) // ..and insert an unconditional call to abort. file_copy.insert( block_starts, - "Call(tmp = core::intrinsics::abort(), ReturnTo(bb1), UnwindUnreachable())\n" + "Call(tmp = core::intrinsics::abort_immediate(), ReturnTo(bb1), UnwindUnreachable())\n" .to_string(), ); file_copy.insert(block_starts, "let tmp = ();\n".to_string()); diff --git a/compiler/rustc_codegen_gcc/example/alloc_example.rs b/compiler/rustc_codegen_gcc/example/alloc_example.rs index 9a0b46d5b221a..338057e1fcb87 100644 --- a/compiler/rustc_codegen_gcc/example/alloc_example.rs +++ b/compiler/rustc_codegen_gcc/example/alloc_example.rs @@ -20,12 +20,12 @@ extern "C" { #[panic_handler] fn panic_handler(_: &core::panic::PanicInfo<'_>) -> ! { - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } #[alloc_error_handler] fn alloc_error_handler(_: alloc::alloc::Layout) -> ! { - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } #[lang = "eh_personality"] diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs index 2d5a29ceb8191..efc3e169678dc 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core.rs @@ -509,7 +509,7 @@ pub trait FnMut: FnOnce { pub fn panic(_msg: &'static str) -> ! { unsafe { libc::puts("Panicking\n\0" as *const str as *const u8); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -546,7 +546,7 @@ panic_const! { fn panic_cannot_unwind() -> ! { unsafe { libc::puts("Panicking\n\0" as *const str as *const u8); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -555,7 +555,7 @@ fn panic_cannot_unwind() -> ! { fn panic_in_cleanup() -> ! { unsafe { libc::printf("panic in a destructor during cleanup\n\0" as *const str as *const i8); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -568,7 +568,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { len, index, ); - intrinsics::abort(); + intrinsics::abort_immediate(); } } @@ -698,7 +698,7 @@ pub mod intrinsics { #[rustc_intrinsic] pub const fn black_box(_dummy: T) -> T; #[rustc_intrinsic] - pub fn abort() -> !; + pub fn abort_immediate() -> !; #[rustc_intrinsic] pub const fn size_of() -> usize; #[rustc_intrinsic] diff --git a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs index ab841d51a7f53..a630c33e086d3 100644 --- a/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs +++ b/compiler/rustc_codegen_gcc/example/mini_core_hello_world.rs @@ -438,10 +438,10 @@ pub enum E2 { #[allow(unreachable_patterns)] fn check_niche_behavior () { if let E1::V2 { .. } = (E1::V1 { f: true }) { - intrinsics::abort(); + intrinsics::abort_immediate(); } if let E2::V1 { .. } = E2::V3:: { - intrinsics::abort(); + intrinsics::abort_immediate(); } } diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs index 4d2590ac81e41..0f735172667ab 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/mod.rs @@ -661,7 +661,7 @@ impl<'a, 'gcc, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'a, 'gcc, 'tc llret } - fn abort(&mut self) { + fn abort_immediate(&mut self) { let func = self.context.get_builtin_function("__builtin_trap"); self.block.add_eval(self.location, self.context.new_call(self.location, func, &[])); } diff --git a/compiler/rustc_codegen_gcc/tests/run/abort1.rs b/compiler/rustc_codegen_gcc/tests/run/abort1.rs index ff2bb75ece22a..c9e3c27a0791d 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort1.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort1.rs @@ -12,7 +12,7 @@ extern crate mini_core; use mini_core::*; fn test_fail() -> ! { - unsafe { intrinsics::abort() }; + unsafe { intrinsics::abort_immediate() }; } #[no_mangle] diff --git a/compiler/rustc_codegen_gcc/tests/run/abort2.rs b/compiler/rustc_codegen_gcc/tests/run/abort2.rs index 781f518e0b222..51f55e9404c1f 100644 --- a/compiler/rustc_codegen_gcc/tests/run/abort2.rs +++ b/compiler/rustc_codegen_gcc/tests/run/abort2.rs @@ -12,7 +12,7 @@ extern crate mini_core; use mini_core::*; fn fail() -> i32 { - unsafe { intrinsics::abort() }; + unsafe { intrinsics::abort_immediate() }; 0 } diff --git a/compiler/rustc_codegen_gcc/tests/run/always_inline.rs b/compiler/rustc_codegen_gcc/tests/run/always_inline.rs index ebd741ee090c8..2a580fe79acaf 100644 --- a/compiler/rustc_codegen_gcc/tests/run/always_inline.rs +++ b/compiler/rustc_codegen_gcc/tests/run/always_inline.rs @@ -47,7 +47,7 @@ fn fib_a(n: u8) -> u8 { #[no_mangle] extern "C" fn main(argc: i32, _argv: *const *const u8) -> i32 { if fib(2) != fib_a(2) { - intrinsics::abort(); + intrinsics::abort_immediate(); } 0 } diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index dc89414940620..d7470be0046d4 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -2129,7 +2129,7 @@ impl<'a, 'll, 'tcx> Builder<'a, 'll, 'tcx> { self.unreachable(); } } else { - self.abort(); + self.abort_immediate(); self.unreachable(); } diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 3163139ba1f04..cfc880ca92827 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -1040,7 +1040,7 @@ impl<'ll, 'tcx> IntrinsicCallBuilderMethods<'tcx> for Builder<'_, 'll, 'tcx> { autocast(self, llret, src_ty, dest_ty) } - fn abort(&mut self) { + fn abort_immediate(&mut self) { self.call_intrinsic("llvm.trap", &[], &[]); } diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 8fa044a45de22..9db1dd700e95e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -199,7 +199,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { "compiler_builtins call to diverging function {:?} replaced with abort", instance.def_id() ); - bx.abort(); + bx.abort_immediate(); bx.unreachable(); return MergingSucc::False; } @@ -587,7 +587,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { // so we should make sure that we never actually do. // We play it safe by using a well-defined `abort`, but we could go for immediate UB // if that turns out to be helpful. - bx.abort(); + bx.abort_immediate(); // `abort` does not terminate the block, so we still need to generate // an `unreachable` terminator after it. bx.unreachable(); @@ -1099,7 +1099,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } // Also we need to terminate the block to avoid an LLVM assertion, // even though we're not going to actually use the IR. - bx.abort(); + bx.abort_immediate(); return MergingSucc::False; } IntrinsicResult::Fallback(instance) => { @@ -2398,7 +2398,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { let (fn_abi, fn_ptr, instance) = common::build_langcall(&bx, self.mir.span, reason.lang_item()); if is_call_from_compiler_builtins_to_upstream_monomorphization(bx.tcx(), instance) { - bx.abort(); + bx.abort_immediate(); } else { let fn_ty = bx.fn_decl_backend_type(fn_abi); diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index e6b70ce2ca77b..650b21bf78a9c 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -121,7 +121,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { if args.is_empty() { match name { - sym::abort + sym::abort_immediate | sym::unreachable | sym::cold_path | sym::gpu_launch_sized_workgroup_mem @@ -152,8 +152,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } let op_val: OperandValue<_> = match name { - sym::abort => { - bx.abort(); + sym::abort_immediate => { + bx.abort_immediate(); OperandValue::ZeroSized } diff --git a/compiler/rustc_codegen_ssa/src/mir/place.rs b/compiler/rustc_codegen_ssa/src/mir/place.rs index 02e125fd31717..c74a5e788689f 100644 --- a/compiler/rustc_codegen_ssa/src/mir/place.rs +++ b/compiler/rustc_codegen_ssa/src/mir/place.rs @@ -264,7 +264,7 @@ impl<'a, 'tcx, V: CodegenObject> PlaceRef<'tcx, V> { Err(UninhabitedVariantError) => { // We play it safe by using a well-defined `abort`, but we could go for immediate UB // if that turns out to be helpful. - bx.abort(); + bx.abort_immediate(); } Ok(Some((tag_field, imm))) => { let tag_place = self.project_field(bx, tag_field.as_usize()); diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 3b33cf5a17602..6391fcd58f4bb 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -834,8 +834,8 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { Err(super::place::UninhabitedVariantError) => { // Like codegen_set_discr we use a sound abort, but could // potentially `unreachable` or just return the poison for - // more optimizability, if that turns out to be helpful. - bx.abort(); + // optimizability, if that turns out to be helpful. + bx.abort_immediate(); let val = OperandValue::poison(bx, layout); OperandRef { val, layout, move_annotation: None } } diff --git a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs index 47144834b5072..0aacbb3b5f7fb 100644 --- a/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/traits/intrinsic.rs @@ -38,7 +38,8 @@ pub trait IntrinsicCallBuilderMethods<'tcx>: BackendTypes { is_cleanup: bool, ) -> Self::Value; - fn abort(&mut self); + /// Ungracefully stop execution in the simplest way possible. + fn abort_immediate(&mut self); fn assume(&mut self, val: Self::Value); fn expect(&mut self, cond: Self::Value, expected: bool) -> Self::Value; /// Trait method used to load a function while testing if it is associated with a type diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 3f7731ce95583..7ee3d2f7826dd 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -484,8 +484,8 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { // CTFE-specific intrinsics. match intrinsic_name { - sym::abort => { - // Note that `abort` is also hooked separately in Miri. + sym::abort_immediate => { + // Note that `abort_immediate` is also hooked separately in Miri. throw_machine_stop!(ConstEvalErrKind::Abort); } sym::ptr_guaranteed_cmp => { diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index bcab1457e0655..3ababc644ddc1 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -67,7 +67,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi // safe extern fns are otherwise unprecedented. // tidy-alphabetical-start - | sym::abort + | sym::abort_immediate | sym::add_with_overflow | sym::aggregate_raw_ptr | sym::align_of @@ -289,7 +289,7 @@ pub(crate) fn check_intrinsic_type( let n_lts = 0; let (n_tps, n_cts, inputs, output) = match intrinsic_name { sym::autodiff => (4, 0, vec![param(0), param(1), param(2)], param(3)), - sym::abort => (0, 0, vec![], tcx.types.never), + sym::abort_immediate => (0, 0, vec![], tcx.types.never), sym::amdgpu_dispatch_ptr => (0, 0, vec![], Ty::new_imm_ptr(tcx, tcx.types.unit)), sym::unreachable => (0, 0, vec![], tcx.types.never), sym::breakpoint => (0, 0, vec![], tcx.types.unit), diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index a003f20e3512d..dbd7cf40061f0 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -398,6 +398,7 @@ symbols! { abi_vectorcall, abi_x86_interrupt, abort, + abort_immediate, add, add_assign, add_with_overflow, diff --git a/library/alloc/src/collections/btree/mem.rs b/library/alloc/src/collections/btree/mem.rs index ad86e9422d974..c9a1ec8ca63c6 100644 --- a/library/alloc/src/collections/btree/mem.rs +++ b/library/alloc/src/collections/btree/mem.rs @@ -19,7 +19,7 @@ pub(super) fn replace(v: &mut T, change: impl FnOnce(T) -> (T, R)) -> R { struct PanicGuard; impl Drop for PanicGuard { fn drop(&mut self) { - intrinsics::abort() + intrinsics::abort_immediate() } } let guard = PanicGuard; diff --git a/library/alloc/src/collections/btree/split.rs b/library/alloc/src/collections/btree/split.rs index 388f41cc1c646..fde6810ed4143 100644 --- a/library/alloc/src/collections/btree/split.rs +++ b/library/alloc/src/collections/btree/split.rs @@ -61,7 +61,7 @@ impl Root { // A panic from a later `search_node` comparison would unwind out of // that state and double-free the shared values (#158165), so abort // instead of exposing it. - let guard = mem::DropGuard::new((), |()| intrinsics::abort()); + let guard = mem::DropGuard::new((), |()| intrinsics::abort_immediate()); loop { split_edge.move_suffix(&mut right_node); diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index 5b42173da5a3a..ffa848998e9a2 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -5,7 +5,6 @@ use core::clone::TrivialClone; use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; @@ -21,7 +20,7 @@ use core::ptr::{self, NonNull}; use core::slice::from_raw_parts_mut; use core::sync::atomic::Ordering::{Acquire, Relaxed, Release}; use core::sync::atomic::{self, Atomic}; -use core::{borrow, fmt, hint}; +use core::{borrow, fmt, hint, intrinsics}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; @@ -2539,7 +2538,7 @@ impl Clone for Arc { // Otherwise, the counter could be brought to an almost-overflow using a compare-exchange loop, // and then overflow using a few `fetch_add`s. if old_size > MAX_REFCOUNT { - abort(); + intrinsics::abort_immediate(); } // SAFETY: Pointer is valid & allocator corresponds to the one used to allocate it. @@ -3587,7 +3586,7 @@ impl Clone for Weak { // See comments in Arc::clone() for why we do this (for mem::forget). if old_size > MAX_REFCOUNT { - abort(); + intrinsics::abort_immediate(); } } @@ -5065,7 +5064,7 @@ impl UniqueArc { // See comments in Arc::clone() for why we do this (for mem::forget). if old_size > MAX_REFCOUNT { - abort(); + intrinsics::abort_immediate(); } Weak { ptr: this.ptr, alloc: this.alloc.clone() } diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index d928e42f71e20..0666995ffe94a 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -248,7 +248,6 @@ use core::clone::TrivialClone; use core::clone::{CloneToUninit, Share, UseCloned}; use core::cmp::Ordering; use core::hash::{Hash, Hasher}; -use core::intrinsics::abort; #[cfg(not(no_global_oom_handling))] use core::iter; use core::marker::{PhantomData, Unsize}; @@ -264,7 +263,7 @@ use core::pin::PinSafePointer; use core::ptr::{self, NonNull, drop_in_place}; #[cfg(not(no_global_oom_handling))] use core::slice::from_raw_parts_mut; -use core::{borrow, fmt, hint}; +use core::{borrow, fmt, hint, intrinsics}; #[cfg(not(no_global_oom_handling))] use crate::alloc::handle_alloc_error; @@ -3939,8 +3938,8 @@ trait RcInnerPtr { // We want to abort on overflow instead of dropping the value. // Checking for overflow after the store instead of before // allows for slightly better code generation. - if core::intrinsics::unlikely(strong == 0) { - abort(); + if intrinsics::unlikely(strong == 0) { + intrinsics::abort_immediate(); } } @@ -3972,8 +3971,8 @@ trait RcInnerPtr { // We want to abort on overflow instead of dropping the value. // Checking for overflow after the store instead of before // allows for slightly better code generation. - if core::intrinsics::unlikely(weak == 0) { - abort(); + if intrinsics::unlikely(weak == 0) { + intrinsics::abort_immediate(); } } diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index f44da9840b8e5..ee25326631107 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -425,26 +425,23 @@ pub fn breakpoint(); #[rustc_intrinsic] pub fn rustc_peek(_: T) -> T; -/// Aborts the execution of the process. +/// Ungracefully aborts the execution of the process. /// -/// Note that, unlike most intrinsics, this is safe to call; -/// it does not require an `unsafe` block. -/// Therefore, implementations must not require the user to uphold -/// any safety invariants. +/// This is the intrinsic for directly implementing [`core::process::abort_immediate`] which, on +/// most platforms, will invoke an invalid instruction. On Unix, the process will probably +/// terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or `SIGBUS`. The +/// precise behavior is not guaranteed and not stable. /// /// [`std::process::abort`](../../std/process/fn.abort.html) is to be preferred if possible, /// as its behavior is more user-friendly and more stable. /// -/// The current implementation of `intrinsics::abort` is to invoke an invalid instruction, -/// on most platforms. -/// On Unix, the -/// process will probably terminate with a signal like `SIGABRT`, `SIGILL`, `SIGTRAP`, `SIGSEGV` or -/// `SIGBUS`. The precise behavior is not guaranteed and not stable. +/// Note that, unlike most intrinsics, this is safe to call; it does not require an `unsafe` block. +/// Therefore, implementations must not require the user to uphold any safety invariants. /// -/// The stabilization-track version of this intrinsic is [`core::process::abort_immediate`]. +/// The stabilized version of this intrinsic is [`core::process::abort_immediate`]. #[rustc_nounwind] #[rustc_intrinsic] -pub const fn abort() -> !; +pub const fn abort_immediate() -> !; /// Informs the optimizer that this point in the code is not reachable, /// enabling further optimizations. diff --git a/library/core/src/panicking.rs b/library/core/src/panicking.rs index 04722e4e2fc10..bd4fbcf68b256 100644 --- a/library/core/src/panicking.rs +++ b/library/core/src/panicking.rs @@ -59,7 +59,7 @@ compile_error!( #[rustc_const_stable_indirect] // must follow stable const rules since it is exposed to stable pub const fn panic_fmt(fmt: fmt::Arguments<'_>) -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call @@ -100,7 +100,7 @@ pub const fn panic_nounwind_fmt(fmt: fmt::Arguments<'_>, force_no_backtrace: boo panic_fmt(fmt) } else #[track_caller] { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } // NOTE This function never crosses the FFI boundary; it's a Rust-to-Rust call @@ -265,7 +265,7 @@ pub const fn panic_display(x: &T) -> ! { #[lang = "panic_bounds_check"] // needed by codegen for panic on OOB array/slice access fn panic_bounds_check(index: usize, len: usize) -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } panic!("index out of bounds: the len is {len} but the index is {index}") @@ -278,7 +278,7 @@ fn panic_bounds_check(index: usize, len: usize) -> ! { #[rustc_nounwind] // `CheckAlignment` MIR pass requires this function to never unwind fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } panic_nounwind_fmt( @@ -296,7 +296,7 @@ fn panic_misaligned_pointer_dereference(required: usize, found: usize) -> ! { #[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind fn panic_null_pointer_dereference() -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } panic_nounwind_fmt( @@ -312,7 +312,7 @@ fn panic_null_pointer_dereference() -> ! { #[rustc_nounwind] // `CheckNull` MIR pass requires this function to never unwind fn panic_null_reference_constructed() -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } panic_nounwind_fmt(format_args!("null reference produced"), /* force_no_backtrace */ false) @@ -325,7 +325,7 @@ fn panic_null_reference_constructed() -> ! { #[rustc_nounwind] // `CheckEnums` MIR pass requires this function to never unwind fn panic_invalid_enum_construction(source: u128) -> ! { if cfg!(panic = "immediate-abort") { - super::intrinsics::abort() + super::intrinsics::abort_immediate() } panic_nounwind_fmt( diff --git a/library/core/src/process.rs b/library/core/src/process.rs index 2da752b42ee85..1c2769f07895b 100644 --- a/library/core/src/process.rs +++ b/library/core/src/process.rs @@ -40,5 +40,5 @@ #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces #[doc(alias = "halt")] pub const fn abort_immediate() -> ! { - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } diff --git a/library/core/src/slice/sort/shared/pivot.rs b/library/core/src/slice/sort/shared/pivot.rs index 9eb60f854ce21..878ec27419fc2 100644 --- a/library/core/src/slice/sort/shared/pivot.rs +++ b/library/core/src/slice/sort/shared/pivot.rs @@ -17,7 +17,7 @@ pub fn choose_pivot bool>(v: &[T], is_less: &mut F) -> us let len = v.len(); if len < 8 { - intrinsics::abort(); + intrinsics::abort_immediate(); } // SAFETY: a, b, c point to initialized regions of len_div_8 elements, diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs index 40939f922bcb6..1510c3d6d8d6c 100644 --- a/library/core/src/slice/sort/shared/smallsort.rs +++ b/library/core/src/slice/sort/shared/smallsort.rs @@ -228,7 +228,7 @@ fn small_sort_general_with_scratch bool>( } if scratch.len() < len + 16 { - intrinsics::abort(); + intrinsics::abort_immediate(); } let v_base = v.as_mut_ptr(); @@ -321,7 +321,7 @@ where } if len > SMALL_SORT_NETWORK_SCRATCH_LEN { - intrinsics::abort(); + intrinsics::abort_immediate(); } let mut stack_array = MaybeUninit::<[T; SMALL_SORT_NETWORK_SCRATCH_LEN]>::uninit(); @@ -422,7 +422,7 @@ where F: FnMut(&T, &T) -> bool, { if v.len() < 9 { - intrinsics::abort(); + intrinsics::abort_immediate(); } let v_base = v.as_mut_ptr(); @@ -471,7 +471,7 @@ where F: FnMut(&T, &T) -> bool, { if v.len() < 13 { - intrinsics::abort(); + intrinsics::abort_immediate(); } let v_base = v.as_mut_ptr(); @@ -578,7 +578,7 @@ pub fn insertion_sort_shift_left bool>( ) { let len = v.len(); if offset == 0 || offset > len { - intrinsics::abort(); + intrinsics::abort_immediate(); } // SAFETY: see individual comments. diff --git a/library/core/src/slice/sort/stable/quicksort.rs b/library/core/src/slice/sort/stable/quicksort.rs index acc8a5e838e12..1696a5e3c0277 100644 --- a/library/core/src/slice/sort/stable/quicksort.rs +++ b/library/core/src/slice/sort/stable/quicksort.rs @@ -96,7 +96,7 @@ fn stable_partition bool>( let len = v.len(); if intrinsics::unlikely(scratch.len() < len || pivot_pos >= len) { - core::intrinsics::abort() + core::intrinsics::abort_immediate() } let v_base = v.as_ptr(); diff --git a/library/core/src/slice/sort/unstable/quicksort.rs b/library/core/src/slice/sort/unstable/quicksort.rs index 5f2991ee722d2..58a9aae7c7afa 100644 --- a/library/core/src/slice/sort/unstable/quicksort.rs +++ b/library/core/src/slice/sort/unstable/quicksort.rs @@ -102,7 +102,7 @@ where } if pivot >= len { - intrinsics::abort(); + intrinsics::abort_immediate(); } // SAFETY: We checked that `pivot` is in-bounds. @@ -124,7 +124,7 @@ where let num_lt = (const { inst_partition::() })(v_without_pivot, pivot, is_less); if num_lt >= len { - intrinsics::abort(); + intrinsics::abort_immediate(); } // SAFETY: We checked that `num_lt` is in-bounds. diff --git a/library/std/src/panicking.rs b/library/std/src/panicking.rs index f69e0a749f579..4a66d2c1d55f5 100644 --- a/library/std/src/panicking.rs +++ b/library/std/src/panicking.rs @@ -706,7 +706,7 @@ pub(crate) fn panic_handler(info: &core::panic::PanicInfo<'_>) -> ! { #[rustc_do_not_const_check] // hooked by const-eval pub const fn begin_panic(msg: M) -> ! { if cfg!(panic = "immediate-abort") { - intrinsics::abort() + intrinsics::abort_immediate() } struct Payload { @@ -887,5 +887,5 @@ fn rust_panic(msg: &mut dyn PanicPayload) -> ! { #[cfg_attr(not(test), rustc_std_internal_symbol)] #[cfg(panic = "immediate-abort")] fn rust_panic(_: &mut dyn PanicPayload) -> ! { - crate::intrinsics::abort(); + crate::intrinsics::abort_immediate(); } diff --git a/library/std/src/sys/exit.rs b/library/std/src/sys/exit.rs index b9ebe2d974fec..1ca2bd8f6b514 100644 --- a/library/std/src/sys/exit.rs +++ b/library/std/src/sys/exit.rs @@ -127,7 +127,7 @@ pub fn exit(code: i32) -> ! { ) }; } - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } any(target_family = "unix", target_os = "wasi") => unsafe { libc::exit(code as crate::ffi::c_int) @@ -147,7 +147,7 @@ pub fn exit(code: i32) -> ! { target_os = "xous" => crate::os::xous::ffi::exit(code as u32), _ => { let _ = code; - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } } } diff --git a/library/std/src/sys/pal/uefi/mod.rs b/library/std/src/sys/pal/uefi/mod.rs index 67499d2c6f17c..bb771c232f2de 100644 --- a/library/std/src/sys/pal/uefi/mod.rs +++ b/library/std/src/sys/pal/uefi/mod.rs @@ -103,8 +103,8 @@ pub fn abort_internal() -> ! { }; } - // In case SystemTable and ImageHandle cannot be reached, use `core::intrinsics::abort` - core::intrinsics::abort(); + // In case SystemTable and ImageHandle cannot be reached, use `abort_immediate` + core::intrinsics::abort_immediate(); } /// Disable access to BootServices if `EVT_SIGNAL_EXIT_BOOT_SERVICES` is signaled diff --git a/library/std/src/sys/pal/unix/mod.rs b/library/std/src/sys/pal/unix/mod.rs index e4a18794f7823..292c02f3d1f3e 100644 --- a/library/std/src/sys/pal/unix/mod.rs +++ b/library/std/src/sys/pal/unix/mod.rs @@ -267,8 +267,8 @@ pub fn cvt_nz(error: libc::c_int) -> io::Result<()> { // Current glibc's abort() function unblocks SIGABRT, raises SIGABRT, clears the // SIGABRT handler and raises it again, and then starts to get creative. // -// See the public documentation for `intrinsics::abort()` and `process::abort()` -// for further discussion. +// See the public documentation for `intrinsics::abort_immediate()` and +// `process::abort()` for further discussion. // // There is confusion about whether libc::abort() flushes stdio streams. // libc::abort() is required by ISO C 99 (7.14.1.1p5) to be async-signal-safe, diff --git a/library/std/src/sys/pal/unsupported/common.rs b/library/std/src/sys/pal/unsupported/common.rs index d94b9015d0f5f..8e53c3212b64b 100644 --- a/library/std/src/sys/pal/unsupported/common.rs +++ b/library/std/src/sys/pal/unsupported/common.rs @@ -17,5 +17,5 @@ pub fn unsupported_err() -> std_io::Error { } pub fn abort_internal() -> ! { - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } diff --git a/library/std/src/sys/pal/windows/mod.rs b/library/std/src/sys/pal/windows/mod.rs index 2a8ffaa0baab8..a9f3cdbdd9d3e 100644 --- a/library/std/src/sys/pal/windows/mod.rs +++ b/library/std/src/sys/pal/windows/mod.rs @@ -275,7 +275,7 @@ pub fn abort_internal() -> ! { core::arch::asm!("brk 0xF003", in("x0") c::FAST_FAIL_FATAL_APP_EXIT, options(noreturn, nostack)); } _ => { - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } } } @@ -284,7 +284,7 @@ pub fn abort_internal() -> ! { #[cfg(miri)] #[track_caller] // even without panics, this helps for Miri backtraces pub fn abort_internal() -> ! { - crate::intrinsics::abort(); + crate::intrinsics::abort_immediate(); } /// Align the inner value to 8 bytes. diff --git a/library/std/src/sys/pal/zkvm/mod.rs b/library/std/src/sys/pal/zkvm/mod.rs index 1a64d3c93d701..3a21e6f66c4e2 100644 --- a/library/std/src/sys/pal/zkvm/mod.rs +++ b/library/std/src/sys/pal/zkvm/mod.rs @@ -31,5 +31,5 @@ pub fn unsupported_err() -> std_io::Error { } pub fn abort_internal() -> ! { - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } diff --git a/library/std/src/sys/personality/mod.rs b/library/std/src/sys/personality/mod.rs index 31bd457adbe6b..be79643bdf846 100644 --- a/library/std/src/sys/personality/mod.rs +++ b/library/std/src/sys/personality/mod.rs @@ -22,7 +22,7 @@ cfg_select! { // aborting stub. #[lang = "eh_personality"] fn rust_eh_personality() { - core::intrinsics::abort() + core::intrinsics::abort_immediate() } } any( diff --git a/library/stdarch/crates/core_arch/src/mips/mod.rs b/library/stdarch/crates/core_arch/src/mips/mod.rs index 1de3ffd03d1f0..84bfd1585e89b 100644 --- a/library/stdarch/crates/core_arch/src/mips/mod.rs +++ b/library/stdarch/crates/core_arch/src/mips/mod.rs @@ -16,5 +16,5 @@ use stdarch_test::assert_instr; #[inline] #[unstable(feature = "stdarch_mips", issue = "111198")] pub unsafe fn break_() -> ! { - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } diff --git a/library/stdarch/crates/core_arch/src/nvptx/mod.rs b/library/stdarch/crates/core_arch/src/nvptx/mod.rs index d382aff41f4bf..ea6fffee3897f 100644 --- a/library/stdarch/crates/core_arch/src/nvptx/mod.rs +++ b/library/stdarch/crates/core_arch/src/nvptx/mod.rs @@ -145,7 +145,7 @@ pub unsafe fn _thread_idx_z() -> u32 { #[inline] #[unstable(feature = "stdarch_nvptx", issue = "111199")] pub unsafe fn trap() -> ! { - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } // Basic CUDA syscall declarations. diff --git a/library/stdarch/crates/core_arch/src/powerpc/mod.rs b/library/stdarch/crates/core_arch/src/powerpc/mod.rs index 53227215d946c..9bb1bf22434dc 100644 --- a/library/stdarch/crates/core_arch/src/powerpc/mod.rs +++ b/library/stdarch/crates/core_arch/src/powerpc/mod.rs @@ -18,5 +18,5 @@ use stdarch_test::assert_instr; #[inline] #[unstable(feature = "stdarch_powerpc", issue = "111145")] pub unsafe fn trap() -> ! { - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } diff --git a/library/stdarch/crates/core_arch/src/wasm32/mod.rs b/library/stdarch/crates/core_arch/src/wasm32/mod.rs index 57c9157bede89..03986e7e08ec7 100644 --- a/library/stdarch/crates/core_arch/src/wasm32/mod.rs +++ b/library/stdarch/crates/core_arch/src/wasm32/mod.rs @@ -29,7 +29,7 @@ pub use self::memory::*; #[inline] #[stable(feature = "unreachable_wasm32", since = "1.37.0")] pub fn unreachable() -> ! { - crate::intrinsics::abort() + crate::intrinsics::abort_immediate() } /// Generates the [`f32.ceil`] instruction, returning the smallest integer greater than or equal to `a`. diff --git a/src/doc/unstable-book/src/language-features/intrinsics.md b/src/doc/unstable-book/src/language-features/intrinsics.md index 9e59dd889985c..c662e5831d3a0 100644 --- a/src/doc/unstable-book/src/language-features/intrinsics.md +++ b/src/doc/unstable-book/src/language-features/intrinsics.md @@ -68,5 +68,5 @@ These are written without a body: #![allow(internal_features)] #[rustc_intrinsic] -pub fn abort() -> !; +pub fn abort_immediate() -> !; ``` diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md index ccc973d013e44..c88f0cb859877 100644 --- a/src/doc/unstable-book/src/language-features/lang-items.md +++ b/src/doc/unstable-book/src/language-features/lang-items.md @@ -85,7 +85,7 @@ unsafe fn allocate(size: usize, _align: usize) -> *mut u8 { // Check if `malloc` failed: if p.is_null() { - intrinsics::abort(); + intrinsics::abort_immediate(); } p @@ -102,7 +102,7 @@ extern "C" fn main(_argc: c_int, _argv: *const *const u8) -> c_int { fn rust_eh_personality() {} #[panic_handler] -fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() } +fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort_immediate() } ``` Note the use of `abort`: the `exchange_malloc` lang item is assumed to diff --git a/src/tools/miri/src/intrinsics/mod.rs b/src/tools/miri/src/intrinsics/mod.rs index 997339f66a51c..aa93632b78470 100644 --- a/src/tools/miri/src/intrinsics/mod.rs +++ b/src/tools/miri/src/intrinsics/mod.rs @@ -95,8 +95,8 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { match intrinsic_name { // Basic control flow - "abort" => { - // Note that `abort` is also hooked separately in CTFE. + "abort_immediate" => { + // Note that `abort_immediate` is also hooked separately in CTFE. throw_machine_stop!(TerminationInfo::Abort( "the program aborted execution".to_owned() )); diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs index 72f45be61b299..cb11c4ac22776 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.rs @@ -16,7 +16,7 @@ mod utils; #[alloc_error_handler] fn alloc_error_handler(layout: Layout) -> ! { let _ = writeln!(utils::MiriStderr, "custom alloc error handler: {layout:?}"); - core::intrinsics::abort(); //~ERROR: aborted + core::intrinsics::abort_immediate(); //~ERROR: aborted } // rustc requires us to provide some more things that aren't actually used by this test diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr index 677fa1b1bb9c0..4e6bdd2d82296 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr @@ -2,8 +2,8 @@ custom alloc error handler: Layout { size: 4, align: 4 (1 << 2) } error: abnormal termination: the program aborted execution --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC | -LL | core::intrinsics::abort(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here +LL | core::intrinsics::abort_immediate(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: stack backtrace: 0: alloc_error_handler diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs index c7c51c95e9c26..d88c8b27e3c94 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.rs @@ -19,7 +19,7 @@ mod utils; fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { let _ = writeln!(utils::MiriStderr, "custom panic handler called!"); let _ = writeln!(utils::MiriStderr, "{panic_info}"); - core::intrinsics::abort(); //~ERROR: aborted + core::intrinsics::abort_immediate(); //~ERROR: aborted } // rustc requires us to provide some more things that aren't actually used by this test diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr index 386e7cdc2bd81..b93848eef5274 100644 --- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr +++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_no_std.stderr @@ -4,8 +4,8 @@ memory allocation of 4 bytes failed error: abnormal termination: the program aborted execution --> tests/fail/alloc/alloc_error_handler_no_std.rs:LL:CC | -LL | core::intrinsics::abort(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here +LL | core::intrinsics::abort_immediate(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: stack backtrace: 0: panic_handler diff --git a/src/tools/miri/tests/fail/panic/no_std.rs b/src/tools/miri/tests/fail/panic/no_std.rs index cd8a3251fef20..e4b212104ede2 100644 --- a/src/tools/miri/tests/fail/panic/no_std.rs +++ b/src/tools/miri/tests/fail/panic/no_std.rs @@ -16,5 +16,5 @@ fn miri_start(_argc: isize, _argv: *const *const u8) -> isize { #[panic_handler] fn panic_handler(panic_info: &core::panic::PanicInfo) -> ! { writeln!(utils::MiriStderr, "{panic_info}").ok(); - core::intrinsics::abort(); //~ ERROR: the program aborted execution + core::intrinsics::abort_immediate(); //~ ERROR: the program aborted execution } diff --git a/src/tools/miri/tests/fail/panic/no_std.stderr b/src/tools/miri/tests/fail/panic/no_std.stderr index 87adb18a7ab90..493ed858c3234 100644 --- a/src/tools/miri/tests/fail/panic/no_std.stderr +++ b/src/tools/miri/tests/fail/panic/no_std.stderr @@ -3,8 +3,8 @@ blarg I am dead error: abnormal termination: the program aborted execution --> tests/fail/panic/no_std.rs:LL:CC | -LL | core::intrinsics::abort(); - | ^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here +LL | core::intrinsics::abort_immediate(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ abnormal termination occurred here | = note: stack backtrace: 0: panic_handler diff --git a/src/tools/rustfmt/tests/source/match.rs b/src/tools/rustfmt/tests/source/match.rs index d1d8d7f2c3665..c171244271f45 100644 --- a/src/tools/rustfmt/tests/source/match.rs +++ b/src/tools/rustfmt/tests/source/match.rs @@ -240,7 +240,7 @@ fn issue383() { fn issue507() { match 1 { - 1 => unsafe { std::intrinsics::abort() }, + 1 => unsafe { std::intrinsics::abort_immediate() }, _ => (), } } diff --git a/src/tools/rustfmt/tests/target/match.rs b/src/tools/rustfmt/tests/target/match.rs index 0e7815a814da2..f751aea547af6 100644 --- a/src/tools/rustfmt/tests/target/match.rs +++ b/src/tools/rustfmt/tests/target/match.rs @@ -249,7 +249,7 @@ fn issue383() { fn issue507() { match 1 { - 1 => unsafe { std::intrinsics::abort() }, + 1 => unsafe { std::intrinsics::abort_immediate() }, _ => (), } } diff --git a/tests/assembly-llvm/mips-div-no-trap.rs b/tests/assembly-llvm/mips-div-no-trap.rs index d2baff77d3070..1088cce4ef26b 100644 --- a/tests/assembly-llvm/mips-div-no-trap.rs +++ b/tests/assembly-llvm/mips-div-no-trap.rs @@ -107,16 +107,16 @@ extern crate minicore; pub unsafe fn unchecked_div(x: T, y: T) -> T; #[rustc_intrinsic] -pub fn abort() -> !; +pub fn abort_immediate() -> !; // NOTRAP-NOT: teq // TRAP: teq #[no_mangle] pub fn div_i32(a: i32, b: i32) -> i32 { match a { - 0 => abort(), + 0 => abort_immediate(), -1 => match b { - -2147483648 => abort(), + -2147483648 => abort_immediate(), _ => unsafe { unchecked_div(a, b) }, }, _ => unsafe { unchecked_div(a, b) }, diff --git a/tests/rustdoc-html/safe-intrinsic.rs b/tests/rustdoc-html/safe-intrinsic.rs index a40116894a84a..1a38a4f5f1c15 100644 --- a/tests/rustdoc-html/safe-intrinsic.rs +++ b/tests/rustdoc-html/safe-intrinsic.rs @@ -14,10 +14,10 @@ pub trait MetaSized: PointeeSized {} #[lang = "sized"] pub trait Sized: MetaSized {} -//@ has 'foo/fn.abort.html' -//@ has - '//pre[@class="rust item-decl"]' 'pub fn abort() -> !' +//@ has 'foo/fn.abort_immediate.html' +//@ has - '//pre[@class="rust item-decl"]' 'pub fn abort_immediate() -> !' #[rustc_intrinsic] -pub fn abort() -> !; +pub fn abort_immediate() -> !; //@ has 'foo/fn.unreachable.html' //@ has - '//pre[@class="rust item-decl"]' 'pub unsafe fn unreachable() -> !' #[rustc_intrinsic] diff --git a/tests/ui/consts/const-eval/const_panic.stderr b/tests/ui/consts/const-eval/const_panic.stderr index 19d8f3ae1c106..c91151b137fbe 100644 --- a/tests/ui/consts/const-eval/const_panic.stderr +++ b/tests/ui/consts/const-eval/const_panic.stderr @@ -76,7 +76,7 @@ error[E0080]: the program aborted execution LL | const ABORT: () = core::process::abort_immediate(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ evaluation of `ABORT` failed inside this call | -note: inside `abort_immediate` +note: inside `std::process::abort_immediate` --> $SRC_DIR/core/src/process.rs:LL:COL error: aborting due to 13 previous errors diff --git a/tests/ui/proc-macro/auxiliary/derive-unstable.rs b/tests/ui/proc-macro/auxiliary/derive-unstable.rs index 8ba3a06e3549e..c7e34db900042 100644 --- a/tests/ui/proc-macro/auxiliary/derive-unstable.rs +++ b/tests/ui/proc-macro/auxiliary/derive-unstable.rs @@ -4,6 +4,5 @@ use proc_macro::TokenStream; #[proc_macro_derive(Unstable)] pub fn derive(_input: TokenStream) -> TokenStream { - - "unsafe fn foo() -> u32 { ::std::intrinsics::abort() }".parse().unwrap() + "unsafe fn foo() -> u32 { ::std::intrinsics::abort_immediate() }".parse().unwrap() } diff --git a/tests/ui/process/signal-exit-status.rs b/tests/ui/process/signal-exit-status.rs index 33aa83abfc377..1a7836b171a81 100644 --- a/tests/ui/process/signal-exit-status.rs +++ b/tests/ui/process/signal-exit-status.rs @@ -12,7 +12,7 @@ pub fn main() { let args: Vec = env::args().collect(); if args.len() >= 2 && args[1] == "signal" { // Raise an aborting signal without UB - core::intrinsics::abort(); + core::intrinsics::abort_immediate(); } else { let status = Command::new(&args[0]).arg("signal").status().unwrap(); assert!(status.code().is_none()); From d3e6cb7dbddfd3545c43f6bdc4741465f580586e Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Sat, 3 Oct 2026 00:52:27 +0530 Subject: [PATCH 1207/1309] Remove broken intra-doc link in check_attr --- compiler/rustc_passes/src/check_attr.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index 7db9ceae5ed7f..368164d3a3db0 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -952,11 +952,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } /// Runs various checks on `#[doc]` attributes. - /// - /// `specified_inline` should be initialized to `None` and kept for the scope - /// of one item. Read the documentation of [`check_doc_inline`] for more information. - /// - /// [`check_doc_inline`]: Self::check_doc_inline fn check_doc_attrs(&self, attr: &DocAttribute, hir_id: HirId, target: Target) { let DocAttribute { first_span: _, From e8aa31c7ef7a37f9b9c490ce2e8cb584b3dd4b5a Mon Sep 17 00:00:00 2001 From: derekbailey Date: Thu, 1 Oct 2026 22:47:57 +0000 Subject: [PATCH 1208/1309] fix(items): format comments after where using clause_shape budget When formatting an item with a where clause, the budget before the where clause is throttled by the item header width. However, comments between the `where` keyword and the first predicate are indented on their own lines and should be formatted with the full clause budget (`clause_shape`) rather than the throttled budget. Pass `clause_shape` to `rewrite_comments_before_after_where` so that comments after `where` are not prematurely wrapped. Fixes rust-lang/rustfmt#7148. --- src/tools/rustfmt/src/items.rs | 20 ++++++------ .../where-clause-comment-wrap-issue-7148.rs | 29 +++++++++++++++++ .../where-clause-comment-wrap-issue-7148.rs | 31 +++++++++++++++++++ 3 files changed, 71 insertions(+), 9 deletions(-) create mode 100644 src/tools/rustfmt/tests/source/where-clause-comment-wrap-issue-7148.rs create mode 100644 src/tools/rustfmt/tests/target/where-clause-comment-wrap-issue-7148.rs diff --git a/src/tools/rustfmt/src/items.rs b/src/tools/rustfmt/src/items.rs index 60d8d8963c524..449cca87afe4a 100644 --- a/src/tools/rustfmt/src/items.rs +++ b/src/tools/rustfmt/src/items.rs @@ -3121,8 +3121,13 @@ fn rewrite_where_keyword( let (span_before, span_after) = missing_span_before_after_where(span_end_before_where, predicates, where_span); - let (comment_before, comment_after) = - rewrite_comments_before_after_where(context, span_before, span_after, shape)?; + let (comment_before, comment_after) = rewrite_comments_before_after_where( + context, + span_before, + span_after, + block_shape, + clause_shape, + )?; let starting_newline = match where_clause_option.snuggle { WhereClauseSpace::Space if comment_before.is_empty() => Cow::from(" "), @@ -3316,14 +3321,11 @@ fn rewrite_comments_before_after_where( context: &RewriteContext<'_>, span_before_where: Span, span_after_where: Span, - shape: Shape, + before_shape: Shape, + after_shape: Shape, ) -> Result<(String, String), RewriteError> { - let before_comment = rewrite_missing_comment(span_before_where, shape, context)?; - let after_comment = rewrite_missing_comment( - span_after_where, - shape.block_indent(context.config.tab_spaces()), - context, - )?; + let before_comment = rewrite_missing_comment(span_before_where, before_shape, context)?; + let after_comment = rewrite_missing_comment(span_after_where, after_shape, context)?; Ok((before_comment, after_comment)) } diff --git a/src/tools/rustfmt/tests/source/where-clause-comment-wrap-issue-7148.rs b/src/tools/rustfmt/tests/source/where-clause-comment-wrap-issue-7148.rs new file mode 100644 index 0000000000000..ba6b3966f6c2c --- /dev/null +++ b/src/tools/rustfmt/tests/source/where-clause-comment-wrap-issue-7148.rs @@ -0,0 +1,29 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 100 +// rustfmt-comment_width: 100 + +// Comments between `where` and the first predicate should be formatted using +// the full column budget rather than a budget derived from the header width. +impl SomeTrait for LongTypeName +where + // A long comment line between where and the first clause that fits within max width limit + // already. So no additional wrapping should occur. + T: SomeTrait, + + // A long comment line between where and the first clause that fits within max width limit + // already. So no additional wrapping should occur. + T: OtherTrait, +{ +} + +// Comments between `where` and the first predicate should be formatted using +// the full column budget rather than a budget derived from the header width. +impl SomeOtherTrait for LongTypeName +where + // A long comment line between where and the first clause that doesn't fit within max width limit already. So additional wrapping should occur. + T: SomeTrait, + + // A long comment line between where and the first clause that doesn't fit within max width limit already. So additional wrapping should occur. + T: OtherTrait, +{ +} diff --git a/src/tools/rustfmt/tests/target/where-clause-comment-wrap-issue-7148.rs b/src/tools/rustfmt/tests/target/where-clause-comment-wrap-issue-7148.rs new file mode 100644 index 0000000000000..08f3d3e43123c --- /dev/null +++ b/src/tools/rustfmt/tests/target/where-clause-comment-wrap-issue-7148.rs @@ -0,0 +1,31 @@ +// rustfmt-wrap_comments: true +// rustfmt-max_width: 100 +// rustfmt-comment_width: 100 + +// Comments between `where` and the first predicate should be formatted using +// the full column budget rather than a budget derived from the header width. +impl SomeTrait for LongTypeName +where + // A long comment line between where and the first clause that fits within max width limit + // already. So no additional wrapping should occur. + T: SomeTrait, + + // A long comment line between where and the first clause that fits within max width limit + // already. So no additional wrapping should occur. + T: OtherTrait, +{ +} + +// Comments between `where` and the first predicate should be formatted using +// the full column budget rather than a budget derived from the header width. +impl SomeOtherTrait for LongTypeName +where + // A long comment line between where and the first clause that doesn't fit within max width + // limit already. So additional wrapping should occur. + T: SomeTrait, + + // A long comment line between where and the first clause that doesn't fit within max width + // limit already. So additional wrapping should occur. + T: OtherTrait, +{ +} From da0baa24c41da903b35aa146503e4261ffe26aaa Mon Sep 17 00:00:00 2001 From: Yara Date: Fri, 2 Oct 2026 15:38:20 +0200 Subject: [PATCH 1209/1309] reflection: fix ICE when TypeId::info called on ADT We are refactoring from a large enum where the fields of the variants contain all the reflection info to a flat enum containing only the type kind (struct/bool/array etc). While we removed the fields of Struct, Enum and Union we forgot to take out the const eval code writing into those fields. That gave an ICE. This fixes that. --- .../src/const_eval/type_info.rs | 4 +- .../src/const_eval/type_info/adt.rs | 178 +----------------- 2 files changed, 7 insertions(+), 175 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/type_info.rs b/compiler/rustc_const_eval/src/const_eval/type_info.rs index 0bece36c64ed0..0df2e9b5fd0ae 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info.rs @@ -91,9 +91,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { self.project_downcast_named(&field_dest, sym::Slice)?; variant } - ty::Adt(adt_def, generics) => { - self.write_adt_type_info(&field_dest, (ty, *adt_def), generics)? - } + ty::Adt(adt_def, _) => self.write_adt_type_info(&field_dest, *adt_def)?, ty::Bool => { let (variant, _variant_place) = self.project_downcast_named(&field_dest, sym::Bool)?; diff --git a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs index 281d7b0a921ba..4ff1b37e953d4 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs @@ -1,13 +1,12 @@ use rustc_abi::{FieldIdx, VariantIdx}; -use rustc_middle::ty::layout::TyAndLayout; use rustc_middle::ty::{ - AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, VariantDef, + AdtDef, AdtKind, Const, ConstKind, GenericArgKind, GenericArgs, Region, Ty, }; use rustc_span::{bug, span_bug, sym}; use crate::const_eval::CompileTimeMachine; use crate::interpret::{ - CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Scalar, Writeable, interp_ok, + CtfeProvenance, InterpCx, InterpResult, MPlaceTy, Projectable, Writeable, interp_ok, }; impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { @@ -15,190 +14,25 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { pub(crate) fn write_adt_type_info( &mut self, place: &impl Writeable<'tcx, CtfeProvenance>, - adt: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, + adt_def: AdtDef<'tcx>, ) -> InterpResult<'tcx, VariantIdx> { - let (adt_ty, adt_def) = adt; let variant_idx = match adt_def.adt_kind() { AdtKind::Struct => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Struct)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_struct_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; + let (variant, _) = self.project_downcast_named(place, sym::Struct)?; variant } AdtKind::Union => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Union)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_union_type_info( - place, - (adt_ty, adt_def.variant(VariantIdx::ZERO)), - generics, - )?; + let (variant, _) = self.project_downcast_named(place, sym::Union)?; variant } AdtKind::Enum => { - let (variant, variant_place) = self.project_downcast_named(place, sym::Enum)?; - let place = self.project_field(&variant_place, FieldIdx::ZERO)?; - self.write_enum_type_info(place, adt, generics)?; + let (variant, _) = self.project_downcast_named(place, sym::Enum)?; variant } }; interp_ok(variant_idx) } - pub(crate) fn write_struct_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - struct_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (struct_ty, struct_def) = struct_; - let struct_layout = self.layout_of(struct_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, struct_def, struct_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = struct_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_union_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - union_: (Ty<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (union_ty, union_def) = union_; - let union_layout = self.layout_of(union_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::fields => { - self.write_variant_fields(field_place, union_def, union_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = union_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - pub(crate) fn write_enum_type_info( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - enum_: (Ty<'tcx>, AdtDef<'tcx>), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (enum_ty, enum_def) = enum_; - let enum_layout = self.layout_of(enum_ty)?; - - for (field_idx, field) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - - match field.name { - sym::generics => self.write_generics(&field_place, generics)?, - sym::type_id_variants => { - self.allocate_fill_and_write_slice_ptr( - &field_place, - enum_def.variants().len() as u64, - |this, i, place| { - let variant_idx = VariantIdx::from_usize(i as usize); - let variant_def = &enum_def.variants()[variant_idx]; - let variant_layout = enum_layout.for_variant(this, variant_idx); - this.write_enum_variant(place, (variant_layout, &variant_def), generics) - }, - )?; - } - sym::non_exhaustive => { - let is_non_exhaustive = enum_def.is_variant_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field.did), "unimplemented field {other}"), - } - } - - interp_ok(()) - } - - fn write_enum_variant( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant: (TyAndLayout<'tcx>, &'tcx VariantDef), - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - let (variant_layout, variant_def) = variant; - - for (field_idx, field_def) in - place.layout().ty.ty_adt_def().unwrap().non_enum_variant().fields.iter_enumerated() - { - let field_place = self.project_field(&place, field_idx)?; - match field_def.name { - sym::name => { - let name_place = self.allocate_str_dedup(variant_def.name.as_str())?; - let ptr = self.mplace_to_imm_ptr(&name_place, None)?; - self.write_immediate(*ptr, &field_place)? - } - sym::fields => { - self.write_variant_fields(field_place, &variant_def, variant_layout, generics)? - } - sym::non_exhaustive => { - let is_non_exhaustive = variant_def.is_field_list_non_exhaustive(); - self.write_scalar(Scalar::from_bool(is_non_exhaustive), &field_place)? - } - other => span_bug!(self.tcx.def_span(field_def.did), "unimplemented field {other}"), - } - } - interp_ok(()) - } - - // Write fields for struct, enum variants - fn write_variant_fields( - &mut self, - place: impl Writeable<'tcx, CtfeProvenance>, - variant_def: &'tcx VariantDef, - variant_layout: TyAndLayout<'tcx>, - generics: &'tcx GenericArgs<'tcx>, - ) -> InterpResult<'tcx> { - self.allocate_fill_and_write_slice_ptr( - &place, - variant_def.fields.len() as u64, - |this, i, place| { - let field_def = &variant_def.fields[FieldIdx::from_usize(i as usize)]; - let field_ty = field_def.ty(*this.tcx, generics).skip_norm_wip(); - this.write_field(field_ty, place, variant_layout, Some(field_def.name), i) - }, - ) - } - pub(super) fn write_generics( &mut self, place: &impl Writeable<'tcx, CtfeProvenance>, From cf8cf61f5ed9b2b314a2992629ad646c49869f36 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Sat, 3 Oct 2026 02:04:27 +0530 Subject: [PATCH 1210/1309] Update feature-gate-doc_cfg test with delayed lint warnings --- tests/rustdoc-ui/feature-gate-doc_cfg.rs | 20 ++++++--- tests/rustdoc-ui/feature-gate-doc_cfg.stderr | 47 +++++++++++++++++--- 2 files changed, 57 insertions(+), 10 deletions(-) diff --git a/tests/rustdoc-ui/feature-gate-doc_cfg.rs b/tests/rustdoc-ui/feature-gate-doc_cfg.rs index b474a1524bc19..9e3d9cdde208b 100644 --- a/tests/rustdoc-ui/feature-gate-doc_cfg.rs +++ b/tests/rustdoc-ui/feature-gate-doc_cfg.rs @@ -1,6 +1,16 @@ #![doc(auto_cfg)] //~ ERROR -#![doc(auto_cfg(false))] //~ ERROR -#![doc(auto_cfg(true))] //~ ERROR -#![doc(auto_cfg(hide(feature = "solecism")))] //~ ERROR -#![doc(auto_cfg(show(feature = "bla")))] //~ ERROR -#![doc(cfg(feature = "solecism"))] //~ ERROR +#![doc(auto_cfg(false))] +//~^ ERROR +//~| WARN +#![doc(auto_cfg(true))] +//~^ ERROR +//~| WARN +#![doc(auto_cfg(hide(feature = "solecism")))] +//~^ ERROR +//~| WARN +#![doc(auto_cfg(show(feature = "bla")))] +//~^ ERROR +//~| WARN +#![doc(cfg(feature = "solecism"))] +//~^ ERROR +//~| WARN diff --git a/tests/rustdoc-ui/feature-gate-doc_cfg.stderr b/tests/rustdoc-ui/feature-gate-doc_cfg.stderr index db2f3b5737549..b8b60553cae28 100644 --- a/tests/rustdoc-ui/feature-gate-doc_cfg.stderr +++ b/tests/rustdoc-ui/feature-gate-doc_cfg.stderr @@ -19,7 +19,7 @@ LL | #![doc(auto_cfg(false))] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental - --> $DIR/feature-gate-doc_cfg.rs:3:8 + --> $DIR/feature-gate-doc_cfg.rs:5:8 | LL | #![doc(auto_cfg(true))] | ^^^^^^^^ @@ -29,7 +29,7 @@ LL | #![doc(auto_cfg(true))] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental - --> $DIR/feature-gate-doc_cfg.rs:4:8 + --> $DIR/feature-gate-doc_cfg.rs:8:8 | LL | #![doc(auto_cfg(hide(feature = "solecism")))] | ^^^^^^^^ @@ -39,7 +39,7 @@ LL | #![doc(auto_cfg(hide(feature = "solecism")))] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental - --> $DIR/feature-gate-doc_cfg.rs:5:8 + --> $DIR/feature-gate-doc_cfg.rs:11:8 | LL | #![doc(auto_cfg(show(feature = "bla")))] | ^^^^^^^^ @@ -49,7 +49,7 @@ LL | #![doc(auto_cfg(show(feature = "bla")))] = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0658]: the `doc(cfg)` and `doc(auto_cfg)` attributes are experimental - --> $DIR/feature-gate-doc_cfg.rs:6:8 + --> $DIR/feature-gate-doc_cfg.rs:14:8 | LL | #![doc(cfg(feature = "solecism"))] | ^^^ @@ -58,6 +58,43 @@ LL | #![doc(cfg(feature = "solecism"))] = help: add `#![feature(doc_cfg)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 6 previous errors +warning: only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]` + --> $DIR/feature-gate-doc_cfg.rs:2:17 + | +LL | #![doc(auto_cfg(false))] + | ^^^^^ + | + = note: `#[warn(invalid_doc_attributes)]` on by default + +warning: only `hide` or `show` are allowed in `#[doc(auto_cfg(...))]` + --> $DIR/feature-gate-doc_cfg.rs:5:17 + | +LL | #![doc(auto_cfg(true))] + | ^^^^ + +warning: `#![doc(auto_cfg(hide(...)))]` only accepts identifiers or `values(...)` + --> $DIR/feature-gate-doc_cfg.rs:8:22 + | +LL | #![doc(auto_cfg(hide(feature = "solecism")))] + | ^^^^^^^^^^^^^^^^^^^^ + +warning: `#![doc(auto_cfg(show(...)))]` only accepts identifiers or `values(...)` + --> $DIR/feature-gate-doc_cfg.rs:11:22 + | +LL | #![doc(auto_cfg(show(feature = "bla")))] + | ^^^^^^^^^^^^^^^ + +warning: unexpected `cfg` condition name: `feature` + --> $DIR/feature-gate-doc_cfg.rs:14:12 + | +LL | #![doc(cfg(feature = "solecism"))] + | ^^^^^^^^^^^^^^^^^^^^ + | + = help: expected names are: `FALSE` and `test` and 34 more + = help: to expect this configuration use `--check-cfg=cfg(feature, values("solecism"))` + = note: see for more information about checking conditional configuration + = note: `#[warn(unexpected_cfgs)]` on by default + +error: aborting due to 6 previous errors; 5 warnings emitted For more information about this error, try `rustc --explain E0658`. From 6065c5ae5206289fa17f13049c8bfad88fbfa3af Mon Sep 17 00:00:00 2001 From: Tyler Mandry Date: Fri, 2 Oct 2026 16:42:27 -0400 Subject: [PATCH 1211/1309] Make the tracking issue template better suited for experiments --- .github/ISSUE_TEMPLATE/tracking_issue.md | 32 +++++++++++++++--------- 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/tracking_issue.md b/.github/ISSUE_TEMPLATE/tracking_issue.md index 0e0fdc5ca864e..e4bdcd212f381 100644 --- a/.github/ISSUE_TEMPLATE/tracking_issue.md +++ b/.github/ISSUE_TEMPLATE/tracking_issue.md @@ -1,6 +1,6 @@ --- name: Tracking Issue -about: A tracking issue for an accepted feature or RFC in Rust. +about: A tracking issue for an unstable feature in Rust. title: Tracking Issue for XXX labels: C-tracking-issue --- @@ -8,19 +8,27 @@ labels: C-tracking-issue NOTE: For library features, please use the "Library Tracking Issue" template instead. Thank you for creating a tracking issue! 📜 Tracking issues are for tracking a -feature from implementation to stabilisation. Make sure to include the relevant -RFC for the feature if it has one. Otherwise provide a short summary of the -feature and link any relevant PRs or issues, and remove any sections that are -not relevant to the feature. +feature from implementation to stabilisation. Remember to add team labels to the tracking issue. -For a language team feature, this would e.g., be `T-lang`. +For a language team feature, this would e.g., be `T-lang`: + +> @rustbot label T-lang + Such a feature should also be labeled with e.g., `F-my_feature`. This label is used to associate issues (e.g., bugs and design questions) to the feature. --> -This is a tracking issue for the RFC "XXX" (rust-lang/rfcs#NNN). -The feature gate for the issue is `#![feature(FFF)]`. +This is a tracking issue for `#![feature(FFF)]`. +The RFC for this feature is rust-lang/rfcs#NNN. + + ### About tracking issues @@ -38,8 +46,8 @@ implementing a feature, followed by a PR that stabilises the feature. However for larger features an implementation could be broken up into multiple PRs. --> -- [ ] Implement the RFC (cc @rust-lang/XXX -- can anyone write up mentoring - instructions?) +- [ ] Create the feature gate +- [ ] Implement the feature - [ ] Adjust documentation ([see instructions on rustc-dev-guide][doc-guide]) - [ ] Style updates for any new syntax ([nightly-style-procedure]) - [ ] Style team decision on new formatting @@ -59,8 +67,8 @@ stabilised. It is useful to link related discussions and conculsions as they develop. --> -- [ ] list all the "unresolved questions" found in the RFC to ensure they are - not forgotten. +- [ ] List any unresolved questions, including those listed in the RFC if there is one, + to ensure they are not forgotten. ### Implementation history From 19fad968ff29e16ae895f7d948f8cb17fdb90978 Mon Sep 17 00:00:00 2001 From: TechnoPorg Date: Fri, 2 Oct 2026 19:56:33 -0400 Subject: [PATCH 1212/1309] chore: fix codegen backend comment --- src/bootstrap/src/core/build_steps/dist.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/dist.rs b/src/bootstrap/src/core/build_steps/dist.rs index 7073b334c414d..7edec3d1bce30 100644 --- a/src/bootstrap/src/core/build_steps/dist.rs +++ b/src/bootstrap/src/core/build_steps/dist.rs @@ -1736,7 +1736,7 @@ impl CommandLineStep for GccCodegenBackend { fn is_default_step(builder: &Builder<'_>) -> bool { // We only want to build the gcc backend in `x dist` if the backend was enabled // in rust.codegen-backends. - // Sadly, we don't have access to the actual target for which we're disting clif here.. + // Sadly, we don't have access to the actual target for which we're disting gcc here.. // So we just use the host target. builder .config From 52e14c730d067040bfb545492bf982ba9e282288 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 3 Oct 2026 04:35:33 +0000 Subject: [PATCH 1213/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to e0452e266c9a4d6522507318f8365741f0b12d29. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 716d825e606bc..4f744e09d6877 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -837b18aae097503892d7aab6c7ddce332a991a21 +e0452e266c9a4d6522507318f8365741f0b12d29 From 5e524bb6c20e1573a1f1421b24446d233bccb9b6 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sat, 3 Oct 2026 04:38:07 +0000 Subject: [PATCH 1214/1309] fmt --- src/tools/miri/src/bin/miri.rs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/tools/miri/src/bin/miri.rs b/src/tools/miri/src/bin/miri.rs index 64eed7b389a6f..0166b65ec4973 100644 --- a/src/tools/miri/src/bin/miri.rs +++ b/src/tools/miri/src/bin/miri.rs @@ -368,8 +368,9 @@ fn run_compiler_and_exit( rustc_driver::install_ctrlc_handler(); // Invoke compiler, catch any unwinding panics and handle return code. - let exit_code = - rustc_driver::catch_with_exit_code(move || rustc_driver::compiler_entrypoint(args, callbacks)); + let exit_code = rustc_driver::catch_with_exit_code(move || { + rustc_driver::compiler_entrypoint(args, callbacks) + }); exit(if exit_code == ExitCode::SUCCESS { rustc_driver::EXIT_SUCCESS } else { From 89f50a5d3a11eb03f983aca5158590e4771bfd16 Mon Sep 17 00:00:00 2001 From: panstromek Date: Sat, 3 Oct 2026 07:01:18 +0200 Subject: [PATCH 1215/1309] ref: Avoid long iterator chain in all_rust_features --- compiler/rustc_target/src/target_features.rs | 42 ++++++++++---------- 1 file changed, 22 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 2ee7dea9f8af3..5272ed2df59b3 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -1062,26 +1062,28 @@ const XTENSA_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ /// /// IMPORTANT: If you're adding another feature list above, make sure to add it to this iterator! pub fn all_rust_features() -> impl Iterator { - std::iter::empty() - .chain(ARM_FEATURES) - .chain(AARCH64_FEATURES) - .chain(X86_FEATURES) - .chain(HEXAGON_FEATURES) - .chain(POWERPC_FEATURES) - .chain(MIPS_FEATURES) - .chain(NVPTX_FEATURES) - .chain(RISCV_FEATURES) - .chain(WASM_FEATURES) - .chain(BPF_FEATURES) - .chain(XTENSA_FEATURES) - .chain(CSKY_FEATURES) - .chain(LOONGARCH_FEATURES) - .chain(IBMZ_FEATURES) - .chain(SPARC_FEATURES) - .chain(M68K_FEATURES) - .chain(AVR_FEATURES) - .cloned() - .map(|(f, s, _)| (f, s)) + [ + ARM_FEATURES, + AARCH64_FEATURES, + X86_FEATURES, + HEXAGON_FEATURES, + POWERPC_FEATURES, + MIPS_FEATURES, + NVPTX_FEATURES, + RISCV_FEATURES, + WASM_FEATURES, + BPF_FEATURES, + XTENSA_FEATURES, + CSKY_FEATURES, + LOONGARCH_FEATURES, + IBMZ_FEATURES, + SPARC_FEATURES, + M68K_FEATURES, + AVR_FEATURES, + ] + .into_iter() + .flatten() + .map(|(f, s, _)| (*f, *s)) } /// Find which target architectures a feature belongs to. From 22f30e6b1c6f639040f01618a9f506b3f0dfe4bc Mon Sep 17 00:00:00 2001 From: panstromek Date: Fri, 2 Oct 2026 15:13:32 +0200 Subject: [PATCH 1216/1309] Outline unreachable from Clause::kind unreachable!() expands to panic("internal error: entered unreachable code"), which makes the happy path perform worse than plain argument-less call. --- compiler/rustc_middle/src/ty/predicate.rs | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_middle/src/ty/predicate.rs b/compiler/rustc_middle/src/ty/predicate.rs index b82fe2ac0e5ee..7870b20c7d304 100644 --- a/compiler/rustc_middle/src/ty/predicate.rs +++ b/compiler/rustc_middle/src/ty/predicate.rs @@ -171,9 +171,17 @@ impl<'tcx> Clause<'tcx> { } pub fn kind(self) -> ty::Binder<'tcx, ClauseKind<'tcx>> { + // Outline the unreachable! call to make the happy path faster. + // see: https://github.com/rust-lang/rust/pull/163657#issuecomment-5956974964 + #[cold] + #[inline(never)] + fn unreachable_inner() -> ! { + unreachable!() + } + self.0.internee.map_bound_no_validate_bound_vars(|kind| match kind { PredicateKind::Clause(clause) => clause, - _ => unreachable!(), + _ => unreachable_inner(), }) } From 5d332db3461e1b67e6b99b9f89762d129677b2bd Mon Sep 17 00:00:00 2001 From: lcnr Date: Fri, 2 Oct 2026 11:52:42 +0200 Subject: [PATCH 1217/1309] add `ignore-compare-mode-next-solver` and change order to be consistent --- ...le-impls-shadowed-in-trait-def.next.stderr | 4 +- ...ble-impls-shadowed-in-trait-def.old.stderr | 4 +- ...-applicable-impls-shadowed-in-trait-def.rs | 1 + .../imply-relevant-nested-item-bounds-2.rs | 1 + .../imply-relevant-nested-item-bounds.rs | 1 + .../orphan-check-alias.classic.stderr | 2 +- .../coherence/orphan-check-alias.next.stderr | 2 +- tests/ui/coherence/orphan-check-alias.rs | 1 + .../orphan-check-projections-nested.rs | 1 + ...ions-not-covering-ambiguity.classic.stderr | 2 +- ...ections-not-covering-ambiguity.next.stderr | 2 +- ...heck-projections-not-covering-ambiguity.rs | 1 + ...ot-covering-multiple-params.classic.stderr | 4 +- ...s-not-covering-multiple-params.next.stderr | 4 +- ...rojections-not-covering-multiple-params.rs | 1 + ...ck-projections-not-covering.classic.stderr | 6 +-- ...check-projections-not-covering.next.stderr | 6 +-- .../orphan-check-projections-not-covering.rs | 1 + ...ck-projections-unsat-bounds.classic.stderr | 2 +- ...check-projections-unsat-bounds.next.stderr | 2 +- .../orphan-check-projections-unsat-bounds.rs | 1 + .../orphan-check-weak-aliases-covering.rs | 1 + .../ui/coinduction/canonicalization-rerun.rs | 1 + .../default-param-wf-concrete.next.stderr | 2 +- .../default-param-wf-concrete.old.stderr | 2 +- .../defaults/default-param-wf-concrete.rs | 1 + ...-on-failed-eval-with-vars-fail.next.stderr | 12 +++--- ...s-on-failed-eval-with-vars-fail.old.stderr | 2 +- ...ambiguous-on-failed-eval-with-vars-fail.rs | 1 + tests/ui/consts/const-fn-variant-ctor.rs | 1 + ...t-len-underflow-separate-spans.next.stderr | 4 +- ...st-len-underflow-separate-spans.old.stderr | 4 +- .../const-len-underflow-separate-spans.rs | 1 + tests/ui/consts/const-try.rs | 1 + tests/ui/consts/trait_alias.fail.stderr | 2 +- tests/ui/consts/trait_alias.next_fail.stderr | 2 +- tests/ui/consts/trait_alias.rs | 1 + .../coroutine/copy-fast-path-query-cycle.rs | 1 + tests/ui/coroutine/gen_block_is_fused_iter.rs | 1 + tests/ui/coroutine/gen_block_is_iter.rs | 1 + tests/ui/coroutine/gen_block_iterate.rs | 1 + tests/ui/error-codes/E0476.next.stderr | 8 ++-- tests/ui/error-codes/E0476.old.stderr | 8 ++-- tests/ui/error-codes/E0476.rs | 1 + .../incoherent-impl.next.stderr | 4 +- .../incoherent-impl.old.stderr | 4 +- .../incoherent-impl.rs | 1 + .../invalid.next.stderr | 16 ++++---- .../invalid.old.stderr | 16 ++++---- tests/ui/field_representing_types/invalid.rs | 1 + .../invariant.next.stderr | 6 +-- .../invariant.old.stderr | 6 +-- .../ui/field_representing_types/invariant.rs | 1 + .../non-struct.next.stderr | 8 ++-- .../non-struct.old.stderr | 8 ++-- .../ui/field_representing_types/non-struct.rs | 1 + .../nonexistent.next.stderr | 40 +++++++++---------- .../nonexistent.old.stderr | 40 +++++++++---------- .../field_representing_types/nonexistent.rs | 1 + .../not-field-if-packed.next.stderr | 4 +- .../not-field-if-packed.old.stderr | 4 +- .../not-field-if-packed.rs | 1 + .../not-field-if-unsized.next.stderr | 12 +++--- .../not-field-if-unsized.old.stderr | 8 ++-- .../not-field-if-unsized.rs | 1 + tests/ui/field_representing_types/offset.rs | 1 + .../privacy.next.stderr | 4 +- .../privacy.old.stderr | 4 +- tests/ui/field_representing_types/privacy.rs | 1 + .../projections.next.stderr | 10 ++--- .../projections.old.stderr | 10 ++--- .../field_representing_types/projections.rs | 1 + .../sized.next.stderr | 24 +++++------ .../field_representing_types/sized.old.stderr | 16 ++++---- tests/ui/field_representing_types/sized.rs | 1 + tests/ui/field_representing_types/traits.rs | 1 + .../weird-impls.next.stderr | 8 ++-- .../weird-impls.old.stderr | 8 ++-- .../field_representing_types/weird-impls.rs | 1 + tests/ui/float/f32-into-f32.next-solver.fixed | 1 + .../ui/float/f32-into-f32.next-solver.stderr | 10 ++--- tests/ui/float/f32-into-f32.old-solver.fixed | 1 + tests/ui/float/f32-into-f32.old-solver.stderr | 10 ++--- tests/ui/float/f32-into-f32.rs | 1 + .../rigid-hr-projection-issue-93340.rs | 1 + .../builtin-closure-like-bounds.rs | 1 + .../closure-bound-codegen-ice.rs | 1 + ...straint-from-nested-projection.next.stderr | 6 +-- .../constraint-from-nested-projection.rs | 1 + .../leak-check/leak-check-in-selection-1.rs | 1 + .../leak-check-in-selection-4-hr-nested.rs | 1 + .../leak-check-in-selection-5-ambig.rs | 1 + .../trait-bounds/issue-100689.rs | 1 + .../trait-bounds/issue-102899.rs | 1 + ...-method-resolution-opaque-type.next.stderr | 2 +- ...e-method-resolution-opaque-type.old.stderr | 2 +- ...rm-before-method-resolution-opaque-type.rs | 1 + .../auto-trait-selection-freeze.next.stderr | 2 +- .../auto-trait-selection-freeze.old.stderr | 6 +-- .../impl-trait/auto-trait-selection-freeze.rs | 1 + .../auto-trait-selection.next.stderr | 2 +- .../auto-trait-selection.old.stderr | 6 +-- tests/ui/impl-trait/auto-trait-selection.rs | 1 + tests/ui/impl-trait/call_method_ambiguous.rs | 1 + .../call_method_on_inherent_impl.rs | 1 + ...inherent_impl_on_rigid_type.current.stderr | 4 +- ...on_inherent_impl_on_rigid_type.next.stderr | 2 +- ...l_method_on_inherent_impl_on_rigid_type.rs | 1 + ...od_on_inherent_impl_ref-err.current.stderr | 4 +- ...ethod_on_inherent_impl_ref-err.next.stderr | 4 +- .../call_method_on_inherent_impl_ref-err.rs | 1 + .../call_method_on_inherent_impl_ref-ok.rs | 1 + ...-to-resolve-instance-ice-105488.old.stderr | 2 +- .../failed-to-resolve-instance-ice-105488.rs | 5 ++- .../hidden-type-is-opaque-2.default.stderr | 4 +- .../hidden-type-is-opaque-2.next.stderr | 4 +- .../ui/impl-trait/hidden-type-is-opaque-2.rs | 1 + .../method/broken-deref-chain.current.stderr | 2 +- .../impl-trait/method/broken-deref-chain.rs | 1 + .../ui/impl-trait/method/method-resolution.rs | 1 + .../method/method-resolution2.next.stderr | 6 +-- .../impl-trait/method/method-resolution2.rs | 1 + .../method/method-resolution3.current.stderr | 6 +-- .../method/method-resolution3.next.stderr | 6 +-- .../impl-trait/method/method-resolution3.rs | 1 + .../impl-trait/method/method-resolution4.rs | 1 + ...olution5-deref-no-constrain.current.stderr | 2 +- .../method-resolution5-deref-no-constrain.rs | 1 + .../method/method-resolution5-deref.rs | 1 + .../would-constrain-opaque.current.stderr | 8 ++-- .../method/would-constrain-opaque.next.stderr | 4 +- .../method/would-constrain-opaque.rs | 1 + tests/ui/impl-trait/recursive-bound-eval.rs | 1 + .../rpit/const_check_false_cycle.rs | 1 + .../ui/impl-trait/rpit/dyn-in-nested-rpit.rs | 1 + .../precise-capture-155151.current.stderr | 2 +- .../impl-trait/rpit/precise-capture-155151.rs | 1 + tests/ui/impl-trait/unsized_coercion.rs | 1 + .../impl-trait/unsized_coercion2.old.stderr | 2 +- tests/ui/impl-trait/unsized_coercion2.rs | 1 + .../impl-trait/unsized_coercion3.next.stderr | 8 ++-- .../impl-trait/unsized_coercion3.old.stderr | 2 +- tests/ui/impl-trait/unsized_coercion3.rs | 1 + tests/ui/impl-trait/unsized_coercion4.rs | 1 + .../impl-trait/unsized_coercion5.old.stderr | 2 +- tests/ui/impl-trait/unsized_coercion5.rs | 1 + ...-on-ref-due-to-missing-bound.current.fixed | 1 + ...on-ref-due-to-missing-bound.current.stderr | 4 +- ...all-on-ref-due-to-missing-bound.next.fixed | 1 + ...ll-on-ref-due-to-missing-bound.next.stderr | 4 +- ...-clone-call-on-ref-due-to-missing-bound.rs | 1 + .../basic/method-on-never.current.stderr | 20 +++++----- .../basic/method-on-never.next.stderr | 20 +++++----- tests/ui/never_type/basic/method-on-never.rs | 1 + tests/ui/sized-hierarchy/alias-bounds.rs | 1 + .../bound-on-assoc-type-projection-1.rs | 1 + .../elaboration-opt-regions-1.rs | 1 + .../elaboration-opt-regions.rs | 1 + ...efault-items-drop-coherence.current.stderr | 2 +- ...n-default-items-drop-coherence.next.stderr | 2 +- ...ialization-default-items-drop-coherence.rs | 1 + .../assoc-type-const-bound-usage-0.rs | 1 + ...pe-const-bound-usage-fail-2.current.stderr | 4 +- ...-type-const-bound-usage-fail-2.next.stderr | 4 +- .../assoc-type-const-bound-usage-fail-2.rs | 1 + ...type-const-bound-usage-fail.current.stderr | 4 +- ...oc-type-const-bound-usage-fail.next.stderr | 4 +- .../assoc-type-const-bound-usage-fail.rs | 1 + .../const-traits/assoc-type.current.stderr | 4 +- .../const-traits/assoc-type.next.stderr | 4 +- tests/ui/traits/const-traits/assoc-type.rs | 1 + .../call-const-closure.next.stderr | 2 +- .../call-const-closure.old.stderr | 2 +- .../traits/const-traits/call-const-closure.rs | 1 + tests/ui/traits/const-traits/call.rs | 1 + ...const-closure-inherited-const-condition.rs | 1 + .../const-closure-trait-method.rs | 1 + .../ui/traits/const-traits/const-closures.rs | 1 + .../const-drop-fail.new_precise.stderr | 12 +++--- .../const-drop-fail.new_stock.stderr | 12 +++--- .../const-drop-fail.old_precise.stderr | 12 +++--- .../const-drop-fail.old_stock.stderr | 12 +++--- .../ui/traits/const-traits/const-drop-fail.rs | 1 + .../drop-manually-drop-no-drop-impl.rs | 1 + .../traits/const-traits/drop-manually-drop.rs | 1 + .../extern-types.current.stderr | 4 +- .../extern-types.next.stderr | 4 +- .../default_auto_traits/extern-types.rs | 1 + ...-missing-clone-issue-141241.current.stderr | 2 +- ...ice-missing-clone-issue-141241.next.stderr | 2 +- .../cow-slice-missing-clone-issue-141241.rs | 1 + .../generic-cow-inference-regression.rs | 1 + .../traits/issue-90662-projection-caching.rs | 1 + .../next-solver/adt-const-param-projection.rs | 1 + .../next-solver/alias-bound-preference.rs | 1 + .../ambiguous-impl-in-resolve.next.stderr | 4 +- .../ambiguous-impl-in-resolve.old.stderr | 4 +- .../next-solver/ambiguous-impl-in-resolve.rs | 1 + ...re-inference-hr-ambig-alias-naming-self.rs | 1 + ...th-bound-vars-incomplete-generalization.rs | 1 + ...ark-const-aliases-as-rigid-in-param-env.rs | 1 + .../dump-layout-opaque-coroutine.next.stderr | 2 +- .../dump-layout-opaque-coroutine.old.stderr | 2 +- .../opaques/dump-layout-opaque-coroutine.rs | 1 + .../overflow/fcw-on-auto-trait.next.stderr | 2 +- .../next-solver/overflow/fcw-on-auto-trait.rs | 1 + .../overflow/fcw-on-normalization.next.stderr | 2 +- .../overflow/fcw-on-normalization.rs | 1 + ...flow-to-ambig-with-constraints.next.stderr | 2 +- .../fcw-overflow-to-ambig-with-constraints.rs | 1 + .../fcw-overflow-to-error.next.stderr | 2 +- .../overflow/fcw-overflow-to-error.rs | 1 + .../next-solver/overflow/nalgebra-hang.rs | 1 + ...ram-env-normalization-fallback.next.stderr | 12 +++--- ...aram-env-normalization-fallback.old.stderr | 12 +++--- .../param-env-normalization-fallback.rs | 1 + .../self-referential-closure-sig-1.rs | 1 + .../self-referential-closure-sig-3.rs | 1 + ...field-location-issue-146016.current.stderr | 26 ++++++------ ...nd-field-location-issue-146016.next.stderr | 26 ++++++------ .../non-send-field-location-issue-146016.rs | 1 + .../normalize/pointee-normalize-equate.rs | 1 + .../illegal-upcast-to-impl-opaque.rs | 1 + .../destructure_tait-ice-113594.rs | 1 + .../lifetime_mismatch.current.stderr | 8 ++-- .../lifetime_mismatch.rs | 1 + .../method_resolution.current.stderr | 2 +- .../method_resolution.next.stderr | 2 +- .../method_resolution.rs | 1 + .../method_resolution2.rs | 1 + .../method_resolution3.current.stderr | 4 +- .../method_resolution3.next.stderr | 4 +- .../method_resolution3.rs | 1 + .../method_resolution4.current.stderr | 4 +- .../method_resolution4.next.stderr | 4 +- .../method_resolution4.rs | 1 + .../method_resolution5.rs | 1 + ...on_trait_method_from_opaque.current.stderr | 4 +- ...ution_trait_method_from_opaque.next.stderr | 2 +- ...hod_resolution_trait_method_from_opaque.rs | 1 + ...ef-uses-in-one-fn-lifetimes.current.stderr | 4 +- .../multiple-def-uses-in-one-fn-lifetimes.rs | 1 + .../mututally-recursive-overflow.rs | 5 ++- .../precise-capture-155151.current.stderr | 2 +- .../precise-capture-155151.rs | 1 + .../type-alias-impl-trait/tait-normalize.rs | 1 + .../wf-in-associated-type.fail.stderr | 6 +-- .../wf-in-associated-type.rs | 1 + tests/ui/typeck/issue-116864.current.stderr | 4 +- tests/ui/typeck/issue-116864.next.stderr | 4 +- tests/ui/typeck/issue-116864.rs | 1 + .../unsafe-fields/auto-traits.current.stderr | 6 +-- .../ui/unsafe-fields/auto-traits.next.stderr | 6 +-- tests/ui/unsafe-fields/auto-traits.rs | 1 + 254 files changed, 520 insertions(+), 388 deletions(-) diff --git a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.next.stderr b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.next.stderr index 30eccc3a72d51..9baf1e6c84a86 100644 --- a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.next.stderr +++ b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq<::Assoc>` is not satisfied - --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:13:17 + --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:14:17 | LL | fn foo() -> IsEqual { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<::Assoc>` is not implemented for `Self` | note: required by a bound in `IsEqual` - --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:9:19 + --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:10:19 | LL | struct IsEqual, U>(T, U); | ^^^^^ required by this bound in `IsEqual` diff --git a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.old.stderr b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.old.stderr index 30eccc3a72d51..9baf1e6c84a86 100644 --- a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.old.stderr +++ b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.old.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `Self: Eq<::Assoc>` is not satisfied - --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:13:17 + --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:14:17 | LL | fn foo() -> IsEqual { | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Eq<::Assoc>` is not implemented for `Self` | note: required by a bound in `IsEqual` - --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:9:19 + --> $DIR/always-applicable-impls-shadowed-in-trait-def.rs:10:19 | LL | struct IsEqual, U>(T, U); | ^^^^^ required by this bound in `IsEqual` diff --git a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.rs b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.rs index 2f8abb6a70d86..8905630617302 100644 --- a/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.rs +++ b/tests/ui/associated-types/always-applicable-impls-shadowed-in-trait-def.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Testing that even if there's an always applicable blanket impl, the trait diff --git a/tests/ui/associated-types/imply-relevant-nested-item-bounds-2.rs b/tests/ui/associated-types/imply-relevant-nested-item-bounds-2.rs index 864c31893504f..eb5a87ebf95a2 100644 --- a/tests/ui/associated-types/imply-relevant-nested-item-bounds-2.rs +++ b/tests/ui/associated-types/imply-relevant-nested-item-bounds-2.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver trait Trait diff --git a/tests/ui/associated-types/imply-relevant-nested-item-bounds.rs b/tests/ui/associated-types/imply-relevant-nested-item-bounds.rs index 5a477a5b34941..235edbdaebf13 100644 --- a/tests/ui/associated-types/imply-relevant-nested-item-bounds.rs +++ b/tests/ui/associated-types/imply-relevant-nested-item-bounds.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver trait Foo diff --git a/tests/ui/coherence/orphan-check-alias.classic.stderr b/tests/ui/coherence/orphan-check-alias.classic.stderr index 29e09ff550e9e..7b263cc7996f9 100644 --- a/tests/ui/coherence/orphan-check-alias.classic.stderr +++ b/tests/ui/coherence/orphan-check-alias.classic.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`B`) - --> $DIR/orphan-check-alias.rs:21:6 + --> $DIR/orphan-check-alias.rs:22:6 | LL | impl foreign::Trait2 for ::Assoc { | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-alias.next.stderr b/tests/ui/coherence/orphan-check-alias.next.stderr index 29e09ff550e9e..7b263cc7996f9 100644 --- a/tests/ui/coherence/orphan-check-alias.next.stderr +++ b/tests/ui/coherence/orphan-check-alias.next.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`B`) - --> $DIR/orphan-check-alias.rs:21:6 + --> $DIR/orphan-check-alias.rs:22:6 | LL | impl foreign::Trait2 for ::Assoc { | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-alias.rs b/tests/ui/coherence/orphan-check-alias.rs index d6c9d0aa8bea1..711e7d83a63e5 100644 --- a/tests/ui/coherence/orphan-check-alias.rs +++ b/tests/ui/coherence/orphan-check-alias.rs @@ -1,6 +1,7 @@ // Alias might not cover type parameters. //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ aux-crate:foreign=parametrized-trait.rs diff --git a/tests/ui/coherence/orphan-check-projections-nested.rs b/tests/ui/coherence/orphan-check-projections-nested.rs index ec244a8005b16..ab4ba9fcf1861 100644 --- a/tests/ui/coherence/orphan-check-projections-nested.rs +++ b/tests/ui/coherence/orphan-check-projections-nested.rs @@ -2,6 +2,7 @@ //@ check-pass //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ aux-crate:dep=trait-with-assoc-ty.rs //@ edition: 2021 diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr index 635d9e6619004..e85dd1c49ecad 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.classic.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:25:6 + --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:26:6 | LL | impl foreign::Trait1 for ::Output {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr index 635d9e6619004..e85dd1c49ecad 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.next.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:25:6 + --> $DIR/orphan-check-projections-not-covering-ambiguity.rs:26:6 | LL | impl foreign::Trait1 for ::Output {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs index 227d8535232df..7070ba8e02b26 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs +++ b/tests/ui/coherence/orphan-check-projections-not-covering-ambiguity.rs @@ -7,6 +7,7 @@ // ambiguity. //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr index e75d4e61772f1..68989253e25ce 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.classic.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:6 + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:18:6 | LL | impl foreign::Trait0 for <() as Trait>::Assoc {} | ^ uncovered type parameter @@ -13,7 +13,7 @@ LL | impl foreign::Trait0 for <() as Trait>::Assoc {} = note: `#[warn(uncovered_param_in_projection)]` (part of `#[warn(future_incompatible)]`) on by default warning: type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:9 + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:18:9 | LL | impl foreign::Trait0 for <() as Trait>::Assoc {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr index e75d4e61772f1..68989253e25ce 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.next.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:6 + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:18:6 | LL | impl foreign::Trait0 for <() as Trait>::Assoc {} | ^ uncovered type parameter @@ -13,7 +13,7 @@ LL | impl foreign::Trait0 for <() as Trait>::Assoc {} = note: `#[warn(uncovered_param_in_projection)]` (part of `#[warn(future_incompatible)]`) on by default warning: type parameter `U` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:17:9 + --> $DIR/orphan-check-projections-not-covering-multiple-params.rs:18:9 | LL | impl foreign::Trait0 for <() as Trait>::Assoc {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs index c5340e854054d..e1369d5466181 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs +++ b/tests/ui/coherence/orphan-check-projections-not-covering-multiple-params.rs @@ -1,4 +1,5 @@ //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr b/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr index 6d1a3114937af..425ba8b6e9ad9 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering.classic.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:22:6 + --> $DIR/orphan-check-projections-not-covering.rs:23:6 | LL | impl foreign::Trait0 for ::Output {} | ^ uncovered type parameter @@ -13,7 +13,7 @@ LL | impl foreign::Trait0 for ::Output {} = note: `#[warn(uncovered_param_in_projection)]` (part of `#[warn(future_incompatible)]`) on by default warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:27:6 + --> $DIR/orphan-check-projections-not-covering.rs:28:6 | LL | impl foreign::Trait0<::Output, Local, T> for Option {} | ^ uncovered type parameter @@ -26,7 +26,7 @@ LL | impl foreign::Trait0<::Output, Local, T> for Option {} = note: for more information, see issue #124559 warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:40:6 + --> $DIR/orphan-check-projections-not-covering.rs:41:6 | LL | impl foreign::Trait1 for ::Output {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr b/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr index 6d1a3114937af..425ba8b6e9ad9 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr +++ b/tests/ui/coherence/orphan-check-projections-not-covering.next.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:22:6 + --> $DIR/orphan-check-projections-not-covering.rs:23:6 | LL | impl foreign::Trait0 for ::Output {} | ^ uncovered type parameter @@ -13,7 +13,7 @@ LL | impl foreign::Trait0 for ::Output {} = note: `#[warn(uncovered_param_in_projection)]` (part of `#[warn(future_incompatible)]`) on by default warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:27:6 + --> $DIR/orphan-check-projections-not-covering.rs:28:6 | LL | impl foreign::Trait0<::Output, Local, T> for Option {} | ^ uncovered type parameter @@ -26,7 +26,7 @@ LL | impl foreign::Trait0<::Output, Local, T> for Option {} = note: for more information, see issue #124559 warning: type parameter `T` must be covered by another type when it appears before the first local type (`Local`) - --> $DIR/orphan-check-projections-not-covering.rs:40:6 + --> $DIR/orphan-check-projections-not-covering.rs:41:6 | LL | impl foreign::Trait1 for ::Output {} | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-not-covering.rs b/tests/ui/coherence/orphan-check-projections-not-covering.rs index 8c2a9a17e2b84..a4722da1f8aea 100644 --- a/tests/ui/coherence/orphan-check-projections-not-covering.rs +++ b/tests/ui/coherence/orphan-check-projections-not-covering.rs @@ -2,6 +2,7 @@ // Projections might not cover type parameters. //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr b/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr index 9021a4757b851..54fcaf1705c2f 100644 --- a/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.classic.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-unsat-bounds.rs:28:6 + --> $DIR/orphan-check-projections-unsat-bounds.rs:29:6 | LL | impl foreign::Trait1 for as Discard>::Output | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr b/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr index 9021a4757b851..54fcaf1705c2f 100644 --- a/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.next.stderr @@ -1,5 +1,5 @@ warning: type parameter `T` must be covered by another type when it appears before the first local type (`LocalTy`) - --> $DIR/orphan-check-projections-unsat-bounds.rs:28:6 + --> $DIR/orphan-check-projections-unsat-bounds.rs:29:6 | LL | impl foreign::Trait1 for as Discard>::Output | ^ uncovered type parameter diff --git a/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs b/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs index bc52673a016f4..05d64ab282687 100644 --- a/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs +++ b/tests/ui/coherence/orphan-check-projections-unsat-bounds.rs @@ -4,6 +4,7 @@ // unsatisfied bounds while normalization outside of orphan checking succeeds. //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coherence/orphan-check-weak-aliases-covering.rs b/tests/ui/coherence/orphan-check-weak-aliases-covering.rs index d976f9d5f360a..7e4dbf1465996 100644 --- a/tests/ui/coherence/orphan-check-weak-aliases-covering.rs +++ b/tests/ui/coherence/orphan-check-weak-aliases-covering.rs @@ -2,6 +2,7 @@ //@ check-pass //@ revisions: classic next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ aux-crate:foreign=parametrized-trait.rs diff --git a/tests/ui/coinduction/canonicalization-rerun.rs b/tests/ui/coinduction/canonicalization-rerun.rs index 06085ebfe0ba5..b6878e18c9081 100644 --- a/tests/ui/coinduction/canonicalization-rerun.rs +++ b/tests/ui/coinduction/canonicalization-rerun.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // If we use canonical goals during trait solving we have to reevaluate diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr index 133d8f6b0f086..df2d5162655ec 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.next.stderr @@ -1,5 +1,5 @@ error[E0080]: attempt to compute `u8::MAX + 1_u8`, which would overflow - --> $DIR/default-param-wf-concrete.rs:4:28 + --> $DIR/default-param-wf-concrete.rs:5:28 | LL | struct Foo; | ^^^^^^^ evaluation of `Foo::{constant#0}` failed here diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr index 133d8f6b0f086..df2d5162655ec 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.old.stderr @@ -1,5 +1,5 @@ error[E0080]: attempt to compute `u8::MAX + 1_u8`, which would overflow - --> $DIR/default-param-wf-concrete.rs:4:28 + --> $DIR/default-param-wf-concrete.rs:5:28 | LL | struct Foo; | ^^^^^^^ evaluation of `Foo::{constant#0}` failed here diff --git a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs index 0385e55e3b29a..a2a2509a1dee1 100644 --- a/tests/ui/const-generics/defaults/default-param-wf-concrete.rs +++ b/tests/ui/const-generics/defaults/default-param-wf-concrete.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver struct Foo; diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr index 0bbfe0626470d..0020a58df5768 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.next.stderr @@ -1,11 +1,11 @@ error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:33:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:34:9 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | note: required by a const generic parameter in `free` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:28:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:29:9 | LL | fn free() -> ([(); N], [(); gca!(FREE::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `free` @@ -15,7 +15,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = free(); | +++++++++++++ error[E0271]: type mismatch resolving `FREE<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:39:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:40:45 | LL | let (mut arr, mut arr_with_weird_len) = free(); | ^^^^^^ expected `2`, found `10` @@ -24,14 +24,14 @@ LL | let (mut arr, mut arr_with_weird_len) = free(); found constant `10` error[E0284]: type annotations needed for `([(); _], [(); 10])` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:50:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:51:9 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------ type must be known at this point | = note: cannot satisfy `::PROJ<_> == 10` note: required by a const generic parameter in `proj` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:45:9 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:46:9 | LL | fn proj() -> ([(); N], [(); gca!(::PROJ::)]) { | ^^^^^^^^^^^^^^ required by this const generic parameter in `proj` @@ -41,7 +41,7 @@ LL | let (mut arr, mut arr_with_weird_len): ([_; N], _) = proj(); | +++++++++++++ error[E0271]: type mismatch resolving `::PROJ<10> == 2` - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:56:45 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:57:45 | LL | let (mut arr, mut arr_with_weird_len) = proj(); | ^^^^^^ expected `2`, found `10` diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr index f3cb4a06cddc8..ffe00153daab8 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.old.stderr @@ -1,5 +1,5 @@ error: `gca_const_items` requires -Znext-solver=globally to be enabled - --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:9:5 + --> $DIR/ambiguous-on-failed-eval-with-vars-fail.rs:10:5 | LL | gca_const_items, | ^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs index e24b11dbb1746..0449754451c2d 100644 --- a/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs +++ b/tests/ui/const-generics/gca/ambiguous-on-failed-eval-with-vars-fail.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // (`test_free_mismatch` is quite difficult to implement in the old solver, so make sure this test // runs on the old solver, just in case someone attempts to implement GCA for the old solver and diff --git a/tests/ui/consts/const-fn-variant-ctor.rs b/tests/ui/consts/const-fn-variant-ctor.rs index db8324f3997bd..b56f3145c11c3 100644 --- a/tests/ui/consts/const-fn-variant-ctor.rs +++ b/tests/ui/consts/const-fn-variant-ctor.rs @@ -1,6 +1,7 @@ //@ check-pass // @ needs-rustc-debug-assertions //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_destruct, const_trait_impl)] diff --git a/tests/ui/consts/const-len-underflow-separate-spans.next.stderr b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr index ef46522f7f5d4..d895803b706c3 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.next.stderr +++ b/tests/ui/consts/const-len-underflow-separate-spans.next.stderr @@ -1,11 +1,11 @@ error[E0080]: attempt to compute `1_usize - 2_usize`, which would overflow - --> $DIR/const-len-underflow-separate-spans.rs:10:20 + --> $DIR/const-len-underflow-separate-spans.rs:11:20 | LL | const LEN: usize = ONE - TWO; | ^^^^^^^^^ evaluation of `LEN` failed here note: erroneous constant encountered - --> $DIR/const-len-underflow-separate-spans.rs:15:17 + --> $DIR/const-len-underflow-separate-spans.rs:16:17 | LL | let a: [i8; LEN] = unimplemented!(); | ^^^ diff --git a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr index ef46522f7f5d4..d895803b706c3 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.old.stderr +++ b/tests/ui/consts/const-len-underflow-separate-spans.old.stderr @@ -1,11 +1,11 @@ error[E0080]: attempt to compute `1_usize - 2_usize`, which would overflow - --> $DIR/const-len-underflow-separate-spans.rs:10:20 + --> $DIR/const-len-underflow-separate-spans.rs:11:20 | LL | const LEN: usize = ONE - TWO; | ^^^^^^^^^ evaluation of `LEN` failed here note: erroneous constant encountered - --> $DIR/const-len-underflow-separate-spans.rs:15:17 + --> $DIR/const-len-underflow-separate-spans.rs:16:17 | LL | let a: [i8; LEN] = unimplemented!(); | ^^^ diff --git a/tests/ui/consts/const-len-underflow-separate-spans.rs b/tests/ui/consts/const-len-underflow-separate-spans.rs index ee8c79dafa799..806acb1cc3f75 100644 --- a/tests/ui/consts/const-len-underflow-separate-spans.rs +++ b/tests/ui/consts/const-len-underflow-separate-spans.rs @@ -3,6 +3,7 @@ // overall context for what caused the evaluation. //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver const ONE: usize = 1; diff --git a/tests/ui/consts/const-try.rs b/tests/ui/consts/const-try.rs index b6dc00140f839..fb958f911c4af 100644 --- a/tests/ui/consts/const-try.rs +++ b/tests/ui/consts/const-try.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Demonstrates what's needed to make use of `?` in const contexts. diff --git a/tests/ui/consts/trait_alias.fail.stderr b/tests/ui/consts/trait_alias.fail.stderr index 62f5ab1a7d2cd..3a28de5a0ed14 100644 --- a/tests/ui/consts/trait_alias.fail.stderr +++ b/tests/ui/consts/trait_alias.fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: [const] Baz` is not satisfied - --> $DIR/trait_alias.rs:24:11 + --> $DIR/trait_alias.rs:25:11 | LL | x.baz(); | ^^^ diff --git a/tests/ui/consts/trait_alias.next_fail.stderr b/tests/ui/consts/trait_alias.next_fail.stderr index 62f5ab1a7d2cd..3a28de5a0ed14 100644 --- a/tests/ui/consts/trait_alias.next_fail.stderr +++ b/tests/ui/consts/trait_alias.next_fail.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `T: [const] Baz` is not satisfied - --> $DIR/trait_alias.rs:24:11 + --> $DIR/trait_alias.rs:25:11 | LL | x.baz(); | ^^^ diff --git a/tests/ui/consts/trait_alias.rs b/tests/ui/consts/trait_alias.rs index 7bda53ca08346..2d472cde242a9 100644 --- a/tests/ui/consts/trait_alias.rs +++ b/tests/ui/consts/trait_alias.rs @@ -1,5 +1,6 @@ #![feature(trait_alias, const_trait_impl)] //@ revisions: next_pass next_fail pass fail +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next_pass] compile-flags: -Znext-solver //@[next_fail] compile-flags: -Znext-solver //@[next_pass] check-pass diff --git a/tests/ui/coroutine/copy-fast-path-query-cycle.rs b/tests/ui/coroutine/copy-fast-path-query-cycle.rs index 644cba0d47af2..4522a129d8338 100644 --- a/tests/ui/coroutine/copy-fast-path-query-cycle.rs +++ b/tests/ui/coroutine/copy-fast-path-query-cycle.rs @@ -1,5 +1,6 @@ //@ edition: 2024 //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coroutine/gen_block_is_fused_iter.rs b/tests/ui/coroutine/gen_block_is_fused_iter.rs index e4eab6195eecf..02cfcdf7a4ec6 100644 --- a/tests/ui/coroutine/gen_block_is_fused_iter.rs +++ b/tests/ui/coroutine/gen_block_is_fused_iter.rs @@ -1,4 +1,5 @@ //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition: 2024 //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coroutine/gen_block_is_iter.rs b/tests/ui/coroutine/gen_block_is_iter.rs index 032360fbee032..6524f41f23e76 100644 --- a/tests/ui/coroutine/gen_block_is_iter.rs +++ b/tests/ui/coroutine/gen_block_is_iter.rs @@ -1,4 +1,5 @@ //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition: 2024 //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/coroutine/gen_block_iterate.rs b/tests/ui/coroutine/gen_block_iterate.rs index afeb56cc2f3f9..4a60600ff4dc6 100644 --- a/tests/ui/coroutine/gen_block_iterate.rs +++ b/tests/ui/coroutine/gen_block_iterate.rs @@ -1,4 +1,5 @@ //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition: 2024 //@[next] compile-flags: -Znext-solver //@ run-pass diff --git a/tests/ui/error-codes/E0476.next.stderr b/tests/ui/error-codes/E0476.next.stderr index 454dbecc7d01f..8b2dcbcf54462 100644 --- a/tests/ui/error-codes/E0476.next.stderr +++ b/tests/ui/error-codes/E0476.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:12:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,18 +9,18 @@ LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:12:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:11:6 + --> $DIR/E0476.rs:12:6 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:11:10 + --> $DIR/E0476.rs:12:10 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ diff --git a/tests/ui/error-codes/E0476.old.stderr b/tests/ui/error-codes/E0476.old.stderr index 454dbecc7d01f..8b2dcbcf54462 100644 --- a/tests/ui/error-codes/E0476.old.stderr +++ b/tests/ui/error-codes/E0476.old.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:12:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,18 +9,18 @@ LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:11:1 + --> $DIR/E0476.rs:12:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:11:6 + --> $DIR/E0476.rs:12:6 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:11:10 + --> $DIR/E0476.rs:12:10 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ diff --git a/tests/ui/error-codes/E0476.rs b/tests/ui/error-codes/E0476.rs index 03656d28b2b99..38854f0768d80 100644 --- a/tests/ui/error-codes/E0476.rs +++ b/tests/ui/error-codes/E0476.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver=coherence #![feature(coerce_unsized)] #![feature(unsize)] diff --git a/tests/ui/field_representing_types/incoherent-impl.next.stderr b/tests/ui/field_representing_types/incoherent-impl.next.stderr index 47f91e8dd2e9d..fc9f663ac076e 100644 --- a/tests/ui/field_representing_types/incoherent-impl.next.stderr +++ b/tests/ui/field_representing_types/incoherent-impl.next.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/incoherent-impl.rs:22:1 + --> $DIR/incoherent-impl.rs:23:1 | LL | impl ForeignTrait for field_of!(Point, x) {} | ^^^^^^^^^^^^^^^^^^^^^^------------------- @@ -11,7 +11,7 @@ LL | impl ForeignTrait for field_of!(Point, x) {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/incoherent-impl.rs:25:1 + --> $DIR/incoherent-impl.rs:26:1 | LL | impl ForeignTrait for field_of!((usize, usize), 0) {} | ^^^^^^^^^^^^^^^^^^^^^^---------------------------- diff --git a/tests/ui/field_representing_types/incoherent-impl.old.stderr b/tests/ui/field_representing_types/incoherent-impl.old.stderr index 47f91e8dd2e9d..fc9f663ac076e 100644 --- a/tests/ui/field_representing_types/incoherent-impl.old.stderr +++ b/tests/ui/field_representing_types/incoherent-impl.old.stderr @@ -1,5 +1,5 @@ error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/incoherent-impl.rs:22:1 + --> $DIR/incoherent-impl.rs:23:1 | LL | impl ForeignTrait for field_of!(Point, x) {} | ^^^^^^^^^^^^^^^^^^^^^^------------------- @@ -11,7 +11,7 @@ LL | impl ForeignTrait for field_of!(Point, x) {} = note: define and implement a trait or new type instead error[E0117]: only traits defined in the current crate can be implemented for types defined outside of the crate - --> $DIR/incoherent-impl.rs:25:1 + --> $DIR/incoherent-impl.rs:26:1 | LL | impl ForeignTrait for field_of!((usize, usize), 0) {} | ^^^^^^^^^^^^^^^^^^^^^^---------------------------- diff --git a/tests/ui/field_representing_types/incoherent-impl.rs b/tests/ui/field_representing_types/incoherent-impl.rs index 22db652359f69..8928e885432fe 100644 --- a/tests/ui/field_representing_types/incoherent-impl.rs +++ b/tests/ui/field_representing_types/incoherent-impl.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ aux-build:extern-crate.rs #![expect(incomplete_features)] diff --git a/tests/ui/field_representing_types/invalid.next.stderr b/tests/ui/field_representing_types/invalid.next.stderr index 38b011ab6f84a..52872001b4dee 100644 --- a/tests/ui/field_representing_types/invalid.next.stderr +++ b/tests/ui/field_representing_types/invalid.next.stderr @@ -1,5 +1,5 @@ error: unexpected end of macro invocation - --> $DIR/invalid.rs:23:28 + --> $DIR/invalid.rs:24:28 | LL | let _: field_of!(Struct); | ^ missing tokens in macro arguments @@ -9,7 +9,7 @@ note: while trying to match `,` = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: unexpected end of macro invocation - --> $DIR/invalid.rs:24:29 + --> $DIR/invalid.rs:25:29 | LL | let _: field_of!(Struct,); | ^ missing tokens in macro arguments @@ -19,7 +19,7 @@ note: while trying to match meta-variable `$fields:expr` = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: no rules expected `extra` - --> $DIR/invalid.rs:25:37 + --> $DIR/invalid.rs:26:37 | LL | let _: field_of!(Struct, field, extra); | ^^^^^ no rules expected this token in macro call @@ -28,13 +28,13 @@ LL | let _: field_of!(Struct, field, extra); = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: offset_of expects dot-separated field and variant names - --> $DIR/invalid.rs:27:28 + --> $DIR/invalid.rs:28:28 | LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ error: `field_of!` expects dot-separated field and variant names - --> $DIR/invalid.rs:27:12 + --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,13 +43,13 @@ LL | let _: field_of!(Enum, Variant..field); | this macro call doesn't expand to a type error: offset_of expects dot-separated field and variant names - --> $DIR/invalid.rs:29:30 + --> $DIR/invalid.rs:30:30 | LL | let _: field_of!(Struct, [42]); | ^^^^ error: `field_of!` expects dot-separated field and variant names - --> $DIR/invalid.rs:29:12 + --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | let _: field_of!(Struct, [42]); | this macro call doesn't expand to a type error: `field_of!` only supports a single field or a variant with a field - --> $DIR/invalid.rs:31:30 + --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); | ------------------^^^^^^-^^^^^^-^^^^^^- diff --git a/tests/ui/field_representing_types/invalid.old.stderr b/tests/ui/field_representing_types/invalid.old.stderr index 38b011ab6f84a..52872001b4dee 100644 --- a/tests/ui/field_representing_types/invalid.old.stderr +++ b/tests/ui/field_representing_types/invalid.old.stderr @@ -1,5 +1,5 @@ error: unexpected end of macro invocation - --> $DIR/invalid.rs:23:28 + --> $DIR/invalid.rs:24:28 | LL | let _: field_of!(Struct); | ^ missing tokens in macro arguments @@ -9,7 +9,7 @@ note: while trying to match `,` = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: unexpected end of macro invocation - --> $DIR/invalid.rs:24:29 + --> $DIR/invalid.rs:25:29 | LL | let _: field_of!(Struct,); | ^ missing tokens in macro arguments @@ -19,7 +19,7 @@ note: while trying to match meta-variable `$fields:expr` = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: no rules expected `extra` - --> $DIR/invalid.rs:25:37 + --> $DIR/invalid.rs:26:37 | LL | let _: field_of!(Struct, field, extra); | ^^^^^ no rules expected this token in macro call @@ -28,13 +28,13 @@ LL | let _: field_of!(Struct, field, extra); = note: this macro expects a container type and a field path, like `field_of!(Type, field)` or `field_of!(Enum, Variant.field)` error: offset_of expects dot-separated field and variant names - --> $DIR/invalid.rs:27:28 + --> $DIR/invalid.rs:28:28 | LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^ error: `field_of!` expects dot-separated field and variant names - --> $DIR/invalid.rs:27:12 + --> $DIR/invalid.rs:28:12 | LL | let _: field_of!(Enum, Variant..field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -43,13 +43,13 @@ LL | let _: field_of!(Enum, Variant..field); | this macro call doesn't expand to a type error: offset_of expects dot-separated field and variant names - --> $DIR/invalid.rs:29:30 + --> $DIR/invalid.rs:30:30 | LL | let _: field_of!(Struct, [42]); | ^^^^ error: `field_of!` expects dot-separated field and variant names - --> $DIR/invalid.rs:29:12 + --> $DIR/invalid.rs:30:12 | LL | let _: field_of!(Struct, [42]); | ^^^^^^^^^^^^^^^^^^^^^^^ @@ -58,7 +58,7 @@ LL | let _: field_of!(Struct, [42]); | this macro call doesn't expand to a type error: `field_of!` only supports a single field or a variant with a field - --> $DIR/invalid.rs:31:30 + --> $DIR/invalid.rs:32:30 | LL | let _: field_of!(Struct, field1.field2.field3); | ------------------^^^^^^-^^^^^^-^^^^^^- diff --git a/tests/ui/field_representing_types/invalid.rs b/tests/ui/field_representing_types/invalid.rs index d1fc217db7ddd..0d8c5d563401c 100644 --- a/tests/ui/field_representing_types/invalid.rs +++ b/tests/ui/field_representing_types/invalid.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/invariant.next.stderr b/tests/ui/field_representing_types/invariant.next.stderr index c9e0b03040d85..147ecd0cb371a 100644 --- a/tests/ui/field_representing_types/invariant.next.stderr +++ b/tests/ui/field_representing_types/invariant.next.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/invariant.rs:16:5 + --> $DIR/invariant.rs:17:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here @@ -15,7 +15,7 @@ LL | consume(x, y); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/invariant.rs:16:5 + --> $DIR/invariant.rs:17:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here @@ -31,7 +31,7 @@ LL | consume(x, y); = help: see for more information about variance error: one or more lifetime errors were found in this item - --> $DIR/invariant.rs:14:4 + --> $DIR/invariant.rs:15:4 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_representing_types/invariant.old.stderr b/tests/ui/field_representing_types/invariant.old.stderr index c9e0b03040d85..147ecd0cb371a 100644 --- a/tests/ui/field_representing_types/invariant.old.stderr +++ b/tests/ui/field_representing_types/invariant.old.stderr @@ -1,5 +1,5 @@ error: lifetime may not live long enough - --> $DIR/invariant.rs:16:5 + --> $DIR/invariant.rs:17:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here @@ -15,7 +15,7 @@ LL | consume(x, y); = help: see for more information about variance error: lifetime may not live long enough - --> $DIR/invariant.rs:16:5 + --> $DIR/invariant.rs:17:5 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | -- -- lifetime `'b` defined here @@ -31,7 +31,7 @@ LL | consume(x, y); = help: see for more information about variance error: one or more lifetime errors were found in this item - --> $DIR/invariant.rs:14:4 + --> $DIR/invariant.rs:15:4 | LL | fn assert_invariant<'a, 'b>(x: field_of!(Struct<'a>, field), y: field_of!(Struct<'b>, field)) { | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_representing_types/invariant.rs b/tests/ui/field_representing_types/invariant.rs index b9b42b2f29105..98ff311da3e49 100644 --- a/tests/ui/field_representing_types/invariant.rs +++ b/tests/ui/field_representing_types/invariant.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/non-struct.next.stderr b/tests/ui/field_representing_types/non-struct.next.stderr index f1ed0e392eafa..f831fc6c41a9a 100644 --- a/tests/ui/field_representing_types/non-struct.next.stderr +++ b/tests/ui/field_representing_types/non-struct.next.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `field_of!(MyUnion, field): Field` is not satisfied - --> $DIR/non-struct.rs:22:20 + --> $DIR/non-struct.rs:23:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyUnion, field)` | note: required by a bound in `assert_field` - --> $DIR/non-struct.rs:18:20 + --> $DIR/non-struct.rs:19:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` error[E0277]: the trait bound `field_of!(MyEnum, A.a): Field` is not satisfied - --> $DIR/non-struct.rs:25:20 + --> $DIR/non-struct.rs:26:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyEnum, A.a)` | note: required by a bound in `assert_field` - --> $DIR/non-struct.rs:18:20 + --> $DIR/non-struct.rs:19:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/non-struct.old.stderr b/tests/ui/field_representing_types/non-struct.old.stderr index f1ed0e392eafa..f831fc6c41a9a 100644 --- a/tests/ui/field_representing_types/non-struct.old.stderr +++ b/tests/ui/field_representing_types/non-struct.old.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `field_of!(MyUnion, field): Field` is not satisfied - --> $DIR/non-struct.rs:22:20 + --> $DIR/non-struct.rs:23:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyUnion, field)` | note: required by a bound in `assert_field` - --> $DIR/non-struct.rs:18:20 + --> $DIR/non-struct.rs:19:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` error[E0277]: the trait bound `field_of!(MyEnum, A.a): Field` is not satisfied - --> $DIR/non-struct.rs:25:20 + --> $DIR/non-struct.rs:26:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyEnum, A.a)` | note: required by a bound in `assert_field` - --> $DIR/non-struct.rs:18:20 + --> $DIR/non-struct.rs:19:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/non-struct.rs b/tests/ui/field_representing_types/non-struct.rs index e5787c3744bdb..2fa3a8125968b 100644 --- a/tests/ui/field_representing_types/non-struct.rs +++ b/tests/ui/field_representing_types/non-struct.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/nonexistent.next.stderr b/tests/ui/field_representing_types/nonexistent.next.stderr index 9f18a667680cd..7fa9defa77517 100644 --- a/tests/ui/field_representing_types/nonexistent.next.stderr +++ b/tests/ui/field_representing_types/nonexistent.next.stderr @@ -1,5 +1,5 @@ error[E0573]: cannot find type `main` in this scope - --> $DIR/nonexistent.rs:43:22 + --> $DIR/nonexistent.rs:44:22 | LL | let _: field_of!(main, field); | ^^^^ not found in this scope @@ -7,115 +7,115 @@ LL | let _: field_of!(main, field); = note: a function named `main` exists in another namespace error[E0609]: no field `other` on type `Struct` - --> $DIR/nonexistent.rs:23:30 + --> $DIR/nonexistent.rs:24:30 | LL | let _: field_of!(Struct, other); | ^^^^^ error[E0609]: no field `0` on type `Struct` - --> $DIR/nonexistent.rs:24:30 + --> $DIR/nonexistent.rs:25:30 | LL | let _: field_of!(Struct, 0); | ^ error[E0609]: no field `other` on type `Union` - --> $DIR/nonexistent.rs:25:29 + --> $DIR/nonexistent.rs:26:29 | LL | let _: field_of!(Union, other); | ^^^^^ error[E0609]: no field `0` on type `Union` - --> $DIR/nonexistent.rs:26:29 + --> $DIR/nonexistent.rs:27:29 | LL | let _: field_of!(Union, 0); | ^ error[E0609]: no field `other` on type `Enum` - --> $DIR/nonexistent.rs:28:36 + --> $DIR/nonexistent.rs:29:36 | LL | let _: field_of!(Enum, Variant.other); | ^^^^^ error[E0609]: no field `0` on type `Enum` - --> $DIR/nonexistent.rs:29:36 + --> $DIR/nonexistent.rs:30:36 | LL | let _: field_of!(Enum, Variant.0); | ^ error[E0599]: no variant named `OtherVariant` found for enum `Enum` - --> $DIR/nonexistent.rs:31:28 + --> $DIR/nonexistent.rs:32:28 | LL | let _: field_of!(Enum, OtherVariant.field); | ^^^^^^^^^^^^ error[E0599]: no variant named `OtherVariant` found for enum `Enum` - --> $DIR/nonexistent.rs:32:28 + --> $DIR/nonexistent.rs:33:28 | LL | let _: field_of!(Enum, OtherVariant.0); | ^^^^^^^^^^^^ error[E0609]: no field `2` on type `((), ())` - --> $DIR/nonexistent.rs:33:32 + --> $DIR/nonexistent.rs:34:32 | LL | let _: field_of!(((), ()), 2); | ^ error[E0609]: no field `field` on type `((), ())` - --> $DIR/nonexistent.rs:34:32 + --> $DIR/nonexistent.rs:35:32 | LL | let _: field_of!(((), ()), field); | ^^^^^ error: type `i32` doesn't have fields - --> $DIR/nonexistent.rs:36:22 + --> $DIR/nonexistent.rs:37:22 | LL | let _: field_of!(i32, field); | ^^^ error: type `[Struct]` doesn't have fields - --> $DIR/nonexistent.rs:37:22 + --> $DIR/nonexistent.rs:38:22 | LL | let _: field_of!([Struct], field); | ^^^^^^^^ error: type `[Struct; 42]` is not yet supported in `field_of!` - --> $DIR/nonexistent.rs:38:22 + --> $DIR/nonexistent.rs:39:22 | LL | let _: field_of!([Struct; 42], field); | ^^^^^^^^^^^^ error: type `&'static Struct` doesn't have fields - --> $DIR/nonexistent.rs:39:22 + --> $DIR/nonexistent.rs:40:22 | LL | let _: field_of!(&'static Struct, field); | ^^^^^^^^^^^^^^^ error: type `*const Struct` doesn't have fields - --> $DIR/nonexistent.rs:40:22 + --> $DIR/nonexistent.rs:41:22 | LL | let _: field_of!(*const Struct, field); | ^^^^^^^^^^^^^ error: type `fn() -> Struct` doesn't have fields - --> $DIR/nonexistent.rs:41:22 + --> $DIR/nonexistent.rs:42:22 | LL | let _: field_of!(fn() -> Struct, field); | ^^^^^^^^^^^^^^ error: type `dyn Trait` doesn't have fields - --> $DIR/nonexistent.rs:42:22 + --> $DIR/nonexistent.rs:43:22 | LL | let _: field_of!(dyn Trait, field); | ^^^^^^^^^ error: cannot use `_` in this position - --> $DIR/nonexistent.rs:44:22 + --> $DIR/nonexistent.rs:45:22 | LL | let _: field_of!(_, field); | ^ error: type `T` doesn't have fields - --> $DIR/nonexistent.rs:48:22 + --> $DIR/nonexistent.rs:49:22 | LL | let _: field_of!(T, field); | ^ diff --git a/tests/ui/field_representing_types/nonexistent.old.stderr b/tests/ui/field_representing_types/nonexistent.old.stderr index 9f18a667680cd..7fa9defa77517 100644 --- a/tests/ui/field_representing_types/nonexistent.old.stderr +++ b/tests/ui/field_representing_types/nonexistent.old.stderr @@ -1,5 +1,5 @@ error[E0573]: cannot find type `main` in this scope - --> $DIR/nonexistent.rs:43:22 + --> $DIR/nonexistent.rs:44:22 | LL | let _: field_of!(main, field); | ^^^^ not found in this scope @@ -7,115 +7,115 @@ LL | let _: field_of!(main, field); = note: a function named `main` exists in another namespace error[E0609]: no field `other` on type `Struct` - --> $DIR/nonexistent.rs:23:30 + --> $DIR/nonexistent.rs:24:30 | LL | let _: field_of!(Struct, other); | ^^^^^ error[E0609]: no field `0` on type `Struct` - --> $DIR/nonexistent.rs:24:30 + --> $DIR/nonexistent.rs:25:30 | LL | let _: field_of!(Struct, 0); | ^ error[E0609]: no field `other` on type `Union` - --> $DIR/nonexistent.rs:25:29 + --> $DIR/nonexistent.rs:26:29 | LL | let _: field_of!(Union, other); | ^^^^^ error[E0609]: no field `0` on type `Union` - --> $DIR/nonexistent.rs:26:29 + --> $DIR/nonexistent.rs:27:29 | LL | let _: field_of!(Union, 0); | ^ error[E0609]: no field `other` on type `Enum` - --> $DIR/nonexistent.rs:28:36 + --> $DIR/nonexistent.rs:29:36 | LL | let _: field_of!(Enum, Variant.other); | ^^^^^ error[E0609]: no field `0` on type `Enum` - --> $DIR/nonexistent.rs:29:36 + --> $DIR/nonexistent.rs:30:36 | LL | let _: field_of!(Enum, Variant.0); | ^ error[E0599]: no variant named `OtherVariant` found for enum `Enum` - --> $DIR/nonexistent.rs:31:28 + --> $DIR/nonexistent.rs:32:28 | LL | let _: field_of!(Enum, OtherVariant.field); | ^^^^^^^^^^^^ error[E0599]: no variant named `OtherVariant` found for enum `Enum` - --> $DIR/nonexistent.rs:32:28 + --> $DIR/nonexistent.rs:33:28 | LL | let _: field_of!(Enum, OtherVariant.0); | ^^^^^^^^^^^^ error[E0609]: no field `2` on type `((), ())` - --> $DIR/nonexistent.rs:33:32 + --> $DIR/nonexistent.rs:34:32 | LL | let _: field_of!(((), ()), 2); | ^ error[E0609]: no field `field` on type `((), ())` - --> $DIR/nonexistent.rs:34:32 + --> $DIR/nonexistent.rs:35:32 | LL | let _: field_of!(((), ()), field); | ^^^^^ error: type `i32` doesn't have fields - --> $DIR/nonexistent.rs:36:22 + --> $DIR/nonexistent.rs:37:22 | LL | let _: field_of!(i32, field); | ^^^ error: type `[Struct]` doesn't have fields - --> $DIR/nonexistent.rs:37:22 + --> $DIR/nonexistent.rs:38:22 | LL | let _: field_of!([Struct], field); | ^^^^^^^^ error: type `[Struct; 42]` is not yet supported in `field_of!` - --> $DIR/nonexistent.rs:38:22 + --> $DIR/nonexistent.rs:39:22 | LL | let _: field_of!([Struct; 42], field); | ^^^^^^^^^^^^ error: type `&'static Struct` doesn't have fields - --> $DIR/nonexistent.rs:39:22 + --> $DIR/nonexistent.rs:40:22 | LL | let _: field_of!(&'static Struct, field); | ^^^^^^^^^^^^^^^ error: type `*const Struct` doesn't have fields - --> $DIR/nonexistent.rs:40:22 + --> $DIR/nonexistent.rs:41:22 | LL | let _: field_of!(*const Struct, field); | ^^^^^^^^^^^^^ error: type `fn() -> Struct` doesn't have fields - --> $DIR/nonexistent.rs:41:22 + --> $DIR/nonexistent.rs:42:22 | LL | let _: field_of!(fn() -> Struct, field); | ^^^^^^^^^^^^^^ error: type `dyn Trait` doesn't have fields - --> $DIR/nonexistent.rs:42:22 + --> $DIR/nonexistent.rs:43:22 | LL | let _: field_of!(dyn Trait, field); | ^^^^^^^^^ error: cannot use `_` in this position - --> $DIR/nonexistent.rs:44:22 + --> $DIR/nonexistent.rs:45:22 | LL | let _: field_of!(_, field); | ^ error: type `T` doesn't have fields - --> $DIR/nonexistent.rs:48:22 + --> $DIR/nonexistent.rs:49:22 | LL | let _: field_of!(T, field); | ^ diff --git a/tests/ui/field_representing_types/nonexistent.rs b/tests/ui/field_representing_types/nonexistent.rs index 252e2fb85c941..c5b49faf733ea 100644 --- a/tests/ui/field_representing_types/nonexistent.rs +++ b/tests/ui/field_representing_types/nonexistent.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/not-field-if-packed.next.stderr b/tests/ui/field_representing_types/not-field-if-packed.next.stderr index 3944316baa8ea..aa12552474c82 100644 --- a/tests/ui/field_representing_types/not-field-if-packed.next.stderr +++ b/tests/ui/field_representing_types/not-field-if-packed.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied - --> $DIR/not-field-if-packed.rs:15:20 + --> $DIR/not-field-if-packed.rs:16:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` | note: required by a bound in `assert_field` - --> $DIR/not-field-if-packed.rs:11:20 + --> $DIR/not-field-if-packed.rs:12:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/not-field-if-packed.old.stderr b/tests/ui/field_representing_types/not-field-if-packed.old.stderr index 3944316baa8ea..aa12552474c82 100644 --- a/tests/ui/field_representing_types/not-field-if-packed.old.stderr +++ b/tests/ui/field_representing_types/not-field-if-packed.old.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied - --> $DIR/not-field-if-packed.rs:15:20 + --> $DIR/not-field-if-packed.rs:16:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` | note: required by a bound in `assert_field` - --> $DIR/not-field-if-packed.rs:11:20 + --> $DIR/not-field-if-packed.rs:12:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/not-field-if-packed.rs b/tests/ui/field_representing_types/not-field-if-packed.rs index 06524b17628d5..a1b6e41cd74c2 100644 --- a/tests/ui/field_representing_types/not-field-if-packed.rs +++ b/tests/ui/field_representing_types/not-field-if-packed.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr index e639d01dc176a..9a2cc84b6ac51 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.next.stderr +++ b/tests/ui/field_representing_types/not-field-if-unsized.next.stderr @@ -1,39 +1,39 @@ error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/not-field-if-unsized.rs:17:20 + --> $DIR/not-field-if-unsized.rs:18:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `field_of!(MyStruct, 0)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required because it appears within the type `MyStruct` - --> $DIR/not-field-if-unsized.rs:10:28 + --> $DIR/not-field-if-unsized.rs:11:28 | LL | pub struct MyStruct(usize, dyn Trait); | ^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyStruct, 0)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` - --> $DIR/not-field-if-unsized.rs:12:20 + --> $DIR/not-field-if-unsized.rs:13:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` error[E0277]: the size for values of type `(dyn Trait + 'static)` cannot be known at compilation time - --> $DIR/not-field-if-unsized.rs:21:20 + --> $DIR/not-field-if-unsized.rs:22:20 | LL | assert_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `field_of!(MyStruct, 1)`, the trait `Sized` is not implemented for `(dyn Trait + 'static)` note: required because it appears within the type `MyStruct` - --> $DIR/not-field-if-unsized.rs:10:28 + --> $DIR/not-field-if-unsized.rs:11:28 | LL | pub struct MyStruct(usize, dyn Trait); | ^^^^^^^^^ required by this field note: required because it appears within the type `field_of!(MyStruct, 1)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `assert_field` - --> $DIR/not-field-if-unsized.rs:12:20 + --> $DIR/not-field-if-unsized.rs:13:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/not-field-if-unsized.old.stderr b/tests/ui/field_representing_types/not-field-if-unsized.old.stderr index 693f1353253bd..41b27584d0cda 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.old.stderr +++ b/tests/ui/field_representing_types/not-field-if-unsized.old.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `field_of!(MyStruct, 0): Field` is not satisfied - --> $DIR/not-field-if-unsized.rs:17:20 + --> $DIR/not-field-if-unsized.rs:18:20 | LL | ..._field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 0)` | note: required by a bound in `assert_field` - --> $DIR/not-field-if-unsized.rs:12:20 + --> $DIR/not-field-if-unsized.rs:13:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` error[E0277]: the trait bound `field_of!(MyStruct, 1): Field` is not satisfied - --> $DIR/not-field-if-unsized.rs:21:20 + --> $DIR/not-field-if-unsized.rs:22:20 | LL | ..._field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyStruct, 1)` | note: required by a bound in `assert_field` - --> $DIR/not-field-if-unsized.rs:12:20 + --> $DIR/not-field-if-unsized.rs:13:20 | LL | fn assert_field() {} | ^^^^^ required by this bound in `assert_field` diff --git a/tests/ui/field_representing_types/not-field-if-unsized.rs b/tests/ui/field_representing_types/not-field-if-unsized.rs index 82a3c385cb799..4675fd98a42fb 100644 --- a/tests/ui/field_representing_types/not-field-if-unsized.rs +++ b/tests/ui/field_representing_types/not-field-if-unsized.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/offset.rs b/tests/ui/field_representing_types/offset.rs index 8c769de884d29..1275cc9f00270 100644 --- a/tests/ui/field_representing_types/offset.rs +++ b/tests/ui/field_representing_types/offset.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ run-pass #![expect(incomplete_features)] diff --git a/tests/ui/field_representing_types/privacy.next.stderr b/tests/ui/field_representing_types/privacy.next.stderr index 237a2cbc55ff7..35a66d76c3d32 100644 --- a/tests/ui/field_representing_types/privacy.next.stderr +++ b/tests/ui/field_representing_types/privacy.next.stderr @@ -1,11 +1,11 @@ error[E0616]: field `a` of struct `foo::Struct` is private - --> $DIR/privacy.rs:28:30 + --> $DIR/privacy.rs:29:30 | LL | let _: field_of!(Struct, a); | ^ private field error[E0616]: field `a` of union `foo::Union` is private - --> $DIR/privacy.rs:30:29 + --> $DIR/privacy.rs:31:29 | LL | let _: field_of!(Union, a); | ^ private field diff --git a/tests/ui/field_representing_types/privacy.old.stderr b/tests/ui/field_representing_types/privacy.old.stderr index 237a2cbc55ff7..35a66d76c3d32 100644 --- a/tests/ui/field_representing_types/privacy.old.stderr +++ b/tests/ui/field_representing_types/privacy.old.stderr @@ -1,11 +1,11 @@ error[E0616]: field `a` of struct `foo::Struct` is private - --> $DIR/privacy.rs:28:30 + --> $DIR/privacy.rs:29:30 | LL | let _: field_of!(Struct, a); | ^ private field error[E0616]: field `a` of union `foo::Union` is private - --> $DIR/privacy.rs:30:29 + --> $DIR/privacy.rs:31:29 | LL | let _: field_of!(Union, a); | ^ private field diff --git a/tests/ui/field_representing_types/privacy.rs b/tests/ui/field_representing_types/privacy.rs index 7805ff6721a6e..9a036d1afa3aa 100644 --- a/tests/ui/field_representing_types/privacy.rs +++ b/tests/ui/field_representing_types/privacy.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/projections.next.stderr b/tests/ui/field_representing_types/projections.next.stderr index bf3b41cc23a54..f5a462e3a8e65 100644 --- a/tests/ui/field_representing_types/projections.next.stderr +++ b/tests/ui/field_representing_types/projections.next.stderr @@ -1,29 +1,29 @@ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:39:18 + --> $DIR/projections.rs:40:18 | LL | _: field_of!(<::Assoc as Special>::Assoc, field), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:45:19 + --> $DIR/projections.rs:46:19 | LL | _x: field_of!(<::Assoc as Special>::Assoc, field), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `::Assoc` - --> $DIR/projections.rs:24:22 + --> $DIR/projections.rs:25:22 | LL | let _: field_of!(::Assoc, field); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:51:22 + --> $DIR/projections.rs:52:22 | LL | let _: field_of!(<::Assoc as Special>::Assoc, field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:56:22 + --> $DIR/projections.rs:57:22 | LL | let _: field_of!(<::Assoc as Special>::Assoc, other); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_representing_types/projections.old.stderr b/tests/ui/field_representing_types/projections.old.stderr index bf3b41cc23a54..f5a462e3a8e65 100644 --- a/tests/ui/field_representing_types/projections.old.stderr +++ b/tests/ui/field_representing_types/projections.old.stderr @@ -1,29 +1,29 @@ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:39:18 + --> $DIR/projections.rs:40:18 | LL | _: field_of!(<::Assoc as Special>::Assoc, field), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:45:19 + --> $DIR/projections.rs:46:19 | LL | _x: field_of!(<::Assoc as Special>::Assoc, field), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `::Assoc` - --> $DIR/projections.rs:24:22 + --> $DIR/projections.rs:25:22 | LL | let _: field_of!(::Assoc, field); | ^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:51:22 + --> $DIR/projections.rs:52:22 | LL | let _: field_of!(<::Assoc as Special>::Assoc, field); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: could not resolve fields of `<::Assoc as Special>::Assoc` - --> $DIR/projections.rs:56:22 + --> $DIR/projections.rs:57:22 | LL | let _: field_of!(<::Assoc as Special>::Assoc, other); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/field_representing_types/projections.rs b/tests/ui/field_representing_types/projections.rs index 625f22e25e991..011e0df23571d 100644 --- a/tests/ui/field_representing_types/projections.rs +++ b/tests/ui/field_representing_types/projections.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![feature(field_projections, freeze)] #![expect(incomplete_features, dead_code)] diff --git a/tests/ui/field_representing_types/sized.next.stderr b/tests/ui/field_representing_types/sized.next.stderr index 254603f09b960..30f1b8e73be32 100644 --- a/tests/ui/field_representing_types/sized.next.stderr +++ b/tests/ui/field_representing_types/sized.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/sized.rs:20:19 + --> $DIR/sized.rs:21:19 | LL | fn generic() { | - this type parameter needs to be `Sized` @@ -7,7 +7,7 @@ LL | impls_field::, count)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `Generic` - --> $DIR/sized.rs:16:5 + --> $DIR/sized.rs:17:5 | LL | pub struct Generic { LL | count: usize, @@ -16,7 +16,7 @@ LL | last: T, note: required because it appears within the type `field_of!(Generic, count)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` @@ -27,7 +27,7 @@ LL + fn generic() { | error[E0277]: the size for values of type `T` cannot be known at compilation time - --> $DIR/sized.rs:22:19 + --> $DIR/sized.rs:23:19 | LL | fn generic() { | - this type parameter needs to be `Sized` @@ -36,7 +36,7 @@ LL | impls_field::, last)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | note: required because it appears within the type `Generic` - --> $DIR/sized.rs:16:5 + --> $DIR/sized.rs:17:5 | LL | pub struct Generic { LL | count: usize, @@ -45,7 +45,7 @@ LL | last: T, note: required because it appears within the type `field_of!(Generic, last)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` @@ -56,14 +56,14 @@ LL + fn generic() { | error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time - --> $DIR/sized.rs:32:19 + --> $DIR/sized.rs:33:19 | LL | impls_field::(); | ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `field_of!(MyDST, count)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` note: required because it appears within the type `MyDST` - --> $DIR/sized.rs:11:5 + --> $DIR/sized.rs:12:5 | LL | pub struct MyDST { LL | count: usize, @@ -72,20 +72,20 @@ LL | last: dyn Debug, note: required because it appears within the type `field_of!(MyDST, count)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` error[E0277]: the size for values of type `(dyn Debug + 'static)` cannot be known at compilation time - --> $DIR/sized.rs:34:19 + --> $DIR/sized.rs:35:19 | LL | impls_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time | = help: within `field_of!(MyDST, last)`, the trait `Sized` is not implemented for `(dyn Debug + 'static)` note: required because it appears within the type `MyDST` - --> $DIR/sized.rs:11:5 + --> $DIR/sized.rs:12:5 | LL | pub struct MyDST { LL | count: usize, @@ -94,7 +94,7 @@ LL | last: dyn Debug, note: required because it appears within the type `field_of!(MyDST, last)` --> $SRC_DIR/core/src/field.rs:LL:COL note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` diff --git a/tests/ui/field_representing_types/sized.old.stderr b/tests/ui/field_representing_types/sized.old.stderr index f86bf6ddd53ee..2f624e33952d1 100644 --- a/tests/ui/field_representing_types/sized.old.stderr +++ b/tests/ui/field_representing_types/sized.old.stderr @@ -1,47 +1,47 @@ error[E0277]: the trait bound `field_of!(Generic, count): Field` is not satisfied - --> $DIR/sized.rs:20:19 + --> $DIR/sized.rs:21:19 | LL | ...::, count)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, count)` | note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` error[E0277]: the trait bound `field_of!(Generic, last): Field` is not satisfied - --> $DIR/sized.rs:22:19 + --> $DIR/sized.rs:23:19 | LL | ...d::, last)>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(Generic, last)` | note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` error[E0277]: the trait bound `field_of!(MyDST, count): Field` is not satisfied - --> $DIR/sized.rs:32:19 + --> $DIR/sized.rs:33:19 | LL | ...field::(); | ^^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, count)` | note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` error[E0277]: the trait bound `field_of!(MyDST, last): Field` is not satisfied - --> $DIR/sized.rs:34:19 + --> $DIR/sized.rs:35:19 | LL | impls_field::(); | ^^^^^^^^^^^^^^^^^^^^^^ the nightly-only, unstable trait `Field` is not implemented for `field_of!(MyDST, last)` | note: required by a bound in `impls_field` - --> $DIR/sized.rs:38:19 + --> $DIR/sized.rs:39:19 | LL | fn impls_field() {} | ^^^^^ required by this bound in `impls_field` diff --git a/tests/ui/field_representing_types/sized.rs b/tests/ui/field_representing_types/sized.rs index 658dd5f24a131..866526b8d65f0 100644 --- a/tests/ui/field_representing_types/sized.rs +++ b/tests/ui/field_representing_types/sized.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/field_representing_types/traits.rs b/tests/ui/field_representing_types/traits.rs index bc31376e60ea2..266643188508d 100644 --- a/tests/ui/field_representing_types/traits.rs +++ b/tests/ui/field_representing_types/traits.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ run-pass #![feature(field_projections, freeze, unsafe_unpin)] diff --git a/tests/ui/field_representing_types/weird-impls.next.stderr b/tests/ui/field_representing_types/weird-impls.next.stderr index 71c6d5d296347..5e3382f3ad53b 100644 --- a/tests/ui/field_representing_types/weird-impls.next.stderr +++ b/tests/ui/field_representing_types/weird-impls.next.stderr @@ -1,23 +1,23 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions - --> $DIR/weird-impls.rs:10:15 + --> $DIR/weird-impls.rs:11:15 | LL | impl Drop for field_of!(MyStruct, 0) { | ^^^^^^^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type defined in the current crate - --> $DIR/weird-impls.rs:15:1 + --> $DIR/weird-impls.rs:16:1 | LL | unsafe impl Send for field_of!(MyStruct, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate error[E0322]: explicit impls for the `Field` trait are not permitted - --> $DIR/weird-impls.rs:21:1 + --> $DIR/weird-impls.rs:22:1 | LL | unsafe impl Field for field_of!(MyStruct2, 0) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Field` not allowed error[E0322]: explicit impls for the `Field` trait are not permitted - --> $DIR/weird-impls.rs:30:1 + --> $DIR/weird-impls.rs:31:1 | LL | unsafe impl Field for MyField { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Field` not allowed diff --git a/tests/ui/field_representing_types/weird-impls.old.stderr b/tests/ui/field_representing_types/weird-impls.old.stderr index 71c6d5d296347..5e3382f3ad53b 100644 --- a/tests/ui/field_representing_types/weird-impls.old.stderr +++ b/tests/ui/field_representing_types/weird-impls.old.stderr @@ -1,23 +1,23 @@ error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions - --> $DIR/weird-impls.rs:10:15 + --> $DIR/weird-impls.rs:11:15 | LL | impl Drop for field_of!(MyStruct, 0) { | ^^^^^^^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate error[E0321]: cross-crate traits with a default impl, like `Send`, can only be implemented for a struct/enum type defined in the current crate - --> $DIR/weird-impls.rs:15:1 + --> $DIR/weird-impls.rs:16:1 | LL | unsafe impl Send for field_of!(MyStruct, 0) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can't implement cross-crate trait for type in another crate error[E0322]: explicit impls for the `Field` trait are not permitted - --> $DIR/weird-impls.rs:21:1 + --> $DIR/weird-impls.rs:22:1 | LL | unsafe impl Field for field_of!(MyStruct2, 0) { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Field` not allowed error[E0322]: explicit impls for the `Field` trait are not permitted - --> $DIR/weird-impls.rs:30:1 + --> $DIR/weird-impls.rs:31:1 | LL | unsafe impl Field for MyField { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ impl of `Field` not allowed diff --git a/tests/ui/field_representing_types/weird-impls.rs b/tests/ui/field_representing_types/weird-impls.rs index d61c0c7a6a056..764ef50a251a0 100644 --- a/tests/ui/field_representing_types/weird-impls.rs +++ b/tests/ui/field_representing_types/weird-impls.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![expect(incomplete_features)] #![feature(field_projections)] diff --git a/tests/ui/float/f32-into-f32.next-solver.fixed b/tests/ui/float/f32-into-f32.next-solver.fixed index 6bc04ff757eef..2b6153135940c 100644 --- a/tests/ui/float/f32-into-f32.next-solver.fixed +++ b/tests/ui/float/f32-into-f32.next-solver.fixed @@ -1,4 +1,5 @@ //@ revisions: old-solver next-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next-solver] compile-flags: -Znext-solver //@ run-pass //@ run-rustfix diff --git a/tests/ui/float/f32-into-f32.next-solver.stderr b/tests/ui/float/f32-into-f32.next-solver.stderr index 1384f73f09689..b1f227511cfc6 100644 --- a/tests/ui/float/f32-into-f32.next-solver.stderr +++ b/tests/ui/float/f32-into-f32.next-solver.stderr @@ -1,5 +1,5 @@ warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:9:9 + --> $DIR/f32-into-f32.rs:10:9 | LL | foo(1.0); | ^^^ help: explicitly specify the type as `f32`: `1.0_f32` @@ -9,7 +9,7 @@ LL | foo(1.0); = note: `#[warn(float_literal_f32_fallback)]` (part of `#[warn(future_incompatible)]`) on by default warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:12:11 + --> $DIR/f32-into-f32.rs:13:11 | LL | foo(-(2.5)); | ^^^ help: explicitly specify the type as `f32`: `2.5_f32` @@ -18,7 +18,7 @@ LL | foo(-(2.5)); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:15:9 + --> $DIR/f32-into-f32.rs:16:9 | LL | foo(1e5); | ^^^ help: explicitly specify the type as `f32`: `1e5_f32` @@ -27,7 +27,7 @@ LL | foo(1e5); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:18:9 + --> $DIR/f32-into-f32.rs:19:9 | LL | foo(0.); | ^^ help: explicitly specify the type as `f32`: `0_f32` @@ -36,7 +36,7 @@ LL | foo(0.); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:22:14 + --> $DIR/f32-into-f32.rs:23:14 | LL | let x = -4.0; | ^^^ help: explicitly specify the type as `f32`: `4.0_f32` diff --git a/tests/ui/float/f32-into-f32.old-solver.fixed b/tests/ui/float/f32-into-f32.old-solver.fixed index 6bc04ff757eef..2b6153135940c 100644 --- a/tests/ui/float/f32-into-f32.old-solver.fixed +++ b/tests/ui/float/f32-into-f32.old-solver.fixed @@ -1,4 +1,5 @@ //@ revisions: old-solver next-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next-solver] compile-flags: -Znext-solver //@ run-pass //@ run-rustfix diff --git a/tests/ui/float/f32-into-f32.old-solver.stderr b/tests/ui/float/f32-into-f32.old-solver.stderr index 1384f73f09689..b1f227511cfc6 100644 --- a/tests/ui/float/f32-into-f32.old-solver.stderr +++ b/tests/ui/float/f32-into-f32.old-solver.stderr @@ -1,5 +1,5 @@ warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:9:9 + --> $DIR/f32-into-f32.rs:10:9 | LL | foo(1.0); | ^^^ help: explicitly specify the type as `f32`: `1.0_f32` @@ -9,7 +9,7 @@ LL | foo(1.0); = note: `#[warn(float_literal_f32_fallback)]` (part of `#[warn(future_incompatible)]`) on by default warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:12:11 + --> $DIR/f32-into-f32.rs:13:11 | LL | foo(-(2.5)); | ^^^ help: explicitly specify the type as `f32`: `2.5_f32` @@ -18,7 +18,7 @@ LL | foo(-(2.5)); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:15:9 + --> $DIR/f32-into-f32.rs:16:9 | LL | foo(1e5); | ^^^ help: explicitly specify the type as `f32`: `1e5_f32` @@ -27,7 +27,7 @@ LL | foo(1e5); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:18:9 + --> $DIR/f32-into-f32.rs:19:9 | LL | foo(0.); | ^^ help: explicitly specify the type as `f32`: `0_f32` @@ -36,7 +36,7 @@ LL | foo(0.); = note: for more information, see issue #154024 warning: falling back to `f32` as the trait bound `f32: From` is not satisfied - --> $DIR/f32-into-f32.rs:22:14 + --> $DIR/f32-into-f32.rs:23:14 | LL | let x = -4.0; | ^^^ help: explicitly specify the type as `f32`: `4.0_f32` diff --git a/tests/ui/float/f32-into-f32.rs b/tests/ui/float/f32-into-f32.rs index 3dbdd20bd3098..1c40088906e1c 100644 --- a/tests/ui/float/f32-into-f32.rs +++ b/tests/ui/float/f32-into-f32.rs @@ -1,4 +1,5 @@ //@ revisions: old-solver next-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next-solver] compile-flags: -Znext-solver //@ run-pass //@ run-rustfix diff --git a/tests/ui/generic-associated-types/rigid-hr-projection-issue-93340.rs b/tests/ui/generic-associated-types/rigid-hr-projection-issue-93340.rs index b55ca845cd3f2..f0ac923b494b3 100644 --- a/tests/ui/generic-associated-types/rigid-hr-projection-issue-93340.rs +++ b/tests/ui/generic-associated-types/rigid-hr-projection-issue-93340.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs index c177ee6fb3a66..4950957f42fec 100644 --- a/tests/ui/higher-ranked/builtin-closure-like-bounds.rs +++ b/tests/ui/higher-ranked/builtin-closure-like-bounds.rs @@ -1,5 +1,6 @@ //@ edition:2024 //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/higher-ranked/closure-bound-codegen-ice.rs b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs index 4d7ae12d7a742..0dc839637d24d 100644 --- a/tests/ui/higher-ranked/closure-bound-codegen-ice.rs +++ b/tests/ui/higher-ranked/closure-bound-codegen-ice.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ build-pass diff --git a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr index bf3e6943f0d5a..bd73cf9f48046 100644 --- a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr +++ b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.next.stderr @@ -1,18 +1,18 @@ error[E0283]: type annotations needed - --> $DIR/constraint-from-nested-projection.rs:31:5 + --> $DIR/constraint-from-nested-projection.rs:32:5 | LL | pick::<(), _>(); | ^^^^^^^^^^^^^ cannot infer type of the type parameter `U` declared on the function `pick` | note: multiple `impl`s satisfying `(): Pick<_>` found - --> $DIR/constraint-from-nested-projection.rs:25:1 + --> $DIR/constraint-from-nested-projection.rs:26:1 | LL | impl RequiresProject<'a>> Pick for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl Pick for T {} | ^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `pick` - --> $DIR/constraint-from-nested-projection.rs:28:12 + --> $DIR/constraint-from-nested-projection.rs:29:12 | LL | fn pick, U>() {} | ^^^^^^^ required by this bound in `pick` diff --git a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs index fda0fa7efa57c..dd7ea263bce04 100644 --- a/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs +++ b/tests/ui/higher-ranked/leak-check/constraint-from-nested-projection.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[old] check-pass diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs index 46a0dccb441ef..487860468eaae 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-1.rs @@ -1,5 +1,6 @@ //@ run-pass //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![allow(coherence_leak_check)] diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs index 8d87bdd064a06..aad2ee21b9514 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-4-hr-nested.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs index 9a44fd2e64a3e..612b87b392c40 100644 --- a/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs +++ b/tests/ui/higher-ranked/leak-check/leak-check-in-selection-5-ambig.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/higher-ranked/trait-bounds/issue-100689.rs b/tests/ui/higher-ranked/trait-bounds/issue-100689.rs index 6bfad56b93d29..8dfb8d2aaca91 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-100689.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-100689.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver struct Foo<'a> { diff --git a/tests/ui/higher-ranked/trait-bounds/issue-102899.rs b/tests/ui/higher-ranked/trait-bounds/issue-102899.rs index 77d4d0179b1ba..d726dbf6b0d73 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-102899.rs +++ b/tests/ui/higher-ranked/trait-bounds/issue-102899.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver pub trait BufferTrait<'buffer> { diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr index dd8375c8b9409..cd1f2aa14acee 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed for `>::Out<_>` - --> $DIR/norm-before-method-resolution-opaque-type.rs:25:9 + --> $DIR/norm-before-method-resolution-opaque-type.rs:26:9 | LL | let x = *x; | ^ diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr index d8b94fd4f7d1b..cc4087c028e08 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr @@ -1,5 +1,5 @@ error[E0507]: cannot move out of `*x` which is behind a shared reference - --> $DIR/norm-before-method-resolution-opaque-type.rs:25:13 + --> $DIR/norm-before-method-resolution-opaque-type.rs:26:13 | LL | let x = *x; | ^^ move occurs because `*x` has type `>::Out`, which does not implement the `Copy` trait diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs index 55e99171ea633..9735683c4c774 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // In the next solver, the opaque was previously defined by using the where-bound when checking diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr index d52cd6833c342..4f08d635cabdc 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:19:16 + --> $DIR/auto-trait-selection-freeze.rs:20:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr index b6c6e74f26052..3baff54885b6e 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection-freeze.rs:19:16 + --> $DIR/auto-trait-selection-freeze.rs:20:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ ----- type must be known at this point @@ -7,14 +7,14 @@ LL | if false { is_trait(foo()) } else { Default::default() } | cannot infer type of the type parameter `U` declared on the function `is_trait` | note: multiple `impl`s satisfying `impl Sized: Trait<_>` found - --> $DIR/auto-trait-selection-freeze.rs:16:1 + --> $DIR/auto-trait-selection-freeze.rs:17:1 | LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection-freeze.rs:11:16 + --> $DIR/auto-trait-selection-freeze.rs:12:16 | LL | fn is_trait, U: Default>(_: T) -> U { | ^^^^^^^^ required by this bound in `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection-freeze.rs b/tests/ui/impl-trait/auto-trait-selection-freeze.rs index 7306a1c41f746..16cafbc2bc545 100644 --- a/tests/ui/impl-trait/auto-trait-selection-freeze.rs +++ b/tests/ui/impl-trait/auto-trait-selection-freeze.rs @@ -2,6 +2,7 @@ //! selection in a code path that succeeds. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(freeze)] diff --git a/tests/ui/impl-trait/auto-trait-selection.next.stderr b/tests/ui/impl-trait/auto-trait-selection.next.stderr index ec65bdc48a089..dbad5680781ec 100644 --- a/tests/ui/impl-trait/auto-trait-selection.next.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/auto-trait-selection.rs:15:16 + --> $DIR/auto-trait-selection.rs:16:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ cannot infer type of the type parameter `T` declared on the function `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection.old.stderr b/tests/ui/impl-trait/auto-trait-selection.old.stderr index 8e44100177154..a660ee7a5d892 100644 --- a/tests/ui/impl-trait/auto-trait-selection.old.stderr +++ b/tests/ui/impl-trait/auto-trait-selection.old.stderr @@ -1,5 +1,5 @@ error[E0283]: type annotations needed - --> $DIR/auto-trait-selection.rs:15:16 + --> $DIR/auto-trait-selection.rs:16:16 | LL | if false { is_trait(foo()) } else { Default::default() } | ^^^^^^^^ ----- type must be known at this point @@ -7,14 +7,14 @@ LL | if false { is_trait(foo()) } else { Default::default() } | cannot infer type of the type parameter `U` declared on the function `is_trait` | note: multiple `impl`s satisfying `impl Sized: Trait<_>` found - --> $DIR/auto-trait-selection.rs:12:1 + --> $DIR/auto-trait-selection.rs:13:1 | LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ LL | impl Trait for T {} | ^^^^^^^^^^^^^^^^^^^^^^^^ note: required by a bound in `is_trait` - --> $DIR/auto-trait-selection.rs:7:16 + --> $DIR/auto-trait-selection.rs:8:16 | LL | fn is_trait, U: Default>(_: T) -> U { | ^^^^^^^^ required by this bound in `is_trait` diff --git a/tests/ui/impl-trait/auto-trait-selection.rs b/tests/ui/impl-trait/auto-trait-selection.rs index ee5612459c257..c921d31f7f622 100644 --- a/tests/ui/impl-trait/auto-trait-selection.rs +++ b/tests/ui/impl-trait/auto-trait-selection.rs @@ -2,6 +2,7 @@ //! selection in a code path that succeeds. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver fn is_trait, U: Default>(_: T) -> U { diff --git a/tests/ui/impl-trait/call_method_ambiguous.rs b/tests/ui/impl-trait/call_method_ambiguous.rs index 021d6c22f79dd..f49c993f8e4cd 100644 --- a/tests/ui/impl-trait/call_method_ambiguous.rs +++ b/tests/ui/impl-trait/call_method_ambiguous.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ run-pass diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl.rs b/tests/ui/impl-trait/call_method_on_inherent_impl.rs index 1dd38bc671730..60426fb956408 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr index 6fdf47fba73e0..3822bb5c9729e 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.current.stderr @@ -1,12 +1,12 @@ error[E0599]: no method named `my_debug` found for reference `&impl Debug` in the current scope - --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11 + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:17:11 | LL | x.my_debug(); | ^^^^^^^^ method not found in `&impl Debug` | = help: items from traits can only be used if the trait is implemented and in scope note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it - --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:5:1 + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:6:1 | LL | trait MyDebug { | ^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr index 8e8a307917265..4ff8117bcc12c 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `my_debug` found for reference `&_` in the current scope - --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:16:11 + --> $DIR/call_method_on_inherent_impl_on_rigid_type.rs:17:11 | LL | x.my_debug(); | ^^^^^^^^ method not found in `&_` diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs index 4f09bd15dcd5f..847cb6e678dff 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ edition: 2015 diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.current.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.current.stderr index 71acbd1497d93..f77c44118966b 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.current.stderr +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.current.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `my_debug` found for opaque type `impl Debug` in the current scope - --> $DIR/call_method_on_inherent_impl_ref-err.rs:18:11 + --> $DIR/call_method_on_inherent_impl_ref-err.rs:19:11 | LL | fn my_debug(&self); | -------- the method is available for `&impl Debug` here @@ -9,7 +9,7 @@ LL | x.my_debug(); | = help: items from traits can only be used if the trait is implemented and in scope note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it - --> $DIR/call_method_on_inherent_impl_ref-err.rs:4:1 + --> $DIR/call_method_on_inherent_impl_ref-err.rs:5:1 | LL | trait MyDebug { | ^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.next.stderr index 523505e980221..71c588cd3a62f 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.next.stderr +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.next.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `my_debug` found for type `_` in the current scope - --> $DIR/call_method_on_inherent_impl_ref-err.rs:18:11 + --> $DIR/call_method_on_inherent_impl_ref-err.rs:19:11 | LL | fn my_debug(&self); | -------- the method is available for `&_` here @@ -9,7 +9,7 @@ LL | x.my_debug(); | = help: items from traits can only be used if the trait is implemented and in scope note: `MyDebug` defines an item `my_debug`, perhaps you need to implement it - --> $DIR/call_method_on_inherent_impl_ref-err.rs:4:1 + --> $DIR/call_method_on_inherent_impl_ref-err.rs:5:1 | LL | trait MyDebug { | ^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.rs index 0ed09bc76a41e..46c281d10e765 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-err.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver trait MyDebug { diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-ok.rs b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-ok.rs index 40739d6a0ce4b..073f5916754d7 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_ref-ok.rs +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_ref-ok.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.old.stderr b/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.old.stderr index 23ee36358e63b..1a6e455ce9dd8 100644 --- a/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.old.stderr +++ b/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.old.stderr @@ -2,7 +2,7 @@ error[E0275]: overflow evaluating the requirement `fn() -> impl MyFnOnce {my_fn_ | = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`failed_to_resolve_instance_ice_105488`) note: required for `WrapFnOnce impl MyFnOnce {my_fn_1}>` to implement `MyFnOnce` - --> $DIR/failed-to-resolve-instance-ice-105488.rs:18:37 + --> $DIR/failed-to-resolve-instance-ice-105488.rs:19:37 | LL | impl D, D: MyFnOnce> MyFnOnce for WrapFnOnce { | -------- ^^^^^^^^ ^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.rs b/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.rs index b2e134176a37a..72ac1be91c8ac 100644 --- a/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.rs +++ b/tests/ui/impl-trait/failed-to-resolve-instance-ice-105488.rs @@ -1,11 +1,12 @@ //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ build-fail // ICE failed to resolve instance for impl MyFnOnce ... // issue: rust-lang/rust#105488 -//[old]~^^^^^^ ERROR overflow evaluating the requirement `fn() -> impl MyFnOnce -//[next]~^^^^^^^ ERROR: overflow evaluating the requirement ` impl MyFnOnce {my_fn_2} as MyFnOnce>::Output == _` [E0275] +//[old]~^^^^^^^ ERROR overflow evaluating the requirement `fn() -> impl MyFnOnce +//[next]~^^^^^^^^ ERROR: overflow evaluating the requirement ` impl MyFnOnce {my_fn_2} as MyFnOnce>::Output == _` [E0275] pub trait MyFnOnce { type Output; diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr b/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr index dca0a7b0a1a9f..2f41e63accafe 100644 --- a/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr +++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:10:17 + --> $DIR/hidden-type-is-opaque-2.rs:11:17 | LL | Thunk::new(|mut cont| { | ^^^^^^^^ @@ -13,7 +13,7 @@ LL | Thunk::new(|mut cont: /* Type */| { | ++++++++++++ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:21:17 + --> $DIR/hidden-type-is-opaque-2.rs:22:17 | LL | Thunk::new(|mut cont| { | ^^^^^^^^ diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr b/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr index dca0a7b0a1a9f..2f41e63accafe 100644 --- a/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr +++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:10:17 + --> $DIR/hidden-type-is-opaque-2.rs:11:17 | LL | Thunk::new(|mut cont| { | ^^^^^^^^ @@ -13,7 +13,7 @@ LL | Thunk::new(|mut cont: /* Type */| { | ++++++++++++ error[E0282]: type annotations needed - --> $DIR/hidden-type-is-opaque-2.rs:21:17 + --> $DIR/hidden-type-is-opaque-2.rs:22:17 | LL | Thunk::new(|mut cont| { | ^^^^^^^^ diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.rs b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs index 7725a04c35847..110ae28a12b09 100644 --- a/tests/ui/impl-trait/hidden-type-is-opaque-2.rs +++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs @@ -2,6 +2,7 @@ // into function arguments via the function's generic parameters // FIXME(oli-obk): make `expected_inputs_for_expected_output` support this //@ revisions: default next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] diff --git a/tests/ui/impl-trait/method/broken-deref-chain.current.stderr b/tests/ui/impl-trait/method/broken-deref-chain.current.stderr index 726f076b183bd..742352d40fad6 100644 --- a/tests/ui/impl-trait/method/broken-deref-chain.current.stderr +++ b/tests/ui/impl-trait/method/broken-deref-chain.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/broken-deref-chain.rs:41:30 + --> $DIR/broken-deref-chain.rs:42:30 | LL | fn trait_method() -> impl Trait { | ---------- the found opaque type diff --git a/tests/ui/impl-trait/method/broken-deref-chain.rs b/tests/ui/impl-trait/method/broken-deref-chain.rs index 8b45e044f4332..7ca98f5bbfb5f 100644 --- a/tests/ui/impl-trait/method/broken-deref-chain.rs +++ b/tests/ui/impl-trait/method/broken-deref-chain.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[next] check-pass diff --git a/tests/ui/impl-trait/method/method-resolution.rs b/tests/ui/impl-trait/method/method-resolution.rs index 60fbacd86462b..96ab58d2e1cb2 100644 --- a/tests/ui/impl-trait/method/method-resolution.rs +++ b/tests/ui/impl-trait/method/method-resolution.rs @@ -2,6 +2,7 @@ //! constrain `foo`'s RPIT to `u32`. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/method/method-resolution2.next.stderr b/tests/ui/impl-trait/method/method-resolution2.next.stderr index 223430e1658b4..3ca95a836e435 100644 --- a/tests/ui/impl-trait/method/method-resolution2.next.stderr +++ b/tests/ui/impl-trait/method/method-resolution2.next.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/method-resolution2.rs:25:11 + --> $DIR/method-resolution2.rs:26:11 | LL | x.bar(); | ^^^ multiple `bar` found | note: candidate #1 is defined in an impl for the type `Bar` - --> $DIR/method-resolution2.rs:19:5 + --> $DIR/method-resolution2.rs:20:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `Bar` - --> $DIR/method-resolution2.rs:15:5 + --> $DIR/method-resolution2.rs:16:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/method/method-resolution2.rs b/tests/ui/impl-trait/method/method-resolution2.rs index 88d4f3d9896c7..15aada8237a7b 100644 --- a/tests/ui/impl-trait/method/method-resolution2.rs +++ b/tests/ui/impl-trait/method/method-resolution2.rs @@ -2,6 +2,7 @@ //! `i32` is the only type that satisfies the RPIT's trait bounds. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[current] check-pass diff --git a/tests/ui/impl-trait/method/method-resolution3.current.stderr b/tests/ui/impl-trait/method/method-resolution3.current.stderr index 87dd862ef8f4f..5a51252011890 100644 --- a/tests/ui/impl-trait/method/method-resolution3.current.stderr +++ b/tests/ui/impl-trait/method/method-resolution3.current.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/method-resolution3.rs:21:11 + --> $DIR/method-resolution3.rs:22:11 | LL | x.bar(); | ^^^ multiple `bar` found | note: candidate #1 is defined in an impl for the type `Bar` - --> $DIR/method-resolution3.rs:15:5 + --> $DIR/method-resolution3.rs:16:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `Bar` - --> $DIR/method-resolution3.rs:11:5 + --> $DIR/method-resolution3.rs:12:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/method/method-resolution3.next.stderr b/tests/ui/impl-trait/method/method-resolution3.next.stderr index 87dd862ef8f4f..5a51252011890 100644 --- a/tests/ui/impl-trait/method/method-resolution3.next.stderr +++ b/tests/ui/impl-trait/method/method-resolution3.next.stderr @@ -1,16 +1,16 @@ error[E0034]: multiple applicable items in scope - --> $DIR/method-resolution3.rs:21:11 + --> $DIR/method-resolution3.rs:22:11 | LL | x.bar(); | ^^^ multiple `bar` found | note: candidate #1 is defined in an impl for the type `Bar` - --> $DIR/method-resolution3.rs:15:5 + --> $DIR/method-resolution3.rs:16:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ note: candidate #2 is defined in an impl for the type `Bar` - --> $DIR/method-resolution3.rs:11:5 + --> $DIR/method-resolution3.rs:12:5 | LL | fn bar(self) {} | ^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/method/method-resolution3.rs b/tests/ui/impl-trait/method/method-resolution3.rs index 8c47ef4fc75c7..7e2713cd01243 100644 --- a/tests/ui/impl-trait/method/method-resolution3.rs +++ b/tests/ui/impl-trait/method/method-resolution3.rs @@ -3,6 +3,7 @@ //! out with ambiguity. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver struct Bar(T); diff --git a/tests/ui/impl-trait/method/method-resolution4.rs b/tests/ui/impl-trait/method/method-resolution4.rs index f90a9309cdab8..7815977242b24 100644 --- a/tests/ui/impl-trait/method/method-resolution4.rs +++ b/tests/ui/impl-trait/method/method-resolution4.rs @@ -5,6 +5,7 @@ //! `std::iter::Empty`. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.current.stderr b/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.current.stderr index 08578de426ade..3257f28428cc3 100644 --- a/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.current.stderr +++ b/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/method-resolution5-deref-no-constrain.rs:20:5 + --> $DIR/method-resolution5-deref-no-constrain.rs:21:5 | LL | fn via_deref() -> impl Deref { | --- expected `&Foo` because of return type diff --git a/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.rs b/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.rs index 2c41f62b9fda5..c93ce5c652a7b 100644 --- a/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.rs +++ b/tests/ui/impl-trait/method/method-resolution5-deref-no-constrain.rs @@ -3,6 +3,7 @@ //! the opaque to `&Foo`. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[next] check-pass diff --git a/tests/ui/impl-trait/method/method-resolution5-deref.rs b/tests/ui/impl-trait/method/method-resolution5-deref.rs index 6133a8efe244d..76e0556f6b4e0 100644 --- a/tests/ui/impl-trait/method/method-resolution5-deref.rs +++ b/tests/ui/impl-trait/method/method-resolution5-deref.rs @@ -3,6 +3,7 @@ //! applying it for the `impl Deref`. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr b/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr index 44597b7313c52..e29297ceea024 100644 --- a/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr +++ b/tests/ui/impl-trait/method/would-constrain-opaque.current.stderr @@ -1,25 +1,25 @@ error[E0599]: no method named `method` found for reference `&impl Sized` in the current scope - --> $DIR/would-constrain-opaque.rs:29:11 + --> $DIR/would-constrain-opaque.rs:30:11 | LL | x.method(); | ^^^^^^ method not found in `&impl Sized` | = help: items from traits can only be used if the trait is implemented and in scope note: `Trait` defines an item `method`, perhaps you need to implement it - --> $DIR/would-constrain-opaque.rs:16:1 + --> $DIR/would-constrain-opaque.rs:17:1 | LL | trait Trait: Sized { | ^^^^^^^^^^^^^^^^^^ error[E0599]: no method named `method` found for reference `&impl Sized` in the current scope - --> $DIR/would-constrain-opaque.rs:31:11 + --> $DIR/would-constrain-opaque.rs:32:11 | LL | x.method(); | ^^^^^^ method not found in `&impl Sized` | = help: items from traits can only be used if the trait is implemented and in scope note: `Trait` defines an item `method`, perhaps you need to implement it - --> $DIR/would-constrain-opaque.rs:16:1 + --> $DIR/would-constrain-opaque.rs:17:1 | LL | trait Trait: Sized { | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr index 3af5833639280..c20b4f2268071 100644 --- a/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr +++ b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `method` found for reference `&_` in the current scope - --> $DIR/would-constrain-opaque.rs:29:11 + --> $DIR/would-constrain-opaque.rs:30:11 | LL | x.method(); | ^^^^^^ method not found in `&_` @@ -11,7 +11,7 @@ LL + use crate::Trait; | error[E0599]: no method named `method` found for reference `&_` in the current scope - --> $DIR/would-constrain-opaque.rs:31:11 + --> $DIR/would-constrain-opaque.rs:32:11 | LL | x.method(); | ^^^^^^ method not found in `&_` diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.rs b/tests/ui/impl-trait/method/would-constrain-opaque.rs index 380dbf3648aa1..1c7489ad08acd 100644 --- a/tests/ui/impl-trait/method/would-constrain-opaque.rs +++ b/tests/ui/impl-trait/method/would-constrain-opaque.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ edition: 2015 diff --git a/tests/ui/impl-trait/recursive-bound-eval.rs b/tests/ui/impl-trait/recursive-bound-eval.rs index 058b12e5651e3..d844fc07b042a 100644 --- a/tests/ui/impl-trait/recursive-bound-eval.rs +++ b/tests/ui/impl-trait/recursive-bound-eval.rs @@ -2,6 +2,7 @@ //! an RPIT. //@ revisions: next current +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/rpit/const_check_false_cycle.rs b/tests/ui/impl-trait/rpit/const_check_false_cycle.rs index d4ea0e3b14785..cad665e9618c7 100644 --- a/tests/ui/impl-trait/rpit/const_check_false_cycle.rs +++ b/tests/ui/impl-trait/rpit/const_check_false_cycle.rs @@ -3,6 +3,7 @@ //! the information is readily available. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs b/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs index 195e11754226d..a040f51abd3a9 100644 --- a/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs +++ b/tests/ui/impl-trait/rpit/dyn-in-nested-rpit.rs @@ -1,6 +1,7 @@ //! Regression test for . //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/rpit/precise-capture-155151.current.stderr b/tests/ui/impl-trait/rpit/precise-capture-155151.current.stderr index 39efb77067e77..97adb366ba76a 100644 --- a/tests/ui/impl-trait/rpit/precise-capture-155151.current.stderr +++ b/tests/ui/impl-trait/rpit/precise-capture-155151.current.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/precise-capture-155151.rs:19:22 + --> $DIR/precise-capture-155151.rs:20:22 | LL | let Foo { x } = foo; | - binding declared here but left uninitialized diff --git a/tests/ui/impl-trait/rpit/precise-capture-155151.rs b/tests/ui/impl-trait/rpit/precise-capture-155151.rs index b01f1098c6c2d..1edc54d16a15d 100644 --- a/tests/ui/impl-trait/rpit/precise-capture-155151.rs +++ b/tests/ui/impl-trait/rpit/precise-capture-155151.rs @@ -1,5 +1,6 @@ #![crate_type = "rlib"] //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition: 2021 //@[current] known-bug: #155151 //@[current] check-fail diff --git a/tests/ui/impl-trait/unsized_coercion.rs b/tests/ui/impl-trait/unsized_coercion.rs index f77f2198be0ef..f19fc87bafd42 100644 --- a/tests/ui/impl-trait/unsized_coercion.rs +++ b/tests/ui/impl-trait/unsized_coercion.rs @@ -2,6 +2,7 @@ //! constraining their hidden type to a trait object. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/impl-trait/unsized_coercion2.old.stderr b/tests/ui/impl-trait/unsized_coercion2.old.stderr index a89d40f1130c1..262a977d69375 100644 --- a/tests/ui/impl-trait/unsized_coercion2.old.stderr +++ b/tests/ui/impl-trait/unsized_coercion2.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion2.rs:15:33 + --> $DIR/unsized_coercion2.rs:16:33 | LL | let y: Box = x; | ^ doesn't have a size known at compile-time diff --git a/tests/ui/impl-trait/unsized_coercion2.rs b/tests/ui/impl-trait/unsized_coercion2.rs index 7368d47dbe2c0..f953dec6e3b63 100644 --- a/tests/ui/impl-trait/unsized_coercion2.rs +++ b/tests/ui/impl-trait/unsized_coercion2.rs @@ -2,6 +2,7 @@ //! constraining their hidden type to a trait object. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[next] check-pass diff --git a/tests/ui/impl-trait/unsized_coercion3.next.stderr b/tests/ui/impl-trait/unsized_coercion3.next.stderr index d254524f5d85c..2d5323475664a 100644 --- a/tests/ui/impl-trait/unsized_coercion3.next.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.next.stderr @@ -1,23 +1,23 @@ error[E0277]: the trait bound `dyn Send: Trait` is not satisfied - --> $DIR/unsized_coercion3.rs:11:15 + --> $DIR/unsized_coercion3.rs:12:15 | LL | fn hello() -> Box { | ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `dyn Send` | help: the trait `Trait` is implemented for `u32` - --> $DIR/unsized_coercion3.rs:9:1 + --> $DIR/unsized_coercion3.rs:10:1 | LL | impl Trait for u32 {} | ^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `dyn Send: Trait` is not satisfied - --> $DIR/unsized_coercion3.rs:14:17 + --> $DIR/unsized_coercion3.rs:15:17 | LL | let x = hello(); | ^^^^^^^ the trait `Trait` is not implemented for `dyn Send` | help: the trait `Trait` is implemented for `u32` - --> $DIR/unsized_coercion3.rs:9:1 + --> $DIR/unsized_coercion3.rs:10:1 | LL | impl Trait for u32 {} | ^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/unsized_coercion3.old.stderr b/tests/ui/impl-trait/unsized_coercion3.old.stderr index 3bb9f9c209510..b8c5705c44181 100644 --- a/tests/ui/impl-trait/unsized_coercion3.old.stderr +++ b/tests/ui/impl-trait/unsized_coercion3.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion3.rs:16:32 + --> $DIR/unsized_coercion3.rs:17:32 | LL | let y: Box = x; | ^ doesn't have a size known at compile-time diff --git a/tests/ui/impl-trait/unsized_coercion3.rs b/tests/ui/impl-trait/unsized_coercion3.rs index 021d43dac6402..7b775f10cc06e 100644 --- a/tests/ui/impl-trait/unsized_coercion3.rs +++ b/tests/ui/impl-trait/unsized_coercion3.rs @@ -2,6 +2,7 @@ //! constraining their hidden type to a trait object. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver trait Trait {} diff --git a/tests/ui/impl-trait/unsized_coercion4.rs b/tests/ui/impl-trait/unsized_coercion4.rs index 1c4d5462ceeb2..6c9a525fb53aa 100644 --- a/tests/ui/impl-trait/unsized_coercion4.rs +++ b/tests/ui/impl-trait/unsized_coercion4.rs @@ -2,6 +2,7 @@ //! constraining their hidden type to a trait object. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@check-pass diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr index 72aa92ef6b9c8..ad510848035b3 100644 --- a/tests/ui/impl-trait/unsized_coercion5.old.stderr +++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time - --> $DIR/unsized_coercion5.rs:15:32 + --> $DIR/unsized_coercion5.rs:16:32 | LL | let y: Box = x as Box; | ^ doesn't have a size known at compile-time diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs index 51ae4f20671e0..bdf574695c8e8 100644 --- a/tests/ui/impl-trait/unsized_coercion5.rs +++ b/tests/ui/impl-trait/unsized_coercion5.rs @@ -2,6 +2,7 @@ //! constraining their hidden type to a trait object. //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@[next] check-pass diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed index 922c883f4f71f..fe821e8f32a8a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.fixed @@ -1,5 +1,6 @@ //@ run-rustfix //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![allow(unused_variables, dead_code)] use std::collections::{BTreeMap, HashSet}; diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr index 5de99cc6ca6ae..f13c5a147c719 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.current.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:20:39 | LL | let mut x: HashSet = v.clone(); | ------------ ^^^^^^^^^ expected `HashSet`, found `&HashSet` @@ -9,7 +9,7 @@ LL | let mut x: HashSet = v.clone(); = note: expected struct `HashSet<_>` found reference `&HashSet<_>` note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned instead - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:20:39 | LL | let mut x: HashSet = v.clone(); | ^ diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed index 922c883f4f71f..fe821e8f32a8a 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.fixed @@ -1,5 +1,6 @@ //@ run-rustfix //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![allow(unused_variables, dead_code)] use std::collections::{BTreeMap, HashSet}; diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr index 5de99cc6ca6ae..f13c5a147c719 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.next.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:20:39 | LL | let mut x: HashSet = v.clone(); | ------------ ^^^^^^^^^ expected `HashSet`, found `&HashSet` @@ -9,7 +9,7 @@ LL | let mut x: HashSet = v.clone(); = note: expected struct `HashSet<_>` found reference `&HashSet<_>` note: `HashSet` does not implement `Clone`, so `&HashSet` was cloned instead - --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:19:39 + --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:20:39 | LL | let mut x: HashSet = v.clone(); | ^ diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs index 6f7b55be8bd28..25f484caf6c8b 100644 --- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs +++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.rs @@ -1,5 +1,6 @@ //@ run-rustfix //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![allow(unused_variables, dead_code)] use std::collections::{BTreeMap, HashSet}; diff --git a/tests/ui/never_type/basic/method-on-never.current.stderr b/tests/ui/never_type/basic/method-on-never.current.stderr index ec89b37bc403e..635c8485ed334 100644 --- a/tests/ui/never_type/basic/method-on-never.current.stderr +++ b/tests/ui/never_type/basic/method-on-never.current.stderr @@ -1,5 +1,5 @@ warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:44:7 + --> $DIR/method-on-never.rs:45:7 | LL | x.method(); | ^^^^^^ @@ -10,7 +10,7 @@ LL | x.method(); = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:48:17 + --> $DIR/method-on-never.rs:49:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -20,7 +20,7 @@ LL | { loop {} }.method(); = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:53:16 + --> $DIR/method-on-never.rs:54:16 | LL | y => y.method(), | ^^^^^^ @@ -30,7 +30,7 @@ LL | y => y.method(), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:59:27 + --> $DIR/method-on-never.rs:60:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | error => (&error).anyhow_kind().new(error), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:65:9 + --> $DIR/method-on-never.rs:66:9 | LL | res.method(); | ^^^^^^ @@ -53,7 +53,7 @@ warning: 5 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:44:7 + --> $DIR/method-on-never.rs:45:7 | LL | x.method(); | ^^^^^^ @@ -65,7 +65,7 @@ LL | x.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:48:17 + --> $DIR/method-on-never.rs:49:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -77,7 +77,7 @@ LL | { loop {} }.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:53:16 + --> $DIR/method-on-never.rs:54:16 | LL | y => y.method(), | ^^^^^^ @@ -89,7 +89,7 @@ LL | y => y.method(), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:59:27 + --> $DIR/method-on-never.rs:60:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | error => (&error).anyhow_kind().new(error), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:65:9 + --> $DIR/method-on-never.rs:66:9 | LL | res.method(); | ^^^^^^ diff --git a/tests/ui/never_type/basic/method-on-never.next.stderr b/tests/ui/never_type/basic/method-on-never.next.stderr index ec89b37bc403e..635c8485ed334 100644 --- a/tests/ui/never_type/basic/method-on-never.next.stderr +++ b/tests/ui/never_type/basic/method-on-never.next.stderr @@ -1,5 +1,5 @@ warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:44:7 + --> $DIR/method-on-never.rs:45:7 | LL | x.method(); | ^^^^^^ @@ -10,7 +10,7 @@ LL | x.method(); = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:48:17 + --> $DIR/method-on-never.rs:49:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -20,7 +20,7 @@ LL | { loop {} }.method(); = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:53:16 + --> $DIR/method-on-never.rs:54:16 | LL | y => y.method(), | ^^^^^^ @@ -30,7 +30,7 @@ LL | y => y.method(), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:59:27 + --> $DIR/method-on-never.rs:60:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | error => (&error).anyhow_kind().new(error), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:65:9 + --> $DIR/method-on-never.rs:66:9 | LL | res.method(); | ^^^^^^ @@ -53,7 +53,7 @@ warning: 5 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:44:7 + --> $DIR/method-on-never.rs:45:7 | LL | x.method(); | ^^^^^^ @@ -65,7 +65,7 @@ LL | x.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:48:17 + --> $DIR/method-on-never.rs:49:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -77,7 +77,7 @@ LL | { loop {} }.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:53:16 + --> $DIR/method-on-never.rs:54:16 | LL | y => y.method(), | ^^^^^^ @@ -89,7 +89,7 @@ LL | y => y.method(), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:59:27 + --> $DIR/method-on-never.rs:60:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | error => (&error).anyhow_kind().new(error), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:65:9 + --> $DIR/method-on-never.rs:66:9 | LL | res.method(); | ^^^^^^ diff --git a/tests/ui/never_type/basic/method-on-never.rs b/tests/ui/never_type/basic/method-on-never.rs index ac928a0e9d071..cbc202a60e766 100644 --- a/tests/ui/never_type/basic/method-on-never.rs +++ b/tests/ui/never_type/basic/method-on-never.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass // Regression test for https://github.com/rust-lang/rust/issues/143349 diff --git a/tests/ui/sized-hierarchy/alias-bounds.rs b/tests/ui/sized-hierarchy/alias-bounds.rs index 87b4bab11b746..4ac7a98eacbc3 100644 --- a/tests/ui/sized-hierarchy/alias-bounds.rs +++ b/tests/ui/sized-hierarchy/alias-bounds.rs @@ -1,6 +1,7 @@ //@ check-pass //@ compile-flags: --crate-type=lib //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(sized_hierarchy)] diff --git a/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs index 4a20ed2cafb16..c6a631f0945e6 100644 --- a/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs +++ b/tests/ui/sized-hierarchy/bound-on-assoc-type-projection-1.rs @@ -1,6 +1,7 @@ //@ check-pass //@ compile-flags: --crate-type=lib //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver use std::marker::PhantomData; diff --git a/tests/ui/sized-hierarchy/elaboration-opt-regions-1.rs b/tests/ui/sized-hierarchy/elaboration-opt-regions-1.rs index d59227beae817..a0d3935022260 100644 --- a/tests/ui/sized-hierarchy/elaboration-opt-regions-1.rs +++ b/tests/ui/sized-hierarchy/elaboration-opt-regions-1.rs @@ -1,6 +1,7 @@ //@ check-pass //@ compile-flags: --crate-type=lib //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(sized_hierarchy)] diff --git a/tests/ui/sized-hierarchy/elaboration-opt-regions.rs b/tests/ui/sized-hierarchy/elaboration-opt-regions.rs index 66e600f3dc96b..3ef7dc4112aaa 100644 --- a/tests/ui/sized-hierarchy/elaboration-opt-regions.rs +++ b/tests/ui/sized-hierarchy/elaboration-opt-regions.rs @@ -1,6 +1,7 @@ //@ check-pass //@ compile-flags: --crate-type=lib //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(sized_hierarchy)] diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr index 36df6bfd9fc15..fbe76a86a0583 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.current.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:26:1 + --> $DIR/specialization-default-items-drop-coherence.rs:27:1 | LL | impl Overlap for u32 { | -------------------- first implementation here diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr index 36df6bfd9fc15..fbe76a86a0583 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.next.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `u32` - --> $DIR/specialization-default-items-drop-coherence.rs:26:1 + --> $DIR/specialization-default-items-drop-coherence.rs:27:1 | LL | impl Overlap for u32 { | -------------------- first implementation here diff --git a/tests/ui/specialization/specialization-default-items-drop-coherence.rs b/tests/ui/specialization/specialization-default-items-drop-coherence.rs index b3c1f72777c4c..45e254c6691e8 100644 --- a/tests/ui/specialization/specialization-default-items-drop-coherence.rs +++ b/tests/ui/specialization/specialization-default-items-drop-coherence.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Should fail. Default items completely drop candidates instead of ambiguity, diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs index 0bda247d5f4eb..2be95117b39b2 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-0.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr index 3976c71899e6b..5407be7fcbc88 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | ::Assoc::::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr index 3976c71899e6b..5407be7fcbc88 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:22:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:23:5 | LL | T::Assoc::::func(); | ^^^^^^^^^^^^^ error[E0277]: the trait bound `U: [const] Other` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail-2.rs:24:5 + --> $DIR/assoc-type-const-bound-usage-fail-2.rs:25:5 | LL | ::Assoc::::func(); | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs index a817fff36fa64..e44f94d823ecf 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail-2.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Check that `[const]` item bounds only hold if the where clauses on the diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr index 1f0248365ce6e..20b01d06e8d5e 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5 | LL | T::Assoc::func(); | ^^^^^^^^ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 | LL | ::Assoc::func(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr index 1f0248365ce6e..20b01d06e8d5e 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:16:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:17:5 | LL | T::Assoc::func(); | ^^^^^^^^ error[E0277]: the trait bound `T: [const] Trait` is not satisfied - --> $DIR/assoc-type-const-bound-usage-fail.rs:18:5 + --> $DIR/assoc-type-const-bound-usage-fail.rs:19:5 | LL | ::Assoc::func(); | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs index 65c3a06e89c2d..39a9bdf8041ad 100644 --- a/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs +++ b/tests/ui/traits/const-traits/assoc-type-const-bound-usage-fail.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Check that `[const]` item bounds only hold if the parent trait is `[const]`. diff --git a/tests/ui/traits/const-traits/assoc-type.current.stderr b/tests/ui/traits/const-traits/assoc-type.current.stderr index 64e2e58f71944..f53747d16752b 100644 --- a/tests/ui/traits/const-traits/assoc-type.current.stderr +++ b/tests/ui/traits/const-traits/assoc-type.current.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied - --> $DIR/assoc-type.rs:35:16 + --> $DIR/assoc-type.rs:36:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ | note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:31:15 + --> $DIR/assoc-type.rs:32:15 | LL | const trait Foo { LL | type Bar: [const] Add; diff --git a/tests/ui/traits/const-traits/assoc-type.next.stderr b/tests/ui/traits/const-traits/assoc-type.next.stderr index 64e2e58f71944..f53747d16752b 100644 --- a/tests/ui/traits/const-traits/assoc-type.next.stderr +++ b/tests/ui/traits/const-traits/assoc-type.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `NonConstAdd: [const] Add` is not satisfied - --> $DIR/assoc-type.rs:35:16 + --> $DIR/assoc-type.rs:36:16 | LL | type Bar = NonConstAdd; | ^^^^^^^^^^^ | note: required by a bound in `Foo::Bar` - --> $DIR/assoc-type.rs:31:15 + --> $DIR/assoc-type.rs:32:15 | LL | const trait Foo { LL | type Bar: [const] Add; diff --git a/tests/ui/traits/const-traits/assoc-type.rs b/tests/ui/traits/const-traits/assoc-type.rs index f01c009b86190..261512a7e698c 100644 --- a/tests/ui/traits/const-traits/assoc-type.rs +++ b/tests/ui/traits/const-traits/assoc-type.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/call-const-closure.next.stderr b/tests/ui/traits/const-traits/call-const-closure.next.stderr index bdea41585c666..7583829d9f69f 100644 --- a/tests/ui/traits/const-traits/call-const-closure.next.stderr +++ b/tests/ui/traits/const-traits/call-const-closure.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): [const] Bar` is not satisfied - --> $DIR/call-const-closure.rs:16:18 + --> $DIR/call-const-closure.rs:17:18 | LL | (const || ().foo())(); | ^^^ diff --git a/tests/ui/traits/const-traits/call-const-closure.old.stderr b/tests/ui/traits/const-traits/call-const-closure.old.stderr index bdea41585c666..7583829d9f69f 100644 --- a/tests/ui/traits/const-traits/call-const-closure.old.stderr +++ b/tests/ui/traits/const-traits/call-const-closure.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `(): [const] Bar` is not satisfied - --> $DIR/call-const-closure.rs:16:18 + --> $DIR/call-const-closure.rs:17:18 | LL | (const || ().foo())(); | ^^^ diff --git a/tests/ui/traits/const-traits/call-const-closure.rs b/tests/ui/traits/const-traits/call-const-closure.rs index 5a5369a075358..a4807dde76da8 100644 --- a/tests/ui/traits/const-traits/call-const-closure.rs +++ b/tests/ui/traits/const-traits/call-const-closure.rs @@ -1,5 +1,6 @@ //@[next] compile-flags: -Znext-solver //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition:2021 #![feature(const_trait_impl, const_closures)] diff --git a/tests/ui/traits/const-traits/call.rs b/tests/ui/traits/const-traits/call.rs index 71dea1ef4e049..c13e4f4c1defa 100644 --- a/tests/ui/traits/const-traits/call.rs +++ b/tests/ui/traits/const-traits/call.rs @@ -1,6 +1,7 @@ //@ check-pass //@[next] compile-flags: -Znext-solver //@revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) #![feature(const_closures, const_trait_impl)] const _: () = { diff --git a/tests/ui/traits/const-traits/const-closure-inherited-const-condition.rs b/tests/ui/traits/const-traits/const-closure-inherited-const-condition.rs index b1c929bf78cd9..68d87f140251d 100644 --- a/tests/ui/traits/const-traits/const-closure-inherited-const-condition.rs +++ b/tests/ui/traits/const-traits/const-closure-inherited-const-condition.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_closures, const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const-closure-trait-method.rs b/tests/ui/traits/const-traits/const-closure-trait-method.rs index 18173371222ea..729e570719e18 100644 --- a/tests/ui/traits/const-traits/const-closure-trait-method.rs +++ b/tests/ui/traits/const-traits/const-closure-trait-method.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const-closures.rs b/tests/ui/traits/const-traits/const-closures.rs index 8f1c018ca5dd4..65c08231774ea 100644 --- a/tests/ui/traits/const-traits/const-closures.rs +++ b/tests/ui/traits/const-traits/const-closures.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(const_trait_impl)] diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr index 33289d9ed3386..9d7d1a154ec78 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_precise.stderr @@ -1,17 +1,17 @@ error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` - --> $DIR/const-drop-fail.rs:19:30 + --> $DIR/const-drop-fail.rs:20:30 | LL | struct ConstImplWithDropGlue(NonTrivialDrop); | ^^^^^^^^^^^^^^ | note: required for this `Drop` impl - --> $DIR/const-drop-fail.rs:22:1 + --> $DIR/const-drop-fail.rs:23:1 | LL | const impl Drop for ConstImplWithDropGlue { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:35:5 + --> $DIR/const-drop-fail.rs:36:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -20,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:37:5 + --> $DIR/const-drop-fail.rs:38:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -35,7 +35,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr index 33289d9ed3386..9d7d1a154ec78 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.new_stock.stderr @@ -1,17 +1,17 @@ error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` - --> $DIR/const-drop-fail.rs:19:30 + --> $DIR/const-drop-fail.rs:20:30 | LL | struct ConstImplWithDropGlue(NonTrivialDrop); | ^^^^^^^^^^^^^^ | note: required for this `Drop` impl - --> $DIR/const-drop-fail.rs:22:1 + --> $DIR/const-drop-fail.rs:23:1 | LL | const impl Drop for ConstImplWithDropGlue { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:35:5 + --> $DIR/const-drop-fail.rs:36:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -20,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:37:5 + --> $DIR/const-drop-fail.rs:38:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -35,7 +35,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr index 33289d9ed3386..9d7d1a154ec78 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_precise.stderr @@ -1,17 +1,17 @@ error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` - --> $DIR/const-drop-fail.rs:19:30 + --> $DIR/const-drop-fail.rs:20:30 | LL | struct ConstImplWithDropGlue(NonTrivialDrop); | ^^^^^^^^^^^^^^ | note: required for this `Drop` impl - --> $DIR/const-drop-fail.rs:22:1 + --> $DIR/const-drop-fail.rs:23:1 | LL | const impl Drop for ConstImplWithDropGlue { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:35:5 + --> $DIR/const-drop-fail.rs:36:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -20,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:37:5 + --> $DIR/const-drop-fail.rs:38:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -35,7 +35,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr index 33289d9ed3386..9d7d1a154ec78 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr +++ b/tests/ui/traits/const-traits/const-drop-fail.old_stock.stderr @@ -1,17 +1,17 @@ error[E0367]: `NonTrivialDrop` does not implement `[const] Destruct` - --> $DIR/const-drop-fail.rs:19:30 + --> $DIR/const-drop-fail.rs:20:30 | LL | struct ConstImplWithDropGlue(NonTrivialDrop); | ^^^^^^^^^^^^^^ | note: required for this `Drop` impl - --> $DIR/const-drop-fail.rs:22:1 + --> $DIR/const-drop-fail.rs:23:1 | LL | const impl Drop for ConstImplWithDropGlue { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:35:5 + --> $DIR/const-drop-fail.rs:36:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -20,13 +20,13 @@ LL | NonTrivialDrop, | ^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` error[E0277]: the trait bound `NonTrivialDrop: const Destruct` is not satisfied - --> $DIR/const-drop-fail.rs:37:5 + --> $DIR/const-drop-fail.rs:38:5 | LL | const _: () = check($exp); | ----- required by a bound introduced by this call @@ -35,7 +35,7 @@ LL | ConstImplWithDropGlue(NonTrivialDrop), | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: required by a bound in `check` - --> $DIR/const-drop-fail.rs:26:19 + --> $DIR/const-drop-fail.rs:27:19 | LL | const fn check(_: T) {} | ^^^^^^^^^^^^^^^^ required by this bound in `check` diff --git a/tests/ui/traits/const-traits/const-drop-fail.rs b/tests/ui/traits/const-traits/const-drop-fail.rs index d85c942bbe6a7..5a3894ed4dfe2 100644 --- a/tests/ui/traits/const-traits/const-drop-fail.rs +++ b/tests/ui/traits/const-traits/const-drop-fail.rs @@ -1,6 +1,7 @@ //@[new_precise] compile-flags: -Znext-solver //@[new_stock] compile-flags: -Znext-solver //@ revisions: new_stock old_stock new_precise old_precise +//@ ignore-compare-mode-next-solver (explicit revisions) //@ ignore-backends: gcc #![feature(const_trait_impl, const_destruct)] diff --git a/tests/ui/traits/const-traits/drop-manually-drop-no-drop-impl.rs b/tests/ui/traits/const-traits/drop-manually-drop-no-drop-impl.rs index 060a543d6c3db..b55c2e7edb9ef 100644 --- a/tests/ui/traits/const-traits/drop-manually-drop-no-drop-impl.rs +++ b/tests/ui/traits/const-traits/drop-manually-drop-no-drop-impl.rs @@ -1,5 +1,6 @@ //@[new] compile-flags: -Znext-solver //@ revisions: old new +//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass use std::mem::ManuallyDrop; diff --git a/tests/ui/traits/const-traits/drop-manually-drop.rs b/tests/ui/traits/const-traits/drop-manually-drop.rs index 23f17701f586e..9e018e961876a 100644 --- a/tests/ui/traits/const-traits/drop-manually-drop.rs +++ b/tests/ui/traits/const-traits/drop-manually-drop.rs @@ -1,5 +1,6 @@ //@[new] compile-flags: -Znext-solver //@ revisions: old new +//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass #![feature(const_destruct)] diff --git a/tests/ui/traits/default_auto_traits/extern-types.current.stderr b/tests/ui/traits/default_auto_traits/extern-types.current.stderr index 593204382e3a1..15b62f1212e11 100644 --- a/tests/ui/traits/default_auto_traits/extern-types.current.stderr +++ b/tests/ui/traits/default_auto_traits/extern-types.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied - --> $DIR/extern-types.rs:50:13 + --> $DIR/extern-types.rs:51:13 | LL | foo(x); | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` @@ -7,7 +7,7 @@ LL | foo(x); | required by a bound introduced by this call | note: required by a bound in `foo` - --> $DIR/extern-types.rs:26:8 + --> $DIR/extern-types.rs:27:8 | LL | fn foo(_: &T) {} | ^ required by this bound in `foo` diff --git a/tests/ui/traits/default_auto_traits/extern-types.next.stderr b/tests/ui/traits/default_auto_traits/extern-types.next.stderr index 593204382e3a1..15b62f1212e11 100644 --- a/tests/ui/traits/default_auto_traits/extern-types.next.stderr +++ b/tests/ui/traits/default_auto_traits/extern-types.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `extern_non_leak::Opaque: Leak` is not satisfied - --> $DIR/extern-types.rs:50:13 + --> $DIR/extern-types.rs:51:13 | LL | foo(x); | --- ^ the trait `Leak` is not implemented for `extern_non_leak::Opaque` @@ -7,7 +7,7 @@ LL | foo(x); | required by a bound introduced by this call | note: required by a bound in `foo` - --> $DIR/extern-types.rs:26:8 + --> $DIR/extern-types.rs:27:8 | LL | fn foo(_: &T) {} | ^ required by this bound in `foo` diff --git a/tests/ui/traits/default_auto_traits/extern-types.rs b/tests/ui/traits/default_auto_traits/extern-types.rs index df106d83171c9..57d3ec65750f5 100644 --- a/tests/ui/traits/default_auto_traits/extern-types.rs +++ b/tests/ui/traits/default_auto_traits/extern-types.rs @@ -1,5 +1,6 @@ //@ compile-flags: -Zexperimental-default-bounds //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver #![feature(auto_traits, extern_types, lang_items, negative_impls, no_core, rustc_attrs)] diff --git a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.current.stderr b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.current.stderr index 4766e426cd331..4e038e4bd7085 100644 --- a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.current.stderr +++ b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `[A]: ToOwned` is not satisfied - --> $DIR/cow-slice-missing-clone-issue-141241.rs:16:11 + --> $DIR/cow-slice-missing-clone-issue-141241.rs:17:11 | LL | test: Cow<'static, [A]>, | ^^^^^^^^^^^^^^^^^ the trait `ToOwned` is not implemented for `[A]` diff --git a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.next.stderr b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.next.stderr index 0d5b9bc94ca27..63d5935ece818 100644 --- a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.next.stderr +++ b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `[A]: ToOwned` is not satisfied - --> $DIR/cow-slice-missing-clone-issue-141241.rs:16:11 + --> $DIR/cow-slice-missing-clone-issue-141241.rs:17:11 | LL | test: Cow<'static, [A]>, | ^^^^^^^^^^^^^^^^^ the trait `ToOwned` is not implemented for `[A]` diff --git a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.rs b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.rs index f1eccd0ce13d7..6fce37f5072a9 100644 --- a/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.rs +++ b/tests/ui/traits/error-reporting/cow-slice-missing-clone-issue-141241.rs @@ -1,4 +1,5 @@ //@ revisions: current next with_clone +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ [with_clone] check-pass diff --git a/tests/ui/traits/generic-cow-inference-regression.rs b/tests/ui/traits/generic-cow-inference-regression.rs index e9dd76d1aea4f..936f5b7d760a2 100644 --- a/tests/ui/traits/generic-cow-inference-regression.rs +++ b/tests/ui/traits/generic-cow-inference-regression.rs @@ -1,5 +1,6 @@ //@[new] compile-flags: -Znext-solver //@ revisions: old new +//@ ignore-compare-mode-next-solver (explicit revisions) //@ run-pass // regression test for #147964: diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs index 247cc78979a91..0084737b008d5 100644 --- a/tests/ui/traits/issue-90662-projection-caching.rs +++ b/tests/ui/traits/issue-90662-projection-caching.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver=coherence //@ check-pass diff --git a/tests/ui/traits/next-solver/adt-const-param-projection.rs b/tests/ui/traits/next-solver/adt-const-param-projection.rs index 926451bae2c3d..8f440b99f4a86 100644 --- a/tests/ui/traits/next-solver/adt-const-param-projection.rs +++ b/tests/ui/traits/next-solver/adt-const-param-projection.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ build-pass //@ compile-flags: --crate-type=lib diff --git a/tests/ui/traits/next-solver/alias-bound-preference.rs b/tests/ui/traits/next-solver/alias-bound-preference.rs index 99008bddf4ffb..305a4735399d0 100644 --- a/tests/ui/traits/next-solver/alias-bound-preference.rs +++ b/tests/ui/traits/next-solver/alias-bound-preference.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ run-pass diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr index 20bbcdd8af423..8650f7fcf1087 100644 --- a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `Option: Overlap` - --> $DIR/ambiguous-impl-in-resolve.rs:17:6 + --> $DIR/ambiguous-impl-in-resolve.rs:18:6 | LL | as Overlap>::f(); | ^^^^^^^^^ | note: multiple `impl`s satisfying `Option: Overlap` found - --> $DIR/ambiguous-impl-in-resolve.rs:10:1 + --> $DIR/ambiguous-impl-in-resolve.rs:11:1 | LL | impl Overlap for Option where Self: Clone, { fn f() {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr index 20bbcdd8af423..8650f7fcf1087 100644 --- a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr @@ -1,11 +1,11 @@ error[E0283]: type annotations needed: cannot satisfy `Option: Overlap` - --> $DIR/ambiguous-impl-in-resolve.rs:17:6 + --> $DIR/ambiguous-impl-in-resolve.rs:18:6 | LL | as Overlap>::f(); | ^^^^^^^^^ | note: multiple `impl`s satisfying `Option: Overlap` found - --> $DIR/ambiguous-impl-in-resolve.rs:10:1 + --> $DIR/ambiguous-impl-in-resolve.rs:11:1 | LL | impl Overlap for Option where Self: Clone, { fn f() {} } | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs index fd90d11575b07..1ee432a9ab1e8 100644 --- a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Impossible where-clauses can cause multiple overlapping impls to apply diff --git a/tests/ui/traits/next-solver/closure-signature-inference-hr-ambig-alias-naming-self.rs b/tests/ui/traits/next-solver/closure-signature-inference-hr-ambig-alias-naming-self.rs index 25649d9290326..3c0962085fe6b 100644 --- a/tests/ui/traits/next-solver/closure-signature-inference-hr-ambig-alias-naming-self.rs +++ b/tests/ui/traits/next-solver/closure-signature-inference-hr-ambig-alias-naming-self.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // When type checking a closure expr we look at the list of unsolved goals diff --git a/tests/ui/traits/next-solver/generalize/alias-with-bound-vars-incomplete-generalization.rs b/tests/ui/traits/next-solver/generalize/alias-with-bound-vars-incomplete-generalization.rs index bf2276e4967b0..2070a3b730e03 100644 --- a/tests/ui/traits/next-solver/generalize/alias-with-bound-vars-incomplete-generalization.rs +++ b/tests/ui/traits/next-solver/generalize/alias-with-bound-vars-incomplete-generalization.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs b/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs index 0c3fb9fcbea3c..ae34fe8fa44e2 100644 --- a/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs +++ b/tests/ui/traits/next-solver/normalize/dont-mark-const-aliases-as-rigid-in-param-env.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.next.stderr b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.next.stderr index 52aa7cbcab583..2faa658195765 100644 --- a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.next.stderr +++ b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.next.stderr @@ -1,5 +1,5 @@ error: size: Size(1 bytes) - --> $DIR/dump-layout-opaque-coroutine.rs:19:1 + --> $DIR/dump-layout-opaque-coroutine.rs:20:1 | LL | type Foo = impl Sized; | ^^^^^^^^ diff --git a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.old.stderr b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.old.stderr index 52aa7cbcab583..2faa658195765 100644 --- a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.old.stderr +++ b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.old.stderr @@ -1,5 +1,5 @@ error: size: Size(1 bytes) - --> $DIR/dump-layout-opaque-coroutine.rs:19:1 + --> $DIR/dump-layout-opaque-coroutine.rs:20:1 | LL | type Foo = impl Sized; | ^^^^^^^^ diff --git a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.rs b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.rs index cb95c2f67475e..04bce2d14e25b 100644 --- a/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.rs +++ b/tests/ui/traits/next-solver/opaques/dump-layout-opaque-coroutine.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ edition: 2024 diff --git a/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.next.stderr b/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.next.stderr index 335cee2dc40cb..64dfcbf180199 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.next.stderr +++ b/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.next.stderr @@ -1,5 +1,5 @@ warning: overflow evaluating the requirement `Foo>>>>>: Sync` - --> $DIR/fcw-on-auto-trait.rs:22:5 + --> $DIR/fcw-on-auto-trait.rs:23:5 | LL | require_sync::>>>>>>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.rs b/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.rs index 73c0a5c153893..450b680214868 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.rs +++ b/tests/ui/traits/next-solver/overflow/fcw-on-auto-trait.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/overflow/fcw-on-normalization.next.stderr b/tests/ui/traits/next-solver/overflow/fcw-on-normalization.next.stderr index b0f923ca887b8..13b47888560cc 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-on-normalization.next.stderr +++ b/tests/ui/traits/next-solver/overflow/fcw-on-normalization.next.stderr @@ -1,5 +1,5 @@ warning: overflow evaluating the requirement `>>>>>>>>> as HasAssoc>::Assoc == ()` - --> $DIR/fcw-on-normalization.rs:40:12 + --> $DIR/fcw-on-normalization.rs:41:12 | LL | let b: >>>>>>>>> as HasAssoc>::Assoc = loop {}; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/overflow/fcw-on-normalization.rs b/tests/ui/traits/next-solver/overflow/fcw-on-normalization.rs index c8fa0366f2944..c9659b24b3120 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-on-normalization.rs +++ b/tests/ui/traits/next-solver/overflow/fcw-on-normalization.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.next.stderr b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.next.stderr index 1aa69678bdfbf..14151fbf4fcfc 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.next.stderr +++ b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.next.stderr @@ -1,5 +1,5 @@ warning: overflow evaluating the requirement `u32: Constrain>>>, W, _>>, _>>` - --> $DIR/fcw-overflow-to-ambig-with-constraints.rs:29:5 + --> $DIR/fcw-overflow-to-ambig-with-constraints.rs:30:5 | LL | fun_times(); | ^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.rs b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.rs index d8606225f246f..4d071a2832b29 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.rs +++ b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-ambig-with-constraints.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.next.stderr b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.next.stderr index bc5097d29ec4a..0632f7dc474b8 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.next.stderr +++ b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.next.stderr @@ -1,5 +1,5 @@ warning: overflow evaluating the requirement `W>>>>: Overflow` - --> $DIR/fcw-overflow-to-error.rs:34:23 + --> $DIR/fcw-overflow-to-error.rs:35:23 | LL | W(W(W(W(W(()))))).foo(); | ^^^ diff --git a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.rs b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.rs index 3dbb9090fe72b..1d8be2cf7a0d8 100644 --- a/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.rs +++ b/tests/ui/traits/next-solver/overflow/fcw-overflow-to-error.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/overflow/nalgebra-hang.rs b/tests/ui/traits/next-solver/overflow/nalgebra-hang.rs index 4bc6039c57dfd..7c9212a36f77f 100644 --- a/tests/ui/traits/next-solver/overflow/nalgebra-hang.rs +++ b/tests/ui/traits/next-solver/overflow/nalgebra-hang.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Regression test for nalgebra hang from diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr b/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr index 8028c4d5415f3..80e87f23c6721 100644 --- a/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Indir: Trait1` is not satisfied - --> $DIR/param-env-normalization-fallback.rs:21:1 + --> $DIR/param-env-normalization-fallback.rs:22:1 | LL | / impl Trait2 for T LL | | @@ -10,29 +10,29 @@ LL | | T: Trait1::Assoc1>, | |__________________________________________________^ unsatisfied trait bound | help: the trait `Trait1` is not implemented for `Indir` - --> $DIR/param-env-normalization-fallback.rs:15:1 + --> $DIR/param-env-normalization-fallback.rs:16:1 | LL | struct Indir; | ^^^^^^^^^^^^ help: this trait has no implementations, consider adding one - --> $DIR/param-env-normalization-fallback.rs:11:1 + --> $DIR/param-env-normalization-fallback.rs:12:1 | LL | trait Trait1 { | ^^^^^^^^^^^^ error[E0277]: the trait bound `Indir: Trait1` is not satisfied - --> $DIR/param-env-normalization-fallback.rs:28:5 + --> $DIR/param-env-normalization-fallback.rs:29:5 | LL | type Assoc2 = (); | ^^^^^^^^^^^ unsatisfied trait bound | help: the trait `Trait1` is not implemented for `Indir` - --> $DIR/param-env-normalization-fallback.rs:15:1 + --> $DIR/param-env-normalization-fallback.rs:16:1 | LL | struct Indir; | ^^^^^^^^^^^^ help: this trait has no implementations, consider adding one - --> $DIR/param-env-normalization-fallback.rs:11:1 + --> $DIR/param-env-normalization-fallback.rs:12:1 | LL | trait Trait1 { | ^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr b/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr index 8028c4d5415f3..80e87f23c6721 100644 --- a/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.old.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `Indir: Trait1` is not satisfied - --> $DIR/param-env-normalization-fallback.rs:21:1 + --> $DIR/param-env-normalization-fallback.rs:22:1 | LL | / impl Trait2 for T LL | | @@ -10,29 +10,29 @@ LL | | T: Trait1::Assoc1>, | |__________________________________________________^ unsatisfied trait bound | help: the trait `Trait1` is not implemented for `Indir` - --> $DIR/param-env-normalization-fallback.rs:15:1 + --> $DIR/param-env-normalization-fallback.rs:16:1 | LL | struct Indir; | ^^^^^^^^^^^^ help: this trait has no implementations, consider adding one - --> $DIR/param-env-normalization-fallback.rs:11:1 + --> $DIR/param-env-normalization-fallback.rs:12:1 | LL | trait Trait1 { | ^^^^^^^^^^^^ error[E0277]: the trait bound `Indir: Trait1` is not satisfied - --> $DIR/param-env-normalization-fallback.rs:28:5 + --> $DIR/param-env-normalization-fallback.rs:29:5 | LL | type Assoc2 = (); | ^^^^^^^^^^^ unsatisfied trait bound | help: the trait `Trait1` is not implemented for `Indir` - --> $DIR/param-env-normalization-fallback.rs:15:1 + --> $DIR/param-env-normalization-fallback.rs:16:1 | LL | struct Indir; | ^^^^^^^^^^^^ help: this trait has no implementations, consider adding one - --> $DIR/param-env-normalization-fallback.rs:11:1 + --> $DIR/param-env-normalization-fallback.rs:12:1 | LL | trait Trait1 { | ^^^^^^^^^^^^ diff --git a/tests/ui/traits/next-solver/param-env-normalization-fallback.rs b/tests/ui/traits/next-solver/param-env-normalization-fallback.rs index aa24df4984ae6..2fd5d30f1966e 100644 --- a/tests/ui/traits/next-solver/param-env-normalization-fallback.rs +++ b/tests/ui/traits/next-solver/param-env-normalization-fallback.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver // Previously the fallback of param env normalization was elaborated param env diff --git a/tests/ui/traits/next-solver/self-referential-closure-sig-1.rs b/tests/ui/traits/next-solver/self-referential-closure-sig-1.rs index ad401602a3267..6451651ef1ec7 100644 --- a/tests/ui/traits/next-solver/self-referential-closure-sig-1.rs +++ b/tests/ui/traits/next-solver/self-referential-closure-sig-1.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/next-solver/self-referential-closure-sig-3.rs b/tests/ui/traits/next-solver/self-referential-closure-sig-3.rs index bbbbc5c3e50cb..352c44bb168cd 100644 --- a/tests/ui/traits/next-solver/self-referential-closure-sig-3.rs +++ b/tests/ui/traits/next-solver/self-referential-closure-sig-3.rs @@ -1,4 +1,5 @@ //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr index 5366c04cb537b..8ae10c22aa5ca 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.current.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.current.stderr @@ -1,58 +1,58 @@ error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:41:20 + --> $DIR/non-send-field-location-issue-146016.rs:42:20 | LL | require_send::>(); | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:26:5 + --> $DIR/non-send-field-location-issue-146016.rs:27:5 | LL | struct Record { LL | unrelated: u8, LL | value: T, | ^^^^^^^^ required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:43:20 + --> $DIR/non-send-field-location-issue-146016.rs:44:20 | LL | require_send::>(); | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:26:5 + --> $DIR/non-send-field-location-issue-146016.rs:27:5 | LL | struct Record { LL | unrelated: u8, LL | value: T, | ^^^^^^^^ required by this field note: required because it appears within the type `Nested<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:30:5 + --> $DIR/non-send-field-location-issue-146016.rs:31:5 | LL | struct Nested { LL | value: Record, | ^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:45:20 + --> $DIR/non-send-field-location-issue-146016.rs:46:20 | LL | require_send::>(); | ^^^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Multiple<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:35:14 + --> $DIR/non-send-field-location-issue-146016.rs:36:14 | LL | enum Multiple { LL | Empty, @@ -61,13 +61,13 @@ LL | Values { first: T, second: T }, | | | required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:55:27 + --> $DIR/non-send-field-location-issue-146016.rs:56:27 | LL | let h = thread::spawn(move || match rx.recv().unwrap() { | _____________-------------_^ @@ -81,7 +81,7 @@ LL | | }); | = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Foo` - --> $DIR/non-send-field-location-issue-146016.rs:21:11 + --> $DIR/non-send-field-location-issue-146016.rs:22:11 | LL | enum Foo { LL | Case(i32), @@ -89,7 +89,7 @@ LL | Case2(Bar), | ^^^ required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure - --> $DIR/non-send-field-location-issue-146016.rs:55:41 + --> $DIR/non-send-field-location-issue-146016.rs:56:41 | LL | let h = thread::spawn(move || match rx.recv().unwrap() { | ^^ diff --git a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr index 5366c04cb537b..8ae10c22aa5ca 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.next.stderr +++ b/tests/ui/traits/non-send-field-location-issue-146016.next.stderr @@ -1,58 +1,58 @@ error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:41:20 + --> $DIR/non-send-field-location-issue-146016.rs:42:20 | LL | require_send::>(); | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Record<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:26:5 + --> $DIR/non-send-field-location-issue-146016.rs:27:5 | LL | struct Record { LL | unrelated: u8, LL | value: T, | ^^^^^^^^ required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:43:20 + --> $DIR/non-send-field-location-issue-146016.rs:44:20 | LL | require_send::>(); | ^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Nested<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Record<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:26:5 + --> $DIR/non-send-field-location-issue-146016.rs:27:5 | LL | struct Record { LL | unrelated: u8, LL | value: T, | ^^^^^^^^ required by this field note: required because it appears within the type `Nested<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:30:5 + --> $DIR/non-send-field-location-issue-146016.rs:31:5 | LL | struct Nested { LL | value: Record, | ^^^^^^^^^^^^^^^^ required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:45:20 + --> $DIR/non-send-field-location-issue-146016.rs:46:20 | LL | require_send::>(); | ^^^^^^^^^^^^^ `*const c_void` cannot be sent between threads safely | = help: within `Multiple<*const c_void>`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Multiple<*const c_void>` - --> $DIR/non-send-field-location-issue-146016.rs:35:14 + --> $DIR/non-send-field-location-issue-146016.rs:36:14 | LL | enum Multiple { LL | Empty, @@ -61,13 +61,13 @@ LL | Values { first: T, second: T }, | | | required by this field note: required by a bound in `require_send` - --> $DIR/non-send-field-location-issue-146016.rs:38:20 + --> $DIR/non-send-field-location-issue-146016.rs:39:20 | LL | fn require_send() {} | ^^^^ required by this bound in `require_send` error[E0277]: `*const c_void` cannot be sent between threads safely - --> $DIR/non-send-field-location-issue-146016.rs:55:27 + --> $DIR/non-send-field-location-issue-146016.rs:56:27 | LL | let h = thread::spawn(move || match rx.recv().unwrap() { | _____________-------------_^ @@ -81,7 +81,7 @@ LL | | }); | = help: within `Foo`, the trait `Send` is not implemented for `*const c_void` note: required because it appears within the type `Foo` - --> $DIR/non-send-field-location-issue-146016.rs:21:11 + --> $DIR/non-send-field-location-issue-146016.rs:22:11 | LL | enum Foo { LL | Case(i32), @@ -89,7 +89,7 @@ LL | Case2(Bar), | ^^^ required by this field = note: required for `std::sync::mpsc::Receiver` to implement `Send` note: required because `rx` is used within this closure - --> $DIR/non-send-field-location-issue-146016.rs:55:41 + --> $DIR/non-send-field-location-issue-146016.rs:56:41 | LL | let h = thread::spawn(move || match rx.recv().unwrap() { | ^^ diff --git a/tests/ui/traits/non-send-field-location-issue-146016.rs b/tests/ui/traits/non-send-field-location-issue-146016.rs index 9f9cd6a20e48b..09a475feb521c 100644 --- a/tests/ui/traits/non-send-field-location-issue-146016.rs +++ b/tests/ui/traits/non-send-field-location-issue-146016.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ edition: 2024 diff --git a/tests/ui/traits/normalize/pointee-normalize-equate.rs b/tests/ui/traits/normalize/pointee-normalize-equate.rs index 3edb010a827b8..45bf1e8f3505a 100644 --- a/tests/ui/traits/normalize/pointee-normalize-equate.rs +++ b/tests/ui/traits/normalize/pointee-normalize-equate.rs @@ -1,5 +1,6 @@ //@ check-pass //@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(ptr_metadata)] diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs index f603ff1ec80ec..9e72bc104f8c4 100644 --- a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs +++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs index a42ea083d740c..4cd2ce55e31b3 100644 --- a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs +++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ build-pass //@ edition: 2021 diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr index 83ed7ae17902c..486566f6aacd5 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.current.stderr @@ -1,5 +1,5 @@ error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:10:5 + --> $DIR/lifetime_mismatch.rs:11:5 | LL | (x, y) | ^^^^^^ @@ -8,13 +8,13 @@ LL | (x, y) | lifetime `'b` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:10:5 + --> $DIR/lifetime_mismatch.rs:11:5 | LL | (x, y) | ^^^^^^ error: opaque type used twice with different lifetimes - --> $DIR/lifetime_mismatch.rs:18:5 + --> $DIR/lifetime_mismatch.rs:19:5 | LL | (i, j) | ^^^^^^ @@ -23,7 +23,7 @@ LL | (i, j) | lifetime `'y` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/lifetime_mismatch.rs:18:5 + --> $DIR/lifetime_mismatch.rs:19:5 | LL | (i, j) | ^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs index 4a8320e922a2e..4d5aa1f81654d 100644 --- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs +++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver=globally //@[next] check-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr index 660e4351d0cae..a2173972a224d 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `bar` found for struct `Bar` in the current scope - --> $DIR/method_resolution.rs:22:14 + --> $DIR/method_resolution.rs:23:14 | LL | struct Bar(T); | ------------- method `bar` not found for this struct diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr index 660e4351d0cae..a2173972a224d 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr @@ -1,5 +1,5 @@ error[E0599]: no method named `bar` found for struct `Bar` in the current scope - --> $DIR/method_resolution.rs:22:14 + --> $DIR/method_resolution.rs:23:14 | LL | struct Bar(T); | ------------- method `bar` not found for this struct diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs index a9162d0e28bee..e4240337544f7 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution.rs @@ -2,6 +2,7 @@ //! `u32` is the hidden type of `Foo` to call `bar` //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs index a4c4bbbace6b2..c6ad2949a94ec 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution2.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs @@ -2,6 +2,7 @@ //! `foo` method call can be resolved unambiguously by doing so. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr index c6aa0e811f36c..4572f622892d9 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.current.stderr @@ -1,5 +1,5 @@ error[E0307]: invalid `self` parameter type: `Bar` - --> $DIR/method_resolution3.rs:16:18 + --> $DIR/method_resolution3.rs:17:18 | LL | fn bar(self: Bar) { | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn bar(self: Bar) { = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0307]: invalid `self` parameter type: `&Bar` - --> $DIR/method_resolution3.rs:20:18 + --> $DIR/method_resolution3.rs:21:18 | LL | fn baz(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr index c6aa0e811f36c..4572f622892d9 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution3.next.stderr @@ -1,5 +1,5 @@ error[E0307]: invalid `self` parameter type: `Bar` - --> $DIR/method_resolution3.rs:16:18 + --> $DIR/method_resolution3.rs:17:18 | LL | fn bar(self: Bar) { | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn bar(self: Bar) { = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0307]: invalid `self` parameter type: `&Bar` - --> $DIR/method_resolution3.rs:20:18 + --> $DIR/method_resolution3.rs:21:18 | LL | fn baz(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs index a18dcc9a2fe3a..00f7cd05d120d 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution3.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs @@ -3,6 +3,7 @@ //! type, registering the generic parameter as the hidden type of the opaque type. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait, arbitrary_self_types)] diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr index 569a9f49bbe4b..3cd72a66706e1 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr @@ -1,5 +1,5 @@ error[E0307]: invalid `self` parameter type: `Bar` - --> $DIR/method_resolution4.rs:25:18 + --> $DIR/method_resolution4.rs:26:18 | LL | fn foo(self: Bar) { | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn foo(self: Bar) { = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0307]: invalid `self` parameter type: `&Bar` - --> $DIR/method_resolution4.rs:29:20 + --> $DIR/method_resolution4.rs:30:20 | LL | fn foomp(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr index 569a9f49bbe4b..3cd72a66706e1 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr @@ -1,5 +1,5 @@ error[E0307]: invalid `self` parameter type: `Bar` - --> $DIR/method_resolution4.rs:25:18 + --> $DIR/method_resolution4.rs:26:18 | LL | fn foo(self: Bar) { | ^^^^^^^^ @@ -8,7 +8,7 @@ LL | fn foo(self: Bar) { = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box`, `self: Rc`, or `self: Arc` error[E0307]: invalid `self` parameter type: `&Bar` - --> $DIR/method_resolution4.rs:29:20 + --> $DIR/method_resolution4.rs:30:20 | LL | fn foomp(self: &Bar) { | ^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs index 8a1b60b0c6e3a..debe79730ffb8 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution4.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs @@ -3,6 +3,7 @@ //! type, registering the generic parameter as the hidden type of the opaque type. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait, arbitrary_self_types)] diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs index b22c44ceb138a..c89e7d8bf6d30 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution5.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs @@ -2,6 +2,7 @@ //! not figure out that `u32` is the hidden type of `Foo` to call `bar`. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr index 841aa12f98309..89500d4fbad23 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr @@ -1,12 +1,12 @@ error: item does not constrain `Tait::{opaque#0}` - --> $DIR/method_resolution_trait_method_from_opaque.rs:26:8 + --> $DIR/method_resolution_trait_method_from_opaque.rs:27:8 | LL | fn foo(&mut self) { | ^^^ | = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` note: this opaque type is supposed to be constrained - --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13 + --> $DIR/method_resolution_trait_method_from_opaque.rs:18:13 | LL | type Tait = impl Iterator; | ^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr index 0c1e6a997ffec..a2e5b3cc972ef 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr @@ -1,5 +1,5 @@ error[E0282]: type annotations needed - --> $DIR/method_resolution_trait_method_from_opaque.rs:28:18 + --> $DIR/method_resolution_trait_method_from_opaque.rs:29:18 | LL | self.bar.next().unwrap(); | ^^^^ diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs index 93461fcbb0b2a..28cde4eb64027 100644 --- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs +++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs @@ -6,6 +6,7 @@ //! won't also be the ones defining the hidden type. //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr index fb67f6ffa44e4..88c2a8a575cab 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.current.stderr @@ -1,5 +1,5 @@ error: opaque type used twice with different lifetimes - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:11:5 | LL | (i, j) | ^^^^^^ @@ -8,7 +8,7 @@ LL | (i, j) | lifetime `'y` previously used here | note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types - --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:10:5 + --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:11:5 | LL | (i, j) | ^^^^^^ diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs index f1c0bc190108b..fd74d7009fff8 100644 --- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs +++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver=globally //@[next] check-pass #![feature(type_alias_impl_trait)] diff --git a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs index 1e42021b806d3..4c39f4e2e5a22 100644 --- a/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs +++ b/tests/ui/type-alias-impl-trait/mututally-recursive-overflow.rs @@ -1,9 +1,10 @@ //@ revisions: next old +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ edition: 2021 //@ build-fail -//[old]~^^^^ ERROR overflow evaluating the requirement `<() as B>::Assoc == _` -//[next]~^^^^^ ERROR: overflow evaluating the requirement `<() as A>::Assoc::{opaque#0} == _` +//[old]~^^^^^ ERROR overflow evaluating the requirement `<() as B>::Assoc == _` +//[next]~^^^^^^ ERROR: overflow evaluating the requirement `<() as A>::Assoc::{opaque#0} == _` #![feature(rustc_attrs)] #![feature(impl_trait_in_assoc_type)] diff --git a/tests/ui/type-alias-impl-trait/precise-capture-155151.current.stderr b/tests/ui/type-alias-impl-trait/precise-capture-155151.current.stderr index 972bf142db671..6d5307508b7a0 100644 --- a/tests/ui/type-alias-impl-trait/precise-capture-155151.current.stderr +++ b/tests/ui/type-alias-impl-trait/precise-capture-155151.current.stderr @@ -1,5 +1,5 @@ error[E0381]: used binding `x` isn't initialized - --> $DIR/precise-capture-155151.rs:20:18 + --> $DIR/precise-capture-155151.rs:21:18 | LL | let Foo { x } = foo; | - binding declared here but left uninitialized diff --git a/tests/ui/type-alias-impl-trait/precise-capture-155151.rs b/tests/ui/type-alias-impl-trait/precise-capture-155151.rs index b470c9373e93a..b535073c7c6aa 100644 --- a/tests/ui/type-alias-impl-trait/precise-capture-155151.rs +++ b/tests/ui/type-alias-impl-trait/precise-capture-155151.rs @@ -1,5 +1,6 @@ #![feature(type_alias_impl_trait)] //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ edition: 2021 //@[current] known-bug: #155151 //@[current] check-fail diff --git a/tests/ui/type-alias-impl-trait/tait-normalize.rs b/tests/ui/type-alias-impl-trait/tait-normalize.rs index f90520d3c5cd1..053c25b6f72db 100644 --- a/tests/ui/type-alias-impl-trait/tait-normalize.rs +++ b/tests/ui/type-alias-impl-trait/tait-normalize.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [next] compile-flags: -Znext-solver //@ check-pass diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr index 34648a420ac51..3fd1666214654 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.fail.stderr @@ -1,5 +1,5 @@ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:40:13 + --> $DIR/wf-in-associated-type.rs:41:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... @@ -8,7 +8,7 @@ LL | req | ^^^ ...so that the type `&'a T` will meet its required lifetime bounds... | note: ...that is required by this bound - --> $DIR/wf-in-associated-type.rs:38:36 + --> $DIR/wf-in-associated-type.rs:39:36 | LL | type Opaque = impl Sized + 'a; | ^^ @@ -18,7 +18,7 @@ LL | impl<'a, T: 'a> Trait<'a, T> for () { | ++++ error[E0309]: the parameter type `T` may not live long enough - --> $DIR/wf-in-associated-type.rs:40:13 + --> $DIR/wf-in-associated-type.rs:41:13 | LL | impl<'a, T> Trait<'a, T> for () { | -- the parameter type `T` must be valid for the lifetime `'a` as defined here... diff --git a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs index e548609e89a46..3982e494153ed 100644 --- a/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs +++ b/tests/ui/type-alias-impl-trait/wf-in-associated-type.rs @@ -1,6 +1,7 @@ // WF check for impl Trait in associated type position. // //@ revisions: pass pass_next fail +//@ ignore-compare-mode-next-solver (explicit revisions) //@ [pass] check-pass //@ [pass_next] compile-flags: -Znext-solver //@ [pass_next] check-pass diff --git a/tests/ui/typeck/issue-116864.current.stderr b/tests/ui/typeck/issue-116864.current.stderr index ae38a6d3439de..7337bf56a6b9d 100644 --- a/tests/ui/typeck/issue-116864.current.stderr +++ b/tests/ui/typeck/issue-116864.current.stderr @@ -1,5 +1,5 @@ error[E0277]: expected an `FnMut(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - --> $DIR/issue-116864.rs:28:1 + --> $DIR/issue-116864.rs:29:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) LL | | @@ -11,7 +11,7 @@ LL | | BAZ: Baz, = note: expected a closure with signature `for<'any> fn(&'any i32)` found a closure with signature `fn(&::Param)` note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` - --> $DIR/issue-116864.rs:20:20 + --> $DIR/issue-116864.rs:21:20 | LL | impl FnMutFut for F | ^^^^^^^^^^^^^^ ^ diff --git a/tests/ui/typeck/issue-116864.next.stderr b/tests/ui/typeck/issue-116864.next.stderr index c53410b1a1ec6..1a04243c2f6ba 100644 --- a/tests/ui/typeck/issue-116864.next.stderr +++ b/tests/ui/typeck/issue-116864.next.stderr @@ -1,5 +1,5 @@ error[E0277]: expected an `FnOnce(&'any i32)` closure, found `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` - --> $DIR/issue-116864.rs:28:1 + --> $DIR/issue-116864.rs:29:1 | LL | / async fn foo(_: BAZ, mut cb: impl for<'any> FnMutFut<&'any BAZ::Param, ()>) LL | | @@ -11,7 +11,7 @@ LL | | BAZ: Baz, = note: expected a closure with signature `for<'any> fn(&'any i32)` found a closure with signature `fn(&::Param)` note: required for `impl for<'any> FnMutFut<&'any BAZ::Param, ()>` to implement `for<'any> FnMutFut<&'any i32, ()>` - --> $DIR/issue-116864.rs:20:20 + --> $DIR/issue-116864.rs:21:20 | LL | impl FnMutFut for F | ^^^^^^^^^^^^^^ ^ diff --git a/tests/ui/typeck/issue-116864.rs b/tests/ui/typeck/issue-116864.rs index 427afe1784e92..a16731174b2be 100644 --- a/tests/ui/typeck/issue-116864.rs +++ b/tests/ui/typeck/issue-116864.rs @@ -1,4 +1,5 @@ //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver //@ edition: 2021 diff --git a/tests/ui/unsafe-fields/auto-traits.current.stderr b/tests/ui/unsafe-fields/auto-traits.current.stderr index 2483556b13918..d2ce00f543aac 100644 --- a/tests/ui/unsafe-fields/auto-traits.current.stderr +++ b/tests/ui/unsafe-fields/auto-traits.current.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied - --> $DIR/auto-traits.rs:24:22 + --> $DIR/auto-traits.rs:25:22 | LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); | ---------------- ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound @@ -7,12 +7,12 @@ LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); | required by a bound introduced by this call | help: the trait `UnsafeAuto` is not implemented for `UnsafeEnum` - --> $DIR/auto-traits.rs:9:1 + --> $DIR/auto-traits.rs:10:1 | LL | enum UnsafeEnum { | ^^^^^^^^^^^^^^^ note: required by a bound in `impl_unsafe_auto` - --> $DIR/auto-traits.rs:20:29 + --> $DIR/auto-traits.rs:21:29 | LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` diff --git a/tests/ui/unsafe-fields/auto-traits.next.stderr b/tests/ui/unsafe-fields/auto-traits.next.stderr index 2483556b13918..d2ce00f543aac 100644 --- a/tests/ui/unsafe-fields/auto-traits.next.stderr +++ b/tests/ui/unsafe-fields/auto-traits.next.stderr @@ -1,5 +1,5 @@ error[E0277]: the trait bound `UnsafeEnum: UnsafeAuto` is not satisfied - --> $DIR/auto-traits.rs:24:22 + --> $DIR/auto-traits.rs:25:22 | LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); | ---------------- ^^^^^^^^^^^^^^^^^^^^ unsatisfied trait bound @@ -7,12 +7,12 @@ LL | impl_unsafe_auto(UnsafeEnum::Safe(42)); | required by a bound introduced by this call | help: the trait `UnsafeAuto` is not implemented for `UnsafeEnum` - --> $DIR/auto-traits.rs:9:1 + --> $DIR/auto-traits.rs:10:1 | LL | enum UnsafeEnum { | ^^^^^^^^^^^^^^^ note: required by a bound in `impl_unsafe_auto` - --> $DIR/auto-traits.rs:20:29 + --> $DIR/auto-traits.rs:21:29 | LL | fn impl_unsafe_auto(_: impl UnsafeAuto) {} | ^^^^^^^^^^ required by this bound in `impl_unsafe_auto` diff --git a/tests/ui/unsafe-fields/auto-traits.rs b/tests/ui/unsafe-fields/auto-traits.rs index e15d0000079ef..ad292da530bd0 100644 --- a/tests/ui/unsafe-fields/auto-traits.rs +++ b/tests/ui/unsafe-fields/auto-traits.rs @@ -1,5 +1,6 @@ //@ compile-flags: --crate-type=lib //@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) //@[next] compile-flags: -Znext-solver #![feature(auto_traits)] From 8111cca7bc46af778c38cd56938cbe34d151b139 Mon Sep 17 00:00:00 2001 From: AMS21 Date: Sat, 3 Oct 2026 10:33:10 +0200 Subject: [PATCH 1218/1309] refactor: migrate to LLVM-C's `LLVMGetOrInsertFunction` --- compiler/rustc_codegen_llvm/src/declare.rs | 5 ++--- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 13 ++++++------- compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 10 ---------- 3 files changed, 8 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/declare.rs b/compiler/rustc_codegen_llvm/src/declare.rs index 3511056f79306..23f9fc93a4ba4 100644 --- a/compiler/rustc_codegen_llvm/src/declare.rs +++ b/compiler/rustc_codegen_llvm/src/declare.rs @@ -43,9 +43,8 @@ pub(crate) fn declare_simple_fn<'ll>( ty: &'ll Type, ) -> &'ll Value { debug!("declare_simple_fn(name={:?}, ty={:?})", name, ty); - let llfn = unsafe { - llvm::LLVMRustGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty) - }; + let llfn = + unsafe { llvm::LLVMGetOrInsertFunction(cx.llmod, name.as_c_char_ptr(), name.len(), ty) }; llvm::SetFunctionCallConv(llfn, callconv); llvm::set_unnamed_address(llfn, unnamed); diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index eca5fe429f541..4c7d60a0cbf67 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -1125,6 +1125,12 @@ unsafe extern "C" { FunctionTy: &'a Type, ) -> &'a Value; pub(crate) fn LLVMDeleteFunction(Fn: &Value); + pub(crate) fn LLVMGetOrInsertFunction<'a>( + M: &'a Module, + Name: *const c_char, + NameLen: size_t, + FunctionTy: &'a Type, + ) -> &'a Value; // Operations about llvm intrinsics pub(crate) fn LLVMLookupIntrinsicID(Name: *const c_char, NameLen: size_t) -> c_uint; @@ -2033,13 +2039,6 @@ unsafe extern "C" { ) -> &Attribute; // Operations on functions - /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGetOrInsertFunction`. - pub(crate) fn LLVMRustGetOrInsertFunction<'a>( - M: &'a Module, - Name: *const c_char, - NameLen: size_t, - FunctionTy: &'a Type, - ) -> &'a Value; pub(crate) fn LLVMRustAddFunctionAttributes<'a>( Fn: &'a Value, index: c_uint, diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index bc8fa60b66a52..6a34383b25be5 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -195,16 +195,6 @@ LLVMRustVerifyFunction(LLVMValueRef Fn, LLVMRustVerifierFailureAction Action) { return LLVMVerifyFunction(Fn, fromRust(Action)); } -extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M, - const char *Name, - size_t NameLen, - LLVMTypeRef FunctionTy) { - return wrap(unwrap(M) - ->getOrInsertFunction(StringRef(Name, NameLen), - unwrap(FunctionTy)) - .getCallee()); -} - // Get the global variable with the given name if it exists or create a new // external global. extern "C" LLVMValueRef From afc06630d2dd367b8547e3874e913b8f1fc8730e Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 30 Sep 2026 15:41:18 +0200 Subject: [PATCH 1219/1309] add Android support based on fallback path --- library/std/src/fs/tests.rs | 3 +-- library/std/src/sys/fs/unix.rs | 21 ++++++--------------- 2 files changed, 7 insertions(+), 17 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 6ed1bdd29ebd2..05ab05e922a32 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -614,7 +614,6 @@ fn set_get_unix_permissions() { } /// Test set_permissions_nofollow on a regular file. -#[cfg(not(target_os = "android"))] #[test] fn set_get_permissions_nofollows() { let tmpdir = tmpdir(); @@ -650,7 +649,7 @@ fn set_get_permissions_nofollows() { } } -#[cfg(not(target_os = "android"))] +/// Test set_permissions_nofollow on a symlink. #[test] fn set_get_permissions_nofollows_symlink() { #[cfg(not(windows))] diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 46d5d33d23ac2..7c29cacbe262d 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -1896,22 +1896,11 @@ pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { Err(crate::io::ErrorKind::Unsupported.into()) } -#[cfg(target_os = "android")] -pub fn set_perm_nofollow(_p: &CStr, _perm: FilePermissions) -> io::Result<()> { - // Currently Android seems to be having inconsistent behavior with fchmodat - // with `AT_SYMLINK_NOFOLLOW` or openat with `O_NOFOLLOW` + fchmod. - // See this issue here mentioning inconsistent behavior on fchmodat: - // https://github.com/android/ndk/issues/1258 - // On the arm-android CI job, using fchmodat with `AT_SYMLINK_NOFOLLOW` + - // fallback behavior on a symlink sets the target file's permissions, - // which is incorrect behavior. - Err(crate::io::ErrorKind::Unsupported.into()) -} - -#[cfg(not(any(target_os = "android", target_os = "vxworks")))] +#[cfg(not(target_os = "vxworks"))] pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { + /// Helper function for fallback open with `O_NOFOLLOW` + `fchmod` behavior. This will + /// successfully change the permissions of non-symlinks and fail when there's a symlink. #[inline] - /// Helper function for fallback open with `O_NOFOLLOW` + `fchmod` behavior fn open_and_set_permissions(p: &CStr, perm: FilePermissions) -> io::Result<()> { use crate::fs::{OpenOptions, Permissions}; @@ -1926,6 +1915,7 @@ pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { use crate::os::unix::fs::OpenOptionsExt; #[cfg(target_os = "wasi")] use crate::os::wasi::fs::OpenOptionsExt; + options.custom_flags(libc::O_NOFOLLOW); } @@ -1940,7 +1930,8 @@ pub fn set_perm_nofollow(p: &CStr, perm: FilePermissions) -> io::Result<()> { #[allow(unused)] let mut res: Result<(), core::io::Error> = Err(crate::io::ErrorKind::Unsupported.into()); - // These platforms support `fchmodat`, so utilize this syscall over `open` + `fchmod` + // These platforms support `fchmodat`, so utilize this syscall over `open` + `fchmod`. + // We can *not* use this on Android due to . #[cfg(any( target_os = "linux", target_os = "macos", From 56bb24407d291bed280defc757b9460fcaed0019 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 2 Oct 2026 23:30:23 +0200 Subject: [PATCH 1220/1309] Correctly link to enum variants when present in `Cache::external_paths` when using the `--generate-link-to-definition` feature --- src/librustdoc/html/format.rs | 10 ++++++--- .../jump-to-def/link-to-variant.rs | 21 +++++++++++++++++++ 2 files changed, 28 insertions(+), 3 deletions(-) create mode 100644 tests/rustdoc-html/jump-to-def/link-to-variant.rs diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index b97bd93181f7a..3f1ed079f2686 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -768,11 +768,15 @@ pub(crate) fn href_with_root_path( false, ), None => { - // Associated items are handled differently with "jump to def". The anchor is generated + // Associated items are handled differently with "jump to def": the anchor is generated // directly here whereas for intra-doc links, we have some extra computation being // performed there. - let def_id_to_get = if root_path.is_some() { original_did } else { did }; - if let Some(&(ref fqp, shortty)) = cache.external_paths.get(&def_id_to_get) { + // + // So if `root_path` is `Some()` and it's an associated item, we enter to enter the + // `else` branch to have the anchor generated here directly. + if (root_path.is_none() || original_did == did) + && let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) + { let module_fqp = to_module_fqp(shortty, fqp); let (parts, is_absolute) = url_parts(cache, did, module_fqp, relative_to)?; (fqp.as_slice(), shortty, parts, is_absolute) diff --git a/tests/rustdoc-html/jump-to-def/link-to-variant.rs b/tests/rustdoc-html/jump-to-def/link-to-variant.rs new file mode 100644 index 0000000000000..dd01f636f873f --- /dev/null +++ b/tests/rustdoc-html/jump-to-def/link-to-variant.rs @@ -0,0 +1,21 @@ +// This test ensures that even if enum variants are imported (and thus present in the +// `Cache::external_paths` rustdoc data), we still link correctly to them. + +#![no_std] +#![crate_name = "foo"] + +//@ compile-flags: -Zunstable-options --generate-link-to-definition + +//@ has 'src/foo/link-to-variant.rs.html' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html#variant.Equal"]' 'Equal' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html"]' 'Ordering' +//@ has - '//a[@href="{{channel}}/core/cmp/enum.Ordering.html"]' 'self' + +use core::cmp::Ordering::{self, Equal}; + +pub fn foo(o: Ordering) -> bool { + match o { + Ordering::Equal => true, + _ => false, + } +} From 73b2a849a09a936d92be71fcbf0e08c31a44d8c2 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Oct 2026 17:16:02 +0200 Subject: [PATCH 1221/1309] Move `rustdoc-html` tests into the right location --- tests/rustdoc-html/{ => deref}/auxiliary/issue-19190-3.rs | 0 .../rustdoc-html/{ => deref}/deref-methods-19190-foreign-type.rs | 0 tests/rustdoc-html/{ => deref}/deref-methods-19190-inline.rs | 0 tests/rustdoc-html/{ => deref}/deref-methods-19190.rs | 0 tests/rustdoc-html/{ => private}/fake-items-doc-private-items.rs | 0 tests/rustdoc-html/{ => private}/pub-method.rs | 0 tests/rustdoc-html/{ => private}/static.rs | 0 tests/rustdoc-html/{ => private}/visibility.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-13698.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-99221-aux.rs | 0 tests/rustdoc-html/{ => reexport}/auxiliary/issue-99734-aux.rs | 0 tests/rustdoc-html/{ => reexport}/doc-hidden-method-13698.rs | 0 .../{ => reexport}/multiple-foreigns-w-same-name-99734.rs | 0 tests/rustdoc-html/{ => reexport}/multiple-import-levels.rs | 0 .../{ => reexport}/multiple-mods-w-same-name-99734.rs | 0 .../{ => reexport}/multiple-mods-w-same-name-doc-inline-83375.rs | 0 .../multiple-mods-w-same-name-doc-inline-last-item-83375.rs | 0 .../{ => reexport}/multiple-structs-w-same-name-99221.rs | 0 18 files changed, 0 insertions(+), 0 deletions(-) rename tests/rustdoc-html/{ => deref}/auxiliary/issue-19190-3.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190-foreign-type.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190-inline.rs (100%) rename tests/rustdoc-html/{ => deref}/deref-methods-19190.rs (100%) rename tests/rustdoc-html/{ => private}/fake-items-doc-private-items.rs (100%) rename tests/rustdoc-html/{ => private}/pub-method.rs (100%) rename tests/rustdoc-html/{ => private}/static.rs (100%) rename tests/rustdoc-html/{ => private}/visibility.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-13698.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-99221-aux.rs (100%) rename tests/rustdoc-html/{ => reexport}/auxiliary/issue-99734-aux.rs (100%) rename tests/rustdoc-html/{ => reexport}/doc-hidden-method-13698.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-foreigns-w-same-name-99734.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-import-levels.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-99734.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-doc-inline-83375.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-mods-w-same-name-doc-inline-last-item-83375.rs (100%) rename tests/rustdoc-html/{ => reexport}/multiple-structs-w-same-name-99221.rs (100%) diff --git a/tests/rustdoc-html/auxiliary/issue-19190-3.rs b/tests/rustdoc-html/deref/auxiliary/issue-19190-3.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-19190-3.rs rename to tests/rustdoc-html/deref/auxiliary/issue-19190-3.rs diff --git a/tests/rustdoc-html/deref-methods-19190-foreign-type.rs b/tests/rustdoc-html/deref/deref-methods-19190-foreign-type.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190-foreign-type.rs rename to tests/rustdoc-html/deref/deref-methods-19190-foreign-type.rs diff --git a/tests/rustdoc-html/deref-methods-19190-inline.rs b/tests/rustdoc-html/deref/deref-methods-19190-inline.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190-inline.rs rename to tests/rustdoc-html/deref/deref-methods-19190-inline.rs diff --git a/tests/rustdoc-html/deref-methods-19190.rs b/tests/rustdoc-html/deref/deref-methods-19190.rs similarity index 100% rename from tests/rustdoc-html/deref-methods-19190.rs rename to tests/rustdoc-html/deref/deref-methods-19190.rs diff --git a/tests/rustdoc-html/fake-items-doc-private-items.rs b/tests/rustdoc-html/private/fake-items-doc-private-items.rs similarity index 100% rename from tests/rustdoc-html/fake-items-doc-private-items.rs rename to tests/rustdoc-html/private/fake-items-doc-private-items.rs diff --git a/tests/rustdoc-html/pub-method.rs b/tests/rustdoc-html/private/pub-method.rs similarity index 100% rename from tests/rustdoc-html/pub-method.rs rename to tests/rustdoc-html/private/pub-method.rs diff --git a/tests/rustdoc-html/static.rs b/tests/rustdoc-html/private/static.rs similarity index 100% rename from tests/rustdoc-html/static.rs rename to tests/rustdoc-html/private/static.rs diff --git a/tests/rustdoc-html/visibility.rs b/tests/rustdoc-html/private/visibility.rs similarity index 100% rename from tests/rustdoc-html/visibility.rs rename to tests/rustdoc-html/private/visibility.rs diff --git a/tests/rustdoc-html/auxiliary/issue-13698.rs b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-13698.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-13698.rs diff --git a/tests/rustdoc-html/auxiliary/issue-99221-aux.rs b/tests/rustdoc-html/reexport/auxiliary/issue-99221-aux.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-99221-aux.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-99221-aux.rs diff --git a/tests/rustdoc-html/auxiliary/issue-99734-aux.rs b/tests/rustdoc-html/reexport/auxiliary/issue-99734-aux.rs similarity index 100% rename from tests/rustdoc-html/auxiliary/issue-99734-aux.rs rename to tests/rustdoc-html/reexport/auxiliary/issue-99734-aux.rs diff --git a/tests/rustdoc-html/doc-hidden-method-13698.rs b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs similarity index 100% rename from tests/rustdoc-html/doc-hidden-method-13698.rs rename to tests/rustdoc-html/reexport/doc-hidden-method-13698.rs diff --git a/tests/rustdoc-html/multiple-foreigns-w-same-name-99734.rs b/tests/rustdoc-html/reexport/multiple-foreigns-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc-html/multiple-foreigns-w-same-name-99734.rs rename to tests/rustdoc-html/reexport/multiple-foreigns-w-same-name-99734.rs diff --git a/tests/rustdoc-html/multiple-import-levels.rs b/tests/rustdoc-html/reexport/multiple-import-levels.rs similarity index 100% rename from tests/rustdoc-html/multiple-import-levels.rs rename to tests/rustdoc-html/reexport/multiple-import-levels.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-99734.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-99734.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-99734.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-99734.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-83375.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-83375.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-83375.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-83375.rs diff --git a/tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-last-item-83375.rs b/tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-last-item-83375.rs similarity index 100% rename from tests/rustdoc-html/multiple-mods-w-same-name-doc-inline-last-item-83375.rs rename to tests/rustdoc-html/reexport/multiple-mods-w-same-name-doc-inline-last-item-83375.rs diff --git a/tests/rustdoc-html/multiple-structs-w-same-name-99221.rs b/tests/rustdoc-html/reexport/multiple-structs-w-same-name-99221.rs similarity index 100% rename from tests/rustdoc-html/multiple-structs-w-same-name-99221.rs rename to tests/rustdoc-html/reexport/multiple-structs-w-same-name-99221.rs From d78744aa4709ad118b8ceab06c84ff42bd8a7051 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 3 Oct 2026 17:29:07 +0200 Subject: [PATCH 1222/1309] Remove `@ !has` annotations from `tests/rustdoc-html/reexport/doc-hidden-method-13698.rs` --- tests/rustdoc-html/reexport/auxiliary/issue-13698.rs | 1 + tests/rustdoc-html/reexport/doc-hidden-method-13698.rs | 7 +++++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs index 5e5381e0d07a3..6bca72ec38f9a 100644 --- a/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs +++ b/tests/rustdoc-html/reexport/auxiliary/issue-13698.rs @@ -3,6 +3,7 @@ pub trait Foo { #[doc(hidden)] fn foo(&self) {} + fn not_hidden(&self) {} } impl Foo for i32 {} diff --git a/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs index 5c0ad18ee2989..2b2d14b2c7067 100644 --- a/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs +++ b/tests/rustdoc-html/reexport/doc-hidden-method-13698.rs @@ -7,7 +7,11 @@ extern crate issue_13698; pub struct Foo; -//@ !has issue_13698/struct.Foo.html '//*[@id="method.foo"]' 'fn foo' +//@ has 'issue_13698/struct.Foo.html' +// There is only one visible trait impl method (from the `Foo` trait). +//@ count - '//*[@id="trait-implementations-list"]//*[@class="method trait-impl"]' 1 +//@ has - '//*[@id="trait-implementations-list"]//*[@class="method trait-impl"]' \ +// 'fn not_hidden(&self)' impl issue_13698::Foo for Foo {} pub trait Bar { @@ -15,5 +19,4 @@ pub trait Bar { fn bar(&self) {} } -//@ !has issue_13698/struct.Foo.html '//*[@id="method.bar"]' 'fn bar' impl Bar for Foo {} From bfbfe1e4834e9fefcd54d3ee18f3ef53b61dd49c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 18:35:56 +0200 Subject: [PATCH 1223/1309] unix open: support opening directories --- src/tools/miri/src/shims/files.rs | 55 ++++++- src/tools/miri/src/shims/unix/fs.rs | 118 +++++++++++--- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 153 ++++++++++++++---- src/tools/miri/tests/pass/shims/fs.rs | 49 +++++- 4 files changed, 306 insertions(+), 69 deletions(-) diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index d842f2f69b713..92144d3aeb764 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -444,7 +444,13 @@ impl FileDescription for FileHandle { assert!(communicate_allowed, "isolation should have prevented even opening a file"); if !self.readable { - return finish.call(ecx, Err(ErrorKind::PermissionDenied.into())); + // Unix returns EBADF, Windows something that translates to `PermissionDenied`. + let err = if ecx.target_os_is_unix() { + LibcError("EBADF") + } else { + ErrorKind::PermissionDenied.into() + }; + return finish.call(ecx, Err(err)); } let mut file = &self.file; @@ -463,13 +469,13 @@ impl FileDescription for FileHandle { assert!(communicate_allowed, "isolation should have prevented even opening a file"); if !self.writable { - // Linux hosts return EBADF here which we can't translate via the platform-independent - // code since it does not map to any `io::ErrorKind` -- so if we don't do anything - // special, we'd throw an "unsupported error code" here. Windows returns something that - // gets translated to `PermissionDenied`. That seems like a good value so let's just use - // this everywhere, even if it means behavior on Unix targets does not match the real - // thing. - return finish.call(ecx, Err(ErrorKind::PermissionDenied.into())); + // Unix returns EBADF, Windows something that translates to `PermissionDenied`. + let err = if ecx.target_os_is_unix() { + LibcError("EBADF") + } else { + ErrorKind::PermissionDenied.into() + }; + return finish.call(ecx, Err(err)); } let result = ecx.write_to_host(&self.file, len, ptr)?; finish.call(ecx, result) @@ -546,6 +552,39 @@ impl FileDescription for DirHandle { #[cfg(not(bootstrap))] return interp_ok(Either::Left(self.dir.self_metadata())); } + + fn read<'tcx>( + self: FileDescriptionRef, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + ecx: &mut MiriInterpCx<'tcx>, + finish: DynMachineCallback<'tcx, Result>, + ) -> InterpResult<'tcx> { + if ecx.target_os_is_unix() { + finish.call(ecx, Err(LibcError("EISDIR"))) + } else { + // No idea what this should do on Windows. + throw_unsup_format!("reading directories is not supported on this target"); + } + } + + fn write<'tcx>( + self: FileDescriptionRef, + _communicate_allowed: bool, + _ptr: Pointer, + _len: usize, + ecx: &mut MiriInterpCx<'tcx>, + finish: DynMachineCallback<'tcx, Result>, + ) -> InterpResult<'tcx> { + if ecx.target_os_is_unix() { + // Directories are opened for reading, so writing returns EBADF. + finish.call(ecx, Err(LibcError("EBADF"))) + } else { + // No idea what this should do on Windows. + throw_unsup_format!("writing directories is not supported on this target"); + } + } } /// Internal type of a file-descriptor - this is what [`FdTable`] expects diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 9b5ed86013f70..2d1ee758f2de1 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -455,6 +455,20 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported access mode {:#x}", access_mode); } + if this.tcx.sess.target.os == Os::Linux { + let o_tmpfile = this.eval_libc_i32("O_TMPFILE"); + // Note that this overaps with O_DIRECTORY! + if flag & o_tmpfile == o_tmpfile { + // if the flag contains `O_TMPFILE` then we return a graceful error + return this.set_errno_and_return_neg1_i32(LibcError("EOPNOTSUPP")); + } + } + let o_directory = this.eval_libc_i32("O_DIRECTORY"); + let mut want_directory = false; + if flag & o_directory == o_directory { + flag &= !o_directory; + want_directory = true; + } let o_append = this.eval_libc_i32("O_APPEND"); if flag & o_append == o_append { flag &= !o_append; @@ -468,6 +482,10 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let o_creat = this.eval_libc_i32("O_CREAT"); if flag & o_creat == o_creat { flag &= !o_creat; + if want_directory { + // O_CREAT + O_DIRECTORY is invalid. + return this.set_errno_and_return_neg1_i32(LibcError("EINVAL")); + } // Get the mode. let ([mode], _) = this.check_varargs( if this.libc_ty_layout("mode_t").size.bytes() >= 4 { @@ -514,14 +532,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We do not need to do anything for this flag because `std` already sets it. // (Technically we do not support *not* setting this flag, but we ignore that.) } - if this.tcx.sess.target.os == Os::Linux { - let o_tmpfile = this.eval_libc_i32("O_TMPFILE"); - if flag & o_tmpfile == o_tmpfile { - // if the flag contains `O_TMPFILE` then we return a graceful error - return this.set_errno_and_return_neg1_i32(LibcError("EOPNOTSUPP")); - } - } - let o_nofollow = this.eval_libc_i32("O_NOFOLLOW"); let mut nofollow = false; if flag & o_nofollow == o_nofollow { @@ -552,23 +562,81 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(ErrorKind::PermissionDenied); } - let file = match options.open(path) { - Ok(file) => file, - Err(err) => return this.set_errno_and_return_neg1_i32(err), - }; - let metadata = file.metadata().expect("a just-opened file should have metadata"); - if metadata.is_dir() { - throw_unsup_format!("open: opening directories is not supported"); - } - if nofollow && !cfg!(unix) { - // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just - // opens the symlink rather than the target. Turn that into an error. - if metadata.is_symlink() { - return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + // We start a retry loop to deal with the `is_dir` race, see below. + // We add a retry counter to avoid infinite loops when things go wrong. + let mut counter = 0u32; + loop { + if counter >= 100 { + panic!( + "open seems stuck in an infinite retry loop. \ + If you can reproduce this, please file a bug." + ); + } + counter = counter.strict_add(1); + + // We need to know if the file is a directory to correctly open directory handles. + // The standard library only lets us open something as a file or a directory, so + // we check for that and then retry if we end up with the wrong thing. + let is_dir = path.is_dir(); + + if is_dir { + // Directories cannot be opened for writing. + if access_mode != o_rdonly { + return this.set_errno_and_return_neg1_i32(LibcError("EISDIR")); + } + // All the other flags don't really do anything. + let dir = match DirHandle::open(&path) { + Ok(dir) => dir, + Err(e) => { + if e.kind() == io::ErrorKind::NotADirectory { + // This changed from a directory to a file. Retry. + continue; + } + return this.set_errno_and_return_neg1_i32(e); + } + }; + #[cfg(bootstrap)] + let metadata = dir.dir.metadata(); + #[cfg(not(bootstrap))] + let metadata = dir.dir.self_metadata(); + if !metadata.unwrap().is_dir() { + // This changed from a directory to a file. Retry. + continue; + } + + let fd = this.machine.fds.insert_new(dir); + return interp_ok(Scalar::from_i32(fd)); + } else { + let file = match options.open(&path) { + Ok(file) => file, + Err(e) => { + if e.kind() == io::ErrorKind::IsADirectory { + // This changed from a directory to a file. Retry. + continue; + } + return this.set_errno_and_return_neg1_i32(e); + } + }; + let metadata = file.metadata().expect("a just-opened file should have metadata"); + if metadata.is_dir() { + // This changed from a file to a directory. Retry. + continue; + } + + if nofollow && !cfg!(unix) { + // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just + // opens the symlink rather than the target. Turn that into an error. + if metadata.is_symlink() { + return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + } + } + if want_directory { + return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); + } + let fd = this.machine.fds.insert_new(FileHandle { file, writable, readable }); + return interp_ok(Scalar::from_i32(fd)); } } - let fd = this.machine.fds.insert_new(FileHandle { file, writable, readable }); - interp_ok(Scalar::from_i32(fd)) } fn lseek( @@ -845,7 +913,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; let Some(dir) = fd.downcast::() else { - return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); }; #[cfg(not(bootstrap))] @@ -937,7 +1005,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; let Some(dir) = fd.downcast::() else { - return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); + return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); }; #[cfg(not(bootstrap))] diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 5e3f1ffc0c491..1142f1182f4bc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -28,10 +28,11 @@ fn main() { test_ftruncate::(libc::ftruncate); #[cfg(target_os = "linux")] test_ftruncate::(libc::ftruncate64); - test_file_open_allow_two_args(); - test_file_open_needs_three_args(); - test_file_open_extra_third_arg(); + test_create_read_write(); + test_file_open_args(); test_file_open_nofollow(); + test_file_open_directory(); + test_file_open_exclusive(); #[cfg(target_os = "linux")] test_o_tmpfile_flag(); test_posix_mkstemp(); @@ -208,10 +209,13 @@ fn test_statx() { } // Relative to a dirfd. - // The only way to get a dirfd in Miri currently is via a `dirfd`. Slightly silly, but whatever. - let dirstream = unsafe { libc::opendir(utils::into_c_string(path.parent().unwrap()).as_ptr()) }; - assert!(!dirstream.is_null()); - let dirfd = unsafe { libc::dirfd(dirstream) }; + let dirfd = errno_result(unsafe { + libc::open( + utils::into_c_string(path.parent().unwrap()).as_ptr(), + libc::O_RDONLY | libc::O_DIRECTORY, + ) + }) + .unwrap(); unsafe { let mut stx = MaybeUninit::::zeroed(); errno_check(libc::statx( @@ -225,7 +229,7 @@ fn test_statx() { let stx = stx.assume_init(); assert_statx_matches_metadata(&stx, &meta, bytes.len() as u64); } - errno_check(unsafe { libc::closedir(dirstream) }); + errno_check(unsafe { libc::close(dirfd) }); remove_file(&path).unwrap(); } @@ -306,26 +310,12 @@ fn test_statx_on_empty_path() { } } -fn test_file_open_allow_two_args() { - let path = utils::prepare_with_content("miri_test_file_open_allow_two_args.txt", &[]); +fn test_file_open_args() { + let path = utils::prepare_with_content("miri_test_file_open_args.txt", &[]); let name = utils::into_c_string(path); + // Works with 2 or 3 arguments. let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY) }).unwrap(); -} - -fn test_file_open_needs_three_args() { - let path = utils::prepare_with_content("miri_test_file_open_needs_three_args.txt", &[]); - let name = utils::into_c_string(path); - - let _fd = - errno_result(unsafe { libc::open(name.as_ptr(), libc::O_CREAT | libc::O_RDWR, 0o666) }) - .unwrap(); -} - -fn test_file_open_extra_third_arg() { - let path = utils::prepare_with_content("miri_test_file_open_extra_third_arg.txt", &[]); - let name = utils::into_c_string(path); - let _fd = errno_result(unsafe { libc::open(name.as_ptr(), libc::O_RDONLY, 42) }).unwrap(); } @@ -358,6 +348,77 @@ fn test_file_open_nofollow() { } } +fn test_file_open_directory() { + let dir_path = utils::prepare_dir("miri_test_file_open_directory"); + create_dir(&dir_path).unwrap(); + let dir_name = utils::into_c_string(dir_path); + + // Opening it for read-write fails. + let err = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDWR) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::EISDIR); + + // Opening it for reading succeeds, but then reading/writing fails. + let fd = errno_result(unsafe { libc::open(dir_name.as_ptr(), libc::O_RDONLY) }).unwrap(); + let mut buf = [0u8; 4]; + let err = + errno_result(unsafe { libc::read(fd, buf.as_mut_ptr().cast(), buf.len()) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::EISDIR, "unexpected errno: {err}"); + let err = errno_result(unsafe { libc::write(fd, buf.as_ptr().cast(), buf.len()) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::EBADF, "unexpected errno: {err}"); + errno_check(unsafe { libc::close(fd) }); + + // Ensure it errors on non-directories when we add the flag. + let path = utils::prepare_with_content("miri_test_fs_not_a_dir", &[]); + let err = errno_result(unsafe { + libc::open(utils::into_c_string(path).as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY) + }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOTDIR); + let err = errno_result(unsafe { + libc::open(c"doesnotexist".as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY) + }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); +} + +fn test_file_open_exclusive() { + let path = utils::prepare("miri_test_file_open_exclusive.txt"); + let cpath = utils::into_c_string(path); + + let fd = errno_result(unsafe { + libc::open(cpath.as_ptr(), libc::O_WRONLY | libc::O_CREAT | libc::O_EXCL, 0o666) + }) + .unwrap(); + errno_check(unsafe { libc::close(fd) }); + + let exist_err = errno_result(unsafe { + libc::open(cpath.as_ptr(), libc::O_WRONLY | libc::O_CREAT | libc::O_EXCL, 0o666) + }) + .unwrap_err(); + assert_eq!(exist_err.raw_os_error().unwrap(), libc::EEXIST, "unexpected errno: {exist_err}"); +} + +fn test_create_read_write() { + let content = b"hello test"; + let path = utils::prepare("miri_test_create_read_write.txt"); + let cpath = utils::into_c_string(path); + + let fd = + errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_WRONLY | libc::O_CREAT, 0o666) }) + .unwrap(); + let read_err = libc_utils::read_exact_array::<4>(fd).unwrap_err(); + assert_eq!(read_err.raw_os_error().unwrap(), libc::EBADF, "unexpected errno: {read_err}"); + libc_utils::write_all(fd, content).unwrap(); + errno_check(unsafe { libc::close(fd) }); + + let fd = errno_result(unsafe { libc::open(cpath.as_ptr(), libc::O_RDONLY) }).unwrap(); + let write_err = libc_utils::write_all(fd, content).unwrap_err(); + assert_eq!(write_err.raw_os_error().unwrap(), libc::EBADF, "unexpected errno: {write_err}"); + let data = libc_utils::read_exact_array::<8>(fd).unwrap(); + assert!(content.starts_with(&data)); + errno_check(unsafe { libc::close(fd) }); +} + fn test_dup_stdout_stderr() { let bytes = b"hello dup fd\n"; unsafe { @@ -887,13 +948,9 @@ fn test_fstatat() { let cfilename = c"file.txt"; fs::write(testdir.join(filename), b"hello").unwrap(); let absfilename = testdir.join(filename); + let cabsfilename = utils::into_c_string(&absfilename); assert!(absfilename.is_absolute()); - // The only way to get a dirfd in Miri currently is via a `dirfd`. Slightly silly, but whatever. - let dirstream = unsafe { libc::opendir(utils::into_c_string(&testdir).as_ptr()) }; - assert!(!dirstream.is_null()); - let dirfd = unsafe { libc::dirfd(dirstream) }; - let checkstat = |stat: &libc::stat| { assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFREG); assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); @@ -914,7 +971,7 @@ fn test_fstatat() { errno_check(unsafe { libc::fstatat( 999, // dirfd - utils::into_c_string(&absfilename).as_ptr(), + cabsfilename.as_ptr(), stat.as_mut_ptr(), 0, // flags ) @@ -922,10 +979,27 @@ fn test_fstatat() { checkstat(unsafe { stat.assume_init_ref() }); // Relative to dirfd. + let dirfd = errno_result(unsafe { + libc::open(utils::into_c_string(&testdir).as_ptr(), libc::O_RDONLY | libc::O_DIRECTORY) + }) + .unwrap(); let mut stat = MaybeUninit::::uninit(); errno_check(unsafe { libc::fstatat(dirfd, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }); checkstat(unsafe { stat.assume_init_ref() }); + // Relative to bogus FD that's not a dir. + let err = errno_result(unsafe { libc::fstatat(0, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOTDIR, "unexpected errno: {err}"); + let fd = errno_result(unsafe { libc::open(cabsfilename.as_ptr(), libc::O_RDONLY) }).unwrap(); + let err = errno_result(unsafe { libc::fstatat(fd, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOTDIR, "unexpected errno: {err}"); + errno_check(unsafe { libc::close(fd) }); + let err = errno_result(unsafe { libc::fstatat(fd, cfilename.as_ptr(), stat.as_mut_ptr(), 0) }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::EBADF, "unexpected errno: {err}"); + if utils::have_symlink_permission() { // Symlink following. let linkname = testdir.join("link"); @@ -943,7 +1017,7 @@ fn test_fstatat() { check_stat_fields(stat); } - errno_check(unsafe { libc::closedir(dirstream) }); + errno_check(unsafe { libc::close(dirfd) }); } fn test_stat() { @@ -1219,9 +1293,22 @@ fn test_dirfd() { // Check that all fields are initialized. check_stat_fields(stat); + // We can also call fstatat on this. + let mut stat = MaybeUninit::::uninit(); + let err = + errno_result(unsafe { libc::fstatat(dirfd, c"missing".as_ptr(), stat.as_mut_ptr(), 0) }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); + errno_check(unsafe { libc::fstatat(dirfd, c".".as_ptr(), stat.as_mut_ptr(), 0) }); + let stat = unsafe { stat.assume_init_ref() }; + assert_eq!(stat.st_mode & libc::S_IFMT, libc::S_IFDIR); + assert_ne!(stat.st_mode & !libc::S_IFMT, 0, "some permission should be set"); + check_stat_fields(stat); + + // Close the stream. errno_check(unsafe { libc::closedir(dir) }); - // `closedir` should also have closed the stream. + // `closedir` should also have closed the underlying FD. let err = errno_result(unsafe { libc::close(dirfd) }).unwrap_err(); assert_eq!(err.raw_os_error().unwrap(), libc::EBADF); } diff --git a/src/tools/miri/tests/pass/shims/fs.rs b/src/tools/miri/tests/pass/shims/fs.rs index 7466a534b0ca4..90c7bdd2e8592 100644 --- a/src/tools/miri/tests/pass/shims/fs.rs +++ b/src/tools/miri/tests/pass/shims/fs.rs @@ -3,6 +3,7 @@ #![feature(io_error_more)] #![feature(io_error_uncategorized)] +#![feature(dirfd)] #![cfg_attr(unix, feature(unix_file_vectored_at))] #![allow(unused_features)] // feature use depends on target @@ -60,6 +61,8 @@ fn main() { test_pread_pwrite(); #[cfg(all(unix, not(target_os = "solaris")))] test_preadv_pwritev(); + + test_directory_handle(); } } @@ -93,9 +96,12 @@ fn test_file() { assert!(!file.is_terminal()); - // Writing to a file opened for reading should error (and not stop interpretation). std does not - // categorize the error so we don't check for details. - file.write(&[0]).unwrap_err(); + // Writing to a file opened for reading should error (and not stop interpretation). This + // produces EBADF on Unix but std does not categorize the error so we don't check for details. + let err = file.write(&[0]).unwrap_err(); + if cfg!(windows) { + assert_eq!(err.kind(), ErrorKind::PermissionDenied); + } // However, writing 0 bytes can succeed or fail. let _ignore = file.write(&[]); @@ -104,6 +110,26 @@ fn test_file() { // Removing file should succeed. remove_file(&path).unwrap(); + + // Opening a directory as a file has target-specific behavior. + let res = File::open(&path.parent().unwrap()); + if cfg!(unix) { + // On Unix this just works. + let mut file = res.unwrap(); + // But reading errors. + let err = file.read(&mut [0u8; 32]).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::IsADirectory); + } else { + // On Windows, it errors. + assert_eq!(res.unwrap_err().kind(), ErrorKind::PermissionDenied); + } + // Opening for writing has a target-specific error. + let err = OpenOptions::new().write(true).open(&path.parent().unwrap()).unwrap_err(); + if cfg!(unix) { + assert_eq!(err.kind(), ErrorKind::IsADirectory); + } else { + assert_eq!(err.kind(), ErrorKind::PermissionDenied); + } } fn test_file_partial_reads_writes() { @@ -619,3 +645,20 @@ fn test_hard_link() { remove_file(&source).unwrap(); remove_file(&link).unwrap(); } + +fn test_directory_handle() { + let filename = utils::prepare_with_content("miri_test_directory_handle.txt", b"hello"); + assert!(filename.is_absolute()); + let dir = fs::Dir::open(filename.parent().unwrap()).unwrap(); + assert!(dir.self_metadata().unwrap().is_dir()); + + let stat = dir.metadata(filename.file_name().unwrap()).unwrap(); + assert!(stat.is_file()); + assert!(stat.len() == 5); + let stat = dir.metadata(&filename).unwrap(); // absolute path + assert!(stat.is_file()); + assert!(stat.len() == 5); + + let err = fs::Dir::open(filename).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::NotADirectory); +} From 6749841b633242f94c75fdda849a41304ddbac56 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sat, 3 Oct 2026 13:25:28 -0400 Subject: [PATCH 1224/1309] Stabilize CStr::display --- library/core/src/ffi/c_str.rs | 12 ++++-------- library/coretests/tests/lib.rs | 1 - library/std/src/ffi/c_str.rs | 2 +- library/std/src/lib.rs | 1 - 4 files changed, 5 insertions(+), 11 deletions(-) diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs index d79af3afbc56e..daa68e885d893 100644 --- a/library/core/src/ffi/c_str.rs +++ b/library/core/src/ffi/c_str.rs @@ -650,12 +650,10 @@ impl CStr { /// # Examples /// /// ``` - /// #![feature(cstr_display)] - /// /// let cstr = c"Hello, world!"; /// println!("{}", cstr.display()); /// ``` - #[unstable(feature = "cstr_display", issue = "139984")] + #[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")] #[must_use = "this does not display the `CStr`; \ it returns an object that can be displayed"] #[inline] @@ -870,27 +868,25 @@ impl FusedIterator for Bytes<'_> {} /// # Examples /// /// ``` -/// #![feature(cstr_display)] -/// /// let s = c"Hello, world!"; /// println!("{}", s.display()); /// ``` /// /// [`Display`]: fmt::Display /// [`format!`]: ../../../std/macro.format.html -#[unstable(feature = "cstr_display", issue = "139984")] +#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")] pub struct Display<'a> { c_str: &'a CStr, } -#[unstable(feature = "cstr_display", issue = "139984")] +#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")] impl fmt::Debug for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(&self.c_str, f) } } -#[unstable(feature = "cstr_display", issue = "139984")] +#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")] impl fmt::Display for Display<'_> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(crate::bstr::ByteStr::from_bytes(self.c_str.to_bytes()), f) diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index fc2430a10edb4..ffa717aa4aa4d 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -47,7 +47,6 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] -#![feature(cstr_display)] #![feature(debug_closure_helpers)] #![feature(dec2flt)] #![feature(duration_constants)] diff --git a/library/std/src/ffi/c_str.rs b/library/std/src/ffi/c_str.rs index 9c3a6758929a8..e35acce2fef81 100644 --- a/library/std/src/ffi/c_str.rs +++ b/library/std/src/ffi/c_str.rs @@ -8,7 +8,7 @@ pub use alloc::ffi::c_str::IntoStringError; pub use alloc::ffi::c_str::{CString, NulError}; #[stable(feature = "rust1", since = "1.0.0")] pub use core::ffi::c_str::CStr; -#[unstable(feature = "cstr_display", issue = "139984")] +#[stable(feature = "cstr_display", since = "CURRENT_RUSTC_VERSION")] pub use core::ffi::c_str::Display; #[stable(feature = "cstr_from_bytes_until_nul", since = "1.69.0")] pub use core::ffi::c_str::FromBytesUntilNulError; diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index baa9f8d769c82..52a87540ac0f0 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -333,7 +333,6 @@ #![feature(core_io)] #![feature(core_io_borrowed_buf)] #![feature(core_io_internals)] -#![feature(cstr_display)] #![feature(cursor_split)] #![feature(derive_const)] #![feature(duration_constants)] From c1259d23980bbfb5cba6d63b14b52b81fb2ee052 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 22:33:26 +0000 Subject: [PATCH 1225/1309] Point at found impl in "not general enough" ``` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | LL | fn tuple_one() | --------- due to a where-clause on `tuple_one`... LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` ... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- compiler/rustc_error_messages/src/lib.rs | 6 +++ .../src/diagnostics/subdiagnostic.rs | 2 +- .../rustc_trait_selection/src/diagnostics.rs | 2 + .../nice_region_error/placeholder_error.rs | 16 ++++++- .../src/error_reporting/traits/ambiguity.rs | 7 ++- .../traits/fulfillment_errors.rs | 23 +++++---- .../src/error_reporting/traits/mod.rs | 2 +- .../src/error_reporting/traits/suggestions.rs | 5 +- .../associated-types-eq-hr.stderr | 48 +++++++++++++++---- ...n-with-leaking-placeholders.current.stderr | 6 ++- .../trait-bounds/hrtb-conflate-regions.stderr | 12 ++++- ...b-exists-forall-trait-contravariant.stderr | 6 ++- .../hrtb-exists-forall-trait-covariant.stderr | 6 ++- .../hrtb-exists-forall-trait-invariant.stderr | 6 ++- .../trait-bounds/hrtb-just-for-static.stderr | 6 ++- .../hrtb-perfect-forwarding.stderr | 6 ++- tests/ui/impl-trait/nested-rpit-hrtb.stderr | 6 ++- 17 files changed, 134 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs index cb3b43aafa155..881f11ff17b0a 100644 --- a/compiler/rustc_error_messages/src/lib.rs +++ b/compiler/rustc_error_messages/src/lib.rs @@ -216,6 +216,12 @@ impl From for MultiSpan { } } +impl From> for MultiSpan { + fn from(span: Option) -> MultiSpan { + MultiSpan::from_spans(span.into_iter().collect()) + } +} + impl From> for MultiSpan { fn from(spans: Vec) -> MultiSpan { MultiSpan::from_spans(spans) diff --git a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs index baf38d2fc381f..058d93e83719a 100644 --- a/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs +++ b/compiler/rustc_macros/src/diagnostics/subdiagnostic.rs @@ -315,7 +315,7 @@ impl<'parent, 'a> SubdiagnosticDeriveVariantBuilder<'parent, 'a> { let binding = info.binding.binding.clone(); // FIXME(#100717): support `Option` on `primary_span` like in the // diagnostic derive - if !matches!(info.ty, FieldInnerTy::Plain(_)) { + if !matches!(info.ty, FieldInnerTy::Plain(_) | FieldInnerTy::Option(_)) { throw_invalid_attr!(attr, |diag| { let diag = diag.note("there must be exactly one primary span"); diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 1b597583d53fc..917f2e83c2282 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1052,6 +1052,8 @@ pub(crate) enum ActualImplExplNotes<'tcx> { trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, has_lifetime: bool, lifetime: usize, + #[primary_span] + span: Option, }, #[note( "...but `{$trait_path}` is actually implemented for the type `{$ty}`{$has_lifetime -> diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 390e21e34ef4c..07b4a142e4014 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -613,7 +613,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let lifetime = actual_has_vid.unwrap_or_default(); let note_2 = if same_self_type { - ActualImplExplNotes::ButActuallyImplementsTrait { trait_path, has_lifetime, lifetime } + let impl_candidates = self.cx.find_similar_impl_candidates( + actual_trait_ref.value.def_id, + actual_trait_ref.value.self_ty(), + ); + let span = if let [candidate] = impl_candidates { + Some(self.tcx().def_span(candidate.impl_def_id)) + } else { + None + }; + ActualImplExplNotes::ButActuallyImplementsTrait { + trait_path, + has_lifetime, + lifetime, + span, + } } else if passive_voice { ActualImplExplNotes::ButActuallyImplementedForTy { trait_path, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 05e1cb6210b50..2a3ddaa54aadd 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -361,8 +361,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { let pred = self.tcx.short_string(predicate, &mut err.long_ty_path()); err.note(format!("cannot satisfy `{pred}`")); } - let impl_candidates = - self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap()); + let clause = predicate.as_trait_clause().unwrap(); + let impl_candidates = self.find_similar_impl_candidates( + clause.def_id(), + clause.self_ty().skip_binder(), + ); if impl_candidates.len() < 40 { self.report_similar_impl_candidates( impl_candidates.as_slice(), diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index ed0ecf459c3b8..3b21c5e5f19ba 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -2121,13 +2121,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } } - pub(super) fn find_similar_impl_candidates( + pub(crate) fn find_similar_impl_candidates( &self, - trait_pred: ty::PolyTraitClause<'tcx>, + trait_def_id: DefId, + self_ty: Ty<'tcx>, ) -> Vec> { let mut candidates: Vec<_> = self .tcx - .all_impls(trait_pred.def_id()) + .all_impls(trait_def_id) .filter_map(|def_id| { let imp = self.tcx.impl_trait_header(def_id); if imp.polarity != ty::ImplPolarity::Positive @@ -2137,9 +2138,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { } let imp = imp.trait_ref.skip_binder(); - self.fuzzy_match_tys(trait_pred.skip_binder().self_ty(), imp.self_ty(), false).map( - |similarity| ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id }, - ) + self.fuzzy_match_tys(self_ty, imp.self_ty(), false).map(|similarity| { + ImplCandidate { trait_ref: imp, similarity, impl_def_id: def_id } + }) }) .collect(); if candidates.iter().any(|c| matches!(c.similarity, CandidateSimilarity::Exact { .. })) { @@ -2772,7 +2773,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { // the user might expect to be presented with. Instead this is // useful for less general traits. if peeled && !self.tcx.trait_is_auto(def_id) && self.tcx.as_lang_item(def_id).is_none() { - let impl_candidates = self.find_similar_impl_candidates(trait_pred); + let impl_candidates = self.find_similar_impl_candidates( + trait_pred.def_id(), + trait_pred.self_ty().skip_binder(), + ); self.report_similar_impl_candidates( &impl_candidates, obligation, @@ -3475,7 +3479,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ); } else if !suggested && trait_predicate.polarity() == ty::ClausePolarity::Positive { // Can't show anything else useful, try to find similar impls. - let impl_candidates = self.find_similar_impl_candidates(trait_predicate); + let impl_candidates = self.find_similar_impl_candidates( + trait_predicate.def_id(), + trait_predicate.self_ty().skip_binder(), + ); if !self.report_similar_impl_candidates( &impl_candidates, obligation, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs index a7a907e8f4d94..1a661270a5d5d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/mod.rs @@ -45,7 +45,7 @@ pub enum CandidateSimilarity { pub struct ImplCandidate<'tcx> { pub trait_ref: ty::TraitRef<'tcx>, pub similarity: CandidateSimilarity, - impl_def_id: DefId, + pub impl_def_id: DefId, } enum GetSafeTransmuteErrorAndReason { diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 9219c709eee83..76755eb481db7 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -1245,7 +1245,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { main_trait_predicate: ty::PolyTraitClause<'tcx>, span: Span, ) -> bool { - let &[candidate] = &self.find_similar_impl_candidates(leaf_trait_predicate)[..] else { + let &[candidate] = &self.find_similar_impl_candidates( + leaf_trait_predicate.def_id(), + leaf_trait_predicate.self_ty().skip_binder(), + )[..] else { return false; }; let candidate = candidate.trait_ref; diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 70596cbab1225..4a24b75700b8b 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -53,7 +53,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -68,7 +72,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough @@ -84,7 +92,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 @@ -99,7 +111,11 @@ LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `TheTrait` is not general enough @@ -115,7 +131,11 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 @@ -130,7 +150,11 @@ LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error[E0308]: mismatched types @@ -175,7 +199,11 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 @@ -190,7 +218,11 @@ LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/associated-types-eq-hr.rs:35:1 + | +LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 12 previous errors diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index 3de229af2a077..f7f000992c06c 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -15,7 +15,11 @@ LL | | }); | |______^ | = note: ...`Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... - = note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` +note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` + --> $DIR/obligation-with-leaking-placeholders.rs:15:1 + | +LL | impl<'a, T> Foo<'a> for Wrap where T: Fn(&'a i32) {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 830ed0638a80d..4111d1f82a89c 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -10,7 +10,11 @@ LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/hrtb-conflate-regions.rs:22:1 + | +LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 @@ -24,7 +28,11 @@ LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... - = note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` +note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` + --> $DIR/hrtb-conflate-regions.rs:22:1 + | +LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index 28ae64dff3e47..d27bf6588cddf 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(&'b u32)>` - = note: ...but it actually implements `Trait`, for some specific lifetime `'0` +note: ...but it actually implements `Trait`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 + | +LL | impl<'a> Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index 4b9d7e1d7109e..0fd20dbb3f0e5 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(fn(&'b u32))>` - = note: ...but it actually implements `Trait`, for some specific lifetime `'0` +note: ...but it actually implements `Trait`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 + | +LL | impl<'a> Trait for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index 45ff3ef758713..eaecabbf544e1 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -11,7 +11,11 @@ LL | foo::<()>(); | ^^^^^^^^^^^ | = note: ...`()` must implement `Trait fn(Cell<&'b u32>)>` - = note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` +note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 + | +LL | impl<'a> Trait)> for () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index 6ba3d119ccb94..1f33e65e7e715 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -10,7 +10,11 @@ LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Foo<&'static isize>` +note: ...but it actually implements `Foo<&'static isize>` + --> $DIR/hrtb-just-for-static.rs:22:1 + | +LL | impl Foo<&'static isize> for StaticInt { } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: lifetime may not live long enough --> $DIR/hrtb-just-for-static.rs:30:5 diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index db22eeb46aef0..2b68dced8af0d 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -66,7 +66,11 @@ LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ | = note: ...`T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... - = note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` +note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` + --> $DIR/hrtb-perfect-forwarding.rs:14:1 + | +LL | impl<'a, X, F> Bar for &'a mut F where F: Bar {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ warning: function cannot return without recursing --> $DIR/hrtb-perfect-forwarding.rs:48:1 diff --git a/tests/ui/impl-trait/nested-rpit-hrtb.stderr b/tests/ui/impl-trait/nested-rpit-hrtb.stderr index 6c1253678e991..1f21373210a6d 100644 --- a/tests/ui/impl-trait/nested-rpit-hrtb.stderr +++ b/tests/ui/impl-trait/nested-rpit-hrtb.stderr @@ -102,7 +102,11 @@ LL | fn one_hrtb_mention_fn_outlives_uses<'b>() -> impl for<'a> Bar<'a, Assoc = | ^^ implementation of `Bar` is not general enough | = note: `()` must implement `Bar<'a>` - = note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` +note: ...but it actually implements `Bar<'0>`, for some specific lifetime `'0` + --> $DIR/nested-rpit-hrtb.rs:16:1 + | +LL | impl<'a> Bar<'a> for () { + | ^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `for<'a, 'b> &'a (): Qux<'b>` is not satisfied --> $DIR/nested-rpit-hrtb.rs:60:64 From 3862c503043e2f26648b8fd634ba8854958aa266 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:04:22 +0000 Subject: [PATCH 1226/1309] Tweak "not general enough" rendering Use a span note instead of span labels so that when talking about the trait that should have been implemented, we always point at where the obligation was introduced in a consistent place. ``` error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ``` --- .../rustc_trait_selection/src/diagnostics.rs | 198 +++++++++--------- .../nice_region_error/placeholder_error.rs | 28 ++- .../associated-types-eq-hr.stderr | 120 ++++++----- ...outine-auto-trait-span-issue-155880.stderr | 13 +- ...olved-typeck-results.no_assumptions.stderr | 26 +-- ...ranked-auto-trait-12.no_assumptions.stderr | 13 +- ...er-ranked-auto-trait-13.assumptions.stderr | 52 ++--- ...ranked-auto-trait-13.no_assumptions.stderr | 78 +++---- ...ranked-auto-trait-15.no_assumptions.stderr | 26 +-- ...er-ranked-auto-trait-16.assumptions.stderr | 26 +-- ...ranked-auto-trait-16.no_assumptions.stderr | 26 +-- ...-ranked-auto-trait-5.no_assumptions.stderr | 15 +- .../issue-110963-early.no_assumptions.stderr | 30 +-- ...ation-not-general-enough-ice-133252.stderr | 11 +- ...n-with-leaking-placeholders.current.stderr | 15 +- ...rtb-closure-suggest-type-annotation.stderr | 30 +-- tests/ui/coroutine/auto-trait-regions.stderr | 26 +-- .../ui/coroutine/resume-arg-late-bound.stderr | 13 +- ...ot-checked-with-right-substitutions.stderr | 13 +- ...hr-fn-ptr-trait-impl-mismatch-29061.stderr | 39 ++-- ...tb-associated-type-leak-check-55731.stderr | 15 +- ...n-ptr-impl-not-general-enough-57936.stderr | 13 +- .../trait-bounds/hrtb-conflate-regions.stderr | 26 +-- ...b-exists-forall-trait-contravariant.stderr | 15 +- .../hrtb-exists-forall-trait-covariant.stderr | 15 +- .../hrtb-exists-forall-trait-invariant.stderr | 15 +- .../trait-bounds/hrtb-just-for-static.stderr | 13 +- .../hrtb-perfect-forwarding.stderr | 15 +- .../trait-bounds/issue-46989.stderr | 13 +- .../trait-bounds/issue-59311.stderr | 30 +-- .../issue-71955.current.stderr | 60 +++--- tests/ui/lifetimes/issue-105675.stderr | 78 +++---- tests/ui/lifetimes/issue-79187-2.stderr | 26 +-- tests/ui/lifetimes/issue-79187.stderr | 26 +-- .../lifetime-errors/issue_74400.stderr | 22 +- .../closure-arg-type-mismatch.stderr | 26 +-- .../closure-mismatch.current.stderr | 52 ++--- tests/ui/nll/ice-106874.stderr | 54 ++--- tests/ui/nll/issue-54302-cases.stderr | 44 ++-- ...missing-universe-cause-issue-114907.stderr | 52 ++--- ...insensitive-scopes-issue-117146.nll.stderr | 22 +- ...sitive-scopes-issue-117146.polonius.stderr | 22 +- .../impl-fn-ignore-binder-via-bottom.stderr | 22 +- tests/ui/unboxed-closures/issue-30906.stderr | 13 +- .../ui/where-clauses/where-for-self-2.stderr | 15 +- 45 files changed, 797 insertions(+), 705 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 917f2e83c2282..9d2238c188157 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -912,133 +912,123 @@ impl IntoDiagArg for TyOrSig<'_> { #[derive(Subdiagnostic)] pub(crate) enum ActualImplExplNotes<'tcx> { - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any two \ + lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`..." + )] ExpectedSignatureTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime \ + `'{$lifetime_1}`..." + )] ExpectedSignatureAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`...")] + #[note( + "closure with signature `{$ty_or_sig}` must implement `{$trait_path}`, for some specific \ + lifetime `'{$lifetime_1}`..." + )] ExpectedSignatureSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }closure with signature `{$ty_or_sig}` must implement `{$trait_path}`" - )] + #[note("closure with signature `{$ty_or_sig}` must implement `{$trait_path}`")] ExpectedSignatureNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any two \ + lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`..." + )] ExpectedPassiveTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any lifetime `'{$lifetime_1}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for any \ + lifetime `'{$lifetime_1}`..." + )] ExpectedPassiveAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some specific lifetime `'{$lifetime_1}`...")] + #[note( + "`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`, for some \ + specific lifetime `'{$lifetime_1}`..." + )] ExpectedPassiveSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`" - )] + #[note("`{$trait_path}` would have to be implemented for the type `{$ty_or_sig}`")] ExpectedPassiveNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, - #[note("{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and `'{$lifetime_2}`...")] + #[note( + "`{$ty_or_sig}` must implement `{$trait_path}`, for any two lifetimes `'{$lifetime_1}` and \ + `'{$lifetime_2}`..." + )] ExpectedOtherTwo { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`..." - )] + #[note("`{$ty_or_sig}` must implement `{$trait_path}`, for any lifetime `'{$lifetime_1}`...")] ExpectedOtherAny { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime `'{$lifetime_1}`..." + "`{$ty_or_sig}` must implement `{$trait_path}`, for some specific lifetime \ + `'{$lifetime_1}`..." )] ExpectedOtherSome { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, }, - #[note( - "{$leading_ellipsis -> - [true] ... - *[false] {\"\"} - }`{$ty_or_sig}` must implement `{$trait_path}`" - )] + #[note("`{$ty_or_sig}` must implement `{$trait_path}`")] ExpectedOtherNothing { - leading_ellipsis: bool, + #[primary_span] + span: MultiSpan, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, }, @@ -1098,66 +1088,71 @@ impl<'tcx> ActualImplExplNotes<'tcx> { pub(crate) fn new_expected( kind: ActualImplExpectedKind, lt_kind: ActualImplExpectedLifetimeKind, - leading_ellipsis: bool, ty_or_sig: TyOrSig<'tcx>, trait_path: Highlighted<'tcx, TraitRefPrintOnlyTraitPath<'tcx>>, lifetime_1: usize, lifetime_2: usize, + satisfy_span: Option, + item_span: Option, + item_name: String, ) -> Self { + let label = format!("unsatisfied where-clause on `{item_name}`"); + let item_label = format!("due to a where-clause on `{item_name}`"); + let span = match (satisfy_span, item_span) { + (Some(satisfy_span), Some(item_span)) => { + let mut span = MultiSpan::from(satisfy_span); + span.push_span_label(satisfy_span, label); + span.push_span_label(item_span, item_label); + span + } + (None, Some(item_span)) => { + let mut span = MultiSpan::from(item_span); + span.push_span_label(item_span, item_label); + span + } + (Some(satisfy_span), None) => { + let mut span = MultiSpan::from(satisfy_span); + span.push_span_label(satisfy_span, label); + span + } + _ => MultiSpan::from(vec![]), + }; match (kind, lt_kind) { (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedSignatureTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedSignatureTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedSignatureAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedSignatureAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedSignatureSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedSignatureSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedSignatureNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedSignatureNothing { span, ty_or_sig, trait_path } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedPassiveTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedPassiveTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedPassiveAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedPassiveAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedPassiveSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedPassiveSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Passive, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedPassiveNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedPassiveNothing { span, ty_or_sig, trait_path } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Two) => { - Self::ExpectedOtherTwo { - leading_ellipsis, - ty_or_sig, - trait_path, - lifetime_1, - lifetime_2, - } + Self::ExpectedOtherTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Any) => { - Self::ExpectedOtherAny { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedOtherAny { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Some) => { - Self::ExpectedOtherSome { leading_ellipsis, ty_or_sig, trait_path, lifetime_1 } + Self::ExpectedOtherSome { span, ty_or_sig, trait_path, lifetime_1 } } (ActualImplExpectedKind::Other, ActualImplExpectedLifetimeKind::Nothing) => { - Self::ExpectedOtherNothing { leading_ellipsis, ty_or_sig, trait_path } + Self::ExpectedOtherNothing { span, ty_or_sig, trait_path } } } } @@ -1168,13 +1163,8 @@ impl<'tcx> ActualImplExplNotes<'tcx> { pub(crate) struct TraitPlaceholderMismatch<'tcx> { #[primary_span] pub span: Span, - #[label("unsatisfied where-clause on `{$def_id}`")] - pub satisfy_span: Option, - #[label("due to a where-clause on `{$def_id}`...")] - pub where_span: Option, #[label("implementation of `{$trait_def_id}` is not general enough")] pub dup_span: Option, - pub def_id: String, pub trait_def_id: String, #[subdiagnostic] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 07b4a142e4014..1b57e3d77d503 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -8,7 +8,7 @@ use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; use rustc_middle::ty::{self, GenericArgsRef, IsSuggestable, RePlaceholder, Region, TyCtxt}; -use rustc_span::bug; +use rustc_span::{Span, bug}; use rustc_structures::Limit; use tracing::{debug, instrument}; @@ -279,13 +279,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _ => break, } } - let (leading_ellipsis, satisfy_span, where_span, dup_span, def_id) = + let (mut satisfy_span, mut item_span, dup_span, item_name) = if let ObligationCauseCode::WhereClause(def_id, span) | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code && def_id != CRATE_DEF_ID.to_def_id() { ( - true, Some(span), Some( self.tcx() @@ -296,8 +295,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { self.tcx().def_path_str(def_id), ) } else { - (false, None, None, Some(span), String::new()) + (None, None, Some(span), String::new()) }; + if let Some(span) = satisfy_span && span.is_dummy() { + satisfy_span = None; + } + if let Some(span) = item_span && span.is_dummy() { + item_span = None; + } let expected_trait_ref = self.cx.deeply_resolve_ignoring_regions( ty::TraitRef::new_from_args(self.cx.tcx, trait_def_id, expected_args), @@ -369,15 +374,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { expected_has_vid, actual_has_vid, any_self_ty_has_vid, - leading_ellipsis, + satisfy_span, + item_span, + item_name, ); let mut err = self.tcx().dcx().create_err(TraitPlaceholderMismatch { span, - satisfy_span, - where_span, dup_span, - def_id, trait_def_id: self.tcx().def_path_str(trait_def_id), actual_impl_expl_notes, }); @@ -494,7 +498,9 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { expected_has_vid: Option, actual_has_vid: Option, any_self_ty_has_vid: bool, - leading_ellipsis: bool, + satisfy_span: Option, + item_span: Option, + item_name: String, ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the // the match inside is meant to be like this: @@ -592,11 +598,13 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let note_1 = ActualImplExplNotes::new_expected( kind, lt_kind, - leading_ellipsis, ty_or_sig, trait_path, lifetime_1, lifetime_2, + satisfy_span, + item_span, + item_name, ); let mut actual_trait_ref = highlight_trait_ref(actual_trait_ref); diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 4a24b75700b8b..19fd633334f00 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -43,16 +43,17 @@ LL | T: for<'x> TheTrait<&'x isize, A = &'x usize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:8 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -62,16 +63,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:8 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -82,16 +84,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:53 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -101,16 +104,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:96:5 | -LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ------------- unsatisfied where-clause on `tuple_one` -... LL | tuple_one::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:59:53 + | +LL | fn tuple_one() + | --------- due to a where-clause on `tuple_one` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, + | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -121,16 +125,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | -LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` -... LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:66:8 + | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -140,16 +145,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:104:5 | -LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ----------------------------------------------------------- unsatisfied where-clause on `tuple_two` -... LL | tuple_two::(); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:66:8 + | +LL | fn tuple_two() + | --------- due to a where-clause on `tuple_two` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -189,16 +195,17 @@ LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | -LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | -------------------------------------------- unsatisfied where-clause on `tuple_four` -... LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:80:8 + | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -208,16 +215,17 @@ LL | impl<'a> TheTrait<(&'a isize, &'a isize)> for Tuple { error: implementation of `TheTrait` is not general enough --> $DIR/associated-types-eq-hr.rs:116:5 | -LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four`... -LL | where -LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | -------------------------------------------- unsatisfied where-clause on `tuple_four` -... LL | tuple_four::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/associated-types-eq-hr.rs:80:8 + | +LL | fn tuple_four() + | ---------- due to a where-clause on `tuple_four` +LL | where +LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr index e7f5413cdaaa0..893124920ee18 100644 --- a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -7,15 +7,16 @@ LL | | std::future::ready(x).await LL | | } | |_- this async fn captures a value whose type is not `Send` ... -LL | fn is_send(_: T) {} - | ------- ---- unsatisfied where-clause on `is_send` - | | - | due to a where-clause on `is_send`... -... LL | is_send(outer()) | ^^^^^^^^^^^^^^^^ | - = note: ...`Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... +note: `Send` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + --> $DIR/coroutine-auto-trait-span-issue-155880.rs:25:15 + | +LL | fn is_send(_: T) {} + | ------- ^^^^ unsatisfied where-clause on `is_send` + | | + | due to a where-clause on `is_send` = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr index 01b99e203c426..da93d5a17547a 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | -LL | fn send(_: T) {} - | ---- ---- unsatisfied where-clause on `send` - | | - | due to a where-clause on `send`... -... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ | - = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... +note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 + | +LL | fn send(_: T) {} + | ---- ^^^^ unsatisfied where-clause on `send` + | | + | due to a where-clause on `send` = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough --> $DIR/drop-tracking-unresolved-typeck-results.rs:102:5 | -LL | fn send(_: T) {} - | ---- ---- unsatisfied where-clause on `send` - | | - | due to a where-clause on `send`... -... LL | / send(async { LL | | Next(&Buffered(Map(Empty(PhantomData), ready::<&()>), FuturesOrdered(PhantomData), 0)).await LL | | }); | |______^ | - = note: ...`fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... +note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implement `FnOnce<(&'1 (),)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 + | +LL | fn send(_: T) {} + | ---- ^^^^ unsatisfied where-clause on `send` + | | + | due to a where-clause on `send` = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr index fd91fd659ac4d..39132cc9b4fb9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -1,11 +1,6 @@ error: implementation of `Robot` is not general enough --> $DIR/higher-ranked-auto-trait-12.rs:31:20 | -LL | fn this_is_send(value: T) -> T { - | ------------ ---- unsatisfied where-clause on `this_is_send` - | | - | due to a where-clause on `this_is_send`... -... LL | let _my_task = this_is_send(async move { | ____________________^ LL | | let _my_iter = IRobot { @@ -16,7 +11,13 @@ LL | | yield_now().await; LL | | }); | |______^ | - = note: ...`Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... +note: `Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-12.rs:24:20 + | +LL | fn this_is_send(value: T) -> T { + | ------------ ^^^^ unsatisfied where-clause on `this_is_send` + | | + | due to a where-clause on `this_is_send` = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot + Send + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr index abc8ba5e7afa3..386a83ebbc761 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -1,58 +1,62 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index 7c8edb40ac62f..02f91c47fffcb 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -1,87 +1,93 @@ error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... +note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:24 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... +note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, ConstructableImpl<'_>>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` error: implementation of `Callable` is not general enough --> $DIR/higher-ranked-auto-trait-13.rs:65:5 | -LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | assert_send(my_send_async_method(struct_with_lifetime, data)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... +note: `Callable<'_>` would have to be implemented for the type `ConstructableImpl<'0>`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-13.rs:52:31 + | +LL | fn assert_send(_: impl Send + Sync) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index fa6dd575527f8..c6c8479474c64 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | -LL | fn require_send(_x: T) {} - | ------------ ---- unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send`... -... LL | require_send(future); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... +note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-15.rs:16:20 + | +LL | fn require_send(_x: T) {} + | ------------ ^^^^ unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | for _ in things.iter().map(|n: &Vec| n.iter()).flatten() { error: implementation of `FnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-15.rs:20:5 | -LL | fn require_send(_x: T) {} - | ------------ ---- unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send`... -... LL | require_send(future); | ^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... +note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce<(&'1 Vec,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-15.rs:16:20 + | +LL | fn require_send(_x: T) {} + | ------------ ^^^^ unsatisfied where-clause on `require_send` + | | + | due to a where-clause on `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr index 69e356703c9f0..52c54f8355c39 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr index 69e356703c9f0..52c54f8355c39 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -1,33 +1,35 @@ error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough --> $DIR/higher-ranked-auto-trait-16.rs:18:5 | -LL | fn assert_send(_: T) {} - | ----------- ---- unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send`... -... LL | / assert_send(async { LL | | commit_if_ok(&mut ctxt, async |_| todo!()).await; LL | | }); | |______^ | - = note: ...`{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... +note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/higher-ranked-auto-trait-16.rs:8:19 + | +LL | fn assert_send(_: T) {} + | ----------- ^^^^ unsatisfied where-clause on `assert_send` + | | + | due to a where-clause on `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index ef743392cb014..6119247429e28 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -5,14 +5,15 @@ LL | / assert_send(async { LL | | call_me.call().await; LL | | }); | |______^ -... -LL | pub fn assert_send(_future: F) - | ----------- due to a where-clause on `assert_send`... -LL | where -LL | F: Future + Send, - | ---- unsatisfied where-clause on `assert_send` | - = note: ...`Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... +note: `Send` would have to be implemented for the type `&'0 str`, for any lifetime `'0`... + --> $DIR/higher-ranked-auto-trait-5.rs:20:17 + | +LL | pub fn assert_send(_future: F) + | ----------- due to a where-clause on `assert_send` +LL | where +LL | F: Future + Send, + | ^^^^ unsatisfied where-clause on `assert_send` = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index be635809f1db7..889d3c2948d61 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -11,14 +11,15 @@ LL | | log_health_check_failure().await; LL | | } LL | | }); | |______^ -... -LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn`... -LL | where -LL | F: Future + Send + 'static, - | ---- unsatisfied where-clause on `spawn` | - = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... +note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + --> $DIR/issue-110963-early.rs:37:17 + | +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn` +LL | where +LL | F: Future + Send + 'static, + | ^^^^ unsatisfied where-clause on `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` error: implementation of `Send` is not general enough @@ -34,14 +35,15 @@ LL | | log_health_check_failure().await; LL | | } LL | | }); | |______^ -... -LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn`... -LL | where -LL | F: Future + Send + 'static, - | ---- unsatisfied where-clause on `spawn` | - = note: ...`Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... +note: `Send` would have to be implemented for the type `impl Future { ::check<'0>(..) }`, for any two lifetimes `'0` and `'1`... + --> $DIR/issue-110963-early.rs:37:17 + | +LL | fn spawn(future: F) -> JoinHandle + | ----- due to a where-clause on `spawn` +LL | where +LL | F: Future + Send + 'static, + | ^^^^ unsatisfied where-clause on `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index b5ea0003b1d63..beb349c94bd1a 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -3,13 +3,14 @@ error: implementation of `LoadQuery` is not general enough | LL | force_send(async_load(¬_static)); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: `LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... + --> $DIR/implementation-not-general-enough-ice-133252.rs:16:18 + | LL | fn force_send(_: T) {} - | ---------- ---- unsatisfied where-clause on `force_send` + | ---------- ^^^^ unsatisfied where-clause on `force_send` | | - | due to a where-clause on `force_send`... - | - = note: ...`LoadQuery<'0>` would have to be implemented for the type `&u8`, for any lifetime `'0`... + | due to a where-clause on `force_send` = note: ...but `LoadQuery<'1>` is actually implemented for the type `&'1 u8`, for some specific lifetime `'1` error[E0597]: `not_static` does not live long enough diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index f7f000992c06c..5f8198ec6bed9 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -1,12 +1,6 @@ error: implementation of `Foo` is not general enough --> $DIR/obligation-with-leaking-placeholders.rs:18:5 | -LL | fn needs_foo(_: T) - | --------- due to a where-clause on `needs_foo`... -LL | where -LL | for<'a> Wrap: Foo<'a>, - | ------- unsatisfied where-clause on `needs_foo` -... LL | / needs_foo(|x| { LL | | LL | | @@ -14,7 +8,14 @@ LL | | x.to_string(); LL | | }); | |______^ | - = note: ...`Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... +note: `Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... + --> $DIR/obligation-with-leaking-placeholders.rs:10:22 + | +LL | fn needs_foo(_: T) + | --------- due to a where-clause on `needs_foo` +LL | where +LL | for<'a> Wrap: Foo<'a>, + | ^^^^^^^ unsatisfied where-clause on `needs_foo` note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` --> $DIR/obligation-with-leaking-placeholders.rs:15:1 | diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr index b918a5c5179c8..5f7636bb34a0e 100644 --- a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -1,16 +1,17 @@ error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | -LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner`... -LL | where -LL | F: FnOnce(&mut [u8]) -> Result, - | ----------------------------------------- unsatisfied where-clause on `inner` -... LL | inner(buf, outer_closure) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:8 + | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner` +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -20,16 +21,17 @@ LL | let outer_closure = |buf: &mut [u8]| { error: implementation of `FnOnce` is not general enough --> $DIR/hrtb-closure-suggest-type-annotation.rs:33:5 | -LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner`... -LL | where -LL | F: FnOnce(&mut [u8]) -> Result, - | -------------------- unsatisfied where-clause on `inner` -... LL | inner(buf, outer_closure) | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 mut [u8]) -> Result` must implement `FnOnce<(&'1 mut [u8],)>`, for any lifetime `'1`... + --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:29 + | +LL | fn inner(buf: &mut [u8], func: F) -> usize + | ----- due to a where-clause on `inner` +LL | where +LL | F: FnOnce(&mut [u8]) -> Result, + | ^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 566f71d89c28d..25f6373124d34 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -1,18 +1,19 @@ error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:31:5 | -LL | fn assert_foo(f: T) {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... +note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... + --> $DIR/auto-trait-regions.rs:21:18 + | +LL | fn assert_foo(f: T) {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error[E0626]: borrow may still be in use when coroutine yields @@ -50,18 +51,19 @@ LL | let generator = #[coroutine] static move || { error: implementation of `Foo` is not general enough --> $DIR/auto-trait-regions.rs:51:5 | -LL | fn assert_foo(f: T) {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | let generator = #[coroutine] move || { | ------- this coroutine captures a value whose type is not `Foo` ... LL | assert_foo(generator); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... +note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two lifetimes `'0` and `'1`... + --> $DIR/auto-trait-regions.rs:21:18 + | +LL | fn assert_foo(f: T) {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index bc1f1d29edd61..b44a8e363128f 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -1,15 +1,16 @@ error: implementation of `Coroutine` is not general enough --> $DIR/resume-arg-late-bound.rs:15:5 | -LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} - | ---- ------------------------------- unsatisfied where-clause on `test` - | | - | due to a where-clause on `test`... -... LL | test(gen); | ^^^^^^^^^ | - = note: ...`{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... +note: `{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifetime `'1`... + --> $DIR/resume-arg-late-bound.rs:8:17 + | +LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` + | | + | due to a where-clause on `test` = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 42aa33c0be186..92d39c70137ce 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -1,15 +1,16 @@ error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | -LL | type Gat<'a>: for<'b> Lengthen>; - | --- ------------------------------- unsatisfied where-clause on `Gat::Gat` - | | - | due to a where-clause on `Gat::Gat`... -... LL | type Gat<'a> = &'a str; | ^^^^^^^ | - = note: ...`Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... +note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... + --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 + | +LL | type Gat<'a>: for<'b> Lengthen>; + | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Gat::Gat` + | | + | due to a where-clause on `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` note: required by a bound in `Gat::Gat` --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 diff --git a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr index 7c3fcf47e6a40..16c1b69d3b053 100644 --- a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr +++ b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr @@ -1,43 +1,46 @@ error: implementation of `HR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:25:5 | -LL | fn hr(_: T) {} - | -- -- unsatisfied where-clause on `hr` - | | - | due to a where-clause on `hr`... -... LL | hr(not_hr_func); | ^^^^^^^^^^^^^^^ | - = note: ...`HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... +note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some specific lifetime `'0`... + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:15:10 + | +LL | fn hr(_: T) {} + | -- ^^ unsatisfied where-clause on `hr` + | | + | due to a where-clause on `hr` = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:27:5 | -LL | fn not_hr(_: T) {} - | ------ ----- unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr`... -... LL | not_hr(hr_func); | ^^^^^^^^^^^^^^^ | - = note: ...`NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` +note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 + | +LL | fn not_hr(_: T) {} + | ------ ^^^^^ unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `NotHR` is not general enough --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:29:5 | -LL | fn not_hr(_: T) {} - | ------ ----- unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr`... -... LL | not_hr(hr_func2); | ^^^^^^^^^^^^^^^^ | - = note: ...`NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` +note: `NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` + --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 + | +LL | fn not_hr(_: T) {} + | ------ ^^^^^ unsatisfied where-clause on `not_hr` + | | + | due to a where-clause on `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr index eaa82c3f77871..d3e10e7a18d20 100644 --- a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr +++ b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr @@ -1,19 +1,20 @@ error: implementation of `DistributedIteratorMulti` is not general enough --> $DIR/hrtb-associated-type-leak-check-55731.rs:49:5 | -LL | fn multi(_reducer: I) - | ----- due to a where-clause on `multi`... -LL | where -LL | I: for<'a> DistributedIteratorMulti<&'a ()>, - | ---------------------------------------- unsatisfied where-clause on `multi` -... LL | / multi(Map { LL | | i: Cloned(PhantomData), LL | | f: X, LL | | }); | |______^ | - = note: ...`DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... +note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`... + --> $DIR/hrtb-associated-type-leak-check-55731.rs:43:8 + | +LL | fn multi(_reducer: I) + | ----- due to a where-clause on `multi` +LL | where +LL | I: for<'a> DistributedIteratorMulti<&'a ()>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `multi` = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr index afed0bca3fffe..f7a9020c59e24 100644 --- a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr +++ b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr @@ -14,15 +14,16 @@ LL | trait X { error: implementation of `X` is not general enough --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:26:5 | -LL | fn indirect() { - | -------- - unsatisfied where-clause on `indirect` - | | - | due to a where-clause on `indirect`... -... LL | indirect::(); | ^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`X` would have to be implemented for the type `for<'a> fn(&'a ())` +note: `X` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:21:16 + | +LL | fn indirect() { + | -------- ^ unsatisfied where-clause on `indirect` + | | + | due to a where-clause on `indirect` = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 4111d1f82a89c..6700778198712 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2`... -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- unsatisfied where-clause on `want_foo2` -... LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/hrtb-conflate-regions.rs:9:15 + | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2` +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | @@ -19,15 +20,16 @@ LL | impl<'a> Foo<(&'a isize, &'a isize)> for SomeStruct error: implementation of `Foo` is not general enough --> $DIR/hrtb-conflate-regions.rs:27:10 | -LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2`... -LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | -------------------------------------- unsatisfied where-clause on `want_foo2` -... LL | fn b() { want_foo2::(); } | ^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... +note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lifetimes `'0` and `'1`... + --> $DIR/hrtb-conflate-regions.rs:9:15 + | +LL | fn want_foo2() + | --------- due to a where-clause on `want_foo2` +LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index d27bf6588cddf..e600c49d564be 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-contravariant.rs:34:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(&'b u32)>, - | -------------------------- unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(&'b u32)>` +note: `()` must implement `Trait fn(&'b u32)>` + --> $DIR/hrtb-exists-forall-trait-contravariant.rs:10:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(&'b u32)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index 0fd20dbb3f0e5..dd720d9989060 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-covariant.rs:33:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(fn(&'b u32))>, - | ------------------------------ unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(fn(&'b u32))>` +note: `()` must implement `Trait fn(fn(&'b u32))>` + --> $DIR/hrtb-exists-forall-trait-covariant.rs:10:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(fn(&'b u32))>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index eaecabbf544e1..446a3102a0938 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -1,16 +1,17 @@ error: implementation of `Trait` is not general enough --> $DIR/hrtb-exists-forall-trait-invariant.rs:28:5 | -LL | fn foo() - | --- due to a where-clause on `foo`... -LL | where -LL | T: Trait fn(Cell<&'b u32>)>, - | -------------------------------- unsatisfied where-clause on `foo` -... LL | foo::<()>(); | ^^^^^^^^^^^ | - = note: ...`()` must implement `Trait fn(Cell<&'b u32>)>` +note: `()` must implement `Trait fn(Cell<&'b u32>)>` + --> $DIR/hrtb-exists-forall-trait-invariant.rs:12:8 + | +LL | fn foo() + | --- due to a where-clause on `foo` +LL | where +LL | T: Trait fn(Cell<&'b u32>)>, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index 1f33e65e7e715..cdfcd30d44fb2 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/hrtb-just-for-static.rs:24:5 | -LL | fn want_hrtb() - | --------- due to a where-clause on `want_hrtb`... -LL | where T : for<'a> Foo<&'a isize> - | ---------------------- unsatisfied where-clause on `want_hrtb` -... LL | want_hrtb::() | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... +note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... + --> $DIR/hrtb-just-for-static.rs:9:15 + | +LL | fn want_hrtb() + | --------- due to a where-clause on `want_hrtb` +LL | where T : for<'a> Foo<&'a isize> + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_hrtb` note: ...but it actually implements `Foo<&'static isize>` --> $DIR/hrtb-just-for-static.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index 2b68dced8af0d..da60e78d2f389 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -56,16 +56,17 @@ LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, error: implementation of `Bar` is not general enough --> $DIR/hrtb-perfect-forwarding.rs:43:5 | -LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) - | ---------------- due to a where-clause on `foo_hrtb_bar_not`... -LL | where -LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, - | ---------------------- unsatisfied where-clause on `foo_hrtb_bar_not` -... LL | foo_hrtb_bar_not(&mut t); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... +note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... + --> $DIR/hrtb-perfect-forwarding.rs:37:8 + | +LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) + | ---------------- due to a where-clause on `foo_hrtb_bar_not` +LL | where +LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, + | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo_hrtb_bar_not` note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` --> $DIR/hrtb-perfect-forwarding.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index e1d900f20ce3b..23cba27a2fc00 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -1,15 +1,16 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-46989.rs:38:5 | -LL | fn assert_foo() {} - | ---------- --- unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo`... -... LL | assert_foo::(); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` +note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` + --> $DIR/issue-46989.rs:35:18 + | +LL | fn assert_foo() {} + | ---------- ^^^ unsatisfied where-clause on `assert_foo` + | | + | due to a where-clause on `assert_foo` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index f7b72ec65db3f..9145a693c95c8 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -1,31 +1,33 @@ error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash`... -LL | where -LL | for<'a> &'a V: Trait + 'static, - | ----- unsatisfied where-clause on `crash` -LL | { LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: ...`Trait` would have to be implemented for the type `&'a V` +note: `Trait` would have to be implemented for the type `&'a V` + --> $DIR/issue-59311.rs:15:20 + | +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash` +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ^^^^^ unsatisfied where-clause on `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` error: implementation of `Trait` is not general enough --> $DIR/issue-59311.rs:17:5 | -LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash`... -LL | where -LL | for<'a> &'a V: Trait + 'static, - | ----- unsatisfied where-clause on `crash` -LL | { LL | v.t(|| {}); | ^^^^^^^^^^ | - = note: ...`Trait` would have to be implemented for the type `&'a V` +note: `Trait` would have to be implemented for the type `&'a V` + --> $DIR/issue-59311.rs:15:20 + | +LL | pub fn crash(v: &V) + | ----- due to a where-clause on `crash` +LL | where +LL | for<'a> &'a V: Trait + 'static, + | ^^^^^ unsatisfied where-clause on `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr index 83a7a9836a1ad..6dd203ac806e5 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr @@ -1,16 +1,17 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:47:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---------------------------------------------------------- unsatisfied where-clause on `foo` -... LL | foo(bar, |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:9 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -20,16 +21,17 @@ LL | foo(bar, |s: &'b &'c str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:47:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---- unsatisfied where-clause on `foo` -... LL | foo(bar, |s| s.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `FnOnce<(&'b &'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:63 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -39,16 +41,17 @@ LL | foo(bar, |s: &'b &'c str| s.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:50:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---------------------------------------------------------- unsatisfied where-clause on `foo` -... LL | foo(baz, |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:9 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -58,16 +61,17 @@ LL | foo(baz, |s: &'b Wrapper<'c>| s.0.len() == 5); error: implementation of `FnOnce` is not general enough --> $DIR/issue-71955.rs:50:5 | -LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo`... -... -LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ---- unsatisfied where-clause on `foo` -... LL | foo(baz, |s| s.0.len() == 5); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implement `FnOnce<(&'b Wrapper<'1>,)>`, for any lifetime `'1`... + --> $DIR/issue-71955.rs:32:63 + | +LL | fn foo(f1: F1, f2: F2) + | --- due to a where-clause on `foo` +... +LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, + | ^^^^ unsatisfied where-clause on `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 18960ff575a2a..995c3604ca6e0 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding explicit type annotations to the closure's arguments | @@ -19,15 +20,16 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding explicit type annotations to the closure's arguments @@ -38,15 +40,16 @@ LL | let f = | _: &u32 , y: &u32 , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -56,15 +59,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -74,15 +78,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&'1 u32, &u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -93,15 +98,16 @@ LL | let f = | x: &u32, y: _ , z: u32 | (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-105675.rs:9:5 | -LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ----------------------- unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... +note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u32, &'1 u32, u32)>`, for any lifetime `'1`... + --> $DIR/issue-105675.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} + | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 7029eeafef0eb..4b2799812fe90 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187-2.rs:8:5 | -LL | fn take_foo(_: impl Foo) {} - | -------- --- unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo`... -... LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | -------- ^^^ unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo` = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | take_foo(|a: &i32| a); error: implementation of `Fn` is not general enough --> $DIR/issue-79187-2.rs:8:5 | -LL | fn take_foo(_: impl Foo) {} - | -------- --- unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo`... -... LL | take_foo(|a| a); | ^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187-2.rs:5:21 + | +LL | fn take_foo(_: impl Foo) {} + | -------- ^^^ unsatisfied where-clause on `take_foo` + | | + | due to a where-clause on `take_foo` = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 3dbb6054a7ad3..2377c4d5ba5f3 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ------------ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | let f = |_: &u32| (); error: implementation of `FnOnce` is not general enough --> $DIR/issue-79187.rs:5:5 | -LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ------------ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing`... -... LL | thing(f); | ^^^^^^^^ | - = note: ...closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, for any lifetime `'1`... + --> $DIR/issue-79187.rs:1:18 + | +LL | fn thing(x: impl FnOnce(&u32)) {} + | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` + | | + | due to a where-clause on `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 3a293cc4b2516..5670dc4ea00f7 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -45,27 +45,29 @@ LL | fn g(data: &[T]) { error: implementation of `Fn` is not general enough --> $DIR/issue_74400.rs:12:5 | -LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - ----------- unsatisfied where-clause on `f` - | | - | due to a where-clause on `f`... -... LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... +note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, for any lifetime `'1`... + --> $DIR/issue_74400.rs:8:34 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - ^^^^^^^^^^^ unsatisfied where-clause on `f` + | | + | due to a where-clause on `f` = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/issue_74400.rs:12:5 | -LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - due to a where-clause on `f`... - unsatisfied where-clause on `f` -... LL | f(data, identity) | ^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... +note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>`, for any lifetime `'1`... + --> $DIR/issue_74400.rs:8:44 + | +LL | fn f(data: &[T], key: impl Fn(&T) -> S) { + | - due to a where-clause on `f` ^ unsatisfied where-clause on `f` = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 856aba98d1c4c..72945d962a570 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -66,29 +66,31 @@ LL | fn baz(_: F) {} error: implementation of `Fn` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | --- ------------- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^^^^ | - = note: ...`fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... +note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime `'1`... + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough --> $DIR/closure-arg-type-mismatch.rs:10:5 | -LL | fn baz(_: F) {} - | --- ------------- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -LL | fn _test<'a>(f: fn(*mut &'a u32)) { LL | baz(f); | ^^^^^^ | - = note: ...`fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... +note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifetime `'1`... + --> $DIR/closure-arg-type-mismatch.rs:8:11 + | +LL | fn baz(_: F) {} + | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 0dbefa4b2aa19..0249537dcba54 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:12:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|_| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | baz(|_: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:12:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|_| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -37,15 +39,16 @@ LL | baz(|_: &()| ()); error: implementation of `FnOnce` is not general enough --> $DIR/closure-mismatch.rs:16:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|x| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -55,15 +58,16 @@ LL | baz(|x: &()| ()); error: implementation of `Fn` is not general enough --> $DIR/closure-mismatch.rs:16:5 | -LL | fn baz(_: T) {} - | --- --- unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz`... -... LL | baz(|x| ()); | ^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/closure-mismatch.rs:9:11 + | +LL | fn baz(_: T) {} + | --- ^^^ unsatisfied where-clause on `baz` + | | + | due to a where-clause on `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 60f155eb45eb1..5e60b16903b82 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -3,13 +3,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` help: consider adding an explicit type annotation to the closure's argument | @@ -21,13 +22,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, for some specific lifetime `'0`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -81,14 +83,13 @@ error: implementation of `FnOnce` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: due to a where-clause on `Rc`... + = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | = note: unsatisfied where-clause on `Rc` - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -101,14 +102,13 @@ error: implementation of `Fn` is not general enough LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | +note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: due to a where-clause on `Rc`... + = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | = note: unsatisfied where-clause on `Rc` - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -120,13 +120,14 @@ error: implementation of `FnOnce` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... + | due to a where-clause on `B` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -138,13 +139,14 @@ error: implementation of `Fn` is not general enough | LL | A(B(C::new(D::new(move |st| f(st))))) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -... + | +note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + --> $DIR/ice-106874.rs:28:10 + | LL | struct B(Rc); - | - - unsatisfied where-clause on `B` + | - ^ unsatisfied where-clause on `B` | | - | due to a where-clause on `B`... - | - = note: ...closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... + | due to a where-clause on `B` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 4c5535258f624..8d45fc4db9c69 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -1,49 +1,53 @@ error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:63:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:69:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:75:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough --> $DIR/issue-54302-cases.rs:81:5 | -LL | fn ref_foo(&self) -> &'static T; - | ------- due to a where-clause on `RefFoo::ref_foo`... -... LL | >::ref_foo(a) - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `RefFoo::ref_foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... + --> $DIR/issue-54302-cases.rs:51:8 | - = note: ...`Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... +LL | fn ref_foo(&self) -> &'static T; + | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index f0f407afd7601..74e240122aa70 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | fn accept(_: C) -> Handshake> { - | ------ ----------- unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:27:14 + | +LL | fn accept(_: C) -> Handshake> { + | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -19,15 +20,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | fn accept(_: C) -> Handshake> { - | ------ ----------- unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:27:14 + | +LL | fn accept(_: C) -> Handshake> { + | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` + | | + | due to a where-clause on `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -38,15 +40,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | struct Handshake { - | --------- ---- unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:20:21 + | +LL | struct Handshake { + | --------- ^^^^ unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -56,15 +59,16 @@ LL | let callback = |_: &()| {}; error: implementation of `FnOnce` is not general enough --> $DIR/missing-universe-cause-issue-114907.rs:33:5 | -LL | struct Handshake { - | --------- ---- unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake`... -... LL | accept(callback); | ^^^^^^^^^^^^^^^^ | - = note: ...closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... +note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/missing-universe-cause-issue-114907.rs:20:21 + | +LL | struct Handshake { + | --------- ^^^^ unsatisfied where-clause on `Handshake` + | | + | due to a where-clause on `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 2e164c9b3abb7..4538c51a2bb52 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -29,13 +29,14 @@ error: implementation of `Fn` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 + | LL | fn bad &()>(_: F) {} - | --- -------------- unsatisfied where-clause on `bad` + | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -47,13 +48,14 @@ error: implementation of `FnOnce` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 + | LL | fn bad &()>(_: F) {} - | --- --- unsatisfied where-clause on `bad` + | --- ^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 2e164c9b3abb7..4538c51a2bb52 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -29,13 +29,14 @@ error: implementation of `Fn` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 + | LL | fn bad &()>(_: F) {} - | --- -------------- unsatisfied where-clause on `bad` + | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -47,13 +48,14 @@ error: implementation of `FnOnce` is not general enough | LL | bad(&b); | ^^^^^^^ -... + | +note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 + | LL | fn bad &()>(_: F) {} - | --- --- unsatisfied where-clause on `bad` + | --- ^^^ unsatisfied where-clause on `bad` | | - | due to a where-clause on `bad`... - | - = note: ...closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (),)>`, for any lifetime `'1`... + | due to a where-clause on `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index ced5c4b8058b0..e03e0cd465158 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -1,25 +1,27 @@ error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | -LL | fn make_f() -> Self::F; - | ------ due to a where-clause on `Y::make_f`... -... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y::make_f` + | ^^^^^^^^^^^^^^^^^^^ + | +note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | - = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` +LL | fn make_f() -> Self::F; + | ^^^^^^ due to a where-clause on `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough --> $DIR/impl-fn-ignore-binder-via-bottom.rs:30:14 | -LL | trait Y { - | - due to a where-clause on `Y`... -... LL | let _x = ::make_f(); - | ^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Y` + | ^^^^^^^^^^^^^^^^^^^ + | +note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` + --> $DIR/impl-fn-ignore-binder-via-bottom.rs:16:7 | - = note: ...`Y` would have to be implemented for the type `for<'a> fn(&'a ())` +LL | trait Y { + | ^ due to a where-clause on `Y` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index fa61b3af02cf0..5d5d712c6e3e4 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -1,15 +1,16 @@ error: implementation of `FnOnce` is not general enough --> $DIR/issue-30906.rs:18:5 | -LL | fn test FnOnce<(&'x str,)>>(_: F) {} - | ---- -------------------------- unsatisfied where-clause on `test` - | | - | due to a where-clause on `test`... -... LL | test(Compose(f, |_| {})); | ^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: ...`fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... +note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime `'1`... + --> $DIR/issue-30906.rs:3:12 + | +LL | fn test FnOnce<(&'x str,)>>(_: F) {} + | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` + | | + | due to a where-clause on `test` = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index 378616d9aca57..7c7af181f601b 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -1,16 +1,17 @@ error: implementation of `Bar` is not general enough --> $DIR/where-for-self-2.rs:23:5 | -LL | fn foo(x: &T) - | --- due to a where-clause on `foo`... -LL | where -LL | for<'a> &'a T: Bar, - | --- unsatisfied where-clause on `foo` -... LL | foo(&X); | ^^^^^^^ | - = note: ...`&'0 u32` must implement `Bar`, for any lifetime `'0`... +note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... + --> $DIR/where-for-self-2.rs:18:20 + | +LL | fn foo(x: &T) + | --- due to a where-clause on `foo` +LL | where +LL | for<'a> &'a T: Bar, + | ^^^ unsatisfied where-clause on `foo` = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to 1 previous error From cf56d126fd0befc4fbccb2cba8eaac1d06a2bb83 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:09:47 +0000 Subject: [PATCH 1227/1309] Tweak wording --- .../rustc_trait_selection/src/diagnostics.rs | 6 ++--- .../nice_region_error/placeholder_error.rs | 8 +++++-- .../associated-types-eq-hr.stderr | 24 +++++++------------ ...outine-auto-trait-span-issue-155880.stderr | 4 +--- ...olved-typeck-results.no_assumptions.stderr | 8 ++----- ...ranked-auto-trait-12.no_assumptions.stderr | 4 +--- ...er-ranked-auto-trait-13.assumptions.stderr | 16 ++++--------- ...ranked-auto-trait-13.no_assumptions.stderr | 24 +++++-------------- ...ranked-auto-trait-15.no_assumptions.stderr | 8 ++----- ...er-ranked-auto-trait-16.assumptions.stderr | 8 ++----- ...ranked-auto-trait-16.no_assumptions.stderr | 8 ++----- ...-ranked-auto-trait-5.no_assumptions.stderr | 3 +-- .../issue-110963-early.no_assumptions.stderr | 6 ++--- ...ation-not-general-enough-ice-133252.stderr | 4 +--- ...n-with-leaking-placeholders.current.stderr | 3 +-- ...rtb-closure-suggest-type-annotation.stderr | 6 ++--- tests/ui/coroutine/auto-trait-regions.stderr | 8 ++----- .../ui/coroutine/resume-arg-late-bound.stderr | 4 +--- ...ot-checked-with-right-substitutions.stderr | 4 +--- ...hr-fn-ptr-trait-impl-mismatch-29061.stderr | 12 +++------- ...tb-associated-type-leak-check-55731.stderr | 3 +-- ...n-ptr-impl-not-general-enough-57936.stderr | 4 +--- .../trait-bounds/hrtb-conflate-regions.stderr | 6 ++--- ...b-exists-forall-trait-contravariant.stderr | 3 +-- .../hrtb-exists-forall-trait-covariant.stderr | 3 +-- .../hrtb-exists-forall-trait-invariant.stderr | 3 +-- .../trait-bounds/hrtb-just-for-static.stderr | 3 +-- .../hrtb-perfect-forwarding.stderr | 3 +-- .../trait-bounds/issue-46989.stderr | 4 +--- .../trait-bounds/issue-59311.stderr | 6 ++--- .../issue-71955.current.stderr | 12 ++++------ tests/ui/lifetimes/issue-105675.stderr | 24 +++++-------------- tests/ui/lifetimes/issue-79187-2.stderr | 8 ++----- tests/ui/lifetimes/issue-79187.stderr | 8 ++----- .../lifetime-errors/issue_74400.stderr | 6 ++--- .../closure-arg-type-mismatch.stderr | 8 ++----- .../closure-mismatch.current.stderr | 16 ++++--------- tests/ui/nll/ice-106874.stderr | 24 +++++-------------- tests/ui/nll/issue-54302-cases.stderr | 8 +++---- ...missing-universe-cause-issue-114907.stderr | 16 ++++--------- ...insensitive-scopes-issue-117146.nll.stderr | 8 ++----- ...sitive-scopes-issue-117146.polonius.stderr | 8 ++----- .../impl-fn-ignore-binder-via-bottom.stderr | 4 ++-- tests/ui/unboxed-closures/issue-30906.stderr | 4 +--- .../ui/where-clauses/where-for-self-2.stderr | 3 +-- 45 files changed, 107 insertions(+), 256 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 9d2238c188157..72b57c6af99d5 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1096,17 +1096,17 @@ impl<'tcx> ActualImplExplNotes<'tcx> { item_span: Option, item_name: String, ) -> Self { - let label = format!("unsatisfied where-clause on `{item_name}`"); - let item_label = format!("due to a where-clause on `{item_name}`"); + let label = format!("required by this bound in `{item_name}`"); let span = match (satisfy_span, item_span) { (Some(satisfy_span), Some(item_span)) => { let mut span = MultiSpan::from(satisfy_span); span.push_span_label(satisfy_span, label); - span.push_span_label(item_span, item_label); + span.push_span_context(item_span); span } (None, Some(item_span)) => { let mut span = MultiSpan::from(item_span); + let item_label = format!("required due to a bound in `{item_name}`"); span.push_span_label(item_span, item_label); span } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 1b57e3d77d503..9cf38a23bf295 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -297,10 +297,14 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { } else { (None, None, Some(span), String::new()) }; - if let Some(span) = satisfy_span && span.is_dummy() { + if let Some(span) = satisfy_span + && span.is_dummy() + { satisfy_span = None; } - if let Some(span) = item_span && span.is_dummy() { + if let Some(span) = item_span + && span.is_dummy() + { item_span = None; } diff --git a/tests/ui/associated-types/associated-types-eq-hr.stderr b/tests/ui/associated-types/associated-types-eq-hr.stderr index 19fd633334f00..4f85111897df5 100644 --- a/tests/ui/associated-types/associated-types-eq-hr.stderr +++ b/tests/ui/associated-types/associated-types-eq-hr.stderr @@ -50,10 +50,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -70,10 +69,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:8 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -91,10 +89,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:53 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -111,10 +108,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:59:53 | LL | fn tuple_one() - | --------- due to a where-clause on `tuple_one` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'x isize>, - | ^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_one` + | ^^^^^^^^^^^^^ required by this bound in `tuple_one` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -132,10 +128,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:66:8 | LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -152,10 +147,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:66:8 | LL | fn tuple_two() - | --------- due to a where-clause on `tuple_two` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize), A = &'y isize>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_two` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_two` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -202,10 +196,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:80:8 | LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | @@ -222,10 +215,9 @@ note: `Tuple` must implement `TheTrait<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/associated-types-eq-hr.rs:80:8 | LL | fn tuple_four() - | ---------- due to a where-clause on `tuple_four` LL | where LL | T: for<'x, 'y> TheTrait<(&'x isize, &'y isize)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `tuple_four` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `tuple_four` note: ...but it actually implements `TheTrait<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/associated-types-eq-hr.rs:35:1 | diff --git a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr index 893124920ee18..3bdb318678d92 100644 --- a/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr +++ b/tests/ui/async-await/coroutine-auto-trait-span-issue-155880.stderr @@ -14,9 +14,7 @@ note: `Send` would have to be implemented for the type `&'0 u32`, for any lifeti --> $DIR/coroutine-auto-trait-span-issue-155880.rs:25:15 | LL | fn is_send(_: T) {} - | ------- ^^^^ unsatisfied where-clause on `is_send` - | | - | due to a where-clause on `is_send` + | ^^^^ required by this bound in `is_send` = note: ...but `Send` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr index da93d5a17547a..a5f148ae0ca76 100644 --- a/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr +++ b/tests/ui/async-await/drop-tracking-unresolved-typeck-results.no_assumptions.stderr @@ -10,9 +10,7 @@ note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implemen --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 | LL | fn send(_: T) {} - | ---- ^^^^ unsatisfied where-clause on `send` - | | - | due to a where-clause on `send` + | ^^^^ required by this bound in `send` = note: ...but it actually implements `FnOnce<(&(),)>` error: implementation of `FnOnce` is not general enough @@ -27,9 +25,7 @@ note: `fn(&'0 ()) -> Ready<&'0 ()> {std::future::ready::<&'0 ()>}` must implemen --> $DIR/drop-tracking-unresolved-typeck-results.rs:13:12 | LL | fn send(_: T) {} - | ---- ^^^^ unsatisfied where-clause on `send` - | | - | due to a where-clause on `send` + | ^^^^ required by this bound in `send` = note: ...but it actually implements `FnOnce<(&(),)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr index 39132cc9b4fb9..a55e42b4b6dfb 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr @@ -15,9 +15,7 @@ note: `Box<(dyn Robot + Send + '0)>` must implement `Robot`, for any l --> $DIR/higher-ranked-auto-trait-12.rs:24:20 | LL | fn this_is_send(value: T) -> T { - | ------------ ^^^^ unsatisfied where-clause on `this_is_send` - | | - | due to a where-clause on `this_is_send` + | ^^^^ required by this bound in `this_is_send` = note: ...but `Robot` is actually implemented for the type `Box<(dyn Robot + Send + 'static)>` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr index 386a83ebbc761..63eef87aa2517 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr @@ -8,9 +8,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -23,9 +21,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -39,9 +35,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -54,9 +48,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr index 02f91c47fffcb..9d89d73270f71 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr @@ -8,9 +8,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -23,9 +21,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -39,9 +35,7 @@ note: `Callable<'_>` would have to be implemented for the type `ConstructableImp --> $DIR/higher-ranked-auto-trait-13.rs:52:24 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: implementation of `Getter` is not general enough @@ -54,9 +48,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` error: implementation of `Getter` is not general enough @@ -69,9 +61,7 @@ note: `Getter<'1>` would have to be implemented for the type `GetterImpl<'0, Con --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Getter<'2>` is actually implemented for the type `GetterImpl<'2, ConstructableImpl<'_>>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` @@ -85,9 +75,7 @@ note: `Callable<'_>` would have to be implemented for the type `ConstructableImp --> $DIR/higher-ranked-auto-trait-13.rs:52:31 | LL | fn assert_send(_: impl Send + Sync) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Callable<'1>` is actually implemented for the type `ConstructableImpl<'1>`, for some specific lifetime `'1` error: aborting due to 6 previous errors diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr index c6c8479474c64..94a187f69c91f 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce --> $DIR/higher-ranked-auto-trait-15.rs:16:20 | LL | fn require_send(_x: T) {} - | ------------ ^^^^ unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send` + | ^^^^ required by this bound in `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'0 _) -> Iter<'_, i32>` must implement `FnOnce --> $DIR/higher-ranked-auto-trait-15.rs:16:20 | LL | fn require_send(_x: T) {} - | ------------ ^^^^ unsatisfied where-clause on `require_send` - | | - | due to a where-clause on `require_send` + | ^^^^ required by this bound in `require_send` = note: ...but it actually implements `FnOnce<(&Vec,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr index 52c54f8355c39..ff7a3230aa6c9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr @@ -10,9 +10,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough @@ -27,9 +25,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr index 52c54f8355c39..ff7a3230aa6c9 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr @@ -10,9 +10,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` error: implementation of `AsyncFnOnce` is not general enough @@ -27,9 +25,7 @@ note: `{async closure@...}` must implement `AsyncFnOnce<(&mut Ctxt<'1>,)>`, for --> $DIR/higher-ranked-auto-trait-16.rs:8:19 | LL | fn assert_send(_: T) {} - | ----------- ^^^^ unsatisfied where-clause on `assert_send` - | | - | due to a where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but it actually implements `AsyncFnOnce<(&mut Ctxt<'_>,)>` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr index 6119247429e28..a95fd2179322f 100644 --- a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr +++ b/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr @@ -10,10 +10,9 @@ note: `Send` would have to be implemented for the type `&'0 str`, for any lifeti --> $DIR/higher-ranked-auto-trait-5.rs:20:17 | LL | pub fn assert_send(_future: F) - | ----------- due to a where-clause on `assert_send` LL | where LL | F: Future + Send, - | ^^^^ unsatisfied where-clause on `assert_send` + | ^^^^ required by this bound in `assert_send` = note: ...but `Send` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr index 889d3c2948d61..63f44d676882d 100644 --- a/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr +++ b/tests/ui/async-await/return-type-notation/issue-110963-early.no_assumptions.stderr @@ -16,10 +16,9 @@ note: `Send` would have to be implemented for the type `impl Future $DIR/issue-110963-early.rs:37:17 | LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn` LL | where LL | F: Future + Send + 'static, - | ^^^^ unsatisfied where-clause on `spawn` + | ^^^^ required by this bound in `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` error: implementation of `Send` is not general enough @@ -40,10 +39,9 @@ note: `Send` would have to be implemented for the type `impl Future $DIR/issue-110963-early.rs:37:17 | LL | fn spawn(future: F) -> JoinHandle - | ----- due to a where-clause on `spawn` LL | where LL | F: Future + Send + 'static, - | ^^^^ unsatisfied where-clause on `spawn` + | ^^^^ required by this bound in `spawn` = note: ...but `Send` is actually implemented for the type `impl Future { ::check<'2>(..) }`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr index beb349c94bd1a..f1a561ef88049 100644 --- a/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr +++ b/tests/ui/borrowck/implementation-not-general-enough-ice-133252.stderr @@ -8,9 +8,7 @@ note: `LoadQuery<'0>` would have to be implemented for the type `&u8`, for any l --> $DIR/implementation-not-general-enough-ice-133252.rs:16:18 | LL | fn force_send(_: T) {} - | ---------- ^^^^ unsatisfied where-clause on `force_send` - | | - | due to a where-clause on `force_send` + | ^^^^ required by this bound in `force_send` = note: ...but `LoadQuery<'1>` is actually implemented for the type `&'1 u8`, for some specific lifetime `'1` error[E0597]: `not_static` does not live long enough diff --git a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr index 5f8198ec6bed9..d8453534d0636 100644 --- a/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr +++ b/tests/ui/closures/deduce-signature/obligation-with-leaking-placeholders.current.stderr @@ -12,10 +12,9 @@ note: `Wrap<{closure@...}>` must implement `Foo<'0>`, for any lifetime `'0`... --> $DIR/obligation-with-leaking-placeholders.rs:10:22 | LL | fn needs_foo(_: T) - | --------- due to a where-clause on `needs_foo` LL | where LL | for<'a> Wrap: Foo<'a>, - | ^^^^^^^ unsatisfied where-clause on `needs_foo` + | ^^^^^^^ required by this bound in `needs_foo` note: ...but it actually implements `Foo<'1>`, for some specific lifetime `'1` --> $DIR/obligation-with-leaking-placeholders.rs:15:1 | diff --git a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr index 5f7636bb34a0e..a8382f3dc4d76 100644 --- a/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr +++ b/tests/ui/closures/hrtb-closure-suggest-type-annotation.stderr @@ -8,10 +8,9 @@ note: closure with signature `fn(&'2 mut [u8]) -> Result` must imp --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:8 | LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner` LL | where LL | F: FnOnce(&mut [u8]) -> Result, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -28,10 +27,9 @@ note: closure with signature `fn(&'2 mut [u8]) -> Result` must imp --> $DIR/hrtb-closure-suggest-type-annotation.rs:8:29 | LL | fn inner(buf: &mut [u8], func: F) -> usize - | ----- due to a where-clause on `inner` LL | where LL | F: FnOnce(&mut [u8]) -> Result, - | ^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `inner` + | ^^^^^^^^^^^^^^^^^^^^ required by this bound in `inner` = note: ...but it actually implements `FnOnce<(&'2 mut [u8],)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/coroutine/auto-trait-regions.stderr b/tests/ui/coroutine/auto-trait-regions.stderr index 25f6373124d34..ea2b5cc18cda3 100644 --- a/tests/ui/coroutine/auto-trait-regions.stderr +++ b/tests/ui/coroutine/auto-trait-regions.stderr @@ -11,9 +11,7 @@ note: `&'0 OnlyFooIfStaticRef` must implement `Foo`, for any lifetime `'0`... --> $DIR/auto-trait-regions.rs:21:18 | LL | fn assert_foo(f: T) {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `&'static OnlyFooIfStaticRef` error[E0626]: borrow may still be in use when coroutine yields @@ -61,9 +59,7 @@ note: `Foo` would have to be implemented for the type `A<'0, '1>`, for any two l --> $DIR/auto-trait-regions.rs:21:18 | LL | fn assert_foo(f: T) {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `A<'_, '2>`, for some specific lifetime `'2` error: aborting due to 4 previous errors diff --git a/tests/ui/coroutine/resume-arg-late-bound.stderr b/tests/ui/coroutine/resume-arg-late-bound.stderr index b44a8e363128f..9211256766669 100644 --- a/tests/ui/coroutine/resume-arg-late-bound.stderr +++ b/tests/ui/coroutine/resume-arg-late-bound.stderr @@ -8,9 +8,7 @@ note: `{coroutine@...}` must implement `Coroutine<&'1 mut bool>`, for any lifeti --> $DIR/resume-arg-late-bound.rs:8:17 | LL | fn test(a: impl for<'a> Coroutine<&'a mut bool>) {} - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` - | | - | due to a where-clause on `test` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` = note: ...but it actually implements `Coroutine<&'2 mut bool>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index 92d39c70137ce..de0882fb665d2 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -8,9 +8,7 @@ note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, f --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | LL | type Gat<'a>: for<'b> Lengthen>; - | --- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `Gat::Gat` - | | - | due to a where-clause on `Gat::Gat` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` note: required by a bound in `Gat::Gat` --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 diff --git a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr index 16c1b69d3b053..9e5de5e6fb61b 100644 --- a/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr +++ b/tests/ui/higher-ranked/hr-fn-ptr-trait-impl-mismatch-29061.stderr @@ -8,9 +8,7 @@ note: `HR` would have to be implemented for the type `fn(&'0 ())`, for some spec --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:15:10 | LL | fn hr(_: T) {} - | -- ^^ unsatisfied where-clause on `hr` - | | - | due to a where-clause on `hr` + | ^^ required by this bound in `hr` = note: ...but `HR` is actually implemented for the type `for<'a> fn(&'a ())` error: implementation of `NotHR` is not general enough @@ -23,9 +21,7 @@ note: `NotHR` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 | LL | fn not_hr(_: T) {} - | ------ ^^^^^ unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr` + | ^^^^^ required by this bound in `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `NotHR` is not general enough @@ -38,9 +34,7 @@ note: `NotHR` would have to be implemented for the type `for<'b> fn(&'b ())` --> $DIR/hr-fn-ptr-trait-impl-mismatch-29061.rs:19:14 | LL | fn not_hr(_: T) {} - | ------ ^^^^^ unsatisfied where-clause on `not_hr` - | | - | due to a where-clause on `not_hr` + | ^^^^^ required by this bound in `not_hr` = note: ...but `NotHR` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 3 previous errors diff --git a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr index d3e10e7a18d20..53586decee2c5 100644 --- a/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr +++ b/tests/ui/higher-ranked/hrtb-associated-type-leak-check-55731.stderr @@ -11,10 +11,9 @@ note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the ty --> $DIR/hrtb-associated-type-leak-check-55731.rs:43:8 | LL | fn multi(_reducer: I) - | ----- due to a where-clause on `multi` LL | where LL | I: for<'a> DistributedIteratorMulti<&'a ()>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `multi` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `multi` = note: ...but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr index f7a9020c59e24..f9862b8ab13a4 100644 --- a/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr +++ b/tests/ui/higher-ranked/hrtb-fn-ptr-impl-not-general-enough-57936.stderr @@ -21,9 +21,7 @@ note: `X` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/hrtb-fn-ptr-impl-not-general-enough-57936.rs:21:16 | LL | fn indirect() { - | -------- ^ unsatisfied where-clause on `indirect` - | | - | due to a where-clause on `indirect` + | ^ required by this bound in `indirect` = note: ...but `X` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: aborting due to 2 previous errors diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr index 6700778198712..0946314f31e80 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-conflate-regions.stderr @@ -8,9 +8,8 @@ note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/hrtb-conflate-regions.rs:9:15 | LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2` LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | @@ -27,9 +26,8 @@ note: `SomeStruct` must implement `Foo<(&'0 isize, &'1 isize)>`, for any two lif --> $DIR/hrtb-conflate-regions.rs:9:15 | LL | fn want_foo2() - | --------- due to a where-clause on `want_foo2` LL | where T : for<'a,'b> Foo<(&'a isize, &'b isize)> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_foo2` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_foo2` note: ...but it actually implements `Foo<(&'2 isize, &'2 isize)>`, for some specific lifetime `'2` --> $DIR/hrtb-conflate-regions.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr index e600c49d564be..8ec6646e73074 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-contravariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(&'b u32)>` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:10:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(&'b u32)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-contravariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr index dd720d9989060..4beade083b781 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-covariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(fn(&'b u32))>` --> $DIR/hrtb-exists-forall-trait-covariant.rs:10:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(fn(&'b u32))>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-covariant.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr index 446a3102a0938..691d5499bc175 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-trait-invariant.stderr @@ -8,10 +8,9 @@ note: `()` must implement `Trait fn(Cell<&'b u32>)>` --> $DIR/hrtb-exists-forall-trait-invariant.rs:12:8 | LL | fn foo() - | --- due to a where-clause on `foo` LL | where LL | T: Trait fn(Cell<&'b u32>)>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` note: ...but it actually implements `Trait)>`, for some specific lifetime `'0` --> $DIR/hrtb-exists-forall-trait-invariant.rs:16:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr index cdfcd30d44fb2..8e224e3447205 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-just-for-static.stderr @@ -8,9 +8,8 @@ note: `StaticInt` must implement `Foo<&'0 isize>`, for any lifetime `'0`... --> $DIR/hrtb-just-for-static.rs:9:15 | LL | fn want_hrtb() - | --------- due to a where-clause on `want_hrtb` LL | where T : for<'a> Foo<&'a isize> - | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `want_hrtb` + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `want_hrtb` note: ...but it actually implements `Foo<&'static isize>` --> $DIR/hrtb-just-for-static.rs:22:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr index da60e78d2f389..b1d725f896cf2 100644 --- a/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr +++ b/tests/ui/higher-ranked/trait-bounds/hrtb-perfect-forwarding.stderr @@ -63,10 +63,9 @@ note: `T` must implement `Bar<&'0 isize>`, for any lifetime `'0`... --> $DIR/hrtb-perfect-forwarding.rs:37:8 | LL | fn foo_hrtb_bar_not<'b, T>(mut t: T) - | ---------------- due to a where-clause on `foo_hrtb_bar_not` LL | where LL | T: for<'a> Foo<&'a isize> + Bar<&'b isize>, - | ^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo_hrtb_bar_not` + | ^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo_hrtb_bar_not` note: ...but it actually implements `Bar<&'1 isize>`, for some specific lifetime `'1` --> $DIR/hrtb-perfect-forwarding.rs:14:1 | diff --git a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr index 23cba27a2fc00..0592e9e149f00 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-46989.stderr @@ -8,9 +8,7 @@ note: `Foo` would have to be implemented for the type `for<'a> fn(&'a i32)` --> $DIR/issue-46989.rs:35:18 | LL | fn assert_foo() {} - | ---------- ^^^ unsatisfied where-clause on `assert_foo` - | | - | due to a where-clause on `assert_foo` + | ^^^ required by this bound in `assert_foo` = note: ...but `Foo` is actually implemented for the type `fn(&'0 i32)`, for some specific lifetime `'0` error: aborting due to 1 previous error diff --git a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr index 9145a693c95c8..d53ff3b080da5 100644 --- a/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr +++ b/tests/ui/higher-ranked/trait-bounds/issue-59311.stderr @@ -8,10 +8,9 @@ note: `Trait` would have to be implemented for the type `&'a V` --> $DIR/issue-59311.rs:15:20 | LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash` LL | where LL | for<'a> &'a V: Trait + 'static, - | ^^^^^ unsatisfied where-clause on `crash` + | ^^^^^ required by this bound in `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` error: implementation of `Trait` is not general enough @@ -24,10 +23,9 @@ note: `Trait` would have to be implemented for the type `&'a V` --> $DIR/issue-59311.rs:15:20 | LL | pub fn crash(v: &V) - | ----- due to a where-clause on `crash` LL | where LL | for<'a> &'a V: Trait + 'static, - | ^^^^^ unsatisfied where-clause on `crash` + | ^^^^^ required by this bound in `crash` = note: ...but `Trait` is actually implemented for the type `&'0 V`, for some specific lifetime `'0` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr index 6dd203ac806e5..2c35e1c853911 100644 --- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr +++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/issue-71955.current.stderr @@ -8,10 +8,9 @@ note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `F --> $DIR/issue-71955.rs:32:9 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -28,10 +27,9 @@ note: closure with signature `for<'a> fn(&'a &'2 str) -> bool` must implement `F --> $DIR/issue-71955.rs:32:63 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^ unsatisfied where-clause on `foo` + | ^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&&'2 str,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -48,10 +46,9 @@ note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implemen --> $DIR/issue-71955.rs:32:9 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `foo` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -68,10 +65,9 @@ note: closure with signature `for<'a> fn(&'a Wrapper<'2>) -> bool` must implemen --> $DIR/issue-71955.rs:32:63 | LL | fn foo(f1: F1, f2: F2) - | --- due to a where-clause on `foo` ... LL | F2: for<'b, 'c> FnOnce(&'b >::Output) -> bool, - | ^^^^ unsatisfied where-clause on `foo` + | ^^^^ required by this bound in `foo` = note: ...but it actually implements `FnOnce<(&Wrapper<'2>,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-105675.stderr b/tests/ui/lifetimes/issue-105675.stderr index 995c3604ca6e0..0c7c8f97de726 100644 --- a/tests/ui/lifetimes/issue-105675.stderr +++ b/tests/ui/lifetimes/issue-105675.stderr @@ -8,9 +8,7 @@ note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding explicit type annotations to the closure's arguments | @@ -27,9 +25,7 @@ note: closure with signature `for<'a> fn(&'2 u32, &'a u32, u32)` must implement --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding explicit type annotations to the closure's arguments @@ -47,9 +43,7 @@ note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&' --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -66,9 +60,7 @@ note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -85,9 +77,7 @@ note: closure with signature `fn(&'2 u32, &u32, u32)` must implement `FnOnce<(&' --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32, &u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -105,9 +95,7 @@ note: closure with signature `fn(&u32, &'2 u32, u32)` must implement `FnOnce<(&u --> $DIR/issue-105675.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32, &u32, u32)) {} - | ----- ^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&u32, &'2 u32, u32)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr index 4b2799812fe90..adc64984a05e9 100644 --- a/tests/ui/lifetimes/issue-79187-2.stderr +++ b/tests/ui/lifetimes/issue-79187-2.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 i32) -> &i32` must implement `FnOnce<(&'1 i --> $DIR/issue-79187-2.rs:5:21 | LL | fn take_foo(_: impl Foo) {} - | -------- ^^^ unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo` + | ^^^ required by this bound in `take_foo` = note: ...but it actually implements `FnOnce<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 i32) -> &i32` must implement `Fn<(&'1 i32,) --> $DIR/issue-79187-2.rs:5:21 | LL | fn take_foo(_: impl Foo) {} - | -------- ^^^ unsatisfied where-clause on `take_foo` - | | - | due to a where-clause on `take_foo` + | ^^^ required by this bound in `take_foo` = note: ...but it actually implements `Fn<(&'2 i32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/lifetimes/issue-79187.stderr b/tests/ui/lifetimes/issue-79187.stderr index 2377c4d5ba5f3..5e9602f80baf1 100644 --- a/tests/ui/lifetimes/issue-79187.stderr +++ b/tests/ui/lifetimes/issue-79187.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, --> $DIR/issue-79187.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 u32)` must implement `FnOnce<(&'1 u32,)>`, --> $DIR/issue-79187.rs:1:18 | LL | fn thing(x: impl FnOnce(&u32)) {} - | ----- ^^^^^^^^^^^^ unsatisfied where-clause on `thing` - | | - | due to a where-clause on `thing` + | ^^^^^^^^^^^^ required by this bound in `thing` = note: ...but it actually implements `FnOnce<(&'2 u32,)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr index 5670dc4ea00f7..d9df584bebf73 100644 --- a/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr +++ b/tests/ui/lifetimes/lifetime-errors/issue_74400.stderr @@ -52,9 +52,7 @@ note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `Fn<(&'1 T,)>`, fo --> $DIR/issue_74400.rs:8:34 | LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - ^^^^^^^^^^^ unsatisfied where-clause on `f` - | | - | due to a where-clause on `f` + | ^^^^^^^^^^^ required by this bound in `f` = note: ...but it actually implements `Fn<(&'2 T,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough @@ -67,7 +65,7 @@ note: `fn(&'2 T) -> &'2 T {identity::<&'2 T>}` must implement `FnOnce<(&'1 T,)>` --> $DIR/issue_74400.rs:8:44 | LL | fn f(data: &[T], key: impl Fn(&T) -> S) { - | - due to a where-clause on `f` ^ unsatisfied where-clause on `f` + | ^ required by this bound in `f` = note: ...but it actually implements `FnOnce<(&'2 T,)>`, for some specific lifetime `'2` error: aborting due to 5 previous errors diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr index 72945d962a570..15c37059416af 100644 --- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr +++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr @@ -73,9 +73,7 @@ note: `fn(*mut &'2 u32)` must implement `Fn<(*mut &'1 u32,)>`, for any lifetime --> $DIR/closure-arg-type-mismatch.rs:8:11 | LL | fn baz(_: F) {} - | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^^^^^^^^^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: implementation of `FnOnce` is not general enough @@ -88,9 +86,7 @@ note: `fn(*mut &'2 u32)` must implement `FnOnce<(*mut &'1 u32,)>`, for any lifet --> $DIR/closure-arg-type-mismatch.rs:8:11 | LL | fn baz(_: F) {} - | --- ^^^^^^^^^^^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^^^^^^^^^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(*mut &'2 u32,)>`, for some specific lifetime `'2` error: aborting due to 6 previous errors diff --git a/tests/ui/mismatched_types/closure-mismatch.current.stderr b/tests/ui/mismatched_types/closure-mismatch.current.stderr index 0249537dcba54..ad734c4e77ea6 100644 --- a/tests/ui/mismatched_types/closure-mismatch.current.stderr +++ b/tests/ui/mismatched_types/closure-mismatch.current.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for an --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -46,9 +42,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -65,9 +59,7 @@ note: closure with signature `fn(&'2 ())` must implement `Fn<(&'1 (),)>`, for an --> $DIR/closure-mismatch.rs:9:11 | LL | fn baz(_: T) {} - | --- ^^^ unsatisfied where-clause on `baz` - | | - | due to a where-clause on `baz` + | ^^^ required by this bound in `baz` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/ice-106874.stderr b/tests/ui/nll/ice-106874.stderr index 5e60b16903b82..0b756a1795f8a 100644 --- a/tests/ui/nll/ice-106874.stderr +++ b/tests/ui/nll/ice-106874.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'0 mut V)` must implement `FnOnce<(&mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'1 mut V,)>`, for some specific lifetime `'1` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -85,11 +81,9 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL - | - = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: unsatisfied where-clause on `Rc` + = note: required by this bound in `Rc` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -104,11 +98,9 @@ LL | A(B(C::new(D::new(move |st| f(st))))) | note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, for any lifetime `'1`... --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL - | - = note: due to a where-clause on `Rc` ::: $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL | - = note: unsatisfied where-clause on `Rc` + = note: required by this bound in `Rc` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -125,9 +117,7 @@ note: closure with signature `fn(&'2 mut V)` must implement `FnOnce<(&'1 mut V,) --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `FnOnce<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -144,9 +134,7 @@ note: closure with signature `fn(&'2 mut V)` must implement `Fn<(&'1 mut V,)>`, --> $DIR/ice-106874.rs:28:10 | LL | struct B(Rc); - | - ^ unsatisfied where-clause on `B` - | | - | due to a where-clause on `B` + | ^ required by this bound in `B` = note: ...but it actually implements `Fn<(&'2 mut V,)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 8d45fc4db9c69..0ebd0293eccca 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -8,7 +8,7 @@ note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -21,7 +21,7 @@ note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -34,7 +34,7 @@ note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` error: implementation of `Foo` is not general enough @@ -47,7 +47,7 @@ note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, f --> $DIR/issue-54302-cases.rs:51:8 | LL | fn ref_foo(&self) -> &'static T; - | ^^^^^^^ due to a where-clause on `RefFoo::ref_foo` + | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` error: aborting due to 4 previous errors diff --git a/tests/ui/nll/missing-universe-cause-issue-114907.stderr b/tests/ui/nll/missing-universe-cause-issue-114907.stderr index 74e240122aa70..c9b5eb8230a0f 100644 --- a/tests/ui/nll/missing-universe-cause-issue-114907.stderr +++ b/tests/ui/nll/missing-universe-cause-issue-114907.stderr @@ -8,9 +8,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:27:14 | LL | fn accept(_: C) -> Handshake> { - | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept` + | ^^^^^^^^^^^ required by this bound in `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -27,9 +25,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:27:14 | LL | fn accept(_: C) -> Handshake> { - | ------ ^^^^^^^^^^^ unsatisfied where-clause on `accept` - | | - | due to a where-clause on `accept` + | ^^^^^^^^^^^ required by this bound in `accept` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument @@ -47,9 +43,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:20:21 | LL | struct Handshake { - | --------- ^^^^ unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake` + | ^^^^ required by this bound in `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -66,9 +60,7 @@ note: closure with signature `fn(&'2 ())` must implement `FnOnce<(&'1 (),)>`, fo --> $DIR/missing-universe-cause-issue-114907.rs:20:21 | LL | struct Handshake { - | --------- ^^^^ unsatisfied where-clause on `Handshake` - | | - | due to a where-clause on `Handshake` + | ^^^^ required by this bound in `Handshake` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` help: consider adding an explicit type annotation to the closure's argument diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr index 4538c51a2bb52..3c1beb5021af8 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.nll.stderr @@ -34,9 +34,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 | LL | fn bad &()>(_: F) {} - | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^^^^^^^^^^^^ required by this bound in `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -53,9 +51,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (), --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 | LL | fn bad &()>(_: F) {} - | --- ^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^ required by this bound in `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr index 4538c51a2bb52..3c1beb5021af8 100644 --- a/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr +++ b/tests/ui/nll/polonius/location-insensitive-scopes-issue-117146.polonius.stderr @@ -34,9 +34,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `Fn<(&'1 (),)>`, --> $DIR/location-insensitive-scopes-issue-117146.rs:21:11 | LL | fn bad &()>(_: F) {} - | --- ^^^^^^^^^^^^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^^^^^^^^^^^^ required by this bound in `bad` = note: ...but it actually implements `Fn<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | @@ -53,9 +51,7 @@ note: closure with signature `fn(&'2 ()) -> &()` must implement `FnOnce<(&'1 (), --> $DIR/location-insensitive-scopes-issue-117146.rs:21:22 | LL | fn bad &()>(_: F) {} - | --- ^^^ unsatisfied where-clause on `bad` - | | - | due to a where-clause on `bad` + | ^^^ required by this bound in `bad` = note: ...but it actually implements `FnOnce<(&'2 (),)>`, for some specific lifetime `'2` help: consider adding an explicit type annotation to the closure's argument | diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index e03e0cd465158..1917b5ca9cea1 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -8,7 +8,7 @@ note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | LL | fn make_f() -> Self::F; - | ^^^^^^ due to a where-clause on `Y::make_f` + | ^^^^^^ required due to a bound in `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough @@ -21,7 +21,7 @@ note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:16:7 | LL | trait Y { - | ^ due to a where-clause on `Y` + | ^ required due to a bound in `Y` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` error: implementation of `Y` is not general enough diff --git a/tests/ui/unboxed-closures/issue-30906.stderr b/tests/ui/unboxed-closures/issue-30906.stderr index 5d5d712c6e3e4..252ee8d85da9d 100644 --- a/tests/ui/unboxed-closures/issue-30906.stderr +++ b/tests/ui/unboxed-closures/issue-30906.stderr @@ -8,9 +8,7 @@ note: `fn(&'2 str) -> T` must implement `FnOnce<(&'1 str,)>`, for any lifetime ` --> $DIR/issue-30906.rs:3:12 | LL | fn test FnOnce<(&'x str,)>>(_: F) {} - | ---- ^^^^^^^^^^^^^^^^^^^^^^^^^^ unsatisfied where-clause on `test` - | | - | due to a where-clause on `test` + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `test` = note: ...but it actually implements `FnOnce<(&'2 str,)>`, for some specific lifetime `'2` error: aborting due to 1 previous error diff --git a/tests/ui/where-clauses/where-for-self-2.stderr b/tests/ui/where-clauses/where-for-self-2.stderr index 7c7af181f601b..1b172f2a57f3c 100644 --- a/tests/ui/where-clauses/where-for-self-2.stderr +++ b/tests/ui/where-clauses/where-for-self-2.stderr @@ -8,10 +8,9 @@ note: `&'0 u32` must implement `Bar`, for any lifetime `'0`... --> $DIR/where-for-self-2.rs:18:20 | LL | fn foo(x: &T) - | --- due to a where-clause on `foo` LL | where LL | for<'a> &'a T: Bar, - | ^^^ unsatisfied where-clause on `foo` + | ^^^ required by this bound in `foo` = note: ...but `Bar` is actually implemented for the type `&'static u32` error: aborting due to 1 previous error From ca762cfe3b4d9112389a92b25a3755adbe6f78d6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:14:38 +0000 Subject: [PATCH 1228/1309] Remove redundant information --- .../nice_region_error/placeholder_error.rs | 24 ++++++++++++------- ...ot-checked-with-right-substitutions.stderr | 6 ----- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 9cf38a23bf295..1cecc2c5de448 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -393,15 +393,21 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { let mut current_code = cause.code(); let mut coroutine_def_id = None; if cause.body_def_id != CRATE_DEF_ID { - self.cx.note_obligation_cause_code( - cause.body_def_id, - &mut err, - actual_trait_ref, - self.tcx().param_env(cause.body_def_id), - cause.code(), - &mut vec![], - &mut Default::default(), - ); + if let ObligationCauseCode::WhereClause(..) + | ObligationCauseCode::WhereClauseInExpr(..) = *code + { + // Do not point at the same bound twice. + } else { + self.cx.note_obligation_cause_code( + cause.body_def_id, + &mut err, + actual_trait_ref, + self.tcx().param_env(cause.body_def_id), + cause.code(), + &mut vec![], + &mut Default::default(), + ); + } } loop { diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index de0882fb665d2..fe84512e6f12e 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -10,12 +10,6 @@ note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, f LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` -note: required by a bound in `Gat::Gat` - --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 - | -LL | trait Gat { -LL | type Gat<'a>: for<'b> Lengthen>; - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` error: aborting due to 1 previous error From 337f98dd5582fdc1552bc76df6060a18f00f9145 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Wed, 30 Sep 2026 23:21:26 +0000 Subject: [PATCH 1229/1309] Tweak note to include trait/impl when appropriate ``` error: implementation of `Lengthen` is not general enough --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:20:20 | LL | type Gat<'a> = &'a str; | ^^^^^^^ | note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | LL | trait Gat { LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` ``` --- compiler/rustc_trait_selection/src/diagnostics.rs | 6 +++++- .../infer/nice_region_error/placeholder_error.rs | 15 ++++++++++++--- ...ds-not-checked-with-right-substitutions.stderr | 1 + tests/ui/nll/issue-54302-cases.stderr | 4 ++++ .../impl-fn-ignore-binder-via-bottom.stderr | 2 ++ 5 files changed, 24 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 72b57c6af99d5..d453b3c809860 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1094,10 +1094,11 @@ impl<'tcx> ActualImplExplNotes<'tcx> { lifetime_2: usize, satisfy_span: Option, item_span: Option, + outer_span: Option, item_name: String, ) -> Self { let label = format!("required by this bound in `{item_name}`"); - let span = match (satisfy_span, item_span) { + let mut span = match (satisfy_span, item_span) { (Some(satisfy_span), Some(item_span)) => { let mut span = MultiSpan::from(satisfy_span); span.push_span_label(satisfy_span, label); @@ -1117,6 +1118,9 @@ impl<'tcx> ActualImplExplNotes<'tcx> { } _ => MultiSpan::from(vec![]), }; + if let Some(outer) = outer_span { + span.push_span_context(outer); + } match (kind, lt_kind) { (ActualImplExpectedKind::Signature, ActualImplExpectedLifetimeKind::Two) => { Self::ExpectedSignatureTwo { span, ty_or_sig, trait_path, lifetime_1, lifetime_2 } diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs index 1cecc2c5de448..fecf41c84a0e2 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/placeholder_error.rs @@ -3,7 +3,7 @@ use std::fmt; use rustc_data_structures::intern::Interned; use rustc_errors::{Applicability, Diag, IntoDiagArg}; use rustc_hir as hir; -use rustc_hir::def::Namespace; +use rustc_hir::def::{DefKind, Namespace}; use rustc_hir::def_id::{CRATE_DEF_ID, DefId}; use rustc_middle::ty::error::ExpectedFound; use rustc_middle::ty::print::{FmtPrinter, Print, PrintTraitRefExt as _, RegionHighlightMode}; @@ -279,11 +279,12 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { _ => break, } } - let (mut satisfy_span, mut item_span, dup_span, item_name) = + let (mut satisfy_span, mut item_span, outer_span, dup_span, item_name) = if let ObligationCauseCode::WhereClause(def_id, span) | ObligationCauseCode::WhereClauseInExpr(def_id, span, ..) = *code && def_id != CRATE_DEF_ID.to_def_id() { + let parent = self.tcx().parent(def_id); ( Some(span), Some( @@ -291,11 +292,16 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { .opt_item_ident(def_id) .map_or_else(|| self.tcx().def_span(def_id), |n| n.span), ), + if let DefKind::Trait | DefKind::Impl { .. } = self.tcx().def_kind(parent) { + Some(self.tcx().def_span(parent).shrink_to_lo()) + } else { + None + }, None, self.tcx().def_path_str(def_id), ) } else { - (None, None, Some(span), String::new()) + (None, None, None, Some(span), String::new()) }; if let Some(span) = satisfy_span && span.is_dummy() @@ -380,6 +386,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { any_self_ty_has_vid, satisfy_span, item_span, + outer_span, item_name, ); @@ -510,6 +517,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { any_self_ty_has_vid: bool, satisfy_span: Option, item_span: Option, + outer_span: Option, item_name: String, ) -> Vec> { // The weird thing here with the `maybe_highlighting_region` calls and the @@ -614,6 +622,7 @@ impl<'tcx> NiceRegionError<'_, 'tcx> { lifetime_2, satisfy_span, item_span, + outer_span, item_name, ); diff --git a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr index fe84512e6f12e..9e56955aff17b 100644 --- a/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr +++ b/tests/ui/generic-associated-types/gat-bounds-not-checked-with-right-substitutions.stderr @@ -7,6 +7,7 @@ LL | type Gat<'a> = &'a str; note: `Lengthen<&'0 str>` would have to be implemented for the type `&'a str`, for any lifetime `'0`... --> $DIR/gat-bounds-not-checked-with-right-substitutions.rs:12:19 | +LL | trait Gat { LL | type Gat<'a>: for<'b> Lengthen>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Gat::Gat` = note: ...but `Lengthen<&'1 str>` is actually implemented for the type `&'1 str`, for some specific lifetime `'1` diff --git a/tests/ui/nll/issue-54302-cases.stderr b/tests/ui/nll/issue-54302-cases.stderr index 0ebd0293eccca..78acd3d640eef 100644 --- a/tests/ui/nll/issue-54302-cases.stderr +++ b/tests/ui/nll/issue-54302-cases.stderr @@ -7,6 +7,7 @@ LL | >::ref_foo(a) note: `Foo<'static, u32>` would have to be implemented for the type `&'0 u32`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u32>` is actually implemented for the type `&'1 u32`, for some specific lifetime `'1` @@ -20,6 +21,7 @@ LL | >::ref_foo(a) note: `Foo<'static, i32>` would have to be implemented for the type `&'0 i32`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i32>` is actually implemented for the type `&'1 i32`, for some specific lifetime `'1` @@ -33,6 +35,7 @@ LL | >::ref_foo(a) note: `Foo<'static, u64>` would have to be implemented for the type `&'0 u64`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, u64>` is actually implemented for the type `&'1 u64`, for some specific lifetime `'1` @@ -46,6 +49,7 @@ LL | >::ref_foo(a) note: `Foo<'static, i64>` would have to be implemented for the type `&'0 i64`, for any lifetime `'0`... --> $DIR/issue-54302-cases.rs:51:8 | +LL | trait RefFoo { LL | fn ref_foo(&self) -> &'static T; | ^^^^^^^ required due to a bound in `RefFoo::ref_foo` = note: ...but `Foo<'_, i64>` is actually implemented for the type `&'1 i64`, for some specific lifetime `'1` diff --git a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr index 1917b5ca9cea1..af896df38aa49 100644 --- a/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr +++ b/tests/ui/nll/relate_tys/impl-fn-ignore-binder-via-bottom.stderr @@ -7,6 +7,8 @@ LL | let _x = ::make_f(); note: `Y` would have to be implemented for the type `for<'a> fn(&'a ())` --> $DIR/impl-fn-ignore-binder-via-bottom.rs:18:8 | +LL | trait Y { +LL | type F; LL | fn make_f() -> Self::F; | ^^^^^^ required due to a bound in `Y::make_f` = note: ...but `Y` is actually implemented for the type `fn(&'0 ())`, for some specific lifetime `'0` From f296fdf92ad3252d0d33e8e4a06a5ca0cb2c5d31 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 3 Oct 2026 20:07:41 +0200 Subject: [PATCH 1230/1309] implement FCW for `rustc_allowed_through_unstable_modules` items --- compiler/rustc_lint_defs/src/builtin.rs | 26 ++ compiler/rustc_passes/src/stability.rs | 6 +- .../clippy/tests/ui/std_instead_of_core.fixed | 2 +- .../clippy/tests/ui/std_instead_of_core.rs | 2 +- .../tests/ui/std_instead_of_core.stderr | 26 +- .../accidental-stable-in-unstable.rs | 3 +- .../accidental-stable-in-unstable.stderr | 24 +- .../accidentally-stable-intrinsics.fixed | 12 +- .../accidentally-stable-intrinsics.rs | 12 +- .../accidentally-stable-intrinsics.stderr | 224 ++++++++++++++++-- .../allowed-through-unstable.rs | 3 +- .../allowed-through-unstable.stderr | 30 ++- .../issue-99286-stable-intrinsics.rs | 2 +- .../issue-99286-stable-intrinsics.stderr | 90 +++++++ 14 files changed, 419 insertions(+), 43 deletions(-) create mode 100644 tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index a722f0e103ea1..34c7e3f19a631 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -137,6 +137,7 @@ pub mod hardwired { UNREACHABLE_PATTERNS, UNSAFE_ATTR_OUTSIDE_UNSAFE, UNSAFE_OP_IN_UNSAFE_FN, + UNSTABLE_IMPORTS, UNSTABLE_NAME_COLLISIONS, UNSTABLE_SYNTAX_PRE_EXPANSION, UNSUPPORTED_CALLING_CONVENTIONS, @@ -5857,3 +5858,28 @@ declare_lint! { "`repr(C, align)` types nested inside `repr(C, packed)` types \ do not always have a C-compatible layout", } + +declare_lint! { + /// The `unstable_imports` lints detects imports that go through unstable modules. + /// + /// ### Example + /// + /// ```rust + /// use core::intrinsics::transmute; + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Previous versions of Rust accidentally allowed certain imports through unstable modules + /// because stability information of modules was not correctly accounted for if the imported + /// item was stable itself. + pub UNSTABLE_IMPORTS, + Deny, + "lints on accidentally allowed unstable imports", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError # 163160), + report_in_deps: true, + }; +} diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs index d607d929b0db6..162914c95c0e5 100644 --- a/compiler/rustc_passes/src/stability.rs +++ b/compiler/rustc_passes/src/stability.rs @@ -19,8 +19,8 @@ use rustc_hir::{ UsePath, Variant, }; use rustc_lint_defs::builtin::{ - DEPRECATED, DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_REEXPORTS, - INEFFECTIVE_UNSTABLE_TRAIT_IMPL, STABLE_FEATURES, + DUPLICATE_FEATURES, INEFFECTIVE_UNSTABLE_REEXPORTS, INEFFECTIVE_UNSTABLE_TRAIT_IMPL, + STABLE_FEATURES, UNSTABLE_IMPORTS, }; use rustc_middle::hir::nested_filter; use rustc_middle::middle::lib_features::{FeatureStability, LibFeatures}; @@ -1079,7 +1079,7 @@ impl<'tcx> Checker<'tcx> { suggestion, }; self.tcx.emit_node_span_lint( - DEPRECATED, + UNSTABLE_IMPORTS, id, method_span.unwrap_or(span), diag, diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.fixed b/src/tools/clippy/tests/ui/std_instead_of_core.fixed index c162dcb0451e2..208678a71cf35 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.fixed +++ b/src/tools/clippy/tests/ui/std_instead_of_core.fixed @@ -1,7 +1,6 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] -#![expect(deprecated)] extern crate alloc; @@ -77,6 +76,7 @@ mod std_in_proc_macro_derive { // replacing std -> core fn intrinsic(a: *mut u8, b: *mut u8) { unsafe { + #[expect(unstable_imports)] core::intrinsics::copy(a, b, 1); //~^ std_instead_of_core } diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.rs b/src/tools/clippy/tests/ui/std_instead_of_core.rs index 6769af11def6f..8c27c1926fae4 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.rs +++ b/src/tools/clippy/tests/ui/std_instead_of_core.rs @@ -1,7 +1,6 @@ //@aux-build:proc_macro_derive.rs #![warn(clippy::std_instead_of_core)] -#![expect(deprecated)] extern crate alloc; @@ -77,6 +76,7 @@ mod std_in_proc_macro_derive { // replacing std -> core fn intrinsic(a: *mut u8, b: *mut u8) { unsafe { + #[expect(unstable_imports)] std::intrinsics::copy(a, b, 1); //~^ std_instead_of_core } diff --git a/src/tools/clippy/tests/ui/std_instead_of_core.stderr b/src/tools/clippy/tests/ui/std_instead_of_core.stderr index ae0783863fbc2..c18f976412611 100644 --- a/src/tools/clippy/tests/ui/std_instead_of_core.stderr +++ b/src/tools/clippy/tests/ui/std_instead_of_core.stderr @@ -1,5 +1,5 @@ error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:13:9 + --> tests/ui/std_instead_of_core.rs:12:9 | LL | use std::hash::Hasher; | ^^^ help: consider importing the item from `core`: `core` @@ -8,61 +8,61 @@ LL | use std::hash::Hasher; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_core)]` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:16:11 + --> tests/ui/std_instead_of_core.rs:15:11 | LL | use ::std::hash::Hash; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:22:9 + --> tests/ui/std_instead_of_core.rs:21:9 | LL | use std::fmt::{Debug, Result}; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:27:9 + --> tests/ui/std_instead_of_core.rs:26:9 | LL | use std::{ | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:34:15 + --> tests/ui/std_instead_of_core.rs:33:15 | LL | let ptr = std::ptr::null::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:36:21 + --> tests/ui/std_instead_of_core.rs:35:21 | LL | let ptr_mut = ::std::ptr::null_mut::(); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:40:16 + --> tests/ui/std_instead_of_core.rs:39:16 | LL | let cell = std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:42:27 + --> tests/ui/std_instead_of_core.rs:41:27 | LL | let cell_absolute = ::std::cell::Cell::new(8u32); | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:47:9 + --> tests/ui/std_instead_of_core.rs:46:9 | LL | use std::error::Error; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `core` - --> tests/ui/std_instead_of_core.rs:51:9 + --> tests/ui/std_instead_of_core.rs:50:9 | LL | use std::iter::Iterator; | ^^^ help: consider importing the item from `core`: `core` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:58:9 + --> tests/ui/std_instead_of_core.rs:57:9 | LL | use std::vec; | ^^^ help: consider importing the item from `alloc`: `alloc` @@ -71,13 +71,13 @@ LL | use std::vec; = help: to override `-D warnings` add `#[allow(clippy::std_instead_of_alloc)]` error: used import from `std` instead of `alloc` - --> tests/ui/std_instead_of_core.rs:60:9 + --> tests/ui/std_instead_of_core.rs:59:9 | LL | use std::vec::Vec; | ^^^ help: consider importing the item from `alloc`: `alloc` error: used import from `alloc` instead of `core` - --> tests/ui/std_instead_of_core.rs:66:9 + --> tests/ui/std_instead_of_core.rs:65:9 | LL | use alloc::slice::from_ref; | ^^^^^ help: consider importing the item from `core`: `core` diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs index a36a78ee442ce..b52912938539e 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.rs +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.rs @@ -8,4 +8,5 @@ use core::unicode::UNICODE_VERSION; //~ ERROR use of unstable library feature `u // Known accidental stabilizations with known users // fully stable @ core::mem::transmute use core::intrinsics::transmute; // depended upon by rand_core -//~^WARN deprecated +//~^ERROR use of deprecated import through accidentally stabilized module +//~| WARN previously accepted diff --git a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr index b0b1f78cb28b2..b2e8072101759 100644 --- a/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr +++ b/tests/ui/stability-attribute/accidental-stable-in-unstable.stderr @@ -7,19 +7,37 @@ LL | use core::unicode::UNICODE_VERSION; = help: add `#![feature(unicode_internals)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -warning: use of deprecated import through accidentally stabilized module `intrinsics` +error: use of deprecated import through accidentally stabilized module `intrinsics` --> $DIR/accidental-stable-in-unstable.rs:10:5 | LL | use core::intrinsics::transmute; // depended upon by rand_core | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(deprecated)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default help: import this function via the `mem` module instead | LL - use core::intrinsics::transmute; // depended upon by rand_core LL + use core::mem::transmute; // depended upon by rand_core | -error: aborting due to 1 previous error; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. +Future incompatibility report: Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidental-stable-in-unstable.rs:10:5 + | +LL | use core::intrinsics::transmute; // depended upon by rand_core + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - use core::intrinsics::transmute; // depended upon by rand_core +LL + use core::mem::transmute; // depended upon by rand_core + | + diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed index 41917c65f5215..47e42c13a4589 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.fixed @@ -1,26 +1,32 @@ //@ run-rustfix #![crate_type = "lib"] #![allow(unnecessary_transmutes, unused_imports)] -#![deny(deprecated)] extern crate core; use std::mem::transmute as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::copy as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use std::ptr::copy_nonoverlapping as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::write_bytes as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::ptr::{ copy as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted copy_nonoverlapping as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted write_bytes as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted }; pub fn what() { @@ -29,11 +35,15 @@ pub fn what() { let mut dst = 0; let _ = std::mem::transmute::(value); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::ptr::copy(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::ptr::copy_nonoverlapping(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted std::ptr::write_bytes(&mut dst, value, 1) //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted } } diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs index 189927e9e8989..f3d9bd14cf62f 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.rs @@ -1,26 +1,32 @@ //@ run-rustfix #![crate_type = "lib"] #![allow(unnecessary_transmutes, unused_imports)] -#![deny(deprecated)] extern crate core; use std::intrinsics::transmute as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::copy as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use std::intrinsics::copy_nonoverlapping as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::write_bytes as _; //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` +//~| WARN previously accepted use core::intrinsics::{ copy as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted copy_nonoverlapping as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted write_bytes as _, //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted }; pub fn what() { @@ -29,11 +35,15 @@ pub fn what() { let mut dst = 0; let _ = std::intrinsics::transmute::(value); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::intrinsics::copy(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted std::intrinsics::write_bytes(&mut dst, value, 1) //~^ ERROR use of deprecated import through accidentally stabilized module `intrinsics` + //~| WARN previously accepted } } diff --git a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr index 645437a306f74..96f56043af189 100644 --- a/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr +++ b/tests/ui/stability-attribute/accidentally-stable-intrinsics.stderr @@ -1,14 +1,12 @@ error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:8:5 + --> $DIR/accidentally-stable-intrinsics.rs:7:5 | LL | use std::intrinsics::transmute as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | -note: the lint level is defined here - --> $DIR/accidentally-stable-intrinsics.rs:4:9 - | -LL | #![deny(deprecated)] - | ^^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default help: import this function via the `mem` module instead | LL - use std::intrinsics::transmute as _; @@ -21,6 +19,8 @@ error: use of deprecated import through accidentally stabilized module `intrinsi LL | use core::intrinsics::copy as _; | ^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::copy as _; @@ -28,11 +28,13 @@ LL + use core::ptr::copy as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:12:5 + --> $DIR/accidentally-stable-intrinsics.rs:13:5 | LL | use std::intrinsics::copy_nonoverlapping as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use std::intrinsics::copy_nonoverlapping as _; @@ -40,11 +42,13 @@ LL + use std::ptr::copy_nonoverlapping as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:14:5 + --> $DIR/accidentally-stable-intrinsics.rs:16:5 | LL | use core::intrinsics::write_bytes as _; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::write_bytes as _; @@ -52,11 +56,13 @@ LL + use core::ptr::write_bytes as _; | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:18:5 + --> $DIR/accidentally-stable-intrinsics.rs:21:5 | LL | copy as _, | ^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -64,11 +70,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:20:5 + --> $DIR/accidentally-stable-intrinsics.rs:24:5 | LL | copy_nonoverlapping as _, | ^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -76,11 +84,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:22:5 + --> $DIR/accidentally-stable-intrinsics.rs:27:5 | LL | write_bytes as _, | ^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - use core::intrinsics::{ @@ -88,11 +98,13 @@ LL + use core::ptr::{ | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:30:17 + --> $DIR/accidentally-stable-intrinsics.rs:36:17 | LL | let _ = std::intrinsics::transmute::(value); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `mem` module instead | LL - let _ = std::intrinsics::transmute::(value); @@ -100,11 +112,13 @@ LL + let _ = std::mem::transmute::(value); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:32:9 + --> $DIR/accidentally-stable-intrinsics.rs:39:9 | LL | core::intrinsics::copy(&value, &mut dst, 1); | ^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - core::intrinsics::copy(&value, &mut dst, 1); @@ -112,11 +126,13 @@ LL + core::ptr::copy(&value, &mut dst, 1); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:34:9 + --> $DIR/accidentally-stable-intrinsics.rs:42:9 | LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); @@ -124,11 +140,13 @@ LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); | error: use of deprecated import through accidentally stabilized module `intrinsics` - --> $DIR/accidentally-stable-intrinsics.rs:36:9 + --> $DIR/accidentally-stable-intrinsics.rs:45:9 | LL | std::intrinsics::write_bytes(&mut dst, value, 1) | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 help: import this function via the `ptr` module instead | LL - std::intrinsics::write_bytes(&mut dst, value, 1) @@ -137,3 +155,179 @@ LL + std::ptr::write_bytes(&mut dst, value, 1) error: aborting due to 11 previous errors +Future incompatibility report: Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:7:5 + | +LL | use std::intrinsics::transmute as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - use std::intrinsics::transmute as _; +LL + use std::mem::transmute as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:10:5 + | +LL | use core::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::copy as _; +LL + use core::ptr::copy as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:13:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:16:5 + | +LL | use core::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::write_bytes as _; +LL + use core::ptr::write_bytes as _; + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:21:5 + | +LL | copy as _, + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:24:5 + | +LL | copy_nonoverlapping as _, + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:27:5 + | +LL | write_bytes as _, + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - use core::intrinsics::{ +LL + use core::ptr::{ + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:36:17 + | +LL | let _ = std::intrinsics::transmute::(value); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `mem` module instead + | +LL - let _ = std::intrinsics::transmute::(value); +LL + let _ = std::mem::transmute::(value); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:39:9 + | +LL | core::intrinsics::copy(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy(&value, &mut dst, 1); +LL + core::ptr::copy(&value, &mut dst, 1); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:42:9 + | +LL | core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - core::intrinsics::copy_nonoverlapping(&value, &mut dst, 1); +LL + core::ptr::copy_nonoverlapping(&value, &mut dst, 1); + | + +Future breakage diagnostic: +error: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/accidentally-stable-intrinsics.rs:45:9 + | +LL | std::intrinsics::write_bytes(&mut dst, value, 1) + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 + = note: `#[deny(unstable_imports)]` (part of `#[deny(future_incompatible)]`) on by default +help: import this function via the `ptr` module instead + | +LL - std::intrinsics::write_bytes(&mut dst, value, 1) +LL + std::ptr::write_bytes(&mut dst, value, 1) + | + diff --git a/tests/ui/stability-attribute/allowed-through-unstable.rs b/tests/ui/stability-attribute/allowed-through-unstable.rs index eaa3ad9b830b4..4af64189dbfe3 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.rs +++ b/tests/ui/stability-attribute/allowed-through-unstable.rs @@ -2,8 +2,9 @@ // //@ aux-build:allowed-through-unstable-core.rs #![crate_type = "lib"] - +#![warn(unstable_imports)] extern crate allowed_through_unstable_core; use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; //~WARN use of deprecated import through accidentally stabilized module `unstable_module` +//~| WARN previously accepted use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; //~ ERROR use of unstable library feature `unstable_test_feature` diff --git a/tests/ui/stability-attribute/allowed-through-unstable.stderr b/tests/ui/stability-attribute/allowed-through-unstable.stderr index 160dd4d4babff..6f2e0bf7a1fe9 100644 --- a/tests/ui/stability-attribute/allowed-through-unstable.stderr +++ b/tests/ui/stability-attribute/allowed-through-unstable.stderr @@ -4,7 +4,13 @@ warning: use of deprecated import through accidentally stabilized module `unstab LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: `#[warn(deprecated)]` on by default + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +note: the lint level is defined here + --> $DIR/allowed-through-unstable.rs:5:9 + | +LL | #![warn(unstable_imports)] + | ^^^^^^^^^^^^^^^^ help: use the new path instead | LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; @@ -12,7 +18,7 @@ LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnsta | error[E0658]: use of unstable library feature `unstable_test_feature` - --> $DIR/allowed-through-unstable.rs:9:36 + --> $DIR/allowed-through-unstable.rs:10:36 | LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowedThroughUnstable; | ^^^^^^^^^^^^^^^ @@ -24,3 +30,23 @@ LL | use allowed_through_unstable_core::unstable_module::NewStableTraitNotAllowe error: aborting due to 1 previous error; 1 warning emitted For more information about this error, try `rustc --explain E0658`. +Future incompatibility report: Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `unstable_module` + --> $DIR/allowed-through-unstable.rs:8:5 + | +LL | use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +note: the lint level is defined here + --> $DIR/allowed-through-unstable.rs:5:9 + | +LL | #![warn(unstable_imports)] + | ^^^^^^^^^^^^^^^^ +help: use the new path instead + | +LL - use allowed_through_unstable_core::unstable_module::OldStableTraitAllowedThoughUnstable; +LL + use allowed_through_unstable_core::stable::OldStableTraitAllowedThoughUnstable; + | + diff --git a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs index d9e810362f2e9..9af880b63042b 100644 --- a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs +++ b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.rs @@ -6,7 +6,7 @@ // is unstable. #![allow(unused_imports)] -#![allow(deprecated)] +#![allow(unstable_imports)] use std::intrinsics::copy_nonoverlapping as _; use std::intrinsics::copy as _; diff --git a/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr new file mode 100644 index 0000000000000..5391a1a43889d --- /dev/null +++ b/tests/ui/stability-attribute/issue-99286-stable-intrinsics.stderr @@ -0,0 +1,90 @@ +Future incompatibility report: Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:11:5 + | +LL | use std::intrinsics::copy_nonoverlapping as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy_nonoverlapping as _; +LL + use std::ptr::copy_nonoverlapping as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:12:5 + | +LL | use std::intrinsics::copy as _; + | ^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::copy as _; +LL + use std::ptr::copy as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:13:5 + | +LL | use std::intrinsics::write_bytes as _; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::write_bytes as _; +LL + use std::ptr::write_bytes as _; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:23 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:44 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + +Future breakage diagnostic: +warning: use of deprecated import through accidentally stabilized module `intrinsics` + --> $DIR/issue-99286-stable-intrinsics.rs:14:50 + | +LL | use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; + | ^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163160 +help: import this function via the `ptr` module instead + | +LL - use std::intrinsics::{copy_nonoverlapping, copy, write_bytes}; +LL + use std::ptr::{copy_nonoverlapping, copy, write_bytes}; + | + From 0103c947a52c4f82123f174881aae86a136fc3ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Thu, 18 Jun 2026 20:28:36 +0000 Subject: [PATCH 1231/1309] When compiling without a specified `--edition`, emit a `eprintln` message Use same wording as cargo does when `package.edition` is unspecified. Do not suggest `--edition=future` on stable. --- compiler/rustc_driver_impl/src/lib.rs | 14 +++- compiler/rustc_interface/src/tests.rs | 10 +-- compiler/rustc_session/src/config.rs | 46 ++++++++---- compiler/rustc_span/src/edition.rs | 21 ++++-- src/librustdoc/config.rs | 4 +- src/tools/compiletest/src/directives.rs | 9 +-- src/tools/compiletest/src/rustdoc_gui_test.rs | 5 +- tests/run-make/broken-pipe-no-ice/rmake.rs | 2 +- tests/run-make/compressed-debuginfo/rmake.rs | 1 + .../const-destruct-stable-toolchain/rmake.rs | 2 + .../const-trait-stable-toolchain/rmake.rs | 4 + .../rmake.rs | 3 +- .../rmake.rs | 15 +++- tests/run-make/crate-loading/rmake.rs | 11 ++- tests/run-make/emit-to-stdout/rmake.rs | 22 +++++- tests/run-make/jobserver-error/rmake.rs | 2 + tests/run-make/linker-warning/rmake.rs | 10 ++- .../missing-unstable-trait-bound/rmake.rs | 1 + tests/run-make/multiline-args-value/rmake.rs | 3 +- tests/run-make/non-unicode-env/rmake.rs | 6 +- .../run-make/option-output-no-space/rmake.rs | 34 +++++++-- tests/run-make/overwrite-input/rmake.rs | 5 +- .../pointer-auth-link-with-c/rmake.rs | 3 + .../rmake.rs | 5 +- .../rustdoc/doctest/test_harness/rmake.rs | 1 + tests/run-make/target-cpu-native/rmake.rs | 1 + tests/run-make/unknown-mod-stdin/rmake.rs | 3 +- .../help-unspecified-edition.stdout | 74 +++++++++++++++++++ tests/run-make/unspecified-edition/main.rs | 1 + tests/run-make/unspecified-edition/rmake.rs | 39 ++++++++++ ...specified-edition-without-compiling.stderr | 4 + .../unspecified-edition.stderr | 2 + 32 files changed, 302 insertions(+), 61 deletions(-) create mode 100644 tests/run-make/unspecified-edition/help-unspecified-edition.stdout create mode 100644 tests/run-make/unspecified-edition/main.rs create mode 100644 tests/run-make/unspecified-edition/rmake.rs create mode 100644 tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr create mode 100644 tests/run-make/unspecified-edition/unspecified-edition.stderr diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs index 959222b19c6e9..1ba7ce953b5d4 100644 --- a/compiler/rustc_driver_impl/src/lib.rs +++ b/compiler/rustc_driver_impl/src/lib.rs @@ -184,14 +184,24 @@ pub fn compiler_entrypoint(at_args: &[String], callbacks: &mut (dyn Callbacks + let args = args::arg_expand_all(&default_early_dcx, at_args); + // For the purposes of checking that an --edition was passed, we only emit a message if the only + // argument passed to rustc is a file name. + let warn_unspecified_edition = match &args[..] { + [] => false, + // We explicitly don't emit the note if we're consuming code from stdin, or passing non-file + // flags. This can happen on some cargo invocations too. + [name] if name.starts_with("-") => false, + [_] => true, + _ => false, + }; let (matches, help_only) = match handle_options(&default_early_dcx, &args) { HandledOptions::None => return, HandledOptions::Normal(matches) => (matches, false), HandledOptions::HelpOnly(matches) => (matches, true), }; - let sopts = config::build_session_options(&mut default_early_dcx, &matches); - // fully initialize ice path static once unstable options are available as context + let sopts = + config::build_session_options(&mut default_early_dcx, &matches, warn_unspecified_edition); let ice_file = ice_path_with_config(Some(&sopts.unstable_opts)).clone(); if let Some(ref code) = matches.opt_str("explain") { diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2f9489ac67ad4..2dfb8f04f58f2 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -42,7 +42,7 @@ where { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(args).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, true); let target = rustc_session::config::build_target_config( &early_dcx, &sessopts.target_triple, @@ -942,7 +942,7 @@ fn test_edition_parsing() { let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); let matches = optgroups().parse(&["--edition=2018".to_string()]).unwrap(); - let sessopts = build_session_options(&mut early_dcx, &matches); + let sessopts = build_session_options(&mut early_dcx, &matches, false); assert!(sessopts.edition == Edition::Edition2018) } @@ -953,7 +953,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { // `-Zassumptions-on-binders` alone enables the next solver globally. let matches = optgroups().parse(&["-Zassumptions-on-binders".to_string()]).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); @@ -964,7 +964,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=coherence".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } @@ -977,7 +977,7 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { ["-Znext-solver=no".to_string(), "-Zassumptions-on-binders".to_string()], ] { let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches); + let opts = build_session_options(&mut early_dcx, &matches, false); assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); } diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index 798dcaf969965..fdfc2aacc79a8 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -21,7 +21,9 @@ use rustc_errors::{ColorConfig, DiagCtxtFlags}; use rustc_feature::UnstableFeatures; use rustc_hashes::Hash64; use rustc_macros::{BlobDecodable, Decodable, Encodable, StableHash}; -use rustc_span::edition::{DEFAULT_EDITION, EDITION_NAME_LIST, Edition, LATEST_STABLE_EDITION}; +use rustc_span::edition::{ + DEFAULT_EDITION, EDITION_NAME_LIST, EDITION_NAME_LIST_STABLE, Edition, LATEST_STABLE_EDITION, +}; use rustc_span::source_map::FilePathMapping; use rustc_span::{ FileName, RealFileName, RemapPathScopeComponents, SourceFileHashAlgorithm, Symbol, sym, @@ -2369,22 +2371,35 @@ pub fn parse_error_format( error_format } -pub fn parse_crate_edition(early_dcx: &EarlyDiagCtxt, matches: &getopts::Matches) -> Edition { +pub fn parse_crate_edition( + early_dcx: &EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Edition { + let is_nightly = nightly_options::match_is_nightly_build(matches); + let edition_list = if is_nightly { EDITION_NAME_LIST } else { EDITION_NAME_LIST_STABLE }; let edition = match matches.opt_str("edition") { Some(arg) => Edition::from_str(&arg).unwrap_or_else(|_| { early_dcx.early_fatal(format!( - "argument for `--edition` must be one of: \ - {EDITION_NAME_LIST}. (instead was `{arg}`)" + "argument for `--edition` must be one of: {edition_list} (instead was `{arg}`)", )) }), - None => DEFAULT_EDITION, + None => { + if has_input { + eprintln!( + "`--edition` is unspecified, defaulting to `{DEFAULT_EDITION}` while the \ + latest is `{LATEST_STABLE_EDITION}`; it must be one of: {edition_list}\n", + ); + } + DEFAULT_EDITION + } }; if !edition.is_stable() && !nightly_options::is_unstable_enabled(matches) { - let is_nightly = nightly_options::match_is_nightly_build(matches); let msg = if !is_nightly { format!( - "the crate requires edition {edition}, but the latest edition supported by this Rust version is {LATEST_STABLE_EDITION}" + "the crate requires edition {edition}, but the latest edition supported by this \ + Rust version is {LATEST_STABLE_EDITION}" ) } else { format!("edition {edition} is unstable and only available with -Z unstable-options") @@ -2681,10 +2696,14 @@ fn parse_remap_path_prefix( // JUSTIFICATION: before wrapper fn is available #[allow(rustc::bad_opt_access)] -pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::Matches) -> Options { +pub fn build_session_options( + early_dcx: &mut EarlyDiagCtxt, + matches: &getopts::Matches, + has_input: bool, +) -> Options { let color = parse_color(early_dcx, matches); - let edition = parse_crate_edition(early_dcx, matches); + let edition = parse_crate_edition(early_dcx, matches, has_input); let crate_name = matches.opt_str("crate-name"); let unstable_features = UnstableFeatures::from_environment(crate_name.as_deref()); @@ -2852,14 +2871,13 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if !unstable_options_enabled && cg.force_frame_pointers == FramePointer::NonLeaf { early_dcx.early_fatal( "`-Cforce-frame-pointers=non-leaf` or `always` also requires `-Zunstable-options` \ - and a nightly compiler", + and a nightly compiler", ) } if !nightly_options::is_unstable_enabled(matches) && !unstable_opts.offload.is_empty() { early_dcx.early_fatal( - "`-Zoffload=Enable` also requires `-Zunstable-options` \ - and a nightly compiler", + "`-Zoffload=Enable` also requires `-Zunstable-options` and a nightly compiler", ) } @@ -2875,8 +2893,8 @@ pub fn build_session_options(early_dcx: &mut EarlyDiagCtxt, matches: &getopts::M if let Some(flavor) = cg.linker_flavor { if flavor.is_unstable() { early_dcx.early_fatal(format!( - "the linker flavor `{}` is unstable, the `-Z unstable-options` \ - flag must also be passed to use the unstable values", + "the linker flavor `{}` is unstable, the `-Z unstable-options` flag must also \ + be passed to use the unstable values", flavor.desc() )); } diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs index 38165f511b417..d4f3f0e208e34 100644 --- a/compiler/rustc_span/src/edition.rs +++ b/compiler/rustc_span/src/edition.rs @@ -45,7 +45,10 @@ pub const ALL_EDITIONS: &[Edition] = &[ Edition::EditionFuture, ]; +/// All the valid editions that `--edition` will accept on nightly. pub const EDITION_NAME_LIST: &str = "<2015|2018|2021|2024|future>"; +/// All the valid editions on stable, which doesn't include `future`. +pub const EDITION_NAME_LIST_STABLE: &str = "<2015|2018|2021|2024>"; pub const DEFAULT_EDITION: Edition = Edition::Edition2015; @@ -53,13 +56,7 @@ pub const LATEST_STABLE_EDITION: Edition = Edition::Edition2024; impl fmt::Display for Edition { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - let s = match *self { - Edition::Edition2015 => "2015", - Edition::Edition2018 => "2018", - Edition::Edition2021 => "2021", - Edition::Edition2024 => "2024", - Edition::EditionFuture => "future", - }; + let s = self.as_str(); write!(f, "{s}") } } @@ -75,6 +72,16 @@ impl Edition { } } + pub fn as_str(&self) -> &'static str { + match *self { + Edition::Edition2015 => "2015", + Edition::Edition2018 => "2018", + Edition::Edition2021 => "2021", + Edition::Edition2024 => "2024", + Edition::EditionFuture => "future", + } + } + pub fn is_stable(self) -> bool { match self { Edition::Edition2015 => true, diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index fb89a6547a931..170352dabf656 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -777,7 +777,9 @@ impl Options { } } - let edition = config::parse_crate_edition(early_dcx, matches); + // We don't want rustdoc invocations to complain about the lack of `--edition`. + let has_input = false; + let edition = config::parse_crate_edition(early_dcx, matches, has_input); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( diff --git a/src/tools/compiletest/src/directives.rs b/src/tools/compiletest/src/directives.rs index 94e949b78d0a1..1037b2c6375b7 100644 --- a/src/tools/compiletest/src/directives.rs +++ b/src/tools/compiletest/src/directives.rs @@ -405,11 +405,10 @@ impl TestProps { } } - if let Some(edition) = self.edition.or(config.edition) { - // The edition is added at the start, since flags from //@compile-flags must be passed - // to rustc last. - self.compile_flags.insert(0, format!("--edition={edition}")); - } + let edition = self.edition.or(config.edition).unwrap_or(Edition::Year(2015)); + // The edition is added at the start, since flags from //@compile-flags must be passed + // to rustc last. + self.compile_flags.insert(0, format!("--edition={edition}")); } fn update_pass_fail_mode(&mut self, ln: &DirectiveLine<'_>, config: &Config) { diff --git a/src/tools/compiletest/src/rustdoc_gui_test.rs b/src/tools/compiletest/src/rustdoc_gui_test.rs index 5a768519f616d..4e1d1138b3168 100644 --- a/src/tools/compiletest/src/rustdoc_gui_test.rs +++ b/src/tools/compiletest/src/rustdoc_gui_test.rs @@ -33,7 +33,10 @@ impl RustdocGuiTestProps { let props = TestProps::from_file(test_file_path, None, &config); - let TestProps { compile_flags, run_flags, .. } = props; + let TestProps { mut compile_flags, run_flags, .. } = props; + // We don't want to pass `--edition=2015` in, which is being set by default by + // `TestProps::from_file`. + compile_flags.remove(0); Self { compile_flags, run_flags } } } diff --git a/tests/run-make/broken-pipe-no-ice/rmake.rs b/tests/run-make/broken-pipe-no-ice/rmake.rs index b0a28b6c899da..0e43ebda9c3e1 100644 --- a/tests/run-make/broken-pipe-no-ice/rmake.rs +++ b/tests/run-make/broken-pipe-no-ice/rmake.rs @@ -68,7 +68,7 @@ fn check_broken_pipe_handled_gracefully(bin: Binary, mut cmd: Command) { fn main() { let mut rustc = bare_rustc(); - rustc.arg("--print=sysroot"); + rustc.arg("--print=sysroot").edition("2015"); let rustc = rustc.into_raw_command(); check_broken_pipe_handled_gracefully(Binary::Rustc, rustc); diff --git a/tests/run-make/compressed-debuginfo/rmake.rs b/tests/run-make/compressed-debuginfo/rmake.rs index 45bfaa6041d97..4a5305a87cbfb 100644 --- a/tests/run-make/compressed-debuginfo/rmake.rs +++ b/tests/run-make/compressed-debuginfo/rmake.rs @@ -12,6 +12,7 @@ use run_make_support::{assert_contains, llvm_readobj, run_in_tmpdir, rustc}; fn check_compression(compression: &str, to_find: &str) { run_in_tmpdir(|| { let out = rustc() + .edition("2015") .crate_name("foo") .crate_type("lib") .emit("obj") diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index c4990582d40ba..47d66cf267ab9 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -10,12 +10,14 @@ use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() .input("const-drop.rs") + .edition("2015") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") .stderr_utf8(); diff().expected_file("const-drop-stable.stderr").actual_text("(rustc)", &out).run(); let out = rustc() .input("const-drop.rs") + .edition("2015") .ui_testing() .run_fail() .assert_stderr_contains( diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index c778873463063..a13b1cb936bbb 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -8,6 +8,7 @@ use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .run_fail() @@ -22,6 +23,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .cfg("feature_enabled") .ui_testing() @@ -34,6 +36,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = stable_bare_rustc() + .edition("2015") .input("const-super-trait.rs") .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") @@ -44,6 +47,7 @@ fn main() { .actual_text("(rustc)", &out) .run(); let out = rustc() + .edition("2015") .input("const-super-trait.rs") .ui_testing() .run_fail() diff --git a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs index 57e0cab92f1ef..f49a848052411 100644 --- a/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs +++ b/tests/run-make/crate-loading-crate-depends-on-itself/rmake.rs @@ -10,9 +10,10 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("foo-prev.rs").run(); + rustc().edition("2015").input("foo-prev.rs").run(); let out = rustc() + .edition("2015") .extra_filename("current") .metadata("current") .input("foo-current.rs") diff --git a/tests/run-make/crate-loading-multiple-candidates/rmake.rs b/tests/run-make/crate-loading-multiple-candidates/rmake.rs index ce090850500b8..9775a1672f0cb 100644 --- a/tests/run-make/crate-loading-multiple-candidates/rmake.rs +++ b/tests/run-make/crate-loading-multiple-candidates/rmake.rs @@ -9,8 +9,18 @@ use run_make_support::{bare_rustc, diff, rfs, rustc}; fn main() { // Check that relative paths are preserved in the diagnostic rfs::create_dir("mylibs"); - rustc().input("crateresolve1-1.rs").out_dir("mylibs").extra_filename("-1").run(); - rustc().input("crateresolve1-2.rs").out_dir("mylibs").extra_filename("-2").run(); + rustc() + .edition("2015") + .input("crateresolve1-1.rs") + .out_dir("mylibs") + .extra_filename("-1") + .run(); + rustc() + .edition("2015") + .input("crateresolve1-2.rs") + .out_dir("mylibs") + .extra_filename("-2") + .run(); check("./mylibs"); // Check that symlinks aren't followed when printing the diagnostic @@ -21,6 +31,7 @@ fn main() { fn check(library_path: &str) { let out = rustc() + .edition("2015") .input("multiple-candidates.rs") .library_search_path(library_path) .ui_testing() diff --git a/tests/run-make/crate-loading/rmake.rs b/tests/run-make/crate-loading/rmake.rs index 8f2577861239d..79f14e1851eff 100644 --- a/tests/run-make/crate-loading/rmake.rs +++ b/tests/run-make/crate-loading/rmake.rs @@ -6,11 +6,16 @@ use run_make_support::{diff, rust_lib_name, rustc}; fn main() { - rustc().input("dependency-1.rs").run(); - rustc().input("dependency-2.rs").extra_filename("2").metadata("2").run(); - rustc().input("dep-2-reexport.rs").extern_("dependency", rust_lib_name("dependency2")).run(); + rustc().edition("2015").input("dependency-1.rs").run(); + rustc().edition("2015").input("dependency-2.rs").extra_filename("2").metadata("2").run(); + rustc() + .edition("2015") + .input("dep-2-reexport.rs") + .extern_("dependency", rust_lib_name("dependency2")) + .run(); let out = rustc() + .edition("2015") .input("multiple-dep-versions.rs") .extern_("dependency", rust_lib_name("dependency")) .extern_("dep_2_reexport", rust_lib_name("foo")) diff --git a/tests/run-make/emit-to-stdout/rmake.rs b/tests/run-make/emit-to-stdout/rmake.rs index 19c15b72fe475..851ab3cb45881 100644 --- a/tests/run-make/emit-to-stdout/rmake.rs +++ b/tests/run-make/emit-to-stdout/rmake.rs @@ -13,8 +13,9 @@ use run_make_support::{diff, run_in_tmpdir, rustc}; // Test emitting text outputs to stdout works correctly fn run_diff(name: &str, file_args: &[&str]) { - rustc().emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); - let out = rustc().emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); + rustc().edition("2015").emit(format!("{name}={name}")).input("test.rs").args(file_args).run(); + let out = + rustc().edition("2015").emit(format!("{name}=-")).input("test.rs").run().stdout_utf8(); diff().expected_file(name).actual_text("stdout", &out).run(); } @@ -29,7 +30,13 @@ fn run_terminal_err_diff(name: &str) { let terminal = File::options().read(true).write(true).open(r"\\.\CONOUT$").unwrap(); let err = File::create(name).unwrap(); - rustc().emit(format!("{name}=-")).input("test.rs").stdout(terminal).stderr(err).run_fail(); + rustc() + .edition("2015") + .emit(format!("{name}=-")) + .input("test.rs") + .stdout(terminal) + .stderr(err) + .run_fail(); diff().expected_file(format!("emit-{name}.stderr")).actual_file(name).run(); } @@ -47,6 +54,7 @@ fn main() { // Test error for emitting multiple types to stdout rustc() + .edition("2015") .input("test.rs") .emit("asm=-") .emit("llvm-ir=-") @@ -58,6 +66,7 @@ fn main() { // Same as above, but using `-o` rustc() + .edition("2015") .input("test.rs") .output("-") .emit("asm,llvm-ir,dep-info,mir") @@ -69,6 +78,11 @@ fn main() { .run(); // Test that `-o -` redirected to a file works correctly (#26719) - rustc().input("test.rs").output("-").stdout(File::create("out-stdout").unwrap()).run(); + rustc() + .edition("2015") + .input("test.rs") + .output("-") + .stdout(File::create("out-stdout").unwrap()) + .run(); }); } diff --git a/tests/run-make/jobserver-error/rmake.rs b/tests/run-make/jobserver-error/rmake.rs index 265eec7190d4e..80c1562299e72 100644 --- a/tests/run-make/jobserver-error/rmake.rs +++ b/tests/run-make/jobserver-error/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{diff, rustc}; fn main() { let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .env("MAKEFLAGS", "--jobserver-auth=1000,1000") .run_fail() @@ -23,6 +24,7 @@ fn main() { diff().expected_file("cannot_open_fd.stderr").actual_text("actual", out).run(); let out = rustc() + .edition("2015") .stdin_buf(("fn main() {}").as_bytes()) .input("-") .env("MAKEFLAGS", "--jobserver-auth=3,3") diff --git a/tests/run-make/linker-warning/rmake.rs b/tests/run-make/linker-warning/rmake.rs index f1a561e1291a5..8b0c22b0fb940 100644 --- a/tests/run-make/linker-warning/rmake.rs +++ b/tests/run-make/linker-warning/rmake.rs @@ -5,6 +5,7 @@ use run_make_support::{Rustc, diff, regex, rustc}; fn run_rustc() -> Rustc { let mut rustc = rustc(); rustc + .edition("2015") .arg("main.rs") // NOTE: `link-self-contained` can vary depending on bootstrap.toml. // Make sure we use a consistent value. @@ -23,9 +24,9 @@ fn run_rustc() -> Rustc { fn main() { // first, compile our linker and our dependencies - rustc().arg("fake-linker.rs").output("fake-linker").run(); - rustc().arg("foo.rs").crate_type("rlib").run(); - rustc().arg("bar.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("fake-linker.rs").output("fake-linker").run(); + rustc().edition("2015").arg("foo.rs").crate_type("rlib").run(); + rustc().edition("2015").arg("bar.rs").crate_type("rlib").run(); // Run rustc with our fake linker, and make sure it shows warnings let warnings = run_rustc().link_arg("run_make_warn").run(); @@ -93,12 +94,14 @@ fn main() { // Make sure we show linker warnings even across `-Z no-link` rustc() + .edition("2015") .arg("-Zno-link") .input("-") .stdin_buf("#![deny(linker_messages)] \n fn main() {}") .run() .assert_stderr_equals(""); rustc() + .edition("2015") .arg("-Zlink-only") .arg("rust_out.rlink") .linker("./fake-linker") @@ -112,6 +115,7 @@ fn main() { // Same thing, but with json output. rustc() + .edition("2015") .error_format("json") .arg("-Zlink-only") .arg("rust_out.rlink") diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 52a011285c95c..807d24b630fd6 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -11,6 +11,7 @@ use run_make_support::{diff, stable_bare_rustc}; fn main() { let out = stable_bare_rustc() + .edition("2015") .input("missing-bound.rs") .run_fail() .assert_stderr_not_contains("help: consider restricting type parameter `T`") diff --git a/tests/run-make/multiline-args-value/rmake.rs b/tests/run-make/multiline-args-value/rmake.rs index 3964cbbc1e605..f9e6290f7d919 100644 --- a/tests/run-make/multiline-args-value/rmake.rs +++ b/tests/run-make/multiline-args-value/rmake.rs @@ -3,7 +3,8 @@ use run_make_support::{cwd, diff, rustc}; fn test_and_compare(test_name: &str, flag: &str, val: &str) { let mut cmd = rustc(); - let output = cmd.input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); + let output = + cmd.edition("2015").input("").arg("--crate-type=lib").arg(flag).arg(val).run_fail(); assert_eq!(output.stdout_utf8(), ""); diff() diff --git a/tests/run-make/non-unicode-env/rmake.rs b/tests/run-make/non-unicode-env/rmake.rs index b7a3c51db5bfd..7a1c7e4322ddc 100644 --- a/tests/run-make/non-unicode-env/rmake.rs +++ b/tests/run-make/non-unicode-env/rmake.rs @@ -6,7 +6,11 @@ fn main() { let non_unicode: &std::ffi::OsStr = std::os::unix::ffi::OsStrExt::from_bytes(&[0xFF]); #[cfg(windows)] let non_unicode: std::ffi::OsString = std::os::windows::ffi::OsStringExt::from_wide(&[0xD800]); - let output = rustc().input("non_unicode_env.rs").env("NON_UNICODE_VAR", non_unicode).run_fail(); + let output = rustc() + .edition("2015") + .input("non_unicode_env.rs") + .env("NON_UNICODE_VAR", non_unicode) + .run_fail(); let expected = rfs::read_to_string("non_unicode_env.stderr"); output.assert_stderr_equals(expected); } diff --git a/tests/run-make/option-output-no-space/rmake.rs b/tests/run-make/option-output-no-space/rmake.rs index 63d2389890155..d77ae4bef12a8 100644 --- a/tests/run-make/option-output-no-space/rmake.rs +++ b/tests/run-make/option-output-no-space/rmake.rs @@ -7,6 +7,7 @@ use run_make_support::rustc; fn main() { // test fake args rustc() + .edition("2015") .input("main.rs") .arg("-optimize") .run() @@ -17,6 +18,7 @@ fn main() { "= note: output filename `-o ptimize` is applied instead of a flag named `optimize`", ); rustc() + .edition("2015") .input("main.rs") .arg("-o0") .run() @@ -26,9 +28,10 @@ fn main() { .assert_stderr_contains( "= note: output filename `-o 0` is applied instead of a flag named `o0`", ); - rustc().input("main.rs").arg("-o1").run(); + rustc().edition("2015").input("main.rs").arg("-o1").run(); // test real args by iter optgroups rustc() + .edition("2015") .input("main.rs") .arg("-out-dir") .run() @@ -43,6 +46,7 @@ fn main() { ); // test real args by iter CG_OPTIONS rustc() + .edition("2015") .input("main.rs") .arg("-opt_level") .run() @@ -58,6 +62,7 @@ fn main() { ); // separater in-sensitive rustc() + .edition("2015") .input("main.rs") .arg("-opt-level") .run() @@ -72,6 +77,7 @@ fn main() { `-o pt-level`", ); rustc() + .edition("2015") .input("main.rs") .arg("-overflow-checks") .run() @@ -88,10 +94,28 @@ fn main() { ); // No warning for Z_OPTIONS - rustc().input("main.rs").arg("-oom").run().assert_stderr_equals(""); + rustc().edition("2015").input("main.rs").arg("-oom").run().assert_stderr_equals(""); // test no warning when there is space between `-o` and arg - rustc().input("main.rs").arg("-o").arg("ptimize").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("--out-dir").arg("xxx").run().assert_stderr_equals(""); - rustc().input("main.rs").arg("-o").arg("out-dir").run().assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("ptimize") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("--out-dir") + .arg("xxx") + .run() + .assert_stderr_equals(""); + rustc() + .edition("2015") + .input("main.rs") + .arg("-o") + .arg("out-dir") + .run() + .assert_stderr_equals(""); } diff --git a/tests/run-make/overwrite-input/rmake.rs b/tests/run-make/overwrite-input/rmake.rs index bdf7860caa8a0..581fee8fe0136 100644 --- a/tests/run-make/overwrite-input/rmake.rs +++ b/tests/run-make/overwrite-input/rmake.rs @@ -8,8 +8,9 @@ use run_make_support::{diff, rustc}; fn main() { - let file_out = rustc().input("main.rs").output("main.rs").run_fail().stderr_utf8(); - let folder_out = rustc().input("main.rs").output(".").run_fail().stderr_utf8(); + let file_out = + rustc().edition("2015").input("main.rs").output("main.rs").run_fail().stderr_utf8(); + let folder_out = rustc().edition("2015").input("main.rs").output(".").run_fail().stderr_utf8(); diff().expected_file("file.stderr").actual_text("actual-file-stderr", file_out).run(); diff().expected_file("folder.stderr").actual_text("actual-folder-stderr", folder_out).run(); } diff --git a/tests/run-make/pointer-auth-link-with-c/rmake.rs b/tests/run-make/pointer-auth-link-with-c/rmake.rs index 1ac68c95559c6..e5793130c6550 100644 --- a/tests/run-make/pointer-auth-link-with-c/rmake.rs +++ b/tests/run-make/pointer-auth-link-with-c/rmake.rs @@ -16,6 +16,7 @@ use run_make_support::{build_native_static_lib, cc, is_windows_msvc, llvm_ar, ru fn main() { build_native_static_lib("test"); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -30,6 +31,7 @@ fn main() { let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); rustc() + .edition("2015") .arg("-Cunsafe-allow-abi-mismatch=branch-protection") .arg("-Zbranch-protection=bti,gcs,pac-ret,leaf") .input("test.rs") @@ -46,6 +48,7 @@ fn main() { // let obj_file = if is_windows_msvc() { "test.obj" } else { "test" }; // llvm_ar().obj_to_ar().output_input("libtest.a", &obj_file).run(); // rustc() + // .edition("2015") // .arg("-Cunsafe-allow-abi-mismatch=branch-protection") // .arg("-Zbranch-protection=bti,pac-ret,pc,leaf") // .input("test.rs") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index 01572a5aad942..49df84b353cd4 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -8,14 +8,15 @@ use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { let stable_invalid_print_request_help = - stable_bare_rustc().print("xxx").run_fail().stderr_utf8(); + stable_bare_rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(!stable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("stable-invalid-print-request-help.err") .actual_text("stable_invalid_print_request_help", &stable_invalid_print_request_help) .run(); - let unstable_invalid_print_request_help = rustc().print("xxx").run_fail().stderr_utf8(); + let unstable_invalid_print_request_help = + rustc().edition("2015").print("xxx").run_fail().stderr_utf8(); assert!(unstable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("unstable-invalid-print-request-help.err") diff --git a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs index 608adebbd54f2..87d57ca1f76ac 100644 --- a/tests/run-make/rustdoc/doctest/test_harness/rmake.rs +++ b/tests/run-make/rustdoc/doctest/test_harness/rmake.rs @@ -19,6 +19,7 @@ fn main() { rustc().input(runtool_path).run(); let output = rustdoc() + .edition("2015") .input(doctests_path) .arg("--test") // for the outer test suite diff --git a/tests/run-make/target-cpu-native/rmake.rs b/tests/run-make/target-cpu-native/rmake.rs index 5791bf01bba2b..dbea1bda2cab5 100644 --- a/tests/run-make/target-cpu-native/rmake.rs +++ b/tests/run-make/target-cpu-native/rmake.rs @@ -9,6 +9,7 @@ use run_make_support::{run, rustc}; fn main() { let out = rustc() + .edition("2015") .input("foo.rs") .arg("-Ctarget-cpu=native") .arg("-Zverify-llvm-ir") diff --git a/tests/run-make/unknown-mod-stdin/rmake.rs b/tests/run-make/unknown-mod-stdin/rmake.rs index 101711b0d2c70..56833569e54bf 100644 --- a/tests/run-make/unknown-mod-stdin/rmake.rs +++ b/tests/run-make/unknown-mod-stdin/rmake.rs @@ -14,7 +14,8 @@ use run_make_support::{diff, rustc}; fn main() { - let out = rustc().crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); + let out = + rustc().edition("2015").crate_type("rlib").stdin_buf(b"mod unknown;").arg("-").run_fail(); diff() .actual_text("actual-stdout", out.stdout_utf8()) .expected_file("unknown-mod.stdout") diff --git a/tests/run-make/unspecified-edition/help-unspecified-edition.stdout b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout new file mode 100644 index 0000000000000..eea9ae297848a --- /dev/null +++ b/tests/run-make/unspecified-edition/help-unspecified-edition.stdout @@ -0,0 +1,74 @@ +Usage: rustc [OPTIONS] INPUT + +Options: + -h, --help Display this message + --cfg Configure the compilation environment. + SPEC supports the syntax `[=""]`. + --check-cfg + Provide list of expected cfgs for checking + -L [=] Add a directory to the library search path. The + optional KIND can be one of + (default: + all). + -l [[:]=][:] + Link the generated crate(s) to the specified native + library NAME. The optional KIND can be one of + (default: dylib). + Optional comma separated MODIFIERS + + may be specified each with a prefix of either '+' to + enable or '-' to disable. + --crate-type + Comma separated list of types of crates + for the compiler to emit + --crate-name + Specify the name of the crate being built + --edition <2015|2018|2021|2024|future> + Specify which edition of the compiler to use when + compiling code. The default is 2015 and the latest + stable edition is 2024. + --emit [=] + Comma separated list of types of output for the + compiler to emit. + Each TYPE has the default FILE name: + * asm - CRATE_NAME.s + * llvm-bc - CRATE_NAME.bc + * dep-info - CRATE_NAME.d + * link - (platform and crate-type dependent) + * llvm-ir - CRATE_NAME.ll + * metadata - libCRATE_NAME.rmeta + * mir - CRATE_NAME.mir + * obj - CRATE_NAME.o + * thin-link-bitcode - CRATE_NAME.indexing.o + --print [=] + Compiler information to print on stdout (or to a file) + INFO may be one of + . + -g Equivalent to -C debuginfo=2 + -O Equivalent to -C opt-level=3 + -o Write output to FILENAME + --out-dir

    Write output to compiler-chosen filename in DIR + --explain Provide a detailed explanation of an error message + --test Build a test harness + --target + Target tuple for which the code is compiled + -A, --allow Set lint allowed + -W, --warn Set lint warnings + --force-warn + Set lint force-warn + -D, --deny Set lint denied + -F, --forbid Set lint forbidden + --cap-lints + Set the most restrictive lint level. More restrictive + lints are capped at this level + -C, --codegen [=] + Set a codegen option + -V, --version Print version info and exit + -v, --verbose Use verbose output + +Additional help: + -C help Print codegen options + -W help Print 'lint' options and default settings + -Z help Print unstable compiler options + --help -v Print the full set of options rustc accepts + diff --git a/tests/run-make/unspecified-edition/main.rs b/tests/run-make/unspecified-edition/main.rs new file mode 100644 index 0000000000000..f328e4d9d04c3 --- /dev/null +++ b/tests/run-make/unspecified-edition/main.rs @@ -0,0 +1 @@ +fn main() {} diff --git a/tests/run-make/unspecified-edition/rmake.rs b/tests/run-make/unspecified-edition/rmake.rs new file mode 100644 index 0000000000000..d20ac26b8e71d --- /dev/null +++ b/tests/run-make/unspecified-edition/rmake.rs @@ -0,0 +1,39 @@ +// When calling `rustc` without an explicit edition, emit a note asking the user to specify one, +// clarifying that the default is 2015. +//@ needs-target-std +//@ ignore-cross-compile + +use run_make_support::{bare_rustc, diff, rustc, rustdoc}; + +fn main() { + bare_rustc().edition("2015").input("main.rs").run().assert_stderr_not_contains("--edition"); + let out = bare_rustc().input("main.rs").run().assert_stderr_contains("--edition").stderr_utf8(); + diff().expected_file("unspecified-edition.stderr").actual_text("(rustc)", &out).run(); + + // Ensure that we only mention --edition when compiling code. + let out = rustc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_file("unspecified-edition-without-compiling.stderr") + .actual_text("(rustc)", &out) + .run(); + + // Ensure that we dont mention --edition when running rustdoc. + let out = rustdoc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); + diff() + .expected_text("(test)", "error: missing file operand\n\n") + .actual_text("(rustc)", &out) + .run(); + + let out = + rustdoc().input("main.rs").run().assert_stderr_not_contains("--edition").stderr_utf8(); + diff().expected_text("(test)", "").actual_text("(rustc)", &out).run(); + + // Ensure that we don't mention --edition when getting help. + let result = bare_rustc().arg("--help").run(); + result.assert_stderr_not_contains("--edition"); + let out = result.stdout_utf8(); + let err = result.stderr_utf8(); + diff().expected_file("help-unspecified-edition.stdout").actual_text("(rustc)", &out).run(); + diff().expected_text("(test)", "").actual_text("(rustc)", &err).run(); + bare_rustc().arg("--version").run().assert_stderr_not_contains("--edition"); +} diff --git a/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr new file mode 100644 index 0000000000000..c36ecca4af4a2 --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition-without-compiling.stderr @@ -0,0 +1,4 @@ +error: no input filename given + +error: aborting due to 1 previous error + diff --git a/tests/run-make/unspecified-edition/unspecified-edition.stderr b/tests/run-make/unspecified-edition/unspecified-edition.stderr new file mode 100644 index 0000000000000..0a15e47d49fae --- /dev/null +++ b/tests/run-make/unspecified-edition/unspecified-edition.stderr @@ -0,0 +1,2 @@ +`--edition` is unspecified, defaulting to `2015` while the latest is `2024`; it must be one of: <2015|2018|2021|2024|future> + From 552ce44b3780cdb85be47aa01da4cd72d97332bd Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 18:59:23 +0200 Subject: [PATCH 1232/1309] slightly extend window-fs test --- src/tools/miri/src/shims/io_error.rs | 2 +- .../miri/tests/pass-dep/shims/windows-fs.rs | 20 +++++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/src/tools/miri/src/shims/io_error.rs b/src/tools/miri/src/shims/io_error.rs index 67b85ecb8985b..22a176c803819 100644 --- a/src/tools/miri/src/shims/io_error.rs +++ b/src/tools/miri/src/shims/io_error.rs @@ -202,8 +202,8 @@ const WINDOWS_IO_ERROR_TABLE: &[(&str, std::io::ErrorKind)] = { &[ ("WSAEADDRINUSE", AddrInUse), ("WSAEADDRNOTAVAIL", AddrNotAvailable), - ("ERROR_ALREADY_EXISTS", AlreadyExists), ("ERROR_FILE_EXISTS", AlreadyExists), + ("ERROR_ALREADY_EXISTS", AlreadyExists), ("ERROR_NO_DATA", BrokenPipe), ("WSAECONNABORTED", ConnectionAborted), ("WSAECONNREFUSED", ConnectionRefused), diff --git a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs index b012b7328eaf3..d53327341f1e0 100644 --- a/src/tools/miri/tests/pass-dep/shims/windows-fs.rs +++ b/src/tools/miri/tests/pass-dep/shims/windows-fs.rs @@ -16,8 +16,9 @@ mod utils; use windows_sys::Wdk::Storage::FileSystem::{NtReadFile, NtWriteFile}; use windows_sys::Win32::Foundation::{ CloseHandle, DUPLICATE_SAME_ACCESS, DuplicateHandle, ERROR_ACCESS_DENIED, ERROR_ALREADY_EXISTS, - ERROR_IO_DEVICE, FALSE, GENERIC_READ, GENERIC_WRITE, GetLastError, RtlNtStatusToDosError, - STATUS_ACCESS_DENIED, STATUS_IO_DEVICE_ERROR, STATUS_SUCCESS, SetLastError, + ERROR_FILE_EXISTS, ERROR_IO_DEVICE, FALSE, GENERIC_READ, GENERIC_WRITE, GetLastError, + RtlNtStatusToDosError, STATUS_ACCESS_DENIED, STATUS_IO_DEVICE_ERROR, STATUS_SUCCESS, + SetLastError, }; use windows_sys::Win32::Storage::FileSystem::{ BY_HANDLE_FILE_INFORMATION, CREATE_ALWAYS, CREATE_NEW, CreateFileW, DeleteFileW, @@ -74,6 +75,19 @@ unsafe fn test_create_dir_file() { if CloseHandle(handle) == 0 { panic!("Failed to close file") }; + + // Without the FILE_FLAG_BACKUP_SEMANTICS, this does not work. + let handle = CreateFileW( + raw_path.as_ptr(), + GENERIC_READ, + FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, + ptr::null_mut(), + OPEN_EXISTING, + 0, + ptr::null_mut(), + ); + assert_eq!(handle.addr(), usize::MAX); + assert_eq!(GetLastError(), ERROR_ACCESS_DENIED); } unsafe fn test_create_normal_file() { @@ -89,6 +103,7 @@ unsafe fn test_create_normal_file() { ptr::null_mut(), ); assert_ne!(handle.addr(), usize::MAX, "CreateFileW Failed: {}", GetLastError()); + assert_eq!(GetLastError(), 0); let mut info = std::mem::zeroed::(); if GetFileInformationByHandle(handle, &mut info) == 0 { panic!("Failed to get file information: {}", GetLastError()) @@ -110,6 +125,7 @@ unsafe fn test_create_normal_file() { ptr::null_mut(), ); assert_eq!(handle.addr(), usize::MAX, "CreateFileW did not fail"); + assert_eq!(GetLastError(), ERROR_FILE_EXISTS); // Test metadata-only handle let handle = CreateFileW( From ed592ea0f4c8fcefca4f497556292f9bd73ee7d4 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 19:03:42 +0200 Subject: [PATCH 1233/1309] fix windows behavior for '.' relative path --- src/tools/miri/src/shims/unix/fs.rs | 133 +++++++++--------- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 6 + 2 files changed, 70 insertions(+), 69 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 2d1ee758f2de1..3ff5094392b66 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -899,37 +899,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } let path = this.read_path_from_c_str(path)?.into_owned(); - let metadata = if path.is_empty() { - throw_unsup_format!("fstatat: empty path is not supported"); - } else if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { - // Either absolute path (dirfd is ignored) or relative to working directory. - FileMetadata::from_host( - this, - if symlink_nofollow_flag { path.symlink_metadata() } else { path.metadata() }, - )? - } else { - // relative to dirfd, which must be a directory handle - let Some(fd) = this.machine.fds.get(dirfd) else { - return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); - }; - let Some(dir) = fd.downcast::() else { - return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); - }; - - #[cfg(not(bootstrap))] - let metadata = if symlink_nofollow_flag { - dir.dir.symlink_metadata(path) - } else { - dir.dir.metadata(path) - }; - #[cfg(bootstrap)] - let metadata = if symlink_nofollow_flag { - dir.fallback.join(path).symlink_metadata() - } else { - dir.fallback.join(path).metadata() - }; - FileMetadata::from_host(this, metadata)? - }; + // Resolve dirfd + path to metadata. + let metadata = FileMetadata::at( + this, + dirfd, + &path, + symlink_nofollow_flag, + /* empty_path_flag */ false, + )?; let metadata = match metadata { Ok(metadata) => metadata, @@ -985,43 +962,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EACCES")); } - // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file - // represented by dirfd, whether it's a directory or otherwise. - let metadata = if path.is_empty() { - // no path: invalid by default, load metadata about dirfd with flag - if !empty_path_flag { - return this.set_errno_and_return_neg1_i32(LibcError("ENOENT")); - } - FileMetadata::from_fd_num(this, dirfd)? - } else if path.is_absolute() || dirfd == this.eval_libc_i32("AT_FDCWD") { - // Either absolute path (dirfd is ignored) or relative to working directory. - FileMetadata::from_host( - this, - if symlink_nofollow_flag { path.symlink_metadata() } else { path.metadata() }, - )? - } else { - // relative to dirfd, which must be a directory handle - let Some(fd) = this.machine.fds.get(dirfd) else { - return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); - }; - let Some(dir) = fd.downcast::() else { - return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); - }; - - #[cfg(not(bootstrap))] - let metadata = if symlink_nofollow_flag { - dir.dir.symlink_metadata(path) - } else { - dir.dir.metadata(path) - }; - #[cfg(bootstrap)] - let metadata = if symlink_nofollow_flag { - dir.fallback.join(path).symlink_metadata() - } else { - dir.fallback.join(path).metadata() - }; - FileMetadata::from_host(this, metadata)? - }; + // Resolve dirfd + path to metadata. + let metadata = + FileMetadata::at(this, dirfd, &path, symlink_nofollow_flag, empty_path_flag)?; let metadata = match metadata { Ok(metadata) => metadata, @@ -2091,9 +2034,61 @@ struct FileMetadata { } impl FileMetadata { + /// Implements the shared "metadata at" semantics of `fstatat` and `statx`. + fn at<'tcx>( + ecx: &mut MiriInterpCx<'tcx>, + dirfd: FdNum, + path: &Path, + symlink_nofollow_flag: bool, + empty_path_flag: bool, + ) -> InterpResult<'tcx, Result> { + // If the path is empty, and the AT_EMPTY_PATH flag is set, we query the open file + // represented by dirfd, whether it's a directory or otherwise. + if path.is_empty() { + // no path: invalid by default, load metadata about dirfd with flag + if !empty_path_flag { + return interp_ok(Err(LibcError("ENOENT"))); + } + FileMetadata::from_fd_num(ecx, dirfd) + } else if path.is_absolute() || dirfd == ecx.eval_libc_i32("AT_FDCWD") { + // Either absolute path (dirfd is ignored) or relative to working directory. + FileMetadata::from_host( + ecx, + if symlink_nofollow_flag { path.symlink_metadata() } else { path.metadata() }, + ) + } else { + // relative to dirfd, which must be a directory handle + let Some(fd) = ecx.machine.fds.get(dirfd) else { + return interp_ok(Err(LibcError("EBADF"))); + }; + let Some(dir) = fd.downcast::() else { + return interp_ok(Err(LibcError("ENOTDIR"))); + }; + + // Windows does not by itself treat `.` correctly so we do that by hand. + #[cfg(not(bootstrap))] + let metadata = if cfg!(windows) && path.to_str() == Some(".") { + dir.dir.self_metadata() + } else if symlink_nofollow_flag { + dir.dir.symlink_metadata(path) + } else { + dir.dir.metadata(path) + }; + #[cfg(bootstrap)] + let metadata = if cfg!(windows) && path.to_str() == Some(".") { + dir.dir.metadata() + } else if symlink_nofollow_flag { + dir.fallback.join(path).symlink_metadata() + } else { + dir.fallback.join(path).metadata() + }; + FileMetadata::from_host(ecx, metadata) + } + } + fn from_fd_num<'tcx>( ecx: &mut MiriInterpCx<'tcx>, - fd_num: i32, + fd_num: FdNum, ) -> InterpResult<'tcx, Result> { let Some(fd) = ecx.machine.fds.get(fd_num) else { return interp_ok(Err(LibcError("EBADF"))); diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 1142f1182f4bc..32f4b46d6d1dc 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -1000,6 +1000,12 @@ fn test_fstatat() { .unwrap_err(); assert_eq!(err.raw_os_error().unwrap(), libc::EBADF, "unexpected errno: {err}"); + // Empty path errors. (We do not support AT_EMPTY_PATH.) + let err = + errno_result(unsafe { libc::fstatat(libc::AT_FDCWD, c"".as_ptr(), stat.as_mut_ptr(), 0) }) + .unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT, "unexpected errno: {err}"); + if utils::have_symlink_permission() { // Symlink following. let linkname = testdir.join("link"); From 4cc87c17ff1050c77fb4fcb4b1cae5d152b3c7a0 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 12:02:52 +0200 Subject: [PATCH 1234/1309] c_str_alloc_error test: mention why this is mostly Miri-only --- library/alloctests/tests/c_str_alloc_error.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/alloctests/tests/c_str_alloc_error.rs b/library/alloctests/tests/c_str_alloc_error.rs index 669a783645baa..1e7d54d75b332 100644 --- a/library/alloctests/tests/c_str_alloc_error.rs +++ b/library/alloctests/tests/c_str_alloc_error.rs @@ -3,7 +3,7 @@ //! rust-lang/rust#70201 gave `::clone_into` a path that moved the //! target `CString`'s buffer out before growing a `Vec`; if that growth's allocation //! failed and unwound, the target was left without its nul terminator. This only -//! reproduces under Miri: in a normal build the `#[global_allocator]` below can't +//! reproduces under Miri: in a normal build, the `#[global_allocator]` below can't //! intercept the reallocation inside `CString::clone_into` (it lives in libstd, which //! library tests link with `-C prefer-dynamic`), so as a regular test it just checks //! the happy path. @@ -46,6 +46,8 @@ unsafe impl GlobalAlloc for OneShotFailingAlloc { } } +// This doesn't actually do anything outside Miri because of `-C prefer-dynamic` which effectively +// hard-codes the default allocator. #[global_allocator] static ALLOC: OneShotFailingAlloc = OneShotFailingAlloc; From e14ff840ee100651faa6b5e6f104492542b520b2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 20:53:36 +0200 Subject: [PATCH 1235/1309] fix forwarding O_NOFOLLOW to Dir::open --- src/tools/miri/src/shims/files.rs | 24 ++++++----- src/tools/miri/src/shims/unix/fs.rs | 41 ++++++++++++------- src/tools/miri/src/shims/windows/fs.rs | 8 ++-- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 32 +++++++++++++++ 4 files changed, 76 insertions(+), 29 deletions(-) diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 92144d3aeb764..95a898609571b 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -522,20 +522,22 @@ pub struct DirHandle { pub(super) dir: Dir, #[cfg(bootstrap)] pub(super) fallback: std::path::PathBuf, - #[cfg(not(bootstrap))] - #[expect(unused)] - fallback: (), } impl DirHandle { - pub fn open(path: &std::path::Path) -> io::Result { - #[cfg(bootstrap)] - let fallback = path.canonicalize()?; - #[cfg(not(bootstrap))] - let fallback = (); - - let dir = Dir::open(path)?; - Ok(DirHandle { dir, fallback }) + pub fn new(dir: Dir, path: &std::path::Path) -> Self { + cfg_select! { + bootstrap => { + // Only stage 1 builds need the fallback so panicking is fine. + let fallback = + path.canonicalize().expect("canonicalizing directory fallback should succeed"); + DirHandle { dir, fallback } + } + _ => { + let _unused = path; + DirHandle { dir } + } + } } } diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 3ff5094392b66..1943630d5108f 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::ffi::OsString; -use std::fs::{self, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; +use std::fs::{self, Dir, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; use std::path::{self, Path}; use std::time::SystemTime; @@ -577,15 +577,15 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // We need to know if the file is a directory to correctly open directory handles. // The standard library only lets us open something as a file or a directory, so // we check for that and then retry if we end up with the wrong thing. - let is_dir = path.is_dir(); + let metadata = if nofollow { path.symlink_metadata() } else { path.metadata() }; + let is_dir = metadata.is_ok_and(|m| m.is_dir()); if is_dir { // Directories cannot be opened for writing. if access_mode != o_rdonly { return this.set_errno_and_return_neg1_i32(LibcError("EISDIR")); } - // All the other flags don't really do anything. - let dir = match DirHandle::open(&path) { + let dir = match Dir::open_with(&path, &options) { Ok(dir) => dir, Err(e) => { if e.kind() == io::ErrorKind::NotADirectory { @@ -596,24 +596,37 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } }; #[cfg(bootstrap)] - let metadata = dir.dir.metadata(); + let metadata = dir.metadata().expect("a just-opened dir should have metadata"); #[cfg(not(bootstrap))] - let metadata = dir.dir.self_metadata(); - if !metadata.unwrap().is_dir() { + let metadata = dir.self_metadata().expect("a just-opened dir should have metadata"); + if !metadata.is_dir() { // This changed from a directory to a file. Retry. continue; } - let fd = this.machine.fds.insert_new(dir); + if nofollow && !cfg!(unix) { + // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just + // opens the symlink rather than the target. Turn that into an error. + if metadata.is_symlink() { + return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); + } + } + + let fd = this.machine.fds.insert_new(DirHandle::new(dir, &path)); return interp_ok(Scalar::from_i32(fd)); } else { let file = match options.open(&path) { Ok(file) => file, Err(e) => { - if e.kind() == io::ErrorKind::IsADirectory { + let kind = e.kind(); + if kind == io::ErrorKind::IsADirectory { // This changed from a directory to a file. Retry. continue; } + if want_directory && kind == io::ErrorKind::FilesystemLoop { + // This is reported as ENOTDIR. + return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); + } return this.set_errno_and_return_neg1_i32(e); } }; @@ -623,6 +636,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { continue; } + if want_directory { + return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); + } if nofollow && !cfg!(unix) { // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just // opens the symlink rather than the target. Turn that into an error. @@ -630,9 +646,6 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); } } - if want_directory { - return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); - } let fd = this.machine.fds.insert_new(FileHandle { file, writable, readable }); return interp_ok(Scalar::from_i32(fd)); } @@ -1233,12 +1246,12 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // in between above and here. One day, the standard library will support converting // between `Dir` and `ReadDir` (one of the two directions would suffice for our // needs), then we'll use that. - let Ok(dir) = DirHandle::open(&name) else { + let Ok(dir) = fs::Dir::open(&name) else { throw_unsup_format!( "cannot `opendir` this directory: failed to create directory handle" ); }; - let dir = this.machine.fds.new_ref(dir); + let dir = this.machine.fds.new_ref(DirHandle::new(dir, &name)); let dir_fd_id = dir.id(); let dir_fd_num = this.machine.fds.insert(dir); diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index 6fc9d37070f67..5cf504c84eb85 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -213,7 +213,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Open this as a directory. // FIXME: shouldn't we check `creation_disposition` here? We do know that it already // exists. - let dir = match DirHandle::open(&file_name) { + let dir = match fs::Dir::open(&file_name) { Ok(dir) => dir, Err(e) => { if e.kind() == io::ErrorKind::NotADirectory { @@ -225,9 +225,9 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } }; #[cfg(bootstrap)] - let metadata = dir.dir.metadata(); + let metadata = dir.metadata(); #[cfg(not(bootstrap))] - let metadata = dir.dir.self_metadata(); + let metadata = dir.self_metadata(); if !metadata.unwrap().is_dir() { // This changed from a directory to a file. Retry. continue; @@ -238,7 +238,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; } - let fd_num = this.machine.fds.insert_new(dir); + let fd_num = this.machine.fds.insert_new(DirHandle::new(dir, &file_name)); return interp_ok(Handle::File(fd_num)); } else { // Per the documentation: diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index 32f4b46d6d1dc..a53598c1b1596 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -345,6 +345,27 @@ fn test_file_open_nofollow() { // while POSIX specifies returning ELOOP. Since this test is run on both native FreeBSD and native // Linux hosts, we just assert that its either of those error codes. assert!([libc::ELOOP, libc::EMLINK].contains(&err.raw_os_error().unwrap())); + + // Also check symlink to directory. + let symlink_path = utils::prepare("miri_test_open_nofollow_symlink_to_dir"); + // We make the symlink point to its parent directory. + std::os::unix::fs::symlink(&symlink_path.parent().unwrap(), &symlink_path).unwrap(); + let symlink_cpath = utils::into_c_string(symlink_path); + let err = errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW) }) + .unwrap_err(); + assert!( + [libc::ELOOP, libc::EMLINK].contains(&err.raw_os_error().unwrap()), + "unexpected errno: {err}" + ); + // If we set O_DIRECTORY, we get a different error on Linux, but still EMLINK on FreeBSD. + let err = errno_result(unsafe { + libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW | libc::O_DIRECTORY) + }) + .unwrap_err(); + assert!( + [libc::ENOTDIR, libc::EMLINK].contains(&err.raw_os_error().unwrap()), + "unexpected errno: {err}" + ); } } @@ -379,6 +400,17 @@ fn test_file_open_directory() { }) .unwrap_err(); assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT); + + if utils::have_symlink_permission() { + // Also check symlink behavior. + let symlink_path = utils::prepare("miri_test_open_directory_symlink"); + // We make the symlink point to its parent directory. + std::os::unix::fs::symlink(&symlink_path.parent().unwrap(), &symlink_path).unwrap(); + let symlink_cpath = utils::into_c_string(symlink_path); + let fd = + errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_DIRECTORY) }).unwrap(); + errno_check(unsafe { libc::close(fd) }); + } } fn test_file_open_exclusive() { From a1ab85a49d7466c35332e7c6ac7ef2a8de495f5c Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 3 Oct 2026 21:20:37 +0200 Subject: [PATCH 1236/1309] add test for opening dangling symlinks --- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index a53598c1b1596..a31839d116fd6 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -31,6 +31,7 @@ fn main() { test_create_read_write(); test_file_open_args(); test_file_open_nofollow(); + test_file_open_dangling_symlink(); test_file_open_directory(); test_file_open_exclusive(); #[cfg(target_os = "linux")] @@ -369,6 +370,29 @@ fn test_file_open_nofollow() { } } +fn test_file_open_dangling_symlink() { + if !utils::have_symlink_permission() { + return; + } + + let symlink_path = utils::prepare("miri_test_open_dangling_symlink"); + std::os::unix::fs::symlink("does-not-exist", &symlink_path).unwrap(); + let symlink_cpath = utils::into_c_string(symlink_path); + + let err = + errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_RDONLY) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT, "unexpected errno: {err}"); + let err = + errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_NOFOLLOW) }).unwrap_err(); + assert!( + [libc::ELOOP, libc::EMLINK].contains(&err.raw_os_error().unwrap()), + "unexpected errno: {err}" + ); + let err = + errno_result(unsafe { libc::open(symlink_cpath.as_ptr(), libc::O_DIRECTORY) }).unwrap_err(); + assert_eq!(err.raw_os_error().unwrap(), libc::ENOENT, "unexpected errno: {err}"); +} + fn test_file_open_directory() { let dir_path = utils::prepare_dir("miri_test_file_open_directory"); create_dir(&dir_path).unwrap(); From 465aca6dd3e8f33ee6e9e3ca07c20c7be4ce5813 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 12:19:25 +0200 Subject: [PATCH 1237/1309] Route `fn_hir_id` into `lower_fn_decl` --- compiler/rustc_ast_lowering/src/expr/closure.rs | 8 ++++++-- compiler/rustc_ast_lowering/src/item.rs | 17 +++++++++++++---- compiler/rustc_ast_lowering/src/lib.rs | 15 ++++++++++++--- 3 files changed, 31 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index c72956545b7c8..a40ce1696b033 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -133,6 +133,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder, capture_clause, closure_id, + expr_hir_id, constness, movability, decl, @@ -159,6 +160,7 @@ impl<'hir> LoweringContext<'_, 'hir> { binder: &ClosureBinder, capture_clause: CaptureBy, closure_id: NodeId, + closure_hir_id: HirId, constness: Const, movability: Movability, decl: &FnDecl, @@ -205,7 +207,8 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = self.lower_fn_decl(decl, closure_id, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); let c = self.arena.alloc(hir::Closure { def_id: closure_def_id, @@ -328,7 +331,8 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = self.lower_fn_decl(&decl, closure_id, FnDeclKind::Closure, None); + let fn_decl = + self.lower_fn_decl(&decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); if let Const::Yes(span) = constness { self.dcx().span_err(span, "const coroutines are not supported"); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6ec5903c5fb3b..b56759a252b4e 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -278,7 +278,12 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = ImplTraitContext::Universal; let (generics, decl) = this.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(decl, id, FnDeclKind::Fn, coroutine_marker) + this.lower_fn_decl( + decl, + id, + hir_id, + FnDeclKind::Fn, + coroutine_marker) }); let sig = hir::FnSig { decl, @@ -616,7 +621,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, i.id, FnDeclKind::ExternFn, None), + this.lower_fn_decl(fdec, i.id, hir_id, FnDeclKind::ExternFn, None), this.lower_fn_params_to_idents(fdec), ) }); @@ -838,6 +843,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, @@ -878,6 +884,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, FnDeclKind::Trait, sig.header.coroutine_marker, attrs, @@ -1088,6 +1095,7 @@ impl<'hir> LoweringContext<'_, 'hir> { generics, sig, i.id, + hir_id, if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, @@ -1533,7 +1541,8 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, generics: &Generics, sig: &FnSig, - id: NodeId, + node_id: NodeId, + hir_id: HirId, kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], @@ -1541,7 +1550,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, id, kind, coroutine_marker) + this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4b6e897da4c87..2bee965db9f3f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -1547,14 +1547,22 @@ impl<'hir> LoweringContext<'_, 'hir> { hir::TyKind::Path(path) } TyKind::FnPtr(f) => { + let hir_id = self.lower_node_id(t.id); let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); - hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { + let kind = hir::TyKind::FnPtr(self.arena.alloc(hir::FnPtrTy { generic_params, safety: self.lower_safety(f.safety, hir::Safety::Safe), abi: self.lower_extern(f.ext), - decl: self.lower_fn_decl(&f.decl, t.id, FnDeclKind::Pointer, None), + decl: self.lower_fn_decl( + &f.decl, + t.id, + hir_id, + FnDeclKind::Pointer, + None, + ), param_idents: self.lower_fn_params_to_idents(&f.decl), - })) + })); + return hir::Ty { kind, span: self.lower_span(t.span), hir_id }; } TyKind::UnsafeBinder(f) => { let generic_params = self.lower_lifetime_binder(t.id, &f.generic_params); @@ -1910,6 +1918,7 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, decl: &FnDecl, fn_node_id: NodeId, + fn_hir_id: HirId, kind: FnDeclKind, coro: Option, ) -> &'hir hir::FnDecl<'hir> { From 539bfe3225367d2a080e829dfc2dd5a0b28ae8fb Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 13:04:19 +0200 Subject: [PATCH 1238/1309] Add regression tests --- tests/ui/attributes/attrs-on-params.rs | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs index c8e9810327c2a..ed4a50efa25db 100644 --- a/tests/ui/attributes/attrs-on-params.rs +++ b/tests/ui/attributes/attrs-on-params.rs @@ -5,4 +5,23 @@ fn function(#[inline] param: u32) { //~| ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes } +trait Test { + fn meow( + #[rustc_splat] a1: u32, + ); + fn meow2( + #[rustc_splat(invalid)] a4: u32, + ); +} + +type Meow = fn( + #[rustc_splat] a1: u32, +); + +extern "Rust" { + fn meow2( + #[rustc_splat] a1: u32, + ); +} + fn main() {} From 9c9d810f25ea3babf1f14e4524d5ee93ab360cab Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 14 Sep 2026 13:32:59 +0200 Subject: [PATCH 1239/1309] Lower attributes for functions without bodies --- .../rustc_ast_lowering/src/expr/closure.rs | 22 +- compiler/rustc_ast_lowering/src/item.rs | 25 ++- compiler/rustc_ast_lowering/src/lib.rs | 30 ++- library/coretests/tests/lib.rs | 2 + tests/ui/attributes/attrs-on-params.rs | 5 + tests/ui/attributes/attrs-on-params.stderr | 62 +++++- .../param-attrs-builtin-attrs.rs | 8 + .../param-attrs-builtin-attrs.stderr | 190 +++++++++++------- tests/ui/splat/splat-invalid.rs | 2 + tests/ui/splat/splat-invalid.stderr | 36 +++- 10 files changed, 284 insertions(+), 98 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/expr/closure.rs b/compiler/rustc_ast_lowering/src/expr/closure.rs index a40ce1696b033..5924d53dd11e4 100644 --- a/compiler/rustc_ast_lowering/src/expr/closure.rs +++ b/compiler/rustc_ast_lowering/src/expr/closure.rs @@ -6,8 +6,8 @@ use rustc_hir::HirId; use rustc_span::{Span, span_bug}; use super::{LoweringContext, MoveExprState}; -use crate::FnDeclKind; use crate::diagnostics::{ClosureCannotBeStatic, CoroutineTooManyParameters}; +use crate::{DiscardParams, FnDeclKind}; impl<'hir> LoweringContext<'_, 'hir> { // Entry point for `ExprKind::Closure`. Plain closures go through @@ -207,8 +207,14 @@ impl<'hir> LoweringContext<'_, 'hir> { let bound_generic_params = self.lower_lifetime_binder(closure_id, generic_params); // Lower outside new scope to preserve `is_in_loop_condition`. - let fn_decl = - self.lower_fn_decl(decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl( + decl, + closure_id, + closure_hir_id, + FnDeclKind::Closure, + None, + DiscardParams::No, + ); let c = self.arena.alloc(hir::Closure { def_id: closure_def_id, @@ -331,8 +337,14 @@ impl<'hir> LoweringContext<'_, 'hir> { // We need to lower the declaration outside the new scope, because we // have to conserve the state of being inside a loop condition for the // closure argument types. - let fn_decl = - self.lower_fn_decl(&decl, closure_id, closure_hir_id, FnDeclKind::Closure, None); + let fn_decl = self.lower_fn_decl( + &decl, + closure_id, + closure_hir_id, + FnDeclKind::Closure, + None, + DiscardParams::No, + ); if let Const::Yes(span) = constness { self.dcx().span_err(span, "const coroutines are not supported"); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index b56759a252b4e..32229aeea0f9f 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -19,8 +19,8 @@ use super::diagnostics::{ }; use super::stability::{enabled_names, gate_unstable_abi}; use super::{ - FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode, - RelaxedBoundForbiddenReason, RelaxedBoundPolicy, + DiscardParams, FnDeclKind, GenericArgsMode, ImplTraitContext, ImplTraitPosition, + LoweringContext, ParamMode, RelaxedBoundForbiddenReason, RelaxedBoundPolicy, }; use crate::diagnostics::{ConstComptimeFn, ResolvingRestrictionKind, RestrictionAncestorOnly}; @@ -283,7 +283,9 @@ impl<'hir> LoweringContext<'_, 'hir> { id, hir_id, FnDeclKind::Fn, - coroutine_marker) + coroutine_marker, + if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, + ) }); let sig = hir::FnSig { decl, @@ -621,7 +623,15 @@ impl<'hir> LoweringContext<'_, 'hir> { let (generics, (decl, fn_args)) = self.lower_generics(generics, itctx, |this| { ( // Disallow `impl Trait` in foreign items. - this.lower_fn_decl(fdec, i.id, hir_id, FnDeclKind::ExternFn, None), + // Parameters are discarded because foreign functions don't have a body + this.lower_fn_decl( + fdec, + i.id, + hir_id, + FnDeclKind::ExternFn, + None, + DiscardParams::Yes, + ), this.lower_fn_params_to_idents(fdec), ) }); @@ -847,6 +857,8 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, sig.header.coroutine_marker, attrs, + // Parameters are discarded for functions without a body + DiscardParams::Yes, ); if define_opaque.is_some() { self.dcx().span_err( @@ -888,6 +900,7 @@ impl<'hir> LoweringContext<'_, 'hir> { FnDeclKind::Trait, sig.header.coroutine_marker, attrs, + DiscardParams::No, ); self.lower_define_opaque(hir_id, &define_opaque); ( @@ -1099,6 +1112,7 @@ impl<'hir> LoweringContext<'_, 'hir> { if is_in_trait_impl { FnDeclKind::Impl } else { FnDeclKind::Inherent }, sig.header.coroutine_marker, attrs, + if body.is_none() { DiscardParams::Yes } else { DiscardParams::No }, ); self.lower_define_opaque(hir_id, &define_opaque); @@ -1546,11 +1560,12 @@ impl<'hir> LoweringContext<'_, 'hir> { kind: FnDeclKind, coroutine_marker: Option, attrs: &[rustc_attr_ir::Attribute], + discard_params: DiscardParams, ) -> (&'hir hir::Generics<'hir>, hir::FnSig<'hir>) { let header = self.lower_fn_header(sig.header, hir::Safety::Safe, attrs); let itctx = ImplTraitContext::Universal; let (generics, decl) = self.lower_generics(generics, itctx, |this| { - this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker) + this.lower_fn_decl(&sig.decl, node_id, hir_id, kind, coroutine_marker, discard_params) }); (generics, hir::FnSig { header, decl, span: self.lower_span(sig.span) }) } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 2bee965db9f3f..66e0f595da0ee 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -807,6 +807,14 @@ enum GenericArgsMode { Silence, } +#[derive(Debug, Copy, Clone)] +enum DiscardParams { + /// Should be used for functions without a body. Lowers the attributes on the parameter and then discards them. + Yes, + /// Should be used for functions with a body. Does not lower the attributes, as lowering of the parameters is done by `lower_body`. + No, +} + impl<'hir> LoweringContext<'_, 'hir> { fn create_def( &mut self, @@ -1559,6 +1567,7 @@ impl<'hir> LoweringContext<'_, 'hir> { hir_id, FnDeclKind::Pointer, None, + DiscardParams::Yes, ), param_idents: self.lower_fn_params_to_idents(&f.decl), })); @@ -1908,11 +1917,17 @@ impl<'hir> LoweringContext<'_, 'hir> { /// /// `decl`: the unlowered (AST) function declaration. /// - /// `fn_node_id`: `impl Trait` arguments are lowered into generic parameters on the given - /// `NodeId`. + /// `fn_node_id`: Node Id of the function. /// - /// `transform_return_type`: if `Some`, applies some conversion to the return type, such as is - /// needed for `async fn` and `gen fn`. See [`CoroutineKind`] for more details. + /// `fn_hir_id`: Hir Id of the function. Used for attribute parsing. + /// + /// `kind`: The kind of function. + /// + /// `coro`: If the function is a coroutine, information about the coroutine. + /// + /// `discard_params`: if `DiscardParams::Yes`, the parameters are lowered and then discarded. Set this to `DiscardParams::Yes` + /// for functions without bodies, as attributes on parameters are otherwise not validated. + /// Set this to `DiscardParams::No` for functions with bodies, as lowering of the parameters is done by `lower_body`. #[instrument(level = "debug", skip(self))] fn lower_fn_decl( &mut self, @@ -1921,6 +1936,7 @@ impl<'hir> LoweringContext<'_, 'hir> { fn_hir_id: HirId, kind: FnDeclKind, coro: Option, + discard_params: DiscardParams, ) -> &'hir hir::FnDecl<'hir> { let c_variadic = decl.c_variadic(); let mut splatted = decl.splatted(); @@ -1935,6 +1951,12 @@ impl<'hir> LoweringContext<'_, 'hir> { inputs = &inputs[..inputs.len() - 1]; } let inputs = self.arena.alloc_from_iter(inputs.iter().map(|param| { + if let DiscardParams::Yes = discard_params { + // FIXME This uses `fn_hir_id`, which is not correct, it should use the parameter hir id instead + // The parameter is currently not lowered for functions without bodies, so there is no place to store the lowered hir id + // This should be fixed by storing function parameters in the `hir::FnSig` instead of `hir::Body` + self.lower_attrs(fn_hir_id, ¶m.attrs, param.span, Target::Param); + } let itctx = match kind { FnDeclKind::Fn | FnDeclKind::Inherent | FnDeclKind::Impl | FnDeclKind::Trait => { ImplTraitContext::Universal diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index fc2430a10edb4..bf84f27c7a0f5 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -111,6 +111,7 @@ #![feature(slice_shift)] #![feature(slice_split_once)] #![feature(sliceindex_wrappers)] +#![feature(splat)] #![feature(split_array)] #![feature(split_as_slice)] #![feature(std_internals)] @@ -131,6 +132,7 @@ #![feature(unicode_internals)] #![feature(unsize)] // tidy-alphabetical-end +#![allow(incomplete_features)] #![allow(internal_features)] #![deny(implicit_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] diff --git a/tests/ui/attributes/attrs-on-params.rs b/tests/ui/attributes/attrs-on-params.rs index ed4a50efa25db..e12ff906fa3f5 100644 --- a/tests/ui/attributes/attrs-on-params.rs +++ b/tests/ui/attributes/attrs-on-params.rs @@ -8,19 +8,24 @@ fn function(#[inline] param: u32) { trait Test { fn meow( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); fn meow2( #[rustc_splat(invalid)] a4: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature + //~| ERROR malformed `rustc_splat` attribute input ); } type Meow = fn( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); extern "Rust" { fn meow2( #[rustc_splat] a1: u32, + //~^ ERROR the `rustc_splat` attribute is an experimental feature ); } diff --git a/tests/ui/attributes/attrs-on-params.stderr b/tests/ui/attributes/attrs-on-params.stderr index b38c590a19a5c..748f189590a46 100644 --- a/tests/ui/attributes/attrs-on-params.stderr +++ b/tests/ui/attributes/attrs-on-params.stderr @@ -12,5 +12,65 @@ LL | fn function(#[inline] param: u32) { | = help: the `inline` attribute can only be applied to functions -error: aborting due to 2 previous errors +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:10:11 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:14:11 + | +LL | #[rustc_splat(invalid)] a4: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0565]: malformed `rustc_splat` attribute input + --> $DIR/attrs-on-params.rs:14:11 + | +LL | #[rustc_splat(invalid)] a4: u32, + | ^^^^^^^^^^^--------- + | | + | didn't expect any arguments here + | +help: must be of the form + | +LL - #[rustc_splat(invalid)] a4: u32, +LL + #[rustc_splat] a4: u32, + | + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:21:7 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error[E0658]: the `rustc_splat` attribute is an experimental feature + --> $DIR/attrs-on-params.rs:27:11 + | +LL | #[rustc_splat] a1: u32, + | ^^^^^^^^^^^ + | + = note: see issue #153629 for more information + = help: add `#![feature(splat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + = note: the `rustc_splat` attribute is experimental + +error: aborting due to 7 previous errors +Some errors have detailed explanations: E0565, E0658. +For more information about an error, try `rustc --explain E0565`. diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs index bb6e7705a29d6..7f1d5c849ebe6 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.rs @@ -8,10 +8,14 @@ extern "C" { //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted ); } @@ -24,10 +28,14 @@ type FnType = fn( //~^ ERROR documentation comments cannot be applied to function #[must_use] //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted /// Baz //~^ ERROR documentation comments cannot be applied to function #[no_mangle] b: i32, //~^ ERROR allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters + //~| WARN cannot be used on function params + //~| WARN previously accepted ); pub fn foo( diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr index cee602a274bb3..db2d8f161dba0 100644 --- a/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr +++ b/tests/ui/rfcs/rfc-2565-param-attrs/param-attrs-builtin-attrs.stderr @@ -5,55 +5,55 @@ LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:21:7 + --> $DIR/param-attrs-builtin-attrs.rs:25:7 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:36:7 + --> $DIR/param-attrs-builtin-attrs.rs:44:7 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:60:11 + --> $DIR/param-attrs-builtin-attrs.rs:68:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:79:11 + --> $DIR/param-attrs-builtin-attrs.rs:87:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:104:11 + --> $DIR/param-attrs-builtin-attrs.rs:112:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:127:11 + --> $DIR/param-attrs-builtin-attrs.rs:135:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:146:11 + --> $DIR/param-attrs-builtin-attrs.rs:154:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:170:11 + --> $DIR/param-attrs-builtin-attrs.rs:178:11 | LL | #[test] a: i32, | ^^^^ not a non-macro attribute error: expected non-macro attribute, found attribute macro `test` - --> $DIR/param-attrs-builtin-attrs.rs:191:11 + --> $DIR/param-attrs-builtin-attrs.rs:199:11 | LL | #[test] a: u32, | ^^^^ not a non-macro attribute @@ -77,313 +77,313 @@ LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:11:9 + --> $DIR/param-attrs-builtin-attrs.rs:13:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:13:9 + --> $DIR/param-attrs-builtin-attrs.rs:15:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:19:5 + --> $DIR/param-attrs-builtin-attrs.rs:23:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:23:5 + --> $DIR/param-attrs-builtin-attrs.rs:27:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:25:5 + --> $DIR/param-attrs-builtin-attrs.rs:29:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:27:5 + --> $DIR/param-attrs-builtin-attrs.rs:33:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:29:5 + --> $DIR/param-attrs-builtin-attrs.rs:35:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:34:5 + --> $DIR/param-attrs-builtin-attrs.rs:42:5 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:38:5 + --> $DIR/param-attrs-builtin-attrs.rs:46:5 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:40:5 + --> $DIR/param-attrs-builtin-attrs.rs:48:5 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:44:5 + --> $DIR/param-attrs-builtin-attrs.rs:52:5 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:46:5 + --> $DIR/param-attrs-builtin-attrs.rs:54:5 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:55:9 + --> $DIR/param-attrs-builtin-attrs.rs:63:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:58:9 + --> $DIR/param-attrs-builtin-attrs.rs:66:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:62:9 + --> $DIR/param-attrs-builtin-attrs.rs:70:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:64:9 + --> $DIR/param-attrs-builtin-attrs.rs:72:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:68:9 + --> $DIR/param-attrs-builtin-attrs.rs:76:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:70:9 + --> $DIR/param-attrs-builtin-attrs.rs:78:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:77:9 + --> $DIR/param-attrs-builtin-attrs.rs:85:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:81:9 + --> $DIR/param-attrs-builtin-attrs.rs:89:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:83:9 + --> $DIR/param-attrs-builtin-attrs.rs:91:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:87:9 + --> $DIR/param-attrs-builtin-attrs.rs:95:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:89:9 + --> $DIR/param-attrs-builtin-attrs.rs:97:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:99:9 + --> $DIR/param-attrs-builtin-attrs.rs:107:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:102:9 + --> $DIR/param-attrs-builtin-attrs.rs:110:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:106:9 + --> $DIR/param-attrs-builtin-attrs.rs:114:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:108:9 + --> $DIR/param-attrs-builtin-attrs.rs:116:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:112:9 + --> $DIR/param-attrs-builtin-attrs.rs:120:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:114:9 + --> $DIR/param-attrs-builtin-attrs.rs:122:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:122:9 + --> $DIR/param-attrs-builtin-attrs.rs:130:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:125:9 + --> $DIR/param-attrs-builtin-attrs.rs:133:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:129:9 + --> $DIR/param-attrs-builtin-attrs.rs:137:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:131:9 + --> $DIR/param-attrs-builtin-attrs.rs:139:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:135:9 + --> $DIR/param-attrs-builtin-attrs.rs:143:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:137:9 + --> $DIR/param-attrs-builtin-attrs.rs:145:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:144:9 + --> $DIR/param-attrs-builtin-attrs.rs:152:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:148:9 + --> $DIR/param-attrs-builtin-attrs.rs:156:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:150:9 + --> $DIR/param-attrs-builtin-attrs.rs:158:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:154:9 + --> $DIR/param-attrs-builtin-attrs.rs:162:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:156:9 + --> $DIR/param-attrs-builtin-attrs.rs:164:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:165:9 + --> $DIR/param-attrs-builtin-attrs.rs:173:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:168:9 + --> $DIR/param-attrs-builtin-attrs.rs:176:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:172:9 + --> $DIR/param-attrs-builtin-attrs.rs:180:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:174:9 + --> $DIR/param-attrs-builtin-attrs.rs:182:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:178:9 + --> $DIR/param-attrs-builtin-attrs.rs:186:9 | LL | /// Qux | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:180:9 + --> $DIR/param-attrs-builtin-attrs.rs:188:9 | LL | #[no_mangle] b: i32, | ^^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:189:9 + --> $DIR/param-attrs-builtin-attrs.rs:197:9 | LL | /// Foo | ^^^^^^^ doc comments are not allowed here error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:193:9 + --> $DIR/param-attrs-builtin-attrs.rs:201:9 | LL | /// Bar | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:195:9 + --> $DIR/param-attrs-builtin-attrs.rs:203:9 | LL | #[must_use] | ^^^^^^^^^^^ error: documentation comments cannot be applied to function parameters - --> $DIR/param-attrs-builtin-attrs.rs:199:9 + --> $DIR/param-attrs-builtin-attrs.rs:207:9 | LL | /// Baz | ^^^^^^^ doc comments are not allowed here error: allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters - --> $DIR/param-attrs-builtin-attrs.rs:201:9 + --> $DIR/param-attrs-builtin-attrs.rs:209:9 | LL | #[no_mangle] b: i32 | ^^^^^^^^^^^^ warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:40:7 + --> $DIR/param-attrs-builtin-attrs.rs:29:7 | LL | #[must_use] | ^^^^^^^^ @@ -393,7 +393,25 @@ LL | #[must_use] = note: requested on the command line with `-W unused-attributes` warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:46:7 + --> $DIR/param-attrs-builtin-attrs.rs:35:7 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^ + | + = help: the `no_mangle` attribute can be applied to functions and statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `must_use` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:48:7 + | +LL | #[must_use] + | ^^^^^^^^ + | + = help: the `must_use` attribute can be applied to data types, functions, and traits + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `no_mangle` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:54:7 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -402,7 +420,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:195:11 + --> $DIR/param-attrs-builtin-attrs.rs:203:11 | LL | #[must_use] | ^^^^^^^^ @@ -411,7 +429,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:201:11 + --> $DIR/param-attrs-builtin-attrs.rs:209:11 | LL | #[no_mangle] b: i32 | ^^^^^^^^^ @@ -420,7 +438,25 @@ LL | #[no_mangle] b: i32 = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:131:11 + --> $DIR/param-attrs-builtin-attrs.rs:139:11 + | +LL | #[must_use] + | ^^^^^^^^ + | + = help: the `must_use` attribute can be applied to data types, functions, and traits + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `no_mangle` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:145:11 + | +LL | #[no_mangle] b: i32, + | ^^^^^^^^^ + | + = help: the `no_mangle` attribute can be applied to functions and statics + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: the `must_use` attribute cannot be used on function params + --> $DIR/param-attrs-builtin-attrs.rs:158:11 | LL | #[must_use] | ^^^^^^^^ @@ -429,7 +465,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:137:11 + --> $DIR/param-attrs-builtin-attrs.rs:164:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -438,7 +474,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:150:11 + --> $DIR/param-attrs-builtin-attrs.rs:72:11 | LL | #[must_use] | ^^^^^^^^ @@ -447,7 +483,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:156:11 + --> $DIR/param-attrs-builtin-attrs.rs:78:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -456,7 +492,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:64:11 + --> $DIR/param-attrs-builtin-attrs.rs:91:11 | LL | #[must_use] | ^^^^^^^^ @@ -465,7 +501,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:70:11 + --> $DIR/param-attrs-builtin-attrs.rs:97:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -474,7 +510,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:83:11 + --> $DIR/param-attrs-builtin-attrs.rs:116:11 | LL | #[must_use] | ^^^^^^^^ @@ -483,7 +519,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:89:11 + --> $DIR/param-attrs-builtin-attrs.rs:122:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -492,7 +528,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:108:11 + --> $DIR/param-attrs-builtin-attrs.rs:182:11 | LL | #[must_use] | ^^^^^^^^ @@ -501,7 +537,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:114:11 + --> $DIR/param-attrs-builtin-attrs.rs:188:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -510,7 +546,7 @@ LL | #[no_mangle] b: i32, = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `must_use` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:174:11 + --> $DIR/param-attrs-builtin-attrs.rs:9:11 | LL | #[must_use] | ^^^^^^^^ @@ -519,7 +555,7 @@ LL | #[must_use] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! warning: the `no_mangle` attribute cannot be used on function params - --> $DIR/param-attrs-builtin-attrs.rs:180:11 + --> $DIR/param-attrs-builtin-attrs.rs:15:11 | LL | #[no_mangle] b: i32, | ^^^^^^^^^ @@ -527,5 +563,5 @@ LL | #[no_mangle] b: i32, = help: the `no_mangle` attribute can be applied to functions and statics = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! -error: aborting due to 64 previous errors; 16 warnings emitted +error: aborting due to 64 previous errors; 20 warnings emitted diff --git a/tests/ui/splat/splat-invalid.rs b/tests/ui/splat/splat-invalid.rs index 9a0101636a8b0..e30ac4a9af276 100644 --- a/tests/ui/splat/splat-invalid.rs +++ b/tests/ui/splat/splat-invalid.rs @@ -69,12 +69,14 @@ fn main() { let multisplat_arg_bad_: fn( #[rustc_splat] #[rustc_splat] + //~^ ERROR multiple `rustc_splat` attributes (u32, i8), ) = multisplat_arg_bad; let multisplat_arg_fn_bad_: fn( #[rustc_splat] //~^ ERROR multiple `#[rustc_splat]`s are not allowed in the same function argument list #[rustc_splat] + //~^ ERROR multiple `rustc_splat` attributes (u32, i8), #[rustc_splat] (u32, i8), ) = multisplat_arg_fn_bad; diff --git a/tests/ui/splat/splat-invalid.stderr b/tests/ui/splat/splat-invalid.stderr index f1c492bd3e37e..8681084a3c594 100644 --- a/tests/ui/splat/splat-invalid.stderr +++ b/tests/ui/splat/splat-invalid.stderr @@ -96,21 +96,21 @@ LL | fn(#[rustc_splat] (u32, i8), #[rustc_splat] (u32, i8)) = multisplat = help: remove `#[rustc_splat]` from all but one argument error: multiple `#[rustc_splat]`s are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:75:9 + --> $DIR/splat-invalid.rs:76:9 | LL | #[rustc_splat] | ^^^^^^^^^^^^^^ LL | LL | #[rustc_splat] | ^^^^^^^^^^^^^^ -LL | (u32, i8), +... LL | #[rustc_splat] (u32, i8), | ^^^^^^^^^^^^^^ | = help: remove `#[rustc_splat]` from all but one argument error: `...` and `#[rustc_splat]` are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:82:47 + --> $DIR/splat-invalid.rs:84:47 | LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ...) = splat_variadic; | ^^^^^^^^^^^^^^ ^^^ @@ -118,13 +118,13 @@ LL | let splat_variadic_: unsafe extern "C" fn(#[rustc_splat] (u32, i8), ... = help: remove `#[rustc_splat]` or remove `...` error: `...` must be the last argument of a C-variadic function - --> $DIR/splat-invalid.rs:84:48 + --> $DIR/splat-invalid.rs:86:48 | LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; | ^^^ error: `...` and `#[rustc_splat]` are not allowed in the same function argument list - --> $DIR/splat-invalid.rs:84:48 + --> $DIR/splat-invalid.rs:86:48 | LL | let splat_variadic2_: unsafe extern "C" fn(..., #[rustc_splat] (u32, i8)) = splat_variadic2; | ^^^ ^^^^^^^^^^^^^^ @@ -155,6 +155,30 @@ note: attribute also specified here LL | #[rustc_splat] | ^^^^^^^^^^^^^^ +error: multiple `rustc_splat` attributes + --> $DIR/splat-invalid.rs:71:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/splat-invalid.rs:70:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ + +error: multiple `rustc_splat` attributes + --> $DIR/splat-invalid.rs:78:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/splat-invalid.rs:76:9 + | +LL | #[rustc_splat] + | ^^^^^^^^^^^^^^ + error[E0053]: method `has_splat` has an incompatible type for trait --> $DIR/splat-invalid.rs:59:5 | @@ -183,6 +207,6 @@ LL | fn no_splat(_: (u32, f64)); = note: expected signature `fn((_, _))` found signature `fn(#[rustc_splat] (_, _))` -error: aborting due to 19 previous errors +error: aborting due to 21 previous errors For more information about this error, try `rustc --explain E0053`. From a836ca5eab894dcca18f600962b24db194512013 Mon Sep 17 00:00:00 2001 From: David Carlier Date: Sat, 3 Oct 2026 21:42:33 +0100 Subject: [PATCH 1240/1309] solarish: support current_exe via /proc/self/path/a.out in readlink. Fixes #5374. --- src/tools/miri/src/shims/unix/fs.rs | 13 ++++++++----- src/tools/miri/tests/pass/shims/env/current_exe.rs | 2 +- 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 9b5ed86013f70..b328f49d0e9a2 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -1722,11 +1722,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(-1); } - // On Linux, special case `/proc/self/exe` so that `std::env::current_exe` works - // in cross-execution. - let result = if matches!(this.tcx.sess.target.os, Os::Linux | Os::Android) - && pathname.to_str() == Some("/proc/self/exe") - { + // Special case the procfs link to the current executable so that + // `std::env::current_exe` works in cross-execution. + let self_exe = match this.tcx.sess.target.os { + Os::Linux | Os::Android => Some("/proc/self/exe"), + Os::Solaris | Os::Illumos => Some("/proc/self/path/a.out"), + _ => None, + }; + let result = if self_exe.is_some() && pathname.to_str() == self_exe { this.machine.current_exe.clone().ok_or(ErrorKind::NotFound.into()) } else { // We read `pathname` as `OsStr` above so we could do the /proc/self/exe check. diff --git a/src/tools/miri/tests/pass/shims/env/current_exe.rs b/src/tools/miri/tests/pass/shims/env/current_exe.rs index 1ba001094ff0c..49e382cc29567 100644 --- a/src/tools/miri/tests/pass/shims/env/current_exe.rs +++ b/src/tools/miri/tests/pass/shims/env/current_exe.rs @@ -1,4 +1,4 @@ -//@ignore-target: freebsd illumos solaris # we don't have the shims this needs here +//@ignore-target: freebsd # we don't have the shims this needs here //@compile-flags: -Zmiri-disable-isolation //@run-native use std::env; From bef651bcdd8920ce97f3cd0d00ebb8d1facb8165 Mon Sep 17 00:00:00 2001 From: tmiasko Date: Sat, 3 Oct 2026 20:22:10 +0000 Subject: [PATCH 1241/1309] Rename tests/mir-opt/dataflow.rs to dump_dataflow.rs To avoid name conflicts with dataflow directory (to be added in subsequent commit). --- ...orrowck.dot => dump_dataflow.main.maybe_uninit.borrowck.dot} | 0 tests/mir-opt/{dataflow.rs => dump_dataflow.rs} | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename tests/mir-opt/{dataflow.main.maybe_uninit.borrowck.dot => dump_dataflow.main.maybe_uninit.borrowck.dot} (100%) rename tests/mir-opt/{dataflow.rs => dump_dataflow.rs} (68%) diff --git a/tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot b/tests/mir-opt/dump_dataflow.main.maybe_uninit.borrowck.dot similarity index 100% rename from tests/mir-opt/dataflow.main.maybe_uninit.borrowck.dot rename to tests/mir-opt/dump_dataflow.main.maybe_uninit.borrowck.dot diff --git a/tests/mir-opt/dataflow.rs b/tests/mir-opt/dump_dataflow.rs similarity index 68% rename from tests/mir-opt/dataflow.rs rename to tests/mir-opt/dump_dataflow.rs index 01981dfbec8b0..b5b6eb54f7d9e 100644 --- a/tests/mir-opt/dataflow.rs +++ b/tests/mir-opt/dump_dataflow.rs @@ -2,5 +2,5 @@ // Test graphviz dataflow output //@ compile-flags: -Z dump-mir=main -Z dump-mir-dataflow -// EMIT_MIR dataflow.main.maybe_uninit.borrowck.dot +// EMIT_MIR dump_dataflow.main.maybe_uninit.borrowck.dot fn main() {} From 143dcb57bbf57143bb2f702a2d061804b6ef1121 Mon Sep 17 00:00:00 2001 From: lcnr Date: Sun, 4 Oct 2026 00:09:56 +0200 Subject: [PATCH 1242/1309] some crashes fixed with next-solver --- tests/crashes/141124.rs | 16 -------- .../issues/borrowck-ambiguity-ice-148511.rs} | 11 ++++- .../issues/relate-mir-borrowck-ice-149162.rs} | 11 ++++- ...tion-cache-rematch-impl-141124.next.stderr | 41 +++++++++++++++++++ .../projection-cache-rematch-impl-141124.rs | 32 +++++++++++++++ 5 files changed, 93 insertions(+), 18 deletions(-) delete mode 100644 tests/crashes/141124.rs rename tests/{crashes/148511.rs => ui/impl-trait/issues/borrowck-ambiguity-ice-148511.rs} (65%) rename tests/{crashes/149162.rs => ui/impl-trait/issues/relate-mir-borrowck-ice-149162.rs} (60%) create mode 100644 tests/ui/traits/projection-cache-rematch-impl-141124.next.stderr create mode 100644 tests/ui/traits/projection-cache-rematch-impl-141124.rs diff --git a/tests/crashes/141124.rs b/tests/crashes/141124.rs deleted file mode 100644 index 38a2a55e1c4a3..0000000000000 --- a/tests/crashes/141124.rs +++ /dev/null @@ -1,16 +0,0 @@ -//@ known-bug: #141124 -struct S; -trait SimpleTrait {} -trait TraitAssoc { - type Assoc; -} - -impl TraitAssoc for T -where - T: SimpleTrait, -{ - type Assoc = <(T,) as TraitAssoc>::Assoc; -} -impl SimpleTrait for ::Assoc {} - -pub fn main() {} diff --git a/tests/crashes/148511.rs b/tests/ui/impl-trait/issues/borrowck-ambiguity-ice-148511.rs similarity index 65% rename from tests/crashes/148511.rs rename to tests/ui/impl-trait/issues/borrowck-ambiguity-ice-148511.rs index 69203ebeb2d21..1163ec24854fd 100644 --- a/tests/crashes/148511.rs +++ b/tests/ui/impl-trait/issues/borrowck-ambiguity-ice-148511.rs @@ -1,5 +1,14 @@ -//@ known-bug: #148511 //@ edition: 2021 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[old] known-bug: #148511 +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr + +// This test previously caused an ICE on `use_service(make_service())` and +// has been fixed with the new solver. use std::any::Any; fn main() { diff --git a/tests/crashes/149162.rs b/tests/ui/impl-trait/issues/relate-mir-borrowck-ice-149162.rs similarity index 60% rename from tests/crashes/149162.rs rename to tests/ui/impl-trait/issues/relate-mir-borrowck-ice-149162.rs index 33532fe365ba4..4d72bd6f9f52f 100644 --- a/tests/crashes/149162.rs +++ b/tests/ui/impl-trait/issues/relate-mir-borrowck-ice-149162.rs @@ -1,4 +1,13 @@ -//@ known-bug: #149162 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[old] known-bug: #149162 +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr + +// This test previously caused an ICE in `fn buttons` when relating opaque +// types. This has been fixed by the opaque type rework in the new solver. use std::marker::PhantomData; pub trait ViewArgument { type Params<'a>; diff --git a/tests/ui/traits/projection-cache-rematch-impl-141124.next.stderr b/tests/ui/traits/projection-cache-rematch-impl-141124.next.stderr new file mode 100644 index 0000000000000..6adfba8e54f71 --- /dev/null +++ b/tests/ui/traits/projection-cache-rematch-impl-141124.next.stderr @@ -0,0 +1,41 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/projection-cache-rematch-impl-141124.rs:22:18 + | +LL | type Assoc = <(T,) as TraitAssoc>::Assoc; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`projection_cache_rematch_impl_141124`) + +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/projection-cache-rematch-impl-141124.rs:27:6 + | +LL | impl SimpleTrait for ::Assoc {} + | ^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::Assoc: SimpleTrait` + --> $DIR/projection-cache-rematch-impl-141124.rs:27:22 + | +LL | impl SimpleTrait for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating whether `::Assoc` is well-formed + --> $DIR/projection-cache-rematch-impl-141124.rs:27:22 + | +LL | impl SimpleTrait for ::Assoc {} + | ^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `<(T,) as TraitAssoc>::Assoc == _` + --> $DIR/projection-cache-rematch-impl-141124.rs:22:5 + | +LL | type Assoc = <(T,) as TraitAssoc>::Assoc; + | ^^^^^^^^^^ + +error[E0275]: overflow evaluating whether `<(T,) as TraitAssoc>::Assoc` is well-formed + --> $DIR/projection-cache-rematch-impl-141124.rs:22:5 + | +LL | type Assoc = <(T,) as TraitAssoc>::Assoc; + | ^^^^^^^^^^ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/projection-cache-rematch-impl-141124.rs b/tests/ui/traits/projection-cache-rematch-impl-141124.rs new file mode 100644 index 0000000000000..0c40d498c3074 --- /dev/null +++ b/tests/ui/traits/projection-cache-rematch-impl-141124.rs @@ -0,0 +1,32 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] known-bug: #141124 +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr + +// This example failed with the old solver in `fn rematch_impl`, +// likely due to a bug with the projection cache. Regression test +// for #141124. + +struct S; +trait SimpleTrait {} +trait TraitAssoc { + type Assoc; +} + +impl TraitAssoc for T +where + T: SimpleTrait, +{ + type Assoc = <(T,) as TraitAssoc>::Assoc; + //[next]~^ ERROR: overflow evaluating the requirement `<(T,) as TraitAssoc>::Assoc == _` + //[next]~| ERROR: overflow evaluating whether `<(T,) as TraitAssoc>::Assoc` is well-formed + //[next]~| ERROR: overflow evaluating the requirement `::Assoc == _` +} +impl SimpleTrait for ::Assoc {} +//[next]~^ ERROR: overflow evaluating the requirement `::Assoc == _` +//[next]~| ERROR: overflow evaluating the requirement `::Assoc: SimpleTrait` +//[next]~| ERROR: overflow evaluating whether `::Assoc` is well-formed + +pub fn main() {} From 17f3f9cae9fb6eb1ea980340f04c0f3ae2be12b9 Mon Sep 17 00:00:00 2001 From: Davlat Davydov Date: Fri, 2 Oct 2026 02:26:15 +0300 Subject: [PATCH 1243/1309] Add documentation for the and attributes Fix test-tidy review changes review changes review changes fix llvm build ignore attribute documentation example fix tidy use no_run instead of ignore --- library/core/src/attribute_docs.rs | 98 ++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/library/core/src/attribute_docs.rs b/library/core/src/attribute_docs.rs index 584e1583c9bdb..1f7504255b408 100644 --- a/library/core/src/attribute_docs.rs +++ b/library/core/src/attribute_docs.rs @@ -406,6 +406,104 @@ const _: () = (); /// [the `no_std` attribute]: ../reference/names/preludes.html#the-no_std-attribute const _: () = (); +#[doc(attribute = "no_main")] +/// Prevents emitting the `main` entrypoint symbol. +/// +/// Written as an inner attribute at the top of the crate root, the `no_main` attribute prevents +/// the compiler from generating the program's standard Rust entrypoint, leaving that up to you. +/// This is useful when some other object being linked into the program defines the entrypoint, +/// or when you want to define the platform's `main` symbol yourself. +/// +/// If you define an entry point symbol that is suitable for your target, it must also be exported +/// under an unmangled name using the [`no_mangle` attribute]: +/// +/// ```no_run +/// #![no_main] +/// +/// use std::ffi::{c_char, c_int}; +/// +/// #[unsafe(no_mangle)] +/// pub extern "C" fn main(_argc: c_int, _argv: *const *const c_char) -> c_int { +/// println!("Hello world!"); +/// 0 +/// } +/// ``` +/// +/// Unlike `no_std`, the `no_main` attribute does not prevent the compiler from generating +/// the startup routine or linking the standard library provided by the operating system's executable [ABI]. +/// +/// [ABI]: https://en.wikipedia.org/wiki/Application_binary_interface +/// [`no_mangle` attribute]: ../reference/abi.html#the-no_mangle-attribute +const _: () = (); + +#[doc(attribute = "repr")] +/// Specifies the [representation] of a type. +/// +/// Written as an outer attribute on a `struct`, `enum` or `union`, `repr` controls how the +/// type is laid out in memory. This is needed when passing types across an [FFI] boundary +/// or whenever you rely on a specific layout. +/// +/// The available representations are: +/// +/// * [`Rust`] (the default): the layout is unspecified and may change between compilations. +/// * [`C`]: the layout follows the rules of the C language for the target platform. +/// * The [primitive representations] (`u8`, `i32`, `usize`, ...): set the discriminant +/// type of an enum. +/// * [`transparent`]: the type has the same layout and ABI as its only non-zero-sized field. +/// +/// The `align(N)` and `packed(N)` modifiers raise or lower the alignment of a type, respectively. +/// `N` must be a power of two no greater than 229. The two modifiers cannot be +/// applied to the same type, and references to fields of a `packed` type cannot be created, +/// since they may be unaligned. +/// +/// # Examples +/// +/// ``` +/// #[repr(C, align(16))] +/// struct Foo { +/// first: u32, +/// second: u32, +/// third: u32, +/// } +/// +/// assert_eq!(align_of::(), 16); +/// // 12 bytes of fields, rounded up to a multiple of the alignment. +/// assert_eq!(size_of::(), 16); +/// ``` +/// +/// ``` +/// #[repr(C, packed(2))] +/// struct Foo { +/// first: u32, +/// second: u32, +/// third: u32, +/// } +/// +/// assert_eq!(align_of::(), 2); +/// assert_eq!(size_of::(), 12); +/// ``` +/// +/// ``` +/// #[repr(C)] +/// struct Foo { +/// item: T, +/// } +/// ``` +/// +/// `Foo` is laid out according to the C rules and is guaranteed to be 16-byte aligned. +/// +/// The representation is a property of the type definition, so it does +/// parameters: below, `Foo` and `Foo` both use the `C` representation. Their actual +/// layouts still differ, because they depend on `T`. +/// +/// [representation]: ../reference/type-layout.html#representations +/// [`Rust`]: ../reference/type-layout.html#the-rust-representation +/// [`C`]: ../reference/type-layout.html#the-c-representation +/// [primitive representations]: ../reference/type-layout.html#primitive-representations +/// [`transparent`]: ../reference/type-layout.html#the-transparent-representation +/// [FFI]: https://en.wikipedia.org/wiki/Foreign_function_interface +const _: () = (); + #[doc(attribute = "inline")] // /// Suggest that the compiler inline a function at its call sites. From 59a24269b1b1c3e30e8a693d4f2796c52fadcb52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sat, 3 Oct 2026 21:36:35 +0000 Subject: [PATCH 1244/1309] Remove useless `.into()` calls --- .../rustc_middle/src/ptrauth/discriminator.rs | 4 +--- compiler/rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_privacy/src/lib.rs | 3 +-- .../src/error_reporting/infer/mod.rs | 18 +++++++++--------- .../src/normalize_projection_ty.rs | 2 +- library/alloc/src/raw_vec/mod.rs | 2 +- src/librustdoc/clean/utils.rs | 10 +++++----- 7 files changed, 19 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/ptrauth/discriminator.rs b/compiler/rustc_middle/src/ptrauth/discriminator.rs index 7501f1b072188..d44ecafb775ef 100644 --- a/compiler/rustc_middle/src/ptrauth/discriminator.rs +++ b/compiler/rustc_middle/src/ptrauth/discriminator.rs @@ -282,9 +282,7 @@ fn compute_fn_ptr_type_discriminator<'tcx>( enc.push(b'E'); - let hash = enc.finish(); - - hash.into() + enc.finish() } // Clang disc type. diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index 0b3af1e2e3cd0..8113a020ef1ca 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2322,7 +2322,7 @@ impl<'a> Parser<'a> { Applicability::MaybeIncorrect, ); } - Err(err.into()) + Err(err) } /// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs index 9406f23155399..16a2ee9f22eaf 100644 --- a/compiler/rustc_privacy/src/lib.rs +++ b/compiler/rustc_privacy/src/lib.rs @@ -518,8 +518,7 @@ impl<'tcx> EmbargoVisitor<'tcx> { max_vis: Option, level: Level, ) -> bool { - let private_vis = - ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id).into()); + let private_vis = ty::Visibility::Restricted(self.tcx.parent_module_from_def_id(def_id)); if max_vis != Some(private_vis) { return self.effective_visibilities.update( def_id, diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index d83df2dfdf291..b2b57e018a7cf 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -1608,15 +1608,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { ValuePairs::TraitRefs(_) => (false, Mismatch::Fixed("trait")), ValuePairs::Aliases(ExpectedFound { expected, .. }) => { let def_id = match expected.kind { - ty::AliasTermKind::ProjectionTy { def_id } => def_id.into(), - ty::AliasTermKind::InherentTy { def_id } => def_id.into(), - ty::AliasTermKind::OpaqueTy { def_id } => def_id.into(), - ty::AliasTermKind::FreeTy { def_id } => def_id.into(), - ty::AliasTermKind::AnonConst { def_id } => def_id.into(), - ty::AliasTermKind::ProjectionConst { def_id } => def_id.into(), - ty::AliasTermKind::FreeConst { def_id } => def_id.into(), - ty::AliasTermKind::InherentConstSelf { def_id } => def_id.into(), - ty::AliasTermKind::InherentConstImpl { def_id } => def_id.into(), + ty::AliasTermKind::ProjectionTy { def_id } + | ty::AliasTermKind::InherentTy { def_id } + | ty::AliasTermKind::OpaqueTy { def_id } + | ty::AliasTermKind::FreeTy { def_id } + | ty::AliasTermKind::AnonConst { def_id } + | ty::AliasTermKind::ProjectionConst { def_id } + | ty::AliasTermKind::FreeConst { def_id } + | ty::AliasTermKind::InherentConstSelf { def_id } + | ty::AliasTermKind::InherentConstImpl { def_id } => def_id, }; (false, Mismatch::Fixed(self.tcx.def_descr(def_id))) } diff --git a/compiler/rustc_traits/src/normalize_projection_ty.rs b/compiler/rustc_traits/src/normalize_projection_ty.rs index c3fe949d29d64..d2ab9298657a2 100644 --- a/compiler/rustc_traits/src/normalize_projection_ty.rs +++ b/compiler/rustc_traits/src/normalize_projection_ty.rs @@ -139,7 +139,7 @@ fn normalize_canonicalized_inherent_projection<'tcx>( let normalized_term = traits::normalize_inherent_projection( selcx, param_env, - goal.into(), + goal, cause, 0, &mut obligations, diff --git a/library/alloc/src/raw_vec/mod.rs b/library/alloc/src/raw_vec/mod.rs index 2a1c30509ebaf..2f284bb4229eb 100644 --- a/library/alloc/src/raw_vec/mod.rs +++ b/library/alloc/src/raw_vec/mod.rs @@ -663,7 +663,7 @@ impl RawVecInner { unsafe { let alloc_size = elem_layout.size().unchecked_mul(self.cap.as_inner()); let layout = Layout::from_size_align_unchecked(alloc_size, elem_layout.align()); - Some((self.ptr.into(), layout)) + Some((self.ptr, layout)) } } } diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index d8a3fa6bed22c..57e5ec2c4f0fb 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -356,11 +356,11 @@ pub(crate) fn print_const(tcx: TyCtxt<'_>, n: ty::Const<'_>) -> String { match n.kind() { ty::ConstKind::Alias(_, ty::AliasConst { kind, .. }) => { let def_id: DefId = match kind { - ty::AliasConstKind::Projection { def_id } => def_id.into(), - ty::AliasConstKind::InherentSelf { def_id } => def_id.into(), - ty::AliasConstKind::InherentImpl { def_id } => def_id.into(), - ty::AliasConstKind::Free { def_id } => def_id.into(), - ty::AliasConstKind::Anon { def_id } => def_id.into(), + ty::AliasConstKind::Projection { def_id } + | ty::AliasConstKind::InherentSelf { def_id } + | ty::AliasConstKind::InherentImpl { def_id } + | ty::AliasConstKind::Free { def_id } + | ty::AliasConstKind::Anon { def_id } => def_id, }; if let Some(local_def_id) = def_id.as_local() && let Some(body_id) = tcx.hir_maybe_body_owned_by(local_def_id) From 8cb6fcaa8fa7a3becf5e5c52dd82307ff6997757 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 4 Oct 2026 00:12:30 +0000 Subject: [PATCH 1245/1309] Another useless into --- compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs index 3c45550016851..6eee95eb2750d 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs @@ -127,7 +127,7 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> { _ => return interp_ok(false), } - trace!("{:?}", self.dump_place(&dest.clone().into())); + trace!("{:?}", self.dump_place(&dest)); self.return_to_block(ret)?; interp_ok(true) } From c7ebf416c75e15a511e45a4d690690b0547cb14b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 4 Oct 2026 00:58:38 +0000 Subject: [PATCH 1246/1309] Another useless into --- compiler/rustc_borrowck/src/type_check/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 0e8565aef3f0b..ab0d786c6f264 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -1848,7 +1848,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> { assert_eq!(tcx.trait_impl_of_assoc(def_id), None); self.prove_clauses( - args.terms().map(|t| ty::ClauseKind::WellFormed(t.into())), + args.terms().map(|t| ty::ClauseKind::WellFormed(t)), locations, ConstraintCategory::Boring, ); From 1b5f48e2c91b00119cd7334667bacb780e7bf7eb Mon Sep 17 00:00:00 2001 From: Rishi Gupta Date: Sun, 4 Oct 2026 07:01:29 +0530 Subject: [PATCH 1247/1309] Fix extra spaces in integer format_into docs --- library/core/src/fmt/num.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/library/core/src/fmt/num.rs b/library/core/src/fmt/num.rs index 070d92537ebde..f72e07cc91bd4 100644 --- a/library/core/src/fmt/num.rs +++ b/library/core/src/fmt/num.rs @@ -273,8 +273,8 @@ macro_rules! impl_Display { #[doc = concat!("let n1 = 32", stringify!($Signed), ";")] /// assert_eq!(n1.format_into(&mut buf), "32"); /// - #[doc = concat!("let n2 = ", stringify!($Signed::MAX), ";")] - #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Signed::MAX), ".to_string());")] + #[doc = concat!("let n2 = ", stringify!($Signed), "::MAX;")] + #[doc = concat!("assert_eq!(n2.format_into(&mut buf), ", stringify!($Signed), "::MAX.to_string());")] /// ``` #[stable(feature = "int_format_into", since = "1.98.0")] pub fn format_into(self, buf: &mut NumBuffer) -> &str { From 340f27671a51f8289a55cc30bb20891ac776b52a Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Sun, 4 Oct 2026 06:00:16 +0000 Subject: [PATCH 1248/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 56343b1a7d3fed3f349a5c2dc474f65b504f5221. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index 4f744e09d6877..b936d2cbc7976 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -e0452e266c9a4d6522507318f8365741f0b12d29 +56343b1a7d3fed3f349a5c2dc474f65b504f5221 From d9d21db1d557138699d034fad3a35811bc117f4d Mon Sep 17 00:00:00 2001 From: Jarrod Petz Date: Sun, 4 Oct 2026 17:29:46 +1100 Subject: [PATCH 1249/1309] Add the `movdir64b` and `movdiri` x86 target features `MOVDIR64B` and `MOVDIRI` (direct stores of 64 bytes and of a 32/64-bit integer) are standalone x86 CPUID features, on Intel Tiger Lake and Sapphire Rapids onwards and AMD Zen 5, that are not part of any psABI microarchitecture level. They need their own unstable target features, gated behind `movdir64b_target_feature` and `movdiri_target_feature`. This is the compiler half of exposing the `_movdir64b`, `_directstoreu_u32` and `_directstoreu_u64` intrinsics; the stdarch half is blocked on this landing. Also update the check-cfg/target_feature UI test reference, which enumerates the full set of valid target features. --- compiler/rustc_feature/src/unstable.rs | 4 ++++ compiler/rustc_span/src/symbol.rs | 2 ++ compiler/rustc_target/src/target_features.rs | 2 ++ tests/ui/check-cfg/target_feature.stderr | 2 ++ 4 files changed, 10 insertions(+) diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 1af55be52abde..1aebf0c9ec56e 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -641,6 +641,10 @@ declare_features! ( (unstable, mips_target_feature, "1.27.0", Some(150253)), /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns. (unstable, more_qualified_paths, "1.54.0", Some(86935)), + /// The `movdir64b` target feature on x86. + (unstable, movdir64b_target_feature, "CURRENT_RUSTC_VERSION", Some(163741)), + /// The `movdiri` target feature on x86. + (unstable, movdiri_target_feature, "CURRENT_RUSTC_VERSION", Some(163741)), /// Allows `move(expr)` in closures. (incomplete, move_expr, "1.97.0", Some(155050)), /// The `movrs` target feature on x86. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 21b14a45ccf14..c3561ba18dcee 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1402,6 +1402,8 @@ symbols! { more_qualified_paths, more_struct_aliases, movbe_target_feature, + movdir64b_target_feature, + movdiri_target_feature, move_expr, move_ref_pattern, move_size_limit, diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs index 5272ed2df59b3..6a06a45f8ad19 100644 --- a/compiler/rustc_target/src/target_features.rs +++ b/compiler/rustc_target/src/target_features.rs @@ -496,6 +496,8 @@ static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[ ("lahfsahf", Unstable(sym::lahfsahf_target_feature), &[]), ("lzcnt", Stable, &[]), ("movbe", Stable, &[]), + ("movdir64b", Unstable(sym::movdir64b_target_feature), &[]), + ("movdiri", Unstable(sym::movdiri_target_feature), &[]), ("movrs", Unstable(sym::movrs_target_feature), &[]), ("pclmulqdq", Stable, &["sse2"]), ("popcnt", Stable, &[]), diff --git a/tests/ui/check-cfg/target_feature.stderr b/tests/ui/check-cfg/target_feature.stderr index 13c49fe00ef1f..8250fc1f1d498 100644 --- a/tests/ui/check-cfg/target_feature.stderr +++ b/tests/ui/check-cfg/target_feature.stderr @@ -211,6 +211,8 @@ LL | cfg!(target_feature = "_UNEXPECTED_VALUE"); `miscsr` `mops` `movbe` +`movdir64b` +`movdiri` `movrs` `movw` `mp` From b6cc6bd03ebc9fdb8d8d725e3739edf7729dc2cd Mon Sep 17 00:00:00 2001 From: Jarrod Petz Date: Sun, 4 Oct 2026 17:29:46 +1100 Subject: [PATCH 1250/1309] Add feature-gate tests for `movdir64b_target_feature` and `movdiri_target_feature` --- .../feature-gate-movdir64b_target_feature.rs | 6 ++++++ .../feature-gate-movdir64b_target_feature.stderr | 13 +++++++++++++ .../feature-gate-movdiri_target_feature.rs | 6 ++++++ .../feature-gate-movdiri_target_feature.stderr | 13 +++++++++++++ 4 files changed, 38 insertions(+) create mode 100644 tests/ui/feature-gates/feature-gate-movdir64b_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-movdir64b_target_feature.stderr create mode 100644 tests/ui/feature-gates/feature-gate-movdiri_target_feature.rs create mode 100644 tests/ui/feature-gates/feature-gate-movdiri_target_feature.stderr diff --git a/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.rs b/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.rs new file mode 100644 index 0000000000000..d05b85dc0a882 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "movdir64b")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.stderr new file mode 100644 index 0000000000000..6119f89cbe64e --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movdir64b_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `movdir64b` is currently unstable + --> $DIR/feature-gate-movdir64b_target_feature.rs:2:18 + | +LL | #[target_feature(enable = "movdir64b")] + | ^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #163741 for more information + = help: add `#![feature(movdir64b_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-movdiri_target_feature.rs b/tests/ui/feature-gates/feature-gate-movdiri_target_feature.rs new file mode 100644 index 0000000000000..76b47ab4df475 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movdiri_target_feature.rs @@ -0,0 +1,6 @@ +//@ only-x86_64 +#[target_feature(enable = "movdiri")] +//~^ ERROR: currently unstable +unsafe fn foo() {} + +fn main() {} diff --git a/tests/ui/feature-gates/feature-gate-movdiri_target_feature.stderr b/tests/ui/feature-gates/feature-gate-movdiri_target_feature.stderr new file mode 100644 index 0000000000000..726872718e6f7 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-movdiri_target_feature.stderr @@ -0,0 +1,13 @@ +error[E0658]: the target feature `movdiri` is currently unstable + --> $DIR/feature-gate-movdiri_target_feature.rs:2:18 + | +LL | #[target_feature(enable = "movdiri")] + | ^^^^^^^^^^^^^^^^^^ + | + = note: see issue #163741 for more information + = help: add `#![feature(movdiri_target_feature)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0658`. From 06b69b5d32f131a5c37ee0498d614c152a740ef8 Mon Sep 17 00:00:00 2001 From: Jarrod Petz Date: Sun, 4 Oct 2026 17:29:46 +1100 Subject: [PATCH 1251/1309] Detect `movdir64b` and `movdiri` in `is_x86_feature_detected!` Wire up runtime detection for both features: add them to the `is_x86_feature_detected!` feature list (gated on `movdir64b_target_feature` and `movdiri_target_feature`), enable them from CPUID leaf 7 ECX bits 28 and 27, and add them to the std_detect x86-specific dump test. --- library/std_detect/src/detect/arch/x86.rs | 6 ++++++ library/std_detect/src/detect/os/x86.rs | 2 ++ library/std_detect/tests/x86-specific.rs | 6 +++++- 3 files changed, 13 insertions(+), 1 deletion(-) diff --git a/library/std_detect/src/detect/arch/x86.rs b/library/std_detect/src/detect/arch/x86.rs index e054546afcb19..408b6ceaaa00b 100644 --- a/library/std_detect/src/detect/arch/x86.rs +++ b/library/std_detect/src/detect/arch/x86.rs @@ -111,6 +111,8 @@ features! { /// * `"adx"` /// * `"rtm"` /// * `"movbe"` + /// * `"movdir64b"` + /// * `"movdiri"` /// * `"ermsb"` /// * `"movrs"` /// * `"xop"` @@ -271,6 +273,10 @@ features! { /// RTM, Intel (Restricted Transactional Memory) @FEATURE: #[stable(feature = "movbe_target_feature", since = "1.67.0")] movbe: "movbe"; /// MOVBE (Move Data After Swapping Bytes) + @FEATURE: #[unstable(feature = "movdir64b_target_feature", issue = "163741")] movdir64b: "movdir64b"; + /// MOVDIR64B (Move 64 Bytes as Direct Store) + @FEATURE: #[unstable(feature = "movdiri_target_feature", issue = "163741")] movdiri: "movdiri"; + /// MOVDIRI (Move Doubleword as Direct Store) @FEATURE: #[unstable(feature = "movrs_target_feature", issue = "137976")] movrs: "movrs"; /// MOVRS (Move data with the read-shared hint) @FEATURE: #[stable(feature = "simd_x86", since = "1.27.0")] ermsb: "ermsb"; diff --git a/library/std_detect/src/detect/os/x86.rs b/library/std_detect/src/detect/os/x86.rs index 4e739fb38d56e..3d348fe2ac439 100644 --- a/library/std_detect/src/detect/os/x86.rs +++ b/library/std_detect/src/detect/os/x86.rs @@ -121,6 +121,8 @@ pub(crate) fn detect_features() -> cache::Initializer { enable(extended_features_ecx, 8, Feature::gfni); enable(extended_features_ecx, 9, Feature::vaes); enable(extended_features_ecx, 10, Feature::vpclmulqdq); + enable(extended_features_ecx, 27, Feature::movdiri); + enable(extended_features_ecx, 28, Feature::movdir64b); enable(extended_features_ebx, 3, Feature::bmi1); enable(extended_features_ebx, 8, Feature::bmi2); diff --git a/library/std_detect/tests/x86-specific.rs b/library/std_detect/tests/x86-specific.rs index 117182558f46a..ff88e25073d34 100644 --- a/library/std_detect/tests/x86-specific.rs +++ b/library/std_detect/tests/x86-specific.rs @@ -5,7 +5,9 @@ x86_amx_intrinsics, xop_target_feature, movrs_target_feature, - clflushopt_target_feature + clflushopt_target_feature, + movdir64b_target_feature, + movdiri_target_feature )] #[macro_use] @@ -68,6 +70,8 @@ fn dump() { println!("adx: {:?}", is_x86_feature_detected!("adx")); println!("rtm: {:?}", is_x86_feature_detected!("rtm")); println!("movbe: {:?}", is_x86_feature_detected!("movbe")); + println!("movdir64b: {:?}", is_x86_feature_detected!("movdir64b")); + println!("movdiri: {:?}", is_x86_feature_detected!("movdiri")); println!("avxvnni: {:?}", is_x86_feature_detected!("avxvnni")); println!("avxvnniint8: {:?}", is_x86_feature_detected!("avxvnniint8")); println!("avxneconvert: {:?}", is_x86_feature_detected!("avxneconvert")); From b4d2b85d68b735c4521fa16d4dc5a32e32fc2c65 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Oct 2026 00:27:03 +0200 Subject: [PATCH 1252/1309] replace directory handling retry loop by more lower-level shenanigans --- src/tools/miri/src/helpers.rs | 4 +- src/tools/miri/src/shims/files.rs | 52 ++++++ src/tools/miri/src/shims/unix/fs.rs | 115 ++++--------- src/tools/miri/src/shims/windows/fs.rs | 225 +++++++++++-------------- 4 files changed, 184 insertions(+), 212 deletions(-) diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs index b0ff200c0614b..f923d5529c6b9 100644 --- a/src/tools/miri/src/helpers.rs +++ b/src/tools/miri/src/helpers.rs @@ -10,7 +10,7 @@ use rustc_hir::def_id::{CRATE_DEF_INDEX, CrateNum, DefId, LOCAL_CRATE}; use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags; use rustc_middle::middle::dependency_format::Linkage; use rustc_middle::middle::exported_symbols::ExportedSymbol; -use rustc_middle::ty::layout::{LayoutOf, MaybeResult, TyAndLayout}; +use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, FnSigKind, IntTy, Ty, TyCtxt, UintTy}; use rustc_span::{Span, Symbol}; use rustc_structures::CrateType; @@ -109,6 +109,8 @@ pub fn resolve_path<'tcx>( /// Gets the layout of a type at a path. #[track_caller] pub fn path_ty_layout<'tcx>(cx: &impl LayoutOf<'tcx>, path: &[&str]) -> TyAndLayout<'tcx> { + use rustc_middle::ty::layout::MaybeResult; + let ty = resolve_path(cx.tcx(), path, Namespace::TypeNS).ty(cx.tcx(), cx.typing_env()); cx.layout_of(ty).to_result().ok().unwrap() } diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 95a898609571b..55b2ce105e6e6 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -718,3 +718,55 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { interp_ok(result.map_err(IoError::HostError)) } } + +/// Open something for which we don't know ahead of time whether it is a file or a directory. +/// +/// Custom flags need to be passed separately since they cannot be read from `opts`... +pub fn open_file_or_dir( + path: &std::path::Path, + mut opts: fs::OpenOptions, + #[cfg(unix)] custom_flags: i32, + #[cfg(windows)] custom_flags: u32, +) -> io::Result> { + #[cfg(unix)] + use std::os::unix::fs::OpenOptionsExt; + #[cfg(windows)] + use std::os::windows::fs::OpenOptionsExt; + + // On Unix, `open` works for files and directories. + // On Windows, that needs FILE_FLAG_BACKUP_SEMANTICS, but we don't want to set that by default. + // So we only set it when needed. + let file = match opts.custom_flags(custom_flags).open(path) { + Ok(file) => file, + + #[cfg(windows)] + Err(err) if err.kind() == io::ErrorKind::PermissionDenied => { + // This can happen when the file is actually a directory. + // So retry with FILE_FLAG_BACKUP_SEMANTICS. + opts.custom_flags( + custom_flags | windows_sys::Win32::Storage::FileSystem::FILE_FLAG_BACKUP_SEMANTICS, + ) + .open(path)? + } + + Err(err) => return Err(err), + }; + + let metadata = file.metadata().expect("just-opened file should have metadata"); + if metadata.is_dir() { + assert!(!metadata.is_symlink()); // Rust makes this mutually exclusive with `is_dir` + // Convert to dir. + cfg_select! { + unix => { + use std::os::fd::OwnedFd; + Ok(Either::Right(OwnedFd::from(file).into())) + } + windows => { + use std::os::windows::io::OwnedHandle; + Ok(Either::Right(OwnedHandle::from(file).into())) + } + } + } else { + Ok(Either::Left(file)) + } +} diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index 1943630d5108f..f2ecfc04480ec 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -2,7 +2,7 @@ use std::borrow::Cow; use std::ffi::OsString; -use std::fs::{self, Dir, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; +use std::fs::{self, DirBuilder, File, FileTimes, FileType, OpenOptions, TryLockError}; use std::io::{self, ErrorKind, Read, Seek, SeekFrom, Write}; use std::path::{self, Path}; use std::time::SystemTime; @@ -14,7 +14,7 @@ use rustc_target::spec::Os; use self::shims::time::system_time_to_duration; use crate::shims::FdId; -use crate::shims::files::{DirHandle, FdNum, FileHandle}; +use crate::shims::files::{DirHandle, FdNum, FileHandle, open_file_or_dir}; use crate::shims::os_str::{PathConversion, bytes_to_os_str}; use crate::shims::sig::Varargs; use crate::shims::unix::fd::{EvalContextExt as _, FlockOp, UnixFileDescription}; @@ -426,6 +426,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let mut flag = flag; let mut options = OpenOptions::new(); + let mut custom_flags = 0; let o_rdonly = this.eval_libc_i32("O_RDONLY"); let o_wronly = this.eval_libc_i32("O_WRONLY"); @@ -468,6 +469,14 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { if flag & o_directory == o_directory { flag &= !o_directory; want_directory = true; + // On Unix we can ask the host to only open directories. That's helpful especially in + // combination with O_NOFOLLOW as it affects which error we get when the final component + // is a symlink. Fixing the error up ourselves is non-trivial so we make the host + // generate the right error. + #[cfg(unix)] + { + custom_flags |= libc::O_DIRECTORY; + } } let o_append = this.eval_libc_i32("O_APPEND"); if flag & o_append == o_append { @@ -539,14 +548,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { nofollow = true; cfg_select! { unix => { - use std::os::unix::fs::OpenOptionsExt; - options.custom_flags(libc::O_NOFOLLOW); + custom_flags |= libc::O_NOFOLLOW; } windows => { - use std::os::windows::fs::OpenOptionsExt; - options.custom_flags( - windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT, - ); + custom_flags |= + windows_sys::Win32::Storage::FileSystem::FILE_FLAG_OPEN_REPARSE_POINT; } } } @@ -562,92 +568,35 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(ErrorKind::PermissionDenied); } - // We start a retry loop to deal with the `is_dir` race, see below. - // We add a retry counter to avoid infinite loops when things go wrong. - let mut counter = 0u32; - loop { - if counter >= 100 { - panic!( - "open seems stuck in an infinite retry loop. \ - If you can reproduce this, please file a bug." - ); - } - counter = counter.strict_add(1); - - // We need to know if the file is a directory to correctly open directory handles. - // The standard library only lets us open something as a file or a directory, so - // we check for that and then retry if we end up with the wrong thing. - let metadata = if nofollow { path.symlink_metadata() } else { path.metadata() }; - let is_dir = metadata.is_ok_and(|m| m.is_dir()); - - if is_dir { - // Directories cannot be opened for writing. - if access_mode != o_rdonly { + // Let's see what we get when we open this! + match open_file_or_dir(&path, options, custom_flags) { + Err(err) => this.set_errno_and_return_neg1_i32(err), + Ok(Either::Right(dir)) => { + // This means it cannot be a symlink, so `nofollow` is fine. + if writable { + // On Windows, opening a folder writable can succeed. + // But here we want it to always fail. return this.set_errno_and_return_neg1_i32(LibcError("EISDIR")); } - let dir = match Dir::open_with(&path, &options) { - Ok(dir) => dir, - Err(e) => { - if e.kind() == io::ErrorKind::NotADirectory { - // This changed from a directory to a file. Retry. - continue; - } - return this.set_errno_and_return_neg1_i32(e); - } - }; - #[cfg(bootstrap)] - let metadata = dir.metadata().expect("a just-opened dir should have metadata"); - #[cfg(not(bootstrap))] - let metadata = dir.self_metadata().expect("a just-opened dir should have metadata"); - if !metadata.is_dir() { - // This changed from a directory to a file. Retry. - continue; - } - - if nofollow && !cfg!(unix) { - // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just - // opens the symlink rather than the target. Turn that into an error. - if metadata.is_symlink() { - return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); - } - } let fd = this.machine.fds.insert_new(DirHandle::new(dir, &path)); - return interp_ok(Scalar::from_i32(fd)); - } else { - let file = match options.open(&path) { - Ok(file) => file, - Err(e) => { - let kind = e.kind(); - if kind == io::ErrorKind::IsADirectory { - // This changed from a directory to a file. Retry. - continue; - } - if want_directory && kind == io::ErrorKind::FilesystemLoop { - // This is reported as ENOTDIR. - return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); - } - return this.set_errno_and_return_neg1_i32(e); - } - }; - let metadata = file.metadata().expect("a just-opened file should have metadata"); - if metadata.is_dir() { - // This changed from a file to a directory. Retry. - continue; - } - + interp_ok(Scalar::from_i32(fd)) + } + Ok(Either::Left(file)) => { if want_directory { return this.set_errno_and_return_neg1_i32(LibcError("ENOTDIR")); } - if nofollow && !cfg!(unix) { - // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it just - // opens the symlink rather than the target. Turn that into an error. - if metadata.is_symlink() { + if file.metadata().unwrap().is_symlink() { + if nofollow { + // On Windows, FILE_FLAG_OPEN_REPARSE_POINT makes opening still succeed, it + // just opens the symlink rather than the target. Turn that into an error. return this.set_errno_and_return_neg1_i32(LibcError("ELOOP")); } + panic!("we should not get a symlink here"); } + let fd = this.machine.fds.insert_new(FileHandle { file, writable, readable }); - return interp_ok(Scalar::from_i32(fd)); + interp_ok(Scalar::from_i32(fd)) } } } diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index 5cf504c84eb85..c967654a9c73a 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -6,7 +6,7 @@ use bitflags::bitflags; use rustc_abi::Size; use rustc_target::spec::Os; -use crate::shims::files::{DirHandle, FileHandle}; +use crate::shims::files::{DirHandle, FileHandle, open_file_or_dir}; use crate::shims::windows::handle::{EvalContextExt as _, Handle}; use crate::*; @@ -186,7 +186,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { ); } - // We start a retry loop to deal with the `is_dir` and `exists_already` race, see below. + // We start a retry loop to deal with the `exists_already` race, see below. // We add a retry counter to avoid infinite loops when things go wrong. let mut counter = 0u32; loop { @@ -198,145 +198,114 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { } counter = counter.strict_add(1); - // We need to know if the file is a directory to correctly open directory handles. - // The standard library only lets us open something as a file or a directory, so - // we check for that and then retry if we end up with the wrong thing. - let is_dir = file_name.is_dir(); - - // BACKUP_SEMANTICS is how Windows calls the act of opening a directory handle. - if !attributes.contains(FileAttributes::BACKUP_SEMANTICS) && is_dir { - this.set_last_error(IoError::WindowsError("ERROR_ACCESS_DENIED"))?; - return interp_ok(Handle::Invalid); - } - - if is_dir { - // Open this as a directory. - // FIXME: shouldn't we check `creation_disposition` here? We do know that it already - // exists. - let dir = match fs::Dir::open(&file_name) { - Ok(dir) => dir, - Err(e) => { - if e.kind() == io::ErrorKind::NotADirectory { - // This changed from a directory to a file. Retry. - continue; - } - this.set_last_error(e)?; - return interp_ok(Handle::Invalid); + // Per the documentation: + // If the specified file exists and is writable, the function truncates the file, + // the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS. + // If the specified file does not exist and is a valid path, a new file is created, + // the function succeeds, and the last-error code is set to zero. + // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew + // + // We check whether it exists before trying to open it. This is racy, but there + // doesn't appear to be an std API that both succeeds whether or not a file already + // exists and tells us whether it is new. So instead we will open the file in a way + // that we can verify whether our guess is correct, and retry if it is not. + let exists_already = file_name.exists(); + + // Compute the OpenOptions. + let mut options = fs::OpenOptions::new(); + options.read(desired_read); + options.write(desired_write); + match creation_disposition { + CreateAlways | OpenAlways => { + // These two create the file if it is missing, but also succeed if it + // already exists. As explained above we cannot just always set `create_new` + // here, so we only do that if we think it is needed. + // We later verify our `exists_already` guess: if we expect it to already + // exist, we set no flag, thus failing if it doesn't exist. If we expect the + // file to not exist, we use `create_new` to fail if it does exist. + if !exists_already { + options.create_new(true); + } + if creation_disposition == CreateAlways { + options.truncate(true); } - }; - #[cfg(bootstrap)] - let metadata = dir.metadata(); - #[cfg(not(bootstrap))] - let metadata = dir.self_metadata(); - if !metadata.unwrap().is_dir() { - // This changed from a directory to a file. Retry. - continue; } - - // Windows communicates information via the error code on success. - if let CreateAlways | OpenAlways = creation_disposition { - this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; + CreateNew => { + options.create_new(true); + // Per `create_new` documentation: + // The file must be opened with write or append access in order to create a new file. + // https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new + if !desired_write { + options.append(true); + } } - - let fd_num = this.machine.fds.insert_new(DirHandle::new(dir, &file_name)); - return interp_ok(Handle::File(fd_num)); - } else { - // Per the documentation: - // If the specified file exists and is writable, the function truncates the file, - // the function succeeds, and last-error code is set to ERROR_ALREADY_EXISTS. - // If the specified file does not exist and is a valid path, a new file is created, - // the function succeeds, and the last-error code is set to zero. - // https://learn.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-createfilew - // - // We check whether it exists before trying to open it. This is racy, but there - // doesn't appear to be an std API that both succeeds whether or not a file already - // exists and tells us whether it is new. So instead we will open the file in a way - // that we can verify whether our guess is correct, and retry if it is not. - let exists_already = file_name.exists(); - - // Open this as a standard file. - let mut options = fs::OpenOptions::new(); - options.read(desired_read); - options.write(desired_write); - match creation_disposition { - CreateAlways | OpenAlways => { - // These two create the file if it is missing, but also succeed if it - // already exists. As explained above we cannot just always set `create_new` - // here, so we only do that if we think it is needed. - // We later verify our `exists_already` guess: if we expect it to already - // exist, we set no flag, thus failing if it doesn't exist. If we expect the - // file to not exist, we use `create_new` to fail if it does exist. - if !exists_already { - options.create_new(true); - } - if creation_disposition == CreateAlways { - options.truncate(true); - } + OpenExisting => { + if !desired_read && !desired_write { + // Windows supports handles with no permissions. These allow things such as + // reading metadata, but not file content. This is used by `Path::metadata`. + // `std` does not support this. To ensure we behave correctly as often as + // possible, we open the file for reading and live with the fact that this + // might incorrectly return `PermissionDenied`. + // FIXME: We could probably use `OpenOptionsExt`? On a Unix host, + // `O_PATH` apparently can open files for metadata use only. + options.read(true); } - CreateNew => { - options.create_new(true); - // Per `create_new` documentation: - // The file must be opened with write or append access in order to create a new file. - // https://doc.rust-lang.org/std/fs/struct.OpenOptions.html#method.create_new - if !desired_write { - options.append(true); - } + } + TruncateExisting => { + options.truncate(true); + } + } + + // Let's see what we get when we open this! + return match open_file_or_dir(&file_name, options, /* custom_flags */ 0) { + Err(err) => { + let kind = err.kind(); + if exists_already && kind == io::ErrorKind::NotFound { + // The file disappeared. Retry. + continue; } - OpenExisting => { - if !desired_read && !desired_write { - // Windows supports handles with no permissions. These allow things such as - // reading metadata, but not file content. This is used by `Path::metadata`. - // `std` does not support this. To ensure we behave correctly as often as - // possible, we open the file for reading and live with the fact that this - // might incorrectly return `PermissionDenied`. - // FIXME: We could probably use `OpenOptionsExt`? On a Unix host, - // `O_PATH` apparently can open files for metadata use only. - options.read(true); - } + if !exists_already && kind == io::ErrorKind::AlreadyExists { + // The file got created by something else. Retry. + continue; } - TruncateExisting => { - options.truncate(true); + + if kind == io::ErrorKind::IsADirectory && desired_write { + // This can happen on Unix hosts when write permissions are requested. + // Windows uses a different error code in that case. + this.set_last_error(IoError::WindowsError("ERROR_ACCESS_DENIED"))?; + } else { + this.set_last_error(err)?; } + return interp_ok(Handle::Invalid); } - - let file = match options.open(&file_name) { - Ok(file) => file, - Err(e) => { - let kind = e.kind(); - if kind == io::ErrorKind::IsADirectory { - // This changed from a file to a directory. Retry. - continue; - } - if exists_already && kind == io::ErrorKind::NotFound { - // The file disappeared. Retry. - continue; - } - if !exists_already && kind == io::ErrorKind::AlreadyExists { - // The file got created by something else. Retry. - continue; - } - this.set_last_error(e)?; + Ok(Either::Right(dir)) => { + // BACKUP_SEMANTICS is how Windows calls the act of opening a directory handle. + if !attributes.contains(FileAttributes::BACKUP_SEMANTICS) { + this.set_last_error(IoError::WindowsError("ERROR_ACCESS_DENIED"))?; return interp_ok(Handle::Invalid); } - }; - if file.metadata().unwrap().is_dir() { - // This changed from a file to a directory. Retry. - continue; + // We excluded this above. + if matches!(creation_disposition, CreateAlways | OpenAlways) { + unreachable!() + } + + let fd_num = this.machine.fds.insert_new(DirHandle::new(dir, &file_name)); + interp_ok(Handle::File(fd_num)) } + Ok(Either::Left(file)) => { + // CreateAlways | OpenAlways update the status code even on success. + if matches!(creation_disposition, CreateAlways | OpenAlways) && exists_already { + this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; + } - // Windows communicates information via the error code on success. - if let CreateAlways | OpenAlways = creation_disposition - && exists_already - { - this.set_last_error(IoError::WindowsError("ERROR_ALREADY_EXISTS"))?; + let fd_num = this.machine.fds.insert_new(FileHandle { + file, + writable: desired_write, + readable: desired_read, + }); + interp_ok(Handle::File(fd_num)) } - let fd_num = this.machine.fds.insert_new(FileHandle { - file, - writable: desired_write, - readable: desired_read, - }); - return interp_ok(Handle::File(fd_num)); - } + }; } } From 0ed52fadf48869a111a0b4e580271e53312914bd Mon Sep 17 00:00:00 2001 From: "Tim (Theemathas Chirananthavat)" Date: Fri, 18 Sep 2026 22:30:45 +0700 Subject: [PATCH 1253/1309] FCW for `#[panic_handler]` on `unsafe fn`. --- compiler/rustc_hir_typeck/src/check.rs | 17 ++++++++ compiler/rustc_hir_typeck/src/diagnostics.rs | 4 ++ compiler/rustc_lint_defs/src/builtin.rs | 39 +++++++++++++++++++ .../ui/codegen/no-mangle-on-panic-handler.rs | 2 +- .../codegen/no-mangle-on-panic-handler.stderr | 4 +- .../ui/panic-handler/unsafe_panic_handler.rs | 12 ++++++ .../panic-handler/unsafe_panic_handler.stderr | 12 ++++++ 7 files changed, 87 insertions(+), 3 deletions(-) create mode 100644 tests/ui/panic-handler/unsafe_panic_handler.rs create mode 100644 tests/ui/panic-handler/unsafe_panic_handler.stderr diff --git a/compiler/rustc_hir_typeck/src/check.rs b/compiler/rustc_hir_typeck/src/check.rs index 4f6345e04070b..35ec1fbaf207d 100644 --- a/compiler/rustc_hir_typeck/src/check.rs +++ b/compiler/rustc_hir_typeck/src/check.rs @@ -6,6 +6,7 @@ use rustc_hir::def::DefKind; use rustc_hir_analysis::check::check_function_signature; use rustc_infer::infer::RegionVariableOrigin; use rustc_infer::traits::WellFormedLoc; +use rustc_lint_defs::builtin::UNSAFE_PANIC_HANDLERS; use rustc_middle::ty::{self, Binder, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::sym; @@ -13,6 +14,7 @@ use rustc_trait_selection::traits::{ObligationCause, ObligationCauseCode}; use tracing::{debug, instrument}; use crate::coercion::CoerceMany; +use crate::diagnostics::UnsafePanicHandlers; use crate::gather_locals::GatherLocalsVisitor; use crate::{CoroutineTypes, Diverges, FnCtxt}; @@ -177,6 +179,21 @@ fn check_panic_info_fn(tcx: TyCtxt<'_>, fn_id: LocalDefId, fn_sig: ty::FnSig<'_> tcx.dcx().span_err(span, "should have no const parameters"); } + if fn_sig.safety().is_unsafe() { + let hir_id = tcx.local_def_id_to_hir_id(fn_id); + let span = tcx.def_span(fn_id); + // If the function is implicitly "unsafe" because it has a `#[target_feature]` attribute, + // then we should already have emitted an error. Don't also emit a warning. + // See `tests/ui/panic-handler/panic-handler-with-target-feature.rs` + if let Some(hir_fn_sig) = tcx.hir_fn_sig_by_hir_id(hir_id) + && hir_fn_sig.header.safety == hir::HeaderSafety::SafeTargetFeatures + { + tcx.dcx().span_delayed_bug(span, "`unsafe_panic_handlers` lint suppressed because there should already be an error for `#[target_feature]`"); + } else { + tcx.emit_node_span_lint(UNSAFE_PANIC_HANDLERS, hir_id, span, UnsafePanicHandlers); + } + } + let panic_info_did = tcx.require_lang_item(LangItem::PanicInfo, span); // build type `for<'a, 'b> fn(&'a PanicInfo<'b>) -> !` diff --git a/compiler/rustc_hir_typeck/src/diagnostics.rs b/compiler/rustc_hir_typeck/src/diagnostics.rs index 5c296fd665945..12e1006cc734f 100644 --- a/compiler/rustc_hir_typeck/src/diagnostics.rs +++ b/compiler/rustc_hir_typeck/src/diagnostics.rs @@ -1345,3 +1345,7 @@ impl ExprParenthesesNeeded { ExprParenthesesNeeded { left: s.shrink_to_lo(), right: s.shrink_to_hi() } } } + +#[derive(Diagnostic)] +#[diag("`#[panic_handler]` functions can't be `unsafe`")] +pub(crate) struct UnsafePanicHandlers; diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs index 34c7e3f19a631..d1dc5e05a0f09 100644 --- a/compiler/rustc_lint_defs/src/builtin.rs +++ b/compiler/rustc_lint_defs/src/builtin.rs @@ -5883,3 +5883,42 @@ declare_lint! { report_in_deps: true, }; } + +declare_lint! { + /// The `unsafe_panic_handlers` lint detects unsafe functions with + /// the `#[panic_handler]` attribute. + /// + /// ### Example + /// + /// ```rust,compile_fail + /// #![no_std] + /// + /// use core::panic::PanicInfo; + /// + /// #[panic_handler] + /// unsafe fn handle(_: &PanicInfo<'_>) -> ! { + /// loop {} + /// } + /// ``` + /// + /// {{produces}} + /// + /// ### Explanation + /// + /// Unsafe functions (declared as `unsafe fn`) are functions that can only be called + /// when the caller ensures that their safety requirements are met. On the other hand, + /// `#[panic_handler]` functions get called automatically by the compiler without + /// checking for any preconditions. Therefore, using the `#[panic_handler]` attribute + /// on unsafe functions is either incorrect or a misuse of `unsafe fn`. + /// + /// This is a [future-incompatible] lint to transition this to a hard + /// error in the future. See [issue #163263] for more details. + /// + /// [issue #163263]: https://github.com/rust-lang/rust/issues/163263 + pub UNSAFE_PANIC_HANDLERS, + Warn, + "detects unsafe functions with the `#[panic_handler]` attribute", + @future_incompatible = FutureIncompatibleInfo { + reason: fcw!(FutureReleaseError #163263), + }; +} diff --git a/tests/ui/codegen/no-mangle-on-panic-handler.rs b/tests/ui/codegen/no-mangle-on-panic-handler.rs index 1dc0cce0a2ece..4ef9fd2b8d372 100644 --- a/tests/ui/codegen/no-mangle-on-panic-handler.rs +++ b/tests/ui/codegen/no-mangle-on-panic-handler.rs @@ -9,6 +9,6 @@ use core::panic::PanicInfo; #[unsafe(no_mangle)] //~ ERROR `#[no_mangle]` cannot be used on internal language items #[panic_handler] -pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! { +pub fn panic_fmt(pi: &PanicInfo) -> ! { loop {} } diff --git a/tests/ui/codegen/no-mangle-on-panic-handler.stderr b/tests/ui/codegen/no-mangle-on-panic-handler.stderr index dc88b66d1b5d7..46cf8e8aec5e9 100644 --- a/tests/ui/codegen/no-mangle-on-panic-handler.stderr +++ b/tests/ui/codegen/no-mangle-on-panic-handler.stderr @@ -4,8 +4,8 @@ error: `#[no_mangle]` cannot be used on internal language items LL | #[unsafe(no_mangle)] | ^^^^^^^^^^^^^^^^^^^^ LL | #[panic_handler] -LL | pub unsafe fn panic_fmt(pi: &PanicInfo) -> ! { - | -------------------------------------------- should be the internal language item +LL | pub fn panic_fmt(pi: &PanicInfo) -> ! { + | ------------------------------------- should be the internal language item | = note: Rustc requires this item to have a specific mangled name. = note: If you are trying to prevent mangling to ease debugging, many diff --git a/tests/ui/panic-handler/unsafe_panic_handler.rs b/tests/ui/panic-handler/unsafe_panic_handler.rs new file mode 100644 index 0000000000000..95ecad168d42d --- /dev/null +++ b/tests/ui/panic-handler/unsafe_panic_handler.rs @@ -0,0 +1,12 @@ +//@ check-pass +#![crate_type = "lib"] +#![no_std] + +use core::panic::PanicInfo; + +#[panic_handler] +unsafe fn handle(_: &PanicInfo) -> ! { + //~^ WARN `#[panic_handler]` functions can't be `unsafe` + //~| WARN this was previously accepted by the compiler but is being phased out + loop {} +} diff --git a/tests/ui/panic-handler/unsafe_panic_handler.stderr b/tests/ui/panic-handler/unsafe_panic_handler.stderr new file mode 100644 index 0000000000000..7111d313b6148 --- /dev/null +++ b/tests/ui/panic-handler/unsafe_panic_handler.stderr @@ -0,0 +1,12 @@ +warning: `#[panic_handler]` functions can't be `unsafe` + --> $DIR/unsafe_panic_handler.rs:8:1 + | +LL | unsafe fn handle(_: &PanicInfo) -> ! { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #163263 + = note: `#[warn(unsafe_panic_handlers)]` on by default + +warning: 1 warning emitted + From 4e604a98b65aa08b6355df75fdf072d6b4e6ee87 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sun, 4 Oct 2026 10:30:38 +0200 Subject: [PATCH 1254/1309] support F_GETFL on files and directories this helps with File debug-printing on Linux (but not on other Unixes) --- src/tools/miri/src/shims/files.rs | 58 +++++---- src/tools/miri/src/shims/unix/fd.rs | 49 ++++---- src/tools/miri/src/shims/unix/fs.rs | 17 +++ .../miri/src/shims/unix/linux_like/epoll.rs | 5 +- .../miri/src/shims/unix/linux_like/eventfd.rs | 5 +- src/tools/miri/src/shims/unix/socket.rs | 22 ++-- src/tools/miri/src/shims/unix/tcp_socket.rs | 28 ++--- .../miri/src/shims/unix/virtual_socket.rs | 112 +++++++++--------- src/tools/miri/tests/pass-dep/libc/libc-fs.rs | 31 ++++- 9 files changed, 181 insertions(+), 146 deletions(-) diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index 55b2ce105e6e6..c1a9bff07dec2 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -195,25 +195,10 @@ pub trait FileDescription: std::fmt::Debug + FileDescriptionExt { false } - fn as_unix<'tcx>( - self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { - panic!("Not a unix file descriptor: {}", self.name()); - } - - /// Implementation of fcntl(F_GETFL) for this FD. - fn get_flags<'tcx>(&self, _ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { - throw_unsup_format!("fcntl: {} is not supported for F_GETFL", self.name()); - } - - /// Implementation of fcntl(F_SETFL) for this FD. - fn set_flags<'tcx>( - &self, - _flag: i32, - _ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Scalar> { - throw_unsup_format!("fcntl: {} is not supported for F_SETFL", self.name()); + /// Converts this FD into a unix file description. Must succeed for all FD types that can be + /// created on Unix targets! + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + panic!("Not a unix file description: {}", self.name()); } /// Get the `ReadinessWatched` of the file description. @@ -228,7 +213,7 @@ pub trait FileDescription: std::fmt::Debug + FileDescriptionExt { } #[derive(Debug)] -struct Stdin { +pub struct Stdin { stdin: io::Stdin, watched: ReadinessWatched, } @@ -278,10 +263,14 @@ impl FileDescription for Stdin { readiness.writable = true; readiness } + + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + self + } } #[derive(Debug)] -struct Stdout { +pub struct Stdout { stdout: io::Stdout, watched: ReadinessWatched, } @@ -331,10 +320,14 @@ impl FileDescription for Stdout { readiness.writable = true; readiness } + + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + self + } } #[derive(Debug)] -struct Stderr { +pub struct Stderr { stderr: io::Stderr, watched: ReadinessWatched, } @@ -378,6 +371,10 @@ impl FileDescription for Stderr { readiness.writable = true; readiness } + + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + self + } } /// Like /dev/null @@ -419,6 +416,10 @@ impl FileDescription for NullOutput { readiness.writable = true; readiness } + + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + self + } } #[derive(Debug)] @@ -505,14 +506,7 @@ impl FileDescription for FileHandle { true } - fn as_unix<'tcx>( - self: FileDescriptionRef, - ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { - assert!( - ecx.target_os_is_unix(), - "unix file operations are only available for unix targets" - ); + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { self } } @@ -587,6 +581,10 @@ impl FileDescription for DirHandle { throw_unsup_format!("writing directories is not supported on this target"); } } + + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { + self + } } /// Internal type of a file-descriptor - this is what [`FdTable`] expects diff --git a/src/tools/miri/src/shims/unix/fd.rs b/src/tools/miri/src/shims/unix/fd.rs index c0278d539d877..e4dbe77240633 100644 --- a/src/tools/miri/src/shims/unix/fd.rs +++ b/src/tools/miri/src/shims/unix/fd.rs @@ -63,6 +63,20 @@ pub trait UnixFileDescription: FileDescription { throw_unsup_format!("cannot flock {}", self.name()); } + /// Implementation of fcntl(F_GETFL) for this FD. + fn get_flags<'tcx>(&self, _ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { + throw_unsup_format!("fcntl: {} is not supported for F_GETFL", self.name()); + } + + /// Implementation of fcntl(F_SETFL) for this FD. + fn set_flags<'tcx>( + &self, + _flag: i32, + _ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + throw_unsup_format!("fcntl: {} is not supported for F_SETFL", self.name()); + } + /// Modifies device parameters. /// `op` is the device-dependent operation code. It's either a `c_long` or `c_int`, depending on /// the target and whether it uses glibc or musl. @@ -78,14 +92,18 @@ pub trait UnixFileDescription: FileDescription { } /// Returns this file description as a Unix socket, if it represents one. - fn as_socket<'tcx>( + fn as_socket( self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, ) -> Option> { None } } +impl UnixFileDescription for shims::files::Stdin {} +impl UnixFileDescription for shims::files::Stdout {} +impl UnixFileDescription for shims::files::Stderr {} +impl UnixFileDescription for shims::files::NullOutput {} + impl<'tcx> EvalContextExt<'tcx> for crate::MiriInterpCx<'tcx> {} pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { fn close(&mut self, fd_num: FdNum) -> InterpResult<'tcx, Scalar> { @@ -94,6 +112,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Some(fd) = this.machine.fds.remove(fd_num) else { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; + let fd = fd.as_unix(); // sanity-check if this.tcx.sess.target.os == Os::Illumos { // Illumos didn't like the Linux semantics of epoll tracking file *descriptions* // rather than file *descriptors*. So on Illumos, when a file description is closed, @@ -171,7 +190,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { throw_unsup_format!("unsupported flags {:#x}", op); }; - let result = fd.as_unix(this).flock(this.machine.communicate(), parsed_op)?; + let result = fd.as_unix().flock(this.machine.communicate(), parsed_op)?; // return `0` if flock is successful let result = result.map(|()| 0i32); interp_ok(Scalar::from_i32(this.try_unwrap_io_result(result)?)) @@ -202,7 +221,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // Since some ioctl operations use the return value as an output parameter, we cannot strictly use the convention of // zero indicating success and -1 indicating an error. - let return_value = fd.as_unix(this).ioctl(op, varargs, this)?; + let return_value = fd.as_unix().ioctl(op, varargs, this)?; interp_ok(Scalar::from_i32(return_value)) } @@ -262,7 +281,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - fd.get_flags(this) + fd.as_unix().get_flags(this) } cmd if cmd == f_setfl => { // Check if this is a valid open file descriptor. @@ -286,7 +305,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { | this.eval_libc_i32("O_NOCTTY") | this.eval_libc_i32("O_TRUNC"); - fd.set_flags(flag & !ignored_flags, this) + fd.as_unix().set_flags(flag & !ignored_flags, this) } cmd if this.tcx.sess.target.os == Os::MacOs && cmd == this.eval_libc_i32("F_FULLFSYNC") => @@ -699,14 +718,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return finish.call(this, Err(LibcError("EINVAL"))); }; - fd.as_unix(this).pread( - this.machine.communicate(), - offset, - ptr, - len, - this, - finish, - )? + fd.as_unix().pread(this.machine.communicate(), offset, ptr, len, this, finish)? } }; interp_ok(()) @@ -758,14 +770,7 @@ trait EvalContextPrivExt<'tcx>: crate::MiriInterpCxExt<'tcx> { let Ok(offset) = u64::try_from(offset) else { return finish.call(this, Err(LibcError("EINVAL"))); }; - fd.as_unix(this).pwrite( - this.machine.communicate(), - ptr, - len, - offset, - this, - finish, - )? + fd.as_unix().pwrite(this.machine.communicate(), ptr, len, offset, this, finish)? } }; interp_ok(()) diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs index f2ecfc04480ec..e385f18e4cbcf 100644 --- a/src/tools/miri/src/shims/unix/fs.rs +++ b/src/tools/miri/src/shims/unix/fs.rs @@ -168,6 +168,22 @@ impl UnixFileDescription for FileHandle { }, } } + + fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { + interp_ok(match (self.readable, self.writable) { + (true, true) => ecx.eval_libc("O_RDWR"), + (true, false) => ecx.eval_libc("O_RDONLY"), + (false, true) => ecx.eval_libc("O_WRONLY"), + _ => unreachable!(), + }) + } +} + +impl UnixFileDescription for DirHandle { + fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { + // Directories are always readonly on Unix. + interp_ok(ecx.eval_libc("O_RDONLY")) + } } /// The table of open directories. @@ -666,6 +682,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { windows => { use std::os::windows::fs; // This is racy, but not much we can do about that. + // FIXME: maybe we can retry based on the error code? if src.is_dir() { fs::symlink_dir(src, dst) } else { diff --git a/src/tools/miri/src/shims/unix/linux_like/epoll.rs b/src/tools/miri/src/shims/unix/linux_like/epoll.rs index fa627f982ec79..482e7972a7364 100644 --- a/src/tools/miri/src/shims/unix/linux_like/epoll.rs +++ b/src/tools/miri/src/shims/unix/linux_like/epoll.rs @@ -28,10 +28,7 @@ impl FileDescription for Epoll { interp_ok(Either::Right("S_IFREG")) } - fn as_unix<'tcx>( - self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { self } } diff --git a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs index 4b84906d71cd7..476f154722437 100644 --- a/src/tools/miri/src/shims/unix/linux_like/eventfd.rs +++ b/src/tools/miri/src/shims/unix/linux_like/eventfd.rs @@ -116,10 +116,7 @@ impl FileDescription for EventFd { } } - fn as_unix<'tcx>( - self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { self } } diff --git a/src/tools/miri/src/shims/unix/socket.rs b/src/tools/miri/src/shims/unix/socket.rs index ce1f5c06b6b2c..a7501326e378c 100644 --- a/src/tools/miri/src/shims/unix/socket.rs +++ b/src/tools/miri/src/shims/unix/socket.rs @@ -250,7 +250,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; @@ -271,7 +271,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; @@ -305,7 +305,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1(LibcError("ENOTSOCK"), dest); }; @@ -392,7 +392,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1(LibcError("ENOTSOCK"), dest); }; @@ -438,7 +438,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1(LibcError("ENOTSOCK"), dest); }; @@ -517,7 +517,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1(LibcError("ENOTSOCK"), dest); }; @@ -609,7 +609,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; @@ -646,7 +646,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; @@ -714,7 +714,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; @@ -746,7 +746,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1(LibcError("EBADF"), dest); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1(LibcError("ENOTSOCK"), dest); }; @@ -789,7 +789,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return this.set_errno_and_return_neg1_i32(LibcError("EBADF")); }; - let Some(socket) = fd.as_unix(this).as_socket(this) else { + let Some(socket) = fd.as_unix().as_socket() else { return this.set_errno_and_return_neg1_i32(LibcError("ENOTSOCK")); }; diff --git a/src/tools/miri/src/shims/unix/tcp_socket.rs b/src/tools/miri/src/shims/unix/tcp_socket.rs index 394f80a151f06..4275926260da9 100644 --- a/src/tools/miri/src/shims/unix/tcp_socket.rs +++ b/src/tools/miri/src/shims/unix/tcp_socket.rs @@ -198,13 +198,20 @@ impl FileDescription for TcpSocket { false } - fn as_unix<'tcx>( - self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { self } + fn readiness_watched(&self) -> Option<&ReadinessWatched> { + Some(&self.watched) + } + + fn readiness(&self) -> Readiness { + *self.io_readiness.borrow() + } +} + +impl UnixFileDescription for TcpSocket { fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { let mut flags = ecx.eval_libc_i32("O_RDWR"); @@ -238,16 +245,6 @@ impl FileDescription for TcpSocket { interp_ok(Scalar::from_i32(0)) } - fn readiness_watched(&self) -> Option<&ReadinessWatched> { - Some(&self.watched) - } - - fn readiness(&self) -> Readiness { - *self.io_readiness.borrow() - } -} - -impl UnixFileDescription for TcpSocket { fn ioctl<'tcx>( &self, op: Scalar, @@ -283,9 +280,8 @@ impl UnixFileDescription for TcpSocket { throw_unsup_format!("ioctl: unsupported operation {op:#x} on socket"); } - fn as_socket<'tcx>( + fn as_socket( self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, ) -> Option> { Some(self) } diff --git a/src/tools/miri/src/shims/unix/virtual_socket.rs b/src/tools/miri/src/shims/unix/virtual_socket.rs index 04bc2ab8a890a..99d73fe9eb5cb 100644 --- a/src/tools/miri/src/shims/unix/virtual_socket.rs +++ b/src/tools/miri/src/shims/unix/virtual_socket.rs @@ -147,65 +147,10 @@ impl FileDescription for VirtualSocket { false } - fn as_unix<'tcx>( - self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, - ) -> FileDescriptionRef { + fn as_unix(self: FileDescriptionRef) -> FileDescriptionRef { self } - fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { - let mut flags = 0; - - // Get flag for file access mode. - // The flag for both socketpair and pipe will remain the same even when the peer - // fd is closed, so we need to look at the original type of this socket, not at whether - // the peer socket still exists. - match self.fd_type { - VirtualSocketType::Socketpair => { - flags |= ecx.eval_libc_i32("O_RDWR"); - } - VirtualSocketType::PipeRead => { - flags |= ecx.eval_libc_i32("O_RDONLY"); - } - VirtualSocketType::PipeWrite => { - flags |= ecx.eval_libc_i32("O_WRONLY"); - } - } - - // Get flag for blocking status. - if self.is_nonblock.get() { - flags |= ecx.eval_libc_i32("O_NONBLOCK"); - } - - interp_ok(Scalar::from_i32(flags)) - } - - fn set_flags<'tcx>( - &self, - mut flag: i32, - ecx: &mut MiriInterpCx<'tcx>, - ) -> InterpResult<'tcx, Scalar> { - let o_nonblock = ecx.eval_libc_i32("O_NONBLOCK"); - - // O_NONBLOCK flag can be set / unset by user. - if flag & o_nonblock == o_nonblock { - self.is_nonblock.set(true); - flag &= !o_nonblock; - } else { - self.is_nonblock.set(false); - } - - // Throw error if there is any unsupported flag. - if flag != 0 { - throw_unsup_format!( - "fcntl: only O_NONBLOCK is supported for F_SETFL on socketpairs and pipes" - ) - } - - interp_ok(Scalar::from_i32(0)) - } - fn readiness_watched(&self) -> Option<&ReadinessWatched> { Some(&self.watched) } @@ -258,6 +203,58 @@ impl FileDescription for VirtualSocket { } impl UnixFileDescription for VirtualSocket { + fn get_flags<'tcx>(&self, ecx: &mut MiriInterpCx<'tcx>) -> InterpResult<'tcx, Scalar> { + let mut flags = 0; + + // Get flag for file access mode. + // The flag for both socketpair and pipe will remain the same even when the peer + // fd is closed, so we need to look at the original type of this socket, not at whether + // the peer socket still exists. + match self.fd_type { + VirtualSocketType::Socketpair => { + flags |= ecx.eval_libc_i32("O_RDWR"); + } + VirtualSocketType::PipeRead => { + flags |= ecx.eval_libc_i32("O_RDONLY"); + } + VirtualSocketType::PipeWrite => { + flags |= ecx.eval_libc_i32("O_WRONLY"); + } + } + + // Get flag for blocking status. + if self.is_nonblock.get() { + flags |= ecx.eval_libc_i32("O_NONBLOCK"); + } + + interp_ok(Scalar::from_i32(flags)) + } + + fn set_flags<'tcx>( + &self, + mut flag: i32, + ecx: &mut MiriInterpCx<'tcx>, + ) -> InterpResult<'tcx, Scalar> { + let o_nonblock = ecx.eval_libc_i32("O_NONBLOCK"); + + // O_NONBLOCK flag can be set / unset by user. + if flag & o_nonblock == o_nonblock { + self.is_nonblock.set(true); + flag &= !o_nonblock; + } else { + self.is_nonblock.set(false); + } + + // Throw error if there is any unsupported flag. + if flag != 0 { + throw_unsup_format!( + "fcntl: only O_NONBLOCK is supported for F_SETFL on socketpairs and pipes" + ) + } + + interp_ok(Scalar::from_i32(0)) + } + fn ioctl<'tcx>( &self, op: Scalar, @@ -301,9 +298,8 @@ impl UnixFileDescription for VirtualSocket { throw_unsup_format!("ioctl: unsupported operation {op:#x} on socket"); } - fn as_socket<'tcx>( + fn as_socket( self: FileDescriptionRef, - _ecx: &MiriInterpCx<'tcx>, ) -> Option> { match self.fd_type { VirtualSocketType::Socketpair => Some(self), diff --git a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs index a31839d116fd6..39a7203c52318 100644 --- a/src/tools/miri/tests/pass-dep/libc/libc-fs.rs +++ b/src/tools/miri/tests/pass-dep/libc/libc-fs.rs @@ -29,6 +29,7 @@ fn main() { #[cfg(target_os = "linux")] test_ftruncate::(libc::ftruncate64); test_create_read_write(); + test_read_and_uninit(); test_file_open_args(); test_file_open_nofollow(); test_file_open_dangling_symlink(); @@ -61,7 +62,7 @@ fn main() { test_lstat(); test_futimens(); test_isatty(); - test_read_and_uninit(); + test_getfl(); #[cfg(target_os = "macos")] test_ioctl(); #[cfg(target_os = "linux")] @@ -1213,6 +1214,34 @@ fn test_isatty() { } } +fn test_getfl() { + let path = utils::prepare_with_content("miri-test-getfl.txt", b"hello"); + let cpath = utils::into_c_string(&path); + + for flag in [libc::O_RDONLY, libc::O_WRONLY, libc::O_RDWR] { + let fd = errno_result(unsafe { libc::open(cpath.as_ptr(), flag) }).unwrap(); + // These flags contain "junk" that the kernel adds, such as a O_LARGEFILE flag, even on + // x86-64 where glibc sets O_LARGEFILE to 0 (but the kernel still says it is 0x8000). + // So we do not check the full flag, just the access mode. + assert_eq!( + errno_result(unsafe { libc::fcntl(fd, libc::F_GETFL) }).unwrap() & libc::O_ACCMODE, + flag + ); + errno_check(unsafe { libc::close(fd) }); + } + + // Also test it on a directory. + let fd = errno_result(unsafe { + libc::open(utils::into_c_string(path.parent().unwrap()).as_ptr(), libc::O_RDONLY) + }) + .unwrap(); + assert_eq!( + errno_result(unsafe { libc::fcntl(fd, libc::F_GETFL) }).unwrap() & libc::O_ACCMODE, + libc::O_RDONLY + ); + errno_check(unsafe { libc::close(fd) }); +} + fn test_read_and_uninit() { { // We test that libc::read initializes its buffer. From 90b278f4cf94374f0ca2ed3786079ac8655a2416 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 4 Oct 2026 12:16:45 +0200 Subject: [PATCH 1255/1309] Add track-diagnostics test --- tests/ui/track-diagnostics/track8.rs | 12 ++++++++++++ tests/ui/track-diagnostics/track8.stderr | 21 +++++++++++++++++++++ 2 files changed, 33 insertions(+) create mode 100644 tests/ui/track-diagnostics/track8.rs create mode 100644 tests/ui/track-diagnostics/track8.stderr diff --git a/tests/ui/track-diagnostics/track8.rs b/tests/ui/track-diagnostics/track8.rs new file mode 100644 index 0000000000000..13fe959a30ed5 --- /dev/null +++ b/tests/ui/track-diagnostics/track8.rs @@ -0,0 +1,12 @@ +//@ compile-flags: -Z track-diagnostics +//@ dont-require-annotations: NOTE + +// Normalize the emitted location so this doesn't need +// updating everytime someone adds or removes a line. +//@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" +//@ normalize-stderr: "/rustc(?:-dev)?/[a-z0-9.]+/" -> "" +#![crate_type = "lib"] + +#[repr] //~ ERROR: malformed `repr` attribute input +#[diagnostic::ferris] //~ WARN unknown diagnostic attribute +pub mod empty {} \ No newline at end of file diff --git a/tests/ui/track-diagnostics/track8.stderr b/tests/ui/track-diagnostics/track8.stderr new file mode 100644 index 0000000000000..0e1ee1f5a9333 --- /dev/null +++ b/tests/ui/track-diagnostics/track8.stderr @@ -0,0 +1,21 @@ +error[E0539]: malformed `repr` attribute input + --> $DIR/track8.rs:LL:CC + | +LL | #[repr] + | ^^^^ expected this to be a list + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/interface.rs:LL:CC + = note: for more information, visit + +warning: unknown diagnostic attribute + --> $DIR/track8.rs:LL:CC + | +LL | #[diagnostic::ferris] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_interface/src/passes.rs:LL:CC + = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0539`. From b4af75e56294740c8f3b2d400b2df7ee270a889e Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 4 Oct 2026 12:25:20 +0200 Subject: [PATCH 1256/1309] rustc_attr_parsing: properly track error locations --- compiler/rustc_attr_parsing/src/context.rs | 33 ++++++++++++++++++++ compiler/rustc_attr_parsing/src/interface.rs | 1 + tests/ui/track-diagnostics/track8.stderr | 2 +- 3 files changed, 35 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index 72839643b4dc3..b4221048cfc82 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -408,6 +408,7 @@ pub struct AcceptContext<'f, 'sess> { } impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { + #[track_caller] pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { self.cx.emit_err(diag) } @@ -497,6 +498,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// The provided span is used as a fallback for diagnostic generation in case `arg` does not /// contain any. It should be the span of the node that contains `arg`. + #[track_caller] pub(crate) fn expect_single_element_list<'arg>( &mut self, arg: &'arg ArgParser, @@ -529,6 +531,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_list<'arg>( &mut self, args: &'arg ArgParser, @@ -550,6 +553,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_single<'arg>( &mut self, list: &'arg MetaItemListParser, @@ -589,6 +593,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_name_value<'arg, Arg>( &mut self, arg: &'arg Arg, @@ -609,6 +614,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> { if let Err(span) = arg.as_no_args() { self.adcx().expected_no_args(span); @@ -631,6 +637,7 @@ impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> { /// /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]). /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error. + #[track_caller] pub(crate) fn expect_string_literal<'arg, Arg>(&mut self, arg: &'arg Arg) -> Option where Arg: ExpectStringLiteral, @@ -644,6 +651,7 @@ pub(crate) trait ExpectNameValue { where Self: 'a; + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -655,6 +663,7 @@ pub(crate) trait ExpectNameValue { impl ExpectNameValue for MetaItemOrLitParser { type Output<'a> = (Ident, &'a NameValueParser); + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -673,6 +682,7 @@ impl ExpectNameValue for MetaItemOrLitParser { impl ExpectNameValue for MetaItemParser { type Output<'a> = (Ident, &'a NameValueParser); + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -697,6 +707,7 @@ impl ExpectNameValue for MetaItemParser { impl ExpectNameValue for ArgParser { type Output<'a> = &'a NameValueParser; + #[track_caller] fn expect_name_value<'a, 'f, 'sess>( &'a self, cx: &mut AcceptContext<'f, 'sess>, @@ -713,11 +724,13 @@ impl ExpectNameValue for ArgParser { } pub(crate) trait ExpectStringLiteral { + #[track_caller] fn expect_string_literal<'f, 'sess>(&self, cx: &mut AcceptContext<'f, 'sess>) -> Option; } impl ExpectStringLiteral for NameValueParser { + #[track_caller] fn expect_string_literal<'f, 'sess>( &self, cx: &mut AcceptContext<'f, 'sess>, @@ -731,6 +744,7 @@ impl ExpectStringLiteral for NameValueParser { } impl ExpectStringLiteral for MetaItemOrLitParser { + #[track_caller] fn expect_string_literal<'f, 'sess>( &self, cx: &mut AcceptContext<'f, 'sess>, @@ -893,6 +907,7 @@ pub enum ShouldEmit { } impl ShouldEmit { + #[track_caller] pub(crate) fn emit_err(self, diag: Diag<'_>) -> ErrorGuaranteed { match self { ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit_err(), @@ -912,6 +927,7 @@ pub(crate) struct AttributeDiagnosticContext<'a, 'f, 'sess> { } impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { + #[track_caller] fn emit_parse_error( &mut self, mut span: Span, @@ -950,6 +966,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// Helpers that can be used to generate errors during attribute parsing. impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { + #[track_caller] pub(crate) fn expected_integer_literal_in_range( &mut self, span: Span, @@ -964,6 +981,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// The provided span is used as a fallback in case `args` does not contain any. It should be /// the span of the node that contains `args`. + #[track_caller] pub(crate) fn expected_list(&mut self, span: Span, args: &ArgParser) -> ErrorGuaranteed { let span = match args { ArgParser::NoArgs => span, @@ -973,6 +991,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList) } + #[track_caller] pub(crate) fn expected_list_with_num_args_or_more( &mut self, args: usize, @@ -984,45 +1003,54 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { ) } + #[track_caller] pub(crate) fn expected_list_or_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs) } + #[track_caller] pub(crate) fn expected_nv_or_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs) } + #[track_caller] pub(crate) fn expected_non_empty_string_literal(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNonEmptyStringLiteral) } + #[track_caller] pub(crate) fn expected_no_args(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs) } /// Emit an error that a `name` was expected here + #[track_caller] pub(crate) fn expected_identifier(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier) } /// Emit an error that a `name = value` pair was expected at this span. The symbol can be given for /// a nicer error message talking about the specific name that was found lacking a value. + #[track_caller] fn expected_name_value(&mut self, span: Span, name: Option) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name)) } /// Emit an error that a `name = value` argument is missing in a list of name-value pairs. + #[track_caller] pub(crate) fn missing_name_value(&mut self, span: Span, name: Symbol) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::MissingNameValue(name)) } /// Emit an error that a `name = value` pair was found where that name was already seen. + #[track_caller] pub(crate) fn duplicate_key(&mut self, span: Span, key: Symbol) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key)) } /// An error that should be emitted when a [`MetaItemOrLitParser`] /// was expected *not* to be a literal, but instead a meta item. + #[track_caller] pub(crate) fn expected_not_literal(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNotLiteral) } @@ -1031,6 +1059,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// The `provided_arguments` argument allows distinguishing between "expected an argument here" /// (when zero arguments are provided) and "expect a single argument here" (when two or more /// arguments are provided). + #[track_caller] pub(crate) fn expected_single_argument( &mut self, span: Span, @@ -1045,11 +1074,13 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { self.emit_parse_error(span, reason) } + #[track_caller] pub(crate) fn expected_at_least_one_argument(&mut self, span: Span) -> ErrorGuaranteed { self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument) } /// Produces an error along the lines of `expected one of [foo, meow]` + #[track_caller] pub(crate) fn expected_specific_argument( &mut self, span: Span, @@ -1067,6 +1098,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { /// Produces an error along the lines of `expected one of [foo, meow] as an argument`. /// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument). + #[track_caller] pub(crate) fn expected_specific_argument_and_list( &mut self, span: Span, @@ -1083,6 +1115,7 @@ impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> { } /// produces an error along the lines of `expected one of ["foo", "meow"]` + #[track_caller] pub(crate) fn expected_specific_argument_strings( &mut self, span: Span, diff --git a/compiler/rustc_attr_parsing/src/interface.rs b/compiler/rustc_attr_parsing/src/interface.rs index 95412c34be371..4ce284a0a9d5a 100644 --- a/compiler/rustc_attr_parsing/src/interface.rs +++ b/compiler/rustc_attr_parsing/src/interface.rs @@ -304,6 +304,7 @@ impl<'sess> AttributeParser<'sess> { self.sess().dcx() } + #[track_caller] pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed { self.should_emit.emit_err(self.sess.dcx().create_err(diag)) } diff --git a/tests/ui/track-diagnostics/track8.stderr b/tests/ui/track-diagnostics/track8.stderr index 0e1ee1f5a9333..fdc33519e3cf0 100644 --- a/tests/ui/track-diagnostics/track8.stderr +++ b/tests/ui/track-diagnostics/track8.stderr @@ -4,7 +4,7 @@ error[E0539]: malformed `repr` attribute input LL | #[repr] | ^^^^ expected this to be a list | - = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/interface.rs:LL:CC + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/repr.rs:LL:CC = note: for more information, visit warning: unknown diagnostic attribute From add63e4e72e07adee0907ca2affb121fcca3904f Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:25:42 -0700 Subject: [PATCH 1257/1309] yeet old solver coherence --- compiler/rustc_ast_passes/src/feature_gate.rs | 5 +- .../src/coherence/orphan.rs | 2 +- compiler/rustc_interface/src/tests.rs | 16 +- compiler/rustc_middle/src/ty/context.rs | 8 +- compiler/rustc_session/src/config.rs | 29 +-- compiler/rustc_session/src/options.rs | 9 +- compiler/rustc_trait_selection/src/lib.rs | 1 - .../src/traits/coherence.rs | 215 +++++------------- .../src/traits/fulfill.rs | 13 +- .../src/traits/normalize.rs | 12 +- .../src/traits/project.rs | 6 +- .../src/traits/query/normalize.rs | 6 +- .../src/traits/select/candidate_assembly.rs | 6 +- .../src/traits/select/mod.rs | 118 ++-------- 14 files changed, 123 insertions(+), 323 deletions(-) diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 45fa1863e715f..1176d6e1398f0 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -5,6 +5,7 @@ use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; use rustc_feature::{DependentFeature, Features}; use rustc_session::Session; +use rustc_session::config::NextSolverConfig; use rustc_session::diagnostics::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, sym}; @@ -698,7 +699,7 @@ fn check_dependent_features(sess: &Session, features: &Features) { } fn warn_next_solver_and_gce(sess: &Session, features: &Features) { - if !sess.opts.unstable_opts.next_solver.globally { + if sess.opts.unstable_opts.next_solver != NextSolverConfig::Globally { return; } @@ -716,7 +717,7 @@ fn warn_next_solver_and_gce(sess: &Session, features: &Features) { } fn check_features_requiring_new_solver(sess: &Session, features: &Features) { - if sess.opts.unstable_opts.next_solver.globally { + if sess.opts.unstable_opts.next_solver == NextSolverConfig::Globally { return; } diff --git a/compiler/rustc_hir_analysis/src/coherence/orphan.rs b/compiler/rustc_hir_analysis/src/coherence/orphan.rs index 496994096d69b..d2c3a08eb714f 100644 --- a/compiler/rustc_hir_analysis/src/coherence/orphan.rs +++ b/compiler/rustc_hir_analysis/src/coherence/orphan.rs @@ -321,7 +321,7 @@ fn orphan_check<'tcx>( // (1) Instantiate all generic params with fresh inference vars. let infcx = tcx .infer_ctxt() - .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) + .with_next_trait_solver(true) .enable_next_solver_overflow_fcw(false) .build(TypingMode::Coherence); let cause = traits::ObligationCause::dummy(); diff --git a/compiler/rustc_interface/src/tests.rs b/compiler/rustc_interface/src/tests.rs index 2dfb8f04f58f2..34ac92faef88c 100644 --- a/compiler/rustc_interface/src/tests.rs +++ b/compiler/rustc_interface/src/tests.rs @@ -859,7 +859,7 @@ fn test_unstable_options_tracking_hash() { // tidy-alphabetical-end // FIXME(#160895): We don't test this when the next-solver is enabled by default. if option_env!("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY").is_none() { - tracked!(next_solver, NextSolverConfig { coherence: true, globally: true }); + tracked!(next_solver, NextSolverConfig::Globally); } // tidy-alphabetical-start tracked!(no_generate_arange_section, true); @@ -948,7 +948,7 @@ fn test_edition_parsing() { #[test] fn test_assumptions_on_binders_enables_next_solver_globally() { - let globally = NextSolverConfig { coherence: true, globally: true }; + let globally = NextSolverConfig::Globally; let mut early_dcx = EarlyDiagCtxt::new(ErrorOutputType::default()); // `-Zassumptions-on-binders` alone enables the next solver globally. @@ -957,18 +957,6 @@ fn test_assumptions_on_binders_enables_next_solver_globally() { assert!(opts.unstable_opts.assumptions_on_binders); assert_eq!(opts.unstable_opts.next_solver, globally); - // Flag order must not matter when both `-Zassumptions-on-binders` and `-Znext-solver` - // are present. - for args in [ - ["-Zassumptions-on-binders".to_string(), "-Znext-solver=coherence".to_string()], - ["-Znext-solver=coherence".to_string(), "-Zassumptions-on-binders".to_string()], - ] { - let matches = optgroups().parse(&args).unwrap(); - let opts = build_session_options(&mut early_dcx, &matches, false); - assert!(opts.unstable_opts.assumptions_on_binders); - assert_eq!(opts.unstable_opts.next_solver, globally); - } - // `-Zassumptions-on-binders` overrides `-Znext-solver=no` regardless of order, since // the assumptions implementation requires the next solver. This also emits an early // warning (covered by the UI test `next-solver-no-overridden`). diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9062cc3125413..aa7fe0872f20c 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -40,6 +40,7 @@ use rustc_index::IndexVec; use rustc_lint_defs::Lint; use rustc_lint_defs::builtin::UNUSED_FEATURES; use rustc_macros::Diagnostic; +use rustc_session::config::NextSolverConfig; use rustc_session::{IncrCompSession, Session}; use rustc_span::def_id::{CRATE_DEF_ID, DefPathHash, StableCrateId}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, bug, kw, sym}; @@ -2816,11 +2817,8 @@ impl<'tcx> TyCtxt<'tcx> { } pub fn next_trait_solver_globally(self) -> bool { - self.sess.opts.unstable_opts.next_solver.globally && !self.features().generic_const_exprs() - } - - pub fn next_trait_solver_in_coherence(self) -> bool { - self.sess.opts.unstable_opts.next_solver.coherence + self.sess.opts.unstable_opts.next_solver == NextSolverConfig::Globally + && !self.features().generic_const_exprs() } pub fn disable_trait_solver_fast_paths(self) -> bool { diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs index fdfc2aacc79a8..64cfdfd5f85a7 100644 --- a/compiler/rustc_session/src/config.rs +++ b/compiler/rustc_session/src/config.rs @@ -1039,13 +1039,11 @@ impl ExternEntry { } } +/// Where the new trait solver should be enabled only in coherence or everywhere. #[derive(Debug, Copy, Clone, Hash, PartialEq, Eq)] -pub struct NextSolverConfig { - /// Whether the new trait solver should be enabled in coherence. - pub coherence: bool = true, - /// Whether the new trait solver should be enabled everywhere. - /// This is only `true` if `coherence` is also enabled. - pub globally: bool = false, +pub enum NextSolverConfig { + Coherence, + Globally, } // FIXME(#160895): Using -Znext-solver as default on nightly @@ -1053,9 +1051,9 @@ pub struct NextSolverConfig { impl Default for NextSolverConfig { fn default() -> Self { if option_env!("CFG_DEFAULT_NEXT_SOLVER_GLOBALLY").is_some() { - Self { coherence: true, globally: true } + Self::Globally } else { - Self { coherence: true, globally: false } + Self::Coherence } } } @@ -2734,17 +2732,22 @@ pub fn build_session_options( // `-Zassumptions-on-binders` requires the next trait solver globally. Normalize after // parsing so the effective config is independent of flag order and so consumers that - // read `next_solver.globally` directly (e.g. feature-gate checks) see the right value. + // read `next_solver` directly (e.g. feature-gate checks) see the right value. if unstable_opts.assumptions_on_binders { - // `NextSolverConfig::default()` has `coherence: true`; the only way `coherence` is - // false here is an explicit `-Znext-solver=no`. - if !unstable_opts.next_solver.coherence { + // Only warn when the last `-Znext-solver` given has a value that doesn't enable + // the solver globally, so a later `-Znext-solver=globally` overrides an earlier one. + let no_next_solver = matches + .opt_strs("Z") + .iter() + .rfind(|arg| arg.starts_with("next-solver")) + .is_some_and(|arg| *arg == "next-solver=no" || *arg == "next-solver=coherence"); + if no_next_solver { early_dcx.early_warn( "-Zassumptions-on-binders unconditionally enables the next trait solver; \ `-Znext-solver=no` is ignored", ); } - unstable_opts.next_solver = NextSolverConfig { coherence: true, globally: true }; + unstable_opts.next_solver = NextSolverConfig::Globally; } if unstable_opts.staticlib_hide_internal_symbols && !crate_types.contains(&CrateType::StaticLib) diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs index 4c153cbb8c031..9a3e74c28348d 100644 --- a/compiler/rustc_session/src/options.rs +++ b/compiler/rustc_session/src/options.rs @@ -877,7 +877,7 @@ mod desc { pub(crate) const parse_unpretty: &str = "`string` or `string=string`"; pub(crate) const parse_treat_err_as_bug: &str = "either no value or a non-negative number"; pub(crate) const parse_next_solver_config: &str = - "either `globally` (when used without an argument), `coherence` (default) or `no`"; + "either `globally` (when used without an argument), or `coherence` (default)"; pub(crate) const parse_lto: &str = "either a boolean (`yes`, `no`, `on`, `off`, etc), `thin`, `fat`, or omitted"; pub(crate) const parse_linker_plugin_lto: &str = @@ -1795,13 +1795,12 @@ pub mod parse { pub(crate) fn parse_next_solver_config(slot: &mut NextSolverConfig, v: Option<&str>) -> bool { if let Some(config) = v { *slot = match config { - "no" => NextSolverConfig { coherence: false, globally: false }, - "coherence" => NextSolverConfig { coherence: true, globally: false }, - "globally" => NextSolverConfig { coherence: true, globally: true }, + "no" | "coherence" => NextSolverConfig::Coherence, + "globally" => NextSolverConfig::Globally, _ => return false, }; } else { - *slot = NextSolverConfig { coherence: true, globally: true }; + *slot = NextSolverConfig::Globally; } true diff --git a/compiler/rustc_trait_selection/src/lib.rs b/compiler/rustc_trait_selection/src/lib.rs index 9a3948f0ac440..9364d65968dd0 100644 --- a/compiler/rustc_trait_selection/src/lib.rs +++ b/compiler/rustc_trait_selection/src/lib.rs @@ -11,7 +11,6 @@ //! This API is completely unstable and subject to change. // tidy-alphabetical-start -#![cfg_attr(bootstrap, feature(unwrap_infallible))] #![feature(associated_type_defaults)] #![feature(default_field_values)] #![feature(deref_patterns)] diff --git a/compiler/rustc_trait_selection/src/traits/coherence.rs b/compiler/rustc_trait_selection/src/traits/coherence.rs index d3c118b33e8ce..df21f682d7380 100644 --- a/compiler/rustc_trait_selection/src/traits/coherence.rs +++ b/compiler/rustc_trait_selection/src/traits/coherence.rs @@ -33,8 +33,7 @@ use crate::solve::{SolverDelegate, deeply_normalize_for_diagnostics, inspect}; use crate::traits::query::evaluate_obligation::InferCtxtExt; use crate::traits::select::IntercrateAmbiguityCause; use crate::traits::{ - FulfillmentErrorCode, NormalizeExt, Obligation, ObligationCause, PredicateObligation, - SelectionContext, SkipLeakCheck, util, + FulfillmentErrorCode, Obligation, ObligationCause, PredicateObligation, SkipLeakCheck, util, }; /// The "header" of an impl is everything outside the body: a Self type, a trait @@ -79,21 +78,6 @@ pub(crate) fn suggest_increasing_recursion_limit<'tcx>( suggest_new_overflow_limit(tcx, err); } -#[derive(Debug, Clone, Copy)] -enum TrackAmbiguityCauses { - Yes, - No, -} - -impl TrackAmbiguityCauses { - fn is_yes(self) -> bool { - match self { - TrackAmbiguityCauses::Yes => true, - TrackAmbiguityCauses::No => false, - } - } -} - /// If there are types that satisfy both impls, returns `Some` /// with a suitably-freshened `ImplHeader` with those types /// instantiated. Otherwise, returns `None`. @@ -157,42 +141,7 @@ fn overlapping_impls( overlap_mode: OverlapMode, is_of_trait: bool, ) -> Option> { - if tcx.next_trait_solver_in_coherence() { - overlap( - tcx, - TrackAmbiguityCauses::Yes, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - ) - } else { - let _overlap_with_bad_diagnostics = overlap( - tcx, - TrackAmbiguityCauses::No, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - )?; - - // In the case where we detect an error, run the check again, but - // this time tracking intercrate ambiguity causes for better - // diagnostics. (These take time and can lead to false errors.) - let overlap = overlap( - tcx, - TrackAmbiguityCauses::Yes, - skip_leak_check, - impl1_def_id, - impl2_def_id, - overlap_mode, - is_of_trait, - ) - .unwrap(); - Some(overlap) - } + overlap(tcx, skip_leak_check, impl1_def_id, impl2_def_id, overlap_mode, is_of_trait) } fn fresh_impl_header<'tcx>( @@ -217,27 +166,11 @@ fn fresh_impl_header<'tcx>( } } -fn fresh_impl_header_normalized<'tcx>( - infcx: &InferCtxt<'tcx>, - param_env: ty::ParamEnv<'tcx>, - impl_def_id: DefId, - is_of_trait: bool, -) -> ImplHeader<'tcx> { - let header = fresh_impl_header(infcx, impl_def_id, is_of_trait); - - let InferOk { value: mut header, obligations } = - infcx.at(&ObligationCause::dummy(), param_env).normalize(Unnormalized::new_wip(header)); - - header.predicates.extend(obligations.into_iter().map(|o| o.predicate)); - header -} - /// Can both impl `a` and impl `b` be satisfied by a common type (including /// where-clauses)? If so, returns an `ImplHeader` that unifies the two impls. #[instrument(level = "debug", skip(tcx))] fn overlap<'tcx>( tcx: TyCtxt<'tcx>, - track_ambiguity_causes: TrackAmbiguityCauses, skip_leak_check: SkipLeakCheck, impl1_def_id: DefId, impl2_def_id: DefId, @@ -260,13 +193,9 @@ fn overlap<'tcx>( let infcx = tcx .infer_ctxt() .skip_leak_check(skip_leak_check.is_yes()) - .with_next_trait_solver(tcx.next_trait_solver_in_coherence()) + .with_next_trait_solver(true) .enable_next_solver_overflow_fcw(false) .build(TypingMode::Coherence); - let selcx = &mut SelectionContext::new(&infcx); - if track_ambiguity_causes.is_yes() { - selcx.enable_tracking_intercrate_ambiguity_causes(); - } // For the purposes of this check, we don't bring any placeholder // types into scope; instead, we replace the generic types with @@ -274,21 +203,12 @@ fn overlap<'tcx>( // empty environment. let param_env = ty::ParamEnv::empty(); - let impl1_header = if tcx.next_trait_solver_in_coherence() { - fresh_impl_header(selcx.infcx, impl1_def_id, is_of_trait) - } else { - fresh_impl_header_normalized(selcx.infcx, param_env, impl1_def_id, is_of_trait) - }; - let impl2_header = if tcx.next_trait_solver_in_coherence() { - fresh_impl_header(selcx.infcx, impl2_def_id, is_of_trait) - } else { - fresh_impl_header_normalized(selcx.infcx, param_env, impl2_def_id, is_of_trait) - }; + let impl1_header = fresh_impl_header(&infcx, impl1_def_id, is_of_trait); + let impl2_header = fresh_impl_header(&infcx, impl2_def_id, is_of_trait); // Equate the headers to find their intersection (the general type, with infer vars, // that may apply both impls). - let mut obligations = - equate_impl_headers(selcx.infcx, param_env, &impl1_header, &impl2_header)?; + let mut obligations = equate_impl_headers(&infcx, param_env, &impl1_header, &impl2_header)?; debug!("overlap: unification check succeeded"); obligations.extend( @@ -299,7 +219,7 @@ fn overlap<'tcx>( let mut overflowing_predicates = Vec::new(); if overlap_mode.use_implicit_negative() { - match impl_intersection_has_impossible_obligation(selcx, &obligations) { + match impl_intersection_has_impossible_obligation(&infcx, &obligations) { IntersectionHasImpossibleObligations::Yes => return None, IntersectionHasImpossibleObligations::No { overflowing_predicates: p } => { overflowing_predicates = p @@ -316,10 +236,8 @@ fn overlap<'tcx>( let intercrate_ambiguity_causes = if !overlap_mode.use_implicit_negative() { Default::default() - } else if infcx.next_trait_solver() { - compute_intercrate_ambiguity_causes(&infcx, &obligations) } else { - selcx.take_intercrate_ambiguity_causes() + compute_intercrate_ambiguity_causes(&infcx, &obligations) }; debug!("overlap: intercrate_ambiguity_causes={:#?}", intercrate_ambiguity_causes); @@ -335,9 +253,7 @@ fn overlap<'tcx>( let mut impl_header = infcx.deeply_resolve_ignoring_regions(impl1_header); // Deeply normalize the impl header for diagnostics, ignoring any errors if this fails. - if infcx.next_trait_solver() { - impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header); - } + impl_header = deeply_normalize_for_diagnostics(&infcx, param_env, impl_header); Some(OverlapResult { impl_header, @@ -375,7 +291,7 @@ fn equate_impl_headers<'tcx>( enum IntersectionHasImpossibleObligations<'tcx> { Yes, No { - /// With `-Znext-solver=coherence`, some obligations may + /// With the next solver, some obligations may /// fail if only the user increased the recursion limit. /// /// We return those obligations here and mention them in the @@ -402,78 +318,53 @@ enum IntersectionHasImpossibleObligations<'tcx> { /// of the two impls above to be empty. /// /// Importantly, this works even if there isn't a `impl !Error for MyLocalType`. -#[instrument(level = "debug", skip(selcx), ret)] -fn impl_intersection_has_impossible_obligation<'a, 'cx, 'tcx>( - selcx: &mut SelectionContext<'cx, 'tcx>, +#[instrument(level = "debug", skip(infcx), ret)] +fn impl_intersection_has_impossible_obligation<'a, 'tcx>( + infcx: &InferCtxt<'tcx>, obligations: &'a [PredicateObligation<'tcx>], ) -> IntersectionHasImpossibleObligations<'tcx> { - let infcx = selcx.infcx; - - if infcx.next_trait_solver() { - // A fast path optimization, try evaluating all goals with - // a very low recursion depth and bail if any of them don't - // hold. - if !obligations.iter().all(|o| { - <&SolverDelegate<'tcx>>::from(infcx) - .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) - }) { - return IntersectionHasImpossibleObligations::Yes; - } - - let ocx = ObligationCtxt::new(infcx); - ocx.register_obligations(obligations.iter().cloned()); - let hard_errors = ocx.try_evaluate_obligations(); - if let TraitErrors::HasErrors(hard_errors) = hard_errors { - assert!( - hard_errors.iter().all(|e| e.is_true_error()), - "should not have detected ambiguity during first pass" - ); - return IntersectionHasImpossibleObligations::Yes; - } + // A fast path optimization, try evaluating all goals with + // a very low recursion depth and bail if any of them don't + // hold. + if !obligations.iter().all(|o| { + <&SolverDelegate<'tcx>>::from(infcx) + .root_goal_may_hold_with_depth(8, Goal::new(infcx.tcx, o.param_env, o.predicate)) + }) { + return IntersectionHasImpossibleObligations::Yes; + } - // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer - // `FulfillmentError`. This is so that we can detect overflowing obligations - // without needing to run the `BestObligation` visitor on true errors. - let ambiguities = ocx.into_pending_obligations(); - let ocx = ObligationCtxt::new_with_diagnostics(infcx); - ocx.register_obligations(ambiguities); - let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity(); - // We only care about the obligations that are *definitely* true errors. - // Ambiguities do not prove the disjointness of two impls. - let (errors, ambiguities): (Vec<_>, Vec<_>) = - errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); - assert!(errors.is_empty(), "should not have ambiguities during second pass"); - - IntersectionHasImpossibleObligations::No { - overflowing_predicates: ambiguities - .into_iter() - .filter(|error| { - matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) - }) - .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)) - .collect(), - } - } else { - for obligation in obligations { - // We use `evaluate_root_obligation` to correctly track intercrate - // ambiguity clauses. - let evaluation_result = selcx.evaluate_root_obligation(obligation); - - match evaluation_result { - Ok(result) => { - if !result.may_apply() { - return IntersectionHasImpossibleObligations::Yes; - } - } - // If overflow occurs, we need to conservatively treat the goal as possibly holding, - // since there can be instantiations of this goal that don't overflow and result in - // success. While this isn't much of a problem in the old solver, since we treat overflow - // fatally, this still can be encountered: . - Err(_overflow) => {} - } - } + let ocx = ObligationCtxt::new(infcx); + ocx.register_obligations(obligations.iter().cloned()); + let hard_errors = ocx.try_evaluate_obligations(); + if let TraitErrors::HasErrors(hard_errors) = hard_errors { + assert!( + hard_errors.iter().all(|e| e.is_true_error()), + "should not have detected ambiguity during first pass" + ); + return IntersectionHasImpossibleObligations::Yes; + } - IntersectionHasImpossibleObligations::No { overflowing_predicates: Vec::new() } + // Make a new `ObligationCtxt` and re-prove the ambiguities with a richer + // `FulfillmentError`. This is so that we can detect overflowing obligations + // without needing to run the `BestObligation` visitor on true errors. + let ambiguities = ocx.into_pending_obligations(); + let ocx = ObligationCtxt::new_with_diagnostics(infcx); + ocx.register_obligations(ambiguities); + let errors_and_ambiguities = ocx.evaluate_obligations_error_on_ambiguity(); + // We only care about the obligations that are *definitely* true errors. + // Ambiguities do not prove the disjointness of two impls. + let (errors, ambiguities): (Vec<_>, Vec<_>) = + errors_and_ambiguities.into_iter().partition(|error| error.is_true_error()); + assert!(errors.is_empty(), "should not have ambiguities during second pass"); + + IntersectionHasImpossibleObligations::No { + overflowing_predicates: ambiguities + .into_iter() + .filter(|error| { + matches!(error.code, FulfillmentErrorCode::Ambiguity { overflow: Some(true) }) + }) + .map(|e| infcx.deeply_resolve_ignoring_regions(e.obligation.predicate)) + .collect(), } } diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index aae323ae1671f..83f1fcd756981 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -176,12 +176,14 @@ where TypingMode::Typeck { defining_opaque_types_and_generators } => { defining_opaque_types_and_generators } - TypingMode::Coherence - | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } + TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } | TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => return Default::default(), + TypingMode::Coherence => { + unreachable!("old solver coherence") + } }; if stalled_coroutines.is_empty() { @@ -872,8 +874,9 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { trait_obligation: PolyTraitObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { + debug_assert!(!self.selcx.typing_mode().is_coherence(), "old solver coherence"); let infcx = self.selcx.infcx; - if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() { + if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { @@ -925,9 +928,11 @@ impl<'a, 'tcx> FulfillProcessor<'a, 'tcx> { project_obligation: PolyProjectionObligation<'tcx>, stalled_on: &mut Vec, ) -> ProcessResult, FulfillmentErrorCode<'tcx>> { + debug_assert!(!self.selcx.typing_mode().is_coherence(), "old solver coherence"); + let tcx = self.selcx.tcx(); let infcx = self.selcx.infcx; - if obligation.predicate.is_global() && !self.selcx.typing_mode().is_coherence() { + if obligation.predicate.is_global() { // no type variables present, can use evaluation for better caching. // FIXME: consider caching errors too. if infcx.predicate_must_hold_considering_regions(obligation) { diff --git a/compiler/rustc_trait_selection/src/traits/normalize.rs b/compiler/rustc_trait_selection/src/traits/normalize.rs index 5a66fafd57361..63f7c6dfc94fc 100644 --- a/compiler/rustc_trait_selection/src/traits/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/normalize.rs @@ -139,11 +139,13 @@ pub(super) fn needs_normalization<'tcx, T: TypeVisitable>>( // so we can ignore those. match infcx.typing_mode_raw().assert_not_erased() { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => flags.remove(ty::TypeFlags::HAS_TY_OPAQUE), TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => {} + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } value.has_type_flags(flags) @@ -426,8 +428,7 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.selcx.typing_mode() { // FIXME(#132279): We likely want to reveal opaques during post borrowck analysis - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.super_fold_with(self), TypingMode::Reflection | TypingMode::PostAnalysis | TypingMode::Codegen => { @@ -449,6 +450,9 @@ impl<'a, 'b, 'tcx> TypeFolder> for AssocTypeNormalizer<'a, 'b, 'tcx self.depth -= 1; folded_ty } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs index 6f7c46089632f..6cea4a9300824 100644 --- a/compiler/rustc_trait_selection/src/traits/project.rs +++ b/compiler/rustc_trait_selection/src/traits/project.rs @@ -1034,8 +1034,7 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( // transmute checking and polymorphic MIR optimizations could // get a result which isn't correct for all monomorphizations. match selcx.typing_mode() { - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::Reflection | TypingMode::PostBorrowck { .. } => { @@ -1053,6 +1052,9 @@ fn assemble_candidates_from_impls<'cx, 'tcx>( selcx.infcx.deeply_resolve_ignoring_regions(trait_ref); !poly_trait_ref.still_further_specializable() } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } } diff --git a/compiler/rustc_trait_selection/src/traits/query/normalize.rs b/compiler/rustc_trait_selection/src/traits/query/normalize.rs index 782697782f94c..b4dffab26d1e4 100644 --- a/compiler/rustc_trait_selection/src/traits/query/normalize.rs +++ b/compiler/rustc_trait_selection/src/traits/query/normalize.rs @@ -231,8 +231,7 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { ty::Opaque { def_id } => { // Only normalize `impl Trait` outside of type inference, usually in codegen. match self.infcx.typing_mode_raw().assert_not_erased() { - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } => ty.try_super_fold_with(self)?, @@ -268,6 +267,9 @@ impl<'a, 'tcx> FallibleTypeFolder> for QueryNormalizer<'a, 'tcx> { self.anon_depth -= 1; folded_ty? } + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 9ebfb4d5ecda0..7228c55b404b4 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -845,6 +845,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } ty::Alias(_, ty::AliasTy { kind: ty::Opaque { def_id }, .. }) => { + debug_assert!(!self.typing_mode().is_coherence(), "old solver coherence"); + if candidates.vec.iter().any(|c| matches!(c, ProjectionCandidate { .. })) { // We do not generate an auto impl candidate for `impl Trait`s which already // reference our auto trait. @@ -855,10 +857,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // // Note that this is only sound as projection candidates of opaque types // are always applicable for auto traits. - } else if self.typing_mode().is_coherence() { - // We do not emit auto trait candidates for opaque types in coherence. - // Doing so can result in weird dependency cycles. - candidates.ambiguous = true; } else if self.infcx.can_define_opaque_ty(def_id) { // We do not emit auto trait candidates for opaque types in their defining scope, as // we need to know the hidden type first, which we can't reliably know within the defining diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs index 4846d75339cd6..05b4ba6a7180c 100644 --- a/compiler/rustc_trait_selection/src/traits/select/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs @@ -35,7 +35,6 @@ use tracing::{debug, instrument, trace}; use self::EvaluationResult::*; use self::SelectionCandidate::*; -use super::coherence::{self, Conflict}; use super::project::ProjectionTermObligation; use super::util::closure_trait_ref_and_return_type; use super::{ @@ -106,14 +105,6 @@ pub struct SelectionContext<'cx, 'tcx> { /// require themselves. freshener: TypeFreshener<'cx, 'tcx>, - /// If `intercrate` is set, we remember predicates which were - /// considered ambiguous because of impls potentially added in other crates. - /// This is used in coherence to give improved diagnostics. - /// We don't do his until we detect a coherence error because it can - /// lead to false overflow results (#47139) and because always - /// computing it may negatively impact performance. - intercrate_ambiguity_causes: Option>>, - /// The mode that trait queries run in, which informs our error handling /// policy. In essence, canonicalized queries need their errors propagated /// rather than immediately reported because we do not have accurate spans. @@ -191,7 +182,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { SelectionContext { infcx, freshener: TypeFreshener::new(infcx), - intercrate_ambiguity_causes: None, query_mode: TraitQueryMode::Standard, } } @@ -208,27 +198,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { SelectionContext { query_mode, ..SelectionContext::new(infcx) } } - /// Enables tracking of intercrate ambiguity causes. See - /// the documentation of [`Self::intercrate_ambiguity_causes`] for more. - pub fn enable_tracking_intercrate_ambiguity_causes(&mut self) { - assert!(self.typing_mode().is_coherence()); - assert!(self.intercrate_ambiguity_causes.is_none()); - - self.intercrate_ambiguity_causes = Some(FxIndexSet::default()); - debug!("selcx: enable_tracking_intercrate_ambiguity_causes"); - } - - /// Gets the intercrate ambiguity causes collected since tracking - /// was enabled and disables tracking at the same time. If - /// tracking is not enabled, just returns an empty vector. - pub fn take_intercrate_ambiguity_causes( - &mut self, - ) -> FxIndexSet> { - assert!(self.typing_mode().is_coherence()); - - self.intercrate_ambiguity_causes.take().unwrap_or_default() - } - pub fn tcx(&self) -> TyCtxt<'tcx> { self.infcx.tcx } @@ -363,42 +332,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { &mut self, stack: &TraitObligationStack<'o, 'tcx>, ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> { - if let Err(conflict) = self.is_knowable(stack) { - debug!("coherence stage: not knowable"); - if self.intercrate_ambiguity_causes.is_some() { - debug!("evaluate_stack: intercrate_ambiguity_causes is some"); - // Heuristics: show the diagnostics when there are no candidates in crate. - if let Ok(candidate_set) = self.assemble_candidates(stack) { - let mut no_candidates_apply = true; - - for c in candidate_set.vec.iter() { - if self.evaluate_candidate(stack, c)?.may_apply() { - no_candidates_apply = false; - break; - } - } - - if !candidate_set.ambiguous && no_candidates_apply { - let trait_ref = self.infcx.deeply_resolve_ignoring_regions( - stack.obligation.predicate.skip_binder().trait_ref, - ); - if !trait_ref.references_error() { - let self_ty = trait_ref.self_ty(); - let self_ty = self_ty.has_concrete_skeleton().then(|| self_ty); - let cause = if let Conflict::Upstream = conflict { - IntercrateAmbiguityCause::UpstreamCrateUpdate { trait_ref, self_ty } - } else { - IntercrateAmbiguityCause::DownstreamCrate { trait_ref, self_ty } - }; - debug!(?cause, "evaluate_stack: pushing cause"); - self.intercrate_ambiguity_causes.as_mut().unwrap().insert(cause); - } - } - } - } - return Ok(None); - } - let candidate_set = self.assemble_candidates(stack)?; if candidate_set.ambiguous { @@ -1000,8 +933,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { previous_stack: TraitObligationStackList<'o, 'tcx>, mut obligation: PolyTraitObligation<'tcx>, ) -> Result { - if !self.typing_mode().is_coherence() - && obligation.is_global() + debug_assert!(!self.typing_mode().is_coherence(), "old solver coherence"); + + if obligation.is_global() && obligation.param_env.caller_bounds().all(|bound| bound.has_param()) { // If a param env has no global bounds, global obligations do not @@ -1432,30 +1366,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { candidates } - fn is_knowable<'o>(&mut self, stack: &TraitObligationStack<'o, 'tcx>) -> Result<(), Conflict> { - let obligation = &stack.obligation; - match self.typing_mode() { - TypingMode::Coherence => {} - TypingMode::Typeck { .. } - | TypingMode::PostTypeckUntilBorrowck { .. } - | TypingMode::Reflection - | TypingMode::PostBorrowck { .. } - | TypingMode::PostAnalysis - | TypingMode::Codegen => return Ok(()), - } - - debug!("is_knowable()"); - - let predicate = self.infcx.deeply_resolve_ignoring_regions(obligation.predicate); - - // Okay to skip binder because of the nature of the - // trait-ref-is-knowable check, which does not care about - // bound regions. - let trait_ref = predicate.skip_binder().trait_ref; - - coherence::trait_ref_is_knowable(self.infcx, trait_ref, |ty| Ok::<_, !>(ty)).into_ok() - } - /// Returns `true` if the global caches can be used. fn can_use_global_caches( &self, @@ -1470,13 +1380,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { } match self.typing_mode() { - // Avoid using the global cache during coherence and just rely - // on the local cache. It is really just a simplification to - // avoid us having to fear that coherence results "pollute" - // the master cache. Since coherence executes pretty quickly, - // it's not worth going to more trouble to increase the - // hit-rate, I don't think. - TypingMode::Coherence => false, // Avoid using the global cache when we're defining opaque types // as their hidden type may impact the result of candidate selection. // @@ -1502,6 +1405,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { // FIXME(#132279): This is still incorrect as we treat opaque types // and default associated items differently between these two modes. TypingMode::PostAnalysis | TypingMode::Codegen => true, + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } @@ -2528,14 +2434,16 @@ impl<'tcx> SelectionContext<'_, 'tcx> { return Err(()); } - TypingMode::Coherence - | TypingMode::Typeck { .. } + TypingMode::Typeck { .. } | TypingMode::PostTypeckUntilBorrowck { .. } | TypingMode::PostBorrowck { .. } | TypingMode::Codegen | TypingMode::ErasedNotCoherence(_) | TypingMode::Reflection | TypingMode::PostAnalysis => {} + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } Ok(Normalized { value: impl_args, obligations: nested_obligations }) @@ -2876,12 +2784,14 @@ impl<'tcx> SelectionContext<'_, 'tcx> { TypingMode::Typeck { defining_opaque_types_and_generators: stalled_generators } => { def_id.as_local().is_some_and(|def_id| stalled_generators.contains(&def_id)) } - TypingMode::Coherence - | TypingMode::PostAnalysis + TypingMode::PostAnalysis | TypingMode::Reflection | TypingMode::Codegen | TypingMode::PostTypeckUntilBorrowck { defining_opaque_types: _ } | TypingMode::PostBorrowck { defined_opaque_types: _ } => false, + TypingMode::Coherence => { + unreachable!("old solver coherence") + } } } } From 3a7efa2543b24daa3fb0f4d0ab232b3b032e12a1 Mon Sep 17 00:00:00 2001 From: sjwang05 <63834813+sjwang05@users.noreply.github.com> Date: Fri, 21 Aug 2026 15:28:41 -0700 Subject: [PATCH 1258/1309] bless tests --- .../assumptions_on_binders/alias_outlives.rs | 2 +- ...higher_ranked_alias_outlives_assumption.rs | 2 +- .../nested-gat-outlives-issue-161067.rs | 2 +- .../placeholder-assumptions-issue-157840.rs | 2 +- .../reflexive-outlives-in-root.rs | 2 +- .../resolved-region-var-max-universe.rs | 2 +- .../same-universe-placeholder-outlives.rs | 2 +- .../test-infra-fails-properly.rs | 2 +- .../test-infra-works.rs | 2 +- .../type-outlives-assumptions.rs | 2 +- .../type_relation_binders_inside_solver-1.rs | 2 +- .../type_relation_binders_inside_solver-2.rs | 2 +- .../type_relation_binders_inside_solver-3.rs | 2 +- .../generic_const_exprs/error_in_ty.rs | 2 -- .../generic_const_exprs/error_in_ty.stderr | 16 +++++----- tests/ui/error-codes/E0476.old.stderr | 31 ------------------- tests/ui/error-codes/E0476.rs | 3 -- .../{E0476.next.stderr => E0476.stderr} | 8 ++--- ...-124857-combine-effect-const-infer-vars.rs | 2 -- ...857-combine-effect-const-infer-vars.stderr | 2 +- .../traits/issue-90662-projection-caching.rs | 3 -- .../ambiguity-causes-canonical-state-ice-1.rs | 1 - .../ambiguity-causes-canonical-state-ice-2.rs | 2 -- ...iguity-causes-canonical-state-ice-2.stderr | 2 +- .../ambiguity-causes-visitor-hang.rs | 2 -- .../ambiguity-causes-visitor-hang.stderr | 2 +- .../coherence/coherence-fulfill-overflow.rs | 2 -- .../coherence-fulfill-overflow.stderr | 2 +- ...e-unknowable-does-not-eagerly-normalize.rs | 1 - .../dont-ice-on-assoc-projection.rs | 2 -- .../dont-ice-on-assoc-projection.stderr | 4 +-- .../normalize/indirectly-constrained-term.rs | 3 -- .../coherence-alias-hang-with-region.rs | 1 - ...cursion-limit-normalizes-to-constraints.rs | 1 - 34 files changed, 31 insertions(+), 87 deletions(-) delete mode 100644 tests/ui/error-codes/E0476.old.stderr rename tests/ui/error-codes/{E0476.next.stderr => E0476.stderr} (92%) diff --git a/tests/ui/assumptions_on_binders/alias_outlives.rs b/tests/ui/assumptions_on_binders/alias_outlives.rs index 0c2ed6585cf45..7dd14da4fd773 100644 --- a/tests/ui/assumptions_on_binders/alias_outlives.rs +++ b/tests/ui/assumptions_on_binders/alias_outlives.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // test that a `::Assoc: '!a_u1` constraint is considered to be satisfied // if there's a `T::Assoc: 'static` assumption in the root universe and if not that it is diff --git a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs index 2f0f2ca8aab85..1d889b8c64362 100644 --- a/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs +++ b/tests/ui/assumptions_on_binders/implied_higher_ranked_alias_outlives_assumption.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally //@ check-pass #![feature(generic_const_items)] diff --git a/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs b/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs index 937b17e5ec872..4e72f328f73e7 100644 --- a/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs +++ b/tests/ui/assumptions_on_binders/nested-gat-outlives-issue-161067.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally //@ needs-rustc-debug-assertions // Regression test for #161067. A nested non-rigid alias must be normalized diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs index 8b0b92b8a7842..b3bc4d6fae25f 100644 --- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs +++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally trait Trait {} diff --git a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs index 641ac3951d76a..fcd436c7df3ed 100644 --- a/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs +++ b/tests/ui/assumptions_on_binders/reflexive-outlives-in-root.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs index ef1a5ca74c546..4c35de2be8759 100644 --- a/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs +++ b/tests/ui/assumptions_on_binders/resolved-region-var-max-universe.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // Regression test for an ICE in the `MaxUniverse` region visitor. When computing // the max universe of a region constraint, a `ReVar` term could already have been diff --git a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs index 6d292416cd4cf..b748dffe34981 100644 --- a/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs +++ b/tests/ui/assumptions_on_binders/same-universe-placeholder-outlives.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs index 97629627ad556..042deefcbb6e5 100644 --- a/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs +++ b/tests/ui/assumptions_on_binders/test-infra-fails-properly.rs @@ -1,4 +1,4 @@ -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/test-infra-works.rs b/tests/ui/assumptions_on_binders/test-infra-works.rs index d8d64d1aac255..b36e16a545bb3 100644 --- a/tests/ui/assumptions_on_binders/test-infra-works.rs +++ b/tests/ui/assumptions_on_binders/test-infra-works.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![feature(test_binder_constraints, non_lifetime_binders)] #![expect(incomplete_features)] diff --git a/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs b/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs index bc3b3a7f2c250..c78231d8ca103 100644 --- a/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs +++ b/tests/ui/assumptions_on_binders/type-outlives-assumptions.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally // Regression test for rust-lang/project-assumptions-on-binders#19, based on the `syn` failure. // The receiver gives us an implied `I: 'b` bound and `'b: 'a` lets that satisfy the object diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs index fe5753c3c9970..212446a179f00 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-1.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs index 78769282a3f4e..0a484d17da542 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-2.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs index c1d4d0ed1c79f..6cc175fbce36d 100644 --- a/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs +++ b/tests/ui/assumptions_on_binders/type_relation_binders_inside_solver-3.rs @@ -1,5 +1,5 @@ //@ check-pass -//@ compile-flags: -Zassumptions-on-binders +//@ compile-flags: -Zassumptions-on-binders -Znext-solver=globally #![crate_type = "lib"] diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs index 29ad935c0149c..9449153060db5 100644 --- a/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(generic_const_exprs)] #![allow(incomplete_features)] diff --git a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr index dea81894463b3..21ca0f6e04d97 100644 --- a/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr +++ b/tests/ui/const-generics/generic_const_exprs/error_in_ty.stderr @@ -1,11 +1,11 @@ error[E0425]: cannot find value `x` in this scope - --> $DIR/error_in_ty.rs:6:31 + --> $DIR/error_in_ty.rs:4:31 | LL | pub struct A {} | ^ not found in this scope | note: similarly named const parameter `z` defined here - --> $DIR/error_in_ty.rs:6:20 + --> $DIR/error_in_ty.rs:4:20 | LL | pub struct A {} | ^ @@ -16,7 +16,7 @@ LL + pub struct A {} | error: `[usize; x]` is forbidden as the type of a const generic parameter - --> $DIR/error_in_ty.rs:6:23 + --> $DIR/error_in_ty.rs:4:23 | LL | pub struct A {} | ^^^^^^^^^^ @@ -28,31 +28,31 @@ LL + #![feature(min_adt_const_params)] | error[E0308]: mismatched types - --> $DIR/error_in_ty.rs:10:8 + --> $DIR/error_in_ty.rs:8:8 | LL | impl A<2> { | ^ expected `[usize; x]`, found integer | note: expected because of the type of the const parameter - --> $DIR/error_in_ty.rs:6:14 + --> $DIR/error_in_ty.rs:4:14 | LL | pub struct A {} | ^^^^^^^^^^^^^^^^^^^ error[E0308]: mismatched types - --> $DIR/error_in_ty.rs:16:8 + --> $DIR/error_in_ty.rs:14:8 | LL | impl A<2> { | ^ expected `[usize; x]`, found integer | note: expected because of the type of the const parameter - --> $DIR/error_in_ty.rs:6:14 + --> $DIR/error_in_ty.rs:4:14 | LL | pub struct A {} | ^^^^^^^^^^^^^^^^^^^ error[E0592]: duplicate definitions with name `B` - --> $DIR/error_in_ty.rs:12:5 + --> $DIR/error_in_ty.rs:10:5 | LL | pub const fn B() {} | ^^^^^^^^^^^^^^^^ duplicate definitions for `B` diff --git a/tests/ui/error-codes/E0476.old.stderr b/tests/ui/error-codes/E0476.old.stderr deleted file mode 100644 index 8b2dcbcf54462..0000000000000 --- a/tests/ui/error-codes/E0476.old.stderr +++ /dev/null @@ -1,31 +0,0 @@ -error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:12:1 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | - = note: conflicting implementation in crate `core`: - - impl<'a, 'b, T, U> CoerceUnsized<&'a U> for &'b T - where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; - -error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:12:1 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:12:6 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^ -note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:12:10 - | -LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} - | ^^ - -error: aborting due to 2 previous errors - -Some errors have detailed explanations: E0119, E0476. -For more information about an error, try `rustc --explain E0119`. diff --git a/tests/ui/error-codes/E0476.rs b/tests/ui/error-codes/E0476.rs index 38854f0768d80..d5e4b8d237274 100644 --- a/tests/ui/error-codes/E0476.rs +++ b/tests/ui/error-codes/E0476.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver=coherence #![feature(coerce_unsized)] #![feature(unsize)] diff --git a/tests/ui/error-codes/E0476.next.stderr b/tests/ui/error-codes/E0476.stderr similarity index 92% rename from tests/ui/error-codes/E0476.next.stderr rename to tests/ui/error-codes/E0476.stderr index 8b2dcbcf54462..0378ac6e8ec91 100644 --- a/tests/ui/error-codes/E0476.next.stderr +++ b/tests/ui/error-codes/E0476.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `CoerceUnsized<&Wrapper<_>>` for type `&Wrapper<_>` - --> $DIR/E0476.rs:12:1 + --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -9,18 +9,18 @@ LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S where 'b: 'a, T: Unsize, T: ?Sized, U: ?Sized; error[E0476]: lifetime of the source pointer does not outlive lifetime bound of the object type - --> $DIR/E0476.rs:12:1 + --> $DIR/E0476.rs:9:1 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: object type is valid for the lifetime `'a` as defined here - --> $DIR/E0476.rs:12:6 + --> $DIR/E0476.rs:9:6 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ note: source pointer is only valid for the lifetime `'b` as defined here - --> $DIR/E0476.rs:12:10 + --> $DIR/E0476.rs:9:10 | LL | impl<'a, 'b, T, S> CoerceUnsized<&'a Wrapper> for &'b Wrapper where S: Unsize {} | ^^ diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs index ba503be2aaff7..39d1840caf41e 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(const_trait_impl)] const trait Foo {} diff --git a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr index 97fdb4b287e8f..76520d1f4d89a 100644 --- a/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr +++ b/tests/ui/traits/const-traits/ice-124857-combine-effect-const-infer-vars.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Foo` for type `i32` - --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:9:1 + --> $DIR/ice-124857-combine-effect-const-infer-vars.rs:7:1 | LL | const impl Foo for i32 {} | ---------------------- first implementation here diff --git a/tests/ui/traits/issue-90662-projection-caching.rs b/tests/ui/traits/issue-90662-projection-caching.rs index 0084737b008d5..ba3b6e4e43b98 100644 --- a/tests/ui/traits/issue-90662-projection-caching.rs +++ b/tests/ui/traits/issue-90662-projection-caching.rs @@ -1,6 +1,3 @@ -//@ revisions: old next -//@ ignore-compare-mode-next-solver (explicit revisions) -//@[next] compile-flags: -Znext-solver=coherence //@ check-pass // Regression test for issue #90662 diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs index 151c3b226c114..48b1a442bf41d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-1.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass // A regression test for #124791. Computing ambiguity causes diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs index b472499cb0bf7..28df3a39ddddf 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - // A regression test for #124791. Computing ambiguity causes // for the overlap of the `ToString` impls caused an ICE. #![crate_type = "lib"] diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr index 469f7a909b141..6200046baa65d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-canonical-state-ice-2.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `str` - --> $DIR/ambiguity-causes-canonical-state-ice-2.rs:18:1 + --> $DIR/ambiguity-causes-canonical-state-ice-2.rs:16:1 | LL | impl + ?Sized> Overlap for T {} | --------------------------------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs index 54854b1b8a522..190531bc9201d 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.rs @@ -4,8 +4,6 @@ // takes multiple minutes when doing so and less than a second // otherwise. -//@ compile-flags: -Znext-solver=coherence - trait RecursiveSuper: Super< A0 = Self::Assoc, diff --git a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr index 3731dc5b74ec0..467981efe2c99 100644 --- a/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr +++ b/tests/ui/traits/next-solver/coherence/ambiguity-causes-visitor-hang.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Overlap` for type `Box<_>` - --> $DIR/ambiguity-causes-visitor-hang.rs:53:1 + --> $DIR/ambiguity-causes-visitor-hang.rs:51:1 | LL | impl Overlap for T {} | ------------------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs index 3fd22c7dbf0c1..551fe619329ff 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - #![feature(rustc_attrs)] #![rustc_no_implicit_bounds] #![recursion_limit = "10"] diff --git a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr index a93fbc2404dad..8e293950f0adb 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr +++ b/tests/ui/traits/next-solver/coherence/coherence-fulfill-overflow.stderr @@ -1,5 +1,5 @@ error[E0119]: conflicting implementations of trait `Trait` for type `W>>>>>>>>>>>>>>>>>>>>>>` - --> $DIR/coherence-fulfill-overflow.rs:14:1 + --> $DIR/coherence-fulfill-overflow.rs:12:1 | LL | impl Trait for W {} | ---------------------------- first implementation here diff --git a/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs index 13cdcc7d93e58..95916365a73f2 100644 --- a/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs +++ b/tests/ui/traits/next-solver/coherence/coherence-unknowable-does-not-eagerly-normalize.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass //@ aux-build:coherence-unknowable-does-not-eagerly-normalize-dep.rs // diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs index cbe489a0430a8..6ad7893e32f1e 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs +++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.rs @@ -1,5 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence - // Makes sure we don't ICE on associated const projection when the feature gate // is not enabled, since we should avoid encountering ICEs on stable if possible. diff --git a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr index e8c1f597e0cd8..4d75a2ef0af99 100644 --- a/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr +++ b/tests/ui/traits/next-solver/dont-ice-on-assoc-projection.stderr @@ -1,5 +1,5 @@ error[E0658]: associated const equality is incomplete - --> $DIR/dont-ice-on-assoc-projection.rs:15:32 + --> $DIR/dont-ice-on-assoc-projection.rs:13:32 | LL | impl Foo for T where T: Bar {} | ^^^^^^^^^ @@ -9,7 +9,7 @@ LL | impl Foo for T where T: Bar {} = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date error[E0119]: conflicting implementations of trait `Foo` for type `()` - --> $DIR/dont-ice-on-assoc-projection.rs:15:1 + --> $DIR/dont-ice-on-assoc-projection.rs:13:1 | LL | impl Foo for () {} | --------------- first implementation here diff --git a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs index 696d567db86d9..7a555b40bf6dd 100644 --- a/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs +++ b/tests/ui/traits/next-solver/normalize/indirectly-constrained-term.rs @@ -1,6 +1,3 @@ -//@ revisions: current next -//@[next] compile-flags: -Znext-solver=coherence -//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass // A regression test for `paperclip-core`. This previously failed to compile diff --git a/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs b/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs index 1df895d732a40..0ccb6f22cf965 100644 --- a/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs +++ b/tests/ui/traits/next-solver/overflow/coherence-alias-hang-with-region.rs @@ -1,6 +1,5 @@ //@ check-pass //@ revisions: ai ia ii -//@ compile-flags: -Znext-solver=coherence // Regression test for nalgebra hang . diff --git a/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs index e5a57a44d4980..f084027acfe68 100644 --- a/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs +++ b/tests/ui/traits/next-solver/overflow/recursion-limit-normalizes-to-constraints.rs @@ -1,4 +1,3 @@ -//@ compile-flags: -Znext-solver=coherence //@ check-pass #![feature(rustc_attrs)] #![rustc_no_implicit_bounds] From c3bee7bbb1275c3eb6f085fd8f7b962338b25a98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Sun, 4 Oct 2026 13:34:20 +0200 Subject: [PATCH 1259/1309] Pass `-Zforce-unstable-if-unmarked` when building cg_gcc's minitests --- compiler/rustc_codegen_gcc/build_system/src/test.rs | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/compiler/rustc_codegen_gcc/build_system/src/test.rs b/compiler/rustc_codegen_gcc/build_system/src/test.rs index a55c2dcf83ddc..98111bb44b4f6 100644 --- a/compiler/rustc_codegen_gcc/build_system/src/test.rs +++ b/compiler/rustc_codegen_gcc/build_system/src/test.rs @@ -247,6 +247,8 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { } .to_string(); let mut command = args.config_info.rustc_command_vec(); + // Implicitly passed by rustc's build system + command.push(&"-Zforce-unstable-if-unmarked"); command.extend_from_slice(&[ &"example/mini_core.rs", &"--crate-name", @@ -261,6 +263,8 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[BUILD] example"); let mut command = args.config_info.rustc_command_vec(); + // Implicitly passed by rustc's build system + command.push(&"-Zforce-unstable-if-unmarked"); command.extend_from_slice(&[ &"example/example.rs", &"--crate-type", @@ -273,6 +277,8 @@ fn mini_tests(env: &Env, args: &TestArg) -> Result<(), String> { // FIXME: create a function "display_if_not_quiet" or something along the line. println!("[AOT] mini_core_hello_world"); let mut command = args.config_info.rustc_command_vec(); + // Implicitly passed by rustc's build system + command.push(&"-Zforce-unstable-if-unmarked"); command.extend_from_slice(&[ &"example/mini_core_hello_world.rs", &"--crate-name", From 63c07bdb5352b561b1a362d01c328982c6a03712 Mon Sep 17 00:00:00 2001 From: Abhinav Srivastav Date: Sun, 4 Oct 2026 17:24:48 +0530 Subject: [PATCH 1260/1309] lower spans of error const args and test binder bounds --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 6ec5903c5fb3b..5583287a832f5 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -2098,7 +2098,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ); hir::TestBinderBoundTypeConstraint { - span: *span, + span: self.lower_span(*span), hir_id: self.lower_node_id(*node_id), params: generics.params, lhs, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4b6e897da4c87..d331c8d732115 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -3363,7 +3363,7 @@ impl UnrepresentableConstArgError { ConstArg { hir_id: lowering_context.next_id(), kind: hir::ConstArgKind::Error(e), - span: self.span, + span: lowering_context.lower_span(self.span), } } } From df0599ea9027aad6f05d76daeaffd4f42b751048 Mon Sep 17 00:00:00 2001 From: ltdk Date: Sun, 4 Oct 2026 08:13:32 -0400 Subject: [PATCH 1261/1309] Revert "implement PartialEq> for Vec, &[T], &mut [T], [T; N], &[T; N] and &mut [T; N]" Revert "fix stability attributes for VecDeque PartialEq impls" This reverts commit 9942d36bf6e6c6e5b5d4f34ded101dcb2b2cd9f7. Revert "update VecDeque PartialEq stability metadata" This reverts commit 3d3f2f823fa54902104dc5ee13c15915cd89a0ce. Revert "update assert-ne-no-invalid-help-issue-146204.stderr for VecDeque PartialEq output" This reverts commit 8cdd010c4e19fb5153247fc9c26a9cb867d376d5. Revert "resolve too_generic_eval_ice stderr conflict" This reverts commit b50d79a556e0aa9cd3d738ca60da826e185fe6c7. Revert "alloc: make VecDeque partial equality symmetric with vec/slice/array" This reverts commit 835975a12f82707097d8abdadb529c704a2847ac. --- .../alloc/src/collections/vec_deque/macros.rs | 20 ------------------ .../alloc/src/collections/vec_deque/mod.rs | 7 ------- library/alloctests/tests/vec_deque.rs | 21 ------------------- .../too_generic_eval_ice.current.stderr | 6 +++--- ...ert-ne-no-invalid-help-issue-146204.stderr | 12 +++++------ 5 files changed, 9 insertions(+), 57 deletions(-) diff --git a/library/alloc/src/collections/vec_deque/macros.rs b/library/alloc/src/collections/vec_deque/macros.rs index dbc1fa3f11578..5c7913073fe87 100644 --- a/library/alloc/src/collections/vec_deque/macros.rs +++ b/library/alloc/src/collections/vec_deque/macros.rs @@ -17,23 +17,3 @@ macro_rules! __impl_slice_eq1 { } } } - -macro_rules! __impl_slice_eq2 { - ($(#[$stability:meta])+, [$($vars:tt)*] $lhs:ty, $rhs:ty, $($constraints:tt)*) => { - $(#[$stability])+ - impl PartialEq<$rhs> for $lhs - where - T: PartialEq, - $($constraints)* - { - fn eq(&self, other: &$rhs) -> bool { - if self.len() != other.len() { - return false; - } - let (oa, ob) = other.as_slices(); - let (sa, sb) = self[..].split_at(oa.len()); - sa == oa && sb == ob - } - } - } -} diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs index 545c6ca59cc32..8e4507c6fd0aa 100644 --- a/library/alloc/src/collections/vec_deque/mod.rs +++ b/library/alloc/src/collections/vec_deque/mod.rs @@ -3907,13 +3907,6 @@ __impl_slice_eq1! { [const N: usize] VecDeque, [U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &[U; N], } __impl_slice_eq1! { [const N: usize] VecDeque, &mut [U; N], } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] Vec, VecDeque, } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &[T], VecDeque, } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [] &mut [T], VecDeque, } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] [T; N], VecDeque, } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &[T; N], VecDeque, } -__impl_slice_eq2! { #[stable(feature = "slice_partial_eq_vec_deque", since = "CURRENT_RUSTC_VERSION")], [const N: usize] &mut [T; N], VecDeque, } - #[stable(feature = "rust1", since = "1.0.0")] impl PartialOrd for VecDeque { fn partial_cmp(&self, other: &Self) -> Option { diff --git a/library/alloctests/tests/vec_deque.rs b/library/alloctests/tests/vec_deque.rs index 3925a1235d3e7..00b2c2e34d569 100644 --- a/library/alloctests/tests/vec_deque.rs +++ b/library/alloctests/tests/vec_deque.rs @@ -631,27 +631,6 @@ fn test_partial_eq_array() { assert!(d == ['a', 'b']); } -#[test] -fn test_partial_eq_vecdeque_reverse() { - let mut d = VecDeque::with_capacity(4); - d.push_back(1); - d.push_back(2); - d.push_back(3); - d.pop_front(); - d.push_back(4); - - let v = vec![2, 3, 4]; - let a = [2, 3, 4]; - let mut b = [2, 3, 4]; - - assert!(v == d); - assert!(&v[..] == d); - assert!(&mut b[..] == d); - assert!(a == d); - assert!(&a == d); - assert!(&mut b == d); -} - #[test] fn test_hash() { let mut x = VecDeque::new(); diff --git a/tests/ui/consts/too_generic_eval_ice.current.stderr b/tests/ui/consts/too_generic_eval_ice.current.stderr index dd5c3bd51bc52..061945e344ede 100644 --- a/tests/ui/consts/too_generic_eval_ice.current.stderr +++ b/tests/ui/consts/too_generic_eval_ice.current.stderr @@ -30,15 +30,15 @@ LL | [5; Self::HOST_SIZE] == [6; 0] | = help: the trait `PartialEq<[{integer}; 0]>` is not implemented for `[{integer}; Self::HOST_SIZE]` = help: the following other types implement trait `PartialEq`: - `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` - `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - and 18 others + `&[u8]` implements `PartialEq` + `&mut [T]` implements `PartialEq>` + and 13 others error: aborting due to 4 previous errors diff --git a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr index 6d36dbdee7ba4..8c3451af7235f 100644 --- a/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr +++ b/tests/ui/macros/assert-ne-no-invalid-help-issue-146204.stderr @@ -6,15 +6,15 @@ LL | assert_ne!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: - `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` - `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - and 18 others + `&[u8]` implements `PartialEq` + `&mut [T]` implements `PartialEq>` + and 13 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:19:5 @@ -24,15 +24,15 @@ LL | assert_eq!(buf, b"----"); | = help: the trait `PartialEq<&[u8; 4]>` is not implemented for `[u8; 4]` = help: the following other types implement trait `PartialEq`: - `&[T; N]` implements `PartialEq>` `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq>` - `&[T]` implements `PartialEq>` `&[T]` implements `PartialEq<[U; N]>` `&[u8; N]` implements `PartialEq` `&[u8; N]` implements `PartialEq` `&[u8]` implements `PartialEq` - and 18 others + `&[u8]` implements `PartialEq` + `&mut [T]` implements `PartialEq>` + and 13 others error[E0277]: can't compare `[u8; 4]` with `&[u8; 4]` --> $DIR/assert-ne-no-invalid-help-issue-146204.rs:5:30 From 3b3e0980a6cc3314bdfd065bd74e8665d87270f4 Mon Sep 17 00:00:00 2001 From: tmiasko Date: Fri, 2 Oct 2026 07:40:01 +0000 Subject: [PATCH 1262/1309] Annotate MIR with dataflow results for testing purposes When requested through an internal rustc attribute, include dataflow results in MIR output, i.e., `-Zunpretty=mir` or `--emit mir`. For now, supported dataflows are: * `#[rustc_mir(rustc_pretty_live_locals)]` * `#[rustc_mir(rustc_pretty_transitive_live_locals)]` The mechanism is intended to supersede existing `rustc_peek` intrinsic. For demonstration also migrates one of tests based on `rustc_peek`: tests/ui/mir-dataflow/liveness-projection.rs. --- Cargo.lock | 1 + compiler/rustc_attr_ir/src/data_structures.rs | 2 + .../src/attributes/rustc_internal.rs | 8 ++ compiler/rustc_interface/Cargo.toml | 1 + compiler/rustc_interface/src/passes.rs | 1 + compiler/rustc_middle/src/hooks.rs | 8 ++ compiler/rustc_middle/src/mir/pretty.rs | 10 +- compiler/rustc_mir_dataflow/src/lib.rs | 6 + compiler/rustc_mir_dataflow/src/pretty.rs | 132 ++++++++++++++++++ compiler/rustc_span/src/symbol.rs | 2 + .../dataflow/liveness.deref.dataflow.0.mir | 25 ++++ .../dataflow/liveness.fields.dataflow.0.mir | 27 ++++ tests/mir-opt/dataflow/liveness.rs | 82 +++++++++++ 13 files changed, 303 insertions(+), 2 deletions(-) create mode 100644 compiler/rustc_mir_dataflow/src/pretty.rs create mode 100644 tests/mir-opt/dataflow/liveness.deref.dataflow.0.mir create mode 100644 tests/mir-opt/dataflow/liveness.fields.dataflow.0.mir create mode 100644 tests/mir-opt/dataflow/liveness.rs diff --git a/Cargo.lock b/Cargo.lock index 49ab9451ba5e0..71086e7203470 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4295,6 +4295,7 @@ dependencies = [ "rustc_metadata", "rustc_middle", "rustc_mir_build", + "rustc_mir_dataflow", "rustc_mir_transform", "rustc_monomorphize", "rustc_parse", diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 55c0bedb9c39c..a1f3f840aa5a2 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -591,6 +591,8 @@ pub enum RustcDumpLayoutKind { #[derive(Clone, Debug, StableHash, Encodable, Decodable, PrintAttribute, PartialEq, Eq)] pub enum RustcMirKind { + PrettyLiveLocals, + PrettyTransitiveLiveLocals, PeekMaybeInit, PeekMaybeUninit, PeekLiveness, diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index bb982184772e7..11554b437e39b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -626,6 +626,14 @@ impl CombineAttributeParser for RustcMirParser { .filter_map(|mi| { if let Some(ident) = mi.ident() { match ident.name { + sym::rustc_pretty_live_locals => { + cx.expect_no_args(mi.args())?; + Some(RustcMirKind::PrettyLiveLocals) + } + sym::rustc_pretty_transitive_live_locals => { + cx.expect_no_args(mi.args())?; + Some(RustcMirKind::PrettyTransitiveLiveLocals) + } sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit), sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit), sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness), diff --git a/compiler/rustc_interface/Cargo.toml b/compiler/rustc_interface/Cargo.toml index ebbecc4ba6867..aea4456792836 100644 --- a/compiler/rustc_interface/Cargo.toml +++ b/compiler/rustc_interface/Cargo.toml @@ -34,6 +34,7 @@ rustc_macros = { path = "../rustc_macros" } rustc_metadata = { path = "../rustc_metadata" } rustc_middle = { path = "../rustc_middle" } rustc_mir_build = { path = "../rustc_mir_build" } +rustc_mir_dataflow = { path = "../rustc_mir_dataflow" } rustc_mir_transform = { path = "../rustc_mir_transform" } rustc_monomorphize = { path = "../rustc_monomorphize" } rustc_parse = { path = "../rustc_parse" } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 5ea1cb20990b5..8975f01de5216 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -906,6 +906,7 @@ pub static DEFAULT_QUERY_PROVIDERS: LazyLock = LazyLock::new(|| { rustc_borrowck::provide(&mut providers.queries); rustc_incremental::provide(providers); rustc_mir_build::provide(providers); + rustc_mir_dataflow::provide(providers); rustc_mir_transform::provide(providers); rustc_monomorphize::provide(providers); rustc_privacy::provide(&mut providers.queries); diff --git a/compiler/rustc_middle/src/hooks.rs b/compiler/rustc_middle/src/hooks.rs index dafed9037615f..7bccc34dbc720 100644 --- a/compiler/rustc_middle/src/hooks.rs +++ b/compiler/rustc_middle/src/hooks.rs @@ -3,6 +3,8 @@ //! similar to queries, but queries come with a lot of machinery for caching and incremental //! compilation, whereas hooks are just plain function pointers without any of the query magic. +use std::io; + use rustc_hir::def_id::{DefId, DefPathHash}; use rustc_index::bit_set::DenseBitSet; use rustc_session::StableCrateId; @@ -123,6 +125,12 @@ declare_hooks! { instance: ty::Instance<'tcx>, typing_env: ty::TypingEnv<'tcx>, ) -> DenseBitSet; + + /// Configures extra data to be included when pretty printing MIR + hook mir_pretty_extra_data( + body: &mir::Body<'tcx>, + ) -> Option io::Result<()>>>; + } #[cold] diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 159a0f9883db3..ae30093b1cda7 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -26,7 +26,7 @@ pub(crate) const ALIGN: usize = 40; /// An indication of where we are in the control flow graph. Used for printing /// extra information in `dump_mir` -#[derive(Clone, Copy)] +#[derive(Clone, Copy, PartialEq, Eq, Hash)] pub enum PassWhere { /// We have not started dumping the control flow graph, but we are about to. BeforeCFG, @@ -332,7 +332,13 @@ pub fn write_mir_pretty<'tcx>(tcx: TyCtxt<'tcx>, w: &mut dyn io::Write) -> io::R } let render_body = |w: &mut dyn io::Write, body| -> io::Result<()> { - writer.write_mir_fn(body, w)?; + if let Some(mut extra_data) = tcx.mir_pretty_extra_data(body) { + let mut writer = MirWriter::new(tcx); + writer.extra_data = &mut *extra_data; + writer.write_mir_fn(body, w)?; + } else { + writer.write_mir_fn(body, w)?; + } for body in tcx.promoted_mir(def_id) { writeln!(w)?; diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs index 8e320e0982077..cd42f5f23f7a4 100644 --- a/compiler/rustc_mir_dataflow/src/lib.rs +++ b/compiler/rustc_mir_dataflow/src/lib.rs @@ -6,6 +6,7 @@ // tidy-alphabetical-end use rustc_middle::ty; +use rustc_middle::util::Providers; // Please change the public `use` directives cautiously, as they might be used by external tools. // See issue #120130. @@ -27,6 +28,7 @@ mod framework; pub mod impls; pub mod move_paths; pub mod points; +mod pretty; pub mod rustc_peek; mod un_derefer; pub mod value_analysis; @@ -35,3 +37,7 @@ pub struct MoveDataTypingEnv<'tcx> { pub move_data: MoveData<'tcx>, pub typing_env: ty::TypingEnv<'tcx>, } + +pub fn provide(providers: &mut Providers) { + providers.hooks.mir_pretty_extra_data = pretty::mir_pretty_extra_data; +} diff --git a/compiler/rustc_mir_dataflow/src/pretty.rs b/compiler/rustc_mir_dataflow/src/pretty.rs new file mode 100644 index 0000000000000..b37ad708e20e0 --- /dev/null +++ b/compiler/rustc_mir_dataflow/src/pretty.rs @@ -0,0 +1,132 @@ +use std::io; + +use rustc_attr_ir::{RustcMirKind, find_attr}; +use rustc_data_structures::fx::FxIndexMap; +use rustc_middle::mir::{self, Body, Local, MirDumper, PassWhere, traversal}; +use rustc_middle::ty::TyCtxt; + +use crate::debuginfo::debuginfo_locals; +use crate::framework::Analysis; +use crate::impls::{MaybeLiveLocals, MaybeTransitiveLiveLocals, borrowed_locals}; +use crate::{ResultsVisitor, visit_results}; + +type ExtraDataFn = dyn Fn(PassWhere, &mut dyn io::Write) -> io::Result<()>; + +pub(crate) fn mir_pretty_extra_data<'tcx>( + tcx: TyCtxt<'tcx>, + body: &Body<'tcx>, +) -> Option> { + let def_id = body.source.def_id(); + let Some(kinds) = find_attr!(tcx, def_id, RustcMir(kind) => kind) else { + return None; + }; + let mut annotations = Annotations::default(); + for kind in kinds { + match kind { + RustcMirKind::PrettyLiveLocals => { + let results = MaybeLiveLocals.iterate_to_fixpoint(tcx, body, None); + let blocks = traversal::reachable(body).map(|(bb, _)| bb); + visit_results( + body, + blocks, + &results, + &mut Annotator { annotations: &mut annotations }, + ); + } + RustcMirKind::PrettyTransitiveLiveLocals => { + let borrowed_locals = borrowed_locals(body); + let debuginfo_locals = debuginfo_locals(body); + let results = MaybeTransitiveLiveLocals::new(&borrowed_locals, &debuginfo_locals) + .iterate_to_fixpoint(tcx, body, None); + let blocks = traversal::reachable(body).map(|(bb, _)| bb); + visit_results( + body, + blocks, + &results, + &mut Annotator { annotations: &mut annotations }, + ); + } + _ => {} + } + } + let extra_data = annotations.into_extra_data()?; + if let Some(dumper) = MirDumper::new(tcx, "dataflow", body) { + dumper.set_extra_data(&*extra_data).dump_mir(body); + } + Some(extra_data) +} + +#[derive(Default)] +struct Annotations { + entries: FxIndexMap>, +} + +impl Annotations { + fn add(&mut self, pass_where: PassWhere, s: String) { + self.entries.entry(pass_where).or_default().push(s); + } + + fn into_extra_data(self) -> Option> { + if self.entries.is_empty() { + return None; + } + Some(Box::new(move |pass_where: PassWhere, out: &mut dyn io::Write| { + let Some(notes) = self.entries.get(&pass_where) else { + return Ok(()); + }; + for s in notes { + writeln!(out, " // {s}")?; + } + Ok(()) + })) + } +} + +/// Examines dataflow results and collects extra annotations for inclusion in MIR pretty printing. +struct Annotator<'a> { + annotations: &'a mut Annotations, +} + +impl<'tcx> ResultsVisitor<'tcx, MaybeLiveLocals> for Annotator<'_> { + fn visit_after_primary_statement_effect( + &mut self, + state: &>::Domain, + _statement: &mir::Statement<'tcx>, + location: mir::Location, + ) { + let live: Vec = state.iter().collect(); + self.annotations.add(PassWhere::BeforeLocation(location), format!("live: {live:?}")); + } + + fn visit_after_primary_terminator_effect( + &mut self, + state: &>::Domain, + _terminator: &mir::Terminator<'tcx>, + location: mir::Location, + ) { + let live: Vec = state.iter().collect(); + self.annotations.add(PassWhere::BeforeLocation(location), format!("live: {live:?}")); + } +} + +impl<'tcx> ResultsVisitor<'tcx, MaybeTransitiveLiveLocals<'_>> for Annotator<'_> { + fn visit_after_primary_statement_effect( + &mut self, + state: &>::Domain, + _statement: &mir::Statement<'tcx>, + location: mir::Location, + ) { + let live: Vec = state.iter().collect(); + self.annotations.add(PassWhere::BeforeLocation(location), format!("live: {live:?}")); + } + + fn visit_after_primary_terminator_effect( + &mut self, + state: &>::Domain, + _terminator: &mir::Terminator<'tcx>, + location: mir::Location, + ) { + let live: Vec = state.iter().collect(); + self.annotations.add(PassWhere::BeforeLocation(location), format!("live: {live:?}")); + } +} diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 21b14a45ccf14..65b4be1ce0188 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1896,6 +1896,8 @@ symbols! { rustc_peek_maybe_init, rustc_peek_maybe_uninit, rustc_preserve_ub_checks, + rustc_pretty_live_locals, + rustc_pretty_transitive_live_locals, rustc_private, rustc_proc_macro_decls, rustc_promotable, diff --git a/tests/mir-opt/dataflow/liveness.deref.dataflow.0.mir b/tests/mir-opt/dataflow/liveness.deref.dataflow.0.mir new file mode 100644 index 0000000000000..52b39d6d27776 --- /dev/null +++ b/tests/mir-opt/dataflow/liveness.deref.dataflow.0.mir @@ -0,0 +1,25 @@ +// MIR for `deref` 0 dataflow + +fn deref() -> () { + let mut _0: (); + let mut _1: usize; + let mut _2: &mut usize; + + bb0: { + // live: [] + // live: [] + _1 = const 42_usize; + // live: [_1] + // live: [_1] + _2 = &mut _1; + // live: [_2] + // live: [_2] + (*_2) = const 24_usize; + // live: [] + // live: [] + _0 = (); + // live: [_0] + // live: [_0] + return; + } +} diff --git a/tests/mir-opt/dataflow/liveness.fields.dataflow.0.mir b/tests/mir-opt/dataflow/liveness.fields.dataflow.0.mir new file mode 100644 index 0000000000000..9869df865833a --- /dev/null +++ b/tests/mir-opt/dataflow/liveness.fields.dataflow.0.mir @@ -0,0 +1,27 @@ +// MIR for `fields` 0 dataflow + +fn fields() -> usize { + let mut _0: usize; + let mut _1: (usize, usize); + + bb0: { + // live: [] + // live: [] + _1 = (const 1_usize, const 0_usize); + // live: [] + // live: [] + (_1.1: usize) = const 2_usize; + // live: [] + // live: [] + _1 = (const 0_usize, const 3_usize); + // live: [_1] + // live: [_1] + (_1.1: usize) = const 4_usize; + // live: [_1] + // live: [_1] + _0 = copy (_1.1: usize); + // live: [_0] + // live: [_0] + return; + } +} diff --git a/tests/mir-opt/dataflow/liveness.rs b/tests/mir-opt/dataflow/liveness.rs new file mode 100644 index 0000000000000..2fb4e28336754 --- /dev/null +++ b/tests/mir-opt/dataflow/liveness.rs @@ -0,0 +1,82 @@ +// Tests for MaybeLiveLocals and MaybeTransitiveLiveLocals dataflows. +#![feature(core_intrinsics, custom_mir, rustc_attrs)] +#![crate_type = "lib"] +use std::intrinsics::mir::*; + +// EMIT_MIR liveness.fields.dataflow.0.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +#[rustc_mir(rustc_pretty_live_locals)] +#[rustc_mir(rustc_pretty_transitive_live_locals)] +pub fn fields() -> usize { + mir! { + let _1: (usize, usize); + { + // CHECK-LABEL: fn fields( + // CHECK: bb0: { + // CHECK-NEXT: live: [] + // CHECK-NEXT: live: [] + // CHECK-NEXT: _1 = (const 1_usize, const 0_usize); + _1 = (1, 0); + // write to _1.1 doesn't make _1 live + // CHECK-NEXT: live: [] + // CHECK-NEXT: live: [] + // CHECK-NEXT: (_1.1: usize) = const 2_usize; + _1.1 = 2; + // write to _1 makes _1 dead + // CHECK-NEXT: live: [] + // CHECK-NEXT: live: [] + // CHECK-NEXT: (const 0_usize, const 3_usize); + _1 = (0, 3); + // write to _1.1 doesn't make _1 dead + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: (_1.1: usize) = const 4_usize; + _1.1 = 4; + // read from _1.1 makes _1 live + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: _0 = copy (_1.1: usize); + RET = _1.1; + // CHECK-NEXT: live: [_0] + // CHECK-NEXT: live: [_0] + // CHECK-NEXT: return; + Return() + } + } +} + +// EMIT_MIR liveness.deref.dataflow.0.mir +#[custom_mir(dialect = "runtime", phase = "optimized")] +#[rustc_mir(rustc_pretty_live_locals)] +#[rustc_mir(rustc_pretty_transitive_live_locals)] +pub fn deref() { + mir! { + let _1: usize; + let _2: &mut usize; + { + // CHECK-LABEL: fn deref( + // CHECK: bb0: { + // CHECK-NEXT: live: [] + // CHECK-NEXT: live: [] + // CHECK-NEXT: _1 = const 42_usize; + _1 = 42; + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: live: [_1] + // CHECK-NEXT: _2 = &mut _1; + _2 = &mut _1; + // deref of _2 makes it live even on LHS of an assignment + // CHECK-NEXT: live: [_2] + // CHECK-NEXT: live: [_2] + // CHECK-NEXT: (*_2) = const 24_usize; + *_2 = 24; + // CHECK-NEXT: live: [] + // CHECK-NEXT: live: [] + // CHECK-NEXT: _0 = (); + RET = (); + // CHECK-NEXT: live: [_0] + // CHECK-NEXT: live: [_0] + // CHECK-NEXT: return; + Return() + } + } +} From 49e1df177a3fa3cb8caccd43317cadf5e8b14583 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Le=C3=B3n=20Orell=20Valerian=20Liehr?= Date: Sat, 19 Sep 2026 01:41:39 +0200 Subject: [PATCH 1263/1309] Parser: Refactor & better document `should_continue_as_assoc_expr` & `can_continue_expr_unambiguously` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * `can_continue_expr_unambiguously` * exhaustively match on `AssocOp` * don't needlessly provide code snippets in comments for ops that are unproblematic, that's not interesting * instead, provide an example / explainer for each op that is ambiguous which is far more relevant * move it into `rustc_parse` since it's only used there & it's only tailored towards parse error recovery * `should_continue_as_assoc_expr` * it used to match on a `(bool, _)` tuple & execute `AssocOp::from_token` unconditionally even though all but one branch cared about the bool being false * instead, first check `expr_is_complete` and bail out early if it's false; no need to execute `AssocOp::from_token` unnecessarily or "bother" the rest of the code with the impossibility of `expr_is_complete` not holding * extract the recovery logic into a new `recover_from_bin_op_after_complete_stmt_expr` that resides in `expr/diagnostics.rs` to clearly separate what is recovery and what is actual parsing * in it check `can_continue_expr_unambiguously` *first* before special-casing some ops (the `Mul | Sub | …` branch) because it's more "important"; in any case it's a superset; renders the control flow & the logic a lot more comprehensible * rewrite the comments from scratch to make it clear that all of that "bin op after complete stmt expr" is recovery code only! when I first came across this function one year ago I was super confused & briefly worried that typeck was potentially making belated parsing decisions * inline it because it's become a single expression --- compiler/rustc_ast/src/util/parser.rs | 26 ------- compiler/rustc_hir_typeck/src/expr.rs | 4 +- .../src/fn_ctxt/suggestions.rs | 4 +- compiler/rustc_hir_typeck/src/op.rs | 9 ++- .../rustc_parse/src/parser/diagnostics.rs | 2 +- compiler/rustc_parse/src/parser/expr.rs | 58 ++------------- .../src/parser/expr/diagnostics.rs | 73 +++++++++++++++++++ compiler/rustc_parse/src/parser/pat.rs | 2 +- compiler/rustc_parse/src/parser/stmt.rs | 2 +- compiler/rustc_session/src/parse.rs | 21 ++++-- 10 files changed, 113 insertions(+), 88 deletions(-) diff --git a/compiler/rustc_ast/src/util/parser.rs b/compiler/rustc_ast/src/util/parser.rs index 1430d04dcca6a..bc5f693a29b7b 100644 --- a/compiler/rustc_ast/src/util/parser.rs +++ b/compiler/rustc_ast/src/util/parser.rs @@ -110,32 +110,6 @@ impl AssocOp { Cast | Binary(_) | Range(_) => false, } } - - /// This operator could be used to follow a block unambiguously. - /// - /// This is used for error recovery at the moment, providing a suggestion to wrap blocks with - /// parentheses while having a high degree of confidence on the correctness of the suggestion. - pub fn can_continue_expr_unambiguously(&self) -> bool { - use AssocOp::*; - use BinOpKind::*; - matches!( - self, - Assign | // `{ 42 } = { 42 }` - Binary( - BitXor | // `{ 42 } ^ 3` - Div | // `{ 42 } / 42` - Rem | // `{ 42 } % 2` - Shr | // `{ 42 } >> 2` - Le | // `{ 42 } <= 3` - Gt | // `{ 42 } > 3` - Ge // `{ 42 } >= 3` - ) | - AssignOp(_) | // `{ 42 } +=` - // Equal | // `{ 42 } == { 42 }` Accepting these here would regress incorrect - // NotEqual | // `{ 42 } != { 42 } struct literals parser recovery. - Cast // `{ 42 } as usize` - ) - } } #[derive(Clone, Copy, PartialEq, PartialOrd)] diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index dbe5a51b25b45..9f0d00d5274fa 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -431,7 +431,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { let mut err = self.dcx().create_err(CantDereference { span: expr.span, ty: oprnd_t }); let sp = tcx.sess.source_map().start_point(expr.span).with_parent(None); - if let Some(sp) = tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = + tcx.sess.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&sp) + { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } // The operand may be an uncalled function, in which case it is its return type diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 6dd6a56e39b87..116bbf6280642 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -1467,7 +1467,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { expr: &hir::Expr<'_>, ) -> bool { let sp = self.tcx.sess.source_map().start_point(expr.span).with_parent(None); - if let Some(sp) = self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = + self.tcx.sess.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&sp) + { // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); true diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs index 48a0ec756d8d9..526f29cb3753b 100644 --- a/compiler/rustc_hir_typeck/src/op.rs +++ b/compiler/rustc_hir_typeck/src/op.rs @@ -1010,8 +1010,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { } let sp = self.tcx.sess.source_map().start_point(ex.span).with_parent(None); - if let Some(sp) = - self.tcx.sess.psess.ambiguous_block_expr_parse.borrow().get(&sp) + if let Some(sp) = self + .tcx + .sess + .psess + .complete_stmt_exprs_before_bin_op_lookalike + .borrow() + .get(&sp) { // If the previous expression was a block expression, suggest parentheses // (turning this into a binary subtraction operation instead.) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index fd4d012ebe2f9..1557aec1322ad 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2236,7 +2236,7 @@ impl<'a> Parser<'a> { }; let mut err = self.dcx().struct_span_err(span, msg); let sp = self.psess.source_map().start_point(self.token.span); - if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = self.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&sp) { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } err.span_label(span, "expected expression"); diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index 9e74a7b1ab38c..bf99bbe26f087 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -36,7 +36,7 @@ use super::{ }; use crate::{exp, maybe_recover_from_interpolated_ty_qpath}; -mod diagnostics; +pub(super) mod diagnostics; #[derive(Debug)] pub(super) enum DestructuredFloat { @@ -149,7 +149,7 @@ impl<'a> Parser<'a> { mut lhs: Box, ) -> PResult<'a, (Box, bool)> { let mut parsed_something = false; - if !self.should_continue_as_assoc_expr(&lhs) { + if self.expr_is_complete(&lhs) && !self.recover_from_bin_op_after_complete_stmt_expr(&lhs) { return Ok((lhs, parsed_something)); } @@ -226,52 +226,6 @@ impl<'a> Parser<'a> { Ok((lhs, parsed_something)) } - fn should_continue_as_assoc_expr(&mut self, lhs: &Expr) -> bool { - match (self.expr_is_complete(lhs), AssocOp::from_token(&self.token)) { - // Semi-statement forms are odd: - // See https://github.com/rust-lang/rust/issues/29071 - (true, None) => false, - (false, _) => true, // Continue parsing the expression. - // An exhaustive check is done in the following block, but these are checked first - // because they *are* ambiguous but also reasonable looking incorrect syntax, so we - // want to keep their span info to improve diagnostics in these cases in a later stage. - (true, Some(AssocOp::Binary( - BinOpKind::Mul | // `{ 42 } *foo = bar;` or `{ 42 } * 3` - BinOpKind::Sub | // `{ 42 } -5` - BinOpKind::Add | // `{ 42 } + 42` (unary plus) - BinOpKind::And | // `{ 42 } &&x` (#61475) or `{ 42 } && if x { 1 } else { 0 }` - BinOpKind::Or | // `{ 42 } || 42` ("logical or" or closure) - BinOpKind::BitOr // `{ 42 } | 42` or `{ 42 } |x| 42` - ))) => { - // These cases are ambiguous and can't be identified in the parser alone. - // - // Bitwise AND is left out because guessing intent is hard. We can make - // suggestions based on the assumption that double-refs are rarely intentional, - // and closures are distinct enough that they don't get mixed up with their - // return value. - let sp = self.psess.source_map().start_point(self.token.span); - self.psess.ambiguous_block_expr_parse.borrow_mut().insert(sp, lhs.span); - false - } - (true, Some(op)) if !op.can_continue_expr_unambiguously() => false, - (true, Some(_)) => { - self.error_found_expr_would_be_stmt(lhs); - true - } - } - } - - /// We've found an expression that would be parsed as a statement, - /// but the next token implies this should be parsed as an expression. - /// For example: `if let Some(x) = x { x } else { 0 } / 2`. - fn error_found_expr_would_be_stmt(&self, lhs: &Expr) { - self.dcx().emit_err(crate::diagnostics::FoundExprWouldBeStmt { - span: self.token.span, - token: pprust::token_to_string(&self.token), - suggestion: crate::diagnostics::ExprParenthesesNeeded::surrounding(lhs.span), - }); - } - /// Possibly translate the current token to an associative operator. /// The method does not advance the current token. pub(super) fn check_assoc_op(&self) -> Option> { @@ -425,7 +379,9 @@ impl<'a> Parser<'a> { }; // a block on the LHS might have been intended to be an expression instead - if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { + if let Some(sp) = + this.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&lo) + { err.add_parentheses = Some(crate::diagnostics::ExprParenthesesNeeded::surrounding(*sp)); } else { @@ -1364,7 +1320,9 @@ impl<'a> Parser<'a> { this.parse_expr_closure().map_err(|mut err| { // If the input is something like `if a { 1 } else { 2 } | if a { 3 } else { 4 }` // then suggest parens around the lhs. - if let Some(sp) = this.psess.ambiguous_block_expr_parse.borrow().get(&lo) { + if let Some(sp) = + this.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&lo) + { err.subdiagnostic(crate::diagnostics::ExprParenthesesNeeded::surrounding( *sp, )); diff --git a/compiler/rustc_parse/src/parser/expr/diagnostics.rs b/compiler/rustc_parse/src/parser/expr/diagnostics.rs index ac5bd737d9349..60b0801755520 100644 --- a/compiler/rustc_parse/src/parser/expr/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/expr/diagnostics.rs @@ -1,5 +1,6 @@ use rustc_ast::util::parser::AssocOp; use rustc_ast::{BinOpKind, Expr, ExprKind, token}; +use rustc_ast_pretty::pprust; use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{Span, Spanned, respan, sym}; @@ -7,6 +8,51 @@ use crate::parser::Parser; use crate::{diagnostics, exp}; impl<'a> Parser<'a> { + /// Recover from a binary operator after complete statement expression as in `{ 4 } / 2`. + pub(super) fn recover_from_bin_op_after_complete_stmt_expr(&self, lhs: &Expr) -> bool { + use BinOpKind::*; + + // Starting point: We've just parsed a *complete* stmt expr (e.g., a block like `{ 4 }`). + + let Some(op) = AssocOp::from_token(&self.token) else { return false }; + + // We've now encountered a token that could(!) be interpreted as a binary operator. This + // could mean that the user intended to write a binary operation where the left operand is + // block-like. In that case they would need to parenthesize the LHS or the entire operation + // (e.g., `{ 4 } / 2` -> `({ 4 }) / 2` or `({ 4 } / 2)`). + + if op_can_continue_stmt_expr_unambiguously(op) { + // We know that the token (e.g., `/`) can't possibly begin a new statement or pattern. + // Instead of letting the stmt/pat parser emit a generic & rather confusing diagnostic, + // let's emit a more targeted one, and continue parsing the expression. + + self.dcx().emit_err(diagnostics::FoundExprWouldBeStmt { + span: self.token.span, + token: pprust::token_to_string(&self.token), + suggestion: diagnostics::ExprParenthesesNeeded::surrounding(lhs.span), + }); + return true; + } + + // The token can begin a new statement or pattern; this means we're on the happy path! + // Still, the user might've meant to write a bin op here but we can't tell at this stage of + // compilation. So if it's a "common lookalike" let's proactively register it somewhere for + // later stages of compilation to potentially retrieve (e.g., in typeck). + // + // We've left out `BitAnd` because guessing its intent is hard. We can make suggestions + // based on the assumption that double-refs are rarely intentional, and closures are + // distinct enough that they don't get mixed up with their return value. + if let AssocOp::Binary(Add | And | BitOr | Mul | Or | Sub) = op { + let sp = self.psess.source_map().start_point(self.token.span); + self.psess + .complete_stmt_exprs_before_bin_op_lookalike + .borrow_mut() + .insert(sp, lhs.span); + } + + false + } + /// Recover from alphabetic logic operators `and` and `or` as found in e.g., Python and PHP. pub(super) fn recover_from_alpha_logic_op(&self) -> Option> { if self.may_recover() @@ -250,6 +296,33 @@ impl<'a> Parser<'a> { } } +/// Whether this operator could be used to follow a complete statement expression unambiguously +/// during parse error recovery. +pub(in crate::parser) fn op_can_continue_stmt_expr_unambiguously(op: AssocOp) -> bool { + // NOTE: At the time of writing, it's only safe to return `true` for tokens that don't share a + // prefix with statements or patterns. For context, statement lists and match arm bodies + // are (the only two) places that use `Restriction::STMT_EXPR` (in the happy path). + + use BinOpKind::*; + match op { + AssocOp::Assign | AssocOp::AssignOp(_) | AssocOp::Cast => true, + AssocOp::Binary(bin_op) => match bin_op { + | BitXor | Div | Ge | Gt | Le | Rem | Shr => true, + | Add // unambiguous but would inhibit our recovery from unary plus + | And // `&&` starts repeated borrow (e.g., `&&x`) + | BitAnd // `&` starts borrow (e.g., `&x`) + | BitOr // `|` starts closure (e.g., `|_| ()`) or leading vert (e.g., `| Some(_)`) + | Eq | Ne // unambiguous but would inhibit our recovery from bad struct literals + | Lt // `<` starts qualified path (e.g., `::P`) + | Mul // `*` starts unary deref (e.g., `*x`, `*x = 0`) + | Or // `||` starts parameterless closure (e.g. `|| 0`) + | Shl // `<<` starts repeated qualified path (e.g., `<::Q as X>::P`) + | Sub => false, // `-` starts unary negation (e.g, `-x`) + }, + AssocOp::Range(_) => false, // `..`/`..=` start ranges w/o lower bound (e.g., `..`, `..=1`) + } +} + #[derive(Copy, Clone)] pub(super) enum IncOrDec { Inc, diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs index f53cfc792bd69..9fd38aa0f3b8f 100644 --- a/compiler/rustc_parse/src/parser/pat.rs +++ b/compiler/rustc_parse/src/parser/pat.rs @@ -1334,7 +1334,7 @@ impl<'a> Parser<'a> { err.span_label(self.token.span, format!("expected {expected}")); let sp = self.psess.source_map().start_point(self.token.span); - if let Some(sp) = self.psess.ambiguous_block_expr_parse.borrow().get(&sp) { + if let Some(sp) = self.psess.complete_stmt_exprs_before_bin_op_lookalike.borrow().get(&sp) { err.subdiagnostic(ExprParenthesesNeeded::surrounding(*sp)); } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index d59ef93eded21..3cee15c5efa49 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -1134,7 +1134,7 @@ impl<'a> Parser<'a> { { true } else if let Some(op) = self.check_assoc_op() - && op.node.can_continue_expr_unambiguously() + && super::expr::diagnostics::op_can_continue_stmt_expr_unambiguously(op.node) { true } else { diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs index b9555e6520087..3bdfedb07775a 100644 --- a/compiler/rustc_session/src/parse.rs +++ b/compiler/rustc_session/src/parse.rs @@ -84,10 +84,21 @@ pub struct ParseSess { pub bad_unicode_identifiers: Lock>>, source_map: Arc, pub buffered_lints: Lock>, - /// Contains the spans of block expressions that could have been incomplete based on the - /// operation token that followed it, but that the parser cannot identify without further - /// analysis. - pub ambiguous_block_expr_parse: Lock>, + /// Places where *complete* stmt exprs are followed by a token that would've been interpreted as + /// a binary operator instead of the start of a following stmt or pat *if we weren't in a stmt + /// expr context*. + /// + /// **For error recovery and diagnostic purposes only!** + /// + /// Maps from the [`start_point`] of the bin op lookalike to the span of the complete stmt expr + /// (e.g., block) that could be interpreted as its left operand. + /// + /// Examples: Given `fn f() { { dbg!(); } *ptr = 0; }` it maps the span of `*` to the span of + /// `{ dbg!(); }`; given `fn f() { { true } && panic!(); }` it maps the span of the first `&` to + /// the span of `{ true }`. + /// + /// [`start_point`]: SourceMap::start_point + pub complete_stmt_exprs_before_bin_op_lookalike: Lock>, pub gated_spans: GatedSpans, pub symbol_gallery: SymbolGallery, /// Used to generate new `AttrId`s. Every `AttrId` is unique. @@ -114,7 +125,7 @@ impl ParseSess { bad_unicode_identifiers: Lock::new(Default::default()), source_map, buffered_lints: Lock::new(vec![]), - ambiguous_block_expr_parse: Lock::new(Default::default()), + complete_stmt_exprs_before_bin_op_lookalike: Lock::new(Default::default()), gated_spans: GatedSpans::default(), symbol_gallery: SymbolGallery::default(), attr_id_generator: AttrIdGenerator::new(), From 5ace3905f777b7f155787678ed859135b57a3402 Mon Sep 17 00:00:00 2001 From: arferreira Date: Fri, 27 Feb 2026 09:54:43 -0500 Subject: [PATCH 1264/1309] Fix relative extern URL depth on source pages --- src/librustdoc/html/format.rs | 89 ++++++++++++------- src/librustdoc/html/highlight.rs | 14 +-- src/librustdoc/html/render/mod.rs | 2 +- src/librustdoc/html/sources.rs | 28 +++--- .../passes/collect_intra_doc_links.rs | 2 +- .../extern/extern-html-root-url-relative.rs | 6 +- 6 files changed, 84 insertions(+), 57 deletions(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 3f1ed079f2686..93153df10b509 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -348,11 +348,11 @@ pub(crate) struct HrefInfo { } /// This function is to get the external macro path because they are not in the cache used in -/// `href_with_root_path`. +/// `href_with_jump_to_def_path_depth`. fn generate_macro_def_id_path( def_id: DefId, cx: &Context<'_>, - root_path: Option<&str>, + jump_to_def_path_depth: Option, ) -> Result { let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); @@ -388,16 +388,16 @@ fn generate_macro_def_id_path( let url = match cache.extern_locations[&def_id.krate] { ExternalLocation::Remote { ref url, is_absolute } => { - let mut prefix = remote_url_prefix(url, is_absolute, cx.current.len()); + let depth = jump_to_def_path_depth.unwrap_or(cx.current.len()); + let mut prefix = remote_url_prefix(url, is_absolute, depth); prefix.extend(module_path.iter().copied()); prefix.push_fmt(format_args!("{}.{last}.html", item_type.as_str())); prefix.finish() } ExternalLocation::Local => { - // `root_path` always end with a `/`. format!( - "{root_path}{path}/{item_type}.{last}.html", - root_path = root_path.unwrap_or(""), + "{prefix}{path}/{item_type}.{last}.html", + prefix = "../".repeat(jump_to_def_path_depth.unwrap_or(0)), path = fmt::from_fn(|f| module_path.iter().joined("/", f)), item_type = item_type.as_str(), ) @@ -505,7 +505,7 @@ fn generate_item_def_id_path( mut def_id: DefId, original_def_id: DefId, cx: &Context<'_>, - root_path: Option<&str>, + jump_to_def_path_depth: Option, ) -> Result { let tcx = cx.tcx(); let crate_name = tcx.crate_name(def_id.krate); @@ -578,8 +578,9 @@ fn generate_item_def_id_path( }; let module_fqp = to_module_fqp(shortty, &fqp); - let (parts, is_absolute) = url_parts(cx.cache(), def_id, module_fqp, &cx.current)?; - let mut url = make_href(root_path, shortty, parts, &fqp, is_absolute); + let (parts, is_remote) = + url_parts(cx.cache(), def_id, module_fqp, &cx.current, jump_to_def_path_depth)?; + let mut url = make_href(jump_to_def_path_depth, shortty, parts, &fqp, is_remote); if def_id != original_def_id { let kind = ItemType::from_def_id(original_def_id, tcx); @@ -624,17 +625,33 @@ fn remote_url_prefix(url: &str, is_absolute: bool, depth: usize) -> UrlPartsBuil } } +/// Returns `(url_parts, is_remote)` where `is_remote` indicates the URL points to an +/// external location and should not use relative URLs. +/// +/// This function tries to generate minimal, relative URLs. When generating an intra-doc +/// link from one item page to another, it compares the paths of both items and generates +/// exactly the right number of "../"'s to reach the deepest common parent, then fills in +/// the rest of the path. This is done by comparing `module_fqp` with `relative_to`. +/// +/// When generating a link for jump-to-def across crates, that won't work, because sources are +/// stored under "src/[crate]/[path].rs". When linking jump-to-def for another crate, we just +/// write enough "../"'s to reach the doc root, then generate the entire path for `module_fqp`. +/// The right number of "../"'s is stored in `jump_to_def_path_depth`. fn url_parts( cache: &Cache, def_id: DefId, module_fqp: &[Symbol], relative_to: &[Symbol], + jump_to_def_path_depth: Option, ) -> Result<(UrlPartsBuilder, bool), HrefError> { match cache.extern_locations[&def_id.krate] { ExternalLocation::Remote { ref url, is_absolute } => { - let mut builder = remote_url_prefix(url, is_absolute, relative_to.len()); + let depth = jump_to_def_path_depth.unwrap_or(relative_to.len()); + let mut builder = remote_url_prefix(url, is_absolute, depth); builder.extend(module_fqp.iter().copied()); - Ok((builder, is_absolute)) + // Remote URLs (both absolute and relative) already encode the correct path; + // no additional depth prefix should be applied. + Ok((builder, true)) } ExternalLocation::Local => Ok((href_relative_parts(module_fqp, relative_to), false)), ExternalLocation::Unknown => Err(HrefError::DocumentationNotBuilt), @@ -642,16 +659,16 @@ fn url_parts( } fn make_href( - root_path: Option<&str>, + jump_to_def_path_depth: Option, shortty: ItemType, mut url_parts: UrlPartsBuilder, fqp: &[Symbol], - is_absolute: bool, + is_remote: bool, ) -> String { - // FIXME: relative extern URLs may break when prefixed with root_path - if !is_absolute && let Some(root_path) = root_path { - let root = root_path.trim_end_matches('/'); - url_parts.push_front(root); + // Remote URLs already have the correct depth via `remote_url_prefix`; + // only local items need `jump_to_def_path_depth` to bridge from source pages to the doc tree. + if !is_remote && let Some(depth) = jump_to_def_path_depth { + url_parts.push_front(&iter::repeat_n("..", depth).join("/")); } debug!(?url_parts); match shortty { @@ -707,10 +724,12 @@ fn inherits_doc_hidden(tcx: TyCtxt<'_>, mut def_id: DefId) -> bool { } } -pub(crate) fn href_with_root_path( +/// If `jump_to_def_path_depth` is `Some`, the link comes from a source page and needs that many +/// `..` segments to reach the doc root; `None` generates a link relative to the current page. +pub(crate) fn href_with_jump_to_def_path_depth( original_did: DefId, cx: &Context<'_>, - root_path: Option<&str>, + jump_to_def_path_depth: Option, preferred_name: Option<&str>, ) -> Result { let tcx = cx.tcx(); @@ -723,7 +742,12 @@ pub(crate) fn href_with_root_path( // If this a constructor, we get the parent (either a struct or a variant) and then // generate the link for this item. DefKind::Ctor(..) => { - return href_with_root_path(tcx.parent(original_did), cx, root_path, preferred_name); + return href_with_jump_to_def_path_depth( + tcx.parent(original_did), + cx, + jump_to_def_path_depth, + preferred_name, + ); } DefKind::ExternCrate => { // Link to the crate itself, not the `extern crate` item. @@ -744,7 +768,7 @@ pub(crate) fn href_with_root_path( if !original_did.is_local() { // If we are generating an href for the "jump to def" feature, then the only case we want // to ignore is if the item is `doc(hidden)` because we can't link to it. - if root_path.is_some() { + if jump_to_def_path_depth.is_some() { if inherits_doc_hidden(tcx, original_did) { return Err(HrefError::Private); } @@ -756,7 +780,7 @@ pub(crate) fn href_with_root_path( } } - let (fqp, shortty, url_parts, is_absolute) = match cache.paths.get(&did) { + let (fqp, shortty, url_parts, is_remote) = match cache.paths.get(&did) { Some(info) => ( info.get_preferred_path(preferred_name), info.ty, @@ -772,32 +796,33 @@ pub(crate) fn href_with_root_path( // directly here whereas for intra-doc links, we have some extra computation being // performed there. // - // So if `root_path` is `Some()` and it's an associated item, we enter to enter the - // `else` branch to have the anchor generated here directly. - if (root_path.is_none() || original_did == did) + // So if `jump_to_def_path_depth` is `Some()` and it's an associated item, we enter to + // enter the `else` branch to have the anchor generated here directly. + if (jump_to_def_path_depth.is_none() || original_did == did) && let Some(&(ref fqp, shortty)) = cache.external_paths.get(&did) { let module_fqp = to_module_fqp(shortty, fqp); - let (parts, is_absolute) = url_parts(cache, did, module_fqp, relative_to)?; - (fqp.as_slice(), shortty, parts, is_absolute) + let (parts, is_remote) = + url_parts(cache, did, module_fqp, relative_to, jump_to_def_path_depth)?; + (fqp.as_slice(), shortty, parts, is_remote) } else if matches!(def_kind, DefKind::Macro(_)) { - return generate_macro_def_id_path(did, cx, root_path); + return generate_macro_def_id_path(did, cx, jump_to_def_path_depth); } else if did.is_local() { return Err(HrefError::Private); } else { - return generate_item_def_id_path(did, original_did, cx, root_path); + return generate_item_def_id_path(did, original_did, cx, jump_to_def_path_depth); } } }; Ok(HrefInfo { - url: make_href(root_path, shortty, url_parts, fqp, is_absolute), + url: make_href(jump_to_def_path_depth, shortty, url_parts, fqp, is_remote), kind: shortty, rust_path: fqp.to_vec(), }) } pub(crate) fn href(did: DefId, cx: &Context<'_>) -> Result { - href_with_root_path(did, cx, None, None) + href_with_jump_to_def_path_depth(did, cx, None, None) } pub(crate) fn href_with_path_check( @@ -805,7 +830,7 @@ pub(crate) fn href_with_path_check( cx: &Context<'_>, text: &str, ) -> Result { - href_with_root_path(did, cx, None, Some(text)) + href_with_jump_to_def_path_depth(did, cx, None, Some(text)) } /// Both paths should only be modules. diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs index 6ef5de0b20aba..a9b8ccc3b2106 100644 --- a/src/librustdoc/html/highlight.rs +++ b/src/librustdoc/html/highlight.rs @@ -33,7 +33,7 @@ pub(crate) struct HrefContext<'a, 'tcx> { pub(crate) file_span: Span, /// This field is used to know "how far" from the top of the directory we are to link to either /// documentation pages or other source pages. - pub(crate) root_path: &'a str, + pub(crate) jump_to_def_path_depth: usize, /// This field is used to calculate precise local URLs. pub(crate) current_href: String, } @@ -1407,26 +1407,26 @@ fn generate_link_to_def( LinkFromSrc::Local(span) => { context.href_from_span_relative(*span, &href_context.current_href) } - LinkFromSrc::External(def_id) => format::href_with_root_path( + LinkFromSrc::External(def_id) => format::href_with_jump_to_def_path_depth( *def_id, context, - Some(href_context.root_path), + Some(href_context.jump_to_def_path_depth), None, ) .ok() .map(|HrefInfo { url, .. }| url), - LinkFromSrc::Primitive(prim) => format::href_with_root_path( + LinkFromSrc::Primitive(prim) => format::href_with_jump_to_def_path_depth( PrimitiveType::primitive_locations(context.tcx())[prim], context, - Some(href_context.root_path), + Some(href_context.jump_to_def_path_depth), None, ) .ok() .map(|HrefInfo { url, .. }| url), - LinkFromSrc::Doc(def_id) => format::href_with_root_path( + LinkFromSrc::Doc(def_id) => format::href_with_jump_to_def_path_depth( *def_id, context, - Some(href_context.root_path), + Some(href_context.jump_to_def_path_depth), None, ) .ok() diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 35947921dc145..974672a050900 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -2903,7 +2903,7 @@ fn render_call_locations( contents_subset, file_span, cx, - &cx.root_path(), + cx.current.len(), &highlight::DecorationInfo(decoration_info), &sources::SourceContext::Embedded(sources::ScrapedInfo { needs_expansion, diff --git a/src/librustdoc/html/sources.rs b/src/librustdoc/html/sources.rs index ea52fe51c5358..2328f0e8b9a11 100644 --- a/src/librustdoc/html/sources.rs +++ b/src/librustdoc/html/sources.rs @@ -1,4 +1,4 @@ -use std::cell::RefCell; +use std::cell::{Cell, RefCell}; use std::ffi::OsStr; use std::path::{Component, Path, PathBuf}; use std::{fmt, fs}; @@ -193,31 +193,28 @@ impl SourceCollector<'_, '_> { let shared = &self.cx.shared; // Create the intermediate directories let cur = RefCell::new(PathBuf::new()); - let root_path = RefCell::new(PathBuf::new()); + // Tracks the extra directory depth accumulated during path traversal. + // Starts at 0; `PathBuf::pop()` on empty is a no-op, so we mirror that + // with `saturating_sub`. The base depth of 2 (for `src//`) is added after. + let extra_depth = Cell::new(0usize); clean_path( &shared.src_root, &p, |component| { cur.borrow_mut().push(component); - root_path.borrow_mut().push(".."); + extra_depth.set(extra_depth.get() + 1); }, || { cur.borrow_mut().pop(); - root_path.borrow_mut().pop(); + extra_depth.set(extra_depth.get().saturating_sub(1)); }, ); + let jump_to_def_path_depth = 2 + extra_depth.get(); + let src_fname = p.file_name().expect("source has no filename").to_os_string(); let mut fname = src_fname.clone(); - - let root_path = PathBuf::from("../../").join(root_path.into_inner()); - let mut root_path = root_path.to_string_lossy(); - if let Some(c) = root_path.as_bytes().last() - && *c != b'/' - { - root_path += "/"; - } let mut file_path = Path::new(&self.crate_name).join(&*cur.borrow()); file_path.push(&fname); fname.push(".html"); @@ -228,6 +225,7 @@ impl SourceCollector<'_, '_> { let title = format!("{} - source", src_fname.to_string_lossy()); let desc = format!("Source of the Rust file `{}`.", p.to_string_lossy()); + let root_path = "../".repeat(jump_to_def_path_depth); let page = layout::Page { title: &title, short_title: &src_fname.to_string_lossy(), @@ -251,7 +249,7 @@ impl SourceCollector<'_, '_> { contents, file_span, self.cx, - &root_path, + jump_to_def_path_depth, &highlight::DecorationInfo::default(), &source_context, ) @@ -330,7 +328,7 @@ pub(crate) fn print_src( s: &str, file_span: rustc_span::Span, cx: &Context<'_>, - root_path: &str, + jump_to_def_path_depth: usize, decoration_info: &highlight::DecorationInfo, source_context: &SourceContext<'_>, ) -> fmt::Result { @@ -358,7 +356,7 @@ pub(crate) fn print_src( Some(highlight::HrefContext { context: cx, file_span: file_span.into(), - root_path, + jump_to_def_path_depth, current_href, }), Some(decoration_info), diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index ac7cf2a42bd3b..ea131574b17e3 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -1251,7 +1251,7 @@ impl LinkCollector<'_, '_> { /// Returns `true` if a link could be generated from the given intra-doc information. /// - /// This is a very light version of `format::href_with_root_path` since we're only interested + /// This is a very light version of `format::href_with_jump_to_def_path_depth` since we're only interested /// about whether we can generate a link to an item or not. /// /// * If `original_did` is local, then we check if the item is reexported or public. diff --git a/tests/rustdoc-html/extern/extern-html-root-url-relative.rs b/tests/rustdoc-html/extern/extern-html-root-url-relative.rs index ba2b50c6bf222..dedc0819ed577 100644 --- a/tests/rustdoc-html/extern/extern-html-root-url-relative.rs +++ b/tests/rustdoc-html/extern/extern-html-root-url-relative.rs @@ -21,7 +21,11 @@ pub mod nested { pub mod intra_doc_link { } -// link-to-definition +// link-to-definition: source pages live under src// so they need +// ../../ to reach the doc root. Previously these links were incorrectly generated +// as ../../../ (one level too deep) which passed the `has` check by substring match. //@ has src/extern_html_root_url_relative/extern-html-root-url-relative.rs.html //@ has - '//a/@href' '../../core/iter/index.html' //@ has - '//a/@href' '../../core/future/index.html' +//@ !has - '//a/@href' '../../../core/iter/index.html' +//@ !has - '//a/@href' '../../../core/future/index.html' From 9ca47aebdf152a7a99d4e034989c1d78d36b97f1 Mon Sep 17 00:00:00 2001 From: arferreira Date: Thu, 12 Mar 2026 06:54:29 -0400 Subject: [PATCH 1265/1309] Escape brackets in doc comment to fix rustdoc warning --- src/librustdoc/html/format.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs index 93153df10b509..7f0c4132456ad 100644 --- a/src/librustdoc/html/format.rs +++ b/src/librustdoc/html/format.rs @@ -634,7 +634,7 @@ fn remote_url_prefix(url: &str, is_absolute: bool, depth: usize) -> UrlPartsBuil /// the rest of the path. This is done by comparing `module_fqp` with `relative_to`. /// /// When generating a link for jump-to-def across crates, that won't work, because sources are -/// stored under "src/[crate]/[path].rs". When linking jump-to-def for another crate, we just +/// stored under `src//.rs`. When linking jump-to-def for another crate, we just /// write enough "../"'s to reach the doc root, then generate the entire path for `module_fqp`. /// The right number of "../"'s is stored in `jump_to_def_path_depth`. fn url_parts( From 6d998877ff20d595e010789ba77cdc6d78bdc482 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sun, 4 Oct 2026 23:25:08 +0200 Subject: [PATCH 1266/1309] rustc_attr_parsing: properly track lint locations --- compiler/rustc_attr_parsing/src/context.rs | 10 ++++- compiler/rustc_middle/src/lint.rs | 4 +- .../clippy/clippy_utils/src/diagnostics.rs | 8 +++- tests/ui/track-diagnostics/track8.rs | 17 ++++++-- tests/ui/track-diagnostics/track8.stderr | 42 +++++++++++++++++-- 5 files changed, 68 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs index b4221048cfc82..060fd74c1db21 100644 --- a/compiler/rustc_attr_parsing/src/context.rs +++ b/compiler/rustc_attr_parsing/src/context.rs @@ -12,7 +12,7 @@ use rustc_ast::{AttrStyle, MetaItemLit, Safety}; use rustc_attr_ir::target::Target; use rustc_attr_ir::{AttrPath, Attribute, AttributeKind}; use rustc_data_structures::sync::{DynSend, DynSync}; -use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan}; +use rustc_errors::{Diag, DiagCtxtHandle, DiagLocation, Diagnostic, Level, MultiSpan}; use rustc_feature::AttributeStability; use rustc_lint_defs::builtin::UNUSED_ATTRIBUTES; use rustc_lint_defs::{Lint, LintId}; @@ -416,15 +416,21 @@ impl<'f, 'sess: 'f> SharedContext<'f, 'sess> { /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing /// must be delayed until after HIR is built. This method will take care of the details of /// that. + #[track_caller] pub(crate) fn emit_lint( &mut self, lint: &'static Lint, diagnostic: impl for<'x> Diagnostic<'x> + DynSend + DynSync + 'static, span: impl Into, ) { + let emitted_at = DiagLocation::caller(); self.emit_lint_inner( lint, - EmitAttribute(Box::new(move |dcx, level, _| diagnostic.into_diag(dcx, level))), + EmitAttribute(Box::new(move |dcx, level, _| { + let mut diag = diagnostic.into_diag(dcx, level); + diag.emitted_at = emitted_at; + diag + })), span, ); } diff --git a/compiler/rustc_middle/src/lint.rs b/compiler/rustc_middle/src/lint.rs index 3655d4594aa38..8822ffee65c29 100644 --- a/compiler/rustc_middle/src/lint.rs +++ b/compiler/rustc_middle/src/lint.rs @@ -2,7 +2,7 @@ use std::cmp::min; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::sorted_map::SortedMap; -use rustc_errors::{Diag, DiagLocation, Diagnostic, EmissionOverride, MultiSpan}; +use rustc_errors::{Diag, Diagnostic, EmissionOverride, MultiSpan}; use rustc_hir::{HirId, ItemLocalId}; use rustc_lint_defs::{ EditionFcw, FutureIncompatibilityReason, Level, Lint, LintExpectationId, LintId, @@ -494,8 +494,6 @@ pub fn emit_lint_base<'a, D: Diagnostic<'a> + 'a>( } else { Diag::new(sess.dcx(), err_level, "") }; - // FIXME: Find a nicer way to expose the `DiagLocation` - err.emitted_at = DiagLocation::caller(); if let Some(span) = span && err.span.primary_span().is_none() diff --git a/src/tools/clippy/clippy_utils/src/diagnostics.rs b/src/tools/clippy/clippy_utils/src/diagnostics.rs index e063b3d6cc632..922e965bbb06e 100644 --- a/src/tools/clippy/clippy_utils/src/diagnostics.rs +++ b/src/tools/clippy/clippy_utils/src/diagnostics.rs @@ -8,7 +8,7 @@ //! Thank you! //! ~The `INTERNAL_METADATA_COLLECTOR` lint -use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagMessage, Diagnostic, Level, MultiSpan}; +use rustc_errors::{Applicability, Diag, DiagCtxtHandle, DiagLocation, DiagMessage, Diagnostic, Level, MultiSpan}; #[cfg(debug_assertions)] use rustc_errors::{SubstitutionPart, Suggestions}; use rustc_hir::HirId; @@ -251,12 +251,15 @@ where } let sp = sp.into(); + let emitted_at = DiagLocation::caller(); + #[expect(clippy::disallowed_methods)] cx.emit_span_lint( lint, sp.clone(), ClippyDiag(|diag: &mut Diag<'_>| { diag.primary_message(msg); + diag.emitted_at = emitted_at; diag.span(sp); f(diag); docs_link(diag, lint); @@ -329,6 +332,8 @@ pub fn span_lint_hir_and_then( msg: impl Into, f: impl FnOnce(&mut Diag<'_>), ) { + let emitted_at = DiagLocation::caller(); + #[expect(clippy::disallowed_methods)] cx.tcx.emit_node_span_lint( lint, @@ -336,6 +341,7 @@ pub fn span_lint_hir_and_then( sp, rustc_errors::DiagDecorator(|diag| { diag.primary_message(msg); + diag.emitted_at = emitted_at; f(diag); docs_link(diag, lint); diff --git a/tests/ui/track-diagnostics/track8.rs b/tests/ui/track-diagnostics/track8.rs index 13fe959a30ed5..6690d8fca63df 100644 --- a/tests/ui/track-diagnostics/track8.rs +++ b/tests/ui/track-diagnostics/track8.rs @@ -1,12 +1,23 @@ //@ compile-flags: -Z track-diagnostics +//@ forbid-output:interface //@ dont-require-annotations: NOTE +#![warn(unreachable_cfg_select_predicates)] // Normalize the emitted location so this doesn't need // updating everytime someone adds or removes a line. //@ normalize-stderr: ".rs:\d+:\d+" -> ".rs:LL:CC" //@ normalize-stderr: "/rustc(?:-dev)?/[a-z0-9.]+/" -> "" -#![crate_type = "lib"] -#[repr] //~ ERROR: malformed `repr` attribute input +cfg_select!{ + _ => {}, + _ => {}, //~ WARN unreachable configuration predicate +} + +#[repr(ferris)] //~ ERROR: malformed `repr` attribute input #[diagnostic::ferris] //~ WARN unknown diagnostic attribute -pub mod empty {} \ No newline at end of file +#[doc(ferris)] //~ WARN unknown `doc` attribute `ferris` +fn main(){ + // Also check locations for buffered lints + #[doc(ferris)] //~ WARN unknown `doc` attribute `ferris` + println!(); +} diff --git a/tests/ui/track-diagnostics/track8.stderr b/tests/ui/track-diagnostics/track8.stderr index fdc33519e3cf0..8a729ca91eb32 100644 --- a/tests/ui/track-diagnostics/track8.stderr +++ b/tests/ui/track-diagnostics/track8.stderr @@ -1,8 +1,34 @@ +warning: unreachable configuration predicate + --> $DIR/track8.rs:LL:CC + | +LL | _ => {}, + | - always matches +LL | _ => {}, + | ^ this configuration predicate is never reached + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/cfg_select.rs:LL:CC +note: the lint level is defined here + --> $DIR/track8.rs:LL:CC + | +LL | #![warn(unreachable_cfg_select_predicates)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +warning: unknown `doc` attribute `ferris` + --> $DIR/track8.rs:LL:CC + | +LL | #[doc(ferris)] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/doc.rs:LL:CC + = note: `#[warn(invalid_doc_attributes)]` on by default + error[E0539]: malformed `repr` attribute input --> $DIR/track8.rs:LL:CC | -LL | #[repr] - | ^^^^ expected this to be a list +LL | #[repr(ferris)] + | ^^^^^------^ + | | + | valid arguments are `align`, `packed`, `Rust`, `C`, `simd`, `transparent`, `i8`, `u8`, `i16`, `u16`, `i32`, `u32`, `i64`, `u64`, `i128`, `u128`, `isize` or `usize` | = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/repr.rs:LL:CC = note: for more information, visit @@ -13,9 +39,17 @@ warning: unknown diagnostic attribute LL | #[diagnostic::ferris] | ^^^^^^ | - = note: -Ztrack-diagnostics: created at compiler/rustc_interface/src/passes.rs:LL:CC + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/diagnostic/mod.rs:LL:CC = note: `#[warn(unknown_diagnostic_attributes)]` (part of `#[warn(unknown_or_malformed_diagnostic_attributes)]`) on by default -error: aborting due to 1 previous error; 1 warning emitted +warning: unknown `doc` attribute `ferris` + --> $DIR/track8.rs:LL:CC + | +LL | #[doc(ferris)] + | ^^^^^^ + | + = note: -Ztrack-diagnostics: created at compiler/rustc_attr_parsing/src/attributes/doc.rs:LL:CC + +error: aborting due to 1 previous error; 4 warnings emitted For more information about this error, try `rustc --explain E0539`. From 9aa65cd49e0c76c499bf0b7a0ac4b80cab6acaf2 Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 14:49:21 -0500 Subject: [PATCH 1267/1309] Document panics --- library/core/src/fmt/builders.rs | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 6a44f9ef5374e..c148c2873a90e 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -1075,8 +1075,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1136,6 +1137,12 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::key`], but formats the /// key using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` @@ -1179,8 +1186,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// @@ -1229,6 +1237,12 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// This method is equivalent to [`DebugMap::value`], but formats the /// value using a provided closure rather than by calling [`Debug::fmt`]. /// + /// # Panics + /// + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. + /// /// # Examples /// /// ``` @@ -1359,8 +1373,9 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// /// # Panics /// - /// `key` must be called before `value` and each call to `key` must be followed - /// by a corresponding call to `value`. Otherwise this method will panic. + /// `key` or `key_with` must be called before `value` or `value_with`, and each + /// `key` call must be followed by a corresponding `value` call. Otherwise this + /// method will panic. /// /// # Examples /// From b47661be5fe3b572912e74a8dec54818a4b3a504 Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 14:12:14 -0500 Subject: [PATCH 1268/1309] Replace type parameters with APIT --- library/core/src/fmt/builders.rs | 54 +++++++++++++++----------------- 1 file changed, 26 insertions(+), 28 deletions(-) diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index c148c2873a90e..5f973eee8bc9e 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -212,10 +212,11 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, name: &str, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn field_with( + &mut self, + name: &str, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.field(name, &DebugOnce(Cell::new(Some(value_fmt)))) } @@ -430,10 +431,10 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn field_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn field_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.field(&DebugOnce(Cell::new(Some(value_fmt)))) } @@ -552,10 +553,7 @@ impl<'a, 'b: 'a> DebugInner<'a, 'b> { self.has_fields = true; } - fn entry_with(&mut self, entry_fmt: F) - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + fn entry_with(&mut self, entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result) { self.entry(&DebugOnce(Cell::new(Some(entry_fmt)))); } @@ -661,10 +659,10 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.inner.entry_with(entry_fmt); self } @@ -878,10 +876,10 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn entry_with(&mut self, entry_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn entry_with( + &mut self, + entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.inner.entry_with(entry_fmt); self } @@ -1171,10 +1169,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn key_with(&mut self, key_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn key_with( + &mut self, + key_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.key(&DebugOnce(Cell::new(Some(key_fmt)))) } @@ -1271,10 +1269,10 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// ); /// ``` #[unstable(feature = "debug_closure_helpers", issue = "117729")] - pub fn value_with(&mut self, value_fmt: F) -> &mut Self - where - F: FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, - { + pub fn value_with( + &mut self, + value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, + ) -> &mut Self { self.value(&DebugOnce(Cell::new(Some(value_fmt)))) } From 384b61a67afcdd1c45c0454c36f6bdb1a8033ec9 Mon Sep 17 00:00:00 2001 From: Noa Date: Wed, 23 Sep 2026 13:36:42 -0500 Subject: [PATCH 1269/1309] Stabilize `debug_closure_helpers` --- compiler/rustc_middle/src/lib.rs | 2 +- compiler/rustc_parse/src/lib.rs | 2 +- library/core/src/fmt/builders.rs | 24 ++++++------------------ library/coretests/tests/lib.rs | 1 - 4 files changed, 8 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs index d964faa30b1f8..695eca6225858 100644 --- a/compiler/rustc_middle/src/lib.rs +++ b/compiler/rustc_middle/src/lib.rs @@ -27,6 +27,7 @@ // tidy-alphabetical-start #![allow(internal_features)] #![allow(rustc::direct_use_of_rustc_type_ir)] +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(doc, feature(intra_doc_pointers))] #![feature(allocator_ext)] #![feature(associated_type_defaults)] @@ -34,7 +35,6 @@ #![feature(const_default)] #![feature(const_trait_impl)] #![feature(core_intrinsics)] -#![feature(debug_closure_helpers)] #![feature(decl_macro)] #![feature(default_field_values)] #![feature(deref_patterns)] diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs index 8a73215351aea..edd280743e437 100644 --- a/compiler/rustc_parse/src/lib.rs +++ b/compiler/rustc_parse/src/lib.rs @@ -1,8 +1,8 @@ //! The main parser interface. // tidy-alphabetical-start +#![cfg_attr(bootstrap, feature(debug_closure_helpers))] #![cfg_attr(test, feature(iter_order_by))] -#![feature(debug_closure_helpers)] #![feature(default_field_values)] #![feature(deref_patterns)] #![feature(iter_intersperse)] diff --git a/library/core/src/fmt/builders.rs b/library/core/src/fmt/builders.rs index 5f973eee8bc9e..20ce752dd7c41 100644 --- a/library/core/src/fmt/builders.rs +++ b/library/core/src/fmt/builders.rs @@ -187,8 +187,6 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Bar { @@ -211,7 +209,7 @@ impl<'a, 'b: 'a> DebugStruct<'a, 'b> { /// r#"Bar { bar: 0x0000000a, another: "Hello World" }"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn field_with( &mut self, name: &str, @@ -409,8 +407,6 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(i32, String); @@ -430,7 +426,7 @@ impl<'a, 'b: 'a> DebugTuple<'a, 'b> { /// r#"Foo(0x0000000a, "Hello World")"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn field_with( &mut self, value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -637,8 +633,6 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -658,7 +652,7 @@ impl<'a, 'b: 'a> DebugSet<'a, 'b> { /// "{[10, 11], {12, 13}}", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn entry_with( &mut self, entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -854,8 +848,6 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec, Vec); @@ -875,7 +867,7 @@ impl<'a, 'b: 'a> DebugList<'a, 'b> { /// "[[10, 11], {12, 13}]", /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn entry_with( &mut self, entry_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -1144,8 +1136,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1168,7 +1158,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn key_with( &mut self, key_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, @@ -1244,8 +1234,6 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// # Examples /// /// ``` - /// #![feature(debug_closure_helpers)] - /// /// use std::fmt; /// /// struct Foo(Vec<(String, i32)>); @@ -1268,7 +1256,7 @@ impl<'a, 'b: 'a> DebugMap<'a, 'b> { /// r#"{entry A: 0x0000000a, entry B: 0x0000000b}"#, /// ); /// ``` - #[unstable(feature = "debug_closure_helpers", issue = "117729")] + #[stable(feature = "debug_closure_helpers", since = "CURRENT_RUSTC_VERSION")] pub fn value_with( &mut self, value_fmt: impl FnOnce(&mut fmt::Formatter<'_>) -> fmt::Result, diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs index 9b623d1c5d25b..1fdb0c820d662 100644 --- a/library/coretests/tests/lib.rs +++ b/library/coretests/tests/lib.rs @@ -47,7 +47,6 @@ #![feature(core_io_borrowed_buf)] #![feature(core_private_bignum)] #![feature(core_private_diy_float)] -#![feature(debug_closure_helpers)] #![feature(dec2flt)] #![feature(duration_constants)] #![feature(duration_constructors)] From 1d7bfc70119462b6f8329518e53ac969bd4a2d2d Mon Sep 17 00:00:00 2001 From: Mend Renovate Date: Mon, 5 Oct 2026 00:25:18 +0000 Subject: [PATCH 1270/1309] Update GitHub Actions to v26 --- .github/workflows/ci.yml | 4 ++-- .github/workflows/ghcr.yml | 2 +- .github/workflows/post-merge.yml | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index f6f663477bc06..c0f896724ae56 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -46,7 +46,7 @@ jobs: # If you want to modify CI jobs, take a look at src/ci/github-actions/jobs.yml. calculate_matrix: name: Calculate job matrix - runs-on: ubuntu-24.04-arm + runs-on: ubuntu-26.04-arm outputs: jobs: ${{ steps.jobs.outputs.jobs }} run_type: ${{ steps.jobs.outputs.run_type }} @@ -309,7 +309,7 @@ jobs: # This job is used to publish toolstate for successful auto builds. outcome: name: publish toolstate - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 needs: [ calculate_matrix, job ] if: ${{ needs.calculate_matrix.outputs.run_type == 'auto' }} environment: ${{ (github.repository == 'rust-lang/rust' && 'bors') || '' }} diff --git a/.github/workflows/ghcr.yml b/.github/workflows/ghcr.yml index 2cc67b822ccfc..f0f0ece750b9f 100644 --- a/.github/workflows/ghcr.yml +++ b/.github/workflows/ghcr.yml @@ -23,7 +23,7 @@ on: jobs: mirror: name: DockerHub mirror - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 if: github.repository == 'rust-lang/rust' permissions: # Needed to write to the ghcr.io registry diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml index 0d78d0774185f..7200aa22a4162 100644 --- a/.github/workflows/post-merge.yml +++ b/.github/workflows/post-merge.yml @@ -10,7 +10,7 @@ on: jobs: analysis: - runs-on: ubuntu-24.04 + runs-on: ubuntu-26.04 if: github.repository == 'rust-lang/rust' permissions: pull-requests: write From a9b28d3401d7d8df6b9d78359658e1a4695d966b Mon Sep 17 00:00:00 2001 From: Ben Kimock Date: Sun, 4 Oct 2026 22:39:14 -0400 Subject: [PATCH 1271/1309] Skip optional asserts in SsaRangePropagation --- .../rustc_mir_transform/src/ssa_range_prop.rs | 8 ++- ...on_arith_overflow.SsaRangePropagation.diff | 54 +++++++++++++++++++ tests/mir-opt/range/ssa_range.rs | 9 ++++ 3 files changed, 69 insertions(+), 2 deletions(-) create mode 100644 tests/mir-opt/range/ssa_range.on_arith_overflow.SsaRangePropagation.diff diff --git a/compiler/rustc_mir_transform/src/ssa_range_prop.rs b/compiler/rustc_mir_transform/src/ssa_range_prop.rs index 79c6868bf87c2..f3f34ce11fe1a 100644 --- a/compiler/rustc_mir_transform/src/ssa_range_prop.rs +++ b/compiler/rustc_mir_transform/src/ssa_range_prop.rs @@ -155,12 +155,16 @@ impl<'tcx> MutVisitor<'tcx> for RangeSet<'tcx, '_, '_> { fn visit_terminator(&mut self, terminator: &mut Terminator<'tcx>, location: Location) { self.super_terminator(terminator, location); match &terminator.kind { - TerminatorKind::Assert { cond, expected, target, .. } + TerminatorKind::Assert { cond, expected, target, msg, .. } if let Some(place) = cond.place() && self.is_ssa(place) => { let successor = Location { block: *target, statement_index: 0 }; - if location.strictly_dominates(successor, &self.dominators) { + if location.strictly_dominates(successor, &self.dominators) + // Don't propagate range information from built-in overflow checks, + // this MIR might be lowered without them! + && !msg.is_optional_overflow_check() + { let val = *expected as u128; let range = WrappingRange { start: val, end: val }; self.insert_range(place, successor, range); diff --git a/tests/mir-opt/range/ssa_range.on_arith_overflow.SsaRangePropagation.diff b/tests/mir-opt/range/ssa_range.on_arith_overflow.SsaRangePropagation.diff new file mode 100644 index 0000000000000..c281cabb57ea8 --- /dev/null +++ b/tests/mir-opt/range/ssa_range.on_arith_overflow.SsaRangePropagation.diff @@ -0,0 +1,54 @@ +- // MIR for `on_arith_overflow` before SsaRangePropagation ++ // MIR for `on_arith_overflow` after SsaRangePropagation + + fn on_arith_overflow(_1: u32, _2: u32) -> bool { + debug a => _1; + debug b => _2; + let mut _0: bool; + let mut _3: u32; + let mut _4: u32; + let mut _5: u32; + let mut _6: (u32, bool); + let mut _7: u32; + let mut _8: u32; + scope 1 { + scope 3 (inlined core::num::::overflowing_add) { + scope 4 { + } + } + } + scope 2 (inlined #[track_caller] ::add) { + let mut _9: (u32, bool); + } + + bb0: { + StorageLive(_3); + StorageLive(_4); + _4 = copy _1; + StorageLive(_5); + _5 = copy _2; + nop; + _9 = AddWithOverflow(copy _1, copy _2); + assert(!copy (_9.1: bool), "attempt to compute `{} + {}`, which would overflow", copy _1, copy _2) -> [success: bb1, unwind unreachable]; + } + + bb1: { + _3 = copy (_9.0: u32); + nop; + StorageDead(_5); + StorageDead(_4); + StorageDead(_3); + StorageLive(_6); + StorageLive(_7); + _7 = copy _1; + StorageLive(_8); + _8 = copy _2; + _6 = copy _9; + StorageDead(_8); + StorageDead(_7); + _0 = copy (_9.1: bool); + StorageDead(_6); + return; + } + } + diff --git a/tests/mir-opt/range/ssa_range.rs b/tests/mir-opt/range/ssa_range.rs index c8440a10a4082..29d955f4a4816 100644 --- a/tests/mir-opt/range/ssa_range.rs +++ b/tests/mir-opt/range/ssa_range.rs @@ -78,3 +78,12 @@ pub fn on_if_2(a: bool) -> bool { } } } + +// EMIT_MIR ssa_range.on_arith_overflow.SsaRangePropagation.diff +pub fn on_arith_overflow(a: u32, b: u32) -> bool { + // CHECK-LABEL: fn on_arith_overflow( + // CHECK: assert(!copy ([[FLAG:.*]].1: bool) + // CHECK: _0 = copy ([[FLAG]].1: bool); + let _ = std::ops::Add::add(a, b); + a.overflowing_add(b).1 +} From 4bfa46e1eb37c31d3719bd18bb6ca3d315f9bd67 Mon Sep 17 00:00:00 2001 From: Walnut <39544927+Walnut356@users.noreply.github.com> Date: Mon, 5 Oct 2026 00:36:20 -0500 Subject: [PATCH 1272/1309] bump Windows CI LLVM to 22.1.8 --- src/ci/scripts/install-clang.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh index 75e8fc240660d..2647fc225c9ab 100755 --- a/src/ci/scripts/install-clang.sh +++ b/src/ci/scripts/install-clang.sh @@ -11,7 +11,7 @@ source "$(cd "$(dirname "$0")" && pwd)/../shared.sh" # Update Windows's tarballs when bumping the version here. # Try to keep this in sync with src/ci/docker/scripts/build-clang.sh -LLVM_VERSION="20.1.3" +LLVM_VERSION="22.1.8" if isWindows && ! isKnownToBeMingwBuild; then # If we're compiling for MSVC then we, like most other distribution builders, From 58eda6ec6775da8f47d119d73bc1d88a4b8f1cd1 Mon Sep 17 00:00:00 2001 From: Zalathar Date: Fri, 2 Oct 2026 16:36:37 +1000 Subject: [PATCH 1273/1309] Use `LLVMGlobalAddMetadata` This function was added in LLVM 22. --- compiler/rustc_codegen_llvm/src/context.rs | 4 ++-- compiler/rustc_codegen_llvm/src/llvm/ffi.rs | 11 +++++------ compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp | 5 ----- 3 files changed, 7 insertions(+), 13 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/context.rs b/compiler/rustc_codegen_llvm/src/context.rs index d64c8de6ed7aa..1059de3c0aec0 100644 --- a/compiler/rustc_codegen_llvm/src/context.rs +++ b/compiler/rustc_codegen_llvm/src/context.rs @@ -1234,7 +1234,7 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { /// Helper method for the sequence of calls: /// - `LLVMMDNodeInContext2` (to create an `llvm::MDNode` from a list of metadata) - /// - `LLVMRustGlobalAddMetadata` (to set that node as metadata of `kind_id` for `global`) + /// - `LLVMGlobalAddMetadata` (to set that node as metadata of `kind_id` for `global`) pub(crate) fn global_add_metadata_node( &self, global: &'ll Value, @@ -1242,7 +1242,7 @@ impl<'ll, CX: Borrow>> GenericCx<'ll, CX> { md_list: &[&'ll Metadata], ) { let md = self.md_node_in_context(md_list); - unsafe { llvm::LLVMRustGlobalAddMetadata(global, kind_id, md) }; + unsafe { llvm::LLVMGlobalAddMetadata(global, kind_id, md) }; } /// Helper method for the sequence of calls: diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs index 4c7d60a0cbf67..f576f29a17cca 100644 --- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs +++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs @@ -993,6 +993,11 @@ unsafe extern "C" { KindID: MetadataKindId, Metadata: &'a Metadata, ); + pub(crate) fn LLVMGlobalAddMetadata<'ll>( + Global: &'ll Value, + Kind: MetadataKindId, + MD: &'ll Metadata, + ); pub(crate) safe fn LLVMValueAsMetadata(Node: &Value) -> &Metadata; // Operations on constants of any type @@ -1968,12 +1973,6 @@ unsafe extern "C" { pub(crate) fn LLVMRustDisableSystemDialogsOnCrash(); // Operations on all values - /// FIXME: After dropping LLVM 21, migrate to LLVM-C's `LLVMGlobalAddMetadata`. - pub(crate) fn LLVMRustGlobalAddMetadata<'a>( - Val: &'a Value, - KindID: MetadataKindId, - Metadata: &'a Metadata, - ); pub(crate) fn LLVMRustIsNonGVFunctionPointerTy(Val: &Value) -> bool; pub(crate) fn LLVMRustStripPointerCasts<'a>(Val: &'a Value) -> &'a Value; diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp index 4b14392db2c94..62aa8c5c57aae 100644 --- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp +++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp @@ -1002,11 +1002,6 @@ extern "C" void LLVMRustRemoveFnAttribute(LLVMValueRef Fn, const char *Name, } } -extern "C" void LLVMRustGlobalAddMetadata(LLVMValueRef Global, unsigned Kind, - LLVMMetadataRef MD) { - unwrap(Global)->addMetadata(Kind, *unwrap(MD)); -} - extern "C" LLVMMetadataRef LLVMRustDIBuilderCreateCompileUnit( LLVMDIBuilderRef Builder, unsigned Lang, LLVMMetadataRef FileRef, const char *Producer, size_t ProducerLen, bool isOptimized, From 2d0258e0d1b4b6c3579dd7bcefaf32be2db36094 Mon Sep 17 00:00:00 2001 From: Senthilnathan Date: Mon, 5 Oct 2026 12:05:52 +0530 Subject: [PATCH 1274/1309] moves rustc_legacy_const_generics checks into attribute parsing --- .../src/attributes/rustc_internal.rs | 44 ++++++++++++++- .../rustc_attr_parsing/src/diagnostics.rs | 35 ++++++++++++ compiler/rustc_passes/src/check_attr.rs | 53 +----------------- compiler/rustc_passes/src/diagnostics.rs | 35 ------------ ...stc_legacy_const_generics-arguments.stderr | 56 +++++++++---------- 5 files changed, 109 insertions(+), 114 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index 11554b437e39b..b76ec0d23e73a 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -1,6 +1,6 @@ use std::path::PathBuf; -use rustc_ast::{LitIntType, LitKind, MetaItemLit}; +use rustc_ast::{GenericParamKind, ItemKind, LitIntType, LitKind, MetaItemLit}; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::{ BorrowckGraphvizFormatKind, CguFields, CguKind, RustcCleanAttribute, RustcCleanQueries, @@ -169,6 +169,48 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { attr_span: cx.attr_span, }) } + + fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + if cx.target != Target::Fn { + // Invalid targets are already diagnosed by target checking. + return; + } + let Some(item) = cx.target_item else { return }; + let ItemKind::Fn(function) = &item.kind else { return }; + let Some(index_list) = rustc_attr_ir::find_attr!(cx.parsed_attrs, RustcLegacyConstGenerics { fn_indexes, .. } => fn_indexes) + else { + return; + }; + let generics = &function.generics; + + for param in &generics.params { + if !matches!(param.kind, GenericParamKind::Const { .. }) { + cx.emit_err(diagnostics::RustcLegacyConstGenericsOnly { + attr_span, + param_span: param.span(), + }); + return; + } + } + + if index_list.len() != generics.params.len() { + cx.emit_err(diagnostics::RustcLegacyConstGenericsIndex { + attr_span, + generics_span: generics.span, + }); + return; + } + + let arg_count = function.sig.decl.inputs.len() + generics.params.len(); + for (index, span) in index_list { + if *index >= arg_count { + cx.emit_err(diagnostics::RustcLegacyConstGenericsIndexExceed { + span: *span, + arg_count, + }); + } + } + } } pub(crate) struct RustcInheritOverflowChecksParser; diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index df426cb5e19f5..1ad619af985a3 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -12,6 +12,41 @@ use rustc_target::spec::TargetTuple; use crate::AttributeTemplate; use crate::context::Suggestion; +#[derive(Diagnostic)] +#[diag("#[rustc_legacy_const_generics] functions must only have const generics")] +pub(crate) struct RustcLegacyConstGenericsOnly { + #[primary_span] + pub attr_span: Span, + #[label("non-const generic parameter")] + pub param_span: Span, +} + +#[derive(Diagnostic)] +#[diag("#[rustc_legacy_const_generics] must have one index for each generic parameter")] +pub(crate) struct RustcLegacyConstGenericsIndex { + #[primary_span] + pub attr_span: Span, + #[label("generic parameters")] + pub generics_span: Span, +} + +#[derive(Diagnostic)] +#[diag("index exceeds number of arguments")] +pub(crate) struct RustcLegacyConstGenericsIndexExceed { + #[primary_span] + #[label( + "there {$arg_count -> + [one] is + *[other] are + } only {$arg_count} {$arg_count -> + [one] argument + *[other] arguments + }" + )] + pub span: Span, + pub arg_count: usize, +} + #[derive(Diagnostic)] #[diag("`{$name}` attribute cannot be used at crate level")] pub(crate) struct InvalidAttrAtCrateLevel { diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs index bea48e553d236..b7b91420455fc 100644 --- a/compiler/rustc_passes/src/check_attr.rs +++ b/compiler/rustc_passes/src/check_attr.rs @@ -24,8 +24,8 @@ use rustc_hir::def::DefKind; use rustc_hir::def_id::LocalModId; use rustc_hir::intravisit::{self, Visitor}; use rustc_hir::{ - self as hir, CRATE_HIR_ID, Constness, FnSig, ForeignItem, GenericParam, GenericParamKind, - HirId, Item, ItemKind, Mod, Node, ParamName, TraitItem, + self as hir, CRATE_HIR_ID, Constness, ForeignItem, GenericParam, GenericParamKind, HirId, Item, + ItemKind, Mod, Node, ParamName, TraitItem, }; use rustc_lint_defs::builtin::{ CONFLICTING_REPR_HINTS, INVALID_DOC_ATTRIBUTES, MALFORMED_DIAGNOSTIC_ATTRIBUTES, @@ -203,9 +203,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { } AttributeKind::Naked(..) => self.check_naked(hir_id, target), AttributeKind::MayDangle(attr_span) => self.check_may_dangle(hir_id, *attr_span), - AttributeKind::RustcLegacyConstGenerics { attr_span, fn_indexes } => { - self.check_rustc_legacy_const_generics(item, *attr_span, fn_indexes) - } AttributeKind::Doc(attr) => self.check_doc_attrs(attr, hir_id, target), AttributeKind::EiiImpl(eii_impl) => self.check_eii_impl(eii_impl), AttributeKind::RustcMustImplementOneOf { attr_span, fn_names } => { @@ -355,6 +352,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> { AttributeKind::RustcInsignificantDtor => (), AttributeKind::RustcIntrinsic => (), AttributeKind::RustcIntrinsicConstStableIndirect => (), + AttributeKind::RustcLegacyConstGenerics { .. } => (), AttributeKind::RustcLintOptDenyFieldAccess { .. } => (), AttributeKind::RustcLintOptTy => (), AttributeKind::RustcLintQueryInstability => (), @@ -1065,51 +1063,6 @@ impl<'tcx> CheckAttrVisitor<'tcx> { self.dcx().emit_err(diagnostics::InvalidMayDangle { attr_span }); } - /// Checks if `#[rustc_legacy_const_generics]` is applied to a function and has a valid argument. - fn check_rustc_legacy_const_generics( - &self, - item: Option<&'tcx Item<'tcx>>, - attr_span: Span, - index_list: &ThinVec<(usize, Span)>, - ) { - let Some(Item { kind: ItemKind::Fn { sig: FnSig { decl, .. }, generics, .. }, .. }) = item - else { - // No error here, since it's already given by the parser - return; - }; - - for param in generics.params { - match param.kind { - hir::GenericParamKind::Const { .. } => {} - _ => { - self.dcx().emit_err(diagnostics::RustcLegacyConstGenericsOnly { - attr_span, - param_span: param.span, - }); - return; - } - } - } - - if index_list.len() != generics.params.len() { - self.dcx().emit_err(diagnostics::RustcLegacyConstGenericsIndex { - attr_span, - generics_span: generics.span, - }); - return; - } - - let arg_count = decl.inputs.len() + generics.params.len(); - for (index, span) in index_list { - if *index >= arg_count { - self.dcx().emit_err(diagnostics::RustcLegacyConstGenericsIndexExceed { - span: *span, - arg_count, - }); - } - } - } - /// Checks if the `#[repr]` attributes on `item` are valid. fn check_repr( &self, diff --git a/compiler/rustc_passes/src/diagnostics.rs b/compiler/rustc_passes/src/diagnostics.rs index 8e13cb6df15fe..53656d1a63c84 100644 --- a/compiler/rustc_passes/src/diagnostics.rs +++ b/compiler/rustc_passes/src/diagnostics.rs @@ -126,41 +126,6 @@ pub(crate) struct BothOptimizeNoneAndInline { pub inline_span: Span, } -#[derive(Diagnostic)] -#[diag("#[rustc_legacy_const_generics] functions must only have const generics")] -pub(crate) struct RustcLegacyConstGenericsOnly { - #[primary_span] - pub attr_span: Span, - #[label("non-const generic parameter")] - pub param_span: Span, -} - -#[derive(Diagnostic)] -#[diag("#[rustc_legacy_const_generics] must have one index for each generic parameter")] -pub(crate) struct RustcLegacyConstGenericsIndex { - #[primary_span] - pub attr_span: Span, - #[label("generic parameters")] - pub generics_span: Span, -} - -#[derive(Diagnostic)] -#[diag("index exceeds number of arguments")] -pub(crate) struct RustcLegacyConstGenericsIndexExceed { - #[primary_span] - #[label( - "there {$arg_count -> - [one] is - *[other] are - } only {$arg_count} {$arg_count -> - [one] argument - *[other] arguments - }" - )] - pub span: Span, - pub arg_count: usize, -} - #[derive(Diagnostic)] #[diag("conflicting representation hints", code = E0566)] pub(crate) struct ReprConflicting { diff --git a/tests/ui/const-generics/invalid-rustc_legacy_const_generics-arguments.stderr b/tests/ui/const-generics/invalid-rustc_legacy_const_generics-arguments.stderr index 4fe55374f0048..4b5a14017f62f 100644 --- a/tests/ui/const-generics/invalid-rustc_legacy_const_generics-arguments.stderr +++ b/tests/ui/const-generics/invalid-rustc_legacy_const_generics-arguments.stderr @@ -1,3 +1,23 @@ +error: #[rustc_legacy_const_generics] must have one index for each generic parameter + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo1() {} + | - generic parameters + +error: index exceeds number of arguments + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31 + | +LL | #[rustc_legacy_const_generics(1)] + | ^ there is only 1 argument + +error: index exceeds number of arguments + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:9:31 + | +LL | #[rustc_legacy_const_generics(2)] + | ^ there are only 2 arguments + error[E0539]: malformed `rustc_legacy_const_generics` attribute input --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:12:3 | @@ -78,6 +98,14 @@ LL | #[rustc_legacy_const_generics(1)] | = help: the `rustc_legacy_const_generics` attribute can only be applied to functions +error: #[rustc_legacy_const_generics] functions must only have const generics + --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:1 + | +LL | #[rustc_legacy_const_generics(0)] + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | fn foo8() {} + | - non-const generic parameter + error: the `rustc_legacy_const_generics` attribute cannot be used on inherent methods --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:37:7 | @@ -111,34 +139,6 @@ LL - #[rustc_legacy_const_generics = 1] LL + #[rustc_legacy_const_generics(N)] | -error: #[rustc_legacy_const_generics] must have one index for each generic parameter - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:3:1 - | -LL | #[rustc_legacy_const_generics(0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn foo1() {} - | - generic parameters - -error: index exceeds number of arguments - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:6:31 - | -LL | #[rustc_legacy_const_generics(1)] - | ^ there is only 1 argument - -error: index exceeds number of arguments - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:9:31 - | -LL | #[rustc_legacy_const_generics(2)] - | ^ there are only 2 arguments - -error: #[rustc_legacy_const_generics] functions must only have const generics - --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:33:1 - | -LL | #[rustc_legacy_const_generics(0)] - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -LL | fn foo8() {} - | - non-const generic parameter - error[E0044]: foreign items may not have const parameters --> $DIR/invalid-rustc_legacy_const_generics-arguments.rs:30:5 | From b317a6a6f0872129a2470158c01bef206cd82a31 Mon Sep 17 00:00:00 2001 From: Senthilnathan Date: Mon, 5 Oct 2026 12:50:25 +0530 Subject: [PATCH 1275/1309] fixes legacy const generics finalize_check signature --- compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index b76ec0d23e73a..a50a47a49f316 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -170,7 +170,7 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { }) } - fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) { + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, attr_span: Span) { if cx.target != Target::Fn { // Invalid targets are already diagnosed by target checking. return; From 9c4bef50e415950ae48f5b968746a36dcf3d7bf5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Thu, 1 Oct 2026 17:25:13 +0200 Subject: [PATCH 1276/1309] optimize empty `NestedGoals::extend_from_child` --- .../rustc_type_ir/src/search_graph/mod.rs | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs index 228b6c34b06ed..0a6e351dcdf8f 100644 --- a/compiler/rustc_type_ir/src/search_graph/mod.rs +++ b/compiler/rustc_type_ir/src/search_graph/mod.rs @@ -531,12 +531,25 @@ impl NestedGoals { /// to all nested goals of that nested goal are also inductive. Otherwise the paths are /// the same as for the child. fn extend_from_child(&mut self, step_kind: PathKind, nested_goals: &NestedGoals) { - // Each nested goal is updated independently, and `insert` only unions paths for that - // goal, so traversal order cannot affect the result. - #[allow(rustc::potential_query_instability)] - for (input, paths_to_nested) in nested_goals.iter() { - let paths_to_nested = paths_to_nested.extend_with(step_kind); - self.insert(input, paths_to_nested); + if nested_goals.is_empty() { + return; + } + + // Each nested goal is updated independently, so traversal order cannot + // affect the result. + #[expect(rustc::potential_query_instability)] + if self.is_empty() { + // Manually avoid HashMap lookups for every input if there aren't + // any preexisting entries. + self.nested_goals.clone_from(&nested_goals.nested_goals); + for paths_to_nested in self.nested_goals.values_mut() { + *paths_to_nested = paths_to_nested.extend_with(step_kind); + } + } else { + for (input, paths_to_nested) in nested_goals.iter() { + let paths_to_nested = paths_to_nested.extend_with(step_kind); + self.insert(input, paths_to_nested); + } } } From f998e4a5916434ac8b4d85bb0a092ee837307d9d Mon Sep 17 00:00:00 2001 From: Senthilnathan Date: Mon, 5 Oct 2026 14:06:22 +0530 Subject: [PATCH 1277/1309] fix: panic on unreasonable cases instead of going silent --- .../src/attributes/rustc_internal.rs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs index a50a47a49f316..b9c03883d7c0b 100644 --- a/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs +++ b/compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs @@ -175,12 +175,12 @@ impl SingleAttributeParser for RustcLegacyConstGenericsParser { // Invalid targets are already diagnosed by target checking. return; } - let Some(item) = cx.target_item else { return }; - let ItemKind::Fn(function) = &item.kind else { return }; - let Some(index_list) = rustc_attr_ir::find_attr!(cx.parsed_attrs, RustcLegacyConstGenerics { fn_indexes, .. } => fn_indexes) - else { - return; + let item = cx.target_item.expect("missing AST target item for Target::Fn"); + let ItemKind::Fn(function) = &item.kind else { + panic!("expected fn AST target item for Target::Fn"); }; + let index_list = rustc_attr_ir::find_attr!(cx.parsed_attrs, RustcLegacyConstGenerics { fn_indexes, .. } => fn_indexes) + .expect("missing parsed RustcLegacyConstGenerics attribute in finalize_check"); let generics = &function.generics; for param in &generics.params { From 6e4e68f3fcc6687e20a45d954cf0d815b34df21a Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Mon, 5 Oct 2026 11:11:26 +0200 Subject: [PATCH 1278/1309] document rustc_comptime --- compiler/rustc_attr_ir/src/attribute_docs.rs | 42 +++++++++++++++++++ compiler/rustc_attr_ir/src/data_structures.rs | 2 +- .../attributes/doc_examples/rustc_comptime.rs | 19 +++++++++ .../doc_examples/rustc_comptime.stderr | 14 +++++++ 4 files changed, 76 insertions(+), 1 deletion(-) create mode 100644 tests/ui/attributes/doc_examples/rustc_comptime.rs create mode 100644 tests/ui/attributes/doc_examples/rustc_comptime.stderr diff --git a/compiler/rustc_attr_ir/src/attribute_docs.rs b/compiler/rustc_attr_ir/src/attribute_docs.rs index 975594771d3fb..b354e0c075c77 100644 --- a/compiler/rustc_attr_ir/src/attribute_docs.rs +++ b/compiler/rustc_attr_ir/src/attribute_docs.rs @@ -283,3 +283,45 @@ const _: () = (); /// [#156920]:https://github.com/rust-lang/rust/issues/156920 "`dyn Allocator` together with `Allocator + Clone` requirements is unsound, leading to UB with `Arc`" /// [#160045]:https://github.com/rust-lang/rust/issues/160045 "`iter::Rev`'s `TrustedLen` impl is unsound with trait objects" const _: () = (); + +#[doc(attribute = "rustc_comptime")] +/// Marks a function as only callable at compile time. +/// +/// Unlike `const fn`, which *can* be called from a [const context], comptime functions *must* be +/// called from a const context. It is an error to call a comptime function outside a const context. +/// +/// # Example +/// +#[doc = include_example!("rustc_comptime")] +/// +/// There are many things which only have meaning at compile time and can make use of such +/// functions: +/// - the [`type_info`] feature, for compile time type reflection. +/// - the const heap intrinsics [`const_allocate`] and [`const_deallocate`], at runtime, return a null +/// pointer and do nothing respectively. +/// - intrinsics such as [`size_of`] and friends cause an ICE when they are called at runtime. The +/// stabilized versions of these functions forward to these intrinsics via associated constants on +/// the `SizedTypeProperties` trait. +/// +/// At this time, +// < October of 2026 > +/// the primary motivation for comptime functions is the [`type_info`] feature. The constructs +/// in [`mem::type_info`] only makes sense at compile time as during compile time we can simply +/// ask the compiler for whatever information we need. At runtime, though, that cannot be done - to +/// support runtime reflection we would have to create some global table with all the information +/// we might possibly need. This is unfeasible and any (third party wrappers for) "runtime +/// reflection" based on `type_info` would be limited to retrieving information queried in advance +/// at compile time. +/// +/// See the [reflection and comptime project goal] for more information about reflection and +/// comptime. +/// +/// See [`AttributeKind::RustcComptime`] for the internal representation of this attribute. +/// +/// [const context]: https://doc.rust-lang.org/nightly/reference/const_eval.html#const-context +/// [`type_info`]: https://github.com/rust-lang/rust/issues/146922 +/// [`const_allocate`]: std::intrinsics::const_allocate +/// [`const_deallocate`]: std::intrinsics::const_deallocate +/// [`mem::type_info`]: std::mem::type_info +/// [reflection and comptime project goal]: https://goals.rust-lang.org/2026/reflection-and-comptime.html +const _: () = (); diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 55c0bedb9c39c..f3c1dba5206e0 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -1178,7 +1178,7 @@ pub enum AttributeKind { /// Represents `#[rustc_coinductive]`. RustcCoinductive, - /// Represents `#[rustc_comptime]` + /// Represents the [`rustc_comptime`](./attribute.rustc_comptime.html) attribute. RustcComptime(Span), /// Represents `#[rustc_confusables]`. diff --git a/tests/ui/attributes/doc_examples/rustc_comptime.rs b/tests/ui/attributes/doc_examples/rustc_comptime.rs new file mode 100644 index 0000000000000..06964912dddee --- /dev/null +++ b/tests/ui/attributes/doc_examples/rustc_comptime.rs @@ -0,0 +1,19 @@ +//@ dont-require-annotations: ERROR +//@ compile-flags: --crate-type lib -Z ui-testing=no + +#![feature(rustc_attrs)] + +#[rustc_comptime] +fn comptime() {} + +fn from_runtime() { + comptime(); // ERROR + + const { comptime() }; // OK +} + +// comptime functions cannot be called from const +// functions, as these may be called at runtime +const fn const_or_runtime() { + comptime(); +} diff --git a/tests/ui/attributes/doc_examples/rustc_comptime.stderr b/tests/ui/attributes/doc_examples/rustc_comptime.stderr new file mode 100644 index 0000000000000..20dd2597d929e --- /dev/null +++ b/tests/ui/attributes/doc_examples/rustc_comptime.stderr @@ -0,0 +1,14 @@ +error: comptime fns can only be called at compile time + --> $DIR/rustc_comptime.rs:10:5 + | +10 | comptime(); // ERROR + | ^^^^^^^^^^ + +error: comptime fns can only be called at compile time + --> $DIR/rustc_comptime.rs:18:5 + | +18 | comptime(); + | ^^^^^^^^^^ + +error: aborting due to 2 previous errors + From d9d979c510f457251755ff25933deba9a6c5fe3d Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 5 Oct 2026 12:04:23 +0200 Subject: [PATCH 1279/1309] When documenting without a specified `--edition`, emit a message --- src/librustdoc/config.rs | 4 +--- tests/run-make/unspecified-edition/rmake.rs | 10 +++++----- .../rustdoc-unspecified-edition.stderr | 2 ++ 3 files changed, 8 insertions(+), 8 deletions(-) create mode 100644 tests/run-make/unspecified-edition/rustdoc-unspecified-edition.stderr diff --git a/src/librustdoc/config.rs b/src/librustdoc/config.rs index 170352dabf656..ebf488fcb31b5 100644 --- a/src/librustdoc/config.rs +++ b/src/librustdoc/config.rs @@ -777,9 +777,7 @@ impl Options { } } - // We don't want rustdoc invocations to complain about the lack of `--edition`. - let has_input = false; - let edition = config::parse_crate_edition(early_dcx, matches, has_input); + let edition = config::parse_crate_edition(early_dcx, matches, true); let mut id_map = html::markdown::IdMap::new(); let Some(external_html) = ExternalHtml::load( diff --git a/tests/run-make/unspecified-edition/rmake.rs b/tests/run-make/unspecified-edition/rmake.rs index d20ac26b8e71d..cabad1b66988a 100644 --- a/tests/run-make/unspecified-edition/rmake.rs +++ b/tests/run-make/unspecified-edition/rmake.rs @@ -17,17 +17,17 @@ fn main() { .actual_text("(rustc)", &out) .run(); - // Ensure that we dont mention --edition when running rustdoc. + rustdoc().edition("2015").input("main.rs").run().assert_stderr_not_contains("--edition"); + let out = rustdoc().input("main.rs").run().assert_stderr_contains("--edition").stderr_utf8(); + diff().expected_file("rustdoc-unspecified-edition.stderr").actual_text("(rustc)", &out).run(); + + // Ensure that we only mention --edition when documenting. let out = rustdoc().run_fail().assert_stderr_not_contains("--edition").stderr_utf8(); diff() .expected_text("(test)", "error: missing file operand\n\n") .actual_text("(rustc)", &out) .run(); - let out = - rustdoc().input("main.rs").run().assert_stderr_not_contains("--edition").stderr_utf8(); - diff().expected_text("(test)", "").actual_text("(rustc)", &out).run(); - // Ensure that we don't mention --edition when getting help. let result = bare_rustc().arg("--help").run(); result.assert_stderr_not_contains("--edition"); diff --git a/tests/run-make/unspecified-edition/rustdoc-unspecified-edition.stderr b/tests/run-make/unspecified-edition/rustdoc-unspecified-edition.stderr new file mode 100644 index 0000000000000..0a15e47d49fae --- /dev/null +++ b/tests/run-make/unspecified-edition/rustdoc-unspecified-edition.stderr @@ -0,0 +1,2 @@ +`--edition` is unspecified, defaulting to `2015` while the latest is `2024`; it must be one of: <2015|2018|2021|2024|future> + From f20f0c4862bb3deb5c47b7c26ad194982d5e505c Mon Sep 17 00:00:00 2001 From: Abhinav Srivastav Date: Wed, 30 Sep 2026 14:08:23 +0530 Subject: [PATCH 1280/1309] rustc_ast_lowering: track implicit Self via explicit flag instead of name --- .../src/delegation/generics.rs | 58 ++++++++++++++----- .../ui/delegation/arg-must-exist-for-infer.rs | 15 +++++ .../arg-must-exist-for-infer.stderr | 17 ++++++ 3 files changed, 76 insertions(+), 14 deletions(-) create mode 100644 tests/ui/delegation/arg-must-exist-for-infer.rs create mode 100644 tests/ui/delegation/arg-must-exist-for-infer.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index 836bf7df2bbd5..cdec2f5312ae2 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -35,6 +35,7 @@ pub(super) struct DelegationGenerics { data: T, pos: GenericsPosition, trait_impl: bool, + has_implicit_self: bool, } type TyGenerics<'hir> = Vec>; @@ -44,11 +45,13 @@ impl<'hir> DelegationGenerics> { params: &'hir [ty::GenericParamDef], pos: GenericsPosition, trait_impl: bool, + has_implicit_self: bool, ) -> Self { DelegationGenerics { data: params.iter().map(|p| GenericArgSlot::Generate(p, None)).collect(), pos, trait_impl, + has_implicit_self, } } } @@ -92,6 +95,7 @@ pub(super) struct GenericsGenerationResults<'hir> { pub(super) struct DelegationGenericArgsIterator<'hir> { index: usize = Default::default(), params: &'hir [hir::GenericParam<'hir>], + has_implicit_self: bool, } /// During generic args propagation we need to create generic args @@ -112,10 +116,10 @@ impl<'hir> DelegationGenericArgsIterator<'hir> { } let p = self.params[self.index]; + let is_implicit_self = self.has_implicit_self && self.index == 0; self.index += 1; - // Skip self generic arg, we do not need to propagate it. - if p.name.ident().name == kw::SelfUpper || p.is_impl_trait() { + if is_implicit_self || p.is_impl_trait() { continue; } @@ -173,6 +177,7 @@ impl<'hir> HirOrTyGenerics<'hir> { data: params, pos: ty.pos, trait_impl: ty.trait_impl, + has_implicit_self: ty.has_implicit_self, }); } } @@ -189,9 +194,11 @@ impl<'hir> HirOrTyGenerics<'hir> { HirOrTyGenerics::Ty(_) => { bug!("attempting to get generic args before uplifting to HIR") } - HirOrTyGenerics::Hir(hir) => { - DelegationGenericArgsIterator { params: hir.data.params, .. } - } + HirOrTyGenerics::Hir(hir) => DelegationGenericArgsIterator { + params: hir.data.params, + has_implicit_self: hir.has_implicit_self, + .. + }, } } @@ -380,13 +387,21 @@ impl<'hir> DelegationResolver<'_, 'hir> { if trait_impl { // Considering parent generics, during signature inheritance // we will take those args that are in trait impl header trait ref. - let parent = - DelegationGenerics { data: vec![], pos: GenericsPosition::Child, trait_impl: true }; + let parent = DelegationGenerics { + data: vec![], + pos: GenericsPosition::Child, + trait_impl: true, + has_implicit_self: false, + }; let parent = GenericsGenerationResult::new(parent); - let child = - DelegationGenerics::generate_all(sig_child_params, GenericsPosition::Child, true); + let child = DelegationGenerics::generate_all( + sig_child_params, + GenericsPosition::Child, + true, + false, + ); let child = GenericsGenerationResult::new(child); @@ -411,15 +426,20 @@ impl<'hir> DelegationResolver<'_, 'hir> { ), pos: GenericsPosition::Parent, trait_impl, + has_implicit_self: generate_free_to_trait_self, }, ParentSegmentArgs::NotSpecified => DelegationGenerics::generate_all( &sig_parent_params[usize::from(skip_self)..], GenericsPosition::Parent, trait_impl, + generate_free_to_trait_self, ), - ParentSegmentArgs::Invalid => { - DelegationGenerics { data: vec![], pos: GenericsPosition::Parent, trait_impl } - } + ParentSegmentArgs::Invalid => DelegationGenerics { + data: vec![], + pos: GenericsPosition::Parent, + trait_impl, + has_implicit_self: false, + }, }; let child_generics = if let Some(args) = res.child_args { @@ -439,9 +459,19 @@ impl<'hir> DelegationResolver<'_, 'hir> { slots.push(GenericArgSlot::Generate(synth_param, None)); } - DelegationGenerics { data: slots, pos: GenericsPosition::Child, trait_impl } + DelegationGenerics { + data: slots, + pos: GenericsPosition::Child, + trait_impl, + has_implicit_self: false, + } } else { - DelegationGenerics::generate_all(sig_child_params, GenericsPosition::Child, trait_impl) + DelegationGenerics::generate_all( + sig_child_params, + GenericsPosition::Child, + trait_impl, + false, + ) }; Ok(GenericsGenerationResults { diff --git a/tests/ui/delegation/arg-must-exist-for-infer.rs b/tests/ui/delegation/arg-must-exist-for-infer.rs new file mode 100644 index 0000000000000..cd0c4489caa18 --- /dev/null +++ b/tests/ui/delegation/arg-must-exist-for-infer.rs @@ -0,0 +1,15 @@ +#![feature(fn_delegation)] + +struct S; + +trait Trait { + //~^ ERROR expected identifier, found keyword `Self` + fn foo(); +} + +impl S { + reuse Trait::<_>::foo; + //~^ ERROR type annotations needed +} + +fn main() {} diff --git a/tests/ui/delegation/arg-must-exist-for-infer.stderr b/tests/ui/delegation/arg-must-exist-for-infer.stderr new file mode 100644 index 0000000000000..750f139b46e1b --- /dev/null +++ b/tests/ui/delegation/arg-must-exist-for-infer.stderr @@ -0,0 +1,17 @@ +error: expected identifier, found keyword `Self` + --> $DIR/arg-must-exist-for-infer.rs:5:19 + | +LL | trait Trait { + | ^^^^ expected identifier, found keyword + +error[E0283]: type annotations needed + --> $DIR/arg-must-exist-for-infer.rs:11:23 + | +LL | reuse Trait::<_>::foo; + | ^^^ cannot infer type + | + = note: the type must implement `Trait` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0283`. From e95998b41d882ac7d5c099cc6bf86f9b5bb91212 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:11:57 +0200 Subject: [PATCH 1281/1309] continue crashes tests next-solver work --- tests/crashes/102047.rs | 45 ------------------- tests/crashes/119786-1.rs | 15 ------- tests/crashes/119786-2.rs | 15 ------- tests/crashes/119786-3.rs | 15 ------- tests/crashes/155497.rs | 13 ------ .../incomplete-hr-alias-relate-ICE.rs | 37 +++++++++++++++ ...n-closure-capture-ice-119786-1.next.stderr | 13 ++++++ .../in-closure-capture-ice-119786-1.rs | 23 ++++++++++ .../in-closure-capture-ice-119786-2.rs | 23 ++++++++++ .../in-closure-capture-ice-119786-3.rs | 23 ++++++++++ ...atible-closure-captures-field-of-opaque.rs | 27 +++++++++++ 11 files changed, 146 insertions(+), 103 deletions(-) delete mode 100644 tests/crashes/102047.rs delete mode 100644 tests/crashes/119786-1.rs delete mode 100644 tests/crashes/119786-2.rs delete mode 100644 tests/crashes/119786-3.rs delete mode 100644 tests/crashes/155497.rs create mode 100644 tests/ui/associated-types/higher-ranked/incomplete-hr-alias-relate-ICE.rs create mode 100644 tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.next.stderr create mode 100644 tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.rs create mode 100644 tests/ui/impl-trait/closures/in-closure-capture-ice-119786-2.rs create mode 100644 tests/ui/impl-trait/closures/in-closure-capture-ice-119786-3.rs create mode 100644 tests/ui/impl-trait/closures/incompatible-closure-captures-field-of-opaque.rs diff --git a/tests/crashes/102047.rs b/tests/crashes/102047.rs deleted file mode 100644 index 61976f51273fc..0000000000000 --- a/tests/crashes/102047.rs +++ /dev/null @@ -1,45 +0,0 @@ -//@ known-bug: #102047 - -struct Ty1; -struct Ty2; - -pub trait Trait {} - -pub trait WithAssoc1<'a> { - type Assoc; -} -pub trait WithAssoc2<'a> { - type Assoc; -} - -impl Trait fn(>::Assoc, >::Assoc)> for (T, U) -where - T: for<'a> WithAssoc1<'a> + for<'a> WithAssoc2<'a, Assoc = i32>, - U: for<'a> WithAssoc2<'a>, -{ -} - -impl WithAssoc1<'_> for Ty1 { - type Assoc = (); -} -impl WithAssoc2<'_> for Ty1 { - type Assoc = i32; -} -impl WithAssoc1<'_> for Ty2 { - type Assoc = (); -} -impl WithAssoc2<'_> for Ty2 { - type Assoc = u32; -} - -fn foo() -where - T: for<'a> WithAssoc1<'a>, - U: for<'a> WithAssoc2<'a>, - (T, U): Trait, -{ -} - -fn main() { - foo::(); -} diff --git a/tests/crashes/119786-1.rs b/tests/crashes/119786-1.rs deleted file mode 100644 index ca79664d8b74c..0000000000000 --- a/tests/crashes/119786-1.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #119786 -//@ edition:2021 - -fn enum_upvar() { - type T = impl Copy; - let foo: T = Some((1u32, 2u32)); - let x = move || { - match foo { - None => (), - Some(yield) => (), - } - }; -} - -pub fn main() {} diff --git a/tests/crashes/119786-2.rs b/tests/crashes/119786-2.rs deleted file mode 100644 index 76c5deb4605ae..0000000000000 --- a/tests/crashes/119786-2.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #119786 -//@ edition:2021 - -fn enum_upvar() { - type T = impl Copy; - let foo: T = Some((1u32, 2u32)); - let x = move || { - match foo { - None => (), - Some(_) => (), - } - }; -} - -pub fn main() {} diff --git a/tests/crashes/119786-3.rs b/tests/crashes/119786-3.rs deleted file mode 100644 index 34bb90fd0fae3..0000000000000 --- a/tests/crashes/119786-3.rs +++ /dev/null @@ -1,15 +0,0 @@ -//@ known-bug: #119786 -//@ edition:2021 - -fn enum_upvar() { - type T = impl Copy; - let foo: T = Some((1u32, 2u32)); - let x = move || { - match foo { - None => (), - Some((a, b)) => (), - } - }; -} - -pub fn main() {} diff --git a/tests/crashes/155497.rs b/tests/crashes/155497.rs deleted file mode 100644 index ed96c205d08b5..0000000000000 --- a/tests/crashes/155497.rs +++ /dev/null @@ -1,13 +0,0 @@ -//@ known-bug: #155497 -//@ compile-flags: -Wrust-2021-incompatible-closure-captures -struct Foo((u32, i128)); - -fn main() { - type T = impl async FnOnce() -> T; - let foo: T = Foo(); - let x = move || { - let x = move || { - let Foo((a, b)) = foo; - }; - }; -} diff --git a/tests/ui/associated-types/higher-ranked/incomplete-hr-alias-relate-ICE.rs b/tests/ui/associated-types/higher-ranked/incomplete-hr-alias-relate-ICE.rs new file mode 100644 index 0000000000000..61e2da89423c9 --- /dev/null +++ b/tests/ui/associated-types/higher-ranked/incomplete-hr-alias-relate-ICE.rs @@ -0,0 +1,37 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #140211 +//@[next] check-pass + +trait Id { + type This<'a>; +} + +#[derive(Copy, Clone)] +struct W(T); +impl Id for W { + type This<'a> = W; +} +impl Id for W { + type This<'a> = W; +} + +trait Trait {} +// when using this impl we only normalize after instantiating +// with infer vars, at this point `::This<'a>` is still +// ambig, so we keep the alias around and require it to structurally +// relate. +impl Trait fn(T::This<'a>)> for T {} +fn is_trait, U>(_x: T) {} + +fn main() { + let x = W(1); + // We prove `W<_>: Trait fn(>::This<'a>)>` during + // typeck, and `W: Trait fn()>` during borrowck. + // This then fails. + is_trait(x); + let _: W = x; +} diff --git a/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.next.stderr b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.next.stderr new file mode 100644 index 0000000000000..d8be615c1de6c --- /dev/null +++ b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.next.stderr @@ -0,0 +1,13 @@ +error: expected identifier, found reserved keyword `yield` + --> $DIR/in-closure-capture-ice-119786-1.rs:17:18 + | +LL | Some(yield) => (), + | ^^^^^ expected identifier, found reserved keyword + | +help: escape `yield` to use it as an identifier + | +LL | Some(r#yield) => (), + | ++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.rs b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.rs new file mode 100644 index 0000000000000..a523580b96d32 --- /dev/null +++ b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-1.rs @@ -0,0 +1,23 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #119786 +//@ edition:2021 + +#![feature(type_alias_impl_trait)] + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some(yield) => (), + //[next]~^ ERROR: expected identifier, found reserved keyword `yield` + } + }; +} + +pub fn main() {} diff --git a/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-2.rs b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-2.rs new file mode 100644 index 0000000000000..f0afd132a5199 --- /dev/null +++ b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-2.rs @@ -0,0 +1,23 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #119786 +//@[next] check-pass +//@ edition:2021 + +#![feature(type_alias_impl_trait)] + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some(_) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-3.rs b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-3.rs new file mode 100644 index 0000000000000..6b7eb9ec0ac2c --- /dev/null +++ b/tests/ui/impl-trait/closures/in-closure-capture-ice-119786-3.rs @@ -0,0 +1,23 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #119786 +//@[next] check-pass +//@ edition:2021 + +#![feature(type_alias_impl_trait)] + +fn enum_upvar() { + type T = impl Copy; + let foo: T = Some((1u32, 2u32)); + let x = move || { + match foo { + None => (), + Some((a, b)) => (), + } + }; +} + +pub fn main() {} diff --git a/tests/ui/impl-trait/closures/incompatible-closure-captures-field-of-opaque.rs b/tests/ui/impl-trait/closures/incompatible-closure-captures-field-of-opaque.rs new file mode 100644 index 0000000000000..63fea3e13c156 --- /dev/null +++ b/tests/ui/impl-trait/closures/incompatible-closure-captures-field-of-opaque.rs @@ -0,0 +1,27 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #155497 +//@[next] check-pass +//@ compile-flags: -Wrust-2021-incompatible-closure-captures +//@ edition: 2018 + +#![feature(type_alias_impl_trait)] + +// This ICE'd with the old solver the nested closure ended up accessing +// the fields of an opaque type. This caused the lint to then encounter +// an opaque type as the base type, resulting in an ICE. +// +// Regression test for #155497. + +struct Foo(i32); + +fn main() { + type T = impl Sized; + let foo: T = Foo(1); + let x = move || { + let Foo(x) = foo; + }; +} From 8391ea0087ebc337e06cb4b27e7503026ad2b5c1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:26:40 +0200 Subject: [PATCH 1282/1309] more crashes tests --- tests/crashes/102252-2.rs | 21 -------------- tests/crashes/102252.rs | 14 --------- ...xpected-infer-var-ice-102252-2.next.stderr | 14 +++++++++ .../unexpected-infer-var-ice-102252-2.rs | 29 +++++++++++++++++++ ...nexpected-infer-var-ice-102252.next.stderr | 15 ++++++++++ .../unexpected-infer-var-ice-102252.rs | 23 +++++++++++++++ 6 files changed, 81 insertions(+), 35 deletions(-) delete mode 100644 tests/crashes/102252-2.rs delete mode 100644 tests/crashes/102252.rs create mode 100644 tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.next.stderr create mode 100644 tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.rs create mode 100644 tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.next.stderr create mode 100644 tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.rs diff --git a/tests/crashes/102252-2.rs b/tests/crashes/102252-2.rs deleted file mode 100644 index ccb15b82736e2..0000000000000 --- a/tests/crashes/102252-2.rs +++ /dev/null @@ -1,21 +0,0 @@ -//@ known-bug: #102252 - -#![feature(min_specialization)] - -trait Trait {} - -impl Trait for T {} - -trait Data { - type Elem; -} - -struct DatasetIter<'a, R: Data> { - data: &'a R::Elem, -} - -pub struct ArrayBase {} - -impl<'a> Trait for DatasetIter<'a, ArrayBase> {} - -fn main() {} diff --git a/tests/crashes/102252.rs b/tests/crashes/102252.rs deleted file mode 100644 index 200782f95c861..0000000000000 --- a/tests/crashes/102252.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: #102252 - -#![feature(min_specialization, rustc_attrs)] - -#[rustc_specialization_trait] -pub trait Trait {} - -struct Struct -where - Self: Iterator::Item>, {} - -impl Trait for Struct {} - -fn main() {} diff --git a/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.next.stderr b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.next.stderr new file mode 100644 index 0000000000000..594a5716a458e --- /dev/null +++ b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.next.stderr @@ -0,0 +1,14 @@ +error: specialization impl does not specialize any associated items + --> $DIR/unexpected-infer-var-ice-102252-2.rs:26:1 + | +LL | impl<'a> Trait for DatasetIter<'a, ArrayBase> {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +note: impl is a specialization of this impl + --> $DIR/unexpected-infer-var-ice-102252-2.rs:14:1 + | +LL | impl Trait for T {} + | ^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.rs b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.rs new file mode 100644 index 0000000000000..f8f51f5828220 --- /dev/null +++ b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252-2.rs @@ -0,0 +1,29 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #102252 + +// Regression test for #102252, which was fixed by switching to the new solver. + +#![feature(min_specialization)] + +trait Trait {} + +impl Trait for T {} + +trait Data { + type Elem; +} + +struct DatasetIter<'a, R: Data> { + data: &'a R::Elem, +} + +pub struct ArrayBase {} + +impl<'a> Trait for DatasetIter<'a, ArrayBase> {} +//[next]~^ ERROR: specialization impl does not specialize any associated items + +fn main() {} diff --git a/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.next.stderr b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.next.stderr new file mode 100644 index 0000000000000..3c7b99a5e56a2 --- /dev/null +++ b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `::Item == _` + --> $DIR/unexpected-infer-var-ice-102252.rs:15:1 + | +LL | struct Struct + | ^^^^^^^^^^^^^ + +error: the type `Struct` is not well-formed + --> $DIR/unexpected-infer-var-ice-102252.rs:20:16 + | +LL | impl Trait for Struct {} + | ^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.rs b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.rs new file mode 100644 index 0000000000000..eb45c7f512364 --- /dev/null +++ b/tests/ui/specialization/min_specialization/unexpected-infer-var-ice-102252.rs @@ -0,0 +1,23 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #102252 + +// Regression test for #102252, which was fixed by switching to the new solver. + +#![feature(min_specialization, rustc_attrs)] + +#[rustc_specialization_trait] +pub trait Trait {} + +struct Struct +//[next]~^ ERROR: overflow evaluating the requirement `::Item == _` +where + Self: Iterator::Item>, {} + +impl Trait for Struct {} +//[next]~^ ERROR: the type `Struct` is not well-formed + +fn main() {} From 51f10935035365fa79438b325f979de6c9d785a9 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:28:01 +0200 Subject: [PATCH 1283/1309] more crashes tests --- tests/crashes/110534.rs | 44 ------------------- ...olver-only-leak-check-on-ambig.next.stderr | 24 ++++++++++ .../old-solver-only-leak-check-on-ambig.rs | 39 ++++++++++++++++ 3 files changed, 63 insertions(+), 44 deletions(-) delete mode 100644 tests/crashes/110534.rs create mode 100644 tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.next.stderr create mode 100644 tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.rs diff --git a/tests/crashes/110534.rs b/tests/crashes/110534.rs deleted file mode 100644 index 240ff6c270413..0000000000000 --- a/tests/crashes/110534.rs +++ /dev/null @@ -1,44 +0,0 @@ -//@ known-bug: #110534 -//@ edition:2021 -use core::cell::Ref; - -struct System; - -trait IntoSystem { - fn into_system(self) -> System; -} - -impl IntoSystem for fn(Ref<'_, u32>) { - fn into_system(self) -> System { System } -} - -impl IntoSystem for fn(A) -where - // n.b. No `Ref<'_, u32>` can satisfy this bound - A: 'static + for<'x> MaybeBorrowed<'x, Output = A>, -{ - fn into_system(self) -> System { System } -} - -//--------------------------------------------------- - -trait MaybeBorrowed<'a> { - type Output: 'a; -} - -// If you comment this out you'll see the compiler chose to look at the -// fn(A) implementation of IntoSystem above -impl<'a, 'b> MaybeBorrowed<'a> for Ref<'b, u32> { - type Output = Ref<'a, u32>; -} - -// --------------------------------------------- - -fn main() { - fn sys_ref(_age: Ref) {} - let _sys_c = (sys_ref as fn(_)).into_system(); - // properly fails - // let _sys_c = (sys_ref as fn(Ref<'static, u32>)).into_system(); - // properly succeeds - // let _sys_c = (sys_ref as fn(Ref<'_, u32>)).into_system(); -} diff --git a/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.next.stderr b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.next.stderr new file mode 100644 index 0000000000000..b139abe71712e --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.next.stderr @@ -0,0 +1,24 @@ +error[E0277]: the trait bound `Option: Trait` is not satisfied + --> $DIR/old-solver-only-leak-check-on-ambig.rs:36:25 + | +LL | let y = impls_trait(None); + | ----------- ^^^^ the trait `Trait` is not implemented for `Option` + | | + | required by a bound introduced by this call + | +help: the trait `Trait` is conditionally implemented for `Option` + --> $DIR/old-solver-only-leak-check-on-ambig.rs:26:1 + | +LL | impl LeakErr<'a>> Trait for Option {} + | ^^^^^^^^-------------------^^^^^^^^^^^^^^^^^^^^^ + | | + | unsatisfied requirement introduced here: `for<'a> _: LeakErr<'a>` +note: required by a bound in `impls_trait` + --> $DIR/old-solver-only-leak-check-on-ambig.rs:31:19 + | +LL | fn impls_trait(x: T) -> T { + | ^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.rs b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.rs new file mode 100644 index 0000000000000..708d0cda8a859 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig.rs @@ -0,0 +1,39 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #110534 + +// Regression test for #110534. This ICE'd with the old solver: +// - evaluation used the leak check in evaluation_probe +// - selection used evaluation only if there are multiple applicable candidates +// - fulfillment never used the leak check +// +// In HIR typeck, we select `Option: Trait` which has two applicable candidates, +// causing us to use evaluate_candidate. `for<'a> Option: LeakErr<'a>` of the +// first impl causes a leak check error. `for<'a> ?x: LeakErr<'a>` of the second +// impl remains ambiguous. This causes us to select the second impl. We then only +// prove `for<'a> u32: LeakErr<'a>` in fulfillment which does not use the leak check. +// THis causes HIR typeck to pass. +// +// In MIR typeck, we select `Option: Trait` which has two applicable candidates, +// causing us to use evaluate_candidate. However, now both candidates fail the leak +// check, causing us to have no applicable impl, causing a selection error. + +trait Trait {} +impl LeakErr<'a>> Trait for T {} +impl LeakErr<'a>> Trait for Option {} + +trait LeakErr<'a> {} +impl LeakErr<'static> for T {} + +fn impls_trait(x: T) -> T { + x +} + +fn main() { + let y = impls_trait(None); + //[next]~^ ERROR: the trait bound `Option: Trait` is not satisfied + let _: Option = y; +} From 7f2478a4c21a3265f07e7999d2d3f48cf253d984 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:43:05 +0200 Subject: [PATCH 1284/1309] more crashes tests + next-solver test migration --- tests/crashes/115435.rs | 25 -------------- .../auxiliary/pr_review_132289_2_lib.rs | 0 .../auxiliary/pr_review_132289_3_lib.rs | 0 .../pr-review-132289-1.next.stderr | 9 +++++ .../pr-review-132289-1.rs | 9 +++-- .../pr-review-132289-2.next.stderr | 17 ++++++++++ .../pr-review-132289-2.rs | 7 +++- .../pr-review-132289-3.old.run.stdout} | 0 .../pr-review-132289-3.rs | 5 ++- .../size_of-assumes-sized-115435.next.stderr | 11 ++++++ .../size_of-assumes-sized-115435.rs | 34 +++++++++++++++++++ 11 files changed, 87 insertions(+), 30 deletions(-) delete mode 100644 tests/crashes/115435.rs rename tests/ui/coherence/{ => dyn-trait-overlap}/auxiliary/pr_review_132289_2_lib.rs (100%) rename tests/ui/coherence/{ => dyn-trait-overlap}/auxiliary/pr_review_132289_3_lib.rs (100%) create mode 100644 tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.next.stderr rename tests/ui/coherence/{ => dyn-trait-overlap}/pr-review-132289-1.rs (81%) create mode 100644 tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.next.stderr rename tests/ui/coherence/{ => dyn-trait-overlap}/pr-review-132289-2.rs (78%) rename tests/ui/coherence/{pr-review-132289-3.run.stdout => dyn-trait-overlap/pr-review-132289-3.old.run.stdout} (100%) rename tests/ui/coherence/{ => dyn-trait-overlap}/pr-review-132289-3.rs (88%) create mode 100644 tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.next.stderr create mode 100644 tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.rs diff --git a/tests/crashes/115435.rs b/tests/crashes/115435.rs deleted file mode 100644 index c6e749867e881..0000000000000 --- a/tests/crashes/115435.rs +++ /dev/null @@ -1,25 +0,0 @@ -//@ known-bug: #115435 -//@ edition:2021 -//@ compile-flags: -Copt-level=0 -trait MyTrait { - type Target: ?Sized; -} - -impl MyTrait for A { - type Target = A; -} - -fn main() { - bug_run::>(); -} - -fn bug_run() -where - ::Target: Sized, -{ - bug::(); -} - -fn bug() { - std::mem::size_of::(); -} diff --git a/tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs b/tests/ui/coherence/dyn-trait-overlap/auxiliary/pr_review_132289_2_lib.rs similarity index 100% rename from tests/ui/coherence/auxiliary/pr_review_132289_2_lib.rs rename to tests/ui/coherence/dyn-trait-overlap/auxiliary/pr_review_132289_2_lib.rs diff --git a/tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs b/tests/ui/coherence/dyn-trait-overlap/auxiliary/pr_review_132289_3_lib.rs similarity index 100% rename from tests/ui/coherence/auxiliary/pr_review_132289_3_lib.rs rename to tests/ui/coherence/dyn-trait-overlap/auxiliary/pr_review_132289_3_lib.rs diff --git a/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.next.stderr b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.next.stderr new file mode 100644 index 0000000000000..f61e239b366d3 --- /dev/null +++ b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.next.stderr @@ -0,0 +1,9 @@ +error[E0284]: type annotations needed: cannot satisfy `<(dyn Something + 'static) as Super>::Assoc == &[usize; 1]` + --> $DIR/pr-review-132289-1.rs:53:22 + | +LL | let _arr2: A = y.method(); + | ^^^^^^ cannot satisfy `<(dyn Something + 'static) as Super>::Assoc == &[usize; 1]` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/coherence/pr-review-132289-1.rs b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.rs similarity index 81% rename from tests/ui/coherence/pr-review-132289-1.rs rename to tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.rs index ab3ed9655e071..2ab564881950f 100644 --- a/tests/ui/coherence/pr-review-132289-1.rs +++ b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-1.rs @@ -3,7 +3,11 @@ // the first example from @steffahn during review. // https://github.com/rust-lang/rust/pull/132289#issuecomment-2564492153 -//@ check-pass +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] known-bug: #57893 +//@[old] check-pass type A = &'static [usize; 1]; type B = &'static [usize; 100]; @@ -47,6 +51,5 @@ fn main() { // this (`_arr2`) can't ever become B either, soundly let _arr2: A = y.method(); - // there aren't any other arrays being defined anywhere in this - // test case, besides the length-1 one containing [1337] + //[next]~^ ERROR: type annotations needed } diff --git a/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.next.stderr b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.next.stderr new file mode 100644 index 0000000000000..1d44b5443b4b2 --- /dev/null +++ b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.next.stderr @@ -0,0 +1,17 @@ +error[E0282]: type annotations needed for `(_, usize)` + --> $DIR/pr-review-132289-2.rs:28:9 + | +LL | let (arr, len) = function::(); + | ^^^^^^^^^^ +LL | +LL | assert_eq!(arr.len(), len); + | --- type must be known at this point + | +help: consider giving this pattern a type, where the placeholders `_` are specified + | +LL | let (arr, len): (_, _) = function::(); + | ++++++++ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0282`. diff --git a/tests/ui/coherence/pr-review-132289-2.rs b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.rs similarity index 78% rename from tests/ui/coherence/pr-review-132289-2.rs rename to tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.rs index 95ad86c61ff19..d62424135b735 100644 --- a/tests/ui/coherence/pr-review-132289-2.rs +++ b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-2.rs @@ -3,7 +3,11 @@ // the second example from @steffahn during review. // https://github.com/rust-lang/rust/pull/132289#issuecomment-2564587796 -//@ run-pass +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] known-bug: #57893 +//@[old] run-pass //@ aux-build: pr_review_132289_2_lib.rs extern crate pr_review_132289_2_lib; @@ -22,5 +26,6 @@ impl LocallyUnimplemented for Dyn {} // is consistent with the function definition's body. fn main() { let (arr, len) = function::(); + //[next]~^ ERROR: type annotations needed for `(_, usize)` assert_eq!(arr.len(), len); } diff --git a/tests/ui/coherence/pr-review-132289-3.run.stdout b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-3.old.run.stdout similarity index 100% rename from tests/ui/coherence/pr-review-132289-3.run.stdout rename to tests/ui/coherence/dyn-trait-overlap/pr-review-132289-3.old.run.stdout diff --git a/tests/ui/coherence/pr-review-132289-3.rs b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-3.rs similarity index 88% rename from tests/ui/coherence/pr-review-132289-3.rs rename to tests/ui/coherence/dyn-trait-overlap/pr-review-132289-3.rs index 7e597baa6ec29..6c99f15bc1ab6 100644 --- a/tests/ui/coherence/pr-review-132289-3.rs +++ b/tests/ui/coherence/dyn-trait-overlap/pr-review-132289-3.rs @@ -3,8 +3,11 @@ // the third example from @steffahn during review. // https://github.com/rust-lang/rust/pull/132289#issuecomment-2564599221 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver //@ run-pass -//@ check-run-results +//@[old] check-run-results //@ aux-build: pr_review_132289_3_lib.rs extern crate pr_review_132289_3_lib; diff --git a/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.next.stderr b/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.next.stderr new file mode 100644 index 0000000000000..b2e2219db151e --- /dev/null +++ b/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.next.stderr @@ -0,0 +1,11 @@ +error[E0284]: type annotations needed + --> $DIR/size_of-assumes-sized-115435.rs:21:5 + | +LL | bug_run::>(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type + | + = note: cannot satisfy ` as MyTrait>::Target == _` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0284`. diff --git a/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.rs b/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.rs new file mode 100644 index 0000000000000..15fcc2595a04e --- /dev/null +++ b/tests/ui/coherence/dyn-trait-overlap/size_of-assumes-sized-115435.rs @@ -0,0 +1,34 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #115435 +//@[old] build-fail +//@ edition:2021 +//@ compile-flags: -Copt-level=0 + +// Regression test for the ICE in #115435. This bug is caused by #57893. +trait MyTrait { + type Target: ?Sized; +} + +impl MyTrait for A { + type Target = A; +} + +fn main() { + bug_run::>(); + //[next]~^ ERROR: type annotations needed +} + +fn bug_run() +where + ::Target: Sized, +{ + bug::(); +} + +fn bug() { + std::mem::size_of::(); +} From 2df0ee65f67b8369d85d42712e21097ba42a55e1 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:47:52 +0200 Subject: [PATCH 1285/1309] more crashes migration --- tests/crashes/120254.rs | 24 -------- .../leak-infer-ice-120254.next.stderr | 60 +++++++++++++++++++ .../leak-infer-ice-120254.rs | 39 ++++++++++++ 3 files changed, 99 insertions(+), 24 deletions(-) delete mode 100644 tests/crashes/120254.rs create mode 100644 tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr create mode 100644 tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.rs diff --git a/tests/crashes/120254.rs b/tests/crashes/120254.rs deleted file mode 100644 index ea68523820ec0..0000000000000 --- a/tests/crashes/120254.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ known-bug: #120254 - -trait Dbg {} - -struct Foo { - input: I, - errors: E, -} - -trait Bar: Offset<::Checkpoint> { - type Checkpoint; -} - -impl Bar for Foo { - type Checkpoint = I::Checkpoint; -} - -trait Offset {} - -impl Offset< as Bar>::Checkpoint> for Foo {} - -impl Foo { - fn record_err(self, _: ::Checkpoint) -> () {} -} diff --git a/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr new file mode 100644 index 0000000000000..fa4d8e13d0b68 --- /dev/null +++ b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr @@ -0,0 +1,60 @@ +error[E0277]: the trait bound `E: Dbg` is not satisfied + --> $DIR/leak-infer-ice-120254.rs:30:28 + | +LL | fn record_err(self, _: ::Checkpoint) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Dbg` is not implemented for `E` + | +note: required for `Foo` to implement `Bar` + --> $DIR/leak-infer-ice-120254.rs:21:22 + | +LL | impl Bar for Foo { + | --- ^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `E` with trait `Dbg` + | +LL | impl Foo { + | +++++ + +error[E0277]: the trait bound `E: Dbg` is not satisfied + | +note: required for `Foo` to implement `Bar` + --> $DIR/leak-infer-ice-120254.rs:21:22 + | +LL | impl Bar for Foo { + | --- ^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here +help: consider restricting type parameter `E` with trait `Dbg` + | +LL | impl Foo { + | +++++ + +error: the type ` as Bar>::Checkpoint` is not well-formed + --> $DIR/leak-infer-ice-120254.rs:30:28 + | +LL | fn record_err(self, _: ::Checkpoint) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `E: Dbg` is not satisfied + --> $DIR/leak-infer-ice-120254.rs:30:28 + | +LL | fn record_err(self, _: ::Checkpoint) -> () {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Dbg` is not implemented for `E` + | +note: required for `Foo` to implement `Bar` + --> $DIR/leak-infer-ice-120254.rs:21:22 + | +LL | impl Bar for Foo { + | --- ^^^ ^^^^^^^^^ + | | + | unsatisfied trait bound introduced here + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` +help: consider restricting type parameter `E` with trait `Dbg` + | +LL | impl Foo { + | +++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.rs b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.rs new file mode 100644 index 0000000000000..0299381e17312 --- /dev/null +++ b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.rs @@ -0,0 +1,39 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #120254 + +//[next]~^^^^^^^ ERROR: the trait bound `E: Dbg` is not satisfied + +// Regression test for #120254. This no longer reproduces with the new solver +// even though the underlying issue has not been fixed. + +trait Dbg {} + +struct Foo { + input: I, + errors: E, +} + +trait Bar: Offset<::Checkpoint> { + type Checkpoint; +} + +impl Bar for Foo { + type Checkpoint = I::Checkpoint; +} + +trait Offset {} + +impl Offset< as Bar>::Checkpoint> for Foo {} + +impl Foo { + fn record_err(self, _: ::Checkpoint) -> () {} + //[next]~^ ERROR: the trait bound `E: Dbg` is not satisfied + //[next]~| ERROR: the type ` as Bar>::Checkpoint` is not well-formed + //[next]~| ERROR: the trait bound `E: Dbg` is not satisfied +} + +fn main() {} From 471b6d2e3cc44e65ecd00faab939fd32eb2e37f5 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:51:49 +0200 Subject: [PATCH 1286/1309] more crashes migration --- tests/crashes/122529.rs | 8 --- ...tion-cache-rematch-impl-122529.next.stderr | 65 +++++++++++++++++++ .../projection-cache-rematch-impl-122529.rs | 25 +++++++ .../leak-infer-ice-120254.next.stderr | 12 ++-- 4 files changed, 96 insertions(+), 14 deletions(-) delete mode 100644 tests/crashes/122529.rs create mode 100644 tests/ui/traits/projection-cache-rematch-impl-122529.next.stderr create mode 100644 tests/ui/traits/projection-cache-rematch-impl-122529.rs diff --git a/tests/crashes/122529.rs b/tests/crashes/122529.rs deleted file mode 100644 index 87d393a453243..0000000000000 --- a/tests/crashes/122529.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ known-bug: #122529 -pub trait Archive { - type Archived; -} - -impl<'a> Archive for <&'a [u8] as Archive>::Archived { - type Archived = (); -} diff --git a/tests/ui/traits/projection-cache-rematch-impl-122529.next.stderr b/tests/ui/traits/projection-cache-rematch-impl-122529.next.stderr new file mode 100644 index 0000000000000..0e269d6a5d23e --- /dev/null +++ b/tests/ui/traits/projection-cache-rematch-impl-122529.next.stderr @@ -0,0 +1,65 @@ +error[E0277]: the trait bound `&'a [u8]: Archive` is not satisfied + --> $DIR/projection-cache-rematch-impl-122529.rs:16:22 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Archive` is not implemented for `&'a [u8]` + | +help: the trait `Archive` is implemented for `<&'a [u8] as Archive>::Archived` + --> $DIR/projection-cache-rematch-impl-122529.rs:16:1 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `&'a [u8]: Archive` is not satisfied + --> $DIR/projection-cache-rematch-impl-122529.rs:16:10 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^ the trait `Archive` is not implemented for `&'a [u8]` + | +help: the trait `Archive` is implemented for `<&'a [u8] as Archive>::Archived` + --> $DIR/projection-cache-rematch-impl-122529.rs:16:1 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `&'a [u8]: Archive` is not satisfied + --> $DIR/projection-cache-rematch-impl-122529.rs:21:21 + | +LL | type Archived = (); + | ^^ the trait `Archive` is not implemented for `&'a [u8]` + | +help: the trait `Archive` is implemented for `<&'a [u8] as Archive>::Archived` + --> $DIR/projection-cache-rematch-impl-122529.rs:16:1 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0277]: the trait bound `&'a [u8]: Archive` is not satisfied + --> $DIR/projection-cache-rematch-impl-122529.rs:16:22 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Archive` is not implemented for `&'a [u8]` + | +help: the trait `Archive` is implemented for `<&'a [u8] as Archive>::Archived` + --> $DIR/projection-cache-rematch-impl-122529.rs:16:1 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error[E0277]: the trait bound `&'a [u8]: Archive` is not satisfied + --> $DIR/projection-cache-rematch-impl-122529.rs:16:22 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Archive` is not implemented for `&'a [u8]` + | +help: the trait `Archive` is implemented for `<&'a [u8] as Archive>::Archived` + --> $DIR/projection-cache-rematch-impl-122529.rs:16:1 + | +LL | impl<'a> Archive for <&'a [u8] as Archive>::Archived { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no` + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/projection-cache-rematch-impl-122529.rs b/tests/ui/traits/projection-cache-rematch-impl-122529.rs new file mode 100644 index 0000000000000..27ada139aed8a --- /dev/null +++ b/tests/ui/traits/projection-cache-rematch-impl-122529.rs @@ -0,0 +1,25 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] known-bug: #122529 +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr + +// This example failed with the old solver in `fn rematch_impl`, +// likely due to a bug with the projection cache. Regression test +// for #122529. + +pub trait Archive { + type Archived; +} + +impl<'a> Archive for <&'a [u8] as Archive>::Archived { +//[next]~^ ERROR: the trait bound `&'a [u8]: Archive` is not satisfied +//[next]~| ERROR: the trait bound `&'a [u8]: Archive` is not satisfied +//[next]~| ERROR: the trait bound `&'a [u8]: Archive` is not satisfied +//[next]~| ERROR: the trait bound `&'a [u8]: Archive` is not satisfied + type Archived = (); + //[next]~^ ERROR: the trait bound `&'a [u8]: Archive` is not satisfied +} + +fn main() {} diff --git a/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr index fa4d8e13d0b68..39deff902a1a0 100644 --- a/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr +++ b/tests/ui/type-inference/snapshot-infer-leakage/leak-infer-ice-120254.next.stderr @@ -1,11 +1,11 @@ error[E0277]: the trait bound `E: Dbg` is not satisfied - --> $DIR/leak-infer-ice-120254.rs:30:28 + --> $DIR/leak-infer-ice-120254.rs:33:28 | LL | fn record_err(self, _: ::Checkpoint) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Dbg` is not implemented for `E` | note: required for `Foo` to implement `Bar` - --> $DIR/leak-infer-ice-120254.rs:21:22 + --> $DIR/leak-infer-ice-120254.rs:24:22 | LL | impl Bar for Foo { | --- ^^^ ^^^^^^^^^ @@ -19,7 +19,7 @@ LL | impl Foo { error[E0277]: the trait bound `E: Dbg` is not satisfied | note: required for `Foo` to implement `Bar` - --> $DIR/leak-infer-ice-120254.rs:21:22 + --> $DIR/leak-infer-ice-120254.rs:24:22 | LL | impl Bar for Foo { | --- ^^^ ^^^^^^^^^ @@ -31,19 +31,19 @@ LL | impl Foo { | +++++ error: the type ` as Bar>::Checkpoint` is not well-formed - --> $DIR/leak-infer-ice-120254.rs:30:28 + --> $DIR/leak-infer-ice-120254.rs:33:28 | LL | fn record_err(self, _: ::Checkpoint) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ error[E0277]: the trait bound `E: Dbg` is not satisfied - --> $DIR/leak-infer-ice-120254.rs:30:28 + --> $DIR/leak-infer-ice-120254.rs:33:28 | LL | fn record_err(self, _: ::Checkpoint) -> () {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Dbg` is not implemented for `E` | note: required for `Foo` to implement `Bar` - --> $DIR/leak-infer-ice-120254.rs:21:22 + --> $DIR/leak-infer-ice-120254.rs:24:22 | LL | impl Bar for Foo { | --- ^^^ ^^^^^^^^^ From a108fb6017b1d65a2a8320cf69ccdf08562870bf Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 12:55:33 +0200 Subject: [PATCH 1287/1309] more crashes migration --- tests/crashes/117392.rs | 47 ------------------- .../issues/relate-mir-borrowck-ice-117392.rs} | 11 ++++- 2 files changed, 10 insertions(+), 48 deletions(-) delete mode 100644 tests/crashes/117392.rs rename tests/{crashes/117392-2.rs => ui/impl-trait/issues/relate-mir-borrowck-ice-117392.rs} (54%) diff --git a/tests/crashes/117392.rs b/tests/crashes/117392.rs deleted file mode 100644 index 95fdf63f893ec..0000000000000 --- a/tests/crashes/117392.rs +++ /dev/null @@ -1,47 +0,0 @@ -//@ known-bug: #117392 -pub trait BorrowComposite { - type Ref<'a> - where - Self: 'a; -} - -impl BorrowComposite for () { - type Ref<'a> = (); -} - -pub trait Component { - type Output; -} - -impl Component for () { - type Output = (); -} - -struct Delay { - _make: Make, -} - -impl< - Args: BorrowComposite, - Make: for<'a> FnMut(Args::Ref<'a>) -> C, - C: Component, - > Component for Delay -{ - type Output = C::Output; -} - -pub fn delay< - Args: BorrowComposite, - Make: for<'a> FnMut(Args::Ref<'a>) -> C, - C: Component, ->( - make: Make, -) -> impl Component { - Delay { _make: make } -} - -pub fn crash() -> impl Component<(), Output = ()> { - delay(|()| delay(|()| ())) -} - -pub fn main() {} diff --git a/tests/crashes/117392-2.rs b/tests/ui/impl-trait/issues/relate-mir-borrowck-ice-117392.rs similarity index 54% rename from tests/crashes/117392-2.rs rename to tests/ui/impl-trait/issues/relate-mir-borrowck-ice-117392.rs index 632ce8b9deece..00778b0dcf1bd 100644 --- a/tests/crashes/117392-2.rs +++ b/tests/ui/impl-trait/issues/relate-mir-borrowck-ice-117392.rs @@ -1,4 +1,13 @@ -//@ known-bug: #117392 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] check-pass +//@[old] known-bug: #117392 +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr + +// This test previously caused an ICE in `fn crash` when relating opaque +// types. This has been fixed by the opaque type rework in the new solver. pub trait BorrowComposite { type Ref<'a>: 'a; } From 38c6c1fc40112fcee4b6a559d5da6a0616a4353a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 13:03:57 +0200 Subject: [PATCH 1288/1309] more crashes migration + move tests --- ...igher-ranked-auto-trait-1.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-1.rs | 0 .../higher-ranked-auto-trait-10.assumptions.stderr | 0 ...gher-ranked-auto-trait-10.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-10.rs | 0 .../higher-ranked-auto-trait-11.assumptions.stderr | 0 ...gher-ranked-auto-trait-11.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-11.rs | 0 ...gher-ranked-auto-trait-12.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-12.rs | 0 .../higher-ranked-auto-trait-13.assumptions.stderr | 0 ...gher-ranked-auto-trait-13.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-13.rs | 0 .../higher-ranked-auto-trait-14.rs | 0 ...gher-ranked-auto-trait-15.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-15.rs | 0 .../higher-ranked-auto-trait-16.assumptions.stderr | 0 ...gher-ranked-auto-trait-16.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-16.rs | 0 ...gher-ranked-auto-trait-17.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-17.rs | 0 ...gher-ranked-auto-trait-18.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-18.rs | 0 .../higher-ranked-auto-trait-2.rs | 0 .../higher-ranked-auto-trait-3.rs | 0 ...igher-ranked-auto-trait-4.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-4.rs | 0 ...igher-ranked-auto-trait-5.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-5.rs | 0 ...igher-ranked-auto-trait-6.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-6.rs | 0 .../higher-ranked-auto-trait-7.rs | 0 ...igher-ranked-auto-trait-8.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-8.rs | 0 ...igher-ranked-auto-trait-9.no_assumptions.stderr | 0 .../higher-ranked-auto-trait-9.rs | 0 ...itness-lifetime-dependent-auto-trait-119095.rs} | 14 +++++++++++++- 37 files changed, 13 insertions(+), 1 deletion(-) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-1.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-1.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-10.assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-10.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-10.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-11.assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-11.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-11.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-12.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-12.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-13.assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-13.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-13.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-14.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-15.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-15.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-16.assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-16.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-16.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-17.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-17.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-18.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-18.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-2.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-3.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-4.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-4.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-5.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-5.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-6.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-6.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-7.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-8.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-8.rs (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-9.no_assumptions.stderr (100%) rename tests/ui/async-await/{ => witness-auto-trait}/higher-ranked-auto-trait-9.rs (100%) rename tests/{crashes/119095.rs => ui/async-await/witness-auto-trait/witness-lifetime-dependent-auto-trait-119095.rs} (58%) diff --git a/tests/ui/async-await/higher-ranked-auto-trait-1.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-1.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-1.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-1.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-1.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-1.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-1.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-1.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-10.assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-10.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-10.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-10.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-10.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-11.assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-11.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-11.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-11.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-11.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-12.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-12.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-12.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-12.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-12.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-12.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-12.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-13.assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-13.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-13.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-13.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-13.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-14.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-14.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-14.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-14.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-15.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-15.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-15.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-15.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-15.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-15.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-15.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-16.assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-16.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-16.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-16.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-16.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-17.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-17.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-17.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-17.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-17.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-17.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-17.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-17.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-18.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-18.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-18.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-18.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-18.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-18.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-18.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-18.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-2.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-2.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-2.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-2.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-3.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-3.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-3.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-3.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-4.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-4.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-4.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-4.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-4.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-4.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-4.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-4.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-5.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-5.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-5.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-5.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-5.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-5.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-5.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-6.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-6.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-6.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-6.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-6.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-6.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-6.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-7.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-7.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-7.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-7.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-8.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-8.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-8.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-8.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-8.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-8.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-8.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-8.rs diff --git a/tests/ui/async-await/higher-ranked-auto-trait-9.no_assumptions.stderr b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-9.no_assumptions.stderr similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-9.no_assumptions.stderr rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-9.no_assumptions.stderr diff --git a/tests/ui/async-await/higher-ranked-auto-trait-9.rs b/tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-9.rs similarity index 100% rename from tests/ui/async-await/higher-ranked-auto-trait-9.rs rename to tests/ui/async-await/witness-auto-trait/higher-ranked-auto-trait-9.rs diff --git a/tests/crashes/119095.rs b/tests/ui/async-await/witness-auto-trait/witness-lifetime-dependent-auto-trait-119095.rs similarity index 58% rename from tests/crashes/119095.rs rename to tests/ui/async-await/witness-auto-trait/witness-lifetime-dependent-auto-trait-119095.rs index 9b6c976d3e5d3..78625cbe4843e 100644 --- a/tests/crashes/119095.rs +++ b/tests/ui/async-await/witness-auto-trait/witness-lifetime-dependent-auto-trait-119095.rs @@ -1,6 +1,18 @@ -//@ known-bug: #119095 +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[next] build-pass +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #119095 +//@[old] build-fail //@ edition: 2021 +// Regression test for #119095. No clue why this does not fail +// to compile with the new solver. Likely because we normalize +// `impl Unit<&'placeholder ()>` in a separate nested goal, so +// its constraints on placeholder are ignored by the leak check. + fn any() -> T { loop {} } From 3ddbe0647f1a53782418dbe21ac83004ca58969f Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 13:05:14 +0200 Subject: [PATCH 1289/1309] yeet duplicate test --- tests/crashes/122710.rs | 24 ------------------------ 1 file changed, 24 deletions(-) delete mode 100644 tests/crashes/122710.rs diff --git a/tests/crashes/122710.rs b/tests/crashes/122710.rs deleted file mode 100644 index 16911fd522f8e..0000000000000 --- a/tests/crashes/122710.rs +++ /dev/null @@ -1,24 +0,0 @@ -//@ known-bug: #122710 -use std::marker::PhantomData; - -pub trait BarTrait { - fn bar(self, _: T); -} - -impl BarTrait for F { - fn bar(self, _: T) { } -} - -impl MyTrait<'a>> BarTrait for () { - fn bar(self, _: T) { } -} - -pub trait MyTrait<'a> { } - -impl<'a> MyTrait<'a> for PhantomData<&'a ()> { } - -fn foo() { - ().bar(PhantomData); -} - -pub fn main() {} From 438196a489ce9d6f09910e97b4d5934fb63b0b13 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 13:08:07 +0200 Subject: [PATCH 1290/1309] remove duplicate test --- tests/crashes/126667.rs | 14 -------------- 1 file changed, 14 deletions(-) delete mode 100644 tests/crashes/126667.rs diff --git a/tests/crashes/126667.rs b/tests/crashes/126667.rs deleted file mode 100644 index 27b170d6da5fc..0000000000000 --- a/tests/crashes/126667.rs +++ /dev/null @@ -1,14 +0,0 @@ -//@ known-bug: rust-lang/rust#126667 -#![warn(rust_2021_compatibility)] - -trait Static<'a> {} - -struct Foo((u32, u32)); - -fn main() { - type T = impl Static; - let foo: T = Foo((1u32, 2u32)); - let x = move || { - let Foo((a, b)) = foo; - }; -} From ca52f5285d2dc13df40190aa2af728d15479d162 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Mon, 5 Oct 2026 19:38:40 +0800 Subject: [PATCH 1291/1309] ci: bump `actions/checkout` to v7.0.1 --- src/tools/rustfmt/.github/workflows/check_diff.yml | 2 +- src/tools/rustfmt/.github/workflows/clippy.yml | 4 ++-- src/tools/rustfmt/.github/workflows/integration.yml | 2 +- src/tools/rustfmt/.github/workflows/rustdoc_check.yml | 2 +- src/tools/rustfmt/.github/workflows/test.yml | 2 +- src/tools/rustfmt/.github/workflows/upload-assets.yml | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/tools/rustfmt/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml index 90944500a44b0..b3543a49c3e9b 100644 --- a/src/tools/rustfmt/.github/workflows/check_diff.yml +++ b/src/tools/rustfmt/.github/workflows/check_diff.yml @@ -50,7 +50,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Build check_diff binary working-directory: ./check_diff diff --git a/src/tools/rustfmt/.github/workflows/clippy.yml b/src/tools/rustfmt/.github/workflows/clippy.yml index 92e385d135c0e..a5aa91346dd84 100644 --- a/src/tools/rustfmt/.github/workflows/clippy.yml +++ b/src/tools/rustfmt/.github/workflows/clippy.yml @@ -12,7 +12,7 @@ jobs: name: check clippy configs steps: - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: install rustup run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh @@ -34,7 +34,7 @@ jobs: - config_proc_macro steps: - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: install rustup run: | curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs > rustup-init.sh diff --git a/src/tools/rustfmt/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml index 09fc59114e97e..224605740e55e 100644 --- a/src/tools/rustfmt/.github/workflows/integration.yml +++ b/src/tools/rustfmt/.github/workflows/integration.yml @@ -59,7 +59,7 @@ jobs: steps: - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Run build - name: install rustup diff --git a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml index 04bb8e1d240f6..b3978005fdf62 100644 --- a/src/tools/rustfmt/.github/workflows/rustdoc_check.yml +++ b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml @@ -12,7 +12,7 @@ jobs: name: rustdoc check steps: - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: install rustup run: | diff --git a/src/tools/rustfmt/.github/workflows/test.yml b/src/tools/rustfmt/.github/workflows/test.yml index aed79eb2e7b72..6d0f25834e596 100644 --- a/src/tools/rustfmt/.github/workflows/test.yml +++ b/src/tools/rustfmt/.github/workflows/test.yml @@ -42,7 +42,7 @@ jobs: if: ${{ matrix.os == 'windows-latest' }} run: git config --global core.autocrlf false - name: checkout - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 - name: Install Rustup using win.rustup.rs if: ${{ matrix.os == 'windows-latest' }} diff --git a/src/tools/rustfmt/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml index a6a3d3bc51a85..991cc965e3d51 100644 --- a/src/tools/rustfmt/.github/workflows/upload-assets.yml +++ b/src/tools/rustfmt/.github/workflows/upload-assets.yml @@ -31,7 +31,7 @@ jobs: target: x86_64-pc-windows-msvc runs-on: ${{ matrix.os }} steps: - - uses: actions/checkout@de0fac2e4500dabe0009e67214ff5f5447ce83dd # v6.0.2 + - uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1 # Run build - name: install rustup From 612d3d92fdfd0694b6f9836ed4cc66a393ed723a Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 14:40:44 +0200 Subject: [PATCH 1292/1309] more crashes migration --- tests/crashes/124440.rs | 23 ------------- ...eak-check-on-ambig-closure-sig.next.stderr | 31 +++++++++++++++++ ...er-only-leak-check-on-ambig-closure-sig.rs | 34 +++++++++++++++++++ 3 files changed, 65 insertions(+), 23 deletions(-) delete mode 100644 tests/crashes/124440.rs create mode 100644 tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.next.stderr create mode 100644 tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.rs diff --git a/tests/crashes/124440.rs b/tests/crashes/124440.rs deleted file mode 100644 index 431c4e444f10a..0000000000000 --- a/tests/crashes/124440.rs +++ /dev/null @@ -1,23 +0,0 @@ -//@ known-bug: rust-lang/rust#124440 - -#![allow(warnings)] - -trait Foo {} - -impl Foo for F where F: FnMut(&()) {} - -struct Bar { - f: F, -} - -impl Foo for Bar where F: Foo {} - -fn assert_foo(_: F) -where - Bar: Foo, -{ -} - -fn main() { - assert_foo(|_| ()); -} diff --git a/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.next.stderr b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.next.stderr new file mode 100644 index 0000000000000..f599cc9af4c33 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.next.stderr @@ -0,0 +1,31 @@ +error[E0277]: the trait bound `Bar<{closure@$DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:32:16: 32:19}>: Foo` is not satisfied + --> $DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:32:16 + | +LL | assert_foo(|_| ()); + | ---------- ^^^^^^ unsatisfied trait bound + | | + | required by a bound introduced by this call + | +help: the trait `Foo` is not implemented for `Bar<{closure@$DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:32:16: 32:19}>` + --> $DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:19:1 + | +LL | struct Bar { + | ^^^^^^^^^^^^^ +help: the trait `Foo` is conditionally implemented for `Bar` + --> $DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:23:1 + | +LL | impl Foo for Bar where F: Foo {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--- + | | + | unsatisfied requirement introduced here: `_: Foo` +note: required by a bound in `assert_foo` + --> $DIR/old-solver-only-leak-check-on-ambig-closure-sig.rs:27:13 + | +LL | fn assert_foo(_: F) +LL | where +LL | Bar: Foo, + | ^^^ required by this bound in `assert_foo` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.rs b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.rs new file mode 100644 index 0000000000000..b79b6f6826c6e --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/old-solver-only-leak-check-on-ambig-closure-sig.rs @@ -0,0 +1,34 @@ +//@ revisions: old next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@[old] failure-status: 101 +//@[old] dont-check-compiler-stderr +//@[old] known-bug: #124440 + +// A variant of `old-solver-only-leak-check-on-ambig.rs` which +// also relies on us failing to infer the closure signature. +// +// We don't recur into the `?expectation: Foo` bound to get the +// nested higher-ranked `FnMut` bound. +#![allow(warnings)] + +trait Foo {} + +impl Foo for F where F: FnMut(&()) {} + +struct Bar { + f: F, +} + +impl Foo for Bar where F: Foo {} + +fn assert_foo(_: F) +where + Bar: Foo, +{ +} + +fn main() { + assert_foo(|_| ()); + //[next]~^ ERROR: the trait bound +} From d7103748ebe81b64ea436a566818c51a1290efd4 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 5 Oct 2026 13:03:21 +0000 Subject: [PATCH 1293/1309] fix `VisibleForLeakCheck` in `RegionOutlives` fast path MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * fix visible for leak check in fast path * add comment * fix typo Co-authored-by: Rémy Rakic --- .../src/solve/delegate.rs | 7 ++++++- .../ignores-explicit-outlives-constraints.rs | 21 +++++++++++++++++++ ...nores-explicit-outlives-constraints.stderr | 13 ++++++++++++ ...eak-check-coinductive-cycle.current.stderr | 17 +++++++++++++++ .../leak-check-coinductive-cycle.next.stderr | 15 +++++++++++++ .../cycles/leak-check-coinductive-cycle.rs | 15 +++++++++++-- 6 files changed, 85 insertions(+), 3 deletions(-) create mode 100644 tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.rs create mode 100644 tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.stderr create mode 100644 tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.current.stderr create mode 100644 tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.next.stderr diff --git a/compiler/rustc_trait_selection/src/solve/delegate.rs b/compiler/rustc_trait_selection/src/solve/delegate.rs index e1043d53fa6fc..951c52df9dd11 100644 --- a/compiler/rustc_trait_selection/src/solve/delegate.rs +++ b/compiler/rustc_trait_selection/src/solve/delegate.rs @@ -215,11 +215,16 @@ impl<'tcx> rustc_next_trait_solver::delegate::SolverDelegate for SolverDelegate< return Outcome::NoFastPath; } + // We use `VisibleForLeakCheck::Yes` for `RegionOutlives` goals without + // the fast path. However, we always change region constraints from nested + // goals to `VisibleForLeakCheck::No`, so to be consistent with this + // behavior as we avoid the nested goal boundary, we have to manually + // set the flag. self.0.sub_regions( SubregionOrigin::RelateRegionParamBound(span, None), outlives.1, outlives.0, - ty::VisibleForLeakCheck::Yes, + ty::VisibleForLeakCheck::No, ); Outcome::TriviallyHolds } diff --git a/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.rs b/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.rs new file mode 100644 index 0000000000000..ecfaff970623a --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.rs @@ -0,0 +1,21 @@ +// This checks whether the leak check during coherence considers explicit outlives +// bounds. If it did, this would compile. Right now, we intentionally error here. +// See #163267. + +trait MayRequireStatic {} +// `for<'a> &'a i32: MayRequireStatic` does not hold +impl<'a: 'static> MayRequireStatic for &'a i32 {} +impl<'a> MayRequireStatic for &'a u32 {} + +trait Trait {} + +impl Trait for i32 {} +impl Trait for T where for<'a> &'a T: MayRequireStatic {} +//~^ ERROR conflicting implementations of trait `Trait` for type `i32` + +fn is_trait() {} + +fn main() { + is_trait::(); + is_trait::(); +} diff --git a/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.stderr b/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.stderr new file mode 100644 index 0000000000000..62cf899454b36 --- /dev/null +++ b/tests/ui/higher-ranked/leak-check/ignores-explicit-outlives-constraints.stderr @@ -0,0 +1,13 @@ +error[E0119]: conflicting implementations of trait `Trait` for type `i32` + --> $DIR/ignores-explicit-outlives-constraints.rs:13:1 + | +LL | impl Trait for i32 {} + | ------------------ first implementation here +LL | impl Trait for T where for<'a> &'a T: MayRequireStatic {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `i32` + | + = note: this behavior recently changed as a result of a bug fix; see rust-lang/rust#56105 for details + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0119`. diff --git a/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.current.stderr b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.current.stderr new file mode 100644 index 0000000000000..2be30c47ab95d --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.current.stderr @@ -0,0 +1,17 @@ +error[E0275]: overflow evaluating the requirement `&(): Trait` + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`leak_check_coinductive_cycle`) +note: required for `(&(), &'b ())` to implement `for<'b> Trait` + --> $DIR/leak-check-coinductive-cycle.rs:17:17 + | +LL | impl<'a, 'b, T> Trait for (&'a (), &'b ()) + | ^^^^^^^^ ^^^^^^^^^^^^^^^^ +... +LL | &'a (): Trait, + | -------- unsatisfied trait bound introduced here + = note: 128 redundant requirements hidden + = note: required for `(&(), &'b ())` to implement `for<'b> Trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.next.stderr b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.next.stderr new file mode 100644 index 0000000000000..bfddc789f4c77 --- /dev/null +++ b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `(&(), &()): Trait<_>` + --> $DIR/leak-check-coinductive-cycle.rs:42:19 + | +LL | impls_trait::<(&(), &()), _>(); + | ^^^^^^^^^^ + | +note: required by a bound in `impls_trait` + --> $DIR/leak-check-coinductive-cycle.rs:30:19 + | +LL | fn impls_trait, U>() {} + | ^^^^^^^^ required by this bound in `impls_trait` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs index c6ec4fd39de11..d392eb1bce5c1 100644 --- a/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs +++ b/tests/ui/traits/next-solver/cycles/leak-check-coinductive-cycle.rs @@ -1,5 +1,15 @@ -//@ compile-flags: -Znext-solver -//@ check-pass +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// This test is no longer testing what it was originally intended to do as we've changed the +// leak check to no longer rely on any constraints from nested goals, see #155749. +// +// Long-term we do want to consider constraints from nested goals, at which point +// this test becomes useful again. + +//[current]~^^^^^^^^^^ ERROR overflow evaluating the requirement `&(): Trait` + #![feature(rustc_attrs)] #[rustc_coinductive] @@ -30,4 +40,5 @@ fn main() { // end up with a single impl for `&'a (): Trait<_>` which infers `_` to `i32` // and succeeds. impls_trait::<(&(), &()), _>(); + //[next]~^ ERROR overflow evaluating the requirement `(&(), &()): Trait<_>` } From adfb5d30b50c8029d245cd0bc8e91a1991f45bd2 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Mon, 5 Oct 2026 14:07:40 +0000 Subject: [PATCH 1294/1309] Fix an issue for clippy's `search_is_some` with the next-solver --- src/tools/clippy/clippy_utils/src/ty/mod.rs | 2 +- ...arch_is_some_arg_no_deref_new_solver.fixed | 22 +++++++++++++++++++ .../search_is_some_arg_no_deref_new_solver.rs | 22 +++++++++++++++++++ ...rch_is_some_arg_no_deref_new_solver.stderr | 11 ++++++++++ 4 files changed, 56 insertions(+), 1 deletion(-) create mode 100644 src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.fixed create mode 100644 src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.rs create mode 100644 src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.stderr diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index 100420a8bfa02..0613d8d7453af 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -794,7 +794,7 @@ pub fn ty_sig<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> Option Some(ExprFnSig::Sig(sig_tys.with(hdr), None)), diff --git a/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.fixed b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.fixed new file mode 100644 index 0000000000000..8c8af388bd9c3 --- /dev/null +++ b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.fixed @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=globally + +// Regression test that ensures clippy fix won't accidently deref the argument of +// a closure when we fix `.find(..).is_some()` into `.any(..)` due to mishandling +// of non-rigid aliases. + +#![warn(clippy::search_is_some)] +#![allow(clippy::explicit_auto_deref, clippy::manual_contains)] +#![expect(clippy::useless_vec)] + +fn make_arg_no_deref_impl() -> impl Fn(&&u32) -> bool { + move |x: &&u32| **x == 78 +} + +fn main() { + let v = vec![3, 2, 1, 0]; + let arg_no_deref_impl = make_arg_no_deref_impl(); + + #[allow(clippy::redundant_closure)] + let _ = v.iter().any(|x: &u32| arg_no_deref_impl(&x)); + //~^ search_is_some +} diff --git a/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.rs b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.rs new file mode 100644 index 0000000000000..76b07741e5f52 --- /dev/null +++ b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver=globally + +// Regression test that ensures clippy fix won't accidently deref the argument of +// a closure when we fix `.find(..).is_some()` into `.any(..)` due to mishandling +// of non-rigid aliases. + +#![warn(clippy::search_is_some)] +#![allow(clippy::explicit_auto_deref, clippy::manual_contains)] +#![expect(clippy::useless_vec)] + +fn make_arg_no_deref_impl() -> impl Fn(&&u32) -> bool { + move |x: &&u32| **x == 78 +} + +fn main() { + let v = vec![3, 2, 1, 0]; + let arg_no_deref_impl = make_arg_no_deref_impl(); + + #[allow(clippy::redundant_closure)] + let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some(); + //~^ search_is_some +} diff --git a/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.stderr b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.stderr new file mode 100644 index 0000000000000..d44fd6db494aa --- /dev/null +++ b/src/tools/clippy/tests/ui/search_is_some_arg_no_deref_new_solver.stderr @@ -0,0 +1,11 @@ +error: called `is_some()` after searching an `Iterator` with `find` + --> tests/ui/search_is_some_arg_no_deref_new_solver.rs:20:22 + | +LL | let _ = v.iter().find(|x: &&u32| arg_no_deref_impl(x)).is_some(); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider using: `any(|x: &u32| arg_no_deref_impl(&x))` + | + = note: `-D clippy::search-is-some` implied by `-D warnings` + = help: to override `-D warnings` add `#[allow(clippy::search_is_some)]` + +error: aborting due to 1 previous error + From 59df6010d5a27b5394af679a75cdb169ae82ce23 Mon Sep 17 00:00:00 2001 From: Shoyu Vanilla Date: Mon, 5 Oct 2026 05:27:31 +0000 Subject: [PATCH 1295/1309] Add a test for suboptimal diagnostics --- ...lowing-opaque-incorrectly-unconstrained.rs | 22 +++++++++++++++++++ ...ng-opaque-incorrectly-unconstrained.stderr | 18 +++++++++++++++ 2 files changed, 40 insertions(+) create mode 100644 tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.rs create mode 100644 tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.stderr diff --git a/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.rs b/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.rs new file mode 100644 index 0000000000000..0c12528f22f68 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.rs @@ -0,0 +1,22 @@ +//@ compile-flags: -Znext-solver + +// FIXME: The diagnostics here are suboptimal. +// See . + +#![feature(type_alias_impl_trait)] +//~^^^^^^ ERROR: overflow evaluating the requirement `X == _` + +// TAIT with self-referencing bounds +type X = impl std::ops::Add; + +struct Foo; + +impl Foo { + #[define_opaque(X)] + pub fn new() -> X { + //~^ ERROR: item does not constrain `X::{opaque#0}` + 0i32 + } +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.stderr b/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.stderr new file mode 100644 index 0000000000000..9445f07778da0 --- /dev/null +++ b/tests/ui/traits/next-solver/diagnostics/overflowing-opaque-incorrectly-unconstrained.stderr @@ -0,0 +1,18 @@ +error: item does not constrain `X::{opaque#0}` + --> $DIR/overflowing-opaque-incorrectly-unconstrained.rs:16:12 + | +LL | pub fn new() -> X { + | ^^^ + | + = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]` +note: this opaque type is supposed to be constrained + --> $DIR/overflowing-opaque-incorrectly-unconstrained.rs:10:10 + | +LL | type X = impl std::ops::Add; + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `X == _` + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. From 1b3fa277c1128bcc3a3064c53e487b5c55d59464 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Mon, 5 Oct 2026 20:30:11 +0530 Subject: [PATCH 1296/1309] Check doc inline conflicts during parsing --- compiler/rustc_attr_ir/src/data_structures.rs | 7 +-- .../rustc_attr_parsing/src/attributes/doc.rs | 51 +++++++++---------- src/librustdoc/clean/inline.rs | 2 +- src/librustdoc/clean/mod.rs | 26 +++++----- src/librustdoc/json/conversions.rs | 2 +- src/librustdoc/visit_ast.rs | 4 +- tests/ui/rustdoc/doc-inline-validation.rs | 2 +- tests/ui/rustdoc/doc-inline-validation.stderr | 2 +- 8 files changed, 45 insertions(+), 51 deletions(-) diff --git a/compiler/rustc_attr_ir/src/data_structures.rs b/compiler/rustc_attr_ir/src/data_structures.rs index 712ed41ae7759..9f297feeca389 100644 --- a/compiler/rustc_attr_ir/src/data_structures.rs +++ b/compiler/rustc_attr_ir/src/data_structures.rs @@ -490,9 +490,7 @@ pub struct DocAttribute { pub aliases: FxIndexMap, pub hidden: Option, - // Because we need to emit the error if there is more than one `inline` attribute on an item - // at the same time as the other doc attributes, we store a list instead of using `Option`. - pub inline: ThinVec<(DocInline, Span)>, + pub inline: Option<(DocInline, Span)>, // unstable pub cfg: ThinVec, @@ -555,8 +553,7 @@ impl rustc_serialize::Encodable for DocAttribute // FIXME: The `doc(inline)` attribute is never encoded, but is it actually the right thing // to do? I suspect the condition was broken, should maybe instead not encode anything if we // have `doc(no_inline)`. - let inline: ThinVec<_> = - inline.iter().filter(|(i, _)| *i != DocInline::Inline).cloned().collect(); + let inline = inline.filter(|(i, _)| *i != DocInline::Inline); rustc_serialize::Encodable::::encode(&inline, encoder); rustc_serialize::Encodable::::encode(cfg, encoder); diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 129d3626e675e..017b8f397df66 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -2,7 +2,7 @@ use rustc_ast::ast::{AttrStyle, LitKind, MetaItemLit}; use rustc_attr_ir::target::Target; use rustc_attr_ir::{ AttributeKind, CfgEntry, CfgHideShow, DocAttribute, DocCfgHideShow, DocCfgHideShowValue, - DocInline, HideOrShow, find_attr, + DocInline, HideOrShow, }; use rustc_data_structures::fx::{FxHashSet, FxIndexMap, IndexEntry}; use rustc_errors::{Applicability, MultiSpan, msg}; @@ -135,6 +135,7 @@ fn parse_keyword_and_attribute( pub(crate) struct DocParser { attribute: DocAttribute, nb_doc_attrs: usize, + inline_conflict: bool, } impl DocParser { @@ -263,7 +264,22 @@ impl DocParser { return; } - self.attribute.inline.push((inline, path.span())); + if self.inline_conflict { + return; + } + + if let Some((previous_inline, previous_span)) = self.attribute.inline { + if previous_inline != inline { + let span = path.span(); + let mut spans = MultiSpan::from_spans(vec![previous_span, span]); + spans.push_span_label(previous_span, msg!("this attribute...")); + spans.push_span_label(span, msg!("{\".\"}..conflicts with this attribute")); + cx.emit_err(DocInlineConflict { spans }); + self.inline_conflict = true; + } + } else { + self.attribute.inline = Some((inline, path.span())); + } } fn parse_cfg(&mut self, cx: &mut AcceptContext<'_, '_>, args: &ArgParser) { @@ -742,31 +758,7 @@ impl DocParser { } } - fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, _attr_span: Span) { - let Some(doc) = find_attr!(cx.parsed_attrs, Doc(doc) => doc) else { - return; - }; - - let span = match doc.inline.as_slice() { - [] => return, - [(_, span)] => *span, - [(inline, span), rest @ ..] => { - for (inline2, span2) in rest { - if inline2 != inline { - let mut spans = MultiSpan::from_spans(vec![*span, *span2]); - spans.push_span_label(*span, msg!("this attribute...")); - spans.push_span_label( - *span2, - msg!("{\".\"}..conflicts with this attribute"), - ); - cx.emit_err(DocInlineConflict { spans }); - return; - } - } - *span - } - }; - + fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, span: Span) { match cx.target { Target::Use | Target::ExternCrate => {} _ => { @@ -856,7 +848,10 @@ impl AttributeParser for DocParser { } fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> { - let &(_, span) = self.attribute.inline.first()?; + if self.inline_conflict { + return None; + } + let (_, span) = self.attribute.inline?; Some((Self::finalize_check, span)) } } diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0a6c4ce6414a1..7f81e29180baf 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -786,7 +786,7 @@ fn build_module_items( && find_attr!( load_attrs(cx.tcx, reexport_def_id), Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::NoInline) + if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline) ) { // We don't inline foreign `use`. diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 9b3c3d01557e0..8b9f3680211c6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -224,7 +224,7 @@ pub(crate) fn macro_reexport_is_inline( let is_inline = find_attr!( inline::load_attrs(tcx, reexport_def_id), Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) + if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline) ); // hidden takes absolute priority over inline on the same node @@ -261,7 +261,7 @@ fn generate_item_with_correct_attrs( let import_is_inline = find_attr!( inline::load_attrs(tcx, import_id.to_def_id()), Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) + if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline) ) || (is_glob_import(tcx, import_id) && (cx.document_hidden() || !tcx.is_doc_hidden(def_id))) || macro_reexport_is_inline(tcx, import_id, def_id); @@ -2897,7 +2897,7 @@ fn add_without_unwanted_attributes<'hir>( if is_inline { attr.cfg = cfg.clone(); } else { - attr.inline = inline.clone(); + attr.inline = *inline; attr.hidden = hidden.clone(); } attr.aliases = aliases.clone(); @@ -3172,7 +3172,7 @@ fn clean_extern_crate<'tcx>( matches!( a, rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) - if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline)) + if d.inline.is_some_and(|(i, _)| i == DocInline::Inline)) }) && !cx.is_json_output(); @@ -3286,9 +3286,9 @@ fn clean_use_statement_leaf<'tcx>( let attrs = cx.tcx.hir_attrs(import_hir_id); let inline_attr = find_attr!( attrs, - Doc(d) if d.inline.first().is_some_and(|(i, _)| *i == DocInline::Inline) => d + Doc(d) if d.inline.is_some_and(|(i, _)| i == DocInline::Inline) => d ) - .and_then(|d| d.inline.first()); + .and_then(|d| d.inline); let pub_underscore = visibility.is_public() && name == Some(kw::Underscore); let current_mod = cx.tcx.parent_module_from_def_id(import_id); let import_def_id = import_id; @@ -3309,7 +3309,7 @@ fn clean_use_statement_leaf<'tcx>( if pub_underscore && let Some((_, inline_span)) = inline_attr { struct_span_code_err!( cx.tcx.dcx(), - *inline_span, + inline_span, E0780, "anonymous imports cannot be inlined" ) @@ -3324,11 +3324,13 @@ fn clean_use_statement_leaf<'tcx>( let mut denied = cx.is_json_output() || !(visibility.is_public() || (cx.document_private() && is_visible_from_parent_mod)) || pub_underscore - || attrs.iter().any(|a| matches!( - a, - rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) - if d.hidden.is_some() || d.inline.first().is_some_and(|(i, _)| *i == DocInline::NoInline) - )); + || attrs.iter().any(|a| { + matches!( + a, + rustc_attr_ir::Attribute::Parsed(AttributeKind::Doc(d)) + if d.hidden.is_some() || d.inline.is_some_and(|(i, _)| i == DocInline::NoInline) + ) + }); // Also check whether imports were asked to be inlined, in case we're trying to re-export a // crate in Rust 2018+ diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs index 814e26b035d5a..556a922f7044c 100644 --- a/src/librustdoc/json/conversions.rs +++ b/src/librustdoc/json/conversions.rs @@ -1172,7 +1172,7 @@ fn maybe_from_hir_attr( ret.push(Attribute::Other(format!("#[doc(alias = {:?})]", alias.as_str()))); } toggle_attr(&mut ret, "hidden", hidden); - if let Some(inline) = inline.first() { + if let Some(inline) = inline { ret.push(Attribute::Other(format!( "#[doc({})]", match inline.0 { diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs index c0f28a933a3a5..df55626ffb05d 100644 --- a/src/librustdoc/visit_ast.rs +++ b/src/librustdoc/visit_ast.rs @@ -280,7 +280,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { let is_no_inline = find_attr!( use_attrs, Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::NoInline) + if d.inline.is_some_and(|(inline, _)| inline == DocInline::NoInline) ) || (document_hidden && use_attrs.iter().any(|attr| attr.is_doc_hidden())); @@ -601,7 +601,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> { find_attr!( attrs, Doc(d) - if d.inline.first().is_some_and(|(inline, _)| *inline == DocInline::Inline) + if d.inline.is_some_and(|(inline, _)| inline == DocInline::Inline) ) }; let ident = match (tree.kind, self.glob_mode) { diff --git a/tests/ui/rustdoc/doc-inline-validation.rs b/tests/ui/rustdoc/doc-inline-validation.rs index 8a64f2bcf4284..56427ed931913 100644 --- a/tests/ui/rustdoc/doc-inline-validation.rs +++ b/tests/ui/rustdoc/doc-inline-validation.rs @@ -29,7 +29,7 @@ pub use std::panic; #[doc(inline)] //~^ ERROR conflicting doc inlining attributes //~| HELP remove one of the conflicting attributes -#[doc(no_inline)] +#[doc(no_inline, inline, no_inline)] pub use std::fmt; #[doc(no_inline)] diff --git a/tests/ui/rustdoc/doc-inline-validation.stderr b/tests/ui/rustdoc/doc-inline-validation.stderr index 1e14e08691105..2b720b8d11cdb 100644 --- a/tests/ui/rustdoc/doc-inline-validation.stderr +++ b/tests/ui/rustdoc/doc-inline-validation.stderr @@ -4,7 +4,7 @@ error: conflicting doc inlining attributes LL | #[doc(inline)] | ^^^^^^ this attribute... ... -LL | #[doc(no_inline)] +LL | #[doc(no_inline, inline, no_inline)] | ^^^^^^^^^ ...conflicts with this attribute | = help: remove one of the conflicting attributes From 5d640cbc1d274f1906fd96eb5bee83603800c787 Mon Sep 17 00:00:00 2001 From: darkraider01 <95766741+darkraider01@users.noreply.github.com> Date: Mon, 5 Oct 2026 21:21:02 +0530 Subject: [PATCH 1297/1309] Validate doc inline targets during parsing --- .../rustc_attr_parsing/src/attributes/doc.rs | 48 ++++++---------- tests/ui/rustdoc/doc-inline-validation.rs | 6 +- tests/ui/rustdoc/doc-inline-validation.stderr | 56 ++++++++++++++++--- 3 files changed, 68 insertions(+), 42 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/doc.rs b/compiler/rustc_attr_parsing/src/attributes/doc.rs index 017b8f397df66..7dc5c6ce9f2b8 100644 --- a/compiler/rustc_attr_parsing/src/attributes/doc.rs +++ b/compiler/rustc_attr_parsing/src/attributes/doc.rs @@ -11,8 +11,8 @@ use rustc_lint_defs::builtin::{INVALID_DOC_ATTRIBUTES, UNUSED_ATTRIBUTES}; use rustc_span::{Span, Symbol, edition, sym}; use super::prelude::{ALL_TARGETS, AllowedTargets}; -use super::{AcceptMapping, AttributeParser, FinalizeCheckFn, template}; -use crate::context::{AcceptContext, FinalizeCheckContext, FinalizeContext}; +use super::{AcceptMapping, AttributeParser, template}; +use crate::context::{AcceptContext, FinalizeContext}; use crate::diagnostics::{ AttrCrateLevelOnly, DocAliasBadChar, DocAliasDuplicated, DocAliasEmpty, DocAliasMalformed, DocAliasStartEnd, DocAttrNotCrateLevel, DocAttributeNotAttribute, DocAutoCfgExpectsHideOrShow, @@ -135,7 +135,6 @@ fn parse_keyword_and_attribute( pub(crate) struct DocParser { attribute: DocAttribute, nb_doc_attrs: usize, - inline_conflict: bool, } impl DocParser { @@ -264,21 +263,28 @@ impl DocParser { return; } - if self.inline_conflict { - return; - } - + let span = path.span(); if let Some((previous_inline, previous_span)) = self.attribute.inline { if previous_inline != inline { - let span = path.span(); let mut spans = MultiSpan::from_spans(vec![previous_span, span]); spans.push_span_label(previous_span, msg!("this attribute...")); spans.push_span_label(span, msg!("{\".\"}..conflicts with this attribute")); cx.emit_err(DocInlineConflict { spans }); - self.inline_conflict = true; } } else { - self.attribute.inline = Some((inline, path.span())); + self.attribute.inline = Some((inline, span)); + } + + match cx.target { + Target::Use | Target::ExternCrate => {} + _ => { + let item_span = cx.target_span; + cx.emit_lint( + INVALID_DOC_ATTRIBUTES, + DocInlineOnlyUse { attr_span: span, item_span }, + span, + ); + } } } @@ -757,20 +763,6 @@ impl DocParser { } } } - - fn finalize_check(cx: &mut FinalizeCheckContext<'_, '_>, span: Span) { - match cx.target { - Target::Use | Target::ExternCrate => {} - _ => { - let item_span = cx.target_span; - cx.emit_lint( - INVALID_DOC_ATTRIBUTES, - DocInlineOnlyUse { attr_span: span, item_span }, - span, - ); - } - } - } } impl AttributeParser for DocParser { @@ -846,12 +838,4 @@ impl AttributeParser for DocParser { None } } - - fn deferred_finalize_check(&self) -> Option<(FinalizeCheckFn, Span)> { - if self.inline_conflict { - return None; - } - let (_, span) = self.attribute.inline?; - Some((Self::finalize_check, span)) - } } diff --git a/tests/ui/rustdoc/doc-inline-validation.rs b/tests/ui/rustdoc/doc-inline-validation.rs index 56427ed931913..1cf1ca678528b 100644 --- a/tests/ui/rustdoc/doc-inline-validation.rs +++ b/tests/ui/rustdoc/doc-inline-validation.rs @@ -29,6 +29,8 @@ pub use std::panic; #[doc(inline)] //~^ ERROR conflicting doc inlining attributes //~| HELP remove one of the conflicting attributes +//~| ERROR conflicting doc inlining attributes +//~| HELP remove one of the conflicting attributes #[doc(no_inline, inline, no_inline)] pub use std::fmt; @@ -59,12 +61,14 @@ pub fn fn_allowed() {} //~^ ERROR this attribute can only be applied to a `use` item pub struct StructWithNoInline; -// Conflict on an invalid target, preserving diagnostic precedence +// Conflict on an invalid target #[deny(invalid_doc_attributes)] #[doc(inline)] //~^ ERROR conflicting doc inlining attributes //~| HELP remove one of the conflicting attributes +//~| ERROR this attribute can only be applied to a `use` item #[doc(no_inline)] +//~^ ERROR this attribute can only be applied to a `use` item pub struct ConflictOnStruct; // Malformed arguments without extra validation diagnostics diff --git a/tests/ui/rustdoc/doc-inline-validation.stderr b/tests/ui/rustdoc/doc-inline-validation.stderr index 2b720b8d11cdb..eb0368fa61b47 100644 --- a/tests/ui/rustdoc/doc-inline-validation.stderr +++ b/tests/ui/rustdoc/doc-inline-validation.stderr @@ -10,7 +10,18 @@ LL | #[doc(no_inline, inline, no_inline)] = help: remove one of the conflicting attributes error: conflicting doc inlining attributes - --> $DIR/doc-inline-validation.rs:35:7 + --> $DIR/doc-inline-validation.rs:29:7 + | +LL | #[doc(inline)] + | ^^^^^^ this attribute... +... +LL | #[doc(no_inline, inline, no_inline)] + | ^^^^^^^^^ ...conflicts with this attribute + | + = help: remove one of the conflicting attributes + +error: conflicting doc inlining attributes + --> $DIR/doc-inline-validation.rs:37:7 | LL | #[doc(no_inline)] | ^^^^^^^^^ this attribute... @@ -21,7 +32,7 @@ LL | #[doc(inline)] = help: remove one of the conflicting attributes error: conflicting doc inlining attributes - --> $DIR/doc-inline-validation.rs:42:7 + --> $DIR/doc-inline-validation.rs:44:7 | LL | #[doc(inline, no_inline)] | ^^^^^^ ^^^^^^^^^ ...conflicts with this attribute @@ -31,7 +42,7 @@ LL | #[doc(inline, no_inline)] = help: remove one of the conflicting attributes error: conflicting doc inlining attributes - --> $DIR/doc-inline-validation.rs:64:7 + --> $DIR/doc-inline-validation.rs:66:7 | LL | #[doc(inline)] | ^^^^^^ this attribute... @@ -42,7 +53,7 @@ LL | #[doc(no_inline)] = help: remove one of the conflicting attributes error: this attribute can only be applied to a `use` item - --> $DIR/doc-inline-validation.rs:49:7 + --> $DIR/doc-inline-validation.rs:51:7 | LL | #[doc(inline)] | ^^^^^^ only applicable on `use` items @@ -52,13 +63,13 @@ LL | pub fn fn_with_inline() {} | = note: read for more information note: the lint level is defined here - --> $DIR/doc-inline-validation.rs:48:8 + --> $DIR/doc-inline-validation.rs:50:8 | LL | #[deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ error: this attribute can only be applied to a `use` item - --> $DIR/doc-inline-validation.rs:58:7 + --> $DIR/doc-inline-validation.rs:60:7 | LL | #[doc(no_inline)] | ^^^^^^^^^ only applicable on `use` items @@ -68,13 +79,40 @@ LL | pub struct StructWithNoInline; | = note: read for more information note: the lint level is defined here - --> $DIR/doc-inline-validation.rs:57:8 + --> $DIR/doc-inline-validation.rs:59:8 + | +LL | #[deny(invalid_doc_attributes)] + | ^^^^^^^^^^^^^^^^^^^^^^ + +error: this attribute can only be applied to a `use` item + --> $DIR/doc-inline-validation.rs:66:7 + | +LL | #[doc(inline)] + | ^^^^^^ only applicable on `use` items +... +LL | pub struct ConflictOnStruct; + | ---------------------------- not a `use` item + | + = note: read for more information +note: the lint level is defined here + --> $DIR/doc-inline-validation.rs:65:8 | LL | #[deny(invalid_doc_attributes)] | ^^^^^^^^^^^^^^^^^^^^^^ +error: this attribute can only be applied to a `use` item + --> $DIR/doc-inline-validation.rs:70:7 + | +LL | #[doc(no_inline)] + | ^^^^^^^^^ only applicable on `use` items +LL | +LL | pub struct ConflictOnStruct; + | ---------------------------- not a `use` item + | + = note: read for more information + warning: didn't expect any arguments here - --> $DIR/doc-inline-validation.rs:71:14 + --> $DIR/doc-inline-validation.rs:75:14 | LL | #[doc(inline = "foo")] | ^^^^^^^ @@ -82,5 +120,5 @@ LL | #[doc(inline = "foo")] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: `#[warn(invalid_doc_attributes)]` on by default -error: aborting due to 6 previous errors; 1 warning emitted +error: aborting due to 9 previous errors; 1 warning emitted From e834c0c6aaf0cf69ac3b7ea0e078b863e07081b7 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Mon, 5 Oct 2026 17:48:31 +0200 Subject: [PATCH 1298/1309] Add some comments and docs related to `AllocatorNightly` --- library/alloc/src/rcs/arc.rs | 3 +++ library/alloc/src/rcs/rc.rs | 3 +++ library/core/src/alloc/mod.rs | 4 ++++ 3 files changed, 10 insertions(+) diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index ffa848998e9a2..8ae3c094b2910 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -264,6 +264,9 @@ macro_rules! acquire { )] pub struct Arc< T: ?Sized, + // FIXME: When stabilizing this parameter, the `AllocatorNightly` + // bound on the `From` impl *must* be weaked to `Allocator`, + // as `Box` is fundamental! #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index dd5c9e0013b95..696bd733b992d 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -324,6 +324,9 @@ fn rc_inner_layout_for_value_layout(layout: Layout) -> Layout { pub struct Rc< T: ?Sized, + // FIXME: When stabilizing this parameter, the `AllocatorNightly` + // bound on the `From` impl *must* be weaked to `Allocator`, + // as `Box` is fundamental! #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] A: Allocator = Global, > { ptr: NonNull>, diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 5066c0ccc21e7..c5825f97f4e78 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -769,6 +769,10 @@ unsafe impl StaticAllocator for &mut A {} /// /// This is to prevent stable code from e.g. constructing `Arc` /// using the `From> for Arc` impl. +/// +/// Note that this trait *will* be removed in the future, but downstream +/// allocators should still feel free to implement it on nightly, to +/// allow use of all containers with unstable allocator support #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub trait AllocatorNightly: Allocator {} From 64ac935164643e57b5510498057cc1fc2d1fc1ce Mon Sep 17 00:00:00 2001 From: Max Date: Mon, 5 Oct 2026 18:19:49 +0200 Subject: [PATCH 1299/1309] Update library/core/src/alloc/mod.rs Co-authored-by: Clar Fon <15850505+clarfonthey@users.noreply.github.com> --- library/core/src/alloc/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index c5825f97f4e78..e30872c09c793 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -772,7 +772,7 @@ unsafe impl StaticAllocator for &mut A {} /// /// Note that this trait *will* be removed in the future, but downstream /// allocators should still feel free to implement it on nightly, to -/// allow use of all containers with unstable allocator support +/// allow use of all containers with unstable allocator support. #[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] pub trait AllocatorNightly: Allocator {} From 2bc67f44dc804ab75a17a13eee7ecd8a1336bab1 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 5 Oct 2026 12:40:51 -0400 Subject: [PATCH 1300/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-10-05 (28221559263a3976766cf305940e80e30cf9ba8a). --- src/tools/rustfmt/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/rust-toolchain.toml b/src/tools/rustfmt/rust-toolchain.toml index 0d01929160891..05c048743fe34 100644 --- a/src/tools/rustfmt/rust-toolchain.toml +++ b/src/tools/rustfmt/rust-toolchain.toml @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-23" +channel = "nightly-2026-10-05" components = ["llvm-tools", "rustc-dev"] From 8333607cb095003db47b8c03e889c79e3a569df0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 10 Aug 2026 22:23:12 +0200 Subject: [PATCH 1301/1309] rustdoc: Only show useable impl items through `Deref` --- src/librustdoc/html/render/mod.rs | 212 +++++++++--------- .../rustdoc-html/deref/deref-to-primitive.rs | 12 +- 2 files changed, 117 insertions(+), 107 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 974672a050900..45c5f50a9cab9 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1884,10 +1884,12 @@ fn render_impl( let item_type = item.type_(); let name = item.name.as_ref().unwrap(); + let mut is_deref = false; let render_method_item = rendering_params.show_non_assoc_items && match render_mode { RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_ } => { + is_deref = true; should_render_item(item, deref_mut_, cx.tcx()) } }; @@ -1997,117 +1999,125 @@ fn render_impl( } } clean::RequiredAssocConstItem(generics, ty) => { - let source_id = format!("{item_type}.{name}"); - let id = cx.derive_id(&source_id); - write!( - w, - "", - assoc_const( - item, - generics, - ty, - AssocConstValue::None, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ), - )?; } clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => { - let source_id = format!("{item_type}.{name}"); - let id = cx.derive_id(&source_id); - write!( - w, - "
    \ - {}", - render_rightside(cx, item, render_mode), - )?; - if trait_.is_some() { - // Anchors are only used on trait impls. - write!(w, "§")?; + if !is_deref { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!( + w, + "
    \ + {}", + render_rightside(cx, item, render_mode), + )?; + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "§")?; + } + write!( + w, + "

    {}

    ", + assoc_const( + item, + &ci.generics, + &ci.type_, + match item.kind { + clean::ProvidedAssocConstItem(_) => + AssocConstValue::TraitDefault(&ci.kind), + clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind), + _ => unreachable!(), + }, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, + ), + )?; } - write!( - w, - "

    {}

    ", - assoc_const( - item, - &ci.generics, - &ci.type_, - match item.kind { - clean::ProvidedAssocConstItem(_) => - AssocConstValue::TraitDefault(&ci.kind), - clean::ImplAssocConstItem(_) => AssocConstValue::Impl(&ci.kind), - _ => unreachable!(), - }, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ), - )?; } clean::RequiredAssocTypeItem(generics, bounds) => { - let source_id = format!("{item_type}.{name}"); - let id = cx.derive_id(&source_id); - write!( - w, - "
    \ - {}", - render_rightside(cx, item, render_mode), - )?; - if trait_.is_some() { - // Anchors are only used on trait impls. - write!(w, "§")?; + if !is_deref { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!( + w, + "
    \ + {}", + render_rightside(cx, item, render_mode), + )?; + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "§")?; + } + write!( + w, + "

    {}

    ", + assoc_type( + item, + generics, + bounds, + None, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, + ), + )?; } - write!( - w, - "

    {}

    ", - assoc_type( - item, - generics, - bounds, - None, - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ), - )?; } clean::AssocTypeItem(tydef, _bounds) => { - let source_id = format!("{item_type}.{name}"); - let id = cx.derive_id(&source_id); - write!( - w, - "
    \ - {}", - render_rightside(cx, item, render_mode), - )?; - if trait_.is_some() { - // Anchors are only used on trait impls. - write!(w, "§")?; + if !is_deref { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!( + w, + "
    \ + {}", + render_rightside(cx, item, render_mode), + )?; + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "§")?; + } + write!( + w, + "

    {}

    ", + assoc_type( + item, + &tydef.generics, + &[], // intentionally leaving out bounds + Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)), + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, + ), + )?; } - write!( - w, - "

    {}

    ", - assoc_type( - item, - &tydef.generics, - &[], // intentionally leaving out bounds - Some(tydef.item_type.as_ref().unwrap_or(&tydef.type_)), - link.anchor(if trait_.is_some() { &source_id } else { &id }), - 0, - cx, - ), - )?; } clean::StrippedItem(..) => return Ok(()), _ => panic!("can't make docs for trait item with name {:?}", item.name), diff --git a/tests/rustdoc-html/deref/deref-to-primitive.rs b/tests/rustdoc-html/deref/deref-to-primitive.rs index 6fdc382b2213b..f0cc5129c28db 100644 --- a/tests/rustdoc-html/deref/deref-to-primitive.rs +++ b/tests/rustdoc-html/deref/deref-to-primitive.rs @@ -1,15 +1,15 @@ #![crate_name = "foo"] //@ has 'foo/struct.Foo.html' -//@ has - '//*[@id="deref-methods-i32"]' 'Methods from Deref' -//@ has - '//*[@id="deref-methods-i32-1"]//*[@id="associatedconstant.BITS"]/h4' \ -// 'pub const BITS: u32 = u32::BITS' -pub struct Foo(i32); +//@ has - '//*[@id="deref-methods-str"]' 'Methods from Deref' +//@ has - '//*[@id="deref-methods-str-1"]//*[@id="method.len"]/h4' \ +// 'pub ' +pub struct Foo(&'static str); impl std::ops::Deref for Foo { - type Target = i32; + type Target = str; fn deref(&self) -> &Self::Target { - &self.0 + self.0 } } From 843fa25bf60fce1e05ce7d16c965df0d36f3a6fe Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Mon, 5 Oct 2026 10:26:34 -0700 Subject: [PATCH 1302/1309] Revert "[win][arm64] Disable FS tests that require symlinks" This reverts commit 0cacc05531a4cf5229213e65eae2763ee4cf293e. --- library/std/src/fs/tests.rs | 16 ---------------- 1 file changed, 16 deletions(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 77fe185c4e286..1e402585dad3a 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1267,10 +1267,6 @@ fn recursive_mkdir_empty() { } #[test] -#[cfg_attr( - all(windows, target_arch = "aarch64"), - ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" -)] fn recursive_rmdir() { let tmpdir = tmpdir(); let d1 = tmpdir.join("d1"); @@ -1290,10 +1286,6 @@ fn recursive_rmdir() { } #[test] -#[cfg_attr( - all(windows, target_arch = "aarch64"), - ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" -)] fn recursive_rmdir_of_symlink() { // test we do not recursively delete a symlink but only dirs. let tmpdir = tmpdir(); @@ -2109,10 +2101,6 @@ fn file_open_not_found() { } #[test] -#[cfg_attr( - all(windows, target_arch = "aarch64"), - ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" -)] fn create_dir_all_with_junctions() { let tmpdir = tmpdir(); let target = tmpdir.join("target"); @@ -2649,10 +2637,6 @@ fn test_rename_symlink() { #[test] #[cfg(windows)] -#[cfg_attr( - all(windows, target_arch = "aarch64"), - ignore = "SymLinks not enabled on Arm64 Windows runners https://github.com/actions/partner-runner-images/issues/94" -)] fn test_rename_junction() { let tmpdir = tmpdir(); let original = tmpdir.join("original"); From d4e1f42e49c7146e8c18f266ce8bfe5e6be81bb0 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 11 Aug 2026 00:24:06 +0200 Subject: [PATCH 1303/1309] Correctly show methods taking `self` if the target type implements `Copy` --- src/librustdoc/clean/inline.rs | 5 +++ src/librustdoc/clean/mod.rs | 6 ++- src/librustdoc/clean/utils.rs | 27 ++++++++++++ src/librustdoc/formats/cache.rs | 4 ++ src/librustdoc/html/render/mod.rs | 48 ++++++++++++++-------- src/librustdoc/html/render/sidebar.rs | 28 +++++++++---- tests/rustdoc-html/deref/deref-copy.rs | 32 +++++++++++++++ tests/rustdoc-html/deref/deref-non-copy.rs | 30 ++++++++++++++ 8 files changed, 153 insertions(+), 27 deletions(-) create mode 100644 tests/rustdoc-html/deref/deref-copy.rs create mode 100644 tests/rustdoc-html/deref/deref-non-copy.rs diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 0a6c4ce6414a1..2306dd92ee515 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -602,6 +602,11 @@ pub(crate) fn build_impl( && polarity != ty::ImplPolarity::Negative { super::build_deref_target_impls(cx, &trait_items, ret); + if let Some(impl_item) = impl_item { + if let Some(for_def_id) = for_.def_id(&cx.cache) { + super::utils::compute_if_deref_target_implements_copy(cx, for_def_id, impl_item); + } + } } if !document_hidden { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index 09dbd279988f6..e6f2ceef385f1 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3102,15 +3102,19 @@ fn clean_impl<'tcx>( .map(|&ii| clean_impl_item(tcx.hir_impl_item(ii), cx)) .collect::>(); + let for_ = clean_ty(impl_.self_ty, cx); + // If this impl block is a positive implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. if trait_.as_ref().is_some_and(|t| tcx.lang_items().deref_trait() == Some(t.def_id())) && tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative { build_deref_target_impls(cx, &items, &mut ret); + if let Some(for_def_id) = for_.def_id(&cx.cache) { + compute_if_deref_target_implements_copy(cx, for_def_id, impl_); + } } - let for_ = clean_ty(impl_.self_ty, cx); let type_alias = for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) { DefKind::TyAlias => Some(clean_middle_ty( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 57e5ec2c4f0fb..67bd333fab015 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -294,6 +294,33 @@ pub(crate) fn build_deref_target_impls( inline::build_impls(cx, did, None, ret); }); } + } else { + break; + } + } +} + +pub(crate) fn compute_if_deref_target_implements_copy( + cx: &mut DocContext<'_>, + for_item_id: DefId, + impl_item: &hir::Impl<'_>, +) { + let tcx = cx.tcx; + for item in impl_item.items { + let item = tcx.hir_impl_item(*item); + if matches!(item.kind, hir::ImplItemKind::Type(_)) { + let item_def_id = item.owner_id.to_def_id(); + // If it's a Ctor, we need to retrieve the actual type. + let item_def_id = match tcx.def_kind(item_def_id) { + hir::def::DefKind::Ctor(_, _) => tcx.parent(item_def_id), + _ => item_def_id, + }; + let ty = tcx.type_of(item_def_id).instantiate_identity().skip_norm_wip(); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); + if tcx.type_is_copy_modulo_regions(typing_env, ty) { + cx.cache.types_which_deref_to_copy_target.insert(for_item_id); + } + break; } } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index 39baca1b4c0cd..bae6cee7d4081 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -168,6 +168,10 @@ pub(crate) struct Cache { /// to check if a stripped item should get its file generated or not: if it's inside a /// `#[doc(hidden)]` item or a private one and not inlined, it shouldn't get a file. pub(crate) inlined_items: DefIdSet, + + /// Contains the list of types `DefId` implementing `Deref` where the `Target` associated item + /// is a type implementing the `Copy` trait. + pub(crate) types_which_deref_to_copy_target: DefIdSet, } /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`. diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 45c5f50a9cab9..5b192cd0ac615 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1642,29 +1642,31 @@ fn render_deref_methods( Ok(()) } -fn should_render_item(item: &clean::Item, deref_mut_: bool, tcx: TyCtxt<'_>) -> bool { +fn should_render_item( + item: &clean::Item, + deref_mut_: bool, + tcx: TyCtxt<'_>, + target_is_copy: bool, +) -> bool { let self_type_opt = match item.kind { clean::MethodItem(ref method, _) => method.decl.receiver_type(), clean::RequiredMethodItem(ref method, _) => method.decl.receiver_type(), _ => None, }; - if let Some(self_ty) = self_type_opt { - let (by_mut_ref, by_box, by_value) = match *self_ty { - clean::Type::BorrowedRef { mutability, .. } => { - (mutability == Mutability::Mut, false, false) - } - clean::Type::Path { ref path } => { - (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) - } - clean::Type::SelfTy => (false, false, true), - _ => (false, false, false), - }; + let Some(self_ty) = self_type_opt else { return false }; + let (by_mut_ref, by_box, by_value) = match *self_ty { + clean::Type::BorrowedRef { mutability, .. } => { + (mutability == Mutability::Mut, false, false) + } + clean::Type::Path { ref path } => { + (false, Some(path.def_id()) == tcx.lang_items().owned_box(), false) + } + clean::Type::SelfTy => (false, false, true), + _ => (false, false, false), + }; - (deref_mut_ || !by_mut_ref) && !by_box && !by_value - } else { - false - } + (deref_mut_ || !by_mut_ref) && !by_box && (!by_value || target_is_copy) } /// `Box` has pass-through impls for `Read`, `Write`, `Iterator`, and `Future` when the @@ -1864,6 +1866,11 @@ fn render_impl( let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = >::with_capacity(2); + let is_copy_target = matches!(render_mode, RenderMode::ForDeref { .. }) + && parent.def_id().is_some_and(|def_id| { + cx.cache().types_which_deref_to_copy_target.contains(&def_id) + }); + // For trait implementations, the `interesting` output contains all methods that have doc // comments, and the `boring` output contains all methods that do not. The distinction is // used to allow hiding the boring methods. @@ -1880,6 +1887,7 @@ fn render_impl( is_default_item: bool, trait_: Option<&clean::Trait>, rendering_params: ImplRenderingParameters, + is_copy_target: bool, ) -> fmt::Result { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); @@ -1890,7 +1898,7 @@ fn render_impl( RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_ } => { is_deref = true; - should_render_item(item, deref_mut_, cx.tcx()) + should_render_item(item, deref_mut_, cx.tcx(), is_copy_target) } }; @@ -2170,6 +2178,7 @@ fn render_impl( false, trait_, rendering_params, + is_copy_target, )?; } _ => {} @@ -2188,6 +2197,7 @@ fn render_impl( false, trait_, rendering_params, + is_copy_target, )?; } for method in methods { @@ -2202,6 +2212,7 @@ fn render_impl( false, trait_, rendering_params, + is_copy_target, )?; } } @@ -2215,6 +2226,7 @@ fn render_impl( parent: &clean::Item, render_mode: RenderMode, rendering_params: ImplRenderingParameters, + is_copy_target: bool, ) -> fmt::Result { for trait_item in &t.items { // Skip over any default trait items that are impossible to reference @@ -2245,6 +2257,7 @@ fn render_impl( true, Some(t), rendering_params, + is_copy_target, )?; } Ok(()) @@ -2267,6 +2280,7 @@ fn render_impl( &i.impl_item, render_mode, rendering_params, + is_copy_target, )?; } if render_mode == RenderMode::Normal { diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 011079f9e4f2b..31da5ef3e1627 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -5,8 +5,7 @@ use std::fmt; use askama::Template; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::CtorKind; -use rustc_hir::def_id::{DefIdMap, DefIdSet}; -use rustc_middle::ty::TyCtxt; +use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet}; use tracing::debug; use super::{Context, ItemSection, impl_trait_key, item_ty_to_section}; @@ -454,7 +453,7 @@ fn sidebar_assoc_items<'a>( impl_, GetMethodsMode::AlsoCollectAssocFns { assoc_fns: &mut assoc_fns }, used_links_bor, - cx.tcx(), + cx, )); } // We want links' order to be reproducible so we don't use unstable sort. @@ -566,9 +565,12 @@ fn sidebar_deref_methods<'a>( .flat_map(|i| { get_methods( i.inner_impl(), - GetMethodsMode::Deref { deref_mut }, + GetMethodsMode::Deref { + deref_mut, + target_id: real_target.def_id(cx.cache()), + }, used_links, - cx.tcx(), + cx, ) .collect::>() }) @@ -756,7 +758,7 @@ fn get_next_url(used_links: &mut UsedLinks, url: String) -> String { } enum GetMethodsMode<'r, 'l> { - Deref { deref_mut: bool }, + Deref { deref_mut: bool, target_id: Option }, AlsoCollectAssocFns { assoc_fns: &'r mut Vec> }, } @@ -764,8 +766,16 @@ fn get_methods<'a>( i: &'a clean::Impl, mut mode: GetMethodsMode<'_, 'a>, used_links: &mut UsedLinks, - tcx: TyCtxt<'_>, + cx: &Context<'_>, ) -> impl Iterator> { + let is_copy_target = if let GetMethodsMode::Deref { target_id, .. } = mode { + target_id.is_some_and(|def_id| { + cx.shared.cache.types_which_deref_to_copy_target.contains(&def_id) + }) + } else { + false + }; + i.items.iter().filter_map(move |item| { if let Some(ref name) = item.name && item.is_method() @@ -777,8 +787,8 @@ fn get_methods<'a>( ) }; match &mut mode { - &mut GetMethodsMode::Deref { deref_mut } => { - if super::should_render_item(item, deref_mut, tcx) { + &mut GetMethodsMode::Deref { deref_mut, .. } => { + if super::should_render_item(item, deref_mut, cx.tcx(), is_copy_target) { Some(build_link()) } else { None diff --git a/tests/rustdoc-html/deref/deref-copy.rs b/tests/rustdoc-html/deref/deref-copy.rs new file mode 100644 index 0000000000000..331d4fad9290f --- /dev/null +++ b/tests/rustdoc-html/deref/deref-copy.rs @@ -0,0 +1,32 @@ +// This test ensures that when we `Deref` to a type implementing `Copy`, the +// methods with `self` are also kept. + +#![crate_name = "foo"] + +#[derive(Clone, Copy)] +pub struct Y; + +impl Y { + pub const ONE: X = X { y: Y }; + + pub fn foo() {} + pub fn bar(&self) {} + pub fn babar(self) {} +} + +// There should be `bar` and `babar` listed... and that's it! +//@ has 'foo/struct.X.html' +//@ count - '//*[@id="deref-methods-Y-1"]/section' 2 +//@ has - '//*[@id="deref-methods-Y-1"]/section[@id="method.bar"]' 'pub fn bar(&self)' +//@ has - '//*[@id="deref-methods-Y-1"]/section[@id="method.babar"]' 'pub fn babar(self)' +pub struct X { + y: Y, +} + +impl std::ops::Deref for X { + type Target = Y; + + fn deref(&self) -> &Self::Target { + &self.y + } +} diff --git a/tests/rustdoc-html/deref/deref-non-copy.rs b/tests/rustdoc-html/deref/deref-non-copy.rs new file mode 100644 index 0000000000000..6131b3afbf26a --- /dev/null +++ b/tests/rustdoc-html/deref/deref-non-copy.rs @@ -0,0 +1,30 @@ +// This test ensures that when we `Deref` to a type doesn't implement `Copy`, the +// methods with `self` are not kept. + +#![crate_name = "foo"] + +pub struct Y; + +impl Y { + pub const ONE: X = X { y: Y }; + + pub fn foo() {} + pub fn bar(&self) {} + pub fn babar(self) {} +} + +// There should be `bar` listed... and that's it! +//@ has 'foo/struct.X.html' +//@ count - '//*[@id="deref-methods-Y-1"]/section' 1 +//@ has - '//*[@id="deref-methods-Y-1"]/section[@id="method.bar"]' 'pub fn bar(&self)' +pub struct X { + y: Y, +} + +impl std::ops::Deref for X { + type Target = Y; + + fn deref(&self) -> &Self::Target { + &self.y + } +} From bc542453c02a90d37f85163c769adc49d4bc863f Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 12 Aug 2026 01:10:20 +0200 Subject: [PATCH 1304/1309] Compute "is copy" information directly in render instead of storing it in `Cache` --- src/librustdoc/clean/inline.rs | 5 -- src/librustdoc/clean/mod.rs | 6 +-- src/librustdoc/clean/utils.rs | 27 ----------- src/librustdoc/formats/cache.rs | 4 -- src/librustdoc/html/render/mod.rs | 66 ++++++++++++++++++--------- src/librustdoc/html/render/sidebar.rs | 35 ++++++-------- 6 files changed, 60 insertions(+), 83 deletions(-) diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs index 2306dd92ee515..0a6c4ce6414a1 100644 --- a/src/librustdoc/clean/inline.rs +++ b/src/librustdoc/clean/inline.rs @@ -602,11 +602,6 @@ pub(crate) fn build_impl( && polarity != ty::ImplPolarity::Negative { super::build_deref_target_impls(cx, &trait_items, ret); - if let Some(impl_item) = impl_item { - if let Some(for_def_id) = for_.def_id(&cx.cache) { - super::utils::compute_if_deref_target_implements_copy(cx, for_def_id, impl_item); - } - } } if !document_hidden { diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs index e6f2ceef385f1..09dbd279988f6 100644 --- a/src/librustdoc/clean/mod.rs +++ b/src/librustdoc/clean/mod.rs @@ -3102,19 +3102,15 @@ fn clean_impl<'tcx>( .map(|&ii| clean_impl_item(tcx.hir_impl_item(ii), cx)) .collect::>(); - let for_ = clean_ty(impl_.self_ty, cx); - // If this impl block is a positive implementation of the Deref trait, then we // need to try inlining the target's inherent impl blocks as well. if trait_.as_ref().is_some_and(|t| tcx.lang_items().deref_trait() == Some(t.def_id())) && tcx.impl_polarity(def_id) != ty::ImplPolarity::Negative { build_deref_target_impls(cx, &items, &mut ret); - if let Some(for_def_id) = for_.def_id(&cx.cache) { - compute_if_deref_target_implements_copy(cx, for_def_id, impl_); - } } + let for_ = clean_ty(impl_.self_ty, cx); let type_alias = for_.def_id(&cx.cache).and_then(|alias_def_id: DefId| match tcx.def_kind(alias_def_id) { DefKind::TyAlias => Some(clean_middle_ty( diff --git a/src/librustdoc/clean/utils.rs b/src/librustdoc/clean/utils.rs index 67bd333fab015..57e5ec2c4f0fb 100644 --- a/src/librustdoc/clean/utils.rs +++ b/src/librustdoc/clean/utils.rs @@ -294,33 +294,6 @@ pub(crate) fn build_deref_target_impls( inline::build_impls(cx, did, None, ret); }); } - } else { - break; - } - } -} - -pub(crate) fn compute_if_deref_target_implements_copy( - cx: &mut DocContext<'_>, - for_item_id: DefId, - impl_item: &hir::Impl<'_>, -) { - let tcx = cx.tcx; - for item in impl_item.items { - let item = tcx.hir_impl_item(*item); - if matches!(item.kind, hir::ImplItemKind::Type(_)) { - let item_def_id = item.owner_id.to_def_id(); - // If it's a Ctor, we need to retrieve the actual type. - let item_def_id = match tcx.def_kind(item_def_id) { - hir::def::DefKind::Ctor(_, _) => tcx.parent(item_def_id), - _ => item_def_id, - }; - let ty = tcx.type_of(item_def_id).instantiate_identity().skip_norm_wip(); - let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); - if tcx.type_is_copy_modulo_regions(typing_env, ty) { - cx.cache.types_which_deref_to_copy_target.insert(for_item_id); - } - break; } } } diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs index bae6cee7d4081..39baca1b4c0cd 100644 --- a/src/librustdoc/formats/cache.rs +++ b/src/librustdoc/formats/cache.rs @@ -168,10 +168,6 @@ pub(crate) struct Cache { /// to check if a stripped item should get its file generated or not: if it's inside a /// `#[doc(hidden)]` item or a private one and not inlined, it shouldn't get a file. pub(crate) inlined_items: DefIdSet, - - /// Contains the list of types `DefId` implementing `Deref` where the `Target` associated item - /// is a type implementing the `Copy` trait. - pub(crate) types_which_deref_to_copy_target: DefIdSet, } /// This struct is used to wrap the `cache` and `tcx` in order to run `DocFolder`. diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 5b192cd0ac615..2e48c319c8c72 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -100,14 +100,23 @@ pub(crate) fn ensure_trailing_slash(v: &str) -> impl fmt::Display { #[derive(Copy, Clone, Debug)] enum AssocItemRender<'a> { All, - DerefFor { trait_: &'a clean::Path, type_: &'a clean::Type, deref_mut_: bool }, + DerefFor { + trait_: &'a clean::Path, + type_: &'a clean::Type, + deref_mut_: bool, + deref_impl_def_id: DefId, + }, } impl AssocItemRender<'_> { - fn render_mode(&self) -> RenderMode { + fn render_mode(&self, tcx: TyCtxt<'_>) -> RenderMode { match self { Self::All => RenderMode::Normal, - &Self::DerefFor { deref_mut_, .. } => RenderMode::ForDeref { mut_: deref_mut_ }, + &Self::DerefFor { deref_mut_, deref_impl_def_id, .. } => { + let is_deref_target_copy = + compute_if_deref_target_implements_copy(tcx, deref_impl_def_id); + RenderMode::ForDeref { mut_: deref_mut_, is_deref_target_copy } + } } } @@ -121,7 +130,7 @@ impl AssocItemRender<'_> { #[derive(Copy, Clone, PartialEq)] enum RenderMode { Normal, - ForDeref { mut_: bool }, + ForDeref { mut_: bool, is_deref_target_copy: bool }, } // Helper structs for rendering items/sidebars and carrying along contextual @@ -1485,7 +1494,7 @@ fn render_assoc_items_inner( let (mut inherent_impls, trait_impls): (Vec<_>, _) = impls.iter().partition(|i| i.inner_impl().trait_.is_none()); if !inherent_impls.is_empty() { - let render_mode = what.render_mode(); + let render_mode = what.render_mode(cx.tcx()); let class_html = what .class() .map(|class| fmt::from_fn(move |f| write!(f, r#" class="{class}""#))) @@ -1623,8 +1632,12 @@ fn render_deref_methods( "Render deref methods for {for_:#?}, target {target:#?}", for_ = impl_.inner_impl().for_ ); - let what = - AssocItemRender::DerefFor { trait_: deref_type, type_: real_target, deref_mut_: deref_mut }; + let what = AssocItemRender::DerefFor { + trait_: deref_type, + type_: real_target, + deref_mut_: deref_mut, + deref_impl_def_id: impl_.def_id(), + }; if let Some(did) = target.def_id(cache) { if let Some(type_did) = impl_.inner_impl().for_.def_id(cache) { // `impl Deref for S` @@ -1866,11 +1879,6 @@ fn render_impl( let trait_ = i.trait_did().map(|did| &traits[&did]); let mut close_tags = >::with_capacity(2); - let is_copy_target = matches!(render_mode, RenderMode::ForDeref { .. }) - && parent.def_id().is_some_and(|def_id| { - cx.cache().types_which_deref_to_copy_target.contains(&def_id) - }); - // For trait implementations, the `interesting` output contains all methods that have doc // comments, and the `boring` output contains all methods that do not. The distinction is // used to allow hiding the boring methods. @@ -1887,7 +1895,6 @@ fn render_impl( is_default_item: bool, trait_: Option<&clean::Trait>, rendering_params: ImplRenderingParameters, - is_copy_target: bool, ) -> fmt::Result { let item_type = item.type_(); let name = item.name.as_ref().unwrap(); @@ -1896,9 +1903,9 @@ fn render_impl( let render_method_item = rendering_params.show_non_assoc_items && match render_mode { RenderMode::Normal => true, - RenderMode::ForDeref { mut_: deref_mut_ } => { + RenderMode::ForDeref { mut_: deref_mut_, is_deref_target_copy } => { is_deref = true; - should_render_item(item, deref_mut_, cx.tcx(), is_copy_target) + should_render_item(item, deref_mut_, cx.tcx(), is_deref_target_copy) } }; @@ -2178,7 +2185,6 @@ fn render_impl( false, trait_, rendering_params, - is_copy_target, )?; } _ => {} @@ -2197,7 +2203,6 @@ fn render_impl( false, trait_, rendering_params, - is_copy_target, )?; } for method in methods { @@ -2212,7 +2217,6 @@ fn render_impl( false, trait_, rendering_params, - is_copy_target, )?; } } @@ -2226,7 +2230,6 @@ fn render_impl( parent: &clean::Item, render_mode: RenderMode, rendering_params: ImplRenderingParameters, - is_copy_target: bool, ) -> fmt::Result { for trait_item in &t.items { // Skip over any default trait items that are impossible to reference @@ -2257,7 +2260,6 @@ fn render_impl( true, Some(t), rendering_params, - is_copy_target, )?; } Ok(()) @@ -2280,7 +2282,6 @@ fn render_impl( &i.impl_item, render_mode, rendering_params, - is_copy_target, )?; } if render_mode == RenderMode::Normal { @@ -3182,3 +3183,26 @@ fn repr_attribute<'tcx>( (!result.is_empty()).then(|| format!("#[repr({})]", result.join(", ")).into()) } + +pub(crate) fn compute_if_deref_target_implements_copy(tcx: TyCtxt<'_>, impl_def_id: DefId) -> bool { + if let Some(impl_def_id) = impl_def_id.as_local() + && let item = tcx.hir_expect_item(impl_def_id) + && let hir::ItemKind::Impl(impl_item) = item.kind + { + for item in impl_item.items { + let item = tcx.hir_impl_item(*item); + if matches!(item.kind, hir::ImplItemKind::Type(_)) { + let item_def_id = item.owner_id.to_def_id(); + // If it's a Ctor, we need to retrieve the actual type. + let item_def_id = match tcx.def_kind(item_def_id) { + hir::def::DefKind::Ctor(_, _) => tcx.parent(item_def_id), + _ => item_def_id, + }; + let ty = tcx.type_of(item_def_id).instantiate_identity().skip_norm_wip(); + let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); + return tcx.type_is_copy_modulo_regions(typing_env, ty); + } + } + } + false +} diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 31da5ef3e1627..3befbf2cff8ff 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -5,7 +5,8 @@ use std::fmt; use askama::Template; use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_hir::def::CtorKind; -use rustc_hir::def_id::{DefId, DefIdMap, DefIdSet}; +use rustc_hir::def_id::{DefIdMap, DefIdSet}; +use rustc_middle::ty::TyCtxt; use tracing::debug; use super::{Context, ItemSection, impl_trait_key, item_ty_to_section}; @@ -453,7 +454,7 @@ fn sidebar_assoc_items<'a>( impl_, GetMethodsMode::AlsoCollectAssocFns { assoc_fns: &mut assoc_fns }, used_links_bor, - cx, + cx.tcx(), )); } // We want links' order to be reproducible so we don't use unstable sort. @@ -547,7 +548,8 @@ fn sidebar_deref_methods<'a>( // Avoid infinite cycles return; } - let deref_mut = v.iter().any(|i| i.trait_did() == cx.tcx().lang_items().deref_mut_trait()); + let tcx = cx.tcx(); + let deref_mut = v.iter().any(|i| i.trait_did() == tcx.lang_items().deref_mut_trait()); let inner_impl = target .def_id(c) .or_else(|| { @@ -556,6 +558,8 @@ fn sidebar_deref_methods<'a>( .and_then(|did| c.impls.get(&did)); if let Some(impls) = inner_impl { debug!("found inner_impl: {impls:?}"); + let is_deref_target_copy = + super::compute_if_deref_target_implements_copy(tcx, impl_.def_id()); let mut ret = impls .iter() .filter(|i| { @@ -565,12 +569,9 @@ fn sidebar_deref_methods<'a>( .flat_map(|i| { get_methods( i.inner_impl(), - GetMethodsMode::Deref { - deref_mut, - target_id: real_target.def_id(cx.cache()), - }, + GetMethodsMode::Deref { deref_mut, is_deref_target_copy }, used_links, - cx, + tcx, ) .collect::>() }) @@ -604,7 +605,7 @@ fn sidebar_deref_methods<'a>( i.inner_impl() .trait_ .as_ref() - .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait()) + .map(|t| Some(t.def_id()) == tcx.lang_items().deref_trait()) .unwrap_or(false) && !i.is_negative_trait_impl() }) @@ -758,7 +759,7 @@ fn get_next_url(used_links: &mut UsedLinks, url: String) -> String { } enum GetMethodsMode<'r, 'l> { - Deref { deref_mut: bool, target_id: Option }, + Deref { deref_mut: bool, is_deref_target_copy: bool }, AlsoCollectAssocFns { assoc_fns: &'r mut Vec> }, } @@ -766,16 +767,8 @@ fn get_methods<'a>( i: &'a clean::Impl, mut mode: GetMethodsMode<'_, 'a>, used_links: &mut UsedLinks, - cx: &Context<'_>, + tcx: TyCtxt<'_>, ) -> impl Iterator> { - let is_copy_target = if let GetMethodsMode::Deref { target_id, .. } = mode { - target_id.is_some_and(|def_id| { - cx.shared.cache.types_which_deref_to_copy_target.contains(&def_id) - }) - } else { - false - }; - i.items.iter().filter_map(move |item| { if let Some(ref name) = item.name && item.is_method() @@ -787,8 +780,8 @@ fn get_methods<'a>( ) }; match &mut mode { - &mut GetMethodsMode::Deref { deref_mut, .. } => { - if super::should_render_item(item, deref_mut, cx.tcx(), is_copy_target) { + &mut GetMethodsMode::Deref { deref_mut, is_deref_target_copy } => { + if super::should_render_item(item, deref_mut, tcx, is_deref_target_copy) { Some(build_link()) } else { None From b0d156733d25f7b07c3b02fceb3e8c996142828c Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Fri, 11 Sep 2026 15:00:14 +0200 Subject: [PATCH 1305/1309] Improve code --- src/librustdoc/html/render/mod.rs | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 2e48c319c8c72..03c31859bfff7 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -1899,12 +1899,10 @@ fn render_impl( let item_type = item.type_(); let name = item.name.as_ref().unwrap(); - let mut is_deref = false; let render_method_item = rendering_params.show_non_assoc_items && match render_mode { RenderMode::Normal => true, RenderMode::ForDeref { mut_: deref_mut_, is_deref_target_copy } => { - is_deref = true; should_render_item(item, deref_mut_, cx.tcx(), is_deref_target_copy) } }; @@ -2014,7 +2012,7 @@ fn render_impl( } } clean::RequiredAssocConstItem(generics, ty) => { - if !is_deref { + if !matches!(render_mode, RenderMode::ForDeref { .. }) { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!( @@ -2043,7 +2041,7 @@ fn render_impl( } } clean::ProvidedAssocConstItem(ci) | clean::ImplAssocConstItem(ci) => { - if !is_deref { + if !matches!(render_mode, RenderMode::ForDeref { .. }) { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!( @@ -2077,7 +2075,7 @@ fn render_impl( } } clean::RequiredAssocTypeItem(generics, bounds) => { - if !is_deref { + if !matches!(render_mode, RenderMode::ForDeref { .. }) { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!( @@ -2106,7 +2104,7 @@ fn render_impl( } } clean::AssocTypeItem(tydef, _bounds) => { - if !is_deref { + if !matches!(render_mode, RenderMode::ForDeref { .. }) { let source_id = format!("{item_type}.{name}"); let id = cx.derive_id(&source_id); write!( @@ -3193,11 +3191,6 @@ pub(crate) fn compute_if_deref_target_implements_copy(tcx: TyCtxt<'_>, impl_def_ let item = tcx.hir_impl_item(*item); if matches!(item.kind, hir::ImplItemKind::Type(_)) { let item_def_id = item.owner_id.to_def_id(); - // If it's a Ctor, we need to retrieve the actual type. - let item_def_id = match tcx.def_kind(item_def_id) { - hir::def::DefKind::Ctor(_, _) => tcx.parent(item_def_id), - _ => item_def_id, - }; let ty = tcx.type_of(item_def_id).instantiate_identity().skip_norm_wip(); let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); return tcx.type_is_copy_modulo_regions(typing_env, ty); From 32561a045e10c277b199cb7a3c2818651422ebd6 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Mon, 5 Oct 2026 19:40:54 +0200 Subject: [PATCH 1306/1309] Fix import errors --- src/librustdoc/html/render/mod.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs index 03c31859bfff7..c2d8cc9ebae3e 100644 --- a/src/librustdoc/html/render/mod.rs +++ b/src/librustdoc/html/render/mod.rs @@ -3185,11 +3185,11 @@ fn repr_attribute<'tcx>( pub(crate) fn compute_if_deref_target_implements_copy(tcx: TyCtxt<'_>, impl_def_id: DefId) -> bool { if let Some(impl_def_id) = impl_def_id.as_local() && let item = tcx.hir_expect_item(impl_def_id) - && let hir::ItemKind::Impl(impl_item) = item.kind + && let rustc_hir::ItemKind::Impl(impl_item) = item.kind { for item in impl_item.items { let item = tcx.hir_impl_item(*item); - if matches!(item.kind, hir::ImplItemKind::Type(_)) { + if matches!(item.kind, rustc_hir::ImplItemKind::Type(_)) { let item_def_id = item.owner_id.to_def_id(); let ty = tcx.type_of(item_def_id).instantiate_identity().skip_norm_wip(); let typing_env = ty::TypingEnv::non_body_analysis(tcx, item_def_id); From c75ec7eb954249fa08ac33aaf4fd92fc8eb84b8a Mon Sep 17 00:00:00 2001 From: Daniel Paoliello Date: Mon, 5 Oct 2026 10:49:59 -0700 Subject: [PATCH 1307/1309] Only create a symlink in recursive_rmdir if we have permissions to do so --- library/std/src/fs/tests.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 1e402585dad3a..9485663f21ad7 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1278,7 +1278,9 @@ fn recursive_rmdir() { check!(fs::create_dir_all(&d2)); check!(check!(File::create(&canary)).write(b"foo")); check!(junction_point(&d2, &dt.join("d2"))); - let _ = symlink_file(&canary, &d1.join("canary")); + if got_symlink_permission(&tmpdir) { + let _ = symlink_file(&canary, &d1.join("canary")); + } check!(fs::remove_dir_all(&d1)); assert!(!d1.is_dir()); From f614da46fc69df644d8e6ae0a8a0c68dc790f174 Mon Sep 17 00:00:00 2001 From: Josh Stone Date: Mon, 5 Oct 2026 13:50:54 -0700 Subject: [PATCH 1308/1309] Trim trailing whitespace from `RELEASES.md` These trailing spaces are fairly old, back in 1.87.0, but my editor has been flagging them as warnings. --- RELEASES.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/RELEASES.md b/RELEASES.md index cd1f3ca7c3800..b4dc100f5d5f1 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1537,7 +1537,7 @@ for more information on Rust's tiered platform support. Libraries --------- - [Stabilize the anonymous pipe API](https://github.com/rust-lang/rust/issues/127154) -- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375) +- [Add support for unbounded left/right shift operations](https://github.com/rust-lang/rust/issues/129375) - [Print pointer metadata in `Debug` impl of raw pointers](https://github.com/rust-lang/rust/pull/135080) - [`Vec::with_capacity` guarantees it allocates with the amount requested, even if `Vec::capacity` returns a different number.](https://github.com/rust-lang/rust/pull/135933) - Most `std::arch` intrinsics which don't take pointer arguments can now be called from safe code if the caller has the appropriate target features already enabled (https://github.com/rust-lang/stdarch/pull/1714, https://github.com/rust-lang/stdarch/pull/1716, https://github.com/rust-lang/stdarch/pull/1717) @@ -1611,7 +1611,7 @@ These previously stable APIs are now stable in const contexts: - [`char::is_digit`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_digit) - [`char::is_whitespace`](https://doc.rust-lang.org/stable/std/primitive.char.html#method.is_whitespace) - [`<[[T; N]]>::as_flattened`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened) -- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut) +- [`<[[T; N]]>::as_flattened_mut`](https://doc.rust-lang.org/stable/std/primitive.slice.html#method.as_flattened_mut) - [`String::into_bytes`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.into_bytes) - [`String::as_str`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.as_str) - [`String::capacity`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.capacity) From 23daa0c375858c33e406a4b24420b07508b4bba3 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Wed, 7 Oct 2026 12:14:53 +0800 Subject: [PATCH 1309/1309] remove redundant unsafe --- library/core/src/hint.rs | 4 ++-- .../stdarch/crates/core_arch/src/arm_shared/hints.rs | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/hint.rs b/library/core/src/hint.rs index 90326e649058b..616bdd9a97b7c 100644 --- a/library/core/src/hint.rs +++ b/library/core/src/hint.rs @@ -300,11 +300,11 @@ pub fn spin_loop() { all(target_feature = "v6", target_feature = "mclass"), ) ) => { - // SAFETY: the `cfg` attr ensures that we only execute this on arm + // The `cfg` attr ensures that we only execute this on arm // targets with support for the this feature. On ARMv6 in Thumb // mode, T2 is required (see Arm DDI0406C Section A8.8.427), // otherwise ARMv6-M or ARMv6K is enough - unsafe { crate::arch::arm::__yield() } + crate::arch::arm::__yield() } target_arch = "loongarch32" => crate::arch::loongarch32::ibar::<0>(), target_arch = "loongarch64" => crate::arch::loongarch64::ibar::<0>(), diff --git a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs index ce64e8341e7eb..f60c107a2aaf3 100644 --- a/library/stdarch/crates/core_arch/src/arm_shared/hints.rs +++ b/library/stdarch/crates/core_arch/src/arm_shared/hints.rs @@ -17,7 +17,7 @@ ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __wfi() { +pub fn __wfi() { hint(HINT_WFI); } @@ -36,7 +36,7 @@ pub unsafe fn __wfi() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __wfe() { +pub fn __wfe() { hint(HINT_WFE); } @@ -54,7 +54,7 @@ pub unsafe fn __wfe() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __sev() { +pub fn __sev() { hint(HINT_SEV); } @@ -72,7 +72,7 @@ pub unsafe fn __sev() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __sevl() { +pub fn __sevl() { hint(HINT_SEVL); } @@ -94,7 +94,7 @@ pub unsafe fn __sevl() { ))] #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __yield() { +pub fn __yield() { hint(HINT_YIELD); } @@ -106,7 +106,7 @@ pub unsafe fn __yield() { /// will increase execution time. #[inline(always)] #[unstable(feature = "stdarch_arm_hints", issue = "117218")] -pub unsafe fn __nop() { +pub fn __nop() { crate::arch::asm!("nop", options(nomem, nostack, preserves_flags)); }
    \ - {}", - render_rightside(cx, item, render_mode) - )?; - if trait_.is_some() { - // Anchors are only used on trait impls. - write!(w, "§")?; + if !is_deref { + let source_id = format!("{item_type}.{name}"); + let id = cx.derive_id(&source_id); + write!( + w, + "
    \ + {}", + render_rightside(cx, item, render_mode) + )?; + if trait_.is_some() { + // Anchors are only used on trait impls. + write!(w, "§")?; + } + write!( + w, + "

    {}

    ", + assoc_const( + item, + generics, + ty, + AssocConstValue::None, + link.anchor(if trait_.is_some() { &source_id } else { &id }), + 0, + cx, + ), + )?; } - write!( - w, - "

    {}

    ::fetch_xor`]: AtomicPtr::fetch_xor #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_xor( @@ -288,8 +414,16 @@ pub const unsafe fn atomic_xor( /// Maximum with the current value using a signed comparison. /// `T` must be a signed integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_max`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_max` method. For example, [`AtomicI32::fetch_max`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_max`]: AtomicI32::fetch_max #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_max(dst: *mut T, src: T) -> T; @@ -297,8 +431,16 @@ pub const unsafe fn atomic_max(dst: *mut T, /// Minimum with the current value using a signed comparison. /// `T` must be a signed integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_min`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] signed integer types via the `fetch_min` method. For example, [`AtomicI32::fetch_min`]. +/// +/// [`Atomic::from_ptr`]: AtomicI32::from_ptr +/// [`Atomic::fetch_min`]: AtomicI32::fetch_min #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_min(dst: *mut T, src: T) -> T; @@ -306,8 +448,16 @@ pub const unsafe fn atomic_min(dst: *mut T, /// Minimum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_min`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_min` method. For example, [`AtomicU32::fetch_min`]. +/// +/// [`Atomic::from_ptr`]: AtomicU32::from_ptr +/// [`Atomic::fetch_min`]: AtomicU32::fetch_min #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_umin(dst: *mut T, src: T) -> T; @@ -315,8 +465,16 @@ pub const unsafe fn atomic_umin(dst: *mut T, /// Maximum with the current value using an unsigned comparison. /// `T` must be an unsigned integer type. /// +/// # Safety +/// +/// This is equivalent to [`Atomic::from_ptr`] followed by [`Atomic::fetch_max`]. +/// Refer to the documentation of [`Atomic::from_ptr`] for safety requirements. +/// /// The stabilized version of this intrinsic is available on the /// [`atomic`] unsigned integer types via the `fetch_max` method. For example, [`AtomicU32::fetch_max`]. +/// +/// [`Atomic::from_ptr`]: AtomicU32::from_ptr +/// [`Atomic::fetch_max`]: AtomicU32::fetch_max #[rustc_intrinsic] #[rustc_nounwind] pub const unsafe fn atomic_umax(dst: *mut T, src: T) -> T; From af8125b742e4414ce35960353810a1174326bbd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jana=20D=C3=B6nszelmann?= Date: Wed, 23 Sep 2026 13:50:06 +0200 Subject: [PATCH 0942/1309] x perf takes database path --- src/bootstrap/src/core/build_steps/perf.rs | 21 +++++++++++++-- src/etc/completions/x.fish | 5 ++++ src/etc/completions/x.ps1 | 5 ++++ src/etc/completions/x.py.fish | 5 ++++ src/etc/completions/x.py.ps1 | 5 ++++ src/etc/completions/x.py.sh | 30 ++++++++++++++++++---- src/etc/completions/x.py.zsh | 5 ++++ src/etc/completions/x.sh | 30 ++++++++++++++++++---- src/etc/completions/x.zsh | 5 ++++ 9 files changed, 99 insertions(+), 12 deletions(-) diff --git a/src/bootstrap/src/core/build_steps/perf.rs b/src/bootstrap/src/core/build_steps/perf.rs index 930f114f1a70e..e01ff61eb6f86 100644 --- a/src/bootstrap/src/core/build_steps/perf.rs +++ b/src/bootstrap/src/core/build_steps/perf.rs @@ -1,5 +1,6 @@ use std::env::consts::EXE_EXTENSION; use std::fmt::{Display, Formatter}; +use std::path::PathBuf; use crate::core::build_steps::compile::Sysroot; use crate::core::build_steps::tool::{RustcPerf, Rustdoc}; @@ -50,6 +51,9 @@ enum PerfCommand { /// The name of the modified artifact to be compared. modified: String, + + #[clap(long, global = true)] + database_path: Option, }, } @@ -87,6 +91,9 @@ struct SharedOpts { /// Select the profiles that should be benchmarked. #[clap(long, global = true, value_delimiter = ',', default_value = "Check,Debug,Opt")] profiles: Vec, + + #[clap(long, global = true)] + database_path: Option, } #[derive(Clone, Copy, Debug, PartialEq, clap::ValueEnum)] @@ -152,7 +159,17 @@ pub fn perf(builder: &Builder<'_>, args: &PerfArgs, trailing_args: &[String]) { // with compile-time benchmarks. cmd.current_dir(builder.src.join("src/tools/rustc-perf")); - let db_path = results_dir.join("results.db"); + let db_path = args + .cmd + .shared_opts() + .and_then(|i| i.database_path.as_ref()) + .or(if let PerfCommand::Compare { database_path: Some(path), .. } = &args.cmd { + Some(path) + } else { + None + }) + .map(|i| PathBuf::from(i.as_str())) + .unwrap_or_else(|| results_dir.join("results.db")); let is_profiling = match &args.cmd { PerfCommand::Eprintln { .. } @@ -214,7 +231,7 @@ Consider setting `rust.debuginfo-level = 1` in `bootstrap.toml`."#); cmd.args(trailing_args); cmd.run(builder); } - PerfCommand::Compare { base, modified } => { + PerfCommand::Compare { base, modified, database_path: _ } => { cmd.arg("bench_cmp"); cmd.arg("--db").arg(&db_path); cmd.arg(base).arg(modified); diff --git a/src/etc/completions/x.fish b/src/etc/completions/x.fish index 58c5e4255caf6..4ce38dd42033a 100644 --- a/src/etc/completions/x.fish +++ b/src/etc/completions/x.fish @@ -920,6 +920,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l database-path -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'host target of the stage0 compiler' -r -f @@ -959,6 +960,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l database-path -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'host target of the stage0 compiler' -r -f @@ -998,6 +1000,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l database-path -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'host target of the stage0 compiler' -r -f @@ -1037,6 +1040,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l database-path -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'host target of the stage0 compiler' -r -f @@ -1072,6 +1076,7 @@ complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_fro complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-std-check-if-no-download-rustc -d 'Skip checking the standard library if `rust.download-rustc` isn\'t available. This is mostly for RA as building the stage1 compiler to check the library tree on each code change might be too much for some computers' complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l database-path -r complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l config -d 'TOML configuration file for build' -r -F complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x -n "__fish_x_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build -d 'host target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.ps1 b/src/etc/completions/x.ps1 index bf7ed50a85b90..61a4d0d65de91 100644 --- a/src/etc/completions/x.ps1 +++ b/src/etc/completions/x.ps1 @@ -1093,6 +1093,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1140,6 +1141,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1187,6 +1189,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1234,6 +1237,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1277,6 +1281,7 @@ Register-ArgumentCompleter -Native -CommandName 'x' -ScriptBlock { break } 'x;perf;compare' { + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish index 292408fbe49f6..28b1767fc0e96 100644 --- a/src/etc/completions/x.py.fish +++ b/src/etc/completions/x.py.fish @@ -920,6 +920,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l database-path -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from eprintln" -l build -d 'host target of the stage0 compiler' -r -f @@ -959,6 +960,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l database-path -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from samply" -l build -d 'host target of the stage0 compiler' -r -f @@ -998,6 +1000,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l database-path -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from cachegrind" -l build -d 'host target of the stage0 compiler' -r -f @@ -1037,6 +1040,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l exclude -d 'Select the benchmarks matching a prefix in this comma-separated list that you don\'t want to run' -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l scenarios -d 'Select the scenarios that should be benchmarked' -r -f -a "{Full\t'',IncrFull\t'',IncrUnchanged\t'',IncrPatched\t''}" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l profiles -d 'Select the profiles that should be benchmarked' -r -f -a "{Check\t'',Debug\t'',Doc\t'',DocJson\t'',Opt\t'',Clippy\t''}" +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l database-path -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l build -d 'host target of the stage0 compiler' -r -f @@ -1072,6 +1076,7 @@ complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcomma complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-stage0-validation -d 'Skip stage0 compiler validation' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -l skip-std-check-if-no-download-rustc -d 'Skip checking the standard library if `rust.download-rustc` isn\'t available. This is mostly for RA as building the stage1 compiler to check the library tree on each code change might be too much for some computers' complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from benchmark" -s h -l help -d 'Print help (see more with \'--help\')' +complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l database-path -r complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l config -d 'TOML configuration file for build' -r -F complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build-dir -d 'Build directory, overrides `build.build-dir` in `bootstrap.toml`' -r -f -a "(__fish_complete_directories)" complete -c x.py -n "__fish_x.py_using_subcommand perf; and __fish_seen_subcommand_from compare" -l build -d 'host target of the stage0 compiler' -r -f diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1 index 5ab4cab3a32a3..7178833189ac6 100644 --- a/src/etc/completions/x.py.ps1 +++ b/src/etc/completions/x.py.ps1 @@ -1093,6 +1093,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1140,6 +1141,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1187,6 +1189,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1234,6 +1237,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { [CompletionResult]::new('--exclude', '--exclude', [CompletionResultType]::ParameterName, 'Select the benchmarks matching a prefix in this comma-separated list that you don''t want to run') [CompletionResult]::new('--scenarios', '--scenarios', [CompletionResultType]::ParameterName, 'Select the scenarios that should be benchmarked') [CompletionResult]::new('--profiles', '--profiles', [CompletionResultType]::ParameterName, 'Select the profiles that should be benchmarked') + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') @@ -1277,6 +1281,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock { break } 'x.py;perf;compare' { + [CompletionResult]::new('--database-path', '--database-path', [CompletionResultType]::ParameterName, 'database-path') [CompletionResult]::new('--config', '--config', [CompletionResultType]::ParameterName, 'TOML configuration file for build') [CompletionResult]::new('--build-dir', '--build-dir', [CompletionResultType]::ParameterName, 'Build directory, overrides `build.build-dir` in `bootstrap.toml`') [CompletionResult]::new('--build', '--build', [CompletionResultType]::ParameterName, 'host target of the stage0 compiler') diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh index 0c449988b0461..f1b35e4cbc894 100644 --- a/src/etc/completions/x.py.sh +++ b/src/etc/completions/x.py.sh @@ -3094,7 +3094,7 @@ _x.py() { return 0 ;; x.py__perf__benchmark) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3116,6 +3116,10 @@ _x.py() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3292,7 +3296,7 @@ _x.py() { return 0 ;; x.py__perf__cachegrind) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3314,6 +3318,10 @@ _x.py() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3490,12 +3498,16 @@ _x.py() { return 0 ;; x.py__perf__compare) - opts="-v -q -i -j -h --verbose --quiet --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3676,7 +3688,7 @@ _x.py() { return 0 ;; x.py__perf__eprintln) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3698,6 +3710,10 @@ _x.py() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3874,7 +3890,7 @@ _x.py() { return 0 ;; x.py__perf__samply) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3896,6 +3912,10 @@ _x.py() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh index 9ee5843a5abd7..8376e44746052 100644 --- a/src/etc/completions/x.py.zsh +++ b/src/etc/completions/x.py.zsh @@ -1123,6 +1123,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1172,6 +1173,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1221,6 +1223,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1270,6 +1273,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1316,6 +1320,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (compare) _arguments "${_arguments_options[@]}" : \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ diff --git a/src/etc/completions/x.sh b/src/etc/completions/x.sh index f8897cc5f5ec8..be81e2e743e7c 100644 --- a/src/etc/completions/x.sh +++ b/src/etc/completions/x.sh @@ -3094,7 +3094,7 @@ _x() { return 0 ;; x__perf__benchmark) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3116,6 +3116,10 @@ _x() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3292,7 +3296,7 @@ _x() { return 0 ;; x__perf__cachegrind) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3314,6 +3318,10 @@ _x() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3490,12 +3498,16 @@ _x() { return 0 ;; x__perf__compare) - opts="-v -q -i -j -h --verbose --quiet --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 fi case "${prev}" in + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3676,7 +3688,7 @@ _x() { return 0 ;; x__perf__eprintln) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3698,6 +3710,10 @@ _x() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then @@ -3874,7 +3890,7 @@ _x() { return 0 ;; x__perf__samply) - opts="-v -q -i -j -h --include --exclude --scenarios --profiles --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." + opts="-v -q -i -j -h --include --exclude --scenarios --profiles --database-path --verbose --quiet --incremental --config --build-dir --build --host --target --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --json-output --compile-time-deps --color --bypass-bootstrap-lock --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --ci --skip-std-check-if-no-download-rustc --help [PATHS]... [ARGS]..." if [[ ${cur} == -* || ${COMP_CWORD} -eq 3 ]] ; then COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") ) return 0 @@ -3896,6 +3912,10 @@ _x() { COMPREPLY=($(compgen -W "Check Debug Doc DocJson Opt Clippy" -- "${cur}")) return 0 ;; + --database-path) + COMPREPLY=($(compgen -f "${cur}")) + return 0 + ;; --config) local oldifs if [ -n "${IFS+x}" ]; then diff --git a/src/etc/completions/x.zsh b/src/etc/completions/x.zsh index f61942a11da4a..3159859c1ea8e 100644 --- a/src/etc/completions/x.zsh +++ b/src/etc/completions/x.zsh @@ -1123,6 +1123,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1172,6 +1173,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1221,6 +1223,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1270,6 +1273,7 @@ _arguments "${_arguments_options[@]}" : \ '*--exclude=[Select the benchmarks matching a prefix in this comma-separated list that you don'\''t want to run]:EXCLUDE:_default' \ '*--scenarios=[Select the scenarios that should be benchmarked]:SCENARIOS:(Full IncrFull IncrUnchanged IncrPatched)' \ '*--profiles=[Select the profiles that should be benchmarked]:PROFILES:(Check Debug Doc DocJson Opt Clippy)' \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ @@ -1316,6 +1320,7 @@ _arguments "${_arguments_options[@]}" : \ ;; (compare) _arguments "${_arguments_options[@]}" : \ +'--database-path=[]:DATABASE_PATH:_default' \ '--config=[TOML configuration file for build]:FILE:_files' \ '--build-dir=[Build directory, overrides \`build.build-dir\` in \`bootstrap.toml\`]:DIR:_files -/' \ '--build=[host target of the stage0 compiler]:BUILD:' \ From 26b5f90dd7f716ffbba11ffc7b04415b5a72b342 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 28 Sep 2026 16:41:56 +0800 Subject: [PATCH 0943/1309] Move `alloc::rc` into `alloc::rcs` --- library/alloc/src/lib.rs | 12 ++++++++++-- library/alloc/src/{ => rcs}/rc.rs | 0 src/etc/natvis/liballoc.natvis | 8 ++++---- src/tools/miri/tests/fail/memleak_rc.stderr | 4 ++-- tests/debuginfo/rc_arc.rs | 12 ++++++------ tests/debuginfo/strings-and-strs.rs | 6 +++--- .../methods/shadowed-intrinsic-method-deref.stderr | 2 +- 7 files changed, 26 insertions(+), 18 deletions(-) rename library/alloc/src/{ => rcs}/rc.rs (100%) diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index de6830a514656..60ada2ba866bb 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -230,12 +230,22 @@ // from other crates, but since this can only appear for lang items, it doesn't seem worth fixing. #![feature(intra_doc_pointers)] +#[cfg(not(no_rc))] +#[stable(feature = "rust1", since = "1.0.0")] +pub use rcs::rc; + // Module with internal macros used by other modules (needs to be included before other modules). #[macro_use] mod macros; mod raw_vec; +/// Implementations of reference-counted pointers. +#[cfg(not(no_rc))] +mod rcs { + pub mod rc; +} + // Heaps provided for low-level allocation strategies pub mod alloc; @@ -256,8 +266,6 @@ pub mod intrinsics; #[unstable(feature = "alloc_io", issue = "154046")] pub mod io; pub mod panicking; -#[cfg(not(no_rc))] -pub mod rc; pub mod slice; pub mod str; pub mod string; diff --git a/library/alloc/src/rc.rs b/library/alloc/src/rcs/rc.rs similarity index 100% rename from library/alloc/src/rc.rs rename to library/alloc/src/rcs/rc.rs diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index b56f6f5800eee..cfcca9014e70c 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -72,7 +72,7 @@ it is necessary for them. --> - + {ptr.pointer->value} @@ -87,7 +87,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -102,7 +102,7 @@ - + {ptr.pointer->value} @@ -117,7 +117,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length diff --git a/src/tools/miri/tests/fail/memleak_rc.stderr b/src/tools/miri/tests/fail/memleak_rc.stderr index a77cf55b0c317..26156050ae5d3 100644 --- a/src/tools/miri/tests/fail/memleak_rc.stderr +++ b/src/tools/miri/tests/fail/memleak_rc.stderr @@ -1,5 +1,5 @@ error: memory leaked: ALLOC (Rust heap, SIZE, ALIGN), allocated here: - --> RUSTLIB/alloc/src/rc.rs:LL:CC + --> RUSTLIB/alloc/src/rcs/rc.rs:LL:CC | LL | Self::from_inner(Box::into_non_null(Box::new(RcInner { | _________________________________________________^ @@ -11,7 +11,7 @@ LL | | }))) | = note: stack backtrace: 0: std::rc::Rc::>>::new - at RUSTLIB/alloc/src/rc.rs:LL:CC + at RUSTLIB/alloc/src/rcs/rc.rs:LL:CC 1: main at tests/fail/memleak_rc.rs:LL:CC diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index 4399dfe54e7a5..39b5dc0d84408 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -27,12 +27,12 @@ //@ cdb-command:g //@ cdb-command:dx rc,d -//@ cdb-check:rc,d : 111 [Type: alloc::rc::Rc] +//@ cdb-check:rc,d : 111 [Type: alloc::rcs::rc::Rc] //@ cdb-check: [Reference count] : 11 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx weak_rc,d -//@ cdb-check:weak_rc,d : 111 [Type: alloc::rc::Weak] +//@ cdb-check:weak_rc,d : 111 [Type: alloc::rcs::rc::Weak] //@ cdb-check: [Reference count] : 11 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -47,17 +47,17 @@ //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx dyn_rc,d -//@ cdb-check:dyn_rc,d [Type: alloc::rc::Rc,alloc::alloc::Global>] +//@ cdb-check:dyn_rc,d [Type: alloc::rcs::rc::Rc,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 31 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx dyn_rc_weak,d -//@ cdb-check:dyn_rc_weak,d [Type: alloc::rc::Weak,alloc::alloc::Global>] +//@ cdb-check:dyn_rc_weak,d [Type: alloc::rcs::rc::Weak,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 31 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx slice_rc,d -//@ cdb-check:slice_rc,d : { len=3 } [Type: alloc::rc::Rc,alloc::alloc::Global>] +//@ cdb-check:slice_rc,d : { len=3 } [Type: alloc::rcs::rc::Rc,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 41 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] @@ -66,7 +66,7 @@ //@ cdb-check: [2] : 3 [Type: u32] //@ cdb-command:dx slice_rc_weak,d -//@ cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rc::Weak,alloc::alloc::Global>] +//@ cdb-check:slice_rc_weak,d : { len=3 } [Type: alloc::rcs::rc::Weak,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 41 [Type: core::cell::Cell] //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] diff --git a/tests/debuginfo/strings-and-strs.rs b/tests/debuginfo/strings-and-strs.rs index 81e3037f1e566..56e9f6a5b9773 100644 --- a/tests/debuginfo/strings-and-strs.rs +++ b/tests/debuginfo/strings-and-strs.rs @@ -20,13 +20,13 @@ //@ gdb-check:$4 = ("Hello", "World") //@ gdb-command:print str_in_rc -//@ gdb-check:$5 = alloc::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +//@ gdb-check:$5 = alloc::rcs::rc::Rc<&str, alloc::alloc::Global> {ptr: core::ptr::non_null::NonNull> {pointer: 0x[...]}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} //@ gdb-command:print box_str //@ gdb-check:$6 = alloc::boxed::Box [87, 111, 114, 108, 100] //@ gdb-command:print rc_str -//@ gdb-check:$7 = alloc::rc::Rc {ptr: core::ptr::non_null::NonNull> {pointer: alloc::rc::RcInner {strong: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, weak: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, value: 0x[...]}}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} +//@ gdb-check:$7 = alloc::rcs::rc::Rc {ptr: core::ptr::non_null::NonNull> {pointer: alloc::rcs::rc::RcInner {strong: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, weak: core::cell::Cell {value: core::cell::UnsafeCell {value: 1}}, value: 0x[...]}}, phantom: core::marker::PhantomData>, alloc: alloc::alloc::Global} // === LLDB TESTS ================================================================================== //@ lldb-command:run @@ -56,7 +56,7 @@ // lldb-command:v rc_str // ignore-tidy-linelength -// lldb-check:(alloc::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } +// lldb-check:(alloc::rcs::rc::Rc) rc_str = strong=1, weak=1 { value = "World" } #![allow(unused_variables)] diff --git a/tests/ui/methods/shadowed-intrinsic-method-deref.stderr b/tests/ui/methods/shadowed-intrinsic-method-deref.stderr index 4e0c5dfc55f09..d4dccd6dc5fdb 100644 --- a/tests/ui/methods/shadowed-intrinsic-method-deref.stderr +++ b/tests/ui/methods/shadowed-intrinsic-method-deref.stderr @@ -6,7 +6,7 @@ LL | let sb : &S = &s.borrow(); | help: the trait `Borrow` is not implemented for `Rc>` but trait `Borrow>` is implemented for it - --> $SRC_DIR/alloc/src/rc.rs:LL:COL + --> $SRC_DIR/alloc/src/rcs/rc.rs:LL:COL = help: for that trait implementation, expected `RefCell`, found `S` = note: there's an inherent method on `RefCell` of the same name, which can be auto-dereferenced from `&RefCell` help: to access the inherent method on `RefCell`, use the fully-qualified path From f74f6ea68cb07dc75af48fffc1efc41b80c411d1 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 28 Sep 2026 16:41:59 +0800 Subject: [PATCH 0944/1309] Rename `library/alloc/src/sync.rs` to `library/alloc/src/rcs/arc.rs` temporarily to keep file history --- library/alloc/src/{sync.rs => rcs/arc.rs} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename library/alloc/src/{sync.rs => rcs/arc.rs} (100%) diff --git a/library/alloc/src/sync.rs b/library/alloc/src/rcs/arc.rs similarity index 100% rename from library/alloc/src/sync.rs rename to library/alloc/src/rcs/arc.rs From cba32372c7b057d58d8d9f4d3fd17848d83d2b93 Mon Sep 17 00:00:00 2001 From: EFanZh Date: Mon, 28 Sep 2026 16:41:59 +0800 Subject: [PATCH 0945/1309] Re-export `alloc::rcs::arc::*` in `alloc::sync` --- library/alloc/src/lib.rs | 3 +++ library/alloc/src/rcs/arc.rs | 10 ---------- library/alloc/src/sync.rs | 14 ++++++++++++++ src/etc/natvis/liballoc.natvis | 8 ++++---- tests/codegen-llvm/debuginfo-cyclic-structure.rs | 2 +- tests/codegen-llvm/issues/issue-111603.rs | 8 ++++---- tests/debuginfo/rc_arc.rs | 12 ++++++------ tests/debuginfo/thread.rs | 2 +- 8 files changed, 33 insertions(+), 26 deletions(-) create mode 100644 library/alloc/src/sync.rs diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index 60ada2ba866bb..b1aa1a9a4f525 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -244,6 +244,9 @@ mod raw_vec; #[cfg(not(no_rc))] mod rcs { pub mod rc; + + #[cfg(all(not(no_sync), target_has_atomic = "ptr"))] + pub(crate) mod arc; } // Heaps provided for low-level allocation strategies diff --git a/library/alloc/src/rcs/arc.rs b/library/alloc/src/rcs/arc.rs index e412cee62d8f6..e61ea5193eccb 100644 --- a/library/alloc/src/rcs/arc.rs +++ b/library/alloc/src/rcs/arc.rs @@ -1,13 +1,3 @@ -#![stable(feature = "rust1", since = "1.0.0")] - -//! Thread-safe reference-counting pointers. -//! -//! See the [`Arc`][Arc] documentation for more details. -//! -//! **Note**: This module is only available on platforms that support atomic -//! loads and stores of pointers. This may be detected at compile time using -//! `#[cfg(target_has_atomic = "ptr")]`. - use core::any::Any; use core::cell::CloneFromCell; #[cfg(not(no_global_oom_handling))] diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs new file mode 100644 index 0000000000000..afb1848d21a24 --- /dev/null +++ b/library/alloc/src/sync.rs @@ -0,0 +1,14 @@ +#![stable(feature = "rust1", since = "1.0.0")] + +//! Thread-safe reference-counting pointers. +//! +//! See the [`Arc`][Arc] documentation for more details. +//! +//! **Note**: This module is only available on platforms that support atomic +//! loads and stores of pointers. This may be detected at compile time using +//! `#[cfg(target_has_atomic = "ptr")]`. + +#[unstable(feature = "unique_rc_arc", issue = "112566")] +pub use crate::rcs::arc::UniqueArc; +#[stable(feature = "rust1", since = "1.0.0")] +pub use crate::rcs::arc::{Arc, Weak}; diff --git a/src/etc/natvis/liballoc.natvis b/src/etc/natvis/liballoc.natvis index cfcca9014e70c..c8e143b49911b 100644 --- a/src/etc/natvis/liballoc.natvis +++ b/src/etc/natvis/liballoc.natvis @@ -131,7 +131,7 @@ - + {ptr.pointer->data} @@ -146,7 +146,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length @@ -160,7 +160,7 @@ - + {ptr.pointer->data} @@ -175,7 +175,7 @@ - + {{ len={ptr.pointer.length} }} ptr.pointer.length diff --git a/tests/codegen-llvm/debuginfo-cyclic-structure.rs b/tests/codegen-llvm/debuginfo-cyclic-structure.rs index b8cc544774158..dc7193dd08ed2 100644 --- a/tests/codegen-llvm/debuginfo-cyclic-structure.rs +++ b/tests/codegen-llvm/debuginfo-cyclic-structure.rs @@ -3,7 +3,7 @@ // Check that debug information exists for structures containing loops (cyclic references). // Previously it may incorrectly prune member information during recursive type inference check. -// CHECK: !DICompositeType(tag: DW_TAG_structure_type, name: "Arc Arc<[u64]> { // CHECK-LABEL: @new_uninit #[no_mangle] pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK: call alloc::rcs::arc::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::rcs::arc::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit(); unsafe { Arc::get_mut_unchecked(&mut arc) }.write([x; 1000]); unsafe { arc.assume_init() } @@ -30,8 +30,8 @@ pub fn new_uninit(x: u64) -> Arc<[u64; 1000]> { // CHECK-LABEL: @new_uninit_slice #[no_mangle] pub fn new_uninit_slice(x: u64) -> Arc<[u64]> { - // CHECK: call alloc::sync::arcinner_layout_for_value_layout - // CHECK-NOT: call alloc::sync::arcinner_layout_for_value_layout + // CHECK: call alloc::rcs::arc::arcinner_layout_for_value_layout + // CHECK-NOT: call alloc::rcs::arc::arcinner_layout_for_value_layout let mut arc = Arc::new_uninit_slice(1000); for elem in unsafe { Arc::get_mut_unchecked(&mut arc) } { elem.write(x); diff --git a/tests/debuginfo/rc_arc.rs b/tests/debuginfo/rc_arc.rs index 39b5dc0d84408..adeb96dba1b80 100644 --- a/tests/debuginfo/rc_arc.rs +++ b/tests/debuginfo/rc_arc.rs @@ -37,12 +37,12 @@ //@ cdb-check: [Weak reference count] : 2 [Type: core::cell::Cell] //@ cdb-command:dx arc,d -//@ cdb-check:arc,d : 222 [Type: alloc::sync::Arc] +//@ cdb-check:arc,d : 222 [Type: alloc::rcs::arc::Arc] //@ cdb-check: [Reference count] : 21 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx weak_arc,d -//@ cdb-check:weak_arc,d : 222 [Type: alloc::sync::Weak] +//@ cdb-check:weak_arc,d : 222 [Type: alloc::rcs::arc::Weak] //@ cdb-check: [Reference count] : 21 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] @@ -75,17 +75,17 @@ //@ cdb-check: [2] : 3 [Type: u32] //@ cdb-command:dx dyn_arc,d -//@ cdb-check:dyn_arc,d [Type: alloc::sync::Arc,alloc::alloc::Global>] +//@ cdb-check:dyn_arc,d [Type: alloc::rcs::arc::Arc,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 51 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx dyn_arc_weak,d -//@ cdb-check:dyn_arc_weak,d [Type: alloc::sync::Weak,alloc::alloc::Global>] +//@ cdb-check:dyn_arc_weak,d [Type: alloc::rcs::arc::Weak,alloc::alloc::Global>] //@ cdb-check: [Reference count] : 51 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] //@ cdb-command:dx slice_arc,d -//@ cdb-check:slice_arc,d : { len=3 } [Type: alloc::sync::Arc,alloc::alloc::Global>] +//@ cdb-check:slice_arc,d : { len=3 } [Type: alloc::rcs::arc::Arc,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 61 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] @@ -94,7 +94,7 @@ //@ cdb-check: [2] : 6 [Type: u32] //@ cdb-command:dx slice_arc_weak,d -//@ cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::sync::Weak,alloc::alloc::Global>] +//@ cdb-check:slice_arc_weak,d : { len=3 } [Type: alloc::rcs::arc::Weak,alloc::alloc::Global>] //@ cdb-check: [Length] : 3 [Type: [...]] //@ cdb-check: [Reference count] : 61 [Type: core::sync::atomic::Atomic] //@ cdb-check: [Weak reference count] : 2 [Type: core::sync::atomic::Atomic] diff --git a/tests/debuginfo/thread.rs b/tests/debuginfo/thread.rs index d78dad406ac6e..ee33f921cc033 100644 --- a/tests/debuginfo/thread.rs +++ b/tests/debuginfo/thread.rs @@ -14,7 +14,7 @@ // //@ cdb-command:dx t,d //@ cdb-check:t,d : [...] [Type: std::thread::thread::Thread *] -//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] +//@ cdb-check:[...] inner [...][Type: core::pin::Pin >] use std::thread; From 9c7ce013216f186768862b653128050f314efedc Mon Sep 17 00:00:00 2001 From: cyrgani Date: Mon, 28 Sep 2026 08:55:49 +0000 Subject: [PATCH 0946/1309] lint on `Ident::from_str_and_span` taking a string literal This function is a wrapper around `Symbol::intern`, which is already checked by the `rustc::symbol_intern_string_literal` lint. --- compiler/rustc_ast_lowering/src/contract.rs | 5 +-- compiler/rustc_builtin_macros/src/eii.rs | 2 +- .../src/global_allocator.rs | 4 +-- compiler/rustc_builtin_macros/src/test.rs | 12 ++----- .../rustc_builtin_macros/src/test_harness.rs | 2 +- compiler/rustc_lint/src/diagnostics.rs | 6 ++-- compiler/rustc_lint/src/internal.rs | 34 +++++++++++++------ compiler/rustc_span/src/symbol.rs | 7 ++++ 8 files changed, 43 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/contract.rs b/compiler/rustc_ast_lowering/src/contract.rs index 80bd0f7f4bb95..cbfeda33040e7 100644 --- a/compiler/rustc_ast_lowering/src/contract.rs +++ b/compiler/rustc_ast_lowering/src/contract.rs @@ -2,6 +2,7 @@ use std::sync::Arc; use rustc_attr_ir::lang_items::LangItem; use rustc_attr_ir::target::Target; +use rustc_span::sym; use thin_vec::thin_vec; use crate::LoweringContext; @@ -239,7 +240,7 @@ impl<'hir> LoweringContext<'_, 'hir> { postcond_span: rustc_span::Span, ) -> &'hir rustc_hir::Block<'hir> { let check_ident: rustc_span::Ident = - rustc_span::Ident::from_str_and_span("__ensures_checker", postcond_span); + rustc_span::Ident::new(sym::__ensures_checker, postcond_span); let (check_hir_id, postcond_decl) = { // Set up the postcondition `let` statement. let (checker_pat, check_hir_id) = self.pat_ident_binding_mode_mut( @@ -309,7 +310,7 @@ impl<'hir> LoweringContext<'_, 'hir> { // ret // } // } - let ret_ident: rustc_span::Ident = rustc_span::Ident::from_str_and_span("__ret", span); + let ret_ident: rustc_span::Ident = rustc_span::Ident::new(sym::__ret, span); // Set up the return `let` statement. let (ret_pat, ret_hir_id) = diff --git a/compiler/rustc_builtin_macros/src/eii.rs b/compiler/rustc_builtin_macros/src/eii.rs index 61b1c50180a6b..ed37599c9e85a 100644 --- a/compiler/rustc_builtin_macros/src/eii.rs +++ b/compiler/rustc_builtin_macros/src/eii.rs @@ -331,7 +331,7 @@ fn generate_default_impl( foreign_item_name.span, // prefix self to explicitly escape the const block generated below // NOTE: this is why EIIs can't be used on statements - vec![Ident::from_str_and_span("self", foreign_item_name.span), foreign_item_name], + vec![Ident::new(kw::SelfLower, foreign_item_name.span), foreign_item_name], )), }); diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs index d6293f8b015d0..fada1c477ac88 100644 --- a/compiler/rustc_builtin_macros/src/global_allocator.rs +++ b/compiler/rustc_builtin_macros/src/global_allocator.rs @@ -131,8 +131,8 @@ impl AllocFnFactory<'_, '_> { // disambiguated somehow. Currently the generated code would // fail to compile with "identifier is bound more than once in // this parameter list". - let size = Ident::from_str_and_span("size", self.span); - let align = Ident::from_str_and_span("align", self.span); + let size = Ident::new(sym::size, self.span); + let align = Ident::new(sym::align, self.span); let usize = self.cx.path_ident(self.span, Ident::new(sym::usize, self.span)); let ty_usize = self.cx.ty_path(usize); diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs index b444505027988..8e99d532029db 100644 --- a/compiler/rustc_builtin_macros/src/test.rs +++ b/compiler/rustc_builtin_macros/src/test.rs @@ -167,11 +167,7 @@ pub(crate) fn expand_test_or_bench( let should_panic_path = |name| { cx.path( sp, - vec![ - test_ident, - Ident::from_str_and_span("ShouldPanic", sp), - Ident::from_str_and_span(name, sp), - ], + vec![test_ident, Ident::new(sym::ShouldPanic, sp), Ident::from_str_and_span(name, sp)], ) }; @@ -179,11 +175,7 @@ pub(crate) fn expand_test_or_bench( let test_type_path = |name| { cx.path( sp, - vec![ - test_ident, - Ident::from_str_and_span("TestType", sp), - Ident::from_str_and_span(name, sp), - ], + vec![test_ident, Ident::new(sym::TestType, sp), Ident::from_str_and_span(name, sp)], ) }; diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs index bd2ea5a3e6696..d6167d30558a3 100644 --- a/compiler/rustc_builtin_macros/src/test_harness.rs +++ b/compiler/rustc_builtin_macros/src/test_harness.rs @@ -324,7 +324,7 @@ fn add_main(cx: &mut TestCtxt<'_>, c: &mut ast::Crate) { // pub fn main() -> ExitCode { ... } let main_ret_ty = if cx.test_runner.is_none() { // Built-in runner has return type `ExitCode`. - let exit_code_path = vec![test_ident, Ident::from_str_and_span("ExitCode", sp)]; + let exit_code_path = vec![test_ident, Ident::new(sym::ExitCode, sp)]; ecx.ty(sp, ast::TyKind::Path(None, ecx.path(sp, exit_code_path))) } else { // User-defined runners have return type `()`. diff --git a/compiler/rustc_lint/src/diagnostics.rs b/compiler/rustc_lint/src/diagnostics.rs index 464423b303f4f..ad6ef1053b8a7 100644 --- a/compiler/rustc_lint/src/diagnostics.rs +++ b/compiler/rustc_lint/src/diagnostics.rs @@ -1238,9 +1238,11 @@ pub(crate) struct QueryUntracked { pub(crate) struct SpanUseEqCtxtDiag; #[derive(Diagnostic)] -#[diag("using `Symbol::intern` on a string literal")] +#[diag("using `{$fn_name}` on a string literal")] #[help("consider adding the symbol to `compiler/rustc_span/src/symbol.rs`")] -pub(crate) struct SymbolInternStringLiteralDiag; +pub(crate) struct SymbolInternStringLiteralDiag { + pub fn_name: &'static str, +} #[derive(Diagnostic)] #[diag("usage of `ty::TyKind::`")] diff --git a/compiler/rustc_lint/src/internal.rs b/compiler/rustc_lint/src/internal.rs index b36326b86ac9a..b32fa2515238a 100644 --- a/compiler/rustc_lint/src/internal.rs +++ b/compiler/rustc_lint/src/internal.rs @@ -603,10 +603,10 @@ fn is_span_ctxt_call(cx: &LateContext<'_>, expr: &hir::Expr<'_>) -> bool { } declare_tool_lint! { - /// The `symbol_intern_string_literal` detects `Symbol::intern` being called on a string literal + /// The `symbol_intern_string_literal` lint detects `Symbol::intern` or `Ident::from_str_and_span` being called on a string literal pub rustc::SYMBOL_INTERN_STRING_LITERAL, Allow, - "Forbid uses of string literals in `Symbol::intern`, suggesting preinterning instead", + "Forbid uses of string literals in `Symbol::intern` or `Ident::from_str_and_span`, suggesting preinterning instead", report_in_external_macro: true } @@ -614,18 +614,30 @@ declare_lint_pass!(SymbolInternStringLiteral => [SYMBOL_INTERN_STRING_LITERAL]); impl<'tcx> LateLintPass<'tcx> for SymbolInternStringLiteral { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx rustc_hir::Expr<'tcx>) { - if let hir::ExprKind::Call(path, [arg]) = expr.kind + if let hir::ExprKind::Call(path, args) = expr.kind && let hir::ExprKind::Path(ref qpath) = path.kind && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id() - && cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) - && let hir::ExprKind::Lit(kind) = arg.kind - && let rustc_ast::LitKind::Str(_, _) = kind.node { - cx.emit_span_lint( - SYMBOL_INTERN_STRING_LITERAL, - kind.span, - SymbolInternStringLiteralDiag, - ); + let (arg, fn_name) = if cx.tcx.is_diagnostic_item(sym::SymbolIntern, def_id) + && let [arg] = args + { + (arg, "Symbol::intern") + } else if cx.tcx.is_diagnostic_item(sym::ident_from_str_and_span, def_id) + && let [arg, _] = args + { + (arg, "Ident::from_str_and_span") + } else { + return; + }; + if let hir::ExprKind::Lit(kind) = arg.kind + && let rustc_ast::LitKind::Str(_, _) = kind.node + { + cx.emit_span_lint( + SYMBOL_INTERN_STRING_LITERAL, + kind.span, + SymbolInternStringLiteralDiag { fn_name }, + ); + } } } } diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 93a83ddf213c1..a39fd0955c344 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -218,6 +218,7 @@ symbols! { Eq, Equal, Err, + ExitCode, Expected, ExternC, ExternRust, @@ -325,6 +326,7 @@ symbols! { SelfTy, Send, SeqCst, + ShouldPanic, Sized, Slice, SliceIndex, @@ -341,6 +343,7 @@ symbols! { Sync, SyncUnsafeCell, Target, + TestType, This, TokenStream, Transmute, @@ -367,6 +370,8 @@ symbols! { __H, __S, __awaitee, + __ensures_checker, + __ret, __try_var, _t, _task_context, @@ -1126,6 +1131,7 @@ symbols! { i128, i128_type, ident, + ident_from_str_and_span, if_let, if_let_guard, if_let_rescope, @@ -2505,6 +2511,7 @@ impl Ident { } /// Maps a string and a span to an identifier. + #[rustc_diagnostic_item = "ident_from_str_and_span"] pub fn from_str_and_span(string: &str, span: Span) -> Ident { Ident::new(Symbol::intern(string), span) } From 42f663b933c0e077669f8a586886be327d4f662b Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 28 Sep 2026 11:07:30 +0200 Subject: [PATCH 0947/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-28 (d080e7dff1b0fc54541545252818f8cccf995d05). --- compiler/rustc_codegen_cranelift/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index 84d28e7f293e0..9e21c2ed9a9b2 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-23" +channel = "nightly-2026-09-28" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From dce48c6b852d62db6819a2e830be41caed7ff16b Mon Sep 17 00:00:00 2001 From: Abhinav Srivastav Date: Mon, 28 Sep 2026 09:18:54 +0000 Subject: [PATCH 0948/1309] emit UnresolvedDelegationCallee for TypeRelativeDelegationRes::Error --- .../src/delegation/resolution.rs | 4 +- compiler/rustc_middle/src/middle/resolve.rs | 1 + tests/ui/delegation/bad-resolve.rs | 8 +++- tests/ui/delegation/bad-resolve.stderr | 42 +++++++++++++++++-- .../delegation-inherent-impl-issue-162774.rs | 18 ++++++++ ...legation-inherent-impl-issue-162774.stderr | 8 ++++ .../def-path-hash-collision-ice-153410.rs | 2 +- .../def-path-hash-collision-ice-153410.stderr | 8 +++- .../generics/synth-params-ice-143498.rs | 2 +- .../generics/synth-params-ice-143498.stderr | 8 +++- tests/ui/delegation/ice-issue-124342.rs | 2 +- tests/ui/delegation/ice-issue-124342.stderr | 8 +++- .../ice-line-bounds-issue-148732.rs | 2 +- .../ice-line-bounds-issue-148732.stderr | 8 +++- .../ice-non-fn-target-in-trait-impl.rs | 2 +- .../ice-non-fn-target-in-trait-impl.stderr | 8 +++- .../inherent-impls-non-local-crate.rs | 4 ++ .../inherent-impls-non-local-crate.stderr | 36 +++++++++++++--- .../ui/delegation/unused-import-ice-144594.rs | 2 +- .../unused-import-ice-144594.stderr | 8 +++- tests/ui/delegation/wrong-lifetime-rib.rs | 2 +- tests/ui/delegation/wrong-lifetime-rib.stderr | 8 +++- 22 files changed, 166 insertions(+), 25 deletions(-) create mode 100644 tests/ui/delegation/delegation-inherent-impl-issue-162774.rs create mode 100644 tests/ui/delegation/delegation-inherent-impl-issue-162774.stderr diff --git a/compiler/rustc_ast_lowering/src/delegation/resolution.rs b/compiler/rustc_ast_lowering/src/delegation/resolution.rs index 0e4992267b250..7678418c47e56 100644 --- a/compiler/rustc_ast_lowering/src/delegation/resolution.rs +++ b/compiler/rustc_ast_lowering/src/delegation/resolution.rs @@ -343,7 +343,9 @@ impl<'tcx> DelegationResolver<'_, 'tcx> { match tcx.resolve_type_relative_delegations(()).get(&def_id) { Some(res) => match *res { TypeRelativeDelegationRes::Ok(sig_id) => Ok(sig_id), - TypeRelativeDelegationRes::Error(err) => Err(err), + TypeRelativeDelegationRes::Error(_) => { + Err(tcx.dcx().emit_err(UnresolvedDelegationCallee { span })) + } TypeRelativeDelegationRes::Ambig(_) => { Err(tcx.dcx().emit_err(AmbiguousDelegationToInherentImpl { span })) } diff --git a/compiler/rustc_middle/src/middle/resolve.rs b/compiler/rustc_middle/src/middle/resolve.rs index 8267cde89ad27..fe8bc8a5f1537 100644 --- a/compiler/rustc_middle/src/middle/resolve.rs +++ b/compiler/rustc_middle/src/middle/resolve.rs @@ -291,6 +291,7 @@ pub struct DelegationInfo { } #[derive(Debug, StableHash)] +// FIXME(fn_delegation): replace with `Result`. pub enum TypeRelativeDelegationRes { Ok(DefId), Ambig(ErrorGuaranteed), diff --git a/tests/ui/delegation/bad-resolve.rs b/tests/ui/delegation/bad-resolve.rs index 0864776ab49fd..52da0f38017a0 100644 --- a/tests/ui/delegation/bad-resolve.rs +++ b/tests/ui/delegation/bad-resolve.rs @@ -43,7 +43,13 @@ impl Trait for S { mod prefix {} reuse unresolved_prefix::{a, b, c}; //~ ERROR cannot find module or crate `unresolved_prefix` +//~| ERROR failed to resolve delegation callee +//~| ERROR failed to resolve delegation callee +//~| ERROR failed to resolve delegation callee reuse prefix::{self, super, crate}; //~ ERROR `crate` in paths can only be used in start position -//~^ ERROR cannot find function `self` in module `prefix` +//~| ERROR failed to resolve delegation callee +//~| ERROR failed to resolve delegation callee +//~| ERROR cannot find function `self` in module `prefix` +//~| ERROR failed to resolve delegation callee fn main() {} diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 9740442e4b9f3..9756a009ec9b9 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -72,13 +72,49 @@ LL | reuse foo { &self.0 } | ^^^ not found in this scope error[E0423]: cannot find function `self` in module `prefix` - --> $DIR/bad-resolve.rs:46:16 + --> $DIR/bad-resolve.rs:49:16 | LL | reuse prefix::{self, super, crate}; | ^^^^ not found in `prefix` | = note: a module named `prefix::self` exists in another namespace +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:45:27 + | +LL | reuse unresolved_prefix::{a, b, c}; + | ^ + +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:45:30 + | +LL | reuse unresolved_prefix::{a, b, c}; + | ^ + +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:45:33 + | +LL | reuse unresolved_prefix::{a, b, c}; + | ^ + +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:49:16 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^ + +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:49:22 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ + +error: failed to resolve delegation callee + --> $DIR/bad-resolve.rs:49:29 + | +LL | reuse prefix::{self, super, crate}; + | ^^^^^ + error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl --> $DIR/bad-resolve.rs:34:11 | @@ -152,12 +188,12 @@ LL | reuse unresolved_prefix::{a, b, c}; = help: you might be missing a crate named `unresolved_prefix` error[E0433]: `crate` in paths can only be used in start position - --> $DIR/bad-resolve.rs:46:29 + --> $DIR/bad-resolve.rs:49:29 | LL | reuse prefix::{self, super, crate}; | ^^^^^ can only be used in path start position -error: aborting due to 14 previous errors; 1 warning emitted +error: aborting due to 20 previous errors; 1 warning emitted Some errors have detailed explanations: E0038, E0046, E0186, E0324, E0407, E0423, E0425, E0433, E0575... For more information about an error, try `rustc --explain E0038`. diff --git a/tests/ui/delegation/delegation-inherent-impl-issue-162774.rs b/tests/ui/delegation/delegation-inherent-impl-issue-162774.rs new file mode 100644 index 0000000000000..32432babd7b63 --- /dev/null +++ b/tests/ui/delegation/delegation-inherent-impl-issue-162774.rs @@ -0,0 +1,18 @@ +#![feature(fn_delegation)] + +trait Trait { + fn foo(&self) {} +} + +struct F; +impl Trait for F {} + +struct S(F); + +impl S { + reuse Trait::foo { self.0 } + reuse Self::foo::<> as bar { self } + //~^ ERROR failed to resolve delegation callee +} + +fn main() {} diff --git a/tests/ui/delegation/delegation-inherent-impl-issue-162774.stderr b/tests/ui/delegation/delegation-inherent-impl-issue-162774.stderr new file mode 100644 index 0000000000000..b2c0f53163470 --- /dev/null +++ b/tests/ui/delegation/delegation-inherent-impl-issue-162774.stderr @@ -0,0 +1,8 @@ +error: failed to resolve delegation callee + --> $DIR/delegation-inherent-impl-issue-162774.rs:14:17 + | +LL | reuse Self::foo::<> as bar { self } + | ^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.rs b/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.rs index a35386fa3720e..73c18e5690fd1 100644 --- a/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.rs +++ b/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.rs @@ -18,7 +18,7 @@ impl Iterator { //~^ ERROR: expected a type, found a trait [E0782] - reuse< < fn()>::Output>::Item as Iterator>::*; + reuse< < fn()>::Output>::Item as Iterator>::*; //~ ERROR failed to resolve delegation callee //~^ ERROR: cannot find method or associated constant `Item` in trait `Iterator` //~| ERROR: ambiguous associated type } diff --git a/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.stderr b/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.stderr index 99bb6ac7e66be..50eaca19144be 100644 --- a/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.stderr +++ b/tests/ui/delegation/generics/def-path-hash-collision-ice-153410.stderr @@ -6,6 +6,12 @@ LL | reuse< < fn()>::Output>::Item as Iterator>::*; | = note: an associated type named `Iterator::Item` exists in another namespace +error: failed to resolve delegation callee + --> $DIR/def-path-hash-collision-ice-153410.rs:21:58 + | +LL | reuse< < fn()>::Output>::Item as Iterator>::*; + | ^ + error[E0782]: expected a type, found a trait --> $DIR/def-path-hash-collision-ice-153410.rs:19:6 | @@ -36,7 +42,7 @@ LL - reuse< < fn()>::Output>::Item as Iterator>::*; LL + reuse< < ::Output>::Item as Iterator>::*; | -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0223, E0575, E0782. For more information about an error, try `rustc --explain E0223`. diff --git a/tests/ui/delegation/generics/synth-params-ice-143498.rs b/tests/ui/delegation/generics/synth-params-ice-143498.rs index 366451ccdc012..2216f05f6c31f 100644 --- a/tests/ui/delegation/generics/synth-params-ice-143498.rs +++ b/tests/ui/delegation/generics/synth-params-ice-143498.rs @@ -18,7 +18,7 @@ impl X { //~^ ERROR: cannot find type `X` in this scope - reuse< std::fmt::Debug as Iterator >::*; + reuse< std::fmt::Debug as Iterator >::*; //~ ERROR failed to resolve delegation callee //~^ ERROR: cannot find method or associated constant `Item` in trait `Iterator` //~| ERROR: expected a type, found a trait } diff --git a/tests/ui/delegation/generics/synth-params-ice-143498.stderr b/tests/ui/delegation/generics/synth-params-ice-143498.stderr index 8db4a84d76c53..21c5e29ad8707 100644 --- a/tests/ui/delegation/generics/synth-params-ice-143498.stderr +++ b/tests/ui/delegation/generics/synth-params-ice-143498.stderr @@ -12,6 +12,12 @@ LL | reuse< std::fmt::Debug as Iterator >::*; | = note: an associated type named `Iterator::Item` exists in another namespace +error: failed to resolve delegation callee + --> $DIR/synth-params-ice-143498.rs:21:43 + | +LL | reuse< std::fmt::Debug as Iterator >::*; + | ^ + error[E0782]: expected a type, found a trait --> $DIR/synth-params-ice-143498.rs:21:12 | @@ -23,7 +29,7 @@ help: you can add the `dyn` keyword if you want a trait object LL | reuse< dyn std::fmt::Debug as Iterator >::*; | +++ -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0425, E0575, E0782. For more information about an error, try `rustc --explain E0425`. diff --git a/tests/ui/delegation/ice-issue-124342.rs b/tests/ui/delegation/ice-issue-124342.rs index b5e7d9386d33d..a882b1bd90e6b 100644 --- a/tests/ui/delegation/ice-issue-124342.rs +++ b/tests/ui/delegation/ice-issue-124342.rs @@ -3,7 +3,7 @@ mod to_reuse {} trait Trait { - reuse to_reuse::foo { foo } + reuse to_reuse::foo { foo } //~ ERROR failed to resolve delegation callee //~^ ERROR cannot find function `foo` in module `to_reuse` //~| ERROR cannot find value `foo` in this scope } diff --git a/tests/ui/delegation/ice-issue-124342.stderr b/tests/ui/delegation/ice-issue-124342.stderr index 19d75e494cafe..df2b2ea91f0bd 100644 --- a/tests/ui/delegation/ice-issue-124342.stderr +++ b/tests/ui/delegation/ice-issue-124342.stderr @@ -15,6 +15,12 @@ help: you might have meant to refer to the associated function LL | reuse to_reuse::foo { Self::foo } | ++++++ -error: aborting due to 2 previous errors +error: failed to resolve delegation callee + --> $DIR/ice-issue-124342.rs:6:21 + | +LL | reuse to_reuse::foo { foo } + | ^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.rs b/tests/ui/delegation/ice-line-bounds-issue-148732.rs index 0123f0c8705b0..b8887f6ecbbf5 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.rs +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.rs @@ -1,4 +1,4 @@ -reuse a as b { +reuse a as b { //~ ERROR failed to resolve delegation callee //~^ ERROR cannot find function `a` in this scope //~| ERROR functions delegation is not yet fully implemented dbg!(b); diff --git a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr index eb93655beb60d..196f984626ce5 100644 --- a/tests/ui/delegation/ice-line-bounds-issue-148732.stderr +++ b/tests/ui/delegation/ice-line-bounds-issue-148732.stderr @@ -19,6 +19,12 @@ LL | | } = help: add `#![feature(fn_delegation)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date +error: failed to resolve delegation callee + --> $DIR/ice-line-bounds-issue-148732.rs:1:7 + | +LL | reuse a as b { + | ^ + error[E0277]: `fn() {b}` doesn't implement `Debug` --> $DIR/ice-line-bounds-issue-148732.rs:4:5 | @@ -30,7 +36,7 @@ LL | dbg!(b); | = help: use parentheses to call this function: `b()` -error: aborting due to 3 previous errors +error: aborting due to 4 previous errors Some errors have detailed explanations: E0277, E0425, E0658. For more information about an error, try `rustc --explain E0277`. diff --git a/tests/ui/delegation/ice-non-fn-target-in-trait-impl.rs b/tests/ui/delegation/ice-non-fn-target-in-trait-impl.rs index 7a61da79f3c8f..2dac22779c3da 100644 --- a/tests/ui/delegation/ice-non-fn-target-in-trait-impl.rs +++ b/tests/ui/delegation/ice-non-fn-target-in-trait-impl.rs @@ -10,7 +10,7 @@ trait Trait { } impl Trait for () { - reuse std::path::<> as bar; + reuse std::path::<> as bar; //~ ERROR failed to resolve delegation callee //~^ ERROR cannot find function `path` in crate `std` reuse core::<> as bar2; //~^ ERROR cannot find function `core` in this scope diff --git a/tests/ui/delegation/ice-non-fn-target-in-trait-impl.stderr b/tests/ui/delegation/ice-non-fn-target-in-trait-impl.stderr index e9eca6b35bb51..f543f823da157 100644 --- a/tests/ui/delegation/ice-non-fn-target-in-trait-impl.stderr +++ b/tests/ui/delegation/ice-non-fn-target-in-trait-impl.stderr @@ -14,6 +14,12 @@ LL | reuse core::<> as bar2; | = note: a crate named `core` exists in another namespace -error: aborting due to 2 previous errors +error: failed to resolve delegation callee + --> $DIR/ice-non-fn-target-in-trait-impl.rs:13:16 + | +LL | reuse std::path::<> as bar; + | ^^^^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0423`. diff --git a/tests/ui/delegation/inherent-impls-non-local-crate.rs b/tests/ui/delegation/inherent-impls-non-local-crate.rs index 27b8d387a7e63..865bdb877a8a1 100644 --- a/tests/ui/delegation/inherent-impls-non-local-crate.rs +++ b/tests/ui/delegation/inherent-impls-non-local-crate.rs @@ -6,13 +6,17 @@ reuse inherent_impl::S::foo; reuse inherent_impl::S::not_existing; //~^ ERROR: no associated function or constant named `not_existing` found for struct `S` in the current scope +//~| ERROR failed to resolve delegation callee reuse inherent_impl::S::TYPE; //~^ ERROR: no associated function or constant named `TYPE` found for struct `S` in the current scope +//~| ERROR failed to resolve delegation callee reuse inherent_impl::S::CONST; //~^ ERROR: expected function, found `usize` [E0618] +//~| ERROR failed to resolve delegation callee reuse inherent_impl::S::bar; //~^ ERROR: no associated function or constant named `bar` found for struct `S` in the current scope +//~| ERROR failed to resolve delegation callee reuse ::bar as trait_bar; diff --git a/tests/ui/delegation/inherent-impls-non-local-crate.stderr b/tests/ui/delegation/inherent-impls-non-local-crate.stderr index 31358b1d7144e..288f72427c376 100644 --- a/tests/ui/delegation/inherent-impls-non-local-crate.stderr +++ b/tests/ui/delegation/inherent-impls-non-local-crate.stderr @@ -1,5 +1,29 @@ +error: failed to resolve delegation callee + --> $DIR/inherent-impls-non-local-crate.rs:7:25 + | +LL | reuse inherent_impl::S::not_existing; + | ^^^^^^^^^^^^ + +error: failed to resolve delegation callee + --> $DIR/inherent-impls-non-local-crate.rs:10:25 + | +LL | reuse inherent_impl::S::TYPE; + | ^^^^ + +error: failed to resolve delegation callee + --> $DIR/inherent-impls-non-local-crate.rs:13:25 + | +LL | reuse inherent_impl::S::CONST; + | ^^^^^ + +error: failed to resolve delegation callee + --> $DIR/inherent-impls-non-local-crate.rs:17:25 + | +LL | reuse inherent_impl::S::bar; + | ^^^ + error: ambiguous delegation to inherent impl function - --> $DIR/inherent-impls-non-local-crate.rs:19:25 + --> $DIR/inherent-impls-non-local-crate.rs:23:25 | LL | reuse inherent_impl::X::foo as x_foo; | ^^^ @@ -11,19 +35,19 @@ LL | reuse inherent_impl::S::not_existing; | ^^^^^^^^^^^^ associated function or constant not found in `S` error[E0599]: no associated function or constant named `TYPE` found for struct `S` in the current scope - --> $DIR/inherent-impls-non-local-crate.rs:9:25 + --> $DIR/inherent-impls-non-local-crate.rs:10:25 | LL | reuse inherent_impl::S::TYPE; | ^^^^ associated function or constant not found in `S` error[E0618]: expected function, found `usize` - --> $DIR/inherent-impls-non-local-crate.rs:11:25 + --> $DIR/inherent-impls-non-local-crate.rs:13:25 | LL | reuse inherent_impl::S::CONST; | ^^^^^ call expression requires function error[E0599]: no associated function or constant named `bar` found for struct `S` in the current scope - --> $DIR/inherent-impls-non-local-crate.rs:14:25 + --> $DIR/inherent-impls-non-local-crate.rs:17:25 | LL | reuse inherent_impl::S::bar; | ^^^ associated function or constant not found in `S` @@ -35,7 +59,7 @@ LL + use inherent_impl::Trait; | error[E0034]: multiple applicable items in scope - --> $DIR/inherent-impls-non-local-crate.rs:19:25 + --> $DIR/inherent-impls-non-local-crate.rs:23:25 | LL | reuse inherent_impl::X::foo as x_foo; | ^^^ multiple `foo` found @@ -43,7 +67,7 @@ LL | reuse inherent_impl::X::foo as x_foo; = note: candidate #1 is defined in an impl for the type `X` = note: candidate #2 is defined in an impl for the type `X` -error: aborting due to 6 previous errors +error: aborting due to 10 previous errors Some errors have detailed explanations: E0034, E0599, E0618. For more information about an error, try `rustc --explain E0034`. diff --git a/tests/ui/delegation/unused-import-ice-144594.rs b/tests/ui/delegation/unused-import-ice-144594.rs index fca67c6ee0b81..f245b409c4999 100644 --- a/tests/ui/delegation/unused-import-ice-144594.rs +++ b/tests/ui/delegation/unused-import-ice-144594.rs @@ -1,6 +1,6 @@ #![feature(fn_delegation)] -reuse a as b { +reuse a as b { //~ ERROR failed to resolve delegation callee //~^ ERROR cannot find function `a` in this scope [E0425] || { use std::ops::Add; diff --git a/tests/ui/delegation/unused-import-ice-144594.stderr b/tests/ui/delegation/unused-import-ice-144594.stderr index f09313aac21f4..27440c0ff83ec 100644 --- a/tests/ui/delegation/unused-import-ice-144594.stderr +++ b/tests/ui/delegation/unused-import-ice-144594.stderr @@ -10,6 +10,12 @@ error[E0425]: cannot find value `x` in this scope LL | x.add | ^ not found in this scope -error: aborting due to 2 previous errors +error: failed to resolve delegation callee + --> $DIR/unused-import-ice-144594.rs:3:7 + | +LL | reuse a as b { + | ^ + +error: aborting due to 3 previous errors For more information about this error, try `rustc --explain E0425`. diff --git a/tests/ui/delegation/wrong-lifetime-rib.rs b/tests/ui/delegation/wrong-lifetime-rib.rs index e9214b7c42260..ca14583eaa525 100644 --- a/tests/ui/delegation/wrong-lifetime-rib.rs +++ b/tests/ui/delegation/wrong-lifetime-rib.rs @@ -8,7 +8,7 @@ mod ice_156342 { impl Trait { //~^ ERROR: cannot define inherent `impl` for a type outside of the crate where the type is defined - reuse None::<&()>; + reuse None::<&()>; //~ ERROR failed to resolve delegation callee //~^ ERROR: expected function, found unit variant `None` } diff --git a/tests/ui/delegation/wrong-lifetime-rib.stderr b/tests/ui/delegation/wrong-lifetime-rib.stderr index ca759995fec42..447328f579df2 100644 --- a/tests/ui/delegation/wrong-lifetime-rib.stderr +++ b/tests/ui/delegation/wrong-lifetime-rib.stderr @@ -4,6 +4,12 @@ error[E0423]: expected function, found unit variant `None` LL | reuse None::<&()>; | ^^^^^^^^^^^ not a function +error: failed to resolve delegation callee + --> $DIR/wrong-lifetime-rib.rs:11:15 + | +LL | reuse None::<&()>; + | ^^^^ + error: inferred lifetimes are not allowed in delegations as we need to inherit signature --> $DIR/wrong-lifetime-rib.rs:17:18 | @@ -144,7 +150,7 @@ help: you can add the `dyn` keyword if you want a trait object LL | let _: &dyn X; | +++ -error: aborting due to 19 previous errors +error: aborting due to 20 previous errors Some errors have detailed explanations: E0116, E0223, E0423, E0782. For more information about an error, try `rustc --explain E0116`. From f9d83558b951201bbf1f7da20dd3a8b3f919890c Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Mon, 28 Sep 2026 11:21:50 +0200 Subject: [PATCH 0949/1309] Simplify rustup.sh a bit --- compiler/rustc_codegen_cranelift/scripts/rustup.sh | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_codegen_cranelift/scripts/rustup.sh b/compiler/rustc_codegen_cranelift/scripts/rustup.sh index 991524a1be912..80e9c4f78c4a6 100755 --- a/compiler/rustc_codegen_cranelift/scripts/rustup.sh +++ b/compiler/rustc_codegen_cranelift/scripts/rustup.sh @@ -2,22 +2,19 @@ set -e -TOOLCHAIN=${TOOLCHAIN:-$(date +%Y-%m-%d)} - export GIT_CONFIG_GLOBAL=../rust/josh.gitconfig export RUSTC_GIT=../rust case $1 in "prepare") - echo "=> Installing new nightly" - rustup toolchain install --profile minimal "nightly-${TOOLCHAIN}" # Sanity check to see if the nightly exists - sed -i "s/\"nightly-.*\"/\"nightly-${TOOLCHAIN}\"/" rust-toolchain.toml - echo "=> Uninstalling all old nightlies" - for nightly in $(rustup toolchain list | grep nightly | grep -v "$TOOLCHAIN" | grep -v nightly-x86_64); do + for nightly in $(RUSTUP_AUTO_INSTALL=0 rustup toolchain list | grep nightly | grep -v nightly-x86_64); do rustup toolchain uninstall "$nightly" done + echo "=> Installing new nightly" + rustup toolchain install + ./clean_all.sh ./y.sh prepare From 5e0bd1ac99ff370970a30fb2640cac7fc62eccdc Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 28 Sep 2026 12:26:05 +0300 Subject: [PATCH 0950/1309] Address review comments --- compiler/rustc_hir_id/src/definitions.rs | 38 +++++++++---------- .../src/rmeta/def_path_hash_map.rs | 8 +++- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index d177630e7a8fc..734f149f3bc77 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -47,27 +47,27 @@ impl LocalDefIdMap { } } -/// Struct that contains two maps: `det_part` is used at the earlier stages of compilation -/// (see where `commit_end_of_determinism` is called, at the moment of writing -/// it is after prefetch of `hir_crate_items` in `run_required_analysis`), `non_det_part` is used -/// when def ids are allocated non-deterministically (in parallel compiler), -/// i.e., order of serialized pairs may be different. -/// In order to preserve deterministic output of the compiler we need to deterministically encode this map, so we use -/// `SortedMap` to store the mapping between local hashes and def indices, which gives us -/// deterministic iteration when encoding crate metadata. For encoding/decoding details see -/// `compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs`. #[derive(Debug, Default)] pub struct DefPathToIndexMap { - pub det_part: DefPathHashMap, - pub non_det_part: Option>, + /// Stores mapping from local hash to def indices which are allocated when the order + /// of their allocation is deterministic (see where `commit_end_of_determinism` is called, + /// at the moment of writing it is after prefetch of `hir_crate_items` in `run_required_analysis`). + pub before_parallel_alloc: DefPathHashMap, + + /// Stores the same mapping as previous map but is used after the allocation order of def indices + /// is not deterministic, so when serializing metadata we have a ready to use sorted by stable local + /// hash (which does not change between compiler invocations) mapping. We use it for relatively small number + /// of definitions, so the majority of them would be stored in `DefPathHashMap`, which makes insertion + /// and serialization costs of `SortedMap` acceptable. + pub after_parallel_alloc: Option>, } impl DefPathToIndexMap { #[inline] pub fn get(&self, hash: Hash64) -> Option { - self.det_part + self.before_parallel_alloc .get(&hash) - .or_else(|| self.non_det_part.as_ref().and_then(|map| map.get(&hash).copied())) + .or_else(|| self.after_parallel_alloc.as_ref().and_then(|map| map.get(&hash).copied())) } /// This insert function does not behave like regular `insert` of a `HashMap`, @@ -76,10 +76,10 @@ impl DefPathToIndexMap { /// def index into `det_part` when we are in non-deterministic mode. #[inline] pub fn insert(&mut self, hash: Hash64, index: DefIndex) -> Option { - match self.non_det_part.as_mut() { - None => self.det_part.insert(&hash, &index), + match self.after_parallel_alloc.as_mut() { + None => self.before_parallel_alloc.insert(&hash, &index), Some(map) => { - if let Some(existing) = self.det_part.get(&hash) { + if let Some(existing) = self.before_parallel_alloc.get(&hash) { return Some(existing); } @@ -292,10 +292,10 @@ pub enum DefPathData { } impl Definitions { - /// This function indicates that def ids allocations are non-deterministic after - /// it was called. + /// This function indicates that the order of def id allocations + /// may be non-deterministic after it was called. pub fn commit_end_of_determinism(&mut self) { - self.def_path_hash_to_index.non_det_part = Some(Default::default()); + self.def_path_hash_to_index.after_parallel_alloc = Some(Default::default()); } #[inline(always)] diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 7f625d59fa784..61ec7ad4cf7b3 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -36,11 +36,15 @@ impl<'a, 'tcx> Encodable> for DefPathHashMapRef<'tcx> { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) { match *self { DefPathHashMapRef::BorrowedFromTcx(map) => { - let bytes = map.det_part.raw_bytes(); + let bytes = map.before_parallel_alloc.raw_bytes(); e.emit_usize(bytes.len()); e.emit_raw_bytes(bytes); - map.non_det_part.as_ref().unwrap_or(&Default::default()).range(..).encode(e); + map.after_parallel_alloc + .as_ref() + .expect("must be set before metadata encoding") + .range(..) + .encode(e); } DefPathHashMapRef::OwnedFromMetadata(..) => { panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") From 2f77d206ab26535798a3157d0d72646bd6f3655b Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 28 Sep 2026 13:02:51 +0300 Subject: [PATCH 0951/1309] Assert that `commit_end_of_determinism` is called only once --- compiler/rustc_hir_id/src/definitions.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 734f149f3bc77..426a4e0109153 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -295,7 +295,10 @@ impl Definitions { /// This function indicates that the order of def id allocations /// may be non-deterministic after it was called. pub fn commit_end_of_determinism(&mut self) { - self.def_path_hash_to_index.after_parallel_alloc = Some(Default::default()); + assert!( + self.def_path_hash_to_index.after_parallel_alloc.replace(Default::default()).is_none(), + "this function should be called only once" + ) } #[inline(always)] From 18b66242ebb000cd67623dbf17db5a1b5ab451f2 Mon Sep 17 00:00:00 2001 From: Daniel Scherzer Date: Sat, 12 Sep 2026 11:35:27 -0700 Subject: [PATCH 0952/1309] unnecessary_self_imports: tweak link to rustfmt issue Show the repository and issue number rather than linking text --- clippy_lints/src/unnecessary_self_imports.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clippy_lints/src/unnecessary_self_imports.rs b/clippy_lints/src/unnecessary_self_imports.rs index ea01f2828e020..9258c74ebf1e5 100644 --- a/clippy_lints/src/unnecessary_self_imports.rs +++ b/clippy_lints/src/unnecessary_self_imports.rs @@ -13,7 +13,7 @@ declare_clippy_lint! { /// /// ### Known problems /// Removing `::{self}` will cause any non-module items at the same path to also be imported. - /// This might cause a [naming conflict](https://github.com/rust-lang/rustfmt/issues/3568). This lint makes no attempt + /// This might cause a naming conflict ([rust-lang/rustfmt#3568](https://github.com/rust-lang/rustfmt/issues/3568)). This lint makes no attempt /// to detect this scenario and that is why it is a restriction lint. /// /// ### Example From e67d79891ce10bde66cd7d84461dcb209dd24d71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 28 Sep 2026 12:55:30 +0200 Subject: [PATCH 0953/1309] Support also `try-jobs:` to specify custom try jobs --- src/ci/citool/src/main.rs | 10 +++++++--- src/ci/citool/tests/jobs.rs | 3 ++- 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs index ff55b4df8f3d1..1bb0c2a34b8d1 100644 --- a/src/ci/citool/src/main.rs +++ b/src/ci/citool/src/main.rs @@ -72,10 +72,12 @@ impl GitHubContext { /// The first is a set of patterns of CI jobs that should be executed. /// /// They can be specified in the form of - /// try-job: + /// ``` + /// try-job[s]: /// or - /// try-job: `` + /// try-job[s]: `` /// (to avoid GitHub rendering the glob patterns as Markdown) + /// ``` /// /// # No limit /// The second is a marker that specifies that the limit on the maximum number of allowed try @@ -96,7 +98,9 @@ impl GitHubContext { nolimit = true; continue; } - let Some(pattern) = line.strip_prefix("try-job: ") else { + let Some(pattern) = + line.strip_prefix("try-job: ").or_else(|| line.strip_prefix("try-jobs: ")) + else { continue; }; // Strip backticks if present diff --git a/src/ci/citool/tests/jobs.rs b/src/ci/citool/tests/jobs.rs index e45510d62d9af..1b19d97534982 100644 --- a/src/ci/citool/tests/jobs.rs +++ b/src/ci/citool/tests/jobs.rs @@ -27,11 +27,12 @@ fn try_custom_jobs() { r#"This is a test PR try-job: test-aarch64-gnu +try-jobs: test-aarch64-apple try-job: dist-i686-msvc"#, "refs/heads/automation/bors/try", ); insta::assert_snapshot!(stdout, @r#" - jobs=[{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"test-aarch64-gnu","full_name":"try - test-aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true}] + jobs=[{"name":"dist-i686-msvc","full_name":"try - dist-i686-msvc","os":"windows-2022","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","CODEGEN_BACKENDS":"llvm,cranelift","DEPLOY_BUCKET":"rust-lang-ci2","DIST_REQUIRE_ALL_TOOLS":1,"RUST_CONFIGURE_ARGS":"--build=i686-pc-windows-msvc --host=i686-pc-windows-msvc --target=i686-pc-windows-msvc,i586-pc-windows-msvc --enable-full-tools --enable-profiler","SCRIPT":"python x.py dist bootstrap --include-default-paths","TOOLSTATE_PUBLISH":1}},{"name":"test-aarch64-apple","full_name":"try - test-aarch64-apple","os":"macos-15","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","DEVELOPER_DIR":"/Applications/Xcode_26.2.app/Contents/Developer","MACOSX_DEPLOYMENT_TARGET":11.0,"MACOSX_STD_DEPLOYMENT_TARGET":11.0,"NO_DEBUG_ASSERTIONS":1,"NO_LLVM_ASSERTIONS":1,"NO_OVERFLOW_CHECKS":1,"RUSTC_RETRY_LINKER_ON_SEGFAULT":1,"RUST_CONFIGURE_ARGS":"--enable-sanitizers --enable-profiler --set build.allocator=jemalloc","SCRIPT":"./x.py --stage 2 test --host=aarch64-apple-darwin --target=aarch64-apple-darwin","TOOLSTATE_PUBLISH":1}},{"name":"test-aarch64-gnu","full_name":"try - test-aarch64-gnu","os":"ubuntu-22.04-arm","env":{"ARTIFACTS_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZN24CBO55","AWS_REGION":"us-west-1","CACHES_AWS_ACCESS_KEY_ID":"AKIA46X5W6CZI5DHEBFL","DEPLOY_BUCKET":"rust-lang-ci2","TOOLSTATE_PUBLISH":1},"free_disk":true}] run_type=try "#); } From b9e7e711bc293c5757150cf6d32fd1d8015fd391 Mon Sep 17 00:00:00 2001 From: eleocraft Date: Mon, 28 Sep 2026 14:02:16 +0200 Subject: [PATCH 0954/1309] nonzero doc: replacing tabs with spaces --- library/core/src/num/nonzero.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs index d7b451c53f059..cdfda32bad43a 100644 --- a/library/core/src/num/nonzero.rs +++ b/library/core/src/num/nonzero.rs @@ -2470,23 +2470,23 @@ macro_rules! nonzero_integer_signedness_dependent_methods { #[doc = concat!("let limit = NonZero::<", stringify!($Uint), ">::new(100).unwrap();")] /// /// assert_eq!( - #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(120).unwrap().clamp_magnitude(limit),")] - #[doc = "\tNonZero::new(100).unwrap(),"] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(120).unwrap().clamp_magnitude(limit),")] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(100).unwrap(),")] /// ); /// /// assert_eq!( - #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(-120).unwrap().clamp_magnitude(limit),")] - #[doc = "\tNonZero::new(-100).unwrap(),"] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(-120).unwrap().clamp_magnitude(limit),")] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(-100).unwrap(),")] /// ); /// /// assert_eq!( - #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(80).unwrap().clamp_magnitude(limit),")] - #[doc = "\tNonZero::new(80).unwrap(),"] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(80).unwrap().clamp_magnitude(limit),")] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(80).unwrap(),")] /// ); /// /// assert_eq!( - #[doc = concat!("\tNonZero::<", stringify!($Int), ">::new(-80).unwrap().clamp_magnitude(limit),")] - #[doc = "\tNonZero::new(-80).unwrap(),"] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(-80).unwrap().clamp_magnitude(limit),")] + #[doc = concat!(" NonZero::<", stringify!($Int), ">::new(-80).unwrap(),")] /// ); /// ``` #[inline] From cea122121f484bb25cb2423c11bdc08924c5147f Mon Sep 17 00:00:00 2001 From: Kokoro2336 <2529677678@qq.com> Date: Fri, 1 May 2026 23:14:42 +0800 Subject: [PATCH 0955/1309] fix: add guard checking. test: supply guard test. chore: update doc. --- clippy_lints/src/matches/collapsible_match.rs | 36 ++++++++++++++++--- tests/ui/collapsible_match.rs | 16 +++++++++ 2 files changed, 47 insertions(+), 5 deletions(-) diff --git a/clippy_lints/src/matches/collapsible_match.rs b/clippy_lints/src/matches/collapsible_match.rs index d210d61648319..d9fce008b5b62 100644 --- a/clippy_lints/src/matches/collapsible_match.rs +++ b/clippy_lints/src/matches/collapsible_match.rs @@ -4,11 +4,12 @@ use clippy_utils::msrvs::Msrv; use clippy_utils::res::MaybeResPath as _; use clippy_utils::source::{IntoSpan as _, SpanExt as _, snippet}; use clippy_utils::usage::mutated_variables; -use clippy_utils::visitors::is_local_used; +use clippy_utils::visitors::{for_each_expr_without_closures, is_local_used}; use clippy_utils::{ SpanlessEq, get_ref_operators, is_none_pattern, is_unit_expr, peel_blocks_with_stmt, peel_ref_operators, span_contains_non_whitespace, }; +use core::ops::ControlFlow; use rustc_ast::BorrowKind; use rustc_errors::{Applicability, MultiSpan}; use rustc_hir::{Arm, Expr, ExprKind, HirId, HirIdSet, Pat, PatKind}; @@ -166,7 +167,7 @@ fn check_arm<'tcx>( (None, Some(e)) | (Some(e), None) => is_unit_expr(e), (Some(a), Some(b)) => SpanlessEq::new(cx).eq_expr(ctxt, a, b), } - && !pat_bindings_moved_or_mutated(cx, outer_pat, inner.cond) + && !pat_bindings_and_inner_cond_moved_or_mutated(cx, outer_pat, inner.cond) { let outer_then_open_bracket = outer_then_body .span @@ -290,9 +291,19 @@ fn build_ref_method_chain(expr: Vec<&Expr<'_>>) -> Option { Some(req_method_calls) } -/// Checks if any of the bindings in the `pat` are moved or mutated in the `expr`. It is invalid to -/// move or mutate bindings in `if` guards. -fn pat_bindings_moved_or_mutated<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, expr: &'tcx Expr<'tcx>) -> bool { +fn is_defined_in(cx: &LateContext<'_>, binding_id: HirId, container_id: HirId) -> bool { + cx.tcx + .hir_parent_id_iter(binding_id) + .any(|parent_id| parent_id == container_id) +} + +/// Checks if any of the bindings in the `pat` and variable in the inner condition are moved or +/// mutated in the `expr`. It is invalid to move or mutate bindings in `if` condition. +fn pat_bindings_and_inner_cond_moved_or_mutated<'tcx>( + cx: &LateContext<'tcx>, + pat: &Pat<'tcx>, + expr: &'tcx Expr<'tcx>, +) -> bool { let mut delegate = MovedVarDelegate { moved: HirIdSet::default(), }; @@ -308,6 +319,7 @@ fn pat_bindings_moved_or_mutated<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, candidates.extend(mutated); } + // Check the pat !pat.walk_short(|pat| { if let PatKind::Binding(_, hir_id, ..) = pat.kind && candidates.contains(&hir_id) @@ -316,6 +328,20 @@ fn pat_bindings_moved_or_mutated<'tcx>(cx: &LateContext<'tcx>, pat: &Pat<'tcx>, } true }) + // Check the inner condition + || for_each_expr_without_closures(expr, |e| { + if let Some(local_id) = e.res_local_id() + // defined outside of the `if` condition + && !is_defined_in(cx, local_id, expr.hir_id) + // moved/mutated + && candidates.contains(&local_id) + { + ControlFlow::Break(()) + } else { + ControlFlow::Continue(()) + } + }) + .is_some() } struct MovedVarDelegate { diff --git a/tests/ui/collapsible_match.rs b/tests/ui/collapsible_match.rs index 0d542e8f329a0..bc7d7876b47db 100644 --- a/tests/ui/collapsible_match.rs +++ b/tests/ui/collapsible_match.rs @@ -489,3 +489,19 @@ fn issue16916() { _ => {}, } } + +// Don't lint and suggest if condition moves a variable used in other arms +fn issue_multi_arm_move() { + let x: Vec = vec![1]; + let tag = 1u8; + match tag { + 1 => if consume(x) {}, + 2 => { + if consume(x) {} // x already moved if first arm fires. We can't collapse it + }, + _ => {}, + } +} +fn consume(_: Vec) -> bool { + true +} From 199f90342c5682cc1edbdcf7579fb1a3d43a1f7d Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Mon, 28 Sep 2026 11:03:13 +0100 Subject: [PATCH 0956/1309] Allow `#[repr(simd)]` with `f16b` --- compiler/rustc_hir_analysis/src/check/check.rs | 2 ++ tests/ui/parser/f16b-repr-simd.rs | 12 ++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 tests/ui/parser/f16b-repr-simd.rs diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index ee151399bd849..1e75902884fe1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -1543,6 +1543,8 @@ fn check_simd(tcx: TyCtxt<'_>, sp: Span, def_id: LocalDefId) { match element_ty.kind() { ty::Param(_) => (), // pass struct([T; 4]) through, let monomorphization catch errors ty::Int(_) | ty::Uint(_) | ty::Float(_) | ty::RawPtr(_, _) => (), // struct([u8; 4]) is ok + // So we can create structs like; `struct bfloat16x4_t (f16b x 4);` + ty::Adt(def, _) if tcx.is_lang_item(def.did(), LangItem::F16B) => (), _ => { struct_span_code_err!( tcx.dcx(), diff --git a/tests/ui/parser/f16b-repr-simd.rs b/tests/ui/parser/f16b-repr-simd.rs new file mode 100644 index 0000000000000..36a8c79cba1a8 --- /dev/null +++ b/tests/ui/parser/f16b-repr-simd.rs @@ -0,0 +1,12 @@ +//@ build-pass +//@ compile-flags: --crate-type=lib +#![feature(f16b, repr_simd)] + +extern crate core; + +#[allow(non_camel_case_types)] +type bfloat16_t = core::num::f16b; + +#[repr(simd)] +#[allow(non_camel_case_types)] +pub struct bfloat16x4([bfloat16_t; 4]); From d3d2163b2004565b8d692dc66175f76e6d9fe614 Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Sat, 19 Sep 2026 18:21:59 +0200 Subject: [PATCH 0957/1309] dont store arbitrary parsed attributes in thir --- compiler/rustc_codegen_llvm/src/builder.rs | 6 +-- compiler/rustc_codegen_ssa/src/mir/block.rs | 6 +-- .../rustc_codegen_ssa/src/traits/builder.rs | 2 +- compiler/rustc_middle/src/mir/terminator.rs | 2 +- compiler/rustc_middle/src/mir/visit.rs | 2 +- compiler/rustc_middle/src/thir.rs | 4 +- compiler/rustc_mir_build/src/builder/cfg.rs | 2 +- .../src/builder/custom/parse.rs | 2 +- .../rustc_mir_build/src/builder/expr/into.rs | 4 +- compiler/rustc_mir_build/src/thir/cx/expr.rs | 18 +++++---- .../rustc_mir_dataflow/src/framework/tests.rs | 2 +- .../src/add_call_guards.rs | 2 +- .../src/add_moves_for_packed_drops.rs | 2 +- .../rustc_mir_transform/src/check_enums.rs | 10 ++--- .../rustc_mir_transform/src/check_pointers.rs | 2 +- .../rustc_mir_transform/src/coroutine/drop.rs | 2 +- .../rustc_mir_transform/src/coroutine/mod.rs | 18 +++++---- .../rustc_mir_transform/src/coverage/tests.rs | 2 +- .../src/early_otherwise_branch.rs | 4 +- .../rustc_mir_transform/src/elaborate_drop.rs | 12 +++++- compiler/rustc_mir_transform/src/inline.rs | 4 +- compiler/rustc_mir_transform/src/patch.rs | 8 ++-- .../rustc_mir_transform/src/promote_consts.rs | 4 +- compiler/rustc_mir_transform/src/shim.rs | 38 ++++++++++++++----- .../src/shim/async_destructor_ctor.rs | 12 ++++-- tests/incremental/cache-lint-expectation.rs | 5 ++- tests/ui/thir-print/str-patterns.stdout | 4 +- .../thir-print/thir-flat-const-variant.stdout | 10 ++--- tests/ui/thir-print/thir-flat.stdout | 2 +- 29 files changed, 116 insertions(+), 75 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs index 477cc25ee6f26..f9b5d5ef03b76 100644 --- a/compiler/rustc_codegen_llvm/src/builder.rs +++ b/compiler/rustc_codegen_llvm/src/builder.rs @@ -340,14 +340,14 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> { } } - fn br_with_attrs(&mut self, dest: &'ll BasicBlock, attributes: &[AttributeKind]) { + fn br_with_attrs(&mut self, dest: &'ll BasicBlock, loop_hint_attrs: &[AttributeKind]) { unsafe { let val = llvm::LLVMBuildBr(self.llbuilder, dest); let mut nodes = Vec::new(); - for attribute in attributes { - let AttributeKind::Unroll(unroll) = attribute else { + for loop_hint_attr in loop_hint_attrs { + let AttributeKind::Unroll(unroll) = loop_hint_attr else { continue; }; // UnrollAttr::Count needs a second operand, the provided count, but the other diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs index 6dbf9185eaebd..8fa044a45de22 100644 --- a/compiler/rustc_codegen_ssa/src/mir/block.rs +++ b/compiler/rustc_codegen_ssa/src/mir/block.rs @@ -140,7 +140,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { bx: &mut Bx, target: mir::BasicBlock, mergeable_succ: bool, - attributes: &[AttributeKind], + loop_hint_attrs: &[AttributeKind], ) -> MergingSucc { let (needs_landing_pad, is_cleanupret) = self.llbb_characteristics(fx, target); if mergeable_succ && !needs_landing_pad && !is_cleanupret { @@ -156,7 +156,7 @@ impl<'a, 'tcx> TerminatorCodegenHelper<'tcx> { // to a trampoline. bx.cleanup_ret(self.funclet(fx).unwrap(), Some(lltarget)); } else { - bx.br_with_attrs(lltarget, attributes); + bx.br_with_attrs(lltarget, loop_hint_attrs); } MergingSucc::False } @@ -1677,7 +1677,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> { } mir::TerminatorKind::Goto { target } => { - helper.funclet_br(self, bx, target, mergeable_succ(), &terminator.attributes) + helper.funclet_br(self, bx, target, mergeable_succ(), &terminator.loop_hint_attrs) } mir::TerminatorKind::SwitchInt { ref discr, ref targets } => { diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs index b6fdcb21bf2d4..59e1f6e9d0098 100644 --- a/compiler/rustc_codegen_ssa/src/traits/builder.rs +++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs @@ -94,7 +94,7 @@ pub trait BuilderMethods<'a, 'tcx>: fn ret_void(&mut self); fn ret(&mut self, v: Self::Value); fn br(&mut self, dest: Self::BasicBlock); - fn br_with_attrs(&mut self, dest: Self::BasicBlock, _attributes: &[AttributeKind]) { + fn br_with_attrs(&mut self, dest: Self::BasicBlock, _loop_hint_attrs: &[AttributeKind]) { self.br(dest) } fn cond_br( diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs index 2d51f382f0998..540a49aece678 100644 --- a/compiler/rustc_middle/src/mir/terminator.rs +++ b/compiler/rustc_middle/src/mir/terminator.rs @@ -419,7 +419,7 @@ impl fmt::Display for AssertKind { pub struct Terminator<'tcx> { pub source_info: SourceInfo, pub kind: TerminatorKind<'tcx>, - pub attributes: ThinVec, + pub loop_hint_attrs: ThinVec, } impl<'tcx> Terminator<'tcx> { diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs index a6d15ac6458b8..1b45378c86c0a 100644 --- a/compiler/rustc_middle/src/mir/visit.rs +++ b/compiler/rustc_middle/src/mir/visit.rs @@ -518,7 +518,7 @@ macro_rules! make_mir_visitor { terminator: &$($mutability)? Terminator<'tcx>, location: Location ) { - let Terminator { source_info, kind, attributes: _ } = terminator; + let Terminator { source_info, kind, loop_hint_attrs: _ } = terminator; self.visit_source_info(source_info); match kind { diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs index 69d518bf82786..a3e5168e4f1e9 100644 --- a/compiler/rustc_middle/src/thir.rs +++ b/compiler/rustc_middle/src/thir.rs @@ -62,7 +62,7 @@ macro_rules! thir_with_elements { #[derive(Debug, StableHash, Clone)] pub struct Thir<'tcx> { pub body_type: BodyTy<'tcx>, - pub attributes: FxIndexMap>, + pub loop_hint_attrs: FxIndexMap>, $( pub $name: IndexVec<$id, $value>, )* @@ -72,7 +72,7 @@ macro_rules! thir_with_elements { pub fn new(body_type: BodyTy<'tcx>) -> Thir<'tcx> { Thir { body_type, - attributes: FxIndexMap::default(), + loop_hint_attrs: FxIndexMap::default(), $( $name: IndexVec::new(), )* diff --git a/compiler/rustc_mir_build/src/builder/cfg.rs b/compiler/rustc_mir_build/src/builder/cfg.rs index 63ccf323fc204..a8e68963ec724 100644 --- a/compiler/rustc_mir_build/src/builder/cfg.rs +++ b/compiler/rustc_mir_build/src/builder/cfg.rs @@ -121,7 +121,7 @@ impl<'tcx> CFG<'tcx> { self.block_data(block) ); self.block_data_mut(block).terminator = - Some(Terminator { source_info, kind, attributes: ThinVec::new() }); + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }); self.block_data_mut(block).terminator.as_mut().unwrap() } diff --git a/compiler/rustc_mir_build/src/builder/custom/parse.rs b/compiler/rustc_mir_build/src/builder/custom/parse.rs index 32284fe5f42bc..73ffbec6685cc 100644 --- a/compiler/rustc_mir_build/src/builder/custom/parse.rs +++ b/compiler/rustc_mir_build/src/builder/custom/parse.rs @@ -319,7 +319,7 @@ impl<'a, 'tcx> ParseCtxt<'a, 'tcx> { data.terminator = Some(Terminator { source_info: SourceInfo { span, scope: self.source_scope }, kind: terminator, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); Ok(data) diff --git a/compiler/rustc_mir_build/src/builder/expr/into.rs b/compiler/rustc_mir_build/src/builder/expr/into.rs index 3a2e750d4904b..6ca12032362be 100644 --- a/compiler/rustc_mir_build/src/builder/expr/into.rs +++ b/compiler/rustc_mir_build/src/builder/expr/into.rs @@ -238,8 +238,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> { let body_block_end = this.expr_into_dest(tmp, body_block, body).into_block(); let goto = this.cfg.goto(body_block_end, source_info, loop_block); - if let Some(attrs) = this.thir.attributes.get(&expr_id) { - goto.attributes = attrs.clone(); + if let Some(attrs) = this.thir.loop_hint_attrs.get(&expr_id) { + goto.loop_hint_attrs = attrs.clone(); } // Loops are only exited by `break` expressions. diff --git a/compiler/rustc_mir_build/src/thir/cx/expr.rs b/compiler/rustc_mir_build/src/thir/cx/expr.rs index ce800491b9842..16e92ae2c51e4 100644 --- a/compiler/rustc_mir_build/src/thir/cx/expr.rs +++ b/compiler/rustc_mir_build/src/thir/cx/expr.rs @@ -57,12 +57,14 @@ impl<'tcx> SplattedFunc<'tcx> { } } -fn parsed_attrs(id: HirId, tcx: TyCtxt<'_>) -> ThinVec { +fn filter_loop_hint_attrs(id: HirId, tcx: TyCtxt<'_>) -> ThinVec { HasAttrs::get_attrs(id, &tcx) .into_iter() .filter_map(|attr| match attr { - rustc_attr_ir::Attribute::Parsed(attrkind) => Some(attrkind.clone()), - rustc_attr_ir::Attribute::Unparsed(_) => None, + rustc_attr_ir::Attribute::Parsed(attrkind @ AttributeKind::Unroll(_)) => { + Some(attrkind.clone()) + } + _ => None, }) .collect() } @@ -91,7 +93,7 @@ impl<'tcx> ThirBuildCx<'tcx> { trace!(?expr.ty); - let mut attrs = ThinVec::new(); + let mut loop_hint_attrs = ThinVec::new(); if let hir::ExprKind::Loop(_, _, _, span) = hir_expr.kind { match span.desugaring_kind() { @@ -103,12 +105,12 @@ impl<'tcx> ThirBuildCx<'tcx> { // ignore async for loops if let hir::Node::Expr(expr) = self.tcx.parent_hir_node(expr.hir_id) { std::assert_matches!(expr.kind, hir::ExprKind::DropTemps(..)); - attrs = parsed_attrs(expr.hir_id, self.tcx) + loop_hint_attrs = filter_loop_hint_attrs(expr.hir_id, self.tcx) } } // For loops defined with `loop` and `while`, the expr already has the attrs Some(DesugaringKind::WhileLoop) | None => { - attrs = parsed_attrs(hir_expr.hir_id, self.tcx); + loop_hint_attrs = filter_loop_hint_attrs(hir_expr.hir_id, self.tcx); } _ => (), } @@ -128,8 +130,8 @@ impl<'tcx> ThirBuildCx<'tcx> { let ty = expr.ty; let value = self.thir.exprs.push(expr); - if !attrs.is_empty() { - self.thir.attributes.insert(value, attrs); + if !loop_hint_attrs.is_empty() { + self.thir.loop_hint_attrs.insert(value, loop_hint_attrs); } // Finally, wrap this up in the expr's scope. diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs index ee6330bfe1c2c..9646caab241d9 100644 --- a/compiler/rustc_mir_dataflow/src/framework/tests.rs +++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs @@ -22,7 +22,7 @@ fn mock_body<'tcx>() -> mir::Body<'tcx> { blocks.push(mir::BasicBlockData::new_stmts( std::iter::repeat(&nop).cloned().take(n).collect(), - Some(mir::Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(mir::Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), false, )) }; diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs index b73cb453752e1..01fd042864019 100644 --- a/compiler/rustc_mir_transform/src/add_call_guards.rs +++ b/compiler/rustc_mir_transform/src/add_call_guards.rs @@ -92,7 +92,7 @@ impl<'tcx> crate::MirPass<'tcx> for AddCallGuards { Some(Terminator { source_info, kind: TerminatorKind::Goto { target }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), is_cleanup, ); diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs index 6b74d53801594..e0c07619efbc6 100644 --- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs +++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs @@ -98,7 +98,7 @@ fn add_move_for_packed_drop<'tcx>( Some(Terminator { source_info, kind: TerminatorKind::Goto { target }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), is_cleanup, )); diff --git a/compiler/rustc_mir_transform/src/check_enums.rs b/compiler/rustc_mir_transform/src/check_enums.rs index e6bc8949a6cad..8d2178a07c5c6 100644 --- a/compiler/rustc_mir_transform/src/check_enums.rs +++ b/compiler/rustc_mir_transform/src/check_enums.rs @@ -64,7 +64,7 @@ impl<'tcx> crate::MirPass<'tcx> for CheckEnums { basic_blocks[block].terminator = Some(Terminator { source_info, kind: TerminatorKind::Goto { target: new_block }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } EnumCheckType::Direct { source_op, discr, op_size, valid_discrs } => { @@ -395,7 +395,7 @@ fn insert_direct_enum_check<'tcx>( invalid_discr_block, ), }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); // Abort in case of an invalid enum discriminant. @@ -415,7 +415,7 @@ fn insert_direct_enum_check<'tcx>( // make a failing UB check turn into much worse UB when we start unwinding. unwind: UnwindAction::Unreachable, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } @@ -461,7 +461,7 @@ fn insert_uninhabited_enum_check<'tcx>( // make a failing UB check turn into much worse UB when we start unwinding. unwind: UnwindAction::Unreachable, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } @@ -539,6 +539,6 @@ fn insert_niche_check<'tcx>( // make a failing UB check turn into much worse UB when we start unwinding. unwind: UnwindAction::Unreachable, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } diff --git a/compiler/rustc_mir_transform/src/check_pointers.rs b/compiler/rustc_mir_transform/src/check_pointers.rs index 7c24e3d29c50a..fb6379a25af95 100644 --- a/compiler/rustc_mir_transform/src/check_pointers.rs +++ b/compiler/rustc_mir_transform/src/check_pointers.rs @@ -117,7 +117,7 @@ pub(crate) fn check_pointers<'tcx, F>( // worse UB when we start unwinding. unwind: UnwindAction::Unreachable, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } } diff --git a/compiler/rustc_mir_transform/src/coroutine/drop.rs b/compiler/rustc_mir_transform/src/coroutine/drop.rs index 6b26a1f242cf0..44ea6aef0e02d 100644 --- a/compiler/rustc_mir_transform/src/coroutine/drop.rs +++ b/compiler/rustc_mir_transform/src/coroutine/drop.rs @@ -376,7 +376,7 @@ pub(super) fn create_coroutine_drop_shim_proxy_async<'tcx>( drop: None, }; body.basic_blocks_mut()[call_bb].terminator = - Some(Terminator { source_info, kind, attributes: ThinVec::new() }); + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }); // Run derefer to fix Derefs that are not in the first place deref_finder(tcx, &mut body, false); diff --git a/compiler/rustc_mir_transform/src/coroutine/mod.rs b/compiler/rustc_mir_transform/src/coroutine/mod.rs index a678e94994aa5..1e63dca78adbb 100644 --- a/compiler/rustc_mir_transform/src/coroutine/mod.rs +++ b/compiler/rustc_mir_transform/src/coroutine/mod.rs @@ -256,7 +256,7 @@ impl<'tcx> TransformVisitor<'tcx> { Some(Terminator { source_info, kind: TerminatorKind::Return, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )); @@ -744,14 +744,14 @@ fn insert_switch<'tcx>( body.basic_blocks_mut()[START_BLOCK].terminator = Some(Terminator { source_info: SourceInfo::outermost(body.span), kind: switch, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } fn insert_term_block<'tcx>(body: &mut Body<'tcx>, kind: TerminatorKind<'tcx>) -> BasicBlock { let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().push(BasicBlockData::new( - Some(Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), false, )) } @@ -776,7 +776,11 @@ fn insert_poll_ready_block<'tcx>(tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) -> Ba let source_info = SourceInfo::outermost(body.span); body.basic_blocks_mut().push(BasicBlockData::new_stmts( [return_poll_ready_assign(tcx, source_info)].to_vec(), - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, )) } @@ -835,7 +839,7 @@ fn generate_poison_block_and_redirect_unwinds_there<'tcx>( source_info, kind: TerminatorKind::UnwindResume, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), true, )); @@ -851,7 +855,7 @@ fn generate_poison_block_and_redirect_unwinds_there<'tcx>( source_info, kind: TerminatorKind::Goto { target: poison_block }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }; } } else if !block.is_cleanup @@ -1019,7 +1023,7 @@ fn create_cases<'tcx>( source_info, kind: TerminatorKind::Goto { target }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )); diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs index ca4fa888a2176..e9876310f112f 100644 --- a/compiler/rustc_mir_transform/src/coverage/tests.rs +++ b/compiler/rustc_mir_transform/src/coverage/tests.rs @@ -73,7 +73,7 @@ impl<'tcx> MockBlocks<'tcx> { Some(Terminator { source_info: SourceInfo::outermost(Span::with_root_ctxt(next_lo, next_hi)), kind, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )) diff --git a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs index b13a4fa16e21d..b1ac4d33445b0 100644 --- a/compiler/rustc_mir_transform/src/early_otherwise_branch.rs +++ b/compiler/rustc_mir_transform/src/early_otherwise_branch.rs @@ -175,7 +175,7 @@ impl<'tcx> crate::MirPass<'tcx> for EarlyOtherwiseBranch { discr: parent_op, targets: eq_targets, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), bbs[parent].is_cleanup, ); @@ -230,7 +230,7 @@ fn evaluate_candidate<'tcx>( let Terminator { kind: TerminatorKind::SwitchInt { targets: child_targets, discr: child_discr }, source_info, - attributes: _, + loop_hint_attrs: _, } = bbs[child].terminator() else { return None; diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index d97441420e63f..9b81f55ab1145 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -1641,7 +1641,11 @@ where #[instrument(level = "trace", skip(self), ret)] fn new_block(&mut self, unwind: Unwind, k: TerminatorKind<'tcx>) -> BasicBlock { self.elaborator.patch().new_block(BasicBlockData::new( - Some(Terminator { source_info: self.source_info, kind: k, attributes: ThinVec::new() }), + Some(Terminator { + source_info: self.source_info, + kind: k, + loop_hint_attrs: ThinVec::new(), + }), unwind.is_cleanup(), )) } @@ -1655,7 +1659,11 @@ where ) -> BasicBlock { self.elaborator.patch().new_block(BasicBlockData::new_stmts( statements, - Some(Terminator { source_info: self.source_info, kind: k, attributes: ThinVec::new() }), + Some(Terminator { + source_info: self.source_info, + kind: k, + loop_hint_attrs: ThinVec::new(), + }), unwind.is_cleanup(), )) } diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index f8df2eabdaf0d..9547b5bb93dff 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -872,7 +872,7 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( Some(Terminator { source_info: terminator.source_info, kind: TerminatorKind::Goto { target: block }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), caller_body[block].is_cleanup, ); @@ -1000,7 +1000,7 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( caller_body[callsite.block].terminator = Some(Terminator { source_info: callsite.source_info, kind: TerminatorKind::Goto { target: integrator.map_block(START_BLOCK) }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); // Copy required constants from the callee_body into the caller_body. Although we are only diff --git a/compiler/rustc_mir_transform/src/patch.rs b/compiler/rustc_mir_transform/src/patch.rs index bd4cbcd89163c..6a2d5101067e7 100644 --- a/compiler/rustc_mir_transform/src/patch.rs +++ b/compiler/rustc_mir_transform/src/patch.rs @@ -93,7 +93,7 @@ impl<'tcx> MirPatch<'tcx> { Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::UnwindResume, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), true, )); @@ -110,7 +110,7 @@ impl<'tcx> MirPatch<'tcx> { Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::Unreachable, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), true, )); @@ -127,7 +127,7 @@ impl<'tcx> MirPatch<'tcx> { Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::Unreachable, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )); @@ -146,7 +146,7 @@ impl<'tcx> MirPatch<'tcx> { Some(Terminator { source_info: SourceInfo::outermost(self.body_span), kind: TerminatorKind::UnwindTerminate(reason), - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), true, )); diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index 43d058c7eef0c..92c2f9a1c20e1 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -757,7 +757,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Some(Terminator { source_info: SourceInfo::outermost(span), kind: TerminatorKind::Return, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )) @@ -846,7 +846,7 @@ impl<'a, 'tcx> Promoter<'a, 'tcx> { Terminator { source_info: terminator.source_info, kind: mem::replace(&mut terminator.kind, TerminatorKind::Goto { target }), - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), } }; diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs index a2a9f6c37456f..faf7039d498b1 100644 --- a/compiler/rustc_mir_transform/src/shim.rs +++ b/compiler/rustc_mir_transform/src/shim.rs @@ -281,7 +281,7 @@ pub fn build_drop_shim<'tcx>( let mut blocks = IndexVec::with_capacity(2); let block = |blocks: &mut IndexVec<_, _>, kind| { blocks.push(BasicBlockData::new( - Some(Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), false, )) }; @@ -338,7 +338,7 @@ pub fn build_drop_shim<'tcx>( call_source: CallSource::Misc, fn_span: span, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }); } else { let patch = { @@ -491,7 +491,11 @@ fn build_thread_local_shim<'tcx>(tcx: TyCtxt<'tcx>, shim: ty::ShimKind<'tcx>) -> Rvalue::ThreadLocalRef(def_id), ))), )], - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, )]); @@ -577,7 +581,7 @@ impl<'tcx> CloneShimBuilder<'tcx> { let source_info = self.source_info(); self.blocks.push(BasicBlockData::new_stmts( statements, - Some(Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), is_cleanup, )) } @@ -923,7 +927,7 @@ fn build_call_shim<'tcx>( let block = |blocks: &mut IndexVec<_, _>, statements, kind, is_cleanup| { blocks.push(BasicBlockData::new_stmts( statements, - Some(Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), is_cleanup, )) }; @@ -1050,7 +1054,11 @@ pub(super) fn build_adt_ctor(tcx: TyCtxt<'_>, ctor_id: DefId) -> Body<'_> { let start_block = BasicBlockData::new_stmts( vec![statement], - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, ); @@ -1133,7 +1141,11 @@ fn build_fn_ptr_as_ptr_shim<'tcx>( let start_block = BasicBlockData::new_stmts( statements, - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, ); let source = MirSource::from_shim(ty::ShimKind::FnPtrAsPtr(def_id, self_ty)); @@ -1168,7 +1180,11 @@ fn build_fn_ptr_from_ptr_shim<'tcx>( let start_block = BasicBlockData::new_stmts( statements, - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, ); let source = MirSource::from_shim(ty::ShimKind::FnPtrFromPtr(def_id, self_ty)); @@ -1266,7 +1282,11 @@ fn build_construct_coroutine_by_move_shim<'tcx>( let statements = vec![stmt]; let start_block = BasicBlockData::new_stmts( statements, - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, ); diff --git a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs index 0570895532370..fcc28b20d25a0 100644 --- a/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs +++ b/compiler/rustc_mir_transform/src/shim/async_destructor_ctor.rs @@ -86,7 +86,7 @@ pub(super) fn build_async_drop_shim<'tcx>( let mut blocks = IndexVec::with_capacity(2); let block = |blocks: &mut IndexVec<_, _>, kind| { blocks.push(BasicBlockData::new( - Some(Terminator { source_info, kind, attributes: ThinVec::new() }), + Some(Terminator { source_info, kind, loop_hint_attrs: ThinVec::new() }), false, )) }; @@ -394,7 +394,7 @@ fn build_adrop_for_adrop_shim<'tcx>( fn_span: span, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )); @@ -419,12 +419,16 @@ fn build_adrop_for_adrop_shim<'tcx>( fn_span: span, }, - attributes: ThinVec::new(), + loop_hint_attrs: ThinVec::new(), }), false, )); blocks.push(BasicBlockData::new( - Some(Terminator { source_info, kind: TerminatorKind::Return, attributes: ThinVec::new() }), + Some(Terminator { + source_info, + kind: TerminatorKind::Return, + loop_hint_attrs: ThinVec::new(), + }), false, )); diff --git a/tests/incremental/cache-lint-expectation.rs b/tests/incremental/cache-lint-expectation.rs index 0fb38008a855a..c05508cbfc934 100644 --- a/tests/incremental/cache-lint-expectation.rs +++ b/tests/incremental/cache-lint-expectation.rs @@ -1,8 +1,11 @@ -// Regression test for #154878 +// Regression test for #154878 and #162811 //@ revisions: bpass1 bpass2 pub fn main() { let x = 42.0; #[expect(invalid_nan_comparisons)] let _b = x == f32::NAN; + + #[allow(dead_code)] + for _ in 0..10 {} } diff --git a/tests/ui/thir-print/str-patterns.stdout b/tests/ui/thir-print/str-patterns.stdout index 61bcbaef5029a..f943eb03675ab 100644 --- a/tests/ui/thir-print/str-patterns.stdout +++ b/tests/ui/thir-print/str-patterns.stdout @@ -3,7 +3,7 @@ Thir { body_type: Fn( fn(&'{erased} str), ), - attributes: {}, + loop_hint_attrs: {}, arms: [ Arm { pattern: Pat { @@ -294,7 +294,7 @@ Thir { body_type: Const( &'{erased} str, ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [], exprs: [ diff --git a/tests/ui/thir-print/thir-flat-const-variant.stdout b/tests/ui/thir-print/thir-flat-const-variant.stdout index 82e197330cca8..e16cda9a7cb47 100644 --- a/tests/ui/thir-print/thir-flat-const-variant.stdout +++ b/tests/ui/thir-print/thir-flat-const-variant.stdout @@ -3,7 +3,7 @@ Thir { body_type: Const( Foo, ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [], exprs: [ @@ -65,7 +65,7 @@ Thir { body_type: Const( Foo, ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [], exprs: [ @@ -127,7 +127,7 @@ Thir { body_type: Const( Foo, ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [], exprs: [ @@ -189,7 +189,7 @@ Thir { body_type: Const( Foo, ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [], exprs: [ @@ -251,7 +251,7 @@ Thir { body_type: Fn( fn(), ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [ Block { diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout index 76df9f4394315..15f63605957c5 100644 --- a/tests/ui/thir-print/thir-flat.stdout +++ b/tests/ui/thir-print/thir-flat.stdout @@ -3,7 +3,7 @@ Thir { body_type: Fn( fn(), ), - attributes: {}, + loop_hint_attrs: {}, arms: [], blocks: [ Block { From 2e58a77da46625e9233cfac7b5cc758c4db29a18 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 16 Sep 2026 20:34:55 +0200 Subject: [PATCH 0958/1309] Fix intra doc link resolution when a doc comment is composed of both inner and outer doc comment --- compiler/rustc_resolve/src/late.rs | 34 +++++++++--- compiler/rustc_resolve/src/rustdoc.rs | 53 +++++++++++-------- compiler/rustc_resolve/src/rustdoc/tests.rs | 3 ++ src/librustdoc/clean/types.rs | 12 +++-- src/librustdoc/clean/types/tests.rs | 1 + .../passes/collect_intra_doc_links.rs | 48 ++++++++++++----- .../passes/lint/redundant_explicit_links.rs | 9 ++-- .../intra-doc/mixed-inner-outer.rs | 22 ++++++++ 8 files changed, 132 insertions(+), 50 deletions(-) create mode 100644 tests/rustdoc-html/intra-doc/mixed-inner-outer.rs diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..4050ec8eee5d5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -12,6 +12,7 @@ use std::debug_assert_matches; use std::mem::{replace, swap, take}; use std::ops::{ControlFlow, Range}; +use rustc_ast::attr::AttributeExt; use rustc_ast::visit::{ AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, try_visit, visit_opt, walk_list, }; @@ -2860,10 +2861,22 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } fn resolve_item(&mut self, item: &'ast Item) { - let mod_inner_docs = - matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs); - if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) { - self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); + match item.kind { + ItemKind::Mod(..) => { + // We only handle outer doc comments for modules here. + let attrs = if let Some(pos) = item.attrs.iter().position(|a| { + a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) + }) { + &item.attrs[..pos] + } else { + &item.attrs + }; + self.resolve_doc_links(attrs, MaybeExported::Ok(item.id)); + } + ItemKind::Impl(..) | ItemKind::Use(..) => {} + _ => { + self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); + } } debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); @@ -2957,9 +2970,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let orig_module = replace(&mut self.parent_scope.module, module); self.with_rib(ValueNS, RibKind::Module(module.expect_local()), |this| { this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { - if mod_inner_docs { - this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); - } + // Outer doc comments were already handled above, now we handle + // inner doc comments. + let attrs = if let Some(pos) = item.attrs.iter().position(|a| { + a.doc_resolution_scope().is_some_and(|style| style == AttrStyle::Inner) + }) { + &item.attrs[pos..] + } else { + &[] + }; + this.resolve_doc_links(attrs, MaybeExported::Ok(item.id)); let old_macro_rules = this.parent_scope.macro_rules; visit::walk_item(this, item); // Maintain macro_rules scopes in the same way as during early resolution diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs index ddf5600f76659..ac463297ad84d 100644 --- a/compiler/rustc_resolve/src/rustdoc.rs +++ b/compiler/rustc_resolve/src/rustdoc.rs @@ -9,9 +9,9 @@ use pulldown_cmark::{ }; use rustc_ast as ast; use rustc_ast::attr::AttributeExt; -use rustc_ast::join_path_syms; use rustc_ast::token::DocFragmentKind; use rustc_ast::util::comments::beautify_doc_string; +use rustc_ast::{AttrStyle, join_path_syms}; use rustc_data_structures::fx::FxIndexMap; use rustc_data_structures::unord::UnordSet; use rustc_middle::ty::TyCtxt; @@ -48,6 +48,7 @@ pub struct DocFragment { /// Because we tamper with the spans context, this information cannot be correctly retrieved /// later on. So instead, we compute it and store it here. pub from_expansion: bool, + pub style: AttrStyle, } #[derive(Clone, Copy, Debug)] @@ -215,8 +216,15 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( (value_span.with_ctxt(attr_span.ctxt()), value_span.from_expansion()) } }; - let fragment = - DocFragment { span, doc, kind: fragment_kind, item_id, indent: 0, from_expansion }; + let fragment = DocFragment { + span, + doc, + kind: fragment_kind, + item_id, + indent: 0, + from_expansion, + style: attr.doc_resolution_scope().unwrap(), + }; doc_fragments.push(fragment); } else if !doc_only { other_attrs.push(attr.clone()); @@ -231,6 +239,14 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( (doc_fragments, other_attrs) } +/// Represents a doc comment, split in two parts, outer and inner attributes. It's needed for +/// the intra-doc link resolution context. +#[derive(Default)] +pub struct DocStrings { + pub outer: String, + pub inner: String, +} + /// Return the doc-comments on this item, grouped by the module they came from. /// The module can be different if this is a re-export with added documentation. /// @@ -238,11 +254,16 @@ pub fn attrs_to_doc_fragments<'a, A: AttributeExt + Clone + 'a>( /// early and late doc link resolution regardless of their position. pub fn prepare_to_doc_link_resolution( doc_fragments: &[DocFragment], -) -> FxIndexMap, String> { - let mut res = FxIndexMap::default(); +) -> FxIndexMap, DocStrings> { + let mut res: FxIndexMap, DocStrings> = FxIndexMap::default(); for fragment in doc_fragments { - let out_str = res.entry(fragment.item_id).or_default(); - add_doc_fragment(out_str, fragment); + let out_strs = res.entry(fragment.item_id).or_default(); + let out = if fragment.style == AttrStyle::Inner { + &mut out_strs.inner + } else { + &mut out_strs.outer + }; + add_doc_fragment(out, fragment); } res } @@ -351,19 +372,6 @@ pub fn strip_generics_from_path(path_str: &str) -> Result, MalformedGen } } -/// Returns whether the first doc-comment is an inner attribute. -/// -/// If there are no doc-comments, return true. -/// FIXME(#78591): Support both inner and outer attributes on the same item. -pub fn inner_docs(attrs: &[impl AttributeExt]) -> bool { - for attr in attrs { - if let Some(attr_style) = attr.doc_resolution_scope() { - return attr_style == ast::AttrStyle::Inner; - } - } - true -} - /// Has `#[rustc_doc_primitive]` or `#[doc(keyword)]` or `#[doc(attribute)]`. pub fn has_primitive_or_keyword_or_attribute_docs(attrs: &[impl AttributeExt]) -> bool { for attr in attrs { @@ -413,7 +421,10 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec) -> bool { + use rustc_ast::attr::AttributeExt; + self.item_id .as_def_id() .map(|did| { - inner_docs( - #[allow(deprecated)] - tcx.get_all_attrs(did), - ) + #[allow(deprecated)] + tcx.get_all_attrs(did).iter().any(|attr| { + attr.doc_resolution_scope().is_some_and(|style| style == ast::AttrStyle::Inner) + }) }) .unwrap_or(false) } diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs index a0fc623c20c48..29a8fd5e2678e 100644 --- a/src/librustdoc/clean/types/tests.rs +++ b/src/librustdoc/clean/types/tests.rs @@ -12,6 +12,7 @@ fn create_doc_fragment(s: &str) -> Vec { kind: DocFragmentKind::Sugared(CommentKind::Line), indent: 0, from_expansion: false, + style: rustc_ast::AttrStyle::Outer, }] } diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs index d7815e64178a7..ac7cf2a42bd3b 100644 --- a/src/librustdoc/passes/collect_intra_doc_links.rs +++ b/src/librustdoc/passes/collect_intra_doc_links.rs @@ -21,8 +21,8 @@ use rustc_middle::ty; use rustc_middle::ty::{Ty, TyCtxt}; use rustc_resolve::rustdoc::pulldown_cmark::LinkType; use rustc_resolve::rustdoc::{ - MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, prepare_to_doc_link_resolution, - source_span_for_markdown_range, strip_generics_from_path, + DocStrings, MalformedGenerics, has_primitive_or_keyword_or_attribute_docs, + prepare_to_doc_link_resolution, source_span_for_markdown_range, strip_generics_from_path, }; use rustc_span::def_id::ModId; use rustc_span::edit_distance::find_best_match_for_name; @@ -1091,14 +1091,7 @@ impl LinkCollector<'_, '_> { return; } - let mut try_insert_links = |item_id, doc: &str| { - if should_skip_link_resolution(item_id) { - return; - } - let module_id = match tcx.def_kind(item_id) { - DefKind::Mod if item.inner_docs(tcx) => ModId::new_unchecked(item_id), - _ => find_nearest_parent_module(tcx, item_id).unwrap(), - }; + let mut try_insert_links_inner = |item_id, module_id, doc: &str| { for md_link in preprocessed_markdown_links(&doc) { let link = self.resolve_link(&doc, item, item_id, module_id, &md_link); if let Some(link) = link { @@ -1112,16 +1105,45 @@ impl LinkCollector<'_, '_> { } }; + let mut try_insert_links = |item_id, docs: &DocStrings| { + if should_skip_link_resolution(item_id) { + return; + } + match tcx.def_kind(item_id) { + DefKind::Mod => { + if !docs.outer.is_empty() { + try_insert_links_inner( + item_id, + find_nearest_parent_module(tcx, item_id).unwrap(), + &docs.outer, + ); + } + if !docs.inner.is_empty() { + try_insert_links_inner(item_id, ModId::new_unchecked(item_id), &docs.inner); + } + } + _ => { + // It's the same handling for non-module items. + let module_id = find_nearest_parent_module(tcx, item_id).unwrap(); + try_insert_links_inner( + item_id, + module_id, + &format!("{}{}", docs.outer, docs.inner), + ); + } + } + }; + // We want to resolve in the lexical scope of the documentation. // In the presence of re-exports, this is not the same as the module of the item. // Rather than merging all documentation into one, resolve it one attribute at a time // so we know which module it came from. for (item_id, doc) in prepare_to_doc_link_resolution(&item.attrs.doc_strings) { - if !may_have_doc_links(&doc) { + if !may_have_doc_links(&doc.inner) && !may_have_doc_links(&doc.outer) { continue; } - debug!("combined_docs={doc}"); + debug!("combined_docs=outer: {} inner: {}", doc.outer, doc.inner); // NOTE: if there are links that start in one crate and end in another, this will not resolve them. // This is a degenerate case and it's not supported by rustdoc. let item_id = item_id.unwrap_or_else(|| item.item_id.expect_def_id()); @@ -1163,7 +1185,7 @@ impl LinkCollector<'_, '_> { } else { item.item_id.expect_def_id() }; - try_insert_links(item_id, note) + try_insert_links(item_id, &DocStrings { outer: note.to_owned(), inner: String::new() }); } } diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs index 902054c917699..e02fbae3e0568 100644 --- a/src/librustdoc/passes/lint/redundant_explicit_links.rs +++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs @@ -30,10 +30,11 @@ struct LinkData { pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item, hir_id: HirId) { let hunks = prepare_to_doc_link_resolution(&item.attrs.doc_strings); for (item_id, doc) in hunks { - if let Some(item_id) = item_id.or(item.def_id()) - && !doc.is_empty() - { - check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + if let Some(item_id) = item_id.or(item.def_id()) { + if !doc.outer.is_empty() || !doc.inner.is_empty() { + let doc = format!("{}{}", doc.outer, doc.inner); + check_redundant_explicit_link_for_did(cx, item, item_id, hir_id, &doc); + } } } } diff --git a/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs b/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs new file mode 100644 index 0000000000000..5a0f92522662d --- /dev/null +++ b/tests/rustdoc-html/intra-doc/mixed-inner-outer.rs @@ -0,0 +1,22 @@ +// This test ensures that when a documentation is composed of both inner and outer +// doc comments, the intra-doc link resolution still works as expected. +// Regression test for . +// Regression test for . +// Regression test for . + +#![crate_name = "foo"] +#![deny(rustdoc::broken_intra_doc_links)] + +//@ has foo/demo/index.html +//@ has - '//a[@href="../struct.Foo.html"]' 'Foo' +//@ has - '//a[@href="struct.DemoStruct.html"]' 'DemoStruct' + +/// Outer doc-comment [`Foo`]. +pub mod demo { + //! + //! Inner doc-comment with link: [`DemoStruct`] + + pub struct DemoStruct; +} + +pub struct Foo; From 9e8ca583f8115555cc39997e4468328c655879f3 Mon Sep 17 00:00:00 2001 From: khyperia <953151+khyperia@users.noreply.github.com> Date: Mon, 28 Sep 2026 15:50:47 +0200 Subject: [PATCH 0959/1309] implement #![feature(gca_adts)] --- Cargo.lock | 1 + compiler/rustc_ast_lowering/Cargo.toml | 1 + compiler/rustc_ast_lowering/src/lib.rs | 149 ++++++++++++------ compiler/rustc_ast_passes/src/feature_gate.rs | 59 ++++--- compiler/rustc_feature/src/lib.rs | 4 +- compiler/rustc_feature/src/unstable.rs | 34 +++- compiler/rustc_hir_analysis/src/collect.rs | 2 +- .../src/collect/generics_of.rs | 2 +- .../src/hir_ty_lowering/errors.rs | 2 +- .../src/hir_ty_lowering/mod.rs | 2 +- .../rustc_resolve/src/diagnostics/impls.rs | 25 +-- compiler/rustc_resolve/src/diagnostics/mod.rs | 4 +- compiler/rustc_resolve/src/ident.rs | 4 +- compiler/rustc_resolve/src/late.rs | 2 +- .../rustc_resolve/src/late/diagnostics.rs | 5 +- compiler/rustc_resolve/src/lib.rs | 2 +- compiler/rustc_span/src/symbol.rs | 1 + .../traits/fulfillment_errors.rs | 3 +- .../src/traits/const_evaluatable.rs | 2 +- .../rustc_trait_selection/src/traits/wf.rs | 2 +- compiler/rustc_type_ir/src/const_kind.rs | 3 - library/core/src/marker.rs | 9 +- library/std/src/lib.rs | 2 +- .../src/language-features/gca-adts.md | 21 +++ .../language-features/gca-min-const-items.md | 2 +- ...onst-pattern-field-type-mismatch-162394.rs | 13 +- ...-pattern-field-type-mismatch-162394.stderr | 2 +- .../const-generics/gca/gca-macro-fn-call.rs | 12 +- .../gca/gca-macro-fn-call.stderr | 10 +- .../gca_adts/missing-dependent-features.rs | 3 + .../missing-dependent-features.stderr | 10 ++ .../gca_adts/none-incomplete.rs | 21 +++ .../gca_adts/none-incomplete.stderr | 8 + tests/ui/const-generics/gca_adts/none.rs | 21 +++ .../inherent-type-const.rs | 5 +- .../mgca/adt_expr_arg_simple.rs | 3 +- .../mgca/adt_expr_arg_simple.stderr | 4 +- .../mgca/adt_expr_arg_tuple_expr_fail.rs | 6 +- .../mgca/adt_expr_erroneuous_inits.rs | 15 +- .../mgca/adt_expr_erroneuous_inits.stderr | 38 ++--- .../mgca/adt_expr_fields_type_check.rs | 3 +- .../mgca/adt_expr_fields_type_check.stderr | 14 +- .../mgca/adt_expr_infers_from_value.rs | 12 +- .../mgca/adt_expr_unit_enum_extra_field.rs | 8 +- .../adt_expr_unit_enum_extra_field.stderr | 6 +- .../mgca/adt_expr_unit_struct_extra_field.rs | 2 +- .../mgca/array-const-arg-len-mismatch.rs | 11 +- .../mgca/array-const-arg-len-mismatch.stderr | 20 +-- .../mgca/array-const-arg-type-mismatch.rs | 3 +- .../mgca/array-const-arg-type-mismatch.stderr | 2 +- .../mgca/array-expr-complex.r1.stderr | 2 +- .../mgca/array-expr-complex.r2.stderr | 2 +- .../mgca/array-expr-complex.r3.stderr | 2 +- .../const-generics/mgca/array-expr-complex.rs | 3 +- .../const-generics/mgca/array-expr-simple.rs | 3 +- ...array-expr-type-mismatch-in-where-bound.rs | 4 +- ...y-expr-type-mismatch-in-where-bound.stderr | 4 +- .../mgca/array-expr-with-assoc-const.rs | 3 +- .../mgca/array-expr-with-macro.rs | 3 +- .../mgca/array-expr-with-struct.rs | 3 +- .../mgca/array-expr-with-tuple.rs | 6 +- .../mgca/array-with-wrong-tuple-type.rs | 4 +- .../mgca/array_elem_type_mismatch.rs | 6 +- .../mgca/array_expr_arg_complex.rs | 3 +- .../mgca/array_expr_arg_complex.stderr | 4 +- ...eric-args-on-enum-variant-segments-fail.rs | 7 +- ...-args-on-enum-variant-segments-fail.stderr | 6 +- .../generic-args-on-enum-variant-segments.rs | 3 +- ...eneric_const_items-mismatched-array-len.rs | 10 +- ...ic_const_items-mismatched-array-len.stderr | 4 +- ...onst_parameter_types-inferred-array-len.rs | 2 +- .../mgca/generic_const_type_mismatch.rs | 8 +- .../mgca/invalid-array-in-tuple.rs | 4 +- ...ixed-direct-anon-expression-diagnostics.rs | 3 +- ...-direct-anon-expression-diagnostics.stderr | 4 +- .../mgca/nonsensical-negated-literal.rs | 4 +- .../printing_valtrees_supports_non_values.rs | 3 +- ...inting_valtrees_supports_non_values.stderr | 18 +-- .../mgca/size-of-generic-ptr-in-array-len.rs | 3 +- .../size-of-generic-ptr-in-array-len.stderr | 6 +- .../mgca/syntactic-type-mismatch.rs | 3 +- .../mgca/syntactic-type-mismatch.stderr | 4 +- .../mgca/tuple_ctor_arg_simple.rs | 3 +- .../mgca/tuple_ctor_complex_args.rs | 3 +- .../mgca/tuple_ctor_complex_args.stderr | 4 +- .../mgca/tuple_ctor_erroneous.rs | 3 +- .../mgca/tuple_ctor_erroneous.stderr | 22 +-- .../const-generics/mgca/tuple_ctor_nested.rs | 3 +- .../mgca/tuple_ctor_type_relative.rs | 3 +- .../mgca/tuple_expr_arg_bad-issue-151048.rs | 3 +- .../tuple_expr_arg_bad-issue-151048.stderr | 2 +- .../mgca/tuple_expr_arg_complex.rs | 3 +- .../mgca/tuple_expr_arg_complex.stderr | 8 +- .../mgca/tuple_expr_arg_macroless.rs | 6 +- .../mgca/tuple_expr_arg_mismatch_type.rs | 3 +- .../mgca/tuple_expr_arg_mismatch_type.stderr | 2 +- .../mgca/tuple_expr_arg_simple.rs | 3 +- .../tuple_expr_arg_unbounded_assoc_const.rs | 2 +- .../mgca/tuple_expr_type_mismatch.rs | 4 +- .../mgca/type_const-adt-expr-missing-field.rs | 12 +- .../type_const-adt-expr-missing-field.stderr | 6 +- ..._const-generic-param-in-type.nogate.stderr | 18 +-- .../mgca/type_const-generic-param-in-type.rs | 9 +- .../mgca/wrapped_array_elem_type_mismatch.rs | 2 +- .../mgca/wrong_type_const_arr_diag.rs | 3 +- .../mgca/wrong_type_const_arr_diag.stderr | 2 +- .../mgca/wrong_type_const_arr_diag_trait.rs | 3 +- .../wrong_type_const_arr_diag_trait.stderr | 2 +- .../tuple_with_infer_arg.rs | 2 +- .../ui/feature-gates/feature-gate-gca-adts.rs | 24 +++ .../feature-gate-gca-adts.without.stderr | 58 +++++++ ...ate-gca-adts.without_with_min_items.stderr | 14 ++ .../non_scalar_alignment_value.rs | 8 +- .../non_scalar_alignment_value.stderr | 8 +- ...struct-exprs-tuple-call-pretty-printing.rs | 3 +- ...ct-exprs-tuple-call-pretty-printing.stdout | 5 +- 116 files changed, 640 insertions(+), 355 deletions(-) create mode 100644 src/doc/unstable-book/src/language-features/gca-adts.md create mode 100644 tests/ui/const-generics/gca_adts/missing-dependent-features.rs create mode 100644 tests/ui/const-generics/gca_adts/missing-dependent-features.stderr create mode 100644 tests/ui/const-generics/gca_adts/none-incomplete.rs create mode 100644 tests/ui/const-generics/gca_adts/none-incomplete.stderr create mode 100644 tests/ui/const-generics/gca_adts/none.rs create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.rs create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.without.stderr create mode 100644 tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr diff --git a/Cargo.lock b/Cargo.lock index b5fb5057716ac..002ee75873ee5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -3626,6 +3626,7 @@ dependencies = [ name = "rustc_ast_lowering" version = "0.0.0" dependencies = [ + "bitflags", "rustc_abi", "rustc_ast", "rustc_attr_ir", diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml index 9dc5f81581e87..350687ba299c7 100644 --- a/compiler/rustc_ast_lowering/Cargo.toml +++ b/compiler/rustc_ast_lowering/Cargo.toml @@ -8,6 +8,7 @@ doctest = false [dependencies] # tidy-alphabetical-start +bitflags = "2.4.1" rustc_abi = { path = "../rustc_abi" } rustc_ast = { path = "../rustc_ast" } rustc_attr_ir = { path = "../rustc_attr_ir" } diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4bc61a22b3b3d..eee6d7af5593d 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -56,7 +56,7 @@ use rustc_data_structures::steal::Steal; use rustc_data_structures::tagged_ptr::TaggedRef; use rustc_errors::codes::*; use rustc_errors::{DiagArgFromDisplay, DiagCtxtHandle, ErrorGuaranteed}; -use rustc_hir::def::{DefKind, Namespace, PerNS, Res}; +use rustc_hir::def::{CtorKind, DefKind, Namespace, PerNS, Res}; use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap}; use rustc_hir::definitions::PerParentDisambiguatorState; use rustc_hir::lints::DelayedLint; @@ -1420,10 +1420,10 @@ impl<'hir> LoweringContext<'_, 'hir> { let ct = self.arena.alloc(ct); return GenericArg::Const(ct.try_as_ambig_ct().unwrap()); } - TyKind::GcaMacro(expr) if self.tcx.features().gca_min_const_items() => { + TyKind::GcaMacro(expr) if self.tcx.features().gca() => { let ct = match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, None), Err(e) => e.emit(self), @@ -2632,18 +2632,12 @@ impl<'hir> LoweringContext<'_, 'hir> { span: Span, ) -> hir::ConstItemRhs<'hir> { let is_direct = |body| { - if self.tcx.features().gca_macroless_items() { - self.can_lower_expr_to_const_arg_direct( - body, - DirectConstArgContext::MacrolessMinGenericConstArgs, - ) - .is_ok() + let context = if self.tcx.features().gca_macroless_items() { + self.direct_const_arg_context_enabled_by_gca_macro() } else { - // do not check can_lower_expr_to_const_arg_direct, but rather just - // ExprKind::GcaMacro, because we don't want e.g. - // `impl { const C: u8 = N; }` to be a direct-rhs const - matches!(body, Expr { kind: ExprKind::GcaMacro(_), .. }) - } + DirectConstArgContext::GCA_MACRO + }; + self.can_lower_expr_to_const_arg_direct(body, context).is_ok() }; if self.tcx.features().gca_min_const_items() && let Some(body) = body @@ -2657,13 +2651,25 @@ impl<'hir> LoweringContext<'_, 'hir> { } } + fn direct_const_arg_context_enabled_by_gca_macro(&self) -> DirectConstArgContext { + let mut result = DirectConstArgContext::GCA_BASE_FEATURES; + if self.tcx.features().gca_min_const_items() { + result |= DirectConstArgContext::GCA_MIN_CONST_ITEMS; + } + if self.tcx.features().gca_adts() { + result |= DirectConstArgContext::GCA_ADTS; + } + result + } + + /// Only valid for const *arg* contexts, not const *item* contexts. fn ambient_direct_const_arg_context(&self) -> DirectConstArgContext { if self.tcx.features().gca_macroless_args() { - DirectConstArgContext::MacrolessMinGenericConstArgs - } else if self.tcx.features().gca_min_const_items() { - DirectConstArgContext::MinGenericConstArgs + self.direct_const_arg_context_enabled_by_gca_macro() + } else if self.tcx.features().gca() { + DirectConstArgContext::GCA } else { - DirectConstArgContext::Stable + DirectConstArgContext::STABLE } } @@ -2675,9 +2681,16 @@ impl<'hir> LoweringContext<'_, 'hir> { res: Option>, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - if let DirectConstArgContext::MacrolessMinGenericConstArgs = context { + if context.contains(DirectConstArgContext::PATH_ANY) { + Ok(()) + } else if context.contains(DirectConstArgContext::PATH_CONST_CTOR) + && matches!(res, Some(Res::Def(DefKind::Ctor(_, CtorKind::Const), _))) + { + // FIXME(gca_adts): This check is incomplete. Type-relative paths and other complicating + // factors make things very difficult - e.g. `>::None` Ok(()) - } else if qself.is_none() + } else if context.contains(DirectConstArgContext::PATH_PLAIN_PARAM) + && qself.is_none() && path.is_single_argless_ident() && matches!(res, Some(Res::Def(DefKind::ConstParam, _))) { @@ -2693,59 +2706,61 @@ impl<'hir> LoweringContext<'_, 'hir> { expr: &Expr, context: DirectConstArgContext, ) -> Result<(), UnrepresentableConstArgError> { - use DirectConstArgContext::*; // Note the only stable case is currently ExprKind::Path - match (&expr.kind, context) { - ( - ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args), - MacrolessMinGenericConstArgs, - ) => { + match &expr.kind { + ExprKind::Call(Expr { kind: ExprKind::Path(_, _), .. }, args) + if context.contains(DirectConstArgContext::TUPLE_CALL) => + { for arg in args { self.can_lower_expr_to_const_arg_direct(arg, context)?; } Ok(()) } - (ExprKind::Tup(exprs), MacrolessMinGenericConstArgs) => { + ExprKind::Tup(exprs) if context.contains(DirectConstArgContext::TUPLE) => { for expr in exprs { self.can_lower_expr_to_const_arg_direct(expr, context)?; } Ok(()) } - (ExprKind::Path(qself, path), _) => { + ExprKind::Path(qself, path) => { let res = self.get_partial_res(expr.id).and_then(|partial_res| partial_res.full_res()); self.can_lower_path_to_const_arg_direct(qself, path, expr.span, res, context) } - (ExprKind::Struct(se), MacrolessMinGenericConstArgs) => { + ExprKind::Struct(se) if context.contains(DirectConstArgContext::STRUCT) => { for f in &se.fields { self.can_lower_expr_to_const_arg_direct(&f.expr, context)?; } Ok(()) } - (ExprKind::Array(elements), MacrolessMinGenericConstArgs) => { + ExprKind::Array(elements) if context.contains(DirectConstArgContext::ARRAY) => { for element in elements { self.can_lower_expr_to_const_arg_direct(element, context)?; } Ok(()) } - (ExprKind::Underscore, MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Paren(expr), MacrolessMinGenericConstArgs) => { + ExprKind::Underscore if context.contains(DirectConstArgContext::UNDERSCORE) => Ok(()), + ExprKind::Paren(expr) if context.contains(DirectConstArgContext::PAREN) => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Block(block, _), MacrolessMinGenericConstArgs) - if let [stmt] = block.stmts.as_slice() + ExprKind::Block(block, _) + if context.contains(DirectConstArgContext::BLOCK) + && let [stmt] = block.stmts.as_slice() && let StmtKind::Expr(expr) = &stmt.kind => { self.can_lower_expr_to_const_arg_direct(expr, context) } - (ExprKind::Lit(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::Unary(UnOp::Neg, inner_expr), MacrolessMinGenericConstArgs) - if let ExprKind::Lit(_) = &inner_expr.kind => + ExprKind::Lit(_) if context.contains(DirectConstArgContext::LIT) => Ok(()), + ExprKind::Unary(UnOp::Neg, inner_expr) + if context.contains(DirectConstArgContext::LIT) + && let ExprKind::Lit(_) = &inner_expr.kind => { Ok(()) } - (ExprKind::ConstBlock(_), MacrolessMinGenericConstArgs) => Ok(()), - (ExprKind::GcaMacro(_), MacrolessMinGenericConstArgs | MinGenericConstArgs) => { + ExprKind::ConstBlock(_) if context.contains(DirectConstArgContext::CONST_BLOCK) => { + Ok(()) + } + ExprKind::GcaMacro(_) if context.contains(DirectConstArgContext::GCA_MACRO) => { // Always report this as able to be represented directly. If it turns out not to be, // `lower_expr_to_const_arg_direct` will report an error. Ok(()) @@ -2931,11 +2946,9 @@ impl<'hir> LoweringContext<'_, 'hir> { // `can_lower_expr_to_const_arg_direct` always returns success upon encountering a // ExprKind::GcaMacro, which effectively forces the expression to be lowered as a // direct arg. If it actually turns out to not be possible, emit an error instead. - // Always use MacrolessMinGenericConstArgs, even if we're under regular GCA, because - // that's what the macro means: to enter a context that is like macroless GCA. match self.can_lower_expr_to_const_arg_direct( expr, - DirectConstArgContext::MacrolessMinGenericConstArgs, + self.direct_const_arg_context_enabled_by_gca_macro(), ) { Ok(()) => self.lower_expr_to_const_arg_direct(expr, id_override), Err(err) => err.emit(self), @@ -3277,19 +3290,53 @@ impl<'hir> GenericArgsCtor<'hir> { } } -#[derive(Copy, Clone, Debug)] -enum DirectConstArgContext { +bitflags::bitflags! { + #[derive(Copy, Clone, Debug)] + struct DirectConstArgContext: u16 { + const TUPLE_CALL = 1 << 0; + const TUPLE = 1 << 1; + const PATH_PLAIN_PARAM = 1 << 2; + const PATH_CONST_CTOR = 1 << 3; + const PATH_ANY = 1 << 4; + const STRUCT = 1 << 5; + const ARRAY = 1 << 6; + const UNDERSCORE = 1 << 7; + const PAREN = 1 << 8; + const BLOCK = 1 << 9; + const LIT = 1 << 10; + const CONST_BLOCK = 1 << 11; + const GCA_MACRO = 1 << 12; + } +} + +impl DirectConstArgContext { /// The only allowed direct const arg representation is simple paths that nameres to generic /// const parameters. - Stable, + const STABLE: DirectConstArgContext = Self::PATH_PLAIN_PARAM; + /// The allowed representations are what is allowed on stable, plus the `gca!` macro. - MinGenericConstArgs, - /// Expressions attempt to be lowered directly, and if that fails, the expression falls back to - /// being represented as an anon const. + const GCA: DirectConstArgContext = Self::STABLE.union(Self::GCA_MACRO); + + /// These expressions are allowed inside the `gca!` macro, regardless of what feature is + /// enabling the base `gca!` functionality. /// - /// This context is also used under MinGenericConstArgs inside a `gca!` macro, for - /// simplicity, as they allow the same code. - MacrolessMinGenericConstArgs, + /// These are also allowed under macroless features without a `gca!` macro. + const GCA_BASE_FEATURES: DirectConstArgContext = Self::GCA + .union(DirectConstArgContext::UNDERSCORE) + .union(DirectConstArgContext::PAREN) + .union(DirectConstArgContext::BLOCK) + .union(DirectConstArgContext::LIT) + .union(DirectConstArgContext::CONST_BLOCK); + + /// These are allowed under `#![feature(gca_min_const_items)]` + const GCA_MIN_CONST_ITEMS: DirectConstArgContext = DirectConstArgContext::PATH_ANY; + + /// These are allowed under `#![feature(gca_adts)]` + const GCA_ADTS: DirectConstArgContext = DirectConstArgContext::PATH_CONST_CTOR + .union(DirectConstArgContext::TUPLE_CALL) + .union(DirectConstArgContext::TUPLE) + .union(DirectConstArgContext::STRUCT) + .union(DirectConstArgContext::ARRAY); } #[derive(Debug)] diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs index 9d0ca67ce93d5..bbc80f6a5728d 100644 --- a/compiler/rustc_ast_passes/src/feature_gate.rs +++ b/compiler/rustc_ast_passes/src/feature_gate.rs @@ -3,7 +3,7 @@ use rustc_ast::{self as ast, AttrVec, GenericBound, NodeId, PatKind, attr, token use rustc_attr_ir::{Attribute, AttributeKind}; use rustc_attr_parsing::AttributeParser; use rustc_errors::msg; -use rustc_feature::Features; +use rustc_feature::{DependentFeature, Features}; use rustc_session::Session; use rustc_session::diagnostics::{feature_err, feature_warn}; use rustc_span::{Span, Spanned, sym}; @@ -651,26 +651,47 @@ fn check_incompatible_features(sess: &Session, features: &Features) { } fn check_dependent_features(sess: &Session, features: &Features) { - for &(parent, children) in - rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, _)| features.enabled(*parent)) + for &(parent, ref children) in + rustc_feature::DEPENDENT_FEATURES.iter().filter(|(parent, children)| { + features.enabled(*parent) && !check_enabled(features, children) + }) { - if children.iter().any(|f| !features.enabled(*f)) { - let parent_span = features - .enabled_features_iter_stable_order() - .find_map(|(name, span)| (name == parent).then_some(span)) - .unwrap(); - // FIXME: should probably format this in fluent instead of here - let missing = children + let parent_span = features + .enabled_features_iter_stable_order() + .find_map(|(name, span)| (name == parent).then_some(span)) + .unwrap(); + // FIXME: should probably format this in fluent instead of here + let missing = format(features, &children); + sess.dcx().emit_err(diagnostics::MissingDependentFeatures { parent_span, parent, missing }); + } + + fn check_enabled(features: &Features, feature: &DependentFeature) -> bool { + match feature { + DependentFeature::And(children) => { + children.iter().all(|child| check_enabled(features, child)) + } + DependentFeature::Or(children) => { + children.iter().any(|child| check_enabled(features, child)) + } + DependentFeature::Leaf(symbol) => features.enabled(*symbol), + } + } + + fn format(features: &Features, feature: &DependentFeature) -> String { + // FIXME: parentheses/precedence + match feature { + DependentFeature::And(children) => children .iter() - .filter(|f| !features.enabled(**f)) - .map(|s| format!("`{}`", s.as_str())) - .intersperse(String::from(", ")) - .collect(); - sess.dcx().emit_err(diagnostics::MissingDependentFeatures { - parent_span, - parent, - missing, - }); + .filter(|child| !check_enabled(features, child)) + .map(|child| format(features, child)) + .intersperse(String::from(" and ")) + .collect(), + DependentFeature::Or(children) => children + .iter() + .map(|child| format(features, child)) + .intersperse(String::from(" or ")) + .collect(), + DependentFeature::Leaf(symbol) => format!("`{}`", symbol.as_str()), } } } diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs index 5b9b899fc463f..83bf4f47a8ac9 100644 --- a/compiler/rustc_feature/src/lib.rs +++ b/compiler/rustc_feature/src/lib.rs @@ -133,6 +133,6 @@ pub use builtin_attrs::{ }; pub use removed::REMOVED_LANG_FEATURES; pub use unstable::{ - DEPENDENT_FEATURES, EnabledLangFeature, EnabledLibFeature, Features, INCOMPATIBLE_FEATURES, - TRACK_FEATURE, UNSTABLE_LANG_FEATURES, + DEPENDENT_FEATURES, DependentFeature, EnabledLangFeature, EnabledLibFeature, Features, + INCOMPATIBLE_FEATURES, TRACK_FEATURE, UNSTABLE_LANG_FEATURES, }; diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs index 49489c0ed903d..71ab8250254f4 100644 --- a/compiler/rustc_feature/src/unstable.rs +++ b/compiler/rustc_feature/src/unstable.rs @@ -119,6 +119,13 @@ impl Features { false } } + + /// The generic_const_args family of features has a set of common behavior that can be enabled + /// by either `gca_min_const_items` or `gca_adts`. There is no actual `gca` base feature, but + /// this method acts as one. + pub fn gca(&self) -> bool { + self.gca_min_const_items() || self.gca_adts() + } } macro_rules! declare_features { @@ -546,6 +553,8 @@ declare_features! ( (internal, freeze_impls, "1.78.0", Some(121675)), /// Frontmatter `---` blocks for use by external tools. (unstable, frontmatter, "1.88.0", Some(136889)), + /// Allows using ADTs in directly represented generic const args. + (incomplete, gca_adts, "CURRENT_RUSTC_VERSION", Some(163420)), /// Allows using generics in more complex const expressions, based on definitional equality. (incomplete, gca_const_items, "1.95.0", Some(151972)), /// Allows directly represented gca_const_items without the `gca!` macro. @@ -857,10 +866,25 @@ pub const INCOMPATIBLE_FEATURES: &[(Symbol, Symbol)] = &[ (sym::ref_pat_eat_one_layer_2024, sym::ref_pat_eat_one_layer_2024_structural), ]; +pub enum DependentFeature { + And(&'static [DependentFeature]), + Or(&'static [DependentFeature]), + Leaf(Symbol), +} + /// Some features require one or more other features to be enabled. -pub const DEPENDENT_FEATURES: &[(Symbol, &[Symbol])] = &[ - (sym::gca_const_items, &[sym::gca_min_const_items]), - (sym::gca_macroless_args, &[sym::gca_min_const_items]), - (sym::gca_macroless_items, &[sym::gca_min_const_items]), - (sym::unsized_const_params, &[sym::adt_const_params]), +pub const DEPENDENT_FEATURES: &[(Symbol, DependentFeature)] = &[ + // tidy-alphabetical-start + ( + sym::gca_adts, + DependentFeature::Or(&[ + DependentFeature::Leaf(sym::min_adt_const_params), + DependentFeature::Leaf(sym::adt_const_params), + ]), + ), + (sym::gca_const_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_args, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::gca_macroless_items, DependentFeature::Leaf(sym::gca_min_const_items)), + (sym::unsized_const_params, DependentFeature::Leaf(sym::adt_const_params)), + // tidy-alphabetical-end ]; diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs index c3cc3bcd6cd0c..9504fce939733 100644 --- a/compiler/rustc_hir_analysis/src/collect.rs +++ b/compiler/rustc_hir_analysis/src/collect.rs @@ -1803,7 +1803,7 @@ fn anon_const_kind<'tcx>(tcx: TyCtxt<'tcx>, def: LocalDefId) -> ty::AnonConstKin debug_assert_matches!(const_arg.kind, hir::ConstArgKind::Anon(hir::AnonConst { def_id, .. }) if *def_id == def); if tcx.features().generic_const_exprs() { ty::AnonConstKind::GCE - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { ty::AnonConstKind::MCG } else if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::Repeat(_, repeat_count), diff --git a/compiler/rustc_hir_analysis/src/collect/generics_of.rs b/compiler/rustc_hir_analysis/src/collect/generics_of.rs index 9605c777e55a9..4d43a9ca5700e 100644 --- a/compiler/rustc_hir_analysis/src/collect/generics_of.rs +++ b/compiler/rustc_hir_analysis/src/collect/generics_of.rs @@ -224,7 +224,7 @@ pub(super) fn generics_of(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::Generics { // Node::AnonConst, or whether it will be represented directly, so it must generate a // DefId. If it ends up being direct, this DefId is then attached to the top-level // ConstArg, which is what we are seeing here. - debug_assert!(tcx.features().gca_min_const_items()); + debug_assert!(tcx.features().gca()); // Forward to the real parent. Some(tcx.local_parent(def_id)) } diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index bee062b27e0f5..1538b3afaf236 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -370,7 +370,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { && let Some(hir_ty) = constraint.ty() && let ty = self.lower_ty(hir_ty) && (ty.is_enum() || ty.references_error()) - && tcx.features().gca_min_const_items() + && tcx.features().gca() { Some(diagnostics::AssocKindMismatchWrapInBracesSugg { lo: hir_ty.span.shrink_to_lo(), diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index e9dc2a61d698d..037996fc926b2 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -3120,7 +3120,7 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { }) } - /// `def_id` is a const item used in the type system. Checks if that's OK. + /// `alias_const` is a const item used in the type system. Checks if that's OK. fn check_const_item_in_type_system( &self, alias_const: ty::AliasConstKind<'tcx>, diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 2ea2f52c696ba..bf1feb2ae5172 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1327,18 +1327,19 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { enable_feature: self.tcx().sess.is_nightly_build(), }) } - ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => { - self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { - span, - name, - param_kind: is_type, - help: self.tcx.sess.is_nightly_build() - && !self.tcx.features().gca_min_const_items(), - is_gca, - help_gca: is_gca, - help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca, - }) - } + ResolutionError::ParamInNonTrivialAnonConst { + is_gca_const_items, + name, + param_kind, + } => self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst { + span, + name, + param_kind, + help: self.tcx.sess.is_nightly_build() && !self.tcx.features().gca(), + is_gca_const_items, + help_gca: is_gca_const_items, + help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca_const_items, + }), ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => { self.dcx().create_err(diagnostics::ParamInEnumDiscriminant { span, diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index ae4f7cabbe87f..c0e687fc94a38 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -409,7 +409,7 @@ pub(crate) struct SelfInConstGenericTy { #[derive(Diagnostic)] #[diag( - "{$is_gca -> + "{$is_gca_const_items -> [true] generic parameters in const blocks are not allowed; use a named `const` item instead *[false] generic parameters may not be used in const operations }" @@ -423,7 +423,7 @@ pub(crate) struct ParamInNonTrivialAnonConst { pub(crate) param_kind: ParamKindInNonTrivialAnonConst, #[help("add `#![feature(generic_const_exprs)]` to allow generic const expressions")] pub(crate) help: bool, - pub(crate) is_gca: bool, + pub(crate) is_gca_const_items: bool, #[help( "consider factoring the expression into a `type const` item and use it as the const argument instead" )] diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs index d743093aae92f..138bb4bd72ab0 100644 --- a/compiler/rustc_resolve/src/ident.rs +++ b/compiler/rustc_resolve/src/ident.rs @@ -1658,7 +1658,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Type, } @@ -1750,7 +1750,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } NoConstantGenericsReason::NonTrivialConstArg => { ResolutionError::ParamInNonTrivialAnonConst { - is_gca: self.features.gca_const_items(), + is_gca_const_items: self.features.gca_const_items(), name: rib_ident.name, param_kind: ParamKindInNonTrivialAnonConst::Const { name: rib_ident.name, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..ebb041bf3878d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5232,7 +5232,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { AnonConstKind::InlineConst => ConstantHasGenerics::Yes, AnonConstKind::ConstArg(_) | AnonConstKind::ArrayLength => { if self.r.features.generic_const_exprs() - || self.r.features.gca_min_const_items() + || self.r.features.gca() || is_trivial_const_arg { ConstantHasGenerics::Yes diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 84c07d0fb0f44..6a4bc7470038d 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -4163,9 +4163,8 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { span: lifetime_ref.ident.span, name: lifetime_ref.ident.name, param_kind: diagnostics::ParamKindInNonTrivialAnonConst::Lifetime, - help: self.r.tcx.sess.is_nightly_build() - && !self.r.features.gca_min_const_items(), - is_gca: self.r.features.gca_const_items(), + help: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca(), + is_gca_const_items: self.r.features.gca_const_items(), help_gca: self.r.features.gca_const_items(), help_suggest_gca: self.r.tcx.sess.is_nightly_build() && !self.r.features.gca_const_items(), diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0a96becf993e9..b62ad9a708c29 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -304,7 +304,7 @@ enum ResolutionError<'ra> { /// /// This error is only emitted when using `min_const_generics`. ParamInNonTrivialAnonConst { - is_gca: bool, + is_gca_const_items: bool, name: Symbol, param_kind: ParamKindInNonTrivialAnonConst, }, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index e62ad42875248..68e7ee914f483 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -1067,6 +1067,7 @@ symbols! { future_trait, fxsr, gca, + gca_adts, gca_const_items, gca_macroless_args, gca_macroless_items, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 63b0733b0a095..e751c87d37007 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -3984,8 +3984,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { obligation: &PredicateObligation<'tcx>, span: Span, ) -> Result, ErrorGuaranteed> { - if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca_min_const_items() - { + if !self.tcx.features().generic_const_exprs() && !self.tcx.features().gca() { let guar = self .dcx() .struct_span_err(span, "constant expression depends on a generic parameter") diff --git a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs index 9acc0682e6641..242aa260b8372 100644 --- a/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs +++ b/compiler/rustc_trait_selection/src/traits/const_evaluatable.rs @@ -84,7 +84,7 @@ pub fn is_const_evaluatable<'tcx>( } _ => bug!("unexpected constkind in `is_const_evalautable: {unexpanded_ct:?}`"), } - } else if tcx.features().gca_min_const_items() { + } else if tcx.features().gca() { // This is a sanity check to make sure that non-generics consts are checked to // be evaluatable in case they aren't cchecked elsewhere. This will NOT error // if the const uses generics, as desired. diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs index 955ab1799a794..ba463184a41f8 100644 --- a/compiler/rustc_trait_selection/src/traits/wf.rs +++ b/compiler/rustc_trait_selection/src/traits/wf.rs @@ -1169,7 +1169,7 @@ impl<'a, 'tcx> TypeVisitor> for WfPredicates<'a, 'tcx> { } ty::ConstKind::Value(val) => { // FIXME(mgca): no need to feature-gate once valtree lifetimes are not erased - if tcx.features().gca_min_const_items() { + if tcx.features().gca() { match val.ty.kind() { ty::Adt(adt_def, args) => { let adt_val = val.destructure_adt_const(); diff --git a/compiler/rustc_type_ir/src/const_kind.rs b/compiler/rustc_type_ir/src/const_kind.rs index d969cca3dcda2..1ef498f072f22 100644 --- a/compiler/rustc_type_ir/src/const_kind.rs +++ b/compiler/rustc_type_ir/src/const_kind.rs @@ -280,9 +280,6 @@ pub enum AnonConstKind { /// `feature(generic_const_exprs)` anon consts are allowed to use arbitrary generic parameters in scope GCE, /// stable `min_const_generics` anon consts are not allowed to use any generic parameters - /// - /// under `feature(gca_min_const_items)`, these may be inline consts as well, and should be - /// treated the same as anon consts. MCG, /// anon consts used as the length of a repeat expr are syntactically allowed to use generic parameters /// but must not depend on the actual instantiation. See #76200 for more information diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs index 514c2aa1c9bd1..d1a68412247ef 100644 --- a/library/core/src/marker.rs +++ b/library/core/src/marker.rs @@ -1074,13 +1074,20 @@ pub const trait Destruct: PointeeSized {} #[rustc_dyn_incompatible_trait] pub trait Tuple {} +// HACK(khyperia): if this is missing, the gca macro's `implied_by = "gca_adts"` emits an error +#[unstable(feature = "gca_adts", issue = "163420")] +#[expect(dead_code)] +struct HackGcaAdtsFeature; + /// Creates a new style directly represented const argument. /// ```ignore (cannot test this from within core yet) /// const BAR: usize = gca!(N); /// const FOO: usize = gca!(BAR::); /// ``` #[rustc_builtin_macro(gca)] -#[unstable(feature = "gca_min_const_items", issue = "132980")] +// HACK: abuse implied_by, this should be enabled if gca_min_const_items or gca_adts is enabled, +// neither one is more particularly special than the other +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] #[macro_export] macro_rules! gca { ($($arg:tt)*) => { diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index f716f49ffd60a..6d579f0cb9601 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -758,7 +758,7 @@ pub use core::concat_bytes; )] #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; -#[unstable(feature = "gca_min_const_items", issue = "132980")] +#[unstable(feature = "gca_min_const_items", issue = "132980", implied_by = "gca_adts")] pub use core::gca; #[stable(feature = "matches_macro", since = "1.42.0")] pub use core::matches; diff --git a/src/doc/unstable-book/src/language-features/gca-adts.md b/src/doc/unstable-book/src/language-features/gca-adts.md new file mode 100644 index 0000000000000..49905d57a9a4c --- /dev/null +++ b/src/doc/unstable-book/src/language-features/gca-adts.md @@ -0,0 +1,21 @@ +# gca_adts + +Enables ADTs under the generic const args family of features (e.g. `gca!` macro). + +The tracking issue for this feature is: [#163420] + +[#163420]: https://github.com/rust-lang/rust/issues/163420 + +## Examples + +```rust +#![feature(gca_min_const_items, min_adt_const_params, gca_adts)] + +use std::gca; + +struct S; + +fn main() { + let _: S = S::; +} +``` diff --git a/src/doc/unstable-book/src/language-features/gca-min-const-items.md b/src/doc/unstable-book/src/language-features/gca-min-const-items.md index 4027e782714ed..486db1f50885b 100644 --- a/src/doc/unstable-book/src/language-features/gca-min-const-items.md +++ b/src/doc/unstable-book/src/language-features/gca-min-const-items.md @@ -1,6 +1,6 @@ # gca_min_const_items -Enables the generic const args MVP (paths to direct const items and constructors for ADTs and primitives). +Enables the generic const args MVP (paths to direct const items and primitives). The tracking issue for this feature is: [#132980] diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs index 7600c4882a91c..b4bfdb494a863 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.rs @@ -1,10 +1,13 @@ //@ compile-flags: -Znext-solver=globally -#![allow(incomplete_features)] -#![feature(gca_macroless_args)] -#![feature(gca_macroless_items)] -#![feature(gca_const_items, gca_min_const_items)] -#![feature(min_adt_const_params)] +#![feature( + gca_adts, + gca_const_items, + gca_macroless_args, + gca_macroless_items, + gca_min_const_items, + min_adt_const_params +)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr index 9dd229cc46a34..42d1d8b5fd1d7 100644 --- a/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr +++ b/tests/ui/const-generics/gca/const-pattern-field-type-mismatch-162394.stderr @@ -1,5 +1,5 @@ error: the constant `"foo"` is not of type `()` - --> $DIR/const-pattern-field-type-mismatch-162394.rs:17:5 + --> $DIR/const-pattern-field-type-mismatch-162394.rs:20:5 | LL | const A2: Foo = Self::FooA("foo"); | ^^^^^^^^^^^^^ expected `()`, found `&'static str` diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.rs b/tests/ui/const-generics/gca/gca-macro-fn-call.rs index 6035c14e5eb75..73945b14af4b9 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.rs +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.rs @@ -13,10 +13,14 @@ //! tuple-variant constructor (unions, primitives, foreign types), not just structs. //@ compile-flags: -Znext-solver -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(gca_const_items)] -#![feature(extern_types)] -#![expect(incomplete_features)] +#![feature( + extern_types, + gca_adts, + gca_const_items, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params +)] struct FieldName([u8; N]); diff --git a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr index 1399bcb1dee92..4b7bf15ace96d 100644 --- a/tests/ui/const-generics/gca/gca-macro-fn-call.stderr +++ b/tests/ui/const-generics/gca/gca-macro-fn-call.stderr @@ -1,29 +1,29 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:35:23 + --> $DIR/gca-macro-fn-call.rs:39:23 | LL | fn bad(_: FieldName<{ FieldName::len() }>) {} | ^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:44:31 + --> $DIR/gca-macro-fn-call.rs:48:31 | LL | fn bad_tracing(_: FieldName<{ FieldName::len_of("id") }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:61:23 + --> $DIR/gca-macro-fn-call.rs:65:23 | LL | fn bad_union(_: Tag<{ Tag::width() }>) {} | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:70:28 + --> $DIR/gca-macro-fn-call.rs:74:28 | LL | fn bad_prim(_: FieldName<{ u32::from_str_radix("10", 10) }>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/gca-macro-fn-call.rs:81:31 + --> $DIR/gca-macro-fn-call.rs:85:31 | LL | fn bad_foreign(_: FieldName<{ Opaque::foo() }>) {} | ^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.rs b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs new file mode 100644 index 0000000000000..55a6338dadb64 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.rs @@ -0,0 +1,3 @@ +#![feature(gca_adts)] +//~^ ERROR `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled +fn main() {} diff --git a/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr new file mode 100644 index 0000000000000..19c96d5d7bd9e --- /dev/null +++ b/tests/ui/const-generics/gca_adts/missing-dependent-features.stderr @@ -0,0 +1,10 @@ +error: `gca_adts` requires `min_adt_const_params` or `adt_const_params` to be enabled + --> $DIR/missing-dependent-features.rs:1:12 + | +LL | #![feature(gca_adts)] + | ^^^^^^^^ + | + = help: enable all of these features + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.rs b/tests/ui/const-generics/gca_adts/none-incomplete.rs new file mode 100644 index 0000000000000..76078a42fa08a --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.rs @@ -0,0 +1,21 @@ +//! This test file ought to be part of `none.rs`, but, type-relative paths are difficult + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct::MyNone)>; + //~^ ERROR complex const arguments must be placed inside of a `const` block +} diff --git a/tests/ui/const-generics/gca_adts/none-incomplete.stderr b/tests/ui/const-generics/gca_adts/none-incomplete.stderr new file mode 100644 index 0000000000000..bf8c538207579 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none-incomplete.stderr @@ -0,0 +1,8 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/none-incomplete.rs:19:24 + | +LL | let _: Struct::MyNone)>; + | ^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + diff --git a/tests/ui/const-generics/gca_adts/none.rs b/tests/ui/const-generics/gca_adts/none.rs new file mode 100644 index 0000000000000..223f01d81a5a8 --- /dev/null +++ b/tests/ui/const-generics/gca_adts/none.rs @@ -0,0 +1,21 @@ +//@check-pass + +#![feature(gca_adts, adt_const_params)] + +use std::gca; +use std::marker::ConstParamTy; + +#[derive(ConstParamTy, PartialEq, Eq)] +enum MyOption { + MySome, + MyNone, +} + +use MyOption::*; + +struct Struct; + +fn main() { + let _: Struct; + let _: Struct; +} diff --git a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs index b4fe7a9a5da2a..0053db1608ea4 100644 --- a/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs +++ b/tests/ui/const-generics/generic_const_parameter_types/inherent-type-const.rs @@ -3,11 +3,12 @@ //@[next] compile-flags: -Znext-solver //@ ignore-compare-mode-next-solver (explicit revisions) #![feature( + const_param_ty_trait, + gca_adts, gca_min_const_items, generic_const_parameter_types, inherent_associated_types, - min_adt_const_params, - const_param_ty_trait + min_adt_const_params )] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs index 112cf5563a59e..cd90cc6f66b99 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr index 96f8461b9cb82..70ed0cbc41f64 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_arg_simple.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/adt_expr_arg_simple.rs:31:35 + --> $DIR/adt_expr_arg_simple.rs:30:35 | LL | foo::<{ gca!(Some:: { 0: N + 1 }) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/adt_expr_arg_simple.rs:36:38 + --> $DIR/adt_expr_arg_simple.rs:35:38 | LL | foo::<{ Some:: { 0: const { N + 1 } } }>(); | ^ diff --git a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs index c488b90aec14b..c9652b1c83385 100644 --- a/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs +++ b/tests/ui/const-generics/mgca/adt_expr_arg_tuple_expr_fail.rs @@ -1,10 +1,10 @@ #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs index 20bac03fab1c0..5bcfea9246066 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.rs @@ -1,26 +1,27 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![crate_type = "lib"] // Miscellaneous assortment of invalid cases of directly represented // `ConstArgKind::Struct`'s under mgca. #[derive(Eq, PartialEq, std::marker::ConstParamTy)] -struct Foo { field: T } +struct Foo { + field: T, +} fn NonStruct() {} fn accepts>() {} fn bar() { - accepts::<{ Foo:: { }}>(); + accepts::<{ Foo:: {} }>(); //~^ ERROR: struct expression with missing field initialiser for `field` - accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); + accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); //~^ ERROR: struct expression with multiple initialisers for `field` - accepts::<{ Fooo:: { field: const { 1 } }}>(); + accepts::<{ Fooo:: { field: const { 1 } } }>(); //~^ ERROR: cannot find struct, variant or union type `Fooo` in this scope //~| ERROR: struct expression with invalid base path - accepts::<{ NonStruct { }}>(); + accepts::<{ NonStruct {} }>(); //~^ ERROR: cannot find struct, variant or union type `NonStruct` in this scope //~| ERROR: struct expression with invalid base path } diff --git a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr index 370a73b5a4bc6..707cfa1b73b31 100644 --- a/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_erroneuous_inits.stderr @@ -1,51 +1,51 @@ error[E0422]: cannot find struct, variant or union type `Fooo` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^ not found in this scope | note: similarly named struct `Foo` defined here - --> $DIR/adt_expr_erroneuous_inits.rs:9:1 + --> $DIR/adt_expr_erroneuous_inits.rs:8:1 | -LL | struct Foo { field: T } +LL | struct Foo { | ^^^^^^^^^^^^^ help: a struct with a similar name exists | -LL - accepts::<{ Fooo:: { field: const { 1 } }}>(); -LL + accepts::<{ Foo:: { field: const { 1 } }}>(); +LL - accepts::<{ Fooo:: { field: const { 1 } } }>(); +LL + accepts::<{ Foo:: { field: const { 1 } } }>(); | error[E0574]: cannot find struct, variant or union type `NonStruct` in this scope - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); +LL | accepts::<{ NonStruct {} }>(); | ^^^^^^^^^ not found in this scope | = note: a function named `NonStruct` exists in another namespace error: struct expression with missing field initialiser for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:16:17 + --> $DIR/adt_expr_erroneuous_inits.rs:17:17 | -LL | accepts::<{ Foo:: { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: {} }>(); + | ^^^^^^^^^^^^ error: struct expression with multiple initialisers for `field` - --> $DIR/adt_expr_erroneuous_inits.rs:18:49 + --> $DIR/adt_expr_erroneuous_inits.rs:19:49 | -LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2} }}>(); - | ^^^^^^^^^^^^^^^^^ +LL | accepts::<{ Foo:: { field: const { 1 }, field: const { 2 } } }>(); + | ^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:20:17 + --> $DIR/adt_expr_erroneuous_inits.rs:21:17 | -LL | accepts::<{ Fooo:: { field: const { 1 } }}>(); +LL | accepts::<{ Fooo:: { field: const { 1 } } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: struct expression with invalid base path - --> $DIR/adt_expr_erroneuous_inits.rs:23:17 + --> $DIR/adt_expr_erroneuous_inits.rs:24:17 | -LL | accepts::<{ NonStruct { }}>(); - | ^^^^^^^^^^^^^ +LL | accepts::<{ NonStruct {} }>(); + | ^^^^^^^^^^^^ error: aborting due to 6 previous errors diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs index 38eb04760c598..f4b59aaa1404e 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct S1 { diff --git a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr index 81f7c5366b461..dea156db19c14 100644 --- a/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_fields_type_check.stderr @@ -1,41 +1,41 @@ error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:24:19 + --> $DIR/adt_expr_fields_type_check.rs:23:19 | LL | accepts_1::<{ S1:: { f1: N, f2: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `isize` - --> $DIR/adt_expr_fields_type_check.rs:27:19 + --> $DIR/adt_expr_fields_type_check.rs:26:19 | LL | accepts_2::<{ S2::(N, N) }>(); | ^^^^^^^^^^^^^^ expected `isize`, found `bool` error: the constant `N` is not of type `u8` - --> $DIR/adt_expr_fields_type_check.rs:30:19 + --> $DIR/adt_expr_fields_type_check.rs:29:19 | LL | accepts_3::<{ En::Var1::(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^ expected `u8`, found `bool` error: the constant `N` is not of type `i64` - --> $DIR/adt_expr_fields_type_check.rs:32:19 + --> $DIR/adt_expr_fields_type_check.rs:31:19 | LL | accepts_3::<{ En::Var2:: { field: N } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i64`, found `bool` error[E0308]: mismatched types - --> $DIR/adt_expr_fields_type_check.rs:34:51 + --> $DIR/adt_expr_fields_type_check.rs:33:51 | LL | accepts_3::<{ En::Var2:: { field: const { false } } }>(); | ^^^^^ expected `i64`, found `bool` diff --git a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs index 30b8ca3dd2752..13feedadbcfd7 100644 --- a/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs +++ b/tests/ui/const-generics/mgca/adt_expr_infers_from_value.rs @@ -1,14 +1,14 @@ //@ check-pass #![feature( - generic_const_items, - gca_min_const_items, - gca_macroless_args, adt_const_params, - generic_const_parameter_types, - const_param_ty_trait + const_param_ty_trait, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_items, + generic_const_parameter_types )] -#![expect(incomplete_features)] use std::gca; use std::marker::{ConstParamTy, ConstParamTy_, PhantomData}; diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs index d48b5cb9e7100..7cc24d660d04c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.rs @@ -1,13 +1,13 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] enum E { - S {} + S {}, } fn foo() {} fn main() { - foo::<{E::S { x: const { 1 } }}>(); - //~^ ERROR variant `E::S` has no field named `x` [E0559] + foo::<{ E::S { x: const { 1 } } }>(); + //~^ ERROR variant `E::S` has no field named `x` [E0559] } diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr index 7ac3b28cdca5b..8d201a2b8943c 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr +++ b/tests/ui/const-generics/mgca/adt_expr_unit_enum_extra_field.stderr @@ -1,8 +1,8 @@ error[E0559]: variant `E::S` has no field named `x` - --> $DIR/adt_expr_unit_enum_extra_field.rs:11:19 + --> $DIR/adt_expr_unit_enum_extra_field.rs:11:20 | -LL | foo::<{E::S { x: const { 1 } }}>(); - | ^ `E::S` does not have this field +LL | foo::<{ E::S { x: const { 1 } } }>(); + | ^ `E::S` does not have this field error: aborting due to 1 previous error diff --git a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs index 0eaadd1a9b31d..68a1600e218eb 100644 --- a/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs +++ b/tests/ui/const-generics/mgca/adt_expr_unit_struct_extra_field.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, std::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs index 134a82e9d3490..59587c0093295 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.rs @@ -2,9 +2,14 @@ //! //! Ensure that providing an array const arg with the wrong number of elements //! doesn't ICE or silently cause UB. -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(unsized_const_params, generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types, + unsized_const_params +)] use std::gca; use std::marker::ConstParamTy_; diff --git a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr index 72c2a367c7246..c0625e737d307 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-len-mismatch.stderr @@ -1,59 +1,59 @@ error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:31:11 + --> $DIR/array-const-arg-len-mismatch.rs:36:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b"\x00\x00\x00"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:33:11 + --> $DIR/array-const-arg-len-mismatch.rs:38:11 | LL | foo::(); | ^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/array-const-arg-len-mismatch.rs:12:42 + --> $DIR/array-const-arg-len-mismatch.rs:17:42 | LL | fn foo() -> [T; N] { | ^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `*b""` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:35:13 + --> $DIR/array-const-arg-len-mismatch.rs:40:13 | LL | bar::<{ [] }>(); | ^^ expected `[u8; 2]`, found `[u8; 0]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"\x01\x02\x03"` is not of type `[u8; 2]` - --> $DIR/array-const-arg-len-mismatch.rs:37:13 + --> $DIR/array-const-arg-len-mismatch.rs:42:13 | LL | bar::<{ [1, 2, 3] }>(); | ^^^^^^^^^ expected `[u8; 2]`, found `[u8; 3]` | note: required by a const generic parameter in `bar` - --> $DIR/array-const-arg-len-mismatch.rs:16:8 + --> $DIR/array-const-arg-len-mismatch.rs:21:8 | LL | fn bar() {} | ^^^^^^^^^^^^^^^^ required by this const generic parameter in `bar` error: the constant `*b"*"` is not of type `[u8; 3]` - --> $DIR/array-const-arg-len-mismatch.rs:39:13 + --> $DIR/array-const-arg-len-mismatch.rs:44:13 | LL | baz::<{ [42] }>(); | ^^^^ expected `[u8; 3]`, found `[u8; 1]` | note: required by a const generic parameter in `baz` - --> $DIR/array-const-arg-len-mismatch.rs:28:8 + --> $DIR/array-const-arg-len-mismatch.rs:33:8 | LL | fn baz::LEN]>() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `baz` diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs index def077e4d292d..a6d1acb773a23 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.rs @@ -1,5 +1,4 @@ -#![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] use std::marker::ConstParamTy; #[derive(Eq, PartialEq, ConstParamTy)] diff --git a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr index 573620366cbce..f8b9a3c9cee37 100644 --- a/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/array-const-arg-type-mismatch.stderr @@ -1,5 +1,5 @@ error: the constant `Bar` is not of type `Foo` - --> $DIR/array-const-arg-type-mismatch.rs:13:14 + --> $DIR/array-const-arg-type-mismatch.rs:12:14 | LL | test::<{ [Bar] }>(); | ^^^^^ expected `Foo`, found `Bar` diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr index 2e3b2172b7325..43a8312a21dbd 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r1.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:13:33 + --> $DIR/array-expr-complex.rs:12:33 | LL | takes_array::<{ gca!([1, 2, 1 + 2]) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr index 2b25efb6ab090..ed9e7d184c023 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r2.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:16:26 + --> $DIR/array-expr-complex.rs:15:26 | LL | takes_array::<{ gca!([X; 3]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr index 09515bafa7025..e67703aab474f 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr +++ b/tests/ui/const-generics/mgca/array-expr-complex.r3.stderr @@ -1,5 +1,5 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array-expr-complex.rs:19:26 + --> $DIR/array-expr-complex.rs:18:26 | LL | takes_array::<{ gca!([0; Y]) }>(); | ^^^^^^ diff --git a/tests/ui/const-generics/mgca/array-expr-complex.rs b/tests/ui/const-generics/mgca/array-expr-complex.rs index 1c96c492b3cfd..12104e5c5bd08 100644 --- a/tests/ui/const-generics/mgca/array-expr-complex.rs +++ b/tests/ui/const-generics/mgca/array-expr-complex.rs @@ -1,7 +1,6 @@ //@ revisions: r1 r2 r3 -#![expect(incomplete_features)] -#![feature(gca_min_const_items, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array-expr-simple.rs b/tests/ui/const-generics/mgca/array-expr-simple.rs index eba86898c41a1..d9436afb6015d 100644 --- a/tests/ui/const-generics/mgca/array-expr-simple.rs +++ b/tests/ui/const-generics/mgca/array-expr-simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array_u32() {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs index a7582258de2f5..fe1641ff38b2f 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.rs @@ -1,7 +1,5 @@ //! regression test for -#![feature(gca_min_const_items, gca_macroless_args)] -#![feature(adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] trait Trait1 {} trait Trait2 {} diff --git a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr index 169282547fc1d..f930849466eae 100644 --- a/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr +++ b/tests/ui/const-generics/mgca/array-expr-type-mismatch-in-where-bound.stderr @@ -1,11 +1,11 @@ error: expected `usize`, found const array - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:11:17 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:9:17 | LL | T: Trait1<{ [] }>, | ^^ error: type annotations needed for the literal - --> $DIR/array-expr-type-mismatch-in-where-bound.rs:17:15 + --> $DIR/array-expr-type-mismatch-in-where-bound.rs:15:15 | LL | T: Trait2<3>, | ^ diff --git a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs index 85ef64c498a4c..5b22ff101030b 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-assoc-const.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] fn takes_array() {} diff --git a/tests/ui/const-generics/mgca/array-expr-with-macro.rs b/tests/ui/const-generics/mgca/array-expr-with-macro.rs index db768339118f3..bf586b90a8e5a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-macro.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-macro.rs @@ -1,6 +1,5 @@ //@ run-pass -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] macro_rules! make_array { diff --git a/tests/ui/const-generics/mgca/array-expr-with-struct.rs b/tests/ui/const-generics/mgca/array-expr-with-struct.rs index 1d4c051e53f0b..bdc7b6009ea04 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-struct.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-struct.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs index f429ca20ce832..a4749c63f3a8a 100644 --- a/tests/ui/const-generics/mgca/array-expr-with-tuple.rs +++ b/tests/ui/const-generics/mgca/array-expr-with-tuple.rs @@ -1,11 +1,11 @@ //@ run-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] #![allow(dead_code)] fn takes_tuple() {} diff --git a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs index a4131a22337aa..624484c4d1467 100644 --- a/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs +++ b/tests/ui/const-generics/mgca/array-with-wrong-tuple-type.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs index aa6385c28ded0..7b5f3747f5a58 100644 --- a/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/array_elem_type_mismatch.rs @@ -1,10 +1,10 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_parameter_types, + gca_adts, + gca_macroless_args, gca_min_const_items, - gca_macroless_args + generic_const_parameter_types )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs index 7edeb25f30e48..308ba90d72646 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr index b044775b80c94..fd963a5055d0e 100644 --- a/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/array_expr_arg_complex.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:15:30 + --> $DIR/array_expr_arg_complex.rs:14:30 | LL | takes_array::<{ gca!([N, N + 1]) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/array_expr_arg_complex.rs:16:42 + --> $DIR/array_expr_arg_complex.rs:15:42 | LL | takes_tuple_with_array::<{ gca!(([N, N + 1], N)) }>(); | ^^^^^ diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs index 9642a066ad32b..258160017f179 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.rs @@ -1,15 +1,18 @@ -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] + use std::gca; + #[derive(PartialEq, Eq, std::marker::ConstParamTy)] pub enum Enum { Unit, Tuple(), Store(T), } + pub mod module { pub use super::Enum::Store; } + fn main() { const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); //~^ ERROR: type arguments are not allowed on unit variant `Unit` [E0109] diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr index 02903379932ae..c9d8033d15b68 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments-fail.stderr @@ -1,5 +1,5 @@ error[E0109]: type arguments are not allowed on unit variant `Unit` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:14:49 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:17:49 | LL | const _: Enum<()> = gca!(Enum::<()>::Unit::<()>); | ---- ^^ type argument not allowed @@ -14,7 +14,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Unit); | error[E0109]: type arguments are not allowed on tuple variant `Tuple` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:16:50 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:19:50 | LL | const _: Enum<()> = gca!(Enum::<()>::Tuple::<()>()); | ----- ^^ type argument not allowed @@ -29,7 +29,7 @@ LL + const _: Enum<()> = gca!(Enum::<()>::Tuple()); | error[E0109]: type arguments are not allowed on module `generic_args_on_enum_variant_segments_fail` - --> $DIR/generic-args-on-enum-variant-segments-fail.rs:18:37 + --> $DIR/generic-args-on-enum-variant-segments-fail.rs:21:37 | LL | const _: Enum<()> = gca!(self::::Enum::<()>::Store); | ---- ^^^ type argument not allowed diff --git a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs index f89dd4b87f32a..b705e695754da 100644 --- a/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs +++ b/tests/ui/const-generics/mgca/generic-args-on-enum-variant-segments.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items)] -#![feature(adt_const_params, unsized_const_params)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs index 009722fbe93a5..2377a3051307c 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.rs @@ -1,7 +1,11 @@ //! Regression test for #160553 (used to ICE) -#![allow(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] -#![feature(generic_const_parameter_types)] +#![feature( + adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_parameter_types +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr index 4906b05939900..08c115d5dedb5 100644 --- a/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr +++ b/tests/ui/const-generics/mgca/generic_const_items-mismatched-array-len.stderr @@ -1,11 +1,11 @@ error: the constant `*b"\x01\x02\x03"` is not of type `[u8; ::LEN]` - --> $DIR/generic_const_items-mismatched-array-len.rs:23:11 + --> $DIR/generic_const_items-mismatched-array-len.rs:27:11 | LL | foo::() | ^ expected `[u8; ::LEN]`, found `[u8; 3]` | note: required by a const generic parameter in `foo` - --> $DIR/generic_const_items-mismatched-array-len.rs:18:18 + --> $DIR/generic_const_items-mismatched-array-len.rs:22:18 | LL | fn foo::LEN]>() -> [u8; ::LEN] { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs index 075237a2094b5..bdf7a50bd3041 100644 --- a/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs +++ b/tests/ui/const-generics/mgca/generic_const_parameter_types-inferred-array-len.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, generic_const_parameter_types)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, generic_const_parameter_types)] use std::gca; diff --git a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs index aecd2b81b1c02..5563d35bb92af 100644 --- a/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/generic_const_type_mismatch.rs @@ -1,11 +1,11 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - generic_const_items, - generic_const_parameter_types, + const_param_ty_trait, + gca_adts, gca_min_const_items, - const_param_ty_trait + generic_const_items, + generic_const_parameter_types )] use std::gca; diff --git a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs index 69c45462fb011..80bfe0d13b35e 100644 --- a/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs +++ b/tests/ui/const-generics/mgca/invalid-array-in-tuple.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![allow(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs index 995f715984d54..3654a2c6ff249 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.rs @@ -2,8 +2,7 @@ //! things that must be an anon const, are currently less than ideal. This test merely asserts the //! current (bad) state of diagnostics, so we can track improvements over time. -#![feature(gca_min_const_items, min_adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr index 4d5f071037f97..744014bb18ca5 100644 --- a/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr +++ b/tests/ui/const-generics/mgca/mixed-direct-anon-expression-diagnostics.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:15:20 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:14:20 | LL | f::<{ gca!((N, 1 + 1)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/mixed-direct-anon-expression-diagnostics.rs:13:12 + --> $DIR/mixed-direct-anon-expression-diagnostics.rs:12:12 | LL | f::<{ (N, 1 + 1) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs index c5f3a6caeb112..5680e0fffe5f9 100644 --- a/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs +++ b/tests/ui/const-generics/mgca/nonsensical-negated-literal.rs @@ -1,10 +1,10 @@ #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs index 6888a45c3bd3f..d35971802e7f2 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.rs @@ -1,8 +1,7 @@ //! Regression test for //@ edition: 2024 -#![allow(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #[derive(Eq, PartialEq, core::marker::ConstParamTy)] struct Foo; diff --git a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr index 0184aebf157ae..9087f98cbb3f4 100644 --- a/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr +++ b/tests/ui/const-generics/mgca/printing_valtrees_supports_non_values.stderr @@ -1,29 +1,29 @@ error: the constant `Option::::Some(N)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:18:13 + --> $DIR/printing_valtrees_supports_non_values.rs:17:13 | LL | foo::<{ Option::Some:: { 0: N } }>; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(::ASSOC)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:23:13 + --> $DIR/printing_valtrees_supports_non_values.rs:22:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error[E0277]: the trait bound `T: Trait` is not satisfied - --> $DIR/printing_valtrees_supports_non_values.rs:30:5 + --> $DIR/printing_valtrees_supports_non_values.rs:29:5 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T` @@ -34,25 +34,25 @@ LL | fn test_ice_missing_bound() { | +++++++ error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:30:13 + --> $DIR/printing_valtrees_supports_non_values.rs:29:13 | LL | foo::<{ Option::Some:: { 0: ::ASSOC } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` error: the constant `Option::::Some(_)` is not of type `Foo` - --> $DIR/printing_valtrees_supports_non_values.rs:36:13 + --> $DIR/printing_valtrees_supports_non_values.rs:35:13 | LL | foo::<{ Option::Some:: { 0: _ } }>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Foo`, found `Option` | note: required by a const generic parameter in `foo` - --> $DIR/printing_valtrees_supports_non_values.rs:15:8 + --> $DIR/printing_valtrees_supports_non_values.rs:14:8 | LL | fn foo() {} | ^^^^^^^^^^^^ required by this const generic parameter in `foo` diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs index 9a4d4ca05be33..115b32d91ea46 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.rs @@ -1,6 +1,5 @@ //! regression test for -#![expect(incomplete_features)] -#![feature(gca_min_const_items, gca_macroless_args)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] fn foo() { [0; size_of::<*mut T>()]; diff --git a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr index 1abfff9518f44..2d725d66fcdc4 100644 --- a/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr +++ b/tests/ui/const-generics/mgca/size-of-generic-ptr-in-array-len.stderr @@ -1,17 +1,17 @@ error: function items cannot be used as const args - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/size-of-generic-ptr-in-array-len.rs:6:9 + --> $DIR/size-of-generic-ptr-in-array-len.rs:5:9 | LL | [0; size_of::<*mut T>()]; | ^^^^^^^^^^^^^^^^^^^ error: generic parameters may not be used in const operations - --> $DIR/size-of-generic-ptr-in-array-len.rs:9:32 + --> $DIR/size-of-generic-ptr-in-array-len.rs:8:32 | LL | [0; const { size_of::<*mut T>() }]; | ^ diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs index f14309f7492f4..9cca963a13f00 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.rs @@ -1,8 +1,7 @@ // This test ensures proper diagnostics emission during HIR ty lowering // See https://github.com/rust-lang/rust/issues/153254 -#![feature(gca_min_const_items)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, min_adt_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr index 3d09bbdab6072..73f0e76498770 100644 --- a/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr +++ b/tests/ui/const-generics/mgca/syntactic-type-mismatch.stderr @@ -1,11 +1,11 @@ error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants - --> $DIR/syntactic-type-mismatch.rs:9:11 + --> $DIR/syntactic-type-mismatch.rs:8:11 | LL | const T0: _ = gca!(()); | ^ not allowed in type signatures error: missing type for `const` item - --> $DIR/syntactic-type-mismatch.rs:12:9 + --> $DIR/syntactic-type-mismatch.rs:11:9 | LL | const T1 = gca!([0]); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs index da66ce8195d0f..318bf82691316 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_arg_simple.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs index 42ebe44172b05..f16106cd798d0 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr index 925572c27cb0b..e3f6b3b8834b2 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_complex_args.stderr @@ -1,11 +1,11 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_ctor_complex_args.rs:13:31 + --> $DIR/tuple_ctor_complex_args.rs:12:31 | LL | with_point::<{ gca!(Point(N + 1, N)) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_ctor_complex_args.rs:16:34 + --> $DIR/tuple_ctor_complex_args.rs:15:34 | LL | with_point::<{ Point(const { N + 1 }, N) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs index db158f3f38b00..6e720aba1b4ac 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::gca; use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr index 56b11b2894aa2..b9bbfcc37469d 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr +++ b/tests/ui/const-generics/mgca/tuple_ctor_erroneous.stderr @@ -1,5 +1,5 @@ error[E0425]: cannot find function, tuple struct or tuple variant `UnresolvedIdent` in this scope - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^ not found in this scope @@ -10,61 +10,61 @@ LL | fn test_errors() { | +++++++++++++++++++++++++++++++++++ error: tuple constructor has 2 arguments but 1 were provided - --> $DIR/tuple_ctor_erroneous.rs:24:23 + --> $DIR/tuple_ctor_erroneous.rs:23:23 | LL | accepts_point::<{ Point(N) }>(); | ^^^^^^^^ error: tuple constructor has 2 arguments but 3 were provided - --> $DIR/tuple_ctor_erroneous.rs:27:23 + --> $DIR/tuple_ctor_erroneous.rs:26:23 | LL | accepts_point::<{ Point(N, N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:30:23 + --> $DIR/tuple_ctor_erroneous.rs:29:23 | LL | accepts_point::<{ UnresolvedIdent(N, N) }>(); | ^^^^^^^^^^^^^^^^^^^^^ error: function items cannot be used as const args - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:34:23 + --> $DIR/tuple_ctor_erroneous.rs:33:23 | LL | accepts_point::<{ non_ctor(N, N) }>(); | ^^^^^^^^^^^^^^ error: tuple constructor with invalid base path - --> $DIR/tuple_ctor_erroneous.rs:38:23 + --> $DIR/tuple_ctor_erroneous.rs:37:23 | LL | accepts_point::<{ CONST_ITEM(N, N) }>(); | ^^^^^^^^^^^^^^^^ error: the constant `Point` is not of type `Point` - --> $DIR/tuple_ctor_erroneous.rs:41:23 + --> $DIR/tuple_ctor_erroneous.rs:40:23 | LL | accepts_point::<{ Point }>(); | ^^^^^ expected `Point`, found struct constructor | note: required by a const generic parameter in `accepts_point` - --> $DIR/tuple_ctor_erroneous.rs:18:18 + --> $DIR/tuple_ctor_erroneous.rs:17:18 | LL | fn accepts_point() {} | ^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_point` error: the constant `MyEnum::::Variant` is not of type `MyEnum` - --> $DIR/tuple_ctor_erroneous.rs:44:22 + --> $DIR/tuple_ctor_erroneous.rs:43:22 | LL | accepts_enum::<{ MyEnum::Variant:: }>(); | ^^^^^^^^^^^^^^^^^^^^^^ expected `MyEnum`, found enum constructor | note: required by a const generic parameter in `accepts_enum` - --> $DIR/tuple_ctor_erroneous.rs:19:17 + --> $DIR/tuple_ctor_erroneous.rs:18:17 | LL | fn accepts_enum>() {} | ^^^^^^^^^^^^^^^^^^^^ required by this const generic parameter in `accepts_enum` diff --git a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs index 096f56d9512a8..e03db5d7b0fdc 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_nested.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_nested.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs index 6a5c28bca6898..eaa1744bc5bbd 100644 --- a/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs +++ b/tests/ui/const-generics/mgca/tuple_ctor_type_relative.rs @@ -1,6 +1,5 @@ //@ run-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] use std::marker::ConstParamTy; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs index 50abdd97e908f..53216e3c5c14b 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] struct Y { stuff: [u8; { ([1, 2], 3, [4, 5]) }], //~ ERROR expected `usize`, found `([1, 2], 3, [4, 5])` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr index aa54a5ae77048..098a676d6d918 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_bad-issue-151048.stderr @@ -1,5 +1,5 @@ error: expected `usize`, found `([1, 2], 3, [4, 5])` - --> $DIR/tuple_expr_arg_bad-issue-151048.rs:5:19 + --> $DIR/tuple_expr_arg_bad-issue-151048.rs:4:19 | LL | stuff: [u8; { ([1, 2], 3, [4, 5]) }], | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs index 2b39a8b585faf..ff73b128fd522 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr index e6f004b2f9d68..cdee5ff343ba3 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_complex.stderr @@ -1,23 +1,23 @@ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:15:30 + --> $DIR/tuple_expr_arg_complex.rs:14:30 | LL | takes_tuple::<{ gca!((N, N + 1)) }>(); | ^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:16:30 + --> $DIR/tuple_expr_arg_complex.rs:15:30 | LL | takes_tuple::<{ gca!((N, T::ASSOC + 1)) }>(); | ^^^^^^^^^^^^ error: complex const arguments must be placed inside of a `const` block - --> $DIR/tuple_expr_arg_complex.rs:18:41 + --> $DIR/tuple_expr_arg_complex.rs:17:41 | LL | takes_nested_tuple::<{ gca!((N, (N, N + 1))) }>(); | ^^^^^ error: generic parameters may not be used in const operations - --> $DIR/tuple_expr_arg_complex.rs:19:49 + --> $DIR/tuple_expr_arg_complex.rs:18:49 | LL | takes_nested_tuple::<{ gca!((N, (N, const { N + 1 }))) }>(); | ^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs index 2b67665d7281b..685d29ed4cec1 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_macroless.rs @@ -1,12 +1,12 @@ //@ check-pass #![feature( - gca_min_const_items, - gca_macroless_args, adt_const_params, + gca_adts, + gca_macroless_args, + gca_min_const_items, unsized_const_params )] -#![expect(incomplete_features)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs index 780b757c0df1c..5247fcdec0e2f 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.rs @@ -1,5 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, min_adt_const_params)] pub fn takes_nested_tuple() { takes_nested_tuple::<{ () }> //~ ERROR expected `u32`, found `()` diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr index d8314a6b6a57e..a45ca91d69e3c 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_mismatch_type.stderr @@ -1,5 +1,5 @@ error: expected `u32`, found `()` - --> $DIR/tuple_expr_arg_mismatch_type.rs:5:28 + --> $DIR/tuple_expr_arg_mismatch_type.rs:4:28 | LL | takes_nested_tuple::<{ () }> | ^^ diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs index 8c4f64adf34dc..315636bc2e75d 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_simple.rs @@ -1,7 +1,6 @@ //@ check-pass -#![feature(gca_min_const_items, adt_const_params, unsized_const_params)] -#![expect(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, adt_const_params, unsized_const_params)] use std::gca; diff --git a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs index 7d8a1a1264bd9..c1c118d575a69 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_arg_unbounded_assoc_const.rs @@ -1,4 +1,4 @@ -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] // Regression test for an ICE in privacy checking while walking the `T` qself // of `T::ASSOC` inside a tuple const argument. diff --git a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs index e67a5a0a72e54..04533b8d96455 100644 --- a/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/tuple_expr_type_mismatch.rs @@ -1,9 +1,9 @@ //! Regression test for -#![expect(incomplete_features)] #![feature( adt_const_params, - gca_min_const_items, + gca_adts, gca_macroless_args, + gca_min_const_items, unsized_const_params )] fn foo() {} diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs index 46c661cfb96ce..e7f396543e66d 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.rs @@ -1,9 +1,13 @@ // Regression test for https://github.com/rust-lang/rust/issues/154632 -#![feature(generic_const_exprs)] -#![feature(gca_min_const_items)] -#![feature(gca_macroless_args)] -#![feature(generic_const_items)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + generic_const_exprs, + generic_const_items, + min_adt_const_params +)] use std::gca; diff --git a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr index 623ae087687f5..7135773752b55 100644 --- a/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr +++ b/tests/ui/const-generics/mgca/type_const-adt-expr-missing-field.stderr @@ -1,5 +1,5 @@ error[E0573]: cannot find type `ADD1` in this scope - --> $DIR/type_const-adt-expr-missing-field.rs:12:22 + --> $DIR/type_const-adt-expr-missing-field.rs:16:22 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^ not found in this scope @@ -7,7 +7,7 @@ LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); = note: a constant named `ADD1` exists in another namespace error: unconstrained generic constant - --> $DIR/type_const-adt-expr-missing-field.rs:10:1 + --> $DIR/type_const-adt-expr-missing-field.rs:14:1 | LL | const ADD1: usize = gca!(const { N + 1 }); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -18,7 +18,7 @@ LL | const ADD1: usize where [(); const { N + 1 }]: = gca!(const | ++++++++++++++++++++++++++++ error: struct expression with missing field initialiser for `0` - --> $DIR/type_const-adt-expr-missing-field.rs:12:43 + --> $DIR/type_const-adt-expr-missing-field.rs:16:43 | LL | const AliasFnUnused: ADD1 = gca!(ADD1::<{ Some:: {} }>); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr index 46be38bb1a53d..aac10bc622b5d 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.nogate.stderr @@ -1,53 +1,53 @@ error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:13:1 + --> $DIR/type_const-generic-param-in-type.rs:18:1 | LL | const FOO: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:16:1 + --> $DIR/type_const-generic-param-in-type.rs:21:1 | LL | const BAR: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:19:1 + --> $DIR/type_const-generic-param-in-type.rs:24:1 | LL | const BAZ<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:37:5 + --> $DIR/type_const-generic-param-in-type.rs:42:5 | LL | const ASSOC: [T; 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:40:5 + --> $DIR/type_const-generic-param-in-type.rs:45:5 | LL | const ASSOC_CONST: StructWithConstParam = gca!(StructWithConstParam::); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:43:5 + --> $DIR/type_const-generic-param-in-type.rs:48:5 | LL | const ASSOC_LT<'a>: [&'a (); 0] = gca!([]); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:24:5 + --> $DIR/type_const-generic-param-in-type.rs:29:5 | LL | const ASSOC: [T; 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[T; 0]` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:28:5 + --> $DIR/type_const-generic-param-in-type.rs:33:5 | LL | const ASSOC_CONST: StructWithConstParam; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `StructWithConstParam` must not depend on other generic parameter error[E0770]: the type of const parameters must not depend on other generic parameters - --> $DIR/type_const-generic-param-in-type.rs:32:5 + --> $DIR/type_const-generic-param-in-type.rs:37:5 | LL | const ASSOC_LT<'a>: [&'a (); 0]; | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the type `[&'a (); 0]` must not depend on other generic parameter diff --git a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs index 80293325d8800..b64853f37bb8f 100644 --- a/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs +++ b/tests/ui/const-generics/mgca/type_const-generic-param-in-type.rs @@ -1,7 +1,12 @@ //@ revisions: nogate gate //@ [gate] check-pass -#![expect(incomplete_features)] -#![feature(adt_const_params, unsized_const_params, gca_min_const_items, generic_const_items)] +#![feature( + adt_const_params, + gca_adts, + gca_min_const_items, + generic_const_items, + unsized_const_params +)] #![cfg_attr(gate, feature(generic_const_parameter_types))] use std::gca; diff --git a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs index a80f602fbf96a..c3ba68ae5213d 100644 --- a/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs +++ b/tests/ui/const-generics/mgca/wrapped_array_elem_type_mismatch.rs @@ -1,5 +1,5 @@ #![expect(incomplete_features)] -#![feature(adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(adt_const_params, gca_min_const_items, gca_macroless_args, gca_adts)] struct ArrWrap; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs index f5d3c06d7bc8e..3ca3c9bcb7536 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params)] struct TakesArr; diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr index a2e212b28ec6f..3e2ee8c5f718a 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag.rs:9:32 + --> $DIR/wrong_type_const_arr_diag.rs:8:32 | LL | let _: TakesArr<{ [N] }> = TakesArr::<{ [1] }>; | ----------------- ^^^^^^^^^^^^^^^^^^^ expected `[N]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs index 225d3ef226cba..ee91819204859 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.rs @@ -1,7 +1,6 @@ // This test causes ERROR: mismatched types [E0308] // and makes rustc to print array from const arguments -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] -#![allow(incomplete_features)] +#![feature(gca_adts, gca_min_const_items, gca_macroless_args, adt_const_params, trivial_bounds)] trait Trait { #[rustc_always_gca] diff --git a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr index 66de4a4d6a864..5338a7bfbd973 100644 --- a/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr +++ b/tests/ui/const-generics/mgca/wrong_type_const_arr_diag_trait.stderr @@ -1,5 +1,5 @@ error[E0308]: mismatched types - --> $DIR/wrong_type_const_arr_diag_trait.rs:17:51 + --> $DIR/wrong_type_const_arr_diag_trait.rs:16:51 | LL | let _: TakesArr<{ [::ASSOC] }> = TakesArr::<{ [1] }>; | ------------------------------------ ^^^^^^^^^^^^^^^^^^^ expected `[::ASSOC]`, found `*b"\x01"` diff --git a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs index 675cecc68f884..e6d8e362dd191 100644 --- a/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs +++ b/tests/ui/const-generics/min_adt_const_params/tuple_with_infer_arg.rs @@ -1,6 +1,6 @@ //@ check-pass -#![feature(min_adt_const_params, gca_min_const_items, gca_macroless_args)] +#![feature(min_adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] struct S; diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.rs b/tests/ui/feature-gates/feature-gate-gca-adts.rs new file mode 100644 index 0000000000000..6b77771fc4cdc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.rs @@ -0,0 +1,24 @@ +//@ revisions: without without_with_min_items with +//@[with] check-pass + +#![feature(min_adt_const_params)] +#![cfg_attr(with, feature(gca_adts))] +// gca_min_const_items enables the gca! macro as well, which is vaguely interesting to test too +#![cfg_attr(without_with_min_items, feature(gca_min_const_items))] + +use std::gca; +//[without]~^ ERROR use of unstable library feature `gca_min_const_items` + +struct S; + +fn main() { + let _: S = S::; + //[without_with_min_items]~^ ERROR complex const arguments must be placed inside of a `const` block + //[without_with_min_items]~| ERROR complex const arguments must be placed inside of a `const` block + //[without]~^^^ ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR use of unstable library feature `gca_min_const_items` + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR expected type, found `gca!()` constant + //[without]~| ERROR type provided when a constant was expected + //[without]~| ERROR type provided when a constant was expected +} diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr new file mode 100644 index 0000000000000..9076e2313db09 --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without.stderr @@ -0,0 +1,58 @@ +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: expected type, found `gca!()` constant + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0658]: use of unstable library feature `gca_min_const_items` + --> $DIR/feature-gate-gca-adts.rs:9:5 + | +LL | use std::gca; + | ^^^^^^^^ + | + = note: see issue #132980 for more information + = help: add `#![feature(gca_min_const_items)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:14 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error[E0747]: type provided when a constant was expected + --> $DIR/feature-gate-gca-adts.rs:15:34 + | +LL | let _: S = S::; + | ^^^^^^^^^^^^ + +error: aborting due to 7 previous errors + +Some errors have detailed explanations: E0658, E0747. +For more information about an error, try `rustc --explain E0658`. diff --git a/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr new file mode 100644 index 0000000000000..84c64b828b3fc --- /dev/null +++ b/tests/ui/feature-gates/feature-gate-gca-adts.without_with_min_items.stderr @@ -0,0 +1,14 @@ +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:19 + | +LL | let _: S = S::; + | ^^^^^^ + +error: complex const arguments must be placed inside of a `const` block + --> $DIR/feature-gate-gca-adts.rs:15:39 + | +LL | let _: S = S::; + | ^^^^^^ + +error: aborting due to 2 previous errors + diff --git a/tests/ui/transmutability/non_scalar_alignment_value.rs b/tests/ui/transmutability/non_scalar_alignment_value.rs index 24e97a2a55356..937fa39876303 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.rs +++ b/tests/ui/transmutability/non_scalar_alignment_value.rs @@ -1,4 +1,10 @@ -#![feature(gca_min_const_items, gca_macroless_args, transmutability)] +#![feature( + gca_adts, + gca_macroless_args, + gca_min_const_items, + min_adt_const_params, + transmutability +)] mod assert { use std::mem::{Assume, TransmuteFrom}; diff --git a/tests/ui/transmutability/non_scalar_alignment_value.stderr b/tests/ui/transmutability/non_scalar_alignment_value.stderr index 80a125d540a8f..020a557573bda 100644 --- a/tests/ui/transmutability/non_scalar_alignment_value.stderr +++ b/tests/ui/transmutability/non_scalar_alignment_value.stderr @@ -1,23 +1,23 @@ error: struct expression with missing field initialiser for `alignment` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `lifetimes` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `safety` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ error: struct expression with missing field initialiser for `validity` - --> $DIR/non_scalar_alignment_value.rs:12:32 + --> $DIR/non_scalar_alignment_value.rs:18:32 | LL | alignment: Assume {}, | ^^^^^^^^^ diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs index a155d9ade5cf3..9895ccbfd0926 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.rs @@ -1,8 +1,7 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![feature(gca_min_const_items, gca_macroless_args, adt_const_params)] -#![expect(incomplete_features)] +#![feature(adt_const_params, gca_adts, gca_min_const_items, gca_macroless_args)] #![allow(dead_code)] use std::marker::ConstParamTy; diff --git a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout index c2c79249a6bd4..f117acc810606 100644 --- a/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout +++ b/tests/ui/unpretty/struct-exprs-tuple-call-pretty-printing.stdout @@ -1,10 +1,9 @@ //@ compile-flags: -Zunpretty=hir //@ check-pass -#![expect(incomplete_features)] #![allow(dead_code)] -#![attr = Feature([gca_min_const_items#0, gca_macroless_args#0, -adt_const_params#0])] +#![attr = Feature([adt_const_params#0, gca_adts#0, gca_min_const_items#0, +gca_macroless_args#0])] extern crate std; #[attr = PreludeImport] use ::std::prelude::rust_2015::*; From ceee44bc9df314e1b522e6e479764b96ad5db82d Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 28 Sep 2026 16:01:46 +0200 Subject: [PATCH 0960/1309] Force the correct type variable to never for method resolution on an adjusted never type --- compiler/rustc_hir_typeck/src/method/probe.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_hir_typeck/src/method/probe.rs b/compiler/rustc_hir_typeck/src/method/probe.rs index 178585984cf27..aee246a61fb1e 100644 --- a/compiler/rustc_hir_typeck/src/method/probe.rs +++ b/compiler/rustc_hir_typeck/src/method/probe.rs @@ -524,8 +524,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> { span, MethodCallOnDivergingInferenceVariable, ); - let root_ty = Ty::new_var(self.tcx, ty_id); - self.demand_eqtype(span, root_ty, self.tcx.types.never); + self.demand_eqtype(span, ty, self.tcx.types.never); } else { let guar = match *ty.kind() { _ if let Some(guar) = self.tainted_by_errors() => guar, From f3b65028f7a6f4cf250929317375d06437b445a2 Mon Sep 17 00:00:00 2001 From: Jonathan Brouwer Date: Mon, 28 Sep 2026 16:02:04 +0200 Subject: [PATCH 0961/1309] Run the `method-on-never` type on the next trait solver --- ....stderr => method-on-never.current.stderr} | 20 ++-- .../basic/method-on-never.next.stderr | 113 ++++++++++++++++++ tests/ui/never_type/basic/method-on-never.rs | 2 + 3 files changed, 125 insertions(+), 10 deletions(-) rename tests/ui/never_type/basic/{method-on-never.stderr => method-on-never.current.stderr} (93%) create mode 100644 tests/ui/never_type/basic/method-on-never.next.stderr diff --git a/tests/ui/never_type/basic/method-on-never.stderr b/tests/ui/never_type/basic/method-on-never.current.stderr similarity index 93% rename from tests/ui/never_type/basic/method-on-never.stderr rename to tests/ui/never_type/basic/method-on-never.current.stderr index f5903616be6f4..ec89b37bc403e 100644 --- a/tests/ui/never_type/basic/method-on-never.stderr +++ b/tests/ui/never_type/basic/method-on-never.current.stderr @@ -1,5 +1,5 @@ warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:42:7 + --> $DIR/method-on-never.rs:44:7 | LL | x.method(); | ^^^^^^ @@ -10,7 +10,7 @@ LL | x.method(); = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:46:17 + --> $DIR/method-on-never.rs:48:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -20,7 +20,7 @@ LL | { loop {} }.method(); = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:51:16 + --> $DIR/method-on-never.rs:53:16 | LL | y => y.method(), | ^^^^^^ @@ -30,7 +30,7 @@ LL | y => y.method(), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:57:27 + --> $DIR/method-on-never.rs:59:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -40,7 +40,7 @@ LL | error => (&error).anyhow_kind().new(error), = note: for more information, see issue #156047 warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:63:9 + --> $DIR/method-on-never.rs:65:9 | LL | res.method(); | ^^^^^^ @@ -53,7 +53,7 @@ warning: 5 warnings emitted Future incompatibility report: Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:42:7 + --> $DIR/method-on-never.rs:44:7 | LL | x.method(); | ^^^^^^ @@ -65,7 +65,7 @@ LL | x.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:46:17 + --> $DIR/method-on-never.rs:48:17 | LL | { loop {} }.method(); | ^^^^^^ @@ -77,7 +77,7 @@ LL | { loop {} }.method(); Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:51:16 + --> $DIR/method-on-never.rs:53:16 | LL | y => y.method(), | ^^^^^^ @@ -89,7 +89,7 @@ LL | y => y.method(), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:57:27 + --> $DIR/method-on-never.rs:59:27 | LL | error => (&error).anyhow_kind().new(error), | ^^^^^^^^^^^ @@ -101,7 +101,7 @@ LL | error => (&error).anyhow_kind().new(error), Future breakage diagnostic: warning: method call on a diverging inference variable - --> $DIR/method-on-never.rs:63:9 + --> $DIR/method-on-never.rs:65:9 | LL | res.method(); | ^^^^^^ diff --git a/tests/ui/never_type/basic/method-on-never.next.stderr b/tests/ui/never_type/basic/method-on-never.next.stderr new file mode 100644 index 0000000000000..ec89b37bc403e --- /dev/null +++ b/tests/ui/never_type/basic/method-on-never.next.stderr @@ -0,0 +1,113 @@ +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:44:7 + | +LL | x.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:48:17 + | +LL | { loop {} }.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:53:16 + | +LL | y => y.method(), + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:59:27 + | +LL | error => (&error).anyhow_kind().new(error), + | ^^^^^^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:65:9 + | +LL | res.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + +warning: 5 warnings emitted + +Future incompatibility report: Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:44:7 + | +LL | x.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:48:17 + | +LL | { loop {} }.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:53:16 + | +LL | y => y.method(), + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:59:27 + | +LL | error => (&error).anyhow_kind().new(error), + | ^^^^^^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + +Future breakage diagnostic: +warning: method call on a diverging inference variable + --> $DIR/method-on-never.rs:65:9 + | +LL | res.method(); + | ^^^^^^ + | + = help: consider providing a type annotation + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #156047 + = note: `#[warn(method_call_on_diverging_infer_var)]` (part of `#[warn(future_incompatible)]`) on by default + diff --git a/tests/ui/never_type/basic/method-on-never.rs b/tests/ui/never_type/basic/method-on-never.rs index 4194884ade9ea..ac928a0e9d071 100644 --- a/tests/ui/never_type/basic/method-on-never.rs +++ b/tests/ui/never_type/basic/method-on-never.rs @@ -1,3 +1,5 @@ +//@ revisions: current next +//@[next] compile-flags: -Znext-solver //@ check-pass // Regression test for https://github.com/rust-lang/rust/issues/143349 From 773ad198b6b28ba21cd319607d264618420b3060 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Mon, 28 Sep 2026 15:39:32 +0200 Subject: [PATCH 0962/1309] Add `stable_rustc` helper in `run-make-support` --- .../src/external_deps/rustc.rs | 24 ++++++++++++++++--- src/tools/run-make-support/src/lib.rs | 4 +++- .../const-destruct-stable-toolchain/rmake.rs | 6 ++--- .../const-trait-stable-toolchain/rmake.rs | 9 +++---- .../issue-149402-suggest-unresolve/rmake.rs | 10 ++------ .../missing-unstable-trait-bound/rmake.rs | 6 ++--- .../rmake.rs | 11 +++------ 7 files changed, 36 insertions(+), 34 deletions(-) diff --git a/src/tools/run-make-support/src/external_deps/rustc.rs b/src/tools/run-make-support/src/external_deps/rustc.rs index 8b28105abe5ed..fab7f2098ea1c 100644 --- a/src/tools/run-make-support/src/external_deps/rustc.rs +++ b/src/tools/run-make-support/src/external_deps/rustc.rs @@ -22,6 +22,15 @@ pub fn bare_rustc() -> Rustc { Rustc::bare() } +/// Construct a plain `rustc` invocation with no flags set that behaves like a stable compiler, +/// i.e. rejects unstable flags. +/// Note that [`set_host_compiler_dylib_path`] still presets the environment variable +/// `HOST_RUSTC_DYLIB_PATH` by default. +#[track_caller] +pub fn stable_bare_rustc() -> Rustc { + Rustc::bare_stable() +} + /// Construct a `rustc` invocation for building `minicore`. /// /// This function: @@ -76,9 +85,6 @@ pub fn rustc_path() -> String { fn setup_common() -> Command { let mut cmd = Command::new(rustc_path()); set_host_compiler_dylib_path(&mut cmd); - if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") { - cmd.arg(format!("-Zcodegen-backend={codegen_backend}")); - } cmd } @@ -100,6 +106,10 @@ impl Rustc { cmd.arg("-Ctarget-feature=-crt-static"); } + if let Ok(codegen_backend) = std::env::var("RUSTC_CODEGEN_BACKEND") { + cmd.arg(format!("-Zcodegen-backend={codegen_backend}")); + } + // Automatically default to cross-compilation Self { cmd, target: Some(target()) } } @@ -111,6 +121,14 @@ impl Rustc { Self { cmd, target: None } } + /// Construct a bare `rustc` invocation with no flags set that acts like a stable compiler. + #[track_caller] + pub fn bare_stable() -> Self { + let mut cmd = setup_common(); + cmd.env("RUSTC_BOOTSTRAP", "-1"); + Self { cmd, target: None } + } + // Argument provider methods /// Configure the compilation environment. diff --git a/src/tools/run-make-support/src/lib.rs b/src/tools/run-make-support/src/lib.rs index d3c2115e745e0..b9717bda1e2c7 100644 --- a/src/tools/run-make-support/src/lib.rs +++ b/src/tools/run-make-support/src/lib.rs @@ -79,7 +79,9 @@ pub use crate::external_deps::llvm::{ llvm_readobj, }; pub use crate::external_deps::python::python_command; -pub use crate::external_deps::rustc::{self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path}; +pub use crate::external_deps::rustc::{ + self, Rustc, bare_rustc, rustc, rustc_minicore, rustc_path, stable_bare_rustc, +}; pub use crate::external_deps::rustdoc::{Rustdoc, bare_rustdoc, rustdoc}; // Path-related helpers. pub use crate::path_helpers::{ diff --git a/tests/run-make/const-destruct-stable-toolchain/rmake.rs b/tests/run-make/const-destruct-stable-toolchain/rmake.rs index 0f36d71f2c874..c4990582d40ba 100644 --- a/tests/run-make/const-destruct-stable-toolchain/rmake.rs +++ b/tests/run-make/const-destruct-stable-toolchain/rmake.rs @@ -1,17 +1,15 @@ //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Test that the suggestion to constrain a type parameter that is dropped in a const // function with a `[const] Destruct` bound is only offered on nightly, since the bound // requires an unstable feature. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { - let out = rustc() + let out = stable_bare_rustc() .input("const-drop.rs") - .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("consider restricting type parameter `T`") .stderr_utf8(); diff --git a/tests/run-make/const-trait-stable-toolchain/rmake.rs b/tests/run-make/const-trait-stable-toolchain/rmake.rs index e2ec58f03db19..c778873463063 100644 --- a/tests/run-make/const-trait-stable-toolchain/rmake.rs +++ b/tests/run-make/const-trait-stable-toolchain/rmake.rs @@ -1,16 +1,14 @@ //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Test output of const super trait errors in both stable and nightly. // We don't want to provide suggestions on stable that only make sense in nightly. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, rustc, stable_bare_rustc}; fn main() { - let out = rustc() + let out = stable_bare_rustc() .input("const-super-trait.rs") - .env("RUSTC_BOOTSTRAP", "-1") .cfg("feature_enabled") .run_fail() .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") @@ -35,9 +33,8 @@ fn main() { .expected_file("const-super-trait-nightly-enabled.stderr") .actual_text("(rustc)", &out) .run(); - let out = rustc() + let out = stable_bare_rustc() .input("const-super-trait.rs") - .env("RUSTC_BOOTSTRAP", "-1") .run_fail() .assert_stderr_not_contains("enable `#![feature(const_trait_impl)]` in your crate and mark") .assert_stderr_not_contains("as `const` to allow it to have `const` implementations") diff --git a/tests/run-make/issue-149402-suggest-unresolve/rmake.rs b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs index 78348b914d1e6..a8d92606ee893 100644 --- a/tests/run-make/issue-149402-suggest-unresolve/rmake.rs +++ b/tests/run-make/issue-149402-suggest-unresolve/rmake.rs @@ -4,18 +4,12 @@ //! //@ only-nightly //@ needs-target-std -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc -use run_make_support::{diff, rustc, similar}; +use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { - let stable_like = rustc() - .env("RUSTC_BOOTSTRAP", "-1") - .edition("2024") - .input("foo.rs") - .run_fail() - .stderr_utf8(); + let stable_like = stable_bare_rustc().edition("2024").input("foo.rs").run_fail().stderr_utf8(); assert!(!stable_like.contains("CoroutineState::Complete")); diff().expected_file("stable.err").actual_text("stable_like", &stable_like).run(); diff --git a/tests/run-make/missing-unstable-trait-bound/rmake.rs b/tests/run-make/missing-unstable-trait-bound/rmake.rs index 753f4abcf32fd..52a011285c95c 100644 --- a/tests/run-make/missing-unstable-trait-bound/rmake.rs +++ b/tests/run-make/missing-unstable-trait-bound/rmake.rs @@ -2,17 +2,15 @@ //@ ignore-wasm32 //@ ignore-wasm64 // ignore-tidy-linelength -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc // Ensure that on stable we don't suggest restricting with an unsafe trait and we continue // mentioning the rest of the obligation chain. -use run_make_support::{diff, rustc}; +use run_make_support::{diff, stable_bare_rustc}; fn main() { - let out = rustc() - .env("RUSTC_BOOTSTRAP", "-1") + let out = stable_bare_rustc() .input("missing-bound.rs") .run_fail() .assert_stderr_not_contains("help: consider restricting type parameter `T`") diff --git a/tests/run-make/print-request-help-stable-unstable/rmake.rs b/tests/run-make/print-request-help-stable-unstable/rmake.rs index 62cf0483f320d..01572a5aad942 100644 --- a/tests/run-make/print-request-help-stable-unstable/rmake.rs +++ b/tests/run-make/print-request-help-stable-unstable/rmake.rs @@ -2,18 +2,13 @@ //! //! Issue: -// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. //@ ignore-backends: gcc -use run_make_support::{diff, rustc, similar}; +use run_make_support::{diff, rustc, similar, stable_bare_rustc}; fn main() { - let stable_invalid_print_request_help = rustc() - .env("RUSTC_BOOTSTRAP", "-1") - .cfg("force_stable") - .print("xxx") - .run_fail() - .stderr_utf8(); + let stable_invalid_print_request_help = + stable_bare_rustc().print("xxx").run_fail().stderr_utf8(); assert!(!stable_invalid_print_request_help.contains("all-target-specs-json")); diff() .expected_file("stable-invalid-print-request-help.err") From 62ce017dc8d51dee67e7bc021c202ab564f507c0 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 28 Sep 2026 17:21:14 +0300 Subject: [PATCH 0963/1309] Allow using different index types when reading and writing to tables --- compiler/rustc_metadata/src/rmeta/decoder.rs | 4 +-- compiler/rustc_metadata/src/rmeta/encoder.rs | 12 ++++--- compiler/rustc_metadata/src/rmeta/mod.rs | 34 ++++++++++++-------- compiler/rustc_metadata/src/rmeta/table.rs | 32 +++++++++++------- 4 files changed, 49 insertions(+), 33 deletions(-) diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs index 27b36c23daf46..7dd920c7e39bd 100644 --- a/compiler/rustc_metadata/src/rmeta/decoder.rs +++ b/compiler/rustc_metadata/src/rmeta/decoder.rs @@ -189,7 +189,7 @@ pub(super) trait LazyDecoder: BlobDecoder { self.read_lazy_offset_then(|pos| LazyArray::from_position_and_num_elems(pos, len)) } - fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { + fn read_lazy_table(&mut self, width: usize, len: usize) -> LazyTable { self.read_lazy_offset_then(|pos| LazyTable::from_position_and_encoded_size(pos, width, len)) } @@ -667,7 +667,7 @@ impl Decodable for LazyArray { } } -impl Decodable for LazyTable { +impl Decodable for LazyTable { fn decode(decoder: &mut D) -> Self { let width = decoder.read_usize(); let len = decoder.read_usize(); diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs index afa5646bea80e..40b61a52d2310 100644 --- a/compiler/rustc_metadata/src/rmeta/encoder.rs +++ b/compiler/rustc_metadata/src/rmeta/encoder.rs @@ -133,7 +133,7 @@ impl<'a, 'tcx, T> Encodable> for LazyArray { } } -impl<'a, 'tcx, I, T> Encodable> for LazyTable { +impl<'a, 'tcx, Ie, Id, T> Encodable> for LazyTable { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) { e.emit_usize(self.width); e.emit_usize(self.len); @@ -547,7 +547,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map())) } - fn encode_source_map(&mut self) -> LazyTable>> { + fn encode_source_map( + &mut self, + ) -> LazyTable>> { let source_map = self.tcx.sess.source_map(); let all_source_files = source_map.files(); @@ -2004,9 +2006,9 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> { } fn encode_hygiene(&mut self) -> (SyntaxContextTable, ExpnDataTable, ExpnHashTable) { - let mut syntax_contexts: TableBuilder<_, _> = Default::default(); - let mut expn_data_table: TableBuilder<_, _> = Default::default(); - let mut expn_hash_table: TableBuilder<_, _> = Default::default(); + let mut syntax_contexts: TableBuilder<_, _, _> = Default::default(); + let mut expn_data_table: TableBuilder<_, _, _> = Default::default(); + let mut expn_hash_table: TableBuilder<_, _, _> = Default::default(); HygieneEncodeContext::encode( &Rc::clone(&self.hygiene_ctxt), diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs index e3f3257acc137..b70151604f679 100644 --- a/compiler/rustc_metadata/src/rmeta/mod.rs +++ b/compiler/rustc_metadata/src/rmeta/mod.rs @@ -48,6 +48,7 @@ use rustc_target::spec::{PanicStrategy, TargetTuple}; use table::TableBuilder; use crate::eii::EiiMapEncodedKeyValue; +use crate::rmeta::table::TableBuilderSingleIdx; mod decoder; mod def_path_hash_map; @@ -143,22 +144,27 @@ impl LazyArray { /// Random-access table (i.e. offering constant-time `get`/`set`), similar to /// `LazyArray`, but without requiring encoding or decoding all the values /// eagerly and in-order. -struct LazyTable { +/// +/// `IdxEncode` - is a type of index that is used to write to the table, +/// `IdxDecode` - is a type of index that is used to read from the table. +struct LazyTable { position: NonZero, /// The encoded size of the elements of a table is selected at runtime to drop /// trailing zeroes. This is the number of bytes used for each table element. width: usize, /// How many elements are in the table. len: usize, - _marker: PhantomData T>, + _marker: PhantomData T>, } -impl LazyTable { +type LazyTableSingleIdx = LazyTable; + +impl LazyTable { fn from_position_and_encoded_size( position: NonZero, width: usize, len: usize, - ) -> LazyTable { + ) -> LazyTable { LazyTable { position, width, len, _marker: PhantomData } } } @@ -177,8 +183,8 @@ impl Clone for LazyArray { } } -impl Copy for LazyTable {} -impl Clone for LazyTable { +impl Copy for LazyTable {} +impl Clone for LazyTable { fn clone(&self) -> Self { *self } @@ -199,9 +205,9 @@ enum LazyState { Previous(NonZero), } -type SyntaxContextTable = LazyTable>>; -type ExpnDataTable = LazyTable>>; -type ExpnHashTable = LazyTable>>; +type SyntaxContextTable = LazyTableSingleIdx>>; +type ExpnDataTable = LazyTableSingleIdx>>; +type ExpnHashTable = LazyTableSingleIdx>>; #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct ProcMacroData { @@ -305,7 +311,7 @@ pub(crate) struct CrateRoot { def_path_hash_map: LazyValue>, - source_map: LazyTable>>, + source_map: LazyTableSingleIdx>>, target_modifiers: LazyArray, denied_partial_mitigations: LazyArray, @@ -389,14 +395,14 @@ macro_rules! define_tables { ) => { #[derive(MetadataEncodable, LazyDecodable)] pub(crate) struct LazyTables { - $($name1: LazyTable<$IDX1, $T1>,)+ - $($name2: LazyTable<$IDX2, Option<$T2>>,)+ + $($name1: LazyTableSingleIdx<$IDX1, $T1>,)+ + $($name2: LazyTableSingleIdx<$IDX2, Option<$T2>>,)+ } #[derive(Default)] struct TableBuilders { - $($name1: TableBuilder<$IDX1, $T1>,)+ - $($name2: TableBuilder<$IDX2, Option<$T2>>,)+ + $($name1: TableBuilderSingleIdx<$IDX1, $T1>,)+ + $($name2: TableBuilderSingleIdx<$IDX2, Option<$T2>>,)+ } impl TableBuilders { diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs index 7b53ebba8adfc..c023b61d73571 100644 --- a/compiler/rustc_metadata/src/rmeta/table.rs +++ b/compiler/rustc_metadata/src/rmeta/table.rs @@ -427,34 +427,38 @@ impl FixedSizeEncoding for Option> { } /// Helper for constructing a table's serialization (also see `Table`). -pub(super) struct TableBuilder { +pub(super) struct TableBuilder { width: usize, - blocks: IndexVec, - _marker: PhantomData, + blocks: IndexVec, + _marker: PhantomData<(IdxDecode, T)>, } -impl Default for TableBuilder { +pub(super) type TableBuilderSingleIdx = TableBuilder; + +impl Default for TableBuilder { fn default() -> Self { TableBuilder { width: 0, blocks: Default::default(), _marker: PhantomData } } } -impl TableBuilder> +impl TableBuilder> where Option: FixedSizeEncoding, { - pub(crate) fn set_some(&mut self, i: I, value: T) { + pub(crate) fn set_some(&mut self, i: Ie, value: T) { self.set(i, Some(value)) } } -impl> TableBuilder { +impl> + TableBuilder +{ /// Sets the table value if it is not default. /// ATTENTION: For optimization default values are simply ignored by this function, because /// right now metadata tables never need to reset non-default values to default. If such need /// arises in the future then a new method (e.g. `clear` or `reset`) will need to be introduced /// for doing that explicitly. - pub(crate) fn set(&mut self, i: I, value: T) { + pub(crate) fn set(&mut self, i: Ie, value: T) { #[cfg(debug_assertions)] { debug_assert!( @@ -477,7 +481,7 @@ impl> TableBui } } - pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { + pub(crate) fn encode(&self, buf: &mut FileEncoder<'_>) -> LazyTable { let pos = buf.position(); let width = self.width; @@ -500,13 +504,17 @@ fn trailing_zeros(x: &[u8]) -> usize { x.iter().rev().take_while(|b| **b == 0).count() } -impl + ParameterizedOverTcx> - LazyTable +impl< + Ie: Idx, + Id: Idx, + const N: usize, + T: FixedSizeEncoding + ParameterizedOverTcx, +> LazyTable where for<'tcx> T::Value<'tcx>: FixedSizeEncoding, { /// Given the metadata, extract out the value at a particular index (if any). - pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: I) -> T::Value<'tcx> { + pub(super) fn get<'a, 'tcx, M: MetaBlob<'a>>(&self, metadata: M, i: Id) -> T::Value<'tcx> { // Access past the end of the table returns a Default if i.index() >= self.len { return Default::default(); From 0012416ca7a155b3c2849b095b4d6ee1ecaa3a27 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Mon, 28 Sep 2026 22:39:19 +0800 Subject: [PATCH 0964/1309] Add safety comments for alloc::str --- library/alloc/src/str.rs | 85 +++++++++++++++++++++++++--------------- 1 file changed, 53 insertions(+), 32 deletions(-) diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs index cd1c149c3c4fc..a736a25ccdeb8 100644 --- a/library/alloc/src/str.rs +++ b/library/alloc/src/str.rs @@ -73,7 +73,8 @@ impl> Join<&str> for [S] { type Output = String; fn join(slice: &Self, sep: &str) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: slice can be borrowed as `[&str]` and sep is `&str`, both are valid UTF-8, + // so the returned `Vec` of `join_generic_copy` is also valid UTF-8. unsafe { String::from_utf8_unchecked(join_generic_copy(slice, sep.as_bytes())) } } } @@ -183,30 +184,37 @@ where let pos = result.len(); debug_assert!(reserved_len >= pos); - // ignore-tidy-undocumented-unsafe - unsafe { - let target = result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos); - // Convert the separator and slices to slices of MaybeUninit - // to simplify implementation in specialize_for_lengths. - let sep_uninit = core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()); - let iter_uninit = iter.map(|it| { - let it = it.borrow().as_ref(); - core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) - }); + // SAFETY: The size of remaining spare is at least `reserved_len - pos`. + let target = unsafe { result.spare_capacity_mut().get_unchecked_mut(..reserved_len - pos) }; + + // Convert the separator and slices to slices of MaybeUninit + // to simplify implementation in specialize_for_lengths. + // SAFETY: `sep` is a slice of `T`, so `sep.as_ptr().cast()` is a valid pointer, + // and `sep.len()` is the number of elements in the slice, so `from_raw_parts` is safe. + let sep_uninit = unsafe { core::slice::from_raw_parts(sep.as_ptr().cast(), sep.len()) }; + let iter_uninit = iter.map(|it| { + let it = it.borrow().as_ref(); + // SAFETY: `it` is a slice of `T`, so `it.as_ptr().cast()` is a valid pointer, + // and `it.len()` is the number of elements in the slice, so `from_raw_parts` is safe. + unsafe { core::slice::from_raw_parts(it.as_ptr().cast(), it.len()) } + }); - // copy separator and slices over without bounds checks. - // `specialize_for_lengths!` internally calls `s.borrow()`, but because it uses - // the bounds-checked `split_at_mut` any misbehaving implementation - // will not write out of bounds. - let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); + // copy separator and slices over without bounds checks. + // `specialize_for_lengths!` internally calls `s.borrow()`, but because it uses + // the bounds-checked `split_at_mut` any misbehaving implementation + // will not write out of bounds. + let remain = specialize_for_lengths!(sep_uninit, target, iter_uninit; 0, 1, 2, 3, 4); - // A weird borrow implementation may return different - // slices for the length calculation and the actual copy. - // Make sure we don't expose uninitialized bytes to the caller. - let result_len = reserved_len - remain.len(); + // A weird borrow implementation may return different + // slices for the length calculation and the actual copy. + // Make sure we don't expose uninitialized bytes to the caller. + let result_len = reserved_len - remain.len(); + // SAFETY: `result_len` is less than `reserved_len`, and all elements in `0..result_len` are initialized. + unsafe { result.set_len(result_len); } + result } @@ -250,7 +258,7 @@ impl ToOwned for str { #[inline] fn to_owned(&self) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` is a valid UTF-8 str. unsafe { String::from_utf8_unchecked(self.as_bytes().to_owned()) } } @@ -319,7 +327,7 @@ impl str { _ => None, } { if let [to_byte] = to.as_bytes() { - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` is a valid UTF-8 str, `from_byte` and `to_byte` are ASCII bytes. return unsafe { replace_ascii(self.as_bytes(), from_byte, *to_byte) }; } } @@ -332,12 +340,16 @@ impl str { let mut result = String::with_capacity(default_capacity); let mut last_end = 0; for (start, part) in self.match_indices(from) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` does not exceed `start`, and `start` does not exceed `self.len()`. + // Therefore, `last_end..start` is within bounds of `self`. + // For each iteration, `last_end` and `start` lie on UTF-8 sequence boundaries. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` is the start of the remaining unmatched suffix of `self`. + // It is 0 or the end of a match returned by `match_indices`, so it is + // a UTF-8 boundary within `self`. `self.len()` is also a UTF-8 boundary. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -374,12 +386,16 @@ impl str { let mut result = String::with_capacity(32); let mut last_end = 0; for (start, part) in self.match_indices(pat).take(count) { - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` does not exceed `start`, and `start` does not exceed `self.len()`. + // Therefore, `last_end..start` is within bounds of `self`. + // For each iteration, `last_end` and `start` lie on UTF-8 sequence boundaries. result.push_str(unsafe { self.get_unchecked(last_end..start) }); result.push_str(to); last_end = start + part.len(); } - // ignore-tidy-undocumented-unsafe + // SAFETY: `last_end` is the start of the remaining suffix of `self`. + // It is 0 or the end of a match returned by `match_indices`, so it is + // a UTF-8 boundary within `self`. `self.len()` is also a UTF-8 boundary. result.push_str(unsafe { self.get_unchecked(last_end..self.len()) }); result } @@ -793,7 +809,7 @@ impl str { #[inline] pub fn into_string(self: Box) -> String { let slice = Box::<[u8]>::from(self); - // ignore-tidy-undocumented-unsafe + // SAFETY: `slice` is a valid UTF-8 sequence because it is created from a `Box`. unsafe { String::from_utf8_unchecked(slice.into_vec()) } } @@ -823,7 +839,7 @@ impl str { #[stable(feature = "repeat_str", since = "1.16.0")] #[inline] pub fn repeat(&self, n: usize) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: The created Vec is valid UTF-8 because `self` is str. unsafe { String::from_utf8_unchecked(self.as_bytes().repeat(n)) } } @@ -984,9 +1000,9 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & } ascii_prefix_len += N; - // ignore-tidy-undocumented-unsafe + // SAFETY: checked in loop condition. slice = unsafe { slice.get_unchecked(N..) }; - // ignore-tidy-undocumented-unsafe + // SAFETY: out_slice has at least same length as input slice. out_slice = unsafe { out_slice.get_unchecked_mut(N..) }; } @@ -1001,9 +1017,9 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & *out_slice.get_unchecked_mut(0) = MaybeUninit::new(convert(&byte)); } ascii_prefix_len += 1; - // ignore-tidy-undocumented-unsafe + // SAFETY: slice has at least one byte, so slicing from 1.. is safe slice = unsafe { slice.get_unchecked(1..) }; - // ignore-tidy-undocumented-unsafe + // SAFETY: out_slice has at least same length as input slice out_slice = unsafe { out_slice.get_unchecked_mut(1..) }; } @@ -1024,6 +1040,11 @@ pub unsafe fn convert_while_ascii(s: &str, convert: fn(&u8) -> u8) -> (String, & #[allow(dead_code)] /// Faster implementation of string replacement for ASCII to ASCII cases. /// Should produce fast vectorized code. +/// +/// # Safety +/// +/// * `utf8_bytes` must contain valid UTF-8. +/// * Both `from` and `to` must be ASCII bytes (at most `0x7F`). unsafe fn replace_ascii(utf8_bytes: &[u8], from: u8, to: u8) -> String { let result: Vec = utf8_bytes.iter().map(|b| if *b == from { to } else { *b }).collect(); // SAFETY: We replaced ascii with ascii on valid utf8 strings. From b6d0fb14576c72e11f0754c6f457ab0341817a8b Mon Sep 17 00:00:00 2001 From: dianne Date: Fri, 11 Sep 2026 09:39:50 -0700 Subject: [PATCH 0965/1309] select: prefer impl candidates over where clauses --- .../rustc_trait_selection/src/solve/select.rs | 15 ++++++++-- ...tin-impl-over-where-clause-in-const-pat.rs | 26 +++++++++++++++++ ...ser-impl-over-where-clause-in-const-pat.rs | 29 +++++++++++++++++++ 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs create mode 100644 tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs diff --git a/compiler/rustc_trait_selection/src/solve/select.rs b/compiler/rustc_trait_selection/src/solve/select.rs index 53b999e4e5244..f41808df8a5b2 100644 --- a/compiler/rustc_trait_selection/src/solve/select.rs +++ b/compiler/rustc_trait_selection/src/solve/select.rs @@ -2,7 +2,7 @@ use std::ops::ControlFlow; use rustc_infer::infer::InferCtxt; use rustc_infer::traits::solve::inspect::ProbeKind; -use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal}; +use rustc_infer::traits::solve::{CandidateSource, Certainty, Goal, ParamEnvSource}; use rustc_infer::traits::{ BuiltinImplSource, ImplSource, ImplSourceUserDefinedData, Obligation, ObligationCause, PolyTraitObligation, Selection, SelectionError, SelectionResult, @@ -93,8 +93,8 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( victim: &inspect::InspectCandidate<'_, 'tcx>, other: &inspect::InspectCandidate<'_, 'tcx>, ) -> bool { - // Don't winnow until `Certainty::Yes` -- we don't need to winnow until - // codegen, and only on the good path. + // Don't winnow until `Certainty::Yes` -- we don't need to winnow until constant evaluation or + // codegen. if matches!(other.result().unwrap(), Certainty::Maybe(_)) { return false; } @@ -137,6 +137,15 @@ fn candidate_should_be_dropped_in_favor_of<'tcx>( victim.goal().infcx().tcx.specializes((other_def_id, victim_def_id)) } + // Prefer impl candidates over global where clause candidates. Unless `generic_const_args` + // is enabled, we currently don't use an empty environment when resolving and evaluating + // constants to lower them to patterns. If we don't drop where clause candidates here, we + // can fail to select impl candidates (#162331). + ( + CandidateSource::ParamEnv(ParamEnvSource::Global), + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_), + ) => true, + _ => false, } } diff --git a/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs b/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs new file mode 100644 index 0000000000000..e774bef50c123 --- /dev/null +++ b/tests/ui/trait-bounds/prefer-builtin-impl-over-where-clause-in-const-pat.rs @@ -0,0 +1,26 @@ +//! Regression test adjacent to +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +#![feature(const_trait_impl)] +#![feature(const_clone)] + +// At the time of writing, `ZERO` is evaluated in an environment containing `g`'s `(u8,): Clone` +// clause. In the new solver, this wasn't dropped in favor of the built-in `(u8,): Clone` impl when +// resolving an instance for `<(u8,) as Clone>::clone`, which resulted in ambiguity. + +const ZERO: (u8,) = (0,).clone(); + +fn g() +where + (u8,): Clone, +{ + match (0,) { + ZERO => {} + _ => {} + } +} + +fn main() {} diff --git a/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs b/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs new file mode 100644 index 0000000000000..e2c27d4f90e11 --- /dev/null +++ b/tests/ui/trait-bounds/prefer-user-impl-over-where-clause-in-const-pat.rs @@ -0,0 +1,29 @@ +//! Regression test for +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver +//@ check-pass + +// At the time of writing, when resolving an instance for `::N`, the environment +// contains `f`'s `u8: Trait` clause. The old solver dropped the where clause candidate in favor of +// the `impl Trait for u8` candidate, but the new solver didn't, which resulted in ambiguity. + +pub trait Trait { + const N: usize; +} + +impl Trait for u8 { + const N: usize = 0; +} + +pub fn f() +where + u8: Trait, +{ + match 0 { + ::N => {} + _ => {} + } +} + +fn main() {} From 67cb4ce2794995b6d1561766251e03153230aef9 Mon Sep 17 00:00:00 2001 From: Jason Gerard DeRose Date: Mon, 28 Sep 2026 09:47:35 -0600 Subject: [PATCH 0966/1309] Add .seek_read_buf_exact() to std::os::windows::fs::FileExt --- library/std/src/fs/tests.rs | 37 +++++++++++++++++++++ library/std/src/os/windows/fs.rs | 56 ++++++++++++++++++++++++++++++++ 2 files changed, 93 insertions(+) diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 250109f277dab..db9a9f3f20b88 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -1075,6 +1075,43 @@ fn test_seek_read_buf() { check!(fs::remove_file(&filename)); } +#[test] +#[cfg(windows)] +fn test_seek_read_buf_exact() { + use crate::os::windows::fs::FileExt; + + let tmpdir = tmpdir(); + let filename = tmpdir.join("file_rt_io_file_test_seek_read_buf_exact.txt"); + { + let oo = OpenOptions::new().create_new(true).write(true).read(true).clone(); + let mut file = check!(oo.open(&filename)); + check!(file.write_all(b"0123456789")); + } + { + let mut file = check!(File::open(&filename)); + let mut buf: [MaybeUninit; 5] = [MaybeUninit::uninit(); 5]; + let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + + // Exact read + check!(file.seek_read_buf_exact(buf.unfilled(), 2)); + assert_eq!(buf.filled(), b"23456"); + assert_eq!(check!(file.stream_position()), 7); + + // Already full + check!(file.seek_read_buf_exact(buf.unfilled(), 3)); + assert_eq!(check!(file.stream_position()), 7); + check!(file.seek_read_buf_exact(buf.unfilled(), 10)); // No call to seek_read() + assert_eq!(buf.filled(), b"23456"); + assert_eq!(check!(file.stream_position()), 7); + + // Non-empty exact read past eof fails + let err = file.seek_read_buf_exact(buf.clear().unfilled(), 6).unwrap_err(); + assert_eq!(err.kind(), ErrorKind::UnexpectedEof); + assert_eq!(check!(file.stream_position()), 10); + } + check!(fs::remove_file(&filename)); +} + #[test] fn file_test_read_buf() { let tmpdir = tmpdir(); diff --git a/library/std/src/os/windows/fs.rs b/library/std/src/os/windows/fs.rs index 3e6a934f318b2..bc3dae156ede4 100644 --- a/library/std/src/os/windows/fs.rs +++ b/library/std/src/os/windows/fs.rs @@ -152,6 +152,62 @@ pub trait FileExt { io::default_read_buf(|b| self.seek_read(b, offset), buf) } + /// Seeks to a given position and reads the exact number of bytes required to fill `buf`. + /// + /// This is equivalent to the [`seek_read_exact`](FileExt::seek_read_exact) method, except + /// that it is passed a [`BorrowedCursor`] rather than `&mut [u8]` to allow use with + /// uninitialized buffers. The new data will be appended to any existing contents of `buf`. + /// + /// Reading beyond the end of the file will always succeed without reading any bytes. + /// + /// # Examples + /// + #[cfg_attr(windows, doc = "```no_run")] + #[cfg_attr(not(windows), doc = "```ignore (needs windows)")] + /// #![feature(core_io_borrowed_buf)] + /// #![feature(seek_read_exact_seek_write_all)] + /// + /// use std::io; + /// use std::io::BorrowedBuf; + /// use std::fs::File; + /// use std::mem::MaybeUninit; + /// use std::os::windows::prelude::*; + /// + /// fn main() -> io::Result<()> { + /// let mut file = File::open("pi.txt")?; + /// + /// // Read some bytes starting from offset 2 + /// let mut buf: [MaybeUninit; 10] = [MaybeUninit::uninit(); 10]; + /// let mut buf = BorrowedBuf::from(buf.as_mut_slice()); + /// file.seek_read_buf_exact(buf.unfilled(), 2)?; + /// + /// assert!(buf.filled().starts_with(b"1")); + /// + /// Ok(()) + /// } + /// ``` + #[unstable(feature = "seek_read_exact_seek_write_all", issue = "162868")] + fn seek_read_buf_exact( + &self, + mut buf: BorrowedCursor<'_, u8>, + mut offset: u64, + ) -> io::Result<()> { + while buf.capacity() > 0 { + let prev_written = buf.written(); + match self.seek_read_buf(buf.reborrow(), offset) { + Ok(()) => {} + Err(e) if e.is_interrupted() => {} + Err(e) => return Err(e), + } + let n = buf.written() - prev_written; + offset += n as u64; + if n == 0 { + return Err(io::Error::READ_EXACT_EOF); + } + } + Ok(()) + } + /// Seeks to a given position and writes a number of bytes. /// /// Returns the number of bytes written. From f06caa3a0d7b9f1b4fad0b12fc4834f284567f69 Mon Sep 17 00:00:00 2001 From: Toni Peter Date: Mon, 21 Sep 2026 17:17:40 +0200 Subject: [PATCH 0967/1309] Add regression test for lifetimes preceding types in generics --- ...lifetime-preceding-type-in-generic-args.rs | 29 ++++++++++ ...time-preceding-type-in-generic-args.stderr | 54 +++++++++++++++++++ 2 files changed, 83 insertions(+) create mode 100644 tests/ui/parser/lifetime-preceding-type-in-generic-args.rs create mode 100644 tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr diff --git a/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs b/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs new file mode 100644 index 0000000000000..9c36f619546be --- /dev/null +++ b/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs @@ -0,0 +1,29 @@ +// Regression test for #59325, specifically for ampersand-less lifetimes in generics. +// Similar tests outside of generics are in recover/recover-ampersand-less-ref-ty.rs. +struct T1; +struct T2; + +struct Foo(T); +struct Bar(T1, T2); + +struct A1 { + x: Foo<'static T1>, //~ERROR expected one of `,` or `>` + //~^ HELP you might have meant to end the type parameters here +} + +struct A2 { + x: Foo<'static mut T1>, //~ERROR expected one of `,` or `>` + //~^ HELP you might have meant to end the type parameters here +} + +struct A3 { + x: Bar<'static T1, T2>, //~ERROR expected one of `,` or `>` + //~^ HELP you might have meant to end the type parameters here +} + +struct A4 { + x: Bar, //~ERROR expected one of `,` or `>` + //~^ HELP you might have meant to end the type parameters here +} + +fn main() {} diff --git a/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr b/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr new file mode 100644 index 0000000000000..1d0d863847f9b --- /dev/null +++ b/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr @@ -0,0 +1,54 @@ +error: expected one of `,` or `>`, found `T1` + --> $DIR/lifetime-preceding-type-in-generic-args.rs:10:20 + | +LL | struct A1 { + | -- while parsing this struct +LL | x: Foo<'static T1>, + | ^^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | x: Foo<'static> T1>, + | + + +error: expected one of `,` or `>`, found keyword `mut` + --> $DIR/lifetime-preceding-type-in-generic-args.rs:15:20 + | +LL | struct A2 { + | -- while parsing this struct +LL | x: Foo<'static mut T1>, + | ^^^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | x: Foo<'static> mut T1>, + | + + +error: expected one of `,` or `>`, found `T1` + --> $DIR/lifetime-preceding-type-in-generic-args.rs:20:20 + | +LL | struct A3 { + | -- while parsing this struct +LL | x: Bar<'static T1, T2>, + | ^^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | x: Bar<'static> T1, T2>, + | + + +error: expected one of `,` or `>`, found `T2` + --> $DIR/lifetime-preceding-type-in-generic-args.rs:25:24 + | +LL | struct A4 { + | -- while parsing this struct +LL | x: Bar, + | ^^ expected one of `,` or `>` + | +help: you might have meant to end the type parameters here + | +LL | x: Bar T2>, + | + + +error: aborting due to 4 previous errors + From ca5f5405898e9caae1d2e516c89f2f74b7ccc065 Mon Sep 17 00:00:00 2001 From: Toni Peter Date: Mon, 28 Sep 2026 14:43:28 +0200 Subject: [PATCH 0968/1309] Improve suggestions for lifetimes preceding types in generics --- .../rustc_parse/src/parser/diagnostics.rs | 38 +++++++++++++++++++ compiler/rustc_parse/src/parser/path.rs | 16 +++++--- compiler/rustc_parse/src/parser/ty.rs | 25 ++++++++---- tests/ui/parser/issues/issue-20616-2.stderr | 8 +++- tests/ui/parser/issues/issue-93867.stderr | 8 +++- ...lifetime-preceding-type-in-generic-args.rs | 11 ++++-- ...time-preceding-type-in-generic-args.stderr | 36 ++++++++++++------ 7 files changed, 108 insertions(+), 34 deletions(-) diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index bb8be3c9c509f..36764a0477baa 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2286,6 +2286,44 @@ impl<'a> Parser<'a> { } } + /// Handle encountering a lifetime in a generic argument list that is not + /// followed by a `,` or `>`. + /// We emit an error and check if the lifetime is followed by a type + /// in, e.g. `Foo<'a T>`. + /// In this case, it is likely the user meant either `Foo<&'a T>` or `Foo<'a, T>`. + /// We give both suggestions, then emit an error. Note that we do not try to recover, + /// since we cannot know which of the two suggestions is correct and emitting either + /// of the two types could cause confusing errors further on. + pub(super) fn handle_lifetime_arg_preceding_type(&mut self, span: Span) -> PResult<'a, ()> { + let snapshot = self.create_snapshot_for_diagnostic(); + let (mutbl, ty) = self.parse_ref_ty_no_leading_ampersand(); + self.restore_snapshot(snapshot); + if ty.is_none() { + // The lifetime is not followed by a type, do nothing. + return Ok(()); + } + // If we find `'a mut T`, suggesting to add a comma is wrong. + let suggest_comma = mutbl.is_not(); + // Add `>` to the list of expected tokens. + self.check(exp!(Gt)); + let mut err = self.unexpected().unwrap_err(); + err.span_suggestion_verbose( + span.shrink_to_lo(), + "you might have meant to write a reference type here", + "&", + Applicability::MaybeIncorrect, + ); + if suggest_comma { + err.span_suggestion_verbose( + span.shrink_to_hi(), + "use a comma to separate type parameters", + ",", + Applicability::MaybeIncorrect, + ); + } + Err(err.into()) + } + /// Handle encountering a symbol in a generic argument list that is not a `,` or `>`. In this /// case, we emit an error and try to suggest enclosing a const argument in braces if it looks /// like the user has forgotten them. diff --git a/compiler/rustc_parse/src/parser/path.rs b/compiler/rustc_parse/src/parser/path.rs index 0ac12d6f392b2..0816b543d27da 100644 --- a/compiler/rustc_parse/src/parser/path.rs +++ b/compiler/rustc_parse/src/parser/path.rs @@ -705,12 +705,16 @@ impl<'a> Parser<'a> { err.emit(); continue; } - if !self.token.kind.should_end_const_arg() - && self.handle_ambiguous_unbraced_const_arg(&mut args)? - { - // We've managed to (partially) recover, so continue trying to parse - // arguments. - continue; + if !self.token.kind.should_end_const_arg() { + if let Some(arg @ AngleBracketedArg::Arg(GenericArg::Lifetime(_))) = args.last() + { + self.handle_lifetime_arg_preceding_type(arg.span())?; + } + if self.handle_ambiguous_unbraced_const_arg(&mut args)? { + // We've managed to (partially) recover, so continue trying to parse + // arguments. + continue; + } } break; } diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs index 5450d23fbbc2e..2d97d46beaaa8 100644 --- a/compiler/rustc_parse/src/parser/ty.rs +++ b/compiler/rustc_parse/src/parser/ty.rs @@ -545,6 +545,17 @@ impl<'a> Parser<'a> { )) } + pub(super) fn parse_ref_ty_no_leading_ampersand(&mut self) -> (Mutability, Option>) { + let mutbl = self.parse_mutability(); + match self.parse_ty_no_plus() { + Ok(ty) => (mutbl, Some(ty)), + Err(err) => { + err.cancel(); + (mutbl, None) + } + } + } + fn maybe_recover_ref_ty_no_leading_ampersand<'cx>( &mut self, lt: Lifetime, @@ -555,9 +566,12 @@ impl<'a> Parser<'a> { return Err(err); } let snapshot = self.create_snapshot_for_diagnostic(); - let mutbl = self.parse_mutability(); - match self.parse_ty_no_plus() { - Ok(ty) => { + match self.parse_ref_ty_no_leading_ampersand() { + (_, None) => { + self.restore_snapshot(snapshot); + Err(err) + } + (mutbl, Some(ty)) => { err.span_suggestion_verbose( lo.shrink_to_lo(), "you might have meant to write a reference type here", @@ -567,11 +581,6 @@ impl<'a> Parser<'a> { err.emit(); Ok(TyKind::Ref(Some(lt), MutTy { ty, mutbl })) } - Err(diag) => { - diag.cancel(); - self.restore_snapshot(snapshot); - Err(err) - } } } diff --git a/tests/ui/parser/issues/issue-20616-2.stderr b/tests/ui/parser/issues/issue-20616-2.stderr index 038b2ffc72b39..ae9dfa2344f32 100644 --- a/tests/ui/parser/issues/issue-20616-2.stderr +++ b/tests/ui/parser/issues/issue-20616-2.stderr @@ -4,9 +4,13 @@ error: expected one of `,` or `>`, found `(` LL | type Type_2 = Type_1_<'static ()>; | ^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here | -LL | type Type_2 = Type_1_<'static> ()>; +LL | type Type_2 = Type_1_<&'static ()>; + | + +help: use a comma to separate type parameters + | +LL | type Type_2 = Type_1_<'static, ()>; | + error: aborting due to 1 previous error diff --git a/tests/ui/parser/issues/issue-93867.stderr b/tests/ui/parser/issues/issue-93867.stderr index c653c8dd4a424..35204660d8a1c 100644 --- a/tests/ui/parser/issues/issue-93867.stderr +++ b/tests/ui/parser/issues/issue-93867.stderr @@ -4,9 +4,13 @@ error: expected one of `,` or `>`, found `K` LL | pub fn entry<'a, K, V>() -> Entry<'a K, V> { | ^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here | -LL | pub fn entry<'a, K, V>() -> Entry<'a> K, V> { +LL | pub fn entry<'a, K, V>() -> Entry<&'a K, V> { + | + +help: use a comma to separate type parameters + | +LL | pub fn entry<'a, K, V>() -> Entry<'a, K, V> { | + error: aborting due to 1 previous error diff --git a/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs b/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs index 9c36f619546be..3ec9fabb15ed9 100644 --- a/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs +++ b/tests/ui/parser/lifetime-preceding-type-in-generic-args.rs @@ -8,22 +8,25 @@ struct Bar(T1, T2); struct A1 { x: Foo<'static T1>, //~ERROR expected one of `,` or `>` - //~^ HELP you might have meant to end the type parameters here + //~^ HELP you might have meant to write a reference type here + //~| HELP use a comma to separate type parameters } struct A2 { x: Foo<'static mut T1>, //~ERROR expected one of `,` or `>` - //~^ HELP you might have meant to end the type parameters here + //~^ HELP you might have meant to write a reference type here } struct A3 { x: Bar<'static T1, T2>, //~ERROR expected one of `,` or `>` - //~^ HELP you might have meant to end the type parameters here + //~^ HELP you might have meant to write a reference type here + //~| HELP use a comma to separate type parameters } struct A4 { x: Bar, //~ERROR expected one of `,` or `>` - //~^ HELP you might have meant to end the type parameters here + //~^ HELP you might have meant to write a reference type here + //~| HELP use a comma to separate type parameters } fn main() {} diff --git a/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr b/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr index 1d0d863847f9b..0c2db58b3ec77 100644 --- a/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr +++ b/tests/ui/parser/lifetime-preceding-type-in-generic-args.stderr @@ -6,48 +6,60 @@ LL | struct A1 { LL | x: Foo<'static T1>, | ^^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here | -LL | x: Foo<'static> T1>, +LL | x: Foo<&'static T1>, + | + +help: use a comma to separate type parameters + | +LL | x: Foo<'static, T1>, | + error: expected one of `,` or `>`, found keyword `mut` - --> $DIR/lifetime-preceding-type-in-generic-args.rs:15:20 + --> $DIR/lifetime-preceding-type-in-generic-args.rs:16:20 | LL | struct A2 { | -- while parsing this struct LL | x: Foo<'static mut T1>, | ^^^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here | -LL | x: Foo<'static> mut T1>, - | + +LL | x: Foo<&'static mut T1>, + | + error: expected one of `,` or `>`, found `T1` - --> $DIR/lifetime-preceding-type-in-generic-args.rs:20:20 + --> $DIR/lifetime-preceding-type-in-generic-args.rs:21:20 | LL | struct A3 { | -- while parsing this struct LL | x: Bar<'static T1, T2>, | ^^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here | -LL | x: Bar<'static> T1, T2>, +LL | x: Bar<&'static T1, T2>, + | + +help: use a comma to separate type parameters + | +LL | x: Bar<'static, T1, T2>, | + error: expected one of `,` or `>`, found `T2` - --> $DIR/lifetime-preceding-type-in-generic-args.rs:25:24 + --> $DIR/lifetime-preceding-type-in-generic-args.rs:27:24 | LL | struct A4 { | -- while parsing this struct LL | x: Bar, | ^^ expected one of `,` or `>` | -help: you might have meant to end the type parameters here +help: you might have meant to write a reference type here + | +LL | x: Bar, + | + +help: use a comma to separate type parameters | -LL | x: Bar T2>, +LL | x: Bar, | + error: aborting due to 4 previous errors From 5931727a13e08bdb8a7b60b65f37f283285a2d8c Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Fri, 28 Aug 2026 12:58:33 +0200 Subject: [PATCH 0969/1309] add `Div` and `Mul` for `Complex<{float}>` --- ...oot_tests-Disable-complex-type-tests.patch | 32 ++++++++++ library/core/src/num/complex.rs | 54 ++++++++++++++++- library/core/src/num/imp/libm.rs | 21 +++++++ library/coretests/tests/num/complex.rs | 60 +++++++++++++++++++ 4 files changed, 166 insertions(+), 1 deletion(-) create mode 100644 compiler/rustc_codegen_cranelift/patches/0029-sysroot_tests-Disable-complex-type-tests.patch diff --git a/compiler/rustc_codegen_cranelift/patches/0029-sysroot_tests-Disable-complex-type-tests.patch b/compiler/rustc_codegen_cranelift/patches/0029-sysroot_tests-Disable-complex-type-tests.patch new file mode 100644 index 0000000000000..d27810a988492 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0029-sysroot_tests-Disable-complex-type-tests.patch @@ -0,0 +1,32 @@ +From 20d296e9a8b837e586fcc8fc648d4ab9687a2a47 Mon Sep 17 00:00:00 2001 +From: Folkert de Vries +Date: Mon, 28 Sep 2026 19:14:22 +0200 +Subject: [PATCH] sysroot_tests: Disable complex type tests + +--- + coretests/tests/num/complex.rs | 2 ++ + 1 file changed, 2 insertions(+) + +diff --git a/coretests/tests/num/complex.rs b/coretests/tests/num/complex.rs +index d73d04b1afc..289c0baec17 100644 +--- a/coretests/tests/num/complex.rs ++++ b/coretests/tests/num/complex.rs +@@ -75,6 +75,7 @@ fn complex_negation() { + } + + #[test] ++#[cfg_attr(target_os = "windows", ignore = "hits an ABI issue with cranelift on windows")] + fn complex_multiplication() { + #[cfg(target_has_reliable_f16)] + assert_eq!(Complex::new(1.0f16, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); +@@ -105,6 +106,7 @@ fn complex_multiplication() { + } + + #[test] ++#[cfg_attr(target_os = "windows", ignore = "hits an ABI issue with cranelift on windows")] + fn complex_div() { + #[cfg(target_has_reliable_f16)] + assert_eq!(Complex::new(2.0f16, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); +-- +2.43.0 + diff --git a/library/core/src/num/complex.rs b/library/core/src/num/complex.rs index 66126c52fadad..c6a56285cdfb1 100644 --- a/library/core/src/num/complex.rs +++ b/library/core/src/num/complex.rs @@ -1,4 +1,5 @@ -use crate::ops::{Add, Neg, Sub}; +use crate::num::imp::libm::complex::*; +use crate::ops::{Add, Div, Mul, Neg, Sub}; /// A complex number. #[derive(Clone, Copy, Debug, PartialEq, Eq)] @@ -91,3 +92,54 @@ impl> Sub for Complex { Complex::new(self.re - rhs, self.im) } } + +macro_rules! impl_complex_mul_div { + ($ty:ty, $mul:ident, $div:ident) => { + #[unstable(feature = "complex_numbers", issue = "154023")] + impl Mul for Complex<$ty> { + type Output = Self; + + #[inline] + fn mul(self, rhs: Self) -> Self::Output { + let Complex { re: a, im: b } = self; + let Complex { re: c, im: d } = rhs; + + let ac = a * c; + let bd = b * d; + let ad = a * d; + let bc = b * c; + + let z = Complex::new(ac - bd, ad + bc); + + // Only call the libcall when both components are NaN. + // + // The naive algorithm would return NaN + NaNi for an input like + // (1 + 0i) * (inf + infi). The libcall instead returns inf + infi. + // + // We duplicate the fast path here so that it can be inlined. We use a libcall + // for the NaN correction to reduce the size of `core`. + if z.re.is_nan() && z.im.is_nan() { + crate::hint::cold_path(); + $mul(a, b, c, d) + } else { + z + } + } + } + + #[unstable(feature = "complex_numbers", issue = "154023")] + impl Div for Complex<$ty> { + type Output = Self; + + #[inline] + fn div(self, rhs: Self) -> Self::Output { + $div(self.re, self.im, rhs.re, rhs.im) + } + } + }; +} + +impl_complex_mul_div!(f16, __rust_mulhc3, __rust_divhc3); +impl_complex_mul_div!(f32, __mulsc3, __divsc3); +impl_complex_mul_div!(f64, __muldc3, __divdc3); +impl_complex_mul_div!(f128, __rust_multc3, __rust_divtc3); diff --git a/library/core/src/num/imp/libm.rs b/library/core/src/num/imp/libm.rs index a8d6bdc0b5d7c..6ce02ad60a5df 100644 --- a/library/core/src/num/imp/libm.rs +++ b/library/core/src/num/imp/libm.rs @@ -76,6 +76,27 @@ unsafe extern "C" { pub(crate) safe fn truncf16(x: f16) -> f16; } +/// These symbols are always provided by compiler-builtins. +pub(crate) mod complex { + use crate::num::Complex; + + unsafe extern "C" { + pub(crate) safe fn __mulsc3(a: f32, b: f32, c: f32, d: f32) -> Complex; + pub(crate) safe fn __muldc3(a: f64, b: f64, c: f64, d: f64) -> Complex; + + pub(crate) safe fn __divsc3(a: f32, b: f32, c: f32, d: f32) -> Complex; + pub(crate) safe fn __divdc3(a: f64, b: f64, c: f64, d: f64) -> Complex; + } + + unsafe extern "Rust" { + pub(crate) safe fn __rust_mulhc3(a: f16, b: f16, c: f16, d: f16) -> Complex; + pub(crate) safe fn __rust_multc3(a: f128, b: f128, c: f128, d: f128) -> Complex; + + pub(crate) safe fn __rust_divhc3(a: f16, b: f16, c: f16, d: f16) -> Complex; + pub(crate) safe fn __rust_divtc3(a: f128, b: f128, c: f128, d: f128) -> Complex; + } +} + /// These symbols will be available when `std` is available, and on many no-std platforms. However, /// since this isn't a guarantee, we cannot rely on them for stable implementations. pub(crate) mod likely_available { diff --git a/library/coretests/tests/num/complex.rs b/library/coretests/tests/num/complex.rs index c22c5b9575b3d..d73d04b1afc98 100644 --- a/library/coretests/tests/num/complex.rs +++ b/library/coretests/tests/num/complex.rs @@ -73,3 +73,63 @@ fn complex_negation() { assert_eq!(-Complex::new(1.0, -2.0), Complex::new(-1.0, 2.0)); assert_eq!(-Complex::new(1.0, f32::INFINITY), Complex::new(-1.0, f32::NEG_INFINITY),); } + +#[test] +fn complex_multiplication() { + #[cfg(target_has_reliable_f16)] + assert_eq!(Complex::new(1.0f16, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); + assert_eq!(Complex::new(1.0f32, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); + assert_eq!(Complex::new(1.0f64, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); + #[cfg(target_has_reliable_f128)] + assert_eq!(Complex::new(1.0f128, 2.0) * Complex::new(3.0, 4.0), Complex::new(-5.0, 10.0)); + + // The naive algorithm would return NaN + NaNi for these inputs, but the libcall handles it. + #[cfg(target_has_reliable_f16)] + assert_eq!( + Complex::new(1.0, 0.0) * Complex::new(f16::INFINITY, f16::INFINITY), + Complex::new(f16::INFINITY, f16::INFINITY) + ); + assert_eq!( + Complex::new(1.0, 0.0) * Complex::new(f32::INFINITY, f32::INFINITY), + Complex::new(f32::INFINITY, f32::INFINITY) + ); + assert_eq!( + Complex::new(1.0, 0.0) * Complex::new(f64::INFINITY, f64::INFINITY), + Complex::new(f64::INFINITY, f64::INFINITY) + ); + #[cfg(target_has_reliable_f128)] + assert_eq!( + Complex::new(1.0, 0.0) * Complex::new(f128::INFINITY, f128::INFINITY), + Complex::new(f128::INFINITY, f128::INFINITY) + ); +} + +#[test] +fn complex_div() { + #[cfg(target_has_reliable_f16)] + assert_eq!(Complex::new(2.0f16, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); + assert_eq!(Complex::new(2.0f32, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); + assert_eq!(Complex::new(2.0f64, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); + #[cfg(target_has_reliable_f128)] + assert_eq!(Complex::new(2.0f128, 11.0) / Complex::new(2.0, 1.0), Complex::new(3.0, 4.0)); + + // The naive algorithm would return NaN + NaNi for these inputs, but the libcall handles it. + #[cfg(target_has_reliable_f16)] + assert_eq!( + Complex::new(f16::INFINITY, 0.0) / Complex::new(1.0, 1.0), + Complex::new(f16::INFINITY, f16::NEG_INFINITY) + ); + assert_eq!( + Complex::new(f32::INFINITY, 0.0) / Complex::new(1.0, 1.0), + Complex::new(f32::INFINITY, f32::NEG_INFINITY) + ); + assert_eq!( + Complex::new(f64::INFINITY, 0.0) / Complex::new(1.0, 1.0), + Complex::new(f64::INFINITY, f64::NEG_INFINITY) + ); + #[cfg(target_has_reliable_f128)] + assert_eq!( + Complex::new(f128::INFINITY, 0.0) / Complex::new(1.0, 1.0), + Complex::new(f128::INFINITY, f128::NEG_INFINITY) + ); +} From 48b2592ad8bdbcba6a5585dd39d560bf4a2e3ca1 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 28 Sep 2026 10:31:49 +0200 Subject: [PATCH 0970/1309] do not complain about unstable target features on nightly --- .../rustc_codegen_ssa/src/target_features.rs | 6 +- compiler/rustc_session/src/session.rs | 4 ++ src/doc/rustc-dev-guide/src/tests/misc.md | 13 ++-- .../run-make/unstable-target-feature/rmake.rs | 20 ++++++ .../unstable-target-feature.rs | 2 + .../unstable-target-feature.stderr | 8 +++ ...cv-discoverability-guidance.riscv32.stderr | 12 +--- ...cv-discoverability-guidance.riscv64.stderr | 12 +--- .../ui/abi/riscv-discoverability-guidance.rs | 5 -- tests/ui/abi/sparcv8plus.rs | 1 - tests/ui/abi/sparcv8plus.sparc.stderr | 2 +- tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr | 2 +- ...cv8plus.sparc_cpu_v9_feature_v8plus.stderr | 10 +-- .../sparcv8plus.sparc_feature_v8plus.stderr | 10 +-- tests/ui/abi/sparcv8plus.sparcv8plus.stderr | 2 +- tests/ui/asm/hexagon-register-pairs.rs | 2 - tests/ui/asm/hexagon-register-pairs.stderr | 12 +--- tests/ui/asm/hexagon/bad-reg.rs | 2 - tests/ui/asm/hexagon/bad-reg.stderr | 64 +++++++++---------- tests/ui/asm/mips/reg-conflict.mips32.stderr | 18 +----- .../ui/asm/mips/reg-conflict.mips32r6.stderr | 18 +----- tests/ui/asm/mips/reg-conflict.mips64.stderr | 18 +----- .../ui/asm/mips/reg-conflict.mips64r6.stderr | 18 +----- tests/ui/asm/mips/reg-conflict.rs | 2 - ...-irrelevant-target-feature-flag-disable.rs | 2 - ...elevant-target-feature-flag-disable.stderr | 8 --- ...bi-required-target-feature-flag-disable.rs | 1 - ...red-target-feature-flag-disable.x86.stderr | 8 +-- .../feature-hierarchy.hexagon-hvxv66.stderr | 8 --- .../feature-hierarchy.hexagon-v60.stderr | 8 --- .../feature-hierarchy.hexagon-v68.stderr | 8 --- tests/ui/target-feature/feature-hierarchy.rs | 4 -- .../packedstack-combinations.rs | 2 - ...edstack-combinations.with_softfloat.stderr | 8 --- tests/ui/target-feature/unstable-feature.rs | 8 --- .../ui/target-feature/unstable-feature.stderr | 8 --- 36 files changed, 100 insertions(+), 236 deletions(-) create mode 100644 tests/run-make/unstable-target-feature/rmake.rs create mode 100644 tests/run-make/unstable-target-feature/unstable-target-feature.rs create mode 100644 tests/run-make/unstable-target-feature/unstable-target-feature.stderr delete mode 100644 tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr delete mode 100644 tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr delete mode 100644 tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr delete mode 100644 tests/ui/target-feature/unstable-feature.rs delete mode 100644 tests/ui/target-feature/unstable-feature.stderr diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs index b630155c144ea..301195efb9a8f 100644 --- a/compiler/rustc_codegen_ssa/src/target_features.rs +++ b/compiler/rustc_codegen_ssa/src/target_features.rs @@ -383,8 +383,10 @@ pub fn internal_target_features<'a, const N: usize>( } else { sess.dcx().emit_warn(diag); } - } else if stability.requires_nightly(/* in_cfg */ false).is_some() { - // An unstable feature. Warn about using it. It makes little sense + } else if stability.requires_nightly(/* in_cfg */ false).is_some() + && !sess.is_nightly_build() + { + // An unstable feature. Warn about using it on stable. It makes little sense // to hard-error here since we just warn about fully unknown // features above. let note = if stability.is_cfg_stable_toggle_unstable() { diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs index 060e614e82180..3180d8ca5d10c 100644 --- a/compiler/rustc_session/src/session.rs +++ b/compiler/rustc_session/src/session.rs @@ -427,6 +427,10 @@ impl EarlySession { pub fn merge_functions(&self) -> MergeFunctions { self.opts.unstable_opts.merge_functions.unwrap_or(self.target.merge_functions) } + + pub fn is_nightly_build(&self) -> bool { + self.opts.unstable_features.is_nightly_build() + } } /// Some info about the backend, returned by `CodegenBackend::init` and put into the `Session`. diff --git a/src/doc/rustc-dev-guide/src/tests/misc.md b/src/doc/rustc-dev-guide/src/tests/misc.md index 34f9faa9cc722..8fe49c82e9873 100644 --- a/src/doc/rustc-dev-guide/src/tests/misc.md +++ b/src/doc/rustc-dev-guide/src/tests/misc.md @@ -12,15 +12,10 @@ This is a bootstrap/compiler implementation detail, but it can also be useful fo This is useful because some behaviors of the compiler (e.g. diagnostics) can differ depending on whether the compiler is nightly or not. -In `ui` tests and other test suites that support `//@ rustc-env`, you can specify - -```rust,ignore -// Force unstable features to be usable on stable rustc -//@ rustc-env:RUSTC_BOOTSTRAP=1 - -// Or force nightly rustc to pretend it is a stable rustc -//@ rustc-env:RUSTC_BOOTSTRAP=-1 -``` +Note that setting `RUSTC_BOOTSTRAP` in ui tests (e.g. via `//@ rustc-env`) is pointless since ui +tests inherit the bootstrap env var from bootstrap (so it's set to `1` by default), and since +compiletest itself passes `-Z` flags (so `-1` breaks the test). To test stable-only behavior, you +need to write a `run-make` test instead. For `run-make`/`run-make-cargo` tests, `//@ rustc-env` is not supported. You can do something like the following for individual `rustc` invocations. diff --git a/tests/run-make/unstable-target-feature/rmake.rs b/tests/run-make/unstable-target-feature/rmake.rs new file mode 100644 index 0000000000000..3fefe11ff791e --- /dev/null +++ b/tests/run-make/unstable-target-feature/rmake.rs @@ -0,0 +1,20 @@ +//@ only-x86_64 +// FIXME: Once GCC backend is fixed, remove this `ignore-backends`. +//@ ignore-backends: gcc + +// Ensure that on stable we don't suggest restricting with an unsafe trait and we continue +// mentioning the rest of the obligation chain. + +use run_make_support::{diff, rustc}; + +fn main() { + let out = rustc() + .env("RUSTC_BOOTSTRAP", "-1") + .input("unstable-target-feature.rs") + .args(&["-Ctarget-feature=+x87", "--crate-type=rlib"]) + .run() + .assert_stderr_not_contains("help: consider restricting type parameter `T`") + .assert_stderr_contains("unstable feature") + .stderr_utf8(); + diff().expected_file("unstable-target-feature.stderr").actual_text("(stable rustc)", &out).run() +} diff --git a/tests/run-make/unstable-target-feature/unstable-target-feature.rs b/tests/run-make/unstable-target-feature/unstable-target-feature.rs new file mode 100644 index 0000000000000..ec7318829e77e --- /dev/null +++ b/tests/run-make/unstable-target-feature/unstable-target-feature.rs @@ -0,0 +1,2 @@ +/// Tidy is unhappy if we leave the file empty. +pub fn empty() {} diff --git a/tests/run-make/unstable-target-feature/unstable-target-feature.stderr b/tests/run-make/unstable-target-feature/unstable-target-feature.stderr new file mode 100644 index 0000000000000..e4b2717f911f3 --- /dev/null +++ b/tests/run-make/unstable-target-feature/unstable-target-feature.stderr @@ -0,0 +1,8 @@ +warning: unstable feature specified for `-Ctarget-feature`: `x87` + | + = note: this feature is not stably supported; its behavior can change in the future + = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: for more information, see issue #162235 + +warning: 1 warning emitted + diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr index c618e5f63546a..0378b9daafe79 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `unaligned-scalar-mem` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error[E0703]: invalid ABI: found `riscv-interrupt` - --> $DIR/riscv-discoverability-guidance.rs:21:8 + --> $DIR/riscv-discoverability-guidance.rs:16:8 | LL | extern "riscv-interrupt" fn isr() {} | ^^^^^^^^^^^^^^^^^ invalid ABI @@ -17,7 +11,7 @@ LL | extern "riscv-interrupt-m" fn isr() {} | ++ error[E0703]: invalid ABI: found `riscv-interrupt-u` - --> $DIR/riscv-discoverability-guidance.rs:26:8 + --> $DIR/riscv-discoverability-guidance.rs:21:8 | LL | extern "riscv-interrupt-u" fn isr_U() {} | ^^^^^^^^^^^^^^^^^^^ invalid ABI @@ -29,6 +23,6 @@ LL - extern "riscv-interrupt-u" fn isr_U() {} LL + extern "riscv-interrupt-m" fn isr_U() {} | -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr index c618e5f63546a..0378b9daafe79 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr +++ b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `unaligned-scalar-mem` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error[E0703]: invalid ABI: found `riscv-interrupt` - --> $DIR/riscv-discoverability-guidance.rs:21:8 + --> $DIR/riscv-discoverability-guidance.rs:16:8 | LL | extern "riscv-interrupt" fn isr() {} | ^^^^^^^^^^^^^^^^^ invalid ABI @@ -17,7 +11,7 @@ LL | extern "riscv-interrupt-m" fn isr() {} | ++ error[E0703]: invalid ABI: found `riscv-interrupt-u` - --> $DIR/riscv-discoverability-guidance.rs:26:8 + --> $DIR/riscv-discoverability-guidance.rs:21:8 | LL | extern "riscv-interrupt-u" fn isr_U() {} | ^^^^^^^^^^^^^^^^^^^ invalid ABI @@ -29,6 +23,6 @@ LL - extern "riscv-interrupt-u" fn isr_U() {} LL + extern "riscv-interrupt-m" fn isr_U() {} | -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0703`. diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs index 9937c28030f89..86e34a44ec59a 100644 --- a/tests/ui/abi/riscv-discoverability-guidance.rs +++ b/tests/ui/abi/riscv-discoverability-guidance.rs @@ -10,11 +10,6 @@ #![no_core] #![feature(no_core, lang_items, abi_riscv_interrupt)] -//~? WARN unstable feature specified for `-Ctarget-feature` -//~? NOTE this feature is not stably supported; its behavior can change in the future -//~? NOTE previously accepted -//~? NOTE for more information, see issue - extern crate minicore; use minicore::*; diff --git a/tests/ui/abi/sparcv8plus.rs b/tests/ui/abi/sparcv8plus.rs index 93e8871c642ee..ec64eb414f2ec 100644 --- a/tests/ui/abi/sparcv8plus.rs +++ b/tests/ui/abi/sparcv8plus.rs @@ -12,7 +12,6 @@ //@[sparc_cpu_v9_feature_v8plus] needs-llvm-components: sparc //@ ignore-backends: gcc -//[sparc_feature_v8plus,sparc_cpu_v9_feature_v8plus]~? WARN unstable feature specified for `-Ctarget-feature` //[sparc_feature_v8plus,sparc_cpu_v9_feature_v8plus]~? WARN `v8plus` must be disabled #![crate_type = "rlib"] diff --git a/tests/ui/abi/sparcv8plus.sparc.stderr b/tests/ui/abi/sparcv8plus.sparc.stderr index 779bf597d6f66..718ff1ab0af52 100644 --- a/tests/ui/abi/sparcv8plus.sparc.stderr +++ b/tests/ui/abi/sparcv8plus.sparc.stderr @@ -1,5 +1,5 @@ error: -v8plus,-v9 - --> $DIR/sparcv8plus.rs:31:1 + --> $DIR/sparcv8plus.rs:30:1 | LL | compile_error!("-v8plus,-v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr index edf75ab70db15..5e5e108d74dfc 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9.stderr @@ -1,5 +1,5 @@ error: -v8plus,+v9 - --> $DIR/sparcv8plus.rs:44:1 + --> $DIR/sparcv8plus.rs:43:1 | LL | compile_error!("-v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr index 7e1d9edff230f..27545025828b5 100644 --- a/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_cpu_v9_feature_v8plus.stderr @@ -1,19 +1,13 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v8plus` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `v8plus` must be disabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:35:1 + --> $DIR/sparcv8plus.rs:34:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr index 3e9e7ff7c4a5c..5fdbdea580fef 100644 --- a/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparc_feature_v8plus.stderr @@ -1,19 +1,13 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v8plus` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `v8plus` must be disabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 error: +v8plus,-v9 (FIXME) - --> $DIR/sparcv8plus.rs:40:1 + --> $DIR/sparcv8plus.rs:39:1 | LL | compile_error!("+v8plus,-v9 (FIXME)"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -error: aborting due to 1 previous error; 2 warnings emitted +error: aborting due to 1 previous error; 1 warning emitted diff --git a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr index 37a03abae9b4b..5e1e1fa5c798f 100644 --- a/tests/ui/abi/sparcv8plus.sparcv8plus.stderr +++ b/tests/ui/abi/sparcv8plus.sparcv8plus.stderr @@ -1,5 +1,5 @@ error: +v8plus,+v9 - --> $DIR/sparcv8plus.rs:35:1 + --> $DIR/sparcv8plus.rs:34:1 | LL | compile_error!("+v8plus,+v9"); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/hexagon-register-pairs.rs b/tests/ui/asm/hexagon-register-pairs.rs index 75f2960778455..e14a80355cc14 100644 --- a/tests/ui/asm/hexagon-register-pairs.rs +++ b/tests/ui/asm/hexagon-register-pairs.rs @@ -7,8 +7,6 @@ #![crate_type = "lib"] #![no_core] -//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - extern crate minicore; use minicore::*; diff --git a/tests/ui/asm/hexagon-register-pairs.stderr b/tests/ui/asm/hexagon-register-pairs.stderr index d59d46363bdb8..6de55c34a8bc2 100644 --- a/tests/ui/asm/hexagon-register-pairs.stderr +++ b/tests/ui/asm/hexagon-register-pairs.stderr @@ -1,11 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: avoid using named labels in inline assembly - --> $DIR/hexagon-register-pairs.rs:32:15 + --> $DIR/hexagon-register-pairs.rs:30:15 | LL | asm!("label1: r7:6 = combine(#2, #3)"); | ^^^^^^ @@ -15,7 +9,7 @@ LL | asm!("label1: r7:6 = combine(#2, #3)"); = note: `#[deny(named_asm_labels)]` on by default error: avoid using named labels in inline assembly - --> $DIR/hexagon-register-pairs.rs:35:15 + --> $DIR/hexagon-register-pairs.rs:33:15 | LL | asm!("hexagon_label: nop"); | ^^^^^^^^^^^^^ @@ -23,5 +17,5 @@ LL | asm!("hexagon_label: nop"); = help: only local labels of the form `:` should be used in inline asm = note: see the asm section of Rust By Example for more information -error: aborting due to 2 previous errors; 1 warning emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/hexagon/bad-reg.rs b/tests/ui/asm/hexagon/bad-reg.rs index 6d3e1521a26cc..cbff6d3c521da 100644 --- a/tests/ui/asm/hexagon/bad-reg.rs +++ b/tests/ui/asm/hexagon/bad-reg.rs @@ -3,8 +3,6 @@ //@ needs-llvm-components: hexagon //@ ignore-backends: gcc -//~? WARN unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - #![crate_type = "lib"] #![feature(no_core, asm_experimental_arch)] #![no_core] diff --git a/tests/ui/asm/hexagon/bad-reg.stderr b/tests/ui/asm/hexagon/bad-reg.stderr index ce8f46e1b8498..5fcdd03c6b93e 100644 --- a/tests/ui/asm/hexagon/bad-reg.stderr +++ b/tests/ui/asm/hexagon/bad-reg.stderr @@ -1,95 +1,89 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvx-length128b` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: invalid register `r19`: r19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:20:18 + --> $DIR/bad-reg.rs:18:18 | LL | asm!("", out("r19") _); | ^^^^^^^^^^^^ error: invalid register `sp`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:22:18 + --> $DIR/bad-reg.rs:20:18 | LL | asm!("", out("sp") _); | ^^^^^^^^^^^ error: invalid register `r29`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:24:18 + --> $DIR/bad-reg.rs:22:18 | LL | asm!("", out("r29") _); | ^^^^^^^^^^^^ error: invalid register `r30`: the frame register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:26:18 + --> $DIR/bad-reg.rs:24:18 | LL | asm!("", out("r30") _); | ^^^^^^^^^^^^ error: invalid register `fr`: the frame register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:28:18 + --> $DIR/bad-reg.rs:26:18 | LL | asm!("", out("fr") _); | ^^^^^^^^^^^ error: invalid register `r31`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:30:18 + --> $DIR/bad-reg.rs:28:18 | LL | asm!("", out("r31") _); | ^^^^^^^^^^^^ error: invalid register `lr`: the link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:32:18 + --> $DIR/bad-reg.rs:30:18 | LL | asm!("", out("lr") _); | ^^^^^^^^^^^ error: invalid register `r19:18`: r19 is used internally by LLVM and cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:36:18 + --> $DIR/bad-reg.rs:34:18 | LL | asm!("", out("r19:18") _); | ^^^^^^^^^^^^^^^ error: invalid register `r29:28`: the stack pointer cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:38:18 + --> $DIR/bad-reg.rs:36:18 | LL | asm!("", out("r29:28") _); | ^^^^^^^^^^^^^^^ error: invalid register `r31:30`: the frame register and link register cannot be used as an operand for inline asm - --> $DIR/bad-reg.rs:40:18 + --> $DIR/bad-reg.rs:38:18 | LL | asm!("", out("r31:30") _); | ^^^^^^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:45:18 + --> $DIR/bad-reg.rs:43:18 | LL | asm!("", in("p0") x); | ^^^^^^^^^^ error: register class `preg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:48:18 + --> $DIR/bad-reg.rs:46:18 | LL | asm!("", out("p0") x); | ^^^^^^^^^^^ error: register class `qreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:54:18 + --> $DIR/bad-reg.rs:52:18 | LL | asm!("", in("q0") x); | ^^^^^^^^^^ error: register class `qreg` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:57:18 + --> $DIR/bad-reg.rs:55:18 | LL | asm!("", out("q0") x); | ^^^^^^^^^^^ error: register `r1:0` conflicts with register `r0` - --> $DIR/bad-reg.rs:99:31 + --> $DIR/bad-reg.rs:97:31 | LL | asm!("", out("r0") _, out("r1:0") _); | ----------- ^^^^^^^^^^^^^ register `r1:0` @@ -97,7 +91,7 @@ LL | asm!("", out("r0") _, out("r1:0") _); | register `r0` error: register `r1:0` conflicts with register `r1` - --> $DIR/bad-reg.rs:101:31 + --> $DIR/bad-reg.rs:99:31 | LL | asm!("", out("r1") _, out("r1:0") _); | ----------- ^^^^^^^^^^^^^ register `r1:0` @@ -105,7 +99,7 @@ LL | asm!("", out("r1") _, out("r1:0") _); | register `r1` error: register `v1:0` conflicts with register `v0` - --> $DIR/bad-reg.rs:105:31 + --> $DIR/bad-reg.rs:103:31 | LL | asm!("", out("v0") _, out("v1:0") _); | ----------- ^^^^^^^^^^^^^ register `v1:0` @@ -113,7 +107,7 @@ LL | asm!("", out("v0") _, out("v1:0") _); | register `v0` error: register `v1:0` conflicts with register `v1` - --> $DIR/bad-reg.rs:107:31 + --> $DIR/bad-reg.rs:105:31 | LL | asm!("", out("v1") _, out("v1:0") _); | ----------- ^^^^^^^^^^^^^ register `v1:0` @@ -121,7 +115,7 @@ LL | asm!("", out("v1") _, out("v1:0") _); | register `v1` error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:45:27 + --> $DIR/bad-reg.rs:43:27 | LL | asm!("", in("p0") x); | ^ @@ -129,7 +123,7 @@ LL | asm!("", in("p0") x); = note: register class `preg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:48:28 + --> $DIR/bad-reg.rs:46:28 | LL | asm!("", out("p0") x); | ^ @@ -137,7 +131,7 @@ LL | asm!("", out("p0") x); = note: register class `preg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:54:27 + --> $DIR/bad-reg.rs:52:27 | LL | asm!("", in("q0") x); | ^ @@ -145,7 +139,7 @@ LL | asm!("", in("q0") x); = note: register class `qreg` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:57:28 + --> $DIR/bad-reg.rs:55:28 | LL | asm!("", out("q0") x); | ^ @@ -153,7 +147,7 @@ LL | asm!("", out("q0") x); = note: register class `qreg` supports these types: error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:62:34 + --> $DIR/bad-reg.rs:60:34 | LL | asm!("/* {} */", in(reg) y); | ^ @@ -161,7 +155,7 @@ LL | asm!("/* {} */", in(reg) y); = note: register class `reg` supports these types: i8, i16, i32, f32 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:66:39 + --> $DIR/bad-reg.rs:64:39 | LL | asm!("/* {} */", in(reg_pair) x); | ^ @@ -169,7 +163,7 @@ LL | asm!("/* {} */", in(reg_pair) x); = note: register class `reg_pair` supports these types: i64, f64 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:70:35 + --> $DIR/bad-reg.rs:68:35 | LL | asm!("/* {} */", in(vreg) x); | ^ @@ -177,7 +171,7 @@ LL | asm!("/* {} */", in(vreg) x); = note: register class `vreg` supports these types: i32x16, i32x32 error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:72:35 + --> $DIR/bad-reg.rs:70:35 | LL | asm!("/* {} */", in(vreg) y); | ^ @@ -185,7 +179,7 @@ LL | asm!("/* {} */", in(vreg) y); = note: register class `vreg` supports these types: i32x16, i32x32 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:76:40 + --> $DIR/bad-reg.rs:74:40 | LL | asm!("/* {} */", in(vreg_pair) x); | ^ @@ -193,12 +187,12 @@ LL | asm!("/* {} */", in(vreg_pair) x); = note: register class `vreg_pair` supports these types: i32x32, i32x64 error: type `i64` cannot be used with this register class - --> $DIR/bad-reg.rs:78:40 + --> $DIR/bad-reg.rs:76:40 | LL | asm!("/* {} */", in(vreg_pair) y); | ^ | = note: register class `vreg_pair` supports these types: i32x32, i32x64 -error: aborting due to 28 previous errors; 1 warning emitted +error: aborting due to 28 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.mips32.stderr b/tests/ui/asm/mips/reg-conflict.mips32.stderr index 0bb1148e94bd2..7e7857662cca2 100644 --- a/tests/ui/asm/mips/reg-conflict.mips32.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips32.stderr @@ -5,20 +5,8 @@ warning: unknown and unstable feature specified for `-Ctarget-feature`: `mips32r = note: for more information, see issue #162235 = help: consider filing a feature request -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -26,12 +14,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/asm/mips/reg-conflict.mips32r6.stderr b/tests/ui/asm/mips/reg-conflict.mips32r6.stderr index ee8f6ee07bf8a..a2adedeef3f77 100644 --- a/tests/ui/asm/mips/reg-conflict.mips32r6.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips32r6.stderr @@ -1,17 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -19,12 +7,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.mips64.stderr b/tests/ui/asm/mips/reg-conflict.mips64.stderr index 1deb3ae1a4b0d..b8cadec4d4102 100644 --- a/tests/ui/asm/mips/reg-conflict.mips64.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips64.stderr @@ -5,20 +5,8 @@ warning: unknown and unstable feature specified for `-Ctarget-feature`: `mips64r = note: for more information, see issue #162235 = help: consider filing a feature request -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -26,12 +14,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 3 warnings emitted +error: aborting due to 2 previous errors; 1 warning emitted diff --git a/tests/ui/asm/mips/reg-conflict.mips64r6.stderr b/tests/ui/asm/mips/reg-conflict.mips64r6.stderr index ee8f6ee07bf8a..a2adedeef3f77 100644 --- a/tests/ui/asm/mips/reg-conflict.mips64r6.stderr +++ b/tests/ui/asm/mips/reg-conflict.mips64r6.stderr @@ -1,17 +1,5 @@ -warning: unstable feature specified for `-Ctarget-feature`: `fp64` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: unstable feature specified for `-Ctarget-feature`: `msa` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - error: register `$f4` conflicts with register `$w4` - --> $DIR/reg-conflict.rs:28:33 + --> $DIR/reg-conflict.rs:26:33 | LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | ------------- ^^^^^^^^^^^^^ register `$f4` @@ -19,12 +7,12 @@ LL | asm!("", in("$w4") 0.0, in("$f4") 0.0); | register `$w4` error: register `$f25` conflicts with register `$w25` - --> $DIR/reg-conflict.rs:30:34 + --> $DIR/reg-conflict.rs:28:34 | LL | asm!("", in("$w25") 0.0, in("$f25") 0.0); | -------------- ^^^^^^^^^^^^^^ register `$f25` | | | register `$w25` -error: aborting due to 2 previous errors; 2 warnings emitted +error: aborting due to 2 previous errors diff --git a/tests/ui/asm/mips/reg-conflict.rs b/tests/ui/asm/mips/reg-conflict.rs index f0c9b5e6fd091..7fdf799b9d2d3 100644 --- a/tests/ui/asm/mips/reg-conflict.rs +++ b/tests/ui/asm/mips/reg-conflict.rs @@ -17,8 +17,6 @@ //[mips32]~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `mips32r5` //[mips64]~? WARN unknown and unstable feature specified for `-Ctarget-feature`: `mips64r5` -//~? WARN unstable feature specified for `-Ctarget-feature`: `fp64` -//~? WARN unstable feature specified for `-Ctarget-feature`: `msa` extern crate minicore; use minicore::*; diff --git a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs index 688f51dad58cb..38b35c67ba6ff 100644 --- a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.rs @@ -12,5 +12,3 @@ extern crate minicore; use minicore::*; - -//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr b/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr deleted file mode 100644 index c7623519db2ed..0000000000000 --- a/tests/ui/target-feature/abi-irrelevant-target-feature-flag-disable.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs index 4faef8d02d673..f15aa5313ba43 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.rs @@ -26,4 +26,3 @@ extern crate minicore; use minicore::*; //~? WARN must be enabled to ensure that the ABI of the current target can be implemented correctly -//[x86]~? WARN unstable feature specified for `-Ctarget-feature` diff --git a/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr index 52611d230af55..d7f4b3d670b73 100644 --- a/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr +++ b/tests/ui/target-feature/abi-required-target-feature-flag-disable.x86.stderr @@ -1,13 +1,7 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - warning: target feature `x87` must be enabled to ensure that the ABI of the current target can be implemented correctly | = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: for more information, see issue #162235 -warning: 2 warnings emitted +warning: 1 warning emitted diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr deleted file mode 100644 index a48e3f28bc683..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-hvxv66.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `hvxv66` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr deleted file mode 100644 index 83ce776cb1c97..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-v60.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v60` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr b/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr deleted file mode 100644 index 2e62c87d7c9d8..0000000000000 --- a/tests/ui/target-feature/feature-hierarchy.hexagon-v68.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `v68` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/feature-hierarchy.rs b/tests/ui/target-feature/feature-hierarchy.rs index 65f7a1e6d3db4..2629f5b000f80 100644 --- a/tests/ui/target-feature/feature-hierarchy.rs +++ b/tests/ui/target-feature/feature-hierarchy.rs @@ -63,10 +63,6 @@ fn check_sve2_includes_neon() { assert!(cfg!(target_feature = "sve2")); } -//[hexagon-v60]~? WARN unstable feature specified for `-Ctarget-feature`: `v60` -//[hexagon-v68]~? WARN unstable feature specified for `-Ctarget-feature`: `v68` -//[hexagon-hvxv66]~? WARN unstable feature specified for `-Ctarget-feature`: `hvxv66` - #[cfg(hexagon_v60)] fn check_v60_not_v68() { // Enabling v60 should not jump up the scalar feature hierarchy. diff --git a/tests/ui/target-feature/packedstack-combinations.rs b/tests/ui/target-feature/packedstack-combinations.rs index 5dc0f6adf812e..dc45ac1ff5e83 100644 --- a/tests/ui/target-feature/packedstack-combinations.rs +++ b/tests/ui/target-feature/packedstack-combinations.rs @@ -38,7 +38,5 @@ pub fn test() { } //[wrong_arch]~? ERROR `-Zpacked-stack` is only supported on s390x -//[backchain_cli]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` //[backchain_cli]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature //[backchain_attr]~? ERROR `-Zpacked-stack` is incompatible with `backchain` target feature -//[with_softfloat]~? WARN unstable feature specified for `-Ctarget-feature`: `backchain` diff --git a/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr b/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr deleted file mode 100644 index eeec785448bc3..0000000000000 --- a/tests/ui/target-feature/packedstack-combinations.with_softfloat.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `backchain` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - diff --git a/tests/ui/target-feature/unstable-feature.rs b/tests/ui/target-feature/unstable-feature.rs deleted file mode 100644 index a79ad4696033a..0000000000000 --- a/tests/ui/target-feature/unstable-feature.rs +++ /dev/null @@ -1,8 +0,0 @@ -//@ compile-flags: -Ctarget-feature=+x87 --crate-type=rlib --target=x86_64-unknown-linux-gnu -//@ build-pass -//@ needs-llvm-components: x86 - -#![feature(no_core)] -#![no_core] - -//~? WARN unstable feature specified for `-Ctarget-feature`: `x87` diff --git a/tests/ui/target-feature/unstable-feature.stderr b/tests/ui/target-feature/unstable-feature.stderr deleted file mode 100644 index c7623519db2ed..0000000000000 --- a/tests/ui/target-feature/unstable-feature.stderr +++ /dev/null @@ -1,8 +0,0 @@ -warning: unstable feature specified for `-Ctarget-feature`: `x87` - | - = note: this feature is not stably supported; its behavior can change in the future - = note: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! - = note: for more information, see issue #162235 - -warning: 1 warning emitted - From 12eb7ef2a8dddc2aae50a66047078e70104a7239 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 28 Sep 2026 20:20:16 +0100 Subject: [PATCH 0971/1309] Clarify comment in TailCopyToMove --- compiler/rustc_mir_transform/src/tail_copy_to_move.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_mir_transform/src/tail_copy_to_move.rs b/compiler/rustc_mir_transform/src/tail_copy_to_move.rs index 1668449190307..e97844748cefb 100644 --- a/compiler/rustc_mir_transform/src/tail_copy_to_move.rs +++ b/compiler/rustc_mir_transform/src/tail_copy_to_move.rs @@ -4,8 +4,8 @@ //! //! MIR building represents reads of values whose type is `Copy` using //! `Operand::Copy`, including when such a local is returned. If that local's -//! address has ever been observed, then the local's allocation is semantically -//! valid until its `StorageDead` or function exit. This keeps the local live +//! address has ever been observed, `MoveElimination` conservatively considers +//! it live until its `StorageDead` or function exit. This keeps the local live //! across `_0 = copy local`, so its live range overlaps with the return place //! and `MoveElimination` cannot unify the source local with `_0`. //! From b89cf31026972568ba8318d55269d71b9a6527ee Mon Sep 17 00:00:00 2001 From: Petrichor Park Date: Mon, 28 Sep 2026 14:32:36 -0500 Subject: [PATCH 0972/1309] Stabilize vec_try_remove --- library/alloc/src/vec/mod.rs | 3 +-- library/alloctests/tests/lib.rs | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs index 4537e50e634f2..f837d963a572e 100644 --- a/library/alloc/src/vec/mod.rs +++ b/library/alloc/src/vec/mod.rs @@ -2421,12 +2421,11 @@ impl Vec { /// # Examples /// /// ``` - /// #![feature(vec_try_remove)] /// let mut v = vec![1, 2, 3]; /// assert_eq!(v.try_remove(0), Some(1)); /// assert_eq!(v.try_remove(2), None); /// ``` - #[unstable(feature = "vec_try_remove", issue = "146954")] + #[stable(feature = "vec_try_remove", since = "CURRENT_RUSTC_VERSION")] #[rustc_confusables("delete", "take", "remove")] pub fn try_remove(&mut self, index: usize) -> Option { let len = self.len(); diff --git a/library/alloctests/tests/lib.rs b/library/alloctests/tests/lib.rs index 9bcb545c8e87d..5c8ee92388dd0 100644 --- a/library/alloctests/tests/lib.rs +++ b/library/alloctests/tests/lib.rs @@ -60,7 +60,6 @@ #![feature(unique_rc_arc)] #![feature(vec_deque_retain_range)] #![feature(vec_peek_mut)] -#![feature(vec_try_remove)] #![feature(write_all_vectored)] // tidy-alphabetical-end From d10b01c846c0dc222d9fcf36efdb2cc0fc0c2d9f Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Sep 2026 13:45:01 +1000 Subject: [PATCH 0973/1309] Use `{IntTy,UintTy}::name` in `Ty::primitive_symbol` --- compiler/rustc_middle/src/ty/sty.rs | 25 +++---------------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index 243ad73e3dfb8..925915c88cdb4 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -2115,28 +2115,9 @@ impl<'tcx> Ty<'tcx> { match self.kind() { ty::Bool => Some(sym::bool), ty::Char => Some(sym::char), - ty::Float(f) => match f { - ty::FloatTy::F16 => Some(sym::f16), - ty::FloatTy::F32 => Some(sym::f32), - ty::FloatTy::F64 => Some(sym::f64), - ty::FloatTy::F128 => Some(sym::f128), - }, - ty::Int(f) => match f { - ty::IntTy::Isize => Some(sym::isize), - ty::IntTy::I8 => Some(sym::i8), - ty::IntTy::I16 => Some(sym::i16), - ty::IntTy::I32 => Some(sym::i32), - ty::IntTy::I64 => Some(sym::i64), - ty::IntTy::I128 => Some(sym::i128), - }, - ty::Uint(f) => match f { - ty::UintTy::Usize => Some(sym::usize), - ty::UintTy::U8 => Some(sym::u8), - ty::UintTy::U16 => Some(sym::u16), - ty::UintTy::U32 => Some(sym::u32), - ty::UintTy::U64 => Some(sym::u64), - ty::UintTy::U128 => Some(sym::u128), - }, + ty::Int(i) => Some(i.name()), + ty::Uint(u) => Some(u.name()), + ty::Float(f) => Some(f.name()), ty::Str => Some(sym::str), _ => None, } From 935c565a18c3768389877b116000baad08649dd8 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 Jul 2026 16:38:02 +1000 Subject: [PATCH 0974/1309] Factor out repeated `get_normal_item` calls --- .../rustc_attr_parsing/src/attributes/cfg.rs | 31 ++++++++++--------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_attr_parsing/src/attributes/cfg.rs b/compiler/rustc_attr_parsing/src/attributes/cfg.rs index 8102208ec519d..d244e6c59e5f9 100644 --- a/compiler/rustc_attr_parsing/src/attributes/cfg.rs +++ b/compiler/rustc_attr_parsing/src/attributes/cfg.rs @@ -306,7 +306,8 @@ pub fn parse_cfg_attr( features: Option<&Features>, lint_node_id: ast::NodeId, ) -> Option<(CfgEntry, Vec<(WithTokens, Span)>)> { - match &cfg_attr.get_normal_item().args { + let item = cfg_attr.get_normal_item(); + match &item.args { ast::AttrArgs::Delimited(ast::DelimArgs { dspan, delim, tokens }) if !tokens.is_empty() => { check_cfg_attr_bad_delim(&sess.psess, *dspan, *delim); match parse_in(&sess.psess, tokens.clone(), "`cfg_attr` input", |p| { @@ -316,11 +317,11 @@ pub fn parse_cfg_attr( Err(e) => { let suggestions = CFG_ATTR_TEMPLATE.suggestions( ParsedDescription::Attribute, - cfg_attr.get_normal_item().unsafety, + item.unsafety, sym::cfg_attr, ); e.with_span_suggestions( - cfg_attr.get_normal_item().span, + item.span, "must be of the form", suggestions, Applicability::HasPlaceholders, @@ -334,25 +335,24 @@ pub fn parse_cfg_attr( } } _ => { - let (span, reason) = if let ast::AttrArgs::Delimited(ast::DelimArgs { dspan, .. }) = - cfg_attr.get_normal_item().args - { - (dspan.entire(), AttributeParseErrorReason::ExpectedAtLeastOneArgument) - } else { - (cfg_attr.get_normal_item().span, AttributeParseErrorReason::ExpectedList) - }; + let (span, reason) = + if let ast::AttrArgs::Delimited(ast::DelimArgs { dspan, .. }) = item.args { + (dspan.entire(), AttributeParseErrorReason::ExpectedAtLeastOneArgument) + } else { + (item.span, AttributeParseErrorReason::ExpectedList) + }; sess.dcx().emit_err(AttributeParseError { span, - inner_span: cfg_attr.get_normal_item().span, + inner_span: item.span, template: CFG_ATTR_TEMPLATE, - path: AttrPath::from_ast(&cfg_attr.get_normal_item().path, identity), + path: AttrPath::from_ast(&item.path, identity), description: ParsedDescription::Attribute, reason, suggestions: diagnostics::AttributeParseErrorSuggestions::CreatedByTemplate( CFG_ATTR_TEMPLATE.suggestions( ParsedDescription::Attribute, - cfg_attr.get_normal_item().unsafety, + item.unsafety, sym::cfg_attr, ), ), @@ -389,13 +389,14 @@ fn parse_cfg_attr_internal<'a>( )?; let pred_span = pred_start.with_hi(parser.token.span.hi()); + let item = attribute.get_normal_item(); let cfg_predicate = AttributeParser::parse_single_args( sess, attribute.span, - attribute.get_normal_item().span, + item.span, attribute.style, AttrPath { segments: attribute.path().into_boxed_slice(), span: attribute.span }, - Some(attribute.get_normal_item().unsafety), + Some(item.unsafety), AttributeSafety::Normal, ParsedDescription::Attribute, pred_span, From bc7618a8dab2415ec18057b4243fba6f3c665ee1 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Mon, 27 Jul 2026 19:03:15 +1000 Subject: [PATCH 0975/1309] Add test case for an invalid attribute with nested `cfg_attr` Prior to #159633, the compiler made an invalid suggestion: ``` help: must be of the form | 1 - #[cfg_attr(true, cfg_attr(true, 3))] 1 + #[cfg_attr(true, #[cfg_attr(predicate, attr1, attr2, ...)])] ``` Now it is correct: ``` help: must be of the form | 1 - #[cfg_attr(true, cfg_attr(true, 3))] 1 + #[cfg_attr(true, cfg_attr(predicate, attr1, attr2, ...))] ``` But there was no test for it. This commit adds one. --- .../cfg_attr-attr-syntax-validation.rs | 3 +++ .../cfg_attr-attr-syntax-validation.stderr | 17 +++++++++++++++-- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs index 907e1b966766f..508b449358964 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.rs @@ -46,6 +46,9 @@ struct S12; //~| WARN previously accepted struct S13; +#[cfg_attr(true, cfg_attr(true, 3))] //~ ERROR expected identifier, found `3` +struct S14; + #[cfg_attr(true, inline())] //~ ERROR malformed `inline` attribute input fn f1() {} diff --git a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr index e901460a4eb88..048affd1c4191 100644 --- a/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr +++ b/tests/ui/conditional-compilation/cfg_attr-attr-syntax-validation.stderr @@ -120,6 +120,19 @@ LL - #[cfg_attr(true)] LL + #[cfg_attr(predicate, attr1, attr2, ...)] | +error: expected identifier, found `3` + --> $DIR/cfg_attr-attr-syntax-validation.rs:49:33 + | +LL | #[cfg_attr(true, cfg_attr(true, 3))] + | ^ expected identifier + | + = note: for more information, visit +help: must be of the form + | +LL - #[cfg_attr(true, cfg_attr(true, 3))] +LL + #[cfg_attr(true, cfg_attr(predicate, attr1, attr2, ...))] + | + error: expected a literal (`1u8`, `1.0f32`, `"string"`, etc.) here, found `expr` metavariable --> $DIR/cfg_attr-attr-syntax-validation.rs:30:30 | @@ -157,7 +170,7 @@ LL | #[cfg_attr(true, link_section = "name")] | ++++++++ error[E0805]: malformed `inline` attribute input - --> $DIR/cfg_attr-attr-syntax-validation.rs:49:18 + --> $DIR/cfg_attr-attr-syntax-validation.rs:52:18 | LL | #[cfg_attr(true, inline())] | ^^^^^^-- @@ -185,7 +198,7 @@ LL | #[cfg_attr(true, link_section)] = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! = note: requested on the command line with `-W unused-attributes` -error: aborting due to 13 previous errors; 1 warning emitted +error: aborting due to 14 previous errors; 1 warning emitted Some errors have detailed explanations: E0539, E0565, E0805. For more information about an error, try `rustc --explain E0539`. From 7af2cce3b04ebe3cb42807d7e75520888021aefc Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 29 Sep 2026 14:25:40 +1000 Subject: [PATCH 0976/1309] Remove unused `rustc_middle::ty::cast::IntTy::is_signed` --- compiler/rustc_middle/src/ty/cast.rs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/compiler/rustc_middle/src/ty/cast.rs b/compiler/rustc_middle/src/ty/cast.rs index 25fc0775b1a32..e53f53d5e5648 100644 --- a/compiler/rustc_middle/src/ty/cast.rs +++ b/compiler/rustc_middle/src/ty/cast.rs @@ -17,12 +17,6 @@ pub enum IntTy { Char, } -impl IntTy { - pub fn is_signed(self) -> bool { - matches!(self, Self::I) - } -} - // Valid types for the result of a non-coercion cast #[derive(Copy, Clone, Debug, PartialEq, Eq)] pub enum CastTy<'tcx> { From a4cd051442bb2ac4e5b79a7cbb01300688365d92 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 29 Sep 2026 04:36:15 +0000 Subject: [PATCH 0977/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 5d8937173e7c40406c167f4e94737da8925333ad. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index ddf759b5d0c48..028e73378b28b 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -22697761c6a01e8d12adcd91e4a5bc755596767a +5d8937173e7c40406c167f4e94737da8925333ad From 52e0abb6befe780561dcbea6c1d444b1d3288caa Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 29 Sep 2026 04:39:43 +0000 Subject: [PATCH 0978/1309] fmt --- src/tools/miri/src/shims/foreign_items.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs index e7e283b757036..66d65ead7c7bd 100644 --- a/src/tools/miri/src/shims/foreign_items.rs +++ b/src/tools/miri/src/shims/foreign_items.rs @@ -170,8 +170,7 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { // picked by the linker. // Make sure we are consistent wrt what is 'first' and 'second'. - let original_span = - tcx.def_span(original.instance.def_id()); + let original_span = tcx.def_span(original.instance.def_id()); let span = tcx.def_span(def_id); if original_span.lo_hi() < span.lo_hi() { throw_machine_stop!( From 3e5b244994234f4144b3c11fa590a1e1b2834f18 Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 28 Jul 2026 11:20:23 +1000 Subject: [PATCH 0979/1309] Mark duplicate attr messages as not machine applicable This commit adds a new test for some uncovered cases. The thing to note here is the varying correctness of the `help:` lines. This is correct: ``` LL | #[inline] | ^^^^^^^^^ help: remove this attribute ``` The following two are half correct. They give the right idea but if applied literally they will produce syntax that triggers either a warning (the former) or an error (the latter). ``` LL | #[cfg_attr(true, inline)] | ^^^^^^ help: remove this attribute LL | #[cfg_attr(true, inline, deprecated)] | ^^^^^^ help: remove this attribute ``` For this reason, this commit also marks these help messages as not machine-applicable. This means we lose the machine applicability on some cases where it's correct, but it seems better to be conservative. --- .../rustc_attr_parsing/src/diagnostics.rs | 4 +- .../cfg-attr-duplicate-attrs.rs | 34 ++++++++ .../cfg-attr-duplicate-attrs.stderr | 78 +++++++++++++++++++ 3 files changed, 114 insertions(+), 2 deletions(-) create mode 100644 tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.rs create mode 100644 tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.stderr diff --git a/compiler/rustc_attr_parsing/src/diagnostics.rs b/compiler/rustc_attr_parsing/src/diagnostics.rs index fb4a32d864fbe..a43cd918c8f35 100644 --- a/compiler/rustc_attr_parsing/src/diagnostics.rs +++ b/compiler/rustc_attr_parsing/src/diagnostics.rs @@ -1235,7 +1235,7 @@ pub(crate) struct UnknownVersionLiteral { #[diag("multiple `{$name}` attributes")] pub(crate) struct UnusedMultiple { #[primary_span] - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "unspecified")] pub this: Span, #[note("attribute also specified here")] pub other: Span, @@ -2061,7 +2061,7 @@ pub(crate) struct AdditionalCommaSuggestion { #[derive(Diagnostic)] #[diag("unused attribute")] pub(crate) struct UnusedDuplicate { - #[suggestion("remove this attribute", code = "", applicability = "machine-applicable")] + #[suggestion("remove this attribute", code = "", applicability = "unspecified")] pub this: Span, #[note("attribute also specified here")] pub other: Span, diff --git a/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.rs b/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.rs new file mode 100644 index 0000000000000..30434569dbe73 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.rs @@ -0,0 +1,34 @@ +// Test for handling of duplicated attributes within `cfg_attr`, in particular the suggestions of +// what to remove. + +#[inline] +#[inline] +//~^ WARN unused attribute +//~| WARN this was previously accepted +fn f1() {} + +#[deprecated] +#[deprecated] +//~^ ERROR multiple `deprecated` attributes +fn f2() {} + +#[inline] +#[cfg_attr(true, inline)] +//~^ WARN unused attribute +//~| WARN this was previously accepted +fn f3() {} + +#[deprecated] +#[cfg_attr(true, deprecated)] +//~^ ERROR multiple `deprecated` attributes +fn f4() {} + +#[inline] +#[deprecated] +#[cfg_attr(true, inline, deprecated)] +//~^ WARN unused attribute +//~| WARN this was previously accepted +//~| ERROR multiple `deprecated` attributes +fn f5() {} + +fn main() {} diff --git a/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.stderr b/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.stderr new file mode 100644 index 0000000000000..c30bc26b22ce7 --- /dev/null +++ b/tests/ui/conditional-compilation/cfg-attr-duplicate-attrs.stderr @@ -0,0 +1,78 @@ +error: multiple `deprecated` attributes + --> $DIR/cfg-attr-duplicate-attrs.rs:11:1 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:10:1 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ + +error: multiple `deprecated` attributes + --> $DIR/cfg-attr-duplicate-attrs.rs:22:18 + | +LL | #[cfg_attr(true, deprecated)] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:21:1 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ + +error: multiple `deprecated` attributes + --> $DIR/cfg-attr-duplicate-attrs.rs:28:26 + | +LL | #[cfg_attr(true, inline, deprecated)] + | ^^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:27:1 + | +LL | #[deprecated] + | ^^^^^^^^^^^^^ + +warning: unused attribute + --> $DIR/cfg-attr-duplicate-attrs.rs:5:1 + | +LL | #[inline] + | ^^^^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:4:1 + | +LL | #[inline] + | ^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + = note: requested on the command line with `-W unused-attributes` + +warning: unused attribute + --> $DIR/cfg-attr-duplicate-attrs.rs:16:18 + | +LL | #[cfg_attr(true, inline)] + | ^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:15:1 + | +LL | #[inline] + | ^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +warning: unused attribute + --> $DIR/cfg-attr-duplicate-attrs.rs:28:18 + | +LL | #[cfg_attr(true, inline, deprecated)] + | ^^^^^^ help: remove this attribute + | +note: attribute also specified here + --> $DIR/cfg-attr-duplicate-attrs.rs:26:1 + | +LL | #[inline] + | ^^^^^^^^^ + = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release! + +error: aborting due to 3 previous errors; 3 warnings emitted + From 28e388b26baea6382cfc2c16fedd023490202f44 Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Tue, 29 Sep 2026 13:08:19 +0600 Subject: [PATCH 0980/1309] add test for duplicate '_ in precise capturing suggestion the test records what the compiler prints today: for an opaque that already has use<'_> and a second anonymous lifetime to capture, it suggested use<'_, '_>, which doesnt compile --- ...e-anon-lifetime-suggestion-issue-132199.rs | 24 ++++++++++ ...on-lifetime-suggestion-issue-132199.stderr | 45 +++++++++++++++++++ 2 files changed, 69 insertions(+) create mode 100644 tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.rs create mode 100644 tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr diff --git a/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.rs b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.rs new file mode 100644 index 0000000000000..1ffe00db8edc3 --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.rs @@ -0,0 +1,24 @@ +//@ edition: 2024 + +// regression test for https://github.com/rust-lang/rust/issues/132199. +// in edition 2024 impl Trait captures every in-scope lifetime by default, so +// E0700 only fires once an explicit use<..> restricts the set. + +struct T; + +impl T { + // dup: opaque already has use<'_>, needs a second anonymous lifetime. + // before the fix, it suggested use<'_, '_>, which doesnt compile. + fn dup(&self, t: &T) -> impl Sized + use<'_> { (self, t) } + //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds + + // single_anon: use<> with one anonymous lifetime still gets use<'_>. + fn single_anon(&self) -> impl Sized + use<> { self } + //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds + + // named: a named lifetime still gets suggested by name. + fn named<'a>(&'a self, t: &'a T) -> impl Sized + use<> { (self, t) } + //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds +} + +fn main() {} diff --git a/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr new file mode 100644 index 0000000000000..863e8227db25d --- /dev/null +++ b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr @@ -0,0 +1,45 @@ +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/duplicate-anon-lifetime-suggestion-issue-132199.rs:12:52 + | +LL | fn dup(&self, t: &T) -> impl Sized + use<'_> { (self, t) } + | -- -------------------- ^^^^^^^^^ + | | | + | | opaque type defined here + | hidden type `(&T, &T)` captures the anonymous lifetime defined here + | +help: add `'_` to the `use<...>` bound to explicitly capture it + | +LL | fn dup(&self, t: &T) -> impl Sized + use<'_, '_> { (self, t) } + | ++++ + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/duplicate-anon-lifetime-suggestion-issue-132199.rs:16:51 + | +LL | fn single_anon(&self) -> impl Sized + use<> { self } + | ----- ------------------ ^^^^ + | | | + | | opaque type defined here + | hidden type `&T` captures the anonymous lifetime defined here + | +help: add `'_` to the `use<...>` bound to explicitly capture it + | +LL | fn single_anon(&self) -> impl Sized + use<'_> { self } + | ++ + +error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds + --> $DIR/duplicate-anon-lifetime-suggestion-issue-132199.rs:20:62 + | +LL | fn named<'a>(&'a self, t: &'a T) -> impl Sized + use<> { (self, t) } + | -- ------------------ ^^^^^^^^^ + | | | + | | opaque type defined here + | hidden type `(&'a T, &'a T)` captures the lifetime `'a` as defined here + | +help: add `'a` to the `use<...>` bound to explicitly capture it + | +LL | fn named<'a>(&'a self, t: &'a T) -> impl Sized + use<'a> { (self, t) } + | ++ + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0700`. From e93919946f844ab7e6a90b7fdc1dda8a3239438f Mon Sep 17 00:00:00 2001 From: albab-hasan Date: Tue, 29 Sep 2026 13:14:52 +0600 Subject: [PATCH 0981/1309] do not suggest capturing '_ twice in precise capturing suggest_precise_capturing was appending '_ to a use<..> list that already had it, suggesting use<'_, '_>, which rustc rejects with cannot capture parameter '_ twice the branch for an opaque with an existing use<..> now bails out the same way the branch for an opaque without one does: both check if the lifetime is already captured --- .../src/error_reporting/infer/region.rs | 9 +++++++++ ...uplicate-anon-lifetime-suggestion-issue-132199.stderr | 5 ----- 2 files changed, 9 insertions(+), 5 deletions(-) diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs index b9f70cea5f5ab..948267ea03c6d 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/region.rs @@ -1380,6 +1380,15 @@ fn suggest_precise_capturing<'tcx>( hir::GenericBound::Use(args, span) => Some((args, span)), _ => None, }) { + // '_ is an elision marker, not a lifetime name, so it cannot appear twice in a + // capture list. the branch for opaques with no use<..> yet already skips captured + // lifetimes; do the same here to avoid suggesting use<'_, '_>. + if args.iter().any(|arg| { + matches!(arg, hir::PreciseCapturingArg::Lifetime(lt) if lt.ident.name == new_lifetime) + }) { + return; + } + let last_lifetime_span = args.iter().rev().find_map(|arg| match arg { hir::PreciseCapturingArg::Lifetime(lt) => Some(lt.ident.span), _ => None, diff --git a/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr index 863e8227db25d..2eebc773743b4 100644 --- a/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr +++ b/tests/ui/impl-trait/precise-capturing/duplicate-anon-lifetime-suggestion-issue-132199.stderr @@ -6,11 +6,6 @@ LL | fn dup(&self, t: &T) -> impl Sized + use<'_> { (self, t) } | | | | | opaque type defined here | hidden type `(&T, &T)` captures the anonymous lifetime defined here - | -help: add `'_` to the `use<...>` bound to explicitly capture it - | -LL | fn dup(&self, t: &T) -> impl Sized + use<'_, '_> { (self, t) } - | ++++ error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds --> $DIR/duplicate-anon-lifetime-suggestion-issue-132199.rs:16:51 From 2ccceb061620c801600b1c5bb31ee6f2e739ce63 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Tue, 29 Sep 2026 16:34:25 +0800 Subject: [PATCH 0982/1309] Add safety comments for alloc::string --- library/alloc/src/string.rs | 41 ++++++++++++++++++++----------------- 1 file changed, 22 insertions(+), 19 deletions(-) diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs index b363b6862f7e5..03c07b15712bb 100644 --- a/library/alloc/src/string.rs +++ b/library/alloc/src/string.rs @@ -802,7 +802,7 @@ impl String { let (chunks, []) = v.as_chunks::<2>() else { return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes }); }; - // ignore-tidy-undocumented-unsafe + // SAFETY: The aligned part of `v` can be transmuted into a valid u16 slice. match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => { @@ -838,7 +838,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_from_utf16_endian", since = "1.98.0")] pub fn from_utf16le_lossy(v: &[u8]) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: The aligned part of `v` can be transmuted into a valid u16 slice. match (cfg!(target_endian = "little"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", @@ -877,7 +877,7 @@ impl String { let (chunks, []) = v.as_chunks::<2>() else { return Err(FromUtf16Error { kind: FromUtf16ErrorKind::OddBytes }); }; - // ignore-tidy-undocumented-unsafe + // SAFETY: The aligned part of `v` can be transmuted into a valid u16 slice. match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16(v), _ => { @@ -913,7 +913,7 @@ impl String { #[cfg(not(no_global_oom_handling))] #[stable(feature = "str_from_utf16_endian", since = "1.98.0")] pub fn from_utf16be_lossy(v: &[u8]) -> String { - // ignore-tidy-undocumented-unsafe + // SAFETY: The aligned part of `v` can be transmuted into a valid u16 slice. match (cfg!(target_endian = "big"), unsafe { v.align_to::() }) { (true, ([], v, [])) => Self::from_utf16_lossy(v), (true, ([], v, [_remainder])) => Self::from_utf16_lossy(v) + "\u{FFFD}", @@ -1143,7 +1143,8 @@ impl String { let additional: Saturating = slice.iter().map(|x| Saturating(x.len())).sum(); self.reserve(additional.0); let (ptr, len, cap) = core::mem::take(self).into_raw_parts(); - // ignore-tidy-undocumented-unsafe + // SAFETY: `self` have reserved enough space for strs in `slice`, and we are copying from valid UTF-8 slices. + // Therefore all unsafe operations are safe. unsafe { let mut dst = ptr.add(len); for new in slice { @@ -1532,7 +1533,7 @@ impl String { pub fn pop(&mut self) -> Option { let ch = self.chars().rev().next()?; let newlen = self.len() - ch.len_utf8(); - // ignore-tidy-undocumented-unsafe + // SAFETY: `newlen` is less than old length. unsafe { self.vec.set_len(newlen); } @@ -1571,7 +1572,11 @@ impl String { let next = idx + ch.len_utf8(); let len = self.len(); - // ignore-tidy-undocumented-unsafe + // SAFETY: + // * Since `next` is not bigger than `len`, `self.vec.as_ptr().add(next)` + // is valid for reads and `self.vec.as_mut_ptr().add(idx)` is valid for writes. + // Both pointers are valid for `len - next` bytes. + // * new length is less than old length. unsafe { ptr::copy(self.vec.as_ptr().add(next), self.vec.as_mut_ptr().add(idx), len - next); self.vec.set_len(len - (next - idx)); @@ -1645,7 +1650,7 @@ impl String { len += count; } - // ignore-tidy-undocumented-unsafe + // SAFETY: `len` is less than or equal to the original length of the string. unsafe { self.vec.set_len(len); } @@ -1954,7 +1959,7 @@ impl String { pub fn split_off(&mut self, at: usize) -> String { assert!(self.is_char_boundary(at)); let other = self.vec.split_off(at); - // ignore-tidy-undocumented-unsafe + // SAFETY: `other` contains only valid UTF-8 because `at` is on a `UTF-8` code point boundary. unsafe { String::from_utf8_unchecked(other) } } @@ -2224,7 +2229,7 @@ impl String { #[inline] pub fn into_boxed_str(self) -> Box { let slice = self.vec.into_boxed_slice(); - // ignore-tidy-undocumented-unsafe + // SAFETY: `slice` contains only valid UTF-8 because `String` is guaranteed to be valid UTF-8. unsafe { from_boxed_utf8_unchecked(slice) } } @@ -2256,7 +2261,7 @@ impl String { #[inline] pub fn leak<'a>(self) -> &'a mut str { let slice = self.vec.leak(); - // ignore-tidy-undocumented-unsafe + // SAFETY: `slice` contains only valid UTF-8 because `String` is guaranteed to be valid UTF-8. unsafe { from_utf8_unchecked_mut(slice) } } } @@ -3586,14 +3591,12 @@ unsafe impl Send for Drain<'_> {} #[stable(feature = "drain", since = "1.6.0")] impl Drop for Drain<'_> { fn drop(&mut self) { - // ignore-tidy-undocumented-unsafe - unsafe { - // Use Vec::drain. "Reaffirm" the bounds checks to avoid - // panic code being inserted again. - let self_vec = (*self.string).as_mut_vec(); - if self.start <= self.end && self.end <= self_vec.len() { - self_vec.drain(self.start..self.end); - } + // Use Vec::drain. "Reaffirm" the bounds checks to avoid + // panic code being inserted again. + // SAFETY: We only use the returned Vec to call drain. + let self_vec = unsafe { &mut *(*self.string).as_mut_vec() }; + if self.start <= self.end && self.end <= self_vec.len() { + self_vec.drain(self.start..self.end); } } } From e490bd5975e2f98bdf9b638bcae352c6b2ae1796 Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Tue, 29 Sep 2026 16:35:22 +0800 Subject: [PATCH 0983/1309] Fix ICE when use tree appears in docs. --- compiler/rustc_resolve/src/check_unused.rs | 7 +++++++ tests/ui/attributes/use-tree-in-docs.rs | 7 +++++++ tests/ui/attributes/use-tree-in-docs.stderr | 8 ++++++++ 3 files changed, 22 insertions(+) create mode 100644 tests/ui/attributes/use-tree-in-docs.rs create mode 100644 tests/ui/attributes/use-tree-in-docs.stderr diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index aac244ad6cf22..91e6188a8c63c 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -250,6 +250,13 @@ impl<'a, 'ra, 'tcx> AsMut> for UnusedImportCheckVisitor<'a, } impl<'a, 'ra, 'tcx> Visitor<'a> for UnusedImportCheckVisitor<'a, 'ra, 'tcx> { + // Don't walk into attributes because imports can appear + // inside (e.g #[doc = {use std::{io,fmt};}]). They have + // a different owner, so they will cause an ICE if we visit + // them. Note that this doc attribute is not valid and will + // be rejected during AST lowering. + fn visit_attribute(&mut self, _: &'a rustc_ast::Attribute) {} + fn visit_item(&mut self, item: &'a ast::Item) { self.item_span = item.span_with_attributes(); match &item.kind { diff --git a/tests/ui/attributes/use-tree-in-docs.rs b/tests/ui/attributes/use-tree-in-docs.rs new file mode 100644 index 0000000000000..69e1121464558 --- /dev/null +++ b/tests/ui/attributes/use-tree-in-docs.rs @@ -0,0 +1,7 @@ +// Don't ICE when use tree appears in docs. (#163355) +#![feature(generic_assert)] +#[doc = assert !(b)] +//~^ ERROR attribute value must be a literal +use std as x; + +fn main(){} diff --git a/tests/ui/attributes/use-tree-in-docs.stderr b/tests/ui/attributes/use-tree-in-docs.stderr new file mode 100644 index 0000000000000..fb03874a714c7 --- /dev/null +++ b/tests/ui/attributes/use-tree-in-docs.stderr @@ -0,0 +1,8 @@ +error: attribute value must be a literal + --> $DIR/use-tree-in-docs.rs:3:9 + | +LL | #[doc = assert !(b)] + | ^^^^^^^^^^^ + +error: aborting due to 1 previous error + From b2c20770a2dd0db94eac6e954fe9b208c68e68a4 Mon Sep 17 00:00:00 2001 From: Davlat Davydov Date: Sat, 26 Sep 2026 15:23:30 +0300 Subject: [PATCH 0984/1309] Update expect messages in library/std/src/os/unix/net/ following style guide review changes --- library/std/src/os/unix/net/addr.rs | 10 ++++---- library/std/src/os/unix/net/datagram.rs | 34 ++++++++++++------------- library/std/src/os/unix/net/listener.rs | 6 ++--- library/std/src/os/unix/net/stream.rs | 22 ++++++++-------- 4 files changed, 36 insertions(+), 36 deletions(-) diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs index 3daddc2d34323..a0a229704911e 100644 --- a/library/std/src/os/unix/net/addr.rs +++ b/library/std/src/os/unix/net/addr.rs @@ -87,7 +87,7 @@ enum AddressKind<'a> { /// return /// } /// }; -/// let addr = socket.local_addr().expect("Couldn't get local address"); +/// let addr = socket.local_addr().expect("`UnixListener::local_addr` should not fail"); /// ``` #[derive(Clone)] #[stable(feature = "unix_socket", since = "1.10.0")] @@ -186,7 +186,7 @@ impl SocketAddr { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixListener::bind("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = socket.local_addr().expect("`UnixListener::local_addr` should not fail"); /// assert_eq!(addr.is_unnamed(), false); /// Ok(()) /// } @@ -200,7 +200,7 @@ impl SocketAddr { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixDatagram::unbound()?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = socket.local_addr().expect("`UnixListener::local_addr` should not fail"); /// assert_eq!(addr.is_unnamed(), true); /// Ok(()) /// } @@ -224,7 +224,7 @@ impl SocketAddr { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixListener::bind("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = socket.local_addr().expect("`UnixListener::local_addr` should not fail"); /// assert_eq!(addr.as_pathname(), Some(Path::new("/tmp/sock"))); /// Ok(()) /// } @@ -238,7 +238,7 @@ impl SocketAddr { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixDatagram::unbound()?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = socket.local_addr().expect("`UnixListener::local_addr` should not fail"); /// assert_eq!(addr.as_pathname(), None); /// Ok(()) /// } diff --git a/library/std/src/os/unix/net/datagram.rs b/library/std/src/os/unix/net/datagram.rs index e03ecd7eed9ea..f80a3a887c54d 100644 --- a/library/std/src/os/unix/net/datagram.rs +++ b/library/std/src/os/unix/net/datagram.rs @@ -273,7 +273,7 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::bind("/path/to/the/socket")?; - /// let sock_copy = sock.try_clone().expect("try_clone failed"); + /// let sock_copy = sock.try_clone().expect("`UnixDatagram::try_clone` should not fail"); /// Ok(()) /// } /// ``` @@ -292,7 +292,7 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::bind("/path/to/the/socket")?; - /// let addr = sock.local_addr().expect("Couldn't get local address"); + /// let addr = sock.local_addr().expect("`UnixDatagram::local_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -317,7 +317,7 @@ impl UnixDatagram { /// let sock = UnixDatagram::unbound()?; /// sock.connect("/path/to/the/socket")?; /// - /// let addr = sock.peer_addr().expect("Couldn't get peer address"); + /// let addr = sock.peer_addr().expect("`UnixDatagram::peer_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -390,7 +390,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::bind("/path/to/the/socket")?; /// let mut buf = vec![0; 10]; - /// sock.recv(buf.as_mut_slice()).expect("recv function failed"); + /// sock.recv(buf.as_mut_slice()).expect("`UnixDatagram::recv` should not fail"); /// Ok(()) /// } /// ``` @@ -523,7 +523,7 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.send_to(b"omelette au fromage", "/some/sock").expect("send_to function failed"); + /// sock.send_to(b"omelette au fromage", "/some/sock").expect("`UnixDatagram::send_to` should not fail"); /// Ok(()) /// } /// ``` @@ -561,7 +561,7 @@ impl UnixDatagram { /// let addr = bound.local_addr()?; /// /// let sock = UnixDatagram::unbound()?; - /// sock.send_to_addr(b"bacon egg and cheese", &addr).expect("send_to_addr function failed"); + /// sock.send_to_addr(b"bacon egg and cheese", &addr).expect("`UnixDatagram::send_to_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -595,8 +595,8 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.connect("/some/sock").expect("Couldn't connect"); - /// sock.send(b"omelette au fromage").expect("send_to function failed"); + /// sock.connect("/some/sock").expect("`UnixDatagram::connect` should not fail"); + /// sock.send(b"omelette au fromage").expect("`UnixDatagram` is not connected"); /// Ok(()) /// } /// ``` @@ -638,7 +638,7 @@ impl UnixDatagram { /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); /// ancillary.add_fds(&fds[..]); /// sock.send_vectored_with_ancillary_to(bufs, &mut ancillary, "/some/sock") - /// .expect("send_vectored_with_ancillary_to function failed"); + /// .expect("`UnixDatagram::send_vectored_with_ancillary_to` should not fail"); /// Ok(()) /// } /// ``` @@ -686,7 +686,7 @@ impl UnixDatagram { /// let mut ancillary = SocketAncillary::new(&mut ancillary_buffer[..]); /// ancillary.add_fds(&fds[..]); /// sock.send_vectored_with_ancillary(bufs, &mut ancillary) - /// .expect("send_vectored_with_ancillary function failed"); + /// .expect("`UnixDatagram::send_vectored_with_ancillary` should not fail"); /// Ok(()) /// } /// ``` @@ -719,7 +719,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; /// sock.set_read_timeout(Some(Duration::new(1, 0))) - /// .expect("set_read_timeout function failed"); + /// .expect("`UnixDatagram::set_read_timeout` should not fail"); /// Ok(()) /// } /// ``` @@ -765,7 +765,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); + /// .expect("`UnixDatagram::set_write_timeout` should not fail"); /// Ok(()) /// } /// ``` @@ -804,7 +804,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; /// sock.set_read_timeout(Some(Duration::new(1, 0))) - /// .expect("set_read_timeout function failed"); + /// .expect("`UnixDatagram::set_read_timeout` should not fail"); /// assert_eq!(sock.read_timeout()?, Some(Duration::new(1, 0))); /// Ok(()) /// } @@ -826,7 +826,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; /// sock.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("set_write_timeout function failed"); + /// .expect("`UnixDatagram::set_write_timeout` should not fail"); /// assert_eq!(sock.write_timeout()?, Some(Duration::new(1, 0))); /// Ok(()) /// } @@ -846,7 +846,7 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.set_nonblocking(true).expect("set_nonblocking function failed"); + /// sock.set_nonblocking(true).expect("`UnixDatagram::set_nonblocking` should not fail"); /// Ok(()) /// } /// ``` @@ -914,7 +914,7 @@ impl UnixDatagram { /// /// fn main() -> std::io::Result<()> { /// let sock = UnixDatagram::unbound()?; - /// sock.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// sock.shutdown(Shutdown::Both).expect("`UnixDatagram::shutdown` should not fail"); /// Ok(()) /// } /// ``` @@ -941,7 +941,7 @@ impl UnixDatagram { /// fn main() -> std::io::Result<()> { /// let socket = UnixDatagram::bind("/tmp/sock")?; /// let mut buf = [0; 10]; - /// let len = socket.peek(&mut buf).expect("peek failed"); + /// let len = socket.peek(&mut buf).expect("`UnixDatagram::peek` should not fail"); /// Ok(()) /// } /// ``` diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs index b7f8d25a85ae5..793e2378e716d 100644 --- a/library/std/src/os/unix/net/listener.rs +++ b/library/std/src/os/unix/net/listener.rs @@ -200,7 +200,7 @@ impl UnixListener { /// /// fn main() -> std::io::Result<()> { /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// let listener_copy = listener.try_clone().expect("try_clone failed"); + /// let listener_copy = listener.try_clone().expect("`UnixListener::try_clone` should not fail"); /// Ok(()) /// } /// ``` @@ -219,7 +219,7 @@ impl UnixListener { /// /// fn main() -> std::io::Result<()> { /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// let addr = listener.local_addr().expect("Couldn't get local address"); + /// let addr = listener.local_addr().expect("`UnixListener::local_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -244,7 +244,7 @@ impl UnixListener { /// /// fn main() -> std::io::Result<()> { /// let listener = UnixListener::bind("/path/to/the/socket")?; - /// listener.set_nonblocking(true).expect("Couldn't set non blocking"); + /// listener.set_nonblocking(true).expect("`UnixListener::set_nonblocking` should not fail"); /// Ok(()) /// } /// ``` diff --git a/library/std/src/os/unix/net/stream.rs b/library/std/src/os/unix/net/stream.rs index 31a908dfe187e..dba49d0406bf1 100644 --- a/library/std/src/os/unix/net/stream.rs +++ b/library/std/src/os/unix/net/stream.rs @@ -199,7 +199,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// let sock_copy = socket.try_clone().expect("Couldn't clone socket"); + /// let sock_copy = socket.try_clone().expect("`UnixStream::try_clone` should not fail"); /// Ok(()) /// } /// ``` @@ -218,7 +218,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// let addr = socket.local_addr().expect("Couldn't get local address"); + /// let addr = socket.local_addr().expect("`UnixStream::local_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -237,7 +237,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// let addr = socket.peer_addr().expect("Couldn't get peer address"); + /// let addr = socket.peer_addr().expect("`UnixStream::peer_addr` should not fail"); /// Ok(()) /// } /// ``` @@ -257,7 +257,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// let peer_cred = socket.peer_cred().expect("Couldn't get peer credentials"); + /// let peer_cred = socket.peer_cred().expect("`UnixStream::peer_cred` should not fail"); /// Ok(()) /// } /// ``` @@ -295,7 +295,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("`UnixStream::set_read_timeout` should not fail"); /// Ok(()) /// } /// ``` @@ -340,7 +340,7 @@ impl UnixStream { /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; /// socket.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("Couldn't set write timeout"); + /// .expect("`UnixStream::connect` should not fail"); /// Ok(()) /// } /// ``` @@ -378,7 +378,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("Couldn't set read timeout"); + /// socket.set_read_timeout(Some(Duration::new(1, 0))).expect("`UnixStream::set_read_timeout` should not fail"); /// assert_eq!(socket.read_timeout()?, Some(Duration::new(1, 0))); /// Ok(()) /// } @@ -400,7 +400,7 @@ impl UnixStream { /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; /// socket.set_write_timeout(Some(Duration::new(1, 0))) - /// .expect("Couldn't set write timeout"); + /// .expect("`UnixStream::set_write_timeout` should not fail"); /// assert_eq!(socket.write_timeout()?, Some(Duration::new(1, 0))); /// Ok(()) /// } @@ -420,7 +420,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.set_nonblocking(true).expect("Couldn't set nonblocking"); + /// socket.set_nonblocking(true).expect("`UnixStream::set_nonblocking` should not fail"); /// Ok(()) /// } /// ``` @@ -493,7 +493,7 @@ impl UnixStream { /// /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; - /// socket.shutdown(Shutdown::Both).expect("shutdown function failed"); + /// socket.shutdown(Shutdown::Both).expect("`UnixStream::shutdown` should not fail"); /// Ok(()) /// } /// ``` @@ -520,7 +520,7 @@ impl UnixStream { /// fn main() -> std::io::Result<()> { /// let socket = UnixStream::connect("/tmp/sock")?; /// let mut buf = [0; 10]; - /// let len = socket.peek(&mut buf).expect("peek failed"); + /// let len = socket.peek(&mut buf).expect("`UnixStream::peek` should not fail"); /// Ok(()) /// } /// ``` From e69056d3551893000a0d9e504663145299347070 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 29 Sep 2026 11:39:49 +0200 Subject: [PATCH 0985/1309] update deferred subtype test --- ...eralize-subtyped-variables-old.next.stderr | 12 +++++ .../generalize-subtyped-variables-old.rs | 27 +++++++++++ .../generalize-subtyped-variables.rs | 45 ++++++++++++------- 3 files changed, 67 insertions(+), 17 deletions(-) create mode 100644 tests/ui/type-inference/generalize-subtyped-variables-old.next.stderr create mode 100644 tests/ui/type-inference/generalize-subtyped-variables-old.rs diff --git a/tests/ui/type-inference/generalize-subtyped-variables-old.next.stderr b/tests/ui/type-inference/generalize-subtyped-variables-old.next.stderr new file mode 100644 index 0000000000000..ce703154fc7ac --- /dev/null +++ b/tests/ui/type-inference/generalize-subtyped-variables-old.next.stderr @@ -0,0 +1,12 @@ +error[E0308]: mismatched types + --> $DIR/generalize-subtyped-variables-old.rs:23:26 + | +LL | let mut w = (&mut x, z, z); + | ^ expected `Option fn(&'a ())>`, found `Option` + | + = note: expected enum `Option fn(&'a ())>` + found enum `Option` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0308`. diff --git a/tests/ui/type-inference/generalize-subtyped-variables-old.rs b/tests/ui/type-inference/generalize-subtyped-variables-old.rs new file mode 100644 index 0000000000000..3eb58a62fdbe6 --- /dev/null +++ b/tests/ui/type-inference/generalize-subtyped-variables-old.rs @@ -0,0 +1,27 @@ +// A test for the way we handle higher-ranked subtyping and subtyping requirements. +// +// - `let y = x` creates a `Subtype` obligation that is deferred for later. +// - `w = a` sets the type of `x` to `Option fn(&'a ())>` and generalized +// `z` first to `Option<_>` and then to `Option`. +// - The various subtyping obligations are then processed. +// +// Whether the `?x <: ?y` obligation incorrectly constrains `?y` to +// `Option fn(&'a ())>` is order dependent and passed with the old +// solver while breaking with the new one. +// +// Found when considering fixes to #117151 + +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[old] check-pass + +fn main() { + let mut x = None; + let y = x; + let z = Default::default(); + let mut w = (&mut x, z, z); + //[next]~^ ERROR: mismatched types + let a = (&mut None::, y, None::); + w = a; +} diff --git a/tests/ui/type-inference/generalize-subtyped-variables.rs b/tests/ui/type-inference/generalize-subtyped-variables.rs index b7cae32ee32ff..558e25cd39a97 100644 --- a/tests/ui/type-inference/generalize-subtyped-variables.rs +++ b/tests/ui/type-inference/generalize-subtyped-variables.rs @@ -1,25 +1,36 @@ -// Test for specific details of how we handle higher-ranked subtyping to make -// sure that any changes are made deliberately. +// A test checking whether we eagerly apply subtype requirements +// when relating types. This relies on incomplete inference with +// higher-ranked types. If we eagerly apply the `?x <: ?y` subtype +// requirements after constraining `?x` to `for<'a> fn(&'a ())` we +// would incorrectly constrain `?y` to also be `for<'a> fn(&'a ())`. // -// - `let y = x` creates a `Subtype` obligation that is deferred for later. -// - `w = a` sets the type of `x` to `Option fn(&'a ())>` and generalizes -// `z` first to `Option<_>` and then to `Option`. -// - The various subtyping obligations are then processed. +// This would then result in an error when relating `y` with `Inv`. // -// This requires that -// 1. the `Subtype` obligation from `y = x` isn't processed while the types of -// `w` and `a` are being unified. -// 2. the pending subtype obligation isn't considered when determining the type -// to generalize `z` to first (when related to the type of `y`). -// -// Found when considering fixes to #117151 +// It's fine for this behavior to change, we should do so intentionally however. + +//@ revisions: old next +//@[next] compile-flags: -Znext-solver +//@ ignore-compare-mode-next-solver (explicit revisions) //@ check-pass +fn to_inv(x: Option) -> Inv { + Inv(None) +} +#[derive(Copy, Clone)] +struct Inv(Option<*mut T>); + fn main() { - let mut x = None; + let x = None; let y = x; - let z = Default::default(); - let mut w = (&mut x, z, z); - let a = (&mut None::, y, None::); + let mut x = to_inv(x); + let y = to_inv(y); + // deferred ?x <: ?y + let z = Inv(None); + // type_of(w) = (Inv, Inv, Inv) + let mut w = (x, z, z); + // type_of(a) = (Inv fn(&'a ())>, Inv, Inv) + let a = (Inv::(None), y, Inv::(None)); + // ?x = for<'a> fn(&'a ()) + // ?y = fn(&'static ()) w = a; } From 5b172d928a56980fc534b5ff8f363354df804fc2 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Wed, 23 Sep 2026 08:36:40 +0200 Subject: [PATCH 0986/1309] =?UTF-8?q?rename=20metadata=5Fat=20=E2=86=92=20?= =?UTF-8?q?metadata=20(and=20metadata=20=E2=86=92=20self=5Fmetadata)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- library/std/src/fs.rs | 24 ++++++----- library/std/src/fs/tests.rs | 16 ++++---- library/std/src/sys/fs/common.rs | 6 +-- library/std/src/sys/fs/unix.rs | 57 +++++++++++++++----------- library/std/src/sys/fs/unix/dir.rs | 24 +++++------ library/std/src/sys/fs/windows/dir.rs | 14 +++---- src/tools/miri/src/shims/files.rs | 5 ++- src/tools/miri/src/shims/windows/fs.rs | 6 ++- 8 files changed, 84 insertions(+), 68 deletions(-) diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs index e7efa32af6964..3f0f276551b45 100644 --- a/library/std/src/fs.rs +++ b/library/std/src/fs.rs @@ -1637,6 +1637,8 @@ impl Dir { /// Queries metadata about the underlying directory. /// + /// This is equivalent to `dir.metadata(".")` but can be more efficient. + /// /// # Examples /// /// ```no_run @@ -1645,13 +1647,13 @@ impl Dir { /// /// fn main() -> std::io::Result<()> { /// let dir = Dir::open("foo")?; - /// let metadata = dir.metadata()?; + /// let metadata = dir.self_metadata()?; /// Ok(()) /// } /// ``` #[unstable(feature = "dirfd", issue = "120426")] - pub fn metadata(&self) -> io::Result { - self.inner.metadata().map(Metadata) + pub fn self_metadata(&self) -> io::Result { + self.inner.self_metadata().map(Metadata) } /// Attempts to open a file in read-only mode relative to this directory. @@ -1897,7 +1899,7 @@ impl Dir { /// /// This function will traverse symbolic links to query information about the destination file. /// To query metadata about the path itself without following symbolic links, use - /// [`symlink_metadata_at`][Self::symlink_metadata_at]. + /// [`symlink_metadata`][Self::symlink_metadata]. /// /// # Examples /// @@ -1907,13 +1909,13 @@ impl Dir { /// /// fn main() -> std::io::Result<()> { /// let dir = Dir::open("foo")?; - /// let metadata = dir.metadata_at("subdir/file.txt")?; + /// let metadata = dir.metadata("subdir/file.txt")?; /// Ok(()) /// } /// ``` #[unstable(feature = "dirfd", issue = "120426")] - pub fn metadata_at>(&self, path: P) -> io::Result { - self.inner.metadata_at(path.as_ref()).map(Metadata) + pub fn metadata>(&self, path: P) -> io::Result { + self.inner.metadata(path.as_ref()).map(Metadata) } /// Queries the file system to get information about a file, directory, etc. relative to this @@ -1921,7 +1923,7 @@ impl Dir { /// /// This function will return the [`Metadata`] of the exact path without traversing symbolic /// links to a resolved destination file. Using this function on a path that is a file or - /// directory (not a symbolic link) will behave the same as [`metadata_at`][Self::metadata_at]. + /// directory (not a symbolic link) will behave the same as [`metadata`][Self::metadata]. /// /// # Examples /// @@ -1931,13 +1933,13 @@ impl Dir { /// /// fn main() -> std::io::Result<()> { /// let dir = Dir::open("foo")?; - /// let metadata = dir.symlink_metadata_at("subdir/file.txt")?; + /// let metadata = dir.symlink_metadata("subdir/file.txt")?; /// Ok(()) /// } /// ``` #[unstable(feature = "dirfd", issue = "120426")] - pub fn symlink_metadata_at>(&self, path: P) -> io::Result { - self.inner.symlink_metadata_at(path.as_ref()).map(Metadata) + pub fn symlink_metadata>(&self, path: P) -> io::Result { + self.inner.symlink_metadata(path.as_ref()).map(Metadata) } } diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs index 15711652cb05f..d1d39d144e4b1 100644 --- a/library/std/src/fs/tests.rs +++ b/library/std/src/fs/tests.rs @@ -3010,10 +3010,10 @@ fn test_dir_clone() { } #[test] -fn test_dir_metadata() { +fn test_dir_self_metadata() { let tmpdir = tmpdir(); let dir = check!(Dir::open(tmpdir.path())); - let metadata = check!(dir.metadata()); + let metadata = check!(dir.self_metadata()); assert!(metadata.is_dir()); } @@ -3103,7 +3103,7 @@ fn test_dir_open_dir() { } #[test] -fn test_dir_metadata_at() { +fn test_dir_metadata() { let tmpdir = tmpdir(); let dir = check!(Dir::open(tmpdir.path())); check!(dir.create_dir("subdir")); @@ -3112,16 +3112,16 @@ fn test_dir_metadata_at() { drop(check!(dir.open_file_with(&barpath, &OpenOptions::new().create(true).write(true)))); check!(symlink_file(&tmpdir.join("subdir/bar.txt"), &tmpdir.join("link"))); - let metadata = check!(dir.metadata_at(&barpath)); + let metadata = check!(dir.metadata(&barpath)); assert!(metadata.is_file()); - let metadata = check!(dir.metadata_at("subdir")); + let metadata = check!(dir.metadata("subdir")); assert!(metadata.is_dir()); - dir.metadata_at("does-not-exist").unwrap_err(); + dir.metadata("does-not-exist").unwrap_err(); - let metadata = check!(dir.metadata_at("link")); + let metadata = check!(dir.metadata("link")); assert!(metadata.is_file()); assert!(!metadata.is_symlink()); - let metadata = check!(dir.symlink_metadata_at("link")); + let metadata = check!(dir.symlink_metadata("link")); assert!(!metadata.is_file()); assert!(metadata.is_symlink()); } diff --git a/library/std/src/sys/fs/common.rs b/library/std/src/sys/fs/common.rs index 70cb57ac2915d..1724e6115462e 100644 --- a/library/std/src/sys/fs/common.rs +++ b/library/std/src/sys/fs/common.rs @@ -85,7 +85,7 @@ impl Dir { File::open(&self.path.join(path), opts) } - pub fn metadata(&self) -> io::Result { + pub fn self_metadata(&self) -> io::Result { self.path.metadata().map(|m| m.into_inner()) } @@ -109,11 +109,11 @@ impl Dir { remove_dir(self.path.join(path)) } - pub fn metadata_at(&self, path: &Path) -> io::Result { + pub fn metadata(&self, path: &Path) -> io::Result { self.path.join(path).metadata().map(|m| m.into_inner()) } - pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { + pub fn symlink_metadata(&self, path: &Path) -> io::Result { self.path.join(path).symlink_metadata().map(|m| m.into_inner()) } } diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs index 988bacd57d1b2..6d1c01be6078f 100644 --- a/library/std/src/sys/fs/unix.rs +++ b/library/std/src/sys/fs/unix.rs @@ -6,6 +6,39 @@ #[cfg(test)] mod tests; +// Import the file operations under consistent names. +cfg_select! { + not(any( + all(target_os = "linux", not(target_env = "musl")), + target_os = "android", + target_os = "hurd", + target_os = "l4re", + )) => { + use libc::{ + dirent as dirent64, fstat as fstat64, ftruncate as ftruncate64, lseek as lseek64, + lstat as lstat64, off_t as off64_t, open as open64, stat as stat64, + }; + } + target_os = "android" => { + // Android's `stat`, `dirent`, and related functions are always 64-bit LFS compatible, and + // `open` already implies `O_LARGEFILE`, so all those don't need to follow Linux. + // However, we still need off64_t, ftruncate64, and lseek64. + use libc::{ + dirent as dirent64, fstat as fstat64, ftruncate64, lseek64, lstat as lstat64, off64_t, + open as open64, stat as stat64, + }; + } + target_os = "l4re" => { + use libc::{ + dirent64, fstat as fstat64, ftruncate as ftruncate64, lseek as lseek64, + lstat as lstat64, off_t as off64_t, open as open64, stat as stat64, + }; + } + _ => { + use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64}; + } +} + #[cfg(all(target_os = "linux", target_env = "gnu"))] use libc::c_char; #[cfg(any( @@ -18,28 +51,6 @@ use libc::c_char; ))] use libc::dirfd; use libc::{c_int, mode_t}; -#[cfg(target_os = "android")] -use libc::{ - dirent as dirent64, fstat as fstat64, fstatat as fstatat64, ftruncate64, lseek64, - lstat as lstat64, off64_t, open as open64, stat as stat64, -}; -#[cfg(not(any( - all(target_os = "linux", not(target_env = "musl")), - target_os = "android", - target_os = "hurd", - target_os = "l4re", -)))] -use libc::{ - dirent as dirent64, fstat as fstat64, ftruncate as ftruncate64, lseek as lseek64, - lstat as lstat64, off_t as off64_t, open as open64, stat as stat64, -}; -#[cfg(target_os = "l4re")] -use libc::{ - dirent64, fstat as fstat64, ftruncate as ftruncate64, lseek as lseek64, lstat as lstat64, - off_t as off64_t, open as open64, stat as stat64, -}; -#[cfg(any(all(target_os = "linux", not(target_env = "musl")), target_os = "hurd"))] -use libc::{dirent64, fstat64, ftruncate64, lseek64, lstat64, off64_t, open64, stat64}; use crate::ffi::{CStr, OsStr, OsString}; use crate::fmt::{self, Write as _}; @@ -1033,7 +1044,7 @@ impl DirEntry { let dir_handle = mem::ManuallyDrop::new(dir::Dir(unsafe { OwnedFd::from_raw_fd(fd) })); - dir_handle.metadata_at_c(&self.name, /* symlink_nofollow */ true) + dir_handle.metadata_c(&self.name, /* symlink_nofollow */ true) } // Fallback based on path diff --git a/library/std/src/sys/fs/unix/dir.rs b/library/std/src/sys/fs/unix/dir.rs index 087916fd9ff63..dd01db58c600d 100644 --- a/library/std/src/sys/fs/unix/dir.rs +++ b/library/std/src/sys/fs/unix/dir.rs @@ -4,16 +4,16 @@ cfg_select! { not(any( all(target_os = "linux", not(target_env = "musl")), target_os = "l4re", - target_os = "android", target_os = "hurd", )) => { - use libc::{fstatat as fstatat64, open as open64, openat as openat64}; + use libc::{fstatat as fstatat64, openat as openat64}; } _ => { - use libc::{fstatat64, open64, openat64}; + use libc::{fstatat64, openat64}; } } +use super::{open64, stat64}; use crate::ffi::CStr; use crate::os::fd::{AsFd, BorrowedFd, IntoRawFd, OwnedFd, RawFd}; #[cfg(target_family = "unix")] @@ -57,7 +57,7 @@ impl Dir { .map(File) } - pub fn metadata(&self) -> io::Result { + pub fn self_metadata(&self) -> io::Result { // Reuse the implementation for files, which should work for all FDs. let fd = self.0.as_raw_fd(); let f = core::mem::ManuallyDrop::new(File( @@ -89,14 +89,14 @@ impl Dir { run_path_with_cstr(path, &|path| self.remove_c(path, /* remove_dir */ true)) } - pub fn metadata_at(&self, path: &Path) -> io::Result { + pub fn metadata(&self, path: &Path) -> io::Result { run_path_with_cstr(path, &|path| { - self.metadata_at_c(path, /* symlink_nofollow */ false) + self.metadata_c(path, /* symlink_nofollow */ false) }) } - pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { - run_path_with_cstr(path, &|path| self.metadata_at_c(path, /* symlink_nofollow */ true)) + pub fn symlink_metadata(&self, path: &Path) -> io::Result { + run_path_with_cstr(path, &|path| self.metadata_c(path, /* symlink_nofollow */ true)) } fn open_with_c(path: &CStr, opts: &OpenOptions) -> io::Result { @@ -154,11 +154,7 @@ impl Dir { cvt(unsafe { mkdirat(self.0.as_raw_fd(), path.as_ptr(), 0o777) }).map(|_| ()) } - pub(super) fn metadata_at_c( - &self, - path: &CStr, - symlink_nofollow: bool, - ) -> io::Result { + pub(super) fn metadata_c(&self, path: &CStr, symlink_nofollow: bool) -> io::Result { let fd = self.0.as_raw_fd(); let flag = if symlink_nofollow { libc::AT_SYMLINK_NOFOLLOW } else { 0 }; @@ -173,7 +169,7 @@ impl Dir { } } - let mut stat: super::stat64 = unsafe { mem::zeroed() }; + let mut stat: stat64 = unsafe { mem::zeroed() }; cvt(unsafe { fstatat64(fd, path.as_ptr(), &mut stat, flag) })?; Ok(FileAttr::from_stat64(stat)) } diff --git a/library/std/src/sys/fs/windows/dir.rs b/library/std/src/sys/fs/windows/dir.rs index 7b8cd60fd8d06..60f8c2522de26 100644 --- a/library/std/src/sys/fs/windows/dir.rs +++ b/library/std/src/sys/fs/windows/dir.rs @@ -223,7 +223,7 @@ impl Dir { .io_result() } - pub fn metadata(&self) -> io::Result { + pub fn self_metadata(&self) -> io::Result { // Reuse the implementation for files, which should work for all handles. let handle = self.handle.as_raw_handle(); let f = core::mem::ManuallyDrop::new(File { @@ -233,14 +233,14 @@ impl Dir { f.file_attr() } - pub fn metadata_at(&self, path: &Path) -> io::Result { + pub fn metadata(&self, path: &Path) -> io::Result { let path = to_u16s_without_nul(path)?; // Same as the `stat` logic used for `fs::metadata` - match self.metadata_at_native(&path, ReparsePoint::Follow) { + match self.metadata_native(&path, ReparsePoint::Follow) { Err(err) if err.raw_os_error() == Some(c::ERROR_CANT_ACCESS_FILE as i32) => { // Fallback to opening reparse points when following fails. Needed for UNIX domain // sockets. See . - if let Ok(attrs) = self.metadata_at_native(&path, ReparsePoint::Open) { + if let Ok(attrs) = self.metadata_native(&path, ReparsePoint::Open) { if !attrs.file_type().is_symlink() { return Ok(attrs); } @@ -251,12 +251,12 @@ impl Dir { } } - pub fn symlink_metadata_at(&self, path: &Path) -> io::Result { + pub fn symlink_metadata(&self, path: &Path) -> io::Result { let path = to_u16s_without_nul(path)?; - self.metadata_at_native(&path, ReparsePoint::Open) + self.metadata_native(&path, ReparsePoint::Open) } - fn metadata_at_native(&self, path: &[u16], reparse: ReparsePoint) -> io::Result { + fn metadata_native(&self, path: &[u16], reparse: ReparsePoint) -> io::Result { let mut opts = OpenOptions::new(); // the NT functions need at least c::FILE_READ_ATTRIBUTES opts.access_mode(c::FILE_READ_ATTRIBUTES); diff --git a/src/tools/miri/src/shims/files.rs b/src/tools/miri/src/shims/files.rs index d73ce57f64f19..cd7a7f4f0250b 100644 --- a/src/tools/miri/src/shims/files.rs +++ b/src/tools/miri/src/shims/files.rs @@ -524,7 +524,10 @@ impl FileDescription for DirHandle { fn metadata<'tcx>( &self, ) -> InterpResult<'tcx, Either, &'static str>> { - interp_ok(Either::Left(self.dir.metadata())) + #[cfg(bootstrap)] + return interp_ok(Either::Left(self.dir.metadata())); + #[cfg(not(bootstrap))] + return interp_ok(Either::Left(self.dir.self_metadata())); } } diff --git a/src/tools/miri/src/shims/windows/fs.rs b/src/tools/miri/src/shims/windows/fs.rs index 9aae6677faeb2..bab26d80dee70 100644 --- a/src/tools/miri/src/shims/windows/fs.rs +++ b/src/tools/miri/src/shims/windows/fs.rs @@ -225,7 +225,11 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> { return interp_ok(Handle::Invalid); } }; - if !dir.metadata().unwrap().is_dir() { + #[cfg(bootstrap)] + let metadata = dir.metadata(); + #[cfg(not(bootstrap))] + let metadata = dir.self_metadata(); + if !metadata.unwrap().is_dir() { // This changed from a directory to a file. Retry. continue; } From da3a40895ea4fe8c4efc444be02d4270a7d144e6 Mon Sep 17 00:00:00 2001 From: Boxy Uwu Date: Tue, 29 Sep 2026 10:16:10 +0000 Subject: [PATCH 0987/1309] add relnotes 1.99.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Asger Hautop Drewsen Co-authored-by: Boxy Co-authored-by: Mark Rousskov Co-authored-by: 许杰友 Jieyou Xu (Joe) <39484203+jieyouxu@users.noreply.github.com> --- RELEASES.md | 130 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 130 insertions(+) diff --git a/RELEASES.md b/RELEASES.md index 34984a29eff51..77b58ce2bcf25 100644 --- a/RELEASES.md +++ b/RELEASES.md @@ -1,3 +1,133 @@ +Version 1.99.0 (2026-10-01) +========================== + + + +Language +-------- +- [Add allow-by-default `raw_borrows_via_references` lint that checks for references that decay immediately into raw borrows](https://github.com/rust-lang/rust/pull/138230) +- [Extend `unconditional_panic` lint to function calls that panic when the chunks/windows size is zero](https://github.com/rust-lang/rust/pull/153563) +- [Stabilize C-variadic function definitions](https://github.com/rust-lang/rust/pull/155697) +- [Stabilize the ability to use `#[unsafe(naked)]` functions to define C-variadic functions (`#![feature(c_variadic_naked_functions)]`).](https://github.com/rust-lang/rust/pull/159746) +- [Trait methods are now resolved on an adjusted never type (producing a FCW)](https://github.com/rust-lang/rust/pull/156047) +- [Coerce from inference variables to trait objects if the inference variable is related via subtyping to a type that is known to be `Sized`](https://github.com/rust-lang/rust/pull/157820) +- [Stabilize `#[my_macro] mod foo;`](https://github.com/rust-lang/rust/pull/157857). This allows outlined modules (`mod foo;`) anywhere in the body of a custom attribute or derive macro. +- [Fix the `overflowing_literals` lint with repeated negation](https://github.com/rust-lang/rust/pull/158302). For instance, it will now no longer lint on `--128_i8`, which is already detected by the `arithmetic_overflow` lint. +- [Add POSIX symbols to the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` lints](https://github.com/rust-lang/rust/pull/158522) +- [Lint unused `#[path]` attributes on inline modules](https://github.com/rust-lang/rust/pull/158835) +- [Enable `unreachable_cfg_select_predicates` lint as part of `unused` lint group](https://github.com/rust-lang/rust/pull/159179) +- [Stabilize passing 128-bit integers via vector registers with `asm!` on x86](https://github.com/rust-lang/rust/pull/159525) +- [Explicitly document that some allocations are allowed to grow in-place (but none are allowed to shrink)](https://github.com/rust-lang/rust/pull/159729) +- We now [guarantee](https://github.com/rust-lang/rust/pull/159730) that the contents of an `UnsafeCell` can be accessed without going through `get` + - [The `invalid_reference_casting` lint was adjusted accordingly](https://github.com/rust-lang/rust/pull/159960) +- [Account for globally enabled target features in `global_asm!`](https://github.com/rust-lang/rust/pull/160594) +- [Warn if an invalid `doc` attribute is used on a macro invocation](https://github.com/rust-lang/rust/pull/161003) + + + + +Compiler +-------- +- [Convert `-Ctarget-cpu` into a target-modifier for AVR, AMDGCN and NVPTX](https://github.com/rust-lang/rust/pull/150732) +- [Enable `static_position_independent_executables` on all gnu targets](https://github.com/rust-lang/rust/pull/158510) +- When providing a suggestion about a missing method, rustc now prefers an exactly matching name from a [doc alias attribute](https://doc.rust-lang.org/rustdoc/advanced-features.html#add-aliases-for-an-item-in-documentation-search) over a similarity search from other method names. If your new users sometimes expect a method under a different name, adding a doc alias will now help them find it via rustc suggestions, in addition to helping them find it via rustdoc search: [When suggesting method names, prefer *exact* doc aliases over similar names](https://github.com/rust-lang/rust/pull/160369) + + + + +Platform Support +---------------- +- [Promote `riscv64-unknown-linux-musl` to Tier 2 with host tools](https://github.com/rust-lang/rust/pull/158766) + + +Refer to Rust's [platform support page][platform-support-doc] +for more information on Rust's tiered platform support. + +[platform-support-doc]: https://doc.rust-lang.org/rustc/platform-support.html + + + +Libraries +--------- +- Iteration on `RangeInclusive` (`a..=b` ranges) is now [optimized better in some circumstances](https://github.com/rust-lang/rust/pull/155114). As a side effect of this, the behavior of `RangeInclusive` values that has already been exhausted (as an iterator) has changed. For example, the return values of `start()` and `end()` on such ranges may return different values, and using such ranges as slice indexes may have different behavior. These behaviors were not guaranteed to be stable, so these changes are considered to not be breaking changes. +- [Relax `transmute_copy` to accept `?Sized` types](https://github.com/rust-lang/rust/pull/155989) +- [Update `transmute_copy` to use a non-unwinding panic](https://github.com/rust-lang/rust/pull/155989) +- [Don't escape U+FF9E and U+FF9F in `escape_debug_ext`](https://github.com/rust-lang/rust/pull/158057) +- [Re-export `core::fmt::NumBuffer` in `alloc` (and `std`)](https://github.com/rust-lang/rust/pull/161430) + + + + +Stabilized APIs +--------------- + +- [`IntoIterator` for `Box<[T; N]>`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html#impl-IntoIterator-for-Box%3C%5BT;+N%5D,+A%3E) +- [`IntoIterator` for `&Box<[T; N]>`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html#impl-IntoIterator-for-%26Box%3C%5BT;+N%5D,+A%3E) +- [`IntoIterator` for `&mut Box<[T; N]>`](https://doc.rust-lang.org/stable/std/iter/trait.IntoIterator.html#impl-IntoIterator-for-%26mut+Box%3C%5BT;+N%5D,+A%3E) +- [`VecDeque::retain_back`](https://doc.rust-lang.org/stable/std/collections/struct.VecDeque.html#method.retain_back) +- [`core::ffi::VaList`](https://doc.rust-lang.org/stable/core/ffi/struct.VaList.html) +- [`Box::into_non_null`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.into_non_null) +- [`Box::from_non_null`](https://doc.rust-lang.org/stable/std/boxed/struct.Box.html#method.from_non_null) +- [`Vec::into_parts`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.into_parts) +- [`Vec::from_parts`](https://doc.rust-lang.org/stable/std/vec/struct.Vec.html#method.from_parts) +- [`core::mem::size_of_val_raw`](https://doc.rust-lang.org/stable/core/mem/fn.size_of_val_raw.html) +- [`core::mem::align_of_val_raw`](https://doc.rust-lang.org/stable/core/mem/fn.align_of_val_raw.html) +- [`core::alloc::Layout::for_value_raw`](https://doc.rust-lang.org/stable/core/alloc/struct.Layout.html#method.for_value_raw) +- [`String::from_utf8_lossy_owned`](https://doc.rust-lang.org/stable/std/string/struct.String.html#method.from_utf8_lossy_owned) +- [`string::FromUtf8Error::into_utf8_lossy`](https://doc.rust-lang.org/stable/std/string/struct.FromUtf8Error.html#method.into_utf8_lossy) +- [`FusedIterator for StepBy`](https://doc.rust-lang.org/stable/std/iter/struct.StepBy.html#impl-FusedIterator-for-StepBy%3CI%3E) +- [`std::fs::set_times`](https://doc.rust-lang.org/stable/std/fs/fn.set_times.html) +- [`std::fs::set_times_nofollow`](https://doc.rust-lang.org/stable/std/fs/fn.set_times_nofollow.html) + + + +Cargo +----- +- Add a new built-in profile `debug`. This is a preparation for transitioning the `dev` profile away from debugging to give a saner default for faster development iterations. Currently there is no difference between `dev` and `debug` profiles. [docs](https://doc.rust-lang.org/nightly/cargo/reference/profiles.html#debug-1) [#17214](https://github.com/rust-lang/cargo/pull/17214) +- Workspace members on edition 2024 or later can now override an inherited workspace dependency's `default-features` field. For example, `serde = { workspace = true, default-features = false }` now turns off default features even when the workspace definition enables them. On earlier editions, `default-features = false` is ignored with a warning. ([RFC 3945](https://github.com/rust-lang/rfcs/pull/3945)) [#17126](https://github.com/rust-lang/cargo/pull/17126) + +See also the [full Cargo changelog](https://doc.rust-lang.org/nightly/cargo/CHANGELOG.html#cargo-199-2026-10-01) + + + +Rustdoc +----- +- [Add new `unused_footnote_definition` rustdoc lint](https://github.com/rust-lang/rust/pull/137858) +- Smarter filtering of trait impls yields performance improvements of 20% on average and up to 40% on some real-world crates. ([1](https://github.com/rust-lang/rust/pull/159623), [2](https://github.com/rust-lang/rust/pull/159721), [3](https://github.com/rust-lang/rust/pull/159779), [4](https://github.com/rust-lang/rust/pull/159854), [5](https://github.com/rust-lang/rust/pull/159091)) + + + +Compatibility Notes +------------------- +- [Fully deprecate the legacy integral modules](https://github.com/rust-lang/rust/pull/146882). For example, `std::i32::MAX` should be accessed via `i32::MAX` instead. +- [Upgrade `no_mangle_generic_items` into hard error](https://github.com/rust-lang/rust/pull/154585) +- [The `Pin::new_unchecked` has had its safety invariants changed slightly](https://github.com/rust-lang/rust/pull/156935) +- [Do not promote references to extern statics](https://github.com/rust-lang/rust/pull/157641) +- [Ensure that the inferred types of `let` patterns typecheck](https://github.com/rust-lang/rust/pull/157841) +- [hermit/fs: Return `unsupported()` instead of `from_raw_os_error(22)`](https://github.com/rust-lang/rust/pull/158247) +- [Fixed a bug where `#[repr(simd)]` was accidentally allowed on macro invocations on stable Rust](https://github.com/rust-lang/rust/pull/158523) +- [Abort const-eval when there are generics in the type of the value being produced](https://github.com/rust-lang/rust/pull/159504) +- [Attributes not applying to anything are now an error in code blocks in doc comments](https://github.com/rust-lang/rust/pull/159849) +- [`Box::leak`: tell people to avoid unleaking](https://github.com/rust-lang/rust/pull/160323) +- [PowerPC inline ASM: Fix scalar floats being in the wrong vector lane on little endian](https://github.com/rust-lang/rust/pull/160441) +- [Do not take `doc(cfg())` into account when filtering doctests](https://github.com/rust-lang/rust/pull/159014) +- [Infer anonymous lifetimes in the types of associated consts as `'static`](https://github.com/rust-lang/rust/pull/156508) +- Macros that expand to a semicolon now produce a warning lint (`semicolon_in_expressions_from_non_local_macros`) even when the macro comes from another crate. Previously, such warnings only appeared for macros from the same crate, to avoid showing warnings that can't be fixed locally; however, this masked problems, as integration tests from the crate providing the macro get compiled as a separate crate, so tests often wouldn't reveal this issue. If you encounter a lint like this, please make sure to report it to the crate providing the macro so they can fix it; don't just silence it in your own crate. + - [`semicolon_in_expressions_from_macros`: Lint on non-local macros too](https://github.com/rust-lang/rust/pull/159222) + - [Split non-local `semicolon_in_expressions_from_macros` into a separate lint](https://github.com/rust-lang/rust/pull/159700) +- In Cargo, incremental compilation is now disabled by default when running in CI. CI is detected via the `CI` environment variable. [#17220](https://github.com/rust-lang/cargo/pull/17220) + + + +Internal Changes +---------------- + +These changes do not affect any public interfaces of Rust, but they represent +significant improvements to the performance or internals of rustc and related +tools. + +- [Update to LLVM 23](https://github.com/rust-lang/rust/pull/158734) + Version 1.98.1 (2026-09-03) =========================== From f9d80e6e5fa48e233aeb88826964dad4930b651d Mon Sep 17 00:00:00 2001 From: yuwk <1729065730@qq.com> Date: Tue, 29 Sep 2026 18:26:14 +0800 Subject: [PATCH 0988/1309] docs: fix `supress` and `excessive_precicion` typos in configuration docs Signed-off-by: yuwk <1729065730@qq.com> --- book/src/lint_configuration.md | 2 +- clippy_config/src/conf.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/book/src/lint_configuration.md b/book/src/lint_configuration.md index b99ae21eaace6..0cb26a63f945a 100644 --- a/book/src/lint_configuration.md +++ b/book/src/lint_configuration.md @@ -544,7 +544,7 @@ The maximum cognitive complexity a function can have ## `const-literal-digits-threshold` -The minimum digits a const float literal must have to supress the `excessive_precicion` lint +The minimum digits a const float literal must have to suppress the `excessive_precision` lint **Default Value:** `30` diff --git a/clippy_config/src/conf.rs b/clippy_config/src/conf.rs index ab809997abc66..eee24f76d2f58 100644 --- a/clippy_config/src/conf.rs +++ b/clippy_config/src/conf.rs @@ -479,7 +479,7 @@ define_Conf! { /// The maximum cognitive complexity a function can have #[lints(cognitive_complexity)] cognitive_complexity_threshold("cognitive-complexity-threshold"): u64 = 25, - /// The minimum digits a const float literal must have to supress the `excessive_precicion` lint + /// The minimum digits a const float literal must have to suppress the `excessive_precision` lint #[lints(excessive_precision)] const_literal_digits_threshold("const-literal-digits-threshold"): u32 = 30, #[rename = cognitive_complexity_threshold] From c2248256e9936f6a9666843b8cd890fc0aa1bb99 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 29 Sep 2026 18:38:02 +0800 Subject: [PATCH 0989/1309] test(config): add regression test for `adjust_max_width` overflows For . --- src/tools/rustfmt/src/config/mod.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index 780402d21fe29..141933cd7cfa9 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -698,6 +698,23 @@ mod test { assert_eq!(config.verbose(), Verbosity::Normal); } + #[test] + fn test_adjust_max_width() { + // Regression tests for #7147, where we didn't handle overflows / integral cast outside of + // range properly. + + // Reduce with huge amount saturates to zero instead of wraparound. + let mut config = Config::default(); + config.reduce_max_width(usize::MAX); + assert_eq!(config.max_width(), 0); + + // Increase with huge amount saturates instead of wraparound. + let mut config = Config::default(); + config.set().max_width(usize::MAX - 1); + config.increase_max_width(2); + assert_eq!(config.max_width(), usize::MAX); + } + #[test] fn test_config_used_to_toml() { let config = Config::default(); From 5e9724cc02b002f2263801efee4e6226ed77e699 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 29 Sep 2026 18:39:46 +0800 Subject: [PATCH 0990/1309] docs(config): `increase_max_width` actually increases max width Copy-pasta typo. --- src/tools/rustfmt/src/config/config_type.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs index f559cc0d620c4..d078fbb8c30ae 100644 --- a/src/tools/rustfmt/src/config/config_type.rs +++ b/src/tools/rustfmt/src/config/config_type.rs @@ -442,7 +442,7 @@ macro_rules! create_config { /// /// This method is intended to be used when creating a forked /// configuration for a particular formatting context in which the - /// total available width needs to be reduced. This increases the + /// total available width needs to be increased. This increases the /// size of max_width, and all other properties affected by small /// heuristics, without treating those adjustments as overrides. /// From 942efae16184d3d6f5f5951339cb7da13a4c287c Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 29 Sep 2026 18:40:38 +0800 Subject: [PATCH 0991/1309] fix(config): use saturating arithmetics in `adjust_max_width` Instead of overflows, or arguably worse, bitwise reinterpretations. They tend to give us garbage (and massive) indentations. --- src/tools/rustfmt/src/config/config_type.rs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/tools/rustfmt/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs index d078fbb8c30ae..6611a387814ab 100644 --- a/src/tools/rustfmt/src/config/config_type.rs +++ b/src/tools/rustfmt/src/config/config_type.rs @@ -435,7 +435,7 @@ macro_rules! create_config { /// arms within a declarative macro. #[allow(unreachable_pub)] pub fn reduce_max_width(&mut self, delta: usize) { - self.adjust_max_width(-(delta as isize)); + self.adjust_max_width(-(delta.min(isize::MAX as usize) as isize)); } /// Increases the maximum width of the configuration. @@ -450,7 +450,7 @@ macro_rules! create_config { /// arms within a declarative macro. #[allow(unreachable_pub)] pub fn increase_max_width(&mut self, delta: usize) { - self.adjust_max_width(delta as isize); + self.adjust_max_width(delta.min(isize::MAX as usize) as isize); } /// Adjusts the maximum width of the configuration. @@ -464,7 +464,9 @@ macro_rules! create_config { /// As an example use case, this method is used when formatting /// arms within a declarative macro. fn adjust_max_width(&mut self, delta: isize) { - let adjust = |value: usize| (value as isize + delta) as usize; + // NB: we need to either saturate or report an error (or some kind of testable + // warning). I picked to saturate here. + let adjust = |value: usize| value.saturating_add_signed(delta); self.array_width.2 = adjust(self.array_width.2); self.attr_fn_like_width.2 = adjust(self.attr_fn_like_width.2); From a048dfd2675aa01b49851d10571b1dd26ed78884 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 29 Sep 2026 19:05:46 +0800 Subject: [PATCH 0992/1309] chore: use r-l/r zulip linkifier for r-l/r rustfmt backport nominations --- triagebot.toml | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/triagebot.toml b/triagebot.toml index bad75dc51d740..611f7724f5cae 100644 --- a/triagebot.toml +++ b/triagebot.toml @@ -952,53 +952,53 @@ message_on_add = "PR #{number} has been **accepted** for **stable** backport." [notify-zulip."beta-nominated".rustfmt] required_labels = ["T-rustfmt"] zulip_stream = 621384 # #t-rustfmt/backports -topic = "#{number}: beta-nominated" +topic = "rust#{number}: beta-nominated" message_on_add = [ """\ -@*T-rustfmt* @*T-rustfmt-contributors* PR #{number} "{title}" has been nominated +@*T-rustfmt* @*T-rustfmt-contributors* PR rust#{number} "{title}" has been nominated for beta backport. """, """\ -/poll Approve beta backport of #{number}? +/poll Approve beta backport of rust#{number}? approve decline don't know """, ] -message_on_remove = "PR #{number}'s beta-nomination has been removed." +message_on_remove = "PR rust#{number}'s beta-nomination has been removed." [notify-zulip."beta-accepted".rustfmt] required_labels = ["T-rustfmt"] zulip_stream = 621384 # #t-rustfmt/backports # Put it in the same thread as beta-nominated. -topic = "#{number}: beta-nominated" -message_on_add = "PR #{number} has been **accepted** for **beta** backport." +topic = "rust#{number}: beta-nominated" +message_on_add = "PR rust#{number} has been **accepted** for **beta** backport." [notify-zulip."stable-nominated".rustfmt] required_labels = ["T-rustfmt"] zulip_stream = 621384 # #t-rustfmt/backports -topic = "#{number}: stable-nominated" +topic = "rust#{number}: stable-nominated" message_on_add = [ """\ -@*T-rustfmt* @*T-rustfmt-contributors* PR #{number} "{title}" has been nominated +@*T-rustfmt* @*T-rustfmt-contributors* PR rust#{number} "{title}" has been nominated for stable backport. """, """\ -/poll Approve stable backport of #{number}? +/poll Approve stable backport of rust#{number}? approve approve (but does not justify new dot release on its own) decline don't know """, ] -message_on_remove = "PR #{number}'s stable-nomination has been removed." +message_on_remove = "PR rust#{number}'s stable-nomination has been removed." [notify-zulip."stable-accepted".rustfmt] required_labels = ["T-rustfmt"] zulip_stream = 621384 # #t-rustfmt/backports # Put it in the same thread as stable-nominated. -topic = "#{number}: stable-nominated" -message_on_add = "PR #{number} has been **accepted** for **stable** backport." +topic = "rust#{number}: stable-nominated" +message_on_add = "PR rust#{number} has been **accepted** for **stable** backport." [notify-zulip."A-edition-2021"] From cdb1e99b97662c7893b77d43f25fefd56399b374 Mon Sep 17 00:00:00 2001 From: Jieyou Xu Date: Tue, 29 Sep 2026 19:15:53 +0800 Subject: [PATCH 0993/1309] chore(triagebot): route rustfmt repo backport nominations to zulip To the [backport channel](https://rust-lang.zulipchat.com/#narrow/channel/621384-t-rustfmt.2Fbackports). --- src/tools/rustfmt/triagebot.toml | 51 ++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/tools/rustfmt/triagebot.toml b/src/tools/rustfmt/triagebot.toml index de28ad00a4272..d156d2b70ae58 100644 --- a/src/tools/rustfmt/triagebot.toml +++ b/src/tools/rustfmt/triagebot.toml @@ -102,6 +102,57 @@ add_labels = ["S-waiting-on-review"] # Documentation at: [shortcut] +# ------------------------------------------------------------------------------ +# Backport nominations (rustfmt repo side) +# ------------------------------------------------------------------------------ + +[notify-zulip."beta-nominated".rustfmt] +zulip_stream = 621384 # #t-rustfmt/backports +topic = "rustfmt#{number}: beta-nominated" +message_on_add = [ + """\ +@*T-rustfmt* @*T-rustfmt-contributors* PR rustfmt#{number} "{title}" has been nominated +for beta backport. +""", + """\ +/poll Approve beta backport of rustfmt#{number}? +approve +decline +don't know +""", +] +message_on_remove = "PR rustfmt#{number}'s beta-nomination has been removed." + +[notify-zulip."beta-accepted".rustfmt] +zulip_stream = 621384 # #t-rustfmt/backports +# Put it in the same thread as beta-nominated. +topic = "rustfmt#{number}: beta-nominated" +message_on_add = "PR rustfmt#{number} has been **accepted** for **beta** backport." + +[notify-zulip."stable-nominated".rustfmt] +zulip_stream = 621384 # #t-rustfmt/backports +topic = "rustfmt#{number}: stable-nominated" +message_on_add = [ + """\ +@*T-rustfmt* @*T-rustfmt-contributors* PR rustfmt#{number} "{title}" has been nominated +for stable backport. +""", + """\ +/poll Approve stable backport of rustfmt#{number}? +approve +approve (but does not justify new dot release on its own) +decline +don't know +""", +] +message_on_remove = "PR rustfmt#{number}'s stable-nomination has been removed." + +[notify-zulip."stable-accepted".rustfmt] +zulip_stream = 621384 # #t-rustfmt/backports +# Put it in the same thread as stable-nominated. +topic = "rustfmt#{number}: stable-nominated" +message_on_add = "PR rustfmt#{number} has been **accepted** for **stable** backport." + # ------------------------------------------------------------------------------ # PR assignments # ------------------------------------------------------------------------------ From 152237dfb52a3e4d31dcd7eb366d9cfe14a96f98 Mon Sep 17 00:00:00 2001 From: Raushan singh Date: Sat, 26 Sep 2026 07:32:36 +0000 Subject: [PATCH 0994/1309] test(resolve): add baseline test for struct shorthand typo suggestions --- tests/ui/resolve/struct-shorthand-typo.rs | 37 +++++++++ tests/ui/resolve/struct-shorthand-typo.stderr | 83 +++++++++++++++++++ 2 files changed, 120 insertions(+) create mode 100644 tests/ui/resolve/struct-shorthand-typo.rs create mode 100644 tests/ui/resolve/struct-shorthand-typo.stderr diff --git a/tests/ui/resolve/struct-shorthand-typo.rs b/tests/ui/resolve/struct-shorthand-typo.rs new file mode 100644 index 0000000000000..d8fc83de2bb76 --- /dev/null +++ b/tests/ui/resolve/struct-shorthand-typo.rs @@ -0,0 +1,37 @@ +//! Regression test for https://github.com/rust-lang/rust/issues/163324 + +const A: usize = 0; +struct S { a: usize } + +fn test_basic() { + S { a }; //~ ERROR cannot find value `a` in this scope +} + +const B: usize = 1; +struct Multi { a: usize, b: usize } +fn test_multi() { + Multi { a: 0, b }; //~ ERROR cannot find value `b` in this scope +} + +const C: usize = 2; +struct Fru { c: usize, d: usize } +fn test_fru() { + let base = Fru { c: 0, d: 0 }; + Fru { c, ..base }; //~ ERROR cannot find value `c` in this scope +} + +const D: usize = 3; +enum E { + StructVariant { d: usize }, +} +fn test_enum() { + E::StructVariant { d }; //~ ERROR cannot find value `d` in this scope +} + +struct Local { e: usize } +fn test_local() { + let E = 4; + Local { e }; //~ ERROR cannot find value `e` in this scope +} + +fn main() {} diff --git a/tests/ui/resolve/struct-shorthand-typo.stderr b/tests/ui/resolve/struct-shorthand-typo.stderr new file mode 100644 index 0000000000000..f390a24fa0db8 --- /dev/null +++ b/tests/ui/resolve/struct-shorthand-typo.stderr @@ -0,0 +1,83 @@ +error[E0425]: cannot find value `a` in this scope + --> $DIR/struct-shorthand-typo.rs:7:9 + | +LL | S { a }; + | ^ not found in this scope + | +note: similarly named constant `A` defined here + --> $DIR/struct-shorthand-typo.rs:3:1 + | +LL | const A: usize = 0; + | ^^^^^^^^^^^^^^^^^^^ +help: a constant with a similar name exists + | +LL - S { a }; +LL + S { A }; + | + +error[E0425]: cannot find value `b` in this scope + --> $DIR/struct-shorthand-typo.rs:13:19 + | +LL | Multi { a: 0, b }; + | ^ not found in this scope + | +note: similarly named constant `B` defined here + --> $DIR/struct-shorthand-typo.rs:10:1 + | +LL | const B: usize = 1; + | ^^^^^^^^^^^^^^^^^^^ +help: a constant with a similar name exists + | +LL - Multi { a: 0, b }; +LL + Multi { a: 0, B }; + | + +error[E0425]: cannot find value `c` in this scope + --> $DIR/struct-shorthand-typo.rs:20:11 + | +LL | Fru { c, ..base }; + | ^ not found in this scope + | +note: similarly named constant `C` defined here + --> $DIR/struct-shorthand-typo.rs:16:1 + | +LL | const C: usize = 2; + | ^^^^^^^^^^^^^^^^^^^ +help: a constant with a similar name exists (notice the capitalization) + | +LL - Fru { c, ..base }; +LL + Fru { C, ..base }; + | + +error[E0425]: cannot find value `d` in this scope + --> $DIR/struct-shorthand-typo.rs:28:24 + | +LL | E::StructVariant { d }; + | ^ not found in this scope + | +note: similarly named constant `D` defined here + --> $DIR/struct-shorthand-typo.rs:23:1 + | +LL | const D: usize = 3; + | ^^^^^^^^^^^^^^^^^^^ +help: a constant with a similar name exists + | +LL - E::StructVariant { d }; +LL + E::StructVariant { D }; + | + +error[E0425]: cannot find value `e` in this scope + --> $DIR/struct-shorthand-typo.rs:34:13 + | +LL | Local { e }; + | ^ not found in this scope + | +help: a local variable with a similar name exists + | +LL - Local { e }; +LL + Local { E }; + | + +error: aborting due to 5 previous errors + +For more information about this error, try `rustc --explain E0425`. From ac14be76e9aa47dce7cd2f805434ce74b0046f62 Mon Sep 17 00:00:00 2001 From: Raushan singh Date: Sat, 26 Sep 2026 09:36:58 +0000 Subject: [PATCH 0995/1309] fix(resolve): correct typo suggestion for struct field shorthands --- .../rustc_resolve/src/diagnostics/impls.rs | 8 +++- .../rustc_resolve/src/late/diagnostics.rs | 17 +++++-- tests/ui/resolve/struct-shorthand-typo.fixed | 44 ++++++++++++++++++ tests/ui/resolve/struct-shorthand-typo.rs | 9 +++- tests/ui/resolve/struct-shorthand-typo.stderr | 45 +++++++++---------- .../struct-fields-shorthand-unresolved.stderr | 5 +-- ...114423-ice-regression-in-suggestion.stderr | 5 +-- 7 files changed, 95 insertions(+), 38 deletions(-) create mode 100644 tests/ui/resolve/struct-shorthand-typo.fixed diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index ccb6139eae652..52016ca5f8d5c 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1987,7 +1987,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { is_expected, &|_| true, ); - self.add_typo_suggestion(err, suggestion, ident.span); + self.add_typo_suggestion(err, suggestion, ident.span, None); self.detect_derive_attribute(err, ident, parent_scope, sugg_span); let import_suggestions = @@ -2271,6 +2271,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { err: &mut Diag<'_>, suggestion: Option, span: Span, + prefix: Option, ) { let suggestion = match suggestion { None => return, @@ -2345,7 +2346,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { format!("maybe you meant this {}", suggestion.res.descr()) } }; - (span, msg, suggestion.candidate.to_ident_string()) + let candidate_str = suggestion.candidate.to_ident_string(); + let sugg = + if let Some(p) = prefix { format!("{p}: {candidate_str}") } else { candidate_str }; + (span, msg, sugg) }; err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect); } diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index e0a3b78fa5e2e..b2061cd9d9d91 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -1194,7 +1194,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { } } } - self.r.add_typo_suggestion(err, typo_sugg, ident_span); + self.r.add_typo_suggestion(err, typo_sugg, ident_span, None); return (true, suggested_candidates, candidates); } @@ -1244,7 +1244,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { &base_error.fallback_label, ) { // We do this to avoid losing a secondary span when we override the main error span. - self.r.add_typo_suggestion(err, typo_sugg, ident_span); + self.r.add_typo_suggestion(err, typo_sugg, ident_span, None); return (true, suggested_candidates, candidates); } } @@ -1429,13 +1429,22 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { return false; } + // Preserve the field name for struct field shorthands to avoid suggesting invalid shorthands. + let mut prefix = None; + if let PathSource::Expr(Some(ast::Expr { kind: ExprKind::Struct(expr), .. })) = source + && let Some(ident) = path.last().map(|seg| seg.ident) + && expr.fields.iter().any(|f| f.ident == ident && f.is_shorthand) + { + prefix = Some(ident); + } + let typo_sugg = self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected); let mut fallback = true; let typo_sugg = typo_sugg .to_opt_suggestion() .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str())); - self.r.add_typo_suggestion(err, typo_sugg, ident_span); + self.r.add_typo_suggestion(err, typo_sugg, ident_span, prefix); match self.diag_metadata.current_let_binding { Some((pat_sp, Some(ty_sp), None)) @@ -1453,7 +1462,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { // If the trait has a single item (which wasn't matched by the algorithm), suggest it let suggestion = self.get_single_associated_item(path, &source, is_expected); - self.r.add_typo_suggestion(err, suggestion, ident_span); + self.r.add_typo_suggestion(err, suggestion, ident_span, prefix); if self.let_binding_suggestion(err, ident_span) { fallback = false; diff --git a/tests/ui/resolve/struct-shorthand-typo.fixed b/tests/ui/resolve/struct-shorthand-typo.fixed new file mode 100644 index 0000000000000..b06bb357d6838 --- /dev/null +++ b/tests/ui/resolve/struct-shorthand-typo.fixed @@ -0,0 +1,44 @@ +//! Regression test for +//! +//! Tests that typo suggestions for unresolved struct shorthands emit valid `field: value` syntax. + +#![allow(unused)] +#![allow(non_snake_case)] + +//@ run-rustfix + +const A: usize = 0; +struct S { a: usize } + +fn test_basic() { + S { a: A }; //~ ERROR cannot find value `a` in this scope +} + +const B: usize = 1; +struct Multi { a: usize, b: usize } +fn test_multi() { + Multi { a: 0, b: B }; //~ ERROR cannot find value `b` in this scope +} + +const C: usize = 2; +struct Fru { c: usize, d: usize } +fn test_fru() { + let base = Fru { c: 0, d: 0 }; + Fru { c: C, ..base }; //~ ERROR cannot find value `c` in this scope +} + +const D: usize = 3; +enum E { + StructVariant { d: usize }, +} +fn test_enum() { + E::StructVariant { d: D }; //~ ERROR cannot find value `d` in this scope +} + +struct Local { e: usize } +fn test_local() { + let E = 4; + Local { e: E }; //~ ERROR cannot find value `e` in this scope +} + +fn main() {} diff --git a/tests/ui/resolve/struct-shorthand-typo.rs b/tests/ui/resolve/struct-shorthand-typo.rs index d8fc83de2bb76..e8c1765751d73 100644 --- a/tests/ui/resolve/struct-shorthand-typo.rs +++ b/tests/ui/resolve/struct-shorthand-typo.rs @@ -1,4 +1,11 @@ -//! Regression test for https://github.com/rust-lang/rust/issues/163324 +//! Regression test for +//! +//! Tests that typo suggestions for unresolved struct shorthands emit valid `field: value` syntax. + +#![allow(unused)] +#![allow(non_snake_case)] + +//@ run-rustfix const A: usize = 0; struct S { a: usize } diff --git a/tests/ui/resolve/struct-shorthand-typo.stderr b/tests/ui/resolve/struct-shorthand-typo.stderr index f390a24fa0db8..620dbbb1eb51c 100644 --- a/tests/ui/resolve/struct-shorthand-typo.stderr +++ b/tests/ui/resolve/struct-shorthand-typo.stderr @@ -1,82 +1,77 @@ error[E0425]: cannot find value `a` in this scope - --> $DIR/struct-shorthand-typo.rs:7:9 + --> $DIR/struct-shorthand-typo.rs:14:9 | LL | S { a }; | ^ not found in this scope | note: similarly named constant `A` defined here - --> $DIR/struct-shorthand-typo.rs:3:1 + --> $DIR/struct-shorthand-typo.rs:10:1 | LL | const A: usize = 0; | ^^^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists | -LL - S { a }; -LL + S { A }; - | +LL | S { a: A }; + | +++ error[E0425]: cannot find value `b` in this scope - --> $DIR/struct-shorthand-typo.rs:13:19 + --> $DIR/struct-shorthand-typo.rs:20:19 | LL | Multi { a: 0, b }; | ^ not found in this scope | note: similarly named constant `B` defined here - --> $DIR/struct-shorthand-typo.rs:10:1 + --> $DIR/struct-shorthand-typo.rs:17:1 | LL | const B: usize = 1; | ^^^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists | -LL - Multi { a: 0, b }; -LL + Multi { a: 0, B }; - | +LL | Multi { a: 0, b: B }; + | +++ error[E0425]: cannot find value `c` in this scope - --> $DIR/struct-shorthand-typo.rs:20:11 + --> $DIR/struct-shorthand-typo.rs:27:11 | LL | Fru { c, ..base }; | ^ not found in this scope | note: similarly named constant `C` defined here - --> $DIR/struct-shorthand-typo.rs:16:1 + --> $DIR/struct-shorthand-typo.rs:23:1 | LL | const C: usize = 2; | ^^^^^^^^^^^^^^^^^^^ -help: a constant with a similar name exists (notice the capitalization) - | -LL - Fru { c, ..base }; -LL + Fru { C, ..base }; +help: a constant with a similar name exists | +LL | Fru { c: C, ..base }; + | +++ error[E0425]: cannot find value `d` in this scope - --> $DIR/struct-shorthand-typo.rs:28:24 + --> $DIR/struct-shorthand-typo.rs:35:24 | LL | E::StructVariant { d }; | ^ not found in this scope | note: similarly named constant `D` defined here - --> $DIR/struct-shorthand-typo.rs:23:1 + --> $DIR/struct-shorthand-typo.rs:30:1 | LL | const D: usize = 3; | ^^^^^^^^^^^^^^^^^^^ help: a constant with a similar name exists | -LL - E::StructVariant { d }; -LL + E::StructVariant { D }; - | +LL | E::StructVariant { d: D }; + | +++ error[E0425]: cannot find value `e` in this scope - --> $DIR/struct-shorthand-typo.rs:34:13 + --> $DIR/struct-shorthand-typo.rs:41:13 | LL | Local { e }; | ^ not found in this scope | help: a local variable with a similar name exists | -LL - Local { e }; -LL + Local { E }; - | +LL | Local { e: E }; + | +++ error: aborting due to 5 previous errors diff --git a/tests/ui/structs/struct-fields-shorthand-unresolved.stderr b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr index 9b4590c76afb1..d3360885fd523 100644 --- a/tests/ui/structs/struct-fields-shorthand-unresolved.stderr +++ b/tests/ui/structs/struct-fields-shorthand-unresolved.stderr @@ -6,9 +6,8 @@ LL | y | help: a local variable with a similar name exists | -LL - y -LL + x - | +LL | y: x + | +++ error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-114423-ice-regression-in-suggestion.stderr b/tests/ui/typeck/issue-114423-ice-regression-in-suggestion.stderr index 9510001193d24..4bf3c6a174410 100644 --- a/tests/ui/typeck/issue-114423-ice-regression-in-suggestion.stderr +++ b/tests/ui/typeck/issue-114423-ice-regression-in-suggestion.stderr @@ -18,9 +18,8 @@ LL | let _ = RGB { r, g, b }; | help: a local variable with a similar name exists | -LL - let _ = RGB { r, g, b }; -LL + let _ = RGB { r, b, b }; - | +LL | let _ = RGB { r, g: b, b }; + | +++ error[E0308]: mismatched types --> $DIR/issue-114423-ice-regression-in-suggestion.rs:7:50 From bc0240cad290c98c0ee608b08754cf61c7069c9e Mon Sep 17 00:00:00 2001 From: Daniel Smith Date: Mon, 28 Sep 2026 13:21:26 -0400 Subject: [PATCH 0996/1309] Don't use the metadata based crate_hash for rustdoc runs --- compiler/rustc_middle/src/ty/context.rs | 2 +- tests/run-make/metrics-dir-crate-hash/lib.rs | 4 ++ tests/run-make/metrics-dir-crate-hash/main.rs | 6 +++ .../run-make/metrics-dir-crate-hash/rmake.rs | 51 +++++++++++++++++++ 4 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tests/run-make/metrics-dir-crate-hash/lib.rs create mode 100644 tests/run-make/metrics-dir-crate-hash/main.rs create mode 100644 tests/run-make/metrics-dir-crate-hash/rmake.rs diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 5cd7322ced683..8da0603715ff9 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1135,7 +1135,7 @@ impl<'tcx> TyCtxt<'tcx> { | CrateType::Cdylib | CrateType::Sdylib => false, CrateType::Rlib | CrateType::Dylib | CrateType::ProcMacro => true, - }) + }) && !self.sess.opts.actually_rustdoc } pub fn needs_hir_hash(self) -> bool { diff --git a/tests/run-make/metrics-dir-crate-hash/lib.rs b/tests/run-make/metrics-dir-crate-hash/lib.rs new file mode 100644 index 0000000000000..e0673f64605f5 --- /dev/null +++ b/tests/run-make/metrics-dir-crate-hash/lib.rs @@ -0,0 +1,4 @@ +#![feature(ascii_char)] // random lib feature +#![feature(test_unstable_lint)] // random lang feature + +pub fn documented() {} diff --git a/tests/run-make/metrics-dir-crate-hash/main.rs b/tests/run-make/metrics-dir-crate-hash/main.rs new file mode 100644 index 0000000000000..844b362c9f179 --- /dev/null +++ b/tests/run-make/metrics-dir-crate-hash/main.rs @@ -0,0 +1,6 @@ +#![feature(ascii_char)] // random lib feature +#![feature(test_unstable_lint)] // random lang feature + +fn main() { + println!("foobar"); +} diff --git a/tests/run-make/metrics-dir-crate-hash/rmake.rs b/tests/run-make/metrics-dir-crate-hash/rmake.rs new file mode 100644 index 0000000000000..90e0b16859c04 --- /dev/null +++ b/tests/run-make/metrics-dir-crate-hash/rmake.rs @@ -0,0 +1,51 @@ +// Verifies that when a crate hash is required solely for a metrics dir, that +// crate hash is successfully generated, either by the fallback mechanism or +// metadata generation. +// See https://github.com/rust-lang/rust/issues/163426. + +//@ ignore-cross-compile + +use std::path::{Path, PathBuf}; + +use run_make_support::rfs::create_dir_all; +use run_make_support::{ + cwd, filename_contains, has_extension, run_in_tmpdir, rustc, rustdoc, shallow_find_files, +}; + +fn find_feature_usage_metrics>(dir: P) -> Vec { + shallow_find_files(dir, |path| { + filename_contains(path, "unstable_feature_usage") && has_extension(path, "json") + }) +} + +fn main() { + let metrics_dir = "metrics-rustdoc"; + create_dir_all(&metrics_dir); + rustdoc() + .input("lib.rs") + .out_dir("doc") + .env("RUST_BACKTRACE", "short") + .arg(format!("-Zmetrics-dir={}", metrics_dir)) + .run() + .assert_stderr_not_contains("internal compiler error"); + assert_eq!( + find_feature_usage_metrics(&metrics_dir).len(), + 1, + "rustdoc should dump exactly one metrics file" + ); + + let metrics_dir = "metrics-rustc"; + create_dir_all(&metrics_dir); + rustc() + .input("main.rs") + .crate_type("bin") + .env("RUST_BACKTRACE", "short") + .arg(format!("-Zmetrics-dir={}", metrics_dir)) + .run() + .assert_stderr_not_contains("internal compiler error"); + assert_eq!( + find_feature_usage_metrics(&metrics_dir).len(), + 1, + "rustc should dump exactly one metrics file" + ); +} From 588c189ee0b9783acd3cc07892f0ff2dd6445c23 Mon Sep 17 00:00:00 2001 From: malezjaa Date: Tue, 29 Sep 2026 16:46:45 +0200 Subject: [PATCH 0997/1309] expose Rc::is_unique --- library/alloc/src/rcs/rc.rs | 51 ++++++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 3 deletions(-) diff --git a/library/alloc/src/rcs/rc.rs b/library/alloc/src/rcs/rc.rs index 8cca09d1d4a8c..04e08c47fb587 100644 --- a/library/alloc/src/rcs/rc.rs +++ b/library/alloc/src/rcs/rc.rs @@ -1985,10 +1985,55 @@ impl Rc { unsafe { drop(Rc::from_raw_in(ptr, alloc)) }; } - /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to - /// this allocation. + /// Determine whether this is the unique reference to the underlying data. + /// + /// Returns `true` if there are no other `Rc` or [`Weak`] pointers to the same allocation; + /// returns `false` otherwise. + /// + /// If this function returns `true`, it is safe to call [`get_mut_unchecked`] + /// immediately afterward. + /// + /// # Examples + /// + /// ``` + /// #![feature(arc_is_unique)] + /// + /// use std::rc::Rc; + /// + /// let x = Rc::new(3); + /// assert!(Rc::is_unique(&x)); + /// + /// let y = Rc::clone(&x); + /// assert!(!Rc::is_unique(&x)); + /// drop(y); + /// + /// // Weak references also count, because they could be upgraded at any time. + /// let z = Rc::downgrade(&x); + /// assert!(!Rc::is_unique(&x)); + /// ``` + /// + /// # Pointer invalidation + /// + /// This function will always return the same value as `Rc::get_mut(rc).is_some()`. However, + /// unlike that operation it does not produce any mutable references to the underlying data, + /// meaning no pointers to the data inside the `Rc` are invalidated by the call. Thus, the + /// following code is valid, even though it would be UB if it used `Rc::get_mut`: + /// + /// ``` + /// #![feature(arc_is_unique)] + /// + /// use std::rc::Rc; + /// + /// let rc = Rc::new(5); + /// let pointer: *const i32 = &*rc; + /// assert!(Rc::is_unique(&rc)); + /// assert_eq!(unsafe { *pointer }, 5); + /// ``` + /// + /// [`get_mut_unchecked`]: Self::get_mut_unchecked #[inline] - fn is_unique(this: &Self) -> bool { + #[unstable(feature = "arc_is_unique", issue = "138938")] + pub fn is_unique(this: &Self) -> bool { Rc::weak_count(this) == 0 && Rc::strong_count(this) == 1 } From 6cc4b6f5b0baff50056707422ff3286695665243 Mon Sep 17 00:00:00 2001 From: Yara Date: Tue, 15 Sep 2026 16:40:04 +0200 Subject: [PATCH 0998/1309] reflection: prefix reflection intrinsics with type_id --- .../src/const_eval/machine.rs | 10 ++++---- .../src/const_eval/type_info/adt.rs | 2 +- .../rustc_hir_analysis/src/check/intrinsic.rs | 24 ++++++++++++------- compiler/rustc_span/src/symbol.rs | 11 +++++---- library/core/src/intrinsics/mod.rs | 10 ++++---- library/core/src/mem/type_info.rs | 14 +++++------ 6 files changed, 39 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index 4251c74eb1ffb..db92b9b3aaceb 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -602,7 +602,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { } } - sym::type_of => { + sym::type_id_type_of => { let ty = ecx.read_type_id(&args[0])?; ecx.write_type_info(ty, dest)?; } @@ -621,7 +621,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ecx.write_scalar(Scalar::from_bool(is_mutable), dest)?; } - sym::size_of_type_id => { + sym::type_id_size_of => { let ty = ecx.read_type_id(&args[0])?; let layout = ecx.layout_of(ty)?; let variant_index = if layout.is_sized() { @@ -758,7 +758,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ecx.write_scalar(Scalar::from_target_usize(variants_num as u64, ecx), dest)?; } - sym::variant_name => { + sym::type_id_variant_name => { let base = ecx.read_type_id(&args[0])?; let field_name = if let ty::Adt(def, _) = base.kind() { @@ -784,7 +784,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { )?; } - sym::variant_non_exhaustive => { + sym::type_id_variant_non_exhaustive => { let base = ecx.read_type_id(&args[0])?; let non_exhaustive = if let ty::Adt(def, _) = base.kind() { @@ -884,7 +884,7 @@ impl<'tcx> interpret::Machine<'tcx> for CompileTimeMachine<'tcx> { ecx.write_type_id_generics(dest, ty)?; } - sym::non_exhaustive => { + sym::type_id_non_exhaustive => { let ty = ecx.read_type_id(&args[0])?; // FIXME(reflection): need a way to obtain non-exhaustiveness of a variant's fields. diff --git a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs index 09662d2bc0a98..bd26e1369996b 100644 --- a/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs +++ b/compiler/rustc_const_eval/src/const_eval/type_info/adt.rs @@ -127,7 +127,7 @@ impl<'tcx> InterpCx<'tcx, CompileTimeMachine<'tcx>> { match field.name { sym::generics => self.write_generics(&field_place, generics)?, - sym::variants => { + sym::type_id_variants => { self.allocate_fill_and_write_slice_ptr( &field_place, enum_def.variants().len() as u64, diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index cca93e8aef0ec..88a93229296c2 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -150,7 +150,6 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::minimumf128 | sym::mul_with_overflow | sym::needs_drop - | sym::non_exhaustive | sym::offload | sym::offload_get_num_devices | sym::offset_of @@ -199,6 +198,7 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::truncf64 | sym::truncf128 | sym::type_id + | sym::type_id_non_exhaustive | sym::type_id_array_len | sym::type_id_element_ty | sym::type_id_eq @@ -212,12 +212,14 @@ fn intrinsic_operation_unsafety(tcx: TyCtxt<'_>, intrinsic_id: LocalDefId) -> hi | sym::type_id_variants | sym::type_id_vtable | sym::type_name - | sym::type_of + | sym::type_id_type_of + | sym::type_id_size_of + | sym::type_id_variants + | sym::type_id_variant_name + | sym::type_id_variant_non_exhaustive | sym::ub_checks | sym::va_copy | sym::variant_count - | sym::variant_name - | sym::variant_non_exhaustive | sym::wrapping_add | sym::wrapping_mul | sym::wrapping_sub @@ -296,7 +298,7 @@ pub(crate) fn check_intrinsic_type( sym::size_of_val | sym::align_of_val => { (1, 0, vec![Ty::new_imm_ptr(tcx, param(0))], tcx.types.usize) } - sym::size_of_type_id => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)), + sym::type_id_size_of => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, tcx.types.usize)), sym::offset_of => (1, 0, vec![tcx.types.u32, tcx.types.u32], tcx.types.usize), sym::field_offset => (1, 0, vec![], tcx.types.usize), sym::rustc_peek => (1, 0, vec![param(0)], param(0)), @@ -339,8 +341,12 @@ pub(crate) fn check_intrinsic_type( sym::type_id_points_mutably => (0, 0, vec![type_id_ty()], tcx.types.bool), sym::type_id_points_to => (0, 0, vec![type_id_ty()], Ty::new_option(tcx, type_id_ty())), sym::type_id_variants => (0, 0, vec![type_id_ty()], tcx.types.usize), - sym::variant_name => (0, 0, vec![type_id_ty(), tcx.types.usize], Ty::new_static_str(tcx)), - sym::variant_non_exhaustive => (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.bool), + sym::type_id_variant_name => { + (0, 0, vec![type_id_ty(), tcx.types.usize], Ty::new_static_str(tcx)) + } + sym::type_id_variant_non_exhaustive => { + (0, 0, vec![type_id_ty(), tcx.types.usize], tcx.types.bool) + } sym::type_id_vtable => { let dyn_metadata = tcx.require_lang_item(LangItem::DynMetadata, span); let dyn_metadata_adt_ref = tcx.adt_def(dyn_metadata); @@ -355,7 +361,7 @@ pub(crate) fn check_intrinsic_type( (0, 0, vec![type_id_ty(); 2], ret_ty) } - sym::type_of => ( + sym::type_id_type_of => ( 0, 0, vec![type_id_ty()], @@ -364,7 +370,7 @@ pub(crate) fn check_intrinsic_type( sym::field_representing_type_actual_type_id => (0, 0, vec![type_id_ty()], type_id_ty()), sym::field_representing_type_name => (0, 0, vec![type_id_ty()], Ty::new_static_str(tcx)), sym::field_representing_type_offset => (0, 0, vec![type_id_ty()], tcx.types.usize), - sym::non_exhaustive => (0, 0, vec![type_id_ty()], tcx.types.bool), + sym::type_id_non_exhaustive => (0, 0, vec![type_id_ty()], tcx.types.bool), sym::type_id_generics => ( 0, 0, diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 4c1b9c78b7963..3adfb62d1ce54 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -2203,8 +2203,14 @@ symbols! { type_id_function_ptr, type_id_generics, type_id_is_signed, + type_id_non_exhaustive, type_id_points_mutably, type_id_points_to, + type_id_size_of, + type_name, + type_id_type_of, + type_id_variant_name, + type_id_variant_non_exhaustive, type_id_variants, type_id_vtable, type_info, @@ -2215,8 +2221,6 @@ symbols! { type_ir_interner, type_length_limit, type_macros, - type_name, - type_of, type_privacy_lints, typed_swap_nonoverlapping, u8, @@ -2344,9 +2348,6 @@ symbols! { var, variadic, variant_count, - variant_name, - variant_non_exhaustive, - variants, vec, vector, verbatim, diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs index ab2bbb8ab4449..12cb3d2b6d8b4 100644 --- a/library/core/src/intrinsics/mod.rs +++ b/library/core/src/intrinsics/mod.rs @@ -2979,7 +2979,7 @@ pub fn type_id_vtable( #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] -pub fn type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; +pub fn type_id_type_of(_id: crate::any::TypeId) -> crate::mem::type_info::Type; /// Gets a static string slice containing the name of a type. /// @@ -3056,7 +3056,7 @@ pub fn type_id_element_ty(_id: crate::any::TypeId) -> Option #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] -pub fn size_of_type_id(_id: crate::any::TypeId) -> Option; +pub fn type_id_size_of(_id: crate::any::TypeId) -> Option; /// Gets the number of variants of the type represented by this `TypeId`. /// @@ -3074,7 +3074,7 @@ pub fn type_id_variants(_id: crate::any::TypeId) -> usize; #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] -pub fn variant_name(_base: crate::any::TypeId, _variant_index: usize) -> &'static str; +pub fn type_id_variant_name(_base: crate::any::TypeId, _variant_index: usize) -> &'static str; /// Returns true when the variant represented by the base `TypeId` and variant_idx is non /// exhaustive. @@ -3086,7 +3086,7 @@ pub fn variant_name(_base: crate::any::TypeId, _variant_index: usize) -> &'stati #[rustc_intrinsic] #[unstable(feature = "core_intrinsics", issue = "none")] #[rustc_comptime] -pub fn variant_non_exhaustive(base: crate::any::TypeId, variant: usize) -> bool; +pub fn type_id_variant_non_exhaustive(base: crate::any::TypeId, variant: usize) -> bool; /// Gets the number of fields at the given `variant_index` represented by this `TypeId`. /// @@ -3155,7 +3155,7 @@ pub fn type_id_function_ptr(_type_id: crate::any::TypeId) -> Option bool; +pub fn type_id_non_exhaustive(_id: crate::any::TypeId) -> bool; /// Returns the list of generic args on this type. /// Only meaningful for Adts, closures, ... Everything else returns an empty slice. diff --git a/library/core/src/mem/type_info.rs b/library/core/src/mem/type_info.rs index a11d1f1d0dc18..1e96cf915e67d 100644 --- a/library/core/src/mem/type_info.rs +++ b/library/core/src/mem/type_info.rs @@ -3,7 +3,7 @@ use crate::any::TypeId; use crate::fmt; -use crate::intrinsics::{self, type_id, type_of}; +use crate::intrinsics; use crate::marker::PointeeSized; use crate::ptr::DynMetadata; @@ -38,7 +38,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn info(self) -> Type { - type_of(self) + intrinsics::type_id_type_of(self) } } @@ -54,7 +54,7 @@ impl Type { #[unstable(feature = "type_info", issue = "146922")] #[rustc_const_unstable(feature = "type_info", issue = "146922")] pub const fn of() -> Self { - const { type_id::().info() } + const { intrinsics::type_id::().info() } } } @@ -328,7 +328,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn size(self) -> Option { - intrinsics::size_of_type_id(self) + intrinsics::type_id_size_of(self) } /// Returns the number of variants of the type represented by this `TypeId`. @@ -566,7 +566,7 @@ impl TypeId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn non_exhaustive(self) -> bool { - intrinsics::non_exhaustive(self) + intrinsics::type_id_non_exhaustive(self) } /// Returns a list of generic parameters of the type. @@ -696,7 +696,7 @@ impl VariantId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn name(self) -> &'static str { - intrinsics::variant_name(self.base, self.variant) + intrinsics::type_id_variant_name(self.base, self.variant) } /// Returns whether this variant is marked with `#[non_exhaustive]`. @@ -704,7 +704,7 @@ impl VariantId { #[rustc_const_unstable(feature = "type_info", issue = "146922")] #[rustc_comptime] pub fn non_exhaustive(self) -> bool { - intrinsics::variant_non_exhaustive(self.base, self.variant) + intrinsics::type_id_variant_non_exhaustive(self.base, self.variant) } } From e054cb5bb68db7af6b38ce5457495cacf58885d1 Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 29 Sep 2026 11:12:52 -0400 Subject: [PATCH 0999/1309] Update gccjit.rs version --- Cargo.lock | 4 ++-- Cargo.toml | 2 +- src/lib.rs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index c174628d0d188..6467f1a8c3763 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -56,9 +56,9 @@ dependencies = [ [[package]] name = "gccjit" -version = "6.1.0" +version = "7.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d85b5754389edaad832ba320709a25086b3081a8c6c0fab2322965e5fb512b3" +checksum = "dfdb84ba432f6679794790de652bfbed86201893a30c03dc669c2bfe7424f472" dependencies = [ "gccjit_sys", ] diff --git a/Cargo.toml b/Cargo.toml index 02be6d56c2310..35046980f0695 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -20,7 +20,7 @@ default = ["master"] [dependencies] object = { version = "0.39.0", default-features = false, features = ["std", "read"] } tempfile = "3.20" -gccjit = { version = "6.1.0", features = ["dlopen"] } +gccjit = { version = "7.0.0", features = ["dlopen"] } #gccjit = { git = "https://github.com/rust-lang/gccjit.rs", branch = "error-dlopen", features = ["dlopen"] } # Local copy. diff --git a/src/lib.rs b/src/lib.rs index 7abbda4a37dc1..4ce332fed5501 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -236,7 +236,7 @@ impl CodegenBackend for GccCodegenBackend { lto_supported: gccjit::is_lto_supported(), }); - gccjit::set_global_personality_function_name(b"rust_eh_personality\0"); + gccjit::set_global_personality_function_name(c"rust_eh_personality"); } #[cfg(not(feature = "master"))] From 0883f590731023f43c3108aedece437285a5e44e Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Tue, 29 Sep 2026 16:52:18 +0200 Subject: [PATCH 1000/1309] x86_64: cleanup `reg_component` --- compiler/rustc_target/src/callconv/x86_64.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs index 5ab2834807d67..57e997f45d4c5 100644 --- a/compiler/rustc_target/src/callconv/x86_64.rs +++ b/compiler/rustc_target/src/callconv/x86_64.rs @@ -131,17 +131,16 @@ where } fn reg_component(cls: &[Option], i: &mut usize, size: Size) -> Option { - if *i >= cls.len() { + let Some(Some(class)) = cls.get(*i) else { return None; - } + }; - match cls[*i] { - None => None, - Some(Class::Int) => { + match class { + Class::Int => { *i += 1; Some(if size.bytes() < 8 { Reg { kind: RegKind::Integer, size } } else { Reg::i64() }) } - Some(Class::Sse) => { + Class::Sse => { let vec_len = 1 + cls[*i + 1..].iter().take_while(|&&c| c == Some(Class::SseUp)).count(); *i += vec_len; @@ -154,7 +153,7 @@ fn reg_component(cls: &[Option], i: &mut usize, size: Size) -> Option unreachable!("reg_component: unhandled class {:?}", c), + c => unreachable!("reg_component: unhandled class {:?}", c), } } From 7f5fdabc90944de7d2d38fee3d43f6ad9bbd17db Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 26 Sep 2026 13:54:41 +0200 Subject: [PATCH 1001/1309] x86 callconv: refactor into separate classify methods --- compiler/rustc_target/src/callconv/x86.rs | 207 ++++++++++++---------- 1 file changed, 112 insertions(+), 95 deletions(-) diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 3476f41e3bc75..6f88706dbf4b7 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -2,7 +2,7 @@ use rustc_abi::{ AddressSpace, Align, BackendRepr, Float, HasDataLayout, Primitive, Reg, RegKind, TyAndLayout, }; -use crate::callconv::{ArgAttribute, FnAbi, PassMode, TyAbiInterface}; +use crate::callconv::{ArgAbi, ArgAttribute, FnAbi, PassMode, TyAbiInterface}; use crate::spec::{HasTargetSpec, RustcAbi}; /// Is this a struct with a single float field? @@ -37,65 +37,136 @@ where } } -#[derive(PartialEq)] +#[derive(Clone, Copy, PartialEq)] pub(crate) enum Flavor { General, FastcallOrVectorcall, } +#[derive(Clone, Copy)] pub(crate) struct X86Options { pub flavor: Flavor, pub regparm: Option, pub reg_struct_return: bool, } -pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options) +fn classify_ret<'a, Ty, C>(cx: &C, opts: X86Options, ret: &mut ArgAbi<'a, Ty>) where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout + HasTargetSpec, { - if !fn_abi.ret.is_ignore() { - if fn_abi.ret.layout.is_aggregate() && fn_abi.ret.layout.is_sized() { - // Returning a structure. Most often, this will use - // a hidden first argument. On some platforms, though, - // small structs are returned as integers. - // - // Some links: - // https://www.angelcode.com/dev/callconv/callconv.html - // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp - let t = cx.target_spec(); - if let Some(Float::F16) = fn_abi.ret.layout.complex_float(cx) { - // `_Complex _Float16` is returned as `<2 x half>`. - let kind = RegKind::Vector { hint_vector_elem: Primitive::Float(Float::F16) }; - fn_abi.ret.cast_to(Reg { kind, size: fn_abi.ret.layout.size }); - } else if t.abi_return_struct_as_int - || opts.reg_struct_return - || fn_abi.ret.layout.is_complex_number(cx) - { - // According to Clang, everyone but MSVC returns single-element - // float aggregates directly in a floating-point register. - if is_single_fp_element(fn_abi.ret.layout, cx) { - match fn_abi.ret.layout.size.bytes() { - 2 => fn_abi.ret.cast_to(Reg::f16()), - 4 => fn_abi.ret.cast_to(Reg::f32()), - 8 => fn_abi.ret.cast_to(Reg::f64()), - _ => fn_abi.ret.make_indirect(), - } - } else { - match fn_abi.ret.layout.size.bytes() { - 1 => fn_abi.ret.cast_to(Reg::i8()), - 2 => fn_abi.ret.cast_to(Reg::i16()), - 4 => fn_abi.ret.cast_to(Reg::i32()), - 8 => fn_abi.ret.cast_to(Reg::i64()), - _ => fn_abi.ret.make_indirect(), - } + if ret.layout.is_aggregate() && ret.layout.is_sized() { + // Returning a structure. Most often, this will use + // a hidden first argument. On some platforms, though, + // small structs are returned as integers. + // + // Some links: + // https://www.angelcode.com/dev/callconv/callconv.html + // Clang's ABI handling is in lib/CodeGen/TargetInfo.cpp + let t = cx.target_spec(); + if let Some(Float::F16) = ret.layout.complex_float(cx) { + // `_Complex _Float16` is returned as `<2 x half>`. + let kind = RegKind::Vector { hint_vector_elem: Primitive::Float(Float::F16) }; + ret.cast_to(Reg { kind, size: ret.layout.size }); + } else if t.abi_return_struct_as_int + || opts.reg_struct_return + || ret.layout.is_complex_number(cx) + { + // According to Clang, everyone but MSVC returns single-element + // float aggregates directly in a floating-point register. + if is_single_fp_element(ret.layout, cx) { + match ret.layout.size.bytes() { + 2 => ret.cast_to(Reg::f16()), + 4 => ret.cast_to(Reg::f32()), + 8 => ret.cast_to(Reg::f64()), + _ => ret.make_indirect(), } } else { - fn_abi.ret.make_indirect(); + match ret.layout.size.bytes() { + 1 => ret.cast_to(Reg::i8()), + 2 => ret.cast_to(Reg::i16()), + 4 => ret.cast_to(Reg::i32()), + 8 => ret.cast_to(Reg::i64()), + _ => ret.make_indirect(), + } } } else { - fn_abi.ret.extend_integer_width_to(32); + ret.make_indirect(); + } + } else { + ret.extend_integer_width_to(32); + } +} + +fn classify_arg<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout + HasTargetSpec, +{ + let t = cx.target_spec(); + let align_4 = Align::from_bytes(4).unwrap(); + let align_16 = Align::from_bytes(16).unwrap(); + + if arg.layout.is_aggregate() { + // We need to compute the alignment of the `byval` argument. The rules can be found in + // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized + // here, they are: + // + // 1. If the natural alignment of the type is <= 4, the alignment is 4. + // + // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment. + // This doesn't matter here because we only pass aggregates via `byval`, not vectors. + // + // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector + // type is 16. + // + // 4. If none of these conditions are true, the alignment is 4. + + fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool + where + Ty: TyAbiInterface<'a, C> + Copy, + { + match layout.backend_repr { + BackendRepr::Scalar(_) | BackendRepr::ScalarPair { .. } => false, + BackendRepr::SimdVector { .. } => true, + BackendRepr::Memory { .. } => { + for i in 0..layout.fields.count() { + if contains_vector(cx, layout.field(cx, i)) { + return true; + } + } + false + } + BackendRepr::SimdScalableVector { .. } => { + panic!("scalable vectors are unsupported") + } + } } + + let byval_align = if arg.layout.align.abi < align_4 { + // (1.) + align_4 + } else if t.is_like_darwin && contains_vector(cx, arg.layout) { + // (3.) + align_16 + } else { + // (4.) + align_4 + }; + + arg.pass_by_stack_offset(Some(byval_align)); + } else { + arg.extend_integer_width_to(32); + } +} + +pub(crate) fn compute_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, opts: X86Options) +where + Ty: TyAbiInterface<'a, C> + Copy, + C: HasDataLayout + HasTargetSpec, +{ + if !fn_abi.ret.is_ignore() { + classify_ret(cx, opts, &mut fn_abi.ret); } for arg in fn_abi.args.iter_mut() { @@ -108,61 +179,7 @@ where continue; } - let t = cx.target_spec(); - let align_4 = Align::from_bytes(4).unwrap(); - let align_16 = Align::from_bytes(16).unwrap(); - - if arg.layout.is_aggregate() { - // We need to compute the alignment of the `byval` argument. The rules can be found in - // `X86_32ABIInfo::getTypeStackAlignInBytes` in Clang's `TargetInfo.cpp`. Summarized - // here, they are: - // - // 1. If the natural alignment of the type is <= 4, the alignment is 4. - // - // 2. Otherwise, on Linux, the alignment of any vector type is the natural alignment. - // This doesn't matter here because we only pass aggregates via `byval`, not vectors. - // - // 3. Otherwise, on Apple platforms, the alignment of anything that contains a vector - // type is 16. - // - // 4. If none of these conditions are true, the alignment is 4. - - fn contains_vector<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool - where - Ty: TyAbiInterface<'a, C> + Copy, - { - match layout.backend_repr { - BackendRepr::Scalar(_) | BackendRepr::ScalarPair { .. } => false, - BackendRepr::SimdVector { .. } => true, - BackendRepr::Memory { .. } => { - for i in 0..layout.fields.count() { - if contains_vector(cx, layout.field(cx, i)) { - return true; - } - } - false - } - BackendRepr::SimdScalableVector { .. } => { - panic!("scalable vectors are unsupported") - } - } - } - - let byval_align = if arg.layout.align.abi < align_4 { - // (1.) - align_4 - } else if t.is_like_darwin && contains_vector(cx, arg.layout) { - // (3.) - align_16 - } else { - // (4.) - align_4 - }; - - arg.pass_by_stack_offset(Some(byval_align)); - } else { - arg.extend_integer_width_to(32); - } + classify_arg(cx, arg); } fill_inregs(cx, fn_abi, opts, false); From 457af24e1eec19ab240ecfe2047fb2b86bb03b71 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 26 Sep 2026 14:04:40 +0200 Subject: [PATCH 1002/1309] x86 callconv: put regparam into `Flavor::General` --- compiler/rustc_target/src/callconv/mod.rs | 10 +++++----- compiler/rustc_target/src/callconv/x86.rs | 21 ++++++++++++++------- 2 files changed, 19 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs index edc23b6c50b45..487de8f54ee62 100644 --- a/compiler/rustc_target/src/callconv/mod.rs +++ b/compiler/rustc_target/src/callconv/mod.rs @@ -733,17 +733,17 @@ impl<'a, Ty> FnAbi<'a, Ty> { let spec = cx.target_spec(); match &spec.arch { Arch::X86 => { - let (flavor, regparm) = match abi { + let flavor = match abi { ExternAbi::Fastcall { .. } | ExternAbi::Vectorcall { .. } => { - (x86::Flavor::FastcallOrVectorcall, None) + x86::Flavor::FastcallOrVectorcall } ExternAbi::C { .. } | ExternAbi::Cdecl { .. } | ExternAbi::Stdcall { .. } => { - (x86::Flavor::General, cx.x86_abi_opt().regparm) + x86::Flavor::General { regparam: cx.x86_abi_opt().regparm } } - _ => (x86::Flavor::General, None), + _ => x86::Flavor::General { regparam: None }, }; let reg_struct_return = cx.x86_abi_opt().reg_struct_return; - let opts = x86::X86Options { flavor, regparm, reg_struct_return }; + let opts = x86::X86Options { flavor, reg_struct_return }; if spec.is_like_msvc { x86_win32::compute_abi_info(cx, self, opts); } else { diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs index 6f88706dbf4b7..efe88bff6504c 100644 --- a/compiler/rustc_target/src/callconv/x86.rs +++ b/compiler/rustc_target/src/callconv/x86.rs @@ -39,14 +39,13 @@ where #[derive(Clone, Copy, PartialEq)] pub(crate) enum Flavor { - General, + General { regparam: Option }, FastcallOrVectorcall, } #[derive(Clone, Copy)] pub(crate) struct X86Options { pub flavor: Flavor, - pub regparm: Option, pub reg_struct_return: bool, } @@ -193,9 +192,6 @@ pub(crate) fn fill_inregs<'a, Ty, C>( ) where Ty: TyAbiInterface<'a, C> + Copy, { - if opts.flavor != Flavor::FastcallOrVectorcall && opts.regparm.is_none_or(|x| x == 0) { - return; - } // Mark arguments as InReg like clang does it, // so our fastcall/vectorcall is compatible with C/C++ fastcall/vectorcall. @@ -205,8 +201,19 @@ pub(crate) fn fill_inregs<'a, Ty, C>( // IsSoftFloatABI is only set to true on ARM platforms, // which in turn can't be x86? - // 2 for fastcall/vectorcall, regparm limited by 3 otherwise - let mut free_regs = opts.regparm.unwrap_or(2).into(); + // The number of registers available for argument passing. + // + // An `extern "fastcall"` and `extern "vectorcall"` function always have 2 registers available. + // Otherwise the `regparam` count (in the range 0..=3) determines the number of available + // registers. If unspecified, no registers are used for argument passing. + let mut free_regs = match opts.flavor { + Flavor::FastcallOrVectorcall => 2, + Flavor::General { regparam } => u64::from(regparam.unwrap_or(0)), + }; + + if free_regs == 0 { + return; + } // For types generating PassMode::Cast, InRegs will not be set. // Maybe, this is a FIXME From 768500b03ce921cb18853761304d41a1ec24822f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 20:42:04 +0000 Subject: [PATCH 1003/1309] Add support for span context to `derive(Diagnostic)` Allow writing ```rust struct Diagnostic { #[primary_span] #[label("label text")] span: Span, #[context] context: Span, } ``` So that the code pointed at by `context` is shown in the rendered diagnostic without an underline. --- .../src/diagnostics/diagnostic_builder.rs | 7 +- compiler/rustc_macros/src/lib.rs | 1 + .../diagnostic-derive-inline.rs | 3 + .../diagnostic-derive-inline.stderr | 128 +++++++++--------- .../diagnostic-derive-pass.rs | 38 ++++++ 5 files changed, 115 insertions(+), 62 deletions(-) create mode 100644 tests/ui-fulldeps/session-diagnostic/diagnostic-derive-pass.rs diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs index cdff1280d69f9..f071028e5937d 100644 --- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs +++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs @@ -347,11 +347,16 @@ impl DiagnosticDeriveVariantBuilder { match (&attr.meta, name.as_str()) { (Meta::Path(_), "primary_span") => { report_error_if_not_applied_to_span(attr, &info)?; - return Ok(quote! { diag.span(#binding); }); } + (Meta::Path(_), "context") => { + report_error_if_not_applied_to_span(attr, &info)?; + return Ok(quote! { + diag.span_context(#binding); + }); + } (Meta::Path(_), "subdiagnostic") => { return Ok(quote! { diag.subdiagnostic(#binding); }); } diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs index f632862dc4627..1cdb4e125aab1 100644 --- a/compiler/rustc_macros/src/lib.rs +++ b/compiler/rustc_macros/src/lib.rs @@ -190,6 +190,7 @@ decl_derive!( // field attributes primary_span, label, + context, subdiagnostic, suggestion)] => #[doc = "See "] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs index 0956556bf5ef2..2351cda7b2195 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.rs @@ -130,6 +130,9 @@ struct MessageWrongType { #[primary_span] //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan` foo: String, + #[context] + //~^ ERROR `#[context]` attribute can only be applied to fields of type `Span` or `MultiSpan` + bar: String, } #[derive(Diagnostic)] diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr index f077dc1221ced..0486ac91de8f5 100644 --- a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-inline.stderr @@ -138,26 +138,32 @@ error: derive(Diagnostic): the `#[primary_span]` attribute can only be applied t LL | #[primary_span] | ^ +error: derive(Diagnostic): the `#[context]` attribute can only be applied to fields of type `Span` or `MultiSpan` + --> $DIR/diagnostic-derive-inline.rs:133:5 + | +LL | #[context] + | ^ + error: derive(Diagnostic): `#[nonsense]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:138:5 + --> $DIR/diagnostic-derive-inline.rs:141:5 | LL | #[nonsense] | ^ error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive-inline.rs:155:5 + --> $DIR/diagnostic-derive-inline.rs:158:5 | LL | #[label("with a label")] | ^ error: derive(Diagnostic): `name` doesn't refer to a field on this type - --> $DIR/diagnostic-derive-inline.rs:163:46 + --> $DIR/diagnostic-derive-inline.rs:166:46 | LL | #[suggestion("with a suggestion", code = "{name}")] | ^^^^^^^^ error: invalid format string: expected `}` but string was terminated - --> $DIR/diagnostic-derive-inline.rs:168:10 + --> $DIR/diagnostic-derive-inline.rs:171:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ expected `}` in format string @@ -166,7 +172,7 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: invalid format string: unmatched `}` found - --> $DIR/diagnostic-derive-inline.rs:178:10 + --> $DIR/diagnostic-derive-inline.rs:181:10 | LL | #[derive(Diagnostic)] | ^^^^^^^^^^ unmatched `}` in format string @@ -175,19 +181,19 @@ LL | #[derive(Diagnostic)] = note: this error originates in the derive macro `Diagnostic` (in Nightly builds, run with -Z macro-backtrace for more info) error: derive(Diagnostic): the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan` - --> $DIR/diagnostic-derive-inline.rs:198:5 + --> $DIR/diagnostic-derive-inline.rs:201:5 | LL | #[label("with a label")] | ^ error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:217:5 + --> $DIR/diagnostic-derive-inline.rs:220:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive-inline.rs:225:39 + --> $DIR/diagnostic-derive-inline.rs:228:39 | LL | #[suggestion("with a suggestion", nonsense = "bar")] | ^^^^^^^^ @@ -195,13 +201,13 @@ LL | #[suggestion("with a suggestion", nonsense = "bar")] = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:225:5 + --> $DIR/diagnostic-derive-inline.rs:228:5 | LL | #[suggestion("with a suggestion", nonsense = "bar")] | ^ error: derive(Diagnostic): invalid nested attribute - --> $DIR/diagnostic-derive-inline.rs:234:39 + --> $DIR/diagnostic-derive-inline.rs:237:39 | LL | #[suggestion("with a suggestion", msg = "bar")] | ^^^ @@ -209,13 +215,13 @@ LL | #[suggestion("with a suggestion", msg = "bar")] = help: only `style`, `code` and `applicability` are valid nested attributes error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:234:5 + --> $DIR/diagnostic-derive-inline.rs:237:5 | LL | #[suggestion("with a suggestion", msg = "bar")] | ^ error: derive(Diagnostic): wrong field type for suggestion - --> $DIR/diagnostic-derive-inline.rs:257:5 + --> $DIR/diagnostic-derive-inline.rs:260:5 | LL | #[suggestion("with a suggestion", code = "This is suggested code")] | ^ @@ -223,91 +229,91 @@ LL | #[suggestion("with a suggestion", code = "This is suggested code")] = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:273:24 + --> $DIR/diagnostic-derive-inline.rs:276:24 | LL | suggestion: (Span, Span, Applicability), | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:273:18 + --> $DIR/diagnostic-derive-inline.rs:276:18 | LL | suggestion: (Span, Span, Applicability), | ^^^^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:281:33 + --> $DIR/diagnostic-derive-inline.rs:284:33 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:281:18 + --> $DIR/diagnostic-derive-inline.rs:284:18 | LL | suggestion: (Applicability, Applicability, Span), | ^^^^^^^^^^^^^ error: derive(Diagnostic): `#[label = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:288:5 + --> $DIR/diagnostic-derive-inline.rs:291:5 | LL | #[label = "bar"] | ^ error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:387:5 + --> $DIR/diagnostic-derive-inline.rs:390:5 | LL | #[suggestion("with a suggestion", code = "...", applicability = "maybe-incorrect")] | ^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:389:24 + --> $DIR/diagnostic-derive-inline.rs:392:24 | LL | suggestion: (Span, Applicability), | ^^^^^^^^^^^^^ error: derive(Diagnostic): invalid applicability - --> $DIR/diagnostic-derive-inline.rs:395:69 + --> $DIR/diagnostic-derive-inline.rs:398:69 | LL | #[suggestion("with a suggestion", code = "...", applicability = "batman")] | ^^^^^^^^ error: derive(Diagnostic): the `#[help(...)]` attribute can only be applied to fields of type `Span`, `MultiSpan`, `bool` or `()` - --> $DIR/diagnostic-derive-inline.rs:458:5 + --> $DIR/diagnostic-derive-inline.rs:461:5 | LL | #[help("with a help")] | ^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:467:29 + --> $DIR/diagnostic-derive-inline.rs:470:29 | LL | #[label("with a label", foo)] | ^^^ error: derive(Diagnostic): a diagnostic message must be the first argument to the attribute - --> $DIR/diagnostic-derive-inline.rs:475:29 + --> $DIR/diagnostic-derive-inline.rs:478:29 | LL | #[label("with a label", "and another one?")] | ^^^^^^^^^^^^^^^^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:483:29 + --> $DIR/diagnostic-derive-inline.rs:486:29 | LL | #[label("with a label", foo = "...")] | ^^^ error: derive(Diagnostic): no nested attribute expected here - --> $DIR/diagnostic-derive-inline.rs:491:29 + --> $DIR/diagnostic-derive-inline.rs:494:29 | LL | #[label("with a label", foo("..."))] | ^^^ error: derive(Diagnostic): `#[error(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:511:1 + --> $DIR/diagnostic-derive-inline.rs:514:1 | LL | #[error("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:511:1 + --> $DIR/diagnostic-derive-inline.rs:514:1 | LL | #[error("this is an example message", code = E0123)] | ^ @@ -315,13 +321,13 @@ LL | #[error("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[warn_(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:518:1 + --> $DIR/diagnostic-derive-inline.rs:521:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:518:1 + --> $DIR/diagnostic-derive-inline.rs:521:1 | LL | #[warn_("this is an example message", code = E0123)] | ^ @@ -329,13 +335,13 @@ LL | #[warn_("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): `#[lint(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:528:1 | LL | #[lint("this is an example message", code = E0123)] | ^ error: derive(Diagnostic): diagnostic message not specified - --> $DIR/diagnostic-derive-inline.rs:525:1 + --> $DIR/diagnostic-derive-inline.rs:528:1 | LL | #[lint("this is an example message", code = E0123)] | ^ @@ -343,19 +349,19 @@ LL | #[lint("this is an example message", code = E0123)] = help: specify the message as the first argument to the `#[diag(...)]` attribute, such as `#[diag("Example error")]` error: derive(Diagnostic): attribute specified multiple times - --> $DIR/diagnostic-derive-inline.rs:534:53 + --> $DIR/diagnostic-derive-inline.rs:537:53 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ | note: previously specified here - --> $DIR/diagnostic-derive-inline.rs:534:39 + --> $DIR/diagnostic-derive-inline.rs:537:39 | LL | #[suggestion("with a suggestion", code = "...", code = ",,,")] | ^^^^ error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:543:24 + --> $DIR/diagnostic-derive-inline.rs:546:24 | LL | suggestion: (Span, usize), | ^^^^^ @@ -363,7 +369,7 @@ LL | suggestion: (Span, usize), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): wrong types for suggestion - --> $DIR/diagnostic-derive-inline.rs:551:17 + --> $DIR/diagnostic-derive-inline.rs:554:17 | LL | suggestion: (Span,), | ^^^^^^^ @@ -371,13 +377,13 @@ LL | suggestion: (Span,), = help: `#[suggestion(...)]` on a tuple field must be applied to fields of type `(Span, Applicability)` error: derive(Diagnostic): suggestion without `code = "..."` - --> $DIR/diagnostic-derive-inline.rs:558:5 + --> $DIR/diagnostic-derive-inline.rs:561:5 | LL | #[suggestion("with a suggestion")] | ^ error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:565:1 + --> $DIR/diagnostic-derive-inline.rs:568:1 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -385,7 +391,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:568:1 + --> $DIR/diagnostic-derive-inline.rs:571:1 | LL | #[multipart_suggestion()] | ^ @@ -393,7 +399,7 @@ LL | #[multipart_suggestion()] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[multipart_suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:572:5 + --> $DIR/diagnostic-derive-inline.rs:575:5 | LL | #[multipart_suggestion("with a suggestion")] | ^ @@ -401,7 +407,7 @@ LL | #[multipart_suggestion("with a suggestion")] = help: consider creating a `Subdiagnostic` instead error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:580:1 + --> $DIR/diagnostic-derive-inline.rs:583:1 | LL | #[suggestion("with a suggestion", code = "...")] | ^ @@ -409,7 +415,7 @@ LL | #[suggestion("with a suggestion", code = "...")] = help: `#[label]` and `#[suggestion]` can only be applied to fields error: derive(Diagnostic): `#[label]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:589:1 + --> $DIR/diagnostic-derive-inline.rs:592:1 | LL | #[label] | ^ @@ -417,67 +423,67 @@ LL | #[label] = help: subdiagnostic message is missing error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:623:5 + --> $DIR/diagnostic-derive-inline.rs:626:5 | LL | #[subdiagnostic(bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic = ...]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:631:5 + --> $DIR/diagnostic-derive-inline.rs:634:5 | LL | #[subdiagnostic = "bad"] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:639:5 + --> $DIR/diagnostic-derive-inline.rs:642:5 | LL | #[subdiagnostic(bad, bad)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:647:5 + --> $DIR/diagnostic-derive-inline.rs:650:5 | LL | #[subdiagnostic("bad")] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:655:5 + --> $DIR/diagnostic-derive-inline.rs:658:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): `#[subdiagnostic(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:676:5 + --> $DIR/diagnostic-derive-inline.rs:679:5 | LL | #[subdiagnostic(eager)] | ^ error: derive(Diagnostic): expected at least one string literal for `code(...)` - --> $DIR/diagnostic-derive-inline.rs:707:44 + --> $DIR/diagnostic-derive-inline.rs:710:44 | LL | #[suggestion("with a suggestion", code())] | ^ error: derive(Diagnostic): `code(...)` must contain only string literals - --> $DIR/diagnostic-derive-inline.rs:715:44 + --> $DIR/diagnostic-derive-inline.rs:718:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: unexpected token, expected `)` - --> $DIR/diagnostic-derive-inline.rs:715:44 + --> $DIR/diagnostic-derive-inline.rs:718:44 | LL | #[suggestion("with a suggestion", code(foo))] | ^^^ error: expected string literal - --> $DIR/diagnostic-derive-inline.rs:724:46 + --> $DIR/diagnostic-derive-inline.rs:727:46 | LL | #[suggestion("with a suggestion", code = 3)] | ^ error: derive(Diagnostic): `#[suggestion(...)]` is not a valid attribute - --> $DIR/diagnostic-derive-inline.rs:739:5 + --> $DIR/diagnostic-derive-inline.rs:742:5 | LL | #[suggestion("with a suggestion", code = "")] | ^ @@ -487,7 +493,7 @@ LL | #[suggestion("with a suggestion", code = "")] = help: to show a variable set of suggestions, use a `Vec` of `Subdiagnostic`s annotated with `#[suggestion(...)]` error: derive(Diagnostic): Variable `nosub` not found in diagnostic - --> $DIR/diagnostic-derive-inline.rs:751:8 + --> $DIR/diagnostic-derive-inline.rs:754:8 | LL | #[diag("does not exist: {$nosub}")] | ^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -501,13 +507,13 @@ LL | #[nonsense("this is an example message", code = E0123)] | ^^^^^^^^ error: cannot find attribute `nonsense` in this scope - --> $DIR/diagnostic-derive-inline.rs:138:7 + --> $DIR/diagnostic-derive-inline.rs:141:7 | LL | #[nonsense] | ^^^^^^^^ error: cannot find attribute `error` in this scope - --> $DIR/diagnostic-derive-inline.rs:511:3 + --> $DIR/diagnostic-derive-inline.rs:514:3 | LL | #[error("this is an example message", code = E0123)] | ^^^^^ @@ -519,7 +525,7 @@ LL | struct ErrorAttribute {} | error: cannot find attribute `warn_` in this scope - --> $DIR/diagnostic-derive-inline.rs:518:3 + --> $DIR/diagnostic-derive-inline.rs:521:3 | LL | #[warn_("this is an example message", code = E0123)] | ^^^^^ @@ -531,7 +537,7 @@ LL + #[warn("this is an example message", code = E0123)] | error: cannot find attribute `lint` in this scope - --> $DIR/diagnostic-derive-inline.rs:525:3 + --> $DIR/diagnostic-derive-inline.rs:528:3 | LL | #[lint("this is an example message", code = E0123)] | ^^^^ @@ -548,7 +554,7 @@ LL + #[lift("this is an example message", code = E0123)] | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:565:3 + --> $DIR/diagnostic-derive-inline.rs:568:3 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ @@ -560,7 +566,7 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:568:3 + --> $DIR/diagnostic-derive-inline.rs:571:3 | LL | #[multipart_suggestion()] | ^^^^^^^^^^^^^^^^^^^^ @@ -572,12 +578,12 @@ LL | struct MultipartSuggestion { | error: cannot find attribute `multipart_suggestion` in this scope - --> $DIR/diagnostic-derive-inline.rs:572:7 + --> $DIR/diagnostic-derive-inline.rs:575:7 | LL | #[multipart_suggestion("with a suggestion")] | ^^^^^^^^^^^^^^^^^^^^ | = note: `multipart_suggestion` is an attribute that can be used by the derive macro `Subdiagnostic`, you might be missing a `derive` attribute -error: aborting due to 75 previous errors +error: aborting due to 76 previous errors diff --git a/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-pass.rs b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-pass.rs new file mode 100644 index 0000000000000..ea116b0f17fd6 --- /dev/null +++ b/tests/ui-fulldeps/session-diagnostic/diagnostic-derive-pass.rs @@ -0,0 +1,38 @@ +//@ check-pass +//@ compile-flags: -Ztrack-diagnostics + +// The proc_macro2 crate handles spans differently when on beta/stable release rather than nightly, +// changing the output of this test. Since Diagnostic is strictly internal to the compiler +// the test is just ignored on stable and beta: +//@ ignore-stage1 +//@ ignore-beta +//@ ignore-stable + +#![feature(rustc_private)] +#![crate_type = "lib"] + +extern crate rustc_span; +use rustc_span::Span; + +extern crate rustc_macros; +use rustc_macros::Diagnostic; + +extern crate rustc_errors; +use rustc_errors::ErrCode; + +extern crate rustc_session; + +extern crate core; + +// E0123 is no longer used, so we define our own constant here just for this test. +const E0123: ErrCode = ErrCode::from_u32(0123); + +#[derive(Diagnostic)] +#[diag("message", code = E0123)] +struct Diagnostic { + #[primary_span] + #[label("label text")] + span: Span, + #[context] + context: Span, +} From c5f17f6260e3927b5953b3fe033624dede72a58b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 21:32:29 +0000 Subject: [PATCH 1004/1309] Point at enclosing item(s) on unexpected item type --- .../rustc_hir_analysis/src/diagnostics.rs | 4 ++++ .../src/hir_ty_lowering/errors.rs | 23 +++++++++++++++++++ .../associated-consts/shadowed-const.stderr | 2 ++ 3 files changed, 29 insertions(+) diff --git a/compiler/rustc_hir_analysis/src/diagnostics.rs b/compiler/rustc_hir_analysis/src/diagnostics.rs index ff5f7dbb119f1..421f0b52d5a3b 100644 --- a/compiler/rustc_hir_analysis/src/diagnostics.rs +++ b/compiler/rustc_hir_analysis/src/diagnostics.rs @@ -40,6 +40,10 @@ pub(crate) struct AssocKindMismatch { #[primary_span] #[label("unexpected {$got}")] pub span: Span, + #[context] + pub item_span: Span, + #[context] + pub enclosing_span: Option, pub expected: &'static str, pub got: &'static str, #[label("expected a {$expected} because of this associated {$expected}")] diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs index bee062b27e0f5..ae5553c592675 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs @@ -394,8 +394,31 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ { (ident.span, None, assoc_tag, assoc_item.tag()) }; + let def_kind = tcx.def_kind(self.item_def_id()); + let item_span = tcx.def_span(self.item_def_id()).shrink_to_lo(); + let (item_span, enclosing_span) = match def_kind { + DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => ( + item_span, + Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo()), + ), + DefKind::OpaqueTy => { + let item_span = tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo(); + let enclosing_span = + if let DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy = + tcx.def_kind(tcx.parent(self.item_def_id().into())) + { + Some(tcx.def_span(tcx.parent(self.item_def_id().into())).shrink_to_lo()) + } else { + None + }; + (item_span, enclosing_span) + } + _ => (item_span, None), + }; self.dcx().emit_err(diagnostics::AssocKindMismatch { span, + item_span, + enclosing_span, expected: assoc_tag_str(expected), got: assoc_tag_str(got), expected_because_label, diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr index 2db645b3c9662..4c105ddaf2974 100644 --- a/tests/ui/associated-consts/shadowed-const.stderr +++ b/tests/ui/associated-consts/shadowed-const.stderr @@ -1,6 +1,8 @@ error: expected type, found constant --> $DIR/shadowed-const.rs:19:20 | +LL | trait Baz3 { +LL | const BAR: usize; LL | const QUX: Self::BAR; | ^^^ unexpected constant | From 1ab22ea44d23a737ce1ecca38631664bf462421f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 22:51:39 +0000 Subject: [PATCH 1005/1309] Show trait/impl for duplicate impl associated items ``` error[E0201]: duplicate definitions with name `Bar`: --> $DIR/associated-item-duplicate-names-3.rs:14:5 | LL | trait Foo { LL | type Bar; | --------- item in trait ... LL | impl Foo for Baz { LL | type Bar = i16; | --------------- previous definition here LL | type Bar = u16; | ^^^^^^^^^^^^^^^ duplicate definition ``` --- .../rustc_resolve/src/diagnostics/impls.rs | 22 ++++++++++++------- compiler/rustc_resolve/src/diagnostics/mod.rs | 4 ++++ compiler/rustc_resolve/src/late.rs | 4 ++++ compiler/rustc_resolve/src/lib.rs | 8 ++++++- .../associated-item-duplicate-names-3.stderr | 2 ++ .../associated-item-duplicate-names.stderr | 6 +++++ ...licate-definition-inside-trait-impl.stderr | 2 ++ tests/ui/delegation/glob-glob-conflict.stderr | 4 ++++ tests/ui/delegation/glob-non-fn.stderr | 2 ++ .../impl-reuse-non-reuse-items.stderr | 1 + tests/ui/error-codes/E0201.stderr | 6 +++++ tests/ui/hygiene/impl_items-2.stderr | 3 +++ .../rpitit-duplicate-associated-fn.stderr | 4 ++++ .../pin-ergonomics/pinned-drop-check.stderr | 4 ++++ tests/ui/traits/issue-8153.stderr | 2 ++ 15 files changed, 65 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 2ea2f52c696ba..4f7147b6f8367 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1407,14 +1407,20 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { trait_item_span, }) .with_code(code), - ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => { - self.dcx().create_err(diagnostics::TraitImplDuplicate { - span, - name, - trait_item_span, - old_span, - }) - } + ResolutionError::TraitImplDuplicate { + name, + trait_item_span, + old_span, + trait_span, + impl_span, + } => self.dcx().create_err(diagnostics::TraitImplDuplicate { + span, + name, + trait_item_span, + trait_span, + impl_span, + old_span, + }), ResolutionError::InvalidAsmSym => { self.dcx().create_err(diagnostics::InvalidAsmSym { span }) } diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index ae4f7cabbe87f..75be11c2a7ce5 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -535,6 +535,10 @@ pub(crate) struct TraitImplDuplicate { pub(crate) old_span: Span, #[label("item in trait")] pub(crate) trait_item_span: Span, + #[context] + pub(crate) trait_span: Span, + #[context] + pub(crate) impl_span: Span, pub(crate) name: Ident, } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e1787eadf5fb9..22ecc02d93c9e 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3882,12 +3882,16 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { match seen_trait_items.entry(id_in_trait) { Entry::Occupied(entry) => { + let trait_span = decl.parent_module.unwrap().span.shrink_to_lo(); + let impl_span = self.current_trait_ref.as_ref().unwrap().1.path.span; self.report_error( span, ResolutionError::TraitImplDuplicate { name: ident, old_span: *entry.get(), trait_item_span: decl.span, + trait_span, + impl_span, }, ); return; diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 0a96becf993e9..efd6fe24e1900 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -325,7 +325,13 @@ enum ResolutionError<'ra> { code: ErrCode, }, /// Error E0201: multiple impl items for the same trait item. - TraitImplDuplicate { name: Ident, trait_item_span: Span, old_span: Span }, + TraitImplDuplicate { + name: Ident, + trait_item_span: Span, + old_span: Span, + trait_span: Span, + impl_span: Span, + }, /// Inline asm `sym` operand must refer to a `fn` or `static`. InvalidAsmSym, /// `self` used instead of `Self` in a generic parameter diff --git a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr index 84a9da0998832..950ee878fb391 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names-3.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names-3.stderr @@ -1,9 +1,11 @@ error[E0201]: duplicate definitions with name `Bar`: --> $DIR/associated-item-duplicate-names-3.rs:14:5 | +LL | trait Foo { LL | type Bar; | --------- item in trait ... +LL | impl Foo for Baz { LL | type Bar = i16; | --------------- previous definition here LL | type Bar = u16; diff --git a/tests/ui/associated-item/associated-item-duplicate-names.stderr b/tests/ui/associated-item/associated-item-duplicate-names.stderr index f89ea6e57cc43..b9c02a910d070 100644 --- a/tests/ui/associated-item/associated-item-duplicate-names.stderr +++ b/tests/ui/associated-item/associated-item-duplicate-names.stderr @@ -1,9 +1,11 @@ error[E0201]: duplicate definitions with name `Ty`: --> $DIR/associated-item-duplicate-names.rs:11:5 | +LL | trait Foo { LL | type Ty; | -------- item in trait ... +LL | impl Foo for () { LL | type Ty = (); | ------------- previous definition here LL | type Ty = usize; @@ -12,9 +14,13 @@ LL | type Ty = usize; error[E0201]: duplicate definitions with name `BAR`: --> $DIR/associated-item-duplicate-names.rs:13:5 | +LL | trait Foo { +LL | type Ty; LL | const BAR: u32; | --------------- item in trait ... +LL | impl Foo for () { +... LL | const BAR: u32 = 7; | ------------------- previous definition here LL | const BAR: u32 = 8; diff --git a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr index 9e2dd8ea84ac9..bd877e24bf2e8 100644 --- a/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr +++ b/tests/ui/delegation/duplicate-definition-inside-trait-impl.stderr @@ -1,9 +1,11 @@ error[E0201]: duplicate definitions with name `foo`: --> $DIR/duplicate-definition-inside-trait-impl.rs:18:5 | +LL | trait Trait { LL | fn foo(&self) -> u32 { 0 } | -------------------------- item in trait ... +LL | impl Trait for S { LL | reuse to_reuse::foo { self } | ---------------------------- previous definition here LL | reuse Trait::foo; diff --git a/tests/ui/delegation/glob-glob-conflict.stderr b/tests/ui/delegation/glob-glob-conflict.stderr index 4ada3eb0efa69..73831c9e48e33 100644 --- a/tests/ui/delegation/glob-glob-conflict.stderr +++ b/tests/ui/delegation/glob-glob-conflict.stderr @@ -1,9 +1,11 @@ error[E0201]: duplicate definitions with name `method`: --> $DIR/glob-glob-conflict.rs:26:5 | +LL | trait Trait { LL | fn method(&self) -> u8; | ----------------------- item in trait ... +LL | impl Trait for u8 { LL | reuse Trait1::*; | ---------------- previous definition here LL | reuse Trait2::*; @@ -12,9 +14,11 @@ LL | reuse Trait2::*; error[E0201]: duplicate definitions with name `method`: --> $DIR/glob-glob-conflict.rs:32:5 | +LL | trait Trait { LL | fn method(&self) -> u8; | ----------------------- item in trait ... +LL | impl Trait for u16 { LL | reuse Trait1::*; | ---------------- previous definition here LL | reuse Trait1::*; diff --git a/tests/ui/delegation/glob-non-fn.stderr b/tests/ui/delegation/glob-non-fn.stderr index e1a4ffce5ac17..3a67933b13222 100644 --- a/tests/ui/delegation/glob-non-fn.stderr +++ b/tests/ui/delegation/glob-non-fn.stderr @@ -19,9 +19,11 @@ LL | reuse Trait::* { &self.0 } error[E0201]: duplicate definitions with name `method`: --> $DIR/glob-non-fn.rs:29:5 | +LL | trait Trait { LL | fn method(&self); | ----------------- item in trait ... +LL | impl Trait for Bad { LL | reuse Trait::* { &self.0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ | | diff --git a/tests/ui/delegation/impl-reuse-non-reuse-items.stderr b/tests/ui/delegation/impl-reuse-non-reuse-items.stderr index 2a33982cc6730..e83b7d4e614db 100644 --- a/tests/ui/delegation/impl-reuse-non-reuse-items.stderr +++ b/tests/ui/delegation/impl-reuse-non-reuse-items.stderr @@ -19,6 +19,7 @@ LL | reuse impl Trait for S { &self.0 } error[E0201]: duplicate definitions with name `method`: --> $DIR/impl-reuse-non-reuse-items.rs:22:5 | +LL | trait Trait { LL | fn method(&self); | ----------------- item in trait ... diff --git a/tests/ui/error-codes/E0201.stderr b/tests/ui/error-codes/E0201.stderr index 608ff69177694..bd1ccc00fbd58 100644 --- a/tests/ui/error-codes/E0201.stderr +++ b/tests/ui/error-codes/E0201.stderr @@ -1,9 +1,13 @@ error[E0201]: duplicate definitions with name `baz`: --> $DIR/E0201.rs:17:5 | +LL | trait Baz { +LL | type Quux; LL | fn baz(&self) -> bool; | ---------------------- item in trait ... +LL | impl Baz for Foo { +... LL | fn baz(&self) -> bool { true } | ------------------------------ previous definition here LL | fn baz(&self) -> bool { self.0 > 5 } @@ -12,9 +16,11 @@ LL | fn baz(&self) -> bool { self.0 > 5 } error[E0201]: duplicate definitions with name `Quux`: --> $DIR/E0201.rs:18:5 | +LL | trait Baz { LL | type Quux; | ---------- item in trait ... +LL | impl Baz for Foo { LL | type Quux = u32; | ---------------- previous definition here ... diff --git a/tests/ui/hygiene/impl_items-2.stderr b/tests/ui/hygiene/impl_items-2.stderr index e7128f83e110b..723324c10294e 100644 --- a/tests/ui/hygiene/impl_items-2.stderr +++ b/tests/ui/hygiene/impl_items-2.stderr @@ -1,12 +1,15 @@ error[E0201]: duplicate definitions with name `foo`: --> $DIR/impl_items-2.rs:14:5 | +LL | trait Trait { LL | fn foo() {} | ----------- item in trait ... LL | fn foo() {} | ----------- previous definition here ... +LL | impl Trait for i32 { +LL | trait_impl!(); LL | fn foo() {} | ^^^^^^^^^^^ duplicate definition diff --git a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr index faa65f45d33cb..5f715ff16fa85 100644 --- a/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr +++ b/tests/ui/impl-trait/in-trait/rpitit-duplicate-associated-fn.stderr @@ -42,9 +42,11 @@ LL | fn foo() -> impl Sized; error[E0201]: duplicate definitions with name `method`: --> $DIR/rpitit-duplicate-associated-fn.rs:12:5 | +LL | trait Bar { LL | fn method() -> impl Sized; | -------------------------- item in trait ... +LL | impl Bar for () { LL | / fn method() -> impl Sized { LL | | 42 LL | | } @@ -57,9 +59,11 @@ LL | | } error[E0201]: duplicate definitions with name `method`: --> $DIR/rpitit-duplicate-associated-fn.rs:25:5 | +LL | trait T { LL | fn method() -> impl Sized; | -------------------------- item in trait ... +LL | impl T for () { LL | / fn method() -> impl Sized { LL | | 42 LL | | } diff --git a/tests/ui/pin-ergonomics/pinned-drop-check.stderr b/tests/ui/pin-ergonomics/pinned-drop-check.stderr index 3dc6e18a9178e..6087d45dd2900 100644 --- a/tests/ui/pin-ergonomics/pinned-drop-check.stderr +++ b/tests/ui/pin-ergonomics/pinned-drop-check.stderr @@ -1,24 +1,28 @@ error[E0201]: duplicate definitions with name `pin_drop`: --> $DIR/pinned-drop-check.rs:196:9 | +LL | impl Drop for Foo { LL | fn drop(&pin mut self) {} | ------------------------- previous definition here LL | fn pin_drop(&pin mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition | --> $SRC_DIR/core/src/ops/drop.rs:LL:COL + ::: $SRC_DIR/core/src/ops/drop.rs:LL:COL | = note: item in trait error[E0201]: duplicate definitions with name `pin_drop`: --> $DIR/pinned-drop-check.rs:201:9 | +LL | impl Drop for Bar { LL | fn drop(&pin mut self) {} | ------------------------- previous definition here LL | fn pin_drop(&pin mut self) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ duplicate definition | --> $SRC_DIR/core/src/ops/drop.rs:LL:COL + ::: $SRC_DIR/core/src/ops/drop.rs:LL:COL | = note: item in trait diff --git a/tests/ui/traits/issue-8153.stderr b/tests/ui/traits/issue-8153.stderr index 8882097af3390..cc0bf646d147c 100644 --- a/tests/ui/traits/issue-8153.stderr +++ b/tests/ui/traits/issue-8153.stderr @@ -1,9 +1,11 @@ error[E0201]: duplicate definitions with name `bar`: --> $DIR/issue-8153.rs:11:5 | +LL | trait Bar { LL | fn bar(&self) -> isize; | ----------------------- item in trait ... +LL | impl Bar for Foo { LL | fn bar(&self) -> isize {1} | -------------------------- previous definition here LL | fn bar(&self) -> isize {2} From be0d4321237e0bc04d4dc9112c00358d81c42307 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 22:59:34 +0000 Subject: [PATCH 1006/1309] Point at trait/impl on associated item mismatch ``` error[E0324]: item `RESOLVED_WRONG` is an associated method, which doesn't match its trait `MyTrait` --> $DIR/unresolved-trait-impl-item.rs:12:5 | LL | trait MyTrait { LL | async fn resolved(&self); LL | const RESOLVED_WRONG: u8 = 0; | ----------------------------- item in trait ... LL | impl MyTrait for i32 { ... LL | async fn RESOLVED_WRONG() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait ``` --- compiler/rustc_resolve/src/diagnostics/impls.rs | 4 ++++ compiler/rustc_resolve/src/diagnostics/mod.rs | 4 ++++ compiler/rustc_resolve/src/late.rs | 4 ++++ compiler/rustc_resolve/src/lib.rs | 2 ++ tests/ui/delegation/bad-resolve.stderr | 7 +++++++ tests/ui/delegation/glob-non-fn.stderr | 6 ++++++ tests/ui/delegation/impl-reuse-non-reuse-items.stderr | 4 ++++ tests/ui/privacy/unresolved-trait-impl-item.stderr | 4 ++++ tests/ui/span/impl-wrong-item-for-trait.stderr | 10 ++++++++++ 9 files changed, 45 insertions(+) diff --git a/compiler/rustc_resolve/src/diagnostics/impls.rs b/compiler/rustc_resolve/src/diagnostics/impls.rs index 4f7147b6f8367..f194690d82757 100644 --- a/compiler/rustc_resolve/src/diagnostics/impls.rs +++ b/compiler/rustc_resolve/src/diagnostics/impls.rs @@ -1397,6 +1397,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { code, trait_item_span, trait_path, + trait_span, + impl_span, } => self .dcx() .create_err(diagnostics::TraitImplMismatch { @@ -1405,6 +1407,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { kind, trait_path, trait_item_span, + trait_span, + impl_span, }) .with_code(code), ResolutionError::TraitImplDuplicate { diff --git a/compiler/rustc_resolve/src/diagnostics/mod.rs b/compiler/rustc_resolve/src/diagnostics/mod.rs index 75be11c2a7ce5..eb06ccb1c8ff4 100644 --- a/compiler/rustc_resolve/src/diagnostics/mod.rs +++ b/compiler/rustc_resolve/src/diagnostics/mod.rs @@ -1414,6 +1414,10 @@ pub(crate) struct TraitImplMismatch { pub(crate) trait_path: String, #[label("item in trait")] pub(crate) trait_item_span: Span, + #[context] + pub(crate) trait_span: Span, + #[context] + pub(crate) impl_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 22ecc02d93c9e..38afe52166d00 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3924,6 +3924,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } }; let trait_path = path_names_to_string(path); + let trait_span = decl.parent_module.unwrap().span.shrink_to_lo(); + let impl_span = self.current_trait_ref.as_ref().unwrap().1.path.span; self.report_error( span, ResolutionError::TraitImplMismatch { @@ -3932,6 +3934,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { code, trait_path, trait_item_span: decl.span, + trait_span, + impl_span, }, ); } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index efd6fe24e1900..334699fbdfbbb 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -323,6 +323,8 @@ enum ResolutionError<'ra> { trait_path: String, trait_item_span: Span, code: ErrCode, + trait_span: Span, + impl_span: Span, }, /// Error E0201: multiple impl items for the same trait item. TraitImplDuplicate { diff --git a/tests/ui/delegation/bad-resolve.stderr b/tests/ui/delegation/bad-resolve.stderr index 9740442e4b9f3..f0ff69b06e5fc 100644 --- a/tests/ui/delegation/bad-resolve.stderr +++ b/tests/ui/delegation/bad-resolve.stderr @@ -1,18 +1,25 @@ error[E0324]: item `C` is an associated method, which doesn't match its trait `Trait` --> $DIR/bad-resolve.rs:23:5 | +LL | trait Trait { LL | const C: u32 = 0; | ----------------- item in trait ... +LL | impl Trait for S { +LL | LL | reuse ::C; | ^^^^^^^^^^^^^^^^^^^^^^ does not match trait error[E0324]: item `Type` is an associated method, which doesn't match its trait `Trait` --> $DIR/bad-resolve.rs:26:5 | +LL | trait Trait { +LL | const C: u32 = 0; LL | type Type; | ---------- item in trait ... +LL | impl Trait for S { +... LL | reuse ::Type; | ^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait diff --git a/tests/ui/delegation/glob-non-fn.stderr b/tests/ui/delegation/glob-non-fn.stderr index 3a67933b13222..a09bc7a5aa27f 100644 --- a/tests/ui/delegation/glob-non-fn.stderr +++ b/tests/ui/delegation/glob-non-fn.stderr @@ -1,18 +1,24 @@ error[E0324]: item `CONST` is an associated method, which doesn't match its trait `Trait` --> $DIR/glob-non-fn.rs:29:5 | +LL | trait Trait { +LL | fn method(&self); LL | const CONST: u8; | ---------------- item in trait ... +LL | impl Trait for Bad { LL | reuse Trait::* { &self.0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait error[E0324]: item `Type` is an associated method, which doesn't match its trait `Trait` --> $DIR/glob-non-fn.rs:29:5 | +LL | trait Trait { +... LL | type Type; | ---------- item in trait ... +LL | impl Trait for Bad { LL | reuse Trait::* { &self.0 } | ^^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait diff --git a/tests/ui/delegation/impl-reuse-non-reuse-items.stderr b/tests/ui/delegation/impl-reuse-non-reuse-items.stderr index e83b7d4e614db..cc894d8ef4330 100644 --- a/tests/ui/delegation/impl-reuse-non-reuse-items.stderr +++ b/tests/ui/delegation/impl-reuse-non-reuse-items.stderr @@ -1,6 +1,8 @@ error[E0324]: item `CONST` is an associated method, which doesn't match its trait `Trait` --> $DIR/impl-reuse-non-reuse-items.rs:22:5 | +LL | trait Trait { +LL | fn method(&self); LL | const CONST: u8; | ---------------- item in trait ... @@ -10,6 +12,8 @@ LL | reuse impl Trait for S { &self.0 } error[E0324]: item `Type` is an associated method, which doesn't match its trait `Trait` --> $DIR/impl-reuse-non-reuse-items.rs:22:5 | +LL | trait Trait { +... LL | type Type; | ---------- item in trait ... diff --git a/tests/ui/privacy/unresolved-trait-impl-item.stderr b/tests/ui/privacy/unresolved-trait-impl-item.stderr index 588e47c26bcd1..3307d9114122b 100644 --- a/tests/ui/privacy/unresolved-trait-impl-item.stderr +++ b/tests/ui/privacy/unresolved-trait-impl-item.stderr @@ -10,9 +10,13 @@ LL | async fn unresolved(&self) {} error[E0324]: item `RESOLVED_WRONG` is an associated method, which doesn't match its trait `MyTrait` --> $DIR/unresolved-trait-impl-item.rs:12:5 | +LL | trait MyTrait { +LL | async fn resolved(&self); LL | const RESOLVED_WRONG: u8 = 0; | ----------------------------- item in trait ... +LL | impl MyTrait for i32 { +... LL | async fn RESOLVED_WRONG() {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ does not match trait diff --git a/tests/ui/span/impl-wrong-item-for-trait.stderr b/tests/ui/span/impl-wrong-item-for-trait.stderr index f919092f9ee92..e8066e224df0f 100644 --- a/tests/ui/span/impl-wrong-item-for-trait.stderr +++ b/tests/ui/span/impl-wrong-item-for-trait.stderr @@ -1,27 +1,37 @@ error[E0323]: item `bar` is an associated const, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:12:5 | +LL | trait Foo { LL | fn bar(&self); | -------------- item in trait ... +LL | impl Foo for FooConstForMethod { +LL | LL | const bar: u64 = 1; | ^^^^^^^^^^^^^^^^^^^ does not match trait error[E0324]: item `MY_CONST` is an associated method, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:22:5 | +LL | trait Foo { +LL | fn bar(&self); LL | const MY_CONST: u32; | -------------------- item in trait ... +LL | impl Foo for FooMethodForConst { +... LL | fn MY_CONST() {} | ^^^^^^^^^^^^^^^^ does not match trait error[E0325]: item `bar` is an associated type, which doesn't match its trait `Foo` --> $DIR/impl-wrong-item-for-trait.rs:30:5 | +LL | trait Foo { LL | fn bar(&self); | -------------- item in trait ... +LL | impl Foo for FooTypeForMethod { +LL | LL | type bar = u64; | ^^^^^^^^^^^^^^^ does not match trait From 246eb149ef7b489e2a94aaf0e78a0dc2f214dbfc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 27 Sep 2026 23:24:17 +0000 Subject: [PATCH 1007/1309] On `impl` item signature mismatch, point at impl and trait ``` error: `impl` item signature doesn't match `trait` item signature --> $DIR/self-without-lifetime-constraint.rs:46:5 | LL | pub trait FromSql: Sized { LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | -------------------------------------------------------------------- expected `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), _>` ... LL | impl FromSql for &str { LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), _>` | = note: expected signature `fn(ValueRef<'1>) -> Result<(&'2 str, &'1 &'2 str), FromSqlError>` found signature `fn(ValueRef<'1>) -> Result<(&'1 str, &'1 &'1 str), FromSqlError>` help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait` --> $DIR/self-without-lifetime-constraint.rs:42:60 | LL | fn column_result(value: ValueRef<'_>) -> FromSqlResult; | ^^^^ consider borrowing this type parameter in the trait ``` --- .../rustc_trait_selection/src/diagnostics.rs | 4 ++++ .../nice_region_error/trait_impl_difference.rs | 16 +++++++++++++--- ...fetime-mismatch-between-trait-and-impl.stderr | 2 ++ ...l-mismatch-elided-lifetime-issue-65866.stderr | 4 ++++ .../issue-75361-mismatched-impl.stderr | 4 ++++ tests/ui/self/elision/no-shadow-pin-self.stderr | 3 +++ .../param-without-lifetime-constraint.stderr | 2 ++ .../self-without-lifetime-constraint.stderr | 2 ++ 8 files changed, 34 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_trait_selection/src/diagnostics.rs b/compiler/rustc_trait_selection/src/diagnostics.rs index 80ffbba041ccd..a2bf84fb81419 100644 --- a/compiler/rustc_trait_selection/src/diagnostics.rs +++ b/compiler/rustc_trait_selection/src/diagnostics.rs @@ -1221,6 +1221,10 @@ pub(crate) struct TraitImplDiff { pub found_short: String, pub expected: String, pub found: String, + #[context] + pub trait_span: Span, + #[context] + pub impl_span: Span, } #[derive(Diagnostic)] diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs index 03baa5c2acbfb..43ac38005dba3 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/nice_region_error/trait_impl_difference.rs @@ -35,14 +35,21 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { ) = error.clone() && let (SubregionOrigin::Subtype(sup_trace), SubregionOrigin::Subtype(sub_trace)) = (&sup_origin, &sub_origin) - && let &ObligationCauseCode::CompareImplItem { trait_item_def_id, .. } = - sub_trace.cause.code() + && let &ObligationCauseCode::CompareImplItem { + trait_item_def_id, impl_item_def_id, .. + } = sub_trace.cause.code() && sub_trace.values == sup_trace.values && let ValuePairs::PolySigs(ExpectedFound { expected, found }) = sub_trace.values { // FIXME(compiler-errors): Don't like that this needs `Ty`s, but // all of the region highlighting machinery only deals with those. - let guar = self.emit_err(var_origin.span(), expected, found, trait_item_def_id); + let guar = self.emit_err( + var_origin.span(), + expected, + found, + trait_item_def_id, + impl_item_def_id.into(), + ); return Some(guar); } None @@ -54,6 +61,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { expected: ty::PolyFnSig<'tcx>, found: ty::PolyFnSig<'tcx>, trait_item_def_id: DefId, + impl_item_def_id: DefId, ) -> ErrorGuaranteed { let trait_sp = self.tcx().def_span(trait_item_def_id); @@ -135,6 +143,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> { found, expected_short, found_short, + trait_span: self.tcx().def_span(self.tcx().parent(trait_item_def_id)).shrink_to_lo(), + impl_span: self.tcx().def_span(self.tcx().parent(impl_item_def_id)).shrink_to_lo(), }; let mut diag = self.tcx().dcx().create_err(diag); diff --git a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr index 917d204367ffe..ad3500a6ff61d 100644 --- a/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr +++ b/tests/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr @@ -1,9 +1,11 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5 | +LL | trait Foo { LL | fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32; | ------------------------------------------- expected `fn(&'1 i32, &'a i32) -> &'a i32` ... +LL | impl Foo for () { LL | fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 i32, &'1 i32) -> &'1 i32` | diff --git a/tests/ui/lifetimes/trait-impl-mismatch-elided-lifetime-issue-65866.stderr b/tests/ui/lifetimes/trait-impl-mismatch-elided-lifetime-issue-65866.stderr index 4c4f6032b0f7b..cfe1e9353316f 100644 --- a/tests/ui/lifetimes/trait-impl-mismatch-elided-lifetime-issue-65866.stderr +++ b/tests/ui/lifetimes/trait-impl-mismatch-elided-lifetime-issue-65866.stderr @@ -1,9 +1,11 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/trait-impl-mismatch-elided-lifetime-issue-65866.rs:17:9 | +LL | trait Bar { LL | fn bar(&self, r: &mut Re); | -------------------------- expected `fn(&'1 Foo, &'2 mut Re<'3>)` ... +LL | impl Bar for Foo { LL | fn bar<'a, 'b>(&'a self, _r: &'b mut Re<'a>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Foo, &'2 mut Re<'1>)` | @@ -20,9 +22,11 @@ LL | fn bar(&self, r: &mut Re); error: `impl` item signature doesn't match `trait` item signature --> $DIR/trait-impl-mismatch-elided-lifetime-issue-65866.rs:40:9 | +LL | trait Bar { LL | fn bar(&self, r: &mut Re); | ------------------------------ expected `fn(&'1 Foo, &'2 mut Re<'3, u8>)` ... +LL | impl Bar for Foo { LL | fn bar<'a, 'b>(&'a self, _r: &'b mut Re<'a, u8>) {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 Foo, &'2 mut Re<'1, u8>)` | diff --git a/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr index 5c2278ddfc6af..09556076d787a 100644 --- a/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr +++ b/tests/ui/mismatched_types/issue-75361-mismatched-impl.stderr @@ -1,9 +1,13 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/issue-75361-mismatched-impl.rs:18:3 | +LL | pub trait Graph { +... LL | fn adjacent_edges(&self) -> Box>; | --------------------------------------------------------------------- expected `fn(&'1 T) -> Box<(dyn MyTrait + 'static)>` ... +LL | impl Graph for T { +... LL | fn adjacent_edges(&self) -> Box + '_> { | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&'1 T) -> Box<(dyn MyTrait + '1)>` | diff --git a/tests/ui/self/elision/no-shadow-pin-self.stderr b/tests/ui/self/elision/no-shadow-pin-self.stderr index 23485e9de79b7..2b2559d5a4274 100644 --- a/tests/ui/self/elision/no-shadow-pin-self.stderr +++ b/tests/ui/self/elision/no-shadow-pin-self.stderr @@ -1,9 +1,12 @@ error: `impl` item signature doesn't match `trait` item signature --> $DIR/no-shadow-pin-self.rs:10:5 | +LL | trait Trait { LL | fn method<'a>(self: Pin<&Self>, f: &'a u32) -> &'a u32 { | ------------------------------------------------------ expected `fn(Pin<&'1 Pin

  • +where + P: [const] core::ops::Deref + core::pin::PinSafePointer, +{ + #[inline] + fn allocate(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate(layout) + } + + #[inline] + fn allocate_zeroed(&self, layout: Layout) -> Result, AllocError> { + (**self).allocate_zeroed(layout) + } + + #[inline] + unsafe fn deallocate(&self, ptr: NonNull, layout: Layout) { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).deallocate(ptr, layout) } + } + + #[inline] + unsafe fn grow( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn grow_zeroed( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).grow_zeroed(ptr, old_layout, new_layout) } + } + + #[inline] + unsafe fn shrink( + &self, + ptr: NonNull, + old_layout: Layout, + new_layout: Layout, + ) -> Result, AllocError> { + // SAFETY: the safety contract must be upheld by the caller + unsafe { (**self).shrink(ptr, old_layout, new_layout) } + } +} + #[unstable(feature = "allocator_api", issue = "32838")] unsafe impl AllocatorClone for &A {} From d577cee5eb686d16a21771d2481743f1e8fe0983 Mon Sep 17 00:00:00 2001 From: Linus Kirkwood Date: Sun, 19 Apr 2026 17:32:01 +1000 Subject: [PATCH 0531/1309] Lint nested `format_args!` for uninlined args Previously a `format_args!` call or a macro marked `clippy::format_args` would not be linted for uninlined arguments when one of the arguments was in turn a `format_args!` call. --- clippy_lints/src/format_args.rs | 44 ++++++++++++++++++++++----- clippy_utils/src/macros.rs | 18 +++++++++++ tests/ui/uninlined_format_args.fixed | 11 ++++--- tests/ui/uninlined_format_args.rs | 5 +-- tests/ui/uninlined_format_args.stderr | 38 ++++++++++++++++++++++- 5 files changed, 100 insertions(+), 16 deletions(-) diff --git a/clippy_lints/src/format_args.rs b/clippy_lints/src/format_args.rs index 22be9d8367daa..48f23f02c75ec 100644 --- a/clippy_lints/src/format_args.rs +++ b/clippy_lints/src/format_args.rs @@ -341,7 +341,7 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs<'tcx> { fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'tcx>) { if let Some(macro_call) = root_macro_call_first_node(cx, expr) && is_format_macro(cx, macro_call.def_id) - && let Some(format_args) = self.format_args.get(cx, expr, macro_call.expn) + && let Some(mut format_args) = self.format_args.get(cx, expr, macro_call.expn) { let mut linter = FormatArgsExpr { cx, @@ -358,8 +358,34 @@ impl<'tcx> LateLintPass<'tcx> for FormatArgs<'tcx> { linter.check_trailing_comma(); linter.check_templates(); - if self.msrv.meets(cx, msrvs::FORMAT_ARGS_CAPTURE) { - linter.check_uninlined_args(); + if !self.msrv.meets(cx, msrvs::FORMAT_ARGS_CAPTURE) { + return; + } + + let mut uninlined_queue = vec![]; + loop { + if linter.check_uninlined_args() { + break; + } + + uninlined_queue.extend(self.format_args.get_nested(format_args)); + if let Some(inner_format_args) = uninlined_queue.pop() { + format_args = inner_format_args; + + linter = FormatArgsExpr { + cx, + expr, + macro_call: ¯o_call, + format_args, + ignore_mixed: self.ignore_mixed, + msrv: &self.msrv, + ty_msrv_map: &self.ty_msrv_map, + has_derived_debug: &mut self.has_derived_debug, + has_pointer_format: &mut self.has_pointer_format, + }; + } else { + break; + } } } } @@ -575,16 +601,16 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { } } - fn check_uninlined_args(&self) { + fn check_uninlined_args(&self) -> bool { if self.format_args.span.from_expansion() { - return; + return false; } if self.macro_call.span.edition() < Edition2021 && (is_panic(self.cx, self.macro_call.def_id) || is_assert_macro(self.cx, self.macro_call.def_id)) { // panic!, assert!, and debug_assert! before 2021 edition considers a single string argument as // non-format - return; + return false; } let mut fixes = Vec::new(); @@ -595,12 +621,12 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { // Example of an un-inlinable format: print!("{}{1}", foo, 2) for (pos, usage) in self.format_arg_positions() { if !self.check_one_arg(pos, usage, &mut fixes) { - return; + return !fixes.is_empty(); } } if fixes.is_empty() { - return; + return false; } // multiline span display suggestion is sometimes broken: https://github.com/rust-lang/rust/pull/102729#discussion_r988704308 @@ -627,6 +653,8 @@ impl<'tcx> FormatArgsExpr<'_, 'tcx> { ); }, ); + + true } fn check_one_arg(&self, pos: &FormatArgPosition, usage: FormatParamUsage, fixes: &mut Vec<(Span, String)>) -> bool { diff --git a/clippy_utils/src/macros.rs b/clippy_utils/src/macros.rs index c0b4a62cdb0b7..1537f1b9e2f49 100644 --- a/clippy_utils/src/macros.rs +++ b/clippy_utils/src/macros.rs @@ -461,6 +461,24 @@ impl FormatArgsStorage { self.0.get()?.get(&format_args_expr.span.with_parent(None)) } + /// Returns AST [`FormatArgs`] nodes if there are any nested inside `parent_format_args`. + pub fn get_nested(&self, parent_format_args: &FormatArgs) -> Vec<&FormatArgs> { + let mut nested = Vec::new(); + let Some(format_args_map) = self.0.get() else { + return nested; + }; + + for arg in parent_format_args.arguments.all_args() { + if matches!(arg.expr.kind, rustc_ast::ExprKind::FormatArgs(_)) + && let Some(format_args) = format_args_map.get(&arg.expr.span.with_parent(None)) + { + nested.push(format_args); + } + } + + nested + } + /// Should only be called by `FormatArgsCollector` pub fn set(&self, format_args: FxHashMap) { self.0 diff --git a/tests/ui/uninlined_format_args.fixed b/tests/ui/uninlined_format_args.fixed index 8d4de4f5bda25..4b2043c4d8ce2 100644 --- a/tests/ui/uninlined_format_args.fixed +++ b/tests/ui/uninlined_format_args.fixed @@ -375,9 +375,10 @@ fn nested_format_args_user() { let local_i32 = 1; let local_f64 = 2.0; - // false negative: should warn but currently doesn't because the inner format_args - // is not processed when it's used as an argument to another format_args - nested_format_args!("{}", local_i32); - nested_format_args!("val='{}'", local_i32); - nested_format_args!("{:.1}", local_f64); + nested_format_args!("{local_i32}"); + //~^ uninlined_format_args + nested_format_args!("val='{local_i32}'"); + //~^ uninlined_format_args + nested_format_args!("{local_f64:.1}"); + //~^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args.rs b/tests/ui/uninlined_format_args.rs index 0af948dd0a4fa..b252876f860be 100644 --- a/tests/ui/uninlined_format_args.rs +++ b/tests/ui/uninlined_format_args.rs @@ -380,9 +380,10 @@ fn nested_format_args_user() { let local_i32 = 1; let local_f64 = 2.0; - // false negative: should warn but currently doesn't because the inner format_args - // is not processed when it's used as an argument to another format_args nested_format_args!("{}", local_i32); + //~^ uninlined_format_args nested_format_args!("val='{}'", local_i32); + //~^ uninlined_format_args nested_format_args!("{:.1}", local_f64); + //~^ uninlined_format_args } diff --git a/tests/ui/uninlined_format_args.stderr b/tests/ui/uninlined_format_args.stderr index 8fc35af75036c..9378a49bb4054 100644 --- a/tests/ui/uninlined_format_args.stderr +++ b/tests/ui/uninlined_format_args.stderr @@ -895,5 +895,41 @@ LL - usr_println!(true, "{:.1}", local_f64); LL + usr_println!(true, "{local_f64:.1}"); | -error: aborting due to 75 previous errors +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:383:5 + | +LL | nested_format_args!("{}", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - nested_format_args!("{}", local_i32); +LL + nested_format_args!("{local_i32}"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:385:5 + | +LL | nested_format_args!("val='{}'", local_i32); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - nested_format_args!("val='{}'", local_i32); +LL + nested_format_args!("val='{local_i32}'"); + | + +error: variables can be used directly in the `format!` string + --> tests/ui/uninlined_format_args.rs:387:5 + | +LL | nested_format_args!("{:.1}", local_f64); + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + | +help: change this to + | +LL - nested_format_args!("{:.1}", local_f64); +LL + nested_format_args!("{local_f64:.1}"); + | + +error: aborting due to 78 previous errors From 3285cce3dad8e74b1ecaf98675cc8b218c900758 Mon Sep 17 00:00:00 2001 From: Folkert de Vries Date: Sat, 19 Sep 2026 16:30:33 +0200 Subject: [PATCH 0532/1309] fix `va_arg` on `f128` on `x86` --- compiler/rustc_codegen_llvm/src/va_arg.rs | 31 +++++++---- tests/assembly-llvm/c-variadic/x86-linux.rs | 57 +++++++++++++++++---- 2 files changed, 68 insertions(+), 20 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/va_arg.rs b/compiler/rustc_codegen_llvm/src/va_arg.rs index b21ce3f2be8e4..18229e6d14ba5 100644 --- a/compiler/rustc_codegen_llvm/src/va_arg.rs +++ b/compiler/rustc_codegen_llvm/src/va_arg.rs @@ -1057,15 +1057,28 @@ pub(super) fn emit_va_arg<'ll, 'tcx>( let stability = target.supports_c_variadic_definitions(); match target.arch { - Arch::X86 => emit_ptr_va_arg( - bx, - addr, - layout, - PassMode::Direct, - SlotSize::Bytes4, - if target.is_like_windows { AllowHigherAlign::No } else { AllowHigherAlign::Yes }, - ForceRightAdjust::No, - ), + Arch::X86 => { + // A small deviation from clang to get the right behavior for f128. + // + // Note that i64 and f64 have an alignment of only 4 on this architecture. + // We need to be careful when adding future types with an alignment bigger + // than 4 (e.g. i128), clang has a bunch of custom logic for them. + let allow_higher_align = if layout.ty == bx.tcx().types.f128 { + AllowHigherAlign::Yes + } else { + AllowHigherAlign::No + }; + + emit_ptr_va_arg( + bx, + addr, + layout, + PassMode::Direct, + SlotSize::Bytes4, + allow_higher_align, + ForceRightAdjust::No, + ) + } Arch::Arm64EC => emit_ptr_va_arg( bx, addr, diff --git a/tests/assembly-llvm/c-variadic/x86-linux.rs b/tests/assembly-llvm/c-variadic/x86-linux.rs index d2f5c1144a991..de647ca861cb6 100644 --- a/tests/assembly-llvm/c-variadic/x86-linux.rs +++ b/tests/assembly-llvm/c-variadic/x86-linux.rs @@ -9,7 +9,7 @@ //@ [I686] compile-flags: -Copt-level=3 -Cllvm-args=-x86-asm-syntax=intel //@ [I686] compile-flags: --target i686-unknown-linux-gnu //@ needs-llvm-components: x86 -#![feature(no_core, lang_items, intrinsics, rustc_attrs)] +#![feature(no_core, lang_items, intrinsics, rustc_attrs, f128)] #![no_core] #![crate_type = "lib"] @@ -64,20 +64,55 @@ unsafe extern "C" fn read_f64(ap: &mut VaList<'_>) -> f64 { ap.next_arg() } +#[unsafe(no_mangle)] +unsafe extern "C" fn read_f128(ap: &mut VaList<'_>) -> f128 { + // CHECK-LABEL: read_f128 + + // X86_64: mov ecx, dword ptr [rdi + 4] + // X86_64-NEXT: cmp rcx, 160 + // X86_64-NEXT: ja .LBB1_2 + // X86_64-NEXT: mov rax, rcx + // X86_64-NEXT: add rax, qword ptr [rdi + 16] + // X86_64-NEXT: add ecx, 16 + // X86_64-NEXT: mov dword ptr [rdi + 4], ecx + // X86_64-NEXT: movaps xmm0, xmmword ptr [rax] + // X86_64-NEXT: ret + // X86_64-NEXT: .LBB1_2: + // X86_64-NEXT: mov rax, qword ptr [rdi + 8] + // X86_64-NEXT: add rax, 15 + // X86_64-NEXT: and rax, -16 + // X86_64-NEXT: lea rcx, [rax + 16] + // X86_64-NEXT: mov qword ptr [rdi + 8], rcx + // X86_64-NEXT: movaps xmm0, xmmword ptr [rax] + // X86_64-NEXT: ret + + // I686: mov ecx, dword ptr [esp + 12] + // I686-NEXT: mov eax, dword ptr [esp + 8] + // I686-NEXT: mov edx, dword ptr [ecx] + // I686-NEXT: add edx, 15 + // I686-NEXT: and edx, -16 + // I686-NEXT: lea esi, [edx + 16] + // I686-NEXT: mov dword ptr [ecx], esi + // I686-NEXT: movaps xmm0, xmmword ptr [edx] + // I686-NEXT: movaps xmmword ptr [eax], xmm0 + // I686-NEXT: pop esi + ap.next_arg() +} + #[unsafe(no_mangle)] unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // CHECK-LABEL: read_i32 // // X86_64: mov ecx, dword ptr [rdi] // X86_64-NEXT: cmp rcx, 40 - // X86_64-NEXT: ja .LBB1_2 + // X86_64-NEXT: ja .LBB2_2 // X86_64-NEXT: mov rax, rcx // X86_64-NEXT: add rax, qword ptr [rdi + 16] // X86_64-NEXT: add ecx, 8 // X86_64-NEXT: mov dword ptr [rdi], ecx // X86_64-NEXT: mov eax, dword ptr [rax] // X86_64-NEXT: ret - // X86_64-NEXT: .LBB1_2: + // X86_64-NEXT: .LBB2_2: // X86_64-NEXT: mov rax, qword ptr [rdi + 8] // X86_64-NEXT: lea rcx, [rax + 8] // X86_64-NEXT: mov qword ptr [rdi + 8], rcx @@ -86,14 +121,14 @@ unsafe extern "C" fn read_i32(ap: &mut VaList<'_>) -> i32 { // X86_64-NEXT_GNUX32: mov ecx, dword ptr [edi] // X86_64-NEXT_GNUX32-NEXT: cmp ecx, 40 - // X86_64-NEXT_GNUX32-NEXT: ja .LBB1_2 + // X86_64-NEXT_GNUX32-NEXT: ja .LBB2_2 // X86_64-NEXT_GNUX32-NEXT: mov eax, dword ptr [edi + 12] // X86_64-NEXT_GNUX32-NEXT: add eax, ecx // X86_64-NEXT_GNUX32-NEXT: add ecx, 8 // X86_64-NEXT_GNUX32-NEXT: mov dword ptr [edi], ecx // X86_64-NEXT_GNUX32-NEXT: mov eax, dword ptr [eax] // X86_64-NEXT_GNUX32-NEXT: ret - // X86_64-NEXT_GNUX32-NEXT: .LBB1_2: + // X86_64-NEXT_GNUX32-NEXT: .LBB2_2: // X86_64-NEXT_GNUX32-NEXT: mov eax, dword ptr [edi + 8] // X86_64-NEXT_GNUX32-NEXT: lea ecx, [rax + 8] // X86_64-NEXT_GNUX32-NEXT: mov dword ptr [edi + 8], ecx @@ -115,14 +150,14 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // X86_64: mov ecx, dword ptr [rdi] // X86_64-NEXT: cmp rcx, 40 - // X86_64-NEXT: ja .LBB2_2 + // X86_64-NEXT: ja .LBB3_2 // X86_64-NEXT: mov rax, rcx // X86_64-NEXT: add rax, qword ptr [rdi + 16] // X86_64-NEXT: add ecx, 8 // X86_64-NEXT: mov dword ptr [rdi], ecx // X86_64-NEXT: mov rax, qword ptr [rax] // X86_64-NEXT: ret - // X86_64-NEXT: .LBB2_2: + // X86_64-NEXT: .LBB3_2: // X86_64-NEXT: mov rax, qword ptr [rdi + 8] // X86_64-NEXT: lea rcx, [rax + 8] // X86_64-NEXT: mov qword ptr [rdi + 8], rcx @@ -131,7 +166,7 @@ unsafe extern "C" fn read_i64(ap: &mut VaList<'_>) -> i64 { // X86_64-NEXT_GNUX32: mov ecx, dword ptr [edi] // X86_64-NEXT_GNUX32-NEXT: cmp ecx, 40 - // X86_64-NEXT_GNUX32-NEXT: ja .LBB2_2 + // X86_64-NEXT_GNUX32-NEXT: ja .LBB3_2 // X86_64-NEXT_GNUX32-NEXT: mov eax, dword ptr [edi + 12] // X86_64-NEXT_GNUX32-NEXT: add eax, ecx // X86_64-NEXT_GNUX32-NEXT: add ecx, 8 @@ -162,14 +197,14 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // // X86_64: mov ecx, dword ptr [rdi] // X86_64-NEXT: cmp rcx, 32 - // X86_64-NEXT: ja .LBB3_2 + // X86_64-NEXT: ja .LBB4_2 // X86_64-NEXT: mov rdx, qword ptr [rdi + 16] // X86_64-NEXT: mov rax, qword ptr [rdx + rcx] // X86_64-NEXT: mov rdx, qword ptr [rdx + rcx + 8] // X86_64-NEXT: add ecx, 16 // X86_64-NEXT: mov dword ptr [rdi], ecx // X86_64-NEXT: ret - // X86_64-NEXT: .LBB3_2: + // X86_64-NEXT: .LBB4_2: // X86_64-NEXT: mov rcx, qword ptr [rdi + 8] // X86_64-NEXT: add rcx, 15 // X86_64-NEXT: and rcx, -16 @@ -181,7 +216,7 @@ unsafe extern "C" fn read_i128(ap: &mut VaList<'_>) -> i128 { // X86_64-NEXT_GNUX32: mov ecx, dword ptr [edi] // X86_64-NEXT_GNUX32-NEXT: cmp ecx, 32 - // X86_64-NEXT_GNUX32-NEXT: ja .LBB3_2 + // X86_64-NEXT_GNUX32-NEXT: ja .LBB4_2 // X86_64-NEXT_GNUX32-NEXT: mov edx, dword ptr [edi + 12] // X86_64-NEXT_GNUX32-NEXT: mov rax, qword ptr [edx + ecx] // X86_64-NEXT_GNUX32-NEXT: mov rdx, qword ptr [edx + ecx + 8] From 094c3893df50948ccf12063a9450c79261b27340 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 17 Sep 2026 18:32:23 +0000 Subject: [PATCH 0533/1309] remove `PathKind`, use `ast::Path` for all local paths directly --- .../rustc_builtin_macros/src/deriving/from.rs | 5 ++-- .../src/deriving/generic/ty.rs | 24 ++++--------------- .../rustc_builtin_macros/src/deriving/hash.rs | 4 ++-- .../src/deriving/partial_eq.rs | 6 ++--- .../src/deriving/partial_ord.rs | 3 +-- 5 files changed, 13 insertions(+), 29 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 0b28df9850097..83a65ed19fbc7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -5,7 +5,7 @@ use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::{Path, PathKind, Ty}; +use crate::deriving::generic::ty::{Path, Ty}; use crate::deriving::generic::*; use crate::deriving::pathvec; use crate::diagnostics; @@ -52,8 +52,7 @@ pub(crate) fn expand_deriving_from( Err(guar) => cx.ty(span, ast::TyKind::Err(guar)), }); - let path = - Path::new_(pathvec!(convert::From), vec![Box::new(from_type.clone())], PathKind::Std); + let path = Path::new_(pathvec!(convert::From), vec![Box::new(from_type.clone())]); // Generate code like this: // diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 9efe0b109f17d..caaeb66c10cd3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -15,24 +15,14 @@ use thin_vec::ThinVec; pub(crate) struct Path { path: Vec, params: Vec>, - kind: PathKind, -} - -#[derive(Clone)] -pub(crate) enum PathKind { - Local, - Std, } impl Path { pub(crate) fn new(path: Vec) -> Path { - Path::new_(path, Vec::new(), PathKind::Std) - } - pub(crate) fn new_local(path: Symbol) -> Path { - Path::new_(vec![path], Vec::new(), PathKind::Local) + Path::new_(path, Vec::new()) } - pub(crate) fn new_(path: Vec, params: Vec>, kind: PathKind) -> Path { - Path { path, params, kind } + pub(crate) fn new_(path: Vec, params: Vec>) -> Path { + Path { path, params } } pub(crate) fn to_path(&self, cx: &ExtCtxt<'_>, span: Span) -> ast::Path { @@ -40,12 +30,8 @@ impl Path { let tys = self.params.iter().map(|t| t.to_ty(cx, span)); let params = tys.map(GenericArg::Type).collect(); - let idents = if let PathKind::Std = self.kind { - let def_site = cx.with_def_site_ctxt(DUMMY_SP); - once(Ident::new(kw::DollarCrate, def_site)).chain(idents).collect() - } else { - idents.collect() - }; + let def_site = cx.with_def_site_ctxt(DUMMY_SP); + let idents = once(Ident::new(kw::DollarCrate, def_site)).chain(idents).collect(); cx.path_all(span, false, idents, params) } } diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index b6a87851254fc..8593a17c0571a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -18,7 +18,7 @@ pub(crate) fn expand_deriving_hash( let typaram = sym::__H; - let arg = Path::new_local(typaram); + let arg = cx.ty_path(cx.path_ident(span, Ident::new(typaram, span))); let param = { let path = cx.path_all(span, false, cx.std_path(&[sym::hash, sym::Hasher]), Vec::new()); @@ -42,7 +42,7 @@ pub(crate) fn expand_deriving_hash( name: sym::hash, generics, explicit_self: true, - nonself_args: smallvec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], + nonself_args: smallvec![(Ref(Box::new(AstTy(arg)), Mutability::Mut), sym::state)], ret_ty: Unit, attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index be48c0532e596..2bfee6b754496 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -1,10 +1,10 @@ use rustc_ast::{BinOpKind, BorrowKind, Expr, ExprKind, Mutability, Safety}; use rustc_expand::base::ExtCtxt; -use rustc_span::{Span, sym}; +use rustc_span::{Ident, Span, sym}; use thin_vec::thin_vec; use crate::deriving::generic::ty::*; -use crate::deriving::generic::{self, *}; +use crate::deriving::generic::*; use crate::deriving::path_std; /// Expands a `#[derive(PartialEq)]` attribute into an implementation for the @@ -43,7 +43,7 @@ pub(crate) fn expand_deriving_partial_eq( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(generic::ty::Path::new_local(sym::bool)), + ret_ty: AstTy(cx.ty_path(cx.path_ident(span, Ident::new(sym::bool, span)))), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(get_substructure_equality_expr), diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 8c1d89da6ab30..2023287af5110 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -15,8 +15,7 @@ pub(crate) fn expand_deriving_partial_ord( is_const: bool, ) { let ordering_ty = Path(path_std!(cmp::Ordering)); - let ret_ty = - Path(Path::new_(pathvec!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std)); + let ret_ty = Path(Path::new_(pathvec!(option::Option), vec![Box::new(ordering_ty)])); // Order in which to perform matching let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { From 69a26a88f37cfdf67b40feb4c8e017e8d1914575 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Thu, 17 Sep 2026 21:30:48 +0000 Subject: [PATCH 0534/1309] bounds are `Path`s, not `Ty`s --- .../src/deriving/clone.rs | 2 +- .../src/deriving/const_param_ty.rs | 2 +- .../src/deriving/generic/mod.rs | 2 +- .../src/deriving/generic/ty.rs | 22 +++---------------- .../src/deriving/partial_eq.rs | 2 +- 5 files changed, 7 insertions(+), 23 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 3257fc3437273..bfdd847d706cd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -50,7 +50,7 @@ pub(crate) fn expand_deriving_clone( } } ItemKind::Union(..) => { - bounds = smallvec![Path(path_std!(marker::Copy))]; + bounds = smallvec![path_std!(marker::Copy)]; is_simple = true; substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); } diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs index 8034a3e9b0b16..91755dfb4c933 100644 --- a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -17,7 +17,7 @@ pub(crate) fn expand_deriving_const_param_ty( path: path_std!(marker::ConstParamTy_), skip_path_as_bound: false, needs_copy_as_bound_if_packed: false, - additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::Eq))], + additional_bounds: smallvec![path_std!(cmp::Eq)], supports_unions: false, methods: SmallVec::new(), associated_types: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 39bfaf40681c6..67f0128b32b49 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -212,7 +212,7 @@ pub(crate) struct TraitDef<'a> { /// Additional bounds required of any type parameters of the type, /// other than the current trait - pub additional_bounds: SmallVec<[Ty; 1]>, + pub additional_bounds: SmallVec<[Path; 1]>, /// Can this trait be derived for unions? pub supports_unions: bool, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index caaeb66c10cd3..b9ebb2963ae46 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -4,7 +4,7 @@ use std::iter::once; pub(crate) use Ty::*; -use rustc_ast::{self as ast, GenericArg, TyKind}; +use rustc_ast::{self as ast, GenericArg}; use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; use thin_vec::ThinVec; @@ -63,25 +63,9 @@ impl Ty { cx.ty_ref(span, raw_ty, None, *mutbl) } Path(p) => cx.ty_path(p.to_path(cx, span)), - Self_ => cx.ty_path(self.to_path(cx, span)), - Unit => { - let ty = ast::TyKind::Tup(ThinVec::new()); - cx.ty(span, ty) - } + Self_ => cx.ty_path(cx.path_ident(span, Ident::new(kw::SelfUpper, span))), + Unit => cx.ty(span, ast::TyKind::Tup(ThinVec::new())), AstTy(ty) => ty.clone(), } } - - pub(crate) fn to_path(&self, cx: &ExtCtxt<'_>, span: Span) -> ast::Path { - match self { - Self_ => cx.path_ident(span, Ident::new(kw::SelfUpper, span)), - Path(p) => p.to_path(cx, span), - AstTy(ty) => match &ty.kind { - TyKind::Path(_, path) => path.clone(), - _ => cx.dcx().span_bug(span, "non-path in a path in generic `derive`"), - }, - Ref(..) => cx.dcx().span_bug(span, "ref in a path in generic `derive`"), - Unit => cx.dcx().span_bug(span, "unit in a path in generic `derive`"), - } - } } diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 2bfee6b754496..85650e9231a09 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -24,7 +24,7 @@ pub(crate) fn expand_deriving_partial_eq( // The `StructuralPartialEq` impl must have the *same* bounds as the `PartialEq` impl, // or it will apply in situations where it should not, such as in the bug // . - additional_bounds: smallvec![ty::Ty::Path(path_std!(cmp::PartialEq))], + additional_bounds: smallvec![path_std!(cmp::PartialEq)], // We really don't support unions, but that's already checked by the impl generated below; // a second check here would lead to redundant error messages. supports_unions: true, From 0dde9186493b43dc2bc4e87c03d5030f735c8697 Mon Sep 17 00:00:00 2001 From: aerooneqq Date: Mon, 21 Sep 2026 14:48:10 +0300 Subject: [PATCH 0535/1309] Deterministic def path hash map encoding --- Cargo.lock | 1 + compiler/rustc_hir_id/src/definitions.rs | 68 ++++++++++++++++++- compiler/rustc_interface/src/passes.rs | 2 + compiler/rustc_metadata/Cargo.toml | 1 + .../src/rmeta/def_path_hash_map.rs | 33 ++++++--- compiler/rustc_middle/src/ty/context.rs | 4 +- 6 files changed, 94 insertions(+), 15 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e57835c9cfef..44c2db1e941a5 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4415,6 +4415,7 @@ dependencies = [ "rustc_expand", "rustc_feature", "rustc_fs_util", + "rustc_hashes", "rustc_hir", "rustc_hir_pretty", "rustc_index", diff --git a/compiler/rustc_hir_id/src/definitions.rs b/compiler/rustc_hir_id/src/definitions.rs index 50f7a15b19adf..a06e8336db2e4 100644 --- a/compiler/rustc_hir_id/src/definitions.rs +++ b/compiler/rustc_hir_id/src/definitions.rs @@ -8,6 +8,7 @@ use std::fmt::{self, Write}; use std::hash::Hash; use rustc_data_structures::fx::FxHashMap; +use rustc_data_structures::sorted_map::SortedMap; use rustc_data_structures::stable_hash::StableHasher; use rustc_hashes::Hash64; use rustc_index::IndexVec; @@ -46,13 +47,68 @@ impl LocalDefIdMap { } } +/// Struct that contains two maps: `det_part` is used at the earlier stages of compilation +/// (see where `commit_end_of_determinism` is called, at the moment of writing +/// it is after prefetch of `hir_crate_items` in `run_required_analysis`), `non_det_part` is used +/// when def ids are allocated non-deterministically (in parallel compiler), +/// i.e., order of serialized pairs may be different. +/// In order to preserve deterministic output of the compiler we need to deterministically encode this map, so we use +/// `SortedMap` to store the mapping between local hashes and def indices, which gives us +/// deterministic iteration when encoding crate metadata. For encoding/decoding details see +/// `compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs`. +#[derive(Debug, Default)] +pub struct DefPathToIndexMap { + pub det_part: DefPathHashMap, + pub non_det_part: SortedMap, + non_det_mode: bool, +} + +impl DefPathToIndexMap { + #[inline] + pub fn get(&self, hash: &Hash64) -> Option { + match self.det_part.get(hash) { + Some(index) => Some(index), + None => { + if self.non_det_mode { + self.non_det_part.get(hash).copied() + } else { + None + } + } + } + } + + /// This insert function does not behave like regular `insert` of a `HashMap`, + /// as the return value is used only for printing information about existing + /// def index for local hash before panicking. So we can do not actually insert + /// def index into `det_part` when we are in non-deterministic mode. + #[inline] + pub fn insert(&mut self, hash: &Hash64, index: DefIndex) -> Option { + match self.non_det_mode { + false => self.det_part.insert(hash, &index), + true => { + if let Some(existing) = self.det_part.get(hash) { + return Some(existing); + } + + self.non_det_part.insert(*hash, index) + } + } + } + + #[inline] + pub fn switch_to_non_det_mode(&mut self) { + self.non_det_mode = true; + } +} + #[derive(Debug)] pub struct Definitions { stable_crate_id: StableCrateId, def_id_to_key: IndexVec, // We do only store the local hash, as all the definitions are from the current crate. def_path_hashes: IndexVec, - def_path_hash_to_index: DefPathHashMap, + def_path_hash_to_index: DefPathToIndexMap, } /// A unique identifier that we can use to lookup a definition @@ -249,6 +305,12 @@ pub enum DefPathData { } impl Definitions { + /// This function indicates that def ids allocations are non-deterministic after + /// it was called. + pub fn commit_end_of_determinism(&mut self) { + self.def_path_hash_to_index.switch_to_non_det_mode(); + } + #[inline(always)] pub fn def_key(&self, id: LocalDefId) -> DefKey { self.def_id_to_key[id] @@ -323,7 +385,7 @@ impl Definitions { // Check for hash collisions of DefPathHashes. These should be // exceedingly rare. if let Some(existing) = - self.def_path_hash_to_index.insert(&local_hash, &def_id.local_def_index) + self.def_path_hash_to_index.insert(&local_hash, def_id.local_def_index) { let def_path1 = self.def_path(LocalDefId { local_def_index: existing }); let def_path2 = self.def_path(def_id); @@ -415,7 +477,7 @@ impl Definitions { .map(|local_def_index| LocalDefId { local_def_index }) } - pub fn def_path_hash_to_def_index_map(&self) -> &DefPathHashMap { + pub fn def_path_hash_to_def_index_map(&self) -> &DefPathToIndexMap { &self.def_path_hash_to_index } diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs index 2316e80b6e945..8a3a149066e6a 100644 --- a/compiler/rustc_interface/src/passes.rs +++ b/compiler/rustc_interface/src/passes.rs @@ -1099,6 +1099,8 @@ fn run_required_analyses(tcx: TyCtxt<'_>) { // to use `hir_crate_items`. tcx.ensure_done().hir_crate_items(()); + tcx.untracked().definitions.write().commit_end_of_determinism(); + rustc_passes::delegation::check_glob_and_list_delegations_target_expr(tcx); let sess = tcx.sess; diff --git a/compiler/rustc_metadata/Cargo.toml b/compiler/rustc_metadata/Cargo.toml index a2ef8454ed6a6..cbcbe4a2ac551 100644 --- a/compiler/rustc_metadata/Cargo.toml +++ b/compiler/rustc_metadata/Cargo.toml @@ -17,6 +17,7 @@ rustc_errors = { path = "../rustc_errors" } rustc_expand = { path = "../rustc_expand" } rustc_feature = { path = "../rustc_feature" } rustc_fs_util = { path = "../rustc_fs_util" } +rustc_hashes = { path = "../rustc_hashes" } rustc_hir = { path = "../rustc_hir" } rustc_hir_pretty = { path = "../rustc_hir_pretty" } rustc_index = { path = "../rustc_index" } diff --git a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs index 949d7630f6736..1092d56a331f6 100644 --- a/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs +++ b/compiler/rustc_metadata/src/rmeta/def_path_hash_map.rs @@ -1,5 +1,8 @@ use rustc_data_structures::owned_slice::OwnedSlice; -use rustc_hir::def_path_hash_map::{Config as HashMapConfig, DefPathHashMap}; +use rustc_data_structures::sorted_map::SortedMap; +use rustc_hashes::Hash64; +use rustc_hir::def_path_hash_map::Config as HashMapConfig; +use rustc_hir::definitions::DefPathToIndexMap; use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use rustc_span::def_id::{DefIndex, DefPathHash}; @@ -7,8 +10,8 @@ use crate::rmeta::EncodeContext; use crate::rmeta::decoder::BlobDecodeContext; pub(crate) enum DefPathHashMapRef<'tcx> { - OwnedFromMetadata(odht::HashTable), - BorrowedFromTcx(&'tcx DefPathHashMap), + OwnedFromMetadata(odht::HashTable, SortedMap), + BorrowedFromTcx(&'tcx DefPathToIndexMap), } impl DefPathHashMapRef<'_> { @@ -17,8 +20,14 @@ impl DefPathHashMapRef<'_> { &self, def_path_hash: &DefPathHash, ) -> Option { - match *self { - DefPathHashMapRef::OwnedFromMetadata(ref map) => map.get(&def_path_hash.local_hash()), + match self { + DefPathHashMapRef::OwnedFromMetadata(det_map, non_det_map) => { + let hash = &def_path_hash.local_hash(); + match det_map.get(hash) { + Some(index) => Some(index), + None => non_det_map.get(hash).copied(), + } + } DefPathHashMapRef::BorrowedFromTcx(_) => { panic!("DefPathHashMap::BorrowedFromTcx variant only exists for serialization") } @@ -29,12 +38,14 @@ impl DefPathHashMapRef<'_> { impl<'a, 'tcx> Encodable> for DefPathHashMapRef<'tcx> { fn encode(&self, e: &mut EncodeContext<'a, 'tcx>) { match *self { - DefPathHashMapRef::BorrowedFromTcx(def_path_hash_map) => { - let bytes = def_path_hash_map.raw_bytes(); + DefPathHashMapRef::BorrowedFromTcx(map) => { + let bytes = map.det_part.raw_bytes(); e.emit_usize(bytes.len()); e.emit_raw_bytes(bytes); + + map.non_det_part.range(..).encode(e); } - DefPathHashMapRef::OwnedFromMetadata(_) => { + DefPathHashMapRef::OwnedFromMetadata(..) => { panic!("DefPathHashMap::OwnedFromMetadata variant only exists for deserialization") } } @@ -55,6 +66,10 @@ impl<'a> Decodable> for DefPathHashMapRef<'static> { let inner = odht::HashTable::from_raw_bytes(o).unwrap_or_else(|e| { panic!("decode error: {e}"); }); - DefPathHashMapRef::OwnedFromMetadata(inner) + + let elements = Vec::<(Hash64, DefIndex)>::decode(d); + let non_det_map = SortedMap::from_presorted_elements(elements); + + DefPathHashMapRef::OwnedFromMetadata(inner, non_det_map) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 9d0b334b63fbd..d5cfaf570bafe 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1377,9 +1377,7 @@ impl<'tcx> TyCtxt<'tcx> { self.untracked.definitions.freeze() } - pub fn def_path_hash_to_def_index_map( - self, - ) -> &'tcx rustc_hir::def_path_hash_map::DefPathHashMap { + pub fn def_path_hash_to_def_index_map(self) -> &'tcx rustc_hir::definitions::DefPathToIndexMap { // Create a dependency to the crate to be sure we re-execute this when the amount of // definitions change. self.ensure_ok().hir_crate_items(()); From cda3cdf19ebd19f523a7943964d1a3d579b6a60b Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Sat, 19 Sep 2026 19:45:01 +0200 Subject: [PATCH 0536/1309] Use newer `make` version when building GCC --- .../docker/host-x86_64/dist-x86_64-linux/Dockerfile | 4 ++++ src/ci/docker/scripts/build-make.sh | 11 +++++++++++ 2 files changed, 15 insertions(+) create mode 100755 src/ci/docker/scripts/build-make.sh diff --git a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile index 6a5bdf05157bb..911bb168d2489 100644 --- a/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile +++ b/src/ci/docker/host-x86_64/dist-x86_64-linux/Dockerfile @@ -52,6 +52,10 @@ WORKDIR /tmp RUN mkdir /home/user COPY scripts/shared.sh /tmp/ +# GCC needs make >= 4 +COPY scripts/build-make.sh /tmp/ +RUN ./build-make.sh + # Need at least GCC 5.1 to compile LLVM nowadays COPY scripts/build-gcc.sh /tmp/ ENV GCC_VERSION=9.5.0 diff --git a/src/ci/docker/scripts/build-make.sh b/src/ci/docker/scripts/build-make.sh new file mode 100755 index 0000000000000..eb2bcfcf9a377 --- /dev/null +++ b/src/ci/docker/scripts/build-make.sh @@ -0,0 +1,11 @@ +#!/bin/sh +set -ex + +MAKE_VERSION="4.4.1" +curl -f "https://ci-mirrors.rust-lang.org/rustc/gcc/make-${MAKE_VERSION}.tar.gz" | tar xzf - +cd "make-${MAKE_VERSION}" +./configure --prefix=/rustroot +make +make install +cd .. +rm -rf "make-${MAKE_VERSION}" From 32e1cf827d2a7880bb40efbe35e6391d9ba6225d Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 14:33:22 +0200 Subject: [PATCH 0537/1309] remove old solver use of `SolverRelating` --- .../src/coherence/builtin/coerce_shared.rs | 11 ++++++++--- compiler/rustc_type_ir/src/relate/solver_relating.rs | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs index bd7130ee48bc8..77330e4fa3b34 100644 --- a/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs +++ b/compiler/rustc_hir_analysis/src/coherence/builtin/coerce_shared.rs @@ -3,9 +3,8 @@ use rustc_hir as hir; use rustc_hir::ItemKind; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::{DefId, LocalDefId}; -use rustc_infer::infer::{InferCtxt, TyCtxtInferExt}; +use rustc_infer::infer::{DefineOpaqueTypes, InferCtxt, TyCtxtInferExt}; use rustc_infer::traits::{Obligation, TraitErrors}; -use rustc_middle::ty::relate::solver_relating::RelateExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, TypingMode, Unnormalized}; use rustc_span::Span; use rustc_trait_selection::error_reporting::InferCtxtErrorExt; @@ -760,6 +759,9 @@ enum FieldRelation { // instantiating a field can expose projections. Each candidate relation uses a // fresh inference context, so failed checks cannot affect the next one; this // intentionally normalizes the fields for each check. +// +// FIXME(field_projections): This function should take `Unnormalized>` for +// `source_ty` and `target_ty`. fn field_tys_satisfy_relation_after_normalization_and_resolution<'tcx>( tcx: TyCtxt<'tcx>, impl_did: LocalDefId, @@ -785,7 +787,10 @@ fn field_tys_satisfy_relation_after_normalization_and_resolution<'tcx>( match relation { FieldRelation::Equal => { - if infcx.relate(param_env, source_ty, ty::Variance::Invariant, target_ty, span).is_err() + if infcx + .at(&cause, param_env) + .relate(DefineOpaqueTypes::Yes, source_ty, ty::Variance::Invariant, target_ty) + .is_err() { return false; } diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 1e8ff77e4d395..96a792edd2f9d 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -84,6 +84,7 @@ where param_env: I::ParamEnv, span: I::Span, ) -> Self { + debug_assert!(infcx.next_trait_solver()); SolverRelating { infcx, span, From 37fd151fa97963971aa459c93aa03f642be53271 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 10:35:54 +0000 Subject: [PATCH 0538/1309] use `ast::Path` everywhere --- .../src/deriving/clone.rs | 6 +-- .../src/deriving/const_param_ty.rs | 4 +- .../rustc_builtin_macros/src/deriving/copy.rs | 2 +- .../src/deriving/debug.rs | 6 +-- .../src/deriving/default.rs | 2 +- .../rustc_builtin_macros/src/deriving/eq.rs | 2 +- .../rustc_builtin_macros/src/deriving/from.rs | 4 +- .../src/deriving/generic/mod.rs | 26 ++++++----- .../src/deriving/generic/ty.rs | 43 +++++++------------ .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../rustc_builtin_macros/src/deriving/mod.rs | 6 +-- .../rustc_builtin_macros/src/deriving/ord.rs | 4 +- .../src/deriving/partial_eq.rs | 6 +-- .../src/deriving/partial_ord.rs | 6 +-- 14 files changed, 52 insertions(+), 67 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index bfdd847d706cd..441dd008dd3cd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -50,7 +50,7 @@ pub(crate) fn expand_deriving_clone( } } ItemKind::Union(..) => { - bounds = smallvec![path_std!(marker::Copy)]; + bounds = smallvec![path_std!(cx, span, marker::Copy)]; is_simple = true; substructure = combine_substructure(|c, s, sub| cs_clone_simple(c, s, sub, true)); } @@ -62,7 +62,7 @@ pub(crate) fn expand_deriving_clone( if is_simple { let trivial_def = TraitDef { span, - path: path_std!(clone::TrivialClone), + path: path_std!(cx, span, clone::TrivialClone), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: bounds.clone(), @@ -81,7 +81,7 @@ pub(crate) fn expand_deriving_clone( let trait_def = TraitDef { span, - path: path_std!(clone::Clone), + path: path_std!(cx, span, clone::Clone), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: bounds, diff --git a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs index 91755dfb4c933..69041a60027d3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/const_param_ty.rs @@ -14,10 +14,10 @@ pub(crate) fn expand_deriving_const_param_ty( ) { let trait_def = TraitDef { span, - path: path_std!(marker::ConstParamTy_), + path: path_std!(cx, span, marker::ConstParamTy_), skip_path_as_bound: false, needs_copy_as_bound_if_packed: false, - additional_bounds: smallvec![path_std!(cmp::Eq)], + additional_bounds: smallvec![path_std!(cx, span, cmp::Eq)], supports_unions: false, methods: SmallVec::new(), associated_types: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/copy.rs b/compiler/rustc_builtin_macros/src/deriving/copy.rs index bae4bd98df465..5badeb7e1877e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/copy.rs +++ b/compiler/rustc_builtin_macros/src/deriving/copy.rs @@ -14,7 +14,7 @@ pub(crate) fn expand_deriving_copy( ) { let trait_def = TraitDef { span, - path: path_std!(marker::Copy), + path: path_std!(cx, span, marker::Copy), skip_path_as_bound: false, needs_copy_as_bound_if_packed: false, additional_bounds: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index e694502d607e8..900b01c2abf9a 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -16,11 +16,11 @@ pub(crate) fn expand_deriving_debug( is_const: bool, ) { // &mut ::std::fmt::Formatter - let fmtr = Ref(Box::new(Path(path_std!(fmt::Formatter))), ast::Mutability::Mut); + let fmtr = Ref(Box::new(Path(path_std!(cx, span, fmt::Formatter))), ast::Mutability::Mut); let trait_def = TraitDef { span, - path: path_std!(fmt::Debug), + path: path_std!(cx, span, fmt::Debug), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: SmallVec::new(), @@ -30,7 +30,7 @@ pub(crate) fn expand_deriving_debug( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(fmtr, sym::character('f'))], - ret_ty: Path(path_std!(fmt::Result)), + ret_ty: Path(path_std!(cx, span, fmt::Result)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index f9f9af4e9f012..94d97271f6de3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -22,7 +22,7 @@ pub(crate) fn expand_deriving_default( let trait_def = TraitDef { span, - path: Path::new(vec![kw::Default, sym::Default]), + path: new_path(cx, span, &[kw::Default, sym::Default], &[]), skip_path_as_bound: has_a_default_variant(item), needs_copy_as_bound_if_packed: false, additional_bounds: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index eaf9298fc10c7..cc18aa342ffdd 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -19,7 +19,7 @@ pub(crate) fn expand_deriving_eq( let trait_def = TraitDef { span, - path: path_std!(cmp::Eq), + path: path_std!(cx, span, cmp::Eq), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 83a65ed19fbc7..6d3f23529f41d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -5,7 +5,7 @@ use rustc_expand::base::{DummyResult, ExtCtxt}; use rustc_span::{Ident, Span, kw, sym}; use thin_vec::thin_vec; -use crate::deriving::generic::ty::{Path, Ty}; +use crate::deriving::generic::ty::*; use crate::deriving::generic::*; use crate::deriving::pathvec; use crate::diagnostics; @@ -52,7 +52,7 @@ pub(crate) fn expand_deriving_from( Err(guar) => cx.ty(span, ast::TyKind::Err(guar)), }); - let path = Path::new_(pathvec!(convert::From), vec![Box::new(from_type.clone())]); + let path = new_path(cx, span, pathvec!(convert::From), &[Box::new(from_type.clone())]); // Generate code like this: // diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 67f0128b32b49..4fb505ba41a38 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -191,7 +191,7 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, respan, sym}; pub(crate) use smallvec::{SmallVec, smallvec}; use thin_vec::{ThinVec, thin_vec}; -use ty::{Path, Ref, Self_, Ty}; +use ty::{Ref, Self_, Ty}; use crate::{deriving, diagnostics}; @@ -202,7 +202,7 @@ pub(crate) struct TraitDef<'a> { pub span: Span, /// Path of the trait, including any type parameters - pub path: Path, + pub path: ast::Path, /// Whether to skip adding the current trait as a bound to the type parameters of the type. pub skip_path_as_bound: bool, @@ -212,7 +212,7 @@ pub(crate) struct TraitDef<'a> { /// Additional bounds required of any type parameters of the type, /// other than the current trait - pub additional_bounds: SmallVec<[Path; 1]>, + pub additional_bounds: SmallVec<[ast::Path; 1]>, /// Can this trait be derived for unions? pub supports_unions: bool, @@ -571,8 +571,6 @@ impl<'a> TraitDef<'a> { methods: impl Iterator>, is_packed: bool, ) -> Box { - let trait_path = self.path.to_path(cx, self.span); - // Transform associated types from `deriving::ty::Ty` into `ast::AssocItem` let associated_types = self.associated_types.iter().map(|&(ident, ref type_def)| { Box::new(ast::AssocItem { @@ -613,11 +611,11 @@ impl<'a> TraitDef<'a> { let bounds: ThinVec<_> = self .additional_bounds .iter() - .map(|p| cx.trait_bound(p.to_path(cx, span), self.is_const)) + .map(|p| cx.trait_bound(ast::Path { span, ..p.clone() }, self.is_const)) .chain( // Add a bound for the current trait. self.skip_path_as_bound.not().then(|| { - let mut trait_path = trait_path.clone(); + let mut trait_path = self.path.clone(); trait_path.span = span; cx.trait_bound(trait_path, self.is_const) }), @@ -625,8 +623,8 @@ impl<'a> TraitDef<'a> { .chain({ // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { - let p = deriving::path_std!(marker::Copy); - Some(cx.trait_bound(p.to_path(cx, span), self.is_const)) + let p = deriving::path_std!(cx, span, marker::Copy); + Some(cx.trait_bound(p, self.is_const)) } else { None } @@ -692,18 +690,18 @@ impl<'a> TraitDef<'a> { let mut bounds: ThinVec<_> = self .additional_bounds .iter() - .map(|p| cx.trait_bound(p.to_path(cx, self.span), self.is_const)) + .map(|p| cx.trait_bound(p.clone(), self.is_const)) .collect(); // Require the current trait. if !self.skip_path_as_bound { - bounds.push(cx.trait_bound(trait_path.clone(), self.is_const)); + bounds.push(cx.trait_bound(self.path.clone(), self.is_const)); } // Add a `Copy` bound if required. if is_packed && self.needs_copy_as_bound_if_packed { - let p = deriving::path_std!(marker::Copy); - bounds.push(cx.trait_bound(p.to_path(cx, self.span), self.is_const)); + let p = deriving::path_std!(cx, self.span, marker::Copy); + bounds.push(cx.trait_bound(p, self.is_const)); } if !bounds.is_empty() { @@ -730,7 +728,7 @@ impl<'a> TraitDef<'a> { let trait_generics = Generics { params, where_clause, span }; // Create the reference to the trait. - let trait_ref = cx.trait_ref(trait_path); + let trait_ref = cx.trait_ref(self.path.clone()); let self_params: Vec<_> = generics .params diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index b9ebb2963ae46..13df8b6d9f0b2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -6,34 +6,21 @@ use std::iter::once; pub(crate) use Ty::*; use rustc_ast::{self as ast, GenericArg}; use rustc_expand::base::ExtCtxt; -use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw}; +use rustc_span::{Ident, Span, Symbol, kw}; use thin_vec::ThinVec; -/// A path, e.g., `::std::option::Option::` (global). Has support -/// for type parameters. -#[derive(Clone)] -pub(crate) struct Path { - path: Vec, - params: Vec>, -} - -impl Path { - pub(crate) fn new(path: Vec) -> Path { - Path::new_(path, Vec::new()) - } - pub(crate) fn new_(path: Vec, params: Vec>) -> Path { - Path { path, params } - } - - pub(crate) fn to_path(&self, cx: &ExtCtxt<'_>, span: Span) -> ast::Path { - let idents = self.path.iter().map(|s| Ident::new(*s, span)); - let tys = self.params.iter().map(|t| t.to_ty(cx, span)); - let params = tys.map(GenericArg::Type).collect(); - - let def_site = cx.with_def_site_ctxt(DUMMY_SP); - let idents = once(Ident::new(kw::DollarCrate, def_site)).chain(idents).collect(); - cx.path_all(span, false, idents, params) - } +pub(crate) fn new_path( + cx: &ExtCtxt<'_>, + span: Span, + path: &[Symbol], + params: &[Box], +) -> ast::Path { + let idents = path.iter().map(|s| Ident::new(*s, span)); + let tys = params.iter().map(|t| t.to_ty(cx, span)); + let params = tys.map(GenericArg::Type).collect(); + + let idents = once(Ident::new(kw::DollarCrate, span)).chain(idents).collect(); + cx.path_all(span, false, idents, params) } /// A type. Supports pointers, Self, literals, unit or an arbitrary AST path. @@ -44,7 +31,7 @@ pub(crate) enum Ty { Ref(Box, ast::Mutability), /// `mod::mod::Type<[lifetime], [Params...]>`, including a plain type /// parameter, and things like `i32` - Path(Path), + Path(ast::Path), /// For () return types. Unit, /// An arbitrary type. @@ -62,7 +49,7 @@ impl Ty { let raw_ty = ty.to_ty(cx, span); cx.ty_ref(span, raw_ty, None, *mutbl) } - Path(p) => cx.ty_path(p.to_path(cx, span)), + Path(p) => cx.ty_path(p.clone()), Self_ => cx.ty_path(cx.path_ident(span, Ident::new(kw::SelfUpper, span))), Unit => cx.ty(span, ast::TyKind::Tup(ThinVec::new())), AstTy(ty) => ty.clone(), diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 8593a17c0571a..8f53e45a408d7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -14,7 +14,7 @@ pub(crate) fn expand_deriving_hash( push: &mut dyn FnMut(Box), is_const: bool, ) { - let path = path_std!(hash::Hash); + let path = path_std!(cx, span, hash::Hash); let typaram = sym::__H; diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs index a1b1d56664f22..66d4a61b97fdc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs @@ -7,11 +7,11 @@ use rustc_span::{Span, Symbol, sym}; use thin_vec::{ThinVec, thin_vec}; macro pathvec($($rest:ident)::+) {{ - vec![ $( sym::$rest ),+ ] + &[ $( sym::$rest ),+ ] }} -macro path_std($($x:tt)*) { - generic::ty::Path::new( pathvec!( $($x)* ) ) +macro path_std($cx: expr, $span: expr, $($x:tt)*) { + generic::ty::new_path($cx, $span, pathvec!( $($x)* ), &[] ) } pub(crate) mod clone; diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 663e9b86a9ebe..376345f6f6bc7 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -16,7 +16,7 @@ pub(crate) fn expand_deriving_ord( ) { let trait_def = TraitDef { span, - path: path_std!(cmp::Ord), + path: path_std!(cx, span, cmp::Ord), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: SmallVec::new(), @@ -26,7 +26,7 @@ pub(crate) fn expand_deriving_ord( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: Path(path_std!(cmp::Ordering)), + ret_ty: Path(path_std!(cx, span, cmp::Ordering)), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(cs_cmp), diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 85650e9231a09..9beb8486e8f4e 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -18,13 +18,13 @@ pub(crate) fn expand_deriving_partial_eq( ) { let structural_trait_def = TraitDef { span, - path: path_std!(marker::StructuralPartialEq), + path: path_std!(cx, span, marker::StructuralPartialEq), skip_path_as_bound: true, // crucial! needs_copy_as_bound_if_packed: false, // The `StructuralPartialEq` impl must have the *same* bounds as the `PartialEq` impl, // or it will apply in situations where it should not, such as in the bug // . - additional_bounds: smallvec![path_std!(cmp::PartialEq)], + additional_bounds: smallvec![path_std!(cx, span, cmp::PartialEq)], // We really don't support unions, but that's already checked by the impl generated below; // a second check here would lead to redundant error messages. supports_unions: true, @@ -51,7 +51,7 @@ pub(crate) fn expand_deriving_partial_eq( let trait_def = TraitDef { span, - path: path_std!(cmp::PartialEq), + path: path_std!(cx, span, cmp::PartialEq), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: SmallVec::new(), diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 2023287af5110..29aa6d54ab165 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -14,8 +14,8 @@ pub(crate) fn expand_deriving_partial_ord( push: &mut dyn FnMut(Box), is_const: bool, ) { - let ordering_ty = Path(path_std!(cmp::Ordering)); - let ret_ty = Path(Path::new_(pathvec!(option::Option), vec![Box::new(ordering_ty)])); + let ordering_ty = Path(path_std!(cx, span, cmp::Ordering)); + let ret_ty = Path(new_path(cx, span, pathvec!(option::Option), &[Box::new(ordering_ty)])); // Order in which to perform matching let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { @@ -81,7 +81,7 @@ pub(crate) fn expand_deriving_partial_ord( let trait_def = TraitDef { span, - path: path_std!(cmp::PartialOrd), + path: path_std!(cx, span, cmp::PartialOrd), skip_path_as_bound: false, needs_copy_as_bound_if_packed: true, additional_bounds: smallvec![], From 82a440525396f811c1d40de8be1f9d9a10ead87e Mon Sep 17 00:00:00 2001 From: cyrgani Date: Fri, 18 Sep 2026 09:43:56 +0000 Subject: [PATCH 0539/1309] convert `other_selflike_exprs` from `Vec` to `Option` --- .../src/deriving/generic/mod.rs | 16 +++++++++------- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../rustc_builtin_macros/src/deriving/ord.rs | 7 +++---- .../src/deriving/partial_eq.rs | 5 ++--- .../src/deriving/partial_ord.rs | 7 +++---- 5 files changed, 18 insertions(+), 19 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 4fb505ba41a38..1138f52c4abf6 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -287,9 +287,9 @@ pub(crate) struct FieldInfo { /// The expression corresponding to this field of `self` /// (specifically, a reference to it). pub self_expr: Box, - /// The expressions corresponding to references to this field in - /// the other selflike arguments. - pub other_selflike_exprs: Vec>, + /// The expression corresponding to a reference to this field in + /// the other selflike argument. + pub other_selflike_expr: Option>, pub maybe_scalar: bool, } @@ -1162,9 +1162,11 @@ impl<'a> MethodDef<'a> { discr_idents.clone().map(|ident| cx.expr_addr_of(span, cx.expr_ident(span, ident))); let self_expr = discr_exprs.next().unwrap(); - let other_selflike_exprs = discr_exprs.collect(); + let other_selflike_expr = discr_exprs.next(); + debug_assert!(discr_exprs.next().is_none()); + let discr_field = - FieldInfo { span, name: None, self_expr, other_selflike_exprs, maybe_scalar: true }; + FieldInfo { span, name: None, self_expr, other_selflike_expr, maybe_scalar: true }; let discr_let_stmts: ThinVec<_> = iter::zip(discr_idents, &selflike_args) .map(|(ident, selflike_arg)| { @@ -1405,12 +1407,12 @@ impl<'a> TraitDef<'a> { let sp = struct_field.span.with_ctxt(self.span.ctxt()); let mut exprs: Vec<_> = mk_exprs(i, struct_field, sp); let self_expr = exprs.remove(0); - let other_selflike_exprs = exprs; + debug_assert!(exprs.len() <= 1); FieldInfo { span: sp.with_ctxt(self.span.ctxt()), name: struct_field.ident, self_expr, - other_selflike_exprs, + other_selflike_expr: exprs.pop(), maybe_scalar: struct_field.ty.peel_refs().kind.maybe_scalar(), } }) diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 8f53e45a408d7..7a844c74d729b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -75,7 +75,7 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_ (stmts, None) } EnumDiscr(discr_field, match_expr) => { - assert!(discr_field.other_selflike_exprs.is_empty()); + assert!(discr_field.other_selflike_expr.is_none()); let stmts = thin_vec![call_hash(discr_field.span, discr_field.self_expr)]; (stmts, match_expr) } diff --git a/compiler/rustc_builtin_macros/src/deriving/ord.rs b/compiler/rustc_builtin_macros/src/deriving/ord.rs index 376345f6f6bc7..426fa41a3b6d4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/ord.rs @@ -57,10 +57,9 @@ pub(crate) fn cs_cmp(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> span, substr, |field| { - let [other_expr] = &field.other_selflike_exprs[..] else { - cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(Ord)`"); - }; - let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; + let other_expr = + field.other_selflike_expr.expect("not exactly 2 arguments in `derive(Ord)`"); + let args = thin_vec![field.self_expr, other_expr]; cx.expr_call_global(field.span, cmp_path.clone(), args) }, |span, expr1, expr2| { diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 9beb8486e8f4e..577d3932a1fd2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -172,9 +172,8 @@ fn get_substructure_equality_expr( /// Panics if there are not exactly two arguments to compare (should be `self` /// and `other`). fn get_field_equality_expr(cx: &ExtCtxt<'_>, field: &FieldInfo) -> Box { - let [rhs] = &field.other_selflike_exprs[..] else { - cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialEq)`"); - }; + let rhs = + field.other_selflike_expr.as_ref().expect("not exactly 2 arguments in `derive(PartialEq)`"); cx.expr_binary( field.span, diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index 29aa6d54ab165..fbdae4acfd833 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -128,10 +128,9 @@ fn cs_partial_cmp( span, substr, |field| { - let [other_expr] = &field.other_selflike_exprs[..] else { - cx.dcx().span_bug(field.span, "not exactly 2 arguments in `derive(PartialOrd)`"); - }; - let args = thin_vec![field.self_expr.clone(), other_expr.clone()]; + let other_expr = + field.other_selflike_expr.expect("not exactly 2 arguments in `derive(PartialOrd)`"); + let args = thin_vec![field.self_expr, other_expr]; cx.expr_call_global(field.span, partial_cmp_path.clone(), args) }, |span, mut expr1, expr2| { From 17bf5fe9f19cfd01a3334cc546bb80accfa8644a Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sat, 19 Sep 2026 22:01:25 +0000 Subject: [PATCH 0540/1309] small tweaks --- .../rustc_builtin_macros/src/deriving/debug.rs | 18 +++++++----------- .../src/deriving/default.rs | 4 +--- .../rustc_builtin_macros/src/deriving/from.rs | 2 +- .../src/deriving/generic/mod.rs | 6 +++--- .../src/deriving/generic/ty.rs | 7 +------ .../rustc_builtin_macros/src/deriving/hash.rs | 10 +++++----- .../src/deriving/partial_eq.rs | 2 +- .../src/deriving/partial_ord.rs | 2 +- 8 files changed, 20 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 900b01c2abf9a..6219f2aa0f1d3 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -45,9 +45,6 @@ pub(crate) fn expand_deriving_debug( } fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { - // We want to make sure we have the ctxt set so that we can use unstable methods - let span = cx.with_def_site_ctxt(span); - let fmt_detail = cx.sess.opts.unstable_opts.fmt_debug; if fmt_detail == FmtDebug::None { return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new()))); @@ -85,13 +82,14 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> // The number of fields that can be handled without an array. const CUTOFF: usize = 5; - let expr_for_field = |field: &FieldInfo, index: usize| -> Box { - if index < fields.len() - 1 { - field.self_expr.clone() + let len = fields.len(); + let expr_for_field = |field: FieldInfo, index: usize| -> Box { + if index < len - 1 { + field.self_expr } else { // Unsized types need an extra indirection, but only the last field // may be unsized. - cx.expr_addr_of(field.span, field.self_expr.clone()) + cx.expr_addr_of(field.span, field.self_expr) } }; @@ -111,8 +109,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> let mut args = ThinVec::with_capacity(2 + fields.len() * args_per_field); args.extend([fmt, name]); - for i in 0..fields.len() { - let field = &fields[i]; + for (i, field) in fields.into_iter().enumerate() { if is_struct { let name = cx.expr_str(field.span, field.name.unwrap().name); args.push(name); @@ -128,8 +125,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> let mut name_exprs = ThinVec::with_capacity(fields.len()); let mut value_exprs = ThinVec::with_capacity(fields.len()); - for i in 0..fields.len() { - let field = &fields[i]; + for (i, field) in fields.into_iter().enumerate() { if is_struct { name_exprs.push(cx.expr_str(field.span, field.name.unwrap().name)); } diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 94d97271f6de3..d35605178f806 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -83,9 +83,7 @@ fn default_struct_substructure( .iter() .map(|field| { let span = field.span.with_ctxt(trait_span.ctxt()); - let value = if let Some(extras) = &field.extras - && let Some(default_val) = &extras.default - { + let value = if let Some(default_val) = field.default_value() { // We use the field default const expression. cx.expr( default_val.value.span, diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index 6d3f23529f41d..fa4caee250c3d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -52,7 +52,7 @@ pub(crate) fn expand_deriving_from( Err(guar) => cx.ty(span, ast::TyKind::Err(guar)), }); - let path = new_path(cx, span, pathvec!(convert::From), &[Box::new(from_type.clone())]); + let path = new_path(cx, span, pathvec!(convert::From), &[from_type.clone()]); // Generate code like this: // diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 1138f52c4abf6..5225f5be01cd9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -1404,12 +1404,12 @@ impl<'a> TraitDef<'a> { .map(|(i, struct_field)| { // For this field, get an expr for each selflike_arg. E.g. for // `PartialEq::eq`, one for each of `&self` and `other`. - let sp = struct_field.span.with_ctxt(self.span.ctxt()); - let mut exprs: Vec<_> = mk_exprs(i, struct_field, sp); + let span = struct_field.span.with_ctxt(self.span.ctxt()); + let mut exprs: Vec<_> = mk_exprs(i, struct_field, span); let self_expr = exprs.remove(0); debug_assert!(exprs.len() <= 1); FieldInfo { - span: sp.with_ctxt(self.span.ctxt()), + span, name: struct_field.ident, self_expr, other_selflike_expr: exprs.pop(), diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs index 13df8b6d9f0b2..8f2de7a46fa18 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs @@ -9,12 +9,7 @@ use rustc_expand::base::ExtCtxt; use rustc_span::{Ident, Span, Symbol, kw}; use thin_vec::ThinVec; -pub(crate) fn new_path( - cx: &ExtCtxt<'_>, - span: Span, - path: &[Symbol], - params: &[Box], -) -> ast::Path { +pub(crate) fn new_path(cx: &ExtCtxt<'_>, span: Span, path: &[Symbol], params: &[Ty]) -> ast::Path { let idents = path.iter().map(|s| Ident::new(*s, span)); let tys = params.iter().map(|t| t.to_ty(cx, span)); let params = tys.map(GenericArg::Type).collect(); diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 7a844c74d729b..037be93f349fa 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -16,13 +16,13 @@ pub(crate) fn expand_deriving_hash( ) { let path = path_std!(cx, span, hash::Hash); - let typaram = sym::__H; + let typaram = Ident::new(sym::__H, span); - let arg = cx.ty_path(cx.path_ident(span, Ident::new(typaram, span))); + let arg = cx.path_ident(span, typaram); let param = { - let path = cx.path_all(span, false, cx.std_path(&[sym::hash, sym::Hasher]), Vec::new()); - cx.typaram(span, Ident::new(typaram, span), thin_vec![cx.trait_bound(path, false)], None) + let path = path_std!(cx, span, hash::Hasher); + cx.typaram(span, typaram, thin_vec![cx.trait_bound(path, false)], None) }; let generics = ast::Generics { @@ -42,7 +42,7 @@ pub(crate) fn expand_deriving_hash( name: sym::hash, generics, explicit_self: true, - nonself_args: smallvec![(Ref(Box::new(AstTy(arg)), Mutability::Mut), sym::state)], + nonself_args: smallvec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)], ret_ty: Unit, attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 577d3932a1fd2..715ecbfd24719 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -43,7 +43,7 @@ pub(crate) fn expand_deriving_partial_eq( generics: cx.empty_generics(span), explicit_self: true, nonself_args: smallvec![(self_ref(), sym::other)], - ret_ty: AstTy(cx.ty_path(cx.path_ident(span, Ident::new(sym::bool, span)))), + ret_ty: Path(cx.path_ident(span, Ident::new(sym::bool, span))), attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Unify, combine_substructure: combine_substructure(get_substructure_equality_expr), diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs index fbdae4acfd833..e176152c507c9 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_ord.rs @@ -15,7 +15,7 @@ pub(crate) fn expand_deriving_partial_ord( is_const: bool, ) { let ordering_ty = Path(path_std!(cx, span, cmp::Ordering)); - let ret_ty = Path(new_path(cx, span, pathvec!(option::Option), &[Box::new(ordering_ty)])); + let ret_ty = Path(new_path(cx, span, pathvec!(option::Option), &[ordering_ty])); // Order in which to perform matching let discr_then_data = if let ItemKind::Enum(_, _, def) = &item.kind { From 10fc55a1b18a4dae6a0753668e46eb435e46d370 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 20 Sep 2026 11:12:30 +0000 Subject: [PATCH 0541/1309] remove `nonselflike_args` --- .../src/deriving/debug.rs | 8 ++- .../src/deriving/generic/mod.rs | 68 +++---------------- .../rustc_builtin_macros/src/deriving/hash.rs | 9 +-- 3 files changed, 21 insertions(+), 64 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index 6219f2aa0f1d3..b4e98db4bd45d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -44,6 +44,10 @@ pub(crate) fn expand_deriving_debug( trait_def.expand(cx, item, push) } +fn formatter_ident(cx: &ExtCtxt<'_>, span: Span) -> Box { + cx.expr_ident(span, Ident::new(sym::character('f'), span)) +} + fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { let fmt_detail = cx.sess.opts.unstable_opts.fmt_debug; if fmt_detail == FmtDebug::None { @@ -58,7 +62,7 @@ fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> }; let name = cx.expr_str(span, ident.name); - let fmt = substr.nonselflike_args[0].clone(); + let fmt = formatter_ident(cx, span); // Fieldless enums have been special-cased earlier if fmt_detail == FmtDebug::Shallow { @@ -214,7 +218,7 @@ fn show_fieldless_enum( def: &EnumDef, substr: Substructure<'_>, ) -> BlockOrExpr { - let fmt = substr.nonselflike_args[0].clone(); + let fmt = formatter_ident(cx, span); let arms = def .variants .iter() diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 5225f5be01cd9..92433916fbff4 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -272,9 +272,6 @@ pub(crate) enum FieldlessVariantsStrategy { pub(crate) struct Substructure<'a> { /// ident of self pub type_ident: Ident, - /// Verbatim access to any non-selflike arguments, i.e. arguments that - /// don't have type `&Self`. - pub nonselflike_args: &'a [Box], pub fields: SubstructureFields<'a>, } @@ -824,17 +821,10 @@ impl<'a> TraitDef<'a> { let field_tys = struct_def.fields().iter().map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args, nonselflike_args } = - method_def.extract_arg_details(cx, self); + let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method( - cx, - self, - type_ident, - &nonselflike_args, - StaticStruct(struct_def), - ) + method_def.call_substructure_method(cx, self, type_ident, StaticStruct(struct_def)) } else { method_def.expand_struct_method_body( cx, @@ -842,7 +832,6 @@ impl<'a> TraitDef<'a> { struct_def, type_ident, &selflike_args, - &nonselflike_args, is_packed, ) }; @@ -868,26 +857,12 @@ impl<'a> TraitDef<'a> { .map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args, nonselflike_args } = - method_def.extract_arg_details(cx, self); + let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method( - cx, - self, - type_ident, - &nonselflike_args, - StaticEnum(enum_def), - ) + method_def.call_substructure_method(cx, self, type_ident, StaticEnum(enum_def)) } else { - method_def.expand_enum_method_body( - cx, - self, - enum_def, - type_ident, - selflike_args, - &nonselflike_args, - ) + method_def.expand_enum_method_body(cx, self, enum_def, type_ident, selflike_args) }; method_def.create_method(cx, self, body) @@ -902,8 +877,6 @@ struct ArgDetails { /// Expressions for `&self` (if present) and also any other /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). selflike_args: ThinVec>, - /// Expressions for all the remaining args. - nonselflike_args: Vec>, } impl<'a> MethodDef<'a> { @@ -912,11 +885,10 @@ impl<'a> MethodDef<'a> { cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>, type_ident: Ident, - nonselflike_args: &[Box], fields: SubstructureFields<'_>, ) -> BlockOrExpr { let span = trait_.span; - let substructure = Substructure { type_ident, nonselflike_args, fields }; + let substructure = Substructure { type_ident, fields }; let f: &CombineSubstructureFunc<'_> = &self.combine_substructure; f(cx, span, substructure) } @@ -927,7 +899,6 @@ impl<'a> MethodDef<'a> { fn extract_arg_details(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ArgDetails { let mut selflike_args = ThinVec::new(); - let mut nonselflike_args = Vec::new(); let span = trait_.span; if self.explicit_self { @@ -943,11 +914,11 @@ impl<'a> MethodDef<'a> { // Selflike (`&Self`) arguments only occur in non-static methods. Ref(Self_, _) if self.explicit_self => selflike_args.push(arg_expr), Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"), - _ => nonselflike_args.push(arg_expr), + _ => (), } } - ArgDetails { selflike_args, nonselflike_args } + ArgDetails { selflike_args } } fn create_method( @@ -1058,20 +1029,13 @@ impl<'a> MethodDef<'a> { struct_def: &'b VariantData, type_ident: Ident, selflike_args: &[Box], - nonselflike_args: &[Box], is_packed: bool, ) -> BlockOrExpr { assert!(selflike_args.len() == 1 || selflike_args.len() == 2); let selflike_fields = trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, is_packed); - self.call_substructure_method( - cx, - trait_, - type_ident, - nonselflike_args, - Struct(struct_def, selflike_fields), - ) + self.call_substructure_method(cx, trait_, type_ident, Struct(struct_def, selflike_fields)) } /// ``` @@ -1116,7 +1080,6 @@ impl<'a> MethodDef<'a> { enum_def: &'b EnumDef, type_ident: Ident, mut selflike_args: ThinVec>, - nonselflike_args: &[Box], ) -> BlockOrExpr { assert!( !selflike_args.is_empty(), @@ -1198,7 +1161,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - nonselflike_args, EnumDiscr(discr_field, None), ); discr_let_stmts.append(&mut discr_check.0); @@ -1209,7 +1171,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - nonselflike_args, AllFieldlessEnum(enum_def), ); } @@ -1222,7 +1183,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - nonselflike_args, EnumMatching(variant, Vec::new()), ); } @@ -1264,13 +1224,7 @@ impl<'a> MethodDef<'a> { // Build up code associated with such a case. let substructure = EnumMatching(variant, fields); let arm_expr = self - .call_substructure_method( - cx, - trait_, - type_ident, - nonselflike_args, - substructure, - ) + .call_substructure_method(cx, trait_, type_ident, substructure) .into_expr(cx, span); cx.arm(span, single_pat, arm_expr) @@ -1289,7 +1243,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - nonselflike_args, EnumMatching(v, Vec::new()), ) .into_expr(cx, span), @@ -1335,7 +1288,6 @@ impl<'a> MethodDef<'a> { cx, trait_, type_ident, - nonselflike_args, EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), ); discr_let_stmts.append(&mut discr_check_plus_match.0); diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 037be93f349fa..0530303270239 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -58,13 +58,14 @@ pub(crate) fn expand_deriving_hash( } fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> BlockOrExpr { - let [state_expr] = substr.nonselflike_args else { - cx.dcx().span_bug(trait_span, "incorrect number of arguments in `derive(Hash)`"); - }; let call_hash = |span, expr| { let strs = cx.std_path(&[sym::hash, sym::Hash, sym::hash]); let hash_path = cx.expr_path(cx.path_global(span, strs)); - let expr = cx.expr_call(span, hash_path, thin_vec![expr, state_expr.clone()]); + let expr = cx.expr_call( + span, + hash_path, + thin_vec![expr, cx.expr_ident(span, Ident::new(sym::state, span))], + ); cx.stmt_expr(expr) }; From 2f86c2408a441039abaa39092c70ff7fb1c71b11 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 20 Sep 2026 11:38:30 +0000 Subject: [PATCH 0542/1309] remove `substr.type_ident` --- .../src/deriving/clone.rs | 5 +- .../src/deriving/debug.rs | 22 ++++++-- .../src/deriving/default.rs | 9 ++- .../src/deriving/generic/mod.rs | 38 ++++--------- tests/ui/derives/deriving-all-codegen.stdout | 56 ++++++++----------- tests/ui/stats/macro-stats.stderr | 4 +- 6 files changed, 57 insertions(+), 77 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index 441dd008dd3cd..a68be4fa5f623 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -171,17 +171,18 @@ fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> Blo cx.expr_call_global(field.span, fn_path.clone(), args) }; + let self_ident = Ident::new(kw::SelfUpper, trait_span); let ctor_path; let all_fields; let vdata; match substr.fields { Struct(vdata_, af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident]); + ctor_path = cx.path(trait_span, vec![self_ident]); all_fields = af; vdata = vdata_; } EnumMatching(.., variant, af) => { - ctor_path = cx.path(trait_span, vec![substr.type_ident, variant.ident]); + ctor_path = cx.path(trait_span, vec![self_ident, variant.ident]); all_fields = af; vdata = &variant.data; } diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index b4e98db4bd45d..c02e13d9c8e30 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -34,7 +34,12 @@ pub(crate) fn expand_deriving_debug( attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::SpecializeIfAllVariantsFieldless, - combine_substructure: combine_substructure(show_substructure), + combine_substructure: combine_substructure(|cx, span, substr| show_substructure( + cx, + span, + substr, + item.kind.ident().unwrap() + )), }], associated_types: SmallVec::new(), is_const, @@ -48,16 +53,21 @@ fn formatter_ident(cx: &ExtCtxt<'_>, span: Span) -> Box { cx.expr_ident(span, Ident::new(sym::character('f'), span)) } -fn show_substructure(cx: &ExtCtxt<'_>, span: Span, substr: Substructure<'_>) -> BlockOrExpr { +fn show_substructure( + cx: &ExtCtxt<'_>, + span: Span, + substr: Substructure<'_>, + type_ident: Ident, +) -> BlockOrExpr { let fmt_detail = cx.sess.opts.unstable_opts.fmt_debug; if fmt_detail == FmtDebug::None { return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new()))); } let (ident, vdata, fields) = match substr.fields { - Struct(vdata, fields) => (substr.type_ident, vdata, fields), + Struct(vdata, fields) => (type_ident, vdata, fields), EnumMatching(v, fields) => (v.ident, &v.data, fields), - AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, substr), + AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, type_ident), _ => cx.dcx().span_bug(span, "unexpected substructure in `derive(Debug)`"), }; @@ -216,14 +226,14 @@ fn show_fieldless_enum( cx: &ExtCtxt<'_>, span: Span, def: &EnumDef, - substr: Substructure<'_>, + type_ident: Ident, ) -> BlockOrExpr { let fmt = formatter_ident(cx, span); let arms = def .variants .iter() .map(|v| { - let variant_path = cx.path(span, vec![substr.type_ident, v.ident]); + let variant_path = cx.path(span, vec![type_ident, v.ident]); let pat = match &v.data { ast::VariantData::Tuple(fields, _) => { debug_assert!(fields.is_empty()); diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index d35605178f806..8592b8ebf99f2 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -38,7 +38,7 @@ pub(crate) fn expand_deriving_default( combine_substructure: combine_substructure(|cx, trait_span, substr| { match substr.fields { StaticStruct(variant_data) => { - default_struct_substructure(cx, trait_span, substr, variant_data) + default_struct_substructure(cx, trait_span, variant_data) } StaticEnum(enum_def) => { default_enum_substructure(cx, trait_span, enum_def, item.span) @@ -66,17 +66,16 @@ fn default_call(cx: &ExtCtxt<'_>, span: Span) -> Box { fn default_struct_substructure( cx: &ExtCtxt<'_>, trait_span: Span, - substr: Substructure<'_>, variant_data: &VariantData, ) -> BlockOrExpr { let expr = match variant_data { - VariantData::Unit(_) => cx.expr_ident(trait_span, substr.type_ident), + VariantData::Unit(_) => cx.expr_ident(trait_span, Ident::new(kw::SelfUpper, trait_span)), VariantData::Tuple(fields, _) => { let exprs = fields .iter() .map(|field| default_call(cx, field.span.with_ctxt(trait_span.ctxt()))) .collect(); - cx.expr_call_ident(trait_span, substr.type_ident, exprs) + cx.expr_call_ident(trait_span, Ident::new(kw::SelfUpper, trait_span), exprs) } VariantData::Struct { fields, .. } => { let default_fields = fields @@ -96,7 +95,7 @@ fn default_struct_substructure( cx.field_imm(span, field.ident.unwrap(), value) }) .collect(); - cx.expr_struct_ident(trait_span, substr.type_ident, default_fields) + cx.expr_struct_ident(trait_span, Ident::new(kw::SelfUpper, trait_span), default_fields) } }; BlockOrExpr::new_expr(expr) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 92433916fbff4..8d6935f1c0e04 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -270,8 +270,6 @@ pub(crate) enum FieldlessVariantsStrategy { /// All the data about the data structure/method being derived upon. pub(crate) struct Substructure<'a> { - /// ident of self - pub type_ident: Ident, pub fields: SubstructureFields<'a>, } @@ -824,13 +822,12 @@ impl<'a> TraitDef<'a> { let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, type_ident, StaticStruct(struct_def)) + method_def.call_substructure_method(cx, self, StaticStruct(struct_def)) } else { method_def.expand_struct_method_body( cx, self, struct_def, - type_ident, &selflike_args, is_packed, ) @@ -860,7 +857,7 @@ impl<'a> TraitDef<'a> { let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); let body = if from_scratch || method_def.is_static() { - method_def.call_substructure_method(cx, self, type_ident, StaticEnum(enum_def)) + method_def.call_substructure_method(cx, self, StaticEnum(enum_def)) } else { method_def.expand_enum_method_body(cx, self, enum_def, type_ident, selflike_args) }; @@ -884,11 +881,10 @@ impl<'a> MethodDef<'a> { &self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>, - type_ident: Ident, fields: SubstructureFields<'_>, ) -> BlockOrExpr { let span = trait_.span; - let substructure = Substructure { type_ident, fields }; + let substructure = Substructure { fields }; let f: &CombineSubstructureFunc<'_> = &self.combine_substructure; f(cx, span, substructure) } @@ -1027,7 +1023,6 @@ impl<'a> MethodDef<'a> { cx: &ExtCtxt<'_>, trait_: &TraitDef<'b>, struct_def: &'b VariantData, - type_ident: Ident, selflike_args: &[Box], is_packed: bool, ) -> BlockOrExpr { @@ -1035,7 +1030,7 @@ impl<'a> MethodDef<'a> { let selflike_fields = trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, is_packed); - self.call_substructure_method(cx, trait_, type_ident, Struct(struct_def, selflike_fields)) + self.call_substructure_method(cx, trait_, Struct(struct_def, selflike_fields)) } /// ``` @@ -1157,12 +1152,8 @@ impl<'a> MethodDef<'a> { // there are multiple variants, we need just an operation on // the discriminant(s). let (discr_field, mut discr_let_stmts) = get_discr_pieces(); - let mut discr_check = self.call_substructure_method( - cx, - trait_, - type_ident, - EnumDiscr(discr_field, None), - ); + let mut discr_check = + self.call_substructure_method(cx, trait_, EnumDiscr(discr_field, None)); discr_let_stmts.append(&mut discr_check.0); return BlockOrExpr(discr_let_stmts, discr_check.1); } @@ -1170,7 +1161,6 @@ impl<'a> MethodDef<'a> { return self.call_substructure_method( cx, trait_, - type_ident, AllFieldlessEnum(enum_def), ); } @@ -1182,7 +1172,6 @@ impl<'a> MethodDef<'a> { return self.call_substructure_method( cx, trait_, - type_ident, EnumMatching(variant, Vec::new()), ); } @@ -1223,9 +1212,8 @@ impl<'a> MethodDef<'a> { // Self arg, assuming all are instances of VariantK. // Build up code associated with such a case. let substructure = EnumMatching(variant, fields); - let arm_expr = self - .call_substructure_method(cx, trait_, type_ident, substructure) - .into_expr(cx, span); + let arm_expr = + self.call_substructure_method(cx, trait_, substructure).into_expr(cx, span); cx.arm(span, single_pat, arm_expr) }) @@ -1239,13 +1227,8 @@ impl<'a> MethodDef<'a> { // variants. The index and actual variant aren't meaningful in // this case, so just use dummy values. Some( - self.call_substructure_method( - cx, - trait_, - type_ident, - EnumMatching(v, Vec::new()), - ) - .into_expr(cx, span), + self.call_substructure_method(cx, trait_, EnumMatching(v, Vec::new())) + .into_expr(cx, span), ) } _ if variants.len() > 1 && selflike_args.len() > 1 => { @@ -1287,7 +1270,6 @@ impl<'a> MethodDef<'a> { let mut discr_check_plus_match = self.call_substructure_method( cx, trait_, - type_ident, EnumDiscr(discr_field, Some(get_match_expr(selflike_args))), ); discr_let_stmts.append(&mut discr_check_plus_match.0); diff --git a/tests/ui/derives/deriving-all-codegen.stdout b/tests/ui/derives/deriving-all-codegen.stdout index be6bd1a914c65..ddd1158132c7d 100644 --- a/tests/ui/derives/deriving-all-codegen.stdout +++ b/tests/ui/derives/deriving-all-codegen.stdout @@ -46,7 +46,7 @@ impl ::core::fmt::Debug for Empty { #[automatically_derived] impl ::core::default::Default for Empty { #[inline] - fn default() -> Self { Empty } + fn default() -> Self { Self } } #[automatically_derived] impl ::core::hash::Hash for Empty { @@ -109,7 +109,7 @@ impl ::core::fmt::Debug for Point { impl ::core::default::Default for Point { #[inline] fn default() -> Self { - Point { + Self { x: ::core::default::Default::default(), y: ::core::default::Default::default(), } @@ -193,7 +193,7 @@ impl ::core::fmt::Debug for PackedPoint { impl ::core::default::Default for PackedPoint { #[inline] fn default() -> Self { - PackedPoint { + Self { x: ::core::default::Default::default(), y: ::core::default::Default::default(), } @@ -270,9 +270,7 @@ impl ::core::fmt::Debug for TupleSingleField { #[automatically_derived] impl ::core::default::Default for TupleSingleField { #[inline] - fn default() -> Self { - TupleSingleField(::core::default::Default::default()) - } + fn default() -> Self { Self(::core::default::Default::default()) } } #[automatically_derived] impl ::core::convert::From for TupleSingleField { @@ -345,9 +343,7 @@ impl ::core::fmt::Debug for SingleField { #[automatically_derived] impl ::core::default::Default for SingleField { #[inline] - fn default() -> Self { - SingleField { foo: ::core::default::Default::default() } - } + fn default() -> Self { Self { foo: ::core::default::Default::default() } } } #[automatically_derived] impl ::core::convert::From for SingleField { @@ -435,7 +431,7 @@ impl ::core::fmt::Debug for Big { impl ::core::default::Default for Big { #[inline] fn default() -> Self { - Big { + Self { b1: ::core::default::Default::default(), b2: ::core::default::Default::default(), b3: ::core::default::Default::default(), @@ -626,7 +622,7 @@ struct NonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for NonCopy { #[inline] - fn clone(&self) -> Self { NonCopy(::core::clone::Clone::clone(&self.0)) } + fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } } // A packed struct that doesn't impl `Copy`, which means it gets the non-trivial @@ -636,9 +632,7 @@ struct PackedNonCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedNonCopy { #[inline] - fn clone(&self) -> Self { - PackedNonCopy(::core::clone::Clone::clone(&{ self.0 })) - } + fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&{ self.0 })) } } // A struct that impls `Copy` manually, which means it gets the non-trivial @@ -647,9 +641,7 @@ struct ManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for ManualCopy { #[inline] - fn clone(&self) -> Self { - ManualCopy(::core::clone::Clone::clone(&self.0)) - } + fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } } impl Copy for ManualCopy {} @@ -660,9 +652,7 @@ struct PackedManualCopy(u32); #[automatically_derived] impl ::core::clone::Clone for PackedManualCopy { #[inline] - fn clone(&self) -> Self { - PackedManualCopy(::core::clone::Clone::clone(&{ self.0 })) - } + fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&{ self.0 })) } } impl Copy for PackedManualCopy {} @@ -735,7 +725,7 @@ impl ::core::clone::Clone for Generic where T::A: ::core::clone::Clone { #[inline] fn clone(&self) -> Self { - Generic { + Self { t: ::core::clone::Clone::clone(&self.t), ta: ::core::clone::Clone::clone(&self.ta), u: ::core::clone::Clone::clone(&self.u), @@ -761,7 +751,7 @@ impl T::A: ::core::default::Default { #[inline] fn default() -> Self { - Generic { + Self { t: ::core::default::Default::default(), ta: ::core::default::Default::default(), u: ::core::default::Default::default(), @@ -854,7 +844,7 @@ impl Self { - PackedGeneric(::core::clone::Clone::clone(&{ self.0 }), + Self(::core::clone::Clone::clone(&{ self.0 }), ::core::clone::Clone::clone(&{ self.1 }), ::core::clone::Clone::clone(&{ self.2 })) } @@ -881,7 +871,7 @@ impl T::A: ::core::default::Default { #[inline] fn default() -> Self { - PackedGeneric(::core::default::Default::default(), + Self(::core::default::Default::default(), ::core::default::Default::default(), ::core::default::Default::default()) } @@ -1029,7 +1019,7 @@ impl ::core::clone::Clone for Enum1 { fn clone(&self) -> Self { match self { Enum1::Single { x: __self_0 } => - Enum1::Single { x: ::core::clone::Clone::clone(__self_0) }, + Self::Single { x: ::core::clone::Clone::clone(__self_0) }, } } } @@ -1103,7 +1093,7 @@ enum Fieldless1 { #[automatically_derived] impl ::core::clone::Clone for Fieldless1 { #[inline] - fn clone(&self) -> Self { Fieldless1::A } + fn clone(&self) -> Self { Self::A } } #[automatically_derived] impl ::core::fmt::Debug for Fieldless1 { @@ -1428,11 +1418,11 @@ impl ::core::clone::Clone for Fielded { fn clone(&self) -> Self { match self { Fielded::X(__self_0) => - Fielded::X(::core::clone::Clone::clone(__self_0)), + Self::X(::core::clone::Clone::clone(__self_0)), Fielded::Y(__self_0) => - Fielded::Y(::core::clone::Clone::clone(__self_0)), + Self::Y(::core::clone::Clone::clone(__self_0)), Fielded::Z(__self_0) => - Fielded::Z(::core::clone::Clone::clone(__self_0)), + Self::Z(::core::clone::Clone::clone(__self_0)), } } } @@ -1536,9 +1526,9 @@ impl ::core::clone::Clone fn clone(&self) -> Self { match self { EnumGeneric::One(__self_0) => - EnumGeneric::One(::core::clone::Clone::clone(__self_0)), + Self::One(::core::clone::Clone::clone(__self_0)), EnumGeneric::Two(__self_0) => - EnumGeneric::Two(::core::clone::Clone::clone(__self_0)), + Self::Two(::core::clone::Clone::clone(__self_0)), } } } @@ -1746,9 +1736,7 @@ impl ::core::marker::Copy for FooCloneAndCopy { } #[automatically_derived] impl ::core::clone::Clone for FooCloneAndCopy { #[inline] - fn clone(&self) -> Self { - FooCloneAndCopy(::core::clone::Clone::clone(&self.0)) - } + fn clone(&self) -> Self { Self(::core::clone::Clone::clone(&self.0)) } } struct FooPartialOrdOrd(i32); diff --git a/tests/ui/stats/macro-stats.stderr b/tests/ui/stats/macro-stats.stderr index e3ef2add347dc..95567e20db3bf 100644 --- a/tests/ui/stats/macro-stats.stderr +++ b/tests/ui/stats/macro-stats.stderr @@ -2,11 +2,11 @@ macro-stats ==================================================================== macro-stats MACRO EXPANSION STATS: macro_stats macro-stats Macro Name Uses Lines Avg Lines Bytes Avg Bytes macro-stats ----------------------------------------------------------------------------------- -macro-stats #[derive(Clone)] 8 67 8.4 1_895 236.9 +macro-stats #[derive(Clone)] 8 67 8.4 1_909 238.6 macro-stats #[derive(Hash)] 2 17 8.5 565 282.5 macro-stats q! 1 26 26.0 519 519.0 macro-stats #[derive(Ord)] 1 15 15.0 505 505.0 -macro-stats #[derive(Default)] 2 16 8.0 407 203.5 +macro-stats #[derive(Default)] 2 16 8.0 409 204.5 macro-stats #[derive(Eq)] 1 11 11.0 312 312.0 macro-stats #[derive(Debug)] 1 8 8.0 277 277.0 macro-stats #[derive(PartialEq)] 1 9 9.0 269 269.0 From f75966c735b231545d572f3be2833b3c0d814b99 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 20 Sep 2026 11:47:40 +0000 Subject: [PATCH 0543/1309] remove `extract_arg_details` --- .../src/deriving/generic/mod.rs | 68 ++++++------------- 1 file changed, 19 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 8d6935f1c0e04..1a4f70c841872 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -174,6 +174,7 @@ //! ) //! ``` +use std::iter::once; use std::ops::Not; use std::{iter, vec}; @@ -819,18 +820,10 @@ impl<'a> TraitDef<'a> { let field_tys = struct_def.fields().iter().map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); - let body = if from_scratch || method_def.is_static() { method_def.call_substructure_method(cx, self, StaticStruct(struct_def)) } else { - method_def.expand_struct_method_body( - cx, - self, - struct_def, - &selflike_args, - is_packed, - ) + method_def.expand_struct_method_body(cx, self, struct_def, is_packed) }; method_def.create_method(cx, self, body) @@ -854,12 +847,10 @@ impl<'a> TraitDef<'a> { .map(|field| &*field.ty); let methods = self.methods.iter().filter_map(|method_def| { - let ArgDetails { selflike_args } = method_def.extract_arg_details(cx, self); - let body = if from_scratch || method_def.is_static() { method_def.call_substructure_method(cx, self, StaticEnum(enum_def)) } else { - method_def.expand_enum_method_body(cx, self, enum_def, type_ident, selflike_args) + method_def.expand_enum_method_body(cx, self, enum_def, type_ident) }; method_def.create_method(cx, self, body) @@ -870,12 +861,6 @@ impl<'a> TraitDef<'a> { } } -struct ArgDetails { - /// Expressions for `&self` (if present) and also any other - /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). - selflike_args: ThinVec>, -} - impl<'a> MethodDef<'a> { fn call_substructure_method( &self, @@ -893,28 +878,19 @@ impl<'a> MethodDef<'a> { !self.explicit_self } - fn extract_arg_details(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ArgDetails { - let mut selflike_args = ThinVec::new(); - let span = trait_.span; - - if self.explicit_self { - // This constructs a fresh `self` path. - selflike_args.push(cx.expr_self(span)); - } - - for (ty, name) in self.nonself_args.iter() { - let ident = Ident::new(*name, span); - let arg_expr = cx.expr_ident(span, ident); + /// Expressions for `&self` and also any other + /// args with the same type (e.g. the `other` arg in `PartialEq::eq`). + fn get_selflike_args(&self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>) -> ThinVec> { + assert!(self.explicit_self); - match ty { - // Selflike (`&Self`) arguments only occur in non-static methods. - Ref(Self_, _) if self.explicit_self => selflike_args.push(arg_expr), - Self_ => cx.dcx().span_bug(span, "`Self` in non-return position"), - _ => (), - } - } + let span = trait_.span; - ArgDetails { selflike_args } + once(cx.expr_self(span)) + .chain(self.nonself_args.iter().filter_map(|(ty, name)| match ty { + Ref(Self_, _) => Some(cx.expr_ident(span, Ident::new(*name, span))), + _ => None, + })) + .collect() } fn create_method( @@ -1023,13 +999,12 @@ impl<'a> MethodDef<'a> { cx: &ExtCtxt<'_>, trait_: &TraitDef<'b>, struct_def: &'b VariantData, - selflike_args: &[Box], is_packed: bool, ) -> BlockOrExpr { - assert!(selflike_args.len() == 1 || selflike_args.len() == 2); + let selflike_args = self.get_selflike_args(cx, trait_); let selflike_fields = - trait_.create_struct_field_access_fields(cx, selflike_args, struct_def, is_packed); + trait_.create_struct_field_access_fields(cx, &selflike_args, struct_def, is_packed); self.call_substructure_method(cx, trait_, Struct(struct_def, selflike_fields)) } @@ -1074,13 +1049,7 @@ impl<'a> MethodDef<'a> { trait_: &TraitDef<'b>, enum_def: &'b EnumDef, type_ident: Ident, - mut selflike_args: ThinVec>, ) -> BlockOrExpr { - assert!( - !selflike_args.is_empty(), - "static methods must use `expand_static_enum_method_body`", - ); - let span = trait_.span; let variants = &enum_def.variants; @@ -1092,13 +1061,14 @@ impl<'a> MethodDef<'a> { // `match *self {}`. This produces machine code identical to `unsafe { // core::intrinsics::unreachable() }` while being safe and stable. if variants.is_empty() { - selflike_args.truncate(1); - let match_arg = cx.expr_deref(span, selflike_args.pop().unwrap()); + let match_arg = cx.expr_deref(span, cx.expr_self(span)); let match_arms = ThinVec::new(); let expr = cx.expr_match(span, match_arg, match_arms); return BlockOrExpr(ThinVec::new(), Some(expr)); } + let selflike_args = self.get_selflike_args(cx, trait_); + let prefixes = iter::once("__self".to_string()) .chain((1..selflike_args.len()).map(|arg_count| format!("__arg{arg_count}"))) .collect::>(); From c2328bf8cef0510495f5c8cbdf80b26387e7baa6 Mon Sep 17 00:00:00 2001 From: cyrgani Date: Sun, 20 Sep 2026 12:24:43 +0000 Subject: [PATCH 0544/1309] merge `Substructure` with `SubstructureFields` --- .../rustc_builtin_macros/src/deriving/clone.rs | 4 ++-- .../rustc_builtin_macros/src/deriving/debug.rs | 2 +- .../src/deriving/default.rs | 2 +- .../rustc_builtin_macros/src/deriving/eq.rs | 2 +- .../rustc_builtin_macros/src/deriving/from.rs | 4 ++-- .../src/deriving/generic/mod.rs | 18 +++++------------- .../rustc_builtin_macros/src/deriving/hash.rs | 2 +- .../src/deriving/partial_eq.rs | 4 +--- 8 files changed, 14 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs index a68be4fa5f623..7cce8a2a46269 100644 --- a/compiler/rustc_builtin_macros/src/deriving/clone.rs +++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs @@ -149,7 +149,7 @@ fn cs_clone_simple( &[sym::clone, sym::AssertParamIsCopy], ); } else { - match substr.fields { + match substr { StaticStruct(vdata, ..) => { process_variant(vdata); } @@ -175,7 +175,7 @@ fn cs_clone(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_>) -> Blo let ctor_path; let all_fields; let vdata; - match substr.fields { + match substr { Struct(vdata_, af) => { ctor_path = cx.path(trait_span, vec![self_ident]); all_fields = af; diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs index c02e13d9c8e30..66e9b3ed82bcc 100644 --- a/compiler/rustc_builtin_macros/src/deriving/debug.rs +++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs @@ -64,7 +64,7 @@ fn show_substructure( return BlockOrExpr::new_expr(cx.expr_ok(span, cx.expr_tuple(span, ThinVec::new()))); } - let (ident, vdata, fields) = match substr.fields { + let (ident, vdata, fields) = match substr { Struct(vdata, fields) => (type_ident, vdata, fields), EnumMatching(v, fields) => (v.ident, &v.data, fields), AllFieldlessEnum(enum_def) => return show_fieldless_enum(cx, span, enum_def, type_ident), diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs index 8592b8ebf99f2..866ffc74da436 100644 --- a/compiler/rustc_builtin_macros/src/deriving/default.rs +++ b/compiler/rustc_builtin_macros/src/deriving/default.rs @@ -36,7 +36,7 @@ pub(crate) fn expand_deriving_default( attributes: thin_vec![cx.attr_word(sym::inline, span)], fieldless_variants_strategy: FieldlessVariantsStrategy::Default, combine_substructure: combine_substructure(|cx, trait_span, substr| { - match substr.fields { + match substr { StaticStruct(variant_data) => { default_struct_substructure(cx, trait_span, variant_data) } diff --git a/compiler/rustc_builtin_macros/src/deriving/eq.rs b/compiler/rustc_builtin_macros/src/deriving/eq.rs index cc18aa342ffdd..1083b37cbf248 100644 --- a/compiler/rustc_builtin_macros/src/deriving/eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/eq.rs @@ -73,7 +73,7 @@ fn cs_total_eq_assert(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<' } }; - match substr.fields { + match substr { StaticStruct(vdata, ..) => { process_variant(vdata); } diff --git a/compiler/rustc_builtin_macros/src/deriving/from.rs b/compiler/rustc_builtin_macros/src/deriving/from.rs index fa4caee250c3d..64cc917302935 100644 --- a/compiler/rustc_builtin_macros/src/deriving/from.rs +++ b/compiler/rustc_builtin_macros/src/deriving/from.rs @@ -88,8 +88,8 @@ pub(crate) fn expand_deriving_from( }; let self_kw = Ident::new(kw::SelfUpper, span); - let expr: Box = match substructure.fields { - SubstructureFields::StaticStruct(variant) => match variant { + let expr: Box = match substructure { + StaticStruct(variant) => match variant { // Self { field: value } VariantData::Struct { .. } => cx.expr_struct_ident( span, diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs index 1a4f70c841872..b6bd482945546 100644 --- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs +++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs @@ -178,7 +178,7 @@ use std::iter::once; use std::ops::Not; use std::{iter, vec}; -pub(crate) use SubstructureFields::*; +pub(crate) use Substructure::*; pub(crate) use rustc_ast as ast; use rustc_ast::token::{IdentKind, LitKind, Token, TokenKind}; use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenTree}; @@ -269,11 +269,6 @@ pub(crate) enum FieldlessVariantsStrategy { SpecializeIfAllVariantsFieldless, } -/// All the data about the data structure/method being derived upon. -pub(crate) struct Substructure<'a> { - pub fields: SubstructureFields<'a>, -} - /// Summary of the relevant parts of a struct/enum field. pub(crate) struct FieldInfo { pub span: Span, @@ -290,7 +285,7 @@ pub(crate) struct FieldInfo { } /// A summary of the possible sets of fields. -pub(crate) enum SubstructureFields<'a> { +pub(crate) enum Substructure<'a> { /// A non-static method where `Self` is a struct. Struct(&'a ast::VariantData, Vec), @@ -866,12 +861,9 @@ impl<'a> MethodDef<'a> { &self, cx: &ExtCtxt<'_>, trait_: &TraitDef<'_>, - fields: SubstructureFields<'_>, + substructure: Substructure<'_>, ) -> BlockOrExpr { - let span = trait_.span; - let substructure = Substructure { fields }; - let f: &CombineSubstructureFunc<'_> = &self.combine_substructure; - f(cx, span, substructure) + (self.combine_substructure)(cx, trait_.span, substructure) } fn is_static(&self) -> bool { @@ -1397,7 +1389,7 @@ pub(crate) fn cs_foldr( // The fallback case for a struct or enum variant with no fields. fieldless: impl Fn() -> Box, ) -> Box { - match substructure.fields { + match substructure { EnumMatching(.., all_fields) | Struct(_, all_fields) => { let mut fields = all_fields.into_iter(); let base_field = fields.next_back(); diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs index 0530303270239..55c1d338c5d2d 100644 --- a/compiler/rustc_builtin_macros/src/deriving/hash.rs +++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs @@ -69,7 +69,7 @@ fn hash_substructure(cx: &ExtCtxt<'_>, trait_span: Span, substr: Substructure<'_ cx.stmt_expr(expr) }; - let (stmts, match_expr) = match substr.fields { + let (stmts, match_expr) = match substr { Struct(_, fields) | EnumMatching(.., fields) => { let stmts = fields.into_iter().map(|field| call_hash(field.span, field.self_expr)).collect(); diff --git a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs index 715ecbfd24719..5c8a6225fa91b 100644 --- a/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs +++ b/compiler/rustc_builtin_macros/src/deriving/partial_eq.rs @@ -121,9 +121,7 @@ fn get_substructure_equality_expr( span: Span, substructure: Substructure<'_>, ) -> BlockOrExpr { - use SubstructureFields::*; - - BlockOrExpr::new_expr(match substructure.fields { + BlockOrExpr::new_expr(match substructure { EnumMatching(.., fields) | Struct(.., fields) => { let combine = move |acc, field| { let rhs = get_field_equality_expr(cx, field); From 1875276f5ced891a5975dd70658226d0574e0c2e Mon Sep 17 00:00:00 2001 From: xonx <119700621+xonx4l@users.noreply.github.com> Date: Mon, 21 Sep 2026 12:47:26 +0000 Subject: [PATCH 0545/1309] simplify get_next_url to a single counter map --- src/librustdoc/html/render/sidebar.rs | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/src/librustdoc/html/render/sidebar.rs b/src/librustdoc/html/render/sidebar.rs index 95cc1c88902e2..011079f9e4f2b 100644 --- a/src/librustdoc/html/render/sidebar.rs +++ b/src/librustdoc/html/render/sidebar.rs @@ -746,25 +746,13 @@ fn sidebar_render_assoc_items( } /// Tracks sidebar link anchors so duplicates get unique names. -#[derive(Default)] -struct UsedLinks { - links: FxHashSet, - /// Next number to try for each anchor. - next_suffix: FxHashMap, -} +type UsedLinks = FxHashMap; fn get_next_url(used_links: &mut UsedLinks, url: String) -> String { - if used_links.links.insert(url.clone()) { - return url; - } - let add = used_links.next_suffix.entry(url.clone()).or_insert(1); - loop { - let candidate = format!("{url}-{add}"); - *add += 1; - if used_links.links.insert(candidate.clone()) { - return candidate; - } - } + let count = used_links.entry(url.clone()).or_insert(0); + let res = if *count == 0 { url } else { format!("{url}-{count}") }; + *count += 1; + res } enum GetMethodsMode<'r, 'l> { From 754219139cc4fd2b1531ad4a6d0cfbe615b917bc Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Wed, 2 Sep 2026 19:19:16 +0200 Subject: [PATCH 0546/1309] Allow `crate::` prepending in 2015 edition in `Ty` display --- .../src/check/compare_impl_item.rs | 4 +- compiler/rustc_middle/src/ty/print/pretty.rs | 9 +- tests/ui/coherence/coherence_inherent.stderr | 2 +- .../ui/coherence/coherence_inherent_cc.stderr | 2 +- tests/ui/hygiene/trait_items.stderr | 2 +- .../impl-restriction-check.e2015.stderr | 98 ------------------- .../impl-restriction-check.rs | 28 +++--- ...8.stderr => impl-restriction-check.stderr} | 28 +++--- ...on_inherent_impl_on_rigid_type.next.stderr | 2 +- .../method/would-constrain-opaque.next.stderr | 4 +- .../no-method-suggested-traits.stderr | 16 +-- ...s-impl-trait-declaration-too-subtle.stderr | 4 +- tests/ui/impl-trait/trait_type.stderr | 2 +- tests/ui/imports/issue-114682-3.stderr | 2 +- tests/ui/imports/overlapping_pub_trait.stderr | 2 +- tests/ui/imports/unnamed_pub_trait.stderr | 2 +- ...rigid-alias-bound-is-not-inherent-2.stderr | 2 +- tests/ui/mismatched_types/issue-13033.stderr | 5 +- .../trait-impl-fn-incompatibility.stderr | 4 +- tests/ui/mut/mismatch-trait-mut.e2015.fixed | 49 ++++++++++ tests/ui/mut/mismatch-trait-mut.e2015.stderr | 77 +++++++++++++++ tests/ui/mut/mismatch-trait-mut.e2018.fixed | 49 ++++++++++ tests/ui/mut/mismatch-trait-mut.e2018.stderr | 77 +++++++++++++++ tests/ui/mut/mismatch-trait-mut.rs | 49 ++++++++++ .../ui/shadowed/shadowed-trait-methods.stderr | 2 +- .../dont-wrap-ambiguous-receivers.stderr | 4 +- ...ort-suggestion-on-method.unimported.stderr | 2 +- .../ui/suggestions/use-placement-typeck.fixed | 2 +- .../suggestions/use-placement-typeck.stderr | 2 +- ...ck-scoped-trait-import-issue-134146.stderr | 10 +- tests/ui/traits/issue-35869.stderr | 2 +- tests/ui/traits/item-privacy.stderr | 12 +-- tests/ui/traits/method-private.stderr | 2 +- ...-mod-trait-method-lookup-leak-10465.stderr | 2 +- .../traits/wrong-mul-method-signature.stderr | 2 +- .../unnameable_type.stderr | 2 +- tests/ui/typeck/issue-43189.stderr | 2 +- 37 files changed, 382 insertions(+), 183 deletions(-) delete mode 100644 tests/ui/impl-restriction/impl-restriction-check.e2015.stderr rename tests/ui/impl-restriction/{impl-restriction-check.e2018.stderr => impl-restriction-check.stderr} (83%) create mode 100644 tests/ui/mut/mismatch-trait-mut.e2015.fixed create mode 100644 tests/ui/mut/mismatch-trait-mut.e2015.stderr create mode 100644 tests/ui/mut/mismatch-trait-mut.e2018.fixed create mode 100644 tests/ui/mut/mismatch-trait-mut.e2018.stderr create mode 100644 tests/ui/mut/mismatch-trait-mut.rs diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs index 4061d247f59f1..677ae7e4d0925 100644 --- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs +++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs @@ -1066,12 +1066,12 @@ fn report_trait_method_mismatch<'tcx>( }; }; } else if let Some(trait_ty) = trait_sig.inputs().get(*i) { - diag.span_suggestion_verbose( + rustc_middle::ty::print::with_crate_prefix!(diag.span_suggestion_verbose( impl_err_span, "change the parameter type to match the trait", trait_ty, Applicability::MachineApplicable, - ); + )); } } _ => {} diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index 1da8071ce69ce..ba4a59daad01d 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -2395,12 +2395,9 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> { fn print_crate_name(&mut self, cnum: CrateNum) -> Result<(), PrintError> { self.empty_path = true; if cnum == LOCAL_CRATE && !with_resolve_crate_name() { - if self.tcx.sess.at_least_rust_2018() { - // We add the `crate::` keyword on Rust 2018, only when desired. - if with_crate_prefix() { - write!(self, "{}", kw::Crate)?; - self.empty_path = false; - } + if with_crate_prefix() { + write!(self, "{}", kw::Crate)?; + self.empty_path = false; } } else { write!(self, "{}", self.tcx.crate_name(cnum))?; diff --git a/tests/ui/coherence/coherence_inherent.stderr b/tests/ui/coherence/coherence_inherent.stderr index df184526c03f0..a4bf750fec8ad 100644 --- a/tests/ui/coherence/coherence_inherent.stderr +++ b/tests/ui/coherence/coherence_inherent.stderr @@ -7,7 +7,7 @@ LL | s.the_fn(); = help: items from traits can only be used if the trait is in scope help: trait `TheTrait` which provides `the_fn` is implemented but not in scope; perhaps you want to import it | -LL + use Lib::TheTrait; +LL + use crate::Lib::TheTrait; | error: aborting due to 1 previous error diff --git a/tests/ui/coherence/coherence_inherent_cc.stderr b/tests/ui/coherence/coherence_inherent_cc.stderr index ad8b630f16b76..3b562ac19ab1e 100644 --- a/tests/ui/coherence/coherence_inherent_cc.stderr +++ b/tests/ui/coherence/coherence_inherent_cc.stderr @@ -7,7 +7,7 @@ LL | s.the_fn(); = help: items from traits can only be used if the trait is in scope help: trait `TheTrait` which provides `the_fn` is implemented but not in scope; perhaps you want to import it | -LL + use coherence_inherent_cc_lib::TheTrait; +LL + use crate::coherence_inherent_cc_lib::TheTrait; | error: aborting due to 1 previous error diff --git a/tests/ui/hygiene/trait_items.stderr b/tests/ui/hygiene/trait_items.stderr index 3609fac714f3d..94d46961dbff8 100644 --- a/tests/ui/hygiene/trait_items.stderr +++ b/tests/ui/hygiene/trait_items.stderr @@ -13,7 +13,7 @@ LL | pub macro m() { ().f() } = help: items from traits can only be used if the trait is in scope help: trait `T` which provides `f` is implemented but not in scope; perhaps you want to import it | -LL + use foo::T; +LL + use crate::foo::T; | error: aborting due to 1 previous error diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr b/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr deleted file mode 100644 index df7cf671bb699..0000000000000 --- a/tests/ui/impl-restriction/impl-restriction-check.e2015.stderr +++ /dev/null @@ -1,98 +0,0 @@ -error: trait cannot be implemented outside `external` - --> $DIR/impl-restriction-check.rs:11:1 - | -LL | impl external::TopLevel for LocalType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/auxiliary/external-impl-restriction.rs:3:5 - | -LL | pub impl(crate) trait TopLevel {} - | ^^^^^^^^^^^ - -error: trait cannot be implemented outside `external` - --> $DIR/impl-restriction-check.rs:12:1 - | -LL | impl external::inner::Inner for LocalType {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/auxiliary/external-impl-restriction.rs:6:9 - | -LL | pub impl(self) trait Inner {} - | ^^^^^^^^^^ - -error: trait cannot be implemented outside `foo::bar` - --> $DIR/impl-restriction-check.rs:29:5 - | -LL | impl bar::Foo for i8 {} - | ^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:16:20 - | -LL | pub(crate) impl(self) trait Foo {} - | ^^^^^^^^^^ - -error: trait cannot be implemented outside `foo::bar` - --> $DIR/impl-restriction-check.rs:38:1 - | -LL | impl foo::bar::Foo for u8 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:16:20 - | -LL | pub(crate) impl(self) trait Foo {} - | ^^^^^^^^^^ - -error: trait cannot be implemented outside `foo` - --> $DIR/impl-restriction-check.rs:40:1 - | -LL | impl foo::bar::Bar for u8 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:17:20 - | -LL | pub(crate) impl(super) trait Bar {} - | ^^^^^^^^^^^ - -error: trait cannot be implemented outside `foo::bar` - --> $DIR/impl-restriction-check.rs:33:5 - | -LL | impl bar::Qux for i8 {} - | ^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:19:20 - | -LL | pub(crate) impl(in crate::foo::bar) trait Qux {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: trait cannot be implemented outside `foo::bar` - --> $DIR/impl-restriction-check.rs:43:1 - | -LL | impl foo::bar::Qux for u8 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:19:20 - | -LL | pub(crate) impl(in crate::foo::bar) trait Qux {} - | ^^^^^^^^^^^^^^^^^^^^^^^^ - -error: trait cannot be implemented outside `foo` - --> $DIR/impl-restriction-check.rs:45:1 - | -LL | impl foo::bar::FooBar for u8 {} - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ - | -note: trait restricted here - --> $DIR/impl-restriction-check.rs:20:20 - | -LL | pub(crate) impl(in crate::foo) trait FooBar {} - | ^^^^^^^^^^^^^^^^^^^ - -error: aborting due to 8 previous errors - diff --git a/tests/ui/impl-restriction/impl-restriction-check.rs b/tests/ui/impl-restriction/impl-restriction-check.rs index f9403e218bd26..ea46230033d57 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.rs +++ b/tests/ui/impl-restriction/impl-restriction-check.rs @@ -1,7 +1,5 @@ //@ aux-build: external-impl-restriction.rs -//@ revisions: e2015 e2018 -//@ [e2015] edition: 2015 -//@ [e2018] edition: 2018.. + #![feature(impl_restriction)] extern crate external_impl_restriction as external; @@ -26,23 +24,23 @@ pub mod foo { impl FooBar for i16 {} // OK } - impl bar::Foo for i8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar` - //[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar` + impl bar::Foo for i8 {} + //~^ ERROR trait cannot be implemented outside `crate::foo::bar` impl bar::Bar for i8 {} // OK impl bar::Baz for i8 {} // OK - impl bar::Qux for i8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar` - //[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar` + impl bar::Qux for i8 {} + //~^ ERROR trait cannot be implemented outside `crate::foo::bar` impl bar::FooBar for i8 {} // OK } -impl foo::bar::Foo for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar` -//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar` -impl foo::bar::Bar for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo` -//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo` +impl foo::bar::Foo for u8 {} +//~^ ERROR trait cannot be implemented outside `crate::foo::bar` +impl foo::bar::Bar for u8 {} +//~^ ERROR trait cannot be implemented outside `crate::foo` impl foo::bar::Baz for u8 {} // OK -impl foo::bar::Qux for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo::bar` -//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo::bar` -impl foo::bar::FooBar for u8 {} //[e2015]~ ERROR trait cannot be implemented outside `foo` -//[e2018]~^ ERROR trait cannot be implemented outside `crate::foo` +impl foo::bar::Qux for u8 {} +//~^ ERROR trait cannot be implemented outside `crate::foo::bar` +impl foo::bar::FooBar for u8 {} +//~^ ERROR trait cannot be implemented outside `crate::foo` fn main() {} diff --git a/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr b/tests/ui/impl-restriction/impl-restriction-check.stderr similarity index 83% rename from tests/ui/impl-restriction/impl-restriction-check.e2018.stderr rename to tests/ui/impl-restriction/impl-restriction-check.stderr index d1ef4fa4dc6c4..f0e0e1159353a 100644 --- a/tests/ui/impl-restriction/impl-restriction-check.e2018.stderr +++ b/tests/ui/impl-restriction/impl-restriction-check.stderr @@ -1,5 +1,5 @@ error: trait cannot be implemented outside `external` - --> $DIR/impl-restriction-check.rs:11:1 + --> $DIR/impl-restriction-check.rs:9:1 | LL | impl external::TopLevel for LocalType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -11,7 +11,7 @@ LL | pub impl(crate) trait TopLevel {} | ^^^^^^^^^^^ error: trait cannot be implemented outside `external` - --> $DIR/impl-restriction-check.rs:12:1 + --> $DIR/impl-restriction-check.rs:10:1 | LL | impl external::inner::Inner for LocalType {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -23,73 +23,73 @@ LL | pub impl(self) trait Inner {} | ^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo::bar` - --> $DIR/impl-restriction-check.rs:29:5 + --> $DIR/impl-restriction-check.rs:27:5 | LL | impl bar::Foo for i8 {} | ^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:16:20 + --> $DIR/impl-restriction-check.rs:14:20 | LL | pub(crate) impl(self) trait Foo {} | ^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo::bar` - --> $DIR/impl-restriction-check.rs:38:1 + --> $DIR/impl-restriction-check.rs:36:1 | LL | impl foo::bar::Foo for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:16:20 + --> $DIR/impl-restriction-check.rs:14:20 | LL | pub(crate) impl(self) trait Foo {} | ^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo` - --> $DIR/impl-restriction-check.rs:40:1 + --> $DIR/impl-restriction-check.rs:38:1 | LL | impl foo::bar::Bar for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:17:20 + --> $DIR/impl-restriction-check.rs:15:20 | LL | pub(crate) impl(super) trait Bar {} | ^^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo::bar` - --> $DIR/impl-restriction-check.rs:33:5 + --> $DIR/impl-restriction-check.rs:31:5 | LL | impl bar::Qux for i8 {} | ^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:19:20 + --> $DIR/impl-restriction-check.rs:17:20 | LL | pub(crate) impl(in crate::foo::bar) trait Qux {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo::bar` - --> $DIR/impl-restriction-check.rs:43:1 + --> $DIR/impl-restriction-check.rs:41:1 | LL | impl foo::bar::Qux for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:19:20 + --> $DIR/impl-restriction-check.rs:17:20 | LL | pub(crate) impl(in crate::foo::bar) trait Qux {} | ^^^^^^^^^^^^^^^^^^^^^^^^ error: trait cannot be implemented outside `crate::foo` - --> $DIR/impl-restriction-check.rs:45:1 + --> $DIR/impl-restriction-check.rs:43:1 | LL | impl foo::bar::FooBar for u8 {} | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | note: trait restricted here - --> $DIR/impl-restriction-check.rs:20:20 + --> $DIR/impl-restriction-check.rs:18:20 | LL | pub(crate) impl(in crate::foo) trait FooBar {} | ^^^^^^^^^^^^^^^^^^^ diff --git a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr index 7570d412bf19b..8e8a307917265 100644 --- a/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr +++ b/tests/ui/impl-trait/call_method_on_inherent_impl_on_rigid_type.next.stderr @@ -7,7 +7,7 @@ LL | x.my_debug(); = help: items from traits can only be used if the trait is implemented and in scope help: trait `MyDebug` which provides `my_debug` is implemented but not in scope; perhaps you want to import it | -LL + use MyDebug; +LL + use crate::MyDebug; | error: aborting due to 1 previous error diff --git a/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr index e2fc9c6d2d88e..3af5833639280 100644 --- a/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr +++ b/tests/ui/impl-trait/method/would-constrain-opaque.next.stderr @@ -7,7 +7,7 @@ LL | x.method(); = help: items from traits can only be used if the trait is implemented and in scope help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use Trait; +LL + use crate::Trait; | error[E0599]: no method named `method` found for reference `&_` in the current scope @@ -19,7 +19,7 @@ LL | x.method(); = help: items from traits can only be used if the trait is implemented and in scope help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use Trait; +LL + use crate::Trait; | error: aborting due to 2 previous errors diff --git a/tests/ui/impl-trait/no-method-suggested-traits.stderr b/tests/ui/impl-trait/no-method-suggested-traits.stderr index 53c3e2caae6ae..ca383523f9238 100644 --- a/tests/ui/impl-trait/no-method-suggested-traits.stderr +++ b/tests/ui/impl-trait/no-method-suggested-traits.stderr @@ -7,9 +7,9 @@ LL | 1u32.method(); = help: items from traits can only be used if the trait is in scope help: the following traits which provide `method` are implemented but not in scope; perhaps you want to import one of them | -LL + use foo::Bar; +LL + use crate::foo::Bar; | -LL + use no_method_suggested_traits::foo::PubPub; +LL + use crate::no_method_suggested_traits::foo::PubPub; | help: there is a method `method2` with a similar name | @@ -25,9 +25,9 @@ LL | std::rc::Rc::new(&mut Box::new(&1u32)).method(); = help: items from traits can only be used if the trait is in scope help: the following traits which provide `method` are implemented but not in scope; perhaps you want to import one of them | -LL + use foo::Bar; +LL + use crate::foo::Bar; | -LL + use no_method_suggested_traits::foo::PubPub; +LL + use crate::no_method_suggested_traits::foo::PubPub; | help: there is a method `method2` with a similar name | @@ -46,7 +46,7 @@ LL | 'a'.method(); = help: items from traits can only be used if the trait is in scope help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use foo::Bar; +LL + use crate::foo::Bar; | help: there is a method `method2` with a similar name | @@ -62,7 +62,7 @@ LL | std::rc::Rc::new(&mut Box::new(&'a')).method(); = help: items from traits can only be used if the trait is in scope help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use foo::Bar; +LL + use crate::foo::Bar; | help: there is a method `method2` with a similar name | @@ -83,7 +83,7 @@ LL | fn method(&self) {} = help: items from traits can only be used if the trait is in scope help: trait `PubPub` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use no_method_suggested_traits::foo::PubPub; +LL + use crate::no_method_suggested_traits::foo::PubPub; | help: there is a method `method3` with a similar name | @@ -99,7 +99,7 @@ LL | std::rc::Rc::new(&mut Box::new(&1i32)).method(); = help: items from traits can only be used if the trait is in scope help: trait `PubPub` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use no_method_suggested_traits::foo::PubPub; +LL + use crate::no_method_suggested_traits::foo::PubPub; | help: there is a method `method3` with a similar name | diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr index f42873ce9e400..f921e5a452244 100644 --- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr +++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr @@ -12,7 +12,7 @@ LL | fn eq(&self, _other: &(Foo, i32)) -> bool { help: change the parameter type to match the trait | LL - fn eq(&self, _other: &(Foo, i32)) -> bool { -LL + fn eq(&self, _other: &(a::Bar, i32)) -> bool { +LL + fn eq(&self, _other: &(crate::a::Bar, i32)) -> bool { | error[E0053]: method `eq` has an incompatible type for trait @@ -34,7 +34,7 @@ LL | fn eq(&self, _other: &(Bar, i32)) -> bool { help: change the parameter type to match the trait | LL - fn eq(&self, _other: &(Bar, i32)) -> bool { -LL + fn eq(&self, _other: &(b::Foo, i32)) -> bool { +LL + fn eq(&self, _other: &(crate::b::Foo, i32)) -> bool { | error: item does not constrain `a::Foo::{opaque#0}` diff --git a/tests/ui/impl-trait/trait_type.stderr b/tests/ui/impl-trait/trait_type.stderr index 69cab0708e687..18d914a96a291 100644 --- a/tests/ui/impl-trait/trait_type.stderr +++ b/tests/ui/impl-trait/trait_type.stderr @@ -9,7 +9,7 @@ LL | fn fmt(&self, x: &str) -> () { } help: change the parameter type to match the trait | LL - fn fmt(&self, x: &str) -> () { } -LL + fn fmt(&self, x: &mut Formatter<'_>) -> () { } +LL + fn fmt(&self, x: &mut std::fmt::Formatter<'_>) -> () { } | error[E0050]: method `fmt` has 1 parameter but the declaration in trait `std::fmt::Display::fmt` has 2 diff --git a/tests/ui/imports/issue-114682-3.stderr b/tests/ui/imports/issue-114682-3.stderr index 6af7a4e026140..73267f35fe71c 100644 --- a/tests/ui/imports/issue-114682-3.stderr +++ b/tests/ui/imports/issue-114682-3.stderr @@ -10,7 +10,7 @@ LL | a.ext(); = help: items from traits can only be used if the trait is in scope help: trait `SettingsExt` which provides `ext` is implemented but not in scope; perhaps you want to import it | -LL + use auto::SettingsExt; +LL + use crate::auto::SettingsExt; | error: aborting due to 1 previous error diff --git a/tests/ui/imports/overlapping_pub_trait.stderr b/tests/ui/imports/overlapping_pub_trait.stderr index 3dedc3528595f..19b47786ddd7d 100644 --- a/tests/ui/imports/overlapping_pub_trait.stderr +++ b/tests/ui/imports/overlapping_pub_trait.stderr @@ -12,7 +12,7 @@ LL | pub trait Tr { fn method(&self); } = help: items from traits can only be used if the trait is in scope help: trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use overlapping_pub_trait_source::m::Tr; +LL + use crate::overlapping_pub_trait_source::m::Tr; | error: aborting due to 1 previous error diff --git a/tests/ui/imports/unnamed_pub_trait.stderr b/tests/ui/imports/unnamed_pub_trait.stderr index 7c4c76f6f2a47..6db4399829ff3 100644 --- a/tests/ui/imports/unnamed_pub_trait.stderr +++ b/tests/ui/imports/unnamed_pub_trait.stderr @@ -12,7 +12,7 @@ LL | pub trait Tr { fn method(&self); } = help: items from traits can only be used if the trait is in scope help: trait `Tr` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use unnamed_pub_trait_source::prelude::*; // trait Tr +LL + use crate::unnamed_pub_trait_source::prelude::*; // trait Tr | error: aborting due to 1 previous error diff --git a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr index 4a8aa61d8bd4a..487ef3e0eadae 100644 --- a/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr +++ b/tests/ui/methods/rigid-alias-bound-is-not-inherent-2.stderr @@ -9,7 +9,7 @@ LL | x.method(); = help: items from traits can only be used if the trait is in scope help: trait `Trait` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use module::Trait; +LL + use crate::module::Trait; | error: aborting due to 1 previous error diff --git a/tests/ui/mismatched_types/issue-13033.stderr b/tests/ui/mismatched_types/issue-13033.stderr index f12f81dcfa52e..f21d49eac7284 100644 --- a/tests/ui/mismatched_types/issue-13033.stderr +++ b/tests/ui/mismatched_types/issue-13033.stderr @@ -13,8 +13,9 @@ LL | fn bar(&mut self, other: &mut dyn Foo); found signature `fn(&mut Baz, &dyn Foo)` help: change the parameter type to match the trait | -LL | fn bar(&mut self, other: &mut dyn Foo) {} - | +++ +LL - fn bar(&mut self, other: &dyn Foo) {} +LL + fn bar(&mut self, other: &mut dyn crate::Foo) {} + | error: aborting due to 1 previous error diff --git a/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr index 45a02982289de..4aabf2372e478 100644 --- a/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr +++ b/tests/ui/mismatched_types/trait-impl-fn-incompatibility.stderr @@ -32,8 +32,8 @@ LL | fn bar(&mut self, bar: &mut Bar); found signature `fn(&mut Bar, &Bar)` help: change the parameter type to match the trait | -LL | fn bar(&mut self, bar: &mut Bar) { } - | +++ +LL | fn bar(&mut self, bar: &mut crate::Bar) { } + | +++++++++++ error: aborting due to 2 previous errors diff --git a/tests/ui/mut/mismatch-trait-mut.e2015.fixed b/tests/ui/mut/mismatch-trait-mut.e2015.fixed new file mode 100644 index 0000000000000..43be28e5a5a46 --- /dev/null +++ b/tests/ui/mut/mismatch-trait-mut.e2015.fixed @@ -0,0 +1,49 @@ +// This test ensures that the suggested path is actually valid and relative to the +// trait impl and not to the trait definition. + +//@ run-rustfix +//@ revisions: e2015 e2018 +//@ [e2015] edition: 2015 +//@ [e2018] edition: 2018.. + +mod bar { + #[allow(dead_code)] + pub struct X; +} + +pub trait A { + fn f(_x: &mut bar::X) {} + //~^ NOTE type in trait + fn g<'a>(_x: &'a mut bar::X) -> &'a () { &() } + //~^ NOTE type in trait + fn f2(_x: &bar::X) {} + //~^ NOTE type in trait + fn g2<'a>(_x: &'a bar::X) -> &'a () { &() } + //~^ NOTE type in trait +} + +mod b { + #[allow(dead_code)] + pub struct X; + + impl crate::A for X { + fn f(_x: &mut crate::bar::X) {} + //~^ ERROR method `f` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&mut X)` + fn g<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a mut X) -> &'a ()` + fn f2(_x: &crate::bar::X) {} + //~^ ERROR method `f2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&X)` + fn g2<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a X) -> &'a ()` + } +} + +fn main() {} diff --git a/tests/ui/mut/mismatch-trait-mut.e2015.stderr b/tests/ui/mut/mismatch-trait-mut.e2015.stderr new file mode 100644 index 0000000000000..bc9d60e66bc33 --- /dev/null +++ b/tests/ui/mut/mismatch-trait-mut.e2015.stderr @@ -0,0 +1,77 @@ +error[E0053]: method `f` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:30:18 + | +LL | fn f(_x: &crate::bar::X) {} + | ^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:15:14 + | +LL | fn f(_x: &mut bar::X) {} + | ^^^^^^^^^^^ + = note: expected signature `fn(&mut X)` + found signature `fn(&X)` +help: change the parameter type to match the trait + | +LL | fn f(_x: &mut crate::bar::X) {} + | +++ + +error[E0053]: method `g` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:34:22 + | +LL | fn g<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:17:18 + | +LL | fn g<'a>(_x: &'a mut bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^ + = note: expected signature `fn(&'a mut X) -> &'a ()` + found signature `fn(&X) -> &()` +help: change the parameter type to match the trait + | +LL | fn g<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + | +++ + +error[E0053]: method `f2` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:38:19 + | +LL | fn f2(_x: &mut crate::bar::X) {} + | ^^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:19:15 + | +LL | fn f2(_x: &bar::X) {} + | ^^^^^^^ + = note: expected signature `fn(&X)` + found signature `fn(&mut X)` +help: change the parameter type to match the trait + | +LL - fn f2(_x: &mut crate::bar::X) {} +LL + fn f2(_x: &crate::bar::X) {} + | + +error[E0053]: method `g2` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:42:23 + | +LL | fn g2<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:21:19 + | +LL | fn g2<'a>(_x: &'a bar::X) -> &'a () { &() } + | ^^^^^^^^^^ + = note: expected signature `fn(&'a X) -> &'a ()` + found signature `fn(&mut X) -> &()` +help: change the parameter type to match the trait + | +LL - fn g2<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } +LL + fn g2<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mut/mismatch-trait-mut.e2018.fixed b/tests/ui/mut/mismatch-trait-mut.e2018.fixed new file mode 100644 index 0000000000000..43be28e5a5a46 --- /dev/null +++ b/tests/ui/mut/mismatch-trait-mut.e2018.fixed @@ -0,0 +1,49 @@ +// This test ensures that the suggested path is actually valid and relative to the +// trait impl and not to the trait definition. + +//@ run-rustfix +//@ revisions: e2015 e2018 +//@ [e2015] edition: 2015 +//@ [e2018] edition: 2018.. + +mod bar { + #[allow(dead_code)] + pub struct X; +} + +pub trait A { + fn f(_x: &mut bar::X) {} + //~^ NOTE type in trait + fn g<'a>(_x: &'a mut bar::X) -> &'a () { &() } + //~^ NOTE type in trait + fn f2(_x: &bar::X) {} + //~^ NOTE type in trait + fn g2<'a>(_x: &'a bar::X) -> &'a () { &() } + //~^ NOTE type in trait +} + +mod b { + #[allow(dead_code)] + pub struct X; + + impl crate::A for X { + fn f(_x: &mut crate::bar::X) {} + //~^ ERROR method `f` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&mut X)` + fn g<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a mut X) -> &'a ()` + fn f2(_x: &crate::bar::X) {} + //~^ ERROR method `f2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&X)` + fn g2<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a X) -> &'a ()` + } +} + +fn main() {} diff --git a/tests/ui/mut/mismatch-trait-mut.e2018.stderr b/tests/ui/mut/mismatch-trait-mut.e2018.stderr new file mode 100644 index 0000000000000..bc9d60e66bc33 --- /dev/null +++ b/tests/ui/mut/mismatch-trait-mut.e2018.stderr @@ -0,0 +1,77 @@ +error[E0053]: method `f` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:30:18 + | +LL | fn f(_x: &crate::bar::X) {} + | ^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:15:14 + | +LL | fn f(_x: &mut bar::X) {} + | ^^^^^^^^^^^ + = note: expected signature `fn(&mut X)` + found signature `fn(&X)` +help: change the parameter type to match the trait + | +LL | fn f(_x: &mut crate::bar::X) {} + | +++ + +error[E0053]: method `g` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:34:22 + | +LL | fn g<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:17:18 + | +LL | fn g<'a>(_x: &'a mut bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^ + = note: expected signature `fn(&'a mut X) -> &'a ()` + found signature `fn(&X) -> &()` +help: change the parameter type to match the trait + | +LL | fn g<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + | +++ + +error[E0053]: method `f2` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:38:19 + | +LL | fn f2(_x: &mut crate::bar::X) {} + | ^^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:19:15 + | +LL | fn f2(_x: &bar::X) {} + | ^^^^^^^ + = note: expected signature `fn(&X)` + found signature `fn(&mut X)` +help: change the parameter type to match the trait + | +LL - fn f2(_x: &mut crate::bar::X) {} +LL + fn f2(_x: &crate::bar::X) {} + | + +error[E0053]: method `g2` has an incompatible type for trait + --> $DIR/mismatch-trait-mut.rs:42:23 + | +LL | fn g2<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + | ^^^^^^^^^^^^^^^^^^^^^ types differ in mutability + | +note: type in trait + --> $DIR/mismatch-trait-mut.rs:21:19 + | +LL | fn g2<'a>(_x: &'a bar::X) -> &'a () { &() } + | ^^^^^^^^^^ + = note: expected signature `fn(&'a X) -> &'a ()` + found signature `fn(&mut X) -> &()` +help: change the parameter type to match the trait + | +LL - fn g2<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } +LL + fn g2<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + | + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0053`. diff --git a/tests/ui/mut/mismatch-trait-mut.rs b/tests/ui/mut/mismatch-trait-mut.rs new file mode 100644 index 0000000000000..3fc7530c03526 --- /dev/null +++ b/tests/ui/mut/mismatch-trait-mut.rs @@ -0,0 +1,49 @@ +// This test ensures that the suggested path is actually valid and relative to the +// trait impl and not to the trait definition. + +//@ run-rustfix +//@ revisions: e2015 e2018 +//@ [e2015] edition: 2015 +//@ [e2018] edition: 2018.. + +mod bar { + #[allow(dead_code)] + pub struct X; +} + +pub trait A { + fn f(_x: &mut bar::X) {} + //~^ NOTE type in trait + fn g<'a>(_x: &'a mut bar::X) -> &'a () { &() } + //~^ NOTE type in trait + fn f2(_x: &bar::X) {} + //~^ NOTE type in trait + fn g2<'a>(_x: &'a bar::X) -> &'a () { &() } + //~^ NOTE type in trait +} + +mod b { + #[allow(dead_code)] + pub struct X; + + impl crate::A for X { + fn f(_x: &crate::bar::X) {} + //~^ ERROR method `f` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&mut X)` + fn g<'a>(_x: &'a crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a mut X) -> &'a ()` + fn f2(_x: &mut crate::bar::X) {} + //~^ ERROR method `f2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&X)` + fn g2<'a>(_x: &'a mut crate::bar::X) -> &'a () { &() } + //~^ ERROR method `g2` has an incompatible type for trait + //~| NOTE types differ in mutability + //~| NOTE expected signature `fn(&'a X) -> &'a ()` + } +} + +fn main() {} diff --git a/tests/ui/shadowed/shadowed-trait-methods.stderr b/tests/ui/shadowed/shadowed-trait-methods.stderr index 647d2c7c95cb1..6f42a7a975af7 100644 --- a/tests/ui/shadowed/shadowed-trait-methods.stderr +++ b/tests/ui/shadowed/shadowed-trait-methods.stderr @@ -10,7 +10,7 @@ LL | ().f() = help: items from traits can only be used if the trait is in scope help: trait `T` which provides `f` is implemented but not in scope; perhaps you want to import it | -LL + use foo::T; +LL + use crate::foo::T; | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr index 9adbf754c70e7..6f32d3c96dd00 100644 --- a/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr +++ b/tests/ui/suggestions/dont-wrap-ambiguous-receivers.stderr @@ -10,9 +10,9 @@ LL | banana::Chaenomeles.pick() = help: items from traits can only be used if the trait is in scope help: the following traits which provide `pick` are implemented but not in scope; perhaps you want to import one of them | -LL + use banana::Apple; +LL + use crate::banana::Apple; | -LL + use banana::Peach; +LL + use crate::banana::Peach; | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr b/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr index 5f5e4b7f47294..b172833f5ac7a 100644 --- a/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr +++ b/tests/ui/suggestions/trait-object-import-suggestion-on-method.unimported.stderr @@ -9,7 +9,7 @@ LL | arg.wait(); | help: another candidate was found in the following trait, perhaps add a `use` for it: | -LL + use private::Future; +LL + use crate::private::Future; | error: aborting due to 1 previous error diff --git a/tests/ui/suggestions/use-placement-typeck.fixed b/tests/ui/suggestions/use-placement-typeck.fixed index 753e47ba6b4d1..2ab00b28099a7 100644 --- a/tests/ui/suggestions/use-placement-typeck.fixed +++ b/tests/ui/suggestions/use-placement-typeck.fixed @@ -7,7 +7,7 @@ // of the file. #![allow(unused)] -use m::Foo; +use crate::m::Foo; fn main() { let s = m::S; s.abc(); //~ ERROR no method named `abc` diff --git a/tests/ui/suggestions/use-placement-typeck.stderr b/tests/ui/suggestions/use-placement-typeck.stderr index a5eb8ac7d0aa9..58d499a48582a 100644 --- a/tests/ui/suggestions/use-placement-typeck.stderr +++ b/tests/ui/suggestions/use-placement-typeck.stderr @@ -13,7 +13,7 @@ LL | pub struct S; = help: items from traits can only be used if the trait is in scope help: trait `Foo` which provides `abc` is implemented but not in scope; perhaps you want to import it | -LL + use m::Foo; +LL + use crate::m::Foo; | error: aborting due to 1 previous error diff --git a/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr index 41827953bb796..412acca28e9ce 100644 --- a/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr +++ b/tests/ui/traits/block-scoped-trait-import-issue-134146.stderr @@ -8,7 +8,7 @@ LL | ().hello(); | ^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = help: trait `main::Hello` which provides `hello` is implemented but not reachable + = help: trait `crate::main::Hello` which provides `hello` is implemented but not reachable error[E0599]: no method named `nested` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:30:8 @@ -20,7 +20,7 @@ LL | ().nested(); | ^^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = help: trait `nested_module::inner::Nested` which provides `nested` is implemented but not reachable + = help: trait `crate::nested_module::inner::Nested` which provides `nested` is implemented but not reachable error[E0599]: no method named `in_const` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:42:8 @@ -32,7 +32,7 @@ LL | ().in_const(); | ^^^^^^^^ method not found in `()` | = help: items from traits can only be used if the trait is in scope - = help: trait `_::InConst` which provides `in_const` is implemented but not reachable + = help: trait `crate::_::InConst` which provides `in_const` is implemented but not reachable error[E0599]: no method named `several` found for unit type `()` in the current scope --> $DIR/block-scoped-trait-import-issue-134146.rs:57:8 @@ -42,8 +42,8 @@ LL | ().several(); | = help: items from traits can only be used if the trait is in scope = help: the following traits which provide `several` are implemented but not reachable: - multiple_candidates::First - multiple_candidates::Second + crate::multiple_candidates::First + crate::multiple_candidates::Second error: aborting due to 4 previous errors diff --git a/tests/ui/traits/issue-35869.stderr b/tests/ui/traits/issue-35869.stderr index 73cf961785433..98cbd4650007b 100644 --- a/tests/ui/traits/issue-35869.stderr +++ b/tests/ui/traits/issue-35869.stderr @@ -33,7 +33,7 @@ LL | fn bar(_: Option); help: change the parameter type to match the trait | LL - fn bar(_: Option) {} -LL + fn bar(_: Option) {} +LL + fn bar(_: std::option::Option) {} | error[E0053]: method `baz` has an incompatible type for trait diff --git a/tests/ui/traits/item-privacy.stderr b/tests/ui/traits/item-privacy.stderr index 7b199542c961e..9b831d3fca594 100644 --- a/tests/ui/traits/item-privacy.stderr +++ b/tests/ui/traits/item-privacy.stderr @@ -8,7 +8,7 @@ LL | S.a(); | ^ | = help: items from traits can only be used if the trait is implemented and in scope - = help: trait `method::A` which provides `a` is implemented but not reachable + = help: trait `crate::method::A` which provides `a` is implemented but not reachable help: there is a method `b` with a similar name | LL - S.a(); @@ -30,7 +30,7 @@ LL | S.b(); = help: items from traits can only be used if the trait is in scope help: trait `B` which provides `b` is implemented but not in scope; perhaps you want to import it | -LL + use method::B; +LL + use crate::method::B; | help: there is a method `c` with a similar name | @@ -57,7 +57,7 @@ LL | S::a(&S); | ^ associated function or constant not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = help: trait `method::A` which provides `a` is implemented but not reachable + = help: trait `crate::method::A` which provides `a` is implemented but not reachable help: there is an associated constant `B` with a similar name --> $DIR/item-privacy.rs:30:9 | @@ -81,7 +81,7 @@ LL | const B: u8 = 0; | ^^^^^^^^^^^ help: trait `B` which provides `b` is implemented but not in scope; perhaps you want to import it | -LL + use method::B; +LL + use crate::method::B; | error[E0624]: method `a` is private @@ -103,7 +103,7 @@ LL | S::A; | ^ associated function or constant not found in `S` | = help: items from traits can only be used if the trait is implemented and in scope - = help: trait `assoc_const::A` which provides `A` is implemented but not reachable + = help: trait `crate::assoc_const::A` which provides `A` is implemented but not reachable help: there is an associated constant `B` with a similar name | LL - S::A; @@ -127,7 +127,7 @@ LL | fn b(&self) { } | ^^^^^^^^^^^ help: trait `B` which provides `B` is implemented but not in scope; perhaps you want to import it | -LL + use assoc_const::B; +LL + use crate::assoc_const::B; | error[E0038]: the trait `assoc_const::C` is not dyn compatible diff --git a/tests/ui/traits/method-private.stderr b/tests/ui/traits/method-private.stderr index 6e9b57bb69e1e..142272b01e6ce 100644 --- a/tests/ui/traits/method-private.stderr +++ b/tests/ui/traits/method-private.stderr @@ -10,7 +10,7 @@ LL | foo.method(); = help: items from traits can only be used if the trait is in scope help: trait `Bar` which provides `method` is implemented but not in scope; perhaps you want to import it | -LL + use inner::Bar; +LL + use crate::inner::Bar; | error: aborting due to 1 previous error diff --git a/tests/ui/traits/nested-mod-trait-method-lookup-leak-10465.stderr b/tests/ui/traits/nested-mod-trait-method-lookup-leak-10465.stderr index f08febe8cc5e8..c10f73bd7906c 100644 --- a/tests/ui/traits/nested-mod-trait-method-lookup-leak-10465.stderr +++ b/tests/ui/traits/nested-mod-trait-method-lookup-leak-10465.stderr @@ -7,7 +7,7 @@ LL | b.foo(); = help: items from traits can only be used if the trait is in scope help: trait `A` which provides `foo` is implemented but not in scope; perhaps you want to import it | -LL + use a::A; +LL + use crate::a::A; | error: aborting due to 1 previous error diff --git a/tests/ui/traits/wrong-mul-method-signature.stderr b/tests/ui/traits/wrong-mul-method-signature.stderr index c85775f48871d..bdfc4320631b0 100644 --- a/tests/ui/traits/wrong-mul-method-signature.stderr +++ b/tests/ui/traits/wrong-mul-method-signature.stderr @@ -23,7 +23,7 @@ LL | fn mul(self, s: f64) -> Vec2 { help: change the parameter type to match the trait | LL - fn mul(self, s: f64) -> Vec2 { -LL + fn mul(self, s: Vec2) -> Vec2 { +LL + fn mul(self, s: crate::Vec2) -> Vec2 { | error[E0053]: method `mul` has an incompatible type for trait diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr index 6e4e024ce691b..48fe7ba275fce 100644 --- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr +++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr @@ -17,7 +17,7 @@ LL | fn dont_define_this(_private: Private) {} help: change the parameter type to match the trait | LL - fn dont_define_this(private: MyPrivate) { -LL + fn dont_define_this(private: Private) { +LL + fn dont_define_this(private: crate::private::Private) { | error: aborting due to 1 previous error diff --git a/tests/ui/typeck/issue-43189.stderr b/tests/ui/typeck/issue-43189.stderr index 8432cbeca2a4b..b3f2d1e9aa661 100644 --- a/tests/ui/typeck/issue-43189.stderr +++ b/tests/ui/typeck/issue-43189.stderr @@ -12,7 +12,7 @@ LL | fn a(&self) {} = help: items from traits can only be used if the trait is in scope help: trait `A` which provides `a` is implemented but not in scope; perhaps you want to import it | -LL + use xcrate_issue_43189_b::xcrate_issue_43189_a::A; +LL + use crate::xcrate_issue_43189_b::xcrate_issue_43189_a::A; | error: aborting due to 1 previous error From 155f135269a07dcf6e43da83466b2fe0162db173 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 15:52:02 +0200 Subject: [PATCH 0547/1309] that made table much too wide Made it easy to miss the last column --- src/doc/rustc-dev-guide/src/appendix/code-index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/src/appendix/code-index.md b/src/doc/rustc-dev-guide/src/appendix/code-index.md index 1808a8e000c32..351be5e39f921 100644 --- a/src/doc/rustc-dev-guide/src/appendix/code-index.md +++ b/src/doc/rustc-dev-guide/src/appendix/code-index.md @@ -23,7 +23,7 @@ Item | Kind | Short description | Chapter | `SourceFile` | struct | Part of the `SourceMap`. Maps AST nodes to their source code for a single source file. Was previously called FileMap | [The parser] | [compiler/rustc_span/src/lib.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.SourceFile.html) `SourceMap` | struct | Maps AST nodes to their source code. It is composed of `SourceFile`s. Was previously called CodeMap | [The parser] | [compiler/rustc_span/src/source_map.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/source_map/struct.SourceMap.html) `Span` | struct | A location in the user's source code, used for error reporting primarily | [Emitting Diagnostics] | [compiler/rustc_span/src/span_encoding.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_span/struct.Span.html) -`rustc_ast::token_stream::TokenStream` | struct | An abstract sequence of tokens, organized into `TokenTree`s | [The parser], [Macro expansion] | [compiler/rustc_ast/src/tokenstream.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/struct.TokenStream.html) +`TokenStream` | struct | An abstract sequence of tokens, organized into `TokenTree`s | [The parser], [Macro expansion] | [compiler/rustc_ast/src/tokenstream.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_ast/tokenstream/struct.TokenStream.html) `TraitDef` | struct | This struct contains a trait's definition with type information | [The `ty` modules] | [compiler/rustc_middle/src/ty/trait_def.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/trait_def/struct.TraitDef.html) `TraitRef` | struct | The combination of a trait and its input types (e.g. `P0: Trait`) | [Trait Solving: Goals and Clauses] | [compiler/rustc_middle/src/ty/sty.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/type.TraitRef.html) `Ty<'tcx>` | struct | This is the internal representation of a type used for type checking | [Type checking] | [compiler/rustc_middle/src/ty/mod.rs](https://doc.rust-lang.org/nightly/nightly-rustc/rustc_middle/ty/struct.Ty.html) From 9acb7866d472c7055eabef228ce961c821251719 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 21 Sep 2026 10:16:30 -0400 Subject: [PATCH 0548/1309] rustc_codegen_llvm: catch up with LLVM 24 on wasm exceptions LLVM 24 removed the -wasm-enable-eh option in favor of relying on TargetMachine.Options.ExceptionModel == Wasm. We were already setting ExceptionModel to Wasm on LLVM 24 in PassWrapper.cpp for wasm targets so this is a no-op on LLVM 24. Further, we already implied the -wasm-enable-eh flag on LLVM 23, so the explicit pass in wasm-exceptions-nostd was redundant and can be safely dropped. --- compiler/rustc_codegen_llvm/src/llvm_util.rs | 2 +- tests/run-make/wasm-exceptions-nostd/rmake.rs | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs index 718a500a9abec..e9d660b42bd9f 100644 --- a/compiler/rustc_codegen_llvm/src/llvm_util.rs +++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs @@ -127,7 +127,7 @@ unsafe fn configure_llvm(sess: &EarlySession) { } } - if wants_wasm_eh(&sess.target) { + if get_version() < (24, 0, 0) && wants_wasm_eh(&sess.target) { add("-wasm-enable-eh", false); } diff --git a/tests/run-make/wasm-exceptions-nostd/rmake.rs b/tests/run-make/wasm-exceptions-nostd/rmake.rs index e43d6bcd02b80..87eb5d501da44 100644 --- a/tests/run-make/wasm-exceptions-nostd/rmake.rs +++ b/tests/run-make/wasm-exceptions-nostd/rmake.rs @@ -10,7 +10,6 @@ fn main() { .input(Path::new("src").join("lib.rs")) .target("wasm32-unknown-unknown") .panic("unwind") - .arg("-Cllvm-args=-wasm-enable-eh") .arg("-Ctarget-feature=+exception-handling") .run(); From 286e3c339ee874b2549825fb10caa21fcfe51422 Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Wed, 16 Sep 2026 14:50:31 +0200 Subject: [PATCH 0549/1309] Expand docs on `rustc_abi::Variants` This information is scattered throughout the comments at the use sites. I thought I'd consolidate it. --- compiler/rustc_abi/src/lib.rs | 32 ++++++++++++++++++++++++-------- 1 file changed, 24 insertions(+), 8 deletions(-) diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs index b056fdc73d40b..774b597a73299 100644 --- a/compiler/rustc_abi/src/lib.rs +++ b/compiler/rustc_abi/src/lib.rs @@ -2005,24 +2005,40 @@ impl BackendRepr { } } +/// Describes the variants of a type. // NOTE: This struct is generic over the FieldIdx and VariantIdx for rust-analyzer usage. #[derive(PartialEq, Eq, Hash, Clone, Debug)] #[cfg_attr(feature = "nightly", derive(StableHash))] pub enum Variants { - /// A type with no valid variants. Must be uninhabited. + /// The type has no valid variants. Must be uninhabited. + /// + /// This is the case for: + /// 1. enums with no inhabited variants + /// 2. the never type Empty, - /// Single enum variants, structs/tuples, unions, and all non-ADTs. + /// The type has a single valid variant. + /// + /// This is the case for: + /// 1. enums with a single inhabited variant + /// 2. structs, unions, and non-ADTs (except coroutines; see below), + /// as those can't have multiple variants Single { - /// Always `0` for types that cannot have multiple variants. + /// - for case 1, this is the index of the inhabited variant + /// - for case 2, this is always `0` (a dummy value) index: VariantIdx, }, - /// Enum-likes with more than one variant: each variant comes with - /// a *discriminant* (usually the same as the variant index but the user can - /// assign explicit discriminant values). That discriminant is encoded - /// as a *tag* on the machine. The layout of each variant is - /// a struct, and they all have space reserved for the tag. + /// The type has multiple valid variants. + /// + /// This is the case for: + /// 1. enums with multiple inhabited variants + /// 2. coroutines + /// + /// Each variant comes with a *discriminant* (usually the same as the + /// variant index but the user can assign explicit discriminant values). + /// That discriminant is encoded as a *tag* on the machine. The layout of + /// each variant is a struct, and they all have space reserved for the tag. /// For enums, the tag is the sole field of the layout. Multiple { tag: Scalar, From be8e59313be41866df82126281a5c3479cb00970 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 16:50:34 +0200 Subject: [PATCH 0550/1309] "*. does not indicate a list element --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 742671ee7b1dd..2d7fd26023e20 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -24,7 +24,7 @@ static REGEX_IGNORE_END: LazyLock = static REGEX_IGNORE_LINK_TARGETS: LazyLock = LazyLock::new(|| Regex::new(r"^\[.+\]: ").unwrap()); static REGEX_SPLIT: LazyLock = - LazyLock::new(|| Regex::new(r"([^\.\d\-\*]\.|[^r\~]\?|!)\s").unwrap()); + LazyLock::new(|| Regex::new(r"([^\.\d\-]\.|[^r\~]\?|!)\s").unwrap()); // list elements, numbered (1.) or not (- and *) static REGEX_LIST_ENTRY: LazyLock = LazyLock::new(|| Regex::new(r"^\s*(\d\.|\-|\*|\d\))\s+").unwrap()); @@ -385,7 +385,6 @@ encountering a cycle doesn't mean that we would get an infinite proof tree. } #[test] -#[ignore] fn should_split() { let original = "the queries that we do, as well as the **query DAG**. The"; let expected = "the queries that we do, as well as the **query DAG**.\nThe\n"; From c18a8e5975955dd8aafdbe0937cca8fafb4b8ab0 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 16:51:35 +0200 Subject: [PATCH 0551/1309] sembr src/ty-fold.md --- src/doc/rustc-dev-guide/src/ty-fold.md | 65 ++++++++++++++------------ 1 file changed, 36 insertions(+), 29 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-fold.md b/src/doc/rustc-dev-guide/src/ty-fold.md index bf0a51e6b7cfb..66dfc648e97c4 100644 --- a/src/doc/rustc-dev-guide/src/ty-fold.md +++ b/src/doc/rustc-dev-guide/src/ty-fold.md @@ -7,13 +7,11 @@ to find any usages of the bound vars in order to replace them. Binders can wrap an arbitrary Rust type `T`, not just a `Ty`. So, how do we implement the `instantiate` methods on the `Early/Binder` types? -The answer is a couple of traits: -[`TypeFoldable`] -and -[`TypeFolder`]. +The answer is a couple of traits: [`TypeFoldable`] +and [`TypeFolder`]. -- `TypeFoldable` is implemented by types that embed type information. It allows you to recursively - process the contents of the `TypeFoldable` and do stuff to them. +- `TypeFoldable` is implemented by types that embed type information. + It allows you to recursively process the contents of the `TypeFoldable` and do stuff to them. - `TypeFolder` defines what you want to do with the types you encounter while processing the `TypeFoldable`. @@ -38,8 +36,10 @@ So to reiterate: In the case of `subst`, we can see that it is implemented as a `TypeFolder`: [`ArgFolder`]. Looking at its implementation, we see where the actual substitutions are happening. -However, you might also notice that the implementation calls this `super_fold_with` method. What is -that? It is a method of `TypeFoldable`. Consider the following `TypeFoldable` type `MyFoldable`: +However, you might also notice that the implementation calls this `super_fold_with` method. +What is that? +It is a method of `TypeFoldable`. +Consider the following `TypeFoldable` type `MyFoldable`: ```rust,ignore struct MyFoldable<'tcx> { @@ -49,12 +49,13 @@ struct MyFoldable<'tcx> { ``` The `TypeFolder` can call `super_fold_with` on `MyFoldable` if it just wants to replace some of the -fields of `MyFoldable` with new values. If it instead wants to replace the whole `MyFoldable` with a -different one, it would call `fold_with` instead (a different method on `TypeFoldable`). +fields of `MyFoldable` with new values. +If it instead wants to replace the whole `MyFoldable` with a different one, +it would call `fold_with` instead (a different method on `TypeFoldable`). In almost all cases, we don’t want to replace the whole struct; we only want to replace `ty::Ty`s in -the struct, so usually we call `super_fold_with`. A typical implementation that `MyFoldable` could -have might do something like this: +the struct, so usually we call `super_fold_with`. +A typical implementation that `MyFoldable` could have might do something like this: ```rust,ignore my_foldable: MyFoldable<'tcx> @@ -72,24 +73,30 @@ impl TypeFoldable for MyFoldable { } ``` -Notice that here, we implement `super_fold_with` to go over the fields of `MyFoldable` and call -`fold_with` on *them*. That is, a folder may replace `def_id` and `ty`, but not the whole -`MyFoldable` struct. - -Here is another example to put things together: suppose we have a type like `Vec>`. The -`ty::Ty` would look like: `Adt(Vec, &[Adt(Vec, &[Param(X)])])`. If we want to do `subst(X => u32)`, -then we would first look at the overall type. We would see that there are no substitutions to be -made at the outer level, so we would descend one level and look at `Adt(Vec, &[Param(X)])`. There -are still no substitutions to be made here, so we would descend again. Now we are looking at -`Param(X)`, which can be substituted, so we replace it with `u32`. We can’t descend any more, so we -are done, and the overall result is `Adt(Vec, &[Adt(Vec, &[u32])])`. - -One last thing to mention: often when folding over a `TypeFoldable`, we don’t want to change most -things. We only want to do something when we reach a type. That means there may be a lot of +Notice that here, +we implement `super_fold_with` to go over the fields of `MyFoldable` and call `fold_with` on *them*. +That is, a folder may replace `def_id` and `ty`, but not the whole `MyFoldable` struct. + +Here is another example to put things together: suppose we have a type like `Vec>`. +The `ty::Ty` would look like: `Adt(Vec, &[Adt(Vec, &[Param(X)])])`. +If we want to do `subst(X => u32)`, +then we would first look at the overall type. +We would see that there are no substitutions to be made at the outer level, +so we would descend one level and look at `Adt(Vec, &[Param(X)])`. +There are still no substitutions to be made here, so we would descend again. +Now we are looking at `Param(X)`, which can be substituted, so we replace it with `u32`. +We can’t descend any more, so we are done, +and the overall result is `Adt(Vec, &[Adt(Vec, &[u32])])`. + +One last thing to mention: often when folding over a `TypeFoldable`, +we don’t want to change most things. +We only want to do something when we reach a type. +That means there may be a lot of `TypeFoldable` types whose implementations basically just forward to their fields’ `TypeFoldable` -implementations. Such implementations of `TypeFoldable` tend to be pretty tedious to write by hand. -For this reason, there is a `derive` macro that allows you to `#![derive(TypeFoldable)]`. It is -defined [here]. +implementations. +Such implementations of `TypeFoldable` tend to be pretty tedious to write by hand. +For this reason, there is a `derive` macro that allows you to `#![derive(TypeFoldable)]`. +It is defined [here]. **`subst`** In the case of substitutions the [actual folder] is going to be doing the indexing we’ve already mentioned. From db6e110a114382fd2f1912354272c2f51d01ddca Mon Sep 17 00:00:00 2001 From: Shunpoco Date: Sun, 19 Oct 2025 10:03:06 +0100 Subject: [PATCH 0552/1309] visit_nested_body and visit_fn for LateLint should return earlier if typeck is tainted We started to check typeck result's tainted_by_errors in check_pat for LateLint, But ideally the check should be in a better place which all lints profit from it. --- compiler/rustc_lint/src/builtin.rs | 5 +---- compiler/rustc_lint/src/late.rs | 21 +++++++++++++++++-- tests/crashes/138361.rs | 6 ------ ...ng-constant-evaluation-cause-dead-code.rs} | 0 ...onstant-evaluation-cause-dead-code.stderr} | 4 ++-- ...ng-constant-evaluation-cause-ice-in-sty.rs | 5 +++++ ...onstant-evaluation-cause-ice-in-sty.stderr | 17 +++++++++++++++ 7 files changed, 44 insertions(+), 14 deletions(-) delete mode 100644 tests/crashes/138361.rs rename tests/ui/consts/{do-not-ice-long-constant-evaluation-in-for-loop.rs => long-constant-evaluation-cause-dead-code.rs} (100%) rename tests/ui/consts/{do-not-ice-long-constant-evaluation-in-for-loop.stderr => long-constant-evaluation-cause-dead-code.stderr} (78%) create mode 100644 tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.rs create mode 100644 tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.stderr diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index 2d571d8b8e13d..d4f213833aa48 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -148,10 +148,7 @@ declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]); impl<'tcx> LateLintPass<'tcx> for NonShorthandFieldPatterns { fn check_pat(&mut self, cx: &LateContext<'_>, pat: &hir::Pat<'_>) { - // The result shouldn't be tainted, otherwise it will cause ICE. - if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind - && cx.typeck_results().tainted_by_errors.is_none() - { + if let PatKind::Struct(ref qpath, field_pats, _) = pat.kind { let variant = cx .typeck_results() .pat_ty(pat) diff --git a/compiler/rustc_lint/src/late.rs b/compiler/rustc_lint/src/late.rs index ac185c65aa127..93ce4118c0ab7 100644 --- a/compiler/rustc_lint/src/late.rs +++ b/compiler/rustc_lint/src/late.rs @@ -99,7 +99,15 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas // The body and typeck results are also set in `visit_fn`. // Only fetch the results if this is for a new body. if old_enclosing_body != Some(body_id) && !self.actually_rustdoc { - self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id)); + let typeck_results = self.context.tcx.typeck_body(body_id); + + // To avoid ICE, skip visiting the body if the typeck_results is tainted. + if typeck_results.tainted_by_errors.is_some() { + self.context.enclosing_body = old_enclosing_body; + self.context.typeck_results = old_typeck_results; + return; + } + self.context.typeck_results = Some(typeck_results); } let body = self.context.tcx.hir_body(body_id); @@ -189,7 +197,16 @@ impl<'tcx, T: LateLintPass<'tcx>> hir_visit::Visitor<'tcx> for LateContextAndPas let old_enclosing_body = self.context.enclosing_body.replace(body_id); let old_typeck_results = self.context.typeck_results; if !self.actually_rustdoc { - self.context.typeck_results = Some(self.context.tcx.typeck_body(body_id)); + let typeck_results = self.context.tcx.typeck_body(body_id); + + // To avoid ICE, skip visiting the body if the typeck_results is tainted. + if typeck_results.tainted_by_errors.is_some() { + self.context.enclosing_body = old_enclosing_body; + self.context.typeck_results = old_typeck_results; + return; + } + + self.context.typeck_results = Some(typeck_results); } let body = self.context.tcx.hir_body(body_id); lint_callback!(self, check_fn, fk, decl, body, span, id); diff --git a/tests/crashes/138361.rs b/tests/crashes/138361.rs deleted file mode 100644 index 8661ed374744a..0000000000000 --- a/tests/crashes/138361.rs +++ /dev/null @@ -1,6 +0,0 @@ -//@ known-bug: #138361 - -fn main() { - [0; loop{}]; - std::mem::transmute(4) -} diff --git a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.rs b/tests/ui/consts/long-constant-evaluation-cause-dead-code.rs similarity index 100% rename from tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.rs rename to tests/ui/consts/long-constant-evaluation-cause-dead-code.rs diff --git a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr b/tests/ui/consts/long-constant-evaluation-cause-dead-code.stderr similarity index 78% rename from tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr rename to tests/ui/consts/long-constant-evaluation-cause-dead-code.stderr index c28f37bc16705..08160f8c78166 100644 --- a/tests/ui/consts/do-not-ice-long-constant-evaluation-in-for-loop.stderr +++ b/tests/ui/consts/long-constant-evaluation-cause-dead-code.stderr @@ -1,5 +1,5 @@ error: constant evaluation is taking a long time - --> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:10:14 + --> $DIR/long-constant-evaluation-cause-dead-code.rs:10:14 | LL | [(); loop {}]; | ^^^^^^^ @@ -7,7 +7,7 @@ LL | [(); loop {}]; = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. If your compilation actually takes a long time, you can safely allow the lint help: the constant being evaluated - --> $DIR/do-not-ice-long-constant-evaluation-in-for-loop.rs:10:14 + --> $DIR/long-constant-evaluation-cause-dead-code.rs:10:14 | LL | [(); loop {}]; | ^^^^^^^ diff --git a/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.rs b/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.rs new file mode 100644 index 0000000000000..04d0f7ee2de84 --- /dev/null +++ b/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.rs @@ -0,0 +1,5 @@ +// The test confirms ICE-138361 is fixed. +fn main() { + [0; loop{}]; //~ ERROR constant evaluation is taking a long time + std::mem::transmute(4) +} diff --git a/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.stderr b/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.stderr new file mode 100644 index 0000000000000..58c62d61adaab --- /dev/null +++ b/tests/ui/consts/long-constant-evaluation-cause-ice-in-sty.stderr @@ -0,0 +1,17 @@ +error: constant evaluation is taking a long time + --> $DIR/long-constant-evaluation-cause-ice-in-sty.rs:3:7 + | +LL | [0; loop{}]; + | ^^^^^^ + | + = note: this lint makes sure the compiler doesn't get stuck due to infinite loops in const eval. + If your compilation actually takes a long time, you can safely allow the lint +help: the constant being evaluated + --> $DIR/long-constant-evaluation-cause-ice-in-sty.rs:3:7 + | +LL | [0; loop{}]; + | ^^^^^^ + = note: `#[deny(long_running_const_eval)]` on by default + +error: aborting due to 1 previous error + From 811fc1045f980ec53693b5f8343feb27ad71bdfd Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:18:23 +0200 Subject: [PATCH 0553/1309] improve ty-fold.md --- src/doc/rustc-dev-guide/src/ty-fold.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-fold.md b/src/doc/rustc-dev-guide/src/ty-fold.md index 66dfc648e97c4..81761252bca98 100644 --- a/src/doc/rustc-dev-guide/src/ty-fold.md +++ b/src/doc/rustc-dev-guide/src/ty-fold.md @@ -11,7 +11,7 @@ The answer is a couple of traits: [`TypeFoldable`] and [`TypeFolder`]. - `TypeFoldable` is implemented by types that embed type information. - It allows you to recursively process the contents of the `TypeFoldable` and do stuff to them. + It allows you to recursively process the contents of `TypeFoldable` and do stuff to them. - `TypeFolder` defines what you want to do with the types you encounter while processing the `TypeFoldable`. @@ -75,7 +75,7 @@ impl TypeFoldable for MyFoldable { Notice that here, we implement `super_fold_with` to go over the fields of `MyFoldable` and call `fold_with` on *them*. -That is, a folder may replace `def_id` and `ty`, but not the whole `MyFoldable` struct. +That is, a folder may replace `def_id` and `ty`, but not the whole `MyFoldable` struct. Here is another example to put things together: suppose we have a type like `Vec>`. The `ty::Ty` would look like: `Adt(Vec, &[Adt(Vec, &[Param(X)])])`. @@ -86,7 +86,7 @@ so we would descend one level and look at `Adt(Vec, &[Param(X)])`. There are still no substitutions to be made here, so we would descend again. Now we are looking at `Param(X)`, which can be substituted, so we replace it with `u32`. We can’t descend any more, so we are done, -and the overall result is `Adt(Vec, &[Adt(Vec, &[u32])])`. +and the overall result is `Adt(Vec, &[Adt(Vec, &[u32])])`. One last thing to mention: often when folding over a `TypeFoldable`, we don’t want to change most things. From f492cb98f367fb7f705054a7736fda06c30c3390 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:18:46 +0200 Subject: [PATCH 0554/1309] sembr src/building/suggested.md --- .../rustc-dev-guide/src/building/suggested.md | 144 +++++++++--------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index 01869dfdc3f75..a938008718148 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -5,14 +5,14 @@ Here are some suggestions to make your life easier. ## Installing a pre-push hook -CI will automatically fail your build if it doesn't pass `tidy`, our internal -tool for ensuring code quality. -If you'd like, you can install a [Git -hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that will +CI will automatically fail your build if it doesn't pass `tidy`, +our internal tool for ensuring code quality. +If you'd like, +you can install a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks) that will automatically run `./x test tidy` on each push, to ensure your code is up to par. If the hook fails then run `./x test tidy --bless` and commit the changes. -If you decide later that the pre-push behavior is undesirable, you can delete -the `pre-push` file in `.git/hooks`. +If you decide later that the pre-push behavior is undesirable, +you can delete the `pre-push` file in `.git/hooks`. A prebuilt git hook lives at [`src/etc/pre-push.sh`]. It can be copied into your `.git/hooks` folder as `pre-push` (without the `.sh` extension!). @@ -24,8 +24,8 @@ You can also install the hook as a step of running `./x setup`! When working on different tasks, you might need to switch between different bootstrap configurations. Sometimes you may want to keep an old configuration for future use. But saving raw config values in -random files and manually copying and pasting them can quickly become messy, especially if you have a -long history of different configurations. +random files and manually copying and pasting them can quickly become messy, +especially if you have a long history of different configurations. To simplify managing multiple configurations, you can create config extensions. @@ -65,8 +65,8 @@ Also, parent extensions always override the inner ones. Checking the "library" tree requires a stage1 compiler, which can be a heavy process on some computers. For this reason, bootstrap has a flag called `--skip-std-check-if-no-download-rustc` that skips checking the "library" tree if `rust.download-rustc` isn't available. -If you want to avoid putting a heavy load on your computer -with `rust-analyzer`, you can add the `--skip-std-check-if-no-download-rustc` flag to your `./x check` command in +If you want to avoid putting a heavy load on your computer with `rust-analyzer`, +you can add the `--skip-std-check-if-no-download-rustc` flag to your `./x check` command in the `rust-analyzer` configuration. ### Project-local rust-analyzer setup @@ -75,15 +75,15 @@ the `rust-analyzer` configuration. By default, `rust-analyzer` runs the `cargo check` and `rustfmt` commands, but you can override these commands to use more adapted versions of these tools when hacking on `rustc`. -With custom setup, `rust-analyzer` can use `./x check` -to check the sources, and the stage 0 rustfmt to format them. +With custom setup, `rust-analyzer` can use `./x check` to check the sources, +and the stage 0 rustfmt to format them. The default `rust-analyzer.check.overrideCommand` command line will check all the crates and tools in the repository. If you are working on a specific part, you can override the command to only check the part you are working on to save checking time. -For example, if you are working on the compiler, you can override -the command to `x check compiler --json-output` to only check the compiler part. +For example, if you are working on the compiler, +you can override the command to `x check compiler --json-output` to only check the compiler part. You can run `x check --help --verbose` to see the available parts. Running `./x setup editor` will prompt you to create a project-local LSP config @@ -97,12 +97,12 @@ it will use a separate build directory from manual command-line builds. You can override this your generated LSP config file if you want to save disk space. However, this is not recommended: -- Each build will lock the build directory and force the other to wait, so it - becomes impossible to run command-line builds while rust-analyzer is running +- Each build will lock the build directory and force the other to wait, + so it becomes impossible to run command-line builds while rust-analyzer is running commands in the background. - There is an increased risk of one of the builds deleting previously-built - artifacts due to conflicting compiler flags or other settings, forcing - additional rebuilds in some cases. + artifacts due to conflicting compiler flags or other settings, + forcing additional rebuilds in some cases. ### Visual Studio Code @@ -153,13 +153,13 @@ Steps for this can be [found here][r-a nvim lsp]. 2. Run `./x setup editor`, and select `vscode` to create a `.vscode/settings.json` file. `neoconf` is able to read and update rust-analyzer settings automatically when the project is opened when this file is detected. - Neovim does not expand VS Code's `${workspaceFolder}` variable, so replace each occurrence - in the generated file with the absolute path to your rust repository. + Neovim does not expand VS Code's `${workspaceFolder}` variable, + so replace each occurrence in the generated file with the absolute path to your rust repository. #### coc.nvim -If you're using `coc.nvim`, you can run `./x setup editor` and select `vim` to -create a `.vim/coc-settings.json`. +If you're using `coc.nvim`, +you can run `./x setup editor` and select `vim` to create a `.vim/coc-settings.json`. The settings can be edited with `:CocLocalConfig`. The recommended settings live at [`src/etc/rust_analyzer_settings.json`]. @@ -230,8 +230,8 @@ through [Eglot](https://www.gnu.org/software/emacs/manual/html_node/eglot/). Steps for setting up Eglot with rust-analyzer can be [found here](https://rust-analyzer.github.io/manual.html#eglot). Having set up Emacs & Eglot for Rust development in general, you can run -`./x setup editor` and select `emacs`, which will prompt you to create -`.dir-locals.el` with the recommended configuration for Eglot. +`./x setup editor` and select `emacs`, +which will prompt you to create `.dir-locals.el` with the recommended configuration for Eglot. The recommended settings live at [`src/etc/rust_analyzer_eglot.el`]. For more information on project-specific Eglot configuration, consult [the manual](https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dspecific-configuration.html). @@ -239,17 +239,17 @@ manual](https://www.gnu.org/software/emacs/manual/html_node/eglot/Project_002dsp ### Helix Helix comes with built-in LSP and rust-analyzer support. -It can be configured through `languages.toml`, as described -[here](https://docs.helix-editor.com/languages.html). -You can run `./x setup editor` and select `helix`, which will prompt you to -create `languages.toml` with the recommended configuration for Helix. +It can be configured through `languages.toml`, +as described [here](https://docs.helix-editor.com/languages.html). +You can run `./x setup editor` and select `helix`, +which will prompt you to create `languages.toml` with the recommended configuration for Helix. The recommended settings live at [`src/etc/rust_analyzer_helix.toml`]. ### Zed Zed comes with built-in LSP and rust-analyzer support. -It can be configured through `.zed/settings.json`, as described -[here](https://zed.dev/docs/configuring-languages). +It can be configured through `.zed/settings.json`, +as described [here](https://zed.dev/docs/configuring-languages). Selecting `zed` in `./x setup editor` will prompt you to create a `.zed/settings.json` file which will configure Zed with the recommended configuration. The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_zed.json`]. @@ -257,8 +257,8 @@ The recommended `rust-analyzer` settings live at [`src/etc/rust_analyzer_zed.jso ## Check, check, and check again When doing simple refactoring, it can be useful to run `./x check` continuously. -If you set up `rust-analyzer` as described above, this will be -done for you every time you save a file. +If you set up `rust-analyzer` as described above, +this will be done for you every time you save a file. Here you are just checking that the compiler can **build**, but often that is all you need (e.g., when renaming a method). @@ -268,8 +268,8 @@ In fact, it is sometimes useful to put off tests even when you are not 100% sure You can then keep building up refactoring commits and only run the tests at some later time. You can then use `git bisect` to track down **precisely** which commit caused the problem. A nice side-effect of this style -is that you are left with a fairly fine-grained set of commits at the end, all -of which build and pass tests. +is that you are left with a fairly fine-grained set of commits at the end, +all of which build and pass tests. This often helps reviewing. ## Configuring `rustup` to use nightly @@ -284,16 +284,16 @@ rustup override set nightly ``` Don't forget to do this for all directories you have [setup a worktree for]. -You may need to use the -pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. +You may need to use the pinned nightly version from `src/stage0`, +but often the normal `nightly` channel will work. -**Note** see [the section on vscode] for how to configure it with this real -rustfmt `x` uses, and [the section on rustup] for how to setup `rustup` +**Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, +and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler **Note** This does _not_ allow you to build `rustc` with cargo directly. -You still have to use `x` to work on the compiler or standard library, this just -lets you use `cargo fmt`. +You still have to use `x` to work on the compiler or standard library, +this just lets you use `cargo fmt`. [install a nightly toolchain]: https://rust-lang.github.io/rustup/concepts/channels.html?highlight=nightl#working-with-nightly-rust [setup a worktree for]: ./suggested.md#working-on-multiple-branches-at-the-same-time @@ -303,12 +303,12 @@ lets you use `cargo fmt`. ## Faster Builds with CI-rustc If you are not working on the compiler, you often don't need to build the compiler tree. -For example, you can skip building the compiler and only build the `library` tree or the -tools under `src/tools`. -To achieve that, you have to enable this by setting the `download-rustc` -option in your configuration. -This tells bootstrap to use the latest nightly compiler for `stage > 0` -steps, meaning it will have two precompiled compilers: stage0 compiler and `download-rustc` compiler +For example, +you can skip building the compiler and only build the `library` tree or the tools under `src/tools`. +To achieve that, +you have to enable this by setting the `download-rustc` option in your configuration. +This tells bootstrap to use the latest nightly compiler for `stage > 0` steps, +meaning it will have two precompiled compilers: stage0 compiler and `download-rustc` compiler for `stage > 0` steps. This way, it will never need to build the in-tree compiler. As a result, your build time will be significantly reduced by not building the in-tree compiler. @@ -330,15 +330,15 @@ The sequence of commands you want is as follows: As mentioned, the effect of `--keep-stage-std=1` is that we just _assume_ that the old standard library can be re-used. -If you are editing the compiler, this is -often true: you haven't changed the standard library, after all. -But sometimes, it's not true: for example, if you are editing the "metadata" part of -the compiler, which controls how the compiler encodes types and other states -into the `rlib` files, or if you are editing things that wind up in the metadata -(such as the definition of the MIR). - -That is, you might get weird behavior from a compile when using -`--keep-stage-std=1`, for example, strange [ICEs](../appendix/glossary.md#ice) or other panics. +If you are editing the compiler, this is often true: you haven't changed the standard library, +after all. +But sometimes, it's not true: for example, if you are editing the "metadata" part of the compiler, +which controls how the compiler encodes types and other states +into the `rlib` files, +or if you are editing things that wind up in the metadata (such as the definition of the MIR). + +That is, you might get weird behavior from a compile when using `--keep-stage-std=1`, +for example, strange [ICEs](../appendix/glossary.md#ice) or other panics. In that case, you should simply remove the `--keep-stage-std=1` from the command and rebuild. You can also use `--keep-stage-std=1` when running tests. @@ -363,17 +363,17 @@ incremental = true ``` Note that incremental compilation will use more disk space than usual. -If disk space is a concern for you, you might want to check the size of the `build` -directory from time to time. +If disk space is a concern for you, +you might want to check the size of the `build` directory from time to time. ## Fine-tuning optimizations Setting `optimize = false` makes the compiler too slow for tests. -However, to improve the test cycle, you can disable optimizations selectively only for the -crates you'll have to rebuild +However, to improve the test cycle, +you can disable optimizations selectively only for the crates you'll have to rebuild ([source](https://rust-lang.zulipchat.com/#narrow/stream/131828-t-compiler/topic/incremental.20compilation.20question/near/202712165)). -For example, when working on `rustc_mir_build`, the `rustc_mir_build` and -`rustc_driver` crates take the most time to incrementally rebuild. +For example, when working on `rustc_mir_build`, +the `rustc_mir_build` and `rustc_driver` crates take the most time to incrementally rebuild. You could therefore set the following in the root `Cargo.toml`: ```toml @@ -385,11 +385,11 @@ opt-level = 0 ## Working on multiple branches at the same time -Working on multiple branches in parallel can be a little annoying, since -building the compiler on one branch will cause the old build and the incremental +Working on multiple branches in parallel can be a little annoying, +since building the compiler on one branch will cause the old build and the incremental compilation cache to be overwritten. -One solution would be to have multiple -clones of the repository, but that would mean storing the Git metadata multiple +One solution would be to have multiple clones of the repository, +but that would mean storing the Git metadata multiple times, and having to update each clone individually. Fortunately, Git has a better solution called [worktrees]. @@ -403,8 +403,8 @@ They will still be cloned multiple times. [worktrees]: https://git-scm.com/docs/git-worktree -Given you are inside the root directory for your Rust repository, you can create -a "linked working tree" in a new "rust2" directory by running the following command: +Given you are inside the root directory for your Rust repository, +you can create a "linked working tree" in a new "rust2" directory by running the following command: ```bash git worktree add ../rust2 @@ -443,9 +443,9 @@ set up correctly. ### Note -Note that when using nix on a not-NixOS distribution, it may be necessary to set -**`build.patch-binaries-for-nix = true` in `bootstrap.toml`**. Bootstrap tries to detect -whether it's running in nix and enable patching automatically, but this +Note that when using nix on a not-NixOS distribution, +it may be necessary to set **`build.patch-binaries-for-nix = true` in `bootstrap.toml`**. +Bootstrap tries to detect whether it's running in nix and enable patching automatically, but this detection can have false negatives. You can also use your nix shell to manage `bootstrap.toml`: @@ -464,8 +464,8 @@ pkgs.mkShell { ## Shell Completions -If you use Bash, Zsh, Fish or PowerShell, you can find automatically-generated shell -completion scripts for `./x` in +If you use Bash, Zsh, Fish or PowerShell, +you can find automatically-generated shell completion scripts for `./x` in [`src/etc/completions`](https://github.com/rust-lang/rust/tree/HEAD/src/etc/completions). You can use `source ./src/etc/completions/x.` to load completions From b2894fa5270738af6ddc7dca355581de4ca16add Mon Sep 17 00:00:00 2001 From: Aleksey Kliger Date: Mon, 21 Sep 2026 11:24:39 -0400 Subject: [PATCH 0555/1309] ci: make musl.sh look for patches next to the script Instead of hardcoding the container layout assuming that the local patches are in /build, look for them next to the script. This helps downstream distros to run this script if their container layout is different and they don't put the musl working dir in /build. This might be an unexpected change for some dowstream distros that were using this script from another directory,but arranged for the patches to still be in `/build` --- src/ci/docker/scripts/musl.sh | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/ci/docker/scripts/musl.sh b/src/ci/docker/scripts/musl.sh index 370b243dd4551..2402ec6ae34bf 100644 --- a/src/ci/docker/scripts/musl.sh +++ b/src/ci/docker/scripts/musl.sh @@ -78,12 +78,14 @@ EOF # project, so we just apply them directly on top of the version we were distributing already. The # patches should be removed once we upgrade to musl >= 1.2.7. # + SCRIPT_DIR=$(cd -- "$(dirname -- "$0")" && pwd) + MUSL_PATCH_DIR="$SCRIPT_DIR" # Advisory: https://www.openwall.com/lists/oss-security/2026/04/09/19 # Patches: https://www.openwall.com/lists/musl/2026/04/03/2/1 - patch -p1 -d $MUSL Date: Fri, 11 Sep 2026 17:31:14 +0200 Subject: [PATCH 0556/1309] test(config): demonstrate `--config-path` searching behavior --- .../tools/rustfmt/.editorconfig | 0 .../tools/rustfmt/.gitattributes | 0 .../tools/rustfmt/.github}/FUNDING.yml | 0 .../rustfmt/.github}/ISSUE_TEMPLATE/bug.md | 0 .../ISSUE_TEMPLATE/feature-request.md | 0 .../rustfmt/.github}/ISSUE_TEMPLATE/ice.md | 0 .../.github}/ISSUE_TEMPLATE/regression.md | 0 .../rustfmt/.github}/pull_request_template.md | 0 .../rustfmt/.github}/workflows/check_diff.yml | 0 .../rustfmt/.github}/workflows/clippy.yml | 0 .../.github}/workflows/integration.yml | 0 .../.github}/workflows/rustdoc_check.yml | 0 .../tools/rustfmt/.github}/workflows/test.yml | 0 .../.github}/workflows/upload-assets.yml | 0 .gitignore => src/tools/rustfmt/.gitignore | 0 .../tools/rustfmt/CHANGELOG.md | 0 .../tools/rustfmt/CODE_OF_CONDUCT.md | 0 Cargo.lock => src/tools/rustfmt/Cargo.lock | 0 Cargo.toml => src/tools/rustfmt/Cargo.toml | 0 .../tools/rustfmt/Configurations.md | 0 .../tools/rustfmt/Contributing.md | 0 Design.md => src/tools/rustfmt/Design.md | 0 .../tools/rustfmt/LICENSE-APACHE | 0 LICENSE-MIT => src/tools/rustfmt/LICENSE-MIT | 0 .../tools/rustfmt/Processes.md | 0 README.md => src/tools/rustfmt/README.md | 0 .../tools/rustfmt/Subtree sync procedure.md | 0 atom.md => src/tools/rustfmt/atom.md | 0 .../tools/rustfmt/bootstrap.sh | 0 build.rs => src/tools/rustfmt/build.rs | 0 .../tools/rustfmt/check_diff}/.gitignore | 0 .../tools/rustfmt/check_diff}/Cargo.lock | 0 .../tools/rustfmt/check_diff}/Cargo.toml | 0 .../tools/rustfmt/check_diff}/src/lib.rs | 0 .../tools/rustfmt/check_diff}/src/main.rs | 0 .../check_diff}/tests/bash_commands.rs | 0 .../rustfmt/check_diff}/tests/check_diff.rs | 0 .../tools/rustfmt/check_diff}/tests/git.rs | 0 {ci => src/tools/rustfmt/ci}/Cargo.lock | 0 {ci => src/tools/rustfmt/ci}/Cargo.toml | 0 .../tools/rustfmt/ci}/src/build_and_test.rs | 0 .../rustfmt/ci}/src/clippy_config_check.rs | 0 {ci => src/tools/rustfmt/ci}/src/common.rs | 0 .../tools/rustfmt/ci}/src/integration.rs | 0 {ci => src/tools/rustfmt/ci}/src/main.rs | 0 .../rustfmt/config_proc_macro}/.gitignore | 0 .../rustfmt/config_proc_macro}/Cargo.lock | 0 .../rustfmt/config_proc_macro}/Cargo.toml | 0 .../rustfmt/config_proc_macro}/src/attrs.rs | 0 .../config_proc_macro}/src/config_type.rs | 0 .../config_proc_macro}/src/item_enum.rs | 0 .../config_proc_macro}/src/item_struct.rs | 0 .../rustfmt/config_proc_macro}/src/lib.rs | 0 .../rustfmt/config_proc_macro}/src/utils.rs | 0 .../rustfmt/config_proc_macro}/tests/smoke.rs | 0 {docs => src/tools/rustfmt/docs}/index.html | 0 intellij.md => src/tools/rustfmt/intellij.md | 0 .../tools/rustfmt/rust-toolchain | 0 .../tools/rustfmt/rustfmt.toml | 0 src/{ => tools/rustfmt/src}/attr.rs | 0 .../rustfmt/src}/attr/doc_comment.rs | 0 src/{ => tools/rustfmt/src}/bin/main.rs | 0 src/{ => tools/rustfmt/src}/cargo-fmt/main.rs | 0 .../src}/cargo-fmt/test/message_format.rs | 0 .../rustfmt/src}/cargo-fmt/test/mod.rs | 0 .../rustfmt/src}/cargo-fmt/test/targets.rs | 0 src/{ => tools/rustfmt/src}/chains.rs | 0 src/{ => tools/rustfmt/src}/closures.rs | 0 src/{ => tools/rustfmt/src}/comment.rs | 0 .../rustfmt/src}/config/config_type.rs | 0 .../rustfmt/src}/config/file_lines.rs | 0 src/{ => tools/rustfmt/src}/config/lists.rs | 0 .../rustfmt/src}/config/macro_names.rs | 0 src/{ => tools/rustfmt/src}/config/mod.rs | 0 src/{ => tools/rustfmt/src}/config/options.rs | 0 .../rustfmt/src}/config/style_edition.rs | 0 src/{ => tools/rustfmt/src}/coverage.rs | 0 src/{ => tools/rustfmt/src}/emitter.rs | 0 .../rustfmt/src}/emitter/checkstyle.rs | 0 .../rustfmt/src}/emitter/checkstyle/xml.rs | 0 src/{ => tools/rustfmt/src}/emitter/diff.rs | 0 src/{ => tools/rustfmt/src}/emitter/files.rs | 0 .../rustfmt/src}/emitter/files_with_backup.rs | 0 src/{ => tools/rustfmt/src}/emitter/json.rs | 0 .../rustfmt/src}/emitter/modified_lines.rs | 0 src/{ => tools/rustfmt/src}/emitter/stdout.rs | 0 src/{ => tools/rustfmt/src}/expr.rs | 0 .../rustfmt/src}/format-diff/main.rs | 0 .../src}/format-diff/test/bindgen.diff | 0 .../rustfmt/src}/format_report_formatter.rs | 0 src/{ => tools/rustfmt/src}/formatting.rs | 0 .../rustfmt/src}/formatting/generated.rs | 0 .../rustfmt/src}/formatting/newline_style.rs | 0 .../rustfmt/src}/git-rustfmt/main.rs | 0 src/{ => tools/rustfmt/src}/header.rs | 0 src/{ => tools/rustfmt/src}/ignore_path.rs | 0 src/{ => tools/rustfmt/src}/imports.rs | 0 src/{ => tools/rustfmt/src}/items.rs | 0 src/{ => tools/rustfmt/src}/lib.rs | 0 src/{ => tools/rustfmt/src}/lists.rs | 0 src/{ => tools/rustfmt/src}/macros.rs | 0 src/{ => tools/rustfmt/src}/matches.rs | 0 src/{ => tools/rustfmt/src}/missed_spans.rs | 0 src/{ => tools/rustfmt/src}/modules.rs | 0 .../rustfmt/src}/modules/visitor.rs | 0 src/{ => tools/rustfmt/src}/overflow.rs | 0 src/{ => tools/rustfmt/src}/pairs.rs | 0 .../rustfmt/src}/parse/macros/asm.rs | 0 .../rustfmt/src}/parse/macros/cfg_if.rs | 0 .../rustfmt/src}/parse/macros/cfg_select.rs | 0 .../rustfmt/src}/parse/macros/lazy_static.rs | 0 .../rustfmt/src}/parse/macros/mod.rs | 0 src/{ => tools/rustfmt/src}/parse/mod.rs | 0 src/{ => tools/rustfmt/src}/parse/parser.rs | 0 src/{ => tools/rustfmt/src}/parse/session.rs | 0 src/{ => tools/rustfmt/src}/patterns.rs | 0 src/{ => tools/rustfmt/src}/range.rs | 0 .../rustfmt/src}/release_channel.rs | 0 src/{ => tools/rustfmt/src}/reorder.rs | 0 src/{ => tools/rustfmt/src}/rewrite.rs | 0 src/{ => tools/rustfmt/src}/rustfmt_diff.rs | 0 src/{ => tools/rustfmt/src}/shape.rs | 0 src/{ => tools/rustfmt/src}/skip.rs | 0 src/{ => tools/rustfmt/src}/sort.rs | 0 src/{ => tools/rustfmt/src}/source_file.rs | 0 src/{ => tools/rustfmt/src}/source_map.rs | 0 src/{ => tools/rustfmt/src}/spanned.rs | 0 src/{ => tools/rustfmt/src}/stmt.rs | 0 src/{ => tools/rustfmt/src}/string.rs | 0 .../src}/test/configuration_snippet.rs | 0 src/{ => tools/rustfmt/src}/test/mod.rs | 0 .../rustfmt/src}/test/mod_resolver.rs | 0 src/{ => tools/rustfmt/src}/test/parser.rs | 0 src/{ => tools/rustfmt/src}/types.rs | 0 src/{ => tools/rustfmt/src}/utils.rs | 0 src/{ => tools/rustfmt/src}/vertical.rs | 0 src/{ => tools/rustfmt/src}/visitor.rs | 0 .../tools/rustfmt/tests}/cargo-fmt/main.rs | 0 .../divergent-crate-dir-names/Cargo.toml | 0 .../dependency-dir-name/Cargo.toml | 0 .../dependency-dir-name/src/lib.rs | 0 .../subdep-dir-name/Cargo.toml | 0 .../subdep-dir-name/src/lib.rs | 0 .../divergent-crate-dir-names/src/main.rs | 0 .../cargo-fmt/source/issue_3164/Cargo.toml | 0 .../cargo-fmt/source/issue_3164/src/main.rs | 0 .../cargo-fmt/source/issues_6517/Cargo.toml | 0 .../source/issues_6517/inner_bin/Cargo.toml | 0 .../source/issues_6517/inner_bin/src/main.rs | 0 .../source/issues_6517/inner_lib/Cargo.toml | 0 .../source/issues_6517/inner_lib/src/lib.rs | 0 .../workspaces/path-dep-above/e/Cargo.toml | 0 .../workspaces/path-dep-above/e/src/main.rs | 0 .../workspaces/path-dep-above/ws/Cargo.toml | 0 .../workspaces/path-dep-above/ws/a/Cargo.toml | 0 .../path-dep-above/ws/a/d/Cargo.toml | 0 .../path-dep-above/ws/a/d/f/Cargo.toml | 0 .../path-dep-above/ws/a/d/f/src/lib.rs | 0 .../path-dep-above/ws/a/d/src/lib.rs | 0 .../path-dep-above/ws/a/src/main.rs | 0 .../workspaces/path-dep-above/ws/b/Cargo.toml | 0 .../path-dep-above/ws/b/src/main.rs | 0 .../workspaces/path-dep-above/ws/c/Cargo.toml | 0 .../workspaces/path-dep-above/ws/c/src/lib.rs | 0 .../tests}/config/disable_all_formatting.toml | 0 .../rustfmt/tests}/config/issue-1111.toml | 0 .../rustfmt/tests}/config/issue-2641.toml | 0 .../rustfmt/tests}/config/issue-3779.toml | 0 .../rustfmt/tests}/config/issue-5801-v1.toml | 0 .../rustfmt/tests}/config/issue-5801-v2.toml | 0 .../rustfmt/tests}/config/issue-5816.toml | 0 .../rustfmt/tests}/config/issue-6302.toml | 0 .../tests/config/issue_4660/Cargo.lock | 7 ++++ .../tests/config/issue_4660/Cargo.toml | 2 ++ .../inner_bin/.rustfmt.unstable.toml | 1 + .../config/issue_4660/inner_bin/Cargo.toml | 6 ++++ .../config/issue_4660/inner_bin/src/main.rs | 1 + .../config/issue_4660/inner_lib/Cargo.toml | 6 ++++ .../config/issue_4660/inner_lib/rustfmt.toml | 1 + .../config/issue_4660/inner_lib/src/lib.rs | 1 + .../rustfmt/tests}/config/skip_children.toml | 0 .../rustfmt/tests}/config/small_tabs.toml | 0 .../just-style-edition/rustfmt.toml | 0 .../style-edition/just-version/rustfmt.toml | 0 .../style-edition/overrides/rustfmt.toml | 0 .../style-edition-and-edition/rustfmt.toml | 0 .../version-edition/rustfmt.toml | 0 .../rustfmt.toml | 0 .../version-style-edition/rustfmt.toml | 0 .../tests}/coverage/source/comments.rs | 0 .../tests}/coverage/target/comments.rs | 0 .../tests}/mod-resolver/issue-4874/bar/baz.rs | 0 .../tests}/mod-resolver/issue-4874/foo.rs | 0 .../tests}/mod-resolver/issue-4874/foo/qux.rs | 0 .../tests}/mod-resolver/issue-4874/main.rs | 0 .../tests}/mod-resolver/issue-5063/foo.rs | 0 .../mod-resolver/issue-5063/foo/bar/baz.rs | 0 .../tests}/mod-resolver/issue-5063/main.rs | 0 .../tests}/mod-resolver/issue-5167/src/a.rs | 0 .../mod-resolver/issue-5167/src/a/mod.rs | 0 .../tests}/mod-resolver/issue-5167/src/lib.rs | 0 .../tests}/mod-resolver/issue-5198/a.rs | 0 .../tests}/mod-resolver/issue-5198/lib.rs | 0 .../tests}/mod-resolver/issue-5198/lib/b.rs | 0 .../tests}/mod-resolver/issue-5198/lib/c/d.rs | 0 .../issue-5198/lib/c/d/explanation.txt | 0 .../mod-resolver/issue-5198/lib/c/d/f.rs | 0 .../mod-resolver/issue-5198/lib/c/d/g/mod.rs | 0 .../tests}/mod-resolver/issue-5198/lib/c/e.rs | 0 .../mod-resolver/issue-5198/lib/c/mod.rs | 0 .../issue-5198/lib/explanation.txt | 0 .../bad_path_attribute/lib.rs | 0 .../module-not-found/relative_module/a.rs | 0 .../module-not-found/relative_module/lib.rs | 0 .../module-not-found/sibling_module/lib.rs | 0 .../mod-resolver/skip-files-issue-5065/foo.rs | 0 .../skip-files-issue-5065/foo/bar/baz.rs | 0 .../skip-files-issue-5065/main.rs | 0 .../mod-resolver/skip-files-issue-5065/one.rs | 0 .../test-submodule-issue-5119/Cargo.toml | 0 .../test-submodule-issue-5119/src/lib.rs | 0 .../test-submodule-issue-5119/tests/test1.rs | 0 .../tests/test1/sub1.rs | 0 .../tests/test1/sub2.rs | 0 .../tests/test1/sub3/mod.rs | 0 .../tests/test1/sub3/sub4.rs | 0 .../tests}/parser/issue-4126/invalid.rs | 0 .../rustfmt/tests}/parser/issue-4126/lib.rs | 0 .../tools/rustfmt/tests}/parser/issue_4418.rs | 0 .../rustfmt/tests}/parser/stashed-diag.rs | 0 .../rustfmt/tests}/parser/stashed-diag2.rs | 0 .../parser/unclosed-delims/issue_4466.rs | 0 .../tools/rustfmt/tests}/rustfmt/main.rs | 35 +++++++++++++++++++ .../tools/rustfmt/tests}/source/5131_crate.rs | 0 .../rustfmt/tests}/source/5131_module.rs | 0 .../tools/rustfmt/tests}/source/5131_one.rs | 0 .../inner-block-doc-comment.rs | 0 .../naive-outer-block-comment.rs | 0 .../outer-block-doc-comment.rs | 0 .../rustc-sample-1.rs | 0 .../rustc-sample-2.rs | 0 .../source/alignment_2633/block_style.rs | 0 .../source/alignment_2633/visual_style.rs | 0 .../rustfmt/tests}/source/array_comment.rs | 0 .../arrow_in_single_comment.rs | 0 .../arrow_in_comments/multiple_arrows.rs | 0 .../tools/rustfmt/tests}/source/assignment.rs | 0 .../associated-types-bounds-wrapping.rs | 0 .../tests}/source/associated_type_bounds.rs | 0 .../rustfmt/tests}/source/async_block.rs | 0 .../tools/rustfmt/tests}/source/async_fn.rs | 0 .../tools/rustfmt/tests}/source/attrib.rs | 0 .../rustfmt/tests}/source/big-impl-block.rs | 0 .../rustfmt/tests}/source/big-impl-visual.rs | 0 .../rustfmt/tests}/source/binary-expr.rs | 0 .../source/binop-separator-back/bitwise.rs | 0 .../source/binop-separator-back/comp.rs | 0 .../source/binop-separator-back/logic.rs | 0 .../source/binop-separator-back/math.rs | 0 .../source/binop-separator-back/patterns.rs | 0 .../source/binop-separator-back/range.rs | 0 .../tests}/source/break-and-continue.rs | 0 .../tools/rustfmt/tests}/source/catch.rs | 0 .../source/cfg_if/detect/arch/aarch64.rs | 0 .../tests}/source/cfg_if/detect/arch/arm.rs | 0 .../tests}/source/cfg_if/detect/arch/mips.rs | 0 .../source/cfg_if/detect/arch/mips64.rs | 0 .../source/cfg_if/detect/arch/powerpc.rs | 0 .../source/cfg_if/detect/arch/powerpc64.rs | 0 .../tests}/source/cfg_if/detect/arch/x86.rs | 0 .../tests}/source/cfg_if/detect/bit.rs | 0 .../tests}/source/cfg_if/detect/cache.rs | 0 .../source/cfg_if/detect/error_macros.rs | 0 .../tests}/source/cfg_if/detect/mod.rs | 0 .../tests}/source/cfg_if/detect/os/aarch64.rs | 0 .../cfg_if/detect/os/freebsd/aarch64.rs | 0 .../source/cfg_if/detect/os/freebsd/arm.rs | 0 .../source/cfg_if/detect/os/freebsd/auxvec.rs | 0 .../source/cfg_if/detect/os/freebsd/mod.rs | 0 .../cfg_if/detect/os/freebsd/powerpc.rs | 0 .../source/cfg_if/detect/os/linux/aarch64.rs | 0 .../source/cfg_if/detect/os/linux/arm.rs | 0 .../source/cfg_if/detect/os/linux/auxvec.rs | 0 .../source/cfg_if/detect/os/linux/cpuinfo.rs | 0 .../source/cfg_if/detect/os/linux/mips.rs | 0 .../source/cfg_if/detect/os/linux/mod.rs | 0 .../source/cfg_if/detect/os/linux/powerpc.rs | 0 .../tests}/source/cfg_if/detect/os/other.rs | 0 .../tests}/source/cfg_if/detect/os/x86.rs | 0 .../tools/rustfmt/tests}/source/cfg_if/lib.rs | 0 .../tools/rustfmt/tests}/source/cfg_if/mod.rs | 0 .../rustfmt/tests}/source/cfg_mod/bar.rs | 0 .../source/cfg_mod/dir/dir1/dir2/wasm32.rs | 0 .../source/cfg_mod/dir/dir1/dir3/wasm32.rs | 0 .../rustfmt/tests}/source/cfg_mod/foo.rs | 0 .../rustfmt/tests}/source/cfg_mod/mod.rs | 0 .../rustfmt/tests}/source/cfg_mod/other.rs | 0 .../rustfmt/tests}/source/cfg_mod/wasm32.rs | 0 .../tools/rustfmt/tests}/source/cfg_select.rs | 0 .../source/cfg_select/format_me_please_1.rs | 0 .../source/cfg_select/format_me_please_2.rs | 0 .../source/cfg_select/format_me_please_3.rs | 0 .../source/cfg_select/format_me_please_4.rs | 0 .../rustfmt/tests}/source/cfg_select/lib.rs | 0 .../rustfmt/tests}/source/cfg_select/lib2.rs | 0 .../tests}/source/cfg_select_stable.rs | 0 .../source/chain_yield_with_comments.rs | 0 .../rustfmt/tests}/source/chains-visual.rs | 0 .../tools/rustfmt/tests}/source/chains.rs | 0 .../tests}/source/chains_with_comment.rs | 0 .../source/closure-block-inside-macro.rs | 0 .../tests}/source/closure-block-labels.rs | 0 .../tools/rustfmt/tests}/source/closure.rs | 0 .../tools/rustfmt/tests}/source/comment.rs | 0 .../tools/rustfmt/tests}/source/comment2.rs | 0 .../tools/rustfmt/tests}/source/comment3.rs | 0 .../tools/rustfmt/tests}/source/comment4.rs | 0 .../tools/rustfmt/tests}/source/comment5.rs | 0 .../tools/rustfmt/tests}/source/comment6.rs | 0 .../tests}/source/comment_crlf_newline.rs | 0 .../wrap-comments-not-normalized.rs | 0 .../comments-in-lists/wrap-comments-true.rs | 0 .../rustfmt/tests}/source/comments_unicode.rs | 0 .../configs/blank_lines_lower_bound/1.rs | 0 .../configs/blank_lines_upper_bound/1.rs | 0 .../configs/blank_lines_upper_bound/2.rs | 0 .../brace_style/fn_always_next_line.rs | 0 .../brace_style/fn_prefer_same_line.rs | 0 .../configs/brace_style/fn_same_line_where.rs | 0 .../brace_style/item_always_next_line.rs | 0 .../brace_style/item_prefer_same_line.rs | 0 .../brace_style/item_same_line_where.rs | 0 .../source/configs/chain_width/always.rs | 0 .../source/configs/chain_width/small.rs | 0 .../tests}/source/configs/chain_width/tiny.rs | 0 .../source/configs/comment_width/above.rs | 0 .../source/configs/comment_width/below.rs | 0 .../source/configs/comment_width/ignore.rs | 0 .../condense_wildcard_suffixes/false.rs | 0 .../condense_wildcard_suffixes/true.rs | 0 .../control_brace_style/always_next_line.rs | 0 .../control_brace_style/always_same_line.rs | 0 .../control_brace_style/closing_next_line.rs | 0 .../configs/disable_all_formatting/false.rs | 0 .../configs/disable_all_formatting/true.rs | 0 .../default-to-max.rs | 0 .../max-to-default.rs | 0 .../doc_comment_code_block_width/100.rs | 0 .../100_greater_max_width.rs | 0 .../doc_comment_code_block_width/50.rs | 0 .../configs/empty_item_single_line/false.rs | 0 .../configs/empty_item_single_line/true.rs | 0 .../enum_discrim_align_threshold/40.rs | 0 .../configs/error_on_line_overflow/false.rs | 0 .../float_literal_trailing_zero/always.rs | 0 .../if-no-postfix.rs | 0 .../float_literal_trailing_zero/never.rs | 0 .../configs/fn_params_layout/compressed.rs | 0 .../source/configs/fn_params_layout/tall.rs | 0 .../configs/fn_params_layout/vertical.rs | 0 .../fn_params_layout/vertical_style_2027.rs | 0 .../source/configs/fn_single_line/false.rs | 0 .../source/configs/fn_single_line/true.rs | 0 .../configs/force_explicit_abi/false.rs | 0 .../source/configs/force_explicit_abi/true.rs | 0 .../configs/force_multiline_block/false.rs | 0 .../configs/force_multiline_block/true.rs | 0 .../configs/format_generated_files/false.rs | 0 ...with_generated_marker_line_search_limit.rs | 0 .../false_with_marker_out_scope_size.rs | 0 .../false_with_zero_search_limit.rs | 0 .../configs/format_generated_files/true.rs | 0 .../true_with_marker_in_scope_size.rs | 0 .../true_with_marker_not_in_header.rs | 0 .../configs/format_macro_bodies/false.rs | 0 .../configs/format_macro_bodies/true.rs | 0 .../configs/format_macro_matchers/false.rs | 0 .../configs/format_macro_matchers/true.rs | 0 .../source/configs/format_strings/false.rs | 0 .../source/configs/format_strings/true.rs | 0 .../group_imports/One-merge_imports.rs | 0 .../configs/group_imports/One-nested.rs | 0 .../configs/group_imports/One-no_reorder.rs | 0 .../source/configs/group_imports/One.rs | 0 .../StdExternalCrate-merge_imports.rs | 0 .../group_imports/StdExternalCrate-nested.rs | 0 .../StdExternalCrate-no_reorder.rs | 0 .../StdExternalCrate-non_consecutive.rs | 0 .../configs/group_imports/StdExternalCrate.rs | 0 .../tests}/source/configs/hard_tabs/false.rs | 0 .../tests}/source/configs/hard_tabs/true.rs | 0 .../hex_literal_case/hex_literal_lower.rs | 0 .../hex_literal_case/hex_literal_preserve.rs | 0 .../hex_literal_case/hex_literal_upper.rs | 0 .../configs/imports_layout/merge_mixed.rs | 0 .../source/configs/indent_style/block_args.rs | 0 .../configs/indent_style/block_array.rs | 0 .../source/configs/indent_style/block_call.rs | 0 .../configs/indent_style/block_chain.rs | 0 .../configs/indent_style/block_generic.rs | 0 .../configs/indent_style/block_struct_lit.rs | 0 .../block_trailing_comma_call/one.rs | 0 .../block_trailing_comma_call/two.rs | 0 .../configs/indent_style/block_where_pred.rs | 0 .../source/configs/indent_style/default.rs | 0 .../source/configs/indent_style/rfc_where.rs | 0 .../configs/indent_style/visual_args.rs | 0 .../configs/indent_style/visual_array.rs | 0 .../configs/indent_style/visual_call.rs | 0 .../configs/indent_style/visual_chain.rs | 0 .../configs/indent_style/visual_generics.rs | 0 .../configs/indent_style/visual_struct_lit.rs | 0 .../indent_style/visual_trailing_comma.rs | 0 .../configs/indent_style/visual_where_pred.rs | 0 .../source/configs/match_arm_blocks/false.rs | 0 .../source/configs/match_arm_blocks/true.rs | 0 .../source/configs/match_arm_indent/attrs.rs | 0 .../source/configs/match_arm_indent/guards.rs | 0 .../configs/match_arm_indent/leading_pipes.rs | 0 .../source/configs/match_arm_indent/nested.rs | 0 .../configs/match_arm_indent/patterns.rs | 0 .../configs/match_arm_indent/unindent.rs | 0 .../configs/match_arm_leading_pipes/always.rs | 0 .../configs/match_arm_leading_pipes/never.rs | 0 .../match_arm_leading_pipes/preserve.rs | 0 .../match_block_trailing_comma/false.rs | 0 .../match_block_trailing_comma/true.rs | 0 .../source/configs/merge_derives/true.rs | 0 .../configs/normalize_comments/false.rs | 0 .../source/configs/normalize_comments/true.rs | 0 .../configs/normalize_doc_attributes/false.rs | 0 .../configs/normalize_doc_attributes/true.rs | 0 .../remove_nested_parens.rs | 0 .../configs/reorder_impl_items/false.rs | 0 .../source/configs/reorder_impl_items/true.rs | 0 .../source/configs/reorder_imports/false.rs | 0 .../source/configs/reorder_imports/true.rs | 0 .../configs/reorder_modules/dolor/mod.rs | 0 .../source/configs/reorder_modules/false.rs | 0 .../configs/reorder_modules/ipsum/mod.rs | 0 .../configs/reorder_modules/lorem/mod.rs | 0 .../source/configs/reorder_modules/sit/mod.rs | 0 .../source/configs/reorder_modules/true.rs | 0 .../short_array_element_width_threshold/10.rs | 0 .../short_array_element_width_threshold/20.rs | 0 .../greater_than_max_width.rs | 0 .../single_line_let_else_max_width/100.rs | 0 .../single_line_let_else_max_width/50.rs | 0 .../single_line_let_else_max_width/zero.rs | 0 .../source/configs/skip_children/foo/mod.rs | 0 .../source/configs/skip_children/true.rs | 0 .../source/configs/space_before_colon/true.rs | 0 .../configs/spaces_around_ranges/false.rs | 0 .../configs/spaces_around_ranges/true.rs | 0 .../struct_field_align_threshold/20.rs | 0 .../configs/struct_lit_single_line/false.rs | 0 .../style_edition/overflow_delim_expr_2015.rs | 0 .../style_edition/overflow_delim_expr_2024.rs | 0 .../tests}/source/configs/tab_spaces/2.rs | 0 .../tests}/source/configs/tab_spaces/4.rs | 0 .../source/configs/trailing_comma/always.rs | 0 .../source/configs/trailing_comma/never.rs | 0 .../source/configs/trailing_comma/vertical.rs | 0 .../type_punctuation_density/compressed.rs | 0 .../configs/type_punctuation_density/wide.rs | 0 .../configs/use_field_init_shorthand/false.rs | 0 .../configs/use_field_init_shorthand/true.rs | 0 .../configs/use_small_heuristics/default.rs | 0 .../configs/use_small_heuristics/max.rs | 0 .../configs/use_small_heuristics/off.rs | 0 .../source/configs/use_try_shorthand/false.rs | 0 .../source/configs/use_try_shorthand/true.rs | 0 .../source/configs/where_single_line/true.rs | 0 .../source/configs/wrap_comments/false.rs | 0 .../source/configs/wrap_comments/true.rs | 0 .../tests}/source/const-block-items.rs | 0 .../rustfmt/tests}/source/const_generics.rs | 0 .../control-brace-style-always-next-line.rs | 0 .../control-brace-style-always-same-line.rs | 0 .../tests}/source/default-field-values.rs | 0 .../rustfmt/tests}/source/direct_const_arg.rs | 0 .../tools/rustfmt/tests}/source/doc-attrib.rs | 0 .../tests}/source/doc-comment-with-example.rs | 0 .../tools/rustfmt/tests}/source/doc.rs | 0 .../tools/rustfmt/tests}/source/dyn_trait.rs | 0 .../else-if-brace-style-always-next-line.rs | 0 .../else-if-brace-style-always-same-line.rs | 0 .../else-if-brace-style-closing-next-line.rs | 0 .../source/empty-item-single-line-false.rs | 0 .../tools/rustfmt/tests}/source/empty_file.rs | 0 .../tools/rustfmt/tests}/source/enum.rs | 0 .../rustfmt/tests}/source/ergonomic_clones.rs | 0 .../rustfmt/tests}/source/existential_type.rs | 0 .../tools/rustfmt/tests}/source/expr-block.rs | 0 .../tests}/source/expr-overflow-delimited.rs | 0 .../tools/rustfmt/tests}/source/expr.rs | 0 .../tools/rustfmt/tests}/source/extern.rs | 0 .../tests}/source/extern_not_explicit.rs | 0 .../rustfmt/tests}/source/file-lines-1.rs | 0 .../rustfmt/tests}/source/file-lines-2.rs | 0 .../rustfmt/tests}/source/file-lines-3.rs | 0 .../rustfmt/tests}/source/file-lines-4.rs | 0 .../rustfmt/tests}/source/file-lines-5.rs | 0 .../rustfmt/tests}/source/file-lines-6.rs | 0 .../rustfmt/tests}/source/file-lines-7.rs | 0 .../rustfmt/tests}/source/file-lines-item.rs | 0 .../rustfmt/tests}/source/fn-custom-2.rs | 0 .../rustfmt/tests}/source/fn-custom-3.rs | 0 .../rustfmt/tests}/source/fn-custom-4.rs | 0 .../rustfmt/tests}/source/fn-custom-6.rs | 0 .../rustfmt/tests}/source/fn-custom-7.rs | 0 .../rustfmt/tests}/source/fn-custom-8.rs | 0 .../tools/rustfmt/tests}/source/fn-custom.rs | 0 .../tests}/source/fn-param-attributes.rs | 0 .../tools/rustfmt/tests}/source/fn-simple.rs | 0 .../source/fn-single-line/version_one.rs | 0 .../source/fn-single-line/version_two.rs | 0 .../tests}/source/fn_args_indent-block.rs | 0 .../tests}/source/fn_args_layout-vertical.rs | 0 .../tests}/source/frontmatter_compact.rs | 0 .../tests}/source/frontmatter_escaped.rs | 0 .../tests}/source/frontmatter_spaced.rs | 0 .../rustfmt/tests}/source/generic_static.rs | 0 .../tools/rustfmt/tests}/source/hard-tabs.rs | 0 .../tools/rustfmt/tests}/source/hello.rs | 0 .../tools/rustfmt/tests}/source/hello2.rs | 0 .../tests}/source/if_while_or_patterns.rs | 0 .../tests}/source/immovable_coroutines.rs | 0 .../rustfmt/tests}/source/impl-restriction.rs | 0 .../tools/rustfmt/tests}/source/impls.rs | 0 .../source/imports/imports-impl-only-use.rs | 0 .../imports-reorder-lines-and-items.rs | 0 .../source/imports/imports-reorder-lines.rs | 0 .../tests}/source/imports/imports-reorder.rs | 0 .../rustfmt/tests}/source/imports/imports.rs | 0 .../source/imports/imports_block_indent.rs | 0 .../imports/imports_granularity_crate.rs | 0 .../imports_granularity_default-with-dups.rs | 0 ...m-with-dups-StdExternalCrate-no-reorder.rs | 0 .../imports_granularity_item-with-dups.rs | 0 .../imports/imports_granularity_item.rs | 0 .../imports/imports_granularity_module.rs | 0 .../source/imports/imports_granularity_one.rs | 0 .../imports_raw_identifiers/version_One.rs | 0 .../imports_raw_identifiers/version_Two.rs | 0 .../invalid-rust-code-in-doc-comment.rs | 0 .../tools/rustfmt/tests}/source/issue-1021.rs | 0 .../tools/rustfmt/tests}/source/issue-1049.rs | 0 .../tools/rustfmt/tests}/source/issue-1111.rs | 0 .../tools/rustfmt/tests}/source/issue-1120.rs | 0 .../tools/rustfmt/tests}/source/issue-1124.rs | 0 .../tools/rustfmt/tests}/source/issue-1127.rs | 0 .../tools/rustfmt/tests}/source/issue-1158.rs | 0 .../tools/rustfmt/tests}/source/issue-1177.rs | 0 .../tools/rustfmt/tests}/source/issue-1192.rs | 0 .../rustfmt/tests}/source/issue-1210/a.rs | 0 .../rustfmt/tests}/source/issue-1210/b.rs | 0 .../rustfmt/tests}/source/issue-1210/c.rs | 0 .../rustfmt/tests}/source/issue-1210/d.rs | 0 .../rustfmt/tests}/source/issue-1210/e.rs | 0 .../tools/rustfmt/tests}/source/issue-1211.rs | 0 .../tools/rustfmt/tests}/source/issue-1216.rs | 0 .../tools/rustfmt/tests}/source/issue-1239.rs | 0 .../tools/rustfmt/tests}/source/issue-1278.rs | 0 .../tools/rustfmt/tests}/source/issue-1350.rs | 0 .../tools/rustfmt/tests}/source/issue-1366.rs | 0 .../tools/rustfmt/tests}/source/issue-1468.rs | 0 .../tools/rustfmt/tests}/source/issue-1693.rs | 0 .../tools/rustfmt/tests}/source/issue-1800.rs | 0 .../tools/rustfmt/tests}/source/issue-1914.rs | 0 .../tools/rustfmt/tests}/source/issue-2025.rs | 0 .../tools/rustfmt/tests}/source/issue-2111.rs | 0 .../tools/rustfmt/tests}/source/issue-2164.rs | 0 .../rustfmt/tests}/source/issue-2179/one.rs | 0 .../rustfmt/tests}/source/issue-2179/two.rs | 0 .../tools/rustfmt/tests}/source/issue-2256.rs | 0 .../tools/rustfmt/tests}/source/issue-2342.rs | 0 .../tools/rustfmt/tests}/source/issue-2445.rs | 0 .../tools/rustfmt/tests}/source/issue-2446.rs | 0 .../tools/rustfmt/tests}/source/issue-2479.rs | 0 .../rustfmt/tests}/source/issue-2482/a.rs | 0 .../rustfmt/tests}/source/issue-2482/b.rs | 0 .../rustfmt/tests}/source/issue-2482/c.rs | 0 .../tools/rustfmt/tests}/source/issue-2496.rs | 0 .../tools/rustfmt/tests}/source/issue-2520.rs | 0 .../tools/rustfmt/tests}/source/issue-2523.rs | 0 .../tools/rustfmt/tests}/source/issue-2582.rs | 0 .../tools/rustfmt/tests}/source/issue-2641.rs | 0 .../tools/rustfmt/tests}/source/issue-2644.rs | 0 .../tools/rustfmt/tests}/source/issue-2728.rs | 0 .../tools/rustfmt/tests}/source/issue-2761.rs | 0 .../tools/rustfmt/tests}/source/issue-2781.rs | 0 .../tools/rustfmt/tests}/source/issue-2794.rs | 0 .../tools/rustfmt/tests}/source/issue-2835.rs | 0 .../tools/rustfmt/tests}/source/issue-2863.rs | 0 .../tools/rustfmt/tests}/source/issue-2869.rs | 0 .../tools/rustfmt/tests}/source/issue-2896.rs | 0 .../tools/rustfmt/tests}/source/issue-2916.rs | 0 .../tests}/source/issue-2917/packed_simd.rs | 0 .../tools/rustfmt/tests}/source/issue-2922.rs | 0 .../rustfmt/tests}/source/issue-2927-2.rs | 0 .../tools/rustfmt/tests}/source/issue-2927.rs | 0 .../tools/rustfmt/tests}/source/issue-2930.rs | 0 .../tools/rustfmt/tests}/source/issue-2936.rs | 0 .../tools/rustfmt/tests}/source/issue-2955.rs | 0 .../tools/rustfmt/tests}/source/issue-2973.rs | 0 .../rustfmt/tests}/source/issue-2977/impl.rs | 0 .../rustfmt/tests}/source/issue-2977/trait.rs | 0 .../tools/rustfmt/tests}/source/issue-2985.rs | 0 .../tools/rustfmt/tests}/source/issue-2995.rs | 0 .../tools/rustfmt/tests}/source/issue-3029.rs | 0 .../tools/rustfmt/tests}/source/issue-3038.rs | 0 .../tools/rustfmt/tests}/source/issue-3049.rs | 0 .../tests}/source/issue-3055/original.rs | 0 .../tools/rustfmt/tests}/source/issue-3059.rs | 0 .../tools/rustfmt/tests}/source/issue-3066.rs | 0 .../tools/rustfmt/tests}/source/issue-3131.rs | 0 .../tools/rustfmt/tests}/source/issue-3153.rs | 0 .../tools/rustfmt/tests}/source/issue-3158.rs | 0 .../tools/rustfmt/tests}/source/issue-3194.rs | 0 .../tools/rustfmt/tests}/source/issue-3198.rs | 0 .../tests}/source/issue-3213/version_one.rs | 0 .../tests}/source/issue-3213/version_two.rs | 0 .../tools/rustfmt/tests}/source/issue-3217.rs | 0 .../rustfmt/tests}/source/issue-3227/two.rs | 0 .../tools/rustfmt/tests}/source/issue-3234.rs | 0 .../tools/rustfmt/tests}/source/issue-3241.rs | 0 .../rustfmt/tests}/source/issue-3253/bar.rs | 0 .../rustfmt/tests}/source/issue-3253/foo.rs | 0 .../rustfmt/tests}/source/issue-3253/lib.rs | 0 .../tests}/source/issue-3253/paths/bar_foo.rs | 0 .../source/issue-3253/paths/excluded.rs | 0 .../tests}/source/issue-3253/paths/foo_bar.rs | 0 .../tools/rustfmt/tests}/source/issue-3265.rs | 0 .../rustfmt/tests}/source/issue-3270/one.rs | 0 .../rustfmt/tests}/source/issue-3270/two.rs | 0 .../rustfmt/tests}/source/issue-3272/v1.rs | 0 .../rustfmt/tests}/source/issue-3272/v2.rs | 0 .../tests}/source/issue-3278/version_one.rs | 0 .../tests}/source/issue-3278/version_two.rs | 0 .../rustfmt/tests}/source/issue-3295/two.rs | 0 .../tools/rustfmt/tests}/source/issue-3302.rs | 0 .../tools/rustfmt/tests}/source/issue-3343.rs | 0 .../tools/rustfmt/tests}/source/issue-3423.rs | 0 .../rustfmt/tests}/source/issue-3434/lib.rs | 0 .../tests}/source/issue-3434/no_entry.rs | 0 .../source/issue-3434/not_skip_macro.rs | 0 .../tools/rustfmt/tests}/source/issue-3465.rs | 0 .../rustfmt/tests}/source/issue-3494/crlf.rs | 0 .../rustfmt/tests}/source/issue-3494/lf.rs | 0 .../tools/rustfmt/tests}/source/issue-3508.rs | 0 .../tools/rustfmt/tests}/source/issue-3515.rs | 0 .../tools/rustfmt/tests}/source/issue-3532.rs | 0 .../tests}/source/issue-3585/extern_crate.rs | 0 .../issue-3585/reorder_imports_disabled.rs | 0 .../issue-3585/reorder_imports_enabled.rs | 0 .../rustfmt/tests}/source/issue-3585/use.rs | 0 .../tools/rustfmt/tests}/source/issue-3636.rs | 0 .../tools/rustfmt/tests}/source/issue-3639.rs | 0 .../tools/rustfmt/tests}/source/issue-3651.rs | 0 .../rustfmt/tests}/source/issue-3665/lib.rs | 0 .../source/issue-3665/not_skip_attribute.rs | 0 .../tests}/source/issue-3665/sub_mod.rs | 0 .../tools/rustfmt/tests}/source/issue-3672.rs | 0 .../tools/rustfmt/tests}/source/issue-3675.rs | 0 .../rustfmt/tests}/source/issue-3701/one.rs | 0 .../rustfmt/tests}/source/issue-3701/two.rs | 0 .../tools/rustfmt/tests}/source/issue-3709.rs | 0 .../tools/rustfmt/tests}/source/issue-3740.rs | 0 .../tools/rustfmt/tests}/source/issue-3750.rs | 0 .../tools/rustfmt/tests}/source/issue-3751.rs | 0 .../rustfmt/tests}/source/issue-3779/ice.rs | 0 .../rustfmt/tests}/source/issue-3779/lib.rs | 0 .../tools/rustfmt/tests}/source/issue-3786.rs | 0 .../tools/rustfmt/tests}/source/issue-3787.rs | 0 .../tools/rustfmt/tests}/source/issue-3805.rs | 0 .../issue-3840/version-one_hard-tabs.rs | 0 .../issue-3840/version-one_soft-tabs.rs | 0 .../issue-3840/version-two_hard-tabs.rs | 0 .../issue-3840/version-two_soft-tabs.rs | 0 .../tools/rustfmt/tests}/source/issue-3984.rs | 0 .../issue-3987/format_macro_bodies_true.rs | 0 .../tools/rustfmt/tests}/source/issue-4018.rs | 0 .../rustfmt/tests}/source/issue-4036/one.rs | 0 .../rustfmt/tests}/source/issue-4036/three.rs | 0 .../rustfmt/tests}/source/issue-4036/two.rs | 0 .../tools/rustfmt/tests}/source/issue-4041.rs | 0 .../tools/rustfmt/tests}/source/issue-4079.rs | 0 .../tools/rustfmt/tests}/source/issue-4120.rs | 0 .../tools/rustfmt/tests}/source/issue-4243.rs | 0 .../tools/rustfmt/tests}/source/issue-4244.rs | 0 .../tools/rustfmt/tests}/source/issue-4245.rs | 0 .../tools/rustfmt/tests}/source/issue-4312.rs | 0 .../source/issue-4381/style_edition_2015.rs | 0 .../tools/rustfmt/tests}/source/issue-4382.rs | 0 .../tools/rustfmt/tests}/source/issue-4398.rs | 0 .../tools/rustfmt/tests}/source/issue-4427.rs | 0 .../tools/rustfmt/tests}/source/issue-447.rs | 0 .../tools/rustfmt/tests}/source/issue-4530.rs | 0 .../tools/rustfmt/tests}/source/issue-4577.rs | 0 .../tools/rustfmt/tests}/source/issue-4603.rs | 0 .../source/issue-4615/minimum_example.rs | 0 .../tools/rustfmt/tests}/source/issue-4643.rs | 0 .../tools/rustfmt/tests}/source/issue-4646.rs | 0 .../source/issue-4656/format_me_please.rs | 0 .../rustfmt/tests}/source/issue-4656/lib.rs | 0 .../rustfmt/tests}/source/issue-4656/lib2.rs | 0 .../rustfmt/tests}/source/issue-4689/one.rs | 0 .../rustfmt/tests}/source/issue-4689/two.rs | 0 .../rustfmt/tests}/source/issue-4791/buggy.rs | 0 .../source/issue-4791/trailing_comma.rs | 0 .../tools/rustfmt/tests}/source/issue-4808.rs | 0 .../rustfmt/tests}/source/issue-4816/lib.rs | 0 .../source/issue-4926/deeply_nested_struct.rs | 0 ...ply_nested_struct_with_long_field_names.rs | 0 .../deeply_nested_struct_with_many_fields.rs | 0 .../source/issue-4926/enum_struct_field.rs | 0 .../source/issue-4926/minimum_example.rs | 0 .../struct_with_long_field_names.rs | 0 .../issue-4926/struct_with_many_fields.rs | 0 .../source/issue-4984/minimum_example.rs | 0 .../source/issue-4984/multi_line_derive.rs | 0 .../issue-4984/multiple_comments_within.rs | 0 .../tools/rustfmt/tests}/source/issue-5011.rs | 0 .../tools/rustfmt/tests}/source/issue-5023.rs | 0 .../tools/rustfmt/tests}/source/issue-5030.rs | 0 .../multi-line_comment_with_trailing_comma.rs | 0 ...lti-line_comment_without_trailing_comma.rs | 0 ...single-line_comment_with_trailing_comma.rs | 0 ...gle-line_comment_without_trailing_comma.rs | 0 ..._nested_long_comment_wrap_comments_true.rs | 0 ..._long_itemized_block_wrap_comments_true.rs | 0 .../very_long_comment_wrap_comments_true.rs | 0 .../tools/rustfmt/tests}/source/issue-510.rs | 0 .../rustfmt/tests}/source/issue-5136-1.rs | 0 .../rustfmt/tests}/source/issue-5136-2.rs | 0 .../rustfmt/tests}/source/issue-5136-3.rs | 0 .../rustfmt/tests}/source/issue-5136-4.rs | 0 .../rustfmt/tests}/source/issue-5136-5.rs | 0 .../indented_itemized_markdown_blockquote.rs | 0 .../nested_itemized_markdown_blockquote.rs | 0 .../support_itemized_markdown_blockquote.rs | 0 .../tools/rustfmt/tests}/source/issue-5234.rs | 0 .../markdown_header_wrap_comments_false.rs | 0 .../markdown_header_wrap_comments_true.rs | 0 .../tools/rustfmt/tests}/source/issue-5260.rs | 0 .../source/issue-5270/merge_derives_true.rs | 0 .../tools/rustfmt/tests}/source/issue-539.rs | 0 .../tools/rustfmt/tests}/source/issue-5488.rs | 0 .../tools/rustfmt/tests}/source/issue-5586.rs | 0 .../rustfmt/tests}/source/issue-5655/one.rs | 0 .../rustfmt/tests}/source/issue-5655/two.rs | 0 .../tools/rustfmt/tests}/source/issue-5791.rs | 0 ...ute_unexpectedly_wraps_before_max_width.rs | 0 ...ent_unexpectedly_wraps_before_max_width.rs | 0 .../tools/rustfmt/tests}/source/issue-5835.rs | 0 .../tests}/source/issue-5852/default.rs | 0 .../tests}/source/issue-5852/horizontal.rs | 0 .../source/issue-5852/horizontal_vertical.rs | 0 .../tests}/source/issue-5852/issue_example.rs | 0 .../rustfmt/tests}/source/issue-5852/split.rs | 0 .../tests}/source/issue-5852/vertical.rs | 0 .../tools/rustfmt/tests}/source/issue-5935.rs | 0 .../rustfmt/tests}/source/issue-5987/two.rs | 0 .../rustfmt/tests}/source/issue-6059/repro.rs | 0 .../source/issue-6147/case_rustfmt_v1.rs | 0 .../source/issue-6147/case_rustfmt_v2.rs | 0 .../tests}/source/issue-6202/long_pat.rs | 0 .../tools/rustfmt/tests}/source/issue-6243.rs | 0 .../tools/rustfmt/tests}/source/issue-6333.rs | 0 .../tests}/source/issue-6561/trait-fn.rs | 0 .../tests}/source/issue-6561/variadic.rs | 0 .../tests}/source/issue-6607/fn-type.rs | 0 .../tests}/source/issue-6651/custom_width.rs | 0 .../tests}/source/issue-6651/default.rs | 0 .../tools/rustfmt/tests}/source/issue-6788.rs | 0 .../tools/rustfmt/tests}/source/issue-6795.rs | 0 .../tools/rustfmt/tests}/source/issue-6825.rs | 0 .../tools/rustfmt/tests}/source/issue-683.rs | 0 .../tests}/source/issue-6863/empty-stmt.rs | 0 .../tests}/source/issue-6863/fn-stmts.rs | 0 .../tools/rustfmt/tests}/source/issue-6985.rs | 0 .../tools/rustfmt/tests}/source/issue-7011.rs | 0 .../tools/rustfmt/tests}/source/issue-7054.rs | 0 .../tools/rustfmt/tests}/source/issue-7056.rs | 0 .../tools/rustfmt/tests}/source/issue-811.rs | 0 .../tools/rustfmt/tests}/source/issue-850.rs | 0 .../tools/rustfmt/tests}/source/issue-855.rs | 0 .../tools/rustfmt/tests}/source/issue-913.rs | 0 .../tools/rustfmt/tests}/source/issue-945.rs | 0 .../tools/rustfmt/tests}/source/issue-977.rs | 0 .../tools/rustfmt/tests}/source/issue_1306.rs | 0 .../tools/rustfmt/tests}/source/issue_3245.rs | 0 .../tools/rustfmt/tests}/source/issue_3561.rs | 0 .../tools/rustfmt/tests}/source/issue_3839.rs | 0 .../tools/rustfmt/tests}/source/issue_3844.rs | 0 .../tools/rustfmt/tests}/source/issue_3853.rs | 0 .../tools/rustfmt/tests}/source/issue_3868.rs | 0 .../tools/rustfmt/tests}/source/issue_4032.rs | 0 .../tools/rustfmt/tests}/source/issue_4037.rs | 0 .../tools/rustfmt/tests}/source/issue_4057.rs | 0 .../tools/rustfmt/tests}/source/issue_4086.rs | 0 .../tools/rustfmt/tests}/source/issue_4257.rs | 0 .../tools/rustfmt/tests}/source/issue_4322.rs | 0 .../tools/rustfmt/tests}/source/issue_4374.rs | 0 .../tools/rustfmt/tests}/source/issue_4475.rs | 0 .../tools/rustfmt/tests}/source/issue_4528.rs | 0 .../tools/rustfmt/tests}/source/issue_4579.rs | 0 .../tools/rustfmt/tests}/source/issue_4584.rs | 0 .../tools/rustfmt/tests}/source/issue_4636.rs | 0 .../tools/rustfmt/tests}/source/issue_4675.rs | 0 .../tools/rustfmt/tests}/source/issue_4823.rs | 0 .../tools/rustfmt/tests}/source/issue_4854.rs | 0 .../tools/rustfmt/tests}/source/issue_4911.rs | 0 .../tools/rustfmt/tests}/source/issue_4943.rs | 0 .../tools/rustfmt/tests}/source/issue_4954.rs | 0 .../tools/rustfmt/tests}/source/issue_4963.rs | 0 .../tools/rustfmt/tests}/source/issue_5027.rs | 0 .../tools/rustfmt/tests}/source/issue_5086.rs | 0 .../tools/rustfmt/tests}/source/issue_5686.rs | 0 .../tools/rustfmt/tests}/source/issue_5721.rs | 0 .../tools/rustfmt/tests}/source/issue_5730.rs | 0 .../tools/rustfmt/tests}/source/issue_5735.rs | 0 .../tools/rustfmt/tests}/source/issue_5739.rs | 0 .../tools/rustfmt/tests}/source/issue_5882.rs | 0 .../tools/rustfmt/tests}/source/issue_5912.rs | 0 .../source/issue_5920_style_edition_2024.rs | 0 .../source/issue_5920_style_edition_2027.rs | 0 .../source/issue_5982_style_edition_2024.rs | 0 .../source/issue_5982_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/source/issue_6209.rs | 0 .../source/issue_6381_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/source/issue_6558.rs | 0 .../tools/rustfmt/tests}/source/issue_6801.rs | 0 .../source/issue_6831_style_edition_2021.rs | 0 .../source/issue_6831_style_edition_2024.rs | 0 .../source/issue_6831_style_edition_2027.rs | 0 .../source/issue_7003_style_edition_2024.rs | 0 .../source/issue_7003_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/source/issue_7036.rs | 0 .../source/issue_7055_style_edition_2024.rs | 0 .../source/issue_7055_style_edition_2027.rs | 0 .../tests}/source/issue_7088_stable.rs | 0 .../tests}/source/issue_7088_unstable.rs | 0 .../item-brace-style-always-next-line.rs | 0 .../item-brace-style-prefer-same-line.rs | 0 .../item-brace-style-same-line-where.rs | 0 .../tests}/source/itemized-blocks/no_wrap.rs | 0 .../source/itemized-blocks/rewrite_fail.rs | 0 .../tests}/source/itemized-blocks/urls.rs | 0 .../tests}/source/itemized-blocks/wrap.rs | 0 .../rustfmt/tests}/source/label_break.rs | 0 .../rustfmt/tests}/source/large-block.rs | 0 .../tools/rustfmt/tests}/source/large_vec.rs | 0 .../tests}/source/lazy_staic_before_2027.rs | 0 .../rustfmt/tests}/source/lazy_static.rs | 0 .../tools/rustfmt/tests}/source/let_chains.rs | 0 .../tools/rustfmt/tests}/source/let_else.rs | 0 .../rustfmt/tests}/source/let_else_v2.rs | 0 .../tests}/source/long-fn-1/version_one.rs | 0 .../tests}/source/long-fn-1/version_two.rs | 0 .../source/long-match-arms-brace-newline.rs | 0 .../source/long-use-statement-issue-3154.rs | 0 .../tests}/source/long_field_access.rs | 0 .../tools/rustfmt/tests}/source/loop.rs | 0 .../rustfmt/tests}/source/macro_not_expr.rs | 0 .../rustfmt/tests}/source/macro_rules.rs | 0 .../tools/rustfmt/tests}/source/macros.rs | 0 .../source/macros/rewrite-const-item.rs | 0 .../source/markdown-comment-with-options.rs | 0 .../rustfmt/tests}/source/markdown-comment.rs | 0 .../source/match-block-trailing-comma.rs | 0 .../rustfmt/tests}/source/match-flattening.rs | 0 .../source/match-nowrap-trailing-comma.rs | 0 .../rustfmt/tests}/source/match-nowrap.rs | 0 .../tools/rustfmt/tests}/source/match.rs | 0 .../tests}/source/match_overflow_expr.rs | 0 .../tests}/source/max-line-length-in-chars.rs | 0 .../source/merge_imports_true_compat.rs | 0 .../tools/rustfmt/tests}/source/mod-1.rs | 0 .../tools/rustfmt/tests}/source/mod-2.rs | 0 .../rustfmt/tests}/source/mod_skip_child.rs | 0 .../tools/rustfmt/tests}/source/multiple.rs | 0 .../rustfmt/tests}/source/mut-restriction.rs | 0 .../tools/rustfmt/tests}/source/mut_ref.rs | 0 .../rustfmt/tests}/source/negative-impl.rs | 0 .../rustfmt/tests}/source/nested-if-else.rs | 0 .../tests}/source/nested_skipped/mod.rs | 0 .../rustfmt/tests}/source/nestedmod/mod.rs | 0 .../rustfmt/tests}/source/nestedmod/mod2a.rs | 0 .../rustfmt/tests}/source/nestedmod/mod2b.rs | 0 .../rustfmt/tests}/source/nestedmod/mod2c.rs | 0 .../tests}/source/nestedmod/mymod1/mod3a.rs | 0 .../tests}/source/nestedmod/submod2/a.rs | 0 .../tests}/source/nestedmod/submod2/mod.rs | 0 .../tests}/source/no_arg_with_comment.rs | 0 .../tests}/source/no_new_line_beginning.rs | 0 .../tests}/source/non-lifetime-binders.rs | 0 ...on_ascii_numerics_import_asciibetically.rs | 0 .../non_ascii_numerics_import_versionsort.rs | 0 ...es_should_not_imply_format_doc_comments.rs | 0 .../normalize_multiline_doc_attribute.rs | 0 .../rustfmt/tests}/source/one_line_if_v1.rs | 0 .../rustfmt/tests}/source/one_line_if_v2.rs | 0 .../tools/rustfmt/tests}/source/other.rs | 0 .../tools/rustfmt/tests}/source/paren.rs | 0 .../rustfmt/tests}/source/path_clarity/foo.rs | 0 .../tests}/source/path_clarity/foo/bar.rs | 0 .../tools/rustfmt/tests}/source/paths.rs | 0 .../source/pattern-condense-wildcards.rs | 0 .../tools/rustfmt/tests}/source/pattern.rs | 0 .../tools/rustfmt/tests}/source/pin_sugar.rs | 0 .../tests}/source/postfix-match/pf-match.rs | 0 .../tests}/source/precise-capturing.rs | 0 .../preserves_carriage_return_for_unix.rs | 0 .../preserves_carriage_return_for_windows.rs | 0 .../rustfmt/tests}/source/pub-restricted.rs | 0 .../tests}/source/remove_blank_lines.rs | 0 .../tests}/source/reorder-impl-items.rs | 0 .../tests}/source/reorder_modules/A2/mod.rs | 0 .../tests}/source/reorder_modules/ABCD/mod.rs | 0 .../tests}/source/reorder_modules/ZYXW/mod.rs | 0 .../source/reorder_modules/ZYXW_/mod.rs | 0 .../source/reorder_modules/ZY_XW/mod.rs | 0 .../source/reorder_modules/Z_YXW/mod.rs | 0 .../source/reorder_modules/_ZYXW/mod.rs | 0 .../source/reorder_modules/_abcd/mod.rs | 0 .../tests}/source/reorder_modules/a1/mod.rs | 0 .../source/reorder_modules/abcde/mod.rs | 0 .../disabled_style_edition_2024.rs | 0 .../disabled_style_edition_2027.rs | 0 .../enabled_style_edition_2015.rs | 0 .../enabled_style_edition_2024.rs | 0 .../enabled_style_edition_2027.rs | 0 .../tests}/source/reorder_modules/u128/mod.rs | 0 .../tests}/source/reorder_modules/u16/mod.rs | 0 .../tests}/source/reorder_modules/u256/mod.rs | 0 .../tests}/source/reorder_modules/u32/mod.rs | 0 .../tests}/source/reorder_modules/u64/mod.rs | 0 .../tests}/source/reorder_modules/u8/mod.rs | 0 .../source/reorder_modules/u_zzz/mod.rs | 0 .../tests}/source/reorder_modules/ua/mod.rs | 0 .../source/reorder_modules/usize/mod.rs | 0 .../tests}/source/reorder_modules/uz/mod.rs | 0 .../tests}/source/reorder_modules/v0/mod.rs | 0 .../tests}/source/reorder_modules/v00/mod.rs | 0 .../tests}/source/reorder_modules/v000/mod.rs | 0 .../tests}/source/reorder_modules/v001/mod.rs | 0 .../tests}/source/reorder_modules/v009/mod.rs | 0 .../tests}/source/reorder_modules/v00t/mod.rs | 0 .../tests}/source/reorder_modules/v01/mod.rs | 0 .../tests}/source/reorder_modules/v010/mod.rs | 0 .../tests}/source/reorder_modules/v09/mod.rs | 0 .../tests}/source/reorder_modules/v0s/mod.rs | 0 .../tests}/source/reorder_modules/v0u/mod.rs | 0 .../tests}/source/reorder_modules/v1/mod.rs | 0 .../tests}/source/reorder_modules/v10/mod.rs | 0 .../tests}/source/reorder_modules/v9/mod.rs | 0 .../source/reorder_modules/w005s09t/mod.rs | 0 .../source/reorder_modules/w5s009t/mod.rs | 0 .../tests}/source/reorder_modules/x64/mod.rs | 0 .../tests}/source/reorder_modules/x86/mod.rs | 0 .../source/reorder_modules/x86_128/mod.rs | 0 .../source/reorder_modules/x86_32/mod.rs | 0 .../source/reorder_modules/x86_64/mod.rs | 0 .../tests}/source/reorder_modules/x87/mod.rs | 0 .../source/reorder_modules/zyxwv/mod.rs | 0 .../source/reorder_modules_2027/abcde/mod.rs | 0 .../source/reorder_modules_2027/zyxwv/mod.rs | 0 .../tests}/source/single-line-if-else.rs | 0 .../tests}/source/single-line-macro/v1.rs | 0 .../tests}/source/single-line-macro/v2.rs | 0 .../source/skip_macro_invocations/all.rs | 0 .../skip_macro_invocations/all_and_name.rs | 0 .../skip_macro_invocations/config_file.rs | 0 .../source/skip_macro_invocations/empty.rs | 0 .../source/skip_macro_invocations/name.rs | 0 .../skip_macro_invocations/name_unknown.rs | 0 .../source/skip_macro_invocations/names.rs | 0 .../path_qualified_invocation_mismatch.rs | 0 .../path_qualified_match.rs | 0 .../path_qualified_name_mismatch.rs | 0 .../use_alias_examples.rs | 0 .../rustfmt/tests}/source/soft-wrapping.rs | 0 .../tests}/source/space-not-before-newline.rs | 0 .../tests}/source/spaces-around-ranges.rs | 0 .../tools/rustfmt/tests}/source/statements.rs | 0 .../tools/rustfmt/tests}/source/static.rs | 0 .../rustfmt/tests}/source/string-lit-2.rs | 0 .../tools/rustfmt/tests}/source/string-lit.rs | 0 .../tests}/source/string_lit_unicode_ws.rs | 0 .../tests}/source/string_punctuation.rs | 0 .../tests}/source/struct-field-attributes.rs | 0 .../tests}/source/struct_field_doc_comment.rs | 0 .../rustfmt/tests}/source/struct_lits.rs | 0 .../tests}/source/struct_lits_multiline.rs | 0 .../tests}/source/struct_lits_visual.rs | 0 .../source/struct_lits_visual_multiline.rs | 0 .../tests}/source/struct_tuple_visual.rs | 0 .../tools/rustfmt/tests}/source/structs.rs | 0 .../tools/rustfmt/tests}/source/super_let.rs | 0 .../tests}/source/trailing-comma-never.rs | 0 ...-bodies-edition-2021-style-edition-2027.rs | 0 ...-bodies-edition-2024-style-edition-2024.rs | 0 .../source/trailing-semicolon/loop-bodies.rs | 0 .../rustfmt/tests}/source/trailing_commas.rs | 0 .../source/trailing_comments/hard_tabs.rs | 0 .../source/trailing_comments/soft_tabs.rs | 0 .../tools/rustfmt/tests}/source/trait.rs | 0 .../rustfmt/tests}/source/try-conversion.rs | 0 .../tools/rustfmt/tests}/source/try_block.rs | 0 .../tests}/source/try_blocks_heterogeneous.rs | 0 .../tools/rustfmt/tests}/source/tuple.rs | 0 .../tools/rustfmt/tests}/source/tuple_v2.rs | 0 .../type-alias-where-clauses-with-comments.rs | 0 .../tests}/source/type-alias-where-clauses.rs | 0 .../tools/rustfmt/tests}/source/type.rs | 0 .../tools/rustfmt/tests}/source/type_alias.rs | 0 .../tools/rustfmt/tests}/source/unicode.rs | 0 .../tools/rustfmt/tests}/source/unions.rs | 0 .../rustfmt/tests}/source/unsafe-binders.rs | 0 .../rustfmt/tests}/source/unsafe-field.rs | 0 .../tools/rustfmt/tests}/source/unsafe-mod.rs | 0 .../use-identifier-order-mixed-edition.rs | 0 .../tests}/source/use-identifier-order.rs | 0 .../tools/rustfmt/tests}/source/visibility.rs | 0 .../rustfmt/tests}/source/visual-fn-type.rs | 0 .../rustfmt/tests}/source/where-clause-rfc.rs | 0 .../rustfmt/tests}/source/where-clause.rs | 0 .../rustfmt/tests}/source/width-heuristics.rs | 0 ...ts_should_not_imply_format_doc_comments.rs | 0 .../tools/rustfmt/tests}/target/5131_crate.rs | 0 .../rustfmt/tests}/target/5131_module.rs | 0 .../tools/rustfmt/tests}/target/5131_one.rs | 0 .../inner-block-doc-comment.rs | 0 .../naive-outer-block-comment.rs | 0 .../outer-block-doc-comment.rs | 0 .../rustc-sample-1.rs | 0 .../rustc-sample-2.rs | 0 .../target/alignment_2633/block_style.rs | 0 .../alignment_2633/horizontal_tactic.rs | 0 .../target/alignment_2633/visual_style.rs | 0 .../rustfmt/tests}/target/array_comment.rs | 0 .../arrow_in_single_comment.rs | 0 .../arrow_in_comments/multiple_arrows.rs | 0 .../tools/rustfmt/tests}/target/assignment.rs | 0 .../rustfmt/tests}/target/associated-items.rs | 0 .../associated-types-bounds-wrapping.rs | 0 .../tests}/target/associated_type_bounds.rs | 0 .../tests}/target/associated_type_defaults.rs | 0 .../rustfmt/tests}/target/async_block.rs | 0 .../rustfmt/tests}/target/async_closure.rs | 0 .../tools/rustfmt/tests}/target/async_fn.rs | 0 .../tools/rustfmt/tests}/target/asyncness.rs | 0 .../tests}/target/attrib-block-expr.rs | 0 .../tests}/target/attrib-extern-crate.rs | 0 .../tools/rustfmt/tests}/target/attrib.rs | 0 .../rustfmt/tests}/target/big-impl-block.rs | 0 .../rustfmt/tests}/target/big-impl-visual.rs | 0 .../rustfmt/tests}/target/binary-expr.rs | 0 .../target/binop-separator-back/bitwise.rs | 0 .../target/binop-separator-back/comp.rs | 0 .../target/binop-separator-back/logic.rs | 0 .../target/binop-separator-back/math.rs | 0 .../target/binop-separator-back/patterns.rs | 0 .../target/binop-separator-back/range.rs | 0 .../tests}/target/break-and-continue.rs | 0 .../tools/rustfmt/tests}/target/catch.rs | 0 .../tests}/target/cfg_attribute_in_where.rs | 0 .../target/cfg_if/detect/arch/aarch64.rs | 0 .../tests}/target/cfg_if/detect/arch/arm.rs | 0 .../tests}/target/cfg_if/detect/arch/mips.rs | 0 .../target/cfg_if/detect/arch/mips64.rs | 0 .../target/cfg_if/detect/arch/powerpc.rs | 0 .../target/cfg_if/detect/arch/powerpc64.rs | 0 .../tests}/target/cfg_if/detect/arch/x86.rs | 0 .../tests}/target/cfg_if/detect/bit.rs | 0 .../tests}/target/cfg_if/detect/cache.rs | 0 .../target/cfg_if/detect/error_macros.rs | 0 .../tests}/target/cfg_if/detect/mod.rs | 0 .../tests}/target/cfg_if/detect/os/aarch64.rs | 0 .../cfg_if/detect/os/freebsd/aarch64.rs | 0 .../target/cfg_if/detect/os/freebsd/arm.rs | 0 .../target/cfg_if/detect/os/freebsd/auxvec.rs | 0 .../target/cfg_if/detect/os/freebsd/mod.rs | 0 .../cfg_if/detect/os/freebsd/powerpc.rs | 0 .../target/cfg_if/detect/os/linux/aarch64.rs | 0 .../target/cfg_if/detect/os/linux/arm.rs | 0 .../target/cfg_if/detect/os/linux/auxvec.rs | 0 .../target/cfg_if/detect/os/linux/cpuinfo.rs | 0 .../target/cfg_if/detect/os/linux/mips.rs | 0 .../target/cfg_if/detect/os/linux/mod.rs | 0 .../target/cfg_if/detect/os/linux/powerpc.rs | 0 .../tests}/target/cfg_if/detect/os/other.rs | 0 .../tests}/target/cfg_if/detect/os/x86.rs | 0 .../tools/rustfmt/tests}/target/cfg_if/lib.rs | 0 .../tools/rustfmt/tests}/target/cfg_if/mod.rs | 0 .../rustfmt/tests}/target/cfg_mod/bar.rs | 0 .../target/cfg_mod/dir/dir1/dir2/wasm32.rs | 0 .../target/cfg_mod/dir/dir1/dir3/wasm32.rs | 0 .../rustfmt/tests}/target/cfg_mod/foo.rs | 0 .../rustfmt/tests}/target/cfg_mod/mod.rs | 0 .../rustfmt/tests}/target/cfg_mod/other.rs | 0 .../rustfmt/tests}/target/cfg_mod/wasm32.rs | 0 .../tools/rustfmt/tests}/target/cfg_select.rs | 0 .../target/cfg_select/format_me_please_1.rs | 0 .../target/cfg_select/format_me_please_2.rs | 0 .../target/cfg_select/format_me_please_3.rs | 0 .../target/cfg_select/format_me_please_4.rs | 0 .../rustfmt/tests}/target/cfg_select/lib.rs | 0 .../rustfmt/tests}/target/cfg_select/lib2.rs | 0 .../tests}/target/cfg_select_stable.rs | 0 .../target/chain_yield_with_comments.rs | 0 .../rustfmt/tests}/target/chains-visual.rs | 0 .../tools/rustfmt/tests}/target/chains.rs | 0 .../tests}/target/chains_with_comment.rs | 0 .../target/closure-block-inside-macro.rs | 0 .../tests}/target/closure-block-labels.rs | 0 .../tools/rustfmt/tests}/target/closure.rs | 0 .../tests}/target/comment-inside-const.rs | 0 .../tests}/target/comment-not-disappear.rs | 0 .../tools/rustfmt/tests}/target/comment.rs | 0 .../tools/rustfmt/tests}/target/comment2.rs | 0 .../tools/rustfmt/tests}/target/comment3.rs | 0 .../tools/rustfmt/tests}/target/comment4.rs | 0 .../tools/rustfmt/tests}/target/comment5.rs | 0 .../tools/rustfmt/tests}/target/comment6.rs | 0 .../tests}/target/comment_crlf_newline.rs | 0 .../rustfmt/tests}/target/comments-fn.rs | 0 .../comments-in-lists/format-doc-comments.rs | 0 .../comments-in-lists/wrap-comments-false.rs | 0 .../wrap-comments-not-normalized.rs | 0 .../comments-in-lists/wrap-comments-true.rs | 0 .../rustfmt/tests}/target/comments_unicode.rs | 0 .../configs/blank_lines_lower_bound/1.rs | 0 .../configs/blank_lines_upper_bound/1.rs | 0 .../configs/blank_lines_upper_bound/2.rs | 0 .../brace_style/fn_always_next_line.rs | 0 .../brace_style/fn_prefer_same_line.rs | 0 .../configs/brace_style/fn_same_line_where.rs | 0 .../brace_style/item_always_next_line.rs | 0 .../brace_style/item_prefer_same_line.rs | 0 .../brace_style/item_same_line_where.rs | 0 .../target/configs/chain_width/always.rs | 0 .../target/configs/chain_width/small.rs | 0 .../tests}/target/configs/chain_width/tiny.rs | 0 .../configs/combine_control_expr/false.rs | 0 .../configs/combine_control_expr/true.rs | 0 .../target/configs/comment_width/above.rs | 0 .../target/configs/comment_width/below.rs | 0 .../target/configs/comment_width/ignore.rs | 0 .../condense_wildcard_suffixes/false.rs | 0 .../condense_wildcard_suffixes/true.rs | 0 .../control_brace_style/always_next_line.rs | 0 .../control_brace_style/always_same_line.rs | 0 .../control_brace_style/closing_next_line.rs | 0 .../configs/disable_all_formatting/false.rs | 0 .../configs/disable_all_formatting/true.rs | 0 .../default-to-max.rs | 0 .../max-to-default.rs | 0 .../doc_comment_code_block_width/100.rs | 0 .../100_greater_max_width.rs | 0 .../doc_comment_code_block_width/50.rs | 0 .../configs/empty_item_single_line/false.rs | 0 .../configs/empty_item_single_line/true.rs | 0 .../enum_discrim_align_threshold/40.rs | 0 .../configs/error_on_line_overflow/false.rs | 0 .../configs/error_on_unformatted/false.rs | 0 .../float_literal_trailing_zero/always.rs | 0 .../always_spaces_around_ranges_true.rs | 0 .../if-no-postfix.rs | 0 ...if-no-postfix_spaces_around_ranges_true.rs | 0 .../float_literal_trailing_zero/never.rs | 0 .../never_spaces_around_ranges_true.rs | 0 .../float_literal_trailing_zero/preserve.rs | 0 .../preserve_spaces_around_ranges_true.rs | 0 .../configs/fn_params_layout/compressed.rs | 0 .../target/configs/fn_params_layout/tall.rs | 0 .../configs/fn_params_layout/vertical.rs | 0 .../fn_params_layout/vertical_style_2027.rs | 0 .../target/configs/fn_single_line/false.rs | 0 .../target/configs/fn_single_line/true.rs | 0 .../configs/force_explicit_abi/false.rs | 0 .../target/configs/force_explicit_abi/true.rs | 0 .../configs/force_multiline_block/false.rs | 0 .../configs/force_multiline_block/true.rs | 0 .../configs/format_generated_files/false.rs | 0 ...with_generated_marker_line_search_limit.rs | 0 .../false_with_marker_out_scope_size.rs | 0 .../false_with_zero_search_limit.rs | 0 .../configs/format_generated_files/true.rs | 0 .../true_with_marker_in_scope_size.rs | 0 .../true_with_marker_not_in_header.rs | 0 .../configs/format_macro_bodies/false.rs | 0 .../configs/format_macro_bodies/true.rs | 0 .../configs/format_macro_matchers/false.rs | 0 .../configs/format_macro_matchers/true.rs | 0 .../target/configs/format_strings/false.rs | 0 .../target/configs/format_strings/true.rs | 0 .../group_imports/One-merge_imports.rs | 0 .../configs/group_imports/One-nested.rs | 0 .../configs/group_imports/One-no_reorder.rs | 0 .../target/configs/group_imports/One.rs | 0 .../StdExternalCrate-merge_imports.rs | 0 .../group_imports/StdExternalCrate-nested.rs | 0 .../StdExternalCrate-no_reorder.rs | 0 .../StdExternalCrate-non_consecutive.rs | 0 .../configs/group_imports/StdExternalCrate.rs | 0 .../tests}/target/configs/hard_tabs/false.rs | 0 .../tests}/target/configs/hard_tabs/true.rs | 0 .../hex_literal_case/hex_literal_lower.rs | 0 .../hex_literal_case/hex_literal_preserve.rs | 0 .../hex_literal_case/hex_literal_upper.rs | 0 .../target/configs/imports_indent/block.rs | 0 .../imports_layout/horizontal_vertical.rs | 0 .../configs/imports_layout/merge_mixed.rs | 0 .../target/configs/imports_layout/mixed.rs | 0 .../target/configs/indent_style/block_args.rs | 0 .../configs/indent_style/block_array.rs | 0 .../target/configs/indent_style/block_call.rs | 0 .../configs/indent_style/block_chain.rs | 0 .../configs/indent_style/block_generic.rs | 0 .../configs/indent_style/block_struct_lit.rs | 0 .../indent_style/block_tab_spaces_call.rs | 0 .../block_trailing_comma_call/one.rs | 0 .../block_trailing_comma_call/two.rs | 0 .../configs/indent_style/block_where_pred.rs | 0 .../target/configs/indent_style/default.rs | 0 .../configs/indent_style/rfc_control.rs | 0 .../target/configs/indent_style/rfc_where.rs | 0 .../configs/indent_style/visual_args.rs | 0 .../configs/indent_style/visual_array.rs | 0 .../configs/indent_style/visual_call.rs | 0 .../configs/indent_style/visual_chain.rs | 0 .../configs/indent_style/visual_generics.rs | 0 .../configs/indent_style/visual_struct_lit.rs | 0 .../indent_style/visual_trailing_comma.rs | 0 .../configs/indent_style/visual_where_pred.rs | 0 .../target/configs/match_arm_blocks/false.rs | 0 .../target/configs/match_arm_blocks/true.rs | 0 .../target/configs/match_arm_indent/attrs.rs | 0 .../target/configs/match_arm_indent/guards.rs | 0 .../configs/match_arm_indent/leading_pipes.rs | 0 .../target/configs/match_arm_indent/nested.rs | 0 .../configs/match_arm_indent/noindent-tabs.rs | 0 .../configs/match_arm_indent/noindent.rs | 0 .../configs/match_arm_indent/patterns.rs | 0 .../configs/match_arm_indent/unindent.rs | 0 .../configs/match_arm_leading_pipes/always.rs | 0 .../configs/match_arm_leading_pipes/never.rs | 0 .../match_arm_leading_pipes/preserve.rs | 0 .../match_block_trailing_comma/false.rs | 0 .../match_block_trailing_comma/true.rs | 0 .../target/configs/merge_derives/true.rs | 0 .../configs/normalize_comments/false.rs | 0 .../target/configs/normalize_comments/true.rs | 0 .../configs/normalize_doc_attributes/false.rs | 0 .../configs/normalize_doc_attributes/true.rs | 0 .../remove_nested_parens.rs | 0 .../configs/reorder_impl_items/false.rs | 0 .../target/configs/reorder_impl_items/true.rs | 0 .../target/configs/reorder_imports/false.rs | 0 .../target/configs/reorder_imports/true.rs | 0 .../configs/reorder_modules/dolor/mod.rs | 0 .../target/configs/reorder_modules/false.rs | 0 .../configs/reorder_modules/ipsum/mod.rs | 0 .../configs/reorder_modules/lorem/mod.rs | 0 .../target/configs/reorder_modules/sit/mod.rs | 0 .../target/configs/reorder_modules/true.rs | 0 .../short_array_element_width_threshold/10.rs | 0 .../short_array_element_width_threshold/20.rs | 0 .../greater_than_max_width.rs | 0 .../single_line_let_else_max_width/100.rs | 0 .../single_line_let_else_max_width/50.rs | 0 .../single_line_let_else_max_width/zero.rs | 0 .../target/configs/skip_children/foo/mod.rs | 0 .../target/configs/skip_children/true.rs | 0 .../target/configs/space_before_colon/true.rs | 0 .../configs/spaces_around_ranges/false.rs | 0 .../configs/spaces_around_ranges/true.rs | 0 .../struct_field_align_threshold/20.rs | 0 .../configs/struct_lit_single_line/false.rs | 0 .../style_edition/overflow_delim_expr_2015.rs | 0 .../style_edition/overflow_delim_expr_2024.rs | 0 .../tests}/target/configs/tab_spaces/2.rs | 0 .../tests}/target/configs/tab_spaces/4.rs | 0 .../target/configs/trailing_comma/always.rs | 0 .../target/configs/trailing_comma/never.rs | 0 .../target/configs/trailing_comma/vertical.rs | 0 .../configs/trailing_semicolon/false.rs | 0 .../target/configs/trailing_semicolon/true.rs | 0 .../type_punctuation_density/compressed.rs | 0 .../configs/type_punctuation_density/wide.rs | 0 .../configs/use_field_init_shorthand/false.rs | 0 .../configs/use_field_init_shorthand/true.rs | 0 .../configs/use_small_heuristics/default.rs | 0 .../configs/use_small_heuristics/max.rs | 0 .../configs/use_small_heuristics/off.rs | 0 .../target/configs/use_try_shorthand/false.rs | 0 .../target/configs/use_try_shorthand/true.rs | 0 .../tests}/target/configs/version/mapped.rs | 0 .../true-with-brace-style.rs | 0 .../target/configs/where_single_line/true.rs | 0 .../target/configs/wrap_comments/false.rs | 0 .../target/configs/wrap_comments/true.rs | 0 .../tests}/target/const-block-items.rs | 0 .../rustfmt/tests}/target/const-generics.rs | 0 .../rustfmt/tests}/target/const_generics.rs | 0 .../rustfmt/tests}/target/const_trait.rs | 0 .../control-brace-style-always-next-line.rs | 0 .../control-brace-style-always-same-line.rs | 0 .../tests}/target/default-field-values.rs | 0 .../rustfmt/tests}/target/direct_const_arg.rs | 0 .../tools/rustfmt/tests}/target/doc-attrib.rs | 0 .../tests}/target/doc-comment-with-example.rs | 0 .../tests}/target/doc-of-generic-item.rs | 0 .../tools/rustfmt/tests}/target/doc.rs | 0 .../tools/rustfmt/tests}/target/dyn_trait.rs | 0 .../else-if-brace-style-always-next-line.rs | 0 .../else-if-brace-style-always-same-line.rs | 0 .../else-if-brace-style-closing-next-line.rs | 0 .../target/empty-item-single-line-false.rs | 0 ...mpty-tuple-no-conversion-to-unit-struct.rs | 0 .../tools/rustfmt/tests}/target/empty_file.rs | 0 .../tools/rustfmt/tests}/target/enum.rs | 0 .../rustfmt/tests}/target/ergonomic_clones.rs | 0 .../rustfmt/tests}/target/existential_type.rs | 0 .../tools/rustfmt/tests}/target/expr-block.rs | 0 .../tests}/target/expr-overflow-delimited.rs | 0 .../tools/rustfmt/tests}/target/expr.rs | 0 .../rustfmt/tests}/target/extern-rust.rs | 0 .../tools/rustfmt/tests}/target/extern.rs | 0 .../tests}/target/extern_not_explicit.rs | 0 .../tests}/target/field-representing-types.rs | 0 .../rustfmt/tests}/target/file-lines-1.rs | 0 .../rustfmt/tests}/target/file-lines-2.rs | 0 .../rustfmt/tests}/target/file-lines-3.rs | 0 .../rustfmt/tests}/target/file-lines-4.rs | 0 .../rustfmt/tests}/target/file-lines-5.rs | 0 .../rustfmt/tests}/target/file-lines-6.rs | 0 .../rustfmt/tests}/target/file-lines-7.rs | 0 .../rustfmt/tests}/target/file-lines-item.rs | 0 .../tools/rustfmt/tests}/target/final-kw.rs | 0 .../target/fn-args-with-last-line-comment.rs | 0 .../rustfmt/tests}/target/fn-custom-2.rs | 0 .../rustfmt/tests}/target/fn-custom-3.rs | 0 .../rustfmt/tests}/target/fn-custom-4.rs | 0 .../rustfmt/tests}/target/fn-custom-6.rs | 0 .../rustfmt/tests}/target/fn-custom-7.rs | 0 .../rustfmt/tests}/target/fn-custom-8.rs | 0 .../tools/rustfmt/tests}/target/fn-custom.rs | 0 .../tests}/target/fn-param-attributes.rs | 0 .../tools/rustfmt/tests}/target/fn-simple.rs | 0 .../target/fn-single-line/version_one.rs | 0 .../target/fn-single-line/version_two.rs | 0 .../tools/rustfmt/tests}/target/fn-ty.rs | 0 .../tools/rustfmt/tests}/target/fn.rs | 0 .../tests}/target/fn_args_indent-block.rs | 0 .../tests}/target/fn_args_layout-vertical.rs | 0 .../tools/rustfmt/tests}/target/fn_once.rs | 0 .../tests}/target/format_strings/issue-202.rs | 0 .../target/format_strings/issue-2833.rs | 0 .../target/format_strings/issue-3263.rs | 0 .../tests}/target/format_strings/issue-687.rs | 0 .../tests}/target/format_strings/issue564.rs | 0 .../tests}/target/frontmatter_compact.rs | 0 .../tests}/target/frontmatter_escaped.rs | 0 .../tests}/target/frontmatter_spaced.rs | 0 .../rustfmt/tests}/target/generic_static.rs | 0 .../rustfmt/tests}/target/guard_patterns.rs | 0 .../tools/rustfmt/tests}/target/hard-tabs.rs | 0 .../tools/rustfmt/tests}/target/hello.rs | 0 .../tests}/target/if_while_or_patterns.rs | 0 .../tests}/target/immovable_coroutines.rs | 0 .../rustfmt/tests}/target/impl-restriction.rs | 0 .../tools/rustfmt/tests}/target/impl.rs | 0 .../tools/rustfmt/tests}/target/impls.rs | 0 .../target/imports/import-fencepost-length.rs | 0 .../target/imports/imports-impl-only-use.rs | 0 .../imports-reorder-lines-and-items.rs | 0 .../target/imports/imports-reorder-lines.rs | 0 .../tests}/target/imports/imports-reorder.rs | 0 .../rustfmt/tests}/target/imports/imports.rs | 0 .../target/imports/imports_2021_edition.rs | 0 .../target/imports/imports_block_indent.rs | 0 .../imports/imports_granularity_crate.rs | 0 .../imports_granularity_default-with-dups.rs | 0 ...m-with-dups-StdExternalCrate-no-reorder.rs | 0 .../imports_granularity_item-with-dups.rs | 0 .../imports/imports_granularity_item.rs | 0 .../imports/imports_granularity_module.rs | 0 .../target/imports/imports_granularity_one.rs | 0 .../imports_raw_identifiers/version_One.rs | 0 .../imports_raw_identifiers/version_Two.rs | 0 .../rustfmt/tests}/target/indented-impl.rs | 0 .../tests}/target/inner-module-path/b.rs | 0 .../tests}/target/inner-module-path/c/d.rs | 0 .../tests}/target/inner-module-path/lib.rs | 0 .../invalid-rust-code-in-doc-comment.rs | 0 .../tools/rustfmt/tests}/target/issue-1021.rs | 0 .../tools/rustfmt/tests}/target/issue-1049.rs | 0 .../tools/rustfmt/tests}/target/issue-1055.rs | 0 .../tools/rustfmt/tests}/target/issue-1096.rs | 0 .../tools/rustfmt/tests}/target/issue-1111.rs | 0 .../tools/rustfmt/tests}/target/issue-1113.rs | 0 .../tools/rustfmt/tests}/target/issue-1120.rs | 0 .../tools/rustfmt/tests}/target/issue-1124.rs | 0 .../tools/rustfmt/tests}/target/issue-1127.rs | 0 .../tools/rustfmt/tests}/target/issue-1158.rs | 0 .../tools/rustfmt/tests}/target/issue-1177.rs | 0 .../tools/rustfmt/tests}/target/issue-1192.rs | 0 .../rustfmt/tests}/target/issue-1210/a.rs | 0 .../rustfmt/tests}/target/issue-1210/b.rs | 0 .../rustfmt/tests}/target/issue-1210/c.rs | 0 .../rustfmt/tests}/target/issue-1210/d.rs | 0 .../rustfmt/tests}/target/issue-1210/e.rs | 0 .../tools/rustfmt/tests}/target/issue-1211.rs | 0 .../tools/rustfmt/tests}/target/issue-1214.rs | 0 .../tools/rustfmt/tests}/target/issue-1216.rs | 0 .../tools/rustfmt/tests}/target/issue-1239.rs | 0 .../tools/rustfmt/tests}/target/issue-1247.rs | 0 .../tools/rustfmt/tests}/target/issue-1255.rs | 0 .../tools/rustfmt/tests}/target/issue-1278.rs | 0 .../tools/rustfmt/tests}/target/issue-1350.rs | 0 .../tools/rustfmt/tests}/target/issue-1366.rs | 0 .../tools/rustfmt/tests}/target/issue-1397.rs | 0 .../tools/rustfmt/tests}/target/issue-1468.rs | 0 .../tools/rustfmt/tests}/target/issue-1598.rs | 0 .../tools/rustfmt/tests}/target/issue-1624.rs | 0 .../tools/rustfmt/tests}/target/issue-1681.rs | 0 .../tools/rustfmt/tests}/target/issue-1693.rs | 0 .../tools/rustfmt/tests}/target/issue-1703.rs | 0 .../tools/rustfmt/tests}/target/issue-1800.rs | 0 .../tools/rustfmt/tests}/target/issue-1802.rs | 0 .../tools/rustfmt/tests}/target/issue-1824.rs | 0 .../tools/rustfmt/tests}/target/issue-1914.rs | 0 .../tools/rustfmt/tests}/target/issue-2025.rs | 0 .../tools/rustfmt/tests}/target/issue-2103.rs | 0 .../tools/rustfmt/tests}/target/issue-2111.rs | 0 .../tools/rustfmt/tests}/target/issue-2123.rs | 0 .../tools/rustfmt/tests}/target/issue-2164.rs | 0 .../rustfmt/tests}/target/issue-2179/one.rs | 0 .../rustfmt/tests}/target/issue-2179/two.rs | 0 .../tools/rustfmt/tests}/target/issue-2197.rs | 0 .../tools/rustfmt/tests}/target/issue-2256.rs | 0 .../tools/rustfmt/tests}/target/issue-2324.rs | 0 .../tools/rustfmt/tests}/target/issue-2329.rs | 0 .../tools/rustfmt/tests}/target/issue-2342.rs | 0 .../tools/rustfmt/tests}/target/issue-2346.rs | 0 .../tools/rustfmt/tests}/target/issue-2401.rs | 0 .../tools/rustfmt/tests}/target/issue-2445.rs | 0 .../tools/rustfmt/tests}/target/issue-2446.rs | 0 .../tools/rustfmt/tests}/target/issue-2479.rs | 0 .../rustfmt/tests}/target/issue-2482/a.rs | 0 .../rustfmt/tests}/target/issue-2482/b.rs | 0 .../rustfmt/tests}/target/issue-2482/c.rs | 0 .../tools/rustfmt/tests}/target/issue-2496.rs | 0 .../tools/rustfmt/tests}/target/issue-2520.rs | 0 .../tools/rustfmt/tests}/target/issue-2523.rs | 0 .../tools/rustfmt/tests}/target/issue-2526.rs | 0 .../issue-2534/format_macro_matchers_false.rs | 0 .../issue-2534/format_macro_matchers_true.rs | 0 .../tools/rustfmt/tests}/target/issue-2551.rs | 0 .../tools/rustfmt/tests}/target/issue-2554.rs | 0 .../tools/rustfmt/tests}/target/issue-2582.rs | 0 .../tools/rustfmt/tests}/target/issue-2641.rs | 0 .../tools/rustfmt/tests}/target/issue-2644.rs | 0 .../target/issue-2673-nonmodrs-mods/foo.rs | 0 .../issue-2673-nonmodrs-mods/foo/bar.rs | 0 .../target/issue-2673-nonmodrs-mods/lib.rs | 0 .../tools/rustfmt/tests}/target/issue-2728.rs | 0 .../tools/rustfmt/tests}/target/issue-2759.rs | 0 .../tools/rustfmt/tests}/target/issue-2761.rs | 0 .../tools/rustfmt/tests}/target/issue-2781.rs | 0 .../tools/rustfmt/tests}/target/issue-2794.rs | 0 .../tools/rustfmt/tests}/target/issue-2810.rs | 0 .../tools/rustfmt/tests}/target/issue-2835.rs | 0 .../tools/rustfmt/tests}/target/issue-2863.rs | 0 .../tools/rustfmt/tests}/target/issue-2869.rs | 0 .../tools/rustfmt/tests}/target/issue-2896.rs | 0 .../tools/rustfmt/tests}/target/issue-2916.rs | 0 .../tests}/target/issue-2917/minimal.rs | 0 .../tests}/target/issue-2917/packed_simd.rs | 0 .../tools/rustfmt/tests}/target/issue-2922.rs | 0 .../rustfmt/tests}/target/issue-2927-2.rs | 0 .../tools/rustfmt/tests}/target/issue-2927.rs | 0 .../tools/rustfmt/tests}/target/issue-2930.rs | 0 .../tools/rustfmt/tests}/target/issue-2936.rs | 0 .../tools/rustfmt/tests}/target/issue-2941.rs | 0 .../tools/rustfmt/tests}/target/issue-2955.rs | 0 .../tools/rustfmt/tests}/target/issue-2973.rs | 0 .../tools/rustfmt/tests}/target/issue-2976.rs | 0 .../rustfmt/tests}/target/issue-2977/block.rs | 0 .../rustfmt/tests}/target/issue-2977/impl.rs | 0 .../rustfmt/tests}/target/issue-2977/item.rs | 0 .../rustfmt/tests}/target/issue-2977/trait.rs | 0 .../tools/rustfmt/tests}/target/issue-2985.rs | 0 .../tools/rustfmt/tests}/target/issue-2995.rs | 0 .../tools/rustfmt/tests}/target/issue-3029.rs | 0 .../tools/rustfmt/tests}/target/issue-3032.rs | 0 .../tools/rustfmt/tests}/target/issue-3038.rs | 0 .../tools/rustfmt/tests}/target/issue-3043.rs | 0 .../tools/rustfmt/tests}/target/issue-3049.rs | 0 .../tests}/target/issue-3055/backtick.rs | 0 .../target/issue-3055/empty-code-block.rs | 0 .../tests}/target/issue-3055/original.rs | 0 .../tools/rustfmt/tests}/target/issue-3059.rs | 0 .../tools/rustfmt/tests}/target/issue-3066.rs | 0 .../tools/rustfmt/tests}/target/issue-3105.rs | 0 .../tools/rustfmt/tests}/target/issue-3118.rs | 0 .../tools/rustfmt/tests}/target/issue-3124.rs | 0 .../tools/rustfmt/tests}/target/issue-3131.rs | 0 .../tools/rustfmt/tests}/target/issue-3132.rs | 0 .../tools/rustfmt/tests}/target/issue-3153.rs | 0 .../tools/rustfmt/tests}/target/issue-3158.rs | 0 .../tools/rustfmt/tests}/target/issue-3182.rs | 0 .../tools/rustfmt/tests}/target/issue-3184.rs | 0 .../tools/rustfmt/tests}/target/issue-3194.rs | 0 .../tools/rustfmt/tests}/target/issue-3198.rs | 0 .../tests}/target/issue-3213/version_one.rs | 0 .../tests}/target/issue-3213/version_two.rs | 0 .../tools/rustfmt/tests}/target/issue-3217.rs | 0 .../tools/rustfmt/tests}/target/issue-3224.rs | 0 .../rustfmt/tests}/target/issue-3227/one.rs | 0 .../rustfmt/tests}/target/issue-3227/two.rs | 0 .../tools/rustfmt/tests}/target/issue-3234.rs | 0 .../tools/rustfmt/tests}/target/issue-3241.rs | 0 .../rustfmt/tests}/target/issue-3253/bar.rs | 0 .../rustfmt/tests}/target/issue-3253/foo.rs | 0 .../rustfmt/tests}/target/issue-3253/lib.rs | 0 .../tests}/target/issue-3253/paths/bar_foo.rs | 0 .../target/issue-3253/paths/excluded.rs | 0 .../tests}/target/issue-3253/paths/foo_bar.rs | 0 .../tools/rustfmt/tests}/target/issue-3265.rs | 0 .../rustfmt/tests}/target/issue-3270/one.rs | 0 .../rustfmt/tests}/target/issue-3270/two.rs | 0 .../rustfmt/tests}/target/issue-3270/wrap.rs | 0 .../rustfmt/tests}/target/issue-3272/v1.rs | 0 .../rustfmt/tests}/target/issue-3272/v2.rs | 0 .../tests}/target/issue-3278/version_one.rs | 0 .../tests}/target/issue-3278/version_two.rs | 0 .../rustfmt/tests}/target/issue-3295/two.rs | 0 .../tools/rustfmt/tests}/target/issue-3302.rs | 0 .../tools/rustfmt/tests}/target/issue-3304.rs | 0 .../tools/rustfmt/tests}/target/issue-3314.rs | 0 .../tools/rustfmt/tests}/target/issue-3343.rs | 0 .../tools/rustfmt/tests}/target/issue-3423.rs | 0 .../rustfmt/tests}/target/issue-3434/lib.rs | 0 .../tests}/target/issue-3434/no_entry.rs | 0 .../target/issue-3434/not_skip_macro.rs | 0 .../tools/rustfmt/tests}/target/issue-3442.rs | 0 .../tools/rustfmt/tests}/target/issue-3465.rs | 0 .../rustfmt/tests}/target/issue-3494/crlf.rs | 0 .../rustfmt/tests}/target/issue-3494/lf.rs | 0 .../tools/rustfmt/tests}/target/issue-3499.rs | 0 .../tools/rustfmt/tests}/target/issue-3508.rs | 0 .../tools/rustfmt/tests}/target/issue-3515.rs | 0 .../tools/rustfmt/tests}/target/issue-3532.rs | 0 .../tools/rustfmt/tests}/target/issue-3539.rs | 0 .../tools/rustfmt/tests}/target/issue-3554.rs | 0 .../tools/rustfmt/tests}/target/issue-3567.rs | 0 .../tools/rustfmt/tests}/target/issue-3568.rs | 0 .../tests}/target/issue-3585/extern_crate.rs | 0 .../issue-3585/reorder_imports_disabled.rs | 0 .../issue-3585/reorder_imports_enabled.rs | 0 .../rustfmt/tests}/target/issue-3585/use.rs | 0 .../tools/rustfmt/tests}/target/issue-3595.rs | 0 .../tools/rustfmt/tests}/target/issue-3601.rs | 0 .../tests}/target/issue-3614/version_one.rs | 0 .../tests}/target/issue-3614/version_two.rs | 0 .../tools/rustfmt/tests}/target/issue-3636.rs | 0 .../tools/rustfmt/tests}/target/issue-3639.rs | 0 .../tools/rustfmt/tests}/target/issue-3645.rs | 0 .../tools/rustfmt/tests}/target/issue-3651.rs | 0 .../rustfmt/tests}/target/issue-3665/lib.rs | 0 .../target/issue-3665/not_skip_attribute.rs | 0 .../tests}/target/issue-3665/sub_mod.rs | 0 .../tools/rustfmt/tests}/target/issue-3672.rs | 0 .../tools/rustfmt/tests}/target/issue-3675.rs | 0 .../rustfmt/tests}/target/issue-3701/one.rs | 0 .../rustfmt/tests}/target/issue-3701/two.rs | 0 .../tools/rustfmt/tests}/target/issue-3709.rs | 0 .../tools/rustfmt/tests}/target/issue-3711.rs | 0 .../tools/rustfmt/tests}/target/issue-3717.rs | 0 .../tools/rustfmt/tests}/target/issue-3718.rs | 0 .../tools/rustfmt/tests}/target/issue-3740.rs | 0 .../tools/rustfmt/tests}/target/issue-3741.rs | 0 .../tools/rustfmt/tests}/target/issue-3750.rs | 0 .../tools/rustfmt/tests}/target/issue-3751.rs | 0 .../tools/rustfmt/tests}/target/issue-3759.rs | 0 .../rustfmt/tests}/target/issue-3779/ice.rs | 0 .../rustfmt/tests}/target/issue-3779/lib.rs | 0 .../tools/rustfmt/tests}/target/issue-3786.rs | 0 .../tools/rustfmt/tests}/target/issue-3787.rs | 0 .../tools/rustfmt/tests}/target/issue-3805.rs | 0 .../tools/rustfmt/tests}/target/issue-3815.rs | 0 .../issue-3840/version-one_hard-tabs.rs | 0 .../issue-3840/version-one_soft-tabs.rs | 0 .../issue-3840/version-two_hard-tabs.rs | 0 .../issue-3840/version-two_soft-tabs.rs | 0 .../tools/rustfmt/tests}/target/issue-3845.rs | 0 .../tools/rustfmt/tests}/target/issue-3882.rs | 0 .../tools/rustfmt/tests}/target/issue-3974.rs | 0 .../tools/rustfmt/tests}/target/issue-3984.rs | 0 .../issue-3987/format_macro_bodies_false.rs | 0 .../issue-3987/format_macro_bodies_true.rs | 0 .../tools/rustfmt/tests}/target/issue-4018.rs | 0 .../tools/rustfmt/tests}/target/issue-4020.rs | 0 .../tools/rustfmt/tests}/target/issue-4029.rs | 0 .../rustfmt/tests}/target/issue-4036/one.rs | 0 .../rustfmt/tests}/target/issue-4036/three.rs | 0 .../rustfmt/tests}/target/issue-4036/two.rs | 0 .../tools/rustfmt/tests}/target/issue-4041.rs | 0 .../tools/rustfmt/tests}/target/issue-4068.rs | 0 .../tools/rustfmt/tests}/target/issue-4079.rs | 0 .../tools/rustfmt/tests}/target/issue-4115.rs | 0 .../tools/rustfmt/tests}/target/issue-4120.rs | 0 .../tools/rustfmt/tests}/target/issue-4152.rs | 0 .../tools/rustfmt/tests}/target/issue-4159.rs | 0 .../tests}/target/issue-4210-disabled.rs | 0 .../tools/rustfmt/tests}/target/issue-4210.rs | 0 .../tools/rustfmt/tests}/target/issue-4243.rs | 0 .../tools/rustfmt/tests}/target/issue-4244.rs | 0 .../tools/rustfmt/tests}/target/issue-4245.rs | 0 .../tools/rustfmt/tests}/target/issue-4310.rs | 0 .../tools/rustfmt/tests}/target/issue-4312.rs | 0 .../tools/rustfmt/tests}/target/issue-4313.rs | 0 .../target/issue-4381/style_edition_2015.rs | 0 .../target/issue-4381/style_edition_2024.rs | 0 .../tools/rustfmt/tests}/target/issue-4382.rs | 0 .../tools/rustfmt/tests}/target/issue-4398.rs | 0 .../tools/rustfmt/tests}/target/issue-4427.rs | 0 .../tools/rustfmt/tests}/target/issue-447.rs | 0 .../tools/rustfmt/tests}/target/issue-4530.rs | 0 .../tools/rustfmt/tests}/target/issue-4577.rs | 0 .../tools/rustfmt/tests}/target/issue-4603.rs | 0 .../target/issue-4615/minimum_example.rs | 0 .../tools/rustfmt/tests}/target/issue-4643.rs | 0 .../tools/rustfmt/tests}/target/issue-4646.rs | 0 .../target/issue-4656/format_me_please.rs | 0 .../rustfmt/tests}/target/issue-4656/lib.rs | 0 .../rustfmt/tests}/target/issue-4656/lib2.rs | 0 .../rustfmt/tests}/target/issue-4689/one.rs | 0 .../rustfmt/tests}/target/issue-4689/two.rs | 0 .../rustfmt/tests}/target/issue-4791/buggy.rs | 0 .../tests}/target/issue-4791/issue_4928.rs | 0 .../target/issue-4791/no_trailing_comma.rs | 0 .../target/issue-4791/trailing_comma.rs | 0 .../tools/rustfmt/tests}/target/issue-4808.rs | 0 .../rustfmt/tests}/target/issue-4816/lib.rs | 0 .../rustfmt/tests}/target/issue-4908-2.rs | 0 .../tools/rustfmt/tests}/target/issue-4908.rs | 0 .../target/issue-4926/deeply_nested_struct.rs | 0 ...ply_nested_struct_with_long_field_names.rs | 0 .../deeply_nested_struct_with_many_fields.rs | 0 .../target/issue-4926/enum_struct_field.rs | 0 .../target/issue-4926/minimum_example.rs | 0 .../struct_with_long_field_names.rs | 0 .../issue-4926/struct_with_many_fields.rs | 0 .../target/issue-4984/minimum_example.rs | 0 .../target/issue-4984/multi_line_derive.rs | 0 .../issue-4984/multiple_comments_within.rs | 0 .../target/issue-4984/should_not_change.rs | 0 .../target/issue-5005/minimum_example.rs | 0 .../target/issue-5009/1_minimum_example.rs | 0 .../2_many_in_connectors_in_pattern.rs | 0 ...sted_for_loop_with_connector_in_pattern.rs | 0 .../4_nested_for_loop_with_if_elseif_else.rs | 0 ...r_loop_with_connector_in_if_elseif_else.rs | 0 ...sted_for_loop_with_connector_in_pattern.rs | 0 .../tools/rustfmt/tests}/target/issue-5011.rs | 0 .../issue-5012/trailing_comma_always.rs | 0 .../target/issue-5012/trailing_comma_never.rs | 0 .../tools/rustfmt/tests}/target/issue-5023.rs | 0 .../tools/rustfmt/tests}/target/issue-5030.rs | 0 .../target/issue-5033/minimum_example.rs | 0 .../target/issue-5033/nested_modules.rs | 0 .../multi-line_comment_with_trailing_comma.rs | 0 ...lti-line_comment_without_trailing_comma.rs | 0 ...single-line_comment_with_trailing_comma.rs | 0 ...gle-line_comment_without_trailing_comma.rs | 0 ...railing_comma_always_struct_lit_width_0.rs | 0 ...trailing_comma_never_struct_lit_width_0.rs | 0 ..._line_struct_with_trailing_comma_always.rs | 0 ...i_line_struct_with_trailing_comma_never.rs | 0 .../issue-5066/with_trailing_comma_always.rs | 0 .../issue-5066/with_trailing_comma_never.rs | 0 ...nested_long_comment_wrap_comments_false.rs | 0 ..._nested_long_comment_wrap_comments_true.rs | 0 ...line_itemized_block_wrap_comments_false.rs | 0 ..._line_itemized_block_wrap_comments_true.rs | 0 ...with_itemized_block_wrap_comments_false.rs | 0 ..._with_itemized_block_wrap_comments_true.rs | 0 ...line_itemized_block_wrap_comments_false.rs | 0 ..._line_itemized_block_wrap_comments_true.rs | 0 ...long_itemized_block_wrap_comments_false.rs | 0 ..._long_itemized_block_wrap_comments_true.rs | 0 ..._with_empty_comment_wrap_comments_false.rs | 0 ...t_with_empty_comment_wrap_comments_true.rs | 0 .../very_long_comment_wrap_comments_false.rs | 0 .../very_long_comment_wrap_comments_true.rs | 0 .../tools/rustfmt/tests}/target/issue-5095.rs | 0 .../tools/rustfmt/tests}/target/issue-510.rs | 0 .../attributes_in_formal_fuction_parameter.rs | 0 .../long_parameter_in_different_positions.rs | 0 .../target/issue-5125/minimum_example.rs | 0 .../with_leading_and_inline_comments.rs | 0 .../rustfmt/tests}/target/issue-5136-1.rs | 0 .../rustfmt/tests}/target/issue-5136-2.rs | 0 .../rustfmt/tests}/target/issue-5136-3.rs | 0 .../rustfmt/tests}/target/issue-5136-4.rs | 0 .../rustfmt/tests}/target/issue-5136-5.rs | 0 .../target/issue-5151/minimum_example.rs | 0 .../indented_itemized_markdown_blockquote.rs | 0 .../nested_itemized_markdown_blockquote.rs | 0 .../support_itemized_markdown_blockquote.rs | 0 .../tools/rustfmt/tests}/target/issue-5234.rs | 0 .../markdown_header_wrap_comments_false.rs | 0 .../markdown_header_wrap_comments_true.rs | 0 .../tests}/target/issue-5244/unwrapped.rs | 0 .../tests}/target/issue-5244/wrapped.rs | 0 .../tools/rustfmt/tests}/target/issue-5260.rs | 0 .../target/issue-5270/merge_derives_false.rs | 0 .../target/issue-5270/merge_derives_true.rs | 0 .../tools/rustfmt/tests}/target/issue-5358.rs | 0 .../tools/rustfmt/tests}/target/issue-539.rs | 0 .../tools/rustfmt/tests}/target/issue-5488.rs | 0 .../tools/rustfmt/tests}/target/issue-5568.rs | 0 .../tools/rustfmt/tests}/target/issue-5586.rs | 0 .../rustfmt/tests}/target/issue-5655/one.rs | 0 .../rustfmt/tests}/target/issue-5655/two.rs | 0 .../tools/rustfmt/tests}/target/issue-5791.rs | 0 .../issue-5797/retain_trailing_semicolon.rs | 0 ...ttribute_does_not_wrap_within_max_width.rs | 0 ...ute_unexpectedly_wraps_before_max_width.rs | 0 .../comment_does_not_wrap_within_max_width.rs | 0 ...ent_unexpectedly_wraps_before_max_width.rs | 0 .../tools/rustfmt/tests}/target/issue-5835.rs | 0 .../tests}/target/issue-5852/default.rs | 0 .../tests}/target/issue-5852/horizontal.rs | 0 .../target/issue-5852/horizontal_vertical.rs | 0 .../tests}/target/issue-5852/issue_example.rs | 0 .../rustfmt/tests}/target/issue-5852/split.rs | 0 .../tests}/target/issue-5852/vertical.rs | 0 .../tools/rustfmt/tests}/target/issue-5871.rs | 0 .../tools/rustfmt/tests}/target/issue-5885.rs | 0 .../tools/rustfmt/tests}/target/issue-5935.rs | 0 .../rustfmt/tests}/target/issue-5987/one.rs | 0 .../rustfmt/tests}/target/issue-5987/two.rs | 0 .../tests}/target/issue-6059/additional.rs | 0 .../rustfmt/tests}/target/issue-6059/repro.rs | 0 .../tools/rustfmt/tests}/target/issue-6105.rs | 0 .../tools/rustfmt/tests}/target/issue-6109.rs | 0 .../target/issue-6147/case_rustfmt_v1.rs | 0 .../target/issue-6147/case_rustfmt_v2.rs | 0 .../tests}/target/issue-6202/long_pat.rs | 0 .../tools/rustfmt/tests}/target/issue-6243.rs | 0 .../rustfmt/tests}/target/issue-6333-2024.rs | 0 .../tools/rustfmt/tests}/target/issue-6333.rs | 0 .../tools/rustfmt/tests}/target/issue-64.rs | 0 .../tools/rustfmt/tests}/target/issue-6411.rs | 0 .../tests}/target/issue-6561/trait-fn.rs | 0 .../tests}/target/issue-6561/variadic.rs | 0 .../tests}/target/issue-6607/fn-type.rs | 0 .../tests}/target/issue-6651/custom_width.rs | 0 .../tests}/target/issue-6651/default.rs | 0 .../tools/rustfmt/tests}/target/issue-6788.rs | 0 .../tools/rustfmt/tests}/target/issue-6795.rs | 0 .../tools/rustfmt/tests}/target/issue-6825.rs | 0 .../tools/rustfmt/tests}/target/issue-683.rs | 0 .../tests}/target/issue-6863/empty-stmt.rs | 0 .../tests}/target/issue-6863/fn-stmts.rs | 0 .../tools/rustfmt/tests}/target/issue-691.rs | 0 .../tools/rustfmt/tests}/target/issue-6985.rs | 0 .../tools/rustfmt/tests}/target/issue-7011.rs | 0 .../tools/rustfmt/tests}/target/issue-7054.rs | 0 .../tools/rustfmt/tests}/target/issue-7056.rs | 0 .../tools/rustfmt/tests}/target/issue-770.rs | 0 .../tools/rustfmt/tests}/target/issue-811.rs | 0 .../tools/rustfmt/tests}/target/issue-831.rs | 0 .../tools/rustfmt/tests}/target/issue-850.rs | 0 .../tools/rustfmt/tests}/target/issue-855.rs | 0 .../tools/rustfmt/tests}/target/issue-913.rs | 0 .../tools/rustfmt/tests}/target/issue-945.rs | 0 .../tools/rustfmt/tests}/target/issue-977.rs | 0 .../tools/rustfmt/tests}/target/issue_1306.rs | 0 .../tools/rustfmt/tests}/target/issue_3033.rs | 0 .../tools/rustfmt/tests}/target/issue_3245.rs | 0 .../tools/rustfmt/tests}/target/issue_3561.rs | 0 .../tools/rustfmt/tests}/target/issue_3839.rs | 0 .../tools/rustfmt/tests}/target/issue_3844.rs | 0 .../tools/rustfmt/tests}/target/issue_3853.rs | 0 .../tools/rustfmt/tests}/target/issue_3854.rs | 0 .../tools/rustfmt/tests}/target/issue_3868.rs | 0 .../tools/rustfmt/tests}/target/issue_3934.rs | 0 .../tools/rustfmt/tests}/target/issue_3937.rs | 0 .../tools/rustfmt/tests}/target/issue_4031.rs | 0 .../tools/rustfmt/tests}/target/issue_4032.rs | 0 .../tools/rustfmt/tests}/target/issue_4037.rs | 0 .../tools/rustfmt/tests}/target/issue_4049.rs | 0 .../tools/rustfmt/tests}/target/issue_4057.rs | 0 .../tools/rustfmt/tests}/target/issue_4086.rs | 0 .../tools/rustfmt/tests}/target/issue_4110.rs | 0 .../tools/rustfmt/tests}/target/issue_4257.rs | 0 .../tools/rustfmt/tests}/target/issue_4322.rs | 0 .../tools/rustfmt/tests}/target/issue_4350.rs | 0 .../tools/rustfmt/tests}/target/issue_4374.rs | 0 .../tools/rustfmt/tests}/target/issue_4467.rs | 0 .../tools/rustfmt/tests}/target/issue_4475.rs | 0 .../tools/rustfmt/tests}/target/issue_4522.rs | 0 .../tools/rustfmt/tests}/target/issue_4528.rs | 0 .../tools/rustfmt/tests}/target/issue_4545.rs | 0 .../tools/rustfmt/tests}/target/issue_4573.rs | 0 .../tools/rustfmt/tests}/target/issue_4579.rs | 0 .../tools/rustfmt/tests}/target/issue_4584.rs | 0 .../tools/rustfmt/tests}/target/issue_4635.rs | 0 .../tools/rustfmt/tests}/target/issue_4636.rs | 0 .../tools/rustfmt/tests}/target/issue_4675.rs | 0 .../tools/rustfmt/tests}/target/issue_4823.rs | 0 .../tools/rustfmt/tests}/target/issue_4850.rs | 0 .../tools/rustfmt/tests}/target/issue_4854.rs | 0 .../tools/rustfmt/tests}/target/issue_4868.rs | 0 .../tools/rustfmt/tests}/target/issue_4911.rs | 0 .../tools/rustfmt/tests}/target/issue_4936.rs | 0 .../tools/rustfmt/tests}/target/issue_4943.rs | 0 .../tools/rustfmt/tests}/target/issue_4954.rs | 0 .../tools/rustfmt/tests}/target/issue_4963.rs | 0 .../tools/rustfmt/tests}/target/issue_5027.rs | 0 .../tools/rustfmt/tests}/target/issue_5086.rs | 0 .../tools/rustfmt/tests}/target/issue_5273.rs | 0 .../tools/rustfmt/tests}/target/issue_5399.rs | 0 .../tools/rustfmt/tests}/target/issue_5533.rs | 0 .../tools/rustfmt/tests}/target/issue_5668.rs | 0 .../tools/rustfmt/tests}/target/issue_5676.rs | 0 .../tools/rustfmt/tests}/target/issue_5686.rs | 0 .../tools/rustfmt/tests}/target/issue_5691.rs | 0 .../tools/rustfmt/tests}/target/issue_5721.rs | 0 .../tools/rustfmt/tests}/target/issue_5728.rs | 0 .../tools/rustfmt/tests}/target/issue_5729.rs | 0 .../tools/rustfmt/tests}/target/issue_5730.rs | 0 .../tools/rustfmt/tests}/target/issue_5735.rs | 0 .../tools/rustfmt/tests}/target/issue_5739.rs | 0 .../tools/rustfmt/tests}/target/issue_5882.rs | 0 .../tools/rustfmt/tests}/target/issue_5907.rs | 0 .../tools/rustfmt/tests}/target/issue_5912.rs | 0 .../target/issue_5920_style_edition_2024.rs | 0 .../target/issue_5920_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/target/issue_5973.rs | 0 .../target/issue_5982_style_edition_2024.rs | 0 .../target/issue_5982_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/target/issue_6069.rs | 0 .../tools/rustfmt/tests}/target/issue_6082.rs | 0 .../tools/rustfmt/tests}/target/issue_6158.rs | 0 .../tools/rustfmt/tests}/target/issue_6159.rs | 0 .../tools/rustfmt/tests}/target/issue_6209.rs | 0 .../target/issue_6381_style_edition_2024.rs | 0 .../target/issue_6381_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/target/issue_6513.rs | 0 .../tools/rustfmt/tests}/target/issue_6558.rs | 0 .../tools/rustfmt/tests}/target/issue_6801.rs | 0 .../target/issue_6831_style_edition_2021.rs | 0 .../target/issue_6831_style_edition_2024.rs | 0 .../target/issue_6831_style_edition_2027.rs | 0 .../target/issue_6859_hard_tab_breaks.rs | 0 .../tools/rustfmt/tests}/target/issue_6869.rs | 0 .../tools/rustfmt/tests}/target/issue_6959.rs | 0 .../target/issue_6984_style_edition_2024.rs | 0 .../target/issue_6984_style_edition_2027.rs | 0 .../target/issue_7003_style_edition_2024.rs | 0 .../target/issue_7003_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/target/issue_7036.rs | 0 .../target/issue_7055_style_edition_2024.rs | 0 .../target/issue_7055_style_edition_2027.rs | 0 .../tools/rustfmt/tests}/target/issue_7057.rs | 0 .../tools/rustfmt/tests}/target/issue_7062.rs | 0 .../tests}/target/issue_7088_stable.rs | 0 .../tests}/target/issue_7088_unstable.rs | 0 .../item-brace-style-always-next-line.rs | 0 .../item-brace-style-prefer-same-line.rs | 0 .../item-brace-style-same-line-where.rs | 0 .../tests}/target/itemized-blocks/no_wrap.rs | 0 .../target/itemized-blocks/rewrite_fail.rs | 0 .../tests}/target/itemized-blocks/urls.rs | 0 .../tests}/target/itemized-blocks/wrap.rs | 0 .../tools/rustfmt/tests}/target/keywords.rs | 0 .../rustfmt/tests}/target/label_break.rs | 0 .../rustfmt/tests}/target/large-block.rs | 0 .../tools/rustfmt/tests}/target/large_vec.rs | 0 .../tests}/target/lazy_staic_before_2027.rs | 0 .../rustfmt/tests}/target/lazy_static.rs | 0 .../tools/rustfmt/tests}/target/let_chains.rs | 0 .../tools/rustfmt/tests}/target/let_else.rs | 0 .../rustfmt/tests}/target/let_else_v2.rs | 0 .../tests}/target/long-fn-1/version_one.rs | 0 .../tests}/target/long-fn-1/version_two.rs | 0 .../target/long-match-arms-brace-newline.rs | 0 .../target/long-use-statement-issue-3154.rs | 0 .../tests}/target/long_field_access.rs | 0 .../tools/rustfmt/tests}/target/loop.rs | 0 .../rustfmt/tests}/target/macro_not_expr.rs | 0 .../rustfmt/tests}/target/macro_rules.rs | 0 .../rustfmt/tests}/target/macro_rules_semi.rs | 0 .../tools/rustfmt/tests}/target/macros.rs | 0 .../target/macros/rewrite-const-item.rs | 0 .../target/markdown-comment-with-options.rs | 0 .../rustfmt/tests}/target/markdown-comment.rs | 0 .../target/match-block-trailing-comma.rs | 0 .../rustfmt/tests}/target/match-flattening.rs | 0 .../target/match-nowrap-trailing-comma.rs | 0 .../rustfmt/tests}/target/match-nowrap.rs | 0 .../tools/rustfmt/tests}/target/match.rs | 0 .../tests}/target/match_overflow_expr.rs | 0 .../tests}/target/max-line-length-in-chars.rs | 0 .../target/merge_imports_true_compat.rs | 0 .../tools/rustfmt/tests}/target/mod-1.rs | 0 .../tools/rustfmt/tests}/target/mod-2.rs | 0 .../rustfmt/tests}/target/mod_skip_child.rs | 0 .../tools/rustfmt/tests}/target/mulit-file.rs | 0 .../target/multiline_string_in_macro_def.rs | 0 .../tools/rustfmt/tests}/target/multiple.rs | 0 .../rustfmt/tests}/target/mut-restriction.rs | 0 .../tools/rustfmt/tests}/target/mut_ref.rs | 0 .../target/named-fn-trait-parameters.rs | 0 .../rustfmt/tests}/target/negative-bounds.rs | 0 .../rustfmt/tests}/target/negative-impl.rs | 0 .../rustfmt/tests}/target/nested-if-else.rs | 0 .../tests}/target/nested-visual-block.rs | 0 .../tests}/target/nested_skipped/mod.rs | 0 .../rustfmt/tests}/target/nestedmod/mod.rs | 0 .../rustfmt/tests}/target/nestedmod/mod2a.rs | 0 .../rustfmt/tests}/target/nestedmod/mod2b.rs | 0 .../rustfmt/tests}/target/nestedmod/mod2c.rs | 0 .../tests}/target/nestedmod/mymod1/mod3a.rs | 0 .../tests}/target/nestedmod/submod2/a.rs | 0 .../tests}/target/nestedmod/submod2/mod.rs | 0 .../tests}/target/no_arg_with_comment.rs | 0 .../tests}/target/no_new_line_beginning.rs | 0 .../tests}/target/non-lifetime-binders.rs | 0 ...on_ascii_numerics_import_asciibetically.rs | 0 .../non_ascii_numerics_import_versionsort.rs | 0 ...es_should_not_imply_format_doc_comments.rs | 0 .../normalize_multiline_doc_attribute.rs | 0 .../tests}/target/obsolete_in_place.rs | 0 .../rustfmt/tests}/target/one_line_if_v1.rs | 0 .../rustfmt/tests}/target/one_line_if_v2.rs | 0 .../tools/rustfmt/tests}/target/other.rs | 0 .../tools/rustfmt/tests}/target/paren.rs | 0 .../rustfmt/tests}/target/path_clarity/foo.rs | 0 .../tests}/target/path_clarity/foo/bar.rs | 0 .../tools/rustfmt/tests}/target/paths.rs | 0 .../target/pattern-condense-wildcards.rs | 0 .../tools/rustfmt/tests}/target/pattern.rs | 0 .../tools/rustfmt/tests}/target/pin_sugar.rs | 0 .../tests}/target/postfix-match/pf-match.rs | 0 .../rustfmt/tests}/target/postfix-yield.rs | 0 .../tests}/target/precise-capturing.rs | 0 .../preserves_carriage_return_for_unix.rs | 0 .../preserves_carriage_return_for_windows.rs | 0 .../rustfmt/tests}/target/pub-restricted.rs | 0 .../rustfmt/tests}/target/raw-lifetimes.rs | 0 .../rustfmt/tests}/target/raw_identifiers.rs | 0 .../tests}/target/remove_blank_lines.rs | 0 .../tests}/target/reorder-impl-items.rs | 0 .../tests}/target/reorder_modules/A2/mod.rs | 0 .../tests}/target/reorder_modules/ABCD/mod.rs | 0 .../tests}/target/reorder_modules/ZYXW/mod.rs | 0 .../target/reorder_modules/ZYXW_/mod.rs | 0 .../target/reorder_modules/ZY_XW/mod.rs | 0 .../target/reorder_modules/Z_YXW/mod.rs | 0 .../target/reorder_modules/_ZYXW/mod.rs | 0 .../target/reorder_modules/_abcd/mod.rs | 0 .../tests}/target/reorder_modules/a1/mod.rs | 0 .../target/reorder_modules/abcde/mod.rs | 0 .../disabled_style_edition_2024.rs | 0 .../disabled_style_edition_2027.rs | 0 .../enabled_style_edition_2015.rs | 0 .../enabled_style_edition_2024.rs | 0 .../enabled_style_edition_2027.rs | 0 .../tests}/target/reorder_modules/u128/mod.rs | 0 .../tests}/target/reorder_modules/u16/mod.rs | 0 .../tests}/target/reorder_modules/u256/mod.rs | 0 .../tests}/target/reorder_modules/u32/mod.rs | 0 .../tests}/target/reorder_modules/u64/mod.rs | 0 .../tests}/target/reorder_modules/u8/mod.rs | 0 .../target/reorder_modules/u_zzz/mod.rs | 0 .../tests}/target/reorder_modules/ua/mod.rs | 0 .../target/reorder_modules/usize/mod.rs | 0 .../tests}/target/reorder_modules/uz/mod.rs | 0 .../tests}/target/reorder_modules/v0/mod.rs | 0 .../tests}/target/reorder_modules/v00/mod.rs | 0 .../tests}/target/reorder_modules/v000/mod.rs | 0 .../tests}/target/reorder_modules/v001/mod.rs | 0 .../tests}/target/reorder_modules/v009/mod.rs | 0 .../tests}/target/reorder_modules/v00t/mod.rs | 0 .../tests}/target/reorder_modules/v01/mod.rs | 0 .../tests}/target/reorder_modules/v010/mod.rs | 0 .../tests}/target/reorder_modules/v09/mod.rs | 0 .../tests}/target/reorder_modules/v0s/mod.rs | 0 .../tests}/target/reorder_modules/v0u/mod.rs | 0 .../tests}/target/reorder_modules/v1/mod.rs | 0 .../tests}/target/reorder_modules/v10/mod.rs | 0 .../tests}/target/reorder_modules/v9/mod.rs | 0 .../target/reorder_modules/w005s09t/mod.rs | 0 .../target/reorder_modules/w5s009t/mod.rs | 0 .../tests}/target/reorder_modules/x64/mod.rs | 0 .../tests}/target/reorder_modules/x86/mod.rs | 0 .../target/reorder_modules/x86_128/mod.rs | 0 .../target/reorder_modules/x86_32/mod.rs | 0 .../target/reorder_modules/x86_64/mod.rs | 0 .../tests}/target/reorder_modules/x87/mod.rs | 0 .../target/reorder_modules/zyxwv/mod.rs | 0 .../target/reorder_modules_2027/abcde/mod.rs | 0 .../target/reorder_modules_2027/zyxwv/mod.rs | 0 .../tests}/target/return-type-notation.rs | 0 ...t_string_when_format_strings_is_not_set.rs | 0 .../tests}/target/single-line-if-else.rs | 0 .../tests}/target/single-line-macro/v1.rs | 0 .../tests}/target/single-line-macro/v2.rs | 0 .../tools/rustfmt/tests}/target/skip.rs | 0 .../tools/rustfmt/tests}/target/skip/foo.rs | 0 .../tools/rustfmt/tests}/target/skip/main.rs | 0 .../target/skip/preserve_trailing_comment.rs | 0 .../target/skip_macro_invocations/all.rs | 0 .../skip_macro_invocations/all_and_name.rs | 0 .../skip_macro_invocations/config_file.rs | 0 .../target/skip_macro_invocations/empty.rs | 0 .../target/skip_macro_invocations/name.rs | 0 .../skip_macro_invocations/name_unknown.rs | 0 .../target/skip_macro_invocations/names.rs | 0 .../path_qualified_invocation_mismatch.rs | 0 .../path_qualified_match.rs | 0 .../path_qualified_name_mismatch.rs | 0 .../use_alias_examples.rs | 0 .../tools/rustfmt/tests}/target/skip_mod.rs | 0 .../rustfmt/tests}/target/soft-wrapping.rs | 0 .../tests}/target/space-not-before-newline.rs | 0 .../tests}/target/spaces-around-ranges.rs | 0 .../tools/rustfmt/tests}/target/splat.rs | 0 .../tools/rustfmt/tests}/target/statements.rs | 0 .../tools/rustfmt/tests}/target/static.rs | 0 .../rustfmt/tests}/target/string-lit-2.rs | 0 .../tests}/target/string-lit-custom.rs | 0 .../tools/rustfmt/tests}/target/string-lit.rs | 0 .../tests}/target/string_lit_unicode_ws.rs | 0 .../tests}/target/string_punctuation.rs | 0 .../tests}/target/struct-field-attributes.rs | 0 .../tests}/target/struct_field_doc_comment.rs | 0 .../rustfmt/tests}/target/struct_lits.rs | 0 .../tests}/target/struct_lits_multiline.rs | 0 .../tests}/target/struct_lits_visual.rs | 0 .../target/struct_lits_visual_multiline.rs | 0 .../tests}/target/struct_tuple_visual.rs | 0 .../tools/rustfmt/tests}/target/structs.rs | 0 .../tests}/target/style_edition/default.rs | 0 .../target/style_edition/follows_edition.rs | 0 .../overrides_edition_when_set.rs | 0 .../tools/rustfmt/tests}/target/super_let.rs | 0 .../tests}/target/trailing-comma-never.rs | 0 ...-bodies-edition-2021-style-edition-2027.rs | 0 ...-bodies-edition-2024-style-edition-2024.rs | 0 .../target/trailing-semicolon/loop-bodies.rs | 0 .../rustfmt/tests}/target/trailing_commas.rs | 0 .../target/trailing_comments/hard_tabs.rs | 0 .../target/trailing_comments/soft_tabs.rs | 0 .../tools/rustfmt/tests}/target/trait.rs | 0 .../rustfmt/tests}/target/try-conversion.rs | 0 .../tools/rustfmt/tests}/target/try_block.rs | 0 .../tests}/target/try_blocks_heterogeneous.rs | 0 .../tools/rustfmt/tests}/target/tuple.rs | 0 .../tools/rustfmt/tests}/target/tuple_v2.rs | 0 .../type-alias-where-clauses-with-comments.rs | 0 .../tests}/target/type-alias-where-clauses.rs | 0 .../tools/rustfmt/tests}/target/type.rs | 0 .../tools/rustfmt/tests}/target/type_alias.rs | 0 .../tools/rustfmt/tests}/target/unicode.rs | 0 .../target/unindent_if_else_cond_comment.rs | 0 .../tools/rustfmt/tests}/target/unions.rs | 0 .../rustfmt/tests}/target/unsafe-binders.rs | 0 .../rustfmt/tests}/target/unsafe-field.rs | 0 .../tools/rustfmt/tests}/target/unsafe-mod.rs | 0 .../tests}/target/unsafe_attributes.rs | 0 .../tests}/target/unsafe_extern_blocks.rs | 0 .../use-identifier-order-mixed-edition.rs | 0 .../tests}/target/use-identifier-order.rs | 0 .../tools/rustfmt/tests}/target/visibility.rs | 0 .../rustfmt/tests}/target/visual-fn-type.rs | 0 .../rustfmt/tests}/target/where-clause-rfc.rs | 0 .../rustfmt/tests}/target/where-clause.rs | 0 .../rustfmt/tests}/target/width-heuristics.rs | 0 ...ts_should_not_imply_format_doc_comments.rs | 0 .../warning/snapshots/deprecated_skip.snap | 0 .../warning/snapshots/invalid_attribute.snap | 0 .../tests}/warning/snapshots/issue_3950.snap | 0 .../tests}/warning/snapshots/issue_4968.snap | 0 .../tests}/warning/snapshots/issue_6442.snap | 0 .../tests}/warning/snapshots/issue_6632.snap | 0 .../tests}/warning/snapshots/issue_6826.snap | 0 .../tests}/warning/snapshots/issue_6850.snap | 0 .../warning/snapshots/line_overflow.snap | 0 .../warning/snapshots/line_overflow_tabs.snap | 0 ...ine_overflow_with_trailing_whitespace.snap | 0 .../warning/snapshots/lost_comment.snap | 0 .../warning/snapshots/multiple_errors.snap | 0 .../snapshots/trailing_whitespace.snap | 0 .../trailing_whitespace_overflow.snap | 0 .../unicode_trailing_whitespace.snap | 0 .../tests}/warning/source/deprecated_skip.rs | 0 .../warning/source/invalid_attribute.rs | 0 .../tests}/warning/source/issue_3950.rs | 0 .../tests}/warning/source/issue_4968.rs | 0 .../tests}/warning/source/issue_6442.rs | 0 .../tests}/warning/source/issue_6632.rs | 0 .../tests}/warning/source/issue_6826.rs | 0 .../tests}/warning/source/issue_6850.rs | 0 .../tests}/warning/source/line_overflow.rs | 0 .../warning/source/line_overflow_tabs.rs | 0 .../line_overflow_with_trailing_whitespace.rs | 0 .../tests}/warning/source/lost_comment.rs | 0 .../tests}/warning/source/multiple_errors.rs | 0 .../warning/source/trailing_whitespace.rs | 0 .../source/trailing_whitespace_overflow.rs | 0 .../source/unicode_trailing_whitespace.rs | 0 .../tests}/writemode/source/fn-single-line.rs | 0 .../rustfmt/tests}/writemode/source/json.rs | 0 .../tests}/writemode/source/modified.rs | 0 .../rustfmt/tests}/writemode/source/stdin.rs | 0 .../tests}/writemode/target/checkstyle.xml | 0 .../tests}/writemode/target/modified.txt | 0 .../tests}/writemode/target/output.json | 0 .../tests}/writemode/target/stdin.json | 0 .../rustfmt/tests}/writemode/target/stdin.xml | 0 .../tools/rustfmt/triagebot.toml | 0 2132 files changed, 60 insertions(+) rename .editorconfig => src/tools/rustfmt/.editorconfig (100%) rename .gitattributes => src/tools/rustfmt/.gitattributes (100%) rename {.github => src/tools/rustfmt/.github}/FUNDING.yml (100%) rename {.github => src/tools/rustfmt/.github}/ISSUE_TEMPLATE/bug.md (100%) rename {.github => src/tools/rustfmt/.github}/ISSUE_TEMPLATE/feature-request.md (100%) rename {.github => src/tools/rustfmt/.github}/ISSUE_TEMPLATE/ice.md (100%) rename {.github => src/tools/rustfmt/.github}/ISSUE_TEMPLATE/regression.md (100%) rename {.github => src/tools/rustfmt/.github}/pull_request_template.md (100%) rename {.github => src/tools/rustfmt/.github}/workflows/check_diff.yml (100%) rename {.github => src/tools/rustfmt/.github}/workflows/clippy.yml (100%) rename {.github => src/tools/rustfmt/.github}/workflows/integration.yml (100%) rename {.github => src/tools/rustfmt/.github}/workflows/rustdoc_check.yml (100%) rename {.github => src/tools/rustfmt/.github}/workflows/test.yml (100%) rename {.github => src/tools/rustfmt/.github}/workflows/upload-assets.yml (100%) rename .gitignore => src/tools/rustfmt/.gitignore (100%) rename CHANGELOG.md => src/tools/rustfmt/CHANGELOG.md (100%) rename CODE_OF_CONDUCT.md => src/tools/rustfmt/CODE_OF_CONDUCT.md (100%) rename Cargo.lock => src/tools/rustfmt/Cargo.lock (100%) rename Cargo.toml => src/tools/rustfmt/Cargo.toml (100%) rename Configurations.md => src/tools/rustfmt/Configurations.md (100%) rename Contributing.md => src/tools/rustfmt/Contributing.md (100%) rename Design.md => src/tools/rustfmt/Design.md (100%) rename LICENSE-APACHE => src/tools/rustfmt/LICENSE-APACHE (100%) rename LICENSE-MIT => src/tools/rustfmt/LICENSE-MIT (100%) rename Processes.md => src/tools/rustfmt/Processes.md (100%) rename README.md => src/tools/rustfmt/README.md (100%) rename Subtree sync procedure.md => src/tools/rustfmt/Subtree sync procedure.md (100%) rename atom.md => src/tools/rustfmt/atom.md (100%) rename bootstrap.sh => src/tools/rustfmt/bootstrap.sh (100%) rename build.rs => src/tools/rustfmt/build.rs (100%) rename {check_diff => src/tools/rustfmt/check_diff}/.gitignore (100%) rename {check_diff => src/tools/rustfmt/check_diff}/Cargo.lock (100%) rename {check_diff => src/tools/rustfmt/check_diff}/Cargo.toml (100%) rename {check_diff => src/tools/rustfmt/check_diff}/src/lib.rs (100%) rename {check_diff => src/tools/rustfmt/check_diff}/src/main.rs (100%) rename {check_diff => src/tools/rustfmt/check_diff}/tests/bash_commands.rs (100%) rename {check_diff => src/tools/rustfmt/check_diff}/tests/check_diff.rs (100%) rename {check_diff => src/tools/rustfmt/check_diff}/tests/git.rs (100%) rename {ci => src/tools/rustfmt/ci}/Cargo.lock (100%) rename {ci => src/tools/rustfmt/ci}/Cargo.toml (100%) rename {ci => src/tools/rustfmt/ci}/src/build_and_test.rs (100%) rename {ci => src/tools/rustfmt/ci}/src/clippy_config_check.rs (100%) rename {ci => src/tools/rustfmt/ci}/src/common.rs (100%) rename {ci => src/tools/rustfmt/ci}/src/integration.rs (100%) rename {ci => src/tools/rustfmt/ci}/src/main.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/.gitignore (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/Cargo.lock (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/Cargo.toml (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/attrs.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/config_type.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/item_enum.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/item_struct.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/lib.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/src/utils.rs (100%) rename {config_proc_macro => src/tools/rustfmt/config_proc_macro}/tests/smoke.rs (100%) rename {docs => src/tools/rustfmt/docs}/index.html (100%) rename intellij.md => src/tools/rustfmt/intellij.md (100%) rename rust-toolchain => src/tools/rustfmt/rust-toolchain (100%) rename rustfmt.toml => src/tools/rustfmt/rustfmt.toml (100%) rename src/{ => tools/rustfmt/src}/attr.rs (100%) rename src/{ => tools/rustfmt/src}/attr/doc_comment.rs (100%) rename src/{ => tools/rustfmt/src}/bin/main.rs (100%) rename src/{ => tools/rustfmt/src}/cargo-fmt/main.rs (100%) rename src/{ => tools/rustfmt/src}/cargo-fmt/test/message_format.rs (100%) rename src/{ => tools/rustfmt/src}/cargo-fmt/test/mod.rs (100%) rename src/{ => tools/rustfmt/src}/cargo-fmt/test/targets.rs (100%) rename src/{ => tools/rustfmt/src}/chains.rs (100%) rename src/{ => tools/rustfmt/src}/closures.rs (100%) rename src/{ => tools/rustfmt/src}/comment.rs (100%) rename src/{ => tools/rustfmt/src}/config/config_type.rs (100%) rename src/{ => tools/rustfmt/src}/config/file_lines.rs (100%) rename src/{ => tools/rustfmt/src}/config/lists.rs (100%) rename src/{ => tools/rustfmt/src}/config/macro_names.rs (100%) rename src/{ => tools/rustfmt/src}/config/mod.rs (100%) rename src/{ => tools/rustfmt/src}/config/options.rs (100%) rename src/{ => tools/rustfmt/src}/config/style_edition.rs (100%) rename src/{ => tools/rustfmt/src}/coverage.rs (100%) rename src/{ => tools/rustfmt/src}/emitter.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/checkstyle.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/checkstyle/xml.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/diff.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/files.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/files_with_backup.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/json.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/modified_lines.rs (100%) rename src/{ => tools/rustfmt/src}/emitter/stdout.rs (100%) rename src/{ => tools/rustfmt/src}/expr.rs (100%) rename src/{ => tools/rustfmt/src}/format-diff/main.rs (100%) rename src/{ => tools/rustfmt/src}/format-diff/test/bindgen.diff (100%) rename src/{ => tools/rustfmt/src}/format_report_formatter.rs (100%) rename src/{ => tools/rustfmt/src}/formatting.rs (100%) rename src/{ => tools/rustfmt/src}/formatting/generated.rs (100%) rename src/{ => tools/rustfmt/src}/formatting/newline_style.rs (100%) rename src/{ => tools/rustfmt/src}/git-rustfmt/main.rs (100%) rename src/{ => tools/rustfmt/src}/header.rs (100%) rename src/{ => tools/rustfmt/src}/ignore_path.rs (100%) rename src/{ => tools/rustfmt/src}/imports.rs (100%) rename src/{ => tools/rustfmt/src}/items.rs (100%) rename src/{ => tools/rustfmt/src}/lib.rs (100%) rename src/{ => tools/rustfmt/src}/lists.rs (100%) rename src/{ => tools/rustfmt/src}/macros.rs (100%) rename src/{ => tools/rustfmt/src}/matches.rs (100%) rename src/{ => tools/rustfmt/src}/missed_spans.rs (100%) rename src/{ => tools/rustfmt/src}/modules.rs (100%) rename src/{ => tools/rustfmt/src}/modules/visitor.rs (100%) rename src/{ => tools/rustfmt/src}/overflow.rs (100%) rename src/{ => tools/rustfmt/src}/pairs.rs (100%) rename src/{ => tools/rustfmt/src}/parse/macros/asm.rs (100%) rename src/{ => tools/rustfmt/src}/parse/macros/cfg_if.rs (100%) rename src/{ => tools/rustfmt/src}/parse/macros/cfg_select.rs (100%) rename src/{ => tools/rustfmt/src}/parse/macros/lazy_static.rs (100%) rename src/{ => tools/rustfmt/src}/parse/macros/mod.rs (100%) rename src/{ => tools/rustfmt/src}/parse/mod.rs (100%) rename src/{ => tools/rustfmt/src}/parse/parser.rs (100%) rename src/{ => tools/rustfmt/src}/parse/session.rs (100%) rename src/{ => tools/rustfmt/src}/patterns.rs (100%) rename src/{ => tools/rustfmt/src}/range.rs (100%) rename src/{ => tools/rustfmt/src}/release_channel.rs (100%) rename src/{ => tools/rustfmt/src}/reorder.rs (100%) rename src/{ => tools/rustfmt/src}/rewrite.rs (100%) rename src/{ => tools/rustfmt/src}/rustfmt_diff.rs (100%) rename src/{ => tools/rustfmt/src}/shape.rs (100%) rename src/{ => tools/rustfmt/src}/skip.rs (100%) rename src/{ => tools/rustfmt/src}/sort.rs (100%) rename src/{ => tools/rustfmt/src}/source_file.rs (100%) rename src/{ => tools/rustfmt/src}/source_map.rs (100%) rename src/{ => tools/rustfmt/src}/spanned.rs (100%) rename src/{ => tools/rustfmt/src}/stmt.rs (100%) rename src/{ => tools/rustfmt/src}/string.rs (100%) rename src/{ => tools/rustfmt/src}/test/configuration_snippet.rs (100%) rename src/{ => tools/rustfmt/src}/test/mod.rs (100%) rename src/{ => tools/rustfmt/src}/test/mod_resolver.rs (100%) rename src/{ => tools/rustfmt/src}/test/parser.rs (100%) rename src/{ => tools/rustfmt/src}/types.rs (100%) rename src/{ => tools/rustfmt/src}/utils.rs (100%) rename src/{ => tools/rustfmt/src}/vertical.rs (100%) rename src/{ => tools/rustfmt/src}/visitor.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/divergent-crate-dir-names/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issue_3164/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issue_3164/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issues_6517/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issues_6517/inner_bin/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/config/disable_all_formatting.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-1111.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-2641.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-3779.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-5801-v1.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-5801-v2.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-5816.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/issue-6302.toml (100%) create mode 100644 src/tools/rustfmt/tests/config/issue_4660/Cargo.lock create mode 100644 src/tools/rustfmt/tests/config/issue_4660/Cargo.toml create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml create mode 100644 src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs rename {tests => src/tools/rustfmt/tests}/config/skip_children.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/small_tabs.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/just-style-edition/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/just-version/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/overrides/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/style-edition-and-edition/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/version-edition/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/version-style-edition-and-edition/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/config/style-edition/version-style-edition/rustfmt.toml (100%) rename {tests => src/tools/rustfmt/tests}/coverage/source/comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/coverage/target/comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-4874/bar/baz.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-4874/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-4874/foo/qux.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-4874/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5063/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5063/foo/bar/baz.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5063/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5167/src/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5167/src/a/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5167/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/d.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/d/explanation.txt (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/d/f.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/d/g/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/e.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/c/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/issue-5198/lib/explanation.txt (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/module-not-found/bad_path_attribute/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/module-not-found/relative_module/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/module-not-found/relative_module/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/module-not-found/sibling_module/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/skip-files-issue-5065/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/skip-files-issue-5065/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/skip-files-issue-5065/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/Cargo.toml (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/src/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/tests/test1.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/issue-4126/invalid.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/issue-4126/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/issue_4418.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/stashed-diag.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/stashed-diag2.rs (100%) rename {tests => src/tools/rustfmt/tests}/parser/unclosed-delims/issue_4466.rs (100%) rename {tests => src/tools/rustfmt/tests}/rustfmt/main.rs (92%) rename {tests => src/tools/rustfmt/tests}/source/5131_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/5131_module.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/5131_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/alignment_2633/block_style.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/alignment_2633/visual_style.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/array_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/arrow_in_comments/arrow_in_single_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/arrow_in_comments/multiple_arrows.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/assignment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/associated-types-bounds-wrapping.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/associated_type_bounds.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/async_block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/async_fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/attrib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/big-impl-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/big-impl-visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binary-expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/bitwise.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/comp.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/logic.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/math.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/binop-separator-back/range.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/break-and-continue.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/catch.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/mips.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/mips64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/powerpc64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/arch/x86.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/bit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/cache.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/error_macros.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/freebsd/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/freebsd/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/freebsd/auxvec.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/freebsd/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/freebsd/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/auxvec.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/cpuinfo.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/mips.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/linux/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/detect/os/x86.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_if/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/dir/dir1/dir2/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/dir/dir1/dir3/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_mod/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/format_me_please_1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/format_me_please_2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/format_me_please_3.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/format_me_please_4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select/lib2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/cfg_select_stable.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/chain_yield_with_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/chains-visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/chains.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/chains_with_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/closure-block-inside-macro.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/closure-block-labels.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/closure.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment3.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment5.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment6.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comment_crlf_newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comments-in-lists/wrap-comments-not-normalized.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comments-in-lists/wrap-comments-true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/comments_unicode.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/blank_lines_lower_bound/1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/blank_lines_upper_bound/1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/blank_lines_upper_bound/2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/fn_always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/fn_prefer_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/fn_same_line_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/item_always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/item_prefer_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/brace_style/item_same_line_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/chain_width/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/chain_width/small.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/chain_width/tiny.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/comment_width/above.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/comment_width/below.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/comment_width/ignore.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/condense_wildcard_suffixes/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/condense_wildcard_suffixes/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/control_brace_style/always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/control_brace_style/always_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/control_brace_style/closing_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/disable_all_formatting/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/disable_all_formatting/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/doc_comment_code_block_small_heuristics/default-to-max.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/doc_comment_code_block_small_heuristics/max-to-default.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/doc_comment_code_block_width/100.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/doc_comment_code_block_width/100_greater_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/doc_comment_code_block_width/50.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/empty_item_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/empty_item_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/enum_discrim_align_threshold/40.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/error_on_line_overflow/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/float_literal_trailing_zero/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/float_literal_trailing_zero/if-no-postfix.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/float_literal_trailing_zero/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_params_layout/compressed.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_params_layout/tall.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_params_layout/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_params_layout/vertical_style_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/fn_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/force_explicit_abi/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/force_explicit_abi/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/force_multiline_block/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/force_multiline_block/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/false_with_marker_out_scope_size.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/false_with_zero_search_limit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/true_with_marker_in_scope_size.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_generated_files/true_with_marker_not_in_header.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_macro_bodies/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_macro_bodies/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_macro_matchers/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_macro_matchers/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_strings/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/format_strings/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/One-merge_imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/One-nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/One-no_reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/One.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/StdExternalCrate-merge_imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/StdExternalCrate-nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/StdExternalCrate-no_reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/StdExternalCrate-non_consecutive.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/group_imports/StdExternalCrate.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/hard_tabs/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/hard_tabs/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/hex_literal_case/hex_literal_lower.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/hex_literal_case/hex_literal_preserve.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/hex_literal_case/hex_literal_upper.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/imports_layout/merge_mixed.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_args.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_array.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_call.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_chain.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_generic.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_struct_lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_trailing_comma_call/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_trailing_comma_call/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/block_where_pred.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/rfc_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_args.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_array.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_call.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_chain.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_generics.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_struct_lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/indent_style/visual_where_pred.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_blocks/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_blocks/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/attrs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/guards.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/leading_pipes.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_indent/unindent.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_leading_pipes/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_leading_pipes/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_arm_leading_pipes/preserve.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_block_trailing_comma/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/match_block_trailing_comma/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/merge_derives/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/normalize_comments/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/normalize_comments/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/normalize_doc_attributes/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/normalize_doc_attributes/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/remove_nested_parens/remove_nested_parens.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_impl_items/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_impl_items/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_imports/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_imports/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/dolor/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/ipsum/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/lorem/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/sit/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/reorder_modules/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/short_array_element_width_threshold/10.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/short_array_element_width_threshold/20.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/short_array_element_width_threshold/greater_than_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/single_line_let_else_max_width/100.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/single_line_let_else_max_width/50.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/single_line_let_else_max_width/zero.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/skip_children/foo/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/skip_children/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/space_before_colon/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/spaces_around_ranges/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/spaces_around_ranges/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/struct_field_align_threshold/20.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/struct_lit_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/style_edition/overflow_delim_expr_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/style_edition/overflow_delim_expr_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/tab_spaces/2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/tab_spaces/4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/trailing_comma/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/trailing_comma/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/trailing_comma/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/type_punctuation_density/compressed.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/type_punctuation_density/wide.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_field_init_shorthand/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_field_init_shorthand/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_small_heuristics/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_small_heuristics/max.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_small_heuristics/off.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_try_shorthand/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/use_try_shorthand/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/where_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/wrap_comments/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/configs/wrap_comments/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/const-block-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/const_generics.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/control-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/control-brace-style-always-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/default-field-values.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/direct_const_arg.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/doc-attrib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/doc-comment-with-example.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/doc.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/dyn_trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/else-if-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/else-if-brace-style-always-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/else-if-brace-style-closing-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/empty-item-single-line-false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/empty_file.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/enum.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/ergonomic_clones.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/existential_type.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/expr-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/expr-overflow-delimited.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/extern.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/extern_not_explicit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-5.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-6.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-7.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/file-lines-item.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-6.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-7.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom-8.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-custom.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-param-attributes.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-simple.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-single-line/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn-single-line/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn_args_indent-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/fn_args_layout-vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/frontmatter_compact.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/frontmatter_escaped.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/frontmatter_spaced.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/generic_static.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/hello.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/hello2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/if_while_or_patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/immovable_coroutines.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/impl-restriction.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/impls.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports-impl-only-use.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports-reorder-lines-and-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports-reorder-lines.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports-reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_block_indent.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_default-with-dups.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_item-with-dups.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_item.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_module.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports/imports_granularity_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports_raw_identifiers/version_One.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/imports_raw_identifiers/version_Two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/invalid-rust-code-in-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1021.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1049.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1111.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1120.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1124.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1127.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1158.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1177.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1192.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1210/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1210/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1210/c.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1210/d.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1210/e.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1211.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1216.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1239.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1278.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1350.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1366.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1468.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1693.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1800.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-1914.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2025.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2111.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2164.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2179/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2179/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2256.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2342.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2445.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2446.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2479.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2482/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2482/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2482/c.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2496.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2520.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2523.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2582.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2641.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2644.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2728.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2761.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2781.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2794.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2835.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2863.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2869.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2896.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2916.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2917/packed_simd.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2922.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2927-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2927.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2930.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2936.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2955.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2973.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2977/impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2977/trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2985.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-2995.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3029.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3038.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3049.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3055/original.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3059.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3066.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3131.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3153.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3158.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3194.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3198.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3213/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3213/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3217.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3227/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3234.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3241.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/paths/bar_foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/paths/excluded.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3253/paths/foo_bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3265.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3270/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3270/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3272/v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3272/v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3278/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3278/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3295/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3302.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3343.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3423.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3434/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3434/no_entry.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3434/not_skip_macro.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3465.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3494/crlf.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3494/lf.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3508.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3515.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3532.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3585/extern_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3585/reorder_imports_disabled.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3585/reorder_imports_enabled.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3585/use.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3636.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3639.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3651.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3665/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3665/not_skip_attribute.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3665/sub_mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3672.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3675.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3701/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3701/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3709.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3740.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3750.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3751.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3779/ice.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3779/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3786.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3787.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3805.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3840/version-one_hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3840/version-one_soft-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3840/version-two_hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3840/version-two_soft-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3984.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-3987/format_macro_bodies_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4018.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4036/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4036/three.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4036/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4041.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4079.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4120.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4243.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4244.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4245.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4312.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4381/style_edition_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4382.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4398.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4427.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-447.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4530.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4577.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4603.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4615/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4643.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4646.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4656/format_me_please.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4656/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4656/lib2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4689/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4689/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4791/buggy.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4791/trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4808.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4816/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/deeply_nested_struct.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/deeply_nested_struct_with_long_field_names.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/deeply_nested_struct_with_many_fields.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/enum_struct_field.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/struct_with_long_field_names.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4926/struct_with_many_fields.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4984/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4984/multi_line_derive.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-4984/multiple_comments_within.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5011.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5023.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5030.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5042/multi-line_comment_with_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5042/multi-line_comment_without_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5042/single-line_comment_with_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5042/single-line_comment_without_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5088/very_long_comment_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-510.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5136-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5136-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5136-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5136-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5136-5.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5157/indented_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5157/nested_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5157/support_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5234.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5238/markdown_header_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5238/markdown_header_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5260.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5270/merge_derives_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-539.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5488.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5586.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5655/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5655/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5791.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5835.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/horizontal.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/horizontal_vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/issue_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/split.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5852/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5935.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-5987/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6059/repro.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6147/case_rustfmt_v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6147/case_rustfmt_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6202/long_pat.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6243.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6333.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6561/trait-fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6561/variadic.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6607/fn-type.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6651/custom_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6651/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6788.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6795.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6825.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-683.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6863/empty-stmt.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6863/fn-stmts.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-6985.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-7011.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-7054.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-7056.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-811.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-850.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-855.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-913.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-945.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue-977.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_1306.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3245.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3561.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3839.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3844.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3853.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_3868.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4032.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4037.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4057.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4086.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4257.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4322.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4374.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4475.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4528.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4579.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4584.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4636.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4675.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4823.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4854.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4911.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4943.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4954.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_4963.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5086.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5686.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5721.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5730.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5735.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5739.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5882.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5912.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5920_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5920_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5982_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_5982_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6209.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6381_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6558.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6801.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6831_style_edition_2021.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6831_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_6831_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7003_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7003_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7036.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7055_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7055_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7088_stable.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/issue_7088_unstable.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/item-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/item-brace-style-prefer-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/item-brace-style-same-line-where.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/itemized-blocks/no_wrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/itemized-blocks/rewrite_fail.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/itemized-blocks/urls.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/itemized-blocks/wrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/label_break.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/large-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/large_vec.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/lazy_staic_before_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/lazy_static.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/let_chains.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/let_else.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/let_else_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/long-fn-1/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/long-fn-1/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/long-match-arms-brace-newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/long-use-statement-issue-3154.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/long_field_access.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/loop.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/macro_not_expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/macro_rules.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/macros.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/macros/rewrite-const-item.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/markdown-comment-with-options.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/markdown-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match-block-trailing-comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match-flattening.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match-nowrap-trailing-comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match-nowrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/match_overflow_expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/max-line-length-in-chars.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/merge_imports_true_compat.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/mod-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/mod-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/mod_skip_child.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/multiple.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/mut-restriction.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/mut_ref.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/negative-impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nested-if-else.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nested_skipped/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/mod2a.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/mod2b.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/mod2c.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/mymod1/mod3a.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/submod2/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/nestedmod/submod2/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/no_arg_with_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/no_new_line_beginning.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/non-lifetime-binders.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/non_ascii_numerics_import_asciibetically.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/non_ascii_numerics_import_versionsort.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/normalize_doc_attributes_should_not_imply_format_doc_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/normalize_multiline_doc_attribute.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/one_line_if_v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/one_line_if_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/paren.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/path_clarity/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/path_clarity/foo/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/paths.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/pattern-condense-wildcards.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/pattern.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/pin_sugar.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/postfix-match/pf-match.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/precise-capturing.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/preserves_carriage_return_for_unix.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/preserves_carriage_return_for_windows.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/pub-restricted.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/remove_blank_lines.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder-impl-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/A2/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/ABCD/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/ZYXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/ZYXW_/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/ZY_XW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/Z_YXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/_ZYXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/_abcd/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/a1/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/abcde/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/disabled_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/disabled_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/enabled_style_edition_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/enabled_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/enabled_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u128/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u16/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u256/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u32/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u8/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/u_zzz/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/ua/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/usize/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/uz/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v0/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v00/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v000/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v001/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v009/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v00t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v01/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v010/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v09/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v0s/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v0u/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v1/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v10/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/v9/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/w005s09t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/w5s009t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x86/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x86_128/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x86_32/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x86_64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/x87/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules/zyxwv/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules_2027/abcde/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/reorder_modules_2027/zyxwv/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/single-line-if-else.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/single-line-macro/v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/single-line-macro/v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/all.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/all_and_name.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/config_file.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/empty.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/name.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/name_unknown.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/names.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/path_qualified_match.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/path_qualified_name_mismatch.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/skip_macro_invocations/use_alias_examples.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/soft-wrapping.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/space-not-before-newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/spaces-around-ranges.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/statements.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/static.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/string-lit-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/string-lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/string_lit_unicode_ws.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/string_punctuation.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct-field-attributes.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_field_doc_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_lits.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_lits_multiline.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_lits_visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_lits_visual_multiline.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/struct_tuple_visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/structs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/super_let.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing-comma-never.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing-semicolon/loop-bodies.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing_commas.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing_comments/hard_tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trailing_comments/soft_tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/try-conversion.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/try_block.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/try_blocks_heterogeneous.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/tuple.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/tuple_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/type-alias-where-clauses-with-comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/type-alias-where-clauses.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/type.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/type_alias.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/unicode.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/unions.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/unsafe-binders.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/unsafe-field.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/unsafe-mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/use-identifier-order-mixed-edition.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/use-identifier-order.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/visibility.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/visual-fn-type.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/where-clause-rfc.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/where-clause.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/width-heuristics.rs (100%) rename {tests => src/tools/rustfmt/tests}/source/wrap_comments_should_not_imply_format_doc_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/5131_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/5131_module.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/5131_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/alignment_2633/block_style.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/alignment_2633/horizontal_tactic.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/alignment_2633/visual_style.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/array_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/arrow_in_comments/arrow_in_single_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/arrow_in_comments/multiple_arrows.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/assignment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/associated-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/associated-types-bounds-wrapping.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/associated_type_bounds.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/associated_type_defaults.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/async_block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/async_closure.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/async_fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/asyncness.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/attrib-block-expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/attrib-extern-crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/attrib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/big-impl-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/big-impl-visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binary-expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/bitwise.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/comp.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/logic.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/math.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/binop-separator-back/range.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/break-and-continue.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/catch.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_attribute_in_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/mips.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/mips64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/powerpc64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/arch/x86.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/bit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/cache.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/error_macros.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/freebsd/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/freebsd/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/freebsd/auxvec.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/freebsd/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/freebsd/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/aarch64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/arm.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/auxvec.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/cpuinfo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/mips.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/linux/powerpc.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/detect/os/x86.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_if/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/dir/dir1/dir2/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/dir/dir1/dir3/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_mod/wasm32.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/format_me_please_1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/format_me_please_2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/format_me_please_3.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/format_me_please_4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select/lib2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/cfg_select_stable.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/chain_yield_with_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/chains-visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/chains.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/chains_with_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/closure-block-inside-macro.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/closure-block-labels.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/closure.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment-inside-const.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment-not-disappear.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment3.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment5.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment6.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comment_crlf_newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments-fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments-in-lists/format-doc-comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments-in-lists/wrap-comments-false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments-in-lists/wrap-comments-not-normalized.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments-in-lists/wrap-comments-true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/comments_unicode.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/blank_lines_lower_bound/1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/blank_lines_upper_bound/1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/blank_lines_upper_bound/2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/fn_always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/fn_prefer_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/fn_same_line_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/item_always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/item_prefer_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/brace_style/item_same_line_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/chain_width/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/chain_width/small.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/chain_width/tiny.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/combine_control_expr/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/combine_control_expr/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/comment_width/above.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/comment_width/below.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/comment_width/ignore.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/condense_wildcard_suffixes/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/condense_wildcard_suffixes/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/control_brace_style/always_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/control_brace_style/always_same_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/control_brace_style/closing_next_line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/disable_all_formatting/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/disable_all_formatting/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/doc_comment_code_block_small_heuristics/default-to-max.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/doc_comment_code_block_small_heuristics/max-to-default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/doc_comment_code_block_width/100.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/doc_comment_code_block_width/100_greater_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/doc_comment_code_block_width/50.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/empty_item_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/empty_item_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/enum_discrim_align_threshold/40.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/error_on_line_overflow/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/error_on_unformatted/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/always_spaces_around_ranges_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/if-no-postfix.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/if-no-postfix_spaces_around_ranges_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/never_spaces_around_ranges_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/preserve.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/float_literal_trailing_zero/preserve_spaces_around_ranges_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_params_layout/compressed.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_params_layout/tall.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_params_layout/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_params_layout/vertical_style_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/fn_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/force_explicit_abi/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/force_explicit_abi/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/force_multiline_block/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/force_multiline_block/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/false_with_marker_out_scope_size.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/false_with_zero_search_limit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/true_with_marker_in_scope_size.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_generated_files/true_with_marker_not_in_header.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_macro_bodies/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_macro_bodies/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_macro_matchers/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_macro_matchers/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_strings/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/format_strings/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/One-merge_imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/One-nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/One-no_reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/One.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/StdExternalCrate-merge_imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/StdExternalCrate-nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/StdExternalCrate-no_reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/StdExternalCrate-non_consecutive.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/group_imports/StdExternalCrate.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/hard_tabs/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/hard_tabs/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/hex_literal_case/hex_literal_lower.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/hex_literal_case/hex_literal_preserve.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/hex_literal_case/hex_literal_upper.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/imports_indent/block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/imports_layout/horizontal_vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/imports_layout/merge_mixed.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/imports_layout/mixed.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_args.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_array.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_call.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_chain.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_generic.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_struct_lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_tab_spaces_call.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_trailing_comma_call/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_trailing_comma_call/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/block_where_pred.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/rfc_control.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/rfc_where.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_args.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_array.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_call.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_chain.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_generics.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_struct_lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/indent_style/visual_where_pred.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_blocks/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_blocks/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/attrs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/guards.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/leading_pipes.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/nested.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/noindent-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/noindent.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_indent/unindent.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_leading_pipes/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_leading_pipes/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_arm_leading_pipes/preserve.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_block_trailing_comma/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/match_block_trailing_comma/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/merge_derives/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/normalize_comments/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/normalize_comments/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/normalize_doc_attributes/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/normalize_doc_attributes/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/remove_nested_parens/remove_nested_parens.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_impl_items/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_impl_items/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_imports/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_imports/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/dolor/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/ipsum/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/lorem/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/sit/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/reorder_modules/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/short_array_element_width_threshold/10.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/short_array_element_width_threshold/20.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/short_array_element_width_threshold/greater_than_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/single_line_let_else_max_width/100.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/single_line_let_else_max_width/50.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/single_line_let_else_max_width/zero.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/skip_children/foo/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/skip_children/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/space_before_colon/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/spaces_around_ranges/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/spaces_around_ranges/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/struct_field_align_threshold/20.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/struct_lit_single_line/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/style_edition/overflow_delim_expr_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/style_edition/overflow_delim_expr_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/tab_spaces/2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/tab_spaces/4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/trailing_comma/always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/trailing_comma/never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/trailing_comma/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/trailing_semicolon/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/trailing_semicolon/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/type_punctuation_density/compressed.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/type_punctuation_density/wide.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_field_init_shorthand/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_field_init_shorthand/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_small_heuristics/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_small_heuristics/max.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_small_heuristics/off.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_try_shorthand/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/use_try_shorthand/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/version/mapped.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/where_single_line/true-with-brace-style.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/where_single_line/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/wrap_comments/false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/configs/wrap_comments/true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/const-block-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/const-generics.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/const_generics.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/const_trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/control-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/control-brace-style-always-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/default-field-values.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/direct_const_arg.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/doc-attrib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/doc-comment-with-example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/doc-of-generic-item.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/doc.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/dyn_trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/else-if-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/else-if-brace-style-always-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/else-if-brace-style-closing-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/empty-item-single-line-false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/empty-tuple-no-conversion-to-unit-struct.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/empty_file.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/enum.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/ergonomic_clones.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/existential_type.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/expr-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/expr-overflow-delimited.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/extern-rust.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/extern.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/extern_not_explicit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/field-representing-types.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-5.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-6.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-7.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/file-lines-item.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/final-kw.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-args-with-last-line-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-6.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-7.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom-8.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-custom.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-param-attributes.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-simple.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-single-line/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-single-line/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn-ty.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn_args_indent-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn_args_layout-vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/fn_once.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/format_strings/issue-202.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/format_strings/issue-2833.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/format_strings/issue-3263.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/format_strings/issue-687.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/format_strings/issue564.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/frontmatter_compact.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/frontmatter_escaped.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/frontmatter_spaced.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/generic_static.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/guard_patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/hello.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/if_while_or_patterns.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/immovable_coroutines.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/impl-restriction.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/impls.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/import-fencepost-length.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports-impl-only-use.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports-reorder-lines-and-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports-reorder-lines.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports-reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_2021_edition.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_block_indent.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_default-with-dups.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_item-with-dups.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_item.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_module.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports/imports_granularity_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports_raw_identifiers/version_One.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/imports_raw_identifiers/version_Two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/indented-impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/inner-module-path/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/inner-module-path/c/d.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/inner-module-path/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/invalid-rust-code-in-doc-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1021.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1049.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1055.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1096.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1111.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1113.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1120.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1124.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1127.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1158.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1177.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1192.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1210/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1210/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1210/c.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1210/d.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1210/e.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1211.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1214.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1216.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1239.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1247.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1255.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1278.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1350.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1366.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1397.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1468.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1598.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1624.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1681.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1693.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1703.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1800.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1802.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1824.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-1914.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2025.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2103.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2111.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2123.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2164.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2179/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2179/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2197.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2256.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2324.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2329.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2342.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2346.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2401.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2445.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2446.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2479.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2482/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2482/b.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2482/c.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2496.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2520.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2523.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2526.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2534/format_macro_matchers_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2534/format_macro_matchers_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2551.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2554.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2582.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2641.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2644.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2673-nonmodrs-mods/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2673-nonmodrs-mods/foo/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2673-nonmodrs-mods/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2728.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2759.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2761.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2781.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2794.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2810.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2835.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2863.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2869.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2896.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2916.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2917/minimal.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2917/packed_simd.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2922.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2927-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2927.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2930.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2936.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2941.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2955.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2973.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2976.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2977/block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2977/impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2977/item.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2977/trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2985.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-2995.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3029.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3032.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3038.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3043.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3049.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3055/backtick.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3055/empty-code-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3055/original.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3059.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3066.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3105.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3118.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3124.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3131.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3132.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3153.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3158.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3182.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3184.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3194.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3198.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3213/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3213/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3217.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3224.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3227/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3227/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3234.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3241.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/paths/bar_foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/paths/excluded.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3253/paths/foo_bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3265.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3270/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3270/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3270/wrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3272/v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3272/v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3278/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3278/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3295/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3302.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3304.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3314.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3343.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3423.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3434/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3434/no_entry.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3434/not_skip_macro.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3442.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3465.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3494/crlf.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3494/lf.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3499.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3508.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3515.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3532.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3539.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3554.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3567.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3568.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3585/extern_crate.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3585/reorder_imports_disabled.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3585/reorder_imports_enabled.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3585/use.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3595.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3601.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3614/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3614/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3636.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3639.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3645.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3651.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3665/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3665/not_skip_attribute.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3665/sub_mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3672.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3675.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3701/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3701/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3709.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3711.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3717.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3718.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3740.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3741.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3750.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3751.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3759.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3779/ice.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3779/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3786.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3787.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3805.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3815.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3840/version-one_hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3840/version-one_soft-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3840/version-two_hard-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3840/version-two_soft-tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3845.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3882.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3974.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3984.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3987/format_macro_bodies_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-3987/format_macro_bodies_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4018.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4020.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4029.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4036/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4036/three.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4036/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4041.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4068.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4079.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4115.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4120.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4152.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4159.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4210-disabled.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4210.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4243.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4244.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4245.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4310.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4312.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4313.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4381/style_edition_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4381/style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4382.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4398.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4427.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-447.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4530.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4577.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4603.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4615/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4643.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4646.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4656/format_me_please.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4656/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4656/lib2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4689/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4689/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4791/buggy.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4791/issue_4928.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4791/no_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4791/trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4808.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4816/lib.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4908-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4908.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/deeply_nested_struct.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/deeply_nested_struct_with_long_field_names.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/deeply_nested_struct_with_many_fields.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/enum_struct_field.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/struct_with_long_field_names.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4926/struct_with_many_fields.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4984/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4984/multi_line_derive.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4984/multiple_comments_within.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-4984/should_not_change.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5005/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/1_minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/2_many_in_connectors_in_pattern.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5011.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5012/trailing_comma_always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5012/trailing_comma_never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5023.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5030.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5033/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5033/nested_modules.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5042/multi-line_comment_with_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5042/multi-line_comment_without_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5042/single-line_comment_with_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5042/single-line_comment_without_trailing_comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/with_trailing_comma_always.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5066/with_trailing_comma_never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/very_long_comment_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5088/very_long_comment_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5095.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-510.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5125/attributes_in_formal_fuction_parameter.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5125/long_parameter_in_different_positions.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5125/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5125/with_leading_and_inline_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5136-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5136-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5136-3.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5136-4.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5136-5.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5151/minimum_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5157/indented_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5157/nested_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5157/support_itemized_markdown_blockquote.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5234.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5238/markdown_header_wrap_comments_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5238/markdown_header_wrap_comments_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5244/unwrapped.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5244/wrapped.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5260.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5270/merge_derives_false.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5270/merge_derives_true.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5358.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-539.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5488.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5568.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5586.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5655/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5655/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5791.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5797/retain_trailing_semicolon.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5801/attribute_does_not_wrap_within_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5801/comment_does_not_wrap_within_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5835.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/horizontal.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/horizontal_vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/issue_example.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/split.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5852/vertical.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5871.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5885.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5935.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5987/one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-5987/two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6059/additional.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6059/repro.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6105.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6109.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6147/case_rustfmt_v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6147/case_rustfmt_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6202/long_pat.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6243.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6333-2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6333.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-64.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6411.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6561/trait-fn.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6561/variadic.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6607/fn-type.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6651/custom_width.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6651/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6788.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6795.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6825.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-683.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6863/empty-stmt.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6863/fn-stmts.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-691.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-6985.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-7011.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-7054.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-7056.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-770.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-811.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-831.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-850.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-855.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-913.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-945.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue-977.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_1306.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3033.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3245.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3561.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3839.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3844.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3853.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3854.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3868.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3934.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_3937.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4031.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4032.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4037.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4049.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4057.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4086.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4110.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4257.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4322.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4350.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4374.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4467.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4475.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4522.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4528.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4545.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4573.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4579.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4584.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4635.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4636.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4675.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4823.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4850.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4854.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4868.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4911.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4936.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4943.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4954.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_4963.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5086.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5273.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5399.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5533.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5668.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5676.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5686.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5691.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5721.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5728.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5729.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5730.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5735.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5739.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5882.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5907.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5912.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5920_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5920_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5973.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5982_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_5982_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6069.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6082.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6158.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6159.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6209.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6381_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6381_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6513.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6558.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6801.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6831_style_edition_2021.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6831_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6831_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6859_hard_tab_breaks.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6869.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6959.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6984_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_6984_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7003_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7003_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7036.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7055_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7055_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7057.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7062.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7088_stable.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/issue_7088_unstable.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/item-brace-style-always-next-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/item-brace-style-prefer-same-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/item-brace-style-same-line-where.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/itemized-blocks/no_wrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/itemized-blocks/rewrite_fail.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/itemized-blocks/urls.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/itemized-blocks/wrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/keywords.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/label_break.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/large-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/large_vec.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/lazy_staic_before_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/lazy_static.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/let_chains.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/let_else.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/let_else_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/long-fn-1/version_one.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/long-fn-1/version_two.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/long-match-arms-brace-newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/long-use-statement-issue-3154.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/long_field_access.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/loop.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/macro_not_expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/macro_rules.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/macro_rules_semi.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/macros.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/macros/rewrite-const-item.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/markdown-comment-with-options.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/markdown-comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match-block-trailing-comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match-flattening.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match-nowrap-trailing-comma.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match-nowrap.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/match_overflow_expr.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/max-line-length-in-chars.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/merge_imports_true_compat.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mod-1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mod-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mod_skip_child.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mulit-file.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/multiline_string_in_macro_def.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/multiple.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mut-restriction.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/mut_ref.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/named-fn-trait-parameters.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/negative-bounds.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/negative-impl.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nested-if-else.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nested-visual-block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nested_skipped/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/mod2a.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/mod2b.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/mod2c.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/mymod1/mod3a.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/submod2/a.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/nestedmod/submod2/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/no_arg_with_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/no_new_line_beginning.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/non-lifetime-binders.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/non_ascii_numerics_import_asciibetically.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/non_ascii_numerics_import_versionsort.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/normalize_doc_attributes_should_not_imply_format_doc_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/normalize_multiline_doc_attribute.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/obsolete_in_place.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/one_line_if_v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/one_line_if_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/other.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/paren.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/path_clarity/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/path_clarity/foo/bar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/paths.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/pattern-condense-wildcards.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/pattern.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/pin_sugar.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/postfix-match/pf-match.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/postfix-yield.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/precise-capturing.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/preserves_carriage_return_for_unix.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/preserves_carriage_return_for_windows.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/pub-restricted.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/raw-lifetimes.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/raw_identifiers.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/remove_blank_lines.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder-impl-items.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/A2/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/ABCD/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/ZYXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/ZYXW_/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/ZY_XW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/Z_YXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/_ZYXW/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/_abcd/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/a1/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/abcde/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/disabled_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/disabled_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/enabled_style_edition_2015.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/enabled_style_edition_2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/enabled_style_edition_2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u128/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u16/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u256/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u32/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u8/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/u_zzz/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/ua/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/usize/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/uz/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v0/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v00/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v000/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v001/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v009/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v00t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v01/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v010/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v09/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v0s/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v0u/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v1/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v10/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/v9/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/w005s09t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/w5s009t/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x86/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x86_128/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x86_32/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x86_64/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/x87/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules/zyxwv/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules_2027/abcde/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/reorder_modules_2027/zyxwv/mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/return-type-notation.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/should_not_format_string_when_format_strings_is_not_set.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/single-line-if-else.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/single-line-macro/v1.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/single-line-macro/v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip/foo.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip/main.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip/preserve_trailing_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/all.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/all_and_name.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/config_file.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/empty.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/name.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/name_unknown.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/names.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/path_qualified_match.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/path_qualified_name_mismatch.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_macro_invocations/use_alias_examples.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/skip_mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/soft-wrapping.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/space-not-before-newline.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/spaces-around-ranges.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/splat.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/statements.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/static.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/string-lit-2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/string-lit-custom.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/string-lit.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/string_lit_unicode_ws.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/string_punctuation.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct-field-attributes.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_field_doc_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_lits.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_lits_multiline.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_lits_visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_lits_visual_multiline.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/struct_tuple_visual.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/structs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/style_edition/default.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/style_edition/follows_edition.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/style_edition/overrides_edition_when_set.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/super_let.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing-comma-never.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing-semicolon/loop-bodies.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing_commas.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing_comments/hard_tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trailing_comments/soft_tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/trait.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/try-conversion.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/try_block.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/try_blocks_heterogeneous.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/tuple.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/tuple_v2.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/type-alias-where-clauses-with-comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/type-alias-where-clauses.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/type.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/type_alias.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unicode.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unindent_if_else_cond_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unions.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unsafe-binders.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unsafe-field.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unsafe-mod.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unsafe_attributes.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/unsafe_extern_blocks.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/use-identifier-order-mixed-edition.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/use-identifier-order.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/visibility.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/visual-fn-type.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/where-clause-rfc.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/where-clause.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/width-heuristics.rs (100%) rename {tests => src/tools/rustfmt/tests}/target/wrap_comments_should_not_imply_format_doc_comments.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/deprecated_skip.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/invalid_attribute.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_3950.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_4968.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_6442.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_6632.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_6826.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/issue_6850.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/line_overflow.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/line_overflow_tabs.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/line_overflow_with_trailing_whitespace.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/lost_comment.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/multiple_errors.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/trailing_whitespace.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/trailing_whitespace_overflow.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/snapshots/unicode_trailing_whitespace.snap (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/deprecated_skip.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/invalid_attribute.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_3950.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_4968.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_6442.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_6632.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_6826.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/issue_6850.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/line_overflow.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/line_overflow_tabs.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/line_overflow_with_trailing_whitespace.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/lost_comment.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/multiple_errors.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/trailing_whitespace.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/trailing_whitespace_overflow.rs (100%) rename {tests => src/tools/rustfmt/tests}/warning/source/unicode_trailing_whitespace.rs (100%) rename {tests => src/tools/rustfmt/tests}/writemode/source/fn-single-line.rs (100%) rename {tests => src/tools/rustfmt/tests}/writemode/source/json.rs (100%) rename {tests => src/tools/rustfmt/tests}/writemode/source/modified.rs (100%) rename {tests => src/tools/rustfmt/tests}/writemode/source/stdin.rs (100%) rename {tests => src/tools/rustfmt/tests}/writemode/target/checkstyle.xml (100%) rename {tests => src/tools/rustfmt/tests}/writemode/target/modified.txt (100%) rename {tests => src/tools/rustfmt/tests}/writemode/target/output.json (100%) rename {tests => src/tools/rustfmt/tests}/writemode/target/stdin.json (100%) rename {tests => src/tools/rustfmt/tests}/writemode/target/stdin.xml (100%) rename triagebot.toml => src/tools/rustfmt/triagebot.toml (100%) diff --git a/.editorconfig b/src/tools/rustfmt/.editorconfig similarity index 100% rename from .editorconfig rename to src/tools/rustfmt/.editorconfig diff --git a/.gitattributes b/src/tools/rustfmt/.gitattributes similarity index 100% rename from .gitattributes rename to src/tools/rustfmt/.gitattributes diff --git a/.github/FUNDING.yml b/src/tools/rustfmt/.github/FUNDING.yml similarity index 100% rename from .github/FUNDING.yml rename to src/tools/rustfmt/.github/FUNDING.yml diff --git a/.github/ISSUE_TEMPLATE/bug.md b/src/tools/rustfmt/.github/ISSUE_TEMPLATE/bug.md similarity index 100% rename from .github/ISSUE_TEMPLATE/bug.md rename to src/tools/rustfmt/.github/ISSUE_TEMPLATE/bug.md diff --git a/.github/ISSUE_TEMPLATE/feature-request.md b/src/tools/rustfmt/.github/ISSUE_TEMPLATE/feature-request.md similarity index 100% rename from .github/ISSUE_TEMPLATE/feature-request.md rename to src/tools/rustfmt/.github/ISSUE_TEMPLATE/feature-request.md diff --git a/.github/ISSUE_TEMPLATE/ice.md b/src/tools/rustfmt/.github/ISSUE_TEMPLATE/ice.md similarity index 100% rename from .github/ISSUE_TEMPLATE/ice.md rename to src/tools/rustfmt/.github/ISSUE_TEMPLATE/ice.md diff --git a/.github/ISSUE_TEMPLATE/regression.md b/src/tools/rustfmt/.github/ISSUE_TEMPLATE/regression.md similarity index 100% rename from .github/ISSUE_TEMPLATE/regression.md rename to src/tools/rustfmt/.github/ISSUE_TEMPLATE/regression.md diff --git a/.github/pull_request_template.md b/src/tools/rustfmt/.github/pull_request_template.md similarity index 100% rename from .github/pull_request_template.md rename to src/tools/rustfmt/.github/pull_request_template.md diff --git a/.github/workflows/check_diff.yml b/src/tools/rustfmt/.github/workflows/check_diff.yml similarity index 100% rename from .github/workflows/check_diff.yml rename to src/tools/rustfmt/.github/workflows/check_diff.yml diff --git a/.github/workflows/clippy.yml b/src/tools/rustfmt/.github/workflows/clippy.yml similarity index 100% rename from .github/workflows/clippy.yml rename to src/tools/rustfmt/.github/workflows/clippy.yml diff --git a/.github/workflows/integration.yml b/src/tools/rustfmt/.github/workflows/integration.yml similarity index 100% rename from .github/workflows/integration.yml rename to src/tools/rustfmt/.github/workflows/integration.yml diff --git a/.github/workflows/rustdoc_check.yml b/src/tools/rustfmt/.github/workflows/rustdoc_check.yml similarity index 100% rename from .github/workflows/rustdoc_check.yml rename to src/tools/rustfmt/.github/workflows/rustdoc_check.yml diff --git a/.github/workflows/test.yml b/src/tools/rustfmt/.github/workflows/test.yml similarity index 100% rename from .github/workflows/test.yml rename to src/tools/rustfmt/.github/workflows/test.yml diff --git a/.github/workflows/upload-assets.yml b/src/tools/rustfmt/.github/workflows/upload-assets.yml similarity index 100% rename from .github/workflows/upload-assets.yml rename to src/tools/rustfmt/.github/workflows/upload-assets.yml diff --git a/.gitignore b/src/tools/rustfmt/.gitignore similarity index 100% rename from .gitignore rename to src/tools/rustfmt/.gitignore diff --git a/CHANGELOG.md b/src/tools/rustfmt/CHANGELOG.md similarity index 100% rename from CHANGELOG.md rename to src/tools/rustfmt/CHANGELOG.md diff --git a/CODE_OF_CONDUCT.md b/src/tools/rustfmt/CODE_OF_CONDUCT.md similarity index 100% rename from CODE_OF_CONDUCT.md rename to src/tools/rustfmt/CODE_OF_CONDUCT.md diff --git a/Cargo.lock b/src/tools/rustfmt/Cargo.lock similarity index 100% rename from Cargo.lock rename to src/tools/rustfmt/Cargo.lock diff --git a/Cargo.toml b/src/tools/rustfmt/Cargo.toml similarity index 100% rename from Cargo.toml rename to src/tools/rustfmt/Cargo.toml diff --git a/Configurations.md b/src/tools/rustfmt/Configurations.md similarity index 100% rename from Configurations.md rename to src/tools/rustfmt/Configurations.md diff --git a/Contributing.md b/src/tools/rustfmt/Contributing.md similarity index 100% rename from Contributing.md rename to src/tools/rustfmt/Contributing.md diff --git a/Design.md b/src/tools/rustfmt/Design.md similarity index 100% rename from Design.md rename to src/tools/rustfmt/Design.md diff --git a/LICENSE-APACHE b/src/tools/rustfmt/LICENSE-APACHE similarity index 100% rename from LICENSE-APACHE rename to src/tools/rustfmt/LICENSE-APACHE diff --git a/LICENSE-MIT b/src/tools/rustfmt/LICENSE-MIT similarity index 100% rename from LICENSE-MIT rename to src/tools/rustfmt/LICENSE-MIT diff --git a/Processes.md b/src/tools/rustfmt/Processes.md similarity index 100% rename from Processes.md rename to src/tools/rustfmt/Processes.md diff --git a/README.md b/src/tools/rustfmt/README.md similarity index 100% rename from README.md rename to src/tools/rustfmt/README.md diff --git a/Subtree sync procedure.md b/src/tools/rustfmt/Subtree sync procedure.md similarity index 100% rename from Subtree sync procedure.md rename to src/tools/rustfmt/Subtree sync procedure.md diff --git a/atom.md b/src/tools/rustfmt/atom.md similarity index 100% rename from atom.md rename to src/tools/rustfmt/atom.md diff --git a/bootstrap.sh b/src/tools/rustfmt/bootstrap.sh similarity index 100% rename from bootstrap.sh rename to src/tools/rustfmt/bootstrap.sh diff --git a/build.rs b/src/tools/rustfmt/build.rs similarity index 100% rename from build.rs rename to src/tools/rustfmt/build.rs diff --git a/check_diff/.gitignore b/src/tools/rustfmt/check_diff/.gitignore similarity index 100% rename from check_diff/.gitignore rename to src/tools/rustfmt/check_diff/.gitignore diff --git a/check_diff/Cargo.lock b/src/tools/rustfmt/check_diff/Cargo.lock similarity index 100% rename from check_diff/Cargo.lock rename to src/tools/rustfmt/check_diff/Cargo.lock diff --git a/check_diff/Cargo.toml b/src/tools/rustfmt/check_diff/Cargo.toml similarity index 100% rename from check_diff/Cargo.toml rename to src/tools/rustfmt/check_diff/Cargo.toml diff --git a/check_diff/src/lib.rs b/src/tools/rustfmt/check_diff/src/lib.rs similarity index 100% rename from check_diff/src/lib.rs rename to src/tools/rustfmt/check_diff/src/lib.rs diff --git a/check_diff/src/main.rs b/src/tools/rustfmt/check_diff/src/main.rs similarity index 100% rename from check_diff/src/main.rs rename to src/tools/rustfmt/check_diff/src/main.rs diff --git a/check_diff/tests/bash_commands.rs b/src/tools/rustfmt/check_diff/tests/bash_commands.rs similarity index 100% rename from check_diff/tests/bash_commands.rs rename to src/tools/rustfmt/check_diff/tests/bash_commands.rs diff --git a/check_diff/tests/check_diff.rs b/src/tools/rustfmt/check_diff/tests/check_diff.rs similarity index 100% rename from check_diff/tests/check_diff.rs rename to src/tools/rustfmt/check_diff/tests/check_diff.rs diff --git a/check_diff/tests/git.rs b/src/tools/rustfmt/check_diff/tests/git.rs similarity index 100% rename from check_diff/tests/git.rs rename to src/tools/rustfmt/check_diff/tests/git.rs diff --git a/ci/Cargo.lock b/src/tools/rustfmt/ci/Cargo.lock similarity index 100% rename from ci/Cargo.lock rename to src/tools/rustfmt/ci/Cargo.lock diff --git a/ci/Cargo.toml b/src/tools/rustfmt/ci/Cargo.toml similarity index 100% rename from ci/Cargo.toml rename to src/tools/rustfmt/ci/Cargo.toml diff --git a/ci/src/build_and_test.rs b/src/tools/rustfmt/ci/src/build_and_test.rs similarity index 100% rename from ci/src/build_and_test.rs rename to src/tools/rustfmt/ci/src/build_and_test.rs diff --git a/ci/src/clippy_config_check.rs b/src/tools/rustfmt/ci/src/clippy_config_check.rs similarity index 100% rename from ci/src/clippy_config_check.rs rename to src/tools/rustfmt/ci/src/clippy_config_check.rs diff --git a/ci/src/common.rs b/src/tools/rustfmt/ci/src/common.rs similarity index 100% rename from ci/src/common.rs rename to src/tools/rustfmt/ci/src/common.rs diff --git a/ci/src/integration.rs b/src/tools/rustfmt/ci/src/integration.rs similarity index 100% rename from ci/src/integration.rs rename to src/tools/rustfmt/ci/src/integration.rs diff --git a/ci/src/main.rs b/src/tools/rustfmt/ci/src/main.rs similarity index 100% rename from ci/src/main.rs rename to src/tools/rustfmt/ci/src/main.rs diff --git a/config_proc_macro/.gitignore b/src/tools/rustfmt/config_proc_macro/.gitignore similarity index 100% rename from config_proc_macro/.gitignore rename to src/tools/rustfmt/config_proc_macro/.gitignore diff --git a/config_proc_macro/Cargo.lock b/src/tools/rustfmt/config_proc_macro/Cargo.lock similarity index 100% rename from config_proc_macro/Cargo.lock rename to src/tools/rustfmt/config_proc_macro/Cargo.lock diff --git a/config_proc_macro/Cargo.toml b/src/tools/rustfmt/config_proc_macro/Cargo.toml similarity index 100% rename from config_proc_macro/Cargo.toml rename to src/tools/rustfmt/config_proc_macro/Cargo.toml diff --git a/config_proc_macro/src/attrs.rs b/src/tools/rustfmt/config_proc_macro/src/attrs.rs similarity index 100% rename from config_proc_macro/src/attrs.rs rename to src/tools/rustfmt/config_proc_macro/src/attrs.rs diff --git a/config_proc_macro/src/config_type.rs b/src/tools/rustfmt/config_proc_macro/src/config_type.rs similarity index 100% rename from config_proc_macro/src/config_type.rs rename to src/tools/rustfmt/config_proc_macro/src/config_type.rs diff --git a/config_proc_macro/src/item_enum.rs b/src/tools/rustfmt/config_proc_macro/src/item_enum.rs similarity index 100% rename from config_proc_macro/src/item_enum.rs rename to src/tools/rustfmt/config_proc_macro/src/item_enum.rs diff --git a/config_proc_macro/src/item_struct.rs b/src/tools/rustfmt/config_proc_macro/src/item_struct.rs similarity index 100% rename from config_proc_macro/src/item_struct.rs rename to src/tools/rustfmt/config_proc_macro/src/item_struct.rs diff --git a/config_proc_macro/src/lib.rs b/src/tools/rustfmt/config_proc_macro/src/lib.rs similarity index 100% rename from config_proc_macro/src/lib.rs rename to src/tools/rustfmt/config_proc_macro/src/lib.rs diff --git a/config_proc_macro/src/utils.rs b/src/tools/rustfmt/config_proc_macro/src/utils.rs similarity index 100% rename from config_proc_macro/src/utils.rs rename to src/tools/rustfmt/config_proc_macro/src/utils.rs diff --git a/config_proc_macro/tests/smoke.rs b/src/tools/rustfmt/config_proc_macro/tests/smoke.rs similarity index 100% rename from config_proc_macro/tests/smoke.rs rename to src/tools/rustfmt/config_proc_macro/tests/smoke.rs diff --git a/docs/index.html b/src/tools/rustfmt/docs/index.html similarity index 100% rename from docs/index.html rename to src/tools/rustfmt/docs/index.html diff --git a/intellij.md b/src/tools/rustfmt/intellij.md similarity index 100% rename from intellij.md rename to src/tools/rustfmt/intellij.md diff --git a/rust-toolchain b/src/tools/rustfmt/rust-toolchain similarity index 100% rename from rust-toolchain rename to src/tools/rustfmt/rust-toolchain diff --git a/rustfmt.toml b/src/tools/rustfmt/rustfmt.toml similarity index 100% rename from rustfmt.toml rename to src/tools/rustfmt/rustfmt.toml diff --git a/src/attr.rs b/src/tools/rustfmt/src/attr.rs similarity index 100% rename from src/attr.rs rename to src/tools/rustfmt/src/attr.rs diff --git a/src/attr/doc_comment.rs b/src/tools/rustfmt/src/attr/doc_comment.rs similarity index 100% rename from src/attr/doc_comment.rs rename to src/tools/rustfmt/src/attr/doc_comment.rs diff --git a/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs similarity index 100% rename from src/bin/main.rs rename to src/tools/rustfmt/src/bin/main.rs diff --git a/src/cargo-fmt/main.rs b/src/tools/rustfmt/src/cargo-fmt/main.rs similarity index 100% rename from src/cargo-fmt/main.rs rename to src/tools/rustfmt/src/cargo-fmt/main.rs diff --git a/src/cargo-fmt/test/message_format.rs b/src/tools/rustfmt/src/cargo-fmt/test/message_format.rs similarity index 100% rename from src/cargo-fmt/test/message_format.rs rename to src/tools/rustfmt/src/cargo-fmt/test/message_format.rs diff --git a/src/cargo-fmt/test/mod.rs b/src/tools/rustfmt/src/cargo-fmt/test/mod.rs similarity index 100% rename from src/cargo-fmt/test/mod.rs rename to src/tools/rustfmt/src/cargo-fmt/test/mod.rs diff --git a/src/cargo-fmt/test/targets.rs b/src/tools/rustfmt/src/cargo-fmt/test/targets.rs similarity index 100% rename from src/cargo-fmt/test/targets.rs rename to src/tools/rustfmt/src/cargo-fmt/test/targets.rs diff --git a/src/chains.rs b/src/tools/rustfmt/src/chains.rs similarity index 100% rename from src/chains.rs rename to src/tools/rustfmt/src/chains.rs diff --git a/src/closures.rs b/src/tools/rustfmt/src/closures.rs similarity index 100% rename from src/closures.rs rename to src/tools/rustfmt/src/closures.rs diff --git a/src/comment.rs b/src/tools/rustfmt/src/comment.rs similarity index 100% rename from src/comment.rs rename to src/tools/rustfmt/src/comment.rs diff --git a/src/config/config_type.rs b/src/tools/rustfmt/src/config/config_type.rs similarity index 100% rename from src/config/config_type.rs rename to src/tools/rustfmt/src/config/config_type.rs diff --git a/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs similarity index 100% rename from src/config/file_lines.rs rename to src/tools/rustfmt/src/config/file_lines.rs diff --git a/src/config/lists.rs b/src/tools/rustfmt/src/config/lists.rs similarity index 100% rename from src/config/lists.rs rename to src/tools/rustfmt/src/config/lists.rs diff --git a/src/config/macro_names.rs b/src/tools/rustfmt/src/config/macro_names.rs similarity index 100% rename from src/config/macro_names.rs rename to src/tools/rustfmt/src/config/macro_names.rs diff --git a/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs similarity index 100% rename from src/config/mod.rs rename to src/tools/rustfmt/src/config/mod.rs diff --git a/src/config/options.rs b/src/tools/rustfmt/src/config/options.rs similarity index 100% rename from src/config/options.rs rename to src/tools/rustfmt/src/config/options.rs diff --git a/src/config/style_edition.rs b/src/tools/rustfmt/src/config/style_edition.rs similarity index 100% rename from src/config/style_edition.rs rename to src/tools/rustfmt/src/config/style_edition.rs diff --git a/src/coverage.rs b/src/tools/rustfmt/src/coverage.rs similarity index 100% rename from src/coverage.rs rename to src/tools/rustfmt/src/coverage.rs diff --git a/src/emitter.rs b/src/tools/rustfmt/src/emitter.rs similarity index 100% rename from src/emitter.rs rename to src/tools/rustfmt/src/emitter.rs diff --git a/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs similarity index 100% rename from src/emitter/checkstyle.rs rename to src/tools/rustfmt/src/emitter/checkstyle.rs diff --git a/src/emitter/checkstyle/xml.rs b/src/tools/rustfmt/src/emitter/checkstyle/xml.rs similarity index 100% rename from src/emitter/checkstyle/xml.rs rename to src/tools/rustfmt/src/emitter/checkstyle/xml.rs diff --git a/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs similarity index 100% rename from src/emitter/diff.rs rename to src/tools/rustfmt/src/emitter/diff.rs diff --git a/src/emitter/files.rs b/src/tools/rustfmt/src/emitter/files.rs similarity index 100% rename from src/emitter/files.rs rename to src/tools/rustfmt/src/emitter/files.rs diff --git a/src/emitter/files_with_backup.rs b/src/tools/rustfmt/src/emitter/files_with_backup.rs similarity index 100% rename from src/emitter/files_with_backup.rs rename to src/tools/rustfmt/src/emitter/files_with_backup.rs diff --git a/src/emitter/json.rs b/src/tools/rustfmt/src/emitter/json.rs similarity index 100% rename from src/emitter/json.rs rename to src/tools/rustfmt/src/emitter/json.rs diff --git a/src/emitter/modified_lines.rs b/src/tools/rustfmt/src/emitter/modified_lines.rs similarity index 100% rename from src/emitter/modified_lines.rs rename to src/tools/rustfmt/src/emitter/modified_lines.rs diff --git a/src/emitter/stdout.rs b/src/tools/rustfmt/src/emitter/stdout.rs similarity index 100% rename from src/emitter/stdout.rs rename to src/tools/rustfmt/src/emitter/stdout.rs diff --git a/src/expr.rs b/src/tools/rustfmt/src/expr.rs similarity index 100% rename from src/expr.rs rename to src/tools/rustfmt/src/expr.rs diff --git a/src/format-diff/main.rs b/src/tools/rustfmt/src/format-diff/main.rs similarity index 100% rename from src/format-diff/main.rs rename to src/tools/rustfmt/src/format-diff/main.rs diff --git a/src/format-diff/test/bindgen.diff b/src/tools/rustfmt/src/format-diff/test/bindgen.diff similarity index 100% rename from src/format-diff/test/bindgen.diff rename to src/tools/rustfmt/src/format-diff/test/bindgen.diff diff --git a/src/format_report_formatter.rs b/src/tools/rustfmt/src/format_report_formatter.rs similarity index 100% rename from src/format_report_formatter.rs rename to src/tools/rustfmt/src/format_report_formatter.rs diff --git a/src/formatting.rs b/src/tools/rustfmt/src/formatting.rs similarity index 100% rename from src/formatting.rs rename to src/tools/rustfmt/src/formatting.rs diff --git a/src/formatting/generated.rs b/src/tools/rustfmt/src/formatting/generated.rs similarity index 100% rename from src/formatting/generated.rs rename to src/tools/rustfmt/src/formatting/generated.rs diff --git a/src/formatting/newline_style.rs b/src/tools/rustfmt/src/formatting/newline_style.rs similarity index 100% rename from src/formatting/newline_style.rs rename to src/tools/rustfmt/src/formatting/newline_style.rs diff --git a/src/git-rustfmt/main.rs b/src/tools/rustfmt/src/git-rustfmt/main.rs similarity index 100% rename from src/git-rustfmt/main.rs rename to src/tools/rustfmt/src/git-rustfmt/main.rs diff --git a/src/header.rs b/src/tools/rustfmt/src/header.rs similarity index 100% rename from src/header.rs rename to src/tools/rustfmt/src/header.rs diff --git a/src/ignore_path.rs b/src/tools/rustfmt/src/ignore_path.rs similarity index 100% rename from src/ignore_path.rs rename to src/tools/rustfmt/src/ignore_path.rs diff --git a/src/imports.rs b/src/tools/rustfmt/src/imports.rs similarity index 100% rename from src/imports.rs rename to src/tools/rustfmt/src/imports.rs diff --git a/src/items.rs b/src/tools/rustfmt/src/items.rs similarity index 100% rename from src/items.rs rename to src/tools/rustfmt/src/items.rs diff --git a/src/lib.rs b/src/tools/rustfmt/src/lib.rs similarity index 100% rename from src/lib.rs rename to src/tools/rustfmt/src/lib.rs diff --git a/src/lists.rs b/src/tools/rustfmt/src/lists.rs similarity index 100% rename from src/lists.rs rename to src/tools/rustfmt/src/lists.rs diff --git a/src/macros.rs b/src/tools/rustfmt/src/macros.rs similarity index 100% rename from src/macros.rs rename to src/tools/rustfmt/src/macros.rs diff --git a/src/matches.rs b/src/tools/rustfmt/src/matches.rs similarity index 100% rename from src/matches.rs rename to src/tools/rustfmt/src/matches.rs diff --git a/src/missed_spans.rs b/src/tools/rustfmt/src/missed_spans.rs similarity index 100% rename from src/missed_spans.rs rename to src/tools/rustfmt/src/missed_spans.rs diff --git a/src/modules.rs b/src/tools/rustfmt/src/modules.rs similarity index 100% rename from src/modules.rs rename to src/tools/rustfmt/src/modules.rs diff --git a/src/modules/visitor.rs b/src/tools/rustfmt/src/modules/visitor.rs similarity index 100% rename from src/modules/visitor.rs rename to src/tools/rustfmt/src/modules/visitor.rs diff --git a/src/overflow.rs b/src/tools/rustfmt/src/overflow.rs similarity index 100% rename from src/overflow.rs rename to src/tools/rustfmt/src/overflow.rs diff --git a/src/pairs.rs b/src/tools/rustfmt/src/pairs.rs similarity index 100% rename from src/pairs.rs rename to src/tools/rustfmt/src/pairs.rs diff --git a/src/parse/macros/asm.rs b/src/tools/rustfmt/src/parse/macros/asm.rs similarity index 100% rename from src/parse/macros/asm.rs rename to src/tools/rustfmt/src/parse/macros/asm.rs diff --git a/src/parse/macros/cfg_if.rs b/src/tools/rustfmt/src/parse/macros/cfg_if.rs similarity index 100% rename from src/parse/macros/cfg_if.rs rename to src/tools/rustfmt/src/parse/macros/cfg_if.rs diff --git a/src/parse/macros/cfg_select.rs b/src/tools/rustfmt/src/parse/macros/cfg_select.rs similarity index 100% rename from src/parse/macros/cfg_select.rs rename to src/tools/rustfmt/src/parse/macros/cfg_select.rs diff --git a/src/parse/macros/lazy_static.rs b/src/tools/rustfmt/src/parse/macros/lazy_static.rs similarity index 100% rename from src/parse/macros/lazy_static.rs rename to src/tools/rustfmt/src/parse/macros/lazy_static.rs diff --git a/src/parse/macros/mod.rs b/src/tools/rustfmt/src/parse/macros/mod.rs similarity index 100% rename from src/parse/macros/mod.rs rename to src/tools/rustfmt/src/parse/macros/mod.rs diff --git a/src/parse/mod.rs b/src/tools/rustfmt/src/parse/mod.rs similarity index 100% rename from src/parse/mod.rs rename to src/tools/rustfmt/src/parse/mod.rs diff --git a/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs similarity index 100% rename from src/parse/parser.rs rename to src/tools/rustfmt/src/parse/parser.rs diff --git a/src/parse/session.rs b/src/tools/rustfmt/src/parse/session.rs similarity index 100% rename from src/parse/session.rs rename to src/tools/rustfmt/src/parse/session.rs diff --git a/src/patterns.rs b/src/tools/rustfmt/src/patterns.rs similarity index 100% rename from src/patterns.rs rename to src/tools/rustfmt/src/patterns.rs diff --git a/src/range.rs b/src/tools/rustfmt/src/range.rs similarity index 100% rename from src/range.rs rename to src/tools/rustfmt/src/range.rs diff --git a/src/release_channel.rs b/src/tools/rustfmt/src/release_channel.rs similarity index 100% rename from src/release_channel.rs rename to src/tools/rustfmt/src/release_channel.rs diff --git a/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs similarity index 100% rename from src/reorder.rs rename to src/tools/rustfmt/src/reorder.rs diff --git a/src/rewrite.rs b/src/tools/rustfmt/src/rewrite.rs similarity index 100% rename from src/rewrite.rs rename to src/tools/rustfmt/src/rewrite.rs diff --git a/src/rustfmt_diff.rs b/src/tools/rustfmt/src/rustfmt_diff.rs similarity index 100% rename from src/rustfmt_diff.rs rename to src/tools/rustfmt/src/rustfmt_diff.rs diff --git a/src/shape.rs b/src/tools/rustfmt/src/shape.rs similarity index 100% rename from src/shape.rs rename to src/tools/rustfmt/src/shape.rs diff --git a/src/skip.rs b/src/tools/rustfmt/src/skip.rs similarity index 100% rename from src/skip.rs rename to src/tools/rustfmt/src/skip.rs diff --git a/src/sort.rs b/src/tools/rustfmt/src/sort.rs similarity index 100% rename from src/sort.rs rename to src/tools/rustfmt/src/sort.rs diff --git a/src/source_file.rs b/src/tools/rustfmt/src/source_file.rs similarity index 100% rename from src/source_file.rs rename to src/tools/rustfmt/src/source_file.rs diff --git a/src/source_map.rs b/src/tools/rustfmt/src/source_map.rs similarity index 100% rename from src/source_map.rs rename to src/tools/rustfmt/src/source_map.rs diff --git a/src/spanned.rs b/src/tools/rustfmt/src/spanned.rs similarity index 100% rename from src/spanned.rs rename to src/tools/rustfmt/src/spanned.rs diff --git a/src/stmt.rs b/src/tools/rustfmt/src/stmt.rs similarity index 100% rename from src/stmt.rs rename to src/tools/rustfmt/src/stmt.rs diff --git a/src/string.rs b/src/tools/rustfmt/src/string.rs similarity index 100% rename from src/string.rs rename to src/tools/rustfmt/src/string.rs diff --git a/src/test/configuration_snippet.rs b/src/tools/rustfmt/src/test/configuration_snippet.rs similarity index 100% rename from src/test/configuration_snippet.rs rename to src/tools/rustfmt/src/test/configuration_snippet.rs diff --git a/src/test/mod.rs b/src/tools/rustfmt/src/test/mod.rs similarity index 100% rename from src/test/mod.rs rename to src/tools/rustfmt/src/test/mod.rs diff --git a/src/test/mod_resolver.rs b/src/tools/rustfmt/src/test/mod_resolver.rs similarity index 100% rename from src/test/mod_resolver.rs rename to src/tools/rustfmt/src/test/mod_resolver.rs diff --git a/src/test/parser.rs b/src/tools/rustfmt/src/test/parser.rs similarity index 100% rename from src/test/parser.rs rename to src/tools/rustfmt/src/test/parser.rs diff --git a/src/types.rs b/src/tools/rustfmt/src/types.rs similarity index 100% rename from src/types.rs rename to src/tools/rustfmt/src/types.rs diff --git a/src/utils.rs b/src/tools/rustfmt/src/utils.rs similarity index 100% rename from src/utils.rs rename to src/tools/rustfmt/src/utils.rs diff --git a/src/vertical.rs b/src/tools/rustfmt/src/vertical.rs similarity index 100% rename from src/vertical.rs rename to src/tools/rustfmt/src/vertical.rs diff --git a/src/visitor.rs b/src/tools/rustfmt/src/visitor.rs similarity index 100% rename from src/visitor.rs rename to src/tools/rustfmt/src/visitor.rs diff --git a/tests/cargo-fmt/main.rs b/src/tools/rustfmt/tests/cargo-fmt/main.rs similarity index 100% rename from tests/cargo-fmt/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/main.rs diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/Cargo.toml diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/Cargo.toml diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/src/lib.rs diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/Cargo.toml diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/dependency-dir-name/subdep-dir-name/src/lib.rs diff --git a/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/divergent-crate-dir-names/src/main.rs diff --git a/tests/cargo-fmt/source/issue_3164/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/issue_3164/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/Cargo.toml diff --git a/tests/cargo-fmt/source/issue_3164/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/issue_3164/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/issue_3164/src/main.rs diff --git a/tests/cargo-fmt/source/issues_6517/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/issues_6517/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/Cargo.toml diff --git a/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_bin/Cargo.toml diff --git a/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_bin/src/main.rs diff --git a/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_lib/Cargo.toml diff --git a/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/issues_6517/inner_lib/src/lib.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/e/src/main.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/f/src/lib.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/d/src/lib.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/a/src/main.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/b/src/main.rs diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/Cargo.toml diff --git a/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs b/src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs similarity index 100% rename from tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs rename to src/tools/rustfmt/tests/cargo-fmt/source/workspaces/path-dep-above/ws/c/src/lib.rs diff --git a/tests/config/disable_all_formatting.toml b/src/tools/rustfmt/tests/config/disable_all_formatting.toml similarity index 100% rename from tests/config/disable_all_formatting.toml rename to src/tools/rustfmt/tests/config/disable_all_formatting.toml diff --git a/tests/config/issue-1111.toml b/src/tools/rustfmt/tests/config/issue-1111.toml similarity index 100% rename from tests/config/issue-1111.toml rename to src/tools/rustfmt/tests/config/issue-1111.toml diff --git a/tests/config/issue-2641.toml b/src/tools/rustfmt/tests/config/issue-2641.toml similarity index 100% rename from tests/config/issue-2641.toml rename to src/tools/rustfmt/tests/config/issue-2641.toml diff --git a/tests/config/issue-3779.toml b/src/tools/rustfmt/tests/config/issue-3779.toml similarity index 100% rename from tests/config/issue-3779.toml rename to src/tools/rustfmt/tests/config/issue-3779.toml diff --git a/tests/config/issue-5801-v1.toml b/src/tools/rustfmt/tests/config/issue-5801-v1.toml similarity index 100% rename from tests/config/issue-5801-v1.toml rename to src/tools/rustfmt/tests/config/issue-5801-v1.toml diff --git a/tests/config/issue-5801-v2.toml b/src/tools/rustfmt/tests/config/issue-5801-v2.toml similarity index 100% rename from tests/config/issue-5801-v2.toml rename to src/tools/rustfmt/tests/config/issue-5801-v2.toml diff --git a/tests/config/issue-5816.toml b/src/tools/rustfmt/tests/config/issue-5816.toml similarity index 100% rename from tests/config/issue-5816.toml rename to src/tools/rustfmt/tests/config/issue-5816.toml diff --git a/tests/config/issue-6302.toml b/src/tools/rustfmt/tests/config/issue-6302.toml similarity index 100% rename from tests/config/issue-6302.toml rename to src/tools/rustfmt/tests/config/issue-6302.toml diff --git a/src/tools/rustfmt/tests/config/issue_4660/Cargo.lock b/src/tools/rustfmt/tests/config/issue_4660/Cargo.lock new file mode 100644 index 0000000000000..e2e277aef8740 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "inner_lib" +version = "0.1.0" diff --git a/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml new file mode 100644 index 0000000000000..c716e9d057548 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/Cargo.toml @@ -0,0 +1,2 @@ +[workspace] +members = ["inner_lib"] diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml new file mode 100644 index 0000000000000..c7ad93bafe36c --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/.rustfmt.unstable.toml @@ -0,0 +1 @@ +disable_all_formatting = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml new file mode 100644 index 0000000000000..bb6a80cd0ce9b --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inner_bin" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs new file mode 100644 index 0000000000000..21c34773b8af5 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_bin/src/main.rs @@ -0,0 +1 @@ +fn main(){println!("Hello, world!")} diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml new file mode 100644 index 0000000000000..c9ddf1793b88f --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/Cargo.toml @@ -0,0 +1,6 @@ +[package] +name = "inner_lib" +version = "0.1.0" +edition = "2021" + +[dependencies] diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml new file mode 100644 index 0000000000000..c7ad93bafe36c --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/rustfmt.toml @@ -0,0 +1 @@ +disable_all_formatting = true diff --git a/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs new file mode 100644 index 0000000000000..42375c99d2c97 --- /dev/null +++ b/src/tools/rustfmt/tests/config/issue_4660/inner_lib/src/lib.rs @@ -0,0 +1 @@ +pub fn add(left:u64,right:u64)->u64{left+right} diff --git a/tests/config/skip_children.toml b/src/tools/rustfmt/tests/config/skip_children.toml similarity index 100% rename from tests/config/skip_children.toml rename to src/tools/rustfmt/tests/config/skip_children.toml diff --git a/tests/config/small_tabs.toml b/src/tools/rustfmt/tests/config/small_tabs.toml similarity index 100% rename from tests/config/small_tabs.toml rename to src/tools/rustfmt/tests/config/small_tabs.toml diff --git a/tests/config/style-edition/just-style-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml similarity index 100% rename from tests/config/style-edition/just-style-edition/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/just-style-edition/rustfmt.toml diff --git a/tests/config/style-edition/just-version/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml similarity index 100% rename from tests/config/style-edition/just-version/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/just-version/rustfmt.toml diff --git a/tests/config/style-edition/overrides/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml similarity index 100% rename from tests/config/style-edition/overrides/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/overrides/rustfmt.toml diff --git a/tests/config/style-edition/style-edition-and-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml similarity index 100% rename from tests/config/style-edition/style-edition-and-edition/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/style-edition-and-edition/rustfmt.toml diff --git a/tests/config/style-edition/version-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml similarity index 100% rename from tests/config/style-edition/version-edition/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/version-edition/rustfmt.toml diff --git a/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml similarity index 100% rename from tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/version-style-edition-and-edition/rustfmt.toml diff --git a/tests/config/style-edition/version-style-edition/rustfmt.toml b/src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml similarity index 100% rename from tests/config/style-edition/version-style-edition/rustfmt.toml rename to src/tools/rustfmt/tests/config/style-edition/version-style-edition/rustfmt.toml diff --git a/tests/coverage/source/comments.rs b/src/tools/rustfmt/tests/coverage/source/comments.rs similarity index 100% rename from tests/coverage/source/comments.rs rename to src/tools/rustfmt/tests/coverage/source/comments.rs diff --git a/tests/coverage/target/comments.rs b/src/tools/rustfmt/tests/coverage/target/comments.rs similarity index 100% rename from tests/coverage/target/comments.rs rename to src/tools/rustfmt/tests/coverage/target/comments.rs diff --git a/tests/mod-resolver/issue-4874/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/issue-4874/bar/baz.rs similarity index 100% rename from tests/mod-resolver/issue-4874/bar/baz.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-4874/bar/baz.rs diff --git a/tests/mod-resolver/issue-4874/foo.rs b/src/tools/rustfmt/tests/mod-resolver/issue-4874/foo.rs similarity index 100% rename from tests/mod-resolver/issue-4874/foo.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-4874/foo.rs diff --git a/tests/mod-resolver/issue-4874/foo/qux.rs b/src/tools/rustfmt/tests/mod-resolver/issue-4874/foo/qux.rs similarity index 100% rename from tests/mod-resolver/issue-4874/foo/qux.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-4874/foo/qux.rs diff --git a/tests/mod-resolver/issue-4874/main.rs b/src/tools/rustfmt/tests/mod-resolver/issue-4874/main.rs similarity index 100% rename from tests/mod-resolver/issue-4874/main.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-4874/main.rs diff --git a/tests/mod-resolver/issue-5063/foo.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs similarity index 100% rename from tests/mod-resolver/issue-5063/foo.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5063/foo.rs diff --git a/tests/mod-resolver/issue-5063/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs similarity index 100% rename from tests/mod-resolver/issue-5063/foo/bar/baz.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5063/foo/bar/baz.rs diff --git a/tests/mod-resolver/issue-5063/main.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs similarity index 100% rename from tests/mod-resolver/issue-5063/main.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5063/main.rs diff --git a/tests/mod-resolver/issue-5167/src/a.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5167/src/a.rs similarity index 100% rename from tests/mod-resolver/issue-5167/src/a.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5167/src/a.rs diff --git a/tests/mod-resolver/issue-5167/src/a/mod.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5167/src/a/mod.rs similarity index 100% rename from tests/mod-resolver/issue-5167/src/a/mod.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5167/src/a/mod.rs diff --git a/tests/mod-resolver/issue-5167/src/lib.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5167/src/lib.rs similarity index 100% rename from tests/mod-resolver/issue-5167/src/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5167/src/lib.rs diff --git a/tests/mod-resolver/issue-5198/a.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/a.rs similarity index 100% rename from tests/mod-resolver/issue-5198/a.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/a.rs diff --git a/tests/mod-resolver/issue-5198/lib.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib.rs diff --git a/tests/mod-resolver/issue-5198/lib/b.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/b.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/b.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/b.rs diff --git a/tests/mod-resolver/issue-5198/lib/c/d.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/d.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d.rs diff --git a/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/d/explanation.txt rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/explanation.txt diff --git a/tests/mod-resolver/issue-5198/lib/c/d/f.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/f.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/d/f.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/f.rs diff --git a/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/d/g/mod.rs diff --git a/tests/mod-resolver/issue-5198/lib/c/e.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/e.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/e.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/e.rs diff --git a/tests/mod-resolver/issue-5198/lib/c/mod.rs b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/mod.rs similarity index 100% rename from tests/mod-resolver/issue-5198/lib/c/mod.rs rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/c/mod.rs diff --git a/tests/mod-resolver/issue-5198/lib/explanation.txt b/src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt similarity index 100% rename from tests/mod-resolver/issue-5198/lib/explanation.txt rename to src/tools/rustfmt/tests/mod-resolver/issue-5198/lib/explanation.txt diff --git a/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs b/src/tools/rustfmt/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs similarity index 100% rename from tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/module-not-found/bad_path_attribute/lib.rs diff --git a/tests/mod-resolver/module-not-found/relative_module/a.rs b/src/tools/rustfmt/tests/mod-resolver/module-not-found/relative_module/a.rs similarity index 100% rename from tests/mod-resolver/module-not-found/relative_module/a.rs rename to src/tools/rustfmt/tests/mod-resolver/module-not-found/relative_module/a.rs diff --git a/tests/mod-resolver/module-not-found/relative_module/lib.rs b/src/tools/rustfmt/tests/mod-resolver/module-not-found/relative_module/lib.rs similarity index 100% rename from tests/mod-resolver/module-not-found/relative_module/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/module-not-found/relative_module/lib.rs diff --git a/tests/mod-resolver/module-not-found/sibling_module/lib.rs b/src/tools/rustfmt/tests/mod-resolver/module-not-found/sibling_module/lib.rs similarity index 100% rename from tests/mod-resolver/module-not-found/sibling_module/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/module-not-found/sibling_module/lib.rs diff --git a/tests/mod-resolver/skip-files-issue-5065/foo.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo.rs similarity index 100% rename from tests/mod-resolver/skip-files-issue-5065/foo.rs rename to src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo.rs diff --git a/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs similarity index 100% rename from tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs rename to src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/foo/bar/baz.rs diff --git a/tests/mod-resolver/skip-files-issue-5065/main.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs similarity index 100% rename from tests/mod-resolver/skip-files-issue-5065/main.rs rename to src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/main.rs diff --git a/tests/mod-resolver/skip-files-issue-5065/one.rs b/src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/one.rs similarity index 100% rename from tests/mod-resolver/skip-files-issue-5065/one.rs rename to src/tools/rustfmt/tests/mod-resolver/skip-files-issue-5065/one.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/Cargo.toml rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/Cargo.toml diff --git a/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/src/lib.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/src/lib.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub1.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub2.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/mod.rs diff --git a/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs b/src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs similarity index 100% rename from tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs rename to src/tools/rustfmt/tests/mod-resolver/test-submodule-issue-5119/tests/test1/sub3/sub4.rs diff --git a/tests/parser/issue-4126/invalid.rs b/src/tools/rustfmt/tests/parser/issue-4126/invalid.rs similarity index 100% rename from tests/parser/issue-4126/invalid.rs rename to src/tools/rustfmt/tests/parser/issue-4126/invalid.rs diff --git a/tests/parser/issue-4126/lib.rs b/src/tools/rustfmt/tests/parser/issue-4126/lib.rs similarity index 100% rename from tests/parser/issue-4126/lib.rs rename to src/tools/rustfmt/tests/parser/issue-4126/lib.rs diff --git a/tests/parser/issue_4418.rs b/src/tools/rustfmt/tests/parser/issue_4418.rs similarity index 100% rename from tests/parser/issue_4418.rs rename to src/tools/rustfmt/tests/parser/issue_4418.rs diff --git a/tests/parser/stashed-diag.rs b/src/tools/rustfmt/tests/parser/stashed-diag.rs similarity index 100% rename from tests/parser/stashed-diag.rs rename to src/tools/rustfmt/tests/parser/stashed-diag.rs diff --git a/tests/parser/stashed-diag2.rs b/src/tools/rustfmt/tests/parser/stashed-diag2.rs similarity index 100% rename from tests/parser/stashed-diag2.rs rename to src/tools/rustfmt/tests/parser/stashed-diag2.rs diff --git a/tests/parser/unclosed-delims/issue_4466.rs b/src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs similarity index 100% rename from tests/parser/unclosed-delims/issue_4466.rs rename to src/tools/rustfmt/tests/parser/unclosed-delims/issue_4466.rs diff --git a/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs similarity index 92% rename from tests/rustfmt/main.rs rename to src/tools/rustfmt/tests/rustfmt/main.rs index ee972d8a6afb7..7d60f3343f646 100644 --- a/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -345,6 +345,41 @@ fn rustfmt_error_improvement_regarding_invalid_toml() { assert!(stderr.contains(&expected_error_message)); } +#[test] +fn config_path_does_not_walk_parent_directories_with_dir_name() { + let src_dir = "tests/config/issue_4660/inner_lib/src"; + let src_file = src_dir.to_owned() + "/lib.rs"; + let args = ["--config-path", src_dir, "--check", &src_file]; + let (stdout, stderr) = rustfmt(&args); + + assert_eq!( + stderr, + format!( + "Error: unable to find a config file for the given path: `{}`\n", + Path::new(src_dir).display(), + ) + ); + assert_eq!(stdout, ""); +} + +#[test] +fn config_path_does_not_walk_parent_directories_with_toml_name() { + let src_dir = "tests/config/issue_4660/inner_bin/src"; + let toml_file = src_dir.to_owned() + "/.rustfmt.unstable.toml"; + let src_file = src_dir.to_owned() + "/main.rs"; + let args = ["--config-path", &toml_file, "--check", &src_file]; + let (stdout, stderr) = rustfmt(&args); + + assert_eq!( + stderr, + format!( + "Error: unable to find a config file for the given path: `{}`\n", + Path::new(&toml_file).display(), + ) + ); + assert_eq!(stdout, ""); +} + #[test] fn rustfmt_allow_not_a_dir_errors() { // See also https://github.com/rust-lang/rustfmt/pull/6624 diff --git a/tests/source/5131_crate.rs b/src/tools/rustfmt/tests/source/5131_crate.rs similarity index 100% rename from tests/source/5131_crate.rs rename to src/tools/rustfmt/tests/source/5131_crate.rs diff --git a/tests/source/5131_module.rs b/src/tools/rustfmt/tests/source/5131_module.rs similarity index 100% rename from tests/source/5131_module.rs rename to src/tools/rustfmt/tests/source/5131_module.rs diff --git a/tests/source/5131_one.rs b/src/tools/rustfmt/tests/source/5131_one.rs similarity index 100% rename from tests/source/5131_one.rs rename to src/tools/rustfmt/tests/source/5131_one.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs b/src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs similarity index 100% rename from tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs rename to src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs b/src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs similarity index 100% rename from tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs rename to src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs b/src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs similarity index 100% rename from tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs rename to src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs b/src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs similarity index 100% rename from tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs rename to src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs diff --git a/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs b/src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs similarity index 100% rename from tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs rename to src/tools/rustfmt/tests/source/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs diff --git a/tests/source/alignment_2633/block_style.rs b/src/tools/rustfmt/tests/source/alignment_2633/block_style.rs similarity index 100% rename from tests/source/alignment_2633/block_style.rs rename to src/tools/rustfmt/tests/source/alignment_2633/block_style.rs diff --git a/tests/source/alignment_2633/visual_style.rs b/src/tools/rustfmt/tests/source/alignment_2633/visual_style.rs similarity index 100% rename from tests/source/alignment_2633/visual_style.rs rename to src/tools/rustfmt/tests/source/alignment_2633/visual_style.rs diff --git a/tests/source/array_comment.rs b/src/tools/rustfmt/tests/source/array_comment.rs similarity index 100% rename from tests/source/array_comment.rs rename to src/tools/rustfmt/tests/source/array_comment.rs diff --git a/tests/source/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs similarity index 100% rename from tests/source/arrow_in_comments/arrow_in_single_comment.rs rename to src/tools/rustfmt/tests/source/arrow_in_comments/arrow_in_single_comment.rs diff --git a/tests/source/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs similarity index 100% rename from tests/source/arrow_in_comments/multiple_arrows.rs rename to src/tools/rustfmt/tests/source/arrow_in_comments/multiple_arrows.rs diff --git a/tests/source/assignment.rs b/src/tools/rustfmt/tests/source/assignment.rs similarity index 100% rename from tests/source/assignment.rs rename to src/tools/rustfmt/tests/source/assignment.rs diff --git a/tests/source/associated-types-bounds-wrapping.rs b/src/tools/rustfmt/tests/source/associated-types-bounds-wrapping.rs similarity index 100% rename from tests/source/associated-types-bounds-wrapping.rs rename to src/tools/rustfmt/tests/source/associated-types-bounds-wrapping.rs diff --git a/tests/source/associated_type_bounds.rs b/src/tools/rustfmt/tests/source/associated_type_bounds.rs similarity index 100% rename from tests/source/associated_type_bounds.rs rename to src/tools/rustfmt/tests/source/associated_type_bounds.rs diff --git a/tests/source/async_block.rs b/src/tools/rustfmt/tests/source/async_block.rs similarity index 100% rename from tests/source/async_block.rs rename to src/tools/rustfmt/tests/source/async_block.rs diff --git a/tests/source/async_fn.rs b/src/tools/rustfmt/tests/source/async_fn.rs similarity index 100% rename from tests/source/async_fn.rs rename to src/tools/rustfmt/tests/source/async_fn.rs diff --git a/tests/source/attrib.rs b/src/tools/rustfmt/tests/source/attrib.rs similarity index 100% rename from tests/source/attrib.rs rename to src/tools/rustfmt/tests/source/attrib.rs diff --git a/tests/source/big-impl-block.rs b/src/tools/rustfmt/tests/source/big-impl-block.rs similarity index 100% rename from tests/source/big-impl-block.rs rename to src/tools/rustfmt/tests/source/big-impl-block.rs diff --git a/tests/source/big-impl-visual.rs b/src/tools/rustfmt/tests/source/big-impl-visual.rs similarity index 100% rename from tests/source/big-impl-visual.rs rename to src/tools/rustfmt/tests/source/big-impl-visual.rs diff --git a/tests/source/binary-expr.rs b/src/tools/rustfmt/tests/source/binary-expr.rs similarity index 100% rename from tests/source/binary-expr.rs rename to src/tools/rustfmt/tests/source/binary-expr.rs diff --git a/tests/source/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs similarity index 100% rename from tests/source/binop-separator-back/bitwise.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/bitwise.rs diff --git a/tests/source/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/source/binop-separator-back/comp.rs similarity index 100% rename from tests/source/binop-separator-back/comp.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/comp.rs diff --git a/tests/source/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/source/binop-separator-back/logic.rs similarity index 100% rename from tests/source/binop-separator-back/logic.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/logic.rs diff --git a/tests/source/binop-separator-back/math.rs b/src/tools/rustfmt/tests/source/binop-separator-back/math.rs similarity index 100% rename from tests/source/binop-separator-back/math.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/math.rs diff --git a/tests/source/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs similarity index 100% rename from tests/source/binop-separator-back/patterns.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/patterns.rs diff --git a/tests/source/binop-separator-back/range.rs b/src/tools/rustfmt/tests/source/binop-separator-back/range.rs similarity index 100% rename from tests/source/binop-separator-back/range.rs rename to src/tools/rustfmt/tests/source/binop-separator-back/range.rs diff --git a/tests/source/break-and-continue.rs b/src/tools/rustfmt/tests/source/break-and-continue.rs similarity index 100% rename from tests/source/break-and-continue.rs rename to src/tools/rustfmt/tests/source/break-and-continue.rs diff --git a/tests/source/catch.rs b/src/tools/rustfmt/tests/source/catch.rs similarity index 100% rename from tests/source/catch.rs rename to src/tools/rustfmt/tests/source/catch.rs diff --git a/tests/source/cfg_if/detect/arch/aarch64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/aarch64.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/aarch64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/aarch64.rs diff --git a/tests/source/cfg_if/detect/arch/arm.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/arm.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/arm.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/arm.rs diff --git a/tests/source/cfg_if/detect/arch/mips.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/mips.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/mips.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/mips.rs diff --git a/tests/source/cfg_if/detect/arch/mips64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/mips64.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/mips64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/mips64.rs diff --git a/tests/source/cfg_if/detect/arch/powerpc.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/powerpc.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/powerpc.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/powerpc.rs diff --git a/tests/source/cfg_if/detect/arch/powerpc64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/powerpc64.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/powerpc64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/powerpc64.rs diff --git a/tests/source/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs similarity index 100% rename from tests/source/cfg_if/detect/arch/x86.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/arch/x86.rs diff --git a/tests/source/cfg_if/detect/bit.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/bit.rs similarity index 100% rename from tests/source/cfg_if/detect/bit.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/bit.rs diff --git a/tests/source/cfg_if/detect/cache.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/cache.rs similarity index 100% rename from tests/source/cfg_if/detect/cache.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/cache.rs diff --git a/tests/source/cfg_if/detect/error_macros.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/error_macros.rs similarity index 100% rename from tests/source/cfg_if/detect/error_macros.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/error_macros.rs diff --git a/tests/source/cfg_if/detect/mod.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/mod.rs similarity index 100% rename from tests/source/cfg_if/detect/mod.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/mod.rs diff --git a/tests/source/cfg_if/detect/os/aarch64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/aarch64.rs similarity index 100% rename from tests/source/cfg_if/detect/os/aarch64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/aarch64.rs diff --git a/tests/source/cfg_if/detect/os/freebsd/aarch64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/aarch64.rs similarity index 100% rename from tests/source/cfg_if/detect/os/freebsd/aarch64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/aarch64.rs diff --git a/tests/source/cfg_if/detect/os/freebsd/arm.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/arm.rs similarity index 100% rename from tests/source/cfg_if/detect/os/freebsd/arm.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/arm.rs diff --git a/tests/source/cfg_if/detect/os/freebsd/auxvec.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/auxvec.rs similarity index 100% rename from tests/source/cfg_if/detect/os/freebsd/auxvec.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/auxvec.rs diff --git a/tests/source/cfg_if/detect/os/freebsd/mod.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/mod.rs similarity index 100% rename from tests/source/cfg_if/detect/os/freebsd/mod.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/mod.rs diff --git a/tests/source/cfg_if/detect/os/freebsd/powerpc.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/powerpc.rs similarity index 100% rename from tests/source/cfg_if/detect/os/freebsd/powerpc.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/freebsd/powerpc.rs diff --git a/tests/source/cfg_if/detect/os/linux/aarch64.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/aarch64.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/aarch64.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/aarch64.rs diff --git a/tests/source/cfg_if/detect/os/linux/arm.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/arm.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/arm.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/arm.rs diff --git a/tests/source/cfg_if/detect/os/linux/auxvec.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/auxvec.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/auxvec.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/auxvec.rs diff --git a/tests/source/cfg_if/detect/os/linux/cpuinfo.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/cpuinfo.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/cpuinfo.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/cpuinfo.rs diff --git a/tests/source/cfg_if/detect/os/linux/mips.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/mips.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/mips.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/mips.rs diff --git a/tests/source/cfg_if/detect/os/linux/mod.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/mod.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/mod.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/mod.rs diff --git a/tests/source/cfg_if/detect/os/linux/powerpc.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/powerpc.rs similarity index 100% rename from tests/source/cfg_if/detect/os/linux/powerpc.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/linux/powerpc.rs diff --git a/tests/source/cfg_if/detect/os/other.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/other.rs similarity index 100% rename from tests/source/cfg_if/detect/os/other.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/other.rs diff --git a/tests/source/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs similarity index 100% rename from tests/source/cfg_if/detect/os/x86.rs rename to src/tools/rustfmt/tests/source/cfg_if/detect/os/x86.rs diff --git a/tests/source/cfg_if/lib.rs b/src/tools/rustfmt/tests/source/cfg_if/lib.rs similarity index 100% rename from tests/source/cfg_if/lib.rs rename to src/tools/rustfmt/tests/source/cfg_if/lib.rs diff --git a/tests/source/cfg_if/mod.rs b/src/tools/rustfmt/tests/source/cfg_if/mod.rs similarity index 100% rename from tests/source/cfg_if/mod.rs rename to src/tools/rustfmt/tests/source/cfg_if/mod.rs diff --git a/tests/source/cfg_mod/bar.rs b/src/tools/rustfmt/tests/source/cfg_mod/bar.rs similarity index 100% rename from tests/source/cfg_mod/bar.rs rename to src/tools/rustfmt/tests/source/cfg_mod/bar.rs diff --git a/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs b/src/tools/rustfmt/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs similarity index 100% rename from tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs rename to src/tools/rustfmt/tests/source/cfg_mod/dir/dir1/dir2/wasm32.rs diff --git a/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs b/src/tools/rustfmt/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs similarity index 100% rename from tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs rename to src/tools/rustfmt/tests/source/cfg_mod/dir/dir1/dir3/wasm32.rs diff --git a/tests/source/cfg_mod/foo.rs b/src/tools/rustfmt/tests/source/cfg_mod/foo.rs similarity index 100% rename from tests/source/cfg_mod/foo.rs rename to src/tools/rustfmt/tests/source/cfg_mod/foo.rs diff --git a/tests/source/cfg_mod/mod.rs b/src/tools/rustfmt/tests/source/cfg_mod/mod.rs similarity index 100% rename from tests/source/cfg_mod/mod.rs rename to src/tools/rustfmt/tests/source/cfg_mod/mod.rs diff --git a/tests/source/cfg_mod/other.rs b/src/tools/rustfmt/tests/source/cfg_mod/other.rs similarity index 100% rename from tests/source/cfg_mod/other.rs rename to src/tools/rustfmt/tests/source/cfg_mod/other.rs diff --git a/tests/source/cfg_mod/wasm32.rs b/src/tools/rustfmt/tests/source/cfg_mod/wasm32.rs similarity index 100% rename from tests/source/cfg_mod/wasm32.rs rename to src/tools/rustfmt/tests/source/cfg_mod/wasm32.rs diff --git a/tests/source/cfg_select.rs b/src/tools/rustfmt/tests/source/cfg_select.rs similarity index 100% rename from tests/source/cfg_select.rs rename to src/tools/rustfmt/tests/source/cfg_select.rs diff --git a/tests/source/cfg_select/format_me_please_1.rs b/src/tools/rustfmt/tests/source/cfg_select/format_me_please_1.rs similarity index 100% rename from tests/source/cfg_select/format_me_please_1.rs rename to src/tools/rustfmt/tests/source/cfg_select/format_me_please_1.rs diff --git a/tests/source/cfg_select/format_me_please_2.rs b/src/tools/rustfmt/tests/source/cfg_select/format_me_please_2.rs similarity index 100% rename from tests/source/cfg_select/format_me_please_2.rs rename to src/tools/rustfmt/tests/source/cfg_select/format_me_please_2.rs diff --git a/tests/source/cfg_select/format_me_please_3.rs b/src/tools/rustfmt/tests/source/cfg_select/format_me_please_3.rs similarity index 100% rename from tests/source/cfg_select/format_me_please_3.rs rename to src/tools/rustfmt/tests/source/cfg_select/format_me_please_3.rs diff --git a/tests/source/cfg_select/format_me_please_4.rs b/src/tools/rustfmt/tests/source/cfg_select/format_me_please_4.rs similarity index 100% rename from tests/source/cfg_select/format_me_please_4.rs rename to src/tools/rustfmt/tests/source/cfg_select/format_me_please_4.rs diff --git a/tests/source/cfg_select/lib.rs b/src/tools/rustfmt/tests/source/cfg_select/lib.rs similarity index 100% rename from tests/source/cfg_select/lib.rs rename to src/tools/rustfmt/tests/source/cfg_select/lib.rs diff --git a/tests/source/cfg_select/lib2.rs b/src/tools/rustfmt/tests/source/cfg_select/lib2.rs similarity index 100% rename from tests/source/cfg_select/lib2.rs rename to src/tools/rustfmt/tests/source/cfg_select/lib2.rs diff --git a/tests/source/cfg_select_stable.rs b/src/tools/rustfmt/tests/source/cfg_select_stable.rs similarity index 100% rename from tests/source/cfg_select_stable.rs rename to src/tools/rustfmt/tests/source/cfg_select_stable.rs diff --git a/tests/source/chain_yield_with_comments.rs b/src/tools/rustfmt/tests/source/chain_yield_with_comments.rs similarity index 100% rename from tests/source/chain_yield_with_comments.rs rename to src/tools/rustfmt/tests/source/chain_yield_with_comments.rs diff --git a/tests/source/chains-visual.rs b/src/tools/rustfmt/tests/source/chains-visual.rs similarity index 100% rename from tests/source/chains-visual.rs rename to src/tools/rustfmt/tests/source/chains-visual.rs diff --git a/tests/source/chains.rs b/src/tools/rustfmt/tests/source/chains.rs similarity index 100% rename from tests/source/chains.rs rename to src/tools/rustfmt/tests/source/chains.rs diff --git a/tests/source/chains_with_comment.rs b/src/tools/rustfmt/tests/source/chains_with_comment.rs similarity index 100% rename from tests/source/chains_with_comment.rs rename to src/tools/rustfmt/tests/source/chains_with_comment.rs diff --git a/tests/source/closure-block-inside-macro.rs b/src/tools/rustfmt/tests/source/closure-block-inside-macro.rs similarity index 100% rename from tests/source/closure-block-inside-macro.rs rename to src/tools/rustfmt/tests/source/closure-block-inside-macro.rs diff --git a/tests/source/closure-block-labels.rs b/src/tools/rustfmt/tests/source/closure-block-labels.rs similarity index 100% rename from tests/source/closure-block-labels.rs rename to src/tools/rustfmt/tests/source/closure-block-labels.rs diff --git a/tests/source/closure.rs b/src/tools/rustfmt/tests/source/closure.rs similarity index 100% rename from tests/source/closure.rs rename to src/tools/rustfmt/tests/source/closure.rs diff --git a/tests/source/comment.rs b/src/tools/rustfmt/tests/source/comment.rs similarity index 100% rename from tests/source/comment.rs rename to src/tools/rustfmt/tests/source/comment.rs diff --git a/tests/source/comment2.rs b/src/tools/rustfmt/tests/source/comment2.rs similarity index 100% rename from tests/source/comment2.rs rename to src/tools/rustfmt/tests/source/comment2.rs diff --git a/tests/source/comment3.rs b/src/tools/rustfmt/tests/source/comment3.rs similarity index 100% rename from tests/source/comment3.rs rename to src/tools/rustfmt/tests/source/comment3.rs diff --git a/tests/source/comment4.rs b/src/tools/rustfmt/tests/source/comment4.rs similarity index 100% rename from tests/source/comment4.rs rename to src/tools/rustfmt/tests/source/comment4.rs diff --git a/tests/source/comment5.rs b/src/tools/rustfmt/tests/source/comment5.rs similarity index 100% rename from tests/source/comment5.rs rename to src/tools/rustfmt/tests/source/comment5.rs diff --git a/tests/source/comment6.rs b/src/tools/rustfmt/tests/source/comment6.rs similarity index 100% rename from tests/source/comment6.rs rename to src/tools/rustfmt/tests/source/comment6.rs diff --git a/tests/source/comment_crlf_newline.rs b/src/tools/rustfmt/tests/source/comment_crlf_newline.rs similarity index 100% rename from tests/source/comment_crlf_newline.rs rename to src/tools/rustfmt/tests/source/comment_crlf_newline.rs diff --git a/tests/source/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs similarity index 100% rename from tests/source/comments-in-lists/wrap-comments-not-normalized.rs rename to src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-not-normalized.rs diff --git a/tests/source/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs similarity index 100% rename from tests/source/comments-in-lists/wrap-comments-true.rs rename to src/tools/rustfmt/tests/source/comments-in-lists/wrap-comments-true.rs diff --git a/tests/source/comments_unicode.rs b/src/tools/rustfmt/tests/source/comments_unicode.rs similarity index 100% rename from tests/source/comments_unicode.rs rename to src/tools/rustfmt/tests/source/comments_unicode.rs diff --git a/tests/source/configs/blank_lines_lower_bound/1.rs b/src/tools/rustfmt/tests/source/configs/blank_lines_lower_bound/1.rs similarity index 100% rename from tests/source/configs/blank_lines_lower_bound/1.rs rename to src/tools/rustfmt/tests/source/configs/blank_lines_lower_bound/1.rs diff --git a/tests/source/configs/blank_lines_upper_bound/1.rs b/src/tools/rustfmt/tests/source/configs/blank_lines_upper_bound/1.rs similarity index 100% rename from tests/source/configs/blank_lines_upper_bound/1.rs rename to src/tools/rustfmt/tests/source/configs/blank_lines_upper_bound/1.rs diff --git a/tests/source/configs/blank_lines_upper_bound/2.rs b/src/tools/rustfmt/tests/source/configs/blank_lines_upper_bound/2.rs similarity index 100% rename from tests/source/configs/blank_lines_upper_bound/2.rs rename to src/tools/rustfmt/tests/source/configs/blank_lines_upper_bound/2.rs diff --git a/tests/source/configs/brace_style/fn_always_next_line.rs b/src/tools/rustfmt/tests/source/configs/brace_style/fn_always_next_line.rs similarity index 100% rename from tests/source/configs/brace_style/fn_always_next_line.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/fn_always_next_line.rs diff --git a/tests/source/configs/brace_style/fn_prefer_same_line.rs b/src/tools/rustfmt/tests/source/configs/brace_style/fn_prefer_same_line.rs similarity index 100% rename from tests/source/configs/brace_style/fn_prefer_same_line.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/fn_prefer_same_line.rs diff --git a/tests/source/configs/brace_style/fn_same_line_where.rs b/src/tools/rustfmt/tests/source/configs/brace_style/fn_same_line_where.rs similarity index 100% rename from tests/source/configs/brace_style/fn_same_line_where.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/fn_same_line_where.rs diff --git a/tests/source/configs/brace_style/item_always_next_line.rs b/src/tools/rustfmt/tests/source/configs/brace_style/item_always_next_line.rs similarity index 100% rename from tests/source/configs/brace_style/item_always_next_line.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/item_always_next_line.rs diff --git a/tests/source/configs/brace_style/item_prefer_same_line.rs b/src/tools/rustfmt/tests/source/configs/brace_style/item_prefer_same_line.rs similarity index 100% rename from tests/source/configs/brace_style/item_prefer_same_line.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/item_prefer_same_line.rs diff --git a/tests/source/configs/brace_style/item_same_line_where.rs b/src/tools/rustfmt/tests/source/configs/brace_style/item_same_line_where.rs similarity index 100% rename from tests/source/configs/brace_style/item_same_line_where.rs rename to src/tools/rustfmt/tests/source/configs/brace_style/item_same_line_where.rs diff --git a/tests/source/configs/chain_width/always.rs b/src/tools/rustfmt/tests/source/configs/chain_width/always.rs similarity index 100% rename from tests/source/configs/chain_width/always.rs rename to src/tools/rustfmt/tests/source/configs/chain_width/always.rs diff --git a/tests/source/configs/chain_width/small.rs b/src/tools/rustfmt/tests/source/configs/chain_width/small.rs similarity index 100% rename from tests/source/configs/chain_width/small.rs rename to src/tools/rustfmt/tests/source/configs/chain_width/small.rs diff --git a/tests/source/configs/chain_width/tiny.rs b/src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs similarity index 100% rename from tests/source/configs/chain_width/tiny.rs rename to src/tools/rustfmt/tests/source/configs/chain_width/tiny.rs diff --git a/tests/source/configs/comment_width/above.rs b/src/tools/rustfmt/tests/source/configs/comment_width/above.rs similarity index 100% rename from tests/source/configs/comment_width/above.rs rename to src/tools/rustfmt/tests/source/configs/comment_width/above.rs diff --git a/tests/source/configs/comment_width/below.rs b/src/tools/rustfmt/tests/source/configs/comment_width/below.rs similarity index 100% rename from tests/source/configs/comment_width/below.rs rename to src/tools/rustfmt/tests/source/configs/comment_width/below.rs diff --git a/tests/source/configs/comment_width/ignore.rs b/src/tools/rustfmt/tests/source/configs/comment_width/ignore.rs similarity index 100% rename from tests/source/configs/comment_width/ignore.rs rename to src/tools/rustfmt/tests/source/configs/comment_width/ignore.rs diff --git a/tests/source/configs/condense_wildcard_suffixes/false.rs b/src/tools/rustfmt/tests/source/configs/condense_wildcard_suffixes/false.rs similarity index 100% rename from tests/source/configs/condense_wildcard_suffixes/false.rs rename to src/tools/rustfmt/tests/source/configs/condense_wildcard_suffixes/false.rs diff --git a/tests/source/configs/condense_wildcard_suffixes/true.rs b/src/tools/rustfmt/tests/source/configs/condense_wildcard_suffixes/true.rs similarity index 100% rename from tests/source/configs/condense_wildcard_suffixes/true.rs rename to src/tools/rustfmt/tests/source/configs/condense_wildcard_suffixes/true.rs diff --git a/tests/source/configs/control_brace_style/always_next_line.rs b/src/tools/rustfmt/tests/source/configs/control_brace_style/always_next_line.rs similarity index 100% rename from tests/source/configs/control_brace_style/always_next_line.rs rename to src/tools/rustfmt/tests/source/configs/control_brace_style/always_next_line.rs diff --git a/tests/source/configs/control_brace_style/always_same_line.rs b/src/tools/rustfmt/tests/source/configs/control_brace_style/always_same_line.rs similarity index 100% rename from tests/source/configs/control_brace_style/always_same_line.rs rename to src/tools/rustfmt/tests/source/configs/control_brace_style/always_same_line.rs diff --git a/tests/source/configs/control_brace_style/closing_next_line.rs b/src/tools/rustfmt/tests/source/configs/control_brace_style/closing_next_line.rs similarity index 100% rename from tests/source/configs/control_brace_style/closing_next_line.rs rename to src/tools/rustfmt/tests/source/configs/control_brace_style/closing_next_line.rs diff --git a/tests/source/configs/disable_all_formatting/false.rs b/src/tools/rustfmt/tests/source/configs/disable_all_formatting/false.rs similarity index 100% rename from tests/source/configs/disable_all_formatting/false.rs rename to src/tools/rustfmt/tests/source/configs/disable_all_formatting/false.rs diff --git a/tests/source/configs/disable_all_formatting/true.rs b/src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs similarity index 100% rename from tests/source/configs/disable_all_formatting/true.rs rename to src/tools/rustfmt/tests/source/configs/disable_all_formatting/true.rs diff --git a/tests/source/configs/doc_comment_code_block_small_heuristics/default-to-max.rs b/src/tools/rustfmt/tests/source/configs/doc_comment_code_block_small_heuristics/default-to-max.rs similarity index 100% rename from tests/source/configs/doc_comment_code_block_small_heuristics/default-to-max.rs rename to src/tools/rustfmt/tests/source/configs/doc_comment_code_block_small_heuristics/default-to-max.rs diff --git a/tests/source/configs/doc_comment_code_block_small_heuristics/max-to-default.rs b/src/tools/rustfmt/tests/source/configs/doc_comment_code_block_small_heuristics/max-to-default.rs similarity index 100% rename from tests/source/configs/doc_comment_code_block_small_heuristics/max-to-default.rs rename to src/tools/rustfmt/tests/source/configs/doc_comment_code_block_small_heuristics/max-to-default.rs diff --git a/tests/source/configs/doc_comment_code_block_width/100.rs b/src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/100.rs similarity index 100% rename from tests/source/configs/doc_comment_code_block_width/100.rs rename to src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/100.rs diff --git a/tests/source/configs/doc_comment_code_block_width/100_greater_max_width.rs b/src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/100_greater_max_width.rs similarity index 100% rename from tests/source/configs/doc_comment_code_block_width/100_greater_max_width.rs rename to src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/100_greater_max_width.rs diff --git a/tests/source/configs/doc_comment_code_block_width/50.rs b/src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/50.rs similarity index 100% rename from tests/source/configs/doc_comment_code_block_width/50.rs rename to src/tools/rustfmt/tests/source/configs/doc_comment_code_block_width/50.rs diff --git a/tests/source/configs/empty_item_single_line/false.rs b/src/tools/rustfmt/tests/source/configs/empty_item_single_line/false.rs similarity index 100% rename from tests/source/configs/empty_item_single_line/false.rs rename to src/tools/rustfmt/tests/source/configs/empty_item_single_line/false.rs diff --git a/tests/source/configs/empty_item_single_line/true.rs b/src/tools/rustfmt/tests/source/configs/empty_item_single_line/true.rs similarity index 100% rename from tests/source/configs/empty_item_single_line/true.rs rename to src/tools/rustfmt/tests/source/configs/empty_item_single_line/true.rs diff --git a/tests/source/configs/enum_discrim_align_threshold/40.rs b/src/tools/rustfmt/tests/source/configs/enum_discrim_align_threshold/40.rs similarity index 100% rename from tests/source/configs/enum_discrim_align_threshold/40.rs rename to src/tools/rustfmt/tests/source/configs/enum_discrim_align_threshold/40.rs diff --git a/tests/source/configs/error_on_line_overflow/false.rs b/src/tools/rustfmt/tests/source/configs/error_on_line_overflow/false.rs similarity index 100% rename from tests/source/configs/error_on_line_overflow/false.rs rename to src/tools/rustfmt/tests/source/configs/error_on_line_overflow/false.rs diff --git a/tests/source/configs/float_literal_trailing_zero/always.rs b/src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/always.rs similarity index 100% rename from tests/source/configs/float_literal_trailing_zero/always.rs rename to src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/always.rs diff --git a/tests/source/configs/float_literal_trailing_zero/if-no-postfix.rs b/src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/if-no-postfix.rs similarity index 100% rename from tests/source/configs/float_literal_trailing_zero/if-no-postfix.rs rename to src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/if-no-postfix.rs diff --git a/tests/source/configs/float_literal_trailing_zero/never.rs b/src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/never.rs similarity index 100% rename from tests/source/configs/float_literal_trailing_zero/never.rs rename to src/tools/rustfmt/tests/source/configs/float_literal_trailing_zero/never.rs diff --git a/tests/source/configs/fn_params_layout/compressed.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs similarity index 100% rename from tests/source/configs/fn_params_layout/compressed.rs rename to src/tools/rustfmt/tests/source/configs/fn_params_layout/compressed.rs diff --git a/tests/source/configs/fn_params_layout/tall.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs similarity index 100% rename from tests/source/configs/fn_params_layout/tall.rs rename to src/tools/rustfmt/tests/source/configs/fn_params_layout/tall.rs diff --git a/tests/source/configs/fn_params_layout/vertical.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs similarity index 100% rename from tests/source/configs/fn_params_layout/vertical.rs rename to src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical.rs diff --git a/tests/source/configs/fn_params_layout/vertical_style_2027.rs b/src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical_style_2027.rs similarity index 100% rename from tests/source/configs/fn_params_layout/vertical_style_2027.rs rename to src/tools/rustfmt/tests/source/configs/fn_params_layout/vertical_style_2027.rs diff --git a/tests/source/configs/fn_single_line/false.rs b/src/tools/rustfmt/tests/source/configs/fn_single_line/false.rs similarity index 100% rename from tests/source/configs/fn_single_line/false.rs rename to src/tools/rustfmt/tests/source/configs/fn_single_line/false.rs diff --git a/tests/source/configs/fn_single_line/true.rs b/src/tools/rustfmt/tests/source/configs/fn_single_line/true.rs similarity index 100% rename from tests/source/configs/fn_single_line/true.rs rename to src/tools/rustfmt/tests/source/configs/fn_single_line/true.rs diff --git a/tests/source/configs/force_explicit_abi/false.rs b/src/tools/rustfmt/tests/source/configs/force_explicit_abi/false.rs similarity index 100% rename from tests/source/configs/force_explicit_abi/false.rs rename to src/tools/rustfmt/tests/source/configs/force_explicit_abi/false.rs diff --git a/tests/source/configs/force_explicit_abi/true.rs b/src/tools/rustfmt/tests/source/configs/force_explicit_abi/true.rs similarity index 100% rename from tests/source/configs/force_explicit_abi/true.rs rename to src/tools/rustfmt/tests/source/configs/force_explicit_abi/true.rs diff --git a/tests/source/configs/force_multiline_block/false.rs b/src/tools/rustfmt/tests/source/configs/force_multiline_block/false.rs similarity index 100% rename from tests/source/configs/force_multiline_block/false.rs rename to src/tools/rustfmt/tests/source/configs/force_multiline_block/false.rs diff --git a/tests/source/configs/force_multiline_block/true.rs b/src/tools/rustfmt/tests/source/configs/force_multiline_block/true.rs similarity index 100% rename from tests/source/configs/force_multiline_block/true.rs rename to src/tools/rustfmt/tests/source/configs/force_multiline_block/true.rs diff --git a/tests/source/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs similarity index 100% rename from tests/source/configs/format_generated_files/false.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/false.rs diff --git a/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs similarity index 100% rename from tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs diff --git a/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs similarity index 100% rename from tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_marker_out_scope_size.rs diff --git a/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs similarity index 100% rename from tests/source/configs/format_generated_files/false_with_zero_search_limit.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/false_with_zero_search_limit.rs diff --git a/tests/source/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs similarity index 100% rename from tests/source/configs/format_generated_files/true.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/true.rs diff --git a/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs similarity index 100% rename from tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_in_scope_size.rs diff --git a/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs b/src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs similarity index 100% rename from tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs rename to src/tools/rustfmt/tests/source/configs/format_generated_files/true_with_marker_not_in_header.rs diff --git a/tests/source/configs/format_macro_bodies/false.rs b/src/tools/rustfmt/tests/source/configs/format_macro_bodies/false.rs similarity index 100% rename from tests/source/configs/format_macro_bodies/false.rs rename to src/tools/rustfmt/tests/source/configs/format_macro_bodies/false.rs diff --git a/tests/source/configs/format_macro_bodies/true.rs b/src/tools/rustfmt/tests/source/configs/format_macro_bodies/true.rs similarity index 100% rename from tests/source/configs/format_macro_bodies/true.rs rename to src/tools/rustfmt/tests/source/configs/format_macro_bodies/true.rs diff --git a/tests/source/configs/format_macro_matchers/false.rs b/src/tools/rustfmt/tests/source/configs/format_macro_matchers/false.rs similarity index 100% rename from tests/source/configs/format_macro_matchers/false.rs rename to src/tools/rustfmt/tests/source/configs/format_macro_matchers/false.rs diff --git a/tests/source/configs/format_macro_matchers/true.rs b/src/tools/rustfmt/tests/source/configs/format_macro_matchers/true.rs similarity index 100% rename from tests/source/configs/format_macro_matchers/true.rs rename to src/tools/rustfmt/tests/source/configs/format_macro_matchers/true.rs diff --git a/tests/source/configs/format_strings/false.rs b/src/tools/rustfmt/tests/source/configs/format_strings/false.rs similarity index 100% rename from tests/source/configs/format_strings/false.rs rename to src/tools/rustfmt/tests/source/configs/format_strings/false.rs diff --git a/tests/source/configs/format_strings/true.rs b/src/tools/rustfmt/tests/source/configs/format_strings/true.rs similarity index 100% rename from tests/source/configs/format_strings/true.rs rename to src/tools/rustfmt/tests/source/configs/format_strings/true.rs diff --git a/tests/source/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs similarity index 100% rename from tests/source/configs/group_imports/One-merge_imports.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/One-merge_imports.rs diff --git a/tests/source/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs similarity index 100% rename from tests/source/configs/group_imports/One-nested.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/One-nested.rs diff --git a/tests/source/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs similarity index 100% rename from tests/source/configs/group_imports/One-no_reorder.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/One-no_reorder.rs diff --git a/tests/source/configs/group_imports/One.rs b/src/tools/rustfmt/tests/source/configs/group_imports/One.rs similarity index 100% rename from tests/source/configs/group_imports/One.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/One.rs diff --git a/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs similarity index 100% rename from tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-merge_imports.rs diff --git a/tests/source/configs/group_imports/StdExternalCrate-nested.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-nested.rs similarity index 100% rename from tests/source/configs/group_imports/StdExternalCrate-nested.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-nested.rs diff --git a/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs similarity index 100% rename from tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-no_reorder.rs diff --git a/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs similarity index 100% rename from tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate-non_consecutive.rs diff --git a/tests/source/configs/group_imports/StdExternalCrate.rs b/src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate.rs similarity index 100% rename from tests/source/configs/group_imports/StdExternalCrate.rs rename to src/tools/rustfmt/tests/source/configs/group_imports/StdExternalCrate.rs diff --git a/tests/source/configs/hard_tabs/false.rs b/src/tools/rustfmt/tests/source/configs/hard_tabs/false.rs similarity index 100% rename from tests/source/configs/hard_tabs/false.rs rename to src/tools/rustfmt/tests/source/configs/hard_tabs/false.rs diff --git a/tests/source/configs/hard_tabs/true.rs b/src/tools/rustfmt/tests/source/configs/hard_tabs/true.rs similarity index 100% rename from tests/source/configs/hard_tabs/true.rs rename to src/tools/rustfmt/tests/source/configs/hard_tabs/true.rs diff --git a/tests/source/configs/hex_literal_case/hex_literal_lower.rs b/src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_lower.rs similarity index 100% rename from tests/source/configs/hex_literal_case/hex_literal_lower.rs rename to src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_lower.rs diff --git a/tests/source/configs/hex_literal_case/hex_literal_preserve.rs b/src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_preserve.rs similarity index 100% rename from tests/source/configs/hex_literal_case/hex_literal_preserve.rs rename to src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_preserve.rs diff --git a/tests/source/configs/hex_literal_case/hex_literal_upper.rs b/src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_upper.rs similarity index 100% rename from tests/source/configs/hex_literal_case/hex_literal_upper.rs rename to src/tools/rustfmt/tests/source/configs/hex_literal_case/hex_literal_upper.rs diff --git a/tests/source/configs/imports_layout/merge_mixed.rs b/src/tools/rustfmt/tests/source/configs/imports_layout/merge_mixed.rs similarity index 100% rename from tests/source/configs/imports_layout/merge_mixed.rs rename to src/tools/rustfmt/tests/source/configs/imports_layout/merge_mixed.rs diff --git a/tests/source/configs/indent_style/block_args.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_args.rs similarity index 100% rename from tests/source/configs/indent_style/block_args.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_args.rs diff --git a/tests/source/configs/indent_style/block_array.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_array.rs similarity index 100% rename from tests/source/configs/indent_style/block_array.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_array.rs diff --git a/tests/source/configs/indent_style/block_call.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_call.rs similarity index 100% rename from tests/source/configs/indent_style/block_call.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_call.rs diff --git a/tests/source/configs/indent_style/block_chain.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_chain.rs similarity index 100% rename from tests/source/configs/indent_style/block_chain.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_chain.rs diff --git a/tests/source/configs/indent_style/block_generic.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_generic.rs similarity index 100% rename from tests/source/configs/indent_style/block_generic.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_generic.rs diff --git a/tests/source/configs/indent_style/block_struct_lit.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_struct_lit.rs similarity index 100% rename from tests/source/configs/indent_style/block_struct_lit.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_struct_lit.rs diff --git a/tests/source/configs/indent_style/block_trailing_comma_call/one.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs similarity index 100% rename from tests/source/configs/indent_style/block_trailing_comma_call/one.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/one.rs diff --git a/tests/source/configs/indent_style/block_trailing_comma_call/two.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs similarity index 100% rename from tests/source/configs/indent_style/block_trailing_comma_call/two.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_trailing_comma_call/two.rs diff --git a/tests/source/configs/indent_style/block_where_pred.rs b/src/tools/rustfmt/tests/source/configs/indent_style/block_where_pred.rs similarity index 100% rename from tests/source/configs/indent_style/block_where_pred.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/block_where_pred.rs diff --git a/tests/source/configs/indent_style/default.rs b/src/tools/rustfmt/tests/source/configs/indent_style/default.rs similarity index 100% rename from tests/source/configs/indent_style/default.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/default.rs diff --git a/tests/source/configs/indent_style/rfc_where.rs b/src/tools/rustfmt/tests/source/configs/indent_style/rfc_where.rs similarity index 100% rename from tests/source/configs/indent_style/rfc_where.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/rfc_where.rs diff --git a/tests/source/configs/indent_style/visual_args.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_args.rs similarity index 100% rename from tests/source/configs/indent_style/visual_args.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_args.rs diff --git a/tests/source/configs/indent_style/visual_array.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_array.rs similarity index 100% rename from tests/source/configs/indent_style/visual_array.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_array.rs diff --git a/tests/source/configs/indent_style/visual_call.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_call.rs similarity index 100% rename from tests/source/configs/indent_style/visual_call.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_call.rs diff --git a/tests/source/configs/indent_style/visual_chain.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_chain.rs similarity index 100% rename from tests/source/configs/indent_style/visual_chain.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_chain.rs diff --git a/tests/source/configs/indent_style/visual_generics.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_generics.rs similarity index 100% rename from tests/source/configs/indent_style/visual_generics.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_generics.rs diff --git a/tests/source/configs/indent_style/visual_struct_lit.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_struct_lit.rs similarity index 100% rename from tests/source/configs/indent_style/visual_struct_lit.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_struct_lit.rs diff --git a/tests/source/configs/indent_style/visual_trailing_comma.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_trailing_comma.rs similarity index 100% rename from tests/source/configs/indent_style/visual_trailing_comma.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_trailing_comma.rs diff --git a/tests/source/configs/indent_style/visual_where_pred.rs b/src/tools/rustfmt/tests/source/configs/indent_style/visual_where_pred.rs similarity index 100% rename from tests/source/configs/indent_style/visual_where_pred.rs rename to src/tools/rustfmt/tests/source/configs/indent_style/visual_where_pred.rs diff --git a/tests/source/configs/match_arm_blocks/false.rs b/src/tools/rustfmt/tests/source/configs/match_arm_blocks/false.rs similarity index 100% rename from tests/source/configs/match_arm_blocks/false.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_blocks/false.rs diff --git a/tests/source/configs/match_arm_blocks/true.rs b/src/tools/rustfmt/tests/source/configs/match_arm_blocks/true.rs similarity index 100% rename from tests/source/configs/match_arm_blocks/true.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_blocks/true.rs diff --git a/tests/source/configs/match_arm_indent/attrs.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/attrs.rs similarity index 100% rename from tests/source/configs/match_arm_indent/attrs.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/attrs.rs diff --git a/tests/source/configs/match_arm_indent/guards.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/guards.rs similarity index 100% rename from tests/source/configs/match_arm_indent/guards.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/guards.rs diff --git a/tests/source/configs/match_arm_indent/leading_pipes.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/leading_pipes.rs similarity index 100% rename from tests/source/configs/match_arm_indent/leading_pipes.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/leading_pipes.rs diff --git a/tests/source/configs/match_arm_indent/nested.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/nested.rs similarity index 100% rename from tests/source/configs/match_arm_indent/nested.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/nested.rs diff --git a/tests/source/configs/match_arm_indent/patterns.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/patterns.rs similarity index 100% rename from tests/source/configs/match_arm_indent/patterns.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/patterns.rs diff --git a/tests/source/configs/match_arm_indent/unindent.rs b/src/tools/rustfmt/tests/source/configs/match_arm_indent/unindent.rs similarity index 100% rename from tests/source/configs/match_arm_indent/unindent.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_indent/unindent.rs diff --git a/tests/source/configs/match_arm_leading_pipes/always.rs b/src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/always.rs similarity index 100% rename from tests/source/configs/match_arm_leading_pipes/always.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/always.rs diff --git a/tests/source/configs/match_arm_leading_pipes/never.rs b/src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/never.rs similarity index 100% rename from tests/source/configs/match_arm_leading_pipes/never.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/never.rs diff --git a/tests/source/configs/match_arm_leading_pipes/preserve.rs b/src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/preserve.rs similarity index 100% rename from tests/source/configs/match_arm_leading_pipes/preserve.rs rename to src/tools/rustfmt/tests/source/configs/match_arm_leading_pipes/preserve.rs diff --git a/tests/source/configs/match_block_trailing_comma/false.rs b/src/tools/rustfmt/tests/source/configs/match_block_trailing_comma/false.rs similarity index 100% rename from tests/source/configs/match_block_trailing_comma/false.rs rename to src/tools/rustfmt/tests/source/configs/match_block_trailing_comma/false.rs diff --git a/tests/source/configs/match_block_trailing_comma/true.rs b/src/tools/rustfmt/tests/source/configs/match_block_trailing_comma/true.rs similarity index 100% rename from tests/source/configs/match_block_trailing_comma/true.rs rename to src/tools/rustfmt/tests/source/configs/match_block_trailing_comma/true.rs diff --git a/tests/source/configs/merge_derives/true.rs b/src/tools/rustfmt/tests/source/configs/merge_derives/true.rs similarity index 100% rename from tests/source/configs/merge_derives/true.rs rename to src/tools/rustfmt/tests/source/configs/merge_derives/true.rs diff --git a/tests/source/configs/normalize_comments/false.rs b/src/tools/rustfmt/tests/source/configs/normalize_comments/false.rs similarity index 100% rename from tests/source/configs/normalize_comments/false.rs rename to src/tools/rustfmt/tests/source/configs/normalize_comments/false.rs diff --git a/tests/source/configs/normalize_comments/true.rs b/src/tools/rustfmt/tests/source/configs/normalize_comments/true.rs similarity index 100% rename from tests/source/configs/normalize_comments/true.rs rename to src/tools/rustfmt/tests/source/configs/normalize_comments/true.rs diff --git a/tests/source/configs/normalize_doc_attributes/false.rs b/src/tools/rustfmt/tests/source/configs/normalize_doc_attributes/false.rs similarity index 100% rename from tests/source/configs/normalize_doc_attributes/false.rs rename to src/tools/rustfmt/tests/source/configs/normalize_doc_attributes/false.rs diff --git a/tests/source/configs/normalize_doc_attributes/true.rs b/src/tools/rustfmt/tests/source/configs/normalize_doc_attributes/true.rs similarity index 100% rename from tests/source/configs/normalize_doc_attributes/true.rs rename to src/tools/rustfmt/tests/source/configs/normalize_doc_attributes/true.rs diff --git a/tests/source/configs/remove_nested_parens/remove_nested_parens.rs b/src/tools/rustfmt/tests/source/configs/remove_nested_parens/remove_nested_parens.rs similarity index 100% rename from tests/source/configs/remove_nested_parens/remove_nested_parens.rs rename to src/tools/rustfmt/tests/source/configs/remove_nested_parens/remove_nested_parens.rs diff --git a/tests/source/configs/reorder_impl_items/false.rs b/src/tools/rustfmt/tests/source/configs/reorder_impl_items/false.rs similarity index 100% rename from tests/source/configs/reorder_impl_items/false.rs rename to src/tools/rustfmt/tests/source/configs/reorder_impl_items/false.rs diff --git a/tests/source/configs/reorder_impl_items/true.rs b/src/tools/rustfmt/tests/source/configs/reorder_impl_items/true.rs similarity index 100% rename from tests/source/configs/reorder_impl_items/true.rs rename to src/tools/rustfmt/tests/source/configs/reorder_impl_items/true.rs diff --git a/tests/source/configs/reorder_imports/false.rs b/src/tools/rustfmt/tests/source/configs/reorder_imports/false.rs similarity index 100% rename from tests/source/configs/reorder_imports/false.rs rename to src/tools/rustfmt/tests/source/configs/reorder_imports/false.rs diff --git a/tests/source/configs/reorder_imports/true.rs b/src/tools/rustfmt/tests/source/configs/reorder_imports/true.rs similarity index 100% rename from tests/source/configs/reorder_imports/true.rs rename to src/tools/rustfmt/tests/source/configs/reorder_imports/true.rs diff --git a/tests/source/configs/reorder_modules/dolor/mod.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/dolor/mod.rs similarity index 100% rename from tests/source/configs/reorder_modules/dolor/mod.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/dolor/mod.rs diff --git a/tests/source/configs/reorder_modules/false.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/false.rs similarity index 100% rename from tests/source/configs/reorder_modules/false.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/false.rs diff --git a/tests/source/configs/reorder_modules/ipsum/mod.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/ipsum/mod.rs similarity index 100% rename from tests/source/configs/reorder_modules/ipsum/mod.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/ipsum/mod.rs diff --git a/tests/source/configs/reorder_modules/lorem/mod.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/lorem/mod.rs similarity index 100% rename from tests/source/configs/reorder_modules/lorem/mod.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/lorem/mod.rs diff --git a/tests/source/configs/reorder_modules/sit/mod.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/sit/mod.rs similarity index 100% rename from tests/source/configs/reorder_modules/sit/mod.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/sit/mod.rs diff --git a/tests/source/configs/reorder_modules/true.rs b/src/tools/rustfmt/tests/source/configs/reorder_modules/true.rs similarity index 100% rename from tests/source/configs/reorder_modules/true.rs rename to src/tools/rustfmt/tests/source/configs/reorder_modules/true.rs diff --git a/tests/source/configs/short_array_element_width_threshold/10.rs b/src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/10.rs similarity index 100% rename from tests/source/configs/short_array_element_width_threshold/10.rs rename to src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/10.rs diff --git a/tests/source/configs/short_array_element_width_threshold/20.rs b/src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/20.rs similarity index 100% rename from tests/source/configs/short_array_element_width_threshold/20.rs rename to src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/20.rs diff --git a/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs b/src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs similarity index 100% rename from tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs rename to src/tools/rustfmt/tests/source/configs/short_array_element_width_threshold/greater_than_max_width.rs diff --git a/tests/source/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs similarity index 100% rename from tests/source/configs/single_line_let_else_max_width/100.rs rename to src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/100.rs diff --git a/tests/source/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs similarity index 100% rename from tests/source/configs/single_line_let_else_max_width/50.rs rename to src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/50.rs diff --git a/tests/source/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs similarity index 100% rename from tests/source/configs/single_line_let_else_max_width/zero.rs rename to src/tools/rustfmt/tests/source/configs/single_line_let_else_max_width/zero.rs diff --git a/tests/source/configs/skip_children/foo/mod.rs b/src/tools/rustfmt/tests/source/configs/skip_children/foo/mod.rs similarity index 100% rename from tests/source/configs/skip_children/foo/mod.rs rename to src/tools/rustfmt/tests/source/configs/skip_children/foo/mod.rs diff --git a/tests/source/configs/skip_children/true.rs b/src/tools/rustfmt/tests/source/configs/skip_children/true.rs similarity index 100% rename from tests/source/configs/skip_children/true.rs rename to src/tools/rustfmt/tests/source/configs/skip_children/true.rs diff --git a/tests/source/configs/space_before_colon/true.rs b/src/tools/rustfmt/tests/source/configs/space_before_colon/true.rs similarity index 100% rename from tests/source/configs/space_before_colon/true.rs rename to src/tools/rustfmt/tests/source/configs/space_before_colon/true.rs diff --git a/tests/source/configs/spaces_around_ranges/false.rs b/src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs similarity index 100% rename from tests/source/configs/spaces_around_ranges/false.rs rename to src/tools/rustfmt/tests/source/configs/spaces_around_ranges/false.rs diff --git a/tests/source/configs/spaces_around_ranges/true.rs b/src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs similarity index 100% rename from tests/source/configs/spaces_around_ranges/true.rs rename to src/tools/rustfmt/tests/source/configs/spaces_around_ranges/true.rs diff --git a/tests/source/configs/struct_field_align_threshold/20.rs b/src/tools/rustfmt/tests/source/configs/struct_field_align_threshold/20.rs similarity index 100% rename from tests/source/configs/struct_field_align_threshold/20.rs rename to src/tools/rustfmt/tests/source/configs/struct_field_align_threshold/20.rs diff --git a/tests/source/configs/struct_lit_single_line/false.rs b/src/tools/rustfmt/tests/source/configs/struct_lit_single_line/false.rs similarity index 100% rename from tests/source/configs/struct_lit_single_line/false.rs rename to src/tools/rustfmt/tests/source/configs/struct_lit_single_line/false.rs diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2015.rs b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs similarity index 100% rename from tests/source/configs/style_edition/overflow_delim_expr_2015.rs rename to src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2015.rs diff --git a/tests/source/configs/style_edition/overflow_delim_expr_2024.rs b/src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs similarity index 100% rename from tests/source/configs/style_edition/overflow_delim_expr_2024.rs rename to src/tools/rustfmt/tests/source/configs/style_edition/overflow_delim_expr_2024.rs diff --git a/tests/source/configs/tab_spaces/2.rs b/src/tools/rustfmt/tests/source/configs/tab_spaces/2.rs similarity index 100% rename from tests/source/configs/tab_spaces/2.rs rename to src/tools/rustfmt/tests/source/configs/tab_spaces/2.rs diff --git a/tests/source/configs/tab_spaces/4.rs b/src/tools/rustfmt/tests/source/configs/tab_spaces/4.rs similarity index 100% rename from tests/source/configs/tab_spaces/4.rs rename to src/tools/rustfmt/tests/source/configs/tab_spaces/4.rs diff --git a/tests/source/configs/trailing_comma/always.rs b/src/tools/rustfmt/tests/source/configs/trailing_comma/always.rs similarity index 100% rename from tests/source/configs/trailing_comma/always.rs rename to src/tools/rustfmt/tests/source/configs/trailing_comma/always.rs diff --git a/tests/source/configs/trailing_comma/never.rs b/src/tools/rustfmt/tests/source/configs/trailing_comma/never.rs similarity index 100% rename from tests/source/configs/trailing_comma/never.rs rename to src/tools/rustfmt/tests/source/configs/trailing_comma/never.rs diff --git a/tests/source/configs/trailing_comma/vertical.rs b/src/tools/rustfmt/tests/source/configs/trailing_comma/vertical.rs similarity index 100% rename from tests/source/configs/trailing_comma/vertical.rs rename to src/tools/rustfmt/tests/source/configs/trailing_comma/vertical.rs diff --git a/tests/source/configs/type_punctuation_density/compressed.rs b/src/tools/rustfmt/tests/source/configs/type_punctuation_density/compressed.rs similarity index 100% rename from tests/source/configs/type_punctuation_density/compressed.rs rename to src/tools/rustfmt/tests/source/configs/type_punctuation_density/compressed.rs diff --git a/tests/source/configs/type_punctuation_density/wide.rs b/src/tools/rustfmt/tests/source/configs/type_punctuation_density/wide.rs similarity index 100% rename from tests/source/configs/type_punctuation_density/wide.rs rename to src/tools/rustfmt/tests/source/configs/type_punctuation_density/wide.rs diff --git a/tests/source/configs/use_field_init_shorthand/false.rs b/src/tools/rustfmt/tests/source/configs/use_field_init_shorthand/false.rs similarity index 100% rename from tests/source/configs/use_field_init_shorthand/false.rs rename to src/tools/rustfmt/tests/source/configs/use_field_init_shorthand/false.rs diff --git a/tests/source/configs/use_field_init_shorthand/true.rs b/src/tools/rustfmt/tests/source/configs/use_field_init_shorthand/true.rs similarity index 100% rename from tests/source/configs/use_field_init_shorthand/true.rs rename to src/tools/rustfmt/tests/source/configs/use_field_init_shorthand/true.rs diff --git a/tests/source/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs similarity index 100% rename from tests/source/configs/use_small_heuristics/default.rs rename to src/tools/rustfmt/tests/source/configs/use_small_heuristics/default.rs diff --git a/tests/source/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs similarity index 100% rename from tests/source/configs/use_small_heuristics/max.rs rename to src/tools/rustfmt/tests/source/configs/use_small_heuristics/max.rs diff --git a/tests/source/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs similarity index 100% rename from tests/source/configs/use_small_heuristics/off.rs rename to src/tools/rustfmt/tests/source/configs/use_small_heuristics/off.rs diff --git a/tests/source/configs/use_try_shorthand/false.rs b/src/tools/rustfmt/tests/source/configs/use_try_shorthand/false.rs similarity index 100% rename from tests/source/configs/use_try_shorthand/false.rs rename to src/tools/rustfmt/tests/source/configs/use_try_shorthand/false.rs diff --git a/tests/source/configs/use_try_shorthand/true.rs b/src/tools/rustfmt/tests/source/configs/use_try_shorthand/true.rs similarity index 100% rename from tests/source/configs/use_try_shorthand/true.rs rename to src/tools/rustfmt/tests/source/configs/use_try_shorthand/true.rs diff --git a/tests/source/configs/where_single_line/true.rs b/src/tools/rustfmt/tests/source/configs/where_single_line/true.rs similarity index 100% rename from tests/source/configs/where_single_line/true.rs rename to src/tools/rustfmt/tests/source/configs/where_single_line/true.rs diff --git a/tests/source/configs/wrap_comments/false.rs b/src/tools/rustfmt/tests/source/configs/wrap_comments/false.rs similarity index 100% rename from tests/source/configs/wrap_comments/false.rs rename to src/tools/rustfmt/tests/source/configs/wrap_comments/false.rs diff --git a/tests/source/configs/wrap_comments/true.rs b/src/tools/rustfmt/tests/source/configs/wrap_comments/true.rs similarity index 100% rename from tests/source/configs/wrap_comments/true.rs rename to src/tools/rustfmt/tests/source/configs/wrap_comments/true.rs diff --git a/tests/source/const-block-items.rs b/src/tools/rustfmt/tests/source/const-block-items.rs similarity index 100% rename from tests/source/const-block-items.rs rename to src/tools/rustfmt/tests/source/const-block-items.rs diff --git a/tests/source/const_generics.rs b/src/tools/rustfmt/tests/source/const_generics.rs similarity index 100% rename from tests/source/const_generics.rs rename to src/tools/rustfmt/tests/source/const_generics.rs diff --git a/tests/source/control-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/source/control-brace-style-always-next-line.rs similarity index 100% rename from tests/source/control-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/source/control-brace-style-always-next-line.rs diff --git a/tests/source/control-brace-style-always-same-line.rs b/src/tools/rustfmt/tests/source/control-brace-style-always-same-line.rs similarity index 100% rename from tests/source/control-brace-style-always-same-line.rs rename to src/tools/rustfmt/tests/source/control-brace-style-always-same-line.rs diff --git a/tests/source/default-field-values.rs b/src/tools/rustfmt/tests/source/default-field-values.rs similarity index 100% rename from tests/source/default-field-values.rs rename to src/tools/rustfmt/tests/source/default-field-values.rs diff --git a/tests/source/direct_const_arg.rs b/src/tools/rustfmt/tests/source/direct_const_arg.rs similarity index 100% rename from tests/source/direct_const_arg.rs rename to src/tools/rustfmt/tests/source/direct_const_arg.rs diff --git a/tests/source/doc-attrib.rs b/src/tools/rustfmt/tests/source/doc-attrib.rs similarity index 100% rename from tests/source/doc-attrib.rs rename to src/tools/rustfmt/tests/source/doc-attrib.rs diff --git a/tests/source/doc-comment-with-example.rs b/src/tools/rustfmt/tests/source/doc-comment-with-example.rs similarity index 100% rename from tests/source/doc-comment-with-example.rs rename to src/tools/rustfmt/tests/source/doc-comment-with-example.rs diff --git a/tests/source/doc.rs b/src/tools/rustfmt/tests/source/doc.rs similarity index 100% rename from tests/source/doc.rs rename to src/tools/rustfmt/tests/source/doc.rs diff --git a/tests/source/dyn_trait.rs b/src/tools/rustfmt/tests/source/dyn_trait.rs similarity index 100% rename from tests/source/dyn_trait.rs rename to src/tools/rustfmt/tests/source/dyn_trait.rs diff --git a/tests/source/else-if-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/source/else-if-brace-style-always-next-line.rs similarity index 100% rename from tests/source/else-if-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/source/else-if-brace-style-always-next-line.rs diff --git a/tests/source/else-if-brace-style-always-same-line.rs b/src/tools/rustfmt/tests/source/else-if-brace-style-always-same-line.rs similarity index 100% rename from tests/source/else-if-brace-style-always-same-line.rs rename to src/tools/rustfmt/tests/source/else-if-brace-style-always-same-line.rs diff --git a/tests/source/else-if-brace-style-closing-next-line.rs b/src/tools/rustfmt/tests/source/else-if-brace-style-closing-next-line.rs similarity index 100% rename from tests/source/else-if-brace-style-closing-next-line.rs rename to src/tools/rustfmt/tests/source/else-if-brace-style-closing-next-line.rs diff --git a/tests/source/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/source/empty-item-single-line-false.rs similarity index 100% rename from tests/source/empty-item-single-line-false.rs rename to src/tools/rustfmt/tests/source/empty-item-single-line-false.rs diff --git a/tests/source/empty_file.rs b/src/tools/rustfmt/tests/source/empty_file.rs similarity index 100% rename from tests/source/empty_file.rs rename to src/tools/rustfmt/tests/source/empty_file.rs diff --git a/tests/source/enum.rs b/src/tools/rustfmt/tests/source/enum.rs similarity index 100% rename from tests/source/enum.rs rename to src/tools/rustfmt/tests/source/enum.rs diff --git a/tests/source/ergonomic_clones.rs b/src/tools/rustfmt/tests/source/ergonomic_clones.rs similarity index 100% rename from tests/source/ergonomic_clones.rs rename to src/tools/rustfmt/tests/source/ergonomic_clones.rs diff --git a/tests/source/existential_type.rs b/src/tools/rustfmt/tests/source/existential_type.rs similarity index 100% rename from tests/source/existential_type.rs rename to src/tools/rustfmt/tests/source/existential_type.rs diff --git a/tests/source/expr-block.rs b/src/tools/rustfmt/tests/source/expr-block.rs similarity index 100% rename from tests/source/expr-block.rs rename to src/tools/rustfmt/tests/source/expr-block.rs diff --git a/tests/source/expr-overflow-delimited.rs b/src/tools/rustfmt/tests/source/expr-overflow-delimited.rs similarity index 100% rename from tests/source/expr-overflow-delimited.rs rename to src/tools/rustfmt/tests/source/expr-overflow-delimited.rs diff --git a/tests/source/expr.rs b/src/tools/rustfmt/tests/source/expr.rs similarity index 100% rename from tests/source/expr.rs rename to src/tools/rustfmt/tests/source/expr.rs diff --git a/tests/source/extern.rs b/src/tools/rustfmt/tests/source/extern.rs similarity index 100% rename from tests/source/extern.rs rename to src/tools/rustfmt/tests/source/extern.rs diff --git a/tests/source/extern_not_explicit.rs b/src/tools/rustfmt/tests/source/extern_not_explicit.rs similarity index 100% rename from tests/source/extern_not_explicit.rs rename to src/tools/rustfmt/tests/source/extern_not_explicit.rs diff --git a/tests/source/file-lines-1.rs b/src/tools/rustfmt/tests/source/file-lines-1.rs similarity index 100% rename from tests/source/file-lines-1.rs rename to src/tools/rustfmt/tests/source/file-lines-1.rs diff --git a/tests/source/file-lines-2.rs b/src/tools/rustfmt/tests/source/file-lines-2.rs similarity index 100% rename from tests/source/file-lines-2.rs rename to src/tools/rustfmt/tests/source/file-lines-2.rs diff --git a/tests/source/file-lines-3.rs b/src/tools/rustfmt/tests/source/file-lines-3.rs similarity index 100% rename from tests/source/file-lines-3.rs rename to src/tools/rustfmt/tests/source/file-lines-3.rs diff --git a/tests/source/file-lines-4.rs b/src/tools/rustfmt/tests/source/file-lines-4.rs similarity index 100% rename from tests/source/file-lines-4.rs rename to src/tools/rustfmt/tests/source/file-lines-4.rs diff --git a/tests/source/file-lines-5.rs b/src/tools/rustfmt/tests/source/file-lines-5.rs similarity index 100% rename from tests/source/file-lines-5.rs rename to src/tools/rustfmt/tests/source/file-lines-5.rs diff --git a/tests/source/file-lines-6.rs b/src/tools/rustfmt/tests/source/file-lines-6.rs similarity index 100% rename from tests/source/file-lines-6.rs rename to src/tools/rustfmt/tests/source/file-lines-6.rs diff --git a/tests/source/file-lines-7.rs b/src/tools/rustfmt/tests/source/file-lines-7.rs similarity index 100% rename from tests/source/file-lines-7.rs rename to src/tools/rustfmt/tests/source/file-lines-7.rs diff --git a/tests/source/file-lines-item.rs b/src/tools/rustfmt/tests/source/file-lines-item.rs similarity index 100% rename from tests/source/file-lines-item.rs rename to src/tools/rustfmt/tests/source/file-lines-item.rs diff --git a/tests/source/fn-custom-2.rs b/src/tools/rustfmt/tests/source/fn-custom-2.rs similarity index 100% rename from tests/source/fn-custom-2.rs rename to src/tools/rustfmt/tests/source/fn-custom-2.rs diff --git a/tests/source/fn-custom-3.rs b/src/tools/rustfmt/tests/source/fn-custom-3.rs similarity index 100% rename from tests/source/fn-custom-3.rs rename to src/tools/rustfmt/tests/source/fn-custom-3.rs diff --git a/tests/source/fn-custom-4.rs b/src/tools/rustfmt/tests/source/fn-custom-4.rs similarity index 100% rename from tests/source/fn-custom-4.rs rename to src/tools/rustfmt/tests/source/fn-custom-4.rs diff --git a/tests/source/fn-custom-6.rs b/src/tools/rustfmt/tests/source/fn-custom-6.rs similarity index 100% rename from tests/source/fn-custom-6.rs rename to src/tools/rustfmt/tests/source/fn-custom-6.rs diff --git a/tests/source/fn-custom-7.rs b/src/tools/rustfmt/tests/source/fn-custom-7.rs similarity index 100% rename from tests/source/fn-custom-7.rs rename to src/tools/rustfmt/tests/source/fn-custom-7.rs diff --git a/tests/source/fn-custom-8.rs b/src/tools/rustfmt/tests/source/fn-custom-8.rs similarity index 100% rename from tests/source/fn-custom-8.rs rename to src/tools/rustfmt/tests/source/fn-custom-8.rs diff --git a/tests/source/fn-custom.rs b/src/tools/rustfmt/tests/source/fn-custom.rs similarity index 100% rename from tests/source/fn-custom.rs rename to src/tools/rustfmt/tests/source/fn-custom.rs diff --git a/tests/source/fn-param-attributes.rs b/src/tools/rustfmt/tests/source/fn-param-attributes.rs similarity index 100% rename from tests/source/fn-param-attributes.rs rename to src/tools/rustfmt/tests/source/fn-param-attributes.rs diff --git a/tests/source/fn-simple.rs b/src/tools/rustfmt/tests/source/fn-simple.rs similarity index 100% rename from tests/source/fn-simple.rs rename to src/tools/rustfmt/tests/source/fn-simple.rs diff --git a/tests/source/fn-single-line/version_one.rs b/src/tools/rustfmt/tests/source/fn-single-line/version_one.rs similarity index 100% rename from tests/source/fn-single-line/version_one.rs rename to src/tools/rustfmt/tests/source/fn-single-line/version_one.rs diff --git a/tests/source/fn-single-line/version_two.rs b/src/tools/rustfmt/tests/source/fn-single-line/version_two.rs similarity index 100% rename from tests/source/fn-single-line/version_two.rs rename to src/tools/rustfmt/tests/source/fn-single-line/version_two.rs diff --git a/tests/source/fn_args_indent-block.rs b/src/tools/rustfmt/tests/source/fn_args_indent-block.rs similarity index 100% rename from tests/source/fn_args_indent-block.rs rename to src/tools/rustfmt/tests/source/fn_args_indent-block.rs diff --git a/tests/source/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs similarity index 100% rename from tests/source/fn_args_layout-vertical.rs rename to src/tools/rustfmt/tests/source/fn_args_layout-vertical.rs diff --git a/tests/source/frontmatter_compact.rs b/src/tools/rustfmt/tests/source/frontmatter_compact.rs similarity index 100% rename from tests/source/frontmatter_compact.rs rename to src/tools/rustfmt/tests/source/frontmatter_compact.rs diff --git a/tests/source/frontmatter_escaped.rs b/src/tools/rustfmt/tests/source/frontmatter_escaped.rs similarity index 100% rename from tests/source/frontmatter_escaped.rs rename to src/tools/rustfmt/tests/source/frontmatter_escaped.rs diff --git a/tests/source/frontmatter_spaced.rs b/src/tools/rustfmt/tests/source/frontmatter_spaced.rs similarity index 100% rename from tests/source/frontmatter_spaced.rs rename to src/tools/rustfmt/tests/source/frontmatter_spaced.rs diff --git a/tests/source/generic_static.rs b/src/tools/rustfmt/tests/source/generic_static.rs similarity index 100% rename from tests/source/generic_static.rs rename to src/tools/rustfmt/tests/source/generic_static.rs diff --git a/tests/source/hard-tabs.rs b/src/tools/rustfmt/tests/source/hard-tabs.rs similarity index 100% rename from tests/source/hard-tabs.rs rename to src/tools/rustfmt/tests/source/hard-tabs.rs diff --git a/tests/source/hello.rs b/src/tools/rustfmt/tests/source/hello.rs similarity index 100% rename from tests/source/hello.rs rename to src/tools/rustfmt/tests/source/hello.rs diff --git a/tests/source/hello2.rs b/src/tools/rustfmt/tests/source/hello2.rs similarity index 100% rename from tests/source/hello2.rs rename to src/tools/rustfmt/tests/source/hello2.rs diff --git a/tests/source/if_while_or_patterns.rs b/src/tools/rustfmt/tests/source/if_while_or_patterns.rs similarity index 100% rename from tests/source/if_while_or_patterns.rs rename to src/tools/rustfmt/tests/source/if_while_or_patterns.rs diff --git a/tests/source/immovable_coroutines.rs b/src/tools/rustfmt/tests/source/immovable_coroutines.rs similarity index 100% rename from tests/source/immovable_coroutines.rs rename to src/tools/rustfmt/tests/source/immovable_coroutines.rs diff --git a/tests/source/impl-restriction.rs b/src/tools/rustfmt/tests/source/impl-restriction.rs similarity index 100% rename from tests/source/impl-restriction.rs rename to src/tools/rustfmt/tests/source/impl-restriction.rs diff --git a/tests/source/impls.rs b/src/tools/rustfmt/tests/source/impls.rs similarity index 100% rename from tests/source/impls.rs rename to src/tools/rustfmt/tests/source/impls.rs diff --git a/tests/source/imports/imports-impl-only-use.rs b/src/tools/rustfmt/tests/source/imports/imports-impl-only-use.rs similarity index 100% rename from tests/source/imports/imports-impl-only-use.rs rename to src/tools/rustfmt/tests/source/imports/imports-impl-only-use.rs diff --git a/tests/source/imports/imports-reorder-lines-and-items.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines-and-items.rs similarity index 100% rename from tests/source/imports/imports-reorder-lines-and-items.rs rename to src/tools/rustfmt/tests/source/imports/imports-reorder-lines-and-items.rs diff --git a/tests/source/imports/imports-reorder-lines.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder-lines.rs similarity index 100% rename from tests/source/imports/imports-reorder-lines.rs rename to src/tools/rustfmt/tests/source/imports/imports-reorder-lines.rs diff --git a/tests/source/imports/imports-reorder.rs b/src/tools/rustfmt/tests/source/imports/imports-reorder.rs similarity index 100% rename from tests/source/imports/imports-reorder.rs rename to src/tools/rustfmt/tests/source/imports/imports-reorder.rs diff --git a/tests/source/imports/imports.rs b/src/tools/rustfmt/tests/source/imports/imports.rs similarity index 100% rename from tests/source/imports/imports.rs rename to src/tools/rustfmt/tests/source/imports/imports.rs diff --git a/tests/source/imports/imports_block_indent.rs b/src/tools/rustfmt/tests/source/imports/imports_block_indent.rs similarity index 100% rename from tests/source/imports/imports_block_indent.rs rename to src/tools/rustfmt/tests/source/imports/imports_block_indent.rs diff --git a/tests/source/imports/imports_granularity_crate.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_crate.rs similarity index 100% rename from tests/source/imports/imports_granularity_crate.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_crate.rs diff --git a/tests/source/imports/imports_granularity_default-with-dups.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs similarity index 100% rename from tests/source/imports/imports_granularity_default-with-dups.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_default-with-dups.rs diff --git a/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs similarity index 100% rename from tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs diff --git a/tests/source/imports/imports_granularity_item-with-dups.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs similarity index 100% rename from tests/source/imports/imports_granularity_item-with-dups.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_item-with-dups.rs diff --git a/tests/source/imports/imports_granularity_item.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs similarity index 100% rename from tests/source/imports/imports_granularity_item.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_item.rs diff --git a/tests/source/imports/imports_granularity_module.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs similarity index 100% rename from tests/source/imports/imports_granularity_module.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_module.rs diff --git a/tests/source/imports/imports_granularity_one.rs b/src/tools/rustfmt/tests/source/imports/imports_granularity_one.rs similarity index 100% rename from tests/source/imports/imports_granularity_one.rs rename to src/tools/rustfmt/tests/source/imports/imports_granularity_one.rs diff --git a/tests/source/imports_raw_identifiers/version_One.rs b/src/tools/rustfmt/tests/source/imports_raw_identifiers/version_One.rs similarity index 100% rename from tests/source/imports_raw_identifiers/version_One.rs rename to src/tools/rustfmt/tests/source/imports_raw_identifiers/version_One.rs diff --git a/tests/source/imports_raw_identifiers/version_Two.rs b/src/tools/rustfmt/tests/source/imports_raw_identifiers/version_Two.rs similarity index 100% rename from tests/source/imports_raw_identifiers/version_Two.rs rename to src/tools/rustfmt/tests/source/imports_raw_identifiers/version_Two.rs diff --git a/tests/source/invalid-rust-code-in-doc-comment.rs b/src/tools/rustfmt/tests/source/invalid-rust-code-in-doc-comment.rs similarity index 100% rename from tests/source/invalid-rust-code-in-doc-comment.rs rename to src/tools/rustfmt/tests/source/invalid-rust-code-in-doc-comment.rs diff --git a/tests/source/issue-1021.rs b/src/tools/rustfmt/tests/source/issue-1021.rs similarity index 100% rename from tests/source/issue-1021.rs rename to src/tools/rustfmt/tests/source/issue-1021.rs diff --git a/tests/source/issue-1049.rs b/src/tools/rustfmt/tests/source/issue-1049.rs similarity index 100% rename from tests/source/issue-1049.rs rename to src/tools/rustfmt/tests/source/issue-1049.rs diff --git a/tests/source/issue-1111.rs b/src/tools/rustfmt/tests/source/issue-1111.rs similarity index 100% rename from tests/source/issue-1111.rs rename to src/tools/rustfmt/tests/source/issue-1111.rs diff --git a/tests/source/issue-1120.rs b/src/tools/rustfmt/tests/source/issue-1120.rs similarity index 100% rename from tests/source/issue-1120.rs rename to src/tools/rustfmt/tests/source/issue-1120.rs diff --git a/tests/source/issue-1124.rs b/src/tools/rustfmt/tests/source/issue-1124.rs similarity index 100% rename from tests/source/issue-1124.rs rename to src/tools/rustfmt/tests/source/issue-1124.rs diff --git a/tests/source/issue-1127.rs b/src/tools/rustfmt/tests/source/issue-1127.rs similarity index 100% rename from tests/source/issue-1127.rs rename to src/tools/rustfmt/tests/source/issue-1127.rs diff --git a/tests/source/issue-1158.rs b/src/tools/rustfmt/tests/source/issue-1158.rs similarity index 100% rename from tests/source/issue-1158.rs rename to src/tools/rustfmt/tests/source/issue-1158.rs diff --git a/tests/source/issue-1177.rs b/src/tools/rustfmt/tests/source/issue-1177.rs similarity index 100% rename from tests/source/issue-1177.rs rename to src/tools/rustfmt/tests/source/issue-1177.rs diff --git a/tests/source/issue-1192.rs b/src/tools/rustfmt/tests/source/issue-1192.rs similarity index 100% rename from tests/source/issue-1192.rs rename to src/tools/rustfmt/tests/source/issue-1192.rs diff --git a/tests/source/issue-1210/a.rs b/src/tools/rustfmt/tests/source/issue-1210/a.rs similarity index 100% rename from tests/source/issue-1210/a.rs rename to src/tools/rustfmt/tests/source/issue-1210/a.rs diff --git a/tests/source/issue-1210/b.rs b/src/tools/rustfmt/tests/source/issue-1210/b.rs similarity index 100% rename from tests/source/issue-1210/b.rs rename to src/tools/rustfmt/tests/source/issue-1210/b.rs diff --git a/tests/source/issue-1210/c.rs b/src/tools/rustfmt/tests/source/issue-1210/c.rs similarity index 100% rename from tests/source/issue-1210/c.rs rename to src/tools/rustfmt/tests/source/issue-1210/c.rs diff --git a/tests/source/issue-1210/d.rs b/src/tools/rustfmt/tests/source/issue-1210/d.rs similarity index 100% rename from tests/source/issue-1210/d.rs rename to src/tools/rustfmt/tests/source/issue-1210/d.rs diff --git a/tests/source/issue-1210/e.rs b/src/tools/rustfmt/tests/source/issue-1210/e.rs similarity index 100% rename from tests/source/issue-1210/e.rs rename to src/tools/rustfmt/tests/source/issue-1210/e.rs diff --git a/tests/source/issue-1211.rs b/src/tools/rustfmt/tests/source/issue-1211.rs similarity index 100% rename from tests/source/issue-1211.rs rename to src/tools/rustfmt/tests/source/issue-1211.rs diff --git a/tests/source/issue-1216.rs b/src/tools/rustfmt/tests/source/issue-1216.rs similarity index 100% rename from tests/source/issue-1216.rs rename to src/tools/rustfmt/tests/source/issue-1216.rs diff --git a/tests/source/issue-1239.rs b/src/tools/rustfmt/tests/source/issue-1239.rs similarity index 100% rename from tests/source/issue-1239.rs rename to src/tools/rustfmt/tests/source/issue-1239.rs diff --git a/tests/source/issue-1278.rs b/src/tools/rustfmt/tests/source/issue-1278.rs similarity index 100% rename from tests/source/issue-1278.rs rename to src/tools/rustfmt/tests/source/issue-1278.rs diff --git a/tests/source/issue-1350.rs b/src/tools/rustfmt/tests/source/issue-1350.rs similarity index 100% rename from tests/source/issue-1350.rs rename to src/tools/rustfmt/tests/source/issue-1350.rs diff --git a/tests/source/issue-1366.rs b/src/tools/rustfmt/tests/source/issue-1366.rs similarity index 100% rename from tests/source/issue-1366.rs rename to src/tools/rustfmt/tests/source/issue-1366.rs diff --git a/tests/source/issue-1468.rs b/src/tools/rustfmt/tests/source/issue-1468.rs similarity index 100% rename from tests/source/issue-1468.rs rename to src/tools/rustfmt/tests/source/issue-1468.rs diff --git a/tests/source/issue-1693.rs b/src/tools/rustfmt/tests/source/issue-1693.rs similarity index 100% rename from tests/source/issue-1693.rs rename to src/tools/rustfmt/tests/source/issue-1693.rs diff --git a/tests/source/issue-1800.rs b/src/tools/rustfmt/tests/source/issue-1800.rs similarity index 100% rename from tests/source/issue-1800.rs rename to src/tools/rustfmt/tests/source/issue-1800.rs diff --git a/tests/source/issue-1914.rs b/src/tools/rustfmt/tests/source/issue-1914.rs similarity index 100% rename from tests/source/issue-1914.rs rename to src/tools/rustfmt/tests/source/issue-1914.rs diff --git a/tests/source/issue-2025.rs b/src/tools/rustfmt/tests/source/issue-2025.rs similarity index 100% rename from tests/source/issue-2025.rs rename to src/tools/rustfmt/tests/source/issue-2025.rs diff --git a/tests/source/issue-2111.rs b/src/tools/rustfmt/tests/source/issue-2111.rs similarity index 100% rename from tests/source/issue-2111.rs rename to src/tools/rustfmt/tests/source/issue-2111.rs diff --git a/tests/source/issue-2164.rs b/src/tools/rustfmt/tests/source/issue-2164.rs similarity index 100% rename from tests/source/issue-2164.rs rename to src/tools/rustfmt/tests/source/issue-2164.rs diff --git a/tests/source/issue-2179/one.rs b/src/tools/rustfmt/tests/source/issue-2179/one.rs similarity index 100% rename from tests/source/issue-2179/one.rs rename to src/tools/rustfmt/tests/source/issue-2179/one.rs diff --git a/tests/source/issue-2179/two.rs b/src/tools/rustfmt/tests/source/issue-2179/two.rs similarity index 100% rename from tests/source/issue-2179/two.rs rename to src/tools/rustfmt/tests/source/issue-2179/two.rs diff --git a/tests/source/issue-2256.rs b/src/tools/rustfmt/tests/source/issue-2256.rs similarity index 100% rename from tests/source/issue-2256.rs rename to src/tools/rustfmt/tests/source/issue-2256.rs diff --git a/tests/source/issue-2342.rs b/src/tools/rustfmt/tests/source/issue-2342.rs similarity index 100% rename from tests/source/issue-2342.rs rename to src/tools/rustfmt/tests/source/issue-2342.rs diff --git a/tests/source/issue-2445.rs b/src/tools/rustfmt/tests/source/issue-2445.rs similarity index 100% rename from tests/source/issue-2445.rs rename to src/tools/rustfmt/tests/source/issue-2445.rs diff --git a/tests/source/issue-2446.rs b/src/tools/rustfmt/tests/source/issue-2446.rs similarity index 100% rename from tests/source/issue-2446.rs rename to src/tools/rustfmt/tests/source/issue-2446.rs diff --git a/tests/source/issue-2479.rs b/src/tools/rustfmt/tests/source/issue-2479.rs similarity index 100% rename from tests/source/issue-2479.rs rename to src/tools/rustfmt/tests/source/issue-2479.rs diff --git a/tests/source/issue-2482/a.rs b/src/tools/rustfmt/tests/source/issue-2482/a.rs similarity index 100% rename from tests/source/issue-2482/a.rs rename to src/tools/rustfmt/tests/source/issue-2482/a.rs diff --git a/tests/source/issue-2482/b.rs b/src/tools/rustfmt/tests/source/issue-2482/b.rs similarity index 100% rename from tests/source/issue-2482/b.rs rename to src/tools/rustfmt/tests/source/issue-2482/b.rs diff --git a/tests/source/issue-2482/c.rs b/src/tools/rustfmt/tests/source/issue-2482/c.rs similarity index 100% rename from tests/source/issue-2482/c.rs rename to src/tools/rustfmt/tests/source/issue-2482/c.rs diff --git a/tests/source/issue-2496.rs b/src/tools/rustfmt/tests/source/issue-2496.rs similarity index 100% rename from tests/source/issue-2496.rs rename to src/tools/rustfmt/tests/source/issue-2496.rs diff --git a/tests/source/issue-2520.rs b/src/tools/rustfmt/tests/source/issue-2520.rs similarity index 100% rename from tests/source/issue-2520.rs rename to src/tools/rustfmt/tests/source/issue-2520.rs diff --git a/tests/source/issue-2523.rs b/src/tools/rustfmt/tests/source/issue-2523.rs similarity index 100% rename from tests/source/issue-2523.rs rename to src/tools/rustfmt/tests/source/issue-2523.rs diff --git a/tests/source/issue-2582.rs b/src/tools/rustfmt/tests/source/issue-2582.rs similarity index 100% rename from tests/source/issue-2582.rs rename to src/tools/rustfmt/tests/source/issue-2582.rs diff --git a/tests/source/issue-2641.rs b/src/tools/rustfmt/tests/source/issue-2641.rs similarity index 100% rename from tests/source/issue-2641.rs rename to src/tools/rustfmt/tests/source/issue-2641.rs diff --git a/tests/source/issue-2644.rs b/src/tools/rustfmt/tests/source/issue-2644.rs similarity index 100% rename from tests/source/issue-2644.rs rename to src/tools/rustfmt/tests/source/issue-2644.rs diff --git a/tests/source/issue-2728.rs b/src/tools/rustfmt/tests/source/issue-2728.rs similarity index 100% rename from tests/source/issue-2728.rs rename to src/tools/rustfmt/tests/source/issue-2728.rs diff --git a/tests/source/issue-2761.rs b/src/tools/rustfmt/tests/source/issue-2761.rs similarity index 100% rename from tests/source/issue-2761.rs rename to src/tools/rustfmt/tests/source/issue-2761.rs diff --git a/tests/source/issue-2781.rs b/src/tools/rustfmt/tests/source/issue-2781.rs similarity index 100% rename from tests/source/issue-2781.rs rename to src/tools/rustfmt/tests/source/issue-2781.rs diff --git a/tests/source/issue-2794.rs b/src/tools/rustfmt/tests/source/issue-2794.rs similarity index 100% rename from tests/source/issue-2794.rs rename to src/tools/rustfmt/tests/source/issue-2794.rs diff --git a/tests/source/issue-2835.rs b/src/tools/rustfmt/tests/source/issue-2835.rs similarity index 100% rename from tests/source/issue-2835.rs rename to src/tools/rustfmt/tests/source/issue-2835.rs diff --git a/tests/source/issue-2863.rs b/src/tools/rustfmt/tests/source/issue-2863.rs similarity index 100% rename from tests/source/issue-2863.rs rename to src/tools/rustfmt/tests/source/issue-2863.rs diff --git a/tests/source/issue-2869.rs b/src/tools/rustfmt/tests/source/issue-2869.rs similarity index 100% rename from tests/source/issue-2869.rs rename to src/tools/rustfmt/tests/source/issue-2869.rs diff --git a/tests/source/issue-2896.rs b/src/tools/rustfmt/tests/source/issue-2896.rs similarity index 100% rename from tests/source/issue-2896.rs rename to src/tools/rustfmt/tests/source/issue-2896.rs diff --git a/tests/source/issue-2916.rs b/src/tools/rustfmt/tests/source/issue-2916.rs similarity index 100% rename from tests/source/issue-2916.rs rename to src/tools/rustfmt/tests/source/issue-2916.rs diff --git a/tests/source/issue-2917/packed_simd.rs b/src/tools/rustfmt/tests/source/issue-2917/packed_simd.rs similarity index 100% rename from tests/source/issue-2917/packed_simd.rs rename to src/tools/rustfmt/tests/source/issue-2917/packed_simd.rs diff --git a/tests/source/issue-2922.rs b/src/tools/rustfmt/tests/source/issue-2922.rs similarity index 100% rename from tests/source/issue-2922.rs rename to src/tools/rustfmt/tests/source/issue-2922.rs diff --git a/tests/source/issue-2927-2.rs b/src/tools/rustfmt/tests/source/issue-2927-2.rs similarity index 100% rename from tests/source/issue-2927-2.rs rename to src/tools/rustfmt/tests/source/issue-2927-2.rs diff --git a/tests/source/issue-2927.rs b/src/tools/rustfmt/tests/source/issue-2927.rs similarity index 100% rename from tests/source/issue-2927.rs rename to src/tools/rustfmt/tests/source/issue-2927.rs diff --git a/tests/source/issue-2930.rs b/src/tools/rustfmt/tests/source/issue-2930.rs similarity index 100% rename from tests/source/issue-2930.rs rename to src/tools/rustfmt/tests/source/issue-2930.rs diff --git a/tests/source/issue-2936.rs b/src/tools/rustfmt/tests/source/issue-2936.rs similarity index 100% rename from tests/source/issue-2936.rs rename to src/tools/rustfmt/tests/source/issue-2936.rs diff --git a/tests/source/issue-2955.rs b/src/tools/rustfmt/tests/source/issue-2955.rs similarity index 100% rename from tests/source/issue-2955.rs rename to src/tools/rustfmt/tests/source/issue-2955.rs diff --git a/tests/source/issue-2973.rs b/src/tools/rustfmt/tests/source/issue-2973.rs similarity index 100% rename from tests/source/issue-2973.rs rename to src/tools/rustfmt/tests/source/issue-2973.rs diff --git a/tests/source/issue-2977/impl.rs b/src/tools/rustfmt/tests/source/issue-2977/impl.rs similarity index 100% rename from tests/source/issue-2977/impl.rs rename to src/tools/rustfmt/tests/source/issue-2977/impl.rs diff --git a/tests/source/issue-2977/trait.rs b/src/tools/rustfmt/tests/source/issue-2977/trait.rs similarity index 100% rename from tests/source/issue-2977/trait.rs rename to src/tools/rustfmt/tests/source/issue-2977/trait.rs diff --git a/tests/source/issue-2985.rs b/src/tools/rustfmt/tests/source/issue-2985.rs similarity index 100% rename from tests/source/issue-2985.rs rename to src/tools/rustfmt/tests/source/issue-2985.rs diff --git a/tests/source/issue-2995.rs b/src/tools/rustfmt/tests/source/issue-2995.rs similarity index 100% rename from tests/source/issue-2995.rs rename to src/tools/rustfmt/tests/source/issue-2995.rs diff --git a/tests/source/issue-3029.rs b/src/tools/rustfmt/tests/source/issue-3029.rs similarity index 100% rename from tests/source/issue-3029.rs rename to src/tools/rustfmt/tests/source/issue-3029.rs diff --git a/tests/source/issue-3038.rs b/src/tools/rustfmt/tests/source/issue-3038.rs similarity index 100% rename from tests/source/issue-3038.rs rename to src/tools/rustfmt/tests/source/issue-3038.rs diff --git a/tests/source/issue-3049.rs b/src/tools/rustfmt/tests/source/issue-3049.rs similarity index 100% rename from tests/source/issue-3049.rs rename to src/tools/rustfmt/tests/source/issue-3049.rs diff --git a/tests/source/issue-3055/original.rs b/src/tools/rustfmt/tests/source/issue-3055/original.rs similarity index 100% rename from tests/source/issue-3055/original.rs rename to src/tools/rustfmt/tests/source/issue-3055/original.rs diff --git a/tests/source/issue-3059.rs b/src/tools/rustfmt/tests/source/issue-3059.rs similarity index 100% rename from tests/source/issue-3059.rs rename to src/tools/rustfmt/tests/source/issue-3059.rs diff --git a/tests/source/issue-3066.rs b/src/tools/rustfmt/tests/source/issue-3066.rs similarity index 100% rename from tests/source/issue-3066.rs rename to src/tools/rustfmt/tests/source/issue-3066.rs diff --git a/tests/source/issue-3131.rs b/src/tools/rustfmt/tests/source/issue-3131.rs similarity index 100% rename from tests/source/issue-3131.rs rename to src/tools/rustfmt/tests/source/issue-3131.rs diff --git a/tests/source/issue-3153.rs b/src/tools/rustfmt/tests/source/issue-3153.rs similarity index 100% rename from tests/source/issue-3153.rs rename to src/tools/rustfmt/tests/source/issue-3153.rs diff --git a/tests/source/issue-3158.rs b/src/tools/rustfmt/tests/source/issue-3158.rs similarity index 100% rename from tests/source/issue-3158.rs rename to src/tools/rustfmt/tests/source/issue-3158.rs diff --git a/tests/source/issue-3194.rs b/src/tools/rustfmt/tests/source/issue-3194.rs similarity index 100% rename from tests/source/issue-3194.rs rename to src/tools/rustfmt/tests/source/issue-3194.rs diff --git a/tests/source/issue-3198.rs b/src/tools/rustfmt/tests/source/issue-3198.rs similarity index 100% rename from tests/source/issue-3198.rs rename to src/tools/rustfmt/tests/source/issue-3198.rs diff --git a/tests/source/issue-3213/version_one.rs b/src/tools/rustfmt/tests/source/issue-3213/version_one.rs similarity index 100% rename from tests/source/issue-3213/version_one.rs rename to src/tools/rustfmt/tests/source/issue-3213/version_one.rs diff --git a/tests/source/issue-3213/version_two.rs b/src/tools/rustfmt/tests/source/issue-3213/version_two.rs similarity index 100% rename from tests/source/issue-3213/version_two.rs rename to src/tools/rustfmt/tests/source/issue-3213/version_two.rs diff --git a/tests/source/issue-3217.rs b/src/tools/rustfmt/tests/source/issue-3217.rs similarity index 100% rename from tests/source/issue-3217.rs rename to src/tools/rustfmt/tests/source/issue-3217.rs diff --git a/tests/source/issue-3227/two.rs b/src/tools/rustfmt/tests/source/issue-3227/two.rs similarity index 100% rename from tests/source/issue-3227/two.rs rename to src/tools/rustfmt/tests/source/issue-3227/two.rs diff --git a/tests/source/issue-3234.rs b/src/tools/rustfmt/tests/source/issue-3234.rs similarity index 100% rename from tests/source/issue-3234.rs rename to src/tools/rustfmt/tests/source/issue-3234.rs diff --git a/tests/source/issue-3241.rs b/src/tools/rustfmt/tests/source/issue-3241.rs similarity index 100% rename from tests/source/issue-3241.rs rename to src/tools/rustfmt/tests/source/issue-3241.rs diff --git a/tests/source/issue-3253/bar.rs b/src/tools/rustfmt/tests/source/issue-3253/bar.rs similarity index 100% rename from tests/source/issue-3253/bar.rs rename to src/tools/rustfmt/tests/source/issue-3253/bar.rs diff --git a/tests/source/issue-3253/foo.rs b/src/tools/rustfmt/tests/source/issue-3253/foo.rs similarity index 100% rename from tests/source/issue-3253/foo.rs rename to src/tools/rustfmt/tests/source/issue-3253/foo.rs diff --git a/tests/source/issue-3253/lib.rs b/src/tools/rustfmt/tests/source/issue-3253/lib.rs similarity index 100% rename from tests/source/issue-3253/lib.rs rename to src/tools/rustfmt/tests/source/issue-3253/lib.rs diff --git a/tests/source/issue-3253/paths/bar_foo.rs b/src/tools/rustfmt/tests/source/issue-3253/paths/bar_foo.rs similarity index 100% rename from tests/source/issue-3253/paths/bar_foo.rs rename to src/tools/rustfmt/tests/source/issue-3253/paths/bar_foo.rs diff --git a/tests/source/issue-3253/paths/excluded.rs b/src/tools/rustfmt/tests/source/issue-3253/paths/excluded.rs similarity index 100% rename from tests/source/issue-3253/paths/excluded.rs rename to src/tools/rustfmt/tests/source/issue-3253/paths/excluded.rs diff --git a/tests/source/issue-3253/paths/foo_bar.rs b/src/tools/rustfmt/tests/source/issue-3253/paths/foo_bar.rs similarity index 100% rename from tests/source/issue-3253/paths/foo_bar.rs rename to src/tools/rustfmt/tests/source/issue-3253/paths/foo_bar.rs diff --git a/tests/source/issue-3265.rs b/src/tools/rustfmt/tests/source/issue-3265.rs similarity index 100% rename from tests/source/issue-3265.rs rename to src/tools/rustfmt/tests/source/issue-3265.rs diff --git a/tests/source/issue-3270/one.rs b/src/tools/rustfmt/tests/source/issue-3270/one.rs similarity index 100% rename from tests/source/issue-3270/one.rs rename to src/tools/rustfmt/tests/source/issue-3270/one.rs diff --git a/tests/source/issue-3270/two.rs b/src/tools/rustfmt/tests/source/issue-3270/two.rs similarity index 100% rename from tests/source/issue-3270/two.rs rename to src/tools/rustfmt/tests/source/issue-3270/two.rs diff --git a/tests/source/issue-3272/v1.rs b/src/tools/rustfmt/tests/source/issue-3272/v1.rs similarity index 100% rename from tests/source/issue-3272/v1.rs rename to src/tools/rustfmt/tests/source/issue-3272/v1.rs diff --git a/tests/source/issue-3272/v2.rs b/src/tools/rustfmt/tests/source/issue-3272/v2.rs similarity index 100% rename from tests/source/issue-3272/v2.rs rename to src/tools/rustfmt/tests/source/issue-3272/v2.rs diff --git a/tests/source/issue-3278/version_one.rs b/src/tools/rustfmt/tests/source/issue-3278/version_one.rs similarity index 100% rename from tests/source/issue-3278/version_one.rs rename to src/tools/rustfmt/tests/source/issue-3278/version_one.rs diff --git a/tests/source/issue-3278/version_two.rs b/src/tools/rustfmt/tests/source/issue-3278/version_two.rs similarity index 100% rename from tests/source/issue-3278/version_two.rs rename to src/tools/rustfmt/tests/source/issue-3278/version_two.rs diff --git a/tests/source/issue-3295/two.rs b/src/tools/rustfmt/tests/source/issue-3295/two.rs similarity index 100% rename from tests/source/issue-3295/two.rs rename to src/tools/rustfmt/tests/source/issue-3295/two.rs diff --git a/tests/source/issue-3302.rs b/src/tools/rustfmt/tests/source/issue-3302.rs similarity index 100% rename from tests/source/issue-3302.rs rename to src/tools/rustfmt/tests/source/issue-3302.rs diff --git a/tests/source/issue-3343.rs b/src/tools/rustfmt/tests/source/issue-3343.rs similarity index 100% rename from tests/source/issue-3343.rs rename to src/tools/rustfmt/tests/source/issue-3343.rs diff --git a/tests/source/issue-3423.rs b/src/tools/rustfmt/tests/source/issue-3423.rs similarity index 100% rename from tests/source/issue-3423.rs rename to src/tools/rustfmt/tests/source/issue-3423.rs diff --git a/tests/source/issue-3434/lib.rs b/src/tools/rustfmt/tests/source/issue-3434/lib.rs similarity index 100% rename from tests/source/issue-3434/lib.rs rename to src/tools/rustfmt/tests/source/issue-3434/lib.rs diff --git a/tests/source/issue-3434/no_entry.rs b/src/tools/rustfmt/tests/source/issue-3434/no_entry.rs similarity index 100% rename from tests/source/issue-3434/no_entry.rs rename to src/tools/rustfmt/tests/source/issue-3434/no_entry.rs diff --git a/tests/source/issue-3434/not_skip_macro.rs b/src/tools/rustfmt/tests/source/issue-3434/not_skip_macro.rs similarity index 100% rename from tests/source/issue-3434/not_skip_macro.rs rename to src/tools/rustfmt/tests/source/issue-3434/not_skip_macro.rs diff --git a/tests/source/issue-3465.rs b/src/tools/rustfmt/tests/source/issue-3465.rs similarity index 100% rename from tests/source/issue-3465.rs rename to src/tools/rustfmt/tests/source/issue-3465.rs diff --git a/tests/source/issue-3494/crlf.rs b/src/tools/rustfmt/tests/source/issue-3494/crlf.rs similarity index 100% rename from tests/source/issue-3494/crlf.rs rename to src/tools/rustfmt/tests/source/issue-3494/crlf.rs diff --git a/tests/source/issue-3494/lf.rs b/src/tools/rustfmt/tests/source/issue-3494/lf.rs similarity index 100% rename from tests/source/issue-3494/lf.rs rename to src/tools/rustfmt/tests/source/issue-3494/lf.rs diff --git a/tests/source/issue-3508.rs b/src/tools/rustfmt/tests/source/issue-3508.rs similarity index 100% rename from tests/source/issue-3508.rs rename to src/tools/rustfmt/tests/source/issue-3508.rs diff --git a/tests/source/issue-3515.rs b/src/tools/rustfmt/tests/source/issue-3515.rs similarity index 100% rename from tests/source/issue-3515.rs rename to src/tools/rustfmt/tests/source/issue-3515.rs diff --git a/tests/source/issue-3532.rs b/src/tools/rustfmt/tests/source/issue-3532.rs similarity index 100% rename from tests/source/issue-3532.rs rename to src/tools/rustfmt/tests/source/issue-3532.rs diff --git a/tests/source/issue-3585/extern_crate.rs b/src/tools/rustfmt/tests/source/issue-3585/extern_crate.rs similarity index 100% rename from tests/source/issue-3585/extern_crate.rs rename to src/tools/rustfmt/tests/source/issue-3585/extern_crate.rs diff --git a/tests/source/issue-3585/reorder_imports_disabled.rs b/src/tools/rustfmt/tests/source/issue-3585/reorder_imports_disabled.rs similarity index 100% rename from tests/source/issue-3585/reorder_imports_disabled.rs rename to src/tools/rustfmt/tests/source/issue-3585/reorder_imports_disabled.rs diff --git a/tests/source/issue-3585/reorder_imports_enabled.rs b/src/tools/rustfmt/tests/source/issue-3585/reorder_imports_enabled.rs similarity index 100% rename from tests/source/issue-3585/reorder_imports_enabled.rs rename to src/tools/rustfmt/tests/source/issue-3585/reorder_imports_enabled.rs diff --git a/tests/source/issue-3585/use.rs b/src/tools/rustfmt/tests/source/issue-3585/use.rs similarity index 100% rename from tests/source/issue-3585/use.rs rename to src/tools/rustfmt/tests/source/issue-3585/use.rs diff --git a/tests/source/issue-3636.rs b/src/tools/rustfmt/tests/source/issue-3636.rs similarity index 100% rename from tests/source/issue-3636.rs rename to src/tools/rustfmt/tests/source/issue-3636.rs diff --git a/tests/source/issue-3639.rs b/src/tools/rustfmt/tests/source/issue-3639.rs similarity index 100% rename from tests/source/issue-3639.rs rename to src/tools/rustfmt/tests/source/issue-3639.rs diff --git a/tests/source/issue-3651.rs b/src/tools/rustfmt/tests/source/issue-3651.rs similarity index 100% rename from tests/source/issue-3651.rs rename to src/tools/rustfmt/tests/source/issue-3651.rs diff --git a/tests/source/issue-3665/lib.rs b/src/tools/rustfmt/tests/source/issue-3665/lib.rs similarity index 100% rename from tests/source/issue-3665/lib.rs rename to src/tools/rustfmt/tests/source/issue-3665/lib.rs diff --git a/tests/source/issue-3665/not_skip_attribute.rs b/src/tools/rustfmt/tests/source/issue-3665/not_skip_attribute.rs similarity index 100% rename from tests/source/issue-3665/not_skip_attribute.rs rename to src/tools/rustfmt/tests/source/issue-3665/not_skip_attribute.rs diff --git a/tests/source/issue-3665/sub_mod.rs b/src/tools/rustfmt/tests/source/issue-3665/sub_mod.rs similarity index 100% rename from tests/source/issue-3665/sub_mod.rs rename to src/tools/rustfmt/tests/source/issue-3665/sub_mod.rs diff --git a/tests/source/issue-3672.rs b/src/tools/rustfmt/tests/source/issue-3672.rs similarity index 100% rename from tests/source/issue-3672.rs rename to src/tools/rustfmt/tests/source/issue-3672.rs diff --git a/tests/source/issue-3675.rs b/src/tools/rustfmt/tests/source/issue-3675.rs similarity index 100% rename from tests/source/issue-3675.rs rename to src/tools/rustfmt/tests/source/issue-3675.rs diff --git a/tests/source/issue-3701/one.rs b/src/tools/rustfmt/tests/source/issue-3701/one.rs similarity index 100% rename from tests/source/issue-3701/one.rs rename to src/tools/rustfmt/tests/source/issue-3701/one.rs diff --git a/tests/source/issue-3701/two.rs b/src/tools/rustfmt/tests/source/issue-3701/two.rs similarity index 100% rename from tests/source/issue-3701/two.rs rename to src/tools/rustfmt/tests/source/issue-3701/two.rs diff --git a/tests/source/issue-3709.rs b/src/tools/rustfmt/tests/source/issue-3709.rs similarity index 100% rename from tests/source/issue-3709.rs rename to src/tools/rustfmt/tests/source/issue-3709.rs diff --git a/tests/source/issue-3740.rs b/src/tools/rustfmt/tests/source/issue-3740.rs similarity index 100% rename from tests/source/issue-3740.rs rename to src/tools/rustfmt/tests/source/issue-3740.rs diff --git a/tests/source/issue-3750.rs b/src/tools/rustfmt/tests/source/issue-3750.rs similarity index 100% rename from tests/source/issue-3750.rs rename to src/tools/rustfmt/tests/source/issue-3750.rs diff --git a/tests/source/issue-3751.rs b/src/tools/rustfmt/tests/source/issue-3751.rs similarity index 100% rename from tests/source/issue-3751.rs rename to src/tools/rustfmt/tests/source/issue-3751.rs diff --git a/tests/source/issue-3779/ice.rs b/src/tools/rustfmt/tests/source/issue-3779/ice.rs similarity index 100% rename from tests/source/issue-3779/ice.rs rename to src/tools/rustfmt/tests/source/issue-3779/ice.rs diff --git a/tests/source/issue-3779/lib.rs b/src/tools/rustfmt/tests/source/issue-3779/lib.rs similarity index 100% rename from tests/source/issue-3779/lib.rs rename to src/tools/rustfmt/tests/source/issue-3779/lib.rs diff --git a/tests/source/issue-3786.rs b/src/tools/rustfmt/tests/source/issue-3786.rs similarity index 100% rename from tests/source/issue-3786.rs rename to src/tools/rustfmt/tests/source/issue-3786.rs diff --git a/tests/source/issue-3787.rs b/src/tools/rustfmt/tests/source/issue-3787.rs similarity index 100% rename from tests/source/issue-3787.rs rename to src/tools/rustfmt/tests/source/issue-3787.rs diff --git a/tests/source/issue-3805.rs b/src/tools/rustfmt/tests/source/issue-3805.rs similarity index 100% rename from tests/source/issue-3805.rs rename to src/tools/rustfmt/tests/source/issue-3805.rs diff --git a/tests/source/issue-3840/version-one_hard-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-one_hard-tabs.rs similarity index 100% rename from tests/source/issue-3840/version-one_hard-tabs.rs rename to src/tools/rustfmt/tests/source/issue-3840/version-one_hard-tabs.rs diff --git a/tests/source/issue-3840/version-one_soft-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-one_soft-tabs.rs similarity index 100% rename from tests/source/issue-3840/version-one_soft-tabs.rs rename to src/tools/rustfmt/tests/source/issue-3840/version-one_soft-tabs.rs diff --git a/tests/source/issue-3840/version-two_hard-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs similarity index 100% rename from tests/source/issue-3840/version-two_hard-tabs.rs rename to src/tools/rustfmt/tests/source/issue-3840/version-two_hard-tabs.rs diff --git a/tests/source/issue-3840/version-two_soft-tabs.rs b/src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs similarity index 100% rename from tests/source/issue-3840/version-two_soft-tabs.rs rename to src/tools/rustfmt/tests/source/issue-3840/version-two_soft-tabs.rs diff --git a/tests/source/issue-3984.rs b/src/tools/rustfmt/tests/source/issue-3984.rs similarity index 100% rename from tests/source/issue-3984.rs rename to src/tools/rustfmt/tests/source/issue-3984.rs diff --git a/tests/source/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs similarity index 100% rename from tests/source/issue-3987/format_macro_bodies_true.rs rename to src/tools/rustfmt/tests/source/issue-3987/format_macro_bodies_true.rs diff --git a/tests/source/issue-4018.rs b/src/tools/rustfmt/tests/source/issue-4018.rs similarity index 100% rename from tests/source/issue-4018.rs rename to src/tools/rustfmt/tests/source/issue-4018.rs diff --git a/tests/source/issue-4036/one.rs b/src/tools/rustfmt/tests/source/issue-4036/one.rs similarity index 100% rename from tests/source/issue-4036/one.rs rename to src/tools/rustfmt/tests/source/issue-4036/one.rs diff --git a/tests/source/issue-4036/three.rs b/src/tools/rustfmt/tests/source/issue-4036/three.rs similarity index 100% rename from tests/source/issue-4036/three.rs rename to src/tools/rustfmt/tests/source/issue-4036/three.rs diff --git a/tests/source/issue-4036/two.rs b/src/tools/rustfmt/tests/source/issue-4036/two.rs similarity index 100% rename from tests/source/issue-4036/two.rs rename to src/tools/rustfmt/tests/source/issue-4036/two.rs diff --git a/tests/source/issue-4041.rs b/src/tools/rustfmt/tests/source/issue-4041.rs similarity index 100% rename from tests/source/issue-4041.rs rename to src/tools/rustfmt/tests/source/issue-4041.rs diff --git a/tests/source/issue-4079.rs b/src/tools/rustfmt/tests/source/issue-4079.rs similarity index 100% rename from tests/source/issue-4079.rs rename to src/tools/rustfmt/tests/source/issue-4079.rs diff --git a/tests/source/issue-4120.rs b/src/tools/rustfmt/tests/source/issue-4120.rs similarity index 100% rename from tests/source/issue-4120.rs rename to src/tools/rustfmt/tests/source/issue-4120.rs diff --git a/tests/source/issue-4243.rs b/src/tools/rustfmt/tests/source/issue-4243.rs similarity index 100% rename from tests/source/issue-4243.rs rename to src/tools/rustfmt/tests/source/issue-4243.rs diff --git a/tests/source/issue-4244.rs b/src/tools/rustfmt/tests/source/issue-4244.rs similarity index 100% rename from tests/source/issue-4244.rs rename to src/tools/rustfmt/tests/source/issue-4244.rs diff --git a/tests/source/issue-4245.rs b/src/tools/rustfmt/tests/source/issue-4245.rs similarity index 100% rename from tests/source/issue-4245.rs rename to src/tools/rustfmt/tests/source/issue-4245.rs diff --git a/tests/source/issue-4312.rs b/src/tools/rustfmt/tests/source/issue-4312.rs similarity index 100% rename from tests/source/issue-4312.rs rename to src/tools/rustfmt/tests/source/issue-4312.rs diff --git a/tests/source/issue-4381/style_edition_2015.rs b/src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs similarity index 100% rename from tests/source/issue-4381/style_edition_2015.rs rename to src/tools/rustfmt/tests/source/issue-4381/style_edition_2015.rs diff --git a/tests/source/issue-4382.rs b/src/tools/rustfmt/tests/source/issue-4382.rs similarity index 100% rename from tests/source/issue-4382.rs rename to src/tools/rustfmt/tests/source/issue-4382.rs diff --git a/tests/source/issue-4398.rs b/src/tools/rustfmt/tests/source/issue-4398.rs similarity index 100% rename from tests/source/issue-4398.rs rename to src/tools/rustfmt/tests/source/issue-4398.rs diff --git a/tests/source/issue-4427.rs b/src/tools/rustfmt/tests/source/issue-4427.rs similarity index 100% rename from tests/source/issue-4427.rs rename to src/tools/rustfmt/tests/source/issue-4427.rs diff --git a/tests/source/issue-447.rs b/src/tools/rustfmt/tests/source/issue-447.rs similarity index 100% rename from tests/source/issue-447.rs rename to src/tools/rustfmt/tests/source/issue-447.rs diff --git a/tests/source/issue-4530.rs b/src/tools/rustfmt/tests/source/issue-4530.rs similarity index 100% rename from tests/source/issue-4530.rs rename to src/tools/rustfmt/tests/source/issue-4530.rs diff --git a/tests/source/issue-4577.rs b/src/tools/rustfmt/tests/source/issue-4577.rs similarity index 100% rename from tests/source/issue-4577.rs rename to src/tools/rustfmt/tests/source/issue-4577.rs diff --git a/tests/source/issue-4603.rs b/src/tools/rustfmt/tests/source/issue-4603.rs similarity index 100% rename from tests/source/issue-4603.rs rename to src/tools/rustfmt/tests/source/issue-4603.rs diff --git a/tests/source/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs similarity index 100% rename from tests/source/issue-4615/minimum_example.rs rename to src/tools/rustfmt/tests/source/issue-4615/minimum_example.rs diff --git a/tests/source/issue-4643.rs b/src/tools/rustfmt/tests/source/issue-4643.rs similarity index 100% rename from tests/source/issue-4643.rs rename to src/tools/rustfmt/tests/source/issue-4643.rs diff --git a/tests/source/issue-4646.rs b/src/tools/rustfmt/tests/source/issue-4646.rs similarity index 100% rename from tests/source/issue-4646.rs rename to src/tools/rustfmt/tests/source/issue-4646.rs diff --git a/tests/source/issue-4656/format_me_please.rs b/src/tools/rustfmt/tests/source/issue-4656/format_me_please.rs similarity index 100% rename from tests/source/issue-4656/format_me_please.rs rename to src/tools/rustfmt/tests/source/issue-4656/format_me_please.rs diff --git a/tests/source/issue-4656/lib.rs b/src/tools/rustfmt/tests/source/issue-4656/lib.rs similarity index 100% rename from tests/source/issue-4656/lib.rs rename to src/tools/rustfmt/tests/source/issue-4656/lib.rs diff --git a/tests/source/issue-4656/lib2.rs b/src/tools/rustfmt/tests/source/issue-4656/lib2.rs similarity index 100% rename from tests/source/issue-4656/lib2.rs rename to src/tools/rustfmt/tests/source/issue-4656/lib2.rs diff --git a/tests/source/issue-4689/one.rs b/src/tools/rustfmt/tests/source/issue-4689/one.rs similarity index 100% rename from tests/source/issue-4689/one.rs rename to src/tools/rustfmt/tests/source/issue-4689/one.rs diff --git a/tests/source/issue-4689/two.rs b/src/tools/rustfmt/tests/source/issue-4689/two.rs similarity index 100% rename from tests/source/issue-4689/two.rs rename to src/tools/rustfmt/tests/source/issue-4689/two.rs diff --git a/tests/source/issue-4791/buggy.rs b/src/tools/rustfmt/tests/source/issue-4791/buggy.rs similarity index 100% rename from tests/source/issue-4791/buggy.rs rename to src/tools/rustfmt/tests/source/issue-4791/buggy.rs diff --git a/tests/source/issue-4791/trailing_comma.rs b/src/tools/rustfmt/tests/source/issue-4791/trailing_comma.rs similarity index 100% rename from tests/source/issue-4791/trailing_comma.rs rename to src/tools/rustfmt/tests/source/issue-4791/trailing_comma.rs diff --git a/tests/source/issue-4808.rs b/src/tools/rustfmt/tests/source/issue-4808.rs similarity index 100% rename from tests/source/issue-4808.rs rename to src/tools/rustfmt/tests/source/issue-4808.rs diff --git a/tests/source/issue-4816/lib.rs b/src/tools/rustfmt/tests/source/issue-4816/lib.rs similarity index 100% rename from tests/source/issue-4816/lib.rs rename to src/tools/rustfmt/tests/source/issue-4816/lib.rs diff --git a/tests/source/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs similarity index 100% rename from tests/source/issue-4926/deeply_nested_struct.rs rename to src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct.rs diff --git a/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs similarity index 100% rename from tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs rename to src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_long_field_names.rs diff --git a/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs similarity index 100% rename from tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs rename to src/tools/rustfmt/tests/source/issue-4926/deeply_nested_struct_with_many_fields.rs diff --git a/tests/source/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs similarity index 100% rename from tests/source/issue-4926/enum_struct_field.rs rename to src/tools/rustfmt/tests/source/issue-4926/enum_struct_field.rs diff --git a/tests/source/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs similarity index 100% rename from tests/source/issue-4926/minimum_example.rs rename to src/tools/rustfmt/tests/source/issue-4926/minimum_example.rs diff --git a/tests/source/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs similarity index 100% rename from tests/source/issue-4926/struct_with_long_field_names.rs rename to src/tools/rustfmt/tests/source/issue-4926/struct_with_long_field_names.rs diff --git a/tests/source/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs similarity index 100% rename from tests/source/issue-4926/struct_with_many_fields.rs rename to src/tools/rustfmt/tests/source/issue-4926/struct_with_many_fields.rs diff --git a/tests/source/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs similarity index 100% rename from tests/source/issue-4984/minimum_example.rs rename to src/tools/rustfmt/tests/source/issue-4984/minimum_example.rs diff --git a/tests/source/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs similarity index 100% rename from tests/source/issue-4984/multi_line_derive.rs rename to src/tools/rustfmt/tests/source/issue-4984/multi_line_derive.rs diff --git a/tests/source/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs similarity index 100% rename from tests/source/issue-4984/multiple_comments_within.rs rename to src/tools/rustfmt/tests/source/issue-4984/multiple_comments_within.rs diff --git a/tests/source/issue-5011.rs b/src/tools/rustfmt/tests/source/issue-5011.rs similarity index 100% rename from tests/source/issue-5011.rs rename to src/tools/rustfmt/tests/source/issue-5011.rs diff --git a/tests/source/issue-5023.rs b/src/tools/rustfmt/tests/source/issue-5023.rs similarity index 100% rename from tests/source/issue-5023.rs rename to src/tools/rustfmt/tests/source/issue-5023.rs diff --git a/tests/source/issue-5030.rs b/src/tools/rustfmt/tests/source/issue-5030.rs similarity index 100% rename from tests/source/issue-5030.rs rename to src/tools/rustfmt/tests/source/issue-5030.rs diff --git a/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs b/src/tools/rustfmt/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs similarity index 100% rename from tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs rename to src/tools/rustfmt/tests/source/issue-5042/multi-line_comment_with_trailing_comma.rs diff --git a/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs b/src/tools/rustfmt/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs similarity index 100% rename from tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs rename to src/tools/rustfmt/tests/source/issue-5042/multi-line_comment_without_trailing_comma.rs diff --git a/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs b/src/tools/rustfmt/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs similarity index 100% rename from tests/source/issue-5042/single-line_comment_with_trailing_comma.rs rename to src/tools/rustfmt/tests/source/issue-5042/single-line_comment_with_trailing_comma.rs diff --git a/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs b/src/tools/rustfmt/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs similarity index 100% rename from tests/source/issue-5042/single-line_comment_without_trailing_comma.rs rename to src/tools/rustfmt/tests/source/issue-5042/single-line_comment_without_trailing_comma.rs diff --git a/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs similarity index 100% rename from tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs rename to src/tools/rustfmt/tests/source/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs diff --git a/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs similarity index 100% rename from tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs rename to src/tools/rustfmt/tests/source/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs diff --git a/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs similarity index 100% rename from tests/source/issue-5088/very_long_comment_wrap_comments_true.rs rename to src/tools/rustfmt/tests/source/issue-5088/very_long_comment_wrap_comments_true.rs diff --git a/tests/source/issue-510.rs b/src/tools/rustfmt/tests/source/issue-510.rs similarity index 100% rename from tests/source/issue-510.rs rename to src/tools/rustfmt/tests/source/issue-510.rs diff --git a/tests/source/issue-5136-1.rs b/src/tools/rustfmt/tests/source/issue-5136-1.rs similarity index 100% rename from tests/source/issue-5136-1.rs rename to src/tools/rustfmt/tests/source/issue-5136-1.rs diff --git a/tests/source/issue-5136-2.rs b/src/tools/rustfmt/tests/source/issue-5136-2.rs similarity index 100% rename from tests/source/issue-5136-2.rs rename to src/tools/rustfmt/tests/source/issue-5136-2.rs diff --git a/tests/source/issue-5136-3.rs b/src/tools/rustfmt/tests/source/issue-5136-3.rs similarity index 100% rename from tests/source/issue-5136-3.rs rename to src/tools/rustfmt/tests/source/issue-5136-3.rs diff --git a/tests/source/issue-5136-4.rs b/src/tools/rustfmt/tests/source/issue-5136-4.rs similarity index 100% rename from tests/source/issue-5136-4.rs rename to src/tools/rustfmt/tests/source/issue-5136-4.rs diff --git a/tests/source/issue-5136-5.rs b/src/tools/rustfmt/tests/source/issue-5136-5.rs similarity index 100% rename from tests/source/issue-5136-5.rs rename to src/tools/rustfmt/tests/source/issue-5136-5.rs diff --git a/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs similarity index 100% rename from tests/source/issue-5157/indented_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/source/issue-5157/indented_itemized_markdown_blockquote.rs diff --git a/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs similarity index 100% rename from tests/source/issue-5157/nested_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/source/issue-5157/nested_itemized_markdown_blockquote.rs diff --git a/tests/source/issue-5157/support_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/source/issue-5157/support_itemized_markdown_blockquote.rs similarity index 100% rename from tests/source/issue-5157/support_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/source/issue-5157/support_itemized_markdown_blockquote.rs diff --git a/tests/source/issue-5234.rs b/src/tools/rustfmt/tests/source/issue-5234.rs similarity index 100% rename from tests/source/issue-5234.rs rename to src/tools/rustfmt/tests/source/issue-5234.rs diff --git a/tests/source/issue-5238/markdown_header_wrap_comments_false.rs b/src/tools/rustfmt/tests/source/issue-5238/markdown_header_wrap_comments_false.rs similarity index 100% rename from tests/source/issue-5238/markdown_header_wrap_comments_false.rs rename to src/tools/rustfmt/tests/source/issue-5238/markdown_header_wrap_comments_false.rs diff --git a/tests/source/issue-5238/markdown_header_wrap_comments_true.rs b/src/tools/rustfmt/tests/source/issue-5238/markdown_header_wrap_comments_true.rs similarity index 100% rename from tests/source/issue-5238/markdown_header_wrap_comments_true.rs rename to src/tools/rustfmt/tests/source/issue-5238/markdown_header_wrap_comments_true.rs diff --git a/tests/source/issue-5260.rs b/src/tools/rustfmt/tests/source/issue-5260.rs similarity index 100% rename from tests/source/issue-5260.rs rename to src/tools/rustfmt/tests/source/issue-5260.rs diff --git a/tests/source/issue-5270/merge_derives_true.rs b/src/tools/rustfmt/tests/source/issue-5270/merge_derives_true.rs similarity index 100% rename from tests/source/issue-5270/merge_derives_true.rs rename to src/tools/rustfmt/tests/source/issue-5270/merge_derives_true.rs diff --git a/tests/source/issue-539.rs b/src/tools/rustfmt/tests/source/issue-539.rs similarity index 100% rename from tests/source/issue-539.rs rename to src/tools/rustfmt/tests/source/issue-539.rs diff --git a/tests/source/issue-5488.rs b/src/tools/rustfmt/tests/source/issue-5488.rs similarity index 100% rename from tests/source/issue-5488.rs rename to src/tools/rustfmt/tests/source/issue-5488.rs diff --git a/tests/source/issue-5586.rs b/src/tools/rustfmt/tests/source/issue-5586.rs similarity index 100% rename from tests/source/issue-5586.rs rename to src/tools/rustfmt/tests/source/issue-5586.rs diff --git a/tests/source/issue-5655/one.rs b/src/tools/rustfmt/tests/source/issue-5655/one.rs similarity index 100% rename from tests/source/issue-5655/one.rs rename to src/tools/rustfmt/tests/source/issue-5655/one.rs diff --git a/tests/source/issue-5655/two.rs b/src/tools/rustfmt/tests/source/issue-5655/two.rs similarity index 100% rename from tests/source/issue-5655/two.rs rename to src/tools/rustfmt/tests/source/issue-5655/two.rs diff --git a/tests/source/issue-5791.rs b/src/tools/rustfmt/tests/source/issue-5791.rs similarity index 100% rename from tests/source/issue-5791.rs rename to src/tools/rustfmt/tests/source/issue-5791.rs diff --git a/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs similarity index 100% rename from tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs rename to src/tools/rustfmt/tests/source/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs diff --git a/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs similarity index 100% rename from tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs rename to src/tools/rustfmt/tests/source/issue-5801/comment_unexpectedly_wraps_before_max_width.rs diff --git a/tests/source/issue-5835.rs b/src/tools/rustfmt/tests/source/issue-5835.rs similarity index 100% rename from tests/source/issue-5835.rs rename to src/tools/rustfmt/tests/source/issue-5835.rs diff --git a/tests/source/issue-5852/default.rs b/src/tools/rustfmt/tests/source/issue-5852/default.rs similarity index 100% rename from tests/source/issue-5852/default.rs rename to src/tools/rustfmt/tests/source/issue-5852/default.rs diff --git a/tests/source/issue-5852/horizontal.rs b/src/tools/rustfmt/tests/source/issue-5852/horizontal.rs similarity index 100% rename from tests/source/issue-5852/horizontal.rs rename to src/tools/rustfmt/tests/source/issue-5852/horizontal.rs diff --git a/tests/source/issue-5852/horizontal_vertical.rs b/src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs similarity index 100% rename from tests/source/issue-5852/horizontal_vertical.rs rename to src/tools/rustfmt/tests/source/issue-5852/horizontal_vertical.rs diff --git a/tests/source/issue-5852/issue_example.rs b/src/tools/rustfmt/tests/source/issue-5852/issue_example.rs similarity index 100% rename from tests/source/issue-5852/issue_example.rs rename to src/tools/rustfmt/tests/source/issue-5852/issue_example.rs diff --git a/tests/source/issue-5852/split.rs b/src/tools/rustfmt/tests/source/issue-5852/split.rs similarity index 100% rename from tests/source/issue-5852/split.rs rename to src/tools/rustfmt/tests/source/issue-5852/split.rs diff --git a/tests/source/issue-5852/vertical.rs b/src/tools/rustfmt/tests/source/issue-5852/vertical.rs similarity index 100% rename from tests/source/issue-5852/vertical.rs rename to src/tools/rustfmt/tests/source/issue-5852/vertical.rs diff --git a/tests/source/issue-5935.rs b/src/tools/rustfmt/tests/source/issue-5935.rs similarity index 100% rename from tests/source/issue-5935.rs rename to src/tools/rustfmt/tests/source/issue-5935.rs diff --git a/tests/source/issue-5987/two.rs b/src/tools/rustfmt/tests/source/issue-5987/two.rs similarity index 100% rename from tests/source/issue-5987/two.rs rename to src/tools/rustfmt/tests/source/issue-5987/two.rs diff --git a/tests/source/issue-6059/repro.rs b/src/tools/rustfmt/tests/source/issue-6059/repro.rs similarity index 100% rename from tests/source/issue-6059/repro.rs rename to src/tools/rustfmt/tests/source/issue-6059/repro.rs diff --git a/tests/source/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs similarity index 100% rename from tests/source/issue-6147/case_rustfmt_v1.rs rename to src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v1.rs diff --git a/tests/source/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs similarity index 100% rename from tests/source/issue-6147/case_rustfmt_v2.rs rename to src/tools/rustfmt/tests/source/issue-6147/case_rustfmt_v2.rs diff --git a/tests/source/issue-6202/long_pat.rs b/src/tools/rustfmt/tests/source/issue-6202/long_pat.rs similarity index 100% rename from tests/source/issue-6202/long_pat.rs rename to src/tools/rustfmt/tests/source/issue-6202/long_pat.rs diff --git a/tests/source/issue-6243.rs b/src/tools/rustfmt/tests/source/issue-6243.rs similarity index 100% rename from tests/source/issue-6243.rs rename to src/tools/rustfmt/tests/source/issue-6243.rs diff --git a/tests/source/issue-6333.rs b/src/tools/rustfmt/tests/source/issue-6333.rs similarity index 100% rename from tests/source/issue-6333.rs rename to src/tools/rustfmt/tests/source/issue-6333.rs diff --git a/tests/source/issue-6561/trait-fn.rs b/src/tools/rustfmt/tests/source/issue-6561/trait-fn.rs similarity index 100% rename from tests/source/issue-6561/trait-fn.rs rename to src/tools/rustfmt/tests/source/issue-6561/trait-fn.rs diff --git a/tests/source/issue-6561/variadic.rs b/src/tools/rustfmt/tests/source/issue-6561/variadic.rs similarity index 100% rename from tests/source/issue-6561/variadic.rs rename to src/tools/rustfmt/tests/source/issue-6561/variadic.rs diff --git a/tests/source/issue-6607/fn-type.rs b/src/tools/rustfmt/tests/source/issue-6607/fn-type.rs similarity index 100% rename from tests/source/issue-6607/fn-type.rs rename to src/tools/rustfmt/tests/source/issue-6607/fn-type.rs diff --git a/tests/source/issue-6651/custom_width.rs b/src/tools/rustfmt/tests/source/issue-6651/custom_width.rs similarity index 100% rename from tests/source/issue-6651/custom_width.rs rename to src/tools/rustfmt/tests/source/issue-6651/custom_width.rs diff --git a/tests/source/issue-6651/default.rs b/src/tools/rustfmt/tests/source/issue-6651/default.rs similarity index 100% rename from tests/source/issue-6651/default.rs rename to src/tools/rustfmt/tests/source/issue-6651/default.rs diff --git a/tests/source/issue-6788.rs b/src/tools/rustfmt/tests/source/issue-6788.rs similarity index 100% rename from tests/source/issue-6788.rs rename to src/tools/rustfmt/tests/source/issue-6788.rs diff --git a/tests/source/issue-6795.rs b/src/tools/rustfmt/tests/source/issue-6795.rs similarity index 100% rename from tests/source/issue-6795.rs rename to src/tools/rustfmt/tests/source/issue-6795.rs diff --git a/tests/source/issue-6825.rs b/src/tools/rustfmt/tests/source/issue-6825.rs similarity index 100% rename from tests/source/issue-6825.rs rename to src/tools/rustfmt/tests/source/issue-6825.rs diff --git a/tests/source/issue-683.rs b/src/tools/rustfmt/tests/source/issue-683.rs similarity index 100% rename from tests/source/issue-683.rs rename to src/tools/rustfmt/tests/source/issue-683.rs diff --git a/tests/source/issue-6863/empty-stmt.rs b/src/tools/rustfmt/tests/source/issue-6863/empty-stmt.rs similarity index 100% rename from tests/source/issue-6863/empty-stmt.rs rename to src/tools/rustfmt/tests/source/issue-6863/empty-stmt.rs diff --git a/tests/source/issue-6863/fn-stmts.rs b/src/tools/rustfmt/tests/source/issue-6863/fn-stmts.rs similarity index 100% rename from tests/source/issue-6863/fn-stmts.rs rename to src/tools/rustfmt/tests/source/issue-6863/fn-stmts.rs diff --git a/tests/source/issue-6985.rs b/src/tools/rustfmt/tests/source/issue-6985.rs similarity index 100% rename from tests/source/issue-6985.rs rename to src/tools/rustfmt/tests/source/issue-6985.rs diff --git a/tests/source/issue-7011.rs b/src/tools/rustfmt/tests/source/issue-7011.rs similarity index 100% rename from tests/source/issue-7011.rs rename to src/tools/rustfmt/tests/source/issue-7011.rs diff --git a/tests/source/issue-7054.rs b/src/tools/rustfmt/tests/source/issue-7054.rs similarity index 100% rename from tests/source/issue-7054.rs rename to src/tools/rustfmt/tests/source/issue-7054.rs diff --git a/tests/source/issue-7056.rs b/src/tools/rustfmt/tests/source/issue-7056.rs similarity index 100% rename from tests/source/issue-7056.rs rename to src/tools/rustfmt/tests/source/issue-7056.rs diff --git a/tests/source/issue-811.rs b/src/tools/rustfmt/tests/source/issue-811.rs similarity index 100% rename from tests/source/issue-811.rs rename to src/tools/rustfmt/tests/source/issue-811.rs diff --git a/tests/source/issue-850.rs b/src/tools/rustfmt/tests/source/issue-850.rs similarity index 100% rename from tests/source/issue-850.rs rename to src/tools/rustfmt/tests/source/issue-850.rs diff --git a/tests/source/issue-855.rs b/src/tools/rustfmt/tests/source/issue-855.rs similarity index 100% rename from tests/source/issue-855.rs rename to src/tools/rustfmt/tests/source/issue-855.rs diff --git a/tests/source/issue-913.rs b/src/tools/rustfmt/tests/source/issue-913.rs similarity index 100% rename from tests/source/issue-913.rs rename to src/tools/rustfmt/tests/source/issue-913.rs diff --git a/tests/source/issue-945.rs b/src/tools/rustfmt/tests/source/issue-945.rs similarity index 100% rename from tests/source/issue-945.rs rename to src/tools/rustfmt/tests/source/issue-945.rs diff --git a/tests/source/issue-977.rs b/src/tools/rustfmt/tests/source/issue-977.rs similarity index 100% rename from tests/source/issue-977.rs rename to src/tools/rustfmt/tests/source/issue-977.rs diff --git a/tests/source/issue_1306.rs b/src/tools/rustfmt/tests/source/issue_1306.rs similarity index 100% rename from tests/source/issue_1306.rs rename to src/tools/rustfmt/tests/source/issue_1306.rs diff --git a/tests/source/issue_3245.rs b/src/tools/rustfmt/tests/source/issue_3245.rs similarity index 100% rename from tests/source/issue_3245.rs rename to src/tools/rustfmt/tests/source/issue_3245.rs diff --git a/tests/source/issue_3561.rs b/src/tools/rustfmt/tests/source/issue_3561.rs similarity index 100% rename from tests/source/issue_3561.rs rename to src/tools/rustfmt/tests/source/issue_3561.rs diff --git a/tests/source/issue_3839.rs b/src/tools/rustfmt/tests/source/issue_3839.rs similarity index 100% rename from tests/source/issue_3839.rs rename to src/tools/rustfmt/tests/source/issue_3839.rs diff --git a/tests/source/issue_3844.rs b/src/tools/rustfmt/tests/source/issue_3844.rs similarity index 100% rename from tests/source/issue_3844.rs rename to src/tools/rustfmt/tests/source/issue_3844.rs diff --git a/tests/source/issue_3853.rs b/src/tools/rustfmt/tests/source/issue_3853.rs similarity index 100% rename from tests/source/issue_3853.rs rename to src/tools/rustfmt/tests/source/issue_3853.rs diff --git a/tests/source/issue_3868.rs b/src/tools/rustfmt/tests/source/issue_3868.rs similarity index 100% rename from tests/source/issue_3868.rs rename to src/tools/rustfmt/tests/source/issue_3868.rs diff --git a/tests/source/issue_4032.rs b/src/tools/rustfmt/tests/source/issue_4032.rs similarity index 100% rename from tests/source/issue_4032.rs rename to src/tools/rustfmt/tests/source/issue_4032.rs diff --git a/tests/source/issue_4037.rs b/src/tools/rustfmt/tests/source/issue_4037.rs similarity index 100% rename from tests/source/issue_4037.rs rename to src/tools/rustfmt/tests/source/issue_4037.rs diff --git a/tests/source/issue_4057.rs b/src/tools/rustfmt/tests/source/issue_4057.rs similarity index 100% rename from tests/source/issue_4057.rs rename to src/tools/rustfmt/tests/source/issue_4057.rs diff --git a/tests/source/issue_4086.rs b/src/tools/rustfmt/tests/source/issue_4086.rs similarity index 100% rename from tests/source/issue_4086.rs rename to src/tools/rustfmt/tests/source/issue_4086.rs diff --git a/tests/source/issue_4257.rs b/src/tools/rustfmt/tests/source/issue_4257.rs similarity index 100% rename from tests/source/issue_4257.rs rename to src/tools/rustfmt/tests/source/issue_4257.rs diff --git a/tests/source/issue_4322.rs b/src/tools/rustfmt/tests/source/issue_4322.rs similarity index 100% rename from tests/source/issue_4322.rs rename to src/tools/rustfmt/tests/source/issue_4322.rs diff --git a/tests/source/issue_4374.rs b/src/tools/rustfmt/tests/source/issue_4374.rs similarity index 100% rename from tests/source/issue_4374.rs rename to src/tools/rustfmt/tests/source/issue_4374.rs diff --git a/tests/source/issue_4475.rs b/src/tools/rustfmt/tests/source/issue_4475.rs similarity index 100% rename from tests/source/issue_4475.rs rename to src/tools/rustfmt/tests/source/issue_4475.rs diff --git a/tests/source/issue_4528.rs b/src/tools/rustfmt/tests/source/issue_4528.rs similarity index 100% rename from tests/source/issue_4528.rs rename to src/tools/rustfmt/tests/source/issue_4528.rs diff --git a/tests/source/issue_4579.rs b/src/tools/rustfmt/tests/source/issue_4579.rs similarity index 100% rename from tests/source/issue_4579.rs rename to src/tools/rustfmt/tests/source/issue_4579.rs diff --git a/tests/source/issue_4584.rs b/src/tools/rustfmt/tests/source/issue_4584.rs similarity index 100% rename from tests/source/issue_4584.rs rename to src/tools/rustfmt/tests/source/issue_4584.rs diff --git a/tests/source/issue_4636.rs b/src/tools/rustfmt/tests/source/issue_4636.rs similarity index 100% rename from tests/source/issue_4636.rs rename to src/tools/rustfmt/tests/source/issue_4636.rs diff --git a/tests/source/issue_4675.rs b/src/tools/rustfmt/tests/source/issue_4675.rs similarity index 100% rename from tests/source/issue_4675.rs rename to src/tools/rustfmt/tests/source/issue_4675.rs diff --git a/tests/source/issue_4823.rs b/src/tools/rustfmt/tests/source/issue_4823.rs similarity index 100% rename from tests/source/issue_4823.rs rename to src/tools/rustfmt/tests/source/issue_4823.rs diff --git a/tests/source/issue_4854.rs b/src/tools/rustfmt/tests/source/issue_4854.rs similarity index 100% rename from tests/source/issue_4854.rs rename to src/tools/rustfmt/tests/source/issue_4854.rs diff --git a/tests/source/issue_4911.rs b/src/tools/rustfmt/tests/source/issue_4911.rs similarity index 100% rename from tests/source/issue_4911.rs rename to src/tools/rustfmt/tests/source/issue_4911.rs diff --git a/tests/source/issue_4943.rs b/src/tools/rustfmt/tests/source/issue_4943.rs similarity index 100% rename from tests/source/issue_4943.rs rename to src/tools/rustfmt/tests/source/issue_4943.rs diff --git a/tests/source/issue_4954.rs b/src/tools/rustfmt/tests/source/issue_4954.rs similarity index 100% rename from tests/source/issue_4954.rs rename to src/tools/rustfmt/tests/source/issue_4954.rs diff --git a/tests/source/issue_4963.rs b/src/tools/rustfmt/tests/source/issue_4963.rs similarity index 100% rename from tests/source/issue_4963.rs rename to src/tools/rustfmt/tests/source/issue_4963.rs diff --git a/tests/source/issue_5027.rs b/src/tools/rustfmt/tests/source/issue_5027.rs similarity index 100% rename from tests/source/issue_5027.rs rename to src/tools/rustfmt/tests/source/issue_5027.rs diff --git a/tests/source/issue_5086.rs b/src/tools/rustfmt/tests/source/issue_5086.rs similarity index 100% rename from tests/source/issue_5086.rs rename to src/tools/rustfmt/tests/source/issue_5086.rs diff --git a/tests/source/issue_5686.rs b/src/tools/rustfmt/tests/source/issue_5686.rs similarity index 100% rename from tests/source/issue_5686.rs rename to src/tools/rustfmt/tests/source/issue_5686.rs diff --git a/tests/source/issue_5721.rs b/src/tools/rustfmt/tests/source/issue_5721.rs similarity index 100% rename from tests/source/issue_5721.rs rename to src/tools/rustfmt/tests/source/issue_5721.rs diff --git a/tests/source/issue_5730.rs b/src/tools/rustfmt/tests/source/issue_5730.rs similarity index 100% rename from tests/source/issue_5730.rs rename to src/tools/rustfmt/tests/source/issue_5730.rs diff --git a/tests/source/issue_5735.rs b/src/tools/rustfmt/tests/source/issue_5735.rs similarity index 100% rename from tests/source/issue_5735.rs rename to src/tools/rustfmt/tests/source/issue_5735.rs diff --git a/tests/source/issue_5739.rs b/src/tools/rustfmt/tests/source/issue_5739.rs similarity index 100% rename from tests/source/issue_5739.rs rename to src/tools/rustfmt/tests/source/issue_5739.rs diff --git a/tests/source/issue_5882.rs b/src/tools/rustfmt/tests/source/issue_5882.rs similarity index 100% rename from tests/source/issue_5882.rs rename to src/tools/rustfmt/tests/source/issue_5882.rs diff --git a/tests/source/issue_5912.rs b/src/tools/rustfmt/tests/source/issue_5912.rs similarity index 100% rename from tests/source/issue_5912.rs rename to src/tools/rustfmt/tests/source/issue_5912.rs diff --git a/tests/source/issue_5920_style_edition_2024.rs b/src/tools/rustfmt/tests/source/issue_5920_style_edition_2024.rs similarity index 100% rename from tests/source/issue_5920_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/issue_5920_style_edition_2024.rs diff --git a/tests/source/issue_5920_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_5920_style_edition_2027.rs similarity index 100% rename from tests/source/issue_5920_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_5920_style_edition_2027.rs diff --git a/tests/source/issue_5982_style_edition_2024.rs b/src/tools/rustfmt/tests/source/issue_5982_style_edition_2024.rs similarity index 100% rename from tests/source/issue_5982_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/issue_5982_style_edition_2024.rs diff --git a/tests/source/issue_5982_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_5982_style_edition_2027.rs similarity index 100% rename from tests/source/issue_5982_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_5982_style_edition_2027.rs diff --git a/tests/source/issue_6209.rs b/src/tools/rustfmt/tests/source/issue_6209.rs similarity index 100% rename from tests/source/issue_6209.rs rename to src/tools/rustfmt/tests/source/issue_6209.rs diff --git a/tests/source/issue_6381_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_6381_style_edition_2027.rs similarity index 100% rename from tests/source/issue_6381_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_6381_style_edition_2027.rs diff --git a/tests/source/issue_6558.rs b/src/tools/rustfmt/tests/source/issue_6558.rs similarity index 100% rename from tests/source/issue_6558.rs rename to src/tools/rustfmt/tests/source/issue_6558.rs diff --git a/tests/source/issue_6801.rs b/src/tools/rustfmt/tests/source/issue_6801.rs similarity index 100% rename from tests/source/issue_6801.rs rename to src/tools/rustfmt/tests/source/issue_6801.rs diff --git a/tests/source/issue_6831_style_edition_2021.rs b/src/tools/rustfmt/tests/source/issue_6831_style_edition_2021.rs similarity index 100% rename from tests/source/issue_6831_style_edition_2021.rs rename to src/tools/rustfmt/tests/source/issue_6831_style_edition_2021.rs diff --git a/tests/source/issue_6831_style_edition_2024.rs b/src/tools/rustfmt/tests/source/issue_6831_style_edition_2024.rs similarity index 100% rename from tests/source/issue_6831_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/issue_6831_style_edition_2024.rs diff --git a/tests/source/issue_6831_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_6831_style_edition_2027.rs similarity index 100% rename from tests/source/issue_6831_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_6831_style_edition_2027.rs diff --git a/tests/source/issue_7003_style_edition_2024.rs b/src/tools/rustfmt/tests/source/issue_7003_style_edition_2024.rs similarity index 100% rename from tests/source/issue_7003_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/issue_7003_style_edition_2024.rs diff --git a/tests/source/issue_7003_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_7003_style_edition_2027.rs similarity index 100% rename from tests/source/issue_7003_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_7003_style_edition_2027.rs diff --git a/tests/source/issue_7036.rs b/src/tools/rustfmt/tests/source/issue_7036.rs similarity index 100% rename from tests/source/issue_7036.rs rename to src/tools/rustfmt/tests/source/issue_7036.rs diff --git a/tests/source/issue_7055_style_edition_2024.rs b/src/tools/rustfmt/tests/source/issue_7055_style_edition_2024.rs similarity index 100% rename from tests/source/issue_7055_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/issue_7055_style_edition_2024.rs diff --git a/tests/source/issue_7055_style_edition_2027.rs b/src/tools/rustfmt/tests/source/issue_7055_style_edition_2027.rs similarity index 100% rename from tests/source/issue_7055_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/issue_7055_style_edition_2027.rs diff --git a/tests/source/issue_7088_stable.rs b/src/tools/rustfmt/tests/source/issue_7088_stable.rs similarity index 100% rename from tests/source/issue_7088_stable.rs rename to src/tools/rustfmt/tests/source/issue_7088_stable.rs diff --git a/tests/source/issue_7088_unstable.rs b/src/tools/rustfmt/tests/source/issue_7088_unstable.rs similarity index 100% rename from tests/source/issue_7088_unstable.rs rename to src/tools/rustfmt/tests/source/issue_7088_unstable.rs diff --git a/tests/source/item-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs similarity index 100% rename from tests/source/item-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/source/item-brace-style-always-next-line.rs diff --git a/tests/source/item-brace-style-prefer-same-line.rs b/src/tools/rustfmt/tests/source/item-brace-style-prefer-same-line.rs similarity index 100% rename from tests/source/item-brace-style-prefer-same-line.rs rename to src/tools/rustfmt/tests/source/item-brace-style-prefer-same-line.rs diff --git a/tests/source/item-brace-style-same-line-where.rs b/src/tools/rustfmt/tests/source/item-brace-style-same-line-where.rs similarity index 100% rename from tests/source/item-brace-style-same-line-where.rs rename to src/tools/rustfmt/tests/source/item-brace-style-same-line-where.rs diff --git a/tests/source/itemized-blocks/no_wrap.rs b/src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs similarity index 100% rename from tests/source/itemized-blocks/no_wrap.rs rename to src/tools/rustfmt/tests/source/itemized-blocks/no_wrap.rs diff --git a/tests/source/itemized-blocks/rewrite_fail.rs b/src/tools/rustfmt/tests/source/itemized-blocks/rewrite_fail.rs similarity index 100% rename from tests/source/itemized-blocks/rewrite_fail.rs rename to src/tools/rustfmt/tests/source/itemized-blocks/rewrite_fail.rs diff --git a/tests/source/itemized-blocks/urls.rs b/src/tools/rustfmt/tests/source/itemized-blocks/urls.rs similarity index 100% rename from tests/source/itemized-blocks/urls.rs rename to src/tools/rustfmt/tests/source/itemized-blocks/urls.rs diff --git a/tests/source/itemized-blocks/wrap.rs b/src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs similarity index 100% rename from tests/source/itemized-blocks/wrap.rs rename to src/tools/rustfmt/tests/source/itemized-blocks/wrap.rs diff --git a/tests/source/label_break.rs b/src/tools/rustfmt/tests/source/label_break.rs similarity index 100% rename from tests/source/label_break.rs rename to src/tools/rustfmt/tests/source/label_break.rs diff --git a/tests/source/large-block.rs b/src/tools/rustfmt/tests/source/large-block.rs similarity index 100% rename from tests/source/large-block.rs rename to src/tools/rustfmt/tests/source/large-block.rs diff --git a/tests/source/large_vec.rs b/src/tools/rustfmt/tests/source/large_vec.rs similarity index 100% rename from tests/source/large_vec.rs rename to src/tools/rustfmt/tests/source/large_vec.rs diff --git a/tests/source/lazy_staic_before_2027.rs b/src/tools/rustfmt/tests/source/lazy_staic_before_2027.rs similarity index 100% rename from tests/source/lazy_staic_before_2027.rs rename to src/tools/rustfmt/tests/source/lazy_staic_before_2027.rs diff --git a/tests/source/lazy_static.rs b/src/tools/rustfmt/tests/source/lazy_static.rs similarity index 100% rename from tests/source/lazy_static.rs rename to src/tools/rustfmt/tests/source/lazy_static.rs diff --git a/tests/source/let_chains.rs b/src/tools/rustfmt/tests/source/let_chains.rs similarity index 100% rename from tests/source/let_chains.rs rename to src/tools/rustfmt/tests/source/let_chains.rs diff --git a/tests/source/let_else.rs b/src/tools/rustfmt/tests/source/let_else.rs similarity index 100% rename from tests/source/let_else.rs rename to src/tools/rustfmt/tests/source/let_else.rs diff --git a/tests/source/let_else_v2.rs b/src/tools/rustfmt/tests/source/let_else_v2.rs similarity index 100% rename from tests/source/let_else_v2.rs rename to src/tools/rustfmt/tests/source/let_else_v2.rs diff --git a/tests/source/long-fn-1/version_one.rs b/src/tools/rustfmt/tests/source/long-fn-1/version_one.rs similarity index 100% rename from tests/source/long-fn-1/version_one.rs rename to src/tools/rustfmt/tests/source/long-fn-1/version_one.rs diff --git a/tests/source/long-fn-1/version_two.rs b/src/tools/rustfmt/tests/source/long-fn-1/version_two.rs similarity index 100% rename from tests/source/long-fn-1/version_two.rs rename to src/tools/rustfmt/tests/source/long-fn-1/version_two.rs diff --git a/tests/source/long-match-arms-brace-newline.rs b/src/tools/rustfmt/tests/source/long-match-arms-brace-newline.rs similarity index 100% rename from tests/source/long-match-arms-brace-newline.rs rename to src/tools/rustfmt/tests/source/long-match-arms-brace-newline.rs diff --git a/tests/source/long-use-statement-issue-3154.rs b/src/tools/rustfmt/tests/source/long-use-statement-issue-3154.rs similarity index 100% rename from tests/source/long-use-statement-issue-3154.rs rename to src/tools/rustfmt/tests/source/long-use-statement-issue-3154.rs diff --git a/tests/source/long_field_access.rs b/src/tools/rustfmt/tests/source/long_field_access.rs similarity index 100% rename from tests/source/long_field_access.rs rename to src/tools/rustfmt/tests/source/long_field_access.rs diff --git a/tests/source/loop.rs b/src/tools/rustfmt/tests/source/loop.rs similarity index 100% rename from tests/source/loop.rs rename to src/tools/rustfmt/tests/source/loop.rs diff --git a/tests/source/macro_not_expr.rs b/src/tools/rustfmt/tests/source/macro_not_expr.rs similarity index 100% rename from tests/source/macro_not_expr.rs rename to src/tools/rustfmt/tests/source/macro_not_expr.rs diff --git a/tests/source/macro_rules.rs b/src/tools/rustfmt/tests/source/macro_rules.rs similarity index 100% rename from tests/source/macro_rules.rs rename to src/tools/rustfmt/tests/source/macro_rules.rs diff --git a/tests/source/macros.rs b/src/tools/rustfmt/tests/source/macros.rs similarity index 100% rename from tests/source/macros.rs rename to src/tools/rustfmt/tests/source/macros.rs diff --git a/tests/source/macros/rewrite-const-item.rs b/src/tools/rustfmt/tests/source/macros/rewrite-const-item.rs similarity index 100% rename from tests/source/macros/rewrite-const-item.rs rename to src/tools/rustfmt/tests/source/macros/rewrite-const-item.rs diff --git a/tests/source/markdown-comment-with-options.rs b/src/tools/rustfmt/tests/source/markdown-comment-with-options.rs similarity index 100% rename from tests/source/markdown-comment-with-options.rs rename to src/tools/rustfmt/tests/source/markdown-comment-with-options.rs diff --git a/tests/source/markdown-comment.rs b/src/tools/rustfmt/tests/source/markdown-comment.rs similarity index 100% rename from tests/source/markdown-comment.rs rename to src/tools/rustfmt/tests/source/markdown-comment.rs diff --git a/tests/source/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/source/match-block-trailing-comma.rs similarity index 100% rename from tests/source/match-block-trailing-comma.rs rename to src/tools/rustfmt/tests/source/match-block-trailing-comma.rs diff --git a/tests/source/match-flattening.rs b/src/tools/rustfmt/tests/source/match-flattening.rs similarity index 100% rename from tests/source/match-flattening.rs rename to src/tools/rustfmt/tests/source/match-flattening.rs diff --git a/tests/source/match-nowrap-trailing-comma.rs b/src/tools/rustfmt/tests/source/match-nowrap-trailing-comma.rs similarity index 100% rename from tests/source/match-nowrap-trailing-comma.rs rename to src/tools/rustfmt/tests/source/match-nowrap-trailing-comma.rs diff --git a/tests/source/match-nowrap.rs b/src/tools/rustfmt/tests/source/match-nowrap.rs similarity index 100% rename from tests/source/match-nowrap.rs rename to src/tools/rustfmt/tests/source/match-nowrap.rs diff --git a/tests/source/match.rs b/src/tools/rustfmt/tests/source/match.rs similarity index 100% rename from tests/source/match.rs rename to src/tools/rustfmt/tests/source/match.rs diff --git a/tests/source/match_overflow_expr.rs b/src/tools/rustfmt/tests/source/match_overflow_expr.rs similarity index 100% rename from tests/source/match_overflow_expr.rs rename to src/tools/rustfmt/tests/source/match_overflow_expr.rs diff --git a/tests/source/max-line-length-in-chars.rs b/src/tools/rustfmt/tests/source/max-line-length-in-chars.rs similarity index 100% rename from tests/source/max-line-length-in-chars.rs rename to src/tools/rustfmt/tests/source/max-line-length-in-chars.rs diff --git a/tests/source/merge_imports_true_compat.rs b/src/tools/rustfmt/tests/source/merge_imports_true_compat.rs similarity index 100% rename from tests/source/merge_imports_true_compat.rs rename to src/tools/rustfmt/tests/source/merge_imports_true_compat.rs diff --git a/tests/source/mod-1.rs b/src/tools/rustfmt/tests/source/mod-1.rs similarity index 100% rename from tests/source/mod-1.rs rename to src/tools/rustfmt/tests/source/mod-1.rs diff --git a/tests/source/mod-2.rs b/src/tools/rustfmt/tests/source/mod-2.rs similarity index 100% rename from tests/source/mod-2.rs rename to src/tools/rustfmt/tests/source/mod-2.rs diff --git a/tests/source/mod_skip_child.rs b/src/tools/rustfmt/tests/source/mod_skip_child.rs similarity index 100% rename from tests/source/mod_skip_child.rs rename to src/tools/rustfmt/tests/source/mod_skip_child.rs diff --git a/tests/source/multiple.rs b/src/tools/rustfmt/tests/source/multiple.rs similarity index 100% rename from tests/source/multiple.rs rename to src/tools/rustfmt/tests/source/multiple.rs diff --git a/tests/source/mut-restriction.rs b/src/tools/rustfmt/tests/source/mut-restriction.rs similarity index 100% rename from tests/source/mut-restriction.rs rename to src/tools/rustfmt/tests/source/mut-restriction.rs diff --git a/tests/source/mut_ref.rs b/src/tools/rustfmt/tests/source/mut_ref.rs similarity index 100% rename from tests/source/mut_ref.rs rename to src/tools/rustfmt/tests/source/mut_ref.rs diff --git a/tests/source/negative-impl.rs b/src/tools/rustfmt/tests/source/negative-impl.rs similarity index 100% rename from tests/source/negative-impl.rs rename to src/tools/rustfmt/tests/source/negative-impl.rs diff --git a/tests/source/nested-if-else.rs b/src/tools/rustfmt/tests/source/nested-if-else.rs similarity index 100% rename from tests/source/nested-if-else.rs rename to src/tools/rustfmt/tests/source/nested-if-else.rs diff --git a/tests/source/nested_skipped/mod.rs b/src/tools/rustfmt/tests/source/nested_skipped/mod.rs similarity index 100% rename from tests/source/nested_skipped/mod.rs rename to src/tools/rustfmt/tests/source/nested_skipped/mod.rs diff --git a/tests/source/nestedmod/mod.rs b/src/tools/rustfmt/tests/source/nestedmod/mod.rs similarity index 100% rename from tests/source/nestedmod/mod.rs rename to src/tools/rustfmt/tests/source/nestedmod/mod.rs diff --git a/tests/source/nestedmod/mod2a.rs b/src/tools/rustfmt/tests/source/nestedmod/mod2a.rs similarity index 100% rename from tests/source/nestedmod/mod2a.rs rename to src/tools/rustfmt/tests/source/nestedmod/mod2a.rs diff --git a/tests/source/nestedmod/mod2b.rs b/src/tools/rustfmt/tests/source/nestedmod/mod2b.rs similarity index 100% rename from tests/source/nestedmod/mod2b.rs rename to src/tools/rustfmt/tests/source/nestedmod/mod2b.rs diff --git a/tests/source/nestedmod/mod2c.rs b/src/tools/rustfmt/tests/source/nestedmod/mod2c.rs similarity index 100% rename from tests/source/nestedmod/mod2c.rs rename to src/tools/rustfmt/tests/source/nestedmod/mod2c.rs diff --git a/tests/source/nestedmod/mymod1/mod3a.rs b/src/tools/rustfmt/tests/source/nestedmod/mymod1/mod3a.rs similarity index 100% rename from tests/source/nestedmod/mymod1/mod3a.rs rename to src/tools/rustfmt/tests/source/nestedmod/mymod1/mod3a.rs diff --git a/tests/source/nestedmod/submod2/a.rs b/src/tools/rustfmt/tests/source/nestedmod/submod2/a.rs similarity index 100% rename from tests/source/nestedmod/submod2/a.rs rename to src/tools/rustfmt/tests/source/nestedmod/submod2/a.rs diff --git a/tests/source/nestedmod/submod2/mod.rs b/src/tools/rustfmt/tests/source/nestedmod/submod2/mod.rs similarity index 100% rename from tests/source/nestedmod/submod2/mod.rs rename to src/tools/rustfmt/tests/source/nestedmod/submod2/mod.rs diff --git a/tests/source/no_arg_with_comment.rs b/src/tools/rustfmt/tests/source/no_arg_with_comment.rs similarity index 100% rename from tests/source/no_arg_with_comment.rs rename to src/tools/rustfmt/tests/source/no_arg_with_comment.rs diff --git a/tests/source/no_new_line_beginning.rs b/src/tools/rustfmt/tests/source/no_new_line_beginning.rs similarity index 100% rename from tests/source/no_new_line_beginning.rs rename to src/tools/rustfmt/tests/source/no_new_line_beginning.rs diff --git a/tests/source/non-lifetime-binders.rs b/src/tools/rustfmt/tests/source/non-lifetime-binders.rs similarity index 100% rename from tests/source/non-lifetime-binders.rs rename to src/tools/rustfmt/tests/source/non-lifetime-binders.rs diff --git a/tests/source/non_ascii_numerics_import_asciibetically.rs b/src/tools/rustfmt/tests/source/non_ascii_numerics_import_asciibetically.rs similarity index 100% rename from tests/source/non_ascii_numerics_import_asciibetically.rs rename to src/tools/rustfmt/tests/source/non_ascii_numerics_import_asciibetically.rs diff --git a/tests/source/non_ascii_numerics_import_versionsort.rs b/src/tools/rustfmt/tests/source/non_ascii_numerics_import_versionsort.rs similarity index 100% rename from tests/source/non_ascii_numerics_import_versionsort.rs rename to src/tools/rustfmt/tests/source/non_ascii_numerics_import_versionsort.rs diff --git a/tests/source/normalize_doc_attributes_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/source/normalize_doc_attributes_should_not_imply_format_doc_comments.rs similarity index 100% rename from tests/source/normalize_doc_attributes_should_not_imply_format_doc_comments.rs rename to src/tools/rustfmt/tests/source/normalize_doc_attributes_should_not_imply_format_doc_comments.rs diff --git a/tests/source/normalize_multiline_doc_attribute.rs b/src/tools/rustfmt/tests/source/normalize_multiline_doc_attribute.rs similarity index 100% rename from tests/source/normalize_multiline_doc_attribute.rs rename to src/tools/rustfmt/tests/source/normalize_multiline_doc_attribute.rs diff --git a/tests/source/one_line_if_v1.rs b/src/tools/rustfmt/tests/source/one_line_if_v1.rs similarity index 100% rename from tests/source/one_line_if_v1.rs rename to src/tools/rustfmt/tests/source/one_line_if_v1.rs diff --git a/tests/source/one_line_if_v2.rs b/src/tools/rustfmt/tests/source/one_line_if_v2.rs similarity index 100% rename from tests/source/one_line_if_v2.rs rename to src/tools/rustfmt/tests/source/one_line_if_v2.rs diff --git a/tests/source/other.rs b/src/tools/rustfmt/tests/source/other.rs similarity index 100% rename from tests/source/other.rs rename to src/tools/rustfmt/tests/source/other.rs diff --git a/tests/source/paren.rs b/src/tools/rustfmt/tests/source/paren.rs similarity index 100% rename from tests/source/paren.rs rename to src/tools/rustfmt/tests/source/paren.rs diff --git a/tests/source/path_clarity/foo.rs b/src/tools/rustfmt/tests/source/path_clarity/foo.rs similarity index 100% rename from tests/source/path_clarity/foo.rs rename to src/tools/rustfmt/tests/source/path_clarity/foo.rs diff --git a/tests/source/path_clarity/foo/bar.rs b/src/tools/rustfmt/tests/source/path_clarity/foo/bar.rs similarity index 100% rename from tests/source/path_clarity/foo/bar.rs rename to src/tools/rustfmt/tests/source/path_clarity/foo/bar.rs diff --git a/tests/source/paths.rs b/src/tools/rustfmt/tests/source/paths.rs similarity index 100% rename from tests/source/paths.rs rename to src/tools/rustfmt/tests/source/paths.rs diff --git a/tests/source/pattern-condense-wildcards.rs b/src/tools/rustfmt/tests/source/pattern-condense-wildcards.rs similarity index 100% rename from tests/source/pattern-condense-wildcards.rs rename to src/tools/rustfmt/tests/source/pattern-condense-wildcards.rs diff --git a/tests/source/pattern.rs b/src/tools/rustfmt/tests/source/pattern.rs similarity index 100% rename from tests/source/pattern.rs rename to src/tools/rustfmt/tests/source/pattern.rs diff --git a/tests/source/pin_sugar.rs b/src/tools/rustfmt/tests/source/pin_sugar.rs similarity index 100% rename from tests/source/pin_sugar.rs rename to src/tools/rustfmt/tests/source/pin_sugar.rs diff --git a/tests/source/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/source/postfix-match/pf-match.rs similarity index 100% rename from tests/source/postfix-match/pf-match.rs rename to src/tools/rustfmt/tests/source/postfix-match/pf-match.rs diff --git a/tests/source/precise-capturing.rs b/src/tools/rustfmt/tests/source/precise-capturing.rs similarity index 100% rename from tests/source/precise-capturing.rs rename to src/tools/rustfmt/tests/source/precise-capturing.rs diff --git a/tests/source/preserves_carriage_return_for_unix.rs b/src/tools/rustfmt/tests/source/preserves_carriage_return_for_unix.rs similarity index 100% rename from tests/source/preserves_carriage_return_for_unix.rs rename to src/tools/rustfmt/tests/source/preserves_carriage_return_for_unix.rs diff --git a/tests/source/preserves_carriage_return_for_windows.rs b/src/tools/rustfmt/tests/source/preserves_carriage_return_for_windows.rs similarity index 100% rename from tests/source/preserves_carriage_return_for_windows.rs rename to src/tools/rustfmt/tests/source/preserves_carriage_return_for_windows.rs diff --git a/tests/source/pub-restricted.rs b/src/tools/rustfmt/tests/source/pub-restricted.rs similarity index 100% rename from tests/source/pub-restricted.rs rename to src/tools/rustfmt/tests/source/pub-restricted.rs diff --git a/tests/source/remove_blank_lines.rs b/src/tools/rustfmt/tests/source/remove_blank_lines.rs similarity index 100% rename from tests/source/remove_blank_lines.rs rename to src/tools/rustfmt/tests/source/remove_blank_lines.rs diff --git a/tests/source/reorder-impl-items.rs b/src/tools/rustfmt/tests/source/reorder-impl-items.rs similarity index 100% rename from tests/source/reorder-impl-items.rs rename to src/tools/rustfmt/tests/source/reorder-impl-items.rs diff --git a/tests/source/reorder_modules/A2/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/A2/mod.rs similarity index 100% rename from tests/source/reorder_modules/A2/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/A2/mod.rs diff --git a/tests/source/reorder_modules/ABCD/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/ABCD/mod.rs similarity index 100% rename from tests/source/reorder_modules/ABCD/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/ABCD/mod.rs diff --git a/tests/source/reorder_modules/ZYXW/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/ZYXW/mod.rs similarity index 100% rename from tests/source/reorder_modules/ZYXW/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/ZYXW/mod.rs diff --git a/tests/source/reorder_modules/ZYXW_/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/ZYXW_/mod.rs similarity index 100% rename from tests/source/reorder_modules/ZYXW_/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/ZYXW_/mod.rs diff --git a/tests/source/reorder_modules/ZY_XW/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/ZY_XW/mod.rs similarity index 100% rename from tests/source/reorder_modules/ZY_XW/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/ZY_XW/mod.rs diff --git a/tests/source/reorder_modules/Z_YXW/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/Z_YXW/mod.rs similarity index 100% rename from tests/source/reorder_modules/Z_YXW/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/Z_YXW/mod.rs diff --git a/tests/source/reorder_modules/_ZYXW/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/_ZYXW/mod.rs similarity index 100% rename from tests/source/reorder_modules/_ZYXW/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/_ZYXW/mod.rs diff --git a/tests/source/reorder_modules/_abcd/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/_abcd/mod.rs similarity index 100% rename from tests/source/reorder_modules/_abcd/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/_abcd/mod.rs diff --git a/tests/source/reorder_modules/a1/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/a1/mod.rs similarity index 100% rename from tests/source/reorder_modules/a1/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/a1/mod.rs diff --git a/tests/source/reorder_modules/abcde/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/abcde/mod.rs similarity index 100% rename from tests/source/reorder_modules/abcde/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/abcde/mod.rs diff --git a/tests/source/reorder_modules/disabled_style_edition_2024.rs b/src/tools/rustfmt/tests/source/reorder_modules/disabled_style_edition_2024.rs similarity index 100% rename from tests/source/reorder_modules/disabled_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/reorder_modules/disabled_style_edition_2024.rs diff --git a/tests/source/reorder_modules/disabled_style_edition_2027.rs b/src/tools/rustfmt/tests/source/reorder_modules/disabled_style_edition_2027.rs similarity index 100% rename from tests/source/reorder_modules/disabled_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/reorder_modules/disabled_style_edition_2027.rs diff --git a/tests/source/reorder_modules/enabled_style_edition_2015.rs b/src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2015.rs similarity index 100% rename from tests/source/reorder_modules/enabled_style_edition_2015.rs rename to src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2015.rs diff --git a/tests/source/reorder_modules/enabled_style_edition_2024.rs b/src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2024.rs similarity index 100% rename from tests/source/reorder_modules/enabled_style_edition_2024.rs rename to src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2024.rs diff --git a/tests/source/reorder_modules/enabled_style_edition_2027.rs b/src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2027.rs similarity index 100% rename from tests/source/reorder_modules/enabled_style_edition_2027.rs rename to src/tools/rustfmt/tests/source/reorder_modules/enabled_style_edition_2027.rs diff --git a/tests/source/reorder_modules/u128/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u128/mod.rs similarity index 100% rename from tests/source/reorder_modules/u128/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u128/mod.rs diff --git a/tests/source/reorder_modules/u16/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u16/mod.rs similarity index 100% rename from tests/source/reorder_modules/u16/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u16/mod.rs diff --git a/tests/source/reorder_modules/u256/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u256/mod.rs similarity index 100% rename from tests/source/reorder_modules/u256/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u256/mod.rs diff --git a/tests/source/reorder_modules/u32/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u32/mod.rs similarity index 100% rename from tests/source/reorder_modules/u32/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u32/mod.rs diff --git a/tests/source/reorder_modules/u64/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u64/mod.rs similarity index 100% rename from tests/source/reorder_modules/u64/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u64/mod.rs diff --git a/tests/source/reorder_modules/u8/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u8/mod.rs similarity index 100% rename from tests/source/reorder_modules/u8/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u8/mod.rs diff --git a/tests/source/reorder_modules/u_zzz/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/u_zzz/mod.rs similarity index 100% rename from tests/source/reorder_modules/u_zzz/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/u_zzz/mod.rs diff --git a/tests/source/reorder_modules/ua/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/ua/mod.rs similarity index 100% rename from tests/source/reorder_modules/ua/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/ua/mod.rs diff --git a/tests/source/reorder_modules/usize/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/usize/mod.rs similarity index 100% rename from tests/source/reorder_modules/usize/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/usize/mod.rs diff --git a/tests/source/reorder_modules/uz/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/uz/mod.rs similarity index 100% rename from tests/source/reorder_modules/uz/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/uz/mod.rs diff --git a/tests/source/reorder_modules/v0/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v0/mod.rs similarity index 100% rename from tests/source/reorder_modules/v0/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v0/mod.rs diff --git a/tests/source/reorder_modules/v00/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v00/mod.rs similarity index 100% rename from tests/source/reorder_modules/v00/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v00/mod.rs diff --git a/tests/source/reorder_modules/v000/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v000/mod.rs similarity index 100% rename from tests/source/reorder_modules/v000/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v000/mod.rs diff --git a/tests/source/reorder_modules/v001/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v001/mod.rs similarity index 100% rename from tests/source/reorder_modules/v001/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v001/mod.rs diff --git a/tests/source/reorder_modules/v009/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v009/mod.rs similarity index 100% rename from tests/source/reorder_modules/v009/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v009/mod.rs diff --git a/tests/source/reorder_modules/v00t/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v00t/mod.rs similarity index 100% rename from tests/source/reorder_modules/v00t/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v00t/mod.rs diff --git a/tests/source/reorder_modules/v01/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v01/mod.rs similarity index 100% rename from tests/source/reorder_modules/v01/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v01/mod.rs diff --git a/tests/source/reorder_modules/v010/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v010/mod.rs similarity index 100% rename from tests/source/reorder_modules/v010/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v010/mod.rs diff --git a/tests/source/reorder_modules/v09/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v09/mod.rs similarity index 100% rename from tests/source/reorder_modules/v09/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v09/mod.rs diff --git a/tests/source/reorder_modules/v0s/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v0s/mod.rs similarity index 100% rename from tests/source/reorder_modules/v0s/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v0s/mod.rs diff --git a/tests/source/reorder_modules/v0u/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v0u/mod.rs similarity index 100% rename from tests/source/reorder_modules/v0u/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v0u/mod.rs diff --git a/tests/source/reorder_modules/v1/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v1/mod.rs similarity index 100% rename from tests/source/reorder_modules/v1/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v1/mod.rs diff --git a/tests/source/reorder_modules/v10/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v10/mod.rs similarity index 100% rename from tests/source/reorder_modules/v10/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v10/mod.rs diff --git a/tests/source/reorder_modules/v9/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/v9/mod.rs similarity index 100% rename from tests/source/reorder_modules/v9/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/v9/mod.rs diff --git a/tests/source/reorder_modules/w005s09t/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/w005s09t/mod.rs similarity index 100% rename from tests/source/reorder_modules/w005s09t/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/w005s09t/mod.rs diff --git a/tests/source/reorder_modules/w5s009t/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/w5s009t/mod.rs similarity index 100% rename from tests/source/reorder_modules/w5s009t/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/w5s009t/mod.rs diff --git a/tests/source/reorder_modules/x64/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x64/mod.rs similarity index 100% rename from tests/source/reorder_modules/x64/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x64/mod.rs diff --git a/tests/source/reorder_modules/x86/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x86/mod.rs similarity index 100% rename from tests/source/reorder_modules/x86/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x86/mod.rs diff --git a/tests/source/reorder_modules/x86_128/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x86_128/mod.rs similarity index 100% rename from tests/source/reorder_modules/x86_128/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x86_128/mod.rs diff --git a/tests/source/reorder_modules/x86_32/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x86_32/mod.rs similarity index 100% rename from tests/source/reorder_modules/x86_32/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x86_32/mod.rs diff --git a/tests/source/reorder_modules/x86_64/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x86_64/mod.rs similarity index 100% rename from tests/source/reorder_modules/x86_64/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x86_64/mod.rs diff --git a/tests/source/reorder_modules/x87/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/x87/mod.rs similarity index 100% rename from tests/source/reorder_modules/x87/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/x87/mod.rs diff --git a/tests/source/reorder_modules/zyxwv/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules/zyxwv/mod.rs similarity index 100% rename from tests/source/reorder_modules/zyxwv/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules/zyxwv/mod.rs diff --git a/tests/source/reorder_modules_2027/abcde/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules_2027/abcde/mod.rs similarity index 100% rename from tests/source/reorder_modules_2027/abcde/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules_2027/abcde/mod.rs diff --git a/tests/source/reorder_modules_2027/zyxwv/mod.rs b/src/tools/rustfmt/tests/source/reorder_modules_2027/zyxwv/mod.rs similarity index 100% rename from tests/source/reorder_modules_2027/zyxwv/mod.rs rename to src/tools/rustfmt/tests/source/reorder_modules_2027/zyxwv/mod.rs diff --git a/tests/source/single-line-if-else.rs b/src/tools/rustfmt/tests/source/single-line-if-else.rs similarity index 100% rename from tests/source/single-line-if-else.rs rename to src/tools/rustfmt/tests/source/single-line-if-else.rs diff --git a/tests/source/single-line-macro/v1.rs b/src/tools/rustfmt/tests/source/single-line-macro/v1.rs similarity index 100% rename from tests/source/single-line-macro/v1.rs rename to src/tools/rustfmt/tests/source/single-line-macro/v1.rs diff --git a/tests/source/single-line-macro/v2.rs b/src/tools/rustfmt/tests/source/single-line-macro/v2.rs similarity index 100% rename from tests/source/single-line-macro/v2.rs rename to src/tools/rustfmt/tests/source/single-line-macro/v2.rs diff --git a/tests/source/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs similarity index 100% rename from tests/source/skip_macro_invocations/all.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/all.rs diff --git a/tests/source/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs similarity index 100% rename from tests/source/skip_macro_invocations/all_and_name.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/all_and_name.rs diff --git a/tests/source/skip_macro_invocations/config_file.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs similarity index 100% rename from tests/source/skip_macro_invocations/config_file.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/config_file.rs diff --git a/tests/source/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs similarity index 100% rename from tests/source/skip_macro_invocations/empty.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/empty.rs diff --git a/tests/source/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs similarity index 100% rename from tests/source/skip_macro_invocations/name.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/name.rs diff --git a/tests/source/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs similarity index 100% rename from tests/source/skip_macro_invocations/name_unknown.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/name_unknown.rs diff --git a/tests/source/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs similarity index 100% rename from tests/source/skip_macro_invocations/names.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/names.rs diff --git a/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs similarity index 100% rename from tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_invocation_mismatch.rs diff --git a/tests/source/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs similarity index 100% rename from tests/source/skip_macro_invocations/path_qualified_match.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_match.rs diff --git a/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs similarity index 100% rename from tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/path_qualified_name_mismatch.rs diff --git a/tests/source/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs similarity index 100% rename from tests/source/skip_macro_invocations/use_alias_examples.rs rename to src/tools/rustfmt/tests/source/skip_macro_invocations/use_alias_examples.rs diff --git a/tests/source/soft-wrapping.rs b/src/tools/rustfmt/tests/source/soft-wrapping.rs similarity index 100% rename from tests/source/soft-wrapping.rs rename to src/tools/rustfmt/tests/source/soft-wrapping.rs diff --git a/tests/source/space-not-before-newline.rs b/src/tools/rustfmt/tests/source/space-not-before-newline.rs similarity index 100% rename from tests/source/space-not-before-newline.rs rename to src/tools/rustfmt/tests/source/space-not-before-newline.rs diff --git a/tests/source/spaces-around-ranges.rs b/src/tools/rustfmt/tests/source/spaces-around-ranges.rs similarity index 100% rename from tests/source/spaces-around-ranges.rs rename to src/tools/rustfmt/tests/source/spaces-around-ranges.rs diff --git a/tests/source/statements.rs b/src/tools/rustfmt/tests/source/statements.rs similarity index 100% rename from tests/source/statements.rs rename to src/tools/rustfmt/tests/source/statements.rs diff --git a/tests/source/static.rs b/src/tools/rustfmt/tests/source/static.rs similarity index 100% rename from tests/source/static.rs rename to src/tools/rustfmt/tests/source/static.rs diff --git a/tests/source/string-lit-2.rs b/src/tools/rustfmt/tests/source/string-lit-2.rs similarity index 100% rename from tests/source/string-lit-2.rs rename to src/tools/rustfmt/tests/source/string-lit-2.rs diff --git a/tests/source/string-lit.rs b/src/tools/rustfmt/tests/source/string-lit.rs similarity index 100% rename from tests/source/string-lit.rs rename to src/tools/rustfmt/tests/source/string-lit.rs diff --git a/tests/source/string_lit_unicode_ws.rs b/src/tools/rustfmt/tests/source/string_lit_unicode_ws.rs similarity index 100% rename from tests/source/string_lit_unicode_ws.rs rename to src/tools/rustfmt/tests/source/string_lit_unicode_ws.rs diff --git a/tests/source/string_punctuation.rs b/src/tools/rustfmt/tests/source/string_punctuation.rs similarity index 100% rename from tests/source/string_punctuation.rs rename to src/tools/rustfmt/tests/source/string_punctuation.rs diff --git a/tests/source/struct-field-attributes.rs b/src/tools/rustfmt/tests/source/struct-field-attributes.rs similarity index 100% rename from tests/source/struct-field-attributes.rs rename to src/tools/rustfmt/tests/source/struct-field-attributes.rs diff --git a/tests/source/struct_field_doc_comment.rs b/src/tools/rustfmt/tests/source/struct_field_doc_comment.rs similarity index 100% rename from tests/source/struct_field_doc_comment.rs rename to src/tools/rustfmt/tests/source/struct_field_doc_comment.rs diff --git a/tests/source/struct_lits.rs b/src/tools/rustfmt/tests/source/struct_lits.rs similarity index 100% rename from tests/source/struct_lits.rs rename to src/tools/rustfmt/tests/source/struct_lits.rs diff --git a/tests/source/struct_lits_multiline.rs b/src/tools/rustfmt/tests/source/struct_lits_multiline.rs similarity index 100% rename from tests/source/struct_lits_multiline.rs rename to src/tools/rustfmt/tests/source/struct_lits_multiline.rs diff --git a/tests/source/struct_lits_visual.rs b/src/tools/rustfmt/tests/source/struct_lits_visual.rs similarity index 100% rename from tests/source/struct_lits_visual.rs rename to src/tools/rustfmt/tests/source/struct_lits_visual.rs diff --git a/tests/source/struct_lits_visual_multiline.rs b/src/tools/rustfmt/tests/source/struct_lits_visual_multiline.rs similarity index 100% rename from tests/source/struct_lits_visual_multiline.rs rename to src/tools/rustfmt/tests/source/struct_lits_visual_multiline.rs diff --git a/tests/source/struct_tuple_visual.rs b/src/tools/rustfmt/tests/source/struct_tuple_visual.rs similarity index 100% rename from tests/source/struct_tuple_visual.rs rename to src/tools/rustfmt/tests/source/struct_tuple_visual.rs diff --git a/tests/source/structs.rs b/src/tools/rustfmt/tests/source/structs.rs similarity index 100% rename from tests/source/structs.rs rename to src/tools/rustfmt/tests/source/structs.rs diff --git a/tests/source/super_let.rs b/src/tools/rustfmt/tests/source/super_let.rs similarity index 100% rename from tests/source/super_let.rs rename to src/tools/rustfmt/tests/source/super_let.rs diff --git a/tests/source/trailing-comma-never.rs b/src/tools/rustfmt/tests/source/trailing-comma-never.rs similarity index 100% rename from tests/source/trailing-comma-never.rs rename to src/tools/rustfmt/tests/source/trailing-comma-never.rs diff --git a/tests/source/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs b/src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs similarity index 100% rename from tests/source/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs rename to src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs diff --git a/tests/source/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs b/src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs similarity index 100% rename from tests/source/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs rename to src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs diff --git a/tests/source/trailing-semicolon/loop-bodies.rs b/src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies.rs similarity index 100% rename from tests/source/trailing-semicolon/loop-bodies.rs rename to src/tools/rustfmt/tests/source/trailing-semicolon/loop-bodies.rs diff --git a/tests/source/trailing_commas.rs b/src/tools/rustfmt/tests/source/trailing_commas.rs similarity index 100% rename from tests/source/trailing_commas.rs rename to src/tools/rustfmt/tests/source/trailing_commas.rs diff --git a/tests/source/trailing_comments/hard_tabs.rs b/src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs similarity index 100% rename from tests/source/trailing_comments/hard_tabs.rs rename to src/tools/rustfmt/tests/source/trailing_comments/hard_tabs.rs diff --git a/tests/source/trailing_comments/soft_tabs.rs b/src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs similarity index 100% rename from tests/source/trailing_comments/soft_tabs.rs rename to src/tools/rustfmt/tests/source/trailing_comments/soft_tabs.rs diff --git a/tests/source/trait.rs b/src/tools/rustfmt/tests/source/trait.rs similarity index 100% rename from tests/source/trait.rs rename to src/tools/rustfmt/tests/source/trait.rs diff --git a/tests/source/try-conversion.rs b/src/tools/rustfmt/tests/source/try-conversion.rs similarity index 100% rename from tests/source/try-conversion.rs rename to src/tools/rustfmt/tests/source/try-conversion.rs diff --git a/tests/source/try_block.rs b/src/tools/rustfmt/tests/source/try_block.rs similarity index 100% rename from tests/source/try_block.rs rename to src/tools/rustfmt/tests/source/try_block.rs diff --git a/tests/source/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs similarity index 100% rename from tests/source/try_blocks_heterogeneous.rs rename to src/tools/rustfmt/tests/source/try_blocks_heterogeneous.rs diff --git a/tests/source/tuple.rs b/src/tools/rustfmt/tests/source/tuple.rs similarity index 100% rename from tests/source/tuple.rs rename to src/tools/rustfmt/tests/source/tuple.rs diff --git a/tests/source/tuple_v2.rs b/src/tools/rustfmt/tests/source/tuple_v2.rs similarity index 100% rename from tests/source/tuple_v2.rs rename to src/tools/rustfmt/tests/source/tuple_v2.rs diff --git a/tests/source/type-alias-where-clauses-with-comments.rs b/src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs similarity index 100% rename from tests/source/type-alias-where-clauses-with-comments.rs rename to src/tools/rustfmt/tests/source/type-alias-where-clauses-with-comments.rs diff --git a/tests/source/type-alias-where-clauses.rs b/src/tools/rustfmt/tests/source/type-alias-where-clauses.rs similarity index 100% rename from tests/source/type-alias-where-clauses.rs rename to src/tools/rustfmt/tests/source/type-alias-where-clauses.rs diff --git a/tests/source/type.rs b/src/tools/rustfmt/tests/source/type.rs similarity index 100% rename from tests/source/type.rs rename to src/tools/rustfmt/tests/source/type.rs diff --git a/tests/source/type_alias.rs b/src/tools/rustfmt/tests/source/type_alias.rs similarity index 100% rename from tests/source/type_alias.rs rename to src/tools/rustfmt/tests/source/type_alias.rs diff --git a/tests/source/unicode.rs b/src/tools/rustfmt/tests/source/unicode.rs similarity index 100% rename from tests/source/unicode.rs rename to src/tools/rustfmt/tests/source/unicode.rs diff --git a/tests/source/unions.rs b/src/tools/rustfmt/tests/source/unions.rs similarity index 100% rename from tests/source/unions.rs rename to src/tools/rustfmt/tests/source/unions.rs diff --git a/tests/source/unsafe-binders.rs b/src/tools/rustfmt/tests/source/unsafe-binders.rs similarity index 100% rename from tests/source/unsafe-binders.rs rename to src/tools/rustfmt/tests/source/unsafe-binders.rs diff --git a/tests/source/unsafe-field.rs b/src/tools/rustfmt/tests/source/unsafe-field.rs similarity index 100% rename from tests/source/unsafe-field.rs rename to src/tools/rustfmt/tests/source/unsafe-field.rs diff --git a/tests/source/unsafe-mod.rs b/src/tools/rustfmt/tests/source/unsafe-mod.rs similarity index 100% rename from tests/source/unsafe-mod.rs rename to src/tools/rustfmt/tests/source/unsafe-mod.rs diff --git a/tests/source/use-identifier-order-mixed-edition.rs b/src/tools/rustfmt/tests/source/use-identifier-order-mixed-edition.rs similarity index 100% rename from tests/source/use-identifier-order-mixed-edition.rs rename to src/tools/rustfmt/tests/source/use-identifier-order-mixed-edition.rs diff --git a/tests/source/use-identifier-order.rs b/src/tools/rustfmt/tests/source/use-identifier-order.rs similarity index 100% rename from tests/source/use-identifier-order.rs rename to src/tools/rustfmt/tests/source/use-identifier-order.rs diff --git a/tests/source/visibility.rs b/src/tools/rustfmt/tests/source/visibility.rs similarity index 100% rename from tests/source/visibility.rs rename to src/tools/rustfmt/tests/source/visibility.rs diff --git a/tests/source/visual-fn-type.rs b/src/tools/rustfmt/tests/source/visual-fn-type.rs similarity index 100% rename from tests/source/visual-fn-type.rs rename to src/tools/rustfmt/tests/source/visual-fn-type.rs diff --git a/tests/source/where-clause-rfc.rs b/src/tools/rustfmt/tests/source/where-clause-rfc.rs similarity index 100% rename from tests/source/where-clause-rfc.rs rename to src/tools/rustfmt/tests/source/where-clause-rfc.rs diff --git a/tests/source/where-clause.rs b/src/tools/rustfmt/tests/source/where-clause.rs similarity index 100% rename from tests/source/where-clause.rs rename to src/tools/rustfmt/tests/source/where-clause.rs diff --git a/tests/source/width-heuristics.rs b/src/tools/rustfmt/tests/source/width-heuristics.rs similarity index 100% rename from tests/source/width-heuristics.rs rename to src/tools/rustfmt/tests/source/width-heuristics.rs diff --git a/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs similarity index 100% rename from tests/source/wrap_comments_should_not_imply_format_doc_comments.rs rename to src/tools/rustfmt/tests/source/wrap_comments_should_not_imply_format_doc_comments.rs diff --git a/tests/target/5131_crate.rs b/src/tools/rustfmt/tests/target/5131_crate.rs similarity index 100% rename from tests/target/5131_crate.rs rename to src/tools/rustfmt/tests/target/5131_crate.rs diff --git a/tests/target/5131_module.rs b/src/tools/rustfmt/tests/target/5131_module.rs similarity index 100% rename from tests/target/5131_module.rs rename to src/tools/rustfmt/tests/target/5131_module.rs diff --git a/tests/target/5131_one.rs b/src/tools/rustfmt/tests/target/5131_one.rs similarity index 100% rename from tests/target/5131_one.rs rename to src/tools/rustfmt/tests/target/5131_one.rs diff --git a/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs b/src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs similarity index 100% rename from tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs rename to src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/inner-block-doc-comment.rs diff --git a/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs b/src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs similarity index 100% rename from tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs rename to src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/naive-outer-block-comment.rs diff --git a/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs b/src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs similarity index 100% rename from tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs rename to src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/outer-block-doc-comment.rs diff --git a/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs b/src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs similarity index 100% rename from tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs rename to src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-1.rs diff --git a/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs b/src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs similarity index 100% rename from tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs rename to src/tools/rustfmt/tests/target/6639-non-idempotent-block-doc-comments/rustc-sample-2.rs diff --git a/tests/target/alignment_2633/block_style.rs b/src/tools/rustfmt/tests/target/alignment_2633/block_style.rs similarity index 100% rename from tests/target/alignment_2633/block_style.rs rename to src/tools/rustfmt/tests/target/alignment_2633/block_style.rs diff --git a/tests/target/alignment_2633/horizontal_tactic.rs b/src/tools/rustfmt/tests/target/alignment_2633/horizontal_tactic.rs similarity index 100% rename from tests/target/alignment_2633/horizontal_tactic.rs rename to src/tools/rustfmt/tests/target/alignment_2633/horizontal_tactic.rs diff --git a/tests/target/alignment_2633/visual_style.rs b/src/tools/rustfmt/tests/target/alignment_2633/visual_style.rs similarity index 100% rename from tests/target/alignment_2633/visual_style.rs rename to src/tools/rustfmt/tests/target/alignment_2633/visual_style.rs diff --git a/tests/target/array_comment.rs b/src/tools/rustfmt/tests/target/array_comment.rs similarity index 100% rename from tests/target/array_comment.rs rename to src/tools/rustfmt/tests/target/array_comment.rs diff --git a/tests/target/arrow_in_comments/arrow_in_single_comment.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs similarity index 100% rename from tests/target/arrow_in_comments/arrow_in_single_comment.rs rename to src/tools/rustfmt/tests/target/arrow_in_comments/arrow_in_single_comment.rs diff --git a/tests/target/arrow_in_comments/multiple_arrows.rs b/src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs similarity index 100% rename from tests/target/arrow_in_comments/multiple_arrows.rs rename to src/tools/rustfmt/tests/target/arrow_in_comments/multiple_arrows.rs diff --git a/tests/target/assignment.rs b/src/tools/rustfmt/tests/target/assignment.rs similarity index 100% rename from tests/target/assignment.rs rename to src/tools/rustfmt/tests/target/assignment.rs diff --git a/tests/target/associated-items.rs b/src/tools/rustfmt/tests/target/associated-items.rs similarity index 100% rename from tests/target/associated-items.rs rename to src/tools/rustfmt/tests/target/associated-items.rs diff --git a/tests/target/associated-types-bounds-wrapping.rs b/src/tools/rustfmt/tests/target/associated-types-bounds-wrapping.rs similarity index 100% rename from tests/target/associated-types-bounds-wrapping.rs rename to src/tools/rustfmt/tests/target/associated-types-bounds-wrapping.rs diff --git a/tests/target/associated_type_bounds.rs b/src/tools/rustfmt/tests/target/associated_type_bounds.rs similarity index 100% rename from tests/target/associated_type_bounds.rs rename to src/tools/rustfmt/tests/target/associated_type_bounds.rs diff --git a/tests/target/associated_type_defaults.rs b/src/tools/rustfmt/tests/target/associated_type_defaults.rs similarity index 100% rename from tests/target/associated_type_defaults.rs rename to src/tools/rustfmt/tests/target/associated_type_defaults.rs diff --git a/tests/target/async_block.rs b/src/tools/rustfmt/tests/target/async_block.rs similarity index 100% rename from tests/target/async_block.rs rename to src/tools/rustfmt/tests/target/async_block.rs diff --git a/tests/target/async_closure.rs b/src/tools/rustfmt/tests/target/async_closure.rs similarity index 100% rename from tests/target/async_closure.rs rename to src/tools/rustfmt/tests/target/async_closure.rs diff --git a/tests/target/async_fn.rs b/src/tools/rustfmt/tests/target/async_fn.rs similarity index 100% rename from tests/target/async_fn.rs rename to src/tools/rustfmt/tests/target/async_fn.rs diff --git a/tests/target/asyncness.rs b/src/tools/rustfmt/tests/target/asyncness.rs similarity index 100% rename from tests/target/asyncness.rs rename to src/tools/rustfmt/tests/target/asyncness.rs diff --git a/tests/target/attrib-block-expr.rs b/src/tools/rustfmt/tests/target/attrib-block-expr.rs similarity index 100% rename from tests/target/attrib-block-expr.rs rename to src/tools/rustfmt/tests/target/attrib-block-expr.rs diff --git a/tests/target/attrib-extern-crate.rs b/src/tools/rustfmt/tests/target/attrib-extern-crate.rs similarity index 100% rename from tests/target/attrib-extern-crate.rs rename to src/tools/rustfmt/tests/target/attrib-extern-crate.rs diff --git a/tests/target/attrib.rs b/src/tools/rustfmt/tests/target/attrib.rs similarity index 100% rename from tests/target/attrib.rs rename to src/tools/rustfmt/tests/target/attrib.rs diff --git a/tests/target/big-impl-block.rs b/src/tools/rustfmt/tests/target/big-impl-block.rs similarity index 100% rename from tests/target/big-impl-block.rs rename to src/tools/rustfmt/tests/target/big-impl-block.rs diff --git a/tests/target/big-impl-visual.rs b/src/tools/rustfmt/tests/target/big-impl-visual.rs similarity index 100% rename from tests/target/big-impl-visual.rs rename to src/tools/rustfmt/tests/target/big-impl-visual.rs diff --git a/tests/target/binary-expr.rs b/src/tools/rustfmt/tests/target/binary-expr.rs similarity index 100% rename from tests/target/binary-expr.rs rename to src/tools/rustfmt/tests/target/binary-expr.rs diff --git a/tests/target/binop-separator-back/bitwise.rs b/src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs similarity index 100% rename from tests/target/binop-separator-back/bitwise.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/bitwise.rs diff --git a/tests/target/binop-separator-back/comp.rs b/src/tools/rustfmt/tests/target/binop-separator-back/comp.rs similarity index 100% rename from tests/target/binop-separator-back/comp.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/comp.rs diff --git a/tests/target/binop-separator-back/logic.rs b/src/tools/rustfmt/tests/target/binop-separator-back/logic.rs similarity index 100% rename from tests/target/binop-separator-back/logic.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/logic.rs diff --git a/tests/target/binop-separator-back/math.rs b/src/tools/rustfmt/tests/target/binop-separator-back/math.rs similarity index 100% rename from tests/target/binop-separator-back/math.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/math.rs diff --git a/tests/target/binop-separator-back/patterns.rs b/src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs similarity index 100% rename from tests/target/binop-separator-back/patterns.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/patterns.rs diff --git a/tests/target/binop-separator-back/range.rs b/src/tools/rustfmt/tests/target/binop-separator-back/range.rs similarity index 100% rename from tests/target/binop-separator-back/range.rs rename to src/tools/rustfmt/tests/target/binop-separator-back/range.rs diff --git a/tests/target/break-and-continue.rs b/src/tools/rustfmt/tests/target/break-and-continue.rs similarity index 100% rename from tests/target/break-and-continue.rs rename to src/tools/rustfmt/tests/target/break-and-continue.rs diff --git a/tests/target/catch.rs b/src/tools/rustfmt/tests/target/catch.rs similarity index 100% rename from tests/target/catch.rs rename to src/tools/rustfmt/tests/target/catch.rs diff --git a/tests/target/cfg_attribute_in_where.rs b/src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs similarity index 100% rename from tests/target/cfg_attribute_in_where.rs rename to src/tools/rustfmt/tests/target/cfg_attribute_in_where.rs diff --git a/tests/target/cfg_if/detect/arch/aarch64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/aarch64.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/aarch64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/aarch64.rs diff --git a/tests/target/cfg_if/detect/arch/arm.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/arm.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/arm.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/arm.rs diff --git a/tests/target/cfg_if/detect/arch/mips.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/mips.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/mips.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/mips.rs diff --git a/tests/target/cfg_if/detect/arch/mips64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/mips64.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/mips64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/mips64.rs diff --git a/tests/target/cfg_if/detect/arch/powerpc.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/powerpc.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/powerpc.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/powerpc.rs diff --git a/tests/target/cfg_if/detect/arch/powerpc64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/powerpc64.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/powerpc64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/powerpc64.rs diff --git a/tests/target/cfg_if/detect/arch/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs similarity index 100% rename from tests/target/cfg_if/detect/arch/x86.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/arch/x86.rs diff --git a/tests/target/cfg_if/detect/bit.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/bit.rs similarity index 100% rename from tests/target/cfg_if/detect/bit.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/bit.rs diff --git a/tests/target/cfg_if/detect/cache.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/cache.rs similarity index 100% rename from tests/target/cfg_if/detect/cache.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/cache.rs diff --git a/tests/target/cfg_if/detect/error_macros.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/error_macros.rs similarity index 100% rename from tests/target/cfg_if/detect/error_macros.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/error_macros.rs diff --git a/tests/target/cfg_if/detect/mod.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/mod.rs similarity index 100% rename from tests/target/cfg_if/detect/mod.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/mod.rs diff --git a/tests/target/cfg_if/detect/os/aarch64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/aarch64.rs similarity index 100% rename from tests/target/cfg_if/detect/os/aarch64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/aarch64.rs diff --git a/tests/target/cfg_if/detect/os/freebsd/aarch64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/aarch64.rs similarity index 100% rename from tests/target/cfg_if/detect/os/freebsd/aarch64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/aarch64.rs diff --git a/tests/target/cfg_if/detect/os/freebsd/arm.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/arm.rs similarity index 100% rename from tests/target/cfg_if/detect/os/freebsd/arm.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/arm.rs diff --git a/tests/target/cfg_if/detect/os/freebsd/auxvec.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/auxvec.rs similarity index 100% rename from tests/target/cfg_if/detect/os/freebsd/auxvec.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/auxvec.rs diff --git a/tests/target/cfg_if/detect/os/freebsd/mod.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/mod.rs similarity index 100% rename from tests/target/cfg_if/detect/os/freebsd/mod.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/mod.rs diff --git a/tests/target/cfg_if/detect/os/freebsd/powerpc.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/powerpc.rs similarity index 100% rename from tests/target/cfg_if/detect/os/freebsd/powerpc.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/freebsd/powerpc.rs diff --git a/tests/target/cfg_if/detect/os/linux/aarch64.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/aarch64.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/aarch64.rs diff --git a/tests/target/cfg_if/detect/os/linux/arm.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/arm.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/arm.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/arm.rs diff --git a/tests/target/cfg_if/detect/os/linux/auxvec.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/auxvec.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/auxvec.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/auxvec.rs diff --git a/tests/target/cfg_if/detect/os/linux/cpuinfo.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/cpuinfo.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/cpuinfo.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/cpuinfo.rs diff --git a/tests/target/cfg_if/detect/os/linux/mips.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/mips.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/mips.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/mips.rs diff --git a/tests/target/cfg_if/detect/os/linux/mod.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/mod.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/mod.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/mod.rs diff --git a/tests/target/cfg_if/detect/os/linux/powerpc.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/powerpc.rs similarity index 100% rename from tests/target/cfg_if/detect/os/linux/powerpc.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/linux/powerpc.rs diff --git a/tests/target/cfg_if/detect/os/other.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/other.rs similarity index 100% rename from tests/target/cfg_if/detect/os/other.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/other.rs diff --git a/tests/target/cfg_if/detect/os/x86.rs b/src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs similarity index 100% rename from tests/target/cfg_if/detect/os/x86.rs rename to src/tools/rustfmt/tests/target/cfg_if/detect/os/x86.rs diff --git a/tests/target/cfg_if/lib.rs b/src/tools/rustfmt/tests/target/cfg_if/lib.rs similarity index 100% rename from tests/target/cfg_if/lib.rs rename to src/tools/rustfmt/tests/target/cfg_if/lib.rs diff --git a/tests/target/cfg_if/mod.rs b/src/tools/rustfmt/tests/target/cfg_if/mod.rs similarity index 100% rename from tests/target/cfg_if/mod.rs rename to src/tools/rustfmt/tests/target/cfg_if/mod.rs diff --git a/tests/target/cfg_mod/bar.rs b/src/tools/rustfmt/tests/target/cfg_mod/bar.rs similarity index 100% rename from tests/target/cfg_mod/bar.rs rename to src/tools/rustfmt/tests/target/cfg_mod/bar.rs diff --git a/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs b/src/tools/rustfmt/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs similarity index 100% rename from tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs rename to src/tools/rustfmt/tests/target/cfg_mod/dir/dir1/dir2/wasm32.rs diff --git a/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs b/src/tools/rustfmt/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs similarity index 100% rename from tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs rename to src/tools/rustfmt/tests/target/cfg_mod/dir/dir1/dir3/wasm32.rs diff --git a/tests/target/cfg_mod/foo.rs b/src/tools/rustfmt/tests/target/cfg_mod/foo.rs similarity index 100% rename from tests/target/cfg_mod/foo.rs rename to src/tools/rustfmt/tests/target/cfg_mod/foo.rs diff --git a/tests/target/cfg_mod/mod.rs b/src/tools/rustfmt/tests/target/cfg_mod/mod.rs similarity index 100% rename from tests/target/cfg_mod/mod.rs rename to src/tools/rustfmt/tests/target/cfg_mod/mod.rs diff --git a/tests/target/cfg_mod/other.rs b/src/tools/rustfmt/tests/target/cfg_mod/other.rs similarity index 100% rename from tests/target/cfg_mod/other.rs rename to src/tools/rustfmt/tests/target/cfg_mod/other.rs diff --git a/tests/target/cfg_mod/wasm32.rs b/src/tools/rustfmt/tests/target/cfg_mod/wasm32.rs similarity index 100% rename from tests/target/cfg_mod/wasm32.rs rename to src/tools/rustfmt/tests/target/cfg_mod/wasm32.rs diff --git a/tests/target/cfg_select.rs b/src/tools/rustfmt/tests/target/cfg_select.rs similarity index 100% rename from tests/target/cfg_select.rs rename to src/tools/rustfmt/tests/target/cfg_select.rs diff --git a/tests/target/cfg_select/format_me_please_1.rs b/src/tools/rustfmt/tests/target/cfg_select/format_me_please_1.rs similarity index 100% rename from tests/target/cfg_select/format_me_please_1.rs rename to src/tools/rustfmt/tests/target/cfg_select/format_me_please_1.rs diff --git a/tests/target/cfg_select/format_me_please_2.rs b/src/tools/rustfmt/tests/target/cfg_select/format_me_please_2.rs similarity index 100% rename from tests/target/cfg_select/format_me_please_2.rs rename to src/tools/rustfmt/tests/target/cfg_select/format_me_please_2.rs diff --git a/tests/target/cfg_select/format_me_please_3.rs b/src/tools/rustfmt/tests/target/cfg_select/format_me_please_3.rs similarity index 100% rename from tests/target/cfg_select/format_me_please_3.rs rename to src/tools/rustfmt/tests/target/cfg_select/format_me_please_3.rs diff --git a/tests/target/cfg_select/format_me_please_4.rs b/src/tools/rustfmt/tests/target/cfg_select/format_me_please_4.rs similarity index 100% rename from tests/target/cfg_select/format_me_please_4.rs rename to src/tools/rustfmt/tests/target/cfg_select/format_me_please_4.rs diff --git a/tests/target/cfg_select/lib.rs b/src/tools/rustfmt/tests/target/cfg_select/lib.rs similarity index 100% rename from tests/target/cfg_select/lib.rs rename to src/tools/rustfmt/tests/target/cfg_select/lib.rs diff --git a/tests/target/cfg_select/lib2.rs b/src/tools/rustfmt/tests/target/cfg_select/lib2.rs similarity index 100% rename from tests/target/cfg_select/lib2.rs rename to src/tools/rustfmt/tests/target/cfg_select/lib2.rs diff --git a/tests/target/cfg_select_stable.rs b/src/tools/rustfmt/tests/target/cfg_select_stable.rs similarity index 100% rename from tests/target/cfg_select_stable.rs rename to src/tools/rustfmt/tests/target/cfg_select_stable.rs diff --git a/tests/target/chain_yield_with_comments.rs b/src/tools/rustfmt/tests/target/chain_yield_with_comments.rs similarity index 100% rename from tests/target/chain_yield_with_comments.rs rename to src/tools/rustfmt/tests/target/chain_yield_with_comments.rs diff --git a/tests/target/chains-visual.rs b/src/tools/rustfmt/tests/target/chains-visual.rs similarity index 100% rename from tests/target/chains-visual.rs rename to src/tools/rustfmt/tests/target/chains-visual.rs diff --git a/tests/target/chains.rs b/src/tools/rustfmt/tests/target/chains.rs similarity index 100% rename from tests/target/chains.rs rename to src/tools/rustfmt/tests/target/chains.rs diff --git a/tests/target/chains_with_comment.rs b/src/tools/rustfmt/tests/target/chains_with_comment.rs similarity index 100% rename from tests/target/chains_with_comment.rs rename to src/tools/rustfmt/tests/target/chains_with_comment.rs diff --git a/tests/target/closure-block-inside-macro.rs b/src/tools/rustfmt/tests/target/closure-block-inside-macro.rs similarity index 100% rename from tests/target/closure-block-inside-macro.rs rename to src/tools/rustfmt/tests/target/closure-block-inside-macro.rs diff --git a/tests/target/closure-block-labels.rs b/src/tools/rustfmt/tests/target/closure-block-labels.rs similarity index 100% rename from tests/target/closure-block-labels.rs rename to src/tools/rustfmt/tests/target/closure-block-labels.rs diff --git a/tests/target/closure.rs b/src/tools/rustfmt/tests/target/closure.rs similarity index 100% rename from tests/target/closure.rs rename to src/tools/rustfmt/tests/target/closure.rs diff --git a/tests/target/comment-inside-const.rs b/src/tools/rustfmt/tests/target/comment-inside-const.rs similarity index 100% rename from tests/target/comment-inside-const.rs rename to src/tools/rustfmt/tests/target/comment-inside-const.rs diff --git a/tests/target/comment-not-disappear.rs b/src/tools/rustfmt/tests/target/comment-not-disappear.rs similarity index 100% rename from tests/target/comment-not-disappear.rs rename to src/tools/rustfmt/tests/target/comment-not-disappear.rs diff --git a/tests/target/comment.rs b/src/tools/rustfmt/tests/target/comment.rs similarity index 100% rename from tests/target/comment.rs rename to src/tools/rustfmt/tests/target/comment.rs diff --git a/tests/target/comment2.rs b/src/tools/rustfmt/tests/target/comment2.rs similarity index 100% rename from tests/target/comment2.rs rename to src/tools/rustfmt/tests/target/comment2.rs diff --git a/tests/target/comment3.rs b/src/tools/rustfmt/tests/target/comment3.rs similarity index 100% rename from tests/target/comment3.rs rename to src/tools/rustfmt/tests/target/comment3.rs diff --git a/tests/target/comment4.rs b/src/tools/rustfmt/tests/target/comment4.rs similarity index 100% rename from tests/target/comment4.rs rename to src/tools/rustfmt/tests/target/comment4.rs diff --git a/tests/target/comment5.rs b/src/tools/rustfmt/tests/target/comment5.rs similarity index 100% rename from tests/target/comment5.rs rename to src/tools/rustfmt/tests/target/comment5.rs diff --git a/tests/target/comment6.rs b/src/tools/rustfmt/tests/target/comment6.rs similarity index 100% rename from tests/target/comment6.rs rename to src/tools/rustfmt/tests/target/comment6.rs diff --git a/tests/target/comment_crlf_newline.rs b/src/tools/rustfmt/tests/target/comment_crlf_newline.rs similarity index 100% rename from tests/target/comment_crlf_newline.rs rename to src/tools/rustfmt/tests/target/comment_crlf_newline.rs diff --git a/tests/target/comments-fn.rs b/src/tools/rustfmt/tests/target/comments-fn.rs similarity index 100% rename from tests/target/comments-fn.rs rename to src/tools/rustfmt/tests/target/comments-fn.rs diff --git a/tests/target/comments-in-lists/format-doc-comments.rs b/src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs similarity index 100% rename from tests/target/comments-in-lists/format-doc-comments.rs rename to src/tools/rustfmt/tests/target/comments-in-lists/format-doc-comments.rs diff --git a/tests/target/comments-in-lists/wrap-comments-false.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs similarity index 100% rename from tests/target/comments-in-lists/wrap-comments-false.rs rename to src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-false.rs diff --git a/tests/target/comments-in-lists/wrap-comments-not-normalized.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs similarity index 100% rename from tests/target/comments-in-lists/wrap-comments-not-normalized.rs rename to src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-not-normalized.rs diff --git a/tests/target/comments-in-lists/wrap-comments-true.rs b/src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs similarity index 100% rename from tests/target/comments-in-lists/wrap-comments-true.rs rename to src/tools/rustfmt/tests/target/comments-in-lists/wrap-comments-true.rs diff --git a/tests/target/comments_unicode.rs b/src/tools/rustfmt/tests/target/comments_unicode.rs similarity index 100% rename from tests/target/comments_unicode.rs rename to src/tools/rustfmt/tests/target/comments_unicode.rs diff --git a/tests/target/configs/blank_lines_lower_bound/1.rs b/src/tools/rustfmt/tests/target/configs/blank_lines_lower_bound/1.rs similarity index 100% rename from tests/target/configs/blank_lines_lower_bound/1.rs rename to src/tools/rustfmt/tests/target/configs/blank_lines_lower_bound/1.rs diff --git a/tests/target/configs/blank_lines_upper_bound/1.rs b/src/tools/rustfmt/tests/target/configs/blank_lines_upper_bound/1.rs similarity index 100% rename from tests/target/configs/blank_lines_upper_bound/1.rs rename to src/tools/rustfmt/tests/target/configs/blank_lines_upper_bound/1.rs diff --git a/tests/target/configs/blank_lines_upper_bound/2.rs b/src/tools/rustfmt/tests/target/configs/blank_lines_upper_bound/2.rs similarity index 100% rename from tests/target/configs/blank_lines_upper_bound/2.rs rename to src/tools/rustfmt/tests/target/configs/blank_lines_upper_bound/2.rs diff --git a/tests/target/configs/brace_style/fn_always_next_line.rs b/src/tools/rustfmt/tests/target/configs/brace_style/fn_always_next_line.rs similarity index 100% rename from tests/target/configs/brace_style/fn_always_next_line.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/fn_always_next_line.rs diff --git a/tests/target/configs/brace_style/fn_prefer_same_line.rs b/src/tools/rustfmt/tests/target/configs/brace_style/fn_prefer_same_line.rs similarity index 100% rename from tests/target/configs/brace_style/fn_prefer_same_line.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/fn_prefer_same_line.rs diff --git a/tests/target/configs/brace_style/fn_same_line_where.rs b/src/tools/rustfmt/tests/target/configs/brace_style/fn_same_line_where.rs similarity index 100% rename from tests/target/configs/brace_style/fn_same_line_where.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/fn_same_line_where.rs diff --git a/tests/target/configs/brace_style/item_always_next_line.rs b/src/tools/rustfmt/tests/target/configs/brace_style/item_always_next_line.rs similarity index 100% rename from tests/target/configs/brace_style/item_always_next_line.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/item_always_next_line.rs diff --git a/tests/target/configs/brace_style/item_prefer_same_line.rs b/src/tools/rustfmt/tests/target/configs/brace_style/item_prefer_same_line.rs similarity index 100% rename from tests/target/configs/brace_style/item_prefer_same_line.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/item_prefer_same_line.rs diff --git a/tests/target/configs/brace_style/item_same_line_where.rs b/src/tools/rustfmt/tests/target/configs/brace_style/item_same_line_where.rs similarity index 100% rename from tests/target/configs/brace_style/item_same_line_where.rs rename to src/tools/rustfmt/tests/target/configs/brace_style/item_same_line_where.rs diff --git a/tests/target/configs/chain_width/always.rs b/src/tools/rustfmt/tests/target/configs/chain_width/always.rs similarity index 100% rename from tests/target/configs/chain_width/always.rs rename to src/tools/rustfmt/tests/target/configs/chain_width/always.rs diff --git a/tests/target/configs/chain_width/small.rs b/src/tools/rustfmt/tests/target/configs/chain_width/small.rs similarity index 100% rename from tests/target/configs/chain_width/small.rs rename to src/tools/rustfmt/tests/target/configs/chain_width/small.rs diff --git a/tests/target/configs/chain_width/tiny.rs b/src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs similarity index 100% rename from tests/target/configs/chain_width/tiny.rs rename to src/tools/rustfmt/tests/target/configs/chain_width/tiny.rs diff --git a/tests/target/configs/combine_control_expr/false.rs b/src/tools/rustfmt/tests/target/configs/combine_control_expr/false.rs similarity index 100% rename from tests/target/configs/combine_control_expr/false.rs rename to src/tools/rustfmt/tests/target/configs/combine_control_expr/false.rs diff --git a/tests/target/configs/combine_control_expr/true.rs b/src/tools/rustfmt/tests/target/configs/combine_control_expr/true.rs similarity index 100% rename from tests/target/configs/combine_control_expr/true.rs rename to src/tools/rustfmt/tests/target/configs/combine_control_expr/true.rs diff --git a/tests/target/configs/comment_width/above.rs b/src/tools/rustfmt/tests/target/configs/comment_width/above.rs similarity index 100% rename from tests/target/configs/comment_width/above.rs rename to src/tools/rustfmt/tests/target/configs/comment_width/above.rs diff --git a/tests/target/configs/comment_width/below.rs b/src/tools/rustfmt/tests/target/configs/comment_width/below.rs similarity index 100% rename from tests/target/configs/comment_width/below.rs rename to src/tools/rustfmt/tests/target/configs/comment_width/below.rs diff --git a/tests/target/configs/comment_width/ignore.rs b/src/tools/rustfmt/tests/target/configs/comment_width/ignore.rs similarity index 100% rename from tests/target/configs/comment_width/ignore.rs rename to src/tools/rustfmt/tests/target/configs/comment_width/ignore.rs diff --git a/tests/target/configs/condense_wildcard_suffixes/false.rs b/src/tools/rustfmt/tests/target/configs/condense_wildcard_suffixes/false.rs similarity index 100% rename from tests/target/configs/condense_wildcard_suffixes/false.rs rename to src/tools/rustfmt/tests/target/configs/condense_wildcard_suffixes/false.rs diff --git a/tests/target/configs/condense_wildcard_suffixes/true.rs b/src/tools/rustfmt/tests/target/configs/condense_wildcard_suffixes/true.rs similarity index 100% rename from tests/target/configs/condense_wildcard_suffixes/true.rs rename to src/tools/rustfmt/tests/target/configs/condense_wildcard_suffixes/true.rs diff --git a/tests/target/configs/control_brace_style/always_next_line.rs b/src/tools/rustfmt/tests/target/configs/control_brace_style/always_next_line.rs similarity index 100% rename from tests/target/configs/control_brace_style/always_next_line.rs rename to src/tools/rustfmt/tests/target/configs/control_brace_style/always_next_line.rs diff --git a/tests/target/configs/control_brace_style/always_same_line.rs b/src/tools/rustfmt/tests/target/configs/control_brace_style/always_same_line.rs similarity index 100% rename from tests/target/configs/control_brace_style/always_same_line.rs rename to src/tools/rustfmt/tests/target/configs/control_brace_style/always_same_line.rs diff --git a/tests/target/configs/control_brace_style/closing_next_line.rs b/src/tools/rustfmt/tests/target/configs/control_brace_style/closing_next_line.rs similarity index 100% rename from tests/target/configs/control_brace_style/closing_next_line.rs rename to src/tools/rustfmt/tests/target/configs/control_brace_style/closing_next_line.rs diff --git a/tests/target/configs/disable_all_formatting/false.rs b/src/tools/rustfmt/tests/target/configs/disable_all_formatting/false.rs similarity index 100% rename from tests/target/configs/disable_all_formatting/false.rs rename to src/tools/rustfmt/tests/target/configs/disable_all_formatting/false.rs diff --git a/tests/target/configs/disable_all_formatting/true.rs b/src/tools/rustfmt/tests/target/configs/disable_all_formatting/true.rs similarity index 100% rename from tests/target/configs/disable_all_formatting/true.rs rename to src/tools/rustfmt/tests/target/configs/disable_all_formatting/true.rs diff --git a/tests/target/configs/doc_comment_code_block_small_heuristics/default-to-max.rs b/src/tools/rustfmt/tests/target/configs/doc_comment_code_block_small_heuristics/default-to-max.rs similarity index 100% rename from tests/target/configs/doc_comment_code_block_small_heuristics/default-to-max.rs rename to src/tools/rustfmt/tests/target/configs/doc_comment_code_block_small_heuristics/default-to-max.rs diff --git a/tests/target/configs/doc_comment_code_block_small_heuristics/max-to-default.rs b/src/tools/rustfmt/tests/target/configs/doc_comment_code_block_small_heuristics/max-to-default.rs similarity index 100% rename from tests/target/configs/doc_comment_code_block_small_heuristics/max-to-default.rs rename to src/tools/rustfmt/tests/target/configs/doc_comment_code_block_small_heuristics/max-to-default.rs diff --git a/tests/target/configs/doc_comment_code_block_width/100.rs b/src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/100.rs similarity index 100% rename from tests/target/configs/doc_comment_code_block_width/100.rs rename to src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/100.rs diff --git a/tests/target/configs/doc_comment_code_block_width/100_greater_max_width.rs b/src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/100_greater_max_width.rs similarity index 100% rename from tests/target/configs/doc_comment_code_block_width/100_greater_max_width.rs rename to src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/100_greater_max_width.rs diff --git a/tests/target/configs/doc_comment_code_block_width/50.rs b/src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/50.rs similarity index 100% rename from tests/target/configs/doc_comment_code_block_width/50.rs rename to src/tools/rustfmt/tests/target/configs/doc_comment_code_block_width/50.rs diff --git a/tests/target/configs/empty_item_single_line/false.rs b/src/tools/rustfmt/tests/target/configs/empty_item_single_line/false.rs similarity index 100% rename from tests/target/configs/empty_item_single_line/false.rs rename to src/tools/rustfmt/tests/target/configs/empty_item_single_line/false.rs diff --git a/tests/target/configs/empty_item_single_line/true.rs b/src/tools/rustfmt/tests/target/configs/empty_item_single_line/true.rs similarity index 100% rename from tests/target/configs/empty_item_single_line/true.rs rename to src/tools/rustfmt/tests/target/configs/empty_item_single_line/true.rs diff --git a/tests/target/configs/enum_discrim_align_threshold/40.rs b/src/tools/rustfmt/tests/target/configs/enum_discrim_align_threshold/40.rs similarity index 100% rename from tests/target/configs/enum_discrim_align_threshold/40.rs rename to src/tools/rustfmt/tests/target/configs/enum_discrim_align_threshold/40.rs diff --git a/tests/target/configs/error_on_line_overflow/false.rs b/src/tools/rustfmt/tests/target/configs/error_on_line_overflow/false.rs similarity index 100% rename from tests/target/configs/error_on_line_overflow/false.rs rename to src/tools/rustfmt/tests/target/configs/error_on_line_overflow/false.rs diff --git a/tests/target/configs/error_on_unformatted/false.rs b/src/tools/rustfmt/tests/target/configs/error_on_unformatted/false.rs similarity index 100% rename from tests/target/configs/error_on_unformatted/false.rs rename to src/tools/rustfmt/tests/target/configs/error_on_unformatted/false.rs diff --git a/tests/target/configs/float_literal_trailing_zero/always.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/always.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/always.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/always.rs diff --git a/tests/target/configs/float_literal_trailing_zero/always_spaces_around_ranges_true.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/always_spaces_around_ranges_true.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/always_spaces_around_ranges_true.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/always_spaces_around_ranges_true.rs diff --git a/tests/target/configs/float_literal_trailing_zero/if-no-postfix.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/if-no-postfix.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/if-no-postfix.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/if-no-postfix.rs diff --git a/tests/target/configs/float_literal_trailing_zero/if-no-postfix_spaces_around_ranges_true.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/if-no-postfix_spaces_around_ranges_true.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/if-no-postfix_spaces_around_ranges_true.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/if-no-postfix_spaces_around_ranges_true.rs diff --git a/tests/target/configs/float_literal_trailing_zero/never.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/never.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/never.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/never.rs diff --git a/tests/target/configs/float_literal_trailing_zero/never_spaces_around_ranges_true.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/never_spaces_around_ranges_true.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/never_spaces_around_ranges_true.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/never_spaces_around_ranges_true.rs diff --git a/tests/target/configs/float_literal_trailing_zero/preserve.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/preserve.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/preserve.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/preserve.rs diff --git a/tests/target/configs/float_literal_trailing_zero/preserve_spaces_around_ranges_true.rs b/src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/preserve_spaces_around_ranges_true.rs similarity index 100% rename from tests/target/configs/float_literal_trailing_zero/preserve_spaces_around_ranges_true.rs rename to src/tools/rustfmt/tests/target/configs/float_literal_trailing_zero/preserve_spaces_around_ranges_true.rs diff --git a/tests/target/configs/fn_params_layout/compressed.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs similarity index 100% rename from tests/target/configs/fn_params_layout/compressed.rs rename to src/tools/rustfmt/tests/target/configs/fn_params_layout/compressed.rs diff --git a/tests/target/configs/fn_params_layout/tall.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs similarity index 100% rename from tests/target/configs/fn_params_layout/tall.rs rename to src/tools/rustfmt/tests/target/configs/fn_params_layout/tall.rs diff --git a/tests/target/configs/fn_params_layout/vertical.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs similarity index 100% rename from tests/target/configs/fn_params_layout/vertical.rs rename to src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical.rs diff --git a/tests/target/configs/fn_params_layout/vertical_style_2027.rs b/src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical_style_2027.rs similarity index 100% rename from tests/target/configs/fn_params_layout/vertical_style_2027.rs rename to src/tools/rustfmt/tests/target/configs/fn_params_layout/vertical_style_2027.rs diff --git a/tests/target/configs/fn_single_line/false.rs b/src/tools/rustfmt/tests/target/configs/fn_single_line/false.rs similarity index 100% rename from tests/target/configs/fn_single_line/false.rs rename to src/tools/rustfmt/tests/target/configs/fn_single_line/false.rs diff --git a/tests/target/configs/fn_single_line/true.rs b/src/tools/rustfmt/tests/target/configs/fn_single_line/true.rs similarity index 100% rename from tests/target/configs/fn_single_line/true.rs rename to src/tools/rustfmt/tests/target/configs/fn_single_line/true.rs diff --git a/tests/target/configs/force_explicit_abi/false.rs b/src/tools/rustfmt/tests/target/configs/force_explicit_abi/false.rs similarity index 100% rename from tests/target/configs/force_explicit_abi/false.rs rename to src/tools/rustfmt/tests/target/configs/force_explicit_abi/false.rs diff --git a/tests/target/configs/force_explicit_abi/true.rs b/src/tools/rustfmt/tests/target/configs/force_explicit_abi/true.rs similarity index 100% rename from tests/target/configs/force_explicit_abi/true.rs rename to src/tools/rustfmt/tests/target/configs/force_explicit_abi/true.rs diff --git a/tests/target/configs/force_multiline_block/false.rs b/src/tools/rustfmt/tests/target/configs/force_multiline_block/false.rs similarity index 100% rename from tests/target/configs/force_multiline_block/false.rs rename to src/tools/rustfmt/tests/target/configs/force_multiline_block/false.rs diff --git a/tests/target/configs/force_multiline_block/true.rs b/src/tools/rustfmt/tests/target/configs/force_multiline_block/true.rs similarity index 100% rename from tests/target/configs/force_multiline_block/true.rs rename to src/tools/rustfmt/tests/target/configs/force_multiline_block/true.rs diff --git a/tests/target/configs/format_generated_files/false.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs similarity index 100% rename from tests/target/configs/format_generated_files/false.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/false.rs diff --git a/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs similarity index 100% rename from tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_generated_marker_line_search_limit.rs diff --git a/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs similarity index 100% rename from tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_marker_out_scope_size.rs diff --git a/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs similarity index 100% rename from tests/target/configs/format_generated_files/false_with_zero_search_limit.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/false_with_zero_search_limit.rs diff --git a/tests/target/configs/format_generated_files/true.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs similarity index 100% rename from tests/target/configs/format_generated_files/true.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/true.rs diff --git a/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs similarity index 100% rename from tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_in_scope_size.rs diff --git a/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs b/src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs similarity index 100% rename from tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs rename to src/tools/rustfmt/tests/target/configs/format_generated_files/true_with_marker_not_in_header.rs diff --git a/tests/target/configs/format_macro_bodies/false.rs b/src/tools/rustfmt/tests/target/configs/format_macro_bodies/false.rs similarity index 100% rename from tests/target/configs/format_macro_bodies/false.rs rename to src/tools/rustfmt/tests/target/configs/format_macro_bodies/false.rs diff --git a/tests/target/configs/format_macro_bodies/true.rs b/src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs similarity index 100% rename from tests/target/configs/format_macro_bodies/true.rs rename to src/tools/rustfmt/tests/target/configs/format_macro_bodies/true.rs diff --git a/tests/target/configs/format_macro_matchers/false.rs b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs similarity index 100% rename from tests/target/configs/format_macro_matchers/false.rs rename to src/tools/rustfmt/tests/target/configs/format_macro_matchers/false.rs diff --git a/tests/target/configs/format_macro_matchers/true.rs b/src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs similarity index 100% rename from tests/target/configs/format_macro_matchers/true.rs rename to src/tools/rustfmt/tests/target/configs/format_macro_matchers/true.rs diff --git a/tests/target/configs/format_strings/false.rs b/src/tools/rustfmt/tests/target/configs/format_strings/false.rs similarity index 100% rename from tests/target/configs/format_strings/false.rs rename to src/tools/rustfmt/tests/target/configs/format_strings/false.rs diff --git a/tests/target/configs/format_strings/true.rs b/src/tools/rustfmt/tests/target/configs/format_strings/true.rs similarity index 100% rename from tests/target/configs/format_strings/true.rs rename to src/tools/rustfmt/tests/target/configs/format_strings/true.rs diff --git a/tests/target/configs/group_imports/One-merge_imports.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs similarity index 100% rename from tests/target/configs/group_imports/One-merge_imports.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/One-merge_imports.rs diff --git a/tests/target/configs/group_imports/One-nested.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs similarity index 100% rename from tests/target/configs/group_imports/One-nested.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/One-nested.rs diff --git a/tests/target/configs/group_imports/One-no_reorder.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs similarity index 100% rename from tests/target/configs/group_imports/One-no_reorder.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/One-no_reorder.rs diff --git a/tests/target/configs/group_imports/One.rs b/src/tools/rustfmt/tests/target/configs/group_imports/One.rs similarity index 100% rename from tests/target/configs/group_imports/One.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/One.rs diff --git a/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs similarity index 100% rename from tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-merge_imports.rs diff --git a/tests/target/configs/group_imports/StdExternalCrate-nested.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-nested.rs similarity index 100% rename from tests/target/configs/group_imports/StdExternalCrate-nested.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-nested.rs diff --git a/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs similarity index 100% rename from tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-no_reorder.rs diff --git a/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs similarity index 100% rename from tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate-non_consecutive.rs diff --git a/tests/target/configs/group_imports/StdExternalCrate.rs b/src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate.rs similarity index 100% rename from tests/target/configs/group_imports/StdExternalCrate.rs rename to src/tools/rustfmt/tests/target/configs/group_imports/StdExternalCrate.rs diff --git a/tests/target/configs/hard_tabs/false.rs b/src/tools/rustfmt/tests/target/configs/hard_tabs/false.rs similarity index 100% rename from tests/target/configs/hard_tabs/false.rs rename to src/tools/rustfmt/tests/target/configs/hard_tabs/false.rs diff --git a/tests/target/configs/hard_tabs/true.rs b/src/tools/rustfmt/tests/target/configs/hard_tabs/true.rs similarity index 100% rename from tests/target/configs/hard_tabs/true.rs rename to src/tools/rustfmt/tests/target/configs/hard_tabs/true.rs diff --git a/tests/target/configs/hex_literal_case/hex_literal_lower.rs b/src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_lower.rs similarity index 100% rename from tests/target/configs/hex_literal_case/hex_literal_lower.rs rename to src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_lower.rs diff --git a/tests/target/configs/hex_literal_case/hex_literal_preserve.rs b/src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_preserve.rs similarity index 100% rename from tests/target/configs/hex_literal_case/hex_literal_preserve.rs rename to src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_preserve.rs diff --git a/tests/target/configs/hex_literal_case/hex_literal_upper.rs b/src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_upper.rs similarity index 100% rename from tests/target/configs/hex_literal_case/hex_literal_upper.rs rename to src/tools/rustfmt/tests/target/configs/hex_literal_case/hex_literal_upper.rs diff --git a/tests/target/configs/imports_indent/block.rs b/src/tools/rustfmt/tests/target/configs/imports_indent/block.rs similarity index 100% rename from tests/target/configs/imports_indent/block.rs rename to src/tools/rustfmt/tests/target/configs/imports_indent/block.rs diff --git a/tests/target/configs/imports_layout/horizontal_vertical.rs b/src/tools/rustfmt/tests/target/configs/imports_layout/horizontal_vertical.rs similarity index 100% rename from tests/target/configs/imports_layout/horizontal_vertical.rs rename to src/tools/rustfmt/tests/target/configs/imports_layout/horizontal_vertical.rs diff --git a/tests/target/configs/imports_layout/merge_mixed.rs b/src/tools/rustfmt/tests/target/configs/imports_layout/merge_mixed.rs similarity index 100% rename from tests/target/configs/imports_layout/merge_mixed.rs rename to src/tools/rustfmt/tests/target/configs/imports_layout/merge_mixed.rs diff --git a/tests/target/configs/imports_layout/mixed.rs b/src/tools/rustfmt/tests/target/configs/imports_layout/mixed.rs similarity index 100% rename from tests/target/configs/imports_layout/mixed.rs rename to src/tools/rustfmt/tests/target/configs/imports_layout/mixed.rs diff --git a/tests/target/configs/indent_style/block_args.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_args.rs similarity index 100% rename from tests/target/configs/indent_style/block_args.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_args.rs diff --git a/tests/target/configs/indent_style/block_array.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_array.rs similarity index 100% rename from tests/target/configs/indent_style/block_array.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_array.rs diff --git a/tests/target/configs/indent_style/block_call.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_call.rs similarity index 100% rename from tests/target/configs/indent_style/block_call.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_call.rs diff --git a/tests/target/configs/indent_style/block_chain.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_chain.rs similarity index 100% rename from tests/target/configs/indent_style/block_chain.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_chain.rs diff --git a/tests/target/configs/indent_style/block_generic.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_generic.rs similarity index 100% rename from tests/target/configs/indent_style/block_generic.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_generic.rs diff --git a/tests/target/configs/indent_style/block_struct_lit.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_struct_lit.rs similarity index 100% rename from tests/target/configs/indent_style/block_struct_lit.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_struct_lit.rs diff --git a/tests/target/configs/indent_style/block_tab_spaces_call.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_tab_spaces_call.rs similarity index 100% rename from tests/target/configs/indent_style/block_tab_spaces_call.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_tab_spaces_call.rs diff --git a/tests/target/configs/indent_style/block_trailing_comma_call/one.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs similarity index 100% rename from tests/target/configs/indent_style/block_trailing_comma_call/one.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/one.rs diff --git a/tests/target/configs/indent_style/block_trailing_comma_call/two.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs similarity index 100% rename from tests/target/configs/indent_style/block_trailing_comma_call/two.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_trailing_comma_call/two.rs diff --git a/tests/target/configs/indent_style/block_where_pred.rs b/src/tools/rustfmt/tests/target/configs/indent_style/block_where_pred.rs similarity index 100% rename from tests/target/configs/indent_style/block_where_pred.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/block_where_pred.rs diff --git a/tests/target/configs/indent_style/default.rs b/src/tools/rustfmt/tests/target/configs/indent_style/default.rs similarity index 100% rename from tests/target/configs/indent_style/default.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/default.rs diff --git a/tests/target/configs/indent_style/rfc_control.rs b/src/tools/rustfmt/tests/target/configs/indent_style/rfc_control.rs similarity index 100% rename from tests/target/configs/indent_style/rfc_control.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/rfc_control.rs diff --git a/tests/target/configs/indent_style/rfc_where.rs b/src/tools/rustfmt/tests/target/configs/indent_style/rfc_where.rs similarity index 100% rename from tests/target/configs/indent_style/rfc_where.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/rfc_where.rs diff --git a/tests/target/configs/indent_style/visual_args.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_args.rs similarity index 100% rename from tests/target/configs/indent_style/visual_args.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_args.rs diff --git a/tests/target/configs/indent_style/visual_array.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_array.rs similarity index 100% rename from tests/target/configs/indent_style/visual_array.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_array.rs diff --git a/tests/target/configs/indent_style/visual_call.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_call.rs similarity index 100% rename from tests/target/configs/indent_style/visual_call.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_call.rs diff --git a/tests/target/configs/indent_style/visual_chain.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_chain.rs similarity index 100% rename from tests/target/configs/indent_style/visual_chain.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_chain.rs diff --git a/tests/target/configs/indent_style/visual_generics.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_generics.rs similarity index 100% rename from tests/target/configs/indent_style/visual_generics.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_generics.rs diff --git a/tests/target/configs/indent_style/visual_struct_lit.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_struct_lit.rs similarity index 100% rename from tests/target/configs/indent_style/visual_struct_lit.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_struct_lit.rs diff --git a/tests/target/configs/indent_style/visual_trailing_comma.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_trailing_comma.rs similarity index 100% rename from tests/target/configs/indent_style/visual_trailing_comma.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_trailing_comma.rs diff --git a/tests/target/configs/indent_style/visual_where_pred.rs b/src/tools/rustfmt/tests/target/configs/indent_style/visual_where_pred.rs similarity index 100% rename from tests/target/configs/indent_style/visual_where_pred.rs rename to src/tools/rustfmt/tests/target/configs/indent_style/visual_where_pred.rs diff --git a/tests/target/configs/match_arm_blocks/false.rs b/src/tools/rustfmt/tests/target/configs/match_arm_blocks/false.rs similarity index 100% rename from tests/target/configs/match_arm_blocks/false.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_blocks/false.rs diff --git a/tests/target/configs/match_arm_blocks/true.rs b/src/tools/rustfmt/tests/target/configs/match_arm_blocks/true.rs similarity index 100% rename from tests/target/configs/match_arm_blocks/true.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_blocks/true.rs diff --git a/tests/target/configs/match_arm_indent/attrs.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/attrs.rs similarity index 100% rename from tests/target/configs/match_arm_indent/attrs.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/attrs.rs diff --git a/tests/target/configs/match_arm_indent/guards.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/guards.rs similarity index 100% rename from tests/target/configs/match_arm_indent/guards.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/guards.rs diff --git a/tests/target/configs/match_arm_indent/leading_pipes.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/leading_pipes.rs similarity index 100% rename from tests/target/configs/match_arm_indent/leading_pipes.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/leading_pipes.rs diff --git a/tests/target/configs/match_arm_indent/nested.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/nested.rs similarity index 100% rename from tests/target/configs/match_arm_indent/nested.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/nested.rs diff --git a/tests/target/configs/match_arm_indent/noindent-tabs.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/noindent-tabs.rs similarity index 100% rename from tests/target/configs/match_arm_indent/noindent-tabs.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/noindent-tabs.rs diff --git a/tests/target/configs/match_arm_indent/noindent.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/noindent.rs similarity index 100% rename from tests/target/configs/match_arm_indent/noindent.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/noindent.rs diff --git a/tests/target/configs/match_arm_indent/patterns.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/patterns.rs similarity index 100% rename from tests/target/configs/match_arm_indent/patterns.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/patterns.rs diff --git a/tests/target/configs/match_arm_indent/unindent.rs b/src/tools/rustfmt/tests/target/configs/match_arm_indent/unindent.rs similarity index 100% rename from tests/target/configs/match_arm_indent/unindent.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_indent/unindent.rs diff --git a/tests/target/configs/match_arm_leading_pipes/always.rs b/src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/always.rs similarity index 100% rename from tests/target/configs/match_arm_leading_pipes/always.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/always.rs diff --git a/tests/target/configs/match_arm_leading_pipes/never.rs b/src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/never.rs similarity index 100% rename from tests/target/configs/match_arm_leading_pipes/never.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/never.rs diff --git a/tests/target/configs/match_arm_leading_pipes/preserve.rs b/src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/preserve.rs similarity index 100% rename from tests/target/configs/match_arm_leading_pipes/preserve.rs rename to src/tools/rustfmt/tests/target/configs/match_arm_leading_pipes/preserve.rs diff --git a/tests/target/configs/match_block_trailing_comma/false.rs b/src/tools/rustfmt/tests/target/configs/match_block_trailing_comma/false.rs similarity index 100% rename from tests/target/configs/match_block_trailing_comma/false.rs rename to src/tools/rustfmt/tests/target/configs/match_block_trailing_comma/false.rs diff --git a/tests/target/configs/match_block_trailing_comma/true.rs b/src/tools/rustfmt/tests/target/configs/match_block_trailing_comma/true.rs similarity index 100% rename from tests/target/configs/match_block_trailing_comma/true.rs rename to src/tools/rustfmt/tests/target/configs/match_block_trailing_comma/true.rs diff --git a/tests/target/configs/merge_derives/true.rs b/src/tools/rustfmt/tests/target/configs/merge_derives/true.rs similarity index 100% rename from tests/target/configs/merge_derives/true.rs rename to src/tools/rustfmt/tests/target/configs/merge_derives/true.rs diff --git a/tests/target/configs/normalize_comments/false.rs b/src/tools/rustfmt/tests/target/configs/normalize_comments/false.rs similarity index 100% rename from tests/target/configs/normalize_comments/false.rs rename to src/tools/rustfmt/tests/target/configs/normalize_comments/false.rs diff --git a/tests/target/configs/normalize_comments/true.rs b/src/tools/rustfmt/tests/target/configs/normalize_comments/true.rs similarity index 100% rename from tests/target/configs/normalize_comments/true.rs rename to src/tools/rustfmt/tests/target/configs/normalize_comments/true.rs diff --git a/tests/target/configs/normalize_doc_attributes/false.rs b/src/tools/rustfmt/tests/target/configs/normalize_doc_attributes/false.rs similarity index 100% rename from tests/target/configs/normalize_doc_attributes/false.rs rename to src/tools/rustfmt/tests/target/configs/normalize_doc_attributes/false.rs diff --git a/tests/target/configs/normalize_doc_attributes/true.rs b/src/tools/rustfmt/tests/target/configs/normalize_doc_attributes/true.rs similarity index 100% rename from tests/target/configs/normalize_doc_attributes/true.rs rename to src/tools/rustfmt/tests/target/configs/normalize_doc_attributes/true.rs diff --git a/tests/target/configs/remove_nested_parens/remove_nested_parens.rs b/src/tools/rustfmt/tests/target/configs/remove_nested_parens/remove_nested_parens.rs similarity index 100% rename from tests/target/configs/remove_nested_parens/remove_nested_parens.rs rename to src/tools/rustfmt/tests/target/configs/remove_nested_parens/remove_nested_parens.rs diff --git a/tests/target/configs/reorder_impl_items/false.rs b/src/tools/rustfmt/tests/target/configs/reorder_impl_items/false.rs similarity index 100% rename from tests/target/configs/reorder_impl_items/false.rs rename to src/tools/rustfmt/tests/target/configs/reorder_impl_items/false.rs diff --git a/tests/target/configs/reorder_impl_items/true.rs b/src/tools/rustfmt/tests/target/configs/reorder_impl_items/true.rs similarity index 100% rename from tests/target/configs/reorder_impl_items/true.rs rename to src/tools/rustfmt/tests/target/configs/reorder_impl_items/true.rs diff --git a/tests/target/configs/reorder_imports/false.rs b/src/tools/rustfmt/tests/target/configs/reorder_imports/false.rs similarity index 100% rename from tests/target/configs/reorder_imports/false.rs rename to src/tools/rustfmt/tests/target/configs/reorder_imports/false.rs diff --git a/tests/target/configs/reorder_imports/true.rs b/src/tools/rustfmt/tests/target/configs/reorder_imports/true.rs similarity index 100% rename from tests/target/configs/reorder_imports/true.rs rename to src/tools/rustfmt/tests/target/configs/reorder_imports/true.rs diff --git a/tests/target/configs/reorder_modules/dolor/mod.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/dolor/mod.rs similarity index 100% rename from tests/target/configs/reorder_modules/dolor/mod.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/dolor/mod.rs diff --git a/tests/target/configs/reorder_modules/false.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/false.rs similarity index 100% rename from tests/target/configs/reorder_modules/false.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/false.rs diff --git a/tests/target/configs/reorder_modules/ipsum/mod.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/ipsum/mod.rs similarity index 100% rename from tests/target/configs/reorder_modules/ipsum/mod.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/ipsum/mod.rs diff --git a/tests/target/configs/reorder_modules/lorem/mod.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/lorem/mod.rs similarity index 100% rename from tests/target/configs/reorder_modules/lorem/mod.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/lorem/mod.rs diff --git a/tests/target/configs/reorder_modules/sit/mod.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/sit/mod.rs similarity index 100% rename from tests/target/configs/reorder_modules/sit/mod.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/sit/mod.rs diff --git a/tests/target/configs/reorder_modules/true.rs b/src/tools/rustfmt/tests/target/configs/reorder_modules/true.rs similarity index 100% rename from tests/target/configs/reorder_modules/true.rs rename to src/tools/rustfmt/tests/target/configs/reorder_modules/true.rs diff --git a/tests/target/configs/short_array_element_width_threshold/10.rs b/src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/10.rs similarity index 100% rename from tests/target/configs/short_array_element_width_threshold/10.rs rename to src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/10.rs diff --git a/tests/target/configs/short_array_element_width_threshold/20.rs b/src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/20.rs similarity index 100% rename from tests/target/configs/short_array_element_width_threshold/20.rs rename to src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/20.rs diff --git a/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs b/src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs similarity index 100% rename from tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs rename to src/tools/rustfmt/tests/target/configs/short_array_element_width_threshold/greater_than_max_width.rs diff --git a/tests/target/configs/single_line_let_else_max_width/100.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs similarity index 100% rename from tests/target/configs/single_line_let_else_max_width/100.rs rename to src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/100.rs diff --git a/tests/target/configs/single_line_let_else_max_width/50.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs similarity index 100% rename from tests/target/configs/single_line_let_else_max_width/50.rs rename to src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/50.rs diff --git a/tests/target/configs/single_line_let_else_max_width/zero.rs b/src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs similarity index 100% rename from tests/target/configs/single_line_let_else_max_width/zero.rs rename to src/tools/rustfmt/tests/target/configs/single_line_let_else_max_width/zero.rs diff --git a/tests/target/configs/skip_children/foo/mod.rs b/src/tools/rustfmt/tests/target/configs/skip_children/foo/mod.rs similarity index 100% rename from tests/target/configs/skip_children/foo/mod.rs rename to src/tools/rustfmt/tests/target/configs/skip_children/foo/mod.rs diff --git a/tests/target/configs/skip_children/true.rs b/src/tools/rustfmt/tests/target/configs/skip_children/true.rs similarity index 100% rename from tests/target/configs/skip_children/true.rs rename to src/tools/rustfmt/tests/target/configs/skip_children/true.rs diff --git a/tests/target/configs/space_before_colon/true.rs b/src/tools/rustfmt/tests/target/configs/space_before_colon/true.rs similarity index 100% rename from tests/target/configs/space_before_colon/true.rs rename to src/tools/rustfmt/tests/target/configs/space_before_colon/true.rs diff --git a/tests/target/configs/spaces_around_ranges/false.rs b/src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs similarity index 100% rename from tests/target/configs/spaces_around_ranges/false.rs rename to src/tools/rustfmt/tests/target/configs/spaces_around_ranges/false.rs diff --git a/tests/target/configs/spaces_around_ranges/true.rs b/src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs similarity index 100% rename from tests/target/configs/spaces_around_ranges/true.rs rename to src/tools/rustfmt/tests/target/configs/spaces_around_ranges/true.rs diff --git a/tests/target/configs/struct_field_align_threshold/20.rs b/src/tools/rustfmt/tests/target/configs/struct_field_align_threshold/20.rs similarity index 100% rename from tests/target/configs/struct_field_align_threshold/20.rs rename to src/tools/rustfmt/tests/target/configs/struct_field_align_threshold/20.rs diff --git a/tests/target/configs/struct_lit_single_line/false.rs b/src/tools/rustfmt/tests/target/configs/struct_lit_single_line/false.rs similarity index 100% rename from tests/target/configs/struct_lit_single_line/false.rs rename to src/tools/rustfmt/tests/target/configs/struct_lit_single_line/false.rs diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2015.rs b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs similarity index 100% rename from tests/target/configs/style_edition/overflow_delim_expr_2015.rs rename to src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2015.rs diff --git a/tests/target/configs/style_edition/overflow_delim_expr_2024.rs b/src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs similarity index 100% rename from tests/target/configs/style_edition/overflow_delim_expr_2024.rs rename to src/tools/rustfmt/tests/target/configs/style_edition/overflow_delim_expr_2024.rs diff --git a/tests/target/configs/tab_spaces/2.rs b/src/tools/rustfmt/tests/target/configs/tab_spaces/2.rs similarity index 100% rename from tests/target/configs/tab_spaces/2.rs rename to src/tools/rustfmt/tests/target/configs/tab_spaces/2.rs diff --git a/tests/target/configs/tab_spaces/4.rs b/src/tools/rustfmt/tests/target/configs/tab_spaces/4.rs similarity index 100% rename from tests/target/configs/tab_spaces/4.rs rename to src/tools/rustfmt/tests/target/configs/tab_spaces/4.rs diff --git a/tests/target/configs/trailing_comma/always.rs b/src/tools/rustfmt/tests/target/configs/trailing_comma/always.rs similarity index 100% rename from tests/target/configs/trailing_comma/always.rs rename to src/tools/rustfmt/tests/target/configs/trailing_comma/always.rs diff --git a/tests/target/configs/trailing_comma/never.rs b/src/tools/rustfmt/tests/target/configs/trailing_comma/never.rs similarity index 100% rename from tests/target/configs/trailing_comma/never.rs rename to src/tools/rustfmt/tests/target/configs/trailing_comma/never.rs diff --git a/tests/target/configs/trailing_comma/vertical.rs b/src/tools/rustfmt/tests/target/configs/trailing_comma/vertical.rs similarity index 100% rename from tests/target/configs/trailing_comma/vertical.rs rename to src/tools/rustfmt/tests/target/configs/trailing_comma/vertical.rs diff --git a/tests/target/configs/trailing_semicolon/false.rs b/src/tools/rustfmt/tests/target/configs/trailing_semicolon/false.rs similarity index 100% rename from tests/target/configs/trailing_semicolon/false.rs rename to src/tools/rustfmt/tests/target/configs/trailing_semicolon/false.rs diff --git a/tests/target/configs/trailing_semicolon/true.rs b/src/tools/rustfmt/tests/target/configs/trailing_semicolon/true.rs similarity index 100% rename from tests/target/configs/trailing_semicolon/true.rs rename to src/tools/rustfmt/tests/target/configs/trailing_semicolon/true.rs diff --git a/tests/target/configs/type_punctuation_density/compressed.rs b/src/tools/rustfmt/tests/target/configs/type_punctuation_density/compressed.rs similarity index 100% rename from tests/target/configs/type_punctuation_density/compressed.rs rename to src/tools/rustfmt/tests/target/configs/type_punctuation_density/compressed.rs diff --git a/tests/target/configs/type_punctuation_density/wide.rs b/src/tools/rustfmt/tests/target/configs/type_punctuation_density/wide.rs similarity index 100% rename from tests/target/configs/type_punctuation_density/wide.rs rename to src/tools/rustfmt/tests/target/configs/type_punctuation_density/wide.rs diff --git a/tests/target/configs/use_field_init_shorthand/false.rs b/src/tools/rustfmt/tests/target/configs/use_field_init_shorthand/false.rs similarity index 100% rename from tests/target/configs/use_field_init_shorthand/false.rs rename to src/tools/rustfmt/tests/target/configs/use_field_init_shorthand/false.rs diff --git a/tests/target/configs/use_field_init_shorthand/true.rs b/src/tools/rustfmt/tests/target/configs/use_field_init_shorthand/true.rs similarity index 100% rename from tests/target/configs/use_field_init_shorthand/true.rs rename to src/tools/rustfmt/tests/target/configs/use_field_init_shorthand/true.rs diff --git a/tests/target/configs/use_small_heuristics/default.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs similarity index 100% rename from tests/target/configs/use_small_heuristics/default.rs rename to src/tools/rustfmt/tests/target/configs/use_small_heuristics/default.rs diff --git a/tests/target/configs/use_small_heuristics/max.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs similarity index 100% rename from tests/target/configs/use_small_heuristics/max.rs rename to src/tools/rustfmt/tests/target/configs/use_small_heuristics/max.rs diff --git a/tests/target/configs/use_small_heuristics/off.rs b/src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs similarity index 100% rename from tests/target/configs/use_small_heuristics/off.rs rename to src/tools/rustfmt/tests/target/configs/use_small_heuristics/off.rs diff --git a/tests/target/configs/use_try_shorthand/false.rs b/src/tools/rustfmt/tests/target/configs/use_try_shorthand/false.rs similarity index 100% rename from tests/target/configs/use_try_shorthand/false.rs rename to src/tools/rustfmt/tests/target/configs/use_try_shorthand/false.rs diff --git a/tests/target/configs/use_try_shorthand/true.rs b/src/tools/rustfmt/tests/target/configs/use_try_shorthand/true.rs similarity index 100% rename from tests/target/configs/use_try_shorthand/true.rs rename to src/tools/rustfmt/tests/target/configs/use_try_shorthand/true.rs diff --git a/tests/target/configs/version/mapped.rs b/src/tools/rustfmt/tests/target/configs/version/mapped.rs similarity index 100% rename from tests/target/configs/version/mapped.rs rename to src/tools/rustfmt/tests/target/configs/version/mapped.rs diff --git a/tests/target/configs/where_single_line/true-with-brace-style.rs b/src/tools/rustfmt/tests/target/configs/where_single_line/true-with-brace-style.rs similarity index 100% rename from tests/target/configs/where_single_line/true-with-brace-style.rs rename to src/tools/rustfmt/tests/target/configs/where_single_line/true-with-brace-style.rs diff --git a/tests/target/configs/where_single_line/true.rs b/src/tools/rustfmt/tests/target/configs/where_single_line/true.rs similarity index 100% rename from tests/target/configs/where_single_line/true.rs rename to src/tools/rustfmt/tests/target/configs/where_single_line/true.rs diff --git a/tests/target/configs/wrap_comments/false.rs b/src/tools/rustfmt/tests/target/configs/wrap_comments/false.rs similarity index 100% rename from tests/target/configs/wrap_comments/false.rs rename to src/tools/rustfmt/tests/target/configs/wrap_comments/false.rs diff --git a/tests/target/configs/wrap_comments/true.rs b/src/tools/rustfmt/tests/target/configs/wrap_comments/true.rs similarity index 100% rename from tests/target/configs/wrap_comments/true.rs rename to src/tools/rustfmt/tests/target/configs/wrap_comments/true.rs diff --git a/tests/target/const-block-items.rs b/src/tools/rustfmt/tests/target/const-block-items.rs similarity index 100% rename from tests/target/const-block-items.rs rename to src/tools/rustfmt/tests/target/const-block-items.rs diff --git a/tests/target/const-generics.rs b/src/tools/rustfmt/tests/target/const-generics.rs similarity index 100% rename from tests/target/const-generics.rs rename to src/tools/rustfmt/tests/target/const-generics.rs diff --git a/tests/target/const_generics.rs b/src/tools/rustfmt/tests/target/const_generics.rs similarity index 100% rename from tests/target/const_generics.rs rename to src/tools/rustfmt/tests/target/const_generics.rs diff --git a/tests/target/const_trait.rs b/src/tools/rustfmt/tests/target/const_trait.rs similarity index 100% rename from tests/target/const_trait.rs rename to src/tools/rustfmt/tests/target/const_trait.rs diff --git a/tests/target/control-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/target/control-brace-style-always-next-line.rs similarity index 100% rename from tests/target/control-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/target/control-brace-style-always-next-line.rs diff --git a/tests/target/control-brace-style-always-same-line.rs b/src/tools/rustfmt/tests/target/control-brace-style-always-same-line.rs similarity index 100% rename from tests/target/control-brace-style-always-same-line.rs rename to src/tools/rustfmt/tests/target/control-brace-style-always-same-line.rs diff --git a/tests/target/default-field-values.rs b/src/tools/rustfmt/tests/target/default-field-values.rs similarity index 100% rename from tests/target/default-field-values.rs rename to src/tools/rustfmt/tests/target/default-field-values.rs diff --git a/tests/target/direct_const_arg.rs b/src/tools/rustfmt/tests/target/direct_const_arg.rs similarity index 100% rename from tests/target/direct_const_arg.rs rename to src/tools/rustfmt/tests/target/direct_const_arg.rs diff --git a/tests/target/doc-attrib.rs b/src/tools/rustfmt/tests/target/doc-attrib.rs similarity index 100% rename from tests/target/doc-attrib.rs rename to src/tools/rustfmt/tests/target/doc-attrib.rs diff --git a/tests/target/doc-comment-with-example.rs b/src/tools/rustfmt/tests/target/doc-comment-with-example.rs similarity index 100% rename from tests/target/doc-comment-with-example.rs rename to src/tools/rustfmt/tests/target/doc-comment-with-example.rs diff --git a/tests/target/doc-of-generic-item.rs b/src/tools/rustfmt/tests/target/doc-of-generic-item.rs similarity index 100% rename from tests/target/doc-of-generic-item.rs rename to src/tools/rustfmt/tests/target/doc-of-generic-item.rs diff --git a/tests/target/doc.rs b/src/tools/rustfmt/tests/target/doc.rs similarity index 100% rename from tests/target/doc.rs rename to src/tools/rustfmt/tests/target/doc.rs diff --git a/tests/target/dyn_trait.rs b/src/tools/rustfmt/tests/target/dyn_trait.rs similarity index 100% rename from tests/target/dyn_trait.rs rename to src/tools/rustfmt/tests/target/dyn_trait.rs diff --git a/tests/target/else-if-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/target/else-if-brace-style-always-next-line.rs similarity index 100% rename from tests/target/else-if-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/target/else-if-brace-style-always-next-line.rs diff --git a/tests/target/else-if-brace-style-always-same-line.rs b/src/tools/rustfmt/tests/target/else-if-brace-style-always-same-line.rs similarity index 100% rename from tests/target/else-if-brace-style-always-same-line.rs rename to src/tools/rustfmt/tests/target/else-if-brace-style-always-same-line.rs diff --git a/tests/target/else-if-brace-style-closing-next-line.rs b/src/tools/rustfmt/tests/target/else-if-brace-style-closing-next-line.rs similarity index 100% rename from tests/target/else-if-brace-style-closing-next-line.rs rename to src/tools/rustfmt/tests/target/else-if-brace-style-closing-next-line.rs diff --git a/tests/target/empty-item-single-line-false.rs b/src/tools/rustfmt/tests/target/empty-item-single-line-false.rs similarity index 100% rename from tests/target/empty-item-single-line-false.rs rename to src/tools/rustfmt/tests/target/empty-item-single-line-false.rs diff --git a/tests/target/empty-tuple-no-conversion-to-unit-struct.rs b/src/tools/rustfmt/tests/target/empty-tuple-no-conversion-to-unit-struct.rs similarity index 100% rename from tests/target/empty-tuple-no-conversion-to-unit-struct.rs rename to src/tools/rustfmt/tests/target/empty-tuple-no-conversion-to-unit-struct.rs diff --git a/tests/target/empty_file.rs b/src/tools/rustfmt/tests/target/empty_file.rs similarity index 100% rename from tests/target/empty_file.rs rename to src/tools/rustfmt/tests/target/empty_file.rs diff --git a/tests/target/enum.rs b/src/tools/rustfmt/tests/target/enum.rs similarity index 100% rename from tests/target/enum.rs rename to src/tools/rustfmt/tests/target/enum.rs diff --git a/tests/target/ergonomic_clones.rs b/src/tools/rustfmt/tests/target/ergonomic_clones.rs similarity index 100% rename from tests/target/ergonomic_clones.rs rename to src/tools/rustfmt/tests/target/ergonomic_clones.rs diff --git a/tests/target/existential_type.rs b/src/tools/rustfmt/tests/target/existential_type.rs similarity index 100% rename from tests/target/existential_type.rs rename to src/tools/rustfmt/tests/target/existential_type.rs diff --git a/tests/target/expr-block.rs b/src/tools/rustfmt/tests/target/expr-block.rs similarity index 100% rename from tests/target/expr-block.rs rename to src/tools/rustfmt/tests/target/expr-block.rs diff --git a/tests/target/expr-overflow-delimited.rs b/src/tools/rustfmt/tests/target/expr-overflow-delimited.rs similarity index 100% rename from tests/target/expr-overflow-delimited.rs rename to src/tools/rustfmt/tests/target/expr-overflow-delimited.rs diff --git a/tests/target/expr.rs b/src/tools/rustfmt/tests/target/expr.rs similarity index 100% rename from tests/target/expr.rs rename to src/tools/rustfmt/tests/target/expr.rs diff --git a/tests/target/extern-rust.rs b/src/tools/rustfmt/tests/target/extern-rust.rs similarity index 100% rename from tests/target/extern-rust.rs rename to src/tools/rustfmt/tests/target/extern-rust.rs diff --git a/tests/target/extern.rs b/src/tools/rustfmt/tests/target/extern.rs similarity index 100% rename from tests/target/extern.rs rename to src/tools/rustfmt/tests/target/extern.rs diff --git a/tests/target/extern_not_explicit.rs b/src/tools/rustfmt/tests/target/extern_not_explicit.rs similarity index 100% rename from tests/target/extern_not_explicit.rs rename to src/tools/rustfmt/tests/target/extern_not_explicit.rs diff --git a/tests/target/field-representing-types.rs b/src/tools/rustfmt/tests/target/field-representing-types.rs similarity index 100% rename from tests/target/field-representing-types.rs rename to src/tools/rustfmt/tests/target/field-representing-types.rs diff --git a/tests/target/file-lines-1.rs b/src/tools/rustfmt/tests/target/file-lines-1.rs similarity index 100% rename from tests/target/file-lines-1.rs rename to src/tools/rustfmt/tests/target/file-lines-1.rs diff --git a/tests/target/file-lines-2.rs b/src/tools/rustfmt/tests/target/file-lines-2.rs similarity index 100% rename from tests/target/file-lines-2.rs rename to src/tools/rustfmt/tests/target/file-lines-2.rs diff --git a/tests/target/file-lines-3.rs b/src/tools/rustfmt/tests/target/file-lines-3.rs similarity index 100% rename from tests/target/file-lines-3.rs rename to src/tools/rustfmt/tests/target/file-lines-3.rs diff --git a/tests/target/file-lines-4.rs b/src/tools/rustfmt/tests/target/file-lines-4.rs similarity index 100% rename from tests/target/file-lines-4.rs rename to src/tools/rustfmt/tests/target/file-lines-4.rs diff --git a/tests/target/file-lines-5.rs b/src/tools/rustfmt/tests/target/file-lines-5.rs similarity index 100% rename from tests/target/file-lines-5.rs rename to src/tools/rustfmt/tests/target/file-lines-5.rs diff --git a/tests/target/file-lines-6.rs b/src/tools/rustfmt/tests/target/file-lines-6.rs similarity index 100% rename from tests/target/file-lines-6.rs rename to src/tools/rustfmt/tests/target/file-lines-6.rs diff --git a/tests/target/file-lines-7.rs b/src/tools/rustfmt/tests/target/file-lines-7.rs similarity index 100% rename from tests/target/file-lines-7.rs rename to src/tools/rustfmt/tests/target/file-lines-7.rs diff --git a/tests/target/file-lines-item.rs b/src/tools/rustfmt/tests/target/file-lines-item.rs similarity index 100% rename from tests/target/file-lines-item.rs rename to src/tools/rustfmt/tests/target/file-lines-item.rs diff --git a/tests/target/final-kw.rs b/src/tools/rustfmt/tests/target/final-kw.rs similarity index 100% rename from tests/target/final-kw.rs rename to src/tools/rustfmt/tests/target/final-kw.rs diff --git a/tests/target/fn-args-with-last-line-comment.rs b/src/tools/rustfmt/tests/target/fn-args-with-last-line-comment.rs similarity index 100% rename from tests/target/fn-args-with-last-line-comment.rs rename to src/tools/rustfmt/tests/target/fn-args-with-last-line-comment.rs diff --git a/tests/target/fn-custom-2.rs b/src/tools/rustfmt/tests/target/fn-custom-2.rs similarity index 100% rename from tests/target/fn-custom-2.rs rename to src/tools/rustfmt/tests/target/fn-custom-2.rs diff --git a/tests/target/fn-custom-3.rs b/src/tools/rustfmt/tests/target/fn-custom-3.rs similarity index 100% rename from tests/target/fn-custom-3.rs rename to src/tools/rustfmt/tests/target/fn-custom-3.rs diff --git a/tests/target/fn-custom-4.rs b/src/tools/rustfmt/tests/target/fn-custom-4.rs similarity index 100% rename from tests/target/fn-custom-4.rs rename to src/tools/rustfmt/tests/target/fn-custom-4.rs diff --git a/tests/target/fn-custom-6.rs b/src/tools/rustfmt/tests/target/fn-custom-6.rs similarity index 100% rename from tests/target/fn-custom-6.rs rename to src/tools/rustfmt/tests/target/fn-custom-6.rs diff --git a/tests/target/fn-custom-7.rs b/src/tools/rustfmt/tests/target/fn-custom-7.rs similarity index 100% rename from tests/target/fn-custom-7.rs rename to src/tools/rustfmt/tests/target/fn-custom-7.rs diff --git a/tests/target/fn-custom-8.rs b/src/tools/rustfmt/tests/target/fn-custom-8.rs similarity index 100% rename from tests/target/fn-custom-8.rs rename to src/tools/rustfmt/tests/target/fn-custom-8.rs diff --git a/tests/target/fn-custom.rs b/src/tools/rustfmt/tests/target/fn-custom.rs similarity index 100% rename from tests/target/fn-custom.rs rename to src/tools/rustfmt/tests/target/fn-custom.rs diff --git a/tests/target/fn-param-attributes.rs b/src/tools/rustfmt/tests/target/fn-param-attributes.rs similarity index 100% rename from tests/target/fn-param-attributes.rs rename to src/tools/rustfmt/tests/target/fn-param-attributes.rs diff --git a/tests/target/fn-simple.rs b/src/tools/rustfmt/tests/target/fn-simple.rs similarity index 100% rename from tests/target/fn-simple.rs rename to src/tools/rustfmt/tests/target/fn-simple.rs diff --git a/tests/target/fn-single-line/version_one.rs b/src/tools/rustfmt/tests/target/fn-single-line/version_one.rs similarity index 100% rename from tests/target/fn-single-line/version_one.rs rename to src/tools/rustfmt/tests/target/fn-single-line/version_one.rs diff --git a/tests/target/fn-single-line/version_two.rs b/src/tools/rustfmt/tests/target/fn-single-line/version_two.rs similarity index 100% rename from tests/target/fn-single-line/version_two.rs rename to src/tools/rustfmt/tests/target/fn-single-line/version_two.rs diff --git a/tests/target/fn-ty.rs b/src/tools/rustfmt/tests/target/fn-ty.rs similarity index 100% rename from tests/target/fn-ty.rs rename to src/tools/rustfmt/tests/target/fn-ty.rs diff --git a/tests/target/fn.rs b/src/tools/rustfmt/tests/target/fn.rs similarity index 100% rename from tests/target/fn.rs rename to src/tools/rustfmt/tests/target/fn.rs diff --git a/tests/target/fn_args_indent-block.rs b/src/tools/rustfmt/tests/target/fn_args_indent-block.rs similarity index 100% rename from tests/target/fn_args_indent-block.rs rename to src/tools/rustfmt/tests/target/fn_args_indent-block.rs diff --git a/tests/target/fn_args_layout-vertical.rs b/src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs similarity index 100% rename from tests/target/fn_args_layout-vertical.rs rename to src/tools/rustfmt/tests/target/fn_args_layout-vertical.rs diff --git a/tests/target/fn_once.rs b/src/tools/rustfmt/tests/target/fn_once.rs similarity index 100% rename from tests/target/fn_once.rs rename to src/tools/rustfmt/tests/target/fn_once.rs diff --git a/tests/target/format_strings/issue-202.rs b/src/tools/rustfmt/tests/target/format_strings/issue-202.rs similarity index 100% rename from tests/target/format_strings/issue-202.rs rename to src/tools/rustfmt/tests/target/format_strings/issue-202.rs diff --git a/tests/target/format_strings/issue-2833.rs b/src/tools/rustfmt/tests/target/format_strings/issue-2833.rs similarity index 100% rename from tests/target/format_strings/issue-2833.rs rename to src/tools/rustfmt/tests/target/format_strings/issue-2833.rs diff --git a/tests/target/format_strings/issue-3263.rs b/src/tools/rustfmt/tests/target/format_strings/issue-3263.rs similarity index 100% rename from tests/target/format_strings/issue-3263.rs rename to src/tools/rustfmt/tests/target/format_strings/issue-3263.rs diff --git a/tests/target/format_strings/issue-687.rs b/src/tools/rustfmt/tests/target/format_strings/issue-687.rs similarity index 100% rename from tests/target/format_strings/issue-687.rs rename to src/tools/rustfmt/tests/target/format_strings/issue-687.rs diff --git a/tests/target/format_strings/issue564.rs b/src/tools/rustfmt/tests/target/format_strings/issue564.rs similarity index 100% rename from tests/target/format_strings/issue564.rs rename to src/tools/rustfmt/tests/target/format_strings/issue564.rs diff --git a/tests/target/frontmatter_compact.rs b/src/tools/rustfmt/tests/target/frontmatter_compact.rs similarity index 100% rename from tests/target/frontmatter_compact.rs rename to src/tools/rustfmt/tests/target/frontmatter_compact.rs diff --git a/tests/target/frontmatter_escaped.rs b/src/tools/rustfmt/tests/target/frontmatter_escaped.rs similarity index 100% rename from tests/target/frontmatter_escaped.rs rename to src/tools/rustfmt/tests/target/frontmatter_escaped.rs diff --git a/tests/target/frontmatter_spaced.rs b/src/tools/rustfmt/tests/target/frontmatter_spaced.rs similarity index 100% rename from tests/target/frontmatter_spaced.rs rename to src/tools/rustfmt/tests/target/frontmatter_spaced.rs diff --git a/tests/target/generic_static.rs b/src/tools/rustfmt/tests/target/generic_static.rs similarity index 100% rename from tests/target/generic_static.rs rename to src/tools/rustfmt/tests/target/generic_static.rs diff --git a/tests/target/guard_patterns.rs b/src/tools/rustfmt/tests/target/guard_patterns.rs similarity index 100% rename from tests/target/guard_patterns.rs rename to src/tools/rustfmt/tests/target/guard_patterns.rs diff --git a/tests/target/hard-tabs.rs b/src/tools/rustfmt/tests/target/hard-tabs.rs similarity index 100% rename from tests/target/hard-tabs.rs rename to src/tools/rustfmt/tests/target/hard-tabs.rs diff --git a/tests/target/hello.rs b/src/tools/rustfmt/tests/target/hello.rs similarity index 100% rename from tests/target/hello.rs rename to src/tools/rustfmt/tests/target/hello.rs diff --git a/tests/target/if_while_or_patterns.rs b/src/tools/rustfmt/tests/target/if_while_or_patterns.rs similarity index 100% rename from tests/target/if_while_or_patterns.rs rename to src/tools/rustfmt/tests/target/if_while_or_patterns.rs diff --git a/tests/target/immovable_coroutines.rs b/src/tools/rustfmt/tests/target/immovable_coroutines.rs similarity index 100% rename from tests/target/immovable_coroutines.rs rename to src/tools/rustfmt/tests/target/immovable_coroutines.rs diff --git a/tests/target/impl-restriction.rs b/src/tools/rustfmt/tests/target/impl-restriction.rs similarity index 100% rename from tests/target/impl-restriction.rs rename to src/tools/rustfmt/tests/target/impl-restriction.rs diff --git a/tests/target/impl.rs b/src/tools/rustfmt/tests/target/impl.rs similarity index 100% rename from tests/target/impl.rs rename to src/tools/rustfmt/tests/target/impl.rs diff --git a/tests/target/impls.rs b/src/tools/rustfmt/tests/target/impls.rs similarity index 100% rename from tests/target/impls.rs rename to src/tools/rustfmt/tests/target/impls.rs diff --git a/tests/target/imports/import-fencepost-length.rs b/src/tools/rustfmt/tests/target/imports/import-fencepost-length.rs similarity index 100% rename from tests/target/imports/import-fencepost-length.rs rename to src/tools/rustfmt/tests/target/imports/import-fencepost-length.rs diff --git a/tests/target/imports/imports-impl-only-use.rs b/src/tools/rustfmt/tests/target/imports/imports-impl-only-use.rs similarity index 100% rename from tests/target/imports/imports-impl-only-use.rs rename to src/tools/rustfmt/tests/target/imports/imports-impl-only-use.rs diff --git a/tests/target/imports/imports-reorder-lines-and-items.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines-and-items.rs similarity index 100% rename from tests/target/imports/imports-reorder-lines-and-items.rs rename to src/tools/rustfmt/tests/target/imports/imports-reorder-lines-and-items.rs diff --git a/tests/target/imports/imports-reorder-lines.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder-lines.rs similarity index 100% rename from tests/target/imports/imports-reorder-lines.rs rename to src/tools/rustfmt/tests/target/imports/imports-reorder-lines.rs diff --git a/tests/target/imports/imports-reorder.rs b/src/tools/rustfmt/tests/target/imports/imports-reorder.rs similarity index 100% rename from tests/target/imports/imports-reorder.rs rename to src/tools/rustfmt/tests/target/imports/imports-reorder.rs diff --git a/tests/target/imports/imports.rs b/src/tools/rustfmt/tests/target/imports/imports.rs similarity index 100% rename from tests/target/imports/imports.rs rename to src/tools/rustfmt/tests/target/imports/imports.rs diff --git a/tests/target/imports/imports_2021_edition.rs b/src/tools/rustfmt/tests/target/imports/imports_2021_edition.rs similarity index 100% rename from tests/target/imports/imports_2021_edition.rs rename to src/tools/rustfmt/tests/target/imports/imports_2021_edition.rs diff --git a/tests/target/imports/imports_block_indent.rs b/src/tools/rustfmt/tests/target/imports/imports_block_indent.rs similarity index 100% rename from tests/target/imports/imports_block_indent.rs rename to src/tools/rustfmt/tests/target/imports/imports_block_indent.rs diff --git a/tests/target/imports/imports_granularity_crate.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_crate.rs similarity index 100% rename from tests/target/imports/imports_granularity_crate.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_crate.rs diff --git a/tests/target/imports/imports_granularity_default-with-dups.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs similarity index 100% rename from tests/target/imports/imports_granularity_default-with-dups.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_default-with-dups.rs diff --git a/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs similarity index 100% rename from tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups-StdExternalCrate-no-reorder.rs diff --git a/tests/target/imports/imports_granularity_item-with-dups.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs similarity index 100% rename from tests/target/imports/imports_granularity_item-with-dups.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_item-with-dups.rs diff --git a/tests/target/imports/imports_granularity_item.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs similarity index 100% rename from tests/target/imports/imports_granularity_item.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_item.rs diff --git a/tests/target/imports/imports_granularity_module.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs similarity index 100% rename from tests/target/imports/imports_granularity_module.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_module.rs diff --git a/tests/target/imports/imports_granularity_one.rs b/src/tools/rustfmt/tests/target/imports/imports_granularity_one.rs similarity index 100% rename from tests/target/imports/imports_granularity_one.rs rename to src/tools/rustfmt/tests/target/imports/imports_granularity_one.rs diff --git a/tests/target/imports_raw_identifiers/version_One.rs b/src/tools/rustfmt/tests/target/imports_raw_identifiers/version_One.rs similarity index 100% rename from tests/target/imports_raw_identifiers/version_One.rs rename to src/tools/rustfmt/tests/target/imports_raw_identifiers/version_One.rs diff --git a/tests/target/imports_raw_identifiers/version_Two.rs b/src/tools/rustfmt/tests/target/imports_raw_identifiers/version_Two.rs similarity index 100% rename from tests/target/imports_raw_identifiers/version_Two.rs rename to src/tools/rustfmt/tests/target/imports_raw_identifiers/version_Two.rs diff --git a/tests/target/indented-impl.rs b/src/tools/rustfmt/tests/target/indented-impl.rs similarity index 100% rename from tests/target/indented-impl.rs rename to src/tools/rustfmt/tests/target/indented-impl.rs diff --git a/tests/target/inner-module-path/b.rs b/src/tools/rustfmt/tests/target/inner-module-path/b.rs similarity index 100% rename from tests/target/inner-module-path/b.rs rename to src/tools/rustfmt/tests/target/inner-module-path/b.rs diff --git a/tests/target/inner-module-path/c/d.rs b/src/tools/rustfmt/tests/target/inner-module-path/c/d.rs similarity index 100% rename from tests/target/inner-module-path/c/d.rs rename to src/tools/rustfmt/tests/target/inner-module-path/c/d.rs diff --git a/tests/target/inner-module-path/lib.rs b/src/tools/rustfmt/tests/target/inner-module-path/lib.rs similarity index 100% rename from tests/target/inner-module-path/lib.rs rename to src/tools/rustfmt/tests/target/inner-module-path/lib.rs diff --git a/tests/target/invalid-rust-code-in-doc-comment.rs b/src/tools/rustfmt/tests/target/invalid-rust-code-in-doc-comment.rs similarity index 100% rename from tests/target/invalid-rust-code-in-doc-comment.rs rename to src/tools/rustfmt/tests/target/invalid-rust-code-in-doc-comment.rs diff --git a/tests/target/issue-1021.rs b/src/tools/rustfmt/tests/target/issue-1021.rs similarity index 100% rename from tests/target/issue-1021.rs rename to src/tools/rustfmt/tests/target/issue-1021.rs diff --git a/tests/target/issue-1049.rs b/src/tools/rustfmt/tests/target/issue-1049.rs similarity index 100% rename from tests/target/issue-1049.rs rename to src/tools/rustfmt/tests/target/issue-1049.rs diff --git a/tests/target/issue-1055.rs b/src/tools/rustfmt/tests/target/issue-1055.rs similarity index 100% rename from tests/target/issue-1055.rs rename to src/tools/rustfmt/tests/target/issue-1055.rs diff --git a/tests/target/issue-1096.rs b/src/tools/rustfmt/tests/target/issue-1096.rs similarity index 100% rename from tests/target/issue-1096.rs rename to src/tools/rustfmt/tests/target/issue-1096.rs diff --git a/tests/target/issue-1111.rs b/src/tools/rustfmt/tests/target/issue-1111.rs similarity index 100% rename from tests/target/issue-1111.rs rename to src/tools/rustfmt/tests/target/issue-1111.rs diff --git a/tests/target/issue-1113.rs b/src/tools/rustfmt/tests/target/issue-1113.rs similarity index 100% rename from tests/target/issue-1113.rs rename to src/tools/rustfmt/tests/target/issue-1113.rs diff --git a/tests/target/issue-1120.rs b/src/tools/rustfmt/tests/target/issue-1120.rs similarity index 100% rename from tests/target/issue-1120.rs rename to src/tools/rustfmt/tests/target/issue-1120.rs diff --git a/tests/target/issue-1124.rs b/src/tools/rustfmt/tests/target/issue-1124.rs similarity index 100% rename from tests/target/issue-1124.rs rename to src/tools/rustfmt/tests/target/issue-1124.rs diff --git a/tests/target/issue-1127.rs b/src/tools/rustfmt/tests/target/issue-1127.rs similarity index 100% rename from tests/target/issue-1127.rs rename to src/tools/rustfmt/tests/target/issue-1127.rs diff --git a/tests/target/issue-1158.rs b/src/tools/rustfmt/tests/target/issue-1158.rs similarity index 100% rename from tests/target/issue-1158.rs rename to src/tools/rustfmt/tests/target/issue-1158.rs diff --git a/tests/target/issue-1177.rs b/src/tools/rustfmt/tests/target/issue-1177.rs similarity index 100% rename from tests/target/issue-1177.rs rename to src/tools/rustfmt/tests/target/issue-1177.rs diff --git a/tests/target/issue-1192.rs b/src/tools/rustfmt/tests/target/issue-1192.rs similarity index 100% rename from tests/target/issue-1192.rs rename to src/tools/rustfmt/tests/target/issue-1192.rs diff --git a/tests/target/issue-1210/a.rs b/src/tools/rustfmt/tests/target/issue-1210/a.rs similarity index 100% rename from tests/target/issue-1210/a.rs rename to src/tools/rustfmt/tests/target/issue-1210/a.rs diff --git a/tests/target/issue-1210/b.rs b/src/tools/rustfmt/tests/target/issue-1210/b.rs similarity index 100% rename from tests/target/issue-1210/b.rs rename to src/tools/rustfmt/tests/target/issue-1210/b.rs diff --git a/tests/target/issue-1210/c.rs b/src/tools/rustfmt/tests/target/issue-1210/c.rs similarity index 100% rename from tests/target/issue-1210/c.rs rename to src/tools/rustfmt/tests/target/issue-1210/c.rs diff --git a/tests/target/issue-1210/d.rs b/src/tools/rustfmt/tests/target/issue-1210/d.rs similarity index 100% rename from tests/target/issue-1210/d.rs rename to src/tools/rustfmt/tests/target/issue-1210/d.rs diff --git a/tests/target/issue-1210/e.rs b/src/tools/rustfmt/tests/target/issue-1210/e.rs similarity index 100% rename from tests/target/issue-1210/e.rs rename to src/tools/rustfmt/tests/target/issue-1210/e.rs diff --git a/tests/target/issue-1211.rs b/src/tools/rustfmt/tests/target/issue-1211.rs similarity index 100% rename from tests/target/issue-1211.rs rename to src/tools/rustfmt/tests/target/issue-1211.rs diff --git a/tests/target/issue-1214.rs b/src/tools/rustfmt/tests/target/issue-1214.rs similarity index 100% rename from tests/target/issue-1214.rs rename to src/tools/rustfmt/tests/target/issue-1214.rs diff --git a/tests/target/issue-1216.rs b/src/tools/rustfmt/tests/target/issue-1216.rs similarity index 100% rename from tests/target/issue-1216.rs rename to src/tools/rustfmt/tests/target/issue-1216.rs diff --git a/tests/target/issue-1239.rs b/src/tools/rustfmt/tests/target/issue-1239.rs similarity index 100% rename from tests/target/issue-1239.rs rename to src/tools/rustfmt/tests/target/issue-1239.rs diff --git a/tests/target/issue-1247.rs b/src/tools/rustfmt/tests/target/issue-1247.rs similarity index 100% rename from tests/target/issue-1247.rs rename to src/tools/rustfmt/tests/target/issue-1247.rs diff --git a/tests/target/issue-1255.rs b/src/tools/rustfmt/tests/target/issue-1255.rs similarity index 100% rename from tests/target/issue-1255.rs rename to src/tools/rustfmt/tests/target/issue-1255.rs diff --git a/tests/target/issue-1278.rs b/src/tools/rustfmt/tests/target/issue-1278.rs similarity index 100% rename from tests/target/issue-1278.rs rename to src/tools/rustfmt/tests/target/issue-1278.rs diff --git a/tests/target/issue-1350.rs b/src/tools/rustfmt/tests/target/issue-1350.rs similarity index 100% rename from tests/target/issue-1350.rs rename to src/tools/rustfmt/tests/target/issue-1350.rs diff --git a/tests/target/issue-1366.rs b/src/tools/rustfmt/tests/target/issue-1366.rs similarity index 100% rename from tests/target/issue-1366.rs rename to src/tools/rustfmt/tests/target/issue-1366.rs diff --git a/tests/target/issue-1397.rs b/src/tools/rustfmt/tests/target/issue-1397.rs similarity index 100% rename from tests/target/issue-1397.rs rename to src/tools/rustfmt/tests/target/issue-1397.rs diff --git a/tests/target/issue-1468.rs b/src/tools/rustfmt/tests/target/issue-1468.rs similarity index 100% rename from tests/target/issue-1468.rs rename to src/tools/rustfmt/tests/target/issue-1468.rs diff --git a/tests/target/issue-1598.rs b/src/tools/rustfmt/tests/target/issue-1598.rs similarity index 100% rename from tests/target/issue-1598.rs rename to src/tools/rustfmt/tests/target/issue-1598.rs diff --git a/tests/target/issue-1624.rs b/src/tools/rustfmt/tests/target/issue-1624.rs similarity index 100% rename from tests/target/issue-1624.rs rename to src/tools/rustfmt/tests/target/issue-1624.rs diff --git a/tests/target/issue-1681.rs b/src/tools/rustfmt/tests/target/issue-1681.rs similarity index 100% rename from tests/target/issue-1681.rs rename to src/tools/rustfmt/tests/target/issue-1681.rs diff --git a/tests/target/issue-1693.rs b/src/tools/rustfmt/tests/target/issue-1693.rs similarity index 100% rename from tests/target/issue-1693.rs rename to src/tools/rustfmt/tests/target/issue-1693.rs diff --git a/tests/target/issue-1703.rs b/src/tools/rustfmt/tests/target/issue-1703.rs similarity index 100% rename from tests/target/issue-1703.rs rename to src/tools/rustfmt/tests/target/issue-1703.rs diff --git a/tests/target/issue-1800.rs b/src/tools/rustfmt/tests/target/issue-1800.rs similarity index 100% rename from tests/target/issue-1800.rs rename to src/tools/rustfmt/tests/target/issue-1800.rs diff --git a/tests/target/issue-1802.rs b/src/tools/rustfmt/tests/target/issue-1802.rs similarity index 100% rename from tests/target/issue-1802.rs rename to src/tools/rustfmt/tests/target/issue-1802.rs diff --git a/tests/target/issue-1824.rs b/src/tools/rustfmt/tests/target/issue-1824.rs similarity index 100% rename from tests/target/issue-1824.rs rename to src/tools/rustfmt/tests/target/issue-1824.rs diff --git a/tests/target/issue-1914.rs b/src/tools/rustfmt/tests/target/issue-1914.rs similarity index 100% rename from tests/target/issue-1914.rs rename to src/tools/rustfmt/tests/target/issue-1914.rs diff --git a/tests/target/issue-2025.rs b/src/tools/rustfmt/tests/target/issue-2025.rs similarity index 100% rename from tests/target/issue-2025.rs rename to src/tools/rustfmt/tests/target/issue-2025.rs diff --git a/tests/target/issue-2103.rs b/src/tools/rustfmt/tests/target/issue-2103.rs similarity index 100% rename from tests/target/issue-2103.rs rename to src/tools/rustfmt/tests/target/issue-2103.rs diff --git a/tests/target/issue-2111.rs b/src/tools/rustfmt/tests/target/issue-2111.rs similarity index 100% rename from tests/target/issue-2111.rs rename to src/tools/rustfmt/tests/target/issue-2111.rs diff --git a/tests/target/issue-2123.rs b/src/tools/rustfmt/tests/target/issue-2123.rs similarity index 100% rename from tests/target/issue-2123.rs rename to src/tools/rustfmt/tests/target/issue-2123.rs diff --git a/tests/target/issue-2164.rs b/src/tools/rustfmt/tests/target/issue-2164.rs similarity index 100% rename from tests/target/issue-2164.rs rename to src/tools/rustfmt/tests/target/issue-2164.rs diff --git a/tests/target/issue-2179/one.rs b/src/tools/rustfmt/tests/target/issue-2179/one.rs similarity index 100% rename from tests/target/issue-2179/one.rs rename to src/tools/rustfmt/tests/target/issue-2179/one.rs diff --git a/tests/target/issue-2179/two.rs b/src/tools/rustfmt/tests/target/issue-2179/two.rs similarity index 100% rename from tests/target/issue-2179/two.rs rename to src/tools/rustfmt/tests/target/issue-2179/two.rs diff --git a/tests/target/issue-2197.rs b/src/tools/rustfmt/tests/target/issue-2197.rs similarity index 100% rename from tests/target/issue-2197.rs rename to src/tools/rustfmt/tests/target/issue-2197.rs diff --git a/tests/target/issue-2256.rs b/src/tools/rustfmt/tests/target/issue-2256.rs similarity index 100% rename from tests/target/issue-2256.rs rename to src/tools/rustfmt/tests/target/issue-2256.rs diff --git a/tests/target/issue-2324.rs b/src/tools/rustfmt/tests/target/issue-2324.rs similarity index 100% rename from tests/target/issue-2324.rs rename to src/tools/rustfmt/tests/target/issue-2324.rs diff --git a/tests/target/issue-2329.rs b/src/tools/rustfmt/tests/target/issue-2329.rs similarity index 100% rename from tests/target/issue-2329.rs rename to src/tools/rustfmt/tests/target/issue-2329.rs diff --git a/tests/target/issue-2342.rs b/src/tools/rustfmt/tests/target/issue-2342.rs similarity index 100% rename from tests/target/issue-2342.rs rename to src/tools/rustfmt/tests/target/issue-2342.rs diff --git a/tests/target/issue-2346.rs b/src/tools/rustfmt/tests/target/issue-2346.rs similarity index 100% rename from tests/target/issue-2346.rs rename to src/tools/rustfmt/tests/target/issue-2346.rs diff --git a/tests/target/issue-2401.rs b/src/tools/rustfmt/tests/target/issue-2401.rs similarity index 100% rename from tests/target/issue-2401.rs rename to src/tools/rustfmt/tests/target/issue-2401.rs diff --git a/tests/target/issue-2445.rs b/src/tools/rustfmt/tests/target/issue-2445.rs similarity index 100% rename from tests/target/issue-2445.rs rename to src/tools/rustfmt/tests/target/issue-2445.rs diff --git a/tests/target/issue-2446.rs b/src/tools/rustfmt/tests/target/issue-2446.rs similarity index 100% rename from tests/target/issue-2446.rs rename to src/tools/rustfmt/tests/target/issue-2446.rs diff --git a/tests/target/issue-2479.rs b/src/tools/rustfmt/tests/target/issue-2479.rs similarity index 100% rename from tests/target/issue-2479.rs rename to src/tools/rustfmt/tests/target/issue-2479.rs diff --git a/tests/target/issue-2482/a.rs b/src/tools/rustfmt/tests/target/issue-2482/a.rs similarity index 100% rename from tests/target/issue-2482/a.rs rename to src/tools/rustfmt/tests/target/issue-2482/a.rs diff --git a/tests/target/issue-2482/b.rs b/src/tools/rustfmt/tests/target/issue-2482/b.rs similarity index 100% rename from tests/target/issue-2482/b.rs rename to src/tools/rustfmt/tests/target/issue-2482/b.rs diff --git a/tests/target/issue-2482/c.rs b/src/tools/rustfmt/tests/target/issue-2482/c.rs similarity index 100% rename from tests/target/issue-2482/c.rs rename to src/tools/rustfmt/tests/target/issue-2482/c.rs diff --git a/tests/target/issue-2496.rs b/src/tools/rustfmt/tests/target/issue-2496.rs similarity index 100% rename from tests/target/issue-2496.rs rename to src/tools/rustfmt/tests/target/issue-2496.rs diff --git a/tests/target/issue-2520.rs b/src/tools/rustfmt/tests/target/issue-2520.rs similarity index 100% rename from tests/target/issue-2520.rs rename to src/tools/rustfmt/tests/target/issue-2520.rs diff --git a/tests/target/issue-2523.rs b/src/tools/rustfmt/tests/target/issue-2523.rs similarity index 100% rename from tests/target/issue-2523.rs rename to src/tools/rustfmt/tests/target/issue-2523.rs diff --git a/tests/target/issue-2526.rs b/src/tools/rustfmt/tests/target/issue-2526.rs similarity index 100% rename from tests/target/issue-2526.rs rename to src/tools/rustfmt/tests/target/issue-2526.rs diff --git a/tests/target/issue-2534/format_macro_matchers_false.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs similarity index 100% rename from tests/target/issue-2534/format_macro_matchers_false.rs rename to src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_false.rs diff --git a/tests/target/issue-2534/format_macro_matchers_true.rs b/src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs similarity index 100% rename from tests/target/issue-2534/format_macro_matchers_true.rs rename to src/tools/rustfmt/tests/target/issue-2534/format_macro_matchers_true.rs diff --git a/tests/target/issue-2551.rs b/src/tools/rustfmt/tests/target/issue-2551.rs similarity index 100% rename from tests/target/issue-2551.rs rename to src/tools/rustfmt/tests/target/issue-2551.rs diff --git a/tests/target/issue-2554.rs b/src/tools/rustfmt/tests/target/issue-2554.rs similarity index 100% rename from tests/target/issue-2554.rs rename to src/tools/rustfmt/tests/target/issue-2554.rs diff --git a/tests/target/issue-2582.rs b/src/tools/rustfmt/tests/target/issue-2582.rs similarity index 100% rename from tests/target/issue-2582.rs rename to src/tools/rustfmt/tests/target/issue-2582.rs diff --git a/tests/target/issue-2641.rs b/src/tools/rustfmt/tests/target/issue-2641.rs similarity index 100% rename from tests/target/issue-2641.rs rename to src/tools/rustfmt/tests/target/issue-2641.rs diff --git a/tests/target/issue-2644.rs b/src/tools/rustfmt/tests/target/issue-2644.rs similarity index 100% rename from tests/target/issue-2644.rs rename to src/tools/rustfmt/tests/target/issue-2644.rs diff --git a/tests/target/issue-2673-nonmodrs-mods/foo.rs b/src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/foo.rs similarity index 100% rename from tests/target/issue-2673-nonmodrs-mods/foo.rs rename to src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/foo.rs diff --git a/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs b/src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs similarity index 100% rename from tests/target/issue-2673-nonmodrs-mods/foo/bar.rs rename to src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/foo/bar.rs diff --git a/tests/target/issue-2673-nonmodrs-mods/lib.rs b/src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/lib.rs similarity index 100% rename from tests/target/issue-2673-nonmodrs-mods/lib.rs rename to src/tools/rustfmt/tests/target/issue-2673-nonmodrs-mods/lib.rs diff --git a/tests/target/issue-2728.rs b/src/tools/rustfmt/tests/target/issue-2728.rs similarity index 100% rename from tests/target/issue-2728.rs rename to src/tools/rustfmt/tests/target/issue-2728.rs diff --git a/tests/target/issue-2759.rs b/src/tools/rustfmt/tests/target/issue-2759.rs similarity index 100% rename from tests/target/issue-2759.rs rename to src/tools/rustfmt/tests/target/issue-2759.rs diff --git a/tests/target/issue-2761.rs b/src/tools/rustfmt/tests/target/issue-2761.rs similarity index 100% rename from tests/target/issue-2761.rs rename to src/tools/rustfmt/tests/target/issue-2761.rs diff --git a/tests/target/issue-2781.rs b/src/tools/rustfmt/tests/target/issue-2781.rs similarity index 100% rename from tests/target/issue-2781.rs rename to src/tools/rustfmt/tests/target/issue-2781.rs diff --git a/tests/target/issue-2794.rs b/src/tools/rustfmt/tests/target/issue-2794.rs similarity index 100% rename from tests/target/issue-2794.rs rename to src/tools/rustfmt/tests/target/issue-2794.rs diff --git a/tests/target/issue-2810.rs b/src/tools/rustfmt/tests/target/issue-2810.rs similarity index 100% rename from tests/target/issue-2810.rs rename to src/tools/rustfmt/tests/target/issue-2810.rs diff --git a/tests/target/issue-2835.rs b/src/tools/rustfmt/tests/target/issue-2835.rs similarity index 100% rename from tests/target/issue-2835.rs rename to src/tools/rustfmt/tests/target/issue-2835.rs diff --git a/tests/target/issue-2863.rs b/src/tools/rustfmt/tests/target/issue-2863.rs similarity index 100% rename from tests/target/issue-2863.rs rename to src/tools/rustfmt/tests/target/issue-2863.rs diff --git a/tests/target/issue-2869.rs b/src/tools/rustfmt/tests/target/issue-2869.rs similarity index 100% rename from tests/target/issue-2869.rs rename to src/tools/rustfmt/tests/target/issue-2869.rs diff --git a/tests/target/issue-2896.rs b/src/tools/rustfmt/tests/target/issue-2896.rs similarity index 100% rename from tests/target/issue-2896.rs rename to src/tools/rustfmt/tests/target/issue-2896.rs diff --git a/tests/target/issue-2916.rs b/src/tools/rustfmt/tests/target/issue-2916.rs similarity index 100% rename from tests/target/issue-2916.rs rename to src/tools/rustfmt/tests/target/issue-2916.rs diff --git a/tests/target/issue-2917/minimal.rs b/src/tools/rustfmt/tests/target/issue-2917/minimal.rs similarity index 100% rename from tests/target/issue-2917/minimal.rs rename to src/tools/rustfmt/tests/target/issue-2917/minimal.rs diff --git a/tests/target/issue-2917/packed_simd.rs b/src/tools/rustfmt/tests/target/issue-2917/packed_simd.rs similarity index 100% rename from tests/target/issue-2917/packed_simd.rs rename to src/tools/rustfmt/tests/target/issue-2917/packed_simd.rs diff --git a/tests/target/issue-2922.rs b/src/tools/rustfmt/tests/target/issue-2922.rs similarity index 100% rename from tests/target/issue-2922.rs rename to src/tools/rustfmt/tests/target/issue-2922.rs diff --git a/tests/target/issue-2927-2.rs b/src/tools/rustfmt/tests/target/issue-2927-2.rs similarity index 100% rename from tests/target/issue-2927-2.rs rename to src/tools/rustfmt/tests/target/issue-2927-2.rs diff --git a/tests/target/issue-2927.rs b/src/tools/rustfmt/tests/target/issue-2927.rs similarity index 100% rename from tests/target/issue-2927.rs rename to src/tools/rustfmt/tests/target/issue-2927.rs diff --git a/tests/target/issue-2930.rs b/src/tools/rustfmt/tests/target/issue-2930.rs similarity index 100% rename from tests/target/issue-2930.rs rename to src/tools/rustfmt/tests/target/issue-2930.rs diff --git a/tests/target/issue-2936.rs b/src/tools/rustfmt/tests/target/issue-2936.rs similarity index 100% rename from tests/target/issue-2936.rs rename to src/tools/rustfmt/tests/target/issue-2936.rs diff --git a/tests/target/issue-2941.rs b/src/tools/rustfmt/tests/target/issue-2941.rs similarity index 100% rename from tests/target/issue-2941.rs rename to src/tools/rustfmt/tests/target/issue-2941.rs diff --git a/tests/target/issue-2955.rs b/src/tools/rustfmt/tests/target/issue-2955.rs similarity index 100% rename from tests/target/issue-2955.rs rename to src/tools/rustfmt/tests/target/issue-2955.rs diff --git a/tests/target/issue-2973.rs b/src/tools/rustfmt/tests/target/issue-2973.rs similarity index 100% rename from tests/target/issue-2973.rs rename to src/tools/rustfmt/tests/target/issue-2973.rs diff --git a/tests/target/issue-2976.rs b/src/tools/rustfmt/tests/target/issue-2976.rs similarity index 100% rename from tests/target/issue-2976.rs rename to src/tools/rustfmt/tests/target/issue-2976.rs diff --git a/tests/target/issue-2977/block.rs b/src/tools/rustfmt/tests/target/issue-2977/block.rs similarity index 100% rename from tests/target/issue-2977/block.rs rename to src/tools/rustfmt/tests/target/issue-2977/block.rs diff --git a/tests/target/issue-2977/impl.rs b/src/tools/rustfmt/tests/target/issue-2977/impl.rs similarity index 100% rename from tests/target/issue-2977/impl.rs rename to src/tools/rustfmt/tests/target/issue-2977/impl.rs diff --git a/tests/target/issue-2977/item.rs b/src/tools/rustfmt/tests/target/issue-2977/item.rs similarity index 100% rename from tests/target/issue-2977/item.rs rename to src/tools/rustfmt/tests/target/issue-2977/item.rs diff --git a/tests/target/issue-2977/trait.rs b/src/tools/rustfmt/tests/target/issue-2977/trait.rs similarity index 100% rename from tests/target/issue-2977/trait.rs rename to src/tools/rustfmt/tests/target/issue-2977/trait.rs diff --git a/tests/target/issue-2985.rs b/src/tools/rustfmt/tests/target/issue-2985.rs similarity index 100% rename from tests/target/issue-2985.rs rename to src/tools/rustfmt/tests/target/issue-2985.rs diff --git a/tests/target/issue-2995.rs b/src/tools/rustfmt/tests/target/issue-2995.rs similarity index 100% rename from tests/target/issue-2995.rs rename to src/tools/rustfmt/tests/target/issue-2995.rs diff --git a/tests/target/issue-3029.rs b/src/tools/rustfmt/tests/target/issue-3029.rs similarity index 100% rename from tests/target/issue-3029.rs rename to src/tools/rustfmt/tests/target/issue-3029.rs diff --git a/tests/target/issue-3032.rs b/src/tools/rustfmt/tests/target/issue-3032.rs similarity index 100% rename from tests/target/issue-3032.rs rename to src/tools/rustfmt/tests/target/issue-3032.rs diff --git a/tests/target/issue-3038.rs b/src/tools/rustfmt/tests/target/issue-3038.rs similarity index 100% rename from tests/target/issue-3038.rs rename to src/tools/rustfmt/tests/target/issue-3038.rs diff --git a/tests/target/issue-3043.rs b/src/tools/rustfmt/tests/target/issue-3043.rs similarity index 100% rename from tests/target/issue-3043.rs rename to src/tools/rustfmt/tests/target/issue-3043.rs diff --git a/tests/target/issue-3049.rs b/src/tools/rustfmt/tests/target/issue-3049.rs similarity index 100% rename from tests/target/issue-3049.rs rename to src/tools/rustfmt/tests/target/issue-3049.rs diff --git a/tests/target/issue-3055/backtick.rs b/src/tools/rustfmt/tests/target/issue-3055/backtick.rs similarity index 100% rename from tests/target/issue-3055/backtick.rs rename to src/tools/rustfmt/tests/target/issue-3055/backtick.rs diff --git a/tests/target/issue-3055/empty-code-block.rs b/src/tools/rustfmt/tests/target/issue-3055/empty-code-block.rs similarity index 100% rename from tests/target/issue-3055/empty-code-block.rs rename to src/tools/rustfmt/tests/target/issue-3055/empty-code-block.rs diff --git a/tests/target/issue-3055/original.rs b/src/tools/rustfmt/tests/target/issue-3055/original.rs similarity index 100% rename from tests/target/issue-3055/original.rs rename to src/tools/rustfmt/tests/target/issue-3055/original.rs diff --git a/tests/target/issue-3059.rs b/src/tools/rustfmt/tests/target/issue-3059.rs similarity index 100% rename from tests/target/issue-3059.rs rename to src/tools/rustfmt/tests/target/issue-3059.rs diff --git a/tests/target/issue-3066.rs b/src/tools/rustfmt/tests/target/issue-3066.rs similarity index 100% rename from tests/target/issue-3066.rs rename to src/tools/rustfmt/tests/target/issue-3066.rs diff --git a/tests/target/issue-3105.rs b/src/tools/rustfmt/tests/target/issue-3105.rs similarity index 100% rename from tests/target/issue-3105.rs rename to src/tools/rustfmt/tests/target/issue-3105.rs diff --git a/tests/target/issue-3118.rs b/src/tools/rustfmt/tests/target/issue-3118.rs similarity index 100% rename from tests/target/issue-3118.rs rename to src/tools/rustfmt/tests/target/issue-3118.rs diff --git a/tests/target/issue-3124.rs b/src/tools/rustfmt/tests/target/issue-3124.rs similarity index 100% rename from tests/target/issue-3124.rs rename to src/tools/rustfmt/tests/target/issue-3124.rs diff --git a/tests/target/issue-3131.rs b/src/tools/rustfmt/tests/target/issue-3131.rs similarity index 100% rename from tests/target/issue-3131.rs rename to src/tools/rustfmt/tests/target/issue-3131.rs diff --git a/tests/target/issue-3132.rs b/src/tools/rustfmt/tests/target/issue-3132.rs similarity index 100% rename from tests/target/issue-3132.rs rename to src/tools/rustfmt/tests/target/issue-3132.rs diff --git a/tests/target/issue-3153.rs b/src/tools/rustfmt/tests/target/issue-3153.rs similarity index 100% rename from tests/target/issue-3153.rs rename to src/tools/rustfmt/tests/target/issue-3153.rs diff --git a/tests/target/issue-3158.rs b/src/tools/rustfmt/tests/target/issue-3158.rs similarity index 100% rename from tests/target/issue-3158.rs rename to src/tools/rustfmt/tests/target/issue-3158.rs diff --git a/tests/target/issue-3182.rs b/src/tools/rustfmt/tests/target/issue-3182.rs similarity index 100% rename from tests/target/issue-3182.rs rename to src/tools/rustfmt/tests/target/issue-3182.rs diff --git a/tests/target/issue-3184.rs b/src/tools/rustfmt/tests/target/issue-3184.rs similarity index 100% rename from tests/target/issue-3184.rs rename to src/tools/rustfmt/tests/target/issue-3184.rs diff --git a/tests/target/issue-3194.rs b/src/tools/rustfmt/tests/target/issue-3194.rs similarity index 100% rename from tests/target/issue-3194.rs rename to src/tools/rustfmt/tests/target/issue-3194.rs diff --git a/tests/target/issue-3198.rs b/src/tools/rustfmt/tests/target/issue-3198.rs similarity index 100% rename from tests/target/issue-3198.rs rename to src/tools/rustfmt/tests/target/issue-3198.rs diff --git a/tests/target/issue-3213/version_one.rs b/src/tools/rustfmt/tests/target/issue-3213/version_one.rs similarity index 100% rename from tests/target/issue-3213/version_one.rs rename to src/tools/rustfmt/tests/target/issue-3213/version_one.rs diff --git a/tests/target/issue-3213/version_two.rs b/src/tools/rustfmt/tests/target/issue-3213/version_two.rs similarity index 100% rename from tests/target/issue-3213/version_two.rs rename to src/tools/rustfmt/tests/target/issue-3213/version_two.rs diff --git a/tests/target/issue-3217.rs b/src/tools/rustfmt/tests/target/issue-3217.rs similarity index 100% rename from tests/target/issue-3217.rs rename to src/tools/rustfmt/tests/target/issue-3217.rs diff --git a/tests/target/issue-3224.rs b/src/tools/rustfmt/tests/target/issue-3224.rs similarity index 100% rename from tests/target/issue-3224.rs rename to src/tools/rustfmt/tests/target/issue-3224.rs diff --git a/tests/target/issue-3227/one.rs b/src/tools/rustfmt/tests/target/issue-3227/one.rs similarity index 100% rename from tests/target/issue-3227/one.rs rename to src/tools/rustfmt/tests/target/issue-3227/one.rs diff --git a/tests/target/issue-3227/two.rs b/src/tools/rustfmt/tests/target/issue-3227/two.rs similarity index 100% rename from tests/target/issue-3227/two.rs rename to src/tools/rustfmt/tests/target/issue-3227/two.rs diff --git a/tests/target/issue-3234.rs b/src/tools/rustfmt/tests/target/issue-3234.rs similarity index 100% rename from tests/target/issue-3234.rs rename to src/tools/rustfmt/tests/target/issue-3234.rs diff --git a/tests/target/issue-3241.rs b/src/tools/rustfmt/tests/target/issue-3241.rs similarity index 100% rename from tests/target/issue-3241.rs rename to src/tools/rustfmt/tests/target/issue-3241.rs diff --git a/tests/target/issue-3253/bar.rs b/src/tools/rustfmt/tests/target/issue-3253/bar.rs similarity index 100% rename from tests/target/issue-3253/bar.rs rename to src/tools/rustfmt/tests/target/issue-3253/bar.rs diff --git a/tests/target/issue-3253/foo.rs b/src/tools/rustfmt/tests/target/issue-3253/foo.rs similarity index 100% rename from tests/target/issue-3253/foo.rs rename to src/tools/rustfmt/tests/target/issue-3253/foo.rs diff --git a/tests/target/issue-3253/lib.rs b/src/tools/rustfmt/tests/target/issue-3253/lib.rs similarity index 100% rename from tests/target/issue-3253/lib.rs rename to src/tools/rustfmt/tests/target/issue-3253/lib.rs diff --git a/tests/target/issue-3253/paths/bar_foo.rs b/src/tools/rustfmt/tests/target/issue-3253/paths/bar_foo.rs similarity index 100% rename from tests/target/issue-3253/paths/bar_foo.rs rename to src/tools/rustfmt/tests/target/issue-3253/paths/bar_foo.rs diff --git a/tests/target/issue-3253/paths/excluded.rs b/src/tools/rustfmt/tests/target/issue-3253/paths/excluded.rs similarity index 100% rename from tests/target/issue-3253/paths/excluded.rs rename to src/tools/rustfmt/tests/target/issue-3253/paths/excluded.rs diff --git a/tests/target/issue-3253/paths/foo_bar.rs b/src/tools/rustfmt/tests/target/issue-3253/paths/foo_bar.rs similarity index 100% rename from tests/target/issue-3253/paths/foo_bar.rs rename to src/tools/rustfmt/tests/target/issue-3253/paths/foo_bar.rs diff --git a/tests/target/issue-3265.rs b/src/tools/rustfmt/tests/target/issue-3265.rs similarity index 100% rename from tests/target/issue-3265.rs rename to src/tools/rustfmt/tests/target/issue-3265.rs diff --git a/tests/target/issue-3270/one.rs b/src/tools/rustfmt/tests/target/issue-3270/one.rs similarity index 100% rename from tests/target/issue-3270/one.rs rename to src/tools/rustfmt/tests/target/issue-3270/one.rs diff --git a/tests/target/issue-3270/two.rs b/src/tools/rustfmt/tests/target/issue-3270/two.rs similarity index 100% rename from tests/target/issue-3270/two.rs rename to src/tools/rustfmt/tests/target/issue-3270/two.rs diff --git a/tests/target/issue-3270/wrap.rs b/src/tools/rustfmt/tests/target/issue-3270/wrap.rs similarity index 100% rename from tests/target/issue-3270/wrap.rs rename to src/tools/rustfmt/tests/target/issue-3270/wrap.rs diff --git a/tests/target/issue-3272/v1.rs b/src/tools/rustfmt/tests/target/issue-3272/v1.rs similarity index 100% rename from tests/target/issue-3272/v1.rs rename to src/tools/rustfmt/tests/target/issue-3272/v1.rs diff --git a/tests/target/issue-3272/v2.rs b/src/tools/rustfmt/tests/target/issue-3272/v2.rs similarity index 100% rename from tests/target/issue-3272/v2.rs rename to src/tools/rustfmt/tests/target/issue-3272/v2.rs diff --git a/tests/target/issue-3278/version_one.rs b/src/tools/rustfmt/tests/target/issue-3278/version_one.rs similarity index 100% rename from tests/target/issue-3278/version_one.rs rename to src/tools/rustfmt/tests/target/issue-3278/version_one.rs diff --git a/tests/target/issue-3278/version_two.rs b/src/tools/rustfmt/tests/target/issue-3278/version_two.rs similarity index 100% rename from tests/target/issue-3278/version_two.rs rename to src/tools/rustfmt/tests/target/issue-3278/version_two.rs diff --git a/tests/target/issue-3295/two.rs b/src/tools/rustfmt/tests/target/issue-3295/two.rs similarity index 100% rename from tests/target/issue-3295/two.rs rename to src/tools/rustfmt/tests/target/issue-3295/two.rs diff --git a/tests/target/issue-3302.rs b/src/tools/rustfmt/tests/target/issue-3302.rs similarity index 100% rename from tests/target/issue-3302.rs rename to src/tools/rustfmt/tests/target/issue-3302.rs diff --git a/tests/target/issue-3304.rs b/src/tools/rustfmt/tests/target/issue-3304.rs similarity index 100% rename from tests/target/issue-3304.rs rename to src/tools/rustfmt/tests/target/issue-3304.rs diff --git a/tests/target/issue-3314.rs b/src/tools/rustfmt/tests/target/issue-3314.rs similarity index 100% rename from tests/target/issue-3314.rs rename to src/tools/rustfmt/tests/target/issue-3314.rs diff --git a/tests/target/issue-3343.rs b/src/tools/rustfmt/tests/target/issue-3343.rs similarity index 100% rename from tests/target/issue-3343.rs rename to src/tools/rustfmt/tests/target/issue-3343.rs diff --git a/tests/target/issue-3423.rs b/src/tools/rustfmt/tests/target/issue-3423.rs similarity index 100% rename from tests/target/issue-3423.rs rename to src/tools/rustfmt/tests/target/issue-3423.rs diff --git a/tests/target/issue-3434/lib.rs b/src/tools/rustfmt/tests/target/issue-3434/lib.rs similarity index 100% rename from tests/target/issue-3434/lib.rs rename to src/tools/rustfmt/tests/target/issue-3434/lib.rs diff --git a/tests/target/issue-3434/no_entry.rs b/src/tools/rustfmt/tests/target/issue-3434/no_entry.rs similarity index 100% rename from tests/target/issue-3434/no_entry.rs rename to src/tools/rustfmt/tests/target/issue-3434/no_entry.rs diff --git a/tests/target/issue-3434/not_skip_macro.rs b/src/tools/rustfmt/tests/target/issue-3434/not_skip_macro.rs similarity index 100% rename from tests/target/issue-3434/not_skip_macro.rs rename to src/tools/rustfmt/tests/target/issue-3434/not_skip_macro.rs diff --git a/tests/target/issue-3442.rs b/src/tools/rustfmt/tests/target/issue-3442.rs similarity index 100% rename from tests/target/issue-3442.rs rename to src/tools/rustfmt/tests/target/issue-3442.rs diff --git a/tests/target/issue-3465.rs b/src/tools/rustfmt/tests/target/issue-3465.rs similarity index 100% rename from tests/target/issue-3465.rs rename to src/tools/rustfmt/tests/target/issue-3465.rs diff --git a/tests/target/issue-3494/crlf.rs b/src/tools/rustfmt/tests/target/issue-3494/crlf.rs similarity index 100% rename from tests/target/issue-3494/crlf.rs rename to src/tools/rustfmt/tests/target/issue-3494/crlf.rs diff --git a/tests/target/issue-3494/lf.rs b/src/tools/rustfmt/tests/target/issue-3494/lf.rs similarity index 100% rename from tests/target/issue-3494/lf.rs rename to src/tools/rustfmt/tests/target/issue-3494/lf.rs diff --git a/tests/target/issue-3499.rs b/src/tools/rustfmt/tests/target/issue-3499.rs similarity index 100% rename from tests/target/issue-3499.rs rename to src/tools/rustfmt/tests/target/issue-3499.rs diff --git a/tests/target/issue-3508.rs b/src/tools/rustfmt/tests/target/issue-3508.rs similarity index 100% rename from tests/target/issue-3508.rs rename to src/tools/rustfmt/tests/target/issue-3508.rs diff --git a/tests/target/issue-3515.rs b/src/tools/rustfmt/tests/target/issue-3515.rs similarity index 100% rename from tests/target/issue-3515.rs rename to src/tools/rustfmt/tests/target/issue-3515.rs diff --git a/tests/target/issue-3532.rs b/src/tools/rustfmt/tests/target/issue-3532.rs similarity index 100% rename from tests/target/issue-3532.rs rename to src/tools/rustfmt/tests/target/issue-3532.rs diff --git a/tests/target/issue-3539.rs b/src/tools/rustfmt/tests/target/issue-3539.rs similarity index 100% rename from tests/target/issue-3539.rs rename to src/tools/rustfmt/tests/target/issue-3539.rs diff --git a/tests/target/issue-3554.rs b/src/tools/rustfmt/tests/target/issue-3554.rs similarity index 100% rename from tests/target/issue-3554.rs rename to src/tools/rustfmt/tests/target/issue-3554.rs diff --git a/tests/target/issue-3567.rs b/src/tools/rustfmt/tests/target/issue-3567.rs similarity index 100% rename from tests/target/issue-3567.rs rename to src/tools/rustfmt/tests/target/issue-3567.rs diff --git a/tests/target/issue-3568.rs b/src/tools/rustfmt/tests/target/issue-3568.rs similarity index 100% rename from tests/target/issue-3568.rs rename to src/tools/rustfmt/tests/target/issue-3568.rs diff --git a/tests/target/issue-3585/extern_crate.rs b/src/tools/rustfmt/tests/target/issue-3585/extern_crate.rs similarity index 100% rename from tests/target/issue-3585/extern_crate.rs rename to src/tools/rustfmt/tests/target/issue-3585/extern_crate.rs diff --git a/tests/target/issue-3585/reorder_imports_disabled.rs b/src/tools/rustfmt/tests/target/issue-3585/reorder_imports_disabled.rs similarity index 100% rename from tests/target/issue-3585/reorder_imports_disabled.rs rename to src/tools/rustfmt/tests/target/issue-3585/reorder_imports_disabled.rs diff --git a/tests/target/issue-3585/reorder_imports_enabled.rs b/src/tools/rustfmt/tests/target/issue-3585/reorder_imports_enabled.rs similarity index 100% rename from tests/target/issue-3585/reorder_imports_enabled.rs rename to src/tools/rustfmt/tests/target/issue-3585/reorder_imports_enabled.rs diff --git a/tests/target/issue-3585/use.rs b/src/tools/rustfmt/tests/target/issue-3585/use.rs similarity index 100% rename from tests/target/issue-3585/use.rs rename to src/tools/rustfmt/tests/target/issue-3585/use.rs diff --git a/tests/target/issue-3595.rs b/src/tools/rustfmt/tests/target/issue-3595.rs similarity index 100% rename from tests/target/issue-3595.rs rename to src/tools/rustfmt/tests/target/issue-3595.rs diff --git a/tests/target/issue-3601.rs b/src/tools/rustfmt/tests/target/issue-3601.rs similarity index 100% rename from tests/target/issue-3601.rs rename to src/tools/rustfmt/tests/target/issue-3601.rs diff --git a/tests/target/issue-3614/version_one.rs b/src/tools/rustfmt/tests/target/issue-3614/version_one.rs similarity index 100% rename from tests/target/issue-3614/version_one.rs rename to src/tools/rustfmt/tests/target/issue-3614/version_one.rs diff --git a/tests/target/issue-3614/version_two.rs b/src/tools/rustfmt/tests/target/issue-3614/version_two.rs similarity index 100% rename from tests/target/issue-3614/version_two.rs rename to src/tools/rustfmt/tests/target/issue-3614/version_two.rs diff --git a/tests/target/issue-3636.rs b/src/tools/rustfmt/tests/target/issue-3636.rs similarity index 100% rename from tests/target/issue-3636.rs rename to src/tools/rustfmt/tests/target/issue-3636.rs diff --git a/tests/target/issue-3639.rs b/src/tools/rustfmt/tests/target/issue-3639.rs similarity index 100% rename from tests/target/issue-3639.rs rename to src/tools/rustfmt/tests/target/issue-3639.rs diff --git a/tests/target/issue-3645.rs b/src/tools/rustfmt/tests/target/issue-3645.rs similarity index 100% rename from tests/target/issue-3645.rs rename to src/tools/rustfmt/tests/target/issue-3645.rs diff --git a/tests/target/issue-3651.rs b/src/tools/rustfmt/tests/target/issue-3651.rs similarity index 100% rename from tests/target/issue-3651.rs rename to src/tools/rustfmt/tests/target/issue-3651.rs diff --git a/tests/target/issue-3665/lib.rs b/src/tools/rustfmt/tests/target/issue-3665/lib.rs similarity index 100% rename from tests/target/issue-3665/lib.rs rename to src/tools/rustfmt/tests/target/issue-3665/lib.rs diff --git a/tests/target/issue-3665/not_skip_attribute.rs b/src/tools/rustfmt/tests/target/issue-3665/not_skip_attribute.rs similarity index 100% rename from tests/target/issue-3665/not_skip_attribute.rs rename to src/tools/rustfmt/tests/target/issue-3665/not_skip_attribute.rs diff --git a/tests/target/issue-3665/sub_mod.rs b/src/tools/rustfmt/tests/target/issue-3665/sub_mod.rs similarity index 100% rename from tests/target/issue-3665/sub_mod.rs rename to src/tools/rustfmt/tests/target/issue-3665/sub_mod.rs diff --git a/tests/target/issue-3672.rs b/src/tools/rustfmt/tests/target/issue-3672.rs similarity index 100% rename from tests/target/issue-3672.rs rename to src/tools/rustfmt/tests/target/issue-3672.rs diff --git a/tests/target/issue-3675.rs b/src/tools/rustfmt/tests/target/issue-3675.rs similarity index 100% rename from tests/target/issue-3675.rs rename to src/tools/rustfmt/tests/target/issue-3675.rs diff --git a/tests/target/issue-3701/one.rs b/src/tools/rustfmt/tests/target/issue-3701/one.rs similarity index 100% rename from tests/target/issue-3701/one.rs rename to src/tools/rustfmt/tests/target/issue-3701/one.rs diff --git a/tests/target/issue-3701/two.rs b/src/tools/rustfmt/tests/target/issue-3701/two.rs similarity index 100% rename from tests/target/issue-3701/two.rs rename to src/tools/rustfmt/tests/target/issue-3701/two.rs diff --git a/tests/target/issue-3709.rs b/src/tools/rustfmt/tests/target/issue-3709.rs similarity index 100% rename from tests/target/issue-3709.rs rename to src/tools/rustfmt/tests/target/issue-3709.rs diff --git a/tests/target/issue-3711.rs b/src/tools/rustfmt/tests/target/issue-3711.rs similarity index 100% rename from tests/target/issue-3711.rs rename to src/tools/rustfmt/tests/target/issue-3711.rs diff --git a/tests/target/issue-3717.rs b/src/tools/rustfmt/tests/target/issue-3717.rs similarity index 100% rename from tests/target/issue-3717.rs rename to src/tools/rustfmt/tests/target/issue-3717.rs diff --git a/tests/target/issue-3718.rs b/src/tools/rustfmt/tests/target/issue-3718.rs similarity index 100% rename from tests/target/issue-3718.rs rename to src/tools/rustfmt/tests/target/issue-3718.rs diff --git a/tests/target/issue-3740.rs b/src/tools/rustfmt/tests/target/issue-3740.rs similarity index 100% rename from tests/target/issue-3740.rs rename to src/tools/rustfmt/tests/target/issue-3740.rs diff --git a/tests/target/issue-3741.rs b/src/tools/rustfmt/tests/target/issue-3741.rs similarity index 100% rename from tests/target/issue-3741.rs rename to src/tools/rustfmt/tests/target/issue-3741.rs diff --git a/tests/target/issue-3750.rs b/src/tools/rustfmt/tests/target/issue-3750.rs similarity index 100% rename from tests/target/issue-3750.rs rename to src/tools/rustfmt/tests/target/issue-3750.rs diff --git a/tests/target/issue-3751.rs b/src/tools/rustfmt/tests/target/issue-3751.rs similarity index 100% rename from tests/target/issue-3751.rs rename to src/tools/rustfmt/tests/target/issue-3751.rs diff --git a/tests/target/issue-3759.rs b/src/tools/rustfmt/tests/target/issue-3759.rs similarity index 100% rename from tests/target/issue-3759.rs rename to src/tools/rustfmt/tests/target/issue-3759.rs diff --git a/tests/target/issue-3779/ice.rs b/src/tools/rustfmt/tests/target/issue-3779/ice.rs similarity index 100% rename from tests/target/issue-3779/ice.rs rename to src/tools/rustfmt/tests/target/issue-3779/ice.rs diff --git a/tests/target/issue-3779/lib.rs b/src/tools/rustfmt/tests/target/issue-3779/lib.rs similarity index 100% rename from tests/target/issue-3779/lib.rs rename to src/tools/rustfmt/tests/target/issue-3779/lib.rs diff --git a/tests/target/issue-3786.rs b/src/tools/rustfmt/tests/target/issue-3786.rs similarity index 100% rename from tests/target/issue-3786.rs rename to src/tools/rustfmt/tests/target/issue-3786.rs diff --git a/tests/target/issue-3787.rs b/src/tools/rustfmt/tests/target/issue-3787.rs similarity index 100% rename from tests/target/issue-3787.rs rename to src/tools/rustfmt/tests/target/issue-3787.rs diff --git a/tests/target/issue-3805.rs b/src/tools/rustfmt/tests/target/issue-3805.rs similarity index 100% rename from tests/target/issue-3805.rs rename to src/tools/rustfmt/tests/target/issue-3805.rs diff --git a/tests/target/issue-3815.rs b/src/tools/rustfmt/tests/target/issue-3815.rs similarity index 100% rename from tests/target/issue-3815.rs rename to src/tools/rustfmt/tests/target/issue-3815.rs diff --git a/tests/target/issue-3840/version-one_hard-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-one_hard-tabs.rs similarity index 100% rename from tests/target/issue-3840/version-one_hard-tabs.rs rename to src/tools/rustfmt/tests/target/issue-3840/version-one_hard-tabs.rs diff --git a/tests/target/issue-3840/version-one_soft-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-one_soft-tabs.rs similarity index 100% rename from tests/target/issue-3840/version-one_soft-tabs.rs rename to src/tools/rustfmt/tests/target/issue-3840/version-one_soft-tabs.rs diff --git a/tests/target/issue-3840/version-two_hard-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs similarity index 100% rename from tests/target/issue-3840/version-two_hard-tabs.rs rename to src/tools/rustfmt/tests/target/issue-3840/version-two_hard-tabs.rs diff --git a/tests/target/issue-3840/version-two_soft-tabs.rs b/src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs similarity index 100% rename from tests/target/issue-3840/version-two_soft-tabs.rs rename to src/tools/rustfmt/tests/target/issue-3840/version-two_soft-tabs.rs diff --git a/tests/target/issue-3845.rs b/src/tools/rustfmt/tests/target/issue-3845.rs similarity index 100% rename from tests/target/issue-3845.rs rename to src/tools/rustfmt/tests/target/issue-3845.rs diff --git a/tests/target/issue-3882.rs b/src/tools/rustfmt/tests/target/issue-3882.rs similarity index 100% rename from tests/target/issue-3882.rs rename to src/tools/rustfmt/tests/target/issue-3882.rs diff --git a/tests/target/issue-3974.rs b/src/tools/rustfmt/tests/target/issue-3974.rs similarity index 100% rename from tests/target/issue-3974.rs rename to src/tools/rustfmt/tests/target/issue-3974.rs diff --git a/tests/target/issue-3984.rs b/src/tools/rustfmt/tests/target/issue-3984.rs similarity index 100% rename from tests/target/issue-3984.rs rename to src/tools/rustfmt/tests/target/issue-3984.rs diff --git a/tests/target/issue-3987/format_macro_bodies_false.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs similarity index 100% rename from tests/target/issue-3987/format_macro_bodies_false.rs rename to src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_false.rs diff --git a/tests/target/issue-3987/format_macro_bodies_true.rs b/src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs similarity index 100% rename from tests/target/issue-3987/format_macro_bodies_true.rs rename to src/tools/rustfmt/tests/target/issue-3987/format_macro_bodies_true.rs diff --git a/tests/target/issue-4018.rs b/src/tools/rustfmt/tests/target/issue-4018.rs similarity index 100% rename from tests/target/issue-4018.rs rename to src/tools/rustfmt/tests/target/issue-4018.rs diff --git a/tests/target/issue-4020.rs b/src/tools/rustfmt/tests/target/issue-4020.rs similarity index 100% rename from tests/target/issue-4020.rs rename to src/tools/rustfmt/tests/target/issue-4020.rs diff --git a/tests/target/issue-4029.rs b/src/tools/rustfmt/tests/target/issue-4029.rs similarity index 100% rename from tests/target/issue-4029.rs rename to src/tools/rustfmt/tests/target/issue-4029.rs diff --git a/tests/target/issue-4036/one.rs b/src/tools/rustfmt/tests/target/issue-4036/one.rs similarity index 100% rename from tests/target/issue-4036/one.rs rename to src/tools/rustfmt/tests/target/issue-4036/one.rs diff --git a/tests/target/issue-4036/three.rs b/src/tools/rustfmt/tests/target/issue-4036/three.rs similarity index 100% rename from tests/target/issue-4036/three.rs rename to src/tools/rustfmt/tests/target/issue-4036/three.rs diff --git a/tests/target/issue-4036/two.rs b/src/tools/rustfmt/tests/target/issue-4036/two.rs similarity index 100% rename from tests/target/issue-4036/two.rs rename to src/tools/rustfmt/tests/target/issue-4036/two.rs diff --git a/tests/target/issue-4041.rs b/src/tools/rustfmt/tests/target/issue-4041.rs similarity index 100% rename from tests/target/issue-4041.rs rename to src/tools/rustfmt/tests/target/issue-4041.rs diff --git a/tests/target/issue-4068.rs b/src/tools/rustfmt/tests/target/issue-4068.rs similarity index 100% rename from tests/target/issue-4068.rs rename to src/tools/rustfmt/tests/target/issue-4068.rs diff --git a/tests/target/issue-4079.rs b/src/tools/rustfmt/tests/target/issue-4079.rs similarity index 100% rename from tests/target/issue-4079.rs rename to src/tools/rustfmt/tests/target/issue-4079.rs diff --git a/tests/target/issue-4115.rs b/src/tools/rustfmt/tests/target/issue-4115.rs similarity index 100% rename from tests/target/issue-4115.rs rename to src/tools/rustfmt/tests/target/issue-4115.rs diff --git a/tests/target/issue-4120.rs b/src/tools/rustfmt/tests/target/issue-4120.rs similarity index 100% rename from tests/target/issue-4120.rs rename to src/tools/rustfmt/tests/target/issue-4120.rs diff --git a/tests/target/issue-4152.rs b/src/tools/rustfmt/tests/target/issue-4152.rs similarity index 100% rename from tests/target/issue-4152.rs rename to src/tools/rustfmt/tests/target/issue-4152.rs diff --git a/tests/target/issue-4159.rs b/src/tools/rustfmt/tests/target/issue-4159.rs similarity index 100% rename from tests/target/issue-4159.rs rename to src/tools/rustfmt/tests/target/issue-4159.rs diff --git a/tests/target/issue-4210-disabled.rs b/src/tools/rustfmt/tests/target/issue-4210-disabled.rs similarity index 100% rename from tests/target/issue-4210-disabled.rs rename to src/tools/rustfmt/tests/target/issue-4210-disabled.rs diff --git a/tests/target/issue-4210.rs b/src/tools/rustfmt/tests/target/issue-4210.rs similarity index 100% rename from tests/target/issue-4210.rs rename to src/tools/rustfmt/tests/target/issue-4210.rs diff --git a/tests/target/issue-4243.rs b/src/tools/rustfmt/tests/target/issue-4243.rs similarity index 100% rename from tests/target/issue-4243.rs rename to src/tools/rustfmt/tests/target/issue-4243.rs diff --git a/tests/target/issue-4244.rs b/src/tools/rustfmt/tests/target/issue-4244.rs similarity index 100% rename from tests/target/issue-4244.rs rename to src/tools/rustfmt/tests/target/issue-4244.rs diff --git a/tests/target/issue-4245.rs b/src/tools/rustfmt/tests/target/issue-4245.rs similarity index 100% rename from tests/target/issue-4245.rs rename to src/tools/rustfmt/tests/target/issue-4245.rs diff --git a/tests/target/issue-4310.rs b/src/tools/rustfmt/tests/target/issue-4310.rs similarity index 100% rename from tests/target/issue-4310.rs rename to src/tools/rustfmt/tests/target/issue-4310.rs diff --git a/tests/target/issue-4312.rs b/src/tools/rustfmt/tests/target/issue-4312.rs similarity index 100% rename from tests/target/issue-4312.rs rename to src/tools/rustfmt/tests/target/issue-4312.rs diff --git a/tests/target/issue-4313.rs b/src/tools/rustfmt/tests/target/issue-4313.rs similarity index 100% rename from tests/target/issue-4313.rs rename to src/tools/rustfmt/tests/target/issue-4313.rs diff --git a/tests/target/issue-4381/style_edition_2015.rs b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs similarity index 100% rename from tests/target/issue-4381/style_edition_2015.rs rename to src/tools/rustfmt/tests/target/issue-4381/style_edition_2015.rs diff --git a/tests/target/issue-4381/style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs similarity index 100% rename from tests/target/issue-4381/style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue-4381/style_edition_2024.rs diff --git a/tests/target/issue-4382.rs b/src/tools/rustfmt/tests/target/issue-4382.rs similarity index 100% rename from tests/target/issue-4382.rs rename to src/tools/rustfmt/tests/target/issue-4382.rs diff --git a/tests/target/issue-4398.rs b/src/tools/rustfmt/tests/target/issue-4398.rs similarity index 100% rename from tests/target/issue-4398.rs rename to src/tools/rustfmt/tests/target/issue-4398.rs diff --git a/tests/target/issue-4427.rs b/src/tools/rustfmt/tests/target/issue-4427.rs similarity index 100% rename from tests/target/issue-4427.rs rename to src/tools/rustfmt/tests/target/issue-4427.rs diff --git a/tests/target/issue-447.rs b/src/tools/rustfmt/tests/target/issue-447.rs similarity index 100% rename from tests/target/issue-447.rs rename to src/tools/rustfmt/tests/target/issue-447.rs diff --git a/tests/target/issue-4530.rs b/src/tools/rustfmt/tests/target/issue-4530.rs similarity index 100% rename from tests/target/issue-4530.rs rename to src/tools/rustfmt/tests/target/issue-4530.rs diff --git a/tests/target/issue-4577.rs b/src/tools/rustfmt/tests/target/issue-4577.rs similarity index 100% rename from tests/target/issue-4577.rs rename to src/tools/rustfmt/tests/target/issue-4577.rs diff --git a/tests/target/issue-4603.rs b/src/tools/rustfmt/tests/target/issue-4603.rs similarity index 100% rename from tests/target/issue-4603.rs rename to src/tools/rustfmt/tests/target/issue-4603.rs diff --git a/tests/target/issue-4615/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs similarity index 100% rename from tests/target/issue-4615/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-4615/minimum_example.rs diff --git a/tests/target/issue-4643.rs b/src/tools/rustfmt/tests/target/issue-4643.rs similarity index 100% rename from tests/target/issue-4643.rs rename to src/tools/rustfmt/tests/target/issue-4643.rs diff --git a/tests/target/issue-4646.rs b/src/tools/rustfmt/tests/target/issue-4646.rs similarity index 100% rename from tests/target/issue-4646.rs rename to src/tools/rustfmt/tests/target/issue-4646.rs diff --git a/tests/target/issue-4656/format_me_please.rs b/src/tools/rustfmt/tests/target/issue-4656/format_me_please.rs similarity index 100% rename from tests/target/issue-4656/format_me_please.rs rename to src/tools/rustfmt/tests/target/issue-4656/format_me_please.rs diff --git a/tests/target/issue-4656/lib.rs b/src/tools/rustfmt/tests/target/issue-4656/lib.rs similarity index 100% rename from tests/target/issue-4656/lib.rs rename to src/tools/rustfmt/tests/target/issue-4656/lib.rs diff --git a/tests/target/issue-4656/lib2.rs b/src/tools/rustfmt/tests/target/issue-4656/lib2.rs similarity index 100% rename from tests/target/issue-4656/lib2.rs rename to src/tools/rustfmt/tests/target/issue-4656/lib2.rs diff --git a/tests/target/issue-4689/one.rs b/src/tools/rustfmt/tests/target/issue-4689/one.rs similarity index 100% rename from tests/target/issue-4689/one.rs rename to src/tools/rustfmt/tests/target/issue-4689/one.rs diff --git a/tests/target/issue-4689/two.rs b/src/tools/rustfmt/tests/target/issue-4689/two.rs similarity index 100% rename from tests/target/issue-4689/two.rs rename to src/tools/rustfmt/tests/target/issue-4689/two.rs diff --git a/tests/target/issue-4791/buggy.rs b/src/tools/rustfmt/tests/target/issue-4791/buggy.rs similarity index 100% rename from tests/target/issue-4791/buggy.rs rename to src/tools/rustfmt/tests/target/issue-4791/buggy.rs diff --git a/tests/target/issue-4791/issue_4928.rs b/src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs similarity index 100% rename from tests/target/issue-4791/issue_4928.rs rename to src/tools/rustfmt/tests/target/issue-4791/issue_4928.rs diff --git a/tests/target/issue-4791/no_trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-4791/no_trailing_comma.rs similarity index 100% rename from tests/target/issue-4791/no_trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-4791/no_trailing_comma.rs diff --git a/tests/target/issue-4791/trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-4791/trailing_comma.rs similarity index 100% rename from tests/target/issue-4791/trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-4791/trailing_comma.rs diff --git a/tests/target/issue-4808.rs b/src/tools/rustfmt/tests/target/issue-4808.rs similarity index 100% rename from tests/target/issue-4808.rs rename to src/tools/rustfmt/tests/target/issue-4808.rs diff --git a/tests/target/issue-4816/lib.rs b/src/tools/rustfmt/tests/target/issue-4816/lib.rs similarity index 100% rename from tests/target/issue-4816/lib.rs rename to src/tools/rustfmt/tests/target/issue-4816/lib.rs diff --git a/tests/target/issue-4908-2.rs b/src/tools/rustfmt/tests/target/issue-4908-2.rs similarity index 100% rename from tests/target/issue-4908-2.rs rename to src/tools/rustfmt/tests/target/issue-4908-2.rs diff --git a/tests/target/issue-4908.rs b/src/tools/rustfmt/tests/target/issue-4908.rs similarity index 100% rename from tests/target/issue-4908.rs rename to src/tools/rustfmt/tests/target/issue-4908.rs diff --git a/tests/target/issue-4926/deeply_nested_struct.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs similarity index 100% rename from tests/target/issue-4926/deeply_nested_struct.rs rename to src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct.rs diff --git a/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs similarity index 100% rename from tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs rename to src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_long_field_names.rs diff --git a/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs similarity index 100% rename from tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs rename to src/tools/rustfmt/tests/target/issue-4926/deeply_nested_struct_with_many_fields.rs diff --git a/tests/target/issue-4926/enum_struct_field.rs b/src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs similarity index 100% rename from tests/target/issue-4926/enum_struct_field.rs rename to src/tools/rustfmt/tests/target/issue-4926/enum_struct_field.rs diff --git a/tests/target/issue-4926/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs similarity index 100% rename from tests/target/issue-4926/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-4926/minimum_example.rs diff --git a/tests/target/issue-4926/struct_with_long_field_names.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs similarity index 100% rename from tests/target/issue-4926/struct_with_long_field_names.rs rename to src/tools/rustfmt/tests/target/issue-4926/struct_with_long_field_names.rs diff --git a/tests/target/issue-4926/struct_with_many_fields.rs b/src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs similarity index 100% rename from tests/target/issue-4926/struct_with_many_fields.rs rename to src/tools/rustfmt/tests/target/issue-4926/struct_with_many_fields.rs diff --git a/tests/target/issue-4984/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs similarity index 100% rename from tests/target/issue-4984/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-4984/minimum_example.rs diff --git a/tests/target/issue-4984/multi_line_derive.rs b/src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs similarity index 100% rename from tests/target/issue-4984/multi_line_derive.rs rename to src/tools/rustfmt/tests/target/issue-4984/multi_line_derive.rs diff --git a/tests/target/issue-4984/multiple_comments_within.rs b/src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs similarity index 100% rename from tests/target/issue-4984/multiple_comments_within.rs rename to src/tools/rustfmt/tests/target/issue-4984/multiple_comments_within.rs diff --git a/tests/target/issue-4984/should_not_change.rs b/src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs similarity index 100% rename from tests/target/issue-4984/should_not_change.rs rename to src/tools/rustfmt/tests/target/issue-4984/should_not_change.rs diff --git a/tests/target/issue-5005/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs similarity index 100% rename from tests/target/issue-5005/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-5005/minimum_example.rs diff --git a/tests/target/issue-5009/1_minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs similarity index 100% rename from tests/target/issue-5009/1_minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-5009/1_minimum_example.rs diff --git a/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs similarity index 100% rename from tests/target/issue-5009/2_many_in_connectors_in_pattern.rs rename to src/tools/rustfmt/tests/target/issue-5009/2_many_in_connectors_in_pattern.rs diff --git a/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs similarity index 100% rename from tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs rename to src/tools/rustfmt/tests/target/issue-5009/3_nested_for_loop_with_connector_in_pattern.rs diff --git a/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs similarity index 100% rename from tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs rename to src/tools/rustfmt/tests/target/issue-5009/4_nested_for_loop_with_if_elseif_else.rs diff --git a/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs b/src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs similarity index 100% rename from tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs rename to src/tools/rustfmt/tests/target/issue-5009/5_nested_for_loop_with_connector_in_if_elseif_else.rs diff --git a/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs b/src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs similarity index 100% rename from tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs rename to src/tools/rustfmt/tests/target/issue-5009/6_deeply_nested_for_loop_with_connector_in_pattern.rs diff --git a/tests/target/issue-5011.rs b/src/tools/rustfmt/tests/target/issue-5011.rs similarity index 100% rename from tests/target/issue-5011.rs rename to src/tools/rustfmt/tests/target/issue-5011.rs diff --git a/tests/target/issue-5012/trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs similarity index 100% rename from tests/target/issue-5012/trailing_comma_always.rs rename to src/tools/rustfmt/tests/target/issue-5012/trailing_comma_always.rs diff --git a/tests/target/issue-5012/trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs similarity index 100% rename from tests/target/issue-5012/trailing_comma_never.rs rename to src/tools/rustfmt/tests/target/issue-5012/trailing_comma_never.rs diff --git a/tests/target/issue-5023.rs b/src/tools/rustfmt/tests/target/issue-5023.rs similarity index 100% rename from tests/target/issue-5023.rs rename to src/tools/rustfmt/tests/target/issue-5023.rs diff --git a/tests/target/issue-5030.rs b/src/tools/rustfmt/tests/target/issue-5030.rs similarity index 100% rename from tests/target/issue-5030.rs rename to src/tools/rustfmt/tests/target/issue-5030.rs diff --git a/tests/target/issue-5033/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs similarity index 100% rename from tests/target/issue-5033/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-5033/minimum_example.rs diff --git a/tests/target/issue-5033/nested_modules.rs b/src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs similarity index 100% rename from tests/target/issue-5033/nested_modules.rs rename to src/tools/rustfmt/tests/target/issue-5033/nested_modules.rs diff --git a/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs similarity index 100% rename from tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-5042/multi-line_comment_with_trailing_comma.rs diff --git a/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs similarity index 100% rename from tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-5042/multi-line_comment_without_trailing_comma.rs diff --git a/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs similarity index 100% rename from tests/target/issue-5042/single-line_comment_with_trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-5042/single-line_comment_with_trailing_comma.rs diff --git a/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs b/src/tools/rustfmt/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs similarity index 100% rename from tests/target/issue-5042/single-line_comment_without_trailing_comma.rs rename to src/tools/rustfmt/tests/target/issue-5042/single-line_comment_without_trailing_comma.rs diff --git a/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs similarity index 100% rename from tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs rename to src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_always_struct_lit_width_0.rs diff --git a/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs similarity index 100% rename from tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs rename to src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_trailing_comma_never_struct_lit_width_0.rs diff --git a/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs similarity index 100% rename from tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs rename to src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_always.rs diff --git a/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs similarity index 100% rename from tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs rename to src/tools/rustfmt/tests/target/issue-5066/multi_line_struct_with_trailing_comma_never.rs diff --git a/tests/target/issue-5066/with_trailing_comma_always.rs b/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_always.rs similarity index 100% rename from tests/target/issue-5066/with_trailing_comma_always.rs rename to src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_always.rs diff --git a/tests/target/issue-5066/with_trailing_comma_never.rs b/src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs similarity index 100% rename from tests/target/issue-5066/with_trailing_comma_never.rs rename to src/tools/rustfmt/tests/target/issue-5066/with_trailing_comma_never.rs diff --git a/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_false.rs diff --git a/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/deeply_nested_long_comment_wrap_comments_true.rs diff --git a/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_false.rs diff --git a/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/multi_line_itemized_block_wrap_comments_true.rs diff --git a/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_false.rs diff --git a/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/multi_line_text_with_itemized_block_wrap_comments_true.rs diff --git a/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_false.rs diff --git a/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/single_line_itemized_block_wrap_comments_true.rs diff --git a/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_false.rs diff --git a/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_very_long_itemized_block_wrap_comments_true.rs diff --git a/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_false.rs diff --git a/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/start_with_empty_comment_wrap_comments_true.rs diff --git a/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5088/very_long_comment_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_false.rs diff --git a/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5088/very_long_comment_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5088/very_long_comment_wrap_comments_true.rs diff --git a/tests/target/issue-5095.rs b/src/tools/rustfmt/tests/target/issue-5095.rs similarity index 100% rename from tests/target/issue-5095.rs rename to src/tools/rustfmt/tests/target/issue-5095.rs diff --git a/tests/target/issue-510.rs b/src/tools/rustfmt/tests/target/issue-510.rs similarity index 100% rename from tests/target/issue-510.rs rename to src/tools/rustfmt/tests/target/issue-510.rs diff --git a/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs b/src/tools/rustfmt/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs similarity index 100% rename from tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs rename to src/tools/rustfmt/tests/target/issue-5125/attributes_in_formal_fuction_parameter.rs diff --git a/tests/target/issue-5125/long_parameter_in_different_positions.rs b/src/tools/rustfmt/tests/target/issue-5125/long_parameter_in_different_positions.rs similarity index 100% rename from tests/target/issue-5125/long_parameter_in_different_positions.rs rename to src/tools/rustfmt/tests/target/issue-5125/long_parameter_in_different_positions.rs diff --git a/tests/target/issue-5125/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5125/minimum_example.rs similarity index 100% rename from tests/target/issue-5125/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-5125/minimum_example.rs diff --git a/tests/target/issue-5125/with_leading_and_inline_comments.rs b/src/tools/rustfmt/tests/target/issue-5125/with_leading_and_inline_comments.rs similarity index 100% rename from tests/target/issue-5125/with_leading_and_inline_comments.rs rename to src/tools/rustfmt/tests/target/issue-5125/with_leading_and_inline_comments.rs diff --git a/tests/target/issue-5136-1.rs b/src/tools/rustfmt/tests/target/issue-5136-1.rs similarity index 100% rename from tests/target/issue-5136-1.rs rename to src/tools/rustfmt/tests/target/issue-5136-1.rs diff --git a/tests/target/issue-5136-2.rs b/src/tools/rustfmt/tests/target/issue-5136-2.rs similarity index 100% rename from tests/target/issue-5136-2.rs rename to src/tools/rustfmt/tests/target/issue-5136-2.rs diff --git a/tests/target/issue-5136-3.rs b/src/tools/rustfmt/tests/target/issue-5136-3.rs similarity index 100% rename from tests/target/issue-5136-3.rs rename to src/tools/rustfmt/tests/target/issue-5136-3.rs diff --git a/tests/target/issue-5136-4.rs b/src/tools/rustfmt/tests/target/issue-5136-4.rs similarity index 100% rename from tests/target/issue-5136-4.rs rename to src/tools/rustfmt/tests/target/issue-5136-4.rs diff --git a/tests/target/issue-5136-5.rs b/src/tools/rustfmt/tests/target/issue-5136-5.rs similarity index 100% rename from tests/target/issue-5136-5.rs rename to src/tools/rustfmt/tests/target/issue-5136-5.rs diff --git a/tests/target/issue-5151/minimum_example.rs b/src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs similarity index 100% rename from tests/target/issue-5151/minimum_example.rs rename to src/tools/rustfmt/tests/target/issue-5151/minimum_example.rs diff --git a/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs similarity index 100% rename from tests/target/issue-5157/indented_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/target/issue-5157/indented_itemized_markdown_blockquote.rs diff --git a/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs similarity index 100% rename from tests/target/issue-5157/nested_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/target/issue-5157/nested_itemized_markdown_blockquote.rs diff --git a/tests/target/issue-5157/support_itemized_markdown_blockquote.rs b/src/tools/rustfmt/tests/target/issue-5157/support_itemized_markdown_blockquote.rs similarity index 100% rename from tests/target/issue-5157/support_itemized_markdown_blockquote.rs rename to src/tools/rustfmt/tests/target/issue-5157/support_itemized_markdown_blockquote.rs diff --git a/tests/target/issue-5234.rs b/src/tools/rustfmt/tests/target/issue-5234.rs similarity index 100% rename from tests/target/issue-5234.rs rename to src/tools/rustfmt/tests/target/issue-5234.rs diff --git a/tests/target/issue-5238/markdown_header_wrap_comments_false.rs b/src/tools/rustfmt/tests/target/issue-5238/markdown_header_wrap_comments_false.rs similarity index 100% rename from tests/target/issue-5238/markdown_header_wrap_comments_false.rs rename to src/tools/rustfmt/tests/target/issue-5238/markdown_header_wrap_comments_false.rs diff --git a/tests/target/issue-5238/markdown_header_wrap_comments_true.rs b/src/tools/rustfmt/tests/target/issue-5238/markdown_header_wrap_comments_true.rs similarity index 100% rename from tests/target/issue-5238/markdown_header_wrap_comments_true.rs rename to src/tools/rustfmt/tests/target/issue-5238/markdown_header_wrap_comments_true.rs diff --git a/tests/target/issue-5244/unwrapped.rs b/src/tools/rustfmt/tests/target/issue-5244/unwrapped.rs similarity index 100% rename from tests/target/issue-5244/unwrapped.rs rename to src/tools/rustfmt/tests/target/issue-5244/unwrapped.rs diff --git a/tests/target/issue-5244/wrapped.rs b/src/tools/rustfmt/tests/target/issue-5244/wrapped.rs similarity index 100% rename from tests/target/issue-5244/wrapped.rs rename to src/tools/rustfmt/tests/target/issue-5244/wrapped.rs diff --git a/tests/target/issue-5260.rs b/src/tools/rustfmt/tests/target/issue-5260.rs similarity index 100% rename from tests/target/issue-5260.rs rename to src/tools/rustfmt/tests/target/issue-5260.rs diff --git a/tests/target/issue-5270/merge_derives_false.rs b/src/tools/rustfmt/tests/target/issue-5270/merge_derives_false.rs similarity index 100% rename from tests/target/issue-5270/merge_derives_false.rs rename to src/tools/rustfmt/tests/target/issue-5270/merge_derives_false.rs diff --git a/tests/target/issue-5270/merge_derives_true.rs b/src/tools/rustfmt/tests/target/issue-5270/merge_derives_true.rs similarity index 100% rename from tests/target/issue-5270/merge_derives_true.rs rename to src/tools/rustfmt/tests/target/issue-5270/merge_derives_true.rs diff --git a/tests/target/issue-5358.rs b/src/tools/rustfmt/tests/target/issue-5358.rs similarity index 100% rename from tests/target/issue-5358.rs rename to src/tools/rustfmt/tests/target/issue-5358.rs diff --git a/tests/target/issue-539.rs b/src/tools/rustfmt/tests/target/issue-539.rs similarity index 100% rename from tests/target/issue-539.rs rename to src/tools/rustfmt/tests/target/issue-539.rs diff --git a/tests/target/issue-5488.rs b/src/tools/rustfmt/tests/target/issue-5488.rs similarity index 100% rename from tests/target/issue-5488.rs rename to src/tools/rustfmt/tests/target/issue-5488.rs diff --git a/tests/target/issue-5568.rs b/src/tools/rustfmt/tests/target/issue-5568.rs similarity index 100% rename from tests/target/issue-5568.rs rename to src/tools/rustfmt/tests/target/issue-5568.rs diff --git a/tests/target/issue-5586.rs b/src/tools/rustfmt/tests/target/issue-5586.rs similarity index 100% rename from tests/target/issue-5586.rs rename to src/tools/rustfmt/tests/target/issue-5586.rs diff --git a/tests/target/issue-5655/one.rs b/src/tools/rustfmt/tests/target/issue-5655/one.rs similarity index 100% rename from tests/target/issue-5655/one.rs rename to src/tools/rustfmt/tests/target/issue-5655/one.rs diff --git a/tests/target/issue-5655/two.rs b/src/tools/rustfmt/tests/target/issue-5655/two.rs similarity index 100% rename from tests/target/issue-5655/two.rs rename to src/tools/rustfmt/tests/target/issue-5655/two.rs diff --git a/tests/target/issue-5791.rs b/src/tools/rustfmt/tests/target/issue-5791.rs similarity index 100% rename from tests/target/issue-5791.rs rename to src/tools/rustfmt/tests/target/issue-5791.rs diff --git a/tests/target/issue-5797/retain_trailing_semicolon.rs b/src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs similarity index 100% rename from tests/target/issue-5797/retain_trailing_semicolon.rs rename to src/tools/rustfmt/tests/target/issue-5797/retain_trailing_semicolon.rs diff --git a/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs similarity index 100% rename from tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs rename to src/tools/rustfmt/tests/target/issue-5801/attribute_does_not_wrap_within_max_width.rs diff --git a/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs similarity index 100% rename from tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs rename to src/tools/rustfmt/tests/target/issue-5801/attribute_unexpectedly_wraps_before_max_width.rs diff --git a/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs similarity index 100% rename from tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs rename to src/tools/rustfmt/tests/target/issue-5801/comment_does_not_wrap_within_max_width.rs diff --git a/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs b/src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs similarity index 100% rename from tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs rename to src/tools/rustfmt/tests/target/issue-5801/comment_unexpectedly_wraps_before_max_width.rs diff --git a/tests/target/issue-5835.rs b/src/tools/rustfmt/tests/target/issue-5835.rs similarity index 100% rename from tests/target/issue-5835.rs rename to src/tools/rustfmt/tests/target/issue-5835.rs diff --git a/tests/target/issue-5852/default.rs b/src/tools/rustfmt/tests/target/issue-5852/default.rs similarity index 100% rename from tests/target/issue-5852/default.rs rename to src/tools/rustfmt/tests/target/issue-5852/default.rs diff --git a/tests/target/issue-5852/horizontal.rs b/src/tools/rustfmt/tests/target/issue-5852/horizontal.rs similarity index 100% rename from tests/target/issue-5852/horizontal.rs rename to src/tools/rustfmt/tests/target/issue-5852/horizontal.rs diff --git a/tests/target/issue-5852/horizontal_vertical.rs b/src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs similarity index 100% rename from tests/target/issue-5852/horizontal_vertical.rs rename to src/tools/rustfmt/tests/target/issue-5852/horizontal_vertical.rs diff --git a/tests/target/issue-5852/issue_example.rs b/src/tools/rustfmt/tests/target/issue-5852/issue_example.rs similarity index 100% rename from tests/target/issue-5852/issue_example.rs rename to src/tools/rustfmt/tests/target/issue-5852/issue_example.rs diff --git a/tests/target/issue-5852/split.rs b/src/tools/rustfmt/tests/target/issue-5852/split.rs similarity index 100% rename from tests/target/issue-5852/split.rs rename to src/tools/rustfmt/tests/target/issue-5852/split.rs diff --git a/tests/target/issue-5852/vertical.rs b/src/tools/rustfmt/tests/target/issue-5852/vertical.rs similarity index 100% rename from tests/target/issue-5852/vertical.rs rename to src/tools/rustfmt/tests/target/issue-5852/vertical.rs diff --git a/tests/target/issue-5871.rs b/src/tools/rustfmt/tests/target/issue-5871.rs similarity index 100% rename from tests/target/issue-5871.rs rename to src/tools/rustfmt/tests/target/issue-5871.rs diff --git a/tests/target/issue-5885.rs b/src/tools/rustfmt/tests/target/issue-5885.rs similarity index 100% rename from tests/target/issue-5885.rs rename to src/tools/rustfmt/tests/target/issue-5885.rs diff --git a/tests/target/issue-5935.rs b/src/tools/rustfmt/tests/target/issue-5935.rs similarity index 100% rename from tests/target/issue-5935.rs rename to src/tools/rustfmt/tests/target/issue-5935.rs diff --git a/tests/target/issue-5987/one.rs b/src/tools/rustfmt/tests/target/issue-5987/one.rs similarity index 100% rename from tests/target/issue-5987/one.rs rename to src/tools/rustfmt/tests/target/issue-5987/one.rs diff --git a/tests/target/issue-5987/two.rs b/src/tools/rustfmt/tests/target/issue-5987/two.rs similarity index 100% rename from tests/target/issue-5987/two.rs rename to src/tools/rustfmt/tests/target/issue-5987/two.rs diff --git a/tests/target/issue-6059/additional.rs b/src/tools/rustfmt/tests/target/issue-6059/additional.rs similarity index 100% rename from tests/target/issue-6059/additional.rs rename to src/tools/rustfmt/tests/target/issue-6059/additional.rs diff --git a/tests/target/issue-6059/repro.rs b/src/tools/rustfmt/tests/target/issue-6059/repro.rs similarity index 100% rename from tests/target/issue-6059/repro.rs rename to src/tools/rustfmt/tests/target/issue-6059/repro.rs diff --git a/tests/target/issue-6105.rs b/src/tools/rustfmt/tests/target/issue-6105.rs similarity index 100% rename from tests/target/issue-6105.rs rename to src/tools/rustfmt/tests/target/issue-6105.rs diff --git a/tests/target/issue-6109.rs b/src/tools/rustfmt/tests/target/issue-6109.rs similarity index 100% rename from tests/target/issue-6109.rs rename to src/tools/rustfmt/tests/target/issue-6109.rs diff --git a/tests/target/issue-6147/case_rustfmt_v1.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs similarity index 100% rename from tests/target/issue-6147/case_rustfmt_v1.rs rename to src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v1.rs diff --git a/tests/target/issue-6147/case_rustfmt_v2.rs b/src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs similarity index 100% rename from tests/target/issue-6147/case_rustfmt_v2.rs rename to src/tools/rustfmt/tests/target/issue-6147/case_rustfmt_v2.rs diff --git a/tests/target/issue-6202/long_pat.rs b/src/tools/rustfmt/tests/target/issue-6202/long_pat.rs similarity index 100% rename from tests/target/issue-6202/long_pat.rs rename to src/tools/rustfmt/tests/target/issue-6202/long_pat.rs diff --git a/tests/target/issue-6243.rs b/src/tools/rustfmt/tests/target/issue-6243.rs similarity index 100% rename from tests/target/issue-6243.rs rename to src/tools/rustfmt/tests/target/issue-6243.rs diff --git a/tests/target/issue-6333-2024.rs b/src/tools/rustfmt/tests/target/issue-6333-2024.rs similarity index 100% rename from tests/target/issue-6333-2024.rs rename to src/tools/rustfmt/tests/target/issue-6333-2024.rs diff --git a/tests/target/issue-6333.rs b/src/tools/rustfmt/tests/target/issue-6333.rs similarity index 100% rename from tests/target/issue-6333.rs rename to src/tools/rustfmt/tests/target/issue-6333.rs diff --git a/tests/target/issue-64.rs b/src/tools/rustfmt/tests/target/issue-64.rs similarity index 100% rename from tests/target/issue-64.rs rename to src/tools/rustfmt/tests/target/issue-64.rs diff --git a/tests/target/issue-6411.rs b/src/tools/rustfmt/tests/target/issue-6411.rs similarity index 100% rename from tests/target/issue-6411.rs rename to src/tools/rustfmt/tests/target/issue-6411.rs diff --git a/tests/target/issue-6561/trait-fn.rs b/src/tools/rustfmt/tests/target/issue-6561/trait-fn.rs similarity index 100% rename from tests/target/issue-6561/trait-fn.rs rename to src/tools/rustfmt/tests/target/issue-6561/trait-fn.rs diff --git a/tests/target/issue-6561/variadic.rs b/src/tools/rustfmt/tests/target/issue-6561/variadic.rs similarity index 100% rename from tests/target/issue-6561/variadic.rs rename to src/tools/rustfmt/tests/target/issue-6561/variadic.rs diff --git a/tests/target/issue-6607/fn-type.rs b/src/tools/rustfmt/tests/target/issue-6607/fn-type.rs similarity index 100% rename from tests/target/issue-6607/fn-type.rs rename to src/tools/rustfmt/tests/target/issue-6607/fn-type.rs diff --git a/tests/target/issue-6651/custom_width.rs b/src/tools/rustfmt/tests/target/issue-6651/custom_width.rs similarity index 100% rename from tests/target/issue-6651/custom_width.rs rename to src/tools/rustfmt/tests/target/issue-6651/custom_width.rs diff --git a/tests/target/issue-6651/default.rs b/src/tools/rustfmt/tests/target/issue-6651/default.rs similarity index 100% rename from tests/target/issue-6651/default.rs rename to src/tools/rustfmt/tests/target/issue-6651/default.rs diff --git a/tests/target/issue-6788.rs b/src/tools/rustfmt/tests/target/issue-6788.rs similarity index 100% rename from tests/target/issue-6788.rs rename to src/tools/rustfmt/tests/target/issue-6788.rs diff --git a/tests/target/issue-6795.rs b/src/tools/rustfmt/tests/target/issue-6795.rs similarity index 100% rename from tests/target/issue-6795.rs rename to src/tools/rustfmt/tests/target/issue-6795.rs diff --git a/tests/target/issue-6825.rs b/src/tools/rustfmt/tests/target/issue-6825.rs similarity index 100% rename from tests/target/issue-6825.rs rename to src/tools/rustfmt/tests/target/issue-6825.rs diff --git a/tests/target/issue-683.rs b/src/tools/rustfmt/tests/target/issue-683.rs similarity index 100% rename from tests/target/issue-683.rs rename to src/tools/rustfmt/tests/target/issue-683.rs diff --git a/tests/target/issue-6863/empty-stmt.rs b/src/tools/rustfmt/tests/target/issue-6863/empty-stmt.rs similarity index 100% rename from tests/target/issue-6863/empty-stmt.rs rename to src/tools/rustfmt/tests/target/issue-6863/empty-stmt.rs diff --git a/tests/target/issue-6863/fn-stmts.rs b/src/tools/rustfmt/tests/target/issue-6863/fn-stmts.rs similarity index 100% rename from tests/target/issue-6863/fn-stmts.rs rename to src/tools/rustfmt/tests/target/issue-6863/fn-stmts.rs diff --git a/tests/target/issue-691.rs b/src/tools/rustfmt/tests/target/issue-691.rs similarity index 100% rename from tests/target/issue-691.rs rename to src/tools/rustfmt/tests/target/issue-691.rs diff --git a/tests/target/issue-6985.rs b/src/tools/rustfmt/tests/target/issue-6985.rs similarity index 100% rename from tests/target/issue-6985.rs rename to src/tools/rustfmt/tests/target/issue-6985.rs diff --git a/tests/target/issue-7011.rs b/src/tools/rustfmt/tests/target/issue-7011.rs similarity index 100% rename from tests/target/issue-7011.rs rename to src/tools/rustfmt/tests/target/issue-7011.rs diff --git a/tests/target/issue-7054.rs b/src/tools/rustfmt/tests/target/issue-7054.rs similarity index 100% rename from tests/target/issue-7054.rs rename to src/tools/rustfmt/tests/target/issue-7054.rs diff --git a/tests/target/issue-7056.rs b/src/tools/rustfmt/tests/target/issue-7056.rs similarity index 100% rename from tests/target/issue-7056.rs rename to src/tools/rustfmt/tests/target/issue-7056.rs diff --git a/tests/target/issue-770.rs b/src/tools/rustfmt/tests/target/issue-770.rs similarity index 100% rename from tests/target/issue-770.rs rename to src/tools/rustfmt/tests/target/issue-770.rs diff --git a/tests/target/issue-811.rs b/src/tools/rustfmt/tests/target/issue-811.rs similarity index 100% rename from tests/target/issue-811.rs rename to src/tools/rustfmt/tests/target/issue-811.rs diff --git a/tests/target/issue-831.rs b/src/tools/rustfmt/tests/target/issue-831.rs similarity index 100% rename from tests/target/issue-831.rs rename to src/tools/rustfmt/tests/target/issue-831.rs diff --git a/tests/target/issue-850.rs b/src/tools/rustfmt/tests/target/issue-850.rs similarity index 100% rename from tests/target/issue-850.rs rename to src/tools/rustfmt/tests/target/issue-850.rs diff --git a/tests/target/issue-855.rs b/src/tools/rustfmt/tests/target/issue-855.rs similarity index 100% rename from tests/target/issue-855.rs rename to src/tools/rustfmt/tests/target/issue-855.rs diff --git a/tests/target/issue-913.rs b/src/tools/rustfmt/tests/target/issue-913.rs similarity index 100% rename from tests/target/issue-913.rs rename to src/tools/rustfmt/tests/target/issue-913.rs diff --git a/tests/target/issue-945.rs b/src/tools/rustfmt/tests/target/issue-945.rs similarity index 100% rename from tests/target/issue-945.rs rename to src/tools/rustfmt/tests/target/issue-945.rs diff --git a/tests/target/issue-977.rs b/src/tools/rustfmt/tests/target/issue-977.rs similarity index 100% rename from tests/target/issue-977.rs rename to src/tools/rustfmt/tests/target/issue-977.rs diff --git a/tests/target/issue_1306.rs b/src/tools/rustfmt/tests/target/issue_1306.rs similarity index 100% rename from tests/target/issue_1306.rs rename to src/tools/rustfmt/tests/target/issue_1306.rs diff --git a/tests/target/issue_3033.rs b/src/tools/rustfmt/tests/target/issue_3033.rs similarity index 100% rename from tests/target/issue_3033.rs rename to src/tools/rustfmt/tests/target/issue_3033.rs diff --git a/tests/target/issue_3245.rs b/src/tools/rustfmt/tests/target/issue_3245.rs similarity index 100% rename from tests/target/issue_3245.rs rename to src/tools/rustfmt/tests/target/issue_3245.rs diff --git a/tests/target/issue_3561.rs b/src/tools/rustfmt/tests/target/issue_3561.rs similarity index 100% rename from tests/target/issue_3561.rs rename to src/tools/rustfmt/tests/target/issue_3561.rs diff --git a/tests/target/issue_3839.rs b/src/tools/rustfmt/tests/target/issue_3839.rs similarity index 100% rename from tests/target/issue_3839.rs rename to src/tools/rustfmt/tests/target/issue_3839.rs diff --git a/tests/target/issue_3844.rs b/src/tools/rustfmt/tests/target/issue_3844.rs similarity index 100% rename from tests/target/issue_3844.rs rename to src/tools/rustfmt/tests/target/issue_3844.rs diff --git a/tests/target/issue_3853.rs b/src/tools/rustfmt/tests/target/issue_3853.rs similarity index 100% rename from tests/target/issue_3853.rs rename to src/tools/rustfmt/tests/target/issue_3853.rs diff --git a/tests/target/issue_3854.rs b/src/tools/rustfmt/tests/target/issue_3854.rs similarity index 100% rename from tests/target/issue_3854.rs rename to src/tools/rustfmt/tests/target/issue_3854.rs diff --git a/tests/target/issue_3868.rs b/src/tools/rustfmt/tests/target/issue_3868.rs similarity index 100% rename from tests/target/issue_3868.rs rename to src/tools/rustfmt/tests/target/issue_3868.rs diff --git a/tests/target/issue_3934.rs b/src/tools/rustfmt/tests/target/issue_3934.rs similarity index 100% rename from tests/target/issue_3934.rs rename to src/tools/rustfmt/tests/target/issue_3934.rs diff --git a/tests/target/issue_3937.rs b/src/tools/rustfmt/tests/target/issue_3937.rs similarity index 100% rename from tests/target/issue_3937.rs rename to src/tools/rustfmt/tests/target/issue_3937.rs diff --git a/tests/target/issue_4031.rs b/src/tools/rustfmt/tests/target/issue_4031.rs similarity index 100% rename from tests/target/issue_4031.rs rename to src/tools/rustfmt/tests/target/issue_4031.rs diff --git a/tests/target/issue_4032.rs b/src/tools/rustfmt/tests/target/issue_4032.rs similarity index 100% rename from tests/target/issue_4032.rs rename to src/tools/rustfmt/tests/target/issue_4032.rs diff --git a/tests/target/issue_4037.rs b/src/tools/rustfmt/tests/target/issue_4037.rs similarity index 100% rename from tests/target/issue_4037.rs rename to src/tools/rustfmt/tests/target/issue_4037.rs diff --git a/tests/target/issue_4049.rs b/src/tools/rustfmt/tests/target/issue_4049.rs similarity index 100% rename from tests/target/issue_4049.rs rename to src/tools/rustfmt/tests/target/issue_4049.rs diff --git a/tests/target/issue_4057.rs b/src/tools/rustfmt/tests/target/issue_4057.rs similarity index 100% rename from tests/target/issue_4057.rs rename to src/tools/rustfmt/tests/target/issue_4057.rs diff --git a/tests/target/issue_4086.rs b/src/tools/rustfmt/tests/target/issue_4086.rs similarity index 100% rename from tests/target/issue_4086.rs rename to src/tools/rustfmt/tests/target/issue_4086.rs diff --git a/tests/target/issue_4110.rs b/src/tools/rustfmt/tests/target/issue_4110.rs similarity index 100% rename from tests/target/issue_4110.rs rename to src/tools/rustfmt/tests/target/issue_4110.rs diff --git a/tests/target/issue_4257.rs b/src/tools/rustfmt/tests/target/issue_4257.rs similarity index 100% rename from tests/target/issue_4257.rs rename to src/tools/rustfmt/tests/target/issue_4257.rs diff --git a/tests/target/issue_4322.rs b/src/tools/rustfmt/tests/target/issue_4322.rs similarity index 100% rename from tests/target/issue_4322.rs rename to src/tools/rustfmt/tests/target/issue_4322.rs diff --git a/tests/target/issue_4350.rs b/src/tools/rustfmt/tests/target/issue_4350.rs similarity index 100% rename from tests/target/issue_4350.rs rename to src/tools/rustfmt/tests/target/issue_4350.rs diff --git a/tests/target/issue_4374.rs b/src/tools/rustfmt/tests/target/issue_4374.rs similarity index 100% rename from tests/target/issue_4374.rs rename to src/tools/rustfmt/tests/target/issue_4374.rs diff --git a/tests/target/issue_4467.rs b/src/tools/rustfmt/tests/target/issue_4467.rs similarity index 100% rename from tests/target/issue_4467.rs rename to src/tools/rustfmt/tests/target/issue_4467.rs diff --git a/tests/target/issue_4475.rs b/src/tools/rustfmt/tests/target/issue_4475.rs similarity index 100% rename from tests/target/issue_4475.rs rename to src/tools/rustfmt/tests/target/issue_4475.rs diff --git a/tests/target/issue_4522.rs b/src/tools/rustfmt/tests/target/issue_4522.rs similarity index 100% rename from tests/target/issue_4522.rs rename to src/tools/rustfmt/tests/target/issue_4522.rs diff --git a/tests/target/issue_4528.rs b/src/tools/rustfmt/tests/target/issue_4528.rs similarity index 100% rename from tests/target/issue_4528.rs rename to src/tools/rustfmt/tests/target/issue_4528.rs diff --git a/tests/target/issue_4545.rs b/src/tools/rustfmt/tests/target/issue_4545.rs similarity index 100% rename from tests/target/issue_4545.rs rename to src/tools/rustfmt/tests/target/issue_4545.rs diff --git a/tests/target/issue_4573.rs b/src/tools/rustfmt/tests/target/issue_4573.rs similarity index 100% rename from tests/target/issue_4573.rs rename to src/tools/rustfmt/tests/target/issue_4573.rs diff --git a/tests/target/issue_4579.rs b/src/tools/rustfmt/tests/target/issue_4579.rs similarity index 100% rename from tests/target/issue_4579.rs rename to src/tools/rustfmt/tests/target/issue_4579.rs diff --git a/tests/target/issue_4584.rs b/src/tools/rustfmt/tests/target/issue_4584.rs similarity index 100% rename from tests/target/issue_4584.rs rename to src/tools/rustfmt/tests/target/issue_4584.rs diff --git a/tests/target/issue_4635.rs b/src/tools/rustfmt/tests/target/issue_4635.rs similarity index 100% rename from tests/target/issue_4635.rs rename to src/tools/rustfmt/tests/target/issue_4635.rs diff --git a/tests/target/issue_4636.rs b/src/tools/rustfmt/tests/target/issue_4636.rs similarity index 100% rename from tests/target/issue_4636.rs rename to src/tools/rustfmt/tests/target/issue_4636.rs diff --git a/tests/target/issue_4675.rs b/src/tools/rustfmt/tests/target/issue_4675.rs similarity index 100% rename from tests/target/issue_4675.rs rename to src/tools/rustfmt/tests/target/issue_4675.rs diff --git a/tests/target/issue_4823.rs b/src/tools/rustfmt/tests/target/issue_4823.rs similarity index 100% rename from tests/target/issue_4823.rs rename to src/tools/rustfmt/tests/target/issue_4823.rs diff --git a/tests/target/issue_4850.rs b/src/tools/rustfmt/tests/target/issue_4850.rs similarity index 100% rename from tests/target/issue_4850.rs rename to src/tools/rustfmt/tests/target/issue_4850.rs diff --git a/tests/target/issue_4854.rs b/src/tools/rustfmt/tests/target/issue_4854.rs similarity index 100% rename from tests/target/issue_4854.rs rename to src/tools/rustfmt/tests/target/issue_4854.rs diff --git a/tests/target/issue_4868.rs b/src/tools/rustfmt/tests/target/issue_4868.rs similarity index 100% rename from tests/target/issue_4868.rs rename to src/tools/rustfmt/tests/target/issue_4868.rs diff --git a/tests/target/issue_4911.rs b/src/tools/rustfmt/tests/target/issue_4911.rs similarity index 100% rename from tests/target/issue_4911.rs rename to src/tools/rustfmt/tests/target/issue_4911.rs diff --git a/tests/target/issue_4936.rs b/src/tools/rustfmt/tests/target/issue_4936.rs similarity index 100% rename from tests/target/issue_4936.rs rename to src/tools/rustfmt/tests/target/issue_4936.rs diff --git a/tests/target/issue_4943.rs b/src/tools/rustfmt/tests/target/issue_4943.rs similarity index 100% rename from tests/target/issue_4943.rs rename to src/tools/rustfmt/tests/target/issue_4943.rs diff --git a/tests/target/issue_4954.rs b/src/tools/rustfmt/tests/target/issue_4954.rs similarity index 100% rename from tests/target/issue_4954.rs rename to src/tools/rustfmt/tests/target/issue_4954.rs diff --git a/tests/target/issue_4963.rs b/src/tools/rustfmt/tests/target/issue_4963.rs similarity index 100% rename from tests/target/issue_4963.rs rename to src/tools/rustfmt/tests/target/issue_4963.rs diff --git a/tests/target/issue_5027.rs b/src/tools/rustfmt/tests/target/issue_5027.rs similarity index 100% rename from tests/target/issue_5027.rs rename to src/tools/rustfmt/tests/target/issue_5027.rs diff --git a/tests/target/issue_5086.rs b/src/tools/rustfmt/tests/target/issue_5086.rs similarity index 100% rename from tests/target/issue_5086.rs rename to src/tools/rustfmt/tests/target/issue_5086.rs diff --git a/tests/target/issue_5273.rs b/src/tools/rustfmt/tests/target/issue_5273.rs similarity index 100% rename from tests/target/issue_5273.rs rename to src/tools/rustfmt/tests/target/issue_5273.rs diff --git a/tests/target/issue_5399.rs b/src/tools/rustfmt/tests/target/issue_5399.rs similarity index 100% rename from tests/target/issue_5399.rs rename to src/tools/rustfmt/tests/target/issue_5399.rs diff --git a/tests/target/issue_5533.rs b/src/tools/rustfmt/tests/target/issue_5533.rs similarity index 100% rename from tests/target/issue_5533.rs rename to src/tools/rustfmt/tests/target/issue_5533.rs diff --git a/tests/target/issue_5668.rs b/src/tools/rustfmt/tests/target/issue_5668.rs similarity index 100% rename from tests/target/issue_5668.rs rename to src/tools/rustfmt/tests/target/issue_5668.rs diff --git a/tests/target/issue_5676.rs b/src/tools/rustfmt/tests/target/issue_5676.rs similarity index 100% rename from tests/target/issue_5676.rs rename to src/tools/rustfmt/tests/target/issue_5676.rs diff --git a/tests/target/issue_5686.rs b/src/tools/rustfmt/tests/target/issue_5686.rs similarity index 100% rename from tests/target/issue_5686.rs rename to src/tools/rustfmt/tests/target/issue_5686.rs diff --git a/tests/target/issue_5691.rs b/src/tools/rustfmt/tests/target/issue_5691.rs similarity index 100% rename from tests/target/issue_5691.rs rename to src/tools/rustfmt/tests/target/issue_5691.rs diff --git a/tests/target/issue_5721.rs b/src/tools/rustfmt/tests/target/issue_5721.rs similarity index 100% rename from tests/target/issue_5721.rs rename to src/tools/rustfmt/tests/target/issue_5721.rs diff --git a/tests/target/issue_5728.rs b/src/tools/rustfmt/tests/target/issue_5728.rs similarity index 100% rename from tests/target/issue_5728.rs rename to src/tools/rustfmt/tests/target/issue_5728.rs diff --git a/tests/target/issue_5729.rs b/src/tools/rustfmt/tests/target/issue_5729.rs similarity index 100% rename from tests/target/issue_5729.rs rename to src/tools/rustfmt/tests/target/issue_5729.rs diff --git a/tests/target/issue_5730.rs b/src/tools/rustfmt/tests/target/issue_5730.rs similarity index 100% rename from tests/target/issue_5730.rs rename to src/tools/rustfmt/tests/target/issue_5730.rs diff --git a/tests/target/issue_5735.rs b/src/tools/rustfmt/tests/target/issue_5735.rs similarity index 100% rename from tests/target/issue_5735.rs rename to src/tools/rustfmt/tests/target/issue_5735.rs diff --git a/tests/target/issue_5739.rs b/src/tools/rustfmt/tests/target/issue_5739.rs similarity index 100% rename from tests/target/issue_5739.rs rename to src/tools/rustfmt/tests/target/issue_5739.rs diff --git a/tests/target/issue_5882.rs b/src/tools/rustfmt/tests/target/issue_5882.rs similarity index 100% rename from tests/target/issue_5882.rs rename to src/tools/rustfmt/tests/target/issue_5882.rs diff --git a/tests/target/issue_5907.rs b/src/tools/rustfmt/tests/target/issue_5907.rs similarity index 100% rename from tests/target/issue_5907.rs rename to src/tools/rustfmt/tests/target/issue_5907.rs diff --git a/tests/target/issue_5912.rs b/src/tools/rustfmt/tests/target/issue_5912.rs similarity index 100% rename from tests/target/issue_5912.rs rename to src/tools/rustfmt/tests/target/issue_5912.rs diff --git a/tests/target/issue_5920_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_5920_style_edition_2024.rs similarity index 100% rename from tests/target/issue_5920_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_5920_style_edition_2024.rs diff --git a/tests/target/issue_5920_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_5920_style_edition_2027.rs similarity index 100% rename from tests/target/issue_5920_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_5920_style_edition_2027.rs diff --git a/tests/target/issue_5973.rs b/src/tools/rustfmt/tests/target/issue_5973.rs similarity index 100% rename from tests/target/issue_5973.rs rename to src/tools/rustfmt/tests/target/issue_5973.rs diff --git a/tests/target/issue_5982_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_5982_style_edition_2024.rs similarity index 100% rename from tests/target/issue_5982_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_5982_style_edition_2024.rs diff --git a/tests/target/issue_5982_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_5982_style_edition_2027.rs similarity index 100% rename from tests/target/issue_5982_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_5982_style_edition_2027.rs diff --git a/tests/target/issue_6069.rs b/src/tools/rustfmt/tests/target/issue_6069.rs similarity index 100% rename from tests/target/issue_6069.rs rename to src/tools/rustfmt/tests/target/issue_6069.rs diff --git a/tests/target/issue_6082.rs b/src/tools/rustfmt/tests/target/issue_6082.rs similarity index 100% rename from tests/target/issue_6082.rs rename to src/tools/rustfmt/tests/target/issue_6082.rs diff --git a/tests/target/issue_6158.rs b/src/tools/rustfmt/tests/target/issue_6158.rs similarity index 100% rename from tests/target/issue_6158.rs rename to src/tools/rustfmt/tests/target/issue_6158.rs diff --git a/tests/target/issue_6159.rs b/src/tools/rustfmt/tests/target/issue_6159.rs similarity index 100% rename from tests/target/issue_6159.rs rename to src/tools/rustfmt/tests/target/issue_6159.rs diff --git a/tests/target/issue_6209.rs b/src/tools/rustfmt/tests/target/issue_6209.rs similarity index 100% rename from tests/target/issue_6209.rs rename to src/tools/rustfmt/tests/target/issue_6209.rs diff --git a/tests/target/issue_6381_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_6381_style_edition_2024.rs similarity index 100% rename from tests/target/issue_6381_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_6381_style_edition_2024.rs diff --git a/tests/target/issue_6381_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_6381_style_edition_2027.rs similarity index 100% rename from tests/target/issue_6381_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_6381_style_edition_2027.rs diff --git a/tests/target/issue_6513.rs b/src/tools/rustfmt/tests/target/issue_6513.rs similarity index 100% rename from tests/target/issue_6513.rs rename to src/tools/rustfmt/tests/target/issue_6513.rs diff --git a/tests/target/issue_6558.rs b/src/tools/rustfmt/tests/target/issue_6558.rs similarity index 100% rename from tests/target/issue_6558.rs rename to src/tools/rustfmt/tests/target/issue_6558.rs diff --git a/tests/target/issue_6801.rs b/src/tools/rustfmt/tests/target/issue_6801.rs similarity index 100% rename from tests/target/issue_6801.rs rename to src/tools/rustfmt/tests/target/issue_6801.rs diff --git a/tests/target/issue_6831_style_edition_2021.rs b/src/tools/rustfmt/tests/target/issue_6831_style_edition_2021.rs similarity index 100% rename from tests/target/issue_6831_style_edition_2021.rs rename to src/tools/rustfmt/tests/target/issue_6831_style_edition_2021.rs diff --git a/tests/target/issue_6831_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_6831_style_edition_2024.rs similarity index 100% rename from tests/target/issue_6831_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_6831_style_edition_2024.rs diff --git a/tests/target/issue_6831_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_6831_style_edition_2027.rs similarity index 100% rename from tests/target/issue_6831_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_6831_style_edition_2027.rs diff --git a/tests/target/issue_6859_hard_tab_breaks.rs b/src/tools/rustfmt/tests/target/issue_6859_hard_tab_breaks.rs similarity index 100% rename from tests/target/issue_6859_hard_tab_breaks.rs rename to src/tools/rustfmt/tests/target/issue_6859_hard_tab_breaks.rs diff --git a/tests/target/issue_6869.rs b/src/tools/rustfmt/tests/target/issue_6869.rs similarity index 100% rename from tests/target/issue_6869.rs rename to src/tools/rustfmt/tests/target/issue_6869.rs diff --git a/tests/target/issue_6959.rs b/src/tools/rustfmt/tests/target/issue_6959.rs similarity index 100% rename from tests/target/issue_6959.rs rename to src/tools/rustfmt/tests/target/issue_6959.rs diff --git a/tests/target/issue_6984_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_6984_style_edition_2024.rs similarity index 100% rename from tests/target/issue_6984_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_6984_style_edition_2024.rs diff --git a/tests/target/issue_6984_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_6984_style_edition_2027.rs similarity index 100% rename from tests/target/issue_6984_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_6984_style_edition_2027.rs diff --git a/tests/target/issue_7003_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_7003_style_edition_2024.rs similarity index 100% rename from tests/target/issue_7003_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_7003_style_edition_2024.rs diff --git a/tests/target/issue_7003_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_7003_style_edition_2027.rs similarity index 100% rename from tests/target/issue_7003_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_7003_style_edition_2027.rs diff --git a/tests/target/issue_7036.rs b/src/tools/rustfmt/tests/target/issue_7036.rs similarity index 100% rename from tests/target/issue_7036.rs rename to src/tools/rustfmt/tests/target/issue_7036.rs diff --git a/tests/target/issue_7055_style_edition_2024.rs b/src/tools/rustfmt/tests/target/issue_7055_style_edition_2024.rs similarity index 100% rename from tests/target/issue_7055_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/issue_7055_style_edition_2024.rs diff --git a/tests/target/issue_7055_style_edition_2027.rs b/src/tools/rustfmt/tests/target/issue_7055_style_edition_2027.rs similarity index 100% rename from tests/target/issue_7055_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/issue_7055_style_edition_2027.rs diff --git a/tests/target/issue_7057.rs b/src/tools/rustfmt/tests/target/issue_7057.rs similarity index 100% rename from tests/target/issue_7057.rs rename to src/tools/rustfmt/tests/target/issue_7057.rs diff --git a/tests/target/issue_7062.rs b/src/tools/rustfmt/tests/target/issue_7062.rs similarity index 100% rename from tests/target/issue_7062.rs rename to src/tools/rustfmt/tests/target/issue_7062.rs diff --git a/tests/target/issue_7088_stable.rs b/src/tools/rustfmt/tests/target/issue_7088_stable.rs similarity index 100% rename from tests/target/issue_7088_stable.rs rename to src/tools/rustfmt/tests/target/issue_7088_stable.rs diff --git a/tests/target/issue_7088_unstable.rs b/src/tools/rustfmt/tests/target/issue_7088_unstable.rs similarity index 100% rename from tests/target/issue_7088_unstable.rs rename to src/tools/rustfmt/tests/target/issue_7088_unstable.rs diff --git a/tests/target/item-brace-style-always-next-line.rs b/src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs similarity index 100% rename from tests/target/item-brace-style-always-next-line.rs rename to src/tools/rustfmt/tests/target/item-brace-style-always-next-line.rs diff --git a/tests/target/item-brace-style-prefer-same-line.rs b/src/tools/rustfmt/tests/target/item-brace-style-prefer-same-line.rs similarity index 100% rename from tests/target/item-brace-style-prefer-same-line.rs rename to src/tools/rustfmt/tests/target/item-brace-style-prefer-same-line.rs diff --git a/tests/target/item-brace-style-same-line-where.rs b/src/tools/rustfmt/tests/target/item-brace-style-same-line-where.rs similarity index 100% rename from tests/target/item-brace-style-same-line-where.rs rename to src/tools/rustfmt/tests/target/item-brace-style-same-line-where.rs diff --git a/tests/target/itemized-blocks/no_wrap.rs b/src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs similarity index 100% rename from tests/target/itemized-blocks/no_wrap.rs rename to src/tools/rustfmt/tests/target/itemized-blocks/no_wrap.rs diff --git a/tests/target/itemized-blocks/rewrite_fail.rs b/src/tools/rustfmt/tests/target/itemized-blocks/rewrite_fail.rs similarity index 100% rename from tests/target/itemized-blocks/rewrite_fail.rs rename to src/tools/rustfmt/tests/target/itemized-blocks/rewrite_fail.rs diff --git a/tests/target/itemized-blocks/urls.rs b/src/tools/rustfmt/tests/target/itemized-blocks/urls.rs similarity index 100% rename from tests/target/itemized-blocks/urls.rs rename to src/tools/rustfmt/tests/target/itemized-blocks/urls.rs diff --git a/tests/target/itemized-blocks/wrap.rs b/src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs similarity index 100% rename from tests/target/itemized-blocks/wrap.rs rename to src/tools/rustfmt/tests/target/itemized-blocks/wrap.rs diff --git a/tests/target/keywords.rs b/src/tools/rustfmt/tests/target/keywords.rs similarity index 100% rename from tests/target/keywords.rs rename to src/tools/rustfmt/tests/target/keywords.rs diff --git a/tests/target/label_break.rs b/src/tools/rustfmt/tests/target/label_break.rs similarity index 100% rename from tests/target/label_break.rs rename to src/tools/rustfmt/tests/target/label_break.rs diff --git a/tests/target/large-block.rs b/src/tools/rustfmt/tests/target/large-block.rs similarity index 100% rename from tests/target/large-block.rs rename to src/tools/rustfmt/tests/target/large-block.rs diff --git a/tests/target/large_vec.rs b/src/tools/rustfmt/tests/target/large_vec.rs similarity index 100% rename from tests/target/large_vec.rs rename to src/tools/rustfmt/tests/target/large_vec.rs diff --git a/tests/target/lazy_staic_before_2027.rs b/src/tools/rustfmt/tests/target/lazy_staic_before_2027.rs similarity index 100% rename from tests/target/lazy_staic_before_2027.rs rename to src/tools/rustfmt/tests/target/lazy_staic_before_2027.rs diff --git a/tests/target/lazy_static.rs b/src/tools/rustfmt/tests/target/lazy_static.rs similarity index 100% rename from tests/target/lazy_static.rs rename to src/tools/rustfmt/tests/target/lazy_static.rs diff --git a/tests/target/let_chains.rs b/src/tools/rustfmt/tests/target/let_chains.rs similarity index 100% rename from tests/target/let_chains.rs rename to src/tools/rustfmt/tests/target/let_chains.rs diff --git a/tests/target/let_else.rs b/src/tools/rustfmt/tests/target/let_else.rs similarity index 100% rename from tests/target/let_else.rs rename to src/tools/rustfmt/tests/target/let_else.rs diff --git a/tests/target/let_else_v2.rs b/src/tools/rustfmt/tests/target/let_else_v2.rs similarity index 100% rename from tests/target/let_else_v2.rs rename to src/tools/rustfmt/tests/target/let_else_v2.rs diff --git a/tests/target/long-fn-1/version_one.rs b/src/tools/rustfmt/tests/target/long-fn-1/version_one.rs similarity index 100% rename from tests/target/long-fn-1/version_one.rs rename to src/tools/rustfmt/tests/target/long-fn-1/version_one.rs diff --git a/tests/target/long-fn-1/version_two.rs b/src/tools/rustfmt/tests/target/long-fn-1/version_two.rs similarity index 100% rename from tests/target/long-fn-1/version_two.rs rename to src/tools/rustfmt/tests/target/long-fn-1/version_two.rs diff --git a/tests/target/long-match-arms-brace-newline.rs b/src/tools/rustfmt/tests/target/long-match-arms-brace-newline.rs similarity index 100% rename from tests/target/long-match-arms-brace-newline.rs rename to src/tools/rustfmt/tests/target/long-match-arms-brace-newline.rs diff --git a/tests/target/long-use-statement-issue-3154.rs b/src/tools/rustfmt/tests/target/long-use-statement-issue-3154.rs similarity index 100% rename from tests/target/long-use-statement-issue-3154.rs rename to src/tools/rustfmt/tests/target/long-use-statement-issue-3154.rs diff --git a/tests/target/long_field_access.rs b/src/tools/rustfmt/tests/target/long_field_access.rs similarity index 100% rename from tests/target/long_field_access.rs rename to src/tools/rustfmt/tests/target/long_field_access.rs diff --git a/tests/target/loop.rs b/src/tools/rustfmt/tests/target/loop.rs similarity index 100% rename from tests/target/loop.rs rename to src/tools/rustfmt/tests/target/loop.rs diff --git a/tests/target/macro_not_expr.rs b/src/tools/rustfmt/tests/target/macro_not_expr.rs similarity index 100% rename from tests/target/macro_not_expr.rs rename to src/tools/rustfmt/tests/target/macro_not_expr.rs diff --git a/tests/target/macro_rules.rs b/src/tools/rustfmt/tests/target/macro_rules.rs similarity index 100% rename from tests/target/macro_rules.rs rename to src/tools/rustfmt/tests/target/macro_rules.rs diff --git a/tests/target/macro_rules_semi.rs b/src/tools/rustfmt/tests/target/macro_rules_semi.rs similarity index 100% rename from tests/target/macro_rules_semi.rs rename to src/tools/rustfmt/tests/target/macro_rules_semi.rs diff --git a/tests/target/macros.rs b/src/tools/rustfmt/tests/target/macros.rs similarity index 100% rename from tests/target/macros.rs rename to src/tools/rustfmt/tests/target/macros.rs diff --git a/tests/target/macros/rewrite-const-item.rs b/src/tools/rustfmt/tests/target/macros/rewrite-const-item.rs similarity index 100% rename from tests/target/macros/rewrite-const-item.rs rename to src/tools/rustfmt/tests/target/macros/rewrite-const-item.rs diff --git a/tests/target/markdown-comment-with-options.rs b/src/tools/rustfmt/tests/target/markdown-comment-with-options.rs similarity index 100% rename from tests/target/markdown-comment-with-options.rs rename to src/tools/rustfmt/tests/target/markdown-comment-with-options.rs diff --git a/tests/target/markdown-comment.rs b/src/tools/rustfmt/tests/target/markdown-comment.rs similarity index 100% rename from tests/target/markdown-comment.rs rename to src/tools/rustfmt/tests/target/markdown-comment.rs diff --git a/tests/target/match-block-trailing-comma.rs b/src/tools/rustfmt/tests/target/match-block-trailing-comma.rs similarity index 100% rename from tests/target/match-block-trailing-comma.rs rename to src/tools/rustfmt/tests/target/match-block-trailing-comma.rs diff --git a/tests/target/match-flattening.rs b/src/tools/rustfmt/tests/target/match-flattening.rs similarity index 100% rename from tests/target/match-flattening.rs rename to src/tools/rustfmt/tests/target/match-flattening.rs diff --git a/tests/target/match-nowrap-trailing-comma.rs b/src/tools/rustfmt/tests/target/match-nowrap-trailing-comma.rs similarity index 100% rename from tests/target/match-nowrap-trailing-comma.rs rename to src/tools/rustfmt/tests/target/match-nowrap-trailing-comma.rs diff --git a/tests/target/match-nowrap.rs b/src/tools/rustfmt/tests/target/match-nowrap.rs similarity index 100% rename from tests/target/match-nowrap.rs rename to src/tools/rustfmt/tests/target/match-nowrap.rs diff --git a/tests/target/match.rs b/src/tools/rustfmt/tests/target/match.rs similarity index 100% rename from tests/target/match.rs rename to src/tools/rustfmt/tests/target/match.rs diff --git a/tests/target/match_overflow_expr.rs b/src/tools/rustfmt/tests/target/match_overflow_expr.rs similarity index 100% rename from tests/target/match_overflow_expr.rs rename to src/tools/rustfmt/tests/target/match_overflow_expr.rs diff --git a/tests/target/max-line-length-in-chars.rs b/src/tools/rustfmt/tests/target/max-line-length-in-chars.rs similarity index 100% rename from tests/target/max-line-length-in-chars.rs rename to src/tools/rustfmt/tests/target/max-line-length-in-chars.rs diff --git a/tests/target/merge_imports_true_compat.rs b/src/tools/rustfmt/tests/target/merge_imports_true_compat.rs similarity index 100% rename from tests/target/merge_imports_true_compat.rs rename to src/tools/rustfmt/tests/target/merge_imports_true_compat.rs diff --git a/tests/target/mod-1.rs b/src/tools/rustfmt/tests/target/mod-1.rs similarity index 100% rename from tests/target/mod-1.rs rename to src/tools/rustfmt/tests/target/mod-1.rs diff --git a/tests/target/mod-2.rs b/src/tools/rustfmt/tests/target/mod-2.rs similarity index 100% rename from tests/target/mod-2.rs rename to src/tools/rustfmt/tests/target/mod-2.rs diff --git a/tests/target/mod_skip_child.rs b/src/tools/rustfmt/tests/target/mod_skip_child.rs similarity index 100% rename from tests/target/mod_skip_child.rs rename to src/tools/rustfmt/tests/target/mod_skip_child.rs diff --git a/tests/target/mulit-file.rs b/src/tools/rustfmt/tests/target/mulit-file.rs similarity index 100% rename from tests/target/mulit-file.rs rename to src/tools/rustfmt/tests/target/mulit-file.rs diff --git a/tests/target/multiline_string_in_macro_def.rs b/src/tools/rustfmt/tests/target/multiline_string_in_macro_def.rs similarity index 100% rename from tests/target/multiline_string_in_macro_def.rs rename to src/tools/rustfmt/tests/target/multiline_string_in_macro_def.rs diff --git a/tests/target/multiple.rs b/src/tools/rustfmt/tests/target/multiple.rs similarity index 100% rename from tests/target/multiple.rs rename to src/tools/rustfmt/tests/target/multiple.rs diff --git a/tests/target/mut-restriction.rs b/src/tools/rustfmt/tests/target/mut-restriction.rs similarity index 100% rename from tests/target/mut-restriction.rs rename to src/tools/rustfmt/tests/target/mut-restriction.rs diff --git a/tests/target/mut_ref.rs b/src/tools/rustfmt/tests/target/mut_ref.rs similarity index 100% rename from tests/target/mut_ref.rs rename to src/tools/rustfmt/tests/target/mut_ref.rs diff --git a/tests/target/named-fn-trait-parameters.rs b/src/tools/rustfmt/tests/target/named-fn-trait-parameters.rs similarity index 100% rename from tests/target/named-fn-trait-parameters.rs rename to src/tools/rustfmt/tests/target/named-fn-trait-parameters.rs diff --git a/tests/target/negative-bounds.rs b/src/tools/rustfmt/tests/target/negative-bounds.rs similarity index 100% rename from tests/target/negative-bounds.rs rename to src/tools/rustfmt/tests/target/negative-bounds.rs diff --git a/tests/target/negative-impl.rs b/src/tools/rustfmt/tests/target/negative-impl.rs similarity index 100% rename from tests/target/negative-impl.rs rename to src/tools/rustfmt/tests/target/negative-impl.rs diff --git a/tests/target/nested-if-else.rs b/src/tools/rustfmt/tests/target/nested-if-else.rs similarity index 100% rename from tests/target/nested-if-else.rs rename to src/tools/rustfmt/tests/target/nested-if-else.rs diff --git a/tests/target/nested-visual-block.rs b/src/tools/rustfmt/tests/target/nested-visual-block.rs similarity index 100% rename from tests/target/nested-visual-block.rs rename to src/tools/rustfmt/tests/target/nested-visual-block.rs diff --git a/tests/target/nested_skipped/mod.rs b/src/tools/rustfmt/tests/target/nested_skipped/mod.rs similarity index 100% rename from tests/target/nested_skipped/mod.rs rename to src/tools/rustfmt/tests/target/nested_skipped/mod.rs diff --git a/tests/target/nestedmod/mod.rs b/src/tools/rustfmt/tests/target/nestedmod/mod.rs similarity index 100% rename from tests/target/nestedmod/mod.rs rename to src/tools/rustfmt/tests/target/nestedmod/mod.rs diff --git a/tests/target/nestedmod/mod2a.rs b/src/tools/rustfmt/tests/target/nestedmod/mod2a.rs similarity index 100% rename from tests/target/nestedmod/mod2a.rs rename to src/tools/rustfmt/tests/target/nestedmod/mod2a.rs diff --git a/tests/target/nestedmod/mod2b.rs b/src/tools/rustfmt/tests/target/nestedmod/mod2b.rs similarity index 100% rename from tests/target/nestedmod/mod2b.rs rename to src/tools/rustfmt/tests/target/nestedmod/mod2b.rs diff --git a/tests/target/nestedmod/mod2c.rs b/src/tools/rustfmt/tests/target/nestedmod/mod2c.rs similarity index 100% rename from tests/target/nestedmod/mod2c.rs rename to src/tools/rustfmt/tests/target/nestedmod/mod2c.rs diff --git a/tests/target/nestedmod/mymod1/mod3a.rs b/src/tools/rustfmt/tests/target/nestedmod/mymod1/mod3a.rs similarity index 100% rename from tests/target/nestedmod/mymod1/mod3a.rs rename to src/tools/rustfmt/tests/target/nestedmod/mymod1/mod3a.rs diff --git a/tests/target/nestedmod/submod2/a.rs b/src/tools/rustfmt/tests/target/nestedmod/submod2/a.rs similarity index 100% rename from tests/target/nestedmod/submod2/a.rs rename to src/tools/rustfmt/tests/target/nestedmod/submod2/a.rs diff --git a/tests/target/nestedmod/submod2/mod.rs b/src/tools/rustfmt/tests/target/nestedmod/submod2/mod.rs similarity index 100% rename from tests/target/nestedmod/submod2/mod.rs rename to src/tools/rustfmt/tests/target/nestedmod/submod2/mod.rs diff --git a/tests/target/no_arg_with_comment.rs b/src/tools/rustfmt/tests/target/no_arg_with_comment.rs similarity index 100% rename from tests/target/no_arg_with_comment.rs rename to src/tools/rustfmt/tests/target/no_arg_with_comment.rs diff --git a/tests/target/no_new_line_beginning.rs b/src/tools/rustfmt/tests/target/no_new_line_beginning.rs similarity index 100% rename from tests/target/no_new_line_beginning.rs rename to src/tools/rustfmt/tests/target/no_new_line_beginning.rs diff --git a/tests/target/non-lifetime-binders.rs b/src/tools/rustfmt/tests/target/non-lifetime-binders.rs similarity index 100% rename from tests/target/non-lifetime-binders.rs rename to src/tools/rustfmt/tests/target/non-lifetime-binders.rs diff --git a/tests/target/non_ascii_numerics_import_asciibetically.rs b/src/tools/rustfmt/tests/target/non_ascii_numerics_import_asciibetically.rs similarity index 100% rename from tests/target/non_ascii_numerics_import_asciibetically.rs rename to src/tools/rustfmt/tests/target/non_ascii_numerics_import_asciibetically.rs diff --git a/tests/target/non_ascii_numerics_import_versionsort.rs b/src/tools/rustfmt/tests/target/non_ascii_numerics_import_versionsort.rs similarity index 100% rename from tests/target/non_ascii_numerics_import_versionsort.rs rename to src/tools/rustfmt/tests/target/non_ascii_numerics_import_versionsort.rs diff --git a/tests/target/normalize_doc_attributes_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/target/normalize_doc_attributes_should_not_imply_format_doc_comments.rs similarity index 100% rename from tests/target/normalize_doc_attributes_should_not_imply_format_doc_comments.rs rename to src/tools/rustfmt/tests/target/normalize_doc_attributes_should_not_imply_format_doc_comments.rs diff --git a/tests/target/normalize_multiline_doc_attribute.rs b/src/tools/rustfmt/tests/target/normalize_multiline_doc_attribute.rs similarity index 100% rename from tests/target/normalize_multiline_doc_attribute.rs rename to src/tools/rustfmt/tests/target/normalize_multiline_doc_attribute.rs diff --git a/tests/target/obsolete_in_place.rs b/src/tools/rustfmt/tests/target/obsolete_in_place.rs similarity index 100% rename from tests/target/obsolete_in_place.rs rename to src/tools/rustfmt/tests/target/obsolete_in_place.rs diff --git a/tests/target/one_line_if_v1.rs b/src/tools/rustfmt/tests/target/one_line_if_v1.rs similarity index 100% rename from tests/target/one_line_if_v1.rs rename to src/tools/rustfmt/tests/target/one_line_if_v1.rs diff --git a/tests/target/one_line_if_v2.rs b/src/tools/rustfmt/tests/target/one_line_if_v2.rs similarity index 100% rename from tests/target/one_line_if_v2.rs rename to src/tools/rustfmt/tests/target/one_line_if_v2.rs diff --git a/tests/target/other.rs b/src/tools/rustfmt/tests/target/other.rs similarity index 100% rename from tests/target/other.rs rename to src/tools/rustfmt/tests/target/other.rs diff --git a/tests/target/paren.rs b/src/tools/rustfmt/tests/target/paren.rs similarity index 100% rename from tests/target/paren.rs rename to src/tools/rustfmt/tests/target/paren.rs diff --git a/tests/target/path_clarity/foo.rs b/src/tools/rustfmt/tests/target/path_clarity/foo.rs similarity index 100% rename from tests/target/path_clarity/foo.rs rename to src/tools/rustfmt/tests/target/path_clarity/foo.rs diff --git a/tests/target/path_clarity/foo/bar.rs b/src/tools/rustfmt/tests/target/path_clarity/foo/bar.rs similarity index 100% rename from tests/target/path_clarity/foo/bar.rs rename to src/tools/rustfmt/tests/target/path_clarity/foo/bar.rs diff --git a/tests/target/paths.rs b/src/tools/rustfmt/tests/target/paths.rs similarity index 100% rename from tests/target/paths.rs rename to src/tools/rustfmt/tests/target/paths.rs diff --git a/tests/target/pattern-condense-wildcards.rs b/src/tools/rustfmt/tests/target/pattern-condense-wildcards.rs similarity index 100% rename from tests/target/pattern-condense-wildcards.rs rename to src/tools/rustfmt/tests/target/pattern-condense-wildcards.rs diff --git a/tests/target/pattern.rs b/src/tools/rustfmt/tests/target/pattern.rs similarity index 100% rename from tests/target/pattern.rs rename to src/tools/rustfmt/tests/target/pattern.rs diff --git a/tests/target/pin_sugar.rs b/src/tools/rustfmt/tests/target/pin_sugar.rs similarity index 100% rename from tests/target/pin_sugar.rs rename to src/tools/rustfmt/tests/target/pin_sugar.rs diff --git a/tests/target/postfix-match/pf-match.rs b/src/tools/rustfmt/tests/target/postfix-match/pf-match.rs similarity index 100% rename from tests/target/postfix-match/pf-match.rs rename to src/tools/rustfmt/tests/target/postfix-match/pf-match.rs diff --git a/tests/target/postfix-yield.rs b/src/tools/rustfmt/tests/target/postfix-yield.rs similarity index 100% rename from tests/target/postfix-yield.rs rename to src/tools/rustfmt/tests/target/postfix-yield.rs diff --git a/tests/target/precise-capturing.rs b/src/tools/rustfmt/tests/target/precise-capturing.rs similarity index 100% rename from tests/target/precise-capturing.rs rename to src/tools/rustfmt/tests/target/precise-capturing.rs diff --git a/tests/target/preserves_carriage_return_for_unix.rs b/src/tools/rustfmt/tests/target/preserves_carriage_return_for_unix.rs similarity index 100% rename from tests/target/preserves_carriage_return_for_unix.rs rename to src/tools/rustfmt/tests/target/preserves_carriage_return_for_unix.rs diff --git a/tests/target/preserves_carriage_return_for_windows.rs b/src/tools/rustfmt/tests/target/preserves_carriage_return_for_windows.rs similarity index 100% rename from tests/target/preserves_carriage_return_for_windows.rs rename to src/tools/rustfmt/tests/target/preserves_carriage_return_for_windows.rs diff --git a/tests/target/pub-restricted.rs b/src/tools/rustfmt/tests/target/pub-restricted.rs similarity index 100% rename from tests/target/pub-restricted.rs rename to src/tools/rustfmt/tests/target/pub-restricted.rs diff --git a/tests/target/raw-lifetimes.rs b/src/tools/rustfmt/tests/target/raw-lifetimes.rs similarity index 100% rename from tests/target/raw-lifetimes.rs rename to src/tools/rustfmt/tests/target/raw-lifetimes.rs diff --git a/tests/target/raw_identifiers.rs b/src/tools/rustfmt/tests/target/raw_identifiers.rs similarity index 100% rename from tests/target/raw_identifiers.rs rename to src/tools/rustfmt/tests/target/raw_identifiers.rs diff --git a/tests/target/remove_blank_lines.rs b/src/tools/rustfmt/tests/target/remove_blank_lines.rs similarity index 100% rename from tests/target/remove_blank_lines.rs rename to src/tools/rustfmt/tests/target/remove_blank_lines.rs diff --git a/tests/target/reorder-impl-items.rs b/src/tools/rustfmt/tests/target/reorder-impl-items.rs similarity index 100% rename from tests/target/reorder-impl-items.rs rename to src/tools/rustfmt/tests/target/reorder-impl-items.rs diff --git a/tests/target/reorder_modules/A2/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/A2/mod.rs similarity index 100% rename from tests/target/reorder_modules/A2/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/A2/mod.rs diff --git a/tests/target/reorder_modules/ABCD/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/ABCD/mod.rs similarity index 100% rename from tests/target/reorder_modules/ABCD/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/ABCD/mod.rs diff --git a/tests/target/reorder_modules/ZYXW/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/ZYXW/mod.rs similarity index 100% rename from tests/target/reorder_modules/ZYXW/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/ZYXW/mod.rs diff --git a/tests/target/reorder_modules/ZYXW_/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/ZYXW_/mod.rs similarity index 100% rename from tests/target/reorder_modules/ZYXW_/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/ZYXW_/mod.rs diff --git a/tests/target/reorder_modules/ZY_XW/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/ZY_XW/mod.rs similarity index 100% rename from tests/target/reorder_modules/ZY_XW/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/ZY_XW/mod.rs diff --git a/tests/target/reorder_modules/Z_YXW/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/Z_YXW/mod.rs similarity index 100% rename from tests/target/reorder_modules/Z_YXW/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/Z_YXW/mod.rs diff --git a/tests/target/reorder_modules/_ZYXW/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/_ZYXW/mod.rs similarity index 100% rename from tests/target/reorder_modules/_ZYXW/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/_ZYXW/mod.rs diff --git a/tests/target/reorder_modules/_abcd/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/_abcd/mod.rs similarity index 100% rename from tests/target/reorder_modules/_abcd/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/_abcd/mod.rs diff --git a/tests/target/reorder_modules/a1/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/a1/mod.rs similarity index 100% rename from tests/target/reorder_modules/a1/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/a1/mod.rs diff --git a/tests/target/reorder_modules/abcde/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/abcde/mod.rs similarity index 100% rename from tests/target/reorder_modules/abcde/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/abcde/mod.rs diff --git a/tests/target/reorder_modules/disabled_style_edition_2024.rs b/src/tools/rustfmt/tests/target/reorder_modules/disabled_style_edition_2024.rs similarity index 100% rename from tests/target/reorder_modules/disabled_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/reorder_modules/disabled_style_edition_2024.rs diff --git a/tests/target/reorder_modules/disabled_style_edition_2027.rs b/src/tools/rustfmt/tests/target/reorder_modules/disabled_style_edition_2027.rs similarity index 100% rename from tests/target/reorder_modules/disabled_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/reorder_modules/disabled_style_edition_2027.rs diff --git a/tests/target/reorder_modules/enabled_style_edition_2015.rs b/src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2015.rs similarity index 100% rename from tests/target/reorder_modules/enabled_style_edition_2015.rs rename to src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2015.rs diff --git a/tests/target/reorder_modules/enabled_style_edition_2024.rs b/src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2024.rs similarity index 100% rename from tests/target/reorder_modules/enabled_style_edition_2024.rs rename to src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2024.rs diff --git a/tests/target/reorder_modules/enabled_style_edition_2027.rs b/src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2027.rs similarity index 100% rename from tests/target/reorder_modules/enabled_style_edition_2027.rs rename to src/tools/rustfmt/tests/target/reorder_modules/enabled_style_edition_2027.rs diff --git a/tests/target/reorder_modules/u128/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u128/mod.rs similarity index 100% rename from tests/target/reorder_modules/u128/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u128/mod.rs diff --git a/tests/target/reorder_modules/u16/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u16/mod.rs similarity index 100% rename from tests/target/reorder_modules/u16/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u16/mod.rs diff --git a/tests/target/reorder_modules/u256/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u256/mod.rs similarity index 100% rename from tests/target/reorder_modules/u256/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u256/mod.rs diff --git a/tests/target/reorder_modules/u32/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u32/mod.rs similarity index 100% rename from tests/target/reorder_modules/u32/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u32/mod.rs diff --git a/tests/target/reorder_modules/u64/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u64/mod.rs similarity index 100% rename from tests/target/reorder_modules/u64/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u64/mod.rs diff --git a/tests/target/reorder_modules/u8/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u8/mod.rs similarity index 100% rename from tests/target/reorder_modules/u8/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u8/mod.rs diff --git a/tests/target/reorder_modules/u_zzz/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/u_zzz/mod.rs similarity index 100% rename from tests/target/reorder_modules/u_zzz/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/u_zzz/mod.rs diff --git a/tests/target/reorder_modules/ua/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/ua/mod.rs similarity index 100% rename from tests/target/reorder_modules/ua/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/ua/mod.rs diff --git a/tests/target/reorder_modules/usize/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/usize/mod.rs similarity index 100% rename from tests/target/reorder_modules/usize/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/usize/mod.rs diff --git a/tests/target/reorder_modules/uz/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/uz/mod.rs similarity index 100% rename from tests/target/reorder_modules/uz/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/uz/mod.rs diff --git a/tests/target/reorder_modules/v0/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v0/mod.rs similarity index 100% rename from tests/target/reorder_modules/v0/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v0/mod.rs diff --git a/tests/target/reorder_modules/v00/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v00/mod.rs similarity index 100% rename from tests/target/reorder_modules/v00/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v00/mod.rs diff --git a/tests/target/reorder_modules/v000/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v000/mod.rs similarity index 100% rename from tests/target/reorder_modules/v000/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v000/mod.rs diff --git a/tests/target/reorder_modules/v001/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v001/mod.rs similarity index 100% rename from tests/target/reorder_modules/v001/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v001/mod.rs diff --git a/tests/target/reorder_modules/v009/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v009/mod.rs similarity index 100% rename from tests/target/reorder_modules/v009/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v009/mod.rs diff --git a/tests/target/reorder_modules/v00t/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v00t/mod.rs similarity index 100% rename from tests/target/reorder_modules/v00t/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v00t/mod.rs diff --git a/tests/target/reorder_modules/v01/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v01/mod.rs similarity index 100% rename from tests/target/reorder_modules/v01/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v01/mod.rs diff --git a/tests/target/reorder_modules/v010/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v010/mod.rs similarity index 100% rename from tests/target/reorder_modules/v010/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v010/mod.rs diff --git a/tests/target/reorder_modules/v09/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v09/mod.rs similarity index 100% rename from tests/target/reorder_modules/v09/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v09/mod.rs diff --git a/tests/target/reorder_modules/v0s/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v0s/mod.rs similarity index 100% rename from tests/target/reorder_modules/v0s/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v0s/mod.rs diff --git a/tests/target/reorder_modules/v0u/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v0u/mod.rs similarity index 100% rename from tests/target/reorder_modules/v0u/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v0u/mod.rs diff --git a/tests/target/reorder_modules/v1/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v1/mod.rs similarity index 100% rename from tests/target/reorder_modules/v1/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v1/mod.rs diff --git a/tests/target/reorder_modules/v10/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v10/mod.rs similarity index 100% rename from tests/target/reorder_modules/v10/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v10/mod.rs diff --git a/tests/target/reorder_modules/v9/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/v9/mod.rs similarity index 100% rename from tests/target/reorder_modules/v9/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/v9/mod.rs diff --git a/tests/target/reorder_modules/w005s09t/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/w005s09t/mod.rs similarity index 100% rename from tests/target/reorder_modules/w005s09t/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/w005s09t/mod.rs diff --git a/tests/target/reorder_modules/w5s009t/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/w5s009t/mod.rs similarity index 100% rename from tests/target/reorder_modules/w5s009t/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/w5s009t/mod.rs diff --git a/tests/target/reorder_modules/x64/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x64/mod.rs similarity index 100% rename from tests/target/reorder_modules/x64/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x64/mod.rs diff --git a/tests/target/reorder_modules/x86/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x86/mod.rs similarity index 100% rename from tests/target/reorder_modules/x86/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x86/mod.rs diff --git a/tests/target/reorder_modules/x86_128/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x86_128/mod.rs similarity index 100% rename from tests/target/reorder_modules/x86_128/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x86_128/mod.rs diff --git a/tests/target/reorder_modules/x86_32/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x86_32/mod.rs similarity index 100% rename from tests/target/reorder_modules/x86_32/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x86_32/mod.rs diff --git a/tests/target/reorder_modules/x86_64/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x86_64/mod.rs similarity index 100% rename from tests/target/reorder_modules/x86_64/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x86_64/mod.rs diff --git a/tests/target/reorder_modules/x87/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/x87/mod.rs similarity index 100% rename from tests/target/reorder_modules/x87/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/x87/mod.rs diff --git a/tests/target/reorder_modules/zyxwv/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules/zyxwv/mod.rs similarity index 100% rename from tests/target/reorder_modules/zyxwv/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules/zyxwv/mod.rs diff --git a/tests/target/reorder_modules_2027/abcde/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules_2027/abcde/mod.rs similarity index 100% rename from tests/target/reorder_modules_2027/abcde/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules_2027/abcde/mod.rs diff --git a/tests/target/reorder_modules_2027/zyxwv/mod.rs b/src/tools/rustfmt/tests/target/reorder_modules_2027/zyxwv/mod.rs similarity index 100% rename from tests/target/reorder_modules_2027/zyxwv/mod.rs rename to src/tools/rustfmt/tests/target/reorder_modules_2027/zyxwv/mod.rs diff --git a/tests/target/return-type-notation.rs b/src/tools/rustfmt/tests/target/return-type-notation.rs similarity index 100% rename from tests/target/return-type-notation.rs rename to src/tools/rustfmt/tests/target/return-type-notation.rs diff --git a/tests/target/should_not_format_string_when_format_strings_is_not_set.rs b/src/tools/rustfmt/tests/target/should_not_format_string_when_format_strings_is_not_set.rs similarity index 100% rename from tests/target/should_not_format_string_when_format_strings_is_not_set.rs rename to src/tools/rustfmt/tests/target/should_not_format_string_when_format_strings_is_not_set.rs diff --git a/tests/target/single-line-if-else.rs b/src/tools/rustfmt/tests/target/single-line-if-else.rs similarity index 100% rename from tests/target/single-line-if-else.rs rename to src/tools/rustfmt/tests/target/single-line-if-else.rs diff --git a/tests/target/single-line-macro/v1.rs b/src/tools/rustfmt/tests/target/single-line-macro/v1.rs similarity index 100% rename from tests/target/single-line-macro/v1.rs rename to src/tools/rustfmt/tests/target/single-line-macro/v1.rs diff --git a/tests/target/single-line-macro/v2.rs b/src/tools/rustfmt/tests/target/single-line-macro/v2.rs similarity index 100% rename from tests/target/single-line-macro/v2.rs rename to src/tools/rustfmt/tests/target/single-line-macro/v2.rs diff --git a/tests/target/skip.rs b/src/tools/rustfmt/tests/target/skip.rs similarity index 100% rename from tests/target/skip.rs rename to src/tools/rustfmt/tests/target/skip.rs diff --git a/tests/target/skip/foo.rs b/src/tools/rustfmt/tests/target/skip/foo.rs similarity index 100% rename from tests/target/skip/foo.rs rename to src/tools/rustfmt/tests/target/skip/foo.rs diff --git a/tests/target/skip/main.rs b/src/tools/rustfmt/tests/target/skip/main.rs similarity index 100% rename from tests/target/skip/main.rs rename to src/tools/rustfmt/tests/target/skip/main.rs diff --git a/tests/target/skip/preserve_trailing_comment.rs b/src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs similarity index 100% rename from tests/target/skip/preserve_trailing_comment.rs rename to src/tools/rustfmt/tests/target/skip/preserve_trailing_comment.rs diff --git a/tests/target/skip_macro_invocations/all.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs similarity index 100% rename from tests/target/skip_macro_invocations/all.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/all.rs diff --git a/tests/target/skip_macro_invocations/all_and_name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs similarity index 100% rename from tests/target/skip_macro_invocations/all_and_name.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/all_and_name.rs diff --git a/tests/target/skip_macro_invocations/config_file.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs similarity index 100% rename from tests/target/skip_macro_invocations/config_file.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/config_file.rs diff --git a/tests/target/skip_macro_invocations/empty.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs similarity index 100% rename from tests/target/skip_macro_invocations/empty.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/empty.rs diff --git a/tests/target/skip_macro_invocations/name.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs similarity index 100% rename from tests/target/skip_macro_invocations/name.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/name.rs diff --git a/tests/target/skip_macro_invocations/name_unknown.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs similarity index 100% rename from tests/target/skip_macro_invocations/name_unknown.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/name_unknown.rs diff --git a/tests/target/skip_macro_invocations/names.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs similarity index 100% rename from tests/target/skip_macro_invocations/names.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/names.rs diff --git a/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs similarity index 100% rename from tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_invocation_mismatch.rs diff --git a/tests/target/skip_macro_invocations/path_qualified_match.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs similarity index 100% rename from tests/target/skip_macro_invocations/path_qualified_match.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_match.rs diff --git a/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs similarity index 100% rename from tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/path_qualified_name_mismatch.rs diff --git a/tests/target/skip_macro_invocations/use_alias_examples.rs b/src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs similarity index 100% rename from tests/target/skip_macro_invocations/use_alias_examples.rs rename to src/tools/rustfmt/tests/target/skip_macro_invocations/use_alias_examples.rs diff --git a/tests/target/skip_mod.rs b/src/tools/rustfmt/tests/target/skip_mod.rs similarity index 100% rename from tests/target/skip_mod.rs rename to src/tools/rustfmt/tests/target/skip_mod.rs diff --git a/tests/target/soft-wrapping.rs b/src/tools/rustfmt/tests/target/soft-wrapping.rs similarity index 100% rename from tests/target/soft-wrapping.rs rename to src/tools/rustfmt/tests/target/soft-wrapping.rs diff --git a/tests/target/space-not-before-newline.rs b/src/tools/rustfmt/tests/target/space-not-before-newline.rs similarity index 100% rename from tests/target/space-not-before-newline.rs rename to src/tools/rustfmt/tests/target/space-not-before-newline.rs diff --git a/tests/target/spaces-around-ranges.rs b/src/tools/rustfmt/tests/target/spaces-around-ranges.rs similarity index 100% rename from tests/target/spaces-around-ranges.rs rename to src/tools/rustfmt/tests/target/spaces-around-ranges.rs diff --git a/tests/target/splat.rs b/src/tools/rustfmt/tests/target/splat.rs similarity index 100% rename from tests/target/splat.rs rename to src/tools/rustfmt/tests/target/splat.rs diff --git a/tests/target/statements.rs b/src/tools/rustfmt/tests/target/statements.rs similarity index 100% rename from tests/target/statements.rs rename to src/tools/rustfmt/tests/target/statements.rs diff --git a/tests/target/static.rs b/src/tools/rustfmt/tests/target/static.rs similarity index 100% rename from tests/target/static.rs rename to src/tools/rustfmt/tests/target/static.rs diff --git a/tests/target/string-lit-2.rs b/src/tools/rustfmt/tests/target/string-lit-2.rs similarity index 100% rename from tests/target/string-lit-2.rs rename to src/tools/rustfmt/tests/target/string-lit-2.rs diff --git a/tests/target/string-lit-custom.rs b/src/tools/rustfmt/tests/target/string-lit-custom.rs similarity index 100% rename from tests/target/string-lit-custom.rs rename to src/tools/rustfmt/tests/target/string-lit-custom.rs diff --git a/tests/target/string-lit.rs b/src/tools/rustfmt/tests/target/string-lit.rs similarity index 100% rename from tests/target/string-lit.rs rename to src/tools/rustfmt/tests/target/string-lit.rs diff --git a/tests/target/string_lit_unicode_ws.rs b/src/tools/rustfmt/tests/target/string_lit_unicode_ws.rs similarity index 100% rename from tests/target/string_lit_unicode_ws.rs rename to src/tools/rustfmt/tests/target/string_lit_unicode_ws.rs diff --git a/tests/target/string_punctuation.rs b/src/tools/rustfmt/tests/target/string_punctuation.rs similarity index 100% rename from tests/target/string_punctuation.rs rename to src/tools/rustfmt/tests/target/string_punctuation.rs diff --git a/tests/target/struct-field-attributes.rs b/src/tools/rustfmt/tests/target/struct-field-attributes.rs similarity index 100% rename from tests/target/struct-field-attributes.rs rename to src/tools/rustfmt/tests/target/struct-field-attributes.rs diff --git a/tests/target/struct_field_doc_comment.rs b/src/tools/rustfmt/tests/target/struct_field_doc_comment.rs similarity index 100% rename from tests/target/struct_field_doc_comment.rs rename to src/tools/rustfmt/tests/target/struct_field_doc_comment.rs diff --git a/tests/target/struct_lits.rs b/src/tools/rustfmt/tests/target/struct_lits.rs similarity index 100% rename from tests/target/struct_lits.rs rename to src/tools/rustfmt/tests/target/struct_lits.rs diff --git a/tests/target/struct_lits_multiline.rs b/src/tools/rustfmt/tests/target/struct_lits_multiline.rs similarity index 100% rename from tests/target/struct_lits_multiline.rs rename to src/tools/rustfmt/tests/target/struct_lits_multiline.rs diff --git a/tests/target/struct_lits_visual.rs b/src/tools/rustfmt/tests/target/struct_lits_visual.rs similarity index 100% rename from tests/target/struct_lits_visual.rs rename to src/tools/rustfmt/tests/target/struct_lits_visual.rs diff --git a/tests/target/struct_lits_visual_multiline.rs b/src/tools/rustfmt/tests/target/struct_lits_visual_multiline.rs similarity index 100% rename from tests/target/struct_lits_visual_multiline.rs rename to src/tools/rustfmt/tests/target/struct_lits_visual_multiline.rs diff --git a/tests/target/struct_tuple_visual.rs b/src/tools/rustfmt/tests/target/struct_tuple_visual.rs similarity index 100% rename from tests/target/struct_tuple_visual.rs rename to src/tools/rustfmt/tests/target/struct_tuple_visual.rs diff --git a/tests/target/structs.rs b/src/tools/rustfmt/tests/target/structs.rs similarity index 100% rename from tests/target/structs.rs rename to src/tools/rustfmt/tests/target/structs.rs diff --git a/tests/target/style_edition/default.rs b/src/tools/rustfmt/tests/target/style_edition/default.rs similarity index 100% rename from tests/target/style_edition/default.rs rename to src/tools/rustfmt/tests/target/style_edition/default.rs diff --git a/tests/target/style_edition/follows_edition.rs b/src/tools/rustfmt/tests/target/style_edition/follows_edition.rs similarity index 100% rename from tests/target/style_edition/follows_edition.rs rename to src/tools/rustfmt/tests/target/style_edition/follows_edition.rs diff --git a/tests/target/style_edition/overrides_edition_when_set.rs b/src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs similarity index 100% rename from tests/target/style_edition/overrides_edition_when_set.rs rename to src/tools/rustfmt/tests/target/style_edition/overrides_edition_when_set.rs diff --git a/tests/target/super_let.rs b/src/tools/rustfmt/tests/target/super_let.rs similarity index 100% rename from tests/target/super_let.rs rename to src/tools/rustfmt/tests/target/super_let.rs diff --git a/tests/target/trailing-comma-never.rs b/src/tools/rustfmt/tests/target/trailing-comma-never.rs similarity index 100% rename from tests/target/trailing-comma-never.rs rename to src/tools/rustfmt/tests/target/trailing-comma-never.rs diff --git a/tests/target/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs b/src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs similarity index 100% rename from tests/target/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs rename to src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies-edition-2021-style-edition-2027.rs diff --git a/tests/target/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs b/src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs similarity index 100% rename from tests/target/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs rename to src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies-edition-2024-style-edition-2024.rs diff --git a/tests/target/trailing-semicolon/loop-bodies.rs b/src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies.rs similarity index 100% rename from tests/target/trailing-semicolon/loop-bodies.rs rename to src/tools/rustfmt/tests/target/trailing-semicolon/loop-bodies.rs diff --git a/tests/target/trailing_commas.rs b/src/tools/rustfmt/tests/target/trailing_commas.rs similarity index 100% rename from tests/target/trailing_commas.rs rename to src/tools/rustfmt/tests/target/trailing_commas.rs diff --git a/tests/target/trailing_comments/hard_tabs.rs b/src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs similarity index 100% rename from tests/target/trailing_comments/hard_tabs.rs rename to src/tools/rustfmt/tests/target/trailing_comments/hard_tabs.rs diff --git a/tests/target/trailing_comments/soft_tabs.rs b/src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs similarity index 100% rename from tests/target/trailing_comments/soft_tabs.rs rename to src/tools/rustfmt/tests/target/trailing_comments/soft_tabs.rs diff --git a/tests/target/trait.rs b/src/tools/rustfmt/tests/target/trait.rs similarity index 100% rename from tests/target/trait.rs rename to src/tools/rustfmt/tests/target/trait.rs diff --git a/tests/target/try-conversion.rs b/src/tools/rustfmt/tests/target/try-conversion.rs similarity index 100% rename from tests/target/try-conversion.rs rename to src/tools/rustfmt/tests/target/try-conversion.rs diff --git a/tests/target/try_block.rs b/src/tools/rustfmt/tests/target/try_block.rs similarity index 100% rename from tests/target/try_block.rs rename to src/tools/rustfmt/tests/target/try_block.rs diff --git a/tests/target/try_blocks_heterogeneous.rs b/src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs similarity index 100% rename from tests/target/try_blocks_heterogeneous.rs rename to src/tools/rustfmt/tests/target/try_blocks_heterogeneous.rs diff --git a/tests/target/tuple.rs b/src/tools/rustfmt/tests/target/tuple.rs similarity index 100% rename from tests/target/tuple.rs rename to src/tools/rustfmt/tests/target/tuple.rs diff --git a/tests/target/tuple_v2.rs b/src/tools/rustfmt/tests/target/tuple_v2.rs similarity index 100% rename from tests/target/tuple_v2.rs rename to src/tools/rustfmt/tests/target/tuple_v2.rs diff --git a/tests/target/type-alias-where-clauses-with-comments.rs b/src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs similarity index 100% rename from tests/target/type-alias-where-clauses-with-comments.rs rename to src/tools/rustfmt/tests/target/type-alias-where-clauses-with-comments.rs diff --git a/tests/target/type-alias-where-clauses.rs b/src/tools/rustfmt/tests/target/type-alias-where-clauses.rs similarity index 100% rename from tests/target/type-alias-where-clauses.rs rename to src/tools/rustfmt/tests/target/type-alias-where-clauses.rs diff --git a/tests/target/type.rs b/src/tools/rustfmt/tests/target/type.rs similarity index 100% rename from tests/target/type.rs rename to src/tools/rustfmt/tests/target/type.rs diff --git a/tests/target/type_alias.rs b/src/tools/rustfmt/tests/target/type_alias.rs similarity index 100% rename from tests/target/type_alias.rs rename to src/tools/rustfmt/tests/target/type_alias.rs diff --git a/tests/target/unicode.rs b/src/tools/rustfmt/tests/target/unicode.rs similarity index 100% rename from tests/target/unicode.rs rename to src/tools/rustfmt/tests/target/unicode.rs diff --git a/tests/target/unindent_if_else_cond_comment.rs b/src/tools/rustfmt/tests/target/unindent_if_else_cond_comment.rs similarity index 100% rename from tests/target/unindent_if_else_cond_comment.rs rename to src/tools/rustfmt/tests/target/unindent_if_else_cond_comment.rs diff --git a/tests/target/unions.rs b/src/tools/rustfmt/tests/target/unions.rs similarity index 100% rename from tests/target/unions.rs rename to src/tools/rustfmt/tests/target/unions.rs diff --git a/tests/target/unsafe-binders.rs b/src/tools/rustfmt/tests/target/unsafe-binders.rs similarity index 100% rename from tests/target/unsafe-binders.rs rename to src/tools/rustfmt/tests/target/unsafe-binders.rs diff --git a/tests/target/unsafe-field.rs b/src/tools/rustfmt/tests/target/unsafe-field.rs similarity index 100% rename from tests/target/unsafe-field.rs rename to src/tools/rustfmt/tests/target/unsafe-field.rs diff --git a/tests/target/unsafe-mod.rs b/src/tools/rustfmt/tests/target/unsafe-mod.rs similarity index 100% rename from tests/target/unsafe-mod.rs rename to src/tools/rustfmt/tests/target/unsafe-mod.rs diff --git a/tests/target/unsafe_attributes.rs b/src/tools/rustfmt/tests/target/unsafe_attributes.rs similarity index 100% rename from tests/target/unsafe_attributes.rs rename to src/tools/rustfmt/tests/target/unsafe_attributes.rs diff --git a/tests/target/unsafe_extern_blocks.rs b/src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs similarity index 100% rename from tests/target/unsafe_extern_blocks.rs rename to src/tools/rustfmt/tests/target/unsafe_extern_blocks.rs diff --git a/tests/target/use-identifier-order-mixed-edition.rs b/src/tools/rustfmt/tests/target/use-identifier-order-mixed-edition.rs similarity index 100% rename from tests/target/use-identifier-order-mixed-edition.rs rename to src/tools/rustfmt/tests/target/use-identifier-order-mixed-edition.rs diff --git a/tests/target/use-identifier-order.rs b/src/tools/rustfmt/tests/target/use-identifier-order.rs similarity index 100% rename from tests/target/use-identifier-order.rs rename to src/tools/rustfmt/tests/target/use-identifier-order.rs diff --git a/tests/target/visibility.rs b/src/tools/rustfmt/tests/target/visibility.rs similarity index 100% rename from tests/target/visibility.rs rename to src/tools/rustfmt/tests/target/visibility.rs diff --git a/tests/target/visual-fn-type.rs b/src/tools/rustfmt/tests/target/visual-fn-type.rs similarity index 100% rename from tests/target/visual-fn-type.rs rename to src/tools/rustfmt/tests/target/visual-fn-type.rs diff --git a/tests/target/where-clause-rfc.rs b/src/tools/rustfmt/tests/target/where-clause-rfc.rs similarity index 100% rename from tests/target/where-clause-rfc.rs rename to src/tools/rustfmt/tests/target/where-clause-rfc.rs diff --git a/tests/target/where-clause.rs b/src/tools/rustfmt/tests/target/where-clause.rs similarity index 100% rename from tests/target/where-clause.rs rename to src/tools/rustfmt/tests/target/where-clause.rs diff --git a/tests/target/width-heuristics.rs b/src/tools/rustfmt/tests/target/width-heuristics.rs similarity index 100% rename from tests/target/width-heuristics.rs rename to src/tools/rustfmt/tests/target/width-heuristics.rs diff --git a/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs b/src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs similarity index 100% rename from tests/target/wrap_comments_should_not_imply_format_doc_comments.rs rename to src/tools/rustfmt/tests/target/wrap_comments_should_not_imply_format_doc_comments.rs diff --git a/tests/warning/snapshots/deprecated_skip.snap b/src/tools/rustfmt/tests/warning/snapshots/deprecated_skip.snap similarity index 100% rename from tests/warning/snapshots/deprecated_skip.snap rename to src/tools/rustfmt/tests/warning/snapshots/deprecated_skip.snap diff --git a/tests/warning/snapshots/invalid_attribute.snap b/src/tools/rustfmt/tests/warning/snapshots/invalid_attribute.snap similarity index 100% rename from tests/warning/snapshots/invalid_attribute.snap rename to src/tools/rustfmt/tests/warning/snapshots/invalid_attribute.snap diff --git a/tests/warning/snapshots/issue_3950.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_3950.snap similarity index 100% rename from tests/warning/snapshots/issue_3950.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_3950.snap diff --git a/tests/warning/snapshots/issue_4968.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_4968.snap similarity index 100% rename from tests/warning/snapshots/issue_4968.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_4968.snap diff --git a/tests/warning/snapshots/issue_6442.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_6442.snap similarity index 100% rename from tests/warning/snapshots/issue_6442.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_6442.snap diff --git a/tests/warning/snapshots/issue_6632.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_6632.snap similarity index 100% rename from tests/warning/snapshots/issue_6632.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_6632.snap diff --git a/tests/warning/snapshots/issue_6826.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_6826.snap similarity index 100% rename from tests/warning/snapshots/issue_6826.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_6826.snap diff --git a/tests/warning/snapshots/issue_6850.snap b/src/tools/rustfmt/tests/warning/snapshots/issue_6850.snap similarity index 100% rename from tests/warning/snapshots/issue_6850.snap rename to src/tools/rustfmt/tests/warning/snapshots/issue_6850.snap diff --git a/tests/warning/snapshots/line_overflow.snap b/src/tools/rustfmt/tests/warning/snapshots/line_overflow.snap similarity index 100% rename from tests/warning/snapshots/line_overflow.snap rename to src/tools/rustfmt/tests/warning/snapshots/line_overflow.snap diff --git a/tests/warning/snapshots/line_overflow_tabs.snap b/src/tools/rustfmt/tests/warning/snapshots/line_overflow_tabs.snap similarity index 100% rename from tests/warning/snapshots/line_overflow_tabs.snap rename to src/tools/rustfmt/tests/warning/snapshots/line_overflow_tabs.snap diff --git a/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap b/src/tools/rustfmt/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap similarity index 100% rename from tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap rename to src/tools/rustfmt/tests/warning/snapshots/line_overflow_with_trailing_whitespace.snap diff --git a/tests/warning/snapshots/lost_comment.snap b/src/tools/rustfmt/tests/warning/snapshots/lost_comment.snap similarity index 100% rename from tests/warning/snapshots/lost_comment.snap rename to src/tools/rustfmt/tests/warning/snapshots/lost_comment.snap diff --git a/tests/warning/snapshots/multiple_errors.snap b/src/tools/rustfmt/tests/warning/snapshots/multiple_errors.snap similarity index 100% rename from tests/warning/snapshots/multiple_errors.snap rename to src/tools/rustfmt/tests/warning/snapshots/multiple_errors.snap diff --git a/tests/warning/snapshots/trailing_whitespace.snap b/src/tools/rustfmt/tests/warning/snapshots/trailing_whitespace.snap similarity index 100% rename from tests/warning/snapshots/trailing_whitespace.snap rename to src/tools/rustfmt/tests/warning/snapshots/trailing_whitespace.snap diff --git a/tests/warning/snapshots/trailing_whitespace_overflow.snap b/src/tools/rustfmt/tests/warning/snapshots/trailing_whitespace_overflow.snap similarity index 100% rename from tests/warning/snapshots/trailing_whitespace_overflow.snap rename to src/tools/rustfmt/tests/warning/snapshots/trailing_whitespace_overflow.snap diff --git a/tests/warning/snapshots/unicode_trailing_whitespace.snap b/src/tools/rustfmt/tests/warning/snapshots/unicode_trailing_whitespace.snap similarity index 100% rename from tests/warning/snapshots/unicode_trailing_whitespace.snap rename to src/tools/rustfmt/tests/warning/snapshots/unicode_trailing_whitespace.snap diff --git a/tests/warning/source/deprecated_skip.rs b/src/tools/rustfmt/tests/warning/source/deprecated_skip.rs similarity index 100% rename from tests/warning/source/deprecated_skip.rs rename to src/tools/rustfmt/tests/warning/source/deprecated_skip.rs diff --git a/tests/warning/source/invalid_attribute.rs b/src/tools/rustfmt/tests/warning/source/invalid_attribute.rs similarity index 100% rename from tests/warning/source/invalid_attribute.rs rename to src/tools/rustfmt/tests/warning/source/invalid_attribute.rs diff --git a/tests/warning/source/issue_3950.rs b/src/tools/rustfmt/tests/warning/source/issue_3950.rs similarity index 100% rename from tests/warning/source/issue_3950.rs rename to src/tools/rustfmt/tests/warning/source/issue_3950.rs diff --git a/tests/warning/source/issue_4968.rs b/src/tools/rustfmt/tests/warning/source/issue_4968.rs similarity index 100% rename from tests/warning/source/issue_4968.rs rename to src/tools/rustfmt/tests/warning/source/issue_4968.rs diff --git a/tests/warning/source/issue_6442.rs b/src/tools/rustfmt/tests/warning/source/issue_6442.rs similarity index 100% rename from tests/warning/source/issue_6442.rs rename to src/tools/rustfmt/tests/warning/source/issue_6442.rs diff --git a/tests/warning/source/issue_6632.rs b/src/tools/rustfmt/tests/warning/source/issue_6632.rs similarity index 100% rename from tests/warning/source/issue_6632.rs rename to src/tools/rustfmt/tests/warning/source/issue_6632.rs diff --git a/tests/warning/source/issue_6826.rs b/src/tools/rustfmt/tests/warning/source/issue_6826.rs similarity index 100% rename from tests/warning/source/issue_6826.rs rename to src/tools/rustfmt/tests/warning/source/issue_6826.rs diff --git a/tests/warning/source/issue_6850.rs b/src/tools/rustfmt/tests/warning/source/issue_6850.rs similarity index 100% rename from tests/warning/source/issue_6850.rs rename to src/tools/rustfmt/tests/warning/source/issue_6850.rs diff --git a/tests/warning/source/line_overflow.rs b/src/tools/rustfmt/tests/warning/source/line_overflow.rs similarity index 100% rename from tests/warning/source/line_overflow.rs rename to src/tools/rustfmt/tests/warning/source/line_overflow.rs diff --git a/tests/warning/source/line_overflow_tabs.rs b/src/tools/rustfmt/tests/warning/source/line_overflow_tabs.rs similarity index 100% rename from tests/warning/source/line_overflow_tabs.rs rename to src/tools/rustfmt/tests/warning/source/line_overflow_tabs.rs diff --git a/tests/warning/source/line_overflow_with_trailing_whitespace.rs b/src/tools/rustfmt/tests/warning/source/line_overflow_with_trailing_whitespace.rs similarity index 100% rename from tests/warning/source/line_overflow_with_trailing_whitespace.rs rename to src/tools/rustfmt/tests/warning/source/line_overflow_with_trailing_whitespace.rs diff --git a/tests/warning/source/lost_comment.rs b/src/tools/rustfmt/tests/warning/source/lost_comment.rs similarity index 100% rename from tests/warning/source/lost_comment.rs rename to src/tools/rustfmt/tests/warning/source/lost_comment.rs diff --git a/tests/warning/source/multiple_errors.rs b/src/tools/rustfmt/tests/warning/source/multiple_errors.rs similarity index 100% rename from tests/warning/source/multiple_errors.rs rename to src/tools/rustfmt/tests/warning/source/multiple_errors.rs diff --git a/tests/warning/source/trailing_whitespace.rs b/src/tools/rustfmt/tests/warning/source/trailing_whitespace.rs similarity index 100% rename from tests/warning/source/trailing_whitespace.rs rename to src/tools/rustfmt/tests/warning/source/trailing_whitespace.rs diff --git a/tests/warning/source/trailing_whitespace_overflow.rs b/src/tools/rustfmt/tests/warning/source/trailing_whitespace_overflow.rs similarity index 100% rename from tests/warning/source/trailing_whitespace_overflow.rs rename to src/tools/rustfmt/tests/warning/source/trailing_whitespace_overflow.rs diff --git a/tests/warning/source/unicode_trailing_whitespace.rs b/src/tools/rustfmt/tests/warning/source/unicode_trailing_whitespace.rs similarity index 100% rename from tests/warning/source/unicode_trailing_whitespace.rs rename to src/tools/rustfmt/tests/warning/source/unicode_trailing_whitespace.rs diff --git a/tests/writemode/source/fn-single-line.rs b/src/tools/rustfmt/tests/writemode/source/fn-single-line.rs similarity index 100% rename from tests/writemode/source/fn-single-line.rs rename to src/tools/rustfmt/tests/writemode/source/fn-single-line.rs diff --git a/tests/writemode/source/json.rs b/src/tools/rustfmt/tests/writemode/source/json.rs similarity index 100% rename from tests/writemode/source/json.rs rename to src/tools/rustfmt/tests/writemode/source/json.rs diff --git a/tests/writemode/source/modified.rs b/src/tools/rustfmt/tests/writemode/source/modified.rs similarity index 100% rename from tests/writemode/source/modified.rs rename to src/tools/rustfmt/tests/writemode/source/modified.rs diff --git a/tests/writemode/source/stdin.rs b/src/tools/rustfmt/tests/writemode/source/stdin.rs similarity index 100% rename from tests/writemode/source/stdin.rs rename to src/tools/rustfmt/tests/writemode/source/stdin.rs diff --git a/tests/writemode/target/checkstyle.xml b/src/tools/rustfmt/tests/writemode/target/checkstyle.xml similarity index 100% rename from tests/writemode/target/checkstyle.xml rename to src/tools/rustfmt/tests/writemode/target/checkstyle.xml diff --git a/tests/writemode/target/modified.txt b/src/tools/rustfmt/tests/writemode/target/modified.txt similarity index 100% rename from tests/writemode/target/modified.txt rename to src/tools/rustfmt/tests/writemode/target/modified.txt diff --git a/tests/writemode/target/output.json b/src/tools/rustfmt/tests/writemode/target/output.json similarity index 100% rename from tests/writemode/target/output.json rename to src/tools/rustfmt/tests/writemode/target/output.json diff --git a/tests/writemode/target/stdin.json b/src/tools/rustfmt/tests/writemode/target/stdin.json similarity index 100% rename from tests/writemode/target/stdin.json rename to src/tools/rustfmt/tests/writemode/target/stdin.json diff --git a/tests/writemode/target/stdin.xml b/src/tools/rustfmt/tests/writemode/target/stdin.xml similarity index 100% rename from tests/writemode/target/stdin.xml rename to src/tools/rustfmt/tests/writemode/target/stdin.xml diff --git a/triagebot.toml b/src/tools/rustfmt/triagebot.toml similarity index 100% rename from triagebot.toml rename to src/tools/rustfmt/triagebot.toml From 880d20ea14d42476d70499dcc39c808cf5d6cc25 Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 11 Sep 2026 21:18:55 +0200 Subject: [PATCH 0557/1309] refactor(config): extract `resolve_project_file()` and `config_from_user_dirs()` --- src/tools/rustfmt/src/config/mod.rs | 92 +++++++++++++++-------------- 1 file changed, 48 insertions(+), 44 deletions(-) diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index a3f9842cd4f7f..abbbd1d913b9c 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -354,50 +354,7 @@ impl Config { style_edition: Option, version: Option, ) -> Result<(Config, Option), Error> { - /// Try to find a project file in the given directory and its parents. - /// Returns the path of the nearest project file if one exists, - /// or `None` if no project file was found. - fn resolve_project_file(dir: &Path) -> Result, Error> { - let mut current = if dir.is_relative() { - env::current_dir()?.join(dir) - } else { - dir.to_path_buf() - }; - - current = fs::canonicalize(current)?; - - loop { - match get_toml_path(¤t) { - Ok(Some(path)) => return Ok(Some(path)), - Err(e) => return Err(e), - _ => (), - } - - // If the current directory has no parent, we're done searching. - if !current.pop() { - break; - } - } - - // If nothing was found, check in the home directory. - if let Some(home_dir) = dirs::home_dir() { - if let Some(path) = get_toml_path(&home_dir)? { - return Ok(Some(path)); - } - } - - // If none was found there either, check in the user's configuration directory. - if let Some(mut config_dir) = dirs::config_dir() { - config_dir.push("rustfmt"); - if let Some(path) = get_toml_path(&config_dir)? { - return Ok(Some(path)); - } - } - - Ok(None) - } - - match resolve_project_file(dir)? { + match resolve_project_file(dir).or_else(|_| config_from_user_dirs())? { None => Ok(( Config::default_for_possible_style_edition(style_edition, edition, version), None, @@ -455,6 +412,53 @@ impl Config { } } +/// Looks for a configuration file in the given directory and its parents. +/// +/// Returns the path of the configuration file nearest to that directory if one exists, or `None` if +/// none was found. +fn resolve_project_file(dir: &Path) -> Result, Error> { + let mut current = if dir.is_relative() { + env::current_dir()?.join(dir) + } else { + dir.to_path_buf() + }; + + current = fs::canonicalize(current)?; + + loop { + match get_toml_path(¤t) { + Ok(Some(path)) => return Ok(Some(path)), + Err(e) => return Err(e), + _ => (), + } + + // If the current directory has no parent, we're done searching. + if !current.pop() { + break Ok(None); + } + } +} + +/// Looks for a configuration file in the user's home directory and configuration directory. +/// +/// Returns the path of the first configuration file found in that order, or `None` if none was +/// found. +fn config_from_user_dirs() -> Result, Error> { + for dir in [ + dirs::home_dir(), + dirs::config_dir().map(|d| d.join("rustfmt")), + ] + .iter() + .flatten() + { + if let Some(path) = get_toml_path(&dir)? { + return Ok(Some(path)); + } + } + + Ok(None) +} + /// Loads a config by checking the client-supplied options and if appropriate, the /// file system (including searching the file system for overrides). pub fn load_config( From ec2bb9caaaef73ef1e1b5f0e6d3e779913a9c32f Mon Sep 17 00:00:00 2001 From: rami3l Date: Fri, 11 Sep 2026 21:40:19 +0200 Subject: [PATCH 0558/1309] fix(config): search for config file recursively on `--config-path` --- src/tools/rustfmt/src/config/mod.rs | 9 +-------- src/tools/rustfmt/tests/rustfmt/main.rs | 12 ++++-------- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs index abbbd1d913b9c..780402d21fe29 100644 --- a/src/tools/rustfmt/src/config/mod.rs +++ b/src/tools/rustfmt/src/config/mod.rs @@ -538,14 +538,7 @@ fn config_path(options: &dyn CliOptions) -> Result, Error> { // If a config file cannot be found from the given path, return error. match options.config_path() { Some(path) if !path.exists() => config_path_not_found(path.to_str().unwrap()), - Some(path) if path.is_dir() => { - let config_file_path = get_toml_path(path)?; - if config_file_path.is_some() { - Ok(config_file_path) - } else { - config_path_not_found(path.to_str().unwrap()) - } - } + Some(path) if path.is_dir() => resolve_project_file(path), Some(path) => Ok(Some( // Canonicalize only after checking above that the `path.exists()`. path.canonicalize()?, diff --git a/src/tools/rustfmt/tests/rustfmt/main.rs b/src/tools/rustfmt/tests/rustfmt/main.rs index 7d60f3343f646..e04fae7ad043c 100644 --- a/src/tools/rustfmt/tests/rustfmt/main.rs +++ b/src/tools/rustfmt/tests/rustfmt/main.rs @@ -346,19 +346,15 @@ fn rustfmt_error_improvement_regarding_invalid_toml() { } #[test] -fn config_path_does_not_walk_parent_directories_with_dir_name() { +fn config_path_walks_parent_directories_with_dir_name() { let src_dir = "tests/config/issue_4660/inner_lib/src"; let src_file = src_dir.to_owned() + "/lib.rs"; let args = ["--config-path", src_dir, "--check", &src_file]; let (stdout, stderr) = rustfmt(&args); - assert_eq!( - stderr, - format!( - "Error: unable to find a config file for the given path: `{}`\n", - Path::new(src_dir).display(), - ) - ); + assert_eq!(stderr, ""); + // Due to `disable_all_formatting = true` in `tests/config/issue_4660/inner_lib/rustfmt.toml`, + // the source file should not be modified. assert_eq!(stdout, ""); } From c644bf30478a9bf19301f63061ab795a486227ea Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:30:02 +0200 Subject: [PATCH 0559/1309] add option for aggressive reflow --- src/doc/rustc-dev-guide/ci/sembr/src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs index 2d7fd26023e20..359deab6f6d7d 100644 --- a/src/doc/rustc-dev-guide/ci/sembr/src/main.rs +++ b/src/doc/rustc-dev-guide/ci/sembr/src/main.rs @@ -14,6 +14,9 @@ struct Cli { /// Modify files that do not comply #[arg(long)] overwrite: bool, + /// This reflows file even when it complies (with one sentence per line) + #[arg(long)] + reflow_harder: bool, /// Applies to lines that are to be split #[arg(long, default_value_t = 100)] line_length_limit: usize, @@ -45,7 +48,10 @@ fn main() -> Result<()> { continue; } let old = fs::read_to_string(&path)?; - let new = comply(&old); + let mut new = comply(&old); + if cli.reflow_harder { + new = lengthen_lines(&new, cli.line_length_limit) + } if new == old { compliant.push(path.clone()); } else if cli.overwrite { From 011344391c6da6f9fc7c8b4d5d9ca54d9cfc218d Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:30:55 +0200 Subject: [PATCH 0560/1309] reflow src/building/suggested.md --- .../rustc-dev-guide/src/building/suggested.md | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/suggested.md b/src/doc/rustc-dev-guide/src/building/suggested.md index a938008718148..ca8dd74ee4ff0 100644 --- a/src/doc/rustc-dev-guide/src/building/suggested.md +++ b/src/doc/rustc-dev-guide/src/building/suggested.md @@ -229,8 +229,8 @@ Emacs provides support for rust-analyzer with project-local configuration through [Eglot](https://www.gnu.org/software/emacs/manual/html_node/eglot/). Steps for setting up Eglot with rust-analyzer can be [found here](https://rust-analyzer.github.io/manual.html#eglot). -Having set up Emacs & Eglot for Rust development in general, you can run -`./x setup editor` and select `emacs`, +Having set up Emacs & Eglot for Rust development in general, +you can run `./x setup editor` and select `emacs`, which will prompt you to create `.dir-locals.el` with the recommended configuration for Eglot. The recommended settings live at [`src/etc/rust_analyzer_eglot.el`]. For more information on project-specific Eglot configuration, consult [the @@ -288,8 +288,7 @@ You may need to use the pinned nightly version from `src/stage0`, but often the normal `nightly` channel will work. **Note** see [the section on vscode] for how to configure it with this real rustfmt `x` uses, -and [the section on rustup] for how to setup `rustup` -toolchain for your bootstrapped compiler +and [the section on rustup] for how to setup `rustup` toolchain for your bootstrapped compiler **Note** This does _not_ allow you to build `rustc` with cargo directly. You still have to use `x` to work on the compiler or standard library, @@ -333,8 +332,7 @@ old standard library can be re-used. If you are editing the compiler, this is often true: you haven't changed the standard library, after all. But sometimes, it's not true: for example, if you are editing the "metadata" part of the compiler, -which controls how the compiler encodes types and other states -into the `rlib` files, +which controls how the compiler encodes types and other states into the `rlib` files, or if you are editing things that wind up in the metadata (such as the definition of the MIR). That is, you might get weird behavior from a compile when using `--keep-stage-std=1`, @@ -389,8 +387,8 @@ Working on multiple branches in parallel can be a little annoying, since building the compiler on one branch will cause the old build and the incremental compilation cache to be overwritten. One solution would be to have multiple clones of the repository, -but that would mean storing the Git metadata multiple -times, and having to update each clone individually. +but that would mean storing the Git metadata multiple times, +and having to update each clone individually. Fortunately, Git has a better solution called [worktrees]. This lets you create multiple "working trees", which all share the same Git database. @@ -445,8 +443,8 @@ set up correctly. Note that when using nix on a not-NixOS distribution, it may be necessary to set **`build.patch-binaries-for-nix = true` in `bootstrap.toml`**. -Bootstrap tries to detect whether it's running in nix and enable patching automatically, but this -detection can have false negatives. +Bootstrap tries to detect whether it's running in nix and enable patching automatically, +but this detection can have false negatives. You can also use your nix shell to manage `bootstrap.toml`: From be73dba6f7c39b6607edfe19def64f6440cecfbf Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:32:42 +0200 Subject: [PATCH 0561/1309] reflow src/ty-fold.md --- src/doc/rustc-dev-guide/src/ty-fold.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/ty-fold.md b/src/doc/rustc-dev-guide/src/ty-fold.md index 81761252bca98..f7fce9a981af1 100644 --- a/src/doc/rustc-dev-guide/src/ty-fold.md +++ b/src/doc/rustc-dev-guide/src/ty-fold.md @@ -7,8 +7,7 @@ to find any usages of the bound vars in order to replace them. Binders can wrap an arbitrary Rust type `T`, not just a `Ty`. So, how do we implement the `instantiate` methods on the `Early/Binder` types? -The answer is a couple of traits: [`TypeFoldable`] -and [`TypeFolder`]. +The answer is a couple of traits: [`TypeFoldable`] and [`TypeFolder`]. - `TypeFoldable` is implemented by types that embed type information. It allows you to recursively process the contents of `TypeFoldable` and do stuff to them. From e0377753dff6c72e3717517376ad8692a7133a84 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:33:14 +0200 Subject: [PATCH 0562/1309] sembr src/tests/intro.md --- src/doc/rustc-dev-guide/src/tests/intro.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/intro.md b/src/doc/rustc-dev-guide/src/tests/intro.md index f8cd390a55fbf..8c1e6c65b1042 100644 --- a/src/doc/rustc-dev-guide/src/tests/intro.md +++ b/src/doc/rustc-dev-guide/src/tests/intro.md @@ -16,8 +16,8 @@ The main test harness for testing the compiler itself is a tool called [compilet [compiletest] supports running different styles of tests, organized into *test suites*. -A *test mode* may provide common presets/behavior for a set of *test -suites*. [compiletest]-supported tests are located in the [`tests`] directory. +A *test mode* may provide common presets/behavior for a set of *test suites*. +[compiletest]-supported tests are located in the [`tests`] directory. The [Compiletest chapter][compiletest] goes into detail on how to use this tool. From 28b5293debd90e0ad9b8ccb937c03e499cfc2170 Mon Sep 17 00:00:00 2001 From: lcnr Date: Mon, 21 Sep 2026 17:16:37 +0200 Subject: [PATCH 0563/1309] add field_projections fixme --- .../src/traits/select/candidate_assembly.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs index 8509be2fb6dec..120f83c14b5c7 100644 --- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs +++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs @@ -1494,6 +1494,9 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> { obligation: &PolyTraitObligation<'tcx>, candidates: &mut SelectionCandidateSet<'tcx>, ) { + // FIXME(field_projections): We should not use `evaluate_obligation` in + // the trait solver. Doing so means we don't track overflow and cycles properly + // encountering query cycles instead. if let ty::Adt(def, args) = obligation.predicate.self_ty().skip_binder().kind() && let Some(FieldInfo { base, ty, .. }) = def.field_representing_type_info(self.tcx(), args) From c263e3de4d240f871206d00075188918eb6e1bbb Mon Sep 17 00:00:00 2001 From: Amirhossein Akhlaghpour Date: Thu, 10 Sep 2026 16:02:27 +0330 Subject: [PATCH 0564/1309] avoid accessing uninferred closure upvars in diagnostics Signed-off-by: Amirhossein Akhlaghpour --- .../src/error_reporting/traits/suggestions.rs | 11 ++++- ...-capture-uninferred-upvars-issue-162440.rs | 12 +++++ ...ture-uninferred-upvars-issue-162440.stderr | 41 ++++++++++++++++ ...-capture-uninferred-upvars-with-capture.rs | 16 ++++++ ...ture-uninferred-upvars-with-capture.stderr | 49 +++++++++++++++++++ 5 files changed, 128 insertions(+), 1 deletion(-) create mode 100644 tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs create mode 100644 tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr create mode 100644 tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs create mode 100644 tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 4f5d93a2fe286..6ede57df7d0f5 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -3787,9 +3787,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> { if typeck_results.hir_owner.to_def_id() != typeck_root { return false; } + + // Error reporting can run before closure capture analysis has inferred the + // tuple of upvar types. avoid accessing upvar types until they are available. + let upvar_tys = match upvar_args.tupled_upvars_ty().kind() { + ty::Tuple(args) => args, + ty::Error(_) => ty::List::empty(), + ty::Infer(_) => return false, + ty => unreachable!("unexpected upvar types tuple: {ty:?}"), + }; + let captures: Vec<_> = typeck_results.closure_min_captures_flattened(closure_def_id).collect(); - let upvar_tys = upvar_args.upvar_tys(); if captures.len() != upvar_tys.len() { return false; } diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs new file mode 100644 index 0000000000000..9b6562ff578bf --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.rs @@ -0,0 +1,12 @@ +// Regression test for #162440. Diagnostics can run before closure capture +// analysis has inferred the tuple of upvar types. The capture-specific note +// must fall back instead of trying to access uninferred upvar types. + +//@ compile-flags: -Znext-solver=globally + +fn main() { + Some([0]).map(|s| s[..]); + //~^ ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time +} diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr new file mode 100644 index 0000000000000..4aed7e179b8ef --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-issue-162440.stderr @@ -0,0 +1,41 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:15 + | +LL | Some([0]).map(|s| s[..]); + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:23 + | +LL | Some([0]).map(|s| s[..]); + | ^^^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` + = note: the return type of a function must have a statically known size + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19 + | +LL | Some([0]).map(|s| s[..]); + | --- ---^^^^^^ + | | | + | | doesn't have a size known at compile-time + | | within this `{closure@$DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19: 8:22}` + | required by a bound introduced by this call + | + = help: within `{closure@$DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19: 8:22}`, the trait `Sized` is not implemented for `[{integer}]` +note: required because it's used within this closure + --> $DIR/closure-capture-uninferred-upvars-issue-162440.rs:8:19 + | +LL | Some([0]).map(|s| s[..]); + | ^^^ +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs new file mode 100644 index 0000000000000..ff4a9b67a3fee --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.rs @@ -0,0 +1,16 @@ +// Diagnostics may run before closure capture analysis has inferred the upvar +// tuple, even for a closure which actually captures a value. + +//@ compile-flags: -Znext-solver=globally + +fn main() { + let x = String::new(); + + Some([0]).map(|s| { + //~^ ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + //~| ERROR the size for values of type `[{integer}]` cannot be known at compilation time + let _ = &x; + s[..] + }); +} diff --git a/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr new file mode 100644 index 0000000000000..b19dca701f2fb --- /dev/null +++ b/tests/ui/traits/next-solver/closure-capture-uninferred-upvars-with-capture.stderr @@ -0,0 +1,49 @@ +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:15 + | +LL | Some([0]).map(|s| { + | ^^^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` +note: required by an implicit `Sized` bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:23 + | +LL | Some([0]).map(|s| { + | _______________________^ +... | +LL | | s[..] +LL | | }); + | |_____^ doesn't have a size known at compile-time + | + = help: the trait `Sized` is not implemented for `[{integer}]` + = note: the return type of a function must have a statically known size + +error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19 + | +LL | Some([0]).map(|s| { + | --- ^-- + | | | + | _______________|___within this `{closure@$DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19: 9:22}` + | | | + | | required by a bound introduced by this call +... | +LL | | s[..] +LL | | }); + | |_____^ doesn't have a size known at compile-time + | + = help: within `{closure@$DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19: 9:22}`, the trait `Sized` is not implemented for `[{integer}]` +note: required because it's used within this closure + --> $DIR/closure-capture-uninferred-upvars-with-capture.rs:9:19 + | +LL | Some([0]).map(|s| { + | ^^^ +note: required by a bound in `Option::::map` + --> $SRC_DIR/core/src/option.rs:LL:COL + +error: aborting due to 3 previous errors + +For more information about this error, try `rustc --explain E0277`. From f87870047f35414c3487265aba71caa646492879 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Sep 2026 17:15:55 +0200 Subject: [PATCH 0565/1309] bootstrap: print when we are testing in Miri --- src/bootstrap/src/core/build_steps/test.rs | 8 +++++++- src/bootstrap/src/core/builder/mod.rs | 3 +++ 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs index 47318d3c086f5..cd647eb32f515 100644 --- a/src/bootstrap/src/core/build_steps/test.rs +++ b/src/bootstrap/src/core/build_steps/test.rs @@ -3634,7 +3634,13 @@ impl CommandLineStep for Crate { if crates.iter().any(|crate_| crate_ == "alloc") { crates.push("alloctests".to_owned()); }; - let description = crate_description(&self.crates); + let mut description = crate_description(&self.crates); + if builder.kind == Kind::Miri { + if !description.is_empty() { + description.push(' '); + } + description.push_str("in Miri"); + } run_cargo_test(cargo, &[], &crates, &*description, target, builder, record_failed_tests); } } diff --git a/src/bootstrap/src/core/builder/mod.rs b/src/bootstrap/src/core/builder/mod.rs index 0bd0781133684..0593f30946320 100644 --- a/src/bootstrap/src/core/builder/mod.rs +++ b/src/bootstrap/src/core/builder/mod.rs @@ -344,6 +344,9 @@ pub fn crate_description(crates: &[impl AsRef]) -> String { if crates.is_empty() { return "".into(); } + if crates.len() == 1 { + return crates[0].as_ref().into(); + } let mut descr = String::from("{"); descr.push_str(crates[0].as_ref()); From f1a050ef31744e8070d9d29182cb2a31e83de2fe Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 17:45:28 +0200 Subject: [PATCH 0566/1309] reflow src/tests/ecosystem-test-jobs/fuchsia.md --- .../rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md index ca7a9f482f1ae..19e3fb44bb8ed 100644 --- a/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md +++ b/src/doc/rustc-dev-guide/src/tests/ecosystem-test-jobs/fuchsia.md @@ -53,8 +53,7 @@ After running a Docker build, you'll find the Fuchsia checkout inside the `obj/test-x86_64-fuchsia/fuchsia` directory of your Rust checkout. If you modify the `KEEP_CHECKOUT` line in the [build-fuchsia.sh] script to `KEEP_CHECKOUT=1`, -you can change the checkout as needed and rerun -the build command above. +you can change the checkout as needed and rerun the build command above. This will reuse all the build results from before. You can find more options to customize the Fuchsia checkout in the [build-fuchsia.sh] script. From 447bb32fc186d47685ab48d4f70f8aeb3efcb07a Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Sep 2026 17:47:24 +0200 Subject: [PATCH 0567/1309] RA settings: disable diagnostics as RA shows many false positives --- src/tools/miri/etc/rust_analyzer_vscode.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/tools/miri/etc/rust_analyzer_vscode.json b/src/tools/miri/etc/rust_analyzer_vscode.json index e82c648f59ab4..42b9d830facf5 100644 --- a/src/tools/miri/etc/rust_analyzer_vscode.json +++ b/src/tools/miri/etc/rust_analyzer_vscode.json @@ -25,4 +25,6 @@ "--compile-time-deps", "--message-format=json", ], + // RA reports false errors due to + "rust-analyzer.diagnostics.enable": false, } From 7ce3e5f226a774579a88ae53e7b9a6390890471c Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 18:00:23 +0200 Subject: [PATCH 0568/1309] sembr src/building/bootstrapping/what-bootstrapping-does.md --- .../bootstrapping/what-bootstrapping-does.md | 132 +++++++++--------- 1 file changed, 66 insertions(+), 66 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md index b986895c3b100..15ad385c17811 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md @@ -16,12 +16,12 @@ See [bootstrap/README.md][bootstrap-internals] to read about bootstrap internals Compiling `rustc` is done in stages. Here's a diagram, adapted from Jynn -Nelson's [talk on bootstrapping][rustconf22-talk] at RustConf 2022, with -detailed explanations below. +Nelson's [talk on bootstrapping][rustconf22-talk] at RustConf 2022, +with detailed explanations below. The `A`, `B`, `C`, and `D` show the ordering of the stages of bootstrapping. -Blue nodes are -downloaded, yellow +Blue nodes are downloaded, +yellow nodes are built with the `stage0` compiler, and green nodes are built with the `stage1` compiler. @@ -54,8 +54,8 @@ The precompiled stage0 compiler is then used only to compile [`src/bootstrap`] a with precompiled stage0 std. Note that to build the stage1 compiler we use the precompiled stage0 compiler and std. -Therefore, to use a compiler with a std that is freshly built from the tree, you need to -build the stage2 compiler. +Therefore, to use a compiler with a std that is freshly built from the tree, +you need to build the stage2 compiler. There are two concepts at play here: a compiler (with its set of dependencies) and its 'target' or 'object' libraries (`std` and `rustc`). @@ -77,8 +77,8 @@ The `stage1` compiler itself was built by precompiled `stage0` compiler and std and hence not by the source in your working directory. This means that the ABI generated by the `stage0` compiler may not match the ABI that would have been made -by the `stage1` compiler, which can cause problems for dynamic libraries, tests -and tools using `rustc_private`. +by the `stage1` compiler, which can cause problems for dynamic libraries, +tests and tools using `rustc_private`. Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called `proc_macro::bridge`, allowing it to be used with `stage1`. @@ -119,20 +119,20 @@ For more information about stages, [see below](#understanding-stages-of-bootstra ## Complications of bootstrapping -Since the build system uses the current beta compiler to build a `stage1` -bootstrapping compiler, the compiler source code can't use some features until +Since the build system uses the current beta compiler to build a `stage1` bootstrapping compiler, +the compiler source code can't use some features until they reach beta (because otherwise the beta compiler doesn't support them). -On the other hand, for [compiler intrinsics][intrinsics] and internal features, the -features _have_ to be used. +On the other hand, for [compiler intrinsics][intrinsics] and internal features, +the features _have_ to be used. Additionally, the compiler makes heavy use of `nightly` features (`#![feature(...)]`). How can we resolve this problem? There are two methods used: -1. The build system sets `--cfg bootstrap` when building with `stage0`, so we - can use `cfg(not(bootstrap))` to only use features when built with `stage1`. - Setting `--cfg bootstrap` in this way is used for features that were just - stabilized, which require `#![feature(...)]` when built with `stage0`, but not for `stage1`. +1. The build system sets `--cfg bootstrap` when building with `stage0`, + so we can use `cfg(not(bootstrap))` to only use features when built with `stage1`. + Setting `--cfg bootstrap` in this way is used for features that were just stabilized, + which require `#![feature(...)]` when built with `stage0`, but not for `stage1`. 2. The build system sets `RUSTC_BOOTSTRAP=1`. This special variable means to _break the stability guarantees_ of Rust: allowing use of `#![feature(...)]` @@ -152,8 +152,8 @@ The convention `./x` uses is that: - A `--stage N` flag means to run the stage N compiler (`stageN/rustc`). - A "stage N artifact" is a build artifact that is _produced_ by the stage N compiler. -- The stage N+1 compiler is assembled from stage N *artifacts*. This process is - called _uplifting_. +- The stage N+1 compiler is assembled from stage N *artifacts*. + This process is called _uplifting_. #### Build artifacts @@ -186,10 +186,10 @@ Build artifacts include, but are not limited to: - `./x test --stage 0 compiler/rustc` builds the compiler but runs no tests: it's running `cargo test -p rustc`, but `cargo` doesn't understand Rust's tests. You shouldn't need to use this; use `test` instead (without arguments). -- `./x build --stage 0 compiler/rustc` builds the compiler, but does not build - `libstd` or even `libcore`. - Most of the time, you'll want `./x build library` - instead, which allows compiling programs without needing to define lang items. +- `./x build --stage 0 compiler/rustc` builds the compiler, + but does not build `libstd` or even `libcore`. + Most of the time, you'll want `./x build library` instead, + which allows compiling programs without needing to define lang items. ### Building vs. running @@ -199,8 +199,8 @@ will later be uplifted to be the stage1 compiler_. In each stage besides 0, two major steps are performed: 1. `std` is compiled by the stage N compiler. -2. That `std` is linked to programs built by the stage N compiler, including the - stage N artifacts (stage N+1 compiler). +2. That `std` is linked to programs built by the stage N compiler, + including the stage N artifacts (stage N+1 compiler). This is somewhat intuitive if one thinks of the stage N artifacts as "just" another program we are building with the stage N compiler: `build --stage N @@ -211,23 +211,23 @@ compiler/rustc` is linking the stage N artifacts to the `std` built by the stage Note that there are two `std` libraries in play here: 1. The library _linked_ to `stageN/rustc`, which was built by stage N-1 (stage N-1 `std`) -2. The library _used to compile programs_ with `stageN/rustc`, which was built - by stage N (stage N `std`). +2. The library _used to compile programs_ with `stageN/rustc`, + which was built by stage N (stage N `std`). Stage N `std` is pretty much necessary for any useful work with the stage N compiler. Without it, you can only compile programs with `#![no_core]` -- not terribly useful! The reason these need to be different is because they aren't necessarily -ABI-compatible: there could be new layout optimizations, changes to `MIR`, or -other changes to Rust metadata on `nightly` that aren't present in beta. +ABI-compatible: there could be new layout optimizations, changes to `MIR`, +or other changes to Rust metadata on `nightly` that aren't present in beta. This is also where `--keep-stage 1 library/std` comes into play. Since most changes to the compiler don't actually change the ABI, once you've produced a `std` in `stage1`, you can probably just reuse it with a different compiler. If the ABI hasn't changed, you're good to go; no need to spend time recompiling that `std`. The flag `--keep-stage` simply instructs the build script to assume -the previous compile is fine and copies those artifacts into the appropriate -place, skipping the `cargo` invocation. +the previous compile is fine and copies those artifacts into the appropriate place, +skipping the `cargo` invocation. ### Cross-compiling rustc @@ -235,8 +235,8 @@ place, skipping the `cargo` invocation. For instance, you might want to build an ARM version of rustc using an x86 machine. Building `stage2` `std` is different when you are cross-compiling. -This is because `./x` uses the following logic: if `HOST` and `TARGET` are the -same, it will reuse `stage1` `std` for `stage2`! +This is because `./x` uses the following logic: if `HOST` and `TARGET` are the same, +it will reuse `stage1` `std` for `stage2`! This is sound because `stage1` `std` was compiled with the `stage1` compiler, i.e. a compiler using the source code you currently have checked out. @@ -250,23 +250,23 @@ So, the `stage2` compiler has to recompile `std` for the target. ### What is a 'sysroot'? -When you build a project with `cargo`, the build artifacts for dependencies are -normally stored in `target/debug/deps`. -This only contains dependencies `cargo` -knows about; in particular, it doesn't have the standard library. +When you build a project with `cargo`, +the build artifacts for dependencies are normally stored in `target/debug/deps`. +This only contains dependencies `cargo` knows about; in particular, +it doesn't have the standard library. Where do `std` or `proc_macro` come from? -They come from the **sysroot**, the root of a number -of directories where the compiler loads build artifacts at runtime. -The `sysroot` doesn't just store the standard library, though - it includes anything -that needs to be loaded at runtime. +They come from the **sysroot**, +the root of a number of directories where the compiler loads build artifacts at runtime. +The `sysroot` doesn't just store the standard library, +though - it includes anything that needs to be loaded at runtime. That includes (but is not limited to): - Libraries `libstd`/`libtest`/`libproc_macro`. - Compiler crates themselves, when using `rustc_private`. In-tree, these are always present; out-of-tree, you need to install `rustc-dev` with `rustup`. - Shared object file `libLLVM.so` for the LLVM project. - In-tree, this is either built from source or downloaded from CI; out-of-tree, you need to install - `llvm-tools-preview` with `rustup`. + In-tree, this is either built from source or downloaded from CI; out-of-tree, + you need to install `llvm-tools-preview` with `rustup`. All the artifacts listed so far are *compiler* runtime dependencies. You can see them with `rustc --print sysroot`: @@ -293,16 +293,16 @@ libcompiler_builtins-ef2408da76957905.rlib Directory `lib/rustlib/` includes libraries like `hashbrown` and `cfg_if`, which are not part of the public API of the standard library, but are used to implement it. -Also,`lib/rustlib/` is part of the search path for linkers, but -`lib` will never be part of the search path. +Also,`lib/rustlib/` is part of the search path for linkers, +but `lib` will never be part of the search path. #### `-Z force-unstable-if-unmarked` Since `lib/rustlib/` is part of the search path we have to be careful about which crates are included in it. In particular, all crates except for the -standard library are built with the flag `-Z force-unstable-if-unmarked`, which -means that you have to use `#![feature(rustc_private)]` in order to load it (as +standard library are built with the flag `-Z force-unstable-if-unmarked`, +which means that you have to use `#![feature(rustc_private)]` in order to load it (as opposed to the standard library, which is always available). The `-Z force-unstable-if-unmarked` flag has a variety of purposes to help @@ -323,12 +323,12 @@ This flag has the following effects: - Marks the crate as "`unstable`" with the `rustc_private` feature if it is not itself marked as `stable` or `unstable`. - Allows these crates to access other forced-unstable crates without any need for attributes. - Normally, a crate would need a `#![feature(rustc_private)]` - attribute to use other `unstable` crates. - However, that would make it - impossible for a crate from crates.io to access its own dependencies since - that crate won't have a `feature(rustc_private)` attribute, but *everything* - is compiled with `-Z force-unstable-if-unmarked`. + Normally, + a crate would need a `#![feature(rustc_private)]` attribute to use other `unstable` crates. + However, + that would make it impossible for a crate from crates.io to access its own dependencies since + that crate won't have a `feature(rustc_private)` attribute, + but *everything* is compiled with `-Z force-unstable-if-unmarked`. Code which does not use `-Z force-unstable-if-unmarked` should include the `#![feature(rustc_private)]` crate attribute to access these forced-unstable crates. @@ -348,10 +348,10 @@ You can find more discussion about sysroots in: Conveniently `./x` allows you to pass stage-specific flags to `rustc` and `cargo` when bootstrapping. The `RUSTFLAGS_BOOTSTRAP` environment variable is -passed as `RUSTFLAGS` to the bootstrap stage (`stage0`), and -`RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages. -`RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, so it -will be rare to want to use it. +passed as `RUSTFLAGS` to the bootstrap stage (`stage0`), +and `RUSTFLAGS_NOT_BOOTSTRAP` is passed when building artifacts for later stages. +`RUSTFLAGS` will work, but also affects the build of `bootstrap` itself, +so it will be rare to want to use it. Finally, `MAGIC_EXTRA_RUSTFLAGS` bypasses the `cargo` cache to pass flags to rustc without recompiling all dependencies. @@ -370,19 +370,19 @@ which you can use to find out the options accepted by the runner. ## Environment Variables During bootstrapping, there are a bunch of compiler-internal environment variables that are used. -If you are trying to run an intermediate version of -`rustc`, sometimes you may need to set some of these environment variables manually. +If you are trying to run an intermediate version of `rustc`, +sometimes you may need to set some of these environment variables manually. Otherwise, you get an error like the following: ```text thread 'main' panicked at 'RUSTC_STAGE was not set: NotPresent', library/core/src/result.rs:1165:5 ``` -If `./stageN/bin/rustc` gives an error about environment variables, that usually -means something is quite wrong -- such as you're trying to compile `rustc` or +If `./stageN/bin/rustc` gives an error about environment variables, +that usually means something is quite wrong -- such as you're trying to compile `rustc` or `std` or something which depends on environment variables. -In the unlikely case that you actually need to invoke `rustc` in such a situation, you can tell the -bootstrap shim to print all `env` variables by adding `-vvv` to your `x` command. +In the unlikely case that you actually need to invoke `rustc` in such a situation, +you can tell the bootstrap shim to print all `env` variables by adding `-vvv` to your `x` command. Finally, bootstrap makes use of the [cc-rs crate] which has [its own method][env-vars] of configuring `C` compilers and `C` flags via environment variables. @@ -392,8 +392,8 @@ method][env-vars] of configuring `C` compilers and `C` flags via environment var ## Clarification of build command's `stdout` -In this part, we will investigate the build command's `stdout` in an action -(similar, but more detailed and complete documentation compare to topic above). +In this part, we will investigate the build command's `stdout` in an action (similar, +but more detailed and complete documentation compare to topic above). When you execute `x build --dry-run` command, the build output will be something like the following: ```text @@ -410,8 +410,8 @@ Building rustdoc for stage1 (x86_64-unknown-linux-gnu) ### Building stage0 {std,compiler} artifacts -These steps use the provided (downloaded, usually) compiler to compile the local -Rust source into libraries we can use. +These steps use the provided (downloaded, +usually) compiler to compile the local Rust source into libraries we can use. ### Copying stage0 \{std,rustc\} From e7b3b140d9aad21a4c7a3de20648e6492a3e5447 Mon Sep 17 00:00:00 2001 From: Yukang Date: Tue, 22 Sep 2026 00:00:27 +0800 Subject: [PATCH 0569/1309] Add regression test for mutable closure argument suggestions --- tests/ui/suggestions/as-mut-closure.rs | 33 ++++++ tests/ui/suggestions/as-mut-closure.stderr | 111 +++++++++++++++++++++ 2 files changed, 144 insertions(+) create mode 100644 tests/ui/suggestions/as-mut-closure.rs create mode 100644 tests/ui/suggestions/as-mut-closure.stderr diff --git a/tests/ui/suggestions/as-mut-closure.rs b/tests/ui/suggestions/as-mut-closure.rs new file mode 100644 index 0000000000000..ab1c8bff5bf77 --- /dev/null +++ b/tests/ui/suggestions/as-mut-closure.rs @@ -0,0 +1,33 @@ +// Borrowing a container for a closure argument must preserve the expected mutability. + +#![allow(unused_mut)] + +fn append(value: &mut String) { + value.push('!'); +} + +fn increment(value: &mut i32) { + *value += 1; +} + +fn main() { + let mut option = Some(String::new()); + let _ = option.map(|arg| append(arg)); + //~^ ERROR mismatched types + let _ = (&mut option).and_then(|arg| Some(append(arg))); + //~^ ERROR mismatched types + + let mut result: Result<_, ()> = Ok(String::new()); + let _ = result.map(|arg| append(arg)); + //~^ ERROR mismatched types + let _ = (&mut result).and_then(|arg| Ok(append(arg))); + //~^ ERROR mismatched types + + // A shared reference cannot supply `as_mut()`. Borrow the copied argument instead. + let shared = &Some(0); + let _ = shared.map(|mut arg| increment(arg)); + //~^ ERROR mismatched types + let nested = &mut &Some(0); + let _ = nested.map(|mut arg| increment(arg)); + //~^ ERROR mismatched types +} diff --git a/tests/ui/suggestions/as-mut-closure.stderr b/tests/ui/suggestions/as-mut-closure.stderr new file mode 100644 index 0000000000000..c133641b6a5a7 --- /dev/null +++ b/tests/ui/suggestions/as-mut-closure.stderr @@ -0,0 +1,111 @@ +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:15:37 + | +LL | let _ = option.map(|arg| append(arg)); + | ------ ^^^ expected `&mut String`, found `String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:5:4 + | +LL | fn append(value: &mut String) { + | ^^^^^^ ------------------ +help: consider using `as_ref` instead + | +LL | let _ = option.as_ref().map(|arg| append(arg)); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:17:54 + | +LL | let _ = (&mut option).and_then(|arg| Some(append(arg))); + | ------ ^^^ expected `&mut String`, found `String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:5:4 + | +LL | fn append(value: &mut String) { + | ^^^^^^ ------------------ +help: consider using `as_ref` instead + | +LL | let _ = (&mut option).as_ref().and_then(|arg| Some(append(arg))); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:21:37 + | +LL | let _ = result.map(|arg| append(arg)); + | ------ ^^^ expected `&mut String`, found `String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:5:4 + | +LL | fn append(value: &mut String) { + | ^^^^^^ ------------------ +help: consider using `as_ref` instead + | +LL | let _ = result.as_ref().map(|arg| append(arg)); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:23:52 + | +LL | let _ = (&mut result).and_then(|arg| Ok(append(arg))); + | ------ ^^^ expected `&mut String`, found `String` + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:5:4 + | +LL | fn append(value: &mut String) { + | ^^^^^^ ------------------ +help: consider using `as_ref` instead + | +LL | let _ = (&mut result).as_ref().and_then(|arg| Ok(append(arg))); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:28:44 + | +LL | let _ = shared.map(|mut arg| increment(arg)); + | --------- ^^^ expected `&mut i32`, found integer + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:9:4 + | +LL | fn increment(value: &mut i32) { + | ^^^^^^^^^ --------------- +help: consider using `as_ref` instead + | +LL | let _ = shared.as_ref().map(|mut arg| increment(arg)); + | +++++++++ + +error[E0308]: mismatched types + --> $DIR/as-mut-closure.rs:31:44 + | +LL | let _ = nested.map(|mut arg| increment(arg)); + | --------- ^^^ expected `&mut i32`, found integer + | | + | arguments to this function are incorrect + | +note: function defined here + --> $DIR/as-mut-closure.rs:9:4 + | +LL | fn increment(value: &mut i32) { + | ^^^^^^^^^ --------------- +help: consider using `as_ref` instead + | +LL | let _ = nested.as_ref().map(|mut arg| increment(arg)); + | +++++++++ + +error: aborting due to 6 previous errors + +For more information about this error, try `rustc --explain E0308`. From e4ad05bf7b23203f954bcf6ab5d67c6051c13a11 Mon Sep 17 00:00:00 2001 From: ltdk Date: Mon, 21 Sep 2026 09:09:52 -0400 Subject: [PATCH 0570/1309] Mark std::os::wasip2 with correct doc-cfgs, mark as unstable --- library/std/src/os/wasip2/mod.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/library/std/src/os/wasip2/mod.rs b/library/std/src/os/wasip2/mod.rs index 809a288f20d04..6932bb577cff2 100644 --- a/library/std/src/os/wasip2/mod.rs +++ b/library/std/src/os/wasip2/mod.rs @@ -3,4 +3,5 @@ //! This module is currently empty, but will be filled over time as wasi-libc support for WASI Preview 2 is stabilized. #![forbid(unsafe_op_in_unsafe_fn)] -#![stable(feature = "raw_ext", since = "1.1.0")] +#![unstable(feature = "wasip2", issue = "none")] +#![doc(cfg(all(target_os = "wasi", target_env = "p2")))] From c6ac020b2c9cad1e72e0b53f0ab85eeb0f93a910 Mon Sep 17 00:00:00 2001 From: Tshepang Mbambo Date: Mon, 21 Sep 2026 18:10:37 +0200 Subject: [PATCH 0571/1309] improve building/bootstrapping/what-bootstrapping-does.md --- .../bootstrapping/what-bootstrapping-does.md | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md index 15ad385c17811..4572d001f12d3 100644 --- a/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md +++ b/src/doc/rustc-dev-guide/src/building/bootstrapping/what-bootstrapping-does.md @@ -78,7 +78,7 @@ and hence not by the source in your working directory. This means that the ABI generated by the `stage0` compiler may not match the ABI that would have been made by the `stage1` compiler, which can cause problems for dynamic libraries, -tests and tools using `rustc_private`. +tests, and tools using `rustc_private`. Note that the `proc_macro` crate avoids this issue with a `C` FFI layer called `proc_macro::bridge`, allowing it to be used with `stage1`. @@ -122,7 +122,7 @@ For more information about stages, [see below](#understanding-stages-of-bootstra Since the build system uses the current beta compiler to build a `stage1` bootstrapping compiler, the compiler source code can't use some features until they reach beta (because otherwise the beta compiler doesn't support them). -On the other hand, for [compiler intrinsics][intrinsics] and internal features, +On the other hand, for [compiler intrinsics] and internal features, the features _have_ to be used. Additionally, the compiler makes heavy use of `nightly` features (`#![feature(...)]`). How can we resolve this problem? @@ -140,7 +140,7 @@ There are two methods used: _Setting `RUSTC_BOOTSTRAP=1` should never be used except when bootstrapping the compiler._ [boot]: https://en.wikipedia.org/wiki/Bootstrapping_(compilers) -[intrinsics]: ../../appendix/glossary.md#intrinsic +[compiler intrinsics]: ../../appendix/glossary.md#intrinsic ## Understanding stages of bootstrap @@ -257,8 +257,8 @@ it doesn't have the standard library. Where do `std` or `proc_macro` come from? They come from the **sysroot**, the root of a number of directories where the compiler loads build artifacts at runtime. -The `sysroot` doesn't just store the standard library, -though - it includes anything that needs to be loaded at runtime. +The `sysroot` doesn't just store the standard library though; +it includes anything that needs to be loaded at runtime. That includes (but is not limited to): - Libraries `libstd`/`libtest`/`libproc_macro`. @@ -393,7 +393,7 @@ method][env-vars] of configuring `C` compilers and `C` flags via environment var ## Clarification of build command's `stdout` In this part, we will investigate the build command's `stdout` in an action (similar, -but more detailed and complete documentation compare to topic above). +but more detailed and complete documentation compared to topic above). When you execute `x build --dry-run` command, the build output will be something like the following: ```text From d3305f1a4b6fa80b734dfb25971ed483743c9b05 Mon Sep 17 00:00:00 2001 From: Amanieu d'Antras Date: Mon, 21 Sep 2026 17:03:36 +0100 Subject: [PATCH 0572/1309] Borrow the destination place with a raw pointer in MIR inlining --- compiler/rustc_mir_transform/src/inline.rs | 23 +++------ tests/mir-opt/inline/indirect_destination.rs | 53 +++++++++++++++++++- 2 files changed, 58 insertions(+), 18 deletions(-) diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs index c70b957da130e..3fd414579e6bb 100644 --- a/compiler/rustc_mir_transform/src/inline.rs +++ b/compiler/rustc_mir_transform/src/inline.rs @@ -886,24 +886,13 @@ fn inline_call<'tcx, I: Inliner<'tcx>>( // Place could result in two different locations if `f` // writes to `i`. To prevent this we need to create a temporary // borrow of the place and pass the destination as `*temp` instead. - fn dest_needs_borrow(place: Place<'_>) -> bool { - for elem in place.projection.iter() { - match elem { - ProjectionElem::Deref | ProjectionElem::Index(_) => return true, - _ => {} - } - } - - false - } - - let dest = if dest_needs_borrow(destination) { + // + // This must be a raw pointer: a mutable reference could be invalidated by + // reading the arguments later, and would be invalid if the destination type + // is uninhabited. + let dest = if !destination.is_stable_offset() { trace!("creating temp for return destination"); - let dest = Rvalue::Ref( - tcx.lifetimes.re_erased, - BorrowKind::Mut { kind: MutBorrowKind::Default }, - destination, - ); + let dest = Rvalue::RawPtr(RawPtrKind::Mut, destination); let dest_ty = dest.ty(caller_body, tcx); let temp = Place::from(new_call_temp(caller_body, callsite, dest_ty, return_block)); caller_body[callsite.block].statements.push(Statement::new( diff --git a/tests/mir-opt/inline/indirect_destination.rs b/tests/mir-opt/inline/indirect_destination.rs index 4246eef08f704..08e34419bdf7a 100644 --- a/tests/mir-opt/inline/indirect_destination.rs +++ b/tests/mir-opt/inline/indirect_destination.rs @@ -11,7 +11,7 @@ use core::intrinsics::mir::*; // CHECK-LABEL: fn f( // CHECK: bb1: { // CHECK-NEXT: StorageLive([[A:.*]]); -// CHECK-NEXT: [[A]] = &mut (*_1); +// CHECK-NEXT: [[A]] = &raw mut (*_1); // CHECK-NEXT: StorageLive([[B:.*]]); // CHECK-NEXT: [[B]] = const 42_u8; // CHECK-NEXT: (*[[A]]) = move [[B]]; @@ -40,3 +40,54 @@ fn g() -> u8 { } } } + +// Reading the argument must not invalidate the saved destination pointer. +#[custom_mir(dialect = "runtime", phase = "initial")] +// CHECK-LABEL: fn indexed( +// CHECK: [[DEST:_[0-9]+]] = &raw mut _2[_1]; +// CHECK: [[ARG:_[0-9]+]] = copy _2[_1]; +// CHECK-NEXT: [[RET:_[0-9]+]] = copy [[ARG]]; +// CHECK-NEXT: (*[[DEST]]) = move [[RET]]; +pub fn indexed(index: usize) -> u32 { + mir! { + let values: [u32; 2]; + { + values = [41, 99]; + Call(values[index] = identity(values[index]), ReturnTo(done), UnwindContinue()) + } + done = { + RET = values[index]; + Return() + } + } +} + +#[inline(always)] +fn identity(value: u32) -> u32 { + value +} + +// Saving an uninhabited destination must not construct an invalid reference. +#[custom_mir(dialect = "runtime", phase = "initial")] +// CHECK-LABEL: fn uninhabited( +// CHECK: [[PTR:_[0-9]+]] = &raw mut _1; +// CHECK: [[DEST:_[0-9]+]] = &raw mut (*[[PTR]]); +// CHECK: panic_fmt +pub fn uninhabited() { + mir! { + let slot: !; + let ptr: *mut !; + { + ptr = &raw mut slot; + Call(*ptr = fail(), ReturnTo(done), UnwindContinue()) + } + done = { + Return() + } + } +} + +#[inline(always)] +fn fail() -> ! { + panic!("expected panic") +} From 22e16a4eae94e692334c601247a9f696b002a768 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Sat, 5 Sep 2026 12:14:36 +0200 Subject: [PATCH 0573/1309] powerpc64-ibm-aix: fix cfg(target_abi) value --- compiler/rustc_target/src/asm/powerpc.rs | 4 + compiler/rustc_target/src/spec/base/aix.rs | 7 +- tests/ui/asm/powerpc/bad-reg.aix64.stderr | 500 ++++++++++++++---- tests/ui/asm/powerpc/bad-reg.powerpc.stderr | 224 ++++---- tests/ui/asm/powerpc/bad-reg.powerpc64.stderr | 224 ++++---- .../ui/asm/powerpc/bad-reg.powerpc64le.stderr | 210 ++++---- .../ui/asm/powerpc/bad-reg.powerpcspe.stderr | 222 ++++---- tests/ui/asm/powerpc/bad-reg.rs | 52 +- tests/ui/check-cfg/well-known-values.stderr | 2 +- 9 files changed, 895 insertions(+), 550 deletions(-) diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index ab85fade8a8eb..36a8657c5d4e1 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -107,6 +107,10 @@ fn reserved_v20to31( _is_clobber: bool, ) -> Result<(), &'static str> { if target.is_like_aix { + // FIXME: using `cfg_abi` here is wrong -- that's not a source of truth, it's just + // what we display to the user. Instead we need to check the knob that controls + // whether the ABI is actually used. Currently there is no such knob, a Rust target + // can therefore never actually use `vec-extabi`. match &target.options.cfg_abi { CfgAbi::VecDefault => Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI"), CfgAbi::VecExtAbi => Ok(()), diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs index 41cf3e001fdfc..5d172cc8b0fcf 100644 --- a/compiler/rustc_target/src/spec/base/aix.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs @@ -7,7 +7,12 @@ use crate::spec::{ pub(crate) fn opts() -> TargetOptions { TargetOptions { - cfg_abi: CfgAbi::VecExtAbi, + // It makes no sense to set "vec-extabi" here without also actually configuring LLVM to use + // that ABI. This needs a new target spec knob to control the relevant LLVM flag. If you are + // adding such a knob, make sure to also: + // - adjust the logic in `asm/powerpc.rs` to check that knob instead of checking `cfg_abi`. + // - adjust the logic in `spec/consistency.rs` to correlate that knob with `cfg_abi`. + cfg_abi: CfgAbi::VecDefault, code_model: Some(CodeModel::Large), cpu: "pwr7".into(), os: Os::Aix, diff --git a/tests/ui/asm/powerpc/bad-reg.aix64.stderr b/tests/ui/asm/powerpc/bad-reg.aix64.stderr index 7631f8a4c9b6d..9017f8c01e806 100644 --- a/tests/ui/asm/powerpc/bad-reg.aix64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.aix64.stderr @@ -29,103 +29,103 @@ LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:131:18 + --> $DIR/bad-reg.rs:155:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:134:18 + --> $DIR/bad-reg.rs:158:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:137:26 + --> $DIR/bad-reg.rs:161:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:140:26 + --> $DIR/bad-reg.rs:164:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:144:18 + --> $DIR/bad-reg.rs:168:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:147:18 + --> $DIR/bad-reg.rs:171:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:150:26 + --> $DIR/bad-reg.rs:174:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:153:26 + --> $DIR/bad-reg.rs:177:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:157:18 + --> $DIR/bad-reg.rs:181:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:160:18 + --> $DIR/bad-reg.rs:184:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:163:26 + --> $DIR/bad-reg.rs:187:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:166:26 + --> $DIR/bad-reg.rs:190:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:170:18 + --> $DIR/bad-reg.rs:194:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:173:18 + --> $DIR/bad-reg.rs:197:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:176:26 + --> $DIR/bad-reg.rs:200:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:179:26 + --> $DIR/bad-reg.rs:203:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:183:31 + --> $DIR/bad-reg.rs:207:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:185:31 + --> $DIR/bad-reg.rs:209:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:187:31 + --> $DIR/bad-reg.rs:211:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:189:31 + --> $DIR/bad-reg.rs:213:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:215:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:217:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:219:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:221:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:200:31 + --> $DIR/bad-reg.rs:224:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:202:31 + --> $DIR/bad-reg.rs:226:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:204:31 + --> $DIR/bad-reg.rs:228:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:206:31 + --> $DIR/bad-reg.rs:230:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:232:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:234:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:236:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:238:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:240:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:242:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:220:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:222:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:224:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:226:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:264:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:266:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:268:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:270:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:272:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:274:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:276:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:278:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:280:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:282:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:284:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:286:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:264:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:266:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:268:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:270:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:328:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:332:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:336:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:340:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:344:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:348:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:352:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:356:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:360:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:364:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:368:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:372:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,7 +701,7 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:332:26 + --> $DIR/bad-reg.rs:380:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ @@ -736,8 +736,80 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai | = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f16, f32, f64, f128, i64x2, f16x8, f64x2 +error: cannot use register `v20`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:75:18 + | +LL | asm!("", out("v20") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v21`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:77:18 + | +LL | asm!("", out("v21") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v22`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:79:18 + | +LL | asm!("", out("v22") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v23`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:81:18 + | +LL | asm!("", out("v23") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v24`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:83:18 + | +LL | asm!("", out("v24") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v25`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:85:18 + | +LL | asm!("", out("v25") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v26`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:87:18 + | +LL | asm!("", out("v26") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v27`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:89:18 + | +LL | asm!("", out("v27") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v28`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:91:18 + | +LL | asm!("", out("v28") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v29`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:93:18 + | +LL | asm!("", out("v29") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v30`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:95:18 + | +LL | asm!("", out("v30") _); + | ^^^^^^^^^^^^ + +error: cannot use register `v31`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:97:18 + | +LL | asm!("", out("v31") _); + | ^^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:28 + --> $DIR/bad-reg.rs:110:28 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -745,7 +817,7 @@ LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:29 + --> $DIR/bad-reg.rs:113:29 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -753,15 +825,87 @@ LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:108:36 + --> $DIR/bad-reg.rs:120:36 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^ | = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 +error: cannot use register `vs52`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:127:18 + | +LL | asm!("", out("vs52") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs53`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:129:18 + | +LL | asm!("", out("vs53") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs54`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:131:18 + | +LL | asm!("", out("vs54") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs55`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:133:18 + | +LL | asm!("", out("vs55") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs56`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:135:18 + | +LL | asm!("", out("vs56") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs57`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:137:18 + | +LL | asm!("", out("vs57") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs58`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:139:18 + | +LL | asm!("", out("vs58") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs59`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:141:18 + | +LL | asm!("", out("vs59") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs60`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:143:18 + | +LL | asm!("", out("vs60") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs61`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:145:18 + | +LL | asm!("", out("vs61") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs62`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:147:18 + | +LL | asm!("", out("vs62") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `vs63`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:149:18 + | +LL | asm!("", out("vs63") _); + | ^^^^^^^^^^^^^ + error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:131:27 + --> $DIR/bad-reg.rs:155:27 | LL | asm!("", in("cr") x); | ^ @@ -769,7 +913,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:134:28 + --> $DIR/bad-reg.rs:158:28 | LL | asm!("", out("cr") x); | ^ @@ -777,7 +921,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:137:33 + --> $DIR/bad-reg.rs:161:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -785,7 +929,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:144:28 + --> $DIR/bad-reg.rs:168:28 | LL | asm!("", in("ctr") x); | ^ @@ -793,7 +937,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:147:29 + --> $DIR/bad-reg.rs:171:29 | LL | asm!("", out("ctr") x); | ^ @@ -801,7 +945,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:150:34 + --> $DIR/bad-reg.rs:174:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -809,7 +953,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:157:27 + --> $DIR/bad-reg.rs:181:27 | LL | asm!("", in("lr") x); | ^ @@ -817,7 +961,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:160:28 + --> $DIR/bad-reg.rs:184:28 | LL | asm!("", out("lr") x); | ^ @@ -825,7 +969,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:163:33 + --> $DIR/bad-reg.rs:187:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -833,7 +977,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:170:28 + --> $DIR/bad-reg.rs:194:28 | LL | asm!("", in("xer") x); | ^ @@ -841,7 +985,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:173:29 + --> $DIR/bad-reg.rs:197:29 | LL | asm!("", out("xer") x); | ^ @@ -849,18 +993,162 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:176:34 + --> $DIR/bad-reg.rs:200:34 | LL | asm!("/* {} */", in(xer) x); | ^ | = note: register class `xer` supports these types: +error: cannot use register `vs52`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:328:18 + | +LL | asm!("", out("vs52") _, out("v20") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v20`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:328:33 + | +LL | asm!("", out("vs52") _, out("v20") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs53`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:332:18 + | +LL | asm!("", out("vs53") _, out("v21") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v21`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:332:33 + | +LL | asm!("", out("vs53") _, out("v21") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs54`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:336:18 + | +LL | asm!("", out("vs54") _, out("v22") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v22`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:336:33 + | +LL | asm!("", out("vs54") _, out("v22") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs55`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:340:18 + | +LL | asm!("", out("vs55") _, out("v23") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v23`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:340:33 + | +LL | asm!("", out("vs55") _, out("v23") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs56`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:344:18 + | +LL | asm!("", out("vs56") _, out("v24") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v24`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:344:33 + | +LL | asm!("", out("vs56") _, out("v24") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs57`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:348:18 + | +LL | asm!("", out("vs57") _, out("v25") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v25`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:348:33 + | +LL | asm!("", out("vs57") _, out("v25") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs58`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:352:18 + | +LL | asm!("", out("vs58") _, out("v26") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v26`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:352:33 + | +LL | asm!("", out("vs58") _, out("v26") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs59`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:356:18 + | +LL | asm!("", out("vs59") _, out("v27") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v27`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:356:33 + | +LL | asm!("", out("vs59") _, out("v27") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs60`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:360:18 + | +LL | asm!("", out("vs60") _, out("v28") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v28`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:360:33 + | +LL | asm!("", out("vs60") _, out("v28") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs61`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:364:18 + | +LL | asm!("", out("vs61") _, out("v29") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v29`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:364:33 + | +LL | asm!("", out("vs61") _, out("v29") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs62`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:368:18 + | +LL | asm!("", out("vs62") _, out("v30") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v30`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:368:33 + | +LL | asm!("", out("vs62") _, out("v30") _); + | ^^^^^^^^^^^^ + +error: cannot use register `vs63`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:372:18 + | +LL | asm!("", out("vs63") _, out("v31") _); + | ^^^^^^^^^^^^^ + +error: cannot use register `v31`: v20-v31 (vs52-vs63) are reserved on vec-default ABI + --> $DIR/bad-reg.rs:372:33 + | +LL | asm!("", out("vs63") _, out("v31") _); + | ^^^^^^^^^^^^ + error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:330:18 + --> $DIR/bad-reg.rs:378:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ -error: aborting due to 114 previous errors +error: aborting due to 162 previous errors diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr index 88a8cecf40550..1c81299a968fa 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc.stderr @@ -29,103 +29,103 @@ LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:131:18 + --> $DIR/bad-reg.rs:155:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:134:18 + --> $DIR/bad-reg.rs:158:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:137:26 + --> $DIR/bad-reg.rs:161:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:140:26 + --> $DIR/bad-reg.rs:164:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:144:18 + --> $DIR/bad-reg.rs:168:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:147:18 + --> $DIR/bad-reg.rs:171:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:150:26 + --> $DIR/bad-reg.rs:174:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:153:26 + --> $DIR/bad-reg.rs:177:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:157:18 + --> $DIR/bad-reg.rs:181:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:160:18 + --> $DIR/bad-reg.rs:184:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:163:26 + --> $DIR/bad-reg.rs:187:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:166:26 + --> $DIR/bad-reg.rs:190:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:170:18 + --> $DIR/bad-reg.rs:194:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:173:18 + --> $DIR/bad-reg.rs:197:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:176:26 + --> $DIR/bad-reg.rs:200:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:179:26 + --> $DIR/bad-reg.rs:203:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:183:31 + --> $DIR/bad-reg.rs:207:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:185:31 + --> $DIR/bad-reg.rs:209:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:187:31 + --> $DIR/bad-reg.rs:211:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:189:31 + --> $DIR/bad-reg.rs:213:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:215:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:217:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:219:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:221:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:200:31 + --> $DIR/bad-reg.rs:224:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:202:31 + --> $DIR/bad-reg.rs:226:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:204:31 + --> $DIR/bad-reg.rs:228:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:206:31 + --> $DIR/bad-reg.rs:230:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:232:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:234:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:236:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:238:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:240:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:242:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:220:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:222:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:224:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:226:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:264:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:266:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:268:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:270:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:272:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:274:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:276:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:278:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:280:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:282:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:284:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:286:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:264:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:266:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:268:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:270:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:328:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:332:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:336:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:340:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:344:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:348:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:352:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:356:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:360:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:364:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:368:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:372:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,7 +701,7 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:332:26 + --> $DIR/bad-reg.rs:380:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ @@ -779,67 +779,67 @@ LL | asm!("/* {} */", out(vreg) _); // requires altivec | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:90:18 + --> $DIR/bad-reg.rs:102:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:92:18 + --> $DIR/bad-reg.rs:104:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:94:18 + --> $DIR/bad-reg.rs:106:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:96:18 + --> $DIR/bad-reg.rs:108:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:110:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:113:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:116:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:108:26 + --> $DIR/bad-reg.rs:120:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:111:26 + --> $DIR/bad-reg.rs:123:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:131:27 + --> $DIR/bad-reg.rs:155:27 | LL | asm!("", in("cr") x); | ^ @@ -847,7 +847,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:134:28 + --> $DIR/bad-reg.rs:158:28 | LL | asm!("", out("cr") x); | ^ @@ -855,7 +855,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:137:33 + --> $DIR/bad-reg.rs:161:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -863,7 +863,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:144:28 + --> $DIR/bad-reg.rs:168:28 | LL | asm!("", in("ctr") x); | ^ @@ -871,7 +871,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:147:29 + --> $DIR/bad-reg.rs:171:29 | LL | asm!("", out("ctr") x); | ^ @@ -879,7 +879,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:150:34 + --> $DIR/bad-reg.rs:174:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -887,7 +887,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:157:27 + --> $DIR/bad-reg.rs:181:27 | LL | asm!("", in("lr") x); | ^ @@ -895,7 +895,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:160:28 + --> $DIR/bad-reg.rs:184:28 | LL | asm!("", out("lr") x); | ^ @@ -903,7 +903,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:163:33 + --> $DIR/bad-reg.rs:187:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -911,7 +911,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:170:28 + --> $DIR/bad-reg.rs:194:28 | LL | asm!("", in("xer") x); | ^ @@ -919,7 +919,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:173:29 + --> $DIR/bad-reg.rs:197:29 | LL | asm!("", out("xer") x); | ^ @@ -927,7 +927,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:176:34 + --> $DIR/bad-reg.rs:200:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -935,7 +935,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:330:18 + --> $DIR/bad-reg.rs:378:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr index 48306cf45ac94..505bef77f8990 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64.stderr @@ -29,103 +29,103 @@ LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:131:18 + --> $DIR/bad-reg.rs:155:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:134:18 + --> $DIR/bad-reg.rs:158:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:137:26 + --> $DIR/bad-reg.rs:161:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:140:26 + --> $DIR/bad-reg.rs:164:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:144:18 + --> $DIR/bad-reg.rs:168:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:147:18 + --> $DIR/bad-reg.rs:171:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:150:26 + --> $DIR/bad-reg.rs:174:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:153:26 + --> $DIR/bad-reg.rs:177:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:157:18 + --> $DIR/bad-reg.rs:181:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:160:18 + --> $DIR/bad-reg.rs:184:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:163:26 + --> $DIR/bad-reg.rs:187:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:166:26 + --> $DIR/bad-reg.rs:190:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:170:18 + --> $DIR/bad-reg.rs:194:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:173:18 + --> $DIR/bad-reg.rs:197:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:176:26 + --> $DIR/bad-reg.rs:200:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:179:26 + --> $DIR/bad-reg.rs:203:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:183:31 + --> $DIR/bad-reg.rs:207:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:185:31 + --> $DIR/bad-reg.rs:209:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:187:31 + --> $DIR/bad-reg.rs:211:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:189:31 + --> $DIR/bad-reg.rs:213:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:215:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:217:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:219:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:221:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:200:31 + --> $DIR/bad-reg.rs:224:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:202:31 + --> $DIR/bad-reg.rs:226:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:204:31 + --> $DIR/bad-reg.rs:228:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:206:31 + --> $DIR/bad-reg.rs:230:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:232:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:234:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:236:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:238:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:240:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:242:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:220:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:222:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:224:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:226:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:264:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:266:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:268:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:270:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:272:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:274:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:276:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:278:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:280:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:282:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:284:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:286:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:264:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:266:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:268:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:270:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:328:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:332:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:336:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:340:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:344:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:348:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:352:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:356:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:360:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:364:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:368:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:372:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,7 +701,7 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:332:26 + --> $DIR/bad-reg.rs:380:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ @@ -761,67 +761,67 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f16, f32, f64, f128, i64x2, f16x8, f64x2 error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:90:18 + --> $DIR/bad-reg.rs:102:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:92:18 + --> $DIR/bad-reg.rs:104:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:94:18 + --> $DIR/bad-reg.rs:106:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:96:18 + --> $DIR/bad-reg.rs:108:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:110:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:113:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:116:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:108:26 + --> $DIR/bad-reg.rs:120:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:111:26 + --> $DIR/bad-reg.rs:123:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:131:27 + --> $DIR/bad-reg.rs:155:27 | LL | asm!("", in("cr") x); | ^ @@ -829,7 +829,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:134:28 + --> $DIR/bad-reg.rs:158:28 | LL | asm!("", out("cr") x); | ^ @@ -837,7 +837,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:137:33 + --> $DIR/bad-reg.rs:161:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -845,7 +845,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:144:28 + --> $DIR/bad-reg.rs:168:28 | LL | asm!("", in("ctr") x); | ^ @@ -853,7 +853,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:147:29 + --> $DIR/bad-reg.rs:171:29 | LL | asm!("", out("ctr") x); | ^ @@ -861,7 +861,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:150:34 + --> $DIR/bad-reg.rs:174:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -869,7 +869,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:157:27 + --> $DIR/bad-reg.rs:181:27 | LL | asm!("", in("lr") x); | ^ @@ -877,7 +877,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:160:28 + --> $DIR/bad-reg.rs:184:28 | LL | asm!("", out("lr") x); | ^ @@ -885,7 +885,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:163:33 + --> $DIR/bad-reg.rs:187:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -893,7 +893,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:170:28 + --> $DIR/bad-reg.rs:194:28 | LL | asm!("", in("xer") x); | ^ @@ -901,7 +901,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:173:29 + --> $DIR/bad-reg.rs:197:29 | LL | asm!("", out("xer") x); | ^ @@ -909,7 +909,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:176:34 + --> $DIR/bad-reg.rs:200:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -917,7 +917,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:330:18 + --> $DIR/bad-reg.rs:378:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr index 7631f8a4c9b6d..b43a39a6997fb 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpc64le.stderr @@ -29,103 +29,103 @@ LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:131:18 + --> $DIR/bad-reg.rs:155:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:134:18 + --> $DIR/bad-reg.rs:158:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:137:26 + --> $DIR/bad-reg.rs:161:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:140:26 + --> $DIR/bad-reg.rs:164:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:144:18 + --> $DIR/bad-reg.rs:168:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:147:18 + --> $DIR/bad-reg.rs:171:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:150:26 + --> $DIR/bad-reg.rs:174:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:153:26 + --> $DIR/bad-reg.rs:177:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:157:18 + --> $DIR/bad-reg.rs:181:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:160:18 + --> $DIR/bad-reg.rs:184:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:163:26 + --> $DIR/bad-reg.rs:187:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:166:26 + --> $DIR/bad-reg.rs:190:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:170:18 + --> $DIR/bad-reg.rs:194:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:173:18 + --> $DIR/bad-reg.rs:197:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:176:26 + --> $DIR/bad-reg.rs:200:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:179:26 + --> $DIR/bad-reg.rs:203:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:183:31 + --> $DIR/bad-reg.rs:207:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:185:31 + --> $DIR/bad-reg.rs:209:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:187:31 + --> $DIR/bad-reg.rs:211:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:189:31 + --> $DIR/bad-reg.rs:213:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:215:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:217:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:219:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:221:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:200:31 + --> $DIR/bad-reg.rs:224:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:202:31 + --> $DIR/bad-reg.rs:226:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:204:31 + --> $DIR/bad-reg.rs:228:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:206:31 + --> $DIR/bad-reg.rs:230:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:232:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:234:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:236:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:238:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:240:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:242:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:220:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:222:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:224:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:226:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:264:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:266:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:268:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:270:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:272:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:274:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:276:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:278:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:280:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:282:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:284:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:286:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:264:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:266:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:268:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:270:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:328:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:332:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:336:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:340:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:344:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:348:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:352:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:356:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:360:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:364:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:368:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:372:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,7 +701,7 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:332:26 + --> $DIR/bad-reg.rs:380:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ @@ -737,7 +737,7 @@ LL | asm!("/* {} */", in(vreg) x); // FIXME: should be ok if vsx is avai = note: register class `vreg` supports these types: i8x16, i16x8, i32x4, f32x4, f16, f32, f64, f128, i64x2, f16x8, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:98:28 + --> $DIR/bad-reg.rs:110:28 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -745,7 +745,7 @@ LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:101:29 + --> $DIR/bad-reg.rs:113:29 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^ @@ -753,7 +753,7 @@ LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:108:36 + --> $DIR/bad-reg.rs:120:36 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^ @@ -761,7 +761,7 @@ LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is ava = note: register class `vsreg` supports these types: f16, f32, f64, f128, i8x16, i16x8, i32x4, i64x2, f16x8, f32x4, f64x2 error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:131:27 + --> $DIR/bad-reg.rs:155:27 | LL | asm!("", in("cr") x); | ^ @@ -769,7 +769,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:134:28 + --> $DIR/bad-reg.rs:158:28 | LL | asm!("", out("cr") x); | ^ @@ -777,7 +777,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:137:33 + --> $DIR/bad-reg.rs:161:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -785,7 +785,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:144:28 + --> $DIR/bad-reg.rs:168:28 | LL | asm!("", in("ctr") x); | ^ @@ -793,7 +793,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:147:29 + --> $DIR/bad-reg.rs:171:29 | LL | asm!("", out("ctr") x); | ^ @@ -801,7 +801,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:150:34 + --> $DIR/bad-reg.rs:174:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -809,7 +809,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:157:27 + --> $DIR/bad-reg.rs:181:27 | LL | asm!("", in("lr") x); | ^ @@ -817,7 +817,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:160:28 + --> $DIR/bad-reg.rs:184:28 | LL | asm!("", out("lr") x); | ^ @@ -825,7 +825,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:163:33 + --> $DIR/bad-reg.rs:187:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -833,7 +833,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:170:28 + --> $DIR/bad-reg.rs:194:28 | LL | asm!("", in("xer") x); | ^ @@ -841,7 +841,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:173:29 + --> $DIR/bad-reg.rs:197:29 | LL | asm!("", out("xer") x); | ^ @@ -849,7 +849,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:176:34 + --> $DIR/bad-reg.rs:200:34 | LL | asm!("/* {} */", in(xer) x); | ^ @@ -857,7 +857,7 @@ LL | asm!("/* {} */", in(xer) x); = note: register class `xer` supports these types: error: cannot use register `spe_acc`: spe_acc is only available on spe targets - --> $DIR/bad-reg.rs:330:18 + --> $DIR/bad-reg.rs:378:18 | LL | asm!("", out("spe_acc") _); | ^^^^^^^^^^^^^^^^ diff --git a/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr b/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr index 86ea5eed9385d..8670ff6180ce2 100644 --- a/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr +++ b/tests/ui/asm/powerpc/bad-reg.powerpcspe.stderr @@ -29,103 +29,103 @@ LL | asm!("", out("vrsave") _); | ^^^^^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:131:18 + --> $DIR/bad-reg.rs:155:18 | LL | asm!("", in("cr") x); | ^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:134:18 + --> $DIR/bad-reg.rs:158:18 | LL | asm!("", out("cr") x); | ^^^^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:137:26 + --> $DIR/bad-reg.rs:161:26 | LL | asm!("/* {} */", in(cr) x); | ^^^^^^^^ error: register class `cr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:140:26 + --> $DIR/bad-reg.rs:164:26 | LL | asm!("/* {} */", out(cr) _); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:144:18 + --> $DIR/bad-reg.rs:168:18 | LL | asm!("", in("ctr") x); | ^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:147:18 + --> $DIR/bad-reg.rs:171:18 | LL | asm!("", out("ctr") x); | ^^^^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:150:26 + --> $DIR/bad-reg.rs:174:26 | LL | asm!("/* {} */", in(ctr) x); | ^^^^^^^^^ error: register class `ctr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:153:26 + --> $DIR/bad-reg.rs:177:26 | LL | asm!("/* {} */", out(ctr) _); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:157:18 + --> $DIR/bad-reg.rs:181:18 | LL | asm!("", in("lr") x); | ^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:160:18 + --> $DIR/bad-reg.rs:184:18 | LL | asm!("", out("lr") x); | ^^^^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:163:26 + --> $DIR/bad-reg.rs:187:26 | LL | asm!("/* {} */", in(lr) x); | ^^^^^^^^ error: register class `lr` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:166:26 + --> $DIR/bad-reg.rs:190:26 | LL | asm!("/* {} */", out(lr) _); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:170:18 + --> $DIR/bad-reg.rs:194:18 | LL | asm!("", in("xer") x); | ^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:173:18 + --> $DIR/bad-reg.rs:197:18 | LL | asm!("", out("xer") x); | ^^^^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:176:26 + --> $DIR/bad-reg.rs:200:26 | LL | asm!("/* {} */", in(xer) x); | ^^^^^^^^^ error: register class `xer` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:179:26 + --> $DIR/bad-reg.rs:203:26 | LL | asm!("/* {} */", out(xer) _); | ^^^^^^^^^^ error: register `cr0` conflicts with register `cr` - --> $DIR/bad-reg.rs:183:31 + --> $DIR/bad-reg.rs:207:31 | LL | asm!("", out("cr") _, out("cr0") _); | ----------- ^^^^^^^^^^^^ register `cr0` @@ -133,7 +133,7 @@ LL | asm!("", out("cr") _, out("cr0") _); | register `cr` error: register `cr1` conflicts with register `cr` - --> $DIR/bad-reg.rs:185:31 + --> $DIR/bad-reg.rs:209:31 | LL | asm!("", out("cr") _, out("cr1") _); | ----------- ^^^^^^^^^^^^ register `cr1` @@ -141,7 +141,7 @@ LL | asm!("", out("cr") _, out("cr1") _); | register `cr` error: register `cr2` conflicts with register `cr` - --> $DIR/bad-reg.rs:187:31 + --> $DIR/bad-reg.rs:211:31 | LL | asm!("", out("cr") _, out("cr2") _); | ----------- ^^^^^^^^^^^^ register `cr2` @@ -149,7 +149,7 @@ LL | asm!("", out("cr") _, out("cr2") _); | register `cr` error: register `cr3` conflicts with register `cr` - --> $DIR/bad-reg.rs:189:31 + --> $DIR/bad-reg.rs:213:31 | LL | asm!("", out("cr") _, out("cr3") _); | ----------- ^^^^^^^^^^^^ register `cr3` @@ -157,7 +157,7 @@ LL | asm!("", out("cr") _, out("cr3") _); | register `cr` error: register `cr4` conflicts with register `cr` - --> $DIR/bad-reg.rs:191:31 + --> $DIR/bad-reg.rs:215:31 | LL | asm!("", out("cr") _, out("cr4") _); | ----------- ^^^^^^^^^^^^ register `cr4` @@ -165,7 +165,7 @@ LL | asm!("", out("cr") _, out("cr4") _); | register `cr` error: register `cr5` conflicts with register `cr` - --> $DIR/bad-reg.rs:193:31 + --> $DIR/bad-reg.rs:217:31 | LL | asm!("", out("cr") _, out("cr5") _); | ----------- ^^^^^^^^^^^^ register `cr5` @@ -173,7 +173,7 @@ LL | asm!("", out("cr") _, out("cr5") _); | register `cr` error: register `cr6` conflicts with register `cr` - --> $DIR/bad-reg.rs:195:31 + --> $DIR/bad-reg.rs:219:31 | LL | asm!("", out("cr") _, out("cr6") _); | ----------- ^^^^^^^^^^^^ register `cr6` @@ -181,7 +181,7 @@ LL | asm!("", out("cr") _, out("cr6") _); | register `cr` error: register `cr7` conflicts with register `cr` - --> $DIR/bad-reg.rs:197:31 + --> $DIR/bad-reg.rs:221:31 | LL | asm!("", out("cr") _, out("cr7") _); | ----------- ^^^^^^^^^^^^ register `cr7` @@ -189,7 +189,7 @@ LL | asm!("", out("cr") _, out("cr7") _); | register `cr` error: register `vs0` conflicts with register `f0` - --> $DIR/bad-reg.rs:200:31 + --> $DIR/bad-reg.rs:224:31 | LL | asm!("", out("f0") _, out("vs0") _); | ----------- ^^^^^^^^^^^^ register `vs0` @@ -197,7 +197,7 @@ LL | asm!("", out("f0") _, out("vs0") _); | register `f0` error: register `vs1` conflicts with register `f1` - --> $DIR/bad-reg.rs:202:31 + --> $DIR/bad-reg.rs:226:31 | LL | asm!("", out("f1") _, out("vs1") _); | ----------- ^^^^^^^^^^^^ register `vs1` @@ -205,7 +205,7 @@ LL | asm!("", out("f1") _, out("vs1") _); | register `f1` error: register `vs2` conflicts with register `f2` - --> $DIR/bad-reg.rs:204:31 + --> $DIR/bad-reg.rs:228:31 | LL | asm!("", out("f2") _, out("vs2") _); | ----------- ^^^^^^^^^^^^ register `vs2` @@ -213,7 +213,7 @@ LL | asm!("", out("f2") _, out("vs2") _); | register `f2` error: register `vs3` conflicts with register `f3` - --> $DIR/bad-reg.rs:206:31 + --> $DIR/bad-reg.rs:230:31 | LL | asm!("", out("f3") _, out("vs3") _); | ----------- ^^^^^^^^^^^^ register `vs3` @@ -221,7 +221,7 @@ LL | asm!("", out("f3") _, out("vs3") _); | register `f3` error: register `vs4` conflicts with register `f4` - --> $DIR/bad-reg.rs:208:31 + --> $DIR/bad-reg.rs:232:31 | LL | asm!("", out("f4") _, out("vs4") _); | ----------- ^^^^^^^^^^^^ register `vs4` @@ -229,7 +229,7 @@ LL | asm!("", out("f4") _, out("vs4") _); | register `f4` error: register `vs5` conflicts with register `f5` - --> $DIR/bad-reg.rs:210:31 + --> $DIR/bad-reg.rs:234:31 | LL | asm!("", out("f5") _, out("vs5") _); | ----------- ^^^^^^^^^^^^ register `vs5` @@ -237,7 +237,7 @@ LL | asm!("", out("f5") _, out("vs5") _); | register `f5` error: register `vs6` conflicts with register `f6` - --> $DIR/bad-reg.rs:212:31 + --> $DIR/bad-reg.rs:236:31 | LL | asm!("", out("f6") _, out("vs6") _); | ----------- ^^^^^^^^^^^^ register `vs6` @@ -245,7 +245,7 @@ LL | asm!("", out("f6") _, out("vs6") _); | register `f6` error: register `vs7` conflicts with register `f7` - --> $DIR/bad-reg.rs:214:31 + --> $DIR/bad-reg.rs:238:31 | LL | asm!("", out("f7") _, out("vs7") _); | ----------- ^^^^^^^^^^^^ register `vs7` @@ -253,7 +253,7 @@ LL | asm!("", out("f7") _, out("vs7") _); | register `f7` error: register `vs8` conflicts with register `f8` - --> $DIR/bad-reg.rs:216:31 + --> $DIR/bad-reg.rs:240:31 | LL | asm!("", out("f8") _, out("vs8") _); | ----------- ^^^^^^^^^^^^ register `vs8` @@ -261,7 +261,7 @@ LL | asm!("", out("f8") _, out("vs8") _); | register `f8` error: register `vs9` conflicts with register `f9` - --> $DIR/bad-reg.rs:218:31 + --> $DIR/bad-reg.rs:242:31 | LL | asm!("", out("f9") _, out("vs9") _); | ----------- ^^^^^^^^^^^^ register `vs9` @@ -269,7 +269,7 @@ LL | asm!("", out("f9") _, out("vs9") _); | register `f9` error: register `vs10` conflicts with register `f10` - --> $DIR/bad-reg.rs:220:32 + --> $DIR/bad-reg.rs:244:32 | LL | asm!("", out("f10") _, out("vs10") _); | ------------ ^^^^^^^^^^^^^ register `vs10` @@ -277,7 +277,7 @@ LL | asm!("", out("f10") _, out("vs10") _); | register `f10` error: register `vs11` conflicts with register `f11` - --> $DIR/bad-reg.rs:222:32 + --> $DIR/bad-reg.rs:246:32 | LL | asm!("", out("f11") _, out("vs11") _); | ------------ ^^^^^^^^^^^^^ register `vs11` @@ -285,7 +285,7 @@ LL | asm!("", out("f11") _, out("vs11") _); | register `f11` error: register `vs12` conflicts with register `f12` - --> $DIR/bad-reg.rs:224:32 + --> $DIR/bad-reg.rs:248:32 | LL | asm!("", out("f12") _, out("vs12") _); | ------------ ^^^^^^^^^^^^^ register `vs12` @@ -293,7 +293,7 @@ LL | asm!("", out("f12") _, out("vs12") _); | register `f12` error: register `vs13` conflicts with register `f13` - --> $DIR/bad-reg.rs:226:32 + --> $DIR/bad-reg.rs:250:32 | LL | asm!("", out("f13") _, out("vs13") _); | ------------ ^^^^^^^^^^^^^ register `vs13` @@ -301,7 +301,7 @@ LL | asm!("", out("f13") _, out("vs13") _); | register `f13` error: register `vs14` conflicts with register `f14` - --> $DIR/bad-reg.rs:228:32 + --> $DIR/bad-reg.rs:252:32 | LL | asm!("", out("f14") _, out("vs14") _); | ------------ ^^^^^^^^^^^^^ register `vs14` @@ -309,7 +309,7 @@ LL | asm!("", out("f14") _, out("vs14") _); | register `f14` error: register `vs15` conflicts with register `f15` - --> $DIR/bad-reg.rs:230:32 + --> $DIR/bad-reg.rs:254:32 | LL | asm!("", out("f15") _, out("vs15") _); | ------------ ^^^^^^^^^^^^^ register `vs15` @@ -317,7 +317,7 @@ LL | asm!("", out("f15") _, out("vs15") _); | register `f15` error: register `vs16` conflicts with register `f16` - --> $DIR/bad-reg.rs:232:32 + --> $DIR/bad-reg.rs:256:32 | LL | asm!("", out("f16") _, out("vs16") _); | ------------ ^^^^^^^^^^^^^ register `vs16` @@ -325,7 +325,7 @@ LL | asm!("", out("f16") _, out("vs16") _); | register `f16` error: register `vs17` conflicts with register `f17` - --> $DIR/bad-reg.rs:234:32 + --> $DIR/bad-reg.rs:258:32 | LL | asm!("", out("f17") _, out("vs17") _); | ------------ ^^^^^^^^^^^^^ register `vs17` @@ -333,7 +333,7 @@ LL | asm!("", out("f17") _, out("vs17") _); | register `f17` error: register `vs18` conflicts with register `f18` - --> $DIR/bad-reg.rs:236:32 + --> $DIR/bad-reg.rs:260:32 | LL | asm!("", out("f18") _, out("vs18") _); | ------------ ^^^^^^^^^^^^^ register `vs18` @@ -341,7 +341,7 @@ LL | asm!("", out("f18") _, out("vs18") _); | register `f18` error: register `vs19` conflicts with register `f19` - --> $DIR/bad-reg.rs:238:32 + --> $DIR/bad-reg.rs:262:32 | LL | asm!("", out("f19") _, out("vs19") _); | ------------ ^^^^^^^^^^^^^ register `vs19` @@ -349,7 +349,7 @@ LL | asm!("", out("f19") _, out("vs19") _); | register `f19` error: register `vs20` conflicts with register `f20` - --> $DIR/bad-reg.rs:240:32 + --> $DIR/bad-reg.rs:264:32 | LL | asm!("", out("f20") _, out("vs20") _); | ------------ ^^^^^^^^^^^^^ register `vs20` @@ -357,7 +357,7 @@ LL | asm!("", out("f20") _, out("vs20") _); | register `f20` error: register `vs21` conflicts with register `f21` - --> $DIR/bad-reg.rs:242:32 + --> $DIR/bad-reg.rs:266:32 | LL | asm!("", out("f21") _, out("vs21") _); | ------------ ^^^^^^^^^^^^^ register `vs21` @@ -365,7 +365,7 @@ LL | asm!("", out("f21") _, out("vs21") _); | register `f21` error: register `vs22` conflicts with register `f22` - --> $DIR/bad-reg.rs:244:32 + --> $DIR/bad-reg.rs:268:32 | LL | asm!("", out("f22") _, out("vs22") _); | ------------ ^^^^^^^^^^^^^ register `vs22` @@ -373,7 +373,7 @@ LL | asm!("", out("f22") _, out("vs22") _); | register `f22` error: register `vs23` conflicts with register `f23` - --> $DIR/bad-reg.rs:246:32 + --> $DIR/bad-reg.rs:270:32 | LL | asm!("", out("f23") _, out("vs23") _); | ------------ ^^^^^^^^^^^^^ register `vs23` @@ -381,7 +381,7 @@ LL | asm!("", out("f23") _, out("vs23") _); | register `f23` error: register `vs24` conflicts with register `f24` - --> $DIR/bad-reg.rs:248:32 + --> $DIR/bad-reg.rs:272:32 | LL | asm!("", out("f24") _, out("vs24") _); | ------------ ^^^^^^^^^^^^^ register `vs24` @@ -389,7 +389,7 @@ LL | asm!("", out("f24") _, out("vs24") _); | register `f24` error: register `vs25` conflicts with register `f25` - --> $DIR/bad-reg.rs:250:32 + --> $DIR/bad-reg.rs:274:32 | LL | asm!("", out("f25") _, out("vs25") _); | ------------ ^^^^^^^^^^^^^ register `vs25` @@ -397,7 +397,7 @@ LL | asm!("", out("f25") _, out("vs25") _); | register `f25` error: register `vs26` conflicts with register `f26` - --> $DIR/bad-reg.rs:252:32 + --> $DIR/bad-reg.rs:276:32 | LL | asm!("", out("f26") _, out("vs26") _); | ------------ ^^^^^^^^^^^^^ register `vs26` @@ -405,7 +405,7 @@ LL | asm!("", out("f26") _, out("vs26") _); | register `f26` error: register `vs27` conflicts with register `f27` - --> $DIR/bad-reg.rs:254:32 + --> $DIR/bad-reg.rs:278:32 | LL | asm!("", out("f27") _, out("vs27") _); | ------------ ^^^^^^^^^^^^^ register `vs27` @@ -413,7 +413,7 @@ LL | asm!("", out("f27") _, out("vs27") _); | register `f27` error: register `vs28` conflicts with register `f28` - --> $DIR/bad-reg.rs:256:32 + --> $DIR/bad-reg.rs:280:32 | LL | asm!("", out("f28") _, out("vs28") _); | ------------ ^^^^^^^^^^^^^ register `vs28` @@ -421,7 +421,7 @@ LL | asm!("", out("f28") _, out("vs28") _); | register `f28` error: register `vs29` conflicts with register `f29` - --> $DIR/bad-reg.rs:258:32 + --> $DIR/bad-reg.rs:282:32 | LL | asm!("", out("f29") _, out("vs29") _); | ------------ ^^^^^^^^^^^^^ register `vs29` @@ -429,7 +429,7 @@ LL | asm!("", out("f29") _, out("vs29") _); | register `f29` error: register `vs30` conflicts with register `f30` - --> $DIR/bad-reg.rs:260:32 + --> $DIR/bad-reg.rs:284:32 | LL | asm!("", out("f30") _, out("vs30") _); | ------------ ^^^^^^^^^^^^^ register `vs30` @@ -437,7 +437,7 @@ LL | asm!("", out("f30") _, out("vs30") _); | register `f30` error: register `vs31` conflicts with register `f31` - --> $DIR/bad-reg.rs:262:32 + --> $DIR/bad-reg.rs:286:32 | LL | asm!("", out("f31") _, out("vs31") _); | ------------ ^^^^^^^^^^^^^ register `vs31` @@ -445,7 +445,7 @@ LL | asm!("", out("f31") _, out("vs31") _); | register `f31` error: register `v0` conflicts with register `vs32` - --> $DIR/bad-reg.rs:264:33 + --> $DIR/bad-reg.rs:288:33 | LL | asm!("", out("vs32") _, out("v0") _); | ------------- ^^^^^^^^^^^ register `v0` @@ -453,7 +453,7 @@ LL | asm!("", out("vs32") _, out("v0") _); | register `vs32` error: register `v1` conflicts with register `vs33` - --> $DIR/bad-reg.rs:266:33 + --> $DIR/bad-reg.rs:290:33 | LL | asm!("", out("vs33") _, out("v1") _); | ------------- ^^^^^^^^^^^ register `v1` @@ -461,7 +461,7 @@ LL | asm!("", out("vs33") _, out("v1") _); | register `vs33` error: register `v2` conflicts with register `vs34` - --> $DIR/bad-reg.rs:268:33 + --> $DIR/bad-reg.rs:292:33 | LL | asm!("", out("vs34") _, out("v2") _); | ------------- ^^^^^^^^^^^ register `v2` @@ -469,7 +469,7 @@ LL | asm!("", out("vs34") _, out("v2") _); | register `vs34` error: register `v3` conflicts with register `vs35` - --> $DIR/bad-reg.rs:270:33 + --> $DIR/bad-reg.rs:294:33 | LL | asm!("", out("vs35") _, out("v3") _); | ------------- ^^^^^^^^^^^ register `v3` @@ -477,7 +477,7 @@ LL | asm!("", out("vs35") _, out("v3") _); | register `vs35` error: register `v4` conflicts with register `vs36` - --> $DIR/bad-reg.rs:272:33 + --> $DIR/bad-reg.rs:296:33 | LL | asm!("", out("vs36") _, out("v4") _); | ------------- ^^^^^^^^^^^ register `v4` @@ -485,7 +485,7 @@ LL | asm!("", out("vs36") _, out("v4") _); | register `vs36` error: register `v5` conflicts with register `vs37` - --> $DIR/bad-reg.rs:274:33 + --> $DIR/bad-reg.rs:298:33 | LL | asm!("", out("vs37") _, out("v5") _); | ------------- ^^^^^^^^^^^ register `v5` @@ -493,7 +493,7 @@ LL | asm!("", out("vs37") _, out("v5") _); | register `vs37` error: register `v6` conflicts with register `vs38` - --> $DIR/bad-reg.rs:276:33 + --> $DIR/bad-reg.rs:300:33 | LL | asm!("", out("vs38") _, out("v6") _); | ------------- ^^^^^^^^^^^ register `v6` @@ -501,7 +501,7 @@ LL | asm!("", out("vs38") _, out("v6") _); | register `vs38` error: register `v7` conflicts with register `vs39` - --> $DIR/bad-reg.rs:278:33 + --> $DIR/bad-reg.rs:302:33 | LL | asm!("", out("vs39") _, out("v7") _); | ------------- ^^^^^^^^^^^ register `v7` @@ -509,7 +509,7 @@ LL | asm!("", out("vs39") _, out("v7") _); | register `vs39` error: register `v8` conflicts with register `vs40` - --> $DIR/bad-reg.rs:280:33 + --> $DIR/bad-reg.rs:304:33 | LL | asm!("", out("vs40") _, out("v8") _); | ------------- ^^^^^^^^^^^ register `v8` @@ -517,7 +517,7 @@ LL | asm!("", out("vs40") _, out("v8") _); | register `vs40` error: register `v9` conflicts with register `vs41` - --> $DIR/bad-reg.rs:282:33 + --> $DIR/bad-reg.rs:306:33 | LL | asm!("", out("vs41") _, out("v9") _); | ------------- ^^^^^^^^^^^ register `v9` @@ -525,7 +525,7 @@ LL | asm!("", out("vs41") _, out("v9") _); | register `vs41` error: register `v10` conflicts with register `vs42` - --> $DIR/bad-reg.rs:284:33 + --> $DIR/bad-reg.rs:308:33 | LL | asm!("", out("vs42") _, out("v10") _); | ------------- ^^^^^^^^^^^^ register `v10` @@ -533,7 +533,7 @@ LL | asm!("", out("vs42") _, out("v10") _); | register `vs42` error: register `v11` conflicts with register `vs43` - --> $DIR/bad-reg.rs:286:33 + --> $DIR/bad-reg.rs:310:33 | LL | asm!("", out("vs43") _, out("v11") _); | ------------- ^^^^^^^^^^^^ register `v11` @@ -541,7 +541,7 @@ LL | asm!("", out("vs43") _, out("v11") _); | register `vs43` error: register `v12` conflicts with register `vs44` - --> $DIR/bad-reg.rs:288:33 + --> $DIR/bad-reg.rs:312:33 | LL | asm!("", out("vs44") _, out("v12") _); | ------------- ^^^^^^^^^^^^ register `v12` @@ -549,7 +549,7 @@ LL | asm!("", out("vs44") _, out("v12") _); | register `vs44` error: register `v13` conflicts with register `vs45` - --> $DIR/bad-reg.rs:290:33 + --> $DIR/bad-reg.rs:314:33 | LL | asm!("", out("vs45") _, out("v13") _); | ------------- ^^^^^^^^^^^^ register `v13` @@ -557,7 +557,7 @@ LL | asm!("", out("vs45") _, out("v13") _); | register `vs45` error: register `v14` conflicts with register `vs46` - --> $DIR/bad-reg.rs:292:33 + --> $DIR/bad-reg.rs:316:33 | LL | asm!("", out("vs46") _, out("v14") _); | ------------- ^^^^^^^^^^^^ register `v14` @@ -565,7 +565,7 @@ LL | asm!("", out("vs46") _, out("v14") _); | register `vs46` error: register `v15` conflicts with register `vs47` - --> $DIR/bad-reg.rs:294:33 + --> $DIR/bad-reg.rs:318:33 | LL | asm!("", out("vs47") _, out("v15") _); | ------------- ^^^^^^^^^^^^ register `v15` @@ -573,7 +573,7 @@ LL | asm!("", out("vs47") _, out("v15") _); | register `vs47` error: register `v16` conflicts with register `vs48` - --> $DIR/bad-reg.rs:296:33 + --> $DIR/bad-reg.rs:320:33 | LL | asm!("", out("vs48") _, out("v16") _); | ------------- ^^^^^^^^^^^^ register `v16` @@ -581,7 +581,7 @@ LL | asm!("", out("vs48") _, out("v16") _); | register `vs48` error: register `v17` conflicts with register `vs49` - --> $DIR/bad-reg.rs:298:33 + --> $DIR/bad-reg.rs:322:33 | LL | asm!("", out("vs49") _, out("v17") _); | ------------- ^^^^^^^^^^^^ register `v17` @@ -589,7 +589,7 @@ LL | asm!("", out("vs49") _, out("v17") _); | register `vs49` error: register `v18` conflicts with register `vs50` - --> $DIR/bad-reg.rs:300:33 + --> $DIR/bad-reg.rs:324:33 | LL | asm!("", out("vs50") _, out("v18") _); | ------------- ^^^^^^^^^^^^ register `v18` @@ -597,7 +597,7 @@ LL | asm!("", out("vs50") _, out("v18") _); | register `vs50` error: register `v19` conflicts with register `vs51` - --> $DIR/bad-reg.rs:302:33 + --> $DIR/bad-reg.rs:326:33 | LL | asm!("", out("vs51") _, out("v19") _); | ------------- ^^^^^^^^^^^^ register `v19` @@ -605,7 +605,7 @@ LL | asm!("", out("vs51") _, out("v19") _); | register `vs51` error: register `v20` conflicts with register `vs52` - --> $DIR/bad-reg.rs:304:33 + --> $DIR/bad-reg.rs:328:33 | LL | asm!("", out("vs52") _, out("v20") _); | ------------- ^^^^^^^^^^^^ register `v20` @@ -613,7 +613,7 @@ LL | asm!("", out("vs52") _, out("v20") _); | register `vs52` error: register `v21` conflicts with register `vs53` - --> $DIR/bad-reg.rs:306:33 + --> $DIR/bad-reg.rs:332:33 | LL | asm!("", out("vs53") _, out("v21") _); | ------------- ^^^^^^^^^^^^ register `v21` @@ -621,7 +621,7 @@ LL | asm!("", out("vs53") _, out("v21") _); | register `vs53` error: register `v22` conflicts with register `vs54` - --> $DIR/bad-reg.rs:308:33 + --> $DIR/bad-reg.rs:336:33 | LL | asm!("", out("vs54") _, out("v22") _); | ------------- ^^^^^^^^^^^^ register `v22` @@ -629,7 +629,7 @@ LL | asm!("", out("vs54") _, out("v22") _); | register `vs54` error: register `v23` conflicts with register `vs55` - --> $DIR/bad-reg.rs:310:33 + --> $DIR/bad-reg.rs:340:33 | LL | asm!("", out("vs55") _, out("v23") _); | ------------- ^^^^^^^^^^^^ register `v23` @@ -637,7 +637,7 @@ LL | asm!("", out("vs55") _, out("v23") _); | register `vs55` error: register `v24` conflicts with register `vs56` - --> $DIR/bad-reg.rs:312:33 + --> $DIR/bad-reg.rs:344:33 | LL | asm!("", out("vs56") _, out("v24") _); | ------------- ^^^^^^^^^^^^ register `v24` @@ -645,7 +645,7 @@ LL | asm!("", out("vs56") _, out("v24") _); | register `vs56` error: register `v25` conflicts with register `vs57` - --> $DIR/bad-reg.rs:314:33 + --> $DIR/bad-reg.rs:348:33 | LL | asm!("", out("vs57") _, out("v25") _); | ------------- ^^^^^^^^^^^^ register `v25` @@ -653,7 +653,7 @@ LL | asm!("", out("vs57") _, out("v25") _); | register `vs57` error: register `v26` conflicts with register `vs58` - --> $DIR/bad-reg.rs:316:33 + --> $DIR/bad-reg.rs:352:33 | LL | asm!("", out("vs58") _, out("v26") _); | ------------- ^^^^^^^^^^^^ register `v26` @@ -661,7 +661,7 @@ LL | asm!("", out("vs58") _, out("v26") _); | register `vs58` error: register `v27` conflicts with register `vs59` - --> $DIR/bad-reg.rs:318:33 + --> $DIR/bad-reg.rs:356:33 | LL | asm!("", out("vs59") _, out("v27") _); | ------------- ^^^^^^^^^^^^ register `v27` @@ -669,7 +669,7 @@ LL | asm!("", out("vs59") _, out("v27") _); | register `vs59` error: register `v28` conflicts with register `vs60` - --> $DIR/bad-reg.rs:320:33 + --> $DIR/bad-reg.rs:360:33 | LL | asm!("", out("vs60") _, out("v28") _); | ------------- ^^^^^^^^^^^^ register `v28` @@ -677,7 +677,7 @@ LL | asm!("", out("vs60") _, out("v28") _); | register `vs60` error: register `v29` conflicts with register `vs61` - --> $DIR/bad-reg.rs:322:33 + --> $DIR/bad-reg.rs:364:33 | LL | asm!("", out("vs61") _, out("v29") _); | ------------- ^^^^^^^^^^^^ register `v29` @@ -685,7 +685,7 @@ LL | asm!("", out("vs61") _, out("v29") _); | register `vs61` error: register `v30` conflicts with register `vs62` - --> $DIR/bad-reg.rs:324:33 + --> $DIR/bad-reg.rs:368:33 | LL | asm!("", out("vs62") _, out("v30") _); | ------------- ^^^^^^^^^^^^ register `v30` @@ -693,7 +693,7 @@ LL | asm!("", out("vs62") _, out("v30") _); | register `vs62` error: register `v31` conflicts with register `vs63` - --> $DIR/bad-reg.rs:326:33 + --> $DIR/bad-reg.rs:372:33 | LL | asm!("", out("vs63") _, out("v31") _); | ------------- ^^^^^^^^^^^^ register `v31` @@ -701,7 +701,7 @@ LL | asm!("", out("vs63") _, out("v31") _); | register `vs63` error: register class `spe_acc` can only be used as a clobber, not as an input or output - --> $DIR/bad-reg.rs:332:26 + --> $DIR/bad-reg.rs:380:26 | LL | asm!("/* {} */", out(spe_acc) _); | ^^^^^^^^^^^^^^ @@ -779,67 +779,67 @@ LL | asm!("/* {} */", out(vreg) _); // requires altivec | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:90:18 + --> $DIR/bad-reg.rs:102:18 | LL | asm!("", in("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:92:18 + --> $DIR/bad-reg.rs:104:18 | LL | asm!("", out("vs0") v32x4); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:94:18 + --> $DIR/bad-reg.rs:106:18 | LL | asm!("", in("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:96:18 + --> $DIR/bad-reg.rs:108:18 | LL | asm!("", out("vs0") v64x2); // requires vsx | ^^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:98:18 + --> $DIR/bad-reg.rs:110:18 | LL | asm!("", in("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:101:18 + --> $DIR/bad-reg.rs:113:18 | LL | asm!("", out("vs0") x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:104:26 + --> $DIR/bad-reg.rs:116:26 | LL | asm!("/* {} */", in(vsreg) v32x4); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:106:26 + --> $DIR/bad-reg.rs:118:26 | LL | asm!("/* {} */", in(vsreg) v64x2); // requires vsx | ^^^^^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:108:26 + --> $DIR/bad-reg.rs:120:26 | LL | asm!("/* {} */", in(vsreg) x); // FIXME: should be ok if vsx is available | ^^^^^^^^^^^ error: register class `vsreg` requires the `vsx` target feature - --> $DIR/bad-reg.rs:111:26 + --> $DIR/bad-reg.rs:123:26 | LL | asm!("/* {} */", out(vsreg) _); // requires vsx | ^^^^^^^^^^^^ error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:131:27 + --> $DIR/bad-reg.rs:155:27 | LL | asm!("", in("cr") x); | ^ @@ -847,7 +847,7 @@ LL | asm!("", in("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:134:28 + --> $DIR/bad-reg.rs:158:28 | LL | asm!("", out("cr") x); | ^ @@ -855,7 +855,7 @@ LL | asm!("", out("cr") x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:137:33 + --> $DIR/bad-reg.rs:161:33 | LL | asm!("/* {} */", in(cr) x); | ^ @@ -863,7 +863,7 @@ LL | asm!("/* {} */", in(cr) x); = note: register class `cr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:144:28 + --> $DIR/bad-reg.rs:168:28 | LL | asm!("", in("ctr") x); | ^ @@ -871,7 +871,7 @@ LL | asm!("", in("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:147:29 + --> $DIR/bad-reg.rs:171:29 | LL | asm!("", out("ctr") x); | ^ @@ -879,7 +879,7 @@ LL | asm!("", out("ctr") x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:150:34 + --> $DIR/bad-reg.rs:174:34 | LL | asm!("/* {} */", in(ctr) x); | ^ @@ -887,7 +887,7 @@ LL | asm!("/* {} */", in(ctr) x); = note: register class `ctr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:157:27 + --> $DIR/bad-reg.rs:181:27 | LL | asm!("", in("lr") x); | ^ @@ -895,7 +895,7 @@ LL | asm!("", in("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:160:28 + --> $DIR/bad-reg.rs:184:28 | LL | asm!("", out("lr") x); | ^ @@ -903,7 +903,7 @@ LL | asm!("", out("lr") x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:163:33 + --> $DIR/bad-reg.rs:187:33 | LL | asm!("/* {} */", in(lr) x); | ^ @@ -911,7 +911,7 @@ LL | asm!("/* {} */", in(lr) x); = note: register class `lr` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:170:28 + --> $DIR/bad-reg.rs:194:28 | LL | asm!("", in("xer") x); | ^ @@ -919,7 +919,7 @@ LL | asm!("", in("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:173:29 + --> $DIR/bad-reg.rs:197:29 | LL | asm!("", out("xer") x); | ^ @@ -927,7 +927,7 @@ LL | asm!("", out("xer") x); = note: register class `xer` supports these types: error: type `i32` cannot be used with this register class - --> $DIR/bad-reg.rs:176:34 + --> $DIR/bad-reg.rs:200:34 | LL | asm!("/* {} */", in(xer) x); | ^ diff --git a/tests/ui/asm/powerpc/bad-reg.rs b/tests/ui/asm/powerpc/bad-reg.rs index 88c78859e8326..4e45a5b61a8df 100644 --- a/tests/ui/asm/powerpc/bad-reg.rs +++ b/tests/ui/asm/powerpc/bad-reg.rs @@ -71,19 +71,31 @@ fn f() { //[powerpc64,powerpc64le,aix64]~^^ ERROR type `i32` cannot be used with this register class asm!("/* {} */", out(vreg) _); // requires altivec //[powerpc,powerpcspe]~^ ERROR register class `vreg` requires at least one of the following target features: altivec, vsx - // v20-v31 (vs52-vs63) are reserved on AIX with vec-default ABI (this ABI is not currently used in Rust's builtin AIX targets). + // v20-v31 (vs52-vs63) are reserved on AIX with vec-default ABI, the ABI we currently use for our AIX target. asm!("", out("v20") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v21") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v22") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v23") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v24") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v25") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v26") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v27") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v28") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v29") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v30") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("v31") _); + //[aix64]~^ ERROR are reserved on vec-default ABI // vsreg asm!("", out("vs0") _); // always ok @@ -111,19 +123,31 @@ fn f() { asm!("/* {} */", out(vsreg) _); // requires vsx //[powerpc,powerpcspe,powerpc64]~^ ERROR register class `vsreg` requires the `vsx` target feature - // v20-v31 (vs52-vs63) are reserved on AIX with vec-default ABI (this ABI is not currently used in Rust's builtin AIX targets). + // v20-v31 (vs52-vs63) are reserved on AIX with vec-default ABI, the ABI we currently use for our AIX target. asm!("", out("vs52") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs53") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs54") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs55") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs56") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs57") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs58") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs59") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs60") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs61") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs62") _); + //[aix64]~^ ERROR are reserved on vec-default ABI asm!("", out("vs63") _); + //[aix64]~^ ERROR are reserved on vec-default ABI // Clobber-only registers // cr @@ -303,28 +327,52 @@ fn f() { //~^ ERROR register `v19` conflicts with register `vs51` asm!("", out("vs52") _, out("v20") _); //~^ ERROR register `v20` conflicts with register `vs52` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs53") _, out("v21") _); //~^ ERROR register `v21` conflicts with register `vs53` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs54") _, out("v22") _); //~^ ERROR register `v22` conflicts with register `vs54` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs55") _, out("v23") _); //~^ ERROR register `v23` conflicts with register `vs55` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs56") _, out("v24") _); //~^ ERROR register `v24` conflicts with register `vs56` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs57") _, out("v25") _); //~^ ERROR register `v25` conflicts with register `vs57` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs58") _, out("v26") _); //~^ ERROR register `v26` conflicts with register `vs58` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs59") _, out("v27") _); //~^ ERROR register `v27` conflicts with register `vs59` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs60") _, out("v28") _); //~^ ERROR register `v28` conflicts with register `vs60` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs61") _, out("v29") _); //~^ ERROR register `v29` conflicts with register `vs61` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs62") _, out("v30") _); //~^ ERROR register `v30` conflicts with register `vs62` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI asm!("", out("vs63") _, out("v31") _); //~^ ERROR register `v31` conflicts with register `vs63` + //[aix64]~| ERROR are reserved on vec-default ABI + //[aix64]~| ERROR are reserved on vec-default ABI // powerpc-*spe target specific tests asm!("", out("spe_acc") _); diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr index 98404cd495dcf..5ccaf1e9aa698 100644 --- a/tests/ui/check-cfg/well-known-values.stderr +++ b/tests/ui/check-cfg/well-known-values.stderr @@ -140,7 +140,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` LL | target_abi = "_UNEXPECTED_VALUE", | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | - = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elfv1`, `elfv2`, `fortanix`, `ilp32`, `ilp32e`, `llvm`, `macabi`, `pauthtest`, `sim`, `softfloat`, `spe`, `uwp`, `v8plus`, `vec-extabi`, and `x32` + = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elfv1`, `elfv2`, `fortanix`, `ilp32`, `ilp32e`, `llvm`, `macabi`, `pauthtest`, `sim`, `softfloat`, `spe`, `uwp`, `v8plus`, `vec-default`, and `x32` = note: see for more information about checking conditional configuration warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE` From e478abb6124a09fa44d093bed1ad127a74ed4c43 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Sep 2026 14:48:04 +0000 Subject: [PATCH 0574/1309] Point at `'static` obligations from an fn being called Add this note to lifetime errors: ```text error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:163:9 | LL | fn bar<'a>(x: &'a &'a u32) { | -- - `x` is a reference that is only valid in the function body | | | lifetime `'a` defined here LL | let y: &dyn Foo = x; LL | y.hello(); | ^^^^^^^^^ | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` | note: `'static` requirement for `<(dyn o::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:158:40 | LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ `'static` requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^ `'static` requirement introduced here ``` This currently only accounts for explicit bounds, other obligations like those arising from `Self` in a `impl dyn Trait {}` or from the receiver in `fn foo(&'static self)` are not accounted for. --- .../src/diagnostics/region_errors.rs | 88 +++ .../ui/async-await/issues/issue-62097.stderr | 8 + tests/ui/async-await/issues/issue-72312.rs | 2 + .../ui/async-await/issues/issue-72312.stderr | 8 +- tests/ui/borrowck/issue-103624.stderr | 6 + ...g-lifetime-but-unused-not-mentioned.stderr | 6 + ...bounds-static-cant-capture-borrowed.stderr | 6 + .../ui/coroutine/resume-arg-outlives-2.stderr | 9 + tests/ui/lifetimes/static-impl-obligation.rs | 290 ++++++++++ .../lifetimes/static-impl-obligation.stderr | 537 ++++++++++++++++++ .../regions-static-bound-on-type-param.rs | 7 + .../regions-static-bound-on-type-param.stderr | 22 + tests/ui/regions/regions-static-bound.stderr | 14 + 13 files changed, 1002 insertions(+), 1 deletion(-) create mode 100644 tests/ui/lifetimes/static-impl-obligation.rs create mode 100644 tests/ui/lifetimes/static-impl-obligation.stderr create mode 100644 tests/ui/regions/regions-static-bound-on-type-param.rs create mode 100644 tests/ui/regions/regions-static-bound-on-type-param.stderr diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index 414f8dd58d439..a8ba8127dd83a 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -6,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::GenericBound::Trait; use rustc_hir::QPath::Resolved; use rustc_hir::WherePredicateKind::BoundPredicate; +use rustc_hir::def::DefKind; use rustc_hir::def::Res::Def; use rustc_hir::def_id::DefId; use rustc_hir::intravisit::Visitor; @@ -391,6 +392,89 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { outlives_suggestion.add_suggestion(self); } + /// Point at `'static` obligations from the item being called. + /// + /// ```text + /// error[E0521]: borrowed data escapes outside of function + /// --> $DIR/static-impl-obligation.rs:163:9 + /// | + /// LL | fn bar<'a>(x: &'a &'a u32) { + /// | -- - `x` is a reference that is only valid in the function body + /// | | + /// | lifetime `'a` defined here + /// LL | let y: &dyn Foo = x; + /// LL | y.hello(); + /// | ^^^^^^^^^ + /// | | + /// | `x` escapes the function body here + /// | argument requires that `'a` must outlive `'static` + /// | + /// note: `'static` requirement for `<(dyn o::Foo + 'static)>::hello` introduced here + /// --> $DIR/static-impl-obligation.rs:158:40 + /// | + /// LL | impl dyn Foo + 'static where Self: 'static { + /// | ^^^^^^^ `'static` requirement introduced here + /// LL | fn hello(&'static self) where Self: 'static {} + /// | ^^^^^^^ `'static` requirement introduced here + /// ``` + fn explain_impl_static_obligation( + &self, + diag: &mut Diag<'_>, + ty: Ty<'tcx>, + outlived_fr: RegionVid, + ) { + let tcx = self.infcx.tcx; + if self.regioncx.to_error_region(outlived_fr) != Some(tcx.lifetimes.re_static) { + return; + } + let ty::FnDef(def_id, args) = ty.kind() else { + return; + }; + let Ok(Some(instance)) = ty::Instance::try_resolve( + tcx, + self.infcx.typing_env(self.infcx.param_env), + *def_id, + self.infcx.deeply_resolve_ignoring_regions(args.no_bound_vars().unwrap()), + ) else { + return; + }; + let def_id = instance.def_id(); + let bounds = + tcx.clauses_of(def_id) + .instantiate(tcx, instance.args) + .into_iter() + .map(|(c, sp)| (c.skip_norm_wip().as_predicate(), sp)) + .filter(|(pred, _)| match pred.kind().skip_binder() { + ty::PredicateKind::Clause(ty::ClauseKind::TypeOutlives( + ty::OutlivesClause(_, lt), + )) + | ty::PredicateKind::Clause(ty::ClauseKind::RegionOutlives( + ty::OutlivesClause(_, lt), + )) if lt.is_static() => true, + _ => false, + }) + .map(|(_, sp)| sp) + .collect::>(); + if !bounds.is_empty() { + let mut multispan: MultiSpan = bounds.clone().into(); + for span in bounds { + multispan.push_span_label(span, "lifetime requirement introduced here"); + } + multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); + let parent = tcx.parent(def_id); + if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { + multispan.push_span_context(tcx.def_span(parent).shrink_to_lo()); + } + diag.span_note( + multispan, + format!( + "`'static` lifetime requirement from `{}` introduced here", + tcx.def_path_str(def_id) + ), + ); + } + } + /// Report that `longer_fr: error_vid`, which doesn't hold, /// where `longer_fr` is a placeholder. fn report_erroneous_rvid_reaches_placeholder( @@ -503,6 +587,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { } }; + if let ConstraintCategory::CallArgument(Some(ty)) = category { + self.explain_impl_static_obligation(&mut diag, ty, outlived_fr); + } + match variance_info { ty::VarianceDiagInfo::None => {} ty::VarianceDiagInfo::Invariant { ty, param_index } => { diff --git a/tests/ui/async-await/issues/issue-62097.stderr b/tests/ui/async-await/issues/issue-62097.stderr index 1422d315f88b0..0edb27f059e64 100644 --- a/tests/ui/async-await/issues/issue-62097.stderr +++ b/tests/ui/async-await/issues/issue-62097.stderr @@ -11,6 +11,14 @@ LL | foo(|| self.bar()).await; | | | `self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `foo` introduced here + --> $DIR/issue-62097.rs:4:19 + | +LL | async fn foo(fun: F) +LL | where +LL | F: FnOnce() + 'static + | ^^^^^^^ lifetime requirement introduced here error[E0373]: closure may outlive the current function, but it borrows `self`, which is owned by the current function --> $DIR/issue-62097.rs:13:13 diff --git a/tests/ui/async-await/issues/issue-72312.rs b/tests/ui/async-await/issues/issue-72312.rs index c2f01071f4a42..e2202fe628acf 100644 --- a/tests/ui/async-await/issues/issue-72312.rs +++ b/tests/ui/async-await/issues/issue-72312.rs @@ -1,5 +1,7 @@ //@ edition:2018 fn require_static(val: T) -> T { + //~^ NOTE: `'static` lifetime requirement from `require_static` introduced here + //~| NOTE: lifetime requirement introduced here val } diff --git a/tests/ui/async-await/issues/issue-72312.stderr b/tests/ui/async-await/issues/issue-72312.stderr index 33092a1abd3ab..5dbe7c18005ba 100644 --- a/tests/ui/async-await/issues/issue-72312.stderr +++ b/tests/ui/async-await/issues/issue-72312.stderr @@ -1,5 +1,5 @@ error[E0521]: borrowed data escapes outside of method - --> $DIR/issue-72312.rs:12:9 + --> $DIR/issue-72312.rs:14:9 | LL | pub async fn start(&self) { | ----- @@ -14,6 +14,12 @@ LL | | }); | | | | |__________`self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `require_static` introduced here + --> $DIR/issue-72312.rs:2:22 + | +LL | fn require_static(val: T) -> T { + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/borrowck/issue-103624.stderr b/tests/ui/borrowck/issue-103624.stderr index 77e961ee48fc2..cbcbbca813ca3 100644 --- a/tests/ui/borrowck/issue-103624.stderr +++ b/tests/ui/borrowck/issue-103624.stderr @@ -16,6 +16,12 @@ LL | | }) | | | | |__________`self` escapes the method body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `spawn_blocking` introduced here + --> $DIR/issue-103624.rs:7:64 + | +LL | async fn spawn_blocking(f: impl (Fn() -> T) + Send + Sync + 'static) -> T { + | ^^^^^^^ lifetime requirement introduced here error[E0507]: cannot move out of `self.b`, as `self` is a captured variable in an `Fn` closure --> $DIR/issue-103624.rs:16:13 diff --git a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr index a3cde891b7cac..e43e257cd9d5b 100644 --- a/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr +++ b/tests/ui/borrowck/var-matching-lifetime-but-unused-not-mentioned.stderr @@ -11,6 +11,12 @@ LL | consume(c); | | | `used_arg` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `consume` introduced here + --> $DIR/var-matching-lifetime-but-unused-not-mentioned.rs:5:15 + | +LL | fn consume(_: T) {} + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr index 654ca665ae09c..37316a331779a 100644 --- a/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr +++ b/tests/ui/closures/closure-bounds-static-cant-capture-borrowed.stderr @@ -14,6 +14,12 @@ LL | | }) | | | | |______`x` escapes the function body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `bar` introduced here + --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:2:39 + | +LL | fn bar(blk: F) where F: FnOnce() + 'static { + | ^^^^^^^ lifetime requirement introduced here error[E0373]: closure may outlive the current function, but it borrows `x`, which is owned by the current function --> $DIR/closure-bounds-static-cant-capture-borrowed.rs:6:9 diff --git a/tests/ui/coroutine/resume-arg-outlives-2.stderr b/tests/ui/coroutine/resume-arg-outlives-2.stderr index 9f6aab8d97ba7..49d3fee47fa9d 100644 --- a/tests/ui/coroutine/resume-arg-outlives-2.stderr +++ b/tests/ui/coroutine/resume-arg-outlives-2.stderr @@ -15,6 +15,15 @@ LL | | }) | | | | |______`s` escapes the function body here | argument requires that `'not_static` must outlive `'static` + | +note: `'static` lifetime requirement from `spawn` introduced here + --> $SRC_DIR/std/src/thread/functions.rs:LL:COL + ::: $SRC_DIR/std/src/thread/functions.rs:LL:COL + | + = note: lifetime requirement introduced here + ::: $SRC_DIR/std/src/thread/functions.rs:LL:COL + | + = note: lifetime requirement introduced here error: aborting due to 1 previous error diff --git a/tests/ui/lifetimes/static-impl-obligation.rs b/tests/ui/lifetimes/static-impl-obligation.rs new file mode 100644 index 0000000000000..106f300bb2352 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.rs @@ -0,0 +1,290 @@ +mod a { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod b { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod c { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod d { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod e { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod f { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod g { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod h { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod i { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod j { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod k { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod l { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod m { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod n { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod o { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod p { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + 'static where Self: 'static { + fn hello(&self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod q { + struct Foo {} + impl Foo { + fn hello(&'static self) {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod r { + struct Foo {} + impl Foo { + fn hello(&'static self) where Self: 'static {} + } + fn bar<'a>(x: &'a &'a Foo) { + x.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod s { + trait Foo {} + impl<'a> Foo for &'a u32 {} + + trait Trait { fn hello(&self) {} } + + impl Trait for dyn Foo { + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod t { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait where Self: 'static { + fn use_self(&self) -> &() where Self: 'static { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} //~ ERROR lifetime bound not satisfied + //~^ ERROR: cannot infer an appropriate lifetime for lifetime parameter `'_` + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod u { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait { + fn use_self(&self) -> &() where Self: 'static { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait + '_ {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod v { + trait OtherTrait<'a> {} + impl<'a> OtherTrait<'a> for &'a () {} + + trait ObjectTrait {} + trait MyTrait where Self: 'static { + fn use_self(&'static self) -> &() { panic!() } + } + trait Irrelevant { + fn use_self(&self) -> &() { panic!() } + } + + impl MyTrait for dyn ObjectTrait {} + + fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + val.use_self() //~ ERROR borrowed data escapes + } +} +mod w { + trait Foo {} + impl<'a> Foo for &'a u32 {} + + trait Trait where Self: 'static { fn hello(&self) {} } + + impl Trait for dyn Foo + '_ { //~ERROR lifetime bound not satisfied + //~^ ERROR: cannot infer an appropriate lifetime for lifetime parameter `'_` + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); //~ ERROR borrowed data escapes outside of function + } +} +mod x { + trait Foo {} + impl<'a> Foo for &'a u32 {} + impl dyn Foo + '_ where Self: '_ { //~ ERROR `'_` cannot be used here + fn hello(&self) {} + } + fn convert<'a>(x: &'a &'a u32) { + let y: &dyn Foo = x; + y.hello(); + } +} +fn main() {} diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr new file mode 100644 index 0000000000000..8b080d11ddf98 --- /dev/null +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -0,0 +1,537 @@ +error[E0637]: `'_` cannot be used here + --> $DIR/static-impl-obligation.rs:282:35 + | +LL | impl dyn Foo + '_ where Self: '_ { + | ^^ `'_` is a reserved lifetime name + +error[E0478]: lifetime bound not satisfied + --> $DIR/static-impl-obligation.rs:221:10 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/static-impl-obligation.rs:221:40 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'_` due to conflicting requirements + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime as defined here... + --> $DIR/static-impl-obligation.rs:221:40 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^ +note: ...so that the types are compatible + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + = note: expected `` + found `` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-impl-obligation.rs:221:22 + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ^^^^^^^^^^^^^^^^^^^^ + +error[E0478]: lifetime bound not satisfied + --> $DIR/static-impl-obligation.rs:270:10 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^ + | +note: lifetime parameter instantiated with the anonymous lifetime as defined here + --> $DIR/static-impl-obligation.rs:270:30 + | +LL | impl Trait for dyn Foo + '_ { + | ^^ + = note: but lifetime parameter must outlive the static lifetime + +error[E0803]: cannot infer an appropriate lifetime for lifetime parameter `'_` due to conflicting requirements + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + | +note: first, the lifetime cannot outlive the anonymous lifetime as defined here... + --> $DIR/static-impl-obligation.rs:270:30 + | +LL | impl Trait for dyn Foo + '_ { + | ^^ +note: ...so that the types are compatible + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + = note: expected `` + found `` + = note: but, the lifetime must be valid for the static lifetime... +note: ...so that the declared lifetime parameter bounds are satisfied + --> $DIR/static-impl-obligation.rs:270:20 + | +LL | impl Trait for dyn Foo + '_ { + | ^^^^^^^^^^^^ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:225:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `t::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:214:31 + | +LL | trait MyTrait where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() where Self: 'static { panic!() } + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:243:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `u::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:234:47 + | +LL | trait MyTrait { +LL | fn use_self(&self) -> &() where Self: 'static { panic!() } + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:261:9 + | +LL | fn use_it<'a>(val: &'a dyn ObjectTrait) -> impl OtherTrait<'a> + 'a { + | -- --- `val` is only valid in the function body + | | + | lifetime `'a` defined here +LL | val.use_self() + | ^^^^^^^^^^^^^^ + | | + | `val` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: the used `impl` has a `'static` requirement + --> $DIR/static-impl-obligation.rs:258:26 + | +LL | fn use_self(&'static self) -> &() { panic!() } + | -------- calling this method introduces the `impl`'s `'static` requirement +... +LL | impl MyTrait for dyn ObjectTrait {} + | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement +note: `'static` lifetime requirement from `v::MyTrait::use_self` introduced here + --> $DIR/static-impl-obligation.rs:251:31 + | +LL | trait MyTrait where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&'static self) -> &() { panic!() } + | +help: consider relaxing the implicit `'static` requirement + | +LL | impl MyTrait for dyn ObjectTrait + '_ {} + | ++++ + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:9:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:20:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:31:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:27:45 + | +LL | impl dyn Foo { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:42:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:38:37 + | +LL | impl dyn Foo { +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:53:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:64:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:75:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:71:45 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:86:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:82:37 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:97:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn i::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:92:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:108:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:103:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:119:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:114:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:130:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn l::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:125:30 + | +LL | impl dyn Foo where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:141:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn m::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:136:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:152:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:147:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) {} + | + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:163:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:158:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:174:9 + | +LL | fn bar<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn p::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:169:40 + | +LL | impl dyn Foo + 'static where Self: 'static { + | ^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:183:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:192:9 + | +LL | fn bar<'a>(x: &'a &'a Foo) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | x.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `r::Foo::hello` introduced here + --> $DIR/static-impl-obligation.rs:189:45 + | +LL | impl Foo { +LL | fn hello(&'static self) where Self: 'static {} + | ^^^^^^^ lifetime requirement introduced here + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:206:9 + | +LL | fn convert<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error[E0521]: borrowed data escapes outside of function + --> $DIR/static-impl-obligation.rs:276:9 + | +LL | fn convert<'a>(x: &'a &'a u32) { + | -- - `x` is only valid in the function body + | | + | lifetime `'a` defined here +LL | let y: &dyn Foo = x; +LL | y.hello(); + | ^^^^^^^^^ + | | + | `x` escapes the function body here + | argument requires that `'a` must outlive `'static` + +error: aborting due to 28 previous errors + +Some errors have detailed explanations: E0478, E0521, E0637, E0803. +For more information about an error, try `rustc --explain E0478`. diff --git a/tests/ui/regions/regions-static-bound-on-type-param.rs b/tests/ui/regions/regions-static-bound-on-type-param.rs new file mode 100644 index 0000000000000..176c120b57285 --- /dev/null +++ b/tests/ui/regions/regions-static-bound-on-type-param.rs @@ -0,0 +1,7 @@ +// https://github.com/rust-lang/rust/issues/162882 + +use std::error::Error; +fn err_is(err: &dyn Error) -> bool { + err.is::() //~ ERROR: borrowed data escapes outside of function +} +fn main() {} diff --git a/tests/ui/regions/regions-static-bound-on-type-param.stderr b/tests/ui/regions/regions-static-bound-on-type-param.stderr new file mode 100644 index 0000000000000..d30f1fbe62782 --- /dev/null +++ b/tests/ui/regions/regions-static-bound-on-type-param.stderr @@ -0,0 +1,22 @@ +error[E0521]: borrowed data escapes outside of function + --> $DIR/regions-static-bound-on-type-param.rs:5:5 + | +LL | fn err_is(err: &dyn Error) -> bool { + | --- - let's call the lifetime of this reference `'1` + | | + | `err` is only valid in the function body +LL | err.is::() + | ^^^^^^^^^^^^^ + | | + | `err` escapes the function body here + | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn std::error::Error + 'static)>::is` introduced here + --> $SRC_DIR/core/src/error.rs:LL:COL + ::: $SRC_DIR/core/src/error.rs:LL:COL + | + = note: lifetime requirement introduced here + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0521`. diff --git a/tests/ui/regions/regions-static-bound.stderr b/tests/ui/regions/regions-static-bound.stderr index df31a17ecf113..bea7b6f87bf8c 100644 --- a/tests/ui/regions/regions-static-bound.stderr +++ b/tests/ui/regions/regions-static-bound.stderr @@ -61,6 +61,12 @@ LL | static_id(&u); | | | `u` escapes the function body here | argument requires that `'1` must outlive `'static` + | +note: `'static` lifetime requirement from `static_id` introduced here + --> $DIR/regions-static-bound.rs:3:57 + | +LL | fn static_id<'a,'b>(t: &'a ()) -> &'static () where 'a: 'static { t } + | ^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/regions-static-bound.rs:20:5 @@ -75,6 +81,14 @@ LL | static_id_indirect(&v); | | | `v` escapes the function body here | argument requires that `'2` must outlive `'static` + | +note: `'static` lifetime requirement from `static_id_indirect` introduced here + --> $DIR/regions-static-bound.rs:10:23 + | +LL | fn static_id_indirect<'a,'b>(t: &'a ()) -> &'static () +... +LL | where 'a: 'b, 'b: 'static { t } + | ^^^^^^^ lifetime requirement introduced here error: aborting due to 3 previous errors; 4 warnings emitted From f7fed80f8cb5651616934302925729fdf3194453 Mon Sep 17 00:00:00 2001 From: rustbot <47979223+rustbot@users.noreply.github.com> Date: Mon, 21 Sep 2026 19:00:41 +0200 Subject: [PATCH 0575/1309] Update books --- src/doc/reference | 2 +- src/doc/rust-by-example | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/doc/reference b/src/doc/reference index e24eecf97b0c9..4245282b97496 160000 --- a/src/doc/reference +++ b/src/doc/reference @@ -1 +1 @@ -Subproject commit e24eecf97b0c9a6dbac67191098204dc8a190aaa +Subproject commit 4245282b97496585e73862b966d639cbb553bd6c diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example index 15308f3e95181..af5ef7024e885 160000 --- a/src/doc/rust-by-example +++ b/src/doc/rust-by-example @@ -1 +1 @@ -Subproject commit 15308f3e951814ef3475d2b58f48276e6b17b9af +Subproject commit af5ef7024e88587aa3be244422f6365e86c50e85 From 80cf81b67a8c8a9e75134eba9b5604eb8d9f31b6 Mon Sep 17 00:00:00 2001 From: The rustc-josh-sync Cronjob Bot Date: Mon, 21 Sep 2026 17:26:15 +0000 Subject: [PATCH 0576/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 56fad885ebfb0447660870715da4dfa75deae93d. --- src/doc/rustc-dev-guide/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/doc/rustc-dev-guide/rust-version b/src/doc/rustc-dev-guide/rust-version index 1c3d6e0224718..6b9ce9470f137 100644 --- a/src/doc/rustc-dev-guide/rust-version +++ b/src/doc/rustc-dev-guide/rust-version @@ -1 +1 @@ -420ed2a0c3d7225b1744266fd884d431b4d8cfe0 +56fad885ebfb0447660870715da4dfa75deae93d From ff88d0d231495e609bd61a62800419ffaa93eb4d Mon Sep 17 00:00:00 2001 From: Cathal Mullan Date: Sat, 13 Jun 2026 21:31:36 +0100 Subject: [PATCH 0577/1309] Integrate `stdarch` tests for aarch64 --- .../stdarch_skip/aarch64_core.txt | 301 +++++ .../stdarch_skip/aarch64_intrinsics_clang.txt | 1 + .../aarch64_intrinsics_common.txt | 1173 +++++++++++++++++ .../build_system/tests.rs | 118 +- compiler/rustc_codegen_cranelift/config.txt | 3 +- .../rustc_codegen_cranelift/example/neon.rs | 963 -------------- .../patches/0001-stdarch-Disable-SVE.patch | 51 + 7 files changed, 1645 insertions(+), 965 deletions(-) create mode 100644 compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_core.txt create mode 100644 compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_clang.txt create mode 100644 compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_common.txt delete mode 100644 compiler/rustc_codegen_cranelift/example/neon.rs create mode 100644 compiler/rustc_codegen_cranelift/patches/0001-stdarch-Disable-SVE.patch diff --git a/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_core.txt b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_core.txt new file mode 100644 index 0000000000000..3a028cd380029 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_core.txt @@ -0,0 +1,301 @@ +vaba_s16 +vaba_s32 +vaba_s8 +vaba_u16 +vaba_u32 +vaba_u8 +vabaq_s16 +vabaq_s32 +vabaq_s8 +vabaq_u16 +vabaq_u32 +vabaq_u8 +vhadd_s16 +vhadd_s32 +vhadd_s8 +vhadd_u16 +vhadd_u32 +vhadd_u8 +vhaddq_s16 +vhaddq_s32 +vhaddq_s8 +vhaddq_u16 +vhaddq_u32 +vhaddq_u8 +vhsub_s16 +vhsub_s32 +vhsub_s8 +vhsub_u16 +vhsub_u32 +vhsub_u8 +vhsubq_s16 +vhsubq_s32 +vhsubq_s8 +vhsubq_u16 +vhsubq_u32 +vhsubq_u8 +vld1_f16_x2 +vld1_f16_x3 +vld1_f16_x4 +vld1_f32_x2 +vld1_f32_x3 +vld1_f32_x4 +vld1_f64_x2 +vld1_f64_x3 +vld1_f64_x4 +vld1_p16_x2 +vld1_p16_x3 +vld1_p16_x4 +vld1_p64_x2 +vld1_p64_x3 +vld1_p64_x4 +vld1_p8_x2 +vld1_p8_x3 +vld1_p8_x4 +vld1_s16_x2 +vld1_s16_x3 +vld1_s16_x4 +vld1_s32_x2 +vld1_s32_x3 +vld1_s32_x4 +vld1_s64_x2 +vld1_s64_x3 +vld1_s64_x4 +vld1_s8_x2 +vld1_s8_x3 +vld1_s8_x4 +vld1_u16_x2 +vld1_u16_x3 +vld1_u16_x4 +vld1_u32_x2 +vld1_u32_x3 +vld1_u32_x4 +vld1_u64_x2 +vld1_u64_x3 +vld1_u64_x4 +vld1_u8_x2 +vld1_u8_x3 +vld1_u8_x4 +vld1q_f16_x2 +vld1q_f16_x3 +vld1q_f16_x4 +vld1q_f32_x2 +vld1q_f32_x3 +vld1q_f32_x4 +vld1q_f64_x2 +vld1q_f64_x3 +vld1q_f64_x4 +vld1q_p16_x2 +vld1q_p16_x3 +vld1q_p16_x4 +vld1q_p64_x2 +vld1q_p64_x3 +vld1q_p64_x4 +vld1q_p8_x2 +vld1q_p8_x3 +vld1q_p8_x4 +vld1q_s16_x2 +vld1q_s16_x3 +vld1q_s16_x4 +vld1q_s32_x2 +vld1q_s32_x3 +vld1q_s32_x4 +vld1q_s64_x2 +vld1q_s64_x3 +vld1q_s64_x4 +vld1q_s8_x2 +vld1q_s8_x3 +vld1q_s8_x4 +vld1q_u16_x2 +vld1q_u16_x3 +vld1q_u16_x4 +vld1q_u32_x2 +vld1q_u32_x3 +vld1q_u32_x4 +vld1q_u64_x2 +vld1q_u64_x3 +vld1q_u64_x4 +vld1q_u8_x2 +vld1q_u8_x3 +vld1q_u8_x4 +vld2_f16 +vld2_f32 +vld2_lane_f16 +vld2_lane_f32 +vld2_lane_s16 +vld2_lane_s32 +vld2_lane_s64 +vld2_lane_s8 +vld2_lane_u16 +vld2_lane_u32 +vld2_lane_u64 +vld2_lane_u8 +vld2_p16 +vld2_p8 +vld2_s16 +vld2_s32 +vld2_s64 +vld2_s8 +vld2_u16 +vld2_u32 +vld2_u64 +vld2_u8 +vld2q_f16 +vld2q_f32 +vld2q_f64 +vld2q_lane_f16 +vld2q_lane_f32 +vld2q_lane_s16 +vld2q_lane_s32 +vld2q_lane_s64 +vld2q_lane_s8 +vld2q_lane_u16 +vld2q_lane_u32 +vld2q_lane_u64 +vld2q_lane_u8 +vld2q_p16 +vld2q_p8 +vld2q_s16 +vld2q_s32 +vld2q_s64 +vld2q_s8 +vld2q_u16 +vld2q_u32 +vld2q_u64 +vld2q_u8 +vld3_f16 +vld3_lane_f16 +vld3_lane_f32 +vld3_lane_s16 +vld3_lane_s32 +vld3_lane_s64 +vld3_lane_s8 +vld3_lane_u16 +vld3_lane_u32 +vld3_lane_u64 +vld3_lane_u8 +vld3q_f16 +vld3q_lane_f16 +vld3q_lane_f32 +vld3q_lane_s16 +vld3q_lane_s32 +vld3q_lane_s64 +vld3q_lane_s8 +vld3q_lane_u16 +vld3q_lane_u32 +vld3q_lane_u64 +vld3q_lane_u8 +vld4_f16 +vld4_lane_f16 +vld4_lane_f32 +vld4_lane_s16 +vld4_lane_s32 +vld4_lane_s64 +vld4_lane_s8 +vld4_lane_u16 +vld4_lane_u32 +vld4_lane_u64 +vld4_lane_u8 +vld4q_f16 +vld4q_lane_f16 +vld4q_lane_f32 +vld4q_lane_s16 +vld4q_lane_s32 +vld4q_lane_s64 +vld4q_lane_s8 +vld4q_lane_u16 +vld4q_lane_u32 +vld4q_lane_u64 +vld4q_lane_u8 +vqtbl2_p8 +vqtbl2_s8 +vqtbl2_u8 +vqtbl2q_p8 +vqtbl2q_s8 +vqtbl2q_u8 +vqtbl3_p8 +vqtbl3_s8 +vqtbl3_u8 +vqtbl3q_p8 +vqtbl3q_s8 +vqtbl3q_u8 +vqtbl4_p8 +vqtbl4_s8 +vqtbl4_u8 +vqtbl4q_p8 +vqtbl4q_s8 +vqtbl4q_u8 +vqtbx1_p8 +vqtbx1_s8 +vqtbx1_u8 +vqtbx1q_p8 +vqtbx1q_s8 +vqtbx1q_u8 +vqtbx2_p8 +vqtbx2_s8 +vqtbx2_u8 +vqtbx2q_p8 +vqtbx2q_s8 +vqtbx2q_u8 +vqtbx3_p8 +vqtbx3_s8 +vqtbx3_u8 +vqtbx3q_p8 +vqtbx3q_s8 +vqtbx3q_u8 +vqtbx4_p8 +vqtbx4_s8 +vqtbx4_u8 +vqtbx4q_p8 +vqtbx4q_s8 +vqtbx4q_u8 +vrhadd_s16 +vrhadd_s32 +vrhadd_s8 +vrhadd_u16 +vrhadd_u32 +vrhadd_u8 +vrhaddq_s16 +vrhaddq_s32 +vrhaddq_s8 +vrhaddq_u16 +vrhaddq_u32 +vrhaddq_u8 +vsli_n_p16 +vsli_n_p8 +vsli_n_s16 +vsli_n_s32 +vsli_n_s64 +vsli_n_s8 +vsli_n_u16 +vsli_n_u32 +vsli_n_u64 +vsli_n_u8 +vsliq_n_p16 +vsliq_n_p8 +vsliq_n_s16 +vsliq_n_s32 +vsliq_n_s64 +vsliq_n_s8 +vsliq_n_u16 +vsliq_n_u32 +vsliq_n_u64 +vsliq_n_u8 +vtbl3_p8 +vtbl3_s8 +vtbl3_u8 +vtbl4_p8 +vtbl4_s8 +vtbl4_u8 +vtbx1_p8 +vtbx1_s8 +vtbx1_u8 +vtbx2_p8 +vtbx2_s8 +vtbx2_u8 +vtbx3_p8 +vtbx3_s8 +vtbx3_u8 +vtbx4_p8 +vtbx4_s8 +vtbx4_u8 diff --git a/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_clang.txt b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_clang.txt new file mode 100644 index 0000000000000..5f11867fd3ee9 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_clang.txt @@ -0,0 +1 @@ +vcvth_s16_f16 diff --git a/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_common.txt b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_common.txt new file mode 100644 index 0000000000000..a452f0c16b593 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/build_system/stdarch_skip/aarch64_intrinsics_common.txt @@ -0,0 +1,1173 @@ +__jcvt +vaba_s16 +vaba_s32 +vaba_s8 +vaba_u16 +vaba_u32 +vaba_u8 +vabal_high_s16 +vabal_high_s32 +vabal_high_s8 +vabal_high_u16 +vabal_high_u32 +vabal_high_u8 +vabal_s16 +vabal_s32 +vabal_s8 +vabal_u16 +vabal_u32 +vabal_u8 +vabaq_s16 +vabaq_s32 +vabaq_s8 +vabaq_u16 +vabaq_u32 +vabaq_u8 +vabd_f16 +vabd_f32 +vabd_f64 +vabd_s16 +vabd_s32 +vabd_s8 +vabd_u16 +vabd_u32 +vabd_u8 +vabdd_f64 +vabdh_f16 +vabdl_high_s16 +vabdl_high_s32 +vabdl_high_s8 +vabdl_high_u16 +vabdl_high_u32 +vabdl_high_u8 +vabdl_s16 +vabdl_s32 +vabdl_s8 +vabdl_u16 +vabdl_u32 +vabdl_u8 +vabdq_f16 +vabdq_f32 +vabdq_f64 +vabdq_s16 +vabdq_s32 +vabdq_s8 +vabdq_u16 +vabdq_u32 +vabdq_u8 +vabds_f32 +vabsd_s64 +vaddlv_s16 +vaddlv_s32 +vaddlv_s8 +vaddlv_u16 +vaddlv_u32 +vaddlv_u8 +vaddlvq_s16 +vaddlvq_s32 +vaddlvq_s8 +vaddlvq_u16 +vaddlvq_u32 +vaddvq_f64 +vamax_f16 +vamaxq_f16 +vamin_f16 +vaminq_f16 +vcadd_rot270_f16 +vcadd_rot270_f32 +vcadd_rot90_f16 +vcadd_rot90_f32 +vcaddq_rot270_f16 +vcaddq_rot270_f32 +vcaddq_rot270_f64 +vcaddq_rot90_f16 +vcaddq_rot90_f32 +vcaddq_rot90_f64 +vcage_f16 +vcage_f32 +vcage_f64 +vcaged_f64 +vcageh_f16 +vcageq_f16 +vcageq_f32 +vcageq_f64 +vcages_f32 +vcagt_f16 +vcagt_f32 +vcagt_f64 +vcagtd_f64 +vcagth_f16 +vcagtq_f16 +vcagtq_f32 +vcagtq_f64 +vcagts_f32 +vcale_f16 +vcale_f32 +vcale_f64 +vcaled_f64 +vcaleh_f16 +vcaleq_f16 +vcaleq_f32 +vcaleq_f64 +vcales_f32 +vcalt_f16 +vcalt_f32 +vcalt_f64 +vcaltd_f64 +vcalth_f16 +vcaltq_f16 +vcaltq_f32 +vcaltq_f64 +vcalts_f32 +vcmla_f16 +vcmla_f32 +vcmla_lane_f16 +vcmla_lane_f32 +vcmla_laneq_f16 +vcmla_laneq_f32 +vcmla_rot180_f16 +vcmla_rot180_f32 +vcmla_rot180_lane_f16 +vcmla_rot180_lane_f32 +vcmla_rot180_laneq_f16 +vcmla_rot180_laneq_f32 +vcmla_rot270_f16 +vcmla_rot270_f32 +vcmla_rot270_lane_f16 +vcmla_rot270_lane_f32 +vcmla_rot270_laneq_f16 +vcmla_rot270_laneq_f32 +vcmla_rot90_f16 +vcmla_rot90_f32 +vcmla_rot90_lane_f16 +vcmla_rot90_lane_f32 +vcmla_rot90_laneq_f16 +vcmla_rot90_laneq_f32 +vcmlaq_f16 +vcmlaq_f32 +vcmlaq_f64 +vcmlaq_lane_f16 +vcmlaq_lane_f32 +vcmlaq_laneq_f16 +vcmlaq_laneq_f32 +vcmlaq_rot180_f16 +vcmlaq_rot180_f32 +vcmlaq_rot180_f64 +vcmlaq_rot180_lane_f16 +vcmlaq_rot180_lane_f32 +vcmlaq_rot180_laneq_f16 +vcmlaq_rot180_laneq_f32 +vcmlaq_rot270_f16 +vcmlaq_rot270_f32 +vcmlaq_rot270_f64 +vcmlaq_rot270_lane_f16 +vcmlaq_rot270_lane_f32 +vcmlaq_rot270_laneq_f16 +vcmlaq_rot270_laneq_f32 +vcmlaq_rot90_f16 +vcmlaq_rot90_f32 +vcmlaq_rot90_f64 +vcmlaq_rot90_lane_f16 +vcmlaq_rot90_lane_f32 +vcmlaq_rot90_laneq_f16 +vcmlaq_rot90_laneq_f32 +vcvt_n_f16_s16 +vcvt_n_f16_u16 +vcvt_n_f32_s32 +vcvt_n_f32_u32 +vcvt_n_f64_s64 +vcvt_n_f64_u64 +vcvt_n_s16_f16 +vcvt_n_s32_f32 +vcvt_n_s64_f64 +vcvt_n_u16_f16 +vcvt_n_u32_f32 +vcvt_n_u64_f64 +vcvt_s32_f32 +vcvt_s64_f64 +vcvt_u32_f32 +vcvt_u64_f64 +vcvta_s16_f16 +vcvta_s32_f32 +vcvta_s64_f64 +vcvta_u16_f16 +vcvta_u32_f32 +vcvta_u64_f64 +vcvtad_s64_f64 +vcvtad_u64_f64 +vcvtah_s16_f16 +vcvtah_s32_f16 +vcvtah_s64_f16 +vcvtah_u16_f16 +vcvtah_u32_f16 +vcvtah_u64_f16 +vcvtaq_s16_f16 +vcvtaq_s32_f32 +vcvtaq_s64_f64 +vcvtaq_u16_f16 +vcvtaq_u32_f32 +vcvtaq_u64_f64 +vcvtas_s32_f32 +vcvtas_u32_f32 +vcvtd_n_f64_s64 +vcvtd_n_f64_u64 +vcvtd_n_s64_f64 +vcvtd_n_u64_f64 +vcvth_n_f16_s16 +vcvth_n_f16_s32 +vcvth_n_f16_s64 +vcvth_n_f16_u16 +vcvth_n_f16_u32 +vcvth_n_f16_u64 +vcvth_n_s16_f16 +vcvth_n_s32_f16 +vcvth_n_s64_f16 +vcvth_n_u16_f16 +vcvth_n_u32_f16 +vcvth_n_u64_f16 +vcvtm_s16_f16 +vcvtm_s32_f32 +vcvtm_s64_f64 +vcvtm_u16_f16 +vcvtm_u32_f32 +vcvtm_u64_f64 +vcvtmd_s64_f64 +vcvtmd_u64_f64 +vcvtmh_s16_f16 +vcvtmh_s32_f16 +vcvtmh_s64_f16 +vcvtmh_u16_f16 +vcvtmh_u32_f16 +vcvtmh_u64_f16 +vcvtmq_s16_f16 +vcvtmq_s32_f32 +vcvtmq_s64_f64 +vcvtmq_u16_f16 +vcvtmq_u32_f32 +vcvtmq_u64_f64 +vcvtms_s32_f32 +vcvtms_u32_f32 +vcvtn_s16_f16 +vcvtn_s32_f32 +vcvtn_s64_f64 +vcvtn_u16_f16 +vcvtn_u32_f32 +vcvtn_u64_f64 +vcvtnd_s64_f64 +vcvtnd_u64_f64 +vcvtnh_s16_f16 +vcvtnh_s32_f16 +vcvtnh_s64_f16 +vcvtnh_u16_f16 +vcvtnh_u32_f16 +vcvtnh_u64_f16 +vcvtnq_s16_f16 +vcvtnq_s64_f64 +vcvtnq_u16_f16 +vcvtnq_u32_f32 +vcvtnq_u64_f64 +vcvtns_s32_f32 +vcvtns_u32_f32 +vcvtp_s16_f16 +vcvtp_s32_f32 +vcvtp_s64_f64 +vcvtp_u16_f16 +vcvtp_u32_f32 +vcvtp_u64_f64 +vcvtpd_s64_f64 +vcvtpd_u64_f64 +vcvtph_s16_f16 +vcvtph_s32_f16 +vcvtph_s64_f16 +vcvtph_u16_f16 +vcvtph_u32_f16 +vcvtph_u64_f16 +vcvtpq_s16_f16 +vcvtpq_s32_f32 +vcvtpq_s64_f64 +vcvtpq_u16_f16 +vcvtpq_u32_f32 +vcvtpq_u64_f64 +vcvtps_s32_f32 +vcvtps_u32_f32 +vcvtq_n_f16_s16 +vcvtq_n_f16_u16 +vcvtq_n_f32_s32 +vcvtq_n_f32_u32 +vcvtq_n_f64_s64 +vcvtq_n_f64_u64 +vcvtq_n_s16_f16 +vcvtq_n_s32_f32 +vcvtq_n_s64_f64 +vcvtq_n_u16_f16 +vcvtq_n_u32_f32 +vcvtq_n_u64_f64 +vcvtq_s64_f64 +vcvtq_u32_f32 +vcvtq_u64_f64 +vcvts_n_f32_s32 +vcvts_n_f32_u32 +vcvts_n_s32_f32 +vcvts_n_u32_f32 +vcvtx_f32_f64 +vcvtx_high_f32_f64 +vcvtxd_f32_f64 +vdot_lane_s32 +vdot_lane_u32 +vdot_laneq_s32 +vdot_laneq_u32 +vdot_s32 +vdot_u32 +vdotq_lane_s32 +vdotq_lane_u32 +vdotq_laneq_s32 +vdotq_laneq_u32 +vdotq_s32 +vdotq_u32 +vfmlal_high_f16 +vfmlal_lane_high_f16 +vfmlal_lane_low_f16 +vfmlal_laneq_high_f16 +vfmlal_laneq_low_f16 +vfmlal_low_f16 +vfmlalq_high_f16 +vfmlalq_lane_high_f16 +vfmlalq_lane_low_f16 +vfmlalq_laneq_high_f16 +vfmlalq_laneq_low_f16 +vfmlalq_low_f16 +vfmlsl_high_f16 +vfmlsl_lane_high_f16 +vfmlsl_lane_low_f16 +vfmlsl_laneq_high_f16 +vfmlsl_laneq_low_f16 +vfmlsl_low_f16 +vfmlslq_high_f16 +vfmlslq_lane_high_f16 +vfmlslq_lane_low_f16 +vfmlslq_laneq_high_f16 +vfmlslq_laneq_low_f16 +vfmlslq_low_f16 +vhadd_s16 +vhadd_s32 +vhadd_s8 +vhadd_u16 +vhadd_u32 +vhadd_u8 +vhaddq_s16 +vhaddq_s32 +vhaddq_s8 +vhaddq_u16 +vhaddq_u32 +vhaddq_u8 +vhsub_s16 +vhsub_s32 +vhsub_s8 +vhsub_u16 +vhsub_u32 +vhsub_u8 +vhsubq_s16 +vhsubq_s32 +vhsubq_s8 +vhsubq_u16 +vhsubq_u32 +vhsubq_u8 +vld1_dup_f16 +vld1_f16 +vld1_f16_x2 +vld1_f16_x3 +vld1_f16_x4 +vld1_lane_f16 +vld1q_dup_f16 +vld1q_f16 +vld1q_f16_x2 +vld1q_f16_x3 +vld1q_f16_x4 +vld1q_lane_f16 +vld2_dup_f16 +vld2_f16 +vld2_lane_f16 +vld2q_dup_f16 +vld2q_f16 +vld2q_lane_f16 +vld3_dup_f16 +vld3_f16 +vld3_lane_f16 +vld3q_dup_f16 +vld3q_f16 +vld3q_lane_f16 +vld4_dup_f16 +vld4_f16 +vld4_lane_f16 +vld4q_dup_f16 +vld4q_f16 +vld4q_lane_f16 +vluti2_lane_f16 +vluti2_laneq_f16 +vluti2q_lane_f16 +vluti2q_laneq_f16 +vluti4q_lane_f16_x2 +vluti4q_laneq_f16_x2 +vmax_f16 +vmaxh_f16 +vmaxnm_f16 +vmaxnm_f32 +vmaxnm_f64 +vmaxnmh_f16 +vmaxnmq_f16 +vmaxnmq_f32 +vmaxnmq_f64 +vmaxnmv_f16 +vmaxnmv_f32 +vmaxnmvq_f16 +vmaxnmvq_f32 +vmaxnmvq_f64 +vmaxq_f16 +vmaxv_f16 +vmaxv_f32 +vmaxvq_f16 +vmaxvq_f32 +vmaxvq_f64 +vmin_f16 +vminh_f16 +vminnm_f16 +vminnm_f32 +vminnm_f64 +vminnmh_f16 +vminnmq_f16 +vminnmq_f32 +vminnmq_f64 +vminnmv_f16 +vminnmv_f32 +vminnmvq_f16 +vminnmvq_f32 +vminnmvq_f64 +vminq_f16 +vminv_f16 +vminv_f32 +vminvq_f16 +vminvq_f32 +vminvq_f64 +vmmlaq_s32 +vmmlaq_u32 +vmul_p8 +vmulq_p8 +vmulx_f16 +vmulx_f32 +vmulx_f64 +vmulx_lane_f16 +vmulx_lane_f32 +vmulx_lane_f64 +vmulx_laneq_f16 +vmulx_laneq_f32 +vmulx_laneq_f64 +vmulx_n_f16 +vmulxd_f64 +vmulxd_lane_f64 +vmulxd_laneq_f64 +vmulxh_f16 +vmulxh_lane_f16 +vmulxh_laneq_f16 +vmulxq_f16 +vmulxq_f32 +vmulxq_f64 +vmulxq_lane_f16 +vmulxq_lane_f32 +vmulxq_lane_f64 +vmulxq_laneq_f16 +vmulxq_laneq_f32 +vmulxq_laneq_f64 +vmulxq_n_f16 +vmulxs_f32 +vmulxs_lane_f32 +vmulxs_laneq_f32 +vpadd_f16 +vpadd_f32 +vpaddq_f16 +vpmax_f16 +vpmaxnm_f16 +vpmaxnm_f32 +vpmaxnmq_f16 +vpmaxnmq_f32 +vpmaxnmq_f64 +vpmaxnmqd_f64 +vpmaxnms_f32 +vpmaxq_f16 +vpmaxqd_f64 +vpmaxs_f32 +vpmin_f16 +vpminnm_f16 +vpminnm_f32 +vpminnmq_f16 +vpminnmq_f32 +vpminnmq_f64 +vpminnmqd_f64 +vpminnms_f32 +vpminq_f16 +vpminqd_f64 +vpmins_f32 +vqabs_s16 +vqabs_s32 +vqabs_s64 +vqabs_s8 +vqabsb_s8 +vqabsd_s64 +vqabsh_s16 +vqabsq_s16 +vqabsq_s32 +vqabsq_s64 +vqabsq_s8 +vqabss_s32 +vqaddd_s64 +vqaddd_u64 +vqadds_s32 +vqadds_u32 +vqdmlal_high_lane_s16 +vqdmlal_high_lane_s32 +vqdmlal_high_laneq_s16 +vqdmlal_high_laneq_s32 +vqdmlal_high_n_s16 +vqdmlal_high_n_s32 +vqdmlal_high_s16 +vqdmlal_high_s32 +vqdmlal_lane_s16 +vqdmlal_lane_s32 +vqdmlal_laneq_s16 +vqdmlal_laneq_s32 +vqdmlal_n_s16 +vqdmlal_n_s32 +vqdmlal_s16 +vqdmlal_s32 +vqdmlalh_lane_s16 +vqdmlalh_laneq_s16 +vqdmlalh_s16 +vqdmlals_lane_s32 +vqdmlals_laneq_s32 +vqdmlals_s32 +vqdmlsl_high_lane_s16 +vqdmlsl_high_lane_s32 +vqdmlsl_high_laneq_s16 +vqdmlsl_high_laneq_s32 +vqdmlsl_high_n_s16 +vqdmlsl_high_n_s32 +vqdmlsl_high_s16 +vqdmlsl_high_s32 +vqdmlsl_lane_s16 +vqdmlsl_lane_s32 +vqdmlsl_laneq_s16 +vqdmlsl_laneq_s32 +vqdmlsl_n_s16 +vqdmlsl_n_s32 +vqdmlsl_s16 +vqdmlsl_s32 +vqdmlslh_lane_s16 +vqdmlslh_laneq_s16 +vqdmlslh_s16 +vqdmlsls_lane_s32 +vqdmlsls_laneq_s32 +vqdmlsls_s32 +vqdmull_high_lane_s16 +vqdmull_high_lane_s32 +vqdmull_high_laneq_s16 +vqdmull_high_laneq_s32 +vqdmull_high_n_s16 +vqdmull_high_n_s32 +vqdmull_high_s16 +vqdmull_high_s32 +vqdmull_lane_s16 +vqdmull_lane_s32 +vqdmull_laneq_s16 +vqdmull_laneq_s32 +vqdmull_n_s16 +vqdmull_n_s32 +vqdmull_s16 +vqdmull_s32 +vqdmullh_lane_s16 +vqdmullh_laneq_s16 +vqdmullh_s16 +vqdmulls_lane_s32 +vqdmulls_laneq_s32 +vqdmulls_s32 +vqmovn_high_s16 +vqmovn_high_s32 +vqmovn_high_s64 +vqmovn_high_u16 +vqmovn_high_u32 +vqmovn_high_u64 +vqmovn_s16 +vqmovn_s32 +vqmovn_s64 +vqmovn_u16 +vqmovn_u32 +vqmovn_u64 +vqmovnd_s64 +vqmovnd_u64 +vqmovnh_s16 +vqmovnh_u16 +vqmovns_s32 +vqmovns_u32 +vqmovun_high_s16 +vqmovun_high_s32 +vqmovun_high_s64 +vqmovun_s16 +vqmovun_s32 +vqmovun_s64 +vqmovund_s64 +vqmovunh_s16 +vqmovuns_s32 +vqneg_s16 +vqneg_s32 +vqneg_s64 +vqneg_s8 +vqnegb_s8 +vqnegd_s64 +vqnegh_s16 +vqnegq_s16 +vqnegq_s32 +vqnegq_s64 +vqnegq_s8 +vqnegs_s32 +vqrdmlah_lane_s16 +vqrdmlah_lane_s32 +vqrdmlah_laneq_s16 +vqrdmlah_laneq_s32 +vqrdmlah_s16 +vqrdmlah_s32 +vqrdmlahh_lane_s16 +vqrdmlahh_laneq_s16 +vqrdmlahh_s16 +vqrdmlahq_lane_s16 +vqrdmlahq_lane_s32 +vqrdmlahq_laneq_s16 +vqrdmlahq_laneq_s32 +vqrdmlahq_s16 +vqrdmlahq_s32 +vqrdmlahs_lane_s32 +vqrdmlahs_laneq_s32 +vqrdmlahs_s32 +vqrdmlsh_lane_s16 +vqrdmlsh_lane_s32 +vqrdmlsh_laneq_s16 +vqrdmlsh_laneq_s32 +vqrdmlsh_s16 +vqrdmlsh_s32 +vqrdmlshh_lane_s16 +vqrdmlshh_laneq_s16 +vqrdmlshh_s16 +vqrdmlshq_lane_s16 +vqrdmlshq_lane_s32 +vqrdmlshq_laneq_s16 +vqrdmlshq_laneq_s32 +vqrdmlshq_s16 +vqrdmlshq_s32 +vqrdmlshs_lane_s32 +vqrdmlshs_laneq_s32 +vqrdmlshs_s32 +vqrdmulh_lane_s16 +vqrdmulh_lane_s32 +vqrdmulh_laneq_s16 +vqrdmulh_laneq_s32 +vqrdmulh_n_s16 +vqrdmulh_n_s32 +vqrdmulh_s16 +vqrdmulh_s32 +vqrdmulhh_lane_s16 +vqrdmulhh_laneq_s16 +vqrdmulhh_s16 +vqrdmulhq_lane_s16 +vqrdmulhq_lane_s32 +vqrdmulhq_laneq_s16 +vqrdmulhq_laneq_s32 +vqrdmulhq_n_s16 +vqrdmulhq_n_s32 +vqrdmulhq_s16 +vqrdmulhq_s32 +vqrdmulhs_lane_s32 +vqrdmulhs_laneq_s32 +vqrdmulhs_s32 +vqrshl_s16 +vqrshl_s32 +vqrshl_s64 +vqrshl_s8 +vqrshl_u16 +vqrshl_u32 +vqrshl_u64 +vqrshl_u8 +vqrshlb_s8 +vqrshlb_u8 +vqrshld_s64 +vqrshld_u64 +vqrshlh_s16 +vqrshlh_u16 +vqrshlq_s16 +vqrshlq_s32 +vqrshlq_s64 +vqrshlq_s8 +vqrshlq_u16 +vqrshlq_u32 +vqrshlq_u64 +vqrshlq_u8 +vqrshls_s32 +vqrshls_u32 +vqrshrn_high_n_s16 +vqrshrn_high_n_s32 +vqrshrn_high_n_s64 +vqrshrn_high_n_u16 +vqrshrn_high_n_u32 +vqrshrn_high_n_u64 +vqrshrn_n_s16 +vqrshrn_n_s32 +vqrshrn_n_s64 +vqrshrn_n_u16 +vqrshrn_n_u32 +vqrshrn_n_u64 +vqrshrnd_n_s64 +vqrshrnd_n_u64 +vqrshrnh_n_s16 +vqrshrnh_n_u16 +vqrshrns_n_s32 +vqrshrns_n_u32 +vqrshrun_high_n_s16 +vqrshrun_high_n_s32 +vqrshrun_high_n_s64 +vqrshrun_n_s16 +vqrshrun_n_s32 +vqrshrun_n_s64 +vqrshrund_n_s64 +vqrshrunh_n_s16 +vqrshruns_n_s32 +vqshl_n_s16 +vqshl_n_s32 +vqshl_n_s64 +vqshl_n_s8 +vqshl_n_u16 +vqshl_n_u32 +vqshl_n_u64 +vqshl_n_u8 +vqshl_s16 +vqshl_s32 +vqshl_s64 +vqshl_s8 +vqshl_u16 +vqshl_u32 +vqshl_u64 +vqshl_u8 +vqshlb_n_s8 +vqshlb_n_u8 +vqshlb_s8 +vqshlb_u8 +vqshld_n_s64 +vqshld_n_u64 +vqshld_s64 +vqshld_u64 +vqshlh_n_s16 +vqshlh_n_u16 +vqshlh_s16 +vqshlh_u16 +vqshlq_n_s16 +vqshlq_n_s32 +vqshlq_n_s64 +vqshlq_n_s8 +vqshlq_n_u16 +vqshlq_n_u32 +vqshlq_n_u64 +vqshlq_n_u8 +vqshlq_s16 +vqshlq_s32 +vqshlq_s64 +vqshlq_s8 +vqshlq_u16 +vqshlq_u32 +vqshlq_u64 +vqshlq_u8 +vqshls_n_s32 +vqshls_n_u32 +vqshls_s32 +vqshls_u32 +vqshlu_n_s16 +vqshlu_n_s32 +vqshlu_n_s64 +vqshlu_n_s8 +vqshlub_n_s8 +vqshlud_n_s64 +vqshluh_n_s16 +vqshluq_n_s16 +vqshluq_n_s32 +vqshluq_n_s64 +vqshluq_n_s8 +vqshlus_n_s32 +vqshrn_high_n_s16 +vqshrn_high_n_s32 +vqshrn_high_n_s64 +vqshrn_high_n_u16 +vqshrn_high_n_u32 +vqshrn_high_n_u64 +vqshrn_n_s16 +vqshrn_n_s32 +vqshrn_n_s64 +vqshrn_n_u16 +vqshrn_n_u32 +vqshrn_n_u64 +vqshrnd_n_s64 +vqshrnd_n_u64 +vqshrnh_n_s16 +vqshrnh_n_u16 +vqshrns_n_s32 +vqshrns_n_u32 +vqshrun_high_n_s16 +vqshrun_high_n_s32 +vqshrun_high_n_s64 +vqshrun_n_s16 +vqshrun_n_s32 +vqshrun_n_s64 +vqshrund_n_s64 +vqshrunh_n_s16 +vqshruns_n_s32 +vqsubd_s64 +vqsubd_u64 +vqsubs_s32 +vqsubs_u32 +vqtbl2_p8 +vqtbl2_s8 +vqtbl2_u8 +vqtbl2q_p8 +vqtbl2q_s8 +vqtbl2q_u8 +vqtbl3_p8 +vqtbl3_s8 +vqtbl3_u8 +vqtbl3q_p8 +vqtbl3q_s8 +vqtbl3q_u8 +vqtbl4_p8 +vqtbl4_s8 +vqtbl4_u8 +vqtbl4q_p8 +vqtbl4q_s8 +vqtbl4q_u8 +vqtbx1_p8 +vqtbx1_s8 +vqtbx1_u8 +vqtbx1q_p8 +vqtbx1q_s8 +vqtbx1q_u8 +vqtbx2_p8 +vqtbx2_s8 +vqtbx2_u8 +vqtbx2q_p8 +vqtbx2q_s8 +vqtbx2q_u8 +vqtbx3_p8 +vqtbx3_s8 +vqtbx3_u8 +vqtbx3q_p8 +vqtbx3q_s8 +vqtbx3q_u8 +vqtbx4_p8 +vqtbx4_s8 +vqtbx4_u8 +vqtbx4q_p8 +vqtbx4q_s8 +vqtbx4q_u8 +vraddhn_high_s16 +vraddhn_high_s32 +vraddhn_high_s64 +vraddhn_high_u16 +vraddhn_high_u32 +vraddhn_high_u64 +vraddhn_s16 +vraddhn_s32 +vraddhn_s64 +vraddhn_u16 +vraddhn_u32 +vraddhn_u64 +vrecpe_f16 +vrecpe_f32 +vrecpe_f64 +vrecpe_u32 +vrecped_f64 +vrecpeh_f16 +vrecpeq_f16 +vrecpeq_f64 +vrecpeq_u32 +vrecpes_f32 +vrecps_f16 +vrecps_f32 +vrecps_f64 +vrecpsd_f64 +vrecpsh_f16 +vrecpsq_f16 +vrecpsq_f64 +vrecpss_f32 +vrecpxd_f64 +vrecpxh_f16 +vrecpxs_f32 +vreinterpretq_f16_p128 +vrhadd_s16 +vrhadd_s32 +vrhadd_s8 +vrhadd_u16 +vrhadd_u32 +vrhadd_u8 +vrhaddq_s16 +vrhaddq_s32 +vrhaddq_s8 +vrhaddq_u16 +vrhaddq_u32 +vrhaddq_u8 +vrnd32x_f32 +vrnd32x_f64 +vrnd32xq_f32 +vrnd32xq_f64 +vrnd32z_f32 +vrnd32z_f64 +vrnd32zq_f32 +vrnd32zq_f64 +vrnd64x_f32 +vrnd64x_f64 +vrnd64xq_f32 +vrnd64xq_f64 +vrnd64z_f32 +vrnd64z_f64 +vrnd64zq_f32 +vrnd64zq_f64 +vrndi_f16 +vrndi_f32 +vrndi_f64 +vrndih_f16 +vrndiq_f16 +vrndiq_f32 +vrndiq_f64 +vrndn_f16 +vrndnh_f16 +vrndnq_f16 +vrndns_f32 +vrshl_s16 +vrshl_s32 +vrshl_s64 +vrshl_s8 +vrshl_u16 +vrshl_u32 +vrshl_u64 +vrshl_u8 +vrshld_s64 +vrshld_u64 +vrshlq_s16 +vrshlq_s32 +vrshlq_s64 +vrshlq_s8 +vrshlq_u16 +vrshlq_u32 +vrshlq_u64 +vrshlq_u8 +vrshr_n_s16 +vrshr_n_s32 +vrshr_n_s64 +vrshr_n_s8 +vrshr_n_u16 +vrshr_n_u32 +vrshr_n_u64 +vrshr_n_u8 +vrshrd_n_s64 +vrshrd_n_u64 +vrshrn_high_n_s16 +vrshrn_high_n_s32 +vrshrn_high_n_s64 +vrshrn_high_n_u16 +vrshrn_high_n_u32 +vrshrn_high_n_u64 +vrshrn_n_s16 +vrshrn_n_s32 +vrshrn_n_s64 +vrshrn_n_u16 +vrshrn_n_u32 +vrshrn_n_u64 +vrshrq_n_s16 +vrshrq_n_s32 +vrshrq_n_s64 +vrshrq_n_s8 +vrshrq_n_u16 +vrshrq_n_u32 +vrshrq_n_u64 +vrshrq_n_u8 +vrsqrte_f16 +vrsqrte_f32 +vrsqrte_f64 +vrsqrte_u32 +vrsqrted_f64 +vrsqrteh_f16 +vrsqrteq_f16 +vrsqrteq_f32 +vrsqrteq_f64 +vrsqrteq_u32 +vrsqrtes_f32 +vrsqrts_f16 +vrsqrts_f32 +vrsqrts_f64 +vrsqrtsd_f64 +vrsqrtsh_f16 +vrsqrtsq_f16 +vrsqrtsq_f32 +vrsqrtsq_f64 +vrsqrtss_f32 +vrsra_n_s16 +vrsra_n_s32 +vrsra_n_s64 +vrsra_n_s8 +vrsra_n_u16 +vrsra_n_u32 +vrsra_n_u64 +vrsra_n_u8 +vrsrad_n_s64 +vrsrad_n_u64 +vrsraq_n_s16 +vrsraq_n_s32 +vrsraq_n_s64 +vrsraq_n_s8 +vrsraq_n_u16 +vrsraq_n_u32 +vrsraq_n_u64 +vrsraq_n_u8 +vrsubhn_high_s16 +vrsubhn_high_s32 +vrsubhn_high_s64 +vrsubhn_high_u16 +vrsubhn_high_u32 +vrsubhn_high_u64 +vrsubhn_s16 +vrsubhn_s32 +vrsubhn_s64 +vrsubhn_u16 +vrsubhn_u32 +vrsubhn_u64 +vscale_f16 +vscaleq_f16 +vshl_s16 +vshl_s32 +vshl_s64 +vshl_s8 +vshl_u16 +vshl_u32 +vshl_u64 +vshl_u8 +vshld_s64 +vshld_u64 +vshlq_s16 +vshlq_s32 +vshlq_s64 +vshlq_s8 +vshlq_u16 +vshlq_u32 +vshlq_u64 +vshlq_u8 +vsli_n_p16 +vsli_n_p64 +vsli_n_p8 +vsli_n_s16 +vsli_n_s32 +vsli_n_s64 +vsli_n_s8 +vsli_n_u16 +vsli_n_u32 +vsli_n_u64 +vsli_n_u8 +vslid_n_s64 +vslid_n_u64 +vsliq_n_p16 +vsliq_n_p64 +vsliq_n_p8 +vsliq_n_s16 +vsliq_n_s32 +vsliq_n_s64 +vsliq_n_s8 +vsliq_n_u16 +vsliq_n_u32 +vsliq_n_u64 +vsliq_n_u8 +vsm3partw1q_u32 +vsm3partw2q_u32 +vsm3ss1q_u32 +vsm3tt1aq_u32 +vsm3tt1bq_u32 +vsm3tt2aq_u32 +vsm3tt2bq_u32 +vsm4ekeyq_u32 +vsm4eq_u32 +vsqadd_u16 +vsqadd_u32 +vsqadd_u64 +vsqadd_u8 +vsqaddb_u8 +vsqaddd_u64 +vsqaddh_u16 +vsqaddq_u16 +vsqaddq_u32 +vsqaddq_u64 +vsqaddq_u8 +vsqadds_u32 +vst1_f16 +vst1_f16_x2 +vst1_f16_x3 +vst1_f16_x4 +vst1_lane_f16 +vst1q_f16 +vst1q_f16_x2 +vst1q_f16_x3 +vst1q_f16_x4 +vst1q_lane_f16 +vst2_f16 +vst2_lane_f16 +vst2q_f16 +vst2q_lane_f16 +vst3_f16 +vst3_lane_f16 +vst3q_f16 +vst3q_lane_f16 +vst4_f16 +vst4_lane_f16 +vst4q_f16 +vst4q_lane_f16 +vsudot_lane_s32 +vsudot_laneq_s32 +vsudotq_lane_s32 +vsudotq_laneq_s32 +vtbl2_p8 +vtbl2_s8 +vtbl2_u8 +vtbl3_p8 +vtbl3_s8 +vtbl3_u8 +vtbl4_p8 +vtbl4_s8 +vtbl4_u8 +vtbx1_p8 +vtbx1_s8 +vtbx1_u8 +vtbx2_p8 +vtbx2_s8 +vtbx2_u8 +vtbx3_p8 +vtbx3_s8 +vtbx3_u8 +vtbx4_p8 +vtbx4_s8 +vtbx4_u8 +vuqadd_s16 +vuqadd_s32 +vuqadd_s64 +vuqadd_s8 +vuqaddb_s8 +vuqaddd_s64 +vuqaddh_s16 +vuqaddq_s16 +vuqaddq_s32 +vuqaddq_s64 +vuqaddq_s8 +vuqadds_s32 +vusdot_lane_s32 +vusdot_laneq_s32 +vusdot_s32 +vusdotq_lane_s32 +vusdotq_laneq_s32 +vusdotq_s32 +vusmmlaq_s32 diff --git a/compiler/rustc_codegen_cranelift/build_system/tests.rs b/compiler/rustc_codegen_cranelift/build_system/tests.rs index 5ae76dc1e591e..3b9ae2608abfe 100644 --- a/compiler/rustc_codegen_cranelift/build_system/tests.rs +++ b/compiler/rustc_codegen_cranelift/build_system/tests.rs @@ -1,4 +1,5 @@ use std::ffi::OsStr; +use std::fs; use std::path::PathBuf; use std::process::Command; @@ -108,7 +109,6 @@ const BASE_SYSROOT_SUITE: &[TestCase] = &[ }), TestCase::build_bin_and_run("aot.issue-72793", "example/issue-72793.rs", &[]), TestCase::build_bin("aot.issue-59326", "example/issue-59326.rs"), - TestCase::build_bin_and_run("aot.neon", "example/neon.rs", &[]), TestCase::build_bin_and_run("aot.gen_block_iterate", "example/gen_block_iterate.rs", &[]), TestCase::build_bin_and_run("aot.raw-dylib", "example/raw-dylib.rs", &[]), TestCase::custom("test.sysroot", &|runner| { @@ -182,6 +182,12 @@ static SYSROOT_TESTS_SRC: RelPath = RelPath::build("sysroot_tests"); static SYSROOT_TESTS: CargoProject = CargoProject::new(SYSROOT_TESTS_SRC, "sysroot_tests_target"); +static STDARCH_SRC: RelPath = RelPath::build("stdarch"); + +static STDARCH: CargoProject = CargoProject::new(STDARCH_SRC, "stdarch_target"); +static STDARCH_RUST_PROGRAMS: CargoProject = + CargoProject::new(RelPath::build("stdarch/rust_programs"), "stdarch_rust_programs_target"); + const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ TestCase::custom("test.rust-random/rand", &|runner| { RAND_REPO.patch(&runner.dirs); @@ -283,6 +289,116 @@ const EXTENDED_SYSROOT_SUITE: &[TestCase] = &[ spawn_and_wait(test_cmd); } }), + TestCase::custom("test.stdarch-core", &|runner| { + let target = runner.target_compiler.target.as_str(); + let (arch, _) = target.split_once('-').unwrap(); + + // FIXME: Add support for remaining architectures. + if !["aarch64"].contains(&arch) { + eprintln!("Skipping `stdarch-core` tests: unsupported target"); + return; + } + + apply_patches( + &runner.dirs, + "stdarch", + &runner.stdlib_source.join("library/stdarch"), + &STDARCH_SRC.to_path(&runner.dirs), + ); + + STDARCH.clean(&runner.dirs); + + let skip = format!("build_system/stdarch_skip/{arch}_core.txt"); + let skip = fs::read_to_string(runner.dirs.source_dir.join(skip)).unwrap_or_default(); + + let skip_functions = skip + .lines() + .map(str::trim) + .filter(|line| !line.is_empty() && !line.starts_with('#')) + .collect::>() + .join(","); + + if runner.is_native { + let mut test_cmd = STDARCH.test(&runner.target_compiler, &runner.dirs); + + test_cmd.env("TARGET", target); + test_cmd.env("STDARCH_TEST_SKIP_FUNCTION", &skip_functions); + + test_cmd.args(["-p", "core_arch", "--tests", "--", "-q"]); + spawn_and_wait(test_cmd); + } else { + eprintln!("Cross-Compiling: Not running tests"); + let mut build_cmd = STDARCH.build(&runner.target_compiler, &runner.dirs); + + build_cmd.env("TARGET", target); + + build_cmd.args(["-p", "core_arch", "--tests"]); + spawn_and_wait(build_cmd); + } + }), + TestCase::custom("test.stdarch-intrinsics", &|runner| { + let target = runner.target_compiler.target.as_str(); + let (arch, _) = target.split_once('-').unwrap(); + + // FIXME: Add support for remaining architectures. + let input = match arch { + "aarch64" => "intrinsics_data/arm_intrinsics.json", + _ => { + eprintln!("Skipping `stdarch-intrinsics` tests: unsupported target"); + return; + } + }; + + apply_patches( + &runner.dirs, + "stdarch", + &runner.stdlib_source.join("library/stdarch"), + &STDARCH_SRC.to_path(&runner.dirs), + ); + + STDARCH_RUST_PROGRAMS.clean(&runner.dirs); + + if !runner.is_native { + eprintln!("Cross-Compiling: Not running tests"); + return; + } + + let cc = if target.contains("apple") { "clang" } else { "gcc" }; + + let mut generate_cmd = STDARCH.run(&runner.target_compiler, &runner.dirs); + generate_cmd.current_dir(STDARCH.source_dir(&runner.dirs)); + generate_cmd.args([ + "-p", + "intrinsic-test", + "--", + input, + "--target", + target, + "--cc-arg-style", + cc, + "--skip", + &format!("crates/intrinsic-test/missing_{arch}_common.txt"), + "--skip", + &format!("crates/intrinsic-test/missing_{arch}_{cc}.txt"), + ]); + + for skip in [ + format!("build_system/stdarch_skip/{arch}_intrinsics_common.txt"), + format!("build_system/stdarch_skip/{arch}_intrinsics_{cc}.txt"), + ] { + let skip = runner.dirs.source_dir.join(skip); + + if skip.exists() { + generate_cmd.arg("--skip").arg(skip); + } + } + + spawn_and_wait(generate_cmd); + + let mut test_cmd = STDARCH_RUST_PROGRAMS.test(&runner.target_compiler, &runner.dirs); + test_cmd.args(["--workspace", "--tests", "--no-fail-fast", "--", "-q"]); + spawn_and_wait(test_cmd); + }), ]; pub(crate) fn run_tests( diff --git a/compiler/rustc_codegen_cranelift/config.txt b/compiler/rustc_codegen_cranelift/config.txt index ca126f4e39e29..c1068e6257d73 100644 --- a/compiler/rustc_codegen_cranelift/config.txt +++ b/compiler/rustc_codegen_cranelift/config.txt @@ -22,7 +22,6 @@ aot.float-minmax-pass aot.powi_libcall_signature aot.issue-72793 aot.issue-59326 -aot.neon aot.gen_block_iterate aot.raw-dylib test.sysroot @@ -32,3 +31,5 @@ test.rust-random/rand test.regex test.graviola test.portable-simd +test.stdarch-core +test.stdarch-intrinsics diff --git a/compiler/rustc_codegen_cranelift/example/neon.rs b/compiler/rustc_codegen_cranelift/example/neon.rs deleted file mode 100644 index ba63333daa339..0000000000000 --- a/compiler/rustc_codegen_cranelift/example/neon.rs +++ /dev/null @@ -1,963 +0,0 @@ -// Most of these tests are copied from https://github.com/japaric/stdsimd/blob/0f4413d01c4f0c3ffbc5a69e9a37fbc7235b31a9/coresimd/arm/neon.rs - -#![cfg_attr(target_arch = "aarch64", feature(portable_simd))] - -#[cfg(target_arch = "aarch64")] -use std::arch::aarch64::*; -#[cfg(target_arch = "aarch64")] -use std::mem::transmute; -#[cfg(target_arch = "aarch64")] -use std::simd::*; - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "crc")] -unsafe fn test_crc32() { - assert!(std::arch::is_aarch64_feature_detected!("crc")); - - let a: u32 = 42; - let b: u64 = 0xdeadbeef; - - assert_eq!(__crc32b(a, b as u8), 0xEB0E363F); - assert_eq!(__crc32h(a, b as u16), 0x9A54BD80); - assert_eq!(__crc32w(a, b as u32), 0xF491F059); - assert_eq!(__crc32d(a, b as u64), 0xD14BBEA6); - - assert_eq!(__crc32cb(a, b as u8), 0xF67C32D8); - assert_eq!(__crc32ch(a, b as u16), 0x479108B8); - assert_eq!(__crc32cw(a, b as u32), 0x979F49F8); - assert_eq!(__crc32cd(a, b as u64), 0x0E6BE593); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_s8() { - let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); - let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); - let e = i8x8::from([-2, -4, 5, 7, 0, 2, 4, 6]); - let r: i8x8 = unsafe { transmute(vpmin_s8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_s16() { - let a = i16x4::from([1, 2, 3, -4]); - let b = i16x4::from([0, 3, 2, 5]); - let e = i16x4::from([1, -4, 0, 2]); - let r: i16x4 = unsafe { transmute(vpmin_s16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_s32() { - let a = i32x2::from([1, -2]); - let b = i32x2::from([0, 3]); - let e = i32x2::from([-2, 0]); - let r: i32x2 = unsafe { transmute(vpmin_s32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_u8() { - let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); - let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); - let e = u8x8::from([1, 3, 5, 7, 0, 2, 4, 6]); - let r: u8x8 = unsafe { transmute(vpmin_u8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_u16() { - let a = u16x4::from([1, 2, 3, 4]); - let b = u16x4::from([0, 3, 2, 5]); - let e = u16x4::from([1, 3, 0, 2]); - let r: u16x4 = unsafe { transmute(vpmin_u16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_u32() { - let a = u32x2::from([1, 2]); - let b = u32x2::from([0, 3]); - let e = u32x2::from([1, 0]); - let r: u32x2 = unsafe { transmute(vpmin_u32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmin_f32() { - let a = f32x2::from([1., -2.]); - let b = f32x2::from([0., 3.]); - let e = f32x2::from([-2., 0.]); - let r: f32x2 = unsafe { transmute(vpmin_f32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_s8() { - let a = i8x8::from([1, -2, 3, -4, 5, 6, 7, 8]); - let b = i8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); - let e = i8x8::from([1, 3, 6, 8, 3, 5, 7, 9]); - let r: i8x8 = unsafe { transmute(vpmax_s8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_s16() { - let a = i16x4::from([1, 2, 3, -4]); - let b = i16x4::from([0, 3, 2, 5]); - let e = i16x4::from([2, 3, 3, 5]); - let r: i16x4 = unsafe { transmute(vpmax_s16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_s32() { - let a = i32x2::from([1, -2]); - let b = i32x2::from([0, 3]); - let e = i32x2::from([1, 3]); - let r: i32x2 = unsafe { transmute(vpmax_s32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_u8() { - let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); - let b = u8x8::from([0, 3, 2, 5, 4, 7, 6, 9]); - let e = u8x8::from([2, 4, 6, 8, 3, 5, 7, 9]); - let r: u8x8 = unsafe { transmute(vpmax_u8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_u16() { - let a = u16x4::from([1, 2, 3, 4]); - let b = u16x4::from([0, 3, 2, 5]); - let e = u16x4::from([2, 4, 3, 5]); - let r: u16x4 = unsafe { transmute(vpmax_u16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_u32() { - let a = u32x2::from([1, 2]); - let b = u32x2::from([0, 3]); - let e = u32x2::from([2, 3]); - let r: u32x2 = unsafe { transmute(vpmax_u32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpmax_f32() { - let a = f32x2::from([1., -2.]); - let b = f32x2::from([0., 3.]); - let e = f32x2::from([1., 3.]); - let r: f32x2 = unsafe { transmute(vpmax_f32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_s16() { - let a = i16x4::from([1, 2, 3, 4]); - let b = i16x4::from([0, -1, -2, -3]); - let r: i16x4 = unsafe { transmute(vpadd_s16(transmute(a), transmute(b))) }; - let e = i16x4::from([3, 7, -1, -5]); - assert_eq!(r, e); -} -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_s32() { - let a = i32x2::from([1, 2]); - let b = i32x2::from([0, -1]); - let r: i32x2 = unsafe { transmute(vpadd_s32(transmute(a), transmute(b))) }; - let e = i32x2::from([3, -1]); - assert_eq!(r, e); -} -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_s8() { - let a = i8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); - let b = i8x8::from([0, -1, -2, -3, -4, -5, -6, -7]); - let r: i8x8 = unsafe { transmute(vpadd_s8(transmute(a), transmute(b))) }; - let e = i8x8::from([3, 7, 11, 15, -1, -5, -9, -13]); - assert_eq!(r, e); -} -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_u16() { - let a = u16x4::from([1, 2, 3, 4]); - let b = u16x4::from([30, 31, 32, 33]); - let r: u16x4 = unsafe { transmute(vpadd_u16(transmute(a), transmute(b))) }; - let e = u16x4::from([3, 7, 61, 65]); - assert_eq!(r, e); -} -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_u32() { - let a = u32x2::from([1, 2]); - let b = u32x2::from([30, 31]); - let r: u32x2 = unsafe { transmute(vpadd_u32(transmute(a), transmute(b))) }; - let e = u32x2::from([3, 61]); - assert_eq!(r, e); -} -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpadd_u8() { - let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 8]); - let b = u8x8::from([30, 31, 32, 33, 34, 35, 36, 37]); - let r: u8x8 = unsafe { transmute(vpadd_u8(transmute(a), transmute(b))) }; - let e = u8x8::from([3, 7, 11, 15, 61, 65, 69, 73]); - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqsub_u8() { - let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); - let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); - let r: u8x8 = unsafe { transmute(vqsub_u8(transmute(a), transmute(b))) }; - let e = u8x8::from([0, 1, 2, 3, 0, 0, 0, 218]); - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqadd_u8() { - let a = u8x8::from([1, 2, 3, 4, 5, 6, 7, 0xff]); - let b = u8x8::from([30, 1, 1, 1, 34, 0xff, 36, 37]); - let r: u8x8 = unsafe { transmute(vqadd_u8(transmute(a), transmute(b))) }; - let e = u8x8::from([31, 3, 4, 5, 39, 0xff, 43, 0xff]); - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vmaxq_f32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.fmax.v4f32 - let a = f32x4::from([0., -1., 2., -3.]); - let b = f32x4::from([-4., 5., -6., 7.]); - let e = f32x4::from([0., 5., 2., 7.]); - let r: f32x4 = unsafe { transmute(vmaxq_f32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vminq_f32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.fmin.v4f32 - let a = f32x4::from([0., -1., 2., -3.]); - let b = f32x4::from([-4., 5., -6., 7.]); - let e = f32x4::from([-4., -1., -6., -3.]); - let r: f32x4 = unsafe { transmute(vminq_f32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vaddvq_f32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.faddv.f32.v4f32 - let a = f32x4::from([0., 1., 2., 3.]); - let e = 6f32; - let r = unsafe { vaddvq_f32(transmute(a)) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vrndnq_f32() { - // llvm intrinsic: llvm.roundeven.v4f32 - let a = f32x4::from([0.1, -1.9, 4.5, 5.5]); - let e = f32x4::from([0., -2., 4., 6.]); - let r: f32x4 = unsafe { transmute(vrndnq_f32(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "aes")] -unsafe fn test_vaeseq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.aese - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = u8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let e = u8x16::from([ - 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, 0xca, - 0xca, - ]); - let r: u8x16 = unsafe { transmute(vaeseq_u8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "aes")] -unsafe fn test_vaesdq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.aesd - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = u8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let e = u8x16::from([ - 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, 0x7c, - 0x7c, - ]); - let r: u8x16 = unsafe { transmute(vaesdq_u8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "aes")] -unsafe fn test_vaesmcq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.aesmc - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let e = u8x16::from([2, 7, 0, 5, 6, 3, 4, 1, 10, 15, 8, 13, 14, 11, 12, 9]); - let r: u8x16 = unsafe { transmute(vaesmcq_u8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "aes")] -unsafe fn test_vaesimcq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.aesimc - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let e = u8x16::from([10, 15, 8, 13, 14, 11, 12, 9, 2, 7, 0, 5, 6, 3, 4, 1]); - let r: u8x16 = unsafe { transmute(vaesimcq_u8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha1cq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1c - let a = u32x4::from([0, 1, 2, 3]); - let b = 8; - let c = u32x4::from([4, 5, 6, 7]); - let e = u32x4::from([0x40072911, 0x40003948, 0x80000072, 0x80000003]); - let r: u32x4 = unsafe { transmute(vsha1cq_u32(transmute(a), b, transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -fn test_vsha1h_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1h - let a = 8; - let e = 0x00000002; - let r = vsha1h_u32(a); - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha1mq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1m - let a = u32x4::from([0, 1, 2, 3]); - let b = 8; - let c = u32x4::from([4, 5, 6, 7]); - let e = u32x4::from([0x4007a107, 0x00003d08, 0x0000007a, 0xc0000003]); - let r: u32x4 = unsafe { transmute(vsha1mq_u32(transmute(a), b, transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha1pq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1p - let a = u32x4::from([0, 1, 2, 3]); - let b = 8; - let c = u32x4::from([4, 5, 6, 7]); - let e = u32x4::from([0x80062d18, 0x4000315c, 0x90000062, 0x00000003]); - let r: u32x4 = unsafe { transmute(vsha1pq_u32(transmute(a), b, transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha1su0q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1su0 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([0x0000000a, 0x0000000b, 0x0000000c, 0x0000000d]); - let r: u32x4 = unsafe { transmute(vsha1su0q_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha1su1q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha1su1 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let e = u32x4::from([0x0000000a, 0x0000000e, 0x0000000a, 0x00000012]); - let r: u32x4 = unsafe { transmute(vsha1su1q_u32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha256hq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha256h - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([0x27bb4ae0, 0xd8f61f7c, 0xb7c1ecdc, 0x10800215]); - let r: u32x4 = unsafe { transmute(vsha256hq_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha256h2q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha256h2 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([0x6989ee0d, 0x4b055920, 0x52800a12, 0x00000014]); - let r: u32x4 = unsafe { transmute(vsha256h2q_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha256su0q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha256su0 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let e = u32x4::from([0x02004000, 0x04008001, 0x0600c002, 0x08010003]); - let r: u32x4 = unsafe { transmute(vsha256su0q_u32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha2")] -unsafe fn test_vsha256su1q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha256su1 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([0x00044005, 0x0004e007, 0xa802211b, 0xec036145]); - let r: u32x4 = unsafe { transmute(vsha256su1q_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vsha512hq_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha512h - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let c = u64x2::from([4, 5]); - let e = u64x2::from([0x001c805053800005, 0x0015400002800003]); - let r: u64x2 = unsafe { transmute(vsha512hq_u64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vsha512h2q_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha512h2 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let c = u64x2::from([4, 5]); - let e = u64x2::from([0x401000514a000405, 0x0000004108000005]); - let r: u64x2 = unsafe { transmute(vsha512h2q_u64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vsha512su0q_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha512su0 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let e = u64x2::from([0x8100000000000000, 0x0200000000000002]); - let r: u64x2 = unsafe { transmute(vsha512su0q_u64(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vsha512su1q_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.sha512su1 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let c = u64x2::from([4, 5]); - let e = u64x2::from([0x0000400000000014, 0x000060000000001e]); - let r: u64x2 = unsafe { transmute(vsha512su1q_u64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_s8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3s.v16i8 - let a = i8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = i8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let c = i8x16::from([32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]); - let e = i8x16::from([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]); - let r: i8x16 = unsafe { transmute(veor3q_s8(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3s.v8i16 - let a = i16x8::from([0, 1, 2, 3, 4, 5, 6, 7]); - let b = i16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let c = i16x8::from([16, 17, 18, 19, 20, 21, 22, 23]); - let e = i16x8::from([24, 25, 26, 27, 28, 29, 30, 31]); - let r: i16x8 = unsafe { transmute(veor3q_s16(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3s.v4i32 - let a = i32x4::from([0, 1, 2, 3]); - let b = i32x4::from([4, 5, 6, 7]); - let c = i32x4::from([8, 9, 10, 11]); - let e = i32x4::from([12, 13, 14, 15]); - let r: i32x4 = unsafe { transmute(veor3q_s32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_s64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3s.v2i64 - let a = i64x2::from([0, 1]); - let b = i64x2::from([2, 3]); - let c = i64x2::from([4, 5]); - let e = i64x2::from([6, 7]); - let r: i64x2 = unsafe { transmute(veor3q_s64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3u.v16i8 - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = u8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let c = u8x16::from([32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]); - let e = u8x16::from([48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63]); - let r: u8x16 = unsafe { transmute(veor3q_u8(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_u16() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3u.v8i16 - let a = u16x8::from([0, 1, 2, 3, 4, 5, 6, 7]); - let b = u16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let c = u16x8::from([16, 17, 18, 19, 20, 21, 22, 23]); - let e = u16x8::from([24, 25, 26, 27, 28, 29, 30, 31]); - let r: u16x8 = unsafe { transmute(veor3q_u16(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3u.v4i32 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([12, 13, 14, 15]); - let r: u32x4 = unsafe { transmute(veor3q_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_veor3q_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.eor3u.v2i64 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let c = u64x2::from([4, 5]); - let e = u64x2::from([6, 7]); - let r: u64x2 = unsafe { transmute(veor3q_u64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_s8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxs.v16i8 - let a = i8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = i8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let c = i8x16::from([32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]); - let e = i8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let r: i8x16 = unsafe { transmute(vbcaxq_s8(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxs.v8i16 - let a = i16x8::from([0, 1, 2, 3, 4, 5, 6, 7]); - let b = i16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let c = i16x8::from([16, 17, 18, 19, 20, 21, 22, 23]); - let e = i16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let r: i16x8 = unsafe { transmute(vbcaxq_s16(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxs.v4i32 - let a = i32x4::from([0, 1, 2, 3]); - let b = i32x4::from([4, 5, 6, 7]); - let c = i32x4::from([8, 9, 10, 11]); - let e = i32x4::from([4, 5, 6, 7]); - let r: i32x4 = unsafe { transmute(vbcaxq_s32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_s64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxs.v2i64 - let a = i64x2::from([0, 1]); - let b = i64x2::from([2, 3]); - let c = i64x2::from([4, 5]); - let e = i64x2::from([2, 3]); - let r: i64x2 = unsafe { transmute(vbcaxq_s64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxu.v16i8 - let a = u8x16::from([0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]); - let b = u8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let c = u8x16::from([32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47]); - let e = u8x16::from([16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31]); - let r: u8x16 = unsafe { transmute(vbcaxq_u8(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_u16() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxu.v8i16 - let a = u16x8::from([0, 1, 2, 3, 4, 5, 6, 7]); - let b = u16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let c = u16x8::from([16, 17, 18, 19, 20, 21, 22, 23]); - let e = u16x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let r: u16x8 = unsafe { transmute(vbcaxq_u16(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxu.v4i32 - let a = u32x4::from([0, 1, 2, 3]); - let b = u32x4::from([4, 5, 6, 7]); - let c = u32x4::from([8, 9, 10, 11]); - let e = u32x4::from([4, 5, 6, 7]); - let r: u32x4 = unsafe { transmute(vbcaxq_u32(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vbcaxq_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.bcaxu.v2i64 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let c = u64x2::from([4, 5]); - let e = u64x2::from([2, 3]); - let r: u64x2 = unsafe { transmute(vbcaxq_u64(transmute(a), transmute(b), transmute(c))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vrax1q_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.rax1 - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let e = u64x2::from([4, 7]); - let r: u64x2 = unsafe { transmute(vrax1q_u64(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "sha3")] -unsafe fn test_vxarq_u64() { - // AArch64 llvm intrinsic: llvm.aarch64.crypto.xar - let a = u64x2::from([0, 1]); - let b = u64x2::from([2, 3]); - let e = u64x2::from([4, 4]); - let r: u64x2 = unsafe { transmute(vxarq_u64::<63>(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -#[target_feature(enable = "aes")] -fn test_vmull_p64() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.pmull64 - let a: u64 = 3; - let b: u64 = 6; - let e: u128 = 10; - let r: u128 = vmull_p64(a, b); - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vmull_p8() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.pmull.v8i16 - let a = u8x8::from([0, 1, 2, 3, 4, 5, 6, 7]); - let b = u8x8::from([8, 9, 10, 11, 12, 13, 14, 15]); - let e = u16x8::from([0x0000, 0x0009, 0x0014, 0x001d, 0x0030, 0x0039, 0x0024, 0x002d]); - let r: u16x8 = unsafe { transmute(vmull_p8(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqdmulh_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.sqdmulh.v4i16 - let a = i16x4::from([1, 2, 4, 8]); - let b = i16x4::from([16384, 16384, 16384, 16384]); - let e = i16x4::from([0, 1, 2, 4]); - let r: i16x4 = unsafe { transmute(vqdmulh_s16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqdmulh_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.sqdmulh.v2i32 - let a = i32x2::from([1, 2]); - let b = i32x2::from([1073741824, 1073741824]); - let e = i32x2::from([0, 1]); - let r: i32x2 = unsafe { transmute(vqdmulh_s32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqdmulhq_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.sqdmulh.v8i16 - let a = i16x8::from([1, 2, 4, 8, 16, 32, 64, 128]); - let b = i16x8::from([16384, 16384, 16384, 16384, 16384, 16384, 16384, 16384]); - let e = i16x8::from([0, 1, 2, 4, 8, 16, 32, 64]); - let r: i16x8 = unsafe { transmute(vqdmulhq_s16(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vqdmulhq_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.sqdmulh.v4i32 - let a = i32x4::from([1, 2, 4, 8]); - let b = i32x4::from([1073741824, 1073741824, 1073741824, 1073741824]); - let e = i32x4::from([0, 1, 2, 4]); - let r: i32x4 = unsafe { transmute(vqdmulhq_s32(transmute(a), transmute(b))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_s8() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v4i16.v8i8 - let a = i8x8::from([1, 2, 3, 4, -5, -6, -7, -8]); - let e = i16x4::from([3, 7, -11, -15]); - let r: i16x4 = unsafe { transmute(vpaddl_s8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v2i32.v4i16 - let a = i16x4::from([1, 2, -3, -4]); - let e = i32x2::from([3, -7]); - let r: i32x2 = unsafe { transmute(vpaddl_s16(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v1i64.v2i32 - let a = i32x2::from([1, -2]); - let e = i64x1::from([-1]); - let r: i64x1 = unsafe { transmute(vpaddl_s32(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_s8() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v8i16.v16i8 - let a = i8x16::from([1, 2, 3, 4, 5, 6, 7, 8, -9, -10, -11, -12, -13, -14, -15, -16]); - let e = i16x8::from([3, 7, 11, 15, -19, -23, -27, -31]); - let r: i16x8 = unsafe { transmute(vpaddlq_s8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_s16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v4i32.v8i16 - let a = i16x8::from([1, 2, 3, 4, -5, -6, -7, -8]); - let e = i32x4::from([3, 7, -11, -15]); - let r: i32x4 = unsafe { transmute(vpaddlq_s16(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_s32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.saddlp.v2i64.v4i32 - let a = i32x4::from([1, 2, -3, -4]); - let e = i64x2::from([3, -7]); - let r: i64x2 = unsafe { transmute(vpaddlq_s32(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v4i16.v8i8 - let a = u8x8::from([255, 254, 253, 252, 251, 250, 249, 248]); - let e = u16x4::from([509, 505, 501, 497]); - let r: u16x4 = unsafe { transmute(vpaddl_u8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_u16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v2i32.v4i16 - let a = u16x4::from([65535, 65534, 65533, 65532]); - let e = u32x2::from([131069, 131065]); - let r: u32x2 = unsafe { transmute(vpaddl_u16(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddl_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v1i64.v2i32 - let a = u32x2::from([4294967295, 4294967294]); - let e = u64x1::from([8589934589]); - let r: u64x1 = unsafe { transmute(vpaddl_u32(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_u8() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v8i16.v16i8 - let a = u8x16::from([ - 255, 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, 240, - ]); - let e = u16x8::from([509, 505, 501, 497, 493, 489, 485, 481]); - let r: u16x8 = unsafe { transmute(vpaddlq_u8(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_u16() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v4i32.v8i16 - let a = u16x8::from([65535, 65534, 65533, 65532, 65531, 65530, 65529, 65528]); - let e = u32x4::from([131069, 131065, 131061, 131057]); - let r: u32x4 = unsafe { transmute(vpaddlq_u16(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -unsafe fn test_vpaddlq_u32() { - // AArch64 llvm intrinsic: llvm.aarch64.neon.uaddlp.v2i64.v4i32 - let a = u32x4::from([4294967295, 4294967294, 4294967293, 4294967292]); - let e = u64x2::from([8589934589, 8589934585]); - let r: u64x2 = unsafe { transmute(vpaddlq_u32(transmute(a))) }; - assert_eq!(r, e); -} - -#[cfg(target_arch = "aarch64")] -fn main() { - unsafe { - test_vpmin_s8(); - test_vpmin_s16(); - test_vpmin_s32(); - test_vpmin_u8(); - test_vpmin_u16(); - test_vpmin_u32(); - test_vpmin_f32(); - test_vpmax_s8(); - test_vpmax_s16(); - test_vpmax_s32(); - test_vpmax_u8(); - test_vpmax_u16(); - test_vpmax_u32(); - test_vpmax_f32(); - - test_vpadd_s16(); - test_vpadd_s32(); - test_vpadd_s8(); - test_vpadd_u16(); - test_vpadd_u32(); - test_vpadd_u8(); - - test_vqsub_u8(); - test_vqadd_u8(); - - test_vmaxq_f32(); - test_vminq_f32(); - test_vaddvq_f32(); - test_vrndnq_f32(); - - test_crc32(); - - test_vaeseq_u8(); - test_vaesdq_u8(); - test_vaesmcq_u8(); - test_vaesimcq_u8(); - - test_vsha1cq_u32(); - test_vsha1h_u32(); - test_vsha1mq_u32(); - test_vsha1pq_u32(); - test_vsha1su0q_u32(); - test_vsha1su1q_u32(); - - test_vsha256hq_u32(); - test_vsha256h2q_u32(); - test_vsha256su0q_u32(); - test_vsha256su1q_u32(); - - if std::arch::is_aarch64_feature_detected!("sha3") { - test_vsha512hq_u64(); - test_vsha512h2q_u64(); - test_vsha512su0q_u64(); - test_vsha512su1q_u64(); - - test_veor3q_s8(); - test_veor3q_s16(); - test_veor3q_s32(); - test_veor3q_s64(); - test_veor3q_u8(); - test_veor3q_u16(); - test_veor3q_u32(); - test_veor3q_u64(); - - test_vbcaxq_s8(); - test_vbcaxq_s16(); - test_vbcaxq_s32(); - test_vbcaxq_s64(); - test_vbcaxq_u8(); - test_vbcaxq_u16(); - test_vbcaxq_u32(); - test_vbcaxq_u64(); - - test_vrax1q_u64(); - test_vxarq_u64(); - } - - test_vmull_p64(); - test_vmull_p8(); - - test_vqdmulh_s16(); - test_vqdmulh_s32(); - test_vqdmulhq_s16(); - test_vqdmulhq_s32(); - - test_vpaddl_s8(); - test_vpaddl_s16(); - test_vpaddl_s32(); - test_vpaddlq_s8(); - test_vpaddlq_s16(); - test_vpaddlq_s32(); - - test_vpaddl_u8(); - test_vpaddl_u16(); - test_vpaddl_u32(); - test_vpaddlq_u8(); - test_vpaddlq_u16(); - test_vpaddlq_u32(); - } -} - -#[cfg(not(target_arch = "aarch64"))] -fn main() {} diff --git a/compiler/rustc_codegen_cranelift/patches/0001-stdarch-Disable-SVE.patch b/compiler/rustc_codegen_cranelift/patches/0001-stdarch-Disable-SVE.patch new file mode 100644 index 0000000000000..e7038699bc998 --- /dev/null +++ b/compiler/rustc_codegen_cranelift/patches/0001-stdarch-Disable-SVE.patch @@ -0,0 +1,51 @@ +From e90274ba5bc4bee03a24e8c134ea223497c3a46b Mon Sep 17 00:00:00 2001 +From: Cathal Mullan +Date: Sat, 13 Jun 2026 20:32:02 +0100 +Subject: [PATCH] Disable SVE + +Cranelift doesn't support scalable vectors. +--- + crates/core_arch/src/aarch64/mod.rs | 8 ++++---- + crates/intrinsic-test/src/arm/mod.rs | 1 + + 2 files changed, 5 insertions(+), 4 deletions(-) + +diff --git a/crates/core_arch/src/aarch64/mod.rs b/crates/core_arch/src/aarch64/mod.rs +index 34fa5c8..a870e31 100644 +--- a/crates/core_arch/src/aarch64/mod.rs ++++ b/crates/core_arch/src/aarch64/mod.rs +@@ -19,16 +19,16 @@ mod neon; + pub use self::neon::*; + + // The rest of `core_arch::aarch64` is available on `arm64ec` but SVE is not supported on `arm64ec`. +-#[cfg(any(all(target_arch = "aarch64", target_endian = "little"), doc))] ++#[cfg(all(not(test), any(all(target_arch = "aarch64", target_endian = "little"), doc)))] + mod sve; +-#[cfg(any(all(target_arch = "aarch64", target_endian = "little"), doc))] ++#[cfg(all(not(test), any(all(target_arch = "aarch64", target_endian = "little"), doc)))] + #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] + pub use self::sve::*; + + // The rest of `core_arch::aarch64` is available on `arm64ec` but SVE is not supported on `arm64ec`. +-#[cfg(any(all(target_arch = "aarch64", target_endian = "little"), doc))] ++#[cfg(all(not(test), any(all(target_arch = "aarch64", target_endian = "little"), doc)))] + mod sve2; +-#[cfg(any(all(target_arch = "aarch64", target_endian = "little"), doc))] ++#[cfg(all(not(test), any(all(target_arch = "aarch64", target_endian = "little"), doc)))] + #[unstable(feature = "stdarch_aarch64_sve", issue = "145052")] + pub use self::sve2::*; + +diff --git a/crates/intrinsic-test/src/arm/mod.rs b/crates/intrinsic-test/src/arm/mod.rs +index 9c2d0f3..3825f41 100644 +--- a/crates/intrinsic-test/src/arm/mod.rs ++++ b/crates/intrinsic-test/src/arm/mod.rs +@@ -66,6 +66,7 @@ impl SupportedArchitecture for Arm { + + let intrinsics = intrinsics + .into_iter() ++ .filter(|i| i.extension != "SVE" && i.extension != "SVE2") + // Skip intrinsics that don't return a value. + .filter(|i| i.results.kind() != TypeKind::Void) + // Skip bfloat intrinsics - not currently supported +-- +2.54.0 + From 140373788f0130353a7b49238ccd14c59b8eb424 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Mon, 21 Sep 2026 14:20:15 -0400 Subject: [PATCH 0578/1309] Skip redundant storage-conflict updates during coroutine layout --- compiler/rustc_mir_transform/src/coroutine/layout.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index a06ae343123d1..1b9ced7fc05b9 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -252,6 +252,7 @@ fn compute_storage_conflicts<'mir, 'tcx>( saved_locals, local_conflicts: BitMatrix::from_row_n(&ineligible_locals, body.local_decls.len()), eligible_storage_live: DenseBitSet::new_empty(body.local_decls.len()), + last_recorded_storage_live: DenseBitSet::new_empty(body.local_decls.len()), }; // Filter out: @@ -296,6 +297,7 @@ struct StorageConflictVisitor<'a> { local_conflicts: BitMatrix, // We keep this bitset as a buffer to avoid reallocating memory. eligible_storage_live: DenseBitSet, + last_recorded_storage_live: DenseBitSet, } impl<'a, 'tcx> ResultsVisitor<'tcx, MaybeRequiresStorage> for StorageConflictVisitor<'a> { @@ -323,9 +325,14 @@ impl StorageConflictVisitor<'_> { self.eligible_storage_live.clone_from(state); self.eligible_storage_live.intersect(&**self.saved_locals); + if self.last_recorded_storage_live.superset(&self.eligible_storage_live) { + return; + } + for local in self.eligible_storage_live.iter() { self.local_conflicts.union_row_with(&self.eligible_storage_live, local); } + std::mem::swap(&mut self.last_recorded_storage_live, &mut self.eligible_storage_live); } } From 796ee3b852d8a01cd01dd321fd7e5e86f2655935 Mon Sep 17 00:00:00 2001 From: asquared31415 <34665709+asquared31415@users.noreply.github.com> Date: Sun, 20 Sep 2026 02:41:53 +0000 Subject: [PATCH 0579/1309] Make CovariantUnsafeCell actually covariant --- compiler/rustc_hir_analysis/src/variance/solve.rs | 13 ++++++++++++- library/core/src/cell/covariant_unsafe_cell.rs | 11 ----------- .../variance/covariant_unsafe_cell_is_covariant.rs | 14 ++++++++++++++ 3 files changed, 26 insertions(+), 12 deletions(-) create mode 100644 tests/ui/variance/covariant_unsafe_cell_is_covariant.rs diff --git a/compiler/rustc_hir_analysis/src/variance/solve.rs b/compiler/rustc_hir_analysis/src/variance/solve.rs index eef26d783e7b7..06e8bc84e4474 100644 --- a/compiler/rustc_hir_analysis/src/variance/solve.rs +++ b/compiler/rustc_hir_analysis/src/variance/solve.rs @@ -5,6 +5,7 @@ //! optimal solution to the constraints. The final variance for each //! inferred is then written into the `variance_map` in the tcx. +use rustc_data_structures::fx::FxHashSet; use rustc_hir::def_id::DefIdMap; use rustc_middle::ty; use tracing::debug; @@ -43,16 +44,26 @@ struct SolveContext<'a, 'tcx> { pub(crate) fn solve_constraints<'tcx>( constraints_cx: ConstraintContext<'_, 'tcx>, ) -> ty::CrateVariancesMap<'tcx> { - let ConstraintContext { terms_cx, constraints, .. } = constraints_cx; + let ConstraintContext { terms_cx, mut constraints, .. } = constraints_cx; + let mut overridden_inferreds = FxHashSet::default(); let mut solutions = vec![ty::Bivariant; terms_cx.inferred_terms.len()]; + // prime the solutions for certain lang items which have hard-coded variance for (id, variances) in &terms_cx.lang_items { let InferredIndex(start) = terms_cx.inferred_starts[id]; for (i, &variance) in variances.iter().enumerate() { solutions[start + i] = variance; + overridden_inferreds.insert(start + i); } } + // ensure the solutions for overridden inferreds are never constrained by anything else + if !overridden_inferreds.is_empty() { + constraints.retain(|Constraint { inferred: InferredIndex(inferred), .. }| { + !overridden_inferreds.contains(inferred) + }); + } + let mut solutions_cx = SolveContext { terms_cx, constraints, solutions }; solutions_cx.solve(); let variances = solutions_cx.create_map(); diff --git a/library/core/src/cell/covariant_unsafe_cell.rs b/library/core/src/cell/covariant_unsafe_cell.rs index 3876cc404cd2e..11ac9b58bbb90 100644 --- a/library/core/src/cell/covariant_unsafe_cell.rs +++ b/library/core/src/cell/covariant_unsafe_cell.rs @@ -170,14 +170,3 @@ impl fmt::Debug for CovariantUnsafeCell { f.debug_struct("CovariantUnsafeCell").finish_non_exhaustive() } } - -#[cfg(test)] -mod tests { - use super::*; - - fn _covarience<'short, 'long: 'short>( - x: CovariantUnsafeCell<&'long ()>, - ) -> CovariantUnsafeCell<&'short ()> { - x - } -} diff --git a/tests/ui/variance/covariant_unsafe_cell_is_covariant.rs b/tests/ui/variance/covariant_unsafe_cell_is_covariant.rs new file mode 100644 index 0000000000000..7664e09a851dd --- /dev/null +++ b/tests/ui/variance/covariant_unsafe_cell_is_covariant.rs @@ -0,0 +1,14 @@ +//@ build-pass + +#![feature(covariant_unsafe_cell)] + +use std::cell::CovariantUnsafeCell; + +/// this function compiling ensures that CovariantUnsafeCell is actually covariant +fn _assert_covariance<'short, 'long: 'short>( + x: CovariantUnsafeCell<&'long ()>, +) -> CovariantUnsafeCell<&'short ()> { + x +} + +fn main () {} From f5d4c29121b00b4cbbb1b9483d818e6dafaa0cbd Mon Sep 17 00:00:00 2001 From: Frank Steffahn Date: Sun, 20 Sep 2026 18:24:48 +0200 Subject: [PATCH 0580/1309] Add variance dump for overridden lang items to UI test --- tests/ui/variance/variance-types.rs | 17 ++++++++++++++++- tests/ui/variance/variance-types.stderr | 20 +++++++++++++++++++- 2 files changed, 35 insertions(+), 2 deletions(-) diff --git a/tests/ui/variance/variance-types.rs b/tests/ui/variance/variance-types.rs index 3b3ac929a2633..f7e8625bce62b 100644 --- a/tests/ui/variance/variance-types.rs +++ b/tests/ui/variance/variance-types.rs @@ -1,5 +1,5 @@ -#![allow(dead_code)] #![feature(rustc_attrs)] +#![feature(covariant_unsafe_cell)] use std::cell::Cell; @@ -38,4 +38,19 @@ enum Enum { //~ ERROR [A: +, B: -, C: o] Zed(Covariant,Contravariant) } +#[rustc_dump_variances] +struct PhantomDataIsCovariant { //~ ERROR [A: +] + t: std::marker::PhantomData +} + +#[rustc_dump_variances] +struct UnsafeCellIsInvariant { //~ ERROR [A: o] + t: std::cell::UnsafeCell +} + +#[rustc_dump_variances] +struct CovariantUnsafeCellIsCovariant { //~ ERROR [A: +] + t: std::cell::CovariantUnsafeCell +} + pub fn main() { } diff --git a/tests/ui/variance/variance-types.stderr b/tests/ui/variance/variance-types.stderr index f2a6794942553..e66f4bacc15e4 100644 --- a/tests/ui/variance/variance-types.stderr +++ b/tests/ui/variance/variance-types.stderr @@ -34,5 +34,23 @@ error: [A: +, B: -, C: o] LL | enum Enum { | ^^^^^^^^^^^^^^^^ -error: aborting due to 6 previous errors +error: [A: +] + --> $DIR/variance-types.rs:42:1 + | +LL | struct PhantomDataIsCovariant { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [A: o] + --> $DIR/variance-types.rs:47:1 + | +LL | struct UnsafeCellIsInvariant { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: [A: +] + --> $DIR/variance-types.rs:52:1 + | +LL | struct CovariantUnsafeCellIsCovariant { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 9 previous errors From 41fede0c0b7081dc7c6c973b170142ce8e9674cf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Sun, 20 Sep 2026 03:02:32 +0000 Subject: [PATCH 0581/1309] Tweak dyn compatibility error when pointing at receiver Account for receivers with arbitrary self types to suggest idiomatic code. ``` error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21 | LL | fn fetcher() -> Box { | ^^^^^^^^^^^ `Fetcher` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:16 | LL | pub trait Fetcher: Send + Sync { | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> | ^^^^^^^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on help: consider changing method `get`'s `self` parameter to be `&self` | LL - fn get<'a>(self: &'a Box) -> Pin> + 'a>> LL + fn get<'a>(&'a self) -> Pin> + 'a>> | ``` Instead of ``` help: consider changing method `get`'s `self` parameter to be `&self` | LL - fn get<'a>(self: &'a Box) -> Pin> + 'a>> LL + fn get<'a>(self: &Self) -> Pin> + 'a>> | ``` --- compiler/rustc_middle/src/traits/mod.rs | 33 +++++++++-------- .../src/traits/dyn_compatibility.rs | 36 +++++++++++++++---- ...ble-receiver-and-wc-references-Self.stderr | 24 +++++++------ ...nders-bare-trait-object-next-solver.stderr | 12 ++++--- ...gate-dispatch-from-dyn-missing-impl.stderr | 12 ++++--- ...bitrary-self-types-dyn-incompatible.stderr | 12 ++++--- ...yn-incompatible-that-does-not-deref.stderr | 12 ++++--- ...patible-trait-should-use-where-sized.fixed | 2 +- ...atible-trait-should-use-where-sized.stderr | 4 +-- .../maybe-bounds-in-dyn-traits.stderr | 8 +++-- 10 files changed, 98 insertions(+), 57 deletions(-) diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs index 8dccead861de7..5520b059f5678 100644 --- a/compiler/rustc_middle/src/traits/mod.rs +++ b/compiler/rustc_middle/src/traits/mod.rs @@ -21,7 +21,7 @@ use rustc_macros::{ Decodable, Encodable, StableHash, TyDecodable, TyEncodable, TypeFoldable, TypeVisitable, }; use rustc_span::def_id::{CRATE_DEF_ID, LocalDefId}; -use rustc_span::{DUMMY_SP, Span, Symbol}; +use rustc_span::{DUMMY_SP, Span, Symbol, sym}; use smallvec::{SmallVec, smallvec}; use thin_vec::ThinVec; @@ -870,8 +870,8 @@ impl DynCompatibilityViolation { add_self_sugg: add_self_sugg.clone(), make_sized_sugg: make_sized_sugg.clone(), }, - Self::Method(name, MethodViolation::UndispatchableReceiver(Some(span)), _) => { - DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span) + Self::Method(name, MethodViolation::UndispatchableReceiver(Some((span, lt))), _) => { + DynCompatibilityViolationSolution::ChangeToRefSelf(*name, *span, *lt) } Self::Method(name, ..) | Self::AssocConst(name, ..) | Self::GenericAssocTy(name, _) => { DynCompatibilityViolationSolution::MoveToAnotherTrait(*name) @@ -909,7 +909,7 @@ pub enum DynCompatibilityViolationSolution { add_self_sugg: (String, Span), make_sized_sugg: (String, Span), }, - ChangeToRefSelf(Symbol, Span), + ChangeToRefSelf(Symbol, Span, Symbol), MoveToAnotherTrait(Symbol), } @@ -922,30 +922,30 @@ impl DynCompatibilityViolationSolution { add_self_sugg, make_sized_sugg, } => { - err.span_suggestion( + err.span_suggestion_verbose( add_self_sugg.1, format!( - "consider turning `{name}` into a method by giving it a `&self` \ - argument, so that it is accessible through the trait object's vtable" + "consider turning `{name}` into a method by giving it a `&self` argument, \ + so that it is accessible through the trait object's vtable", ), add_self_sugg.0, Applicability::MaybeIncorrect, ); - err.span_suggestion( + err.span_suggestion_verbose( make_sized_sugg.1, format!( - "alternatively, consider constraining `{name}` so it is explicitly \ - marked as not applying to trait objects" + "alternatively, consider constraining `{name}` so it is explicitly marked \ + as not applying to trait objects", ), make_sized_sugg.0, Applicability::MaybeIncorrect, ); } - DynCompatibilityViolationSolution::ChangeToRefSelf(name, span) => { - err.span_suggestion( + DynCompatibilityViolationSolution::ChangeToRefSelf(name, span, lt) => { + err.span_suggestion_verbose( span, format!("consider changing method `{name}`'s `self` parameter to be `&self`"), - "&Self", + format!("&{lt}{}self", if lt != sym::empty { " " } else { "" }), Applicability::MachineApplicable, ); } @@ -983,8 +983,11 @@ pub enum MethodViolation { /// e.g., `fn (mut ap: ...)` CVariadic, - /// the method's receiver (`self` argument) can't be dispatched on - UndispatchableReceiver(Option), + /// The method's receiver (`self` argument) can't be dispatched on + /// + /// The `Span` points at the receiver. The `Symbol` is the lifetime's name `'a` when we have + /// Arbitrary Self Types like `self: &'a ()`. + UndispatchableReceiver(Option<(Span, Symbol)>), } /// Reasons an associated const might not be dyn compatible. diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs index f2b221c59ee95..e964c09420b0e 100644 --- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs +++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs @@ -16,7 +16,7 @@ use rustc_middle::ty::{ TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, Upcast, elaborate, }; -use rustc_span::{DUMMY_SP, Span}; +use rustc_span::{DUMMY_SP, Span, kw, sym}; use smallvec::SmallVec; use tracing::{debug, instrument}; @@ -403,7 +403,7 @@ pub fn dyn_compatibility_violations_for_assoc_item( // Get an accurate span depending on the violation. let span = match (&v, node) { (MethodViolation::ReferencesSelfInput(Some(span)), _) => *span, - (MethodViolation::UndispatchableReceiver(Some(span)), _) => *span, + (MethodViolation::UndispatchableReceiver(Some((span, _))), _) => *span, (MethodViolation::ReferencesImplTraitInTrait(span), _) => *span, (MethodViolation::ReferencesSelfOutput, Some(node)) => { node.fn_decl().map_or(item.ident(tcx).span, |decl| decl.output.span()) @@ -519,16 +519,40 @@ fn virtual_call_violations_for_method<'tcx>( // `Receiver: Unsize dyn Trait]>`. if receiver_ty != tcx.types.self_param { if !receiver_is_dispatchable(tcx, method, receiver_ty) { - let span = if let Some(hir::Node::TraitItem(hir::TraitItem { - kind: hir::TraitItemKind::Fn(sig, _), + let span_n_lt = if let Some(hir::Node::TraitItem(hir::TraitItem { + kind: hir::TraitItemKind::Fn(sig, trait_fn), .. })) = tcx.hir_get_if_local(method.def_id).as_ref() { - Some(sig.decl.inputs[0].span) + // If we have `self: &'a Ty`, get `'a`, so that we can suggest `&'a self`. + let lt = match sig.decl.inputs[0].kind { + hir::TyKind::Ref(lt, _) if lt.ident.name == kw::UnderscoreLifetime => { + sym::empty + } + hir::TyKind::Ref(lt, _) => lt.ident.name, + _ => sym::empty, + }; + // Get the `Span` for all of `self: Ty`, not just `Ty`. + match trait_fn { + hir::TraitFn::Required([Some(name), ..]) + if name.span.eq_ctxt(sig.decl.inputs[0].span) => + { + Some(name.span.to(sig.decl.inputs[0].span)) + } + hir::TraitFn::Provided(body_id) + if let body = tcx.hir_body(*body_id) + && let Some(p) = body.params.get(0) + && p.span.eq_ctxt(p.ty_span) => + { + Some(p.span.to(p.ty_span)) + } + _ => None, + } + .map(|sp| (sp, lt)) } else { None }; - errors.push(MethodViolation::UndispatchableReceiver(span)); + errors.push(MethodViolation::UndispatchableReceiver(span_n_lt)); } else { // We confirm that the `receiver_is_dispatchable` is accurate later, // see `check_receiver_correct`. It should be kept in sync with this code. diff --git a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr index 867a719e2ebfd..8048ff3e9c0c3 100644 --- a/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr +++ b/tests/ui/dyn-compatibility/undispatchable-receiver-and-wc-references-Self.stderr @@ -1,38 +1,42 @@ error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:19:21 | -LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> - | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` -... LL | fn fetcher() -> Box { | ^^^^^^^^^^^ `Fetcher` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:16 | LL | pub trait Fetcher: Send + Sync { | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> - | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on + | ^^^^^^^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on +help: consider changing method `get`'s `self` parameter to be `&self` + | +LL - fn get<'a>(self: &'a Box) -> Pin> + 'a>> +LL + fn get<'a>(&'a self) -> Pin> + 'a>> + | error[E0038]: the trait `Fetcher` is not dyn compatible --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:25:19 | -LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> - | ------------- help: consider changing method `get`'s `self` parameter to be `&self`: `&Self` -... LL | let fetcher = fetcher(); | ^^^^^^^^^ `Fetcher` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:22 + --> $DIR/undispatchable-receiver-and-wc-references-Self.rs:11:16 | LL | pub trait Fetcher: Send + Sync { | ------- this trait is not dyn compatible... LL | fn get<'a>(self: &'a Box) -> Pin> + 'a>> - | ^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on + | ^^^^^^^^^^^^^^^^^^^ ...because method `get`'s `self` parameter cannot be dispatched on +help: consider changing method `get`'s `self` parameter to be `&self` + | +LL - fn get<'a>(self: &'a Box) -> Pin> + 'a>> +LL + fn get<'a>(&'a self) -> Pin> + 'a>> + | error: aborting due to 2 previous errors diff --git a/tests/ui/dyn-compatibility/unsafe-binders-bare-trait-object-next-solver.stderr b/tests/ui/dyn-compatibility/unsafe-binders-bare-trait-object-next-solver.stderr index 6ca8ec6bd1a5a..e333fccd69f5d 100644 --- a/tests/ui/dyn-compatibility/unsafe-binders-bare-trait-object-next-solver.stderr +++ b/tests/ui/dyn-compatibility/unsafe-binders-bare-trait-object-next-solver.stderr @@ -32,20 +32,22 @@ LL | fn method(self: &unsafe<'ops> &'a dyn Bar) {} error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:17:13 | -LL | fn method(self: &unsafe<'ops> &'a Bar) {} - | --------------------- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self` -... LL | fn test(x: &dyn Foo) { | ^^^^^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:10:21 + --> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:10:15 | LL | trait Foo: Deref &'a dyn Bar> { | --- this trait is not dyn compatible... LL | fn method(self: &unsafe<'ops> &'a Bar) {} - | ^^^^^^^^^^^^^^^^^^^^^ ...because method `method`'s `self` parameter cannot be dispatched on + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...because method `method`'s `self` parameter cannot be dispatched on +help: consider changing method `method`'s `self` parameter to be `&self` + | +LL - fn method(self: &unsafe<'ops> &'a Bar) {} +LL + fn method(&self) {} + | error[E0599]: no method named `method` found for reference `&dyn Foo` in the current scope --> $DIR/unsafe-binders-bare-trait-object-next-solver.rs:19:7 diff --git a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr index c70ab65aa9056..3aeb3edb8690c 100644 --- a/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr +++ b/tests/ui/feature-gates/feature-gate-dispatch-from-dyn-missing-impl.stderr @@ -1,21 +1,23 @@ error[E0038]: the trait `Trait` is not dyn compatible --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:32:33 | -LL | fn ptr(self: Ptr); - | --------- help: consider changing method `ptr`'s `self` parameter to be `&self`: `&Self` -... LL | Ptr(Box::new(4)) as Ptr; | ^^^^^ `Trait` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:18 + --> $DIR/feature-gate-dispatch-from-dyn-missing-impl.rs:25:12 | LL | trait Trait { | ----- this trait is not dyn compatible... LL | fn ptr(self: Ptr); - | ^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on + | ^^^^^^^^^^^^^^^ ...because method `ptr`'s `self` parameter cannot be dispatched on = help: only type `i32` implements `Trait`; consider using it directly instead. +help: consider changing method `ptr`'s `self` parameter to be `&self` + | +LL - fn ptr(self: Ptr); +LL + fn ptr(&self); + | error: aborting due to 1 previous error diff --git a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr index fe4802c9b3a47..ccc322d36acea 100644 --- a/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr +++ b/tests/ui/self/arbitrary-self-types-dyn-incompatible.stderr @@ -1,21 +1,23 @@ error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/arbitrary-self-types-dyn-incompatible.rs:29:39 | -LL | fn foo(self: &Rc) -> usize; - | --------- help: consider changing method `foo`'s `self` parameter to be `&self`: `&Self` -... LL | let x = Rc::new(5usize) as Rc; | ^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/arbitrary-self-types-dyn-incompatible.rs:4:18 + --> $DIR/arbitrary-self-types-dyn-incompatible.rs:4:12 | LL | trait Foo { | --- this trait is not dyn compatible... LL | fn foo(self: &Rc) -> usize; - | ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on + | ^^^^^^^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on = help: only type `usize` implements `Foo`; consider using it directly instead. +help: consider changing method `foo`'s `self` parameter to be `&self` + | +LL - fn foo(self: &Rc) -> usize; +LL + fn foo(&self) -> usize; + | error: aborting due to 1 previous error diff --git a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr index b37dd6411cab3..276da3ebaf9bc 100644 --- a/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr +++ b/tests/ui/self/dispatch-dyn-incompatible-that-does-not-deref.stderr @@ -1,20 +1,22 @@ error[E0038]: the trait `Foo` is not dyn compatible --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:12:13 | -LL | fn method(self: &W) {} - | -- help: consider changing method `method`'s `self` parameter to be `&self`: `&Self` -... LL | fn test(x: &dyn Foo) { | ^^^^^^^ `Foo` is not dyn compatible | note: for a trait to be dyn compatible it needs to allow building a vtable for more information, visit - --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21 + --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:15 | LL | trait Foo: Deref { | --- this trait is not dyn compatible... LL | fn method(self: &W) {} - | ^^ ...because method `method`'s `self` parameter cannot be dispatched on + | ^^^^^^^^ ...because method `method`'s `self` parameter cannot be dispatched on +help: consider changing method `method`'s `self` parameter to be `&self` + | +LL - fn method(self: &W) {} +LL + fn method(&self) {} + | error[E0307]: invalid `self` parameter type: `&W` --> $DIR/dispatch-dyn-incompatible-that-does-not-deref.rs:8:21 diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed index 2b26d8cc82ee3..3bc052f127214 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.fixed @@ -3,7 +3,7 @@ trait Trait { fn foo(&self) where Self: Other, Self: Sized { } - fn bar(self: &Self) {} //~ ERROR invalid `self` parameter type + fn bar(&self) {} //~ ERROR invalid `self` parameter type } fn bar(x: &dyn Trait) {} //~ ERROR the trait `Trait` is not dyn compatible diff --git a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr index 17c819660f51d..a1d5a3bd2228c 100644 --- a/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr +++ b/tests/ui/suggestions/dyn-incompatible-trait-should-use-where-sized.stderr @@ -13,7 +13,7 @@ LL | trait Trait { LL | fn foo() where Self: Other, { } | ^^^ ...because associated function `foo` has no `self` parameter LL | fn bar(self: ()) {} - | ^^ ...because method `bar`'s `self` parameter cannot be dispatched on + | ^^^^^^^^ ...because method `bar`'s `self` parameter cannot be dispatched on help: consider turning `foo` into a method by giving it a `&self` argument, so that it is accessible through the trait object's vtable | LL | fn foo(&self) where Self: Other, { } @@ -25,7 +25,7 @@ LL | fn foo() where Self: Other, Self: Sized { } help: consider changing method `bar`'s `self` parameter to be `&self` | LL - fn bar(self: ()) {} -LL + fn bar(self: &Self) {} +LL + fn bar(&self) {} | error[E0307]: invalid `self` parameter type: `()` diff --git a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr index f29950de63798..7fb3980839e4f 100644 --- a/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr +++ b/tests/ui/traits/default_auto_traits/maybe-bounds-in-dyn-traits.stderr @@ -19,9 +19,6 @@ LL | impl LeakTr for LeakS {} error[E0038]: the trait `DynCompatCheck2` is not dyn compatible --> $DIR/maybe-bounds-in-dyn-traits.rs:90:17 | -LL | fn mut_foo(&mut self) {} - | --------- help: consider changing method `mut_foo`'s `self` parameter to be `&self`: `&Self` -... LL | let _: &dyn DynCompatCheck2 = &NonLeakS; | ^^^^^^^^^^^^^^^ `DynCompatCheck2` is not dyn compatible | @@ -34,6 +31,11 @@ LL | trait DynCompatCheck2: ?Leak { LL | fn mut_foo(&mut self) {} | ^^^^^^^^^ ...because method `mut_foo`'s `self` parameter cannot be dispatched on = help: only type `NonLeakS` implements `DynCompatCheck2`; consider using it directly instead. +help: consider changing method `mut_foo`'s `self` parameter to be `&self` + | +LL - fn mut_foo(&mut self) {} +LL + fn mut_foo(&self) {} + | error[E0107]: trait takes 0 generic arguments but 1 generic argument was supplied --> $DIR/maybe-bounds-in-dyn-traits.rs:98:26 From b39898fa70f1f72ce47a81b493d5d44f5168ceef Mon Sep 17 00:00:00 2001 From: jackh726 Date: Mon, 14 Sep 2026 23:25:48 +0000 Subject: [PATCH 0582/1309] Pass liveness/variances through a separate LivenessSource trait --- .../src/polonius/constraints.rs | 128 ++++++++++++------ compiler/rustc_borrowck/src/polonius/dump.rs | 20 +-- compiler/rustc_borrowck/src/polonius/mod.rs | 22 ++- .../rustc_borrowck/src/region_infer/values.rs | 4 + 4 files changed, 112 insertions(+), 62 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 4989b87845a31..5a3c0aa3987a1 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -2,7 +2,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_index::IndexVec; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::RegionVid; -use rustc_mir_dataflow::points::PointIndex; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use crate::BorrowSet; use crate::constraints::OutlivesConstraint; @@ -49,11 +49,79 @@ pub(super) struct LocalizedConstraintGraph { logical_edges: IndexVec>, } +/// For a given region, the relevant liveness and variance information. +pub(super) struct RegionLiveness<'a> { + region: RegionVid, + direction: ConstraintDirection, + liveness: &'a LivenessValues, +} + +impl<'a> RegionLiveness<'a> { + pub(super) fn new<'tcx>( + region: RegionVid, + live_region_variances: &LiveRegionVariances, + universal_regions: &UniversalRegions<'tcx>, + liveness: &'a LivenessValues, + ) -> Self { + // Universal regions propagate loans along the CFG, i.e. forwards only. + let is_universal_region = universal_regions.is_universal_region(region); + + // Note: there currently are cases related to promoted and const generics, where we don't yet + // have variance information (possibly about temporary regions created when typeck sanitizes the + // promoteds). Until that is done, we conservatively fallback to maximizing reachability by + // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus + // propagate liveness when needed. + // + // FIXME: add the missing variance information and remove this fallback bidirectional edge. + let direction = if is_universal_region { + ConstraintDirection::Forward + } else { + live_region_variances + .get(region) + .copied() + .flatten() + .unwrap_or(ConstraintDirection::Bidirectional) + }; + Self { region, direction, liveness } + } + + fn is_live_at(&self, point: PointIndex) -> bool { + self.liveness.points().contains(self.region, point) + } +} + +/// The source of liveness information for a given region. +pub(super) trait LivenessSource<'loc> { + fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>; + fn location_map(&self) -> &'loc DenseLocationMap; +} + +/// A `LivenessSource` for already-existing liveness and variance data. +pub(super) struct CachedLivenessSource<'a, 'tcx> { + pub(super) live_region_variances: &'a LiveRegionVariances, + pub(super) universal_regions: &'a UniversalRegions<'tcx>, + pub(super) liveness: &'a LivenessValues, +} + +impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { + fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { + RegionLiveness::new( + region, + self.live_region_variances, + self.universal_regions, + self.liveness, + ) + } + fn location_map(&self) -> &'a DenseLocationMap { + self.liveness.location_map() + } +} + /// The visitor interface when traversing a `LocalizedConstraintGraph`. pub(super) trait LocalizedConstraintGraphVisitor { /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't /// visited before. - fn on_node_traversed(&mut self, _loan: BorrowIndex, _node: LocalizedNode) {} + fn on_node_traversed(&mut self, _loan: BorrowIndex, _node: LocalizedNode, _is_live: bool) {} /// Callback called when discovering a new `successor` node for the `current_node`. fn on_successor_discovered(&mut self, _current_node: LocalizedNode, _successor: LocalizedNode) { @@ -63,7 +131,7 @@ pub(super) trait LocalizedConstraintGraphVisitor { impl LocalizedConstraintGraph { /// Traverses the constraints and returns the indexed graph of edges per node. pub(super) fn new<'tcx>( - liveness: &LivenessValues, + location_map: &DenseLocationMap, outlives_constraints: impl Iterator>, ) -> Self { let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); @@ -80,7 +148,7 @@ impl LocalizedConstraintGraph { Locations::Single(location) => { let node = LocalizedNode { region: outlives_constraint.sup, - point: liveness.point_from_location(location), + point: location_map.point_from_location(location), }; edges.entry(node).or_default().insert(outlives_constraint.sub); } @@ -92,20 +160,18 @@ impl LocalizedConstraintGraph { /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered /// nodes and successors. - pub(super) fn traverse<'tcx>( + pub(super) fn traverse<'tcx, 'loc>( &self, body: &Body<'tcx>, - liveness: &LivenessValues, - live_region_variances: &LiveRegionVariances, - universal_regions: &UniversalRegions<'tcx>, borrow_set: &BorrowSet<'tcx>, + liveness_source: &mut impl LivenessSource<'loc>, visitor: &mut impl LocalizedConstraintGraphVisitor, ) { - let live_regions = liveness.points(); - let mut visited = FxHashSet::default(); let mut stack = Vec::new(); + let location_map = liveness_source.location_map(); + // Compute reachability per loan by traversing each loan's subgraph starting from where it // is introduced. for (loan_idx, loan) in borrow_set.iter_enumerated() { @@ -114,15 +180,16 @@ impl LocalizedConstraintGraph { let start_node = LocalizedNode { region: loan.region, - point: liveness.point_from_location(loan.reserve_location), + point: location_map.point_from_location(loan.reserve_location), }; visited.insert(start_node); stack.push(start_node); while let Some(node) = stack.pop() { + let liveness = liveness_source.liveness_for_region(node.region); // We've reached a node we haven't visited before. - let location = liveness.location_from_point(node.point); - visitor.on_node_traversed(loan_idx, node); + let location = location_map.to_location(node.point); + visitor.on_node_traversed(loan_idx, node, liveness.is_live_at(node.point)); // When we find a _new_ successor, we'd like to // - visit it eventually, @@ -140,26 +207,6 @@ impl LocalizedConstraintGraph { // - the materialized logical edges that exist virtually at all points for this // node's region, localized at this point. - // Universal regions propagate loans along the CFG, i.e. forwards only. - let is_universal_region = universal_regions.is_universal_region(node.region); - - // Note: there currently are cases related to promoted and const generics, where we don't yet - // have variance information (possibly about temporary regions created when typeck sanitizes the - // promoteds). Until that is done, we conservatively fallback to maximizing reachability by - // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus - // propagate liveness when needed. - // - // FIXME: add the missing variance information and remove this fallback bidirectional edge. - let liveness_direction = if is_universal_region { - ConstraintDirection::Forward - } else { - live_region_variances - .get(node.region) - .copied() - .flatten() - .unwrap_or(ConstraintDirection::Bidirectional) - }; - // The physical edges present at this node are: // // 1. the typeck edges that flow from region to region *at this point*. @@ -178,14 +225,14 @@ impl LocalizedConstraintGraph { // // We still need to check liveness for each next point though. if matches!( - liveness_direction, + liveness.direction, ConstraintDirection::Forward | ConstraintDirection::Bidirectional ) { if body[location.block].statements.get(location.statement_index).is_some() { // Intra-block edges, straight line constraints from each point to its successor // within the same block. let next_point = node.point + 1; - if live_regions.contains(node.region, next_point) { + if liveness.is_live_at(next_point) { successor_found(LocalizedNode { region: node.region, point: next_point, @@ -197,8 +244,8 @@ impl LocalizedConstraintGraph { for successor_block in body[location.block].terminator().successors() { let next_location = Location { block: successor_block, statement_index: 0 }; - let next_point = liveness.point_from_location(next_location); - if live_regions.contains(node.region, next_point) { + let next_point = location_map.point_from_location(next_location); + if liveness.is_live_at(next_point) { successor_found(LocalizedNode { region: node.region, point: next_point, @@ -219,9 +266,9 @@ impl LocalizedConstraintGraph { // Liveness flows into the regions live at the next point. So, in a backwards view, we'll link // the region from the current point, if it's live there, to the previous point. if matches!( - liveness_direction, + liveness.direction, ConstraintDirection::Backward | ConstraintDirection::Bidirectional - ) && live_regions.contains(node.region, node.point) + ) && liveness.is_live_at(node.point) { if location.statement_index > 0 { // Backward edges to the predecessor point in the same block. @@ -239,7 +286,8 @@ impl LocalizedConstraintGraph { block: pred_block, statement_index: body[pred_block].statements.len(), }; - let previous_point = liveness.point_from_location(previous_location); + let previous_point = + location_map.point_from_location(previous_location); successor_found(LocalizedNode { region: node.region, point: previous_point, diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index 0c63b00ce5461..e84a8b955db6a 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -11,7 +11,9 @@ use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; -use crate::polonius::{LocalizedConstraintGraphVisitor, LocalizedNode, PoloniusContext}; +use crate::polonius::{ + CachedLivenessSource, LocalizedConstraintGraphVisitor, LocalizedNode, PoloniusContext, +}; use crate::region_infer::values::LivenessValues; use crate::type_check::Locations; use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext}; @@ -41,16 +43,14 @@ pub(crate) fn dump_polonius_mir<'tcx>( // If we have a polonius graph to dump along the rest of the MIR and NLL info, we extract its // constraints here. + let mut liveness_source = CachedLivenessSource { + live_region_variances: &polonius_context.live_region_variances, + universal_regions: regioncx.universal_regions(), + liveness: regioncx.liveness_constraints(), + }; let mut collector = MirDumpCollector::default(); if let Some(graph) = &polonius_context.graph { - graph.traverse( - body, - regioncx.liveness_constraints(), - &polonius_context.live_region_variances, - regioncx.universal_regions(), - borrow_set, - &mut collector, - ); + graph.traverse(body, borrow_set, &mut liveness_source, &mut collector); } let extra_data = &|pass_where, out: &mut dyn io::Write| { @@ -98,7 +98,7 @@ struct MirDumpCollector { } impl LocalizedConstraintGraphVisitor for MirDumpCollector { - fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode) { + fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode, _is_live: bool) { self.reachability.entry(loan).or_default().push(node); } diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 0735aa6120c37..e3ef284475a31 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -139,18 +139,17 @@ impl PoloniusContext { // From the outlives constraints, liveness, and variances, we can compute reachability // on the lazy localized constraint graph to trace the liveness of loans, for the next // step in the chain (the NLL loan scope and active loans computations). - let graph = LocalizedConstraintGraph::new(liveness, outlives_constraints); + let graph = + LocalizedConstraintGraph::new(liveness.location_map(), outlives_constraints); let mut live_loans = LiveLoans::new(num_points, borrow_set.len()); - let mut visitor = LoanLivenessVisitor { liveness, live_loans: &mut live_loans }; - graph.traverse( - body, - liveness, - &self.live_region_variances, + let mut liveness_source = CachedLivenessSource { + live_region_variances: &self.live_region_variances, universal_regions, - borrow_set, - &mut visitor, - ); + liveness, + }; + let mut visitor = LoanLivenessVisitor { live_loans: &mut live_loans }; + graph.traverse(body, borrow_set, &mut liveness_source, &mut visitor); liveness.record_live_loans(live_loans); // The graph can be traversed again during MIR dumping, so we store it here. @@ -161,12 +160,11 @@ impl PoloniusContext { /// Visitor to record loan liveness when traversing the localized constraint graph. struct LoanLivenessVisitor<'a> { - liveness: &'a LivenessValues, live_loans: &'a mut LiveLoans, } impl LocalizedConstraintGraphVisitor for LoanLivenessVisitor<'_> { - fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode) { + fn on_node_traversed(&mut self, loan: BorrowIndex, node: LocalizedNode, is_live: bool) { // Record the loan as being live on entry to this point if it reaches a live region // there. // @@ -208,7 +206,7 @@ impl LocalizedConstraintGraphVisitor for LoanLivenessVisitor<'_> { // // FIXME: analyze potential unsoundness, possibly in concert with a borrowck // implementation in a-mir-formality, fuzzing, or manually crafting counter-examples. - if self.liveness.is_live_at_point(node.region, node.point) { + if is_live { self.live_loans.insert(node.point, loan); } } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 2f03fec0d2245..c7f4e520d3fad 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -200,6 +200,10 @@ impl LivenessValues { self.location_map.to_location(point) } + pub(crate) fn location_map(&self) -> &Rc { + &self.location_map + } + /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active /// loans dataflow computations. pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) { From 670ea69e18e7369a499d621f058d66a131bd031b Mon Sep 17 00:00:00 2001 From: jackh726 Date: Mon, 14 Sep 2026 23:25:48 +0000 Subject: [PATCH 0583/1309] Basics needed for deferred liveness --- compiler/rustc_borrowck/src/lib.rs | 4 +- compiler/rustc_borrowck/src/nll.rs | 10 +- .../src/polonius/constraints.rs | 67 +--------- compiler/rustc_borrowck/src/polonius/dump.rs | 30 ++++- .../rustc_borrowck/src/polonius/liveness.rs | 122 ++++++++++++++++++ compiler/rustc_borrowck/src/polonius/mod.rs | 76 +++++++++-- .../src/type_check/liveness/mod.rs | 7 +- .../src/type_check/liveness/trace.rs | 13 +- compiler/rustc_borrowck/src/type_check/mod.rs | 4 +- 9 files changed, 241 insertions(+), 92 deletions(-) create mode 100644 compiler/rustc_borrowck/src/polonius/liveness.rs diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs index 546d91187e05e..d2a22f3a135ed 100644 --- a/compiler/rustc_borrowck/src/lib.rs +++ b/compiler/rustc_borrowck/src/lib.rs @@ -310,7 +310,7 @@ struct CollectRegionConstraintsResult<'tcx> { deferred_closure_requirements: DeferredClosureRequirements<'tcx>, deferred_opaque_type_errors: Vec>, polonius_facts: Option>, - polonius_context: Option, + polonius_context: Option>, } /// Start borrow checking by collecting the region constraints for @@ -798,7 +798,7 @@ pub(crate) struct MirBorrowckCtxt<'a, 'diag, 'tcx> { /// Results of Polonius analysis. polonius_output: Option<&'a PoloniusOutput>, /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics. - polonius_context: Option<&'a PoloniusContext>, + polonius_context: Option<&'a PoloniusContext<'tcx>>, } // Check that: diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index 1a328f62fc73e..fed7fdd97ac4d 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -46,7 +46,7 @@ pub(crate) struct NllOutput<'tcx> { /// When using `-Zpolonius=next`: the data used to compute errors and diagnostics, e.g. /// localized typeck and liveness constraints. - pub polonius_context: Option, + pub polonius_context: Option>, } /// Rewrites the regions in the MIR to use NLL variables, also scraping out the set of universal @@ -121,7 +121,7 @@ pub(crate) fn compute_regions<'tcx>( universal_region_relations: Frozen>, constraints: MirTypeckRegionConstraints<'tcx>, mut polonius_facts: Option>, - mut polonius_context: Option, + mut polonius_context: Option>, ) -> NllOutput<'tcx> { let polonius_output = root_cx.consumer.as_ref().map_or(false, |c| c.polonius_output()) || infcx.tcx.sess.opts.unstable_opts.polonius.is_legacy_enabled(); @@ -144,20 +144,20 @@ pub(crate) fn compute_regions<'tcx>( &lowered_constraints, ); - let num_points = location_map.num_points(); - // If requested for `-Zpolonius=next`, compute loan liveness information. // This is done prior to `RegionInferenceContext::new`, because we may add // additional liveness constraints. if let Some(polonius_context) = polonius_context.as_mut() { let _timer = infcx.tcx.prof.generic_activity("borrowck_polonius_loan_liveness"); polonius_context.compute_loan_liveness( + infcx, &mut lowered_constraints.liveness_constraints, lowered_constraints.outlives_constraints.outlives().iter().copied(), &universal_region_relations.universal_regions, body, + move_data, + &location_map, borrow_set, - num_points, ); } diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 5a3c0aa3987a1..44a21708c8419 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -7,10 +7,9 @@ use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use crate::BorrowSet; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; -use crate::polonius::{ConstraintDirection, LiveRegionVariances}; -use crate::region_infer::values::LivenessValues; +use crate::polonius::ConstraintDirection; +use crate::polonius::liveness::RegionLiveness; use crate::type_check::Locations; -use crate::universal_regions::UniversalRegions; /// A localized outlives constraint reifies the CFG location where the outlives constraint holds, /// within the origins themselves as if they were different from point to point: from `a: b` @@ -49,74 +48,12 @@ pub(super) struct LocalizedConstraintGraph { logical_edges: IndexVec>, } -/// For a given region, the relevant liveness and variance information. -pub(super) struct RegionLiveness<'a> { - region: RegionVid, - direction: ConstraintDirection, - liveness: &'a LivenessValues, -} - -impl<'a> RegionLiveness<'a> { - pub(super) fn new<'tcx>( - region: RegionVid, - live_region_variances: &LiveRegionVariances, - universal_regions: &UniversalRegions<'tcx>, - liveness: &'a LivenessValues, - ) -> Self { - // Universal regions propagate loans along the CFG, i.e. forwards only. - let is_universal_region = universal_regions.is_universal_region(region); - - // Note: there currently are cases related to promoted and const generics, where we don't yet - // have variance information (possibly about temporary regions created when typeck sanitizes the - // promoteds). Until that is done, we conservatively fallback to maximizing reachability by - // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus - // propagate liveness when needed. - // - // FIXME: add the missing variance information and remove this fallback bidirectional edge. - let direction = if is_universal_region { - ConstraintDirection::Forward - } else { - live_region_variances - .get(region) - .copied() - .flatten() - .unwrap_or(ConstraintDirection::Bidirectional) - }; - Self { region, direction, liveness } - } - - fn is_live_at(&self, point: PointIndex) -> bool { - self.liveness.points().contains(self.region, point) - } -} - /// The source of liveness information for a given region. pub(super) trait LivenessSource<'loc> { fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>; fn location_map(&self) -> &'loc DenseLocationMap; } -/// A `LivenessSource` for already-existing liveness and variance data. -pub(super) struct CachedLivenessSource<'a, 'tcx> { - pub(super) live_region_variances: &'a LiveRegionVariances, - pub(super) universal_regions: &'a UniversalRegions<'tcx>, - pub(super) liveness: &'a LivenessValues, -} - -impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { - fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { - RegionLiveness::new( - region, - self.live_region_variances, - self.universal_regions, - self.liveness, - ) - } - fn location_map(&self) -> &'a DenseLocationMap { - self.liveness.location_map() - } -} - /// The visitor interface when traversing a `LocalizedConstraintGraph`. pub(super) trait LocalizedConstraintGraphVisitor { /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index e84a8b955db6a..ec7f688b6423f 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -5,23 +5,47 @@ use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; -use rustc_mir_dataflow::points::PointIndex; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; +use crate::polonius::liveness::RegionLiveness; use crate::polonius::{ - CachedLivenessSource, LocalizedConstraintGraphVisitor, LocalizedNode, PoloniusContext, + LiveRegionVariances, LivenessSource, LocalizedConstraintGraphVisitor, LocalizedNode, + PoloniusContext, }; use crate::region_infer::values::LivenessValues; use crate::type_check::Locations; +use crate::universal_regions::UniversalRegions; use crate::{BorrowckInferCtxt, ClosureRegionRequirements, RegionInferenceContext}; /// The polonius MIR dump template: a regular HTML file for easy editing, with special dummy /// sections to be replaced by real contents. const TEMPLATE: &str = include_str!("./dump/polonius-mir-dump.template.html"); +/// A `LivenessSource` for already-existing liveness and variance data. +struct CachedLivenessSource<'a, 'tcx> { + live_region_variances: &'a LiveRegionVariances, + universal_regions: &'a UniversalRegions<'tcx>, + liveness: &'a LivenessValues, +} + +impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { + fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { + RegionLiveness::new( + region, + self.live_region_variances, + self.universal_regions, + self.liveness, + ) + } + fn location_map(&self) -> &'a DenseLocationMap { + self.liveness.location_map() + } +} + /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. pub(crate) fn dump_polonius_mir<'tcx>( infcx: &BorrowckInferCtxt<'tcx>, @@ -29,7 +53,7 @@ pub(crate) fn dump_polonius_mir<'tcx>( regioncx: &RegionInferenceContext<'tcx>, closure_region_requirements: &Option>, borrow_set: &BorrowSet<'tcx>, - polonius_context: Option<&PoloniusContext>, + polonius_context: Option<&PoloniusContext<'tcx>>, ) { let tcx = infcx.tcx; if !tcx.sess.opts.unstable_opts.polonius.is_next_enabled() { diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs new file mode 100644 index 0000000000000..2864cbf3c1ce9 --- /dev/null +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -0,0 +1,122 @@ +use rustc_index::IndexVec; +use rustc_middle::mir::Local; +use rustc_middle::ty::{GenericArg, RegionVid, Ty}; +use rustc_mir_dataflow::points::PointIndex; + +use crate::BorrowckInferCtxt; +use crate::polonius::{ConstraintDirection, LiveRegionVariances}; +use crate::region_infer::values::LivenessValues; +use crate::type_check::liveness::LivenessComputation; +use crate::universal_regions::UniversalRegions; + +#[derive(Default)] +pub(crate) struct DeferredLocals<'tcx> { + /// For each region, the local whose liveness is deferred. + /// + /// Importantly, because of MIR renumbering, this will always be a 1:1 relationship. + by_region: IndexVec>, + + /// For each deferred local, gets the regions contained within that local at use and drop. + drop_args_by_local: IndexVec>>>, +} + +impl<'tcx> DeferredLocals<'tcx> { + pub(crate) fn defer_local( + &mut self, + infcx: &BorrowckInferCtxt<'tcx>, + universal_regions: &UniversalRegions<'tcx>, + local: Local, + local_ty: Ty<'tcx>, + dropck_kinds: &[GenericArg<'tcx>], + ) { + let tcx = infcx.tcx; + + // We already have drop data for this local, because we need to register + // region constraints eagerly. So, we'll store this so we don't need to + // recompute. + self.drop_args_by_local.insert(local, dropck_kinds.to_vec()); + + // Then, we want to map all the regions contained within this local to + // the local itself. Later, when asked for liveness of a given region, + // we can trace liveness for the local containing it. + let by_region = &mut self.by_region; + tcx.for_each_free_region(&local_ty, |region| { + // See note in [`VarianceExtractor::record_variance`]. + if region.is_bound() || region.is_erased() { + return; + } + let vid = universal_regions.to_region_vid(region); + // Because of MIR renumbering, we should always have a 1:1 mapping + // between a region and a local. + let previous = by_region.insert(vid, local); + debug_assert!( + previous.is_none(), + "{vid:?} is in the type of both {previous:?} and {local:?}, but \ + MIR renumbering should ensure that this is impossible.", + ); + }); + } + + /// For a given region, compute the liveness for the local containing it, if if is deferred. + #[inline] + pub(crate) fn compute_deferred_local( + &mut self, + region: RegionVid, + universal_regions: &UniversalRegions<'tcx>, + liveness: &mut LivenessValues, + live_region_variances: &mut LiveRegionVariances, + comp: &mut LivenessComputation<'_, 'tcx>, + ) { + let Some(local) = self.by_region.remove(region) else { + return; + }; + let Some(drop_args) = self.drop_args_by_local.remove(local) else { + return; + }; + + comp.compute(local, universal_regions, Some(live_region_variances), liveness, || { + &drop_args + }); + } +} + +/// For a given region, the relevant liveness and variance information. +pub(super) struct RegionLiveness<'a> { + region: RegionVid, + pub(super) direction: ConstraintDirection, + liveness: &'a LivenessValues, +} + +impl<'a> RegionLiveness<'a> { + pub(super) fn new<'tcx>( + region: RegionVid, + live_region_variances: &LiveRegionVariances, + universal_regions: &UniversalRegions<'tcx>, + liveness: &'a LivenessValues, + ) -> Self { + // Universal regions propagate loans along the CFG, i.e. forwards only. + let is_universal_region = universal_regions.is_universal_region(region); + + // Note: there currently are cases related to promoted and const generics, where we don't yet + // have variance information (possibly about temporary regions created when typeck sanitizes the + // promoteds). Until that is done, we conservatively fallback to maximizing reachability by + // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus + // propagate liveness when needed. + // + // FIXME: add the missing variance information and remove this fallback bidirectional edge. + let direction = if is_universal_region { + ConstraintDirection::Forward + } else { + live_region_variances + .get(region) + .copied() + .flatten() + .unwrap_or(ConstraintDirection::Bidirectional) + }; + Self { region, direction, liveness } + } + + pub(super) fn is_live_at(&self, point: PointIndex) -> bool { + self.liveness.points().contains(self.region, point) + } +} diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index e3ef284475a31..8e38f5a37048e 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -36,6 +36,7 @@ mod constraints; mod dump; pub(crate) mod legacy; +mod liveness; mod liveness_constraints; use rustc_data_structures::fx::FxHashSet; @@ -43,16 +44,20 @@ use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; use rustc_middle::mir::{Body, Local}; use rustc_middle::ty::RegionVid; -use rustc_mir_dataflow::points::PointIndex; +use rustc_mir_dataflow::move_paths::MoveData; +use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; pub(self) use self::constraints::*; pub(crate) use self::dump::dump_polonius_mir; pub(crate) use self::liveness_constraints::record_live_region_variance; -use crate::BorrowSet; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; +pub(crate) use crate::polonius::liveness::DeferredLocals; +use crate::polonius::liveness::RegionLiveness; use crate::region_infer::values::LivenessValues; +use crate::type_check::liveness::{LivenessComputation, LocalUseMap}; use crate::universal_regions::UniversalRegions; +use crate::{BorrowSet, BorrowckInferCtxt}; pub(crate) type LiveRegionVariances = IndexVec>; @@ -84,7 +89,7 @@ impl LiveLoans { /// polonius localized constraints, during NLL region inference as well as MIR dumping, /// - data needed by the borrowck error computation and diagnostics. #[derive(Default)] -pub(crate) struct PoloniusContext { +pub(crate) struct PoloniusContext<'tcx> { /// The graph from which we extract the localized outlives constraints. graph: Option, @@ -97,6 +102,10 @@ pub(crate) struct PoloniusContext { /// currently has more boring locals than NLLs so we record the latter to use in errors and /// diagnostics, to focus on the locals we consider relevant and match NLL diagnostics. pub(crate) boring_nll_locals: FxHashSet, + + pub(crate) deferred_locals_for_liveness: DeferredLocals<'tcx>, + + pub(crate) local_use_map: Option, } /// The direction a constraint can flow into. Used to create liveness constraints according to @@ -113,7 +122,7 @@ pub(crate) enum ConstraintDirection { Bidirectional, } -impl PoloniusContext { +impl<'tcx> PoloniusContext<'tcx> { /// Computes live loans using the set of loans model for `-Zpolonius=next`. /// /// First, creates a constraint graph combining regions and CFG points, by: @@ -124,14 +133,16 @@ impl PoloniusContext { /// loan scope and active loans computations. /// /// The constraint data will be used to compute errors and diagnostics. - pub(crate) fn compute_loan_liveness<'tcx>( + pub(crate) fn compute_loan_liveness( &mut self, + infcx: &BorrowckInferCtxt<'tcx>, liveness: &mut LivenessValues, outlives_constraints: impl Iterator>, universal_regions: &UniversalRegions<'tcx>, body: &Body<'tcx>, + move_data: &MoveData<'tcx>, + location_map: &DenseLocationMap, borrow_set: &BorrowSet<'tcx>, - num_points: usize, ) { // We don't need to prepare the graph (index NLL constraints, etc.) if we have no loans to // trace throughout localized constraints. @@ -142,11 +153,21 @@ impl PoloniusContext { let graph = LocalizedConstraintGraph::new(liveness.location_map(), outlives_constraints); - let mut live_loans = LiveLoans::new(num_points, borrow_set.len()); - let mut liveness_source = CachedLivenessSource { - live_region_variances: &self.live_region_variances, - universal_regions, + let local_use_map = self + .local_use_map + .as_ref() + .expect("local use map should be computed before loan liveness"); + let deferred_locals_for_liveness = + std::mem::take(&mut self.deferred_locals_for_liveness); + let mut live_loans = LiveLoans::new(location_map.num_points(), borrow_set.len()); + let comp = + LivenessComputation::new(infcx, body, location_map, move_data, &local_use_map); + let mut liveness_source = DeferredLivenessSource { liveness, + live_region_variances: &mut self.live_region_variances, + universal_regions, + deferred_locals_for_liveness, + comp, }; let mut visitor = LoanLivenessVisitor { live_loans: &mut live_loans }; graph.traverse(body, borrow_set, &mut liveness_source, &mut visitor); @@ -158,6 +179,41 @@ impl PoloniusContext { } } +/// A `LivenessSource` that will dynamically compute liveness on-demand when traversing +/// the outlives graph. This allows avoiding computing liveness eagerly on many more locals +/// than NLLs, which can be expensive. +struct DeferredLivenessSource<'a, 'tcx> { + liveness: &'a mut LivenessValues, + live_region_variances: &'a mut LiveRegionVariances, + universal_regions: &'a UniversalRegions<'tcx>, + deferred_locals_for_liveness: DeferredLocals<'tcx>, + comp: LivenessComputation<'a, 'tcx>, +} + +impl<'a> LivenessSource<'a> for DeferredLivenessSource<'a, '_> { + #[inline] + fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { + self.deferred_locals_for_liveness.compute_deferred_local( + region, + self.universal_regions, + &mut self.liveness, + &mut self.live_region_variances, + &mut self.comp, + ); + + RegionLiveness::new( + region, + self.live_region_variances, + self.universal_regions, + self.liveness, + ) + } + + fn location_map(&self) -> &'a DenseLocationMap { + self.comp.location_map + } +} + /// Visitor to record loan liveness when traversing the localized constraint graph. struct LoanLivenessVisitor<'a> { live_loans: &'a mut LiveLoans, diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index c2fa8ab8637af..fcfffaff9fcd1 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -21,6 +21,9 @@ use crate::universal_regions::UniversalRegions; mod local_use_map; mod trace; +pub(crate) use local_use_map::LocalUseMap; +pub(crate) use trace::LivenessComputation; + /// Combines liveness analysis with initialization analysis to /// determine which variables are live at which points, both due to /// ordinary uses and drops. Returns a set of (ty, location) pairs @@ -155,7 +158,7 @@ fn record_regular_live_regions<'tcx>( tcx: TyCtxt<'tcx>, liveness_constraints: &mut LivenessValues, universal_regions: &UniversalRegions<'tcx>, - polonius_context: &mut Option, + polonius_context: &mut Option>, body: &Body<'tcx>, ) { let mut visitor = @@ -170,7 +173,7 @@ struct LiveVariablesVisitor<'a, 'tcx> { tcx: TyCtxt<'tcx>, liveness_constraints: &'a mut LivenessValues, universal_regions: &'a UniversalRegions<'tcx>, - polonius_context: &'a mut Option, + polonius_context: &'a mut Option>, } impl<'a, 'tcx> Visitor<'tcx> for LiveVariablesVisitor<'a, 'tcx> { diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index d0302faa513b2..a58f8bd8d931d 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -18,7 +18,7 @@ use rustc_trait_selection::traits::query::dropck_outlives; use rustc_trait_selection::traits::query::type_op::{DropckOutlives, TypeOpOutput}; use tracing::debug; -use crate::polonius::{LiveRegionVariances, record_live_region_variance}; +use crate::polonius::{DeferredLocals, LiveRegionVariances, record_live_region_variance}; use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::local_use_map::LocalUseMap; use crate::type_check::liveness::make_all_regions_live; @@ -60,11 +60,18 @@ pub(super) fn trace<'tcx>( let mut results = LivenessResults::new(typeck, comp); + let deferred_locals = DeferredLocals::default(); + results.record_legacy_polonius_drop_facts(relevant_live_locals); results.compute_for_all_locals(relevant_live_locals); results.dropck_boring_locals(boring_locals); + + if let Some(polonius_context) = &mut typeck.polonius_context { + polonius_context.deferred_locals_for_liveness = deferred_locals; + polonius_context.local_use_map = Some(local_use_map); + } } pub(crate) struct LivenessComputation<'a, 'tcx> { @@ -73,7 +80,7 @@ pub(crate) struct LivenessComputation<'a, 'tcx> { pub(crate) body: &'a Body<'tcx>, /// Defines the `PointIndex` mapping - location_map: &'a DenseLocationMap, + pub(crate) location_map: &'a DenseLocationMap, /// Mapping to/from the various indices used for initialization tracking. move_data: &'a MoveData<'tcx>, @@ -299,7 +306,7 @@ impl<'a, 'tcx> LivenessComputation<'a, 'tcx> { } /// Compute for a given local the use- and drop-live points - fn compute<'drop_data>( + pub(crate) fn compute<'drop_data>( &mut self, local: Local, universal_regions: &UniversalRegions<'tcx>, diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 6418c73173df0..eb489bdc3da89 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -247,7 +247,7 @@ struct TypeChecker<'a, 'tcx> { constraints: &'a mut MirTypeckRegionConstraints<'tcx>, deferred_closure_requirements: &'a mut DeferredClosureRequirements<'tcx>, /// When using `-Zpolonius=next`, the liveness helper data used to create polonius constraints. - polonius_context: Option, + polonius_context: Option>, } /// Holder struct for passing results from MIR typeck to the rest of the non-lexical regions @@ -258,7 +258,7 @@ pub(crate) struct MirTypeckResults<'tcx> { pub(crate) region_bound_pairs: Frozen>, pub(crate) known_type_outlives_obligations: Frozen>>, pub(crate) deferred_closure_requirements: DeferredClosureRequirements<'tcx>, - pub(crate) polonius_context: Option, + pub(crate) polonius_context: Option>, } /// A collection of region constraints that must be satisfied for the From 8a4ca917839d90b183a7497a62c9fbb783e0da8e Mon Sep 17 00:00:00 2001 From: jackh726 Date: Fri, 28 Aug 2026 05:21:45 +0000 Subject: [PATCH 0584/1309] Defer nll-boring/polonius-relevant locals --- .../src/type_check/liveness/mod.rs | 66 ++++++++---- .../src/type_check/liveness/trace.rs | 102 ++++++++++++++++-- 2 files changed, 137 insertions(+), 31 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index fcfffaff9fcd1..6b9eae7428475 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -1,5 +1,5 @@ use itertools::{Either, Itertools}; -use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::fx::{FxHashSet, FxIndexSet}; use rustc_index::interval::IntervalSet; use rustc_middle::mir::visit::{TyContext, Visitor}; use rustc_middle::mir::{Body, Local, Location, SourceInfo}; @@ -45,35 +45,59 @@ pub(super) fn generate<'tcx>( typeck.constraints.liveness_constraints.add_all_points(region); } - let mut free_regions = regions_that_outlive_free_regions( + let free_regions = regions_that_outlive_free_regions( typeck.infcx.num_region_vars(), &typeck.universal_regions, &typeck.constraints.outlives_constraints, ); - // NLLs can avoid computing some liveness data here because its constraints are - // location-insensitive, but that doesn't work in polonius: locals whose type contains a region - // that outlives a free region are not necessarily live everywhere in a flow-sensitive setting, - // unlike NLLs. - // We do record these regions in the polonius context, since they're used to differentiate - // relevant and boring locals, which is a key distinction used later in diagnostics. - // This additional liveness information is ultimately used for *loan* liveness, - // so we don't need to compute it when there are no loans. + let (relevant_live_locals, boring_locals) = + compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); + + // Under Polonius Alpha, a larger set of locals are considered relevant: specifically, + // locals containing regions *outliving* universal regions are relevant and only + // locals containing solely universal regions are considered boring. + // + // However, we don't actually need liveness information for *all* these locals, + // only when actually computing loans. So, we can defer computing the liveness + // until we try to propagate the loan, which is gated on `LocalizedConstraintGraph` + // traversal. + // + // Potentially in theory, we could defer computing liveness for *all* locals, + // but that's a much bigger refactor (many things rely on liveness of + // NLL-relevant locals). So, we only defer NLL-boring/Polonius-relevant locals + // for now. // FIXME: this NLL optimization idea, to reduce work to relevant locals only, still makes sense // for polonius, and should be investigated to improve liveness performance. - if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() - && typeck.borrow_set.len() > 0 - { - let (_, boring_locals) = + let deferred_locals = 'deferred: { + // If we aren't going to be using the additional liveness information, + // don't even bother computing the larger relevant set. + // Similarly, since this liveness information is ultimately used for *loan* + // liveness, we don't need to compute it when there are no loans. + if typeck.polonius_context.is_none() || typeck.borrow_set.len() == 0 { + break 'deferred FxIndexSet::default(); + } + + let free_regions: FxHashSet = + typeck.universal_regions.universal_regions_iter().collect(); + let (polonius_relevant, _) = compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - typeck.polonius_context.as_mut().unwrap().boring_nll_locals = - boring_locals.into_iter().collect(); - free_regions = typeck.universal_regions.universal_regions_iter().collect(); - } - let (relevant_live_locals, boring_locals) = - compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - trace::trace(typeck, location_map, move_data, &relevant_live_locals, &boring_locals); + let boring: FxHashSet = boring_locals.iter().copied().collect(); + let deferred: FxIndexSet = + polonius_relevant.into_iter().filter(|local| boring.contains(local)).collect(); + typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring; + deferred + }; + + trace::trace( + typeck, + location_map, + move_data, + &relevant_live_locals, + &boring_locals, + &deferred_locals, + ); // Mark regions that should be live where they appear within rvalues or within a call: like // args, regions, and types. diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index a58f8bd8d931d..b70285214115f 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -46,10 +46,14 @@ pub(super) fn trace<'tcx>( move_data: &MoveData<'tcx>, relevant_live_locals: &[Local], boring_locals: &[Local], + deferred: &FxIndexSet, ) { let _timer = typeck.tcx().prof.generic_activity("borrowck_liveness_trace"); - let local_use_map = LocalUseMap::build(&relevant_live_locals, location_map, typeck.body); + // The use map must also cover the deferred locals: their liveness is computed later, from + // this same map, when the loan liveness traversal first reaches one of their regions. + let use_map_locals: Vec = relevant_live_locals.iter().chain(deferred).copied().collect(); + let local_use_map = LocalUseMap::build(&use_map_locals, location_map, typeck.body); let comp = LivenessComputation::new( typeck.infcx, typeck.body, @@ -60,13 +64,13 @@ pub(super) fn trace<'tcx>( let mut results = LivenessResults::new(typeck, comp); - let deferred_locals = DeferredLocals::default(); + let mut deferred_locals = DeferredLocals::default(); - results.record_legacy_polonius_drop_facts(relevant_live_locals); + results.record_legacy_polonius_drop_facts(relevant_live_locals, &deferred); results.compute_for_all_locals(relevant_live_locals); - results.dropck_boring_locals(boring_locals); + results.dropck_boring_locals(boring_locals, &deferred, &mut deferred_locals); if let Some(polonius_context) = &mut typeck.polonius_context { polonius_context.deferred_locals_for_liveness = deferred_locals; @@ -190,19 +194,94 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { /// These are all the locals which do not potentially reference a region local /// to this body. Locals which only reference free regions are always drop-live /// and can therefore safely be dropped. - fn dropck_boring_locals(&mut self, boring_locals: &[Local]) { + fn dropck_boring_locals( + &mut self, + boring_locals: &[Local], + deferred: &FxIndexSet, + deferred_locals: &mut DeferredLocals<'tcx>, + ) { for &local in boring_locals { - let local_ty = self.comp.body.local_decls[local].ty; - let local_span = self.comp.body.local_decls[local].source_info.span; - dropck_local(&self.typeck.infcx, &mut self.drop_data, local_ty, local_span); + self.dropck_boring_local(local, deferred, deferred_locals); + } + } + + fn dropck_boring_local( + &mut self, + local: Local, + deferred: &FxIndexSet, + deferred_locals: &mut DeferredLocals<'tcx>, + ) { + let typeck = &mut *self.typeck; + let local_ty = self.comp.body.local_decls[local].ty; + let local_span = self.comp.body.local_decls[local].source_info.span; + + // If we had treated this as "relevant", we would have run `compute_for_local`. This + // in turn would have skipped calculating dropck *at all* for locals without drop-liveness. + // Calculating drop-liveness is expensive, but we can skip it when we know that there + // are *no* drops (which is relatively cheap). + if deferred.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { + deferred_locals.defer_local( + typeck.infcx, + typeck.universal_regions, + local, + local_ty, + &[], + ); + return; + } + + // We need to compute dropck for *all* boring locals because we report overflows. + // + // FIXME: there is an argument to be made that we don't need to do this for boring locals + // without drop-liveness, because we skip it for *relevant* locals without drop-liveness. + // But, this is preexisting even on NLL, so leaving it for now. + let drop_data = dropck_local(&typeck.infcx, &mut self.drop_data, local_ty, local_span); + + // We are done with *truly* boring locals. + if !deferred.contains(&local) { + return; + } + + // If this local is deferred and has drop region constraints, we need to register + // them, but *only if the local is drop-live*. + // It doesn't really make sense to only check drop-liveness but defer use-liveness, + // so we just treat this as eager. + if drop_data.region_constraint_data.is_some() { + self.compute_for_local(local); + return; } + + // The only other thing we need to do *eagerly* for deferred locals is to register + // legacy drop facts (because these facts are on `typeck`). + for &kind in &drop_data.dropck_result.kinds { + polonius::legacy::emit_drop_facts( + typeck.tcx(), + local, + &kind, + typeck.universal_regions, + typeck.polonius_facts, + ); + } + + // Finally, we mark that this local is deferred, including the drop kinds. + deferred_locals.defer_local( + typeck.infcx, + typeck.universal_regions, + local, + local_ty, + &drop_data.dropck_result.kinds, + ); } /// Add extra drop facts needed for Polonius Legacy. /// /// Add facts for all locals with free regions, since regions may outlive /// the function body only at certain nodes in the CFG. - fn record_legacy_polonius_drop_facts(&mut self, relevant_live_locals: &[Local]) { + fn record_legacy_polonius_drop_facts( + &mut self, + relevant_live_locals: &[Local], + deferred: &FxIndexSet, + ) { // This is *all wonky* because this used to call a shared // `add_drop_live_facts_for` function that was also used for regular // relevant locals. Presumably, this can be cleaned up quite a bit. @@ -221,7 +300,10 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { .iter() .filter_map(|&(local, location_index)| { let local_ty = self.comp.body.local_decls[local].ty; - if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() { + if relevant_live_locals.contains(&local) + || deferred.contains(&local) + || !local_ty.has_free_regions() + { return None; } From 86b1e3d33c0164065a57e1930d73e1b5b45bdf81 Mon Sep 17 00:00:00 2001 From: jackh726 Date: Sat, 19 Sep 2026 17:55:03 +0000 Subject: [PATCH 0585/1309] Make RegionLiveness store points directly, add a couple inlines, and add timer --- compiler/rustc_borrowck/src/polonius/dump.rs | 2 +- compiler/rustc_borrowck/src/polonius/liveness.rs | 12 +++++++----- compiler/rustc_borrowck/src/polonius/mod.rs | 2 +- compiler/rustc_borrowck/src/region_infer/values.rs | 1 + .../rustc_borrowck/src/type_check/liveness/trace.rs | 2 ++ 5 files changed, 12 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index ec7f688b6423f..fff31691f4086 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -38,7 +38,7 @@ impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { region, self.live_region_variances, self.universal_regions, - self.liveness, + self.liveness.points(), ) } fn location_map(&self) -> &'a DenseLocationMap { diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 2864cbf3c1ce9..0bef063b0162c 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -1,4 +1,5 @@ use rustc_index::IndexVec; +use rustc_index::interval::{IntervalSet, SparseIntervalMatrix}; use rustc_middle::mir::Local; use rustc_middle::ty::{GenericArg, RegionVid, Ty}; use rustc_mir_dataflow::points::PointIndex; @@ -82,17 +83,17 @@ impl<'tcx> DeferredLocals<'tcx> { /// For a given region, the relevant liveness and variance information. pub(super) struct RegionLiveness<'a> { - region: RegionVid, pub(super) direction: ConstraintDirection, - liveness: &'a LivenessValues, + live_points: Option<&'a IntervalSet>, } impl<'a> RegionLiveness<'a> { + #[inline] pub(super) fn new<'tcx>( region: RegionVid, live_region_variances: &LiveRegionVariances, universal_regions: &UniversalRegions<'tcx>, - liveness: &'a LivenessValues, + live_points: &'a SparseIntervalMatrix, ) -> Self { // Universal regions propagate loans along the CFG, i.e. forwards only. let is_universal_region = universal_regions.is_universal_region(region); @@ -113,10 +114,11 @@ impl<'a> RegionLiveness<'a> { .flatten() .unwrap_or(ConstraintDirection::Bidirectional) }; - Self { region, direction, liveness } + let live_points = live_points.row(region); + Self { direction, live_points } } pub(super) fn is_live_at(&self, point: PointIndex) -> bool { - self.liveness.points().contains(self.region, point) + self.live_points.map_or(false, |points| points.contains(point)) } } diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 8e38f5a37048e..654c750dfccd1 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -205,7 +205,7 @@ impl<'a> LivenessSource<'a> for DeferredLivenessSource<'a, '_> { region, self.live_region_variances, self.universal_regions, - self.liveness, + self.liveness.points(), ) } diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index c7f4e520d3fad..6e4e9405e3ada 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -87,6 +87,7 @@ impl LivenessValues { /// Returns the liveness matrix of points where each region is live. Panics if the liveness /// values have been created without any per-point data (that is, for promoteds). + #[inline] pub(crate) fn points(&self) -> &SparseIntervalMatrix { if let LiveRegions::AtPoints(points) = &self.live_regions { points diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index b70285214115f..0811b66d43acf 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -398,6 +398,8 @@ impl<'a, 'tcx> LivenessComputation<'a, 'tcx> { ) where 'tcx: 'drop_data, { + let _timer = self.infcx.tcx.prof.generic_activity("borrowck_liveness_compute"); + self.reset_local_state(); self.add_defs_for(local); self.compute_use_live_points_for(local); From 240e41a85ec2fc1751848184f32ded19ed00e2b0 Mon Sep 17 00:00:00 2001 From: Augie Fackler Date: Mon, 21 Sep 2026 16:26:16 -0400 Subject: [PATCH 0586/1309] librustdoc: remove stale dep on base64 This appears to have become unused in August 2025. I noticed today because of trying to consolidate versions of things in the toolchain. --- Cargo.lock | 9 +-------- src/librustdoc/Cargo.toml | 1 - 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 5e57835c9cfef..97bea2f05c4ce 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -285,12 +285,6 @@ dependencies = [ "windows-targets", ] -[[package]] -name = "base64" -version = "0.21.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d297deb1925b89f2ccc13d7635fa0714f12c87adce1c75356b39ca9b7178567" - [[package]] name = "base64" version = "0.22.1" @@ -2135,7 +2129,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8bdc5a74b0feeb5e6a1dc2dd08c34280a61e37668d10a6a3b27ad69d0fb9ce2e" dependencies = [ "aho-corasick", - "base64 0.22.1", + "base64", "bstr", "jaq-core", "jiff", @@ -5051,7 +5045,6 @@ version = "0.0.0" dependencies = [ "arrayvec", "askama", - "base64 0.21.7", "expect-test", "indexmap", "itertools", diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml index 4d7895264c158..64fff96201939 100644 --- a/src/librustdoc/Cargo.toml +++ b/src/librustdoc/Cargo.toml @@ -11,7 +11,6 @@ path = "lib.rs" # tidy-alphabetical-start arrayvec = { version = "0.7", default-features = false } askama = { version = "0.16.1", default-features = false, features = ["alloc", "config", "derive"] } -base64 = "0.21.7" indexmap = { version = "2", features = ["serde"] } itertools = "0.15" libc = "0.2" From 3101cb2c3350543631f4d6b7bccd3828120e0572 Mon Sep 17 00:00:00 2001 From: Matt Turner Date: Sun, 20 Sep 2026 12:31:38 -0400 Subject: [PATCH 0587/1309] powerpc64: don't pass single-field or nested unions in FPRs on ELFv1 The ELFv1 ABI defines aggregates as structures and arrays; unions are consistently listed separately. A union is therefore never a "one member aggregate", not even when it has a single field or when it is nested within a structure or array. Extend the previous commit to reject any layout that is or contains a union. This matches GCC in all cases. Clang still passes single-field unions (including nested ones) in FPRs, contrary to the specification; https://github.com/llvm/llvm-project/pull/223481 fixes that. --- compiler/rustc_abi/src/callconv.rs | 4 + .../rustc_target/src/callconv/powerpc64.rs | 35 ++++++--- .../powerpc64-abi/homogeneous-aggregate.rs | 77 +++++++++++++++++++ 3 files changed, 104 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs index 4fda4735b613c..1bab82667232b 100644 --- a/compiler/rustc_abi/src/callconv.rs +++ b/compiler/rustc_abi/src/callconv.rs @@ -58,6 +58,10 @@ impl<'a, Ty> TyAndLayout<'a, Ty> { /// /// Note: We generally ignore 1-ZST fields when computing this value (see #56877). /// + /// Note: The fields of a union are merged as if it were a struct, so the result does not + /// distinguish the two. `powerpc64::is_or_contains_union` in `rustc_target` walks the layout + /// again to do that, mirroring the array handling here. + /// /// This is public so that it can be used in unit tests, but /// should generally only be relevant to the ABI details of /// specific targets. diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs index 5c31552bdcfcc..ca79a52d2874f 100644 --- a/compiler/rustc_target/src/callconv/powerpc64.rs +++ b/compiler/rustc_target/src/callconv/powerpc64.rs @@ -15,27 +15,38 @@ enum ABI { } use ABI::*; -/// Whether `layout` is or contains a union with more than one non-1-ZST field. +/// Whether `layout` is or contains a union. /// -/// `homogeneous_aggregate` merges the fields of a union, so it cannot tell such a union from a -/// structure. This walks the layout a second time; keep the array and 1-ZST handling here in sync -/// with `homogeneous_aggregate`. -fn contains_multi_field_union<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool +/// `homogeneous_aggregate` merges the fields of a union, so it cannot tell a union from a +/// structure. This walks the layout a second time; keep the array handling here in sync with +/// `homogeneous_aggregate`. ZSTs are ignored entirely, as both GCC and Clang do. +/// +/// This does not look at enums that are represented as unions at the ABI level (e.g. a +/// `#[repr(C)]` enum with fields). That does not matter here: enums can only have integer +/// discriminants, and `is_homogeneous_aggregate` rejects anything containing an integer, so an +/// enum can never be a float or vector homogeneous aggregate. +fn is_or_contains_union<'a, Ty, C>(cx: &C, layout: TyAndLayout<'a, Ty>) -> bool where Ty: TyAbiInterface<'a, C> + Copy, C: HasDataLayout, { - let fields = - || (0..layout.fields.count()).map(|i| layout.field(cx, i)).filter(|f| !f.is_1zst()); + if layout.is_zst() { + return false; + } match layout.fields { FieldsShape::Primitive => false, + // A `repr(transparent)` union is guaranteed to be ABI-compatible with its single + // non-1-ZST field, so look through it instead of rejecting it. FieldsShape::Union(_) => { - fields().count() > 1 || fields().any(|f| contains_multi_field_union(cx, f)) + match layout.non_1zst_field(cx).filter(|_| layout.is_transparent()) { + Some((_, field)) => is_or_contains_union(cx, field), + None => true, + } } - FieldsShape::Array { count, .. } => { - count > 0 && contains_multi_field_union(cx, layout.field(cx, 0)) + FieldsShape::Array { .. } => is_or_contains_union(cx, layout.field(cx, 0)), + FieldsShape::Arbitrary { .. } => { + (0..layout.fields.count()).any(|i| is_or_contains_union(cx, layout.field(cx, i))) } - FieldsShape::Arbitrary { .. } => fields().any(|f| contains_multi_field_union(cx, f)), } } @@ -52,7 +63,7 @@ where // ELFv1 and AIX only passes one-member aggregates transparently. // ELFv2 passes up to eight uniquely addressable members. if ((abi == ELFv1 || abi == AIX) - && (arg.layout.size > unit.size || contains_multi_field_union(cx, arg.layout))) + && (arg.layout.size > unit.size || is_or_contains_union(cx, arg.layout))) || arg.layout.size > unit.size.checked_mul(8, cx).unwrap() { return None; diff --git a/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs index 5e247092cb643..58dd9c837603f 100644 --- a/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs +++ b/tests/codegen-llvm/powerpc64-abi/homogeneous-aggregate.rs @@ -145,3 +145,80 @@ pub struct OneFloatAndZstUnion { pub extern "C" fn test_struct_one_float_and_zst_union(a: OneFloatAndZstUnion) { hint::black_box(a); } + +// On ELFv1 unions are not considered aggregates for the ABI, so they are never passed in a +// floating point register, not even when they have a single field or are nested within an +// aggregate. See https://github.com/rust-lang/rust/issues/162011. +#[repr(C)] +pub union OneFloat { + pub a: f32, +} + +// ppc64: define void @test_union_one_float(i32 %0) +// ppc64_vsx: define void @test_union_one_float(i32 %0) +// ppc64le: define void @test_union_one_float(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_union_one_float(a: OneFloat) { + hint::black_box(a); +} + +#[repr(C)] +pub struct StructOfUnion { + pub u: OneFloat, +} + +// ppc64: define void @test_struct_of_union(i32 %0) +// ppc64_vsx: define void @test_struct_of_union(i32 %0) +// ppc64le: define void @test_struct_of_union(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_struct_of_union(a: StructOfUnion) { + hint::black_box(a); +} + +#[repr(C)] +pub union UnionOfStruct { + pub s: OneFloatStruct, +} + +// ppc64: define void @test_union_of_struct(i32 %0) +// ppc64_vsx: define void @test_union_of_struct(i32 %0) +// ppc64le: define void @test_union_of_struct(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_union_of_struct(a: UnionOfStruct) { + hint::black_box(a); +} + +// A `repr(transparent)` union like `MaybeUninit` is guaranteed to be ABI-compatible with its single +// non-1-ZST field, so it is passed in a floating point register like the field would be. +// +// ppc64: define void @test_transparent_union_one_float(float %a) +// ppc64_vsx: define void @test_transparent_union_one_float(float %a) +// ppc64le: define void @test_transparent_union_one_float(float %a) +#[unsafe(no_mangle)] +pub extern "C" fn test_transparent_union_one_float(a: MaybeUninit) { + hint::black_box(a); +} + +#[repr(C)] +pub struct StructOfTransparentUnion { + pub u: MaybeUninit, +} + +// ppc64: define void @test_struct_of_transparent_union(float %0) +// ppc64_vsx: define void @test_struct_of_transparent_union(float %0) +// ppc64le: define void @test_struct_of_transparent_union(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_struct_of_transparent_union(a: StructOfTransparentUnion) { + hint::black_box(a); +} + +// A `repr(transparent)` union whose field is itself a union is still not passed in a floating +// point register on ELFv1. +// +// ppc64: define void @test_transparent_union_of_union(i32 %0) +// ppc64_vsx: define void @test_transparent_union_of_union(i32 %0) +// ppc64le: define void @test_transparent_union_of_union(float %0) +#[unsafe(no_mangle)] +pub extern "C" fn test_transparent_union_of_union(a: MaybeUninit) { + hint::black_box(a); +} From 931b8bb93ad7cef2915f64743ca6c3a1e616b149 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Mon, 21 Sep 2026 21:05:25 +0000 Subject: [PATCH 0588/1309] Point at `'static` receiver ``` note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:16:18 | LL | impl dyn Foo { LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here ``` --- .../src/diagnostics/region_errors.rs | 33 +++++++++++- .../lifetimes/static-impl-obligation.stderr | 53 +++++++++++++++---- 2 files changed, 74 insertions(+), 12 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a8ba8127dd83a..acfcc95d08257 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -439,7 +439,7 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { return; }; let def_id = instance.def_id(); - let bounds = + let mut bounds = tcx.clauses_of(def_id) .instantiate(tcx, instance.args) .into_iter() @@ -455,6 +455,37 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { }) .map(|(_, sp)| sp) .collect::>(); + + // Look at the receiver for `&'static self`, which introduces a `'static` obligation. + // ``` + // impl Foo { + // fn foo(&'static self) {} + // ^^^^^^^^^^^^^ + // ``` + if let Some(recv) = + tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) + && let ty::Ref(region, _, _) = recv.kind() + && *region == tcx.lifetimes.re_static + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.is_method() + { + let def_span = tcx.def_span(def_id); + // We have a `&'static self` receiver. + if let Some(def_id) = def_id.as_local() + && let owner = tcx.expect_hir_owner_node(def_id) + && let Some(decl) = owner.fn_decl() + && let Some(ty) = decl.inputs.get(0) + { + // Point at the `&'static self` receiver. + bounds.push(ty.span); + } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + // The method is not defined on the local crate, point at the signature instead of + // just the receiver as an approximation. We don't add it if there are already + // other spans with overlap with the def `Span`, as the other will be more specific. + bounds.push(def_span) + } + } + if !bounds.is_empty() { let mut multispan: MultiSpan = bounds.clone().into(); for span in bounds { diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 8b080d11ddf98..3fe8162ed519d 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -148,7 +148,7 @@ note: `'static` lifetime requirement from `v::MyTrait::use_self` introduced here LL | trait MyTrait where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn use_self(&'static self) -> &() { panic!() } - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ {} @@ -181,6 +181,13 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:16:18 + | +LL | impl dyn Foo { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:31:9 @@ -197,11 +204,13 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:27:45 + --> $DIR/static-impl-obligation.rs:27:18 | LL | impl dyn Foo { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:42:9 @@ -251,6 +260,13 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:60:18 + | +LL | impl dyn Foo + 'static { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:75:9 @@ -267,11 +283,13 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:71:45 + --> $DIR/static-impl-obligation.rs:71:18 | LL | impl dyn Foo + 'static { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:86:9 @@ -336,7 +354,7 @@ note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` intr LL | impl dyn Foo where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:119:9 @@ -358,7 +376,9 @@ note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` intr LL | impl dyn Foo where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:130:9 @@ -424,7 +444,7 @@ note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` intr LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} - | + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:163:9 @@ -446,7 +466,9 @@ note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` intr LL | impl dyn Foo + 'static where Self: 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:174:9 @@ -482,6 +504,13 @@ LL | x.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `q::Foo::hello` introduced here + --> $DIR/static-impl-obligation.rs:180:18 + | +LL | impl Foo { +LL | fn hello(&'static self) {} + | ^^^^^^^^^^^^^ lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:192:9 @@ -497,11 +526,13 @@ LL | x.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `r::Foo::hello` introduced here - --> $DIR/static-impl-obligation.rs:189:45 + --> $DIR/static-impl-obligation.rs:189:18 | LL | impl Foo { LL | fn hello(&'static self) where Self: 'static {} - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:206:9 From 16ede108f08f85dbbac01dc4cc3318f092d1893f Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 22 Sep 2026 00:42:42 +0200 Subject: [PATCH 0589/1309] library: prune allowed lints --- library/alloc/src/alloc.rs | 1 - library/alloc/src/lib.rs | 1 - library/alloctests/lib.rs | 1 - library/core/src/alloc/mod.rs | 2 +- library/core/src/lib.rs | 1 - library/core/src/num/int_macros.rs | 3 --- library/core/src/panic/panic_info.rs | 2 +- library/core/src/str/mod.rs | 1 - library/std/src/alloc.rs | 1 - library/std/src/env.rs | 2 +- library/std/src/lib.rs | 31 +++++++++++++--------------- library/std/src/num/f32.rs | 2 +- library/std/src/num/f64.rs | 2 +- 13 files changed, 19 insertions(+), 31 deletions(-) diff --git a/library/alloc/src/alloc.rs b/library/alloc/src/alloc.rs index 0846063cbc175..f921bc292568d 100644 --- a/library/alloc/src/alloc.rs +++ b/library/alloc/src/alloc.rs @@ -663,7 +663,6 @@ pub const fn handle_alloc_error(layout: Layout) -> ! { #[cfg(not(no_global_oom_handling))] #[doc(hidden)] -#[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] pub mod __alloc_error_handler { // called via generated `__rust_alloc_error_handler` if there is no diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs index acdc22ac5b331..664e3a4b1e218 100644 --- a/library/alloc/src/lib.rs +++ b/library/alloc/src/lib.rs @@ -58,7 +58,6 @@ #![allow(unused_features)] #![allow(incomplete_features)] -#![allow(unused_attributes)] #![expect(clippy::partialeq_ne_impl, reason = "we need to implement ne for a lot of alloc types")] #![stable(feature = "alloc", since = "1.36.0")] #![doc( diff --git a/library/alloctests/lib.rs b/library/alloctests/lib.rs index 3c26ecf9875e2..50c58092bd41a 100644 --- a/library/alloctests/lib.rs +++ b/library/alloctests/lib.rs @@ -1,5 +1,4 @@ #![cfg(test)] -#![allow(unused_attributes)] #![unstable(feature = "alloctests", issue = "none")] #![no_std] // Lints: diff --git a/library/core/src/alloc/mod.rs b/library/core/src/alloc/mod.rs index 6069c468f96e4..9acd3dd12a64c 100644 --- a/library/core/src/alloc/mod.rs +++ b/library/core/src/alloc/mod.rs @@ -15,7 +15,7 @@ pub use self::layout::Layout; note = "Name does not follow std convention, use LayoutError", suggestion = "LayoutError" )] -#[allow(deprecated, deprecated_in_future)] +#[allow(deprecated)] pub use self::layout::LayoutErr; #[stable(feature = "alloc_layout_error", since = "1.50.0")] pub use self::layout::LayoutError; diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs index c215560122022..d7d8d32ed88e7 100644 --- a/library/core/src/lib.rs +++ b/library/core/src/lib.rs @@ -367,7 +367,6 @@ pub mod primitive; unused_imports, unsafe_op_in_unsafe_fn, ambiguous_glob_reexports, - deprecated_in_future, unreachable_pub, // FIXME: stdach is a submodule so clippy lints should be fixed (and ideally enforced) there clippy::all, diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs index bb37a734824fa..4cbd012e0021b 100644 --- a/library/core/src/num/int_macros.rs +++ b/library/core/src/num/int_macros.rs @@ -2485,7 +2485,6 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[allow(unused_attributes)] #[inline] pub const fn wrapping_abs(self) -> Self { if self.is_negative() { @@ -2978,7 +2977,6 @@ macro_rules! int_impl { #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] #[must_use = "this returns the result of the operation, \ without modifying the original"] - #[allow(unused_attributes)] pub const fn overflowing_neg(self) -> (Self, bool) { if intrinsics::unlikely(self == Self::MIN) { (Self::MIN, true) @@ -3630,7 +3628,6 @@ macro_rules! int_impl { /// ``` #[stable(feature = "rust1", since = "1.0.0")] #[rustc_const_stable(feature = "const_int_methods", since = "1.32.0")] - #[allow(unused_attributes)] #[must_use = "this returns the result of the operation, \ without modifying the original"] #[inline] diff --git a/library/core/src/panic/panic_info.rs b/library/core/src/panic/panic_info.rs index ee22521cb014c..a5448b39ad7c0 100644 --- a/library/core/src/panic/panic_info.rs +++ b/library/core/src/panic/panic_info.rs @@ -106,7 +106,7 @@ impl<'a> PanicInfo<'a> { /// [`std::panic::PanicHookInfo::payload`]: ../../std/panic/struct.PanicHookInfo.html#method.payload #[deprecated(since = "1.81.0", note = "this never returns anything useful")] #[stable(feature = "panic_hooks", since = "1.10.0")] - #[allow(deprecated, deprecated_in_future)] + #[allow(deprecated)] pub fn payload(&self) -> &(dyn crate::any::Any + Send) { struct NoPayload; &NoPayload diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs index cc96e51d83393..99eb935cb2715 100644 --- a/library/core/src/str/mod.rs +++ b/library/core/src/str/mod.rs @@ -510,7 +510,6 @@ impl str { #[rustc_const_stable(feature = "str_as_bytes", since = "1.39.0")] #[must_use] #[inline(always)] - #[allow(unused_attributes)] pub const fn as_bytes(&self) -> &[u8] { // SAFETY: const sound because we transmute two types with the same layout unsafe { mem::transmute(self) } diff --git a/library/std/src/alloc.rs b/library/std/src/alloc.rs index 558ab0f2fc66d..8e0143c137b5e 100644 --- a/library/std/src/alloc.rs +++ b/library/std/src/alloc.rs @@ -444,7 +444,6 @@ pub fn rust_oom(layout: Layout) -> ! { #[cfg(not(test))] #[doc(hidden)] -#[allow(unused_attributes)] #[unstable(feature = "alloc_internals", issue = "none")] pub mod __default_lib_allocator { use super::Layout; diff --git a/library/std/src/env.rs b/library/std/src/env.rs index 762ad071e967c..07645debe82be 100644 --- a/library/std/src/env.rs +++ b/library/std/src/env.rs @@ -592,7 +592,7 @@ impl fmt::Display for JoinPathsError { #[stable(feature = "env", since = "1.0.0")] impl Error for JoinPathsError { - #[allow(deprecated, deprecated_in_future)] + #[allow(deprecated)] fn description(&self) -> &str { self.inner.description() } diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs index 3f853df52bc53..acc8cdfc8281d 100644 --- a/library/std/src/lib.rs +++ b/library/std/src/lib.rs @@ -244,7 +244,6 @@ #![warn(unreachable_pub)] #![warn(missing_debug_implementations)] #![allow(explicit_outlives_requirements)] -#![allow(unused_lifetimes)] #![allow(internal_features)] #![deny(implicit_provenance_casts)] #![deny(unsafe_op_in_unsafe_fn)] @@ -539,24 +538,24 @@ pub use core::future; #[stable(feature = "core_hint", since = "1.27.0")] pub use core::hint; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::i8; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::i16; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::i32; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::i64; #[stable(feature = "i128", since = "1.26.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::i128; #[stable(feature = "rust1", since = "1.0.0")] pub use core::intrinsics; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::isize; #[stable(feature = "rust1", since = "1.0.0")] pub use core::iter; @@ -577,24 +576,24 @@ pub use core::range; #[stable(feature = "rust1", since = "1.0.0")] pub use core::result; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::u8; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::u16; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::u32; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::u64; #[stable(feature = "i128", since = "1.26.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::u128; #[unstable(feature = "unsafe_binders", issue = "130516")] pub use core::unsafe_binder; #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::usize; #[stable(feature = "rust1", since = "1.0.0")] @@ -740,7 +739,7 @@ pub mod alloc; mod panicking; #[path = "../../backtrace/src/lib.rs"] -#[allow(dead_code, unused_attributes, implicit_provenance_casts, unsafe_op_in_unsafe_fn)] +#[allow(implicit_provenance_casts, unsafe_op_in_unsafe_fn)] #[allow(clippy::len_zero, clippy::needless_borrow, clippy::filter_map_next)] // FIXME mod backtrace_rs; @@ -760,12 +759,10 @@ pub use core::concat_bytes; #[unstable(feature = "derive_macro_global_path", issue = "154645")] pub use core::derive; #[stable(feature = "matches_macro", since = "1.42.0")] -#[allow(deprecated, deprecated_in_future)] pub use core::matches; #[stable(feature = "core_primitive", since = "1.43.0")] pub use core::primitive; #[stable(feature = "todo_macro", since = "1.40.0")] -#[allow(deprecated, deprecated_in_future)] pub use core::todo; // Re-export built-in macros defined through core. #[stable(feature = "builtin_macro_prelude", since = "1.38.0")] @@ -776,7 +773,7 @@ pub use core::{ }; // Re-export macros defined in core. #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future)] +#[expect(deprecated, reason = "`try! macro")] pub use core::{ assert_eq, assert_ne, debug_assert, debug_assert_eq, debug_assert_ne, r#try, unimplemented, unreachable, write, writeln, diff --git a/library/std/src/num/f32.rs b/library/std/src/num/f32.rs index b89c71dd1abe1..5792d236b4e89 100644 --- a/library/std/src/num/f32.rs +++ b/library/std/src/num/f32.rs @@ -13,7 +13,7 @@ #![allow(missing_docs)] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::f32::{ DIGITS, EPSILON, INFINITY, MANTISSA_DIGITS, MAX, MAX_10_EXP, MAX_EXP, MIN, MIN_10_EXP, MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX, consts, diff --git a/library/std/src/num/f64.rs b/library/std/src/num/f64.rs index c3f5d8cca6014..8ca38cc0be69e 100644 --- a/library/std/src/num/f64.rs +++ b/library/std/src/num/f64.rs @@ -13,7 +13,7 @@ #![allow(missing_docs)] #[stable(feature = "rust1", since = "1.0.0")] -#[allow(deprecated, deprecated_in_future, clippy::legacy_numeric_constants)] +#[allow(deprecated, clippy::legacy_numeric_constants)] pub use core::f64::{ DIGITS, EPSILON, INFINITY, MANTISSA_DIGITS, MAX, MAX_10_EXP, MAX_EXP, MIN, MIN_10_EXP, MIN_EXP, MIN_POSITIVE, NAN, NEG_INFINITY, RADIX, consts, From 99ad5253410791aed55a6587057c29f4e4d115cd Mon Sep 17 00:00:00 2001 From: Shun Sakai Date: Tue, 22 Sep 2026 08:34:00 +0900 Subject: [PATCH 0590/1309] feat(time): add `Duration::{WEEK, DAY, HOUR, MINUTE}` --- library/core/src/time.rs | 80 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) diff --git a/library/core/src/time.rs b/library/core/src/time.rs index c123c66ee3bc0..6f33fdd36e53b 100644 --- a/library/core/src/time.rs +++ b/library/core/src/time.rs @@ -136,6 +136,86 @@ impl Duration { #[unstable(feature = "duration_constants", issue = "57391")] pub const NANOSECOND: Duration = Duration::from_nanos(1); + /// The duration of one week. + /// + /// For this constant, one week is defined as 7 days, or 604,800 seconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let week = Duration::WEEK; + /// + /// assert_eq!(week, Duration::from_weeks(1)); + /// assert_eq!(week.as_secs(), 604_800); + /// assert_eq!(week.subsec_nanos(), 0); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + // Also, #[unstable(feature = "duration_constructors", issue = "120301")] + pub const WEEK: Duration = Duration::from_weeks(1); + + /// The duration of one day. + /// + /// For this constant, one day is defined as 24 hours, or 86,400 seconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// #![feature(duration_constructors)] + /// use std::time::Duration; + /// + /// let day = Duration::DAY; + /// + /// assert_eq!(day, Duration::from_days(1)); + /// assert_eq!(day.as_secs(), 86400); + /// assert_eq!(day.subsec_nanos(), 0); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + // Also, #[unstable(feature = "duration_constructors", issue = "120301")] + pub const DAY: Duration = Duration::from_days(1); + + /// The duration of one hour. + /// + /// For this constant, one hour is defined as 60 minutes, or 3,600 seconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// let hour = Duration::HOUR; + /// + /// assert_eq!(hour, Duration::from_hours(1)); + /// assert_eq!(hour.as_secs(), 3600); + /// assert_eq!(hour.subsec_nanos(), 0); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const HOUR: Duration = Duration::from_hours(1); + + /// The duration of one minute. + /// + /// For this constant, one minute is defined as 60 seconds. + /// + /// # Examples + /// + /// ``` + /// #![feature(duration_constants)] + /// use std::time::Duration; + /// + /// let minute = Duration::MINUTE; + /// + /// assert_eq!(minute, Duration::from_mins(1)); + /// assert_eq!(minute.as_secs(), 60); + /// assert_eq!(minute.subsec_nanos(), 0); + /// ``` + #[unstable(feature = "duration_constants", issue = "57391")] + pub const MINUTE: Duration = Duration::from_mins(1); + /// A duration of zero time. /// /// # Examples From 398b396390732ee60f3d4d916073eb162cf809a5 Mon Sep 17 00:00:00 2001 From: Yilin Chen <1479826151@qq.com> Date: Tue, 22 Sep 2026 09:40:09 +0800 Subject: [PATCH 0591/1309] Document safety requirements for intrinsic fallbacks --- library/core/src/intrinsics/fallback.rs | 27 +++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/library/core/src/intrinsics/fallback.rs b/library/core/src/intrinsics/fallback.rs index d2794a5b1202d..3e6829ab16b18 100644 --- a/library/core/src/intrinsics/fallback.rs +++ b/library/core/src/intrinsics/fallback.rs @@ -112,8 +112,13 @@ const impl CarryingMulAdd for i128 { #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] pub const trait DisjointBitOr: Copy + 'static { - /// See [`super::disjoint_bitor`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::disjoint_bitor`], with `self` corresponding to `a` and + /// `other` corresponding to `b`. unsafe fn disjoint_bitor(self, other: Self) -> Self; } macro_rules! zero { @@ -149,12 +154,22 @@ impl_disjoint_bitor! { #[rustc_const_unstable(feature = "core_intrinsics_fallbacks", issue = "none")] pub const trait FunnelShift: Copy + 'static { - /// See [`super::unchecked_funnel_shl`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::unchecked_funnel_shl`], with `self` corresponding to `a` and + /// `right` corresponding to `b`. unsafe fn unchecked_funnel_shl(self, right: Self, shift: u32) -> Self; - /// See [`super::unchecked_funnel_shr`]; we just need the trait indirection to handle - /// different types since calling intrinsics with generics doesn't work. + /// We just need the trait indirection to handle different types + /// since calling intrinsics with generics doesn't work. + /// + /// # Safety + /// + /// See [`super::unchecked_funnel_shr`], with `self` corresponding to `a` and + /// `right` corresponding to `b`. unsafe fn unchecked_funnel_shr(self, right: Self, shift: u32) -> Self; } From 63dfd1cfe20e444d366083b0564df006664944a1 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 02:39:48 -0400 Subject: [PATCH 0592/1309] chore: Prepare CHANGELOG for v1.11.0 release --- CHANGELOG.md | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b6d9a3b8dc82..0b05c62419fa0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,47 @@ ## [Unreleased] +### Fixed +- Preserve attributes on `fn` type parameters [#6590](https://github.com/rust-lang/rustfmt/pull/6590). +- Preserve inner attributes from `loop`, `for` and `while` expressions [#6010](https://github.com/rust-lang/rustfmt/pull/6010). +- Fixed ICE when formatting inner attributes of a loop body defined inside a closure [#6978](https://github.com/rust-lang/rustfmt/pull/6978). +- Fixed ICE when whitespace separated `macro_rules` and `!` [#6990](https://github.com/rust-lang/rustfmt/pull/6990). +- Correct `#[cfg]` struct field pattern indentation when using `style_edition=2027` [#6983](https://github.com/rust-lang/rustfmt/pull/6983). +- rustfmt now wraps a braceless closure that ends with an open range in parentheses if it's followed by a field access. For example, `|| 1.. .field` is formatted as `(|| 1..).field` [#7013](https://github.com/rust-lang/rustfmt/pull/7013). +- Handle `cargo fmt --manifest-path` correctly when specifying the workspace's root `Cargo.toml` [#6524](https://github.com/rust-lang/rustfmt/pull/6524). +- Prevent comment duplication between attributes and struct field patterns [#7004](https://github.com/rust-lang/rustfmt/pull/7004). +- Fix char boundary panics when reporting formatting errors [#7029](https://github.com/rust-lang/rustfmt/pull/7029). +- Correct comment wrapping at or before `comment_width` when using `wrap_comments=true` [#6802](https://github.com/rust-lang/rustfmt/pull/6802). +- Adjust opening brace placement when setting `style_edition=2027` to better align with the style guide for multi-line control flow expressions [#7005](https://github.com/rust-lang/rustfmt/pull/7005). +- Remove repeated `--style-edition` CLI help text [#7050](https://github.com/rust-lang/rustfmt/pull/7050). +- Fix ICE when `for await` had extra whitespace between `for` and `await` [#7063](https://github.com/rust-lang/rustfmt/pull/7063). +- Use the correct span when rewriting `ast::TyKind::FnPtr` to prevent comment recovery code from copying `cfg_attr` content into `fn` type [#7066](https://github.com/rust-lang/rustfmt/pull/7066). +- Prevent infinite loops when parsing items from `cfg_select!` arms [#7089](https://github.com/rust-lang/rustfmt/pull/7089). +- Correct visibility and defaultness order on associated impl type alias [#7064](https://github.com/rust-lang/rustfmt/pull/7064). +- Correctly calculate the `shape` for inline const blocks when using `style_edition=2027` [#7065](https://github.com/rust-lang/rustfmt/pull/7065). +- Prevent invalid code generation in macros that use raw identifiers [#7110](https://github.com/rust-lang/rustfmt/pull/7110). +- Prevent rustfmt from reporting on `max_width` configuration issues when formatting macros [#6651](https://github.com/rust-lang/rustfmt/pull/6651). + +### Changed +- No longer apply `use_field_init_shorthand` when formatting macros [#6981](https://github.com/rust-lang/rustfmt/pull/6981). +- Include trailing commas when rewriting single parameter `fn` declaration when setting `style_edition=2027` and `fn_params_layout="Vertical"` [#6890](https://github.com/rust-lang/rustfmt/pull/6890). +- The rustfmt CLI now prevents users from setting `--check` and `--config=emit_mode` as well as `--config=emit_mode` and `--emit` [#7002](https://github.com/rust-lang/rustfmt/pull/7002). +> [!IMPORTANT] +> Potential breaking changes. +> - Formatting doc comments within macros is now more consistent across doc-comment styles. For example, `///` vs `#[doc]`. Users may notice indentation changes `[#7042](https://github.com/rust-lang/rustfmt/pull/7042). +> - Block doc-comment closer formatting change to prevent an idempotence issue. This might impact users who use block doc-comments [#7017](https://github.com/rust-lang/rustfmt/pull/7017). +> - Correct binary operator expression indentation when using `hard_tabs=true`. Binary expression formatting might change if you're using `hard_tabs=true` [#6883](https://github.com/rust-lang/rustfmt/pull/6883). + +### Added +- Support formatting for `#![feature(generic_const_items)]` [#6956](https://github.com/rust-lang/rustfmt/pull/6956). +- Format `cfg_select!` macros on the nightly release channel [rust-lang/rust#154202](https://github.com/rust-lang/rust/pull/154202) [rust-lang/rust#160998](https://github.com/rust-lang/rust/pull/160998). + +### Misc +- Bump `annotate-snippets` to 0.12 [#6947](https://github.com/rust-lang/rustfmt/pull/6947). +- Bump `toml` to 1.1 [#7008](https://github.com/rust-lang/rustfmt/pull/7008). +- Bump `tracing-subscriber` to 0.3.20 [#6760](https://github.com/rust-lang/rustfmt/pull/6760) [#6772](https://github.com/rust-lang/rustfmt/pull/6772). +- Add clippy linting to all rustfmt packages [#7116](https://github.com/rust-lang/rustfmt/pull/7116) [#7124](https://github.com/rust-lang/rustfmt/pull/7124). + ## [1.10.0] 2026-07-21 From 100e50e882685f4146b65ddc653d69cdefbe2f16 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 02:52:41 -0400 Subject: [PATCH 0593/1309] chore: Prepare v1.11.0 release --- CHANGELOG.md | 4 ++++ Cargo.lock | 2 +- Cargo.toml | 2 +- 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0b05c62419fa0..f242b71c12e9b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,10 @@ ## [Unreleased] + + +## [1.11.0] 2026-11-12 + ### Fixed - Preserve attributes on `fn` type parameters [#6590](https://github.com/rust-lang/rustfmt/pull/6590). - Preserve inner attributes from `loop`, `for` and `while` expressions [#6010](https://github.com/rust-lang/rustfmt/pull/6010). diff --git a/Cargo.lock b/Cargo.lock index 9ba1ded57c853..5126167ca22ed 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -573,7 +573,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.10.0" +version = "1.11.0" dependencies = [ "annotate-snippets", "anyhow", diff --git a/Cargo.toml b/Cargo.toml index 7e4d2e60565b3..bf1474284ad05 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "rustfmt-nightly" -version = "1.10.0" +version = "1.11.0" description = "Tool to find and fix Rust formatting issues" repository = "https://github.com/rust-lang/rustfmt" license = "Apache-2.0 OR MIT" From 51aa65eabb4bd69f8c1fa46cd0c0e9a333145a83 Mon Sep 17 00:00:00 2001 From: Yacin Tmimi Date: Mon, 21 Sep 2026 22:25:57 -0400 Subject: [PATCH 0594/1309] chore: bump rustfmt version to v1.11.0 --- Cargo.lock | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index 5e57835c9cfef..bc62ae98e0372 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5131,7 +5131,7 @@ dependencies = [ [[package]] name = "rustfmt-nightly" -version = "1.10.0" +version = "1.11.0" dependencies = [ "annotate-snippets 0.12.16", "anyhow", From 819623a338ec917162444961a2b7fc51cbe312aa Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 3 Sep 2026 12:41:47 +0000 Subject: [PATCH 0595/1309] don't merge distinct impl candidates --- .../src/solve/trait_goals.rs | 27 ++++++++++++++++--- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 902ad882f2123..d6a96f1e487f3 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1493,14 +1493,31 @@ where } } + fn has_distinct_impl_candidates( + &self, + trait_def_id: I::TraitId, + candidates: &[Candidate], + ) -> bool { + let impls = + candidates.iter().filter(|c| matches!(c.source, CandidateSource::Impl(_))).count(); + let builtin_impls = + candidates.iter().any(|c| matches!(c.source, CandidateSource::BuiltinImpl(_))); + impls + builtin_impls as usize > 1 && !self.cx().trait_is_marker(trait_def_id) + } + #[instrument(level = "debug", skip(self), ret)] pub(super) fn merge_trait_candidates( &mut self, - candidate_preference_mode: CandidatePreferenceMode, + trait_def_id: I::TraitId, mut candidates: Vec>, failed_candidate_info: FailedCandidateInfo, ) -> Result<(CanonicalResponse, Option), NoSolution> { + let candidate_preference_mode = CandidatePreferenceMode::compute(self.cx(), trait_def_id); if self.typing_mode().is_coherence() { + if self.has_distinct_impl_candidates(trait_def_id, &candidates) { + return self.flounder(&candidates).map(|r| (r, None)); + } + return if let Some((response, _)) = self.try_merge_candidates(&candidates) { Ok((response, Some(TraitGoalProvenVia::Misc))) } else { @@ -1613,6 +1630,10 @@ where TraitGoalProvenVia::Misc }; + if self.has_distinct_impl_candidates(trait_def_id, &candidates) { + return self.flounder(&candidates).map(|r| (r, None)); + } + if let Some((response, _)) = self.try_merge_candidates(&candidates) { Ok((response, Some(proven_via))) } else { @@ -1628,9 +1649,7 @@ where { let (candidates, failed_candidate_info) = self.assemble_and_evaluate_candidates(goal, AssembleCandidatesFrom::All)?; - let candidate_preference_mode = - CandidatePreferenceMode::compute(self.cx(), goal.predicate.def_id()); - self.merge_trait_candidates(candidate_preference_mode, candidates, failed_candidate_info) + self.merge_trait_candidates(goal.predicate.def_id(), candidates, failed_candidate_info) .map_err(Into::into) } From f002f33ab880b5b85aee27a94d051d6ae3d59006 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 3 Sep 2026 12:41:47 +0000 Subject: [PATCH 0596/1309] drop specialized impls with equal inference constraints --- compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 51e1aea3850e4..38afd45370c26 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1054,6 +1054,7 @@ where // the only allowed region constraints may be constraints also present on the default impl. if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes) || has_only_region_constraints(c.result) + || c.result == candidates[i].result { if self.cx().impl_specializes(other_def_id, victim_def_id) { candidates.remove(i); From ffa9001a7062af82546074304e56e0d5a9fedfa9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 03:56:31 +0000 Subject: [PATCH 0597/1309] Point at `impl dyn Trait` `'static` obligation ``` note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:4:5 | LL | impl dyn Foo { | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | ``` --- .../src/diagnostics/region_errors.rs | 70 ++++++++++++------- .../lifetimes/static-impl-obligation.stderr | 42 +++++++++-- tests/ui/regions/issue-78262.base.stderr | 8 +++ tests/ui/regions/issue-78262.polonius.stderr | 8 +++ .../regions-static-bound-on-type-param.stderr | 2 + ...yn-trait-with-implicit-static-bound.stderr | 21 ++++++ 6 files changed, 119 insertions(+), 32 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index acfcc95d08257..a085ffa64d409 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -430,9 +430,10 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { let ty::FnDef(def_id, args) = ty.kind() else { return; }; + let typing_env = self.infcx.typing_env(self.infcx.param_env); let Ok(Some(instance)) = ty::Instance::try_resolve( tcx, - self.infcx.typing_env(self.infcx.param_env), + typing_env, *def_id, self.infcx.deeply_resolve_ignoring_regions(args.no_bound_vars().unwrap()), ) else { @@ -456,33 +457,51 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .map(|(_, sp)| sp) .collect::>(); - // Look at the receiver for `&'static self`, which introduces a `'static` obligation. - // ``` - // impl Foo { - // fn foo(&'static self) {} - // ^^^^^^^^^^^^^ - // ``` - if let Some(recv) = + let parent = tcx.parent(def_id); + if let Some(rcvr) = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) - && let ty::Ref(region, _, _) = recv.kind() - && *region == tcx.lifetimes.re_static - && let Some(assoc) = tcx.opt_associated_item(def_id) - && assoc.is_method() { - let def_span = tcx.def_span(def_id); - // We have a `&'static self` receiver. - if let Some(def_id) = def_id.as_local() - && let owner = tcx.expect_hir_owner_node(def_id) - && let Some(decl) = owner.fn_decl() - && let Some(ty) = decl.inputs.get(0) + // Look at the receiver for `&'static self`, which introduces a `'static` obligation. + // ``` + // impl Foo { + // fn foo(&'static self) {} + // ^^^^^^^^^^^^^ + // ``` + if let ty::Ref(region, _, _) = rcvr.kind() + && *region == tcx.lifetimes.re_static + && let Some(assoc) = tcx.opt_associated_item(def_id) + && assoc.is_method() { - // Point at the `&'static self` receiver. - bounds.push(ty.span); - } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { - // The method is not defined on the local crate, point at the signature instead of - // just the receiver as an approximation. We don't add it if there are already - // other spans with overlap with the def `Span`, as the other will be more specific. - bounds.push(def_span) + let def_span = tcx.def_span(def_id); + // We have a `&'static self` receiver. + if let Some(def_id) = def_id.as_local() + && let owner = tcx.expect_hir_owner_node(def_id) + && let Some(decl) = owner.fn_decl() + && let Some(ty) = decl.inputs.get(0) + { + // Point at the `&'static self` receiver. + bounds.push(ty.span); + } else if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + // The method is not defined on the local crate, point at the signature instead of + // just the receiver as an approximation. We don't add it if there are already + // other spans with overlap with the def `Span`, as the other will be more specific. + bounds.push(def_span) + } + } + + if let DefKind::Impl { .. } = tcx.def_kind(parent) + && let ty = tcx.type_of(parent).instantiate_identity().skip_norm_wip() + && let ty::Dynamic(_, region) = ty.kind() + && *region == tcx.lifetimes.re_static + { + // We have a call into a method of either `impl dyn Trait {}` or + // `impl dyn Trait + 'static {}`. We point at the whole def `Span` for now. We + // should instead point only at the `dyn Trait` with an explanation of where the + // `'static` obligation comes from, or only the `'static` when it is explicit. + let def_span = tcx.def_span(parent); + if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + bounds.push(def_span); + } } } @@ -492,7 +511,6 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { multispan.push_span_label(span, "lifetime requirement introduced here"); } multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); - let parent = tcx.parent(def_id); if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { multispan.push_span_context(tcx.def_span(parent).shrink_to_lo()); } diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 3fe8162ed519d..25da231557094 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -167,6 +167,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:4:5 + | +LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:20:9 @@ -183,9 +191,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:16:18 + --> $DIR/static-impl-obligation.rs:15:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -204,9 +213,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:27:18 + --> $DIR/static-impl-obligation.rs:26:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -227,9 +237,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:38:37 + --> $DIR/static-impl-obligation.rs:37:5 | LL | impl dyn Foo { + | ^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -246,6 +257,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here + --> $DIR/static-impl-obligation.rs:48:5 + | +LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:64:9 @@ -262,9 +281,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:60:18 + --> $DIR/static-impl-obligation.rs:59:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -283,9 +303,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:71:18 + --> $DIR/static-impl-obligation.rs:70:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -306,9 +327,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:82:37 + --> $DIR/static-impl-obligation.rs:81:5 | LL | impl dyn Foo + 'static { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -547,6 +569,14 @@ LL | y.hello(); | | | `x` escapes the function body here | argument requires that `'a` must outlive `'static` + | +note: `'static` lifetime requirement from `<(dyn s::Foo + 'static) as s::Trait>::hello` introduced here + --> $DIR/static-impl-obligation.rs:201:5 + | +LL | impl Trait for dyn Foo { + | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn hello(&self) {} + | error[E0521]: borrowed data escapes outside of function --> $DIR/static-impl-obligation.rs:276:9 diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 472d46ef93644..2a7d6181cf9fb 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> $DIR/issue-78262.rs:7:1 + | +LL | impl dyn TT { + | ^^^^^^^^^^^ lifetime requirement introduced here +LL | fn func(&self) {} + | error: aborting due to 1 previous error diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 472d46ef93644..2a7d6181cf9fb 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> $DIR/issue-78262.rs:7:1 + | +LL | impl dyn TT { + | ^^^^^^^^^^^ lifetime requirement introduced here +LL | fn func(&self) {} + | error: aborting due to 1 previous error diff --git a/tests/ui/regions/regions-static-bound-on-type-param.stderr b/tests/ui/regions/regions-static-bound-on-type-param.stderr index d30f1fbe62782..64496cb703bee 100644 --- a/tests/ui/regions/regions-static-bound-on-type-param.stderr +++ b/tests/ui/regions/regions-static-bound-on-type-param.stderr @@ -13,6 +13,8 @@ LL | err.is::() | note: `'static` lifetime requirement from `<(dyn std::error::Error + 'static)>::is` introduced here --> $SRC_DIR/core/src/error.rs:LL:COL + | + = note: lifetime requirement introduced here ::: $SRC_DIR/core/src/error.rs:LL:COL | = note: lifetime requirement introduced here diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 8ef1b052384c6..9f5e45ecddec4 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -18,6 +18,13 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn foo::ObjectTrait + 'static) as foo::MyTrait>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:5 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { @@ -43,6 +50,13 @@ LL | impl dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn bat::ObjectTrait + 'static)>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:5 + | +LL | impl dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl dyn ObjectTrait + '_ { @@ -120,6 +134,13 @@ LL | impl MyTrait for dyn ObjectTrait { | ^^^^^^^^^^^ this has an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement +note: `'static` lifetime requirement from `<(dyn bar::ObjectTrait + 'static) as bar::MyTrait>::use_self` introduced here + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:5 + | +LL | impl MyTrait for dyn ObjectTrait { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here +LL | fn use_self(&self) -> &() { panic!() } + | help: consider relaxing the implicit `'static` requirement | LL | impl MyTrait for dyn ObjectTrait + '_ { From 5a61e9c99b78edc38528a53629f8884058b2c572 Mon Sep 17 00:00:00 2001 From: The Miri Cronjob Bot Date: Tue, 22 Sep 2026 04:32:16 +0000 Subject: [PATCH 0598/1309] Prepare for merging from rust-lang/rust This updates the rust-version file to 88638df1e741778019e42fcdf307072865d19501. --- src/tools/miri/rust-version | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version index e861a160a977a..89c3e1334a546 100644 --- a/src/tools/miri/rust-version +++ b/src/tools/miri/rust-version @@ -1 +1 @@ -feaadeeaca7db0594da854e7c8c07495341c7439 +88638df1e741778019e42fcdf307072865d19501 From 7840dfe4cb81eaa9365938f52aa4c3af4e580ad6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 04:40:15 +0000 Subject: [PATCH 0599/1309] Use better spans on local `impl dyn Trait` when pointing at `'static` lifetime ``` note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:4:10 | LL | impl dyn Foo { | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | ``` ``` note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here --> $DIR/static-impl-obligation.rs:48:20 | LL | impl dyn Foo + 'static { | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | ``` --- .../src/diagnostics/region_errors.rs | 39 +++++++-- .../lifetimes/static-impl-obligation.stderr | 84 +++++++++++-------- tests/ui/regions/issue-78262.base.stderr | 4 +- tests/ui/regions/issue-78262.polonius.stderr | 4 +- ...yn-trait-with-implicit-static-bound.stderr | 12 +-- 5 files changed, 91 insertions(+), 52 deletions(-) diff --git a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs index a085ffa64d409..9d795ff567087 100644 --- a/compiler/rustc_borrowck/src/diagnostics/region_errors.rs +++ b/compiler/rustc_borrowck/src/diagnostics/region_errors.rs @@ -1,6 +1,6 @@ //! Error reporting machinery for lifetime errors. -use rustc_data_structures::fx::FxIndexSet; +use rustc_data_structures::fx::{FxHashMap, FxIndexSet}; use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan, msg}; use rustc_hir as hir; use rustc_hir::GenericBound::Trait; @@ -457,6 +457,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { .map(|(_, sp)| sp) .collect::>(); + let mut labels = FxHashMap::default(); + let parent = tcx.parent(def_id); if let Some(rcvr) = tcx.fn_sig(def_id).instantiate_identity().skip_norm_wip().inputs().skip_binder().get(0) @@ -495,12 +497,32 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { && *region == tcx.lifetimes.re_static { // We have a call into a method of either `impl dyn Trait {}` or - // `impl dyn Trait + 'static {}`. We point at the whole def `Span` for now. We - // should instead point only at the `dyn Trait` with an explanation of where the - // `'static` obligation comes from, or only the `'static` when it is explicit. - let def_span = tcx.def_span(parent); - if !bounds.iter().any(|sp| sp.overlaps(def_span)) { - bounds.push(def_span); + // `impl dyn Trait + 'static {}`. + if let Some(def_id) = parent.as_local() + && let hir::OwnerNode::Item(item) = tcx.expect_hir_owner_node(def_id) + && let hir::ItemKind::Impl(impl_) = item.kind + && let hir::TyKind::TraitObject(_, tagged_ref) = impl_.self_ty.kind + { + if tagged_ref.is_static() { + // impl dyn Trait + 'static { + // ^^^^^^^ lifetime requirement introduced here + bounds.push(tagged_ref.pointer().ident.span); + } else if tagged_ref.is_implicit() { + // impl dyn Trait { + // ^^^^^^^^^ `dyn Trait` introduces an... + bounds.push(impl_.self_ty.span); + labels.insert( + impl_.self_ty.span, + "`dyn Trait` introduces an implicit `'static` lifetime requirement", + ); + } + } else { + // Non-local `impl`, we don't have a way to differentiate between `+ 'static` + // and bare `dyn Trait`. We point at the whole def `Span` for now. + let def_span = tcx.def_span(parent); + if !bounds.iter().any(|sp| sp.overlaps(def_span)) { + bounds.push(def_span); + } } } } @@ -508,7 +530,8 @@ impl<'diag, 'tcx> MirBorrowckCtxt<'_, 'diag, 'tcx> { if !bounds.is_empty() { let mut multispan: MultiSpan = bounds.clone().into(); for span in bounds { - multispan.push_span_label(span, "lifetime requirement introduced here"); + let label = labels.get(&span).unwrap_or(&"lifetime requirement introduced here"); + multispan.push_span_label(span, *label); } multispan.push_span_context(tcx.def_span(def_id).shrink_to_lo()); if let DefKind::Impl { .. } | DefKind::Trait = tcx.def_kind(parent) { diff --git a/tests/ui/lifetimes/static-impl-obligation.stderr b/tests/ui/lifetimes/static-impl-obligation.stderr index 25da231557094..27751557ab51d 100644 --- a/tests/ui/lifetimes/static-impl-obligation.stderr +++ b/tests/ui/lifetimes/static-impl-obligation.stderr @@ -169,10 +169,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn a::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:4:5 + --> $DIR/static-impl-obligation.rs:4:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | @@ -191,10 +191,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn b::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:15:5 + --> $DIR/static-impl-obligation.rs:15:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -213,10 +213,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn c::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:26:5 + --> $DIR/static-impl-obligation.rs:26:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -237,10 +237,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn d::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:37:5 + --> $DIR/static-impl-obligation.rs:37:10 | LL | impl dyn Foo { - | ^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -259,10 +259,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn e::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:48:5 + --> $DIR/static-impl-obligation.rs:48:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) {} | @@ -281,10 +281,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn f::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:59:5 + --> $DIR/static-impl-obligation.rs:59:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -303,10 +303,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn g::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:70:5 + --> $DIR/static-impl-obligation.rs:70:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -327,10 +327,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn h::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:81:5 + --> $DIR/static-impl-obligation.rs:81:20 | LL | impl dyn Foo + 'static { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -349,10 +349,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn i::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:92:30 + --> $DIR/static-impl-obligation.rs:92:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | @@ -371,10 +373,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn j::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:103:30 + --> $DIR/static-impl-obligation.rs:103:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -393,10 +397,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn k::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:114:30 + --> $DIR/static-impl-obligation.rs:114:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -417,10 +423,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn l::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:125:30 + --> $DIR/static-impl-obligation.rs:125:10 | LL | impl dyn Foo where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -439,10 +447,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn m::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:136:40 + --> $DIR/static-impl-obligation.rs:136:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&self) {} | @@ -461,10 +471,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn n::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:147:40 + --> $DIR/static-impl-obligation.rs:147:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&'static self) {} | ^^^^^^^^^^^^^ lifetime requirement introduced here @@ -483,10 +495,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn o::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:158:40 + --> $DIR/static-impl-obligation.rs:158:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&'static self) where Self: 'static {} | ^^^^^^^^^^^^^ ^^^^^^^ lifetime requirement introduced here | | @@ -507,10 +521,12 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn p::Foo + 'static)>::hello` introduced here - --> $DIR/static-impl-obligation.rs:169:40 + --> $DIR/static-impl-obligation.rs:169:20 | LL | impl dyn Foo + 'static where Self: 'static { - | ^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ ^^^^^^^ lifetime requirement introduced here + | | + | lifetime requirement introduced here LL | fn hello(&self) where Self: 'static {} | ^^^^^^^ lifetime requirement introduced here @@ -571,10 +587,10 @@ LL | y.hello(); | argument requires that `'a` must outlive `'static` | note: `'static` lifetime requirement from `<(dyn s::Foo + 'static) as s::Trait>::hello` introduced here - --> $DIR/static-impl-obligation.rs:201:5 + --> $DIR/static-impl-obligation.rs:201:20 | LL | impl Trait for dyn Foo { - | ^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn hello(&self) {} | diff --git a/tests/ui/regions/issue-78262.base.stderr b/tests/ui/regions/issue-78262.base.stderr index 2a7d6181cf9fb..54a2393c913ed 100644 --- a/tests/ui/regions/issue-78262.base.stderr +++ b/tests/ui/regions/issue-78262.base.stderr @@ -10,10 +10,10 @@ LL | let f = |x: &dyn TT| x.func(); | `x` is only valid in the closure body | note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here - --> $DIR/issue-78262.rs:7:1 + --> $DIR/issue-78262.rs:7:6 | LL | impl dyn TT { - | ^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn func(&self) {} | diff --git a/tests/ui/regions/issue-78262.polonius.stderr b/tests/ui/regions/issue-78262.polonius.stderr index 2a7d6181cf9fb..54a2393c913ed 100644 --- a/tests/ui/regions/issue-78262.polonius.stderr +++ b/tests/ui/regions/issue-78262.polonius.stderr @@ -10,10 +10,10 @@ LL | let f = |x: &dyn TT| x.func(); | `x` is only valid in the closure body | note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here - --> $DIR/issue-78262.rs:7:1 + --> $DIR/issue-78262.rs:7:6 | LL | impl dyn TT { - | ^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn func(&self) {} | diff --git a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr index 9f5e45ecddec4..9793b7fb8dc7a 100644 --- a/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr +++ b/tests/ui/suggestions/impl-on-dyn-trait-with-implicit-static-bound.stderr @@ -19,10 +19,10 @@ LL | impl MyTrait for dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn foo::ObjectTrait + 'static) as foo::MyTrait>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:15:28 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement @@ -51,10 +51,10 @@ LL | impl dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn bat::ObjectTrait + 'static)>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:67:10 | LL | impl dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement @@ -135,10 +135,10 @@ LL | impl MyTrait for dyn ObjectTrait { LL | fn use_self(&self) -> &() { panic!() } | -------- calling this method introduces the `impl`'s `'static` requirement note: `'static` lifetime requirement from `<(dyn bar::ObjectTrait + 'static) as bar::MyTrait>::use_self` introduced here - --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:5 + --> $DIR/impl-on-dyn-trait-with-implicit-static-bound.rs:32:22 | LL | impl MyTrait for dyn ObjectTrait { - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime requirement introduced here + | ^^^^^^^^^^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement LL | fn use_self(&self) -> &() { panic!() } | help: consider relaxing the implicit `'static` requirement From 9c18639026876e93b4bb739fad7925d013c6f32f Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 5 Sep 2026 01:04:39 +0000 Subject: [PATCH 0600/1309] Add regression test for auto trait leakage of foreign hidden types --- .../auxiliary/opaque-auto-trait-leakage.rs | 15 ++++++++ .../opaque-hidden-ty-inference.rs | 38 +++++++++++++++++++ .../opaque-hidden-ty-inference.stderr | 30 +++++++++++++++ 3 files changed, 83 insertions(+) create mode 100644 tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs create mode 100644 tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.rs create mode 100644 tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr diff --git a/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs b/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs new file mode 100644 index 0000000000000..d7a2c4a8642eb --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs @@ -0,0 +1,15 @@ +pub struct WaddupGamers(Option, U); + +impl, U> Unpin for WaddupGamers {} + +pub trait Leak { + type Assoc; +} + +impl Leak for T { + type Assoc = T; +} + +pub fn define() -> impl Sized { + WaddupGamers(None::, || ()) +} diff --git a/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.rs b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.rs new file mode 100644 index 0000000000000..d1b4e54ff3bb2 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.rs @@ -0,0 +1,38 @@ +//@ ignore-compare-mode-next-solver +//@ compile-flags: -Znext-solver +//@ aux-build:opaque-auto-trait-leakage.rs + +//! Regression test for https://github.com/rust-lang/rust/issues/134578. +//! Leaking the auto traits of a foreign opaque must not constrain inference +//! variables in the caller, as that would leak the hidden type itself. Here +//! that would constrain `NameMe` to a closure from the auxiliary crate and +//! ICE in typeck. The hidden type may still show up in the diagnostic. + +#![feature(type_alias_impl_trait)] +#![allow(unused)] + +extern crate opaque_auto_trait_leakage as dep; + +use dep::*; + +fn require_auto(x: T) -> T { + x +} + +type NameMe = impl Sized; + +#[define_opaque(NameMe)] +fn leak() -> NameMe +where + T: Leak>, +{ + // Proving `impl Sized: Unpin` must not constrain `NameMe` + // to the foreign closure hidden inside `define`. + let opaque = require_auto(define::()); + //~^ ERROR type mismatch resolving `::Assoc == {closure@define::{closure#0}}` + let closure; + loop {} + return closure; +} + +fn main() {} diff --git a/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr new file mode 100644 index 0000000000000..b70fde561cd43 --- /dev/null +++ b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr @@ -0,0 +1,30 @@ +error[E0271]: type mismatch resolving `::Assoc == {closure@define::{closure#0}}` + --> $DIR/opaque-hidden-ty-inference.rs:31:31 + | +LL | let opaque = require_auto(define::()); + | ------------ ^^^^^^^^^^^^^ expected closure, found `!` + | | + | required by a bound introduced by this call + | + ::: $DIR/auxiliary/opaque-auto-trait-leakage.rs:14:29 + | +LL | WaddupGamers(None::, || ()) + | -- the expected closure + | + = note: expected closure `{closure@dep::define::{closure#0}}` + found type `!` + = note: required for `WaddupGamers::{closure#0}}>` to implement `Unpin` +note: required because it appears within the type `impl Sized` + --> $DIR/auxiliary/opaque-auto-trait-leakage.rs:13:23 + | +LL | pub fn define() -> impl Sized { + | ^^^^^^^^^^ +note: required by a bound in `require_auto` + --> $DIR/opaque-hidden-ty-inference.rs:18:20 + | +LL | fn require_auto(x: T) -> T { + | ^^^^^ required by this bound in `require_auto` + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0271`. From b3d3ab1cae40e53a66fb3894c02b9581e6a61c7d Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 5 Sep 2026 03:27:03 +0000 Subject: [PATCH 0601/1309] Add opaque mayleak to bail out PostTypeckUntilBorrowck from opaque constraint --- .../rustc_next_trait_solver/src/solve/trait_goals.rs | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index bad038022b1fb..f2c85509b9d42 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1305,8 +1305,20 @@ where ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) }); + let opaque_types_may_leak = match self.typing_mode() { + TypingMode::PostTypeckUntilBorrowck { .. } => false, + TypingMode::Coherence + | TypingMode::Typeck { .. } + | TypingMode::PostBorrowck { .. } + | TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::ErasedNotCoherence(MayBeErased) => true, + }; + match candidate { Ok(candidate) if has_only_region_constraints(candidate.result) => Ok(candidate), + Ok(candidate) if !opaque_types_may_leak => Ok(candidate), Ok(_) => self.forced_ambiguity(MaybeInfo::AMBIGUOUS), Err(err) => Err(err), } From d86652ace45f8373fc6ae2b1122458b85162dadf Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 11 Sep 2026 15:16:36 +0000 Subject: [PATCH 0602/1309] Contraint the var_values to not contain type and const inference variable during PostTypeckUntilBorrowck for auto trait opaque ty --- .../src/solve/trait_goals.rs | 61 +++++++++++++------ .../auxiliary/opaque-auto-trait-leakage.rs | 6 ++ .../opaque-hidden-ty-inference.stderr | 4 +- 3 files changed, 49 insertions(+), 22 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index f2c85509b9d42..649ce4d2dd76f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -5,7 +5,7 @@ use rustc_type_ir::fast_reject::DeepRejectCtxt; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverTraitLangItem; use rustc_type_ir::solve::{ - AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, MaybeInfo, + AliasBoundKind, CandidatePreferenceMode, CanonicalResponse, ExternalConstraintsData, MaybeInfo, NoSolutionOrRerunNonErased, OpaqueTypesJank, QueryResultOrRerunNonErased, RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, }; @@ -1286,9 +1286,6 @@ where ) -> Result, NoSolutionOrRerunNonErased> { let cx = self.cx(); let source = CandidateSource::BuiltinImpl(BuiltinImplSource::Misc); - if self.opaque_accesses.might_rerun() { - match self.opaque_accesses.rerun_always(RerunReason::AutoTraitLeakage)? {} - } for item_bound in cx.item_self_bounds(def_id.into()).skip_binder() { if item_bound.as_trait_clause().is_some_and(|b| b.def_id() == goal.predicate.def_id()) { @@ -1303,25 +1300,49 @@ where goal.with(cx, goal.predicate.with_replaced_self_ty(cx, hidden_ty)), )?; ecx.evaluate_added_goals_and_make_canonical_response(Certainty::Yes) - }); + })?; - let opaque_types_may_leak = match self.typing_mode() { - TypingMode::PostTypeckUntilBorrowck { .. } => false, - TypingMode::Coherence - | TypingMode::Typeck { .. } - | TypingMode::PostBorrowck { .. } - | TypingMode::Reflection - | TypingMode::PostAnalysis - | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased) => true, - }; + // Proving an auto trait for the hidden type must not constrain inference + // variables, as that would leak the hidden type itself. + if !candidate.result.value.var_values.is_identity_modulo_regions() { + return self.forced_ambiguity(MaybeInfo::AMBIGUOUS); + } - match candidate { - Ok(candidate) if has_only_region_constraints(candidate.result) => Ok(candidate), - Ok(candidate) if !opaque_types_may_leak => Ok(candidate), - Ok(_) => self.forced_ambiguity(MaybeInfo::AMBIGUOUS), - Err(err) => Err(err), + let ExternalConstraintsData { + region_constraints: _, + ref opaque_types, + ref normalization_nested_goals, + } = *candidate.result.value.external_constraints; + debug_assert!(normalization_nested_goals.is_empty()); + + // New defining uses may leak an opaque's hidden type into the caller's + // inference state. This is safe after typeck, where hidden types are already + // fixed and only regions are inferred, but not during typeck while hidden + // types may still contain inference variables. + if !opaque_types.is_empty() { + match self.typing_mode() { + // We're inferring regions of opaque types, but + // the type itself is already fully known, no way + // to leak the hidden type. + TypingMode::PostTypeckUntilBorrowck { .. } => {} + // We're inferring the hidden type of opaques, could + // leak types through it. + TypingMode::Typeck { .. } => { + return self.forced_ambiguity(MaybeInfo::AMBIGUOUS); + } + // we never add new uses to the opaque type storage + TypingMode::Coherence + | TypingMode::PostBorrowck { .. } + | TypingMode::Reflection + | TypingMode::PostAnalysis + | TypingMode::Codegen + | TypingMode::ErasedNotCoherence(MayBeErased) => { + return self.forced_ambiguity(MaybeInfo::AMBIGUOUS); + } + } } + + Ok(candidate) } // Return `Some` if there is an impl (built-in or user provided) that may diff --git a/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs b/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs index d7a2c4a8642eb..c32f4ae09dcf1 100644 --- a/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs +++ b/tests/ui/impl-trait/auto-trait-leakage/auxiliary/opaque-auto-trait-leakage.rs @@ -1,3 +1,9 @@ +// External crate for `opaque-hidden-ty-inference.rs`. +// +// `define` returns `WaddupGamers`. Its `Unpin` impl only holds if +// `::Assoc` is that closure. The test's caller says `Assoc` is its +// own opaque type instead, so checking `Unpin` would try to set that opaque +// type to this closure. pub struct WaddupGamers(Option, U); impl, U> Unpin for WaddupGamers {} diff --git a/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr index b70fde561cd43..cd750cf3261a7 100644 --- a/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr +++ b/tests/ui/impl-trait/auto-trait-leakage/opaque-hidden-ty-inference.stderr @@ -6,7 +6,7 @@ LL | let opaque = require_auto(define::()); | | | required by a bound introduced by this call | - ::: $DIR/auxiliary/opaque-auto-trait-leakage.rs:14:29 + ::: $DIR/auxiliary/opaque-auto-trait-leakage.rs:20:29 | LL | WaddupGamers(None::, || ()) | -- the expected closure @@ -15,7 +15,7 @@ LL | WaddupGamers(None::, || ()) found type `!` = note: required for `WaddupGamers::{closure#0}}>` to implement `Unpin` note: required because it appears within the type `impl Sized` - --> $DIR/auxiliary/opaque-auto-trait-leakage.rs:13:23 + --> $DIR/auxiliary/opaque-auto-trait-leakage.rs:19:23 | LL | pub fn define() -> impl Sized { | ^^^^^^^^^^ From 9fecc5aefe59d203ed2111b3cdf2c3f26138347b Mon Sep 17 00:00:00 2001 From: Nicholas Nethercote Date: Tue, 22 Sep 2026 08:52:22 +1000 Subject: [PATCH 0603/1309] Clean up diagnostic hashing `DiagInner` impls `PartialEq` and `Hash`, as you'd expect for storing it in a hash table. But there's a couple of strange things. - We only store the hash value of the `DiagInner` to do deduplication, not the `DiagInner` itself, which means the `PartialEq` impl is unused. - The `Hash` impl only considers some of the fields. Some of the ignored fields are clearly deliberate (there are comments) but for some it is unclear if it is deliberate. This commit: - Removes the unused `PartialEq` impl. - Inlines and removes `keys` now that it's not needed for `PartialEq`. - Uses struct deconstruction to ensure no fields can be accidentally ignored. I have preserved existing behaviour by assuming that all the ignored fields are supposed to be ignored. - Renames `hash` as an inherent method `dedup_hash` to indicate that it's not a typical hash function, and simplifies it to just return `Hash128` instead of being generic. - Replaces the unnecessary `collect` on `args` with `as_slice`. - Improves the comment on `emitted_diagnostics`. --- compiler/rustc_errors/src/diagnostic.rs | 71 ++++++++++--------------- compiler/rustc_errors/src/lib.rs | 13 ++--- 2 files changed, 34 insertions(+), 50 deletions(-) diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs index 9a12d6d53b6e6..729569fd5f5d1 100644 --- a/compiler/rustc_errors/src/diagnostic.rs +++ b/compiler/rustc_errors/src/diagnostic.rs @@ -1,13 +1,15 @@ use std::borrow::Cow; use std::fmt::{self, Debug}; -use std::hash::{Hash, Hasher}; +use std::hash::Hash; use std::ops::{Deref, DerefMut}; use std::panic; use std::path::PathBuf; use std::thread::panicking; use rustc_ast::attr::version::RustcVersion; -use rustc_error_messages::{DiagArgMap, DiagArgName, DiagArgValue, IntoDiagArg}; +use rustc_data_structures::stable_hash::StableHasher; +use rustc_error_messages::{DiagArgMap, DiagArgName, IntoDiagArg}; +use rustc_hashes::Hash128; use rustc_lint_defs::{Applicability, LintExpectationId}; use rustc_macros::{Decodable, Encodable}; use rustc_span::{DUMMY_SP, Span, Spanned, Symbol}; @@ -305,46 +307,31 @@ impl DiagInner { } } - /// Fields used for Hash, and PartialEq trait. - fn keys( - &self, - ) -> ( - &Level, - &[(DiagMessage, Style)], - &Option, - &MultiSpan, - &[Subdiag], - &Suggestions, - Vec<(&DiagArgName, &DiagArgValue)>, - &Option, - ) { - ( - &self.level, - &self.messages, - &self.code, - &self.span, - &self.children, - &self.suggestions, - self.args.iter().collect(), - // omit self.sort_span - &self.is_lint, - // omit self.emitted_at - ) - } -} - -impl Hash for DiagInner { - fn hash(&self, state: &mut H) - where - H: Hasher, - { - self.keys().hash(state); - } -} - -impl PartialEq for DiagInner { - fn eq(&self, other: &Self) -> bool { - self.keys() == other.keys() + /// Hash used to determine if two diagnostics are the same. Used by + /// `DiagCtxtInner::emitted_diagnostics`. Some fields are ignored for the hash. + pub(crate) fn dedup_hash(&self) -> Hash128 { + // Deconstruct to ensure all fields are considered. + let DiagInner { + level, + messages, + code, + lint_id: _, // ignore + span, + children, + suggestions, + args, + sort_span: _, // ignore + is_lint, + long_ty_path: _, // ignore + emitted_at: _, // ignore + } = self; + + let hashed_parts = + (level, messages, code, span, children, suggestions, args.as_slice(), is_lint); + + let mut hasher = StableHasher::new(); + hashed_parts.hash(&mut hasher); + hasher.finish() } } diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs index 30791a51f7644..68e10802e21c5 100644 --- a/compiler/rustc_errors/src/lib.rs +++ b/compiler/rustc_errors/src/lib.rs @@ -325,8 +325,10 @@ struct DiagCtxtInner { emitted_diagnostic_codes: FxIndexSet, /// This set contains a hash of every diagnostic that has been emitted by - /// this `DiagCtxt`. These hashes is used to avoid emitting the same error - /// twice. + /// this `DiagCtxt`. These hashes are used to avoid emitting the same error + /// twice. (Because we don't store the diagnostics themselves, two + /// different diagnostics with the same hash value will be considered + /// equivalent. Such collisions should be vanishingly rare...) emitted_diagnostics: FxHashSet, /// We only want to emit `recursion_depth_exceeding_limit` once per @@ -1301,12 +1303,7 @@ impl DiagCtxtInner { self.emitted_diagnostic_codes.insert(code); } - let already_emitted = { - let mut hasher = StableHasher::new(); - diagnostic.hash(&mut hasher); - let diagnostic_hash = hasher.finish(); - !self.emitted_diagnostics.insert(diagnostic_hash) - }; + let already_emitted = !self.emitted_diagnostics.insert(diagnostic.dedup_hash()); let is_error = diagnostic.is_error(); let is_lint = diagnostic.is_lint.is_some(); From 7dc9aeebf8cfb84a25fe896fecf5ff34d5a22e71 Mon Sep 17 00:00:00 2001 From: Ralf Jung Date: Mon, 21 Sep 2026 18:35:35 +0200 Subject: [PATCH 0604/1309] remove incorrect cfg_abi check from asm/powerpc; that makes CfgAbi::VecExtAbi basically unused so remove it --- compiler/rustc_target/src/asm/powerpc.rs | 13 +++---------- compiler/rustc_target/src/spec/base/aix.rs | 9 +++++---- compiler/rustc_target/src/spec/consistency.rs | 2 +- compiler/rustc_target/src/spec/mod.rs | 1 - 4 files changed, 9 insertions(+), 16 deletions(-) diff --git a/compiler/rustc_target/src/asm/powerpc.rs b/compiler/rustc_target/src/asm/powerpc.rs index 36a8657c5d4e1..54a93935afa37 100644 --- a/compiler/rustc_target/src/asm/powerpc.rs +++ b/compiler/rustc_target/src/asm/powerpc.rs @@ -4,7 +4,7 @@ use rustc_data_structures::fx::FxIndexSet; use rustc_span::Symbol; use super::{InlineAsmArch, InlineAsmType, ModifierInfo}; -use crate::spec::{CfgAbi, RelocModel, RustcAbi, Target}; +use crate::spec::{RelocModel, RustcAbi, Target}; def_reg_class! { PowerPC PowerPCInlineAsmRegClass { @@ -107,15 +107,8 @@ fn reserved_v20to31( _is_clobber: bool, ) -> Result<(), &'static str> { if target.is_like_aix { - // FIXME: using `cfg_abi` here is wrong -- that's not a source of truth, it's just - // what we display to the user. Instead we need to check the knob that controls - // whether the ABI is actually used. Currently there is no such knob, a Rust target - // can therefore never actually use `vec-extabi`. - match &target.options.cfg_abi { - CfgAbi::VecDefault => Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI"), - CfgAbi::VecExtAbi => Ok(()), - abi => unreachable!("unrecognized AIX ABI: {abi}"), - } + // We do not support the vec-extabi at the moment. + Err("v20-v31 (vs52-vs63) are reserved on vec-default ABI") } else { Ok(()) } diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs index 5d172cc8b0fcf..1f581a01b1642 100644 --- a/compiler/rustc_target/src/spec/base/aix.rs +++ b/compiler/rustc_target/src/spec/base/aix.rs @@ -8,10 +8,11 @@ use crate::spec::{ pub(crate) fn opts() -> TargetOptions { TargetOptions { // It makes no sense to set "vec-extabi" here without also actually configuring LLVM to use - // that ABI. This needs a new target spec knob to control the relevant LLVM flag. If you are - // adding such a knob, make sure to also: - // - adjust the logic in `asm/powerpc.rs` to check that knob instead of checking `cfg_abi`. - // - adjust the logic in `spec/consistency.rs` to correlate that knob with `cfg_abi`. + // that ABI. Since https://github.com/llvm/llvm-project/pull/221670 this probably just needs + // `llvm_abiname` to be set properly. If you are doing that, make sure to also: + // - adjust the logic in `reserved_v20to31` in `asm/powerpc.rs` to allow the extra registers + // to be used depending on `llvm_abiname`. + // - adjust the logic in `spec/consistency.rs` to correlate `llvm_abiname` with `cfg_abi`. cfg_abi: CfgAbi::VecDefault, code_model: Some(CodeModel::Large), cpu: "pwr7".into(), diff --git a/compiler/rustc_target/src/spec/consistency.rs b/compiler/rustc_target/src/spec/consistency.rs index cdfbd6c2acbfc..5f88c352d3340 100644 --- a/compiler/rustc_target/src/spec/consistency.rs +++ b/compiler/rustc_target/src/spec/consistency.rs @@ -484,7 +484,7 @@ impl Target { // (vec-default vs vec-ext). check_matches!( (&self.llvm_abiname, &self.cfg_abi), - (LlvmAbi::Unspecified, CfgAbi::VecDefault | CfgAbi::VecExtAbi), + (LlvmAbi::Unspecified, CfgAbi::VecDefault), "invalid PowerPC64 AIX ABI name and `cfg(target_abi)` combination:\n\ ABI name: {}\n\ cfg(target_abi): {}", diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs index 9f97a33bfdc75..42d817c7daa31 100644 --- a/compiler/rustc_target/src/spec/mod.rs +++ b/compiler/rustc_target/src/spec/mod.rs @@ -1950,7 +1950,6 @@ crate::target_spec_enum! { Spe = "spe", Uwp = "uwp", VecDefault = "vec-default", - VecExtAbi = "vec-extabi", X32 = "x32", V8Plus = "v8plus", Unspecified = "", From 684d929f9d6e59720e3f550b580cad2d59b55508 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakub=20Ber=C3=A1nek?= Date: Tue, 22 Sep 2026 10:46:50 +0200 Subject: [PATCH 0605/1309] Rename `rust-toolchain` to `rust-toolchain.toml` To ensure compatibility with Josh. The old name is legacy anyway. --- src/tools/rustfmt/Subtree sync procedure.md | 2 +- src/tools/rustfmt/{rust-toolchain => rust-toolchain.toml} | 0 src/tools/rustfmt/src/bin/main.rs | 4 ---- src/tools/rustfmt/src/lib.rs | 1 - 4 files changed, 1 insertion(+), 6 deletions(-) rename src/tools/rustfmt/{rust-toolchain => rust-toolchain.toml} (100%) diff --git a/src/tools/rustfmt/Subtree sync procedure.md b/src/tools/rustfmt/Subtree sync procedure.md index 99e01486ed1be..e993456f8bc37 100644 --- a/src/tools/rustfmt/Subtree sync procedure.md +++ b/src/tools/rustfmt/Subtree sync procedure.md @@ -100,7 +100,7 @@ $ git merge upstream/main --no-ff ### 4. Bump the nightly toolchain version in the `rustfmt` repository Using the same latest nightly date (that you can obtain by inspecting `rustup check` output), -manually edit `rust-toolchain`: +manually edit `rust-toolchain.toml`: ```diff [toolchain] diff --git a/src/tools/rustfmt/rust-toolchain b/src/tools/rustfmt/rust-toolchain.toml similarity index 100% rename from src/tools/rustfmt/rust-toolchain rename to src/tools/rustfmt/rust-toolchain.toml diff --git a/src/tools/rustfmt/src/bin/main.rs b/src/tools/rustfmt/src/bin/main.rs index ffe9aa7e3a49c..05a22324d0f68 100644 --- a/src/tools/rustfmt/src/bin/main.rs +++ b/src/tools/rustfmt/src/bin/main.rs @@ -671,10 +671,6 @@ impl GetOptsOptions { } } - if let Some(ref edition_str) = matches.opt_str("style-edition") { - options.style_edition = Some(style_edition_from_style_edition_str(edition_str)?); - } - Ok(options) } diff --git a/src/tools/rustfmt/src/lib.rs b/src/tools/rustfmt/src/lib.rs index f54d0641f4629..285fa26d00a50 100644 --- a/src/tools/rustfmt/src/lib.rs +++ b/src/tools/rustfmt/src/lib.rs @@ -3,7 +3,6 @@ #![warn(unreachable_pub)] #![recursion_limit = "256"] #![allow(clippy::match_like_matches_macro)] -#![allow(unreachable_pub)] // N.B. these crates are loaded from the sysroot, so they need extern crate. extern crate rustc_ast; From 2269cba9d027a6e17389fffe7d959a87112f90d3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 11:03:27 +0200 Subject: [PATCH 0606/1309] we have the `location_map` at home simplify liveness sources to not need a lifetime or a location map --- compiler/rustc_borrowck/src/nll.rs | 2 +- .../src/polonius/constraints.rs | 25 ++++++++++--------- compiler/rustc_borrowck/src/polonius/dump.rs | 7 ++---- compiler/rustc_borrowck/src/polonius/mod.rs | 14 +++++------ .../rustc_borrowck/src/region_infer/values.rs | 4 --- 5 files changed, 22 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_borrowck/src/nll.rs b/compiler/rustc_borrowck/src/nll.rs index fed7fdd97ac4d..00f28ecd1cfeb 100644 --- a/compiler/rustc_borrowck/src/nll.rs +++ b/compiler/rustc_borrowck/src/nll.rs @@ -156,7 +156,7 @@ pub(crate) fn compute_regions<'tcx>( &universal_region_relations.universal_regions, body, move_data, - &location_map, + Rc::clone(&location_map), borrow_set, ); } diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 44a21708c8419..51969c38a9e97 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -1,3 +1,5 @@ +use std::rc::Rc; + use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet}; use rustc_index::IndexVec; use rustc_middle::mir::{Body, Location}; @@ -38,6 +40,8 @@ pub(super) struct LocalizedNode { /// The localized constraint graph indexes the physical and logical edges to lazily compute a given /// node's successors during traversal. pub(super) struct LocalizedConstraintGraph { + location_map: Rc, + /// The actual, physical, edges we have recorded for a given node. We localize them on-demand /// when traversing from the node to the successor region. edges: FxHashMap>, @@ -49,9 +53,8 @@ pub(super) struct LocalizedConstraintGraph { } /// The source of liveness information for a given region. -pub(super) trait LivenessSource<'loc> { +pub(super) trait LivenessSource { fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>; - fn location_map(&self) -> &'loc DenseLocationMap; } /// The visitor interface when traversing a `LocalizedConstraintGraph`. @@ -68,7 +71,7 @@ pub(super) trait LocalizedConstraintGraphVisitor { impl LocalizedConstraintGraph { /// Traverses the constraints and returns the indexed graph of edges per node. pub(super) fn new<'tcx>( - location_map: &DenseLocationMap, + location_map: Rc, outlives_constraints: impl Iterator>, ) -> Self { let mut edges: FxHashMap<_, FxIndexSet<_>> = FxHashMap::default(); @@ -92,23 +95,21 @@ impl LocalizedConstraintGraph { } } - LocalizedConstraintGraph { edges, logical_edges } + LocalizedConstraintGraph { location_map, edges, logical_edges } } /// Traverses the localized constraint graph per-loan, and notifies the `visitor` of discovered /// nodes and successors. - pub(super) fn traverse<'tcx, 'loc>( + pub(super) fn traverse<'tcx>( &self, body: &Body<'tcx>, borrow_set: &BorrowSet<'tcx>, - liveness_source: &mut impl LivenessSource<'loc>, + liveness_source: &mut impl LivenessSource, visitor: &mut impl LocalizedConstraintGraphVisitor, ) { let mut visited = FxHashSet::default(); let mut stack = Vec::new(); - let location_map = liveness_source.location_map(); - // Compute reachability per loan by traversing each loan's subgraph starting from where it // is introduced. for (loan_idx, loan) in borrow_set.iter_enumerated() { @@ -117,7 +118,7 @@ impl LocalizedConstraintGraph { let start_node = LocalizedNode { region: loan.region, - point: location_map.point_from_location(loan.reserve_location), + point: self.location_map.point_from_location(loan.reserve_location), }; visited.insert(start_node); stack.push(start_node); @@ -125,7 +126,7 @@ impl LocalizedConstraintGraph { while let Some(node) = stack.pop() { let liveness = liveness_source.liveness_for_region(node.region); // We've reached a node we haven't visited before. - let location = location_map.to_location(node.point); + let location = self.location_map.to_location(node.point); visitor.on_node_traversed(loan_idx, node, liveness.is_live_at(node.point)); // When we find a _new_ successor, we'd like to @@ -181,7 +182,7 @@ impl LocalizedConstraintGraph { for successor_block in body[location.block].terminator().successors() { let next_location = Location { block: successor_block, statement_index: 0 }; - let next_point = location_map.point_from_location(next_location); + let next_point = self.location_map.point_from_location(next_location); if liveness.is_live_at(next_point) { successor_found(LocalizedNode { region: node.region, @@ -224,7 +225,7 @@ impl LocalizedConstraintGraph { statement_index: body[pred_block].statements.len(), }; let previous_point = - location_map.point_from_location(previous_location); + self.location_map.point_from_location(previous_location); successor_found(LocalizedNode { region: node.region, point: previous_point, diff --git a/compiler/rustc_borrowck/src/polonius/dump.rs b/compiler/rustc_borrowck/src/polonius/dump.rs index fff31691f4086..fb4c6fbcc9da9 100644 --- a/compiler/rustc_borrowck/src/polonius/dump.rs +++ b/compiler/rustc_borrowck/src/polonius/dump.rs @@ -5,7 +5,7 @@ use rustc_index::IndexVec; use rustc_middle::mir::pretty::{MirDumper, PassWhere, PrettyPrintMirOptions}; use rustc_middle::mir::{Body, Location}; use rustc_middle::ty::{RegionVid, TyCtxt}; -use rustc_mir_dataflow::points::{DenseLocationMap, PointIndex}; +use rustc_mir_dataflow::points::PointIndex; use rustc_session::config::MirIncludeSpans; use crate::borrow_set::BorrowSet; @@ -32,7 +32,7 @@ struct CachedLivenessSource<'a, 'tcx> { liveness: &'a LivenessValues, } -impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { +impl<'a, 'tcx> LivenessSource for CachedLivenessSource<'a, 'tcx> { fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { RegionLiveness::new( region, @@ -41,9 +41,6 @@ impl<'a, 'tcx> LivenessSource<'a> for CachedLivenessSource<'a, 'tcx> { self.liveness.points(), ) } - fn location_map(&self) -> &'a DenseLocationMap { - self.liveness.location_map() - } } /// `-Zdump-mir=polonius` dumps MIR annotated with NLL and polonius specific information. diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 654c750dfccd1..36f1f9c795dae 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -39,6 +39,8 @@ pub(crate) mod legacy; mod liveness; mod liveness_constraints; +use std::rc::Rc; + use rustc_data_structures::fx::FxHashSet; use rustc_index::IndexVec; use rustc_index::bit_set::DenseBitSet; @@ -141,7 +143,7 @@ impl<'tcx> PoloniusContext<'tcx> { universal_regions: &UniversalRegions<'tcx>, body: &Body<'tcx>, move_data: &MoveData<'tcx>, - location_map: &DenseLocationMap, + location_map: Rc, borrow_set: &BorrowSet<'tcx>, ) { // We don't need to prepare the graph (index NLL constraints, etc.) if we have no loans to @@ -151,7 +153,7 @@ impl<'tcx> PoloniusContext<'tcx> { // on the lazy localized constraint graph to trace the liveness of loans, for the next // step in the chain (the NLL loan scope and active loans computations). let graph = - LocalizedConstraintGraph::new(liveness.location_map(), outlives_constraints); + LocalizedConstraintGraph::new(Rc::clone(&location_map), outlives_constraints); let local_use_map = self .local_use_map @@ -161,7 +163,7 @@ impl<'tcx> PoloniusContext<'tcx> { std::mem::take(&mut self.deferred_locals_for_liveness); let mut live_loans = LiveLoans::new(location_map.num_points(), borrow_set.len()); let comp = - LivenessComputation::new(infcx, body, location_map, move_data, &local_use_map); + LivenessComputation::new(infcx, body, &location_map, move_data, &local_use_map); let mut liveness_source = DeferredLivenessSource { liveness, live_region_variances: &mut self.live_region_variances, @@ -190,7 +192,7 @@ struct DeferredLivenessSource<'a, 'tcx> { comp: LivenessComputation<'a, 'tcx>, } -impl<'a> LivenessSource<'a> for DeferredLivenessSource<'a, '_> { +impl<'a> LivenessSource for DeferredLivenessSource<'a, '_> { #[inline] fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_> { self.deferred_locals_for_liveness.compute_deferred_local( @@ -208,10 +210,6 @@ impl<'a> LivenessSource<'a> for DeferredLivenessSource<'a, '_> { self.liveness.points(), ) } - - fn location_map(&self) -> &'a DenseLocationMap { - self.comp.location_map - } } /// Visitor to record loan liveness when traversing the localized constraint graph. diff --git a/compiler/rustc_borrowck/src/region_infer/values.rs b/compiler/rustc_borrowck/src/region_infer/values.rs index 6e4e9405e3ada..800f72275b052 100644 --- a/compiler/rustc_borrowck/src/region_infer/values.rs +++ b/compiler/rustc_borrowck/src/region_infer/values.rs @@ -201,10 +201,6 @@ impl LivenessValues { self.location_map.to_location(point) } - pub(crate) fn location_map(&self) -> &Rc { - &self.location_map - } - /// When using `-Zpolonius=next`, records the given live loans for the loan scopes and active /// loans dataflow computations. pub(crate) fn record_live_loans(&mut self, live_loans: LiveLoans) { From acabd50ac736a34977d6c34c100a5949b99346a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 11:05:35 +0200 Subject: [PATCH 0607/1309] fix typo --- compiler/rustc_borrowck/src/polonius/liveness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 0bef063b0162c..017055c368364 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -58,7 +58,7 @@ impl<'tcx> DeferredLocals<'tcx> { }); } - /// For a given region, compute the liveness for the local containing it, if if is deferred. + /// For a given region, compute the liveness for the local containing it, if it is deferred. #[inline] pub(crate) fn compute_deferred_local( &mut self, From 87e35b58c732dc5d0b0dbed23597051a39318a00 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 11:32:05 +0200 Subject: [PATCH 0608/1309] assorted cleanups in `LivenessComputation::compute` - tiny renamings - tiny type simplifications (type ascription, closure return type) - fixing a comment --- .../src/type_check/liveness/trace.rs | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 0811b66d43acf..f0de106412538 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -394,7 +394,7 @@ impl<'a, 'tcx> LivenessComputation<'a, 'tcx> { universal_regions: &UniversalRegions<'tcx>, live_region_variances: Option<&mut LiveRegionVariances>, liveness_constraints: &mut LivenessValues, - get_drop_args: impl FnOnce() -> &'drop_data Vec>, + get_drop_args: impl FnOnce() -> &'drop_data [GenericArg<'tcx>], ) where 'tcx: 'drop_data, { @@ -431,17 +431,16 @@ impl<'a, 'tcx> LivenessComputation<'a, 'tcx> { if !self.drop_live_at.is_empty() { let drop_data = get_drop_args(); - // `drop_live_at` is using a DenseBitSet, but `make_all_regions_live` - // expects an IntervalSet. We thus convert between those two here. - // Using a `DenseBitSet` has better performance, but storing liveness - // as a dense matrix has worse performance. There's probably room here - // for some cleanup, but this works for now. - let mut drop_live_at: IntervalSet = - IntervalSet::new(self.drop_live_at.domain_size()); - for item in self.drop_live_at.iter() { + // `compute_drop_live_points_for` computes `drop_live_at` as a `DenseBitSet`, but + // `make_all_regions_live` expects an `IntervalSet`. We thus convert between those two + // here. Using a `DenseBitSet` has better performance, but storing liveness as a dense + // matrix has worse performance. There's probably room here for some cleanup, but this + // works for now. + let mut drop_live_at = IntervalSet::new(self.drop_live_at.domain_size()); + for point in self.drop_live_at.iter() { // We iterate the `drop_live_at` set from smallest to largest values, so // we can use append to add things to the interval set at the end. - drop_live_at.append(item); + drop_live_at.append(point); } for &kind in drop_data { From 38ca3d31f3819d3dd5a3e7c141609e1aa39940c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 11:40:35 +0200 Subject: [PATCH 0609/1309] expand comment to match callback signature --- compiler/rustc_borrowck/src/polonius/constraints.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 51969c38a9e97..8386f60c40f03 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -60,7 +60,7 @@ pub(super) trait LivenessSource { /// The visitor interface when traversing a `LocalizedConstraintGraph`. pub(super) trait LocalizedConstraintGraphVisitor { /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't - /// visited before. + /// visited before, and whether its region is live at that point. fn on_node_traversed(&mut self, _loan: BorrowIndex, _node: LocalizedNode, _is_live: bool) {} /// Callback called when discovering a new `successor` node for the `current_node`. From 4a461d05962ab505bb149237381017e61bca7fd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 11:57:29 +0200 Subject: [PATCH 0610/1309] move `LivenessSource` to liveness module and group it with related code --- .../src/polonius/constraints.rs | 7 +- .../rustc_borrowck/src/polonius/liveness.rs | 89 ++++++++++--------- compiler/rustc_borrowck/src/polonius/mod.rs | 2 +- 3 files changed, 49 insertions(+), 49 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/constraints.rs b/compiler/rustc_borrowck/src/polonius/constraints.rs index 8386f60c40f03..5855f60a85217 100644 --- a/compiler/rustc_borrowck/src/polonius/constraints.rs +++ b/compiler/rustc_borrowck/src/polonius/constraints.rs @@ -10,7 +10,7 @@ use crate::BorrowSet; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; use crate::polonius::ConstraintDirection; -use crate::polonius::liveness::RegionLiveness; +use crate::polonius::liveness::LivenessSource; use crate::type_check::Locations; /// A localized outlives constraint reifies the CFG location where the outlives constraint holds, @@ -52,11 +52,6 @@ pub(super) struct LocalizedConstraintGraph { logical_edges: IndexVec>, } -/// The source of liveness information for a given region. -pub(super) trait LivenessSource { - fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>; -} - /// The visitor interface when traversing a `LocalizedConstraintGraph`. pub(super) trait LocalizedConstraintGraphVisitor { /// Callback called when traversing a given `loan` encounters a localized `node` it hasn't diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 017055c368364..a3653debd9897 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -10,6 +10,53 @@ use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::LivenessComputation; use crate::universal_regions::UniversalRegions; +/// The source of liveness information for a given region. +pub(super) trait LivenessSource { + fn liveness_for_region(&mut self, region: RegionVid) -> RegionLiveness<'_>; +} + +/// For a given region, the relevant liveness and variance information. +pub(super) struct RegionLiveness<'a> { + pub(super) direction: ConstraintDirection, + live_points: Option<&'a IntervalSet>, +} + +impl<'a> RegionLiveness<'a> { + #[inline] + pub(super) fn new<'tcx>( + region: RegionVid, + live_region_variances: &LiveRegionVariances, + universal_regions: &UniversalRegions<'tcx>, + live_points: &'a SparseIntervalMatrix, + ) -> Self { + // Universal regions propagate loans along the CFG, i.e. forwards only. + let is_universal_region = universal_regions.is_universal_region(region); + + // Note: there currently are cases related to promoted and const generics, where we don't yet + // have variance information (possibly about temporary regions created when typeck sanitizes the + // promoteds). Until that is done, we conservatively fallback to maximizing reachability by + // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus + // propagate liveness when needed. + // + // FIXME: add the missing variance information and remove this fallback bidirectional edge. + let direction = if is_universal_region { + ConstraintDirection::Forward + } else { + live_region_variances + .get(region) + .copied() + .flatten() + .unwrap_or(ConstraintDirection::Bidirectional) + }; + let live_points = live_points.row(region); + Self { direction, live_points } + } + + pub(super) fn is_live_at(&self, point: PointIndex) -> bool { + self.live_points.map_or(false, |points| points.contains(point)) + } +} + #[derive(Default)] pub(crate) struct DeferredLocals<'tcx> { /// For each region, the local whose liveness is deferred. @@ -80,45 +127,3 @@ impl<'tcx> DeferredLocals<'tcx> { }); } } - -/// For a given region, the relevant liveness and variance information. -pub(super) struct RegionLiveness<'a> { - pub(super) direction: ConstraintDirection, - live_points: Option<&'a IntervalSet>, -} - -impl<'a> RegionLiveness<'a> { - #[inline] - pub(super) fn new<'tcx>( - region: RegionVid, - live_region_variances: &LiveRegionVariances, - universal_regions: &UniversalRegions<'tcx>, - live_points: &'a SparseIntervalMatrix, - ) -> Self { - // Universal regions propagate loans along the CFG, i.e. forwards only. - let is_universal_region = universal_regions.is_universal_region(region); - - // Note: there currently are cases related to promoted and const generics, where we don't yet - // have variance information (possibly about temporary regions created when typeck sanitizes the - // promoteds). Until that is done, we conservatively fallback to maximizing reachability by - // adding a bidirectional edge here. This will not limit traversal whatsoever, and thus - // propagate liveness when needed. - // - // FIXME: add the missing variance information and remove this fallback bidirectional edge. - let direction = if is_universal_region { - ConstraintDirection::Forward - } else { - live_region_variances - .get(region) - .copied() - .flatten() - .unwrap_or(ConstraintDirection::Bidirectional) - }; - let live_points = live_points.row(region); - Self { direction, live_points } - } - - pub(super) fn is_live_at(&self, point: PointIndex) -> bool { - self.live_points.map_or(false, |points| points.contains(point)) - } -} diff --git a/compiler/rustc_borrowck/src/polonius/mod.rs b/compiler/rustc_borrowck/src/polonius/mod.rs index 36f1f9c795dae..73133b6ca0811 100644 --- a/compiler/rustc_borrowck/src/polonius/mod.rs +++ b/compiler/rustc_borrowck/src/polonius/mod.rs @@ -55,7 +55,7 @@ pub(crate) use self::liveness_constraints::record_live_region_variance; use crate::constraints::OutlivesConstraint; use crate::dataflow::BorrowIndex; pub(crate) use crate::polonius::liveness::DeferredLocals; -use crate::polonius::liveness::RegionLiveness; +use crate::polonius::liveness::{LivenessSource, RegionLiveness}; use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::{LivenessComputation, LocalUseMap}; use crate::universal_regions::UniversalRegions; From ec908e68c4be4e99b362739801c8f29424a38ff9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 12:07:38 +0200 Subject: [PATCH 0611/1309] remove unneeded `BorrowckInferCtxt` from `defer_local` --- compiler/rustc_borrowck/src/polonius/liveness.rs | 7 ++----- compiler/rustc_borrowck/src/type_check/liveness/trace.rs | 4 ++-- 2 files changed, 4 insertions(+), 7 deletions(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index a3653debd9897..4779eadaba1a8 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -1,10 +1,9 @@ use rustc_index::IndexVec; use rustc_index::interval::{IntervalSet, SparseIntervalMatrix}; use rustc_middle::mir::Local; -use rustc_middle::ty::{GenericArg, RegionVid, Ty}; +use rustc_middle::ty::{GenericArg, RegionVid, Ty, TyCtxt}; use rustc_mir_dataflow::points::PointIndex; -use crate::BorrowckInferCtxt; use crate::polonius::{ConstraintDirection, LiveRegionVariances}; use crate::region_infer::values::LivenessValues; use crate::type_check::liveness::LivenessComputation; @@ -71,14 +70,12 @@ pub(crate) struct DeferredLocals<'tcx> { impl<'tcx> DeferredLocals<'tcx> { pub(crate) fn defer_local( &mut self, - infcx: &BorrowckInferCtxt<'tcx>, + tcx: TyCtxt<'tcx>, universal_regions: &UniversalRegions<'tcx>, local: Local, local_ty: Ty<'tcx>, dropck_kinds: &[GenericArg<'tcx>], ) { - let tcx = infcx.tcx; - // We already have drop data for this local, because we need to register // region constraints eagerly. So, we'll store this so we don't need to // recompute. diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index f0de106412538..e7fe48cc10919 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -221,7 +221,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // are *no* drops (which is relatively cheap). if deferred.contains(&local) && self.comp.local_use_map.drops(local).next().is_none() { deferred_locals.defer_local( - typeck.infcx, + typeck.infcx.tcx, typeck.universal_regions, local, local_ty, @@ -265,7 +265,7 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // Finally, we mark that this local is deferred, including the drop kinds. deferred_locals.defer_local( - typeck.infcx, + typeck.infcx.tcx, typeck.universal_regions, local, local_ty, From 711bae498cd3b533c618ae03e61f1d54520b58c9 Mon Sep 17 00:00:00 2001 From: bjorn3 <17426603+bjorn3@users.noreply.github.com> Date: Tue, 22 Sep 2026 12:13:32 +0200 Subject: [PATCH 0612/1309] Prepare for merging from rust-lang/rust This updates the rust-toolchain.toml file to nightly-2026-09-22. --- compiler/rustc_codegen_cranelift/rust-toolchain.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_codegen_cranelift/rust-toolchain.toml b/compiler/rustc_codegen_cranelift/rust-toolchain.toml index ec7694364a8c9..a4cf19824d3d2 100644 --- a/compiler/rustc_codegen_cranelift/rust-toolchain.toml +++ b/compiler/rustc_codegen_cranelift/rust-toolchain.toml @@ -1,4 +1,4 @@ [toolchain] -channel = "nightly-2026-09-18" +channel = "nightly-2026-09-22" components = ["rust-src", "rustc-dev", "llvm-tools", "rustfmt"] profile = "minimal" From 1d76d15654fecf6dda2d1fb654d52e86871532c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 12:15:08 +0200 Subject: [PATCH 0613/1309] remove pre-existing link that doesn't work --- compiler/rustc_borrowck/src/polonius/liveness.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 4779eadaba1a8..5724648a41caf 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -86,7 +86,7 @@ impl<'tcx> DeferredLocals<'tcx> { // we can trace liveness for the local containing it. let by_region = &mut self.by_region; tcx.for_each_free_region(&local_ty, |region| { - // See note in [`VarianceExtractor::record_variance`]. + // See note in `VarianceExtractor::record_variance`. if region.is_bound() || region.is_erased() { return; } From 0875187de8adb22e31d529f8b038a0ad2cda4335 Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Tue, 26 May 2026 14:21:18 +0000 Subject: [PATCH 0614/1309] fix issue-156949 --- compiler/rustc_resolve/src/late.rs | 25 +++++++++- .../ui/resolve/detect-missing-else-in-let.rs | 11 +++++ .../resolve/detect-missing-else-in-let.stderr | 47 +++++++++++++++++++ 3 files changed, 82 insertions(+), 1 deletion(-) create mode 100644 tests/ui/resolve/detect-missing-else-in-let.rs create mode 100644 tests/ui/resolve/detect-missing-else-in-let.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 7d90b93b62375..253a7620c519d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -759,9 +759,12 @@ pub(crate) struct DiagMetadata<'ast> { /// they are used (in a `break` or `continue` statement) unused_labels: FxIndexMap, - /// Only used for better errors on `let : ;`. + /// Used for better errors on `let : ;`. current_let_binding: Option<(Span, Option, Option)>, + /// Only used for better errors on `let = val{}` when the user forget `else`. + struct_field_parse_failed: bool, + current_pat: Option<&'ast Pat>, /// Used to detect possible `if let` written without `let` and to provide structured suggestion. @@ -4673,6 +4676,20 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | PathSource::PreciseCapturingArg(..) = source { this.suggest_adding_generic_parameter(path, source) + } else if let Some(Res::Local(_)) = &res + && this.diag_metadata.struct_field_parse_failed + && this.diag_metadata.current_let_binding.is_some() + { + let span = path[0].ident.span.shrink_to_hi(); + ( + Some(( + span, + "try adding `else` here:", + " else ".to_string(), + Applicability::MaybeIncorrect, + )), + None, + ) } else { (None, None) }; @@ -5279,7 +5296,13 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ExprKind::Struct(ref se) => { + if let StructRest::NoneWithError(_) = &se.rest + && se.fields.is_empty() + { + self.diag_metadata.struct_field_parse_failed = true; + } self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct(parent)); + self.diag_metadata.struct_field_parse_failed = false; // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the // parent in for accurate suggestions when encountering `Foo { bar }` that should // have been `Foo { bar: self.bar }`. diff --git a/tests/ui/resolve/detect-missing-else-in-let.rs b/tests/ui/resolve/detect-missing-else-in-let.rs new file mode 100644 index 0000000000000..c7472f5e4dffd --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let.rs @@ -0,0 +1,11 @@ +// detect missing else in let statement. (issue #135857) +fn main() { + let foo = Some(1); + let Some(a) = foo{return;}; //~ ERROR E0574 + //~| HELP try adding `else` here: + //~| HELP escape `return` to use it as an identifier + //~| ERROR expected identifier, found keyword `return` + let Some(b) = foo{todo!()}; //~ ERROR E0574 + //~| HELP try adding `else` here: + //~| ERROR expected one of `,`, `:`, or `}`, found `!` +} diff --git a/tests/ui/resolve/detect-missing-else-in-let.stderr b/tests/ui/resolve/detect-missing-else-in-let.stderr new file mode 100644 index 0000000000000..48ea7cf96a824 --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let.stderr @@ -0,0 +1,47 @@ +error: expected identifier, found keyword `return` + --> $DIR/detect-missing-else-in-let.rs:4:23 + | +LL | let Some(a) = foo{return;}; + | --- ^^^^^^ expected identifier, found keyword + | | + | while parsing this struct + | +help: escape `return` to use it as an identifier + | +LL | let Some(a) = foo{r#return;}; + | ++ + +error: expected one of `,`, `:`, or `}`, found `!` + --> $DIR/detect-missing-else-in-let.rs:8:27 + | +LL | let Some(b) = foo{todo!()}; + | --- ----^ expected one of `,`, `:`, or `}` + | | | + | | while parsing this struct field + | while parsing this struct + +error[E0574]: expected struct, variant or union type, found local variable `foo` + --> $DIR/detect-missing-else-in-let.rs:4:19 + | +LL | let Some(a) = foo{return;}; + | ^^^ not a struct, variant or union type + | +help: try adding `else` here: + | +LL | let Some(a) = foo else {return;}; + | ++++ + +error[E0574]: expected struct, variant or union type, found local variable `foo` + --> $DIR/detect-missing-else-in-let.rs:8:19 + | +LL | let Some(b) = foo{todo!()}; + | ^^^ not a struct, variant or union type + | +help: try adding `else` here: + | +LL | let Some(b) = foo else {todo!()}; + | ++++ + +error: aborting due to 4 previous errors + +For more information about this error, try `rustc --explain E0574`. From f9276f4bf58f347b732ef624896e1ad77b96a011 Mon Sep 17 00:00:00 2001 From: b1yd <2156864690@qq.com> Date: Mon, 1 Jun 2026 11:52:02 +0800 Subject: [PATCH 0615/1309] fix --- compiler/rustc_resolve/src/late.rs | 10 +++++-- ...let.rs => detect-missing-else-in-let-1.rs} | 4 +-- ...rr => detect-missing-else-in-let-1.stderr} | 14 ++++++---- .../resolve/detect-missing-else-in-let-2.rs | 10 +++++++ .../detect-missing-else-in-let-2.stderr | 28 +++++++++++++++++++ 5 files changed, 55 insertions(+), 11 deletions(-) rename tests/ui/resolve/{detect-missing-else-in-let.rs => detect-missing-else-in-let-1.rs} (74%) rename tests/ui/resolve/{detect-missing-else-in-let.stderr => detect-missing-else-in-let-1.stderr} (67%) create mode 100644 tests/ui/resolve/detect-missing-else-in-let-2.rs create mode 100644 tests/ui/resolve/detect-missing-else-in-let-2.stderr diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 253a7620c519d..1450348384109 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -762,7 +762,7 @@ pub(crate) struct DiagMetadata<'ast> { /// Used for better errors on `let : ;`. current_let_binding: Option<(Span, Option, Option)>, - /// Only used for better errors on `let = val{}` when the user forget `else`. + /// Only used for better errors on `let = val {}` when the user forget `else`. struct_field_parse_failed: bool, current_pat: Option<&'ast Pat>, @@ -4684,7 +4684,10 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ( Some(( span, - "try adding `else` here:", + "you might have meant to write a diverging block on a refutable `let` \ + statement by using `let-else`\n\ + for more information, visit \ + ", " else ".to_string(), Applicability::MaybeIncorrect, )), @@ -5296,13 +5299,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ExprKind::Struct(ref se) => { + let struct_field_parse_failed = self.diag_metadata.struct_field_parse_failed; if let StructRest::NoneWithError(_) = &se.rest && se.fields.is_empty() { self.diag_metadata.struct_field_parse_failed = true; } self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct(parent)); - self.diag_metadata.struct_field_parse_failed = false; + self.diag_metadata.struct_field_parse_failed = struct_field_parse_failed; // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the // parent in for accurate suggestions when encountering `Foo { bar }` that should // have been `Foo { bar: self.bar }`. diff --git a/tests/ui/resolve/detect-missing-else-in-let.rs b/tests/ui/resolve/detect-missing-else-in-let-1.rs similarity index 74% rename from tests/ui/resolve/detect-missing-else-in-let.rs rename to tests/ui/resolve/detect-missing-else-in-let-1.rs index c7472f5e4dffd..26046eb7c40ac 100644 --- a/tests/ui/resolve/detect-missing-else-in-let.rs +++ b/tests/ui/resolve/detect-missing-else-in-let-1.rs @@ -2,10 +2,10 @@ fn main() { let foo = Some(1); let Some(a) = foo{return;}; //~ ERROR E0574 - //~| HELP try adding `else` here: + //~| HELP you might have meant to write a diverging block //~| HELP escape `return` to use it as an identifier //~| ERROR expected identifier, found keyword `return` let Some(b) = foo{todo!()}; //~ ERROR E0574 - //~| HELP try adding `else` here: + //~| HELP you might have meant to write a diverging block //~| ERROR expected one of `,`, `:`, or `}`, found `!` } diff --git a/tests/ui/resolve/detect-missing-else-in-let.stderr b/tests/ui/resolve/detect-missing-else-in-let-1.stderr similarity index 67% rename from tests/ui/resolve/detect-missing-else-in-let.stderr rename to tests/ui/resolve/detect-missing-else-in-let-1.stderr index 48ea7cf96a824..da37fca4e4498 100644 --- a/tests/ui/resolve/detect-missing-else-in-let.stderr +++ b/tests/ui/resolve/detect-missing-else-in-let-1.stderr @@ -1,5 +1,5 @@ error: expected identifier, found keyword `return` - --> $DIR/detect-missing-else-in-let.rs:4:23 + --> $DIR/detect-missing-else-in-let-1.rs:4:23 | LL | let Some(a) = foo{return;}; | --- ^^^^^^ expected identifier, found keyword @@ -12,7 +12,7 @@ LL | let Some(a) = foo{r#return;}; | ++ error: expected one of `,`, `:`, or `}`, found `!` - --> $DIR/detect-missing-else-in-let.rs:8:27 + --> $DIR/detect-missing-else-in-let-1.rs:8:27 | LL | let Some(b) = foo{todo!()}; | --- ----^ expected one of `,`, `:`, or `}` @@ -21,23 +21,25 @@ LL | let Some(b) = foo{todo!()}; | while parsing this struct error[E0574]: expected struct, variant or union type, found local variable `foo` - --> $DIR/detect-missing-else-in-let.rs:4:19 + --> $DIR/detect-missing-else-in-let-1.rs:4:19 | LL | let Some(a) = foo{return;}; | ^^^ not a struct, variant or union type | -help: try adding `else` here: +help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` + for more information, visit | LL | let Some(a) = foo else {return;}; | ++++ error[E0574]: expected struct, variant or union type, found local variable `foo` - --> $DIR/detect-missing-else-in-let.rs:8:19 + --> $DIR/detect-missing-else-in-let-1.rs:8:19 | LL | let Some(b) = foo{todo!()}; | ^^^ not a struct, variant or union type | -help: try adding `else` here: +help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` + for more information, visit | LL | let Some(b) = foo else {todo!()}; | ++++ diff --git a/tests/ui/resolve/detect-missing-else-in-let-2.rs b/tests/ui/resolve/detect-missing-else-in-let-2.rs new file mode 100644 index 0000000000000..2b12a8c53d1d7 --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let-2.rs @@ -0,0 +1,10 @@ +// the compiler currently will suggest the user to add `else` in this case +// it shouldn't because `bar` is an irrefutable pattern, the else block would never be valid/useful +// it is currently unmitigated +fn main(){ + let foo = 12; + let bar = foo{return;};//~ ERROR E0574 + //~| HELP you might have meant to write a diverging block + //~| HELP escape `return` to use it as an identifier + //~| ERROR expected identifier, found keyword `return` +} diff --git a/tests/ui/resolve/detect-missing-else-in-let-2.stderr b/tests/ui/resolve/detect-missing-else-in-let-2.stderr new file mode 100644 index 0000000000000..f29dfa0db7b07 --- /dev/null +++ b/tests/ui/resolve/detect-missing-else-in-let-2.stderr @@ -0,0 +1,28 @@ +error: expected identifier, found keyword `return` + --> $DIR/detect-missing-else-in-let-2.rs:6:19 + | +LL | let bar = foo{return;}; + | --- ^^^^^^ expected identifier, found keyword + | | + | while parsing this struct + | +help: escape `return` to use it as an identifier + | +LL | let bar = foo{r#return;}; + | ++ + +error[E0574]: expected struct, variant or union type, found local variable `foo` + --> $DIR/detect-missing-else-in-let-2.rs:6:15 + | +LL | let bar = foo{return;}; + | ^^^ not a struct, variant or union type + | +help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` + for more information, visit + | +LL | let bar = foo else {return;}; + | ++++ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0574`. From 355aec9742693ca5a855619aa32325464d716aa3 Mon Sep 17 00:00:00 2001 From: byd1 <2156864690@qq.com> Date: Wed, 8 Jul 2026 20:47:31 +0800 Subject: [PATCH 0616/1309] changed to parser --- compiler/rustc_parse/src/diagnostics.rs | 12 +++++ compiler/rustc_parse/src/parser/expr.rs | 31 +++++++++++- compiler/rustc_parse/src/parser/mod.rs | 3 ++ compiler/rustc_parse/src/parser/stmt.rs | 7 ++- compiler/rustc_resolve/src/late.rs | 29 +---------- .../ui/parser/detect-missing-else-in-let-1.rs | 8 +++ .../detect-missing-else-in-let-1.stderr | 20 ++++++++ .../detect-missing-else-in-let-2.rs | 4 +- .../detect-missing-else-in-let-2.stderr | 10 +--- .../resolve/detect-missing-else-in-let-1.rs | 11 ----- .../detect-missing-else-in-let-1.stderr | 49 ------------------- 11 files changed, 79 insertions(+), 105 deletions(-) create mode 100644 tests/ui/parser/detect-missing-else-in-let-1.rs create mode 100644 tests/ui/parser/detect-missing-else-in-let-1.stderr rename tests/ui/{resolve => parser}/detect-missing-else-in-let-2.rs (77%) rename tests/ui/{resolve => parser}/detect-missing-else-in-let-2.stderr (66%) delete mode 100644 tests/ui/resolve/detect-missing-else-in-let-1.rs delete mode 100644 tests/ui/resolve/detect-missing-else-in-let-1.stderr diff --git a/compiler/rustc_parse/src/diagnostics.rs b/compiler/rustc_parse/src/diagnostics.rs index 566b257d1058d..b6482aa23e836 100644 --- a/compiler/rustc_parse/src/diagnostics.rs +++ b/compiler/rustc_parse/src/diagnostics.rs @@ -4651,3 +4651,15 @@ pub(crate) struct SuggestIntroduceTypeParameter { pub span: Span, pub parameters: String, } + +#[derive(Subdiagnostic)] +#[suggestion( + "you might have meant to write a diverging block on a refutable `let` statement by using `let-else` + for more information, visit ", + code = " else ", + applicability = "maybe-incorrect" +)] +pub(crate) struct MissingElseInLet { + #[primary_span] + pub span: Span, +} diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs index a2db5c047394a..5bc30ae7ba325 100644 --- a/compiler/rustc_parse/src/parser/expr.rs +++ b/compiler/rustc_parse/src/parser/expr.rs @@ -57,7 +57,11 @@ impl<'a> Parser<'a> { self.current_closure.take(); self.parse_expr_res(Restrictions::empty()) } - + #[inline] + pub fn parse_expr_in_let(&mut self) -> PResult<'a, Box> { + self.current_closure.take(); + self.parse_expr_res(Restrictions::IN_LET) + } /// Parses an expression, forcing tokens to be collected. pub fn parse_expr_force_collect(&mut self) -> PResult<'a, Box> { self.current_closure.take(); @@ -3680,11 +3684,12 @@ impl<'a> Parser<'a> { Option, /* async blocks are forbidden in Rust 2015 */ ), > { + let open_span = self.prev_token.span; //{ let mut fields = ThinVec::new(); let mut base = ast::StructRest::None; let mut recovered_async = None; let in_if_guard = self.restrictions.contains(Restrictions::IN_IF_GUARD); - + let in_let = self.restrictions.contains(Restrictions::IN_LET); let async_block_err = |e: &mut Diag<'_>, span: Span| { crate::diagnostics::AsyncBlockIn2015 { span }.add_to_diag(e); crate::diagnostics::HelpUseLatestEdition::new().add_to_diag(e); @@ -3769,6 +3774,28 @@ impl<'a> Parser<'a> { return Err(e); } + if in_let { + // Better diagnostic for `foo { return 42; };` + // We've consumed `foo {` already + let mut snapshot = self.create_snapshot_for_diagnostic(); + let might_be_stmt = snapshot.token.is_keyword(kw::Return); + snapshot.consume_block( + exp!(OpenBrace), + exp!(CloseBrace), + super::diagnostics::ConsumeClosingDelim::Yes, + ); //consume to the end of the block, including `}` + + // make sure the block is at the end by eating a `;`, + // we shouldn't report such diagnostic for `let a = foo{return 43;}+bar;` + // also skip the suggestion if the span cross macro boundaries + if might_be_stmt && snapshot.eat(exp!(Semi)) && pth.span.eq_ctxt(open_span) + { + let span = pth.span.between(open_span); + e.subdiagnostic(crate::diagnostics::MissingElseInLet { span }); + self.restore_snapshot(snapshot); + return Err(e); + } + } let guar = e.emit_err(); if pth == kw::Async { recovered_async = Some(guar); diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs index 281ca98e97639..50ded81e3eeec 100644 --- a/compiler/rustc_parse/src/parser/mod.rs +++ b/compiler/rustc_parse/src/parser/mod.rs @@ -125,6 +125,9 @@ bitflags::bitflags! { /// expression, but halts parsing the expression when reaching certain /// tokens like `=`. const IS_PAT = 1 << 5; + /// Used to detect a missing `else` in a let statement. + /// e.g. let Some(foo) = bar{return;}; + const IN_LET = 1 << 6; } } diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs index a082ea678737d..d59ef93eded21 100644 --- a/compiler/rustc_parse/src/parser/stmt.rs +++ b/compiler/rustc_parse/src/parser/stmt.rs @@ -3,14 +3,13 @@ use std::mem; use std::ops::Bound; use ast::Label; -use rustc_ast as ast; use rustc_ast::token::{self, Delimiter, InvisibleOrigin, MetaVarKind, TokenKind}; use rustc_ast::tokenstream::TokenTree; use rustc_ast::util::classify::{self, TrailingBrace}; use rustc_ast::visit::{Visitor, walk_expr}; use rustc_ast::{ - AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, HasAttrs, Local, - LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind, + self as ast, AttrStyle, AttrVec, Block, BlockCheckMode, DUMMY_NODE_ID, Expr, ExprKind, + HasAttrs, Local, LocalKind, MacCall, MacCallStmt, MacStmtStyle, Recovered, Stmt, StmtKind, }; use rustc_errors::{Applicability, Diag, PResult}; use rustc_span::{ErrorGuaranteed, Ident, Span, kw, sym}; @@ -517,7 +516,7 @@ impl<'a> Parser<'a> { _ => self.eat(exp!(Eq)), }; - Ok(if eq_consumed || eq_optional { Some(self.parse_expr()?) } else { None }) + Ok(if eq_consumed || eq_optional { Some(self.parse_expr_in_let()?) } else { None }) } /// Parses a block. No inner attributes are allowed. diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 1450348384109..7d90b93b62375 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -759,12 +759,9 @@ pub(crate) struct DiagMetadata<'ast> { /// they are used (in a `break` or `continue` statement) unused_labels: FxIndexMap, - /// Used for better errors on `let : ;`. + /// Only used for better errors on `let : ;`. current_let_binding: Option<(Span, Option, Option)>, - /// Only used for better errors on `let = val {}` when the user forget `else`. - struct_field_parse_failed: bool, - current_pat: Option<&'ast Pat>, /// Used to detect possible `if let` written without `let` and to provide structured suggestion. @@ -4676,23 +4673,6 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { | PathSource::PreciseCapturingArg(..) = source { this.suggest_adding_generic_parameter(path, source) - } else if let Some(Res::Local(_)) = &res - && this.diag_metadata.struct_field_parse_failed - && this.diag_metadata.current_let_binding.is_some() - { - let span = path[0].ident.span.shrink_to_hi(); - ( - Some(( - span, - "you might have meant to write a diverging block on a refutable `let` \ - statement by using `let-else`\n\ - for more information, visit \ - ", - " else ".to_string(), - Applicability::MaybeIncorrect, - )), - None, - ) } else { (None, None) }; @@ -5299,14 +5279,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ExprKind::Struct(ref se) => { - let struct_field_parse_failed = self.diag_metadata.struct_field_parse_failed; - if let StructRest::NoneWithError(_) = &se.rest - && se.fields.is_empty() - { - self.diag_metadata.struct_field_parse_failed = true; - } self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct(parent)); - self.diag_metadata.struct_field_parse_failed = struct_field_parse_failed; // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the // parent in for accurate suggestions when encountering `Foo { bar }` that should // have been `Foo { bar: self.bar }`. diff --git a/tests/ui/parser/detect-missing-else-in-let-1.rs b/tests/ui/parser/detect-missing-else-in-let-1.rs new file mode 100644 index 0000000000000..9f9d11e558d4c --- /dev/null +++ b/tests/ui/parser/detect-missing-else-in-let-1.rs @@ -0,0 +1,8 @@ +// detect missing else in let statement. (issue #135857) +fn main() { + let foo = Some(1); + let Some(a) = foo{return;}; + //~^ HELP you might have meant to write a diverging block + //~| HELP escape `return` to use it as an identifier + //~| ERROR expected identifier, found keyword `return` +} diff --git a/tests/ui/parser/detect-missing-else-in-let-1.stderr b/tests/ui/parser/detect-missing-else-in-let-1.stderr new file mode 100644 index 0000000000000..2236bb1671464 --- /dev/null +++ b/tests/ui/parser/detect-missing-else-in-let-1.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found keyword `return` + --> $DIR/detect-missing-else-in-let-1.rs:4:23 + | +LL | let Some(a) = foo{return;}; + | --- ^^^^^^ expected identifier, found keyword + | | + | while parsing this struct + | +help: escape `return` to use it as an identifier + | +LL | let Some(a) = foo{r#return;}; + | ++ +help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` + for more information, visit + | +LL | let Some(a) = foo else {return;}; + | ++++ + +error: aborting due to 1 previous error + diff --git a/tests/ui/resolve/detect-missing-else-in-let-2.rs b/tests/ui/parser/detect-missing-else-in-let-2.rs similarity index 77% rename from tests/ui/resolve/detect-missing-else-in-let-2.rs rename to tests/ui/parser/detect-missing-else-in-let-2.rs index 2b12a8c53d1d7..87a5a750bf9f5 100644 --- a/tests/ui/resolve/detect-missing-else-in-let-2.rs +++ b/tests/ui/parser/detect-missing-else-in-let-2.rs @@ -3,8 +3,8 @@ // it is currently unmitigated fn main(){ let foo = 12; - let bar = foo{return;};//~ ERROR E0574 - //~| HELP you might have meant to write a diverging block + let bar = foo{return;}; + //~^ HELP you might have meant to write a diverging block //~| HELP escape `return` to use it as an identifier //~| ERROR expected identifier, found keyword `return` } diff --git a/tests/ui/resolve/detect-missing-else-in-let-2.stderr b/tests/ui/parser/detect-missing-else-in-let-2.stderr similarity index 66% rename from tests/ui/resolve/detect-missing-else-in-let-2.stderr rename to tests/ui/parser/detect-missing-else-in-let-2.stderr index f29dfa0db7b07..5f21c9fe5fa83 100644 --- a/tests/ui/resolve/detect-missing-else-in-let-2.stderr +++ b/tests/ui/parser/detect-missing-else-in-let-2.stderr @@ -10,19 +10,11 @@ help: escape `return` to use it as an identifier | LL | let bar = foo{r#return;}; | ++ - -error[E0574]: expected struct, variant or union type, found local variable `foo` - --> $DIR/detect-missing-else-in-let-2.rs:6:15 - | -LL | let bar = foo{return;}; - | ^^^ not a struct, variant or union type - | help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` for more information, visit | LL | let bar = foo else {return;}; | ++++ -error: aborting due to 2 previous errors +error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0574`. diff --git a/tests/ui/resolve/detect-missing-else-in-let-1.rs b/tests/ui/resolve/detect-missing-else-in-let-1.rs deleted file mode 100644 index 26046eb7c40ac..0000000000000 --- a/tests/ui/resolve/detect-missing-else-in-let-1.rs +++ /dev/null @@ -1,11 +0,0 @@ -// detect missing else in let statement. (issue #135857) -fn main() { - let foo = Some(1); - let Some(a) = foo{return;}; //~ ERROR E0574 - //~| HELP you might have meant to write a diverging block - //~| HELP escape `return` to use it as an identifier - //~| ERROR expected identifier, found keyword `return` - let Some(b) = foo{todo!()}; //~ ERROR E0574 - //~| HELP you might have meant to write a diverging block - //~| ERROR expected one of `,`, `:`, or `}`, found `!` -} diff --git a/tests/ui/resolve/detect-missing-else-in-let-1.stderr b/tests/ui/resolve/detect-missing-else-in-let-1.stderr deleted file mode 100644 index da37fca4e4498..0000000000000 --- a/tests/ui/resolve/detect-missing-else-in-let-1.stderr +++ /dev/null @@ -1,49 +0,0 @@ -error: expected identifier, found keyword `return` - --> $DIR/detect-missing-else-in-let-1.rs:4:23 - | -LL | let Some(a) = foo{return;}; - | --- ^^^^^^ expected identifier, found keyword - | | - | while parsing this struct - | -help: escape `return` to use it as an identifier - | -LL | let Some(a) = foo{r#return;}; - | ++ - -error: expected one of `,`, `:`, or `}`, found `!` - --> $DIR/detect-missing-else-in-let-1.rs:8:27 - | -LL | let Some(b) = foo{todo!()}; - | --- ----^ expected one of `,`, `:`, or `}` - | | | - | | while parsing this struct field - | while parsing this struct - -error[E0574]: expected struct, variant or union type, found local variable `foo` - --> $DIR/detect-missing-else-in-let-1.rs:4:19 - | -LL | let Some(a) = foo{return;}; - | ^^^ not a struct, variant or union type - | -help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` - for more information, visit - | -LL | let Some(a) = foo else {return;}; - | ++++ - -error[E0574]: expected struct, variant or union type, found local variable `foo` - --> $DIR/detect-missing-else-in-let-1.rs:8:19 - | -LL | let Some(b) = foo{todo!()}; - | ^^^ not a struct, variant or union type - | -help: you might have meant to write a diverging block on a refutable `let` statement by using `let-else` - for more information, visit - | -LL | let Some(b) = foo else {todo!()}; - | ++++ - -error: aborting due to 4 previous errors - -For more information about this error, try `rustc --explain E0574`. From a577aaec25d16310827a219511acbc6c885ce0ce Mon Sep 17 00:00:00 2001 From: Ada Alakbarova Date: Tue, 22 Sep 2026 12:40:45 +0200 Subject: [PATCH 0617/1309] Various small simplifications in `clippy_utils::ty` --- clippy_utils/src/ty/mod.rs | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a244767cf3c3f..cf7ea42d72f80 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -25,8 +25,8 @@ use rustc_middle::ty::layout::{LayoutError, LayoutOf as _, TyAndLayout}; use rustc_middle::ty::{ self, AdtDef, AliasTy, AssocItem, AssocTag, Binder, BoundRegion, BoundVarIndexKind, FnSig, GenericArg, GenericArgKind, GenericArgsRef, IntTy, ProjectionAliasTy, Region, RegionKind, TraitRef, Ty, TyCtxt, - TypeSuperVisitable as _, TypeVisitable, TypeVisitableExt as _, TypeVisitor, UintTy, Unnormalized, Upcast as _, - VariantDef, VariantDiscr, + TypeSuperVisitable as _, TypeVisitable, TypeVisitableExt as _, TypeVisitor, UintTy, Unnormalized, VariantDef, + VariantDiscr, }; use rustc_span::symbol::Ident; use rustc_span::{DUMMY_SP, Span, Symbol}; @@ -291,8 +291,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( let (infcx, param_env) = tcx.infer_ctxt().build_with_typing_env(typing_env); let args = args .into_iter() - .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())) - .collect::>(); + .map(|arg| arg.into().unwrap_or_else(|| infcx.next_ty_var(DUMMY_SP).into())); let trait_ref = TraitRef::new(tcx, trait_id, [GenericArg::from(ty)].into_iter().chain(args)); @@ -304,12 +303,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( #[cfg(debug_assertions)] assert_generic_args_match(tcx, trait_id, trait_ref.args); - let obligation = Obligation { - cause: ObligationCause::dummy(), - param_env, - recursion_depth: 0, - predicate: trait_ref.upcast(tcx), - }; + let obligation = Obligation::new(tcx, ObligationCause::dummy(), param_env, trait_ref); infcx .evaluate_obligation(&obligation) .is_ok_and(EvaluationResult::must_apply_modulo_regions) @@ -317,10 +311,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>( /// Checks whether this type implements `Drop`. pub fn has_drop<'tcx>(cx: &LateContext<'tcx>, ty: Ty<'tcx>) -> bool { - match ty.ty_adt_def() { - Some(def) => def.has_dtor(cx.tcx), - None => false, - } + ty.ty_adt_def().is_some_and(|def| def.has_dtor(cx.tcx)) } /// Returns whether the `ty` has `#[must_use]` attribute, or acts like it does according to the @@ -1459,9 +1450,8 @@ pub fn get_adt_inherent_method<'a>(cx: &'a LateContext<'_>, ty: Ty<'_>, method_n cx.tcx.inherent_impls(ty_did).iter().find_map(|&did| { cx.tcx .associated_items(did) - .filter_by_name_unhygienic(method_name) + .filter_by_name_unhygienic_and_kind(method_name, AssocTag::Fn) .next() - .filter(|item| item.tag() == AssocTag::Fn) }) } @@ -1480,8 +1470,7 @@ pub fn get_field_by_name<'tcx>(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>, name: Symbol) -> } pub fn get_field_def_id_by_name(ty: Ty<'_>, name: Symbol) -> Option { - let ty::Adt(adt_def, ..) = ty.kind() else { return None }; - adt_def + ty.ty_adt_def()? .all_fields() .find_map(|field| if field.name == name { Some(field.did) } else { None }) } From abcb9780d6d41fde73929b766238acc2b0582fa4 Mon Sep 17 00:00:00 2001 From: David Venhoek Date: Mon, 7 Sep 2026 14:09:09 +0200 Subject: [PATCH 0618/1309] Rename the src install build step to rust-src. This avoids installing the src component from the command line also triggering a whole lot of other things which are behind the src path. Furthermore, it makes the name match the component as distributed in rustup, reducing confusion. --- bootstrap.example.toml | 2 +- src/bootstrap/src/core/build_steps/install.rs | 4 +-- src/bootstrap/src/core/builder/tests.rs | 36 ++----------------- src/bootstrap/src/utils/change_tracker.rs | 5 +++ .../install-rust-for-fuchsia.sh | 2 +- 5 files changed, 11 insertions(+), 38 deletions(-) diff --git a/bootstrap.example.toml b/bootstrap.example.toml index 0470b9151ef34..7f4aac63f36a8 100644 --- a/bootstrap.example.toml +++ b/bootstrap.example.toml @@ -431,7 +431,7 @@ # "rust-analyzer", # "rust-analyzer-proc-macro-srv", # "analysis", -# "src", +# "rust-src", # "wasm-component-ld", # "miri", "cargo-miri" # for dev/nightly channels #] diff --git a/src/bootstrap/src/core/build_steps/install.rs b/src/bootstrap/src/core/build_steps/install.rs index db0d18e8368e2..cad6117e686da 100644 --- a/src/bootstrap/src/core/build_steps/install.rs +++ b/src/bootstrap/src/core/build_steps/install.rs @@ -324,12 +324,12 @@ impl CommandLineStep for Src { const IS_HOST: bool = true; fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> { - run.path("src") + run.alias("rust-src") } fn is_default_step(builder: &Builder<'_>) -> bool { let config = &builder.config; - config.extended && config.tools.as_ref().is_none_or(|t| t.contains("src")) + config.extended && config.tools.as_ref().is_none_or(|t| t.contains("rust-src")) } fn make_run(run: RunConfig<'_>) { diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs index 9c613811c8ccc..cc6ac39672950 100644 --- a/src/bootstrap/src/core/builder/tests.rs +++ b/src/bootstrap/src/core/builder/tests.rs @@ -2798,7 +2798,7 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("install") - .path("src") + .path("rust-src") .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -2815,36 +2815,7 @@ mod snapshot { .render_with(RenderConfig { normalize_host: false }), @r" - [build] llvm - [build] rustc 0 -> rustc 1 - [build] rustc 1 -> std 1 - [build] rustc 0 -> UnstableBookGen 1 - [build] rustc 0 -> Rustbook 1 - [doc] unstable-book (book) - [doc] book (book) - [doc] book/first-edition (book) - [doc] book/second-edition (book) - [doc] book/2018-edition (book) - [build] rustdoc 1 - [doc] rustc 1 -> standalone 2 - [doc] rustc 1 -> std 1 crates=[alloc,compiler_builtins,core,panic_abort,panic_unwind,proc_macro,rustc-std-workspace-core,std,std_detect,sysroot,test,unwind] - [build] rustc 1 -> rustc 2 - [build] rustc 1 -> error-index 2 - [doc] rustc 1 -> error-index 2 - [doc] nomicon (book) - [doc] rustc 1 -> reference (book) 2 - [doc] rustdoc (book) - [doc] rust-by-example (book) - [build] rustc 0 -> LintDocs 1 - [doc] rustc (book) - [doc] cargo (book) - [doc] clippy (book) - [doc] embedded-book (book) - [doc] edition-guide (book) - [doc] style-guide (book) - [doc] rustc 1 -> releases 2 [build] rustc 0 -> RustInstaller 1 - [dist] docs [dist] src <> "); } @@ -2854,7 +2825,7 @@ mod snapshot { let ctx = TestCtx::new(); insta::assert_snapshot!( ctx.config("install") - .path("src") + .path("rust-src") .args(&[ // Using backslashes fails with `--set` "--set", &format!("install.prefix={}", ctx.normalized_dir()), @@ -2872,10 +2843,7 @@ mod snapshot { .render_with(RenderConfig { normalize_host: false }), @r" - [build] llvm - [build] rustc 0 -> rustc 1 [build] rustc 0 -> RustInstaller 1 - [dist] docs [dist] src <> "); } diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs index 25c0963aa4191..922d969ec1f35 100644 --- a/src/bootstrap/src/utils/change_tracker.rs +++ b/src/bootstrap/src/utils/change_tracker.rs @@ -671,4 +671,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[ severity: ChangeSeverity::Warning, summary: "The `override-allocator` option has been renamed: The global setting is now `build.allocator` and the per-target setting is `target..allocator`. It can now be set to 'system' to explicitly request the system allocator.", }, + ChangeInfo { + change_id: 162423, + severity: ChangeSeverity::Warning, + summary: "You should now use `x install rust-src` instead of `x install src` to install the standard library source component. If you want to install it as part of a custom `build.tools` set, include `rust-src` in `build.tools.", + }, ]; diff --git a/src/ci/docker/host-x86_64/test-x86_64-fuchsia/install-rust-for-fuchsia.sh b/src/ci/docker/host-x86_64/test-x86_64-fuchsia/install-rust-for-fuchsia.sh index a7b0f295090d6..edfbc7fdf5c66 100755 --- a/src/ci/docker/host-x86_64/test-x86_64-fuchsia/install-rust-for-fuchsia.sh +++ b/src/ci/docker/host-x86_64/test-x86_64-fuchsia/install-rust-for-fuchsia.sh @@ -5,7 +5,7 @@ set -ex # Build the components of Rust that are needed by the Fuchsia build system. python3 ../x.py install \ --target=$TARGETS \ - compiler/rustc library/std clippy rustfmt src + compiler/rustc library/std clippy rustfmt rust-src # The Fuchsia build system requires that shared libraries that are used inside Fuchsia are stripped, # so use `llvm-objcopy` to remove the debug symbols and strip the libraries, but keeping the From 622fd6a3f80ff4398db552ed138243c845347298 Mon Sep 17 00:00:00 2001 From: lcnr Date: Tue, 22 Sep 2026 13:46:48 +0200 Subject: [PATCH 0619/1309] treat inductive cycles as ambig --- .../src/solve/eval_ctxt/mod.rs | 5 ++- .../src/solve/search_graph.rs | 34 +++++++------------ .../placeholder-assumptions-issue-157840.rs | 2 +- ...laceholder-assumptions-issue-157840.stderr | 11 ++---- ...aram-recursion-issue-152716.current.stderr | 15 ++++++++ ...d-param-recursion-issue-152716.next.stderr | 9 +++++ .../find-param-recursion-issue-152716.rs | 7 ++-- .../find-param-recursion-issue-152716.stderr | 14 -------- ...ursive-self-normalization-2.current.stderr | 9 +++++ ...recursive-self-normalization-2.next.stderr | 15 ++++++++ .../recursive-self-normalization-2.rs | 7 ++-- .../recursive-self-normalization-2.stderr | 19 ----------- ...e-self-normalization-simple.current.stderr | 9 +++++ ...sive-self-normalization-simple.next.stderr | 9 +++++ .../recursive-self-normalization-simple.rs | 19 +++++++++++ ...ecursive-self-normalization.current.stderr | 9 +++++ .../recursive-self-normalization.next.stderr | 9 +++++ .../overflow/recursive-self-normalization.rs | 6 ++-- .../recursive-self-normalization.stderr | 19 ----------- 19 files changed, 138 insertions(+), 89 deletions(-) create mode 100644 tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr create mode 100644 tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr delete mode 100644 tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr delete mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr create mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr delete mode 100644 tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3a4875c1d0951..e5b8c8759f9bc 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -460,7 +460,10 @@ where // Relating types is always unproductive. If we were to map proof trees to // corecursive functions as explained in #136824, relating types never // introduces a constructor which could cause the recursion to be guarded. - GoalSource::TypeRelating => PathKind::Inductive, + // + // FIXME(-Znext-solver=coinductive): For now we treat all inductive cycles as + // `Unknown`. See the comment in `fn initial_provisional_result`. + GoalSource::TypeRelating => PathKind::Unknown, // These goal sources are likely unproductive and can be changed to // `PathKind::Inductive`. Keeping them as unknown until we're confident // about this and have an example where it is necessary. diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs index e147a139a65e1..ecd175d694d7d 100644 --- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs +++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs @@ -1,9 +1,9 @@ use std::convert::Infallible; use std::marker::PhantomData; +use rustc_type_ir::Interner; use rustc_type_ir::search_graph::{self, PathKind}; use rustc_type_ir::solve::{AccessedOpaques, Certainty, NoSolution, QueryResult, RerunResultExt}; -use rustc_type_ir::{Interner, MayBeErased, TypingMode}; use crate::canonical::response_no_constraints_raw; use crate::delegate::SolverDelegate; @@ -52,29 +52,21 @@ where PathKind::Unknown | PathKind::ForcedAmbiguity => { response_no_constraints(cx, input, Certainty::overflow(false)) } - // Even though we know these cycles to be unproductive, we still return - // overflow during coherence. This is both as we are not 100% confident in - // the implementation yet and any incorrect errors would be unsound there. + // Even though we know some cycles to be unproductive, we still treat them + // as unknown for now. This is both as we are not 100% confident in the + // implementation yet and any incorrect errors would be unsound there. + // // The affected cases are also fairly artificial and not necessarily desirable // so keeping this as ambiguity is fine for now. // - // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an - // example where this would matter. We likely should change these cycles to `NoSolution` - // even in coherence once this is a bit more settled. - PathKind::Inductive => match input.typing_mode.0 { - TypingMode::Coherence => { - response_no_constraints(cx, input, Certainty::overflow(false)) - } - TypingMode::Typeck { .. } - | TypingMode::PostTypeckUntilBorrowck { .. } - | TypingMode::Reflection - | TypingMode::PostBorrowck { .. } - | TypingMode::PostAnalysis - | TypingMode::Codegen - | TypingMode::ErasedNotCoherence(MayBeErased) => { - (Err(NoSolution), AccessedOpaques::default()) - } - }, + // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` and + // `tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs` + // for examples where this would matter. + // + // FIXME(-Znext-solver=coinductive): Long term, we probably do want to + // return `NoSolution` here. This should happen separately from the + // stabilization of the new solver. + PathKind::Inductive => unreachable!(), } } diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs index f449e02baadb8..8b0b92b8a7842 100644 --- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs +++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.rs @@ -10,7 +10,7 @@ fn foo<'a, T>() where T: Proj<'a, Assoc = fn(::Assoc)>, (): Trait<>::Assoc>, - //~^ ERROR the trait bound `(): Trait fn(>::Assoc))>` is not satisfied + //~^ ERROR overflow evaluating the requirement `(): Trait<>::Assoc>` { } diff --git a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr index 5e8e131addd28..9d1c8c4a10d02 100644 --- a/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr +++ b/tests/ui/assumptions_on_binders/placeholder-assumptions-issue-157840.stderr @@ -1,14 +1,9 @@ -error[E0277]: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied +error[E0275]: overflow evaluating the requirement `(): Trait<>::Assoc>` --> $DIR/placeholder-assumptions-issue-157840.rs:12:9 | LL | (): Trait<>::Assoc>, - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait fn(>::Assoc))>` is not implemented for `()` - | -help: consider extending the `where` clause, but there might be an alternative better way to express this requirement - | -LL | (): Trait<>::Assoc>, (): Trait fn(>::Assoc))> - | +++++++++++++++++++++++++++++++++++++++++++++++++ + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ error: aborting due to 1 previous error -For more information about this error, try `rustc --explain E0277`. +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr new file mode 100644 index 0000000000000..2c9694cdd419a --- /dev/null +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.current.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `for<'b> T: Proj<'b>` + --> $DIR/find-param-recursion-issue-152716.rs:15:1 + | +LL | / fn foo() +LL | | +LL | | where +LL | | T: for<'a> Proj<'a, Assoc = for<'b> fn(>::Assoc)>, +LL | | (): Trait<>::Assoc> + | |__________________________________________^ + | + = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`find_param_recursion_issue_152716`) + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr new file mode 100644 index 0000000000000..c722813ddd663 --- /dev/null +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.next.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `(): Trait<>::Assoc>` + --> $DIR/find-param-recursion-issue-152716.rs:19:9 + | +LL | (): Trait<>::Assoc> + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs index 4d088073c3ba6..fb1ac0d8d0298 100644 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs +++ b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.rs @@ -1,4 +1,6 @@ -//@ compile-flags: -Znext-solver +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver // Regression test for . // @@ -11,10 +13,11 @@ trait Proj<'a> { type Assoc; } fn foo() +//[current]~^ ERROR: overflow evaluating the requirement `for<'b> T: Proj<'b>` where T: for<'a> Proj<'a, Assoc = for<'b> fn(>::Assoc)>, (): Trait<>::Assoc> - //~^ ERROR: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied + //[next]~^ ERROR: overflow evaluating the requirement `(): Trait<>::Assoc>` { } diff --git a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr b/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr deleted file mode 100644 index 1408890184a90..0000000000000 --- a/tests/ui/traits/next-solver/find-param-recursion-issue-152716.stderr +++ /dev/null @@ -1,14 +0,0 @@ -error[E0277]: the trait bound `(): Trait fn(>::Assoc))>` is not satisfied - --> $DIR/find-param-recursion-issue-152716.rs:16:9 - | -LL | (): Trait<>::Assoc> - | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait fn(>::Assoc))>` is not implemented for `()` - | -help: consider extending the `where` clause, but there might be an alternative better way to express this requirement - | -LL | (): Trait<>::Assoc>, (): Trait fn(>::Assoc))> - | +++++++++++++++++++++++++++++++++++++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr new file mode 100644 index 0000000000000..230871107a6cf --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.current.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Assoc1 == _` + --> $DIR/recursive-self-normalization-2.rs:16:1 + | +LL | fn test::Assoc2> + Foo2::Assoc1>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr new file mode 100644 index 0000000000000..ea8b5cd51a309 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.next.stderr @@ -0,0 +1,15 @@ +error[E0275]: overflow evaluating the requirement `::Assoc1 == _` + --> $DIR/recursive-self-normalization-2.rs:16:1 + | +LL | fn test::Assoc2> + Foo2::Assoc1>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error[E0275]: overflow evaluating the requirement `::Assoc2 == _` + --> $DIR/recursive-self-normalization-2.rs:16:1 + | +LL | fn test::Assoc2> + Foo2::Assoc1>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 2 previous errors + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs index 8dc27c0da605a..0e08a6b4d7e03 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs @@ -1,4 +1,6 @@ -//@ compile-flags: -Znext-solver +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver trait Foo1 { type Assoc1; @@ -12,8 +14,9 @@ trait Bar {} fn needs_bar() {} fn test::Assoc2> + Foo2::Assoc1>>() { + //~^ ERROR overflow evaluating the requirement `::Assoc1 == _` + //[next]~| ERROR overflow evaluating the requirement `::Assoc2 == _` needs_bar::(); - //~^ ERROR: the trait bound `::Assoc1: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr deleted file mode 100644 index 6f5111a6193ca..0000000000000 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: the trait bound `::Assoc1: Bar` is not satisfied - --> $DIR/recursive-self-normalization-2.rs:15:17 - | -LL | needs_bar::(); - | ^^^^^^^^^ the trait `Bar` is not implemented for `::Assoc1` - | -note: required by a bound in `needs_bar` - --> $DIR/recursive-self-normalization-2.rs:12:17 - | -LL | fn needs_bar() {} - | ^^^ required by this bound in `needs_bar` -help: consider further restricting the associated type - | -LL | fn test::Assoc2> + Foo2::Assoc1>>() where ::Assoc1: Bar { - | ++++++++++++++++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr new file mode 100644 index 0000000000000..4b9be86b9e5a5 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.current.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/recursive-self-normalization-simple.rs:15:1 + | +LL | fn test::Assoc>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr new file mode 100644 index 0000000000000..4b9be86b9e5a5 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.next.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/recursive-self-normalization-simple.rs:15:1 + | +LL | fn test::Assoc>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs new file mode 100644 index 0000000000000..b511dc4a732e3 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-simple.rs @@ -0,0 +1,19 @@ +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver + +// A variant of `recursive-self-normalization.rs` which passes if +// we treat inductive cycles as `NoSolution` in the trait solver. + +trait Foo { + type Assoc; +} + +trait Bar {} +fn needs_bar() {} + +fn test::Assoc>>() { + //~^ ERROR overflow evaluating the requirement `::Assoc == _` +} + +fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr new file mode 100644 index 0000000000000..6569be7347911 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.current.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/recursive-self-normalization.rs:12:1 + | +LL | fn test::Assoc>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr new file mode 100644 index 0000000000000..6569be7347911 --- /dev/null +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.next.stderr @@ -0,0 +1,9 @@ +error[E0275]: overflow evaluating the requirement `::Assoc == _` + --> $DIR/recursive-self-normalization.rs:12:1 + | +LL | fn test::Assoc>>() { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0275`. diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs index f441ac499f99c..a25d028bd1b52 100644 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs +++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs @@ -1,4 +1,6 @@ -//@ compile-flags: -Znext-solver +//@ revisions: current next +//@ ignore-compare-mode-next-solver (explicit revisions) +//@[next] compile-flags: -Znext-solver trait Foo { type Assoc; @@ -8,8 +10,8 @@ trait Bar {} fn needs_bar() {} fn test::Assoc>>() { + //~^ ERROR overflow evaluating the requirement `::Assoc == _` needs_bar::(); - //~^ ERROR the trait bound `::Assoc: Bar` is not satisfied } fn main() {} diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr deleted file mode 100644 index c551823468741..0000000000000 --- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr +++ /dev/null @@ -1,19 +0,0 @@ -error[E0277]: the trait bound `::Assoc: Bar` is not satisfied - --> $DIR/recursive-self-normalization.rs:11:17 - | -LL | needs_bar::(); - | ^^^^^^^^ the trait `Bar` is not implemented for `::Assoc` - | -note: required by a bound in `needs_bar` - --> $DIR/recursive-self-normalization.rs:8:17 - | -LL | fn needs_bar() {} - | ^^^ required by this bound in `needs_bar` -help: consider further restricting the associated type - | -LL | fn test::Assoc>>() where ::Assoc: Bar { - | ++++++++++++++++++++++++++++ - -error: aborting due to 1 previous error - -For more information about this error, try `rustc --explain E0277`. From e83bfcabca99e7d18ce0a57a6ac8f57345596d65 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:39 +0100 Subject: [PATCH 0620/1309] Move `Const` from `rustc_middle` to `rustc_type_ir` --- compiler/rustc_middle/src/ty/codec.rs | 13 - compiler/rustc_middle/src/ty/consts.rs | 246 ++---------------- compiler/rustc_middle/src/ty/context.rs | 26 +- .../src/ty/context/impl_interner.rs | 14 +- compiler/rustc_middle/src/ty/mod.rs | 3 +- compiler/rustc_middle/src/ty/print/pretty.rs | 4 +- compiler/rustc_middle/src/ty/relate.rs | 10 - .../rustc_middle/src/ty/structural_impls.rs | 88 +------ compiler/rustc_type_ir/src/inherent.rs | 70 ++--- compiler/rustc_type_ir/src/intern/mod.rs | 4 +- compiler/rustc_type_ir/src/interner.rs | 20 +- compiler/rustc_type_ir/src/ir_print.rs | 13 +- compiler/rustc_type_ir/src/serialize.rs | 20 +- compiler/rustc_type_ir/src/sty/consts.rs | 243 +++++++++++++++++ compiler/rustc_type_ir/src/sty/mod.rs | 3 + compiler/rustc_type_ir/src/ty_info.rs | 2 +- 16 files changed, 365 insertions(+), 414 deletions(-) create mode 100644 compiler/rustc_type_ir/src/sty/consts.rs diff --git a/compiler/rustc_middle/src/ty/codec.rs b/compiler/rustc_middle/src/ty/codec.rs index 9d4899d6fd450..81462e214b20f 100644 --- a/compiler/rustc_middle/src/ty/codec.rs +++ b/compiler/rustc_middle/src/ty/codec.rs @@ -142,12 +142,6 @@ impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Clause<'tcx> { } } -impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Const<'tcx> { - fn encode(&self, e: &mut E) { - self.0.0.encode(e); - } -} - impl<'tcx, E: TyEncoder<'tcx>> Encodable for ty::Pattern<'tcx> { fn encode(&self, e: &mut E) { self.0.0.encode(e); @@ -292,13 +286,6 @@ impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::ParamEnv<'tcx> { } } -impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Const<'tcx> { - fn decode(decoder: &mut D) -> Self { - let kind: ty::ConstKind<'tcx> = Decodable::decode(decoder); - decoder.interner().mk_ct_from_kind(kind) - } -} - impl<'tcx, D: TyDecoder<'tcx>> Decodable for ty::Pattern<'tcx> { fn decode(decoder: &mut D) -> Self { decoder.interner().mk_pat(Decodable::decode(decoder)) diff --git a/compiler/rustc_middle/src/ty/consts.rs b/compiler/rustc_middle/src/ty/consts.rs index 9e9f8d5df45de..cbe7b6d732c0f 100644 --- a/compiler/rustc_middle/src/ty/consts.rs +++ b/compiler/rustc_middle/src/ty/consts.rs @@ -1,10 +1,7 @@ -use std::borrow::Cow; - -use rustc_data_structures::intern::Interned; -use rustc_macros::StableHash; -use rustc_span::{Span, bug}; +use rustc_macros::extension; +use rustc_span::bug; use rustc_type_ir::walk::TypeWalker; -use rustc_type_ir::{self as ir, TypeFlags, WithCachedTypeInfo}; +use rustc_type_ir::{self as ir}; use crate::mir::interpret::Scalar; use crate::ty::{self, Ty, TyCtxt}; @@ -17,204 +14,21 @@ mod valtree; pub use int::*; pub use kind::*; pub use lit::*; -use rustc_span::{DUMMY_SP, ErrorGuaranteed}; pub use valtree::*; pub type ConstKind<'tcx> = ir::ConstKind>; pub type AliasConst<'tcx> = ir::AliasConst>; pub type AliasConstKind<'tcx> = ir::AliasConstKind>; +pub type Const<'tcx> = ir::Const>; #[cfg(target_pointer_width = "64")] rustc_data_structures::static_assert_size!(ConstKind<'_>, 32); -#[derive(Copy, Clone, PartialEq, Eq, Hash, StableHash)] -#[rustc_pass_by_value] -pub struct Const<'tcx>(pub(super) Interned<'tcx, WithCachedTypeInfo>>); - -impl<'tcx> rustc_type_ir::inherent::IntoKind for Const<'tcx> { - type Kind = ConstKind<'tcx>; - - fn kind(self) -> ConstKind<'tcx> { - self.kind() - } -} - -impl<'tcx> rustc_type_ir::Flags for Const<'tcx> { - fn flags(&self) -> TypeFlags { - self.0.flags - } - - fn outer_exclusive_binder(&self) -> rustc_type_ir::DebruijnIndex { - self.0.outer_exclusive_binder - } -} - -impl<'tcx> Const<'tcx> { - #[inline] - pub fn kind(self) -> ConstKind<'tcx> { - let a: &ConstKind<'tcx> = self.0.0; - *a - } - - #[inline] - pub fn new(tcx: TyCtxt<'tcx>, kind: ty::ConstKind<'tcx>) -> Const<'tcx> { - tcx.mk_ct_from_kind(kind) - } - - #[inline] - pub fn new_param(tcx: TyCtxt<'tcx>, param: ty::ParamConst) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Param(param)) - } - - #[inline] - pub fn new_var(tcx: TyCtxt<'tcx>, infer: ty::ConstVid) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Var(infer))) - } - - #[inline] - pub fn new_fresh(tcx: TyCtxt<'tcx>, fresh: u32) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Infer(ty::InferConst::Fresh(fresh))) - } - - #[inline] - pub fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Infer(infer)) - } - - #[inline] - pub fn new_bound( - tcx: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst<'tcx>, - ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_const)) - } - - #[inline] - pub fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: ty::BoundVar) -> Const<'tcx> { - Const::new( - tcx, - ty::ConstKind::Bound(ty::BoundVarIndexKind::Canonical, ty::BoundConst::new(var)), - ) - } - - #[inline] - pub fn new_placeholder( - tcx: TyCtxt<'tcx>, - placeholder: ty::PlaceholderConst<'tcx>, - ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Placeholder(placeholder)) - } - - #[inline] - pub fn new_alias( - tcx: TyCtxt<'tcx>, - is_rigid: ty::IsRigid, - alias_const: ty::AliasConst<'tcx>, - ) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Alias(is_rigid, alias_const)) - } - - #[inline] - pub fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree })) - } - - #[inline] - pub fn new_expr(tcx: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Expr(expr)) - } - - #[inline] - pub fn new_error(tcx: TyCtxt<'tcx>, e: ty::ErrorGuaranteed) -> Const<'tcx> { - Const::new(tcx, ty::ConstKind::Error(e)) - } - - /// Like [Ty::new_error] but for constants. - #[track_caller] - pub fn new_misc_error(tcx: TyCtxt<'tcx>) -> Const<'tcx> { - Const::new_error_with_message( - tcx, - DUMMY_SP, - "ty::ConstKind::Error constructed but no error reported", - ) - } - - /// Like [Ty::new_error_with_message] but for constants. - #[track_caller] - pub fn new_error_with_message( - tcx: TyCtxt<'tcx>, - span: Span, - msg: impl Into>, - ) -> Const<'tcx> { - let reported = tcx.dcx().span_delayed_bug(span, msg); - Const::new_error(tcx, reported) - } - - pub fn is_trivially_wf(self) -> bool { - match self.kind() { - ty::ConstKind::Param(_) | ty::ConstKind::Placeholder(_) | ty::ConstKind::Bound(..) => { - true - } - ty::ConstKind::Infer(_) - | ty::ConstKind::Alias(..) - | ty::ConstKind::Value(_) - | ty::ConstKind::Error(_) - | ty::ConstKind::Expr(_) => false, - } - } -} - -impl<'tcx> rustc_type_ir::inherent::Const> for Const<'tcx> { - fn new_infer(tcx: TyCtxt<'tcx>, infer: ty::InferConst) -> Self { - Const::new_infer(tcx, infer) - } - - fn new_var(tcx: TyCtxt<'tcx>, vid: ty::ConstVid) -> Self { - Const::new_var(tcx, vid) - } - - fn new_bound( - interner: TyCtxt<'tcx>, - debruijn: ty::DebruijnIndex, - bound_const: ty::BoundConst<'tcx>, - ) -> Self { - Const::new_bound(interner, debruijn, bound_const) - } - - fn new_anon_bound(tcx: TyCtxt<'tcx>, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self { - Const::new_bound(tcx, debruijn, ty::BoundConst::new(var)) - } - - fn new_canonical_bound(tcx: TyCtxt<'tcx>, var: rustc_type_ir::BoundVar) -> Self { - Const::new_canonical_bound(tcx, var) - } - - fn new_placeholder(tcx: TyCtxt<'tcx>, placeholder: ty::PlaceholderConst<'tcx>) -> Self { - Const::new_placeholder(tcx, placeholder) - } - - fn new_alias( - interner: TyCtxt<'tcx>, - is_rigid: ty::IsRigid, - alias_const: ty::AliasConst<'tcx>, - ) -> Self { - Const::new_alias(interner, is_rigid, alias_const) - } - - fn new_expr(interner: TyCtxt<'tcx>, expr: ty::Expr<'tcx>) -> Self { - Const::new_expr(interner, expr) - } - - fn new_error(interner: TyCtxt<'tcx>, guar: ErrorGuaranteed) -> Self { - Const::new_error(interner, guar) - } -} - +#[extension(pub trait ConstExt<'tcx>)] impl<'tcx> Const<'tcx> { /// Creates a constant with the given integer value and interns it. #[inline] - pub fn from_bits( + fn from_bits( tcx: TyCtxt<'tcx>, bits: u128, typing_env: ty::TypingEnv<'tcx>, @@ -224,33 +38,36 @@ impl<'tcx> Const<'tcx> { .layout_of(typing_env.as_query_input(ty)) .unwrap_or_else(|e| panic!("could not compute layout for {ty:?}: {e:?}")) .size; - ty::Const::new_value( - tcx, - ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()), - ty, - ) + let valtree = + ty::ValTree::from_scalar_int(tcx, ScalarInt::try_from_uint(bits, size).unwrap()); + ty::Const::new_value(tcx, valtree, ty) } #[inline] /// Creates an interned zst constant. - pub fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { + fn zero_sized(tcx: TyCtxt<'tcx>, ty: Ty<'tcx>) -> Self { ty::Const::new_value(tcx, ty::ValTree::zst(tcx), ty) } + #[inline] + fn new_value(tcx: TyCtxt<'tcx>, valtree: ty::ValTree<'tcx>, ty: Ty<'tcx>) -> Const<'tcx> { + Const::new(tcx, ty::ConstKind::Value(ty::Value { ty, valtree })) + } + #[inline] /// Creates an interned bool constant. - pub fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { + fn from_bool(tcx: TyCtxt<'tcx>, v: bool) -> Self { Self::from_bits(tcx, v as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.bool) } #[inline] /// Creates an interned usize constant. - pub fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { + fn from_target_usize(tcx: TyCtxt<'tcx>, n: u64) -> Self { Self::from_bits(tcx, n as u128, ty::TypingEnv::fully_monomorphized(), tcx.types.usize) } /// Panics if `self.kind != ty::ConstKind::Value`. - pub fn to_value(self) -> ty::Value<'tcx> { + fn to_value(self) -> ty::Value<'tcx> { match self.kind() { ty::ConstKind::Value(cv) => cv, _ => bug!("expected ConstKind::Value, got {:?}", self.kind()), @@ -260,7 +77,7 @@ impl<'tcx> Const<'tcx> { /// Attempts to convert to a value. /// /// Note that this does not normalize the constant. - pub fn try_to_value(self) -> Option> { + fn try_to_value(self) -> Option> { match self.kind() { ty::ConstKind::Value(cv) => Some(cv), _ => None, @@ -272,7 +89,7 @@ impl<'tcx> Const<'tcx> { /// /// Note that this does not normalize the constant. #[inline] - pub fn to_leaf(self) -> ScalarInt { + fn to_leaf(self) -> ScalarInt { self.to_value().to_leaf() } @@ -281,28 +98,28 @@ impl<'tcx> Const<'tcx> { /// /// Note that this does not normalize the constant. #[inline] - pub fn to_branch(self) -> &'tcx [ty::Const<'tcx>] { + fn to_branch(self) -> &'tcx [ty::Const<'tcx>] { self.to_value().to_branch() } /// Attempts to convert to a `ValTreeKind::Leaf` value. /// /// Note that this does not normalize the constant. - pub fn try_to_leaf(self) -> Option { + fn try_to_leaf(self) -> Option { self.try_to_value()?.try_to_leaf() } /// Attempts to convert to a `ValTreeKind::Leaf` value. /// /// Note that this does not normalize the constant. - pub fn try_to_scalar(self) -> Option { + fn try_to_scalar(self) -> Option { self.try_to_leaf().map(Scalar::Int) } /// Attempts to convert to a `ValTreeKind::Branch` value. /// /// Note that this does not normalize the constant. - pub fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> { + fn try_to_branch(self) -> Option<&'tcx [ty::Const<'tcx>]> { self.try_to_value()?.try_to_branch() } @@ -311,21 +128,10 @@ impl<'tcx> Const<'tcx> { /// /// Note that this does not evaluate the constant. #[inline] - pub fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { + fn try_to_target_usize(self, tcx: TyCtxt<'tcx>) -> Option { self.try_to_value()?.try_to_target_usize(tcx) } - pub fn is_ct_infer(self) -> bool { - matches!(self.kind(), ty::ConstKind::Infer(_)) - } - - pub fn ct_vid(self) -> Option { - match self.kind() { - ConstKind::Infer(ty::InferConst::Var(vid)) => Some(vid), - _ => None, - } - } - /// Iterator that walks `self` and any types reachable from /// `self`, in depth-first order. Note that just walks the types /// that appear in `self`, it does not descend into the fields of @@ -336,7 +142,7 @@ impl<'tcx> Const<'tcx> { /// Foo> => { Foo>, Bar, isize } /// [isize] => { [isize], isize } /// ``` - pub fn walk(self) -> TypeWalker> { + fn walk(self) -> TypeWalker> { TypeWalker::new(self.into()) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index bd9a5e80b1855..8b8ec7c98182f 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -69,11 +69,11 @@ use crate::traits::solve::{ }; use crate::ty::predicate::ExistentialPredicateStableCmpExt as _; use crate::ty::{ - self, AdtDef, AdtDefData, AdtKind, Binder, Clause, ClausePolarity, Clauses, Const, FnSigKind, - GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, ListWithCachedTypeInfo, - ParamConst, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, Predicate, - PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyVid, ValTree, - ValTreeKind, Visibility, + self, AdtDef, AdtDefData, AdtKind, Binder, Clause, ClausePolarity, Clauses, Const, ConstKind, + FnSigKind, GenericArg, GenericArgs, GenericArgsRef, GenericParamDefKind, List, + ListWithCachedTypeInfo, ParamConst, Pattern, PatternKind, PolyExistentialPredicate, PolyFnSig, + Predicate, PredicateKind, Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, + TyVid, ValTree, ValTreeKind, Visibility, }; impl<'tcx> rustc_type_ir::inherent::DefId> for DefId { @@ -1711,7 +1711,6 @@ macro_rules! nop_list_lift { } nop_lift! { type_; Ty<'a> => Ty<'tcx> } -nop_lift! { const_; Const<'a> => Const<'tcx> } nop_lift! { pat; Pattern<'a> => Pattern<'tcx> } nop_lift! { const_allocation; ConstAllocation<'a> => ConstAllocation<'tcx> } nop_lift! { predicate; Predicate<'a> => Predicate<'tcx> } @@ -1731,6 +1730,21 @@ impl<'a, 'tcx> Lift> for Interned<'a, RegionKind<'a>> { } } +// `rustc_type_ir::Const` is only the generic wrapper; lifting it delegates +// to `I::InternedConstKind`, so the concrete interned const representation +// must itself implement `Lift`. +impl<'a, 'tcx> Lift> for Interned<'a, WithCachedTypeInfo>> { + type Lifted = Interned<'tcx, WithCachedTypeInfo>>; + + #[track_caller] + fn lift_to_interner(self, tcx: TyCtxt<'tcx>) -> Self::Lifted { + assert!(tcx.interners.const_.contains_pointer_to(&InternedInSet(&*self.0))); + // SAFETY: we just checked that `self` is interned in this `TyCtxt`, so + // its pointee is valid for the entire lifetime of the target `TyCtxt`. + unsafe { mem::transmute(self) } + } +} + nop_list_lift! { type_lists; Ty<'a> => Ty<'tcx> } nop_list_lift! { clauses: ListWithCachedTypeInfo; Clause<'a> => Clause<'tcx> } nop_list_lift! { diff --git a/compiler/rustc_middle/src/ty/context/impl_interner.rs b/compiler/rustc_middle/src/ty/context/impl_interner.rs index 6e838c4454c4c..f13797b48fcbf 100644 --- a/compiler/rustc_middle/src/ty/context/impl_interner.rs +++ b/compiler/rustc_middle/src/ty/context/impl_interner.rs @@ -13,7 +13,7 @@ use rustc_type_ir::lang_items::{SolverAdtLangItem, SolverProjectionLangItem, Sol use rustc_type_ir::solve::CanonicalInputData; use rustc_type_ir::{ BoundVar, CollectAndApply, DebruijnIndex, Interner, RegionVid, TypeFoldable, Unnormalized, - VisitorResult, search_graph, try_visit, + VisitorResult, WithCachedTypeInfo, search_graph, try_visit, }; use crate::dep_graph::{DepKind, DepNodeIndex}; @@ -109,8 +109,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type Pat = Pattern<'tcx>; type PatList = &'tcx List>; type Safety = hir::Safety; - type Const = ty::Const<'tcx>; - type Consts = &'tcx List; + type Consts = &'tcx List>; type ParamConst = ty::ParamConst; type ValueConst = ty::Value<'tcx>; @@ -118,6 +117,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { type ValTree = ty::ValTree<'tcx>; type ScalarInt = ty::ScalarInt; type InternedRegionKind = Interned<'tcx, ty::RegionKind<'tcx>>; + type InternedConstKind = Interned<'tcx, WithCachedTypeInfo>>; type EarlyParamRegion = ty::EarlyParamRegion; type LateParamRegionKind = ty::LateParamRegionKind; @@ -292,6 +292,10 @@ impl<'tcx> Interner for TyCtxt<'tcx> { self.mk_type_list_from_iter(args) } + fn mk_ct_from_kind(self, kind: ty::ConstKind<'tcx>) -> ty::Const<'tcx> { + self.mk_ct_from_kind(kind) + } + fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId { self.parent(def_id) } @@ -733,9 +737,7 @@ impl<'tcx> Interner for TyCtxt<'tcx> { } } -impl<'tcx, T: std::fmt::Debug + Clone + Copy> rustc_type_ir::intern::Interned> - for Interned<'tcx, T> -{ +impl<'tcx, T: Clone + Copy> rustc_type_ir::intern::Interned> for Interned<'tcx, T> { type Value = T; fn get(self) -> T { *self.0 diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 94345380a544e..c7de3afb7cd3c 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -124,6 +124,8 @@ pub mod abstract_const; pub mod adjustment; pub mod cast; pub mod codec; +// FIXME(#159654): This should get deleted soon +pub mod consts; pub mod error; pub mod fast_reject; pub mod inhabitedness; @@ -143,7 +145,6 @@ pub mod vtable; mod adt; mod assoc; mod closure; -mod consts; mod context; mod diagnostics; mod elaborate_impl; diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs index ba4a59daad01d..3ba7ea6d43794 100644 --- a/compiler/rustc_middle/src/ty/print/pretty.rs +++ b/compiler/rustc_middle/src/ty/print/pretty.rs @@ -24,6 +24,7 @@ use smallvec::SmallVec; use super::*; use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar}; use crate::query::{IntoQueryKey, Providers}; +use crate::ty::consts::ConstExt; use crate::ty::{ ConstInt, Expr, GenericArgKind, ParamConst, ScalarInt, Term, TermKind, TraitClause, TypeFoldable, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, @@ -3140,8 +3141,7 @@ macro_rules! define_print_and_forward_display { forward_display_to_print! { Ty<'tcx>, - &'tcx ty::List>, - ty::Const<'tcx> + &'tcx ty::List> } define_print! { diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs index abbfd0f279a93..477e5133cc358 100644 --- a/compiler/rustc_middle/src/ty/relate.rs +++ b/compiler/rustc_middle/src/ty/relate.rs @@ -98,16 +98,6 @@ impl<'tcx> Relate> for ty::GenericArgsRef<'tcx> { } } -impl<'tcx> Relate> for ty::Const<'tcx> { - fn relate>>( - relation: &mut R, - a: ty::Const<'tcx>, - b: ty::Const<'tcx>, - ) -> RelateResult<'tcx, ty::Const<'tcx>> { - relation.consts(a, b) - } -} - impl<'tcx> Relate> for ty::Expr<'tcx> { fn relate>>( relation: &mut R, diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs index 0ea7e403ee111..02107fee370cb 100644 --- a/compiler/rustc_middle/src/ty/structural_impls.rs +++ b/compiler/rustc_middle/src/ty/structural_impls.rs @@ -9,7 +9,7 @@ use rustc_abi::TyAndLayout; use rustc_hir::def::Namespace; use rustc_hir::def_id::LocalDefId; use rustc_span::Spanned; -use rustc_type_ir::{ConstKind, PredicateProxy, TypeFolder, Upcast, VisitorResult, try_visit}; +use rustc_type_ir::{PredicateProxy, TypeFolder, Upcast, VisitorResult, try_visit}; use super::{GenericArg, GenericArgKind, Pattern}; use crate::mir::PlaceElem; @@ -141,18 +141,6 @@ impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> { } } -impl<'tcx> fmt::Debug for ty::Const<'tcx> { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { - // If this is a value, we spend some effort to make it look nice. - if let ConstKind::Value(cv) = self.kind() { - write!(f, "{}", cv) - } else { - // Fall back to something verbose. - write!(f, "{:?}", self.kind()) - } - } -} - impl<'tcx> fmt::Debug for GenericArg<'tcx> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { match self.kind() { @@ -651,80 +639,6 @@ impl<'tcx> TypeSuperFoldable> for ty::Clauses<'tcx> { } } -impl<'tcx> TypeFoldable> for ty::Const<'tcx> { - fn try_fold_with>>( - self, - folder: &mut F, - ) -> Result { - folder.try_fold_const(self) - } - - fn fold_with>>(self, folder: &mut F) -> Self { - folder.fold_const(self) - } -} - -impl<'tcx> TypeVisitable> for ty::Const<'tcx> { - fn visit_with>>(&self, visitor: &mut V) -> V::Result { - visitor.visit_const(*self) - } -} - -impl<'tcx> TypeSuperFoldable> for ty::Const<'tcx> { - fn try_super_fold_with>>( - self, - folder: &mut F, - ) -> Result { - let kind = match self.kind() { - ConstKind::Alias(is_rigid, alias_const) => { - ConstKind::Alias(is_rigid, alias_const.try_fold_with(folder)?) - } - ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), - ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), - - ConstKind::Param(_) - | ConstKind::Infer(_) - | ConstKind::Bound(..) - | ConstKind::Placeholder(_) - | ConstKind::Error(_) => return Ok(self), - }; - if kind != self.kind() { Ok(folder.cx().mk_ct_from_kind(kind)) } else { Ok(self) } - } - - fn super_fold_with>>(self, folder: &mut F) -> Self { - let kind = match self.kind() { - ConstKind::Alias(is_rigid, alias_const) => { - ConstKind::Alias(is_rigid, alias_const.fold_with(folder)) - } - ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)), - ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)), - - ConstKind::Param(_) - | ConstKind::Infer(_) - | ConstKind::Bound(..) - | ConstKind::Placeholder(_) - | ConstKind::Error(_) => return self, - }; - if kind != self.kind() { folder.cx().mk_ct_from_kind(kind) } else { self } - } -} - -impl<'tcx> TypeSuperVisitable> for ty::Const<'tcx> { - fn super_visit_with>>(&self, visitor: &mut V) -> V::Result { - match self.kind() { - ConstKind::Alias(_, alias_const) => alias_const.visit_with(visitor), - ConstKind::Value(v) => v.visit_with(visitor), - ConstKind::Expr(e) => e.visit_with(visitor), - ConstKind::Error(e) => e.visit_with(visitor), - - ConstKind::Param(_) - | ConstKind::Infer(_) - | ConstKind::Bound(..) - | ConstKind::Placeholder(_) => V::Result::output(), - } - } -} - impl<'tcx> TypeVisitable> for ty::ValTree<'tcx> { fn visit_with>>(&self, visitor: &mut V) -> V::Result { let inner: &ty::ValTreeKind> = &*self; diff --git a/compiler/rustc_type_ir/src/inherent.rs b/compiler/rustc_type_ir/src/inherent.rs index bf90ef707c051..26d094817ba09 100644 --- a/compiler/rustc_type_ir/src/inherent.rs +++ b/compiler/rustc_type_ir/src/inherent.rs @@ -14,7 +14,8 @@ use crate::relate::Relate; use crate::solve::{AdtDestructorKind, SizedTraitKind}; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable}; use crate::{ - self as ty, ClauseKind, CollectAndApply, FieldInfo, Interner, PredicateKind, Region, UpcastFrom, + self as ty, ClauseKind, CollectAndApply, Const, FieldInfo, Interner, PredicateKind, Region, + UpcastFrom, }; #[rust_analyzer::prefer_underscore_import] @@ -111,7 +112,7 @@ pub trait Ty>: fn new_ref(interner: I, region: Region, ty: Self, mutbl: Mutability) -> Self; - fn new_array_with_const_len(interner: I, ty: Self, len: I::Const) -> Self; + fn new_array_with_const_len(interner: I, ty: Self, len: Const) -> Self; fn new_slice(interner: I, ty: Self) -> Self; @@ -228,50 +229,6 @@ pub trait Safety>: Copy + Debug + Hash + Eq { fn prefix_str(self) -> &'static str; } -pub trait Const>: - Copy - + Debug - + Hash - + Eq - + Into - + Into - + IntoKind> - + TypeSuperVisitable - + TypeSuperFoldable - + Relate - + Flags -{ - fn new_infer(interner: I, var: ty::InferConst) -> Self; - - fn new_var(interner: I, var: ty::ConstVid) -> Self; - - fn new_bound(interner: I, debruijn: ty::DebruijnIndex, bound_const: ty::BoundConst) -> Self; - - fn new_anon_bound(interner: I, debruijn: ty::DebruijnIndex, var: ty::BoundVar) -> Self; - - fn new_canonical_bound(interner: I, var: ty::BoundVar) -> Self; - - fn new_placeholder(interner: I, param: ty::PlaceholderConst) -> Self; - - fn new_alias(interner: I, is_rigid: ty::IsRigid, alias_const: ty::AliasConst) -> Self; - - fn new_expr(interner: I, expr: I::ExprConst) -> Self; - - fn new_error(interner: I, guar: I::ErrorGuaranteed) -> Self; - - fn new_error_with_message(interner: I, msg: impl ToString) -> Self { - Self::new_error(interner, interner.delay_bug(msg)) - } - - fn is_ct_var(self) -> bool { - matches!(self.kind(), ty::ConstKind::Infer(ty::InferConst::Var(_))) - } - - fn is_ct_error(self) -> bool { - matches!(self.kind(), ty::ConstKind::Error(_)) - } -} - #[rust_analyzer::prefer_underscore_import] pub trait ValueConst>: Copy + Debug + Hash + Eq { fn ty(self) -> I::Ty; @@ -300,7 +257,7 @@ pub trait GenericArg>: + Relate + From + From> - + From + + From> + From { fn as_term(&self) -> Option { @@ -319,11 +276,11 @@ pub trait GenericArg>: self.as_type().expect("expected a type") } - fn as_const(&self) -> Option { + fn as_const(&self) -> Option> { if let ty::GenericArgKind::Const(c) = self.kind() { Some(c) } else { None } } - fn expect_const(&self) -> I::Const { + fn expect_const(&self) -> Const { self.as_const().expect("expected a const") } @@ -346,7 +303,14 @@ pub trait GenericArg>: #[rust_analyzer::prefer_underscore_import] pub trait Term>: - Copy + Debug + Hash + Eq + IntoKind> + TypeFoldable + Relate + Copy + + Debug + + Hash + + Eq + + IntoKind> + + TypeFoldable + + Relate + + From> { fn as_type(&self) -> Option { if let ty::TermKind::Ty(ty) = self.kind() { Some(ty) } else { None } @@ -356,11 +320,11 @@ pub trait Term>: self.as_type().expect("expected a type, but found a const") } - fn as_const(&self) -> Option { + fn as_const(&self) -> Option> { if let ty::TermKind::Const(c) = self.kind() { Some(c) } else { None } } - fn expect_const(&self) -> I::Const { + fn expect_const(&self) -> Const { self.as_const().expect("expected a const, but found a type") } @@ -420,7 +384,7 @@ pub trait GenericArgs>: fn region_at(self, i: usize) -> Region; - fn const_at(self, i: usize) -> I::Const; + fn const_at(self, i: usize) -> Const; fn identity_for_item(interner: I, def_id: I::DefId) -> I::GenericArgs; diff --git a/compiler/rustc_type_ir/src/intern/mod.rs b/compiler/rustc_type_ir/src/intern/mod.rs index a4cdd85fe175b..88634b3829fe2 100644 --- a/compiler/rustc_type_ir/src/intern/mod.rs +++ b/compiler/rustc_type_ir/src/intern/mod.rs @@ -1,8 +1,6 @@ use std::hash::Hash; -use crate::fmt::Debug; - -pub trait Interned: Copy + Debug + Hash + Eq + PartialEq { +pub trait Interned: Copy + Hash + Eq + PartialEq { type Value; fn get(self) -> Self::Value; } diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 0a11a82c99e76..474a4689997d7 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -1,5 +1,5 @@ use std::borrow::Borrow; -use std::fmt::Debug; +use std::fmt::{Debug, Display}; use std::hash::Hash; use std::ops::Deref; @@ -21,8 +21,8 @@ use crate::solve::{ }; use crate::visit::{Flags, TypeVisitable}; use crate::{ - self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, DebruijnIndex, - Region, RegionKind, RegionVid, TraitRef, search_graph, + self as ty, AliasTermKind, BoundRegion, BoundVar, CanonicalParamEnvCache, Const, ConstKind, + DebruijnIndex, Region, RegionKind, RegionVid, TraitRef, WithCachedTypeInfo, search_graph, }; /// The central trait in the shared abstraction layer, specifying all implementation-specific @@ -177,7 +177,7 @@ pub trait Interner: type Symbol: Symbol; // Things stored inside of tys - type ErrorGuaranteed: Copy + Debug + Hash + Eq; + type ErrorGuaranteed: Copy + Debug + Hash + Eq + TypeVisitable; type BoundExistentialPredicates: BoundExistentialPredicates; type AllocId: Copy + Debug + Hash + Eq; type Pat: Copy @@ -198,10 +198,9 @@ pub trait Interner: type Safety: Safety; // Kinds of consts - type Const: Const; - type Consts: Copy + Debug + Hash + Eq + SliceLike + Default; + type Consts: Copy + Debug + Hash + Eq + SliceLike> + Default; type ParamConst: Copy + Debug + Hash + Eq + ParamLike; - type ValueConst: ValueConst; + type ValueConst: ValueConst + TypeFoldable + Display; type ExprConst: ExprConst; type ValTree: Copy + Debug + Hash + Eq + IntoKind>; type ScalarInt: Copy + Debug + Hash + Eq; @@ -238,6 +237,7 @@ pub trait Interner: + RegionName; type InternedRegionKind: Interned>; + type InternedConstKind: Interned>>; type RegionAssumptions: Copy + Debug @@ -285,7 +285,7 @@ pub trait Interner: fn const_of_item( self, alias: ty::AliasConstKind, - ) -> Option>; + ) -> Option>>; fn anon_const_kind(self, def_id: Self::DefId) -> ty::AnonConstKind; fn def_span(self, def_id: Self::DefId) -> Self::Span; @@ -328,6 +328,8 @@ pub trait Interner: I: Iterator, T: CollectAndApply; + fn mk_ct_from_kind(self, kind: ConstKind) -> Const; + fn projection_parent(self, def_id: Self::TraitAssocTermId) -> Self::TraitId; /// This can be an impl, or a trait if this is a defaulted term. @@ -575,7 +577,6 @@ macro_rules! declare_lift_into { declare_lift_into! { BoundVarKinds, - Const, DefId, EarlyParamRegion, ErrorGuaranteed, @@ -585,6 +586,7 @@ declare_lift_into! { GenericArgs, InherentAssocConstId, InherentAssocTyId, + InternedConstKind, InternedRegionKind, OpaqueTyId, ParamEnv, diff --git a/compiler/rustc_type_ir/src/ir_print.rs b/compiler/rustc_type_ir/src/ir_print.rs index 8133862e1bf1a..1f588a64bd80d 100644 --- a/compiler/rustc_type_ir/src/ir_print.rs +++ b/compiler/rustc_type_ir/src/ir_print.rs @@ -3,8 +3,8 @@ use std::fmt; #[cfg(feature = "nightly")] use crate::{AliasConst, ClosureKind}; use crate::{ - AliasTerm, AliasTy, Binder, CoercePredicate, ExistentialProjection, ExistentialTraitRef, FnSig, - HostEffectClause, Interner, NormalizesTo, OutlivesClause, PatternKind, Placeholder, + AliasTerm, AliasTy, Binder, CoercePredicate, Const, ExistentialProjection, ExistentialTraitRef, + FnSig, HostEffectClause, Interner, NormalizesTo, OutlivesClause, PatternKind, Placeholder, ProjectionClause, Region, SubtypePredicate, TraitClause, TraitRef, }; @@ -64,6 +64,15 @@ where } } +impl fmt::Display for Const +where + I: IrPrint>, +{ + fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result { + >>::print(self, fmt) + } +} + impl fmt::Display for OutlivesClause where I: IrPrint>, diff --git a/compiler/rustc_type_ir/src/serialize.rs b/compiler/rustc_type_ir/src/serialize.rs index 835383b101136..eae1d05b7e8e7 100644 --- a/compiler/rustc_type_ir/src/serialize.rs +++ b/compiler/rustc_type_ir/src/serialize.rs @@ -2,7 +2,7 @@ use rustc_serialize::{Decodable, Decoder, Encodable, Encoder}; use crate::inherent::*; use crate::visit::TypeVisitable; -use crate::{self as ty, Interner, Region, RegionKind, UnsafeBinderInner}; +use crate::{self as ty, Const, ConstKind, Interner, Region, RegionKind, UnsafeBinderInner}; /// A decoder that can reconstruct interned type IR values by supplying the /// interner that owns the decoded data. @@ -117,3 +117,21 @@ where decoder.interner().intern_region(Decodable::decode(decoder)) } } + +impl Encodable for Const +where + ConstKind: Encodable, +{ + fn encode(&self, e: &mut E) { + self.kind().encode(e); + } +} + +impl> Decodable for Const +where + ConstKind: Decodable, +{ + fn decode(decoder: &mut D) -> Self { + Const::new(decoder.interner(), Decodable::decode(decoder)) + } +} diff --git a/compiler/rustc_type_ir/src/sty/consts.rs b/compiler/rustc_type_ir/src/sty/consts.rs new file mode 100644 index 0000000000000..da2256078efa7 --- /dev/null +++ b/compiler/rustc_type_ir/src/sty/consts.rs @@ -0,0 +1,243 @@ +use std::fmt; + +use derive_where::derive_where; +use rustc_ast_ir::visit::VisitorResult; +#[cfg(feature = "nightly")] +use rustc_macros::StableHash_NoContext; +use rustc_type_ir_macros::{GenericTypeVisitable, Lift_Generic}; + +use crate::inherent::*; +use crate::intern::Interned; +use crate::relate::{Relate, RelateResult, TypeRelation}; +use crate::{ + AliasConst, BoundConst, BoundVar, BoundVarIndexKind, ConstKind, ConstVid, DebruijnIndex, + FallibleTypeFolder, Flags, InferConst, Interner, IsRigid, PlaceholderConst, TypeFlags, + TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, +}; + +#[derive_where(Clone, Copy, PartialEq, Eq, Hash; I: Interner)] +#[cfg_attr(feature = "nightly", derive(StableHash_NoContext))] +#[cfg_attr(feature = "nightly", rustc_pass_by_value)] +#[derive(GenericTypeVisitable, Lift_Generic)] +pub struct Const(pub I::InternedConstKind); + +impl fmt::Debug for Const { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + // If this is a value, we spend some effort to make it look nice. + if let ConstKind::Value(cv) = self.kind() { + write!(f, "{}", cv) + } else { + // Fall back to something verbose. + write!(f, "{:?}", self.kind()) + } + } +} + +impl Const { + #[inline] + pub fn kind(self) -> ConstKind { + *self.0.get() + } + + #[inline] + pub fn new(interner: I, kind: ConstKind) -> Self { + interner.mk_ct_from_kind(kind) + } + + #[inline] + pub fn new_var(interner: I, infer: ConstVid) -> Self { + Self::new(interner, ConstKind::Infer(InferConst::Var(infer))) + } + + #[inline] + pub fn new_infer(interner: I, infer: InferConst) -> Self { + Self::new(interner, ConstKind::Infer(infer)) + } + + #[inline] + pub fn new_bound(interner: I, debruijn: DebruijnIndex, bound_const: BoundConst) -> Self { + Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Bound(debruijn), bound_const)) + } + + #[inline] + pub fn new_anon_bound(interner: I, debruijn: DebruijnIndex, var: BoundVar) -> Self { + Self::new_bound(interner, debruijn, BoundConst::new(var)) + } + + #[inline] + pub fn new_canonical_bound(interner: I, var: BoundVar) -> Self { + Self::new(interner, ConstKind::Bound(BoundVarIndexKind::Canonical, BoundConst::new(var))) + } + + #[inline] + pub fn new_placeholder(interner: I, placeholder: PlaceholderConst) -> Self { + Self::new(interner, ConstKind::Placeholder(placeholder)) + } + + #[inline] + pub fn new_alias(interner: I, is_rigid: IsRigid, alias_const: AliasConst) -> Self { + Self::new(interner, ConstKind::Alias(is_rigid, alias_const)) + } + + #[inline] + pub fn new_expr(interner: I, expr: I::ExprConst) -> Self { + Const::new(interner, ConstKind::Expr(expr)) + } + + #[inline] + pub fn new_error(interner: I, e: I::ErrorGuaranteed) -> Self { + Const::new(interner, ConstKind::Error(e)) + } + + #[inline] + pub fn is_ct_var(self) -> bool { + matches!(self.kind(), ConstKind::Infer(InferConst::Var(_))) + } + + #[inline] + pub fn is_ct_error(self) -> bool { + matches!(self.kind(), ConstKind::Error(_)) + } + + #[inline] + pub fn new_param(interner: I, param: I::ParamConst) -> Self { + Self::new(interner, ConstKind::Param(param)) + } + + #[inline] + pub fn new_fresh(interner: I, fresh: u32) -> Self { + Self::new(interner, ConstKind::Infer(InferConst::Fresh(fresh))) + } + + #[track_caller] + pub fn new_misc_error(interner: I) -> Self { + Self::new_error_with_message( + interner, + I::Span::dummy(), + "ty::ConstKind::Error constructed but no error reported", + ) + } + + #[track_caller] + pub fn new_error_with_message(interner: I, span: I::Span, msg: impl ToString) -> Self { + let reported = interner.span_delayed_bug(span, msg); + Self::new_error(interner, reported) + } + + pub fn is_trivially_wf(self) -> bool { + match self.kind() { + ConstKind::Param(_) | ConstKind::Placeholder(_) | ConstKind::Bound(..) => true, + ConstKind::Infer(_) + | ConstKind::Alias(..) + | ConstKind::Value(_) + | ConstKind::Error(_) + | ConstKind::Expr(_) => false, + } + } + + pub fn is_ct_infer(self) -> bool { + matches!(self.kind(), ConstKind::Infer(_)) + } + + pub fn ct_vid(self) -> Option { + match self.kind() { + ConstKind::Infer(InferConst::Var(vid)) => Some(vid), + _ => None, + } + } +} + +impl Flags for Const { + fn flags(&self) -> TypeFlags { + self.0.get().flags + } + + fn outer_exclusive_binder(&self) -> DebruijnIndex { + self.0.get().outer_exclusive_binder + } +} + +impl IntoKind for Const { + type Kind = ConstKind; + + fn kind(self) -> Self::Kind { + *self.0.get() + } +} + +impl TypeFoldable for Const { + fn try_fold_with>(self, folder: &mut F) -> Result { + folder.try_fold_const(self) + } + + fn fold_with>(self, folder: &mut F) -> Self { + folder.fold_const(self) + } +} + +impl TypeVisitable for Const { + fn visit_with>(&self, visitor: &mut V) -> V::Result { + visitor.visit_const(*self) + } +} + +impl TypeSuperFoldable for Const { + fn try_super_fold_with>( + self, + folder: &mut F, + ) -> Result { + let kind = match self.kind() { + ConstKind::Alias(is_rigid, alias_const) => { + ConstKind::Alias(is_rigid, alias_const.try_fold_with(folder)?) + } + ConstKind::Value(v) => ConstKind::Value(v.try_fold_with(folder)?), + ConstKind::Expr(e) => ConstKind::Expr(e.try_fold_with(folder)?), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) + | ConstKind::Error(_) => return Ok(self), + }; + if kind != self.kind() { Ok(Self::new(folder.cx(), kind)) } else { Ok(self) } + } + + fn super_fold_with>(self, folder: &mut F) -> Self { + let kind = match self.kind() { + ConstKind::Alias(is_rigid, alias_const) => { + ConstKind::Alias(is_rigid, alias_const.fold_with(folder)) + } + ConstKind::Value(v) => ConstKind::Value(v.fold_with(folder)), + ConstKind::Expr(e) => ConstKind::Expr(e.fold_with(folder)), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) + | ConstKind::Error(_) => return self, + }; + if kind != self.kind() { Self::new(folder.cx(), kind) } else { self } + } +} + +impl TypeSuperVisitable for Const { + fn super_visit_with>(&self, visitor: &mut V) -> V::Result { + match self.kind() { + ConstKind::Alias(_, alias_const) => alias_const.visit_with(visitor), + ConstKind::Value(v) => v.visit_with(visitor), + ConstKind::Expr(e) => e.visit_with(visitor), + ConstKind::Error(e) => e.visit_with(visitor), + + ConstKind::Param(_) + | ConstKind::Infer(_) + | ConstKind::Bound(..) + | ConstKind::Placeholder(_) => V::Result::output(), + } + } +} + +impl Relate for Const { + fn relate>(relation: &mut R, a: Self, b: Self) -> RelateResult { + relation.consts(a, b) + } +} diff --git a/compiler/rustc_type_ir/src/sty/mod.rs b/compiler/rustc_type_ir/src/sty/mod.rs index 0dfdda6af16cc..d513dd88faae6 100644 --- a/compiler/rustc_type_ir/src/sty/mod.rs +++ b/compiler/rustc_type_ir/src/sty/mod.rs @@ -1,3 +1,6 @@ +pub use consts::*; +mod consts; + use std::fmt; use derive_where::derive_where; diff --git a/compiler/rustc_type_ir/src/ty_info.rs b/compiler/rustc_type_ir/src/ty_info.rs index 7aa34183a7a38..1a0975c657e9b 100644 --- a/compiler/rustc_type_ir/src/ty_info.rs +++ b/compiler/rustc_type_ir/src/ty_info.rs @@ -11,7 +11,7 @@ use crate::{DebruijnIndex, TypeFlags}; /// A helper type that you can wrap round your own type in order to automatically /// cache the type flags and debruijn index on creation and not recompute it /// whenever the information is needed. -#[derive(Copy, Clone, GenericTypeVisitable)] +#[derive(Copy, Clone, Debug, GenericTypeVisitable)] pub struct WithCachedTypeInfo { pub internee: T, From 51e2875c331053b6764a59c4710d454a1b134a72 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:40 +0100 Subject: [PATCH 0621/1309] Remap `I::Const` -> `Const` --- .../src/canonical/canonicalizer.rs | 6 +++--- .../src/canonical/mod.rs | 6 +++--- .../rustc_next_trait_solver/src/coherence.rs | 4 ++-- .../rustc_next_trait_solver/src/delegate.rs | 6 +++--- .../rustc_next_trait_solver/src/normalize.rs | 6 +++--- .../src/placeholder.rs | 9 +++++---- .../src/solve/assembly/mod.rs | 4 ++-- .../src/solve/eval_ctxt/mod.rs | 12 +++++------ .../eval_ctxt/solver_region_constraints.rs | 6 +++--- .../rustc_next_trait_solver/src/solve/mod.rs | 10 +++++----- .../src/solve/normalizes_to.rs | 3 ++- compiler/rustc_type_ir/src/binder.rs | 12 +++++------ compiler/rustc_type_ir/src/canonical.rs | 2 +- compiler/rustc_type_ir/src/error.rs | 8 ++++---- compiler/rustc_type_ir/src/fast_reject.rs | 4 ++-- compiler/rustc_type_ir/src/flags.rs | 4 ++-- compiler/rustc_type_ir/src/fold.rs | 20 +++++++++---------- compiler/rustc_type_ir/src/generic_arg.rs | 4 ++-- compiler/rustc_type_ir/src/infer_ctxt.rs | 17 +++++++--------- compiler/rustc_type_ir/src/pattern.rs | 4 ++-- compiler/rustc_type_ir/src/predicate_kind.rs | 8 ++++---- .../rustc_type_ir/src/region_constraint.rs | 4 +++- compiler/rustc_type_ir/src/relate.rs | 10 +++++----- compiler/rustc_type_ir/src/relate/combine.rs | 8 ++++---- .../src/relate/solver_relating.rs | 4 ++-- compiler/rustc_type_ir/src/solve/mod.rs | 6 +++--- compiler/rustc_type_ir/src/term_kind.rs | 6 +++--- compiler/rustc_type_ir/src/ty_kind.rs | 4 ++-- compiler/rustc_type_ir/src/universe.rs | 4 ++-- compiler/rustc_type_ir/src/visit.rs | 8 ++++---- 30 files changed, 105 insertions(+), 104 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs index f0f0ebaf2b3bb..75c7513758cd0 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/canonicalizer.rs @@ -5,8 +5,8 @@ use rustc_type_ir::inherent::*; use rustc_type_ir::solve::{Goal, QueryInput}; use rustc_type_ir::{ self as ty, Canonical, CanonicalParamEnvCacheEntry, CanonicalVarKind, CanonicalizerState, - Flags, InferCtxtLike, Interner, PlaceholderConst, PlaceholderType, PredicateProxy, Region, - TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + Const, Flags, InferCtxtLike, Interner, PlaceholderConst, PlaceholderType, PredicateProxy, + Region, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; use thin_vec::ThinVec; @@ -525,7 +525,7 @@ impl, I: Interner> TypeFolder for Canonicaliz } } - fn fold_const(&mut self, c: I::Const) -> I::Const { + fn fold_const(&mut self, c: Const) -> Const { if !c.flags().intersects(NEEDS_CANONICAL) { return c; } diff --git a/compiler/rustc_next_trait_solver/src/canonical/mod.rs b/compiler/rustc_next_trait_solver/src/canonical/mod.rs index fc9024333bf44..45ae4cadf519c 100644 --- a/compiler/rustc_next_trait_solver/src/canonical/mod.rs +++ b/compiler/rustc_next_trait_solver/src/canonical/mod.rs @@ -18,8 +18,8 @@ use rustc_type_ir::relate::{ self, Relate, RelateResult, TypeRelation, VarianceDiagInfo, relate_args_invariantly, }; use rustc_type_ir::{ - self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, InferCtxtLike, Interner, Region, - TypeFoldable, TypingMode, TypingModeEqWrapper, + self as ty, Canonical, CanonicalVarKind, CanonicalVarValues, Const, InferCtxtLike, Interner, + Region, TypeFoldable, TypingMode, TypingModeEqWrapper, }; use thin_vec::ThinVec; use tracing::instrument; @@ -421,7 +421,7 @@ where } #[instrument(skip(self), level = "trace")] - fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { + fn consts(&mut self, a: Const, b: Const) -> RelateResult> { if a == b { return Ok(a); } diff --git a/compiler/rustc_next_trait_solver/src/coherence.rs b/compiler/rustc_next_trait_solver/src/coherence.rs index e37e69a617bbd..ad6fc98601f69 100644 --- a/compiler/rustc_next_trait_solver/src/coherence.rs +++ b/compiler/rustc_next_trait_solver/src/coherence.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use rustc_type_ir::inherent::*; use rustc_type_ir::lang_items::SolverAdtLangItem; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, Region, TrivialTypeTraversalImpls, TypeVisitable, + self as ty, Const, InferCtxtLike, Interner, Region, TrivialTypeTraversalImpls, TypeVisitable, TypeVisitableExt, TypeVisitor, }; use tracing::instrument; @@ -469,7 +469,7 @@ where /// As these should be quite rare as const arguments and especially rare as impl /// parameters, allowing uncovered const parameters in impls seems more useful /// than allowing `impl Trait for i32` to compile. - fn visit_const(&mut self, _c: I::Const) -> Self::Result { + fn visit_const(&mut self, _c: Const) -> Self::Result { ControlFlow::Continue(()) } } diff --git a/compiler/rustc_next_trait_solver/src/delegate.rs b/compiler/rustc_next_trait_solver/src/delegate.rs index 0a307f766ebb2..24e321fc68c67 100644 --- a/compiler/rustc_next_trait_solver/src/delegate.rs +++ b/compiler/rustc_next_trait_solver/src/delegate.rs @@ -5,7 +5,7 @@ use rustc_type_ir::solve::{ Certainty, ComputeGoalFastPathOutcome, FetchEligibleAssocItemResponse, Goal, NoSolution, VisibleForLeakCheck, }; -use rustc_type_ir::{self as ty, CanonicalizerState, InferCtxtLike, Interner, TypeFoldable}; +use rustc_type_ir::{self as ty, CanonicalizerState, Const, InferCtxtLike, Interner, TypeFoldable}; /// `SolverDelegate` is one of the two traits in the `rustc_type_ir` shared abstraction layer /// between rustc and rust-analyzer abstracting over the [InferCtxt][inferctxt-doc], which had to be @@ -63,7 +63,7 @@ pub trait SolverDelegate: Deref + Sized { normalize_ty: impl FnOnce( ty::Unnormalized::Ty>, ) -> Result<::Ty, E>, - ) -> Result::Const>, E>; + ) -> Result>, E>; // FIXME: This only is here because `wf::obligations` is in `rustc_trait_selection`! fn well_formed_goals( @@ -112,7 +112,7 @@ pub trait SolverDelegate: Deref + Sized { &self, src: ::Ty, dst: ::Ty, - assume: ::Const, + assume: Const, ) -> Result; /// Obtain canonicalizer state, either by allocating it afresh (the default) or by reusing diff --git a/compiler/rustc_next_trait_solver/src/normalize.rs b/compiler/rustc_next_trait_solver/src/normalize.rs index ab3a92da4ba54..c7d8d2919089b 100644 --- a/compiler/rustc_next_trait_solver/src/normalize.rs +++ b/compiler/rustc_next_trait_solver/src/normalize.rs @@ -2,8 +2,8 @@ use std::fmt::Debug; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, AliasTerm, Binder, FallibleTypeFolder, InferCtxtLike, Interner, PredicateProxy, - TypeFoldable, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, + self as ty, AliasTerm, Binder, Const, FallibleTypeFolder, InferCtxtLike, Interner, + PredicateProxy, TypeFoldable, TypeSuperFoldable, TypeVisitableExt, UniverseIndex, }; use tracing::instrument; @@ -147,7 +147,7 @@ where } #[instrument(level = "trace", skip(self), ret)] - fn try_fold_const(&mut self, ct: I::Const) -> Result { + fn try_fold_const(&mut self, ct: Const) -> Result, Self::Error> { let infcx = self.infcx; let original = ct; diff --git a/compiler/rustc_next_trait_solver/src/placeholder.rs b/compiler/rustc_next_trait_solver/src/placeholder.rs index 84811a101fb11..c96aa90a10792 100644 --- a/compiler/rustc_next_trait_solver/src/placeholder.rs +++ b/compiler/rustc_next_trait_solver/src/placeholder.rs @@ -3,8 +3,9 @@ use core::panic; use rustc_type_ir::data_structures::IndexMap; use rustc_type_ir::inherent::*; use rustc_type_ir::{ - self as ty, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, PlaceholderType, - PredicateProxy, Region, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, + self as ty, Const, InferCtxtLike, Interner, PlaceholderConst, PlaceholderRegion, + PlaceholderType, PredicateProxy, Region, TypeFoldable, TypeFolder, TypeSuperFoldable, + TypeVisitableExt, }; use tracing::debug; @@ -160,7 +161,7 @@ where } } - fn fold_const(&mut self, ct: I::Const) -> I::Const { + fn fold_const(&mut self, ct: Const) -> Const { match ct.kind() { ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), _) if debruijn.as_usize() + 1 @@ -310,7 +311,7 @@ where } } - fn fold_const(&mut self, ct: I::Const) -> I::Const { + fn fold_const(&mut self, ct: Const) -> Const { let ct = self.infcx.shallow_resolve_const(ct); if let ty::ConstKind::Placeholder(p) = ct.kind() { let replace_var = self.mapped_consts.get(&p); diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 485568850bee0..32e38ad88c856 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -14,7 +14,7 @@ use rustc_type_ir::solve::{ RerunNonErased, RerunReason, RerunResultExt, SizedTraitKind, StalledOnCoroutines, }; use rustc_type_ir::{ - self as ty, AliasTy, Interner, MayBeErased, Region, TypeFlags, TypeFoldable, TypeFolder, + self as ty, AliasTy, Const, Interner, MayBeErased, Region, TypeFlags, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, Unnormalized, Upcast, elaborate, }; @@ -1466,7 +1466,7 @@ where } } - fn visit_const(&mut self, ct: I::Const) -> Self::Result { + fn visit_const(&mut self, ct: Const) -> Self::Result { let ct = self.ecx.replace_bound_vars(ct, &mut self.universes); let Ok(ct) = self.ecx.structurally_normalize_const(self.param_env, ct) else { return ControlFlow::Break(Err(NoSolution)); diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs index 3a4875c1d0951..52eaa445d68a6 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs @@ -17,7 +17,7 @@ use rustc_type_ir::solve::{ RerunNonErased, RerunReason, RerunResultExt, SmallCopySet, TyOrConstInferVar, }; use rustc_type_ir::{ - self as ty, CanonicalVarValues, ClauseKind, InferCtxtLike, Interner, MayBeErased, + self as ty, CanonicalVarValues, ClauseKind, Const, InferCtxtLike, Interner, MayBeErased, OpaqueTypeKey, PredicateKind, PredicateProxy, Region, RegionVid, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor, TypingMode, max_universe, }; @@ -1057,7 +1057,7 @@ where ty } - pub(super) fn next_const_infer(&mut self) -> I::Const { + pub(super) fn next_const_infer(&mut self) -> Const { let ct = self.delegate.next_const_infer(); self.inspect.add_var_value(ct); ct @@ -1154,7 +1154,7 @@ where ControlFlow::Continue(()) } - fn visit_const(&mut self, c: I::Const) -> Self::Result { + fn visit_const(&mut self, c: Const) -> Self::Result { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { if let ty::TermKind::Const(term) = self.term.kind() @@ -1409,7 +1409,7 @@ where &mut self, param_env: I::ParamEnv, alias_const: ty::AliasConst, - ) -> Result, NoSolutionOrRerunNonErased> { + ) -> Result>, NoSolutionOrRerunNonErased> { if self.typing_mode().is_erased_not_coherence() { match self.opaque_accesses.rerun_always(RerunReason::EvaluateConst)? {} } @@ -1470,7 +1470,7 @@ where &mut self, src: I::Ty, dst: I::Ty, - assume: I::Const, + assume: Const, ) -> Result { self.delegate.is_transmutable(dst, src, assume) } @@ -1760,7 +1760,7 @@ fn filter_irrelevant_region_constraints( } t.super_visit_with(self); } - fn visit_const(&mut self, c: I::Const) { + fn visit_const(&mut self, c: Const) { // The same goes for consts. if !c.has_infer_regions() { return; diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs index 5ecc06b30f33b..10dd8585b09c4 100644 --- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs +++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/solver_region_constraints.rs @@ -11,8 +11,8 @@ use rustc_type_ir::region_constraint::{ propagate_ambiguity, }; use rustc_type_ir::{ - AliasTy, Binder, ClauseKind, InferCtxtLike, Interner, Region, TypeVisitable, TypeVisitableExt, - TypeVisitor, UniverseIndex, + AliasTy, Binder, ClauseKind, Const, InferCtxtLike, Interner, Region, TypeVisitable, + TypeVisitableExt, TypeVisitor, UniverseIndex, }; use tracing::{debug, instrument}; @@ -63,7 +63,7 @@ where ); } - fn visit_const(&mut self, c: I::Const) { + fn visit_const(&mut self, c: Const) { self.out.extend( self.ecx .well_formed_goals(self.param_env, c.into()) diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs index 10ee038005d8e..1d7d2dd75c316 100644 --- a/compiler/rustc_next_trait_solver/src/solve/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs @@ -23,7 +23,7 @@ mod trait_goals; use derive_where::derive_where; use rustc_type_ir::inherent::*; pub use rustc_type_ir::solve::*; -use rustc_type_ir::{self as ty, Interner, Region, TypeVisitableExt}; +use rustc_type_ir::{self as ty, Const, Interner, Region, TypeVisitableExt}; use tracing::instrument; pub use self::eval_ctxt::{ @@ -205,7 +205,7 @@ where #[instrument(level = "trace", skip(self))] fn compute_const_evaluatable_goal( &mut self, - Goal { param_env, predicate: ct }: Goal, + Goal { param_env, predicate: ct }: Goal>, ) -> QueryResultOrRerunNonErased { match ct.kind() { ty::ConstKind::Alias(ty::IsRigid::Yes, _) @@ -248,7 +248,7 @@ where #[instrument(level = "trace", skip(self), ret)] fn compute_const_arg_has_type_goal( &mut self, - goal: Goal, + goal: Goal, I::Ty)>, ) -> QueryResultOrRerunNonErased { let (ct, ty) = goal.predicate; let ct = self.structurally_normalize_const(goal.param_env, ct)?; @@ -375,8 +375,8 @@ where fn structurally_normalize_const( &mut self, param_env: I::ParamEnv, - ct: I::Const, - ) -> Result { + ct: Const, + ) -> Result, NoSolutionOrRerunNonErased> { self.structurally_normalize_term(param_env, ct.into()).map(|term| term.expect_const()) } diff --git a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs index cb878f2c54878..388b334ccf618 100644 --- a/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs +++ b/compiler/rustc_next_trait_solver/src/solve/normalizes_to.rs @@ -8,7 +8,8 @@ use rustc_type_ir::solve::{ RerunNonErased, RerunReason, RerunResultExt, }; use rustc_type_ir::{ - self as ty, FieldInfo, Interner, NormalizesTo, PredicateKind, Region, Unnormalized, Upcast as _, + self as ty, Const, FieldInfo, Interner, NormalizesTo, PredicateKind, Region, Unnormalized, + Upcast as _, }; use tracing::instrument; diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs index a16610a520406..6722adfe24d5d 100644 --- a/compiler/rustc_type_ir/src/binder.rs +++ b/compiler/rustc_type_ir/src/binder.rs @@ -16,7 +16,7 @@ use crate::fold::{FallibleTypeFolder, TypeFoldable, TypeFolder, TypeSuperFoldabl use crate::inherent::*; use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor}; use crate::{ - self as ty, DebruijnIndex, Interner, PredicateProxy, Region, UniverseIndex, Unnormalized, + self as ty, Const, DebruijnIndex, Interner, PredicateProxy, Region, UniverseIndex, Unnormalized, }; /// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the @@ -262,7 +262,7 @@ impl TypeVisitor for ValidateBoundVars { t.super_visit_with(self) } - fn visit_const(&mut self, c: I::Const) -> Self::Result { + fn visit_const(&mut self, c: Const) -> Self::Result { if c.outer_exclusive_binder() < self.binder_index { return ControlFlow::Break(()); } @@ -741,7 +741,7 @@ impl<'a, I: Interner> TypeFolder for ArgFolder<'a, I> { } } - fn fold_const(&mut self, c: I::Const) -> I::Const { + fn fold_const(&mut self, c: Const) -> Const { if let ty::ConstKind::Param(p) = c.kind() { self.const_for_param(p, c) } else { @@ -796,7 +796,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { ) } - fn const_for_param(&self, p: I::ParamConst, source_ct: I::Const) -> I::Const { + fn const_for_param(&self, p: I::ParamConst, source_ct: Const) -> Const { // Look up the const in the args. It really should be in there. let opt_ct = self.args.get(p.index() as usize).map(|arg| arg.kind()); let ct = match opt_ct { @@ -813,7 +813,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { fn const_param_expected( &self, p: I::ParamConst, - ct: I::Const, + ct: Const, kind: ty::GenericArgKind, ) -> ! { panic!( @@ -828,7 +828,7 @@ impl<'a, I: Interner> ArgFolder<'a, I> { #[cold] #[inline(never)] - fn const_param_out_of_range(&self, p: I::ParamConst, ct: I::Const) -> ! { + fn const_param_out_of_range(&self, p: I::ParamConst, ct: Const) -> ! { panic!( "const parameter `{:?}` ({:?}/{}) out of range when instantiating args={:?}", p, diff --git a/compiler/rustc_type_ir/src/canonical.rs b/compiler/rustc_type_ir/src/canonical.rs index bba271ba13033..66ee34693c118 100644 --- a/compiler/rustc_type_ir/src/canonical.rs +++ b/compiler/rustc_type_ir/src/canonical.rs @@ -12,7 +12,7 @@ use thin_vec::ThinVec; use crate::data_structures::{DelayedMap, HashMap}; use crate::inherent::*; -use crate::{self as ty, Interner, Region, TypingModeEqWrapper, UniverseIndex}; +use crate::{self as ty, Const, Interner, Region, TypingModeEqWrapper, UniverseIndex}; #[derive_where(Clone, Hash, PartialEq, Debug; I: Interner, V)] #[derive_where(Copy; I: Interner, V: Copy)] diff --git a/compiler/rustc_type_ir/src/error.rs b/compiler/rustc_type_ir/src/error.rs index 59ceb4bd1e327..76b86d21b6ae4 100644 --- a/compiler/rustc_type_ir/src/error.rs +++ b/compiler/rustc_type_ir/src/error.rs @@ -3,7 +3,7 @@ use rustc_abi::ExternAbi; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use crate::solve::{NoSolution, NoSolutionOrRerunNonErased}; -use crate::{self as ty, Interner, Region}; +use crate::{self as ty, Const, Interner, Region}; #[derive(Clone, Copy, Debug, PartialEq, Eq)] #[derive(TypeFoldable_Generic, TypeVisitable_Generic, GenericTypeVisitable)] @@ -30,7 +30,7 @@ pub enum TypeError { Mutability, ArgumentMutability(usize), TupleSize(ExpectedFound), - ArraySize(ExpectedFound), + ArraySize(ExpectedFound>), ArgCount, RegionsDoesNotOutlive(Region, Region), @@ -47,10 +47,10 @@ pub enum TypeError { /// created a cycle (because it appears somewhere within that /// type). CyclicTy(I::Ty), - CyclicConst(I::Const), + CyclicConst(Const), ProjectionMismatched(ExpectedFound>), ExistentialMismatch(ExpectedFound), - ConstMismatch(ExpectedFound), + ConstMismatch(ExpectedFound>), IntrinsicCast, /// `#[rustc_force_inline]` functions must be inlined and must not be codegened independently, diff --git a/compiler/rustc_type_ir/src/fast_reject.rs b/compiler/rustc_type_ir/src/fast_reject.rs index e9339338a6ef1..398fddcd4a141 100644 --- a/compiler/rustc_type_ir/src/fast_reject.rs +++ b/compiler/rustc_type_ir/src/fast_reject.rs @@ -9,7 +9,7 @@ use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash}; use crate::inherent::*; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, Interner}; +use crate::{self as ty, Const, Interner}; /// See `simplify_type`. #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] @@ -486,7 +486,7 @@ impl bool { + fn consts_may_unify_inner(self, lhs: Const, rhs: Const) -> bool { match rhs.kind() { ty::ConstKind::Param(_) => { if INSTANTIATE_RHS_WITH_INFER { diff --git a/compiler/rustc_type_ir/src/flags.rs b/compiler/rustc_type_ir/src/flags.rs index 7b0a098ad1948..4af4f1479ec82 100644 --- a/compiler/rustc_type_ir/src/flags.rs +++ b/compiler/rustc_type_ir/src/flags.rs @@ -1,6 +1,6 @@ use crate::inherent::*; use crate::visit::Flags; -use crate::{self as ty, Interner, Region}; +use crate::{self as ty, Const, Interner, Region}; bitflags::bitflags! { /// Flags that we track on types. These flags are propagated upwards @@ -463,7 +463,7 @@ impl FlagComputation { } } - fn add_const(&mut self, c: I::Const) { + fn add_const(&mut self, c: Const) { self.add_flags(c.flags()); self.add_exclusive_binder(c.outer_exclusive_binder()); } diff --git a/compiler/rustc_type_ir/src/fold.rs b/compiler/rustc_type_ir/src/fold.rs index 2b25de4132e62..388796732c2cb 100644 --- a/compiler/rustc_type_ir/src/fold.rs +++ b/compiler/rustc_type_ir/src/fold.rs @@ -56,8 +56,8 @@ use tracing::{debug, instrument}; use crate::inherent::*; use crate::visit::{TypeVisitable, TypeVisitableExt as _}; use crate::{ - self as ty, Binder, BoundVarIndexKind, ClauseKind, Flags, Interner, ProjectionClause, Region, - TypeSuperVisitable, + self as ty, Binder, BoundVarIndexKind, ClauseKind, Const, Flags, Interner, ProjectionClause, + Region, TypeSuperVisitable, }; /// This trait is implemented for every type that can be folded, @@ -144,7 +144,7 @@ pub trait TypeFolder: Sized { r } - fn fold_const(&mut self, c: I::Const) -> I::Const { + fn fold_const(&mut self, c: Const) -> Const { c.super_fold_with(self) } @@ -213,7 +213,7 @@ pub trait FallibleTypeFolder: Sized { Ok(r) } - fn try_fold_const(&mut self, c: I::Const) -> Result { + fn try_fold_const(&mut self, c: Const) -> Result, Self::Error> { c.try_super_fold_with(self) } @@ -448,7 +448,7 @@ impl TypeFolder for Shifter { } } - fn fold_const(&mut self, ct: I::Const) -> I::Const { + fn fold_const(&mut self, ct: Const) -> Const { match ct.kind() { ty::ConstKind::Bound(ty::BoundVarIndexKind::Bound(debruijn), bound_ct) if debruijn >= self.current_index => @@ -572,7 +572,7 @@ where if t.has_regions() { t.super_fold_with(self) } else { t } } - fn fold_const(&mut self, ct: I::Const) -> I::Const { + fn fold_const(&mut self, ct: Const) -> Const { if ct.has_regions() { ct.super_fold_with(self) } else { ct } } @@ -698,7 +698,7 @@ impl TypeFolder for RigidnessFolder { } } - fn fold_const(&mut self, c: I::Const) -> I::Const { + fn fold_const(&mut self, c: Const) -> Const { if !self.mode.needs_change(&c) { return c; } @@ -708,13 +708,13 @@ impl TypeFolder for RigidnessFolder { let alias_const = alias_const.fold_with(self); match self.mode { RigidnessFoldMode::AllToRigid => { - I::Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const) + Const::new_alias(self.cx, ty::IsRigid::Yes, alias_const) } RigidnessFoldMode::AllToNonRigid => { - I::Const::new_alias(self.cx(), ty::IsRigid::No, alias_const) + Const::new_alias(self.cx(), ty::IsRigid::No, alias_const) } RigidnessFoldMode::OpaqueToNonRigid | RigidnessFoldMode::TypeToRigid => { - I::Const::new_alias(self.cx(), is_rigid, alias_const) + Const::new_alias(self.cx(), is_rigid, alias_const) } } } diff --git a/compiler/rustc_type_ir/src/generic_arg.rs b/compiler/rustc_type_ir/src/generic_arg.rs index b42a3c3159a07..31c87f7b1684e 100644 --- a/compiler/rustc_type_ir/src/generic_arg.rs +++ b/compiler/rustc_type_ir/src/generic_arg.rs @@ -3,7 +3,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; use rustc_type_ir_macros::GenericTypeVisitable; -use crate::{Interner, Region}; +use crate::{Const, Interner, Region}; #[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)] #[derive(GenericTypeVisitable)] @@ -14,7 +14,7 @@ use crate::{Interner, Region}; pub enum GenericArgKind { Lifetime(Region), Type(I::Ty), - Const(I::Const), + Const(Const), } impl Eq for GenericArgKind {} diff --git a/compiler/rustc_type_ir/src/infer_ctxt.rs b/compiler/rustc_type_ir/src/infer_ctxt.rs index a86a07edb902f..22ebedd9f7e3c 100644 --- a/compiler/rustc_type_ir/src/infer_ctxt.rs +++ b/compiler/rustc_type_ir/src/infer_ctxt.rs @@ -11,7 +11,7 @@ use crate::relate::RelateResult; use crate::relate::combine::PredicateEmittingRelation; use crate::solve::{TyOrConstInferVar, VisibleForLeakCheck}; use crate::{ - self as ty, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder, + self as ty, Const, Interner, PredicateProxy, Region, TyVid, TypeFoldable, TypeFolder, TypeSuperFoldable, TypeVisitableExt, }; @@ -434,14 +434,14 @@ pub trait InferCtxtLike: Sized { fn shallow_resolve_ty_var(&self, vid: ty::TyVid) -> ::Ty; fn shallow_resolve_int_var(&self, vid: ty::IntVid) -> ::Ty; fn shallow_resolve_float_var(&self, vid: ty::FloatVid) -> ::Ty; - fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> ::Const; + fn shallow_resolve_const_var(&self, vid: ty::ConstVid) -> Const; fn shallow_resolve_region_var(&self, vid: ty::RegionVid) -> Region; fn ty_or_const_infer_var_changed(&self, var: TyOrConstInferVar) -> bool; fn next_region_infer(&self) -> Region; fn next_ty_infer(&self) -> ::Ty; - fn next_const_infer(&self) -> ::Const; + fn next_const_infer(&self) -> Const; fn fresh_args_for_item( &self, def_id: ::DefId, @@ -478,7 +478,7 @@ pub trait InferCtxtLike: Sized { fn instantiate_ty_var_raw(&self, vid: ty::TyVid, ty: ::Ty); /// Use `instantiate_const_var` instead unless you have reasons to skip /// generalization. - fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: ::Const); + fn instantiate_const_var_raw(&self, vid: ty::ConstVid, ct: Const); fn instantiate_ty_var>( &self, relation: &mut R, @@ -494,7 +494,7 @@ pub trait InferCtxtLike: Sized { relation: &mut R, target_is_expected: bool, target_vid: ty::ConstVid, - source_ct: ::Const, + source_ct: Const, ) -> RelateResult; fn set_tainted_by_errors(&self, e: ::ErrorGuaranteed); @@ -503,10 +503,7 @@ pub trait InferCtxtLike: Sized { &self, ty: ::Ty, ) -> ::Ty; - fn shallow_resolve_const( - &self, - ty: ::Const, - ) -> ::Const; + fn shallow_resolve_const(&self, ty: Const) -> Const; fn deeply_resolve_ignoring_regions(&self, value: T) -> T where @@ -694,7 +691,7 @@ impl, I: Interner> TypeFolder } } - fn fold_const(&mut self, c: I::Const) -> I::Const { + fn fold_const(&mut self, c: Const) -> Const { match c.kind() { ty::ConstKind::Infer(ty::InferConst::Var(vid)) => { let resolved = self.delegate.shallow_resolve_const_var(vid); diff --git a/compiler/rustc_type_ir/src/pattern.rs b/compiler/rustc_type_ir/src/pattern.rs index 69b2c414695bc..dbd4ea4ad9867 100644 --- a/compiler/rustc_type_ir/src/pattern.rs +++ b/compiler/rustc_type_ir/src/pattern.rs @@ -5,7 +5,7 @@ use rustc_type_ir_macros::{ GenericTypeVisitable, Lift_Generic, TypeFoldable_Generic, TypeVisitable_Generic, }; -use crate::Interner; +use crate::{Const, Interner}; #[derive_where(Clone, Copy, Hash, PartialEq; I: Interner)] #[derive(TypeVisitable_Generic, GenericTypeVisitable, TypeFoldable_Generic, Lift_Generic)] @@ -14,7 +14,7 @@ use crate::Interner; derive(Decodable_NoContext, Encodable_NoContext, StableHash_NoContext) )] pub enum PatternKind { - Range { start: I::Const, end: I::Const }, + Range { start: Const, end: Const }, Or(I::PatList), NotNull, } diff --git a/compiler/rustc_type_ir/src/predicate_kind.rs b/compiler/rustc_type_ir/src/predicate_kind.rs index d6276ea0062bd..946fff0d3a649 100644 --- a/compiler/rustc_type_ir/src/predicate_kind.rs +++ b/compiler/rustc_type_ir/src/predicate_kind.rs @@ -5,7 +5,7 @@ use derive_where::derive_where; use rustc_macros::{Decodable_NoContext, Encodable_NoContext, StableHash_NoContext}; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; -use crate::{self as ty, Interner, Region}; +use crate::{self as ty, Const, Interner, Region}; /// A clause is something that can appear in where bounds or be inferred /// by implied bounds. @@ -33,13 +33,13 @@ pub enum ClauseKind { /// Ensures that a const generic argument to a parameter `const N: u8` /// is of type `u8`. - ConstArgHasType(I::Const, I::Ty), + ConstArgHasType(Const, I::Ty), /// No syntax: `T` well-formed. WellFormed(I::Term), /// Constant initializer must evaluate successfully. - ConstEvaluatable(I::Const), + ConstEvaluatable(Const), /// Enforces the constness of the clause we're calling. Like a projection /// goal from a where clause, it's always going to be paired with a @@ -88,7 +88,7 @@ pub enum PredicateKind { Coerce(ty::CoercePredicate), /// Constants must be equal. The first component is the const that is expected. - ConstEquate(I::Const, I::Const), + ConstEquate(Const, Const), /// A marker predicate that is always ambiguous. /// Used for coherence to mark opaque types as possibly equal to each other but ambiguous. diff --git a/compiler/rustc_type_ir/src/region_constraint.rs b/compiler/rustc_type_ir/src/region_constraint.rs index 0dd79d8d0449e..58763593f9b7e 100644 --- a/compiler/rustc_type_ir/src/region_constraint.rs +++ b/compiler/rustc_type_ir/src/region_constraint.rs @@ -9,6 +9,8 @@ use rustc_macros::StableHash_NoContext; use rustc_type_ir_macros::{GenericTypeVisitable, TypeFoldable_Generic, TypeVisitable_Generic}; use tracing::{debug, instrument}; +use crate::Const; + // Workaround for TransitiveRelation being in rustc_data_structures which isn't accessible on stable #[cfg(not(feature = "nightly"))] #[derive(Default, Clone, Debug)] @@ -1227,7 +1229,7 @@ impl<'a, Infcx: InferCtxtLike, I: Interner> TypeRelation Ok(a) } - fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { + fn consts(&mut self, a: Const, b: Const) -> RelateResult> { rustc_type_ir::relate::structurally_relate_consts(self, a, b) } diff --git a/compiler/rustc_type_ir/src/relate.rs b/compiler/rustc_type_ir/src/relate.rs index 49fcb38968abe..e87b584ebcb6b 100644 --- a/compiler/rustc_type_ir/src/relate.rs +++ b/compiler/rustc_type_ir/src/relate.rs @@ -7,7 +7,7 @@ use tracing::{instrument, trace}; use crate::error::{ExpectedFound, TypeError}; use crate::fold::TypeFoldable; use crate::inherent::*; -use crate::{self as ty, Interner, Region}; +use crate::{self as ty, Const, Interner, Region}; pub mod combine; pub mod solver_relating; @@ -90,7 +90,7 @@ pub trait TypeRelation: Sized { fn regions(&mut self, a: Region, b: Region) -> RelateResult>; - fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult; + fn consts(&mut self, a: Const, b: Const) -> RelateResult>; fn binders( &mut self, @@ -551,9 +551,9 @@ pub fn structurally_relate_tys>( /// See the HACKs below. pub fn structurally_relate_consts>( relation: &mut R, - mut a: I::Const, - mut b: I::Const, -) -> RelateResult { + mut a: Const, + mut b: Const, +) -> RelateResult> { trace!( "structurally_relate_consts::<{}>(a = {:?}, b = {:?})", std::any::type_name::(), diff --git a/compiler/rustc_type_ir/src/relate/combine.rs b/compiler/rustc_type_ir/src/relate/combine.rs index 7b747141889fe..054dff869e650 100644 --- a/compiler/rustc_type_ir/src/relate/combine.rs +++ b/compiler/rustc_type_ir/src/relate/combine.rs @@ -10,7 +10,7 @@ use crate::inherent::*; use crate::relate::VarianceDiagInfo; use crate::solve::Goal; use crate::visit::TypeVisitableExt as _; -use crate::{self as ty, InferCtxtLike, Interner, TypingMode, Upcast}; +use crate::{self as ty, Const, InferCtxtLike, Interner, TypingMode, Upcast}; pub trait PredicateEmittingRelation::Interner>: TypeRelation @@ -143,9 +143,9 @@ where pub fn super_combine_consts( infcx: &Infcx, relation: &mut R, - a: I::Const, - b: I::Const, -) -> RelateResult + a: Const, + b: Const, +) -> RelateResult> where Infcx: InferCtxtLike, I: Interner, diff --git a/compiler/rustc_type_ir/src/relate/solver_relating.rs b/compiler/rustc_type_ir/src/relate/solver_relating.rs index 96a792edd2f9d..3a7056234553b 100644 --- a/compiler/rustc_type_ir/src/relate/solver_relating.rs +++ b/compiler/rustc_type_ir/src/relate/solver_relating.rs @@ -5,7 +5,7 @@ use crate::data_structures::DelayedSet; use crate::relate::combine::combine_ty_args; pub use crate::relate::*; use crate::solve::{Goal, VisibleForLeakCheck}; -use crate::{self as ty, InferCtxtLike, Interner, Region}; +use crate::{self as ty, Const, InferCtxtLike, Interner, Region}; pub trait RelateExt: InferCtxtLike { fn relate>( @@ -254,7 +254,7 @@ where } #[instrument(skip(self), level = "trace")] - fn consts(&mut self, a: I::Const, b: I::Const) -> RelateResult { + fn consts(&mut self, a: Const, b: Const) -> RelateResult> { super_combine_consts(self.infcx, self, a, b) } diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs index 88d2184ed95b2..c6d88bb6603de 100644 --- a/compiler/rustc_type_ir/src/solve/mod.rs +++ b/compiler/rustc_type_ir/src/solve/mod.rs @@ -18,8 +18,8 @@ use crate::lang_items::SolverTraitLangItem; use crate::region_constraint::RegionConstraint; use crate::search_graph::PathKind; use crate::{ - self as ty, Canonical, CanonicalVarValues, CantBeErased, ConstVid, FloatVid, GenericArgKind, - InferConst, IntVid, Interner, TermKind, TyVid, TypingMode, Upcast, + self as ty, Canonical, CanonicalVarValues, CantBeErased, Const, ConstVid, FloatVid, + GenericArgKind, InferConst, IntVid, Interner, TermKind, TyVid, TypingMode, Upcast, }; pub type CanonicalInputData = @@ -1090,7 +1090,7 @@ impl TyOrConstInferVar { /// Tries to extract an inference variable from a constant, returns `None` /// for constants other than `ty::ConstKind::Infer(_)` (or `InferConst::Fresh`). - fn maybe_from_const(ct: I::Const) -> Option { + fn maybe_from_const(ct: Const) -> Option { match ct.kind() { ty::ConstKind::Infer(InferConst::Var(v)) => Some(TyOrConstInferVar::Const(v)), _ => None, diff --git a/compiler/rustc_type_ir/src/term_kind.rs b/compiler/rustc_type_ir/src/term_kind.rs index 6a4b1f023dde2..0c151e678a614 100644 --- a/compiler/rustc_type_ir/src/term_kind.rs +++ b/compiler/rustc_type_ir/src/term_kind.rs @@ -8,7 +8,7 @@ use rustc_type_ir_macros::{ }; use crate::inherent::*; -use crate::{self as ty, AliasTerm, Interner}; +use crate::{self as ty, AliasTerm, Const, Interner}; #[derive_where(Clone, Copy, PartialEq, Debug; I: Interner)] #[derive(GenericTypeVisitable)] @@ -18,7 +18,7 @@ use crate::{self as ty, AliasTerm, Interner}; )] pub enum TermKind { Ty(I::Ty), - Const(I::Const), + Const(Const), } impl Eq for TermKind {} @@ -213,7 +213,7 @@ impl AliasTerm { .into() }; let alias_const = |kind| { - I::Const::new_alias(interner, is_rigid, ty::AliasConst::new(interner, kind, self.args)) + Const::new_alias(interner, is_rigid, ty::AliasConst::new(interner, kind, self.args)) .into() }; match self.kind { diff --git a/compiler/rustc_type_ir/src/ty_kind.rs b/compiler/rustc_type_ir/src/ty_kind.rs index 248ba00348749..68a1b479830e2 100644 --- a/compiler/rustc_type_ir/src/ty_kind.rs +++ b/compiler/rustc_type_ir/src/ty_kind.rs @@ -19,7 +19,7 @@ pub use self::closure::*; use crate::inherent::*; use crate::ty::AliasTy; use crate::{ - self as ty, BoundVarIndexKind, FloatTy, FreeAliasTy, InherentAliasTy, IntTy, Interner, + self as ty, BoundVarIndexKind, Const, FloatTy, FreeAliasTy, InherentAliasTy, IntTy, Interner, OpaqueAliasTy, ProjectionAliasTy, Region, UintTy, Unnormalized, }; @@ -187,7 +187,7 @@ pub enum TyKind { Str, /// An array with the given length. Written as `[T; N]`. - Array(I::Ty, I::Const), + Array(I::Ty, Const), /// A pattern newtype. /// diff --git a/compiler/rustc_type_ir/src/universe.rs b/compiler/rustc_type_ir/src/universe.rs index 1f38edd78023d..34210a0251fb8 100644 --- a/compiler/rustc_type_ir/src/universe.rs +++ b/compiler/rustc_type_ir/src/universe.rs @@ -4,7 +4,7 @@ use crate::data_structures::HashSet; use crate::inherent::*; use crate::visit::TypeVisitableExt; use crate::{ - ConstKind, InferCtxtLike, InferTy, Interner, Region, RegionKind, TyKind, TypeFoldable, + Const, ConstKind, InferCtxtLike, InferTy, Interner, Region, RegionKind, TyKind, TypeFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitor, UniverseIndex, }; @@ -130,7 +130,7 @@ impl< assert!(self.cache.insert(t), "we shouldn't visit {t:?} twice"); } - fn visit_const(&mut self, c: I::Const) { + fn visit_const(&mut self, c: Const) { if !Self::needs_visit(&c) { return; } diff --git a/compiler/rustc_type_ir/src/visit.rs b/compiler/rustc_type_ir/src/visit.rs index 1138d8cf9edad..008b6aeb239ee 100644 --- a/compiler/rustc_type_ir/src/visit.rs +++ b/compiler/rustc_type_ir/src/visit.rs @@ -52,7 +52,7 @@ use smallvec::SmallVec; use thin_vec::ThinVec; use crate::inherent::*; -use crate::{self as ty, Interner, PredicateProxy, Region, TypeFlags}; +use crate::{self as ty, Const, Interner, PredicateProxy, Region, TypeFlags}; /// This trait is implemented for every type that can be visited, /// providing the skeleton of the traversal. @@ -112,7 +112,7 @@ pub trait TypeVisitor: Sized { } } - fn visit_const(&mut self, c: I::Const) -> Self::Result { + fn visit_const(&mut self, c: Const) -> Self::Result { c.super_visit_with(self) } @@ -475,7 +475,7 @@ impl TypeVisitor for HasTypeFlagsVisitor { } #[inline] - fn visit_const(&mut self, c: I::Const) -> Self::Result { + fn visit_const(&mut self, c: Const) -> Self::Result { // Note: no `super_visit_with` call. if c.flags().intersects(self.flags) { ControlFlow::Break(FoundFlags) @@ -583,7 +583,7 @@ impl TypeVisitor for HasEscapingVarsVisitor { } } - fn visit_const(&mut self, ct: I::Const) -> Self::Result { + fn visit_const(&mut self, ct: Const) -> Self::Result { // If the outer-exclusive-binder is *strictly greater* than // `outer_index`, that means that `ct` contains some content // bound at `outer_index` or above (because From af2f1f375c6f8aebfaf91c40883ae148c294f756 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:40 +0100 Subject: [PATCH 0622/1309] `use ConstExt` for methods that do not yet exist in `rustc_type_ir` --- compiler/rustc_borrowck/src/type_check/mod.rs | 1 + compiler/rustc_codegen_cranelift/src/base.rs | 1 + compiler/rustc_codegen_cranelift/src/debuginfo/types.rs | 1 + compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs | 1 + compiler/rustc_codegen_cranelift/src/unsize.rs | 1 + compiler/rustc_codegen_gcc/src/intrinsic/simd.rs | 1 + compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs | 1 + compiler/rustc_codegen_llvm/src/intrinsic.rs | 1 + compiler/rustc_codegen_ssa/src/base.rs | 1 + compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs | 1 + compiler/rustc_codegen_ssa/src/mir/constant.rs | 1 + compiler/rustc_codegen_ssa/src/mir/intrinsic.rs | 1 + compiler/rustc_codegen_ssa/src/mir/operand.rs | 1 + compiler/rustc_codegen_ssa/src/mir/rvalue.rs | 1 + compiler/rustc_const_eval/src/const_eval/machine.rs | 1 + compiler/rustc_const_eval/src/const_eval/mod.rs | 1 + compiler/rustc_const_eval/src/const_eval/valtrees.rs | 1 + compiler/rustc_const_eval/src/interpret/cast.rs | 1 + compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs | 1 + compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs | 1 + compiler/rustc_hir_analysis/src/check/check.rs | 1 + compiler/rustc_hir_analysis/src/check/intrinsic.rs | 1 + compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs | 1 + compiler/rustc_hir_typeck/src/expr.rs | 1 + compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs | 1 + compiler/rustc_hir_typeck/src/inline_asm.rs | 1 + compiler/rustc_hir_typeck/src/pat.rs | 1 + compiler/rustc_lint/src/builtin.rs | 1 + compiler/rustc_lint/src/types.rs | 1 + compiler/rustc_lint/src/unused/must_use.rs | 1 + compiler/rustc_middle/src/mir/consts.rs | 1 + compiler/rustc_middle/src/mir/pretty.rs | 1 + compiler/rustc_middle/src/mir/statement.rs | 1 + compiler/rustc_middle/src/ty/consts/valtree.rs | 1 + .../rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs | 1 + compiler/rustc_middle/src/ty/inhabitedness/mod.rs | 1 + compiler/rustc_middle/src/ty/layout.rs | 1 + compiler/rustc_middle/src/ty/pattern.rs | 1 + compiler/rustc_middle/src/ty/sty.rs | 1 + compiler/rustc_middle/src/ty/typetree.rs | 1 + compiler/rustc_middle/src/ty/util.rs | 1 + compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs | 1 + compiler/rustc_mir_build/src/builder/matches/match_pair.rs | 1 + compiler/rustc_mir_build/src/builder/matches/mod.rs | 1 + compiler/rustc_mir_build/src/builder/scope.rs | 1 + compiler/rustc_mir_build/src/thir/constant.rs | 1 + compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs | 1 + compiler/rustc_mir_build/src/thir/pattern/mod.rs | 1 + compiler/rustc_mir_dataflow/src/move_paths/builder.rs | 1 + compiler/rustc_mir_transform/src/coroutine/layout.rs | 1 + compiler/rustc_mir_transform/src/elaborate_drop.rs | 1 + compiler/rustc_mir_transform/src/gvn.rs | 1 + compiler/rustc_mir_transform/src/instsimplify.rs | 1 + compiler/rustc_mir_transform/src/known_panics_lint.rs | 1 + compiler/rustc_mir_transform/src/promote_consts.rs | 1 + compiler/rustc_mir_transform/src/remove_zsts.rs | 1 + compiler/rustc_pattern_analysis/src/rustc.rs | 1 + compiler/rustc_public_bridge/src/context/impls.rs | 1 + .../rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs | 1 + compiler/rustc_symbol_mangling/src/legacy.rs | 1 + compiler/rustc_symbol_mangling/src/v0.rs | 1 + compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs | 1 + .../src/error_reporting/traits/ambiguity.rs | 1 + .../src/error_reporting/traits/fulfillment_errors.rs | 1 + .../src/error_reporting/traits/on_unimplemented.rs | 1 + .../src/error_reporting/traits/suggestions.rs | 1 + compiler/rustc_trait_selection/src/traits/fulfill.rs | 1 + compiler/rustc_trait_selection/src/traits/mod.rs | 1 + .../rustc_trait_selection/src/traits/query/dropck_outlives.rs | 1 + compiler/rustc_transmute/src/lib.rs | 1 + compiler/rustc_ty_utils/src/consts.rs | 1 + 71 files changed, 71 insertions(+) diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs index 4c5acd58638fb..e5bbab89bf1ac 100644 --- a/compiler/rustc_borrowck/src/type_check/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/mod.rs @@ -24,6 +24,7 @@ use rustc_middle::mir::*; use rustc_middle::traits::query::NoSolution; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::CastTy; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt, UserArgs, UserTypeAnnotationIndex, fold_regions, diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs index 506037c151148..638463b5cb438 100644 --- a/compiler/rustc_codegen_cranelift/src/base.rs +++ b/compiler/rustc_codegen_cranelift/src/base.rs @@ -12,6 +12,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_index::IndexVec; use rustc_middle::ty::TypeVisitableExt; use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{FnAbiOf, HasTypingEnv as _}; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_session::config::OutputFilenames; diff --git a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs index 18a0632a0939d..2eb4725fc5b20 100644 --- a/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs +++ b/compiler/rustc_codegen_cranelift/src/debuginfo/types.rs @@ -3,6 +3,7 @@ use gimli::write::{AttributeValue, UnitEntryId}; use rustc_codegen_ssa::debuginfo::type_names; use rustc_data_structures::fx::FxHashMap; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::{self, Ty, TyCtxt}; diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs index 270ea4e88a999..f04c32a70390a 100644 --- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs +++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs @@ -3,6 +3,7 @@ use cranelift_codegen::ir::immediates::Offset32; use rustc_abi::Endian; use rustc_middle::ty::SimdAlign; +use rustc_middle::ty::consts::ConstExt; use super::*; use crate::prelude::*; diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs index 48fb0f6c7d4a8..efc89075cdeb2 100644 --- a/compiler/rustc_codegen_cranelift/src/unsize.rs +++ b/compiler/rustc_codegen_cranelift/src/unsize.rs @@ -3,6 +3,7 @@ //! [`PointerCoercion::Unsize`]: `rustc_middle::ty::adjustment::PointerCoercion::Unsize` use rustc_codegen_ssa::base::validate_trivial_unsize; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::print::{with_no_trimmed_paths, with_no_visible_paths}; diff --git a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs index bb32a85f193ea..54013b6be6173 100644 --- a/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs +++ b/compiler/rustc_codegen_gcc/src/intrinsic/simd.rs @@ -15,6 +15,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, LayoutTy #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_span::{ErrorGuaranteed, Span, Symbol, span_bug, sym}; diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs index 735dd0fbaba10..a3bcce34566cb 100644 --- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs +++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs @@ -10,6 +10,7 @@ use rustc_codegen_ssa::debuginfo::type_names::{VTableNameKind, cpp_like_debuginf use rustc_codegen_ssa::traits::*; use rustc_hir::def::{CtorKind, DefKind}; use rustc_hir::def_id::{DefId, LOCAL_CRATE}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{ HasTypingEnv, LayoutOf, TyAndLayout, WIDE_PTR_ADDR, WIDE_PTR_EXTRA, }; diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs index 2e01ebca05c26..454347a5e041e 100644 --- a/compiler/rustc_codegen_llvm/src/intrinsic.rs +++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs @@ -19,6 +19,7 @@ use rustc_hir::def_id::LOCAL_CRATE; use rustc_hir::find_attr; use rustc_lint_defs::builtin::DEPRECATED_LLVM_INTRINSIC; use rustc_middle::mir::BinOp; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{FnAbiOf, HasTyCtxt, HasTypingEnv, LayoutOf}; use rustc_middle::ty::offload_meta::OffloadMetadata; use rustc_middle::ty::{self, GenericArgsRef, Instance, SimdAlign, Ty, TyCtxt, TypingEnv}; diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs index de921a9cb0d1e..e054394ccade0 100644 --- a/compiler/rustc_codegen_ssa/src/base.rs +++ b/compiler/rustc_codegen_ssa/src/base.rs @@ -26,6 +26,7 @@ use rustc_middle::mir::interpret::{CTFE_ALLOC_SALT, ErrorHandled, Scalar}; use rustc_middle::mir::{BinOp, ConstValue}; use rustc_middle::mono::{CodegenUnit, CodegenUnitNameBuilder, MonoItem, MonoItemPartitions}; use rustc_middle::query::Providers; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, PatternKind, Ty, TyCtxt, UintTy, Unnormalized}; use rustc_session::config::{self, EntryFnType}; diff --git a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs index 810253956b186..9cf68c6e3909c 100644 --- a/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs +++ b/compiler/rustc_codegen_ssa/src/debuginfo/type_names.rs @@ -20,6 +20,7 @@ use rustc_hashes::Hash64; use rustc_hir::def_id::DefId; use rustc_hir::definitions::{DefPathData, DefPathDataName, DisambiguatedDefPathData}; use rustc_hir::{CoroutineDesugaring, CoroutineKind, CoroutineSource, Mutability}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{ self, ExistentialProjection, GenericArgKind, GenericArgsRef, Ty, TyCtxt, Unnormalized, diff --git a/compiler/rustc_codegen_ssa/src/mir/constant.rs b/compiler/rustc_codegen_ssa/src/mir/constant.rs index 625e1dd8491db..b6f16f72b021e 100644 --- a/compiler/rustc_codegen_ssa/src/mir/constant.rs +++ b/compiler/rustc_codegen_ssa/src/mir/constant.rs @@ -1,6 +1,7 @@ use rustc_abi::BackendRepr; use rustc_middle::mir; use rustc_middle::mir::interpret::ErrorHandled; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv}; use rustc_middle::ty::{self, Ty}; use rustc_span::{bug, span_bug}; diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs index 22ab228e15b5f..e6b70ce2ca77b 100644 --- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs +++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs @@ -1,5 +1,6 @@ use rustc_abi::{Align, FieldIdx, WrappingRange}; use rustc_middle::mir::SourceInfo; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_session::config::OptLevel; use rustc_span::{ErrorGuaranteed, bug, span_bug, sym}; diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs index 5b07eb84f40d7..d11ba53e58c89 100644 --- a/compiler/rustc_codegen_ssa/src/mir/operand.rs +++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs @@ -8,6 +8,7 @@ use rustc_abi::{ use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::mir::interpret::{Pointer, Scalar, alloc_range}; use rustc_middle::mir::{self, ConstValue}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Ty}; use rustc_session::config::{AnnotateMoves, DebugInfo, OptLevel}; diff --git a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs index 130958f3705c9..3b33cf5a17602 100644 --- a/compiler/rustc_codegen_ssa/src/mir/rvalue.rs +++ b/compiler/rustc_codegen_ssa/src/mir/rvalue.rs @@ -5,6 +5,7 @@ use rustc_abi::{self as abi, BackendRepr, FIRST_VARIANT}; use rustc_index::IndexVec; use rustc_middle::mir; use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, LayoutOf, TyAndLayout}; use rustc_middle::ty::{self, Instance, Mutability, Ty, TyCtxt}; use rustc_session::config::OptLevel; diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs index d176ee1628cb5..c0617c19263e7 100644 --- a/compiler/rustc_const_eval/src/const_eval/machine.rs +++ b/compiler/rustc_const_eval/src/const_eval/machine.rs @@ -13,6 +13,7 @@ use rustc_middle::mir; use rustc_middle::mir::AssertMessage; use rustc_middle::mir::interpret::ReportedErrorInfo; use rustc_middle::query::TyCtxtAt; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, HasTypingEnv, TyAndLayout, ValidityRequirement}; use rustc_middle::ty::{self, FieldInfo, ScalarInt, Ty, TyCtxt}; use rustc_span::{Span, Symbol, bug, span_bug, sym}; diff --git a/compiler/rustc_const_eval/src/const_eval/mod.rs b/compiler/rustc_const_eval/src/const_eval/mod.rs index 58b8418707eff..1a08c166770cf 100644 --- a/compiler/rustc_const_eval/src/const_eval/mod.rs +++ b/compiler/rustc_const_eval/src/const_eval/mod.rs @@ -2,6 +2,7 @@ use rustc_abi::{FieldIdx, VariantIdx}; use rustc_middle::mir; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, bug}; use tracing::instrument; diff --git a/compiler/rustc_const_eval/src/const_eval/valtrees.rs b/compiler/rustc_const_eval/src/const_eval/valtrees.rs index de8dd989c6a00..6cb327f1efca6 100644 --- a/compiler/rustc_const_eval/src/const_eval/valtrees.rs +++ b/compiler/rustc_const_eval/src/const_eval/valtrees.rs @@ -3,6 +3,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet}; use rustc_middle::mir; use rustc_middle::mir::interpret::{EvalToValTreeResult, GlobalId, ValTreeCreationError}; use rustc_middle::traits::ObligationCause; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutCx, TyAndLayout}; use rustc_middle::ty::{self, Ty, TyCtxt}; use rustc_span::{DUMMY_SP, bug}; diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs index 79a3887d5123d..1f16aab095843 100644 --- a/compiler/rustc_const_eval/src/interpret/cast.rs +++ b/compiler/rustc_const_eval/src/interpret/cast.rs @@ -6,6 +6,7 @@ use rustc_apfloat::{Float, FloatConvert}; use rustc_middle::mir::CastKind; use rustc_middle::mir::interpret::{InterpResult, PointerArithmetic, Scalar}; use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{IntegerExt, TyAndLayout}; use rustc_middle::ty::{self, FloatTy, Ty}; use rustc_span::{bug, span_bug}; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs index 48218703c8ec1..3c45550016851 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/atomic.rs @@ -1,4 +1,5 @@ use rustc_middle::mir::BinOp; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::{mir, ty}; use rustc_span::{Symbol, span_bug, sym}; use tracing::trace; diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs index 476ba405f19ca..ad191e9b4d763 100644 --- a/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs +++ b/compiler/rustc_const_eval/src/interpret/intrinsics/simd.rs @@ -3,6 +3,7 @@ use rustc_abi::{BackendRepr, Endian}; use rustc_apfloat::ieee::{Double, Half, Quad, Single}; use rustc_apfloat::{Float, Round}; use rustc_middle::mir::interpret::{InterpErrorKind, Pointer, UndefinedBehaviorInfo}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{FloatTy, ScalarInt, SimdAlign}; use rustc_middle::{err_ub_format, mir, throw_unsup_format, ty}; use rustc_span::{Symbol, bug, span_bug, sym}; diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs index 788b063bd0ecf..924041c399ef1 100644 --- a/compiler/rustc_hir_analysis/src/check/check.rs +++ b/compiler/rustc_hir_analysis/src/check/check.rs @@ -19,6 +19,7 @@ use rustc_macros::Diagnostic; use rustc_middle::hir::nested_filter; use rustc_middle::middle::resolve_bound_vars::ResolvedArg; use rustc_middle::middle::stability::EvalResult; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::TypeErrorToStringExt; use rustc_middle::ty::layout::LayoutError; use rustc_middle::ty::util::Discr; diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs index cca93e8aef0ec..b566f6b04bf41 100644 --- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs +++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs @@ -4,6 +4,7 @@ use rustc_errors::DiagMessage; use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_middle::traits::{ObligationCause, ObligationCauseCode}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Const, Ty, TyCtxt}; use rustc_span::def_id::LocalDefId; use rustc_span::{Span, Symbol, sym}; diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs index 6bb1c4d04e065..e7ecde09ce27b 100644 --- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs +++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs @@ -42,6 +42,7 @@ use rustc_infer::traits::DynCompatibilityViolation; use rustc_lint_defs::builtin::AMBIGUOUS_ASSOCIATED_ITEMS; use rustc_macros::{TypeFoldable, TypeVisitable}; use rustc_middle::middle::stability::AllowUnstable; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, Const, FnSigKind, GenericArgKind, GenericArgsRef, GenericParamDefKind, LitToConstInput, Ty, TyCtxt, TypeSuperFoldable, TypeVisitableExt, TypingMode, Unnormalized, Upcast, diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs index d191fdbdc1ec0..04e55dd0fdd95 100644 --- a/compiler/rustc_hir_typeck/src/expr.rs +++ b/compiler/rustc_hir_typeck/src/expr.rs @@ -26,6 +26,7 @@ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer as _; use rustc_infer::infer::{self, DefineOpaqueTypes, InferOk, RegionVariableOrigin}; use rustc_infer::traits::query::NoSolution; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AllowTwoPhase}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{self, AdtKind, GenericArgsRef, Ty, TypeVisitableExt, Unnormalized}; use rustc_session::diagnostics::feature_err; diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs index 8895faef0890f..7f8edae4f17c3 100644 --- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs +++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs @@ -18,6 +18,7 @@ use rustc_hir::{ use rustc_hir_analysis::hir_ty_lowering::HirTyLowerer; use rustc_hir_analysis::suggest_impl_trait; use rustc_middle::middle::stability::EvalResult; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::{with_no_trimmed_paths, with_types_for_suggestion}; use rustc_middle::ty::{ self, Article, Binder, IsSuggestable, Ty, TyCtxt, TypeVisitableExt, Unnormalized, Upcast, diff --git a/compiler/rustc_hir_typeck/src/inline_asm.rs b/compiler/rustc_hir_typeck/src/inline_asm.rs index 6470e45b3bb3a..52f3957d6f512 100644 --- a/compiler/rustc_hir_typeck/src/inline_asm.rs +++ b/compiler/rustc_hir_typeck/src/inline_asm.rs @@ -6,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def_id::DefId; use rustc_lint_defs::builtin::ASM_SUB_REGISTER; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, Article, FloatTy, IntTy, Ty, TyCtxt, TypeVisitableExt, UintTy, Unnormalized, }; diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs index 6852ea635e924..298ea7da5d0e3 100644 --- a/compiler/rustc_hir_typeck/src/pat.rs +++ b/compiler/rustc_hir_typeck/src/pat.rs @@ -21,6 +21,7 @@ use rustc_hir_analysis::autoderef::report_autoderef_recursion_limit_error; use rustc_infer::infer::RegionVariableOrigin; use rustc_lint_defs::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS; use rustc_middle::traits::PatternOriginExpr; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Pinnedness, Ty, TypeVisitableExt, Unnormalized}; use rustc_session::diagnostics::feature_err; use rustc_span::edit_distance::find_best_match_for_name; diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs index bb5f535f51466..b714940e4c331 100644 --- a/compiler/rustc_lint/src/builtin.rs +++ b/compiler/rustc_lint/src/builtin.rs @@ -33,6 +33,7 @@ use rustc_hir::{self as hir, Body, FnDecl, ImplItemImplKind, PatKind, PredicateO // Lints from rustc_lint_defs pub use rustc_lint_defs::builtin::*; use rustc_lint_defs::{declare_lint, declare_lint_pass, fcw, impl_lint_pass}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::LayoutOf; use rustc_middle::ty::print::with_no_trimmed_paths; use rustc_middle::ty::{ diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs index 4d741e06198b5..d62fca02cf4cf 100644 --- a/compiler/rustc_lint/src/types.rs +++ b/compiler/rustc_lint/src/types.rs @@ -6,6 +6,7 @@ use rustc_hir as hir; use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::{Expr, ExprKind, HirId, find_attr}; use rustc_lint_defs::{declare_lint, declare_lint_pass, impl_lint_pass}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutOf, SizeSkeleton}; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; use rustc_span::{DUMMY_SP, Span, Symbol, bug, sym}; diff --git a/compiler/rustc_lint/src/unused/must_use.rs b/compiler/rustc_lint/src/unused/must_use.rs index 981d9df9c0f29..a637e8cf3b0f4 100644 --- a/compiler/rustc_lint/src/unused/must_use.rs +++ b/compiler/rustc_lint/src/unused/must_use.rs @@ -7,6 +7,7 @@ use rustc_hir::def_id::DefId; use rustc_hir::{self as hir, find_attr}; use rustc_infer::traits::util::elaborate; use rustc_lint_defs::{declare_lint, declare_lint_pass}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, Unnormalized}; use rustc_span::{Span, Symbol, sym}; use tracing::instrument; diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs index 83f62ee65025c..0acfe437493c0 100644 --- a/compiler/rustc_middle/src/mir/consts.rs +++ b/compiler/rustc_middle/src/mir/consts.rs @@ -10,6 +10,7 @@ use rustc_type_ir::TypeVisitableExt; use super::interpret::ReportedErrorInfo; use crate::mir::interpret::{AllocId, AllocRange, ErrorHandled, GlobalAlloc, Scalar, alloc_range}; use crate::mir::{Promoted, pretty_print_const_value}; +use crate::ty::consts::ConstExt; use crate::ty::print::{pretty_print_const, with_no_trimmed_paths}; use crate::ty::{self, ConstKind, GenericArgsRef, ScalarInt, Ty, TyCtxt}; diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs index 870819d7a2b93..159a0f9883db3 100644 --- a/compiler/rustc_middle/src/mir/pretty.rs +++ b/compiler/rustc_middle/src/mir/pretty.rs @@ -18,6 +18,7 @@ use crate::mir::interpret::{ use crate::mir::visit::Visitor; use crate::mir::*; use crate::ty::CoroutineArgsExt; +use crate::ty::consts::ConstExt; const INDENT: &str = " "; /// Alignment for lining up comments following MIR statements diff --git a/compiler/rustc_middle/src/mir/statement.rs b/compiler/rustc_middle/src/mir/statement.rs index 22366f70fbe4e..b6542fb328aac 100644 --- a/compiler/rustc_middle/src/mir/statement.rs +++ b/compiler/rustc_middle/src/mir/statement.rs @@ -10,6 +10,7 @@ use tracing::instrument; use super::interpret::GlobalAlloc; use super::*; +use crate::ty::consts::ConstExt; use crate::ty::{CoroutineArgsExt, Unnormalized}; /////////////////////////////////////////////////////////////////////////// diff --git a/compiler/rustc_middle/src/ty/consts/valtree.rs b/compiler/rustc_middle/src/ty/consts/valtree.rs index 9c4700b41d1ff..28e32a4a82d0d 100644 --- a/compiler/rustc_middle/src/ty/consts/valtree.rs +++ b/compiler/rustc_middle/src/ty/consts/valtree.rs @@ -11,6 +11,7 @@ use rustc_span::bug; use super::ScalarInt; use crate::mir::interpret::{ErrorHandled, Scalar}; +use crate::ty::consts::ConstExt; use crate::ty::print::{FmtPrinter, PrettyPrinter}; use crate::ty::{self, Ty, TyCtxt, ValTreeKind}; diff --git a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs index 6b0234c971830..61e3a40e363d9 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/inhabited_predicate.rs @@ -4,6 +4,7 @@ use rustc_span::def_id::{LocalModId, ModId}; use smallvec::SmallVec; use tracing::instrument; +use crate::ty::consts::ConstExt; use crate::ty::{self, OpaqueTypeKey, Ty, TyCtxt, TypingEnv, Unnormalized}; /// Represents whether some type is inhabited in a given context. diff --git a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs index 60ea2bf49a046..078a171491520 100644 --- a/compiler/rustc_middle/src/ty/inhabitedness/mod.rs +++ b/compiler/rustc_middle/src/ty/inhabitedness/mod.rs @@ -53,6 +53,7 @@ use rustc_type_ir::TyKind::*; use tracing::instrument; use crate::query::Providers; +use crate::ty::consts::ConstExt; use crate::ty::{ self, AdtDef, DefId, Ty, TyCtxt, TypeVisitableExt, TypingEnv, VariantDef, Visibility, }; diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs index f717f8270daf3..1e4e96ceed576 100644 --- a/compiler/rustc_middle/src/ty/layout.rs +++ b/compiler/rustc_middle/src/ty/layout.rs @@ -21,6 +21,7 @@ use tracing::debug; use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::query::TyCtxtAt; use crate::traits::ObligationCause; +use crate::ty::consts::ConstExt; use crate::ty::normalize_erasing_regions::NormalizationError; use crate::ty::{self, CoroutineArgsExt, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; diff --git a/compiler/rustc_middle/src/ty/pattern.rs b/compiler/rustc_middle/src/ty/pattern.rs index 2d73124265fc2..71d3bf0853f04 100644 --- a/compiler/rustc_middle/src/ty/pattern.rs +++ b/compiler/rustc_middle/src/ty/pattern.rs @@ -7,6 +7,7 @@ use rustc_type_ir::{self as ir, FlagComputation, Flags}; use super::TyCtxt; use crate::ty; +use crate::ty::consts::ConstExt; pub type PatternKind<'tcx> = ir::PatternKind>; diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs index f4b1f0ce0881d..fe569bf282d36 100644 --- a/compiler/rustc_middle/src/ty/sty.rs +++ b/compiler/rustc_middle/src/ty/sty.rs @@ -27,6 +27,7 @@ use super::{AdtFlags, GenericParamDefKind}; use crate::infer::canonical::Canonical; use crate::traits::ObligationCause; use crate::ty::InferTy::*; +use crate::ty::consts::ConstExt; use crate::ty::{ self, AdtDef, Const, Discr, GenericArg, GenericArgs, GenericArgsRef, List, ParamEnv, Region, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor, UintTy, ValTree, diff --git a/compiler/rustc_middle/src/ty/typetree.rs b/compiler/rustc_middle/src/ty/typetree.rs index c2479e0c62bca..54cbc591c5fb3 100644 --- a/compiler/rustc_middle/src/ty/typetree.rs +++ b/compiler/rustc_middle/src/ty/typetree.rs @@ -2,6 +2,7 @@ use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree}; use rustc_span::bug; use tracing::trace; +use crate::ty::consts::ConstExt; use crate::ty::context::TyCtxt; use crate::ty::{self, Ty}; diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs index db983038e1af9..a66d15299f16c 100644 --- a/compiler/rustc_middle/src/ty/util.rs +++ b/compiler/rustc_middle/src/ty/util.rs @@ -25,6 +25,7 @@ use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags; use crate::mir; use crate::query::Providers; use crate::traits::ObligationCause; +use crate::ty::consts::ConstExt; use crate::ty::layout::{FloatExt, IntegerExt}; use crate::ty::{ self, Asyncness, FallibleTypeFolder, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeFoldable, diff --git a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs index 695684452fc56..09c76d6beb4a1 100644 --- a/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs +++ b/compiler/rustc_mir_build/src/builder/expr/as_rvalue.rs @@ -8,6 +8,7 @@ use rustc_middle::mir::*; use rustc_middle::thir::*; use rustc_middle::ty::adjustment::PointerCoercion; use rustc_middle::ty::cast::{CastTy, mir_cast_kind}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::util::IntTypeExt; use rustc_middle::ty::{self, Ty, UpvarArgs}; use rustc_span::{DUMMY_SP, Span, Spanned, bug}; diff --git a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs index 392712619a3f2..57ffee758b325 100644 --- a/compiler/rustc_mir_build/src/builder/matches/match_pair.rs +++ b/compiler/rustc_mir_build/src/builder/matches/match_pair.rs @@ -3,6 +3,7 @@ use std::sync::Arc; use rustc_abi::FieldIdx; use rustc_middle::mir::{Pinnedness, Place, PlaceElem, ProjectionElem}; use rustc_middle::thir::{Ascription, DerefPatBorrowMode, FieldPat, Pat, PatKind}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TypeVisitableExt}; use rustc_span::{Span, span_bug}; diff --git a/compiler/rustc_mir_build/src/builder/matches/mod.rs b/compiler/rustc_mir_build/src/builder/matches/mod.rs index 6034d657a005e..f9c399797a400 100644 --- a/compiler/rustc_mir_build/src/builder/matches/mod.rs +++ b/compiler/rustc_mir_build/src/builder/matches/mod.rs @@ -17,6 +17,7 @@ use rustc_hir::{BindingMode, ByRef, LetStmt, LocalSource, Node}; use rustc_middle::middle::region::{self, TempLifetime}; use rustc_middle::mir::*; use rustc_middle::thir::{self, *}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, CanonicalUserTypeAnnotation, Ty, ValTree, ValTreeKind}; use rustc_pattern_analysis::constructor::RangeEnd; use rustc_pattern_analysis::rustc::{DeconstructedPat, RustcPatCtxt}; diff --git a/compiler/rustc_mir_build/src/builder/scope.rs b/compiler/rustc_mir_build/src/builder/scope.rs index 872ffec45f30a..4b3c224a84357 100644 --- a/compiler/rustc_mir_build/src/builder/scope.rs +++ b/compiler/rustc_mir_build/src/builder/scope.rs @@ -91,6 +91,7 @@ use rustc_lint_defs::Level; use rustc_middle::middle::region; use rustc_middle::mir::{self, *}; use rustc_middle::thir::{AdtExpr, AdtExprBase, ArmId, ExprId, ExprKind}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, ValTree}; use rustc_pattern_analysis::rustc::RustcPatCtxt; use rustc_span::{DUMMY_SP, Span, Spanned, bug, span_bug}; diff --git a/compiler/rustc_mir_build/src/thir/constant.rs b/compiler/rustc_mir_build/src/thir/constant.rs index 667eff50a0d32..fa2b149f71926 100644 --- a/compiler/rustc_mir_build/src/thir/constant.rs +++ b/compiler/rustc_mir_build/src/thir/constant.rs @@ -1,6 +1,7 @@ use rustc_abi::Size; use rustc_ast::{self as ast, UintTy}; use rustc_hir::attrs::lang_items::LangItem; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, LitToConstInput, ScalarInt, Ty, TyCtxt, TypeVisitableExt as _}; use rustc_span::bug; use tracing::trace; diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs index df39350bd5c8c..3aec71f400de3 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs @@ -12,6 +12,7 @@ use rustc_infer::infer::TyCtxtInferExt; use rustc_infer::traits::Obligation; use rustc_middle::mir::interpret::ErrorHandled; use rustc_middle::thir::{FieldPat, Pat, PatKind}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{ self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitableExt, TypeVisitor, Unnormalized, }; diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs index 5b7a4d626aae3..f5e44d768faa1 100644 --- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs +++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs @@ -19,6 +19,7 @@ use rustc_middle::thir::{ Ascription, FieldPat, LocalVarId, Pat, PatKind, PatRange, PatRangeBoundary, }; use rustc_middle::ty::adjustment::{PatAdjust, PatAdjustment}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, CanonicalUserTypeAnnotation, LitToConstInput, Ty, TyCtxt, const_lit_matches_ty, diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs index f22ce4079e58c..3c1c631285f96 100644 --- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs +++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs @@ -2,6 +2,7 @@ use std::mem; use rustc_index::IndexVec; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{bug, span_bug}; use smallvec::{SmallVec, smallvec}; diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index a06ae343123d1..0ae39b1507b6a 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -33,6 +33,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_infer::traits::TraitErrors; use rustc_lint_defs::builtin::MUST_NOT_SUSPEND; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, CoroutineArgs, CoroutineArgsExt, Ty, TyCtxt, TypingMode}; use rustc_mir_dataflow::impls::{ MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive, diff --git a/compiler/rustc_mir_transform/src/elaborate_drop.rs b/compiler/rustc_mir_transform/src/elaborate_drop.rs index d9d9914d02bd4..0786d0cf42ba4 100644 --- a/compiler/rustc_mir_transform/src/elaborate_drop.rs +++ b/compiler/rustc_mir_transform/src/elaborate_drop.rs @@ -8,6 +8,7 @@ use rustc_hir::{CoroutineDesugaring, CoroutineKind}; use rustc_index::Idx; use rustc_middle::mir::*; use rustc_middle::ty::adjustment::PointerCoercion; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::util::{Discr, IntTypeExt}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt}; use rustc_mir_dataflow::DropFlagState; diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs index 78881d37a093b..81a41be1c62da 100644 --- a/compiler/rustc_mir_transform/src/gvn.rs +++ b/compiler/rustc_mir_transform/src/gvn.rs @@ -114,6 +114,7 @@ use rustc_index::{IndexVec, newtype_index}; use rustc_middle::mir::interpret::{AllocRange, GlobalAlloc}; use rustc_middle::mir::visit::*; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::HasTypingEnv; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt, Unnormalized}; use rustc_mir_dataflow::{Analysis, ResultsCursor}; diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs index b3b3dd1241a71..9a39bd8d75d24 100644 --- a/compiler/rustc_mir_transform/src/instsimplify.rs +++ b/compiler/rustc_mir_transform/src/instsimplify.rs @@ -6,6 +6,7 @@ use rustc_hir::find_attr; use rustc_index::IndexVec; use rustc_middle::mir::visit::MutVisitor; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{IntegerExt, ValidityRequirement}; use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, layout}; use rustc_span::{Symbol, bug, sym}; diff --git a/compiler/rustc_mir_transform/src/known_panics_lint.rs b/compiler/rustc_mir_transform/src/known_panics_lint.rs index fc210ecebfa48..1c598af1af98e 100644 --- a/compiler/rustc_mir_transform/src/known_panics_lint.rs +++ b/compiler/rustc_mir_transform/src/known_panics_lint.rs @@ -15,6 +15,7 @@ use rustc_index::bit_set::DenseBitSet; use rustc_lint_defs::builtin::UNCONDITIONAL_PANIC; use rustc_middle::mir::visit::{MutatingUseContext, NonMutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{LayoutError, LayoutOf, LayoutOfHelpers, TyAndLayout}; use rustc_middle::ty::{ self, ConstInt, GenericArgKind, GenericParamDefKind, ScalarInt, Ty, TyCtxt, TypeVisitableExt, diff --git a/compiler/rustc_mir_transform/src/promote_consts.rs b/compiler/rustc_mir_transform/src/promote_consts.rs index b749d6d36cf84..43d058c7eef0c 100644 --- a/compiler/rustc_mir_transform/src/promote_consts.rs +++ b/compiler/rustc_mir_transform/src/promote_consts.rs @@ -23,6 +23,7 @@ use rustc_index::{IndexSlice, IndexVec}; use rustc_middle::mir; use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor}; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, GenericArgs, List, Ty, TyCtxt, TypeVisitableExt}; use rustc_span::{Span, Spanned, bug, span_bug}; use tracing::{debug, instrument}; diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs index 09379fc252072..98f4009c15665 100644 --- a/compiler/rustc_mir_transform/src/remove_zsts.rs +++ b/compiler/rustc_mir_transform/src/remove_zsts.rs @@ -2,6 +2,7 @@ use rustc_middle::mir::visit::*; use rustc_middle::mir::*; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty, TyCtxt}; use crate::PassPolicy; diff --git a/compiler/rustc_pattern_analysis/src/rustc.rs b/compiler/rustc_pattern_analysis/src/rustc.rs index 5e6b682626210..581f1061bb80c 100644 --- a/compiler/rustc_pattern_analysis/src/rustc.rs +++ b/compiler/rustc_pattern_analysis/src/rustc.rs @@ -9,6 +9,7 @@ use rustc_index::{Idx, IndexVec}; use rustc_lint_defs::builtin::{NON_CONTIGUOUS_RANGE_ENDPOINTS, OVERLAPPING_RANGE_ENDPOINTS}; use rustc_middle::middle::stability::EvalResult; use rustc_middle::thir::{self, Pat, PatKind, PatRange, PatRangeBoundary}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, FieldDef, OpaqueTypeKey, ScalarInt, Ty, TyCtxt, TypeVisitableExt, VariantDef, diff --git a/compiler/rustc_public_bridge/src/context/impls.rs b/compiler/rustc_public_bridge/src/context/impls.rs index 70e2498ac350b..c653aac541c2a 100644 --- a/compiler/rustc_public_bridge/src/context/impls.rs +++ b/compiler/rustc_public_bridge/src/context/impls.rs @@ -11,6 +11,7 @@ use rustc_hir::attrs::lang_items::LangItem; use rustc_hir::def::DefKind; use rustc_middle::mir::interpret::{AllocId, ConstAllocation, ErrorHandled, GlobalAlloc, Scalar}; use rustc_middle::mir::{BinOp, Body, Const as MirConst, ConstValue, UnOp}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{FnAbiOf, LayoutOf}; use rustc_middle::ty::print::{ with_forced_trimmed_paths, with_no_trimmed_paths, with_resolve_crate_name, diff --git a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs index c487914bc362f..0b3beb329e0f8 100644 --- a/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs +++ b/compiler/rustc_sanitizers/src/cfi/typeid/itanium_cxx_abi/encode.rs @@ -12,6 +12,7 @@ use rustc_data_structures::base_n::{ALPHANUMERIC_ONLY, CASE_INSENSITIVE, ToBaseN use rustc_data_structures::fx::FxHashMap; use rustc_hir as hir; use rustc_hir::find_attr; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::{ self, Const, ExistentialPredicate, FloatTy, FnSig, GenericArg, GenericArgKind, GenericArgsRef, diff --git a/compiler/rustc_symbol_mangling/src/legacy.rs b/compiler/rustc_symbol_mangling/src/legacy.rs index e2be87e6b271f..bebfd746e1f6b 100644 --- a/compiler/rustc_symbol_mangling/src/legacy.rs +++ b/compiler/rustc_symbol_mangling/src/legacy.rs @@ -5,6 +5,7 @@ use rustc_data_structures::stable_hash::{StableHash, StableHasher}; use rustc_hashes::Hash64; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::{PrettyPrinter, Print, PrintError, Printer}; use rustc_middle::ty::{ self, GenericArg, GenericArgKind, Instance, ReifyReason, Ty, TyCtxt, TypeVisitableExt, diff --git a/compiler/rustc_symbol_mangling/src/v0.rs b/compiler/rustc_symbol_mangling/src/v0.rs index e0d9d6976bd14..fb9f242f60085 100644 --- a/compiler/rustc_symbol_mangling/src/v0.rs +++ b/compiler/rustc_symbol_mangling/src/v0.rs @@ -14,6 +14,7 @@ use rustc_hir as hir; use rustc_hir::def::CtorKind; use rustc_hir::def_id::{CrateNum, DefId}; use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::IntegerExt; use rustc_middle::ty::print::{Print, PrintError, Printer}; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs index 76edf906bca94..f554620c57208 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs @@ -60,6 +60,7 @@ use rustc_hir::{self as hir, find_attr}; use rustc_infer::infer::DefineOpaqueTypes; use rustc_macros::extension; use rustc_middle::traits::PatternOriginExpr; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError, TypeErrorToStringExt}; use rustc_middle::ty::print::{PrintTraitRefExt as _, WrapBinderMode, with_forced_trimmed_paths}; use rustc_middle::ty::{ diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs index 62ac12a8edd24..261dc5594bd24 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs @@ -11,6 +11,7 @@ use rustc_infer::traits::util::elaborate; use rustc_infer::traits::{ Obligation, ObligationCause, ObligationCauseCode, PolyTraitObligation, PredicateObligation, }; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::PrintPolyTraitClauseExt; use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitable as _, TypeVisitableExt as _, Unnormalized}; use rustc_session::diagnostics::feature_err_unstable_feature_bound; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs index 5090e36af9d8a..bc5bf38ec9266 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs @@ -24,6 +24,7 @@ use rustc_infer::traits::{ImplSource, TraitErrors}; use rustc_middle::traits::SignatureMismatchData; use rustc_middle::traits::select::OverflowError; use rustc_middle::ty::abstract_const::NotConstEvaluatable; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::print::{ PrintPolyTraitClauseExt, PrintPolyTraitRefExt as _, PrintTraitClauseExt as _, diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs index ed22d4f4ef246..2967dfb64e710 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs @@ -4,6 +4,7 @@ use rustc_hir as hir; use rustc_hir::attrs::diagnostic::{CustomDiagnostic, FilterOptions, FormatArgs}; use rustc_hir::def_id::LocalDefId; use rustc_hir::find_attr; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::print::PrintTraitRefExt; use rustc_middle::ty::{self, GenericParamDef, GenericParamDefKind}; use rustc_span::Symbol; diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs index 5e9288fc7a592..47652c22a7ebc 100644 --- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs +++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs @@ -24,6 +24,7 @@ use rustc_infer::traits::ImplSource; use rustc_middle::middle::privacy::Level; use rustc_middle::traits::IsConstable; use rustc_middle::ty::adjustment::{Adjust, DerefAdjustKind}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::TypeError; use rustc_middle::ty::print::{ PrintPolyTraitClauseExt as _, PrintPolyTraitRefExt, PrintTraitClauseExt as _, diff --git a/compiler/rustc_trait_selection/src/traits/fulfill.rs b/compiler/rustc_trait_selection/src/traits/fulfill.rs index f5a4ec9ae0494..aae323ae1671f 100644 --- a/compiler/rustc_trait_selection/src/traits/fulfill.rs +++ b/compiler/rustc_trait_selection/src/traits/fulfill.rs @@ -11,6 +11,7 @@ use rustc_infer::traits::{ TraitEngine, TraitErrors, }; use rustc_middle::ty::abstract_const::NotConstEvaluatable; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, Binder, Const, DelayedSet, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs index aa676dab91bbc..8ad7fd4ac3a69 100644 --- a/compiler/rustc_trait_selection/src/traits/mod.rs +++ b/compiler/rustc_trait_selection/src/traits/mod.rs @@ -30,6 +30,7 @@ use rustc_errors::ErrorGuaranteed; pub use rustc_infer::traits::*; use rustc_macros::TypeVisitable; use rustc_middle::query::Providers; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::error::{ExpectedFound, TypeError}; use rustc_middle::ty::{ self, BottomUpFolder, Clause, GenericArgs, GenericArgsRef, Ty, TyCtxt, TypeFoldable, diff --git a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs index e9e1cea48ba20..31d2e8620af90 100644 --- a/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs +++ b/compiler/rustc_trait_selection/src/traits/query/dropck_outlives.rs @@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet; use rustc_infer::traits::TraitErrors; use rustc_infer::traits::query::type_op::DropckOutlives; use rustc_middle::traits::query::{DropckConstraint, DropckOutlivesResult}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, EarlyBinder, ParamEnvAnd, Ty, TyCtxt, Unnormalized}; use rustc_span::Span; use thin_vec::ThinVec; diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs index e2e1b0a08e15a..53287dbe331ee 100644 --- a/compiler/rustc_transmute/src/lib.rs +++ b/compiler/rustc_transmute/src/lib.rs @@ -104,6 +104,7 @@ pub enum Reason { #[cfg(feature = "rustc")] mod rustc { use rustc_hir::attrs::lang_items::LangItem; + use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{Const, Region, Ty, TyCtxt}; use super::*; diff --git a/compiler/rustc_ty_utils/src/consts.rs b/compiler/rustc_ty_utils/src/consts.rs index 0507265ded631..79369e5715d21 100644 --- a/compiler/rustc_ty_utils/src/consts.rs +++ b/compiler/rustc_ty_utils/src/consts.rs @@ -5,6 +5,7 @@ use rustc_middle::query::Providers; use rustc_middle::thir::visit; use rustc_middle::thir::visit::Visitor; use rustc_middle::ty::abstract_const::CastKind; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Expr, LitToConstInput, TyCtxt, TypeVisitableExt}; use rustc_middle::{mir, thir}; use rustc_span::{Span, bug}; From 46d8bca83e4cf09bc298e900d21ae9c46c062c62 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:40 +0100 Subject: [PATCH 0623/1309] `use ConstExt` for methods that do not yet exist in `rustc_type_ir` --- src/intrinsic/simd.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/intrinsic/simd.rs b/src/intrinsic/simd.rs index bb32a85f193ea..54013b6be6173 100644 --- a/src/intrinsic/simd.rs +++ b/src/intrinsic/simd.rs @@ -15,6 +15,7 @@ use rustc_codegen_ssa::traits::{BaseTypeCodegenMethods, BuilderMethods, LayoutTy #[cfg(feature = "master")] use rustc_hir as hir; use rustc_middle::mir::BinOp; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf}; use rustc_middle::ty::{self, Ty}; use rustc_span::{ErrorGuaranteed, Span, Symbol, span_bug, sym}; From c58247047226f8d8bff9b92afbcdea50a68466aa Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:40 +0100 Subject: [PATCH 0624/1309] Use `ConstExt` in clippy --- src/tools/clippy/clippy_lints/src/indexing_slicing.rs | 1 + src/tools/clippy/clippy_lints/src/large_const_arrays.rs | 1 + src/tools/clippy/clippy_lints/src/large_stack_arrays.rs | 1 + src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs | 1 + src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs | 1 + src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs | 1 + src/tools/clippy/clippy_lints/src/matches/single_match.rs | 1 + src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs | 1 + src/tools/clippy/clippy_lints/src/methods/utils.rs | 1 + src/tools/clippy/clippy_lints/src/trailing_empty_array.rs | 1 + src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs | 1 + src/tools/clippy/clippy_utils/src/consts.rs | 1 + src/tools/clippy/clippy_utils/src/ty/mod.rs | 1 + 13 files changed, 13 insertions(+) diff --git a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs index 107ab36741b2b..cd71a1e712c22 100644 --- a/src/tools/clippy/clippy_lints/src/indexing_slicing.rs +++ b/src/tools/clippy/clippy_lints/src/indexing_slicing.rs @@ -6,6 +6,7 @@ use clippy_utils::{higher, is_from_proc_macro, is_in_test, sym}; use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs index 4d8ef09d17da3..d395d7b53c607 100644 --- a/src/tools/clippy/clippy_lints/src/large_const_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_const_arrays.rs @@ -5,6 +5,7 @@ use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, Ty, Unnormalized}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::{BytePos, Pos as _, Span}; declare_clippy_lint! { diff --git a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs index 49d4fe478cdf4..6762083fd324e 100644 --- a/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs +++ b/src/tools/clippy/clippy_lints/src/large_stack_arrays.rs @@ -10,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Span; +use rustc_middle::ty::consts::ConstExt; declare_clippy_lint! { /// ### What it does diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs index ba2a418104a47..a9caa42a8b3dd 100644 --- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs @@ -14,6 +14,7 @@ use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, EarlyBinder, Ty}; +use rustc_middle::ty::consts::ConstExt; pub(super) fn check( cx: &LateContext<'_>, diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs index ec0c4fb23390b..b0ddec9513722 100644 --- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs +++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs @@ -13,6 +13,7 @@ use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Pat, PatKind, StmtKind} use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; +use rustc_middle::ty::consts::ConstExt; use std::fmt::Display; /// Checks for `for` loops that sequentially copy items from one slice-like diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs index e72842d72f5cb..71676c5007407 100644 --- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs +++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs @@ -15,6 +15,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath}; use rustc_lint::LateContext; use rustc_middle::middle::region; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{Span, SyntaxContext}; diff --git a/src/tools/clippy/clippy_lints/src/matches/single_match.rs b/src/tools/clippy/clippy_lints/src/matches/single_match.rs index 3d9a634f2008f..24d644625d685 100644 --- a/src/tools/clippy/clippy_lints/src/matches/single_match.rs +++ b/src/tools/clippy/clippy_lints/src/matches/single_match.rs @@ -12,6 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_pat}; use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::Span; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; diff --git a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs index 7ec9021af11d8..54b29b06b35c1 100644 --- a/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/src/tools/clippy/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -5,6 +5,7 @@ use clippy_utils::{expr_or_init, sym}; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty; use super::ITER_OUT_OF_BOUNDS; diff --git a/src/tools/clippy/clippy_lints/src/methods/utils.rs b/src/tools/clippy/clippy_lints/src/methods/utils.rs index 9e7764fa19c80..6860b920fa82f 100644 --- a/src/tools/clippy/clippy_lints/src/methods/utils.rs +++ b/src/tools/clippy/clippy_lints/src/methods/utils.rs @@ -5,6 +5,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, QPath, Stmt, use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::Span; use rustc_span::symbol::sym; diff --git a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs index 9fa66fc86c305..22f2ed3b3e518 100644 --- a/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs +++ b/src/tools/clippy/clippy_lints/src/trailing_empty_array.rs @@ -1,3 +1,4 @@ +use rustc_middle::ty::consts::ConstExt; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{has_repr_attr, is_in_test}; use rustc_hir::{Item, ItemKind}; diff --git a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs index c339affc3e8ba..1f0f678668b17 100644 --- a/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs +++ b/src/tools/clippy/clippy_lints/src/tuple_array_conversions.rs @@ -8,6 +8,7 @@ use clippy_utils::{SpanlessEq, is_from_proc_macro}; use core::ops::ControlFlow::{Break, Continue}; use core::{iter, mem}; use rustc_ast::LitKind; +use rustc_middle::ty::consts::ConstExt; use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list}; use rustc_data_structures::packed::Pu128; use rustc_hir::intravisit::Visitor; diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs index 192ce4df77c2a..890fc7cb4e947 100644 --- a/src/tools/clippy/clippy_utils/src/consts.rs +++ b/src/tools/clippy/clippy_utils/src/consts.rs @@ -17,6 +17,7 @@ use rustc_hir::{ BinOpKind, Block, ConstArgKind, ConstBlock, ConstItemRhs, Expr, ExprKind, HirId, PatExpr, PatExprKind, QPath, TyKind, UnOp, }; +use rustc_middle::ty::consts::ConstExt; use rustc_lexer::{FrontmatterAllowed, tokenize}; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{Scalar, alloc_range}; diff --git a/src/tools/clippy/clippy_utils/src/ty/mod.rs b/src/tools/clippy/clippy_utils/src/ty/mod.rs index a244767cf3c3f..89174b281b773 100644 --- a/src/tools/clippy/clippy_utils/src/ty/mod.rs +++ b/src/tools/clippy/clippy_utils/src/ty/mod.rs @@ -20,6 +20,7 @@ use rustc_lint::unused::must_use::{IsTyMustUse, MustUsePath, is_ty_must_use}; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::{LayoutError, LayoutOf as _, TyAndLayout}; use rustc_middle::ty::{ From 5e56705e41153b18e2ced91daf527f83bf909ad7 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 14:42:03 +0100 Subject: [PATCH 0625/1309] Add better code comments for peculiarities --- compiler/rustc_middle/src/ty/context.rs | 4 +--- compiler/rustc_type_ir/src/interner.rs | 4 ++++ 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 8b8ec7c98182f..4009191430afb 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -1730,9 +1730,7 @@ impl<'a, 'tcx> Lift> for Interned<'a, RegionKind<'a>> { } } -// `rustc_type_ir::Const` is only the generic wrapper; lifting it delegates -// to `I::InternedConstKind`, so the concrete interned const representation -// must itself implement `Lift`. +// FIXME: unclear why exactly the macro doesn't work. impl<'a, 'tcx> Lift> for Interned<'a, WithCachedTypeInfo>> { type Lifted = Interned<'tcx, WithCachedTypeInfo>>; diff --git a/compiler/rustc_type_ir/src/interner.rs b/compiler/rustc_type_ir/src/interner.rs index 474a4689997d7..85a69af53539a 100644 --- a/compiler/rustc_type_ir/src/interner.rs +++ b/compiler/rustc_type_ir/src/interner.rs @@ -177,6 +177,10 @@ pub trait Interner: type Symbol: Symbol; // Things stored inside of tys + + // `TypeVisitable` is required to prevent a problem where the flags + // on `Const` indicated that an error was present, as the visitor could no + // longer reach the corresponding ErrorGuaranteed type ErrorGuaranteed: Copy + Debug + Hash + Eq + TypeVisitable; type BoundExistentialPredicates: BoundExistentialPredicates; type AllocId: Copy + Debug + Hash + Eq; From 9bf2c2a06230efb1531705323df934a9ebb044c9 Mon Sep 17 00:00:00 2001 From: James Barford-Evans Date: Thu, 17 Sep 2026 09:36:40 +0100 Subject: [PATCH 0626/1309] Use `ConstExt` in clippy --- clippy_lints/src/indexing_slicing.rs | 1 + clippy_lints/src/large_const_arrays.rs | 1 + clippy_lints/src/large_stack_arrays.rs | 1 + clippy_lints/src/loops/explicit_iter_loop.rs | 1 + clippy_lints/src/loops/manual_memcpy.rs | 1 + clippy_lints/src/loops/needless_range_loop.rs | 1 + clippy_lints/src/matches/single_match.rs | 1 + clippy_lints/src/methods/iter_out_of_bounds.rs | 1 + clippy_lints/src/methods/utils.rs | 1 + clippy_lints/src/trailing_empty_array.rs | 1 + clippy_lints/src/tuple_array_conversions.rs | 1 + clippy_utils/src/consts.rs | 1 + clippy_utils/src/ty/mod.rs | 1 + 13 files changed, 13 insertions(+) diff --git a/clippy_lints/src/indexing_slicing.rs b/clippy_lints/src/indexing_slicing.rs index 107ab36741b2b..cd71a1e712c22 100644 --- a/clippy_lints/src/indexing_slicing.rs +++ b/clippy_lints/src/indexing_slicing.rs @@ -6,6 +6,7 @@ use clippy_utils::{higher, is_from_proc_macro, is_in_test, sym}; use rustc_ast::ast::RangeLimits; use rustc_hir::{Expr, ExprKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty}; declare_clippy_lint! { diff --git a/clippy_lints/src/large_const_arrays.rs b/clippy_lints/src/large_const_arrays.rs index 4d8ef09d17da3..d395d7b53c607 100644 --- a/clippy_lints/src/large_const_arrays.rs +++ b/clippy_lints/src/large_const_arrays.rs @@ -5,6 +5,7 @@ use rustc_hir::{Item, ItemKind}; use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty::layout::LayoutOf as _; use rustc_middle::ty::{self, Ty, Unnormalized}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::{BytePos, Pos as _, Span}; declare_clippy_lint! { diff --git a/clippy_lints/src/large_stack_arrays.rs b/clippy_lints/src/large_stack_arrays.rs index 49d4fe478cdf4..6762083fd324e 100644 --- a/clippy_lints/src/large_stack_arrays.rs +++ b/clippy_lints/src/large_stack_arrays.rs @@ -10,6 +10,7 @@ use rustc_lint::{LateContext, LateLintPass, impl_lint_pass}; use rustc_middle::ty; use rustc_middle::ty::layout::LayoutOf as _; use rustc_span::Span; +use rustc_middle::ty::consts::ConstExt; declare_clippy_lint! { /// ### What it does diff --git a/clippy_lints/src/loops/explicit_iter_loop.rs b/clippy_lints/src/loops/explicit_iter_loop.rs index ba2a418104a47..a9caa42a8b3dd 100644 --- a/clippy_lints/src/loops/explicit_iter_loop.rs +++ b/clippy_lints/src/loops/explicit_iter_loop.rs @@ -14,6 +14,7 @@ use rustc_hir::{Expr, Mutability}; use rustc_lint::LateContext; use rustc_middle::ty::adjustment::{Adjust, Adjustment, AutoBorrow, AutoBorrowMutability}; use rustc_middle::ty::{self, EarlyBinder, Ty}; +use rustc_middle::ty::consts::ConstExt; pub(super) fn check( cx: &LateContext<'_>, diff --git a/clippy_lints/src/loops/manual_memcpy.rs b/clippy_lints/src/loops/manual_memcpy.rs index ec0c4fb23390b..b0ddec9513722 100644 --- a/clippy_lints/src/loops/manual_memcpy.rs +++ b/clippy_lints/src/loops/manual_memcpy.rs @@ -13,6 +13,7 @@ use rustc_hir::{BinOpKind, Block, Expr, ExprKind, HirId, Pat, PatKind, StmtKind} use rustc_lint::LateContext; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::sym; +use rustc_middle::ty::consts::ConstExt; use std::fmt::Display; /// Checks for `for` loops that sequentially copy items from one slice-like diff --git a/clippy_lints/src/loops/needless_range_loop.rs b/clippy_lints/src/loops/needless_range_loop.rs index e72842d72f5cb..71676c5007407 100644 --- a/clippy_lints/src/loops/needless_range_loop.rs +++ b/clippy_lints/src/loops/needless_range_loop.rs @@ -15,6 +15,7 @@ use rustc_hir::intravisit::{Visitor, walk_expr}; use rustc_hir::{BinOpKind, BorrowKind, Closure, Expr, ExprKind, HirId, Mutability, Pat, PatKind, QPath}; use rustc_lint::LateContext; use rustc_middle::middle::region; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::{self, Ty}; use rustc_span::symbol::{Symbol, sym}; use rustc_span::{Span, SyntaxContext}; diff --git a/clippy_lints/src/matches/single_match.rs b/clippy_lints/src/matches/single_match.rs index 3d9a634f2008f..24d644625d685 100644 --- a/clippy_lints/src/matches/single_match.rs +++ b/clippy_lints/src/matches/single_match.rs @@ -12,6 +12,7 @@ use rustc_hir::intravisit::{Visitor, walk_pat}; use rustc_hir::{Arm, Expr, ExprKind, HirId, Node, Pat, PatExpr, PatExprKind, PatKind, QPath, StmtKind}; use rustc_lint::LateContext; use rustc_middle::ty::{self, AdtDef, TyCtxt, TypeckResults, VariantDef}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::Span; use super::{MATCH_BOOL, SINGLE_MATCH, SINGLE_MATCH_ELSE}; diff --git a/clippy_lints/src/methods/iter_out_of_bounds.rs b/clippy_lints/src/methods/iter_out_of_bounds.rs index 7ec9021af11d8..54b29b06b35c1 100644 --- a/clippy_lints/src/methods/iter_out_of_bounds.rs +++ b/clippy_lints/src/methods/iter_out_of_bounds.rs @@ -5,6 +5,7 @@ use clippy_utils::{expr_or_init, sym}; use rustc_ast::LitKind; use rustc_hir::{Expr, ExprKind}; use rustc_lint::LateContext; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty; use super::ITER_OUT_OF_BOUNDS; diff --git a/clippy_lints/src/methods/utils.rs b/clippy_lints/src/methods/utils.rs index 9e7764fa19c80..6860b920fa82f 100644 --- a/clippy_lints/src/methods/utils.rs +++ b/clippy_lints/src/methods/utils.rs @@ -5,6 +5,7 @@ use rustc_hir::{BorrowKind, Expr, ExprKind, HirId, Mutability, Pat, QPath, Stmt, use rustc_lint::LateContext; use rustc_middle::hir::nested_filter; use rustc_middle::ty::{self, Ty}; +use rustc_middle::ty::consts::ConstExt; use rustc_span::Span; use rustc_span::symbol::sym; diff --git a/clippy_lints/src/trailing_empty_array.rs b/clippy_lints/src/trailing_empty_array.rs index 9fa66fc86c305..22f2ed3b3e518 100644 --- a/clippy_lints/src/trailing_empty_array.rs +++ b/clippy_lints/src/trailing_empty_array.rs @@ -1,3 +1,4 @@ +use rustc_middle::ty::consts::ConstExt; use clippy_utils::diagnostics::span_lint_and_help; use clippy_utils::{has_repr_attr, is_in_test}; use rustc_hir::{Item, ItemKind}; diff --git a/clippy_lints/src/tuple_array_conversions.rs b/clippy_lints/src/tuple_array_conversions.rs index c339affc3e8ba..1f0f678668b17 100644 --- a/clippy_lints/src/tuple_array_conversions.rs +++ b/clippy_lints/src/tuple_array_conversions.rs @@ -8,6 +8,7 @@ use clippy_utils::{SpanlessEq, is_from_proc_macro}; use core::ops::ControlFlow::{Break, Continue}; use core::{iter, mem}; use rustc_ast::LitKind; +use rustc_middle::ty::consts::ConstExt; use rustc_ast::visit::{VisitorResult, try_visit, visit_opt, walk_list}; use rustc_data_structures::packed::Pu128; use rustc_hir::intravisit::Visitor; diff --git a/clippy_utils/src/consts.rs b/clippy_utils/src/consts.rs index 192ce4df77c2a..890fc7cb4e947 100644 --- a/clippy_utils/src/consts.rs +++ b/clippy_utils/src/consts.rs @@ -17,6 +17,7 @@ use rustc_hir::{ BinOpKind, Block, ConstArgKind, ConstBlock, ConstItemRhs, Expr, ExprKind, HirId, PatExpr, PatExprKind, QPath, TyKind, UnOp, }; +use rustc_middle::ty::consts::ConstExt; use rustc_lexer::{FrontmatterAllowed, tokenize}; use rustc_lint::LateContext; use rustc_middle::mir::interpret::{Scalar, alloc_range}; diff --git a/clippy_utils/src/ty/mod.rs b/clippy_utils/src/ty/mod.rs index a244767cf3c3f..89174b281b773 100644 --- a/clippy_utils/src/ty/mod.rs +++ b/clippy_utils/src/ty/mod.rs @@ -20,6 +20,7 @@ use rustc_lint::unused::must_use::{IsTyMustUse, MustUsePath, is_ty_must_use}; use rustc_middle::mir::ConstValue; use rustc_middle::mir::interpret::Scalar; use rustc_middle::traits::EvaluationResult; +use rustc_middle::ty::consts::ConstExt; use rustc_middle::ty::adjustment::{Adjust, Adjustment, DerefAdjustKind}; use rustc_middle::ty::layout::{LayoutError, LayoutOf as _, TyAndLayout}; use rustc_middle::ty::{ From bae45db91d526101fdba2f316491bfdde891c209 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 22 Sep 2026 13:00:32 +0000 Subject: [PATCH 0627/1309] Add unreachable for modes which never adds opaque types --- compiler/rustc_next_trait_solver/src/solve/trait_goals.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 649ce4d2dd76f..8e2baed38a2e2 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1320,7 +1320,9 @@ where // fixed and only regions are inferred, but not during typeck while hidden // types may still contain inference variables. if !opaque_types.is_empty() { - match self.typing_mode() { + let typing_mode = self.typing_mode(); + + match typing_mode { // We're inferring regions of opaque types, but // the type itself is already fully known, no way // to leak the hidden type. @@ -1337,7 +1339,9 @@ where | TypingMode::PostAnalysis | TypingMode::Codegen | TypingMode::ErasedNotCoherence(MayBeErased) => { - return self.forced_ambiguity(MaybeInfo::AMBIGUOUS); + unreachable!( + "we never add new uses to opaque types in typing mode {typing_mode:?}" + ); } } } From a35e5a6272ab3ea18f16d7cd5dc61fedad788682 Mon Sep 17 00:00:00 2001 From: Guillaume Gomez Date: Tue, 22 Sep 2026 15:03:57 +0200 Subject: [PATCH 0628/1309] Remove unused `make3.sh` CI script --- src/ci/docker/scripts/make3.sh | 10 ---------- 1 file changed, 10 deletions(-) delete mode 100644 src/ci/docker/scripts/make3.sh diff --git a/src/ci/docker/scripts/make3.sh b/src/ci/docker/scripts/make3.sh deleted file mode 100644 index 283700d06f6cc..0000000000000 --- a/src/ci/docker/scripts/make3.sh +++ /dev/null @@ -1,10 +0,0 @@ -#!/bin/sh -set -ex - -curl -f https://ftp.gnu.org/gnu/make/make-3.81.tar.gz | tar xzf - -cd make-3.81 -./configure --prefix=/usr -make -make install -cd .. -rm -rf make-3.81 From db0b931b23cf226407979eece7c69c2aa2dbd8aa Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 22 Sep 2026 09:21:06 -0400 Subject: [PATCH 0629/1309] Update to nightly-2026-09-22 --- rust-toolchain | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rust-toolchain b/rust-toolchain index 0c81f7c7c7398..f3106ee20c331 100644 --- a/rust-toolchain +++ b/rust-toolchain @@ -1,3 +1,3 @@ [toolchain] -channel = "nightly-2026-09-18" +channel = "nightly-2026-09-22" components = ["rust-src", "rustc-dev", "llvm-tools-preview"] From baf4778d7c89cd81c11f0fe9ecb03820f1467ba9 Mon Sep 17 00:00:00 2001 From: Bee Date: Mon, 24 Aug 2026 12:55:55 +0100 Subject: [PATCH 0630/1309] Add `f16` inline ASM support for `nvptx64-nvidia-cuda` --- compiler/rustc_target/src/asm/nvptx.rs | 6 +-- tests/assembly-llvm/asm/nvptx-types.rs | 72 ++++++++++++++++---------- 2 files changed, 48 insertions(+), 30 deletions(-) diff --git a/compiler/rustc_target/src/asm/nvptx.rs b/compiler/rustc_target/src/asm/nvptx.rs index da8b79d8935be..4aaafe1e9b49c 100644 --- a/compiler/rustc_target/src/asm/nvptx.rs +++ b/compiler/rustc_target/src/asm/nvptx.rs @@ -36,9 +36,9 @@ impl NvptxInlineAsmRegClass { _arch: InlineAsmArch, ) -> &'static [(InlineAsmType, Option)] { match self { - Self::reg16 => types! { _: I8, I16; }, - Self::reg32 => types! { _: I8, I16, I32, F32; }, - Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; }, + Self::reg16 => types! { _: I8, I16, F16; }, + Self::reg32 => types! { _: I8, I16, F16, I32, F32; }, + Self::reg64 => types! { _: I8, I16, F16, I32, F32, I64, F64; }, } } } diff --git a/tests/assembly-llvm/asm/nvptx-types.rs b/tests/assembly-llvm/asm/nvptx-types.rs index 1cb176cf5148a..15c4dabbfecee 100644 --- a/tests/assembly-llvm/asm/nvptx-types.rs +++ b/tests/assembly-llvm/asm/nvptx-types.rs @@ -3,7 +3,7 @@ //@ compile-flags: --target nvptx64-nvidia-cuda //@ needs-llvm-components: nvptx -#![feature(no_core, asm_experimental_arch)] +#![feature(no_core, asm_experimental_arch, f16)] #![crate_type = "rlib"] #![no_core] @@ -38,78 +38,96 @@ macro_rules! check { // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i8 // CHECK: // begin inline asm -// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg16_i8 i8 reg16 "mov.i16"); +check!(reg16_i8 i8 reg16 "mov.b16"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i16 // CHECK: // begin inline asm -// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg16_i16 i16 reg16 "mov.i16"); +check!(reg16_i16 i16 reg16 "mov.b16"); + +// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg16_f16 +// CHECK: // begin inline asm +// CHECK: mov.b16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm +check!(reg16_f16 f16 reg16 "mov.b16"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i8 // CHECK: // begin inline asm -// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg32_i8 i8 reg32 "mov.i32"); +check!(reg32_i8 i8 reg32 "mov.b32"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i16 // CHECK: // begin inline asm -// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg32_i16 i16 reg32 "mov.i32"); +check!(reg32_i16 i16 reg32 "mov.b32"); + +// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg32_f16 +// CHECK: // begin inline asm +// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm +check!(reg32_f16 f16 reg32 "mov.b32"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i32 // CHECK: // begin inline asm -// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg32_i32 i32 reg32 "mov.i32"); +check!(reg32_i32 i32 reg32 "mov.b32"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_f32 // CHECK: // begin inline asm -// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg32_f32 f32 reg32 "mov.i32"); +check!(reg32_f32 f32 reg32 "mov.b32"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i8 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_i8 i8 reg64 "mov.i64"); +check!(reg64_i8 i8 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i16 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: // end inline asm +check!(reg64_i16 i16 reg64 "mov.b64"); + +// CHECK-LABEL: .visible .func (.param .align 2 .b8 func_retval0[2]) reg64_f16 +// CHECK: // begin inline asm +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_i16 i16 reg64 "mov.i64"); +check!(reg64_f16 f16 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i32 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_i32 i32 reg64 "mov.i64"); +check!(reg64_i32 i32 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_f32 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_f32 f32 reg64 "mov.i64"); +check!(reg64_f32 f32 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_i64 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_i64 i64 reg64 "mov.i64"); +check!(reg64_i64 i64 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_f64 // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_f64 f64 reg64 "mov.i64"); +check!(reg64_f64 f64 reg64 "mov.b64"); // CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_ptr // CHECK: // begin inline asm -// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; +// CHECK: mov.b64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}}; // CHECK: // end inline asm -check!(reg64_ptr ptr reg64 "mov.i64"); +check!(reg64_ptr ptr reg64 "mov.b64"); From 3438e6f4ffa42fff4eea95681d53ba66173fea08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 16:13:13 +0200 Subject: [PATCH 0631/1309] clarify some names in `record_legacy_polonius_drop_facts` --- .../rustc_borrowck/src/type_check/liveness/trace.rs | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index e7fe48cc10919..2b452f39ccfdd 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -279,8 +279,8 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { /// the function body only at certain nodes in the CFG. fn record_legacy_polonius_drop_facts( &mut self, - relevant_live_locals: &[Local], - deferred: &FxIndexSet, + nll_relevant_locals: &[Local], + deferred_polonius_relevant_locals: &FxIndexSet, ) { // This is *all wonky* because this used to call a shared // `add_drop_live_facts_for` function that was also used for regular @@ -292,16 +292,15 @@ impl<'a, 'typeck, 'tcx> LivenessResults<'a, 'typeck, 'tcx> { // `add_drop_live_facts_for()` that make sense. let Some(facts) = self.typeck.polonius_facts.as_ref() else { return }; let facts_to_add: Vec<_> = { - let relevant_live_locals: FxIndexSet<_> = - relevant_live_locals.iter().copied().collect(); + let nll_relevant_locals: FxIndexSet<_> = nll_relevant_locals.iter().copied().collect(); facts .var_dropped_at .iter() .filter_map(|&(local, location_index)| { let local_ty = self.comp.body.local_decls[local].ty; - if relevant_live_locals.contains(&local) - || deferred.contains(&local) + if nll_relevant_locals.contains(&local) + || deferred_polonius_relevant_locals.contains(&local) || !local_ty.has_free_regions() { return None; From 9a24de63f9af0cdad383955920ba55203a5b4e65 Mon Sep 17 00:00:00 2001 From: Weihang Lo Date: Tue, 22 Sep 2026 10:17:58 -0400 Subject: [PATCH 0632/1309] Update cargo submodule --- src/tools/cargo | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/tools/cargo b/src/tools/cargo index 495c385d0875c..98a09e7e7d628 160000 --- a/src/tools/cargo +++ b/src/tools/cargo @@ -1 +1 @@ -Subproject commit 495c385d0875c4ba51eb72ea0448a2d4c018b8d4 +Subproject commit 98a09e7e7d62850f14e5b6132101fc1edd19a16f From 7a8706e98c13918cad687d8e8d1423280b6d68fd Mon Sep 17 00:00:00 2001 From: Antoni Boucher Date: Tue, 22 Sep 2026 10:22:49 -0400 Subject: [PATCH 0633/1309] Skip test_mm_srav_epi64 as it's broken upstream --- .github/workflows/stdarch.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/stdarch.yml b/.github/workflows/stdarch.yml index 17d6449c85e08..34499c6e7b522 100644 --- a/.github/workflows/stdarch.yml +++ b/.github/workflows/stdarch.yml @@ -96,14 +96,16 @@ jobs: if: ${{ !matrix.cargo_runner }} run: | # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + ./y.sh test --release --stdarch-tests -- --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 - name: Run stdarch tests if: ${{ matrix.cargo_runner }} run: | # FIXME: these tests fail when the sysroot is compiled with LTO because of a missing symbol in proc-macro. # FIXME: remove --skip test_tile_ and --skip --skip test__tile when it's implemented. - STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile + # FIXME: remove --skip test_mm_srav_epi64 when it's fixed upstream. + STDARCH_TEST_SKIP_FUNCTION="xsave,xsaveopt,xsave64,xsaveopt64" STDARCH_TEST_EVERYTHING=1 CHANNEL=release CARGO_TARGET_X86_64_UNKNOWN_LINUX_GNU_RUNNER="${{ matrix.cargo_runner }}" TARGET=x86_64-unknown-linux-gnu CG_RUSTFLAGS="-Ainternal_features" ./y.sh cargo test --manifest-path build/build_sysroot/sysroot_src/library/stdarch/Cargo.toml -- --skip rtm --skip tbm --skip sse4a --skip test_tile_ --skip test__tile --skip test_mm_srav_epi64 # Summary job for the merge queue. # ALL THE PREVIOUS JOBS NEED TO BE ADDED TO THE `needs` SECTION OF THIS JOB! From d72a519a5a7ca0efa7af26a457757a86175a6f74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 16:26:57 +0200 Subject: [PATCH 0634/1309] remove unneeded type ascription --- compiler/rustc_borrowck/src/type_check/liveness/mod.rs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs index 6b9eae7428475..905547c7dce51 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs @@ -78,13 +78,12 @@ pub(super) fn generate<'tcx>( break 'deferred FxIndexSet::default(); } - let free_regions: FxHashSet = - typeck.universal_regions.universal_regions_iter().collect(); + let free_regions = typeck.universal_regions.universal_regions_iter().collect(); let (polonius_relevant, _) = compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body); - let boring: FxHashSet = boring_locals.iter().copied().collect(); - let deferred: FxIndexSet = + let boring: FxHashSet<_> = boring_locals.iter().copied().collect(); + let deferred = polonius_relevant.into_iter().filter(|local| boring.contains(local)).collect(); typeck.polonius_context.as_mut().unwrap().boring_nll_locals = boring; deferred From 6241eb0b89e9b1a7f82216d69abd3b6978bb3633 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 17:01:35 +0200 Subject: [PATCH 0635/1309] remove allocation to create the local use map --- .../src/type_check/liveness/local_use_map.rs | 12 +++++------- .../rustc_borrowck/src/type_check/liveness/trace.rs | 4 ++-- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs index 9c39645ec677d..0bb6ecb8e2049 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/local_use_map.rs @@ -82,7 +82,7 @@ impl<'a> Iterator for AppearancesIter<'a> { impl LocalUseMap { pub(crate) fn build( - live_locals: &[Local], + mut live_locals: impl Iterator, location_map: &DenseLocationMap, body: &Body<'_>, ) -> Self { @@ -94,13 +94,11 @@ impl LocalUseMap { appearances: IndexVec::new(), }; - if live_locals.is_empty() { - return local_use_map; - } + let Some(head) = live_locals.next() else { return local_use_map }; - let mut locals_with_use_data: DenseBitSet = - DenseBitSet::new_empty(body.local_decls.len()); - live_locals.iter().for_each(|&local| { + let mut locals_with_use_data = DenseBitSet::new_empty(body.local_decls.len()); + locals_with_use_data.insert(head); + live_locals.for_each(|local| { locals_with_use_data.insert(local); }); diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs index 2b452f39ccfdd..21b2e0f304b05 100644 --- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs +++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs @@ -52,8 +52,8 @@ pub(super) fn trace<'tcx>( // The use map must also cover the deferred locals: their liveness is computed later, from // this same map, when the loan liveness traversal first reaches one of their regions. - let use_map_locals: Vec = relevant_live_locals.iter().chain(deferred).copied().collect(); - let local_use_map = LocalUseMap::build(&use_map_locals, location_map, typeck.body); + let use_map_locals = relevant_live_locals.iter().chain(deferred).copied(); + let local_use_map = LocalUseMap::build(use_map_locals, location_map, typeck.body); let comp = LivenessComputation::new( typeck.infcx, typeck.body, From d86cf85387c1eb079a0244c2ee4f5c41dbc36466 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Thu, 20 Aug 2026 07:04:27 +0000 Subject: [PATCH 0636/1309] update fallout tests --- ...erence-inherited-assoc-ty-cycle-err.stderr | 7 ++- .../cycles/fixpoint-rerun-all-cycle-heads.rs | 2 + .../fixpoint-rerun-all-cycle-heads.stderr | 59 ++++++++++++++++++- 3 files changed, 65 insertions(+), 3 deletions(-) diff --git a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr index 5b6ce4e2eec89..0fcc164a25872 100644 --- a/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr +++ b/tests/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr @@ -4,7 +4,12 @@ error[E0391]: cycle detected when building specialization graph of trait `Trait` LL | trait Trait { type Assoc; } | ^^^^^^^^^^^^^^ | - = note: ...which immediately requires building specialization graph of trait `Trait` again +note: ...which requires computing whether impls specialize one another... + --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:17:1 + | +LL | impl Trait for String { + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^ + = note: ...which again requires building specialization graph of trait `Trait`, completing the cycle = note: cycle used when coherence checking all impls of trait `Trait` = note: for more information, see and diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs index 326d888a55f3d..1956f4a65f7e6 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.rs @@ -19,6 +19,7 @@ impl<'a, 'b, T> Trait<'a, 'b> for A where B: Trait<'a, 'b> {} // not have a cycle with `A`. This candidate never applies because of // the `A: NotImplemented` bound. impl<'a, 'b, T> Trait<'a, 'b> for B +//~^ ERROR: type annotations needed: cannot satisfy `B: Trait<'a, 'b>` [E0283] where A: Trait<'a, 'b>, A: NotImplemented, @@ -33,6 +34,7 @@ where // regions in the `A: Trait<'a, 'b>` where-bound. As both the impl above // and the impl below now apply with some constraints, we failed with ambiguity. impl<'a, 'b, T> Trait<'a, 'b> for B +//~^ ERROR: type annotations needed: cannot satisfy `B: Trait<'a, 'b>` [E0283] where A: NotImplemented, {} diff --git a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr index c88081736f3c3..6088fb52e808f 100644 --- a/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr +++ b/tests/ui/traits/next-solver/cycles/fixpoint-rerun-all-cycle-heads.stderr @@ -1,10 +1,65 @@ +error[E0283]: type annotations needed: cannot satisfy `B: Trait<'a, 'b>` + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:21:35 + | +LL | impl<'a, 'b, T> Trait<'a, 'b> for B + | ^^^^ + | +note: multiple `impl`s satisfying `B: Trait<'a, 'b>` found + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:21:1 + | +LL | / impl<'a, 'b, T> Trait<'a, 'b> for B +LL | | +LL | | where +LL | | A: Trait<'a, 'b>, +LL | | A: NotImplemented, + | |_________________________^ +... +LL | / impl<'a, 'b, T> Trait<'a, 'b> for B +LL | | +LL | | where +LL | | A: NotImplemented, + | |_________________________^ +... +LL | / impl<'a, T> Trait<'a, 'static> for B +LL | | where +LL | | C: Trait<'a, 'a>, + | |________________________^ + +error[E0283]: type annotations needed: cannot satisfy `B: Trait<'a, 'b>` + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:36:35 + | +LL | impl<'a, 'b, T> Trait<'a, 'b> for B + | ^^^^ + | +note: multiple `impl`s satisfying `B: Trait<'a, 'b>` found + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:21:1 + | +LL | / impl<'a, 'b, T> Trait<'a, 'b> for B +LL | | +LL | | where +LL | | A: Trait<'a, 'b>, +LL | | A: NotImplemented, + | |_________________________^ +... +LL | / impl<'a, 'b, T> Trait<'a, 'b> for B +LL | | +LL | | where +LL | | A: NotImplemented, + | |_________________________^ +... +LL | / impl<'a, T> Trait<'a, 'static> for B +LL | | where +LL | | C: Trait<'a, 'a>, + | |________________________^ + error: lifetime may not live long enough - --> $DIR/fixpoint-rerun-all-cycle-heads.rs:60:5 + --> $DIR/fixpoint-rerun-all-cycle-heads.rs:62:5 | LL | fn check<'a, T>() { | -- lifetime `'a` defined here LL | impls_trait::<'a, 'static, A>(); | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static` -error: aborting due to 1 previous error +error: aborting due to 3 previous errors +For more information about this error, try `rustc --explain E0283`. From 0adc046717d42f4c1d766d00f39d142eeefe6288 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Fri, 18 Sep 2026 13:45:38 +0000 Subject: [PATCH 0637/1309] add tests --- .../ambiguous-impl-in-resolve.next.stderr | 17 +++++++++++++++++ .../ambiguous-impl-in-resolve.old.stderr | 17 +++++++++++++++++ .../next-solver/ambiguous-impl-in-resolve.rs | 8 ++++++-- 3 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr create mode 100644 tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr new file mode 100644 index 0000000000000..20bbcdd8af423 --- /dev/null +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.next.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `Option: Overlap` + --> $DIR/ambiguous-impl-in-resolve.rs:17:6 + | +LL | as Overlap>::f(); + | ^^^^^^^^^ + | +note: multiple `impl`s satisfying `Option: Overlap` found + --> $DIR/ambiguous-impl-in-resolve.rs:10:1 + | +LL | impl Overlap for Option where Self: Clone, { fn f() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Overlap for Option where Self: Local, { fn f() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr new file mode 100644 index 0000000000000..20bbcdd8af423 --- /dev/null +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.old.stderr @@ -0,0 +1,17 @@ +error[E0283]: type annotations needed: cannot satisfy `Option: Overlap` + --> $DIR/ambiguous-impl-in-resolve.rs:17:6 + | +LL | as Overlap>::f(); + | ^^^^^^^^^ + | +note: multiple `impl`s satisfying `Option: Overlap` found + --> $DIR/ambiguous-impl-in-resolve.rs:10:1 + | +LL | impl Overlap for Option where Self: Clone, { fn f() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +LL | impl Overlap for Option where Self: Local, { fn f() {} } + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +error: aborting due to 1 previous error + +For more information about this error, try `rustc --explain E0283`. diff --git a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs index 78dffcbf6abc3..fd90d11575b07 100644 --- a/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs +++ b/tests/ui/traits/next-solver/ambiguous-impl-in-resolve.rs @@ -1,5 +1,8 @@ -//@ check-pass -//@ compile-flags: -Znext-solver +//@ revisions: old next +//@[next] compile-flags: -Znext-solver + +// Impossible where-clauses can cause multiple overlapping impls to apply +// with the same constraints. trait Local {} @@ -12,6 +15,7 @@ where Option: Clone + Local, { as Overlap>::f(); + //~^ ERROR type annotations needed } fn main() {} From 781bc2b42b8e7cd1583affb2d002dadab2567d78 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Sat, 19 Sep 2026 15:52:05 +0000 Subject: [PATCH 0638/1309] replace has_distinct_impl_candidates with try_merge_impl_candidates and add docs --- .../src/solve/assembly/mod.rs | 3 + .../src/solve/trait_goals.rs | 55 +++++++++++-------- 2 files changed, 34 insertions(+), 24 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs index 38afd45370c26..02f209c9e4662 100644 --- a/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs +++ b/compiler/rustc_next_trait_solver/src/solve/assembly/mod.rs @@ -1052,6 +1052,9 @@ where // we still use modulo regions here. This is fine as specialization currently // assumes that specializing impls have to be always applicable, meaning that // the only allowed region constraints may be constraints also present on the default impl. + // + // If both impls have the same response, dropping victim doesn't change the + // result. We need to do so here as we don't merge distinct impl candidates. if matches!(allow_inference_constraints, AllowInferenceConstraints::Yes) || has_only_region_constraints(c.result) || c.result == candidates[i].result diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index d6a96f1e487f3..126807a72e9fa 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1493,16 +1493,33 @@ where } } - fn has_distinct_impl_candidates( - &self, + /// Like `try_merge_candidates`, but returns `None` if there are multiple user-written + /// impls, or a user-written impl and a builtin impl, in which case we flounder. + /// + /// Candidates with equal responses can still come from conflicting impls, ex - two + /// overlapping impls which both apply due to impossible where-clauses. We don't want + /// to merge these. Multiple builtin impls are still merged as usual. This is not + /// done for marker traits, as their impls are allowed to overlap. + #[instrument(level = "trace", skip(self), ret)] + fn try_merge_impl_candidates( + &mut self, trait_def_id: I::TraitId, candidates: &[Candidate], - ) -> bool { - let impls = - candidates.iter().filter(|c| matches!(c.source, CandidateSource::Impl(_))).count(); - let builtin_impls = - candidates.iter().any(|c| matches!(c.source, CandidateSource::BuiltinImpl(_))); - impls + builtin_impls as usize > 1 && !self.cx().trait_is_marker(trait_def_id) + ) -> Option> { + if !self.cx().trait_is_marker(trait_def_id) { + let impl_count = candidates + .iter() + .filter(|candidate| matches!(candidate.source, CandidateSource::Impl(_))) + .count(); + let has_builtin_impl = candidates + .iter() + .any(|candidate| matches!(candidate.source, CandidateSource::BuiltinImpl(_))); + if impl_count + usize::from(has_builtin_impl) > 1 { + return None; + } + } + + self.try_merge_candidates(candidates).map(|(response, _)| response) } #[instrument(level = "debug", skip(self), ret)] @@ -1514,14 +1531,9 @@ where ) -> Result<(CanonicalResponse, Option), NoSolution> { let candidate_preference_mode = CandidatePreferenceMode::compute(self.cx(), trait_def_id); if self.typing_mode().is_coherence() { - if self.has_distinct_impl_candidates(trait_def_id, &candidates) { - return self.flounder(&candidates).map(|r| (r, None)); - } - - return if let Some((response, _)) = self.try_merge_candidates(&candidates) { - Ok((response, Some(TraitGoalProvenVia::Misc))) - } else { - self.flounder(&candidates).map(|r| (r, None)) + return match self.try_merge_impl_candidates(trait_def_id, &candidates) { + Some(response) => Ok((response, Some(TraitGoalProvenVia::Misc))), + None => self.flounder(&candidates).map(|r| (r, None)), }; } @@ -1630,14 +1642,9 @@ where TraitGoalProvenVia::Misc }; - if self.has_distinct_impl_candidates(trait_def_id, &candidates) { - return self.flounder(&candidates).map(|r| (r, None)); - } - - if let Some((response, _)) = self.try_merge_candidates(&candidates) { - Ok((response, Some(proven_via))) - } else { - self.flounder(&candidates).map(|r| (r, None)) + match self.try_merge_impl_candidates(trait_def_id, &candidates) { + Some(response) => Ok((response, Some(proven_via))), + None => self.flounder(&candidates).map(|r| (r, None)), } } From b49ec626c4925328eb6ab0668d5aaea76b551b82 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 22 Sep 2026 03:32:20 +0000 Subject: [PATCH 0639/1309] add merge_candidates_or_bail_with_ambiguity and merge_impl_candidates_or_flounder helpers --- .../src/solve/trait_goals.rs | 87 +++++++++++-------- 1 file changed, 50 insertions(+), 37 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index 126807a72e9fa..ee5040ccd4eb8 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1506,20 +1506,41 @@ where trait_def_id: I::TraitId, candidates: &[Candidate], ) -> Option> { - if !self.cx().trait_is_marker(trait_def_id) { - let impl_count = candidates - .iter() - .filter(|candidate| matches!(candidate.source, CandidateSource::Impl(_))) - .count(); - let has_builtin_impl = candidates - .iter() - .any(|candidate| matches!(candidate.source, CandidateSource::BuiltinImpl(_))); - if impl_count + usize::from(has_builtin_impl) > 1 { - return None; - } + let is_marker = self.cx().trait_is_marker(trait_def_id); + let all_builtin = candidates + .iter() + .all(|candidate| matches!(candidate.source, CandidateSource::BuiltinImpl(_))); + + if is_marker || all_builtin { + self.try_merge_candidates(candidates).map(|(response, _)| response) + } else if candidates.len() > 1 { + None + } else { + candidates.first().map(|candidate| candidate.result) } + } - self.try_merge_candidates(candidates).map(|(response, _)| response) + fn merge_candidates_or_bail_with_ambiguity( + &mut self, + candidates: &[Candidate], + proven_via: TraitGoalProvenVia, + ) -> (CanonicalResponse, Option) { + if let Some((response, _)) = self.try_merge_candidates(candidates) { + (response, Some(proven_via)) + } else { + (self.bail_with_ambiguity(candidates), None) + } + } + + fn merge_impl_candidates_or_flounder( + &mut self, + trait_def_id: I::TraitId, + candidates: &[Candidate], + ) -> Result<(CanonicalResponse, Option), NoSolution> { + match self.try_merge_impl_candidates(trait_def_id, candidates) { + Some(response) => Ok((response, Some(TraitGoalProvenVia::Misc))), + None => self.flounder(candidates).map(|r| (r, None)), + } } #[instrument(level = "debug", skip(self), ret)] @@ -1531,10 +1552,7 @@ where ) -> Result<(CanonicalResponse, Option), NoSolution> { let candidate_preference_mode = CandidatePreferenceMode::compute(self.cx(), trait_def_id); if self.typing_mode().is_coherence() { - return match self.try_merge_impl_candidates(trait_def_id, &candidates) { - Some(response) => Ok((response, Some(TraitGoalProvenVia::Misc))), - None => self.flounder(&candidates).map(|r| (r, None)), - }; + return self.merge_impl_candidates_or_flounder(trait_def_id, &candidates); } // We prefer trivial builtin candidates, i.e. builtin impls without any @@ -1561,11 +1579,10 @@ where let alias_bounds: Vec<_> = candidates .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(..))) .collect(); - return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { - Ok((response, Some(TraitGoalProvenVia::AliasBound))) - } else { - Ok((self.bail_with_ambiguity(&alias_bounds), None)) - }; + return Ok(self.merge_candidates_or_bail_with_ambiguity( + &alias_bounds, + TraitGoalProvenVia::AliasBound, + )); } // If there are non-global where-bounds, prefer where-bounds @@ -1617,11 +1634,10 @@ where let alias_bounds: Vec<_> = candidates .extract_if(.., |c| matches!(c.source, CandidateSource::AliasBound(_))) .collect(); - return if let Some((response, _)) = self.try_merge_candidates(&alias_bounds) { - Ok((response, Some(TraitGoalProvenVia::AliasBound))) - } else { - Ok((self.bail_with_ambiguity(&alias_bounds), None)) - }; + return Ok(self.merge_candidates_or_bail_with_ambiguity( + &alias_bounds, + TraitGoalProvenVia::AliasBound, + )); } self.filter_specialized_impls(AllowInferenceConstraints::No, &mut candidates); @@ -1631,20 +1647,17 @@ where // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the // remaining candidates. - let proven_via = if candidates - .iter() - .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))) - { - TraitGoalProvenVia::ParamEnv + let only_global_where_bounds = !candidates.is_empty() + && candidates + .iter() + .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); + if only_global_where_bounds { + Ok(self + .merge_candidates_or_bail_with_ambiguity(&candidates, TraitGoalProvenVia::ParamEnv)) } else { candidates .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); - TraitGoalProvenVia::Misc - }; - - match self.try_merge_impl_candidates(trait_def_id, &candidates) { - Some(response) => Ok((response, Some(proven_via))), - None => self.flounder(&candidates).map(|r| (r, None)), + self.merge_impl_candidates_or_flounder(trait_def_id, &candidates) } } From 0c27f4b00ddbc342c183ff640f44ab21ae819fa9 Mon Sep 17 00:00:00 2001 From: bit-aloo Date: Tue, 22 Sep 2026 15:18:54 +0000 Subject: [PATCH 0640/1309] Remove flounder from merge_trait_candidates --- .../src/solve/trait_goals.rs | 32 ++++++++++++------- 1 file changed, 21 insertions(+), 11 deletions(-) diff --git a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs index ee5040ccd4eb8..aedd66a08832f 100644 --- a/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs +++ b/compiler/rustc_next_trait_solver/src/solve/trait_goals.rs @@ -1494,7 +1494,7 @@ where } /// Like `try_merge_candidates`, but returns `None` if there are multiple user-written - /// impls, or a user-written impl and a builtin impl, in which case we flounder. + /// impls, or a user-written impl and a builtin impl, in which case we bail with ambiguity. /// /// Candidates with equal responses can still come from conflicting impls, ex - two /// overlapping impls which both apply due to impossible where-clauses. We don't want @@ -1532,14 +1532,18 @@ where } } - fn merge_impl_candidates_or_flounder( + fn merge_impl_candidates_or_bail_with_ambiguity( &mut self, trait_def_id: I::TraitId, candidates: &[Candidate], - ) -> Result<(CanonicalResponse, Option), NoSolution> { + ) -> (CanonicalResponse, Option) { + debug_assert!(candidates.iter().all(|c| matches!( + c.source, + CandidateSource::Impl(_) | CandidateSource::BuiltinImpl(_) + ))); match self.try_merge_impl_candidates(trait_def_id, candidates) { - Some(response) => Ok((response, Some(TraitGoalProvenVia::Misc))), - None => self.flounder(candidates).map(|r| (r, None)), + Some(response) => (response, Some(TraitGoalProvenVia::Misc)), + None => (self.bail_with_ambiguity(candidates), None), } } @@ -1550,9 +1554,16 @@ where mut candidates: Vec>, failed_candidate_info: FailedCandidateInfo, ) -> Result<(CanonicalResponse, Option), NoSolution> { + if candidates.is_empty() { + return Err(NoSolution); + } + let candidate_preference_mode = CandidatePreferenceMode::compute(self.cx(), trait_def_id); if self.typing_mode().is_coherence() { - return self.merge_impl_candidates_or_flounder(trait_def_id, &candidates); + return Ok(match self.try_merge_impl_candidates(trait_def_id, &candidates) { + Some(response) => (response, Some(TraitGoalProvenVia::Misc)), + None => (self.bail_with_ambiguity(&candidates), None), + }); } // We prefer trivial builtin candidates, i.e. builtin impls without any @@ -1647,17 +1658,16 @@ where // is still reported as being proven-via the param-env so that rigid projections // operate correctly. Otherwise, drop all global where-bounds before merging the // remaining candidates. - let only_global_where_bounds = !candidates.is_empty() - && candidates - .iter() - .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); + let only_global_where_bounds = candidates + .iter() + .all(|c| matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); if only_global_where_bounds { Ok(self .merge_candidates_or_bail_with_ambiguity(&candidates, TraitGoalProvenVia::ParamEnv)) } else { candidates .retain(|c| !matches!(c.source, CandidateSource::ParamEnv(ParamEnvSource::Global))); - self.merge_impl_candidates_or_flounder(trait_def_id, &candidates) + Ok(self.merge_impl_candidates_or_bail_with_ambiguity(trait_def_id, &candidates)) } } From 9a3ab6566b1f483f08d1e914584ae1e761da98bf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=A9my=20Rakic?= Date: Tue, 22 Sep 2026 17:27:03 +0200 Subject: [PATCH 0641/1309] add comment --- compiler/rustc_borrowck/src/polonius/liveness.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/compiler/rustc_borrowck/src/polonius/liveness.rs b/compiler/rustc_borrowck/src/polonius/liveness.rs index 5724648a41caf..9cbaa2d6ddc4d 100644 --- a/compiler/rustc_borrowck/src/polonius/liveness.rs +++ b/compiler/rustc_borrowck/src/polonius/liveness.rs @@ -56,6 +56,8 @@ impl<'a> RegionLiveness<'a> { } } +/// The data needed to compute region liveness on-demand while traversing the localized outlives +/// constraint graph to compute loan liveness. #[derive(Default)] pub(crate) struct DeferredLocals<'tcx> { /// For each region, the local whose liveness is deferred. From 6c0f3aacde12d32f4393e5d577c70ce76e7075eb Mon Sep 17 00:00:00 2001 From: mejrs <59372212+mejrs@users.noreply.github.com> Date: Tue, 22 Sep 2026 17:57:52 +0200 Subject: [PATCH 0642/1309] macro_metavar_expr_concat: support concatenating into string literals --- compiler/rustc_expand/src/mbe/metavar_expr.rs | 20 ++++-- compiler/rustc_expand/src/mbe/quoted.rs | 21 +++++-- compiler/rustc_expand/src/mbe/transcribe.rs | 62 ++++++++++++++----- compiler/rustc_span/src/symbol.rs | 1 + .../feature-gate-macro-metavar-expr-concat.rs | 3 +- ...ture-gate-macro-metavar-expr-concat.stderr | 14 ++++- .../concat-allowed-operations.rs | 51 ++++++++++++++- .../metavar-expressions/concat-str-escape.rs | 20 ++++++ .../metavar-expressions/concat-str-horror.rs | 13 ++++ .../macros/metavar-expressions/concat-str.rs | 20 ++++++ .../metavar-expressions/concat-str.stderr | 35 +++++++++++ 11 files changed, 228 insertions(+), 32 deletions(-) create mode 100644 tests/ui/macros/metavar-expressions/concat-str-escape.rs create mode 100644 tests/ui/macros/metavar-expressions/concat-str-horror.rs create mode 100644 tests/ui/macros/metavar-expressions/concat-str.rs create mode 100644 tests/ui/macros/metavar-expressions/concat-str.stderr diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs index 96b39f0ae6863..9774165c73400 100644 --- a/compiler/rustc_expand/src/mbe/metavar_expr.rs +++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs @@ -15,8 +15,11 @@ pub(crate) const UNSUPPORTED_CONCAT_ELEM_ERR: &str = "expected identifier or str /// A meta-variable expression, for expansions based on properties of meta-variables. #[derive(Debug, PartialEq, Encodable, Decodable)] pub(crate) enum MetaVarExpr { - /// Unification of two or more identifiers. - Concat(Box<[MetaVarExprConcatElem]>), + /// Unification of two or more identifiers/literals/metavariables into an identifier. + ConcatIdent(Box<[MetaVarExprConcatElem]>), + + /// Unification of two or more identifiers/literals/metavariables into a string literal. + ConcatStr(Box<[MetaVarExprConcatElem]>), /// The number of repetitions of an identifier. Count(Ident, usize), @@ -73,7 +76,12 @@ impl MetaVarExpr { let mut iter = args.iter(); let rslt = match ident.name { - sym::concat => parse_concat(&mut iter, psess, outer_span, ident.span)?, + sym::concat => { + MetaVarExpr::ConcatIdent(parse_concat(&mut iter, psess, outer_span, ident.span)?) + } + sym::concat_str => { + MetaVarExpr::ConcatStr(parse_concat(&mut iter, psess, outer_span, ident.span)?) + } sym::count => parse_count(&mut iter, psess, ident.span)?, sym::ignore => { eat_dollar(&mut iter, psess, ident.span)?; @@ -95,7 +103,7 @@ impl MetaVarExpr { pub(crate) fn for_each_metavar(&self, mut aux: A, mut cb: impl FnMut(A, &Ident) -> A) -> A { match self { - MetaVarExpr::Concat(elems) => { + MetaVarExpr::ConcatIdent(elems) | MetaVarExpr::ConcatStr(elems) => { for elem in elems { if let MetaVarExprConcatElem::Var(ident) = elem { aux = cb(aux, ident) @@ -175,7 +183,7 @@ fn parse_concat<'psess>( psess: &'psess ParseSess, outer_span: Span, expr_ident_span: Span, -) -> PResult<'psess, MetaVarExpr> { +) -> PResult<'psess, Box<[MetaVarExprConcatElem]>> { let mut result = Vec::new(); loop { let is_var = try_eat_dollar(iter); @@ -210,7 +218,7 @@ fn parse_concat<'psess>( .dcx() .struct_span_err(expr_ident_span, "`concat` must have at least two elements")); } - Ok(MetaVarExpr::Concat(result.into())) + Ok(result.into()) } /// Parse a meta-variable `count` expression: `count(ident[, depth])` diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs index aed69c9f5d938..ff1607c9e4456 100644 --- a/compiler/rustc_expand/src/mbe/quoted.rs +++ b/compiler/rustc_expand/src/mbe/quoted.rs @@ -7,7 +7,7 @@ use rustc_feature::Features; use rustc_session::Session; use rustc_session::diagnostics::feature_err; use rustc_span::edition::Edition; -use rustc_span::{Ident, Span, kw, sym}; +use rustc_span::{Ident, Span, Symbol, kw, sym}; use crate::diagnostics; use crate::mbe::macro_parser::count_metavar_decls; @@ -204,9 +204,14 @@ fn maybe_emit_macro_metavar_expr_feature(features: &Features, sess: &Session, sp } } -fn maybe_emit_macro_metavar_expr_concat_feature(features: &Features, sess: &Session, span: Span) { +fn maybe_emit_macro_metavar_expr_concat_feature( + features: &Features, + sess: &Session, + span: Span, + what: Symbol, +) { if !features.macro_metavar_expr_concat() { - let msg = "the `concat` meta-variable expression is unstable"; + let msg = format!("the `{what}` meta-variable expression is unstable"); feature_err(sess, sym::macro_metavar_expr_concat, span, msg).emit(); } } @@ -278,11 +283,19 @@ fn parse_tree<'a>( return TokenTree::token(token::Dollar, dollar_span); } Ok(elem) => { - if let MetaVarExpr::Concat(_) = elem { + if matches!(elem, MetaVarExpr::ConcatIdent(_)) { + maybe_emit_macro_metavar_expr_concat_feature( + features, + sess, + delim_span.entire(), + sym::concat, + ); + } else if matches!(elem, MetaVarExpr::ConcatStr(_)) { maybe_emit_macro_metavar_expr_concat_feature( features, sess, delim_span.entire(), + sym::concat_str, ); } else { maybe_emit_macro_metavar_expr_feature( diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs index c258d9e471079..8d036972ad592 100644 --- a/compiler/rustc_expand/src/mbe/transcribe.rs +++ b/compiler/rustc_expand/src/mbe/transcribe.rs @@ -597,7 +597,8 @@ fn transcribe_metavar_expr<'tx>( ) -> PResult<'tx, ()> { let dcx = tscx.psess.dcx(); let tt = match *expr { - MetaVarExpr::Concat(ref elements) => metavar_expr_concat(tscx, dspan, elements)?, + MetaVarExpr::ConcatIdent(ref elements) => metavar_expr_concat_ident(tscx, dspan, elements)?, + MetaVarExpr::ConcatStr(ref elements) => metavar_expr_concat_str(tscx, dspan, elements)?, MetaVarExpr::Count(original_ident, depth) => { let matched = matched_from_ident(dcx, original_ident, tscx.interp)?; let count = count_repetitions(dcx, depth, matched, &tscx.repeats, &dspan)?; @@ -635,11 +636,52 @@ fn transcribe_metavar_expr<'tx>( } /// Handle the `${concat(...)}` metavariable expression. -fn metavar_expr_concat<'tx>( +fn metavar_expr_concat_ident<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + dspan: DelimSpan, + elements: &[MetaVarExprConcatElem], +) -> PResult<'tx, TokenTree> { + let (symbol, concatenated_span) = metavar_expr_concat(tscx, dspan, elements)?; + if !rustc_lexer::is_ident(symbol.as_str()) { + return Err(tscx.psess.dcx().create_err(ConcatInvalidIdent { + span: concatenated_span, + reason: InvalidIdentReason::new(symbol), + })); + } + tscx.psess.symbol_gallery.insert(symbol, concatenated_span); + + // The current implementation marks the span as coming from the macro regardless of + // contexts of the concatenated identifiers but this behavior may change in the + // future. + Ok(TokenTree::Token( + Token::from_ast_ident(Ident::new(symbol, concatenated_span)), + Spacing::Alone, + )) +} + +/// Handle the `${concat_str(...)}` metavariable expression. +fn metavar_expr_concat_str<'tx>( tscx: &mut TranscrCtx<'tx, '_>, dspan: DelimSpan, elements: &[MetaVarExprConcatElem], ) -> PResult<'tx, TokenTree> { + let (symbol, concatenated_span) = metavar_expr_concat(tscx, dspan, elements)?; + + // The current implementation marks the span as coming from the macro regardless of + // contexts of the concatenated identifiers but this behavior may change in the + // future. + Ok(TokenTree::Token( + Token::new(TokenKind::lit(LitKind::Str, symbol, None), concatenated_span), + Spacing::Alone, + )) +} + +/// Shared logic for concat/concat_str metavariable expressions +fn metavar_expr_concat<'tx>( + tscx: &mut TranscrCtx<'tx, '_>, + dspan: DelimSpan, + elements: &[MetaVarExprConcatElem], +) -> PResult<'tx, (Symbol, Span)> { let dcx = tscx.psess.dcx(); let mut concatenated = String::new(); for element in elements { @@ -668,21 +710,7 @@ fn metavar_expr_concat<'tx>( } let symbol = nfc_normalize(&concatenated); let concatenated_span = tscx.visited_dspan(dspan); - if !rustc_lexer::is_ident(symbol.as_str()) { - return Err(dcx.create_err(ConcatInvalidIdent { - span: concatenated_span, - reason: InvalidIdentReason::new(symbol), - })); - } - tscx.psess.symbol_gallery.insert(symbol, concatenated_span); - - // The current implementation marks the span as coming from the macro regardless of - // contexts of the concatenated identifiers but this behavior may change in the - // future. - Ok(TokenTree::Token( - Token::from_ast_ident(Ident::new(symbol, concatenated_span)), - Spacing::Alone, - )) + Ok((symbol, concatenated_span)) } /// Store the metavariable span for this original span into a side table. diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs index 098b6595f166e..bd70e5acab4d7 100644 --- a/compiler/rustc_span/src/symbol.rs +++ b/compiler/rustc_span/src/symbol.rs @@ -680,6 +680,7 @@ symbols! { complex, concat, concat_bytes, + concat_str, conservative_impl_trait, console, const_allocate, diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs index e700999ae4bd8..898bc28974c88 100644 --- a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs +++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.rs @@ -1,7 +1,8 @@ macro_rules! join { ($lhs:ident, $rhs:ident) => { - let ${concat($lhs, $rhs)}: () = (); + let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)}; //~^ ERROR the `concat` meta-variable expression is unstable + //~| ERROR the `concat_str` meta-variable expression is unstable }; } diff --git a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr index 5b2589d8c89be..47c09a119298d 100644 --- a/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr +++ b/tests/ui/feature-gates/feature-gate-macro-metavar-expr-concat.stderr @@ -1,13 +1,23 @@ error[E0658]: the `concat` meta-variable expression is unstable --> $DIR/feature-gate-macro-metavar-expr-concat.rs:3:14 | -LL | let ${concat($lhs, $rhs)}: () = (); +LL | let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)}; | ^^^^^^^^^^^^^^^^^^^^ | = note: see issue #124225 for more information = help: add `#![feature(macro_metavar_expr_concat)]` to the crate attributes to enable = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date -error: aborting due to 1 previous error +error[E0658]: the `concat_str` meta-variable expression is unstable + --> $DIR/feature-gate-macro-metavar-expr-concat.rs:3:52 + | +LL | let ${concat($lhs, $rhs)}: &'static str = ${concat_str($lhs, $rhs)}; + | ^^^^^^^^^^^^^^^^^^^^^^^^ + | + = note: see issue #124225 for more information + = help: add `#![feature(macro_metavar_expr_concat)]` to the crate attributes to enable + = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date + +error: aborting due to 2 previous errors For more information about this error, try `rustc --explain E0658`. diff --git a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs index 5ac50c943d030..cd0c23da1dd4f 100644 --- a/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs +++ b/tests/ui/macros/metavar-expressions/concat-allowed-operations.rs @@ -5,7 +5,7 @@ macro_rules! create_things { ($lhs:ident) => { - struct ${concat($lhs, _separated_idents_in_a_struct)} { + struct ${concat($lhs, _separated_idents_in_a_struct)} { foo: i32, ${concat($lhs, _separated_idents_in_a_field)}: i32, } @@ -20,19 +20,23 @@ macro_rules! create_things { macro_rules! many_idents { ($a:ident, $c:ident) => { + #[allow(dead_code, reason = ${concat_str($a, B, $c, D)})] const ${concat($a, B, $c, D)}: i32 = 1; }; } macro_rules! valid_tts { ($_0:tt, $_1:tt) => { + #[allow(dead_code, reason = ${concat_str($_0, $_1)})] const ${concat($_0, $_1)}: i32 = 1; } } macro_rules! without_dollar_sign_is_an_ident { ($ident:ident) => { + #[allow(dead_code, reason = ${concat_str(VAR, ident)})] const ${concat(VAR, ident)}: i32 = 1; + #[allow(dead_code, reason = ${concat_str(VAR, $ident)})] const ${concat(VAR, $ident)}: i32 = 2; }; } @@ -40,60 +44,103 @@ macro_rules! without_dollar_sign_is_an_ident { macro_rules! combinations { ($ident:ident, $literal:literal, $tt_ident:tt, $tt_literal:tt) => {{ // tt ident + #[allow(dead_code, reason = ${concat_str($tt_ident, b)})] let ${concat($tt_ident, b)} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, _b)})] let ${concat($tt_ident, _b)} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, "b")})] let ${concat($tt_ident, "b")} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, $tt_ident)})] let ${concat($tt_ident, $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, $tt_literal)})] let ${concat($tt_ident, $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, $ident)})] + let ${concat($tt_ident, $ident)} = (); + #[allow(dead_code, reason = ${concat_str($tt_ident, $ident)})] let ${concat($tt_ident, $ident)} = (); - let ${concat($tt_ident, $literal)} = (); // tt literal + #[allow(dead_code, reason = ${concat_str($tt_literal, b)})] let ${concat($tt_literal, b)} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, _b)})] let ${concat($tt_literal, _b)} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, "b")})] let ${concat($tt_literal, "b")} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, $tt_ident)})] let ${concat($tt_literal, $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, $tt_literal)})] let ${concat($tt_literal, $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, $ident)})] let ${concat($tt_literal, $ident)} = (); + #[allow(dead_code, reason = ${concat_str($tt_literal, $literal)})] let ${concat($tt_literal, $literal)} = (); // ident (adhoc) + #[allow(dead_code, reason = ${concat_str(_b, b)})] let ${concat(_b, b)} = (); + #[allow(dead_code, reason = ${concat_str(_b, _b)})] let ${concat(_b, _b)} = (); + #[allow(dead_code, reason = ${concat_str(_b, "b")})] let ${concat(_b, "b")} = (); + #[allow(dead_code, reason = ${concat_str(_b, $tt_ident)})] let ${concat(_b, $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str(_b, $tt_literal)})] let ${concat(_b, $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str(_b, $ident)})] let ${concat(_b, $ident)} = (); + #[allow(dead_code, reason = ${concat_str(_b, $literal)})] let ${concat(_b, $literal)} = (); // ident (param) + #[allow(dead_code, reason = ${concat_str($ident, b)})] let ${concat($ident, b)} = (); + #[allow(dead_code, reason = ${concat_str($ident, _b)})] let ${concat($ident, _b)} = (); + #[allow(dead_code, reason = ${concat_str($ident, "b")})] let ${concat($ident, "b")} = (); + #[allow(dead_code, reason = ${concat_str($ident, $tt_ident)})] let ${concat($ident, $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str($ident, $tt_literal)})] let ${concat($ident, $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str($ident, $ident)})] let ${concat($ident, $ident)} = (); + #[allow(dead_code, reason = ${concat_str($ident, $literal)})] let ${concat($ident, $literal)} = (); // literal (adhoc) + #[allow(dead_code, reason = ${concat_str("a", b)})] let ${concat("a", b)} = (); + #[allow(dead_code, reason = ${concat_str("a", _b)})] let ${concat("a", _b)} = (); + #[allow(dead_code, reason = ${concat_str("a", "b")})] let ${concat("a", "b")} = (); + #[allow(dead_code, reason = ${concat_str("a", $tt_ident)})] let ${concat("a", $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str("a", $tt_literal)})] let ${concat("a", $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str("a", $ident)})] let ${concat("a", $ident)} = (); + #[allow(dead_code, reason = ${concat_str("a", $literal)})] let ${concat("a", $literal)} = (); // literal (param) + #[allow(dead_code, reason = ${concat_str($literal, b)})] let ${concat($literal, b)} = (); + #[allow(dead_code, reason = ${concat_str($literal, _b)})] let ${concat($literal, _b)} = (); + #[allow(dead_code, reason = ${concat_str($literal, "b")})] let ${concat($literal, "b")} = (); + #[allow(dead_code, reason = ${concat_str($literal, $tt_ident)})] let ${concat($literal, $tt_ident)} = (); + #[allow(dead_code, reason = ${concat_str($literal, $tt_literal)})] let ${concat($literal, $tt_literal)} = (); + #[allow(dead_code, reason = ${concat_str($literal, $ident)})] let ${concat($literal, $ident)} = (); + #[allow(dead_code, reason = ${concat_str($literal, $literal)})] let ${concat($literal, $literal)} = (); }}; } macro_rules! int_struct { ($n: literal) => { + #[allow(dead_code, reason = ${concat_str(E, $n)})] struct ${concat(E, $n)}; } } diff --git a/tests/ui/macros/metavar-expressions/concat-str-escape.rs b/tests/ui/macros/metavar-expressions/concat-str-escape.rs new file mode 100644 index 0000000000000..612c957b831eb --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-str-escape.rs @@ -0,0 +1,20 @@ +//@ run-pass + +#![feature(macro_metavar_expr_concat)] + +macro_rules! escape_literal { + ($literal:literal, $concatted:literal) => { + let lit = ${concat_str("_", "\"foo", $literal)}; + assert_eq!(lit, concat!("_", "\"foo", $literal)); + assert_eq!(lit, $concatted); + + } +} + +fn main(){ + escape_literal!("\u{00BD}", "_\"foo\u{00BD}"); + escape_literal!("\x41", "_\"foo\x41"); + escape_literal!("🤷", "_\"foo🤷"); + escape_literal!("\u{1F980}", "_\"foo🦀"); + escape_literal!("aaa \"bbb\" ccc", "_\"fooaaa \"bbb\" ccc"); +} diff --git a/tests/ui/macros/metavar-expressions/concat-str-horror.rs b/tests/ui/macros/metavar-expressions/concat-str-horror.rs new file mode 100644 index 0000000000000..558e55539e870 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-str-horror.rs @@ -0,0 +1,13 @@ +//@ run-pass +#![feature(macro_metavar_expr_concat)] + +macro_rules! format_horror{ + ($arg1:ident, $arg2:expr, $arg3:expr) => { + format!(${concat_str("horror ", $arg1, " horror {} horror {}")}, $arg2, $arg3) + } +} + +fn main(){ + let x = format_horror!(a, "b", "c"); + assert_eq!(x, "horror a horror b horror c"); +} diff --git a/tests/ui/macros/metavar-expressions/concat-str.rs b/tests/ui/macros/metavar-expressions/concat-str.rs new file mode 100644 index 0000000000000..f04e620d6826e --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-str.rs @@ -0,0 +1,20 @@ +#![feature(macro_metavar_expr_concat)] +#![crate_type = "lib"] + +macro_rules! make_stuff { + ($prefix:literal, $name:ident) => { + #[deprecated(since = "1.0.0", note = ${concat_str($prefix, " ", $name, " trait")})] + #[diagnostic::on_unimplemented(message = ${concat_str("please do not the ", $name)})] + pub trait ${concat(New, $name)} {} + } +} + +make_stuff!("blah blah blah", AAAAAA); + +pub fn foo(x: impl NewAAAAAA) {} +//~^ WARN use of deprecated trait `NewAAAAAA`: blah blah blah AAAAAA trait [deprecated] + +fn bar(){ + foo(()); + //~^ ERROR please do not the AAAAAA [E0277] +} diff --git a/tests/ui/macros/metavar-expressions/concat-str.stderr b/tests/ui/macros/metavar-expressions/concat-str.stderr new file mode 100644 index 0000000000000..2e7e8cda4af06 --- /dev/null +++ b/tests/ui/macros/metavar-expressions/concat-str.stderr @@ -0,0 +1,35 @@ +warning: use of deprecated trait `NewAAAAAA`: blah blah blah AAAAAA trait + --> $DIR/concat-str.rs:14:20 + | +LL | pub fn foo(x: impl NewAAAAAA) {} + | ^^^^^^^^^ + | + = note: `#[warn(deprecated)]` on by default + +error[E0277]: please do not the AAAAAA + --> $DIR/concat-str.rs:18:9 + | +LL | macro_rules! make_stuff { +... +LL | foo(()); + | --- ^^ the trait `NewAAAAAA` is not implemented for `()` + | | + | required by a bound introduced by this call + | +help: this trait has no implementations, consider adding one + --> $DIR/concat-str.rs:8:9 + | +LL | pub trait ${concat(New, $name)} {} + | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +... +LL | make_stuff!("blah blah blah", AAAAAA); + | ------------------------------------- in this macro invocation +note: required by a bound in `foo` + --> $DIR/concat-str.rs:14:20 + | +LL | pub fn foo(x: impl NewAAAAAA) {} + | ^^^^^^^^^ required by this bound in `foo` + +error: aborting due to 1 previous error; 1 warning emitted + +For more information about this error, try `rustc --explain E0277`. From 94dc6dd98ad000c78b950acb1bb34e2ccdf9e990 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 15:59:30 +0000 Subject: [PATCH 0643/1309] Fix test --- src/tools/clippy/tests/ui/crashes/ice-6256.stderr | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr index 4cb83e24e7a05..b0cd8abed048b 100644 --- a/src/tools/clippy/tests/ui/crashes/ice-6256.stderr +++ b/src/tools/clippy/tests/ui/crashes/ice-6256.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> tests/ui/crashes/ice-6256.rs:7:6 + | +LL | impl dyn TT { + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement +LL | fn func(&self) {} + | error: aborting due to 1 previous error From 711fd935f1ebb7f1d714cfd335f2f96b30627ec0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Esteban=20K=C3=BCber?= Date: Tue, 22 Sep 2026 15:59:30 +0000 Subject: [PATCH 0644/1309] Fix test --- tests/ui/crashes/ice-6256.stderr | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tests/ui/crashes/ice-6256.stderr b/tests/ui/crashes/ice-6256.stderr index 4cb83e24e7a05..b0cd8abed048b 100644 --- a/tests/ui/crashes/ice-6256.stderr +++ b/tests/ui/crashes/ice-6256.stderr @@ -8,6 +8,14 @@ LL | let f = |x: &dyn TT| x.func(); | | | argument requires that `'1` must outlive `'static` | | let's call the lifetime of this reference `'1` | `x` is only valid in the closure body + | +note: `'static` lifetime requirement from `<(dyn TT + 'static)>::func` introduced here + --> tests/ui/crashes/ice-6256.rs:7:6 + | +LL | impl dyn TT { + | ^^^^^^ `dyn Trait` introduces an implicit `'static` lifetime requirement +LL | fn func(&self) {} + | error: aborting due to 1 previous error From fc83fc885ddfef7c695c49e1be3af90655f4af44 Mon Sep 17 00:00:00 2001 From: Takayuki Maeda Date: Wed, 9 Sep 2026 05:02:14 +0900 Subject: [PATCH 0645/1309] avoid ICEs when recovering malformed function parameters --- .../rustc_parse/src/parser/diagnostics.rs | 36 +++++++++++++------ .../recover-invalid-fn-trait-bound-pattern.rs | 5 +++ ...over-invalid-fn-trait-bound-pattern.stderr | 20 +++++++++++ ...over-invalid-function-parameter-pattern.rs | 6 ++++ ...-invalid-function-parameter-pattern.stderr | 28 +++++++++++++++ 5 files changed, 85 insertions(+), 10 deletions(-) create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.rs create mode 100644 tests/ui/parser/recover-invalid-function-parameter-pattern.stderr diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs index db6af6ab17aca..928518c88fec6 100644 --- a/compiler/rustc_parse/src/parser/diagnostics.rs +++ b/compiler/rustc_parse/src/parser/diagnostics.rs @@ -2140,16 +2140,32 @@ impl<'a> Parser<'a> { let pat = self.parse_pat_no_top_alt(Some(Expected::ArgumentName), None)?; self.expect(exp!(Colon))?; let ty = self.parse_ty()?; - self.dcx().emit_err(PatternMethodParamWithoutBody { - span: pat.span, - target: match context { - FnContext::Trait => "methods without bodies", - FnContext::FunctionPtrType => "function pointer types", - FnContext::ParenthesizedArgumentList => "parenthesized argument list", - FnContext::Free => unreachable!("This method is not called in free functions, as patterns are always allowed there"), - FnContext::Impl => unreachable!("This method is not called in impls, as patterns are always allowed there"), - }, - }); + match context { + FnContext::Trait + | FnContext::FunctionPtrType + | FnContext::ParenthesizedArgumentList => { + self.dcx().emit_err(PatternMethodParamWithoutBody { + span: pat.span, + target: if context == FnContext::Trait { + "methods without bodies" + } else if context == FnContext::FunctionPtrType { + "function pointer types" + } else { + "parenthesized argument list" + }, + }); + } + FnContext::Free | FnContext::Impl => { + self.dcx().span_delayed_bug( + pat.span, + if context == FnContext::Free { + "This method is not called in free functions, as patterns are always allowed there" + } else { + "This method is not called in impls, as patterns are always allowed there" + }, + ); + } + } // Pretend the pattern is `_`, to avoid duplicate errors from AST validation. let pat = Box::new(Pat { kind: PatKind::Wild, span: pat.span, id: ast::DUMMY_NODE_ID }); diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs new file mode 100644 index 0000000000000..abbff103bb2be --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.rs @@ -0,0 +1,5 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +struct Baz where U : fn(() : bool) +//~^ ERROR expected identifier, found keyword `fn` +//~| ERROR expected `{` after struct name, found `` diff --git a/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr new file mode 100644 index 0000000000000..02ec950b3a365 --- /dev/null +++ b/tests/ui/parser/recover-invalid-fn-trait-bound-pattern.stderr @@ -0,0 +1,20 @@ +error: expected identifier, found keyword `fn` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:22 + | +LL | struct Baz where U : fn(() : bool) + | ^^ + | +help: use `Fn` to refer to the trait (notice the capitalization) + | +LL - struct Baz where U : fn(() : bool) +LL + struct Baz where U : Fn(() : bool) + | + +error: expected `{` after struct name, found `` + --> $DIR/recover-invalid-fn-trait-bound-pattern.rs:3:34 + | +LL | struct Baz where U : fn(() : bool) + | ^ expected `{` after struct name + +error: aborting due to 2 previous errors + diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.rs b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs new file mode 100644 index 0000000000000..a9e6a5578486f --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.rs @@ -0,0 +1,6 @@ +// Regression test for https://github.com/rust-lang/rust/issues/160337. + +fn main(... : ...) +//~^ ERROR unexpected `...` +//~| ERROR unexpected `...` +//~| ERROR expected one of `->`, `where`, or `{`, found `` diff --git a/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr new file mode 100644 index 0000000000000..d4b78db29dba9 --- /dev/null +++ b/tests/ui/parser/recover-invalid-function-parameter-pattern.stderr @@ -0,0 +1,28 @@ +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:9 + | +LL | fn main(... : ...) + | ^^^ not a valid pattern + | +help: for a rest pattern, use `..` instead of `...` + | +LL - fn main(... : ...) +LL + fn main(.. : ...) + | + +error: unexpected `...` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:15 + | +LL | fn main(... : ...) + | ^^^ + | + = note: only `extern "C"` and `extern "C-unwind"` functions may have a C variable argument list + +error: expected one of `->`, `where`, or `{`, found `` + --> $DIR/recover-invalid-function-parameter-pattern.rs:3:18 + | +LL | fn main(... : ...) + | ^ expected one of `->`, `where`, or `{` + +error: aborting due to 3 previous errors + From 41ae947f504a0584e14ae718fb6f25d37c50a6f3 Mon Sep 17 00:00:00 2001 From: WANG Rui Date: Tue, 22 Sep 2026 10:54:23 +0800 Subject: [PATCH 0646/1309] tests: Update `f16b` codegen test for LoongArch and RISC-V Add target-specific revisions to the `f16b` codegen test to account for LoongArch and RISC-V lowering `f16b` to LLVM `half` rather than `bfloat`. --- tests/codegen-llvm/float/f16b.rs | 57 +++++++++++++++++++++++++++----- 1 file changed, 49 insertions(+), 8 deletions(-) diff --git a/tests/codegen-llvm/float/f16b.rs b/tests/codegen-llvm/float/f16b.rs index 7de6a776190c9..3bd245546b7cf 100644 --- a/tests/codegen-llvm/float/f16b.rs +++ b/tests/codegen-llvm/float/f16b.rs @@ -1,4 +1,13 @@ //@ compile-flags: -Copt-level=3 +//@ revisions: GENERIC LOONGARCH32 LOONGARCH64 RISCV32 RISCV64 +//@ [GENERIC] ignore-loongarch32 +//@ [GENERIC] ignore-loongarch64 +//@ [GENERIC] ignore-riscv32 +//@ [GENERIC] ignore-riscv64 +//@ [LOONGARCH32] only-loongarch32 +//@ [LOONGARCH64] only-loongarch64 +//@ [RISCV32] only-riscv32 +//@ [RISCV64] only-riscv64 #![crate_type = "lib"] #![feature(f16b)] @@ -8,31 +17,63 @@ extern crate core; use core::num::f16b; -// CHECK-LABEL: define{{.*}} bfloat @identity_f16b(bfloat +// GENERIC-LABEL: define{{.*}} bfloat @identity_f16b(bfloat +// LOONGARCH32-LABEL: define{{.*}} half @identity_f16b(half +// LOONGARCH64-LABEL: define{{.*}} half @identity_f16b(half +// RISCV32-LABEL: define{{.*}} half @identity_f16b(half +// RISCV64-LABEL: define{{.*}} half @identity_f16b(half #[no_mangle] pub extern "C" fn identity_f16b(value: f16b) -> f16b { - // CHECK: ret bfloat + // GENERIC: ret bfloat + // LOONGARCH32: ret half + // LOONGARCH64: ret half + // RISCV32: ret half + // RISCV64: ret half value } -// CHECK-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat +// GENERIC-LABEL: define{{.*}} i16 @f16b_to_bits(bfloat +// LOONGARCH32-LABEL: define{{.*}} i16 @f16b_to_bits(half +// LOONGARCH64-LABEL: define{{.*}} i16 @f16b_to_bits(half +// RISCV32-LABEL: define{{.*}} i16 @f16b_to_bits(half +// RISCV64-LABEL: define{{.*}} i16 @f16b_to_bits(half #[no_mangle] pub extern "C" fn f16b_to_bits(value: f16b) -> u16 { - // CHECK: bitcast bfloat %value to i16 + // GENERIC: bitcast bfloat %value to i16 + // LOONGARCH32: bitcast half %0 to i16 + // LOONGARCH64: bitcast half %0 to i16 + // RISCV32: bitcast half %0 to i16 + // RISCV64: bitcast half %0 to i16 value.to_bits() } -// CHECK-LABEL: define{{.*}} bfloat @f16b_from_bits(i16 +// GENERIC-LABEL: define{{.*}} bfloat @f16b_from_bits(i16 +// LOONGARCH32-LABEL: define{{.*}} half @f16b_from_bits(i16 +// LOONGARCH64-LABEL: define{{.*}} half @f16b_from_bits(i16 +// RISCV32-LABEL: define{{.*}} half @f16b_from_bits(i16 +// RISCV64-LABEL: define{{.*}} half @f16b_from_bits(i16 #[no_mangle] pub extern "C" fn f16b_from_bits(bits: u16) -> f16b { - // CHECK: bitcast i16 %bits to bfloat + // GENERIC: bitcast i16 %bits to bfloat + // LOONGARCH32: bitcast i16 %bits to half + // LOONGARCH64: bitcast i16 %bits to half + // RISCV32: bitcast i16 %bits to half + // RISCV64: bitcast i16 %bits to half f16b::from_bits(bits) } -// CHECK-LABEL: define{{.*}} float @widen_f16b(bfloat +// GENERIC-LABEL: define{{.*}} float @widen_f16b(bfloat +// LOONGARCH32-LABEL: define{{.*}} float @widen_f16b(half +// LOONGARCH64-LABEL: define{{.*}} float @widen_f16b(half +// RISCV32-LABEL: define{{.*}} float @widen_f16b(half +// RISCV64-LABEL: define{{.*}} float @widen_f16b(half #[no_mangle] pub extern "C" fn widen_f16b(value: f16b) -> f32 { - // CHECK: bitcast bfloat %value to i16 + // GENERIC: bitcast bfloat %value to i16 + // LOONGARCH32: bitcast half %0 to i16 + // LOONGARCH64: bitcast half %0 to i16 + // RISCV32: bitcast half %0 to i16 + // RISCV64: bitcast half %0 to i16 // CHECK: zext i16 // CHECK: shl nuw i32 {{.*}}, 16 // CHECK: bitcast i32 {{.*}} to float From b693b3ac0f5d8adbf563b9fc839a2a430501fc55 Mon Sep 17 00:00:00 2001 From: PabstMirror Date: Sat, 19 Sep 2026 13:22:24 -0500 Subject: [PATCH 0647/1309] Fix: `match_str_case` not matching str in or pattern (`|`) --- .../src/matches/match_str_case_mismatch.rs | 42 ++++++++++++++----- tests/ui/match_str_case_mismatch.fixed | 11 +++++ tests/ui/match_str_case_mismatch.rs | 11 +++++ tests/ui/match_str_case_mismatch.stderr | 14 ++++++- 4 files changed, 67 insertions(+), 11 deletions(-) diff --git a/clippy_lints/src/matches/match_str_case_mismatch.rs b/clippy_lints/src/matches/match_str_case_mismatch.rs index 93f9c3f14904b..dff5af725826b 100644 --- a/clippy_lints/src/matches/match_str_case_mismatch.rs +++ b/clippy_lints/src/matches/match_str_case_mismatch.rs @@ -7,7 +7,7 @@ use rustc_ast::ast::LitKind; use rustc_attr_ir::lang_items::LangItem; use rustc_errors::Applicability; use rustc_hir::intravisit::{Visitor, walk_expr}; -use rustc_hir::{Arm, Expr, ExprKind, PatExpr, PatExprKind, PatKind}; +use rustc_hir::{Arm, Expr, ExprKind, Lit, PatExpr, PatExprKind, PatKind}; use rustc_lint::LateContext; use rustc_middle::ty; use rustc_span::Span; @@ -85,17 +85,39 @@ fn verify_case<'a>(case_method: &'a CaseMethod, arms: &'a [Arm<'_>]) -> Option<( CaseMethod::UpperCase => |input: &str| -> bool { input.chars().all(|c| c.to_uppercase().next() == Some(c)) }, CaseMethod::AsciiUppercase => |input: &str| -> bool { !input.chars().any(|c| c.is_ascii_lowercase()) }, }; + let verify_pattern_expression = |lit: &Lit| -> Option<(Span, Symbol)> { + if let LitKind::Str(symbol, _) = lit.node { + let input = symbol.as_str(); + if !case_check(input) { + return Some((lit.span, symbol)); + } + } + None + }; for arm in arms { - if let PatKind::Expr(PatExpr { - kind: PatExprKind::Lit { lit, negated: false }, - .. - }) = arm.pat.kind - && let LitKind::Str(symbol, _) = lit.node - && let input = symbol.as_str() - && !case_check(input) - { - return Some((lit.span, symbol)); + match arm.pat.kind { + PatKind::Expr(PatExpr { + kind: PatExprKind::Lit { lit, negated: false }, + .. + }) => { + if let Some(result) = verify_pattern_expression(lit) { + return Some(result); + } + }, + PatKind::Or(fields) => { + for field in fields { + if let PatKind::Expr(PatExpr { + kind: PatExprKind::Lit { lit, negated: false }, + .. + }) = field.kind + && let Some(result) = verify_pattern_expression(lit) + { + return Some(result); + } + } + }, + _ => {}, } } diff --git a/tests/ui/match_str_case_mismatch.fixed b/tests/ui/match_str_case_mismatch.fixed index 8ab6a33dab490..6075c70707a69 100644 --- a/tests/ui/match_str_case_mismatch.fixed +++ b/tests/ui/match_str_case_mismatch.fixed @@ -188,4 +188,15 @@ fn alternating_chain_mismatch() { } } +fn or_pattern_mismatch() { + let var = "BAR"; + + match var.to_ascii_lowercase().as_str() { + "foo" | "f" => {}, + //~^ match_str_case_mismatch + "bar" => {}, + _ => {}, + } +} + fn main() {} diff --git a/tests/ui/match_str_case_mismatch.rs b/tests/ui/match_str_case_mismatch.rs index 8533404bcea7b..b94194994a35c 100644 --- a/tests/ui/match_str_case_mismatch.rs +++ b/tests/ui/match_str_case_mismatch.rs @@ -188,4 +188,15 @@ fn alternating_chain_mismatch() { } } +fn or_pattern_mismatch() { + let var = "BAR"; + + match var.to_ascii_lowercase().as_str() { + "Foo" | "f" => {}, + //~^ match_str_case_mismatch + "bar" => {}, + _ => {}, + } +} + fn main() {} diff --git a/tests/ui/match_str_case_mismatch.stderr b/tests/ui/match_str_case_mismatch.stderr index e1f7ef8de7cd1..199a6b2fb5ee6 100644 --- a/tests/ui/match_str_case_mismatch.stderr +++ b/tests/ui/match_str_case_mismatch.stderr @@ -84,5 +84,17 @@ LL - "bAR" => {}, LL + "BAR" => {}, | -error: aborting due to 7 previous errors +error: this `match` arm has a differing case than its expression + --> tests/ui/match_str_case_mismatch.rs:195:9 + | +LL | "Foo" | "f" => {}, + | ^^^^^ + | +help: consider changing the case of this arm to respect `to_ascii_lowercase` (notice the capitalization) + | +LL - "Foo" | "f" => {}, +LL + "foo" | "f" => {}, + | + +error: aborting due to 8 previous errors From 501b40c89d67530ed3b5b55335b202d5f5cab136 Mon Sep 17 00:00:00 2001 From: Charlie Marsh Date: Tue, 22 Sep 2026 13:15:17 -0400 Subject: [PATCH 0648/1309] Document coroutine storage-conflict fast path --- compiler/rustc_mir_transform/src/coroutine/layout.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/compiler/rustc_mir_transform/src/coroutine/layout.rs b/compiler/rustc_mir_transform/src/coroutine/layout.rs index 1b9ced7fc05b9..03d4aff960fcf 100644 --- a/compiler/rustc_mir_transform/src/coroutine/layout.rs +++ b/compiler/rustc_mir_transform/src/coroutine/layout.rs @@ -297,6 +297,9 @@ struct StorageConflictVisitor<'a> { local_conflicts: BitMatrix, // We keep this bitset as a buffer to avoid reallocating memory. eligible_storage_live: DenseBitSet, + // The last live set whose conflicts were recorded. This is just a fast path: + // if the current live set is a subset, we can skip updating the conflict matrix + // since its conflicts have already been recorded. last_recorded_storage_live: DenseBitSet, } From a748eaedff6c55cab762add747a011271d93a0e8 Mon Sep 17 00:00:00 2001 From: Alex Crichton Date: Tue, 22 Sep 2026 10:35:09 -0700 Subject: [PATCH 0649/1309] std: Update `wasip3` crate dependency Keeping it up-to-date and resolving minor issues with it. --- library/Cargo.lock | 12 ++++++------ library/std/Cargo.toml | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/library/Cargo.lock b/library/Cargo.lock index 3ddddbd5985b7..98fa2c5117411 100644 --- a/library/Cargo.lock +++ b/library/Cargo.lock @@ -426,9 +426,9 @@ dependencies = [ [[package]] name = "wasip2" -version = "2.0.0+wasi-0.2.12" +version = "2.0.1+wasi-0.2.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "96744b5e833bfd2d84c6faa7569693ce9e04a47c0a4d5519e6442f18af1a0fed" +checksum = "89aafd4b69fb41a64cfd5d7f214cde92ab422ec4d9bcd55fcc816d3f5f49bbf3" dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -437,9 +437,9 @@ dependencies = [ [[package]] name = "wasip3" -version = "0.8.0+wasi-0.3.0" +version = "0.9.0+wasi-0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42a999271e77c083825863fc85404197523b3f3cebe9b402aece658ebea90065" +checksum = "f1d5749fdf69bb9400562eba50f8f25f5cd800ef4b74300038b6f99ae7409674" dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", @@ -456,9 +456,9 @@ version = "0.61.100" [[package]] name = "wit-bindgen" -version = "0.61.1" +version = "0.62.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e473fd0095479f9689ac7d2a52c427cc96bb2b973ace50238dfcc1ab1cd52d93" +checksum = "53cb4b5556c3a791e86838ea287782bdafa704d55b0e68b5b81a3a16b9ea5f4b" dependencies = [ "rustc-std-workspace-alloc", "rustc-std-workspace-core", diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml index de5c1feadb298..1d35b42a53947 100644 --- a/library/std/Cargo.toml +++ b/library/std/Cargo.toml @@ -84,12 +84,12 @@ wasip1 = { version = "1.0.0", features = [ ], default-features = false } [target.'cfg(all(target_os = "wasi", target_env = "p2"))'.dependencies] -wasip2 = { version = '2.0.0', features = [ +wasip2 = { version = '2.0.1', features = [ 'rustc-dep-of-std', ], default-features = false } [target.'cfg(all(target_os = "wasi", target_env = "p3"))'.dependencies] -wasip3 = { version = '0.8.0', features = [ +wasip3 = { version = '0.9.0', features = [ 'rustc-dep-of-std', ], default-features = false } From 84a341bb5cf6e6e371b0b1ecf80521f5408b5ac7 Mon Sep 17 00:00:00 2001 From: Max Dexheimer Date: Mon, 21 Sep 2026 11:16:47 +0200 Subject: [PATCH 0650/1309] Use wrapping arithmetic in `from_str_radix` --- library/core/src/num/mod.rs | 25 +++++++++++++++++++------ 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs index db41d23770477..c2b21701645a0 100644 --- a/library/core/src/num/mod.rs +++ b/library/core/src/num/mod.rs @@ -1573,6 +1573,16 @@ pub enum FpCategory { #[inline(always)] #[unstable(issue = "none", feature = "std_internals")] pub const fn can_not_overflow(radix: u32, is_signed_ty: bool, digits: &[u8]) -> bool { + // Assume that `digits` represents a whole number N in base `radix`. + // Then in infinite precision arithmetic (on whole numbers), we have: + // + // |N| <= pow(radix, digits.len()) - 1 + // <= pow(16, 2 * size_of::() - is_signed) - 1 + // == pow(2, 8 * size_of::() - 4 * is_signed) - 1 + // <= pow(2, 8 * size_of::() - is_signed) - 1 + // == T::MAX + // + // Therefore this condition is sufficient for having no overflow. radix <= 16 && digits.len() <= size_of::() * 2 - is_signed_ty as usize } @@ -1816,20 +1826,23 @@ macro_rules! from_str_int_impl { // Consider radix 16 as it has the highest information density per digit and will thus overflow the earliest: // `u8::MAX` is `ff` - any str of len 2 is guaranteed to not overflow. // `i8::MAX` is `7f` - only a str of len 1 is guaranteed to not overflow. - macro_rules! run_unchecked_loop { - ($unchecked_additive_op:tt) => {{ + // + // NOTE: We could use unchecked arithmetic here, but we don't, based on the observation + // that it produces the same assembly as wrapping ones. See #163099. + macro_rules! run_no_check_loop { + ($additive_op:ident) => {{ while let [c, rest @ ..] = digits { - result = result * (radix as $int_ty); + result = <$int_ty>::wrapping_mul(result, radix as _); let x = unwrap_or_PIE!((*c as char).to_digit(radix), InvalidDigit); - result = result $unchecked_additive_op (x as $int_ty); + result = result.$additive_op(x as $int_ty); digits = rest; } }}; } if is_positive { - run_unchecked_loop!(+) + run_no_check_loop!(wrapping_add) } else { - run_unchecked_loop!(-) + run_no_check_loop!(wrapping_sub) }; } else { macro_rules! run_checked_loop { From 1aa709d241a7185b26c758d673f32cb9dc5df0a4 Mon Sep 17 00:00:00 2001 From: durationextender Date: Sun, 23 Aug 2026 15:41:35 +0200 Subject: [PATCH 0651/1309] fix(while_let_loop): detect the pattern when the loop has a label --- clippy_lints/src/loops/while_let_loop.rs | 50 +++++++++++++++--------- tests/ui/while_let_loop.rs | 47 ++++++++++++++++++++++ tests/ui/while_let_loop.stderr | 43 +++++++++++++++++++- 3 files changed, 120 insertions(+), 20 deletions(-) diff --git a/clippy_lints/src/loops/while_let_loop.rs b/clippy_lints/src/loops/while_let_loop.rs index e2ea24c399807..f2068f7be0f02 100644 --- a/clippy_lints/src/loops/while_let_loop.rs +++ b/clippy_lints/src/loops/while_let_loop.rs @@ -4,9 +4,9 @@ use clippy_utils::source::{snippet, snippet_indent, snippet_opt}; use clippy_utils::ty::needs_ordered_drop; use clippy_utils::visitors::any_temporaries_need_ordered_drop; use clippy_utils::{higher, peel_blocks}; -use rustc_ast::BindingMode; +use rustc_ast::{BindingMode, Label}; use rustc_errors::Applicability; -use rustc_hir::{Block, Expr, ExprKind, LetStmt, MatchSource, Pat, PatKind, Path, QPath, StmtKind, Ty}; +use rustc_hir::{Block, Expr, ExprKind, HirId, LetStmt, MatchSource, Pat, PatKind, Path, QPath, StmtKind, Ty}; use rustc_lint::LateContext; pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_block: &'tcx Block<'_>) { @@ -26,10 +26,14 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo _ => return, }; let has_trailing_exprs = loop_block.stmts.len() + usize::from(loop_block.expr.is_some()) > 1; - + let loop_label = if let ExprKind::Loop(_, label, ..) = expr.kind { + label + } else { + None + }; if let Some(if_let) = higher::IfLet::hir(cx, init) && let Some(else_expr) = if_let.if_else - && is_simple_break_expr(else_expr) + && is_simple_break_expr(else_expr, loop_label, expr.hir_id) { could_be_while_let( cx, @@ -39,15 +43,16 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo has_trailing_exprs, let_info, Some(if_let.if_then), + loop_label, ); - } else if els.is_some_and(is_simple_break_block) + } else if els.is_some_and(|b| is_simple_break_block(b, loop_label, expr.hir_id)) && let Some((pat, _)) = let_info { - could_be_while_let(cx, expr, pat, init, has_trailing_exprs, let_info, None); + could_be_while_let(cx, expr, pat, init, has_trailing_exprs, let_info, None, loop_label); } else if let ExprKind::Match(scrutinee, [arm1, arm2], MatchSource::Normal) = init.kind && arm1.guard.is_none() && arm2.guard.is_none() - && is_simple_break_expr(arm2.body) + && is_simple_break_expr(arm2.body, loop_label, expr.hir_id) { could_be_while_let( cx, @@ -57,30 +62,34 @@ pub(super) fn check<'tcx>(cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>, loop_blo has_trailing_exprs, let_info, Some(arm1.body), + loop_label, ); } } -/// Checks if `block` contains a single unlabeled `break` expression or statement, possibly embedded -/// inside other blocks. -fn is_simple_break_block(block: &Block<'_>) -> bool { +/// Checks if `block` contains a single (labeled or unlabeled) `break` +/// expression or statement, possibly embedded inside other blocks. +fn is_simple_break_block(block: &Block<'_>, loop_label: Option Allocator for &A where @@ -627,7 +629,7 @@ where } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[stable(feature = "allocator_api", since = "CURRENT_RUSTC_VERSION")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] const unsafe impl Allocator for &mut A where @@ -683,9 +685,9 @@ where } } -#[unstable(feature = "allocator_api", issue = "32838")] +#[unstable(feature = "allocator_ext", issue = "163177", implied_by = "allocator_api")] #[rustc_const_unstable(feature = "const_heap", issue = "79597")] -#[unstable_feature_bound(allocator_api)] +#[unstable_feature_bound(allocator_ext)] const unsafe impl